session-orchestrator 5.2.0 → 5.4.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 (427) hide show
  1. package/.agents/skills/architecture/SKILL.md +3 -1
  2. package/.agents/skills/autopilot/SKILL.md +5 -1
  3. package/.agents/skills/autopilot/agents/openai.yaml +5 -0
  4. package/.agents/skills/bootstrap/SKILL.md +5 -1
  5. package/.agents/skills/bootstrap/agents/openai.yaml +5 -0
  6. package/.agents/skills/brainstorm/SKILL.md +5 -1
  7. package/.agents/skills/brainstorm/agents/openai.yaml +5 -0
  8. package/.agents/skills/claude-md-drift-check/SKILL.md +4 -2
  9. package/.agents/skills/close/SKILL.md +5 -1
  10. package/.agents/skills/close/agents/openai.yaml +5 -0
  11. package/.agents/skills/convergence-monitoring/SKILL.md +4 -2
  12. package/.agents/skills/debug/SKILL.md +5 -1
  13. package/.agents/skills/debug/agents/openai.yaml +5 -0
  14. package/.agents/skills/discovery/SKILL.md +5 -1
  15. package/.agents/skills/discovery/agents/openai.yaml +5 -0
  16. package/.agents/skills/dispatcher/SKILL.md +5 -1
  17. package/.agents/skills/dispatcher/agents/openai.yaml +5 -0
  18. package/.agents/skills/docs-orchestrator/SKILL.md +3 -1
  19. package/.agents/skills/ecosystem-health/SKILL.md +3 -1
  20. package/.agents/skills/eli5/SKILL.md +5 -1
  21. package/.agents/skills/eli5/agents/openai.yaml +5 -0
  22. package/.agents/skills/eval/SKILL.md +6 -2
  23. package/.agents/skills/eval/agents/openai.yaml +5 -0
  24. package/.agents/skills/evolve/SKILL.md +6 -2
  25. package/.agents/skills/evolve/agents/openai.yaml +5 -0
  26. package/.agents/skills/frontmatter-guard/SKILL.md +3 -1
  27. package/.agents/skills/gitlab-ops/SKILL.md +3 -1
  28. package/.agents/skills/gitlab-portfolio/SKILL.md +3 -1
  29. package/.agents/skills/go/SKILL.md +5 -1
  30. package/.agents/skills/go/agents/openai.yaml +5 -0
  31. package/.agents/skills/grill/SKILL.md +5 -1
  32. package/.agents/skills/grill/agents/openai.yaml +5 -0
  33. package/.agents/skills/harness-audit/SKILL.md +5 -1
  34. package/.agents/skills/harness-audit/agents/openai.yaml +5 -0
  35. package/.agents/skills/hook-development/SKILL.md +3 -1
  36. package/.agents/skills/mcp-builder/SKILL.md +3 -1
  37. package/.agents/skills/memory-cleanup/SKILL.md +5 -1
  38. package/.agents/skills/memory-cleanup/agents/openai.yaml +5 -0
  39. package/.agents/skills/mode-selector/SKILL.md +3 -1
  40. package/.agents/skills/navigator/SKILL.md +22 -0
  41. package/.agents/skills/navigator/agents/openai.yaml +5 -0
  42. package/.agents/skills/npm-publish/SKILL.md +4 -2
  43. package/.agents/skills/peekaboo-driver/SKILL.md +3 -1
  44. package/.agents/skills/persona-panel/SKILL.md +5 -1
  45. package/.agents/skills/persona-panel/agents/openai.yaml +5 -0
  46. package/.agents/skills/plan/SKILL.md +5 -1
  47. package/.agents/skills/plan/agents/openai.yaml +5 -0
  48. package/.agents/skills/playwright-driver/SKILL.md +3 -1
  49. package/.agents/skills/portfolio/SKILL.md +5 -1
  50. package/.agents/skills/portfolio/agents/openai.yaml +5 -0
  51. package/.agents/skills/quality-gates/SKILL.md +3 -1
  52. package/.agents/skills/reconcile/SKILL.md +5 -1
  53. package/.agents/skills/reconcile/agents/openai.yaml +5 -0
  54. package/.agents/skills/release/SKILL.md +5 -1
  55. package/.agents/skills/release/agents/openai.yaml +5 -0
  56. package/.agents/skills/remote-offload/SKILL.md +3 -1
  57. package/.agents/skills/repo-audit/SKILL.md +5 -1
  58. package/.agents/skills/repo-audit/agents/openai.yaml +5 -0
  59. package/.agents/skills/session/SKILL.md +21 -0
  60. package/.agents/skills/session/agents/openai.yaml +5 -0
  61. package/.agents/skills/session-end/SKILL.md +3 -1
  62. package/.agents/skills/session-plan/SKILL.md +3 -1
  63. package/.agents/skills/session-start/SKILL.md +3 -1
  64. package/.agents/skills/spinout/SKILL.md +5 -1
  65. package/.agents/skills/spinout/agents/openai.yaml +5 -0
  66. package/.agents/skills/sunset-review/SKILL.md +5 -1
  67. package/.agents/skills/sunset-review/agents/openai.yaml +5 -0
  68. package/.agents/skills/templates-ack/SKILL.md +21 -0
  69. package/.agents/skills/templates-ack/agents/openai.yaml +5 -0
  70. package/.agents/skills/test/SKILL.md +5 -1
  71. package/.agents/skills/test/agents/openai.yaml +5 -0
  72. package/.agents/skills/test-audit/SKILL.md +21 -0
  73. package/.agents/skills/test-audit/agents/openai.yaml +5 -0
  74. package/.agents/skills/test-runner/SKILL.md +3 -1
  75. package/.agents/skills/tmux-layout/SKILL.md +3 -1
  76. package/.agents/skills/using-orchestrator/SKILL.md +3 -1
  77. package/.agents/skills/ux-grill/SKILL.md +5 -1
  78. package/.agents/skills/ux-grill/agents/openai.yaml +5 -0
  79. package/.agents/skills/vault-mirror/SKILL.md +3 -1
  80. package/.agents/skills/vault-sync/SKILL.md +3 -1
  81. package/.agents/skills/wave-executor/SKILL.md +3 -1
  82. package/.agents/skills/write-executable-plan/SKILL.md +3 -1
  83. package/.claude-plugin/marketplace.json +1 -1
  84. package/.claude-plugin/plugin.json +1 -1
  85. package/.codex-plugin/plugin.json +4 -4
  86. package/.codex-plugin/skills/claude-md-drift-check/SKILL.md +1 -1
  87. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +1 -3
  88. package/.codex-plugin/skills/eval/SKILL.md +1 -1
  89. package/.codex-plugin/skills/evolve/SKILL.md +1 -1
  90. package/.codex-plugin/skills/navigator/SKILL.md +22 -0
  91. package/.codex-plugin/skills/{convergence-monitoring → navigator}/agents/openai.yaml +2 -2
  92. package/.codex-plugin/skills/npm-publish/SKILL.md +1 -3
  93. package/.codex-plugin/skills/session/SKILL.md +1 -1
  94. package/.codex-plugin/skills/test-audit/SKILL.md +21 -0
  95. package/.codex-plugin/skills/{npm-publish → test-audit}/agents/openai.yaml +1 -1
  96. package/.cursor/commands/eval.md +1 -1
  97. package/.cursor/commands/navigator.md +15 -0
  98. package/.cursor/commands/session.md +1 -1
  99. package/.cursor/commands/test-audit.md +14 -0
  100. package/.cursor/rules/000-session-orchestrator.mdc +0 -2
  101. package/.cursor/rules/050-plan.mdc +1 -1
  102. package/.cursor/rules/060-evolve.mdc +27 -12
  103. package/.cursor/skills/claude-md-drift-check/SKILL.md +1 -1
  104. package/.cursor/skills/convergence-monitoring/SKILL.md +1 -0
  105. package/.cursor/skills/eval/SKILL.md +1 -1
  106. package/.cursor/skills/navigator/SKILL.md +13 -0
  107. package/.cursor/skills/npm-publish/SKILL.md +1 -0
  108. package/.cursor/skills/test-audit/SKILL.md +12 -0
  109. package/.cursor-plugin/plugin.json +1 -1
  110. package/.orchestrator/policy/blocked-commands.json +12 -3
  111. package/AGENTS.md +9 -30
  112. package/CHANGELOG.md +206 -0
  113. package/README.md +13 -9
  114. package/SECURITY.md +12 -0
  115. package/agents/dialectic-deriver.md +13 -10
  116. package/agents/eval-judge.md +67 -45
  117. package/agents/skill-applied-judge.md +34 -19
  118. package/commands/session.md +7 -3
  119. package/docs/agent-authoring.md +2 -2
  120. package/docs/baseline.md +22 -7
  121. package/docs/ci-setup.md +57 -4
  122. package/docs/codex-setup.md +14 -2
  123. package/docs/components.md +12 -10
  124. package/docs/events-schema.md +65 -15
  125. package/docs/persona-panel.md +5 -4
  126. package/docs/rule-authoring.md +84 -17
  127. package/docs/scope-collision-guard.md +26 -4
  128. package/docs/session-config-reference.md +154 -12
  129. package/docs/session-config-template.md +41 -3
  130. package/docs/telemetry.md +2 -0
  131. package/hooks/_lib/hook-import-set.json +87 -6
  132. package/hooks/_lib/subagent-transcript.mjs +582 -31
  133. package/hooks/config-protection.mjs +11 -3
  134. package/hooks/cwd-change-restore.mjs +11 -3
  135. package/hooks/enforce-commands.mjs +70 -23
  136. package/hooks/enforce-scope.mjs +143 -33
  137. package/hooks/hooks-codex.json +1 -1
  138. package/hooks/hooks-cursor.json +5 -0
  139. package/hooks/hooks-pi.json +5 -0
  140. package/hooks/hooks.json +6 -1
  141. package/hooks/loop-guard.mjs +11 -3
  142. package/hooks/on-session-end.mjs +58 -23
  143. package/hooks/on-session-start.mjs +101 -11
  144. package/hooks/on-stop.mjs +170 -22
  145. package/hooks/operator-steer.mjs +11 -3
  146. package/hooks/post-bash-issue-budget-refund.mjs +18 -8
  147. package/hooks/post-bash-write-verify.mjs +3 -2
  148. package/hooks/post-edit-import-probe.mjs +17 -9
  149. package/hooks/post-edit-validate.mjs +13 -5
  150. package/hooks/post-subagent-discovery-validator.mjs +98 -13
  151. package/hooks/post-tool-batch-wave-signal.mjs +202 -38
  152. package/hooks/post-tool-failure-corrective-context.mjs +11 -5
  153. package/hooks/post-tooluse-frontend-slop.mjs +10 -4
  154. package/hooks/pre-auq-clarity.mjs +15 -2
  155. package/hooks/pre-bash-destructive-guard.mjs +80 -9
  156. package/hooks/pre-bash-issue-budget.mjs +16 -11
  157. package/hooks/pre-bash-memory-propose-audit.mjs +137 -56
  158. package/hooks/pre-bash-sessions-ledger-guard.mjs +419 -22
  159. package/hooks/pre-bash-staging-fence.mjs +335 -31
  160. package/hooks/pre-bash-templates-first.mjs +19 -14
  161. package/hooks/pre-edit-sessions-ledger-guard.mjs +162 -0
  162. package/hooks/pre-task-scope-disjoint.mjs +792 -74
  163. package/hooks/subagent-telemetry.mjs +111 -38
  164. package/hooks/wave-scope-commit-guard.mjs +197 -100
  165. package/monitors/monitors.json +1 -1
  166. package/output-styles/wave-summary.md +1 -1
  167. package/package.json +3 -3
  168. package/pi/prompts/eval.md +1 -1
  169. package/pi/prompts/navigator.md +12 -0
  170. package/pi/prompts/session.md +1 -1
  171. package/pi/prompts/test-audit.md +12 -0
  172. package/rules/README.md +7 -2
  173. package/rules/_index.md +3 -3
  174. package/rules/always-on/bash-harness-pitfalls.md +7 -1
  175. package/rules/opt-in-domain/prompt-caching.md +6 -2
  176. package/rules/opt-in-stack/backend-data.md +10 -2
  177. package/rules/opt-in-stack/backend.md +10 -4
  178. package/rules/opt-in-stack/frontend.md +7 -2
  179. package/rules/opt-in-stack/security-web.md +10 -4
  180. package/rules/opt-in-stack/swift.md +6 -2
  181. package/scripts/apply-session-learnings.mjs +492 -0
  182. package/scripts/archive-closed-prds.mjs +2 -1
  183. package/scripts/autopilot.mjs +70 -53
  184. package/scripts/backfill-abandoned-sessions.mjs +118 -16
  185. package/scripts/baseline-archetypes.mjs +1 -1
  186. package/scripts/check-package-manager.mjs +62 -5
  187. package/scripts/check-sessions-integrity.mjs +300 -0
  188. package/scripts/cursor-install.mjs +1 -4
  189. package/scripts/dialectic-deriver.mjs +50 -13
  190. package/scripts/emit-session.mjs +371 -31
  191. package/scripts/eval-session.mjs +65 -3
  192. package/scripts/export-hw-learnings.mjs +22 -3
  193. package/scripts/fleet-checkin.mjs +147 -0
  194. package/scripts/generate-agents-skills.mjs +102 -29
  195. package/scripts/generate-cursor-adapter.mjs +61 -16
  196. package/scripts/lib/agent-frontmatter.mjs +3 -3
  197. package/scripts/lib/agent-status.mjs +2 -31
  198. package/scripts/lib/auq/clarity.mjs +10 -2
  199. package/scripts/lib/auq/parse.mjs +12 -31
  200. package/scripts/lib/auq/schema.mjs +56 -41
  201. package/scripts/lib/auto-dialectic.mjs +304 -15
  202. package/scripts/lib/auto-dream.mjs +7 -6
  203. package/scripts/lib/autopilot/flags.mjs +18 -2
  204. package/scripts/lib/autopilot/kill-switches.mjs +6 -3
  205. package/scripts/lib/autopilot/loop.mjs +19 -2
  206. package/scripts/lib/autopilot/stall-sampler.mjs +80 -23
  207. package/scripts/lib/baseline-archetypes.mjs +41 -22
  208. package/scripts/lib/ci-status-banner.mjs +376 -16
  209. package/scripts/lib/command-blocker.mjs +275 -28
  210. package/scripts/lib/config/dialectic.mjs +12 -3
  211. package/scripts/lib/config/gate.mjs +74 -0
  212. package/scripts/lib/config/host-paths.mjs +79 -0
  213. package/scripts/lib/config/persona-gate-wave.mjs +3 -3
  214. package/scripts/lib/config/reaper.mjs +163 -0
  215. package/scripts/lib/config-schema.mjs +13 -0
  216. package/scripts/lib/config.mjs +85 -10
  217. package/scripts/lib/convergence-monitor.mjs +74 -11
  218. package/scripts/lib/ecosystem-health.mjs +11 -0
  219. package/scripts/lib/eval/engine.mjs +421 -53
  220. package/scripts/lib/eval/judge.mjs +463 -40
  221. package/scripts/lib/eval/schema.mjs +10 -1
  222. package/scripts/lib/events-rotation.mjs +221 -25
  223. package/scripts/lib/events-schema.mjs +114 -0
  224. package/scripts/lib/events.mjs +545 -7
  225. package/scripts/lib/fleet-protocol.mjs +270 -0
  226. package/scripts/lib/frontmatter-guard.mjs +21 -10
  227. package/scripts/lib/gates/gate-baseline.mjs +40 -5
  228. package/scripts/lib/gates/gate-full.mjs +35 -5
  229. package/scripts/lib/gates/gate-helpers.mjs +336 -23
  230. package/scripts/lib/gates/gate-incremental.mjs +49 -23
  231. package/scripts/lib/gates/gate-per-file.mjs +42 -8
  232. package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +6 -1
  233. package/scripts/lib/instruction-budget-guard.mjs +208 -8
  234. package/scripts/lib/io.mjs +42 -8
  235. package/scripts/lib/issue-close-strip-labels.mjs +207 -49
  236. package/scripts/lib/js-mask.mjs +197 -0
  237. package/scripts/lib/learnings/evolve-telemetry.mjs +11 -7
  238. package/scripts/lib/learnings/expiry-sweep.mjs +34 -3
  239. package/scripts/lib/learnings/io.mjs +154 -26
  240. package/scripts/lib/learnings/schema.mjs +163 -15
  241. package/scripts/lib/learnings/sizing-subject.mjs +2 -2
  242. package/scripts/lib/maintenance-due-banner.mjs +53 -88
  243. package/scripts/lib/memory-proposals/schema.mjs +11 -5
  244. package/scripts/lib/named-baseline-resolver.mjs +53 -28
  245. package/scripts/lib/named-vault-resolver.mjs +104 -5
  246. package/scripts/lib/orphan-reaper/defaults.mjs +41 -0
  247. package/scripts/lib/orphan-reaper/ps-snapshot.mjs +181 -0
  248. package/scripts/lib/orphan-reaper/reaper-audit.mjs +291 -0
  249. package/scripts/lib/orphan-reaper/reaper-decide.mjs +395 -0
  250. package/scripts/lib/orphan-reaper/scan-throttle.mjs +92 -0
  251. package/scripts/lib/orphan-reaper/scan.mjs +506 -0
  252. package/scripts/lib/orphan-reaper.mjs +316 -0
  253. package/scripts/lib/owner-yaml.mjs +104 -6
  254. package/scripts/lib/peer-cards/merger.mjs +48 -10
  255. package/scripts/lib/peer-cards/reader.mjs +78 -2
  256. package/scripts/lib/persona-panel/catalog-loader.mjs +1 -1
  257. package/scripts/lib/process-group.mjs +950 -0
  258. package/scripts/lib/project-hygiene.mjs +21 -1
  259. package/scripts/lib/quality-gate.mjs +152 -33
  260. package/scripts/lib/reconcile/backlog.mjs +368 -0
  261. package/scripts/lib/reconcile/engine.mjs +55 -188
  262. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +302 -60
  263. package/scripts/lib/reconcile/sanitize.mjs +69 -3
  264. package/scripts/lib/reconcile-nudge-banner.mjs +138 -45
  265. package/scripts/lib/resource-probe/parsers.mjs +31 -0
  266. package/scripts/lib/resource-probe.mjs +1 -1
  267. package/scripts/lib/rule-loader.mjs +141 -74
  268. package/scripts/lib/rules-sync.mjs +27 -12
  269. package/scripts/lib/scope-baseline.mjs +3 -4
  270. package/scripts/lib/scope-echo.mjs +39 -2
  271. package/scripts/lib/scope-gate.mjs +605 -1
  272. package/scripts/lib/session-close-backfill.mjs +33 -6
  273. package/scripts/lib/session-id.mjs +9 -20
  274. package/scripts/lib/session-invocation.mjs +20 -0
  275. package/scripts/lib/session-record-repair.mjs +183 -26
  276. package/scripts/lib/session-registry.mjs +27 -2
  277. package/scripts/lib/session-schema/constants.mjs +56 -2
  278. package/scripts/lib/session-schema/normalizer.mjs +56 -4
  279. package/scripts/lib/session-schema/validator.mjs +28 -1
  280. package/scripts/lib/session-schema.mjs +8 -3
  281. package/scripts/lib/session-start-probes.mjs +95 -10
  282. package/scripts/lib/session-token-rollup.mjs +245 -52
  283. package/scripts/lib/sessions-canonical.mjs +118 -4
  284. package/scripts/lib/sessions-integrity-banner.mjs +7 -1
  285. package/scripts/lib/sessions-staleness-banner.mjs +193 -51
  286. package/scripts/lib/sh-quote.mjs +29 -0
  287. package/scripts/lib/skill-evidence-window.mjs +891 -0
  288. package/scripts/lib/skill-evolution/candidate-intake.mjs +133 -12
  289. package/scripts/lib/skill-evolution/engine.mjs +18 -9
  290. package/scripts/lib/skill-judge.mjs +45 -3
  291. package/scripts/lib/subagents-schema.mjs +30 -3
  292. package/scripts/lib/tail-window.mjs +56 -0
  293. package/scripts/lib/telemetry/pricing.mjs +118 -71
  294. package/scripts/lib/telemetry/schema.mjs +30 -0
  295. package/scripts/lib/telemetry/sync.mjs +61 -6
  296. package/scripts/lib/telemetry-flush-health-banner.mjs +4 -22
  297. package/scripts/lib/test-runner/issue-reconcile.mjs +48 -16
  298. package/scripts/lib/tests-src-ratio.mjs +140 -23
  299. package/scripts/lib/tmux-layout/layouts.mjs +1 -11
  300. package/scripts/lib/tmux-layout/telemetry-stats.mjs +72 -13
  301. package/scripts/lib/tmux-layout/tmux-shell.mjs +2 -11
  302. package/scripts/lib/user-invocable-skills.mjs +23 -3
  303. package/scripts/lib/ux-grill/reconcile.mjs +48 -22
  304. package/scripts/lib/validate/check-agents-skills.mjs +26 -15
  305. package/scripts/lib/validate/check-agents.mjs +1 -1
  306. package/scripts/lib/validate/check-cursor-adapter.mjs +1 -0
  307. package/scripts/lib/validate/check-entry-guard.mjs +13 -50
  308. package/scripts/lib/validate/check-hook-entry-guards.mjs +636 -0
  309. package/scripts/lib/validate/check-hooks-symmetry.mjs +5 -0
  310. package/scripts/lib/validate/check-learnings-shell-writes.mjs +214 -0
  311. package/scripts/lib/validate/check-pi-prompts.mjs +1 -0
  312. package/scripts/lib/validate/check-rules.mjs +7 -5
  313. package/scripts/lib/validate/check-skill-links.mjs +9 -1
  314. package/scripts/lib/validate/check-skill-script-paths.mjs +239 -27
  315. package/scripts/lib/validate/check-test-git-config-target.mjs +24 -34
  316. package/scripts/lib/validate/check-test-value-bans.mjs +87 -14
  317. package/scripts/lib/validate/check-unicode-safety.mjs +1 -0
  318. package/scripts/lib/validate/check-untracked-test-deps.mjs +7 -102
  319. package/scripts/lib/validate/check-unwired-features.mjs +130 -27
  320. package/scripts/lib/validate/check-validator-registration.mjs +34 -10
  321. package/scripts/lib/validate/confidential-names.mjs +10 -0
  322. package/scripts/lib/validate-vendored-rules.mjs +210 -84
  323. package/scripts/lib/vault-mirror/namespace.mjs +46 -8
  324. package/scripts/lib/vault-mirror/process.mjs +10 -3
  325. package/scripts/lib/vault-mirror/render-sessions.mjs +12 -2
  326. package/scripts/lib/vault-mirror/telemetry.mjs +8 -1
  327. package/scripts/lib/vault-status/board-writer.mjs +48 -11
  328. package/scripts/lib/vault-status/narrative-mirror.mjs +71 -16
  329. package/scripts/lib/vault-yaml.mjs +118 -0
  330. package/scripts/lib/wave-executor/dispatch-common.mjs +10 -18
  331. package/scripts/lib/wave-executor/foreign-dispatch.mjs +1 -1
  332. package/scripts/lib/wave-executor/remote-dispatch.mjs +1 -1
  333. package/scripts/lib/wave-resource-gate.mjs +34 -8
  334. package/scripts/lib/worktree/lifecycle.mjs +153 -1
  335. package/scripts/memory-propose.mjs +18 -5
  336. package/scripts/release-session-lock.mjs +306 -0
  337. package/scripts/release.mjs +40 -8
  338. package/scripts/repair-invalid-sessions.mjs +37 -4
  339. package/scripts/resolve-session-invocation.mjs +59 -0
  340. package/scripts/run-migrate-v2-cross-repo.mjs +158 -30
  341. package/scripts/run-quality-gate.mjs +357 -197
  342. package/scripts/site-numbers.mjs +163 -5
  343. package/scripts/sweep-expired-learnings.mjs +56 -5
  344. package/scripts/sweep-expired-rules.mjs +16 -4
  345. package/scripts/validate-plugin.mjs +19 -0
  346. package/scripts/validate-wave-scope.mjs +32 -105
  347. package/scripts/vault-integration-watcher.mjs +2 -1
  348. package/scripts/vault-mirror.mjs +81 -47
  349. package/scripts/wave-scope-binding.mjs +2 -1
  350. package/skills/_shared/config-reading.md +3 -3
  351. package/skills/_shared/fleet-protocol.md +131 -0
  352. package/skills/_shared/platform-tools.md +23 -11
  353. package/skills/_shared/state-ownership.md +5 -0
  354. package/skills/autopilot/SKILL.md +47 -18
  355. package/skills/bootstrap/SKILL.md +1 -1
  356. package/skills/bootstrap/_shared-template.md +1 -1
  357. package/skills/bootstrap/fast-template.md +1 -1
  358. package/skills/bootstrap/private-contract.md +2 -1
  359. package/skills/bootstrap/public-fallback.md +6 -3
  360. package/skills/bootstrap/references/bootstrap-retroactive-flow.md +2 -1
  361. package/skills/claude-md-drift-check/SKILL.md +10 -10
  362. package/skills/claude-md-drift-check/checker.mjs +26 -18
  363. package/skills/convergence-monitoring/README.md +8 -1
  364. package/skills/convergence-monitoring/SIGNALS.md +50 -6
  365. package/skills/convergence-monitoring/SKILL.md +15 -6
  366. package/skills/eval/SKILL.md +39 -24
  367. package/skills/eval/rubric-v1.md +1 -0
  368. package/skills/eval/rubric-v2.md +457 -0
  369. package/skills/evolve/SKILL.md +3 -3
  370. package/skills/evolve/references/evolve-analyze-mode.md +10 -6
  371. package/skills/evolve/references/evolve-dialectic-mode.md +42 -25
  372. package/skills/gitlab-ops/SKILL.md +3 -2
  373. package/skills/memory-cleanup/SKILL.md +1 -1
  374. package/skills/navigator/SKILL.md +193 -0
  375. package/skills/navigator/references/account-check.sh +87 -0
  376. package/skills/navigator/references/fleet-decisions.mjs +231 -0
  377. package/skills/navigator/references/slot-check.sh +114 -0
  378. package/skills/npm-publish/SKILL.md +1 -1
  379. package/skills/persona-panel/SKILL.md +2 -2
  380. package/skills/persona-panel/persona-format.md +2 -2
  381. package/skills/persona-panel/presets/designer-lens.md +1 -1
  382. package/skills/persona-panel/presets/engineer-lens.md +1 -1
  383. package/skills/persona-panel/presets/pm-lens.md +1 -1
  384. package/skills/plan/mode-retro.md +19 -4
  385. package/skills/quality-gates/SKILL.md +6 -4
  386. package/skills/reconcile/SKILL.md +11 -0
  387. package/skills/remote-offload/SKILL.md +4 -2
  388. package/skills/session-end/SKILL.md +13 -16
  389. package/skills/session-end/discovery-scan.md +1 -1
  390. package/skills/session-end/learning-patterns.md +22 -12
  391. package/skills/session-end/metrics-collection.md +5 -6
  392. package/skills/session-end/phase-3-6-tail.md +55 -9
  393. package/skills/session-end/references/phase-3-documentation-updates.md +2 -2
  394. package/skills/session-end/references/phase-4a-worktree-cleanup.md +2 -0
  395. package/skills/session-end/references/phase-5-issue-cleanup.md +9 -14
  396. package/skills/session-end/references/session-summary-template.md +1 -1
  397. package/skills/session-end/session-metrics-write.md +32 -60
  398. package/skills/session-plan/SKILL.md +17 -8
  399. package/skills/session-plan/references/session-plan-task-classification.md +2 -2
  400. package/skills/session-start/SKILL.md +6 -0
  401. package/skills/session-start/references/operations-contract.md +4 -0
  402. package/skills/session-start/references/phase-1-7-vault-status-board.md +1 -1
  403. package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
  404. package/skills/test-audit/SKILL.md +152 -0
  405. package/skills/test-audit/references/campaign.md +111 -0
  406. package/skills/test-audit/references/mutate.sh +50 -0
  407. package/skills/ux-grill/SKILL.md +1 -1
  408. package/skills/wave-executor/SKILL.md +9 -5
  409. package/skills/wave-executor/circuit-breaker.md +2 -0
  410. package/skills/wave-executor/references/wave-executor-state-init.md +8 -3
  411. package/skills/wave-executor/references/wave-loop-dispatch.md +5 -2
  412. package/skills/wave-executor/references/wave-loop-review.md +3 -5
  413. package/templates/personas/README.md +5 -5
  414. package/templates/personas/accounting-compliance.v1.md +1 -1
  415. package/templates/personas/accounting-tax-advisor.v1.md +1 -1
  416. package/templates/personas/buyer-p1-cto.v1.md +1 -1
  417. package/templates/personas/buyer-p2-kanzlei.v1.md +1 -1
  418. package/templates/personas/buyer-p3-build.v1.md +1 -1
  419. package/templates/personas/buyer-p4-tech-veto.v1.md +1 -1
  420. package/templates/personas/buyer-p5-solo.v1.md +1 -1
  421. package/templates/personas/buyer-p6-ld.v1.md +1 -1
  422. package/templates/personas/klima-ai-expert.v1.md +1 -1
  423. package/templates/personas/klima-physicist.v1.md +1 -1
  424. package/.cursor/commands/convergence-monitoring.md +0 -13
  425. package/.cursor/commands/npm-publish.md +0 -13
  426. package/pi/prompts/convergence-monitoring.md +0 -11
  427. package/pi/prompts/npm-publish.md +0 -11
@@ -2,21 +2,39 @@
2
2
  * autopilot/stall-sampler.mjs — Stateless progress sampler for STALL_TIMEOUT
3
3
  * kill-switch (ADR-364, issue #371).
4
4
  *
5
- * The sampler reads `autopilot.jsonl` mtime as the progress marker: the
6
- * autopilot loop writes one record per session atomically (tmp+rename), so the
7
- * file mtime advances exactly when the loop makes progress. No false-positive
8
- * churn from in-place writes, no need to parse JSON, microsecond precision.
5
+ * PROGRESS MARKER PRECEDENCE (HR-102: a better signal REPLACES a worse one).
9
6
  *
10
- * Stateless — single statSync call per invocation, no side effects, no async.
11
- * Wire-up to the kill-switch + loop is deferred (see #371 follow-up); this
12
- * module ships in isolation under the ADR-364 thin-slice MVP.
7
+ * 1. `session.lock` `last_heartbeat` (schema v2) — advances DURING a run:
8
+ * `hooks/on-stop.mjs` refreshes it at every turn-end and
9
+ * `hooks/post-tool-batch-wave-signal.mjs` at every tool batch.
10
+ * 2. `autopilot.jsonl` mtime — the legacy marker, used only when no lock path
11
+ * is supplied or the lock is absent/corrupt/timestamp-less.
12
+ *
13
+ * The header of this module used to claim `autopilot.jsonl` carries "one record
14
+ * per session". It does not: `telemetry.mjs` writes ONE record per /autopilot
15
+ * INVOCATION, and `loop.mjs` calls it exactly twice — once for the dry-run
16
+ * preview and once AFTER the `for(;;)` loop. So during a real run the mtime the
17
+ * sampler read belonged to the PREVIOUS autopilot run, typically hours or days
18
+ * old, and the post-session check fired STALL_TIMEOUT after iteration 1 every
19
+ * time. The append-once contract is correct and stays; the marker was wrong.
20
+ *
21
+ * CEILING (BV-004). The heartbeat only advances while some live session owns the
22
+ * lock: `updateHeartbeat()` refuses on a session_id mismatch, and a child
23
+ * `claude -p` spawned while a parent session already holds the lock never
24
+ * acquires one (`hooks/_lib/lock-bootstrap.mjs` bails on `reason: 'active'`).
25
+ * In that one invocation shape — the headless driver started FROM a chat
26
+ * session rather than from a bare shell — the heartbeat freezes and the check
27
+ * degrades to today's behaviour. Revisit if STALL_TIMEOUT is ever observed
28
+ * firing on a run whose child session did real work.
29
+ *
30
+ * Stateless — at most two sync reads per invocation, no side effects, no async.
13
31
  *
14
32
  * Exports:
15
33
  * SAMPLE_CADENCE_MS — shared constant (30_000) defining the "fresh" window
16
34
  * sampleProgress(opts) — returns progress descriptor; never throws
17
35
  */
18
36
 
19
- import { statSync } from 'node:fs';
37
+ import { readFileSync, statSync } from 'node:fs';
20
38
 
21
39
  // ---------------------------------------------------------------------------
22
40
  // Constants
@@ -32,9 +50,40 @@ export const SAMPLE_CADENCE_MS = 30_000;
32
50
  const DEFAULT_AUTOPILOT_JSONL = '.orchestrator/metrics/autopilot.jsonl';
33
51
  const DEFAULT_STALL_TIMEOUT_SECONDS = 600;
34
52
  const MARKER_SUCCESS = 'autopilot.jsonl:mtime';
53
+ const MARKER_HEARTBEAT = 'session.lock:last_heartbeat';
35
54
  const MARKER_MISSING = 'missing';
36
55
  const MARKER_INVALID = 'invalid';
37
56
 
57
+ /**
58
+ * Read the live heartbeat timestamp (ms) out of `session.lock`.
59
+ *
60
+ * Returns `null` — meaning "fall back to the mtime marker" — for every failure
61
+ * mode: no path supplied, file absent, unreadable, not JSON, or carrying no
62
+ * parsable timestamp. A missing measurement is NOT a zero here; conflating the
63
+ * two would report a stall of `now` seconds the moment the lock is unreadable.
64
+ *
65
+ * @param {string} [sessionLockPath]
66
+ * @returns {number | null}
67
+ */
68
+ function readHeartbeatMs(sessionLockPath) {
69
+ if (typeof sessionLockPath !== 'string' || sessionLockPath.length === 0) return null;
70
+ let lock;
71
+ try {
72
+ lock = JSON.parse(readFileSync(sessionLockPath, 'utf8'));
73
+ } catch {
74
+ return null;
75
+ }
76
+ if (typeof lock !== 'object' || lock === null) return null;
77
+ // Same precedence `session-lock.mjs` uses on read: a v1 lock has no
78
+ // `last_heartbeat`, and its `started_at` is the best available stand-in.
79
+ const raw = typeof lock.last_heartbeat === 'string' && lock.last_heartbeat.length > 0
80
+ ? lock.last_heartbeat
81
+ : lock.started_at;
82
+ if (typeof raw !== 'string' || raw.length === 0) return null;
83
+ const ms = Date.parse(raw);
84
+ return Number.isFinite(ms) ? ms : null;
85
+ }
86
+
38
87
  // ---------------------------------------------------------------------------
39
88
  // Progress sampler
40
89
  // ---------------------------------------------------------------------------
@@ -45,6 +94,10 @@ const MARKER_INVALID = 'invalid';
45
94
  * @param {object} [opts]
46
95
  * @param {string} [opts.autopilotJsonlPath] — path to autopilot.jsonl (default
47
96
  * '.orchestrator/metrics/autopilot.jsonl').
97
+ * @param {string} [opts.sessionLockPath] — path to `session.lock`. When supplied
98
+ * and readable, its `last_heartbeat` (falling back to `started_at`, the schema
99
+ * v1 normalisation `session-lock.mjs` applies on read) REPLACES the mtime
100
+ * marker. Omitted → mtime only, which is what every pre-existing caller gets.
48
101
  * @param {number} [opts.stallTimeoutSeconds] — kill-switch threshold (default
49
102
  * 600). NOT range-clamped here; caller is responsible for bounds.
50
103
  * @param {() => number} [opts.nowMs] — wall-clock supplier (default Date.now).
@@ -66,22 +119,26 @@ export function sampleProgress(opts = {}) {
66
119
  void _stallTimeoutSeconds;
67
120
  const nowMs = typeof opts.nowMs === 'function' ? opts.nowMs : Date.now;
68
121
 
69
- let mtimeMs;
70
- try {
71
- const st = statSync(autopilotJsonlPath);
72
- mtimeMs = st.mtimeMs;
73
- } catch (err) {
74
- const marker = err && err.code === 'ENOENT' ? MARKER_MISSING : MARKER_INVALID;
75
- return {
76
- progressed: false,
77
- lastMarker: null,
78
- stallSeconds: 0,
79
- marker,
80
- };
122
+ let markerMs = readHeartbeatMs(opts.sessionLockPath);
123
+ let markerName = MARKER_HEARTBEAT;
124
+
125
+ if (markerMs === null) {
126
+ markerName = MARKER_SUCCESS;
127
+ try {
128
+ markerMs = statSync(autopilotJsonlPath).mtimeMs;
129
+ } catch (err) {
130
+ const marker = err && err.code === 'ENOENT' ? MARKER_MISSING : MARKER_INVALID;
131
+ return {
132
+ progressed: false,
133
+ lastMarker: null,
134
+ stallSeconds: 0,
135
+ marker,
136
+ };
137
+ }
81
138
  }
82
139
 
83
140
  const now = nowMs();
84
- const deltaMs = now - mtimeMs;
141
+ const deltaMs = now - markerMs;
85
142
  // Clamp negative deltas (clock skew, file mtime in the future) to 0.
86
143
  const stallSeconds = Math.max(0, Math.round(deltaMs / 1000));
87
144
  // Fresh if within the sample cadence window (also covers the clock-skew
@@ -90,8 +147,8 @@ export function sampleProgress(opts = {}) {
90
147
 
91
148
  return {
92
149
  progressed,
93
- lastMarker: mtimeMs,
150
+ lastMarker: markerMs,
94
151
  stallSeconds,
95
- marker: MARKER_SUCCESS,
152
+ marker: markerName,
96
153
  };
97
154
  }
@@ -19,10 +19,11 @@ const BASENAME = /^[a-zA-Z0-9][a-zA-Z0-9_.-]*\.md$/;
19
19
  const unique = (items) => [...new Set(items)].sort();
20
20
  const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
21
21
 
22
+ /** `message` must never interpolate a baseline root or any other host path. */
22
23
  export class BaselineContractError extends Error {
23
- constructor(reason) { super(`Baseline archetype lookup failed (${reason}).`); this.name = 'BaselineContractError'; this.reason = reason; }
24
+ constructor(reason, message = `Baseline archetype lookup failed (${reason}).`) { super(message); this.name = 'BaselineContractError'; this.reason = reason; }
24
25
  }
25
- function fail(reason = 'invalid-contract') { throw new BaselineContractError(reason); }
26
+ function fail(reason = 'invalid-contract', message) { throw new BaselineContractError(reason, message); }
26
27
  function check(condition) { if (!condition) fail(); }
27
28
  function shape(value, required, optional = []) {
28
29
  check(object(value) && required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => [...required, ...optional].includes(key)));
@@ -122,24 +123,38 @@ process.stdout.write(JSON.stringify(resolveConfiguredBaselinePath(JSON.parse(rea
122
123
  return realpathSync(root);
123
124
  }
124
125
 
125
- /** Resolve a canonical relative source and reject symlinks at every component. */
126
- export function baselineSourcePath(root, source, directory = false) {
126
+ /** Resolve a canonical relative source and reject symlinks at every component.
127
+ * Only an ENOENT thrown by the per-component `lstatSync` itself maps to
128
+ * `missingReason`; every other failure is `unsafe-source`. Existence is never
129
+ * probed with a link-following call (existsSync/statSync/accessSync/realpathSync):
130
+ * a dangling symlink would then read as "missing" instead of `unsafe-source`.
131
+ */
132
+ export function baselineSourcePath(root, source, directory = false, { missingReason = 'unsafe-source' } = {}) {
127
133
  relative(source);
134
+ // Resolved first: a vanished root is unsafe, never a missing source.
135
+ let realRoot;
136
+ try { realRoot = realpathSync(root); } catch { fail('unsafe-source'); }
128
137
  let current = root;
129
- try {
130
- for (const component of source.split('/')) {
131
- current = path.join(current, component);
132
- if (lstatSync(current).isSymbolicLink()) fail('unsafe-source');
133
- }
134
- const stat = lstatSync(current);
135
- if (directory ? !stat.isDirectory() : !stat.isFile()) fail('unsafe-source');
136
- if (!realpathSync(current).startsWith(`${realpathSync(root)}${path.sep}`)) fail('unsafe-source');
137
- return current;
138
- } catch { fail('unsafe-source'); }
138
+ let stat;
139
+ for (const component of source.split('/')) {
140
+ current = path.join(current, component);
141
+ try { stat = lstatSync(current); } catch (error) { fail(error?.code === 'ENOENT' ? missingReason : 'unsafe-source'); }
142
+ if (stat.isSymbolicLink()) fail('unsafe-source');
143
+ }
144
+ if (directory ? !stat.isDirectory() : !stat.isFile()) fail('unsafe-source');
145
+ let real;
146
+ try { real = realpathSync(current); } catch { fail('unsafe-source'); }
147
+ if (!real.startsWith(`${realRoot}${path.sep}`)) fail('unsafe-source');
148
+ return current;
139
149
  }
140
150
 
151
+ const PRODUCER = 'scripts/archetype-manifest.mjs';
141
152
  function projection(root, args, { timeoutMs = 5000, maxBuffer = MAX_BYTES } = {}) {
142
- const script = baselineSourcePath(root, 'scripts/archetype-manifest.mjs');
153
+ let script;
154
+ try { script = baselineSourcePath(root, PRODUCER, false, { missingReason: 'producer-missing' }); } catch (error) {
155
+ if (error?.reason !== 'producer-missing') throw error;
156
+ fail('producer-missing', `Baseline archetype lookup failed (producer-missing): the configured baseline has no ${PRODUCER} exporter — see docs/baseline.md § How bootstrap finds it.`);
157
+ }
143
158
  const result = spawnSync(process.execPath, [script, ...args], {
144
159
  cwd: root, encoding: 'utf8', timeout: Math.min(timeoutMs, 5000), maxBuffer: Math.min(maxBuffer, MAX_BYTES),
145
160
  shell: false, killSignal: 'SIGKILL', stdio: ['ignore', 'pipe', 'pipe'],
@@ -195,7 +210,8 @@ export async function loadBaselineArchetypes(options = {}) {
195
210
  let manifest;
196
211
  try { manifest = validateBaselineContract(JSON.parse(projection(root, ['export'], options))); }
197
212
  catch (error) { if (error instanceof BaselineContractError) throw error; fail(); }
198
- for (const item of manifest.archetypes) baselineSourcePath(root, item.templatePath, true);
213
+ // An absent declared source is an incomplete baseline, not a security refusal (#1447 3a).
214
+ for (const item of manifest.archetypes) baselineSourcePath(root, item.templatePath, true, { missingReason: 'invalid-contract' });
199
215
  const facts = collectFacts(repoRoot);
200
216
  const ordered = [...manifest.archetypes].sort((a, b) => a.order - b.order);
201
217
  const archetypes = ordered.map(({ id, order, runtimes, packageManagers, ui, api, deploy }) => ({ id, order, runtimes, packageManagers, ui, api, deploy }));
@@ -220,7 +236,7 @@ export async function loadBaselineArchetypes(options = {}) {
220
236
  if (!ruleTargets.includes(name) || seen.has(name)) fail('invalid-rule-projection');
221
237
  seen.add(name);
222
238
  if (owned.includes(name)) continue;
223
- baselineSourcePath(root, source);
239
+ baselineSourcePath(root, source, false, { missingReason: 'invalid-rule-projection' });
224
240
  baselineRules.push({ source, target: `.claude/rules/${name}` });
225
241
  }
226
242
  if (ruleTargets.some((name) => !seen.has(name))) fail('invalid-rule-projection');
@@ -230,7 +246,9 @@ export async function loadBaselineArchetypes(options = {}) {
230
246
  pluginRuleTargets: ruleTargets.filter((name) => owned.includes(name)), baselineRules,
231
247
  } };
232
248
  } catch (error) {
233
- return { status: 'error', reason: error instanceof BaselineContractError ? error.reason : 'lookup-failed', archetypes: [], selected: null };
249
+ // Only a BaselineContractError message is path-free by construction; others stay opaque.
250
+ const contract = error instanceof BaselineContractError;
251
+ return { status: 'error', reason: contract ? error.reason : 'lookup-failed', ...(contract && { message: error.message }), archetypes: [], selected: null };
234
252
  }
235
253
  }
236
254
 
@@ -290,11 +308,12 @@ function applyCopies(plan) {
290
308
  return { status: 'applied', created, preserved };
291
309
  }
292
310
  function applyFailure(error) {
293
- return { status: 'error', reason: error instanceof BaselineContractError ? error.reason : 'apply-failed', created: [], preserved: [] };
311
+ const contract = error instanceof BaselineContractError;
312
+ return { status: 'error', reason: contract ? error.reason : 'apply-failed', ...(contract && { message: error.message }), created: [], preserved: [] };
294
313
  }
295
314
  async function selectedContext(options) {
296
315
  const result = await loadBaselineArchetypes(options);
297
- if (result.status !== 'private' || !result.selected) fail(result.reason);
316
+ if (result.status !== 'private' || !result.selected) fail(result.reason, result.message);
298
317
  const root = await resolveBaselineLocation(options);
299
318
  if (!root) fail('baseline-unavailable');
300
319
  return { root, selected: result.selected };
@@ -340,7 +359,7 @@ export async function scaffoldBaselineArchetype(options = {}) {
340
359
  const { repoRoot = process.cwd(), projectName } = options;
341
360
  if (typeof projectName !== 'string' || !ID.test(projectName)) fail('invalid-project-name');
342
361
  const { root, selected } = await selectedContext(options);
343
- const template = baselineSourcePath(root, selected.templatePath, true);
362
+ const template = baselineSourcePath(root, selected.templatePath, true, { missingReason: 'invalid-contract' });
344
363
  sourceFiles(template);
345
364
  const shared = baselineSourcePath(root, 'templates/shared', true);
346
365
  sourceFiles(shared);
@@ -401,7 +420,7 @@ export async function syncBootstrapRules(options = {}) {
401
420
  // ordinary plugin rules, just as its minimal scaffold does.
402
421
  const contract = options.minimal ? { status: 'public', selected: null }
403
422
  : await loadBaselineArchetypes({ ...options, repoRoot, pluginRoot, archetype });
404
- if (contract.status === 'error') fail(contract.reason);
423
+ if (contract.status === 'error') fail(contract.reason, contract.message);
405
424
  if (contract.status === 'private' && !contract.selected && !hasUnselectedFastLock(repoRoot)) fail(contract.reason);
406
425
  const before = new Set();
407
426
  for (const name of pluginRuleTargets(pluginRoot)) {