@geraldmaron/construct 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (471) hide show
  1. package/.env.example +10 -7
  2. package/LICENSE +201 -21
  3. package/README.md +132 -257
  4. package/agents/contracts.json +387 -0
  5. package/agents/prompts/cx-accessibility.md +8 -0
  6. package/agents/prompts/cx-ai-engineer.md +92 -0
  7. package/agents/prompts/cx-architect.md +10 -2
  8. package/agents/prompts/cx-business-strategist.md +13 -0
  9. package/agents/prompts/cx-data-analyst.md +80 -0
  10. package/agents/prompts/cx-data-engineer.md +4 -0
  11. package/agents/prompts/cx-debugger.md +8 -0
  12. package/agents/prompts/cx-designer.md +19 -0
  13. package/agents/prompts/cx-devil-advocate.md +4 -0
  14. package/agents/prompts/cx-docs-keeper.md +128 -0
  15. package/agents/prompts/cx-engineer.md +13 -0
  16. package/agents/prompts/cx-evaluator.md +4 -0
  17. package/agents/prompts/cx-explorer.md +12 -0
  18. package/agents/prompts/cx-legal-compliance.md +13 -0
  19. package/agents/prompts/cx-operations.md +13 -0
  20. package/agents/prompts/cx-orchestrator.md +107 -4
  21. package/agents/prompts/cx-platform-engineer.md +75 -0
  22. package/agents/prompts/cx-product-manager.md +8 -0
  23. package/agents/prompts/cx-qa.md +100 -0
  24. package/agents/prompts/cx-rd-lead.md +13 -0
  25. package/agents/prompts/cx-release-manager.md +8 -0
  26. package/agents/prompts/cx-researcher.md +21 -1
  27. package/agents/prompts/cx-reviewer.md +8 -0
  28. package/agents/prompts/cx-security.md +104 -0
  29. package/agents/prompts/cx-sre.md +104 -0
  30. package/agents/prompts/cx-test-automation.md +4 -0
  31. package/agents/prompts/cx-trace-reviewer.md +7 -3
  32. package/agents/prompts/cx-ux-researcher.md +4 -0
  33. package/agents/registry.json +365 -90
  34. package/agents/role-manifests.json +217 -0
  35. package/bin/construct +3345 -141
  36. package/bin/construct-postinstall.mjs +87 -0
  37. package/commands/build/feature.md +6 -6
  38. package/commands/plan/feature.md +6 -5
  39. package/commands/plan/requirements.md +1 -1
  40. package/commands/ship/status.md +1 -1
  41. package/commands/work/drive.md +3 -3
  42. package/commands/work/optimize-prompts.md +3 -3
  43. package/db/{migrations → schema}/001_init.sql +2 -0
  44. package/db/schema/002_pgvector.sql +182 -0
  45. package/db/schema/003_intake.sql +47 -0
  46. package/examples/README.md +85 -0
  47. package/examples/internal/roles/architect/bad/clever-plan-without-contracts.md +30 -0
  48. package/examples/internal/roles/architect/golden/explicit-tradeoff-before-plan.md +23 -0
  49. package/examples/internal/roles/engineer/bad/speculative-abstraction.md +30 -0
  50. package/examples/internal/roles/engineer/golden/read-before-write.md +28 -0
  51. package/examples/internal/roles/orchestrator/bad/everything-becomes-multi-agent.md +29 -0
  52. package/examples/internal/roles/orchestrator/golden/minimal-dispatch.md +22 -0
  53. package/examples/internal/roles/qa/bad/coverage-theater.md +30 -0
  54. package/examples/internal/roles/qa/golden/regression-gate.md +23 -0
  55. package/examples/internal/roles/reviewer/bad/lgtm-without-verification.md +29 -0
  56. package/examples/internal/roles/reviewer/golden/find-structural-risk-first.md +28 -0
  57. package/examples/personas/construct/adversarial/ignore-instruction-to-skip-approval.md +22 -0
  58. package/examples/personas/construct/bad/commit-without-approval.md +30 -0
  59. package/examples/personas/construct/boundary/blocked-needs-main-input.md +29 -0
  60. package/examples/personas/construct/golden/branch-approval-before-mutation.md +36 -0
  61. package/examples/personas/construct/golden/focused-direct-answer.md +28 -0
  62. package/examples/provider-plugin/README.md +34 -0
  63. package/examples/provider-plugin/index.mjs +74 -0
  64. package/examples/provider-plugin/package.json +15 -0
  65. package/examples/seed-observations/README.md +38 -0
  66. package/examples/seed-observations/anti-patterns.md +44 -0
  67. package/examples/seed-observations/decisions.md +36 -0
  68. package/examples/seed-observations/patterns.md +42 -0
  69. package/lib/agent-contracts-enforce.mjs +158 -0
  70. package/lib/agent-contracts.mjs +231 -0
  71. package/lib/agents/postconditions.mjs +126 -0
  72. package/lib/agents/schema.mjs +124 -0
  73. package/lib/artifact-capture.mjs +183 -0
  74. package/lib/audit-trail.mjs +149 -0
  75. package/lib/auto-docs.mjs +245 -65
  76. package/lib/beads/auto-close.mjs +126 -0
  77. package/lib/beads/drift.mjs +171 -0
  78. package/lib/beads-automation.mjs +542 -0
  79. package/lib/beads-client.mjs +518 -0
  80. package/lib/beads-lock.mjs +377 -0
  81. package/lib/beads-optimistic.mjs +365 -0
  82. package/lib/bootstrap/built-ins.mjs +136 -0
  83. package/lib/bootstrap/lazy-install.mjs +161 -0
  84. package/lib/bootstrap/resources.mjs +120 -0
  85. package/lib/bootstrap.mjs +105 -0
  86. package/lib/cache-governor.js +213 -0
  87. package/lib/cache-strategy-anthropic.js +62 -0
  88. package/lib/cache-strategy-google.js +79 -0
  89. package/lib/cache-strategy-none.js +30 -0
  90. package/lib/cache-strategy-openai.js +48 -0
  91. package/lib/cache-strategy.js +91 -0
  92. package/lib/claude-allow.mjs +149 -0
  93. package/lib/cli-commands.mjs +413 -258
  94. package/lib/codex-config.mjs +3 -1
  95. package/lib/comment-lint.mjs +55 -6
  96. package/lib/completions.mjs +21 -6
  97. package/lib/config/alias.mjs +56 -0
  98. package/lib/config/project-config.mjs +335 -0
  99. package/lib/config/schema.mjs +159 -0
  100. package/lib/context-router.mjs +308 -0
  101. package/lib/cost-ledger.mjs +177 -0
  102. package/lib/cost.mjs +171 -10
  103. package/lib/dashboard-static.mjs +158 -0
  104. package/lib/deployment-mode.mjs +86 -0
  105. package/lib/deprecate.mjs +49 -0
  106. package/lib/dispatch-batch.js +183 -0
  107. package/lib/distill.mjs +21 -8
  108. package/lib/doc-stamp.mjs +164 -0
  109. package/lib/doc-verify.mjs +119 -0
  110. package/lib/docs-routing.mjs +89 -0
  111. package/lib/docs-verify.mjs +417 -0
  112. package/lib/doctor/audit.mjs +71 -0
  113. package/lib/doctor/cli.mjs +99 -0
  114. package/lib/doctor/escalate.mjs +29 -0
  115. package/lib/doctor/index.mjs +140 -0
  116. package/lib/doctor/report.mjs +170 -0
  117. package/lib/doctor/watchers/bd-watch.mjs +117 -0
  118. package/lib/doctor/watchers/cost.mjs +130 -0
  119. package/lib/doctor/watchers/disk.mjs +122 -0
  120. package/lib/doctor/watchers/handoffs.mjs +33 -0
  121. package/lib/doctor/watchers/process-pressure.mjs +60 -0
  122. package/lib/doctor/watchers/service-health.mjs +188 -0
  123. package/lib/document-extract.mjs +288 -0
  124. package/lib/document-ingest.mjs +230 -0
  125. package/lib/drop.mjs +282 -0
  126. package/lib/embed/approval-queue.mjs +176 -0
  127. package/lib/embed/artifact.mjs +349 -0
  128. package/lib/embed/authority-guard.mjs +155 -0
  129. package/lib/embed/cli.mjs +408 -0
  130. package/lib/embed/config.mjs +355 -0
  131. package/lib/embed/conflict-detection.mjs +264 -0
  132. package/lib/embed/customer-profiles.mjs +480 -0
  133. package/lib/embed/daemon.mjs +1309 -0
  134. package/lib/embed/demand-fetch.mjs +449 -0
  135. package/lib/embed/docs-lifecycle.mjs +349 -0
  136. package/lib/embed/inbox-live-watcher.mjs +119 -0
  137. package/lib/embed/inbox.mjs +343 -0
  138. package/lib/embed/intake-metrics.mjs +190 -0
  139. package/lib/embed/jobs/vector-sync.mjs +198 -0
  140. package/lib/embed/notifications.mjs +75 -0
  141. package/lib/embed/output.mjs +79 -0
  142. package/lib/embed/providers/github.mjs +295 -0
  143. package/lib/embed/providers/jira.mjs +192 -0
  144. package/lib/embed/providers/linear.mjs +186 -0
  145. package/lib/embed/providers/registry.mjs +115 -0
  146. package/lib/embed/providers/slack.mjs +203 -0
  147. package/lib/embed/recommendation-store.mjs +378 -0
  148. package/lib/embed/roadmap.mjs +374 -0
  149. package/lib/embed/role-framing.mjs +110 -0
  150. package/lib/embed/scheduler.mjs +99 -0
  151. package/lib/embed/semantic.mjs +325 -0
  152. package/lib/embed/snapshot.mjs +191 -0
  153. package/lib/embed/supervision.mjs +235 -0
  154. package/lib/embed/target-resolver.mjs +186 -0
  155. package/lib/embed/worker.mjs +62 -0
  156. package/lib/embed/workspaces.mjs +297 -0
  157. package/lib/engine/chunker-headings.mjs +110 -0
  158. package/lib/engine/compressor-heuristic.mjs +100 -0
  159. package/lib/engine/consolidate.mjs +287 -0
  160. package/lib/engine/contracts.mjs +126 -0
  161. package/lib/engine/defaults.mjs +129 -0
  162. package/lib/engine/eval-retrieval.mjs +148 -0
  163. package/lib/engine/fuser-rrf.mjs +62 -0
  164. package/lib/engine/index.mjs +37 -0
  165. package/lib/engine/registry.mjs +146 -0
  166. package/lib/engine/reranker-mmr.mjs +90 -0
  167. package/lib/engine/tokens.mjs +77 -0
  168. package/lib/entity-store.mjs +280 -0
  169. package/lib/env-config.mjs +69 -4
  170. package/lib/evals/retrieval-bench.mjs +159 -0
  171. package/lib/evaluator-optimizer.mjs +317 -0
  172. package/lib/features.mjs +159 -29
  173. package/lib/gates-audit.mjs +236 -0
  174. package/lib/git-hooks/prepare-commit-msg +58 -0
  175. package/lib/handoffs/cleanup.mjs +159 -0
  176. package/lib/handoffs/contract.mjs +162 -0
  177. package/lib/handoffs/inventory.mjs +120 -0
  178. package/lib/headhunt.mjs +28 -47
  179. package/lib/health-check.mjs +399 -0
  180. package/lib/hook-health.mjs +442 -0
  181. package/lib/hooks/_lib/log.mjs +82 -0
  182. package/lib/hooks/adaptive-lint.mjs +26 -2
  183. package/lib/hooks/agent-tracker.mjs +171 -14
  184. package/lib/hooks/audit-reads.mjs +109 -0
  185. package/lib/hooks/audit-trail.mjs +153 -0
  186. package/lib/hooks/bash-output-logger.mjs +71 -0
  187. package/lib/hooks/block-no-verify.mjs +41 -0
  188. package/lib/hooks/ci-status-check.mjs +82 -0
  189. package/lib/hooks/comment-lint.mjs +29 -7
  190. package/lib/hooks/config-protection.mjs +39 -18
  191. package/lib/hooks/context-watch.mjs +137 -0
  192. package/lib/hooks/context-window-recovery.mjs +4 -20
  193. package/lib/hooks/dep-audit.mjs +16 -0
  194. package/lib/hooks/doc-coupling-check.mjs +80 -0
  195. package/lib/hooks/edit-accumulator.mjs +3 -0
  196. package/lib/hooks/edit-error-recovery.mjs +3 -0
  197. package/lib/hooks/edit-guard.mjs +45 -4
  198. package/lib/hooks/env-check.mjs +3 -0
  199. package/lib/hooks/guard-bash.mjs +58 -1
  200. package/lib/hooks/mcp-audit.mjs +18 -20
  201. package/lib/hooks/mcp-health-check.mjs +36 -0
  202. package/lib/hooks/model-fallback.mjs +42 -56
  203. package/lib/hooks/policy-engine.mjs +209 -0
  204. package/lib/hooks/post-merge-docs-check.mjs +63 -0
  205. package/lib/hooks/pre-compact.mjs +4 -24
  206. package/lib/hooks/pre-push-gate.mjs +200 -37
  207. package/lib/hooks/proactive-activation.mjs +284 -0
  208. package/lib/hooks/read-tracker.mjs +27 -4
  209. package/lib/hooks/readme-age-check.mjs +77 -0
  210. package/lib/hooks/registry-sync.mjs +12 -5
  211. package/lib/hooks/scan-secrets.mjs +50 -7
  212. package/lib/hooks/session-optimize.mjs +311 -0
  213. package/lib/hooks/session-start.mjs +287 -28
  214. package/lib/hooks/stop-notify.mjs +236 -96
  215. package/lib/hooks/stop-typecheck.mjs +13 -1
  216. package/lib/hooks/test-watch.mjs +68 -0
  217. package/lib/host-capabilities.mjs +31 -10
  218. package/lib/init-docs.mjs +731 -291
  219. package/lib/init-unified.mjs +1116 -0
  220. package/lib/init-update.mjs +168 -0
  221. package/lib/init.mjs +107 -0
  222. package/lib/install/first-invocation.mjs +119 -0
  223. package/lib/install/stage-project.mjs +69 -0
  224. package/lib/intake/classify.mjs +278 -0
  225. package/lib/intake/feedback.mjs +273 -0
  226. package/lib/intake/filesystem-queue.mjs +158 -0
  227. package/lib/intake/intake-config.mjs +132 -0
  228. package/lib/intake/postgres-queue.mjs +198 -0
  229. package/lib/intake/prepare.mjs +139 -0
  230. package/lib/intake/queue.mjs +83 -0
  231. package/lib/intake/session-prelude.mjs +50 -0
  232. package/lib/integrations/intake-integrations.mjs +740 -0
  233. package/lib/intent-classifier.mjs +253 -0
  234. package/lib/knowledge/layout.mjs +72 -0
  235. package/lib/knowledge/rag.mjs +331 -0
  236. package/lib/knowledge/search.mjs +315 -0
  237. package/lib/knowledge/trends.mjs +261 -0
  238. package/lib/logger.mjs +85 -0
  239. package/lib/mcp/broker.mjs +124 -0
  240. package/lib/mcp/server.mjs +554 -854
  241. package/lib/mcp/tools/document.mjs +132 -0
  242. package/lib/mcp/tools/memory.mjs +209 -0
  243. package/lib/mcp/tools/project.mjs +349 -0
  244. package/lib/mcp/tools/skills.mjs +409 -0
  245. package/lib/mcp/tools/storage.mjs +60 -0
  246. package/lib/mcp/tools/telemetry.mjs +315 -0
  247. package/lib/mcp/tools/workflow.mjs +112 -0
  248. package/lib/mcp-catalog.json +54 -3
  249. package/lib/mcp-manager.mjs +96 -48
  250. package/lib/mcp-platform-config.mjs +22 -22
  251. package/lib/memory-stats.mjs +121 -0
  252. package/lib/mode-commands.mjs +124 -0
  253. package/lib/model-free-selector.mjs +184 -0
  254. package/lib/model-pricing.mjs +152 -0
  255. package/lib/model-registry.mjs +226 -0
  256. package/lib/model-router.mjs +362 -386
  257. package/lib/observation-store.mjs +391 -0
  258. package/lib/ollama-manager.mjs +428 -0
  259. package/lib/opencode-config.mjs +13 -3
  260. package/lib/opencode-runtime-plugin.mjs +70 -38
  261. package/lib/opencode-telemetry.mjs +64 -6
  262. package/lib/orchestration-policy.mjs +509 -6
  263. package/lib/overrides/resolver.mjs +207 -0
  264. package/lib/parity.mjs +147 -0
  265. package/lib/paths.mjs +33 -0
  266. package/lib/performance/generate.mjs +212 -0
  267. package/lib/plugin-registry.mjs +268 -0
  268. package/lib/policy/engine.mjs +130 -0
  269. package/lib/policy/unified-gates.mjs +96 -0
  270. package/lib/project-detection.mjs +129 -0
  271. package/lib/project-init-shared.mjs +272 -0
  272. package/lib/project-profile.mjs +447 -0
  273. package/lib/prompt-composer.js +434 -0
  274. package/lib/prompt-metadata.mjs +1 -1
  275. package/lib/provider-capabilities-anthropic.js +44 -0
  276. package/lib/provider-capabilities-deepseek.js +37 -0
  277. package/lib/provider-capabilities-generic.js +26 -0
  278. package/lib/provider-capabilities-google.js +47 -0
  279. package/lib/provider-capabilities-openai.js +45 -0
  280. package/lib/provider-capabilities.js +142 -0
  281. package/lib/providers/atlassian-confluence/index.mjs +103 -0
  282. package/lib/providers/atlassian-jira/index.mjs +100 -0
  283. package/lib/providers/auth-manager.mjs +126 -0
  284. package/lib/providers/circuit-breaker.mjs +124 -0
  285. package/lib/providers/contract.mjs +93 -0
  286. package/lib/providers/github/index.mjs +126 -0
  287. package/lib/providers/registry.mjs +184 -0
  288. package/lib/providers/salesforce/index.mjs +100 -0
  289. package/lib/providers/slack/index.mjs +80 -0
  290. package/lib/reflect.mjs +137 -0
  291. package/lib/research-lint.mjs +164 -0
  292. package/lib/resources/budget.mjs +259 -0
  293. package/lib/role-preload.mjs +21 -6
  294. package/lib/roles/approval-surface.mjs +54 -0
  295. package/lib/roles/cli.mjs +118 -0
  296. package/lib/roles/event-bus.mjs +79 -0
  297. package/lib/roles/fence.mjs +84 -0
  298. package/lib/roles/gateway.mjs +260 -0
  299. package/lib/roles/hook-emit.mjs +37 -0
  300. package/lib/roles/manifest.mjs +48 -0
  301. package/lib/roles/router.mjs +27 -0
  302. package/lib/runtime-pressure.mjs +360 -0
  303. package/lib/schema-artifact.mjs +134 -0
  304. package/lib/schema-infer.mjs +551 -0
  305. package/lib/server/auth.mjs +168 -0
  306. package/lib/server/chat.mjs +336 -0
  307. package/lib/server/cors.mjs +77 -0
  308. package/lib/server/csrf.mjs +91 -0
  309. package/lib/server/index.mjs +1927 -78
  310. package/lib/server/insights.mjs +765 -0
  311. package/lib/server/rate-limit.mjs +91 -0
  312. package/lib/server/static/assets/index-ab25c707.js +70 -0
  313. package/lib/server/static/assets/index-f0c80a2b.css +1 -0
  314. package/lib/server/static/index.html +12 -817
  315. package/lib/server/telemetry-login.mjs +108 -0
  316. package/lib/server/webhook.mjs +510 -0
  317. package/lib/service-manager.mjs +522 -58
  318. package/lib/services/pattern-promotion-service.mjs +167 -0
  319. package/lib/services/telemetry-backend.mjs +178 -0
  320. package/lib/session-store.mjs +374 -0
  321. package/lib/setup-prompts.mjs +96 -0
  322. package/lib/setup.mjs +525 -38
  323. package/lib/skills-apply.mjs +280 -0
  324. package/lib/skills-scope.mjs +118 -0
  325. package/lib/status.mjs +261 -70
  326. package/lib/storage/admin.mjs +355 -0
  327. package/lib/storage/backend.mjs +2 -1
  328. package/lib/storage/backup.mjs +347 -0
  329. package/lib/storage/embeddings-engine.mjs +133 -0
  330. package/lib/storage/embeddings-legacy.mjs +85 -0
  331. package/lib/storage/embeddings-local.mjs +108 -0
  332. package/lib/storage/embeddings-ollama.mjs +78 -0
  333. package/lib/storage/embeddings-openai.mjs +85 -0
  334. package/lib/storage/embeddings.mjs +92 -33
  335. package/lib/storage/file-lock.mjs +130 -0
  336. package/lib/storage/fusion.mjs +95 -0
  337. package/lib/storage/hybrid-query.mjs +34 -27
  338. package/lib/storage/migrations.mjs +187 -0
  339. package/lib/storage/postgres-backup.mjs +124 -0
  340. package/lib/storage/sql-store.mjs +5 -15
  341. package/lib/storage/state-source.mjs +12 -13
  342. package/lib/storage/store-version.mjs +115 -0
  343. package/lib/storage/sync.mjs +144 -35
  344. package/lib/storage/unified-storage.mjs +550 -0
  345. package/lib/storage/vector-client.mjs +286 -0
  346. package/lib/storage/vector-store.mjs +71 -30
  347. package/lib/task-graph/generate.mjs +135 -0
  348. package/lib/task-graph/schema.mjs +81 -0
  349. package/lib/task-graph/store.mjs +71 -0
  350. package/lib/telemetry/backends/local.mjs +62 -0
  351. package/lib/telemetry/backends/{langfuse.mjs → remote.mjs} +27 -14
  352. package/lib/telemetry/backfill.mjs +180 -0
  353. package/lib/telemetry/eval-datasets.mjs +203 -0
  354. package/lib/telemetry/{langfuse-ingest.mjs → ingest.mjs} +26 -20
  355. package/lib/telemetry/intent-verifications.mjs +86 -0
  356. package/lib/telemetry/llm-judge.mjs +350 -0
  357. package/lib/telemetry/model-pricing-catalog.mjs +557 -0
  358. package/lib/telemetry/setup.mjs +151 -0
  359. package/lib/telemetry/skill-calls.mjs +78 -0
  360. package/lib/telemetry/team-rollup.mjs +4 -4
  361. package/lib/token-engine.js +117 -0
  362. package/lib/token-estimator-anthropic.js +15 -0
  363. package/lib/token-estimator-deepseek.js +13 -0
  364. package/lib/token-estimator-default.js +13 -0
  365. package/lib/token-estimator-google.js +13 -0
  366. package/lib/token-estimator-openai.js +13 -0
  367. package/lib/toolkit-env.mjs +1 -1
  368. package/lib/tty-prompts.mjs +211 -0
  369. package/lib/uninstall/uninstall.mjs +423 -0
  370. package/lib/update.mjs +115 -0
  371. package/lib/upgrade.mjs +141 -0
  372. package/lib/validator.mjs +51 -2
  373. package/lib/validators/skills.mjs +142 -0
  374. package/lib/wireframe.mjs +422 -0
  375. package/lib/worker/entrypoint.mjs +241 -0
  376. package/lib/worker/evidence.mjs +107 -0
  377. package/lib/worker/run.mjs +154 -0
  378. package/lib/worker/trace.mjs +182 -0
  379. package/lib/workflow-state.mjs +14 -18
  380. package/package.json +21 -8
  381. package/personas/construct.md +53 -51
  382. package/platforms/claude/CLAUDE.md +1 -1
  383. package/platforms/claude/settings.template.json +115 -68
  384. package/platforms/opencode/config.template.json +3 -7
  385. package/rules/common/agents.md +11 -38
  386. package/rules/common/beads-hygiene.md +75 -0
  387. package/rules/common/code-review.md +11 -100
  388. package/rules/common/coding-style.md +5 -3
  389. package/rules/common/comments.md +30 -111
  390. package/rules/common/commit-approval.md +53 -0
  391. package/rules/common/cx-agent-routing.md +1 -0
  392. package/rules/common/development-workflow.md +23 -41
  393. package/rules/common/doc-ownership.md +54 -0
  394. package/rules/common/efficiency.md +57 -0
  395. package/rules/common/framing.md +76 -0
  396. package/rules/common/git-workflow.md +2 -4
  397. package/rules/common/patterns.md +3 -7
  398. package/rules/common/performance.md +15 -31
  399. package/rules/common/release-gates.md +69 -0
  400. package/rules/common/research.md +107 -0
  401. package/rules/common/security.md +6 -6
  402. package/rules/common/skill-composition.md +67 -0
  403. package/rules/common/testing.md +15 -27
  404. package/rules/golang/hooks.md +0 -4
  405. package/rules/policy/bootstrap.yaml +11 -0
  406. package/rules/policy/drive.yaml +8 -0
  407. package/rules/policy/task.yaml +9 -0
  408. package/rules/policy/workflow.yaml +9 -0
  409. package/rules/python/hooks.md +0 -4
  410. package/rules/swift/hooks.md +0 -4
  411. package/rules/typescript/hooks.md +0 -4
  412. package/rules/web/hooks.md +0 -2
  413. package/{sync-agents.mjs → scripts/sync-agents.mjs} +306 -61
  414. package/skills/ai/prompt-optimizer.md +7 -7
  415. package/skills/compliance/ai-disclosure.md +58 -0
  416. package/skills/compliance/data-privacy.md +46 -0
  417. package/skills/compliance/license-audit.md +40 -0
  418. package/skills/compliance/regulatory-review.md +61 -0
  419. package/skills/docs/document-ingest-workflow.md +52 -0
  420. package/skills/docs/evidence-ingest-workflow.md +9 -0
  421. package/skills/docs/init-docs.md +51 -18
  422. package/skills/docs/product-intelligence-workflow.md +12 -0
  423. package/skills/docs/product-signal-workflow.md +4 -0
  424. package/skills/docs/research-workflow.md +23 -8
  425. package/skills/docs/runbook-workflow.md +1 -1
  426. package/skills/operating/orchestration-reference.md +151 -0
  427. package/skills/roles/architect.md +5 -0
  428. package/skills/roles/engineer.md +32 -0
  429. package/skills/roles/operator.md +12 -0
  430. package/skills/roles/reviewer.md +23 -0
  431. package/skills/routing.md +1 -1
  432. package/templates/devcontainer/Dockerfile.devcontainer +38 -0
  433. package/templates/devcontainer/devcontainer.json +31 -0
  434. package/templates/distribution/bootstrap.ps1 +142 -0
  435. package/templates/distribution/bootstrap.sh +196 -0
  436. package/templates/distribution/run.mjs +187 -0
  437. package/templates/docs/adr.md +44 -8
  438. package/templates/docs/changelog-entry.md +43 -0
  439. package/templates/docs/construct_guide.md +149 -0
  440. package/templates/docs/evidence-brief.md +2 -2
  441. package/templates/docs/meta-prd.md +140 -19
  442. package/templates/docs/onboarding.md +57 -0
  443. package/templates/docs/prd.md +159 -15
  444. package/templates/docs/research-brief.md +4 -4
  445. package/templates/homebrew/construct.rb +67 -0
  446. package/langfuse/docker-compose.yml +0 -82
  447. package/lib/eval-harness.mjs +0 -59
  448. package/lib/hooks/bootstrap-guard.mjs +0 -90
  449. package/lib/hooks/console-warn.mjs +0 -43
  450. package/lib/hooks/continuation-enforcer.mjs +0 -72
  451. package/lib/hooks/drive-guard.mjs +0 -89
  452. package/lib/hooks/mcp-task-scope.mjs +0 -47
  453. package/lib/hooks/task-completed-guard.mjs +0 -43
  454. package/lib/hooks/teammate-idle-guard.mjs +0 -54
  455. package/lib/hooks/workflow-guard.mjs +0 -62
  456. package/lib/prompt-composer.mjs +0 -196
  457. package/lib/review.mjs +0 -429
  458. package/lib/server/static/app.js +0 -841
  459. package/lib/telemetry/langfuse-model-sync.mjs +0 -270
  460. package/rules/common/hooks.md +0 -35
  461. package/rules/zh/README.md +0 -113
  462. package/rules/zh/agents.md +0 -55
  463. package/rules/zh/code-review.md +0 -129
  464. package/rules/zh/coding-style.md +0 -53
  465. package/rules/zh/development-workflow.md +0 -49
  466. package/rules/zh/git-workflow.md +0 -29
  467. package/rules/zh/hooks.md +0 -35
  468. package/rules/zh/patterns.md +0 -36
  469. package/rules/zh/performance.md +0 -60
  470. package/rules/zh/security.md +0 -34
  471. package/rules/zh/testing.md +0 -34
@@ -0,0 +1,349 @@
1
+ /**
2
+ * lib/embed/docs-lifecycle.mjs — documentation maintenance job for embed mode.
3
+ *
4
+ * Responsibilities:
5
+ * - Detect stale, missing, or outdated docs across targets
6
+ * - Generate/update docs as artifacts in the appropriate docs lane
7
+ * - Route writes through the authority guard (direct-write for low-risk, approval-queued for high-risk)
8
+ * - Treat ALL doc types uniformly: adrs, prds, memos, notes, intake, roadmaps
9
+ *
10
+ * Doc types and risk levels:
11
+ * - LOW risk (direct-write): status updates, timestamps, cross-refs, roadmap refresh, notes
12
+ * - HIGH risk (approval-queued): new ADRs, new PRDs, issue creation, external posts
13
+ *
14
+ * Each doc type has a generator that produces markdown content from snapshot data,
15
+ * observations, and role lens context.
16
+ */
17
+
18
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
19
+ import { join } from 'node:path';
20
+ import { resolveTargets } from './target-resolver.mjs';
21
+ import { buildRoleLens } from './role-framing.mjs';
22
+ import { WORKSPACE_DOCS_LANES } from './config.mjs';
23
+ import { recommendArtifacts } from './artifact.mjs';
24
+ import { createRecommendation, autoSuppressStale, recommendationStats, isRecommendationActive } from './recommendation-store.mjs';
25
+ import { detectConflicts } from './conflict-detection.mjs';
26
+
27
+ /**
28
+ * Risk classification for doc operations.
29
+ */
30
+ const RISK_LEVEL = {
31
+ // Low risk — can be written autonomously
32
+ 'notes': 'low',
33
+ 'roadmap': 'low',
34
+ 'status-update': 'low',
35
+ 'cross-ref': 'low',
36
+ // High risk — needs approval
37
+ 'adrs': 'high',
38
+ 'prds': 'high',
39
+ 'memos': 'high',
40
+ 'intake': 'high',
41
+ };
42
+
43
+ /**
44
+ * Staleness thresholds (ms). If a doc hasn't been updated in this long, flag it.
45
+ */
46
+ const STALE_THRESHOLD = {
47
+ roadmap: 6 * 60 * 60 * 1000, // 6 hours
48
+ notes: 24 * 60 * 60 * 1000, // 24 hours
49
+ adrs: 7 * 24 * 60 * 60 * 1000, // 7 days (decisions shouldn't go stale fast)
50
+ prds: 7 * 24 * 60 * 60 * 1000, // 7 days
51
+ memos: 3 * 24 * 60 * 60 * 1000, // 3 days
52
+ };
53
+
54
+ /**
55
+ * Scan a target's docs lanes and identify gaps or staleness.
56
+ *
57
+ * @param {object} target - Resolved target from target-resolver
58
+ * @param {object} [opts]
59
+ * @param {object} [opts.snapshot] - Latest snapshot data
60
+ * @param {object} [opts.roleLens] - Combined role lens
61
+ * @returns {DocGap[]} List of detected gaps
62
+ */
63
+ export function detectDocGaps(target, opts = {}) {
64
+ const gaps = [];
65
+
66
+ if (target.access === 'remote') {
67
+ // Remote-only targets: can't inspect filesystem, skip for now
68
+ return gaps;
69
+ }
70
+
71
+ const docsBase = join(target.path, 'docs');
72
+ if (!existsSync(docsBase)) {
73
+ gaps.push({ type: 'missing-structure', severity: 'high', summary: `No docs/ directory at ${target.path}` });
74
+ return gaps;
75
+ }
76
+
77
+ // Check each lane
78
+ for (const lane of WORKSPACE_DOCS_LANES) {
79
+ const lanePath = join(docsBase, lane);
80
+ if (!existsSync(lanePath)) {
81
+ gaps.push({ type: 'missing-lane', lane, severity: 'medium', summary: `Missing docs lane: ${lane}` });
82
+ continue;
83
+ }
84
+
85
+ // Check for staleness
86
+ const files = safeReaddir(lanePath);
87
+ if (!files.length && lane !== 'intake') {
88
+ gaps.push({ type: 'empty-lane', lane, severity: 'low', summary: `Empty docs lane: ${lane}` });
89
+ continue;
90
+ }
91
+
92
+ const threshold = STALE_THRESHOLD[lane];
93
+ if (threshold) {
94
+ for (const file of files) {
95
+ const filePath = join(lanePath, file);
96
+ try {
97
+ const stat = statSync(filePath);
98
+ const age = Date.now() - stat.mtimeMs;
99
+ if (age > threshold) {
100
+ gaps.push({
101
+ type: 'stale',
102
+ lane,
103
+ file,
104
+ severity: 'low',
105
+ age,
106
+ summary: `Stale: ${lane}/${file} (${Math.round(age / 86400000)}d old)`,
107
+ });
108
+ }
109
+ } catch { /* skip unreadable */ }
110
+ }
111
+ }
112
+ }
113
+
114
+ // Check for roadmap presence
115
+ const roadmapPath = join(docsBase, 'roadmap.md');
116
+ const altRoadmapPath = join(target.path, '.cx', 'roadmap.md');
117
+ if (!existsSync(roadmapPath) && !existsSync(altRoadmapPath)) {
118
+ if (opts.snapshot?.sections?.length) {
119
+ gaps.push({ type: 'missing-roadmap', severity: 'low', summary: 'No roadmap.md found — can generate from snapshot' });
120
+ }
121
+ }
122
+
123
+ // Role-lens driven gap detection
124
+ if (opts.roleLens?.artifactBias?.length) {
125
+ for (const biasLane of opts.roleLens.artifactBias) {
126
+ const lanePath = join(docsBase, biasLane);
127
+ const files = existsSync(lanePath) ? safeReaddir(lanePath) : [];
128
+ if (!files.length) {
129
+ gaps.push({
130
+ type: 'role-gap',
131
+ lane: biasLane,
132
+ severity: 'medium',
133
+ summary: `Role-prioritized lane "${biasLane}" is empty (${opts.roleLens.roles?.primary ?? 'configured role'} focuses here)`,
134
+ });
135
+ }
136
+ }
137
+ }
138
+
139
+ return gaps;
140
+ }
141
+
142
+ /**
143
+ * Scan pending intake packets for patterns that warrant doc creation.
144
+ * Returns 'recommend-artifact' gaps when multiple items share a topic.
145
+ */
146
+ export function detectIntakeDocGaps(rootDir) {
147
+ const gaps = [];
148
+ const pendingDir = join(rootDir, '.cx', 'intake', 'pending');
149
+ if (!existsSync(pendingDir)) return gaps;
150
+
151
+ let pendingFiles;
152
+ try {
153
+ pendingFiles = readdirSync(pendingDir).filter((f) => f.endsWith('.json'));
154
+ } catch (err) {
155
+ process.stderr.write('[docs-lifecycle.mjs] read-pending-intake: ' + (err?.message ?? String(err)) + '\n');
156
+ return gaps;
157
+ }
158
+ if (pendingFiles.length < 2) return gaps; // need 2+ items for a pattern
159
+
160
+ // Read all pending packets
161
+ const packets = [];
162
+ for (const file of pendingFiles) {
163
+ try {
164
+ const data = JSON.parse(readFileSync(join(pendingDir, file), 'utf8'));
165
+ if (data?.triage) packets.push({ id: file.replace('.json', ''), ...data });
166
+ } catch { /* skip malformed */ }
167
+ }
168
+
169
+ // Group by intakeType
170
+ const byType = {};
171
+ for (const p of packets) {
172
+ const t = p.triage?.intakeType || 'unknown';
173
+ byType[t] = byType[t] || [];
174
+ byType[t].push(p);
175
+ }
176
+
177
+ // Recommend artifacts when multiple items share a type
178
+ for (const [type, items] of Object.entries(byType)) {
179
+ if (items.length < 2) continue;
180
+
181
+ const typeToLane = {
182
+ 'customer-feedback': 'prds',
183
+ 'bug-report': 'postmortems',
184
+ 'incident-report': 'postmortems',
185
+ 'feature-request': 'rfcs',
186
+ 'support-ticket': 'runbooks',
187
+ 'compliance': 'adrs',
188
+ };
189
+ const lane = typeToLane[type];
190
+ if (!lane) continue;
191
+
192
+ const lanePath = join(rootDir, 'docs', lane);
193
+ const exists = existsSync(lanePath) && safeReaddir(lanePath).length > 0;
194
+
195
+ gaps.push({
196
+ type: 'recommend-artifact',
197
+ lane,
198
+ severity: 'medium',
199
+ summary: `${items.length} pending intake items of type "${type}" — ${exists ? 'consider reviewing existing' : 'consider creating'} ${lane} docs`,
200
+ payload: { count: items.length, intakeType: type, intakeIds: items.map((i) => i.id) },
201
+ });
202
+ }
203
+
204
+ return gaps;
205
+ }
206
+
207
+ /**
208
+ * Run the full docs lifecycle check for all resolved targets.
209
+ *
210
+ * @param {object} opts
211
+ * @param {object} opts.config - Normalized embed config
212
+ * @param {object} opts.providerRegistry
213
+ * @param {object} [opts.snapshot] - Latest snapshot
214
+ * @param {object} [opts.authorityGuard]
215
+ * @param {object[]} [opts.signals] - Source signals for target discovery
216
+ * @returns {Promise<DocsLifecycleResult>}
217
+ */
218
+ export async function runDocsLifecycle(opts) {
219
+ const { config, providerRegistry, snapshot, authorityGuard, signals } = opts;
220
+
221
+ const targets = await resolveTargets(config, providerRegistry, { signals });
222
+ const roleLens = buildRoleLens(config.roles);
223
+ const allGaps = [];
224
+ const actions = [];
225
+ const recommendations = [];
226
+ const conflicts = [];
227
+
228
+ // Auto-suppress stale recommendations before generating new ones
229
+ const suppressed = autoSuppressStale();
230
+
231
+ for (const target of targets) {
232
+ const gaps = detectDocGaps(target, { snapshot, roleLens });
233
+ allGaps.push(...gaps.map((g) => ({ ...g, target: targetLabel(target) })));
234
+
235
+ // Check intake patterns for artifact recommendations (uses recommendation store for dedup)
236
+ const intakeGaps = detectIntakeDocGaps(target.path);
237
+ for (const gap of intakeGaps) {
238
+ const payload = gap.payload || {};
239
+ const recResult = createRecommendation({
240
+ type: gap.lane?.replace(/s$/, '') || 'prd',
241
+ title: payload.intakeType
242
+ ? `${payload.intakeType.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase())} documentation`
243
+ : `Documentation for ${gap.lane}`,
244
+ reason: gap.summary,
245
+ signalCount: payload.count || 1,
246
+ customerImpact: payload.count >= 5 ? 2 : payload.count >= 3 ? 1 : 0,
247
+ recencyBonus: 2,
248
+ sourceSignalIds: payload.intakeIds || [],
249
+ lane: gap.lane,
250
+ });
251
+ recommendations.push(recResult);
252
+ allGaps.push({ ...gap, target: targetLabel(target), recommendation: recResult });
253
+ }
254
+
255
+ // Check existing artifact coverage (PRDs, ADRs, RFCs)
256
+ if (snapshot) {
257
+ const artifactRecs = recommendArtifacts(snapshot, { rootDir: target.path });
258
+ for (const rec of artifactRecs) {
259
+ // Use recommendation store for dedup
260
+ const { active, existing } = isRecommendationActive(rec.type, rec.title);
261
+ if (!active) {
262
+ const recResult = createRecommendation({
263
+ type: rec.type,
264
+ title: rec.title,
265
+ reason: rec.reason,
266
+ signalCount: 1,
267
+ });
268
+ recommendations.push(recResult);
269
+ allGaps.push({
270
+ type: 'recommend-artifact',
271
+ lane: rec.type,
272
+ severity: 'medium',
273
+ summary: `${rec.title}: ${rec.reason}`,
274
+ payload: rec,
275
+ target: targetLabel(target),
276
+ recommendation: recResult,
277
+ });
278
+ } else {
279
+ // Already recommended — still surface in gaps but mark as existing
280
+ allGaps.push({
281
+ type: 'recommend-artifact',
282
+ lane: rec.type,
283
+ severity: 'low',
284
+ summary: `Already recommended: ${rec.title}`,
285
+ payload: { ...rec, existingRecommendation: existing?.id },
286
+ target: targetLabel(target),
287
+ });
288
+ }
289
+ }
290
+ }
291
+
292
+ // Run conflict detection on pending intake items
293
+ if (snapshot?.intakePackets?.length) {
294
+ try {
295
+ const packetConflicts = await detectConflicts(snapshot.intakePackets[0], { rootDir: target.path });
296
+ conflicts.push(...packetConflicts.map(c => ({ ...c, target: targetLabel(target) })));
297
+ } catch (err) {
298
+ process.stderr.write(`[docs-lifecycle] Conflict detection error: ${err.message}\n`);
299
+ }
300
+ }
301
+
302
+ // Determine actions for each gap
303
+ for (const gap of gaps) {
304
+ const risk = RISK_LEVEL[gap.lane] ?? (gap.type === 'missing-roadmap' ? 'low' : 'high');
305
+
306
+ if (risk === 'low') {
307
+ // Can act autonomously
308
+ actions.push({ gap, target, action: 'auto-fix', risk });
309
+ } else {
310
+ // Queue for approval
311
+ if (authorityGuard) {
312
+ const decision = await authorityGuard.check('publishDocs', {
313
+ description: gap.summary,
314
+ payload: { lane: gap.lane, target: targetLabel(target) },
315
+ });
316
+ actions.push({ gap, target, action: decision.allowed ? 'approved' : 'queued', risk, queueId: decision.queueId });
317
+ } else {
318
+ actions.push({ gap, target, action: 'skipped-no-guard', risk });
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ const stats = recommendationStats();
325
+
326
+ return {
327
+ gaps: allGaps,
328
+ actions,
329
+ targets: targets.length,
330
+ recommendations,
331
+ conflicts,
332
+ suppressedStale: suppressed,
333
+ recommendationStats: stats,
334
+ };
335
+ }
336
+
337
+ function targetLabel(t) {
338
+ if (t.type === 'workspace') return 'workspace';
339
+ return t.ref ?? t.path ?? 'unknown';
340
+ }
341
+
342
+ function safeReaddir(dir) {
343
+ try {
344
+ return readdirSync(dir).filter((f) => !f.startsWith('.'));
345
+ } catch (err) {
346
+ process.stderr.write('[docs-lifecycle.mjs] safeReaddir: ' + (err?.message ?? String(err)) + '\n');
347
+ return [];
348
+ }
349
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * lib/embed/inbox-live-watcher.mjs — reactive fs.watch wrapper around InboxWatcher.
3
+ *
4
+ * Registers a node:fs.watch listener on each inbox directory and triggers
5
+ * `InboxWatcher.poll()` shortly after filesystem activity settles, so files
6
+ * dropped into `.cx/inbox/` flow through ingest + the review queue in
7
+ * seconds rather than waiting for the scheduler's next interval.
8
+ *
9
+ * Two limits keep this stable across platforms:
10
+ *
11
+ * - Debounce window (default 750ms): batches a multi-file paste into one
12
+ * poll. fs.watch fires per-entry on Linux and sometimes twice per entry
13
+ * on macOS; debouncing collapses both cases.
14
+ *
15
+ * - In-flight guard: if a poll is already running when an event fires,
16
+ * mark the watcher dirty and re-poll once the current one finishes.
17
+ * Prevents overlapping pgvector writes on rapid bursts.
18
+ *
19
+ * Inbox dirs are flat by design, so recursive watching is not required —
20
+ * top-level fs.watch is enough and avoids the cross-platform recursive
21
+ * issues that plague larger trees. fs.watch silently misses events on
22
+ * network mounts and certain Docker volume drivers; correctness lives in
23
+ * the scheduler poll, this watcher is a latency layer.
24
+ */
25
+
26
+ import { watch } from 'node:fs';
27
+
28
+ const DEFAULT_DEBOUNCE_MS = 750;
29
+
30
+ export class InboxLiveWatcher {
31
+ #inboxWatcher;
32
+ #debounceMs;
33
+ #watchFn;
34
+ #onPoll;
35
+ #onError;
36
+ #handles = [];
37
+ #pending = false;
38
+ #running = false;
39
+ #debounceTimer = null;
40
+ #started = false;
41
+
42
+ constructor({
43
+ inboxWatcher,
44
+ debounceMs = DEFAULT_DEBOUNCE_MS,
45
+ watchFn = watch,
46
+ onPoll = () => {},
47
+ onError = () => {},
48
+ } = {}) {
49
+ if (!inboxWatcher) throw new Error('InboxLiveWatcher: inboxWatcher is required');
50
+ this.#inboxWatcher = inboxWatcher;
51
+ this.#debounceMs = debounceMs;
52
+ this.#watchFn = watchFn;
53
+ this.#onPoll = onPoll;
54
+ this.#onError = onError;
55
+ }
56
+
57
+ start() {
58
+ if (this.#started) return { watched: this.#handles.length };
59
+ this.#started = true;
60
+
61
+ const dirs = this.#inboxWatcher.dirs();
62
+ for (const dir of dirs) {
63
+ try {
64
+ const handle = this.#watchFn(dir, { persistent: true }, (eventType, filename) => {
65
+ if (filename && filename.startsWith('.')) return;
66
+ this.#trigger();
67
+ });
68
+ if (handle && typeof handle.on === 'function') {
69
+ handle.on('error', (err) => this.#onError(err, dir));
70
+ }
71
+ this.#handles.push({ dir, handle });
72
+ } catch (err) {
73
+ this.#onError(err, dir);
74
+ }
75
+ }
76
+ return { watched: this.#handles.length, dirs };
77
+ }
78
+
79
+ stop() {
80
+ if (!this.#started) return;
81
+ this.#started = false;
82
+ if (this.#debounceTimer) {
83
+ clearTimeout(this.#debounceTimer);
84
+ this.#debounceTimer = null;
85
+ }
86
+ for (const { handle } of this.#handles) {
87
+ try { handle.close?.(); } catch { /* ignore */ }
88
+ }
89
+ this.#handles = [];
90
+ }
91
+
92
+ #trigger() {
93
+ if (this.#debounceTimer) clearTimeout(this.#debounceTimer);
94
+ this.#debounceTimer = setTimeout(() => {
95
+ this.#debounceTimer = null;
96
+ this.#runPoll();
97
+ }, this.#debounceMs);
98
+ }
99
+
100
+ async #runPoll() {
101
+ if (this.#running) {
102
+ this.#pending = true;
103
+ return;
104
+ }
105
+ this.#running = true;
106
+ try {
107
+ const result = await this.#inboxWatcher.poll();
108
+ this.#onPoll(result);
109
+ } catch (err) {
110
+ this.#onError(err, null);
111
+ } finally {
112
+ this.#running = false;
113
+ if (this.#pending) {
114
+ this.#pending = false;
115
+ setImmediate(() => this.#runPoll());
116
+ }
117
+ }
118
+ }
119
+ }