@geraldmaron/construct 1.2.3 → 1.3.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 (505) hide show
  1. package/README.md +7 -10
  2. package/bin/construct +235 -209
  3. package/bin/construct-postinstall.mjs +0 -21
  4. package/commands/work/optimize-prompts.md +1 -1
  5. package/examples/distribution/sources/adr.md +2 -2
  6. package/examples/seed-observations/decisions.md +1 -1
  7. package/lib/artifact-loop-core.mjs +412 -0
  8. package/lib/artifact-manifest.mjs +6 -0
  9. package/lib/artifact-release-gate.mjs +115 -49
  10. package/lib/audit-rules.mjs +2 -4
  11. package/lib/audit-skills.mjs +32 -20
  12. package/lib/audit-specialists.mjs +44 -26
  13. package/lib/auto-docs.mjs +6 -5
  14. package/lib/brand-prose.mjs +3 -3
  15. package/lib/brand-tokens.mjs +2 -2
  16. package/lib/certification/artifact-fixtures.mjs +4 -1
  17. package/lib/certification/demo-parity.mjs +6 -32
  18. package/lib/certification/real-llm-scenarios.mjs +58 -13
  19. package/lib/certification/role-cards.mjs +7 -6
  20. package/lib/certification/role-overlays.mjs +4 -4
  21. package/lib/certification/runner.mjs +9 -2
  22. package/lib/certification/skill-inventory.mjs +34 -22
  23. package/lib/certification/skill-scenarios.mjs +21 -8
  24. package/lib/certification/specialist-contracts.mjs +4 -3
  25. package/lib/certification/specialist-scenarios.mjs +7 -6
  26. package/lib/certification/status.mjs +5 -4
  27. package/lib/cli-commands.mjs +55 -54
  28. package/lib/comment-lint.mjs +1 -5
  29. package/lib/completions.mjs +20 -2
  30. package/lib/config/legacy-config-migration.mjs +90 -24
  31. package/lib/config/schema.mjs +5 -5
  32. package/lib/config/source-targets.mjs +80 -0
  33. package/lib/contracts/validate.mjs +119 -51
  34. package/lib/decisions/golden.mjs +3 -2
  35. package/lib/decisions/registry.mjs +11 -6
  36. package/lib/demo-project.mjs +188 -0
  37. package/lib/demo-recording.mjs +9 -34
  38. package/lib/demo-script.mjs +2 -2
  39. package/lib/demo-surface.mjs +13 -131
  40. package/lib/demo-tour-renderer.mjs +92 -0
  41. package/lib/demo.mjs +69 -54
  42. package/lib/diagram-export.mjs +63 -14
  43. package/lib/doctor/cli.mjs +12 -2
  44. package/lib/doctor/source-checkout.mjs +3 -4
  45. package/lib/doctor/watchers/consistency.mjs +148 -43
  46. package/lib/doctor/watchers/credential-parity.mjs +97 -0
  47. package/lib/doctor/watchers/mcp-protocol.mjs +1 -1
  48. package/lib/doctor/watchers/service-health.mjs +4 -32
  49. package/lib/document-export.mjs +73 -9
  50. package/lib/document-extract.mjs +10 -198
  51. package/lib/embed/artifact.mjs +2 -3
  52. package/lib/embed/cli.mjs +1 -1
  53. package/lib/embed/config.mjs +1 -2
  54. package/lib/embed/customer-profiles.mjs +1 -1
  55. package/lib/embed/daemon.mjs +5 -6
  56. package/lib/embed/demand-fetch.mjs +114 -2
  57. package/lib/embed/docs-lifecycle.mjs +9 -5
  58. package/lib/embed/intake-metrics.mjs +2 -2
  59. package/lib/embed/notifications.mjs +2 -3
  60. package/lib/embed/recommendation-store.mjs +25 -22
  61. package/lib/embed/role-framing.mjs +4 -9
  62. package/lib/embedded-contract/capability.mjs +4 -2
  63. package/lib/embedded-contract/contract-version.mjs +1 -1
  64. package/lib/env-config.mjs +2 -2
  65. package/lib/flavors/loader.mjs +21 -19
  66. package/lib/graph/build-from-registry.mjs +31 -7
  67. package/lib/graph/staleness.mjs +1 -1
  68. package/lib/headhunt.mjs +82 -35
  69. package/lib/hooks/agent-tracker.mjs +2 -2
  70. package/lib/hooks/config-protection.mjs +1 -1
  71. package/lib/hooks/registry-sync.mjs +3 -3
  72. package/lib/host-capabilities.mjs +5 -5
  73. package/lib/improvement/controller.mjs +2 -2
  74. package/lib/init-unified.mjs +19 -21
  75. package/lib/intake/classify.mjs +26 -0
  76. package/lib/intake/daemon.mjs +2 -3
  77. package/lib/intake/prepare.mjs +10 -3
  78. package/lib/intake/session-prelude.mjs +1 -1
  79. package/lib/intake/tables/creative.mjs +9 -9
  80. package/lib/intake/tables/operations.mjs +4 -4
  81. package/lib/intake/tables/research.mjs +2 -2
  82. package/lib/integrations/intake-integrations.mjs +9 -10
  83. package/lib/knowledge/research-store.mjs +2 -2
  84. package/lib/mcp/server.mjs +104 -61
  85. package/lib/mcp/tool-budget.mjs +1 -46
  86. package/lib/mcp/tool-recovery.mjs +44 -0
  87. package/lib/mcp/tools/artifact-author.mjs +36 -0
  88. package/lib/mcp/tools/find-tool.mjs +86 -0
  89. package/lib/mcp/tools/orchestration-run.mjs +107 -69
  90. package/lib/mcp/tools/project.mjs +4 -3
  91. package/lib/mcp/tools/{profile.mjs → scope.mjs} +54 -52
  92. package/lib/mcp/tools/skills.mjs +39 -22
  93. package/lib/mcp/tools/telemetry.mjs +2 -1
  94. package/lib/mcp/tools/workflow.mjs +1 -1
  95. package/lib/mcp-platform-config.mjs +7 -5
  96. package/lib/migrations/index.mjs +4 -2
  97. package/lib/migrations/v2-unified-registry.mjs +35 -0
  98. package/lib/model-router.mjs +203 -36
  99. package/lib/models/catalog.mjs +25 -9
  100. package/lib/models/execution-capability-profile.mjs +3 -3
  101. package/lib/models/execution-policy.mjs +7 -6
  102. package/lib/models/provider-poll.mjs +18 -4
  103. package/lib/opencode-config.mjs +56 -1
  104. package/lib/opencode-runtime-plugin.mjs +13 -10
  105. package/lib/oracle/artifact-gate.mjs +14 -4
  106. package/lib/oracle/cli.mjs +2 -0
  107. package/lib/oracle/dispatch.mjs +18 -1
  108. package/lib/oracle/execute.mjs +39 -7
  109. package/lib/oracle/index.mjs +1 -1
  110. package/lib/oracle/org-graph.mjs +10 -5
  111. package/lib/oracle/policy.mjs +6 -0
  112. package/lib/oracle/read-model.mjs +103 -6
  113. package/lib/oracle/reconcile.mjs +31 -4
  114. package/lib/oracle/remediation-dispatch.mjs +53 -0
  115. package/lib/oracle/routing.mjs +5 -0
  116. package/lib/oracle/synthesize.mjs +80 -3
  117. package/lib/orchestration/routing-tables.mjs +44 -10
  118. package/lib/orchestration/runtime.mjs +2 -0
  119. package/lib/orchestration/worker.mjs +1 -1
  120. package/lib/orchestration-policy.mjs +351 -62
  121. package/lib/overrides/resolver.mjs +1 -12
  122. package/lib/parity.mjs +37 -11
  123. package/lib/policy/engine.mjs +80 -15
  124. package/lib/prompt-composer.js +51 -15
  125. package/lib/prompt-metadata.mjs +3 -2
  126. package/lib/providers/connection-probe.mjs +58 -0
  127. package/lib/providers/copilot-auth.mjs +1 -1
  128. package/lib/providers/credential-bootstrap.mjs +1 -1
  129. package/lib/providers/op-run.mjs +3 -4
  130. package/lib/providers/secret-resolver.mjs +31 -0
  131. package/lib/publish-tooling.mjs +3 -11
  132. package/lib/publish.mjs +12 -29
  133. package/lib/reconcile/mcp-entry-reconcile.mjs +14 -9
  134. package/lib/reflect.mjs +2 -2
  135. package/lib/registry/agent-manifest.mjs +190 -0
  136. package/lib/registry/assemble.mjs +133 -0
  137. package/lib/registry/catalog.mjs +171 -0
  138. package/lib/registry/cli.mjs +590 -6
  139. package/lib/registry/consolidation.mjs +5 -4
  140. package/lib/registry/docs-sync.mjs +67 -0
  141. package/lib/registry/loader.mjs +147 -0
  142. package/lib/registry/org-io.mjs +76 -0
  143. package/lib/registry/retired-paths.mjs +71 -0
  144. package/lib/registry/surface-map.mjs +5 -7
  145. package/lib/registry/validator.mjs +438 -0
  146. package/lib/research-execution-policy.mjs +173 -0
  147. package/lib/roles/catalog.mjs +4 -9
  148. package/lib/roles/fence.mjs +107 -1
  149. package/lib/roles/flavor-bindings.mjs +68 -0
  150. package/lib/roles/gateway.mjs +140 -29
  151. package/lib/roles/manifest.mjs +22 -13
  152. package/lib/roles/router.mjs +1 -1
  153. package/lib/scopes/enrich.mjs +67 -0
  154. package/lib/scopes/hooks.mjs +12 -0
  155. package/lib/{profiles → scopes}/lifecycle.mjs +70 -70
  156. package/lib/scopes/loader.mjs +104 -0
  157. package/lib/scopes/rebrand.mjs +32 -0
  158. package/lib/scopes/research-profile.mjs +16 -0
  159. package/lib/scopes/teams.mjs +98 -0
  160. package/lib/service-manager.mjs +1 -117
  161. package/lib/setup-prompts.mjs +1 -1
  162. package/lib/setup.mjs +6 -26
  163. package/lib/skills/composition-graph.mjs +98 -0
  164. package/lib/skills/router.mjs +80 -0
  165. package/lib/specialist-contracts.mjs +17 -18
  166. package/lib/specialists/postconditions.mjs +2 -2
  167. package/lib/specialists/prompt-schema.mjs +6 -5
  168. package/lib/specialists/roster.mjs +7 -12
  169. package/lib/specialists/schema.mjs +9 -6
  170. package/lib/status.mjs +25 -90
  171. package/lib/storage/file-lock.mjs +6 -3
  172. package/lib/telemetry/skill-calls.mjs +1 -1
  173. package/lib/templates/doc-presentation.mjs +63 -0
  174. package/lib/templates/visual-requirements.mjs +35 -2
  175. package/lib/term-format.mjs +107 -2
  176. package/lib/test-env-setup.mjs +21 -0
  177. package/lib/ui/components.mjs +42 -0
  178. package/lib/ui/glyphs.mjs +58 -0
  179. package/lib/ui/links.mjs +115 -0
  180. package/lib/ui/theme.mjs +108 -0
  181. package/lib/uninstall/uninstall.mjs +2 -1
  182. package/lib/validator.mjs +45 -8
  183. package/lib/validators/skill-effectiveness.mjs +174 -0
  184. package/lib/validators/skills.mjs +1 -1
  185. package/package.json +12 -8
  186. package/personas/construct.md +12 -3
  187. package/platforms/claude/CLAUDE.md +1 -1
  188. package/rules/common/beads-hygiene.md +52 -0
  189. package/rules/common/neurodivergent-output.md +4 -7
  190. package/rules/common/research.md +2 -0
  191. package/scripts/sync-specialists.mjs +269 -51
  192. package/skills/ai/prompt-optimizer.md +3 -3
  193. package/skills/brand/output-vibe.md +48 -0
  194. package/skills/docs/adr-workflow.md +3 -0
  195. package/skills/docs/backlog-proposal-workflow.md +3 -0
  196. package/skills/docs/codebase-research-workflow.md +5 -2
  197. package/skills/docs/customer-profile-workflow.md +3 -0
  198. package/skills/docs/document-ingest-workflow.md +3 -0
  199. package/skills/docs/evidence-ingest-workflow.md +4 -1
  200. package/skills/docs/init-project.md +1 -1
  201. package/skills/docs/prd-workflow.md +1 -1
  202. package/skills/docs/prfaq-workflow.md +3 -0
  203. package/skills/docs/product-intelligence-workflow.md +4 -1
  204. package/skills/docs/product-signal-workflow.md +3 -0
  205. package/skills/docs/research-workflow.md +13 -6
  206. package/skills/docs/runbook-workflow.md +3 -0
  207. package/skills/docs/strategy-workflow.md +3 -0
  208. package/skills/docs/user-research-workflow.md +6 -3
  209. package/skills/operating/orchestration-reference.md +1 -1
  210. package/skills/roles/{engineer.ai.md → ai-engineer.md} +2 -2
  211. package/skills/roles/architect.ai-systems.md +1 -1
  212. package/skills/roles/architect.data.md +1 -1
  213. package/skills/roles/architect.enterprise.md +1 -1
  214. package/skills/roles/architect.integration.md +1 -1
  215. package/skills/roles/architect.md +1 -1
  216. package/skills/roles/architect.platform.md +1 -1
  217. package/skills/roles/{product-manager.business-strategy.md → business-strategist.md} +3 -3
  218. package/skills/roles/data-analyst.experiment.md +1 -1
  219. package/skills/roles/data-analyst.md +1 -1
  220. package/skills/roles/data-analyst.product-intelligence.md +1 -1
  221. package/skills/roles/data-analyst.product.md +1 -1
  222. package/skills/roles/data-analyst.telemetry.md +1 -1
  223. package/skills/roles/{engineer.data.md → data-engineer.md} +2 -2
  224. package/skills/roles/data-engineer.pipeline.md +2 -2
  225. package/skills/roles/data-engineer.vector-retrieval.md +2 -2
  226. package/skills/roles/data-engineer.warehouse.md +2 -2
  227. package/skills/roles/debugger.md +1 -1
  228. package/skills/roles/designer.accessibility.md +1 -1
  229. package/skills/roles/designer.md +1 -1
  230. package/skills/roles/{reviewer.devil-advocate.md → devil-advocate.md} +2 -2
  231. package/skills/roles/{operator.docs.md → docs-keeper.md} +3 -3
  232. package/skills/roles/engineer.md +3 -7
  233. package/skills/roles/{reviewer.evaluator.md → evaluator.md} +2 -2
  234. package/skills/roles/{researcher.explorer.md → explorer.md} +2 -2
  235. package/skills/roles/{operator.md → operations.md} +2 -5
  236. package/skills/roles/orchestrator.md +1 -1
  237. package/skills/roles/{engineer.platform.md → platform-engineer.md} +2 -2
  238. package/skills/roles/product-manager.ai-product.md +1 -1
  239. package/skills/roles/product-manager.enterprise.md +1 -1
  240. package/skills/roles/product-manager.growth.md +1 -2
  241. package/skills/roles/product-manager.md +1 -2
  242. package/skills/roles/product-manager.platform.md +1 -1
  243. package/skills/roles/product-manager.product.md +1 -1
  244. package/skills/roles/qa.ai-eval.md +1 -1
  245. package/skills/roles/qa.api-contract.md +1 -1
  246. package/skills/roles/qa.data-pipeline.md +1 -1
  247. package/skills/roles/qa.md +1 -1
  248. package/skills/roles/qa.web-ui.md +1 -1
  249. package/skills/roles/{operator.release.md → release-manager.md} +3 -3
  250. package/skills/roles/researcher.md +1 -1
  251. package/skills/roles/reviewer.md +1 -1
  252. package/skills/roles/security.ai.md +1 -1
  253. package/skills/roles/security.appsec.md +1 -1
  254. package/skills/roles/security.cloud.md +1 -1
  255. package/skills/roles/security.legal-compliance.md +1 -1
  256. package/skills/roles/security.md +1 -1
  257. package/skills/roles/security.privacy.md +1 -1
  258. package/skills/roles/security.supply-chain.md +1 -1
  259. package/skills/roles/{operator.sre.md → sre.md} +3 -3
  260. package/skills/roles/{qa.test-automation.md → test-automation.md} +2 -2
  261. package/skills/roles/{reviewer.trace.md → trace-reviewer.md} +2 -2
  262. package/skills/roles/{researcher.ux.md → ux-researcher.md} +2 -2
  263. package/skills/routing.json +18 -0
  264. package/skills/routing.md +1 -1
  265. package/specialists/artifact-manifest.json +2 -1
  266. package/specialists/audit-enrichments.json +14 -14
  267. package/specialists/org/contracts/accessibility-to-qa.json +37 -0
  268. package/specialists/org/contracts/any-to-business-strategist.json +57 -0
  269. package/specialists/org/contracts/any-to-debugger.json +38 -0
  270. package/specialists/org/contracts/any-to-designer.json +33 -0
  271. package/specialists/org/contracts/any-to-docs-keeper.json +34 -0
  272. package/specialists/org/contracts/any-to-explorer.json +39 -0
  273. package/specialists/org/contracts/any-to-sre-incident.json +33 -0
  274. package/specialists/org/contracts/any-to-trace-reviewer.json +32 -0
  275. package/specialists/org/contracts/architect-to-ai-engineer.json +32 -0
  276. package/specialists/org/contracts/architect-to-data-engineer.json +52 -0
  277. package/specialists/org/contracts/architect-to-devil-advocate.json +38 -0
  278. package/specialists/org/contracts/architect-to-engineer.json +34 -0
  279. package/specialists/org/contracts/architect-to-evaluator.json +59 -0
  280. package/specialists/org/contracts/architect-to-legal-compliance.json +55 -0
  281. package/specialists/org/contracts/architect-to-operations.json +45 -0
  282. package/specialists/org/contracts/architect-to-platform-engineer.json +42 -0
  283. package/specialists/org/contracts/business-strategist-to-product-manager.json +39 -0
  284. package/specialists/org/contracts/construct-to-orchestrator.json +36 -0
  285. package/specialists/org/contracts/construct-to-rd-lead.json +53 -0
  286. package/specialists/org/contracts/data-analyst-to-product-manager.json +43 -0
  287. package/specialists/org/contracts/data-engineer-to-platform-engineer.json +36 -0
  288. package/specialists/org/contracts/designer-to-accessibility.json +36 -0
  289. package/specialists/org/contracts/engineer-to-qa.json +34 -0
  290. package/specialists/org/contracts/engineer-to-reviewer.json +52 -0
  291. package/specialists/org/contracts/explorer-to-engineer.json +38 -0
  292. package/specialists/org/contracts/legal-compliance-to-release-manager.json +43 -0
  293. package/specialists/org/contracts/platform-engineer-to-engineer.json +31 -0
  294. package/specialists/org/contracts/product-manager-to-architect.json +71 -0
  295. package/specialists/org/contracts/product-manager-to-data-analyst.json +49 -0
  296. package/specialists/org/contracts/product-manager-to-ux-researcher.json +51 -0
  297. package/specialists/org/contracts/qa-to-release-manager.json +42 -0
  298. package/specialists/org/contracts/qa-to-test-automation.json +42 -0
  299. package/specialists/org/contracts/rd-lead-to-architect.json +38 -0
  300. package/specialists/org/contracts/researcher-to-architect.json +40 -0
  301. package/specialists/org/contracts/researcher-to-product-manager.json +57 -0
  302. package/specialists/org/contracts/reviewer-to-security.json +41 -0
  303. package/specialists/org/contracts/sre-to-release-manager.json +36 -0
  304. package/specialists/org/contracts/test-automation-to-engineer.json +34 -0
  305. package/specialists/org/contracts/trace-reviewer-to-sre.json +41 -0
  306. package/specialists/org/contracts/user-to-construct.json +30 -0
  307. package/specialists/org/groups/engineering-group.json +43 -0
  308. package/specialists/org/groups/governance-group.json +38 -0
  309. package/specialists/org/groups/operations-group.json +41 -0
  310. package/specialists/org/groups/product-group.json +46 -0
  311. package/specialists/org/groups/quality-group.json +42 -0
  312. package/specialists/org/groups/strategy-group.json +41 -0
  313. package/specialists/org/policies/action-approval.json +13 -0
  314. package/specialists/org/policies/agents-routing.json +13 -0
  315. package/specialists/org/policies/architecture.json +20 -0
  316. package/specialists/org/policies/bash-safety.json +13 -0
  317. package/specialists/org/policies/beads-hygiene.json +13 -0
  318. package/specialists/org/policies/bootstrap-state.json +13 -0
  319. package/specialists/org/policies/code-review.json +13 -0
  320. package/specialists/org/policies/coding-style.json +13 -0
  321. package/specialists/org/policies/comments.json +13 -0
  322. package/specialists/org/policies/commit-approval.json +13 -0
  323. package/specialists/org/policies/contract-preconditions.json +13 -0
  324. package/specialists/org/policies/deployment.json +20 -0
  325. package/specialists/org/policies/description.json +14 -0
  326. package/specialists/org/policies/design-approval.json +19 -0
  327. package/specialists/org/policies/doc-ownership.json +13 -0
  328. package/specialists/org/policies/file-path-fence.json +13 -0
  329. package/specialists/org/policies/framing.json +13 -0
  330. package/specialists/org/policies/git-workflow.json +13 -0
  331. package/specialists/org/policies/incident-response.json +15 -0
  332. package/specialists/org/policies/intake-triage.json +15 -0
  333. package/specialists/org/policies/neurodivergent-output.json +13 -0
  334. package/specialists/org/policies/no-fabrication.json +13 -0
  335. package/specialists/org/policies/patterns.json +13 -0
  336. package/specialists/org/policies/quality-gate-approval.json +17 -0
  337. package/specialists/org/policies/release-gates.json +13 -0
  338. package/specialists/org/policies/research-evidence.json +13 -0
  339. package/specialists/org/policies/review-before-change.json +13 -0
  340. package/specialists/org/policies/rollback.json +15 -0
  341. package/specialists/org/policies/scope-change.json +20 -0
  342. package/specialists/org/policies/secret-scan.json +13 -0
  343. package/specialists/org/policies/security-approval.json +17 -0
  344. package/specialists/org/policies/security.json +13 -0
  345. package/specialists/org/policies/session-efficiency.json +13 -0
  346. package/specialists/org/policies/skill-routing.json +13 -0
  347. package/specialists/org/policies/strategic-prioritization.json +17 -0
  348. package/specialists/org/policies/testing.json +13 -0
  349. package/specialists/org/policies/tool-invisibility.json +14 -0
  350. package/specialists/org/scopes/creative.json +54 -0
  351. package/specialists/org/scopes/operations.json +51 -0
  352. package/specialists/org/scopes/research.json +60 -0
  353. package/specialists/org/scopes/rnd.json +81 -0
  354. package/specialists/org/specialists/cx-accessibility.json +69 -0
  355. package/specialists/org/specialists/cx-ai-engineer.json +75 -0
  356. package/specialists/org/specialists/cx-architect.json +89 -0
  357. package/specialists/org/specialists/cx-business-strategist.json +72 -0
  358. package/specialists/org/specialists/cx-data-analyst.json +68 -0
  359. package/specialists/org/specialists/cx-data-engineer.json +71 -0
  360. package/specialists/org/specialists/cx-debugger.json +75 -0
  361. package/specialists/org/specialists/cx-designer.json +85 -0
  362. package/specialists/org/specialists/cx-devil-advocate.json +71 -0
  363. package/specialists/org/specialists/cx-docs-keeper.json +82 -0
  364. package/specialists/org/specialists/cx-engineer.json +106 -0
  365. package/specialists/org/specialists/cx-evaluator.json +69 -0
  366. package/specialists/org/specialists/cx-explorer.json +69 -0
  367. package/specialists/org/specialists/cx-legal-compliance.json +74 -0
  368. package/specialists/org/specialists/cx-operations.json +72 -0
  369. package/specialists/org/specialists/cx-oracle.json +46 -0
  370. package/specialists/org/specialists/cx-orchestrator.json +81 -0
  371. package/specialists/org/specialists/cx-platform-engineer.json +80 -0
  372. package/specialists/org/specialists/cx-product-manager.json +102 -0
  373. package/specialists/org/specialists/cx-qa.json +79 -0
  374. package/specialists/org/specialists/cx-rd-lead.json +73 -0
  375. package/specialists/org/specialists/cx-release-manager.json +77 -0
  376. package/specialists/org/specialists/cx-researcher.json +82 -0
  377. package/specialists/org/specialists/cx-reviewer.json +71 -0
  378. package/specialists/org/specialists/cx-security.json +91 -0
  379. package/specialists/org/specialists/cx-sre.json +94 -0
  380. package/specialists/org/specialists/cx-test-automation.json +69 -0
  381. package/specialists/org/specialists/cx-trace-reviewer.json +69 -0
  382. package/specialists/org/specialists/cx-ux-researcher.json +68 -0
  383. package/specialists/org/teams/accessibility-team.json +39 -0
  384. package/specialists/org/teams/design-team.json +40 -0
  385. package/specialists/org/teams/engineering-team.json +50 -0
  386. package/specialists/org/teams/governance-team.json +41 -0
  387. package/specialists/org/teams/operations-team.json +46 -0
  388. package/specialists/org/teams/product-management-team.json +45 -0
  389. package/specialists/org/teams/quality-team.json +49 -0
  390. package/specialists/org/teams/research-team.json +39 -0
  391. package/specialists/org/teams/strategy-team.json +48 -0
  392. package/specialists/org/teams/ux-research-team.json +39 -0
  393. package/specialists/prompts/_shared/validation-contract.md +1 -1
  394. package/specialists/prompts/_team-template.md +10 -0
  395. package/specialists/prompts/cx-accessibility.md +1 -0
  396. package/specialists/prompts/cx-ai-engineer.md +1 -1
  397. package/specialists/prompts/cx-business-strategist.md +1 -1
  398. package/specialists/prompts/cx-data-engineer.md +1 -1
  399. package/specialists/prompts/cx-designer.md +1 -0
  400. package/specialists/prompts/cx-devil-advocate.md +1 -1
  401. package/specialists/prompts/cx-docs-keeper.md +1 -1
  402. package/specialists/prompts/cx-evaluator.md +1 -1
  403. package/specialists/prompts/cx-explorer.md +1 -1
  404. package/specialists/prompts/cx-operations.md +1 -1
  405. package/specialists/prompts/cx-oracle.md +7 -3
  406. package/specialists/prompts/cx-orchestrator.md +17 -1
  407. package/specialists/prompts/cx-platform-engineer.md +1 -1
  408. package/specialists/prompts/cx-product-manager.md +2 -0
  409. package/specialists/prompts/cx-release-manager.md +1 -1
  410. package/specialists/prompts/cx-researcher.md +7 -4
  411. package/specialists/prompts/cx-sre.md +1 -1
  412. package/specialists/prompts/cx-test-automation.md +2 -2
  413. package/specialists/prompts/cx-trace-reviewer.md +3 -3
  414. package/specialists/prompts/cx-ux-researcher.md +2 -1
  415. package/templates/demos/scripts/architecture-review-adr.json +30 -0
  416. package/templates/demos/scripts/capability-contract.json +25 -0
  417. package/templates/demos/scripts/intake-triage.json +25 -0
  418. package/templates/demos/scripts/profile-doctor-health.json +25 -0
  419. package/templates/demos/tapes/agentic-platforms-prd.tape +2 -2
  420. package/templates/demos/tapes/architecture-review-adr.tape +44 -0
  421. package/templates/demos/tapes/capability-contract.tape +39 -0
  422. package/templates/demos/tapes/intake-triage.tape +39 -0
  423. package/templates/demos/tapes/profile-doctor-health.tape +39 -0
  424. package/templates/distribution/construct-brand.typ +23 -18
  425. package/templates/distribution/construct-decision.typ +1 -1
  426. package/templates/distribution/construct-pdf.typ +1 -1
  427. package/templates/distribution/construct-prd.typ +1 -1
  428. package/templates/distribution/construct-research.typ +1 -1
  429. package/templates/distribution/mermaid-puppeteer.json +8 -0
  430. package/templates/docs/persona-artifact.md +1 -1
  431. package/templates/docs/prd.md +6 -0
  432. package/apps/chat/engine/ai-sdk-agent.mjs +0 -183
  433. package/apps/chat/engine/loop-driver.mjs +0 -211
  434. package/apps/chat/engine/models.mjs +0 -122
  435. package/apps/chat/engine/provider-adapters.mjs +0 -171
  436. package/apps/chat/engine/tools/permission.mjs +0 -54
  437. package/apps/chat/engine/tools/primitives.mjs +0 -180
  438. package/apps/chat/engine/tools/registry.mjs +0 -122
  439. package/apps/chat/engine/turn-controls.mjs +0 -70
  440. package/lib/boundary.mjs +0 -127
  441. package/lib/certification/dashboard-api.mjs +0 -71
  442. package/lib/chat/cli.mjs +0 -333
  443. package/lib/chat/command-suggest.mjs +0 -161
  444. package/lib/chat/commands.mjs +0 -215
  445. package/lib/chat/config.mjs +0 -142
  446. package/lib/chat/context-compactor.mjs +0 -250
  447. package/lib/chat/context-continuation.mjs +0 -253
  448. package/lib/chat/continuation-source.mjs +0 -58
  449. package/lib/chat/demo-guide.mjs +0 -61
  450. package/lib/chat/design-tokens.mjs +0 -91
  451. package/lib/chat/desktop-binary.mjs +0 -81
  452. package/lib/chat/desktop-build.mjs +0 -130
  453. package/lib/chat/desktop-launcher.mjs +0 -133
  454. package/lib/chat/evidence.mjs +0 -145
  455. package/lib/chat/export.mjs +0 -74
  456. package/lib/chat/harness/driver.mjs +0 -91
  457. package/lib/chat/list-picker.mjs +0 -112
  458. package/lib/chat/model-picker.mjs +0 -356
  459. package/lib/chat/openrouter-fallback.mjs +0 -151
  460. package/lib/chat/permission-prompt.mjs +0 -33
  461. package/lib/chat/picker-catalog.mjs +0 -45
  462. package/lib/chat/policy-telemetry.mjs +0 -34
  463. package/lib/chat/present.mjs +0 -246
  464. package/lib/chat/session-context.mjs +0 -39
  465. package/lib/chat/session-persist.mjs +0 -73
  466. package/lib/chat/session-restore.mjs +0 -71
  467. package/lib/chat/session-settings.mjs +0 -53
  468. package/lib/chat/system-prompt.mjs +0 -52
  469. package/lib/chat/transparency.mjs +0 -93
  470. package/lib/chat/tui/color-scheme.mjs +0 -42
  471. package/lib/chat/tui/markdown.mjs +0 -123
  472. package/lib/chat/tui/presentation.mjs +0 -100
  473. package/lib/chat/tui/render.mjs +0 -500
  474. package/lib/chat/tui/turn-block.mjs +0 -284
  475. package/lib/chat/tui/turn-present.mjs +0 -18
  476. package/lib/chat/tui/turn-state.mjs +0 -88
  477. package/lib/chat/tui/usage.mjs +0 -122
  478. package/lib/chat/web-commands.mjs +0 -146
  479. package/lib/chat/web-launcher.mjs +0 -63
  480. package/lib/chat/web-picker-keys.mjs +0 -46
  481. package/lib/chat/web-session.mjs +0 -159
  482. package/lib/config/alias.mjs +0 -57
  483. package/lib/dashboard-demo.mjs +0 -71
  484. package/lib/dashboard-static.mjs +0 -175
  485. package/lib/install/desktop-binary-download.mjs +0 -88
  486. package/lib/profiles/loader.mjs +0 -123
  487. package/lib/profiles/rebrand.mjs +0 -46
  488. package/lib/server/auth.mjs +0 -169
  489. package/lib/server/chat-loop.mjs +0 -622
  490. package/lib/server/chat.mjs +0 -336
  491. package/lib/server/cors.mjs +0 -77
  492. package/lib/server/csrf.mjs +0 -103
  493. package/lib/server/demo-preview.mjs +0 -63
  494. package/lib/server/index.mjs +0 -2641
  495. package/lib/server/insights.mjs +0 -780
  496. package/lib/server/langfuse-login.mjs +0 -58
  497. package/lib/server/rate-limit.mjs +0 -93
  498. package/lib/server/telemetry-login.mjs +0 -100
  499. package/lib/server/webhook.mjs +0 -512
  500. package/specialists/contracts.json +0 -1032
  501. package/specialists/contracts.schema.json +0 -83
  502. package/specialists/policy-inventory.json +0 -188
  503. package/specialists/registry.json +0 -1412
  504. package/specialists/role-manifests.json +0 -217
  505. package/specialists/teams.json +0 -94
@@ -153,7 +153,7 @@ export function detectActiveSessions() {
153
153
  // dispatch or config-driven agents): Claude Code, OpenCode.
154
154
  // mcp-orchestrated — no native subagent primitive, but the host calls the
155
155
  // `orchestration_run` MCP tool to reach the same orchestrated
156
- // outcome via the daemon: Codex, VS Code, Cursor, Copilot.
156
+ // outcome in-process: Codex, VS Code, Cursor, Copilot.
157
157
  // prompt-only — neither native dispatch nor MCP; instruction files only.
158
158
  // No supported 2026 host is prompt-only.
159
159
 
@@ -211,7 +211,7 @@ export function detectHostCapabilities() {
211
211
  sharedTaskRuntime: "tracker-plus-plan",
212
212
  lifecycleHooks: [],
213
213
  notes: [
214
- "Run a full multi-specialist chain via the `orchestration_run` MCP tool (start `construct dashboard`).",
214
+ "Run a full multi-specialist chain via the `orchestration_run` MCP tool (in-process; no daemon needed).",
215
215
  "Use Construct profiles, MCP project/memory tools, and the active session for single-pass work.",
216
216
  ],
217
217
  },
@@ -225,7 +225,7 @@ export function detectHostCapabilities() {
225
225
  sharedTaskRuntime: "editor-session",
226
226
  lifecycleHooks: [],
227
227
  notes: [
228
- "Run a full multi-specialist chain via the `orchestration_run` MCP tool in Copilot agent mode (start `construct dashboard`).",
228
+ "Run a full multi-specialist chain via the `orchestration_run` MCP tool in Copilot agent mode (in-process; no daemon needed).",
229
229
  "Construct's MCP servers load from `.vscode/mcp.json` (project) and the user-profile `mcp.json` (global, only when it already exists).",
230
230
  ],
231
231
  },
@@ -239,7 +239,7 @@ export function detectHostCapabilities() {
239
239
  sharedTaskRuntime: "editor-session",
240
240
  lifecycleHooks: [],
241
241
  notes: [
242
- "Run a full multi-specialist chain via the `orchestration_run` MCP tool (start `construct dashboard`).",
242
+ "Run a full multi-specialist chain via the `orchestration_run` MCP tool (in-process; no daemon needed).",
243
243
  "Construct manages Cursor MCP registrations in `.cursor/mcp.json` (project) and `~/.cursor/mcp.json` (global, when it already exists).",
244
244
  ],
245
245
  },
@@ -253,7 +253,7 @@ export function detectHostCapabilities() {
253
253
  sharedTaskRuntime: "editor-session",
254
254
  lifecycleHooks: [],
255
255
  notes: [
256
- "Copilot agent mode runs Construct's MCP tools — use `orchestration_run` for a real multi-specialist chain (start `construct dashboard`).",
256
+ "Copilot agent mode runs Construct's MCP tools — use `orchestration_run` for a real multi-specialist chain (in-process; no daemon needed).",
257
257
  "Construct also writes reusable prompt profiles under `.github/prompts/` for single-pass role work.",
258
258
  ],
259
259
  },
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * The controller is the mutation boundary for the governed loop. It admits only
6
6
  * versioned artifacts — proposal objects, dataset items, and evaluation reports,
7
- * never raw chat history — and refuses any candidate that lacks provenance,
7
+ * never raw unversioned session history — and refuses any candidate that lacks provenance,
8
8
  * lacks held-out evaluation evidence, failed a deterministic gate, names an unknown
9
9
  * approver, or has an unresolved dependency. Promotability is re-derived from the
10
10
  * report's own gate results rather than a precomputed flag, so a tampered decision
@@ -22,7 +22,7 @@ function isVersioned(artifact) {
22
22
 
23
23
  /**
24
24
  * Admit the input artifacts. Only versioned proposal/dataset/evaluation objects are
25
- * accepted; an unversioned blob (such as raw chat history) is refused
25
+ * accepted; an unversioned blob (such as raw session history) is refused
26
26
  * (construct-6zga.1.5 AC1).
27
27
  */
28
28
  export function admitArtifacts({ proposal = null, dataset = null, evaluationReport = null } = {}) {
@@ -69,11 +69,11 @@ const commitBootstrap = args.includes("--commit-bootstrap");
69
69
  const withHostFlags = new Set(HOST_KEYS.filter((k) => args.includes(`--with-${k}`)));
70
70
  const allHosts = args.includes("--all-hosts");
71
71
 
72
- // Active profile selector. `--profile=<id>` writes the field into the
73
- // project's construct.config.json so resolveActiveProfile picks it up
72
+ // Active scope selector. `--scope=<id>` writes the field into the
73
+ // project's construct.config.json so resolveActiveScope picks it up
74
74
  // on first run. Unknown ids are rejected with the available catalog.
75
- const profileArg = args.find((arg) => arg.startsWith("--profile="));
76
- const profileId = profileArg ? profileArg.split("=")[1] : null;
75
+ const scopeArg = args.find((arg) => arg.startsWith("--scope="));
76
+ const scopeId = scopeArg ? scopeArg.split("=")[1] : null;
77
77
 
78
78
  const created = [];
79
79
  const skipped = [];
@@ -745,10 +745,10 @@ async function main() {
745
745
  const { findProjectConfigPath, loadProjectConfig, writeProjectConfig, PROJECT_CONFIG_FILENAME } = await import('./config/project-config.mjs');
746
746
  const { DEFAULT_PROJECT_CONFIG } = await import('./config/schema.mjs');
747
747
 
748
- if (profileId) {
749
- const { loadProfile, listProfiles } = await import('./profiles/loader.mjs');
750
- if (!loadProfile(profileId)) {
751
- console.error(`Unknown profile: ${profileId}. Available: ${listProfiles().join(', ')}`);
748
+ if (scopeId) {
749
+ const { loadScope, listScopes } = await import('./scopes/loader.mjs');
750
+ if (!loadScope(scopeId)) {
751
+ console.error(`Unknown scope: ${scopeId}. Available: ${listScopes().join(', ')}`);
752
752
  process.exit(1);
753
753
  }
754
754
  }
@@ -763,29 +763,29 @@ async function main() {
763
763
  const cfg = {
764
764
  $schema: "./node_modules/@geraldmaron/construct/schemas/project-config.schema.json",
765
765
  ...DEFAULT_PROJECT_CONFIG,
766
- profile: profileId || 'rnd',
766
+ scope: scopeId || 'rnd',
767
767
  };
768
768
  // Explicitly write the full default config object so all options are
769
769
  // visible and discoverable to the user in the file. The $schema property
770
770
  // provides inline documentation and validation in supported editors.
771
771
  writeProjectConfig(cfgPath, cfg, { validate: true, silent: true });
772
772
  created.push(PROJECT_CONFIG_FILENAME);
773
- if (!quiet && profileId) console.log(`Profile set to ${profileId}.`);
774
- } else if (profileId) {
773
+ if (!quiet && scopeId) console.log(`Scope set to ${scopeId}.`);
774
+ } else if (scopeId) {
775
775
  const loaded = loadProjectConfig(target);
776
776
  const cfg = loaded?.raw ? { ...loaded.raw } : { version: 1 };
777
- cfg.profile = profileId;
777
+ cfg.scope = scopeId;
778
778
  writeProjectConfig(cfgPath, cfg, { validate: true, silent: true });
779
- if (!quiet) console.log(`Profile set to ${profileId}.`);
779
+ if (!quiet) console.log(`Scope set to ${scopeId}.`);
780
780
  }
781
781
  }
782
782
 
783
- // Resolve active profile to drive capability-gated scaffolding (intake
784
- // archetype, attribution stamping). Falls back to rnd when no profile is
785
- // configured — matches resolveActiveProfile semantics elsewhere.
783
+ // Resolve active scope to drive capability-gated scaffolding (intake
784
+ // archetype, attribution stamping). Falls back to rnd when no scope is
785
+ // configured — matches resolveActiveScope semantics elsewhere.
786
786
 
787
- const { resolveActiveProfile } = await import('./profiles/loader.mjs');
788
- const activeProfile = resolveActiveProfile(target, profileId) ?? null;
787
+ const { resolveActiveScope } = await import('./scopes/loader.mjs');
788
+ const activeProfile = resolveActiveScope(target, scopeId) ?? null;
789
789
  const intakeCap = activeProfile?.capabilities?.intake ?? null;
790
790
  const { gatherAttribution } = await import('./intake/attribution.mjs');
791
791
  const attribution = intakeCap?.attribution ? gatherAttribution() : null;
@@ -1228,12 +1228,10 @@ async function main() {
1228
1228
 
1229
1229
  if (!quiet) {
1230
1230
  console.log('\nServices:');
1231
- let dashboardUrl = null;
1232
1231
  for (const svc of results) {
1233
1232
  if (svc.status === 'started' || svc.status === 'reused') {
1234
1233
  const status = svc.status === 'reused' ? ' (running)' : '';
1235
1234
  console.log(` ${svc.name}${status}${svc.url ? ` ${svc.url}` : ''}`);
1236
- if (svc.name === 'Dashboard' && svc.url) dashboardUrl = svc.url;
1237
1235
  } else if (svc.status === 'failed') {
1238
1236
  console.log(` ${svc.name} — failed${svc.note ? ` (${svc.note})` : ''}`);
1239
1237
  }
@@ -1241,7 +1239,7 @@ async function main() {
1241
1239
 
1242
1240
  const telemetrySvc = results.find(r => r.name === 'Telemetry' && r.url?.includes('localhost'));
1243
1241
  if (telemetrySvc) console.log(`\nTelemetry: ${telemetrySvc.url}`);
1244
- if (dashboardUrl) console.log(`\nDashboard: ${dashboardUrl} · stop services with \`construct stop\``);
1242
+ console.log('\nStop services with `construct stop`');
1245
1243
  }
1246
1244
  } catch (error) {
1247
1245
  console.error(`Services could not be started: ${error.message}`);
@@ -34,6 +34,11 @@
34
34
  */
35
35
 
36
36
  import path from 'node:path';
37
+ import { createRequire } from 'node:module';
38
+ import { fileURLToPath } from 'node:url';
39
+
40
+ const require = createRequire(import.meta.url);
41
+ const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
37
42
 
38
43
  // Backward-compatible exports. RND defaults preserve the symbol surface
39
44
  // referenced by intake-config, prepare, and existing tests.
@@ -72,6 +77,22 @@ const TABLES = {
72
77
  research: researchTable,
73
78
  };
74
79
 
80
+ const dynamicTableCache = new Map();
81
+
82
+ function loadClassificationTable(tableRef) {
83
+ if (!tableRef || typeof tableRef !== 'string') return null;
84
+ if (dynamicTableCache.has(tableRef)) return dynamicTableCache.get(tableRef);
85
+ const abs = path.isAbsolute(tableRef) ? tableRef : path.join(REPO_ROOT, tableRef);
86
+ try {
87
+ const mod = require(abs);
88
+ const table = mod.default ?? mod;
89
+ dynamicTableCache.set(tableRef, table);
90
+ return table;
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+
75
96
  // Filename patterns are explicit author-intent signals. The boost remains
76
97
  // at +0.4 so a clear keyword majority can still override (a postmortem
77
98
  // genuinely about a CVE escalation routes to security, not incident).
@@ -167,6 +188,11 @@ function matcherFor(entry) {
167
188
  function resolveTable(profile) {
168
189
  if (!profile) return rndTable;
169
190
  const id = typeof profile === 'string' ? profile : profile.id;
191
+ const tableRef = typeof profile === 'object' ? profile?.intake?.classificationTable : null;
192
+ if (typeof tableRef === 'string') {
193
+ const fromPath = loadClassificationTable(tableRef);
194
+ if (fromPath) return fromPath;
195
+ }
170
196
  return TABLES[id] || rndTable;
171
197
  }
172
198
 
@@ -19,14 +19,13 @@ import { join, basename } from 'node:path';
19
19
 
20
20
  import { createDaemon, classifyPacket } from '../daemons/contract.mjs';
21
21
  import { memoryCapMbFor } from '../resources/process-budget.mjs';
22
- import { stateDir } from '../config/xdg.mjs';
23
22
 
24
23
  const KILLSWITCH_ENV = 'CONSTRUCT_INTAKE_DAEMON';
25
24
 
26
25
  function inboxDir(cwd) { return join(cwd, 'inbox'); }
27
26
  function pendingDir(cwd) { return join(cwd, '.cx', 'intake', 'pending'); }
28
27
  function deadLetterDir(cwd) { return join(cwd, '.cx', 'intake', 'dead-letter'); }
29
- function heartbeatPath() { return join(stateDir(), 'intake-daemon.heartbeat'); }
28
+ function heartbeatPath(cwd) { return join(cwd, '.cx', 'runtime', 'intake-daemon.heartbeat'); }
30
29
 
31
30
  function ensureDir(dir) {
32
31
  try { mkdirSync(dir, { recursive: true }); } catch { /* ignore */ }
@@ -128,7 +127,7 @@ export function buildIntakeDaemon({ cwd = process.cwd(), intervalMs = 60_000, cl
128
127
  name: 'intake',
129
128
  intervalMs,
130
129
  killswitchEnv: KILLSWITCH_ENV,
131
- heartbeatPath: heartbeatPath(),
130
+ heartbeatPath: heartbeatPath(cwd),
132
131
  maxRuntimeMs: 24 * 60 * 60 * 1000,
133
132
  maxIdleTicks: 6,
134
133
  memoryCapMb: memoryCapMbFor('intake', cwd),
@@ -34,7 +34,8 @@ import { suggestDocsLaneForFile } from '../docs-routing.mjs';
34
34
  import { createIntakeQueue } from './queue.mjs';
35
35
  import { classifyRdIntake, suggestTags } from './classify.mjs';
36
36
  import { detectCustomerMentions, linkSignalToCustomer, updateCustomerProfile } from '../embed/customer-profiles.mjs';
37
- import { resolveActiveProfile } from '../profiles/loader.mjs';
37
+ import { resolveActiveScope } from '../scopes/loader.mjs';
38
+ import { resolveResearchProfile } from '../scopes/research-profile.mjs';
38
39
  import { emitBestEffort as emitRoleEvent } from '../roles/event-bus.mjs';
39
40
  import { gatherAttribution, stampAttribution } from './attribution.mjs';
40
41
  import { MANIFEST_REL_PATH } from './manifest.mjs';
@@ -91,13 +92,19 @@ export async function prepareIntakeForIngestedFile({
91
92
  // Resolve the active profile so non-RND projects route to their own table.
92
93
  // Falls back to rnd for any project without explicit configuration, which
93
94
  // preserves prior behavior for every existing user.
94
- const activeProfile = resolveActiveProfile(rootDir);
95
- const triage = classifyFn({
95
+ const activeProfile = resolveActiveScope(rootDir);
96
+ const classified = classifyFn({
96
97
  sourcePath: ingestedFile.sourcePath,
97
98
  extractedText: extracted,
98
99
  related,
99
100
  profile: activeProfile?.id,
100
101
  });
102
+ const researchProfile = resolveResearchProfile({
103
+ intakeType: classified?.intakeType,
104
+ artifactType: lane,
105
+ scope: activeProfile,
106
+ });
107
+ const triage = researchProfile ? { ...classified, researchProfile } : classified;
101
108
 
102
109
  // Detect customer mentions and update profiles
103
110
  const customerMentions = detectCustomerMentions(extracted.slice(0, 2000));
@@ -13,7 +13,7 @@
13
13
  import { createIntakeQueue } from './queue.mjs';
14
14
  import { formatTriageLine } from './classify.mjs';
15
15
  import { isBrokered } from '../mcp/broker.mjs';
16
- import { getRebrand } from '../profiles/rebrand.mjs';
16
+ import { getRebrand } from '../scopes/rebrand.mjs';
17
17
  import { homedir as osHomedir } from 'node:os';
18
18
  import { readLastTick } from '../oracle/index.mjs';
19
19
  import { listPending } from '../oracle/actions.mjs';
@@ -11,8 +11,8 @@ export const STAGES = ['brief', 'research', 'draft', 'review', 'publish', 'measu
11
11
  export const UNKNOWN_TRIAGE = {
12
12
  intakeType: 'unknown',
13
13
  rdStage: 'unknown',
14
- primaryOwner: 'operator',
15
- recommendedChain: ['operator'],
14
+ primaryOwner: 'operations',
15
+ recommendedChain: ['operations'],
16
16
  recommendedAction: 'summarize',
17
17
  risk: 'low',
18
18
  requiresApproval: false,
@@ -33,8 +33,8 @@ export const CLASSIFICATION_TABLE = [
33
33
  intakeType: 'brief',
34
34
  keywords: ['brief', 'campaign', 'launch plan', 'go-to-market', 'gtm', 'positioning', 'narrative', 'audience'],
35
35
  rdStage: 'brief',
36
- primaryOwner: 'product-lead',
37
- recommendedChain: ['product-lead', 'researcher', 'content-writer'],
36
+ primaryOwner: 'product-manager',
37
+ recommendedChain: ['product-manager', 'researcher', 'docs-keeper'],
38
38
  recommendedAction: 'draft-prd',
39
39
  risk: 'medium',
40
40
  requiresApproval: false,
@@ -43,8 +43,8 @@ export const CLASSIFICATION_TABLE = [
43
43
  intakeType: 'content-request',
44
44
  keywords: ['blog', 'article', 'landing page', 'social post', 'newsletter', 'email copy', 'video script', 'headline', 'post', 'content'],
45
45
  rdStage: 'draft',
46
- primaryOwner: 'content-writer',
47
- recommendedChain: ['content-writer', 'reviewer'],
46
+ primaryOwner: 'docs-keeper',
47
+ recommendedChain: ['docs-keeper', 'reviewer'],
48
48
  recommendedAction: 'draft-rfc',
49
49
  risk: 'low',
50
50
  requiresApproval: false,
@@ -74,7 +74,7 @@ export const CLASSIFICATION_TABLE = [
74
74
  keywords: ['report', 'dashboard', 'attribution', 'ctr', 'cpa', 'roas', 'conversion', 'funnel', 'engagement'],
75
75
  rdStage: 'measure',
76
76
  primaryOwner: 'data-analyst',
77
- recommendedChain: ['data-analyst', 'product-lead'],
77
+ recommendedChain: ['data-analyst', 'product-manager'],
78
78
  recommendedAction: 'evaluate',
79
79
  risk: 'low',
80
80
  requiresApproval: false,
@@ -83,8 +83,8 @@ export const CLASSIFICATION_TABLE = [
83
83
  intakeType: 'ops',
84
84
  keywords: ['process', 'workflow', 'template', 'sla', 'calendar', 'planning', 'editorial calendar'],
85
85
  rdStage: 'review',
86
- primaryOwner: 'operator',
87
- recommendedChain: ['operator', 'product-lead'],
86
+ primaryOwner: 'operations',
87
+ recommendedChain: ['operations', 'product-manager'],
88
88
  recommendedAction: 'create-runbook',
89
89
  risk: 'low',
90
90
  requiresApproval: false,
@@ -12,8 +12,8 @@ export const STAGES = ['request', 'triage', 'resolve', 'document', 'improve'];
12
12
  export const UNKNOWN_TRIAGE = {
13
13
  intakeType: 'unknown',
14
14
  rdStage: 'unknown',
15
- primaryOwner: 'operator',
16
- recommendedChain: ['operator'],
15
+ primaryOwner: 'operations',
16
+ recommendedChain: ['operations'],
17
17
  recommendedAction: 'summarize',
18
18
  risk: 'low',
19
19
  requiresApproval: false,
@@ -74,8 +74,8 @@ export const CLASSIFICATION_TABLE = [
74
74
  intakeType: 'request',
75
75
  keywords: ['request', 'access', 'feature request', 'integration', 'new tool', 'change request', 'how do i', 'can someone'],
76
76
  rdStage: 'triage',
77
- primaryOwner: 'operator',
78
- recommendedChain: ['operator', 'engineer'],
77
+ primaryOwner: 'operations',
78
+ recommendedChain: ['operations', 'engineer'],
79
79
  recommendedAction: 'clarify',
80
80
  risk: 'low',
81
81
  requiresApproval: false,
@@ -74,8 +74,8 @@ export const CLASSIFICATION_TABLE = [
74
74
  intakeType: 'ops',
75
75
  keywords: ['process', 'methodology', 'template', 'protocol', 'consent form', 'data handling'],
76
76
  rdStage: 'gather',
77
- primaryOwner: 'operator',
78
- recommendedChain: ['operator', 'researcher'],
77
+ primaryOwner: 'operations',
78
+ recommendedChain: ['operations', 'researcher'],
79
79
  recommendedAction: 'create-runbook',
80
80
  risk: 'low',
81
81
  requiresApproval: false,
@@ -19,6 +19,7 @@ import { join } from 'node:path';
19
19
  import { homedir } from 'node:os';
20
20
  import { spawnSync } from 'node:child_process';
21
21
  import { configDir } from '../config/xdg.mjs';
22
+ import { resolveOpRef } from '../providers/secret-resolver.mjs';
22
23
 
23
24
  // ── Multi-method auth helpers ────────────────────────────────────────────
24
25
 
@@ -628,8 +629,7 @@ function resolveCredentialSync(varName, homeDir) {
628
629
  const opMatch = content.match(opRe);
629
630
  if (opMatch) {
630
631
  try {
631
- const result = spawnSync('op', ['read', opMatch[1]], { encoding: 'utf8', timeout: 5000 });
632
- if (result.status === 0) return result.stdout.trim();
632
+ return resolveOpRef(opMatch[1]);
633
633
  } catch { /* op read failed */ }
634
634
  }
635
635
  }
@@ -730,16 +730,15 @@ function resolveCredential(varName, homeDir) {
730
730
  const opRe = new RegExp(`export\\s+${varName}=["']?\\$\\(op read '([^']+)'\\)["']?`, 'm');
731
731
  const opMatch = content.match(opRe);
732
732
  if (opMatch) {
733
+ // op read failures often mean the rc-file field name doesn't match the
734
+ // actual 1Password item field; surface them under the debug flag.
733
735
  try {
734
- const result = spawnSync('op', ['read', opMatch[1]], { encoding: 'utf8', timeout: 5000 });
735
- if (result.status === 0) return result.stdout.trim();
736
- // Log op read failures — often the field name in the rc file
737
- // doesn't match the actual 1Password item field name.
738
- const errMsg = (result.stderr || '').trim().slice(0, 200);
739
- if (errMsg && process.env.CONSTRUCT_DEBUG_CREDENTIALS === '1') {
740
- process.stderr.write(`[credentials] op read failed for ${varName}: ${errMsg}\n`);
736
+ return resolveOpRef(opMatch[1]);
737
+ } catch (err) {
738
+ if (process.env.CONSTRUCT_DEBUG_CREDENTIALS === '1') {
739
+ process.stderr.write(`[credentials] op read failed for ${varName}: ${String(err.message).slice(0, 200)}\n`);
741
740
  }
742
- } catch { /* op read failed */ }
741
+ }
743
742
  }
744
743
 
745
744
  // If the value uses command substitution ($(...)), try evaluating via
@@ -18,7 +18,7 @@
18
18
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
19
19
  import { dirname, join } from 'node:path';
20
20
  import { syncFileStateToSql } from '../storage/sync.mjs';
21
- import { resolveActiveProfile } from '../profiles/loader.mjs';
21
+ import { resolveActiveScope } from '../scopes/loader.mjs';
22
22
  import { ensureCxDir } from '../project-init-shared.mjs';
23
23
 
24
24
  const ROOT = '.cx/knowledge/external/research';
@@ -64,7 +64,7 @@ export async function addResearchFinding({
64
64
  throw new Error('addResearchFinding: confidence=confirmed requires at least one source');
65
65
  }
66
66
 
67
- const profile = resolveActiveProfile(cwd);
67
+ const profile = resolveActiveScope(cwd);
68
68
  const now = new Date();
69
69
  const expiresAt = new Date(now.getTime() + ttlDays * 24 * 60 * 60 * 1000).toISOString();
70
70