@geraldmaron/construct 1.0.0 → 1.0.2

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 +9 -6
  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 +1000 -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 +523 -36
  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,315 @@
1
+ /**
2
+ * lib/mcp/tools/telemetry.mjs — Telemetry MCP tools: trace/score, session usage, efficiency snapshot.
3
+ *
4
+ * Exposes cxTrace, cxScore, sessionUsage, and efficiencySnapshot.
5
+ * Requires ROOT_DIR injected via opts. Telemetry credentials must be in env.
6
+ */
7
+ import { join, resolve } from 'node:path';
8
+ import { homedir } from 'node:os';
9
+ import { readFileSync, existsSync } from 'node:fs';
10
+ import { isAvailable as telemetryAvailable } from '../../telemetry/backends/remote.mjs';
11
+ import { summarizePromptComposition } from '../../prompt-composer.js';
12
+ import { enrichMetadataWithPrompt } from '../../prompt-metadata.mjs';
13
+ import { readCurrentModels, resolveExecutionContractModelMetadata, selectModelTierForWorkCategory } from '../../model-router.mjs';
14
+ import { routeRequest } from '../../orchestration-policy.mjs';
15
+ import { loadWorkflow } from '../../workflow-state.mjs';
16
+ import { buildStatus } from '../../status.mjs';
17
+ import { readEfficiencyLog, buildCompactEfficiencyDigest } from '../../efficiency.mjs';
18
+ import { addObservation } from '../../observation-store.mjs';
19
+ // Local mock ingest client for fallback when ingestion service is unavailable
20
+ import { loadConstructEnv } from '../../env-config.mjs';
21
+
22
+ // Load config.env once at module init so config.env values win over shell env
23
+ // (shell env may have stale/truncated credentials from earlier sessions)
24
+ const CONF_ENV = loadConstructEnv({ warn: false });
25
+
26
+ function readJSON(filePath) {
27
+ if (!existsSync(filePath)) return null;
28
+ try {
29
+ return JSON.parse(readFileSync(filePath, 'utf8'));
30
+ } catch {
31
+ return null;
32
+ }
33
+ }
34
+
35
+ import { execSync as _execSync } from 'node:child_process';
36
+
37
+ // Mock ingest client for fallback to direct API when the real client is not available.
38
+
39
+ function getOrCreateIngestClient() {
40
+ return {
41
+ available: false,
42
+ trace: () => {}
43
+ };
44
+ }
45
+
46
+ function resolveReleaseTag(cwd) {
47
+ try {
48
+ return _execSync('git rev-parse --short HEAD', { stdio: 'pipe', cwd, timeout: 2000 }).toString().trim() || undefined;
49
+ } catch {
50
+ return undefined;
51
+ }
52
+ }
53
+
54
+ function telemetryHeaders() {
55
+ const key = CONF_ENV.CONSTRUCT_TELEMETRY_PUBLIC_KEY ?? process.env.CONSTRUCT_TELEMETRY_PUBLIC_KEY;
56
+ const secret = CONF_ENV.CONSTRUCT_TELEMETRY_SECRET_KEY ?? process.env.CONSTRUCT_TELEMETRY_SECRET_KEY;
57
+ if (!key || !secret) throw new Error('CONSTRUCT_TELEMETRY_PUBLIC_KEY and CONSTRUCT_TELEMETRY_SECRET_KEY must be set.');
58
+ return {
59
+ Authorization: `Basic ${Buffer.from(`${key}:${secret}`).toString('base64')}`,
60
+ 'Content-Type': 'application/json',
61
+ };
62
+ }
63
+
64
+ function telemetryBaseUrl() {
65
+ return (CONF_ENV.CONSTRUCT_TELEMETRY_URL ?? process.env.CONSTRUCT_TELEMETRY_URL ?? '').replace(/\/$/, '');
66
+ }
67
+
68
+ function resolveSessionContext() {
69
+ const cwd = process.cwd();
70
+ let workflowId;
71
+ let workflowPhase;
72
+ let workflowOwner;
73
+ try {
74
+ const wf = loadWorkflow(cwd);
75
+ if (wf) {
76
+ workflowId = wf.id;
77
+ workflowPhase = wf.phase;
78
+ const active = (wf.tasks || []).find((t) => t.status === 'in-progress' || t.status === 'in_progress');
79
+ if (active) workflowOwner = active.owner;
80
+ }
81
+ } catch { /* best effort */ }
82
+ const sessionId = process.env.CLAUDE_SESSION_ID
83
+ || process.env.CX_SESSION_ID
84
+ || process.env.OPENCODE_SESSION_ID
85
+ || workflowId;
86
+ const userId = process.env.USER || process.env.USERNAME || process.env.LOGNAME;
87
+ return { cwd, sessionId, userId, release: resolveReleaseTag(cwd), workflowPhase, workflowOwner, workflowId };
88
+ }
89
+
90
+ export async function cxTrace(args, { ROOT_DIR }) {
91
+ const ctx = resolveSessionContext();
92
+ const registry = readJSON(join(ROOT_DIR, 'agents', 'registry.json')) ?? {};
93
+ const registryModels = registry.models ?? {};
94
+ const currentModels = readCurrentModels(join(ROOT_DIR, '.env'), registryModels, process.env);
95
+ const route = typeof args.input === 'string' ? routeRequest({ request: args.input }) : null;
96
+ const executionContractModel = resolveExecutionContractModelMetadata({
97
+ envValues: currentModels,
98
+ registryModels,
99
+ requestedTier: selectModelTierForWorkCategory(route?.workCategory),
100
+ workCategory: route?.workCategory || null,
101
+ });
102
+ const runtimePromptMetadata = summarizePromptComposition(args.name, {
103
+ rootDir: ROOT_DIR,
104
+ request: typeof args.input === 'string' ? args.input : '',
105
+ route,
106
+ registryModels,
107
+ envValues: currentModels,
108
+ executionContractModel,
109
+ hostConstraints: {
110
+ runtime: 'mcp',
111
+ providerAgnostic: true,
112
+ telemetryBackend: 'telemetry',
113
+ },
114
+ });
115
+ const metadata = enrichMetadataWithPrompt(args.name, {
116
+ ...(args.metadata && typeof args.metadata === 'object' ? args.metadata : {}),
117
+ ...runtimePromptMetadata,
118
+ // Extract model metadata from executionContractModel for backward compatibility
119
+ ...(runtimePromptMetadata.executionContractModel ? {
120
+ selectedTier: runtimePromptMetadata.executionContractModel.selectedTier,
121
+ selectedModel: runtimePromptMetadata.executionContractModel.selectedModel,
122
+ selectedModelSource: runtimePromptMetadata.executionContractModel.selectedModelSource,
123
+ tiers: runtimePromptMetadata.executionContractModel.tiers,
124
+ } : {}),
125
+ workflowId: ctx.workflowId,
126
+ workflowPhase: ctx.workflowPhase,
127
+ workflowOwner: ctx.workflowOwner,
128
+ }, { rootDir: ROOT_DIR });
129
+ const traceId = args.id ?? crypto.randomUUID();
130
+ try {
131
+ const available = await telemetryAvailable();
132
+ if (!available) return { ok: false, error: 'Telemetry credentials not configured', id: traceId };
133
+ const teamId = args.metadata?.teamId ?? metadata.teamId;
134
+ const workCategoryValue = route?.workCategory ?? (typeof args.input === 'string' ? classifyWorkCategory({ request: args.input }) : null);
135
+ const body = {
136
+ id: traceId,
137
+ name: args.name,
138
+ // Ensure workCategory is set, falling back to direct classification if needed
139
+ workCategory: workCategoryValue,
140
+
141
+ metadata: {
142
+ ...metadata,
143
+ agentName: args.name,
144
+ goal: typeof args.input === 'string' ? args.input : JSON.stringify(args.input ?? ''),
145
+ teamId,
146
+ traceSource: 'mcp',
147
+ workCategory: workCategoryValue,
148
+ ...(args.output ? { hasOutput: true } : {}),
149
+ },
150
+ tags: [args.name, teamId].filter(Boolean),
151
+ userId: ctx.userId,
152
+ sessionId: args.session_id || ctx.sessionId,
153
+ input: args.input,
154
+ output: args.output, // Include output if provided — most callers pass it later via cx_score, but some pass it eagerly
155
+ timestamp: args.timestamp ?? new Date().toISOString(),
156
+ release: ctx.release,
157
+ };
158
+
159
+ // Add version to metadata for test compatibility
160
+ body.metadata.version = 'v1';
161
+
162
+ // Use ingestion batch for creation (handles large payloads better than direct API)
163
+ const ingestClient = getOrCreateIngestClient();
164
+ if (ingestClient?.available) {
165
+ ingestClient.trace(body);
166
+ return { ok: true, id: traceId };
167
+ }
168
+
169
+ // Fallback: direct API call
170
+ const res = await fetch(`${telemetryBaseUrl()}/api/public/traces`, {
171
+ method: 'POST',
172
+ headers: telemetryHeaders(),
173
+ body: JSON.stringify(body),
174
+ });
175
+ if (!res.ok) {
176
+ const text = await res.text().catch(() => '');
177
+ return { ok: false, error: `Telemetry API error ${res.status}: ${text}`, id: traceId };
178
+ }
179
+ return { ok: true, id: traceId };
180
+ } catch (err) {
181
+ return { ok: false, error: err.message, id: traceId };
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Update an existing trace with output and metadata.
187
+ * Call this when a trace was created early but the result is only known later.
188
+ * Uses the telemetry PATCH endpoint directly since trace updates are infrequent.
189
+ */
190
+ export async function cxTraceUpdate(args) {
191
+ const traceId = args.trace_id ?? '';
192
+ const output = args.output;
193
+ const metadata = args.metadata;
194
+
195
+ try {
196
+ const available = await telemetryAvailable();
197
+ if (!available) return { ok: false, error: 'Telemetry credentials not configured' };
198
+
199
+ const res = await fetch(`${telemetryBaseUrl()}/api/public/traces/${traceId}`, {
200
+ method: 'PATCH',
201
+ headers: telemetryHeaders(),
202
+ body: JSON.stringify({
203
+ output,
204
+ metadata: {
205
+ ...(metadata && typeof metadata === 'object' ? metadata : {}),
206
+ traceUpdatedAt: new Date().toISOString(),
207
+ },
208
+ }),
209
+ });
210
+
211
+ if (!res.ok) {
212
+ const text = await res.text().catch(() => '');
213
+ return { ok: false, error: `Telemetry PATCH error ${res.status}: ${text}` };
214
+ }
215
+
216
+ // Also record as observation for local learning
217
+ if (output || metadata) {
218
+ const rootDir = homedir();
219
+ addObservation(rootDir, {
220
+ role: 'construct',
221
+ category: 'insight',
222
+ summary: `Trace ${traceId.slice(0, 8)} updated with output`,
223
+ content: `traceId: ${traceId}\nhasOutput: ${Boolean(output)}\nmetadata: ${metadata ? Object.keys(metadata).join(', ') : 'none'}`,
224
+ tags: ['trace-update', 'telemetry'],
225
+ confidence: 0.9,
226
+ source: 'cx_trace_update',
227
+ });
228
+ }
229
+
230
+ return { ok: true, traceId };
231
+ } catch (err) {
232
+ return { ok: false, error: err.message };
233
+ }
234
+ }
235
+
236
+ // Quality score thresholds for observation recording
237
+ const SCORE_POOR_THRESHOLD = 0.5; // below this → record anti-pattern
238
+ const SCORE_GOOD_THRESHOLD = 0.85; // at or above this → record positive pattern
239
+
240
+ export async function cxScore(args) {
241
+ const traceId = args.trace_id ?? '';
242
+ try {
243
+ const available = await telemetryAvailable();
244
+ if (!available) return { ok: false, error: 'Telemetry credentials not configured' };
245
+ const body = {
246
+ id: crypto.randomUUID(),
247
+ traceId,
248
+ name: args.name ?? 'quality',
249
+ value: args.value,
250
+ dataType: 'NUMERIC',
251
+ comment: args.comment,
252
+ };
253
+ const res = await fetch(`${telemetryBaseUrl()}/api/public/scores`, {
254
+ method: 'POST',
255
+ headers: telemetryHeaders(),
256
+ body: JSON.stringify(body),
257
+ });
258
+ if (!res.ok) {
259
+ const text = await res.text().catch(() => '');
260
+ return { ok: false, error: `Telemetry API error ${res.status}: ${text}` };
261
+ }
262
+
263
+ // Feed score back into the local observation store so future agents learn from it.
264
+ // Low scores generate anti-pattern observations; high scores reinforce positive patterns.
265
+ const numericValue = Number(args.value);
266
+ if (Number.isFinite(numericValue)) {
267
+ const rootDir = homedir();
268
+ const agentName = args.name && args.name !== 'quality' ? args.name : null;
269
+ const comment = args.comment ? String(args.comment) : '';
270
+
271
+ if (numericValue < SCORE_POOR_THRESHOLD) {
272
+ addObservation(rootDir, {
273
+ role: agentName ?? 'construct',
274
+ category: 'anti-pattern',
275
+ summary: `Low quality score (${numericValue.toFixed(2)}) on trace ${traceId.slice(0, 8)}${comment ? `: ${comment}` : ''}`,
276
+ content: `Trace: ${traceId}\nScore: ${numericValue}\nComment: ${comment || 'none'}\nAgent: ${agentName ?? 'unknown'}\nRecorded at: ${new Date().toISOString()}`,
277
+ tags: ['quality-score', 'low-score', agentName].filter(Boolean),
278
+ confidence: 0.8,
279
+ source: 'cx_score',
280
+ });
281
+ } else if (numericValue >= SCORE_GOOD_THRESHOLD) {
282
+ addObservation(rootDir, {
283
+ role: agentName ?? 'construct',
284
+ category: 'pattern',
285
+ summary: `High quality score (${numericValue.toFixed(2)}) on trace ${traceId.slice(0, 8)}${comment ? `: ${comment}` : ''}`,
286
+ content: `Trace: ${traceId}\nScore: ${numericValue}\nComment: ${comment || 'none'}\nAgent: ${agentName ?? 'unknown'}\nRecorded at: ${new Date().toISOString()}`,
287
+ tags: ['quality-score', 'high-score', agentName].filter(Boolean),
288
+ confidence: 0.75,
289
+ source: 'cx_score',
290
+ });
291
+ }
292
+ }
293
+
294
+ return { ok: true, traceId };
295
+ } catch (err) {
296
+ return { ok: false, error: err.message };
297
+ }
298
+ }
299
+
300
+ export async function sessionUsage(args, { ROOT_DIR }) {
301
+ const cwd = args.cwd ? resolve(String(args.cwd)) : process.cwd();
302
+ const homeDir = args.home_dir ? resolve(args.home_dir) : homedir();
303
+ const status = await buildStatus({ rootDir: ROOT_DIR, cwd, homeDir, env: process.env });
304
+ return {
305
+ cwd,
306
+ sessionUsage: status.sessionUsage,
307
+ };
308
+ }
309
+
310
+ export function efficiencySnapshot(args) {
311
+ const homeDir = args.home_dir ? resolve(String(args.home_dir)) : homedir();
312
+ const stats = readEfficiencyLog(homeDir);
313
+ const digest = buildCompactEfficiencyDigest(stats);
314
+ return digest || { status: 'unavailable', summary: 'No read-efficiency data recorded yet' };
315
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * lib/mcp/tools/workflow.mjs — Workflow MCP tools: status, init, add/update tasks, validate, and import plan.
3
+ *
4
+ * All functions are synchronous. Wraps lib/workflow-state.mjs.
5
+ * workflowStatus is located in project.mjs because it also builds publicHealth context.
6
+ */
7
+ import { resolve } from 'node:path';
8
+ import {
9
+ addTask,
10
+ addTaskFromIntent,
11
+ addTasksFromPlan,
12
+ createNeedsMainInputPacket,
13
+ initWorkflow,
14
+ loadWorkflow,
15
+ summarizeWorkflow,
16
+ updateTask,
17
+ validateWorkflowState,
18
+ } from '../../workflow-state.mjs';
19
+
20
+ export function workflowInit(args) {
21
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
22
+ const title = args.title || 'Untitled workflow';
23
+ const { workflow, created } = initWorkflow(cwd, title, args.spec_ref ?? null);
24
+ return { cwd, created, workflow, summary: summarizeWorkflow(workflow) };
25
+ }
26
+
27
+ export function workflowAddTask(args) {
28
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
29
+ if (args.request) {
30
+ const workflow = addTaskFromIntent(cwd, args.request, {
31
+ key: args.key,
32
+ title: args.title,
33
+ phase: args.phase,
34
+ owner: args.owner,
35
+ files: args.files,
36
+ readFirst: args.readFirst,
37
+ doNotChange: args.doNotChange,
38
+ acceptanceCriteria: args.acceptanceCriteria,
39
+ verification: args.verification,
40
+ overlays: args.overlays,
41
+ challengeRequired: args.challengeRequired,
42
+ challengeStatus: args.challengeStatus,
43
+ tokenBudget: args.tokenBudget,
44
+ status: args.status,
45
+ });
46
+ if (!workflow) return { ok: true, skipped: true, reason: 'immediate-track' };
47
+ return { cwd, workflow, summary: summarizeWorkflow(workflow), source: 'intent' };
48
+ }
49
+ const workflow = addTask(cwd, {
50
+ key: args.key,
51
+ title: args.title,
52
+ phase: args.phase,
53
+ owner: args.owner,
54
+ files: args.files,
55
+ readFirst: args.readFirst,
56
+ doNotChange: args.doNotChange,
57
+ acceptanceCriteria: args.acceptanceCriteria,
58
+ verification: args.verification,
59
+ dependsOn: args.dependsOn,
60
+ overlays: args.overlays,
61
+ challengeRequired: args.challengeRequired,
62
+ challengeStatus: args.challengeStatus,
63
+ });
64
+ return { cwd, workflow, summary: summarizeWorkflow(workflow), source: 'manual' };
65
+ }
66
+
67
+ export function workflowUpdateTask(args) {
68
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
69
+ const workflow = updateTask(cwd, args.key, {
70
+ status: args.status,
71
+ owner: args.owner,
72
+ phase: args.phase,
73
+ note: args.note,
74
+ verification: args.verification,
75
+ overlays: args.overlays,
76
+ challengeRequired: args.challengeRequired,
77
+ challengeStatus: args.challengeStatus,
78
+ });
79
+ return { cwd, workflow, summary: summarizeWorkflow(workflow) };
80
+ }
81
+
82
+ export function workflowNeedsMainInput(args) {
83
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
84
+ const packet = createNeedsMainInputPacket(args);
85
+ const workflow = updateTask(cwd, args.taskKey, {
86
+ status: 'blocked_needs_user',
87
+ note: `${packet.worker}: ${packet.blocker} | question: ${packet.question}`,
88
+ });
89
+ return { cwd, packet, workflow, summary: summarizeWorkflow(workflow) };
90
+ }
91
+
92
+ export function workflowValidate(args) {
93
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
94
+ const workflow = loadWorkflow(cwd);
95
+ const result = validateWorkflowState(workflow);
96
+ return { cwd, ...result };
97
+ }
98
+
99
+ export function workflowImportPlan(args) {
100
+ const cwd = args.cwd ? resolve(args.cwd) : process.cwd();
101
+ const markdown = args.markdown ?? '';
102
+ const { workflow, count } = addTasksFromPlan(cwd, markdown, {
103
+ phase: args.phase,
104
+ owner: args.owner,
105
+ readFirst: Array.isArray(args.readFirst) ? args.readFirst : undefined,
106
+ doNotChange: Array.isArray(args.doNotChange) ? args.doNotChange : undefined,
107
+ acceptanceCriteria: Array.isArray(args.acceptanceCriteria) ? args.acceptanceCriteria : undefined,
108
+ workflowTitle: args.title,
109
+ specRef: args.spec_ref,
110
+ });
111
+ return { cwd, count, workflow, summary: summarizeWorkflow(workflow) };
112
+ }
@@ -14,6 +14,11 @@
14
14
  ],
15
15
  "env": {},
16
16
  "requiredEnv": [],
17
+ "hostSupport": {
18
+ "claude": { "mode": "managed" },
19
+ "opencode": { "mode": "managed" },
20
+ "codex": { "mode": "managed" }
21
+ },
17
22
  "usedBy": [
18
23
  "cx-docs-researcher",
19
24
  "cx-engineer",
@@ -34,6 +39,11 @@
34
39
  ],
35
40
  "env": {},
36
41
  "requiredEnv": [],
42
+ "hostSupport": {
43
+ "claude": { "mode": "managed" },
44
+ "opencode": { "mode": "managed" },
45
+ "codex": { "mode": "managed" }
46
+ },
37
47
  "usedBy": [
38
48
  "construct",
39
49
  "cx-architect",
@@ -45,7 +55,7 @@
45
55
  "id": "memory",
46
56
  "name": "Memory",
47
57
  "category": "optional",
48
- "description": "Persistent cross-session knowledge graph. Agents remember decisions and findings across sessions.",
58
+ "description": "cass-memory over HTTP. Persistent cross-session and cross-agent memory for decisions, findings, and handoffs.",
49
59
  "type": "url",
50
60
  "url": "http://127.0.0.1:8765/",
51
61
  "env": {},
@@ -54,12 +64,18 @@
54
64
  "auto",
55
65
  "manual"
56
66
  ],
67
+ "hostSupport": {
68
+ "claude": { "mode": "unsupported", "label": "construct-mcp (project .mcp.json)" },
69
+ "opencode": { "mode": "unsupported", "label": "construct-mcp (stdio)" },
70
+ "codex": { "mode": "unsupported", "label": "construct-mcp / local observation tools" }
71
+ },
72
+ "setupNote": "Claude Code and Codex reject the cass-memory HTTP endpoint because `cm serve` skips the MCP `initialize` handshake. On Claude, memory tools (memory_search, memory_add_observations, memory_recent, memory_create_entities) are exposed through the project-local construct-mcp stdio server in .mcp.json. OpenCode does not support the cass-memory HTTP endpoint (SSE transport fails with 405) — use construct-mcp stdio server instead, which wraps memory tools correctly.",
57
73
  "usedBy": [
58
74
  "construct",
59
75
  "cx-docs-keeper",
60
76
  "cx-researcher"
61
77
  ],
62
- "degradedMessage": "No cross-session memory. Each session starts fresh with no prior context."
78
+ "degradedMessage": "No cass-memory service. Each session starts fresh with no prior context or shared cross-agent memory."
63
79
  },
64
80
  {
65
81
  "id": "playwright",
@@ -74,6 +90,11 @@
74
90
  ],
75
91
  "env": {},
76
92
  "requiredEnv": [],
93
+ "hostSupport": {
94
+ "claude": { "mode": "managed" },
95
+ "opencode": { "mode": "managed" },
96
+ "codex": { "mode": "managed" }
97
+ },
77
98
  "usedBy": [
78
99
  "construct",
79
100
  "cx-qa",
@@ -84,6 +105,7 @@
84
105
  {
85
106
  "id": "github",
86
107
  "name": "GitHub",
108
+ "aliases": ["github-mcp", "github-mcp-server"],
87
109
  "category": "optional",
88
110
  "description": "GitHub API: issues, PRs, code search, repository operations.",
89
111
  "type": "url",
@@ -99,8 +121,13 @@
99
121
  "auto",
100
122
  "manual"
101
123
  ],
124
+ "hostSupport": {
125
+ "claude": { "mode": "managed" },
126
+ "opencode": { "mode": "managed" },
127
+ "codex": { "mode": "plugin", "plugin": "github@openai-curated", "label": "Codex Plugin" }
128
+ },
102
129
  "setupUrl": null,
103
- "setupNote": "Run 'gh auth login' to authenticate via browser, then re-run 'construct mcp add github'. The token is sourced from the gh CLI automatically.",
130
+ "setupNote": "Run 'gh auth login' to authenticate via browser, then re-run 'construct mcp add github'. Construct wires Claude Code and OpenCode directly. In Codex, use the built-in GitHub plugin/app path instead of a standalone GitHub MCP server.",
104
131
  "usedBy": [
105
132
  "construct",
106
133
  "cx-engineer",
@@ -112,6 +139,7 @@
112
139
  {
113
140
  "id": "atlassian",
114
141
  "name": "Atlassian (Jira + Confluence)",
142
+ "aliases": ["atlassian-mcp-server", "atlassian-mcp"],
115
143
  "category": "integration",
116
144
  "description": "Jira issue tracking and Confluence wiki access via Atlassian's official remote MCP server. OAuth is handled by each MCP client.",
117
145
  "type": "url",
@@ -121,6 +149,11 @@
121
149
  "setupModes": [
122
150
  "auto"
123
151
  ],
152
+ "hostSupport": {
153
+ "claude": { "mode": "managed" },
154
+ "opencode": { "mode": "managed" },
155
+ "codex": { "mode": "managed" }
156
+ },
124
157
  "setupNote": "Uses Atlassian's official remote MCP server with OAuth 2.1. Browser auth prompt appears on first use. Requires a Rovo license on your Atlassian account.",
125
158
  "usedBy": [
126
159
  "cx-product-manager",
@@ -133,6 +166,7 @@
133
166
  {
134
167
  "id": "linear",
135
168
  "name": "Linear",
169
+ "aliases": ["linear-mcp", "linear-mcp-server"],
136
170
  "category": "integration",
137
171
  "description": "Linear issue tracking — create issues, update status, search projects.",
138
172
  "package": "@linear/mcp-server",
@@ -150,6 +184,11 @@
150
184
  "setupModes": [
151
185
  "manual"
152
186
  ],
187
+ "hostSupport": {
188
+ "claude": { "mode": "managed" },
189
+ "opencode": { "mode": "managed" },
190
+ "codex": { "mode": "managed" }
191
+ },
153
192
  "setupUrl": "https://linear.app/settings/api",
154
193
  "setupNote": "Generate a personal API key at linear.app/settings/api.",
155
194
  "usedBy": [
@@ -162,6 +201,7 @@
162
201
  {
163
202
  "id": "slack",
164
203
  "name": "Slack",
204
+ "aliases": ["slack-mcp", "slack-mcp-server"],
165
205
  "category": "integration",
166
206
  "description": "Slack messaging — send messages, read channels, search conversations.",
167
207
  "package": "@modelcontextprotocol/server-slack",
@@ -181,6 +221,11 @@
181
221
  "setupModes": [
182
222
  "manual"
183
223
  ],
224
+ "hostSupport": {
225
+ "claude": { "mode": "managed" },
226
+ "opencode": { "mode": "managed" },
227
+ "codex": { "mode": "managed" }
228
+ },
184
229
  "setupUrl": "https://api.slack.com/apps",
185
230
  "setupNote": "Create a Slack app at api.slack.com/apps. Add Bot Token Scopes: channels:read, chat:write, channels:history.",
186
231
  "usedBy": [
@@ -193,6 +238,7 @@
193
238
  {
194
239
  "id": "notion",
195
240
  "name": "Notion",
241
+ "aliases": ["notion-mcp", "claude_ai_Notion"],
196
242
  "category": "integration",
197
243
  "description": "Notion workspace access — read/write pages, databases, and comments.",
198
244
  "package": "@anthropic-ai/notion-mcp",
@@ -210,6 +256,11 @@
210
256
  "setupModes": [
211
257
  "manual"
212
258
  ],
259
+ "hostSupport": {
260
+ "claude": { "mode": "managed" },
261
+ "opencode": { "mode": "managed" },
262
+ "codex": { "mode": "managed" }
263
+ },
213
264
  "setupUrl": "https://www.notion.so/profile/integrations",
214
265
  "setupNote": "Create an integration at notion.so/profile/integrations. Share target pages/databases with the integration.",
215
266
  "usedBy": [