@geraldmaron/construct 1.4.1 → 1.5.0

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 (556) hide show
  1. package/.env.example +36 -0
  2. package/README.md +41 -7
  3. package/bin/construct +1029 -65
  4. package/bin/construct-postinstall.mjs +27 -2
  5. package/config/tag-vocabulary.json +264 -0
  6. package/examples/distribution/sources/deck-one-pager.md +1 -1
  7. package/lib/acp/server.mjs +21 -7
  8. package/lib/adapters-sync.mjs +2 -1
  9. package/lib/audit-trail.mjs +185 -2
  10. package/lib/beads/auto-close.mjs +2 -1
  11. package/lib/beads/drift.mjs +2 -1
  12. package/lib/bridges/copilot-proxy.mjs +20 -5
  13. package/lib/certification/skill-inventory.mjs +10 -1
  14. package/lib/cli/approvals.mjs +147 -0
  15. package/lib/cli-commands.mjs +105 -14
  16. package/lib/comment-lint.mjs +127 -8
  17. package/lib/config/schema.mjs +7 -30
  18. package/lib/config/source-target-registry.mjs +70 -0
  19. package/lib/config/source-targets.mjs +179 -205
  20. package/lib/contracts/coverage.mjs +77 -0
  21. package/lib/contracts/validate.mjs +102 -13
  22. package/lib/contracts/violation-log.mjs +50 -4
  23. package/lib/db/migrate.mjs +69 -0
  24. package/lib/db/migrations/001_orchestration_runs.sql +9 -0
  25. package/lib/db/migrations/002_queue_provider.sql +50 -0
  26. package/lib/db/migrations/003_worker_registry.sql +17 -0
  27. package/lib/db/migrations/004_trace_events.sql +16 -0
  28. package/lib/db/migrations/005_shared_memory.sql +15 -0
  29. package/lib/db/migrations/006_orchestration_runs_tenant.sql +5 -0
  30. package/lib/decisions/enforced-baseline.json +0 -2
  31. package/lib/decisions/registry.mjs +3 -2
  32. package/lib/deployment/parity-contract.mjs +1 -1
  33. package/lib/deployment-mode.mjs +78 -2
  34. package/lib/diagram-export.mjs +10 -1
  35. package/lib/distill.mjs +5 -2
  36. package/lib/docs-verify.mjs +2 -1
  37. package/lib/doctor/cli.mjs +1 -0
  38. package/lib/doctor/command-on-path.mjs +24 -0
  39. package/lib/doctor/diagnosis.mjs +109 -0
  40. package/lib/doctor/embedding-health.mjs +50 -0
  41. package/lib/doctor/engine-health.mjs +93 -0
  42. package/lib/doctor/graph-validate.mjs +47 -0
  43. package/lib/doctor/index.mjs +23 -4
  44. package/lib/doctor/sidecar-providers.mjs +56 -0
  45. package/lib/doctor/watchers/consistency.mjs +93 -1
  46. package/lib/doctor/watchers/cx-budget.mjs +1 -1
  47. package/lib/doctor/watchers/graph-staleness.mjs +1 -1
  48. package/lib/doctor/watchers/mcp-protocol.mjs +17 -0
  49. package/lib/doctor/watchers/oracle-liveness.mjs +92 -0
  50. package/lib/doctor/watchers/orchestration-runs.mjs +108 -0
  51. package/lib/doctor/watchers/provider-breaker.mjs +78 -0
  52. package/lib/document-export.mjs +52 -27
  53. package/lib/document-extract/docling-client.mjs +9 -5
  54. package/lib/document-extract/docling-sidecar.py +30 -0
  55. package/lib/document-extract.mjs +1 -1
  56. package/lib/document-ingest.mjs +9 -0
  57. package/lib/embed/approval-queue.mjs +184 -88
  58. package/lib/embed/authority-guard.mjs +65 -2
  59. package/lib/embed/capability-jobs.mjs +365 -0
  60. package/lib/embed/capability-lifecycle.mjs +219 -0
  61. package/lib/embed/capability-loader.mjs +303 -0
  62. package/lib/embed/capability-runtime.mjs +58 -0
  63. package/lib/embed/cli.mjs +185 -8
  64. package/lib/embed/config.mjs +4 -0
  65. package/lib/embed/daemon.mjs +125 -6
  66. package/lib/embed/demand-fetch.mjs +190 -54
  67. package/lib/embed/inbox.mjs +12 -10
  68. package/lib/embed/presets/ops-triage.mjs +236 -0
  69. package/lib/embed/presets/pm-feedback.mjs +341 -0
  70. package/lib/embed/presets/tpm.mjs +401 -0
  71. package/lib/embed/providers/jira.mjs +72 -1
  72. package/lib/embed/providers/registry.mjs +140 -33
  73. package/lib/embed/worker.mjs +5 -0
  74. package/lib/embedded-contract/capability.mjs +4 -0
  75. package/lib/embedded-contract/execution.mjs +1 -1
  76. package/lib/embedded-contract/model-resolve.mjs +53 -3
  77. package/lib/embedded-contract/workflow-defs.mjs +48 -73
  78. package/lib/embedded-contract/workflow-invoke.mjs +144 -4
  79. package/lib/embedded-contract/workflows/architecture-review.manifest.json +15 -0
  80. package/lib/embedded-contract/workflows/data-structure.manifest.json +14 -0
  81. package/lib/embedded-contract/workflows/evidence-ingest.manifest.json +14 -0
  82. package/lib/embedded-contract/workflows/memo-draft.manifest.json +14 -0
  83. package/lib/embedded-contract/workflows/operations-triage.manifest.json +18 -0
  84. package/lib/embedded-contract/workflows/operations.manifest.json +18 -0
  85. package/lib/embedded-contract/workflows/pm-feedback.manifest.json +18 -0
  86. package/lib/embedded-contract/workflows/prd-draft.manifest.json +15 -0
  87. package/lib/embedded-contract/workflows/proposal-review.manifest.json +15 -0
  88. package/lib/embedded-contract/workflows/research-synthesis.manifest.json +14 -0
  89. package/lib/embedded-contract/workflows/risk-review.manifest.json +15 -0
  90. package/lib/embedded-contract/workflows/structure-notes.manifest.json +14 -0
  91. package/lib/embedded-contract/workflows/transcript-process.manifest.json +14 -0
  92. package/lib/embedded-contract/workflows/triage.manifest.json +14 -0
  93. package/lib/env-config.mjs +60 -11
  94. package/lib/export-validate.mjs +34 -2
  95. package/lib/extensions/index.mjs +27 -0
  96. package/lib/extensions/loader.mjs +120 -0
  97. package/lib/extensions/manifest-schema.mjs +141 -0
  98. package/lib/extensions/manifests/anthropic.manifest.json +12 -0
  99. package/lib/extensions/manifests/atlassian-confluence.manifest.json +12 -0
  100. package/lib/extensions/manifests/atlassian-jira.manifest.json +53 -0
  101. package/lib/extensions/manifests/directory.manifest.json +12 -0
  102. package/lib/extensions/manifests/docling.manifest.json +37 -0
  103. package/lib/extensions/manifests/echo.manifest.json +8 -0
  104. package/lib/extensions/manifests/feedback.manifest.json +12 -0
  105. package/lib/extensions/manifests/github-copilot.manifest.json +12 -0
  106. package/lib/extensions/manifests/github.manifest.json +52 -0
  107. package/lib/extensions/manifests/linear.manifest.json +50 -0
  108. package/lib/extensions/manifests/local.manifest.json +12 -0
  109. package/lib/extensions/manifests/ollama.manifest.json +12 -0
  110. package/lib/extensions/manifests/openai.manifest.json +12 -0
  111. package/lib/extensions/manifests/openrouter-anthropic.manifest.json +12 -0
  112. package/lib/extensions/manifests/openrouter-deepseek.manifest.json +12 -0
  113. package/lib/extensions/manifests/openrouter-google.manifest.json +12 -0
  114. package/lib/extensions/manifests/openrouter-llama.manifest.json +12 -0
  115. package/lib/extensions/manifests/openrouter-qwen.manifest.json +12 -0
  116. package/lib/extensions/manifests/openrouter.manifest.json +12 -0
  117. package/lib/extensions/manifests/postgres.manifest.json +12 -0
  118. package/lib/extensions/manifests/salesforce.manifest.json +12 -0
  119. package/lib/extensions/manifests/slack.manifest.json +58 -0
  120. package/lib/extensions/manifests/whisper.manifest.json +36 -0
  121. package/lib/extensions/validate.mjs +175 -0
  122. package/lib/features.mjs +13 -9
  123. package/lib/flows/checkpoint.mjs +184 -0
  124. package/lib/flows/constants.mjs +27 -0
  125. package/lib/flows/define.mjs +146 -0
  126. package/lib/flows/engine.mjs +249 -0
  127. package/lib/flows/errors.mjs +19 -0
  128. package/lib/flows/index.mjs +27 -0
  129. package/lib/flows/joins.mjs +18 -0
  130. package/lib/flows/schema.mjs +90 -0
  131. package/lib/flows/state.mjs +31 -0
  132. package/lib/frameworks/loader.mjs +99 -0
  133. package/lib/frameworks/schema.mjs +157 -0
  134. package/lib/graph/build-from-corpus.mjs +67 -0
  135. package/lib/graph/build-from-embed.mjs +82 -0
  136. package/lib/graph/build-from-registry.mjs +164 -3
  137. package/lib/graph/cli.mjs +456 -12
  138. package/lib/graph/gap-queries.mjs +156 -0
  139. package/lib/graph/gaps.mjs +41 -0
  140. package/lib/graph/impacted.mjs +129 -0
  141. package/lib/graph/runtime-evidence.mjs +177 -0
  142. package/lib/graph/security-coverage.mjs +113 -0
  143. package/lib/graph/staleness.mjs +241 -10
  144. package/lib/graph/store.mjs +24 -7
  145. package/lib/graph/validate.mjs +161 -0
  146. package/lib/headhunt.mjs +9 -8
  147. package/lib/health-check.mjs +15 -7
  148. package/lib/hook-health.mjs +1 -1
  149. package/lib/hooks/agent-tracker.mjs +10 -4
  150. package/lib/hooks/edit-guard.mjs +3 -3
  151. package/lib/hooks/graph-impact-advisory.mjs +2 -2
  152. package/lib/hooks/guard-bash.mjs +41 -15
  153. package/lib/hooks/mcp-health-check.mjs +11 -4
  154. package/lib/hooks/model-fallback.mjs +50 -6
  155. package/lib/hooks/orchestration-dispatch-guard.mjs +14 -3
  156. package/lib/hooks/pre-compact.mjs +181 -173
  157. package/lib/hooks/rule-verifier.mjs +2 -1
  158. package/lib/hooks/session-reflect.mjs +2 -1
  159. package/lib/hooks/session-start.mjs +3 -3
  160. package/lib/host/readiness.mjs +109 -0
  161. package/lib/host-capabilities.mjs +13 -2
  162. package/lib/host-disposition.mjs +29 -8
  163. package/lib/identity.mjs +92 -0
  164. package/lib/ingest/degraded-extract.mjs +96 -0
  165. package/lib/ingest/docling-remote.mjs +2 -1
  166. package/lib/ingest/provider-extract.mjs +7 -19
  167. package/lib/ingest/sidecar-providers.mjs +196 -0
  168. package/lib/ingest-tooling.mjs +11 -5
  169. package/lib/init-unified.mjs +55 -38
  170. package/lib/init-update.mjs +2 -1
  171. package/lib/install/legacy-global-cleanup.mjs +25 -0
  172. package/lib/install/stage-project.mjs +41 -4
  173. package/lib/intake/daemon.mjs +99 -8
  174. package/lib/intake/git-queue.mjs +110 -38
  175. package/lib/intake/prepare.mjs +2 -0
  176. package/lib/intake/queue-registry.mjs +50 -0
  177. package/lib/intake/queue.mjs +133 -17
  178. package/lib/intake/session-prelude.mjs +57 -8
  179. package/lib/integrations/intake-integrations.mjs +61 -111
  180. package/lib/intent-classifier.mjs +43 -5
  181. package/lib/libreoffice-export.mjs +8 -8
  182. package/lib/logging/rotate.mjs +5 -4
  183. package/lib/mcp/broker.mjs +332 -17
  184. package/lib/mcp/denied-store.mjs +95 -0
  185. package/lib/mcp/destructive-approval.mjs +57 -0
  186. package/lib/mcp/destructive-gate.mjs +30 -0
  187. package/lib/mcp/dispatch-envelope.mjs +199 -0
  188. package/lib/mcp/memory-bridge.mjs +2 -1
  189. package/lib/mcp/server.mjs +185 -1268
  190. package/lib/mcp/tool-definitions-memory.mjs +376 -0
  191. package/lib/mcp/tool-definitions-project.mjs +271 -0
  192. package/lib/mcp/tool-definitions-skills.mjs +311 -0
  193. package/lib/mcp/tool-definitions-workflow.mjs +398 -0
  194. package/lib/mcp/tool-definitions.mjs +25 -0
  195. package/lib/mcp/tool-rate-limit.mjs +47 -0
  196. package/lib/mcp/tool-registry.mjs +107 -0
  197. package/lib/mcp/tool-safety.mjs +95 -0
  198. package/lib/mcp/tool-surface-parity.mjs +60 -0
  199. package/lib/mcp/tools/orchestration-delegation-next.tool.mjs +68 -0
  200. package/lib/mcp/tools/orchestration-run.mjs +197 -19
  201. package/lib/mcp/tools/orchestration-task-result.tool.mjs +77 -0
  202. package/lib/mcp/tools/project.mjs +25 -8
  203. package/lib/mcp/tools/provider-write.mjs +187 -0
  204. package/lib/mcp/tools/scope.mjs +0 -3
  205. package/lib/mcp/tools/skills.mjs +1 -1
  206. package/lib/mcp/tools/storage.mjs +2 -2
  207. package/lib/mcp/tools/web-search-governance.mjs +96 -0
  208. package/lib/mcp/tools/web-search.mjs +5 -76
  209. package/lib/mcp/transport/auth.mjs +238 -0
  210. package/lib/mcp/transport/http.mjs +136 -0
  211. package/lib/mcp/transport/mode.mjs +31 -0
  212. package/lib/mcp/transport/stdio.mjs +22 -0
  213. package/lib/mcp-catalog.json +4 -4
  214. package/lib/mcp-manager.mjs +34 -23
  215. package/lib/mcp-platform-config.mjs +53 -20
  216. package/lib/mode-capabilities.mjs +109 -0
  217. package/lib/model-router.mjs +42 -9
  218. package/lib/models/catalog.mjs +40 -1
  219. package/lib/net-guard.mjs +247 -0
  220. package/lib/observation-store.mjs +6 -2
  221. package/lib/ollama/provision-context.mjs +2 -1
  222. package/lib/opencode-config.mjs +22 -3
  223. package/lib/opencode-runtime-plugin.mjs +120 -2
  224. package/lib/oracle/actions.mjs +204 -10
  225. package/lib/oracle/cli.mjs +24 -3
  226. package/lib/oracle/daemon-entry.mjs +6 -0
  227. package/lib/oracle/dispatch.mjs +2 -1
  228. package/lib/oracle/execute.mjs +2 -2
  229. package/lib/oracle/gaps.mjs +3 -3
  230. package/lib/oracle/heartbeat.mjs +53 -0
  231. package/lib/oracle/read-model.mjs +69 -13
  232. package/lib/oracle/reconcile.mjs +3 -46
  233. package/lib/oracle/routing.mjs +37 -31
  234. package/lib/oracle/synthesize.mjs +1 -1
  235. package/lib/orchestration/classification.mjs +434 -0
  236. package/lib/orchestration/delegation-flow.mjs +132 -0
  237. package/lib/orchestration/flow-selection.mjs +418 -0
  238. package/lib/orchestration/gates.mjs +244 -0
  239. package/lib/orchestration/host-sampling.mjs +121 -0
  240. package/lib/orchestration/policy-constants.mjs +48 -0
  241. package/lib/orchestration/provider-outcome.mjs +197 -0
  242. package/lib/orchestration/readiness.mjs +114 -13
  243. package/lib/orchestration/run-store-postgres.mjs +32 -26
  244. package/lib/orchestration/run-store-sqlite.mjs +8 -14
  245. package/lib/orchestration/run-store.mjs +25 -12
  246. package/lib/orchestration/runtime.mjs +508 -62
  247. package/lib/orchestration/store.mjs +87 -12
  248. package/lib/orchestration/trace-store.mjs +125 -0
  249. package/lib/orchestration/web-capability.mjs +60 -0
  250. package/lib/orchestration/worker-runtime.mjs +162 -0
  251. package/lib/orchestration/worker.mjs +763 -80
  252. package/lib/orchestration-policy.mjs +67 -1111
  253. package/lib/output-quality.mjs +61 -2
  254. package/lib/packs/cli.mjs +144 -0
  255. package/lib/packs/core-pack.mjs +112 -0
  256. package/lib/packs/enablement.mjs +187 -0
  257. package/lib/packs/index.mjs +23 -0
  258. package/lib/packs/loader.mjs +176 -0
  259. package/lib/packs/manifest-schema.mjs +58 -0
  260. package/lib/packs/prompts.mjs +120 -0
  261. package/lib/packs/validate.mjs +208 -0
  262. package/lib/path-policy.mjs +56 -0
  263. package/lib/plugin-registry.mjs +4 -5
  264. package/lib/policy/audit-gate.mjs +42 -0
  265. package/lib/policy/consumption-budget.mjs +149 -0
  266. package/lib/policy/engine.mjs +81 -6
  267. package/lib/policy/role-authority.mjs +89 -0
  268. package/lib/prompt-composer.js +19 -3
  269. package/lib/providers/contract/adapters/confluence/governed-write.mjs +215 -0
  270. package/lib/providers/contract/adapters/confluence/manifest.json +17 -0
  271. package/lib/providers/contract/adapters/confluence/transport.mjs +135 -0
  272. package/lib/providers/contract/adapters/github/governed-write.mjs +121 -0
  273. package/lib/providers/contract/adapters/github/index.mjs +38 -3
  274. package/lib/providers/contract/adapters/jira/adf.mjs +151 -0
  275. package/lib/providers/contract/adapters/jira/createmeta.mjs +143 -0
  276. package/lib/providers/contract/adapters/jira/governed-write.mjs +182 -0
  277. package/lib/providers/contract/adapters/jira/manifest.json +17 -0
  278. package/lib/providers/contract/adapters/jira/transport.mjs +119 -0
  279. package/lib/providers/contract.mjs +207 -0
  280. package/lib/providers/credential-bootstrap.mjs +7 -4
  281. package/lib/providers/credential-sources.mjs +14 -2
  282. package/lib/providers/directory/index.mjs +261 -0
  283. package/lib/providers/feedback/index.mjs +392 -0
  284. package/lib/providers/filter-audit.mjs +68 -0
  285. package/lib/providers/filter-schema.mjs +54 -0
  286. package/lib/providers/github/index.mjs +31 -0
  287. package/lib/providers/instance-config.mjs +215 -0
  288. package/lib/providers/op-locate.mjs +96 -0
  289. package/lib/providers/op-run.mjs +64 -9
  290. package/lib/providers/registry.mjs +26 -3
  291. package/lib/providers/secret-audit-wiring.mjs +41 -18
  292. package/lib/providers/secret-resolver.mjs +263 -31
  293. package/lib/publish-template.mjs +6 -3
  294. package/lib/publish-tooling.mjs +4 -0
  295. package/lib/publish.mjs +32 -4
  296. package/lib/queue/pg-queue.mjs +395 -0
  297. package/lib/reflect.mjs +2 -1
  298. package/lib/registry/assemble.mjs +28 -2
  299. package/lib/registry/catalog.mjs +6 -0
  300. package/lib/registry/consolidation.mjs +8 -1
  301. package/lib/registry/custom-scaffold.mjs +200 -0
  302. package/lib/registry/custom-schema.mjs +137 -0
  303. package/lib/registry/loader.mjs +15 -4
  304. package/lib/registry/manifests/format-engines.default.json +15 -0
  305. package/lib/registry/manifests/surface-map.default.json +46 -0
  306. package/lib/registry/retired-paths.mjs +1 -0
  307. package/lib/registry/surface-map.mjs +100 -50
  308. package/lib/registry/validate.mjs +3 -3
  309. package/lib/render-visual-check.mjs +240 -0
  310. package/lib/resources/budget.mjs +40 -17
  311. package/lib/roles/flavor-bindings.mjs +36 -14
  312. package/lib/roles/gateway.mjs +15 -8
  313. package/lib/roots.mjs +107 -0
  314. package/lib/runtime/uv-bootstrap.mjs +32 -6
  315. package/lib/runtime/whisper-bootstrap.mjs +11 -3
  316. package/lib/runtime-env.mjs +5 -2
  317. package/lib/sandbox.mjs +1 -1
  318. package/lib/scheduler/index.mjs +8 -20
  319. package/lib/schema-infer.mjs +31 -2
  320. package/lib/scopes/lifecycle.mjs +29 -25
  321. package/lib/scopes/loader.mjs +49 -12
  322. package/lib/scopes/teams.mjs +1 -1
  323. package/lib/security/ingest-boundary.mjs +80 -0
  324. package/lib/security/recall-wrapper.mjs +99 -0
  325. package/lib/security/trust.mjs +132 -0
  326. package/lib/service-manager.mjs +93 -24
  327. package/lib/setup.mjs +41 -23
  328. package/lib/skills-apply.mjs +4 -2
  329. package/lib/specialists/postconditions.mjs +2 -2
  330. package/lib/state-root.mjs +147 -0
  331. package/lib/status.mjs +597 -6
  332. package/lib/storage/admin.mjs +84 -7
  333. package/lib/storage/backend-registry.mjs +73 -0
  334. package/lib/storage/backend.mjs +63 -9
  335. package/lib/storage/embeddings-openai.mjs +12 -2
  336. package/lib/storage/hybrid-query.mjs +11 -3
  337. package/lib/storage/retrieval-hardening.mjs +384 -0
  338. package/lib/storage/shared-memory.mjs +158 -0
  339. package/lib/storage/vector-client.mjs +69 -2
  340. package/lib/team/health.mjs +72 -0
  341. package/lib/telemetry/backends/local.mjs +9 -3
  342. package/lib/telemetry/client.mjs +3 -7
  343. package/lib/template-registry.mjs +10 -12
  344. package/lib/tenant/context.mjs +82 -0
  345. package/lib/tenant/isolation.mjs +129 -0
  346. package/lib/test-corpus-inventory.mjs +103 -2
  347. package/lib/uninstall/uninstall.mjs +78 -12
  348. package/lib/validator.mjs +4 -6
  349. package/lib/worker/entrypoint.mjs +2 -1
  350. package/lib/worker/run.mjs +2 -2
  351. package/lib/worker/trace.mjs +5 -11
  352. package/lib/workflow-state.mjs +52 -8
  353. package/lib/workflows/liveness.mjs +203 -0
  354. package/lib/workflows/loader.mjs +177 -0
  355. package/lib/workflows/manifest-schema.mjs +71 -0
  356. package/lib/workflows/surface-parity.mjs +118 -0
  357. package/lib/workflows/validate.mjs +127 -0
  358. package/lib/writes/control-plane.mjs +140 -0
  359. package/lib/writes/envelope.mjs +206 -0
  360. package/lib/writes/sent-log.mjs +86 -0
  361. package/lib/writes/write-intent.mjs +109 -0
  362. package/package.json +20 -7
  363. package/personas/construct.md +12 -3
  364. package/registry/agent-manifest.json +117 -0
  365. package/registry/capabilities.json +1987 -0
  366. package/rules/common/comments.md +1 -0
  367. package/schemas/brand-voice.schema.json +24 -0
  368. package/schemas/capability-registry.schema.json +72 -0
  369. package/schemas/certification-run.schema.json +130 -0
  370. package/schemas/demo-recording.schema.json +46 -0
  371. package/schemas/eval-dataset.schema.json +79 -0
  372. package/schemas/execution-capability-profile.schema.json +46 -0
  373. package/schemas/execution-policy.schema.json +114 -0
  374. package/schemas/improvement-proposal.schema.json +65 -0
  375. package/schemas/mcp-tool-output.schema.json +61 -0
  376. package/schemas/platform-capabilities.schema.json +83 -0
  377. package/schemas/project-config.schema.json +215 -0
  378. package/schemas/project-demo.schema.json +60 -0
  379. package/schemas/provider-behavior-matrix.schema.json +91 -0
  380. package/schemas/scope.schema.json +197 -0
  381. package/schemas/specialist-trace.schema.json +107 -0
  382. package/schemas/team.schema.json +99 -0
  383. package/schemas/unified-registry.schema.json +546 -0
  384. package/scripts/sync-specialists.mjs +336 -106
  385. package/skills/docs/adr-workflow.md +1 -1
  386. package/skills/docs/codebase-research-workflow.md +3 -3
  387. package/skills/docs/prd-workflow.md +5 -6
  388. package/skills/docs/runbook-workflow.md +2 -2
  389. package/skills/docs/user-research-workflow.md +3 -3
  390. package/skills/operating/fleet-health-routing.md +77 -0
  391. package/skills/roles/ai-engineer.md +1 -1
  392. package/skills/roles/architect.md +0 -1
  393. package/skills/roles/business-strategist.md +1 -1
  394. package/skills/roles/data-analyst.telemetry.md +1 -1
  395. package/skills/roles/data-engineer.md +1 -1
  396. package/skills/roles/data-engineer.pipeline.md +1 -1
  397. package/skills/roles/data-engineer.vector-retrieval.md +1 -2
  398. package/skills/roles/data-engineer.warehouse.md +1 -1
  399. package/skills/roles/designer.accessibility.md +1 -1
  400. package/skills/roles/designer.md +0 -1
  401. package/skills/roles/devil-advocate.md +1 -1
  402. package/skills/roles/docs-keeper.md +1 -1
  403. package/skills/roles/evaluator.md +1 -1
  404. package/skills/roles/explorer.md +1 -1
  405. package/skills/roles/platform-engineer.md +1 -1
  406. package/skills/roles/qa.ai-eval.md +1 -2
  407. package/skills/roles/qa.api-contract.md +0 -1
  408. package/skills/roles/qa.data-pipeline.md +0 -1
  409. package/skills/roles/qa.md +0 -1
  410. package/skills/roles/qa.web-ui.md +0 -1
  411. package/skills/roles/release-manager.md +1 -1
  412. package/skills/roles/researcher.md +0 -2
  413. package/skills/roles/reviewer.md +0 -3
  414. package/skills/roles/security.ai.md +1 -1
  415. package/skills/roles/security.legal-compliance.md +1 -1
  416. package/skills/roles/security.md +0 -1
  417. package/skills/roles/security.privacy.md +0 -1
  418. package/skills/roles/security.supply-chain.md +1 -1
  419. package/skills/roles/sre.md +1 -1
  420. package/skills/roles/test-automation.md +1 -1
  421. package/skills/roles/trace-reviewer.md +1 -1
  422. package/skills/roles/ux-researcher.md +1 -1
  423. package/specialists/artifact-manifest.json +36 -36
  424. package/specialists/org/contracts/accessibility-to-qa.json +11 -3
  425. package/specialists/org/contracts/any-to-business-strategist.json +19 -7
  426. package/specialists/org/contracts/any-to-debugger.json +7 -1
  427. package/specialists/org/contracts/any-to-designer.json +7 -1
  428. package/specialists/org/contracts/any-to-docs-keeper.json +18 -4
  429. package/specialists/org/contracts/any-to-explorer.json +13 -4
  430. package/specialists/org/contracts/any-to-sre-incident.json +6 -2
  431. package/specialists/org/contracts/any-to-trace-reviewer.json +16 -4
  432. package/specialists/org/contracts/architect-to-ai-engineer.json +6 -2
  433. package/specialists/org/contracts/architect-to-data-engineer.json +17 -5
  434. package/specialists/org/contracts/architect-to-devil-advocate.json +11 -3
  435. package/specialists/org/contracts/architect-to-engineer.json +20 -4
  436. package/specialists/org/contracts/architect-to-evaluator.json +15 -5
  437. package/specialists/org/contracts/architect-to-legal-compliance.json +15 -5
  438. package/specialists/org/contracts/architect-to-operations.json +17 -4
  439. package/specialists/org/contracts/architect-to-platform-engineer.json +20 -4
  440. package/specialists/org/contracts/construct-to-orchestrator.json +10 -2
  441. package/specialists/org/contracts/data-analyst-to-product-manager.json +11 -2
  442. package/specialists/org/contracts/engineer-to-qa.json +20 -4
  443. package/specialists/org/contracts/engineer-to-reviewer.json +29 -5
  444. package/specialists/org/contracts/explorer-to-engineer.json +11 -3
  445. package/specialists/org/contracts/legal-compliance-to-release-manager.json +12 -4
  446. package/specialists/org/contracts/operations-to-user.json +53 -0
  447. package/specialists/org/contracts/operations-triage-output.json +53 -0
  448. package/specialists/org/contracts/pm-requirements-candidates.json +53 -0
  449. package/specialists/org/contracts/product-manager-to-architect.json +30 -10
  450. package/specialists/org/contracts/product-manager-to-data-analyst.json +13 -3
  451. package/specialists/org/contracts/product-manager-to-ux-researcher.json +15 -5
  452. package/specialists/org/contracts/qa-to-release-manager.json +11 -3
  453. package/specialists/org/contracts/researcher-to-architect.json +10 -2
  454. package/specialists/org/contracts/researcher-to-product-manager.json +16 -5
  455. package/specialists/org/contracts/reviewer-to-security.json +17 -3
  456. package/specialists/org/contracts/test-automation-to-engineer.json +11 -3
  457. package/specialists/org/contracts/trace-reviewer-to-sre.json +12 -4
  458. package/specialists/org/contracts/user-to-construct.json +11 -4
  459. package/specialists/org/frameworks/cx-architect-constraint-option-failure.md +66 -0
  460. package/specialists/org/frameworks/cx-engineer-feasibility-blast-radius.md +66 -0
  461. package/specialists/org/frameworks/cx-ops-dependency-sequencing.md +74 -0
  462. package/specialists/org/frameworks/cx-pm-value-tradeoff.md +66 -0
  463. package/specialists/org/frameworks/cx-qa-risk-based-coverage.md +69 -0
  464. package/specialists/org/groups/engineering-group.json +2 -6
  465. package/specialists/org/groups/governance-group.json +2 -3
  466. package/specialists/org/groups/operations-group.json +5 -8
  467. package/specialists/org/groups/product-group.json +4 -8
  468. package/specialists/org/groups/quality-group.json +3 -7
  469. package/specialists/org/groups/strategy-group.json +6 -9
  470. package/specialists/org/models.json.example +8 -0
  471. package/specialists/org/scopes/creative.json +6 -1
  472. package/specialists/org/scopes/operations.json +7 -1
  473. package/specialists/org/scopes/research.json +6 -1
  474. package/specialists/org/scopes/rnd.json +7 -1
  475. package/specialists/org/specialists/cx-architect.json +27 -8
  476. package/specialists/org/specialists/cx-designer.json +22 -8
  477. package/specialists/org/specialists/cx-engineer.json +71 -7
  478. package/specialists/org/specialists/cx-operations.json +89 -15
  479. package/specialists/org/specialists/cx-orchestrator.json +16 -4
  480. package/specialists/org/specialists/cx-product-manager.json +28 -9
  481. package/specialists/org/specialists/cx-qa.json +16 -6
  482. package/specialists/org/specialists/cx-researcher.json +41 -7
  483. package/specialists/org/specialists/cx-reviewer.json +61 -11
  484. package/specialists/org/specialists/cx-security.json +30 -10
  485. package/specialists/org/teams/design-team.json +3 -4
  486. package/specialists/org/teams/engineering-team.json +3 -10
  487. package/specialists/org/teams/governance-team.json +3 -5
  488. package/specialists/org/teams/operations-team.json +6 -12
  489. package/specialists/org/teams/product-management-team.json +2 -3
  490. package/specialists/org/teams/quality-team.json +4 -12
  491. package/specialists/org/teams/research-team.json +3 -3
  492. package/specialists/org/teams/strategy-team.json +7 -14
  493. package/specialists/prompts/cx-architect.md +20 -1
  494. package/specialists/prompts/cx-data-analyst.md +1 -1
  495. package/specialists/prompts/cx-designer.md +12 -4
  496. package/specialists/prompts/cx-engineer.md +15 -1
  497. package/specialists/prompts/cx-operations.md +14 -2
  498. package/specialists/prompts/cx-orchestrator.md +9 -5
  499. package/specialists/prompts/cx-product-manager.md +5 -1
  500. package/specialists/prompts/cx-qa.md +6 -2
  501. package/specialists/prompts/cx-researcher.md +27 -31
  502. package/specialists/prompts/cx-reviewer.md +19 -1
  503. package/specialists/prompts/cx-security.md +5 -1
  504. package/templates/distribution/construct-brand.typ +123 -59
  505. package/templates/distribution/construct-decision.typ +6 -3
  506. package/templates/distribution/construct-pdf.typ +11 -4
  507. package/templates/distribution/construct-prd.typ +6 -3
  508. package/templates/distribution/construct-research.typ +7 -4
  509. package/vendor/pandoc-ext/README.md +3 -0
  510. package/vendor/pandoc-ext/diagram.lua +687 -0
  511. package/lib/providers/contract/adapters/git/index.mjs +0 -115
  512. package/lib/providers/contract/adapters/slack/index.mjs +0 -175
  513. package/specialists/org/contracts/business-strategist-to-product-manager.json +0 -39
  514. package/specialists/org/contracts/construct-to-rd-lead.json +0 -53
  515. package/specialists/org/contracts/data-engineer-to-platform-engineer.json +0 -36
  516. package/specialists/org/contracts/designer-to-accessibility.json +0 -36
  517. package/specialists/org/contracts/platform-engineer-to-engineer.json +0 -31
  518. package/specialists/org/contracts/qa-to-test-automation.json +0 -42
  519. package/specialists/org/contracts/rd-lead-to-architect.json +0 -38
  520. package/specialists/org/contracts/sre-to-release-manager.json +0 -36
  521. package/specialists/org/specialists/cx-accessibility.json +0 -69
  522. package/specialists/org/specialists/cx-ai-engineer.json +0 -75
  523. package/specialists/org/specialists/cx-business-strategist.json +0 -72
  524. package/specialists/org/specialists/cx-data-engineer.json +0 -71
  525. package/specialists/org/specialists/cx-devil-advocate.json +0 -71
  526. package/specialists/org/specialists/cx-docs-keeper.json +0 -82
  527. package/specialists/org/specialists/cx-evaluator.json +0 -69
  528. package/specialists/org/specialists/cx-explorer.json +0 -69
  529. package/specialists/org/specialists/cx-legal-compliance.json +0 -74
  530. package/specialists/org/specialists/cx-oracle.json +0 -46
  531. package/specialists/org/specialists/cx-platform-engineer.json +0 -80
  532. package/specialists/org/specialists/cx-rd-lead.json +0 -73
  533. package/specialists/org/specialists/cx-release-manager.json +0 -77
  534. package/specialists/org/specialists/cx-sre.json +0 -94
  535. package/specialists/org/specialists/cx-test-automation.json +0 -69
  536. package/specialists/org/specialists/cx-trace-reviewer.json +0 -69
  537. package/specialists/org/specialists/cx-ux-researcher.json +0 -68
  538. package/specialists/org/teams/accessibility-team.json +0 -39
  539. package/specialists/org/teams/ux-research-team.json +0 -39
  540. package/specialists/prompts/cx-accessibility.md +0 -55
  541. package/specialists/prompts/cx-ai-engineer.md +0 -124
  542. package/specialists/prompts/cx-business-strategist.md +0 -58
  543. package/specialists/prompts/cx-data-engineer.md +0 -55
  544. package/specialists/prompts/cx-devil-advocate.md +0 -59
  545. package/specialists/prompts/cx-docs-keeper.md +0 -164
  546. package/specialists/prompts/cx-evaluator.md +0 -49
  547. package/specialists/prompts/cx-explorer.md +0 -71
  548. package/specialists/prompts/cx-legal-compliance.md +0 -58
  549. package/specialists/prompts/cx-oracle.md +0 -98
  550. package/specialists/prompts/cx-platform-engineer.md +0 -97
  551. package/specialists/prompts/cx-rd-lead.md +0 -59
  552. package/specialists/prompts/cx-release-manager.md +0 -54
  553. package/specialists/prompts/cx-sre.md +0 -111
  554. package/specialists/prompts/cx-test-automation.md +0 -55
  555. package/specialists/prompts/cx-trace-reviewer.md +0 -101
  556. package/specialists/prompts/cx-ux-researcher.md +0 -53
@@ -2,7 +2,9 @@
2
2
  * lib/embed/providers/registry.mjs — ProviderRegistry.
3
3
  *
4
4
  * Holds named provider instances and exposes an async factory that builds
5
- * the standard set from environment variables. Each provider implements:
5
+ * the standard set from the unified extension manifest registry (LMCP-B1,
6
+ * lib/extensions/*) rather than a second, hardcoded env-var table. Each
7
+ * embed-mode provider implements:
6
8
  *
7
9
  * read(ref, opts) → Promise<Item[]>
8
10
  * ref: source-type string e.g. 'prs', 'issues', 'commits', 'messages'
@@ -11,11 +13,106 @@
11
13
  * write(action) → Promise<void> (optional — only mutation providers)
12
14
  * action: { type, channel?, text?, … }
13
15
  *
16
+ * `fromEnv()` reads the merged builtin/user/project manifest tiers, keeps
17
+ * only `kind: 'data-source'` manifests that declare the `read` capability
18
+ * and have a registered embed adapter (ADAPTERS below), and gates each on
19
+ * the credential predicate declared next to that adapter. A manifest with
20
+ * no adapter entry, or whose credential predicate fails, is never silently
21
+ * dropped: `fromEnv()` also returns the unavailable set with a reason so
22
+ * callers (construct status, `describe()`) can surface "configured but
23
+ * unavailable" instead of a provider that appears to simply not exist.
24
+ *
14
25
  * Providers are registered by name and can be swapped for test doubles.
15
26
  */
16
27
 
28
+ import { loadManifestsFromDir, mergeManifests, resolveManifestDirs } from '../../extensions/loader.mjs';
29
+
30
+ /**
31
+ * Registered embed adapters keyed by unified-manifest id. Each entry names
32
+ * the module to dynamically import, the aliases to register the instance
33
+ * under, how to build the constructor options from env, and a credential
34
+ * predicate over the manifest's own `secretEnvKeys` — so "is this provider
35
+ * usable" is derived from the manifest's declared keys, not re-hardcoded.
36
+ *
37
+ * `credentials` is one of:
38
+ * { anyOf: [...] } — usable if at least one listed env var is set (GitHub)
39
+ * { allOf: [...] } — usable only if every listed env var is set (Jira)
40
+ */
41
+ const ADAPTERS = {
42
+ github: {
43
+ aliases: ['github', 'gh'],
44
+ credentials: { anyOf: ['GITHUB_TOKEN', 'GITHUB_PERSONAL_ACCESS_TOKEN', 'GH_TOKEN'] },
45
+ load: () => import('./github.mjs'),
46
+ build: (mod, env) => new mod.GitHubProvider({
47
+ token: env.GITHUB_TOKEN || env.GITHUB_PERSONAL_ACCESS_TOKEN || env.GH_TOKEN,
48
+ }),
49
+ },
50
+ slack: {
51
+ aliases: ['slack'],
52
+ credentials: { anyOf: ['SLACK_BOT_TOKEN'] },
53
+ load: () => import('./slack.mjs'),
54
+ build: (mod, env) => new mod.SlackProvider({
55
+ token: env.SLACK_BOT_TOKEN,
56
+ teamId: env.SLACK_TEAM_ID,
57
+ }),
58
+ },
59
+ linear: {
60
+ aliases: ['linear'],
61
+ credentials: { anyOf: ['LINEAR_API_KEY'] },
62
+ load: () => import('./linear.mjs'),
63
+ build: (mod, env) => new mod.LinearProvider({
64
+ apiKey: env.LINEAR_API_KEY,
65
+ }),
66
+ },
67
+ 'atlassian-jira': {
68
+ aliases: ['jira', 'atlassian'],
69
+ credentials: { allOf: ['JIRA_BASE_URL', 'JIRA_EMAIL', 'JIRA_API_TOKEN'] },
70
+ load: () => import('./jira.mjs'),
71
+ build: (mod, env) => new mod.JiraProvider({
72
+ baseUrl: env.JIRA_BASE_URL,
73
+ email: env.JIRA_EMAIL,
74
+ token: env.JIRA_API_TOKEN,
75
+ }),
76
+ },
77
+ };
78
+
79
+ function credentialStatus(predicate, env) {
80
+ if (!predicate) return { ok: true, missing: [] };
81
+ if (predicate.anyOf) {
82
+ const ok = predicate.anyOf.some((key) => !!env[key]);
83
+ return { ok, missing: ok ? [] : predicate.anyOf };
84
+ }
85
+ if (predicate.allOf) {
86
+ const missing = predicate.allOf.filter((key) => !env[key]);
87
+ return { ok: missing.length === 0, missing };
88
+ }
89
+ return { ok: true, missing: [] };
90
+ }
91
+
92
+ /**
93
+ * Load the merged data-source manifests (builtin < user < project tiers)
94
+ * that also carry a registered embed adapter. Manifests for kinds embed
95
+ * mode cannot use (e.g. ingestion-provider) are excluded here rather than
96
+ * downstream, so every caller of this helper sees the same candidate set.
97
+ */
98
+ function candidateManifests(rootDir) {
99
+ const { builtin, user, project } = resolveManifestDirs({ rootDir });
100
+ const { manifests: builtinManifests } = loadManifestsFromDir(builtin);
101
+ const { manifests: userManifests } = loadManifestsFromDir(user);
102
+ const { manifests: projectManifests } = loadManifestsFromDir(project);
103
+ const merged = mergeManifests(builtinManifests, userManifests, projectManifests);
104
+
105
+ return merged.filter((m) => (
106
+ m.kind === 'data-source' &&
107
+ Array.isArray(m.capabilities) &&
108
+ m.capabilities.includes('read') &&
109
+ Object.prototype.hasOwnProperty.call(ADAPTERS, m.id)
110
+ ));
111
+ }
112
+
17
113
  export class ProviderRegistry {
18
114
  #providers = new Map();
115
+ #unavailable = [];
19
116
 
20
117
  /**
21
118
  * Register a provider under one or more names.
@@ -68,46 +165,56 @@ export class ProviderRegistry {
68
165
  }
69
166
 
70
167
  /**
71
- * Build a registry pre-populated with all concrete providers derived
72
- * from the supplied environment. Providers whose required credentials
73
- * are absent are silently omitted callers get a warning at runtime
74
- * when a source references a missing provider.
168
+ * Manifest-declared data-source providers this registry knows about but
169
+ * did not register each entry names why, so status surfaces render
170
+ * "configured but unavailable" instead of the provider vanishing.
171
+ * @returns {{ id: string, displayName: string, reason: string }[]}
172
+ */
173
+ unavailable() {
174
+ return this.#unavailable;
175
+ }
176
+
177
+ /**
178
+ * Build a registry pre-populated with every unified-registry data-source
179
+ * manifest (LMCP-B1, lib/extensions/*) that declares the `read` capability
180
+ * and has a registered embed adapter, gated on that adapter's credential
181
+ * predicate. Providers whose required credentials are absent are not
182
+ * registered but are recorded in `unavailable()` with a reason — callers
183
+ * get an explicit "configured but unavailable" signal rather than a
184
+ * provider that silently doesn't exist.
75
185
  *
76
186
  * @param {object} env - Merged environment (loadConstructEnv output)
187
+ * @param {object} [opts]
188
+ * @param {string} [opts.rootDir] - Project root for project-tier manifests
77
189
  * @returns {Promise<ProviderRegistry>}
78
190
  */
79
- static async fromEnv(env = process.env) {
191
+ static async fromEnv(env = process.env, { rootDir = process.cwd() } = {}) {
80
192
  const registry = new ProviderRegistry();
81
193
 
82
- if (env.GITHUB_TOKEN || env.GITHUB_PERSONAL_ACCESS_TOKEN) {
83
- const { GitHubProvider } = await import('./github.mjs');
84
- registry.register(['github', 'gh'], new GitHubProvider({
85
- token: env.GITHUB_TOKEN || env.GITHUB_PERSONAL_ACCESS_TOKEN,
86
- }));
87
- }
88
-
89
- if (env.SLACK_BOT_TOKEN) {
90
- const { SlackProvider } = await import('./slack.mjs');
91
- registry.register(['slack'], new SlackProvider({
92
- token: env.SLACK_BOT_TOKEN,
93
- teamId: env.SLACK_TEAM_ID,
94
- }));
95
- }
194
+ for (const manifest of candidateManifests(rootDir)) {
195
+ const adapter = ADAPTERS[manifest.id];
196
+ const { ok, missing } = credentialStatus(adapter.credentials, env);
96
197
 
97
- if (env.LINEAR_API_KEY) {
98
- const { LinearProvider } = await import('./linear.mjs');
99
- registry.register(['linear'], new LinearProvider({
100
- apiKey: env.LINEAR_API_KEY,
101
- }));
102
- }
198
+ if (!ok) {
199
+ registry.#unavailable.push({
200
+ id: manifest.id,
201
+ displayName: manifest.id,
202
+ reason: `missing credentials: ${missing.join(', ')}`,
203
+ });
204
+ continue;
205
+ }
103
206
 
104
- if (env.JIRA_API_TOKEN && env.JIRA_USER_EMAIL && env.JIRA_BASE_URL) {
105
- const { JiraProvider } = await import('./jira.mjs');
106
- registry.register(['jira', 'atlassian'], new JiraProvider({
107
- baseUrl: env.JIRA_BASE_URL,
108
- email: env.JIRA_USER_EMAIL,
109
- token: env.JIRA_API_TOKEN,
110
- }));
207
+ try {
208
+ const mod = await adapter.load();
209
+ const instance = adapter.build(mod, env);
210
+ registry.register(adapter.aliases, instance);
211
+ } catch (err) {
212
+ registry.#unavailable.push({
213
+ id: manifest.id,
214
+ displayName: manifest.id,
215
+ reason: `adapter failed to load: ${err.message}`,
216
+ });
217
+ }
111
218
  }
112
219
 
113
220
  return registry;
@@ -9,6 +9,7 @@
9
9
  import os from 'node:os';
10
10
  import path from 'node:path';
11
11
  import { prepareConstructEnv } from '../runtime-env.mjs';
12
+ import { enableSecretAuditTrail } from '../providers/secret-audit-wiring.mjs';
12
13
  import { EmbedDaemon } from './daemon.mjs';
13
14
 
14
15
  function parseArgv(argv) {
@@ -18,6 +19,10 @@ function parseArgv(argv) {
18
19
  return null;
19
20
  }
20
21
 
22
+ // Snapshot ticks resolve provider credentials in the daemon's own process; wiring
23
+ // the sink here records those op reads on the same trail as the CLI entrypoint.
24
+ enableSecretAuditTrail();
25
+
21
26
  const configPath = parseArgv(process.argv.slice(2));
22
27
  const env = prepareConstructEnv();
23
28
 
@@ -100,6 +100,10 @@ function buildModels(env) {
100
100
  local: f.local,
101
101
  requiresEnv: f.requiresEnv,
102
102
  configured: f.configured,
103
+ // `configured` is a presence check (env/op:// ref/CLI session found), not proof
104
+ // the credential authenticates — deep verification is the opt-in provider probe
105
+ // (construct doctor --probe-providers / orchestrate preflight --probe).
106
+ configuredBasis: 'presence',
103
107
  healthStatus: 'unknown',
104
108
  }));
105
109
  const tiers = resolveModelTiers({ env });
@@ -162,7 +162,7 @@ export function resolveExecution(request = {}, { env = process.env, cwd = proces
162
162
  let degradationReason = null;
163
163
  if (!orchestrationAvailable) {
164
164
  degraded = true;
165
- degradationReason = `Model could not be resolved; orchestration requires a runnable model — ${modelResolution.error?.reason || 'no model available'}.`;
165
+ degradationReason = `Model could not be resolved; orchestration requires a runnable model — ${(modelResolution.error?.reason || 'no model available').replace(/\.$/, '')}.`;
166
166
  } else if (requestedStrategy === 'orchestrated') {
167
167
  degraded = true;
168
168
  degradationReason = `Orchestration was requested but no orchestration plan is available${workflowType ? ` for workflowType "${workflowType}"` : ''}.`;
@@ -15,7 +15,14 @@
15
15
  * claims provider health it cannot verify (`healthStatus` defaults to unknown).
16
16
  */
17
17
 
18
- import { describeModelFamily, listModelFamilies } from '../model-router.mjs';
18
+ import {
19
+ defaultModelRegistryPath,
20
+ describeModelFamily,
21
+ formatModelResolutionNotices,
22
+ isModelAvailable,
23
+ listModelFamilies,
24
+ resolveValidatedModel,
25
+ } from '../model-router.mjs';
19
26
  import { resolveModelTiers } from '../model-registry.mjs';
20
27
  import { resolveProviderCapabilitiesSync } from '../provider-capabilities.js';
21
28
 
@@ -158,9 +165,24 @@ export function resolveEmbeddedModel(request = {}, { env = process.env, registry
158
165
  });
159
166
  }
160
167
 
161
- const tiers = resolveModelTiers({ env, registryPath });
168
+ const tiers = resolveModelTiers({ env, registryPath: registryPath ?? defaultModelRegistryPath(env) });
162
169
  const defaultModel = tiers.models[tier];
163
170
  if (defaultModel) {
171
+ // The env/registry tier pin is a preference, not blind truth: validate it
172
+ // against the retired-slug denylist and provider-configured catalog before
173
+ // emitting it, so a stale pin (e.g. a retired Anthropic slug) surfaces a
174
+ // named warning instead of resolving silently (construct-uccl.4). Route
175
+ // through resolveValidatedModel so a rejected pin also surfaces a
176
+ // catalog-wide recommended replacement, not just the rejection notice.
177
+ const validation = isModelAvailable(defaultModel, { env, strictPin: true });
178
+ if (!validation.ok) {
179
+ const validated = resolveValidatedModel({ env, requested: defaultModel });
180
+ for (const notice of validated.notices) warnings.push(notice);
181
+ if (!validated.notices.length) {
182
+ for (const notice of formatModelResolutionNotices({ rejected: validation })) warnings.push(notice);
183
+ }
184
+ }
185
+
164
186
  const fallbackReason = hadHostContext
165
187
  ? 'Host context could not be honored within its family; used the Construct tier default after cross-provider fallback was permitted.'
166
188
  : 'No host context supplied; used the Construct tier default.';
@@ -178,10 +200,38 @@ export function resolveEmbeddedModel(request = {}, { env = process.env, registry
178
200
  });
179
201
  }
180
202
 
203
+ // No pin resolved (env/registry tier-default came back empty). Before
204
+ // degrading, check whether ANY provider family has a credential configured
205
+ // and fall back to that family's tier default — the remediation on the
206
+ // config-error path ("configure a provider credential") is otherwise
207
+ // unfollowable, since this path never consulted credentials at all
208
+ // (construct-uccl.2). An explicit pin always wins over this fallback
209
+ // because it is only reached once resolveModelTiers found no pin.
210
+ const configuredFamily = listModelFamilies({ env, allowAmbient }).find((f) => f.configured && f.tiers[tier]);
211
+ if (configuredFamily) {
212
+ const model = configuredFamily.tiers[tier];
213
+ warnings.push(
214
+ `Model tier '${tier}' is unpinned; using ${model} from the ${configuredFamily.id} credential family. `
215
+ + `Pin with CX_MODEL_${tier.toUpperCase()} to override.`,
216
+ );
217
+ return success({
218
+ selectedModel: model,
219
+ family: configuredFamily,
220
+ tier,
221
+ resolutionSource: 'credential-family-fallback',
222
+ fallbackReason: `No tier pin configured; resolved the ${tier} model from the ${configuredFamily.id} credential family.`,
223
+ tierSource: 'credential-family-fallback',
224
+ capabilities,
225
+ warnings,
226
+ env,
227
+ allowAmbient,
228
+ });
229
+ }
230
+
181
231
  return configError({
182
232
  tier,
183
233
  reason: `No model could be resolved for the ${tier} tier.`,
184
- remediation: 'Set CX_MODEL_REASONING/STANDARD/FAST or configure a provider credential.',
234
+ remediation: `Set CX_MODEL_${tier.toUpperCase()}=<provider/model>, or configure a provider credential such as ANTHROPIC_API_KEY / OPENROUTER_API_KEY, then rerun`,
185
235
  warnings,
186
236
  });
187
237
  }
@@ -1,6 +1,15 @@
1
1
  /**
2
2
  * lib/embedded-contract/workflow-defs.mjs — embedded workflow type definitions.
3
3
  *
4
+ * Generated/compat shim (LMCP-D2) — this module has no hand-authored catalog.
5
+ * DEFS is computed at import time exclusively from lib/workflows/loader.mjs
6
+ * (LMCP-D1), which reads builtin/pack/project *.manifest.json files. Editing a
7
+ * workflow means editing a manifest under lib/embedded-contract/workflows/ (or a
8
+ * pack/.cx manifest); this file cannot silently drift from them because it does
9
+ * not store data of its own. scripts/check-workflow-defs-drift.mjs enforces that
10
+ * invariant in CI — it fails if the source regains a hardcoded catalog entry or
11
+ * loses the loader import.
12
+ *
4
13
  * The single source of truth for the workflow types an embedding application can
5
14
  * invoke. Each definition names a default role chain (real registry role ids), a
6
15
  * model tier, a default approval mode, an optional output-schema artifact, and a
@@ -8,80 +17,40 @@
8
17
  * selected roles' declared skills (role-facts) so this file never names a skill
9
18
  * id that does not exist. Capability discovery reads these definitions so the
10
19
  * published workflow list cannot drift from what invocation actually supports.
20
+ *
21
+ * INTAKE_TO_WORKFLOW starts from a hand-authored base table (the mapping for
22
+ * the 11 builtin workflows) and is then extended by every loaded manifest's
23
+ * optional `intakeType` field (LMCP-D3) — a pack or project workflow
24
+ * contribution claims or remaps a classifier label by declaring `intakeType`
25
+ * in its manifest, with no edit to this file. Manifests are applied in
26
+ * `workflows` array order, which mirrors loader precedence (builtin, then
27
+ * pack, then project) for overridden ids and appends new project/pack ids
28
+ * last, so a project-contributed `intakeType` wins ties over the hardcoded
29
+ * base table.
11
30
  */
12
31
 
13
- const DEFS = {
14
- 'evidence-ingest': {
15
- tier: 'fast',
16
- defaultApprovalMode: 'proposal-only',
17
- chain: ['researcher', 'data-analyst'],
18
- outputSchema: null,
19
- description: 'Ingest and structure raw evidence (notes, documents, signals) into a normalized summary.',
20
- },
21
- 'proposal-review': {
22
- tier: 'standard',
23
- defaultApprovalMode: 'requires-human-approval',
24
- chain: ['reviewer', 'devil-advocate'],
25
- outputSchema: 'review-report',
26
- description: 'Review a proposal for correctness, risk, and hidden assumptions before acceptance.',
27
- },
28
- 'prd-draft': {
29
- tier: 'standard',
30
- defaultApprovalMode: 'proposal-only',
31
- chain: ['product-manager', 'architect'],
32
- outputSchema: 'decision',
33
- description: 'Draft a product requirements document from a problem statement and supporting evidence.',
34
- },
35
- 'architecture-review': {
36
- tier: 'reasoning',
37
- defaultApprovalMode: 'requires-human-approval',
38
- chain: ['architect', 'security', 'devil-advocate'],
39
- outputSchema: 'review-report',
40
- description: 'Review an architecture or design for trade-offs, failure modes, and security exposure.',
41
- },
42
- 'risk-review': {
43
- tier: 'reasoning',
44
- defaultApprovalMode: 'requires-human-approval',
45
- chain: ['devil-advocate', 'security', 'legal-compliance'],
46
- outputSchema: 'review-report',
47
- description: 'Stress-test a plan for risk: failure modes, security, and compliance exposure.',
48
- },
49
- 'research-synthesis': {
50
- tier: 'reasoning',
51
- defaultApprovalMode: 'proposal-only',
52
- chain: ['researcher', 'data-analyst', 'evaluator'],
53
- outputSchema: null,
54
- description: 'Synthesize multiple sources into a cited, evidence-graded research summary.',
55
- },
56
- 'transcript-process': {
57
- tier: 'fast',
58
- defaultApprovalMode: 'proposal-only',
59
- chain: ['researcher', 'data-analyst'],
60
- outputSchema: null,
61
- description: 'Process a meeting/call transcript into a summary, decisions, and action items.',
62
- },
63
- 'data-structure': {
64
- tier: 'standard',
65
- defaultApprovalMode: 'proposal-only',
66
- chain: ['data-analyst', 'data-engineer'],
67
- outputSchema: null,
68
- description: 'Parse, validate, and profile a raw dataset into a structured, described shape.',
69
- },
70
- 'memo-draft': {
71
- tier: 'fast',
72
- defaultApprovalMode: 'proposal-only',
73
- chain: ['docs-keeper', 'reviewer'],
74
- outputSchema: null,
75
- description: 'Draft a decision or status memo from a problem statement and context.',
76
- },
77
- 'structure-notes': {
78
- tier: 'fast',
79
- defaultApprovalMode: 'proposal-only',
80
- chain: ['orchestrator', 'researcher'],
32
+ import { loadAllWorkflows } from '../workflows/loader.mjs';
33
+
34
+ const { workflows } = loadAllWorkflows();
35
+
36
+ // Embed manifests are a workflow-manifest specialization (an embed capability,
37
+ // discovered by the embed-capability loader) — they carry an embed block, no
38
+ // executable role chain so they are excluded from the invokable workflow-type
39
+ // catalog rather than surfaced as a chain-less workflow.
40
+ const DEFS = {};
41
+ for (const wf of workflows) {
42
+ if (wf.type === 'embed') continue;
43
+ DEFS[wf.id] = {
44
+ tier: wf.tier || 'standard',
45
+ defaultApprovalMode: wf.defaultApprovalMode,
46
+ chain: wf.roleChain || [],
81
47
  outputSchema: null,
82
- description: 'Structure an unclassified brain-dump or rough notes into a normalized summary with extracted intents.',
83
- },
84
- };
48
+ description: wf.description || '',
49
+ };
50
+ if (wf.outputSchema?.artifact) {
51
+ DEFS[wf.id].outputSchema = wf.outputSchema.artifact;
52
+ }
53
+ }
85
54
 
86
55
  // Maps a classifier intakeType to the workflow type that would carry it out, so
87
56
  // the triage contract can suggest a directly-invokable workflow. Returns null
@@ -106,6 +75,12 @@ const INTAKE_TO_WORKFLOW = {
106
75
  unknown: 'structure-notes',
107
76
  };
108
77
 
78
+ for (const wf of workflows) {
79
+ if (typeof wf.intakeType === 'string' && wf.intakeType) {
80
+ INTAKE_TO_WORKFLOW[wf.intakeType] = wf.id;
81
+ }
82
+ }
83
+
109
84
  export const WORKFLOW_TYPES = Object.keys(DEFS);
110
85
 
111
86
  export function getWorkflowDef(type) {
@@ -117,9 +92,9 @@ export function getWorkflowDef(type) {
117
92
  * @returns {Array<object>}
118
93
  */
119
94
  export function listWorkflowDefs() {
120
- return WORKFLOW_TYPES.map((type) => ({ type, ...DEFS[type] }));
95
+ return Object.entries(DEFS).map(([type, def]) => ({ type, ...def }));
121
96
  }
122
97
 
123
98
  export function workflowTypeForIntake(intakeType) {
124
99
  return INTAKE_TO_WORKFLOW[intakeType] || null;
125
- }
100
+ }