its-magic 0.1.3-1 → 0.1.3-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/installer.ps1 +8 -0
  2. package/installer.py +8 -0
  3. package/installer.sh +1 -0
  4. package/package.json +1 -1
  5. package/template/.cursor/commands/auto.md +90 -0
  6. package/template/.cursor/commands/execute.md +26 -0
  7. package/template/.cursor/commands/refresh-context.md +32 -0
  8. package/template/.cursor/commands/sovereign-critic.md +104 -0
  9. package/template/.cursor/rules/sovereign-role-manifest.mdc.example +27 -0
  10. package/template/.cursor/scratchpad.md +141 -0
  11. package/template/.cursor/sovereign-role-manifest.yaml.example +53 -0
  12. package/template/decisions/DEC-0104.md +279 -0
  13. package/template/decisions/DEC-0105.md +231 -0
  14. package/template/decisions/DEC-0107.md +246 -0
  15. package/template/docs/engineering/architecture.md +78 -0
  16. package/template/docs/engineering/auto-orchestration-reference.md +7 -0
  17. package/template/docs/engineering/context/installer-owned-paths.manifest +8 -0
  18. package/template/docs/engineering/reason_codes.md +411 -0
  19. package/template/docs/engineering/runbook.md +922 -0
  20. package/template/docs/engineering/sovereign-memory/.gitkeep +0 -0
  21. package/template/docs/engineering/sovereign-memory/retrospectives/.gitkeep +0 -0
  22. package/template/handoffs/sovereign_decisions/.gitkeep +0 -0
  23. package/template/handoffs/sovereign_deferrals/.gitkeep +0 -0
  24. package/template/handoffs/sovereign_role_reviews.jsonl +0 -0
  25. package/template/scripts/__pycache__/decision_ledger_lib.cpython-312.pyc +0 -0
  26. package/template/scripts/check_intake_template_parity.py +119 -0
  27. package/template/scripts/decision_ledger_lib.py +732 -0
  28. package/template/scripts/ledger_validate.py +153 -0
  29. package/template/scripts/parallel_dev_arbiter.py +923 -0
  30. package/template/scripts/release_trigger_adapters.py +843 -0
  31. package/template/scripts/self_healing_deploy_lib.py +463 -0
  32. package/template/scripts/self_healing_deploy_validate.py +78 -0
  33. package/template/scripts/sovereign_convergence_lib.py +994 -0
  34. package/template/scripts/sovereign_convergence_validate.py +206 -0
  35. package/template/scripts/sovereign_critic_lib.py +629 -0
  36. package/template/scripts/sovereign_critic_validate.py +131 -0
  37. package/template/scripts/sovereign_loop_lib.py +828 -0
  38. package/template/scripts/sovereign_loop_validate.py +122 -0
  39. package/template/scripts/sovereign_memory_lib.py +869 -0
  40. package/template/scripts/sovereign_memory_validate.py +153 -0
  41. package/template/scripts/sovereign_role_manifest_lib.py +547 -0
  42. package/template/scripts/sovereign_role_manifest_validate.py +105 -0
  43. package/template/tests/us0108_contract_test.py +207 -0
  44. package/template/tests/us0109_contract_test.py +209 -0
  45. package/template/tests/us0109_us0110_compose_test.py +34 -0
  46. package/template/tests/us0111_contract_test.py +345 -0
@@ -0,0 +1,246 @@
1
+ # DEC-0107: Sovereign Loop Mode (US-0107)
2
+
3
+ - **Date**: 2026-06-29
4
+ - **Status**: Accepted
5
+ - **Story**: `US-0107`
6
+ - **Composes on**: **US-0088** (quiet mode), **US-0092** (full-autonomy outer driver), **US-0095** (native-chain segments), **US-0044** (backlog drain), **US-0103** (decision ledger), **US-0105** (sovereign memory), **US-0110** (goal convergence) — **do not amend**; US-0107 **layers** orchestration only
7
+ - **Related**: `R-0094` (research anchor), **US-0109** (deploy smoke — downstream deferral writer), **US-0069** (spawn-only), **US-0045** (status authority), **US-0017** (template parity)
8
+ - **Supersedes**: none
9
+ - **Default-off**: `AUTO_SOVEREIGN=0` — zero overhead when off
10
+
11
+ ## Context
12
+
13
+ Project-level autonomous delivery orchestration for the sovereign-loop batch. When operators enable **`AUTO_SOVEREIGN`**, the outer driver owns **deferral register**, **drain-generate** (PO proposals when backlog empty but not converged), **notification dispatch** on terminal events, and **convergence hooks** via **US-0110**. **US-0088 / US-0092 / US-0095 / US-0044 / US-0103 / US-0105 / US-0110 are UNCHANGED** — US-0107 adds scratchpad keys, JSONL deferral register, loop lib API, sidecar run-state, and compose hooks only.
14
+
15
+ Research basis: `R-0094` Q1–Q7 closed.
16
+
17
+ ## Decision
18
+
19
+ ### §1 — Scratchpad keys + goal-mode coupling (AC-1)
20
+
21
+ | Key | Values | Default | Notes |
22
+ |-----|--------|---------|-------|
23
+ | **`AUTO_SOVEREIGN`** | **`0`** \| **`1`** | **`0`** | When `0`, zero overhead — no deferral reads/writes, no advance, no notifications. |
24
+ | **`AUTO_SOVEREIGN_DEFERRAL_MAX`** | int ≥ **1** | **`50`** | Max open deferral rows; append rejected at cap. |
25
+ | **`AUTO_SOVEREIGN_DRAIN_GENERATE_MAX`** | int ≥ **0** | **`3`** | Max drain-generate PO iterations per `orchestrator_run_id`. |
26
+ | **`AUTO_SOVEREIGN_DEFERRAL_POLICY`** | **`stop`** \| **`skip`** \| **`resolve_first`** | **`resolve_first`** | How open deferrals gate advance. |
27
+ | **`SOVEREIGN_NOTIFY_TARGET`** | **`off`** \| **`ntfy`** \| **`email`** \| **`hook`** | **`off`** | Notification adapter selection. |
28
+ | **`SOVEREIGN_NOTIFY_NTFY_TOPIC`** | string | *(empty)* | ntfy topic — **local-only** value. |
29
+ | **`SOVEREIGN_NOTIFY_NTFY_BASE`** | URL | *(empty)* | Optional ntfy base URL override — **local-only**. |
30
+ | **`SOVEREIGN_NOTIFY_HOOK_URL`** | URL | *(empty)* | Webhook POST target — **local-only**. |
31
+ | **`SOVEREIGN_NOTIFY_EMAIL_TO`** | email | *(empty)* | Email v1 deferred — **local-only** name. |
32
+
33
+ Published in **`.cursor/scratchpad.md`** (+ **`template/.cursor/scratchpad.md`** byte-parity per **US-0017**). Config key **names** in committed scratchpad; **values** in `.cursor/scratchpad.local.md` or env vars only.
34
+
35
+ **Goal-mode coupling (fail-closed)**: `is_sovereign_loop_enabled(scratchpad)` requires **`AUTO_SOVEREIGN=1` AND `SOVEREIGN_GOAL_MODE=goal_convergence`** (via `is_goal_convergence_enabled()` from **US-0110**). When sovereign flag on but goal mode `phase_driven` → `advance_sovereign_loop` returns `action=blocked`, `reason_code=SOVEREIGN_LOOP_GOAL_MODE_REQUIRED` **before** convergence eval.
36
+
37
+ **Rejected**: auto-enable `goal_convergence` when `AUTO_SOVEREIGN=1` — silently changes terminal semantics without operator intent (**R1**).
38
+ **Rejected**: sovereign loop without goal mode — undefined terminal condition.
39
+
40
+ **Operator recipe**: set both `AUTO_SOVEREIGN=1` and `SOVEREIGN_GOAL_MODE=goal_convergence` in `.cursor/scratchpad.local.md`.
41
+
42
+ ### §2 — Deferral register JSONL v1 (AC-2)
43
+
44
+ **Path**: **`handoffs/sovereign_deferrals.jsonl`** (+ template **`handoffs/sovereign_deferrals/`** `.gitkeep` only).
45
+
46
+ **Bootstrap**: **create-on-first-write**; ship **`.gitkeep`** — no empty tracked JSONL seed.
47
+
48
+ **Required fields** (each JSONL line):
49
+
50
+ | Field | Type | Notes |
51
+ |-------|------|-------|
52
+ | **`schema_version`** | int | **`1`** |
53
+ | **`deferral_id`** | UUIDv4 | Stable id across lifecycle rows |
54
+ | **`ts`** | ISO 8601 UTC | Sortable timestamp |
55
+ | **`reason_code`** | string | Orchestrator reason (e.g. `DEPLOY_DEFERRED`, `BLOCK_RETRY_CAP_EXHAUSTED`) |
56
+ | **`work_item_kind`** | enum | **`story`** \| **`bug`** \| **`deploy`** \| **`block`** |
57
+ | **`work_item_ref`** | string | Max **128** chars — `US-xxxx`, `BUG-xxxx`, deploy target, phase token |
58
+ | **`state`** | enum | **`open`** \| **`resolved`** \| **`superseded`** |
59
+ | **`source_orchestrator_run_id`** | string | Non-empty provenance |
60
+ | **`remediation_hint`** | string | Non-empty, max **512** chars |
61
+
62
+ **Optional fields**: `blocked_by_phase` (canonical phase id), `retry_count` (int ≥ 0), `ledger_decision_id` (UUID — **US-0103** provenance only; no ledger schema change).
63
+
64
+ **Lifecycle (append-only)**: `append_deferral` writes `state=open`; `resolve_deferral(deferral_id)` appends new row with same `deferral_id`, `state=resolved`, fresh `ts`; supersede uses `state=superseded`. **Latest-state-wins** per `deferral_id` when computing open set.
65
+
66
+ **Open-row cap**: reject append when `len(list_open_deferrals()) >= AUTO_SOVEREIGN_DEFERRAL_MAX` → **`SOVEREIGN_DEFERRAL_CAP_EXCEEDED`**.
67
+
68
+ **Secret scan**: reject when `remediation_hint` or `work_item_ref` match secret heuristics (mirror **US-0103** / **US-0105**: `api_key=`, PEM, `sk-`, `ghp_`).
69
+
70
+ **Sidecar run-state**: **`handoffs/sovereign_loop_state.json`** v1 — per-`orchestrator_run_id` drain-generate iteration counter (not git-tracked content in template; schema documented only).
71
+
72
+ **Rejected**: in-place mutation of deferral rows (**rejected** — breaks audit trail).
73
+ **Rejected**: empty tracked JSONL seed (**rejected** — create-on-first-write).
74
+
75
+ ### §3 — Validator CLI (AC-2, AC-7)
76
+
77
+ **Script**: **`scripts/sovereign_loop_validate.py`** (+ template mirror).
78
+
79
+ | Flag | Purpose |
80
+ |------|---------|
81
+ | **`--file`** | Validate single JSONL file |
82
+ | **`--repo`** | Validate repo deferrals path |
83
+ | **`--self-test`** | Contract self-test |
84
+ | **`--enforce`** | Fail-closed exit on first invalid line |
85
+
86
+ Exit **0/1/2** mirrors **DEC-0103** / **DEC-0105**. Success token: **`[SOVEREIGN_LOOP_VALIDATION_OK]`**.
87
+
88
+ Lib helper: `schema_check_deferral(entry) -> (bool, error|None)`.
89
+
90
+ ### §4 — Helper library API (AC-3)
91
+
92
+ **Script**: **`scripts/sovereign_loop_lib.py`** (+ template mirror). Research stub ships schemas, gates, dataclasses + self-test (`[SOVEREIGN_LOOP_SELF_TEST_OK]`); advance/dispatch bodies finalized at execute tranche B.
93
+
94
+ **`SovereignLoopStepResult` v1** fields: `schema_version=1`, `action` ∈ {`noop`,`continue`,`defer`,`drain_generate`,`terminal_converged`,`terminal_timeout`,`terminal_cap`,`blocked`}, optional `reason_code`, optional `stop_reason` (native-chain breadcrumb), `orchestrator_run_id`, `evaluated_at` (ISO UTC), optional `deferral_id`, optional `drain_generate_bundle`, optional `notification_dispatched` (bool), optional `convergence` (embedded **US-0110** `ConvergenceResult.to_dict()` snapshot).
95
+
96
+ | Function | Purpose |
97
+ |----------|---------|
98
+ | **`is_sovereign_loop_enabled(scratchpad) -> bool`** | `AUTO_SOVEREIGN=1` **and** `is_goal_convergence_enabled(scratchpad)` |
99
+ | **`resolve_deferrals_path(repo_root) -> Path`** | `handoffs/sovereign_deferrals.jsonl` |
100
+ | **`schema_check_deferral(entry) -> (bool, error\|None)`** | v1 field validation + secret scan |
101
+ | **`list_open_deferrals(repo, *, scratchpad) -> (rows, reason\|None)`** | Latest-state-wins open rows; empty when disabled |
102
+ | **`append_deferral(repo, scratchpad, *, fields...) -> (deferral_id\|None, reason\|None)`** | Append-only + cap enforcement |
103
+ | **`resolve_deferral(repo, deferral_id, *, orchestrator_run_id) -> (ok, reason\|None)`** | Append resolved row |
104
+ | **`count_drain_generate_iterations(repo, orchestrator_run_id) -> int`** | Per-run counter from sidecar |
105
+ | **`advance_sovereign_loop(repo, scratchpad, *, orchestrator_run_id, iteration=None) -> SovereignLoopStepResult`** | Main orchestrator advance — §5 |
106
+ | **`build_drain_generate_spawn_inputs(repo, scratchpad, convergence) -> dict`** | Vision narrow-read + optional memory digest |
107
+ | **`dispatch_notification(scratchpad, event_type, payload) -> (ok, reason\|None)`** | Fail-open adapters — §7 |
108
+ | **`self_test() -> bool`** | **`[SOVEREIGN_LOOP_SELF_TEST_OK]`** |
109
+
110
+ ### §5 — `advance_sovereign_loop` algorithm (AC-3)
111
+
112
+ 1. If `AUTO_SOVEREIGN≠1` → `action=noop` (zero overhead; do not import convergence).
113
+ 2. If `SOVEREIGN_GOAL_MODE≠goal_convergence` → `action=blocked`, `reason_code=SOVEREIGN_LOOP_GOAL_MODE_REQUIRED`.
114
+ 3. `result = evaluate_convergence(repo, scratchpad, orchestrator_run_id=...)`.
115
+ 4. If `result.converged` → `action=terminal_converged` + `dispatch_notification(convergence)` + sovereign terminal stop **`converged`**.
116
+ 5. If `check_timeout(scratchpad, iteration)` → `action=terminal_timeout` + `write_partial_delivery_report` (**US-0110**) + notification.
117
+ 6. Apply **`AUTO_SOVEREIGN_DEFERRAL_POLICY`**: `stop` → block advance when open deferrals; `skip` → informational only; `resolve_first` → block until open deferrals empty (default).
118
+ 7. If backlog has OPEN stories → `action=continue` (delegate to native **US-0044** drain — no bypass).
119
+ 8. If OPEN stories **0** and `not result.converged` and iterations `< AUTO_SOVEREIGN_DRAIN_GENERATE_MAX` → `action=drain_generate` + spawn bundle (§6).
120
+ 9. Else cap/terminal paths → `SOVEREIGN_DRAIN_GENERATE_CAP` or deferral cap + notification.
121
+
122
+ **Sovereign terminal stops** (additive to **US-0088**/**US-0092** matrix): `converged`, `SOVEREIGN_GOAL_TIMEOUT`, `SOVEREIGN_DEFERRAL_CAP_EXCEEDED`, `SOVEREIGN_DRAIN_GENERATE_CAP` — do **not** replace `decision_gate`, `loop_max`, `security deny`, or `BLOCK_RETRY_CAP_EXHAUSTED`.
123
+
124
+ **`drain_terminated`**: set only on sovereign terminal stops — **not** on OPEN-story exhaustion alone (**R5**).
125
+
126
+ ### §6 — Drain-generate contract (AC-4)
127
+
128
+ **Trigger** (all required): `is_sovereign_loop_enabled`, backlog OPEN story count **0**, `evaluate_convergence(...).converged=false`, drain-generate iterations `< AUTO_SOVEREIGN_DRAIN_GENERATE_MAX`, no blocking deferral policy conflict.
129
+
130
+ **Spawn surface**: **`/auto`** outer driver spawns fresh **PO** subagent (spawn-only per **US-0095** / **US-0069**) with ephemeral work item id `drain-gen-{orchestrator_run_id}-{iteration}` — **not** a backlog row until accepted.
131
+
132
+ **PO inputs** (`build_drain_generate_spawn_inputs`): narrow-read `docs/product/vision.md` (exclude Discovery/Intake note sections — same skip rules as **US-0110** goal derive); optional `sovereign_memory_digest` when **`SOVEREIGN_MEMORY=1`** via `build_injection_digest_block()` only; attach `unmet_conditions[]`, `blocked_by[]`, `goal_text` from convergence eval.
133
+
134
+ **`DrainGenerateCandidateBundle` v1** (ephemeral — **not persisted** pre-gate): `schema_version=1`, `orchestrator_run_id`, `iteration`, `generated_at`, `candidates[]` (max **3** per iteration) each with `candidate_id` (UUIDv4), `title` (max **120**), `summary` (max **512**), `ac_sketch` (string[], max **8** items × **256** chars), optional `plan_area_id`, `priority` (default **`P2`**), `provenance` ∈ {`vision`,`memory`,`both`}.
135
+
136
+ **Decision gate (mandatory per candidate)**: PO output → standard **`decision_gate`** in **`/auto`** — operator accept → **`/intake`** or controlled backlog append; reject → discard candidate. **Rejected**: auto-append without gate — violates **US-0092** hard gates (**R2**).
137
+
138
+ **Cap exhausted**: `SOVEREIGN_DRAIN_GENERATE_CAP` sovereign terminal + optional `dispatch_notification(drain_generate_cap)`.
139
+
140
+ ### §7 — Notification adapters (AC-5)
141
+
142
+ **`SOVEREIGN_NOTIFY_TARGET`**: `off` (zero overhead) \| `ntfy` \| `hook` \| `email`.
143
+
144
+ **Event types**: `convergence`, `timeout`, `deferral_cap`, `drain_generate_cap`.
145
+
146
+ **Payload envelope v1**: `{schema_version, event_type, ts, orchestrator_run_id, reason_code, unmet_conditions[], blocked_by[], goal_progress}` where `goal_progress` embeds **US-0110** block when available.
147
+
148
+ **ntfy v1**: stdlib `urllib.request` POST plain-text body to `{SOVEREIGN_NOTIFY_NTFY_BASE or https://ntfy.sh}/{SOVEREIGN_NOTIFY_NTFY_TOPIC}`; headers `Title`, `Priority` (4 for cap/timeout, 3 for convergence), `Tags: sovereign,auto`; timeout **10s**.
149
+
150
+ **hook v1**: POST `application/json` to `SOVEREIGN_NOTIFY_HOOK_URL` with payload envelope; timeout **10s**.
151
+
152
+ **email v1**: **deferred** — `dispatch_notification` returns `(False, SOVEREIGN_NOTIFY_TARGET_INVALID)` with info log; runbook documents v1.1 SMTP stub. **Rejected**: stdlib SMTP in v1 (credential handling + deliverability risk).
153
+
154
+ **Fail-open**: any adapter exception → log **`SOVEREIGN_NOTIFY_DISPATCH_FAILED`**, return `(True, None)` — notification must not block loop.
155
+
156
+ **Secret handling (R4)**: topic/URL values local-only; never write into git-tracked handoffs or JSONL.
157
+
158
+ ### §8 — US-0109 integration declaration (AC-6)
159
+
160
+ **US-0109** implements post-deploy smoke + bounded repair. On cap exhaustion writes **`DEPLOY_DEFERRED`** row to **`sovereign_deferrals.jsonl`** using §2 schema (`work_item_kind=deploy`). **US-0107** owns register schema, validator, read paths, and documents integration contract — **no** deploy smoke logic in US-0107 scope.
161
+
162
+ **`DEPLOY_DEFERRED`**: reserved reason_code for **US-0109** writer; non-blocking deferral row (not advance-block by itself unless policy applies).
163
+
164
+ ### §9 — Reason code inventory (AC-8)
165
+
166
+ | Code | Blocking? | Surface |
167
+ |------|-----------|---------|
168
+ | **`SOVEREIGN_LOOP_DISABLED`** | no (info) | `AUTO_SOVEREIGN=0` zero overhead |
169
+ | **`SOVEREIGN_LOOP_GOAL_MODE_REQUIRED`** | yes | sovereign on without `goal_convergence` |
170
+ | **`SOVEREIGN_DEFERRAL_CAP_EXCEEDED`** | yes | append cap / sovereign terminal |
171
+ | **`SOVEREIGN_DEFERRAL_SCHEMA_INVALID`** | yes | validator / append |
172
+ | **`SOVEREIGN_DEFERRAL_APPEND_FAILED`** | yes | I/O |
173
+ | **`SOVEREIGN_DRAIN_GENERATE_CAP`** | yes | drain-generate iterations exhausted |
174
+ | **`SOVEREIGN_DRAIN_GENERATE_BLOCKED`** | yes | policy/deferral gate blocks spawn |
175
+ | **`SOVEREIGN_NOTIFY_DISPATCH_FAILED`** | no (fail-open log) | adapter errors |
176
+ | **`SOVEREIGN_NOTIFY_TARGET_INVALID`** | no | unknown target / email v1 defer |
177
+ | **`SOVEREIGN_NOTIFY_CONFIG_MISSING`** | no (skip notify) | target on but config absent |
178
+ | **`SOVEREIGN_LOOP_ADVANCE_BLOCKED`** | yes | deferral policy `stop`/`resolve_first` |
179
+ | **`DEPLOY_DEFERRED`** | no (deferral row) | **US-0109** writer (integration) |
180
+
181
+ ### §10 — Contract tests + parity (AC-7, AC-8)
182
+
183
+ Eight **`test_us0107_*`** markers in **`tests/us0107_contract_test.py`**:
184
+
185
+ 1. `test_us0107_scratchpad_keys_literals`
186
+ 2. `test_us0107_deferral_jsonl_schema_contract`
187
+ 3. `test_us0107_advance_deferral_policy_literals`
188
+ 4. `test_us0107_drain_generate_gate_contract`
189
+ 5. `test_us0107_notification_fail_open_literals`
190
+ 6. `test_us0107_goal_mode_coupling_fail_closed`
191
+ 7. `test_us0107_zero_overhead_default`
192
+ 8. `test_us0107_compose_no_stop_matrix_change`
193
+
194
+ Compose regression guards (AC-8):
195
+
196
+ - `test_us0107_us0110_convergence_import_contract`
197
+ - `test_us0107_us0095_spawn_only_regression_guard`
198
+
199
+ **`SOVEREIGN_LOOP_PAIRS`** for `check_intake_template_parity.py --scope=sovereign-loop`:
200
+
201
+ - `scripts/sovereign_loop_lib.py` ↔ `template/scripts/sovereign_loop_lib.py`
202
+ - `scripts/sovereign_loop_validate.py` ↔ `template/scripts/sovereign_loop_validate.py`
203
+ - `.cursor/scratchpad.md` ↔ `template/.cursor/scratchpad.md` (`AUTO_SOVEREIGN_*` + `SOVEREIGN_NOTIFY_*` block)
204
+ - `handoffs/sovereign_deferrals/.gitkeep` ↔ `template/handoffs/sovereign_deferrals/.gitkeep`
205
+ - `decisions/DEC-0107.md` ↔ `template/decisions/DEC-0107.md`
206
+ - `scripts/check_intake_template_parity.py` ↔ `template/scripts/check_intake_template_parity.py` (scope registration)
207
+
208
+ ### §11 — Composition rules
209
+
210
+ | Story | Compose rule |
211
+ |-------|--------------|
212
+ | **US-0088** / **US-0092** / **US-0095** | Stop matrix, spawn-only, native chain **unchanged**; sovereign terminal stops additive only. |
213
+ | **US-0044** / **US-0087** | Drain mutex unchanged; sovereign advance consults deferrals before story selection. |
214
+ | **US-0103** | Optional deferral provenance via `ledger_decision_id`; ledger schema unchanged. |
215
+ | **US-0105** | Drain-generate reads `build_injection_digest_block()` only when `SOVEREIGN_MEMORY=1`. |
216
+ | **US-0110** | Import `evaluate_convergence`, `is_goal_convergence_enabled`, `build_goal_progress_block`, `check_timeout`, `write_partial_delivery_report`; export `list_open_deferrals()` for `zero_deferrals` conjunct wiring — **do not amend** five-conjunct set or **DEC-0110**. |
217
+ | **US-0109** | Downstream `DEPLOY_DEFERRED` writer — schema stable in US-0107 first (**R6**). |
218
+ | **US-0069** | Spawn-only PO for drain-generate — no in-chat chain bypass. |
219
+ | **US-0045** | US-0107 remains **OPEN** until release closure. |
220
+
221
+ ### §12 — Risks
222
+
223
+ | Risk | Mitigation |
224
+ |------|------------|
225
+ | **R1** Goal-mode coupling | Fail-closed **`SOVEREIGN_LOOP_GOAL_MODE_REQUIRED`**; operator recipe in runbook §1 |
226
+ | **R2** Drain-generate scope creep | Max **3** candidates/iteration + mandatory decision gate per candidate §6 |
227
+ | **R3** Deferral cap vs **`CONVERGENCE_DEFERRALS_PENDING`** | Shared `list_open_deferrals()` latest-state-wins; cap blocks append, open rows block convergence |
228
+ | **R4** Notification secrets | Local-only config; payload excludes hook URLs/topics |
229
+ | **R5** Sovereign terminal vs **US-0095** segments | Terminal stops additive post-segment eval; `drain_terminated` only on sovereign terminal |
230
+ | **R6** **US-0109** ordering | Deferral v1 schema + validator stable in US-0107; **`DEPLOY_DEFERRED`** reserved |
231
+
232
+ ### §13 — Implementation tranche order
233
+
234
+ 1. **Tranche A** — scratchpad keys + reason codes + `DEC-0107` template mirror + deferrals `.gitkeep`
235
+ 2. **Tranche B** — **`sovereign_loop_lib.py`** deferral CRUD + `list_open_deferrals` + self-test core
236
+ 3. **Tranche C** — **`advance_sovereign_loop`** + **`sovereign_loop_validate.py`** + sidecar run-state
237
+ 4. **Tranche D** — drain-generate spawn inputs + notification adapters + **`/auto`** advance wiring + **US-0110** `zero_deferrals` compose
238
+ 5. **Tranche E** — eight `test_us0107_*` + compose guards + **`SOVEREIGN_LOOP_PAIRS`** parity + runbook + architecture `# US-0107`
239
+
240
+ ## References
241
+
242
+ - `docs/engineering/research.md` — **`R-0094`**
243
+ - `docs/product/backlog.md` — **`## US-0107`**
244
+ - `handoffs/intake_evidence/intake-sovereign-20260627-01.json`
245
+ - `scripts/sovereign_loop_lib.py` — research stub + self-test
246
+ - Shipped compose: `scripts/sovereign_convergence_lib.py` (**US-0110**), `scripts/sovereign_memory_lib.py` (**US-0105**), `scripts/decision_ledger_lib.py` (**US-0103**)
@@ -7,3 +7,81 @@
7
7
  ## Risks
8
8
 
9
9
  ## Decisions
10
+
11
+ # US-0112 — Model-catalog example preset delivery
12
+
13
+ **Story**: US-0112 (Ship model-catalog example presets on install/upgrade)
14
+ **Decision**: DEC-0112 (Accepted)
15
+ **Research anchor**: R-0090 (delivered, Q1–Q8 closed)
16
+
17
+ ## Framework vs operator boundary
18
+
19
+ The 8 `model-catalog.local.example*.json` presets are **framework files** under installer manifest control. They ship on install/upgrade and are refreshed when stale (same semantics as `scratchpad.local.example.md` per US-0075/US-0018/US-0057).
20
+
21
+ The active operator-owned `.cursor/model-catalog.local.json` is **gitignored**, outside `install_include_paths` and `clean_paths`, and never touched by any installer mode. This is a DEC-0086/DEC-0087 boundary — US-0112 completes delivery of existing presets without altering catalog schema (US-0101) or role precedence (US-0102).
22
+
23
+ ## Manifest rows (8 paths)
24
+
25
+ Under `[install_include_paths]` in both `docs/engineering/context/installer-owned-paths.manifest` and `template/docs/engineering/context/installer-owned-paths.manifest` (16 rows total, byte-parity):
26
+
27
+ 1. `.cursor/model-catalog.local.example.json`
28
+ 2. `.cursor/model-catalog.local.example.cursor-only.json`
29
+ 3. `.cursor/model-catalog.local.example.level-1-easy.json`
30
+ 4. `.cursor/model-catalog.local.example.level-2-complex.json`
31
+ 5. `.cursor/model-catalog.local.example.level-3-mega.json`
32
+ 6. `.cursor/model-catalog.local.example.level-4-super.json`
33
+ 7. `.cursor/model-catalog.local.example.role-based-balanced.json`
34
+ 8. `.cursor/model-catalog.local.example.role-based-highend.json`
35
+
36
+ ## Upgrade classification (framework files)
37
+
38
+ - **Missing mode**: copies all 8 examples when absent; no-op when present; deterministic log/status per file.
39
+ - **Upgrade mode**: refreshes stale framework files (template content differs); skips byte-identical files; never touches `.cursor/model-catalog.local.json`.
40
+ - **Triple installer parity**: `installer.py`, `installer.ps1`, `installer.sh` all classify `.cursor/model-catalog.local.example*.json` as `framework` via explicit enumeration in `FRAMEWORK_EXACT` (Python) / `$frameworkExact` (PowerShell) / case pattern (Bash).
41
+
42
+ ## DEC-0086 / DEC-0087 compose
43
+
44
+ US-0112 does **not** amend:
45
+ - US-0101 (catalog schema, DEC-0086)
46
+ - US-0102 (role catalog precedence, DEC-0087)
47
+ - US-0054 (publish confirmation gates)
48
+ - US-0057 (example-first refresh)
49
+ - US-0075 (scratchpad example-first)
50
+
51
+ US-0112 only extends the installer manifest to include the 8 example presets as framework files, completing DEC-0086/DEC-0087 delivery path.
52
+
53
+ ## Active catalog protection invariant
54
+
55
+ `.cursor/model-catalog.local.json` is:
56
+ - Gitignored (not tracked)
57
+ - Outside `install_include_paths` (not manifest-copied)
58
+ - Outside `clean_paths` (not manifest-cleaned)
59
+ - Never auto-populated by any installer mode
60
+ - Operator-owned; installer respects DEC-0086/DEC-0087 ownership boundary
61
+
62
+ ## Test markers (8+)
63
+
64
+ `tests/us0112_contract_test.py` provides:
65
+ - `test_us0112_manifest_lists_eight_paths` (active + template)
66
+ - `test_us0112_missing_mode_adds_absent_framework_files` (Python/PS1/Bash)
67
+ - `test_us0112_upgrade_mode_refreshes_stale_framework_files`
68
+ - `test_us0112_upgrade_mode_preserves_unchanged_files`
69
+ - `test_us0112_upgrade_mode_never_touches_local_catalog`
70
+ - `test_us0112_active_catalog_protection_invariant`
71
+ - `test_us0112_parity_scope_model_catalog_examples`
72
+ - `test_us0112_runbook_lists_eight_preset_literals`
73
+
74
+ ## Parity scope
75
+
76
+ `scripts/check_intake_template_parity.py --scope=model-catalog-examples` validates active vs template byte-parity for the manifest rows (16 rows total). Constant: `MODEL_CATALOG_EXAMPLE_PAIRS` includes the manifest pair.
77
+
78
+ ## Reason codes
79
+
80
+ - `MODEL_CATALOG_EXAMPLE_PARITY_SCOPE_OK`
81
+ - `MODEL_CATALOG_EXAMPLE_PARITY_SCOPE_MISMATCH`
82
+
83
+ ## Compose guards (non-negotiable)
84
+
85
+ DO NOT amend: US-0008, US-0018, US-0040, US-0054, US-0057, US-0075, US-0100, US-0101, US-0102, US-0103, US-0107, US-0110.
86
+
87
+ US-0112 is additive only — extends manifest + installer classification; no schema/precedence changes.
@@ -1126,6 +1126,13 @@ when stack cannot be resolved. Connect block fields align with
1126
1126
  `AUTO_ROLE_REFRESH_CONTEXT`), enforce execute default deny / override
1127
1127
  contract, and run the preflight capability gate; on failure stop with
1128
1128
  `PHASE_ROLE_CAPABILITY_MISSING` (no unrelated-role spawn).
1129
+ - **US-0105 / DEC-0105**: When `SOVEREIGN_MEMORY=1`, after phase-context
1130
+ narrow-read and **before** role instructions, append read-only
1131
+ **`sovereign_memory_digest`** block assembled via
1132
+ `build_injection_digest_block(...)` from `scripts/sovereign_memory_lib.py`
1133
+ (bounded top-N/top-K merge; char cap `SOVEREIGN_MEMORY_MAX_CHARS`). When
1134
+ `SOVEREIGN_MEMORY=0` (default), skip with zero overhead — **US-0023**
1135
+ fresh-context boundary unchanged.
1129
1136
  - **US-0069 / DEC-0051**: After each phase completes, validate isolation
1130
1137
  `role` and strict-proof `role` against the preflight-resolved expected
1131
1138
  role; on conflict stop with `PHASE_ROLE_MISMATCH`.
@@ -14,6 +14,14 @@
14
14
  .cursor/hooks
15
15
  .cursor/hooks.json
16
16
  .cursor/scratchpad.local.example.md
17
+ .cursor/model-catalog.local.example.json
18
+ .cursor/model-catalog.local.example.cursor-only.json
19
+ .cursor/model-catalog.local.example.level-1-easy.json
20
+ .cursor/model-catalog.local.example.level-2-complex.json
21
+ .cursor/model-catalog.local.example.level-3-mega.json
22
+ .cursor/model-catalog.local.example.level-4-super.json
23
+ .cursor/model-catalog.local.example.role-based-balanced.json
24
+ .cursor/model-catalog.local.example.role-based-highend.json
17
25
  docs
18
26
  sprints
19
27
  handoffs