@tyroneross/build-loop 0.30.3 → 0.35.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 +4 -4
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/AGENTS.md +11 -2
- package/README.md +8 -7
- package/agents/advisor.md +111 -0
- package/agents/alignment-checker.md +11 -0
- package/agents/assessment-orchestrator.md +1 -1
- package/agents/build-orchestrator.md +28 -33
- package/agents/fact-checker.md +1 -1
- package/agents/fix-critique.md +1 -1
- package/agents/independent-auditor.md +1 -1
- package/agents/overfitting-reviewer.md +1 -1
- package/agents/plan-critic.md +8 -6
- package/agents/promotion-reviewer.md +1 -1
- package/agents/retrospective-synthesizer.md +20 -3
- package/agents/scope-auditor.md +1 -1
- package/agents/security-reviewer.md +1 -1
- package/agents/self-improvement-architect.md +1 -1
- package/commands/{handoff.md → compose-handoff.md} +4 -4
- package/commands/{optimize.md → optimize-run.md} +1 -1
- package/commands/{agent-rally-point.md → rally-point.md} +3 -3
- package/commands/{research.md → research-run.md} +1 -1
- package/commands/setup-memory.md +32 -0
- package/commands/{plan-verify.md → verify-plan.md} +1 -1
- package/docs/agent-surface-policy.md +38 -20
- package/docs/memory-setup.md +19 -14
- package/hooks/_resolve_python.sh +28 -0
- package/hooks/closeout.sh +58 -0
- package/hooks/git/pre-push +69 -6
- package/hooks/hooks.json +34 -13
- package/hooks/post-push-closeout.sh +73 -0
- package/hooks/session-start-closeout.sh +69 -0
- package/hooks/session-start-memory.sh +27 -0
- package/hooks/session-start-plugin-heal.sh +33 -0
- package/hooks/test_closeout.sh +124 -0
- package/package.json +7 -4
- package/plugin-artifacts/codex/.codex-plugin/plugin.json +41 -0
- package/plugin-artifacts/codex/AGENTS.md +507 -0
- package/plugin-artifacts/codex/BUILD-ARTIFACT.md +5 -0
- package/plugin-artifacts/codex/LICENSE +202 -0
- package/plugin-artifacts/codex/README.md +404 -0
- package/plugin-artifacts/codex/docs/agent-surface-policy.md +63 -0
- package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +62 -0
- package/plugin-artifacts/codex/references/agent-role-taxonomy.md +135 -0
- package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +161 -0
- package/plugin-artifacts/codex/references/autonomy-config.md +231 -0
- package/plugin-artifacts/codex/references/capability-routing.md +182 -0
- package/plugin-artifacts/codex/references/codex-subagents.md +106 -0
- package/plugin-artifacts/codex/references/coordination-file-template.md +181 -0
- package/plugin-artifacts/codex/references/coordination-rules.md +283 -0
- package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +112 -0
- package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +102 -0
- package/plugin-artifacts/codex/references/implementer-envelope-schema.md +302 -0
- package/plugin-artifacts/codex/references/intent-capability-pack.md +257 -0
- package/plugin-artifacts/codex/references/intent-exploration-prompts.md +96 -0
- package/plugin-artifacts/codex/references/leadership.md +72 -0
- package/plugin-artifacts/codex/references/memory-systems.md +238 -0
- package/plugin-artifacts/codex/references/memory.md +299 -0
- package/plugin-artifacts/codex/references/model-tier-mapping.md +257 -0
- package/plugin-artifacts/codex/references/modular-systems-pack.md +96 -0
- package/plugin-artifacts/codex/references/phase-1-assess.md +231 -0
- package/plugin-artifacts/codex/references/phase-2-plan.md +78 -0
- package/plugin-artifacts/codex/references/phase-3-execute.md +49 -0
- package/plugin-artifacts/codex/references/phase-4-review.md +322 -0
- package/plugin-artifacts/codex/references/phase-5-iterate.md +71 -0
- package/plugin-artifacts/codex/references/phase-6-learn.md +56 -0
- package/plugin-artifacts/codex/references/recent-design-structures.md +274 -0
- package/plugin-artifacts/codex/references/research-trigger-policy.md +140 -0
- package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +42 -0
- package/plugin-artifacts/codex/references/self-review.md +234 -0
- package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +90 -0
- package/plugin-artifacts/codex/references/task-capture-policy.md +68 -0
- package/plugin-artifacts/codex/references/ui-io-contract.md +116 -0
- package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +65 -0
- package/plugin-artifacts/codex/skills/build-loop/SKILL.md +372 -0
- package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +82 -0
- package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +65 -0
- package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +549 -0
- package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +42 -0
- package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +267 -0
- package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
- package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +439 -0
- package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
- package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +182 -0
- package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +106 -0
- package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +161 -0
- package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +177 -0
- package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +72 -0
- package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +257 -0
- package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +96 -0
- package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +72 -0
- package/plugin-artifacts/codex/skills/build-loop/references/memory.md +299 -0
- package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +96 -0
- package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +129 -0
- package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +98 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +231 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +78 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +49 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +322 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +71 -0
- package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +56 -0
- package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +274 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
- package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
- package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +77 -0
- package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +234 -0
- package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +116 -0
- package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
- package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +35 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +100 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
- package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +40 -0
- package/scripts/_paths.py +59 -13
- package/scripts/build_codex_plugin_artifact.py +314 -0
- package/scripts/check_cache_sync.py +1 -1
- package/scripts/install_memory.py +11 -3
- package/scripts/prune_plugin_cache.py +225 -11
- package/scripts/sync_navgator_lessons.py +25 -0
- package/scripts/sync_plugin_cache.py +66 -36
- package/skills/agent-rally-point/SKILL.md +1 -1
- package/skills/agent-rally-watcher/SKILL.md +1 -1
- package/skills/build-loop/SKILL.md +11 -155
- package/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
- package/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
- package/skills/build-loop/references/capability-routing.md +4 -3
- package/skills/build-loop/references/codex-subagents.md +8 -0
- package/skills/build-loop/references/coordination.md +1 -1
- package/skills/build-loop/references/intent-capability-pack.md +88 -1
- package/skills/build-loop/references/memory.md +17 -2
- package/skills/build-loop/references/phase-1-assess.md +13 -0
- package/skills/build-loop/references/phase-2-plan.md +2 -1
- package/skills/build-loop/references/phase-3-execute.md +4 -2
- package/skills/build-loop/references/phase-4-review.md +12 -0
- package/skills/build-loop/references/phase-6-learn.md +1 -1
- package/skills/build-loop/references/self-review.md +4 -2
- package/skills/build-loop/templates/codex-worker-prompt.md +45 -34
- package/skills/handoff/SKILL.md +3 -3
- package/skills/loop-builder/SKILL.md +98 -0
- package/skills/loop-builder/presets/active-project-evidence.yaml +97 -0
- package/skills/loop-builder/presets/generic-artifact-loop.yaml +95 -0
- package/skills/loop-builder/presets/presentation-audit.yaml +96 -0
- package/skills/loop-builder/presets/research-synthesis.yaml +96 -0
- package/skills/loop-builder/presets/source-ingestion-raw-data-audit.yaml +96 -0
- package/skills/loop-builder/references/spec-format.md +80 -0
- package/skills/loop-builder/scripts/loop_builder.py +346 -0
- package/skills/model-tiering/SKILL.md +65 -40
- package/skills/optimize/SKILL.md +2 -2
- package/skills/plan-verify/SKILL.md +1 -1
- package/skills/plugin-builder/references/distribution.md +8 -0
- package/skills/research/SKILL.md +33 -6
- package/skills/runtime-parity-verification/SKILL.md +51 -0
- package/skills/spec-writing/SKILL.md +19 -0
- package/templates/memory/README.md +65 -0
- package/templates/memory/charter.md.template +46 -0
- package/templates/memory/manifest.json +24 -4
- package/codex-skills/debug-loop/SKILL.md +0 -18
- package/codex-skills/handoff/SKILL.md +0 -22
- package/codex-skills/knowledge/SKILL.md +0 -21
- package/codex-skills/optimize/SKILL.md +0 -18
- package/codex-skills/research/SKILL.md +0 -18
- /package/commands/{knowledge-review.md → review-knowledge.md} +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Phase 4: Review (full protocol)
|
|
4
|
+
|
|
5
|
+
> Loaded from `skills/build-loop/SKILL.md` summary. Contains the seven sub-steps A–G including Sub-step F Auto-Resolve with all 4 routing arms (auto/warn/confirm/block).
|
|
6
|
+
|
|
7
|
+
## Phase 4: Review — Critic, Validate, Fact-Check, Simplify, Auto-Resolve, Report
|
|
8
|
+
|
|
9
|
+
**Goal**: evaluate the built output against the rubric and decide pass / fail / iterate. Everything that used to live in phases 4.5, 4.7, 5, 7, 8, and 8.5 happens here as ordered sub-steps. One phase heading, seven sub-steps, single exit point.
|
|
10
|
+
|
|
11
|
+
Review runs every time we need an evaluation (initial post-Execute, and again after each Iterate pass). The report sub-step (G) writes final artifacts only on the LAST pass — intermediate Reviews skip it.
|
|
12
|
+
|
|
13
|
+
### Sub-step A: Critic (adversarial read-only)
|
|
14
|
+
|
|
15
|
+
Catch scope drift, patch-over-root-cause, missed edge cases, and rubric violations before spending tokens on full validation. Uses a separate read-only agent with no incentive to sandbag.
|
|
16
|
+
|
|
17
|
+
0. **Quality-gate trigger profile (QM v0.13.0, single source of truth — F4)**: run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/review_trigger.py --context .build-loop/state.json $(git diff --name-only origin/main..HEAD | sed 's/^/--changed-file /') --json`. The returned `{independent_review_required, cross_vendor_required, reasons}` is the **single source** for when adversarial/cross-vendor review fires — don't invent separate heuristics. Triggers cover `riskSurfaceChange`, architecture-boundary crossing, new dependency/runtime, auth/file/network/persistence/security/model-tool changes, and low-confidence critic output.
|
|
18
|
+
1. **Dispatch `independent-auditor`** at `scope: "build"` against the full build diff (`<pre_build_sha>..HEAD`). Consolidated 2026-05-23 — single source of truth replacing both retired `commit-auditor` (chunk + build scope) and earlier retired `sonnet-critic`. The auditor has tools=[Read, Grep, Glob, Bash] (Bash for `git diff`), no Edit/Write. For Phase 3 step 7 (per-chunk advisory), dispatch the same `independent-auditor` with `diff_sha_range: <chunk_parent_sha>..<chunk_sha>` and `reason: "chunk-advisory"`. **Cross-vendor (QM v0.13.0)**: when the profile sets `cross_vendor_required` and a peer host is reachable (rally channel / `codex exec`), fan out a second-vendor reviewer in parallel and reconcile by severity+evidence; if no peer host can execute, record `cross_vendor: untested` — never claim it ran (per host-agent-is-the-LLM, this is the host's peer, not a vendored API call).
|
|
19
|
+
|
|
20
|
+
**Auditor dispatch ladder & parent-dispatch contract (GAP-1 — the LLM auditor is never silently skipped).** Dispatching `independent-auditor` via `Agent(subagent_type=...)` requires the Agent tool. A *nested* orchestrator — one dispatched as a subagent (`Agent(subagent_type="build-loop:build-orchestrator")`, Mode B) or running per-commit mode — does **not** have the Agent tool, because the harness blocks sub-subagents. The historical failure (2026-06-06 IBR retro, 4+ runs): the nested orchestrator silently substituted inline self-reasoning and reported it as "independent-auditor ran inline", rubber-stamping a HIGH cookie-leak + 2 MEDIUM findings a real dispatch later caught. To make that impossible, walk this ladder and record `auditor_status` honestly:
|
|
21
|
+
|
|
22
|
+
1. **Agent tool present** (top-level / Mode A) → dispatch `independent-auditor` at build scope as above → `auditor_status: ran:dispatched-agent`.
|
|
23
|
+
2. **No Agent tool, peer host reachable** → run the auditor as a **peer process** over the same channel the cross-vendor reviewer uses (rally channel handoff / `codex exec <prompt>` — reachable because the orchestrator retains Bash even when nested). Reconcile the peer's JSON envelope into `.build-loop/judge-decisions.json` with `judge_id: "independent-auditor"` (a real, cross-host verdict that satisfies the `write_run_entry --scope build` gate honestly) → `auditor_status: ran:peer-host(<host>)`. Prefer this over the not-run signal whenever a peer host can execute.
|
|
24
|
+
3. **Neither reachable** → `auditor_status: not-run:parent-must-dispatch` (or `cross-vendor-deferred` when a peer host exists but cannot execute this pass). Then, **all of**: (a) do NOT write any `judge_id` containing `independent-auditor` for inline self-reasoning — *inline self-audit is not the independent auditor*, and a mislabeled record would defeat the gate; (b) do NOT report a `scope=build` code-touching run as a review-complete `pass` — use `outcome: partial`; (c) surface `auditor_status: not-run:parent-must-dispatch` in the orchestrator's return envelope.
|
|
25
|
+
|
|
26
|
+
**Parent-dispatch contract.** A run or commit whose envelope carries `auditor_status: not-run:parent-must-dispatch` (or `cross-vendor-deferred`) is **NOT review-complete**. The dispatching parent — the top-level session that *does* have the Agent tool (the `/build-loop:run` skill body, or the human-driving session) — MUST, on receiving such an envelope: (1) dispatch `Agent(subagent_type="build-loop:independent-auditor")` on the run's diff range (`<pre_build_sha>..HEAD`); (2) append its verdict to `.build-loop/judge-decisions.json`; (3) re-run `write_run_entry --scope build` so the review-completeness gate passes, and only then finalize Report. The existing gate (`scripts/write_run_entry`, `review_completeness_error` → exit 3 on a `pass` + `scope=build` + files-touched run lacking a real auditor verdict) is the structural backstop: it cannot be satisfied by an honest nested orchestrator, which is what forces the parent to finish the audit instead of shipping un-audited code.
|
|
27
|
+
2. **Input**: the rubric from `.build-loop/goal.md` + the implementer's diff (`git diff HEAD~1` or the changed-file set).
|
|
28
|
+
3. **Output**: JSON envelope with `verdict` ∈ {yay, nay, suggest_correction, look_again} + normalized `findings[]` (`severity: critical|high|medium|low`). See `agents/independent-auditor.md` for the full schema.
|
|
29
|
+
4. **Routing** (QM v0.13.0 normalized severities; legacy `major→high`, `minor→medium`, `info→low`):
|
|
30
|
+
- `verdict: yay` → proceed to sub-step B (Validate)
|
|
31
|
+
- `verdict: nay` (paired with a `critical`/`high` finding) → route back to **Execute** for fixes (strong-checkpoint; no iteration counter burn yet on critic-only failures). If the diff reveals the *plan* is wrong, re-plan instead — orchestrator's call.
|
|
32
|
+
- `verdict: suggest_correction` with `auto_fixable: true` AND `severity in {medium, low}` → Auto-Resolve queue (Sub-step F)
|
|
33
|
+
- `verdict: look_again` → operator gathers the named `missing_artifacts` and re-runs the auditor
|
|
34
|
+
- `severity: medium|low` findings → record in `.build-loop/issues/` and proceed; `critical|high` never proceed silently (they block the final pass — see Sub-step G no-critical/high exit gate)
|
|
35
|
+
5. **Escalation**: if the same chunk fails critic twice, escalate the implementer to Opus per `model-tiering` skill §Escalation Triggers.
|
|
36
|
+
6. **Skip** on re-reviews after Iterate (critic already saw the diff at first pass) unless Iterate touched different files. Skip entirely for trivial chunks (single-file typo, config value).
|
|
37
|
+
7. **Push-hold marker (set on blocking verdict, clear on resolution)** — close the "autonomous push of un-reviewed work" defect at the git layer, not the app layer. When the auditor returns `verdict: nay` OR `verdict: suggest_correction` OR `verdict: look_again` AND those findings are NOT yet resolved, immediately set the push-hold marker so a parallel autonomous push (self-review `apply_push`, `codex-autonomy-poller`, any path that doesn't consult `deployment_policy.py`) gets blocked by `hooks/git/pre-push`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/push_hold.py --set \
|
|
41
|
+
--source review-a \
|
|
42
|
+
--reason "<verdict> from independent-auditor (run <run_id>)" \
|
|
43
|
+
--auditor-verdict "<verdict>" \
|
|
44
|
+
--finding-ids "<comma-separated finding ids>" \
|
|
45
|
+
--run-id "<run_id>" --json
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The marker is auto-detected as a hold by the pre-push hook even when the orchestrator crashes mid-run — that's the whole reason it lives at the git layer. On re-audit pass (verdict `yay`, OR every prior `critical`/`high` finding now has `resolved: true` in `state.json.runs[-1].judge_decisions[]`), CLEAR the marker:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python3 ${CLAUDE_PLUGIN_ROOT}/scripts/push_hold.py --release \
|
|
52
|
+
--reason "auditor findings resolved (run <run_id>)" --json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The state.json signal is a backstop: if the marker was somehow lost, `push_hold.evaluate_push` will still detect an unresolved blocking verdict in `runs[-1].judge_decisions[]` and block. The explicit marker takes precedence; both are honored. Bypass exists at `BUILDLOOP_PUSH_HOLD_BYPASS=1` (logged to `.build-loop/audit-log.md`) for genuine emergencies — never in autonomous mode without an explicit operator decision. The pre-push hook is installed via `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/install_git_hooks.py --install` (idempotent; mirror of the existing `audit_before_commit.py` install pattern).
|
|
56
|
+
|
|
57
|
+
### Sub-step B: Validate (graders + memory-first gate)
|
|
58
|
+
|
|
59
|
+
Test every criterion from Assess with evidence.
|
|
60
|
+
|
|
61
|
+
**UI validation — build-loop-owned route** (`uiTarget != null`): dispatch `ui-validator` first, then run the static design-rule scanner and UI input/output contract check. Build-loop does not auto-route to IBR for validation. If the user explicitly requested IBR, treat that as a manual auxiliary validator and keep its findings out of the default gate order.
|
|
62
|
+
|
|
63
|
+
**UI validation fallback**: paste `fallbacks.md#web-ui` into the validation subagent prompt when `ui-validator` cannot render the route. The fallback contains 10 specific grep checks (Gestalt violations, touch targets, missing handlers, missing aria-labels, status-pill anti-patterns, off-token colors, non-8pt spacing, console leftovers, mock data) plus a file-check matrix for landmarks, focus styles, and viewport tags. Findings get `⚠️ static-analysis only — browser/simulator evidence unavailable` in the Review-G report. This is the standalone UI validation path — degraded vs rendered validation, but not silent.
|
|
64
|
+
|
|
65
|
+
**UI input/output contract validation** (`uiTarget != null`): read the plan's `## UI Input/Output Contract` section and compare it to changed UI files before visual validation. Confirm every user input and system output in the changed surface has a data taxonomy, operation/domain verb, component mapping, state coverage, modality fallback when relevant, validation/security layer, and schema/API/design-system trace. Missing coverage is a Validate failure unless the change is copy-only and the contract explicitly says no data surface changed.
|
|
66
|
+
|
|
67
|
+
**Calm Precision core-consideration validation** (`uiTarget != null`): check `.build-loop/app-contract/ui.md` or the implementer return envelope for the relevant Calm Precision principles, foundations, and implementation effects. Missing consideration is a Validate failure for non-trivial UI work, because Calm Precision is a design gate, not a passive reference.
|
|
68
|
+
|
|
69
|
+
**Code-based graders first** (fast, deterministic):
|
|
70
|
+
```
|
|
71
|
+
test suite → pass/fail
|
|
72
|
+
lint / type check → pass/fail
|
|
73
|
+
build → pass/fail
|
|
74
|
+
accessibility → threshold pass/fail (if web)
|
|
75
|
+
schema validation → pass/fail
|
|
76
|
+
custom assertions → pass/fail
|
|
77
|
+
design-rule scan → must-fix=0 pass/fail (uiTarget != null only)
|
|
78
|
+
ui io contract → pass/fail (uiTarget != null only)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Design-rule scan** (when `uiTarget != null`):
|
|
82
|
+
```
|
|
83
|
+
node "${CLAUDE_PLUGIN_ROOT}/skills/build-loop/scanners/audit-design-rules.mjs" --root=<project> --platform=<swiftui|react|web> --json
|
|
84
|
+
```
|
|
85
|
+
Exit 0 = clean. Exit 1 = warnings only (continue, log). Exit 2 = must-fix found (fail; route to Iterate).
|
|
86
|
+
|
|
87
|
+
This is the static-analysis gate that catches what mockup-parity misses — colored status pills, ungated `.repeatForever`, raw `UIColor` outside Theme, literal `cornerRadius`, body-copy `.font(.system(size:))`, icon-only `Image(systemName:)` without accessibility labels. Maintained in `scanners/audit-design-rules.mjs`, dependency-free Node 18+, per-platform packs.
|
|
88
|
+
|
|
89
|
+
**Visual validation** (REQUIRED when `uiTarget != null`): the static scanner cannot catch rendering bugs — an upside-down arc, an invisible track stroke, a row clipped behind a floating tab bar, a chip that wraps. After the scanner passes, render the actual screen via the platform's preferred tool:
|
|
90
|
+
- iOS / macOS / watchOS: `xcrun simctl io booted screenshot` after installing and launching the build, or the built-in native AX driver for macOS interaction checks
|
|
91
|
+
- Web: browser/screenshot tooling against the dev server URL
|
|
92
|
+
- Fallback: static scanner + explicit missing-visual-evidence note
|
|
93
|
+
|
|
94
|
+
**The audit is mandatory; the verdict is advisory.** The screenshot/browser artifact path MUST be written to `state.json.runs[].artifacts.uiAudit[]` and surfaced in the Phase 4 Report `## Notes from judges` section. **Findings are WARN-only — never block the build** (same posture as `synthesis-critic`). The user retains final visual judgment; build-loop's job is to guarantee the artifact lands in the operator's view before any TestFlight/preview/production push. Subjective UI judgments (intended chrome change vs scope creep, deliberate layout shift vs regression) cannot be mechanically distinguished from intended changes — a fail-closed audit would halt every legitimate UI change with false-positive layout-shift noise. Per [[pattern_buildloop_coordination_default]]. **Scope-creep signal:** if the diff vs prior baseline shows substantial pixel delta on routes the plan did NOT name as touched, surface in `## Notes from judges` as `scope_creep_signal` with the route list — advisory only; build does NOT pause and does NOT route to `## Held`.
|
|
95
|
+
|
|
96
|
+
For returning-user states (post-onboarding screens, dashboards with data), use the DebugSeeder pattern (see `templates/ui-subagent-prompt.md` §DebugSeeder) so visual states can be verified in seconds without manual data entry. Build 55 of a real shipped app passed scanner exit 0 but rendered an upside-down semicircle gauge with stray tick marks because no one rendered the actual screen — visual validation is non-negotiable for UI work.
|
|
97
|
+
|
|
98
|
+
**Live HTTP/SSE smoke** (REQUIRED when `triggers.runtimeServer == true` AND the diff touches `runtimeServerInfo.server_module` OR `runtimeServerInfo.embedded_ui_module`): pytest with mocked SDKs is necessary but not sufficient for projects that ship a live server — it does not iterate real DOM trees, does not open SSE connections, and does not render embedded HTML. Implements decision `_unscoped/0003`. The 5-step procedure:
|
|
99
|
+
|
|
100
|
+
1. Restart the server in background. Read `state.json.runtimeServerInfo.start_command` if present, else fall back to `uv run <package> --serve --port <default_port>` derived from `pyproject.toml`'s package name and `runtimeServerInfo.default_port`. Redirect stdout/stderr to `/tmp/buildloop-serve.log` for forensic surface in Review-F.
|
|
101
|
+
2. Wait up to 15s for `/api/status` (or `/`) to return HTTP 200 — poll once per second.
|
|
102
|
+
3. Run a 5-second curl POST against the SSE route:
|
|
103
|
+
```
|
|
104
|
+
curl -sN -X POST http://localhost:<port><sse_route> \
|
|
105
|
+
-H 'Content-Type: application/json' -d '<minimal-prompt>' --max-time 5 \
|
|
106
|
+
| grep -oE '"type":\s*"[^"]+"' | sort -u
|
|
107
|
+
```
|
|
108
|
+
4. Read the UI's event-handler switch at the locations from `runtimeServerInfo.event_handler_locations[]` and extract every handled event type (regex on `d\.type === '([^']+)'` and `d\.type == "([^"]+)"`). Skip this step when `embedded_ui_module: null` (API-only services have no embedded UI to compare).
|
|
109
|
+
5. **Fail the build** when an observed event type from step 3 has no matching handler arm from step 4 — this is the silent-server, ignored-client class of bug. Surface as a Validate failure → routes to Iterate.
|
|
110
|
+
|
|
111
|
+
If any infrastructure step fails (server won't start, curl errors, can't parse handler) → log evidence to `.build-loop/issues/live-smoke-<date>.md` and surface as `⚠️ untested live-flow` in Review-F. Do NOT fail the build on infrastructure issues — only on the specific server/client contract violation. Heavier integration tests (Playwright/Selenium) are still the right answer for full correctness; this gate is the cheapest check that catches what pytest-with-mocks cannot.
|
|
112
|
+
|
|
113
|
+
**LLM-as-judge graders second** (for nuanced criteria):
|
|
114
|
+
- Each criterion → its own focused judge prompt
|
|
115
|
+
- Binary pass/fail output only
|
|
116
|
+
- No multi-dimension scoring in a single prompt
|
|
117
|
+
|
|
118
|
+
**Evidence collection**:
|
|
119
|
+
- Every pass/fail must have evidence: command output, screenshot, or judge reasoning
|
|
120
|
+
- Use `verification-before-completion` for evidence-based claims
|
|
121
|
+
- No criterion marked "pass" without proof
|
|
122
|
+
|
|
123
|
+
**Runtime smoke gate (post-tests, pre-LLM-judges)**: after code-based graders pass, invoke `python3 scripts/runtime_smoke.py --changed-files <list> --workdir "$PWD" --json` whenever any changed file matches a runtime-smoke trigger. The script auto-detects a dev-server adapter from the project's manifest (Next.js today; FastAPI, Express, and SSE-consumer adapters are documented future slots). `pass` proceeds; `fail` routes to Iterate using the smoke envelope's `findings` as the rubric; `skipped` (no trigger matched or no adapter for this stack) records `runtime_smoke: skipped (<reason>)` in Review-F and proceeds — library-only repos never fail this gate. See `references/runtime-smoke-triggers.md` for the full trigger-pattern table and adapter roadmap, and `agents/build-orchestrator.md` §"Review-B: Runtime smoke gate" for the routing rules.
|
|
124
|
+
|
|
125
|
+
**Pytest-collection gate (full-suite-load check, every run)**: after code-based graders pass and before LLM judges, invoke `python3 scripts/pytest_collect_gate.py --workdir "$PWD" --json` on Python-bearing repos. The gate runs `pytest scripts/ tests/ --collect-only` with `PYTHONPATH` stripped (matching the spec's `env -u PYTHONPATH` discipline). Collection-only is the bar — it does NOT require the full suite to execute green (db/live tests legitimately skip via their markers); it only verifies that every test module *loads*. `pass` (exit 0, no findings) proceeds; `fail` (exit 1, one or more import/syntax errors) routes to Iterate using `findings[]` as the rubric — each finding carries `{file, line, error_class, message}` pointing at the broken module so the next iteration fixes the import rather than papering over the test; `exit 2` (runner error — pytest not found or a usage error with no parseable output) carries `status="fail"` with `error_class="RunnerError"` and `stderr_tail` — treat it exactly as `fail` and route to Iterate; `skipped` (no `pyproject.toml`/`pytest.ini`/`setup.cfg` and no test paths — library-only repo) records `pytest_collect: skipped (<reason>)` in Review-F and proceeds. **Non-standard layouts**: when `pyproject.toml` is present but the default `scripts/`/`tests/` paths are absent, the gate skips with a loud reason naming the gap — pass `--paths <dir> [...]` so a Python-bearing repo with tests elsewhere is not silently bypassed. **Why this gate exists** (every issue is a systems issue): build-loop's run gate historically scoped to changed-area tests, so a broken import that quietly removed an entire test module from coverage would not fail the build — exactly how 8750d2a's psycopg breakage and the EXECUTION_SCHEMA_VERSION miss hid for multiple runs. The collection gate closes that gap with one cheap check; the gate file is `scripts/pytest_collect_gate.py`, its regression tests are `scripts/test_pytest_collect_gate.py`.
|
|
126
|
+
|
|
127
|
+
**Memory-first gate (on any failing criterion)**: before routing failures to Iterate, the orchestrator runs the gate (read_logs → synthesize symptom → invoke `Skill("build-loop:debugging-memory")` → act on verdict). See `agents/build-orchestrator.md` §Phase 4 sub-step B for the orchestrator's exact when-to-fire and gate-recording policy. **Memory is a hypothesis, not a patch — every verdict routes to Iterate as an adapted plan by default**:
|
|
128
|
+
|
|
129
|
+
- `KNOWN_FIX` → adapt prior incident as the Iterate fix plan. Direct-apply only when all three gates hold: file match + version match + second validation signal (stack frame, error class, or log entry). Otherwise behave as LIKELY_MATCH.
|
|
130
|
+
- `LIKELY_MATCH` → adapt prior incident as the Iterate fix plan
|
|
131
|
+
- `WEAK_SIGNAL` → note reference in the Iterate plan, investigate normally
|
|
132
|
+
- `NO_MATCH` → standard Iterate fallthrough; store at sub-step G Report for future learning
|
|
133
|
+
|
|
134
|
+
The memory gate is always on. Build-loop bundles native debugging-memory skills and file-backed search/store, with standalone Coding Debugger available only as an optional cross-project memory plugin when explicitly installed. If structured memory is unavailable, the orchestrator falls through to the local-grep fallback. The strict direct-apply triple-gate spec lives in `skills/debugging-memory/SKILL.md` §"Direct-apply gate (strict)".
|
|
135
|
+
|
|
136
|
+
**Output**: per-criterion pass/fail with evidence. Any `fail` → Iterate. All `pass` → sub-step C.
|
|
137
|
+
|
|
138
|
+
### Sub-step C: Optimize (opt-in, only with a mechanical metric)
|
|
139
|
+
|
|
140
|
+
Metric-driven autonomous optimization using Karpathy's autoresearch pattern. Opt-in — runs only when a mechanical metric exists AND the user hasn't disabled it.
|
|
141
|
+
|
|
142
|
+
**Load the `build-loop:optimize` skill for the full protocol.**
|
|
143
|
+
|
|
144
|
+
1. **Discover targets**: Run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/optimize_loop.py --detect --workdir "$PWD"`.
|
|
145
|
+
2. **`simplify` is always available** when code changed: reduces line count in files changed by Execute. Metric = total lines, direction = lower, guard = build passes.
|
|
146
|
+
3. **Other targets** appear when the repo has the right tooling (build script → optimize-build, test runner → optimize-tests, bundler → optimize-bundle).
|
|
147
|
+
4. **Budget**: 3-5 iterations (polish, not deep optimization).
|
|
148
|
+
5. **Post-loop**: dispatch `overfitting-reviewer`. Archive to `.build-loop/optimize/experiments/`.
|
|
149
|
+
|
|
150
|
+
**Skip** when: no mechanical metric, build was trivial (<20 lines), or user opts out. Optimization results feed back into Validate as additional evidence.
|
|
151
|
+
|
|
152
|
+
### Sub-step D: Fact-Check & Mock/Privacy Scan
|
|
153
|
+
|
|
154
|
+
Nothing false, fabricated, or placeholder reaches the user. Three gates, run in parallel. Load `phases/fact-check.md` for detailed guidance.
|
|
155
|
+
|
|
156
|
+
- **Gate 1 — Fact Checker**: Trace every rendered %, $, score, count, or assessment to its data source. Flag "always", "never", "100%", "guaranteed" — replace with accurate language unless genuinely absolute. Every rendered metric needs a traceable path: source → transformation → display.
|
|
157
|
+
- **Gate 2 — Mock/Privacy Data Scanner**: Run via `mock-scanner`. Lightweight scan of production code paths and public release/package surfaces for residual mock/placeholder data and private data leaks — hardcoded fake data, placeholder text, faker/random in display paths, stubs replacing real implementations, live-looking API keys/secrets, absolute local paths, private vault/wiki/session paths, persona/profile exports, customer/user lists, resumes, calendars, private notes, transcripts, hostnames, Rally runtime logs, worktree bundles, and other personal or machine-specific data. Exclude test files, dev-only code, and clearly synthetic documentation examples.
|
|
158
|
+
- **Gate 3 — Architectural Violation Check**: invoke `Skill("build-loop:architecture-rules")` (no plugin gate — the native skill no-ops cleanly when `.navgator/architecture/index.json` is absent). Executes `navgator rules --json` and classifies blocking (`circular-dependency`, `layer-violation`, `database-isolation`, `frontend-direct-db` at error) vs warning (`hotspot`, `high-fan-out`, `orphan`). Flags recurrences against `.navgator/lessons/lessons.json`. For cross-layer changes, escalate to `Skill("build-loop:architecture-review")` for the full integrity review.
|
|
159
|
+
- **Gate 4 — Plugin Cache Sync Check** (only when `pluginWork: true`): run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/check_cache_sync.py --host claude --source <plugin-source-repo>` for Claude runtime surfaces. If the build changes Codex-visible surfaces (`.codex-plugin/`, `AGENTS.md`, `README.md`, `skills/`, or `commands/`), also run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/check_cache_sync.py --host codex --source <plugin-source-repo>`. `[DIVERGED]`, `[MISSING IN CACHE]`, or stale installed Codex versions are **blocking** when they affect the host being used — runtime invocations will hit stale or missing files. Fix with `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/sync_plugin_cache.py --source <plugin-source-repo> --host <claude|codex|all>`, which syncs committed `HEAD` by default; use `--dirty --file <path>` only for explicit temporary runtime testing. Defer version bumps until the feature batch is declared complete (see Gate 6). Missing cache with no installed version skips silently (user has not installed the plugin, nothing to break).
|
|
160
|
+
- **Gate 5 — Design-Rule Scanner** (only when `uiTarget != null`): run `audit-design-rules.mjs` across full project (broader than Sub-step B's changed-files scope). Surfaces any pre-existing must-fix violations newly observable due to scanner rule additions. Pre-existing findings on first run are logged to `.build-loop/issues/` with break-what-if analysis (user decides scope). New-content findings are blocking. See `phases/ui-validation.md` for tuning.
|
|
161
|
+
- **Gate 5a — UI Input/Output Contract Scan** (only when `uiTarget != null`): walk the full rendered surface touched by the build and trace every input/output against `## UI Input/Output Contract`. Flag user-visible data without a component mapping, validation layer, state branch, or source trace. New-content gaps are blocking; pre-existing gaps are logged to `.build-loop/issues/` with user impact and recommended follow-up.
|
|
162
|
+
- **Gate 6 — Version-Bump Advisor** (only when `pluginWork: true`): run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/version_advisor.py --workdir "$PWD"`. Default state is `hold` — emits a one-line note in Review-F: `"N commits accumulated since vX.Y.Z. Holding version. Create .build-loop/release-pending.md when the batch is ready."` Switches to `suggest` only when `.build-loop/release-pending.md` exists; in `suggest` mode, Review-F proposes `vA.B.C` (semver inferred from Conventional Commits) and asks for explicit user confirmation before any plugin.json edit. Never auto-bumps. Never blocks. The marker file is the user's release signal; build-loop only ever advises.
|
|
163
|
+
- **Gate 7 — UX Triage** (only when `uiTarget != null`): run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/ux_triage.py --workdir "$PWD" --clear`. Static-scans for four dimensions — interactability, performance, data-accuracy beyond current scope, usability — across the full project (not just changed files). Each `blocker` or `major` finding becomes a queue entry in `.build-loop/ux-queue/<id>.md` with a complete fix plan, evidence, files-touched, and an `architecture_impact` flag. Minor findings stay in the Review-F report only. The agent layer augments static findings with `performance-assessor` and `fact-checker` agent dispatches against the same surface for dimensions the static scanner can't fully cover. Queue entries feed into Phase 5 Iterate (see "Iterate input contract" below). Never block the current build — UX rot fixes ride along, they don't gate.
|
|
164
|
+
- **Gate 8 — UI Coverage-Gap** (only when `uiTarget != null`): compare changed surfaces against existing project test files and the UI input/output contract. If a changed critical surface has no interaction/render coverage, add a queue entry to `.build-loop/ux-queue/` with `dimension: test-coverage` and a proposed repo-native test plan. Build-loop does not auto-draft `.ibr-test.json` files.
|
|
165
|
+
|
|
166
|
+
Blocking issues (Gates 1-4) -> route to Iterate; do not halt the run. For Gate 2 privacy findings, the orchestrator invokes the appropriate implementer, auditor, or specialist agent to remediate, then re-runs validation. Prefer `.gitignore` plus untracking for runtime/generated files, archive or private-store relocation over deletion for useful evidence, and redaction/scrubbing over removing useful public documentation. Queue entries (Gates 7-8) -> flow into Phase 5's prioritized work list. Warnings -> include in Report (sub-step G). Auto-bumping is forbidden.
|
|
167
|
+
|
|
168
|
+
### Sub-step E: Simplify (trim the diff)
|
|
169
|
+
|
|
170
|
+
Simplify = remove dead code AND restructure over-complex logic/architecture into clearer, equal-or-better-performing forms; preserve behavior + correctness. Both categories run as the default pass on every build.
|
|
171
|
+
|
|
172
|
+
Run `/simplify` (or load the `simplify` skill directly) against the changed files. The running build-loop subagent reasons over the diff directly and language-agnostically — no external tool required. Focus:
|
|
173
|
+
|
|
174
|
+
**Dead code (remove):**
|
|
175
|
+
- Inline single-use helpers extracted "just in case"
|
|
176
|
+
- Dead branches, commented-out code, unused imports
|
|
177
|
+
- Collapse try/except that catches a thing that can't happen
|
|
178
|
+
- Remove validation for invariants the type system or upstream already guarantees
|
|
179
|
+
- Reduce abstractions that have exactly one call site
|
|
180
|
+
|
|
181
|
+
**Over-complex logic/architecture (restructure — clear wins only):**
|
|
182
|
+
- Deep nesting that flattens without behavioral change (early-return, extracted predicate)
|
|
183
|
+
- Duplicated logic that a single well-named extraction eliminates (DRY)
|
|
184
|
+
- Accidental-quadratic or redundant multi-pass loops where a single-pass equivalent is obvious
|
|
185
|
+
- Needless indirection layers that obscure the data flow without protecting a boundary
|
|
186
|
+
|
|
187
|
+
For changed Python files, `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/complexity_detector.py --changed-files <changed .py files> --json` is a precise accelerator — its ranked hotspot envelope (`high_complexity`, `deep_nesting`, `accidental_quadratic`, `redundant_multipass`, `needless_indirection`) focuses attention on `severity: "high"` candidates. It is diff-scoped, zero-dependency, and non-fatal on unparseable/missing paths. Use it when it applies; reason directly over the diff for all other languages.
|
|
188
|
+
|
|
189
|
+
**Apply vs. advise.** APPLY a restructure only if all hold: (a) it is a clear win (not a lateral rewrite); (b) the existing test subset for the touched files still passes — reuse the Sub-step B Validate machinery on E's changed paths only, not the full gate; (c) public signatures and observable behavior are unchanged. If ambiguous, uncertain-architectural, or fails (b)/(c) → do not apply; emit as an advisory finding via the existing independent-auditor surface (Phase 4 Report `## Notes from judges`). No perf gate, no benchmark, no cost-proxy — equal-or-better performance is an unmeasured bonus, never asserted or gated.
|
|
190
|
+
|
|
191
|
+
Applied edits flow through the existing single-writer Phase 3 commit contract — part of the build's diff, not a side-channel.
|
|
192
|
+
|
|
193
|
+
Preserve: public API surface, test coverage, observability (logging/tracing), documented behavior, and modular boundaries that protect user value, scalability, accuracy, security, testability, or stable interfaces. If an integrated simplification is better, document `MODULARITY EXCEPTION: <reason>`. For **plugin work**: also re-run `plugin-dev/scripts/hook-linter.sh` against any touched `hooks.json` and `grep` the manifest for `../` or bare paths.
|
|
194
|
+
|
|
195
|
+
**Self-recursive builds:** when `selfRecursive.enabled == true` (the build is editing build-loop itself), Sub-step E also consumes `self_review.py`'s `self_simplification[]` findings as an additional hotspot source. Any simplification applied to build-loop's own code from this list MUST pass `python3 scripts/self_mod_verify.py --scope full --auto-revert --json` (`verdict: pass`) before it is committed. A `verdict: fail` auto-reverts the change; it does not route to Iterate — move it to `.build-loop/proposals/needs-human/` instead.
|
|
196
|
+
|
|
197
|
+
**Report.** Log one line: `[Simplify] N hotspots, M applied, K advised`; record applied/advised counts in the Sub-step G report. An applied rewrite that later fails a re-validate routes like any Sub-step B failure (Phase 5 Iterate, existing 5x cap).
|
|
198
|
+
|
|
199
|
+
#### Sub-step E telemetry
|
|
200
|
+
|
|
201
|
+
**Sub-step E telemetry (mandatory, every Review pass, all builds).** After E completes for this Review pass, the orchestrator MUST append one row to `state.json["reviewE"]` via:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
update_execution_state(state_path, 'review_e_pass',
|
|
205
|
+
files_scanned=[<files E actually inspected this pass>],
|
|
206
|
+
is_final=<True iff this is the final Review pass>)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
This is **measurement infrastructure, not a factor** — it is present and identical on every build regardless of any cadence policy. It records *what E did this pass*; it must NOT change *what E does*. `pass_idx` auto-derives from the existing row count (0-based). When a cadence policy scopes E to only iterate-changed files on Review re-entry, the recorded `files_scanned` naturally shrinks on non-first passes — that difference is the signal a deterministic scorer reads. Telemetry write failure is logged, never blocks the build.
|
|
210
|
+
|
|
211
|
+
### Sub-step F: Auto-Resolve (drain non-destructive open items)
|
|
212
|
+
|
|
213
|
+
Drain the candidate auto-resolve queue before writing the final scorecard. Items in the queue come from four sources:
|
|
214
|
+
|
|
215
|
+
- **Sub-step A Critic** — findings with normalized `severity in {medium, low}` AND `suggestion` naming a single `file:line` (canonical independent-auditor finding fields per `agents/independent-auditor.md`; QM v0.13.0 — legacy `minor→medium`, `info→low`)
|
|
216
|
+
- **Sub-step D Fact-Check & Mock Scan** — non-blocking gate findings (e.g. `Plugin Cache Sync` divergence, `Version-Bump Advisor` notes when `release-pending.md` is absent, single-file documentation drift)
|
|
217
|
+
- **Quality / performance findings this run** (C-HEAL / self_heal_safe_issues) — any quality or performance issue surfaced by this run's self-review, fact-check, simplify, or efficiency scan whose fix classifies SAFE. Auto-fix them in-pass; do NOT defer to followup, do NOT surface. RISKY/DECISION findings from this same path still route to `## Held` / report as usual.
|
|
218
|
+
- **Operator queue** — items previously deferred via the `## Held` section of a prior build's report
|
|
219
|
+
|
|
220
|
+
For each item:
|
|
221
|
+
|
|
222
|
+
1. Build a short `<label>` and the corresponding shell `<command>` describing the action.
|
|
223
|
+
2. Invoke `python3 scripts/autonomy_gate.py --workdir "$PWD" --action "<label>" --command "<command>" --json` (single source of truth — see `references/autonomy-config.md`).
|
|
224
|
+
3. Route on the verdict:
|
|
225
|
+
- `auto` (exit 0) → execute the action via the appropriate implementer/script and record the result in `## Done` for Report.
|
|
226
|
+
- `warn` (exit 0) → execute the action (does not block), record in `## Done` with `[warn] <reason>` prefix, and emit a one-line entry to `state.json.runs[].autonomyEvents[]` for match-rate tracking. See `references/autonomy-config.md` §"Warn-before-block workflow" for the autonomyEvents shape.
|
|
227
|
+
- `confirm` (exit 1) → record in `## Held` with the `reason` field from the gate's envelope verbatim. Do NOT prompt the operator inline.
|
|
228
|
+
- `block` (exit 2) → record in `## Blocked` with the same reason field.
|
|
229
|
+
|
|
230
|
+
Cap auto-execute attempts per item at the existing Iterate ceiling (5x). After the cap, demote to `## Held` with reason `"auto-resolve cap reached after N attempts"`.
|
|
231
|
+
|
|
232
|
+
**What does NOT belong in Auto-Resolve:**
|
|
233
|
+
- Strong-checkpoint findings from Sub-step A — a `nay` routes back to Execute (no iteration counter burn).
|
|
234
|
+
- Sub-step B Validate failures — those route to Phase 5 Iterate.
|
|
235
|
+
- Anything matching deployment_policy.py heuristics — autonomy_gate delegates to deployment_policy automatically; the verdict still flows through `auto | confirm | block`, but the source-of-truth is deployment_policy for those items.
|
|
236
|
+
|
|
237
|
+
The auto-resolve queue is rebuilt from scratch per Phase 4 invocation. Items not drained on a given pass don't carry forward unless explicitly re-surfaced by Sub-steps A/D on the next pass.
|
|
238
|
+
|
|
239
|
+
### Sub-step G: Report (only on final Review pass)
|
|
240
|
+
|
|
241
|
+
Runs only when all prior sub-steps pass OR when iteration cap is hit. Writes final artifacts and closes the build.
|
|
242
|
+
|
|
243
|
+
**No-critical/high exit gate (QM v0.13.0 Piece 3, BLOCKING).** Before this final pass may report `pass`, collect every reviewer findings JSON produced this run (independent-auditor + security-reviewer) and run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/review_finding_gate.py --findings-json <each.json> --json`. It normalizes legacy (`major→high`, `minor→medium`, `info→low`; security `CRITICAL|HIGH|MEDIUM|LOW` case-insensitively; ambiguous→`high`) and returns `{pass, blocking_count, ...}`, exit 1 when any `critical`/`high` finding is open (not `closed` + `closure_proof`). **Exit 1 → the final pass is blocked; route the blocking findings to Phase 5 Iterate** (the fixed 5-iteration cap cannot finalize with an open critical/high). Exit 0 → proceed. Medium/low never block here — they route through the ux-queue/followup with explicit disposition; they are never silently skipped.
|
|
244
|
+
|
|
245
|
+
**Judgment-dispatch gate (BLOCKING on stakes-gated runs).** The advisor/auditor ladders RECORD which rung fired but nothing ENFORCED it, so an inline run (skill-as-methodology, no orchestrator dispatch) silently sat at the inline-Opus floor and the Frontier judgment never happened (observed: agent-rally-point v0.1.2 ran 16 commits with 0 Fable dispatches until the user asked why). Before this final pass may report `pass`, run `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/judgment_gate.py --workdir "$PWD" --run-id <this run> --agent-tool-available <true|false> --json`. Pass `--run-id` so stakes/statuses/ledger are scoped to THIS run only (never a stale top-level trigger or a prior run's ledger row — the gate reads stakes from the run record); omit it to default to the latest `runs[]` entry. Pass `--agent-tool-available false` only for a nested orchestrator / no-Agent-tool context. Stakes-conditional (mirrors the ladders): no stakes trigger → `pass`; stakes fired + `auditor_status`/`advisor_status` shows a real Frontier/peer dispatch → `pass`; stakes fired + the inline floor (`fallback:inline-opus` / `not-run:parent-must-dispatch` / unrecorded) with the Agent tool reachable → **exit 1, `fail`**. **Exit 1 → the run is NOT review-complete: dispatch the independent-auditor (and, for a stakes-gated Phase 2, the advisor) to Frontier, then re-run.** Also fails on an `agent-ledger.jsonl` `verify`/`author` action recorded at a non-frontier tier. This closes the inline-substitution hole — the same class as the inline self-audit masquerading as the independent auditor.
|
|
246
|
+
|
|
247
|
+
Final report sections, in this order:
|
|
248
|
+
|
|
249
|
+
- `## Done` — every verified pass + every Auto-Resolve `auto` item, with one-line evidence each.
|
|
250
|
+
- `## Held` — items Auto-Resolve verdicted as `confirm`, with the `reason` field from `autonomy_gate.py` quoted verbatim. The user may run any held command manually if they want to. Build-loop does NOT prompt or auto-execute these.
|
|
251
|
+
- `## Blocked` — items Auto-Resolve verdicted as `block`, same shape as Held.
|
|
252
|
+
- `## Status markers` — ✅ Known / ⚠️ Untested / ❓ Unfixed (existing convention; keep this section).
|
|
253
|
+
|
|
254
|
+
Research citation gate: before emitting, read
|
|
255
|
+
`.build-loop/state.json.researchGate`. When `blocks_final_claims: true`, every
|
|
256
|
+
current/external/API/package claim in the report must cite the research packet
|
|
257
|
+
or explicitly say the evidence was unavailable and the claim is unverified. If
|
|
258
|
+
`packet_path` is non-null, add a compact `research_packet:` evidence item to
|
|
259
|
+
`## Done` or `## Status markers`.
|
|
260
|
+
|
|
261
|
+
Reference-capture report field (mirrors the researchGate citation contract):
|
|
262
|
+
every run reports one `references captured:` line in `## Done` or `## Status
|
|
263
|
+
markers` — `references captured: N (<files>)` when one or more external fetches
|
|
264
|
+
informed a decision and were captured via the canonical writer, `none — no
|
|
265
|
+
external fetch informed a decision` when no web/doc fetch fed a decision, or
|
|
266
|
+
`skipped: <rationale>` when a fetch informed a decision but capture was
|
|
267
|
+
intentionally not run. This makes the default-on capture trigger
|
|
268
|
+
(`references/research-trigger-policy.md` §"Reference Capture") accountable in the
|
|
269
|
+
run report instead of advisory-only.
|
|
270
|
+
|
|
271
|
+
Before emitting the final report, write the draft to a temp file and run BOTH linters (orthogonal — structural vs style):
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
python3 scripts/build_report_lint.py <draft.md> --json # structural: parallel_batch, merge_plan, evidence triplets
|
|
275
|
+
python3 scripts/report_lint.py <draft.md> --json # style: headline shape, validation line, jargon, contrastive pivot, length
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Structural lint (`build_report_lint.py`):
|
|
279
|
+
|
|
280
|
+
- Exit 0 → emit the report.
|
|
281
|
+
- Exit 1 → revise the report before emitting it. The linter blocks vague verified/known claims, missing `parallel_batch` / `parallel_skipped_reason`, and missing `merge_plan` fields.
|
|
282
|
+
- Exit 2 → lint outage. Record `[warn] build-report-lint skipped (<reason>)` in `## Done` and continue.
|
|
283
|
+
|
|
284
|
+
Style lint (`report_lint.py`) — WARN with self-heal, never a hard halt. The user has asked for enforced concise, no-jargon user-facing output (`skills/build-loop/references/output-style.md` is the contract):
|
|
285
|
+
|
|
286
|
+
- `summary.total == 0` → emit the report.
|
|
287
|
+
- `summary.total > 0` → auto-revise the draft ONCE to clear the findings (translate jargon to plain language per the contract's blocklist, rewrite a missing headline as a one-sentence statement of what changed, add a validation line naming the exact command/method that verified the work, remove contrastive-pivot constructions), then re-run the lint. If a second pass still has findings, emit the report with a `[warn] report-lint findings remain after one revise pass` line in `## Done` and continue. Never block on style.
|
|
288
|
+
- Script error / file not found → record `[warn] report-lint skipped (<reason>)` in `## Done` and continue.
|
|
289
|
+
|
|
290
|
+
The two lints are orthogonal: structural rules live in `build_report_lint.py`, style/jargon rules live in `report_lint.py`. Neither replaces the other. The lints target ONLY the final user-facing report markdown; internal envelopes between agents stay structured/jargon-ok.
|
|
291
|
+
|
|
292
|
+
Evidence contract: each verified/known claim carries its evidence in the compact form `✅ <claim> [<method> → <artifact>]` (e.g. `✅ auth works [pytest → ci.log]`); `@<observer>` only when the observer isn't this run's orchestrator. One line per claim — no restated context or process narration. Multi-chunk or parallel reports must include `merge_plan:` with `clean_against`, `conflicts_with`, and `suggested_order`.
|
|
293
|
+
|
|
294
|
+
**Forbidden in the report**:
|
|
295
|
+
- Recommendation-list headers (e.g. headers that invite operator selection of which items to execute)
|
|
296
|
+
- "Next Action" sentences that read like questions
|
|
297
|
+
- Any bullet phrased as `Want me to X?` or `Should I Y?`
|
|
298
|
+
- Any list that presents items as choices for the operator to pick from
|
|
299
|
+
|
|
300
|
+
If a category is empty (no Held items, no Blocked items), omit the section entirely — no header, no `_(none)_` placeholder. A reader infers "none" from absence.
|
|
301
|
+
|
|
302
|
+
Write scorecard to `.build-loop/evals/YYYY-MM-DD-<topic>-scorecard.md`.
|
|
303
|
+
|
|
304
|
+
**Debugger store + outcome**: for each resolved Review-B/Iterate failure, write a native `.build-loop/issues/<incident>.md` incident note with `{symptom, root_cause, fix, tags, files}`. If `availablePlugins.codingDebugger` is true and the run explicitly requested cross-project memory, mirror the same outcome to standalone Coding Debugger. Both sides of the memory feedback loop — local store and outcome status — are required for learning.
|
|
305
|
+
|
|
306
|
+
**Orphan scan**: invoke `Skill("build-loop:architecture-dead")` — runs `navgator dead`, diffs against the Phase 1 Assess baseline, surfaces ONLY new orphans introduced this build. No-ops cleanly when `.navgator/architecture/index.json` is absent.
|
|
307
|
+
|
|
308
|
+
**Deployment policy gate** (before any push/deploy): run:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/deployment_policy.py" \
|
|
312
|
+
--workdir "$PWD" \
|
|
313
|
+
--command "$CANDIDATE_DEPLOY_COMMAND"
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Follow the returned `action`: `auto` may proceed after Review passes; `confirm` requires an explicit user confirmation in chat before running the command; `block` must not run and should be reported as a configured repo policy. Defaults favor speed for preview/TestFlight and safety for production/unknown.
|
|
317
|
+
|
|
318
|
+
**Auto-version-bump (LAST step before push/merge for plugin-bearing repos)**: when `plugin.json` (or `.claude-plugin/plugin.json`) exists at repo root AND `git diff --name-only origin/main..HEAD` includes any path outside `docs/`, `tests/`, `*.md`: bump the patch segment of `plugin.json:version`; mirror the new version into every locally-known `.claude-plugin/marketplace.json` (search `~/dev/git-folder/`, `~/.claude/plugins/marketplaces/`) entry referencing this plugin; commit `chore(version): bump <plugin-name> to <new-version>`. No minor/major bumps; no bumps for docs-only diffs.
|
|
319
|
+
|
|
320
|
+
**Post-deploy verification gate (after a deploy actually ran)**: once a deploy executed — i.e. the deployment policy gate returned `auto` and the deploy/push command ran, or the pushed branch auto-deploys via Vercel — invoke `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/verify_deploy.py --workdir "$PWD" --changed-route <route> [--changed-route <route> ...] --json`. The script detects a Vercel link (`.vercel/project.json` or `vercel.json`), resolves the latest production deployment, polls `vercel inspect` to a terminal state, then probes the prod root + each changed route. `pass` proceeds; `fail` routes to Iterate using the envelope's `findings` as the rubric; `skipped` (no Vercel link, CLI missing, not authed, or other transient infra) records `deploy_verify: skipped (<reason>)` in Review-F and proceeds. An auth-gated `401`/`403` on a protected route is **healthy** (function deployed and running) — only a `5xx`/build-error is a real failure. Never block the build on infra. See `agents/build-orchestrator.md` §"Review: Post-deploy verification gate" for the routing rules and `fallbacks.md#web-deploy-verify` for the inline degraded procedure.
|
|
321
|
+
|
|
322
|
+
**Append a run entry to `.build-loop/state.json.runs[]`** for Learn (Phase 6) to scan. The orchestrator agent owns the invocation — see `agents/build-orchestrator.md` §G for the canonical call (including `--judge-decisions-json` and `--budget-summary-json`). Schema and flags are owned by `scripts/write_run_entry/__main__.py --help`; do not hand-write JSON.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Phase 5: Iterate (full protocol)
|
|
4
|
+
|
|
5
|
+
> Loaded from `skills/build-loop/SKILL.md` summary. Contains the full Iterate phase: prioritized work list, fan-out, stuck-cascade, and convergence detection.
|
|
6
|
+
|
|
7
|
+
## Phase 5: Iterate — Fix Review Failures + UX Queue (up to 5x)
|
|
8
|
+
|
|
9
|
+
**Goal**: Fix failures surfaced by Review *plus* drain the UX queue accumulated by Sub-step D Gates 7-8, systematically not blindly. Loops back to Review after each pass.
|
|
10
|
+
|
|
11
|
+
Entered when Review sub-step A, B, or D finds blocking issues OR `.build-loop/ux-queue/` is non-empty. Critic-only failures (strong-checkpoint from A without touching B) route to Execute instead — no iteration counter burn.
|
|
12
|
+
|
|
13
|
+
**Iterate input contract (prioritized work list)**:
|
|
14
|
+
|
|
15
|
+
| Priority | Source | Notes |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| 1 | Blocking Validate failures (Sub-step B) | Test/lint/build/UI validation failures |
|
|
18
|
+
| 2 | Blocker UX queue entries with `architecture_impact: false` | `.build-loop/ux-queue/*.md` filtered |
|
|
19
|
+
| 3 | Major UX queue entries with `architecture_impact: false` | Same source, lower severity |
|
|
20
|
+
| 4 | Optimization findings (Sub-step C) | Opt-in |
|
|
21
|
+
| 5 | UI coverage-gap queue entries (`dimension: test-coverage`) | Lowest — additions, not fixes |
|
|
22
|
+
| **deferred** | Any UX entry with `architecture_impact: true` | Surfaces in Review-F for explicit user confirmation; Iterate does not pick up |
|
|
23
|
+
|
|
24
|
+
The "code is cheap, AI agents build fast" framing: the orchestrator does NOT defer based on patch size. It defers only when `architecture_impact: true` (new component, new data flow, navigation graph change, schema migration, auth provider swap). Everything else is fair game for the current loop.
|
|
25
|
+
|
|
26
|
+
**Fan-out** (mode-dependent): After dequeue, partition entries by `files_touched` into independent groups (no overlapping files).
|
|
27
|
+
|
|
28
|
+
- **Top-level mode** (orchestrator invoked directly via the user's session): dispatch up to 4 `implementer` subagents in parallel via `Agent(subagent_type="build-loop:implementer", ...)` per the bundled `agents/implementer.md` (Sonnet 4.6, scoped tools=[Read, Write, Edit, Bash, Glob, Grep]). Hard cap from `~/.claude/CLAUDE.md` §Sub-Agents. Sequential groups process after the parallel batch.
|
|
29
|
+
- **Subagent mode** (orchestrator was itself spawned via `Agent(...)` so the no-sub-sub-agents rule applies): degrade to **inline-implementer mode** — iterate the queue serially, apply each fix following the implementer's protocol (scope to `files_touched`, refuse `architecture_impact: true`, verify locally before declaring fixed). No parallelism, same quality bar. The orchestrator surfaces the degradation in Review-F.
|
|
30
|
+
|
|
31
|
+
In both modes, each pass returns the same structured outcome (status + files_changed + verifications). Status routing covers all 9 implementer return values:
|
|
32
|
+
- `fixed` → mark done (delete the .md)
|
|
33
|
+
- `partial` → keep entry, re-pass next iteration
|
|
34
|
+
- `scope_breach` → ask user before extending scope
|
|
35
|
+
- `deferred_architecture` → Review-F surfaces for explicit user confirmation
|
|
36
|
+
- `evidence_stale` → regenerate via `ux_triage.py --clear`, then re-pass
|
|
37
|
+
- `plan_malformed` → same as `evidence_stale` (regenerate); log id to `.build-loop/state.json.malformedPlans[]`
|
|
38
|
+
- `needs_dependency` → ask user; never auto-add deps
|
|
39
|
+
- `failed` → re-pass with implementer's `notes` as `additional_context`; after 2 attempts escalate to Opus per `model-tiering`; after 3 surface as ❓ Unfixed
|
|
40
|
+
- `concurrent_modification_detected` → abort current parallel batch (orchestrator partition bug; never transient)
|
|
41
|
+
|
|
42
|
+
Results re-enter Sub-step B for re-validation. For Validate failures (no queue entry), construct an inline plan in the same shape and treat identically.
|
|
43
|
+
|
|
44
|
+
**UI re-validate hook (when uiTarget != null)**: After each implementer subagent reports back AND before re-entering Sub-step B Validate, the orchestrator runs the build-loop-owned UI re-validate path for affected surfaces: `ui-validator` for web routes when resolvable, native AX driver for macOS, or simulator screenshot/interaction commands for iOS. Catches "fix introduced a new visual or interaction regression" cheaply, without burning a full Validate cycle. If no renderable surface can be resolved, record the gap and fall back to `audit-design-rules.mjs`. IBR is not invoked unless the user explicitly requested it for this build.
|
|
45
|
+
|
|
46
|
+
**Infra self-heal before counting an attempt (C-HEAL / self_heal_safe_issues).** When an Iterate attempt's own tooling, hook, or Bash command FAILS (infra error — non-zero exit that is not a graded-criterion failure, e.g. a pre-commit hook crash, a lint runner that throws on a binary file, a script that errors on a missing env var): ROOT-CAUSE and FIX that infra error first. Classify via `scripts/classify_action.py`. SAFE → apply, verify (re-run the failed action), commit, then resume the Iterate attempt. RISKY/DECISION/PRODUCTION → isolate/surface per the normal routing table. An infra self-heal does NOT burn the iterate budget; only a graded-criterion failure (test/lint/validate failure against the rubric) burns a count. This prevents `--no-verify` bypasses and other workarounds from masking fixable infra errors.
|
|
47
|
+
|
|
48
|
+
Per attempt:
|
|
49
|
+
1. **Diagnose root cause** — don't just retry. Start the failure brief in plain language, then trace visible symptom -> technical failure -> upstream dependency/interface/process failure -> first controllable system failure. Actor-blame phrases such as "agent forgot" or "model missed context" are not terminal causes unless paired with the missing control that allowed them.
|
|
50
|
+
2. **Stuck-iteration cascade (always on)**: at the START of EACH attempt, the orchestrator runs the cascade in order — see `agents/build-orchestrator.md` §Phase 5 for the full ladder. Summary:
|
|
51
|
+
- **Evidence-gap repair (highest priority)**: if the prior gate flagged `evidence_gap: true`, invoke `Skill("build-loop:logging-tracer")` with intent `repair`. Ephemeral-by-default — Mechanism A (`DEBUG_TRACE=1` runtime gate) or Mechanism B (`git-stash` throwaway). Re-run the failed criterion; if output is now informative, proceed with new context.
|
|
52
|
+
- **Memory-first re-check**: invoke `Skill("build-loop:debugging-memory")` again with the new symptom (it may have shifted shape after the prior fix attempt).
|
|
53
|
+
- **2 consecutive same-root-cause failures** → parallel multi-domain assessment via `build-loop:debugging-assess`. Pass `model: sonnet` to domain assessors explicitly (override `inherit` default to prevent 4× Opus fan-out from the Opus 4.7 orchestrator). The full procedure is documented in `skills/debug-loop/SKILL.md` §"If stuck — parallel multi-domain assessment".
|
|
54
|
+
- **3 consecutive same-criterion failures** → causal-tree investigation via `Skill("build-loop:debug-loop")`. Runs its own 7-phase cycle internally; returns with fix applied or hard-stop.
|
|
55
|
+
3. **Build the prioritized work list** from the table above (Validate failures + UX queue).
|
|
56
|
+
4. **Partition for parallel fan-out**: group by disjoint `files_touched`; dispatch ≤4 subagents in parallel.
|
|
57
|
+
5. **Execute fixes**; for UI files, run the UI re-validate hook before continuing.
|
|
58
|
+
6. **Loop back to Review sub-step B** (Validate). Sub-step A (Critic) usually skipped on re-runs unless the fix touched new files. Sub-steps C-F run only on final pass.
|
|
59
|
+
7. **Followup overflow**: when the iteration cap (5) is reached and queue entries remain, write them to `.build-loop/followup/<topic>.md` for a subsequent `/build-loop:run` invocation. Plan content is already complete — the followup build skips its own Plan phase for these entries.
|
|
60
|
+
8. **Track**: attempt count, what failed, what was attempted, what changed, queue depth before/after each pass.
|
|
61
|
+
|
|
62
|
+
**Convergence detection**:
|
|
63
|
+
- Same criterion fails 2x with same root cause → escalate to user
|
|
64
|
+
- Fix A breaks criterion B (oscillation) → flag and ask user
|
|
65
|
+
- 3+ criteria fail simultaneously after a fix → systemic issue, stop and reassess
|
|
66
|
+
|
|
67
|
+
**Stop condition (QM v0.13.0 — severity-aware, replaces the blunt 5-cap for critical/high)**. The 5-iteration cap still bounds the loop, but it **cannot finalize with an open `critical` or `high` finding** (the no-critical/high exit gate in Review-G, `review_finding_gate.py`, blocks the final pass). On reaching the cap:
|
|
68
|
+
- **Open `critical`/`high` remain** → do NOT silently ship as ❓ Unfixed. Escalate to the user with the blocking findings and their `closure_proof` gaps; the build does not pass until they close or the user explicitly waives. (If the same approach keeps failing, re-plan instead of burning more iterations.)
|
|
69
|
+
- **Only `medium`/`low` remain** → proceed to Review sub-step G Report with those marked ❓ Unfixed and routed to `.build-loop/followup/<topic>.md` for a subsequent run.
|
|
70
|
+
|
|
71
|
+
Log each iteration to `.build-loop/state.json`.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
|
|
3
|
+
# Phase 6: Learn (full protocol)
|
|
4
|
+
|
|
5
|
+
> Loaded from `skills/build-loop/SKILL.md` summary. Contains the full Learn phase: pattern detection, experimental skill drafting, and sample review sweep.
|
|
6
|
+
|
|
7
|
+
## Phase 6: Learn — Cross-Build Pattern Detection (mandatory; always runs and always reports)
|
|
8
|
+
|
|
9
|
+
**Goal**: detect recurring patterns across recent runs, auto-draft experimental skills/agents to address them, surface them for keep/remove decisions. Closes the loop between "build N times" and "build N+1 is faster because we learned."
|
|
10
|
+
|
|
11
|
+
**Load the `build-loop:self-improve` skill for the full protocol.** (Skill keeps its existing name for backward compatibility; this phase was named "Self-Improvement Review" in v0.2.0 — renamed here to avoid collision with Phase 4 Review.)
|
|
12
|
+
|
|
13
|
+
**Mandatory contract (v0.30.0+).** Every Phase 6 always does three things: (a) dispatches the Haiku detector (cheap), (b) runs `consolidate_memory.py` + `procedural_governance.py --mode detect-patterns` (already unconditional), and (c) emits a `## Learn` outcome line in the Review-G report — even when nothing crosses threshold. Net marginal cost over the prior gated path is one cheap Haiku state-scan per run. The expensive arm (Sonnet draft + Opus signoff) stays conditional on `runs[] >= 3` AND a pattern crossing threshold AND not-deferred. Also user-invokable via `/build-loop:self-improve` to run a scan without a build.
|
|
14
|
+
|
|
15
|
+
Quick flow:
|
|
16
|
+
|
|
17
|
+
1. **Detect** — dispatch `recurring-pattern-detector` (Haiku). Reads **two signal sources**:
|
|
18
|
+
- **Signal 1**: `.build-loop/state.json.runs[]` — emits `phase_failure`, `manual_intervention`, and `security_finding` patterns (real pain signals; `diagnostic_repeat` and `file_churn` were removed to prevent skill sprawl). **`runs[]` is written by the orchestrator's Review-G, so an INLINE run (skill-as-methodology, no orchestrator dispatch) records nothing and is invisible to Learn.** Any run-close path that did not go through Review-G — inline runs, the memory closeout — MUST record the run with `python3 scripts/append_run.py --workdir "$PWD" --run-id <id> --goal "..." --outcome <done|partial|blocked> [--manual-intervention "<phase>:<note>"] [--phase "<id>:<status>"]` (append-only, idempotent on `run_id`). Without it, inline work never accrues toward the `runs[] >= 3` threshold and recurring inline pain (e.g. the user re-prompting for a skipped step) never becomes a `manual_intervention` pattern.
|
|
19
|
+
- **Signal 2**: `.build-loop/proposals/enforce-from-retro/*.md` (the post-push retrospective's enforce-candidates) — emits `enforce_recurrence` patterns when the same normalized candidate signature appears across ≥ 2 distinct run-ids. The orchestrator may cite `python3 scripts/enforce_retro_signals.py --workdir "$PWD" --json` as pre-computed input to the agent. This delivers "anything prompted/needed repeatedly → enforce" **across** sessions, not just within one.
|
|
20
|
+
2. **Filter** — keep only `confidence: high` or `count >= 4`; manual interventions at lower threshold. Dedupe against existing active/experimental skill names. Cap 2 artifacts per scan.
|
|
21
|
+
3. **Draft** — for each kept pattern, dispatch `self-improvement-architect` (Sonnet). Writes to `.build-loop/skills/experimental/<name>/SKILL.md` with an A/B Experiment section including `run_id` and `co_applied_experimental_artifacts[]` schema.
|
|
22
|
+
4. **Signoff** — orchestrator (Opus 4.7) reviews each draft: APPROVE / REVISE (1 retry) / DISCARD.
|
|
23
|
+
5. **Sample review sweep** — for artifacts in `.build-loop/skills/experimental/` from prior runs: if `.build-loop/config.json.autoPromote` is true AND effective (non-confounded) sample ≥ 8 AND target met → eligible for promotion. **Promotion is no longer silent.** Each eligible candidate goes through (a) advisory review by `promotion-reviewer` (Opus, agent), (b) async user confirmation via PushNotification + TaskCreate fallback. The reviewer's variance verdict (approve / rethink / new_approach) becomes the body of the notification. Move from `experimental/` to `active/` happens only after the user confirms via `/build-loop:promote-experiment <name>`. Regressions and inconclusive-at-2N write proposals to `.build-loop/proposals/` for user confirmation — never auto-delete.
|
|
24
|
+
|
|
25
|
+
**Promotion-reviewer dispatch protocol** (per advisory-judge design, plan §12 / `agents/promotion-reviewer.md`):
|
|
26
|
+
- For each eligible candidate, dispatch `Agent(subagent_type="build-loop:promotion-reviewer", ...)` with brief fields: `artifact_path`, `experiment_log`, `sample_size`, `target_metric`, `triggering_run_id`, `recent_judge_decisions`.
|
|
27
|
+
- Append the returned verdict object to the run's `judge_decisions[]` via `python3 ${CLAUDE_PLUGIN_ROOT}/scripts/write_run_entry/__main__.py --judge-decisions-json <verdict.json>` (combined with other Phase 4 verdicts if any).
|
|
28
|
+
- Compose the user-facing notification body from the verdict's `variances[]` and `meta_guidance`. Fire `PushNotification` if available; fall back to `TaskCreate` with subject `"[BUILD-LOOP] Promotion candidate <name>: <verdict> — review needed"`.
|
|
29
|
+
- Write a marker file at `.build-loop/proposals/<name>.pending.md` with the verdict + how-to-confirm so the user can resume context later (TTL 14 days; lapsed candidates auto-archive to `.build-loop/proposals/<name>.lapsed.md`).
|
|
30
|
+
- **Do not move the artifact.** The user-invoked `/build-loop:promote-experiment <name>` command performs the move after reading the pending verdict.
|
|
31
|
+
|
|
32
|
+
6. **Notify** — concise synthesis appended to Review sub-step G report, including: (a) removal command for each artifact moved or proposed, (b) for each pending promotion: the reviewer verdict + confirmation command.
|
|
33
|
+
|
|
34
|
+
**Always-run + report gating (v0.30.0)**
|
|
35
|
+
|
|
36
|
+
Phase 6 has NO "skip entirely" condition. Three outcome states cover every run:
|
|
37
|
+
|
|
38
|
+
| State | Trigger | What runs | Review-G `## Learn` line |
|
|
39
|
+
|---|---|---|---|
|
|
40
|
+
| **Accruing** | `runs[] < 3` | Detector + consolidation only (no Sonnet draft) | `Learn: accruing (N/3 runs)` |
|
|
41
|
+
| **Deferred** | debug-only (`closeout: false` in dispatch envelope) OR budget-exhausted (`budget_check` envelope `action == "finalize_and_stop"` at Phase 6 entry) | Detector + consolidation; write `.build-loop/proposals/learn-deferred-<run-id>.md` marker with `{reason, runs_count, budget_action}`; skip Sonnet draft + Opus signoff | `Learn: deferred — <reason>` |
|
|
42
|
+
| **Full** | `runs[] >= 3` AND detector returned a pattern AND not deferred | Detector + consolidation + Sonnet draft + Opus signoff + sample sweep | `Learn: <N> patterns drafted` (or `Learn: 0 patterns above threshold (N runs scanned)` when detector returned nothing) |
|
|
43
|
+
|
|
44
|
+
**Deprecated escape hatch (migration no-op).** `.build-loop/config.json.autoSelfImprove: false` is no longer honored. It is read for migration safety: when present and `false`, the orchestrator appends a one-line `state.json.warnings[]` entry (`"autoSelfImprove: false is deprecated; ignored (migration no-op)"`) and proceeds as if the key were absent. Old user configs do not error. Remove the key at your convenience.
|
|
45
|
+
|
|
46
|
+
**User control (unchanged safety boundary)**:
|
|
47
|
+
- Remove any artifact: `rm -rf .build-loop/skills/experimental/<name>/` or `active/<name>/`
|
|
48
|
+
- Block re-promotion of a name: add it to `.build-loop/skills/.demoted`
|
|
49
|
+
- Inspect tracking: `cat .build-loop/experiments/<name>.jsonl`
|
|
50
|
+
- Promotion to `active/` STILL requires explicit `/build-loop:promote-experiment <name>` (decision-3 safety boundary preserved — auto-promote of unreviewed drafts never happens).
|
|
51
|
+
- Auto-promote defaults to OFF — set `"autoPromote": true` to enable (requires effective sample ≥ 8).
|
|
52
|
+
|
|
53
|
+
**What this phase will NOT do**:
|
|
54
|
+
- Modify the build-loop plugin repo
|
|
55
|
+
- Promote artifacts cross-project without explicit `/build-loop:promote-experiment <name>`
|
|
56
|
+
- Run more than once per build
|