@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,399 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * lib/health-check.mjs — reusable prerequisite and health checks.
4
+ *
5
+ * Used by:
6
+ * - `construct dev` (auto-checks before starting services)
7
+ * - `construct doctor` (comprehensive system audit)
8
+ * - `construct init` (pre-init validation)
9
+ */
10
+
11
+ import { spawnSync } from 'node:child_process';
12
+ import os from 'node:os';
13
+ import path from 'node:path';
14
+ import { existsSync, readFileSync } from 'node:fs';
15
+
16
+ const isWindows = os.platform() === 'win32';
17
+
18
+ /**
19
+ * Check if a command exists on PATH.
20
+ * @param {string} command - Command name to check
21
+ * @returns {boolean} - True if command exists
22
+ */
23
+ export function commandExists(command) {
24
+ const result = spawnSync(isWindows ? 'where' : 'zsh',
25
+ isWindows ? [command] : ['-lc', `command -v ${command}`],
26
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] }
27
+ );
28
+ return result.status === 0;
29
+ }
30
+
31
+ /**
32
+ * Get version string from a command.
33
+ * @param {string} command - Command name
34
+ * @param {string[]} args - Arguments to get version
35
+ * @returns {string|null} - Version string or null
36
+ */
37
+ export function getVersion(command, args = ['--version']) {
38
+ try {
39
+ const result = spawnSync(command, args, { encoding: 'utf8' });
40
+ if (result.status === 0) {
41
+ return result.stdout.trim().split('\n')[0].trim();
42
+ }
43
+ } catch {
44
+ // Ignore
45
+ }
46
+ return null;
47
+ }
48
+
49
+ /**
50
+ * Run prerequisite checks for Construct.
51
+ * @param {Object} options - Options
52
+ * @param {boolean} options.interactive - Whether to prompt for fixes
53
+ * @param {boolean} options.autoFix - Whether to auto-fix issues
54
+ * @param {string} options.homeDir - Home directory path
55
+ * @returns {Promise<{ok: boolean, missing: string[], warnings: string[]}>}
56
+ */
57
+ export async function checkPrerequisites(options = {}) {
58
+ const { interactive = false, autoFix = false, homeDir } = options;
59
+
60
+ const checks = [];
61
+ const missing = [];
62
+ const warnings = [];
63
+
64
+ // Check Docker
65
+ const dockerVersion = getVersion('docker');
66
+ const hasDocker = !!dockerVersion;
67
+ checks.push({
68
+ name: 'Docker',
69
+ required: true,
70
+ installed: hasDocker,
71
+ version: dockerVersion,
72
+ why: 'Required for telemetry backend (trace observability) and managed Postgres',
73
+ install: isWindows
74
+ ? 'https://docs.docker.com/desktop/install/windows-install/'
75
+ : 'https://docs.docker.com/get-docker/',
76
+ });
77
+
78
+ // Check cm (Memory MCP server)
79
+ const hasCm = commandExists('cm');
80
+ const cmVersion = hasCm ? getVersion('cm', ['--version']) : null;
81
+ checks.push({
82
+ name: 'cm (Memory Server)',
83
+ required: true,
84
+ installed: hasCm,
85
+ version: cmVersion,
86
+ why: 'Required for cross-session agent memory and handoffs',
87
+ install: 'brew install dicklesworthstone/tap/cm (macOS) or npm install -g @dicklesworthstone/cm',
88
+ });
89
+
90
+ // Check Node.js
91
+ const nodeVersion = process.version;
92
+ const nodeOk = parseInt(nodeVersion.slice(1)) >= 20;
93
+ checks.push({
94
+ name: 'Node.js',
95
+ required: true,
96
+ installed: nodeOk,
97
+ version: nodeVersion,
98
+ why: 'Required to run Construct CLI (v20+)',
99
+ install: 'https://nodejs.org/',
100
+ });
101
+
102
+ // Check construct CLI on PATH (warning only)
103
+ const constructOnPath = commandExists('construct');
104
+ checks.push({
105
+ name: 'construct CLI',
106
+ required: false,
107
+ installed: constructOnPath,
108
+ version: constructOnPath ? getVersion('construct', ['version']) : null,
109
+ why: 'Recommended for global access',
110
+ install: 'npm install -g @geraldmaron/construct',
111
+ });
112
+
113
+ // Check user config
114
+ const hasUserConfig = existsSync(path.join(homeDir || os.homedir(), '.construct', 'config.env')) ||
115
+ existsSync(path.join(homeDir || os.homedir(), '.construct'));
116
+ checks.push({
117
+ name: 'User config',
118
+ required: false,
119
+ installed: hasUserConfig,
120
+ version: null,
121
+ why: 'Created on first `construct init`',
122
+ install: 'construct init',
123
+ });
124
+
125
+ // Print results if interactive
126
+ if (interactive) {
127
+ console.log('\n🔍 Checking prerequisites...\n');
128
+
129
+ for (const check of checks) {
130
+ const icon = check.installed ? '✓' : '✗';
131
+ const status = check.installed
132
+ ? (check.version ? `v${check.version}` : 'installed')
133
+ : 'MISSING';
134
+ const indent = ' ';
135
+ console.log(`${indent}${icon} ${check.name.padEnd(25)} ${status}`);
136
+
137
+ if (!check.installed) {
138
+ console.log(`${indent} → ${check.why}`);
139
+ console.log(`${indent} → Install: ${check.install}`);
140
+
141
+ if (check.required) {
142
+ missing.push(check.name);
143
+ } else {
144
+ warnings.push(check.name);
145
+ }
146
+ }
147
+ }
148
+
149
+ if (missing.length > 0) {
150
+ console.log(`\n⚠️ Missing ${missing.length} required dependenc${missing.length === 1 ? 'y' : 'ies'}: ${missing.join(', ')}`);
151
+
152
+ if (autoFix) {
153
+ console.log('\n🔧 Auto-fix enabled — attempting to install missing dependencies...');
154
+ return { ok: false, missing, warnings, autoFixRequested: true };
155
+ }
156
+
157
+ console.log('\n💡 Run `construct install --yes` to install missing dependencies automatically.');
158
+ } else if (warnings.length > 0) {
159
+ console.log(`\n⚠️ ${warnings.length} optional component${warnings.length === 1 ? '' : 's'} missing: ${warnings.join(', ')}`);
160
+ console.log(' Construct will work but some features may be limited.');
161
+ } else {
162
+ console.log('\n✅ All prerequisites met!\n');
163
+ }
164
+ }
165
+
166
+ return { ok: missing.length === 0, missing, warnings, checks };
167
+ }
168
+
169
+ /**
170
+ * Get a value from shell env by checking common sources.
171
+ * Looks in process.env → project .env → ~/.env → ~/.construct/config.env
172
+ * → shell rc files for op:// refs (resolved via 'op read').
173
+ */
174
+ function getEnvFromShell(varName, homeDir) {
175
+ if (process.env[varName]) return process.env[varName];
176
+
177
+ const projectEnv = path.join(process.cwd(), '.env');
178
+ if (existsSync(projectEnv)) {
179
+ try {
180
+ const content = readFileSync(projectEnv, 'utf8');
181
+ const m = content.match(new RegExp(`^${varName}=["']?(.+?)["']?$`, 'm'));
182
+ if (m) return m[1].trim();
183
+ } catch { /* skip */ }
184
+ }
185
+
186
+ const homeEnv = path.join(homeDir, '.env');
187
+ if (existsSync(homeEnv)) {
188
+ try {
189
+ const content = readFileSync(homeEnv, 'utf8');
190
+ const m = content.match(new RegExp(`^${varName}=["']?(.+?)["']?$`, 'm'));
191
+ if (m) return m[1].trim();
192
+ } catch { /* skip */ }
193
+ }
194
+
195
+ const cfgPath = path.join(homeDir, '.construct', 'config.env');
196
+ if (existsSync(cfgPath)) {
197
+ try {
198
+ const content = readFileSync(cfgPath, 'utf8');
199
+ const m = content.match(new RegExp(`^${varName}=(.+)$`, 'm'));
200
+ if (m) return m[1].trim();
201
+ } catch { /* skip */ }
202
+ }
203
+
204
+ const shellFiles = [
205
+ path.join(homeDir, '.zshrc'),
206
+ path.join(homeDir, '.bashrc'),
207
+ path.join(homeDir, '.bash_profile'),
208
+ path.join(homeDir, '.profile'),
209
+ ];
210
+ for (const rcPath of shellFiles) {
211
+ if (!existsSync(rcPath)) continue;
212
+ try {
213
+ const content = readFileSync(rcPath, 'utf8');
214
+ const re = new RegExp(`export\\s+${varName}=["']?\\$\\(op read '([^']+)'\\)["']?`, 'm');
215
+ const m = content.match(re);
216
+ if (m) {
217
+ const opRef = m[1];
218
+ try {
219
+ const result = spawnSync('op', ['read', opRef], {
220
+ encoding: 'utf8',
221
+ stdio: ['pipe', 'pipe', 'pipe'],
222
+ timeout: 5000,
223
+ });
224
+ if (result.status === 0) return result.stdout.trim();
225
+ } catch { /* op read failed */ }
226
+ }
227
+ } catch { /* skip unreadable files */ }
228
+ }
229
+
230
+ // If we found an op:// reference but couldn't read it, log the error
231
+ // for diagnostic purposes when DEBUG is on.
232
+ if (process.env.CONSTRUCT_DEBUG_CREDENTIALS === '1') {
233
+ for (const rcPath of shellFiles) {
234
+ if (!existsSync(rcPath)) continue;
235
+ try {
236
+ const content = readFileSync(rcPath, 'utf8');
237
+ const re = new RegExp(`export\\s+${varName}=["']?\\$\\(op read '([^']+)'\\)["']?`, 'm');
238
+ const m = content.match(re);
239
+ if (m) {
240
+ try {
241
+ const result = spawnSync('op', ['read', m[1]], { encoding: 'utf8', timeout: 5000 });
242
+ if (result.status !== 0) {
243
+ const errMsg = (result.stderr || '').trim().slice(0, 200);
244
+ process.stderr.write(`[credentials] ${varName}: op read '${m[1]}' failed: ${errMsg}\n`);
245
+ }
246
+ } catch (e) {
247
+ process.stderr.write(`[credentials] ${varName}: op CLI error: ${e.message}\n`);
248
+ }
249
+ }
250
+ } catch { /* skip */ }
251
+ }
252
+ }
253
+
254
+ return null;
255
+ }
256
+
257
+ /**
258
+ * Known credential env vars and their 1Password lookup patterns.
259
+ */
260
+ const CREDENTIAL_VARS = [
261
+ 'OPENROUTER_API_KEY',
262
+ 'ANTHROPIC_API_KEY',
263
+ 'OPENAI_API_KEY',
264
+ 'GEMINI_API_KEY',
265
+ 'GOOGLE_API_KEY',
266
+ 'GITHUB_TOKEN',
267
+ 'GH_TOKEN',
268
+ 'SLACK_BOT_TOKEN',
269
+ 'SLACK_USER_TOKEN',
270
+ 'JIRA_API_TOKEN',
271
+ 'CONFLUENCE_API_TOKEN',
272
+ 'SALESFORCE_ACCESS_TOKEN',
273
+ 'OPENCODE_API_KEY',
274
+ 'HUGGINGFACE_API_KEY',
275
+ 'GROQ_API_KEY',
276
+ 'MISTRAL_API_KEY',
277
+ 'REPLICATE_API_KEY',
278
+ 'COHERE_API_KEY',
279
+ 'AI21_API_KEY',
280
+ 'TOGETHER_API_KEY',
281
+ 'DEEPSEEK_API_KEY',
282
+ 'PERPLEXITY_API_KEY',
283
+ 'CLAUDE_API_KEY',
284
+ 'AZURE_OPENAI_API_KEY',
285
+ 'AZURE_OPENAI_ENDPOINT',
286
+ 'CONSTRUCT_TELEMETRY_PUBLIC_KEY',
287
+ 'CONSTRUCT_TELEMETRY_SECRET_KEY',
288
+ 'CONSTRUCT_TELEMETRY_URL',
289
+ ];
290
+
291
+ /**
292
+ * Resolve all known credentials from env, .env files, and 1Password.
293
+ * @param {Object} options
294
+ * @param {string} options.homeDir
295
+ * @param {boolean} options.writeConfig - Write resolved keys to config.env (default: true)
296
+ * @returns {Promise<Record<string, string>>} resolved key-value pairs
297
+ */
298
+ export async function resolveCredentials(options = {}) {
299
+ const { homeDir = os.homedir(), writeConfig = true } = options;
300
+ const resolved = {};
301
+
302
+ for (const varName of CREDENTIAL_VARS) {
303
+ const value = getEnvFromShell(varName, homeDir);
304
+ if (value) resolved[varName] = value;
305
+ }
306
+
307
+ // Write resolved keys to config.env so subprocesses and the dashboard find them
308
+ if (writeConfig && Object.keys(resolved).length > 0) {
309
+ try {
310
+ const { writeEnvValues, getUserEnvPath } = await import('./env-config.mjs');
311
+ writeEnvValues(getUserEnvPath(homeDir), resolved);
312
+ } catch { /* best effort */ }
313
+ }
314
+
315
+ return resolved;
316
+ }
317
+
318
+ /**
319
+ * Detect existing credentials and tools on the system.
320
+ * @param {Object} options
321
+ * @param {string} options.homeDir
322
+ * @returns {object} detected credentials
323
+ */
324
+ export function detectCredentials(options = {}) {
325
+ const homeDir = options.homeDir || os.homedir();
326
+ const found = {};
327
+
328
+ // GitHub CLI auth
329
+ const ghAuth = spawnSync('gh', ['auth', 'status'], { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] });
330
+ found.github_cli = ghAuth.status === 0;
331
+
332
+ // GitHub Copilot (check VS Code extension state)
333
+ const copilotDir = path.join(homeDir, '.vscode', 'extensions');
334
+ const copilotExists = existsSync(copilotDir) && existsSync(path.join(homeDir, '.config', 'Code', 'User', 'globalStorage', 'github.copilot'));
335
+ found.copilot = copilotExists || commandExists('copilot');
336
+
337
+ // OpenRouter API key
338
+ found.openrouter_key = !!getEnvFromShell('OPENROUTER_API_KEY', homeDir);
339
+
340
+ // Anthropic API key
341
+ found.anthropic_key = !!getEnvFromShell('ANTHROPIC_API_KEY', homeDir);
342
+
343
+ // OpenAI API key
344
+ found.openai_key = !!getEnvFromShell('OPENAI_API_KEY', homeDir);
345
+
346
+ // GitHub token
347
+ found.github_token = !!getEnvFromShell('GITHUB_TOKEN', homeDir) || !!getEnvFromShell('GH_TOKEN', homeDir);
348
+
349
+ // VS Code installed
350
+ found.vscode = commandExists('code');
351
+
352
+ // Claude Code config
353
+ found.claude_code = existsSync(path.join(homeDir, '.claude', 'settings.json'));
354
+
355
+ // OpenCode config
356
+ found.opencode = existsSync(path.join(homeDir, '.config', 'opencode', 'opencode.json')) ||
357
+ existsSync(path.join(homeDir, '.config', 'opencode', 'opencode.jsonc'));
358
+
359
+ // Ollama (local LLMs)
360
+ found.ollama = commandExists('ollama');
361
+
362
+ // Docker (already checked but include for completeness)
363
+ found.docker = commandExists('docker');
364
+
365
+ return found;
366
+ }
367
+
368
+ /**
369
+ * Quick health check for `construct dev` — checks prerequisites + credentials.
370
+ * @param {Object} options - Options
371
+ * @param {string} options.homeDir - Home directory
372
+ * @param {boolean} options.showCredentials - Show credential summary (default: false)
373
+ * @returns {Promise<{ok: boolean, missing: string[], credentials: object}>}
374
+ */
375
+ export async function quickHealthCheck(options = {}) {
376
+ const { homeDir, showCredentials = false } = options;
377
+
378
+ const critical = [];
379
+
380
+ // Silent Docker check
381
+ if (!commandExists('docker')) {
382
+ critical.push('Docker');
383
+ }
384
+
385
+ // Silent cm check
386
+ if (!commandExists('cm')) {
387
+ critical.push('cm (Memory MCP server)');
388
+ }
389
+
390
+ // Node.js check
391
+ const nodeOk = parseInt(process.version.slice(1)) >= 20;
392
+ if (!nodeOk) {
393
+ critical.push(`Node.js ${process.version} (v20+ required)`);
394
+ }
395
+
396
+ const credentials = showCredentials ? detectCredentials({ homeDir }) : {};
397
+
398
+ return { ok: critical.length === 0, missing: critical, credentials };
399
+ }