@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/artifact.mjs — On-demand and embed-triggered artifact generation.
3
+ *
4
+ * Generates PRDs, RFCs, and ADRs as structured markdown files under docs/.
5
+ * Each artifact type has a fixed schema and front-matter. Numbering is auto-
6
+ * incremented by scanning the target directory. Entry points cover the CLI,
7
+ * the embed daemon when analysis triggers a recommendation, and the dashboard
8
+ * API.
9
+ */
10
+
11
+ import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';
12
+ import { join } from 'path';
13
+ import { randomUUID } from 'crypto';
14
+
15
+ // ── Constants ──────────────────────────────────────────────────────────────
16
+
17
+ const ARTIFACT_TYPES = ['prd', 'adr', 'rfc'];
18
+
19
+ const DIRS = {
20
+ prd: 'docs/prd',
21
+ adr: 'docs/adr',
22
+ rfc: 'docs/rfc',
23
+ };
24
+
25
+ // ── Numbering ──────────────────────────────────────────────────────────────
26
+
27
+ /**
28
+ * Scan a directory for existing artifacts and return the next sequence number.
29
+ * Files must match the pattern NNNN-*.md.
30
+ */
31
+ function nextSequenceNumber(dir) {
32
+ if (!existsSync(dir)) return 1;
33
+ const files = readdirSync(dir).filter(f => /^\d{4}-.*\.md$/.test(f));
34
+ if (!files.length) return 1;
35
+ const nums = files.map(f => parseInt(f.slice(0, 4), 10)).filter(n => !isNaN(n));
36
+ return Math.max(...nums) + 1;
37
+ }
38
+
39
+ function padNum(n) {
40
+ return String(n).padStart(4, '0');
41
+ }
42
+
43
+ function slugify(title) {
44
+ return title
45
+ .toLowerCase()
46
+ .replace(/[^a-z0-9]+/g, '-')
47
+ .replace(/^-+|-+$/g, '')
48
+ .slice(0, 60);
49
+ }
50
+
51
+ // ── Front-matter ───────────────────────────────────────────────────────────
52
+
53
+ function buildFrontMatter(fields) {
54
+ const lines = ['---'];
55
+ for (const [k, v] of Object.entries(fields)) {
56
+ lines.push(`${k}: ${v}`);
57
+ }
58
+ lines.push('---', '');
59
+ return lines.join('\n');
60
+ }
61
+
62
+ // ── Templates ──────────────────────────────────────────────────────────────
63
+
64
+ function prdTemplate({ number, title, owner, problem, goals, nonGoals, users }) {
65
+ const num = padNum(number);
66
+ const date = new Date().toISOString().slice(0, 10);
67
+ const fm = buildFrontMatter({
68
+ cx_doc_id: randomUUID(),
69
+ created_at: new Date().toISOString(),
70
+ updated_at: new Date().toISOString(),
71
+ generator: 'construct/artifact',
72
+ status: 'draft',
73
+ });
74
+
75
+ return `${fm}# PRD-${num}: ${title}
76
+
77
+ - **Date**: ${date}
78
+ - **Owner**: ${owner || 'TBD'}
79
+ - **Status**: draft
80
+
81
+ ## Problem
82
+
83
+ ${problem || 'TODO: Describe the problem this PRD addresses.'}
84
+
85
+ ## Users
86
+
87
+ | Segment | Description | Current workaround |
88
+ |---|---|---|
89
+ | TODO | TODO | TODO |
90
+
91
+ ## Goals
92
+
93
+ ${(goals || []).map(g => `- ${g}`).join('\n') || '- TODO'}
94
+
95
+ ## Non-goals
96
+
97
+ ${(nonGoals || []).map(g => `- ${g}`).join('\n') || '- TODO'}
98
+
99
+ ## Requirements
100
+
101
+ ### Functional
102
+
103
+ | ID | Requirement | Priority |
104
+ |---|---|---|
105
+ | F1 | TODO | P0 |
106
+
107
+ ### Non-functional
108
+
109
+ | ID | Requirement | Target |
110
+ |---|---|---|
111
+ | NF1 | TODO | TODO |
112
+
113
+ ## Open questions
114
+
115
+ - TODO
116
+ `;
117
+ }
118
+
119
+ function adrTemplate({ number, title, status, context, decision, consequences, alternatives }) {
120
+ const num = padNum(number);
121
+ const fm = buildFrontMatter({
122
+ cx_doc_id: randomUUID(),
123
+ created_at: new Date().toISOString(),
124
+ updated_at: new Date().toISOString(),
125
+ generator: 'construct/artifact',
126
+ body_hash: 'sha256:placeholder',
127
+ });
128
+
129
+ const altSection = (alternatives || []).length
130
+ ? alternatives.map(a => `### ${a.title}\n\n${a.reason || 'Rejected.'}`).join('\n\n')
131
+ : '### Alternative A\n\nTODO: describe and explain rejection.';
132
+
133
+ return `${fm}# ADR-${num}: ${title}
134
+
135
+ ## Status
136
+
137
+ ${status || 'Proposed'}
138
+
139
+ ## Context
140
+
141
+ ${context || 'TODO: Describe the context and problem that led to this decision.'}
142
+
143
+ ## Decision
144
+
145
+ ${decision || 'TODO: State the architectural decision.'}
146
+
147
+ ## Consequences
148
+
149
+ ${(consequences || []).map(c => `- ${c}`).join('\n') || '- TODO'}
150
+
151
+ ## Rejected alternatives
152
+
153
+ ${altSection}
154
+ `;
155
+ }
156
+
157
+ function rfcTemplate({ number, title, author, summary, motivation, design, drawbacks, alternatives, unresolved }) {
158
+ const num = padNum(number);
159
+ const date = new Date().toISOString().slice(0, 10);
160
+ const fm = buildFrontMatter({
161
+ cx_doc_id: randomUUID(),
162
+ created_at: new Date().toISOString(),
163
+ updated_at: new Date().toISOString(),
164
+ generator: 'construct/artifact',
165
+ status: 'draft',
166
+ });
167
+
168
+ return `${fm}# RFC-${num}: ${title}
169
+
170
+ - **Date**: ${date}
171
+ - **Author**: ${author || 'TBD'}
172
+ - **Status**: draft
173
+
174
+ ## Summary
175
+
176
+ ${summary || 'TODO: One-paragraph summary of the change being proposed.'}
177
+
178
+ ## Motivation
179
+
180
+ ${motivation || 'TODO: Why is this change needed? What problem does it solve?'}
181
+
182
+ ## Design
183
+
184
+ ${design || 'TODO: Detailed description of the proposed design or implementation.'}
185
+
186
+ ## Drawbacks
187
+
188
+ ${(drawbacks || []).map(d => `- ${d}`).join('\n') || '- TODO'}
189
+
190
+ ## Alternatives
191
+
192
+ ${(alternatives || []).map(a => `- ${a}`).join('\n') || '- TODO'}
193
+
194
+ ## Unresolved questions
195
+
196
+ ${(unresolved || []).map(u => `- ${u}`).join('\n') || '- TODO'}
197
+ `;
198
+ }
199
+
200
+ // ── Core generator ─────────────────────────────────────────────────────────
201
+
202
+ /**
203
+ * Generate an artifact file.
204
+ *
205
+ * @param {object} opts
206
+ * @param {string} opts.type - 'prd' | 'adr' | 'rfc'
207
+ * @param {string} opts.title - Human-readable title (required)
208
+ * @param {string} [opts.rootDir] - Project root (default: cwd)
209
+ * @param {object} [opts.fields] - Type-specific fields (see templates above)
210
+ * @param {boolean} [opts.dryRun] - If true, return content without writing
211
+ * @returns {{ path: string, content: string, number: number }}
212
+ */
213
+ export function generateArtifact({ type, title, rootDir, fields = {}, dryRun = false }) {
214
+ if (!ARTIFACT_TYPES.includes(type)) {
215
+ throw new Error(`Unknown artifact type "${type}". Must be one of: ${ARTIFACT_TYPES.join(', ')}`);
216
+ }
217
+ if (!title || typeof title !== 'string' || !title.trim()) {
218
+ throw new Error('title is required');
219
+ }
220
+
221
+ const root = rootDir || process.cwd();
222
+ const dir = join(root, DIRS[type]);
223
+
224
+ const number = nextSequenceNumber(dir);
225
+ const slug = slugify(title.trim());
226
+ const filename = `${padNum(number)}-${slug}.md`;
227
+ const filePath = join(dir, filename);
228
+
229
+ let content;
230
+ const ctx = { number, title: title.trim(), ...fields };
231
+
232
+ if (type === 'prd') content = prdTemplate(ctx);
233
+ else if (type === 'adr') content = adrTemplate(ctx);
234
+ else content = rfcTemplate(ctx);
235
+
236
+ if (!dryRun) {
237
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
238
+ writeFileSync(filePath, content, 'utf8');
239
+ }
240
+
241
+ return { path: filePath, relativePath: join(DIRS[type], filename), content, number };
242
+ }
243
+
244
+ // ── List artifacts ─────────────────────────────────────────────────────────
245
+
246
+ /**
247
+ * List all artifacts of a given type (or all types).
248
+ *
249
+ * @param {object} opts
250
+ * @param {string} [opts.type] - Filter by type; if omitted, returns all
251
+ * @param {string} [opts.rootDir] - Project root
252
+ * @returns {Array<{ type, number, slug, filename, title, status, path }>}
253
+ */
254
+ export function listArtifacts({ type, rootDir } = {}) {
255
+ const root = rootDir || process.cwd();
256
+ const types = type ? [type] : ARTIFACT_TYPES;
257
+ const results = [];
258
+
259
+ for (const t of types) {
260
+ const dir = join(root, DIRS[t]);
261
+ if (!existsSync(dir)) continue;
262
+
263
+ for (const file of readdirSync(dir).sort()) {
264
+ if (!/^\d{4}-.*\.md$/.test(file)) continue;
265
+ const filePath = join(dir, file);
266
+ let titleLine = file.replace('.md', '').replace(/^\d{4}-/, '').replace(/-/g, ' ');
267
+ let status = 'unknown';
268
+
269
+ try {
270
+ const raw = readFileSync(filePath, 'utf8');
271
+ const headingMatch = raw.match(/^# .+?: (.+)$/m);
272
+ if (headingMatch) titleLine = headingMatch[1].trim();
273
+ const statusMatch = raw.match(/\*\*Status\*\*: (\S+)|^## Status\s+\n+(\S[^\n]*)/m);
274
+ if (statusMatch) status = (statusMatch[1] || statusMatch[2] || 'unknown').trim().toLowerCase();
275
+ } catch { /* ignore read errors */ }
276
+
277
+ results.push({
278
+ type: t,
279
+ number: parseInt(file.slice(0, 4), 10),
280
+ filename: file,
281
+ title: titleLine,
282
+ status,
283
+ path: filePath,
284
+ relativePath: join(DIRS[t], file),
285
+ });
286
+ }
287
+ }
288
+
289
+ return results;
290
+ }
291
+
292
+ // ── Embed trigger ──────────────────────────────────────────────────────────
293
+
294
+ /**
295
+ * Evaluate a snapshot and return artifact recommendations.
296
+ * Called by the embed daemon after each snapshot cycle.
297
+ *
298
+ * @param {object} snapshot - Snapshot from SnapshotEngine
299
+ * @param {object} [opts]
300
+ * @param {string} [opts.rootDir]
301
+ * @returns {Array<{ type, title, reason, fields }>}
302
+ */
303
+ export function recommendArtifacts(snapshot, { rootDir } = {}) {
304
+ const root = rootDir || process.cwd();
305
+ const existing = listArtifacts({ rootDir: root });
306
+ const recommendations = [];
307
+
308
+ // If no PRD exists, recommend one
309
+ const hasPrd = existing.some(a => a.type === 'prd');
310
+ if (!hasPrd) {
311
+ recommendations.push({
312
+ type: 'prd',
313
+ title: 'Project Overview',
314
+ reason: 'No PRD found. A product requirements document helps align contributors and agents.',
315
+ });
316
+ }
317
+
318
+ // If snapshot has errors and no ADR for error handling, recommend one
319
+ const snapshotHasErrors = snapshot?.summary?.some?.(s => s.status === 'error');
320
+ if (snapshotHasErrors) {
321
+ const hasErrorAdr = existing.some(a =>
322
+ a.type === 'adr' && /error|resilience|failure/i.test(a.title)
323
+ );
324
+ if (!hasErrorAdr) {
325
+ recommendations.push({
326
+ type: 'adr',
327
+ title: 'Error Handling and Resilience Strategy',
328
+ reason: 'Snapshot detected provider errors. Document the error-handling strategy.',
329
+ });
330
+ }
331
+ }
332
+
333
+ // If there are multiple providers and no integration RFC, recommend one
334
+ const providerCount = snapshot?.providers?.length ?? 0;
335
+ if (providerCount >= 3) {
336
+ const hasIntegrationRfc = existing.some(a =>
337
+ a.type === 'rfc' && /integration|provider/i.test(a.title)
338
+ );
339
+ if (!hasIntegrationRfc) {
340
+ recommendations.push({
341
+ type: 'rfc',
342
+ title: 'Multi-Provider Integration Strategy',
343
+ reason: `${providerCount} providers are configured. Consider documenting the integration approach as an RFC.`,
344
+ });
345
+ }
346
+ }
347
+
348
+ return recommendations;
349
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * lib/embed/authority-guard.mjs — runtime enforcement of operating profile authority boundaries.
3
+ *
4
+ * Maps the authority fields declared in the embedded operating profile to
5
+ * actual allow/queue/deny decisions. Consults the ApprovalQueue for
6
+ * `approval-queued` actions and lets `autonomous` actions pass immediately.
7
+ *
8
+ * Authority fields (from DEFAULT_OPERATING_PROFILE.authority):
9
+ * - read → autonomous
10
+ * - summarize → autonomous
11
+ * - draftArtifacts → autonomous
12
+ * - createIssues → approval-queued
13
+ * - updateIssues → approval-queued
14
+ * - publishDocs → approval-queued
15
+ * - externalPost → approval-queued
16
+ * - repoWrites → approval-queued
17
+ *
18
+ * Usage:
19
+ * const guard = new AuthorityGuard(operatingProfile, approvalQueue);
20
+ * const result = await guard.check('externalPost', { description: 'Post roadmap to Slack' });
21
+ * if (result.allowed) { ... execute ... }
22
+ * else { ... it's been queued or denied ... }
23
+ */
24
+
25
+ // ─── Action-type → authority-key mapping ────────────────────────────────────
26
+
27
+ const ACTION_TO_AUTHORITY = {
28
+ // Read / summarize
29
+ read: 'read',
30
+ summarize: 'summarize',
31
+ // Artifact drafting
32
+ draftArtifacts: 'draftArtifacts',
33
+ 'artifact:prd': 'draftArtifacts',
34
+ 'artifact:adr': 'draftArtifacts',
35
+ 'artifact:rfc': 'draftArtifacts',
36
+ 'artifact:memo': 'draftArtifacts',
37
+ // Issue management
38
+ createIssues: 'createIssues',
39
+ 'issue:create': 'createIssues',
40
+ updateIssues: 'updateIssues',
41
+ 'issue:update': 'updateIssues',
42
+ // Documentation publishing
43
+ publishDocs: 'publishDocs',
44
+ 'docs:publish': 'publishDocs',
45
+ 'docs:write': 'publishDocs',
46
+ // External messaging
47
+ externalPost: 'externalPost',
48
+ 'slack:post': 'externalPost',
49
+ 'email:send': 'externalPost',
50
+ // Repo writes
51
+ repoWrites: 'repoWrites',
52
+ 'git:commit': 'repoWrites',
53
+ 'git:push': 'repoWrites',
54
+ 'git:pr': 'repoWrites',
55
+ };
56
+
57
+ /**
58
+ * Resolve the authority key for an action type.
59
+ * Falls back to the action type itself (for forward-compat).
60
+ */
61
+ function resolveAuthorityKey(actionType) {
62
+ return ACTION_TO_AUTHORITY[actionType] ?? actionType;
63
+ }
64
+
65
+ // ─── AuthorityGuard ──────────────────────────────────────────────────────────
66
+
67
+ export class AuthorityGuard {
68
+ #authority;
69
+ #approvalQueue;
70
+
71
+ /**
72
+ * @param {object} operatingProfile - The embed config's operatingProfile object
73
+ * @param {ApprovalQueue} approvalQueue
74
+ */
75
+ constructor(operatingProfile, approvalQueue) {
76
+ this.#authority = operatingProfile?.authority ?? {};
77
+ this.#approvalQueue = approvalQueue;
78
+ }
79
+
80
+ /**
81
+ * Check whether an action is allowed under the current authority profile.
82
+ *
83
+ * @param {string} actionType - e.g. 'externalPost', 'artifact:prd', 'issue:create'
84
+ * @param {object} [meta] - Optional metadata: { description, payload }
85
+ * @returns {{ allowed: boolean, mode: string, queueId?: string, reason?: string }}
86
+ */
87
+ async check(actionType, meta = {}) {
88
+ const key = resolveAuthorityKey(actionType);
89
+ const level = this.#authority[key] ?? 'approval-queued'; // fail-safe default
90
+
91
+ if (level === 'autonomous') {
92
+ return { allowed: true, mode: 'autonomous' };
93
+ }
94
+
95
+ if (level === 'denied') {
96
+ return { allowed: false, mode: 'denied', reason: `Authority level for "${key}" is denied` };
97
+ }
98
+
99
+ // approval-queued: consult the ApprovalQueue
100
+ if (this.#approvalQueue) {
101
+ // Check if there's already an approved item for this action
102
+ const mode = this.#approvalQueue.approvalMode(actionType);
103
+ if (mode === 'auto') {
104
+ return { allowed: true, mode: 'auto-approved' };
105
+ }
106
+
107
+ // Queue the action and return not-yet-allowed
108
+ const queueId = this.#approvalQueue.enqueue({
109
+ type: actionType,
110
+ authorityKey: key,
111
+ description: meta.description ?? actionType,
112
+ payload: meta.payload ?? {},
113
+ requestedAt: new Date().toISOString(),
114
+ });
115
+ return {
116
+ allowed: false,
117
+ mode: 'queued',
118
+ queueId,
119
+ reason: `Action "${actionType}" requires human approval (authority: ${key} = approval-queued)`,
120
+ };
121
+ }
122
+
123
+ // No approval queue present — default to deny for safety
124
+ return {
125
+ allowed: false,
126
+ mode: 'no-queue',
127
+ reason: `Action "${actionType}" requires approval but no ApprovalQueue is configured`,
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Synchronous check — returns allowed: true only for autonomous actions.
133
+ * Use this where async is not possible.
134
+ */
135
+ checkSync(actionType) {
136
+ const key = resolveAuthorityKey(actionType);
137
+ const level = this.#authority[key] ?? 'approval-queued';
138
+ return { allowed: level === 'autonomous', mode: level };
139
+ }
140
+
141
+ /**
142
+ * Return a summary of the current authority settings for diagnostics.
143
+ */
144
+ summary() {
145
+ const autonomous = [];
146
+ const queued = [];
147
+ const denied = [];
148
+ for (const [k, v] of Object.entries(this.#authority)) {
149
+ if (v === 'autonomous') autonomous.push(k);
150
+ else if (v === 'denied') denied.push(k);
151
+ else queued.push(k);
152
+ }
153
+ return { autonomous, queued, denied };
154
+ }
155
+ }