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.
01 · one paragraph
What is M2
02 · locked for M2
Shared non-negotiables
These do not move during M2. If a change is needed, escalate before shipping.
- pUSD only on Polygon. No USDC.e. No other stables.
- V2 only. CLOB V2, EIP-712 v2, CTFExchangeV2 contract allow-list.
- builderCode pinned at the full 66-char canonical value. Never masked in dev or audit surfaces.
- Audit receipts on every action — reason code, builderCode and envelope ID, always visible.
- 109 bots frozen at their current 27-section specs for the duration of M2.
- Global kill switch and jurisdiction blocks live throughout.
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.
| Concern | Status | Their position → our position | Where 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_SCOPE | Market entered the strategy’s evaluable set (cluster membership added, or manual list edit). |
STRAT_MARKET_OUT_OF_SCOPE | Market dropped out (cluster removal, manual de-selection, or market resolution). |
STRAT_MOMENTUM_LONG | Momentum strategy entered a long position (backtest or live). |
STRAT_MOMENTUM_EXIT | Momentum strategy exited on signal reversal or take-profit (backtest or live). |
STRAT_RESHAPED_BY_RISK | OrderIntent 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.
- Strategy → Portfolio binding at runtime. Stop-and-relaunch on portfolio change, or live migration? Our lean: stop-and-relaunch
- Backtest data window. 90 days, 180 days, or full history? Our lean: 180 days
-
score_typeregistry. Locked allow-list or open? Our lean: locked (fair_value, momentum, expected_edge, confidence, custom), expandable via PR - Cluster taxonomy ownership. Static config, tenant admin, or per-portfolio? Open — no lean yet
- Watchlist persistence. Per-operator or per-tenant? Mock is per-operator, not locked — confirm or change
- Tenant layer in M2. Data model in M2, UI in M3? Our lean: yes, that split
-
Backtest reason-code coverage. Reuse
STRAT_*with BACKTEST badging, or a newBACKTEST_*family? Our lean: reuse - Manual-list cap of 50 markets per strategy. Confirm or change. Our lean: 50
-
New reason codes
STRAT_MARKET_IN_SCOPEandSTRAT_MARKET_OUT_OF_SCOPE. Confirm naming. Our lean: keep names - 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
docs-complete → demo-wired → limited_live → wide_live) per class. Documentation pass.generator/dev_pages.py :: render_m2_alignment() with the date in the eyebrow updated.