@tyroneross/build-loop 0.30.3 → 0.34.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 (170) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +4 -4
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/AGENTS.md +9 -0
  6. package/README.md +8 -7
  7. package/agents/advisor.md +111 -0
  8. package/agents/alignment-checker.md +11 -0
  9. package/agents/assessment-orchestrator.md +1 -1
  10. package/agents/build-orchestrator.md +28 -33
  11. package/agents/fact-checker.md +1 -1
  12. package/agents/fix-critique.md +1 -1
  13. package/agents/independent-auditor.md +1 -1
  14. package/agents/overfitting-reviewer.md +1 -1
  15. package/agents/plan-critic.md +5 -4
  16. package/agents/promotion-reviewer.md +1 -1
  17. package/agents/retrospective-synthesizer.md +20 -3
  18. package/agents/scope-auditor.md +1 -1
  19. package/agents/security-reviewer.md +1 -1
  20. package/agents/self-improvement-architect.md +1 -1
  21. package/commands/{handoff.md → compose-handoff.md} +4 -4
  22. package/commands/{optimize.md → optimize-run.md} +1 -1
  23. package/commands/{agent-rally-point.md → rally-point.md} +3 -3
  24. package/commands/{research.md → research-run.md} +1 -1
  25. package/commands/setup-memory.md +32 -0
  26. package/commands/{plan-verify.md → verify-plan.md} +1 -1
  27. package/docs/agent-surface-policy.md +38 -20
  28. package/docs/memory-setup.md +19 -14
  29. package/hooks/_resolve_python.sh +28 -0
  30. package/hooks/closeout.sh +58 -0
  31. package/hooks/git/pre-push +69 -6
  32. package/hooks/hooks.json +34 -13
  33. package/hooks/post-push-closeout.sh +73 -0
  34. package/hooks/session-start-closeout.sh +69 -0
  35. package/hooks/session-start-memory.sh +27 -0
  36. package/hooks/session-start-plugin-heal.sh +33 -0
  37. package/hooks/test_closeout.sh +124 -0
  38. package/package.json +7 -4
  39. package/plugin-artifacts/codex/.codex-plugin/plugin.json +41 -0
  40. package/plugin-artifacts/codex/AGENTS.md +499 -0
  41. package/plugin-artifacts/codex/BUILD-ARTIFACT.md +5 -0
  42. package/plugin-artifacts/codex/LICENSE +202 -0
  43. package/plugin-artifacts/codex/README.md +404 -0
  44. package/plugin-artifacts/codex/docs/agent-surface-policy.md +63 -0
  45. package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +62 -0
  46. package/plugin-artifacts/codex/references/agent-role-taxonomy.md +101 -0
  47. package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +161 -0
  48. package/plugin-artifacts/codex/references/autonomy-config.md +231 -0
  49. package/plugin-artifacts/codex/references/capability-routing.md +182 -0
  50. package/plugin-artifacts/codex/references/codex-subagents.md +106 -0
  51. package/plugin-artifacts/codex/references/coordination-file-template.md +181 -0
  52. package/plugin-artifacts/codex/references/coordination-rules.md +283 -0
  53. package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +112 -0
  54. package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +102 -0
  55. package/plugin-artifacts/codex/references/implementer-envelope-schema.md +302 -0
  56. package/plugin-artifacts/codex/references/intent-capability-pack.md +257 -0
  57. package/plugin-artifacts/codex/references/intent-exploration-prompts.md +96 -0
  58. package/plugin-artifacts/codex/references/leadership.md +72 -0
  59. package/plugin-artifacts/codex/references/memory-systems.md +238 -0
  60. package/plugin-artifacts/codex/references/memory.md +297 -0
  61. package/plugin-artifacts/codex/references/model-tier-mapping.md +257 -0
  62. package/plugin-artifacts/codex/references/modular-systems-pack.md +96 -0
  63. package/plugin-artifacts/codex/references/phase-1-assess.md +231 -0
  64. package/plugin-artifacts/codex/references/phase-2-plan.md +77 -0
  65. package/plugin-artifacts/codex/references/phase-3-execute.md +47 -0
  66. package/plugin-artifacts/codex/references/phase-4-review.md +320 -0
  67. package/plugin-artifacts/codex/references/phase-5-iterate.md +71 -0
  68. package/plugin-artifacts/codex/references/phase-6-learn.md +56 -0
  69. package/plugin-artifacts/codex/references/recent-design-structures.md +274 -0
  70. package/plugin-artifacts/codex/references/research-trigger-policy.md +140 -0
  71. package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +42 -0
  72. package/plugin-artifacts/codex/references/self-review.md +234 -0
  73. package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +90 -0
  74. package/plugin-artifacts/codex/references/task-capture-policy.md +68 -0
  75. package/plugin-artifacts/codex/references/ui-io-contract.md +116 -0
  76. package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +65 -0
  77. package/plugin-artifacts/codex/skills/build-loop/SKILL.md +372 -0
  78. package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +82 -0
  79. package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +65 -0
  80. package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +549 -0
  81. package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +42 -0
  82. package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +267 -0
  83. package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
  84. package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +439 -0
  85. package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
  86. package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +182 -0
  87. package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +106 -0
  88. package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +161 -0
  89. package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +177 -0
  90. package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +72 -0
  91. package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +257 -0
  92. package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +96 -0
  93. package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +72 -0
  94. package/plugin-artifacts/codex/skills/build-loop/references/memory.md +297 -0
  95. package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +96 -0
  96. package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +129 -0
  97. package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +98 -0
  98. package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +231 -0
  99. package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +77 -0
  100. package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +47 -0
  101. package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +320 -0
  102. package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +71 -0
  103. package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +56 -0
  104. package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +274 -0
  105. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
  106. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
  107. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
  108. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
  109. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
  110. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
  111. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
  112. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
  113. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
  114. package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +77 -0
  115. package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +234 -0
  116. package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +116 -0
  117. package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
  118. package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
  119. package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +35 -0
  120. package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +96 -0
  121. package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
  122. package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +40 -0
  123. package/scripts/_paths.py +59 -13
  124. package/scripts/build_codex_plugin_artifact.py +314 -0
  125. package/scripts/check_cache_sync.py +1 -1
  126. package/scripts/install_memory.py +11 -3
  127. package/scripts/prune_plugin_cache.py +225 -11
  128. package/scripts/sync_navgator_lessons.py +25 -0
  129. package/scripts/sync_plugin_cache.py +66 -36
  130. package/skills/agent-rally-point/SKILL.md +1 -1
  131. package/skills/agent-rally-watcher/SKILL.md +1 -1
  132. package/skills/build-loop/SKILL.md +11 -155
  133. package/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
  134. package/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
  135. package/skills/build-loop/references/capability-routing.md +4 -3
  136. package/skills/build-loop/references/codex-subagents.md +8 -0
  137. package/skills/build-loop/references/coordination.md +1 -1
  138. package/skills/build-loop/references/intent-capability-pack.md +88 -1
  139. package/skills/build-loop/references/memory.md +17 -2
  140. package/skills/build-loop/references/phase-1-assess.md +13 -0
  141. package/skills/build-loop/references/phase-2-plan.md +1 -1
  142. package/skills/build-loop/references/phase-4-review.md +12 -0
  143. package/skills/build-loop/references/phase-6-learn.md +1 -1
  144. package/skills/build-loop/references/self-review.md +4 -2
  145. package/skills/build-loop/templates/codex-worker-prompt.md +41 -34
  146. package/skills/handoff/SKILL.md +3 -3
  147. package/skills/loop-builder/SKILL.md +98 -0
  148. package/skills/loop-builder/presets/active-project-evidence.yaml +97 -0
  149. package/skills/loop-builder/presets/generic-artifact-loop.yaml +95 -0
  150. package/skills/loop-builder/presets/presentation-audit.yaml +96 -0
  151. package/skills/loop-builder/presets/research-synthesis.yaml +96 -0
  152. package/skills/loop-builder/presets/source-ingestion-raw-data-audit.yaml +96 -0
  153. package/skills/loop-builder/references/spec-format.md +80 -0
  154. package/skills/loop-builder/scripts/loop_builder.py +346 -0
  155. package/skills/model-tiering/SKILL.md +65 -40
  156. package/skills/optimize/SKILL.md +2 -2
  157. package/skills/plan-verify/SKILL.md +1 -1
  158. package/skills/plugin-builder/references/distribution.md +8 -0
  159. package/skills/research/SKILL.md +33 -6
  160. package/skills/runtime-parity-verification/SKILL.md +51 -0
  161. package/skills/spec-writing/SKILL.md +19 -0
  162. package/templates/memory/README.md +65 -0
  163. package/templates/memory/charter.md.template +46 -0
  164. package/templates/memory/manifest.json +24 -4
  165. package/codex-skills/debug-loop/SKILL.md +0 -18
  166. package/codex-skills/handoff/SKILL.md +0 -22
  167. package/codex-skills/knowledge/SKILL.md +0 -21
  168. package/codex-skills/optimize/SKILL.md +0 -18
  169. package/codex-skills/research/SKILL.md +0 -18
  170. /package/commands/{knowledge-review.md → review-knowledge.md} +0 -0
@@ -19,8 +19,8 @@ A 5-phase development loop with a mandatory Phase 6: assess state and criteria,
19
19
  Internal modes:
20
20
 
21
21
  - **Build** (default): Full 5-phase loop plus mandatory Phase 6 Learn — triggered by implementation, fix, refactor, migrate, or update language
22
- - **Optimize**: Metric-driven optimization loop — triggered by "speed up", "reduce", "improve" + a mechanical metric (`/build-loop:optimize` as a direct override)
23
- - **Research**: Pre-decision analysis, outputs a research packet, no commits — triggered by "research", "evaluate", "compare", "should I" (`/build-loop:research` as a direct override)
22
+ - **Optimize**: Metric-driven optimization loop — triggered by "speed up", "reduce", "improve" + a mechanical metric (`/build-loop:optimize-run` as a direct override)
23
+ - **Research**: Pre-decision analysis, outputs a research packet, no commits — triggered by "research", "evaluate", "compare", "should I" (`/build-loop:research-run` as a direct override)
24
24
  - **Debug**: Deep iterative root-cause investigation — triggered by symptom language; also auto-invoked inside the loop on Review-B failures (`/build-loop:debug` as a direct override)
25
25
  - **Test**: Static plugin-test suite — triggered by "test plugin", "validate plugin" (`/build-loop:test` as a direct override)
26
26
 
@@ -38,158 +38,14 @@ To raise the cap toward the hard ceiling, set in `.build-loop/config.json`:
38
38
 
39
39
  Values above 12 are clamped. Values above `cpu_count−2` are clamped to `cpu_count−2` to leave headroom for the orchestrator and host OS.
40
40
 
41
- ## Autonomous Mode (Queue-Drain Loop)
41
+ ## Autonomous Mode + Per-Commit Mode
42
42
 
43
- Autonomous mode generalizes Phase 5 Iterate into a self-replenishing worker that drains its own `ux-queue/` + `issues/` + `proposals/`, alignment-checks each item against the original intent, executes the aligned subset, and commits in batches until the queue is empty or the wall-clock budget elapses. Default since this mode shipped (`--autonomous=false` opts back to classic one-pass).
43
+ Both are conditional modes their flag tables, budget/iteration caps, question-timeout rules, self-recursive detection, and the per-commit dispatch contract (incl. the GAP-1 parent-dispatch audit + E3 Learn/retro contract) load on demand from `references/autonomous-and-per-commit-modes.md`. Read it when:
44
44
 
45
- **End-of-run backlog/issues drain SHIPPED DEFAULT 2026-06-04**: every run now auto-drains `.build-loop/issues/` then `.build-loop/backlog/` at end-of-thread without asking. Reversible per-repo via `.build-loop/config.json`:
45
+ - the invocation carries `--long` / `--budget` / `--autonomous=false`, or the goal text matches a long-running keyword (`overnight`, `large-scale`, `multi-day`, …) **Autonomous Mode** detail;
46
+ - `state.json.selfRecursive.enabled` is true, or the invocation carries `--per-commit` / `--no-per-commit` → **Per-Commit Mode** detail.
46
47
 
47
- ```json
48
- { "sessionPrefs": { "continueFromQueues": "never" } }
49
- ```
50
-
51
- `PRODUCTION`/`DECISION`-classified items still surface (not auto-executed). The continuation runs the same alignment-checker + scope-auditor + independent-auditor wiring as the in-run iterate loop. Stop conditions: iterate-cap (25 autonomous / 5 classic), budget exhausted, PRODUCTION encountered, 5 consecutive iterate failures, explicit user pause. Surfaced in the run report's `## Queue continuation` section.
52
-
53
- ### Flag surface
54
-
55
- | Invocation | Effect |
56
- |---|---|
57
- | `/build-loop:run "goal text"` | default mode, 2h budget, autonomous=true |
58
- | `/build-loop:run --long "goal text"` | long mode, 8h budget |
59
- | `/build-loop:run --budget 4h "goal text"` | custom budget (overrides `--long`) |
60
- | `/build-loop:run --budget 30m "goal text"` | accepts `30s`, `30m`, `4h`, or bare integer seconds |
61
- | `/build-loop:run --autonomous=false "goal text"` | classic single-pass; queue items become `followup/` |
62
- | `/build-loop:run "overnight refactor of auth ..."` | keyword `overnight` → long mode, 8h |
63
-
64
- **Flag precedence (strict, top wins):**
65
-
66
- 1. `--budget <duration>` — explicit duration always wins; mode tagged `custom`.
67
- 2. `--long` — sets mode `long`, budget 8h.
68
- 3. Keyword detection in goal text — only when `--long` not explicitly set.
69
- 4. Default — mode `default`, budget 2h, autonomous=true.
70
-
71
- `--autonomous=false` is orthogonal: it can combine with any budget flag but disables the queue-drain loop entirely. With autonomous off, `--budget` still tracks wall-clock but the orchestrator runs classic Phase 1–6 once and reports.
72
-
73
- ### Keyword fallback
74
-
75
- Case-insensitive whole-word match against the goal text (or `intent.update_intent`). Detection runs ONLY when `--long` is not explicit on the command line. The flag always wins over keyword inference.
76
-
77
- | Keyword | Example phrasings |
78
- |---|---|
79
- | `long` | "long refactor of …" |
80
- | `long-running` | "long-running migration" |
81
- | `overnight` | "overnight build" |
82
- | `large-scale` | "large-scale rewrite" |
83
- | `multi-day` | "multi-day backfill" |
84
-
85
- Keyword list is configurable via `.build-loop/config.json.autonomy.keywordsLong[]`. The default list above is hard-coded in the orchestrator.
86
-
87
- ### Budget tracking
88
-
89
- The orchestrator writes `state.execution.budget` at autonomous-mode start:
90
-
91
- ```json
92
- {
93
- "mode": "default | long | custom",
94
- "started_at": "<iso8601 UTC>",
95
- "deadline_at": "<iso8601 UTC>",
96
- "last_checkin_at": "<iso8601 UTC> | null",
97
- "commits_since_push": 0,
98
- "checkin_interval_pct": 50
99
- }
100
- ```
101
-
102
- `scripts/budget_check.py` reads this block at every iterate-loop entry, every commit, and every phase boundary, returning a routing envelope (`continue | checkin | finalize_and_stop`). The script is informational — exit 0 always; sub-5ms compute.
103
-
104
- **Resume contract**: when a budget block exists and the run resumes via `--resume <run_id>`, the orchestrator MUST reuse the original `deadline_at`. A 2h budget that crashed at 1h59m does NOT get a fresh 2h. `scripts/resume_resolver.py._resolve_budget_on_resume()` is the single source of truth for this rule and surfaces the preserved budget under `budget_resume.preserve_deadline: true`.
105
-
106
- ### Iteration caps
107
-
108
- | Mode | Per-build cap | Per-item cap |
109
- |---|---|---|
110
- | Classic (autonomous=false) | 5 | n/a |
111
- | Autonomous default | 25 | 3 same-verdict |
112
- | Autonomous long | 25 | 3 same-verdict |
113
-
114
- `maxIterateAttemptsAutonomous` is configurable in `.build-loop/config.json.autonomy.maxIterateAttemptsAutonomous`.
115
-
116
- ### Question timeout (autonomous auto-decide)
117
-
118
- In autonomous / `--long` mode a question that would otherwise block on the human auto-resolves if unanswered within a window, so an unattended run never stalls. When the orchestrator surfaces such a question it states a **recommended default** + a deadline; `scripts/question_timeout.py` is consulted (e.g. on a `ScheduleWakeup` resume) and returns `answered | take_default | wait`. On `take_default` the orchestrator takes the recommended option, records it to `state.execution.autonomousDefaults[]` + `auto-decision-capture`, continues, and lists every auto-decided question in the end-of-run readback for override (prefer the reversible option when deciding).
119
-
120
- **Never auto-resolves — waits indefinitely:** production push, destructive/irreversible delete, and anything the autonomy gate verdicts `confirm`/`block` (gates #1–#2 in `agents/build-orchestrator.md`). Only reversible / `user_impact: major` decisions (gate #3) and steering clarifications time out — the single production gate is preserved.
121
-
122
- Config (`.build-loop/config.json.autonomy`): `questionTimeoutMinutes` (default 10), `onTimeout` (`decide_default` default | `wait`).
123
-
124
- ### Per-Phase A constraint
125
-
126
- Phase A (current ship) wires queue drain + alignment-check + time budget. **Pushes stay manual** — `scripts/autonomous_push.py` and the K-commit batch-push policy ship in Phase B. The `should_push_now` field returned by `budget_check.py` is informational in Phase A; the orchestrator surfaces it in check-ins but does not push autonomously yet.
127
-
128
- ## Per-Commit Mode (Self-Recursive Builds)
129
-
130
- Per-commit mode splits a multi-commit build into one independent orchestrator dispatch per commit, so each commit reviews and lands cleanly before the next one starts. It activates automatically when the working directory IS the runtime — that is, when the user is editing the build-loop plugin itself (or any plugin whose runtime symlink points back to the working tree). It can also be explicitly opted into or out of via skill arguments.
131
-
132
- ### Detection
133
-
134
- Phase 1 Assess writes `selfRecursive.enabled: true|false` to `.build-loop/state.json` (commit 1 wired this via `scripts/detect_self_recursive.py`). The skill body MUST read this field BEFORE deciding which dispatch shape to use. If the field is absent, treat it as `false`.
135
-
136
- ### Mode Resolution
137
-
138
- | Skill arg | `selfRecursive` | Resulting mode |
139
- |---|---|---|
140
- | `--per-commit` (explicit) | either | per-commit |
141
- | `--no-per-commit` (explicit) | either | single-orchestrator |
142
- | (none) | true | per-commit (default for self-recursive) |
143
- | (none) | false | single-orchestrator (today's behavior) |
144
-
145
- Passing both `--per-commit` and `--no-per-commit` is a user error — fail loud with a one-line message naming the conflict and stop before any dispatch.
146
-
147
- ### Dispatch Contract (Per-Commit Mode)
148
-
149
- 1. **Plan first, dispatch many.** The skill body invokes a single planning orchestrator (Phase 1 Assess + Phase 2 Plan only). Its return must include a per-commit work list at `.build-loop/per-commit-plan.json` with this exact JSON shape:
150
-
151
- ```json
152
- {
153
- "run_id": "run_<UTC>_<hash>",
154
- "commits": [
155
- {
156
- "id": "c1",
157
- "subject": "feat(scripts): add foo helper",
158
- "scope": "...",
159
- "files_planned": ["scripts/foo.py", "tests/test_foo.py"],
160
- "spec": "verbatim packet for the implementer orchestrator",
161
- "depends_on": []
162
- }
163
- ],
164
- "branch": "feat/...",
165
- "from_branch": "main"
166
- }
167
- ```
168
-
169
- 2. **Per-commit orchestrator dispatch.** For each commit in the plan (respecting `depends_on`), the skill body dispatches a fresh `Agent(subagent_type="build-loop:build-orchestrator", ...)` carrying ONLY that commit's packet plus a `PER_COMMIT_DISPATCH: { commit_id, run_id, prior_commit_hashes }` prompt prefix. Each dispatched orchestrator runs Phase 3 Execute + Phase 4 Review for ITS commit only, then commits and returns. The dispatched orchestrator's behavior on the prefix is documented in `agents/build-orchestrator.md` §0a.
170
-
171
- 3. **Aggregate.** The skill body collects each orchestrator's return envelope and writes a final report combining all commits' results. On partial failure (commit N fails), do NOT dispatch downstream commits; retain `.build-loop/per-commit-plan.json` so a subsequent `/build-loop:run --resume` invocation can pick up where it stopped. **Parent-dispatch contract (GAP-1):** the dispatcher (this skill body) HAS the Agent tool, so it is the parent that owes the audit. For every returned envelope whose `auditor_status` is `not-run:parent-must-dispatch` or `cross-vendor-deferred`, the dispatcher MUST — before declaring that commit/run review-complete — dispatch `Agent(subagent_type="build-loop:independent-auditor")` on that commit's diff range, append the verdict to `.build-loop/judge-decisions.json`, and re-run `write_run_entry --scope build` so the review-completeness gate passes. A nested per-commit orchestrator cannot audit itself; the audit is the dispatcher's responsibility, not an optional step.
172
-
173
- **Parent owes Phase 6 Learn + retrospective (E3).** A stop-early dispatch that never reaches Phase 4 Review-G can't run Phase 6 Learn or the post-push retro — so the dispatching parent owes them at close, under the same parent-dispatch contract as GAP-1 (not optional, name the owner at dispatch). Full contract: `agents/build-orchestrator.md` §Phase 4 A (E3 block).
174
-
175
- ### State.json schema
176
-
177
- The per-commit dispatcher tracks its own progress under a `perCommit` block alongside the existing `execution` block:
178
-
179
- ```json
180
- {
181
- "perCommit": {
182
- "enabled": true,
183
- "mode_source": "self_recursive_default|explicit_flag|opt_out",
184
- "plan_path": ".build-loop/per-commit-plan.json",
185
- "completed": [{"commit_id": "c1", "hash": "abc123", "completed_at": "..."}],
186
- "in_flight": "c2",
187
- "queued": ["c3"]
188
- }
189
- }
190
- ```
191
-
192
- M2's `execution.iterate_attempt` continues to track per-commit-orchestrator attempt counters (each dispatched orchestrator manages its own iterate counter) — do not duplicate iteration tracking inside `perCommit`.
48
+ Default behavior with none of those signals: classic single-pass Phase 1–6, 2h budget, autonomous queue-drain on. The end-of-run `issues/` then `backlog/` drain is a SHIPPED DEFAULT (2026-06-04), reversible per-repo via `.build-loop/config.json` `sessionPrefs.continueFromQueues: "never"`.
193
49
 
194
50
  ## Scope Check
195
51
 
@@ -357,13 +213,13 @@ Key steps: subagent-driven-development → model assignment (Sonnet default) →
357
213
 
358
214
  ## Phase 4: Review — Critic, Validate, Fact-Check, Simplify, Auto-Resolve, Report
359
215
 
360
- Seven sub-steps run in order: A Critic → B Validate → C Optimize (opt-in) → D Fact-Check → E Simplify → F Auto-Resolve → G Report. F drains non-destructive items via `scripts/autonomy_gate.py` (auto/warn/confirm/block routing). G is final-pass-only.
216
+ Seven sub-steps run in order (A–G): Critic → Validate → Optimize (opt-in) → Fact-Check → Simplify → Auto-Resolve → Report. F (Auto-Resolve) drains non-destructive items via `scripts/autonomy_gate.py` (auto/warn/confirm/block routing). G (Report) is final-pass-only.
361
217
 
362
218
  Key steps: independent-auditor (build scope) adversarial read → build-loop-owned UI validation when UI changed → code-based graders → live smoke gate → LLM judges → fact-checker + mock-scanner + architecture-rules in parallel → simplify → autonomy gate queue → final scorecard + run entry → **non-gating post-push retrospective dispatch** (`build-loop:retrospective-synthesizer` writes the 9-section `.build-loop/retrospectives/<date>/<run-id>.md` + ≤5-line summary surfaced inline; enforce-candidates land at `.build-loop/proposals/enforce-from-retro/` for human review — never auto-promoted; fire-and-continue, run-close is NOT delayed). On self-recursive runs, G appends `## Self-modifications (readback)` listing every self-modification attempted this run — file, what/why, gate verdict, additional-review finding — so the human sees results at the end without the loop stopping. Full spec in `agents/build-orchestrator.md` §G.
363
219
 
364
220
  **Load `skills/build-loop/references/phase-4-review.md`** for sub-step details, gate matrices, routing rules, and the full Sub-step F Auto-Resolve protocol (all 4 verdict arms including `warn` exit-0 behavior).
365
221
 
366
- **Independent commit auditor — boundary gate + dispatched judge.** Single consolidated auditor (2026-05-23 — replaces retired `commit-auditor` and earlier retired `sonnet-critic`). Two surfaces share the same context-gathering procedure and verdict taxonomy: (1) a PreToolUse Bash hook fires `scripts/audit_before_commit.py` on every `git commit` regardless of who initiates it (manual, Codex, build-loop, IDE) — deterministic packet-builder, hard-blocks (exit 2) on staged secrets and merge-conflict markers, bypass via `BUILDLOOP_AUDIT_BYPASS=1`; (2) the `independent-auditor` agent dispatches at Phase 3 chunk-close (chunk advisory) and Phase 4 Review-A (build scope) for LLM-grade judgment. Four verdicts: `yay (approve)` / `nay (reject)` / `suggest_correction` / `look_again`. **Auditor dispatch ladder (GAP-1):** a *nested* orchestrator (dispatched as a subagent, or per-commit mode) has no Agent tool and cannot dispatch the auditor — it walks `dispatched-agent → peer-host (rally / codex exec) → not-run:parent-must-dispatch`, records the chosen rung in `auditor_status`, and **never** lets inline self-reasoning masquerade as the independent auditor. A `not-run:parent-must-dispatch` run is not review-complete: the dispatching parent owes the audit before Report. Full reference: `skills/build-loop/references/independent-auditor.md` + `references/phase-4-review.md` §"Sub-step A" + `agents/independent-auditor.md`.
222
+ **Independent commit auditor — boundary gate + dispatched judge.** Single consolidated auditor (2026-05-23 — replaces retired `commit-auditor` and earlier retired `sonnet-critic`). Two surfaces share the same context-gathering procedure and verdict taxonomy: (1) a PreToolUse Bash hook fires `scripts/audit_before_commit.py` on every `git commit` regardless of who initiates it (manual, Codex, build-loop, IDE) — deterministic packet-builder, hard-blocks (exit 2) on staged secrets and merge-conflict markers, bypass via `BUILDLOOP_AUDIT_BYPASS=1`; (2) the `independent-auditor` agent dispatches at Phase 3 chunk-close (chunk advisory) and Phase 4 Review-A (build scope) for LLM-grade judgment. Four verdicts: `yay (approve)` / `nay (reject)` / `suggest_correction` / `look_again`. **Auditor dispatch ladder (GAP-1):** a *nested* orchestrator (dispatched as a subagent, or per-commit mode) has no Agent tool and cannot dispatch the auditor — it walks `dispatched-agent → peer-host (rally / codex exec) → not-run:parent-must-dispatch`, records the chosen rung in `auditor_status`, and **never** lets inline self-reasoning masquerade as the independent auditor. A `not-run:parent-must-dispatch` run is not review-complete: under the parent-dispatch contract the dispatching parent owes the audit before Report. Full reference: `skills/build-loop/references/independent-auditor.md` + `references/phase-4-review.md` §"Sub-step A" + `agents/independent-auditor.md`.
367
223
 
368
224
  ## Phase 5: Iterate — Fix Review Failures + UX Queue (up to 5x)
369
225
 
@@ -383,11 +239,11 @@ Key steps: recurring-pattern-detector (Haiku; reads `state.json.runs[]` AND `.bu
383
239
 
384
240
  ## Memory — Global and Project-Scoped
385
241
 
386
- One consolidated long-term tree: `~/dev/git-folder/build-loop-memory/`. Project-specific durable memory lives under `projects/<slug>/...`; cross-project lessons/design/debugging/product memory lives in the matching top-level lane. Every build runs `scripts/context_bootstrap.py` at Phase 1 Assess, which reads canonical root/project `MEMORY.md` and `constitution.md` files, canonical indexes/folders through `memory_facade.py`, repo-local `.build-loop/` context, Codex memory at `~/.codex/memories`, and best-effort Rally/coordination state when relevant. Live handoff state is written separately by `scripts/context_snapshot.py` under `.build-loop/context/`; snapshots are not durable memory unless Review-G promotes a reusable decision or lesson. Writes go to exactly one canonical memory lane based on scope. Legacy paths (`~/.build-loop/memory`, `.episodic/decisions`, and `build-loop-memory/decisions/<project>`) are migration/archive inputs only.
242
+ One consolidated long-term tree: `~/dev/git-folder/build-loop-memory/`. Project-specific durable memory lives under `projects/<slug>/...`; cross-project lessons/design/debugging/product memory lives in the matching top-level lane. Every build runs `scripts/context_bootstrap.py` at Phase 1 Assess, which reads the store-root `INDEX.md` first, then root/project `constitution.md` / `MEMORY.md` where present, canonical indexes/folders through `memory_facade`, repo-local `.build-loop/` context, Codex memory at `~/.codex/memories`, and best-effort Rally/coordination state when relevant. Live handoff state is written separately by `scripts/context_snapshot.py` under `.build-loop/context/`; snapshots are not durable memory unless Review-G promotes a reusable decision or lesson. Writes go to exactly one canonical memory lane based on scope. Legacy paths (`~/.build-loop/memory`, `.episodic/decisions`, and `build-loop-memory/decisions/<project>`) are migration/archive inputs only.
387
243
 
388
244
  Routing rule: "Would this apply to a different project?" Yes → global. No → project. Ambiguous → ask the user once.
389
245
 
390
- Append-only memory contract: (1) steering answers from `AskUserQuestion` append to `build-loop-memory/projects/<slug>/decisions/` immediately via `auto-decision-capture` — do not let them die in context; (2) every run appends a milestone at Review-G via `scripts/append_milestone.py` — the permanent progress record, never rewritten; (3) Phase 1 flags staleness when the latest milestone predates HEAD (`scripts/memory_staleness_check.py`). Full write protocol in `references/memory.md`.
246
+ Append-only memory contract: (1) steering answers from `AskUserQuestion` append to `build-loop-memory/projects/<slug>/decisions/` immediately via the decision writer — do not let them die in context; (2) durable lessons/decisions are written when discovered, then deduped at Review-G; (3) every run appends a milestone at Review-G via `scripts/append_milestone.py` when warranted — the permanent progress record, never rewritten; (4) Phase 1 flags staleness when the latest memory update/milestone predates HEAD (`scripts/memory_staleness_check.py`). Full recall-optimized write protocol in `references/memory.md` and `build-loop-memory/references/2026-06-11-memory-discipline-prompt.md` (`version: 2026-06-11.1`).
391
247
 
392
248
  **Load `skills/build-loop/references/memory.md`** for the full routing rule, write timing, read timing, and memory type taxonomy.
393
249
 
@@ -0,0 +1,62 @@
1
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
2
+
3
+ # Advisor dispatch ladder (Phase 2 plan synthesis at Frontier)
4
+
5
+ The Advisor (Fable) is the Frontier standing role that **authors and re-plans** the Phase 2 plan synthesis. Generating a plan is harder than evaluating one, so the deepest reasoning pays here — but the Advisor is **pull-based**: summoned only when stakes-gating trips, not every run. This ladder enforces that the plan is authored at Frontier *when it matters*, without breaking the runs where it doesn't.
6
+
7
+ It deliberately **mirrors the GAP-1 independent-auditor ladder** (`phase-4-review.md` §"Sub-step A"). Same shape, same honesty discipline, an analogous `advisor_status` field. If you know that ladder, you know this one.
8
+
9
+ ## When the ladder is evaluated (stakes-gating)
10
+
11
+ The orchestrator walks this ladder at the Phase 2 plan-synthesis step **only when** any of these objective triggers fire:
12
+
13
+ - `state.json.synthesisDensity > 5` (synthesis-dense plan), or
14
+ - `triggers.riskSurfaceChange` (security/persistence/runtime/deploy/trust boundary), or
15
+ - `stakes >= medium` (from the commander's-intent posture / charter), or
16
+ - an explicit `dispatch_tier: frontier` on any work item in the draft plan.
17
+
18
+ If none trips, the ladder is skipped entirely — the orchestrator synthesizes the plan inline as today (most runs stay single-context; this respects the multi-agent-handoff risk by not decomposing more than needed). **Triggers are objective signals, never self-reported confidence** (models are systematically overconfident).
19
+
20
+ ## The four rungs (record `advisor_status` honestly)
21
+
22
+ Dispatching the Advisor via `Agent(subagent_type="build-loop:advisor")` requires the Agent tool. A *nested* orchestrator (dispatched as a subagent — Mode B — or running per-commit mode) does **not** have the Agent tool, because the harness blocks sub-subagents. Walk the ladder and record `advisor_status`:
23
+
24
+ 1. **Rung 0 — own context already Frontier** (the orchestrator is itself running on Fable, e.g. `/build-loop:run` while the session model is Fable): **synthesize the plan inline** — it is *already* Frontier, no handoff needed. → `advisor_status: inline-frontier`. Zero added cost.
25
+
26
+ 2. **Rung 1 — Agent tool present** (top-level / Mode A, own context not already Frontier): **dispatch the Fable Advisor** (`Agent(subagent_type="build-loop:advisor")`) to author/re-plan, then verify via plan-critic + scope-auditor. → `advisor_status: ran:dispatched-agent`.
27
+
28
+ 3. **Rung 2 — no Agent tool, peer host reachable** (nested Mode B, but a peer host — rally channel / `codex exec` — can execute; reachable because the orchestrator retains Bash even when nested): **run the Advisor as a peer process** over the same channel the cross-vendor reviewer uses. Reconcile the peer's plan + envelope into the plan artifact. → `advisor_status: ran:peer-host(<host>)`. Prefer this over the fallback whenever a peer host can execute (fresh-context synthesis is plausibly *higher quality*, not merely cheaper — see "Quality, not only cost" below).
29
+
30
+ 4. **Rung 3 — none reachable** (no Agent tool, no peer host): **synthesize inline on the orchestrator's own model (Opus)**, labeled honestly. → `advisor_status: fallback:inline-opus`.
31
+
32
+ ## Non-breaking guarantee
33
+
34
+ **Rung 3 IS today's behavior** — the orchestrator synthesizing the plan inline on Opus. The floor of this ladder equals the current state; it is strictly better whenever a dispatch path (Rung 1/2) or an already-Frontier context (Rung 0) is reachable. The handoff cost fires *only* in Rung 1/2 — i.e., only when the active context isn't already Frontier — so you pay it exactly where it buys an upgrade and never where planning is already Frontier. Worst case equals current; there is no regression path.
35
+
36
+ ## Quality, not only cost
37
+
38
+ Dispatch is a **quality lever**, not just a cost knob. Context-separation evidence (⚠️ 2026 cross-context-review lead, directionally consistent with the corroborated self-correction literature: correction needs *external* feedback; intrinsic self-correction degrades accuracy) indicates synthesis in a *fresh* context beats same-session work. So Rungs 1/2 (fresh-context dispatch) are plausibly *higher quality* than Rung 0/3 inline — inline is a genuine quality compromise, taken only when dispatch is unreachable. The Advisor is a **separate agent**, never the executor self-reflecting.
39
+
40
+ ## Ledger row per Advisor action (the instrument)
41
+
42
+ The orchestrator (single writer) appends one row to `.build-loop/agent-ledger.jsonl` per Advisor action via `scripts/agent_ledger.py`:
43
+
44
+ ```
45
+ action: author | re-plan
46
+ agent: advisor · tier: frontier · model: <resolved id (fable / gpt-5.x / …)>
47
+ rung: 0|1|2|3 · status: pass|fail|partial · trigger: <synthesisDensity>5 | riskSurfaceChange | stakes>=medium | dispatch_tier:frontier>
48
+ refs: {output: docs/plans/<slug>.md, input: <prior plan / failure evidence>}
49
+ note: <on re-plan: failure evidence + why a retry is justified>
50
+ ```
51
+
52
+ This closes the unmeasured quality-delta: the A/B test reads the ledger to compare plan outcomes by `rung`/`model` and find whether Frontier planning actually pays.
53
+
54
+ ## Re-plan mode (the remediation contract, v1)
55
+
56
+ When the orchestrator diagnoses a **planning miss** during Iterate (the plan itself no longer fits, on an objective signal — test/build failure, auditor verdict, retry-count, scope breach), it re-enters this ladder with `action: re-plan`. The Advisor reads the **failure evidence + the diff vs the current plan**, diagnoses planning-miss vs execution-miss (*its* Frontier call, never the failing executor's self-report), and on a planning miss issues **corrected instructions** — a diff against the prior plan + the evidence — so execution resumes at the cheap tier on a sound plan.
57
+
58
+ **v1 scope:** author + re-plan only. The **take-over-execution rung** (the Advisor executing a chunk directly) and **proactive mid-run checkpoint check-ins** are **v2** — land after the A/B confirms the core pays.
59
+
60
+ ## Always verified — never self-certifying
61
+
62
+ The Advisor's authored/re-planned plan is checked by the existing Frontier critics before any implementer runs: `plan_verify.py` (deterministic) → `plan-critic` (reasoning; **blocking on the same stakes triggers**, advisory otherwise) → `scope-auditor` at the Plan→Execute boundary. Frontier-authored output does not get a pass on review. Keep the verification panel multi-specialist — do not collapse it to a single judge.
@@ -0,0 +1,161 @@
1
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> -->
2
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
3
+ # Autonomous Mode + Per-Commit Mode (conditional detail)
4
+
5
+ Extracted from `SKILL.md` (WP-A, 2026-06-09): both modes are conditional — their
6
+ tables and contracts are load-bearing only when the mode is active, yet they
7
+ loaded in every session. The SKILL.md body now carries a one-line pointer to
8
+ each; the full detail lives here and loads on demand.
9
+
10
+ ## Autonomous Mode (Queue-Drain Loop)
11
+
12
+ Autonomous mode generalizes Phase 5 Iterate into a self-replenishing worker that drains its own `ux-queue/` + `issues/` + `proposals/`, alignment-checks each item against the original intent, executes the aligned subset, and commits in batches until the queue is empty or the wall-clock budget elapses. Default since this mode shipped (`--autonomous=false` opts back to classic one-pass).
13
+
14
+ **End-of-run backlog/issues drain — SHIPPED DEFAULT 2026-06-04**: every run now auto-drains `.build-loop/issues/` then `.build-loop/backlog/` at end-of-thread without asking. Reversible per-repo via `.build-loop/config.json`:
15
+
16
+ ```json
17
+ { "sessionPrefs": { "continueFromQueues": "never" } }
18
+ ```
19
+
20
+ `PRODUCTION`/`DECISION`-classified items still surface (not auto-executed). The continuation runs the same alignment-checker + scope-auditor + independent-auditor wiring as the in-run iterate loop. Stop conditions: iterate-cap (25 autonomous / 5 classic), budget exhausted, PRODUCTION encountered, 5 consecutive iterate failures, explicit user pause. Surfaced in the run report's `## Queue continuation` section.
21
+
22
+ ### Flag surface
23
+
24
+ | Invocation | Effect |
25
+ |---|---|
26
+ | `/build-loop:run "goal text"` | default mode, 2h budget, autonomous=true |
27
+ | `/build-loop:run --long "goal text"` | long mode, 8h budget |
28
+ | `/build-loop:run --budget 4h "goal text"` | custom budget (overrides `--long`) |
29
+ | `/build-loop:run --budget 30m "goal text"` | accepts `30s`, `30m`, `4h`, or bare integer seconds |
30
+ | `/build-loop:run --autonomous=false "goal text"` | classic single-pass; queue items become `followup/` |
31
+ | `/build-loop:run "overnight refactor of auth ..."` | keyword `overnight` → long mode, 8h |
32
+
33
+ **Flag precedence (strict, top wins):**
34
+
35
+ 1. `--budget <duration>` — explicit duration always wins; mode tagged `custom`.
36
+ 2. `--long` — sets mode `long`, budget 8h.
37
+ 3. Keyword detection in goal text — only when `--long` not explicitly set.
38
+ 4. Default — mode `default`, budget 2h, autonomous=true.
39
+
40
+ `--autonomous=false` is orthogonal: it can combine with any budget flag but disables the queue-drain loop entirely. With autonomous off, `--budget` still tracks wall-clock but the orchestrator runs classic Phase 1–6 once and reports.
41
+
42
+ ### Keyword fallback
43
+
44
+ Case-insensitive whole-word match against the goal text (or `intent.update_intent`). Detection runs ONLY when `--long` is not explicit on the command line. The flag always wins over keyword inference.
45
+
46
+ | Keyword | Example phrasings |
47
+ |---|---|
48
+ | `long` | "long refactor of …" |
49
+ | `long-running` | "long-running migration" |
50
+ | `overnight` | "overnight build" |
51
+ | `large-scale` | "large-scale rewrite" |
52
+ | `multi-day` | "multi-day backfill" |
53
+
54
+ Keyword list is configurable via `.build-loop/config.json.autonomy.keywordsLong[]`. The default list above is hard-coded in the orchestrator.
55
+
56
+ ### Budget tracking
57
+
58
+ The orchestrator writes `state.execution.budget` at autonomous-mode start:
59
+
60
+ ```json
61
+ {
62
+ "mode": "default | long | custom",
63
+ "started_at": "<iso8601 UTC>",
64
+ "deadline_at": "<iso8601 UTC>",
65
+ "last_checkin_at": "<iso8601 UTC> | null",
66
+ "commits_since_push": 0,
67
+ "checkin_interval_pct": 50
68
+ }
69
+ ```
70
+
71
+ `scripts/budget_check.py` reads this block at every iterate-loop entry, every commit, and every phase boundary, returning a routing envelope (`continue | checkin | finalize_and_stop`). The script is informational — exit 0 always; sub-5ms compute.
72
+
73
+ **Resume contract**: when a budget block exists and the run resumes via `--resume <run_id>`, the orchestrator MUST reuse the original `deadline_at`. A 2h budget that crashed at 1h59m does NOT get a fresh 2h. `scripts/resume_resolver.py._resolve_budget_on_resume()` is the single source of truth for this rule and surfaces the preserved budget under `budget_resume.preserve_deadline: true`.
74
+
75
+ ### Iteration caps
76
+
77
+ | Mode | Per-build cap | Per-item cap |
78
+ |---|---|---|
79
+ | Classic (autonomous=false) | 5 | n/a |
80
+ | Autonomous default | 25 | 3 same-verdict |
81
+ | Autonomous long | 25 | 3 same-verdict |
82
+
83
+ `maxIterateAttemptsAutonomous` is configurable in `.build-loop/config.json.autonomy.maxIterateAttemptsAutonomous`.
84
+
85
+ ### Question timeout (autonomous auto-decide)
86
+
87
+ In autonomous / `--long` mode a question that would otherwise block on the human auto-resolves if unanswered within a window, so an unattended run never stalls. When the orchestrator surfaces such a question it states a **recommended default** + a deadline; `scripts/question_timeout.py` is consulted (e.g. on a `ScheduleWakeup` resume) and returns `answered | take_default | wait`. On `take_default` the orchestrator takes the recommended option, records it to `state.execution.autonomousDefaults[]` + `auto-decision-capture`, continues, and lists every auto-decided question in the end-of-run readback for override (prefer the reversible option when deciding).
88
+
89
+ **Never auto-resolves — waits indefinitely:** production push, destructive/irreversible delete, and anything the autonomy gate verdicts `confirm`/`block` (gates #1–#2 in `agents/build-orchestrator.md`). Only reversible / `user_impact: major` decisions (gate #3) and steering clarifications time out — the single production gate is preserved.
90
+
91
+ Config (`.build-loop/config.json.autonomy`): `questionTimeoutMinutes` (default 10), `onTimeout` (`decide_default` default | `wait`).
92
+
93
+ ### Per-Phase A constraint
94
+
95
+ Phase A (current ship) wires queue drain + alignment-check + time budget. **Pushes stay manual** — `scripts/autonomous_push.py` and the K-commit batch-push policy ship in Phase B. The `should_push_now` field returned by `budget_check.py` is informational in Phase A; the orchestrator surfaces it in check-ins but does not push autonomously yet.
96
+
97
+ ## Per-Commit Mode (Self-Recursive Builds)
98
+
99
+ Per-commit mode splits a multi-commit build into one independent orchestrator dispatch per commit, so each commit reviews and lands cleanly before the next one starts. It activates automatically when the working directory IS the runtime — that is, when the user is editing the build-loop plugin itself (or any plugin whose runtime symlink points back to the working tree). It can also be explicitly opted into or out of via skill arguments.
100
+
101
+ ### Detection
102
+
103
+ Phase 1 Assess writes `selfRecursive.enabled: true|false` to `.build-loop/state.json` (commit 1 wired this via `scripts/detect_self_recursive.py`). The skill body MUST read this field BEFORE deciding which dispatch shape to use. If the field is absent, treat it as `false`.
104
+
105
+ ### Mode Resolution
106
+
107
+ | Skill arg | `selfRecursive` | Resulting mode |
108
+ |---|---|---|
109
+ | `--per-commit` (explicit) | either | per-commit |
110
+ | `--no-per-commit` (explicit) | either | single-orchestrator |
111
+ | (none) | true | per-commit (default for self-recursive) |
112
+ | (none) | false | single-orchestrator (today's behavior) |
113
+
114
+ Passing both `--per-commit` and `--no-per-commit` is a user error — fail loud with a one-line message naming the conflict and stop before any dispatch.
115
+
116
+ ### Dispatch Contract (Per-Commit Mode)
117
+
118
+ 1. **Plan first, dispatch many.** The skill body invokes a single planning orchestrator (Phase 1 Assess + Phase 2 Plan only). Its return must include a per-commit work list at `.build-loop/per-commit-plan.json` with this exact JSON shape:
119
+
120
+ ```json
121
+ {
122
+ "run_id": "run_<UTC>_<hash>",
123
+ "commits": [
124
+ {
125
+ "id": "c1",
126
+ "subject": "feat(scripts): add foo helper",
127
+ "scope": "...",
128
+ "files_planned": ["scripts/foo.py", "tests/test_foo.py"],
129
+ "spec": "verbatim packet for the implementer orchestrator",
130
+ "depends_on": []
131
+ }
132
+ ],
133
+ "branch": "feat/...",
134
+ "from_branch": "main"
135
+ }
136
+ ```
137
+
138
+ 2. **Per-commit orchestrator dispatch.** For each commit in the plan (respecting `depends_on`), the skill body dispatches a fresh `Agent(subagent_type="build-loop:build-orchestrator", ...)` carrying ONLY that commit's packet plus a `PER_COMMIT_DISPATCH: { commit_id, run_id, prior_commit_hashes }` prompt prefix. Each dispatched orchestrator runs Phase 3 Execute + Phase 4 Review for ITS commit only, then commits and returns. The dispatched orchestrator's behavior on the prefix is documented in `agents/build-orchestrator.md` §0a.
139
+
140
+ 3. **Aggregate.** The skill body collects each orchestrator's return envelope and writes a final report combining all commits' results. On partial failure (commit N fails), do NOT dispatch downstream commits; retain `.build-loop/per-commit-plan.json` so a subsequent `/build-loop:run --resume` invocation can pick up where it stopped. **Parent-dispatch contract (GAP-1):** the dispatcher (this skill body) HAS the Agent tool, so it is the parent that owes the audit. For every returned envelope whose `auditor_status` is `not-run:parent-must-dispatch` or `cross-vendor-deferred`, the dispatcher MUST — before declaring that commit/run review-complete — dispatch `Agent(subagent_type="build-loop:independent-auditor")` on that commit's diff range, append the verdict to `.build-loop/judge-decisions.json`, and re-run `write_run_entry --scope build` so the review-completeness gate passes. A nested per-commit orchestrator cannot audit itself; the audit is the dispatcher's responsibility, not an optional step.
141
+
142
+ **Parent owes Phase 6 Learn + retrospective (E3).** A stop-early dispatch that never reaches Phase 4 Review-G can't run Phase 6 Learn or the post-push retro — so the dispatching parent owes them at close, under the same parent-dispatch contract as GAP-1 (not optional, name the owner at dispatch). Full contract: `agents/build-orchestrator.md` §Phase 4 A (E3 block).
143
+
144
+ ### State.json schema
145
+
146
+ The per-commit dispatcher tracks its own progress under a `perCommit` block alongside the existing `execution` block:
147
+
148
+ ```json
149
+ {
150
+ "perCommit": {
151
+ "enabled": true,
152
+ "mode_source": "self_recursive_default|explicit_flag|opt_out",
153
+ "plan_path": ".build-loop/per-commit-plan.json",
154
+ "completed": [{"commit_id": "c1", "hash": "abc123", "completed_at": "..."}],
155
+ "in_flight": "c2",
156
+ "queued": ["c3"]
157
+ }
158
+ }
159
+ ```
160
+
161
+ M2's `execution.iterate_attempt` continues to track per-commit-orchestrator attempt counters (each dispatched orchestrator manages its own iterate counter) — do not duplicate iteration tracking inside `perCommit`.
@@ -16,7 +16,8 @@ Phase 1 runs `node ${CLAUDE_PLUGIN_ROOT}/skills/build-loop/detect-plugins.mjs` a
16
16
  |-------|---------|----------|
17
17
  | `writing-plans` | Phase 2 (Plan) | Write a structured plan directly: goal, tasks with exact file paths, dependency order, test commands |
18
18
  | `subagent-driven-development` | Phase 3 (Execute) | Dispatch parallel agents manually using the host's available delegation tool for independent file groups |
19
- | `verification-before-completion` | Phase 4 sub-step G (Report) | Run all test/build/lint commands and confirm output before claiming completion |
19
+ | `verification-before-completion` | Phase 4 sub-step G (Report) | Run all test/build/lint commands and confirm output before claiming completion. For app/UI changes this is NOT sufficient alone — also run the runtime UI⇄source-of-truth parity check (`runtime-parity-verification`); compile-green and a screenshot do not prove the running flow works |
20
+ | `runtime-parity-verification` | Phase 4 Review-B + Phase 5 Iterate (any `uiTarget != null` or user-visible flow) | Cross-check the rendered/queryable UI against the authoritative backend (DB/API/daemon/tool-state), screen-independently, and keep a validated per-repo smoke. Catches the "action does nothing / not showing / shows empty despite real data / stale projection" class. Drivers: web `ui-validator`; macOS `native-ax-driver` / IBR `scan_macos`; iOS `idb`; agent = tool-result vs rendered output. Reference smoke: easy-terminal `tools/smoke_launch.py` |
20
21
  | `simplify` (slash: `/simplify`) | Phase 4 sub-step E (Simplify) | Self-review the diff: remove scaffolding, inline single-use helpers, delete dead branches |
21
22
  | `complexity_detector.py` (accelerator, not a gate) | Phase 4 sub-step E (Simplify) | Diff-scoped stdlib-AST hotspot detector for changed Python; surfaces high-severity hotspots for a simpler rewrite, apply-vs-advise via existing Review-B + independent-auditor. Optional Python aid — the default Simplify pass reasons over the diff language-agnostically (see `phase-4-review.md` §"Sub-step E: Simplify") |
22
23
  | `build-loop:self-improve` | Phase 6 (Learn) | Scan recent runs for recurring patterns, auto-draft experimental skills/agents with A/B tracking, notify user for keep/remove decisions |
@@ -80,7 +81,7 @@ Tie-breaker: if signals are mixed (an Apple project with both `ios/` and a macOS
80
81
 
81
82
  **Migration source**: if `.replit` / `replit.nix` present → `migrationSource: "replit"`. Lovable / Bolt / v0 export markers (e.g. `lovable.config`, `bolt.config`, `v0.dev` in comments) → corresponding source. `replit-migrate` skills generalize — load `migration-scan` for any of the above, override hints as needed.
82
83
 
83
- **Apple deploy**: when `platform: "apple"` AND goal includes "deploy", "TestFlight", or "App Store" → Phase 7/8 invoke `apple-dev` deploy flow using ASC creds per `~/.claude/projects/-Users-tyroneross/memory/reference_asc_credentials.md`. Apply deployment policy first: TestFlight/App Store Connect upload/export defaults to `auto`; App Store production release/submission defaults to `confirm`.
84
+ **Apple deploy**: when `platform: "apple"` AND goal includes "deploy", "TestFlight", or "App Store" → Phase 7/8 invoke `apple-dev` deploy flow using ASC creds from your harness memory store (e.g. `~/.claude/projects/<project-slug>/memory/reference_asc_credentials.md`). Apply deployment policy first: TestFlight/App Store Connect upload/export defaults to `auto`; App Store production release/submission defaults to `confirm`.
84
85
 
85
86
  **Web deploy verify**: fires when `.vercel/project.json` or `vercel.json` is present AND the build performed a push/deploy → Phase 4 Review-B invokes `scripts/verify_deploy.py` (preferred-tier upgrade: Vercel MCP only if the user has added it to `.mcp.json`). Infra failures return `skipped`, never block the build.
86
87
 
@@ -175,7 +176,7 @@ If Phase 1 detects that the task touches plugin components, Phase 3 must map eac
175
176
 
176
177
  | Source | When | How |
177
178
  |---|---|---|
178
- | `/cookbook` | Claude API patterns: tool calling, PTC, code execution, Agent SDK, RAG, thinking, structured output, batch, caching | Invoke `/cookbook` or read `~/.claude/projects/-Users-tyroneross/memory/reference_claude_cookbook.md` |
179
+ | `/cookbook` | Claude API patterns: tool calling, PTC, code execution, Agent SDK, RAG, thinking, structured output, batch, caching | Invoke `/cookbook` or read `reference_claude_cookbook.md` from your harness memory store (`~/.claude/projects/<project-slug>/memory/`) |
179
180
  | `RossLabs-AI-Toolkit/LESSONS-LEARNED.md` | Any plugin work | Read during Phase 1 ASSESS |
180
181
  | `context7` MCP | Any library/framework use | `query-docs` / `resolve-library-id` — do NOT code from training data |
181
182
  | `research` skill | Factual claims, pricing, versions | Run `scripts/research_trigger.py` first; T1 official docs → T4 forums; 2-source minimum |
@@ -70,6 +70,14 @@ Prefer explicit prompt packets over full context forks. Use full context only wh
70
70
 
71
71
  Shared reads should happen once in the lead session, then be condensed into worker prompts. This keeps workers focused and reduces contradictory interpretations.
72
72
 
73
+ ### Prompt Cache Discipline
74
+
75
+ OpenAI prompt caching is automatic, so Build Loop cannot call the cache directly from Codex. The lever the Codex adapter controls is prompt shape: keep the reusable prefix stable, and move volatile task state later.
76
+
77
+ For Codex CLI and Codex app runs, put reusable role rules, output contracts, validation expectations, and ownership schema before task-specific facts. Put Rally state, timestamps, command output, diffs, browser comments, thread IDs, worktree metadata, current claims, and task IDs after the stable contract.
78
+
79
+ Do not reorder stable sections between worker prompts. Monitoring cached-token counters only detects prefix churn; the improvement comes from preserving the prefix and reducing noisy context before dispatch.
80
+
73
81
  ## Parallel Pattern
74
82
 
75
83
  1. Lead creates the plan and identifies parallel-safe groups.
@@ -100,7 +100,7 @@ explicit extraction edges:
100
100
 
101
101
  | Future plugin | Embedded namespace | Build-loop compatibility entrypoints |
102
102
  |---|---|---|
103
- | `agent-rally-point` | `scripts/rally_point/**` | `scripts/agent_rally.py`, `commands/agent-rally-point.md`, `hooks/*rally-point.sh`, `scripts/coordination_status.py`, `scripts/coordination_rally.py`, `scripts/coordination_bootstrap.py` |
103
+ | `agent-rally-point` | `scripts/rally_point/**` | `scripts/agent_rally.py`, `commands/rally-point.md`, `hooks/*rally-point.sh`, `scripts/coordination_status.py`, `scripts/coordination_rally.py`, `scripts/coordination_bootstrap.py` |
104
104
  | `agent-rally-watcher` | `scripts/agent_rally_watcher/**` | `scripts/coordination_watch.py` |
105
105
 
106
106
  The machine-readable contract lives at
@@ -17,6 +17,65 @@ Every build starts by capturing:
17
17
 
18
18
  Write the result to `.build-loop/intent.md` and mirror the compact version into `.build-loop/state.json.intent`.
19
19
 
20
+ ### Commander's-intent posture (WP-F, all OPTIONAL — LLM-inferred, confirm-on-ambiguity)
21
+
22
+ North Star captures who/what; **posture** captures the tradeoff stance that drives
23
+ autonomous forks when the agent loses comms (the Marine-Corps commander's-intent
24
+ analog: purpose + key tasks + end state, so a subordinate who can't ask still
25
+ chooses correctly). A walkie-talkie app for generals-on-ops, for kids, and for
26
+ traders share North Star *fields* but differ entirely in *what to optimize when
27
+ forced to choose*. All fields are OPTIONAL and LLM-inferred from the ask; confirm
28
+ only on genuine ambiguity (reuse the restatement protocol — never `AskUserQuestion`,
29
+ never a gate). Mirror into `state.json.intent.posture`.
30
+
31
+ - **audience** + **stakes** — one line each (who the change serves; what a failure
32
+ costs). `stakes` ∈ {low, medium, high}.
33
+ - **priority_order** — the ranked tie-breaker the agent applies when two viable
34
+ paths conflict. FIXED VOCAB (ordered subset of
35
+ `security / reliability / speed / cost / simplicity / polish`) plus a free-text
36
+ `notes` escape for expressiveness. The fixed vocab aids weak-LLM recall; `notes`
37
+ carries anything the vocab can't.
38
+ - **acceptable_tradeoffs** — what is OK to cut under pressure.
39
+ - **non_goals** — what is never cut. At `stakes: high`, a `non_goals` entry that
40
+ names a REAL risk is a candidate to **graduate to a constitution invariant** — but
41
+ only once it is **promoted into the project constitution** (`projects/<slug>/constitution.md`),
42
+ where the LLM enforces it as a hard line. Until promoted, it stays advisory like the
43
+ rest of the posture. There is no separate deterministic gate that reads `non_goals`
44
+ directly (`grep non_goals scripts/` is intentionally empty); enforcement rides the
45
+ constitution, not a parallel mechanism. See the tiered charter below.
46
+
47
+ `priority_order` wires into the `alignment-checker` as the Phase-2-fork and
48
+ Phase-5-queue-drain tie-breaker: not just "matches intent?" but "which viable path
49
+ does THIS user's priority order prefer?" — advisory data the LLM weighs, never a gate.
50
+
51
+ ### Tiered intent — `stakes` is the depth dial (WP-F/F2)
52
+
53
+ - **Per-run intent** (ephemeral, `.build-loop/intent.md`): restated ask + this
54
+ change's posture. Unchanged lifecycle.
55
+ - **Project charter** (persistent): stable North Star + posture + invariants + key
56
+ architecture decisions. ACCRETES via promotion — a fact promotes to durable when
57
+ user-confirmed OR stable/unchallenged across N runs; stays `inferred` until then;
58
+ carries the falsifier that would unseat it (doctrine rule 8). Storage + sync:
59
+ `scripts/charter.py` (canonical `build-loop-memory/projects/<slug>/charter.md`;
60
+ repo mirror `.build-loop/charter.md` with a `canonical:` pointer + content hash;
61
+ one writer = the run, from canonical; user hand-edit of the mirror promotes to
62
+ canonical `authored_by: user` on next run via hash-mismatch detection).
63
+ - **Depth scales by `stakes`**: low → intent line only (skills/agents/toys — do NOT
64
+ force a charter, that's the anti-pattern); medium → thin charter (web/mobile);
65
+ high → full charter, and risk-naming `non_goals` become candidates to promote into
66
+ the constitution as invariants (where the LLM enforces them). The promotion is the
67
+ enforcement; no `non_goals`-specific gate exists outside the constitution.
68
+ - **PRD stance**: opt-in upfront via `start-prd`; accretion is the default; never
69
+ required. A PRD, when present, PREFILLS the charter richer — input, not a gate.
70
+
71
+ Enforcement philosophy (binding): all advisory. The one stronger-than-advisory path
72
+ is **constitution promotion** — a risk-naming `non_goals` at `stakes: high` graduates
73
+ to a hard invariant only when it is written into `projects/<slug>/constitution.md`,
74
+ which the LLM treats as a binding line. Per `feedback_deterministic_only_for_known_risks` —
75
+ posture/charter depth is the dial; the LLM weighs, never a gate. The constitution, not
76
+ a `non_goals`-specific script, carries any graduated invariant (no dormant determinism
77
+ claim — there is no `non_goals` enforcement code to wire up).
78
+
20
79
  ## Intent restatement protocol (always-on)
21
80
 
22
81
  Run this protocol on every build, judged by the orchestrator LLM — never a regex, never a detector script, never a binary gate. Depth scales with ambiguity, not a threshold. The behavior is intrinsic to Phase 1; no separate skill, script, or routing step gates it.
@@ -73,10 +132,38 @@ Mirror the result to `.build-loop/state.json.intent`:
73
132
  "restated_intent": "<one sentence>",
74
133
  "approach_options": ["<label>", "<label>"], // optional; empty when Step A alone fired
75
134
  "assumptions": ["<line>", "<line>"], // optional; empty when no leaps were made
76
- "confidence": "high" | "medium" | "low" // LLM judgment, not a script
135
+ "confidence": "high" | "medium" | "low", // LLM judgment, not a script
136
+ "run_id": "<current run_id>" // Step E: the run this intent was written for
77
137
  }
78
138
  ```
79
139
 
140
+ ### Step E — Run-id freshness stamp (per-run staleness guard)
141
+
142
+ `intent.md` lives in `.build-loop/` and survives across runs in the same workdir, so a
143
+ resumed or back-to-back run finds the PRIOR run's intent on disk. The "auto-execute fast
144
+ path" (Step A: "write the line and move on" for a concrete goal) can be misread as
145
+ "the present file already satisfies the protocol", so the rewrite gets skipped and the
146
+ stale intent describes prior work — the exact bl-intent-refresh-per-run failure (the
147
+ A–H consolidation run listed as a non-goal what WP-A shipped).
148
+
149
+ Two cheap, deterministic moves close it:
150
+
151
+ 1. **Stamp on write.** Whenever Phase 1 (re)writes `intent.md`, embed the current
152
+ `run_id` as an HTML comment so the prose never has to carry it:
153
+ `<!-- intent_run_id: <run_id> -->` (helper: `intent_freshness.stamp_marker(run_id)`).
154
+ Mirror `run_id` into `state.json.intent.run_id`.
155
+ 2. **Check at Phase 1 start.** Run
156
+ `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/intent_freshness.py --workdir "$PWD" --json`.
157
+ A `stale` (stamp ≠ current run) or `unstamped` verdict means the on-disk intent is
158
+ from a prior run — re-run Steps A–D and re-stamp. The check is **advisory** and exit-0
159
+ always: a run-id *mismatch* is an objective structural fact (equality, not a content
160
+ judgment), so detecting it respects "never a content gate" — only the refresh (the LLM
161
+ rewriting the prose) is judgment. Surface the verdict line in the run report; never
162
+ `AskUserQuestion`, never `## Held`, never block.
163
+
164
+ This is detection-by-structure + refresh-by-LLM: it does not re-introduce the retired
165
+ regex that judged intent *content*; it only answers "does this file belong to this run?".
166
+
80
167
  ### Hard guarantees (non-negotiable)
81
168
 
82
169
  - **Never `AskUserQuestion`.** Intent capture is autonomous. The user reads the restatement + assumptions in the run report and can correct on the next dispatch.