@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
@@ -0,0 +1,73 @@
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
+ # post-push-closeout.sh — warm-context soft closeout after a `git push`.
6
+ #
7
+ # Triggered by Claude Code PostToolUse:Bash (see hooks/hooks.json). When the
8
+ # command that just ran was a `git push`, fire the EXISTING closeout in the
9
+ # BACKGROUND (nohup) while context is still warm. This complements — does NOT
10
+ # replace — the crash-fallback path:
11
+ #
12
+ # - pre-push (hooks/git/pre-push) arms .build-loop/closeout/armed.json.
13
+ # - next SessionStart (hooks/session-start-closeout.sh) drains the baton.
14
+ #
15
+ # This hook short-circuits that fallback in the common case by draining
16
+ # immediately in the background. It reuses `python3 -m closeout` verbatim — NO
17
+ # duplicated closeout logic. Because closeout writes durable memory + clears the
18
+ # baton on success, the next SessionStart simply finds nothing to drain.
19
+ #
20
+ # Discipline: PostToolUse hooks observe; this one never blocks the tool result.
21
+ # Fail-open (always exit 0). The actual closeout runs detached so a slow memory
22
+ # write never stalls the agent's turn. Minimal-PATH safe (resolves python3 via
23
+ # command -v); no bare `set -e`.
24
+
25
+ set -u
26
+
27
+ # PostToolUse passes the tool command; Claude Code exposes it as $TOOL_INPUT
28
+ # (matching the sibling Bash matcher in hooks.json). Fall back to reading stdin
29
+ # JSON if the env var is absent (host portability).
30
+ CMD="${TOOL_INPUT:-}"
31
+ if [ -z "$CMD" ]; then
32
+ # Best-effort: some hosts deliver the payload on stdin as JSON.
33
+ STDIN_JSON="$(cat 2>/dev/null || true)"
34
+ CMD="$STDIN_JSON"
35
+ fi
36
+
37
+ # Only act on a real `git push`. Anchor on the verb pair to avoid matching
38
+ # `git push --help`-style noise loosely; a trailing `--dry-run` push still
39
+ # closes out harmlessly (closeout is idempotent + fail-open).
40
+ printf '%s' "$CMD" | grep -qE '\bgit[[:space:]]+push\b' || exit 0
41
+
42
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${PWD}}"
43
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${PROJECT_DIR}}"
44
+
45
+ # A closeout only makes sense inside a build-loop project.
46
+ [ -d "${PROJECT_DIR}/.build-loop" ] || exit 0
47
+
48
+ # Resolve python3 without depending on a populated PATH (shared helper).
49
+ _HOOK_DIR="$(dirname "$0")"
50
+ _py=""
51
+ [ -f "${_HOOK_DIR}/_resolve_python.sh" ] && . "${_HOOK_DIR}/_resolve_python.sh"
52
+ [ -n "$_py" ] || exit 0
53
+
54
+ CLOSEOUT_LOG_DIR="${PROJECT_DIR}/.build-loop/closeout"
55
+ mkdir -p "$CLOSEOUT_LOG_DIR" 2>/dev/null || true
56
+ RID="postpush-$(date -u +%Y%m%dT%H%M%SZ)"
57
+
58
+ # Ensure the closeout package (scripts/closeout/) is importable regardless of
59
+ # the invoking environment's PYTHONPATH (hooks run under minimal PATH; the package
60
+ # is not installed globally — it lives under PLUGIN_ROOT/scripts/).
61
+ export PYTHONPATH="${PLUGIN_ROOT}/scripts${PYTHONPATH:+:$PYTHONPATH}"
62
+
63
+ # Fire the existing closeout in the background; never block the turn. On success
64
+ # the closeout module clears the armed baton, so the SessionStart fallback finds
65
+ # nothing to do. Detached + redirected so the agent's turn returns immediately.
66
+ nohup "$_py" -m closeout \
67
+ --workdir "$PROJECT_DIR" \
68
+ --run-id "$RID" \
69
+ --source post-push \
70
+ --json \
71
+ >"${CLOSEOUT_LOG_DIR}/${RID}.stdout.json" 2>/dev/null &
72
+
73
+ exit 0
@@ -0,0 +1,69 @@
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
+ # session-start-closeout.sh — drain a post-push armed baton and surface
6
+ # pending-lesson candidates to the host coding agent.
7
+ #
8
+ # Triggered by Claude Code SessionStart (see hooks/hooks.json). Fail-open
9
+ # (always ``exit 0``) so a broken hook can never wedge a session start.
10
+ #
11
+ # Two responsibilities:
12
+ # 1. If ``.build-loop/closeout/armed.json`` exists, the previous session
13
+ # ran ``git push``. Drain the baton by invoking ``python3 -m closeout``
14
+ # with ``--source post-push-armed`` and delete the baton on success.
15
+ # 2. Surface pending-lesson candidates (one-shot) so the host agent sees
16
+ # them in the next turn without having to re-discover them.
17
+ #
18
+ # Minimal PATH safe: resolves ``python3`` via ``command -v``; bare ``set -e``
19
+ # is intentionally avoided.
20
+
21
+ set -u
22
+
23
+ # Resolve the project / plugin root.
24
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-${PWD}}"
25
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${PROJECT_DIR}}"
26
+
27
+ # Resolve a python3 binary without depending on PATH being populated (shared helper).
28
+ _HOOK_DIR="$(dirname "$0")"
29
+ _py=""
30
+ [ -f "${_HOOK_DIR}/_resolve_python.sh" ] && . "${_HOOK_DIR}/_resolve_python.sh"
31
+ [ -n "$_py" ] || exit 0
32
+
33
+ ARMED="${PROJECT_DIR}/.build-loop/closeout/armed.json"
34
+ CLOSEOUT_LOG_DIR="${PROJECT_DIR}/.build-loop/closeout"
35
+ mkdir -p "$CLOSEOUT_LOG_DIR" 2>/dev/null || true
36
+
37
+ # Ensure the closeout package (scripts/closeout/) is importable in hook env.
38
+ # PLUGIN_ROOT already resolves to the repo root (see above); scripts/ is the
39
+ # package parent. Set once here so both the closeout call and surface_pending use it.
40
+ export PYTHONPATH="${PLUGIN_ROOT}/scripts${PYTHONPATH:+:$PYTHONPATH}"
41
+
42
+ # 1. Drain the armed baton if present.
43
+ if [ -f "$ARMED" ]; then
44
+ RID="armed-$(date -u +%Y%m%dT%H%M%SZ)"
45
+ "$_py" -m closeout \
46
+ --workdir "$PROJECT_DIR" \
47
+ --run-id "$RID" \
48
+ --source post-push-armed \
49
+ --json \
50
+ 2>/dev/null \
51
+ >"${CLOSEOUT_LOG_DIR}/${RID}.stdout.json" \
52
+ && rm -f "$ARMED" 2>/dev/null \
53
+ || true
54
+ fi
55
+
56
+ # 2. Surface pending-lesson candidates (quiet — nothing prints when empty).
57
+ SURFACED="${CLOSEOUT_LOG_DIR}/surfaced-$(date -u +%Y%m%dT%H%M%SZ).md"
58
+ "$_py" "${PLUGIN_ROOT}/scripts/surface_pending_lessons.py" \
59
+ --workdir "$PROJECT_DIR" \
60
+ --quiet \
61
+ 2>/dev/null \
62
+ >"$SURFACED" \
63
+ || true
64
+ # Drop the surfaced file when empty so the directory stays clean.
65
+ if [ ! -s "$SURFACED" ]; then
66
+ rm -f "$SURFACED" 2>/dev/null || true
67
+ fi
68
+
69
+ exit 0
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ # Bootstrap build-loop-memory on session start (idempotent, fail-open).
4
+ # Seeds the central memory store (constitution.md, MEMORY.md, indexes/,
5
+ # projects/) from the packaged PUBLIC seed only when the store is entirely
6
+ # absent. install_memory.py is idempotent (skip-if-exists) and copies no
7
+ # personal content. Never blocks, never overwrites, never errors the session.
8
+ # Repair of a partial store is the user-facing `/build-loop:setup-memory` job.
9
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PROJECT_DIR:-$PWD}}"
10
+ installer="${PLUGIN_ROOT}/scripts/install_memory.py"
11
+ [ -f "$installer" ] || exit 0
12
+ command -v python3 >/dev/null 2>&1 || exit 0
13
+
14
+ # Seed only when the store ROOT dir is missing. Parse --check JSON properly so a
15
+ # nested per-file "exists" cannot be mistaken for the top-level store flag.
16
+ # (python3 -c, not a heredoc: a heredoc inside $() with an apostrophe trips
17
+ # macOS bash 3.2 tokenization.)
18
+ need="$(python3 -c '
19
+ import json, subprocess, sys
20
+ try:
21
+ out = subprocess.run([sys.executable, sys.argv[1], "--check", "--json"], capture_output=True, text=True, timeout=5).stdout
22
+ print("1" if not json.loads(out).get("exists") else "0")
23
+ except Exception:
24
+ print("0")
25
+ ' "$installer")"
26
+ [ "$need" = "1" ] && python3 "$installer" >/dev/null 2>&1
27
+ exit 0
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env bash
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ # Plugin-cache self-heal, fire-and-forget, plugin-relative.
4
+ #
5
+ # Heals a Claude Code plugin install whose versioned cache dir vanished while
6
+ # another session was bound to it. Two cases:
7
+ # A) /plugin install archived the prior dir to ~/.claude/plugins/removed/
8
+ # → move it back to its registered installPath.
9
+ # B) /plugin update hard-deleted the prior dir after installing a newer one
10
+ # → create a symlink old→new so the frozen ${CLAUDE_PLUGIN_ROOT} path
11
+ # resolves to live scripts.
12
+ #
13
+ # Heals the NEXT session (CC re-resolves ${CLAUDE_PLUGIN_ROOT} only at session
14
+ # start). Cannot save a currently-bound dead-path session — restart-or-symlink
15
+ # remains the only in-session remedy.
16
+ #
17
+ # Opt out: BUILDLOOP_NO_PLUGIN_HEAL=1.
18
+ D="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ . "$D/_session_start_lib.sh"
20
+ ROOT="${CLAUDE_PLUGIN_ROOT:-$D/..}"
21
+ # Heal only runs against ~/.claude (Claude Code's pre-validate-dir-exists is
22
+ # the hazard; Codex doesn't have the same harness behaviour). Cheap-skip on
23
+ # Codex hosts by path heuristic.
24
+ case "$ROOT" in
25
+ */.codex/*) exit 0 ;;
26
+ esac
27
+ if [ "${BUILDLOOP_NO_PLUGIN_HEAL:-}" = "1" ]; then
28
+ exit 0
29
+ fi
30
+ if [ -f "$ROOT/scripts/hooks/plugin_dir_heal.py" ]; then
31
+ bl_fire_bg "$ROOT/scripts/hooks/plugin_dir_heal.py"
32
+ fi
33
+ exit 0
@@ -0,0 +1,124 @@
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
+ # test_closeout.sh — integration tests for hooks/closeout.sh + scripts/stop_closeout.py (f6).
6
+ #
7
+ # Exercises the bash shim end-to-end (the part the python unit tests can't cover):
8
+ # self-gating, minimal-PATH safety, interpreter fail-open, and the session-id
9
+ # stdin path. Run directly: bash hooks/test_closeout.sh
10
+
11
+ set -u
12
+
13
+ REPO="$(cd "$(dirname "$0")/.." && pwd)"
14
+ HOOK="$REPO/hooks/closeout.sh"
15
+ PASS=0
16
+ FAIL=0
17
+
18
+ ok() { PASS=$((PASS+1)); printf ' ok %s\n' "$1"; }
19
+ bad() { FAIL=$((FAIL+1)); printf ' FAIL %s\n' "$1"; }
20
+
21
+ # Build a throwaway project with a recordable inline run (matching session,
22
+ # stakes-gated, not yet in runs[]).
23
+ make_project() {
24
+ local dir; dir="$(mktemp -d)"
25
+ mkdir -p "$dir/.build-loop"
26
+ cat >"$dir/.build-loop/state.json" <<'JSON'
27
+ {
28
+ "phase": "done",
29
+ "triggers": {"riskSurfaceChange": true},
30
+ "execution": {
31
+ "build_loop_id": "bl-itest-001",
32
+ "current_session_id": "sess-itest",
33
+ "started_by_session_id": "sess-itest",
34
+ "last_heartbeat_at": "2999-01-01T00:00:00Z",
35
+ "run_label": "itest#001"
36
+ },
37
+ "runs": []
38
+ }
39
+ JSON
40
+ printf '%s' "$dir"
41
+ }
42
+
43
+ runs_count() { python3 -c "import json,sys;print(len(json.load(open(sys.argv[1])).get('runs',[])))" "$1/.build-loop/state.json"; }
44
+
45
+ # --- 1. present + matching session → records + surfaces WARN + exit 0 -------
46
+ P="$(make_project)"
47
+ OUT="$(printf '{"session_id":"sess-itest"}' | CLAUDE_PROJECT_DIR="$P" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" stop)"
48
+ RC=$?
49
+ if [ "$RC" -eq 0 ] && [ "$(runs_count "$P")" = "1" ] && printf '%s' "$OUT" | grep -q '"systemMessage"' && printf '%s' "$OUT" | grep -q 'WARN'; then
50
+ ok "present+stakes → append_run ran + WARN surfaced + exit 0"
51
+ else
52
+ bad "present+stakes (rc=$RC runs=$(runs_count "$P") out=$OUT)"
53
+ fi
54
+ [ -f "$P/.build-loop/closeout-pending/bl-itest-001.md" ] && ok "closeout-pending marker written" || bad "marker not written"
55
+
56
+ # --- 1b. second Stop in the same run → no-op (no double-record, no advisory) -
57
+ OUT2="$(printf '{"session_id":"sess-itest"}' | CLAUDE_PROJECT_DIR="$P" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" stop)"
58
+ if [ "$(runs_count "$P")" = "1" ] && ! printf '%s' "$OUT2" | grep -q 'systemMessage'; then
59
+ ok "second Stop same run → no-op"
60
+ else
61
+ bad "second Stop not idempotent (runs=$(runs_count "$P") out=$OUT2)"
62
+ fi
63
+
64
+ # --- 1c. session-start surfaces the marker once, then archives it -----------
65
+ OUT3="$(CLAUDE_PROJECT_DIR="$P" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" session-start </dev/null)"
66
+ if printf '%s' "$OUT3" | grep -q 'additionalContext' && printf '%s' "$OUT3" | grep -q 'bl-itest-001' \
67
+ && [ ! -f "$P/.build-loop/closeout-pending/bl-itest-001.md" ] \
68
+ && [ -f "$P/.build-loop/closeout-pending/surfaced/bl-itest-001.md" ]; then
69
+ ok "session-start surfaced marker once + archived"
70
+ else
71
+ bad "session-start surfacing (out=$OUT3)"
72
+ fi
73
+ rm -rf "$P"
74
+
75
+ # --- 2. no .build-loop/ → silent exit 0 ------------------------------------
76
+ P2="$(mktemp -d)"
77
+ OUT="$(printf '{"session_id":"x"}' | CLAUDE_PROJECT_DIR="$P2" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" stop)"
78
+ RC=$?
79
+ if [ "$RC" -eq 0 ] && [ -z "$OUT" ]; then
80
+ ok "no .build-loop/ → silent exit 0"
81
+ else
82
+ bad "no .build-loop (rc=$RC out=$OUT)"
83
+ fi
84
+ rm -rf "$P2"
85
+
86
+ # --- 3. minimal PATH (/usr/bin:/bin — the real hook env) → still works ------
87
+ P3="$(make_project)"
88
+ OUT="$(printf '{"session_id":"sess-itest"}' | env -i PATH="/usr/bin:/bin" CLAUDE_PROJECT_DIR="$P3" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" stop)"
89
+ RC=$?
90
+ if [ "$RC" -eq 0 ] && [ "$(runs_count "$P3")" = "1" ]; then
91
+ ok "minimal PATH=/usr/bin:/bin → records + exit 0"
92
+ else
93
+ bad "minimal PATH (rc=$RC runs=$(runs_count "$P3") out=$OUT)"
94
+ fi
95
+ rm -rf "$P3"
96
+
97
+ # --- 4. broken PATH (python not on PATH) → resolves via absolute fallback ---
98
+ # Invoke bash by absolute path (so the harness itself survives the broken PATH);
99
+ # inside, command -v python3 fails and the script must fall back to an absolute
100
+ # python (/usr/bin/python3 …). Contract: exit 0, never crash, valid/empty JSON.
101
+ P4="$(make_project)"
102
+ OUT="$(printf '{"session_id":"sess-itest"}' | env -i PATH="/nonexistent" CLAUDE_PROJECT_DIR="$P4" CLAUDE_PLUGIN_ROOT="$REPO" /bin/bash "$HOOK" stop 2>/dev/null)"
103
+ RC=$?
104
+ if [ "$RC" -eq 0 ] && { [ -z "$OUT" ] || printf '%s' "$OUT" | python3 -c 'import json,sys;json.load(sys.stdin)' 2>/dev/null; }; then
105
+ ok "broken PATH → fail-open exit 0 (absolute-fallback python or silent skip)"
106
+ else
107
+ bad "broken PATH not fail-open (rc=$RC out=$OUT)"
108
+ fi
109
+ rm -rf "$P4"
110
+
111
+ # --- 5. helper script missing (fake plugin root) → silent exit 0 -----------
112
+ P5="$(make_project)"
113
+ FAKE="$(mktemp -d)" # no scripts/stop_closeout.py here
114
+ OUT="$(printf '{"session_id":"sess-itest"}' | CLAUDE_PROJECT_DIR="$P5" CLAUDE_PLUGIN_ROOT="$FAKE" bash "$HOOK" stop)"
115
+ RC=$?
116
+ if [ "$RC" -eq 0 ] && [ "$(runs_count "$P5")" = "0" ]; then
117
+ ok "missing helper script → silent exit 0 (no record)"
118
+ else
119
+ bad "missing helper not fail-open (rc=$RC runs=$(runs_count "$P5") out=$OUT)"
120
+ fi
121
+ rm -rf "$P5" "$FAKE"
122
+
123
+ printf '\n%d passed, %d failed\n' "$PASS" "$FAIL"
124
+ [ "$FAIL" -eq 0 ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tyroneross/build-loop",
3
- "version": "0.30.3",
3
+ "version": "0.34.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://npm.pkg.github.com",
6
6
  "access": "public"
@@ -18,12 +18,14 @@
18
18
  "files": [
19
19
  "dist",
20
20
  "codex-skills",
21
+ "plugin-artifacts/codex",
21
22
  "commands",
22
23
  "skills",
23
24
  "scripts/_paths.py",
24
25
  "scripts/_db_url.py",
25
26
  "scripts/blm.py",
26
27
  "scripts/blm_api.py",
28
+ "scripts/build_codex_plugin_artifact.py",
27
29
  "scripts/check_cache_sync.py",
28
30
  "scripts/embed_backend.py",
29
31
  "scripts/install_memory.py",
@@ -44,7 +46,7 @@
44
46
  ".cursor",
45
47
  ".claude-plugin",
46
48
  ".codex-plugin",
47
- ".agents",
49
+ ".agents/plugins",
48
50
  "README.md",
49
51
  "AGENTS.md",
50
52
  "LICENSE",
@@ -61,10 +63,11 @@
61
63
  "clean": "rm -rf dist",
62
64
  "plugin:prune-cache": "python3 scripts/prune_plugin_cache.py --source .",
63
65
  "plugin:prune-cache:apply": "python3 scripts/prune_plugin_cache.py --source . --apply",
64
- "plugin:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host all",
66
+ "plugin:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host claude && npm run codex:sync-cache",
65
67
  "plugin:sync-cache:hooks": "python3 scripts/sync_plugin_cache.py --source . --host all --install-git-hooks",
66
68
  "codex:prune-cache": "python3 scripts/prune_codex_plugin_cache.py --source .",
67
- "codex:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host codex",
69
+ "codex:build-artifact": "python3 scripts/build_codex_plugin_artifact.py --source . --target plugin-artifacts/codex",
70
+ "codex:sync-cache": "npm run codex:build-artifact && python3 scripts/sync_plugin_cache.py --source plugin-artifacts/codex --host codex",
68
71
  "codex:prune-cache:apply": "python3 scripts/prune_codex_plugin_cache.py --source . --apply",
69
72
  "claude:prune-cache": "python3 scripts/prune_plugin_cache.py --source . --host claude",
70
73
  "claude:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host claude",
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "build-loop",
3
+ "version": "0.33.0",
4
+ "description": "Multi-phase build orchestration with native debugging: assess, plan, execute, review, iterate. Plan-verify gate on Phase 2. Optional UI design gates. Native debug-loop, debugging-memory, and logging-tracer skills provide root-cause investigation without a bundled MCP server. Orchestrator owns when-to-fire; bundled skills own procedural detail; bridges are optional escalation hops to supporting plugins for extended capability.",
5
+ "author": {
6
+ "name": "Tyrone Ross",
7
+ "url": "https://github.com/tyroneross"
8
+ },
9
+ "homepage": "https://github.com/tyroneross/build-loop#readme",
10
+ "repository": "https://github.com/tyroneross/build-loop",
11
+ "license": "Apache-2.0",
12
+ "keywords": [
13
+ "development",
14
+ "orchestration",
15
+ "evaluation",
16
+ "iteration",
17
+ "build",
18
+ "tdd",
19
+ "fact-checking",
20
+ "code-quality",
21
+ "ui-validation",
22
+ "accessibility",
23
+ "design-rules",
24
+ "debug-loop",
25
+ "debugging",
26
+ "causal-tree",
27
+ "incident-memory"
28
+ ],
29
+ "skills": "./skills",
30
+ "interface": {
31
+ "displayName": "Build Loop",
32
+ "shortDescription": "Multi-phase build orchestration with review gates, UI validation, debugging, and a Codex subagent adapter.",
33
+ "longDescription": "Multi-phase build orchestration with native debugging: assess, plan, execute, review, iterate. Plan-verify gate on Phase 2. Optional UI design gates. Native debug-loop, debugging-memory, and logging-tracer skills provide root-cause investigation without a bundled MCP server. Orchestrator owns when-to-fire; bundled skills own procedural detail; bridges are optional escalation hops to supporting plugins for extended capability.",
34
+ "developerName": "Ross Labs",
35
+ "category": "Coding",
36
+ "capabilities": [
37
+ "Read",
38
+ "Write"
39
+ ]
40
+ }
41
+ }