@mmerterden/multi-agent-pipeline 12.5.0 → 12.7.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 (290) hide show
  1. package/CHANGELOG.md +213 -0
  2. package/README.md +19 -19
  3. package/docs/FIGMA_PIPELINE.md +34 -34
  4. package/docs/adr/0001-three-model-triage.md +12 -12
  5. package/docs/adr/0002-instruction-driven-flag.md +5 -5
  6. package/docs/adr/0003-unified-shared-skills.md +5 -5
  7. package/docs/adr/0004-zero-dependency-philosophy.md +5 -5
  8. package/docs/adr/0005-lazy-phase-docs.md +2 -2
  9. package/docs/adr/0006-skills-core-external-split.md +6 -6
  10. package/docs/adr/0007-multi-tool-adapter-framework.md +19 -19
  11. package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +19 -19
  12. package/docs/adr/README.md +1 -1
  13. package/docs/best-practices.md +3 -3
  14. package/docs/features.md +48 -28
  15. package/docs/performance.md +16 -16
  16. package/docs/recovery-guide.md +39 -39
  17. package/index.js +11 -5
  18. package/install/_common.mjs +5 -11
  19. package/install/_copilot-instructions.mjs +2 -2
  20. package/install/_dev-only-files.mjs +2 -1
  21. package/install/_platform-filter.mjs +1 -1
  22. package/install/_telemetry.mjs +1 -1
  23. package/install/claude.mjs +10 -9
  24. package/install/copilot.mjs +10 -19
  25. package/install/index.mjs +7 -15
  26. package/install/templates/copilot-instructions.md +54 -54
  27. package/install.js +1 -1
  28. package/package.json +15 -11
  29. package/pipeline/agents/security-auditor.md +1 -1
  30. package/pipeline/commands/archive-guard.md +5 -5
  31. package/pipeline/commands/multi-agent/SKILL.md +3 -1
  32. package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
  33. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +1 -1
  34. package/pipeline/commands/multi-agent/autopilot/SKILL.md +1 -1
  35. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +1 -1
  36. package/pipeline/commands/multi-agent/create-jira/SKILL.md +1 -1
  37. package/pipeline/commands/multi-agent/design-check/SKILL.md +287 -0
  38. package/pipeline/commands/multi-agent/dev/SKILL.md +1 -1
  39. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +1 -1
  40. package/pipeline/commands/multi-agent/dev-local/SKILL.md +1 -1
  41. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +1 -1
  42. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +1 -1
  43. package/pipeline/commands/multi-agent/finish/SKILL.md +6 -6
  44. package/pipeline/commands/multi-agent/forget/SKILL.md +1 -1
  45. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  46. package/pipeline/commands/multi-agent/help/SKILL.md +46 -6
  47. package/pipeline/commands/multi-agent/issue/SKILL.md +1 -1
  48. package/pipeline/commands/multi-agent/jira/SKILL.md +1 -1
  49. package/pipeline/commands/multi-agent/kill/SKILL.md +1 -1
  50. package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
  51. package/pipeline/commands/multi-agent/local/SKILL.md +1 -1
  52. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
  53. package/pipeline/commands/multi-agent/log/SKILL.md +1 -1
  54. package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
  55. package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -1
  56. package/pipeline/commands/multi-agent/purge/SKILL.md +1 -1
  57. package/pipeline/commands/multi-agent/refactor/SKILL.md +107 -19
  58. package/pipeline/commands/multi-agent/resume/SKILL.md +2 -2
  59. package/pipeline/commands/multi-agent/review/SKILL.md +2 -2
  60. package/pipeline/commands/multi-agent/review-issue/SKILL.md +1 -1
  61. package/pipeline/commands/multi-agent/review-jira/SKILL.md +1 -1
  62. package/pipeline/commands/multi-agent/routines/SKILL.md +1 -1
  63. package/pipeline/commands/multi-agent/save/SKILL.md +1 -1
  64. package/pipeline/commands/multi-agent/scan/SKILL.md +1 -1
  65. package/pipeline/commands/multi-agent/search/SKILL.md +1 -1
  66. package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
  67. package/pipeline/commands/multi-agent/stack/SKILL.md +3 -3
  68. package/pipeline/commands/multi-agent/status/SKILL.md +1 -1
  69. package/pipeline/commands/multi-agent/sync/SKILL.md +123 -16
  70. package/pipeline/commands/multi-agent/test/SKILL.md +2 -2
  71. package/pipeline/commands/multi-agent/uninstall/SKILL.md +1 -1
  72. package/pipeline/commands/multi-agent/update/SKILL.md +3 -3
  73. package/pipeline/commands/sim-test.md +5 -5
  74. package/pipeline/eval/run-metrics-fixture.json +60 -13
  75. package/pipeline/lib/account-resolver.sh +1 -1
  76. package/pipeline/lib/channels-multi-repo.sh +1 -1
  77. package/pipeline/lib/context-link-extractor.sh +1 -1
  78. package/pipeline/lib/credential-store.sh +33 -1
  79. package/pipeline/lib/fetch-confluence.sh +1 -1
  80. package/pipeline/lib/fetch-crashlytics.sh +1 -1
  81. package/pipeline/lib/fetch-fortify.sh +1 -1
  82. package/pipeline/lib/fetch-graylog.sh +1 -1
  83. package/pipeline/lib/fetch-swagger.sh +1 -1
  84. package/pipeline/lib/issue-fetcher.sh +1 -1
  85. package/pipeline/lib/multi-repo-pipeline.sh +1 -1
  86. package/pipeline/lib/repo-cache.sh +1 -1
  87. package/pipeline/lib/submodule-detector.sh +1 -1
  88. package/pipeline/multi-agent-refs/component-dispatch.md +1 -1
  89. package/pipeline/multi-agent-refs/component-generation.md +121 -0
  90. package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
  91. package/pipeline/multi-agent-refs/features/model-fallback.md +2 -2
  92. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +2 -2
  93. package/pipeline/multi-agent-refs/phases/phase-4-review.md +1 -1
  94. package/pipeline/multi-agent-refs/phases/phase-5-test.md +4 -4
  95. package/pipeline/preferences-template.json +23 -12
  96. package/pipeline/schemas/agent-state.schema.json +125 -5
  97. package/pipeline/schemas/analysis-output.schema.json +18 -4
  98. package/pipeline/schemas/analysis-spec.schema.json +120 -32
  99. package/pipeline/schemas/clarify-output.schema.json +15 -5
  100. package/pipeline/schemas/design-check-config.schema.json +183 -0
  101. package/pipeline/schemas/dev-critic-output.schema.json +20 -5
  102. package/pipeline/schemas/figma-project-config.schema.json +42 -10
  103. package/pipeline/schemas/learnings-ledger.schema.json +10 -2
  104. package/pipeline/schemas/migrations/figma-config-1.0.0-to-2.0.0.mjs +1 -4
  105. package/pipeline/schemas/migrations/prefs-2.0.0-to-2.1.0.mjs +24 -7
  106. package/pipeline/schemas/migrations/state-2.0.0-to-2.1.0.mjs +30 -12
  107. package/pipeline/schemas/plan-todos.schema.json +6 -3
  108. package/pipeline/schemas/planning-output.schema.json +5 -1
  109. package/pipeline/schemas/prefs.schema.json +215 -197
  110. package/pipeline/schemas/test-gap.schema.json +5 -5
  111. package/pipeline/schemas/token-budget.json +8 -8
  112. package/pipeline/schemas/triage-corpus.schema.json +1 -1
  113. package/pipeline/scripts/README.md +7 -5
  114. package/pipeline/scripts/aggregate-metrics.mjs +18 -6
  115. package/pipeline/scripts/build-skills-index.mjs +6 -2
  116. package/pipeline/scripts/build-stack-plugins.mjs +142 -39
  117. package/pipeline/scripts/check-derived-drift.mjs +196 -0
  118. package/pipeline/scripts/check-md-links.mjs +6 -2
  119. package/pipeline/scripts/classify-plan-safety.mjs +26 -8
  120. package/pipeline/scripts/cost-budget-check.mjs +11 -6
  121. package/pipeline/scripts/cost-table.json +1 -1
  122. package/pipeline/scripts/diff-explain.mjs +7 -3
  123. package/pipeline/scripts/diff-risk-score.mjs +13 -3
  124. package/pipeline/scripts/eval-golden-tasks-live.mjs +8 -3
  125. package/pipeline/scripts/eval-golden-tasks.mjs +21 -9
  126. package/pipeline/scripts/eval-intent.mjs +8 -4
  127. package/pipeline/scripts/eval-mine-corpus.mjs +14 -4
  128. package/pipeline/scripts/evidence-gate.mjs +7 -2
  129. package/pipeline/scripts/fixtures/install-layout.tsv +7 -7
  130. package/pipeline/scripts/gen-mode-dispatch.mjs +38 -21
  131. package/pipeline/scripts/gen-skills-index.mjs +18 -3
  132. package/pipeline/scripts/learning-curve.mjs +13 -3
  133. package/pipeline/scripts/learnings-ledger.mjs +119 -34
  134. package/pipeline/scripts/lint-mcp-refs.mjs +218 -0
  135. package/pipeline/scripts/lint-skills.mjs +20 -9
  136. package/pipeline/scripts/localize-commands.mjs +6 -1
  137. package/pipeline/scripts/match-skills.mjs +15 -4
  138. package/pipeline/scripts/memory-load.sh +5 -1
  139. package/pipeline/scripts/migrate-prefs.mjs +33 -16
  140. package/pipeline/scripts/phase-tracker.sh +3 -1
  141. package/pipeline/scripts/render-work-summary.sh +4 -1
  142. package/pipeline/scripts/repo-map.mjs +110 -64
  143. package/pipeline/scripts/review-scope.mjs +7 -1
  144. package/pipeline/scripts/routine-registry.mjs +4 -9
  145. package/pipeline/scripts/run-aggregator.mjs +11 -5
  146. package/pipeline/scripts/run-metrics.mjs +13 -8
  147. package/pipeline/scripts/run-smokes.mjs +57 -3
  148. package/pipeline/scripts/scorecard.mjs +258 -0
  149. package/pipeline/scripts/smoke-command-inventory.sh +81 -0
  150. package/pipeline/scripts/smoke-commands-skills-parity.sh +1 -1
  151. package/pipeline/scripts/smoke-compliance-skills.sh +4 -4
  152. package/pipeline/scripts/smoke-context-budget.sh +72 -0
  153. package/pipeline/scripts/smoke-cross-cli-behavior.sh +12 -2
  154. package/pipeline/scripts/smoke-generate-issue.sh +6 -5
  155. package/pipeline/scripts/smoke-model-fallback.sh +1 -1
  156. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +86 -7
  157. package/pipeline/scripts/smoke-own-punctuation.sh +103 -0
  158. package/pipeline/scripts/smoke-per-repo-memory.sh +2 -2
  159. package/pipeline/scripts/smoke-review-readiness.sh +3 -2
  160. package/pipeline/scripts/smoke-schema-validation.sh +19 -5
  161. package/pipeline/scripts/smoke-shadow-git.sh +4 -2
  162. package/pipeline/scripts/smoke-workflow-audit.sh +43 -11
  163. package/pipeline/scripts/smoke-write-state.sh +49 -5
  164. package/pipeline/scripts/test-gap-rules/android.json +11 -11
  165. package/pipeline/scripts/test-gap-rules/ios.json +16 -11
  166. package/pipeline/scripts/test-gap-rules/node.json +19 -7
  167. package/pipeline/scripts/test-gap-rules/python.json +10 -4
  168. package/pipeline/scripts/test-gap-scan.mjs +44 -12
  169. package/pipeline/scripts/test-integrity-gate.mjs +5 -1
  170. package/pipeline/scripts/token-budget-report.mjs +44 -21
  171. package/pipeline/scripts/triage-memory.mjs +142 -32
  172. package/pipeline/scripts/uninstall.mjs +75 -31
  173. package/pipeline/scripts/validate-analysis-doc.mjs +15 -5
  174. package/pipeline/scripts/validate-diff-risk.mjs +32 -18
  175. package/pipeline/scripts/validate-test-gap.mjs +17 -7
  176. package/pipeline/scripts/validate-triage.mjs +17 -5
  177. package/pipeline/scripts/write-state.mjs +32 -9
  178. package/pipeline/skills/.skill-manifest.json +24 -8
  179. package/pipeline/skills/.skills-index.json +125 -89
  180. package/pipeline/skills/shared/README.md +65 -61
  181. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +10 -8
  182. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +1 -1
  183. package/pipeline/skills/shared/core/multi-agent/SKILL.md +26 -279
  184. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +1 -1
  185. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
  186. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +1 -1
  187. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  188. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  189. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +248 -0
  190. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +1 -1
  191. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +1 -1
  192. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +1 -1
  193. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +1 -1
  194. package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +1 -1
  195. package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
  196. package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +1 -1
  197. package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +1 -1
  198. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +23 -1
  199. package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +1 -1
  200. package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +1 -1
  201. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +1 -1
  202. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
  203. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
  204. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +1 -1
  205. package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +1 -1
  206. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +1 -1
  207. package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +1 -1
  208. package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +1 -1
  209. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +82 -18
  210. package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
  211. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +2 -2
  212. package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
  213. package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
  214. package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +1 -1
  215. package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +1 -1
  216. package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +1 -1
  217. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +1 -1
  218. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
  219. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +3 -3
  220. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +1 -1
  221. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +51 -9
  222. package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +2 -2
  223. package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +1 -1
  224. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +1 -1
  225. package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +1 -1
  226. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -4
  227. package/pipeline/skills/shared/external/agentflow/SKILL.md +1 -1
  228. package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +1 -1
  229. package/pipeline/skills/shared/external/android_ui_verification/SKILL.md +1 -1
  230. package/pipeline/skills/shared/external/api-patterns/SKILL.md +1 -1
  231. package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +1 -1
  232. package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +1 -1
  233. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  234. package/pipeline/skills/shared/external/backlog/SKILL.md +12 -12
  235. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -1
  236. package/pipeline/skills/shared/external/context-compression/SKILL.md +1 -1
  237. package/pipeline/skills/shared/external/council/SKILL.md +3 -3
  238. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -1
  239. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -1
  240. package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +1 -1
  241. package/pipeline/skills/shared/external/docker-expert/SKILL.md +1 -1
  242. package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +1 -1
  243. package/pipeline/skills/shared/external/firebase/SKILL.md +1 -1
  244. package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +1 -1
  245. package/pipeline/skills/shared/external/help-skills/SKILL.md +1 -1
  246. package/pipeline/skills/shared/external/hig-components-content/SKILL.md +1 -1
  247. package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +1 -1
  248. package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
  249. package/pipeline/skills/shared/external/hig-components-system/SKILL.md +1 -1
  250. package/pipeline/skills/shared/external/hig-foundations/SKILL.md +1 -1
  251. package/pipeline/skills/shared/external/hig-inputs/SKILL.md +1 -1
  252. package/pipeline/skills/shared/external/hig-patterns/SKILL.md +1 -1
  253. package/pipeline/skills/shared/external/hig-platforms/SKILL.md +1 -1
  254. package/pipeline/skills/shared/external/hig-technologies/SKILL.md +1 -1
  255. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -1
  256. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -1
  257. package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +1 -1
  258. package/pipeline/skills/shared/external/ios-developer/SKILL.md +1 -1
  259. package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +1 -1
  260. package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +1 -1
  261. package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +1 -1
  262. package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +1 -1
  263. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -1
  264. package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +1 -1
  265. package/pipeline/skills/shared/external/observability-engineer/SKILL.md +1 -1
  266. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -1
  267. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -1
  268. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -1
  269. package/pipeline/skills/shared/external/search-first/SKILL.md +2 -2
  270. package/pipeline/skills/shared/external/skill-creator/SKILL.md +12 -12
  271. package/pipeline/skills/shared/external/skill-creator/audit.md +21 -21
  272. package/pipeline/skills/shared/external/skill-creator/checklist.md +3 -3
  273. package/pipeline/skills/shared/external/skill-creator/examples.md +10 -10
  274. package/pipeline/skills/shared/external/skill-creator/label-check.md +17 -17
  275. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +86 -50
  276. package/pipeline/skills/shared/external/skill-creator/template.md +9 -9
  277. package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +1 -1
  278. package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +1 -1
  279. package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +1 -1
  280. package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +1 -1
  281. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -1
  282. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -1
  283. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -1
  284. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -1
  285. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -1
  286. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -1
  287. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -1
  288. package/pipeline/skills/shared/external/xcode-build-benchmark/schemas/build-benchmark.schema.json +9 -49
  289. package/pipeline/skills/skills-index.md +63 -59
  290. package/pipeline/scripts/smoke-plugin-validate.sh +0 -64
@@ -34,8 +34,10 @@
34
34
  // - infrastructure 20 - touches Dockerfile, CI yaml, Gradle wrapper,
35
35
  // package.json resolutions / engines, install.js
36
36
  //
37
- // recommendPause = true when score >= 50 (tuned: any two medium signals or
38
- // any one heavy signal flips it).
37
+ // recommendPause = true when any one heavy signal (weight >= 30) fires, OR two
38
+ // or more medium-and-above signals (weight >= 20) fire, OR the accumulated
39
+ // score reaches 50. A score threshold alone cannot express the first two
40
+ // clauses: the heaviest single rule is 35 and two medium signals can total 45.
39
41
  //
40
42
  // Exit codes: 0 = verdict produced, 1 = malformed input, 2 = usage error.
41
43
 
@@ -72,9 +74,17 @@ const reasons = [];
72
74
  // --- file-count ---
73
75
  const fileCount = allFiles.size;
74
76
  if (fileCount > 15) {
75
- reasons.push({ rule: "file-count-high", weight: 30, detail: `plan touches ${fileCount} files (threshold 15)` });
77
+ reasons.push({
78
+ rule: "file-count-high",
79
+ weight: 30,
80
+ detail: `plan touches ${fileCount} files (threshold 15)`,
81
+ });
76
82
  } else if (fileCount >= 8) {
77
- reasons.push({ rule: "file-count-medium", weight: 10, detail: `plan touches ${fileCount} files` });
83
+ reasons.push({
84
+ rule: "file-count-medium",
85
+ weight: 10,
86
+ detail: `plan touches ${fileCount} files`,
87
+ });
78
88
  }
79
89
 
80
90
  // --- destructive verb ---
@@ -100,7 +110,8 @@ if (destructiveHits.length > 0) {
100
110
  // mid-word hits like "Reauthorize" do not. A trailing anchor here would miss
101
111
  // the common "AuthManager"/"TokenStore" suffix-naming and let sensitive files
102
112
  // slip past the autopilot pause heuristic.
103
- const securityRe = /(\/|^)(auth|keychain|credentials?|secret|security|tokens?|cert|encrypt|signing|privacy)/i;
113
+ const securityRe =
114
+ /(\/|^)(auth|keychain|credentials?|secret|security|tokens?|cert|encrypt|signing|privacy)/i;
104
115
  const securityHits = [];
105
116
  for (const f of allFiles) if (securityRe.test(f)) securityHits.push(f);
106
117
  if (securityHits.length > 0) {
@@ -128,7 +139,11 @@ for (const t of tasks) {
128
139
  if (!destructiveRe.test(t.title || "")) continue;
129
140
  const taskDirs = new Set((t.files || []).map((f) => f.split("/").slice(0, -1).join("/")));
130
141
  let covered = false;
131
- for (const d of taskDirs) if (testFileDirs.has(d)) { covered = true; break; }
142
+ for (const d of taskDirs)
143
+ if (testFileDirs.has(d)) {
144
+ covered = true;
145
+ break;
146
+ }
132
147
  if (!covered) deleteWithoutTest.push(t.id || t.title);
133
148
  }
134
149
  if (deleteWithoutTest.length > 0) {
@@ -155,7 +170,8 @@ if (schemaHits.length > 0) {
155
170
  }
156
171
 
157
172
  // --- infrastructure ---
158
- const infraRe = /(^|\/)(Dockerfile|install\.js|package\.json|build\.gradle|settings\.gradle|Gemfile|pyproject\.toml|\.github\/workflows\/.*\.ya?ml|vercel\.(json|ts))$/i;
173
+ const infraRe =
174
+ /(^|\/)(Dockerfile|install\.js|package\.json|build\.gradle|settings\.gradle|Gemfile|pyproject\.toml|\.github\/workflows\/.*\.ya?ml|vercel\.(json|ts))$/i;
159
175
  const infraHits = [];
160
176
  for (const f of allFiles) if (infraRe.test(f)) infraHits.push(f);
161
177
  if (infraHits.length > 0) {
@@ -168,7 +184,9 @@ if (infraHits.length > 0) {
168
184
 
169
185
  // --- aggregate ---
170
186
  const score = reasons.reduce((s, r) => s + r.weight, 0);
171
- const recommendPause = score >= 50;
187
+ const heavyHits = reasons.filter((r) => r.weight >= 30);
188
+ const mediumOrAboveHits = reasons.filter((r) => r.weight >= 20);
189
+ const recommendPause = heavyHits.length >= 1 || mediumOrAboveHits.length >= 2 || score >= 50;
172
190
 
173
191
  let summary;
174
192
  if (recommendPause) {
@@ -33,6 +33,7 @@
33
33
 
34
34
  import { readFileSync, existsSync } from "fs";
35
35
  import { dirname, join } from "path";
36
+ import { homedir } from "os";
36
37
  import { fileURLToPath } from "url";
37
38
  import { costUsd } from "./_cost.mjs";
38
39
 
@@ -103,10 +104,11 @@ function resolveTracker() {
103
104
  const id = flags["task-id"];
104
105
  if (!id) die("either --tracker or --task-id is required");
105
106
  const bare = String(id).replace(/^#/, "");
107
+ const logRoot = join(homedir(), ".claude", "logs", "multi-agent");
106
108
  for (const c of [
107
- join(process.cwd(), ".worktrees", String(id), "phase-tracker.json"),
108
- join(process.cwd(), ".worktrees", bare, "phase-tracker.json"),
109
- join(process.cwd(), ".worktrees", `task-${bare}`, "phase-tracker.json"),
109
+ join(logRoot, String(id), "tracker-state.json"),
110
+ join(logRoot, bare, "tracker-state.json"),
111
+ join(logRoot, `task-${bare}`, "tracker-state.json"),
110
112
  ]) {
111
113
  if (existsSync(c)) return c;
112
114
  }
@@ -134,22 +136,25 @@ if (!rate) die(`no price for model "${cfg.pricingModel}" in cost-table.json`);
134
136
 
135
137
  let tokensIn = 0;
136
138
  let tokensOut = 0;
139
+ let tokensCached = 0;
137
140
  for (const p of Object.values(tracker.phases || {})) {
138
141
  tokensIn += Number(p?.tokens_in || 0);
139
142
  tokensOut += Number(p?.tokens_out || 0);
143
+ tokensCached += Number(p?.tokens_cached || 0);
140
144
  }
141
145
 
142
- const usd = costUsd(rate, tokensIn, tokensOut);
146
+ const usd = costUsd(rate, tokensIn, tokensOut, tokensCached);
143
147
  const pctOfMax = (usd / cfg.maxUsd) * 100;
144
148
  const usdStr = `$${usd.toFixed(2)}`;
145
- const totalTok = tokensIn + tokensOut;
149
+ const totalTok = tokensIn + tokensOut + tokensCached;
146
150
 
147
151
  const base =
148
152
  `cost-budget: ${usdStr} of $${cfg.maxUsd.toFixed(2)} ` +
149
153
  `(${pctOfMax.toFixed(0)}%, ${totalTok.toLocaleString("en-US")} tok @ ${cfg.pricingModel})`;
150
154
 
151
155
  if (usd > cfg.maxUsd) {
152
- const action = cfg.onExceed === "halt" ? "HALT - run multi-agent:resume to continue" : "over budget";
156
+ const action =
157
+ cfg.onExceed === "halt" ? "HALT - run multi-agent:resume to continue" : "over budget";
153
158
  process.stdout.write(`EXCEEDED: ${base} - ${action}\n`);
154
159
  process.exit(11);
155
160
  }
@@ -35,4 +35,4 @@
35
35
  "note": "Copilot CLI Reviewer 2 - approximate; verify against OpenAI pricing page before relying on totals."
36
36
  }
37
37
  }
38
- }
38
+ }
@@ -83,7 +83,7 @@ function loadTriage() {
83
83
  if (flags["task-id"]) {
84
84
  die(
85
85
  "--task-id resolution not implemented in this script - use --triage or --state directly. " +
86
- "The slash command resolves task IDs via the orchestrator and passes --state to this script.",
86
+ "The slash command resolves task IDs via the orchestrator and passes --state to this script.",
87
87
  );
88
88
  }
89
89
  die("one of --triage, --state, or --task-id is required");
@@ -239,7 +239,9 @@ lines.push("# Phase 4 Triage Diff Bridge");
239
239
  lines.push("");
240
240
  lines.push("## Summary");
241
241
  lines.push("");
242
- lines.push(`- **Accepted:** ${counts.accepted} (🚫 ${counts.blocking} blocking · ⚠️ ${counts.important} important · 💡 ${counts.suggestion} suggestion)`);
242
+ lines.push(
243
+ `- **Accepted:** ${counts.accepted} (🚫 ${counts.blocking} blocking · ⚠️ ${counts.important} important · 💡 ${counts.suggestion} suggestion)`,
244
+ );
243
245
  lines.push(`- **Deferred:** ${counts.deferred} · **Rejected:** ${counts.rejected}`);
244
246
  lines.push(`- **Approved:** ${triage.approved === true ? "✅ yes" : "❌ no"}`);
245
247
  lines.push("");
@@ -252,7 +254,9 @@ for (const [file, items] of byFile) {
252
254
  const icon = severityIcon(item.severity);
253
255
  const bucketTag = bucketIcon(item._bucket);
254
256
  const reviewer = item.reviewer ? ` _(${item.reviewer})_` : "";
255
- lines.push(`### ${bucketTag} ${icon} ${severityLabel(item.severity)} - line ${item.line ?? "?"}${reviewer}`);
257
+ lines.push(
258
+ `### ${bucketTag} ${icon} ${severityLabel(item.severity)} - line ${item.line ?? "?"}${reviewer}`,
259
+ );
256
260
  lines.push("");
257
261
  if (item._reason) lines.push(`> _${item._bucket}: ${item._reason}_`);
258
262
  lines.push(`> ${item.issue}`);
@@ -71,11 +71,20 @@ function git(args) {
71
71
 
72
72
  function resolveBase() {
73
73
  if (BASE) return BASE;
74
- for (const ref of ["origin/main", "main", "origin/master", "master", "develop", "origin/develop"]) {
74
+ for (const ref of [
75
+ "origin/main",
76
+ "main",
77
+ "origin/master",
78
+ "master",
79
+ "develop",
80
+ "origin/develop",
81
+ ]) {
75
82
  try {
76
83
  execFileSync("git", ["-C", ROOT, "rev-parse", "--verify", ref], { stdio: "ignore" });
77
84
  return ref;
78
- } catch { /* try next */ }
85
+ } catch {
86
+ /* try next */
87
+ }
79
88
  }
80
89
  throw new Error("no base ref found (tried origin/main, main, master, develop)");
81
90
  }
@@ -210,7 +219,8 @@ function complexitySignal(addedLines) {
210
219
  let count = 0;
211
220
  for (const l of addedLines) {
212
221
  if (/^\s*(if|guard|switch|case\s|while|for|do|try)\b/.test(l)) count++;
213
- else if (/\b\?\s*:/.test(l)) count++; // ternary
222
+ else if (/\b\?\s*:/.test(l))
223
+ count++; // ternary
214
224
  else if (/&&|\|\|/.test(l)) count++;
215
225
  }
216
226
  return count;
@@ -269,7 +269,8 @@ const summary = {
269
269
  cases_run: results.length,
270
270
  cases_passed: results.filter((r) => r.pass === true).length,
271
271
  cases_failed: results.filter((r) => r.pass === false).length,
272
- cases_skipped: results.filter((r) => typeof r.pass === "string" && r.pass.startsWith("skipped")).length,
272
+ cases_skipped: results.filter((r) => typeof r.pass === "string" && r.pass.startsWith("skipped"))
273
+ .length,
273
274
  budget_per_case: budget,
274
275
  total_budget: totalBudget,
275
276
  projected_spend: projectedSpend,
@@ -280,8 +281,12 @@ if (asJson) {
280
281
  } else {
281
282
  console.log("");
282
283
  console.log(`eval-golden-tasks-live (${summary.mode})`);
283
- console.log(` cases: ${summary.cases_run}/${summary.cases_total} run, ${summary.cases_passed} passed, ${summary.cases_failed} failed, ${summary.cases_skipped} skipped`);
284
- console.log(` budget: $${budget.toFixed(2)}/case · total cap $${totalBudget.toFixed(2)} · projected spend $${projectedSpend.toFixed(2)}`);
284
+ console.log(
285
+ ` cases: ${summary.cases_run}/${summary.cases_total} run, ${summary.cases_passed} passed, ${summary.cases_failed} failed, ${summary.cases_skipped} skipped`,
286
+ );
287
+ console.log(
288
+ ` budget: $${budget.toFixed(2)}/case · total cap $${totalBudget.toFixed(2)} · projected spend $${projectedSpend.toFixed(2)}`,
289
+ );
285
290
  console.log("");
286
291
  for (const r of results) {
287
292
  const icon = r.pass === true ? "✓" : r.pass === false ? "✗" : "·";
@@ -44,7 +44,7 @@ const validators = {
44
44
  analysis: join(root, "pipeline", "scripts", "validate-analysis.mjs"),
45
45
  planning: join(root, "pipeline", "scripts", "validate-planning.mjs"),
46
46
  reviewer: join(root, "pipeline", "scripts", "validate-reviewer.mjs"),
47
- triage: join(root, "pipeline", "scripts", "validate-triage.mjs"),
47
+ triage: join(root, "pipeline", "scripts", "validate-triage.mjs"),
48
48
  };
49
49
 
50
50
  const args = process.argv.slice(2);
@@ -108,10 +108,12 @@ function runCase(name) {
108
108
 
109
109
  // --- schema checks ---
110
110
  const a = runValidator(validators.analysis, analysisPath);
111
- if (a.code !== 0) errors.push(`phase-1-analysis fails validate-analysis (exit ${a.code}): ${a.stderr.trim()}`);
111
+ if (a.code !== 0)
112
+ errors.push(`phase-1-analysis fails validate-analysis (exit ${a.code}): ${a.stderr.trim()}`);
112
113
 
113
114
  const p = runValidator(validators.planning, planPath);
114
- if (p.code !== 0) errors.push(`phase-2-plan fails validate-planning (exit ${p.code}): ${p.stderr.trim()}`);
115
+ if (p.code !== 0)
116
+ errors.push(`phase-2-plan fails validate-planning (exit ${p.code}): ${p.stderr.trim()}`);
115
117
 
116
118
  // phase-4-review is an array (one entry per reviewer) - validate each
117
119
  if (!Array.isArray(review)) {
@@ -124,20 +126,26 @@ function runCase(name) {
124
126
  input: tmpPayload,
125
127
  encoding: "utf-8",
126
128
  });
127
- if (r.status !== 0) errors.push(`phase-4-review[${idx}] fails validate-reviewer (exit ${r.status}): ${(r.stderr || "").trim()}`);
129
+ if (r.status !== 0)
130
+ errors.push(
131
+ `phase-4-review[${idx}] fails validate-reviewer (exit ${r.status}): ${(r.stderr || "").trim()}`,
132
+ );
128
133
  });
129
134
  }
130
135
 
131
136
  const t = runValidator(validators.triage, triagePath);
132
137
  // validate-triage exit codes: 0 valid+clean, 2 contradiction, 3 correction.
133
138
  // For fixtures we accept 0 only.
134
- if (t.code !== 0) errors.push(`phase-4-triage fails validate-triage (exit ${t.code}): ${t.stderr.trim()}`);
139
+ if (t.code !== 0)
140
+ errors.push(`phase-4-triage fails validate-triage (exit ${t.code}): ${t.stderr.trim()}`);
135
141
 
136
142
  // --- cross-file consistency ---
137
143
 
138
144
  // 1. Stack match
139
145
  if (analysis.stack?.primary !== task.expectedStack) {
140
- errors.push(`stack mismatch: task.expectedStack=${task.expectedStack}, phase-1.stack.primary=${analysis.stack?.primary}`);
146
+ errors.push(
147
+ `stack mismatch: task.expectedStack=${task.expectedStack}, phase-1.stack.primary=${analysis.stack?.primary}`,
148
+ );
141
149
  }
142
150
 
143
151
  // 2. plan files ⊆ analysis touchedAreas paths
@@ -162,7 +170,7 @@ function runCase(name) {
162
170
  ].filter((f) => f && typeof f === "object");
163
171
  const triageKeys = new Set(triageAll.map((f) => `${f.file}::${f.line}::${f.issue}`));
164
172
 
165
- for (const rev of (Array.isArray(review) ? review : [])) {
173
+ for (const rev of Array.isArray(review) ? review : []) {
166
174
  for (const f of rev.findings || []) {
167
175
  const key = `${f.file}::${f.line}::${f.issue}`;
168
176
  const inPlan = plannedFiles.has(f.file);
@@ -176,11 +184,15 @@ function runCase(name) {
176
184
  // 4. blocker + deferral counts match task.expected*
177
185
  const acceptedBlockers = (triage.accepted || []).filter((x) => x.severity === "blocking").length;
178
186
  if (typeof task.expectedBlockers === "number" && acceptedBlockers !== task.expectedBlockers) {
179
- errors.push(`expectedBlockers=${task.expectedBlockers}, triage.accepted blocking count=${acceptedBlockers}`);
187
+ errors.push(
188
+ `expectedBlockers=${task.expectedBlockers}, triage.accepted blocking count=${acceptedBlockers}`,
189
+ );
180
190
  }
181
191
  const deferredCount = (triage.deferred || []).length;
182
192
  if (typeof task.expectedDeferrals === "number" && deferredCount !== task.expectedDeferrals) {
183
- errors.push(`expectedDeferrals=${task.expectedDeferrals}, triage.deferred count=${deferredCount}`);
193
+ errors.push(
194
+ `expectedDeferrals=${task.expectedDeferrals}, triage.deferred count=${deferredCount}`,
195
+ );
184
196
  }
185
197
 
186
198
  return { name, ok: errors.length === 0, errors };
@@ -70,8 +70,8 @@ function isSafe(expected, got) {
70
70
  return false;
71
71
  }
72
72
 
73
- const mismatches = []; // operationally unsafe (gate-failing)
74
- const exactMisses = []; // not exact, but operationally safe (informational)
73
+ const mismatches = []; // operationally unsafe (gate-failing)
74
+ const exactMisses = []; // not exact, but operationally safe (informational)
75
75
  let safe = 0;
76
76
  let exact = 0;
77
77
  for (const c of cases) {
@@ -96,8 +96,12 @@ const summary = {
96
96
  console.log(JSON.stringify(summary, null, 2));
97
97
 
98
98
  if (accuracy < minAccuracy) {
99
- console.error(`\neval-intent: safe accuracy ${(accuracy * 100).toFixed(1)}% < required ${(minAccuracy * 100).toFixed(0)}% (${mismatches.length} dangerous misclassification(s))`);
99
+ console.error(
100
+ `\neval-intent: safe accuracy ${(accuracy * 100).toFixed(1)}% < required ${(minAccuracy * 100).toFixed(0)}% (${mismatches.length} dangerous misclassification(s))`,
101
+ );
100
102
  process.exit(1);
101
103
  }
102
- console.error(`\neval-intent: safe ${(accuracy * 100).toFixed(1)}% (${safe}/${cases.length}), exact ${(exact / cases.length * 100).toFixed(1)}% - pass`);
104
+ console.error(
105
+ `\neval-intent: safe ${(accuracy * 100).toFixed(1)}% (${safe}/${cases.length}), exact ${((exact / cases.length) * 100).toFixed(1)}% - pass`,
106
+ );
103
107
  process.exit(0);
@@ -45,7 +45,9 @@ for (let i = 0; i < args.length; i++) {
45
45
  else if (args[i] === "--limit") opts.limit = Number(args[++i]) || Infinity;
46
46
  else if (args[i] === "--dry-run") opts.dryRun = true;
47
47
  else if (args[i] === "-h" || args[i] === "--help") {
48
- console.log("Usage: eval-mine-corpus.mjs [--corpus <path>] [--repo-slug <slug>] [--limit N] [--dry-run]");
48
+ console.log(
49
+ "Usage: eval-mine-corpus.mjs [--corpus <path>] [--repo-slug <slug>] [--limit N] [--dry-run]",
50
+ );
49
51
  process.exit(0);
50
52
  }
51
53
  }
@@ -182,19 +184,27 @@ for (const c of selected) {
182
184
  writeFileSync(join(dir, "expected.json"), JSON.stringify(c.expected, null, 2) + "\n");
183
185
  writeFileSync(
184
186
  join(dir, "meta.json"),
185
- JSON.stringify({ task_id: c.taskId, source: "eval-mine-corpus", hasHumanSignal: c.hasHumanSignal }, null, 2) + "\n",
187
+ JSON.stringify(
188
+ { task_id: c.taskId, source: "eval-mine-corpus", hasHumanSignal: c.hasHumanSignal },
189
+ null,
190
+ 2,
191
+ ) + "\n",
186
192
  );
187
193
  // Validate the emitted expected.json against the triage contract; flag if bad.
188
194
  const res = spawnSync("node", [validator, join(dir, "expected.json")], { encoding: "utf-8" });
189
195
  const ok = res.status === 0;
190
196
  if (!ok) invalid++;
191
- console.log(` emitted: triage-candidates/${safe}${tag} ${ok ? "(schema OK)" : "(SCHEMA FAIL - review)"}`);
197
+ console.log(
198
+ ` emitted: triage-candidates/${safe}${tag} ${ok ? "(schema OK)" : "(SCHEMA FAIL - review)"}`,
199
+ );
192
200
  written++;
193
201
  }
194
202
 
195
203
  if (!opts.dryRun) {
196
204
  console.log("");
197
- console.log(`eval-mine-corpus: ${written} candidate(s) written to pipeline/eval/triage-candidates/`);
205
+ console.log(
206
+ `eval-mine-corpus: ${written} candidate(s) written to pipeline/eval/triage-candidates/`,
207
+ );
198
208
  if (invalid > 0) console.log(` ${invalid} failed schema validation - fix before adopting.`);
199
209
  console.log(" Review each, fill scope/diffSummary, then move good ones into");
200
210
  console.log(" pipeline/eval/triage/<NN>-<name>/ to add them to the eval suite.");
@@ -72,7 +72,10 @@ function parseArgs(argv) {
72
72
  const body = a.slice(2);
73
73
  // --key=value form accepts a value starting with "--" too.
74
74
  const eq = body.indexOf("=");
75
- if (eq !== -1) { out[body.slice(0, eq)] = body.slice(eq + 1); continue; }
75
+ if (eq !== -1) {
76
+ out[body.slice(0, eq)] = body.slice(eq + 1);
77
+ continue;
78
+ }
76
79
  const key = body;
77
80
  const next = argv[i + 1];
78
81
  if (next === undefined || next.startsWith("--")) {
@@ -158,7 +161,9 @@ if (showsFailure) {
158
161
  }
159
162
  // No failure, but also no success marker -> unproven -> default-FAIL.
160
163
  if (!showsSuccess) {
161
- fail(`${claim} evidence does not contain a success marker - pass claim unverified by ${evidence}`);
164
+ fail(
165
+ `${claim} evidence does not contain a success marker - pass claim unverified by ${evidence}`,
166
+ );
162
167
  }
163
168
 
164
169
  ok(`${claim} pass claim substantiated by ${evidence}`);
@@ -1,19 +1,19 @@
1
1
  .claude/.pipeline-version 1
2
2
  .claude/CLAUDE.md 1
3
3
  .claude/agents 8
4
- .claude/commands 47
4
+ .claude/commands 48
5
5
  .claude/lib 27
6
6
  .claude/multi-agent-preferences.json 1
7
- .claude/multi-agent-refs 52
7
+ .claude/multi-agent-refs 53
8
8
  .claude/rules 12
9
- .claude/schemas 24
10
- .claude/scripts 199
9
+ .claude/schemas 25
10
+ .claude/scripts 204
11
11
  .claude/settings.json 1
12
12
  .claude/skills 428
13
13
  .copilot/.pipeline-version 1
14
14
  .copilot/agents 8
15
15
  .copilot/copilot-instructions.md 1
16
16
  .copilot/lib 27
17
- .copilot/schemas 24
18
- .copilot/scripts 199
19
- .copilot/skills 470
17
+ .copilot/schemas 25
18
+ .copilot/scripts 204
19
+ .copilot/skills 471
@@ -53,15 +53,31 @@ const PHASE_NAMES_NO_TEST = PHASE_NAMES.filter((p) => p !== "5:Test");
53
53
  * against its generator output.
54
54
  */
55
55
  const MODES = {
56
- dev: { phases: ["0:Init", "3:Dev", "5:Test", "6:Commit", "7:Report"], local: false, autopilot: false },
57
- "dev-autopilot": { phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"], local: false, autopilot: true },
58
- "dev-local": { phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"], local: true, autopilot: false },
59
- "dev-local-autopilot": { phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"], local: true, autopilot: true },
60
- autopilot: { phases: PHASE_NAMES_NO_TEST, local: false, autopilot: true },
61
- full: { phases: PHASE_NAMES, local: false, autopilot: false },
62
- local: { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
63
- "local-autopilot": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: true },
64
- "full-local": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
56
+ dev: {
57
+ phases: ["0:Init", "3:Dev", "5:Test", "6:Commit", "7:Report"],
58
+ local: false,
59
+ autopilot: false,
60
+ },
61
+ "dev-autopilot": {
62
+ phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
63
+ local: false,
64
+ autopilot: true,
65
+ },
66
+ "dev-local": {
67
+ phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
68
+ local: true,
69
+ autopilot: false,
70
+ },
71
+ "dev-local-autopilot": {
72
+ phases: ["0:Init", "3:Dev", "6:Commit", "7:Report"],
73
+ local: true,
74
+ autopilot: true,
75
+ },
76
+ autopilot: { phases: PHASE_NAMES_NO_TEST, local: false, autopilot: true },
77
+ full: { phases: PHASE_NAMES, local: false, autopilot: false },
78
+ local: { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
79
+ "local-autopilot": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: true },
80
+ "full-local": { phases: PHASE_NAMES_NO_TEST, local: true, autopilot: false },
65
81
  };
66
82
 
67
83
  const spec = MODES[MODE];
@@ -80,22 +96,23 @@ const phaseSequence = activeIds.map((id) => `Phase ${id}`).join(" → ");
80
96
 
81
97
  // Mode label for prose - how to refer to the mode in the TaskCreate paragraph.
82
98
  const MODE_LABELS = {
83
- "dev": "`--dev`",
84
- "dev-autopilot": "`--dev autopilot`",
85
- "dev-local": "`--dev local`",
86
- "dev-local-autopilot": "`--dev local autopilot`",
87
- "autopilot": "`autopilot`",
88
- "full": "full-pipeline",
89
- "local": "`--local`",
90
- "local-autopilot": "`--local autopilot`",
91
- "full-local": "full-pipeline + `--local`",
99
+ dev: "`--dev`",
100
+ "dev-autopilot": "`--dev autopilot`",
101
+ "dev-local": "`--dev local`",
102
+ "dev-local-autopilot": "`--dev local autopilot`",
103
+ autopilot: "`autopilot`",
104
+ full: "full-pipeline",
105
+ local: "`--local`",
106
+ "local-autopilot": "`--local autopilot`",
107
+ "full-local": "full-pipeline + `--local`",
92
108
  };
93
109
  const modeLabel = MODE_LABELS[MODE] ?? `\`${MODE}\``;
94
110
 
95
111
  // Prose for the skip-set + ordering paragraphs.
96
- const skipNote = skippedIds.length > 0
97
- ? `${modeLabel} mode does NOT TaskCreate phases ${skippedIds.join("/")} - those are not part of the ${modeLabel} phase set (\`${spec.phases.join(" ")}\`). Only register tiles for the active set.`
98
- : `${modeLabel} mode TaskCreates all 8 phases (no phase is skipped).`;
112
+ const skipNote =
113
+ skippedIds.length > 0
114
+ ? `${modeLabel} mode does NOT TaskCreate phases ${skippedIds.join("/")} - those are not part of the ${modeLabel} phase set (\`${spec.phases.join(" ")}\`). Only register tiles for the active set.`
115
+ : `${modeLabel} mode TaskCreates all 8 phases (no phase is skipped).`;
99
116
 
100
117
  const orderingNote = `**All TaskCreate calls fire in strict phase-number order BEFORE any TaskUpdate is applied.** For ${modeLabel} that means: ${phaseSequence}. The native widget renders by creation order, not by phase number - out-of-order calls produce visually scrambled tile stacks. Full ordering contract in \`$HOME/.claude/multi-agent-refs/tracker-contract.md\` section "TaskCreate ordering (strict)".`;
101
118
 
@@ -28,11 +28,26 @@ function parseFrontmatter(md) {
28
28
  }
29
29
 
30
30
  function categorize(name) {
31
- if (name.startsWith("multi-agent") || name === "apple-archive-compliance" || name === "google-play-compliance") return "pipeline";
32
- if (/^(swift|swiftui|swiftdata|ios|storekit|healthkit|mapkit|callkit|weatherkit|musickit|passkit|pencilkit|realitykit|cloudkit|apple-on-device-ai|permissionkit|metrickit|homekit-matter|coreml|core-bluetooth|core-motion|core-nfc|speech-recognition|natural-language|vision-framework|contacts-framework|eventkit|energykit|shareplay|background-processing|live-activities|push-notifications|tipkit|widgetkit|authentication|app-clips|app-intents|app-store|alarmkit|macos-|hig-|photos-camera|accessibility-compliance|firebase|device-integrity)/.test(name)) return "ios";
31
+ if (
32
+ name.startsWith("multi-agent") ||
33
+ name === "apple-archive-compliance" ||
34
+ name === "google-play-compliance"
35
+ )
36
+ return "pipeline";
37
+ if (
38
+ /^(swift|swiftui|swiftdata|ios|storekit|healthkit|mapkit|callkit|weatherkit|musickit|passkit|pencilkit|realitykit|cloudkit|apple-on-device-ai|permissionkit|metrickit|homekit-matter|coreml|core-bluetooth|core-motion|core-nfc|speech-recognition|natural-language|vision-framework|contacts-framework|eventkit|energykit|shareplay|background-processing|live-activities|push-notifications|tipkit|widgetkit|authentication|app-clips|app-intents|app-store|alarmkit|macos-|hig-|photos-camera|accessibility-compliance|firebase|device-integrity)/.test(
39
+ name,
40
+ )
41
+ )
42
+ return "ios";
33
43
  if (/^(android|compose|gradle|kotlin|retrofit|room|play-store)/.test(name)) return "android";
34
44
  if (/^(react|nextjs|vue|tailwind|css|html|typescript|web-|figma)/.test(name)) return "web";
35
- if (/^(fastapi|nodejs|python|docker|rest-api|api-|database|testing-backend|observability|monorepo)/.test(name)) return "backend";
45
+ if (
46
+ /^(fastapi|nodejs|python|docker|rest-api|api-|database|testing-backend|observability|monorepo)/.test(
47
+ name,
48
+ )
49
+ )
50
+ return "backend";
36
51
  return "misc";
37
52
  }
38
53
 
@@ -66,12 +66,20 @@ for (const e of events) {
66
66
  if (!id) continue;
67
67
  let t = tasks.get(id);
68
68
  if (!t) {
69
- t = { firstTs: e.ts, reviewCycles: null, rework: 0, tokensIn: 0, tokensOut: 0, tokensCached: 0 };
69
+ t = {
70
+ firstTs: e.ts,
71
+ reviewCycles: null,
72
+ rework: 0,
73
+ tokensIn: 0,
74
+ tokensOut: 0,
75
+ tokensCached: 0,
76
+ };
70
77
  tasks.set(id, t);
71
78
  }
72
79
  if (e.ts && (!t.firstTs || e.ts < t.firstTs)) t.firstTs = e.ts;
73
80
  const d = e.details || {};
74
- if (e.event === "review.completed" && d.review_cycles != null) t.reviewCycles = num(d.review_cycles);
81
+ if (e.event === "review.completed" && d.review_cycles != null)
82
+ t.reviewCycles = num(d.review_cycles);
75
83
  if (e.event === "rework.started") t.rework += 1;
76
84
  t.tokensIn += num(d.tokens_in);
77
85
  t.tokensOut += num(d.tokens_out);
@@ -149,7 +157,9 @@ const arrow = (v, goodIsUp) => {
149
157
  return `${up ? "+" : ""}${v} ${good ? "(better)" : "(worse)"}`;
150
158
  };
151
159
  console.log(`# Learning curve (${opts.bucketDays}-day buckets)\n`);
152
- console.log("| Bucket | Tasks | First-pass clean | Avg review cycles | Rework/task | Tokens/task | Cache ratio |");
160
+ console.log(
161
+ "| Bucket | Tasks | First-pass clean | Avg review cycles | Rework/task | Tokens/task | Cache ratio |",
162
+ );
153
163
  console.log("|---|---|---|---|---|---|---|");
154
164
  for (const b of buckets) {
155
165
  console.log(