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,390 @@
1
+ <!-- source: session-orchestrator plugin (canonical: rules/opt-in-stack/backend.md) -->
2
+ ---
3
+ globs:
4
+ - src/app/**
5
+ - src/services/**
6
+ - src/lib/api/**
7
+ - src/routes/**
8
+ - src/app/api/**
9
+ tier: wave-only
10
+ ---
11
+ # Backend Rules (Path-scoped)
12
+
13
+ ## Server Actions (Next.js)
14
+ - File pattern: `src/app/actions/*.actions.ts`
15
+ - Always `"use server"` at top of file.
16
+ - Auth first: `const { user, supabase } = await requireAuth()`
17
+ - For tenant-specific data, look up `businessId` from the database after auth (do not destructure from `requireAuth`).
18
+ - Cache `businessId` per request via `React.cache()` wrapping a `getBusinessId(userId, supabase)` helper to avoid redundant DB lookups.
19
+ - Zod validation on all inputs before any DB operation.
20
+ - Return typed results using the canonical API response envelope (see below).
21
+ - Never return raw DB errors to client.
22
+
23
+ ### Canonical API Response Envelope (SEC-009)
24
+ All API responses and server action returns MUST use the canonical envelope from `@your-org/zod-schemas`:
25
+ - **Success:** `{ success: true, data: T }` | **Error:** `{ success: false, error: { code, message, details? } }`
26
+ - **Standard codes:** `VALIDATION_ERROR` (400), `UNAUTHORIZED` (401), `FORBIDDEN` (403), `NOT_FOUND` (404), `CONFLICT` (409), `RATE_LIMITED` (429), `INTERNAL_ERROR` (500). Do not invent new codes without documenting.
27
+ - Never return raw error objects or `error.message` to client (SEC-009). Map to standard code + user-friendly message.
28
+ - `details` field: only for validation errors (Zod issues array). Never include stack traces.
29
+ - **Error construction (SEC-009 defense-in-depth):** when throwing a typed error, keep `message` static/user-facing and move raw upstream content (DB `error.message`, dependency output) into a structured `details` field for server-side logging — never interpolate it into the message string. The wrapper strips `details` from the client envelope, so a sanitizer bypass still cannot leak it into user-facing text.
30
+ - **MCP tools mirror SEC-009.** New MCP tools MUST sanitize errors like server actions: structured `console.error({ error_class, error_message })` server-side + a static, caller-safe return message. Even AUTHENTICATED callers must never receive raw DB error strings (table/column names, PG codes).
31
+ - Import: `import { ApiErrorSchema, apiSuccess } from '@your-org/zod-schemas'`
32
+
33
+ ### SaaS Response Envelope (internal vs SaaS)
34
+
35
+ Two envelopes, one per consumer class. Pick **one** per endpoint — do not mix shapes inside a route group.
36
+
37
+ | Use for | Envelope shape | Error codes | Import |
38
+ |---|---|---|---|
39
+ | **Internal** — Next.js server actions, internal service-to-service | `{ success: true, data }` / `{ success: false, error }` | `ApiErrorCode` enum (above) | `@your-org/zod-schemas` (root) |
40
+ | **SaaS** — service-token-gated public API consumed by external clients | `{ data, meta? }` / `{ error: { code, message, details? } }` | `SaasErrorCode` enum (`VALIDATION_ERROR`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `CONFLICT`, `RATE_LIMITED`, `PLAN_LIMIT_EXCEEDED`, `PAYMENT_REQUIRED`, `QUOTA_EXHAUSTED`, `UPSTREAM_ERROR`, `INTERNAL_ERROR`) | `@your-org/zod-schemas/saas-response` |
41
+
42
+ ```ts
43
+ import { saasResponseSchema, saasErrorSchema } from '@your-org/zod-schemas/saas-response';
44
+ ```
45
+
46
+ When to choose SaaS over internal:
47
+ - The endpoint is authenticated with a **service token** (not a user session) and carries a **plan / quota** concept. Plan-limit and quota errors have first-class codes.
48
+ - The response is paginated with stable `{ total, limit, offset }` meta — external clients need the shape to be contract-stable.
49
+ - The caller is billed or rate-limited at the subscription level, and must differentiate `RATE_LIMITED` from `PLAN_LIMIT_EXCEEDED`.
50
+
51
+ Anti-pattern: routing a SaaS client through the internal envelope. The internal `ApiErrorCode` set lacks `PLAN_LIMIT_EXCEEDED` / `QUOTA_EXHAUSTED`, which forces integrators to pattern-match on `message` strings — a breakage vector on every copy edit.
52
+
53
+ Harvested from a SaaS service codebase (baseline #196).
54
+
55
+ ### Wrapper Contract (BE-012)
56
+ Server actions wrapped by auth/tenant/validation higher-order functions MUST throw on error and return **data-only** on success. The wrapper — not the inner action — converts the thrown error into the `{ success: false, ... }` envelope.
57
+
58
+ This contract prevents a silent-pass class of bug: if the inner action returns `{ success: false, error: ... }` and the wrapper returns `{ success: true, data: <innerResult> }`, the client receives `{ success: true, data: { success: false, ... } }`. Tests that only check `result.success` pass green while production fails.
59
+
60
+ **Bad — nested envelopes, silently passing:**
61
+ ```ts
62
+ async function createInvoice(input) {
63
+ const parsed = InvoiceSchema.safeParse(input);
64
+ if (!parsed.success) return { success: false, error: { code: 'VALIDATION_ERROR', message: 'bad input' } };
65
+ // ...
66
+ return { success: true, data: invoice };
67
+ }
68
+ export const action = withAuth(createInvoice); // wraps the returned `{success:false}` as data
69
+ ```
70
+
71
+ **Good — inner throws, wrapper enveloppes:**
72
+ ```ts
73
+ async function createInvoice(input) {
74
+ const parsed = InvoiceSchema.parse(input); // throws ZodError on failure
75
+ // ...
76
+ return invoice; // data-only; wrapper wraps as { success: true, data: invoice }
77
+ }
78
+ export const action = withAuth(createInvoice);
79
+ ```
80
+
81
+ The wrapper contract:
82
+ ```ts
83
+ function withAuth<T>(fn: (ctx: AuthCtx, input: any) => Promise<T>) {
84
+ return async (input: any) => {
85
+ try {
86
+ const ctx = await requireAuth();
87
+ const data = await fn(ctx, input);
88
+ return { success: true, data } as const;
89
+ } catch (err) {
90
+ return toErrorEnvelope(err); // maps ZodError → VALIDATION_ERROR, AuthError → UNAUTHORIZED, etc.
91
+ }
92
+ };
93
+ }
94
+ ```
95
+
96
+ **Reviewer detection** — wrapped actions that return an envelope directly are suspect:
97
+ ```bash
98
+ rg -n "return \{\s*success:\s*(true|false)" src/app/actions/ src/services/
99
+ ```
100
+ Any hit inside a function that is then passed through `withAuth(...)` / `withTenant(...)` / `withValidation(...)` is a likely BE-012 violation. Test-quality cross-reference: `testing.md` § "Test Quality — False-Positive Prevention" covers how unit tests must assert `data`/`error` fields shape, not just `success` boolean.
101
+
102
+ **Evidence:** A production Next.js app migration converted 66+ server actions after discovering the silent-pass pattern in production.
103
+
104
+ ## API Routes (Next.js)
105
+ - Use for webhooks, external API endpoints, cron jobs only.
106
+ - Server Actions preferred over API routes for internal mutations.
107
+ - Validate webhook signatures (HMAC, timing-safe comparison).
108
+ - A webhook endpoint's `api_version` cannot be updated in place — recreating the endpoint mints a NEW signing secret and breaks the deployed secret env until it is updated too. Treat secret-rotation + env-update as a single coordinated go-live step, never a mid-session mutation. (Enabling a disabled endpoint IS a safe in-place update.)
109
+ - Rate limit all public endpoints.
110
+
111
+ ## Express Services
112
+ - ESM modules (`"type": "module"` in package.json).
113
+ - Helmet for security headers.
114
+ - Prom-client for Prometheus metrics.
115
+ - Structured logging with Pino.
116
+ - Health check endpoint: `GET /health` (returns 200 + uptime + version).
117
+
118
+ ### Graceful Shutdown
119
+ - Handle `SIGTERM` and `SIGINT` signals to drain connections before exiting.
120
+ - Call `server.close()` to stop accepting new connections, then wait for in-flight requests to complete.
121
+ - Set a forced exit timeout (10s) to prevent hanging: `setTimeout(() => process.exit(1), 10_000).unref()`.
122
+ - Return 503 during shutdown drain if a load balancer continues sending traffic.
123
+ - Close database connections and flush logs after the HTTP server is closed.
124
+ - Wrap `app.listen()` in `if (process.env.NODE_ENV !== 'test')` so test imports don't start the server.
125
+
126
+ ### API + Worker Split (ROLE pattern)
127
+ Split api and worker into separate processes when any of these apply: queue-based jobs (BullMQ / pg-boss), CPU-heavy jobs (>500ms or >256MB), long-running jobs (p95 >10s), external binaries (Chromium / ffmpeg / pandoc), or ≥1 worker-bound endpoint that would block the HTTP server.
128
+
129
+ - **Single codebase, env-var routing:** set `ROLE=api|worker|both`; a generic router in `src/role-router.ts` starts only the subsystems for that role.
130
+ - **Default:** `ROLE=both` in `docker-compose.yml` — no split needed until traffic or job characteristics demand it.
131
+ - **Scale-out:** `docker-compose.scaled.yml` in `templates/docker-service/` launches `api` and `worker` as separate services. Scale workers independently: `docker compose up -d --scale worker=N`.
132
+ - **Redis:** prefer an external managed Redis instance for production. An in-compose Redis service is commented-optional in the scaled template.
133
+
134
+ ### Logging & Error Tracking
135
+ - Use `@your-org/logger` (Pino-based) for structured logging. Initialize with `new Logger()`, set level via `LOG_LEVEL` env var.
136
+ - Never log PII (emails, names, IBANs, Steuernummer). Use UUIDs and correlation IDs instead.
137
+ - Use `req.id` or `x-request-id` header for request correlation. Inject into logger context.
138
+ - Log levels: `error` (failures), `warn` (degraded), `info` (request lifecycle), `debug` (dev only).
139
+ - Cross-references: structured logging and DSGVO PII rules live in the baseline `infrastructure` / `security-compliance` rules (not vendored into this plugin).
140
+
141
+ ### Sentry Integration
142
+ - **SDK selection:** Next.js App Router → `@sentry/nextjs` | Express/Docker → `@sentry/node` | Swift → `sentry-cocoa`.
143
+ - **Init order (Express):** `initSentry()` → `express()` → security middleware → `express.json()` → routes → `Sentry.setupExpressErrorHandler(app)` (last, before error handler).
144
+ - **PII redaction:** Configure `beforeSend` to strip `authorization`/`cookie` headers and redact `request.data`. Configure `beforeBreadcrumb` to scrub emails/IBANs from URLs and messages using a regex redactor. Extend to `beforeSendTransaction` and `beforeSendSpan` (Sentry v8+).
145
+ - **User context:** `Sentry.setUser({ id: user.id })` after auth — never set email or name.
146
+ - **Config:** Set `environment` from `NODE_ENV`, `release` from `package.json` version. Never log `SENTRY_DSN` — it's a secret URL.
147
+
148
+ ## Streaming / SSE Patterns
149
+ - Use SSE for real-time one-way data (AI streaming, live updates, long-lived event channels). Set `Content-Type: text/event-stream`.
150
+ - Send `data: [DONE]\n\n` as final event. Max 3 concurrent SSE connections per user.
151
+ - Client: `EventSource` or Vercel AI SDK `useChat`/`useCompletion`.
152
+ - Clean up on disconnect: `req.on('close')` (Express) or `signal.aborted` (Next.js).
153
+
154
+ ### SSE vs WebSocket decision
155
+ - **SSE** — one-way server→client, HTTP/1.1 friendly (proxies, CDNs, auth middleware all pass through), `EventSource` auto-reconnect is built-in. **Prefer for:** AI token streaming, dashboard live updates, webhook relay, notification feeds. Default choice.
156
+ - **WebSocket** — bidirectional, higher proxy complexity (requires `Upgrade` header handling end-to-end). **Prefer only when:** client→server messages share the channel (chat, collaborative editing, RPC over long-lived connection) AND polling / separate POST is insufficient.
157
+ - Rule of thumb: if the client would otherwise open a second HTTP request per action, SSE is correct. If every user keystroke or cursor move must hit the server, WebSocket is correct.
158
+
159
+ ### Heartbeat cadence
160
+ - Send a comment-line heartbeat every **30s** (`: heartbeat\n\n`) to keep intermediaries (nginx, Vercel, Cloudflare, corporate proxies) from timing out idle connections.
161
+ - Comment lines are ignored by `EventSource`, so they don't fire client `onmessage` handlers — zero client-side cost.
162
+ - If the stream is genuinely noisy (>1 event/sec steady), heartbeat is optional. If there are natural silence windows, heartbeat is mandatory.
163
+
164
+ ### Event-name convention
165
+ - Named events (`event: <name>\n`) instead of untyped `data:` payloads, so client code reads `source.addEventListener('<name>', ...)` rather than switching on payload shape.
166
+ - Naming: lowercase, dot-scoped, noun-verb. Examples: `draft.ready`, `classification.done`, `job.failed`, `stream.heartbeat`, `stream.end`.
167
+ - Scope events by domain, not by endpoint. Two endpoints emitting `job.failed` is fine if the payload shape is identical.
168
+ - Document the event catalog in the service's `CLAUDE.md` or `docs/api.md` — consumers need to know what to listen for without reading source.
169
+
170
+ ### Client reconnect pattern
171
+ - `EventSource` reconnects automatically on network drop. Use the `Last-Event-ID` header to resume from the last received ID — set `id: <number>\n` on each server event for this to work.
172
+ - Server must accept `Last-Event-ID` (header or `?lastEventId=` query fallback) and replay missed events from its buffer. If no buffer, skip resume and send a `stream.reset` event so the client discards stale UI state.
173
+ - Bound reconnect attempts on the client side only if the UI should give up (e.g., "connection lost, reload"). For always-on dashboards, let the browser's default backoff (0 → 3s → 30s) run.
174
+
175
+ ### Auth on SSE endpoints
176
+ - `EventSource` has **no API to send custom headers** — cannot use `Authorization: Bearer ...`.
177
+ - Options, in order of preference:
178
+ 1. **Cookie-based session** (same-origin / strict SameSite cookie) — works transparently, preferred for first-party dashboards.
179
+ 2. **Short-lived token in query string** (`?token=<jwt>`) — acceptable when session cookies are unavailable. Token TTL ≤5 min, single-use if possible, never logged (strip from access logs).
180
+ 3. **Upgrade to `fetch()` + `ReadableStream`** if the client library supports it (Vercel AI SDK does). This allows custom headers.
181
+ - Never put long-lived tokens in query strings — they end up in server logs, browser history, and referer headers.
182
+
183
+ ### Minimal server outline (Hono / Express / Next.js shape)
184
+ ```ts
185
+ // Hono example (SSE daemon pattern)
186
+ app.get('/events', streamSSE(async (stream) => {
187
+ const onDraft = (payload) => stream.writeSSE({ event: 'draft.ready', data: JSON.stringify(payload), id: String(++seq) });
188
+ emitter.on('draft.ready', onDraft);
189
+ const hb = setInterval(() => stream.writeSSE({ data: ': heartbeat' }), 30_000);
190
+ stream.onAbort(() => { clearInterval(hb); emitter.off('draft.ready', onDraft); });
191
+ }));
192
+ ```
193
+ Evidence: an event-driven daemon (`GET /events`) — Hono SSE with heartbeat + `EventEmitter` fan-out.
194
+
195
+ ## Health Check Response Schema
196
+ - **Liveness** (`GET /health`): `{ status: "ok", uptime, version }` — HTTP 200, no external calls.
197
+ - **Readiness** (`GET /health/ready`): `{ status: "ok"|"degraded"|"unhealthy", checks: { database, redis, ... } }` — 2s timeout per check, 503 if critical check fails.
198
+ - **Liveness alias** (`GET /health/live`): `{ status: "ok" }` — Kubernetes convention.
199
+ - **Detailed** (`GET /health/detailed`): Full diagnostics (API-key protected).
200
+ - All health endpoints excluded from rate limiting, auth, and access logging. Use `createHealthRouter()` from `templates/shared/src/health.ts.template`.
201
+
202
+ ## Retry with Exponential Backoff
203
+ - Config: 3 attempts, base 1s, max 30s, jitter enabled. Formula: `min(base * 2^attempt + random(0, base), max)`.
204
+ - Only retry transient errors (5xx, network timeouts, ECONNRESET). Never retry 4xx.
205
+ - Circuit breaker: 5 consecutive failures in 60s → open for 30s → return 503.
206
+ - Log every retry attempt with attempt number, delay, and error reason.
207
+ - Implement as a generic `withRetry<T>(fn, opts)` wrapper. See `@your-org/http-client` for `fetchWithRetry()`.
208
+
209
+ ## API Response Shapes
210
+ Uses the canonical envelope from the [Canonical API Response Envelope](#canonical-api-response-envelope-sec-009) section above.
211
+ - **List variant:** `{ success: true, data: T[], count: number }` — always include total count for pagination.
212
+ - **Status codes:** 200 (success), 201 (created), 204 (deleted, no body), 400/401/403/404/409/429/500 per standard codes above.
213
+
214
+ ## API Design Patterns
215
+
216
+ ### Pagination (Cursor-based)
217
+ - Use `?cursor=<opaque_id>&limit=20`. Return `{ data: T[], nextCursor: string | null, hasMore: boolean }`.
218
+ - Default limit: 20, max: 100. Cursor = opaque base64-encoded `id` or `created_at`. Never use offset pagination for large datasets.
219
+
220
+ ### Versioning
221
+ - URL prefix: `/api/v1/`, `/api/v2/`. Max 2 concurrent versions. Deprecate with `Sunset` header.
222
+ - Breaking changes (removed fields, renamed endpoints) → new version. Non-breaking → current version.
223
+
224
+ ### Filtering & Sorting
225
+ - Convention: `?filter[status]=active&sort=-created_at&limit=20`. `-` prefix for descending.
226
+ - Validate all filter/sort fields against an allowlist. Reject unknown fields with 400.
227
+
228
+ ## Error Handling Patterns
229
+ - Use typed error classes: base `AppError(statusCode, message, code)` with subclasses like `NotFoundError`, `ValidationError`.
230
+ - Distinguish operational errors (expected: 4xx, recoverable) from programmer errors (unexpected: 5xx).
231
+ - Express: centralize in a single `(err, req, res, next)` handler mapping `AppError` subclasses to responses.
232
+ - Next.js Server Actions: try/catch → return canonical error envelope. Never throw (triggers error boundary).
233
+
234
+ ## External API Integration
235
+ - User-supplied URLs: `safeFetch()`/`safeFetchJSON()` from `@your-org/http-client` (SEC-014). Trusted URLs: `fetchWithTimeout()`/`fetchWithRetry()`.
236
+ - **Error classification:** Use `classifyError()` from `@your-org/http-client/errors` to convert raw fetch errors into typed classes (`NetworkError`, `TimeoutError`, `HttpError`, `ValidationError`, `SSRFBlockedError`). Check `error.isRetryable()` for retry decisions.
237
+ - Wrap in service classes. Apply retry + circuit breaker (see sections above). Timeout: 30s default.
238
+ - Log request/response (minus sensitive data) for debugging.
239
+
240
+ ## API Documentation
241
+ - Generate OpenAPI 3.1 specs from Zod schemas using `@asteasolutions/zod-to-openapi`.
242
+ - Use the helpers from `@your-org/zod-schemas/openapi`: `createOpenAPIRegistry()`, `registerSchema()`, `generateOpenAPIDocument()`.
243
+ - Register every request/response Zod schema in the OpenAPI registry. This ensures the spec stays in sync with validation logic.
244
+ - Serve the spec at `GET /api/docs/openapi.json` (raw JSON) and `GET /api/docs` (Scalar UI via `@scalar/express-api-reference`).
245
+ - Reuse canonical envelope schemas (`ApiErrorSchema`, `apiSuccessSchema`) in route registrations.
246
+ - Register routes via `registry.registerPath()` with method, path, request, and response schemas.
247
+ - Keep the registry setup co-located with route definitions or in a dedicated `src/routes/docs.ts` module.
248
+ - See `templates/express-service/src/routes/docs.ts.template` for reference implementation.
249
+
250
+ ## Distributed Tracing (OpenTelemetry)
251
+ - Use OpenTelemetry SDK with OTLP exporter for all backend services. Express: `src/lib/tracing.ts` (import first, before express). Next.js: `src/instrumentation.ts` (`register()` hook).
252
+ - Environment variables: `OTEL_SERVICE_NAME` (default: package name), `OTEL_EXPORTER_OTLP_ENDPOINT` (default: `http://localhost:4318`), `OTEL_ENABLED` (default: false in dev, true in prod).
253
+ - Auto-instrument HTTP, Express, and database clients. Disable `fs` instrumentation to reduce noise. Skip `/health` and `/metrics` from traces.
254
+ - Span naming: `HTTP ${method} ${route}` for HTTP spans, `${db.system} ${operation}` for DB spans, `${service}.${method}` for custom spans. Use normalized routes (`:id` not UUIDs) to prevent high cardinality.
255
+ - Add custom spans for: external API calls, database transactions, message queue operations, and any operation >100ms. Use `tracer.startActiveSpan()` with `span.end()` in `finally`.
256
+ - Inject `traceId` into Pino log bindings for log-trace correlation. Use `trace-context` middleware to expose `req.traceId`.
257
+ - Call `shutdown()` during graceful shutdown to flush pending spans before process exit.
258
+ - Backend: Grafana Tempo. See the baseline `infrastructure` rules § Tracing Backend (not vendored into this plugin).
259
+
260
+ ## Bounded Ring-Buffer for Admin Observability
261
+ - Fixed-capacity FIFO ring buffer of recent backend events (exits, errors, rate-limit hits, quota exhaustion) exposed via an authenticated admin endpoint. In-memory only — **zero DB overhead**, intended for rapid diagnosis between scrapes.
262
+ - **When to use:** gateway / proxy / worker services that need to answer "what just happened?" without adding a logs table or waiting for the next Prometheus scrape. Not a replacement for metrics or logs; a complement for operator triage.
263
+ - **Size guidance:** 50 entries minimum (useful diagnostic depth), 1000 entries maximum (memory bound). Default to `200` unless service-specific tuning applies. Per-entry payload stays small — event type, timestamp, `backendId`/`handlerId`, classification code, optional error summary string (≤256 chars). No stack traces, no request bodies.
264
+ - **TTL:** default `30min`. Entries older than TTL are dropped on read (lazy eviction) even if the ring has capacity — prevents stale data dominating the buffer during low-traffic periods.
265
+ - **Endpoint:** `GET /admin/backend-status` with filters (`backend`, `classification`, `since`, `limit`). **Admin-only** — must sit behind the same auth boundary as `/health/detailed`. Never expose on the public base path.
266
+ - **Code outline:**
267
+ ```ts
268
+ interface RingEntry<T> { ts: number; payload: T }
269
+ class RingBuffer<T> {
270
+ private buf: RingEntry<T>[] = [];
271
+ constructor(private size: number, private ttlMs: number) {}
272
+ push(payload: T) {
273
+ this.buf.push({ ts: Date.now(), payload });
274
+ if (this.buf.length > this.size) this.buf.shift();
275
+ }
276
+ read(filter?: (p: T) => boolean, limit = 100): RingEntry<T>[] {
277
+ const cutoff = Date.now() - this.ttlMs;
278
+ return this.buf
279
+ .filter(e => e.ts >= cutoff && (!filter || filter(e.payload)))
280
+ .slice(-limit);
281
+ }
282
+ }
283
+ ```
284
+ - **Evidence:** an internal LLM proxy service (`src/backends/exit-log.ts` + `src/routes/admin.ts` L144–231). An equivalent `BoundedMap` FIFO pattern is used by other services for event buses (50–1000 entries).
285
+ - **Reusable helper:** candidate for `@your-org/http-client` or a dedicated `@your-org/ringbuffer` package if demand grows past 2 consumer repos.
286
+
287
+ ## Feature Flags
288
+ - Use environment-variable-backed typed flags as default (see `docs/feature-flags.md`).
289
+ - Naming convention: `FF_<FEATURE_NAME>` in `.env`.
290
+ - Every flag must have an expiry date. Remove within 30 days of full rollout.
291
+
292
+ ## AI Provider Abstraction
293
+
294
+ ### Rule: No Direct Provider SDK in Business Logic
295
+ - NEVER import `@anthropic-ai/sdk`, `openai`, `@google/generative-ai`, or other provider SDKs directly in business logic (`src/app/`, `src/routes/`, `src/services/`).
296
+ - Use the **Vercel AI SDK** (`ai` package) as the unified abstraction layer. It provides `generateText()`, `streamText()`, `generateObject()` with provider-agnostic APIs.
297
+ - Route all LLM calls through the centralized LLM proxy for usage tracking, rate limiting, and credential management.
298
+
299
+ ### Allowed Import Locations
300
+ - `src/lib/ai/` — AI client setup, model configuration, provider initialization
301
+ - `src/providers/` — Custom provider adapters (e.g., local model integration)
302
+ - `tests/` — Test files may import SDKs directly for mocking
303
+
304
+ ### Environment Configuration
305
+ ```
306
+ AI_GATEWAY_URL=https://<your-gateway-host> # Centralized proxy
307
+ AI_GATEWAY_TOKEN=<from env> # Auth token
308
+ AI_DEFAULT_MODEL=claude-sonnet-4-20250514 # Default model
309
+ AI_FALLBACK_PROVIDER=openrouter # Fallback when primary unavailable
310
+ ```
311
+
312
+ ### Pattern: AI Client Factory
313
+ ```typescript
314
+ // src/lib/ai/client.ts — single point of AI configuration
315
+ import { createAnthropic } from '@ai-sdk/anthropic';
316
+ import { generateText } from 'ai';
317
+
318
+ const provider = createAnthropic({
319
+ baseURL: process.env.AI_GATEWAY_URL,
320
+ apiKey: process.env.AI_GATEWAY_TOKEN,
321
+ });
322
+
323
+ export async function askAI(prompt: string, options?: { model?: string; maxTokens?: number }) {
324
+ return generateText({
325
+ model: provider(options?.model ?? process.env.AI_DEFAULT_MODEL ?? 'claude-sonnet-4-20250514'),
326
+ prompt,
327
+ maxTokens: options?.maxTokens ?? 4096,
328
+ });
329
+ }
330
+ ```
331
+
332
+ ### Anti-Patterns
333
+ - Importing `@anthropic-ai/sdk` in a route handler or server action — use `askAI()` from `src/lib/ai/`.
334
+ - Hardcoding model names in business logic — use environment variables or the client factory.
335
+ - Calling LLM APIs without going through the centralized LLM proxy — breaks usage tracking and rate limiting.
336
+ - Creating multiple provider instances — use a single shared client from `src/lib/ai/client.ts`.
337
+
338
+ ## AI Observability
339
+
340
+ **Token Tracking**
341
+ - Wrap every LLM call with token tracking. Two patterns:
342
+ - Vercel AI SDK: use `onFinish` callback on `generateText()`/`streamText()` — extracts `usage.promptTokens`, `usage.completionTokens`
343
+ - Anthropic SDK direct: read `response.usage.input_tokens`, `response.usage.output_tokens`
344
+ - Log to `ai_usage_log` table (see Supabase migration template)
345
+ - Include: `userId`, `feature` (which app feature triggered the call), `model`, `provider`, `tokensInput`, `tokensOutput`, `costUsd`, `durationMs`, `finishReason`
346
+ - Validate log entries with `aiUsageLogSchema` from `@your-org/zod-schemas`
347
+
348
+ **OTel Span Attributes**
349
+ - Every LLM call MUST create an OTel span with these attributes (following OpenTelemetry Semantic Conventions for GenAI):
350
+ - `gen_ai.system`: provider name (anthropic, openai, etc.)
351
+ - `gen_ai.request.model`: model identifier
352
+ - `gen_ai.response.model`: actual model used (may differ from request)
353
+ - `gen_ai.usage.input_tokens`: prompt token count
354
+ - `gen_ai.usage.output_tokens`: completion token count
355
+ - `gen_ai.response.finish_reasons`: array of finish reasons
356
+ - Custom: `ai.cost.usd` (calculated cost), `ai.feature` (app feature), `ai.duration_ms`
357
+ - Span name: `gen_ai.{operation}` (e.g., `gen_ai.generate`, `gen_ai.stream`)
358
+ - Set span status to ERROR on LLM failures (rate limit, context length exceeded, model overloaded)
359
+
360
+ **Cost Attribution**
361
+ - Calculate cost per call: `(tokensInput * inputPrice + tokensOutput * outputPrice)` using model pricing lookup
362
+ - Maintain a pricing table (env var or config): model → price per 1K input/output tokens
363
+ - Aggregate in `ai_usage_daily` materialized view: per-user, per-feature, per-model daily rollups
364
+ - Dashboard query pattern: `SELECT feature, SUM(cost_usd) FROM ai_usage_log WHERE created_at >= now() - interval '30 days' GROUP BY feature ORDER BY 2 DESC`
365
+
366
+ **Budget Enforcement**
367
+ - Middleware pattern: check `ai_budget_config` table before every LLM call
368
+ - Two limit types: `dailyLimitUsd` and `monthlyLimitUsd`
369
+ - Soft limit (alert at `alertThresholdPct`): log warning + Discord notification via Clank webhook
370
+ - Hard limit (`hardLimit: true`): return 429 with `{ code: 'AI_BUDGET_EXCEEDED', message: 'AI-Budget ueberschritten' }` using canonical error envelope
371
+ - Override: admin endpoint to temporarily increase limits
372
+ - Validate config with `aiBudgetConfigSchema` from `@your-org/zod-schemas`
373
+
374
+ **Error Codes for AI Failures**
375
+ - `AI_RATE_LIMITED` (429): provider rate limit hit → retry with exponential backoff
376
+ - `AI_CONTEXT_LENGTH` (400): input too long → truncate or summarize
377
+ - `AI_MODEL_OVERLOADED` (503): model unavailable → fall back to `AI_FALLBACK_PROVIDER`
378
+ - `AI_BUDGET_EXCEEDED` (429): budget limit hit → block request, notify admin
379
+ - `AI_CONTENT_FILTERED` (400): content policy violation → return safe error message
380
+ - Map all to canonical `ApiError` envelope. Never expose raw provider errors to client.
381
+
382
+ **Anti-Patterns**
383
+ - Calling LLM APIs without token tracking — all calls must be logged
384
+ - Hardcoding model pricing — use config-driven lookup table
385
+ - Skipping OTel spans for "quick" AI calls — every call needs observability
386
+ - Returning raw provider error messages to client (exposes internal details)
387
+ - Checking budget after the LLM call (check before, enforce before spending)
388
+
389
+ ## See Also
390
+ development.md · security.md · security-web.md · testing.md · frontend.md · backend-data.md · swift.md · mvp-scope.md · cli-design.md · parallel-sessions.md
@@ -0,0 +1,98 @@
1
+ <!-- source: session-orchestrator plugin (canonical: rules/opt-in-stack/frontend.md) -->
2
+ ---
3
+ globs:
4
+ - src/**/*.tsx
5
+ - src/**/*.css
6
+ - src/**/*.module.css
7
+ - "**/components/**/*.{ts,tsx}"
8
+ tier: wave-only
9
+ ---
10
+ # Frontend Rules (Path-scoped)
11
+
12
+ ## React & Next.js
13
+
14
+ - Use Server Components by default. Add `"use client"` only when state, effects, or browser APIs are required.
15
+ - Co-locate component styles using CSS Modules (`*.module.css`). Never use global class names for component-scoped styles.
16
+ - File naming: PascalCase for component files (`UserCard.tsx`), kebab-case for utility files (`format-date.ts`).
17
+ - One component per file. Export named, not default, unless the file is a Next.js page/layout.
18
+ - Never import server-only modules (`fs`, `crypto`, `database`) in client components.
19
+ - `next.config` `redirects()` with identical `source` and `destination` does NOT short-circuit — it emits a real 307 and loops to `ERR_TOO_MANY_REDIRECTS`. Exclude the matched path with a negative-lookahead in `source` (e.g. `/admin/:path((?!auth(?:/.*)?$).*)`), and validate every rule with `path-to-regexp` (Next.js' own routing lib) before shipping.
20
+
21
+ ## Component Design
22
+
23
+ - Prefer composition over props drilling. Use Context or Zustand for shared state that spans more than 2 component levels.
24
+ - Keep components small and focused. If a component renders more than ~150 lines, extract sub-components.
25
+ - Separate data-fetching from presentation: fetch in Server Components or custom hooks, render in presentation components.
26
+ - Avoid `useEffect` for data fetching — use Server Components or SWR/React Query.
27
+ - Shared/reusable components MUST explicitly accept and forward `data-testid` (and spread rest props) to their root element. A closed prop list silently drops it — the testid never reaches the DOM, yet mock-based unit tests stay green over a broken product (test-the-mock; see `testing.md`).
28
+
29
+ ## Styling
30
+
31
+ - Tailwind CSS for utility classes. CSS Modules for component-scoped styles that would require many utility classes.
32
+ - Never use `!important`. If needed, refactor the specificity instead.
33
+ - Dark mode: use the `dark:` Tailwind variant. Never hardcode `#000` / `#fff` — use semantic tokens.
34
+ - Responsive design: mobile-first. Base styles target mobile, `md:` and `lg:` progressively enhance.
35
+ <!-- rule:pure-black-ink -->
36
+ - Never pure black text (`color:#000` / `black` / `rgb(0,0,0)`). Tint toward the brand hue (very dark, slightly-hued ink) — pure black reads harsh on screen.
37
+
38
+ ## Accessibility
39
+
40
+ - Every interactive element must be keyboard-accessible and have an accessible label.
41
+ - Use semantic HTML elements (`<button>`, `<nav>`, `<main>`, `<header>`) over generic `<div>` with ARIA roles.
42
+ - Images: always include `alt` text. Decorative images use `alt=""`.
43
+ - Colour contrast: minimum WCAG 2.1 AA (4.5:1 for normal text, 3:1 for large text).
44
+ - Test with VoiceOver (macOS/iOS) or NVDA (Windows) for screen-reader flows.
45
+
46
+ ## Performance
47
+
48
+ - Lazy-load below-the-fold components with `next/dynamic` (`{ loading: () => <Skeleton /> }`).
49
+ - Optimise images with `next/image`. Never use raw `<img>` for content images.
50
+ - Avoid large bundle additions: check `next build` output and `@next/bundle-analyzer` before merging heavy dependencies.
51
+ - Prefer server-side data fetching (React Server Components) over client-side fetches to reduce waterfall round-trips.
52
+
53
+ ## Forms
54
+
55
+ - Use `react-hook-form` + Zod resolver for all forms with validation.
56
+ - Bind Server Actions with `useTransition` + `startTransition` for progressive enhancement.
57
+ - Show field-level validation errors inline. Never show raw Zod error strings to users.
58
+ - Disable the submit button while `isPending` to prevent double-submission.
59
+
60
+ ## Next.js Server Actions
61
+
62
+ - After a `useActionState` action, do NOT call `router.refresh()` — it REPLAYS the action (duplicate DB writes + a re-fired success effect that bounces the redirect). The action's `revalidatePath` already handles freshness; guard the success effect with a `useRef` idempotency flag.
63
+ - Never call `router.push()` INSIDE `startTransition` — `isPending` stays true until navigation AND all server revalidations settle, so the submit button hangs under load. Capture a success flag inside the transition, then navigate from a SEPARATE `useEffect` guarded by a `hasNavigatedRef`.
64
+ - These bugs surface only in live (local-Docker) E2E — unit tests and static review pass them green. Smoke the create/edit flow against a running server before claiming done.
65
+
66
+ ## Anti-Patterns
67
+
68
+ - `useEffect` for business logic — move to event handlers or server actions.
69
+ - Passing raw `any` typed props — always declare typed interfaces.
70
+ - Nesting Server and Client Components incorrectly — read the Next.js docs on composition patterns.
71
+ - `dangerouslySetInnerHTML` without DOMPurify sanitization.
72
+ - `eslint-disable-next-line react-hooks/exhaustive-deps` — under the React Compiler it triggers a `react-compiler/react-compiler` warning that blocks commits at `max-warnings 0`. Restructure (drop the `useEffect`, or include all deps) instead of disabling.
73
+
74
+ ## Absolute Bans
75
+
76
+ <!-- rule:gradient-text -->
77
+ - Never gradient text (`background-clip:text` + gradient, or Tailwind `bg-clip-text`). Decorative, never meaningful — use a solid color; carry emphasis with weight/size.
78
+ <!-- rule:side-stripe-border -->
79
+ - Never a side-stripe accent border (colored `border-left/right` ≥ 2px, incl. `border-l-4`). Use full borders, a background tint, a leading icon/number, or nothing.
80
+ <!-- rule:overused-font -->
81
+ - Avoid overused primary fonts (Inter / Roboto / Arial / Helvetica as the FIRST family). Pick a font with a point of view; keep these only as deeper fallbacks. (also referenced by development.md)
82
+ <!-- rule:ai-purple-gradient -->
83
+ - No purple/indigo "AI" gradient (purple→blue ramp or two-purple gradient) — the single most recognizable AI tell. If purple is genuinely the brand, keep it flat; else pick a committed strategy. (fpRisk: high — brand-purple is the honest exception.)
84
+
85
+ ## Motion
86
+
87
+ <!-- rule:bounce-easing -->
88
+ - No bounce/elastic/overshoot easing (`bounce`/`elastic`/`spring` keywords, or `cubic-bezier` with a control point > 1 or < 0). Ease out with exponential curves (ease-out-quart/quint/expo).
89
+ <!-- rule:layout-property-transition -->
90
+ - Don't animate layout properties (`width`/`height`/`top`/`margin`/`padding` in a `transition`). Animate `transform`/`opacity` instead — layout animation thrashes the main thread.
91
+
92
+ ## Layout
93
+
94
+ <!-- rule:arbitrary-z-index -->
95
+ - No arbitrary z-index (`z-index: 999 / 9999`). Build a semantic z-index scale (dropdown → sticky → modal → toast → tooltip); never magic numbers.
96
+
97
+ ## See Also
98
+ development.md · security.md · security-web.md · testing.md · backend.md · backend-data.md · mvp-scope.md · parallel-sessions.md