@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
@@ -65,9 +65,23 @@ The Python pipeline produces deterministic bullets from captured signals. When y
65
65
 
66
66
  If you do enrich, re-write the active file using `Edit` (preserving the headers; only adding new bullets under existing section headers). Skip enrichment when the deterministic output already captures everything.
67
67
 
68
- ## Step 3 — Return envelope
68
+ ## Step 3 — Emit closeout status (mandatory)
69
69
 
70
- Return the JSON envelope verbatim from Step 1 (plus an `enrichment_applied: true|false` flag if you modified the file in Step 2). Example shape:
70
+ After Step 2, run the machine-readable closeout this is the durable enforcement layer for the build-loop memory closeout contract:
71
+
72
+ ```bash
73
+ python3 -m closeout \
74
+ --workdir "$WORKDIR" \
75
+ --run-id "$RUN_ID" \
76
+ --source post-push \
77
+ --json
78
+ ```
79
+
80
+ The script emits exactly one `closeout_status`: `wrote_memory` | `queued_pending_lesson` | `no_durable_lesson`. Copy it into your envelope under `closeout_status` and `closeout_reason`. The script is non-raising; on degraded internal error it returns exit 0 with `error:` populated — surface that under `closeout_error` and continue. A skipped closeout on a run with durable signal is a DETECTABLE failure (asserted by `scripts/closeout/test_status.py`), so this step is non-optional.
81
+
82
+ ## Step 4 — Return envelope
83
+
84
+ Return the JSON envelope verbatim from Step 1 (plus an `enrichment_applied: true|false` flag if you modified the file in Step 2, plus `closeout_status` / `closeout_reason` / `closeout_error` from Step 3). Example shape:
71
85
 
72
86
  ```json
73
87
  {
@@ -78,7 +92,10 @@ Return the JSON envelope verbatim from Step 1 (plus an `enrichment_applied: true
78
92
  "status": "ok",
79
93
  "reason": null,
80
94
  "meta": { "run_id": "...", "prompt_count": 24, "cluster_count": 2, "transcript_present": true },
81
- "enrichment_applied": false
95
+ "enrichment_applied": false,
96
+ "closeout_status": "wrote_memory | queued_pending_lesson | no_durable_lesson",
97
+ "closeout_reason": "human-readable reason",
98
+ "closeout_error": null
82
99
  }
83
100
  ```
84
101
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: scope-auditor
3
3
  description: Read-only Plan→Execute boundary check. For every commit that changes a public function/component/type signature, traces every caller-site outside the commit's owned-files, then either confirms `internal_only: true` or appends the missing caller files to the appropriate commit's owned-files list. Prevents the "fan-out scope-blindness" defect class observed in round-2 of dispatch-pattern testing (example-app 2026-05-07).
4
- model: opus
4
+ model: fable
5
5
  tools: ["Read", "Grep", "Glob"]
6
6
  ---
7
7
 
@@ -14,7 +14,7 @@ description: |
14
14
  user: "Security check on the auth changes"
15
15
  assistant: "I'll use the security-reviewer agent — diff vs OWASP Web A01/A03 + LLM06 + ASI03 — and emit a structured findings report."
16
16
  </example>
17
- model: claude-sonnet-4-6
17
+ model: fable
18
18
  color: red
19
19
  tools: ["Read", "Grep", "Glob"]
20
20
  ---
@@ -115,7 +115,7 @@ Keep the Experiment section small otherwise: one metric, one decision rule, expl
115
115
  ## Constraints
116
116
 
117
117
  - **No invention**. If the pattern evidence is weak, flag it in your synthesis output (`warning: low-signal pattern, artifact is speculative`) and produce a minimal skill.
118
- - **No promotion authority**. You draft, never promote. Promotion is Opus 4.7 territory via build-orchestrator.
118
+ - **No promotion authority**. You draft, never promote. Promotion verdict is `promotion-reviewer` (Fable) territory, dispatched via build-orchestrator.
119
119
  - **No changes outside `.build-loop/`**. Experimental artifacts are project-local.
120
120
  - **Include a removal pointer**. The user must be able to delete your artifact with one command.
121
121
  - **Use `plugin-dev` skills**. Do not wing the SKILL.md format. Load the reference.
@@ -79,7 +79,7 @@ Present the full output. Also note:
79
79
 
80
80
  To launch a fresh session after handoff, re-run with `--launch`:
81
81
  ```
82
- /build-loop:handoff --launch
82
+ /build-loop:compose-handoff --launch
83
83
  ```
84
84
 
85
85
  {{/if}}
@@ -90,18 +90,18 @@ To launch a fresh session after handoff, re-run with `--launch`:
90
90
 
91
91
  **Emit to stdout (default)**
92
92
  ```
93
- /build-loop:handoff
93
+ /build-loop:compose-handoff
94
94
  ```
95
95
 
96
96
  **Write to file**
97
97
  ```
98
- /build-loop:handoff --workdir /path/to/repo
98
+ /build-loop:compose-handoff --workdir /path/to/repo
99
99
  ```
100
100
  (Use `--output` flag in the script directly for file output.)
101
101
 
102
102
  **Emit + launch fresh session**
103
103
  ```
104
- /build-loop:handoff --launch
104
+ /build-loop:compose-handoff --launch
105
105
  ```
106
106
 
107
107
  **JSON envelope (for programmatic use)**
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: optimize
2
+ name: optimize-run
3
3
  description: "(Advanced override — `/build-loop:run` auto-routes here; use this only to force the mode.) Run autonomous metric-driven optimization. Detects available targets or accepts a specific one."
4
4
  argument-hint: "[target]"
5
5
  ---
@@ -178,7 +178,7 @@ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/coordination_bootstrap.py \
178
178
  --json
179
179
  ```
180
180
 
181
- Example invocation: `/agent-rally-point init v0130-feature-x "Add new feature X across orchestrator + bootstrap + tests"`
181
+ Example invocation: `/build-loop:rally-point init v0130-feature-x "Add new feature X across orchestrator + bootstrap + tests"`
182
182
 
183
183
  Example output:
184
184
 
@@ -220,7 +220,7 @@ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/agent_rally.py lead <op> \
220
220
  - `relinquish` — give up the lead so the next `claim` succeeds immediately.
221
221
  - `status` — read the current lead + `lease_valid`.
222
222
 
223
- Example: `/agent-rally-point lead status`
223
+ Example: `/build-loop:rally-point lead status`
224
224
 
225
225
  ### `escalate <reason>`
226
226
 
@@ -269,7 +269,7 @@ Shows the subcommand reference table (replaces what the no-args case used to do
269
269
  Outputs:
270
270
 
271
271
  ```
272
- /agent-rally-point — inspect or invoke build-loop's multi-session coordination
272
+ /build-loop:rally-point — inspect or invoke build-loop's multi-session coordination
273
273
 
274
274
  Subcommands:
275
275
  status (default) Sensor poll: active peers, unresolved verdicts, coord file
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: research
2
+ name: research-run
3
3
  description: "(Advanced override — `/build-loop:run` auto-routes here; use this only to force the mode.) Generate a repo-grounded research packet without committing to build. Pre-decision analysis."
4
4
  argument-hint: "[topic]"
5
5
  ---
@@ -0,0 +1,32 @@
1
+ ---
2
+ description: "Set up or verify the build-loop central memory store (build-loop-memory). Guided and idempotent — copies only the packaged public seed, never overwrites your content. Safe to re-run."
3
+ argument-hint: "[--check]"
4
+ ---
5
+
6
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
7
+
8
+ {{#if ARGUMENTS}}
9
+ {{#contains ARGUMENTS "--check"}}
10
+ Run `python3 "${CLAUDE_PLUGIN_ROOT:-$PWD}/scripts/install_memory.py" --check` and report the memory store status: which template files and which lanes (`indexes/`, `projects/`) exist vs are missing. Do not write anything.
11
+ {{else}}
12
+ Run `python3 "${CLAUDE_PLUGIN_ROOT:-$PWD}/scripts/install_memory.py" --guided` and report what was seeded vs already present, then surface the installer's printed next steps to the user.
13
+ {{/contains}}
14
+ {{else}}
15
+ Run `python3 "${CLAUDE_PLUGIN_ROOT:-$PWD}/scripts/install_memory.py" --guided` and report what was seeded vs already present, then surface the installer's printed next steps to the user.
16
+ {{/if}}
17
+
18
+ ---
19
+
20
+ ## Reference
21
+
22
+ **Guided setup (idempotent — public seed only, no personal content):**
23
+ ```
24
+ /build-loop:setup-memory
25
+ ```
26
+
27
+ **Status check (no writes):**
28
+ ```
29
+ /build-loop:setup-memory --check
30
+ ```
31
+
32
+ The store lives at `memory_store_root()`. Resolution: an env override (`$BUILD_LOOP_MEMORY_STORE_ROOT` / `$BUILD_LOOP_MEMORY_ROOT` / `$AGENT_MEMORY_ROOT`), else a pre-existing legacy `~/dev/git-folder/build-loop-memory` if it is already on disk, else the neutral fresh-install default `~/.build-loop-memory`. On a fresh machine it is also bootstrapped automatically on session start by `hooks/session-start-memory.sh` when entirely absent; this command is the manual / repair path and the way to see what's present. Research packets, project lessons, decisions, and debugging memory all persist under this store.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: plan-verify
2
+ name: verify-plan
3
3
  description: "Deterministic verifier for plan markdown — grep-checkable rules (delete-with-callers, numeric-drift, route-change-evidence, package-state, missing-evidence). Run before accepting a Phase 2 plan."
4
4
  argument-hint: "<plan.md>"
5
5
  ---
@@ -1,25 +1,42 @@
1
1
  # Agent Surface Policy
2
2
 
3
- Build Loop exposes a small public entrypoint set and keeps implementation
4
- helpers internal.
3
+ Build Loop keeps one user-facing Codex entrypoint while preserving the richer
4
+ Claude Code skill tree for hosts that can route helpers internally.
5
5
 
6
6
  ## Public Entry Points
7
7
 
8
- These are the only skills that should appear as user-facing Build Loop choices:
8
+ Codex must expose exactly one user-facing Build Loop choice:
9
9
 
10
- - `build-loop` — main multi-step code workflow
11
- - `debug-loop` root-cause debugging workflow
12
- - `optimize` — metric-driven optimization
13
- - `research` repo-grounded pre-build research
14
- - `knowledge` — durable decisions and lessons
15
- - `handoff` — compose a durable handoff from build-loop run state (BL-4)
10
+ - `build-loop` — main workflow and router for build, fix, debug, optimize,
11
+ research, knowledge capture, handoff, and plugin-test work
12
+
13
+ Claude Code may expose advanced direct overrides in its command/skill surface
14
+ where useful:
15
+
16
+ - `build-loop`
17
+ - `debug-loop`
18
+ - `optimize`
19
+ - `research`
20
+ - `knowledge`
21
+ - `handoff`
16
22
 
17
23
  ## Host Rules
18
24
 
19
- Codex and ChatGPT use `.codex-plugin/plugin.json`, which points at
20
- `./codex-skills`. That directory contains wrapper skills for the public
21
- entrypoints only. The full `./skills` tree still ships in the package for
22
- internal references.
25
+ Codex and ChatGPT install from `plugin-artifacts/codex`, not from the source
26
+ repo root. Codex auto-discovers root `skills/*/SKILL.md` files and manifest
27
+ skill paths supplement that default, so installing the source root leaks every
28
+ internal helper into the picker. The artifact is generated by:
29
+
30
+ ```bash
31
+ python3 scripts/build_codex_plugin_artifact.py --source . --target plugin-artifacts/codex
32
+ ```
33
+
34
+ The artifact contains one `skills/build-loop/SKILL.md` copied from the
35
+ canonical workflow and `.codex-plugin/plugin.json` rewritten to
36
+ `"skills": "./skills"`. It must not contain any other `SKILL.md` files.
37
+
38
+ The local Codex marketplace (`.agents/plugins/marketplace.json`) points at this
39
+ artifact. Release and marketplace updates must do the same.
23
40
 
24
41
  Claude Code keeps `.claude-plugin/plugin.json` pointed at `./skills` because
25
42
  commands and orchestrator agents load internal skills by qualified name. Helper
@@ -27,19 +44,20 @@ skills must set `user-invocable: false`; the public entrypoints set
27
44
  `user-invocable: true`.
28
45
 
29
46
  Cursor and other AGENTS.md-style tools should treat `AGENTS.md` plus this file
30
- as the routing contract. Start from the public entrypoints above. Read helper
31
- files under `skills/` only when the active entrypoint, a command, or an
32
- orchestrator instruction explicitly references them.
47
+ as the routing contract. Start from `build-loop`. Read helper files under
48
+ `skills/` only when the active entrypoint, a command, or an orchestrator
49
+ instruction explicitly references them.
33
50
 
34
51
  ## Cache Hygiene
35
52
 
36
53
  Plugin cache pruning is explicit and auditable:
37
54
 
38
55
  ```bash
56
+ npm run codex:sync-cache
39
57
  python3 scripts/prune_plugin_cache.py --source . --apply
40
58
  ```
41
59
 
42
- The command keeps the current host manifest version and deletes older verified
43
- cache directories for the same plugin. It checks both `.codex-plugin/plugin.json`
44
- and `.claude-plugin/plugin.json` by default. Use `--host codex` or
45
- `--host claude` for a single host.
60
+ `npm run codex:sync-cache` rebuilds the slim artifact first, then syncs that
61
+ artifact into the Codex cache. The prune command keeps the current host manifest
62
+ version and deletes older verified cache directories for the same plugin. Use
63
+ `--host codex` or `--host claude` for a single host.
@@ -1,12 +1,17 @@
1
1
  # Memory Setup
2
2
 
3
3
  Build-loop's advisory judges and the Phase 1 Assess memory-load step read from
4
- one consolidated tree under `~/dev/git-folder/build-loop-memory/` by default:
4
+ one consolidated tree. The root (`<memory-root>` below) is resolved by
5
+ `scripts/_paths.memory_store_root()`:
6
+
7
+ 1. an env override — `$BUILD_LOOP_MEMORY_STORE_ROOT` / `$BUILD_LOOP_MEMORY_ROOT` / `$AGENT_MEMORY_ROOT`;
8
+ 2. else a pre-existing legacy `~/dev/git-folder/build-loop-memory` if it is already on disk (installs that predate the neutral default keep their location with zero config);
9
+ 3. else the neutral fresh-install default `~/.build-loop-memory`.
5
10
 
6
11
  | Tier | Location | Owner | Versioning |
7
12
  |---|---|---|---|
8
- | Global | `~/dev/git-folder/build-loop-memory/` plus top-level lanes such as `lessons/` | This user | **Should be in a private git repo** (your lessons live here) |
9
- | Project | `~/dev/git-folder/build-loop-memory/projects/<slug>/` (slug derived via `scripts/_paths.derive_slug_from_cwd` — basename of the git repo root, lowercased + normalized; `workers/` sub-component becomes `<slug>/workers`) | This user | Same private repo as global |
13
+ | Global | `<memory-root>/` plus top-level lanes such as `lessons/` | This user | **Should be in a private git repo** (your lessons live here) |
14
+ | Project | `<memory-root>/projects/<slug>/` (slug derived via `scripts/_paths.derive_slug_from_cwd` — basename of the git repo root, lowercased + normalized; `workers/` sub-component becomes `<slug>/workers`) | This user | Same private repo as global |
10
15
 
11
16
  > **History** — until PR 3 of the memory-consolidation series (merged 2026-05-13), the legacy per-repo location was also read by `memory_facade._resolve_memory_dirs` as a transitional shim. As of PR 3, only the consolidated tree is read; any pre-migration content still at the legacy path is invisible. Operators with such content should run `scripts/migrate_project_memory.py --apply` (idempotent), then `scripts/cleanup_legacy_memory_stubs.py --apply` to remove the now-inert `.MOVED.md` stubs.
12
17
 
@@ -20,10 +25,10 @@ operator preferences that are not appropriate for public distribution.
20
25
 
21
26
  ```bash
22
27
  # Guided terminal install. This validates the packaged public seed first, then
23
- # creates ~/dev/git-folder/build-loop-memory/ with scaffold-only files.
28
+ # creates <memory-root>/ with scaffold-only files.
24
29
  python3 ${CLAUDE_PLUGIN_ROOT}/scripts/install_memory.py --guided
25
30
 
26
- # Bootstrap with templates (creates ~/dev/git-folder/build-loop-memory/ if missing,
31
+ # Bootstrap with templates (creates <memory-root>/ if missing,
27
32
  # seeds constitution.md + MEMORY.md from templates/memory/, plus indexes/ and projects/)
28
33
  python3 ${CLAUDE_PLUGIN_ROOT}/scripts/install_memory.py
29
34
 
@@ -37,7 +42,7 @@ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/install_memory.py --validate-seed
37
42
  This creates:
38
43
 
39
44
  ```
40
- ~/dev/git-folder/build-loop-memory/
45
+ <memory-root>/
41
46
  ├── constitution.md # template — replace with your invariants
42
47
  ├── MEMORY.md # template — index for entries you add
43
48
  ├── indexes/ # rebuildable local indexes, including semantic_facts.sqlite
@@ -79,7 +84,7 @@ The repo should contain `constitution.md` and `MEMORY.md` plus your existing les
79
84
 
80
85
  ```bash
81
86
  python3 scripts/install_memory.py
82
- cd ~/dev/git-folder/build-loop-memory
87
+ cd <memory-root> # default ~/.build-loop-memory on a fresh install
83
88
  git init
84
89
  git add constitution.md MEMORY.md
85
90
  git commit -m "init: build-loop memory scaffolding"
@@ -150,7 +155,7 @@ Keep `MEMORY.md` under ~200 lines; entries past that get truncated when loaded i
150
155
  ## What about decisions?
151
156
 
152
157
  The **canonical decision store** is
153
- `~/dev/git-folder/build-loop-memory/projects/<project>/decisions/`. It is
158
+ `<memory-root>/projects/<project>/decisions/`. It is
154
159
  project-tagged and written by `scripts/write_decision.py` — it captures the
155
160
  discrete "we decided X" events of any project.
156
161
 
@@ -158,11 +163,11 @@ The top-level `lessons/` lane is for **cross-project lessons** — patterns and
158
163
  feedback that apply broadly, not project-specific decisions.
159
164
 
160
165
  ```
161
- ~/dev/git-folder/build-loop-memory/ # canonical root
162
- ~/dev/git-folder/build-loop-memory/lessons/ # cross-project lessons
163
- ~/dev/git-folder/build-loop-memory/indexes/updates.jsonl # global update ledger
164
- ~/dev/git-folder/build-loop-memory/projects/<slug>/ # project-local memory
165
- ~/dev/git-folder/build-loop-memory/projects/_archive/<slug>/ # retired projects, still queryable
166
+ <memory-root>/ # canonical root
167
+ <memory-root>/lessons/ # cross-project lessons
168
+ <memory-root>/indexes/updates.jsonl # global update ledger
169
+ <memory-root>/projects/<slug>/ # project-local memory
170
+ <memory-root>/projects/_archive/<slug>/ # retired projects, still queryable
166
171
  <repo>/.build-loop/memory/ # legacy project location — no longer read (PR 3 removed the shim); migrate via scripts/migrate_project_memory.py
167
172
  <repo>/.episodic/decisions/ # legacy local decision store (migration/archive)
168
173
  ```
@@ -215,7 +220,7 @@ If any of these fail, see `references/memory-systems.md` for the full backend to
215
220
 
216
221
  ## Privacy
217
222
 
218
- Treat `~/dev/git-folder/build-loop-memory/` as containing potentially-sensitive context:
223
+ Treat `<memory-root>/` as containing potentially-sensitive context:
219
224
 
220
225
  - Operator preferences, project-specific decisions, client names if you write them in
221
226
  - Constitution rules may reveal architectural patterns from past projects
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # _resolve_python.sh — source (don't exec) to set `$_py` to a usable python3
6
+ # without depending on a populated PATH. Hooks run under a minimal PATH
7
+ # (/usr/bin:/bin), so resolve via `command -v` then absolute fallbacks. Sets
8
+ # `_py=""` when none is found.
9
+ #
10
+ # . "$(dirname "$0")/_resolve_python.sh"
11
+ # [ -n "$_py" ] || exit 0
12
+ #
13
+ # Single source of truth for the resolver shared by closeout.sh,
14
+ # session-start-closeout.sh, and post-push-closeout.sh. See memory
15
+ # `reference_hooks_minimal_path_failopen`.
16
+
17
+ _py=""
18
+ for _candidate in python3 python; do
19
+ if command -v "$_candidate" >/dev/null 2>&1; then
20
+ _py="$_candidate"
21
+ break
22
+ fi
23
+ done
24
+ for _fallback in /usr/bin/python3 /usr/local/bin/python3 /opt/homebrew/bin/python3; do
25
+ if [ -z "$_py" ] && [ -x "$_fallback" ]; then
26
+ _py="$_fallback"
27
+ fi
28
+ done
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+ # closeout.sh — structural run-close shim for INLINE build-loop runs (f6).
6
+ #
7
+ # Backs the Claude Code `Stop` hook and the Codex `Stop` equivalent (see
8
+ # hooks/hooks.json + .codex/hooks.json). Thin minimal-PATH-safe wrapper around
9
+ # scripts/stop_closeout.py, which holds the (tested) logic. Mirrors the existing
10
+ # `commit_state_check.py --hook` invocation pattern.
11
+ #
12
+ # $1 = mode: "stop" (default) | "session-start"
13
+ #
14
+ # Contract:
15
+ # - Advisory + fail-open: ALWAYS exit 0; never `decision: block`.
16
+ # - Self-gates on `.build-loop/` presence (walk up); silent elsewhere — safe
17
+ # to install globally.
18
+ # - Minimal-PATH safe: hooks run under /usr/bin:/bin. Resolve python3 via
19
+ # `command -v` + absolute fallbacks; missing → silent exit 0.
20
+ # - stdin (the hook JSON payload, carrying session_id) is forwarded to python
21
+ # untouched so stop_closeout.py can read the session id.
22
+ #
23
+ # See memory `reference_hooks_minimal_path_failopen`.
24
+
25
+ set -u
26
+
27
+ MODE="${1:-stop}"
28
+
29
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${PWD}}"
30
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${PROJECT_DIR}}"
31
+
32
+ # Walk up from the project dir to find a `.build-loop/`. Absent → silent exit 0
33
+ # (this hook is safe to install globally; it does nothing outside a build-loop repo).
34
+ _dir="$PROJECT_DIR"
35
+ _found=""
36
+ for _ in 1 2 3 4 5 6 7 8; do
37
+ if [ -d "${_dir}/.build-loop" ]; then
38
+ _found="$_dir"
39
+ break
40
+ fi
41
+ _parent="$(dirname "$_dir")"
42
+ [ "$_parent" = "$_dir" ] && break
43
+ _dir="$_parent"
44
+ done
45
+ [ -n "$_found" ] || exit 0
46
+
47
+ # Resolve a python3 binary without depending on a populated PATH (shared helper).
48
+ _HOOK_DIR="$(dirname "$0")"
49
+ _py=""
50
+ [ -f "${_HOOK_DIR}/_resolve_python.sh" ] && . "${_HOOK_DIR}/_resolve_python.sh"
51
+ [ -n "$_py" ] || exit 0
52
+
53
+ SCRIPT="${PLUGIN_ROOT}/scripts/stop_closeout.py"
54
+ [ -f "$SCRIPT" ] || exit 0
55
+
56
+ # Emit whatever the helper prints (valid hook JSON), then exit 0 no matter what.
57
+ "$_py" "$SCRIPT" --workdir "$_found" --mode "$MODE" --hook 2>/dev/null || printf '{}'
58
+ exit 0
@@ -65,11 +65,18 @@ def _repo_root() -> Path:
65
65
  return Path.cwd()
66
66
 
67
67
 
68
- def _fail_open(reason: str) -> int:
69
- """Internal-error path: print to stderr, return 0 (allow push)."""
68
+ def _fail_open(reason: str, *, repo: Path | None = None) -> int:
69
+ """Internal-error path: print to stderr, return 0 (allow push).
70
+
71
+ Even on the internal-error fail-open path we still ARM the post-push
72
+ closeout baton: a missing ``push_hold`` import shouldn't silently drop
73
+ the durable-memory contract for ad-hoc pushes.
74
+ """
70
75
  sys.stderr.write(
71
76
  f"[build-loop pre-push] internal error — allowing push: {reason}\n"
72
77
  )
78
+ if repo is not None:
79
+ _arm_post_push_closeout(repo)
73
80
  return 0
74
81
 
75
82
 
@@ -110,7 +117,59 @@ def _format_block_message(verdict: dict) -> str:
110
117
  )
111
118
 
112
119
 
120
+ def _arm_post_push_closeout(repo: Path) -> None:
121
+ """Drop a tiny JSON baton at ``.build-loop/closeout/armed.json``.
122
+
123
+ Git has no native client-side post-push hook. We arm a baton here so the
124
+ next session-start handler (``hooks/session-start-closeout.sh``) drains it
125
+ by invoking ``python3 -m closeout --source post-push-armed``.
126
+
127
+ Fail-open by design — any error is silently swallowed; an armed baton is a
128
+ nice-to-have, never a push blocker.
129
+ """
130
+ try:
131
+ from datetime import datetime, timezone
132
+ import json as _json
133
+ import subprocess as _sp
134
+ import tempfile as _tf
135
+
136
+ bl_dir = repo / ".build-loop" / "closeout"
137
+ bl_dir.mkdir(parents=True, exist_ok=True)
138
+ head = ""
139
+ try:
140
+ head = _sp.check_output(
141
+ ["git", "rev-parse", "HEAD"],
142
+ cwd=str(repo),
143
+ stderr=_sp.DEVNULL,
144
+ text=True,
145
+ ).strip()
146
+ except (_sp.CalledProcessError, FileNotFoundError, OSError):
147
+ pass
148
+
149
+ payload = {
150
+ "armed_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
151
+ "source": "post-push-armed",
152
+ "head_sha": head or None,
153
+ }
154
+ target = bl_dir / "armed.json"
155
+ fd, tmp = _tf.mkstemp(dir=str(bl_dir), prefix=".armed-", suffix=".json")
156
+ try:
157
+ with os.fdopen(fd, "w", encoding="utf-8") as fh:
158
+ _json.dump(payload, fh, indent=2, sort_keys=True)
159
+ fh.write("\n")
160
+ os.replace(tmp, target)
161
+ finally:
162
+ if os.path.exists(tmp):
163
+ try:
164
+ os.unlink(tmp)
165
+ except OSError:
166
+ pass
167
+ except Exception: # noqa: BLE001 — never break a push for the baton
168
+ return
169
+
170
+
113
171
  def main() -> int:
172
+ repo: Path | None = None
114
173
  try:
115
174
  repo = _repo_root()
116
175
  scripts_dir = repo / "scripts"
@@ -119,22 +178,26 @@ def main() -> int:
119
178
  try:
120
179
  import push_hold # type: ignore
121
180
  except Exception as exc: # pragma: no cover — exercised by installer test
122
- return _fail_open(f"could not import push_hold: {exc!r}")
181
+ return _fail_open(f"could not import push_hold: {exc!r}", repo=repo)
123
182
 
124
183
  try:
125
184
  stdin_lines = sys.stdin.readlines()
126
185
  except OSError as exc:
127
- return _fail_open(f"could not read stdin: {exc!r}")
186
+ return _fail_open(f"could not read stdin: {exc!r}", repo=repo)
128
187
 
129
188
  verdict = push_hold.evaluate_push(repo, stdin_lines, env=os.environ)
130
189
  action = verdict.get("action", "allow")
131
190
  if action == "block":
132
191
  sys.stderr.write(_format_block_message(verdict))
133
192
  return int(verdict.get("exit_code") or 1)
134
- # allow / bypass / anything else → exit 0
193
+ # allow / bypass / anything else → exit 0.
194
+ # Arm the post-push closeout baton BEFORE the push completes — git has
195
+ # no native client-side post-push hook, so the next session-start
196
+ # drains the baton via ``python3 -m closeout --source post-push-armed``.
197
+ _arm_post_push_closeout(repo)
135
198
  return 0
136
199
  except Exception as exc: # noqa: BLE001 — broad on purpose; we MUST fail-open
137
- return _fail_open(f"unhandled exception: {exc!r}")
200
+ return _fail_open(f"unhandled exception: {exc!r}", repo=repo)
138
201
 
139
202
 
140
203
  if __name__ == "__main__":
package/hooks/hooks.json CHANGED
@@ -33,6 +33,26 @@
33
33
  "type": "command",
34
34
  "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/session-start-plugin-drift.sh\" </dev/null >/dev/null 2>&1; exit 0",
35
35
  "timeout": 2000
36
+ },
37
+ {
38
+ "type": "command",
39
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/session-start-plugin-heal.sh\" </dev/null >/dev/null 2>&1; exit 0",
40
+ "timeout": 2000
41
+ },
42
+ {
43
+ "type": "command",
44
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/session-start-memory.sh\" </dev/null >/dev/null 2>&1; exit 0",
45
+ "timeout": 6000
46
+ },
47
+ {
48
+ "type": "command",
49
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/session-start-closeout.sh\" </dev/null >/dev/null 2>&1; exit 0",
50
+ "timeout": 3000
51
+ },
52
+ {
53
+ "type": "command",
54
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/closeout.sh\" session-start </dev/null 2>/dev/null; exit 0",
55
+ "timeout": 3000
36
56
  }
37
57
  ]
38
58
  }
@@ -58,18 +78,8 @@
58
78
  "hooks": [
59
79
  {
60
80
  "type": "command",
61
- "command": "root=\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}\"; hook=\"$root/scripts/hooks/pre_bash_autonomy.sh\"; if [ -x \"$hook\" ]; then \"$hook\"; else printf '{}'; fi",
62
- "timeout": 2000
63
- },
64
- {
65
- "type": "command",
66
- "command": "root=\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}\"; hook=\"$root/scripts/hooks/pre_bash_dependency_cooldown.sh\"; if [ -x \"$hook\" ]; then \"$hook\"; else printf '{}'; fi",
67
- "timeout": 2000
68
- },
69
- {
70
- "type": "command",
71
- "command": "root=\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}\"; hook=\"$root/scripts/audit_before_commit.py\"; if [ -f \"$hook\" ]; then python3 \"$hook\"; else printf '{}'; fi",
72
- "timeout": 5000
81
+ "command": "root=\"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}\"; hook=\"$root/scripts/hooks/pre_bash_dispatch.sh\"; if [ -x \"$hook\" ]; then \"$hook\"; else printf '{}'; fi",
82
+ "timeout": 9000
73
83
  },
74
84
  {
75
85
  "type": "command",
@@ -85,7 +95,13 @@
85
95
  "hooks": [
86
96
  {
87
97
  "type": "command",
88
- "command": "[ -f .build-loop/state.json ] || exit 0; python3 -c \"import json,sys; s=json.load(open('.build-loop/state.json')); p7=s.get('phases',{}).get('fact_check',{}).get('completed',False); active=s.get('active',False); sys.exit(0 if (not active or p7) else 1)\" 2>/dev/null && exit 0; echo \"$TOOL_INPUT\" | grep -qE '\\b(git\\s+push|npm\\s+publish|vercel\\s+deploy|gh\\s+release)\\b' && echo 'Build loop Phase 7 (fact-check) has not completed. Run fact-check before deploying.'; exit 0"
98
+ "command": "[ -f .build-loop/state.json ] || exit 0; python3 -c \"import json,sys; s=json.load(open('.build-loop/state.json')); p7=s.get('phases',{}).get('fact_check',{}).get('completed',False); active=s.get('active',False); sys.exit(0 if (not active or p7) else 1)\" 2>/dev/null && exit 0; echo \"$TOOL_INPUT\" | grep -qE '\\b(git\\s+push|npm\\s+publish|vercel\\s+deploy|gh\\s+release)\\b' && echo 'Build loop Phase 7 (fact-check) has not completed. Run fact-check before deploying.'; exit 0",
99
+ "timeout": 3000
100
+ },
101
+ {
102
+ "type": "command",
103
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/post-push-closeout.sh\" </dev/null >/dev/null 2>&1; exit 0",
104
+ "timeout": 2000
89
105
  }
90
106
  ]
91
107
  }
@@ -118,6 +134,11 @@
118
134
  "type": "command",
119
135
  "command": "if [ -f \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/scripts/commit_state_check.py\" ]; then python3 \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/scripts/commit_state_check.py\" --workdir \"${CLAUDE_PROJECT_DIR}\" --hook; else printf '{}'; fi",
120
136
  "timeout": 5000
137
+ },
138
+ {
139
+ "type": "command",
140
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT:-$CLAUDE_PROJECT_DIR}/hooks/closeout.sh\" stop 2>/dev/null; exit 0",
141
+ "timeout": 6000
121
142
  }
122
143
  ]
123
144
  }