@tyroneross/build-loop 0.36.1 → 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.
- package/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/build-loop-surface.mdc +12 -11
- package/.cursor/rules/skill-index.mdc +33 -0
- package/AGENTS.md +213 -34
- package/README.md +99 -31
- package/agents/advisor.md +4 -4
- package/agents/alignment-checker.md +2 -2
- package/agents/architecture-scout.md +4 -4
- package/agents/build-orchestrator.md +38 -36
- package/agents/database-assessor.md +10 -4
- package/agents/design-contract-specialist.md +8 -8
- package/agents/fact-checker.md +13 -3
- package/agents/fix-critique.md +2 -2
- package/agents/independent-auditor.md +60 -7
- package/agents/leak-scanner.md +82 -0
- package/agents/overfitting-reviewer.md +2 -2
- package/agents/plan-critic.md +1 -1
- package/agents/promotion-reviewer.md +5 -5
- package/agents/retrospective-synthesizer.md +138 -35
- package/agents/scope-auditor.md +82 -11
- package/agents/security-reviewer.md +55 -1
- package/agents/self-improvement-architect.md +17 -3
- package/agents/transcript-pattern-miner.md +5 -5
- package/agents/ui-validator.md +1 -1
- package/bin/build-loop-debugger.js +143 -0
- package/bin/build-loop-install.js +1 -4
- package/bin/build-loop-load-probe.js +345 -0
- package/codex-skills/build-loop/SKILL.md +28 -6
- package/commands/feedback.md +37 -0
- package/dist/src/interactive-verifier.d.ts +1 -14
- package/dist/src/interactive-verifier.d.ts.map +1 -1
- package/dist/src/interactive-verifier.js +6 -113
- package/dist/src/interactive-verifier.js.map +1 -1
- package/dist/src/quality.d.ts +5 -0
- package/dist/src/quality.d.ts.map +1 -0
- package/dist/src/quality.js +81 -0
- package/dist/src/quality.js.map +1 -0
- package/dist/src/storage.d.ts.map +1 -1
- package/dist/src/storage.js +37 -3
- package/dist/src/storage.js.map +1 -1
- package/docs/agent-surface-policy.md +35 -31
- package/docs/memory-setup.md +19 -0
- package/hooks/git/pre-push +65 -4
- package/hooks/hooks.json +95 -38
- package/hooks/pre-commit +20 -1
- package/hooks/pre-edit-rally-point.sh +10 -3
- package/hooks/session-start-codex-hook-trust.sh +30 -0
- package/hooks/session-start-git-hooks.sh +3 -1
- package/hooks/session-start-rally-point.sh +52 -4
- package/hooks/session-start-worktree-gc.sh +47 -94
- package/hooks/stop-transcript-sweep.sh +173 -0
- package/hooks/test_closeout.sh +14 -2
- package/package.json +8 -7
- package/scripts/README.md +1 -1
- package/scripts/_paths.py +65 -0
- package/scripts/groundwork_exchange.py +1012 -0
- package/scripts/install_memory.py +33 -1
- package/scripts/lessons_index/ingest.py +13 -2
- package/scripts/lessons_index/query.py +36 -13
- package/scripts/memory_context/__init__.py +108 -14
- package/scripts/memory_graph/__init__.py +5 -1
- package/scripts/project_resolver.py +42 -36
- package/scripts/sync_plugin_cache.py +37 -2
- package/skills/agent-rally-point/SKILL.md +46 -0
- package/skills/api-registry-bridge/SKILL.md +1 -1
- package/skills/architecture/dead/SKILL.md +1 -1
- package/skills/architecture/impact/SKILL.md +1 -1
- package/skills/architecture/review/SKILL.md +1 -1
- package/skills/architecture/rules/SKILL.md +3 -3
- package/skills/architecture/scan/SKILL.md +1 -1
- package/skills/architecture/trace/SKILL.md +1 -1
- package/skills/attribution-standard/SKILL.md +6 -6
- package/skills/auto-decision-capture/SKILL.md +31 -2
- package/skills/auto-finding-capture/SKILL.md +28 -1
- package/skills/build-loop/SKILL.md +131 -23
- package/skills/build-loop/fallbacks.md +16 -21
- package/skills/build-loop/phases/ui-validation.md +2 -2
- package/skills/build-loop/references/advisor-dispatch-ladder.md +1 -1
- package/skills/build-loop/references/apple-native-planning.md +1 -1
- package/skills/build-loop/references/autonomous-and-per-commit-modes.md +11 -5
- package/skills/build-loop/references/autonomy-dashboard.md +115 -0
- package/skills/build-loop/references/capability-routing.md +24 -2
- package/skills/build-loop/references/coordination.md +24 -6
- package/skills/build-loop/references/experiment-results-template.md +15 -3
- package/skills/build-loop/references/leadership.md +1 -1
- package/skills/build-loop/references/memory.md +14 -3
- package/skills/build-loop/references/modular-systems-pack.md +8 -0
- package/skills/build-loop/references/output-style.md +86 -0
- package/skills/build-loop/references/phase-1-assess.md +102 -2
- package/skills/build-loop/references/phase-2-plan.md +9 -1
- package/skills/build-loop/references/phase-3-execute.md +5 -2
- package/skills/build-loop/references/phase-4-review.md +85 -8
- package/skills/build-loop/references/phase-5-iterate.md +76 -8
- package/skills/build-loop/references/phase-6-learn.md +10 -17
- package/skills/build-loop/references/privileged-request-broker.md +254 -0
- package/skills/build-loop/references/resource-aware-execution.md +183 -0
- package/skills/build-loop/references/self-recursive-dev.md +2 -2
- package/skills/build-loop/references/status-output-format.md +207 -0
- package/skills/build-loop/references/verify-dispatch.md +56 -2
- package/skills/building-with-deepagents/SKILL.md +1 -1
- package/skills/claim-scope/SKILL.md +185 -0
- package/skills/color-engine/SKILL.md +103 -0
- package/skills/color-engine/_core.py +464 -0
- package/skills/color-engine/color_engine.py +175 -0
- package/skills/cost-rca/SKILL.md +61 -0
- package/skills/data-plane-worktrees/SKILL.md +139 -0
- package/skills/data-plane-worktrees/agents/openai.yaml +4 -0
- package/skills/database-practice/SKILL.md +200 -0
- package/skills/database-practice/references/diagnostic-queries.sql +126 -0
- package/skills/database-practice/references/vector-and-graph-tuning.md +208 -0
- package/skills/database-practice/scripts/db_table_map.py +1244 -0
- package/skills/database-practice/scripts/test_db_table_map.py +514 -0
- package/skills/debug-loop/SKILL.md +36 -6
- package/skills/debugging-memory/SKILL.md +32 -430
- package/skills/debugging-memory/references/pattern-extraction.md +4 -4
- package/skills/debugging-memory/references/search.md +32 -120
- package/skills/debugging-memory/references/store.md +32 -126
- package/skills/debugging-memory/references/subagent-integration.md +1 -1
- package/skills/decision-queue/SKILL.md +251 -0
- package/skills/decision-queue/assets/template.html +1242 -0
- package/skills/decision-queue/references/example-large-queue-batching.md +164 -0
- package/skills/decision-queue/scripts/regen_template_constants.py +160 -0
- package/skills/defenseclaw-bridge/SKILL.md +2 -2
- package/skills/defenseclaw-bridge/references/dc-config-mapping.md +2 -9
- package/skills/drain-proposals/SKILL.md +53 -0
- package/skills/focused-loop-builder/SKILL.md +31 -0
- package/skills/focused-loop-builder/references/spec-format.md +27 -0
- package/skills/handoff/SKILL.md +169 -8
- package/skills/ibr-bridge/SKILL.md +4 -1
- package/skills/knowledge/SKILL.md +26 -14
- package/skills/knowledge/references/review-mode.md +2 -3
- package/skills/knowledge/templates/madr-minimal.md +1 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/model-bakeoff/SKILL.md +48 -10
- package/skills/model-tiering/SKILL.md +92 -31
- package/skills/native-ax-driver/SKILL.md +38 -5
- package/skills/native-ax-driver/scripts/native_driver.py +278 -22
- package/skills/native-ax-driver/scripts/test_native_driver.py +227 -0
- package/skills/optimize/SKILL.md +1 -1
- package/skills/plugin-builder/SKILL.md +48 -1
- package/skills/plugin-builder/references/build-loop-phase-guidance.md +3 -4
- package/skills/plugin-builder/references/distribution.md +13 -2
- package/skills/plugin-builder/references/plugin-hygiene-lessons.md +2 -2
- package/skills/plugin-tests/SKILL.md +2 -2
- package/skills/recursive-retrospective/SKILL.md +1 -1
- package/skills/repo-closeout/SKILL.md +17 -0
- package/skills/repo-closeout/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/SKILL.md +179 -0
- package/skills/repo-maintenance/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/references/pre-public-hygiene.md +134 -0
- package/skills/repo-maintenance/references/repository-taxonomy.md +161 -0
- package/skills/repo-maintenance/references/safety-protocol.md +106 -0
- package/skills/repo-maintenance/references/stack-profiles.md +138 -0
- package/skills/repo-maintenance/scripts/audit_repo_maintenance.py +1198 -0
- package/skills/repo-maintenance/scripts/test_audit_repo_maintenance.py +506 -0
- package/skills/repository-intelligence/SKILL.md +189 -0
- package/skills/repository-intelligence/agents/openai.yaml +4 -0
- package/skills/repository-intelligence/references/assessment-rubric.md +88 -0
- package/skills/repository-intelligence/scripts/repository_inventory.py +347 -0
- package/skills/research/SKILL.md +12 -2
- package/skills/root-cause-analysis/SKILL.md +1 -1
- package/skills/runtime-parity-verification/SKILL.md +36 -1
- package/skills/security-methodology/SKILL.md +22 -9
- package/skills/security-methodology/references/agentic-handoff-templates.md +220 -0
- package/skills/security-methodology/references/cross-source-matrix.md +1 -1
- package/skills/security-methodology/references/owasp-agentic-top-10.md +1 -1
- package/skills/security-scan/SKILL.md +55 -15
- package/skills/self-improve/SKILL.md +70 -50
- package/skills/silent-assumptions/SKILL.md +341 -0
- package/skills/silent-assumptions/references/elicitation-detectors.md +342 -0
- package/skills/spec-writing/SKILL.md +128 -24
- package/skills/spec-writing/scripts/check_checklist.py +114 -15
- package/skills/ui-design/SKILL.md +6 -4
- package/skills/ui-design/references/color-engine.md +132 -0
- package/skills/ui-design/references/design-preferences-from-owned-apps.md +8 -8
- package/skills/ui-design/references/ui-guidance-sources.md +1 -1
- package/skills/ui-design/references/universal-design-principles.alt.md +2 -2
- package/plugin-artifacts/codex/.codex-plugin/plugin.json +0 -41
- package/plugin-artifacts/codex/AGENTS.md +0 -560
- package/plugin-artifacts/codex/BUILD-ARTIFACT.md +0 -5
- package/plugin-artifacts/codex/LICENSE +0 -202
- package/plugin-artifacts/codex/README.md +0 -313
- package/plugin-artifacts/codex/assets/build-loop-plugin-icon.png +0 -0
- package/plugin-artifacts/codex/docs/agent-surface-policy.md +0 -63
- package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/references/agent-role-taxonomy.md +0 -135
- package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/references/autonomy-config.md +0 -231
- package/plugin-artifacts/codex/references/backlog-system.md +0 -285
- package/plugin-artifacts/codex/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/references/coordination-file-template.md +0 -181
- package/plugin-artifacts/codex/references/coordination-rules.md +0 -552
- package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +0 -112
- package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +0 -102
- package/plugin-artifacts/codex/references/implementer-envelope-schema.md +0 -302
- package/plugin-artifacts/codex/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/references/leadership.md +0 -72
- package/plugin-artifacts/codex/references/memory-systems.md +0 -261
- package/plugin-artifacts/codex/references/memory.md +0 -313
- package/plugin-artifacts/codex/references/model-tier-mapping.md +0 -296
- package/plugin-artifacts/codex/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/references/research-trigger-policy.md +0 -140
- package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +0 -42
- package/plugin-artifacts/codex/references/self-review.md +0 -234
- package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +0 -90
- package/plugin-artifacts/codex/references/task-capture-policy.md +0 -68
- package/plugin-artifacts/codex/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +0 -65
- package/plugin-artifacts/codex/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/SKILL.md +0 -381
- package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +0 -82
- package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +0 -65
- package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +0 -549
- package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +0 -42
- package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +0 -267
- package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +0 -439
- package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +0 -177
- package/plugin-artifacts/codex/skills/build-loop/references/experiment-results-template.md +0 -101
- package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/memory.md +0 -313
- package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +0 -222
- package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +0 -98
- package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +0 -149
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +0 -32
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +0 -48
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +0 -60
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +0 -51
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +0 -71
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +0 -52
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +0 -202
- package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +0 -77
- package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +0 -234
- package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/skills/build-loop/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +0 -476
- package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +0 -239
- package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +0 -35
- package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +0 -100
- package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +0 -179
- package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +0 -40
- 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:
|
|
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("
|
|
49
|
-
7. `Bash("
|
|
50
|
-
8. `Bash("
|
|
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
|
|
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
|
|
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:
|
|
5
|
-
tier:
|
|
4
|
+
model: opus
|
|
5
|
+
tier: thinking
|
|
6
6
|
segment: governance_evaluation
|
|
7
7
|
tools: ["Read", "Glob", "Grep"]
|
|
8
8
|
---
|
package/agents/plan-critic.md
CHANGED
|
@@ -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:
|
|
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:
|
|
18
|
-
tier:
|
|
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
|
-
-
|
|
43
|
-
- Project constitution if present at
|
|
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
|
-
-
|
|
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
|
|
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
|
+
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
40
|
+
# Pipeline (run all six steps in order)
|
|
39
41
|
|
|
40
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
54
|
-
4.
|
|
55
|
-
5.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
117
|
+
**3c. Apply the filled plan. It writes the receipt for you.**
|
|
69
118
|
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
167
|
+
## Step 6 — Return the envelope
|
|
85
168
|
|
|
86
|
-
Return the
|
|
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
|
-
|
|
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
|
|
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.
|