session-orchestrator 3.16.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 (762) hide show
  1. package/.claude-plugin/marketplace.json +29 -0
  2. package/.claude-plugin/plugin.json +18 -0
  3. package/.codex-plugin/agents/explorer.toml +14 -0
  4. package/.codex-plugin/agents/session-reviewer.toml +23 -0
  5. package/.codex-plugin/agents/wave-worker.toml +15 -0
  6. package/.codex-plugin/config.toml +20 -0
  7. package/.codex-plugin/plugin.json +37 -0
  8. package/.cursor/rules/000-session-orchestrator.mdc +73 -0
  9. package/.cursor/rules/010-session-workflow.mdc +170 -0
  10. package/.cursor/rules/020-quality-gates.mdc +128 -0
  11. package/.cursor/rules/030-wave-execution.mdc +216 -0
  12. package/.cursor/rules/040-discovery.mdc +242 -0
  13. package/.cursor/rules/050-plan.mdc +235 -0
  14. package/.cursor/rules/060-evolve.mdc +232 -0
  15. package/.cursor/rules/070-gitlab-ops.mdc +246 -0
  16. package/.cursor/rules/080-ecosystem-health.mdc +145 -0
  17. package/.mcp.json +8 -0
  18. package/CHANGELOG.md +1544 -0
  19. package/LICENSE +21 -0
  20. package/NOTICE +64 -0
  21. package/README.md +242 -0
  22. package/SECURITY.md +90 -0
  23. package/agents/AGENTS.md +136 -0
  24. package/agents/analyst.md +99 -0
  25. package/agents/architect-reviewer.md +93 -0
  26. package/agents/code-implementer.md +106 -0
  27. package/agents/db-specialist.md +104 -0
  28. package/agents/dialectic-deriver.md +139 -0
  29. package/agents/docs-writer.md +113 -0
  30. package/agents/eval-judge.md +146 -0
  31. package/agents/memory-proposal-collector.md +297 -0
  32. package/agents/qa-strategist.md +102 -0
  33. package/agents/schemas/analyst.schema.json +46 -0
  34. package/agents/schemas/architect-reviewer.schema.json +50 -0
  35. package/agents/schemas/code-implementer.schema.json +61 -0
  36. package/agents/schemas/db-specialist.schema.json +80 -0
  37. package/agents/schemas/docs-writer.schema.json +56 -0
  38. package/agents/schemas/persona-panel-sidecar.schema.json +245 -0
  39. package/agents/schemas/qa-strategist.schema.json +46 -0
  40. package/agents/schemas/security-reviewer.schema.json +86 -0
  41. package/agents/schemas/session-reviewer.schema.json +69 -0
  42. package/agents/schemas/test-writer.schema.json +69 -0
  43. package/agents/schemas/ui-developer.schema.json +90 -0
  44. package/agents/schemas/ux-evaluator.schema.json +51 -0
  45. package/agents/security-reviewer.md +236 -0
  46. package/agents/session-reviewer.md +201 -0
  47. package/agents/skill-applied-judge.md +122 -0
  48. package/agents/test-writer.md +123 -0
  49. package/agents/ui-developer.md +109 -0
  50. package/agents/ux-evaluator.md +161 -0
  51. package/assets/icon.svg +11 -0
  52. package/assets/og-card.png +0 -0
  53. package/assets/og-card.svg +47 -0
  54. package/commands/autopilot-multi.md +74 -0
  55. package/commands/autopilot.md +80 -0
  56. package/commands/bootstrap.md +56 -0
  57. package/commands/brainstorm.md +48 -0
  58. package/commands/close.md +24 -0
  59. package/commands/debug.md +36 -0
  60. package/commands/discovery.md +32 -0
  61. package/commands/dispatcher.md +59 -0
  62. package/commands/eval.md +28 -0
  63. package/commands/evolve.md +10 -0
  64. package/commands/go.md +41 -0
  65. package/commands/grill.md +45 -0
  66. package/commands/harness-audit.md +26 -0
  67. package/commands/memory-cleanup.md +25 -0
  68. package/commands/persona-panel.md +121 -0
  69. package/commands/plan.md +15 -0
  70. package/commands/portfolio.md +97 -0
  71. package/commands/reconcile.md +23 -0
  72. package/commands/repo-audit.md +24 -0
  73. package/commands/session.md +30 -0
  74. package/commands/spinout.md +15 -0
  75. package/commands/sunset-review.md +27 -0
  76. package/commands/templates-ack.md +96 -0
  77. package/commands/test.md +97 -0
  78. package/docs/README.md +105 -0
  79. package/docs/USER-GUIDE.md +1403 -0
  80. package/docs/ci-setup.md +81 -0
  81. package/docs/codex-setup.md +142 -0
  82. package/docs/components.md +74 -0
  83. package/docs/cursor-setup.md +104 -0
  84. package/docs/events-schema.md +81 -0
  85. package/docs/migration-v3.md +148 -0
  86. package/docs/owner-config-schema.md +154 -0
  87. package/docs/persona-panel.md +433 -0
  88. package/docs/pi-setup.md +115 -0
  89. package/docs/plugin-architecture-v3.md +296 -0
  90. package/docs/pm-skills-marketplace.md +114 -0
  91. package/docs/policy-cache-validation-2026-04-28.md +118 -0
  92. package/docs/rule-authoring.md +316 -0
  93. package/docs/session-config-reference.md +1439 -0
  94. package/docs/session-config-template.md +961 -0
  95. package/docs/vault-docs-architecture.md +297 -0
  96. package/hooks/_lib/lock-bootstrap.mjs +272 -0
  97. package/hooks/_lib/lock-reconcile.mjs +93 -0
  98. package/hooks/_lib/profile-gate.mjs +95 -0
  99. package/hooks/_lib/transcript-history.mjs +211 -0
  100. package/hooks/agent-teams-h3-test.sh +362 -0
  101. package/hooks/config-protection.mjs +0 -0
  102. package/hooks/cwd-change-restore.mjs +131 -0
  103. package/hooks/enforce-commands.mjs +179 -0
  104. package/hooks/enforce-scope.mjs +273 -0
  105. package/hooks/hooks-codex.json +60 -0
  106. package/hooks/hooks-cursor.json +15 -0
  107. package/hooks/hooks-pi.json +115 -0
  108. package/hooks/hooks.json +215 -0
  109. package/hooks/loop-guard.mjs +260 -0
  110. package/hooks/on-session-end.mjs +217 -0
  111. package/hooks/on-session-start.mjs +660 -0
  112. package/hooks/on-stop.mjs +294 -0
  113. package/hooks/operator-steer.mjs +64 -0
  114. package/hooks/post-edit-validate.mjs +225 -0
  115. package/hooks/post-subagent-discovery-validator.mjs +398 -0
  116. package/hooks/post-tool-batch-wave-signal.mjs +328 -0
  117. package/hooks/post-tool-failure-corrective-context.mjs +248 -0
  118. package/hooks/post-tooluse-frontend-slop.mjs +184 -0
  119. package/hooks/pre-bash-destructive-guard.mjs +515 -0
  120. package/hooks/pre-bash-memory-propose-audit.mjs +206 -0
  121. package/hooks/pre-bash-staging-fence.mjs +223 -0
  122. package/hooks/pre-bash-templates-first.mjs +404 -0
  123. package/hooks/run-node.sh +72 -0
  124. package/hooks/skill-invocation-telemetry.mjs +99 -0
  125. package/hooks/subagent-telemetry.mjs +249 -0
  126. package/hooks/wave-scope-commit-guard.mjs +191 -0
  127. package/monitors/monitors.json +14 -0
  128. package/output-styles/finding-report.md +48 -0
  129. package/output-styles/session-report.md +53 -0
  130. package/output-styles/wave-summary.md +38 -0
  131. package/package.json +94 -0
  132. package/pi/extensions/session-orchestrator.ts +25 -0
  133. package/pi/prompts/autopilot-multi.md +12 -0
  134. package/pi/prompts/autopilot.md +12 -0
  135. package/pi/prompts/bootstrap.md +12 -0
  136. package/pi/prompts/brainstorm.md +12 -0
  137. package/pi/prompts/close.md +11 -0
  138. package/pi/prompts/debug.md +12 -0
  139. package/pi/prompts/discovery.md +12 -0
  140. package/pi/prompts/dispatcher.md +12 -0
  141. package/pi/prompts/eval.md +12 -0
  142. package/pi/prompts/evolve.md +12 -0
  143. package/pi/prompts/go.md +12 -0
  144. package/pi/prompts/grill.md +12 -0
  145. package/pi/prompts/harness-audit.md +12 -0
  146. package/pi/prompts/memory-cleanup.md +12 -0
  147. package/pi/prompts/persona-panel.md +12 -0
  148. package/pi/prompts/plan.md +12 -0
  149. package/pi/prompts/portfolio.md +12 -0
  150. package/pi/prompts/reconcile.md +12 -0
  151. package/pi/prompts/repo-audit.md +12 -0
  152. package/pi/prompts/session.md +12 -0
  153. package/pi/prompts/spinout.md +12 -0
  154. package/pi/prompts/sunset-review.md +12 -0
  155. package/pi/prompts/templates-ack.md +12 -0
  156. package/pi/prompts/test.md +12 -0
  157. package/rules/_index.md +51 -0
  158. package/rules/always-on/commit-discipline.md +26 -0
  159. package/rules/always-on/npm-quality-gates.md +26 -0
  160. package/rules/always-on/parallel-sessions.md +43 -0
  161. package/rules/opt-in-domain/prompt-caching.md +270 -0
  162. package/rules/opt-in-stack/backend-data.md +188 -0
  163. package/rules/opt-in-stack/backend.md +390 -0
  164. package/rules/opt-in-stack/frontend.md +98 -0
  165. package/rules/opt-in-stack/security-web.md +194 -0
  166. package/rules/opt-in-stack/swift.md +65 -0
  167. package/scripts/archive-closed-prds.mjs +416 -0
  168. package/scripts/autopilot-multi.mjs +802 -0
  169. package/scripts/autopilot.mjs +383 -0
  170. package/scripts/backfill-abandoned-sessions.mjs +265 -0
  171. package/scripts/backfill-learnings-expires.mjs +196 -0
  172. package/scripts/backfill-learnings.mjs +203 -0
  173. package/scripts/backfill-sessions.mjs +282 -0
  174. package/scripts/check-doc-consistency.sh +279 -0
  175. package/scripts/check-package-manager.mjs +445 -0
  176. package/scripts/ci/assert-vitest-green.mjs +267 -0
  177. package/scripts/codex-install.mjs +435 -0
  178. package/scripts/compute-grounding-injection.sh +186 -0
  179. package/scripts/cursor-install.mjs +113 -0
  180. package/scripts/dialectic-deriver.mjs +573 -0
  181. package/scripts/emit-event.mjs +160 -0
  182. package/scripts/emit-session.mjs +212 -0
  183. package/scripts/eval-session.mjs +262 -0
  184. package/scripts/export-hw-learnings.mjs +437 -0
  185. package/scripts/gc-stale-worktrees.mjs +666 -0
  186. package/scripts/generate-pi-prompts.mjs +127 -0
  187. package/scripts/harness-audit.mjs +287 -0
  188. package/scripts/lib/agent-frontmatter.mjs +266 -0
  189. package/scripts/lib/agent-output-schema.mjs +166 -0
  190. package/scripts/lib/agent-status.mjs +303 -0
  191. package/scripts/lib/ajv-loader.mjs +34 -0
  192. package/scripts/lib/auto-dialectic.mjs +382 -0
  193. package/scripts/lib/auto-dream.mjs +471 -0
  194. package/scripts/lib/autonomy/suitability.mjs +212 -0
  195. package/scripts/lib/autopilot/dep-graph.mjs +417 -0
  196. package/scripts/lib/autopilot/durable-telemetry.mjs +121 -0
  197. package/scripts/lib/autopilot/flags.mjs +104 -0
  198. package/scripts/lib/autopilot/kill-switches.mjs +174 -0
  199. package/scripts/lib/autopilot/loop.mjs +320 -0
  200. package/scripts/lib/autopilot/mr-draft.mjs +520 -0
  201. package/scripts/lib/autopilot/multi-killswitch.mjs +184 -0
  202. package/scripts/lib/autopilot/recent-runs.mjs +106 -0
  203. package/scripts/lib/autopilot/stall-sampler.mjs +97 -0
  204. package/scripts/lib/autopilot/telemetry.mjs +224 -0
  205. package/scripts/lib/autopilot/worktree-pipeline.mjs +605 -0
  206. package/scripts/lib/autopilot-telemetry.mjs +11 -0
  207. package/scripts/lib/autopilot.mjs +39 -0
  208. package/scripts/lib/backlog-scan.mjs +179 -0
  209. package/scripts/lib/bootstrap-lock-freshness.mjs +260 -0
  210. package/scripts/lib/bootstrap-lock-refresh.mjs +186 -0
  211. package/scripts/lib/build-live-signals.mjs +150 -0
  212. package/scripts/lib/ci-status-banner.mjs +425 -0
  213. package/scripts/lib/claude-md-budget-lint.mjs +246 -0
  214. package/scripts/lib/cli-flags.mjs +158 -0
  215. package/scripts/lib/codex/plugin-contract.mjs +610 -0
  216. package/scripts/lib/cold-start-detector.mjs +240 -0
  217. package/scripts/lib/command-blocker.mjs +458 -0
  218. package/scripts/lib/common.mjs +333 -0
  219. package/scripts/lib/config/auto-dream.mjs +77 -0
  220. package/scripts/lib/config/block-header.mjs +94 -0
  221. package/scripts/lib/config/broken-window.mjs +114 -0
  222. package/scripts/lib/config/coercers.mjs +248 -0
  223. package/scripts/lib/config/cold-start.mjs +92 -0
  224. package/scripts/lib/config/config-protection.mjs +120 -0
  225. package/scripts/lib/config/cross-repo.mjs +104 -0
  226. package/scripts/lib/config/custom-phases.mjs +213 -0
  227. package/scripts/lib/config/dialectic.mjs +92 -0
  228. package/scripts/lib/config/discovery-validator.mjs +75 -0
  229. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +240 -0
  230. package/scripts/lib/config/dispatcher-autonomy.mjs +152 -0
  231. package/scripts/lib/config/docs-orchestrator.mjs +90 -0
  232. package/scripts/lib/config/docs-staleness.mjs +96 -0
  233. package/scripts/lib/config/drift-check.mjs +155 -0
  234. package/scripts/lib/config/eval.mjs +130 -0
  235. package/scripts/lib/config/events-rotation.mjs +74 -0
  236. package/scripts/lib/config/evolve.mjs +308 -0
  237. package/scripts/lib/config/frontend-slop-hook.mjs +104 -0
  238. package/scripts/lib/config/gitlab-portfolio.mjs +150 -0
  239. package/scripts/lib/config/handover-gate.mjs +106 -0
  240. package/scripts/lib/config/host-paths.mjs +76 -0
  241. package/scripts/lib/config/io.mjs +54 -0
  242. package/scripts/lib/config/loop-guard.mjs +117 -0
  243. package/scripts/lib/config/memory.mjs +150 -0
  244. package/scripts/lib/config/persona-gate-wave.mjs +258 -0
  245. package/scripts/lib/config/reconcile.mjs +205 -0
  246. package/scripts/lib/config/section-extractor.mjs +100 -0
  247. package/scripts/lib/config/skill-evolution.mjs +112 -0
  248. package/scripts/lib/config/slopcheck.mjs +99 -0
  249. package/scripts/lib/config/state-md-lock.mjs +83 -0
  250. package/scripts/lib/config/templates-first.mjs +94 -0
  251. package/scripts/lib/config/test.mjs +113 -0
  252. package/scripts/lib/config/vault-integration.mjs +201 -0
  253. package/scripts/lib/config/vault-mirror-quality.mjs +99 -0
  254. package/scripts/lib/config/vault-staleness.mjs +84 -0
  255. package/scripts/lib/config/vault-sync.mjs +96 -0
  256. package/scripts/lib/config/verification-auto-fix.mjs +84 -0
  257. package/scripts/lib/config/wave-reviewers.mjs +133 -0
  258. package/scripts/lib/config-schema.mjs +345 -0
  259. package/scripts/lib/config.mjs +474 -0
  260. package/scripts/lib/convergence-monitor.mjs +389 -0
  261. package/scripts/lib/coordinator-snapshot.mjs +371 -0
  262. package/scripts/lib/crypto-digest-utils.mjs +91 -0
  263. package/scripts/lib/discovery/helpers.mjs +127 -0
  264. package/scripts/lib/discovery/triage-state.mjs +279 -0
  265. package/scripts/lib/dispatcher/cli.mjs +257 -0
  266. package/scripts/lib/dispatcher/enumerate.mjs +243 -0
  267. package/scripts/lib/dispatcher/rank.mjs +363 -0
  268. package/scripts/lib/ecosystem-health.mjs +224 -0
  269. package/scripts/lib/ecosystem-wizard/ci-detector.mjs +18 -0
  270. package/scripts/lib/ecosystem-wizard/config-parser.mjs +54 -0
  271. package/scripts/lib/ecosystem-wizard/config-writer.mjs +287 -0
  272. package/scripts/lib/ecosystem-wizard/package-manager-detector.mjs +42 -0
  273. package/scripts/lib/ecosystem-wizard/wizard-prompt.mjs +246 -0
  274. package/scripts/lib/ecosystem-wizard.mjs +48 -0
  275. package/scripts/lib/env-check.mjs +89 -0
  276. package/scripts/lib/eval/engine.mjs +605 -0
  277. package/scripts/lib/eval/judge.mjs +433 -0
  278. package/scripts/lib/eval/report.mjs +367 -0
  279. package/scripts/lib/eval/schema.mjs +618 -0
  280. package/scripts/lib/eval/session-resolve.mjs +137 -0
  281. package/scripts/lib/eval/sink.mjs +77 -0
  282. package/scripts/lib/events-rotation.mjs +86 -0
  283. package/scripts/lib/events-schema.mjs +81 -0
  284. package/scripts/lib/events.mjs +80 -0
  285. package/scripts/lib/evolve/autonomy-verdict.mjs +461 -0
  286. package/scripts/lib/evolve/autopilot-effectiveness.mjs +293 -0
  287. package/scripts/lib/exclusivity-matrix.mjs +68 -0
  288. package/scripts/lib/fetch-baseline.mjs +311 -0
  289. package/scripts/lib/file-lock.mjs +512 -0
  290. package/scripts/lib/frontend-detect/detect.mjs +138 -0
  291. package/scripts/lib/frontend-detect/rules.mjs +295 -0
  292. package/scripts/lib/frontmatter-guard.mjs +241 -0
  293. package/scripts/lib/gates/echo-stub-detect.mjs +39 -0
  294. package/scripts/lib/gates/gate-baseline.mjs +42 -0
  295. package/scripts/lib/gates/gate-full.mjs +85 -0
  296. package/scripts/lib/gates/gate-helpers.mjs +231 -0
  297. package/scripts/lib/gates/gate-incremental.mjs +76 -0
  298. package/scripts/lib/gates/gate-per-file.mjs +55 -0
  299. package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +447 -0
  300. package/scripts/lib/gitlab-portfolio/aggregator.mjs +383 -0
  301. package/scripts/lib/gitlab-portfolio/cli.mjs +428 -0
  302. package/scripts/lib/gitlab-portfolio/markdown-writer.mjs +289 -0
  303. package/scripts/lib/gitlab-portfolio/vcs-detect.mjs +182 -0
  304. package/scripts/lib/handover-gate.mjs +222 -0
  305. package/scripts/lib/hardening.mjs +43 -0
  306. package/scripts/lib/hardware-pattern-detector.mjs +238 -0
  307. package/scripts/lib/harness-audit/categories/category1.mjs +123 -0
  308. package/scripts/lib/harness-audit/categories/category2.mjs +145 -0
  309. package/scripts/lib/harness-audit/categories/category3.mjs +143 -0
  310. package/scripts/lib/harness-audit/categories/category4.mjs +202 -0
  311. package/scripts/lib/harness-audit/categories/category5.mjs +152 -0
  312. package/scripts/lib/harness-audit/categories/category6.mjs +211 -0
  313. package/scripts/lib/harness-audit/categories/category7.mjs +125 -0
  314. package/scripts/lib/harness-audit/categories/category8.mjs +328 -0
  315. package/scripts/lib/harness-audit/categories/category9.mjs +294 -0
  316. package/scripts/lib/harness-audit/categories/helpers.mjs +165 -0
  317. package/scripts/lib/harness-audit/categories.mjs +19 -0
  318. package/scripts/lib/historical-guard.mjs +15 -0
  319. package/scripts/lib/host-identity.mjs +262 -0
  320. package/scripts/lib/instruction-budget-guard.mjs +332 -0
  321. package/scripts/lib/io.mjs +304 -0
  322. package/scripts/lib/issue-close-strip-labels.mjs +161 -0
  323. package/scripts/lib/language-mappers/README.md +57 -0
  324. package/scripts/lib/language-mappers/index.mjs +165 -0
  325. package/scripts/lib/language-mappers/markdown.mjs +149 -0
  326. package/scripts/lib/language-mappers/python.mjs +249 -0
  327. package/scripts/lib/language-mappers/swift.mjs +201 -0
  328. package/scripts/lib/language-mappers/typescript.mjs +433 -0
  329. package/scripts/lib/learnings/expiry-sweep.mjs +164 -0
  330. package/scripts/lib/learnings/filters.mjs +43 -0
  331. package/scripts/lib/learnings/io.mjs +255 -0
  332. package/scripts/lib/learnings/schema.mjs +518 -0
  333. package/scripts/lib/learnings/surface.mjs +207 -0
  334. package/scripts/lib/learnings.mjs +42 -0
  335. package/scripts/lib/lock-reaper.mjs +648 -0
  336. package/scripts/lib/locks/index.mjs +31 -0
  337. package/scripts/lib/locks/lock-body.mjs +62 -0
  338. package/scripts/lib/locks/staging-fence-lock.mjs +267 -0
  339. package/scripts/lib/locks/state-md-lock.mjs +351 -0
  340. package/scripts/lib/loop-readiness-banner.mjs +144 -0
  341. package/scripts/lib/memory-banner.mjs +478 -0
  342. package/scripts/lib/memory-cleanup/worktree-sweep.mjs +108 -0
  343. package/scripts/lib/memory-cleanup-stamp.mjs +56 -0
  344. package/scripts/lib/memory-paths.mjs +31 -0
  345. package/scripts/lib/memory-proposals/collector.mjs +334 -0
  346. package/scripts/lib/memory-proposals/schema.mjs +289 -0
  347. package/scripts/lib/memory-proposals/sink.mjs +507 -0
  348. package/scripts/lib/memory-proposals/store.mjs +441 -0
  349. package/scripts/lib/mission-status-schema.mjs +114 -0
  350. package/scripts/lib/mode-selector/alternatives.mjs +64 -0
  351. package/scripts/lib/mode-selector/constants.mjs +29 -0
  352. package/scripts/lib/mode-selector/context-pressure.mjs +157 -0
  353. package/scripts/lib/mode-selector/rationale.mjs +55 -0
  354. package/scripts/lib/mode-selector/scoring.mjs +221 -0
  355. package/scripts/lib/mode-selector-accuracy.mjs +121 -0
  356. package/scripts/lib/mode-selector.mjs +160 -0
  357. package/scripts/lib/multi-provider-build/providers.mjs +64 -0
  358. package/scripts/lib/multi-provider-build/templating.mjs +130 -0
  359. package/scripts/lib/named-baseline-resolver.mjs +233 -0
  360. package/scripts/lib/named-vault-resolver.mjs +433 -0
  361. package/scripts/lib/owner-config/coerce.mjs +29 -0
  362. package/scripts/lib/owner-config/constants.mjs +21 -0
  363. package/scripts/lib/owner-config/defaults.mjs +50 -0
  364. package/scripts/lib/owner-config/error.mjs +19 -0
  365. package/scripts/lib/owner-config/index.mjs +13 -0
  366. package/scripts/lib/owner-config/merge.mjs +52 -0
  367. package/scripts/lib/owner-config/validate.mjs +259 -0
  368. package/scripts/lib/owner-config-banner.mjs +126 -0
  369. package/scripts/lib/owner-config-loader.mjs +159 -0
  370. package/scripts/lib/owner-config.example.yaml +72 -0
  371. package/scripts/lib/owner-config.mjs +28 -0
  372. package/scripts/lib/owner-interview.mjs +243 -0
  373. package/scripts/lib/owner-yaml.mjs +571 -0
  374. package/scripts/lib/package-manager.mjs +160 -0
  375. package/scripts/lib/path-utils.mjs +217 -0
  376. package/scripts/lib/peer-cards/merger.mjs +310 -0
  377. package/scripts/lib/peer-cards/reader.mjs +125 -0
  378. package/scripts/lib/peer-cards/schema.mjs +230 -0
  379. package/scripts/lib/peer-cards/staleness-banner.mjs +86 -0
  380. package/scripts/lib/peer-cards/writer.mjs +138 -0
  381. package/scripts/lib/peer-discovery.mjs +200 -0
  382. package/scripts/lib/persona-panel/catalog-loader.mjs +577 -0
  383. package/scripts/lib/persona-panel/consolidator.mjs +370 -0
  384. package/scripts/lib/persona-panel/persona-runner.mjs +375 -0
  385. package/scripts/lib/persona-panel/threshold.mjs +130 -0
  386. package/scripts/lib/pi-hook-bridge.mjs +328 -0
  387. package/scripts/lib/platform.mjs +266 -0
  388. package/scripts/lib/playwright-driver/runner.mjs +297 -0
  389. package/scripts/lib/plugin-root.mjs +210 -0
  390. package/scripts/lib/pre-dispatch-check.mjs +126 -0
  391. package/scripts/lib/product-repo-detect.mjs +121 -0
  392. package/scripts/lib/profiles/registry.mjs +176 -0
  393. package/scripts/lib/profiles/schema.mjs +209 -0
  394. package/scripts/lib/qg-command-drift-banner.mjs +88 -0
  395. package/scripts/lib/quality-gate/diagnostics.mjs +92 -0
  396. package/scripts/lib/quality-gate.mjs +536 -0
  397. package/scripts/lib/quality-gates-cache.mjs +228 -0
  398. package/scripts/lib/quality-gates-policy.mjs +95 -0
  399. package/scripts/lib/recommendations-v0.mjs +156 -0
  400. package/scripts/lib/reconcile/eligibility.mjs +203 -0
  401. package/scripts/lib/reconcile/emitter.mjs +244 -0
  402. package/scripts/lib/reconcile/engine.mjs +412 -0
  403. package/scripts/lib/reconcile/idempotency.mjs +239 -0
  404. package/scripts/lib/reconcile/renderer.mjs +211 -0
  405. package/scripts/lib/reconcile/writer.mjs +293 -0
  406. package/scripts/lib/reconcile-nudge-banner.mjs +284 -0
  407. package/scripts/lib/resource-probe/evaluate.mjs +190 -0
  408. package/scripts/lib/resource-probe/parsers.mjs +181 -0
  409. package/scripts/lib/resource-probe/probe-platform.mjs +300 -0
  410. package/scripts/lib/resource-probe.mjs +95 -0
  411. package/scripts/lib/rule-loader.mjs +552 -0
  412. package/scripts/lib/rules-sync.mjs +439 -0
  413. package/scripts/lib/scope-gate.mjs +496 -0
  414. package/scripts/lib/session-close-backfill.mjs +539 -0
  415. package/scripts/lib/session-discovery.mjs +256 -0
  416. package/scripts/lib/session-end/phase-skip.mjs +357 -0
  417. package/scripts/lib/session-end/worktree-cleanup.mjs +112 -0
  418. package/scripts/lib/session-id.mjs +362 -0
  419. package/scripts/lib/session-lock.mjs +703 -0
  420. package/scripts/lib/session-registry.mjs +355 -0
  421. package/scripts/lib/session-schema/aliases.mjs +71 -0
  422. package/scripts/lib/session-schema/constants.mjs +115 -0
  423. package/scripts/lib/session-schema/normalizer.mjs +66 -0
  424. package/scripts/lib/session-schema/timestamps.mjs +64 -0
  425. package/scripts/lib/session-schema/validator.mjs +453 -0
  426. package/scripts/lib/session-schema.mjs +71 -0
  427. package/scripts/lib/session-token-rollup.mjs +137 -0
  428. package/scripts/lib/sessions-staleness-banner.mjs +247 -0
  429. package/scripts/lib/skill-evolution/blast-radius-classifier.mjs +114 -0
  430. package/scripts/lib/skill-evolution/candidate-intake.mjs +270 -0
  431. package/scripts/lib/skill-evolution/config-validation-gate.mjs +279 -0
  432. package/scripts/lib/skill-evolution/engine.mjs +719 -0
  433. package/scripts/lib/skill-evolution/idempotency.mjs +279 -0
  434. package/scripts/lib/skill-evolution/mr-opener.mjs +507 -0
  435. package/scripts/lib/skill-health/join.mjs +181 -0
  436. package/scripts/lib/skill-health/score.mjs +123 -0
  437. package/scripts/lib/skill-invocations-schema.mjs +214 -0
  438. package/scripts/lib/skill-judge.mjs +348 -0
  439. package/scripts/lib/skill-judgments-schema.mjs +264 -0
  440. package/scripts/lib/slopcheck.mjs +501 -0
  441. package/scripts/lib/soul-resolve.mjs +118 -0
  442. package/scripts/lib/spiral-carryover.mjs +495 -0
  443. package/scripts/lib/state-md/body-sections.mjs +851 -0
  444. package/scripts/lib/state-md/frontmatter-mutators.mjs +453 -0
  445. package/scripts/lib/state-md/mission-status.mjs +247 -0
  446. package/scripts/lib/state-md/recommendations.mjs +57 -0
  447. package/scripts/lib/state-md/yaml-parser.mjs +234 -0
  448. package/scripts/lib/state-md-peer-guard.mjs +232 -0
  449. package/scripts/lib/state-md.mjs +53 -0
  450. package/scripts/lib/subagents-schema.mjs +309 -0
  451. package/scripts/lib/sunset/walker.mjs +1192 -0
  452. package/scripts/lib/test-runner/artifact-paths.mjs +94 -0
  453. package/scripts/lib/test-runner/fingerprint.mjs +33 -0
  454. package/scripts/lib/test-runner/issue-reconcile.mjs +770 -0
  455. package/scripts/lib/tmux-layout/layouts.mjs +224 -0
  456. package/scripts/lib/tmux-layout/telemetry-stats.mjs +100 -0
  457. package/scripts/lib/tmux-layout/telemetry.mjs +88 -0
  458. package/scripts/lib/tmux-layout/tmux-shell.mjs +82 -0
  459. package/scripts/lib/tmux-layout/vcs-detector.mjs +88 -0
  460. package/scripts/lib/validate/check-agents.mjs +457 -0
  461. package/scripts/lib/validate/check-codex-plugin.mjs +37 -0
  462. package/scripts/lib/validate/check-commands.mjs +148 -0
  463. package/scripts/lib/validate/check-component-paths.mjs +112 -0
  464. package/scripts/lib/validate/check-dead-bridge.mjs +180 -0
  465. package/scripts/lib/validate/check-hooks-symmetry.mjs +258 -0
  466. package/scripts/lib/validate/check-json-files.mjs +116 -0
  467. package/scripts/lib/validate/check-owner-leakage.mjs +1011 -0
  468. package/scripts/lib/validate/check-path-utils-canary.mjs +175 -0
  469. package/scripts/lib/validate/check-peekaboo-driver-canary.mjs +201 -0
  470. package/scripts/lib/validate/check-pi-package.mjs +110 -0
  471. package/scripts/lib/validate/check-pi-prompts.mjs +43 -0
  472. package/scripts/lib/validate/check-playwright-mcp-canary.mjs +154 -0
  473. package/scripts/lib/validate/check-plugin-json.mjs +96 -0
  474. package/scripts/lib/validate/check-plugin-monitors.mjs +206 -0
  475. package/scripts/lib/validate/check-plugin-schema.mjs +137 -0
  476. package/scripts/lib/validate/check-rules.mjs +143 -0
  477. package/scripts/lib/validate/check-session-plan-routing.mjs +154 -0
  478. package/scripts/lib/validate/check-test-fixture-shapes.mjs +280 -0
  479. package/scripts/lib/validate/check-unicode-safety.mjs +533 -0
  480. package/scripts/lib/validate/confidential-names.mjs +169 -0
  481. package/scripts/lib/validate/dead-bridge-corpus.mjs +141 -0
  482. package/scripts/lib/validate/dead-bridge-detectors.mjs +568 -0
  483. package/scripts/lib/validate/tier-inference.mjs +100 -0
  484. package/scripts/lib/validate-vendored-rules.mjs +519 -0
  485. package/scripts/lib/vault-archive.mjs +404 -0
  486. package/scripts/lib/vault-backfill/glab.mjs +164 -0
  487. package/scripts/lib/vault-backfill/manifest.mjs +75 -0
  488. package/scripts/lib/vault-backfill/template.mjs +130 -0
  489. package/scripts/lib/vault-consolidate-fs.mjs +331 -0
  490. package/scripts/lib/vault-migration-rules.mjs +155 -0
  491. package/scripts/lib/vault-mirror/auto-commit.mjs +203 -0
  492. package/scripts/lib/vault-mirror/namespace.mjs +152 -0
  493. package/scripts/lib/vault-mirror/process.mjs +567 -0
  494. package/scripts/lib/vault-mirror/pseudonym-map.mjs +164 -0
  495. package/scripts/lib/vault-mirror/render-learnings.mjs +201 -0
  496. package/scripts/lib/vault-mirror/render-sessions.mjs +367 -0
  497. package/scripts/lib/vault-mirror/render.mjs +8 -0
  498. package/scripts/lib/vault-mirror/utils.mjs +217 -0
  499. package/scripts/lib/vault-relocation-rules.mjs +555 -0
  500. package/scripts/lib/vault-repo-backfill.mjs +235 -0
  501. package/scripts/lib/vault-staleness-banner.mjs +142 -0
  502. package/scripts/lib/vault-status/board-writer.mjs +769 -0
  503. package/scripts/lib/vault-status/narrative-mirror.mjs +544 -0
  504. package/scripts/lib/vault-sync-baseline.mjs +152 -0
  505. package/scripts/lib/wave-context.mjs +29 -0
  506. package/scripts/lib/wave-executor/pool.mjs +248 -0
  507. package/scripts/lib/wave-resource-gate.mjs +204 -0
  508. package/scripts/lib/wave-sizing.mjs +75 -0
  509. package/scripts/lib/webhook-url.mjs +105 -0
  510. package/scripts/lib/workspace.mjs +198 -0
  511. package/scripts/lib/worktree/constants.mjs +35 -0
  512. package/scripts/lib/worktree/index.mjs +17 -0
  513. package/scripts/lib/worktree/lifecycle.mjs +287 -0
  514. package/scripts/lib/worktree/listing.mjs +118 -0
  515. package/scripts/lib/worktree/meta.mjs +64 -0
  516. package/scripts/lib/worktree-freshness.mjs +313 -0
  517. package/scripts/lib/worktree.mjs +15 -0
  518. package/scripts/lifecycle-sim-v6.mjs +347 -0
  519. package/scripts/lock-reaper.mjs +185 -0
  520. package/scripts/mcp-server.sh +241 -0
  521. package/scripts/measure-policy-cache-effectiveness.mjs +427 -0
  522. package/scripts/memory-propose.mjs +464 -0
  523. package/scripts/migrate-cold-start-seed.mjs +404 -0
  524. package/scripts/migrate-learnings-jsonl.mjs +189 -0
  525. package/scripts/migrate-legacy-learnings.sh +61 -0
  526. package/scripts/migrate-sessions-jsonl.mjs +448 -0
  527. package/scripts/migrate-subagents-jsonl.mjs +196 -0
  528. package/scripts/migrate-vault-paths.mjs +796 -0
  529. package/scripts/parse-config.mjs +149 -0
  530. package/scripts/pi-install.mjs +117 -0
  531. package/scripts/print-applicable-rules.mjs +247 -0
  532. package/scripts/promote-vault-strict.mjs +496 -0
  533. package/scripts/relocate-vault-corpus.mjs +1178 -0
  534. package/scripts/run-migrate-v2-cross-repo.mjs +385 -0
  535. package/scripts/run-quality-gate.mjs +216 -0
  536. package/scripts/spikes/h3-agent-teams/preflight.sh +53 -0
  537. package/scripts/spikes/h3-agent-teams/run-h3.sh +112 -0
  538. package/scripts/spikes/h3-agent-teams/setup.sh +137 -0
  539. package/scripts/spikes/h3-agent-teams/toggle.sh +38 -0
  540. package/scripts/sweep-expired-learnings.mjs +135 -0
  541. package/scripts/sync-vault-schema.mjs +376 -0
  542. package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +8 -0
  543. package/scripts/tmux-layout.mjs +245 -0
  544. package/scripts/token-audit.sh +191 -0
  545. package/scripts/typecheck.mjs +42 -0
  546. package/scripts/upload-social-preview.mjs +316 -0
  547. package/scripts/validate-config.mjs +46 -0
  548. package/scripts/validate-plugin-manifests.mjs +163 -0
  549. package/scripts/validate-plugin.mjs +264 -0
  550. package/scripts/validate-wave-scope.mjs +289 -0
  551. package/scripts/vault-backfill.mjs +404 -0
  552. package/scripts/vault-consolidate.mjs +596 -0
  553. package/scripts/vault-integration-watcher.mjs +394 -0
  554. package/scripts/vault-mirror.mjs +430 -0
  555. package/skills/_shared/bootstrap-gate.md +111 -0
  556. package/skills/_shared/config-reading.md +226 -0
  557. package/skills/_shared/instruction-file-resolution.md +79 -0
  558. package/skills/_shared/model-selection.md +64 -0
  559. package/skills/_shared/monitor-patterns.md +300 -0
  560. package/skills/_shared/parallel-aware-auq.md +121 -0
  561. package/skills/_shared/parallel-aware-preamble.md +185 -0
  562. package/skills/_shared/platform-tools.md +96 -0
  563. package/skills/_shared/state-ownership.md +221 -0
  564. package/skills/architecture/DEEPENING.md +37 -0
  565. package/skills/architecture/INTERFACE-DESIGN.md +44 -0
  566. package/skills/architecture/LANGUAGE.md +53 -0
  567. package/skills/architecture/SKILL.md +92 -0
  568. package/skills/autopilot/SKILL.md +419 -0
  569. package/skills/bootstrap/SKILL.md +592 -0
  570. package/skills/bootstrap/STATE.md.template +24 -0
  571. package/skills/bootstrap/_shared-template.md +243 -0
  572. package/skills/bootstrap/deep-template.md +659 -0
  573. package/skills/bootstrap/fast-template.md +251 -0
  574. package/skills/bootstrap/intensity-heuristic.md +80 -0
  575. package/skills/bootstrap/public-fallback.md +342 -0
  576. package/skills/bootstrap/standard-template.md +736 -0
  577. package/skills/bootstrap/templates/agents/project-code-review.md +18 -0
  578. package/skills/bootstrap/templates/agents/project-discovery.md +18 -0
  579. package/skills/bootstrap/templates/agents/project-quality-gate.md +18 -0
  580. package/skills/brainstorm/SKILL.md +268 -0
  581. package/skills/brainstorm/soul.md +49 -0
  582. package/skills/claude-md-drift-check/SKILL.md +186 -0
  583. package/skills/claude-md-drift-check/checker.mjs +1380 -0
  584. package/skills/claude-md-drift-check/checker.sh +37 -0
  585. package/skills/claude-md-drift-check/package.json +16 -0
  586. package/skills/convergence-monitoring/README.md +39 -0
  587. package/skills/convergence-monitoring/SIGNALS.md +246 -0
  588. package/skills/convergence-monitoring/SKILL.md +285 -0
  589. package/skills/daily/SKILL.md +222 -0
  590. package/skills/daily/generate.sh +92 -0
  591. package/skills/daily/templates/daily.md.tpl +36 -0
  592. package/skills/debug/SKILL.md +188 -0
  593. package/skills/debug/soul.md +35 -0
  594. package/skills/discovery/SKILL.md +567 -0
  595. package/skills/discovery/issue-templates.md +237 -0
  596. package/skills/discovery/probes/docs-staleness.mjs +195 -0
  597. package/skills/discovery/probes/frontend-slop.mjs +186 -0
  598. package/skills/discovery/probes/ssot-code-diff.mjs +310 -0
  599. package/skills/discovery/probes/supply-chain-slopcheck.mjs +440 -0
  600. package/skills/discovery/probes/vault-narrative-staleness.mjs +355 -0
  601. package/skills/discovery/probes/vault-staleness.mjs +272 -0
  602. package/skills/discovery/probes-arch.md +252 -0
  603. package/skills/discovery/probes-audit.md +95 -0
  604. package/skills/discovery/probes-code.md +329 -0
  605. package/skills/discovery/probes-docs.md +76 -0
  606. package/skills/discovery/probes-feature.md +150 -0
  607. package/skills/discovery/probes-infra.md +138 -0
  608. package/skills/discovery/probes-intro.md +25 -0
  609. package/skills/discovery/probes-session.md +495 -0
  610. package/skills/discovery/probes-supply-chain.md +94 -0
  611. package/skills/discovery/probes-ui.md +147 -0
  612. package/skills/discovery/probes-vault.md +64 -0
  613. package/skills/discovery/slop-patterns.md +115 -0
  614. package/skills/dispatcher/SKILL.md +173 -0
  615. package/skills/docs-orchestrator/SKILL.md +362 -0
  616. package/skills/docs-orchestrator/audience-mapping.md +140 -0
  617. package/skills/domain-model/ADR-FORMAT.md +47 -0
  618. package/skills/domain-model/CONTEXT-FORMAT.md +77 -0
  619. package/skills/domain-model/SKILL.md +85 -0
  620. package/skills/ecosystem-health/SKILL.md +119 -0
  621. package/skills/ecosystem-health/wizard.md +193 -0
  622. package/skills/eval/SKILL.md +293 -0
  623. package/skills/eval/rubric-v1.md +218 -0
  624. package/skills/evolve/SKILL.md +546 -0
  625. package/skills/frontmatter-guard/SKILL.md +126 -0
  626. package/skills/gitlab-ops/SKILL.md +368 -0
  627. package/skills/gitlab-portfolio/SKILL.md +196 -0
  628. package/skills/grill/SKILL.md +185 -0
  629. package/skills/grill/soul.md +55 -0
  630. package/skills/hook-development/SKILL.md +413 -0
  631. package/skills/mcp-builder/SKILL.md +260 -0
  632. package/skills/memory-cleanup/SKILL.md +310 -0
  633. package/skills/mode-selector/SKILL.md +226 -0
  634. package/skills/peekaboo-driver/SKILL.md +237 -0
  635. package/skills/peekaboo-driver/soul.md +32 -0
  636. package/skills/persona-panel/SKILL.md +365 -0
  637. package/skills/persona-panel/persona-format.md +205 -0
  638. package/skills/persona-panel/presets/designer-lens.md +87 -0
  639. package/skills/persona-panel/presets/engineer-lens.md +88 -0
  640. package/skills/persona-panel/presets/pm-lens.md +86 -0
  641. package/skills/plan/SKILL.md +496 -0
  642. package/skills/plan/mode-feature.md +141 -0
  643. package/skills/plan/mode-new.md +297 -0
  644. package/skills/plan/mode-retro.md +271 -0
  645. package/skills/plan/prd-feature-template.md +132 -0
  646. package/skills/plan/prd-full-template.md +151 -0
  647. package/skills/plan/prd-reviewer-prompt.md +103 -0
  648. package/skills/plan/retro-template.md +75 -0
  649. package/skills/plan/soul.md +62 -0
  650. package/skills/playwright-driver/SKILL.md +226 -0
  651. package/skills/playwright-driver/soul.md +30 -0
  652. package/skills/quality-gates/SKILL.md +212 -0
  653. package/skills/reconcile/SKILL.md +324 -0
  654. package/skills/repo-audit/SKILL.md +272 -0
  655. package/skills/session-end/SKILL.md +1044 -0
  656. package/skills/session-end/discovery-scan.md +37 -0
  657. package/skills/session-end/drift-operations.md +97 -0
  658. package/skills/session-end/learning-patterns.md +78 -0
  659. package/skills/session-end/metrics-collection.md +175 -0
  660. package/skills/session-end/phase-3-2-docs-verification.md +148 -0
  661. package/skills/session-end/phase-3-6-tail.md +344 -0
  662. package/skills/session-end/phase-3-7a-recommendations.md +86 -0
  663. package/skills/session-end/plan-verification.md +288 -0
  664. package/skills/session-end/session-metrics-write.md +223 -0
  665. package/skills/session-end/vault-operations.md +50 -0
  666. package/skills/session-end/verification-checklist.md +20 -0
  667. package/skills/session-plan/SKILL.md +554 -0
  668. package/skills/session-plan/wave-template.md +37 -0
  669. package/skills/session-start/SKILL.md +1043 -0
  670. package/skills/session-start/phase-2-5-docs-planning.md +119 -0
  671. package/skills/session-start/phase-4-5-resource-health.md +49 -0
  672. package/skills/session-start/phase-7-1-premise-check.md +47 -0
  673. package/skills/session-start/phase-7-5-mode-selector.md +237 -0
  674. package/skills/session-start/phase-8-5-express-path.md +61 -0
  675. package/skills/session-start/presentation-format.md +81 -0
  676. package/skills/session-start/soul.md +57 -0
  677. package/skills/skill-creator/SKILL.md +168 -0
  678. package/skills/spinout/SKILL.md +76 -0
  679. package/skills/sunset-review/SKILL.md +96 -0
  680. package/skills/test-runner/SKILL.md +362 -0
  681. package/skills/test-runner/rubric-v1.md +388 -0
  682. package/skills/test-runner/soul.md +46 -0
  683. package/skills/tmux-layout/SKILL.md +104 -0
  684. package/skills/ubiquitous-language/SKILL.md +97 -0
  685. package/skills/using-orchestrator/SKILL.md +144 -0
  686. package/skills/vault-mirror/SKILL.md +234 -0
  687. package/skills/vault-sync/SKILL.md +319 -0
  688. package/skills/vault-sync/package-lock.json +40 -0
  689. package/skills/vault-sync/package.json +11 -0
  690. package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +8 -0
  691. package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
  692. package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +8 -0
  693. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
  694. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +8 -0
  695. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +8 -0
  696. package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +8 -0
  697. package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +10 -0
  698. package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +8 -0
  699. package/skills/vault-sync/tests/fixtures/clean-vault/README.md +3 -0
  700. package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +11 -0
  701. package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
  702. package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +9 -0
  703. package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +8 -0
  704. package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
  705. package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
  706. package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +7 -0
  707. package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +9 -0
  708. package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
  709. package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +11 -0
  710. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +3 -0
  711. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +3 -0
  712. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
  713. package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +11 -0
  714. package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
  715. package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +11 -0
  716. package/skills/vault-sync/tests/schema-drift.test.mjs +133 -0
  717. package/skills/vault-sync/validator.mjs +658 -0
  718. package/skills/vault-sync/validator.sh +55 -0
  719. package/skills/wave-executor/SKILL.md +496 -0
  720. package/skills/wave-executor/circuit-breaker.md +169 -0
  721. package/skills/wave-executor/wave-loop.md +1043 -0
  722. package/skills/write-executable-plan/SKILL.md +237 -0
  723. package/skills/write-executable-plan/plan-template.md +154 -0
  724. package/templates/_minimal/CLAUDE.md.tmpl +41 -0
  725. package/templates/_minimal/README.md.tmpl +15 -0
  726. package/templates/_minimal/gitignore.tmpl +47 -0
  727. package/templates/_shared/harte-regeln.md +16 -0
  728. package/templates/_shared/loop.md +90 -0
  729. package/templates/_shared/rules/parallel-sessions.md +77 -0
  730. package/templates/nextjs-minimal/README.md +30 -0
  731. package/templates/nextjs-minimal/app/layout.tsx +18 -0
  732. package/templates/nextjs-minimal/app/page.tsx +7 -0
  733. package/templates/nextjs-minimal/eslint.config.mjs +16 -0
  734. package/templates/nextjs-minimal/next.config.mjs +4 -0
  735. package/templates/nextjs-minimal/package.json +27 -0
  736. package/templates/nextjs-minimal/tsconfig.json +23 -0
  737. package/templates/node-minimal/README.md +33 -0
  738. package/templates/node-minimal/eslint.config.mjs +10 -0
  739. package/templates/node-minimal/package.json +21 -0
  740. package/templates/node-minimal/src/index.ts +1 -0
  741. package/templates/node-minimal/tests/sanity.test.ts +5 -0
  742. package/templates/node-minimal/tsconfig.json +17 -0
  743. package/templates/personas/README.md +150 -0
  744. package/templates/personas/accounting-compliance.v1.md +120 -0
  745. package/templates/personas/accounting-tax-advisor.v1.md +116 -0
  746. package/templates/personas/buyer-p1-cto.v1.md +125 -0
  747. package/templates/personas/buyer-p2-kanzlei.v1.md +134 -0
  748. package/templates/personas/buyer-p3-build.v1.md +130 -0
  749. package/templates/personas/buyer-p4-tech-veto.v1.md +130 -0
  750. package/templates/personas/buyer-p5-solo.v1.md +132 -0
  751. package/templates/personas/buyer-p6-ld.v1.md +130 -0
  752. package/templates/personas/klima-ai-expert.v1.md +114 -0
  753. package/templates/personas/klima-physicist.v1.md +117 -0
  754. package/templates/python-uv/README.md +28 -0
  755. package/templates/python-uv/pyproject.toml +32 -0
  756. package/templates/python-uv/src/__PROJECT_NAME__/__init__.py +0 -0
  757. package/templates/python-uv/src/__PROJECT_NAME__/main.py +6 -0
  758. package/templates/python-uv/tests/test_sanity.py +2 -0
  759. package/templates/static-html/README.md +19 -0
  760. package/templates/static-html/index.html +15 -0
  761. package/templates/static-html/script.js +1 -0
  762. package/templates/static-html/styles.css +26 -0
@@ -0,0 +1,433 @@
1
+ /**
2
+ * named-vault-resolver.mjs — Walk-up named-vault resolution (Issue #700 Part 2).
3
+ *
4
+ * Generalises single-vault resolution to N named vaults. Each named vault is
5
+ * declared in the host-local `owner.yaml` under an optional `vaults:` list.
6
+ * When `vaults:` is absent, all exports degrade gracefully to byte-identical
7
+ * single-vault behaviour — absent-tolerant, never throws.
8
+ *
9
+ * ── Design ───────────────────────────────────────────────────────────────────
10
+ *
11
+ * Precedence for resolveNamedVault():
12
+ * 1. explicit vaultName arg (--vault-name CLI / Session Config vault-name)
13
+ * 2. walk-up org-prefix match against ownerConfig.vaults[].match.org-prefix
14
+ * 3. single-vault fallback → {source:'fallback'} (byte-identical to today)
15
+ *
16
+ * IO is fully injectable (existsSync, realpathSync, env, gitRemote) so every
17
+ * branch is unit-testable without touching disk or git.
18
+ *
19
+ * ── Exports ──────────────────────────────────────────────────────────────────
20
+ *
21
+ * parseNamedVaults(ownerConfig)
22
+ * canonicalSuffixesFromVaults(vaults, envOverride)
23
+ * matchVaultForRepo(repoSlug, vaults)
24
+ * resolveCanonicalSuffixes({ ownerConfig, env })
25
+ * findRepoRoot(cwd, { existsSync, realpathSync })
26
+ * resolveNamedVault({ vaultName, cwd, ownerConfig, env, gitRemote, existsSync, realpathSync })
27
+ */
28
+
29
+ import { join, dirname } from 'node:path';
30
+ import { existsSync as nodeExistsSync, realpathSync as nodeRealpathSync } from 'node:fs';
31
+ import { spawnSync } from 'node:child_process';
32
+
33
+ // ---------------------------------------------------------------------------
34
+ // Internal helpers
35
+ // ---------------------------------------------------------------------------
36
+
37
+ /** @param {unknown} v */
38
+ function isPlainObject(v) {
39
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
40
+ }
41
+
42
+ /**
43
+ * Default canonical suffix — mirrors vault-mirror.mjs _resolveCanonicalSuffix
44
+ * @internal
45
+ */
46
+ const DEFAULT_SUFFIX = '/agents/vault';
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // parseNamedVaults — PURE
50
+ // ---------------------------------------------------------------------------
51
+
52
+ /**
53
+ * Extract and validate the `vaults:` list from a raw ownerConfig object.
54
+ *
55
+ * Drop-and-WARN on malformed entries; never throw. Returns [] when the
56
+ * section is absent or empty — this is the backward-compat no-op path.
57
+ *
58
+ * Each valid entry: { name: string, suffix: string, root: string, match?: { 'org-prefix'?: string } }
59
+ *
60
+ * @param {object|undefined} ownerConfig — raw parsed owner.yaml (NOT merged with defaults)
61
+ * @returns {Array<{name:string, suffix:string, root:string, match:{'org-prefix'?:string}}>}
62
+ */
63
+ export function parseNamedVaults(ownerConfig) {
64
+ const raw = ownerConfig?.vaults;
65
+
66
+ // Absent or explicit null/empty → no-op
67
+ if (raw === undefined || raw === null) return [];
68
+ if (Array.isArray(raw) && raw.length === 0) return [];
69
+
70
+ if (!Array.isArray(raw)) {
71
+ process.stderr.write(
72
+ 'WARN named-vault-resolver: owner.yaml vaults: must be an array; ignoring\n',
73
+ );
74
+ return [];
75
+ }
76
+
77
+ const result = [];
78
+ for (let i = 0; i < raw.length; i++) {
79
+ const entry = raw[i];
80
+ if (!isPlainObject(entry)) {
81
+ process.stderr.write(
82
+ `WARN named-vault-resolver: owner.yaml vaults[${i}] is not an object; dropping\n`,
83
+ );
84
+ continue;
85
+ }
86
+
87
+ const { name, suffix, root, match } = entry;
88
+
89
+ if (typeof name !== 'string' || name.trim() === '') {
90
+ process.stderr.write(
91
+ `WARN named-vault-resolver: owner.yaml vaults[${i}].name must be a non-empty string; dropping entry\n`,
92
+ );
93
+ continue;
94
+ }
95
+ if (typeof suffix !== 'string' || suffix.trim() === '') {
96
+ process.stderr.write(
97
+ `WARN named-vault-resolver: owner.yaml vaults[${i}].suffix must be a non-empty string; dropping entry\n`,
98
+ );
99
+ continue;
100
+ }
101
+ if (typeof root !== 'string' || root.trim() === '') {
102
+ process.stderr.write(
103
+ `WARN named-vault-resolver: owner.yaml vaults[${i}].root must be a non-empty string; dropping entry\n`,
104
+ );
105
+ continue;
106
+ }
107
+
108
+ // match is optional; if present, validate it
109
+ let matchObj = {};
110
+ if (match !== undefined && match !== null) {
111
+ if (!isPlainObject(match)) {
112
+ process.stderr.write(
113
+ `WARN named-vault-resolver: owner.yaml vaults[${i}].match must be an object; ignoring match field\n`,
114
+ );
115
+ } else {
116
+ const orgPrefix = match['org-prefix'];
117
+ if (orgPrefix !== undefined && typeof orgPrefix !== 'string') {
118
+ process.stderr.write(
119
+ `WARN named-vault-resolver: owner.yaml vaults[${i}].match.org-prefix must be a string; ignoring\n`,
120
+ );
121
+ } else {
122
+ matchObj = { 'org-prefix': orgPrefix };
123
+ }
124
+ }
125
+ }
126
+
127
+ result.push({
128
+ name: name.trim(),
129
+ suffix: suffix.trim(),
130
+ root: root.trim(),
131
+ match: matchObj,
132
+ });
133
+ }
134
+
135
+ return result;
136
+ }
137
+
138
+ // ---------------------------------------------------------------------------
139
+ // canonicalSuffixesFromVaults — PURE
140
+ // ---------------------------------------------------------------------------
141
+
142
+ /**
143
+ * Build the array of canonical suffixes used in the .some() guard.
144
+ *
145
+ * When `vaults` is empty AND `envOverride` is absent/blank → returns
146
+ * ['/agents/vault'] — byte-identical to the pre-#700 single-suffix path.
147
+ *
148
+ * When `envOverride` is set (non-blank) → returns [envOverride.trim()] always,
149
+ * mirroring the original VAULT_MIRROR_CANONICAL_SUFFIX env-wins behaviour.
150
+ *
151
+ * When `vaults` is non-empty AND no env override → returns the suffix from
152
+ * each named vault entry.
153
+ *
154
+ * @param {Array<{suffix:string}>} vaults — result of parseNamedVaults()
155
+ * @param {string|undefined} [envOverride] — process.env.VAULT_MIRROR_CANONICAL_SUFFIX
156
+ * @returns {string[]}
157
+ */
158
+ export function canonicalSuffixesFromVaults(vaults, envOverride) {
159
+ // Env override always wins (mirrors _resolveCanonicalSuffix)
160
+ if (typeof envOverride === 'string' && envOverride.trim() !== '') {
161
+ return [envOverride.trim()];
162
+ }
163
+
164
+ // Named vaults present → collect their suffixes
165
+ if (vaults.length > 0) {
166
+ return vaults.map((v) => v.suffix);
167
+ }
168
+
169
+ // Fallback: single-vault default
170
+ return [DEFAULT_SUFFIX];
171
+ }
172
+
173
+ // ---------------------------------------------------------------------------
174
+ // matchVaultForRepo — PURE
175
+ // ---------------------------------------------------------------------------
176
+
177
+ /**
178
+ * Find the first named vault whose `match.org-prefix` is a prefix of the given
179
+ * repoSlug (format: `org/repo-name` as returned by deriveRepo()).
180
+ *
181
+ * Returns the matching vault entry or null when no match found or when the
182
+ * entry has no match.org-prefix defined.
183
+ *
184
+ * First-match-wins; caller is responsible for WARN on ambiguity if needed.
185
+ *
186
+ * @param {string} repoSlug — e.g. 'bernhard-group/foo'
187
+ * @param {Array<{name:string, suffix:string, root:string, match:{'org-prefix'?:string}}>} vaults
188
+ * @returns {{name:string, suffix:string, root:string, match:object}|null}
189
+ */
190
+ export function matchVaultForRepo(repoSlug, vaults) {
191
+ if (!repoSlug || vaults.length === 0) return null;
192
+
193
+ const slug = String(repoSlug);
194
+ const matched = [];
195
+
196
+ for (const v of vaults) {
197
+ const orgPrefix = v.match?.['org-prefix'];
198
+ if (typeof orgPrefix !== 'string' || orgPrefix.trim() === '') continue;
199
+
200
+ // Match: repoSlug starts with the org-prefix
201
+ if (slug === orgPrefix || slug.startsWith(`${orgPrefix}/`) || slug.startsWith(`${orgPrefix}-`)) {
202
+ matched.push(v);
203
+ }
204
+ }
205
+
206
+ if (matched.length > 1) {
207
+ process.stderr.write(
208
+ `WARN named-vault-resolver: multiple named vaults match repo "${repoSlug}": ${matched.map((v) => v.name).join(', ')}; using first match "${matched[0].name}"\n`,
209
+ );
210
+ }
211
+
212
+ return matched.length > 0 ? matched[0] : null;
213
+ }
214
+
215
+ // ---------------------------------------------------------------------------
216
+ // resolveCanonicalSuffixes — thin wrapper (ownerConfig injectable)
217
+ // ---------------------------------------------------------------------------
218
+
219
+ /**
220
+ * Resolve the canonical suffix array for the vault-mirror guard.
221
+ *
222
+ * Caller is expected to pass ownerConfig (loaded from disk by the caller).
223
+ * vault-mirror.mjs loads it via loadOwnerConfig() before calling this.
224
+ * When ownerConfig is not provided (undefined), falls back to single-vault
225
+ * default — byte-identical to pre-#700 behaviour.
226
+ *
227
+ * @param {{ ownerConfig?: object, env?: Record<string, string|undefined> }} [opts]
228
+ * @returns {string[]}
229
+ */
230
+ export function resolveCanonicalSuffixes({ ownerConfig, env = process.env } = {}) {
231
+ const vaults = parseNamedVaults(ownerConfig);
232
+ return canonicalSuffixesFromVaults(vaults, env?.VAULT_MIRROR_CANONICAL_SUFFIX);
233
+ }
234
+
235
+ // ---------------------------------------------------------------------------
236
+ // findRepoRoot — injectable IO
237
+ // ---------------------------------------------------------------------------
238
+
239
+ /**
240
+ * Walk up from `cwd` (after resolving symlinks) to locate the nearest `.git`
241
+ * directory, handling worktree `.git` files (same idiom as workspace.mjs L62-96).
242
+ *
243
+ * Stops at filesystem root. Returns null (never throws) when no `.git` found.
244
+ *
245
+ * @param {string} [cwd]
246
+ * @param {{ existsSync?: Function, realpathSync?: Function }} [io]
247
+ * @returns {string|null} absolute path of the repo root, or null
248
+ */
249
+ export function findRepoRoot(cwd = process.cwd(), { existsSync = nodeExistsSync, realpathSync = nodeRealpathSync } = {}) {
250
+ let start;
251
+ try {
252
+ start = realpathSync(cwd);
253
+ } catch {
254
+ start = cwd;
255
+ }
256
+
257
+ let p = start;
258
+ let levels = 0;
259
+ while (levels < 20) {
260
+ const gitEntry = join(p, '.git');
261
+ if (existsSync(gitEntry)) {
262
+ // Symlink / worktree file vs real directory handled at call site —
263
+ // for the purposes of finding the root, the directory containing .git is enough
264
+ return p;
265
+ }
266
+ const parent = dirname(p);
267
+ if (parent === p) break; // filesystem root
268
+ p = parent;
269
+ levels++;
270
+ }
271
+
272
+ return null;
273
+ }
274
+
275
+ // ---------------------------------------------------------------------------
276
+ // resolveNamedVault — main resolution entry point
277
+ // ---------------------------------------------------------------------------
278
+
279
+ /**
280
+ * Resolve the named vault to use for a given cwd / explicit override.
281
+ *
282
+ * Precedence:
283
+ * 1. explicit vaultName → {source:'explicit'} — skips cwd/git entirely
284
+ * 2. walk-up org-prefix match against vaults[].match.org-prefix
285
+ * using the git remote of the repo found at cwd → {source:'walkup'}
286
+ * 3. single-vault fallback → {source:'fallback'}
287
+ *
288
+ * Injectable IO (existsSync, realpathSync, gitRemote) for full unit-testability.
289
+ * `gitRemote(repoRoot)` is called ONLY in the walk-up path — injecting a
290
+ * stub that throws proves the explicit path never calls it.
291
+ *
292
+ * @param {{
293
+ * vaultName?: string|null,
294
+ * cwd?: string,
295
+ * ownerConfig?: object,
296
+ * env?: Record<string, string|undefined>,
297
+ * gitRemote?: (repoRoot: string) => string,
298
+ * existsSync?: Function,
299
+ * realpathSync?: Function,
300
+ * }} [opts]
301
+ * @returns {{
302
+ * root: string|null,
303
+ * suffix: string,
304
+ * name: string|null,
305
+ * source: 'explicit'|'walkup'|'fallback'
306
+ * }}
307
+ */
308
+ export function resolveNamedVault({
309
+ vaultName = null,
310
+ cwd = process.cwd(),
311
+ ownerConfig,
312
+ env = process.env,
313
+ gitRemote = _defaultGitRemote,
314
+ existsSync = nodeExistsSync,
315
+ realpathSync = nodeRealpathSync,
316
+ } = {}) {
317
+ const vaults = parseNamedVaults(ownerConfig);
318
+
319
+ // ── Path 1: explicit vault-name ──────────────────────────────────────────
320
+ const trimmedName = typeof vaultName === 'string' ? vaultName.trim() : '';
321
+ if (trimmedName) {
322
+ // Look up by name in the vaults list
323
+ const entry = vaults.find((v) => v.name === trimmedName) ?? null;
324
+ return {
325
+ root: entry?.root ?? null,
326
+ suffix: entry?.suffix ?? _resolveEnvSuffix(env) ?? DEFAULT_SUFFIX,
327
+ name: trimmedName,
328
+ source: 'explicit',
329
+ };
330
+ }
331
+
332
+ // ── Path 2: walk-up org-prefix match ────────────────────────────────────
333
+ if (vaults.length > 0) {
334
+ const repoRoot = findRepoRoot(cwd, { existsSync, realpathSync });
335
+ if (repoRoot !== null) {
336
+ // Get the git remote for origin
337
+ let remoteUrl;
338
+ try {
339
+ remoteUrl = gitRemote(repoRoot);
340
+ } catch {
341
+ remoteUrl = '';
342
+ }
343
+
344
+ if (remoteUrl) {
345
+ // Derive org/repo from the remote URL (strip suffix/.git/scheme)
346
+ const repoSlug = _deriveSlugFromRemote(remoteUrl);
347
+
348
+ // Guard: if this repo IS one of the vaults, skip (don't self-mirror)
349
+ const canonicalSuffixes = canonicalSuffixesFromVaults(vaults, env?.VAULT_MIRROR_CANONICAL_SUFFIX);
350
+ const normalized = _normalizeRemoteUrl(remoteUrl);
351
+ if (canonicalSuffixes.some((s) => normalized.endsWith(s))) {
352
+ // This is the vault itself — fall through to fallback
353
+ } else {
354
+ const match = matchVaultForRepo(repoSlug, vaults);
355
+ if (match !== null) {
356
+ return {
357
+ root: match.root,
358
+ suffix: match.suffix,
359
+ name: match.name,
360
+ source: 'walkup',
361
+ };
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ // ── Path 3: single-vault fallback ────────────────────────────────────────
369
+ return {
370
+ root: null,
371
+ suffix: _resolveEnvSuffix(env) ?? DEFAULT_SUFFIX,
372
+ name: null,
373
+ source: 'fallback',
374
+ };
375
+ }
376
+
377
+ // ---------------------------------------------------------------------------
378
+ // Internal utilities
379
+ // ---------------------------------------------------------------------------
380
+
381
+ /**
382
+ * Resolve the env-var suffix override (mirrors _resolveCanonicalSuffix).
383
+ * Returns null when the env var is absent/blank.
384
+ * @param {Record<string, string|undefined>} env
385
+ * @returns {string|null}
386
+ */
387
+ function _resolveEnvSuffix(env) {
388
+ const v = env?.VAULT_MIRROR_CANONICAL_SUFFIX;
389
+ return typeof v === 'string' && v.trim() !== '' ? v.trim() : null;
390
+ }
391
+
392
+ /**
393
+ * Normalize a git remote URL to host/path tail (mirrors vault-mirror.mjs _normalizeRemote).
394
+ * @param {string} url
395
+ * @returns {string}
396
+ */
397
+ function _normalizeRemoteUrl(url) {
398
+ return String(url ?? '')
399
+ .trim()
400
+ .replace(/\.git$/, '')
401
+ .replace(/^git@([^:]+):/, '$1/')
402
+ .replace(/^[a-z]+:\/\//, '')
403
+ .replace(/\/+$/, '');
404
+ }
405
+
406
+ /**
407
+ * Derive an org/repo slug from a git remote URL.
408
+ * e.g. 'git@github.com:my-org/my-repo.git' → 'my-org/my-repo'
409
+ * @param {string} url
410
+ * @returns {string}
411
+ */
412
+ function _deriveSlugFromRemote(url) {
413
+ const normalized = _normalizeRemoteUrl(url);
414
+ // normalized is now 'host/path/to/repo' — take the last two segments
415
+ const parts = normalized.split('/').filter(Boolean);
416
+ if (parts.length >= 2) {
417
+ return `${parts[parts.length - 2]}/${parts[parts.length - 1]}`;
418
+ }
419
+ return normalized;
420
+ }
421
+
422
+ /**
423
+ * Default gitRemote implementation: runs `git -C <repoRoot> remote get-url origin`.
424
+ * @param {string} repoRoot
425
+ * @returns {string}
426
+ */
427
+ function _defaultGitRemote(repoRoot) {
428
+ const res = spawnSync('git', ['-C', repoRoot, 'remote', 'get-url', 'origin'], {
429
+ encoding: 'utf8',
430
+ });
431
+ if (res.status !== 0) return '';
432
+ return res.stdout.trim();
433
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * owner-config/coerce.mjs — Strict-mode wrapper around validate().
3
+ *
4
+ * Imports: validate + OwnerConfigError. Throws on validation failure, returns
5
+ * the normalized value on success. Convenient for CLI entrypoints and tests
6
+ * that want to assert on success without inspecting `ok`.
7
+ */
8
+
9
+ import { validate } from './validate.mjs';
10
+ import { OwnerConfigError } from './error.mjs';
11
+
12
+ /**
13
+ * Strict-mode wrapper around validate(). Returns the normalized value when
14
+ * the input passes the gate, otherwise throws OwnerConfigError with the
15
+ * full error list attached as `.errors`.
16
+ *
17
+ * @param {unknown} raw
18
+ * @returns {object}
19
+ */
20
+ export function coerce(raw) {
21
+ const result = validate(raw);
22
+ if (!result.ok) {
23
+ throw new OwnerConfigError(
24
+ `owner config validation failed (${result.errors.length} error${result.errors.length === 1 ? '' : 's'})`,
25
+ result.errors
26
+ );
27
+ }
28
+ return result.value;
29
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * owner-config/constants.mjs — Schema constants for the owner persona config.
3
+ *
4
+ * Leaf module. No imports. All exported arrays are frozen so consumers cannot
5
+ * accidentally mutate the canonical enum sets.
6
+ */
7
+
8
+ /** Current owner-config schema version. New writes are stamped with this. */
9
+ export const CURRENT_OWNER_SCHEMA_VERSION = 1;
10
+
11
+ /** Valid values for tone.style. */
12
+ export const VALID_TONE_STYLES = Object.freeze(['direct', 'neutral', 'friendly']);
13
+
14
+ /** Valid values for efficiency.output-level. */
15
+ export const VALID_OUTPUT_LEVELS = Object.freeze(['lite', 'full', 'ultra']);
16
+
17
+ /** Valid values for efficiency.preamble. */
18
+ export const VALID_PREAMBLE_LEVELS = Object.freeze(['minimal', 'verbose']);
19
+
20
+ /** Valid values for efficiency.comments-in-code. */
21
+ export const VALID_COMMENTS_LEVELS = Object.freeze(['minimal', 'full']);
@@ -0,0 +1,50 @@
1
+ /**
2
+ * owner-config/defaults.mjs — Canonical default-filled owner config factory.
3
+ *
4
+ * Imports constants only. Leaf in the dependency sense (no circular deps).
5
+ * Returns the fully-default-filled config with `owner.name` and
6
+ * `owner.language` intentionally left blank — those are required from the user;
7
+ * the bootstrap interview (D2) fills them in.
8
+ */
9
+
10
+ import { CURRENT_OWNER_SCHEMA_VERSION } from './constants.mjs';
11
+
12
+ /**
13
+ * Returns the canonical default-filled owner config. `owner.name` and
14
+ * `owner.language` are intentionally empty — those are user-required fields
15
+ * the bootstrap interview (D2) fills in. The `defaults()` shape is what
16
+ * `merge()` uses as its base when callers pass partial overrides.
17
+ *
18
+ * @returns {object}
19
+ */
20
+ export function defaults() {
21
+ return {
22
+ 'schema-version': CURRENT_OWNER_SCHEMA_VERSION,
23
+ owner: {
24
+ name: '',
25
+ 'email-hash': null,
26
+ language: '',
27
+ },
28
+ tone: {
29
+ style: 'neutral',
30
+ tonality: null,
31
+ },
32
+ efficiency: {
33
+ 'output-level': 'full',
34
+ preamble: 'minimal',
35
+ 'comments-in-code': 'minimal',
36
+ },
37
+ 'hardware-sharing': {
38
+ enabled: false,
39
+ 'hash-salt': null,
40
+ },
41
+ defaults: {
42
+ 'preferred-test-command': null,
43
+ 'preferred-editor': null,
44
+ },
45
+ metadata: {
46
+ created_at: null,
47
+ updated_at: null,
48
+ },
49
+ };
50
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * owner-config/error.mjs — OwnerConfigError class.
3
+ *
4
+ * Leaf module. No imports. Thrown by coerce() when validation fails. The
5
+ * `.errors` array carries the full list of human-readable failure messages
6
+ * collected by validate().
7
+ */
8
+
9
+ export class OwnerConfigError extends Error {
10
+ /**
11
+ * @param {string} message
12
+ * @param {string[]} [errors]
13
+ */
14
+ constructor(message, errors = []) {
15
+ super(message);
16
+ this.name = 'OwnerConfigError';
17
+ this.errors = errors;
18
+ }
19
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * owner-config/index.mjs — Re-export hub for all 10 public symbols.
3
+ *
4
+ * DAG: constants/error (leaves) → defaults → merge; constants/error → validate → coerce.
5
+ * This hub is the single import target for `scripts/lib/owner-config.mjs` (top wrapper).
6
+ */
7
+
8
+ export { CURRENT_OWNER_SCHEMA_VERSION, VALID_TONE_STYLES, VALID_OUTPUT_LEVELS, VALID_PREAMBLE_LEVELS, VALID_COMMENTS_LEVELS } from './constants.mjs';
9
+ export { OwnerConfigError } from './error.mjs';
10
+ export { defaults } from './defaults.mjs';
11
+ export { validate } from './validate.mjs';
12
+ export { coerce } from './coerce.mjs';
13
+ export { merge } from './merge.mjs';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * owner-config/merge.mjs — Deep merge for owner persona configs.
3
+ *
4
+ * Imports: constants + defaults. One-level-deep section merge because the
5
+ * schema has no nested object leaves beyond top-level sections. The output is
6
+ * always a full default-filled config — either input may be partial.
7
+ */
8
+
9
+ import { CURRENT_OWNER_SCHEMA_VERSION } from './constants.mjs';
10
+ import { defaults } from './defaults.mjs';
11
+
12
+ function isPlainObject(v) {
13
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
14
+ }
15
+
16
+ /**
17
+ * Deep merge two owner configs. `override` values win on every leaf key
18
+ * where they are defined (i.e. not undefined). The returned value is a
19
+ * full default-filled config — either input may be partial.
20
+ *
21
+ * Used by D3 (`soul.md` runtime-merge) and D4 (baseline-propagation +
22
+ * per-session override). The merge is one level deep on each top-level
23
+ * section (owner, tone, efficiency, hardware-sharing, defaults, metadata)
24
+ * because the schema has no nested object leaves beyond that.
25
+ *
26
+ * @param {object|null|undefined} base
27
+ * @param {object|null|undefined} override
28
+ * @returns {object}
29
+ */
30
+ export function merge(base, override) {
31
+ const baseSafe = isPlainObject(base) ? base : {};
32
+ const overSafe = isPlainObject(override) ? override : {};
33
+ const def = defaults();
34
+
35
+ const sections = ['owner', 'tone', 'efficiency', 'hardware-sharing', 'defaults', 'metadata'];
36
+ const out = {
37
+ 'schema-version': CURRENT_OWNER_SCHEMA_VERSION,
38
+ };
39
+
40
+ for (const section of sections) {
41
+ const baseSection = isPlainObject(baseSafe[section]) ? baseSafe[section] : {};
42
+ const overSection = isPlainObject(overSafe[section]) ? overSafe[section] : {};
43
+ out[section] = { ...def[section], ...baseSection };
44
+ for (const [k, v] of Object.entries(overSection)) {
45
+ if (v !== undefined) {
46
+ out[section][k] = v;
47
+ }
48
+ }
49
+ }
50
+
51
+ return out;
52
+ }