@tyroneross/build-loop 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/AGENTS.md +71 -18
  6. package/README.md +208 -299
  7. package/agents/advisor.md +2 -0
  8. package/agents/alignment-checker.md +2 -0
  9. package/agents/api-assessor.md +3 -1
  10. package/agents/architecture-scout.md +2 -0
  11. package/agents/assessment-orchestrator.md +2 -0
  12. package/agents/build-orchestrator.md +13 -8
  13. package/agents/database-assessor.md +107 -3
  14. package/agents/design-contract-specialist.md +2 -0
  15. package/agents/fact-checker.md +2 -0
  16. package/agents/fix-critique.md +26 -5
  17. package/agents/frontend-assessor.md +3 -1
  18. package/agents/implementer.md +2 -0
  19. package/agents/independent-auditor.md +2 -0
  20. package/agents/mock-scanner.md +2 -0
  21. package/agents/optimize-runner.md +2 -0
  22. package/agents/overfitting-reviewer.md +2 -0
  23. package/agents/performance-assessor.md +3 -1
  24. package/agents/plan-critic.md +5 -2
  25. package/agents/promotion-reviewer.md +2 -0
  26. package/agents/recurring-pattern-detector.md +4 -1
  27. package/agents/retrospective-synthesizer.md +14 -0
  28. package/agents/root-cause-investigator.md +39 -2
  29. package/agents/scope-auditor.md +2 -0
  30. package/agents/security-reviewer.md +3 -0
  31. package/agents/self-improvement-architect.md +2 -0
  32. package/agents/synthesis-critic.md +2 -0
  33. package/agents/transcript-pattern-miner.md +2 -0
  34. package/agents/ui-validator.md +2 -0
  35. package/assets/build-loop-plugin-icon.png +0 -0
  36. package/bin/build-loop-install.js +234 -0
  37. package/commands/run.md +1 -1
  38. package/hooks/git/pre-commit +40 -0
  39. package/hooks/git/pre-push +35 -10
  40. package/hooks/hooks.json +42 -5
  41. package/hooks/pre-edit-architecture.sh +2 -2
  42. package/hooks/route-guard.sh +15 -0
  43. package/hooks/route_guard.py +221 -0
  44. package/hooks/session-start-extensions.sh +10 -0
  45. package/hooks/session-start-git-hooks.sh +6 -1
  46. package/hooks/session-start-rally-point.sh +23 -1
  47. package/hooks/test_session_start_rally_version.sh +123 -0
  48. package/package.json +7 -2
  49. package/plugin-artifacts/codex/.codex-plugin/plugin.json +1 -1
  50. package/plugin-artifacts/codex/AGENTS.md +77 -16
  51. package/plugin-artifacts/codex/README.md +208 -299
  52. package/plugin-artifacts/codex/assets/build-loop-plugin-icon.png +0 -0
  53. package/plugin-artifacts/codex/references/agent-role-taxonomy.md +34 -0
  54. package/plugin-artifacts/codex/references/backlog-system.md +285 -0
  55. package/plugin-artifacts/codex/references/capability-routing.md +49 -0
  56. package/plugin-artifacts/codex/references/coordination-file-template.md +2 -2
  57. package/plugin-artifacts/codex/references/coordination-rules.md +275 -6
  58. package/plugin-artifacts/codex/references/memory-systems.md +25 -2
  59. package/plugin-artifacts/codex/references/memory.md +16 -0
  60. package/plugin-artifacts/codex/references/model-tier-mapping.md +45 -6
  61. package/plugin-artifacts/codex/references/phase-1-assess.md +19 -1
  62. package/plugin-artifacts/codex/references/phase-2-plan.md +10 -1
  63. package/plugin-artifacts/codex/references/phase-3-execute.md +5 -3
  64. package/plugin-artifacts/codex/references/phase-4-review.md +22 -1
  65. package/plugin-artifacts/codex/references/phase-5-iterate.md +4 -3
  66. package/plugin-artifacts/codex/references/phase-6-learn.md +3 -1
  67. package/plugin-artifacts/codex/references/verify-dispatch.md +85 -0
  68. package/plugin-artifacts/codex/skills/build-loop/SKILL.md +19 -10
  69. package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +1 -1
  70. package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +49 -0
  71. package/plugin-artifacts/codex/skills/build-loop/references/experiment-results-template.md +101 -0
  72. package/plugin-artifacts/codex/skills/build-loop/references/memory.md +16 -0
  73. package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +98 -5
  74. package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +19 -1
  75. package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +10 -1
  76. package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +5 -3
  77. package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +22 -1
  78. package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +4 -3
  79. package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +3 -1
  80. package/plugin-artifacts/codex/skills/build-loop/references/verify-dispatch.md +85 -0
  81. package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +4 -0
  82. package/scripts/build_codex_plugin_artifact.py +7 -0
  83. package/scripts/embed_backend.py +17 -13
  84. package/scripts/lessons_index/query.py +1 -1
  85. package/scripts/memory_graph/__init__.py +2 -2
  86. package/scripts/sync_navgator_lessons.py +4 -4
  87. package/skills/api-registry-bridge/SKILL.md +1 -1
  88. package/skills/auto-decision-capture/SKILL.md +4 -3
  89. package/skills/auto-finding-capture/SKILL.md +119 -0
  90. package/skills/build-loop/SKILL.md +19 -10
  91. package/skills/build-loop/fallbacks.md +1 -1
  92. package/skills/build-loop/references/capability-routing.md +49 -0
  93. package/skills/build-loop/references/experiment-results-template.md +101 -0
  94. package/skills/build-loop/references/memory.md +14 -0
  95. package/skills/build-loop/references/output-style.md +98 -5
  96. package/skills/build-loop/references/phase-1-assess.md +19 -1
  97. package/skills/build-loop/references/phase-2-plan.md +10 -1
  98. package/skills/build-loop/references/phase-3-execute.md +5 -3
  99. package/skills/build-loop/references/phase-4-review.md +20 -1
  100. package/skills/build-loop/references/phase-5-iterate.md +4 -3
  101. package/skills/build-loop/references/phase-6-learn.md +2 -0
  102. package/skills/build-loop/references/verify-dispatch.md +85 -0
  103. package/skills/build-loop/templates/codex-worker-prompt.md +4 -0
  104. package/skills/debug-loop/SKILL.md +4 -2
  105. package/skills/debugging-memory/SKILL.md +24 -12
  106. package/skills/{debugging/assess/SKILL.md → debugging-memory/references/assess.md} +6 -13
  107. package/skills/{debugging/memory/SKILL.md → debugging-memory/references/search.md} +10 -17
  108. package/skills/{debugging/store/SKILL.md → debugging-memory/references/store.md} +5 -13
  109. package/skills/debugging-memory/references/subagent-integration.md +3 -3
  110. package/skills/defenseclaw-bridge/SKILL.md +1 -1
  111. package/skills/{loop-builder → focused-loop-builder}/SKILL.md +6 -6
  112. package/skills/ibr-bridge/SKILL.md +1 -1
  113. package/skills/knowledge/SKILL.md +13 -2
  114. package/skills/{knowledge-review/SKILL.md → knowledge/references/review-mode.md} +8 -20
  115. package/skills/logging-tracer/SKILL.md +20 -4
  116. package/skills/model-bakeoff/SKILL.md +44 -0
  117. package/skills/model-tiering/SKILL.md +55 -20
  118. package/skills/optimize/SKILL.md +2 -2
  119. package/skills/prd-bridge/SKILL.md +1 -1
  120. package/skills/recursive-retrospective/SKILL.md +46 -0
  121. package/skills/recursive-retrospective/references/01-retrospective.md +136 -0
  122. package/skills/recursive-retrospective/references/02-learning-capture.md +72 -0
  123. package/skills/recursive-retrospective/references/03-judge.md +45 -0
  124. package/skills/research/SKILL.md +1 -1
  125. package/skills/root-cause-analysis/SKILL.md +42 -0
  126. package/skills/security-methodology/SKILL.md +10 -1
  127. package/skills/security-scan/SKILL.md +55 -0
  128. package/skills/spec-writing/SKILL.md +42 -1
  129. package/skills/sync-skills/SKILL.md +8 -7
  130. package/commands/assess.md +0 -41
  131. package/commands/compose-handoff.md +0 -113
  132. package/commands/debug.md +0 -20
  133. package/commands/debugger-detail.md +0 -34
  134. package/commands/debugger-scan.md +0 -15
  135. package/commands/debugger-status.md +0 -20
  136. package/commands/debugger.md +0 -32
  137. package/commands/optimize-run.md +0 -31
  138. package/commands/promote-experiment.md +0 -129
  139. package/commands/rally-point.md +0 -301
  140. package/commands/research-run.md +0 -22
  141. package/commands/review-knowledge.md +0 -16
  142. package/commands/self-review.md +0 -51
  143. package/commands/setup-memory.md +0 -32
  144. package/commands/start-prd.md +0 -57
  145. package/commands/test.md +0 -34
  146. package/commands/verify-plan.md +0 -39
  147. package/skills/debugging/debug-loop/SKILL.md +0 -231
  148. package/skills/logging-tracer-bridge/SKILL.md +0 -70
  149. /package/skills/{loop-builder → focused-loop-builder}/presets/active-project-evidence.yaml +0 -0
  150. /package/skills/{loop-builder → focused-loop-builder}/presets/generic-artifact-loop.yaml +0 -0
  151. /package/skills/{loop-builder → focused-loop-builder}/presets/presentation-audit.yaml +0 -0
  152. /package/skills/{loop-builder → focused-loop-builder}/presets/research-synthesis.yaml +0 -0
  153. /package/skills/{loop-builder → focused-loop-builder}/presets/source-ingestion-raw-data-audit.yaml +0 -0
  154. /package/skills/{loop-builder → focused-loop-builder}/references/spec-format.md +0 -0
  155. /package/skills/{loop-builder → focused-loop-builder}/scripts/loop_builder.py +0 -0
@@ -333,19 +333,19 @@ def _upsert_lesson(
333
333
  with conn.cursor() as cur:
334
334
  if project is None:
335
335
  cur.execute(
336
- f"DELETE FROM {schema}.semantic_facts "
336
+ f"DELETE FROM {schema}.semantic_facts " # nosec: schema is a validated identifier (^[a-z][a-z0-9_]*$); values bound as params
337
337
  "WHERE subject = %s AND project IS NULL;",
338
338
  (subject,),
339
339
  )
340
340
  else:
341
341
  cur.execute(
342
- f"DELETE FROM {schema}.semantic_facts "
342
+ f"DELETE FROM {schema}.semantic_facts " # nosec: schema is a validated identifier (^[a-z][a-z0-9_]*$); values bound as params
343
343
  "WHERE subject = %s AND project = %s;",
344
344
  (subject, project),
345
345
  )
346
346
  if vec_lit is None:
347
347
  sql = (
348
- f"INSERT INTO {schema}.semantic_facts "
348
+ f"INSERT INTO {schema}.semantic_facts " # nosec: schema is a validated identifier (^[a-z][a-z0-9_]*$); values bound as params
349
349
  "(subject, predicate, object, confidence, status, embedding, metadata, "
350
350
  " project, tool, task_category, files_touched, "
351
351
  " confidence_source, domain) "
@@ -368,7 +368,7 @@ def _upsert_lesson(
368
368
  )
369
369
  else:
370
370
  sql = (
371
- f"INSERT INTO {schema}.semantic_facts "
371
+ f"INSERT INTO {schema}.semantic_facts " # nosec: schema is a validated identifier (^[a-z][a-z0-9_]*$); values bound as params
372
372
  "(subject, predicate, object, confidence, status, embedding, metadata, "
373
373
  " project, tool, task_category, files_touched, "
374
374
  " confidence_source, domain) "
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: api-registry-bridge
3
- description: Use when Phase 1 Assess or Phase 5 Iterate detects a new API dependency, API config fails, or the user asks to "register this API" or "check the API registry". Consults api-registry plugin; degrades gracefully if plugin is absent.
3
+ description: Use when Phase 1 Assess or Phase 5 Iterate detects a new API dependency, API config fails, or the user asks to "register this API" or "check the API registry". Consults api-registry plugin; degrades gracefully if plugin is absent. NOT for PRD strategic grounding (use `prd-bridge`) or UI verification (use `ibr-bridge`).
4
4
  user-invocable: false
5
5
  ---
6
6
 
@@ -141,7 +141,7 @@ captures should set these explicitly when the signal is clear:
141
141
  | Field | Skill default | Example | When to override |
142
142
  |---|---|---|---|
143
143
  | `--tool` | `claude-code` (Stop hook fires inside Claude Code) | `claude-code` | If the conversation references another tool authoring the decision (rare) |
144
- | `--model` | `claude-opus-4-7` (or `$CLAUDE_MODEL`) | `claude-sonnet-4-6` | When you know the active sub-agent's model |
144
+ | `--model` | `claude-opus-4-8` (or `$CLAUDE_MODEL`) | `claude-sonnet-5` | When you know the active sub-agent's model |
145
145
  | `--author` | `auto` (skill-driven captures) | `auto` | Always `auto` for in-session skill writes |
146
146
  | `--project` | derived from entity prefix or `$CLAUDE_PROJECT_DIR` | `build-loop` | Almost never; the default is right |
147
147
  | `--task-category` | `unknown` if no signal | `bugfix`, `feature`, `refactor`, `research`, `docs`, `migration`, `experiment`, `config` | **Set explicitly** whenever the conversational signal is clear (user said "fix this bug" → `bugfix`; "add this feature" → `feature`; "investigate why X" → `research`) |
@@ -367,8 +367,9 @@ self-heals as more signal arrives.
367
367
 
368
368
  ## When the user runs `/knowledge:review`, surface…
369
369
 
370
- The review surface (loaded by `build-loop:knowledge-review`, backed by
371
- `scripts/knowledge_review.py`) shows four sections of decisions and
370
+ The review surface (loaded by `build-loop:knowledge` review mode
371
+ `references/review-mode.md`, backed by `scripts/knowledge_review.py`)
372
+ shows four sections of decisions and
372
373
  procedures awaiting human attention:
373
374
 
374
375
  1. **Review queue** — tier-3 / inferred captures sitting in
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: auto-finding-capture
3
+ description: Project-scoped skill documenting build-loop's DEFAULT-ON auto-capture of clearly-identified findings/issues into the backlog, regardless of which terminal or agent surfaced them. Provides the detection contract, routing rules, dedup strategy, and the standing rule that agents/critics must NOT gate identified issues behind a user selection. Use when an agent, audit, or critic surfaces a concrete severity-labeled issue, or when reasoning about where findings persist.
4
+ user-invocable: false
5
+ when_to_use: |
6
+ - Any agent/audit/critic states a concrete, severity-labeled issue in the session
7
+ - A dispatched ad-hoc audit (Codex, NavGator, a security pass) returns findings in conversation
8
+ - You are about to ask the user "which of these should I add to the backlog?" — DON'T; capture is automatic
9
+ - You need to know where session findings persist and how they dedup
10
+ namespace: .build-loop/backlog/ (review-queue overflow: .build-loop/proposals/)
11
+ companion_scripts:
12
+ - scripts/scan_findings/__main__.py — Stop-hook deterministic findings sweep
13
+ - scripts/scan_findings/detect.py — detector (severity-label + structured-JSON extraction)
14
+ - scripts/backlog.py — the single writer (new/sync/list); mirrors to build-loop-memory on sync
15
+ - scripts/review_finding_gate.py — canonical severity taxonomy (SEVERITY_MAP), reused for normalization
16
+ ---
17
+
18
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
19
+
20
+ # auto-finding-capture — clearly-identified findings land in the backlog by DEFAULT
21
+
22
+ A clearly-identified finding is durable work. The user should never have to
23
+ remember to add it, and should never be asked to select which findings to keep.
24
+ Whenever ANY agent, audit, or critic surfaces a concrete issue in a session —
25
+ build-loop's own in-run reviewers OR an ad-hoc audit dispatched from a plain
26
+ terminal (Codex, NavGator, a one-off security pass) — that finding is captured
27
+ to the backlog automatically at session end.
28
+
29
+ ## Standing rule (binding)
30
+
31
+ **Do not gate an identified issue behind a user selection.** If an agent or
32
+ critic has stated a concrete, severity-labeled finding, it is captured — full
33
+ stop. Asking "which of these should I add to the backlog?" is the workflow
34
+ violation this skill exists to remove. Surface findings in conversation AND let
35
+ them persist; the two are not in tension. The user can always drop a backlog
36
+ item later (`status: dropped` + `backlog.py sync`); they cannot recover a
37
+ finding that was never written down.
38
+
39
+ This mirrors the analogous DEFAULT-ON behavior for DECISIONS
40
+ (`auto-decision-capture` + `scan_transcript_for_decisions.py`) and for
41
+ CORRECTIONS/LESSONS (`scan_corrections`). Findings are the third lane.
42
+
43
+ ## How it works — deterministic Stop-hook sweep
44
+
45
+ The Stop hook in `hooks/hooks.json` runs `python3 -m scan_findings` against
46
+ `$CLAUDE_TRANSCRIPT_PATH` at session end. It is **deterministic (zero-LLM)** —
47
+ pure regex + JSON parsing, no Ollama dependency — so it fails open with no model
48
+ installed. It scans the agent-authored surface of the transcript: host-assistant
49
+ text blocks AND `tool_result` blocks (where a dispatched sub-agent's condensed
50
+ return lands). It does NOT reach a sub-agent's isolated internal transcript —
51
+ only what surfaces in the session, which is exactly the gap this closes (ad-hoc
52
+ audits report their findings into the conversation).
53
+
54
+ ### What counts as a clearly-identified finding (high precision over recall)
55
+
56
+ | Signal | Example | Route |
57
+ |---|---|---|
58
+ | **Structured findings JSON** (recognized severity) | `{"findings":[{"severity":"high","title":"Token logged in plaintext"}]}` | **backlog** |
59
+ | **Prose severity label** (UPPERCASE) + concrete clause | `HIGH: verify-install.yml interpolates dispatch input into shell — command injection` | **backlog** |
60
+ | **Explicit `severity:` field** + clause | `severity: medium — cache key collides across tenants` | **backlog** |
61
+ | Structured finding with **absent/unknown severity** | `{"severity":"banana","title":"..."}` | **review queue** |
62
+ | Prose **finding keyword / Bug:/Issue: prefix**, NO severity | `I suspect a race condition in the worker pool` | **review queue** |
63
+ | Anything else (questions, "low latency" prose, hedges) | `Is this high risk?` | ignored |
64
+
65
+ Routing is MECE: a **recognized severity** → backlog; a **finding signal without
66
+ a recognized severity** → `.build-loop/proposals/` for human triage; **neither**
67
+ → ignored. A false backlog item is worse than a missed one, so anything short of
68
+ an asserted severity goes to the review queue, never straight to the backlog.
69
+
70
+ ### Backlog mapping
71
+
72
+ Findings are written through `backlog.py new` (the single, host-agnostic writer
73
+ — never by hand), with:
74
+
75
+ - `--type fix`, `--area audit`
76
+ - `--priority` from severity: critical→P0, high→P1, medium→P2, low→P3
77
+ - `--provenance-source auto-finding-sweep[:<agent>]` — marks the auto-sweep and
78
+ the originating agent where detectable (e.g. `auto-finding-sweep:security-reviewer`)
79
+ - `--provenance-ref finding-hash:<hash>` — the cross-session dedup key
80
+
81
+ ### Dedup (idempotent)
82
+
83
+ Each finding carries a stable `finding-hash` = sha1 of its severity-stripped
84
+ normalized clause. Before writing, the sweep loads every existing backlog item
85
+ (active + archived) and review proposal and collects their hashes + normalized
86
+ titles. A candidate is skipped when its hash already exists OR its normalized
87
+ title equals an existing open item's title. Re-running the sweep on the same
88
+ transcript creates nothing new. The same finding re-stated at a different
89
+ severity (or re-swept on a later Stop) hashes identically and is deduped.
90
+
91
+ ## Hook safety contract
92
+
93
+ Non-blocking, fail-open, identical guardrails to the decision sweep:
94
+
95
+ - any error logs and exits 0 (the hook backgrounds with `nohup … &; printf '{}'`)
96
+ - `.build-loop/.no-capture` (per-session opt-out) → clean exit 0
97
+ - single-flight `fcntl.flock` on `/tmp/build-loop-findings-scan.lock`
98
+ - wall-clock budget `SCAN_FINDINGS_BUDGET_S` (default 15s); partial completion is
99
+ safe (each backlog write is its own atomic `backlog.py new` process)
100
+ - durable log at `${XDG_STATE_HOME:-~/.local/state}/build-loop/findings-scan.log`
101
+
102
+ ## Manual run
103
+
104
+ ```bash
105
+ # What the Stop hook runs (PYTHONPATH lets `-m scan_findings` resolve):
106
+ PYTHONPATH=scripts python3 -m scan_findings \
107
+ --workdir "$PWD" --transcript "$CLAUDE_TRANSCRIPT_PATH" --print-json
108
+ ```
109
+
110
+ `--print-json` reports `{candidates, backlog, review, skipped_dup}`. After a
111
+ sweep, `python3 scripts/backlog.py sync --repo .` refreshes the INDEX and mirrors
112
+ the new items into `build-loop-memory/projects/<slug>/backlog/`.
113
+
114
+ ## Deferred (NOT built)
115
+
116
+ An LLM-judged extraction path (for findings stated without a severity label or a
117
+ finding keyword) is a possible future extension. v1 is deterministic-only by
118
+ design: it satisfies the acceptance contract, adds no dependency, and keeps
119
+ precision high. Add the LLM path only against a named, observed miss in this repo.
@@ -14,17 +14,22 @@ A 5-phase development loop with a mandatory Phase 6: assess state and criteria,
14
14
 
15
15
  ## Routing
16
16
 
17
- `/build-loop:run <any task>` is the single entry for all coding work build, fix, optimize, research, debug, or test. The orchestrator classifies intent automatically and routes to the right mode; no flag or command choice required.
17
+ **`/build-loop:run` is the ONLY human-facing command.** Type it with any request in plain language or just describe what you need — and the orchestrator classifies intent and routes to the right internal mode. No flags, no picking a mode, no other commands to learn. Everything below is reached by intent, not by a separate command; agents/build-loop invoke these internally.
18
18
 
19
- Internal modes:
19
+ Intent → internal mode:
20
20
 
21
- - **Build** (default): Full 5-phase loop plus mandatory Phase 6 Learn — triggered by implementation, fix, refactor, migrate, or update language
22
- - **Optimize**: Metric-driven optimization loop triggered by "speed up", "reduce", "improve" + a mechanical metric (`/build-loop:optimize-run` as a direct override)
23
- - **Research**: Pre-decision analysis, outputs a research packet, no commits triggered by "research", "evaluate", "compare", "should I" (`/build-loop:research-run` as a direct override)
24
- - **Debug**: Deep iterative root-cause investigation triggered by symptom language; also auto-invoked inside the loop on Review-B failures (`/build-loop:debug` as a direct override)
25
- - **Test**: Static plugin-test suite — triggered by "test plugin", "validate plugin" (`/build-loop:test` as a direct override)
21
+ - **Build** (default): full 5-phase loop + mandatory Phase 6 Learn — implementation / fix / refactor / migrate / update / "add" / "wire up" language.
22
+ - **Debug**: deep iterative root-cause investigationsymptom language ("broken", "doesn't work", "failing"); also auto-invoked on Review-B failures.
23
+ - **Optimize**: metric-driven optimization loop — "speed up", "reduce", "improve" + a mechanical metric.
24
+ - **Research**: pre-decision analysis, research packet, no commits "research", "evaluate", "compare", "should I".
25
+ - **Test**: static plugin-test suite — "test plugin", "validate plugin".
26
+ - **Root-cause analysis**: blameless RCA producing durable system levers — "root cause", "why did this fail", "post-mortem" (delegates to the `root-cause-analysis` skill).
27
+ - **Retrospective**: recursive learning retrospective on a build/project — "retrospective", "retro", "what did we learn", "review this project's trajectory" (delegates to `recursive-retrospective`). *Example: "I need a root cause and a retrospective" → run does both.*
28
+ - **Plan / spec**: "write a plan", "spec this" → spec-writing + plan-verify.
29
+ - **PRD**: "start a PRD", "spec out a new app" → prd-bridge / start-prd flow.
30
+ - **Self-improve / promote / knowledge / handoff / memory setup**: "scan recent runs", "promote this experiment", "record a decision", "hand this off", "set up memory" → the matching internal skill (self-improve, promotion-reviewer, knowledge, handoff, setup-memory).
26
31
 
27
- The standalone commands are advanced overrides for forcing a specific mode. Normal usage only needs `/build-loop:run`.
32
+ **Design intent:** one command for humans, plain-language routing, everything else agent-invoked within build-loop. If a request doesn't match a mode, run treats it as a Build task or asks one clarifying question — it never makes the user pick a command.
28
33
 
29
34
  ### Parallelism config
30
35
 
@@ -95,6 +100,8 @@ Self-heal is **both reactive and proactive**. It is not only triggered by errors
95
100
 
96
101
  **Investigate every open issue to root cause before declaring done — verified by a second subagent.** Before any "done"/completion claim, investigate EVERY open issue — failed tests, loose ends, errors, warnings, minor issues — none are left unaddressed. For each, reach the ROOT CAUSE, not a surface patch. Use the debugging skills (`build-loop:debug-loop` / `root-cause-investigator` / `systematic-debugging`) and/or a **5-whys / causal-tree** analysis to determine the true cause and its blast radius (same root cause at other sites → fix all of them). The fix MUST address the root cause — a surface patch is a violation — AND MUST be verified by another, independent subagent before "done." The second-subagent check reuses `independent-auditor`, `fix-critique`, or a dispatched verifier — no new agent required.
97
102
 
103
+ **Closure test (counterfactual):** a root cause is not closed at "an actionable control." It is closed only when the named lever would have **prevented, detected, or contained THIS exact failure on the real input** (not a hand-constructed one) — a control that exists but stays dormant on the real signal does not count. **Fix strength:** prefer the strongest feasible control — `eliminate → impossible-state → automated-block → detect → contain → decision-support → docs` — over the reflex "add a detect-gate." A dependency you don't own is never "ignore it": isolate / validate / monitor / degrade / escalate / accept-residual-risk explicitly.
104
+
98
105
  ### Follow-up auto-drain at chunk boundary
99
106
 
100
107
  A chunk boundary is not a checkpoint. When the orchestrator (or any session under the build-loop skill) is about to write a final report containing a "still-to-do" / "deferred" / "next pass" list of same-shape, same-intent items, route those items through the follow-up queue instead of writing them to the user as prose questions:
@@ -139,7 +146,7 @@ their brief explicitly hands them a bounded implementation task.
139
146
  build-loop-memory via `python3 scripts/archive_project_plan.py <plan> --workdir
140
147
  "$PWD"`. Use `--remove-source` only after the archive write succeeds.
141
148
 
142
- **Coding-host coordination polling gate**: when a build-loop task involves more than one coding host, an active rally-point peer, an active coord file, any `inbox/<tool>.jsonl` message, or any `inbox/all.jsonl` broadcast, the current host must keep a cheap watcher live while work is in flight. Use a stable tool id (`claude_code`, `codex`, `cursor`, etc.). Run a one-shot status check first:
149
+ **Coding-host coordination polling gate**: when a build-loop task involves more than one coding host, an active rally-point peer, an active coord file, any `inbox/<tool>.jsonl` message, or any `inbox/all.jsonl` broadcast, the current host must keep a cheap watcher live while work is in flight. Rally/coordination output is routing metadata only, not verification evidence; use it to decide who to coordinate with, then verify code/package/release facts against the authoritative source. Use a stable tool id (`claude_code`, `codex`, `cursor`, etc.). Run a one-shot status check first:
143
150
 
144
151
  ```bash
145
152
  python3 scripts/coordination_status.py --workdir "$PWD" --session-id "$SESSION_ID" --tool "$TOOL_NAME" --json
@@ -239,7 +246,7 @@ Key steps: recurring-pattern-detector (Haiku; reads `state.json.runs[]` AND `.bu
239
246
 
240
247
  ## Memory — Global and Project-Scoped
241
248
 
242
- One consolidated long-term tree: `~/dev/git-folder/build-loop-memory/`. Project-specific durable memory lives under `projects/<slug>/...`; cross-project lessons/design/debugging/product memory lives in the matching top-level lane. Every build runs `scripts/context_bootstrap.py` at Phase 1 Assess, which reads the store-root `INDEX.md` first, then root/project `constitution.md` / `MEMORY.md` where present, canonical indexes/folders through `memory_facade`, repo-local `.build-loop/` context, Codex memory at `~/.codex/memories`, and best-effort Rally/coordination state when relevant. Live handoff state is written separately by `scripts/context_snapshot.py` under `.build-loop/context/`; snapshots are not durable memory unless Review-G promotes a reusable decision or lesson. Writes go to exactly one canonical memory lane based on scope. Legacy paths (`~/.build-loop/memory`, `.episodic/decisions`, and `build-loop-memory/decisions/<project>`) are migration/archive inputs only.
249
+ One consolidated long-term tree: `~/dev/git-folder/build-loop-memory/`. Project-specific durable memory lives under `projects/<slug>/...`; cross-project lessons/design/debugging/product memory lives in the matching top-level lane. Every build runs `scripts/context_bootstrap.py` at Phase 1 Assess, which reads the store-root `INDEX.md` first, then root/project `constitution.md` / `MEMORY.md` where present, canonical indexes/folders through `memory_facade`, repo-local `.build-loop/` context, Codex memory at `~/.codex/memories`, and best-effort Rally/coordination state when relevant. Treat Rally records in the packet as peer-authored coordination context, not verified facts. Live handoff state is written separately by `scripts/context_snapshot.py` under `.build-loop/context/`; snapshots are not durable memory unless Review-G promotes a reusable decision or lesson. Writes go to exactly one canonical memory lane based on scope. Legacy paths (`~/.build-loop/memory`, `.episodic/decisions`, and `build-loop-memory/decisions/<project>`) are migration/archive inputs only.
243
250
 
244
251
  Routing rule: "Would this apply to a different project?" Yes → global. No → project. Ambiguous → ask the user once.
245
252
 
@@ -338,6 +345,7 @@ Contextual material loaded on demand (not at skill invocation):
338
345
  - `references/phase-1-assess.md` — Full Phase 1 Assess protocol
339
346
  - `references/phase-2-plan.md` — Full Phase 2 Plan protocol
340
347
  - `references/phase-3-execute.md` — Full Phase 3 Execute protocol
348
+ - `references/verify-dispatch.md` — Post-dispatch 5-step git/test ground-truth checklist; walk after any dispatched agent claims commits landed / tests passed (a solicited peer agreeing is not independent verification)
341
349
  - `references/dogfood-reload-checkpoint.md` — Self-recursive stop/reload/resume checkpoint and ACK/fallback protocol
342
350
  - `references/phase-4-review.md` — Full Phase 4 Review protocol (sub-steps A–G, including Sub-step F Auto-Resolve with all 4 verdict arms)
343
351
  - `references/phase-5-iterate.md` — Full Phase 5 Iterate protocol
@@ -346,6 +354,7 @@ Contextual material loaded on demand (not at skill invocation):
346
354
  - `references/leadership.md` — Initiative + decision-escalation doctrine (decide-at-70%, self-research → memory → peers → persona panel → human-only-for-irreversible, parallel-work-before-idling, token-posture gauge). Synthesized from intent-based leadership / mission command / two-door decisions.
347
355
  - `references/research-trigger-policy.md` — Research plugin trigger/depth gate, t-shirt depth lower bounds, and final-claim citation/unavailable rule
348
356
  - `references/task-capture-policy.md` — Read-only active task surface over existing plan/state/queue/backlog surfaces; no new task ledger by default
357
+ - `references/backlog-system.md` — Host-agnostic, multi-repo backlog system: MD+YAML items (canonical truth) + regenerable INDEX, pure-stdlib `scripts/backlog.py` (new/sync/list), one-way mirror to personal memory. Read via `BACKLOG.md`→`INDEX.md`→grep; write via the CLI
349
358
  - `references/agent-role-taxonomy.md` — Lead/peer/coder-assessor/reviewer/skill responsibility map; use before adding or renaming agents.
350
359
  - `references/capability-routing.md` — Full capability routing table, trigger conditions, sub-routers
351
360
  - `references/recent-design-structures.md` — Recent UI structure library loaded by `design-contract-specialist` in Phase 2. Structures are options, not mandates.
@@ -418,7 +418,7 @@ Use the **6-Part Stack** for any system prompt or agent prompt:
418
418
  Calibrate to model tier:
419
419
 
420
420
  - **Frontier (T1 — Opus 4.6, GPT-5)**: can handle longer instructions, implicit reasoning, self-correction. Prefer clarity over verbosity.
421
- - **Mid (T2 — Sonnet 4.6, GPT-4)**: explicit instructions; show, don't tell; 1-2 few-shot examples help.
421
+ - **Mid (T2 — Sonnet 5, GPT-5 class)**: explicit instructions; show, don't tell; 1-2 few-shot examples help.
422
422
  - **Small/fast (T3 — Haiku 4.5, gpt-4-mini)**: keep prompts short; single task only; deterministic output format; more examples (3-5).
423
423
 
424
424
  Review checklist — when auditing an existing prompt:
@@ -25,6 +25,55 @@ Phase 1 runs `node ${CLAUDE_PLUGIN_ROOT}/skills/build-loop/detect-plugins.mjs` a
25
25
  | Modular systems pack | Phases 1-4 | Read `references/modular-systems-pack.md`; partition files/tasks MECE; prefer modular scalable boundaries unless an exception is documented |
26
26
  | Codex subagent adapter | Phase 3 (Execute, Codex only) | Read `references/codex-subagents.md`; use `templates/codex-worker-prompt.md` for authorized Codex workers |
27
27
 
28
+ ### Spec/Plan author router (intent-driven, ordered)
29
+
30
+ This router selects the single skill that AUTHORS the plan/spec/task graph for this run. It is a recommendation that DRIVES Phase 2 — recorded into `state.json.intent.spec_router`, consumed by Phase 2 Plan, never a hard block.
31
+
32
+ **Scope — author selection only.** `prd-bridge` is NOT in this router. It is mandatory in Phase 1 step 10 and only *consumes* an existing PRD (`docs/prd-*.md` → `state.json.prd`); it never authors. PRD-context is orthogonal to author selection — keep them separate.
33
+
34
+ **Governing rule**: select on intent + goal + context, not on a trigger-word match. A skill's word-overlap activation is not enough to call it (this is why `prd-builder` over-fired during build-loop runs). The router is the intent-side selection; it pairs with the activation-side guard (prd-builder's negative-trigger scope, which excludes in-flight changes and active build-loop runs).
35
+
36
+ Signals (all set during Phase 1 Assess):
37
+
38
+ - `run_active` — is a build-loop run active? (`true` for any `/build-loop:run` or build-orchestrator dispatch.)
39
+ - `plan_status` — `no-plan` | `plan-valid`, from the Phase 2 plan-exists gate (`.build-loop/plan.md` absent/empty + last `plan-verify` result).
40
+ - `intent_kind` — `PRD-author` | `build-plan` | `task-graph` | `none`, the LLM's read of what this run needs authored.
41
+ - `code_exists` — does the repo have substantive existing code? (Assess maps architecture: new/empty repo → false, existing repo → true.)
42
+ - `goal_scope` — `new-app` | `existing-app-change` | `in-build-task-breakdown`.
43
+
44
+ The rows are ORDERED — first match wins, so exactly one author is selected and no case matches two. The final default row makes the table exhaustive: every `(run_active, plan_status, intent_kind)` combination matches exactly one row, so nothing falls through.
45
+
46
+ | # | Match condition (first true wins) | route_type / action | Author selected | Why |
47
+ |---|---|---|---|---|
48
+ | 1 | `intent_kind == none` — nothing to author (Q&A, status, trivial, read-only, or advisory-context-only) | `noop` (call nothing) | — (`skill: null`) | no plan/spec/task graph needed |
49
+ | 2 | `run_active == false` AND greenfield PRD authoring is explicitly intended (new app with no code, OR `/start-prd` requested for a project) | `call` (or `recommend` outside an interactive session) | `prd-builder` | greenfield authoring + interactive intake; honors prd-builder's negative trigger — never fires inside an active run |
50
+ | 3 | `run_active == true` AND `plan_status == no-plan` | `call` | `build-loop:spec-writing` | author the in-build, non-interactive, gated plan for the orchestrator |
51
+ | 4 | `run_active == true` AND `plan_status == plan-valid` | `call` | `build-loop:writing-plans` (external) | turn the accepted plan into the task / dependency graph |
52
+ | 5 (default) | else (no earlier row matched) — the canonical case is `run_active == false` AND `intent_kind` is `build-plan` or `task-graph`: a direct, out-of-run invocation of plan authoring on an existing repo | `recommend` | `build-loop:spec-writing` | recommend, not auto-call: there is no active run to drive, so surface the author for the lead to run if it chooses |
53
+
54
+ The order is the contract: row 1 short-circuits before any author runs; row 2 is the only PRD author and is fenced off from active runs; rows 3 and 4 are mutually exclusive on `plan_status`; row 5 is the exhaustive `else` default that catches every remaining combination — its canonical case is an out-of-run `build-plan`/`task-graph` intent, but as the final row it also absorbs any residual (e.g. an out-of-run non-greenfield `PRD-author`) so no signal combination ever falls through. The table extends to any future author skill — add a row at the right precedence above the default, key it on the same signals, and the system still selects exactly one and records why.
55
+
56
+ `build-loop:writing-plans` (row 4) is the **external** `writing-plans` skill from the superpowers plugin — it is not vendored in this repo (`skills/writing-plans/SKILL.md` does not exist here). When it is absent, fall back to the inline "write a structured plan directly" path in the §"Core loop skills/assets" table above.
57
+
58
+ > Future refinement (do not over-build now): for monorepos, a `target_code_exists` signal (does the *target sub-path* already have code, vs the repo as a whole) would refine row 2's greenfield test. Out of scope until a monorepo case demands it.
59
+
60
+ **Phase 1 record (the consumable contract)**. Phase 1 writes the matched decision into `state.json.intent.spec_router` so a Codex lead (no `Skill()` auto-activation) can consume it deterministically:
61
+
62
+ ```json
63
+ {
64
+ "route_type": "author",
65
+ "action": "call" | "recommend" | "noop",
66
+ "skill": "build-loop:spec-writing" | "build-loop:writing-plans" | "prd-builder" | null,
67
+ "fallback": "<fallbacks.md section or inline guidance> | null",
68
+ "matched_row": 1 | 2 | 3 | 4 | 5,
69
+ "signals": { "run_active": true, "plan_status": "no-plan", "intent_kind": "build-plan", "code_exists": true, "goal_scope": "existing-app-change" }
70
+ }
71
+ ```
72
+
73
+ `action: "noop"` → `skill: null`, Phase 2 authors nothing from the router (terminal). `action: "recommend"` → `skill` carries the recommended author name (so the lead knows what to run if it chooses); Phase 2 surfaces the recommendation in the report and does NOT auto-call. `action: "call"` → `skill` is non-null and Phase 2 calls it. The three actions are distinct: `call` auto-invokes, `recommend` surfaces-only, `noop` skips.
74
+
75
+ **Phase 2 read (the load-bearing wire)**. Phase 2 Plan READS `state.json.intent.spec_router` and acts on `action`/`skill` — it does NOT independently re-decide which author to call. See `references/phase-2-plan.md` step 0.
76
+
28
77
  ### Phase quick reference
29
78
 
30
79
  | # | Phase | Purpose | Sub-steps / key actions |
@@ -0,0 +1,101 @@
1
+ <!-- SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com> | SPDX-License-Identifier: Apache-2.0 -->
2
+ <!-- CONFIG: v1.0 | T2 | plugin(report-writeup) | Analytical | SCORE: 22/25 [A:5|C:4|Cs:5|D:4|Cp:4] -->
3
+
4
+ # Experiment / data-analysis results — reusable template + guide
5
+
6
+ One write-up shape for any analysis: A/B, DOE / full-factorial / fractional-factorial,
7
+ regression, backtest, ablation, regression-test. Fill the blanks; delete the Method
8
+ sub-lines that don't apply; never delete the honesty rails (n, direction legend,
9
+ certainty, "not computed — why").
10
+
11
+ ---
12
+
13
+ ## The template (copy below this line)
14
+
15
+ ```markdown
16
+ # <test name> — results
17
+ <!-- headline: DECISION: <build X / don't / inconclusive> · certainty: <high|medium|low> · n=<N> -->
18
+
19
+ ## Objective
20
+ - **Testing:** <the one thing under test>
21
+ - **Why:** <the recurring problem or the decision this informs>
22
+ - **Payoff if it succeeds (user-visible):** <what changes for the end user / consumer>
23
+ - **Decision this unblocks:** <what we do differently on a pass vs a fail>
24
+
25
+ ## What we did
26
+ - **Analysis type:** <A/B | DOE full-factorial | fractional-factorial | regression | backtest | ablation | regression-test | other>
27
+ - **Method (1 paragraph):** <how it ran, start to finish>
28
+ - **Sample size n = <N>** (<unit: bugs / runs / requests / rows / sessions>) ← never omit
29
+ - **Arms / factors** (keep the line that fits your type):
30
+ - A/B: control = <...> · treatment(s) = <...>
31
+ - DOE/factorial: factors × levels = <...> · runs = <...> · design = <full | fractional res IV | ...>
32
+ - Regression: predictors = <...> · response = <...> · model = <OLS | logistic | ...>
33
+ - Backtest: data + window = <...> · in/out-of-sample split = <...>
34
+ - Ablation: component removed = <...> · baseline = <...>
35
+ - **Held constant (confounds managed):** <model, environment, inputs, seed, …>
36
+ - **Measurement:** <who/what scored, against what ground truth, and exactly how>
37
+ - Blinding: <none | labels withheld | fully blinded> — <if you claim blinded, say what made it so; if a tell leaked, say so>
38
+
39
+ ## Hypothesis
40
+ - **Predicted:** <outcome> **because** <mechanism / prior reason>
41
+ - **Pass means:** <what it implies> → **action:** <...>
42
+ - **Fail means:** <what it implies> → **action:** <...>
43
+ - **Pre-registered?** <yes + link | no> · decision rule fixed before running? <yes | no>
44
+
45
+ ## Results
46
+
47
+ **Metric legend — state direction for EVERY metric (this is mandatory):**
48
+ | Metric | Measures | Direction | Scale |
49
+ |--------|----------|-----------|-------|
50
+ | <m1> | <...> | higher better / lower better | <0–2 · % · ms · count · $> |
51
+ | <cost> | effort/latency/$ | lower better (only counts when quality ties or wins) | <calls · s · $> |
52
+
53
+ **Data:**
54
+ | <arm / run / config> | <m1> | <m2> | <cost> |
55
+ |---|---|---|---|
56
+ | <...> | | | |
57
+
58
+ **Statistics — fill what you actually computed; for the rest write "not computed — <why>":**
59
+ - **Effect size:** <metric: value (e.g. Δ, Cohen's d, lift %)> | not computed — <why>
60
+ - **Statistical significance:** <test, p-value, CI> | **NOT COMPUTABLE — n=<N> too small (directional only)**
61
+ - **Correlation:** <vars: r> | not computed — <why>
62
+ - **Goodness of fit** (regression only): <R², adj-R², residual check> | n/a
63
+ - **Winner / direction:** <which, on which metrics>
64
+
65
+ ## Interpretation
66
+ - **Certainty:** ✅ high | ⚠️ medium | ❓ low — <why, tied to n + method strength>
67
+ - **What it shows / does NOT show:** <scope of the claim>
68
+ - **Threats to validity / confounds:** <weak blinding (how), small n, self-selected subject, model substitution, single grader, …>
69
+ - **Unknowns:** <what could not be verified>
70
+ - **Honesty check:** every adjective here is earned by the method — no "fair / blind / significant / proven" unless the method above supports it.
71
+
72
+ ## Next steps
73
+ - [ ] **Implement winner:** <...> (or: do not implement — <why>)
74
+ - [ ] **Stronger re-test:** <what raises certainty — larger n, cleaner blinding, a real significance test, second grader>
75
+ - [ ] **New tests suggested:** <...>
76
+ - [ ] **Risks to monitor after rollout:** <...>
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Usage guide
82
+
83
+ 1. **Pick one Method sub-line** for your analysis type; delete the others. The honesty
84
+ rails — `n`, the direction legend, the statistics block, certainty — stay regardless
85
+ of type.
86
+ 2. **Direction legend is not optional.** A table of numbers is unreadable without "higher
87
+ or lower better" per metric. Cost metrics (calls, time, $) are lower-better but only
88
+ count as a win when quality ties or improves (Accuracy > Speed > Cost).
89
+ 3. **When stats don't apply, say so explicitly** — never leave significance/correlation/
90
+ fit blank or imply them. Rules of thumb: significance/correlation need roughly n ≥ 8–10+
91
+ to mean anything; below that write "directional only (n too small)". Regression fit
92
+ (R²) is n/a unless you actually fit a model. DOE reports main effects + interactions,
93
+ not p-values, unless replicated.
94
+ 4. **Earn every adjective.** Do not write "fair", "blind", "robust", "significant", or
95
+ "proven" unless the Method section shows what made it so. If blinding leaked (e.g. the
96
+ treatment's output format was a tell), record it as a threat to validity — don't claim
97
+ blindness.
98
+ 5. **Headline = decision + certainty + n.** A decision-maker should get "build it / don't /
99
+ inconclusive", how sure, and on how much data, from the first line.
100
+ 6. **Pre-register when the result will drive a real decision** — commit Objective +
101
+ Hypothesis + decision rule before running, so the verdict can't be retrofit.
@@ -136,6 +136,20 @@ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/memory_writer.py \
136
136
 
137
137
  The writer auto-detects `source_repo` from the workdir's git remote, appends a row to the lane-local `INDEX.jsonl`, appends a row to the global update ledger at `indexes/updates.jsonl`, and (on update) preserves `created_at` + `applied_in_repos` so cross-repo validation history survives edits. Direct writes are repair/fallback work only: use them only when no canonical writer exists or the current task is explicitly a memory-system repair, then run the host index/check step and verify reachability.
138
138
 
139
+ ### Codex cross-repo write guard
140
+
141
+ When using Codex `apply_patch`, path resolution is relative to the active
142
+ workspace, not to a shell command `workdir`. If a memory artifact belongs in a
143
+ different repo such as `build-loop-memory`, use one of these safe paths:
144
+
145
+ - Prefer `scripts/memory_writer.py` for normal memory writes.
146
+ - If direct repair is unavoidable, pass absolute target paths to `apply_patch`.
147
+ - Before moving a generated file that already appeared in a Codex file card,
148
+ leave an openable pointer, mirror, or stub at the old path and update any
149
+ dependent indexes/links. Do not strand UI/Finder file cards at missing paths.
150
+ - After a move, verify both the canonical destination and every old path that a
151
+ user-facing file card, index, or markdown link still references.
152
+
139
153
  ### Reader side — surface peer writes via INDEX.jsonl
140
154
 
141
155
  Between phases (or at every M2 heartbeat), tail since your last check:
@@ -10,16 +10,18 @@ It extends — does not duplicate — the existing guidance:
10
10
 
11
11
  Scope: **user-facing output only.** Internal agent-to-agent envelopes (subagent return JSON, judge-decisions, run records, MECE briefs) are structured data and stay as-is — they exist for machines, not the human.
12
12
 
13
- ## The five rules
13
+ ## The rules
14
14
 
15
15
  1. **Headline = one plain full sentence** stating what changed. First non-blank line. Not a noun phrase, not a telegraph fragment, not a heading.
16
- 2. **Bulleted concrete artifacts.** Below the headline: commit hashes, file paths, issue paths. Concrete things the user can grep, open, or `git show`.
17
- 3. **Substance bullets.** What the change captures or does, in plain language. Optional when the artifacts alone are self-explanatory.
18
- 4. **Validation line, explicit.** Name the exact command, method, or observer that verified the work, with a status marker:
16
+ 2. **Outcome framing lead with what changes for the user.** The headline and substance lead with what the user can now do, what stops failing, or what no longer needs a manual step — the *result*, not the implementation. Use before→after when it clarifies. Mechanism, file paths, and design detail still belong in the report below the lead, in the progressive-disclosure detail (see rules 3–4), never in the headline. See "Outcome framing" below for the worked good/bad pair.
17
+ 3. **Bulleted concrete artifacts.** Below the headline: commit hashes, file paths, issue paths. Concrete things the user can grep, open, or `git show`.
18
+ 4. **Substance bullets.** What the change does for the user, in plain language (outcome-first per rule 2). Optional when the artifacts alone are self-explanatory.
19
+ 5. **Validation line, explicit.** Name the exact command, method, or observer that verified the work, with a status marker:
19
20
  - `✅ Verified by <method>` — ran the script, passing test, curl response, IBR scan, demo
20
21
  - `⚠️ Untested — <what couldn't be verified and why>`
21
22
  - `❓ Uncertain — <what's assumed and what would close it>`
22
- 5. **Plain language.** No jargon (see blocklist below). No contrastive pivot (`not X — it's Y`, `isn't X, it's Y`, `not just X but Y`) — state the point directly.
23
+ 6. **Plain language, stated directly.** No jargon (see blocklist below). No contrastive pivot (`not X — it's Y`, `isn't X, it's Y`, `not just X but Y`) and no soft hedging — state the point directly, and state cause and effect directly (see "Precision and Brevity" below: shorter words, data over adjectives, direct cause→effect). The contrastive-pivot ban and the direct-cause-and-effect rule are the same instinct: say what happened and why, without negation or padding.
24
+ 7. **Numbers only when supplied or verified.** Never invent a metric, date, percentage, or count to make a sentence concrete. This is the user-facing-style restatement of build-loop's existing "no false data, no unverified claims" guarantee — the fact-checker (Review-D) traces every rendered metric to its source; this rule keeps the report from adding one the fact-checker never saw. If you have no number, write the plain claim without one.
23
25
 
24
26
  ## Jargon blocklist (user-facing only)
25
27
 
@@ -39,6 +41,97 @@ These tokens are fine in internal envelopes; they must be translated to plain la
39
41
  | `state.json.runs[]` | "run record" |
40
42
  | Internal phase codenames (C-HEAL, C-RCA, C-FLOW…) | Describe the behavior, not the code |
41
43
 
44
+ ## Outcome framing — lead with the result, not the mechanism
45
+
46
+ The report describes what the change DOES FOR THE USER, not the feature or mechanism that delivers it. Lead with what the user can now do, what stops failing, or what no longer needs a manual step. Before→after where it clarifies. Plain language, minimal jargon. The mechanism — script names, normalization, TTLs, file paths — still appears, but in the progressive-disclosure detail below the lead, never in the headline or the first substance line.
47
+
48
+ This is judgment, not a deterministic check: `report_lint.py` does NOT grade outcome framing (a fuzzy "is this outcome-framed?" rule would false-green on disguised mechanism prose and false-block on terse-but-correct outcome reports). The rule is enforced by the Review-G one-pass self-heal — the orchestrator rewrites a mechanism-only lead into an outcome-first one before emitting.
49
+
50
+ ### Good — outcome-framed (the user-approved target style)
51
+
52
+ ```
53
+ When you run build-loop and a model it depends on goes down, the work now keeps
54
+ running on a backup instead of stopping and waiting for you to step in — and when
55
+ that model comes back, it returns to it on its own. You stop having to be the
56
+ manual fallback.
57
+
58
+ - No more stalled runs during an outage — if the preferred model is unavailable,
59
+ agents automatically continue on the next-best one, instead of erroring out and
60
+ needing a restart.
61
+ - Self-recovery — once the model is back, the system returns to it within about
62
+ half an hour by itself, rather than staying on the backup until someone resets it.
63
+ - Quality holds during fallback — it won't quietly drop verification to a weaker
64
+ model, and won't pick a model the setup can't run.
65
+ - Works as you add or change models — the same behavior applies no matter which
66
+ vendor a model comes from.
67
+ ```
68
+
69
+ Why this is good: the headline says what changes for the user ("the work now keeps running … you stop having to be the manual fallback"), each bullet leads with the user-visible outcome (no stalled runs, self-recovery, quality holds, works as you change models), and the before→after contrast ("instead of stopping and waiting", "rather than staying on the backup") makes the gain concrete. The mechanism that delivers it (the fallback script, the recovery window, the tier floor, vendor-agnostic resolution) is implied through outcomes, not enumerated.
70
+
71
+ ### Bad — mechanism-only (same change, tells the user nothing)
72
+
73
+ ```
74
+ Added dispatch_fallback.py with canonical-id normalization and a host-provider
75
+ filter; outages persist to model-availability.json with a TTL.
76
+ ```
77
+
78
+ Why this is bad: it is the exact same change, but described as the feature/implementation. The reader learns what files exist, not that their runs stop stalling during an outage or that quality holds on the backup. It leads with the mechanism (`dispatch_fallback.py`, `canonical-id normalization`, `host-provider filter`, `model-availability.json`, `TTL`) and never states the user outcome. The fix is the rewrite above: keep this detail, but move it below an outcome-first lead.
79
+
80
+ ## Precision and Brevity — sentence architecture
81
+
82
+ Clear, concise statements depend less on better words and more on sentence architecture. Strongest pattern: concrete noun + strong verb + specific object/outcome + cause/evidence when needed.
83
+
84
+ ### 1. Core elements of a clear sentence
85
+ | Element | Job | Strong | Weak |
86
+ |---|---|---|---|
87
+ | Actor/subject | Who or what it is about | The team | There was |
88
+ | Verb | What happened/changed | launched, cut, missed, caused | had, was, experienced |
89
+ | Object/outcome | What the action affected | the onboarding flow | the process |
90
+ | Cause | Why it happened | because ownership was split | due to various issues |
91
+ | Metric/evidence | What proves it | 70% dropped at step 5 | many users struggled |
92
+ | Time/place | When/where | in Q2, at step 5 of 7 | recently, during the process |
93
+ | Implication | Why it matters | so the team should shorten setup | which is important |
94
+
95
+ Core sentence spine: [Actor] [verb] [object/outcome] [because cause].
96
+ Example: The team launched behind schedule because ownership was split across three groups.
97
+
98
+ ### 2. Parts of speech: what to favor
99
+ - Nouns — concrete: name real things/people/roles/systems/outcomes. ("Users abandoned onboarding at step 5." not "There was friction in the user journey.")
100
+ - Verbs — carry the sentence: had an impact on→changed; was responsible for→caused; made improvements to→improved; experienced delays→slipped; provided support for→supported; made a decision→decided.
101
+ - Adjectives — only when they add precision: "missed the regulatory deadline" (why it matters) not "an important deadline" (asks for trust).
102
+ - Adverbs — usually replace with data: significantly increased→increased 42%; quickly resolved→resolved in two days; frequently failed→failed in 3 of 5 tests; strongly suggests→suggests; materially improved→improved conversion by 8 points.
103
+
104
+ ### 3. Most useful sentence patterns
105
+ 1. Outcome → Cause — [Actor] [outcome] because [cause]. ("The model gave inconsistent answers because the prompt lacked success criteria.")
106
+ 2. Metric → Behavior → Location → Meaning — [Metric] of [group] [behavior] at [point], suggesting [meaning]. ("70% of users abandoned onboarding at step 5 of 7, suggesting the flow was too long.") Use "suggesting" when data implies but does not prove a cause.
107
+ 3. Cause → Outcome — [Cause] caused [outcome]. ("No single owner caused the project to stall.")
108
+ 4. Actor → Action → Object → Reason — [Actor] should [action] [object] because [reason]. ("The team should cut onboarding from seven steps to three because most users drop off before setup is complete.")
109
+ 5. Decision → Rationale → Tradeoff — [Decision] works because [rationale], but [tradeoff]. ("A shorter onboarding flow should improve completion, but it may collect less user data upfront.")
110
+ 6. If → Then → Because — If [condition], then [action/outcome] because [reason]. ("If users abandon step 5, then the team should test a shorter flow because the current sequence likely asks for too much upfront.")
111
+
112
+ ### 4. Order of information
113
+ Default: (1) main point, (2) evidence or cause, (3) implication or next step.
114
+ Example: "Users are dropping out late in onboarding. 70% abandon at step 5 of 7, suggesting the setup asks for too much before users see value. The team should test a three-step version."
115
+
116
+ ### 5. Practical rule set
117
+ 1. Start with the real actor, not "there is" / "it is."
118
+ 2. Use one strong verb instead of a weak verb plus extra words.
119
+ 3. Prefer numbers over vague claims.
120
+ 4. Put the main point before the explanation.
121
+ 5. Use "because" for known causes.
122
+ 6. Use "suggesting" for likely causes.
123
+ 7. Cut adjectives unless they add specific meaning.
124
+ 8. Replace adverbs with data when possible.
125
+ 9. Keep one main idea per sentence.
126
+ 10. Keep caveats close to the claim they qualify.
127
+ Do not invent data: numbers, dates, and evidence appear only when supplied or verified (this is the user-facing-style face of build-loop's no-false-data principle + the fact-checker, not a second check).
128
+
129
+ ### Best default formula
130
+ [Specific actor] + [strong verb] + [specific outcome] + because + [specific cause].
131
+ Example: "Users abandoned onboarding because the seven-step flow asked for too much before showing value."
132
+
133
+ This section is JUDGMENT-enforced in the Review-G one-pass self-heal alongside outcome framing — `report_lint.py` does NOT grade "shorter words", sentence patterns, or "is this a causal sentence": a fuzzy check there would false-flag correct terse prose and over-block, against the deterministic-only-for-known-risks rule. The direct cause→effect guidance is the same instinct as rule 6's no-contrastive-pivot ban (state what happened and why, without negation or padding); the no-invented-data line is the user-facing-style face of rule 7 and of build-loop's standing "no false data, no unverified claims" principle, traced by the fact-checker in Review-D — not a second enforcement path. Apply these when rewriting the draft; do not add a lint for them.
134
+
42
135
  ## Good — the exemplar (Codex output, captured 2026-06-04)
43
136
 
44
137
  ```