@geraldmaron/construct 1.4.2 → 1.5.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 (519) hide show
  1. package/.env.example +36 -0
  2. package/README.md +41 -7
  3. package/bin/construct +1027 -64
  4. package/examples/distribution/sources/deck-one-pager.md +1 -1
  5. package/lib/acp/server.mjs +21 -7
  6. package/lib/adapters-sync.mjs +2 -1
  7. package/lib/audit-trail.mjs +185 -2
  8. package/lib/beads/auto-close.mjs +2 -1
  9. package/lib/beads/drift.mjs +2 -1
  10. package/lib/bridges/copilot-proxy.mjs +20 -5
  11. package/lib/certification/skill-inventory.mjs +10 -1
  12. package/lib/cli/approvals.mjs +147 -0
  13. package/lib/cli-commands.mjs +105 -14
  14. package/lib/comment-lint.mjs +127 -8
  15. package/lib/config/schema.mjs +6 -29
  16. package/lib/config/source-target-registry.mjs +70 -0
  17. package/lib/config/source-targets.mjs +179 -205
  18. package/lib/contracts/coverage.mjs +77 -0
  19. package/lib/contracts/validate.mjs +102 -13
  20. package/lib/contracts/violation-log.mjs +50 -4
  21. package/lib/db/migrate.mjs +69 -0
  22. package/lib/db/migrations/001_orchestration_runs.sql +9 -0
  23. package/lib/db/migrations/002_queue_provider.sql +50 -0
  24. package/lib/db/migrations/003_worker_registry.sql +17 -0
  25. package/lib/db/migrations/004_trace_events.sql +16 -0
  26. package/lib/db/migrations/005_shared_memory.sql +15 -0
  27. package/lib/db/migrations/006_orchestration_runs_tenant.sql +5 -0
  28. package/lib/decisions/enforced-baseline.json +0 -2
  29. package/lib/decisions/registry.mjs +3 -2
  30. package/lib/deployment/parity-contract.mjs +1 -1
  31. package/lib/deployment-mode.mjs +78 -2
  32. package/lib/diagram-export.mjs +10 -1
  33. package/lib/distill.mjs +5 -2
  34. package/lib/docs-verify.mjs +2 -1
  35. package/lib/doctor/cli.mjs +1 -0
  36. package/lib/doctor/command-on-path.mjs +24 -0
  37. package/lib/doctor/diagnosis.mjs +89 -0
  38. package/lib/doctor/embedding-health.mjs +50 -0
  39. package/lib/doctor/engine-health.mjs +93 -0
  40. package/lib/doctor/graph-validate.mjs +47 -0
  41. package/lib/doctor/index.mjs +18 -4
  42. package/lib/doctor/sidecar-providers.mjs +56 -0
  43. package/lib/doctor/watchers/consistency.mjs +93 -1
  44. package/lib/doctor/watchers/cx-budget.mjs +1 -1
  45. package/lib/doctor/watchers/graph-staleness.mjs +1 -1
  46. package/lib/doctor/watchers/mcp-protocol.mjs +17 -0
  47. package/lib/doctor/watchers/oracle-liveness.mjs +92 -0
  48. package/lib/doctor/watchers/orchestration-runs.mjs +108 -0
  49. package/lib/doctor/watchers/provider-breaker.mjs +78 -0
  50. package/lib/document-export.mjs +52 -27
  51. package/lib/document-extract/docling-client.mjs +9 -5
  52. package/lib/document-extract/docling-sidecar.py +30 -0
  53. package/lib/document-extract.mjs +1 -1
  54. package/lib/document-ingest.mjs +9 -0
  55. package/lib/embed/approval-queue.mjs +184 -88
  56. package/lib/embed/authority-guard.mjs +65 -2
  57. package/lib/embed/capability-jobs.mjs +365 -0
  58. package/lib/embed/capability-lifecycle.mjs +219 -0
  59. package/lib/embed/capability-loader.mjs +303 -0
  60. package/lib/embed/capability-runtime.mjs +58 -0
  61. package/lib/embed/cli.mjs +185 -8
  62. package/lib/embed/config.mjs +4 -0
  63. package/lib/embed/daemon.mjs +125 -6
  64. package/lib/embed/demand-fetch.mjs +190 -54
  65. package/lib/embed/inbox.mjs +12 -10
  66. package/lib/embed/presets/ops-triage.mjs +236 -0
  67. package/lib/embed/presets/pm-feedback.mjs +341 -0
  68. package/lib/embed/presets/tpm.mjs +401 -0
  69. package/lib/embed/providers/jira.mjs +72 -1
  70. package/lib/embed/providers/registry.mjs +140 -33
  71. package/lib/embedded-contract/capability.mjs +4 -0
  72. package/lib/embedded-contract/execution.mjs +1 -1
  73. package/lib/embedded-contract/model-resolve.mjs +53 -3
  74. package/lib/embedded-contract/workflow-defs.mjs +48 -73
  75. package/lib/embedded-contract/workflow-invoke.mjs +144 -4
  76. package/lib/embedded-contract/workflows/architecture-review.manifest.json +15 -0
  77. package/lib/embedded-contract/workflows/data-structure.manifest.json +14 -0
  78. package/lib/embedded-contract/workflows/evidence-ingest.manifest.json +14 -0
  79. package/lib/embedded-contract/workflows/memo-draft.manifest.json +14 -0
  80. package/lib/embedded-contract/workflows/operations-triage.manifest.json +18 -0
  81. package/lib/embedded-contract/workflows/operations.manifest.json +18 -0
  82. package/lib/embedded-contract/workflows/pm-feedback.manifest.json +18 -0
  83. package/lib/embedded-contract/workflows/prd-draft.manifest.json +15 -0
  84. package/lib/embedded-contract/workflows/proposal-review.manifest.json +15 -0
  85. package/lib/embedded-contract/workflows/research-synthesis.manifest.json +14 -0
  86. package/lib/embedded-contract/workflows/risk-review.manifest.json +15 -0
  87. package/lib/embedded-contract/workflows/structure-notes.manifest.json +14 -0
  88. package/lib/embedded-contract/workflows/transcript-process.manifest.json +14 -0
  89. package/lib/embedded-contract/workflows/triage.manifest.json +14 -0
  90. package/lib/env-config.mjs +50 -9
  91. package/lib/extensions/index.mjs +27 -0
  92. package/lib/extensions/loader.mjs +120 -0
  93. package/lib/extensions/manifest-schema.mjs +141 -0
  94. package/lib/extensions/manifests/anthropic.manifest.json +12 -0
  95. package/lib/extensions/manifests/atlassian-confluence.manifest.json +12 -0
  96. package/lib/extensions/manifests/atlassian-jira.manifest.json +53 -0
  97. package/lib/extensions/manifests/directory.manifest.json +12 -0
  98. package/lib/extensions/manifests/docling.manifest.json +37 -0
  99. package/lib/extensions/manifests/echo.manifest.json +8 -0
  100. package/lib/extensions/manifests/feedback.manifest.json +12 -0
  101. package/lib/extensions/manifests/github-copilot.manifest.json +12 -0
  102. package/lib/extensions/manifests/github.manifest.json +52 -0
  103. package/lib/extensions/manifests/linear.manifest.json +50 -0
  104. package/lib/extensions/manifests/local.manifest.json +12 -0
  105. package/lib/extensions/manifests/ollama.manifest.json +12 -0
  106. package/lib/extensions/manifests/openai.manifest.json +12 -0
  107. package/lib/extensions/manifests/openrouter-anthropic.manifest.json +12 -0
  108. package/lib/extensions/manifests/openrouter-deepseek.manifest.json +12 -0
  109. package/lib/extensions/manifests/openrouter-google.manifest.json +12 -0
  110. package/lib/extensions/manifests/openrouter-llama.manifest.json +12 -0
  111. package/lib/extensions/manifests/openrouter-qwen.manifest.json +12 -0
  112. package/lib/extensions/manifests/openrouter.manifest.json +12 -0
  113. package/lib/extensions/manifests/postgres.manifest.json +12 -0
  114. package/lib/extensions/manifests/salesforce.manifest.json +12 -0
  115. package/lib/extensions/manifests/slack.manifest.json +58 -0
  116. package/lib/extensions/manifests/whisper.manifest.json +36 -0
  117. package/lib/extensions/validate.mjs +175 -0
  118. package/lib/features.mjs +13 -9
  119. package/lib/flows/checkpoint.mjs +184 -0
  120. package/lib/flows/constants.mjs +27 -0
  121. package/lib/flows/define.mjs +146 -0
  122. package/lib/flows/engine.mjs +249 -0
  123. package/lib/flows/errors.mjs +19 -0
  124. package/lib/flows/index.mjs +27 -0
  125. package/lib/flows/joins.mjs +18 -0
  126. package/lib/flows/schema.mjs +90 -0
  127. package/lib/flows/state.mjs +31 -0
  128. package/lib/frameworks/loader.mjs +99 -0
  129. package/lib/frameworks/schema.mjs +157 -0
  130. package/lib/graph/build-from-corpus.mjs +67 -0
  131. package/lib/graph/build-from-embed.mjs +82 -0
  132. package/lib/graph/build-from-registry.mjs +164 -3
  133. package/lib/graph/cli.mjs +456 -12
  134. package/lib/graph/gap-queries.mjs +156 -0
  135. package/lib/graph/gaps.mjs +41 -0
  136. package/lib/graph/impacted.mjs +129 -0
  137. package/lib/graph/runtime-evidence.mjs +177 -0
  138. package/lib/graph/security-coverage.mjs +113 -0
  139. package/lib/graph/staleness.mjs +241 -10
  140. package/lib/graph/store.mjs +24 -7
  141. package/lib/graph/validate.mjs +161 -0
  142. package/lib/headhunt.mjs +9 -8
  143. package/lib/health-check.mjs +15 -7
  144. package/lib/hook-health.mjs +1 -1
  145. package/lib/hooks/agent-tracker.mjs +10 -4
  146. package/lib/hooks/edit-guard.mjs +3 -3
  147. package/lib/hooks/graph-impact-advisory.mjs +2 -2
  148. package/lib/hooks/guard-bash.mjs +41 -15
  149. package/lib/hooks/mcp-health-check.mjs +11 -4
  150. package/lib/hooks/model-fallback.mjs +50 -6
  151. package/lib/hooks/orchestration-dispatch-guard.mjs +14 -3
  152. package/lib/hooks/pre-compact.mjs +181 -173
  153. package/lib/hooks/rule-verifier.mjs +2 -1
  154. package/lib/hooks/session-reflect.mjs +2 -1
  155. package/lib/hooks/session-start.mjs +3 -3
  156. package/lib/host-capabilities.mjs +13 -2
  157. package/lib/host-disposition.mjs +19 -7
  158. package/lib/identity.mjs +92 -0
  159. package/lib/ingest/degraded-extract.mjs +96 -0
  160. package/lib/ingest/docling-remote.mjs +2 -1
  161. package/lib/ingest/provider-extract.mjs +7 -19
  162. package/lib/ingest/sidecar-providers.mjs +196 -0
  163. package/lib/ingest-tooling.mjs +11 -5
  164. package/lib/init-unified.mjs +57 -45
  165. package/lib/init-update.mjs +2 -1
  166. package/lib/install/legacy-global-cleanup.mjs +25 -0
  167. package/lib/intake/daemon.mjs +99 -8
  168. package/lib/intake/git-queue.mjs +110 -38
  169. package/lib/intake/queue-registry.mjs +50 -0
  170. package/lib/intake/queue.mjs +133 -17
  171. package/lib/intake/session-prelude.mjs +57 -8
  172. package/lib/integrations/intake-integrations.mjs +61 -111
  173. package/lib/intent-classifier.mjs +43 -5
  174. package/lib/libreoffice-export.mjs +8 -8
  175. package/lib/logging/rotate.mjs +5 -4
  176. package/lib/mcp/broker.mjs +332 -17
  177. package/lib/mcp/denied-store.mjs +95 -0
  178. package/lib/mcp/destructive-gate.mjs +30 -0
  179. package/lib/mcp/dispatch-envelope.mjs +199 -0
  180. package/lib/mcp/memory-bridge.mjs +2 -1
  181. package/lib/mcp/server.mjs +154 -1411
  182. package/lib/mcp/tool-definitions-memory.mjs +376 -0
  183. package/lib/mcp/tool-definitions-project.mjs +271 -0
  184. package/lib/mcp/tool-definitions-skills.mjs +311 -0
  185. package/lib/mcp/tool-definitions-workflow.mjs +398 -0
  186. package/lib/mcp/tool-definitions.mjs +25 -0
  187. package/lib/mcp/tool-registry.mjs +107 -0
  188. package/lib/mcp/tool-safety.mjs +1 -0
  189. package/lib/mcp/tools/orchestration-delegation-next.tool.mjs +68 -0
  190. package/lib/mcp/tools/orchestration-run.mjs +165 -25
  191. package/lib/mcp/tools/orchestration-task-result.tool.mjs +77 -0
  192. package/lib/mcp/tools/provider-write.mjs +187 -0
  193. package/lib/mcp/tools/scope.mjs +0 -3
  194. package/lib/mcp/tools/skills.mjs +1 -1
  195. package/lib/mcp/tools/storage.mjs +0 -8
  196. package/lib/mcp/transport/auth.mjs +238 -0
  197. package/lib/mcp/transport/http.mjs +136 -0
  198. package/lib/mcp/transport/mode.mjs +31 -0
  199. package/lib/mcp/transport/stdio.mjs +22 -0
  200. package/lib/mcp-catalog.json +4 -4
  201. package/lib/mcp-manager.mjs +34 -23
  202. package/lib/mcp-platform-config.mjs +31 -7
  203. package/lib/mode-capabilities.mjs +109 -0
  204. package/lib/model-router.mjs +42 -9
  205. package/lib/models/catalog.mjs +40 -1
  206. package/lib/net-guard.mjs +247 -0
  207. package/lib/observation-store.mjs +6 -2
  208. package/lib/ollama/provision-context.mjs +2 -1
  209. package/lib/opencode-config.mjs +22 -3
  210. package/lib/opencode-runtime-plugin.mjs +120 -2
  211. package/lib/oracle/actions.mjs +204 -10
  212. package/lib/oracle/cli.mjs +24 -3
  213. package/lib/oracle/dispatch.mjs +2 -1
  214. package/lib/oracle/execute.mjs +2 -2
  215. package/lib/oracle/gaps.mjs +3 -3
  216. package/lib/oracle/heartbeat.mjs +53 -0
  217. package/lib/oracle/read-model.mjs +69 -13
  218. package/lib/oracle/reconcile.mjs +3 -46
  219. package/lib/oracle/routing.mjs +37 -31
  220. package/lib/oracle/synthesize.mjs +1 -1
  221. package/lib/orchestration/classification.mjs +434 -0
  222. package/lib/orchestration/delegation-flow.mjs +132 -0
  223. package/lib/orchestration/flow-selection.mjs +418 -0
  224. package/lib/orchestration/gates.mjs +244 -0
  225. package/lib/orchestration/host-sampling.mjs +121 -0
  226. package/lib/orchestration/policy-constants.mjs +48 -0
  227. package/lib/orchestration/provider-outcome.mjs +197 -0
  228. package/lib/orchestration/readiness.mjs +114 -13
  229. package/lib/orchestration/run-store-postgres.mjs +32 -26
  230. package/lib/orchestration/run-store-sqlite.mjs +8 -14
  231. package/lib/orchestration/run-store.mjs +25 -12
  232. package/lib/orchestration/runtime.mjs +446 -39
  233. package/lib/orchestration/store.mjs +87 -12
  234. package/lib/orchestration/trace-store.mjs +125 -0
  235. package/lib/orchestration/web-capability.mjs +3 -2
  236. package/lib/orchestration/worker-runtime.mjs +162 -0
  237. package/lib/orchestration/worker.mjs +528 -89
  238. package/lib/orchestration-policy.mjs +67 -1111
  239. package/lib/packs/cli.mjs +144 -0
  240. package/lib/packs/core-pack.mjs +112 -0
  241. package/lib/packs/enablement.mjs +187 -0
  242. package/lib/packs/index.mjs +23 -0
  243. package/lib/packs/loader.mjs +176 -0
  244. package/lib/packs/manifest-schema.mjs +58 -0
  245. package/lib/packs/prompts.mjs +120 -0
  246. package/lib/packs/validate.mjs +208 -0
  247. package/lib/plugin-registry.mjs +4 -5
  248. package/lib/policy/audit-gate.mjs +42 -0
  249. package/lib/policy/consumption-budget.mjs +149 -0
  250. package/lib/policy/engine.mjs +81 -6
  251. package/lib/policy/role-authority.mjs +89 -0
  252. package/lib/prompt-composer.js +19 -3
  253. package/lib/providers/contract/adapters/confluence/governed-write.mjs +215 -0
  254. package/lib/providers/contract/adapters/confluence/manifest.json +17 -0
  255. package/lib/providers/contract/adapters/confluence/transport.mjs +135 -0
  256. package/lib/providers/contract/adapters/github/governed-write.mjs +121 -0
  257. package/lib/providers/contract/adapters/github/index.mjs +38 -3
  258. package/lib/providers/contract/adapters/jira/adf.mjs +151 -0
  259. package/lib/providers/contract/adapters/jira/createmeta.mjs +143 -0
  260. package/lib/providers/contract/adapters/jira/governed-write.mjs +182 -0
  261. package/lib/providers/contract/adapters/jira/manifest.json +17 -0
  262. package/lib/providers/contract/adapters/jira/transport.mjs +119 -0
  263. package/lib/providers/contract.mjs +207 -0
  264. package/lib/providers/credential-bootstrap.mjs +7 -4
  265. package/lib/providers/credential-sources.mjs +14 -2
  266. package/lib/providers/directory/index.mjs +273 -0
  267. package/lib/providers/feedback/index.mjs +392 -0
  268. package/lib/providers/filter-audit.mjs +68 -0
  269. package/lib/providers/filter-schema.mjs +54 -0
  270. package/lib/providers/github/index.mjs +31 -0
  271. package/lib/providers/instance-config.mjs +215 -0
  272. package/lib/providers/op-locate.mjs +96 -0
  273. package/lib/providers/op-run.mjs +64 -9
  274. package/lib/providers/registry.mjs +26 -3
  275. package/lib/providers/secret-audit-wiring.mjs +6 -0
  276. package/lib/providers/secret-resolver.mjs +240 -23
  277. package/lib/publish-template.mjs +6 -3
  278. package/lib/publish-tooling.mjs +4 -0
  279. package/lib/publish.mjs +32 -4
  280. package/lib/queue/pg-queue.mjs +395 -0
  281. package/lib/reflect.mjs +2 -1
  282. package/lib/registry/assemble.mjs +28 -2
  283. package/lib/registry/consolidation.mjs +8 -1
  284. package/lib/registry/custom-scaffold.mjs +200 -0
  285. package/lib/registry/custom-schema.mjs +137 -0
  286. package/lib/registry/loader.mjs +8 -3
  287. package/lib/registry/manifests/format-engines.default.json +15 -0
  288. package/lib/registry/manifests/surface-map.default.json +46 -0
  289. package/lib/registry/retired-paths.mjs +1 -0
  290. package/lib/registry/surface-map.mjs +100 -50
  291. package/lib/render-visual-check.mjs +240 -0
  292. package/lib/resources/budget.mjs +40 -17
  293. package/lib/roles/flavor-bindings.mjs +36 -14
  294. package/lib/roles/gateway.mjs +15 -8
  295. package/lib/roots.mjs +107 -0
  296. package/lib/runtime/uv-bootstrap.mjs +32 -6
  297. package/lib/runtime/whisper-bootstrap.mjs +11 -3
  298. package/lib/runtime-env.mjs +5 -2
  299. package/lib/scheduler/index.mjs +8 -20
  300. package/lib/schema-infer.mjs +31 -2
  301. package/lib/scopes/lifecycle.mjs +29 -25
  302. package/lib/scopes/loader.mjs +49 -12
  303. package/lib/scopes/teams.mjs +1 -1
  304. package/lib/security/ingest-boundary.mjs +80 -0
  305. package/lib/security/recall-wrapper.mjs +99 -0
  306. package/lib/security/trust.mjs +132 -0
  307. package/lib/service-manager.mjs +38 -19
  308. package/lib/setup.mjs +41 -23
  309. package/lib/skills-apply.mjs +4 -2
  310. package/lib/specialists/postconditions.mjs +2 -2
  311. package/lib/state-root.mjs +147 -0
  312. package/lib/status.mjs +597 -6
  313. package/lib/storage/admin.mjs +77 -5
  314. package/lib/storage/backend-registry.mjs +73 -0
  315. package/lib/storage/backend.mjs +63 -9
  316. package/lib/storage/embeddings-openai.mjs +12 -2
  317. package/lib/storage/hybrid-query.mjs +11 -3
  318. package/lib/storage/retrieval-hardening.mjs +384 -0
  319. package/lib/storage/shared-memory.mjs +158 -0
  320. package/lib/storage/vector-client.mjs +69 -2
  321. package/lib/team/health.mjs +72 -0
  322. package/lib/telemetry/backends/local.mjs +9 -3
  323. package/lib/telemetry/client.mjs +3 -7
  324. package/lib/template-registry.mjs +10 -12
  325. package/lib/tenant/context.mjs +82 -0
  326. package/lib/tenant/isolation.mjs +129 -0
  327. package/lib/test-corpus-inventory.mjs +104 -2
  328. package/lib/uninstall/uninstall.mjs +78 -12
  329. package/lib/validator.mjs +4 -6
  330. package/lib/worker/entrypoint.mjs +2 -1
  331. package/lib/worker/run.mjs +2 -2
  332. package/lib/worker/trace.mjs +5 -11
  333. package/lib/workflow-state.mjs +52 -8
  334. package/lib/workflows/liveness.mjs +203 -0
  335. package/lib/workflows/loader.mjs +177 -0
  336. package/lib/workflows/manifest-schema.mjs +71 -0
  337. package/lib/workflows/surface-parity.mjs +118 -0
  338. package/lib/workflows/validate.mjs +127 -0
  339. package/lib/writes/control-plane.mjs +140 -0
  340. package/lib/writes/envelope.mjs +206 -0
  341. package/lib/writes/sent-log.mjs +86 -0
  342. package/lib/writes/write-intent.mjs +109 -0
  343. package/package.json +16 -8
  344. package/personas/construct.md +12 -3
  345. package/registry/capabilities.json +143 -36
  346. package/rules/common/comments.md +1 -0
  347. package/schemas/project-config.schema.json +0 -12
  348. package/schemas/unified-registry.schema.json +2 -4
  349. package/scripts/sync-specialists.mjs +284 -81
  350. package/skills/docs/adr-workflow.md +1 -1
  351. package/skills/docs/codebase-research-workflow.md +3 -3
  352. package/skills/docs/prd-workflow.md +5 -6
  353. package/skills/docs/runbook-workflow.md +2 -2
  354. package/skills/docs/user-research-workflow.md +3 -3
  355. package/skills/operating/fleet-health-routing.md +77 -0
  356. package/skills/roles/ai-engineer.md +1 -1
  357. package/skills/roles/architect.md +0 -1
  358. package/skills/roles/business-strategist.md +1 -1
  359. package/skills/roles/data-analyst.telemetry.md +1 -1
  360. package/skills/roles/data-engineer.md +1 -1
  361. package/skills/roles/data-engineer.pipeline.md +1 -1
  362. package/skills/roles/data-engineer.vector-retrieval.md +1 -2
  363. package/skills/roles/data-engineer.warehouse.md +1 -1
  364. package/skills/roles/designer.accessibility.md +1 -1
  365. package/skills/roles/designer.md +0 -1
  366. package/skills/roles/devil-advocate.md +1 -1
  367. package/skills/roles/docs-keeper.md +1 -1
  368. package/skills/roles/evaluator.md +1 -1
  369. package/skills/roles/explorer.md +1 -1
  370. package/skills/roles/platform-engineer.md +1 -1
  371. package/skills/roles/qa.ai-eval.md +1 -2
  372. package/skills/roles/qa.api-contract.md +0 -1
  373. package/skills/roles/qa.data-pipeline.md +0 -1
  374. package/skills/roles/qa.md +0 -1
  375. package/skills/roles/qa.web-ui.md +0 -1
  376. package/skills/roles/release-manager.md +1 -1
  377. package/skills/roles/researcher.md +0 -2
  378. package/skills/roles/reviewer.md +0 -3
  379. package/skills/roles/security.ai.md +1 -1
  380. package/skills/roles/security.legal-compliance.md +1 -1
  381. package/skills/roles/security.md +0 -1
  382. package/skills/roles/security.privacy.md +0 -1
  383. package/skills/roles/security.supply-chain.md +1 -1
  384. package/skills/roles/sre.md +1 -1
  385. package/skills/roles/test-automation.md +1 -1
  386. package/skills/roles/trace-reviewer.md +1 -1
  387. package/skills/roles/ux-researcher.md +1 -1
  388. package/specialists/artifact-manifest.json +36 -36
  389. package/specialists/org/contracts/accessibility-to-qa.json +11 -3
  390. package/specialists/org/contracts/any-to-business-strategist.json +19 -7
  391. package/specialists/org/contracts/any-to-debugger.json +7 -1
  392. package/specialists/org/contracts/any-to-designer.json +7 -1
  393. package/specialists/org/contracts/any-to-docs-keeper.json +18 -4
  394. package/specialists/org/contracts/any-to-explorer.json +13 -4
  395. package/specialists/org/contracts/any-to-sre-incident.json +6 -2
  396. package/specialists/org/contracts/any-to-trace-reviewer.json +16 -4
  397. package/specialists/org/contracts/architect-to-ai-engineer.json +6 -2
  398. package/specialists/org/contracts/architect-to-data-engineer.json +17 -5
  399. package/specialists/org/contracts/architect-to-devil-advocate.json +11 -3
  400. package/specialists/org/contracts/architect-to-engineer.json +20 -4
  401. package/specialists/org/contracts/architect-to-evaluator.json +15 -5
  402. package/specialists/org/contracts/architect-to-legal-compliance.json +15 -5
  403. package/specialists/org/contracts/architect-to-operations.json +17 -4
  404. package/specialists/org/contracts/architect-to-platform-engineer.json +20 -4
  405. package/specialists/org/contracts/construct-to-orchestrator.json +10 -2
  406. package/specialists/org/contracts/data-analyst-to-product-manager.json +11 -2
  407. package/specialists/org/contracts/engineer-to-qa.json +20 -4
  408. package/specialists/org/contracts/engineer-to-reviewer.json +29 -5
  409. package/specialists/org/contracts/explorer-to-engineer.json +11 -3
  410. package/specialists/org/contracts/legal-compliance-to-release-manager.json +12 -4
  411. package/specialists/org/contracts/operations-to-user.json +53 -0
  412. package/specialists/org/contracts/operations-triage-output.json +53 -0
  413. package/specialists/org/contracts/pm-requirements-candidates.json +53 -0
  414. package/specialists/org/contracts/product-manager-to-architect.json +30 -10
  415. package/specialists/org/contracts/product-manager-to-data-analyst.json +13 -3
  416. package/specialists/org/contracts/product-manager-to-ux-researcher.json +15 -5
  417. package/specialists/org/contracts/qa-to-release-manager.json +11 -3
  418. package/specialists/org/contracts/researcher-to-architect.json +10 -2
  419. package/specialists/org/contracts/researcher-to-product-manager.json +16 -5
  420. package/specialists/org/contracts/reviewer-to-security.json +17 -3
  421. package/specialists/org/contracts/test-automation-to-engineer.json +11 -3
  422. package/specialists/org/contracts/trace-reviewer-to-sre.json +12 -4
  423. package/specialists/org/contracts/user-to-construct.json +11 -4
  424. package/specialists/org/frameworks/cx-architect-constraint-option-failure.md +66 -0
  425. package/specialists/org/frameworks/cx-engineer-feasibility-blast-radius.md +66 -0
  426. package/specialists/org/frameworks/cx-ops-dependency-sequencing.md +74 -0
  427. package/specialists/org/frameworks/cx-pm-value-tradeoff.md +66 -0
  428. package/specialists/org/frameworks/cx-qa-risk-based-coverage.md +69 -0
  429. package/specialists/org/groups/engineering-group.json +2 -6
  430. package/specialists/org/groups/governance-group.json +2 -3
  431. package/specialists/org/groups/operations-group.json +5 -8
  432. package/specialists/org/groups/product-group.json +4 -8
  433. package/specialists/org/groups/quality-group.json +3 -7
  434. package/specialists/org/groups/strategy-group.json +6 -9
  435. package/specialists/org/models.json.example +8 -0
  436. package/specialists/org/scopes/creative.json +6 -1
  437. package/specialists/org/scopes/operations.json +7 -1
  438. package/specialists/org/scopes/research.json +6 -1
  439. package/specialists/org/scopes/rnd.json +7 -1
  440. package/specialists/org/specialists/cx-architect.json +27 -8
  441. package/specialists/org/specialists/cx-designer.json +22 -8
  442. package/specialists/org/specialists/cx-engineer.json +71 -7
  443. package/specialists/org/specialists/cx-operations.json +89 -15
  444. package/specialists/org/specialists/cx-orchestrator.json +16 -4
  445. package/specialists/org/specialists/cx-product-manager.json +28 -9
  446. package/specialists/org/specialists/cx-qa.json +16 -6
  447. package/specialists/org/specialists/cx-researcher.json +40 -7
  448. package/specialists/org/specialists/cx-reviewer.json +61 -11
  449. package/specialists/org/specialists/cx-security.json +30 -10
  450. package/specialists/org/teams/design-team.json +3 -4
  451. package/specialists/org/teams/engineering-team.json +3 -10
  452. package/specialists/org/teams/governance-team.json +3 -5
  453. package/specialists/org/teams/operations-team.json +6 -12
  454. package/specialists/org/teams/product-management-team.json +2 -3
  455. package/specialists/org/teams/quality-team.json +4 -12
  456. package/specialists/org/teams/research-team.json +3 -3
  457. package/specialists/org/teams/strategy-team.json +7 -14
  458. package/specialists/prompts/cx-architect.md +20 -1
  459. package/specialists/prompts/cx-data-analyst.md +1 -1
  460. package/specialists/prompts/cx-designer.md +12 -4
  461. package/specialists/prompts/cx-engineer.md +15 -1
  462. package/specialists/prompts/cx-operations.md +14 -2
  463. package/specialists/prompts/cx-orchestrator.md +9 -5
  464. package/specialists/prompts/cx-product-manager.md +5 -1
  465. package/specialists/prompts/cx-qa.md +6 -2
  466. package/specialists/prompts/cx-researcher.md +25 -30
  467. package/specialists/prompts/cx-reviewer.md +19 -1
  468. package/specialists/prompts/cx-security.md +5 -1
  469. package/templates/distribution/construct-brand.typ +123 -59
  470. package/templates/distribution/construct-decision.typ +6 -3
  471. package/templates/distribution/construct-pdf.typ +11 -4
  472. package/templates/distribution/construct-prd.typ +6 -3
  473. package/templates/distribution/construct-research.typ +7 -4
  474. package/lib/providers/contract/adapters/git/index.mjs +0 -115
  475. package/lib/providers/contract/adapters/slack/index.mjs +0 -175
  476. package/specialists/org/contracts/business-strategist-to-product-manager.json +0 -39
  477. package/specialists/org/contracts/construct-to-rd-lead.json +0 -53
  478. package/specialists/org/contracts/data-engineer-to-platform-engineer.json +0 -36
  479. package/specialists/org/contracts/designer-to-accessibility.json +0 -36
  480. package/specialists/org/contracts/platform-engineer-to-engineer.json +0 -31
  481. package/specialists/org/contracts/qa-to-test-automation.json +0 -42
  482. package/specialists/org/contracts/rd-lead-to-architect.json +0 -38
  483. package/specialists/org/contracts/sre-to-release-manager.json +0 -36
  484. package/specialists/org/specialists/cx-accessibility.json +0 -69
  485. package/specialists/org/specialists/cx-ai-engineer.json +0 -75
  486. package/specialists/org/specialists/cx-business-strategist.json +0 -72
  487. package/specialists/org/specialists/cx-data-engineer.json +0 -71
  488. package/specialists/org/specialists/cx-devil-advocate.json +0 -71
  489. package/specialists/org/specialists/cx-docs-keeper.json +0 -82
  490. package/specialists/org/specialists/cx-evaluator.json +0 -69
  491. package/specialists/org/specialists/cx-explorer.json +0 -69
  492. package/specialists/org/specialists/cx-legal-compliance.json +0 -74
  493. package/specialists/org/specialists/cx-oracle.json +0 -46
  494. package/specialists/org/specialists/cx-platform-engineer.json +0 -80
  495. package/specialists/org/specialists/cx-rd-lead.json +0 -73
  496. package/specialists/org/specialists/cx-release-manager.json +0 -77
  497. package/specialists/org/specialists/cx-sre.json +0 -94
  498. package/specialists/org/specialists/cx-test-automation.json +0 -69
  499. package/specialists/org/specialists/cx-trace-reviewer.json +0 -69
  500. package/specialists/org/specialists/cx-ux-researcher.json +0 -68
  501. package/specialists/org/teams/accessibility-team.json +0 -39
  502. package/specialists/org/teams/ux-research-team.json +0 -39
  503. package/specialists/prompts/cx-accessibility.md +0 -55
  504. package/specialists/prompts/cx-ai-engineer.md +0 -124
  505. package/specialists/prompts/cx-business-strategist.md +0 -58
  506. package/specialists/prompts/cx-data-engineer.md +0 -55
  507. package/specialists/prompts/cx-devil-advocate.md +0 -59
  508. package/specialists/prompts/cx-docs-keeper.md +0 -164
  509. package/specialists/prompts/cx-evaluator.md +0 -49
  510. package/specialists/prompts/cx-explorer.md +0 -71
  511. package/specialists/prompts/cx-legal-compliance.md +0 -58
  512. package/specialists/prompts/cx-oracle.md +0 -98
  513. package/specialists/prompts/cx-platform-engineer.md +0 -97
  514. package/specialists/prompts/cx-rd-lead.md +0 -59
  515. package/specialists/prompts/cx-release-manager.md +0 -54
  516. package/specialists/prompts/cx-sre.md +0 -111
  517. package/specialists/prompts/cx-test-automation.md +0 -55
  518. package/specialists/prompts/cx-trace-reviewer.md +0 -101
  519. package/specialists/prompts/cx-ux-researcher.md +0 -53
@@ -4,9 +4,24 @@
4
4
  * Invokes a named Construct workflow non-interactively and returns a provenanced
5
5
  * execution plan: the selected roles (auto/explicit/constrained), each role's
6
6
  * rationale, the skills they apply, the resolved model, the evidence the chain
7
- * requires, and the output contract it will produce. Construct supplies the
8
- * orchestration plan and provenance; the host agent runtime performs the
9
- * specialist reasoning so this contract never fabricates specialist output.
7
+ * requires, the bound persona reasoning framework (ADR-0062), and the output
8
+ * contract to be produced. Construct supplies the orchestration plan and
9
+ * provenance; the host agent runtime performs the specialist reasoning, so
10
+ * the contract never fabricates specialist output.
11
+ *
12
+ * Framework wiring (LMCP-F8, ADR-0062 §3): the primary role's framework is
13
+ * resolved through the same pack registry and tier precedence (E1/ADR-0055)
14
+ * that resolves persona prompts (lib/orchestration/worker.mjs), by matching a
15
+ * pack-declared framework's `appliesToRole` against the role. The resolved
16
+ * framework's ordered `steps` become prompt fragments in the plan, and its
17
+ * `emits` tokens (in step order) are the output contract's required fields —
18
+ * the host runtime that performs the reasoning must return one labeled output
19
+ * per token, in order. A role with no matching framework never falls back to
20
+ * silent generic reasoning: the plan carries `framework: { available: false,
21
+ * degraded: 'framework-missing', role }`, a visible flag a caller can branch
22
+ * on. Traces record `{frameworkId, version, source}` alongside the existing
23
+ * F1 provenance fields so a downstream audit can tell which reasoning
24
+ * procedure (if any) governed the run.
10
25
  *
11
26
  * Durable side effects are gated by approval mode (resolveWriteGate):
12
27
  * - proposal-only → status 'proposed', zero writes
@@ -19,10 +34,15 @@
19
34
  */
20
35
 
21
36
  import { randomUUID } from 'node:crypto';
37
+ import { dirname, join, resolve } from 'node:path';
38
+ import { fileURLToPath } from 'node:url';
22
39
 
23
40
  import { getDeploymentMode } from '../deployment-mode.mjs';
24
41
  import { addObservation } from '../observation-store.mjs';
25
42
  import { recordApprovalRequest } from '../roles/approval-surface.mjs';
43
+ import { loadAllPacks } from '../packs/loader.mjs';
44
+ import { resolveFramework } from '../frameworks/loader.mjs';
45
+ import { parseFrameworkFile } from '../frameworks/schema.mjs';
26
46
  import { getWorkflowDef, WORKFLOW_TYPES } from './workflow-defs.mjs';
27
47
  import { roleMap, roleRationale, skillsForChain, contractFacts } from './role-facts.mjs';
28
48
  import { resolveEmbeddedModel } from './model-resolve.mjs';
@@ -31,6 +51,89 @@ import { resolveWriteGate, newTraceId, DEFAULT_APPROVAL_MODE } from './audit.mjs
31
51
 
32
52
  const VALID_STRATEGIES = ['auto', 'explicit', 'constrained'];
33
53
 
54
+ const HERE = dirname(fileURLToPath(import.meta.url));
55
+ const PACKAGE_ROOT = resolve(HERE, '..', '..');
56
+
57
+ // Mirrors lib/orchestration/worker.mjs sortByTierPrecedence: a project pack's
58
+ // framework for a role must win over a builtin pack's framework for the same
59
+ // role, not just over another version of the same pack id (ADR-0055).
60
+
61
+ const PACK_TIER_RANK = { project: 0, user: 1, builtin: 2, unknown: 3 };
62
+
63
+ function sortByTierPrecedence(packs) {
64
+ return [...packs].sort((a, b) => (PACK_TIER_RANK[a._tier] ?? 3) - (PACK_TIER_RANK[b._tier] ?? 3));
65
+ }
66
+
67
+ /**
68
+ * Find the frameworkId a pack registry binds to a role, honoring tier
69
+ * precedence. A framework equips a role via its own frontmatter
70
+ * `appliesToRole` (ADR-0062 §2) — there is no separate specialist→framework
71
+ * map to consult, so packs are walked in precedence order and the first
72
+ * framework file whose parsed `appliesToRole` matches wins.
73
+ *
74
+ * @param {string} roleId bare role id, e.g. 'product-manager'
75
+ * @param {object[]} packs tier-precedence ordered pack list
76
+ * @param {string} packageRoot
77
+ * @returns {string|null}
78
+ */
79
+ function frameworkIdForRole(roleId, packs, packageRoot) {
80
+ for (const pack of packs) {
81
+ const frameworks = pack?.frameworks || {};
82
+ const root = pack?._packDir || packageRoot;
83
+ for (const [frameworkId, relPath] of Object.entries(frameworks)) {
84
+ if (typeof relPath !== 'string' || !relPath) continue;
85
+ const parsed = parseFrameworkFile(join(root, relPath));
86
+ if (parsed.valid && parsed.frontmatter?.appliesToRole === roleId) return frameworkId;
87
+ }
88
+ }
89
+ return null;
90
+ }
91
+
92
+ /**
93
+ * Resolve the persona reasoning framework bound to a role through the pack
94
+ * registry (E1 precedence), or a visible degradation flag when no pack
95
+ * declares one for this role — never a silent fallback to generic reasoning
96
+ * (ADR-0062 §3).
97
+ *
98
+ * @param {string} roleId
99
+ * @param {object} opts
100
+ * @param {object} opts.env
101
+ * @param {string} opts.cwd
102
+ * @returns {{available:true, frameworkId:string, version:*, source:string, steps:object[], requiredOutputFields:string[]} | {available:false, degraded:'framework-missing', role:string}}
103
+ */
104
+ function resolveRoleFramework(roleId, { env, cwd }) {
105
+ const deploymentMode = getDeploymentMode(env, { cwd });
106
+ const { packs } = loadAllPacks({ deploymentMode, env, rootDir: cwd, packageRoot: PACKAGE_ROOT });
107
+ const ordered = sortByTierPrecedence(packs);
108
+
109
+ const frameworkId = frameworkIdForRole(roleId, ordered, PACKAGE_ROOT);
110
+ if (!frameworkId) {
111
+ return { available: false, degraded: 'framework-missing', role: roleId };
112
+ }
113
+
114
+ const resolved = resolveFramework(frameworkId, { packs: ordered, packageRoot: PACKAGE_ROOT });
115
+ if (!resolved.found) {
116
+ return { available: false, degraded: 'framework-missing', role: roleId };
117
+ }
118
+
119
+ const steps = (resolved.frontmatter.steps || []).map((step) => ({
120
+ id: step.id,
121
+ move: step.move,
122
+ question: step.question,
123
+ emits: step.emits,
124
+ cites: step.cites,
125
+ }));
126
+
127
+ return {
128
+ available: true,
129
+ frameworkId: resolved.frontmatter.id,
130
+ version: resolved.frontmatter.version,
131
+ source: resolved.packId,
132
+ steps,
133
+ requiredOutputFields: steps.map((s) => s.emits),
134
+ };
135
+ }
136
+
34
137
  function selectRoles({ strategy, defChain, requestedRoles, map, warnings }) {
35
138
  const filterKnown = (ids) => ids.filter((id) => {
36
139
  if (map.has(id)) return true;
@@ -63,6 +166,7 @@ function errorResult({ workflowId, traceId, approvalMode, code, message, warning
63
166
  roleRationale: [],
64
167
  skillsApplied: [],
65
168
  modelResolution: null,
169
+ framework: null,
66
170
  outputs: null,
67
171
  recommendations: [],
68
172
  evidence: { requirements: [], satisfied: [], traceId },
@@ -71,6 +175,7 @@ function errorResult({ workflowId, traceId, approvalMode, code, message, warning
71
175
  approvalMode: approvalMode || DEFAULT_APPROVAL_MODE,
72
176
  durableWritesPerformed: [],
73
177
  traceId,
178
+ trace: { role: null, frameworkId: null, frameworkVersion: null, frameworkSource: null, degraded: null },
74
179
  errors: [{ code, message }],
75
180
  warnings,
76
181
  };
@@ -154,6 +259,15 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
154
259
  const skillsApplied = skillsForChain(selectedRoles, map);
155
260
  const rationale = roleRationale(selectedRoles, map);
156
261
 
262
+ // The bound framework equips the plan's primary role only — the role the
263
+ // output contract and evidence requirements are already scoped to
264
+ // (contractFacts(primaryOwner) above) — not every role in the chain.
265
+
266
+ const framework = resolveRoleFramework(primaryOwner, { env, cwd });
267
+ if (!framework.available) {
268
+ warnings.push(`framework: no reasoning framework bound for role '${primaryOwner}'; proceeding without a reasoning scaffold (degraded: framework-missing).`);
269
+ }
270
+
157
271
  // Evidence is satisfied only when a requirement key is actually present in the
158
272
  // caller-supplied context; missing requirements are reported, never assumed.
159
273
 
@@ -165,9 +279,14 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
165
279
  const mode = approvalMode || def.defaultApprovalMode;
166
280
  const gate = resolveWriteGate({ approvalMode: mode, deploymentMode });
167
281
 
282
+ // requiredOutputFields carries the framework's `emits` tokens IN STEP ORDER
283
+ // (ADR-0062 §3): the host runtime must return one labeled output per token,
284
+ // in that order, so the reasoning procedure is checkable, not just prose.
285
+
168
286
  const outputs = {
169
287
  schema: def.outputSchema,
170
288
  expected: facts.expectedOutputs,
289
+ requiredOutputFields: framework.available ? framework.requiredOutputFields : [],
171
290
  note: 'Construct returns the orchestration plan and output contract; specialist reasoning is performed by the host agent runtime.',
172
291
  };
173
292
  const recommendations = [`Run roles in order: ${selectedRoles.map((r) => `cx-${r}`).join(' → ')}.`];
@@ -176,7 +295,11 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
176
295
  const riskFactors = [];
177
296
  if (missingEvidence.length) riskFactors.push(`missing required evidence: ${missingEvidence.join(', ')}`);
178
297
  if (modelResolution.error) riskFactors.push(`model could not be resolved: ${modelResolution.error.reason}`);
179
- const risks = { level: missingEvidence.length || modelResolution.error ? 'medium' : 'low', factors: riskFactors };
298
+ if (!framework.available) riskFactors.push(`no reasoning framework bound for role '${primaryOwner}' (degraded: framework-missing)`);
299
+ const risks = {
300
+ level: missingEvidence.length || modelResolution.error || !framework.available ? 'medium' : 'low',
301
+ factors: riskFactors,
302
+ };
180
303
 
181
304
  const durableWritesPerformed = [];
182
305
  const errors = [];
@@ -214,6 +337,21 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
214
337
  status = 'proposed';
215
338
  }
216
339
 
340
+ // Trace provenance (LMCP-F1 alignment): a downstream audit reads
341
+ // {frameworkId, frameworkVersion, frameworkSource} off the trace to know
342
+ // which reasoning procedure (if any) governed this run, the same way F1
343
+ // already records {specialistId, packId, promptVersion} for the persona
344
+ // that ran. traceId itself is already carried (and correlated) at the top
345
+ // level, so it is not duplicated here.
346
+
347
+ const traceProvenance = {
348
+ role: primaryOwner,
349
+ frameworkId: framework.available ? framework.frameworkId : null,
350
+ frameworkVersion: framework.available ? framework.version : null,
351
+ frameworkSource: framework.available ? framework.source : null,
352
+ degraded: framework.available ? null : framework.degraded,
353
+ };
354
+
217
355
  return {
218
356
  workflowId,
219
357
  workflowType,
@@ -225,6 +363,7 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
225
363
  skillsApplied,
226
364
  modelResolution,
227
365
  execution,
366
+ framework,
228
367
  outputs,
229
368
  recommendations,
230
369
  evidence: { requirements: facts.evidenceRequirements, satisfied, missing: missingEvidence, traceId },
@@ -233,6 +372,7 @@ export async function invokeWorkflow(request = {}, { env = process.env, cwd = pr
233
372
  approvalMode: gate.approvalMode,
234
373
  durableWritesPerformed,
235
374
  traceId,
375
+ trace: traceProvenance,
236
376
  errors,
237
377
  warnings,
238
378
  };
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "architecture-review",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["architect", "security", "reviewer"],
8
+ "defaultApprovalMode": "requires-human-approval",
9
+ "outputSchema": { "artifact": "review-report" },
10
+ "durableStateModel": "none",
11
+ "tier": "reasoning",
12
+ "description": "Review an architecture or design for trade-offs, failure modes, and security exposure.",
13
+ "owner": "construct-core",
14
+ "compatVersion": 1
15
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "data-structure",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["data-analyst", "engineer"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "standard",
11
+ "description": "Parse, validate, and profile a raw dataset into a structured, described shape.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "evidence-ingest",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["researcher", "data-analyst"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "fast",
11
+ "description": "Ingest and structure raw evidence (notes, documents, signals) into a normalized summary.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "memo-draft",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["operations", "reviewer"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "fast",
11
+ "description": "Draft a decision or status memo from a problem statement and context.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "operations-triage",
3
+ "version": "1.0.0",
4
+ "type": "embed",
5
+ "defaultApprovalMode": "proposal-only",
6
+ "compatVersion": 1,
7
+ "owner": "construct-core",
8
+ "description": "Triage preset: the operations specialist reviews new/changed Jira tickets, detects duplicates and under-specified issues, then proposes triage actions (duplicate-link, needs-info comment) held for approval. Never auto-executes writes.",
9
+ "embed": {
10
+ "specialist": "cx-operations",
11
+ "providerBindings": ["atlassian-jira", "atlassian-confluence", "directory"],
12
+ "framework": "cx-ops-dependency-sequencing",
13
+ "outputContract": "operations-triage",
14
+ "proposalAuthority": "propose-only",
15
+ "runtime": "auto",
16
+ "cadence": { "every": "PT2H" }
17
+ }
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "operations",
3
+ "version": "1.0.0",
4
+ "type": "embed",
5
+ "defaultApprovalMode": "proposal-only",
6
+ "compatVersion": 1,
7
+ "owner": "construct-core",
8
+ "description": "TPM preset: the operations specialist reads Jira, product docs (Confluence), and Slack, then produces a recurring briefing — work missing versus the PRDs, timeline-risk findings with evidence, and proposed Jira tickets held for approval. Never auto-creates issues.",
9
+ "embed": {
10
+ "specialist": "cx-operations",
11
+ "providerBindings": ["atlassian-jira", "atlassian-confluence", "slack"],
12
+ "framework": "cx-ops-dependency-sequencing",
13
+ "outputContract": "operations-tpm-briefing",
14
+ "proposalAuthority": "propose-only",
15
+ "runtime": "auto",
16
+ "cadence": { "every": "PT4H" }
17
+ }
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "pm-feedback",
3
+ "version": "1.0.0",
4
+ "type": "embed",
5
+ "defaultApprovalMode": "proposal-only",
6
+ "compatVersion": 1,
7
+ "owner": "construct-core",
8
+ "description": "PM feedback preset: the product-manager specialist reads customer feedback and PRDs (Confluence), clusters feedback by theme, scores each theme with the user-value rubric, cross-references PRD requirements, and emits a requirements-candidates artifact. Artifact-only — proposes no provider write.",
9
+ "embed": {
10
+ "specialist": "cx-product-manager",
11
+ "providerBindings": ["feedback", "atlassian-confluence"],
12
+ "framework": "cx-pm-value-tradeoff",
13
+ "outputContract": "pm-requirements-candidates",
14
+ "proposalAuthority": "propose-only",
15
+ "runtime": "auto",
16
+ "cadence": { "every": "PT24H" }
17
+ }
18
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "prd-draft",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["product-manager", "architect"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "outputSchema": { "artifact": "decision" },
10
+ "durableStateModel": "none",
11
+ "tier": "standard",
12
+ "description": "Draft a product requirements document from a problem statement and supporting evidence.",
13
+ "owner": "construct-core",
14
+ "compatVersion": 1
15
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "proposal-review",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["reviewer"],
8
+ "defaultApprovalMode": "requires-human-approval",
9
+ "outputSchema": { "artifact": "review-report" },
10
+ "durableStateModel": "none",
11
+ "tier": "standard",
12
+ "description": "Review a proposal for correctness, risk, and hidden assumptions before acceptance.",
13
+ "owner": "construct-core",
14
+ "compatVersion": 1
15
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "research-synthesis",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["researcher", "data-analyst", "reviewer"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "reasoning",
11
+ "description": "Synthesize multiple sources into a cited, evidence-graded research summary.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "id": "risk-review",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["reviewer", "security"],
8
+ "defaultApprovalMode": "requires-human-approval",
9
+ "outputSchema": { "artifact": "review-report" },
10
+ "durableStateModel": "none",
11
+ "tier": "reasoning",
12
+ "description": "Stress-test a plan for risk: failure modes, security, and compliance exposure.",
13
+ "owner": "construct-core",
14
+ "compatVersion": 1
15
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "structure-notes",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["orchestrator", "researcher"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "fast",
11
+ "description": "Structure an unclassified brain-dump or rough notes into a normalized summary with extracted intents.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "transcript-process",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo", "team"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["researcher", "data-analyst"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "fast",
11
+ "description": "Process a meeting/call transcript into a summary, decisions, and action items.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "id": "triage",
3
+ "version": "1.0.0",
4
+ "type": "linear",
5
+ "modes": ["solo"],
6
+ "surfaces": ["mcp", "cli"],
7
+ "roleChain": ["orchestrator", "researcher"],
8
+ "defaultApprovalMode": "proposal-only",
9
+ "durableStateModel": "none",
10
+ "tier": "fast",
11
+ "description": "Classify and route unstructured input to the appropriate workflow.",
12
+ "owner": "construct-core",
13
+ "compatVersion": 1
14
+ }
@@ -8,6 +8,13 @@
8
8
  * order — project .env over config.env — so a key resolves the same way on both
9
9
  * paths. Backs setup, model-router, and the MCP server when they resolve API keys
10
10
  * and model overrides without leaking secrets.
11
+ *
12
+ * The `rootDir` param is the project .env tier's location and must be the
13
+ * user's project root, not the toolkit install checkout — bin/construct and
14
+ * lib/mcp/server.mjs both resolve it via lib/roots.mjs's resolveProjectRoot()
15
+ * (walk up from cwd to a `.cx/` or `package.json` marker) before calling
16
+ * loadConstructEnv/prepareConstructEnv, so a `.env` in the user's repo loads
17
+ * on both surfaces.
11
18
  */
12
19
  import fs from 'node:fs';
13
20
  import os from 'node:os';
@@ -16,10 +23,15 @@ import { configDir } from './config/xdg.mjs';
16
23
  import { API_KEY_CREDENTIALS } from './providers/credential-catalog.mjs';
17
24
  import { extractOpRef } from './providers/secret-resolver.mjs';
18
25
 
19
- export function parseEnvFile(filePath) {
20
- if (!filePath || !fs.existsSync(filePath)) return {};
26
+ // The single dotenv-line parser: strips a leading and/or trailing quote
27
+ // independently (an unpaired quote `KEY="abc` — still loses its one quote
28
+ // character rather than being left untouched). lib/providers/secret-resolver.mjs's
29
+ // file tier calls this same function so a value never differs between the two
30
+ // dotenv readers.
31
+
32
+ export function parseEnvContent(content) {
21
33
  const env = {};
22
- for (const rawLine of fs.readFileSync(filePath, 'utf8').split(/\r?\n/)) {
34
+ for (const rawLine of String(content ?? '').split(/\r?\n/)) {
23
35
  const line = rawLine.trim();
24
36
  if (!line || line.startsWith('#')) continue;
25
37
  const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
@@ -30,6 +42,11 @@ export function parseEnvFile(filePath) {
30
42
  return env;
31
43
  }
32
44
 
45
+ export function parseEnvFile(filePath) {
46
+ if (!filePath || !fs.existsSync(filePath)) return {};
47
+ return parseEnvContent(fs.readFileSync(filePath, 'utf8'));
48
+ }
49
+
33
50
  export function getUserConfigDir(homeDir = os.homedir()) {
34
51
  return configDir(homeDir);
35
52
  }
@@ -119,7 +136,35 @@ export function preferInjectedCredential(envValue, fileValue) {
119
136
  );
120
137
  }
121
138
 
122
- export function loadConstructEnv({ rootDir, homeDir = os.homedir(), env = process.env, warn = true } = {}) {
139
+ // The canonical resolver for a non-negative numeric env setting (milliseconds,
140
+ // byte caps, counts, loop bounds). An explicit 0 is a valid, meaningful value
141
+ // (disable / no-cap), so only null/undefined/blank or a non-finite/negative parse
142
+ // falls back — `Number(env) || fallback` would silently rewrite an explicit 0.
143
+ // Mirrors the "0 disables" convention documented at lib/mcp/server.mjs.
144
+
145
+ export function resolveNonNegativeSetting(env, key, fallback) {
146
+ const val = env?.[key];
147
+ if (val === undefined || val === null) return fallback;
148
+ if (typeof val === 'string' && val.trim() === '') return fallback;
149
+ const raw = Number(val);
150
+ return Number.isFinite(raw) && raw >= 0 ? raw : fallback;
151
+ }
152
+
153
+ // The env-vs-file shadow winner differs by surface: the MCP server and other
154
+ // callers use loadConstructEnv's file-wins return, but bin/construct copies only
155
+ // the keys missing from process.env, so on a conflict the shell value wins there.
156
+ // The caller declares which value actually wins so the warning names the truth
157
+ // rather than asserting file-wins on every surface.
158
+
159
+ export function shadowWarningMessage(key, shadowWinner = 'file') {
160
+ const winnerClause = shadowWinner === 'shell'
161
+ ? 'The shell value will be used'
162
+ : 'The config file will be used';
163
+ return `[construct] WARNING: process.env.${key} differs from the config file value. `
164
+ + `${winnerClause}. To silence: unset the shell variable or update the config file to match.`;
165
+ }
166
+
167
+ export function loadConstructEnv({ rootDir, homeDir = os.homedir(), env = process.env, warn = true, shadowWinner = 'file' } = {}) {
123
168
  const rootEnv = rootDir ? parseEnvFile(path.join(rootDir, '.env')) : {};
124
169
  const userEnv = parseEnvFile(getUserEnvPath(homeDir));
125
170
 
@@ -153,11 +198,7 @@ export function loadConstructEnv({ rootDir, homeDir = os.homedir(), env = proces
153
198
  if (!env[key]) continue;
154
199
  if (key in fileEnv && fileEnv[key] !== env[key]) {
155
200
  if (preferInjectedCredential(env[key], fileEnv[key])) continue;
156
- process.stderr.write(
157
- `[construct] WARNING: process.env.${key} differs from the config file value. ` +
158
- `The config file will be used. To silence: unset the shell variable or ` +
159
- `update the config file to match.\n`,
160
- );
201
+ process.stderr.write(`${shadowWarningMessage(key, shadowWinner)}\n`);
161
202
  }
162
203
  }
163
204
  }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * lib/extensions/index.mjs — public API for the extension manifest system.
3
+ *
4
+ * Re-exports all symbols from the three extension sub-modules so consumers
5
+ * can import from a single entry point:
6
+ *
7
+ * import { validateManifest, loadManifestsFromDir, MANIFEST_KINDS } from './extensions/index.mjs';
8
+ */
9
+
10
+ export {
11
+ MANIFEST_KINDS,
12
+ REQUIRED_FIELDS,
13
+ OPTIONAL_FIELDS,
14
+ COMPAT_VERSION,
15
+ ALLOWED_SECRET_ENV_PREFIXES,
16
+ ESCALATION_SENSITIVE_KINDS,
17
+ KNOWN_REQUESTABLE_TOOL_GRANTS,
18
+ BUILTIN_SPECIALIST_IDS,
19
+ } from './manifest-schema.mjs';
20
+
21
+ export { validateManifest } from './validate.mjs';
22
+
23
+ export {
24
+ loadManifestsFromDir,
25
+ mergeManifests,
26
+ resolveManifestDirs,
27
+ } from './loader.mjs';