session-orchestrator 3.24.0 → 4.0.1

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 (435) 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 +3 -2
  47. package/.codex-plugin/skills/architecture/SKILL.md +20 -0
  48. package/.codex-plugin/skills/autopilot/SKILL.md +21 -0
  49. package/.codex-plugin/skills/autopilot/agents/openai.yaml +5 -0
  50. package/.codex-plugin/skills/bootstrap/SKILL.md +22 -0
  51. package/.codex-plugin/skills/bootstrap/agents/openai.yaml +5 -0
  52. package/.codex-plugin/skills/brainstorm/SKILL.md +22 -0
  53. package/.codex-plugin/skills/brainstorm/agents/openai.yaml +5 -0
  54. package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +17 -0
  55. package/.codex-plugin/skills/close/SKILL.md +21 -0
  56. package/.codex-plugin/skills/close/agents/openai.yaml +5 -0
  57. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +24 -0
  58. package/.codex-plugin/skills/debug/SKILL.md +21 -0
  59. package/.codex-plugin/skills/debug/agents/openai.yaml +5 -0
  60. package/.codex-plugin/skills/discovery/SKILL.md +21 -0
  61. package/.codex-plugin/skills/discovery/agents/openai.yaml +5 -0
  62. package/.codex-plugin/skills/dispatcher/SKILL.md +21 -0
  63. package/.codex-plugin/skills/dispatcher/agents/openai.yaml +5 -0
  64. package/.codex-plugin/skills/docs-orchestrator/SKILL.md +20 -0
  65. package/.codex-plugin/skills/ecosystem-health/SKILL.md +22 -0
  66. package/.codex-plugin/skills/eli5/SKILL.md +21 -0
  67. package/.codex-plugin/skills/eli5/agents/openai.yaml +5 -0
  68. package/.codex-plugin/skills/eval/SKILL.md +21 -0
  69. package/.codex-plugin/skills/eval/agents/openai.yaml +5 -0
  70. package/.codex-plugin/skills/evolve/SKILL.md +21 -0
  71. package/.codex-plugin/skills/evolve/agents/openai.yaml +5 -0
  72. package/.codex-plugin/skills/frontmatter-guard/SKILL.md +17 -0
  73. package/.codex-plugin/skills/gitlab-ops/SKILL.md +22 -0
  74. package/.codex-plugin/skills/gitlab-portfolio/SKILL.md +17 -0
  75. package/.codex-plugin/skills/go/SKILL.md +22 -0
  76. package/.codex-plugin/skills/go/agents/openai.yaml +5 -0
  77. package/.codex-plugin/skills/grill/SKILL.md +21 -0
  78. package/.codex-plugin/skills/grill/agents/openai.yaml +5 -0
  79. package/.codex-plugin/skills/harness-audit/SKILL.md +19 -0
  80. package/.codex-plugin/skills/harness-audit/agents/openai.yaml +5 -0
  81. package/.codex-plugin/skills/hook-development/SKILL.md +17 -0
  82. package/.codex-plugin/skills/mcp-builder/SKILL.md +17 -0
  83. package/.codex-plugin/skills/memory-cleanup/SKILL.md +21 -0
  84. package/.codex-plugin/skills/memory-cleanup/agents/openai.yaml +5 -0
  85. package/.codex-plugin/skills/mode-selector/SKILL.md +19 -0
  86. package/.codex-plugin/skills/npm-publish/SKILL.md +18 -0
  87. package/.codex-plugin/skills/peekaboo-driver/SKILL.md +20 -0
  88. package/.codex-plugin/skills/persona-panel/SKILL.md +22 -0
  89. package/.codex-plugin/skills/persona-panel/agents/openai.yaml +5 -0
  90. package/.codex-plugin/skills/plan/SKILL.md +22 -0
  91. package/.codex-plugin/skills/plan/agents/openai.yaml +5 -0
  92. package/.codex-plugin/skills/playwright-driver/SKILL.md +22 -0
  93. package/.codex-plugin/skills/portfolio/SKILL.md +21 -0
  94. package/.codex-plugin/skills/portfolio/agents/openai.yaml +5 -0
  95. package/.codex-plugin/skills/quality-gates/SKILL.md +22 -0
  96. package/.codex-plugin/skills/reconcile/SKILL.md +21 -0
  97. package/.codex-plugin/skills/reconcile/agents/openai.yaml +5 -0
  98. package/.codex-plugin/skills/release/SKILL.md +22 -0
  99. package/.codex-plugin/skills/release/agents/openai.yaml +5 -0
  100. package/.codex-plugin/skills/remote-offload/SKILL.md +22 -0
  101. package/.codex-plugin/skills/repo-audit/SKILL.md +19 -0
  102. package/.codex-plugin/skills/repo-audit/agents/openai.yaml +5 -0
  103. package/.codex-plugin/skills/session/SKILL.md +21 -0
  104. package/.codex-plugin/skills/session/agents/openai.yaml +5 -0
  105. package/.codex-plugin/skills/session-end/SKILL.md +22 -0
  106. package/.codex-plugin/skills/session-plan/SKILL.md +22 -0
  107. package/.codex-plugin/skills/session-start/SKILL.md +22 -0
  108. package/.codex-plugin/skills/spinout/SKILL.md +21 -0
  109. package/.codex-plugin/skills/spinout/agents/openai.yaml +5 -0
  110. package/.codex-plugin/skills/sunset-review/SKILL.md +21 -0
  111. package/.codex-plugin/skills/sunset-review/agents/openai.yaml +5 -0
  112. package/.codex-plugin/skills/templates-ack/SKILL.md +21 -0
  113. package/.codex-plugin/skills/templates-ack/agents/openai.yaml +5 -0
  114. package/.codex-plugin/skills/test/SKILL.md +21 -0
  115. package/.codex-plugin/skills/test/agents/openai.yaml +5 -0
  116. package/.codex-plugin/skills/test-runner/SKILL.md +22 -0
  117. package/.codex-plugin/skills/tmux-layout/SKILL.md +23 -0
  118. package/.codex-plugin/skills/using-orchestrator/SKILL.md +19 -0
  119. package/.codex-plugin/skills/vault-mirror/SKILL.md +17 -0
  120. package/.codex-plugin/skills/vault-sync/SKILL.md +17 -0
  121. package/.codex-plugin/skills/wave-executor/SKILL.md +22 -0
  122. package/.codex-plugin/skills/write-executable-plan/SKILL.md +24 -0
  123. package/.cursor/commands/autopilot.md +2 -2
  124. package/.cursor/commands/bootstrap.md +1 -1
  125. package/.cursor/commands/brainstorm.md +1 -1
  126. package/.cursor/commands/debug.md +1 -1
  127. package/.cursor/commands/discovery.md +1 -1
  128. package/.cursor/commands/dispatcher.md +2 -2
  129. package/.cursor/commands/eli5.md +2 -2
  130. package/.cursor/commands/eval.md +2 -2
  131. package/.cursor/commands/evolve.md +1 -1
  132. package/.cursor/commands/go.md +1 -1
  133. package/.cursor/commands/grill.md +2 -2
  134. package/.cursor/commands/memory-cleanup.md +2 -2
  135. package/.cursor/commands/persona-panel.md +1 -1
  136. package/.cursor/commands/plan.md +1 -1
  137. package/.cursor/commands/portfolio.md +1 -1
  138. package/.cursor/commands/reconcile.md +2 -2
  139. package/.cursor/commands/release.md +2 -2
  140. package/.cursor/commands/session.md +2 -2
  141. package/.cursor/commands/spinout.md +2 -2
  142. package/.cursor/commands/sunset-review.md +2 -2
  143. package/.cursor/commands/templates-ack.md +2 -2
  144. package/.cursor/commands/test.md +2 -2
  145. package/.cursor/skills/brainstorm/SKILL.md +1 -1
  146. package/.cursor/skills/eval/SKILL.md +1 -1
  147. package/.cursor/skills/quality-gates/SKILL.md +1 -1
  148. package/.cursor/skills/remote-offload/SKILL.md +1 -1
  149. package/.cursor-plugin/plugin.json +30 -0
  150. package/.orchestrator/policy/blocked-commands.json +121 -0
  151. package/.orchestrator/policy/ecosystem.schema.json +66 -0
  152. package/.orchestrator/policy/quality-gates.example.json +16 -0
  153. package/.orchestrator/policy/quality-gates.schema.json +38 -0
  154. package/.orchestrator/policy/templates-policy.json +27 -0
  155. package/.orchestrator/policy/test-profiles.json +47 -0
  156. package/AGENTS.md +225 -0
  157. package/CHANGELOG.md +1314 -2
  158. package/NOTICE +11 -6
  159. package/README.md +135 -94
  160. package/agents/eval-judge.md +1 -1
  161. package/agents/skill-applied-judge.md +1 -1
  162. package/assets/wave-lifecycle.svg +98 -0
  163. package/commands/release.md +6 -3
  164. package/commands/session.md +18 -3
  165. package/docs/README.md +4 -0
  166. package/{agents/AGENTS.md → docs/agent-authoring.md} +19 -26
  167. package/docs/baseline.md +67 -0
  168. package/docs/ci-setup.md +108 -62
  169. package/docs/codex-setup.md +107 -29
  170. package/docs/components.md +38 -16
  171. package/docs/cursor-setup.md +6 -2
  172. package/docs/events-schema.md +9 -6
  173. package/docs/instruction-delivery.md +69 -0
  174. package/{agents/memory-proposal-collector.md → docs/memory-proposal-flow.md} +1 -8
  175. package/docs/migration-v4.md +365 -0
  176. package/docs/pi-setup.md +6 -1
  177. package/docs/plugin-architecture-v3.md +1 -1
  178. package/docs/rule-authoring.md +85 -19
  179. package/docs/scope-collision-guard.md +5 -5
  180. package/docs/session-config-reference.md +57 -56
  181. package/docs/session-config-template.md +6 -29
  182. package/docs/telemetry.md +157 -3
  183. package/docs/vault-docs-architecture.md +50 -11
  184. package/hooks/_lib/hook-import-set.json +1488 -0
  185. package/hooks/_lib/subagent-transcript.mjs +562 -0
  186. package/hooks/config-protection.mjs +2 -2
  187. package/hooks/cwd-change-restore.mjs +2 -2
  188. package/hooks/enforce-commands.mjs +69 -0
  189. package/hooks/hooks-codex.json +1 -1
  190. package/hooks/hooks-cursor.json +10 -0
  191. package/hooks/hooks-pi.json +5 -0
  192. package/hooks/hooks.json +6 -1
  193. package/hooks/loop-guard.mjs +3 -3
  194. package/hooks/on-session-end.mjs +2 -2
  195. package/hooks/on-session-start.mjs +103 -2
  196. package/hooks/on-stop.mjs +60 -14
  197. package/hooks/operator-steer.mjs +2 -2
  198. package/hooks/post-bash-write-verify.mjs +85 -0
  199. package/hooks/post-edit-import-probe.mjs +344 -0
  200. package/hooks/post-subagent-discovery-validator.mjs +187 -431
  201. package/hooks/post-tool-batch-wave-signal.mjs +118 -4
  202. package/hooks/post-tool-failure-corrective-context.mjs +2 -2
  203. package/hooks/post-tooluse-frontend-slop.mjs +3 -3
  204. package/hooks/pre-bash-destructive-guard.mjs +39 -13
  205. package/hooks/skill-invocation-telemetry.mjs +17 -5
  206. package/hooks/subagent-telemetry.mjs +13 -4
  207. package/monitors/monitors.json +3 -3
  208. package/package.json +9 -1
  209. package/pi/prompts/session.md +2 -2
  210. package/scripts/backfill-abandoned-sessions.mjs +50 -4
  211. package/scripts/backfill-learnings-from-vault.mjs +9 -3
  212. package/scripts/dialectic-deriver.mjs +73 -8
  213. package/scripts/export-hw-learnings.mjs +113 -1
  214. package/scripts/generate-agents-skills.mjs +378 -0
  215. package/scripts/generate-codex-skills.mjs +246 -0
  216. package/scripts/generate-cursor-adapter.mjs +45 -8
  217. package/scripts/generate-hook-import-set.mjs +292 -0
  218. package/scripts/lib/agent-status.mjs +13 -2
  219. package/scripts/lib/auto-dream.mjs +38 -36
  220. package/scripts/lib/autonomy/suitability.mjs +6 -0
  221. package/scripts/lib/autopilot/loop.mjs +2 -2
  222. package/scripts/lib/ci-status-banner.mjs +220 -75
  223. package/scripts/lib/codex/plugin-contract.mjs +88 -6
  224. package/scripts/lib/config/auto-dream.mjs +2 -1
  225. package/scripts/lib/config/block-header.mjs +8 -0
  226. package/scripts/lib/config/block-preprocess.mjs +177 -0
  227. package/scripts/lib/config/broken-window.mjs +2 -1
  228. package/scripts/lib/config/cold-start.mjs +2 -1
  229. package/scripts/lib/config/config-protection.mjs +22 -2
  230. package/scripts/lib/config/context-coverage.mjs +2 -1
  231. package/scripts/lib/config/cross-repo.mjs +2 -1
  232. package/scripts/lib/config/custom-phases.mjs +2 -1
  233. package/scripts/lib/config/dialectic.mjs +2 -1
  234. package/scripts/lib/config/discovery-validator.mjs +2 -1
  235. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +24 -1
  236. package/scripts/lib/config/dispatcher-autonomy.mjs +2 -1
  237. package/scripts/lib/config/docs-orchestrator.mjs +2 -1
  238. package/scripts/lib/config/docs-staleness.mjs +2 -1
  239. package/scripts/lib/config/drift-check.mjs +2 -1
  240. package/scripts/lib/config/eval.mjs +2 -1
  241. package/scripts/lib/config/events-rotation.mjs +2 -1
  242. package/scripts/lib/config/evolve.mjs +8 -2
  243. package/scripts/lib/config/frontend-slop-hook.mjs +7 -3
  244. package/scripts/lib/config/gitlab-portfolio.mjs +2 -1
  245. package/scripts/lib/config/handover-gate.mjs +2 -1
  246. package/scripts/lib/config/health-endpoints.mjs +7 -2
  247. package/scripts/lib/config/host-paths.mjs +20 -4
  248. package/scripts/lib/config/issue-budget.mjs +2 -1
  249. package/scripts/lib/config/loop-guard.mjs +2 -1
  250. package/scripts/lib/config/memory.mjs +2 -1
  251. package/scripts/lib/config/moc-staleness.mjs +2 -1
  252. package/scripts/lib/config/persona-gate-wave.mjs +2 -1
  253. package/scripts/lib/config/private-config-dir.mjs +67 -0
  254. package/scripts/lib/config/reconcile.mjs +2 -1
  255. package/scripts/lib/config/remote-hosts.mjs +2 -1
  256. package/scripts/lib/config/section-extractor.mjs +7 -1
  257. package/scripts/lib/config/skill-evolution.mjs +2 -1
  258. package/scripts/lib/config/slopcheck.mjs +2 -1
  259. package/scripts/lib/config/state-md-lock.mjs +2 -1
  260. package/scripts/lib/config/templates-first.mjs +2 -1
  261. package/scripts/lib/config/test.mjs +2 -1
  262. package/scripts/lib/config/vault-integration.mjs +7 -1
  263. package/scripts/lib/config/vault-mirror-quality.mjs +2 -1
  264. package/scripts/lib/config/vault-staleness.mjs +2 -1
  265. package/scripts/lib/config/vault-sync.mjs +2 -1
  266. package/scripts/lib/config/verification-auto-fix.mjs +2 -1
  267. package/scripts/lib/config/wave-reviewers.mjs +2 -1
  268. package/scripts/lib/config/worktree-orphans.mjs +2 -1
  269. package/scripts/lib/convergence-monitor.mjs +82 -16
  270. package/scripts/lib/dispatcher/rank.mjs +124 -48
  271. package/scripts/lib/ecosystem-health.mjs +16 -2
  272. package/scripts/lib/eval/engine.mjs +9 -1
  273. package/scripts/lib/eval/session-resolve.mjs +23 -4
  274. package/scripts/lib/events.mjs +22 -6
  275. package/scripts/lib/frontmatter-guard.mjs +131 -13
  276. package/scripts/lib/gates/gate-full.mjs +30 -0
  277. package/scripts/lib/gates/gate-helpers.mjs +76 -0
  278. package/scripts/lib/hardware-pattern-detector.mjs +18 -1
  279. package/scripts/lib/harness-audit/categories/category4.mjs +31 -11
  280. package/scripts/lib/host-identity.mjs +50 -11
  281. package/scripts/lib/instruction-budget-guard.mjs +171 -5
  282. package/scripts/lib/learnings/evolve-telemetry.mjs +178 -0
  283. package/scripts/lib/learnings/io.mjs +60 -6
  284. package/scripts/lib/memory-proposals/store.mjs +30 -22
  285. package/scripts/lib/owner-config-banner.mjs +41 -6
  286. package/scripts/lib/owner-config-loader.mjs +21 -10
  287. package/scripts/lib/owner-interview.mjs +3 -3
  288. package/scripts/lib/owner-yaml.mjs +215 -15
  289. package/scripts/lib/platform.mjs +108 -15
  290. package/scripts/lib/plugin-update-banner.mjs +414 -0
  291. package/scripts/lib/project-hygiene.mjs +38 -2
  292. package/scripts/lib/qg-command-drift-banner.mjs +50 -12
  293. package/scripts/lib/quality-gate.mjs +133 -44
  294. package/scripts/lib/reconcile/emitter.mjs +68 -6
  295. package/scripts/lib/reconcile/engine.mjs +51 -11
  296. package/scripts/lib/reconcile/idempotency.mjs +37 -4
  297. package/scripts/lib/reconcile/writer.mjs +40 -18
  298. package/scripts/lib/session-close-backfill.mjs +67 -9
  299. package/scripts/lib/session-id.mjs +12 -23
  300. package/scripts/lib/session-identity/own-session.mjs +125 -10
  301. package/scripts/lib/session-lock-shape.mjs +43 -0
  302. package/scripts/lib/session-lock.mjs +5 -10
  303. package/scripts/lib/session-registry.mjs +25 -9
  304. package/scripts/lib/session-schema/constants.mjs +64 -3
  305. package/scripts/lib/session-schema/validator.mjs +38 -4
  306. package/scripts/lib/session-start-probes.mjs +30 -1
  307. package/scripts/lib/sessions-staleness-banner.mjs +18 -11
  308. package/scripts/lib/skill-health/join.mjs +17 -4
  309. package/scripts/lib/state-md.mjs +78 -0
  310. package/scripts/lib/sunset/walker.mjs +6 -0
  311. package/scripts/lib/telemetry/schema.mjs +202 -9
  312. package/scripts/lib/telemetry/sync.mjs +368 -12
  313. package/scripts/lib/telemetry-flush-health-banner.mjs +211 -0
  314. package/scripts/lib/validate/check-agents-skills.mjs +327 -0
  315. package/scripts/lib/validate/check-agents.mjs +3 -3
  316. package/scripts/lib/validate/check-codex-skills.mjs +191 -0
  317. package/scripts/lib/validate/check-cursor-adapter.mjs +234 -72
  318. package/scripts/lib/validate/check-hooks-symmetry.mjs +45 -16
  319. package/scripts/lib/validate/check-owner-leakage.mjs +319 -22
  320. package/scripts/lib/validate/check-skill-links.mjs +193 -0
  321. package/scripts/lib/validate/check-skill-script-paths.mjs +47 -28
  322. package/scripts/lib/validate/check-test-git-config-target.mjs +192 -12
  323. package/scripts/lib/validate/check-unwired-features.mjs +163 -15
  324. package/scripts/lib/validate/check-validator-registration.mjs +10 -4
  325. package/scripts/lib/validate/confidential-names.mjs +95 -30
  326. package/scripts/lib/validate/enumerate-repo-files.mjs +317 -0
  327. package/scripts/lib/validate/repo-files.mjs +48 -14
  328. package/scripts/lib/vault-backfill/template.mjs +63 -6
  329. package/scripts/lib/vault-mirror/process.mjs +165 -42
  330. package/scripts/lib/vault-mirror/telemetry.mjs +2 -2
  331. package/scripts/lib/vault-status/narrative-mirror.mjs +127 -18
  332. package/scripts/lib/wave-executor/dispatch-common.mjs +164 -0
  333. package/scripts/lib/wave-executor/foreign-dispatch.mjs +7 -142
  334. package/scripts/lib/wave-executor/remote-dispatch.mjs +5 -7
  335. package/scripts/lib/wave-resource-gate.mjs +8 -2
  336. package/scripts/lib/wave-sizing.mjs +4 -1
  337. package/scripts/lib/wave-transcript-tail.mjs +118 -4
  338. package/scripts/materialize-wave-scope.mjs +12 -5
  339. package/scripts/memory-propose.mjs +19 -5
  340. package/scripts/migrate-cold-start-seed.mjs +4 -1
  341. package/scripts/parse-config.mjs +60 -3
  342. package/scripts/release.mjs +430 -31
  343. package/scripts/repair-invalid-sessions.mjs +3 -3
  344. package/scripts/run-quality-gate.mjs +128 -11
  345. package/scripts/site-numbers.mjs +344 -8
  346. package/scripts/sweep-expired-learnings.mjs +90 -0
  347. package/scripts/sync-vault-schema.mjs +3 -1
  348. package/scripts/telemetry.mjs +2 -2
  349. package/scripts/validate-plugin.mjs +164 -0
  350. package/scripts/validate-wave-scope.mjs +28 -8
  351. package/scripts/wave-scope-binding.mjs +215 -0
  352. package/skills/_shared/instruction-file-resolution.md +10 -0
  353. package/skills/_shared/parallel-aware-preamble.md +1 -0
  354. package/skills/_shared/platform-tools.md +1 -1
  355. package/skills/_shared/state-ownership.md +1 -1
  356. package/skills/architecture/SKILL.md +7 -5
  357. package/skills/{domain-model/SKILL.md → architecture/references/domain-model.md} +9 -9
  358. package/skills/autopilot/SKILL.md +4 -18
  359. package/skills/claude-md-drift-check/SKILL.md +5 -1
  360. package/skills/claude-md-drift-check/checker.mjs +62 -2
  361. package/skills/convergence-monitoring/SIGNALS.md +55 -0
  362. package/skills/discovery/probes/vault-staleness.mjs +37 -13
  363. package/skills/discovery/probes-arch.md +20 -18
  364. package/skills/dispatcher/SKILL.md +3 -2
  365. package/skills/evolve/SKILL.md +65 -26
  366. package/skills/frontmatter-guard/SKILL.md +11 -5
  367. package/skills/npm-publish/SKILL.md +1 -1
  368. package/skills/reconcile/SKILL.md +33 -0
  369. package/skills/remote-offload/SKILL.md +1 -1
  370. package/skills/session-end/SKILL.md +18 -905
  371. package/skills/session-end/phase-3-6-tail.md +10 -3
  372. package/skills/session-end/plan-verification.md +221 -155
  373. package/skills/session-end/references/phase-2-quality-gate.md +93 -0
  374. package/skills/session-end/references/phase-3-documentation-updates.md +229 -0
  375. package/skills/session-end/references/phase-4a-worktree-cleanup.md +120 -0
  376. package/skills/session-end/references/phase-4b-worktree-orphan-sweep.md +58 -0
  377. package/skills/session-end/references/phase-5-issue-cleanup.md +104 -0
  378. package/skills/session-end/references/session-summary-template.md +62 -0
  379. package/skills/session-plan/SKILL.md +49 -0
  380. package/skills/session-start/SKILL.md +22 -904
  381. package/skills/session-start/phase-8-5-express-path.md +1 -1
  382. package/skills/session-start/references/phase-1-1-dispatcher-autonomy-capture.md +55 -0
  383. package/skills/session-start/references/phase-1-2-session-lock.md +140 -0
  384. package/skills/session-start/references/phase-1-5-session-continuity.md +254 -0
  385. package/skills/session-start/references/phase-1-7-vault-status-board.md +53 -0
  386. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +75 -0
  387. package/skills/session-start/references/phase-4-ssot-environment-check.md +160 -0
  388. package/skills/session-start/references/phase-6-5-forced-reads.md +75 -0
  389. package/skills/session-start/references/phase-6-6-project-intelligence.md +81 -0
  390. package/skills/session-start/references/phase-6-7-memory-banner-telemetry-consent.md +103 -0
  391. package/skills/vault-sync/SKILL.md +10 -0
  392. package/skills/vault-sync/validator.mjs +21 -27
  393. package/skills/wave-executor/SKILL.md +15 -1
  394. package/skills/wave-executor/references/wave-loop-dispatch.md +612 -0
  395. package/skills/wave-executor/references/wave-loop-review.md +570 -0
  396. package/skills/wave-executor/references/wave-loop-scope-manifest.md +162 -0
  397. package/skills/wave-executor/wave-loop.md +14 -1309
  398. package/templates/_shared/journey-manifest.md +10 -6
  399. package/.cursor/commands/autopilot-multi.md +0 -14
  400. package/.cursor/commands/contract-version-bump.md +0 -14
  401. package/.cursor/commands/journey-audit.md +0 -14
  402. package/.cursor/skills/contract-version-bump/SKILL.md +0 -12
  403. package/.cursor/skills/daily/SKILL.md +0 -12
  404. package/.cursor/skills/domain-model/SKILL.md +0 -13
  405. package/.cursor/skills/journey-audit/SKILL.md +0 -13
  406. package/.cursor/skills/skill-creator/SKILL.md +0 -13
  407. package/.cursor/skills/ubiquitous-language/SKILL.md +0 -13
  408. package/commands/autopilot-multi.md +0 -74
  409. package/commands/contract-version-bump.md +0 -28
  410. package/commands/journey-audit.md +0 -43
  411. package/pi/prompts/autopilot-multi.md +0 -12
  412. package/pi/prompts/contract-version-bump.md +0 -12
  413. package/pi/prompts/journey-audit.md +0 -12
  414. package/scripts/autopilot-multi.mjs +0 -885
  415. package/scripts/backfill-learnings-expires.mjs +0 -196
  416. package/scripts/backfill-learnings.mjs +0 -203
  417. package/scripts/fleet-instruction-scan.mjs +0 -141
  418. package/scripts/lib/autopilot/dep-graph.mjs +0 -417
  419. package/scripts/lib/autopilot/multi-killswitch.mjs +0 -184
  420. package/scripts/lib/webhook-url.mjs +0 -105
  421. package/scripts/lifecycle-sim-v6.mjs +0 -347
  422. package/scripts/migrate-learnings-jsonl.mjs +0 -189
  423. package/scripts/migrate-subagents-jsonl.mjs +0 -196
  424. package/scripts/upload-social-preview.mjs +0 -316
  425. package/skills/_shared/model-selection.md +0 -64
  426. package/skills/contract-version-bump/SKILL.md +0 -219
  427. package/skills/daily/SKILL.md +0 -222
  428. package/skills/daily/generate.sh +0 -92
  429. package/skills/daily/templates/daily.md.tpl +0 -36
  430. package/skills/journey-audit/SKILL.md +0 -270
  431. package/skills/skill-creator/SKILL.md +0 -168
  432. package/skills/ubiquitous-language/SKILL.md +0 -97
  433. package/skills/vault-sync/package-lock.json +0 -40
  434. /package/skills/{domain-model → architecture/references}/ADR-FORMAT.md +0 -0
  435. /package/skills/{domain-model → architecture/references}/CONTEXT-FORMAT.md +0 -0
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Check: every `scripts/**.mjs` path cited in `skills/`, `commands/` and
4
- * `agents/` either EXISTS or is annotated as deliberately absent (#1176).
5
- * Extended (#1187) to also cite `scripts/**.sh` and `hooks/**.sh` — see
6
- * "## Mode: BLOCKING for `.mjs`, ADVISORY for `.sh`" below for why that half
7
- * is advisory, not blocking.
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.
8
11
  *
9
12
  * ## Why
10
13
  *
@@ -12,8 +15,8 @@
12
15
  * `node scripts/lib/auto-commit.mjs` costs an operator a failed command and a
13
16
  * re-derivation of what the file was supposed to do — and nothing in the
14
17
  * corpus notices, because a markdown file compiles under every gate. Measured
15
- * 2026-09-02 @ c3ab480: 237 distinct citations across the three scan roots,
16
- * 7 of them dead.
18
+ * 2026-09-02 @ c3ab480: 237 distinct citations across the (then three) scan
19
+ * roots, 7 of them dead.
17
20
  *
18
21
  * ## Fences are skipped, and that is most of the answer
19
22
  *
@@ -58,27 +61,37 @@
58
61
  * The `.sh` half of the citation grammar (below) does not get that same
59
62
  * severity by default. A #1176 repo-wide grep (`scripts/hooks` prose across
60
63
  * `skills/commands/agents/docs/hooks`) found 27 distinct `.sh` citations, 21
61
- * dead — but only ONE of those 27 sits inside this checker's three scan roots
62
- * (`skills/contract-version-bump/SKILL.md:134`, itself arguably a
63
- * cross-repo path — see the dry-run note at `scanSkillScriptPaths`'s
64
- * `strictSh` option). The other 26 live in `docs/`, which this checker does
65
- * NOT scan and — per this same paragraph's own evidence — MUST NOT start
66
- * scanning as a side effect of the `.sh` extension: `docs/adr/*.md` alone
67
- * carries 7 dead `.mjs` citations of its own (all historical/planned ADR
68
- * prose, e.g. `scripts/lib/tool-adapter.mjs`, `scripts/lib/auto-commit.mjs`),
69
- * none annotated, all outside this task's edit scope. Widening `SCAN_DIRS` to
70
- * `docs` would turn those 7 into new BLOCKING findings on a doc surface
71
- * nobody triaged the opposite of "the `.mjs` behaviour stays exactly as
72
- * today". So `SCAN_DIRS` stays `['skills', 'commands', 'agents']`; the wider
73
- * `docs`/`hooks` prose census is a follow-up for whoever owns those files,
74
- * not a silent scope change here.
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.
75
86
  *
76
87
  * A `.sh` finding is therefore `WARN:` by default (visible, never blocking —
77
88
  * `ok` and the CLI exit code ignore `severity: 'warn'` findings) and only
78
89
  * becomes `FAIL:`/blocking under the `--strict-sh` CLI flag (or
79
90
  * `strictSh: true` for `scanSkillScriptPaths()` callers) — flip that default
80
91
  * once the dead `.sh` citations this checker CAN see are fixed by their doc
81
- * owner (BV-004 revisit trigger).
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).
82
95
  *
83
96
  * @module scripts/lib/validate/check-skill-script-paths
84
97
  */
@@ -86,11 +99,11 @@
86
99
  import { existsSync, readFileSync } from 'node:fs';
87
100
  import path from 'node:path';
88
101
  import { pathToFileURL } from 'node:url';
89
- import { listRepoFiles } from './repo-files.mjs';
102
+ import { enumerateRepoFiles } from './enumerate-repo-files.mjs';
90
103
  import { forEachLine } from './markdown-fences.mjs';
91
104
 
92
105
  /** Documentation roots whose prose is treated as a claim about the repo. */
93
- export const SCAN_DIRS = Object.freeze(['skills', 'commands', 'agents']);
106
+ export const SCAN_DIRS = Object.freeze(['skills', 'commands', 'agents', 'docs']);
94
107
 
95
108
  /**
96
109
  * A cited script path. One regex, one alternation, reused for every
@@ -246,10 +259,16 @@ export function scanSkillScriptPaths({ pluginRoot, dirs = SCAN_DIRS, strictSh =
246
259
  /** @type {string[]} */
247
260
  let files;
248
261
  try {
249
- // The git index, never a `readdirSync` walk (#1143): a walk cannot see
250
- // `.gitignore`, so a worktree under `.claude/worktrees/` or any ignored
251
- // artefact would enter this census as if it were repository documentation.
252
- files = listRepoFiles(pluginRoot, { dirs, exts: ['.md'] });
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'] });
253
272
  } catch (error) {
254
273
  findings.push({
255
274
  kind: 'tool-error',
@@ -40,6 +40,37 @@
40
40
  * measures that second population so the gap is visible in the OUTPUT, not
41
41
  * only in this comment.
42
42
  *
43
+ * ## Wrapper-aware: `fixtureGit` / `fixtureGitSpawn` are git invocations
44
+ *
45
+ * Since 2026-09-06 most fixtures do not spawn `git` themselves — they call
46
+ * `fixtureGit(args, cwd, opts)` / `fixtureGitSpawn(…)` from
47
+ * `tests/_helpers/tmp-fixture.mjs`, which prepend `...NO_BACKGROUND_WRITER` and
48
+ * spawn the binary inside the helper. Two consequences, both measured
49
+ * 2026-09-07 against this tree:
50
+ *
51
+ * - Resolving only the helper's own two `execFileSync`/`spawnSync` lines
52
+ * (i.e. teaching {@link classifyArgv} to skip the allowlisted flag-only
53
+ * spread, see {@link NOOP_PREFIX_SPREADS}) changes NOTHING: `applicable`
54
+ * stays at **17**, because the token after the allowlisted spread is
55
+ * `...args` — an unknown spread the census must still refuse to guess past.
56
+ * - Recognising the two helpers BY NAME, and reading the argv array's first
57
+ * element as the subcommand, lifts `applicable` to **~200** with **0**
58
+ * findings (197 → 198 → 200 across the 2026-09-07 re-measurements as
59
+ * sibling waves added fixtures; re-measure before quoting) — the census
60
+ * then sees the real test population instead of a residue. That population is **244** `fixtureGit`/`fixtureGitSpawn` call
61
+ * sites, measured 2026-09-07 with
62
+ * `rg -o "\bfixtureGit(Spawn)?\s*\(" tests/ -g '*.mjs' | wc -l`
63
+ * (the header claimed 239 until that re-measurement; `applicable` is the
64
+ * smaller number because read-only and unresolved-argv calls are excluded).
65
+ *
66
+ * Wrapper-aware is therefore the mode this file implements. It costs one extra
67
+ * rule: the helper takes its target as the SECOND POSITIONAL, not as a `cwd:`
68
+ * key, and `undefined`, `null` or an ABSENT second positional all mean "no
69
+ * destination was handed to the helper" — see {@link wrapperHasCwd}, which
70
+ * judges the COMMENT-STRIPPED tail so an inline comment cannot stand in for the
71
+ * argument. Judging a wrapper call by the `cwd:` scan alone would have reported
72
+ * nearly every routed fixture as untargeted.
73
+ *
43
74
  * Further named gaps:
44
75
  * - **A non-literal argv array is never judged.** `execFileSync('git', args, …)`
45
76
  * cannot be classified from the call site; counted as `unresolvedArgv`.
@@ -163,6 +194,16 @@ const TARGET_DECLARING_GLOBALS = Object.freeze(['-C', '--git-dir', '--work-tree'
163
194
  /** Call shapes that hand an argv ARRAY to a `git` binary. */
164
195
  const ARGV_CALL_RE = /\b(?:execFileSync|execFile|spawnSync|spawn)\s*\(\s*['"]git['"]\s*,\s*/g;
165
196
 
197
+ /**
198
+ * Call shapes that route a `git` argv through this suite's fixture helpers.
199
+ *
200
+ * `fixtureGit(args, cwd, opts)` / `fixtureGitSpawn(args, cwd, opts)` from
201
+ * `tests/_helpers/tmp-fixture.mjs` ARE git invocations — the binary is inside
202
+ * the helper. Recognising them by name is what makes the census reflect the
203
+ * real test population; see § Wrapper-aware in the header.
204
+ */
205
+ const WRAPPER_CALL_RE = /\b(?:fixtureGit|fixtureGitSpawn)\s*\(/g;
206
+
166
207
  /** Call shapes that hand a SHELL STRING opening with `git` to a shell. */
167
208
  const SHELL_CALL_RE = /\b(?:execSync|exec)\s*\(\s*(['"`])\s*git\s/g;
168
209
 
@@ -226,15 +267,30 @@ function matchBracket(text, open, openChar, closeChar) {
226
267
  }
227
268
 
228
269
  /**
229
- * @typedef {{t:'lit', v:string} | {t:'spread'} | {t:'expr'}} ArgvToken
230
- * `lit` a string literal · `spread` a `...rest` element · `expr` any other
270
+ * @typedef {{t:'lit', v:string} | {t:'spread', name:string} | {t:'expr'}} ArgvToken
271
+ * `lit` a string literal · `spread` a `...rest` element, carrying the spread
272
+ * identifier (`''` when it is not a plain identifier) · `expr` any other
231
273
  * expression (an identifier, a member access, an interpolated template).
232
274
  *
233
275
  * The `spread`/`expr` split is load-bearing, not cosmetic: `['init','-q',dir]`
234
276
  * carries its target in an `expr` positional, while `['-C',dir,...args]`
235
277
  * carries an unknowable tail in a `spread`. Folding both to "opaque" is what
236
278
  * produced the first measurement's 11 false positives.
279
+ *
280
+ * The spread's NAME is load-bearing in turn — see {@link NOOP_PREFIX_SPREADS}.
281
+ */
282
+
283
+ /**
284
+ * Spread identifiers that are known to contain ONLY `git` global flags, so a
285
+ * leading `...NAME` may be skipped exactly as a literal `-c k=v` run is.
286
+ *
287
+ * An explicit allowlist, never a heuristic: any OTHER spread keeps the
288
+ * fail-closed `subcommand: null`, because guessing past an unknown spread is
289
+ * precisely what produced the 11 false positives named in the header.
290
+ *
291
+ * @type {ReadonlySet<string>}
237
292
  */
293
+ const NOOP_PREFIX_SPREADS = new Set(['NO_BACKGROUND_WRITER']);
238
294
 
239
295
  /**
240
296
  * Tokenize a literal argv array body into ordered tokens.
@@ -245,13 +301,13 @@ function matchBracket(text, open, openChar, closeChar) {
245
301
  export function tokenizeArgv(inner) {
246
302
  /** @type {ArgvToken[]} */
247
303
  const tokens = [];
248
- const re = /(['"])((?:\\.|(?!\1)[^\\])*)\1|`([^`$]*)`|(\.\.\.)[\w$.[\]]*|([A-Za-z_$][\w$.[\]]*|`[^`]*`)/g;
304
+ const re = /(['"])((?:\\.|(?!\1)[^\\])*)\1|`([^`$]*)`|(\.\.\.)([\w$.[\]]*)|([A-Za-z_$][\w$.[\]]*|`[^`]*`)/g;
249
305
  /** @type {RegExpExecArray|null} */
250
306
  let m;
251
307
  while ((m = re.exec(inner)) !== null) {
252
308
  if (m[2] !== undefined) tokens.push({ t: 'lit', v: m[2] });
253
309
  else if (m[3] !== undefined) tokens.push({ t: 'lit', v: m[3] });
254
- else if (m[4] !== undefined) tokens.push({ t: 'spread' });
310
+ else if (m[4] !== undefined) tokens.push({ t: 'spread', name: m[5] ?? '' });
255
311
  else tokens.push({ t: 'expr' });
256
312
  }
257
313
  return tokens;
@@ -268,8 +324,13 @@ export function classifyArgv(tokens) {
268
324
  let index = 0;
269
325
  while (index < tokens.length) {
270
326
  const token = tokens[index];
271
- // A non-literal in leading-flag position makes the subcommand unknowable;
272
- // never guess past it.
327
+ // An ALLOWLISTED flag-only spread is skipped exactly like a `-c k=v` run.
328
+ if (token.t === 'spread' && NOOP_PREFIX_SPREADS.has(token.name)) {
329
+ index += 1;
330
+ continue;
331
+ }
332
+ // Any other non-literal in leading-flag position makes the subcommand
333
+ // unknowable; never guess past it.
273
334
  if (token.t !== 'lit') return { hasArgvTarget, subcommand: null, rest: [] };
274
335
  if (!token.v.startsWith('-')) break;
275
336
 
@@ -416,6 +477,84 @@ export function insideStringLiteral(body, index) {
416
477
  return quote !== null;
417
478
  }
418
479
 
480
+ /**
481
+ * Replace every comment in `text` with a single space, leaving string literals
482
+ * untouched.
483
+ *
484
+ * Not cosmetic: {@link wrapperHasCwd} judges the SECOND POSITIONAL textually,
485
+ * so an inline `/* … *\/` between the comma and the argument used to shift the
486
+ * argument out of view and the call read as targeted — a comment that says
487
+ * "no cwd" measured as a cwd. `inCommentLine` cannot serve here: it answers a
488
+ * question about a whole LINE, while this one runs inside a call expression.
489
+ *
490
+ * @param {string} text
491
+ * @returns {string} same length semantics, comments blanked to one space
492
+ */
493
+ export function stripComments(text) {
494
+ let out = '';
495
+ /** @type {string|null} */
496
+ let quote = null;
497
+ for (let i = 0; i < text.length; i += 1) {
498
+ const ch = text[i];
499
+ if (quote !== null) {
500
+ out += ch;
501
+ if (ch === '\\') {
502
+ out += text[i + 1] ?? '';
503
+ i += 1;
504
+ } else if (ch === quote) quote = null;
505
+ continue;
506
+ }
507
+ if (ch === "'" || ch === '"' || ch === '`') {
508
+ quote = ch;
509
+ out += ch;
510
+ continue;
511
+ }
512
+ if (ch === '/' && text[i + 1] === '*') {
513
+ const end = text.indexOf('*/', i + 2);
514
+ i = end === -1 ? text.length : end + 1;
515
+ out += ' ';
516
+ continue;
517
+ }
518
+ if (ch === '/' && text[i + 1] === '/') {
519
+ const end = text.indexOf('\n', i);
520
+ i = end === -1 ? text.length : end - 1;
521
+ out += ' ';
522
+ continue;
523
+ }
524
+ out += ch;
525
+ }
526
+ return out;
527
+ }
528
+
529
+ /**
530
+ * Decide whether a fixture-helper call names a working directory.
531
+ *
532
+ * `fixtureGit(args, cwd, opts)` takes the target as its SECOND POSITIONAL, not
533
+ * as a `cwd:` key — so the textual `cwd:` scan that judges a raw `execFileSync`
534
+ * would report every one of these as untargeted.
535
+ *
536
+ * Three shapes are explicitly NOT a target, because none of them hands the
537
+ * helper a destination: a literal `undefined` (the documented "the argv names
538
+ * the target" form), a literal `null` (same at runtime — `spawnSync` inherits
539
+ * the ambient cwd for both), and an ABSENT second positional. Judging is done
540
+ * on the COMMENT-STRIPPED tail: `fixtureGit([…], /* no cwd *\/ undefined)` read
541
+ * as targeted before 2026-09-07 — the comment, not the argument, was what the
542
+ * second-positional scan saw.
543
+ *
544
+ * @param {string} tail call arguments AFTER the argv array's `]`, bounded by
545
+ * the call's closing paren
546
+ * @returns {boolean}
547
+ */
548
+ export function wrapperHasCwd(tail) {
549
+ const clean = stripComments(tail);
550
+ const m = /^\s*,\s*/.exec(clean);
551
+ if (m) {
552
+ const second = clean.slice(m[0].length);
553
+ if (second !== '' && !/^(?:undefined|null)\b/.test(second) && !/^,/.test(second)) return true;
554
+ }
555
+ return CWD_OPTION_RE.test(clean);
556
+ }
557
+
419
558
  /**
420
559
  * Scan one file for `git` invocations.
421
560
  *
@@ -428,7 +567,7 @@ export function scanFile(relative, body, tally) {
428
567
  /** @type {Array<{kind: string, file: string, line: number, form: string, command: string, message: string}>} */
429
568
  const findings = [];
430
569
 
431
- /** @type {Array<{index: number, form: 'argv'|'shell', tokens: Array<string|null>, tail: string}>} */
570
+ /** @type {Array<{index: number, form: 'argv'|'shell'|'wrapper', tokens: Array<string|null>, tail: string}>} */
432
571
  const calls = [];
433
572
 
434
573
  ARGV_CALL_RE.lastIndex = 0;
@@ -454,6 +593,35 @@ export function scanFile(relative, body, tally) {
454
593
  });
455
594
  }
456
595
 
596
+ WRAPPER_CALL_RE.lastIndex = 0;
597
+ while ((m = WRAPPER_CALL_RE.exec(body)) !== null) {
598
+ const openParen = m.index + m[0].length - 1;
599
+ const callEnd = matchBracket(body, openParen, '(', ')');
600
+ if (callEnd === -1) {
601
+ tally.unresolvedArgv += 1;
602
+ continue;
603
+ }
604
+ const argsText = body.slice(openParen + 1, callEnd);
605
+ const arrayStart = argsText.search(/\S/);
606
+ if (arrayStart === -1 || argsText[arrayStart] !== '[') {
607
+ // `fixtureGit(args, dir)` — a variable argv, unjudgeable like its
608
+ // `execFileSync` counterpart.
609
+ tally.unresolvedArgv += 1;
610
+ continue;
611
+ }
612
+ const close = matchBracket(argsText, arrayStart, '[', ']');
613
+ if (close === -1) {
614
+ tally.unresolvedArgv += 1;
615
+ continue;
616
+ }
617
+ calls.push({
618
+ index: m.index,
619
+ form: 'wrapper',
620
+ tokens: tokenizeArgv(argsText.slice(arrayStart + 1, close)),
621
+ tail: argsText.slice(close + 1),
622
+ });
623
+ }
624
+
457
625
  SHELL_CALL_RE.lastIndex = 0;
458
626
  while ((m = SHELL_CALL_RE.exec(body)) !== null) {
459
627
  const quote = m[1];
@@ -487,11 +655,20 @@ export function scanFile(relative, body, tally) {
487
655
  }
488
656
  tally.applicable += 1;
489
657
 
490
- // The options object: everything up to the end of the call expression.
658
+ // The options object: everything up to the end of the call expression. For
659
+ // a wrapper call `call.tail` is ALREADY bounded by the call's own closing
660
+ // paren, and its second positional — not a `cwd:` key — carries the target.
661
+ const isWrapper = call.form === 'wrapper';
491
662
  const callEnd = matchBracket(call.tail, call.tail.indexOf('('), '(', ')');
492
- const optionsText = callEnd === -1 ? call.tail.slice(0, 400) : call.tail.slice(0, callEnd);
493
- const opaqueOptions = OPAQUE_OPTIONS_RE.test(call.tail);
494
- const hasCwd = CWD_OPTION_RE.test(optionsText);
663
+ const optionsText = isWrapper
664
+ ? call.tail
665
+ : callEnd === -1
666
+ ? call.tail.slice(0, 400)
667
+ : call.tail.slice(0, callEnd);
668
+ const opaqueOptions = !isWrapper && OPAQUE_OPTIONS_RE.test(call.tail);
669
+ const hasCwd = isWrapper
670
+ ? wrapperHasCwd(call.tail)
671
+ : CWD_OPTION_RE.test(optionsText);
495
672
  const hasEnvTarget = GIT_ENV_TARGET_RE.test(optionsText);
496
673
  const hasTarget =
497
674
  hasArgvTarget || hasCwd || hasEnvTarget || hasSubcommandTarget(subcommand, rest);
@@ -582,7 +759,10 @@ export function inspectTestGitConfigTarget(pluginRoot) {
582
759
  });
583
760
  return result;
584
761
  }
585
- if (!/['"`]\s*git[\s'"`]/.test(body)) continue;
762
+ // Cheap prefilter. The second alternative is load-bearing since the census
763
+ // became wrapper-aware: a file that only calls `fixtureGit([...])` never
764
+ // writes the quoted binary name and would otherwise be skipped unseen.
765
+ if (!/['"`]\s*git[\s'"`]/.test(body) && !/\bfixtureGit(?:Spawn)?\s*\(/.test(body)) continue;
586
766
  findings.push(...scanFile(relative, body, tally));
587
767
  }
588
768