@geraldmaron/construct 1.0.5 → 1.0.7

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 (268) hide show
  1. package/README.md +24 -18
  2. package/agents/contracts.json +617 -2
  3. package/agents/contracts.schema.json +83 -0
  4. package/agents/prompts/cx-accessibility.md +5 -3
  5. package/agents/prompts/cx-ai-engineer.md +9 -7
  6. package/agents/prompts/cx-architect.md +8 -6
  7. package/agents/prompts/cx-business-strategist.md +8 -6
  8. package/agents/prompts/cx-data-analyst.md +9 -7
  9. package/agents/prompts/cx-data-engineer.md +5 -3
  10. package/agents/prompts/cx-debugger.md +8 -6
  11. package/agents/prompts/cx-designer.md +7 -5
  12. package/agents/prompts/cx-devil-advocate.md +6 -4
  13. package/agents/prompts/cx-docs-keeper.md +7 -5
  14. package/agents/prompts/cx-engineer.md +7 -5
  15. package/agents/prompts/cx-evaluator.md +4 -2
  16. package/agents/prompts/cx-explorer.md +10 -8
  17. package/agents/prompts/cx-legal-compliance.md +4 -2
  18. package/agents/prompts/cx-operations.md +7 -5
  19. package/agents/prompts/cx-orchestrator.md +12 -10
  20. package/agents/prompts/cx-platform-engineer.md +7 -5
  21. package/agents/prompts/cx-product-manager.md +6 -4
  22. package/agents/prompts/cx-qa.md +10 -8
  23. package/agents/prompts/cx-rd-lead.md +11 -9
  24. package/agents/prompts/cx-release-manager.md +7 -5
  25. package/agents/prompts/cx-researcher.md +24 -22
  26. package/agents/prompts/cx-reviewer.md +9 -7
  27. package/agents/prompts/cx-security.md +12 -10
  28. package/agents/prompts/cx-sre.md +9 -7
  29. package/agents/prompts/cx-test-automation.md +5 -3
  30. package/agents/prompts/cx-trace-reviewer.md +10 -8
  31. package/agents/prompts/cx-ux-researcher.md +5 -3
  32. package/agents/registry.json +8 -3
  33. package/bin/construct +444 -53
  34. package/commands/build/feature.md +4 -4
  35. package/commands/build/fix.md +8 -8
  36. package/commands/design/access.md +3 -3
  37. package/commands/design/flow.md +3 -3
  38. package/commands/design/ui.md +4 -4
  39. package/commands/measure/experiment.md +5 -5
  40. package/commands/measure/metrics.md +3 -3
  41. package/commands/measure/results.md +4 -4
  42. package/commands/plan/api.md +3 -3
  43. package/commands/plan/challenge.md +3 -3
  44. package/commands/plan/decide.md +3 -3
  45. package/commands/plan/feature.md +7 -7
  46. package/commands/plan/requirements.md +3 -3
  47. package/commands/remember/context.md +5 -5
  48. package/commands/remember/handoff.md +3 -3
  49. package/commands/remember/runbook.md +3 -3
  50. package/commands/review/code.md +8 -8
  51. package/commands/review/quality.md +4 -4
  52. package/commands/review/security.md +3 -3
  53. package/commands/ship/ready.md +3 -3
  54. package/commands/ship/release.md +3 -3
  55. package/commands/ship/status.md +4 -4
  56. package/commands/understand/docs.md +3 -3
  57. package/commands/understand/this.md +4 -4
  58. package/commands/understand/why.md +8 -8
  59. package/commands/work/clean.md +14 -14
  60. package/commands/work/drive.md +10 -10
  61. package/commands/work/optimize-prompts.md +9 -9
  62. package/commands/work/parallel-review.md +8 -8
  63. package/db/schema/006_graph.sql +24 -0
  64. package/examples/provider-plugin/README.md +7 -7
  65. package/examples/seed-observations/README.md +6 -6
  66. package/examples/seed-observations/anti-patterns.md +14 -14
  67. package/examples/seed-observations/decisions.md +4 -4
  68. package/examples/seed-observations/patterns.md +14 -14
  69. package/lib/auto-docs.mjs +13 -8
  70. package/lib/boundary.mjs +126 -0
  71. package/lib/cache-strategy-google.js +26 -31
  72. package/lib/cli-commands.mjs +2 -2
  73. package/lib/comment-lint.mjs +134 -0
  74. package/lib/contracts/validate.mjs +323 -0
  75. package/lib/daemons/contract.mjs +210 -0
  76. package/lib/docs-verify.mjs +59 -6
  77. package/lib/doctor/cli.mjs +16 -1
  78. package/lib/doctor/index.mjs +3 -1
  79. package/lib/doctor/watchers/consistency.mjs +310 -0
  80. package/lib/doctor/watchers/mcp-protocol.mjs +232 -0
  81. package/lib/document-extract.mjs +211 -1
  82. package/lib/embed/cli.mjs +124 -3
  83. package/lib/embed/daemon.mjs +43 -4
  84. package/lib/embed/docs-lifecycle.mjs +1 -1
  85. package/lib/embed/inbox.mjs +2 -0
  86. package/lib/embed/scheduler.mjs +33 -5
  87. package/lib/evaluator-optimizer.mjs +2 -3
  88. package/lib/flavors/loader.mjs +1 -1
  89. package/lib/hooks/comment-lint.mjs +16 -0
  90. package/lib/hooks/mcp-audit.mjs +2 -1
  91. package/lib/hooks/proactive-activation.mjs +0 -14
  92. package/lib/hooks/rule-verifier.mjs +217 -0
  93. package/lib/hooks/session-optimize.mjs +2 -1
  94. package/lib/init-unified.mjs +55 -65
  95. package/lib/intake/classify.mjs +108 -24
  96. package/lib/intake/daemon.mjs +121 -0
  97. package/lib/intake/filesystem-queue.mjs +6 -1
  98. package/lib/intake/intake-config.mjs +2 -1
  99. package/lib/intake/prepare.mjs +0 -1
  100. package/lib/intake/session-prelude.mjs +7 -1
  101. package/lib/intake/traceability.mjs +90 -0
  102. package/lib/knowledge/graph.mjs +213 -0
  103. package/lib/knowledge/research-store.mjs +2 -0
  104. package/lib/maintenance/cleanup.mjs +315 -0
  105. package/lib/mcp/memory-bridge.mjs +276 -0
  106. package/lib/mcp/server.mjs +189 -1
  107. package/lib/mcp/tools/profile.mjs +270 -0
  108. package/lib/mcp/tools/workflow.mjs +25 -0
  109. package/lib/mcp-catalog.json +12 -8
  110. package/lib/mcp-platform-config.mjs +16 -8
  111. package/lib/migrations/index.mjs +106 -0
  112. package/lib/migrations/v1-baseline.mjs +33 -0
  113. package/lib/observation-store.mjs +9 -4
  114. package/lib/outcomes/record.mjs +2 -0
  115. package/lib/profiles/rebrand.mjs +46 -0
  116. package/lib/project-init-shared.mjs +12 -0
  117. package/lib/provider-capabilities.js +20 -7
  118. package/lib/providers/auth-manager.mjs +58 -17
  119. package/lib/reflect.mjs +49 -12
  120. package/lib/server/index.mjs +22 -28
  121. package/lib/session-store.mjs +6 -4
  122. package/lib/setup.mjs +14 -3
  123. package/lib/telemetry/client.mjs +5 -1
  124. package/lib/version.mjs +51 -0
  125. package/lib/worker/trace.mjs +5 -1
  126. package/package.json +4 -1
  127. package/personas/construct.md +3 -1
  128. package/platforms/claude/CLAUDE.md +6 -6
  129. package/rules/common/agents.md +2 -2
  130. package/rules/common/beads-hygiene.md +11 -11
  131. package/rules/common/code-review.md +1 -1
  132. package/rules/common/coding-style.md +1 -1
  133. package/rules/common/comments.md +8 -8
  134. package/rules/common/commit-approval.md +4 -4
  135. package/rules/common/cx-agent-routing.md +2 -2
  136. package/rules/common/cx-skill-routing.md +2 -2
  137. package/rules/common/development-workflow.md +3 -2
  138. package/rules/common/doc-ownership.md +2 -2
  139. package/rules/common/efficiency.md +3 -3
  140. package/rules/common/framing.md +1 -1
  141. package/rules/common/git-workflow.md +1 -1
  142. package/rules/common/no-fabrication.md +69 -0
  143. package/rules/common/patterns.md +1 -1
  144. package/rules/common/performance.md +1 -1
  145. package/rules/common/release-gates.md +7 -7
  146. package/rules/common/research.md +4 -4
  147. package/rules/common/review-before-change.md +58 -0
  148. package/rules/common/security.md +1 -1
  149. package/rules/common/skill-composition.md +8 -8
  150. package/rules/common/testing.md +1 -1
  151. package/rules/golang/coding-style.md +2 -2
  152. package/rules/golang/hooks.md +1 -1
  153. package/rules/golang/patterns.md +1 -1
  154. package/rules/golang/security.md +1 -1
  155. package/rules/golang/testing.md +1 -1
  156. package/rules/python/coding-style.md +1 -1
  157. package/rules/python/hooks.md +1 -1
  158. package/rules/python/patterns.md +1 -1
  159. package/rules/python/security.md +1 -1
  160. package/rules/python/testing.md +1 -1
  161. package/rules/swift/coding-style.md +3 -3
  162. package/rules/swift/hooks.md +2 -2
  163. package/rules/swift/patterns.md +2 -2
  164. package/rules/swift/security.md +4 -4
  165. package/rules/swift/testing.md +2 -2
  166. package/rules/typescript/coding-style.md +1 -1
  167. package/rules/typescript/hooks.md +1 -1
  168. package/rules/typescript/patterns.md +1 -1
  169. package/rules/typescript/security.md +1 -1
  170. package/rules/typescript/testing.md +1 -1
  171. package/rules/web/coding-style.md +1 -1
  172. package/rules/web/design-quality.md +1 -1
  173. package/rules/web/hooks.md +1 -1
  174. package/rules/web/patterns.md +1 -1
  175. package/rules/web/performance.md +1 -1
  176. package/rules/web/security.md +1 -1
  177. package/rules/web/testing.md +1 -1
  178. package/scripts/sync-agents.mjs +45 -14
  179. package/skills/ai/agent-dev.md +1 -1
  180. package/skills/ai/llm-security.md +1 -1
  181. package/skills/ai/ml-ops.md +6 -6
  182. package/skills/ai/orchestration-workflow.md +1 -1
  183. package/skills/ai/prompt-and-eval.md +1 -1
  184. package/skills/ai/prompt-optimizer.md +13 -13
  185. package/skills/ai/rag-system.md +1 -1
  186. package/skills/architecture/api-design.md +1 -1
  187. package/skills/architecture/caching.md +1 -1
  188. package/skills/architecture/cloud-native.md +1 -1
  189. package/skills/architecture/message-queue.md +1 -1
  190. package/skills/architecture/security-arch.md +1 -1
  191. package/skills/compliance/ai-disclosure.md +1 -1
  192. package/skills/compliance/data-privacy.md +1 -1
  193. package/skills/compliance/license-audit.md +2 -2
  194. package/skills/compliance/regulatory-review.md +1 -1
  195. package/skills/development/cpp.md +1 -1
  196. package/skills/development/go.md +1 -1
  197. package/skills/development/java.md +1 -1
  198. package/skills/development/kotlin.md +9 -9
  199. package/skills/development/mobile-crossplatform.md +13 -13
  200. package/skills/development/python.md +1 -1
  201. package/skills/development/rust.md +1 -1
  202. package/skills/development/shell.md +1 -1
  203. package/skills/development/swift.md +6 -6
  204. package/skills/development/typescript.md +1 -1
  205. package/skills/devops/ci-cd.md +5 -5
  206. package/skills/devops/containerization.md +9 -9
  207. package/skills/devops/cost-optimization.md +1 -1
  208. package/skills/devops/data-engineering.md +2 -2
  209. package/skills/devops/database.md +1 -1
  210. package/skills/devops/dependency-management.md +3 -3
  211. package/skills/devops/devsecops.md +1 -1
  212. package/skills/devops/git-workflow.md +1 -1
  213. package/skills/devops/incident-response.md +18 -18
  214. package/skills/devops/monorepo.md +5 -5
  215. package/skills/devops/observability.md +1 -1
  216. package/skills/devops/performance.md +1 -1
  217. package/skills/devops/testing.md +1 -1
  218. package/skills/docs/adr-workflow.md +2 -2
  219. package/skills/docs/backlog-proposal-workflow.md +1 -1
  220. package/skills/docs/customer-profile-workflow.md +1 -1
  221. package/skills/docs/document-ingest-workflow.md +1 -1
  222. package/skills/docs/evidence-ingest-workflow.md +1 -1
  223. package/skills/docs/init-docs.md +15 -15
  224. package/skills/docs/init-project.md +1 -1
  225. package/skills/docs/prd-workflow.md +3 -3
  226. package/skills/docs/prfaq-workflow.md +1 -1
  227. package/skills/docs/product-intelligence-review.md +1 -1
  228. package/skills/docs/product-intelligence-workflow.md +1 -1
  229. package/skills/docs/product-signal-workflow.md +9 -9
  230. package/skills/docs/research-workflow.md +10 -10
  231. package/skills/docs/runbook-workflow.md +2 -2
  232. package/skills/docs/strategy-workflow.md +3 -3
  233. package/skills/exploration/repo-map.md +11 -11
  234. package/skills/frameworks/django.md +15 -15
  235. package/skills/frameworks/nextjs.md +16 -16
  236. package/skills/frameworks/react.md +12 -12
  237. package/skills/frameworks/spring-boot.md +12 -12
  238. package/skills/frontend-design/accessibility.md +6 -6
  239. package/skills/frontend-design/component-patterns.md +1 -1
  240. package/skills/frontend-design/engineering.md +1 -1
  241. package/skills/frontend-design/state-management.md +1 -1
  242. package/skills/frontend-design/ui-aesthetics.md +1 -1
  243. package/skills/frontend-design/ux-principles.md +1 -1
  244. package/skills/operating/orchestration-reference.md +27 -27
  245. package/skills/quality-gates/review-work.md +3 -3
  246. package/skills/quality-gates/verify-change.md +1 -1
  247. package/skills/quality-gates/verify-module.md +1 -1
  248. package/skills/quality-gates/verify-quality.md +1 -1
  249. package/skills/quality-gates/verify-security.md +1 -1
  250. package/skills/routing.md +14 -14
  251. package/skills/security/blue-team.md +1 -1
  252. package/skills/security/code-audit.md +1 -1
  253. package/skills/security/pentest.md +1 -1
  254. package/skills/security/red-team.md +1 -1
  255. package/skills/security/threat-intel.md +1 -1
  256. package/skills/security/vuln-research.md +1 -1
  257. package/skills/utility/clean-code.md +2 -2
  258. package/templates/docs/changelog-entry.md +1 -1
  259. package/templates/docs/construct_guide.md +18 -18
  260. package/templates/docs/meta-prd.md +16 -16
  261. package/templates/docs/one-pager.md +1 -1
  262. package/templates/docs/prd-business.md +1 -1
  263. package/templates/docs/prd-platform.md +1 -1
  264. package/templates/docs/prd.md +17 -17
  265. package/templates/docs/research-brief.md +8 -8
  266. package/templates/docs/rfc.md +1 -1
  267. package/templates/docs/skill-artifact.md +1 -1
  268. package/templates/docs/strategy.md +1 -1
@@ -1,10 +1,10 @@
1
1
  <!--
2
- commands/work/optimize-prompts.md Prompt optimization command.
2
+ commands/work/optimize-prompts.md: Prompt optimization command.
3
3
 
4
4
  Runs the closed-loop prompt optimization workflow using telemetry trace data.
5
5
  -->
6
6
  ---
7
- description: Closed-loop prompt optimization read telemetry traces, diagnose failures, push improved version to staging
7
+ description: "Closed-loop prompt optimization: read telemetry traces, diagnose failures, push improved version to staging"
8
8
  ---
9
9
 
10
10
  You are cx-trace-reviewer running a prompt optimization cycle for: $ARGUMENTS
@@ -18,13 +18,13 @@ Optimize prompt fragments and overlays, not the runtime orchestration policy. If
18
18
 
19
19
  ## Required steps
20
20
 
21
- 1. **Read current prompt** read the agent's prompt from `agents/registry.json` (or its `promptFile`)
22
- 2. **Fetch recent scores** GET `{CONSTRUCT_TELEMETRY_URL}/api/public/scores?name=quality&limit=200`
23
- 3. **Skip agents with fewer than 20 scored traces** insufficient signal; note them but do not optimize
24
- 4. **Diagnose failure patterns** analyze low-scoring traces, identify top 3 recurring patterns
25
- 5. **Generate improved prompt** targeted edits that address failures without breaking high-scoring behaviors
26
- 6. **Push to staging** update the prompt in a staging marker comment; log the candidate via `cx_trace` with `promptVersion: staging-{timestamp}`
27
- 7. **Report** for each agent: before/after median score estimate, patterns addressed, staging version note
21
+ 1. **Read current prompt**: read the agent's prompt from `agents/registry.json` (or its `promptFile`)
22
+ 2. **Fetch recent scores**: GET `{CONSTRUCT_TELEMETRY_URL}/api/public/scores?name=quality&limit=200`
23
+ 3. **Skip agents with fewer than 20 scored traces**: insufficient signal; note them but do not optimize
24
+ 4. **Diagnose failure patterns**: analyze low-scoring traces, identify top 3 recurring patterns
25
+ 5. **Generate improved prompt**: targeted edits that address failures without breaking high-scoring behaviors
26
+ 6. **Push to staging**: update the prompt in a staging marker comment; log the candidate via `cx_trace` with `promptVersion: staging-{timestamp}`
27
+ 7. **Report**: for each agent: before/after median score estimate, patterns addressed, staging version note
28
28
 
29
29
  ## Output
30
30
 
@@ -1,21 +1,21 @@
1
1
  <!--
2
- commands/work/parallel-review.md Adversarial parallel review 5 reviewers must agree before output ships
2
+ commands/work/parallel-review.md (Adversarial parallel review) 5 reviewers must agree before output ships
3
3
 
4
- Adversarial parallel review 5 reviewers must agree before output ships
4
+ Adversarial parallel review: 5 reviewers must agree before output ships
5
5
  -->
6
6
  ---
7
- description: Adversarial parallel review 5 reviewers must agree before output ships
7
+ description: "Adversarial parallel review: 5 reviewers must agree before output ships"
8
8
  ---
9
9
 
10
10
  You are Construct running a parallel adversarial review of: $ARGUMENTS
11
11
 
12
12
  Dispatch the following 5 review roles concurrently:
13
13
 
14
- 1. **cx-reviewer** Correctness and logic: does it do what it claims? Are there off-by-ones, edge cases, or control flow bugs?
15
- 2. **cx-security** Vulnerabilities and data exposure: injection, auth bypass, secret leakage, SSRF, unvalidated input
16
- 3. **cx-qa** Test coverage and edge cases: what's untested? What inputs would break this?
17
- 4. **cx-devil-advocate** Assumption stress-test: what are we assuming that could be wrong? What failure modes are unaddressed?
18
- 5. **cx-accessibility** (UI changes) or **cx-trace-reviewer** (non-UI) Inclusive UX or performance bottlenecks
14
+ 1. **cx-reviewer**: Correctness and logic: does it do what it claims? Are there off-by-ones, edge cases, or control flow bugs?
15
+ 2. **cx-security**: Vulnerabilities and data exposure: injection, auth bypass, secret leakage, SSRF, unvalidated input
16
+ 3. **cx-qa**: Test coverage and edge cases: what's untested? What inputs would break this?
17
+ 4. **cx-devil-advocate**: Assumption stress-test: what are we assuming that could be wrong? What failure modes are unaddressed?
18
+ 5. **cx-accessibility** (UI changes) or **cx-trace-reviewer** (non-UI): Inclusive UX or performance bottlenecks
19
19
 
20
20
  ## Merge Gate
21
21
 
@@ -0,0 +1,24 @@
1
+ -- 006_graph.sql. GraphRAG community columns for entities.
2
+ --
3
+ -- Phase C9 foundations. Adds community_id (label propagation output) and a
4
+ -- community summary table so the Pg-backed deployment can query communities
5
+ -- without a JSONL scan. Solo-mode JSONL remains the source of truth; this
6
+ -- table is the projection.
7
+
8
+ ALTER TABLE construct_entities
9
+ ADD COLUMN IF NOT EXISTS community_id text,
10
+ ADD COLUMN IF NOT EXISTS community_size int;
11
+
12
+ CREATE INDEX IF NOT EXISTS idx_entities_community ON construct_entities(project, community_id);
13
+
14
+ CREATE TABLE IF NOT EXISTS construct_entity_communities (
15
+ community_id text NOT NULL,
16
+ project text NOT NULL,
17
+ size int NOT NULL DEFAULT 0,
18
+ top_members jsonb DEFAULT '[]'::jsonb,
19
+ summary text,
20
+ updated_at timestamptz NOT NULL DEFAULT now(),
21
+ PRIMARY KEY (project, community_id)
22
+ );
23
+
24
+ CREATE INDEX IF NOT EXISTS idx_communities_size ON construct_entity_communities(project, size DESC);
@@ -1,4 +1,4 @@
1
- # Hello World Construct provider plugin example
1
+ # Hello World: Construct provider plugin example
2
2
 
3
3
  A minimal reference implementation of the [Construct provider contract](../../docs/providers/authoring.md). Returns canned data; no external credentials required.
4
4
 
@@ -18,16 +18,16 @@ construct provider test hello-world --query "greet"
18
18
  ## What this shows
19
19
 
20
20
  - The factory function signature (`create({ env })`)
21
- - `meta` id, displayName, capabilities
22
- - `configSchema` JSON Schema for provider settings
23
- - `health()` always-healthy health check
24
- - `read()` look up a single item by id
25
- - `search()` full-text filter over canned items
21
+ - `meta`: id, displayName, capabilities
22
+ - `configSchema`: JSON Schema for provider settings
23
+ - `health()`: always-healthy health check
24
+ - `read()`: look up a single item by id
25
+ - `search()`: full-text filter over canned items
26
26
 
27
27
  ## Adapting for real providers
28
28
 
29
29
  1. Replace the `ITEMS` constant with real API calls.
30
- 2. Add auth logic in `create()` read tokens from `env` or `config`.
30
+ 2. Add auth logic in `create()`: read tokens from `env` or `config`.
31
31
  3. Add `watch()` and/or `webhook()` if your source supports push.
32
32
  4. Publish as an npm package and register via `construct provider plugins add <package>`.
33
33
 
@@ -1,5 +1,5 @@
1
1
  <!--
2
- examples/seed-observations/README.md seed corpus for Construct's in-tree memory layer.
2
+ examples/seed-observations/README.md: seed corpus for Construct's in-tree memory layer.
3
3
 
4
4
  Run `construct bootstrap` to import these files into the local observation and entity stores.
5
5
  The seed corpus gives the hybrid BM25 + cosine retrieval a meaningful starting signal
@@ -25,14 +25,14 @@ This corpus seeds the Construct memory layer with high-value starting knowledge.
25
25
  construct bootstrap
26
26
  ```
27
27
 
28
- Imports all three files into the local observation store. Safe to re-run duplicate
28
+ Imports all three files into the local observation store. Safe to re-run: duplicate
29
29
  observations are deduplicated by content hash.
30
30
 
31
31
  ## Payoff Timeline
32
32
 
33
- - **0 sessions** retrieval is cold; seed corpus provides baseline recall
34
- - **5 sessions** personal patterns start surfacing; seed corpus still dominant
35
- - **20 sessions** personal patterns dominate; seed corpus recedes to backstop
36
- - **50+ sessions** retrieval is fully personalized; seed corpus rarely surfaces
33
+ - **0 sessions**: retrieval is cold; seed corpus provides baseline recall
34
+ - **5 sessions**: personal patterns start surfacing; seed corpus still dominant
35
+ - **20 sessions**: personal patterns dominate; seed corpus recedes to backstop
36
+ - **50+ sessions**: retrieval is fully personalized; seed corpus rarely surfaces
37
37
 
38
38
  Run `construct memory stats` to see whether memory is paying off.
@@ -1,5 +1,5 @@
1
1
  <!--
2
- examples/seed-observations/anti-patterns.md recurring mistakes for Construct memory seed corpus.
2
+ examples/seed-observations/anti-patterns.md: recurring mistakes for Construct memory seed corpus.
3
3
 
4
4
  Each entry becomes one observation in the store with category "anti-pattern". Imported via
5
5
  `construct bootstrap`.
@@ -9,36 +9,36 @@ Each entry becomes one observation in the store with category "anti-pattern". Im
9
9
 
10
10
  ## Context Waste
11
11
 
12
- **Reading the whole file to find one function** Use Grep to locate the line number, then Read with offset/limit to read only that section. Reading a 500-line file to find a 10-line function burns ~5k tokens.
12
+ **Reading the whole file to find one function**: Use Grep to locate the line number, then Read with offset/limit to read only that section. Reading a 500-line file to find a 10-line function burns ~5k tokens.
13
13
 
14
- **Re-reading already-loaded files** If the file content is already in context, reading it again is pure waste. Check context before issuing another Read.
14
+ **Re-reading already-loaded files**: If the file content is already in context, reading it again is pure waste. Check context before issuing another Read.
15
15
 
16
- **Sequential tool calls that could be parallel** Issuing Glob, then Read, then Grep one at a time when they're independent triples the latency. Batch independent calls in one message.
16
+ **Sequential tool calls that could be parallel**: Issuing Glob, then Read, then Grep one at a time when they're independent triples the latency. Batch independent calls in one message.
17
17
 
18
18
  ## Code Authoring
19
19
 
20
- **Guessing a function signature** Never guess an API or function signature. Read the source or check the docs first. Wrong signatures produce runtime errors that cost a full round-trip to fix.
20
+ **Guessing a function signature**: Never guess an API or function signature. Read the source or check the docs first. Wrong signatures produce runtime errors that cost a full round-trip to fix.
21
21
 
22
- **Editing without reading** Issuing an Edit without a prior Read produces "oldString not found" failures when the file differs from assumptions. Always read first.
22
+ **Editing without reading**: Issuing an Edit without a prior Read produces "oldString not found" failures when the file differs from assumptions. Always read first.
23
23
 
24
- **Creating new files instead of editing existing ones** Adding a new file when the logic belongs in an existing one fragments the codebase. Check for the right home first.
24
+ **Creating new files instead of editing existing ones**: Adding a new file when the logic belongs in an existing one fragments the codebase. Check for the right home first.
25
25
 
26
- **Commenting what the code already says** `// increment counter` above `count++` adds noise. Comments earn their place by explaining non-obvious constraints, not restating syntax.
26
+ **Commenting what the code already says**: `// increment counter` above `count++` adds noise. Comments earn their place by explaining non-obvious constraints, not restating syntax.
27
27
 
28
28
  ## Testing
29
29
 
30
- **Testing the mock instead of the behavior** A test that only verifies that a mock was called doesn't confirm the real behavior. Prefer integration-level assertions over spy counts.
30
+ **Testing the mock instead of the behavior**: A test that only verifies that a mock was called doesn't confirm the real behavior. Prefer integration-level assertions over spy counts.
31
31
 
32
- **Skipping the failing test to make CI green** Skipping tests hides regressions. Fix the failure or delete the test with a comment explaining why it no longer applies.
32
+ **Skipping the failing test to make CI green**: Skipping tests hides regressions. Fix the failure or delete the test with a comment explaining why it no longer applies.
33
33
 
34
34
  ## Git
35
35
 
36
- **Amending a pushed commit** `git commit --amend` after a push requires force-push, which rewrites shared history. Use a new commit instead.
36
+ **Amending a pushed commit**: `git commit --amend` after a push requires force-push, which rewrites shared history. Use a new commit instead.
37
37
 
38
- **Committing without running tests** Tests exist to catch regressions before they land on main. A green build is the only signal that a change is safe to ship.
38
+ **Committing without running tests**: Tests exist to catch regressions before they land on main. A green build is the only signal that a change is safe to ship.
39
39
 
40
40
  ## Agent Behavior
41
41
 
42
- **Stopping without surfacing incomplete tasks** An agent that stops while tasks are `in_progress` or have unmet acceptance criteria leaves the user without visibility. Surface the state before stopping.
42
+ **Stopping without surfacing incomplete tasks**: An agent that stops while tasks are `in_progress` or have unmet acceptance criteria leaves the user without visibility. Surface the state before stopping.
43
43
 
44
- **Making assumptions about user intent** When a requirement is ambiguous, ask one targeted question rather than guessing and building the wrong thing.
44
+ **Making assumptions about user intent**: When a requirement is ambiguous, ask one targeted question rather than guessing and building the wrong thing.
@@ -1,5 +1,5 @@
1
1
  <!--
2
- examples/seed-observations/decisions.md key architectural decisions for Construct memory seed corpus.
2
+ examples/seed-observations/decisions.md: key architectural decisions for Construct memory seed corpus.
3
3
 
4
4
  Each entry becomes one observation in the store with category "decision". Imported via
5
5
  `construct bootstrap`.
@@ -13,7 +13,7 @@ Each entry becomes one observation in the store with category "decision". Import
13
13
 
14
14
  ## Two-Phase Sync with Lockfile
15
15
 
16
- `construct sync` writes to `.cx/sync-staging/` first, then atomically renames into place. A lockfile at `.cx/sync.lock` prevents concurrent runs from corrupting the output. This makes partial syncs impossible either the full sync lands or nothing does.
16
+ `construct sync` writes to `.cx/sync-staging/` first, then atomically renames into place. A lockfile at `.cx/sync.lock` prevents concurrent runs from corrupting the output. This makes partial syncs impossible: either the full sync lands or nothing does.
17
17
 
18
18
  ## Hook Ceiling: 30
19
19
 
@@ -25,7 +25,7 @@ The memory layer uses a hashing bag-of-words cosine similarity for dense recall
25
25
 
26
26
  ## Tiered Session-Start Injection
27
27
 
28
- Session-start injects context in three tiers: Tier 1 (always header, branch, status), Tier 2 (when fresh and meaningful workflow, observations, context.md), Tier 3 (hint-only efficiency snapshot, skill scope). This caps injection size and avoids loading the model with stale or irrelevant context on every session.
28
+ Session-start injects context in three tiers: Tier 1 (always (header, branch, status), Tier 2 (when fresh and meaningful) workflow, observations, context.md), Tier 3 (hint-only: efficiency snapshot, skill scope). This caps injection size and avoids loading the model with stale or irrelevant context on every session.
29
29
 
30
30
  ## Declarative Policy Rules
31
31
 
@@ -33,4 +33,4 @@ Hook guards for workflow, drive, bootstrap, and task behavior are expressed as Y
33
33
 
34
34
  ## Registry as Single Source of Truth
35
35
 
36
- `agents/registry.json` is the canonical definition for all agents on all platforms (Claude Code, OpenCode, Codex, Copilot). `construct sync` regenerates all platform-specific files from the registry. Never edit generated files directly edits are overwritten on the next sync.
36
+ `agents/registry.json` is the canonical definition for all agents on all platforms (Claude Code, OpenCode, Codex, Copilot). `construct sync` regenerates all platform-specific files from the registry. Never edit generated files directly: edits are overwritten on the next sync.
@@ -1,5 +1,5 @@
1
1
  <!--
2
- examples/seed-observations/patterns.md engineering patterns for Construct memory seed corpus.
2
+ examples/seed-observations/patterns.md: engineering patterns for Construct memory seed corpus.
3
3
 
4
4
  Each entry becomes one observation in the store. Format: ## Category, then pattern entries
5
5
  with **Pattern name** and description. Imported via `construct bootstrap`.
@@ -9,34 +9,34 @@ with **Pattern name** and description. Imported via `construct bootstrap`.
9
9
 
10
10
  ## Code Quality
11
11
 
12
- **Read before edit** Always read the target file with the Read tool before writing or editing. Editing without reading produces stale edits that fail with "oldString not found".
12
+ **Read before edit**: Always read the target file with the Read tool before writing or editing. Editing without reading produces stale edits that fail with "oldString not found".
13
13
 
14
- **Parallel tool calls for independent work** When two tool calls don't depend on each other's output, issue them in the same message. Cuts wall time roughly in half for multi-file operations.
14
+ **Parallel tool calls for independent work**: When two tool calls don't depend on each other's output, issue them in the same message. Cuts wall time roughly in half for multi-file operations.
15
15
 
16
- **Probe before bulk read** Use Glob or Grep to identify which files are relevant before reading them. Bulk-reading 10 files to find the one that matters burns context and slows response.
16
+ **Probe before bulk read**: Use Glob or Grep to identify which files are relevant before reading them. Bulk-reading 10 files to find the one that matters burns context and slows response.
17
17
 
18
- **Edit smallest possible diff** Target the exact lines that need to change. Large oldString blocks with unchanged surrounding context are fragile when the file is modified concurrently.
18
+ **Edit smallest possible diff**: Target the exact lines that need to change. Large oldString blocks with unchanged surrounding context are fragile when the file is modified concurrently.
19
19
 
20
20
  ## Testing
21
21
 
22
- **Run targeted test first** Before running the full suite, run only the affected test file. Faster feedback loop; full suite confirms no regressions.
22
+ **Run targeted test first**: Before running the full suite, run only the affected test file. Faster feedback loop; full suite confirms no regressions.
23
23
 
24
- **Assert the contract, not the implementation** Tests that check internal state (private variables, call counts) break on refactors that don't change behavior. Test the public output.
24
+ **Assert the contract, not the implementation**: Tests that check internal state (private variables, call counts) break on refactors that don't change behavior. Test the public output.
25
25
 
26
- **Table-driven tests for edge cases** When a function has many input/output pairs to verify, a single table-driven test is more maintainable than N separate `it()` blocks.
26
+ **Table-driven tests for edge cases**: When a function has many input/output pairs to verify, a single table-driven test is more maintainable than N separate `it()` blocks.
27
27
 
28
28
  ## Git Discipline
29
29
 
30
- **Branch, test, merge** Never commit directly to main. Branch for every feature or fix, verify tests pass, then merge.
30
+ **Branch, test, merge**: Never commit directly to main. Branch for every feature or fix, verify tests pass, then merge.
31
31
 
32
- **Commit message: why, not what** The diff already shows what changed. The commit message should explain why. "fix dry-run bypass" is less useful than "fix: dry-run skipped mkdirp calls, causing 31 phantom files in test home".
32
+ **Commit message: why, not what**: The diff already shows what changed. The commit message should explain why. "fix dry-run bypass" is less useful than "fix: dry-run skipped mkdirp calls, causing 31 phantom files in test home".
33
33
 
34
- **Atomic commits** One logical change per commit. Mixing a bug fix with a refactor makes bisect and revert painful.
34
+ **Atomic commits**: One logical change per commit. Mixing a bug fix with a refactor makes bisect and revert painful.
35
35
 
36
36
  ## Agent Dispatch
37
37
 
38
- **Route through Construct** Construct is the single dispatch point. Invoking specialist agents directly bypasses context injection and workflow tracking.
38
+ **Route through Construct**: Construct is the single dispatch point. Invoking specialist agents directly bypasses context injection and workflow tracking.
39
39
 
40
- **Subagent for isolated subtasks** Use Task tool dispatch when a subtask has a clear input/output contract and doesn't need the parent conversation history. Keeps the main context lean.
40
+ **Subagent for isolated subtasks**: Use Task tool dispatch when a subtask has a clear input/output contract and doesn't need the parent conversation history. Keeps the main context lean.
41
41
 
42
- **Timeout specialist calls** Agent dispatch without a timeout can block indefinitely. Set `timeout: 120_000` as a floor; use 300_000 for heavy analysis tasks.
42
+ **Timeout specialist calls**: Agent dispatch without a timeout can block indefinitely. Set `timeout: 120_000` as a floor; use 300_000 for heavy analysis tasks.
package/lib/auto-docs.mjs CHANGED
@@ -158,11 +158,16 @@ function buildAgentsTable(rootDir) {
158
158
  const agents = registry.agents ?? registry;
159
159
  if (!Array.isArray(agents)) return '';
160
160
 
161
- const rows = ['| Agent | Tier | Purpose |', '|---|---|---|'];
161
+ const rows = ['| Specialist | Tier | Purpose |', '|---|---|---|'];
162
162
  for (const agent of agents.slice(0, 30)) {
163
- const name = agent.id ?? agent.name ?? '';
164
- const tier = agent.tier ?? agent.model_tier ?? '';
165
- const purpose = (agent.description ?? agent.purpose ?? '').split('\n')[0].slice(0, 80);
163
+ const name = agent.name ?? agent.id ?? 'n/a';
164
+ const tier = agent.modelTier ?? agent.tier ?? agent.model_tier ?? 'n/a';
165
+ // Strip em-dashes from descriptions so the prose lint stays clean across
166
+ // AUTO regen. Em-dashes are allowed in the registry's source descriptions
167
+ // but never in the rendered markdown.
168
+ const purpose = (agent.description ?? agent.purpose ?? '')
169
+ .split('\n')[0].slice(0, 80)
170
+ .replace(/ — /g, '. ').replace(/—/g, ',');
166
171
  rows.push(`| \`${name}\` | ${tier} | ${purpose} |`);
167
172
  }
168
173
  if (agents.length > 30) rows.push(`| *(+${agents.length - 30} more)* | | |`);
@@ -190,7 +195,7 @@ export async function regenerateDocs({ rootDir, check = false } = {}) {
190
195
  },
191
196
  },
192
197
  {
193
- file: path.join(rootDir, 'docs', 'concepts', 'architecture.md'),
198
+ file: path.join(rootDir, 'docs', 'concepts', 'architecture.mdx'),
194
199
  regions: {
195
200
  agents: buildAgentsTable(rootDir),
196
201
  },
@@ -391,13 +396,13 @@ function renderAgentsPage(rootDir) {
391
396
  if (!table) return null;
392
397
  return [
393
398
  '---',
394
- 'title: Agents',
395
- 'description: The 28 cx-* specialists plus the construct persona. Generated from agents/registry.json.',
399
+ 'title: Specialists',
400
+ 'description: The 28 specialists behind the construct persona. Generated from agents/registry.json.',
396
401
  '---',
397
402
  '',
398
403
  '> Generated from `agents/registry.json`. Re-run `construct docs:site` to refresh.',
399
404
  '',
400
- 'Construct ships one persona (`construct`) plus 28 specialists. Each specialist has a role, model tier, and prompt that defines its decision authority. Specialists are addressable directly when you want a focused conversation; for everyday work, address `@construct` and let it route.',
405
+ 'Construct ships one persona (`construct`) and 28 specialists behind it. You address `@construct` for all everyday work; it routes to specialists internally. Each specialist has a role, model tier, and prompt file that defines its decision authority.',
401
406
  '',
402
407
  table,
403
408
  '',
@@ -0,0 +1,126 @@
1
+ /**
2
+ * lib/boundary.mjs — Authenticated parent/child boundary registration.
3
+ *
4
+ * Verifies a parent Construct instance is reachable, validates an HMAC
5
+ * signature over `childInstanceId|nonce` when a shared secret is configured,
6
+ * and persists the binding to ~/.construct/boundary.json (mode 0600). A
7
+ * different parent rotates the registration only when explicitly allowed via
8
+ * CONSTRUCT_BOUNDARY_ALLOW_OVERRIDE=1; prior configs are archived alongside
9
+ * the active one. Exposed as a standalone module so the dashboard endpoint
10
+ * and the functional tests share the same logic.
11
+ */
12
+
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+ import { homedir } from 'node:os';
16
+ import { createHmac, timingSafeEqual, randomBytes } from 'node:crypto';
17
+ import { request as httpRequest } from 'node:http';
18
+ import { request as httpsRequest } from 'node:https';
19
+
20
+ export const BOUNDARY_VERSION = '1.0';
21
+
22
+ function boundaryDir(home = homedir()) {
23
+ return join(home, '.construct');
24
+ }
25
+
26
+ export function boundaryConfigPath(home = homedir()) {
27
+ return join(boundaryDir(home), 'boundary.json');
28
+ }
29
+
30
+ export async function registerBoundary({
31
+ parentInstance,
32
+ parentUrl,
33
+ childInstanceId,
34
+ nonce,
35
+ signature,
36
+ sharedSecret = null,
37
+ home = homedir(),
38
+ allowOverride = process.env.CONSTRUCT_BOUNDARY_ALLOW_OVERRIDE === '1',
39
+ probe = probeParent,
40
+ }) {
41
+ if (!parentInstance || !parentUrl) {
42
+ return { ok: false, status: 400, error: 'parentInstance and parentUrl are required' };
43
+ }
44
+ if (!childInstanceId) {
45
+ return { ok: false, status: 400, error: 'childInstanceId is required' };
46
+ }
47
+
48
+ if (sharedSecret) {
49
+ if (!nonce || !signature) {
50
+ return { ok: false, status: 401, error: 'nonce and signature are required when a shared secret is configured' };
51
+ }
52
+ const expected = createHmac('sha256', sharedSecret).update(`${childInstanceId}|${nonce}`).digest('hex');
53
+ const a = Buffer.from(expected, 'hex');
54
+ let b;
55
+ try { b = Buffer.from(String(signature), 'hex'); } catch { return { ok: false, status: 401, error: 'invalid signature encoding' }; }
56
+ if (a.length !== b.length || !timingSafeEqual(a, b)) {
57
+ return { ok: false, status: 401, error: 'signature mismatch' };
58
+ }
59
+ }
60
+
61
+ const reachable = await probe(parentUrl);
62
+ if (!reachable.ok) {
63
+ return { ok: false, status: 502, error: `parent unreachable: ${reachable.error}` };
64
+ }
65
+
66
+ const dir = boundaryDir(home);
67
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
68
+ const cfgPath = boundaryConfigPath(home);
69
+
70
+ let prior = null;
71
+ if (existsSync(cfgPath)) {
72
+ try { prior = JSON.parse(readFileSync(cfgPath, 'utf8')); } catch { prior = null; }
73
+ }
74
+
75
+ if (prior && prior.parentInstance && prior.parentInstance !== parentInstance) {
76
+ if (!allowOverride) {
77
+ return {
78
+ ok: false,
79
+ status: 409,
80
+ error: `child already bound to parent '${prior.parentInstance}'; set CONSTRUCT_BOUNDARY_ALLOW_OVERRIDE=1 to rotate`,
81
+ };
82
+ }
83
+ const archivePath = join(dir, `boundary.${Date.now()}.json`);
84
+ try { writeFileSync(archivePath, JSON.stringify(prior, null, 2)); } catch { /* archive is best effort */ }
85
+ }
86
+
87
+ const config = {
88
+ parentInstance,
89
+ parentUrl,
90
+ childInstanceId,
91
+ registeredAt: new Date().toISOString(),
92
+ rotatedFrom: prior?.parentInstance || null,
93
+ nonce: nonce || randomBytes(16).toString('hex'),
94
+ boundaryVersion: BOUNDARY_VERSION,
95
+ };
96
+
97
+ writeFileSync(cfgPath, JSON.stringify(config, null, 2), { mode: 0o600 });
98
+ return { ok: true, config, path: cfgPath };
99
+ }
100
+
101
+ export function probeParent(parentUrl) {
102
+ return new Promise((resolve) => {
103
+ let parsed;
104
+ try { parsed = new URL(parentUrl); } catch { return resolve({ ok: false, error: 'invalid URL' }); }
105
+ if (!/^https?:$/.test(parsed.protocol)) return resolve({ ok: false, error: 'unsupported protocol' });
106
+ const fn = parsed.protocol === 'https:' ? httpsRequest : httpRequest;
107
+ const req = fn({
108
+ method: 'HEAD',
109
+ protocol: parsed.protocol,
110
+ hostname: parsed.hostname,
111
+ port: parsed.port,
112
+ path: parsed.pathname || '/',
113
+ timeout: 3000,
114
+ }, (response) => {
115
+ resolve({ ok: response.statusCode < 500 });
116
+ response.resume();
117
+ });
118
+ req.on('timeout', () => { req.destroy(); resolve({ ok: false, error: 'timeout' }); });
119
+ req.on('error', (err) => resolve({ ok: false, error: err.message }));
120
+ req.end();
121
+ });
122
+ }
123
+
124
+ export function signBoundaryRequest({ childInstanceId, nonce, sharedSecret }) {
125
+ return createHmac('sha256', sharedSecret).update(`${childInstanceId}|${nonce}`).digest('hex');
126
+ }
@@ -1,17 +1,34 @@
1
1
  /**
2
- * lib/cache-strategy-google.js — Google Gemini cache strategy.
2
+ * lib/cache-strategy-google.js — Google Gemini cache strategy (agnostic skeleton).
3
3
  *
4
- * Google uses cachedContent API (resource-based caching, not annotations).
5
- * Cache TTL: 1h via cachedContent resource.
6
- * Requires separate API call to create/update cached content.
4
+ * Gemini uses a resource-based cachedContent API rather than per-message
5
+ * annotations. Construct does not own that integration: this module exposes
6
+ * the same surface as the other cache-strategy adapters and resolves cached
7
+ * resources via a pluggable resolver. The default resolver returns null
8
+ * (no cached resource), which is the safe agnostic default — callers will
9
+ * fall through to a fresh request. Provider plugins or operators can register
10
+ * a resolver via `setCachedContentResolver` to enable resource caching.
7
11
  */
8
12
  import { estimateTokens } from './token-engine.js';
9
13
 
10
14
  const GEMINI_CACHE_ENDPOINT = 'https://generativelanguage.googleapis.com/v1';
11
15
 
16
+ let cachedContentResolver = null;
17
+
18
+ /**
19
+ * Register a resolver responsible for producing a cachedContent resource name
20
+ * for a given system prompt. Contract:
21
+ * resolver({ systemText, caps, apiKey, modelId }) -> Promise<string|null>
22
+ * Returning null means no cached resource is available; the annotation is
23
+ * omitted and the request proceeds without a cached prefix.
24
+ */
25
+ export function setCachedContentResolver(resolver) {
26
+ cachedContentResolver = typeof resolver === 'function' ? resolver : null;
27
+ }
28
+
12
29
  /**
13
- * Annotate prompt structure for Google Gemini models.
14
- * Note: Gemini uses cachedContent API, not message annotations.
30
+ * Annotate prompt structure for Google Gemini models. Returns the shared
31
+ * annotation shape that every cache-strategy adapter emits.
15
32
  *
16
33
  * @param {object} promptStructure - { system, messages }
17
34
  * @param {object} caps - Provider capabilities
@@ -22,12 +39,10 @@ export async function annotate(promptStructure, caps, { apiKey, modelId } = {})
22
39
  const { system, messages } = promptStructure || {};
23
40
 
24
41
  let cachedContentName = null;
25
-
26
- if (apiKey && system) {
42
+ if (cachedContentResolver && apiKey && system) {
27
43
  try {
28
- cachedContentName = await createCachedContent(system, caps, apiKey, modelId);
29
- } catch (err) {
30
- }
44
+ cachedContentName = await cachedContentResolver({ systemText: system, caps, apiKey, modelId });
45
+ } catch { /* resolver failure is non-fatal — fall through with no annotation */ }
31
46
  }
32
47
 
33
48
  return {
@@ -49,26 +64,6 @@ export async function annotate(promptStructure, caps, { apiKey, modelId } = {})
49
64
  };
50
65
  }
51
66
 
52
- async function createCachedContent(systemText, caps, apiKey, modelId) {
53
- // POST to https://generativelanguage.googleapis.com/v1/cachedContents
54
- // Body: { model: 'gemini-1.5-pro', contents: [{ parts: [{ text: systemText }] }] }
55
- // Returns: { name: 'cachedContents/abc123' }
56
-
57
- const model = extractModelName(modelId);
58
- const url = `${GEMINI_CACHE_ENDPOINT}/cachedContents?key=${apiKey}`;
59
-
60
- // This is async but we don't want to block dispatch
61
- // In production, this should be pre-cached
62
- // For now, return null (defer to Phase C follow-up with live probing)
63
- return null;
64
- }
65
-
66
- function extractModelName(modelId) {
67
- const id = String(modelId || '').toLowerCase();
68
- const match = id.match(/google\/(gemini-[^\/]+)/);
69
- return match ? match[1] : 'gemini-1.5-pro';
70
- }
71
-
72
67
  export async function capabilities() {
73
68
  return {
74
69
  supportsAnnotations: false,
@@ -92,7 +92,7 @@ export const CLI_COMMANDS = [
92
92
  emoji: '📥',
93
93
  category: 'Core',
94
94
  core: true,
95
- description: 'View and process R&D intake queue',
95
+ description: 'View and process the active profile\'s intake queue (queue label varies by profile)',
96
96
  usage: 'construct intake list|show|done|skip',
97
97
  },
98
98
  {
@@ -166,7 +166,7 @@ export const CLI_COMMANDS = [
166
166
  { name: 'show', desc: 'Show the active profile' },
167
167
  { name: 'list', desc: 'List curated profiles' },
168
168
  { name: 'set <id>', desc: 'Switch the active profile (writes construct.config.json)' },
169
- { name: 'create <id> [--display="..."]', desc: 'Scaffold a draft profile + requirements brief under .cx/profiles/draft-<id>/' },
169
+ { name: 'create <id> [--display=…] [--role=…] [--department=…] [--yes|--dry-run]', desc: 'Scaffold a draft profile; previews and confirms by default, prompts interactively when no flags' },
170
170
  { name: 'drafts', desc: 'List in-progress draft profiles' },
171
171
  { name: 'archive <id> --reason="..."', desc: 'Move a curated profile into archive/profiles/<id>/' },
172
172
  { name: 'health <id> [--days=N]', desc: 'Per-profile observation + outcome rollup' },