@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.
Files changed (171) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +4 -4
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/AGENTS.md +11 -2
  6. package/README.md +8 -7
  7. package/agents/advisor.md +111 -0
  8. package/agents/alignment-checker.md +11 -0
  9. package/agents/assessment-orchestrator.md +1 -1
  10. package/agents/build-orchestrator.md +28 -33
  11. package/agents/fact-checker.md +1 -1
  12. package/agents/fix-critique.md +1 -1
  13. package/agents/independent-auditor.md +1 -1
  14. package/agents/overfitting-reviewer.md +1 -1
  15. package/agents/plan-critic.md +8 -6
  16. package/agents/promotion-reviewer.md +1 -1
  17. package/agents/retrospective-synthesizer.md +20 -3
  18. package/agents/scope-auditor.md +1 -1
  19. package/agents/security-reviewer.md +1 -1
  20. package/agents/self-improvement-architect.md +1 -1
  21. package/commands/{handoff.md → compose-handoff.md} +4 -4
  22. package/commands/{optimize.md → optimize-run.md} +1 -1
  23. package/commands/{agent-rally-point.md → rally-point.md} +3 -3
  24. package/commands/{research.md → research-run.md} +1 -1
  25. package/commands/setup-memory.md +32 -0
  26. package/commands/{plan-verify.md → verify-plan.md} +1 -1
  27. package/docs/agent-surface-policy.md +38 -20
  28. package/docs/memory-setup.md +19 -14
  29. package/hooks/_resolve_python.sh +28 -0
  30. package/hooks/closeout.sh +58 -0
  31. package/hooks/git/pre-push +69 -6
  32. package/hooks/hooks.json +34 -13
  33. package/hooks/post-push-closeout.sh +73 -0
  34. package/hooks/session-start-closeout.sh +69 -0
  35. package/hooks/session-start-memory.sh +27 -0
  36. package/hooks/session-start-plugin-heal.sh +33 -0
  37. package/hooks/test_closeout.sh +124 -0
  38. package/package.json +7 -4
  39. package/plugin-artifacts/codex/.codex-plugin/plugin.json +41 -0
  40. package/plugin-artifacts/codex/AGENTS.md +507 -0
  41. package/plugin-artifacts/codex/BUILD-ARTIFACT.md +5 -0
  42. package/plugin-artifacts/codex/LICENSE +202 -0
  43. package/plugin-artifacts/codex/README.md +404 -0
  44. package/plugin-artifacts/codex/docs/agent-surface-policy.md +63 -0
  45. package/plugin-artifacts/codex/references/advisor-dispatch-ladder.md +62 -0
  46. package/plugin-artifacts/codex/references/agent-role-taxonomy.md +135 -0
  47. package/plugin-artifacts/codex/references/autonomous-and-per-commit-modes.md +161 -0
  48. package/plugin-artifacts/codex/references/autonomy-config.md +231 -0
  49. package/plugin-artifacts/codex/references/capability-routing.md +182 -0
  50. package/plugin-artifacts/codex/references/codex-subagents.md +106 -0
  51. package/plugin-artifacts/codex/references/coordination-file-template.md +181 -0
  52. package/plugin-artifacts/codex/references/coordination-rules.md +283 -0
  53. package/plugin-artifacts/codex/references/dogfood-reload-checkpoint.md +112 -0
  54. package/plugin-artifacts/codex/references/halt-and-ask-protocol.md +102 -0
  55. package/plugin-artifacts/codex/references/implementer-envelope-schema.md +302 -0
  56. package/plugin-artifacts/codex/references/intent-capability-pack.md +257 -0
  57. package/plugin-artifacts/codex/references/intent-exploration-prompts.md +96 -0
  58. package/plugin-artifacts/codex/references/leadership.md +72 -0
  59. package/plugin-artifacts/codex/references/memory-systems.md +238 -0
  60. package/plugin-artifacts/codex/references/memory.md +299 -0
  61. package/plugin-artifacts/codex/references/model-tier-mapping.md +257 -0
  62. package/plugin-artifacts/codex/references/modular-systems-pack.md +96 -0
  63. package/plugin-artifacts/codex/references/phase-1-assess.md +231 -0
  64. package/plugin-artifacts/codex/references/phase-2-plan.md +78 -0
  65. package/plugin-artifacts/codex/references/phase-3-execute.md +49 -0
  66. package/plugin-artifacts/codex/references/phase-4-review.md +322 -0
  67. package/plugin-artifacts/codex/references/phase-5-iterate.md +71 -0
  68. package/plugin-artifacts/codex/references/phase-6-learn.md +56 -0
  69. package/plugin-artifacts/codex/references/recent-design-structures.md +274 -0
  70. package/plugin-artifacts/codex/references/research-trigger-policy.md +140 -0
  71. package/plugin-artifacts/codex/references/runtime-smoke-triggers.md +42 -0
  72. package/plugin-artifacts/codex/references/self-review.md +234 -0
  73. package/plugin-artifacts/codex/references/single-writer-commit-protocol.md +90 -0
  74. package/plugin-artifacts/codex/references/task-capture-policy.md +68 -0
  75. package/plugin-artifacts/codex/references/ui-io-contract.md +116 -0
  76. package/plugin-artifacts/codex/references/ui-spotcheck-protocol.md +65 -0
  77. package/plugin-artifacts/codex/skills/build-loop/SKILL.md +372 -0
  78. package/plugin-artifacts/codex/skills/build-loop/detect-plugins.mjs +82 -0
  79. package/plugin-artifacts/codex/skills/build-loop/eval-guide.md +65 -0
  80. package/plugin-artifacts/codex/skills/build-loop/fallbacks.md +549 -0
  81. package/plugin-artifacts/codex/skills/build-loop/phases/fact-check.md +42 -0
  82. package/plugin-artifacts/codex/skills/build-loop/phases/ui-validation.md +267 -0
  83. package/plugin-artifacts/codex/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
  84. package/plugin-artifacts/codex/skills/build-loop/references/apple-native-planning.md +439 -0
  85. package/plugin-artifacts/codex/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
  86. package/plugin-artifacts/codex/skills/build-loop/references/capability-routing.md +182 -0
  87. package/plugin-artifacts/codex/skills/build-loop/references/codex-subagents.md +106 -0
  88. package/plugin-artifacts/codex/skills/build-loop/references/coordination.md +161 -0
  89. package/plugin-artifacts/codex/skills/build-loop/references/correction-aware-capture.md +177 -0
  90. package/plugin-artifacts/codex/skills/build-loop/references/independent-auditor.md +72 -0
  91. package/plugin-artifacts/codex/skills/build-loop/references/intent-capability-pack.md +257 -0
  92. package/plugin-artifacts/codex/skills/build-loop/references/intent-exploration-prompts.md +96 -0
  93. package/plugin-artifacts/codex/skills/build-loop/references/leadership.md +72 -0
  94. package/plugin-artifacts/codex/skills/build-loop/references/memory.md +299 -0
  95. package/plugin-artifacts/codex/skills/build-loop/references/modular-systems-pack.md +96 -0
  96. package/plugin-artifacts/codex/skills/build-loop/references/output-style.md +129 -0
  97. package/plugin-artifacts/codex/skills/build-loop/references/pay-it-forward-arch.md +98 -0
  98. package/plugin-artifacts/codex/skills/build-loop/references/phase-1-assess.md +231 -0
  99. package/plugin-artifacts/codex/skills/build-loop/references/phase-2-plan.md +78 -0
  100. package/plugin-artifacts/codex/skills/build-loop/references/phase-3-execute.md +49 -0
  101. package/plugin-artifacts/codex/skills/build-loop/references/phase-4-review.md +322 -0
  102. package/plugin-artifacts/codex/skills/build-loop/references/phase-5-iterate.md +71 -0
  103. package/plugin-artifacts/codex/skills/build-loop/references/phase-6-learn.md +56 -0
  104. package/plugin-artifacts/codex/skills/build-loop/references/recent-design-structures.md +274 -0
  105. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/ASSESSMENT.md +85 -0
  106. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/STANDALONE_TEST_RUN.md +149 -0
  107. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/01-simple-bugfix.md +32 -0
  108. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/02-ui-build-with-iteration.md +48 -0
  109. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/03-multi-failure-escalation.md +60 -0
  110. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/04-ui-build-ibr-absent.md +51 -0
  111. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/05-refactor-navgator-absent.md +71 -0
  112. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/scenarios/06-recurring-bug-debugger-absent.md +52 -0
  113. package/plugin-artifacts/codex/skills/build-loop/references/refactor-history/trace-comparison.md +202 -0
  114. package/plugin-artifacts/codex/skills/build-loop/references/self-recursive-dev.md +77 -0
  115. package/plugin-artifacts/codex/skills/build-loop/references/self-review.md +234 -0
  116. package/plugin-artifacts/codex/skills/build-loop/references/ui-io-contract.md +116 -0
  117. package/plugin-artifacts/codex/skills/build-loop/scanners/audit-design-rules.mjs +476 -0
  118. package/plugin-artifacts/codex/skills/build-loop/scanners/require-visual-evidence.mjs +239 -0
  119. package/plugin-artifacts/codex/skills/build-loop/templates/backlog-item.md +35 -0
  120. package/plugin-artifacts/codex/skills/build-loop/templates/codex-worker-prompt.md +100 -0
  121. package/plugin-artifacts/codex/skills/build-loop/templates/ui-subagent-prompt.md +179 -0
  122. package/plugin-artifacts/codex/skills/build-loop/templates/ux-fix-plan.md +40 -0
  123. package/scripts/_paths.py +59 -13
  124. package/scripts/build_codex_plugin_artifact.py +314 -0
  125. package/scripts/check_cache_sync.py +1 -1
  126. package/scripts/install_memory.py +11 -3
  127. package/scripts/prune_plugin_cache.py +225 -11
  128. package/scripts/sync_navgator_lessons.py +25 -0
  129. package/scripts/sync_plugin_cache.py +66 -36
  130. package/skills/agent-rally-point/SKILL.md +1 -1
  131. package/skills/agent-rally-watcher/SKILL.md +1 -1
  132. package/skills/build-loop/SKILL.md +11 -155
  133. package/skills/build-loop/references/advisor-dispatch-ladder.md +62 -0
  134. package/skills/build-loop/references/autonomous-and-per-commit-modes.md +161 -0
  135. package/skills/build-loop/references/capability-routing.md +4 -3
  136. package/skills/build-loop/references/codex-subagents.md +8 -0
  137. package/skills/build-loop/references/coordination.md +1 -1
  138. package/skills/build-loop/references/intent-capability-pack.md +88 -1
  139. package/skills/build-loop/references/memory.md +17 -2
  140. package/skills/build-loop/references/phase-1-assess.md +13 -0
  141. package/skills/build-loop/references/phase-2-plan.md +2 -1
  142. package/skills/build-loop/references/phase-3-execute.md +4 -2
  143. package/skills/build-loop/references/phase-4-review.md +12 -0
  144. package/skills/build-loop/references/phase-6-learn.md +1 -1
  145. package/skills/build-loop/references/self-review.md +4 -2
  146. package/skills/build-loop/templates/codex-worker-prompt.md +45 -34
  147. package/skills/handoff/SKILL.md +3 -3
  148. package/skills/loop-builder/SKILL.md +98 -0
  149. package/skills/loop-builder/presets/active-project-evidence.yaml +97 -0
  150. package/skills/loop-builder/presets/generic-artifact-loop.yaml +95 -0
  151. package/skills/loop-builder/presets/presentation-audit.yaml +96 -0
  152. package/skills/loop-builder/presets/research-synthesis.yaml +96 -0
  153. package/skills/loop-builder/presets/source-ingestion-raw-data-audit.yaml +96 -0
  154. package/skills/loop-builder/references/spec-format.md +80 -0
  155. package/skills/loop-builder/scripts/loop_builder.py +346 -0
  156. package/skills/model-tiering/SKILL.md +65 -40
  157. package/skills/optimize/SKILL.md +2 -2
  158. package/skills/plan-verify/SKILL.md +1 -1
  159. package/skills/plugin-builder/references/distribution.md +8 -0
  160. package/skills/research/SKILL.md +33 -6
  161. package/skills/runtime-parity-verification/SKILL.md +51 -0
  162. package/skills/spec-writing/SKILL.md +19 -0
  163. package/templates/memory/README.md +65 -0
  164. package/templates/memory/charter.md.template +46 -0
  165. package/templates/memory/manifest.json +24 -4
  166. package/codex-skills/debug-loop/SKILL.md +0 -18
  167. package/codex-skills/handoff/SKILL.md +0 -22
  168. package/codex-skills/knowledge/SKILL.md +0 -21
  169. package/codex-skills/optimize/SKILL.md +0 -18
  170. package/codex-skills/research/SKILL.md +0 -18
  171. /package/commands/{knowledge-review.md → review-knowledge.md} +0 -0
@@ -0,0 +1,346 @@
1
+ #!/usr/bin/env python3
2
+ # SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ """Generate focused-loop packs from preset specs.
5
+
6
+ Preset files use YAML-compatible JSON so this tool stays stdlib-only while the
7
+ generated loop spec remains readable YAML.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import copy
13
+ import json
14
+ import re
15
+ import shutil
16
+ import sys
17
+ from pathlib import Path
18
+ from typing import Any
19
+
20
+ HERE = Path(__file__).resolve().parent
21
+ SKILL_ROOT = HERE.parent
22
+ PRESETS_DIR = SKILL_ROOT / "presets"
23
+
24
+ IDENTIFIER_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
25
+
26
+
27
+ class LoopBuilderError(RuntimeError):
28
+ pass
29
+
30
+
31
+ def slugify(value: str) -> str:
32
+ slug = re.sub(r"[^a-z0-9]+", "-", value.lower()).strip("-")
33
+ slug = re.sub(r"-+", "-", slug)
34
+ if not slug:
35
+ raise LoopBuilderError("loop id cannot be empty")
36
+ return slug
37
+
38
+
39
+ def require_identifier(value: str, *, field: str) -> str:
40
+ slug = slugify(value)
41
+ if not IDENTIFIER_RE.match(slug):
42
+ raise LoopBuilderError(f"{field} must be kebab-case: {value!r}")
43
+ return slug
44
+
45
+
46
+ def preset_paths() -> list[Path]:
47
+ return sorted(PRESETS_DIR.glob("*.yaml"))
48
+
49
+
50
+ def available_presets() -> list[str]:
51
+ return [path.stem for path in preset_paths()]
52
+
53
+
54
+ def load_preset(name: str) -> dict[str, Any]:
55
+ preset_id = require_identifier(name, field="preset")
56
+ path = PRESETS_DIR / f"{preset_id}.yaml"
57
+ if not path.is_file():
58
+ choices = ", ".join(available_presets()) or "(none)"
59
+ raise LoopBuilderError(f"unknown preset {preset_id!r}; available: {choices}")
60
+ try:
61
+ data = json.loads(path.read_text(encoding="utf-8"))
62
+ except json.JSONDecodeError as exc:
63
+ raise LoopBuilderError(f"invalid preset JSON in {path}: {exc}") from exc
64
+ validate_preset(data, source=path)
65
+ return data
66
+
67
+
68
+ def validate_preset(data: dict[str, Any], *, source: Path | None = None) -> None:
69
+ required = ("id", "title", "summary", "inputs", "outputs", "phases", "validators", "gates", "skill_chain", "learn")
70
+ missing = [key for key in required if key not in data]
71
+ if missing:
72
+ label = str(source) if source else data.get("id", "<preset>")
73
+ raise LoopBuilderError(f"{label} missing required fields: {', '.join(missing)}")
74
+ require_identifier(str(data["id"]), field="preset id")
75
+ if not isinstance(data["phases"], dict) or not data["phases"]:
76
+ raise LoopBuilderError(f"{data['id']} phases must be a non-empty object")
77
+ if not isinstance(data["validators"], list) or not data["validators"]:
78
+ raise LoopBuilderError(f"{data['id']} validators must be a non-empty list")
79
+ if not isinstance(data["skill_chain"], dict):
80
+ raise LoopBuilderError(f"{data['id']} skill_chain must be an object")
81
+
82
+
83
+ def scalar_to_yaml(value: Any) -> str:
84
+ if value is True:
85
+ return "true"
86
+ if value is False:
87
+ return "false"
88
+ if value is None:
89
+ return "null"
90
+ if isinstance(value, (int, float)):
91
+ return str(value)
92
+ return json.dumps(str(value), ensure_ascii=False)
93
+
94
+
95
+ def to_yaml(value: Any, indent: int = 0) -> str:
96
+ pad = " " * indent
97
+ if isinstance(value, dict):
98
+ if not value:
99
+ return pad + "{}"
100
+ lines: list[str] = []
101
+ for key, item in value.items():
102
+ if isinstance(item, (dict, list)):
103
+ if not item:
104
+ lines.append(f"{pad}{key}: {to_yaml(item, 0).strip()}")
105
+ else:
106
+ lines.append(f"{pad}{key}:")
107
+ lines.append(to_yaml(item, indent + 2))
108
+ else:
109
+ lines.append(f"{pad}{key}: {scalar_to_yaml(item)}")
110
+ return "\n".join(lines)
111
+ if isinstance(value, list):
112
+ if not value:
113
+ return pad + "[]"
114
+ lines = []
115
+ for item in value:
116
+ if isinstance(item, (dict, list)):
117
+ lines.append(f"{pad}-")
118
+ lines.append(to_yaml(item, indent + 2))
119
+ else:
120
+ lines.append(f"{pad}- {scalar_to_yaml(item)}")
121
+ return "\n".join(lines)
122
+ return pad + scalar_to_yaml(value)
123
+
124
+
125
+ def build_loop_spec(preset: dict[str, Any], *, loop_id: str, title: str | None, preset_name: str) -> dict[str, Any]:
126
+ spec = copy.deepcopy(preset)
127
+ spec["schema_version"] = 1
128
+ spec["id"] = loop_id
129
+ spec["source_preset"] = preset_name
130
+ if title:
131
+ spec["title"] = title
132
+ return spec
133
+
134
+
135
+ def render_loop_yaml(spec: dict[str, Any]) -> str:
136
+ header = [
137
+ "# Generated focused-loop spec.",
138
+ "# Edit the artifact contract, validators, and skill_chain before using on high-stakes work.",
139
+ "",
140
+ ]
141
+ return "\n".join(header) + to_yaml(spec) + "\n"
142
+
143
+
144
+ def render_rubric(spec: dict[str, Any]) -> str:
145
+ lines = [
146
+ f"# {spec['title']} Rubric",
147
+ "",
148
+ spec["summary"],
149
+ "",
150
+ "## Binary Validators",
151
+ "",
152
+ "| Validator | Pass Condition | Method |",
153
+ "|---|---|---|",
154
+ ]
155
+ for validator in spec["validators"]:
156
+ lines.append(
157
+ f"| `{validator['id']}` | {validator['pass_condition']} | {validator.get('method', 'review')} |"
158
+ )
159
+ lines.extend(
160
+ [
161
+ "",
162
+ "## Confirmation Gates",
163
+ "",
164
+ ]
165
+ )
166
+ for gate_name, gate_items in spec.get("gates", {}).items():
167
+ lines.append(f"### {gate_name}")
168
+ lines.append("")
169
+ for item in gate_items:
170
+ lines.append(f"- `{item}`")
171
+ lines.append("")
172
+ return "\n".join(lines).rstrip() + "\n"
173
+
174
+
175
+ def render_report_template(spec: dict[str, Any]) -> str:
176
+ validator_rows = "\n".join(f"| `{item['id']}` | pass/fail | evidence |" for item in spec["validators"])
177
+ outputs = "\n".join(f"- {item}" for item in spec["outputs"])
178
+ return f"""# {spec['title']} Report
179
+
180
+ ## Bottom Line
181
+
182
+ [One sentence: what changed, what decision/artifact is ready, and what remains open.]
183
+
184
+ ## Outputs
185
+
186
+ {outputs}
187
+
188
+ ## Evidence
189
+
190
+ - [source path / transcript timestamp / row or slide reference]
191
+
192
+ ## Validator Results
193
+
194
+ | Validator | Verdict | Evidence |
195
+ |---|---|---|
196
+ {validator_rows}
197
+
198
+ ## Gates
199
+
200
+ - External send/publish: [clear/confirm]
201
+ - Sensitive data exposure: [clear/confirm]
202
+ - Irreversible source-of-truth change: [clear/confirm]
203
+
204
+ ## Learn
205
+
206
+ - Reusable artifact:
207
+ - Source quirks:
208
+ - Rubric failures:
209
+ """
210
+
211
+
212
+ def render_validator(spec: dict[str, Any]) -> str:
213
+ required_tokens = ["schema_version", "id", "phases", "validators", "gates", "skill_chain", "learn"]
214
+ token_literal = repr(required_tokens)
215
+ return f'''#!/usr/bin/env python3
216
+ # SPDX-FileCopyrightText: 2025-2026 Tyrone Ross, Jr <46267523+tyroneross@users.noreply.github.com>
217
+ # SPDX-License-Identifier: Apache-2.0
218
+ """Basic generated validator for the {spec["id"]} loop pack."""
219
+ from __future__ import annotations
220
+
221
+ import sys
222
+ from pathlib import Path
223
+
224
+
225
+ ROOT = Path(__file__).resolve().parents[1]
226
+ REQUIRED_FILES = [
227
+ ROOT / "loop.yaml",
228
+ ROOT / "rubric.md",
229
+ ROOT / "templates" / "report.md",
230
+ ]
231
+ REQUIRED_TOKENS = {token_literal}
232
+
233
+
234
+ def main() -> int:
235
+ missing = [str(path.relative_to(ROOT)) for path in REQUIRED_FILES if not path.is_file()]
236
+ if missing:
237
+ print("missing required files: " + ", ".join(missing), file=sys.stderr)
238
+ return 1
239
+ text = (ROOT / "loop.yaml").read_text(encoding="utf-8")
240
+ absent = [token for token in REQUIRED_TOKENS if token + ":" not in text]
241
+ if absent:
242
+ print("loop.yaml missing required fields: " + ", ".join(absent), file=sys.stderr)
243
+ return 1
244
+ print("loop pack ok: " + str(ROOT))
245
+ return 0
246
+
247
+
248
+ if __name__ == "__main__":
249
+ raise SystemExit(main())
250
+ '''
251
+
252
+
253
+ def write_file(path: Path, content: str, *, executable: bool = False) -> None:
254
+ path.parent.mkdir(parents=True, exist_ok=True)
255
+ path.write_text(content, encoding="utf-8")
256
+ if executable:
257
+ path.chmod(0o755)
258
+
259
+
260
+ def create_loop(
261
+ *,
262
+ loop_id_raw: str,
263
+ preset_name: str,
264
+ output: Path | None,
265
+ title: str | None,
266
+ force: bool,
267
+ ) -> Path:
268
+ loop_id = require_identifier(loop_id_raw, field="loop id")
269
+ preset_id = require_identifier(preset_name, field="preset")
270
+ preset = load_preset(preset_id)
271
+ spec = build_loop_spec(preset, loop_id=loop_id, title=title, preset_name=preset_id)
272
+ target = output.expanduser().resolve() if output else (Path.cwd() / ".build-loop" / "loops" / loop_id).resolve()
273
+ if target.exists():
274
+ if not force:
275
+ raise LoopBuilderError(f"target already exists: {target}; pass --force to replace")
276
+ shutil.rmtree(target)
277
+ write_file(target / "loop.yaml", render_loop_yaml(spec))
278
+ write_file(target / "rubric.md", render_rubric(spec))
279
+ write_file(target / "templates" / "report.md", render_report_template(spec))
280
+ write_file(target / "validators" / "validate_loop.py", render_validator(spec), executable=True)
281
+ write_file(
282
+ target / "README.md",
283
+ f"# {spec['title']}\n\nGenerated from `{preset_id}`. Start with `loop.yaml`, then run `python3 validators/validate_loop.py`.\n",
284
+ )
285
+ return target
286
+
287
+
288
+ def cmd_list(_args: argparse.Namespace) -> int:
289
+ for name in available_presets():
290
+ preset = load_preset(name)
291
+ print(f"{name}\t{preset['title']}")
292
+ return 0
293
+
294
+
295
+ def cmd_inspect(args: argparse.Namespace) -> int:
296
+ preset = load_preset(args.preset)
297
+ print(render_loop_yaml(build_loop_spec(preset, loop_id=preset["id"], title=None, preset_name=preset["id"])))
298
+ return 0
299
+
300
+
301
+ def cmd_create(args: argparse.Namespace) -> int:
302
+ target = create_loop(
303
+ loop_id_raw=args.loop_id,
304
+ preset_name=args.preset,
305
+ output=Path(args.output) if args.output else None,
306
+ title=args.title,
307
+ force=args.force,
308
+ )
309
+ print(f"created loop pack: {target}")
310
+ return 0
311
+
312
+
313
+ def build_parser() -> argparse.ArgumentParser:
314
+ parser = argparse.ArgumentParser(description=__doc__)
315
+ sub = parser.add_subparsers(dest="command", required=True)
316
+
317
+ list_parser = sub.add_parser("list", help="List available loop presets.")
318
+ list_parser.set_defaults(func=cmd_list)
319
+
320
+ inspect_parser = sub.add_parser("inspect", help="Print a preset as generated loop YAML.")
321
+ inspect_parser.add_argument("preset")
322
+ inspect_parser.set_defaults(func=cmd_inspect)
323
+
324
+ create_parser = sub.add_parser("create", help="Create a focused-loop pack.")
325
+ create_parser.add_argument("loop_id")
326
+ create_parser.add_argument("--preset", required=True, help="Preset name from `list`.")
327
+ create_parser.add_argument("--output", help="Target directory. Defaults to .build-loop/loops/<loop-id>.")
328
+ create_parser.add_argument("--title", help="Override generated title.")
329
+ create_parser.add_argument("--force", action="store_true", help="Replace an existing target directory.")
330
+ create_parser.set_defaults(func=cmd_create)
331
+
332
+ return parser
333
+
334
+
335
+ def main(argv: list[str] | None = None) -> int:
336
+ parser = build_parser()
337
+ args = parser.parse_args(argv)
338
+ try:
339
+ return int(args.func(args))
340
+ except LoopBuilderError as exc:
341
+ print(f"error: {exc}", file=sys.stderr)
342
+ return 1
343
+
344
+
345
+ if __name__ == "__main__":
346
+ raise SystemExit(main())
@@ -17,18 +17,21 @@ skill answers "which tier should run the role?", not "who owns the work?".
17
17
 
18
18
  | Tier | Anthropic default | Role | Equivalents (advisory — verify benchmarks before swapping) |
19
19
  |---|---|---|---|
20
- | **Thinking** | Opus 4.7 | Synthesis, planning, ambiguity resolution, severity ranking, audit/learnings, cross-file judgment | GPT-5 Thinking, Gemini 2.5 Pro, future Claude tier; any model >= Opus 4.6 on SWE-bench Verified + Frontier-class on ARC-AGI / MMLU-Pro |
21
- | **Code** | Sonnet 4.6 | Applicationapply rule to bounded input, scoped implementation, adversarial critic, mechanical refactor | Sonnet 4.7+, GPT-5 Codex, qwen2.5-coder-32B (local); any model with SWE-bench Verified within ~5pt of Sonnet 4.6 (currently ~79.6%) |
20
+ | **Frontier** | Fable 5 | **Phase 2 Plan synthesis (frame goal, draft spec/ADRs, F-criteria, MECE partition) via the Advisor dispatch ladder when stakes-gated** — `advisor` agent / peer host / already-Fable session; honestly-labeled inline-Opus fallback otherwise (`references/advisor-dispatch-ladder.md`). (Advisor v1 = Phase 2 only; Phase 1 Assess synthesis runs inline as today until v2.) AND verification judgment (plan-critic, scope-auditor, independent-auditor, fix-critique, fact-checker, security-reviewer, overfitting-reviewer, promotion-reviewer) | GPT-5.5 Thinking (or whichever tier scores above the prior Thinking-tier ceiling), future Claude tier above Opus; any model that benchmarks above the Thinking-tier contract on SWE-bench Verified AND ARC-AGI / GPQA Diamond |
21
+ | **Thinking** | Opus 4.8 | Coordinationbuild-orchestrator, assessment-orchestrator and the escalation target for execution (ambiguous spec, 2 consecutive failures, cross-file surprise) and audit/learnings synthesis when Frontier is unavailable | GPT-5 Thinking, Gemini 2.5 Pro; any model >= Opus 4.6 on SWE-bench Verified + Frontier-class on ARC-AGI / MMLU-Pro |
22
+ | **Code** | Sonnet 4.6 | Application — apply rule to bounded input, scoped implementation, mechanical refactor, bounded domain assessment | Sonnet 4.7+, GPT-5 Codex, qwen2.5-coder-32B (local); any model with SWE-bench Verified within ~5pt of Sonnet 4.6 (currently ~79.6%) |
22
23
  | **Pattern** | Haiku 4.5 | Recognition — regex/syntactic match, classification into known buckets, log scan, deterministic checklist | Haiku 4.6, GPT-5 Mini, llama3.2-3b (local); any small/fast model that handles structured pattern matching |
23
24
 
24
- **Rule of substitution:** tier A's swap target must score within tolerance of the default on the benchmark relevant to its role. For Code tier that's SWE-bench Verified ≥75% AND tool-use accuracy ≥85%; for Thinking tier that's SWE-bench ≥78% AND ARC-AGI / GPQA Diamond competitive; for Pattern tier no benchmark — just "fast and cheap, doesn't hallucinate on bounded structured tasks."
25
+ **Rule of substitution:** tier A's swap target must score within tolerance of the default on the benchmark relevant to its role. For Code tier that's SWE-bench Verified ≥75% AND tool-use accuracy ≥85%; for Thinking tier that's SWE-bench ≥78% AND ARC-AGI / GPQA Diamond competitive; for Frontier tier that's clearing the Thinking-tier contract AND scoring above the prior-generation Thinking-tier ceiling on at least one of SWE-bench Verified / ARC-AGI / GPQA Diamond; for Pattern tier no benchmark — just "fast and cheap, doesn't hallucinate on bounded structured tasks."
26
+
27
+ **Why Frontier sits above Thinking for plan + verification (and not for execution):** wrong plans and wrong verdicts compound — a bad plan dispatches N implementers into the wrong work, and a bad verdict ships a regression. The user's standing priority is Accuracy > Speed > Cost (`feedback_accuracy_speed_cost_priority.md`), so the planning and verification surfaces — where one miscall poisons everything downstream — pay the Frontier premium. Execution and coordination stay on Sonnet/Opus because they're either bounded application (Sonnet implementer applies a settled plan) or routing (Opus orchestrator chooses which subagent runs next, with deterministic gates as the safety net).
25
28
 
26
29
  ## Provider-swap recipe
27
30
 
28
- Build-loop's agent frontmatter uses Anthropic model aliases (`opus`, `sonnet`, `haiku`) because Claude Code is the primary host. To run on a different provider:
31
+ Build-loop's agent frontmatter uses Anthropic model aliases (`fable`, `opus`, `sonnet`, `haiku`) because Claude Code is the primary host. To run on a different provider:
29
32
 
30
- 1. **One-time edit per agent:** open each `agents/*.md` and change the `model:` field to your provider's equivalent. The tier (Thinking/Code/Pattern) determines the substitution target.
31
- 2. **Runtime override:** `.build-loop/config.json.modelOverrides` accepts `{ thinking: "<id>", code: "<id>", pattern: "<id>" }`. The orchestrator resolves this through `scripts/model_overrides.py` before dispatching subagents (see `references/model-tier-mapping.md` for full schema).
33
+ 1. **One-time edit per agent:** open each `agents/*.md` and change the `model:` field to your provider's equivalent. The tier (Frontier/Thinking/Code/Pattern) determines the substitution target.
34
+ 2. **Runtime override:** `.build-loop/config.json.modelOverrides` accepts `{ frontier: "<id>", thinking: "<id>", code: "<id>", pattern: "<id>" }`. The orchestrator resolves this through `scripts/model_overrides.py` before dispatching subagents (see `references/model-tier-mapping.md` for full schema). Configs without `frontier` resolve frontier → `fable` by default.
32
35
  3. **Per-dispatch override:** any orchestrator dispatch may pass `model: <id>` in the subagent prompt to force that call.
33
36
 
34
37
  The role-and-task table below uses tier names. The Anthropic-default mapping in the right column is illustrative; substitute your equivalents at swap time.
@@ -41,7 +44,7 @@ The role-and-task table below uses tier names. The Anthropic-default mapping in
41
44
  - Deciding whether to escalate mid-flow after failures
42
45
  - Evaluating whether to swap providers (use the Tier abstraction table above as the contract)
43
46
 
44
- ## Evidence base (2026 Q1)
47
+ ## Evidence base (2026 Q1–Q2)
45
48
 
46
49
  | Claim | Source | Certainty |
47
50
  |-------|--------|-----------|
@@ -49,43 +52,57 @@ The role-and-task table below uses tier names. The Anthropic-default mapping in
49
52
  | Opus 4.6: 80.8% SWE-bench Verified (1.2pt gap — smallest in Claude history) | Same | ⚠️ T2, single-source |
50
53
  | Sonnet 4.6 uses 70% fewer tokens than 4.5 on complex file ops with +38% accuracy | Anthropic Sonnet 4.6 announcement | ⚠️ T2, single-source |
51
54
  | Pricing: Sonnet $3/$15 per MTok input/output | Anthropic pricing page | ⚠️ verify before billing |
52
- | Pricing: Opus $15/$75 per MTok input/output (5x gap) | Anthropic pricing page | ⚠️ verify before billing |
55
+ | Pricing: Opus 4.8 $5/$25 per MTok input/output | Anthropic pricing page | ⚠️ verify before billing |
56
+ | Pricing: Fable 5 $10/$50 per MTok input/output (1M context, capability tier above Opus 4.8) | claude-api skill cache 2026-05-26 (T1 — Anthropic) | ✅ T1 source, advisory until re-confirmed at next billing audit |
53
57
 
54
58
  ## MECE primitive: cognitive type of the task
55
59
 
56
- Before consulting the role table, classify the task by reasoning shape. The MECE cut is the kind of thinking the task requires; lifecycle stage (plan/execute/review) is a second-order cut that often mixes types.
60
+ Before consulting the role table, classify the task by reasoning shape. The MECE cut is the kind of thinking the task requires; lifecycle stage (plan/execute/review) is a second-order cut that often mixes types. Within Synthesis, a second-order cut decides whether the task is a planning/verification decision (Frontier) or coordination/escalation/learnings (Thinking).
57
61
 
58
62
  | Reasoning shape | Model | What it means | Example tasks |
59
63
  |---|---|---|---|
60
- | **Synthesis** — combine N inputs into a novel decision; cross-file/cross-system reasoning; ambiguity resolution; severity ranking | **Opus** | The "what" and "why" calls. No single rule produces the answer. | Frame goal, draft spec/ADRs, trace call-paths across files, rank finding severity, escalate stuck iteration with causal-tree, write audit/learnings |
61
- | **Application** — apply a known rule, spec, or pattern to bounded input; produce an artifact that matches a contract | **Sonnet** | The "how" call when "what" is decided. Single-correct-answer derivable from a rule. | Implement a commit's owned files per spec, write tests for given F-criteria, adversarial critic vs rubric, mechanical simplify, fact-check with named source |
62
- | **Recognition** — pure regex/syntactic match; classify into known buckets; no judgment | **Haiku** | No gradient matches or doesn't. | Mock-data scan, log pattern detection, file inventory, cross-run pattern detection, deterministic checklist verification |
64
+ | **Planning + Verification synthesis** — frame the goal, draft the spec/ADRs, define F-criteria, MECE-partition the work, then later judge whether a plan, a commit, a fix, a claim, or a security/scope boundary actually holds | **Fable (Frontier)** | The "what to do" and "did it actually work" calls. Wrong calls poison every downstream dispatch. | Phase 2 Plan drafting (reaches Fable via the stakes-gated Advisor ladder; Phase 1 Assess synthesis stays inline until v2), plan-critic, scope-auditor, independent-auditor, fix-critique, fact-checker, security-reviewer, overfitting-reviewer, promotion-reviewer |
65
+ | **Coordination + escalation synthesis** — route work between subagents, ladder severity, run causal-tree on stuck iterations, write audit/learnings | **Opus (Thinking)** | The "who runs next" + "why did the rule run out" calls. Deterministic gates backstop the routing. | build-orchestrator, assessment-orchestrator, severity ranking after critic findings, causal-tree after 2 consecutive failures, Phase 6 Learn audit synthesis (when no Frontier escalation needed) |
66
+ | **Application** — apply a known rule, spec, or pattern to bounded input; produce an artifact that matches a contract | **Sonnet (Code)** | The "how" call when "what" is decided. Single-correct-answer derivable from a rule. | Implement a commit's owned files per spec, write tests for given F-criteria, mechanical simplify, bounded domain assessment (api/db/frontend/perf), design-contract reconciliation, ui-validator, retrospective-synthesizer, self-improvement-architect drafting |
67
+ | **Recognition** — pure regex/syntactic match; classify into known buckets; no judgment | **Haiku (Pattern)** | No gradient — matches or doesn't. | Mock-data scan, log pattern detection, file inventory, cross-run pattern detection, deterministic checklist verification |
63
68
 
64
- **Decision tree:** "Does this task have a single-correct answer derivable from a rule applied to bounded input?" → Yes = Application/Sonnet. Else "Is the answer pure pattern-match?" → Yes = Recognition/Haiku. Else = Synthesis/Opus.
69
+ **Decision tree:** "Does this task have a single-correct answer derivable from a rule applied to bounded input?" → Yes = Application/Sonnet. Else "Is the answer pure pattern-match?" → Yes = Recognition/Haiku. Else, Synthesis. Then ask: "Is this a planning decision (what to build) or a verification verdict (did it hold)?" → Yes = Frontier/Fable. Else (routing, escalation, audit-synthesis when no verdict is being rendered) = Thinking/Opus.
65
70
 
66
71
  ## Default assignments
67
72
 
68
73
  | Task | Reasoning shape | Model | effort | Why |
69
74
  |------|------|-------|--------|-----|
70
- | Frame & plan: goal, ADRs, scope, F-criteria, MECE partition | Synthesis | Opus | medium | Ambiguity resolution; wrong plan compounds |
75
+ | Frame & plan: goal, ADRs, scope, F-criteria, MECE partition | Planning synthesis | Fable | medium | A wrong plan dispatches N implementers into the wrong work; user's standing priority Accuracy > Speed > Cost |
71
76
  | Plan-verify deterministic checklist | Recognition | (script) | — | No model; runs `plan_verify.py` |
72
- | Plan-critic adversarial review against rubric+checklist | Application | Sonnet | high | Boundedrubric is the rule. Separation drives quality |
73
- | **Scope auditor (NEW — Plan→Execute boundary)**: trace callers of every modified-API symbol; annotate `caller_audit:` per commit | Synthesis | Opus | medium | Cross-file call-path tracing that fanned-out implementers can't do (round-2 lesson) |
74
- | Code execution — bounded chunk, spec clear | Application | Sonnet | medium | Default. High accuracy, cheaper |
75
- | Code execution — ambiguous spec | Synthesis | Opus | medium | Interpretation cost cheaper than rework |
76
- | Adversarial critic pass (read-only diff vs rubric) | Application | Sonnet | high | Bounded rubric vs diff is rule-application; separation effect |
77
- | Code review — severity ranking + recommendation order (given findings) | Synthesis | Opus | medium | Cross-finding judgment about what matters most |
77
+ | Plan-critic adversarial review against rubric+checklist | Verification synthesis | Fable | high | Verification verdict separation drives quality; verdict gates Phase 3 dispatch |
78
+ | Scope auditor (Plan→Execute boundary): trace callers of every modified-API symbol; annotate `caller_audit:` per commit | Verification synthesis | Fable | medium | Cross-file call-path tracing AND a gating verdict on whether a commit is `internal_only`; verification compound risk |
79
+ | Code execution — bounded chunk, spec clear | Application | Sonnet | medium | Default workhorse. Spec is settled; apply the rule |
80
+ | Code execution — ambiguous spec or cross-file surprise mid-execution | Coordination synthesis | Opus | medium | Escalation target; interpretation cost cheaper than rework |
81
+ | Independent-auditor adversarial pass (read-only diff vs rubric at chunk + build scope) | Verification synthesis | Fable | high | Verdict gates the build's outcome line; a missed regression in production-impacting work is the most expensive miss in the loop |
82
+ | Severity ranking + recommendation order (given findings) | Coordination synthesis | Opus | medium | Cross-finding routing; no per-finding verdict being rendered, the verdicts are upstream |
78
83
  | Mock data scanning | Recognition | Haiku | low | Regex only |
79
- | Fact-checking — trace metric → source, judge accuracy | Synthesis | Opus | medium | Cross-system; "is this number real?" requires cross-context judgment |
80
- | Fact-checkingtrace metric named-source pattern (rule-bound) | Application | Sonnet | medium | When the source-pattern rule is explicit |
84
+ | Fact-checking — trace metric → source, judge accuracy | Verification synthesis | Fable | medium | Final read on "is this number real" before report ships; user-trust verdict |
85
+ | Fix-critiquepressure-test a proposed fix before "resolved" | Verification synthesis | Fable | medium | Verdict on whether the fix addresses root cause vs symptom; wrong verdict reopens the bug downstream |
86
+ | Security-reviewer — adversarial OWASP/ATLAS pass | Verification synthesis | Fable | high | Verdict gates riskSurfaceChange dispatch; missed exposure is the most expensive verification miss |
87
+ | Overfitting-reviewer — Goodhart / test-gaming verdict on optimize runs | Verification synthesis | Fable | medium | Verdict on whether optimization is genuine; cheap to wrong-call into a regression |
88
+ | Promotion-reviewer — Phase 6 Learn experimental promotion verdict | Verification synthesis | Fable | medium | Gates the move from `experimental/` to `active/`; durable surface |
81
89
  | Simplify — apply known simplifications | Application | Sonnet | medium | Inline single-use helper, delete dead branch — bounded |
82
90
  | Debugging — symptom-to-known-pattern match | Application | Sonnet | high | Memory-first gate's "Application until the rule runs out" |
83
- | Debugging — causal-tree after 2 consecutive failures | Synthesis | Opus | high | Synthesis takes over when rule-match exhausts |
84
- | Novel architecture decision | Synthesis | Opus | medium | Cross-file impact; wrong call is expensive |
85
- | Writing user-facing prose (copy, microcopy, errors) | Synthesis | Opus | medium | Tone, restraint, and nuance matter |
86
- | Audit / learnings / Phase 6 promotion-decision | Synthesis | Opus | medium | Cross-run synthesis |
91
+ | Debugging — causal-tree after 2 consecutive failures | Coordination synthesis | Opus | high | Synthesis takes over routing when rule-match exhausts |
92
+ | Novel architecture decision | Planning synthesis | Fable | medium | Cross-file impact; wrong call compounds |
93
+ | Writing user-facing prose (copy, microcopy, errors) | Coordination synthesis | Opus | medium | Tone, restraint, and nuance matter; no verification verdict being rendered |
94
+ | Audit / learnings / Phase 6 audit synthesis | Coordination synthesis | Opus | medium | Cross-run routing; promotion-reviewer carries the gating verdict separately |
87
95
  | Recurring-pattern detection across runs[] | Recognition | Haiku | low | Pattern-match across structured logs |
88
96
 
97
+ ### Deliberate exceptions (Sonnet retained for cost where the surface is high-frequency advisory)
98
+
99
+ Two verification-shaped agents stay on Sonnet rather than escalating to Fable. The tension with round-2 evidence ("rubric-application = Sonnet is robust") is real; the user chose Fable for the rest of the verification surface anyway because the compound risk of a wrong verification verdict outweighs the per-call premium. Pins are defaults, not locks — these can be overridden per dispatch or re-tiered after telemetry.
100
+
101
+ | Agent | Pin | Why retained on Sonnet |
102
+ |---|---|---|
103
+ | `alignment-checker` | Sonnet | Called once per queue item during autonomous iterate (up to 25× per run). Advisory only — flags drift, doesn't gate. Cost dominates value at this fan-out frequency. |
104
+ | `synthesis-critic` | Sonnet | Per-UI-commit WARN-only check. Advisory only — never gates. Frequency × non-gating shape means a cheaper tier is the right tradeoff. |
105
+
89
106
  ## Round 2 evidence (2026-05-07, example-app news-podcast iteration 2)
90
107
 
91
108
  n=2 dispatch-pattern A/B comparison on a 6-commit feature reversed the round-1 belief that Skill-path (Sonnet fan-out) is materially cheaper across the board:
@@ -105,16 +122,20 @@ Findings that updated the model tiering:
105
122
  3. **Inline-Opus is faster wall-clock** when there's no real parallelism to exploit. Fan-out parallelism is only a win when ≥3 chunks are truly independent.
106
123
  4. **Plan-critic on Sonnet caught 17 substantive findings** on a written spec — confirms "rubric-application = Sonnet" is robust.
107
124
 
108
- These findings inform the role assignments, especially the rubric-application=Sonnet vs severity-assessment=Opus split for code review.
125
+ These findings informed the earlier rubric-application=Sonnet split for code review. The current org overrides that for the verification surface specifically — the user chose Fable for verification because a missed verdict at this stage compounds, even though round-2 showed Sonnet rubric-application was substantively robust on a 17-finding plan-critic pass. The exceptions table above (alignment-checker, synthesis-critic) preserves the Sonnet split where the surface is high-frequency advisory and non-gating.
109
126
 
110
- ## Escalation triggers (stay on Sonnet UNLESS)
127
+ ## Escalation triggers (Sonnet execution Opus, NOT to Fable)
111
128
 
112
- - 2 consecutive failures on the same chunk after a retry at effort=high
113
- - Spec is ambiguous and interpretation will materially change implementation
114
- - A cross-file architectural decision surfaces mid-execution that wasn't in the plan
115
- - Critic flags a "strong-checkpoint" finding that requires judgment, not just a fix
116
- - Novel error pattern not found in `.build-loop/issues/` or debugging memory
117
- - Task produces user-visible prose where tone and restraint are load-bearing
129
+ Execution escalates to **Opus**, not Fable. Fable is reserved for planning and verification; execution under genuine ambiguity is a coordination call (interpret the spec, route to a new chunk, decide whether to re-plan) that the orchestrator owns.
130
+
131
+ - 2 consecutive failures on the same chunk after a retry at effort=high → respawn implementer at Opus
132
+ - Spec is ambiguous and interpretation will materially change implementation Opus
133
+ - A cross-file architectural decision surfaces mid-execution that wasn't in the plan Opus, then route back to Plan if the decision changes the MECE partition
134
+ - Critic flags a "strong-checkpoint" finding that requires judgment, not just a fix → Opus
135
+ - Novel error pattern not found in `.build-loop/issues/` or debugging memory → Opus
136
+ - Task produces user-visible prose where tone and restraint are load-bearing → Opus
137
+
138
+ If the ambiguity surfaces a **planning** problem (the original plan no longer fits) rather than an execution problem, route back to Phase 2 Plan — Fable re-plans, then execution resumes on Sonnet/Opus.
118
139
 
119
140
  ## Techniques that work
120
141
 
@@ -149,19 +170,21 @@ These findings inform the role assignments, especially the rubric-application=So
149
170
 
150
171
  ## How the build-loop uses this
151
172
 
152
- Orchestrator (Opus 4.7) spawns implementer subagent (Sonnet, effort=medium) → external verification gate (tests/lint/types) → Sonnet critic agent (read-only, effort=high) if strong-checkpoint flagged, escalate to Opus for judgment call. See `agents/build-orchestrator.md §Escalation Triggers`. The **tier mapping** is the policy; the cost numbers above are advisory context, not the basis for overrides.
173
+ **Fable plans (when stakes-gated) and verifies. Opus coordinates. Sonnet executes. Haiku recognizes.**
153
174
 
154
- Haiku is only used for Phase 7B mock scanning. Never for reasoning tasks.
175
+ Phase 2 Plan synthesis reaches **Fable** through the **Advisor dispatch ladder** when stakes-gating trips (`synthesisDensity > 5`, `riskSurfaceChange`, `stakes >= medium`, or `dispatch_tier: frontier`): the orchestrator dispatches the `advisor` agent (Rung 1), routes to a peer host (Rung 2), or — if its own session is already Fable synthesizes inline at Frontier (Rung 0). When no trigger fires or no dispatch path is reachable, the orchestrator synthesizes the plan **inline on its own model (Opus)** and labels it honestly (Rung 3 = today's behavior; the floor equals current state). So "Fable plans" is the *guarantee on high-stakes plans*, with an honestly-labeled inline fallback otherwise — not unconditional. Full protocol: `references/advisor-dispatch-ladder.md`. The Advisor frames the goal, drafts the spec/ADRs, sets F-criteria, and MECE-partitions the work. The orchestrator (**Opus**, `build-orchestrator`, `assessment-orchestrator`) coordinates: it routes dispatches, runs deterministic gates, manages parallel fan-out, walks the Advisor ladder, and handles the escalation ladder. Phase 3 implementer subagents run on **Sonnet** at effort=medium (default workhorse) → external verification gate (tests/lint/types) → adversarial **Fable** verification surface (`plan-critic`, `scope-auditor`, `independent-auditor`, `fix-critique`, `fact-checker`, `security-reviewer`, `overfitting-reviewer`, `promotion-reviewer`). If a strong-checkpoint finding or 2 consecutive chunk failures surface, execution escalates to **Opus** for judgment; if the failure traces back to a planning miss, route back to Fable to re-plan. See `agents/build-orchestrator.md §Escalation Triggers`. The **tier mapping** is the policy; the cost numbers above are advisory context, not the basis for overrides.
176
+
177
+ Haiku is only used for Phase 7B mock scanning and recurring-pattern detection across `runs[]`. Never for reasoning tasks.
155
178
 
156
179
  ## Pin vs inherit in agent frontmatter
157
180
 
158
181
  Not every agent should hard-pin its model. Use this rule:
159
182
 
160
- - **Pin** (`model: opus | sonnet | haiku`) when the task has a clear right tier and cost/quality drift from user's session choice would be a bug. Examples: `independent-auditor` (Sonnet advisory judge across chunk + build scope, consolidated 2026-05-23replaces retired `commit-auditor` and earlier `sonnet-critic`), `mock-scanner` (pattern matching only), `build-orchestrator` (Opus judgment at plan/review boundaries).
161
- - **Inherit** (`model: inherit`) when user intent should flow through. The user's main-session choice is itself a cost/speed preference; respect it. Pair with a "recommended: X" note in this skill rather than forcing via frontmatter. Example: `fact-checker` — recommended Sonnet, but inherit honors whatever tier the user picked upstream.
162
- - **Override mechanism**: users can override any pin by passing `model:` when spawning the agent or by editing the frontmatter. Pins are defaults, not locks.
183
+ - **Pin** (`model: fable | opus | sonnet | haiku`) when the task has a clear right tier and cost/quality drift from user's session choice would be a bug. Examples: `plan-critic` / `independent-auditor` / `scope-auditor` / `fact-checker` / `fix-critique` / `security-reviewer` / `overfitting-reviewer` / `promotion-reviewer` (Fable verification verdicts gate downstream work), `mock-scanner` (Haiku, pattern matching only), `build-orchestrator` and `assessment-orchestrator` (Opus, coordination at plan/review boundaries), `implementer` (Sonnet, default execution workhorse).
184
+ - **Inherit** (`model: inherit`) when user intent should flow through. The user's main-session choice is itself a cost/speed preference; respect it. Pair with a "recommended: X" note in this skill rather than forcing via frontmatter. Example: `root-cause-investigator` — recommended Opus on causal-tree work, but inherit honors whatever tier the user picked upstream.
185
+ - **Override mechanism**: users can override any pin by passing `model:` when spawning the agent or by editing the frontmatter. Pins are defaults, not locks. The deliberate exceptions documented above (`alignment-checker`, `synthesis-critic` on Sonnet despite being verification-shaped) are exactly this kind of cost-vs-judgment pin and can be lifted if telemetry says so.
163
186
 
164
- Forward-compat note: pinned family aliases (`sonnet`, `opus`) auto-track latest versions (e.g., 4.6 → 4.7). `inherit` additionally picks up brand-new tiers (e.g., a future Flash-class model) without frontmatter edits.
187
+ Forward-compat note: pinned family aliases (`fable`, `sonnet`, `opus`) auto-track latest versions in their tier (e.g., Sonnet 4.6 → 4.7, Opus 4.7 → 4.8, Fable 5 → 6). `inherit` additionally picks up brand-new tiers (e.g., a future Flash-class model) without frontmatter edits.
165
188
 
166
189
  ## Limitations of this guidance
167
190
 
@@ -213,4 +236,6 @@ python3 ${CLAUDE_PLUGIN_ROOT}/scripts/model_overrides.py \
213
236
  --json
214
237
  ```
215
238
 
239
+ Accepted tiers: `frontier` (default `fable`), `thinking` (default `opus`), `code` (default `sonnet`), `pattern` (default `haiku`). Configs without `frontier` resolve frontier → `fable` so older repos keep working without edits.
240
+
216
241
  Full contract and routing matrix: `~/dev/research/topics/llm/llm.build-loop-router-integration-2026-04.md`
@@ -40,7 +40,7 @@ Highest-leverage phase. Wrong metric = Goodhart's Law. Wrong factors = wasted ru
40
40
  |---|---|---|
41
41
  | **A. Power-user explicit** | User supplied factors via CLI flag, `.build-loop/optimize/factors.json`, or inline ("optimize batch_size, retries, workers for throughput") | Skip suggestion; use the user's factors directly |
42
42
  | **B. Vague optimization** *(default)* | "run optimization", "make my app faster", "improve performance", "speed up", "reduce <metric>" without naming factors | Run factor-identification scan; propose candidates; **AskUserQuestion to confirm before running** |
43
- | **C. Single-variable explicit** | "simplify this file", "reduce build time", scoped `/build-loop:optimize <known-target>` | Skip DOE; run autoresearch (existing behavior, Phase 2 LOOP unchanged) |
43
+ | **C. Single-variable explicit** | "simplify this file", "reduce build time", scoped `/build-loop:optimize-run <known-target>` | Skip DOE; run autoresearch (existing behavior, Phase 2 LOOP unchanged) |
44
44
 
45
45
  ### Step 1.2 — Branch A or B: factor identification
46
46
 
@@ -186,7 +186,7 @@ Dispatch the `optimize-runner` agent. It executes:
186
186
 
187
187
  Phase 4.7 (AUTO-OPTIMIZE): after Phase 4 Execute completes and commits, check for optimization targets. Run sequentially (not parallel with Phase 4).
188
188
 
189
- Standalone: `/build-loop:optimize [target]`
189
+ Standalone: `/build-loop:optimize-run [target]`
190
190
 
191
191
  ## State Files
192
192
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plan-verify
3
- description: Use when build-loop Phase 2 wraps plan drafting, the user runs `/build-loop:plan-verify`, asks to "verify the plan" or "lint the plan", or any plan markdown change touches evidence, synthesis-density, risk_reason, or modifies_api fields. Runs deterministic plan-verify rules and emits findings JSON.
3
+ description: Use when build-loop Phase 2 wraps plan drafting, the user runs `/build-loop:verify-plan`, asks to "verify the plan" or "lint the plan", or any plan markdown change touches evidence, synthesis-density, risk_reason, or modifies_api fields. Runs deterministic plan-verify rules and emits findings JSON.
4
4
  user-invocable: false
5
5
  ---
6
6
 
@@ -213,6 +213,10 @@ mapping is valid. A real publish can still fail after a successful dry-run when
213
213
  the npm package settings do not match the GitHub workflow. After publishing,
214
214
  verify the registry metadata includes
215
215
  `dist.attestations.provenance.predicateType = https://slsa.dev/provenance/v1`.
216
+ If the real publish step prints the final `+ @scope/package@version` line but
217
+ the immediate metadata check returns `E404`, do not rerun the same publish.
218
+ npmjs metadata can lag for a few minutes after acceptance; poll `npm view` or
219
+ use a verify-only workflow path.
216
220
 
217
221
  ### Access Token Fallback Gate
218
222
 
@@ -286,6 +290,10 @@ npm audit signatures
286
290
  gh run rerun <run-id> --failed
287
291
  ```
288
292
 
293
+ - If npmjs succeeds through the final `+ @scope/package@version` line but the
294
+ post-publish metadata check returns `E404`, treat it as a visibility lag until
295
+ registry polling proves otherwise. Do not rerun the publish for that version;
296
+ rerun a verify-only path or poll `npm view`.
289
297
  - Use local npm login or token publishing only as an explicit fallback decision,
290
298
  because it bypasses the trusted-publisher/provenance path.
291
299