session-orchestrator 3.23.0 → 4.0.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 (393) hide show
  1. package/.agents/skills/architecture/SKILL.md +18 -0
  2. package/.agents/skills/autopilot/SKILL.md +17 -0
  3. package/.agents/skills/bootstrap/SKILL.md +20 -0
  4. package/.agents/skills/brainstorm/SKILL.md +22 -0
  5. package/.agents/skills/claude-md-drift-check/SKILL.md +15 -0
  6. package/.agents/skills/convergence-monitoring/SKILL.md +22 -0
  7. package/.agents/skills/debug/SKILL.md +22 -0
  8. package/.agents/skills/discovery/SKILL.md +20 -0
  9. package/.agents/skills/dispatcher/SKILL.md +15 -0
  10. package/.agents/skills/docs-orchestrator/SKILL.md +18 -0
  11. package/.agents/skills/ecosystem-health/SKILL.md +20 -0
  12. package/.agents/skills/eli5/SKILL.md +20 -0
  13. package/.agents/skills/eval/SKILL.md +21 -0
  14. package/.agents/skills/evolve/SKILL.md +21 -0
  15. package/.agents/skills/frontmatter-guard/SKILL.md +15 -0
  16. package/.agents/skills/gitlab-ops/SKILL.md +20 -0
  17. package/.agents/skills/gitlab-portfolio/SKILL.md +15 -0
  18. package/.agents/skills/grill/SKILL.md +22 -0
  19. package/.agents/skills/hook-development/SKILL.md +15 -0
  20. package/.agents/skills/mcp-builder/SKILL.md +15 -0
  21. package/.agents/skills/memory-cleanup/SKILL.md +21 -0
  22. package/.agents/skills/mode-selector/SKILL.md +17 -0
  23. package/.agents/skills/npm-publish/SKILL.md +16 -0
  24. package/.agents/skills/peekaboo-driver/SKILL.md +18 -0
  25. package/.agents/skills/persona-panel/SKILL.md +17 -0
  26. package/.agents/skills/plan/SKILL.md +20 -0
  27. package/.agents/skills/playwright-driver/SKILL.md +20 -0
  28. package/.agents/skills/quality-gates/SKILL.md +20 -0
  29. package/.agents/skills/reconcile/SKILL.md +21 -0
  30. package/.agents/skills/remote-offload/SKILL.md +20 -0
  31. package/.agents/skills/repo-audit/SKILL.md +16 -0
  32. package/.agents/skills/session-end/SKILL.md +20 -0
  33. package/.agents/skills/session-plan/SKILL.md +20 -0
  34. package/.agents/skills/session-start/SKILL.md +20 -0
  35. package/.agents/skills/spinout/SKILL.md +16 -0
  36. package/.agents/skills/sunset-review/SKILL.md +16 -0
  37. package/.agents/skills/test-runner/SKILL.md +20 -0
  38. package/.agents/skills/tmux-layout/SKILL.md +21 -0
  39. package/.agents/skills/using-orchestrator/SKILL.md +17 -0
  40. package/.agents/skills/vault-mirror/SKILL.md +15 -0
  41. package/.agents/skills/vault-sync/SKILL.md +15 -0
  42. package/.agents/skills/wave-executor/SKILL.md +20 -0
  43. package/.agents/skills/write-executable-plan/SKILL.md +22 -0
  44. package/.claude-plugin/marketplace.json +1 -1
  45. package/.claude-plugin/plugin.json +1 -1
  46. package/.codex-plugin/plugin.json +1 -1
  47. package/.cursor/commands/autopilot.md +2 -2
  48. package/.cursor/commands/bootstrap.md +1 -1
  49. package/.cursor/commands/brainstorm.md +1 -1
  50. package/.cursor/commands/debug.md +1 -1
  51. package/.cursor/commands/discovery.md +1 -1
  52. package/.cursor/commands/dispatcher.md +2 -2
  53. package/.cursor/commands/eli5.md +2 -2
  54. package/.cursor/commands/eval.md +2 -2
  55. package/.cursor/commands/evolve.md +1 -1
  56. package/.cursor/commands/go.md +1 -1
  57. package/.cursor/commands/grill.md +2 -2
  58. package/.cursor/commands/memory-cleanup.md +2 -2
  59. package/.cursor/commands/persona-panel.md +1 -1
  60. package/.cursor/commands/plan.md +1 -1
  61. package/.cursor/commands/portfolio.md +1 -1
  62. package/.cursor/commands/reconcile.md +2 -2
  63. package/.cursor/commands/release.md +2 -2
  64. package/.cursor/commands/session.md +2 -2
  65. package/.cursor/commands/spinout.md +2 -2
  66. package/.cursor/commands/sunset-review.md +2 -2
  67. package/.cursor/commands/templates-ack.md +2 -2
  68. package/.cursor/commands/test.md +2 -2
  69. package/.cursor/skills/brainstorm/SKILL.md +1 -1
  70. package/.cursor/skills/eval/SKILL.md +1 -1
  71. package/.cursor/skills/quality-gates/SKILL.md +1 -1
  72. package/.cursor/skills/remote-offload/SKILL.md +13 -0
  73. package/.orchestrator/policy/blocked-commands.json +121 -0
  74. package/.orchestrator/policy/ecosystem.schema.json +66 -0
  75. package/.orchestrator/policy/quality-gates.example.json +16 -0
  76. package/.orchestrator/policy/quality-gates.schema.json +38 -0
  77. package/.orchestrator/policy/templates-policy.json +27 -0
  78. package/.orchestrator/policy/test-profiles.json +47 -0
  79. package/AGENTS.md +225 -0
  80. package/CHANGELOG.md +1401 -0
  81. package/NOTICE +11 -6
  82. package/README.md +127 -92
  83. package/agents/db-specialist.md +0 -1
  84. package/agents/eval-judge.md +1 -1
  85. package/agents/skill-applied-judge.md +1 -1
  86. package/assets/wave-lifecycle.svg +98 -0
  87. package/commands/release.md +6 -3
  88. package/commands/session.md +18 -3
  89. package/docs/README.md +4 -0
  90. package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
  91. package/docs/baseline.md +67 -0
  92. package/docs/ci-setup.md +249 -48
  93. package/docs/codex-setup.md +66 -22
  94. package/docs/components.md +37 -16
  95. package/docs/cursor-setup.md +6 -2
  96. package/docs/events-schema.md +51 -10
  97. package/docs/instruction-delivery.md +62 -0
  98. package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
  99. package/docs/migration-v4.md +341 -0
  100. package/docs/pi-setup.md +6 -1
  101. package/docs/plugin-architecture-v3.md +1 -1
  102. package/docs/rule-authoring.md +85 -19
  103. package/docs/scope-collision-guard.md +8 -8
  104. package/docs/session-config-reference.md +120 -61
  105. package/docs/session-config-template.md +40 -33
  106. package/docs/telemetry/telemetry-claims.md +11 -10
  107. package/docs/telemetry.md +187 -4
  108. package/docs/vault-docs-architecture.md +50 -11
  109. package/hooks/_lib/atomic-json.mjs +111 -0
  110. package/hooks/_lib/hook-import-set.json +1487 -0
  111. package/hooks/_lib/subagent-paths.mjs +143 -0
  112. package/hooks/_lib/subagent-transcript.mjs +562 -0
  113. package/hooks/config-protection.mjs +2 -2
  114. package/hooks/cwd-change-restore.mjs +11 -31
  115. package/hooks/enforce-commands.mjs +69 -0
  116. package/hooks/enforce-scope.mjs +35 -6
  117. package/hooks/hooks-codex.json +1 -1
  118. package/hooks/hooks-cursor.json +10 -0
  119. package/hooks/hooks-pi.json +5 -0
  120. package/hooks/hooks.json +6 -1
  121. package/hooks/loop-guard.mjs +3 -3
  122. package/hooks/on-session-end.mjs +280 -14
  123. package/hooks/on-session-start.mjs +153 -4
  124. package/hooks/on-stop.mjs +371 -17
  125. package/hooks/operator-steer.mjs +2 -2
  126. package/hooks/post-bash-write-verify.mjs +189 -4
  127. package/hooks/post-edit-import-probe.mjs +344 -0
  128. package/hooks/post-subagent-discovery-validator.mjs +278 -392
  129. package/hooks/post-tool-batch-wave-signal.mjs +272 -44
  130. package/hooks/post-tool-failure-corrective-context.mjs +11 -34
  131. package/hooks/post-tooluse-frontend-slop.mjs +3 -3
  132. package/hooks/pre-bash-destructive-guard.mjs +39 -13
  133. package/hooks/pre-bash-memory-propose-audit.mjs +13 -7
  134. package/hooks/skill-invocation-telemetry.mjs +17 -5
  135. package/hooks/subagent-telemetry.mjs +24 -30
  136. package/monitors/monitors.json +3 -3
  137. package/package.json +9 -1
  138. package/pi/prompts/session.md +2 -2
  139. package/plugin.json +27 -0
  140. package/scripts/autopilot.mjs +26 -12
  141. package/scripts/backfill-abandoned-sessions.mjs +130 -15
  142. package/scripts/backfill-learnings-from-vault.mjs +9 -3
  143. package/scripts/dialectic-deriver.mjs +73 -8
  144. package/scripts/emit-event.mjs +10 -2
  145. package/scripts/export-hw-learnings.mjs +113 -1
  146. package/scripts/generate-agents-skills.mjs +378 -0
  147. package/scripts/generate-cursor-adapter.mjs +45 -8
  148. package/scripts/generate-hook-import-set.mjs +249 -0
  149. package/scripts/lib/agent-status.mjs +13 -2
  150. package/scripts/lib/auq/parse.mjs +5 -29
  151. package/scripts/lib/auto-dialectic.mjs +68 -0
  152. package/scripts/lib/auto-dream.mjs +38 -36
  153. package/scripts/lib/autonomy/suitability.mjs +6 -0
  154. package/scripts/lib/autopilot/loop.mjs +2 -2
  155. package/scripts/lib/autopilot/worktree-pipeline.mjs +82 -6
  156. package/scripts/lib/build-live-signals.mjs +25 -22
  157. package/scripts/lib/ci-status-banner.mjs +220 -75
  158. package/scripts/lib/codex/plugin-contract.mjs +82 -6
  159. package/scripts/lib/cold-start-detector.mjs +23 -14
  160. package/scripts/lib/config/auto-dream.mjs +2 -1
  161. package/scripts/lib/config/block-header.mjs +63 -0
  162. package/scripts/lib/config/block-preprocess.mjs +177 -0
  163. package/scripts/lib/config/broken-window.mjs +2 -1
  164. package/scripts/lib/config/cold-start.mjs +2 -1
  165. package/scripts/lib/config/config-protection.mjs +22 -2
  166. package/scripts/lib/config/context-coverage.mjs +2 -1
  167. package/scripts/lib/config/cross-repo.mjs +2 -1
  168. package/scripts/lib/config/custom-phases.mjs +2 -1
  169. package/scripts/lib/config/dialectic.mjs +2 -1
  170. package/scripts/lib/config/discovery-validator.mjs +9 -3
  171. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
  172. package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
  173. package/scripts/lib/config/docs-orchestrator.mjs +2 -1
  174. package/scripts/lib/config/docs-staleness.mjs +2 -1
  175. package/scripts/lib/config/drift-check.mjs +2 -1
  176. package/scripts/lib/config/eval.mjs +2 -1
  177. package/scripts/lib/config/events-rotation.mjs +2 -1
  178. package/scripts/lib/config/evolve.mjs +8 -2
  179. package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
  180. package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
  181. package/scripts/lib/config/handover-gate.mjs +2 -1
  182. package/scripts/lib/config/health-endpoints.mjs +388 -0
  183. package/scripts/lib/config/issue-budget.mjs +2 -1
  184. package/scripts/lib/config/loop-guard.mjs +2 -1
  185. package/scripts/lib/config/memory.mjs +2 -1
  186. package/scripts/lib/config/moc-staleness.mjs +2 -1
  187. package/scripts/lib/config/persona-gate-wave.mjs +2 -1
  188. package/scripts/lib/config/private-config-dir.mjs +67 -0
  189. package/scripts/lib/config/reconcile.mjs +2 -1
  190. package/scripts/lib/config/remote-hosts.mjs +234 -0
  191. package/scripts/lib/config/section-extractor.mjs +7 -1
  192. package/scripts/lib/config/skill-evolution.mjs +2 -1
  193. package/scripts/lib/config/slopcheck.mjs +2 -1
  194. package/scripts/lib/config/state-md-lock.mjs +2 -1
  195. package/scripts/lib/config/templates-first.mjs +2 -1
  196. package/scripts/lib/config/test.mjs +2 -1
  197. package/scripts/lib/config/vault-integration.mjs +7 -1
  198. package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
  199. package/scripts/lib/config/vault-staleness.mjs +2 -1
  200. package/scripts/lib/config/vault-sync.mjs +2 -1
  201. package/scripts/lib/config/verification-auto-fix.mjs +2 -1
  202. package/scripts/lib/config/wave-reviewers.mjs +2 -1
  203. package/scripts/lib/config/worktree-orphans.mjs +2 -1
  204. package/scripts/lib/config.mjs +31 -3
  205. package/scripts/lib/convergence-monitor.mjs +82 -16
  206. package/scripts/lib/dispatcher/enumerate.mjs +2 -17
  207. package/scripts/lib/dispatcher/rank.mjs +124 -48
  208. package/scripts/lib/ecosystem-health.mjs +16 -2
  209. package/scripts/lib/eval/engine.mjs +9 -1
  210. package/scripts/lib/eval/session-resolve.mjs +23 -4
  211. package/scripts/lib/events-schema.mjs +48 -0
  212. package/scripts/lib/events.mjs +256 -7
  213. package/scripts/lib/evolve/autonomy-verdict.mjs +9 -4
  214. package/scripts/lib/evolve/autopilot-effectiveness.mjs +18 -1
  215. package/scripts/lib/frontmatter-guard.mjs +131 -13
  216. package/scripts/lib/gates/gate-full.mjs +26 -0
  217. package/scripts/lib/gates/gate-helpers.mjs +76 -0
  218. package/scripts/lib/gitlab-portfolio/cli.mjs +3 -15
  219. package/scripts/lib/hardware-pattern-detector.mjs +18 -1
  220. package/scripts/lib/harness-audit/categories/category1.mjs +17 -6
  221. package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
  222. package/scripts/lib/host-identity.mjs +50 -11
  223. package/scripts/lib/instruction-budget-guard.mjs +171 -5
  224. package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
  225. package/scripts/lib/learnings/io.mjs +60 -6
  226. package/scripts/lib/memory-banner.mjs +20 -8
  227. package/scripts/lib/memory-proposals/store.mjs +30 -22
  228. package/scripts/lib/owner-config-banner.mjs +43 -6
  229. package/scripts/lib/owner-config-loader.mjs +21 -10
  230. package/scripts/lib/owner-interview.mjs +3 -3
  231. package/scripts/lib/owner-yaml.mjs +207 -14
  232. package/scripts/lib/peer-discovery.mjs +20 -2
  233. package/scripts/lib/platform.mjs +108 -15
  234. package/scripts/lib/plugin-update-banner.mjs +406 -0
  235. package/scripts/lib/project-hygiene.mjs +38 -2
  236. package/scripts/lib/qg-command-drift-banner.mjs +50 -12
  237. package/scripts/lib/quality-gate.mjs +133 -44
  238. package/scripts/lib/reconcile/emitter.mjs +68 -6
  239. package/scripts/lib/reconcile/engine.mjs +249 -9
  240. package/scripts/lib/reconcile/idempotency.mjs +37 -4
  241. package/scripts/lib/reconcile/writer.mjs +40 -18
  242. package/scripts/lib/scope-gate.mjs +36 -0
  243. package/scripts/lib/session-close-backfill.mjs +125 -18
  244. package/scripts/lib/session-discovery.mjs +57 -3
  245. package/scripts/lib/session-end/phase-skip.mjs +2 -2
  246. package/scripts/lib/session-id.mjs +12 -23
  247. package/scripts/lib/session-identity/own-session.mjs +187 -11
  248. package/scripts/lib/session-lock-shape.mjs +43 -0
  249. package/scripts/lib/session-lock.mjs +5 -10
  250. package/scripts/lib/session-registry.mjs +25 -9
  251. package/scripts/lib/session-schema/constants.mjs +36 -2
  252. package/scripts/lib/session-schema/validator.mjs +38 -4
  253. package/scripts/lib/session-start-probes.mjs +18 -1
  254. package/scripts/lib/session-transition.mjs +1 -1
  255. package/scripts/lib/sessions-canonical.mjs +446 -0
  256. package/scripts/lib/sessions-staleness-banner.mjs +18 -11
  257. package/scripts/lib/skill-health/join.mjs +17 -4
  258. package/scripts/lib/state-md.mjs +78 -0
  259. package/scripts/lib/sunset/walker.mjs +6 -0
  260. package/scripts/lib/telemetry/schema.mjs +255 -17
  261. package/scripts/lib/telemetry/sync.mjs +417 -24
  262. package/scripts/lib/tmux-layout/telemetry.mjs +14 -2
  263. package/scripts/lib/validate/check-agents-skills.mjs +327 -0
  264. package/scripts/lib/validate/check-agents.mjs +3 -3
  265. package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
  266. package/scripts/lib/validate/check-doc-cli-commands.mjs +9 -33
  267. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +370 -0
  268. package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
  269. package/scripts/lib/validate/check-owner-leakage.mjs +281 -20
  270. package/scripts/lib/validate/check-skill-links.mjs +163 -0
  271. package/scripts/lib/validate/check-skill-script-paths.mjs +455 -0
  272. package/scripts/lib/validate/check-untracked-test-deps.mjs +10 -0
  273. package/scripts/lib/validate/check-unwired-features.mjs +0 -9
  274. package/scripts/lib/validate/check-validator-registration.mjs +254 -0
  275. package/scripts/lib/validate/check-vcs-repo-flag.mjs +6 -28
  276. package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
  277. package/scripts/lib/validate/markdown-fences.mjs +196 -0
  278. package/scripts/lib/vault-backfill/template.mjs +63 -6
  279. package/scripts/lib/vault-mirror/process.mjs +165 -42
  280. package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
  281. package/scripts/lib/vault-status/board-lock.mjs +185 -0
  282. package/scripts/lib/vault-status/board-writer.mjs +174 -135
  283. package/scripts/lib/vault-status/narrative-mirror.mjs +129 -37
  284. package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
  285. package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
  286. package/scripts/lib/wave-executor/remote-dispatch.mjs +502 -0
  287. package/scripts/lib/wave-resource-gate.mjs +133 -7
  288. package/scripts/lib/wave-sizing.mjs +4 -1
  289. package/scripts/lib/wave-transcript-tail.mjs +142 -8
  290. package/scripts/materialize-wave-scope.mjs +32 -9
  291. package/scripts/memory-propose.mjs +146 -8
  292. package/scripts/migrate-cold-start-seed.mjs +4 -1
  293. package/scripts/parse-config.mjs +60 -3
  294. package/scripts/promote-vault-strict.mjs +4 -15
  295. package/scripts/release.mjs +337 -29
  296. package/scripts/repair-invalid-sessions.mjs +3 -3
  297. package/scripts/run-quality-gate.mjs +128 -11
  298. package/scripts/site-numbers.mjs +36 -4
  299. package/scripts/sweep-expired-learnings.mjs +90 -0
  300. package/scripts/sync-vault-schema.mjs +3 -1
  301. package/scripts/telemetry.mjs +2 -2
  302. package/scripts/validate-plugin.mjs +187 -0
  303. package/scripts/validate-wave-scope.mjs +28 -8
  304. package/scripts/vault-consolidate.mjs +3 -11
  305. package/scripts/vault-integration-watcher.mjs +2 -4
  306. package/scripts/vault-mirror.mjs +111 -26
  307. package/scripts/wave-scope-binding.mjs +215 -0
  308. package/skills/_shared/instruction-file-resolution.md +10 -0
  309. package/skills/_shared/parallel-aware-auq.md +31 -2
  310. package/skills/_shared/parallel-aware-preamble.md +18 -4
  311. package/skills/_shared/platform-tools.md +1 -1
  312. package/skills/_shared/state-ownership.md +1 -1
  313. package/skills/architecture/SKILL.md +7 -5
  314. package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
  315. package/skills/autopilot/SKILL.md +4 -18
  316. package/skills/claude-md-drift-check/SKILL.md +5 -1
  317. package/skills/claude-md-drift-check/checker.mjs +62 -2
  318. package/skills/convergence-monitoring/SIGNALS.md +55 -0
  319. package/skills/discovery/probes/vault-staleness.mjs +37 -13
  320. package/skills/discovery/probes-arch.md +20 -18
  321. package/skills/dispatcher/SKILL.md +3 -2
  322. package/skills/ecosystem-health/SKILL.md +4 -1
  323. package/skills/ecosystem-health/wizard.md +5 -0
  324. package/skills/evolve/SKILL.md +87 -11
  325. package/skills/frontmatter-guard/SKILL.md +11 -5
  326. package/skills/npm-publish/SKILL.md +1 -1
  327. package/skills/reconcile/SKILL.md +38 -2
  328. package/skills/remote-offload/SKILL.md +89 -0
  329. package/skills/session-end/SKILL.md +18 -905
  330. package/skills/session-end/phase-3-6-tail.md +19 -9
  331. package/skills/session-end/plan-verification.md +221 -155
  332. package/skills/session-end/references/phase-2-quality-gate.md +93 -0
  333. package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
  334. package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
  335. package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
  336. package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
  337. package/skills/session-end/references/session-summary-template.md +62 -0
  338. package/skills/session-plan/SKILL.md +49 -0
  339. package/skills/session-start/SKILL.md +41 -900
  340. package/skills/session-start/phase-8-5-express-path.md +1 -1
  341. package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
  342. package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
  343. package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
  344. package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
  345. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
  346. package/skills/session-start/references/phase-4-ssot-environment-check.md +155 -0
  347. package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
  348. package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
  349. package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
  350. package/skills/vault-sync/validator.mjs +21 -27
  351. package/skills/wave-executor/SKILL.md +16 -2
  352. package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
  353. package/skills/wave-executor/references/wave-loop-review.md +570 -0
  354. package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
  355. package/skills/wave-executor/wave-loop.md +14 -1271
  356. package/templates/_shared/journey-manifest.md +10 -6
  357. package/.cursor/commands/autopilot-multi.md +0 -14
  358. package/.cursor/commands/contract-version-bump.md +0 -14
  359. package/.cursor/commands/journey-audit.md +0 -14
  360. package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
  361. package/.cursor/skills/daily/SKILL.md +0 -12
  362. package/.cursor/skills/domain-model/SKILL.md +0 -13
  363. package/.cursor/skills/journey-audit/SKILL.md +0 -13
  364. package/.cursor/skills/skill-creator/SKILL.md +0 -13
  365. package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
  366. package/commands/autopilot-multi.md +0 -74
  367. package/commands/contract-version-bump.md +0 -28
  368. package/commands/journey-audit.md +0 -43
  369. package/pi/prompts/autopilot-multi.md +0 -12
  370. package/pi/prompts/contract-version-bump.md +0 -12
  371. package/pi/prompts/journey-audit.md +0 -12
  372. package/scripts/autopilot-multi.mjs +0 -885
  373. package/scripts/backfill-learnings-expires.mjs +0 -196
  374. package/scripts/backfill-learnings.mjs +0 -203
  375. package/scripts/fleet-instruction-scan.mjs +0 -141
  376. package/scripts/lib/autopilot/dep-graph.mjs +0 -417
  377. package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
  378. package/scripts/lib/webhook-url.mjs +0 -105
  379. package/scripts/lifecycle-sim-v6.mjs +0 -347
  380. package/scripts/migrate-learnings-jsonl.mjs +0 -189
  381. package/scripts/migrate-subagents-jsonl.mjs +0 -196
  382. package/scripts/upload-social-preview.mjs +0 -316
  383. package/skills/_shared/model-selection.md +0 -64
  384. package/skills/contract-version-bump/SKILL.md +0 -219
  385. package/skills/daily/SKILL.md +0 -222
  386. package/skills/daily/generate.sh +0 -92
  387. package/skills/daily/templates/daily.md.tpl +0 -36
  388. package/skills/journey-audit/SKILL.md +0 -269
  389. package/skills/skill-creator/SKILL.md +0 -168
  390. package/skills/ubiquitous-language/SKILL.md +0 -97
  391. package/skills/vault-sync/package-lock.json +0 -40
  392. /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
  393. /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
@@ -0,0 +1,455 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Check: every `scripts/**.mjs` path cited in `skills/`, `commands/`,
4
+ * `agents/` and `docs/` either EXISTS or is annotated as deliberately absent
5
+ * (#1176). Extended (#1187) to also cite `scripts/**.sh` and `hooks/**.sh` —
6
+ * see "## Mode: BLOCKING for `.mjs`, ADVISORY for `.sh`" below for why that
7
+ * half is advisory, not blocking. `docs/` joined `SCAN_DIRS` in #1208, after
8
+ * the 22 dead paths it carried at the time (9 `.mjs`, all ADR/reference
9
+ * prose) were annotated — see that section below for the census and why
10
+ * widening the scan root had to wait for the annotation pass, not precede it.
11
+ *
12
+ * ## Why
13
+ *
14
+ * Prose is not executed. A skill body that tells the coordinator to run
15
+ * `node scripts/lib/auto-commit.mjs` costs an operator a failed command and a
16
+ * re-derivation of what the file was supposed to do — and nothing in the
17
+ * corpus notices, because a markdown file compiles under every gate. Measured
18
+ * 2026-09-02 @ c3ab480: 237 distinct citations across the (then three) scan
19
+ * roots, 7 of them dead.
20
+ *
21
+ * ## Fences are skipped, and that is most of the answer
22
+ *
23
+ * 4 of those 7 sat inside fenced code blocks — synthetic example paths
24
+ * (`scripts/example.mjs`, `scripts/lib/a.mjs`) in a snippet demonstrating a
25
+ * command's argument shape. A fenced snippet is an illustration of a FORM, not
26
+ * a claim that a file exists, so the shared fence tracker
27
+ * (`./markdown-fences.mjs`, #1181) silences them structurally
28
+ * rather than by allowlist.
29
+ *
30
+ * ## Annotation, and why placement is a rule rather than a convenience
31
+ *
32
+ * A citation in PROSE is a claim. When the claim is deliberate — a planned file
33
+ * behind an issue, a historical path kept for narrative, an inline example —
34
+ * say so on the line:
35
+ *
36
+ * <!-- path-check: planned #214 -->
37
+ * <!-- path-check: historical -->
38
+ * <!-- path-check: example -->
39
+ *
40
+ * The marker is honoured on the SAME line as the citation, or on the line
41
+ * IMMEDIATELY above WHEN THAT LINE CITES NOTHING ITSELF — nowhere else. A line
42
+ * carrying `citation + marker` exempts only that citation; it does not reach
43
+ * down to the next line, which would silently exempt a citation nobody
44
+ * annotated. Two lines above is INERT and the citation
45
+ * still reports, which is pinned by a test. The reason is the rule
46
+ * `recurring-issue-an-exemption-marker-that-only-works-same-line-is-visually-identical-to-one-in-a-comment-block-3bff005.md`
47
+ * in `.claude/rules/`:
48
+ * a marker that reads like an exemption but changes nothing is worse than no
49
+ * marker at all, because the guard then looks wrong instead of the marker
50
+ * looking misplaced. A malformed marker (unknown class, or `planned` without a
51
+ * `#<iid>`) is itself a finding for the same reason — it must never fail silent.
52
+ *
53
+ * ## Mode: BLOCKING for `.mjs`, ADVISORY for `.sh` (#1187)
54
+ *
55
+ * Unlike `check-doc-cli-commands.mjs`, the oracle here is the repository's own
56
+ * filesystem, not a locally installed third-party binary — there is no version
57
+ * skew that could red an unrelated commit. So `.mjs` findings are `FAIL:` and
58
+ * the check returns non-zero, EXACTLY as before this module grew a second
59
+ * extension.
60
+ *
61
+ * The `.sh` half of the citation grammar (below) does not get that same
62
+ * severity by default. A #1176 repo-wide grep (`scripts/hooks` prose across
63
+ * `skills/commands/agents/docs/hooks`) found 27 distinct `.sh` citations, 21
64
+ * dead — but at the time only ONE of those 27 sat inside this checker's
65
+ * (then three) scan roots (`skills/contract-version-bump/SKILL.md:134`,
66
+ * itself arguably a cross-repo path — see the dry-run note at
67
+ * `scanSkillScriptPaths`'s `strictSh` option). The other 26 lived in `docs/`,
68
+ * which this checker did not yet scan.
69
+ *
70
+ * #1208 closed that gap in two steps, annotation before widening rather than
71
+ * the reverse: first, a `dirs: ['docs']` re-scan (530 citations, 66 files)
72
+ * found 50 findings — 22 unique dead paths (9 `.mjs`, 15 `.sh`) across
73
+ * 24 (file, path) pairs, concentrated in `docs/adr/*.md` (ADR prose citing
74
+ * not-yet-built modules like `scripts/lib/tool-adapter.mjs`) and
75
+ * `docs/changelog/v2.md` (23 `.sh` citations to the pre-`.mjs`-migration
76
+ * shell scripts, #218/#317 — historical by construction). Every one of the
77
+ * 22 was annotated (`planned #<iid>` for the ADR gaps, `historical` for the
78
+ * changelog, `example` for the one illustrative path in
79
+ * `docs/scope-collision-guard.md`) — zero of them were real defects. Only
80
+ * then did `SCAN_DIRS` gain `'docs'`, so the widening added zero new
81
+ * BLOCKING findings on arrival (re-verify: `scanSkillScriptPaths({
82
+ * pluginRoot, dirs: ['docs'] })` → `ok: true`, `findings: 0`). The wider
83
+ * `hooks/` `.sh` prose census (26 of the 27 `.sh` citations above are outside
84
+ * `SCAN_DIRS` even now, since `hooks/` prose itself is not a scanned root)
85
+ * remains a follow-up for whoever owns those files.
86
+ *
87
+ * A `.sh` finding is therefore `WARN:` by default (visible, never blocking —
88
+ * `ok` and the CLI exit code ignore `severity: 'warn'` findings) and only
89
+ * becomes `FAIL:`/blocking under the `--strict-sh` CLI flag (or
90
+ * `strictSh: true` for `scanSkillScriptPaths()` callers) — flip that default
91
+ * once the dead `.sh` citations this checker CAN see are fixed by their doc
92
+ * owner (BV-004 revisit trigger). `--strict-sh` gained a validate-plugin run
93
+ * surface in #1208 (advisory, non-blocking — see `scripts/validate-plugin.mjs`
94
+ * near its `check-skill-script-paths.mjs` call).
95
+ *
96
+ * @module scripts/lib/validate/check-skill-script-paths
97
+ */
98
+
99
+ import { existsSync, readFileSync } from 'node:fs';
100
+ import path from 'node:path';
101
+ import { pathToFileURL } from 'node:url';
102
+ import { enumerateRepoFiles } from './enumerate-repo-files.mjs';
103
+ import { forEachLine } from './markdown-fences.mjs';
104
+
105
+ /** Documentation roots whose prose is treated as a claim about the repo. */
106
+ export const SCAN_DIRS = Object.freeze(['skills', 'commands', 'agents', 'docs']);
107
+
108
+ /**
109
+ * A cited script path. One regex, one alternation, reused for every
110
+ * extension rather than a second scanner (#1187): `scripts/**.mjs` (the
111
+ * original, still the only `.mjs` root scanned), `scripts/**.sh` and
112
+ * `hooks/**.sh`. `hooks/**.mjs` is deliberately NOT part of this grammar —
113
+ * the `.mjs` half of the citation surface stays exactly `scripts/`, matching
114
+ * every existing annotation and fence-skip test unchanged.
115
+ */
116
+ const CITATION_RE = /scripts\/[a-zA-Z0-9_/-]*\.(?:mjs|sh)|hooks\/[a-zA-Z0-9_/-]*\.sh/g;
117
+
118
+ /**
119
+ * Filename fragments that mark a citation as an ILLUSTRATIVE placeholder —
120
+ * `scripts/example.sh`, `hooks/my-hook.sh`, `scripts/<name>.sh` — rather than
121
+ * a claim that a real file exists. Checked only for a citation that already
122
+ * failed `existsSync` (a real file is never suppressed by this list, no
123
+ * matter what it's named). Recognised automatically, with no marker needed,
124
+ * because #1176 found 6 such `hooks/*.mjs` example names in hook-development
125
+ * prose (`hooks/example.mjs`, `guard.mjs`, `my-hook.mjs`, …) that would
126
+ * otherwise all need a hand-written `<!-- path-check: example -->` on every
127
+ * occurrence.
128
+ *
129
+ * Ceiling (BV-004): exactly these six fragments, case-insensitive substring
130
+ * match. A REAL path that happens to contain one of them (`scripts/lib/
131
+ * foobar-report.mjs`, `hooks/my-guard.sh`) is indistinguishable from a
132
+ * placeholder by this heuristic and would be silently swallowed if it were
133
+ * ever cited before being created. Revisit by shrinking this list (never
134
+ * growing it further) the moment that collision is observed for real — the
135
+ * escape hatch until then is the same `<!-- path-check: planned #<iid> -->`
136
+ * marker every other deliberate citation already uses.
137
+ */
138
+ const PLACEHOLDER_FRAGMENTS = Object.freeze(['example', 'my-', '<', 'placeholder', 'foo', 'bar']);
139
+
140
+ /**
141
+ * Is `citedPath` an illustrative placeholder name rather than a real path?
142
+ *
143
+ * @param {string} citedPath
144
+ * @returns {boolean}
145
+ */
146
+ export function isPlaceholderCitation(citedPath) {
147
+ const lower = citedPath.toLowerCase();
148
+ return PLACEHOLDER_FRAGMENTS.some((fragment) => lower.includes(fragment));
149
+ }
150
+
151
+ /** The annotation marker, in any of its three classes. */
152
+ const ANNOTATION_RE = /<!--\s*path-check:\s*([^>]*?)\s*-->/;
153
+
154
+ /**
155
+ * Judge one annotation payload.
156
+ *
157
+ * @param {string} payload the text between `path-check:` and `-->`
158
+ * @returns {{ok: boolean, class: string}}
159
+ */
160
+ export function classifyAnnotation(payload) {
161
+ const text = payload.trim();
162
+ if (text === 'historical' || text === 'example') return { ok: true, class: text };
163
+ const planned = text.match(/^planned\s+#(\d+)$/);
164
+ if (planned) return { ok: true, class: `planned #${planned[1]}` };
165
+ return { ok: false, class: text };
166
+ }
167
+
168
+ /**
169
+ * Split a markdown body into citations and annotations, both OUTSIDE fences.
170
+ *
171
+ * The fence automaton is `./markdown-fences.mjs` (#1181 — one tracker
172
+ * shared with `check-doc-cli-commands.mjs` and
173
+ * `check-vcs-repo-flag.mjs`): a fence opens on ``` / ~~~ with an optional
174
+ * info string and closes on the same character, at least as long, with no
175
+ * info string.
176
+ *
177
+ * Two properties are load-bearing because the automaton fails OPEN:
178
+ *
179
+ * 1. A fence that never closes swallows the whole rest of the file. That is a
180
+ * doc defect in its own right (`unbalanced-fence`), so it is REPORTED —
181
+ * and the swallowed tail is re-read as prose, so a dead citation hiding
182
+ * behind the unmatched opener still surfaces instead of being silenced by
183
+ * the very defect that made it invisible. Measured on
184
+ * `agents/db-specialist.md`, where a stray closing fence opened a block
185
+ * that ran to EOF and blinded the last 41 lines.
186
+ * 2. A fence inside a blockquote (`> ```) is a fence. Without stripping the
187
+ * `>` chain first, a quoted fenced example is read as prose and its
188
+ * illustrative paths are reported — a false red, the fail-CLOSED mirror of
189
+ * the same blind spot.
190
+ *
191
+ * @param {string[]} lines body split on `\n`
192
+ * @returns {{citations: {line: number, path: string}[], annotations: Map<number, {ok: boolean, class: string, raw: string}>, unbalancedFence: {line: number} | null}}
193
+ */
194
+ export function extractCitations(lines) {
195
+ /** @type {{line: number, path: string}[]} */
196
+ const citations = [];
197
+ /** @type {Map<number, {ok: boolean, class: string, raw: string}>} */
198
+ const annotations = new Map();
199
+
200
+ /**
201
+ * Read one line as prose.
202
+ *
203
+ * @param {string} raw the line
204
+ * @param {number} lineNumber its 1-based position
205
+ */
206
+ const collect = (raw, lineNumber) => {
207
+ const annotation = raw.match(ANNOTATION_RE);
208
+ if (annotation) {
209
+ annotations.set(lineNumber, { ...classifyAnnotation(annotation[1]), raw: annotation[0] });
210
+ }
211
+ for (const hit of raw.matchAll(CITATION_RE)) {
212
+ citations.push({ line: lineNumber, path: hit[0] });
213
+ }
214
+ };
215
+
216
+ // A blockquoted fence is still a fence — the shared tracker strips the `>`
217
+ // chain before detection so the quoted example's body stays fenced.
218
+ const { unbalancedFenceLine } = forEachLine(
219
+ lines.join('\n'),
220
+ (raw, { lineNumber, inFence }) => {
221
+ if (inFence) return;
222
+ collect(raw, lineNumber);
223
+ },
224
+ { stripBlockquotes: true },
225
+ );
226
+
227
+ if (unbalancedFenceLine === null) return { citations, annotations, unbalancedFence: null };
228
+
229
+ // EOF with the fence still open: never swallow silently. Re-read the tail as
230
+ // prose so the citations the defect hid are reported alongside it.
231
+ for (let index = unbalancedFenceLine; index < lines.length; index += 1) collect(lines[index], index + 1);
232
+ return { citations, annotations, unbalancedFence: { line: unbalancedFenceLine } };
233
+ }
234
+
235
+ /**
236
+ * Census the documentation corpus for dead `scripts/**.mjs`/`.sh` and
237
+ * `hooks/**.sh` citations.
238
+ *
239
+ * @param {{pluginRoot: string, dirs?: string[], strictSh?: boolean}} options
240
+ * `strictSh` (default `false`) promotes a dead `.sh` citation from
241
+ * `severity: 'warn'` to `severity: 'fail'` — see the module docblock
242
+ * "Mode: BLOCKING for `.mjs`, ADVISORY for `.sh`" for why the default stays
243
+ * advisory in this release.
244
+ * @returns {{ok: boolean, summary: object, findings: {kind: string, file: string, line: number, path: string, annotation: string | null, message: string, severity: 'fail' | 'warn'}[], toolError: boolean}}
245
+ */
246
+ export function scanSkillScriptPaths({ pluginRoot, dirs = SCAN_DIRS, strictSh = false }) {
247
+ /** @type {{kind: string, file: string, line: number, path: string, annotation: string | null, message: string, severity: 'fail' | 'warn'}[]} */
248
+ const findings = [];
249
+ const summary = {
250
+ filesScanned: 0,
251
+ citations: 0,
252
+ existing: 0,
253
+ annotated: 0,
254
+ placeholders: 0,
255
+ findings: 0,
256
+ warnings: 0,
257
+ };
258
+
259
+ /** @type {string[]} */
260
+ let files;
261
+ try {
262
+ // The population is "exists in this repo, tracked or not" (#1248) — NOT
263
+ // "is versioned". A doc that cites a dead script is a defect the moment it
264
+ // is written; the bare git index cannot see it until it is staged, so the
265
+ // check reported clean on the exact tree carrying the bug (measured: an
266
+ // untracked `skills/zz-probe/SKILL.md` → `1 passed, 0 failed` before
267
+ // `git add -A`, `0 passed, 1 failed` after). `enumerateRepoFiles` still
268
+ // honours `.gitignore`, so the #1143 exposure a bare `readdirSync` walk
269
+ // would reintroduce (a worktree under `.claude/worktrees/`, gitignored
270
+ // `docs/specs/*.md`) stays closed — see that module's header.
271
+ files = enumerateRepoFiles({ repoRoot: pluginRoot, dirs, exts: ['.md'] });
272
+ } catch (error) {
273
+ findings.push({
274
+ kind: 'tool-error',
275
+ file: '-',
276
+ line: 0,
277
+ path: '-',
278
+ annotation: null,
279
+ message: `cannot enumerate the scan corpus: ${error instanceof Error ? error.message : String(error)}`,
280
+ severity: 'fail',
281
+ });
282
+ return { ok: false, summary, findings, toolError: true };
283
+ }
284
+
285
+ for (const absolute of files) {
286
+ const relative = path.relative(pluginRoot, absolute);
287
+ /** @type {string} */
288
+ let body;
289
+ try {
290
+ body = readFileSync(absolute, 'utf8');
291
+ } catch (error) {
292
+ findings.push({
293
+ kind: 'tool-error',
294
+ file: relative,
295
+ line: 0,
296
+ path: '-',
297
+ annotation: null,
298
+ message: `cannot read: ${error instanceof Error ? error.message : String(error)}`,
299
+ severity: 'fail',
300
+ });
301
+ return { ok: false, summary, findings, toolError: true };
302
+ }
303
+ summary.filesScanned += 1;
304
+
305
+ const { citations, annotations, unbalancedFence } = extractCitations(body.split('\n'));
306
+ if (unbalancedFence) {
307
+ findings.push({
308
+ kind: 'unbalanced-fence',
309
+ file: relative,
310
+ line: unbalancedFence.line,
311
+ path: '-',
312
+ annotation: null,
313
+ message:
314
+ 'a code fence opens here and never closes — every line below it is invisible to this ' +
315
+ 'check (a fence closes only with the same character, at least as long, and no info ' +
316
+ 'string); close it or remove the stray marker',
317
+ severity: 'fail',
318
+ });
319
+ }
320
+ // Which lines carry a citation of their own. A marker that sits on such a
321
+ // line is that citation's OWN exemption and must not also reach downward.
322
+ const citedLines = new Set(citations.map((c) => c.line));
323
+
324
+ // A malformed marker is reported wherever it stands, even with nothing to
325
+ // exempt: it reads as an exemption and grants none.
326
+ for (const [line, annotation] of annotations) {
327
+ if (annotation.ok) continue;
328
+ findings.push({
329
+ kind: 'bad-annotation',
330
+ file: relative,
331
+ line,
332
+ path: '-',
333
+ annotation: annotation.raw,
334
+ message:
335
+ `malformed marker \`${annotation.raw}\` — expected \`path-check: planned #<iid>\`, ` +
336
+ '`path-check: historical` or `path-check: example`',
337
+ severity: 'fail',
338
+ });
339
+ }
340
+
341
+ for (const citation of citations) {
342
+ summary.citations += 1;
343
+ if (existsSync(path.join(pluginRoot, citation.path))) {
344
+ summary.existing += 1;
345
+ continue;
346
+ }
347
+ // An illustrative placeholder name needs no marker — see
348
+ // `isPlaceholderCitation`'s docblock for the closed fragment list and
349
+ // its named ceiling.
350
+ if (isPlaceholderCitation(citation.path)) {
351
+ summary.placeholders += 1;
352
+ continue;
353
+ }
354
+ // Same line, or the line immediately above — and the line above only
355
+ // when it carries NO citation itself. A `citation + marker` line is one
356
+ // self-contained exemption; letting it also cover the next line silently
357
+ // exempts a dead citation nobody ever annotated (the live shape at
358
+ // skills/wave-executor/wave-loop.md's `example` marker).
359
+ const above = citedLines.has(citation.line - 1)
360
+ ? undefined
361
+ : annotations.get(citation.line - 1);
362
+ const marker = annotations.get(citation.line) ?? above;
363
+ if (marker?.ok) {
364
+ summary.annotated += 1;
365
+ continue;
366
+ }
367
+ if (marker && !marker.ok) continue; // already reported as bad-annotation
368
+
369
+ // `.mjs` is blocking exactly as before this module grew a `.sh` half.
370
+ // `.sh` is advisory (`warn`) unless the caller opted into `strictSh`.
371
+ const isSh = path.extname(citation.path) === '.sh';
372
+ const severity = isSh && !strictSh ? 'warn' : 'fail';
373
+ if (severity === 'warn') summary.warnings += 1;
374
+ findings.push({
375
+ kind: 'missing-path',
376
+ file: relative,
377
+ line: citation.line,
378
+ path: citation.path,
379
+ annotation: null,
380
+ message:
381
+ (isSh
382
+ ? severity === 'warn'
383
+ ? `\`${citation.path}\` does not exist (advisory — .sh citations do not block ` +
384
+ 'validate-plugin until re-run with --strict-sh; see #1187) — '
385
+ : `\`${citation.path}\` does not exist (--strict-sh) — `
386
+ : `\`${citation.path}\` does not exist — `) +
387
+ 'create it, fix the path, or annotate the citation with ' +
388
+ '`<!-- path-check: planned #<iid> | historical | example -->` on this line or the ' +
389
+ 'line directly above',
390
+ severity,
391
+ });
392
+ }
393
+ }
394
+
395
+ findings.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
396
+ summary.findings = findings.length;
397
+ const blocking = findings.filter((f) => f.severity !== 'warn');
398
+ return { ok: blocking.length === 0, summary, findings, toolError: false };
399
+ }
400
+
401
+ /**
402
+ * Run the human-readable validator CLI.
403
+ *
404
+ * @param {string} pluginRoot absolute plugin root
405
+ * @returns {number} 0 = clean, 1 = findings, 2 = tool error
406
+ */
407
+ export function runCheckSkillScriptPaths(pluginRoot, { strictSh = false } = {}) {
408
+ console.log('--- Check: scripts/*.mjs (+ *.sh) paths cited in skills/commands/agents exist ---');
409
+ const inspection = scanSkillScriptPaths({ pluginRoot, strictSh });
410
+
411
+ for (const item of inspection.findings) {
412
+ // A `warn`-severity finding (a `.sh` citation, non-strict mode) is
413
+ // reported for visibility but must NOT print as ` FAIL:` — the
414
+ // validate-plugin aggregator counts failures by that exact 2-space
415
+ // prefix (`scripts/validate-plugin.mjs`'s `runCheck()`), so a `WARN:`
416
+ // line is how this check stays advisory end-to-end.
417
+ const label = item.severity === 'warn' ? 'WARN' : 'FAIL';
418
+ console.log(` ${label}: [${item.kind}] ${item.file}:${item.line} ${item.path} — ${item.message}`);
419
+ }
420
+ if (inspection.toolError) {
421
+ console.log('');
422
+ console.log(`Results: 0 passed, ${inspection.findings.length} failed`);
423
+ return 2;
424
+ }
425
+
426
+ const s = inspection.summary;
427
+ const blockingCount = inspection.findings.filter((f) => f.severity !== 'warn').length;
428
+ if (inspection.ok) {
429
+ console.log(
430
+ ` PASS: ${s.citations} script citation(s) in ${s.filesScanned} doc file(s) — ` +
431
+ `${s.existing} exist, ${s.annotated} annotated as deliberately absent, ` +
432
+ `${s.placeholders} placeholder(s)` +
433
+ (s.warnings > 0 ? `, ${s.warnings} advisory .sh warning(s) (see --strict-sh)` : ''),
434
+ );
435
+ }
436
+ console.log('');
437
+ console.log(`Results: ${inspection.ok ? 1 : 0} passed, ${blockingCount} failed`);
438
+ return inspection.ok ? 0 : 1;
439
+ }
440
+
441
+ const isMain = import.meta.url === pathToFileURL(process.argv[1] || '').href;
442
+ if (isMain) {
443
+ const strictSh = process.argv.includes('--strict-sh');
444
+ const args = process.argv.slice(2).filter((arg) => arg !== '--json' && arg !== '--strict-sh');
445
+ const root = path.resolve(args[0] || process.cwd());
446
+ if (process.argv.includes('--json')) {
447
+ const inspection = scanSkillScriptPaths({ pluginRoot: root, strictSh });
448
+ // Write, THEN set the exit code — `process.exit()` after a large print
449
+ // discards whatever is still queued on an async stdout pipe.
450
+ process.stdout.write(`${JSON.stringify(inspection, null, 2)}\n`);
451
+ process.exitCode = inspection.toolError ? 2 : inspection.ok ? 0 : 1;
452
+ } else {
453
+ process.exitCode = runCheckSkillScriptPaths(root, { strictSh });
454
+ }
455
+ }
@@ -695,9 +695,19 @@ export function resolveUntrackedOracle(repoRoot, candidates) {
695
695
  // directory candidates (`.git`, `.claude`, `docs/prd`, `skills/bootstrap`, …)
696
696
  // were all false. A directory can therefore only be condemned by
697
697
  // `check-ignore`, which does judge directories correctly.
698
+ //
699
+ // `.git` ALSO needs an explicit exemption from THIS FILES-ONLY branch, not
700
+ // just from the directory-only reasoning above. In a normal checkout `.git`
701
+ // is a directory and the `isFile()` guard already excludes it — but in a
702
+ // LINKED WORKTREE (`git worktree add`) `.git` is a FILE containing
703
+ // `gitdir: <path>`, which makes `existsSync() && isFile()` true and
704
+ // re-opens exactly the false-positive the comment above says is closed.
705
+ // `.git` is present in every clone/worktree by construction regardless of
706
+ // which shape it takes, so it is never a "never git-add-ed" candidate.
698
707
  for (const c of all) {
699
708
  if (untracked.has(c)) continue;
700
709
  if (tracked.has(c)) continue;
710
+ if (c === '.git') continue;
701
711
  try {
702
712
  const abs = path.join(repoRoot, c);
703
713
  if (existsSync(abs) && statSync(abs).isFile()) untracked.add(c);
@@ -302,15 +302,6 @@ const ALLOWLIST = Object.freeze({
302
302
  'prose-only consumer — skills/wave-executor/wave-loop.md gates the per-wave commit step on this key; the commit itself is a coordinator action, not a script',
303
303
  'instruction-budget':
304
304
  'dedicated reader outside the parser layer — scripts/lib/instruction-budget-guard.mjs parses this block itself (S2 exemption only; S1 evidence is real)',
305
- webhooks:
306
- 'dedicated reader outside the parser layer — scripts/lib/webhook-url.mjs resolves these URLs env-first (S2 exemption only; S1 evidence is real)',
307
- // S4 entry (module path, not a config key). The prose-only state is REAL and
308
- // recorded here BY NAME rather than left anonymous among the ~50-module S4
309
- // backlog, where a per-module expectation cannot be reviewed. Named callers
310
- // let a reviewer check the four sites; the self-draining `allowlist-stale`
311
- // rule reports this entry the day a .mjs caller makes it reachable.
312
- [path.join('scripts', 'lib', 'session-transition.mjs')]:
313
- 'prose-only consumer — leaveSourceRoot() is called by 4 skill prose sites (skills/session-start/SKILL.md:45 + :229, skills/_shared/parallel-aware-auq.md, skills/_shared/parallel-aware-preamble.md); the worktree promotion is a coordinator action, not a script (#1069)',
314
305
  });
315
306
 
316
307
  /**