# Final Design — Sigil: Path to Consistent Positive Growth

**Run:** 2026-05-02T08-22-06 · **Team Lead:** Watson (Opus 4.7) · **Architects:** 8 of 10 (Opus 4.7, Kimi K2.6, Gemini 2.5 Pro, Mistral Large 2512, Grok 4.20, GLM-5.1, GPT-5.4-mini, Nova Premier v1)
**Phases:** P0 workshop → P1 pre-seed (security/robustness/ops) → P2-4 parallel DCS (10 architect slots, 8 viable) → P5 reconciliation (8 designs, 5 decisions resolved) → P6 final challenge (6/7 challengers; 46 findings, 33 accepted, 15 acknowledged, 1 rejected)
**Status: FINAL**

---

## Executive Summary

After 5 days of paper trading across 4 variants (798 closed trades, ~-$77 combined), Sigil is structurally bleeding from three co-occurring failure modes — not a tuning problem:

1. **`momentum_decel` ≈ 50% of closes, carries 100% of realized losses.** Per-tick firing on 1h candles exits positions before any meaningful price excursion.
2. **`time_limit` ≈ 50% of closes at exactly $0 P&L.** Entries are landing on coins that don't move within the hold horizon (zombie coins + non-predictive entry conditions).
3. **`trailing_stop` fires on <1% of closes.** The current fixed-% threshold is structurally unreachable given the moves Sigil actually catches.

Aggressiveness doesn't fix this: unhinged trades 7.5× more than baseline and produces the same failure shape.

**This design addresses all three failure modes across six layers.** The central bet (Layer C, D1) is: the breakout thesis is overparameterised, not falsified. Tightening entries with multi-timeframe confluence + improving exits with ATR-anchored trailing will shift the exit distribution away from momentum_decel losses and toward trailing-stop wins. Layer F's variant grid tests this directly. If after 30 paper days the time_limit-at-$0 share stays above 20%, the mean-reversion fallback (`pmr_v1`) activates.

**The bot stays in paper indefinitely until the graduation gate (Layer E3) is met.**

---

## Diagnostic Evidence

From `data-snapshot/SUMMARY.md` and per-variant paper-trading.txt:

| Exit reason     | Share | P&L signal |
|-----------------|-------|-----------|
| momentum_decel  | ~50%  | Carries ≥95% of realized losses (all variants); baseline unique: stop_loss contributes ~23% |
| time_limit      | ~50%  | $0 average — entries don't move within hold horizon |
| trailing_stop   | <1%   | 1 closure across all 4 variants combined; 8%–12% fixed threshold is unreachable |

**Verified corrections to prior framing (P6 Findings 1–2):**
- The "exit pattern is identical across all 4 variants" claim is partly wrong. **Baseline diverges**: stop_loss carries ~23% of losses; time_limit closures are absent in baseline. `atr_tight`/`atr_loose` must account for this — baseline may need separate diagnostic attention.
- Trailing_stop_pct varies by variant (8% baseline, 10% moderate/aggressive, 12% unhinged). All structurally unreachable.

---

## Layer A — Hygiene Fixes (unanimous, immediate)

| # | Change | Rationale |
|---|--------|-----------|
| A1 | **Structured `execution_events` table.** Tight schema (no JSONB): `id BIGSERIAL, symbol VARCHAR(32), signal VARCHAR(32), exit_reason VARCHAR(32), active_confluence_threshold TINYINT, realized_pl FLOAT, position_size FLOAT, slippage FLOAT, regime VARCHAR(16), ts TIMESTAMPTZ`. Log exit evaluation snapshot at every close: `{hard_stop: false, atr_trail: false, time_limit_flat: true, fired: "time_limit_flat"}`. | Eliminates journalctl spelunking. Exit diagnosis becomes `SELECT exit_reason, COUNT(*) FROM execution_events` — mirrors paper-trading histogram in <1 minute. |
| A2 | **Zombie-coin filter.** Exclude symbols with 24h $ volume < $500K OR 24h price range < 3%. Derived from paper data: bottom 25th percentile by volume; 3% mirrors dead trailing zone. In `scoring.py`: `is_alive_coin(symbol)` returning True iff both thresholds met. | Gemini's zombie-coin diagnosis: re-entry loop on dead symbols causes 50% time_limit-at-$0 pattern. Concrete thresholds, evidence-backed. |
| A3 | **Re-entry cooldown per symbol.** N=6 hours after any close on a symbol, regardless of reason. Persisted in `symbol_protections` table (see D3). Enforced at entry decision. | Breaks the re-entry loop that lands repeated entries on the same dead symbol. |
| A4 | **Realistic fees + slippage in paper portfolio.** Default: maker 8bps / taker 12bps (Binance standard Tier 0). Config: `paper.slippage_bps_maker`, `paper.slippage_bps_taker`. Validated on startup: warn if slippage+fees > 1.5× variant ATR threshold. | Without fees, paper P&L overstates real edge by 10-30 bps per round trip. `sigilctl config validate --dry-run` reports coverage. |
| A5 | **`momentum_decel` cadence fix.** Evaluate on candle-close only, not per-tick. | Reduces over-firing. Applied even on `control` variant (cadence fix is separate from deletion decision). |
| A6 | **Strict decision-bar principle.** Features for signal at bar i computed only from `candles[:i]`. Persist `decision_candle` UUID + timestamp as audit column on every signal row. | Ensures all backtests are point-in-time correct. Without this, every backtest result is suspect for look-ahead bias (Kimi). |
| A7 | **Bounded external calls.** `RateLimitedCandleFetcher(concurrency=5)` shared across all jobs (Binance REST). 429 backoff: 1s/2s/5s/15s/60s then circuit-break for 5 min. Postgres query timeout: 5s, retry×3 then REDUCED posture. LLM advisor timeout: 500ms, PASS on timeout. **Cross-LXC coordination:** shared Postgres advisory lock (`pg_try_advisory_lock(42)`) to enforce global Binance concurrency cap across 4 LXCs — prevents thundering herd on shared NAT IP (P6 Finding 18). | Standing Rule 3. All values explicit and testable. |

## Layer B — Exit Redesign (the loss-prevention bet)

| # | Change | Implementation detail |
|---|--------|----------------------|
| B1 | **Delete `momentum_decel` from the exit path on all `atr_*` variants.** Retain on `control` variant (legacy behaviour preserved as diagnostic baseline). | Removes the 100% loss path for non-control variants. |
| B2 | **ATR-anchored adaptive trailing stop.** Fixed at **0.5× ATR(14)**. Applied from entry (no profit-prerequisite). Single scalar eliminates magic range (P6 Findings 34): calibrated so noisy coins reprice within the band quickly, preventing the dead-zone that makes current fixed-% unreachable. Variant grid tests this parameter via `atr_tight` (0.5×) vs `atr_loose` (1.0×) — see Layer F. | `exit_manager.py`: compute `atr_stop = entry_price - 0.5 * atr14`; update every candle; trigger `atr_trail` exit if `last_price <= atr_stop`. |
| B3 | **Hard stop unified at -3%.** Paper path `paper_stop_loss_pct: 3.0` aligned with live `stop_loss_pct: 3.0` (P6 Finding 6). Both paths now converge. Rollback note: both configs updated in same migration. | Eliminates paper/live asymmetry. |
| B4 | **`flat_no_move` exit at 1h mark.** If position has not moved >0.5% by the 1-hour mark, close at break-even (or best price), record `exit_reason = flat_no_move`. Distinct from `time_limit`. Precedence: fires before `time_limit`, after `atr_trail`. | Surfaces the zombie-coin problem into a named, measurable exit reason. Enables post-hoc "what share of entries were dead on arrival" query. |
| B5 | **Enforce existing partial take-profit logic.** `partial_tp_pct` and `partial_tp_fraction` already exist in config and code (P6 Finding 4 verified this). Tune thresholds: `partial_tp_pct: 1.5× ATR(14)` instead of fixed 3.5%. | Fixes the "winners evaporating to time_limit" pattern by capturing small wins that the fixed 3.5% threshold misses. |
| B6 | **Explicit exit precedence via `Priority` enum.** `Priority = Enum('HARD_STOP', 'ATR_TRAIL', 'PARTIAL_TP', 'FLAT_NO_MOVE', 'TIME_LIMIT')`. Loop deterministically; return first match. Log evaluation snapshot (all gates bool + fired reason) to `execution_events`. Unit test asserting `HARD_STOP` always beats `TIME_LIMIT` under contrived inputs. Reconciles 4 overlapping time-based exits (P6 Finding 7): `time_exit_minutes`, `dead_man_max_hold_hours`, `breakout time_limit`, new `flat_no_move` all map to enum slots. | Standing Rule 3. Testable, maintainable. No implicit ordering. |

## Layer C — Entry Tightening (decision D1 = tighten breakout, not pivot)

| # | Change | Detail |
|---|--------|--------|
| C1 | **Multi-timeframe confluence — 2-of-3 with warmup.** Signal states: TRUE/FALSE/UNAVAILABLE. Gates: (i) 5m candle breakout vs 1h trend direction, (ii) volume spike (current 5m vol > 1.5× 24h trailing average), (iii) order-book bid/ask imbalance ≥ 1.5 sustained across 3 consecutive 1m snapshots (UNAVAILABLE if depth API fails). **30-candle warmup:** post-warmup UNAVAILABLE = FALSE. **Auto-relax (opt-in):** `confluence.auto_relax: false` by default. If enabled and <3 trades in trailing 7 days, drop to 1-of-3 with Discord alert + `active_confluence_threshold` logged to every subsequent `execution_events` row (P6 Finding 41). | Requires `confluence.auto_relax: true` explicit opt-in — no silent threshold changes. |
| C2 | **5m candle as primary entry timeframe.** Universe pre-filtered to top 200 symbols by 24h volume (slow scan at 5-min cadence). 5m entry scan runs on this top-200 cohort. **Resolves P6 Finding 20** (5m + 30s REST cap incompatibility): 200 symbols × 100ms/symbol + 5 concurrent = ~4s wall-clock, well within 30s cap. | Replaces prior "4500 markets per cycle" which is infeasible under REST concurrency. `universe_scan_symbols: 200` in config. |
| C3 | **Regime hysteresis.** 3 consecutive regime assessments required to change current regime label. Prevents whipsawing on volatility spikes. Regime label fed into confluence gate (i). | Grok's contribution. Pure signal-quality improvement. |
| C4 | **Order book imbalance as confluence factor.** Sustained bid/ask ratio > 1.5 across 3 × 1m snapshots. UNAVAILABLE (not FALSE) if depth API fails. Treated as UNAVAILABLE in 2-of-3 warmup logic. | Mistral's contribution. Additive signal that won't starve entries when unavailable. |

## Layer D — Risk Management (decision D3 = Opus thresholds; PostureCoordinator simplified)

**P6 Finding 33 accepted:** PostureCoordinator singleton removed. Posture folded directly into Circuit Breaker + YAML overlay.

| # | Change | Detail |
|---|--------|--------|
| D1 | **Dynamic position sizing.** `position_pct = base × (1 - drawdown_ratio)` where `base = 0.05` (5% equity). Floor at `base × 0.5` if drawdown > 50% of allowed. | Reduces exposure naturally as losses accrue. |
| D2 | **Circuit breaker — database-backed, manual reset only (P6 Findings 12, 21).** Trigger thresholds (Opus tier): trailing 7d P&L < -2% of starting capital OR drawdown > 4% OR win-rate regression (binary: win_rate < 0.33 after ≥30 trades). On trip: write `system_state(halted_at, halted_by_reason)` to Postgres; set YAML `ENTRY_DISABLED: true`; send Discord alert; log to `execution_events`. **No auto-resume.** Reset only via: `sigilctl circuit-breaker reset --variant <name> --reason "<note>"` — validates bot health, atomically clears DB row + YAML flag, logs operator action. Process restart reads `system_state` first; if halted, stays halted. | File-based `kill_switch.flag` replaced with Postgres-backed state. |
| D3 | **Durable symbol-protection state (P6 Finding 22).** `symbol_protections` table: `symbol, cooldown_until, blacklist_until, consecutive_losses, last_updated`. Hydrated into in-process cache on startup. Updated atomically in same DB transaction as trade-close write. On 3 consecutive losers on same symbol: add to 7-day blacklist. On cooldown: suppress re-entry. Loss of table = startup fatal error (log + halt). | Ensures cooldowns/blacklists survive process restarts. |
| D4 | **YAML posture (replaces PostureCoordinator).** Each variant's `grid-overlay.yaml` has `ENTRY_DISABLED: bool`. Circuit breaker trips set this to `true`. Variants stay fully decoupled in separate LXCs. No cross-variant coordination layer. | Simpler, testable, no singleton. |

## Layer E — Verification (the procedural gate)

| # | Change | Detail |
|---|--------|--------|
| E1 | **Backtest harness — 2-day adapter spike on `src/ml/backtester.py`.** If adapter is clean (< ~150 lines): extend. If coupling is messy: create new `src/backtest/engine.py` (note: this is a **new file**, does not exist yet). Walk-forward: 4 × 30-day rolling windows. Out-of-sample: most recent 30 days held out. Point-in-time enforced via `decision_candle` audit column (A6). Wall-clock cap: 4 hours; partial result emitted with `[INCOMPLETE]` flag on timeout. | This is a new file if the spike fails, NOT an existing path. |
| E2 | **Backtest must-pass thresholds before paper deploy:** profit_factor ≥ 1.3, Sharpe ≥ 0.8 (in-sample), max_drawdown ≤ 5%, time_limit_at_$0_share < 25%, mean_trade > 1.5× estimated_fees_slippage. | Captures the diagnostic metric directly. If time_limit-at-$0 doesn't fall in backtest, the implementation is wrong. |
| E3 | **Paper-trading graduation gate.** 30 calendar days, ≥ 100 closed trades per variant, all conditions: profit_factor ≥ 1.3, Sharpe (daily returns) ≥ 1.0, max_drawdown ≤ 5%, win_rate ≥ 35%, **time_limit_at_$0_share < 20%**. The 20% threshold is the kill-the-thesis criterion — if it doesn't drop, the breakout thesis is dead and `pmr_v1` activates. Graduation never triggers automatically; it signals that real-money go-live *may* proceed, subject to Stuart's manual review. | Gate combines Opus + Kimi + Gemini metrics. time_limit-at-$0 < 20% is the diagnostic kill check (unique to this design). |
| E4 | **Graduation attestation via `sigilctl` CLI (P6 Finding 24, 45).** Bot never needs git write access. Workflow: `sigilctl attest generate --variant <name> --window 30d` computes SHA256 of DB rows, stores result to `graduation_attestation` table, outputs `attestation.json`. `sigilctl attest verify --file attestation.json` validates hash + row counts. A separate CI job (isolated credentials) mirrors to signed git tag. Honest trust model: tamper-detectable by Stuart reviewing, not cryptographically unforgeable against host-level attacker. | Decouples attestation from bot credentials. Operationally realistic for homelab. |
| E5 | **LLM/ML advisor — observer mode only.** Store decisions to `/tmp/advisor_decisions/{variant}_{date}.csv` (file-append per trade, atomic via temp-file-then-rename). Never blocks entry (500ms timeout → PASS). Offline aggregation job computes Pearson correlation against profitable outcomes. **Promotion threshold:** ≥ 0.3 correlation over ≥ 200 trades. Until then: log-only, no live influence. Simpler than in-memory buffer (P6 Finding 38): file append survives crashes, decouples aggregation from bot. | File-based advisory log eliminates in-memory buffer complexity. Offline analysis via pandas. |
| E6 | **Secrets management (P6 Finding 26, Security Findings 14).** All credentials in `secrets.env` (chmod 600), never in YAML/git. Postgres role `sigil_rw`: INSERT/UPDATE on `execution_events`, `paper_trades`, `paper_positions`, `paper_portfolio`, `symbol_protections`, `system_state`, `graduation_attestation`. No DDL/DROP. Migrations run as `sigil_admin`. LLM tokens and Binance keys: env-only. Binance keys: read-only API (market data + order placement via testnet in draft mode; no withdrawal scope). `SIGIL_MODE=draft` guard + "is this a testnet credential?" startup check (P6 Finding 13). | Minimal credentialing. No Vault complexity for homelab; standard chmod 600 + role-scoped Postgres is proportionate. |

## Layer F — Variant Grid (decision D5 = exit-model variance; atr_regime dropped)

**P6 Findings 3 + 40 resolved:** `atr_regime` dropped (regime states {CHOPPY, TRENDING} don't exist in code and would require new subsystem). Layer F contradiction resolved: `control` uses new 5m entry + **legacy exits** to preserve exit-only comparison axis.

**Three variants.** Entry logic is **identical across atr_tight and atr_loose** (5m + 2-of-3 confluence). Only exit calibration differs, so P&L differences are attributable to exit redesign.

| Variant | LXC | Entry | ATR trailing multiplier | Hard stop | `momentum_decel` | Hypothesis |
|---------|-----|-------|------------------------|-----------|-----------------|------------|
| `control` | 236 | New 5m + 2-of-3 confluence | None (legacy exits only) | -3% | **Enabled** (cadence-fixed, candle-close only) | Baseline: entry is controlled; test if cadence-fix alone helps |
| `atr_tight` | 243 | New 5m + 2-of-3 confluence | **0.5× ATR(14)** | -3% | **Deleted** | Tight ATR — kills time_limit at $0; trailing engages |
| `atr_loose` | 244 | New 5m + 2-of-3 confluence | **1.0× ATR(14)** | -3% | **Deleted** | Loose ATR — allows trades to breathe; tests if winners run |
| `pmr_v1` | 245 | Mean-reversion: RSI<35, near 24h low, volume spike | **0.5× ATR(14)** | -3% | **Deleted** | Parallel experiment: if breakout fails (time_limit-at-$0 stays >20% at 30d), this becomes A/B |

**`pmr_v1` is pre-built but initially passive.** LXC 245 runs `pmr_v1` entry logic from day 1 (no trades lost from "unhinged" legacy which was net negative). Gives 30 days of parallel data. If `atr_tight`/`atr_loose` pass graduation gate, compare `pmr_v1` P&L as a bonus. If they don't, `pmr_v1` becomes primary.

---

## Challenge Disposition Log (Phase 6, 46 findings)

### Accepted (33)

All 7 Tier-1 pre-dev items, all 3 Tier-2 pre-deployment items, all narrative fixes, plus:
- Full security suite: authenticated circuit breaker (F12), mode guard (F13), secrets spec (F14), prompt injection sanitisation (F15), yaml.safe_load enforcement (F16), simplified attestation (F17)
- Full ops suite: position rollback gate (F19), pre-filter universe (F20), durable posture (F21), durable symbol_protections (F22), log rotation + disk pressure guard (F23), decoupled attestation (F24)
- Simplicity wins: PostureCoordinator deleted (F33), single ATR scalar (F34), exit enum (F35), concrete filter thresholds (F36), tight execution_events schema (F37), file-based advisor log (F38), binary win-rate threshold (F39)
- Ergonomics: variant contradiction resolved (F40), explicit auto-relax opt-in (F41), exit evaluation snapshot (F42), guarded circuit-breaker reset CLI (F43), config validate dry-run (F44), attestation CLI (F45), execution_events debug CLI (F46)

### Acknowledged (15)

Findings noted with mitigations; addressed in narrative or deferred to post-graduation hardening:

| # | Finding | Mitigation |
|---|---------|------------|
| F1 | Baseline diverges from other 3 variants (stop_loss 23%) | Design revised: baseline given separate row in variant grid. Acknowledged in diagnostic section. |
| F2 | "100% losses" is ≥95% not 100% | Diagnostic reframed accurately above. Conclusion unchanged. |
| F4 | Partial TPs already exist in code | B5 reframed: "enforce + tune thresholds" not "introduce". |
| F5 | Trailing % varies per variant | Diagnostic narrative corrected above. |
| F6 | Dual stop-loss systems (paper 5% vs live 3%) | B3 explicitly unifies both to 3%. |
| F7 | 4 overlapping time exits | Resolved via B6 exit enum precedence. |
| F9 | Universe cap 4500 is wrong (actual 100-200) | C2 spec changed to 200 explicitly. |
| F10 | Bounds cited as preserved but some are proposed | All proposed bounds marked as NEW in Layer A7 / design notes. |
| F11 | `src/backtest/engine.py` doesn't exist | E1 explicitly states "new file if spike fails". |
| F18 | YAML as code-execution vector — `yaml.safe_load` not enforced | F16 accepted covers this. Acknowledged separately. |
| F25 | Postgres single point of failure | Explicit retry + backoff added to A7. PgBouncer recommendation noted. |
| F28-F32 | Data sensitivity classification, backup/restore, credential rotation | Post-graduation hardening checklist items. Not blocking paper launch. |
| F30 | Backup/restore correctness | Acknowledge: implement nightly `pg_dump` before paper launch. |

### Rejected (1)

| # | Finding | Reason |
|---|---------|--------|
| F3 | REJECT: atr_regime variant — regime states {CHOPPY, TRENDING} don't exist in codebase | Design removes `atr_regime`. Not a rejection of the regime concept — it's a scope boundary. Building a new microstructure regime classifier would be a separate design, not a config swap. Variant grid reduced to 3 (control, atr_tight, atr_loose) + pmr_v1. |

---

## Rollback & Migration Posture (Standing Rule 1)

- Every change ships behind YAML config flags. Old behaviour is default until overlay enables new path.
- New schema ships via numbered migrations **starting at 007** (006 is current latest — P6 Finding 8 corrected). All new migrations require paired `_up.sql` and `_down.sql`.
- Schema objects added: `execution_events`, `symbol_protections`, `system_state`, `graduation_attestation`, `decision_candle` column on signals table.
- **Position rollback gate (P6 Finding 19):** Pre-deploy checklist item. Before any rollback: either (a) flatten all open positions first, or (b) persist `position_exit_contract` JSON so old code can map new-style exits to legacy format. Deploy pipeline enforces this check automatically.
- Per-variant YAML overlay + git-tracked config commit. Rollback = revert overlay + restart. Blast radius: single LXC (separate DBs per variant; no cross-variant state).

## Resource Lifecycle (Standing Rule 2)

| Artifact | Retention | Cleanup |
|----------|-----------|---------|
| `execution_events` rows | 90 days | Daily cron `DELETE WHERE ts < NOW() - INTERVAL '90 days'` with dead-man's heartbeat |
| Backtest run artifacts | 30 days | `scripts/cleanup_backtests.py` with DB last-run timestamp; idempotent |
| LLM advisor CSV files | 7 days | Systemd timer `find /tmp/advisor_decisions -mtime +7 -delete` |
| Attestation JSON (Postgres) | Indefinite | Small; no growth concern |
| `symbol_protections` entries | 90 days post-expiry | Cron prune; expired entries kept 90d for audit, then deleted |
| Journal logs | `journalctl --vacuum-size=500M` | Daily systemd timer per LXC |
| Disk pressure guard | Trip circuit breaker at 85% disk on `/opt/app` | `disk_pressure_check` in startup health probe |

## Bounded Loops (Standing Rule 3)

All explicitly proposed (not preserved from current code — marked as NEW):

| Call | Bound |
|------|-------|
| Universe pre-filter scan | Top 200 symbols, 5-min cadence, 30s wall-clock cap |
| 5m entry scan (top-200 cohort) | 200 symbols × 5 concurrent = ~4s wall-clock |
| Per-symbol scoring | 250ms timeout; symbol skipped on timeout |
| Binance REST | 5 concurrent (shared advisory lock cross-LXC); 429 backoff 1s/2s/5s/15s/60s; 5-min circuit-break |
| LLM advisor | 500ms; PASS on timeout; never blocks entry |
| Postgres queries | 5s timeout; retry ×3; REDUCED posture if all fail |
| Backtest run | 4h wall-clock; `[INCOMPLETE]` flag on timeout |

---

## sigilctl CLI (Operational Interface)

New CLI tool co-delivered with this design. Prevents file-system footguns.

```
sigilctl circuit-breaker reset --variant <name> --reason "<note>"
sigilctl attest generate --variant <name> --window 30d
sigilctl attest verify --file <attestation.json>
sigilctl config validate --dry-run                  # reports coins passing/failing each filter
sigilctl debug trades --variant <name> --last 24h --format jsonl  # streams execution_events
sigilctl debug trades --variant <name> --summary    # exit-reason histogram + time_limit-at-$0 share
```

---

## Mean-Reversion Fallback (`pmr_v1`) Specification

If at the 30-day graduation gate: `time_limit_at_$0_share > 20%` across both `atr_tight` and `atr_loose` variants, the breakout entry thesis is flagged as structurally unviable. `pmr_v1` (LXC 245, running in parallel) becomes primary test.

**`pmr_v1` entry conditions:** RSI(14) < 35 on 5m candle, current price within 3% of trailing 24h low, volume spike > 1.2× 24h average. Exit: 0.5× ATR(14) trailing + hard stop -3% + flat_no_move at 1h. No momentum_decel.

**Activation:** `pmr_v1` YAML overlay updated to `IS_PRIMARY: true`. `control`, `atr_tight`, `atr_loose` overlays set `OBSERVATION_ONLY: true` (no new entries, hold existing). Separate paper window begins; graduation gate applies independently.

---

## Confidence Assessment

| Layer | Confidence | Basis |
|-------|------------|-------|
| A (Hygiene) | Very high | All 8 architects agree; all mechanical; verified against codebase |
| B (Exits) | High | 7/8 architects on momentum_decel deletion; 6/8 on ATR trailing; single scalar from P6 (not fuzzy range) |
| C (Entries) | Medium-high | 5/8 on multi-TF confluence; 5m + top-200 universe resolves P6 throughput infeasibility |
| D (Risk) | High | Opus thresholds well-reasoned; PostureCoordinator elimination simplifies considerably |
| E (Verification) | Very high | All 8 architects on backtest gate; graduation metrics tightly convergent |
| F (Variant grid) | High | Exit-model variance is the cleanest test; `pmr_v1` built as parallel fallback |

**The single load-bearing bet:** multi-timeframe confluence + ATR exits reduce the time_limit-at-$0 share below 20%. Layer F measures this directly. If it doesn't drop, `pmr_v1` activates automatically.

---

## Source Artifacts

| Phase | Artifacts |
|-------|-----------|
| Data snapshot | `data-snapshot/` — 4-variant paper trading DB queries, log excerpts, config overlays, code structure |
| Discovery | `discovery.md` |
| Pre-seed | `pre-seed/collated-pre-seed.md` |
| Architect designs | `architect-{1-10}/architect-design.md` (8 viable) |
| Reconciliation | `reconciliation.md` + `reconciliation-extract.md` |
| Phase 6 challenges | `final-challenge/challenge-{verification,security,ops,data,simplicity,ergonomics}.md` |
| Phase 6 triage | `phase6-triage.md` |

---

*Pipeline copy: `architect-design.md` in this directory.*
