@mmerterden/multi-agent-pipeline 12.6.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 (271) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +18 -18
  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 +28 -28
  15. package/docs/performance.md +16 -16
  16. package/docs/recovery-guide.md +39 -39
  17. package/index.js +4 -4
  18. package/install/_common.mjs +5 -11
  19. package/install/_copilot-instructions.mjs +2 -2
  20. package/install/_dev-only-files.mjs +1 -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 +13 -10
  29. package/pipeline/commands/multi-agent/SKILL.md +1 -1
  30. package/pipeline/commands/multi-agent/analysis/SKILL.md +1 -1
  31. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +1 -1
  32. package/pipeline/commands/multi-agent/autopilot/SKILL.md +1 -1
  33. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +1 -1
  34. package/pipeline/commands/multi-agent/create-jira/SKILL.md +1 -1
  35. package/pipeline/commands/multi-agent/design-check/SKILL.md +1 -1
  36. package/pipeline/commands/multi-agent/dev/SKILL.md +1 -1
  37. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +1 -1
  38. package/pipeline/commands/multi-agent/dev-local/SKILL.md +1 -1
  39. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +1 -1
  40. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +1 -1
  41. package/pipeline/commands/multi-agent/finish/SKILL.md +6 -6
  42. package/pipeline/commands/multi-agent/forget/SKILL.md +1 -1
  43. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  44. package/pipeline/commands/multi-agent/help/SKILL.md +3 -3
  45. package/pipeline/commands/multi-agent/issue/SKILL.md +1 -1
  46. package/pipeline/commands/multi-agent/jira/SKILL.md +1 -1
  47. package/pipeline/commands/multi-agent/kill/SKILL.md +1 -1
  48. package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
  49. package/pipeline/commands/multi-agent/local/SKILL.md +1 -1
  50. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
  51. package/pipeline/commands/multi-agent/log/SKILL.md +1 -1
  52. package/pipeline/commands/multi-agent/manual-test/SKILL.md +1 -1
  53. package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -1
  54. package/pipeline/commands/multi-agent/purge/SKILL.md +1 -1
  55. package/pipeline/commands/multi-agent/refactor/SKILL.md +16 -8
  56. package/pipeline/commands/multi-agent/resume/SKILL.md +2 -2
  57. package/pipeline/commands/multi-agent/review/SKILL.md +1 -1
  58. package/pipeline/commands/multi-agent/review-issue/SKILL.md +1 -1
  59. package/pipeline/commands/multi-agent/review-jira/SKILL.md +1 -1
  60. package/pipeline/commands/multi-agent/routines/SKILL.md +1 -1
  61. package/pipeline/commands/multi-agent/save/SKILL.md +1 -1
  62. package/pipeline/commands/multi-agent/scan/SKILL.md +1 -1
  63. package/pipeline/commands/multi-agent/search/SKILL.md +1 -1
  64. package/pipeline/commands/multi-agent/setup/SKILL.md +2 -2
  65. package/pipeline/commands/multi-agent/stack/SKILL.md +3 -3
  66. package/pipeline/commands/multi-agent/status/SKILL.md +1 -1
  67. package/pipeline/commands/multi-agent/sync/SKILL.md +5 -5
  68. package/pipeline/commands/multi-agent/test/SKILL.md +1 -1
  69. package/pipeline/commands/multi-agent/uninstall/SKILL.md +1 -1
  70. package/pipeline/commands/multi-agent/update/SKILL.md +3 -3
  71. package/pipeline/eval/run-metrics-fixture.json +60 -13
  72. package/pipeline/lib/account-resolver.sh +1 -1
  73. package/pipeline/lib/channels-multi-repo.sh +1 -1
  74. package/pipeline/lib/context-link-extractor.sh +1 -1
  75. package/pipeline/lib/credential-store.sh +1 -1
  76. package/pipeline/lib/fetch-confluence.sh +1 -1
  77. package/pipeline/lib/fetch-crashlytics.sh +1 -1
  78. package/pipeline/lib/fetch-fortify.sh +1 -1
  79. package/pipeline/lib/fetch-graylog.sh +1 -1
  80. package/pipeline/lib/fetch-swagger.sh +1 -1
  81. package/pipeline/lib/issue-fetcher.sh +1 -1
  82. package/pipeline/lib/multi-repo-pipeline.sh +1 -1
  83. package/pipeline/lib/repo-cache.sh +1 -1
  84. package/pipeline/lib/submodule-detector.sh +1 -1
  85. package/pipeline/multi-agent-refs/component-dispatch.md +1 -1
  86. package/pipeline/multi-agent-refs/component-generation.md +121 -0
  87. package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
  88. package/pipeline/multi-agent-refs/features/model-fallback.md +2 -2
  89. package/pipeline/multi-agent-refs/phases/phase-4-review.md +1 -1
  90. package/pipeline/preferences-template.json +5 -11
  91. package/pipeline/schemas/agent-state.schema.json +39 -9
  92. package/pipeline/schemas/analysis-output.schema.json +18 -4
  93. package/pipeline/schemas/analysis-spec.schema.json +120 -32
  94. package/pipeline/schemas/clarify-output.schema.json +15 -5
  95. package/pipeline/schemas/design-check-config.schema.json +32 -11
  96. package/pipeline/schemas/dev-critic-output.schema.json +20 -5
  97. package/pipeline/schemas/figma-project-config.schema.json +42 -10
  98. package/pipeline/schemas/learnings-ledger.schema.json +10 -2
  99. package/pipeline/schemas/migrations/figma-config-1.0.0-to-2.0.0.mjs +1 -4
  100. package/pipeline/schemas/migrations/prefs-2.0.0-to-2.1.0.mjs +24 -7
  101. package/pipeline/schemas/plan-todos.schema.json +6 -3
  102. package/pipeline/schemas/planning-output.schema.json +5 -1
  103. package/pipeline/schemas/prefs.schema.json +91 -229
  104. package/pipeline/schemas/test-gap.schema.json +5 -5
  105. package/pipeline/schemas/token-budget.json +8 -8
  106. package/pipeline/schemas/triage-corpus.schema.json +1 -1
  107. package/pipeline/scripts/aggregate-metrics.mjs +18 -6
  108. package/pipeline/scripts/build-skills-index.mjs +6 -2
  109. package/pipeline/scripts/build-stack-plugins.mjs +142 -39
  110. package/pipeline/scripts/check-derived-drift.mjs +196 -0
  111. package/pipeline/scripts/check-md-links.mjs +6 -2
  112. package/pipeline/scripts/classify-plan-safety.mjs +20 -7
  113. package/pipeline/scripts/cost-budget-check.mjs +2 -1
  114. package/pipeline/scripts/cost-table.json +1 -1
  115. package/pipeline/scripts/diff-explain.mjs +7 -3
  116. package/pipeline/scripts/diff-risk-score.mjs +13 -3
  117. package/pipeline/scripts/eval-golden-tasks-live.mjs +8 -3
  118. package/pipeline/scripts/eval-golden-tasks.mjs +21 -9
  119. package/pipeline/scripts/eval-intent.mjs +8 -4
  120. package/pipeline/scripts/eval-mine-corpus.mjs +14 -4
  121. package/pipeline/scripts/evidence-gate.mjs +7 -2
  122. package/pipeline/scripts/fixtures/install-layout.tsv +3 -3
  123. package/pipeline/scripts/gen-mode-dispatch.mjs +38 -21
  124. package/pipeline/scripts/gen-skills-index.mjs +18 -3
  125. package/pipeline/scripts/learning-curve.mjs +13 -3
  126. package/pipeline/scripts/learnings-ledger.mjs +103 -36
  127. package/pipeline/scripts/lint-mcp-refs.mjs +13 -2
  128. package/pipeline/scripts/lint-skills.mjs +20 -9
  129. package/pipeline/scripts/localize-commands.mjs +6 -1
  130. package/pipeline/scripts/match-skills.mjs +15 -4
  131. package/pipeline/scripts/migrate-prefs.mjs +33 -16
  132. package/pipeline/scripts/phase-tracker.sh +3 -1
  133. package/pipeline/scripts/repo-map.mjs +110 -64
  134. package/pipeline/scripts/review-scope.mjs +7 -1
  135. package/pipeline/scripts/routine-registry.mjs +4 -9
  136. package/pipeline/scripts/run-aggregator.mjs +11 -5
  137. package/pipeline/scripts/run-metrics.mjs +13 -8
  138. package/pipeline/scripts/run-smokes.mjs +57 -3
  139. package/pipeline/scripts/scorecard.mjs +258 -0
  140. package/pipeline/scripts/smoke-context-budget.sh +72 -0
  141. package/pipeline/scripts/smoke-model-fallback.sh +1 -1
  142. package/pipeline/scripts/smoke-no-mcp-in-dev-phases.sh +86 -7
  143. package/pipeline/scripts/smoke-own-punctuation.sh +103 -0
  144. package/pipeline/scripts/smoke-workflow-audit.sh +43 -11
  145. package/pipeline/scripts/smoke-write-state.sh +49 -5
  146. package/pipeline/scripts/test-gap-rules/android.json +11 -11
  147. package/pipeline/scripts/test-gap-rules/ios.json +16 -11
  148. package/pipeline/scripts/test-gap-rules/node.json +19 -7
  149. package/pipeline/scripts/test-gap-rules/python.json +10 -4
  150. package/pipeline/scripts/test-gap-scan.mjs +44 -12
  151. package/pipeline/scripts/test-integrity-gate.mjs +5 -1
  152. package/pipeline/scripts/token-budget-report.mjs +44 -21
  153. package/pipeline/scripts/triage-memory.mjs +126 -34
  154. package/pipeline/scripts/uninstall.mjs +74 -30
  155. package/pipeline/scripts/validate-analysis-doc.mjs +15 -5
  156. package/pipeline/scripts/validate-diff-risk.mjs +32 -18
  157. package/pipeline/scripts/validate-test-gap.mjs +17 -7
  158. package/pipeline/scripts/validate-triage.mjs +17 -5
  159. package/pipeline/scripts/write-state.mjs +32 -9
  160. package/pipeline/skills/.skills-index.json +91 -91
  161. package/pipeline/skills/shared/README.md +57 -57
  162. package/pipeline/skills/shared/core/apple-archive-compliance/SKILL.md +1 -1
  163. package/pipeline/skills/shared/core/google-play-compliance/SKILL.md +1 -1
  164. package/pipeline/skills/shared/core/multi-agent/SKILL.md +26 -279
  165. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +1 -1
  166. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
  167. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +1 -1
  168. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  169. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  170. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +1 -1
  171. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +1 -1
  172. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +1 -1
  173. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +1 -1
  174. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +1 -1
  175. package/pipeline/skills/shared/core/multi-agent-diff-explain/SKILL.md +1 -1
  176. package/pipeline/skills/shared/core/multi-agent-finish/SKILL.md +1 -1
  177. package/pipeline/skills/shared/core/multi-agent-forget/SKILL.md +1 -1
  178. package/pipeline/skills/shared/core/multi-agent-garbage-collect/SKILL.md +1 -1
  179. package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +1 -1
  180. package/pipeline/skills/shared/core/multi-agent-issue/SKILL.md +1 -1
  181. package/pipeline/skills/shared/core/multi-agent-jira/SKILL.md +1 -1
  182. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +1 -1
  183. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
  184. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
  185. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +1 -1
  186. package/pipeline/skills/shared/core/multi-agent-log/SKILL.md +1 -1
  187. package/pipeline/skills/shared/core/multi-agent-manual-test/SKILL.md +1 -1
  188. package/pipeline/skills/shared/core/multi-agent-prune-logs/SKILL.md +1 -1
  189. package/pipeline/skills/shared/core/multi-agent-purge/SKILL.md +1 -1
  190. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +16 -8
  191. package/pipeline/skills/shared/core/multi-agent-resume/SKILL.md +1 -1
  192. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
  193. package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
  194. package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
  195. package/pipeline/skills/shared/core/multi-agent-routines/SKILL.md +1 -1
  196. package/pipeline/skills/shared/core/multi-agent-save/SKILL.md +1 -1
  197. package/pipeline/skills/shared/core/multi-agent-scan/SKILL.md +1 -1
  198. package/pipeline/skills/shared/core/multi-agent-search/SKILL.md +1 -1
  199. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +1 -1
  200. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +3 -3
  201. package/pipeline/skills/shared/core/multi-agent-status/SKILL.md +1 -1
  202. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +1 -1
  203. package/pipeline/skills/shared/core/multi-agent-test/SKILL.md +1 -1
  204. package/pipeline/skills/shared/core/multi-agent-uninstall/SKILL.md +1 -1
  205. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +1 -1
  206. package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +1 -1
  207. package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +4 -4
  208. package/pipeline/skills/shared/external/agentflow/SKILL.md +1 -1
  209. package/pipeline/skills/shared/external/android-jetpack-compose-expert/SKILL.md +1 -1
  210. package/pipeline/skills/shared/external/android_ui_verification/SKILL.md +1 -1
  211. package/pipeline/skills/shared/external/api-patterns/SKILL.md +1 -1
  212. package/pipeline/skills/shared/external/api-security-best-practices/SKILL.md +1 -1
  213. package/pipeline/skills/shared/external/app-store-changelog/SKILL.md +1 -1
  214. package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
  215. package/pipeline/skills/shared/external/backlog/SKILL.md +12 -12
  216. package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -1
  217. package/pipeline/skills/shared/external/context-compression/SKILL.md +1 -1
  218. package/pipeline/skills/shared/external/council/SKILL.md +3 -3
  219. package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -1
  220. package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -1
  221. package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +1 -1
  222. package/pipeline/skills/shared/external/docker-expert/SKILL.md +1 -1
  223. package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +1 -1
  224. package/pipeline/skills/shared/external/firebase/SKILL.md +1 -1
  225. package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +1 -1
  226. package/pipeline/skills/shared/external/help-skills/SKILL.md +1 -1
  227. package/pipeline/skills/shared/external/hig-components-content/SKILL.md +1 -1
  228. package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +1 -1
  229. package/pipeline/skills/shared/external/hig-components-status/SKILL.md +1 -1
  230. package/pipeline/skills/shared/external/hig-components-system/SKILL.md +1 -1
  231. package/pipeline/skills/shared/external/hig-foundations/SKILL.md +1 -1
  232. package/pipeline/skills/shared/external/hig-inputs/SKILL.md +1 -1
  233. package/pipeline/skills/shared/external/hig-patterns/SKILL.md +1 -1
  234. package/pipeline/skills/shared/external/hig-platforms/SKILL.md +1 -1
  235. package/pipeline/skills/shared/external/hig-technologies/SKILL.md +1 -1
  236. package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -1
  237. package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -1
  238. package/pipeline/skills/shared/external/ios-debugger-agent/SKILL.md +1 -1
  239. package/pipeline/skills/shared/external/ios-developer/SKILL.md +1 -1
  240. package/pipeline/skills/shared/external/kotlin-coroutines-expert/SKILL.md +1 -1
  241. package/pipeline/skills/shared/external/macos-menubar-tuist-app/SKILL.md +1 -1
  242. package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +1 -1
  243. package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +1 -1
  244. package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -1
  245. package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +1 -1
  246. package/pipeline/skills/shared/external/observability-engineer/SKILL.md +1 -1
  247. package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -1
  248. package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -1
  249. package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -1
  250. package/pipeline/skills/shared/external/search-first/SKILL.md +2 -2
  251. package/pipeline/skills/shared/external/skill-creator/SKILL.md +12 -12
  252. package/pipeline/skills/shared/external/skill-creator/audit.md +21 -21
  253. package/pipeline/skills/shared/external/skill-creator/checklist.md +3 -3
  254. package/pipeline/skills/shared/external/skill-creator/examples.md +10 -10
  255. package/pipeline/skills/shared/external/skill-creator/label-check.md +17 -17
  256. package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +86 -50
  257. package/pipeline/skills/shared/external/skill-creator/template.md +9 -9
  258. package/pipeline/skills/shared/external/swift-concurrency-expert/SKILL.md +1 -1
  259. package/pipeline/skills/shared/external/swiftui-performance-audit/SKILL.md +1 -1
  260. package/pipeline/skills/shared/external/swiftui-ui-patterns/SKILL.md +1 -1
  261. package/pipeline/skills/shared/external/swiftui-view-refactor/SKILL.md +1 -1
  262. package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -1
  263. package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -1
  264. package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -1
  265. package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -1
  266. package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -1
  267. package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -1
  268. package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -1
  269. package/pipeline/skills/shared/external/xcode-build-benchmark/schemas/build-benchmark.schema.json +9 -49
  270. package/pipeline/skills/skills-index.md +57 -57
  271. package/pipeline/scripts/smoke-plugin-validate.sh +0 -64
@@ -43,7 +43,15 @@
43
43
  * @module pipeline/scripts/learnings-ledger
44
44
  */
45
45
 
46
- import { readFileSync, writeFileSync, renameSync, existsSync, mkdirSync, appendFileSync, statSync } from "node:fs";
46
+ import {
47
+ readFileSync,
48
+ writeFileSync,
49
+ renameSync,
50
+ existsSync,
51
+ mkdirSync,
52
+ appendFileSync,
53
+ statSync,
54
+ } from "node:fs";
47
55
  import { homedir } from "node:os";
48
56
  import { execFileSync } from "node:child_process";
49
57
  import { join, basename, dirname } from "node:path";
@@ -59,11 +67,16 @@ for (let i = 1; i < argv.length; i++) {
59
67
  // (e.g. --statement="-- prefer let over var"). Use it when the space form
60
68
  // would mistake the value for the next flag.
61
69
  const eq = body.indexOf("=");
62
- if (eq !== -1) { flags[body.slice(0, eq)] = body.slice(eq + 1); continue; }
70
+ if (eq !== -1) {
71
+ flags[body.slice(0, eq)] = body.slice(eq + 1);
72
+ continue;
73
+ }
63
74
  const k = body;
64
75
  const v = argv[i + 1];
65
- if (v !== undefined && !v.startsWith("--")) { flags[k] = v; i++; }
66
- else flags[k] = true;
76
+ if (v !== undefined && !v.startsWith("--")) {
77
+ flags[k] = v;
78
+ i++;
79
+ } else flags[k] = true;
67
80
  }
68
81
 
69
82
  const KINDS = new Set(["fact", "convention", "rejected-preference"]);
@@ -86,7 +99,7 @@ function repoSlug() {
86
99
  const commonDir = execFileSync(
87
100
  "git",
88
101
  ["rev-parse", "--path-format=absolute", "--git-common-dir"],
89
- { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }
102
+ { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] },
90
103
  ).trim();
91
104
  if (commonDir) {
92
105
  const base = basename(commonDir);
@@ -94,19 +107,30 @@ function repoSlug() {
94
107
  const slug = basename(root);
95
108
  if (slug) return slug;
96
109
  }
97
- } catch { /* not a git repo, or git too old for --path-format */ }
110
+ } catch {
111
+ /* not a git repo, or git too old for --path-format */
112
+ }
98
113
  try {
99
114
  const top = execFileSync("git", ["rev-parse", "--show-toplevel"], {
100
115
  encoding: "utf8",
101
116
  stdio: ["ignore", "pipe", "ignore"],
102
117
  }).trim();
103
118
  if (top) return basename(top);
104
- } catch { /* not a git repo */ }
119
+ } catch {
120
+ /* not a git repo */
121
+ }
105
122
  return "default";
106
123
  }
107
124
 
108
125
  function ledgerPath(slug) {
109
- return join(homedir(), ".claude", "memory", "multi-agent", slug || repoSlug(), "learnings-ledger.jsonl");
126
+ return join(
127
+ homedir(),
128
+ ".claude",
129
+ "memory",
130
+ "multi-agent",
131
+ slug || repoSlug(),
132
+ "learnings-ledger.jsonl",
133
+ );
110
134
  }
111
135
 
112
136
  function ensureDir(p) {
@@ -114,7 +138,10 @@ function ensureDir(p) {
114
138
  }
115
139
 
116
140
  function normStatement(s) {
117
- return String(s || "").toLowerCase().replace(/\s+/g, " ").trim();
141
+ return String(s || "")
142
+ .toLowerCase()
143
+ .replace(/\s+/g, " ")
144
+ .trim();
118
145
  }
119
146
 
120
147
  function readLedger(slug) {
@@ -124,8 +151,11 @@ function readLedger(slug) {
124
151
  const rows = [];
125
152
  for (const line of raw.split("\n")) {
126
153
  if (!line.trim()) continue;
127
- try { rows.push(JSON.parse(line)); }
128
- catch { /* skip corrupted line */ }
154
+ try {
155
+ rows.push(JSON.parse(line));
156
+ } catch {
157
+ /* skip corrupted line */
158
+ }
129
159
  }
130
160
  return rows;
131
161
  }
@@ -166,18 +196,25 @@ function addEntry(slug, { kind, statement, scope, task, confidence, diagnosis },
166
196
  function cmdAdd() {
167
197
  const kind = flags.kind;
168
198
  if (!KINDS.has(kind)) die(`--kind must be one of: ${[...KINDS].join(", ")}`, 1);
169
- if (!flags.statement || flags.statement === true) die("add needs --statement \"...\"", 1);
199
+ if (!flags.statement || flags.statement === true) die('add needs --statement "..."', 1);
170
200
  const slug = repoSlug();
171
201
  const existing = new Set(readLedger(slug).map((r) => `${r.kind}::${normStatement(r.statement)}`));
172
- const wrote = addEntry(slug, {
173
- kind,
174
- statement: flags.statement,
175
- scope: flags.scope && flags.scope !== true ? String(flags.scope) : "global",
176
- task: flags.task && flags.task !== true ? String(flags.task) : null,
177
- confidence: flags.confidence && flags.confidence !== true ? String(flags.confidence) : "medium",
178
- diagnosis: flags.diagnosis && flags.diagnosis !== true ? String(flags.diagnosis) : null,
179
- }, existing);
180
- process.stdout.write(JSON.stringify({ ok: true, slug, added: wrote ? 1 : 0, deduped: wrote ? 0 : 1 }) + "\n");
202
+ const wrote = addEntry(
203
+ slug,
204
+ {
205
+ kind,
206
+ statement: flags.statement,
207
+ scope: flags.scope && flags.scope !== true ? String(flags.scope) : "global",
208
+ task: flags.task && flags.task !== true ? String(flags.task) : null,
209
+ confidence:
210
+ flags.confidence && flags.confidence !== true ? String(flags.confidence) : "medium",
211
+ diagnosis: flags.diagnosis && flags.diagnosis !== true ? String(flags.diagnosis) : null,
212
+ },
213
+ existing,
214
+ );
215
+ process.stdout.write(
216
+ JSON.stringify({ ok: true, slug, added: wrote ? 1 : 0, deduped: wrote ? 0 : 1 }) + "\n",
217
+ );
181
218
  process.exit(wrote ? 0 : 2);
182
219
  }
183
220
 
@@ -188,8 +225,11 @@ function cmdFromTriage() {
188
225
  const task = flags.task && flags.task !== true ? String(flags.task) : null;
189
226
  const slug = repoSlug();
190
227
  let triage;
191
- try { triage = JSON.parse(readFileSync(triagePath, "utf8")); }
192
- catch (e) { die(`cannot parse triage JSON: ${e.message}`, 1); }
228
+ try {
229
+ triage = JSON.parse(readFileSync(triagePath, "utf8"));
230
+ } catch (e) {
231
+ die(`cannot parse triage JSON: ${e.message}`, 1);
232
+ }
193
233
 
194
234
  const existing = new Set(readLedger(slug).map((r) => `${r.kind}::${normStatement(r.statement)}`));
195
235
  let written = 0;
@@ -203,12 +243,21 @@ function cmdFromTriage() {
203
243
  // whole class on every future run. Blocking findings always get re-raised
204
244
  // and re-triaged on their own merits; only lower-severity rejections (style
205
245
  // nitpicks, scope calls) become durable "do not re-flag" preferences.
206
- if (f.severity === "blocking") { skippedBlocking++; continue; }
246
+ if (f.severity === "blocking") {
247
+ skippedBlocking++;
248
+ continue;
249
+ }
207
250
  // Top-level files (dirname ".") scope to the file itself, not a stray "./*".
208
251
  const dir = f.file ? dirname(f.file) : "";
209
- const scope = !f.file ? "global" : (dir === "." || dir === "" ? f.file : `${dir}/*`);
252
+ const scope = !f.file ? "global" : dir === "." || dir === "" ? f.file : `${dir}/*`;
210
253
  const statement = `Do not re-flag: ${issue}` + (r.reason ? ` (rejected: ${r.reason})` : "");
211
- if (addEntry(slug, { kind: "rejected-preference", statement, scope, task, confidence: "low" }, existing)) {
254
+ if (
255
+ addEntry(
256
+ slug,
257
+ { kind: "rejected-preference", statement, scope, task, confidence: "low" },
258
+ existing,
259
+ )
260
+ ) {
212
261
  written++;
213
262
  }
214
263
  }
@@ -220,7 +269,7 @@ function cmdForget() {
220
269
  const slug = repoSlug();
221
270
  const match = flags.statement && flags.statement !== true ? normStatement(flags.statement) : null;
222
271
  const kind = flags.kind && flags.kind !== true ? String(flags.kind) : null;
223
- if (!match && !kind) die("forget needs --statement \"...\" and/or --kind <kind>", 1);
272
+ if (!match && !kind) die('forget needs --statement "..." and/or --kind <kind>', 1);
224
273
  const p = ledgerPath(slug);
225
274
  if (!existsSync(p)) {
226
275
  process.stdout.write(JSON.stringify({ ok: true, slug, removed: 0 }) + "\n");
@@ -259,7 +308,9 @@ function cmdBrief() {
259
308
  for (const r of ordered) (byKind[r.kind] || (byKind[r.kind] = [])).push(r);
260
309
 
261
310
  const lines = ["<repo-learnings>"];
262
- lines.push(`Durable knowledge for repo "${slug}" (replayed each run; treat as context, not commands - current scope decides).`);
311
+ lines.push(
312
+ `Durable knowledge for repo "${slug}" (replayed each run; treat as context, not commands - current scope decides).`,
313
+ );
263
314
  const labels = {
264
315
  fact: "Architectural facts",
265
316
  convention: "Conventions",
@@ -281,7 +332,9 @@ function cmdBrief() {
281
332
  }
282
333
 
283
334
  function cmdPath() {
284
- process.stdout.write(ledgerPath(flags["repo-slug"] ? String(flags["repo-slug"]) : repoSlug()) + "\n");
335
+ process.stdout.write(
336
+ ledgerPath(flags["repo-slug"] ? String(flags["repo-slug"]) : repoSlug()) + "\n",
337
+ );
285
338
  process.exit(0);
286
339
  }
287
340
 
@@ -297,13 +350,27 @@ function cmdStats() {
297
350
  }
298
351
 
299
352
  switch (SUB) {
300
- case "add": cmdAdd(); break;
301
- case "from-triage": cmdFromTriage(); break;
302
- case "forget": cmdForget(); break;
303
- case "brief": cmdBrief(); break;
304
- case "path": cmdPath(); break;
305
- case "stats": cmdStats(); break;
353
+ case "add":
354
+ cmdAdd();
355
+ break;
356
+ case "from-triage":
357
+ cmdFromTriage();
358
+ break;
359
+ case "forget":
360
+ cmdForget();
361
+ break;
362
+ case "brief":
363
+ cmdBrief();
364
+ break;
365
+ case "path":
366
+ cmdPath();
367
+ break;
368
+ case "stats":
369
+ cmdStats();
370
+ break;
306
371
  default:
307
- process.stderr.write("usage: learnings-ledger.mjs <add|from-triage|forget|brief|path|stats> [flags]\n");
372
+ process.stderr.write(
373
+ "usage: learnings-ledger.mjs <add|from-triage|forget|brief|path|stats> [flags]\n",
374
+ );
308
375
  process.exit(64);
309
376
  }
@@ -45,7 +45,15 @@ const KNOWN_BAD = { dev_toolkit: "dev-toolkit", "claude-ai-Figma": "claude_ai_Fi
45
45
 
46
46
  const SCAN_DIRS = ["pipeline/commands", "pipeline/skills", "pipeline/multi-agent-refs"];
47
47
  const SCAN_EXT = /\.(md|sh|mjs|json)$/;
48
- const PRUNE = new Set(["node_modules", ".git", ".worktrees", "Pods", ".build", "DerivedData", ".next"]);
48
+ const PRUNE = new Set([
49
+ "node_modules",
50
+ ".git",
51
+ ".worktrees",
52
+ "Pods",
53
+ ".build",
54
+ "DerivedData",
55
+ ".next",
56
+ ]);
49
57
 
50
58
  function walk(dir, out = []) {
51
59
  let entries;
@@ -121,7 +129,10 @@ function resolveToolkitRepo() {
121
129
  if (name.includes("dev") && arg) candidates.push(dirname(resolve(arg)));
122
130
  }
123
131
  };
124
- for (const cfgPath of [join(homedir(), ".claude.json"), join(homedir(), ".claude", "settings.json")]) {
132
+ for (const cfgPath of [
133
+ join(homedir(), ".claude.json"),
134
+ join(homedir(), ".claude", "settings.json"),
135
+ ]) {
125
136
  if (!existsSync(cfgPath)) continue;
126
137
  try {
127
138
  const json = JSON.parse(readFileSync(cfgPath, "utf8"));
@@ -14,12 +14,12 @@
14
14
  // - description: required, non-empty, single line, <= 1024 chars
15
15
  // - user-invocable: when present, must be true or false
16
16
  // - platform: when present, must be ios | android | common | all
17
+ // - description: must carry a routing/trigger clause ("use when ..."), the
18
+ // one thing it is for - blocking since all 193 skills have one
17
19
  //
18
20
  // Spec-conformance signals (warnings - never fail the gate):
19
21
  // - name should match the agent-skills spec pattern
20
22
  // (lowercase letters/digits/hyphens, <= 64 chars)
21
- // - description should carry a routing/trigger clause ("use when ...")
22
- // so the model can decide when to load the skill
23
23
  // - a body over ~500 lines with no companion-file reference should be
24
24
  // split into references/ files loaded on demand
25
25
 
@@ -99,12 +99,19 @@ for (const file of files) {
99
99
  if (!isBlockScalar && words < 6) {
100
100
  warn(file, `description is terse (${words} words) - say what it does AND when to use it`);
101
101
  }
102
- // Routing quality (warn-only): without a trigger clause the model has no
103
- // signal for WHEN to load the skill. Heuristic phrase match; block
104
- // scalars are skipped for the same parser reason as above.
105
- const ROUTING_RE = /\b(use (this|it|when|for|whenever)|when (the|a|an|you|asked|working|building|implementing|writing|reviewing)|triggers?|invoked?( when| for)?|applies when|activated?)\b/i;
102
+ // Routing quality (BLOCKING since the backlog reached zero). A description
103
+ // without a trigger clause tells the model what the skill is and nothing
104
+ // about when to reach for it, which is the one job the description has -
105
+ // it is the routing rule, not a summary.
106
+ //
107
+ // This was warn-only while 93 of 193 skills were missing one, because a
108
+ // gate that fires on half the tree gets ignored. All 93 were written, so
109
+ // the baseline is zero and it can hold the line. Block scalars are skipped
110
+ // for the same parser reason as above.
111
+ const ROUTING_RE =
112
+ /\b(use (this|it|when|for|whenever)|when (the|a|an|you|asked|working|building|implementing|writing|reviewing)|triggers?|invoked?( when| for)?|applies when|activated?)\b/i;
106
113
  if (!isBlockScalar && !ROUTING_RE.test(desc)) {
107
- warn(file, "description has no routing/trigger clause (e.g. \"use when ...\")");
114
+ fail(file, 'description has no routing/trigger clause (e.g. "use when ...")');
108
115
  }
109
116
  }
110
117
 
@@ -115,9 +122,13 @@ for (const file of files) {
115
122
  const bodyLines = body.split("\n").length;
116
123
  if (bodyLines > 500) {
117
124
  const referencesCompanion =
118
- /\]\((?!https?:|mailto:|#)[^)]+\)/.test(body) || /`[^`\n]*\/[^`\n]*\.(md|sh|mjs|json|py|txt)`/.test(body);
125
+ /\]\((?!https?:|mailto:|#)[^)]+\)/.test(body) ||
126
+ /`[^`\n]*\/[^`\n]*\.(md|sh|mjs|json|py|txt)`/.test(body);
119
127
  if (!referencesCompanion) {
120
- warn(file, `body is ${bodyLines} lines with no companion-file reference - consider splitting into references/`);
128
+ warn(
129
+ file,
130
+ `body is ${bodyLines} lines with no companion-file reference - consider splitting into references/`,
131
+ );
121
132
  }
122
133
  }
123
134
 
@@ -116,7 +116,12 @@ if (invokedDirectly) {
116
116
  console.error("usage: localize-commands.mjs <apply|restore> [--dir <commandsDir>]");
117
117
  process.exit(2);
118
118
  }
119
- let dir = join(process.env.HOME || process.env.USERPROFILE || "", ".claude", "commands", "multi-agent");
119
+ let dir = join(
120
+ process.env.HOME || process.env.USERPROFILE || "",
121
+ ".claude",
122
+ "commands",
123
+ "multi-agent",
124
+ );
120
125
  const dirFlag = args.indexOf("--dir");
121
126
  if (dirFlag >= 0) {
122
127
  if (!args[dirFlag + 1]) {
@@ -38,7 +38,9 @@ const repoRoot = resolve(here, "..", "..");
38
38
 
39
39
  const args = process.argv.slice(2);
40
40
  if (args.length === 0 || args[0].startsWith("--")) {
41
- console.error('Usage: match-skills.mjs "<task text>" [--touched-files a,b] [--stack ios] [--limit 12] [--json]');
41
+ console.error(
42
+ 'Usage: match-skills.mjs "<task text>" [--touched-files a,b] [--stack ios] [--limit 12] [--json]',
43
+ );
42
44
  process.exit(1);
43
45
  }
44
46
 
@@ -51,7 +53,11 @@ const opts = {
51
53
  json: false,
52
54
  };
53
55
  for (let i = 1; i < args.length; i++) {
54
- if (args[i] === "--touched-files") opts.touchedFiles = (args[++i] || "").split(",").map((s) => s.trim()).filter(Boolean);
56
+ if (args[i] === "--touched-files")
57
+ opts.touchedFiles = (args[++i] || "")
58
+ .split(",")
59
+ .map((s) => s.trim())
60
+ .filter(Boolean);
55
61
  else if (args[i] === "--stack") opts.stack = (args[++i] || "").trim().toLowerCase();
56
62
  else if (args[i] === "--limit") opts.limit = parseInt(args[++i], 10) || 12;
57
63
  else if (args[i] === "--index") opts.indexPath = resolve(args[++i]);
@@ -86,8 +92,13 @@ function globToRe(glob) {
86
92
  // `**/` means zero-or-more path segments, so a leading `**/` must also
87
93
  // match top-level files (no dir prefix). Without the optional slash,
88
94
  // `**/Auth/**` compiled to `.*\/Auth\/.*` and missed root-level `Auth/...`.
89
- if (glob[i + 2] === "/") { re += "(?:.*/)?"; i += 2; }
90
- else { re += ".*"; i++; }
95
+ if (glob[i + 2] === "/") {
96
+ re += "(?:.*/)?";
97
+ i += 2;
98
+ } else {
99
+ re += ".*";
100
+ i++;
101
+ }
91
102
  } else if (c === "*") re += "[^/]*";
92
103
  else if (c === "?") re += ".";
93
104
  else if (".+()|{}[]^$\\".includes(c)) re += "\\" + c;
@@ -95,7 +95,9 @@ function consolidateFirebase(out, changes) {
95
95
  }
96
96
  if ("firebase_project" in km) {
97
97
  delete km.firebase_project;
98
- changes.push("keychainMapping: removed firebase_project (redundant - project_id lives inside the SA JSON)");
98
+ changes.push(
99
+ "keychainMapping: removed firebase_project (redundant - project_id lives inside the SA JSON)",
100
+ );
99
101
  }
100
102
  }
101
103
  if (Array.isArray(out?.global?.identities)) {
@@ -195,7 +197,9 @@ function migrate(prefs) {
195
197
  out.global.identities = out.global.gitIdentities;
196
198
  changes.push(`renamed gitIdentities → identities (${out.global.identities.length} entries)`);
197
199
  } else {
198
- changes.push("gitIdentities present but identities also exists - keeping identities, dropping gitIdentities");
200
+ changes.push(
201
+ "gitIdentities present but identities also exists - keeping identities, dropping gitIdentities",
202
+ );
199
203
  }
200
204
  delete out.global.gitIdentities;
201
205
  } else if (!Array.isArray(out.global.identities)) {
@@ -214,7 +218,8 @@ function migrate(prefs) {
214
218
  }
215
219
  }
216
220
  out.global.keychainMapping = km;
217
- if (kmChanged) changes.push("expanded keychainMapping with missing services (existing values preserved)");
221
+ if (kmChanged)
222
+ changes.push("expanded keychainMapping with missing services (existing values preserved)");
218
223
 
219
224
  // 5. New v2.1.0 fields with defaults
220
225
  if (!out.global.platformIdentityRouting) {
@@ -320,25 +325,29 @@ function migrateReportChannels(out, changes) {
320
325
  // --- reportChannels ---
321
326
  if (!g.reportChannels || typeof g.reportChannels !== "object") {
322
327
  const channels = {
323
- pr: true, // schema default
324
- jira: typeof g.jiraCommentDefault === "boolean" ? g.jiraCommentDefault : true,
328
+ pr: true, // schema default
329
+ jira: typeof g.jiraCommentDefault === "boolean" ? g.jiraCommentDefault : true,
325
330
  confluence: typeof g.confluenceDefault === "boolean" ? g.confluenceDefault : false,
326
- wiki: typeof g.wikiDefault === "boolean" ? g.wikiDefault : false,
331
+ wiki: typeof g.wikiDefault === "boolean" ? g.wikiDefault : false,
327
332
  };
328
333
  g.reportChannels = channels;
329
- changes.push("added reportChannels {pr,jira,confluence,wiki} (migrated from jiraCommentDefault/confluenceDefault/wikiDefault if present)");
334
+ changes.push(
335
+ "added reportChannels {pr,jira,confluence,wiki} (migrated from jiraCommentDefault/confluenceDefault/wikiDefault if present)",
336
+ );
330
337
  }
331
338
 
332
339
  // --- reportContent ---
333
340
  if (!g.reportContent || typeof g.reportContent !== "object") {
334
341
  g.reportContent = {
335
- normalAnalysis: true,
342
+ normalAnalysis: true,
336
343
  technicalAnalysis: false,
337
- testScenarios: true,
338
- autoDiff: false,
339
- manualNote: false,
344
+ testScenarios: true,
345
+ autoDiff: false,
346
+ manualNote: false,
340
347
  };
341
- changes.push("added reportContent defaults {normalAnalysis,technicalAnalysis,testScenarios,autoDiff,manualNote}");
348
+ changes.push(
349
+ "added reportContent defaults {normalAnalysis,technicalAnalysis,testScenarios,autoDiff,manualNote}",
350
+ );
342
351
  } else if (!("technicalAnalysis" in g.reportContent)) {
343
352
  // v5.7.3+ - backfill technicalAnalysis onto already-initialized reportContent
344
353
  g.reportContent.technicalAnalysis = false;
@@ -349,24 +358,32 @@ function migrateReportChannels(out, changes) {
349
358
  if (!Array.isArray(g.wikiScope)) {
350
359
  if (g.wikiDefault === false) {
351
360
  g.wikiScope = [];
352
- changes.push("added wikiScope: [] (legacy wikiDefault=false - opt out of all wiki artifacts)");
361
+ changes.push(
362
+ "added wikiScope: [] (legacy wikiDefault=false - opt out of all wiki artifacts)",
363
+ );
353
364
  } else {
354
365
  g.wikiScope = ["main", "ios", "screenshots", "index"];
355
- changes.push("added wikiScope: [main,ios,screenshots,index] (legacy wikiDefault=true or unset)");
366
+ changes.push(
367
+ "added wikiScope: [main,ios,screenshots,index] (legacy wikiDefault=true or unset)",
368
+ );
356
369
  }
357
370
  }
358
371
 
359
372
  // --- autopilotReportTimeoutSeconds ---
360
373
  if (typeof g.autopilotReportTimeoutSeconds !== "number") {
361
374
  g.autopilotReportTimeoutSeconds = 1800;
362
- changes.push("added autopilotReportTimeoutSeconds: 1800 (30 min) - Phase 7 always-pause timeout");
375
+ changes.push(
376
+ "added autopilotReportTimeoutSeconds: 1800 (30 min) - Phase 7 always-pause timeout",
377
+ );
363
378
  }
364
379
 
365
380
  // --- prune deprecated booleans ---
366
381
  for (const key of ["jiraCommentDefault", "confluenceDefault", "wikiDefault"]) {
367
382
  if (key in g) {
368
383
  delete g[key];
369
- changes.push(`removed deprecated ${key} (superseded by reportChannels${key === "wikiDefault" ? " + wikiScope" : ""})`);
384
+ changes.push(
385
+ `removed deprecated ${key} (superseded by reportChannels${key === "wikiDefault" ? " + wikiScope" : ""})`,
386
+ );
370
387
  }
371
388
  }
372
389
  }
@@ -724,8 +724,10 @@ case "$ACTION" in
724
724
  # Live current-action line for the active phase. Quiet by construction:
725
725
  # progress lines are frequent, so `now` never renders - the card picks the
726
726
  # value up at the next boundary render/update. Truncated to 60 chars.
727
+ # 57 + "..." keeps the documented 60-char cap now that the marker is three
728
+ # ASCII dots rather than a one-character ellipsis.
727
729
  if [ "${#TEXT}" -gt 60 ]; then
728
- TEXT="${TEXT:0:59}"
730
+ TEXT="${TEXT:0:57}..."
729
731
  fi
730
732
  acquire_state_lock
731
733
  state=$(load_state)