@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,280 @@
1
+ /**
2
+ * lib/skills-apply.mjs — writes per-host skill filter configs from the
3
+ * project profile.
4
+ *
5
+ * The detection layer (lib/project-profile.mjs) is host-agnostic. This layer
6
+ * consumes a profile and writes host-specific configuration that scopes which
7
+ * skills/plugins auto-inject in the current project.
8
+ *
9
+ * Safety guarantees (org-in-a-box):
10
+ * 1. isProtectedSkill() from project-profile.mjs defines a NEVER-FILTER set
11
+ * covering construct personas, cx-* specialists, cross-cutting skills,
12
+ * role-domain namespaces (engineering:, product-management:, etc.), and
13
+ * Claude Code dev infrastructure. These are always kept enabled.
14
+ * 2. The filter is *additive recommendation* — disabled plugins remain on
15
+ * disk and can be called explicitly. We only remove them from automatic
16
+ * per-turn injection.
17
+ * 3. A construct-native manifest (.cx/skills-profile.json) records the
18
+ * decision so construct-mcp can read it at session start and surface
19
+ * what was filtered.
20
+ * 4. Never overwrite an existing `.claude/settings.json` key the user set
21
+ * manually — merge into disabledPlugins with de-dup.
22
+ */
23
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
24
+ import { homedir } from 'node:os';
25
+ import { dirname, join, resolve } from 'node:path';
26
+ import {
27
+ classifySkillRelevance,
28
+ detectProjectProfile,
29
+ enumerateInstalledSkills,
30
+ writeProfile,
31
+ } from './project-profile.mjs';
32
+
33
+ const SUPPORTED_HOSTS = new Set(['claude', 'opencode', 'codex', 'all']);
34
+
35
+ function readJsonSafe(path) {
36
+ try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return null; }
37
+ }
38
+
39
+ function writeJsonPretty(path, data) {
40
+ mkdirSync(dirname(path), { recursive: true });
41
+ writeFileSync(path, JSON.stringify(data, null, 2) + '\n', 'utf8');
42
+ }
43
+
44
+ function unionArrays(existing, incoming) {
45
+ const seen = new Set();
46
+ const result = [];
47
+ for (const arr of [existing, incoming]) {
48
+ for (const item of arr || []) {
49
+ if (seen.has(item)) continue;
50
+ seen.add(item);
51
+ result.push(item);
52
+ }
53
+ }
54
+ return result.sort();
55
+ }
56
+
57
+ /**
58
+ * Writes the construct-native project manifest to `<cwd>/.cx/skills-profile.json`.
59
+ * The authoritative record consumed by construct-mcp and any future per-host
60
+ * writers that want to re-derive the decision.
61
+ */
62
+ export function writeConstructManifest(cwd, profile, classification) {
63
+ const path = join(cwd, '.cx', 'skills-profile.json');
64
+ const payload = {
65
+ version: 1,
66
+ generatedAt: new Date().toISOString(),
67
+ profile: {
68
+ tags: profile.tags,
69
+ signals: profile.signals,
70
+ },
71
+ decision: {
72
+ relevant: classification.relevant,
73
+ irrelevant: classification.irrelevant,
74
+ unknown: classification.unknown,
75
+ protected: classification.protected || [],
76
+ },
77
+ // The "recommended disabled" list. Never includes protected skills.
78
+ // Hosts are expected to honor this as a scoping recommendation.
79
+ recommendedDisable: classification.irrelevant,
80
+ };
81
+ writeJsonPretty(path, payload);
82
+ return path;
83
+ }
84
+
85
+ /**
86
+ * Writes `<cwd>/.claude/construct-skills.json` — a construct-owned sidecar
87
+ * that records the recommended per-project scoping for Claude Code.
88
+ *
89
+ * Why a sidecar and not `settings.json`? Claude Code today only reads
90
+ * `permissions`, `hooks`, and `mcpServers` from settings.json. A
91
+ * `disabledPlugins` key would be ignored silently. Writing a sidecar is
92
+ * honest — it documents the recommendation without pretending the harness
93
+ * enforces it. The construct-mcp session-start path can read this sidecar
94
+ * and inject a "skills out of scope for this project" note.
95
+ *
96
+ * If Claude Code adds per-project plugin scoping in the future, the
97
+ * adapter will flip to writing the supported key(s) directly.
98
+ */
99
+ export function writeClaudeHostConfig(cwd, classification) {
100
+ const path = join(cwd, '.claude', 'construct-skills.json');
101
+ writeJsonPretty(path, {
102
+ $comment: 'Construct-owned sidecar. Claude Code does not currently honor project-level skill scoping; this is advisory. construct-mcp can read this to surface out-of-scope skills at session start.',
103
+ version: 1,
104
+ generatedAt: new Date().toISOString(),
105
+ source: '.cx/skills-profile.json',
106
+ recommendedDisable: classification.irrelevant,
107
+ protected: classification.protected || [],
108
+ });
109
+ return path;
110
+ }
111
+
112
+ /**
113
+ * Writes a Construct-owned OpenCode sidecar at `<cwd>/.opencode/construct-skills.json`.
114
+ *
115
+ * OpenCode will eagerly parse `<cwd>/opencode.json` as first-party config, so
116
+ * Construct must not write custom top-level keys there. The session-start
117
+ * adapter can read this sidecar and surface skill-scoping guidance without
118
+ * breaking OpenCode's schema validation.
119
+ */
120
+ export function writeOpenCodeHostConfig(cwd, classification) {
121
+ const path = join(cwd, '.opencode', 'construct-skills.json');
122
+ const existing = readJsonSafe(path) || {};
123
+ const currentDisabled = existing?.recommendedDisable || existing?.disabledSkills || [];
124
+ const disabledSkills = unionArrays(currentDisabled, classification.irrelevant);
125
+ writeJsonPretty(path, {
126
+ $comment: 'Construct-owned sidecar. OpenCode rejects unknown top-level opencode.json keys; construct-mcp reads .cx/skills-profile.json at session start.',
127
+ version: 1,
128
+ generatedAt: new Date().toISOString(),
129
+ source: '.cx/skills-profile.json',
130
+ recommendedDisable: disabledSkills,
131
+ disabledSkills,
132
+ protected: classification.protected || [],
133
+ });
134
+ return path;
135
+ }
136
+
137
+ /**
138
+ * Writes per-project Codex config hints. Codex config is TOML; to avoid a TOML
139
+ * dependency we write a sidecar JSON file instead — `.codex/skills-profile.json` —
140
+ * that the Codex adapter can read at session start. Users who want the filter
141
+ * baked into codex config itself can run `construct sync` after this.
142
+ */
143
+ export function writeCodexHostConfig(cwd, classification) {
144
+ const path = join(cwd, '.codex', 'skills-profile.json');
145
+ writeJsonPretty(path, {
146
+ version: 1,
147
+ generatedAt: new Date().toISOString(),
148
+ disabledSkills: classification.irrelevant,
149
+ });
150
+ return path;
151
+ }
152
+
153
+ const HOST_WRITERS = {
154
+ claude: writeClaudeHostConfig,
155
+ opencode: writeOpenCodeHostConfig,
156
+ codex: writeCodexHostConfig,
157
+ };
158
+
159
+ function parseArgs(args) {
160
+ const options = { host: null, dryRun: false, cwd: process.cwd(), yes: false };
161
+ for (let i = 0; i < args.length; i += 1) {
162
+ const arg = args[i];
163
+ if (arg === '--dry-run' || arg === '-n') options.dryRun = true;
164
+ else if (arg === '--yes' || arg === '-y') options.yes = true;
165
+ else if (arg === '--help' || arg === '-h') options.help = true;
166
+ else if (arg === '--host') options.host = args[++i];
167
+ else if (arg.startsWith('--host=')) options.host = arg.slice(7);
168
+ else if (arg === '--cwd') options.cwd = args[++i];
169
+ else if (arg.startsWith('--cwd=')) options.cwd = arg.slice(6);
170
+ }
171
+ return options;
172
+ }
173
+
174
+ export async function runSkillsApplyCli(args = []) {
175
+ const options = parseArgs(args);
176
+
177
+ if (options.help) {
178
+ console.log(`Usage: construct skills apply --host <name> [options]
179
+
180
+ Applies a per-project skill filter based on the detected project profile.
181
+ Writes host-specific config that scopes which skills auto-inject for this
182
+ project, reducing per-turn context bloat without affecting other repos.
183
+
184
+ Options:
185
+ --host <name> claude | opencode | codex | all (required)
186
+ --cwd <path> Target directory (default: CWD)
187
+ --dry-run, -n Preview the filter without writing any files
188
+ --yes, -y Skip confirmation prompt
189
+ -h, --help Show this message
190
+
191
+ Safety: skills protected by rules/common/doc-ownership.md and Construct's
192
+ cx-* specialist infrastructure are NEVER filtered. The filter is an
193
+ auto-injection scope — disabled skills remain callable via get_skill.
194
+
195
+ The .cx/skills-profile.json manifest records the decision for audit.
196
+ `);
197
+ return;
198
+ }
199
+
200
+ if (!options.host) {
201
+ console.error('Error: --host <claude|opencode|codex|all> is required.');
202
+ console.error('Run with --help for usage.');
203
+ process.exit(1);
204
+ }
205
+ if (!SUPPORTED_HOSTS.has(options.host)) {
206
+ console.error(`Error: unknown host "${options.host}". Supported: claude, opencode, codex, all.`);
207
+ process.exit(1);
208
+ }
209
+
210
+ const cwd = resolve(options.cwd);
211
+ const profile = detectProjectProfile(cwd);
212
+
213
+ if (profile.tags.length === 0) {
214
+ console.log('No tech-stack signals detected in this directory.');
215
+ console.log('Skipping filter generation — an empty profile would disable nothing useful.');
216
+ return;
217
+ }
218
+
219
+ const installed = enumerateInstalledSkills(homedir());
220
+ const classification = classifySkillRelevance(profile, installed);
221
+
222
+ console.log('Project profile');
223
+ console.log('═══════════════');
224
+ console.log(` Detected: ${profile.tags.join(', ')}`);
225
+ console.log(` Host: ${options.host}`);
226
+ console.log('');
227
+ console.log(` Installed skills: ${installed.length}`);
228
+ console.log(` Protected: ${classification.protected.length} (never filtered)`);
229
+ console.log(` Relevant: ${classification.relevant.length}`);
230
+ console.log(` Unmapped: ${classification.unknown.length}`);
231
+ console.log(` Will be disabled: ${classification.irrelevant.length}`);
232
+ console.log('');
233
+
234
+ if (classification.irrelevant.length === 0) {
235
+ console.log('Nothing to disable — exiting.');
236
+ return;
237
+ }
238
+
239
+ console.log('Skills that will be disabled for this project:');
240
+ console.log(classification.irrelevant.map((s) => ` - ${s}`).join('\n'));
241
+ console.log('');
242
+ console.log('Safeguards applied:');
243
+ console.log(` - ${classification.protected.length} skills protected by construct safeguards`);
244
+ console.log(` - ${classification.unknown.length} unmapped skills kept as relevant by default`);
245
+ console.log(` - Disabled skills remain on disk; callable via get_skill on demand`);
246
+ console.log(` - cx-* specialists use construct-mcp get_skill (never host injection)`);
247
+ console.log('');
248
+
249
+ if (options.dryRun) {
250
+ console.log('Dry run — no files written. Use without --dry-run to apply.');
251
+ return;
252
+ }
253
+
254
+ // Always write the construct manifest first — it's the authoritative record.
255
+ const manifestPath = writeConstructManifest(cwd, profile, classification);
256
+ writeProfile(profile, cwd);
257
+ console.log(`✓ Manifest: ${manifestPath}`);
258
+
259
+ const hostsToWrite = options.host === 'all' ? ['claude', 'opencode', 'codex'] : [options.host];
260
+ for (const host of hostsToWrite) {
261
+ const writer = HOST_WRITERS[host];
262
+ if (!writer) continue;
263
+ try {
264
+ const path = writer(cwd, classification);
265
+ console.log(`✓ ${host.padEnd(8)}: ${path}`);
266
+ } catch (err) {
267
+ console.error(`✗ ${host.padEnd(8)}: ${err?.message || 'write failed'}`);
268
+ }
269
+ }
270
+ console.log('');
271
+ console.log('Manifest + per-host sidecars written. Host support varies:');
272
+ console.log(' - Claude Code: sidecar at .claude/construct-skills.json (advisory today;');
273
+ console.log(' construct-mcp can read it at session start).');
274
+ console.log(' - OpenCode: sidecar at .opencode/construct-skills.json');
275
+ console.log(' (construct-owned metadata; avoids invalid opencode.json keys).');
276
+ console.log(' - Codex: sidecar at .codex/skills-profile.json (adapter reads at startup).');
277
+ console.log('');
278
+ console.log('The authoritative record is .cx/skills-profile.json (version-controllable).');
279
+ console.log('To revert: delete the files under .claude/, .opencode/, or .codex/ as appropriate.');
280
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * lib/skills-scope.mjs — CLI surface for project-profile-driven skill scoping.
3
+ *
4
+ * Powers `construct skills scope` (and, later, auto-generation of per-host
5
+ * skill filters). The detection layer is in lib/project-profile.mjs and is
6
+ * host-agnostic by design — this file composes it into a reportable workflow
7
+ * and will later wire per-host filter writers.
8
+ */
9
+ import { homedir } from 'node:os';
10
+ import {
11
+ classifySkillRelevance,
12
+ detectProjectProfile,
13
+ enumerateInstalledSkills,
14
+ writeProfile,
15
+ } from './project-profile.mjs';
16
+
17
+ function formatList(list, { limit = 20 } = {}) {
18
+ if (list.length === 0) return ' (none)';
19
+ const shown = list.slice(0, limit);
20
+ const rest = list.length > limit ? `\n ... and ${list.length - limit} more` : '';
21
+ return shown.map((name) => ` - ${name}`).join('\n') + rest;
22
+ }
23
+
24
+ export async function runSkillsScopeCli(args = []) {
25
+ const flags = new Set();
26
+ const options = { cwd: process.cwd() };
27
+ for (let i = 0; i < args.length; i += 1) {
28
+ const arg = args[i];
29
+ if (arg === '--json') flags.add('json');
30
+ else if (arg === '--write') flags.add('write');
31
+ else if (arg === '--no-write') flags.add('no-write');
32
+ else if (arg === '--help' || arg === '-h') flags.add('help');
33
+ else if (arg === '--cwd') options.cwd = args[++i];
34
+ else if (arg.startsWith('--cwd=')) options.cwd = arg.slice(6);
35
+ }
36
+
37
+ if (flags.has('help')) {
38
+ console.log(`Usage: construct skills scope [options]
39
+
40
+ Detects the project's tech stack from filesystem signals (package.json,
41
+ pyproject.toml, go.mod, Cargo.toml, etc.) and reports which installed
42
+ skills are relevant vs irrelevant to the current repo.
43
+
44
+ Writes .cx/project-profile.json by default (disable with --no-write).
45
+
46
+ Options:
47
+ --cwd <path> Target directory (defaults to CWD)
48
+ --json Emit the profile + classification as JSON
49
+ --no-write Skip writing .cx/project-profile.json
50
+ --write Force write (default behavior)
51
+ -h, --help Show this message
52
+
53
+ The detection layer is host-agnostic. A future pass can use the profile to
54
+ generate per-host skill filters (.claude/ sidecars, .opencode/ sidecars, etc.).
55
+ `);
56
+ return;
57
+ }
58
+
59
+ const profile = detectProjectProfile(options.cwd);
60
+ const installed = enumerateInstalledSkills(homedir());
61
+ const classification = classifySkillRelevance(profile, installed);
62
+
63
+ let profilePath = null;
64
+ if (!flags.has('no-write')) {
65
+ try { profilePath = writeProfile(profile, options.cwd); } catch { /* best effort */ }
66
+ }
67
+
68
+ if (flags.has('json')) {
69
+ console.log(JSON.stringify({
70
+ profile,
71
+ classification,
72
+ installedCount: installed.length,
73
+ profilePath,
74
+ }, null, 2));
75
+ return;
76
+ }
77
+
78
+ const irrelevantRatio = installed.length === 0 ? 0 :
79
+ Math.round((classification.irrelevant.length / installed.length) * 100);
80
+
81
+ console.log('Project profile');
82
+ console.log('═══════════════');
83
+ console.log(` Root ${profile.root}`);
84
+ console.log(` Detected ${profile.tags.length ? profile.tags.join(', ') : '(no signals matched)'}`);
85
+ console.log(` Signals ${profile.signals.length ? profile.signals.join(', ') : '(none)'}`);
86
+ if (profilePath) console.log(` Saved ${profilePath}`);
87
+ console.log('');
88
+
89
+ console.log('Installed skills classification');
90
+ console.log('───────────────────────────────');
91
+ console.log(` Total installed: ${installed.length}`);
92
+ console.log(` Relevant: ${classification.relevant.length}`);
93
+ console.log(` Irrelevant: ${classification.irrelevant.length} (${irrelevantRatio}% of total)`);
94
+ console.log(` Unmapped: ${classification.unknown.length} (default: treat as relevant)`);
95
+ console.log('');
96
+
97
+ if (classification.irrelevant.length > 0) {
98
+ console.log('Irrelevant skills for this project:');
99
+ console.log(formatList(classification.irrelevant));
100
+ console.log('');
101
+ console.log('These are loaded on every turn by the host but do not match this');
102
+ console.log('project\'s tech stack. To reduce per-turn context footprint:');
103
+ console.log('');
104
+ console.log(' - Claude Code: edit ~/.claude/settings.json or per-project .claude/');
105
+ console.log(' plugins.json to disable plugins you don\'t need in this repo.');
106
+ console.log(' - OpenCode: edit ~/.config/opencode/opencode.json');
107
+ console.log(' - Codex: edit ~/.codex/agents/ filters');
108
+ console.log('');
109
+ console.log('Future: `construct skills apply --host <name>` will generate these');
110
+ console.log('filter configs automatically from the profile above.');
111
+ }
112
+
113
+ if (classification.unknown.length > 0 && classification.unknown.length < 40) {
114
+ console.log('');
115
+ console.log(`Unmapped skills (no relevance rule — default kept):`);
116
+ console.log(formatList(classification.unknown, { limit: 10 }));
117
+ }
118
+ }