loki-mode 11.3.0 → 11.3.1

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 (215) hide show
  1. package/README.md +68 -650
  2. package/SKILL.md +4 -4
  3. package/VERSION +1 -1
  4. package/autonomy/completion-council.sh +2 -2
  5. package/autonomy/context-tracker.py +4 -4
  6. package/autonomy/council-v2.sh +1 -1
  7. package/autonomy/grill.sh +1 -1
  8. package/autonomy/lib/done-recognition.sh +1 -1
  9. package/autonomy/lib/prd-enrich.sh +1 -1
  10. package/autonomy/lib/voter-agents.sh +1 -1
  11. package/autonomy/loki +99 -75
  12. package/autonomy/run.sh +30 -18
  13. package/autonomy/sandbox.sh +1 -1
  14. package/autonomy/tui.sh +6 -5
  15. package/autonomy/verify.sh +1 -1
  16. package/bin/loki +166 -59
  17. package/completions/_loki +2 -0
  18. package/completions/loki.bash +2 -2
  19. package/dashboard/__init__.py +1 -1
  20. package/dashboard/server.py +25 -31
  21. package/docs/ARCHITECTURE.md +337 -0
  22. package/docs/BRANDING.md +124 -0
  23. package/docs/CLI-REFERENCE.md +7 -1
  24. package/docs/COMPONENTS.md +447 -0
  25. package/docs/DEPLOYMENT.md +9 -9
  26. package/docs/DOCKER.md +469 -0
  27. package/docs/INSTALLATION.md +67 -1045
  28. package/docs/KNOWN-ISSUES.md +11 -35
  29. package/docs/TESTING.md +161 -0
  30. package/docs/air-gapped.md +1 -2
  31. package/docs/alternative-installations.md +14 -24
  32. package/docs/architecture/DECISIONS.md +333 -0
  33. package/docs/audit-logging.md +7 -7
  34. package/docs/authentication.md +3 -3
  35. package/docs/authorization.md +1 -1
  36. package/docs/certification/04-production-deployment/lab.md +6 -6
  37. package/docs/certification/04-production-deployment/lesson.md +4 -4
  38. package/docs/certification/README.md +1 -1
  39. package/docs/control-plane-container.md +2 -2
  40. package/docs/dev/real-run.md +34 -0
  41. package/docs/dev/release-checklist.md +2 -2
  42. package/docs/exit-codes.md +3 -3
  43. package/docs/git-workflow.md +3 -3
  44. package/docs/metrics.md +37 -55
  45. package/docs/network-security.md +1 -1
  46. package/docs/siem-integration.md +5 -5
  47. package/docs/v10/CLI-MODERN.md +4 -3
  48. package/docs/v10/DECISIONS.md +44 -0
  49. package/docs/v10/DEPS.md +22 -22
  50. package/docs/v10/ENGINE.md +1 -1
  51. package/docs/v10/FAILURE-CLASSES.md +118 -1
  52. package/docs/v10/FOUNDER-QUEUE.md +1 -0
  53. package/docs/v10/GUARDS.md +13 -0
  54. package/docs/v10/LEGACY-REMOVAL.md +4 -6
  55. package/docs/v10/METRICS.md +2 -2
  56. package/docs/v10/MODERNIZE.md +1 -1
  57. package/docs/v10/OPERATING-MODEL.md +2 -1
  58. package/docs/v10/PROGRESS.md +29 -0
  59. package/docs/v11/COST-HALF.md +352 -0
  60. package/docs/v11/MARKET-SLICES.md +315 -0
  61. package/docs/v11/REGISTRIES.md +730 -0
  62. package/loki-ts/data/model-pricing.json +52 -24
  63. package/loki-ts/dist/loki.js +1036 -957
  64. package/mcp/__init__.py +1 -1
  65. package/package.json +1 -1
  66. package/packages/control-plane/dist/server.js +2467 -736
  67. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  68. package/src/protocols/mcp-client.js +6 -2
  69. package/src/protocols/mcp-server.js +13 -3
  70. package/tools/audit-docs.py +1 -1
  71. package/web-app/dist/assets/{AdminPage-D_e45uTw.js → AdminPage-CMkHNJbF.js} +1 -1
  72. package/web-app/dist/assets/{Avatar-T3nIpoaf.js → Avatar-BJyjV7Zi.js} +1 -1
  73. package/web-app/dist/assets/{Badge-BKqb59pP.js → Badge-D572l0uq.js} +1 -1
  74. package/web-app/dist/assets/{Button-DjVlkh8_.js → Button-T4BnOZgl.js} +1 -1
  75. package/web-app/dist/assets/{CockpitPage-DXJgLGmh.js → CockpitPage-Cj_GFsNn.js} +1 -1
  76. package/web-app/dist/assets/{ComparePage-BRP_eVc_.js → ComparePage-A8m4ZXak.js} +1 -1
  77. package/web-app/dist/assets/{ErrorBoundary-CLjpGLjC.js → ErrorBoundary-hugCg5yg.js} +1 -1
  78. package/web-app/dist/assets/{EvidenceReceiptPanel-DX-vb4Xy.js → EvidenceReceiptPanel-CuJKDC2G.js} +1 -1
  79. package/web-app/dist/assets/{GitHubIssuesPanel-214HVHtX.js → GitHubIssuesPanel-BYGKjarC.js} +1 -1
  80. package/web-app/dist/assets/{GitHubPRsPanel-BEiZKc4t.js → GitHubPRsPanel-c7sFIJlf.js} +1 -1
  81. package/web-app/dist/assets/{HomePage-VvMHS5ga.js → HomePage-A1MIkG2P.js} +2 -2
  82. package/web-app/dist/assets/{LoginPage-5WD-v7n3.js → LoginPage-8KQMRhtR.js} +1 -1
  83. package/web-app/dist/assets/{MagicPage-DUQT_Jye.js → MagicPage-C05QW2Lx.js} +1 -1
  84. package/web-app/dist/assets/{MetricsPage-lga-z79v.js → MetricsPage-Oukv5hme.js} +1 -1
  85. package/web-app/dist/assets/{NotFoundPage-CGhBX3G1.js → NotFoundPage-DKIwsawz.js} +1 -1
  86. package/web-app/dist/assets/{ProjectPage-CdzF2GzZ.js → ProjectPage-DwFRPLCG.js} +3 -3
  87. package/web-app/dist/assets/{ProjectsPage-DRG64N8s.js → ProjectsPage-CgY4YYDX.js} +1 -1
  88. package/web-app/dist/assets/{SettingsPage-5fzW9Frb.js → SettingsPage-BpfcSjUA.js} +1 -1
  89. package/web-app/dist/assets/{ShowcasePage-DrTdxO4y.js → ShowcasePage-BqBakC4K.js} +1 -1
  90. package/web-app/dist/assets/{SystemSettingsPage-C9Mqs6Rd.js → SystemSettingsPage-CZLu5VB0.js} +1 -1
  91. package/web-app/dist/assets/{TeamsPage-CUGPdSWo.js → TeamsPage-D55S1jKz.js} +1 -1
  92. package/web-app/dist/assets/{TemplatesPage-CNraDY0F.js → TemplatesPage-D3SydvxN.js} +1 -1
  93. package/web-app/dist/assets/{TerminalOutput-BIu_6Pea.js → TerminalOutput-hNg8G1-e.js} +1 -1
  94. package/web-app/dist/assets/{activity-Bk-kgqaf.js → activity-D2C0VagO.js} +1 -1
  95. package/web-app/dist/assets/{bell-BXmUdmo8.js → bell-CMvYi36w.js} +1 -1
  96. package/web-app/dist/assets/{bot-CiuzXxUR.js → bot-BvtQ6lmo.js} +1 -1
  97. package/web-app/dist/assets/{check-BEzjXppd.js → check-B13xkXed.js} +1 -1
  98. package/web-app/dist/assets/{chevron-left-AYWCXHf8.js → chevron-left-emu6r49E.js} +1 -1
  99. package/web-app/dist/assets/{circle-alert-BNg2uSRq.js → circle-alert-CExlwjuy.js} +1 -1
  100. package/web-app/dist/assets/{clock-DTj0kkGT.js → clock-D7Uas3oL.js} +1 -1
  101. package/web-app/dist/assets/{cloud-x4nTDBLT.js → cloud-CkB4S86C.js} +1 -1
  102. package/web-app/dist/assets/{code-xml-BVh_MLrk.js → code-xml-SL9IIWIn.js} +1 -1
  103. package/web-app/dist/assets/{database-DdfBaowG.js → database-BQFkd7t1.js} +1 -1
  104. package/web-app/dist/assets/{dollar-sign-XuYFmAOY.js → dollar-sign-qHmnNYsU.js} +1 -1
  105. package/web-app/dist/assets/{file-code-corner-D4cRnmeL.js → file-code-corner-C2YUDP0K.js} +1 -1
  106. package/web-app/dist/assets/{file-plus-CyoVlHc_.js → file-plus-C_ooIkDe.js} +1 -1
  107. package/web-app/dist/assets/{globe-Y6IK2RPW.js → globe-CQ-GL485.js} +1 -1
  108. package/web-app/dist/assets/{hammer-BKzr9VZI.js → hammer-U05L_D7V.js} +1 -1
  109. package/web-app/dist/assets/{index-B20cSx5G.js → index-CooHd7I-.js} +3 -3
  110. package/web-app/dist/assets/{layers-DebNOhGS.js → layers-Buo17rjW.js} +1 -1
  111. package/web-app/dist/assets/{loader-circle-DyGbrEgd.js → loader-circle-15vK3oV1.js} +1 -1
  112. package/web-app/dist/assets/{lock-BKPpyt20.js → lock-BeXLebuJ.js} +1 -1
  113. package/web-app/dist/assets/{package-egF5Wi4y.js → package-MVh_6-6R.js} +1 -1
  114. package/web-app/dist/assets/{plus-OiEgKIc-.js → plus-Dh_nd9vS.js} +1 -1
  115. package/web-app/dist/assets/{refresh-cw-CzKvrONq.js → refresh-cw-C9cBJEAT.js} +1 -1
  116. package/web-app/dist/assets/{rotate-ccw-Bu2mII0p.js → rotate-ccw-D3PAtzST.js} +1 -1
  117. package/web-app/dist/assets/{scroll-text-CSkiyax8.js → scroll-text-DZCoXQjo.js} +1 -1
  118. package/web-app/dist/assets/{server-DlPthJFw.js → server-OCOLI5J_.js} +1 -1
  119. package/web-app/dist/assets/{shield-alert-CbpHWQQX.js → shield-alert-oVhmf1_h.js} +1 -1
  120. package/web-app/dist/assets/{thumbs-up-DgGpZe-Q.js → thumbs-up-B-kbX4vN.js} +1 -1
  121. package/web-app/dist/assets/{trash-2-BV3GlCB-.js → trash-2-EL6moveW.js} +1 -1
  122. package/web-app/dist/assets/{trending-down-Y4TJtXhD.js → trending-down-Cl3kjpsx.js} +1 -1
  123. package/web-app/dist/assets/{trending-up-DsDNoHZY.js → trending-up-DST7I6M2.js} +1 -1
  124. package/web-app/dist/assets/{upload-gkThrc_I.js → upload-CUOT780G.js} +1 -1
  125. package/web-app/dist/assets/{usePolling-jpNSeNAe.js → usePolling-Djmt90eb.js} +1 -1
  126. package/web-app/dist/assets/{user-3Zez1WOK.js → user-BRBohA6J.js} +1 -1
  127. package/web-app/dist/index.html +1 -1
  128. package/docs/ARCHITECTURE-OVERVIEW.md +0 -209
  129. package/docs/AUTONOMI-ECOSYSTEM.md +0 -107
  130. package/docs/COCKPIT-SPEC.md +0 -72
  131. package/docs/COCKPIT-UX-MANDATE.md +0 -53
  132. package/docs/COMPETITIVE-ANALYSIS.md +0 -303
  133. package/docs/COMPETITIVE-NEXT-10.md +0 -316
  134. package/docs/COMPETITIVE-RALPH-ZEROSHOT-2026-07-08.md +0 -81
  135. package/docs/DASHBOARD-9.12-EVIDENCE.md +0 -97
  136. package/docs/DASHBOARD-ARCHITECTURE.md +0 -425
  137. package/docs/DASHBOARD_V2_CHECKLIST.md +0 -243
  138. package/docs/DEMOS.md +0 -63
  139. package/docs/ENTERPRISE-IDENTITY-ROADMAP.md +0 -206
  140. package/docs/EVIDENCE-RECEIPT-BUILD-APPLICABILITY.md +0 -79
  141. package/docs/FEAT-PRDREUSE-DOCKER-PLAN.md +0 -144
  142. package/docs/GATE-FAILURE-TRIAGE.md +0 -254
  143. package/docs/HANDOFF-2026-08-03.md +0 -439
  144. package/docs/LOOP-CANDIDATE-PROPOSAL-v1.md +0 -167
  145. package/docs/LOOP-HARNESS-AUDIT.md +0 -684
  146. package/docs/MERGE-DEDUP-MAP.md +0 -420
  147. package/docs/MERGE-ROUTE-MAP.md +0 -139
  148. package/docs/MODEL-REGISTRY-PLAN.md +0 -155
  149. package/docs/OUTCOME-FRONTIER.md +0 -536
  150. package/docs/P2-SPEC-ROBUSTNESS-PLAN.md +0 -192
  151. package/docs/PLANS-INDEX.md +0 -32
  152. package/docs/PRD-REUSE-DONE-RECOGNITION-PLAN.md +0 -536
  153. package/docs/PROMPT-ABLATION-RESULT.md +0 -97
  154. package/docs/R4-TRUST-TRAJECTORY-DESIGN.md +0 -127
  155. package/docs/R5-AUTO-WIKI-DESIGN.md +0 -137
  156. package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +0 -107
  157. package/docs/R7-ZERO-CONFIG-FIRST-RUN-PLAN.md +0 -137
  158. package/docs/R8-SHAREABLE-TEAM-ASSETS-PLAN.md +0 -129
  159. package/docs/R9-OPEN-CORE-HOOKS-PLAN.md +0 -113
  160. package/docs/RARV-C-100X-PLAN.md +0 -286
  161. package/docs/RARV-C-LOOP-EFFICIENCY-PLAN.md +0 -470
  162. package/docs/SHAREABLE-PROOF-PLAN.md +0 -194
  163. package/docs/SONNET5-DEFAULT-PLAN.md +0 -157
  164. package/docs/SPEED-AND-FIRST-PASS-PLAN.md +0 -281
  165. package/docs/STALE-STATE-AUDIT.md +0 -174
  166. package/docs/SYNERGY-TASKS.md +0 -143
  167. package/docs/TASKLIST-ACCURACY-PLAN.md +0 -355
  168. package/docs/TOP-100-BACKLOG.md +0 -159
  169. package/docs/V8-ACCEPTANCE-TRIAGE-2026-07-24.md +0 -114
  170. package/docs/V8-COMPLEXITY-AUDIT-2026-07-24.md +0 -45
  171. package/docs/V8-MAJOR-RELEASE-PLAN.md +0 -137
  172. package/docs/V8-OVERNIGHT-PLAN-2026-07-25.md +0 -82
  173. package/docs/V8-SDK-RESEARCH-RAW.md +0 -129
  174. package/docs/WELCOME-OPENER-PLAN.md +0 -106
  175. package/docs/adoption-baseline-2026-07-31.md +0 -84
  176. package/docs/architecture/bmad-integration-epic.md +0 -271
  177. package/docs/architecture/bmad-integration-review.md +0 -86
  178. package/docs/architecture/bmad-integration-validation.md +0 -249
  179. package/docs/architecture/bmad-loki-voice-agent-council-analysis.md +0 -61
  180. package/docs/auto-claude-comparison.md +0 -250
  181. package/docs/bug-fixes/agent-01-cli-fixes.md +0 -101
  182. package/docs/bug-fixes/agent-02-purplelab-fixes.md +0 -88
  183. package/docs/bug-fixes/agent-03-dashboard-fixes.md +0 -119
  184. package/docs/bug-fixes/agent-04-memory-fixes.md +0 -105
  185. package/docs/bug-fixes/agent-05-provider-fixes.md +0 -86
  186. package/docs/bug-fixes/agent-06-integration-fixes.md +0 -101
  187. package/docs/bug-fixes/agent-07-dash-run-fixes.md +0 -101
  188. package/docs/bug-fixes/agent-08-docker-fixes.md +0 -164
  189. package/docs/bug-fixes/agent-09-e2e-build-fixes.md +0 -69
  190. package/docs/bug-fixes/agent-10-e2e-fullstack-fixes.md +0 -102
  191. package/docs/bug-fixes/agent-11-e2e-session-fixes.md +0 -70
  192. package/docs/bug-fixes/agent-12-scenario-fixes.md +0 -120
  193. package/docs/bug-fixes/agent-13-enterprise-fixes.md +0 -143
  194. package/docs/bug-fixes/agent-14-uat-newuser-fixes.md +0 -88
  195. package/docs/bug-fixes/agent-15-uat-poweruser-fixes.md +0 -132
  196. package/docs/bug-fixes/agent-19-code-review.md +0 -316
  197. package/docs/bug-fixes/agent-20-architecture-review.md +0 -331
  198. package/docs/competitive/bolt-new-analysis.md +0 -579
  199. package/docs/competitive/emergence-others-analysis.md +0 -605
  200. package/docs/competitive/replit-lovable-analysis.md +0 -622
  201. package/docs/dashboard-guide.md +0 -487
  202. package/docs/enterprise/migration.md +0 -265
  203. package/docs/history/one-run-audit.md +0 -304
  204. package/docs/plans/FORGE-AUTONOMOUS-QUEUE.md +0 -312
  205. package/docs/plans/ULTRAPLAN-FORGE-BAAS.md +0 -612
  206. package/docs/plans/UT2-6-LSP-DIAGNOSTIC-BROADCAST.md +0 -394
  207. package/docs/prd-purple-lab-ide.md +0 -152
  208. package/docs/prd-purple-lab-platform-v2.md +0 -223
  209. package/docs/prd-purple-lab-platform.md +0 -319
  210. package/docs/retrospectives/v7.5.15-fleet-postmortem.md +0 -325
  211. package/docs/retrospectives/v7.5.15-honesty-audit.md +0 -136
  212. package/docs/retrospectives/v7.5.15-llm-failure-modes.md +0 -49
  213. package/docs/show-hn-post.md +0 -46
  214. package/docs/test-scenarios/enterprise-scenarios.md +0 -732
  215. package/docs/thick2thin.md +0 -173
@@ -1,536 +0,0 @@
1
- # PRD-Reuse Done-Recognition Gate -- Implementation Plan
2
-
3
- Architect design. DESIGN ONLY: no production code in this doc, one file created
4
- (this plan). Read-only against the engine. No emojis. No em dashes.
5
-
6
- Repo: /Users/lokesh/git/loki-mode
7
- Feature: when a no-PRD run reuses a previously generated PRD, model-verify
8
- whether the codebase already satisfies that PRD before rebuilding a task queue
9
- and re-running the RARV loop. If verified done, finish through the normal
10
- completion path and tell the user clearly. If not, build only the unsatisfied
11
- requirements. If inconclusive, build (safe default). Never fake-green.
12
-
13
- ---
14
-
15
- ## 1. The bug, restated as a control-flow gap
16
-
17
- On a no-PRD run over a project Loki already built and completed, the auto-detect
18
- block in `run_autonomous()` (autonomy/run.sh:15140-15217) calls
19
- `decide_generated_prd_action()` (autonomy/run.sh:5590). When the codebase
20
- signature matches the stored one it returns `reuse`, and the block does exactly:
21
-
22
- reuse) ... prd_path="$_gen_prd" ;;
23
-
24
- Control then falls straight through to `populate_prd_queue "$prd_path"`
25
- (autonomy/run.sh:15439), which extracts all `prd-*` features from the PRD
26
- (autonomy/run.sh:14580, dedup only by `existing_ids` at 14878), and into the
27
- main RARV loop. Nothing on the `reuse` path ever asks "is this reused PRD
28
- already satisfied by the current codebase?" So a genuinely-done project gets a
29
- fresh 11-task queue plus new iteration-N work, re-running RARV over completed
30
- work. The prior run had already written `.loki/signals/COMPLETION_REQUESTED`,
31
- `.loki/state/completion.json`, and `completion-evidence.md`; the reuse path
32
- ignores all of it.
33
-
34
- The fix is a single localized gate between the action decision and the
35
- queue/loop, that re-verifies ground truth with the model and routes to one of
36
- three outcomes.
37
-
38
- ---
39
-
40
- ## 2. Integration point (exact function + line region)
41
-
42
- Two-part, both inside `run_autonomous()`:
43
-
44
- ### 2a. Set up the gate inputs in the existing decision block (15140-15217)
45
- No structural change. The block already computes `GENERATED_PRD_ACTION`,
46
- `_gen_prd`, and `_prd_date`. We add nothing here except (optionally) reading the
47
- gate's outcome variable later. Leave 15140-15217 byte-stable for the static
48
- prompt prefix; the action variable continues to be set once per run.
49
-
50
- ### 2b. Add the gate as a self-contained function called AFTER load_state,
51
- AFTER the restarted-run snapshot, and BEFORE the delegate-branch/start-sha block
52
- and queue build.
53
-
54
- Verified line ordering inside `run_autonomous()`:
55
- - 15238 `load_state` (15239 already reads `ITERATION_COUNT` right after).
56
- - ~15248 start-sha capture (`_start_sha_file`, `mkdir .loki/state`).
57
- - 15259 delegate-branch block (`LOKI_DELEGATE_BRANCH`, spawns `loki/delegate-*`).
58
- - 15313-15319 restarted-run snapshot + export.
59
- - 15328-15331 `LOKI_TRUST_RUN_ID` minted (`record_trust_event_bash run_start`).
60
- - 15439 `populate_prd_queue`.
61
-
62
- Required call site: BETWEEN `load_state` (15238) and the start-sha / delegate
63
- block (~15248-15259). At that window `ITERATION_COUNT` is live (15239 reads it,
64
- so the gate's fresh-vs-resume disclosure works) AND neither the start-sha capture
65
- nor the delegate branch has run yet, so a verified-done project never spawns a
66
- stray `loki/delegate-*` branch or moves the diff window. Placing the gate at
67
- 15319 (after the delegate block) would defeat that, which is why the call site is
68
- the pre-15248 window, not the restarted-snapshot line.
69
-
70
- One ordering tradeoff to fold in at edit time: `LOKI_TRUST_RUN_ID` is minted at
71
- 15328-15331, AFTER this window. If the done path records a trust event, either
72
- mint the run id inside the gate or hoist 15328-15331 above the gate. Prefer
73
- hoisting the mint (15328-15331) to just after `load_state` so both the gate and
74
- the existing call site see a stable id; verify no other consumer depends on its
75
- current position before moving it.
76
-
77
- Why not 15218 with a bare `exit 0`: 15218 is before `load_state`, so
78
- `ITERATION_COUNT` is not yet restored, and a bare `exit` skips main's terminal
79
- finalization (section 6.1). The gate must instead return through `run_autonomous`
80
- so `main()` runs its terminal block.
81
-
82
- - Before `populate_prd_queue` (15439): a done verdict must short-circuit the
83
- ENTIRE queue-build + loop, and an incomplete verdict must hand the queue
84
- builder its "only-unsatisfied" filter before it runs.
85
-
86
- New function name: `reuse_done_recognition_gate` (call once, run-scoped).
87
- The function returns control by either (a) running the council-parity
88
- finalization subset and `return 0` from `run_autonomous`, so `main()`'s terminal
89
- block (18595-18629) finishes the run (done -- see section 6.1), or (b) writing a
90
- satisfied-requirements manifest and falling through (incomplete), or (c) doing
91
- nothing and falling through (inconclusive / fast-path build).
92
-
93
- ---
94
-
95
- ## 3. Which GENERATED_PRD_ACTION values arm the gate
96
-
97
- The gate runs only on a no-PRD run that is reusing an existing generated PRD:
98
-
99
- - `reuse` -> ARM the gate. Canonical bug case (codebase unchanged).
100
- - `user_owned` -> ARM the gate. Codebase unchanged, PRD hand-edited; same
101
- "already built" situation. The model verifies against the
102
- hand-edited requirements.
103
- - `update` -> ARM the gate, but FAST-STOP DISABLED. Codebase changed
104
- since the PRD, so the PRD is stale by definition (that is why
105
- the action is `update`). Judging "already done?" against a
106
- spec that is about to be rewritten is a false-stop risk, so on
107
- the `update` path the gate may resolve ONLY to incomplete or
108
- inconclusive -- never to a fast-stop `done`. Its value here is
109
- exclusively the incremental-queue case: mark which still-valid
110
- requirements are met so the rebuild touches only the gap. A
111
- model `done` on the `update` path is treated as inconclusive
112
- (fall through to build / normal update flow).
113
- - `generate` -> DO NOT arm. First run / forced regen (LOKI_PRD_REGEN). There
114
- is no prior PRD to be "already satisfied"; maps to the
115
- negative fast-path (build).
116
-
117
- Guard condition at the call site:
118
-
119
- case "${GENERATED_PRD_ACTION:-}" in
120
- reuse|user_owned|update) reuse_done_recognition_gate "$prd_path" ;;
121
- esac
122
-
123
- Only `reuse` and `user_owned` (codebase unchanged) may terminate as a
124
- fast-stop `done`. `update` may resolve only to incomplete/inconclusive. For
125
- `reuse`/`user_owned`, "incomplete" is still possible (user deleted code, a
126
- requirement regressed). The model decides the verdict; the action selects whether
127
- to arm AND whether a `done` verdict is allowed to fast-stop.
128
-
129
- ---
130
-
131
- ## 4. Fast-path hints (cheap, EXCLUSIVELY negative)
132
-
133
- Before any model call, evaluate cheap deterministic signals. CRITICAL CONSTRAINT
134
- (requirements 1 and 3): the fast path may only ever short-circuit toward BUILD
135
- (skip the model, fall through to queue). There is NO deterministic
136
- "checklist all-verified -> stop" shortcut. A positive done verdict is ALWAYS the
137
- model's, grounded in re-verified reality. The very bug shows the deterministic
138
- checklist artifact was stale/desynced (14-vs-19 discrepancy), so it can never be
139
- trusted as a positive done signal.
140
-
141
- Negative fast-path: skip the model and fall through to BUILD when ground-truth
142
- "surely not done" signals hold, e.g.:
143
- - No `.loki/signals/COMPLETION_REQUESTED` AND no `.loki/state/completion.json`
144
- AND no `.loki/checklist/checklist.json`: the project was never completed by a
145
- prior run; there is nothing plausibly done. Build. (Cheapest, most common
146
- miss-avoidance: never pay for a model call on a project with zero completion
147
- footprint.)
148
- - Provider unavailable / degraded (`_loki_done_recog_provider_ok` mirrors
149
- `_loki_prd_enrich_provider_ok`, autonomy/lib/prd-enrich.sh:65): cannot
150
- model-verify -> inconclusive -> build (never assert done offline).
151
- - Explicit opt-out (LOKI_REUSE_DONE_RECOG=0): build.
152
-
153
- These are hints/inputs only. Their PRESENCE (a completion signal exists) does NOT
154
- short-circuit to done; it merely makes the model call worthwhile. The model still
155
- re-runs tests and re-checks each requirement.
156
-
157
- ---
158
-
159
- ## 5. Model-intelligence verification design
160
-
161
- Mirror the proven, mockable single-call pattern of prd-enrich
162
- (autonomy/lib/prd-enrich.sh). New library: `autonomy/lib/done-recognition.sh`,
163
- sourced at the gate call site the same way prd-enrich.sh is sourced at
164
- autonomy/run.sh:14931-14937.
165
-
166
- ### 5.1 The single model-call primitive (the ONE provider touch, mockable)
167
-
168
- _loki_done_recog_invoke <prompt> # echoes the raw model response
169
-
170
- Implementation copies `_loki_prd_enrich_invoke` (autonomy/lib/prd-enrich.sh:43)
171
- verbatim in shape: `command -v claude`, `timeout "${LOKI_DONE_RECOG_TIMEOUT}"`,
172
- `claude --dangerously-skip-permissions -p "$prompt"`, return 1 on any
173
- nonzero/empty. Tests stub THIS function to return canned JSON, exactly as
174
- prd-enrich tests stub `_loki_prd_enrich_invoke`. This is the injection seam that
175
- makes a bash+model gate deterministically testable.
176
-
177
- Bounds (mirror prd-enrich):
178
- : "${LOKI_DONE_RECOG_TIMEOUT:=180}"
179
- : "${LOKI_DONE_RECOG_MAX_PRD_CHARS:=16000}"
180
- : "${LOKI_DONE_RECOG_MAX_TEST_CHARS:=4000}"
181
-
182
- ### 5.2 Ground-truth re-verification BEFORE the model call
183
-
184
- The model must judge against re-run reality, not artifacts alone. Before
185
- building the prompt, the gate captures fresh ground truth:
186
-
187
- 1. Tests: reuse `ensure_completion_test_evidence` (autonomy/run.sh:9094) which
188
- calls `enforce_test_coverage` (autonomy/run.sh:8595) and persists
189
- `.loki/quality/test-results.json`. This is the SAME evidence axis the
190
- completion council/evidence gate reads, so the gate cannot reach a verdict
191
- that contradicts the council. `enforce_test_coverage` is CWD-safe (it anchors
192
- every path on `${TARGET_DIR:-.}` internally, confirmed at 8595-8607), so it
193
- is safe at this pre-loop site. Swallow rc with `|| true` (red tests are data,
194
- not a crash). If no runner exists, the file records `runner:none` and the
195
- test axis is honestly inconclusive (feeds "inconclusive -> build" unless the
196
- model can establish done by code inspection alone, which it should treat
197
- conservatively).
198
-
199
- 2. Requirements list: derive from the reused PRD (`$prd_path`, i.e.
200
- `.loki/generated-prd.md`). Cap to LOKI_DONE_RECOG_MAX_PRD_CHARS.
201
-
202
- 3. Existing completion evidence (as INPUT/hint only): the prior
203
- `completion-evidence.md`, `.loki/state/completion.json`, and
204
- `.loki/checklist/checklist.json` are passed to the model as context labeled
205
- "PRIOR CLAIMS, possibly stale -- verify against the code, do not trust."
206
-
207
- ### 5.3 The prompt and the structured return
208
-
209
- The prompt instructs the model to: read the PRD requirements; for EACH
210
- requirement, inspect the actual code (and the fresh test-results.json) and
211
- decide whether it is met NOW; treat all prior Loki artifacts as unverified
212
- claims; and return ONLY a JSON object (no prose, no fences), defensively parsed
213
- (slice first `{` to last `}`, mirroring prd-enrich's array slice at
214
- prd-enrich.sh:326):
215
-
216
- {
217
- "verdict": "done" | "incomplete" | "inconclusive",
218
- "summary": "<one sentence for the user>",
219
- "tests": { "passed": <int>, "total": <int>, "green": true|false },
220
- "requirements": [
221
- { "id": "<stable id or title slug>",
222
- "title": "<requirement>",
223
- "status": "met" | "unmet" | "uncertain",
224
- "evidence": "<file:line or test name proving it>" }
225
- ]
226
- }
227
-
228
- Verdict rules enforced in the prompt AND re-derived defensively in bash/python
229
- (never trust the model's top-line verdict blindly):
230
- - `done` requires ALL requirements `met` AND tests green in the fresh
231
- test-results.json (or `runner:none` with the model citing concrete code
232
- evidence for every requirement). If the model says `done` but the fresh
233
- test-results.json shows red or any requirement is `unmet`/`uncertain`, the gate
234
- DOWNGRADES to `incomplete` (or `inconclusive`). The trust decision is grounded
235
- in re-verified reality, so a model overclaim cannot fake-green.
236
- - `incomplete` when one or more requirements are `unmet` (with at least one
237
- `met`, or none).
238
- - `inconclusive` when the model could not establish ground truth (parse failure,
239
- empty response, all `uncertain`, provider error). Falls to build.
240
-
241
- This satisfies requirement 1 (model judgment, not a hardcoded checklist rule),
242
- requirement 3 (trust moat: done is model-verified against re-run tests + code,
243
- never asserted from a stale artifact; inconclusive -> build), and keeps the
244
- verdict consistent with the council's evidence axis.
245
-
246
- ---
247
-
248
- ## 6. Outcome routing
249
-
250
- ### 6.1 done -> finish through the normal completion path (NOT a bare exit)
251
-
252
- A bare `exit 0` would skip finalization and risk leaving status/dashboard in a
253
- "running" state with no fresh trust evidence. Instead, REFRESH the verified
254
- completion record and exit through the same machinery a normal finish uses.
255
-
256
- Verified exit path. The gate runs INSIDE `run_autonomous()` (the pre-loop
257
- window in section 2b). `main()` calls `run_autonomous "$PRD_PATH"` at
258
- autonomy/run.sh:18515 (`|| result=$?`) and then UNCONDITIONALLY runs its terminal
259
- finalization at 18595-18629 -- `_advance_current_phase "COMPLETED"`, the COMPLETED
260
- marker (18604-18606), proof-of-run (18597-18598), and HANDOFF.md (18614-18629).
261
- That terminal block lives in `main()`, NOT in `run_autonomous()`. So when the
262
- gate `return`s from `run_autonomous` (with or without entering the loop), control
263
- returns to `main()` at 18515 and the terminal finalization runs exactly once.
264
- This is the mechanism that makes step 3's receipt promise real -- a pre-loop
265
- `return` reaches the terminal because the terminal is in the caller, not in the
266
- loop body.
267
-
268
- Concretely, on `done` the gate:
269
- 1. Writes a fresh verified-completion record reflecting the NOW re-run results.
270
- The fresh `.loki/quality/test-results.json` is already on disk. Reuse the
271
- standalone completion-summary writer `build_completion_summary`
272
- (autonomy/run.sh:3026), which emits both `.loki/state/completion.json`
273
- (3196-3210) and `completion-evidence.md` -- the SAME writer the council
274
- approval path uses (called from completion-council.sh:3211). Confirm it is
275
- callable standalone from the pre-loop site (it reads git/state, not loop
276
- locals); if it requires loop-set vars, pass them explicitly or factor the
277
- write. The per-requirement `requirements[]` array is recorded as the evidence
278
- body, so the record is reconciled-and-refreshed, not a parallel fabricated one.
279
- 2. Runs the same finalization subset the council approval path runs (mirroring
280
- autonomy/run.sh:17688-17704), then RETURNS from `run_autonomous` so `main()`'s
281
- terminal block (18595-18629) does the COMPLETED marker, phase-advance, proof,
282
- and handoff. To avoid double-writing the COMPLETED marker / phase, the gate
283
- should do the council-parity pieces that the main terminal does NOT
284
- (`council_write_report`, `run_memory_consolidation`, `on_run_complete`,
285
- `emit_completion_summary complete`, `save_state ... reuse_already_satisfied`)
286
- and let main own `_advance_current_phase "COMPLETED"` + the COMPLETED marker
287
- (18604-18606). Verify at edit time which subset main already covers so neither
288
- is run twice:
289
- type council_write_report &>/dev/null && council_write_report
290
- run_memory_consolidation
291
- on_run_complete # autonomy/run.sh:3516 (optional PR/summary/ping)
292
- emit_completion_summary complete # autonomy/run.sh:3367
293
- save_state ${RETRY_COUNT:-0} "reuse_already_satisfied" 0
294
- return 0 # back to main() -> terminal finalization at 18595-18629
295
- Do NOT `exit`. Do NOT enter the loop. A `return 0` (clean) is correct here; a
296
- `return 2` is unnecessary because there is no loop to stop -- the pre-loop
297
- return already skips queue-build and iteration.
298
-
299
- Alternative (if `build_completion_summary` proves loop-coupled): have the gate
300
- only write the COMPLETED marker + refreshed completion.json + advance phase,
301
- then `return 0`; main's `is_completed()` check (17205) is INSIDE the loop and
302
- so is irrelevant on the pre-loop return -- the loop never runs. Either way the
303
- single guaranteed terminal is main's 18595-18629. Pick the
304
- `build_completion_summary`-reuse route if it is standalone-safe (preferred:
305
- one writer, no divergence); fall back to the marker-only route otherwise.
306
- 3. The proof-of-run + HANDOFF.md generation (autonomy/run.sh:18597-18629) runs in
307
- main's terminal block after `run_autonomous` returns, so the user gets a
308
- receipt with the honest re-run headline.
309
-
310
- This is the "interacts with completion machinery without contradicting it"
311
- requirement: we reconcile WITH the prior evidence, refreshed against re-run
312
- reality, and exit through the one true completion path. No double-gating: the
313
- council never runs because the loop never starts; the gate produced the same
314
- kind of evidence the council would have read.
315
-
316
- ### 6.2 incomplete -> incremental queue (only unsatisfied requirements)
317
-
318
- `populate_prd_queue` (14580) builds ALL features; its only filter is the
319
- `existing_ids` dedup at 14878. To make it incremental we add ONE read-point:
320
-
321
- - The gate writes a satisfied-requirements manifest:
322
- `.loki/state/satisfied-requirements.json`:
323
-
324
- {
325
- "prd_sha": "<hash of the PRD the verdict was computed against>",
326
- "generated_at": "<iso8601>",
327
- "satisfied": ["prd-001 title or stable id", "..."],
328
- "source": "reuse-done-recognition"
329
- }
330
-
331
- Identity is by the same requirement key the queue builder uses to mint task
332
- ids (`prd-NNN` is positional at 14877; to be robust, key on the feature TITLE
333
- and let the manifest store titles, matched case-insensitively in the builder).
334
-
335
- - `populate_prd_queue` reads the manifest once (guarded: only when it exists AND
336
- its `prd_sha` matches the current PRD hash, so a stale manifest is ignored) and
337
- SKIPS any feature whose title is in `satisfied[]`, alongside the existing
338
- `existing_ids` skip at 14878:
339
-
340
- if task_title_satisfied(feat["title"]): # new, manifest-driven
341
- continue
342
-
343
- Result: only unmet requirements become `prd-*` tasks; the RARV loop works only
344
- the remaining gap, not a from-scratch rebuild. If the manifest is absent or
345
- stale, the builder behaves exactly as today (full build) -- safe default.
346
-
347
- - Disclosure: the gate logs "N of M requirements already satisfied; building
348
- only the K unmet (<titles>). Pass --fresh-prd to rebuild from scratch."
349
-
350
- Then the gate falls through (no exit); the run proceeds into queue-build and the
351
- loop normally, now scoped to the gap.
352
-
353
- ### 6.3 inconclusive -> build (safe default, never falsely done)
354
-
355
- Do nothing: write no manifest, no completion. Log "Could not verify whether the
356
- project already satisfies its spec (<reason>); proceeding to build." Control
357
- falls through to the normal full queue-build + loop. This is the prd-enrich
358
- graceful-fallback contract (provider missing / timeout / unparsable ->
359
- deterministic fall-through), applied to the done decision. NEVER declare done on
360
- inconclusive.
361
-
362
- ---
363
-
364
- ## 7. User-facing messaging (enterprise UX, requirement 2)
365
-
366
- - done:
367
- "This project already satisfies its spec. Verified N/N requirements met and
368
- tests green (re-ran the suite now). Nothing to build. To rebuild from scratch
369
- run `loki start --fresh-prd`; to extend it, edit the spec or pass a new/changed
370
- PRD." (emitted via log + emit_completion_summary complete.)
371
- Risk-mitigating clarity: a user who genuinely WANTS to extend a done project
372
- must immediately see the two escape hatches (--fresh-prd, new/changed spec).
373
- Make that the last line of the done message so it is unmissable.
374
-
375
- - incomplete:
376
- "This project partially satisfies its spec: K of M requirements still need
377
- work (<short list>). Building only those. (Pass --fresh-prd to rebuild
378
- everything.)"
379
-
380
- - inconclusive:
381
- "Could not confirm whether the existing code already satisfies the reused spec
382
- (<reason: provider unavailable / tests inconclusive / unparsable verdict>).
383
- Proceeding to build to be safe."
384
-
385
- All strings: plain text, no emojis, no em dashes (repo convention).
386
-
387
- ---
388
-
389
- ## 8. Interaction with existing council / completion machinery (no double-gate)
390
-
391
- - On `done`: the loop never starts, so council_should_stop / council_vote /
392
- council_evidence_gate never run. The gate produces the SAME evidence those
393
- gates read (fresh test-results.json + completion.json), so there is no
394
- contradictory or parallel notion of "done." The completion finalization
395
- subset it runs is the SAME one the council approval path runs
396
- (run.sh:17688-17704), so dashboards/markers/memory stay consistent.
397
- - On `incomplete`/`inconclusive`: the gate adds no completion state; the normal
398
- loop, council, and evidence gate are fully in force for the (possibly reduced)
399
- remaining work. No behavior change to those paths.
400
- - The fast-path uses the council's artifacts (COMPLETION_REQUESTED,
401
- completion.json, checklist.json) only as NEGATIVE inputs (their absence ->
402
- build), never as a positive done shortcut, so it cannot inherit the stale-
403
- artifact bug.
404
-
405
- ---
406
-
407
- ## 9. Test strategy (deterministic bash + mocked model)
408
-
409
- New test: `tests/test-reuse-done-recognition.sh`, style mirroring the prd-enrich
410
- and stop-scoping tests (bash, set -u, ok/bad counters, mktemp -d under /tmp with
411
- trap-rm on every exit, no network, no real agent). The model call is injected by
412
- overriding `_loki_done_recog_invoke` to echo canned JSON, exactly as prd-enrich
413
- tests override `_loki_prd_enrich_invoke`.
414
-
415
- Cases:
416
- - T1 done verdict + green test-results.json -> gate routes to completion:
417
- assert `.loki/COMPLETED` written, `.loki/state/completion.json` refreshed,
418
- NO `.loki/queue/pending.json` prd-* tasks built, normal-terminal return.
419
- - T2 model says done but fresh test-results.json is RED -> DOWNGRADE: assert NOT
420
- done (incomplete/inconclusive), no COMPLETED marker (no fake-green).
421
- - T3 model says done but a requirement is `unmet` -> downgrade to incomplete;
422
- assert satisfied-requirements manifest excludes the unmet one.
423
- - T4 incomplete -> manifest written with the met titles; stub populate read-point
424
- test asserts only unmet features become tasks (feed a 3-feature PRD, mark 2
425
- satisfied, assert 1 task).
426
- - T5 inconclusive (invoke returns nonzero / empty / unparsable) -> no manifest,
427
- no completion, falls through to full build.
428
- - T6 negative fast-path: no COMPLETION_REQUESTED + no completion.json + no
429
- checklist -> model NOT called (assert the stub recorded zero calls), full
430
- build.
431
- - T7 provider not ok (stub `_loki_done_recog_provider_ok` false) -> inconclusive
432
- fast-path, build, model NOT called.
433
- - T8 action gating: GENERATED_PRD_ACTION=generate -> gate not armed (no model
434
- call); reuse/user_owned/update -> armed.
435
- - T9 manifest staleness: prd_sha mismatch -> populate_prd_queue ignores manifest
436
- and does a full build (safe default).
437
- - T10 no-emoji/no-em-dash static grep over the new lib and the new strings.
438
-
439
- Register in scripts/local-ci.sh (mirror the prd-enrich registration):
440
- run_check "tests/test-reuse-done-recognition.sh (reuse done-recognition gate)" \
441
- "bash tests/test-reuse-done-recognition.sh 2>&1 | tail -3"
442
-
443
- Sourceability: the gate logic lives in `autonomy/lib/done-recognition.sh` (like
444
- prd-enrich.sh), which is independently sourceable in the test without sourcing
445
- run.sh. The `populate_prd_queue` read-point change is tested by exercising
446
- populate_prd_queue in a temp project (it is already invoked in integration-style
447
- tests) or by awk-extracting the python heredoc filter, defaulting to the
448
- sourceable-lib approach for the gate proper.
449
-
450
- ---
451
-
452
- ## 10. Rollout
453
-
454
- - Phase 1 (one release): env-gated DEFAULT-ON with a documented opt-out, so the
455
- intelligent default ships immediately (requirement 5: unified default, not a
456
- new knob) but operators retain an escape hatch:
457
- LOKI_REUSE_DONE_RECOG=1 # default (on)
458
- LOKI_REUSE_DONE_RECOG=0 # opt out (legacy reuse-then-build behavior)
459
- No new user-facing CLI flag is added; --fresh-prd / LOKI_PRD_REGEN already
460
- exist as the rebuild escape hatch and are surfaced in every gate message.
461
- - Because the safe default on any uncertainty is BUILD (the legacy behavior), the
462
- blast radius of a wrong gate is bounded: worst case it behaves like today.
463
- - After one release of field evidence (proof-of-run + trust metrics show the gate
464
- is correctly recognizing done without false-done), drop the env gate to
465
- hard-on (keep `=0` opt-out for one more release, then remove).
466
-
467
- ---
468
-
469
- ## 11. Risks and mitigations
470
-
471
- - R1 (highest, requirement 2): a genuinely-done project the user WANTS to extend.
472
- Mitigation: the done message's final line names BOTH escape hatches
473
- (`--fresh-prd` to rebuild, edit/pass a new spec to extend). The gate only
474
- fires on a NO-PRD reuse run; the moment the user supplies a changed/new PRD,
475
- the user-PRD path (found_prd at 15159, or persist_user_prd) takes precedence
476
- and the gate's reuse arming does not apply.
477
- - R2 false-done (fake-green): mitigated by re-running tests NOW
478
- (ensure_completion_test_evidence) and DOWNGRADING any model `done` that the
479
- fresh test-results.json or an `unmet`/`uncertain` requirement contradicts. The
480
- positive verdict is never sourced from a stale artifact.
481
- - R3 false-incomplete (rebuilds something already done): bounded -- worst case is
482
- today's behavior (it rebuilds). The incremental manifest only ever REDUCES
483
- work; if the model is unsure it marks `uncertain` (not satisfied) and that
484
- requirement is rebuilt. No regression vs status quo.
485
- - R4 model cost on every reuse run: the negative fast-path skips the call
486
- entirely on projects with no completion footprint (the common case for a fresh
487
- reuse that is clearly not done is rare; the common reuse over a built project
488
- pays one bounded call). Timeout-bounded (LOKI_DONE_RECOG_TIMEOUT). On non-
489
- claude/degraded providers the call is skipped (inconclusive -> build).
490
- - R5 manifest/PRD identity drift: manifest is guarded by `prd_sha`; a mismatch is
491
- ignored and a full build runs. Keying on feature title (not positional
492
- prd-NNN) avoids index-shift misskips.
493
- - R6 finalization ordering: the gate runs after load_state and before the
494
- delegate-branch/start-sha block, so a done verdict never spawns a delegate
495
- branch or moves the diff window. Verify final line placement at edit time
496
- against the live ordering of 15238 (load_state), the delegate block (~15259),
497
- and 15439 (populate_prd_queue).
498
-
499
- ---
500
-
501
- ## 12. Files touched (for the eventual implementation, not this doc)
502
-
503
- - autonomy/lib/done-recognition.sh (NEW): `_loki_done_recog_invoke`,
504
- `_loki_done_recog_provider_ok`, `reuse_done_recognition_gate`, payload/parse
505
- python heredocs. Mirrors autonomy/lib/prd-enrich.sh.
506
- - autonomy/run.sh:
507
- - new call site after ~15319 (source the lib like 14931-14937; arm the gate per
508
- section 3 guard).
509
- - populate_prd_queue (14580): one manifest read-point + per-feature skip near
510
- 14878 (section 6.2).
511
- - reuse the existing finalization functions (3367, 3516, 1653, 13190, 17692)
512
- and completion-summary writer `build_completion_summary` (3026, which writes
513
- 3196-3210) on the done path -- no new completion code.
514
- - tests/test-reuse-done-recognition.sh (NEW).
515
- - scripts/local-ci.sh: register the new test.
516
- - CHANGELOG.md + version-bump locations: per the repo's standard bump list (see
517
- the prior reuse design's section 9 for the canonical 14-location list).
518
- - Docs: a short note in the no-PRD reuse documentation that a reuse run now
519
- verifies whether the project is already done and stops fast if so.
520
-
521
- ---
522
-
523
- ## 13. Divergences from the prior design (loki-plan/v7734-prd-reuse-design.md)
524
-
525
- That doc designed the reuse/update/generate DECISION and the codebase signature.
526
- It is now implemented (decide_generated_prd_action at run.sh:5590). This plan
527
- builds the next layer ON TOP of its `reuse` outcome:
528
- - The prior doc's `reuse` ends at "point prd_path at the generated PRD and run."
529
- This plan inserts the done-recognition gate between that and the queue/loop.
530
- - The prior doc relied on a deterministic signature to decide reuse-vs-update.
531
- This plan deliberately does NOT add any deterministic done-shortcut; the
532
- done/incomplete TRUST decision is the model's, grounded in re-run tests + code,
533
- precisely because the signature/checklist artifacts proved untrustworthy as a
534
- done signal (the 14-vs-19 checklist desync in the live bug). The signature
535
- still does its job (reuse-vs-update); the new gate adds the satisfied-or-not
536
- judgment the signature was never meant to make.
@@ -1,97 +0,0 @@
1
- # Prompt ablation: measured result
2
-
3
- Date: 2026-08-03. Instrument: `benchmarks/run-prompt-ablation.sh`,
4
- reporter `benchmarks/report-prompt-ablation.py`. Raw rows:
5
- `benchmarks/results/prompt-ablation.jsonl`.
6
-
7
- ## The question
8
-
9
- Anthropic deleted roughly 80% of Claude Code's system prompt for Opus 5, on
10
- the finding that instructions written to correct older models had become dead
11
- weight, and that the model measured slightly MORE capable without them.
12
-
13
- `LOKI_SIMPLE=1` strips the coaching half of our prompt: the RARV cycle, SDLC
14
- phases, memory habits. Per-iteration state (which gate failed, self-heal
15
- output, checklist status) is never touched, because that is information the
16
- model cannot derive from anywhere else.
17
-
18
- Prompt size fell 78% (about 1562 tokens per iteration), reproduced
19
- independently on both the bash and Bun routes. That is a TOKEN measurement.
20
- It says nothing about whether the stripped arm builds the same thing, faster
21
- or slower, more or less reliably. This is that measurement.
22
-
23
- ## Result
24
-
25
- ```
26
- trials recorded: full=3 simple=3
27
-
28
- metric full (default) simple (LOKI_SIMPLE=1)
29
- -----------------------------------------------------------
30
- wall clock 8.2 min [7.3-8.7] n=3 7.6 min [6.2-8.0] n=3
31
- iterations 1.0 [1.0-1.0] n=3 1.0 [1.0-1.0] n=3
32
-
33
- full reliability: 3/3 completed
34
- simple reliability: 3/3 completed
35
-
36
- VERDICT: NO DIFFERENCE DEMONSTRATED -- the arms' ranges overlap
37
- (full 7.3-8.7, simple 6.2-8.0), so the median gap is within
38
- the run-to-run noise.
39
- ```
40
-
41
- ## What this means, stated carefully
42
-
43
- **Speed: no difference demonstrated.** The simple arm's median is 0.6 min
44
- lower, but the ranges overlap heavily. A gap smaller than the variance each
45
- arm shows against itself is not a finding.
46
-
47
- **Reliability: no difference demonstrated.** 3/3 completed in both arms, and
48
- every run passed its acceptance check. Both arms finished in a single
49
- iteration.
50
-
51
- **Cost: the token saving is real and stands on its own.** 78% less prompt per
52
- iteration is a deterministic, reproducible measurement that does not depend on
53
- these trials at all.
54
-
55
- **The honest summary: stripping the coaching prompt cost us nothing
56
- measurable, and saved 78% of the prompt.** That is a weaker claim than "the
57
- model is better without it" and a stronger one than "no effect" -- removing
58
- 1562 tokens of instruction per iteration did not degrade speed, completion, or
59
- acceptance across six real builds.
60
-
61
- ## Why this was nearly reported wrong
62
-
63
- After trial 1, the numbers were full 8.2 min against simple 6.2 min. That is a
64
- 24% improvement, and it is exactly the shape of result that gets written into
65
- a release note.
66
-
67
- Trial 2 reversed it: full 7.3, simple 8.0.
68
-
69
- One trial of a stochastic agent is indistinguishable from noise. The reporter
70
- refuses to declare a winner when the ranges overlap, and refuses entirely
71
- below n=3 per arm, which is why the instrument was built before the claim
72
- rather than after it.
73
-
74
- ## Limits, stated rather than left for a reader to discover
75
-
76
- - **n=3 per arm.** Enough to see that the arms overlap; not enough to detect a
77
- small real effect. A difference under roughly 20% would not be visible here.
78
- - **One spec, one model.** A single small build on sonnet. Coaching may matter
79
- more on a longer task, a weaker model, or a spec where the RARV structure is
80
- load-bearing. This says nothing about those.
81
- - **Both arms finished in one iteration**, so this never exercised the
82
- iterate-and-recover path where per-iteration state matters most. That is the
83
- case where stripping coaching is most likely to be safe and where the
84
- remaining prompt does the most work, and it is untested.
85
- - **Degraded providers are unaffected.** Codex and Aider take an earlier
86
- return path, so the flag never reaches its gate there. Measured as a 0-byte
87
- delta, not assumed.
88
-
89
- ## Reproduce
90
-
91
- ```bash
92
- benchmarks/run-prompt-ablation.sh --trials 3 --model sonnet --max-iters 6
93
- python3 benchmarks/report-prompt-ablation.py benchmarks/results/prompt-ablation.jsonl
94
- ```
95
-
96
- Both arms run in ONE engine copy; the only difference is the environment
97
- variable read at prompt-assembly time.