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,347 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * scripts/lifecycle-sim-v6.mjs — Lifecycle simulation v6
4
- *
5
- * Issue #86 — measure the interaction between SO's enforcement layer and the
6
- * downstream Claude Code agent layer. Real telemetry (GL#84) is still blocked,
7
- * so v6 falls back to a discrete-event simulation parameterised from
8
- * directional intuition codified in the issue and the existing v3.2 docs.
9
- *
10
- * The sim does NOT claim statistical authority. It produces a directional
11
- * comparison between `enforcement: warn` and `enforcement: strict` over N
12
- * synthetic sessions with a fixed RNG seed. The output is meant to seed a
13
- * follow-up real-run experiment, not to drive a policy flip on its own.
14
- *
15
- * Usage:
16
- * node scripts/lifecycle-sim-v6.mjs [--enforcement warn|strict|both]
17
- * [--sessions N] [--seed K]
18
- * [--json]
19
- *
20
- * Defaults: --enforcement both --sessions 100 --seed 42
21
- *
22
- * Exit codes (per cli-design.md):
23
- * 0 — sim ran successfully
24
- * 1 — bad CLI args
25
- * 2 — internal error
26
- */
27
-
28
- import { parseArgs } from 'node:util';
29
-
30
- // -----------------------------------------------------------------------------
31
- // Deterministic RNG — mulberry32 (small, well-known, seedable)
32
- // -----------------------------------------------------------------------------
33
- function mulberry32(seed) {
34
- let a = seed >>> 0;
35
- return function rng() {
36
- a = (a + 0x6d2b79f5) >>> 0;
37
- let t = a;
38
- t = Math.imul(t ^ (t >>> 15), t | 1);
39
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
40
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
41
- };
42
- }
43
-
44
- /** Box-Muller normal sample, clamped to [min, max], rounded to int. */
45
- function gaussianInt(rng, mean, stddev, min, max) {
46
- // two uniforms → standard normal
47
- let u1 = rng();
48
- if (u1 < 1e-9) u1 = 1e-9;
49
- const u2 = rng();
50
- const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
51
- const value = Math.round(mean + z * stddev);
52
- return Math.max(min, Math.min(max, value));
53
- }
54
-
55
- // -----------------------------------------------------------------------------
56
- // Simulation parameters (kept as an explicit object so the report can echo them)
57
- // -----------------------------------------------------------------------------
58
- const PARAMS = Object.freeze({
59
- // Per-session planned issues sampled from a clipped Gaussian.
60
- plannedMean: 12,
61
- plannedStddev: 5,
62
- plannedMin: 5,
63
- plannedMax: 25,
64
-
65
- // Base completion rate (fraction of planned issues an idealised session
66
- // completes when nothing is blocked). Per-session jitter applied on top.
67
- baseCompletion: 0.78,
68
- completionJitter: 0.08, // ±8 percentage points
69
-
70
- // Probability that a planned issue triggers a scope-friction event during
71
- // its first edit attempt. Independent of enforcement level — the friction
72
- // exists regardless; what differs is what the harness *does* about it.
73
- scopeFrictionProb: 0.12,
74
-
75
- // Carryover into next session: fraction of unfinished issues that roll over.
76
- // 1.0 = everything carries over; lower values model dropped scope.
77
- carryoverFraction: 1.0,
78
-
79
- // Stagnation threshold: a session is "stagnant" when carryover_ratio > this.
80
- stagnationCarryoverRatio: 0.5,
81
-
82
- // Stagnation streak length triggering the "stagnant streak" bucket.
83
- stagnationStreakLength: 3,
84
-
85
- // Enforcement-mode-specific multipliers — see the report for the rationale
86
- // and limits of these values.
87
- modes: {
88
- warn: {
89
- // warn: friction is logged but the agent is allowed to retry, often
90
- // converging on a partial solution. Friction events drag completion
91
- // down moderately (each event costs ~1.5% completion) and a small
92
- // fraction of friction events become permanent blocks.
93
- frictionCompletionPenalty: 0.015,
94
- blockConversionRate: 0.18,
95
- },
96
- strict: {
97
- // strict: every scope-violation hard-aborts the agent's current step.
98
- // The agent has to re-plan. This hurts completion more per event but
99
- // converts fewer events into permanent blocks because the agent never
100
- // produces partial-but-wrong output.
101
- frictionCompletionPenalty: 0.025,
102
- blockConversionRate: 0.08,
103
- },
104
- },
105
- });
106
-
107
- // -----------------------------------------------------------------------------
108
- // Single-mode simulation
109
- // -----------------------------------------------------------------------------
110
- function simulateMode({ mode, sessions, seed }) {
111
- if (!PARAMS.modes[mode]) {
112
- throw new Error(`Unknown enforcement mode: ${mode}`);
113
- }
114
- const { frictionCompletionPenalty, blockConversionRate } = PARAMS.modes[mode];
115
-
116
- // Seed each mode independently of the other so order doesn't matter, but
117
- // derive the seed from the user seed so re-runs with the same --seed are
118
- // identical.
119
- const modeSeed = seed ^ (mode === 'warn' ? 0xa5a5a5a5 : 0x5a5a5a5a);
120
- const rng = mulberry32(modeSeed);
121
-
122
- let carryoverIssues = 0;
123
- let stagnationStreak = 0;
124
- let longestStagnationStreak = 0;
125
- let stagnantSessionCount = 0;
126
- let totalPlanned = 0;
127
- let totalCompleted = 0;
128
- let totalBlocked = 0;
129
- const carryoverRatios = [];
130
-
131
- for (let i = 0; i < sessions; i++) {
132
- const fresh = gaussianInt(
133
- rng,
134
- PARAMS.plannedMean,
135
- PARAMS.plannedStddev,
136
- PARAMS.plannedMin,
137
- PARAMS.plannedMax,
138
- );
139
- const planned = fresh + carryoverIssues;
140
- totalPlanned += planned;
141
-
142
- // Friction events: one Bernoulli draw per planned issue.
143
- let frictionEvents = 0;
144
- let permanentBlocks = 0;
145
- for (let j = 0; j < planned; j++) {
146
- if (rng() < PARAMS.scopeFrictionProb) {
147
- frictionEvents += 1;
148
- if (rng() < blockConversionRate) {
149
- permanentBlocks += 1;
150
- }
151
- }
152
- }
153
-
154
- // Effective completion rate — base, jitter, friction penalty.
155
- const jitter = (rng() * 2 - 1) * PARAMS.completionJitter;
156
- let completionRate = PARAMS.baseCompletion + jitter;
157
- completionRate -= frictionEvents * frictionCompletionPenalty;
158
- completionRate = Math.max(0, Math.min(1, completionRate));
159
-
160
- const completable = planned - permanentBlocks;
161
- const completed = Math.min(completable, Math.round(completable * completionRate));
162
- totalCompleted += completed;
163
- totalBlocked += permanentBlocks;
164
-
165
- const unfinished = planned - completed;
166
- const carryoverRatio = planned === 0 ? 0 : unfinished / planned;
167
- carryoverRatios.push(carryoverRatio);
168
-
169
- if (carryoverRatio > PARAMS.stagnationCarryoverRatio) {
170
- stagnationStreak += 1;
171
- if (stagnationStreak >= PARAMS.stagnationStreakLength) {
172
- stagnantSessionCount += 1;
173
- }
174
- if (stagnationStreak > longestStagnationStreak) {
175
- longestStagnationStreak = stagnationStreak;
176
- }
177
- } else {
178
- stagnationStreak = 0;
179
- }
180
-
181
- carryoverIssues = Math.round(unfinished * PARAMS.carryoverFraction);
182
- }
183
-
184
- carryoverRatios.sort((a, b) => a - b);
185
- const meanCarryover =
186
- carryoverRatios.reduce((s, v) => s + v, 0) / carryoverRatios.length;
187
- const p95Index = Math.min(
188
- carryoverRatios.length - 1,
189
- Math.floor(0.95 * carryoverRatios.length),
190
- );
191
- const p95Carryover = carryoverRatios[p95Index];
192
-
193
- return {
194
- mode,
195
- sessions,
196
- totals: {
197
- planned: totalPlanned,
198
- completed: totalCompleted,
199
- blocked: totalBlocked,
200
- },
201
- completionRatio: totalPlanned === 0 ? 0 : totalCompleted / totalPlanned,
202
- carryover: {
203
- meanRatio: meanCarryover,
204
- p95Ratio: p95Carryover,
205
- },
206
- stagnation: {
207
- streakThreshold: PARAMS.stagnationStreakLength,
208
- carryoverThreshold: PARAMS.stagnationCarryoverRatio,
209
- stagnantSessions: stagnantSessionCount,
210
- stagnationRate: stagnantSessionCount / sessions,
211
- longestStreak: longestStagnationStreak,
212
- },
213
- };
214
- }
215
-
216
- // -----------------------------------------------------------------------------
217
- // CLI
218
- // -----------------------------------------------------------------------------
219
- function parseCli(argv) {
220
- const { values } = parseArgs({
221
- args: argv,
222
- options: {
223
- enforcement: { type: 'string', default: 'both' },
224
- sessions: { type: 'string', default: '100' },
225
- seed: { type: 'string', default: '42' },
226
- json: { type: 'boolean', default: false },
227
- help: { type: 'boolean', short: 'h', default: false },
228
- },
229
- allowPositionals: false,
230
- });
231
- return values;
232
- }
233
-
234
- const HELP = `lifecycle-sim-v6 — issue #86 directional simulation
235
-
236
- Usage:
237
- node scripts/lifecycle-sim-v6.mjs [--enforcement warn|strict|both]
238
- [--sessions N] [--seed K]
239
- [--json]
240
-
241
- Options:
242
- --enforcement warn | strict | both (default: both)
243
- --sessions N number of simulated sessions per mode (default: 100)
244
- --seed K RNG seed for reproducibility (default: 42)
245
- --json emit JSON to stdout (default: human text)
246
- -h, --help show this help
247
-
248
- Exit codes:
249
- 0 success
250
- 1 bad arguments
251
- 2 internal error
252
- `;
253
-
254
- function humanReport(results, opts) {
255
- const lines = [];
256
- lines.push('lifecycle-sim-v6 — directional results (NOT statistical)');
257
- lines.push(`seed=${opts.seed} sessions=${opts.sessions} per mode`);
258
- lines.push('');
259
- for (const r of results) {
260
- lines.push(`mode: ${r.mode}`);
261
- lines.push(` planned issues: ${r.totals.planned}`);
262
- lines.push(` completed: ${r.totals.completed}`);
263
- lines.push(` permanently blocked: ${r.totals.blocked}`);
264
- lines.push(` completion ratio: ${r.completionRatio.toFixed(3)}`);
265
- lines.push(` mean carryover ratio: ${r.carryover.meanRatio.toFixed(3)}`);
266
- lines.push(` p95 carryover ratio: ${r.carryover.p95Ratio.toFixed(3)}`);
267
- lines.push(
268
- ` stagnant sessions: ${r.stagnation.stagnantSessions} ` +
269
- `(rate ${r.stagnation.stagnationRate.toFixed(3)})`,
270
- );
271
- lines.push(` longest streak: ${r.stagnation.longestStreak}`);
272
- lines.push('');
273
- }
274
- return lines.join('\n');
275
- }
276
-
277
- function main() {
278
- let opts;
279
- try {
280
- opts = parseCli(process.argv.slice(2));
281
- } catch (err) {
282
- process.stderr.write(`bad args: ${err.message}\n`);
283
- return 1;
284
- }
285
- if (opts.help) {
286
- process.stdout.write(HELP);
287
- return 0;
288
- }
289
- const sessions = Number.parseInt(opts.sessions, 10);
290
- const seed = Number.parseInt(opts.seed, 10);
291
- if (!Number.isFinite(sessions) || sessions <= 0) {
292
- process.stderr.write('--sessions must be a positive integer\n');
293
- return 1;
294
- }
295
- if (!Number.isFinite(seed)) {
296
- process.stderr.write('--seed must be an integer\n');
297
- return 1;
298
- }
299
-
300
- let modes;
301
- if (opts.enforcement === 'both') {
302
- modes = ['warn', 'strict'];
303
- } else if (opts.enforcement === 'warn' || opts.enforcement === 'strict') {
304
- modes = [opts.enforcement];
305
- } else {
306
- process.stderr.write(`--enforcement must be warn|strict|both\n`);
307
- return 1;
308
- }
309
-
310
- let results;
311
- try {
312
- results = modes.map((mode) => simulateMode({ mode, sessions, seed }));
313
- } catch (err) {
314
- process.stderr.write(`sim error: ${err.message}\n`);
315
- return 2;
316
- }
317
-
318
- if (opts.json) {
319
- const out = {
320
- seed,
321
- sessions,
322
- params: PARAMS,
323
- results,
324
- };
325
- process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
326
- } else {
327
- process.stdout.write(humanReport(results, { sessions, seed }));
328
- }
329
- return 0;
330
- }
331
-
332
- // Entry point — only run when invoked as a script (not when imported by tests).
333
- const isDirectRun = (() => {
334
- try {
335
- const argv1 = process.argv[1] ? new URL(`file://${process.argv[1]}`).href : '';
336
- return import.meta.url === argv1;
337
- } catch {
338
- return false;
339
- }
340
- })();
341
-
342
- if (isDirectRun) {
343
- process.exit(main());
344
- }
345
-
346
- // Named exports for tests.
347
- export { mulberry32, gaussianInt, simulateMode, PARAMS, parseCli, main };
@@ -1,189 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * migrate-learnings-jsonl.mjs — one-shot migration helper for learnings.jsonl.
4
- *
5
- * Fixes schema drift described in issue #303:
6
- * - description | recommendation → insight
7
- * - missing id → crypto.randomUUID()
8
- * - missing schema_version → 1
9
- *
10
- * Usage:
11
- * node scripts/migrate-learnings-jsonl.mjs [--source <path>] [--dry-run] [--apply]
12
- *
13
- * Flags:
14
- * --source <path> Path to learnings.jsonl (default: .orchestrator/metrics/learnings.jsonl)
15
- * --dry-run Preview changes without writing (DEFAULT)
16
- * --apply Write migrated records back to the file
17
- *
18
- * Exit codes:
19
- * 0 Success (including no-op if everything is already canonical)
20
- * 1 Input/validation error
21
- * 2 I/O error
22
- *
23
- * Idempotent: running --apply a second time produces no further changes.
24
- *
25
- * Output (stdout — one JSON object per line):
26
- * {"action":"migrated"|"already-canonical","id":"...","changes":[...]}
27
- *
28
- * Summary line (stderr):
29
- * migrate-learnings: N migrated, M already-canonical, K failed-validation [dry-run|applied]
30
- */
31
-
32
- import { existsSync, readFileSync, writeFileSync, renameSync } from 'node:fs';
33
- import { mkdirSync } from 'node:fs';
34
- import { dirname } from 'node:path';
35
- import {
36
- migrateLegacyLearning,
37
- validateLearning,
38
- ValidationError,
39
- } from './lib/learnings.mjs';
40
-
41
- // ---------------------------------------------------------------------------
42
- // Arg parsing
43
- // ---------------------------------------------------------------------------
44
-
45
- const args = process.argv.slice(2);
46
- const helpFlag = args.includes('--help') || args.includes('-h');
47
- if (helpFlag) {
48
- process.stdout.write(`Usage: migrate-learnings-jsonl.mjs [--source <path>] [--dry-run] [--apply]
49
-
50
- Options:
51
- --source <path> Path to learnings.jsonl (default: .orchestrator/metrics/learnings.jsonl)
52
- --dry-run Preview changes without writing (DEFAULT)
53
- --apply Write migrated records back to the file
54
-
55
- Exit codes: 0 success 1 input error 2 I/O error
56
- `);
57
- process.exit(0);
58
- }
59
-
60
- const applyFlag = args.includes('--apply');
61
- const dryRun = !applyFlag; // default is --dry-run
62
-
63
- const sourceIdx = args.indexOf('--source');
64
- const sourcePath =
65
- sourceIdx !== -1 && args[sourceIdx + 1]
66
- ? args[sourceIdx + 1]
67
- : '.orchestrator/metrics/learnings.jsonl';
68
-
69
- // ---------------------------------------------------------------------------
70
- // Load
71
- // ---------------------------------------------------------------------------
72
-
73
- if (!existsSync(sourcePath)) {
74
- process.stderr.write(`migrate-learnings: source file not found: ${sourcePath}\n`);
75
- process.exit(1);
76
- }
77
-
78
- let raw;
79
- try {
80
- raw = readFileSync(sourcePath, 'utf8');
81
- } catch (err) {
82
- process.stderr.write(`migrate-learnings: failed to read ${sourcePath}: ${err.message}\n`);
83
- process.exit(2);
84
- }
85
-
86
- const lines = raw.split('\n').filter((l) => l.trim().length > 0);
87
-
88
- // ---------------------------------------------------------------------------
89
- // Migrate
90
- // ---------------------------------------------------------------------------
91
-
92
- let countMigrated = 0;
93
- let countCanonical = 0;
94
- let countFailedValidation = 0;
95
- let countMalformed = 0;
96
-
97
- const outputLines = [];
98
-
99
- for (const line of lines) {
100
- let parsed;
101
- try {
102
- parsed = JSON.parse(line);
103
- } catch {
104
- countMalformed++;
105
- process.stderr.write(`migrate-learnings: WARN skipping malformed JSON line: ${line.slice(0, 80)}\n`);
106
- // Preserve the original malformed line as-is (do not discard data)
107
- outputLines.push(line);
108
- continue;
109
- }
110
-
111
- // Detect which fields need migration
112
- const changes = [];
113
- if (!parsed.id) changes.push('id:added');
114
- if (!parsed.insight) {
115
- if (typeof parsed.description === 'string') changes.push('description→insight');
116
- else if (typeof parsed.recommendation === 'string') changes.push('recommendation→insight');
117
- }
118
- if (parsed.schema_version === undefined || parsed.schema_version === null) {
119
- changes.push('schema_version:1');
120
- }
121
-
122
- const migrated = migrateLegacyLearning(parsed);
123
-
124
- // Validate after migration — records that still fail after migration are
125
- // preserved in-place (no data loss) but flagged in the summary.
126
- let validated;
127
- try {
128
- // Stamp schema_version before validation so appendLearning-style stamping
129
- // is mimicked (migrateLegacyLearning already does this, but be explicit).
130
- validated = validateLearning({
131
- ...migrated,
132
- schema_version: migrated.schema_version ?? 1,
133
- });
134
- } catch (err) {
135
- countFailedValidation++;
136
- const reason = err instanceof ValidationError ? err.message : String(err);
137
- process.stderr.write(
138
- `migrate-learnings: WARN record id=${parsed.id ?? '<no id>'} still fails validation after migration: ${reason}\n`
139
- );
140
- // Preserve original line — do not destroy unmigratable records
141
- outputLines.push(line);
142
- process.stdout.write(
143
- JSON.stringify({ action: 'failed-validation', id: parsed.id ?? null, reason, changes }) + '\n'
144
- );
145
- continue;
146
- }
147
-
148
- if (changes.length === 0) {
149
- countCanonical++;
150
- outputLines.push(JSON.stringify(validated));
151
- process.stdout.write(JSON.stringify({ action: 'already-canonical', id: validated.id }) + '\n');
152
- } else {
153
- countMigrated++;
154
- outputLines.push(JSON.stringify(validated));
155
- process.stdout.write(JSON.stringify({ action: 'migrated', id: validated.id, changes }) + '\n');
156
- }
157
- }
158
-
159
- // ---------------------------------------------------------------------------
160
- // Write (--apply only)
161
- // ---------------------------------------------------------------------------
162
-
163
- const modeLabel = dryRun ? 'dry-run' : 'applied';
164
-
165
- if (!dryRun) {
166
- const body = outputLines.join('\n') + '\n';
167
- const tmp = `${sourcePath}.migrate-tmp-${process.pid}-${Date.now()}`;
168
- try {
169
- mkdirSync(dirname(sourcePath), { recursive: true });
170
- writeFileSync(tmp, body, 'utf8');
171
- renameSync(tmp, sourcePath);
172
- } catch (err) {
173
- process.stderr.write(`migrate-learnings: ERROR failed to write ${sourcePath}: ${err.message}\n`);
174
- // Attempt cleanup of tmp
175
- try { if (existsSync(tmp)) renameSync(tmp, tmp + '.failed'); } catch { /* ignore */ }
176
- process.exit(2);
177
- }
178
- }
179
-
180
- // ---------------------------------------------------------------------------
181
- // Summary
182
- // ---------------------------------------------------------------------------
183
-
184
- process.stderr.write(
185
- `migrate-learnings: ${countMigrated} migrated, ${countCanonical} already-canonical, ` +
186
- `${countFailedValidation} failed-validation, ${countMalformed} malformed [${modeLabel}]\n`
187
- );
188
-
189
- process.exit(countFailedValidation > 0 ? 1 : 0);