Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board

Plan › M2 alignment · updated 18 May 2026 · internal

M2 alignment — the developer kickoff page

One page. What M2 is, our position on every concern in the May dev-team note, deep links to everything already shipped, and the open items still to settle this week. Start here before touching M2 code.

Intelligence layer Crypto decision-making → 7 existing sensors + 7 new valuators + 3 shared combiners Intelligence layer Politics decision-making → 8 existing sensors + 9 new valuators + 3 shared combiners

01 · one paragraph

What is M2

M2 is the milestone where Polytraders trades real money on a deliberately narrow surface. It takes the platform from “mocks, fixtures and frozen specs” to “signed orders, real pUSD, real fills, real audit receipts” — but only on one venue, one stablecoin, one strategy family, and only for operators and reviewers. Nothing public-facing, no marketing claims, no track records. The point of keeping it narrow is so we can ship audited real-balance trading with confidence, then expand from a known-good base in M3 and M4.

02 · locked for M2

Shared non-negotiables

These do not move during M2. If a change is needed, escalate before shipping.

03 · response to the May note

Where each concern landed

Canonical record of every concern in the May dev-team note, our position, and where it lives now in the build.

ConcernStatusTheir position → our positionWhere it lives
Markets Agreed Read-only canonical layer → agreed; single-venue (Polymarket V2) in M2; multi-venue and smart-routing in M4+. Markets registry
Portfolios Agreed Should be the unit of account → agreed; strategies, positions, signals and risk all hang off a Portfolio. Worked example PORT-001 in the mock. Portfolios · PortfolioConfig.json
Clusters vs Watchlists Agreed Distinct concepts → clusters carry risk meaning (caps, receipt disclosure, strategy market scope); watchlists are operator views only. Glossary
Strategy → portfolio binding Agreed One strategy = one portfolio at launch → changing portfolio is stop-and-relaunch with a new audit envelope per launch. Launch wizard
Strategy: score field Shipped Rename Fair Value to strategy_score + score_type → done; fair_value is now one valid score_type, not the field name. Signal.json · Strategy Detail
Strategy: 27-section spec Locked Stays the contract → agreed; frozen for M2; 109 bots stay on current specs. Bot interface
Strategy: backtests Shipped Operator-only, never marketed → agreed and enforced; every panel badged BACKTEST; operator-only callout in place. Backtest
Strategy: market selection New Not in the original note → cluster binding (primary) plus manual list capped at 50 (fallback); DSL deferred to M3; backtest uses the same scope rule. M2 scope › Market scope · MarketScope.json
Strategy: parameter changes in mock Agreed Demo-only, not persistent → agreed; the mock is a UX surface, not a config store. Strategy Detail
Strategy: reshape-by-risk Shipped Path stays → agreed; STRAT_RESHAPED_BY_RISK registered; Risk receives OrderIntent only after Strategy emits. Reason codes
Target audience Agreed Operators and reviewers, not retail → UI is dense, audit-first, full-disclosure; no marketing surfaces; public-facing waits. This page
Naming Locked Lock terms → locked: Portfolio, Strategy, Cluster, Watchlist, strategy_score, score_type, Backtest, Tenant, Bot, Market scope. Glossary
Plan vs Dev Guide gap Shipped No single source of truth for what’s M2 → resolved; M2 scope doc walks the Dev Guide section by section with in / partial / deferred badges. M2 scope mapping

04 · ready to use today

What’s shipped so a backend dev can start now

Four surfaces, all live in the repo and on this site. Pull these and you can begin implementation against a stable contract.

1 Schemas as code

JSON Schemas in /schemas/ are the single source of truth. TypeScript and Pydantic artefacts are generated by scripts/codegen/generate_types.py. Drift fails the build.

2 Fixtures (good and bad)

Known-good and known-bad JSON for every schema. The mock-app consumes the good ones; verify runs the bad ones through schema validation to assert rejection. Each bad fixture carries a _why_bad field naming the rule it violates.

3 Mock surfaces showing the M2 contract

Every UI surface developers will eventually wire is already rendered against the schemas above. Look at these for the operator-facing shape of M2.

4 New reason codes registered

Five new codes are live in the registry. See the next section for definitions, or open the full registry for every code in the system.

05 · emitted to audit envelopes

New reason codes you’ll see in M2

All five follow the locked pattern ^(INTEL|DISC|STRAT|RISK|EXEC|SEC|GOV)_[A-Z0-9_]+$ and are emitted to audit envelopes with the canonical builderCode.

STRAT_MARKET_IN_SCOPEMarket entered the strategy’s evaluable set (cluster membership added, or manual list edit).
STRAT_MARKET_OUT_OF_SCOPEMarket dropped out (cluster removal, manual de-selection, or market resolution).
STRAT_MOMENTUM_LONGMomentum strategy entered a long position (backtest or live).
STRAT_MOMENTUM_EXITMomentum strategy exited on signal reversal or take-profit (backtest or live).
STRAT_RESHAPED_BY_RISKOrderIntent reshaped by Risk before submission. Both shapes audited.

06 · need a decision this week

Open items

Lean yes-or-no on each and we can lock M2 and start sequencing implementation. Greens are our recommended position; ambers are open.

  1. Strategy → Portfolio binding at runtime. Stop-and-relaunch on portfolio change, or live migration? Our lean: stop-and-relaunch
  2. Backtest data window. 90 days, 180 days, or full history? Our lean: 180 days
  3. score_type registry. Locked allow-list or open? Our lean: locked (fair_value, momentum, expected_edge, confidence, custom), expandable via PR
  4. Cluster taxonomy ownership. Static config, tenant admin, or per-portfolio? Open — no lean yet
  5. Watchlist persistence. Per-operator or per-tenant? Mock is per-operator, not locked — confirm or change
  6. Tenant layer in M2. Data model in M2, UI in M3? Our lean: yes, that split
  7. Backtest reason-code coverage. Reuse STRAT_* with BACKTEST badging, or a new BACKTEST_* family? Our lean: reuse
  8. Manual-list cap of 50 markets per strategy. Confirm or change. Our lean: 50
  9. New reason codes STRAT_MARKET_IN_SCOPE and STRAT_MARKET_OUT_OF_SCOPE. Confirm naming. Our lean: keep names
  10. One mode per strategy in M2 (no mixed cluster + manual override). Mixed modes deferred to M3. Confirm. Our lean: one mode

07 · still on our side

What’s still on our side to ship

Conformance test suiteSmall headless suite a backend implementer runs against their service. Inputs are the fixtures, expected outputs are the audit envelopes plus rejection reason codes. Coming next.
Mode-ladder gatesExplicit checklists for each transition (docs-complete → demo-wired → limited_live → wide_live) per class. Documentation pass.
Versioning. This page is the canonical kickoff doc for M2. Changes require a PR against generator/dev_pages.py :: render_m2_alignment() with the date in the eyebrow updated.