@tyroneross/build-loop 0.36.0 → 0.43.0

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 (270) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/.cursor/rules/build-loop-surface.mdc +12 -11
  6. package/.cursor/rules/skill-index.mdc +33 -0
  7. package/AGENTS.md +213 -34
  8. package/README.md +99 -31
  9. package/agents/advisor.md +4 -4
  10. package/agents/alignment-checker.md +2 -2
  11. package/agents/architecture-scout.md +4 -4
  12. package/agents/build-orchestrator.md +38 -36
  13. package/agents/database-assessor.md +11 -5
  14. package/agents/design-contract-specialist.md +8 -8
  15. package/agents/fact-checker.md +13 -3
  16. package/agents/fix-critique.md +2 -2
  17. package/agents/independent-auditor.md +60 -7
  18. package/agents/leak-scanner.md +82 -0
  19. package/agents/overfitting-reviewer.md +2 -2
  20. package/agents/plan-critic.md +1 -1
  21. package/agents/promotion-reviewer.md +5 -5
  22. package/agents/retrospective-synthesizer.md +138 -35
  23. package/agents/scope-auditor.md +82 -11
  24. package/agents/security-reviewer.md +56 -2
  25. package/agents/self-improvement-architect.md +17 -3
  26. package/agents/transcript-pattern-miner.md +5 -5
  27. package/agents/ui-validator.md +1 -1
  28. package/bin/build-loop-debugger.js +143 -0
  29. package/bin/build-loop-install.js +1 -4
  30. package/bin/build-loop-load-probe.js +345 -0
  31. package/codex-skills/build-loop/SKILL.md +28 -6
  32. package/commands/feedback.md +37 -0
  33. package/dist/src/interactive-verifier.d.ts +1 -14
  34. package/dist/src/interactive-verifier.d.ts.map +1 -1
  35. package/dist/src/interactive-verifier.js +6 -113
  36. package/dist/src/interactive-verifier.js.map +1 -1
  37. package/dist/src/quality.d.ts +5 -0
  38. package/dist/src/quality.d.ts.map +1 -0
  39. package/dist/src/quality.js +81 -0
  40. package/dist/src/quality.js.map +1 -0
  41. package/dist/src/storage.d.ts.map +1 -1
  42. package/dist/src/storage.js +37 -3
  43. package/dist/src/storage.js.map +1 -1
  44. package/docs/agent-surface-policy.md +35 -31
  45. package/docs/memory-setup.md +19 -0
  46. package/hooks/git/pre-push +65 -4
  47. package/hooks/hooks.json +95 -38
  48. package/hooks/pre-commit +20 -1
  49. package/hooks/pre-edit-rally-point.sh +10 -3
  50. package/hooks/session-start-codex-hook-trust.sh +30 -0
  51. package/hooks/session-start-git-hooks.sh +3 -1
  52. package/hooks/session-start-rally-point.sh +52 -4
  53. package/hooks/session-start-worktree-gc.sh +47 -94
  54. package/hooks/stop-transcript-sweep.sh +173 -0
  55. package/hooks/test_closeout.sh +14 -2
  56. package/package.json +8 -7
  57. package/scripts/README.md +1 -1
  58. package/scripts/_paths.py +65 -0
  59. package/scripts/groundwork_exchange.py +1012 -0
  60. package/scripts/install_memory.py +33 -1
  61. package/scripts/lessons_index/ingest.py +13 -2
  62. package/scripts/lessons_index/query.py +36 -13
  63. package/scripts/memory_context/__init__.py +108 -14
  64. package/scripts/memory_graph/__init__.py +5 -1
  65. package/scripts/project_resolver.py +42 -36
  66. package/scripts/sync_plugin_cache.py +37 -2
  67. package/skills/agent-rally-point/SKILL.md +46 -0
  68. package/skills/api-registry-bridge/SKILL.md +1 -1
  69. package/skills/architecture/dead/SKILL.md +1 -1
  70. package/skills/architecture/impact/SKILL.md +1 -1
  71. package/skills/architecture/review/SKILL.md +1 -1
  72. package/skills/architecture/rules/SKILL.md +3 -3
  73. package/skills/architecture/scan/SKILL.md +1 -1
  74. package/skills/architecture/trace/SKILL.md +1 -1
  75. package/skills/attribution-standard/SKILL.md +6 -6
  76. package/skills/auto-decision-capture/SKILL.md +31 -2
  77. package/skills/auto-finding-capture/SKILL.md +28 -1
  78. package/skills/build-loop/SKILL.md +131 -23
  79. package/skills/build-loop/fallbacks.md +16 -21
  80. package/skills/build-loop/phases/ui-validation.md +2 -2
  81. package/skills/build-loop/references/advisor-dispatch-ladder.md +1 -1
  82. package/skills/build-loop/references/apple-native-planning.md +1 -1
  83. package/skills/build-loop/references/autonomous-and-per-commit-modes.md +11 -5
  84. package/skills/build-loop/references/autonomy-dashboard.md +115 -0
  85. package/skills/build-loop/references/capability-routing.md +24 -2
  86. package/skills/build-loop/references/coordination.md +24 -6
  87. package/skills/build-loop/references/experiment-results-template.md +15 -3
  88. package/skills/build-loop/references/leadership.md +1 -1
  89. package/skills/build-loop/references/memory.md +14 -3
  90. package/skills/build-loop/references/modular-systems-pack.md +8 -0
  91. package/skills/build-loop/references/output-style.md +86 -0
  92. package/skills/build-loop/references/phase-1-assess.md +102 -2
  93. package/skills/build-loop/references/phase-2-plan.md +9 -1
  94. package/skills/build-loop/references/phase-3-execute.md +5 -2
  95. package/skills/build-loop/references/phase-4-review.md +85 -8
  96. package/skills/build-loop/references/phase-5-iterate.md +76 -8
  97. package/skills/build-loop/references/phase-6-learn.md +10 -17
  98. package/skills/build-loop/references/privileged-request-broker.md +254 -0
  99. package/skills/build-loop/references/resource-aware-execution.md +183 -0
  100. package/skills/build-loop/references/self-recursive-dev.md +2 -2
  101. package/skills/build-loop/references/status-output-format.md +207 -0
  102. package/skills/build-loop/references/verify-dispatch.md +56 -2
  103. package/skills/building-with-deepagents/SKILL.md +1 -1
  104. package/skills/claim-scope/SKILL.md +185 -0
  105. package/skills/color-engine/SKILL.md +103 -0
  106. package/skills/color-engine/_core.py +464 -0
  107. package/skills/color-engine/color_engine.py +175 -0
  108. package/skills/cost-rca/SKILL.md +61 -0
  109. package/skills/data-plane-worktrees/SKILL.md +139 -0
  110. package/skills/data-plane-worktrees/agents/openai.yaml +4 -0
  111. package/skills/database-practice/SKILL.md +200 -0
  112. package/skills/database-practice/references/diagnostic-queries.sql +126 -0
  113. package/skills/database-practice/references/vector-and-graph-tuning.md +208 -0
  114. package/skills/database-practice/scripts/db_table_map.py +1244 -0
  115. package/skills/database-practice/scripts/test_db_table_map.py +514 -0
  116. package/skills/debug-loop/SKILL.md +36 -6
  117. package/skills/debugging-memory/SKILL.md +32 -430
  118. package/skills/debugging-memory/references/pattern-extraction.md +4 -4
  119. package/skills/debugging-memory/references/search.md +32 -120
  120. package/skills/debugging-memory/references/store.md +32 -126
  121. package/skills/debugging-memory/references/subagent-integration.md +1 -1
  122. package/skills/decision-queue/SKILL.md +251 -0
  123. package/skills/decision-queue/assets/template.html +1242 -0
  124. package/skills/decision-queue/references/example-large-queue-batching.md +164 -0
  125. package/skills/decision-queue/scripts/regen_template_constants.py +160 -0
  126. package/skills/defenseclaw-bridge/SKILL.md +2 -2
  127. package/skills/defenseclaw-bridge/references/dc-config-mapping.md +2 -9
  128. package/skills/drain-proposals/SKILL.md +53 -0
  129. package/skills/focused-loop-builder/SKILL.md +31 -0
  130. package/skills/focused-loop-builder/references/spec-format.md +27 -0
  131. package/skills/handoff/SKILL.md +169 -8
  132. package/skills/ibr-bridge/SKILL.md +4 -1
  133. package/skills/knowledge/SKILL.md +26 -14
  134. package/skills/knowledge/references/review-mode.md +2 -3
  135. package/skills/knowledge/templates/madr-minimal.md +1 -1
  136. package/skills/mcp-builder/SKILL.md +1 -1
  137. package/skills/model-bakeoff/SKILL.md +48 -10
  138. package/skills/model-tiering/SKILL.md +92 -31
  139. package/skills/native-ax-driver/SKILL.md +38 -5
  140. package/skills/native-ax-driver/scripts/native_driver.py +278 -22
  141. package/skills/native-ax-driver/scripts/test_native_driver.py +227 -0
  142. package/skills/optimize/SKILL.md +1 -1
  143. package/skills/plugin-builder/SKILL.md +48 -1
  144. package/skills/plugin-builder/references/build-loop-phase-guidance.md +3 -4
  145. package/skills/plugin-builder/references/distribution.md +13 -2
  146. package/skills/plugin-builder/references/plugin-hygiene-lessons.md +2 -2
  147. package/skills/plugin-tests/SKILL.md +2 -2
  148. package/skills/recursive-retrospective/SKILL.md +1 -1
  149. package/skills/repo-closeout/SKILL.md +17 -0
  150. package/skills/repo-closeout/agents/openai.yaml +4 -0
  151. package/skills/repo-maintenance/SKILL.md +179 -0
  152. package/skills/repo-maintenance/agents/openai.yaml +4 -0
  153. package/skills/repo-maintenance/references/pre-public-hygiene.md +134 -0
  154. package/skills/repo-maintenance/references/repository-taxonomy.md +161 -0
  155. package/skills/repo-maintenance/references/safety-protocol.md +106 -0
  156. package/skills/repo-maintenance/references/stack-profiles.md +138 -0
  157. package/skills/repo-maintenance/scripts/audit_repo_maintenance.py +1198 -0
  158. package/skills/repo-maintenance/scripts/test_audit_repo_maintenance.py +506 -0
  159. package/skills/repository-intelligence/SKILL.md +189 -0
  160. package/skills/repository-intelligence/agents/openai.yaml +4 -0
  161. package/skills/repository-intelligence/references/assessment-rubric.md +88 -0
  162. package/skills/repository-intelligence/scripts/repository_inventory.py +347 -0
  163. package/skills/research/SKILL.md +12 -2
  164. package/skills/root-cause-analysis/SKILL.md +1 -1
  165. package/skills/runtime-parity-verification/SKILL.md +36 -1
  166. package/skills/security-methodology/SKILL.md +23 -10
  167. package/skills/security-methodology/references/agentic-handoff-templates.md +220 -0
  168. package/skills/security-methodology/references/cross-source-matrix.md +1 -1
  169. package/skills/security-methodology/references/owasp-agentic-top-10.md +1 -1
  170. package/skills/security-scan/SKILL.md +55 -15
  171. package/skills/self-improve/SKILL.md +70 -50
  172. package/skills/silent-assumptions/SKILL.md +341 -0
  173. package/skills/silent-assumptions/references/elicitation-detectors.md +342 -0
  174. package/skills/spec-writing/SKILL.md +128 -24
  175. package/skills/spec-writing/scripts/check_checklist.py +114 -15
  176. package/skills/ui-design/SKILL.md +6 -4
  177. package/skills/ui-design/references/color-engine.md +132 -0
  178. package/skills/ui-design/references/design-preferences-from-owned-apps.md +8 -8
  179. package/skills/ui-design/references/ui-guidance-sources.md +1 -1
  180. package/skills/ui-design/references/universal-design-principles.alt.md +2 -2
  181. package/plugin-artifacts/codex/.codex-plugin/plugin.json +0 -41
  182. package/plugin-artifacts/codex/AGENTS.md +0 -560
  183. package/plugin-artifacts/codex/BUILD-ARTIFACT.md +0 -5
  184. package/plugin-artifacts/codex/LICENSE +0 -202
  185. package/plugin-artifacts/codex/README.md +0 -313
  186. package/plugin-artifacts/codex/assets/build-loop-plugin-icon.png +0 -0
  187. package/plugin-artifacts/codex/docs/agent-surface-policy.md +0 -63
  188. package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +0 -62
  189. package/plugin-artifacts/codex/references/agent-role-taxonomy.md +0 -135
  190. package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +0 -161
  191. package/plugin-artifacts/codex/references/autonomy-config.md +0 -231
  192. package/plugin-artifacts/codex/references/backlog-system.md +0 -285
  193. package/plugin-artifacts/codex/references/capability-routing.md +0 -231
  194. package/plugin-artifacts/codex/references/codex-subagents.md +0 -106
  195. package/plugin-artifacts/codex/references/coordination-file-template.md +0 -181
  196. package/plugin-artifacts/codex/references/coordination-rules.md +0 -552
  197. package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +0 -112
  198. package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +0 -102
  199. package/plugin-artifacts/codex/references/implementer-envelope-schema.md +0 -302
  200. package/plugin-artifacts/codex/references/intent-capability-pack.md +0 -257
  201. package/plugin-artifacts/codex/references/intent-exploration-prompts.md +0 -96
  202. package/plugin-artifacts/codex/references/leadership.md +0 -72
  203. package/plugin-artifacts/codex/references/memory-systems.md +0 -261
  204. package/plugin-artifacts/codex/references/memory.md +0 -313
  205. package/plugin-artifacts/codex/references/model-tier-mapping.md +0 -296
  206. package/plugin-artifacts/codex/references/modular-systems-pack.md +0 -96
  207. package/plugin-artifacts/codex/references/phase-1-assess.md +0 -249
  208. package/plugin-artifacts/codex/references/phase-2-plan.md +0 -86
  209. package/plugin-artifacts/codex/references/phase-3-execute.md +0 -49
  210. package/plugin-artifacts/codex/references/phase-4-review.md +0 -341
  211. package/plugin-artifacts/codex/references/phase-5-iterate.md +0 -72
  212. package/plugin-artifacts/codex/references/phase-6-learn.md +0 -58
  213. package/plugin-artifacts/codex/references/recent-design-structures.md +0 -274
  214. package/plugin-artifacts/codex/references/research-trigger-policy.md +0 -140
  215. package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +0 -42
  216. package/plugin-artifacts/codex/references/self-review.md +0 -234
  217. package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +0 -90
  218. package/plugin-artifacts/codex/references/task-capture-policy.md +0 -68
  219. package/plugin-artifacts/codex/references/ui-io-contract.md +0 -116
  220. package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +0 -65
  221. package/plugin-artifacts/codex/references/verify-dispatch.md +0 -85
  222. package/plugin-artifacts/codex/skills/build-loop/SKILL.md +0 -381
  223. package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +0 -82
  224. package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +0 -65
  225. package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +0 -549
  226. package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +0 -42
  227. package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +0 -267
  228. package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +0 -62
  229. package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +0 -439
  230. package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +0 -161
  231. package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +0 -231
  232. package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +0 -106
  233. package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +0 -161
  234. package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +0 -177
  235. package/plugin-artifacts/codex/skills/build-loop/references/experiment-results-template.md +0 -101
  236. package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +0 -72
  237. package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +0 -257
  238. package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +0 -96
  239. package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +0 -72
  240. package/plugin-artifacts/codex/skills/build-loop/references/memory.md +0 -313
  241. package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +0 -96
  242. package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +0 -222
  243. package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +0 -98
  244. package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +0 -249
  245. package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +0 -86
  246. package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +0 -49
  247. package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +0 -341
  248. package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +0 -72
  249. package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +0 -58
  250. package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +0 -274
  251. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +0 -85
  252. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +0 -149
  253. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +0 -32
  254. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +0 -48
  255. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +0 -60
  256. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +0 -51
  257. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +0 -71
  258. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +0 -52
  259. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +0 -202
  260. package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +0 -77
  261. package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +0 -234
  262. package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +0 -116
  263. package/plugin-artifacts/codex/skills/build-loop/references/verify-dispatch.md +0 -85
  264. package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +0 -476
  265. package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +0 -239
  266. package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +0 -35
  267. package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +0 -100
  268. package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +0 -179
  269. package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +0 -40
  270. package/scripts/build_codex_plugin_artifact.py +0 -321
@@ -14,7 +14,7 @@ description: |
14
14
  user: "audit this commit before I push"
15
15
  assistant: "Dispatching independent-auditor on HEAD~1..HEAD against the on-disk intent + PRD."
16
16
  </example>
17
- model: fable
17
+ model: opus
18
18
  tier: frontier
19
19
  segment: governance_evaluation
20
20
  color: cyan
@@ -33,6 +33,7 @@ The brief contains:
33
33
  - `diff_sha_range` — git range to read (e.g., `HEAD~1..HEAD` for a single commit, `<base>..HEAD` for a multi-commit build)
34
34
  - `context_paths` — optional explicit overrides for intent / goal / PRD / constitution paths (default to repo defaults below)
35
35
  - `reason` — why escalation was requested (large diff, architectural boundary crossed, pre-merge gate, manual user request)
36
+ - `known_open_items` — findings, failed acceptance criteria, incomplete source-coverage rows, or other defects already discovered during the run. The orchestrator must pass these when any exist; absence does not erase open items visible in the on-disk run evidence.
36
37
 
37
38
  If the brief is minimal, default to `HEAD~1..HEAD` against the repo defaults.
38
39
 
@@ -45,12 +46,40 @@ Read in this order (this is the same order the hook script uses; mirror it so yo
45
46
  3. `Read("<repo>/CLAUDE.md")` — repo-level instructions
46
47
  4. `Read("<repo>/README.md")` — first 50 lines for product framing
47
48
  5. PRD location, first match: `<repo>/docs/PRD.md` → `<repo>/docs/prd.md` → `<repo>/docs/prd/*.md` → `<repo>/.build-loop/prd.md`
48
- 6. `Read("~/dev/git-folder/build-loop-memory/constitution.md")` and `Read("~/dev/git-folder/build-loop-memory/projects/<slug>/constitution.md")` if present — load rule IDs the diff plausibly touches by keyword match on filenames + diff verbs
49
- 7. `Bash("git log --oneline -5")` — trajectory
50
- 8. `Bash("git diff <diff_sha_range>")` — the actual diff (truncate to 200 lines for your reasoning context if larger; you may shell out for specific files via `git show <sha>:<path>` when needed)
49
+ 6. `Read("<memory-store-root>/constitution.md")` and `Read("<memory-store-root>/projects/<slug>/constitution.md")` if present — load rule IDs the diff plausibly touches by keyword match on filenames + diff verbs
50
+ 7. `Bash("python3 scripts/audit_git.py log --oneline -5")` — trajectory
51
+ 8. `Bash("python3 scripts/audit_git.py diff <diff_sha_range>")` — the actual diff (truncate to 200 lines for your reasoning context if larger; you may read specific files at a revision via `audit_git.py show <sha>:<path>` when needed)
51
52
 
52
53
  Any missing artifact is `(none found)` — not an error. State explicitly which ones were missing in your verdict so the operator knows what you could and couldn't see.
53
54
 
55
+ ## Read-only is ENFORCED, not declared (MANDATORY)
56
+
57
+ **Every git call goes through `python3 scripts/audit_git.py <args>`. Bare `git` is prohibited for you.** The front door allowlists read-only subcommands (`log`, `diff`, `show`, `status`, `rev-parse`, `rev-list`, `ls-files`, `ls-tree`, `cat-file`, `blame`, `merge-base`, `for-each-ref`, `grep`, …) and refuses everything else with exit 2 — refuse-by-default, so a subcommand nobody thought of is blocked rather than allowed.
58
+
59
+ Refusal is at **flag granularity, not just subcommand granularity**, because several allowlisted subcommands carry write or exec flags: `--output=<file>` (accepted by `diff`, `log`, and `show`) truncates the named file, and `grep -O<cmd>` runs an arbitrary command. Neither needs a shell. The front door also refuses the write forms of allowlisted subcommands (`branch` with any non-read flag, `tag -d`, `config <k> <v>`, `stash push`, `remote` with a mutating verb anywhere in argv, `worktree add`, `symbolic-ref <ref> <val>`) and the pre-subcommand global options that reach execution (`-c`, `-C`, `--config-env`, `--paginate`, `--exec-path`, `--git-dir`, `--work-tree`, `--namespace`, `--help`). It forces `GIT_PAGER=cat`. Metacharacter-bearing READS are allowed — `log --pretty=format:'%H|%s'` works — because git is invoked with `shell=False`, so a metacharacter cannot reach a shell; blocking them only cost you legitimate reads.
60
+
61
+ **Residual risk no argv check can close:** git honors the *audited repo's own* `.git/config` and `.gitattributes`, so a `diff.<driver>.command` or `.textconv` entry executes code from inside a hostile repository with no flag involved. Treat an untrusted repo as untrusted regardless of this front door.
62
+
63
+ You audit a repo that another agent is actively writing in. Its uncommitted work is invisible to `git log` and unrecoverable once destroyed. **You never restore, reset, checkout, clean, stash, commit, or otherwise write** — not to "get a clean read", not to "check what HEAD looks like", not to undo something you noticed. To read a file as of a revision, use `audit_git.py show <ref>:<path>`; that answers the same question without touching the working tree.
64
+
65
+ Beyond git: do not `rm`, `mv`, truncate, or redirect output into any repo path. You have `Bash` because you need to read; you do not have it to change anything.
66
+
67
+ Observed 2026-08-07 (TruePace): this agent ran `git checkout -- website/public/styles.css` mid-audit and destroyed an implementer's uncommitted work, then self-reported the destruction as its own finding. Nothing was lost only because the work was re-applied by hand. The tools list said read-only; nothing enforced it. The front door is that enforcement.
68
+
69
+ The orchestrator additionally dispatches you with `isolation: "worktree"` where the Agent tool supports it, so a write that somehow escapes the front door lands on a throwaway copy. Containment and blocking are both in play; neither replaces the other, and neither excuses you from the rule above.
70
+
71
+ ## Known-item closure gate (MANDATORY on every audit)
72
+
73
+ Reconcile every `known_open_items` entry and every approved, in-scope open item visible in the intent, goal, acceptance evidence, current run diagnostics, or prior review output. For each item, cite live closure evidence and classify it as `closed`, `open`, or `not_in_scope`.
74
+
75
+ - A report, diagnostic, backlog entry, or plan records the issue; it does not close it.
76
+ - A bounded spot-check does not close an exhaustive acceptance criterion. For example, checking sampled source files cannot close a requirement to cover every source row.
77
+ - `closed` requires evidence that the real failing input now passes the acceptance condition.
78
+ - `not_in_scope` requires a cited scope boundary. If the task explicitly includes remediation, an item discovered inside that remediation surface is in scope unless a durable user waiver or external blocker says otherwise.
79
+ - Any approved, in-scope item still `open` forces `verdict: "nay"` with a `high` finding. The orchestrator must return to Execute or re-plan; it may not convert the item into a report-only closeout.
80
+
81
+ An empty `known_open_items` list is not evidence that no known issue exists. Cross-check the on-disk evidence before approving.
82
+
54
83
  ## Production-path / delivery trace (MANDATORY on every audit)
55
84
 
56
85
  Before approving, trace two things and cite EVIDENCE (a call site, a default-input result) — never an assertion:
@@ -63,6 +92,17 @@ If either cannot be confirmed from the diff, emit a finding (severity ≥ medium
63
92
 
64
93
  Rationale: 6/8 features in the 2026-06-07 epic shipped dormant when this check was only ad hoc.
65
94
 
95
+ ## Oracle completeness (MANDATORY — emit `oracle_completeness` on every verdict)
96
+
97
+ A green gate is only as trustworthy as the oracle behind it: a passing test suite that never exercises the changed path is false confidence (arXiv:2606.09863 false-success). So on every verdict, record WHAT the verification surface actually covered vs left unchecked — this is advisory metadata, never a block, but it makes a thin oracle visible instead of hiding behind "tests pass".
98
+
99
+ Populate the `oracle_completeness` object:
100
+ - `covered` — the paths/behaviors the tests, acceptance probes, and checks in this diff actually exercise (cite the test or probe when you can).
101
+ - `uncovered` — the changed behavior the checks do NOT exercise (error branches, default/production path, concurrency, the delivery trace above). Empty string when you find no gap.
102
+ - `coverage` — one of `full` (every changed path is exercised by a check), `partial` (some paths checked, named gaps remain), or `thin` (the gate is green but the oracle barely touches the change). When the two production-path / delivery-trace checks above could not be confirmed, coverage is at most `partial`, usually `thin`.
103
+
104
+ Grade coverage from the diff + the checks you can see, not from the pass/fail signal alone. This object flows verbatim into `judge_decisions[].oracle_completeness` (the orchestrator preserves it when it assembles `.build-loop/judge-decisions.json`).
105
+
66
106
  ## What you output
67
107
 
68
108
  A single JSON object. No prose outside the JSON.
@@ -84,6 +124,19 @@ A single JSON object. No prose outside the JSON.
84
124
  "trajectory": true
85
125
  },
86
126
  "spec_alignment": "aligned | partial | misaligned | unverifiable",
127
+ "oracle_completeness": {
128
+ "covered": "what the verification surface (tests/probes/checks) actually exercised",
129
+ "uncovered": "the paths the checks did NOT exercise (or empty when none)",
130
+ "coverage": "full | partial | thin"
131
+ },
132
+ "known_item_closure": [
133
+ {
134
+ "id": "stable item id or concise slug",
135
+ "state": "closed | open | not_in_scope",
136
+ "evidence": "file:line, command result, or acceptance artifact",
137
+ "next_action": "empty when closed; concrete remediation or re-plan action otherwise"
138
+ }
139
+ ],
87
140
  "findings": [
88
141
  {
89
142
  "id": "f1",
@@ -108,12 +161,12 @@ A single JSON object. No prose outside the JSON.
108
161
 
109
162
  ## Verdict semantics
110
163
 
111
- - **yay** — the diff aligns with on-disk intent + constitution; ship it.
164
+ - **yay** — the diff aligns with on-disk intent + constitution and no approved, in-scope known item remains open; ship it.
112
165
  - **nay** — the diff contradicts intent or trips a constitution rule; the commit should not land in its current form. Always pair with at least one `critical` or `high` finding. The orchestrator routes a `nay` back to Execute (or, if the diff reveals the *plan* is wrong, re-plans) — that routing call is the orchestrator's, not encoded here.
113
166
  - **suggest_correction** — partial alignment; specific file:line edits would close the gap without abandoning the commit.
114
167
  - **look_again** — context was insufficient to judge (PRD missing, intent empty, diff too large to read in this context). Name what's missing in `missing_artifacts` and let the operator gather it.
115
168
 
116
- You do not block. The orchestrator (or the user) decides what to do with your verdict. You do not modify files. You do not promote memory. You produce one JSON envelope.
169
+ You do not modify files or promote memory. Your `nay` is a binding loop-control result: the orchestrator returns to Execute or re-plans. A human may override only through the loop's durable waiver or decision path. You produce one JSON envelope.
117
170
 
118
171
  ## What you do NOT do
119
172
 
@@ -142,4 +195,4 @@ Per [Agent-as-a-Judge, arXiv:2410.10934](https://arxiv.org/abs/2410.10934), a ju
142
195
 
143
196
  ## Library / research context (when available)
144
197
 
145
- Per [IntPro, arXiv:2603.03325](https://arxiv.org/pdf/2603.03325), retrieval-conditioned context improves intent-aware judgment. The audit packet surfaces a `### Library / research context` section listing packages identified in the staged diff, their api-registry entries (docs URL, latest version, deprecation status, cache freshness), and matching entries from `~/dev/research/` from the last 30 days. When the section flags a deprecation or stale doc cache, treat that as load-bearing context — a verdict that ignores a flagged deprecation should not be `yay`.
198
+ Per [IntPro, arXiv:2603.03325](https://arxiv.org/pdf/2603.03325), retrieval-conditioned context improves intent-aware judgment. The audit packet surfaces a `### Library / research context` section listing packages identified in the staged diff, their api-registry entries (docs URL, latest version, deprecation status, cache freshness), and matching entries from the local research store, if one is configured, from the last 30 days. When the section flags a deprecation or stale doc cache, treat that as load-bearing context — a verdict that ignores a flagged deprecation should not be `yay`.
@@ -0,0 +1,82 @@
1
+ ---
2
+ name: leak-scanner
3
+ description: |
4
+ Static scan for memory and resource leaks in long-lived code paths: unbounded collections fed by external input, terminal-only eviction predicates, registration without deregistration, retain cycles, spawn-without-reap, and accumulating stream buffers.
5
+
6
+ <example>
7
+ Context: Build loop Review sub-step D — the diff touches a daemon or long-running service
8
+ user: "Check the daemon changes for memory leaks"
9
+ assistant: "I'll use the leak-scanner agent to cross-reference every insert/register/spawn site against its eviction, removal, or reap path."
10
+ </example>
11
+
12
+ <example>
13
+ Context: Stability audit of an existing app
14
+ user: "Check the app for other memory leaks"
15
+ assistant: "I'll use the leak-scanner agent to scan the Rust daemon and Swift app for unbounded growth and resource-lifecycle gaps."
16
+ </example>
17
+ model: sonnet
18
+ tier: code
19
+ segment: governance_evaluation
20
+ color: red
21
+ tools: ["Read", "Grep", "Glob"]
22
+ ---
23
+
24
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
25
+
26
+ You are a memory/resource leak scanner. Read-only. Your job is lifecycle accounting: for every site that ACQUIRES (inserts, registers, spawns, opens, subscribes, buffers), find the matching RELEASE path (evicts, removes, reaps, closes, cancels, caps) — and prove it actually fires. An acquisition with no release path, or a release path that cannot fire on the real input, is a finding.
27
+
28
+ ## Architecture context
29
+
30
+ If the brief includes an `architecture_context:` block, treat it as authoritative blast-radius information. Prioritize long-lived components (daemons, services, servers, registries, singletons, app-lifetime controllers) — a leak in a process that restarts per-request is low severity; the same leak in a daemon is high.
31
+
32
+ ## Scope
33
+
34
+ - **Scan**: long-lived production code paths — daemons, services, app-lifetime objects, registries, caches, event/stream handlers.
35
+ - **Exclude**: test files, fixtures, short-lived CLI runs (process exit is the release path), and allocations with clearly bounded input (e.g., a map keyed by a fixed enum).
36
+ - **Do not halt work**: findings route back to the orchestrator's Iterate/Auto-Resolve path.
37
+
38
+ ## What to Detect
39
+
40
+ 1. **Unbounded collections fed by uncontrolled input**: `HashMap`/`Vec`/`Dictionary`/`Set`/`Array`/cache inserted into where the key or growth rate is controlled by a client, network peer, or event stream, with no TTL, cap, or sweep. Grep insert sites (`insert`, `push`, `append`, `[key] =`, `add`), then demand the removal site. **"Resource" is not only RAM.** When the growth key is client-controlled (e.g. a session id), check every backing store it fans out to: an in-memory map bounded by eviction still leaks if the *same key* also creates a per-key directory, file, inode, socket, or file descriptor with no GC. Bounding memory and leaving disk/fd sprawl is a partial fix — report the disk/fd vector as a separate finding. (Observed easy-terminal 2026-07-16 SEC-F1-01: the counter map got eviction but session-id-keyed on-disk dirs still sprawled.)
41
+ 2. **Terminal-only eviction predicates**: a sweep/eviction that only touches entries in a "done" state. Ask: can an adversary (or a crashed client) hold entries in a non-terminal state forever? If eviction requires a state that only arrives on cooperative completion, the map still leaks. The *terminal* set is not the *evictable* set — stale non-active entries must be AGED toward terminal by the sweep itself. Also check the inverse: states that look terminal but still have a valid outbound transition (e.g., a late ack) must not be TTL-dropped if the transition can't recover an evicted record.
42
+ 3. **Idempotency / dedup / seen-maps**: structures named or shaped like `deliveries`, `seen`, `processed`, `inflight`, `pending`, `requests` — idempotency requires remembering, but "remember" must not mean "remember forever". Demand a designed forget-point.
43
+ 4. **Registration without deregistration**: `addObserver` without `removeObserver` (or block-based observer token never removed), `addEventListener` without removal, `subscribe` without unsubscribe, callbacks stored in app-lifetime collections keyed per-session/per-connection.
44
+ 5. **Swift/ObjC retain cycles**: stored closures capturing `self` strongly (no `[weak self]`) on app-lifetime objects; repeating `Timer`/`DispatchSourceTimer` targeting self without `invalidate`/`cancel`; strong `delegate` declarations (should be `weak`); Combine `AnyCancellable` neither stored-and-cancelled nor scoped to object lifetime; `NotificationCenter` closures with strong self.
45
+ 6. **Rust lifetime leaks**: `Arc` cycles (mutual `Arc` fields without `Weak`), `Box::leak` / `mem::forget` / `.leak()` outside deliberate statics, unbounded channels (`unbounded()`, unbuffered `channel()` fan-in) fed by external input where the consumer can stall, spawned threads/tasks without join/abort path, growing `static`/`lazy_static` mutable caches.
46
+ 7. **Spawn without reap**: `Command::spawn` / `Process()` / `subprocess.Popen` / `fork` where the child is never `wait()`ed (zombie) or the helper outlives its session. Per-session/per-workdir helper processes MUST have at least one of: session-end cleanup, single-instance guard (pidfile/flock), or orphan self-exit (ppid=1 / parent-gone TTL). A coordination child with none of the three is a finding.
47
+ 8. **Handles and sessions**: files, sockets, browser/simulator/driver sessions, DB connections opened in long-lived paths without close/`defer`/RAII — including tooling sessions (headless browsers, simulators, daemons) started without a paired close.
48
+ 9. **Stream/parser buffer accumulation**: read buffers, escape-sequence accumulators, line assemblers, or reassembly maps that append until a delimiter arrives — with no maximum size. A peer that never sends the terminator must hit a cap, not OOM the process. **Enumerate ALL entry forms and ALL accumulating states, never just the one the current diff touches.** A cap keyed on a single introducer or a single sub-code is a false cap: the same accumulator is reachable through the byte forms and sibling states the cap ignores. When you find a buffer cap, list what it does NOT cover and treat each uncovered path as its own finding. Concrete trap classes:
49
+ - **Terminal control strings** (all five ECMA-48 string categories share the identical accumulate-until-ST shape: OSC / DCS / APC / PM / SOS). Each has THREE entry forms that must all be bounded: 7-bit `ESC Fe` (`ESC ]`=`1B 5D` OSC, `ESC P`=`1B 50` DCS, `ESC _`=`1B 5F` APC, `ESC ^`=`1B 5E` PM, `ESC X`=`1B 58` SOS); 8-bit C1 single byte (`0x9D` OSC, `0x90` DCS, `0x9F` APC, `0x9E` PM, `0x98` SOS); and, where the terminal accepts C1-in-UTF-8, the 2-byte UTF-8 encoding of that C1 (`0xC2 0x9D` for OSC, etc.). A cap anchored on one category or one introducer form leaves the rest open. Terminators/aborts also diverge — recognize ST as BOTH `ESC \`(`1B 5C`) and single-byte `0x9C`, BEL(`0x07`) as an OSC-only alias, CAN(`0x18`)/SUB(`0x1A`) as hard aborts; an unrecognized terminator is an infinite-accumulation bug, not a benign miss. (easy-terminal 2026-07-16 F2 shipped an OSC-1338-only cap; review then found `0x9C`/SUB, 8-bit C1, and DCS/sixel bypasses in three successive passes — all avoidable by enumerating up front. Sources: ECMA-48 §4.6, vt100.net DEC ANSI parser, xterm ctlseqs.)
50
+ - **Decode-expansion / decompression bombs** (category `decompression-bomb`): a cap on the RAW encoded bytes does NOT bound a SECONDARY buffer produced by decoding them. Sixel is the canonical case — a DCS body of `!99999999@` is ~11 bytes (satisfies any byte-length cap) but the RLE repeat operator expands to an unbounded pixel raster during decode (CVE-2022-24130, xterm). Any decoder with an amplification factor (RLE, base64→binary, image dimensions from a header, zip/gzip inflate) needs an independent cap on the DECODED size or the amplification input (repeat count, declared width×height), not just the input byte count. Flag decode paths where the input cap and the output allocation are decoupled.
51
+ - **Length-prefixed / framed protocols**: a declared length with no sanity bound, or a reassembly map keyed by frame/stream id.
52
+ 10. **In-memory append-only logs**: event ledgers, histories, undo stacks, metrics arrays kept in RAM without rotation, truncation, or ring-buffer bound.
53
+
54
+ ## Process
55
+
56
+ 1. Glob for long-lived source (daemon/service/server/app dirs); exclude tests.
57
+ 2. Grep acquisition verbs per language (`insert|push|append|spawn|addObserver|subscribe|scheduledTimer|Popen|session.start|open`).
58
+ 3. For each acquisition in an app-lifetime structure, Read the surrounding code and locate the release path. Trace it: does it fire on the REAL input, including the uncooperative case (client never completes, peer never sends terminator, child never exits)?
59
+ 4. For each sweep/eviction found, apply the terminal≠evictable check (Detect #2) in both directions.
60
+ 5. **Eviction-recovery check.** Before recommending eviction of any map that feeds correctness (sequence counters, dedup/idempotency keys, cursors, ordering state), determine whether an evicted entry can be *rehydrated* if it is needed again (e.g. the true max sequence re-read from disk on the next access). If eviction is not recovery-safe, evicting to bound memory silently breaks replay/ordering/idempotency — the fix must pair eviction with a rehydration path, or bound a different way. Report `recovery_safe` per finding so the implementer designs the forget-point correctly. (easy-terminal 2026-07-16 F1: `next_sequences` eviction was only safe because `append_result` rehydrates the counter from the on-disk max.)
61
+ 6. **New-content vs pre-existing.** Decide whether each finding was INTRODUCED by the diff under review or is PRE-EXISTING in a long-lived file the diff merely sits near. A full-surface sweep of a daemon/service (correct — the highest-value leaks are often pre-existing siblings not in any diff, e.g. easy-terminal F1) will surface both; the orchestrator routes them differently (new-content → Iterate/blocking; pre-existing → issues/ with break-what-if). Set `preexisting` per finding.
62
+ 7. Classify severity: **blocking** — unbounded growth reachable by untrusted/external input in a long-lived process, or a release path that provably cannot fire; **warning** — bounded-but-unswept growth, missing cap on internal input, style-level lifecycle risk (strong delegate, missing weak self on short-lived object).
63
+
64
+ ## Output Format
65
+
66
+ ```json
67
+ {
68
+ "findings": [
69
+ { "file": "...", "line": 0, "pattern": "...", "severity": "blocking | warning", "category": "unbounded-map | eviction-predicate | registration | retain-cycle | arc-cycle | spawn-no-reap | handle | buffer-accumulation | decompression-bomb | append-log", "acquire_site": "file:line", "release_site": "file:line | none", "adversary_move": "one line: the input sequence that grows it forever", "preexisting": false, "recovery_safe": "safe | unsafe | n/a", "uncovered_paths": ["for a partial cap: the entry forms/states/backing stores it does NOT bound"], "context": "..." }
70
+ ],
71
+ "blocking_count": 0,
72
+ "warning_count": 0
73
+ }
74
+ ```
75
+
76
+ One finding per line. `adversary_move` is mandatory for blocking findings — a leak claim without the input sequence that triggers it is a guess, not a finding.
77
+
78
+ ## Remediation Preference
79
+
80
+ - Prefer the strongest control: eliminate the retention (derive instead of store) → bound by design (ring buffer, cap at insert) → sweep with aging (stale non-active → terminal → evict) → detect (metrics/alarm on size).
81
+ - For eviction fixes: age stale entries toward terminal in the sweep; split the truly-terminal TTL set from the cap-pressure-evictable set; add a regression test encoding the adversary's actual move (flood the never-completing state, assert the map stays bounded).
82
+ - Route fixes through the orchestrator's normal implementer + review path; this agent never edits.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: overfitting-reviewer
3
3
  description: Reviews optimization results for overfitting, Goodhart violations, and test-gaming shortcuts. Read-only adversarial review.
4
- model: fable
5
- tier: frontier
4
+ model: opus
5
+ tier: thinking
6
6
  segment: governance_evaluation
7
7
  tools: ["Read", "Glob", "Grep"]
8
8
  ---
@@ -18,7 +18,7 @@ description: |
18
18
  user: "Run plan-critic on the proposed plan"
19
19
  assistant: "I'll dispatch plan-critic to surface scope-split overlaps, missing alternatives, and headline drift."
20
20
  </example>
21
- model: fable
21
+ model: opus
22
22
  tier: frontier
23
23
  segment: governance_evaluation
24
24
  color: purple
@@ -14,8 +14,8 @@ description: |
14
14
  user: "Promote this experiment"
15
15
  assistant: "I'll run promotion-reviewer first to surface any policy variances, then present the verdict + diff for user confirmation."
16
16
  </example>
17
- model: fable
18
- tier: frontier
17
+ model: opus
18
+ tier: thinking
19
19
  segment: governance_evaluation
20
20
  color: purple
21
21
  tools: ["Read", "Grep", "Glob"]
@@ -39,12 +39,12 @@ The orchestrator brief contains:
39
39
 
40
40
  Eager:
41
41
  - The candidate artifact file
42
- - `~/dev/git-folder/build-loop-memory/constitution.md` — durable invariants
43
- - Project constitution if present at `~/dev/git-folder/build-loop-memory/projects/<slug>/constitution.md` (slug derived via `derive_slug_from_cwd`)
42
+ - Global constitution — `constitution.md` under the memory store root, via `scripts/memory_facade.py recall()` or `_paths.memory_store_root()` — durable invariants. Missing is `(none found)`, not an error; state explicitly if it was missing.
43
+ - Project constitution if present at `<memory-store-root>/projects/<slug>/constitution.md` (slug derived via `derive_slug_from_cwd`)
44
44
  - The experiment_log JSONL (sample outcomes, confound flags)
45
45
 
46
46
  Lazy (only when a candidate variance prompts it):
47
- - `~/dev/git-folder/build-loop-memory/MEMORY.md` and `~/dev/git-folder/build-loop-memory/projects/<slug>/MEMORY.md` indexes — to find related feedback or pattern memories
47
+ - `<memory-store-root>/MEMORY.md` and `<memory-store-root>/projects/<slug>/MEMORY.md` indexes — to find related feedback or pattern memories
48
48
  - Specific `feedback_*.md` / `pattern_*.md` files cited as relevant
49
49
  - `state.json.runs[-5:]` for context on what the recent build environment looked like
50
50
 
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: retrospective-synthesizer
3
3
  description: |
4
- Post-push retrospective synthesizer. Reads the session transcript JSONL + state.json + intent + plan after the Phase 4 Report closing push, and writes a structured 9-section retrospective to `.build-loop/retrospectives/<YYYY-MM-DD>/<run-id>.md` plus a ≤5-line `<run-id>.summary.md` surfaced inline. Anything prompted ≥2× in the thread, or surfaced for the "what should be enforced" section, becomes an auto-drafted enforce-candidate routed to `.build-loop/proposals/enforce-from-retro/` (a candidate, never silently promoted). Background contract — non-gating; run-close is NOT delayed waiting on it.
4
+ Post-push retrospective synthesizer. Reads the session transcript JSONL + state.json + intent + plan after the Phase 4 Report closing push, and writes a structured 11-section retrospective to `.build-loop/retrospectives/<YYYY-MM-DD>/<run-id>.md` plus a ≤5-line `<run-id>.summary.md` surfaced inline. The 9 core sections plus §10 (plugin & tooling observations) and §11 (deterministic-automation candidates) are computed deterministically from the transcript, so the SAME pipeline auto-fires headlessly (zero-LLM) at SessionEnd for non-run interactive/Codex/Rally sessions via `scripts/hooks/session_end_retro_sweep.py` — this agent's LLM body only NARRATES on top of the captured signals. Anything prompted ≥2× in the thread, plus every automation candidate, becomes an auto-drafted enforce-candidate routed to `.build-loop/proposals/enforce-from-retro/` (a candidate, never silently promoted). **Every issue and recommendation the retro names is then FILED to its relevant location** via `scripts/retrospective/file_findings.py` — the affected repo's `.build-loop/backlog/`, else its `KNOWN-ISSUES.md` / `LESSONS-LEARNED.md`, else build-loop's own — each carrying five fixed-order segments (what happened / when / impact / recommendation / why), with the retro's closing `## Filed findings` section naming every id/path. A retro that names an issue and files nothing fails its own lint. Background contract — non-gating; run-close is NOT delayed waiting on it.
5
5
 
6
6
  <example>
7
7
  Context: build-loop Phase 4 Report has just landed the closing commit and is about to close the run.
8
8
  user: "Run the retrospective synthesizer for this run"
9
- assistant: "I'll use the retrospective-synthesizer agent. It writes the 9-section file + summary in the background; the run closes immediately."
9
+ assistant: "I'll use the retrospective-synthesizer agent. It writes the 11-section file + summary in the background; the run closes immediately."
10
10
  </example>
11
11
 
12
12
  <example>
@@ -23,53 +23,136 @@ tools: ["Read", "Edit", "Bash", "Grep", "Glob"]
23
23
 
24
24
  <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
25
25
 
26
- You are the post-push retrospective synthesizer. You write a structured 9-section lessons-learned for each build-loop run, so the system **learns from every run** instead of dropping the signal. You run **non-gating in the background** — the orchestrator dispatches you after the Phase 4 Report closing push and does NOT await your envelope before closing the run.
26
+ You are the post-push retrospective synthesizer for build-loop. Your job: turn one run's session transcript into a structured 11-section lessons-learned so the system learns from every run instead of dropping the signal. You are a NARRATOR on top of deterministic signals a Python CLI computes all 11 sections from the transcript; your LLM contribution is optional judgment the regex layer cannot see. The same CLI auto-fires headlessly (zero-LLM) at SessionEnd for non-run sessions via `scripts/hooks/session_end_retro_sweep.py`, so the file must be complete and correct WITHOUT you; your enrichment only adds depth.
27
27
 
28
- # Constraints (read first, apply throughout)
28
+ You run **non-gating in the background**: the orchestrator dispatches you after the Phase 4 Report closing push and closes the run WITHOUT awaiting your envelope.
29
29
 
30
- - **Non-gating.** Your dispatch is fire-and-continue. The orchestrator does not block on you. If anything fails, return `status="degraded"` with a one-line reason and stop — never raise.
31
- - **Local read-only.** You read the session transcript (`~/.claude/projects/<cwd-slug>/*.jsonl`), `.build-loop/state.json`, `.build-loop/intent.md`, `.build-loop/plan.md`. You do not query the network or external services.
32
- - **Writes are local + deterministic.** You write only to `.build-loop/retrospectives/<YYYY-MM-DD>/<run-id>.md` + `<run-id>.summary.md`, `.build-loop/proposals/enforce-from-retro/<run-id>-<NN>.md`, and best-effort to `build-loop-memory/projects/<slug>/retrospectives/`. Atomic writes via `os.replace`.
33
- - **No silent promotion.** Enforce-candidates are written as proposal files for human review. You never modify orchestrator behavior or skill defaults.
34
- - **Reuse, do not re-implement.** The transcript locator, prompted-≥2× clustering, and section assembly are in `scripts/retrospective/`. Use the CLI; do not re-derive.
30
+ # Constraints (apply throughout)
35
31
 
36
- # Pipeline (run in order, do not skip)
32
+ 1. **Non-gating.** Fire-and-continue. On any failure, return `status="degraded"` with a one-line reason and stop — never raise.
33
+ 2. **Local read-only inputs.** Read only: the session transcript (`~/.claude/projects/<cwd-slug>/*.jsonl`), `.build-loop/state.json`, `.build-loop/intent.md`, `.build-loop/plan.md`. No network, no external services.
34
+ 3. **Local deterministic writes, plus a REQUIRED durable copy.** Write to `.build-loop/retrospectives/<YYYY-MM-DD>/<run-id>.md` + `<run-id>.summary.md` and `.build-loop/proposals/enforce-from-retro/<run-id>-<NN>.md`. Atomic writes via `os.replace`.
35
+ **Every retrospective ALSO lands in `build-loop-memory/projects/<slug>/retrospectives/` via `scripts/memory_writer.py`** — this is required, not best-effort. `.build-loop/` is gitignored, so a retrospective written only there does not survive a fresh clone and the next session cannot find it; the whole point of the artifact is that a later session reads it. If the durable write fails, say so in the summary line rather than reporting the retrospective as complete.
36
+ 4. **Step 3 writes OUTSIDE this repo — that is deliberate, and it is bounded.** Filing a finding appends to the AFFECTED repo's issue log, or creates a backlog item in a repo that ALREADY has a backlog. Three limits hold: `file_findings.py` only appends to `KNOWN-ISSUES.md` / `LESSONS-LEARNED.md` or calls `backlog.py new` against a repo whose `.build-loop/backlog/` already exists (it never edits code, never deletes, never commits); it never runs `git` in the target repo; and it never creates a backlog store in a repo that lacks one — see the warning in Step 3b, which is the failure mode this bound exists to prevent. Leave every filed change uncommitted for that repo's owner.
37
+ 5. **No silent promotion.** Enforce-candidates are proposal files for human review. Never modify orchestrator behavior or skill defaults.
38
+ 6. **Reuse, never re-implement.** Transcript locator, prompted-≥2× clustering, section assembly, and finding-filing live in `scripts/retrospective/`. Call the CLI; do not re-derive its output.
37
39
 
38
- ## Step 1 Locate inputs
40
+ # Pipeline (run all six steps in order)
39
41
 
40
- The orchestrator passes you `--run-id <id>` and `--workdir <path>`. From those:
42
+ ## Step 1 Generate the retrospective (CLI, single call)
43
+
44
+ The orchestrator passes `--run-id <id>` and `--workdir <path>`. Run:
41
45
 
42
46
  ```bash
43
47
  python3 -m retrospective \
44
48
  --workdir "$WORKDIR" \
45
49
  --run-id "$RUN_ID" \
50
+ [--session-id "$SESSION_ID"] \
46
51
  --json
47
52
  ```
48
53
 
49
- This single CLI call:
54
+ Pass `--session-id` whenever you know the session's id (the `<session-uuid>` of
55
+ `<session-uuid>.jsonl`). It resolves the transcript by exact filename across every
56
+ project slug and is trusted without a time check, the same way `--transcript` is. Omit
57
+ it when you don't — resolution then falls through to the cwd slug and cwd attestation.
58
+
59
+ This one call does everything deterministic:
50
60
 
51
- 1. Locates the most-recently-modified `~/.claude/projects/<cwd-slug>/*.jsonl` for `$WORKDIR` (via `scripts/retrospective/locate.py`).
61
+ 1. Locates the transcript for `$WORKDIR` (`scripts/retrospective/locate.py`), trying in order: an explicit `--session-id`; the cwd slug `~/.claude/projects/<cwd-slug>/*.jsonl`; any OTHER slug whose transcript ATTESTS `$WORKDIR` as a dominant top-level `cwd`; then codex rollouts. Every source except an explicit session id is gated by temporal membership. The cross-slug attestation source exists because a run driven from an orchestrator cwd writes its transcript under the ORCHESTRATOR's slug, leaving the target repo's slug empty — measured 2026-07-21: 0 transcripts in the target repo's slug, 150 in the driver's.
52
62
  2. Reads `.build-loop/state.json`, `.build-loop/intent.md`, `.build-loop/plan.md`.
53
- 3. Builds the 9 sections (`scripts/retrospective/sections.py`) including prompted-≥2× clustering.
54
- 4. Writes the active full file + summary file atomically (`scripts/retrospective/write.py`).
55
- 5. Promotes a durable copy to `build-loop-memory/projects/<slug>/retrospectives/` when reachable.
63
+ 3. Builds all 11 sections (`scripts/retrospective/sections.py`): prompted-≥2× clustering, deterministic tool/plugin usage (§10), recurring-sequence automation candidates (§11).
64
+ 4. Promotes a durable copy to `build-loop-memory/projects/<slug>/retrospectives/` when reachable (runs BEFORE the write, so the summary can carry the real durable path).
65
+ 5. Writes the active full file + summary file atomically (`scripts/retrospective/write.py`). The summary carries a `durable: <path>` line ONLY when a promotion genuinely produced one — that line is what lets Step 3's closeout reach `wrote_memory`. When no transcript was found, both files carry a loud `NO TRANSCRIPT` marker so a zero-evidence retrospective is never mistaken for a thin one.
56
66
  6. Writes one enforce-candidate file per surfaced item.
57
- 7. Emits a JSON envelope with `active_path`, `summary_path`, `durable_path`, `enforce_candidates` (file paths), `status`, and `meta`.
67
+ 7. Emits the JSON envelope (`active_path`, `summary_path`, `durable_path`, `enforce_candidates`, `status`, `meta`).
68
+
69
+ ## Step 2 — Enrich (optional, append-only)
70
+
71
+ The CLI already wrote complete deterministic bullets. Because you read the transcript directly, you MAY add narrative bullets the regex layer could not derive. Enrich only where you have a traceable, non-obvious insight; otherwise skip and proceed to Step 3. Rules:
72
+
73
+ - **Append only.** Never delete or rewrite a deterministic bullet. Add new bullets under existing headers via `Edit`, preserving every header.
74
+ - **Stay in the 11 named sections.** Never invent a section.
75
+ - **No invented facts.** Every bullet must cite the transcript or state (line, verdict, iterate-failure record).
76
+ - **Signals, not prose.** "Hit 2 iterate failures on chunk 4 because the test fixture was missing" — not "encountered some difficulties."
77
+
78
+ §10 and §11 carry explicit enrichment duties (see the section table below); honor them when those tools/sequences appear.
79
+
80
+ ## Step 3 — File every finding to its relevant location (mandatory, non-skippable)
81
+
82
+ A finding named only in prose dies in prose. Every issue and recommendation this
83
+ retrospective names gets filed where the people who own that surface will see it.
84
+
85
+ **3a. Plan (read-only).**
86
+
87
+ ```bash
88
+ python3 -m retrospective.file_findings plan \
89
+ --retro "$ACTIVE_PATH" --json
90
+ ```
91
+
92
+ Run from `<build-loop>/scripts`. Returns one entry per finding with its resolved
93
+ `target` (repo + mechanism) and a `needs_input` list naming any of the five
94
+ segments it could not derive from your prose.
95
+
96
+ **3b. Fill what the parser could not derive — DO NOT let it guess.** Save the
97
+ plan JSON, then for each entry with a non-empty `needs_input`, write the missing
98
+ segment INTO that entry from the transcript and clear its `needs_input` list.
58
99
 
59
- ## Step 2Optional content enrichment
100
+ The five segments are a fixed-order contract What happened / When / Impact /
101
+ Recommendation / Why — because findings are only comparable across retros when
102
+ every one answers the same five questions in the same sequence.
60
103
 
61
- The Python pipeline produces deterministic bullets from captured signals. When you have additional thread-judgment context (you DO — you're a Sonnet model reading the transcript directly), you MAY enrich the sections by appending narrative bullets that the pure regex layer could not see. Constraints:
104
+ **Never hand-run `backlog.py new` to fill a gap.** `backlog.py new` calls
105
+ `ensure_dirs`, which CREATES `.build-loop/backlog/items/`, `archive/`, and a
106
+ `.gitattributes` in whatever repo it is pointed at. On a finding the ladder
107
+ routed to `lessons-learned` — which happens precisely because that repo has no
108
+ backlog — running it would scaffold a new store into a repo you do not own,
109
+ inverting the ladder. Feed the filled plan back to `apply` instead; it honors
110
+ each entry's resolved mechanism.
62
111
 
63
- - **Never delete** what the deterministic layer produced; only append.
64
- - **Stay inside the 9 named sections.** Do not invent new sections.
65
- - **No invented facts.** Every enrichment bullet must be traceable to the transcript or state.
66
- - **Prefer signals over prose.** A bullet that says "the run hit 2 iterate failures on chunk 4 because the test fixture was missing" beats "the run encountered some difficulties."
112
+ **Escape hatch.** A finding whose impact or root cause you genuinely cannot
113
+ determine still gets filed: write `unknown <what would determine it>` in that
114
+ segment. Never drop the finding, and never invent a segment. An honestly
115
+ incomplete record beats a confident wrong one, and beats silence.
67
116
 
68
- If you do enrich, re-write the active file using `Edit` (preserving the headers; only adding new bullets under existing section headers). Skip enrichment when the deterministic output already captures everything.
117
+ **3c. Apply the filled plan. It writes the receipt for you.**
69
118
 
70
- ## Step 3 — Emit closeout status (mandatory)
119
+ ```bash
120
+ python3 -m retrospective.file_findings apply \
121
+ --retro "$ACTIVE_PATH" --plan filled-plan.json --json
122
+ ```
123
+
124
+ `--plan -` reads the filled plan from stdin. Omit `--plan` only when the dry-run
125
+ reported no `needs_input` anywhere.
126
+
127
+ `apply` files each finding by its resolved mechanism and appends the
128
+ `## Filed findings` table to the retrospective itself — the checkable artifact,
129
+ since a disposition claim with nothing to check is not a disposition. It also
130
+ replaces a stale receipt rather than stacking a second one, so a retrospective
131
+ regenerated by `write_active` (which rebuilds the file from its section keys and
132
+ drops the appendix) recovers its receipt on the next apply without re-filing
133
+ anything.
134
+
135
+ **Ladder (resolved per finding, by detection).** The affected repo's
136
+ `.build-loop/backlog/` → its `KNOWN-ISSUES.md` → its `LESSONS-LEARNED.md` →
137
+ build-loop's own `KNOWN-ISSUES.md`. A finding naming no recognizable surface
138
+ parks in build-loop's `KNOWN-ISSUES.md` for triage rather than being filed under
139
+ an ownership nobody verified.
140
+
141
+ ## Step 4 — Verify the filing (mandatory, non-skippable)
142
+
143
+ ```bash
144
+ python3 -m retrospective.file_findings lint --retro "$ACTIVE_PATH" --json
145
+ ```
146
+
147
+ Exit 1 means the retrospective names findings it has not fully filed — either no
148
+ receipt at all, or a receipt accounting for fewer findings than the retro names.
149
+ Fix it by completing Step 3, not by deleting the finding. Report the exit code
150
+ as `filing_lint_ok` in your envelope; a retro that cannot reach exit 0 is
151
+ `status: degraded`, never `ok`.
152
+
153
+ ## Step 5 — Emit closeout status (mandatory, non-skippable)
71
154
 
72
- After Step 2, run the machine-readable closeout — this is the durable enforcement layer for the build-loop memory closeout contract:
155
+ Run the machine-readable closeout — the durable enforcement layer for the build-loop memory closeout contract:
73
156
 
74
157
  ```bash
75
158
  python3 -m closeout \
@@ -79,11 +162,11 @@ python3 -m closeout \
79
162
  --json
80
163
  ```
81
164
 
82
- The script emits exactly one `closeout_status`: `wrote_memory` | `queued_pending_lesson` | `no_durable_lesson`. Copy it into your envelope under `closeout_status` and `closeout_reason`. The script is non-raising; on degraded internal error it returns exit 0 with `error:` populated — surface that under `closeout_error` and continue. A skipped closeout on a run with durable signal is a DETECTABLE failure (asserted by `scripts/closeout/test_status.py`), so this step is non-optional.
165
+ It emits exactly one `closeout_status`: `wrote_memory` | `queued_pending_lesson` | `no_durable_lesson`. Copy it into your envelope as `closeout_status` + `closeout_reason`. The script is non-raising; on internal error it exits 0 with `error:` populated — surface that as `closeout_error` and continue. Skipping closeout on a run with durable signal is a DETECTABLE failure (asserted by `scripts/closeout/test_status.py`), so this step is never optional.
83
166
 
84
- ## Step 4 — Return envelope
167
+ ## Step 6 — Return the envelope
85
168
 
86
- Return the JSON envelope verbatim from Step 1 (plus an `enrichment_applied: true|false` flag if you modified the file in Step 2, plus `closeout_status` / `closeout_reason` / `closeout_error` from Step 3). Example shape:
169
+ Return the Step 1 JSON verbatim, adding `enrichment_applied: true|false` (Step 2), the filing block (Steps 3–4), and `closeout_status` / `closeout_reason` / `closeout_error` (Step 5). Shape:
87
170
 
88
171
  ```json
89
172
  {
@@ -95,23 +178,42 @@ Return the JSON envelope verbatim from Step 1 (plus an `enrichment_applied: true
95
178
  "reason": null,
96
179
  "meta": { "run_id": "...", "prompt_count": 24, "cluster_count": 2, "transcript_present": true },
97
180
  "enrichment_applied": false,
181
+ "findings_total": 6,
182
+ "findings_filed": [
183
+ { "title": "...", "mechanism": "backlog", "id": "BUIL-GUARD-m17dppm", "path": "/.../items/BUIL-GUARD-m17dppm.md" }
184
+ ],
185
+ "findings_unfiled": [ { "title": "...", "reason": "needs_input", "missing": ["why"] } ],
186
+ "filing_lint_ok": true,
98
187
  "closeout_status": "wrote_memory | queued_pending_lesson | no_durable_lesson",
99
188
  "closeout_reason": "human-readable reason",
100
189
  "closeout_error": null
101
190
  }
102
191
  ```
103
192
 
104
- # Output sections (exactly 9 match the spec)
193
+ `findings_total` must equal `len(findings_filed) + len(findings_unfiled)`. A
194
+ non-empty `findings_unfiled` with `filing_lint_ok: true` is a contradiction —
195
+ re-run Step 4 before returning.
196
+
197
+ # Output sections (EXACTLY 11 numbered — never 9, never add a 12th)
198
+
199
+ The retrospective has exactly 11 NUMBERED sections: 9 core + §10 + §11. Sections 1–9 are the core lessons record; §§8–11 are fully deterministic (the CLI derives them from the transcript with no LLM). Never add, drop, rename, or renumber a section.
200
+
201
+ **`## Filed findings` is an unnumbered appendix, not a 12th section.** It is a
202
+ disposition receipt for the findings named in §3, §4, §7, and §9 — a table of
203
+ ids and paths, carrying no analysis. It appends after §11 and is required
204
+ whenever any of those sections names a finding (Step 4 enforces this).
105
205
 
106
206
  1. **Lessons learned** — concrete content/process learnings from this run.
107
207
  2. **Key takeaways** — headline points worth remembering.
108
208
  3. **Recommendations** — next-action items; each is also an enforce-candidate.
109
- 4. **What could be done better** — failures, iterate-failures, friction.
209
+ 4. **What could be done better** — failures, iterate-failures, friction, plus transcript issue signals (errored tool calls, tracebacks) and per-tool error counts.
110
210
  5. **What went well** — judge-approved checkpoints, smooth phases.
111
211
  6. **What went well by accident** — split **Planned and earned** vs **Lucky / unplanned good**.
112
212
  7. **What should be enforced** — items the next run should not have to ask for. Anything prompted ≥2× lands here; every entry becomes an enforce-candidate file.
113
- 8. **User prompts this thread** — every user prompt + a "Prompted ≥2×" subsection clustering repeats.
114
- 9. **Issues (with causal tree)** — each judge-flagged failure or iterate-failure traced to root cause via 5-whys / causal-tree. Always name the missing system control — never blame the agent.
213
+ 8. **User prompts this thread** — every user prompt + a "Prompted ≥2×" subsection clustering repeats (the interaction-pattern / common-request signal).
214
+ 9. **Issues (with causal tree)** — each judge-flagged failure or iterate-failure PLUS transcript issue signals, traced to root cause via 5-whys / causal-tree. Always name the missing system control — never blame the agent.
215
+ 10. **Plugin & tooling observations** — deterministic per-tool / per-plugin / per-skill / per-subagent usage counts, and which tools returned errors (the objective plugin-performance signal). **Enrichment duty:** for each plugin exercised, narrate how it performed and name ONE concrete enhancement — a missing flag, a flaky path, a better default, or a script that would remove observed friction. Tie each to the usage evidence.
216
+ 11. **Deterministic-automation candidates** — recurring tool sequences that read like a manual ritual worth turning into a script/hook. Each routes to `enforce-from-retro/` (kind: automation) so Phase 6 Learn can draft the script. **Enrichment duty:** for the top candidates, name the concrete script/hook that would collapse the ritual and the exact path where it would live (e.g. `scripts/hooks/<name>.py`).
115
217
 
116
218
  # Constraint on the issues section
117
219
 
@@ -124,7 +226,7 @@ When you elaborate causal trees in section 9 during Step 2 enrichment:
124
226
 
125
227
  # Conditional depth — recursive-learning lenses (opt-in, default OFF)
126
228
 
127
- The 9 sections are the default and are sufficient for bounded execution / infra / audit runs. **Do NOT add sections.** Only when the run is **contested-meaning** — ANY of: (a) the product/feature is pre-public or at an architecture-direction decision point, (b) the run recommends redirect/reset on a major area, (c) ≥3 issues share a suspected single root cause — additionally apply these four lenses, each folded into an EXISTING section as enrichment bullets:
229
+ The 11 sections are the default and are sufficient for bounded execution / infra / audit runs. **Do NOT add sections.** Only when the run is **contested-meaning** — ANY of: (a) the product/feature is pre-public or at an architecture-direction decision point, (b) the run recommends redirect/reset on a major area, (c) ≥3 issues share a suspected single root cause — additionally apply these four lenses, each folded into an EXISTING section as enrichment bullets:
128
230
 
129
231
  1. **Project-maturity posture** → *Key takeaways*: one line — preserve / refine / redirect / reset — with the reason, and an explicit "from-scratch redesign NOT warranted" when the work is shipped/validated (guards against over-redesign).
130
232
  2. **Spec → current → desired gap** → *Lessons learned*: name any gap between intent, what shipped, and the desired end state that the pass/fail outcome hides (e.g. a v1 tradeoff with a deferred hardening successor).
@@ -138,3 +240,4 @@ Evidence for keeping this gated rather than always-on: a head-to-head judge test
138
240
  - Return concise JSON. No commentary outside the envelope.
139
241
  - Use ✅ / ⚠️ / ❓ markers in section bodies sparingly — only where status would otherwise be unclear.
140
242
  - Never propose changes to build-loop's own code from inside this agent. Surfaces flow to enforce-candidate files for human review.
243
+ - Never report a retrospective as complete while a finding it named sits unfiled. "I noted it" is not a disposition; an id or a path is.