@tyroneross/build-loop 0.36.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/plugins/marketplace.json +2 -2
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor/rules/build-loop-surface.mdc +12 -11
- package/.cursor/rules/skill-index.mdc +33 -0
- package/AGENTS.md +213 -34
- package/README.md +99 -31
- package/agents/advisor.md +4 -4
- package/agents/alignment-checker.md +2 -2
- package/agents/architecture-scout.md +4 -4
- package/agents/build-orchestrator.md +38 -36
- package/agents/database-assessor.md +11 -5
- package/agents/design-contract-specialist.md +8 -8
- package/agents/fact-checker.md +13 -3
- package/agents/fix-critique.md +2 -2
- package/agents/independent-auditor.md +60 -7
- package/agents/leak-scanner.md +82 -0
- package/agents/overfitting-reviewer.md +2 -2
- package/agents/plan-critic.md +1 -1
- package/agents/promotion-reviewer.md +5 -5
- package/agents/retrospective-synthesizer.md +138 -35
- package/agents/scope-auditor.md +82 -11
- package/agents/security-reviewer.md +56 -2
- package/agents/self-improvement-architect.md +17 -3
- package/agents/transcript-pattern-miner.md +5 -5
- package/agents/ui-validator.md +1 -1
- package/bin/build-loop-debugger.js +143 -0
- package/bin/build-loop-install.js +1 -4
- package/bin/build-loop-load-probe.js +345 -0
- package/codex-skills/build-loop/SKILL.md +28 -6
- package/commands/feedback.md +37 -0
- package/dist/src/interactive-verifier.d.ts +1 -14
- package/dist/src/interactive-verifier.d.ts.map +1 -1
- package/dist/src/interactive-verifier.js +6 -113
- package/dist/src/interactive-verifier.js.map +1 -1
- package/dist/src/quality.d.ts +5 -0
- package/dist/src/quality.d.ts.map +1 -0
- package/dist/src/quality.js +81 -0
- package/dist/src/quality.js.map +1 -0
- package/dist/src/storage.d.ts.map +1 -1
- package/dist/src/storage.js +37 -3
- package/dist/src/storage.js.map +1 -1
- package/docs/agent-surface-policy.md +35 -31
- package/docs/memory-setup.md +19 -0
- package/hooks/git/pre-push +65 -4
- package/hooks/hooks.json +95 -38
- package/hooks/pre-commit +20 -1
- package/hooks/pre-edit-rally-point.sh +10 -3
- package/hooks/session-start-codex-hook-trust.sh +30 -0
- package/hooks/session-start-git-hooks.sh +3 -1
- package/hooks/session-start-rally-point.sh +52 -4
- package/hooks/session-start-worktree-gc.sh +47 -94
- package/hooks/stop-transcript-sweep.sh +173 -0
- package/hooks/test_closeout.sh +14 -2
- package/package.json +8 -7
- package/scripts/README.md +1 -1
- package/scripts/_paths.py +65 -0
- package/scripts/groundwork_exchange.py +1012 -0
- package/scripts/install_memory.py +33 -1
- package/scripts/lessons_index/ingest.py +13 -2
- package/scripts/lessons_index/query.py +36 -13
- package/scripts/memory_context/__init__.py +108 -14
- package/scripts/memory_graph/__init__.py +5 -1
- package/scripts/project_resolver.py +42 -36
- package/scripts/sync_plugin_cache.py +37 -2
- package/skills/agent-rally-point/SKILL.md +46 -0
- package/skills/api-registry-bridge/SKILL.md +1 -1
- package/skills/architecture/dead/SKILL.md +1 -1
- package/skills/architecture/impact/SKILL.md +1 -1
- package/skills/architecture/review/SKILL.md +1 -1
- package/skills/architecture/rules/SKILL.md +3 -3
- package/skills/architecture/scan/SKILL.md +1 -1
- package/skills/architecture/trace/SKILL.md +1 -1
- package/skills/attribution-standard/SKILL.md +6 -6
- package/skills/auto-decision-capture/SKILL.md +31 -2
- package/skills/auto-finding-capture/SKILL.md +28 -1
- package/skills/build-loop/SKILL.md +131 -23
- package/skills/build-loop/fallbacks.md +16 -21
- package/skills/build-loop/phases/ui-validation.md +2 -2
- package/skills/build-loop/references/advisor-dispatch-ladder.md +1 -1
- package/skills/build-loop/references/apple-native-planning.md +1 -1
- package/skills/build-loop/references/autonomous-and-per-commit-modes.md +11 -5
- package/skills/build-loop/references/autonomy-dashboard.md +115 -0
- package/skills/build-loop/references/capability-routing.md +24 -2
- package/skills/build-loop/references/coordination.md +24 -6
- package/skills/build-loop/references/experiment-results-template.md +15 -3
- package/skills/build-loop/references/leadership.md +1 -1
- package/skills/build-loop/references/memory.md +14 -3
- package/skills/build-loop/references/modular-systems-pack.md +8 -0
- package/skills/build-loop/references/output-style.md +86 -0
- package/skills/build-loop/references/phase-1-assess.md +102 -2
- package/skills/build-loop/references/phase-2-plan.md +9 -1
- package/skills/build-loop/references/phase-3-execute.md +5 -2
- package/skills/build-loop/references/phase-4-review.md +85 -8
- package/skills/build-loop/references/phase-5-iterate.md +76 -8
- package/skills/build-loop/references/phase-6-learn.md +10 -17
- package/skills/build-loop/references/privileged-request-broker.md +254 -0
- package/skills/build-loop/references/resource-aware-execution.md +183 -0
- package/skills/build-loop/references/self-recursive-dev.md +2 -2
- package/skills/build-loop/references/status-output-format.md +207 -0
- package/skills/build-loop/references/verify-dispatch.md +56 -2
- package/skills/building-with-deepagents/SKILL.md +1 -1
- package/skills/claim-scope/SKILL.md +185 -0
- package/skills/color-engine/SKILL.md +103 -0
- package/skills/color-engine/_core.py +464 -0
- package/skills/color-engine/color_engine.py +175 -0
- package/skills/cost-rca/SKILL.md +61 -0
- package/skills/data-plane-worktrees/SKILL.md +139 -0
- package/skills/data-plane-worktrees/agents/openai.yaml +4 -0
- package/skills/database-practice/SKILL.md +200 -0
- package/skills/database-practice/references/diagnostic-queries.sql +126 -0
- package/skills/database-practice/references/vector-and-graph-tuning.md +208 -0
- package/skills/database-practice/scripts/db_table_map.py +1244 -0
- package/skills/database-practice/scripts/test_db_table_map.py +514 -0
- package/skills/debug-loop/SKILL.md +36 -6
- package/skills/debugging-memory/SKILL.md +32 -430
- package/skills/debugging-memory/references/pattern-extraction.md +4 -4
- package/skills/debugging-memory/references/search.md +32 -120
- package/skills/debugging-memory/references/store.md +32 -126
- package/skills/debugging-memory/references/subagent-integration.md +1 -1
- package/skills/decision-queue/SKILL.md +251 -0
- package/skills/decision-queue/assets/template.html +1242 -0
- package/skills/decision-queue/references/example-large-queue-batching.md +164 -0
- package/skills/decision-queue/scripts/regen_template_constants.py +160 -0
- package/skills/defenseclaw-bridge/SKILL.md +2 -2
- package/skills/defenseclaw-bridge/references/dc-config-mapping.md +2 -9
- package/skills/drain-proposals/SKILL.md +53 -0
- package/skills/focused-loop-builder/SKILL.md +31 -0
- package/skills/focused-loop-builder/references/spec-format.md +27 -0
- package/skills/handoff/SKILL.md +169 -8
- package/skills/ibr-bridge/SKILL.md +4 -1
- package/skills/knowledge/SKILL.md +26 -14
- package/skills/knowledge/references/review-mode.md +2 -3
- package/skills/knowledge/templates/madr-minimal.md +1 -1
- package/skills/mcp-builder/SKILL.md +1 -1
- package/skills/model-bakeoff/SKILL.md +48 -10
- package/skills/model-tiering/SKILL.md +92 -31
- package/skills/native-ax-driver/SKILL.md +38 -5
- package/skills/native-ax-driver/scripts/native_driver.py +278 -22
- package/skills/native-ax-driver/scripts/test_native_driver.py +227 -0
- package/skills/optimize/SKILL.md +1 -1
- package/skills/plugin-builder/SKILL.md +48 -1
- package/skills/plugin-builder/references/build-loop-phase-guidance.md +3 -4
- package/skills/plugin-builder/references/distribution.md +13 -2
- package/skills/plugin-builder/references/plugin-hygiene-lessons.md +2 -2
- package/skills/plugin-tests/SKILL.md +2 -2
- package/skills/recursive-retrospective/SKILL.md +1 -1
- package/skills/repo-closeout/SKILL.md +17 -0
- package/skills/repo-closeout/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/SKILL.md +179 -0
- package/skills/repo-maintenance/agents/openai.yaml +4 -0
- package/skills/repo-maintenance/references/pre-public-hygiene.md +134 -0
- package/skills/repo-maintenance/references/repository-taxonomy.md +161 -0
- package/skills/repo-maintenance/references/safety-protocol.md +106 -0
- package/skills/repo-maintenance/references/stack-profiles.md +138 -0
- package/skills/repo-maintenance/scripts/audit_repo_maintenance.py +1198 -0
- package/skills/repo-maintenance/scripts/test_audit_repo_maintenance.py +506 -0
- package/skills/repository-intelligence/SKILL.md +189 -0
- package/skills/repository-intelligence/agents/openai.yaml +4 -0
- package/skills/repository-intelligence/references/assessment-rubric.md +88 -0
- package/skills/repository-intelligence/scripts/repository_inventory.py +347 -0
- package/skills/research/SKILL.md +12 -2
- package/skills/root-cause-analysis/SKILL.md +1 -1
- package/skills/runtime-parity-verification/SKILL.md +36 -1
- package/skills/security-methodology/SKILL.md +23 -10
- package/skills/security-methodology/references/agentic-handoff-templates.md +220 -0
- package/skills/security-methodology/references/cross-source-matrix.md +1 -1
- package/skills/security-methodology/references/owasp-agentic-top-10.md +1 -1
- package/skills/security-scan/SKILL.md +55 -15
- package/skills/self-improve/SKILL.md +70 -50
- package/skills/silent-assumptions/SKILL.md +341 -0
- package/skills/silent-assumptions/references/elicitation-detectors.md +342 -0
- package/skills/spec-writing/SKILL.md +128 -24
- package/skills/spec-writing/scripts/check_checklist.py +114 -15
- package/skills/ui-design/SKILL.md +6 -4
- package/skills/ui-design/references/color-engine.md +132 -0
- package/skills/ui-design/references/design-preferences-from-owned-apps.md +8 -8
- package/skills/ui-design/references/ui-guidance-sources.md +1 -1
- package/skills/ui-design/references/universal-design-principles.alt.md +2 -2
- package/plugin-artifacts/codex/.codex-plugin/plugin.json +0 -41
- package/plugin-artifacts/codex/AGENTS.md +0 -560
- package/plugin-artifacts/codex/BUILD-ARTIFACT.md +0 -5
- package/plugin-artifacts/codex/LICENSE +0 -202
- package/plugin-artifacts/codex/README.md +0 -313
- package/plugin-artifacts/codex/assets/build-loop-plugin-icon.png +0 -0
- package/plugin-artifacts/codex/docs/agent-surface-policy.md +0 -63
- package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/references/agent-role-taxonomy.md +0 -135
- package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/references/autonomy-config.md +0 -231
- package/plugin-artifacts/codex/references/backlog-system.md +0 -285
- package/plugin-artifacts/codex/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/references/coordination-file-template.md +0 -181
- package/plugin-artifacts/codex/references/coordination-rules.md +0 -552
- package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +0 -112
- package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +0 -102
- package/plugin-artifacts/codex/references/implementer-envelope-schema.md +0 -302
- package/plugin-artifacts/codex/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/references/leadership.md +0 -72
- package/plugin-artifacts/codex/references/memory-systems.md +0 -261
- package/plugin-artifacts/codex/references/memory.md +0 -313
- package/plugin-artifacts/codex/references/model-tier-mapping.md +0 -296
- package/plugin-artifacts/codex/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/references/research-trigger-policy.md +0 -140
- package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +0 -42
- package/plugin-artifacts/codex/references/self-review.md +0 -234
- package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +0 -90
- package/plugin-artifacts/codex/references/task-capture-policy.md +0 -68
- package/plugin-artifacts/codex/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +0 -65
- package/plugin-artifacts/codex/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/SKILL.md +0 -381
- package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +0 -82
- package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +0 -65
- package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +0 -549
- package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +0 -42
- package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +0 -267
- package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +0 -62
- package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +0 -439
- package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +0 -231
- package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +0 -106
- package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +0 -161
- package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +0 -177
- package/plugin-artifacts/codex/skills/build-loop/references/experiment-results-template.md +0 -101
- package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +0 -257
- package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/memory.md +0 -313
- package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +0 -96
- package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +0 -222
- package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +0 -98
- package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +0 -249
- package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +0 -86
- package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +0 -49
- package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +0 -341
- package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +0 -72
- package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +0 -58
- package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +0 -274
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +0 -149
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +0 -32
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +0 -48
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +0 -60
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +0 -51
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +0 -71
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +0 -52
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +0 -202
- package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +0 -77
- package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +0 -234
- package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +0 -116
- package/plugin-artifacts/codex/skills/build-loop/references/verify-dispatch.md +0 -85
- package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +0 -476
- package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +0 -239
- package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +0 -35
- package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +0 -100
- package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +0 -179
- package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +0 -40
- package/scripts/build_codex_plugin_artifact.py +0 -321
|
@@ -0,0 +1,173 @@
|
|
|
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
|
+
# stop-transcript-sweep.sh — launch ONE background transcript sweep from the
|
|
6
|
+
# Claude Code `Stop` hook.
|
|
7
|
+
#
|
|
8
|
+
# $1 = sweep: all | decisions | corrections | findings | cost-ledger
|
|
9
|
+
#
|
|
10
|
+
# `all` is the ONLY mode that should be REGISTERED as a hook. The four
|
|
11
|
+
# sweeps share a firing moment, an input, and an intent (extract signals
|
|
12
|
+
# from this session's transcript), so four registrations were four
|
|
13
|
+
# copies of one hook -- each re-resolving and re-normalizing the same
|
|
14
|
+
# transcript. One hook resolves once and fans out. The individual modes
|
|
15
|
+
# remain callable for testing and manual re-runs.
|
|
16
|
+
#
|
|
17
|
+
# WHY THIS EXISTS (the defect it fixes)
|
|
18
|
+
# ------------------------------------
|
|
19
|
+
# The four Stop-hook sweeps were previously guarded inline with
|
|
20
|
+
# `if [ -n "$CLAUDE_TRANSCRIPT_PATH" ]; then ... fi`. **There is no
|
|
21
|
+
# `CLAUDE_TRANSCRIPT_PATH` environment variable.** Claude Code delivers the
|
|
22
|
+
# transcript path ONLY inside the stdin JSON payload, as `transcript_path`
|
|
23
|
+
# (see https://code.claude.com/docs/en/hooks.md — documented hook env vars are
|
|
24
|
+
# CLAUDE_PROJECT_DIR / CLAUDE_PLUGIN_ROOT / CLAUDE_PLUGIN_DATA / CLAUDE_EFFORT /
|
|
25
|
+
# CLAUDE_CODE_REMOTE / CLAUDE_CODE_BRIDGE_SESSION_ID / CLAUDE_PLUGIN_OPTION_*).
|
|
26
|
+
# The guard was therefore false in every real session, the python never
|
|
27
|
+
# launched, and nothing logged — a completely silent failure. Forensics on
|
|
28
|
+
# `~/.local/state/build-loop/scan.log` (2026-05-05 .. 2026-08-11) found 0
|
|
29
|
+
# references to a real `~/.claude/projects/` transcript. See
|
|
30
|
+
# `scripts/hooks/session_end_retro_sweep.py::resolve_transcript` for the same
|
|
31
|
+
# note, and hooks/hooks.json SessionEnd for the pattern this mirrors.
|
|
32
|
+
#
|
|
33
|
+
# STDIN CONTRACT (verified live, 2026-08-14, Claude Code 2.1.232)
|
|
34
|
+
# ---------------------------------------------------------------
|
|
35
|
+
# Sibling hooks inside ONE matcher group run in PARALLEL and EACH command
|
|
36
|
+
# process is spawned with its OWN stdin pipe carrying a full copy of the
|
|
37
|
+
# payload. A three-sibling `cat > file` probe produced three byte-identical
|
|
38
|
+
# 562-byte payloads (same md5), so draining stdin here cannot starve a later
|
|
39
|
+
# hook. Reading stdin independently per entry is correct; no read-once-and-share
|
|
40
|
+
# coordination is needed. (`scripts/hooks/stop_finalize.sh` already does
|
|
41
|
+
# `INPUT=$(cat)` in this same group and has always worked, consistent with
|
|
42
|
+
# this.)
|
|
43
|
+
#
|
|
44
|
+
# Contract:
|
|
45
|
+
# - Advisory + fail-open: ALWAYS exit 0; never emits `decision: block`.
|
|
46
|
+
# - Emits `{}` on stdout (valid Stop-hook JSON) and nothing on stderr.
|
|
47
|
+
# - Backgrounds the sweep (`nohup ... &`) so the hook returns in <500ms.
|
|
48
|
+
# - Minimal-PATH safe: hooks run under /usr/bin:/bin. python3 is resolved via
|
|
49
|
+
# `command -v` + absolute fallbacks (hooks/_resolve_python.sh); missing
|
|
50
|
+
# python → silent no-op exit 0.
|
|
51
|
+
# - Payload values reach python via ARGV / env, never by shell-string
|
|
52
|
+
# interpolation into python source (closes docs/SECURITY_FOLLOWUP_2026-05-05.md).
|
|
53
|
+
#
|
|
54
|
+
# See memory `reference_hooks_minimal_path_failopen`.
|
|
55
|
+
|
|
56
|
+
set -u
|
|
57
|
+
|
|
58
|
+
SWEEP="${1:-}"
|
|
59
|
+
|
|
60
|
+
# Always emit valid no-op hook JSON and exit 0, whatever happened.
|
|
61
|
+
_noop() {
|
|
62
|
+
printf '{}'
|
|
63
|
+
exit 0
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
[ -n "$SWEEP" ] || _noop
|
|
67
|
+
|
|
68
|
+
# Read the Stop payload once. Empty/absent stdin is a normal no-op.
|
|
69
|
+
# Empty stdin is NORMAL on a host that supplies no Stop payload (Codex). The
|
|
70
|
+
# old `[ -n "$PAYLOAD" ] || _noop` here made every non-Claude host a silent
|
|
71
|
+
# no-op before the transcript was ever looked for.
|
|
72
|
+
PAYLOAD="$(cat 2>/dev/null || true)"
|
|
73
|
+
|
|
74
|
+
# Resolve python3 without depending on a populated PATH (shared helper).
|
|
75
|
+
_HOOK_DIR="$(dirname "$0")"
|
|
76
|
+
_py=""
|
|
77
|
+
[ -f "${_HOOK_DIR}/_resolve_python.sh" ] && . "${_HOOK_DIR}/_resolve_python.sh"
|
|
78
|
+
[ -n "$_py" ] || _noop
|
|
79
|
+
|
|
80
|
+
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PROJECT_DIR:-$PWD}}"
|
|
81
|
+
|
|
82
|
+
# Extract transcript_path + cwd from the payload. The payload is passed through
|
|
83
|
+
# the environment (never interpolated into the python source) so a value
|
|
84
|
+
# containing quotes or shell metacharacters cannot inject.
|
|
85
|
+
_BL_STOP_PAYLOAD="$PAYLOAD"
|
|
86
|
+
export _BL_STOP_PAYLOAD
|
|
87
|
+
# Two newline-separated lines: transcript_path, then cwd. Newlines are stripped
|
|
88
|
+
# from the values so the line framing can't be spoofed by a crafted payload.
|
|
89
|
+
_parsed="$(
|
|
90
|
+
"$_py" - <<'PY' 2>/dev/null
|
|
91
|
+
import json, os
|
|
92
|
+
try:
|
|
93
|
+
d = json.loads(os.environ.get("_BL_STOP_PAYLOAD", "") or "{}")
|
|
94
|
+
if not isinstance(d, dict):
|
|
95
|
+
d = {}
|
|
96
|
+
except Exception:
|
|
97
|
+
d = {}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def safe(v):
|
|
101
|
+
return " ".join(str(v or "").split("\n"))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
print(safe(d.get("transcript_path")))
|
|
105
|
+
print(safe(d.get("cwd")))
|
|
106
|
+
PY
|
|
107
|
+
)" || _parsed=""
|
|
108
|
+
|
|
109
|
+
TRANSCRIPT="$(printf '%s\n' "$_parsed" | sed -n '1p')"
|
|
110
|
+
CWD="$(printf '%s\n' "$_parsed" | sed -n '2p')"
|
|
111
|
+
[ -n "$CWD" ] || CWD="${CLAUDE_PROJECT_DIR:-$PWD}"
|
|
112
|
+
|
|
113
|
+
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/build-loop"
|
|
114
|
+
|
|
115
|
+
# No transcript in the payload: resolve the host's own session from CWD and
|
|
116
|
+
# normalize it to the Claude shape every sweep below parses. One call does both
|
|
117
|
+
# -- handing back a raw Codex path would move the no-op one step downstream.
|
|
118
|
+
# Claude always supplies transcript_path, so this is for hosts that do not.
|
|
119
|
+
if [ -z "$TRANSCRIPT" ]; then
|
|
120
|
+
_adapter="${PLUGIN_ROOT}/scripts/transcript_adapter.py"
|
|
121
|
+
if [ -f "$_adapter" ]; then
|
|
122
|
+
TRANSCRIPT="$("$_py" "$_adapter" --find-codex-session "$CWD" \
|
|
123
|
+
--cache-dir "$STATE_DIR/transcript-cache" 2>/dev/null)" || TRANSCRIPT=""
|
|
124
|
+
fi
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Every sweep needs a transcript; check once rather than in each arm.
|
|
128
|
+
[ -n "$TRANSCRIPT" ] || _noop
|
|
129
|
+
|
|
130
|
+
_run_one() {
|
|
131
|
+
case "$1" in
|
|
132
|
+
decisions)
|
|
133
|
+
nohup "$_py" "${PLUGIN_ROOT}/scripts/scan_transcript_for_decisions.py" \
|
|
134
|
+
--workdir "$CWD" \
|
|
135
|
+
--transcript "$TRANSCRIPT" \
|
|
136
|
+
--log-file "${STATE_DIR}/scan.log" \
|
|
137
|
+
</dev/null >/dev/null 2>&1 &
|
|
138
|
+
;;
|
|
139
|
+
corrections)
|
|
140
|
+
nohup env PYTHONPATH="${PLUGIN_ROOT}/scripts" "$_py" -m scan_corrections \
|
|
141
|
+
--workdir "$CWD" \
|
|
142
|
+
--transcript "$TRANSCRIPT" \
|
|
143
|
+
--source stop-hook \
|
|
144
|
+
</dev/null >/dev/null 2>&1 &
|
|
145
|
+
;;
|
|
146
|
+
findings)
|
|
147
|
+
nohup env PYTHONPATH="${PLUGIN_ROOT}/scripts" "$_py" -m scan_findings \
|
|
148
|
+
--workdir "$CWD" \
|
|
149
|
+
--transcript "$TRANSCRIPT" \
|
|
150
|
+
--log-file "${STATE_DIR}/findings-scan.log" \
|
|
151
|
+
</dev/null >/dev/null 2>&1 &
|
|
152
|
+
;;
|
|
153
|
+
cost-ledger)
|
|
154
|
+
# cost_ledger_hook.py parses the Stop payload itself (it needs
|
|
155
|
+
# session_id + cwd + transcript_path), so hand it the RAW payload on
|
|
156
|
+
# stdin rather than argv. printf writes and exits; the sweep stays
|
|
157
|
+
# detached.
|
|
158
|
+
printf '%s' "$PAYLOAD" \
|
|
159
|
+
| nohup "$_py" "${PLUGIN_ROOT}/scripts/cost_ledger_hook.py" \
|
|
160
|
+
>/dev/null 2>&1 &
|
|
161
|
+
;;
|
|
162
|
+
esac
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if [ "$SWEEP" = "all" ]; then
|
|
166
|
+
for one in decisions corrections findings cost-ledger; do
|
|
167
|
+
_run_one "$one"
|
|
168
|
+
done
|
|
169
|
+
else
|
|
170
|
+
_run_one "$SWEEP"
|
|
171
|
+
fi
|
|
172
|
+
|
|
173
|
+
_noop
|
package/hooks/test_closeout.sh
CHANGED
|
@@ -32,7 +32,9 @@ make_project() {
|
|
|
32
32
|
"current_session_id": "sess-itest",
|
|
33
33
|
"started_by_session_id": "sess-itest",
|
|
34
34
|
"last_heartbeat_at": "2999-01-01T00:00:00Z",
|
|
35
|
-
"run_label": "itest#001"
|
|
35
|
+
"run_label": "itest#001",
|
|
36
|
+
"run_worktree_branch": "bl/run-itest-001",
|
|
37
|
+
"run_worktree_path": ".build-loop/worktrees/run-itest-001"
|
|
36
38
|
},
|
|
37
39
|
"runs": []
|
|
38
40
|
}
|
|
@@ -41,6 +43,7 @@ JSON
|
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
runs_count() { python3 -c "import json,sys;print(len(json.load(open(sys.argv[1])).get('runs',[])))" "$1/.build-loop/state.json"; }
|
|
46
|
+
branch_ledger_ok() { python3 -c 'import json,sys;s=json.load(open(sys.argv[1]));r=s["runs"][0];x=r["createdRefs"][0];raise SystemExit(0 if s["execution"]=={} and x["branch"]=="bl/run-itest-001" and x["status"]=="open" and r["branch_closeout"]["status"]=="pending_external_merge" and "owner_release" not in r["branch_closeout"] else 1)' "$1/.build-loop/state.json"; }
|
|
44
47
|
|
|
45
48
|
# --- 1. present + matching session → records + surfaces WARN + exit 0 -------
|
|
46
49
|
P="$(make_project)"
|
|
@@ -51,7 +54,16 @@ if [ "$RC" -eq 0 ] && [ "$(runs_count "$P")" = "1" ] && printf '%s' "$OUT" | gre
|
|
|
51
54
|
else
|
|
52
55
|
bad "present+stakes (rc=$RC runs=$(runs_count "$P") out=$OUT)"
|
|
53
56
|
fi
|
|
54
|
-
[ -f "$P/.build-loop/closeout-pending/bl-itest-001.md" ]
|
|
57
|
+
if [ -f "$P/.build-loop/closeout-pending/bl-itest-001.md" ]; then
|
|
58
|
+
ok "closeout-pending marker written"
|
|
59
|
+
else
|
|
60
|
+
bad "marker not written"
|
|
61
|
+
fi
|
|
62
|
+
if branch_ledger_ok "$P"; then
|
|
63
|
+
ok "Stop archived identity after persisting open branch ownership"
|
|
64
|
+
else
|
|
65
|
+
bad "branch ownership missing or over-authorized"
|
|
66
|
+
fi
|
|
55
67
|
|
|
56
68
|
# --- 1b. second Stop in the same run → no-op (no double-record, no advisory) -
|
|
57
69
|
OUT2="$(printf '{"session_id":"sess-itest"}' | CLAUDE_PROJECT_DIR="$P" CLAUDE_PLUGIN_ROOT="$REPO" bash "$HOOK" stop)"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tyroneross/build-loop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.43.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://npm.pkg.github.com",
|
|
6
6
|
"access": "public"
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
"main": "dist/src/index.js",
|
|
10
10
|
"types": "dist/src/index.d.ts",
|
|
11
11
|
"bin": {
|
|
12
|
-
"build-loop-install": "bin/build-loop-install.js"
|
|
12
|
+
"build-loop-install": "bin/build-loop-install.js",
|
|
13
|
+
"build-loop-debugger": "bin/build-loop-debugger.js",
|
|
14
|
+
"build-loop-load-probe": "bin/build-loop-load-probe.js"
|
|
13
15
|
},
|
|
14
16
|
"exports": {
|
|
15
17
|
".": {
|
|
@@ -22,7 +24,6 @@
|
|
|
22
24
|
"dist",
|
|
23
25
|
"bin",
|
|
24
26
|
"codex-skills",
|
|
25
|
-
"plugin-artifacts/codex",
|
|
26
27
|
"assets",
|
|
27
28
|
"commands",
|
|
28
29
|
"skills",
|
|
@@ -30,9 +31,9 @@
|
|
|
30
31
|
"scripts/_db_url.py",
|
|
31
32
|
"scripts/blm.py",
|
|
32
33
|
"scripts/blm_api.py",
|
|
33
|
-
"scripts/build_codex_plugin_artifact.py",
|
|
34
34
|
"scripts/check_cache_sync.py",
|
|
35
35
|
"scripts/embed_backend.py",
|
|
36
|
+
"scripts/groundwork_exchange.py",
|
|
36
37
|
"scripts/install_memory.py",
|
|
37
38
|
"scripts/lessons_index",
|
|
38
39
|
"scripts/memory_context",
|
|
@@ -63,7 +64,8 @@
|
|
|
63
64
|
"build": "tsc",
|
|
64
65
|
"watch": "tsc --watch",
|
|
65
66
|
"prepublishOnly": "npm run build",
|
|
66
|
-
"test": "python3 -m unittest scripts/test_commit_state_check.py scripts/test_bridge_preflight.py scripts/test_mcp_registration.py scripts/test_build_loop_install_cli.py && bash scripts/hooks/test_hooks.sh",
|
|
67
|
+
"test": "python3 -m unittest scripts/test_commit_state_check.py scripts/test_bridge_preflight.py scripts/test_mcp_registration.py scripts/test_build_loop_install_cli.py scripts/test_native_debugger.py scripts/test_reference_pointer_lint.py scripts/test_groundwork_exchange.py scripts/test_groundwork_exchange_distribution.py scripts/test_load_probe.py scripts/hooks/test_unbounded_load_gate.py && bash scripts/hooks/test_hooks.sh",
|
|
68
|
+
"test:groundwork-exchange": "python3 -m unittest scripts/test_groundwork_exchange.py scripts/test_groundwork_exchange_distribution.py",
|
|
67
69
|
"benchmark": "node benchmark-scoring.js",
|
|
68
70
|
"clean": "rm -rf dist",
|
|
69
71
|
"plugin:prune-cache": "python3 scripts/prune_plugin_cache.py --source .",
|
|
@@ -71,8 +73,7 @@
|
|
|
71
73
|
"plugin:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host claude && npm run codex:sync-cache",
|
|
72
74
|
"plugin:sync-cache:hooks": "python3 scripts/sync_plugin_cache.py --source . --host all --install-git-hooks",
|
|
73
75
|
"codex:prune-cache": "python3 scripts/prune_codex_plugin_cache.py --source .",
|
|
74
|
-
"codex:
|
|
75
|
-
"codex:sync-cache": "npm run codex:build-artifact && python3 scripts/sync_plugin_cache.py --source plugin-artifacts/codex --host codex",
|
|
76
|
+
"codex:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host codex",
|
|
76
77
|
"codex:prune-cache:apply": "python3 scripts/prune_codex_plugin_cache.py --source . --apply",
|
|
77
78
|
"claude:prune-cache": "python3 scripts/prune_plugin_cache.py --source . --host claude",
|
|
78
79
|
"claude:sync-cache": "python3 scripts/sync_plugin_cache.py --source . --host claude",
|
package/scripts/README.md
CHANGED
|
@@ -101,7 +101,7 @@ hygiene check as `scripts/` scales.
|
|
|
101
101
|
| `plan_verify.py` | Deterministic plan grep-rules verifier |
|
|
102
102
|
| `version_advisor.py` | Suggest semver bumps based on `release-pending.md` |
|
|
103
103
|
| `ux_triage.py` | Sub-step D Gates 7/8 UX triage and UI coverage-gap queueing |
|
|
104
|
-
| `ibr_quickpass.py` | Legacy
|
|
104
|
+
| `ibr_quickpass.py` | Legacy helper for headless IBR suite runs; current UI verification policy lives in `references/ibr-ui-verification-policy.md` |
|
|
105
105
|
| `optimize_loop.py`, `optimize_doe.py`, `metric_runner.py` | Optimization runner + DOE |
|
|
106
106
|
| `systemic_rca_eval.py` | Experimental scorer for system-level RCA report shape: plain-language lead, failure-map depth, system-control terminal cause, evidence, tradeoffs/impact, and prevention control |
|
|
107
107
|
| `systemic_rca_doe.py` | Experimental packet builder and results scorer for the systemic RCA DOE matrix |
|
package/scripts/_paths.py
CHANGED
|
@@ -36,6 +36,7 @@ inspection. They never mkdir or touch files; callers handle creation.
|
|
|
36
36
|
"""
|
|
37
37
|
from __future__ import annotations
|
|
38
38
|
|
|
39
|
+
import json
|
|
39
40
|
import os
|
|
40
41
|
import re
|
|
41
42
|
import subprocess
|
|
@@ -396,6 +397,53 @@ def _canonical_repo_root(cwd_path: Path) -> Path | None:
|
|
|
396
397
|
return None
|
|
397
398
|
|
|
398
399
|
|
|
400
|
+
MEMORY_SLUG_PIN_KEY = "memoryProjectSlug"
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def _read_pinned_slug(repo_root: Path) -> str | None:
|
|
404
|
+
"""Read the durable memory-project-slug PIN from a repo's config.
|
|
405
|
+
|
|
406
|
+
Field: ``<repo_root>/.build-loop/config.json`` -> top-level
|
|
407
|
+
``"memoryProjectSlug"`` (camelCase, matching the existing ``selfReview``
|
|
408
|
+
/ ``deploymentPolicy`` top-level keys in that file).
|
|
409
|
+
|
|
410
|
+
This is the anchor that survives a ``basename(repo_root)`` rename: the
|
|
411
|
+
2026-07-09 control-plane RCA (P0-4) found renaming
|
|
412
|
+
``RossLabs-AI-Assistant`` silently orphaned 7 lessons under the old
|
|
413
|
+
``ai-assistant`` slug, because the slug was derived purely from the
|
|
414
|
+
directory name with no durable pin. When this field is set, callers use
|
|
415
|
+
it verbatim instead of deriving a slug from ``repo_root.name``.
|
|
416
|
+
|
|
417
|
+
Returns ``None`` (never raises) when: the config file is absent,
|
|
418
|
+
unreadable, not valid JSON, not a JSON object, the field is missing or
|
|
419
|
+
not a non-empty string, or the value fails ``_safe_project_tag``
|
|
420
|
+
validation — every one of those falls through to the existing
|
|
421
|
+
dirname-derivation path, so a malformed pin degrades gracefully instead
|
|
422
|
+
of breaking resolution.
|
|
423
|
+
"""
|
|
424
|
+
config_path = repo_root / ".build-loop" / "config.json"
|
|
425
|
+
if not config_path.is_file():
|
|
426
|
+
return None
|
|
427
|
+
try:
|
|
428
|
+
raw = config_path.read_text(encoding="utf-8")
|
|
429
|
+
data = json.loads(raw)
|
|
430
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError):
|
|
431
|
+
return None
|
|
432
|
+
if not isinstance(data, dict):
|
|
433
|
+
return None
|
|
434
|
+
pinned = data.get(MEMORY_SLUG_PIN_KEY)
|
|
435
|
+
if not isinstance(pinned, str):
|
|
436
|
+
return None
|
|
437
|
+
pinned = pinned.strip()
|
|
438
|
+
if not pinned:
|
|
439
|
+
return None
|
|
440
|
+
try:
|
|
441
|
+
_safe_project_tag(pinned)
|
|
442
|
+
except ValueError:
|
|
443
|
+
return None
|
|
444
|
+
return pinned
|
|
445
|
+
|
|
446
|
+
|
|
399
447
|
def derive_slug_from_cwd(cwd: Path | str | None = None) -> str:
|
|
400
448
|
"""Derive the project slug from a working directory.
|
|
401
449
|
|
|
@@ -406,6 +454,12 @@ def derive_slug_from_cwd(cwd: Path | str | None = None) -> str:
|
|
|
406
454
|
``~/.claude/plugins/build-loop`` resolves to ``~/dev/git-folder/build-loop``.
|
|
407
455
|
2. Walk up looking for a ``.git`` entry (file OR dir — worktrees use
|
|
408
456
|
a file). The deepest enclosing ``.git`` defines the repo root.
|
|
457
|
+
2.5. **Slug PIN check** (durable-slug-pin, added post P0-4 RCA):
|
|
458
|
+
if the canonical repo root (or, when that lookup fails, the
|
|
459
|
+
worktree-local repo root) has a valid ``memoryProjectSlug`` pin in
|
|
460
|
+
``.build-loop/config.json`` (see ``_read_pinned_slug``), return it
|
|
461
|
+
verbatim and skip steps 3-4 entirely. A rename of the repo
|
|
462
|
+
directory no longer changes the slug once pinned.
|
|
409
463
|
3. Slug base = ``basename(repo_root)`` lowercased; non-safe chars
|
|
410
464
|
collapsed to ``-``; runs of ``-`` collapsed; leading/trailing
|
|
411
465
|
``-`` stripped; capped at 64 chars.
|
|
@@ -460,6 +514,17 @@ def derive_slug_from_cwd(cwd: Path | str | None = None) -> str:
|
|
|
460
514
|
if canonical is not None:
|
|
461
515
|
base_root = canonical
|
|
462
516
|
|
|
517
|
+
# Step 2.5 — durable slug PIN. Check the canonical root first (the
|
|
518
|
+
# preferred place to set the pin — shared by every worktree), then fall
|
|
519
|
+
# back to the worktree-local root. A hit here bypasses dirname
|
|
520
|
+
# derivation entirely, so a `basename(repo_root)` rename cannot change
|
|
521
|
+
# the resolved slug once pinned.
|
|
522
|
+
pinned = _read_pinned_slug(base_root)
|
|
523
|
+
if pinned is None and base_root != repo_root:
|
|
524
|
+
pinned = _read_pinned_slug(repo_root)
|
|
525
|
+
if pinned is not None:
|
|
526
|
+
return pinned
|
|
527
|
+
|
|
463
528
|
base = base_root.name.lower()
|
|
464
529
|
base = re.sub(r"[^a-z0-9._-]", "-", base)
|
|
465
530
|
base = re.sub(r"-{2,}", "-", base).strip("-")
|