@geraldmaron/construct 1.0.15 → 1.0.17

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 (198) hide show
  1. package/README.md +19 -3
  2. package/bin/construct +376 -98
  3. package/bin/construct-postinstall.mjs +17 -2
  4. package/db/schema/010_cx_scores.sql +51 -0
  5. package/lib/cli-commands.mjs +333 -147
  6. package/lib/contracts/validate.mjs +20 -10
  7. package/lib/contracts/violation-log.mjs +27 -12
  8. package/lib/embedded-contract/audit.mjs +52 -0
  9. package/lib/embedded-contract/capability.mjs +179 -0
  10. package/lib/embedded-contract/contract-version.mjs +39 -0
  11. package/lib/embedded-contract/envelope.mjs +70 -0
  12. package/lib/embedded-contract/index.mjs +71 -0
  13. package/lib/embedded-contract/ingest.mjs +77 -0
  14. package/lib/embedded-contract/model-resolve.mjs +186 -0
  15. package/lib/embedded-contract/redaction.mjs +91 -0
  16. package/lib/embedded-contract/role-facts.mjs +66 -0
  17. package/lib/embedded-contract/triage.mjs +134 -0
  18. package/lib/embedded-contract/workflow-defs.mjs +125 -0
  19. package/lib/embedded-contract/workflow-invoke.mjs +218 -0
  20. package/lib/hooks/config-protection.mjs +12 -5
  21. package/lib/hooks/stop-notify.mjs +7 -0
  22. package/lib/init-unified.mjs +36 -26
  23. package/lib/install/first-invocation.mjs +5 -1
  24. package/lib/intake/classify.mjs +6 -0
  25. package/lib/intake/prepare.mjs +22 -4
  26. package/lib/intake/tables/rnd.mjs +33 -0
  27. package/lib/integrations/intake-integrations.mjs +28 -2
  28. package/lib/mcp/server.mjs +69 -0
  29. package/lib/mcp/tools/embedded-contract.mjs +77 -0
  30. package/lib/mcp/tools/telemetry.mjs +30 -0
  31. package/lib/model-router.mjs +40 -0
  32. package/lib/op-log.mjs +61 -0
  33. package/lib/orchestration-policy.mjs +15 -0
  34. package/lib/roles/catalog.mjs +26 -95
  35. package/lib/roles/gateway.mjs +30 -1
  36. package/lib/scheduler/index.mjs +24 -4
  37. package/lib/server/insights.mjs +12 -0
  38. package/lib/service-manager.mjs +33 -11
  39. package/lib/setup.mjs +73 -10
  40. package/lib/update.mjs +31 -3
  41. package/lib/upgrade.mjs +31 -4
  42. package/lib/validators/skills.mjs +21 -0
  43. package/package.json +9 -3
  44. package/personas/construct.md +2 -0
  45. package/platforms/claude/CLAUDE.md +43 -15
  46. package/scripts/sync-specialists.mjs +32 -5
  47. package/skills/ai/agent-dev.md +2 -0
  48. package/skills/ai/llm-security.md +2 -0
  49. package/skills/ai/ml-ops.md +2 -0
  50. package/skills/ai/orchestration-workflow.md +2 -0
  51. package/skills/ai/prompt-and-eval.md +2 -0
  52. package/skills/ai/prompt-optimizer.md +2 -0
  53. package/skills/ai/rag-system.md +2 -0
  54. package/skills/ai/trace-triage.md +36 -0
  55. package/skills/architecture/api-design.md +2 -0
  56. package/skills/architecture/caching.md +2 -0
  57. package/skills/architecture/cloud-native.md +2 -0
  58. package/skills/architecture/message-queue.md +2 -0
  59. package/skills/architecture/security-arch.md +2 -0
  60. package/skills/compliance/ai-disclosure.md +2 -0
  61. package/skills/compliance/data-privacy.md +2 -0
  62. package/skills/compliance/license-audit.md +2 -0
  63. package/skills/compliance/regulatory-review.md +2 -0
  64. package/skills/development/cpp.md +2 -0
  65. package/skills/development/go.md +2 -0
  66. package/skills/development/java.md +2 -0
  67. package/skills/development/kotlin.md +2 -0
  68. package/skills/development/mobile-crossplatform.md +2 -0
  69. package/skills/development/python.md +2 -0
  70. package/skills/development/rust.md +2 -0
  71. package/skills/development/shell.md +2 -0
  72. package/skills/development/swift.md +2 -0
  73. package/skills/development/typescript.md +2 -0
  74. package/skills/devops/ci-cd.md +2 -0
  75. package/skills/devops/containerization.md +2 -0
  76. package/skills/devops/cost-optimization.md +2 -0
  77. package/skills/devops/data-engineering.md +2 -0
  78. package/skills/devops/database.md +2 -0
  79. package/skills/devops/dependency-management.md +2 -0
  80. package/skills/devops/devsecops.md +2 -0
  81. package/skills/devops/git-workflow.md +2 -0
  82. package/skills/devops/incident-response.md +2 -0
  83. package/skills/devops/monorepo.md +2 -0
  84. package/skills/devops/observability.md +2 -0
  85. package/skills/devops/performance.md +2 -0
  86. package/skills/devops/testing.md +2 -0
  87. package/skills/docs/adr-workflow.md +2 -0
  88. package/skills/docs/backlog-proposal-workflow.md +2 -0
  89. package/skills/docs/customer-profile-workflow.md +2 -0
  90. package/skills/docs/document-ingest-workflow.md +2 -0
  91. package/skills/docs/evidence-ingest-workflow.md +2 -0
  92. package/skills/docs/init-docs.md +2 -0
  93. package/skills/docs/init-project.md +2 -0
  94. package/skills/docs/memo-and-decision-capture.md +45 -0
  95. package/skills/docs/prd-workflow.md +2 -0
  96. package/skills/docs/prfaq-workflow.md +2 -0
  97. package/skills/docs/product-intelligence-review.md +2 -0
  98. package/skills/docs/product-intelligence-workflow.md +2 -0
  99. package/skills/docs/product-signal-workflow.md +2 -0
  100. package/skills/docs/research-workflow.md +2 -0
  101. package/skills/docs/runbook-workflow.md +2 -0
  102. package/skills/docs/strategy-workflow.md +2 -0
  103. package/skills/docs/transcript-synthesis.md +43 -0
  104. package/skills/exploration/dependency-graph-reading.md +2 -0
  105. package/skills/exploration/repo-map.md +2 -0
  106. package/skills/exploration/tracer-bullet-method.md +2 -0
  107. package/skills/exploration/unknown-codebase-onboarding.md +2 -0
  108. package/skills/frameworks/django.md +2 -0
  109. package/skills/frameworks/nextjs.md +2 -0
  110. package/skills/frameworks/react.md +2 -0
  111. package/skills/frameworks/spring-boot.md +2 -0
  112. package/skills/frontend-design/accessibility.md +2 -0
  113. package/skills/frontend-design/component-patterns.md +2 -0
  114. package/skills/frontend-design/engineering.md +2 -0
  115. package/skills/frontend-design/screen-reader-testing.md +34 -0
  116. package/skills/frontend-design/state-management.md +2 -0
  117. package/skills/frontend-design/ui-aesthetics.md +2 -0
  118. package/skills/frontend-design/ux-principles.md +2 -0
  119. package/skills/operating/change-management.md +2 -0
  120. package/skills/operating/incident-response.md +2 -0
  121. package/skills/operating/oncall-rotation.md +2 -0
  122. package/skills/operating/orchestration-reference.md +2 -0
  123. package/skills/operating/raw-data-structuring.md +44 -0
  124. package/skills/operating/unstructured-triage.md +45 -0
  125. package/skills/quality-gates/premortem.md +37 -0
  126. package/skills/quality-gates/review-work.md +2 -0
  127. package/skills/quality-gates/verify-change.md +2 -0
  128. package/skills/quality-gates/verify-module.md +2 -0
  129. package/skills/quality-gates/verify-quality.md +2 -0
  130. package/skills/quality-gates/verify-security.md +2 -0
  131. package/skills/roles/architect.ai-systems.md +2 -0
  132. package/skills/roles/architect.data.md +2 -0
  133. package/skills/roles/architect.enterprise.md +2 -0
  134. package/skills/roles/architect.integration.md +2 -0
  135. package/skills/roles/architect.md +2 -0
  136. package/skills/roles/architect.platform.md +2 -0
  137. package/skills/roles/data-analyst.experiment.md +2 -0
  138. package/skills/roles/data-analyst.md +2 -0
  139. package/skills/roles/data-analyst.product-intelligence.md +2 -0
  140. package/skills/roles/data-analyst.product.md +2 -0
  141. package/skills/roles/data-analyst.telemetry.md +2 -0
  142. package/skills/roles/data-engineer.pipeline.md +2 -0
  143. package/skills/roles/data-engineer.vector-retrieval.md +2 -0
  144. package/skills/roles/data-engineer.warehouse.md +2 -0
  145. package/skills/roles/debugger.md +2 -0
  146. package/skills/roles/designer.accessibility.md +2 -0
  147. package/skills/roles/designer.md +2 -0
  148. package/skills/roles/engineer.ai.md +2 -0
  149. package/skills/roles/engineer.data.md +2 -0
  150. package/skills/roles/engineer.md +2 -0
  151. package/skills/roles/engineer.platform.md +2 -0
  152. package/skills/roles/operator.docs.md +2 -0
  153. package/skills/roles/operator.md +2 -0
  154. package/skills/roles/operator.release.md +2 -0
  155. package/skills/roles/operator.sre.md +2 -0
  156. package/skills/roles/orchestrator.md +2 -0
  157. package/skills/roles/product-manager.ai-product.md +2 -0
  158. package/skills/roles/product-manager.business-strategy.md +2 -0
  159. package/skills/roles/product-manager.enterprise.md +2 -0
  160. package/skills/roles/product-manager.growth.md +2 -0
  161. package/skills/roles/product-manager.md +2 -0
  162. package/skills/roles/product-manager.platform.md +2 -0
  163. package/skills/roles/product-manager.product.md +2 -0
  164. package/skills/roles/qa.ai-eval.md +2 -0
  165. package/skills/roles/qa.api-contract.md +2 -0
  166. package/skills/roles/qa.data-pipeline.md +2 -0
  167. package/skills/roles/qa.md +2 -0
  168. package/skills/roles/qa.test-automation.md +2 -0
  169. package/skills/roles/qa.web-ui.md +2 -0
  170. package/skills/roles/researcher.explorer.md +2 -0
  171. package/skills/roles/researcher.md +2 -0
  172. package/skills/roles/researcher.ux.md +2 -0
  173. package/skills/roles/reviewer.devil-advocate.md +2 -0
  174. package/skills/roles/reviewer.evaluator.md +2 -0
  175. package/skills/roles/reviewer.md +2 -0
  176. package/skills/roles/reviewer.trace.md +2 -0
  177. package/skills/roles/security.ai.md +2 -0
  178. package/skills/roles/security.appsec.md +2 -0
  179. package/skills/roles/security.cloud.md +2 -0
  180. package/skills/roles/security.legal-compliance.md +2 -0
  181. package/skills/roles/security.md +2 -0
  182. package/skills/roles/security.privacy.md +2 -0
  183. package/skills/roles/security.supply-chain.md +2 -0
  184. package/skills/security/blue-team.md +2 -0
  185. package/skills/security/code-audit.md +2 -0
  186. package/skills/security/pentest.md +2 -0
  187. package/skills/security/red-team.md +2 -0
  188. package/skills/security/threat-intel.md +2 -0
  189. package/skills/security/vuln-research.md +2 -0
  190. package/skills/strategy/competitive-landscape.md +2 -0
  191. package/skills/strategy/jobs-to-be-done.md +38 -0
  192. package/skills/strategy/market-research-methods.md +2 -0
  193. package/skills/strategy/narrative-arc.md +2 -0
  194. package/skills/strategy/pricing-positioning.md +2 -0
  195. package/skills/utility/clean-code.md +2 -0
  196. package/specialists/prompts/cx-engineer.md +1 -1
  197. package/specialists/registry.json +18 -9
  198. package/specialists/role-manifests.json +1 -1
@@ -9,6 +9,7 @@
9
9
  * Command Visibility:
10
10
  * - core: true → shown in default --help (90% of users)
11
11
  * - core: false → hidden unless --all flag (advanced/internal commands)
12
+ * - internal: true → hidden from --help and --all; callable but not advertised
12
13
  */
13
14
 
14
15
  export const CLI_COMMANDS = [
@@ -19,7 +20,11 @@ export const CLI_COMMANDS = [
19
20
  category: 'Core',
20
21
  core: true,
21
22
  description: 'Start services for development',
22
- usage: 'construct dev',
23
+ usage: 'construct dev [--select] [--only=postgres,dashboard,...]',
24
+ options: [
25
+ { flag: '--select', desc: 'Pick which services to start from an interactive checklist' },
26
+ { flag: '--only=<a,b,c>', desc: 'Start only the named services (postgres, dashboard, telemetry, memory, opencode)' },
27
+ ],
23
28
  },
24
29
  {
25
30
  name: 'stop',
@@ -45,10 +50,12 @@ export const CLI_COMMANDS = [
45
50
  emoji: '🛠️',
46
51
  category: 'Core',
47
52
  core: true,
48
- description: 'Machine setup: install Docker, cm, and bootstrap config',
49
- usage: 'construct install [--yes]',
53
+ description: 'Machine setup (once per machine): Docker, cm/cass, config, embeddings',
54
+ usage: 'construct install [--yes] [--no-docker] [--reconfigure]',
50
55
  options: [
51
- { flag: '--yes', desc: 'Apply defaults without prompts' },
56
+ { flag: '--yes', desc: 'Apply defaults without prompts' },
57
+ { flag: '--no-docker', desc: 'Skip Docker-based service setup (local Postgres)' },
58
+ { flag: '--reconfigure', desc: 'Re-prompt for service consent, ignoring cached answers' },
52
59
  ],
53
60
  },
54
61
  {
@@ -56,7 +63,7 @@ export const CLI_COMMANDS = [
56
63
  emoji: '🏗️',
57
64
  category: 'Core',
58
65
  core: true,
59
- description: 'Initialize project and start services',
66
+ description: 'Project setup (once per repo): scaffold .cx/, AGENTS.md, plan.md, adapters',
60
67
  usage: 'construct init [path] [options]',
61
68
  options: [
62
69
  { flag: '--yes', desc: 'Accept all defaults (non-interactive)' },
@@ -93,7 +100,16 @@ export const CLI_COMMANDS = [
93
100
  category: 'Core',
94
101
  core: true,
95
102
  description: 'View and process the active profile\'s intake queue (queue label varies by profile)',
96
- usage: 'construct intake list|show|done|skip',
103
+ usage: 'construct intake list|show|done|skip|reopen|integrate|classify',
104
+ subcommands: [
105
+ { name: 'list', desc: 'List pending packets' },
106
+ { name: 'show <id>', desc: 'Show one packet (triage, related docs, excerpt, tag suggestions)' },
107
+ { name: 'done <id> [--output=<path>]', desc: 'Mark processed; optionally stamp the produced artifact' },
108
+ { name: 'skip <id> [--reason=…]', desc: 'Drop without action; preserves audit trail' },
109
+ { name: 'reopen <id>', desc: 'Move a processed or skipped packet back to pending' },
110
+ { name: 'integrate <id> <github|jira|confluence> [--publish-issues]', desc: 'Create an external ticket from a packet (--publish-issues unlocks the demo-source gate)' },
111
+ { name: 'classify --json [--text|--file|<stdin>]', desc: 'Classify an artifact and return a role-aware plan without enqueuing (embedded contract)' },
112
+ ],
97
113
  },
98
114
  {
99
115
  name: 'recommendations',
@@ -205,17 +221,28 @@ export const CLI_COMMANDS = [
205
221
  category: 'Core',
206
222
  core: true,
207
223
  description: 'Check installation health',
208
- usage: 'construct doctor',
224
+ usage: 'construct doctor [<status|logs|tick|report|consistency|watch|stop|credentials>] [--fix-legacy-agents]',
225
+ subcommands: [
226
+ { name: 'status', desc: 'Doctor daemon status' },
227
+ { name: 'logs', desc: 'Tail doctor daemon logs' },
228
+ { name: 'tick', desc: 'Run one doctor daemon check cycle now' },
229
+ { name: 'report', desc: 'Print the latest health report' },
230
+ { name: 'consistency', desc: 'Run cross-surface consistency checks' },
231
+ { name: 'watch', desc: 'Start the doctor daemon (continuous checks)' },
232
+ { name: 'stop', desc: 'Stop the doctor daemon' },
233
+ { name: 'credentials', desc: 'Diagnose provider credential resolution' },
234
+ ],
235
+ options: [
236
+ { flag: '--fix-legacy-agents', desc: 'Sweep legacy cx-*.md agents at user scope and re-sync' },
237
+ ],
209
238
  },
210
-
211
- // ── Work (project workflows) ──────────────────────────────────────────
212
239
  {
213
240
  name: 'distill',
214
241
  emoji: '🔬',
215
242
  category: 'Work',
216
243
  core: false,
217
244
  description: 'Distill documents with query-focused chunking',
218
- usage: 'construct distill <dir> [--format=summary|decisions|full]',
245
+ usage: 'construct distill <file>',
219
246
  },
220
247
  {
221
248
  name: 'ingest',
@@ -223,7 +250,7 @@ export const CLI_COMMANDS = [
223
250
  category: 'Work',
224
251
  core: false,
225
252
  description: 'Convert documents to indexed markdown',
226
- usage: 'construct ingest <file> [--sync]',
253
+ usage: 'construct ingest <file> [--strict] [--legacy-extractor]',
227
254
  },
228
255
  {
229
256
  name: 'infer',
@@ -231,7 +258,7 @@ export const CLI_COMMANDS = [
231
258
  category: 'Work',
232
259
  core: false,
233
260
  description: 'Infer schema from documents',
234
- usage: 'construct infer <file> [--unified]',
261
+ usage: 'construct infer <file>',
235
262
  },
236
263
  {
237
264
  name: 'search',
@@ -247,7 +274,7 @@ export const CLI_COMMANDS = [
247
274
  category: 'Work',
248
275
  core: false,
249
276
  description: 'Manage storage backend',
250
- usage: 'construct storage sync|status|reset',
277
+ usage: 'construct storage <status|reset>',
251
278
  },
252
279
  {
253
280
  name: 'headhunt',
@@ -255,7 +282,7 @@ export const CLI_COMMANDS = [
255
282
  category: 'Work',
256
283
  core: false,
257
284
  description: 'Create domain expertise overlays',
258
- usage: 'construct headhunt <domain>',
285
+ usage: 'construct headhunt <create|list>',
259
286
  },
260
287
  {
261
288
  name: 'graph',
@@ -263,229 +290,202 @@ export const CLI_COMMANDS = [
263
290
  category: 'Work',
264
291
  core: false,
265
292
  description: 'Task graph management',
266
- usage: 'construct graph list|show|from-intake',
293
+ usage: 'construct graph <list|show|from-intake|recommend>',
294
+ subcommands: [
295
+ { name: 'recommend --json [--text|--file|<stdin>]', desc: 'Return a role-aware plan for an artifact without enqueuing (embedded contract; alias of intake classify)' },
296
+ ],
267
297
  },
268
-
269
- // ── Models & Integrations ─────────────────────────────────────────────
270
298
  {
271
299
  name: 'models',
272
300
  emoji: '🧠',
273
301
  category: 'Models & Integrations',
302
+ core: false,
274
303
  description: 'Show or update model tier assignments',
275
- usage: 'construct models [--poll|--apply|--reset|--tier=TIER|--set=MODEL|--prefer-free|--prefer-free-same-family]',
276
- options: [
277
- { flag: '--poll', desc: 'Query OpenRouter for currently free models' },
278
- { flag: '--apply', desc: 'Auto-apply best free models and sync' },
279
- { flag: '--reset', desc: 'Remove model overrides, restore defaults' },
280
- { flag: '--tier=TIER', desc: 'Target tier: reasoning | standard | fast' },
281
- { flag: '--set=MODEL_ID',desc: 'Set specific model for the tier' },
282
- { flag: '--prefer-free', desc: 'When inferring sibling tiers, prefer free models where possible' },
283
- { flag: '--prefer-free-same-family', desc: 'Prefer free siblings only when they stay in the same provider family' },
304
+ usage: 'construct models <list|set|free|reset|usage|cost|resolve>',
305
+ subcommands: [
306
+ { name: 'list', desc: 'Show current tier assignments' },
307
+ { name: 'set --tier=<reasoning|standard|fast> --model=<model>', desc: 'Set a model for a tier' },
308
+ { name: 'free', desc: 'List available free models' },
309
+ { name: 'reset', desc: 'Reset all tier assignments' },
310
+ { name: 'usage', desc: 'Show token usage per tier' },
311
+ { name: 'cost', desc: 'Show cost breakdown' },
312
+ { name: 'resolve --json', desc: 'Resolve the model for an embedded workflow given host context' },
313
+ ],
314
+ },
315
+ {
316
+ name: 'capability',
317
+ emoji: '🧩',
318
+ category: 'Models & Integrations',
319
+ core: false,
320
+ description: 'Describe what this Construct install can do (embedded contract; read-only, secret-free)',
321
+ usage: 'construct capability describe --json',
322
+ subcommands: [
323
+ { name: 'describe --json', desc: 'Emit versions, interfaces, roles, skills, workflows, schemas, models, policies, telemetry, plugins' },
284
324
  ],
285
325
  },
286
326
  {
287
327
  name: 'mcp',
288
328
  emoji: '🔌',
289
329
  category: 'Models & Integrations',
330
+ core: false,
290
331
  description: 'Manage MCP integrations',
291
- usage: 'construct mcp <list|add|remove|info> [name]',
332
+ usage: 'construct mcp <list|add|remove|info>',
292
333
  subcommands: [
293
- { name: 'list', desc: 'Show all MCP integrations and status' },
294
- { name: 'add', desc: 'Add an MCP integration interactively' },
295
- { name: 'remove', desc: 'Remove an MCP integration' },
296
- { name: 'info', desc: 'Show setup details for an integration' },
334
+ { name: 'list', desc: 'List configured MCP integrations' },
335
+ { name: 'add <id>', desc: 'Add an MCP integration by id' },
336
+ { name: 'remove <id>', desc: 'Remove an MCP integration' },
337
+ { name: 'info <id>', desc: 'Show details for one MCP integration' },
297
338
  ],
298
339
  },
299
340
  {
300
341
  name: 'plugin',
301
342
  emoji: '🧩',
302
343
  category: 'Models & Integrations',
344
+ core: false,
303
345
  description: 'Manage external Construct plugin manifests',
304
- usage: 'construct plugin <list|info|validate|init> [name]',
346
+ usage: 'construct plugin <list|info|init|validate|engine>',
305
347
  subcommands: [
306
- { name: 'list', desc: 'Show loaded plugins and manifest sources' },
307
- { name: 'info', desc: 'Show details for a plugin' },
308
- { name: 'validate', desc: 'Validate all discovered plugin manifests' },
309
- { name: 'init', desc: 'Create a starter plugin manifest in .cx/plugins/' },
348
+ { name: 'list', desc: 'List discovered plugin manifests' },
349
+ { name: 'info <id>', desc: 'Show details for one plugin' },
350
+ { name: 'init', desc: 'Scaffold a new plugin manifest' },
351
+ { name: 'validate', desc: 'Validate a plugin manifest against the schema' },
352
+ { name: 'engine', desc: 'Plugin engine operations' },
310
353
  ],
311
354
  },
312
355
  {
313
356
  name: 'hosts',
314
357
  emoji: '🖥️',
315
358
  category: 'Models & Integrations',
359
+ core: false,
316
360
  description: 'Show host support for Construct orchestration',
317
- usage: 'construct hosts',
361
+ usage: 'construct hosts [--json]',
318
362
  },
319
363
  {
320
364
  name: 'claude:allow',
321
365
  emoji: '🔓',
322
366
  category: 'Models & Integrations',
367
+ core: false,
323
368
  description: 'Manage Claude Code `permissions.allow` from the outside (auto-classifier blocks the agent from editing it)',
324
- usage: 'construct claude:allow <list|add|remove|check> [pattern...] [--apply]',
325
- subcommands: [
326
- { name: 'list', desc: 'Print every allowlist entry' },
327
- { name: 'add', desc: 'Add one or more patterns (idempotent)' },
328
- { name: 'remove', desc: 'Remove patterns' },
329
- { name: 'check', desc: 'Detect branch-prefix gaps; `--apply` writes the suggestions' },
330
- ],
369
+ usage: 'construct claude:allow <check|apply|add|remove>',
331
370
  },
332
-
333
- // ── Observability ─────────────────────────────────────────────────────
334
371
  {
335
372
  name: 'review',
336
373
  emoji: '📈',
337
374
  category: 'Observability',
375
+ core: false,
338
376
  description: 'Generate agent performance review from Langfuse trace backend',
339
- usage: 'construct review [--days=N] [--agent=NAME] [--schedule]',
340
- options: [
341
- { flag: '--days=N', desc: 'Review window in days (default: 30)' },
342
- { flag: '--agent=NAME', desc: 'Filter to a specific agent' },
343
- { flag: '--out=PATH', desc: 'Output directory' },
344
- { flag: '--json-only', desc: 'Write raw JSON only, skip markdown report' },
345
- { flag: '--schedule', desc: 'Schedule automatic weekly reviews' },
346
- { flag: '--cadence=CRON',desc: 'Cron expression for --schedule (default: Monday 9am)' },
347
- ],
377
+ usage: 'construct review [--agent=<id>] [--days=N]',
348
378
  },
349
379
  {
350
380
  name: 'optimize',
351
381
  emoji: '⚙️',
352
382
  category: 'Observability',
383
+ core: false,
353
384
  description: 'Prompt optimization using Langfuse trace quality scores',
354
- usage: 'construct optimize <agent> [--dry-run] [--list]',
355
- options: [
356
- { flag: '--dry-run', desc: 'Preview changes without applying' },
357
- { flag: '--list', desc: 'Show all agents with quality scores' },
358
- { flag: '--threshold=N', desc: 'Quality threshold to trigger optimization (default: 0.7)' },
359
- { flag: '--days=N', desc: 'Trace window in days (default: 7)' },
360
- { flag: '--min-traces=N', desc: 'Minimum traces required (default: 20)' },
361
- ],
385
+ usage: 'construct optimize <agent>',
362
386
  },
363
387
  {
364
388
  name: 'telemetry-backfill',
365
389
  emoji: '🩹',
366
390
  category: 'Observability',
391
+ core: false,
367
392
  description: 'Backfill sparse traces with observations (trace backend)',
368
- usage: 'construct telemetry-backfill [--limit=N]',
369
- options: [
370
- { flag: '--limit=N', desc: 'Maximum sparse traces to backfill (default: 10)' },
371
- { flag: '--best-effort', desc: 'Skip failures instead of exiting non-zero' },
372
- ],
393
+ usage: 'construct telemetry-backfill',
373
394
  },
374
395
  {
375
396
  name: 'eval-datasets',
376
397
  emoji: '📊',
377
398
  category: 'Observability',
399
+ core: false,
378
400
  description: 'Sync scored Langfuse traces into eval datasets for prompt regression testing',
379
- usage: 'construct eval-datasets [--limit=N]',
380
- options: [
381
- { flag: '--limit=N', desc: 'Maximum scored traces to sync (default: 100)' },
382
- ],
401
+ usage: 'construct eval-datasets',
383
402
  },
384
403
  {
385
404
  name: 'llm-judge',
386
405
  emoji: '⚖️',
387
406
  category: 'Observability',
407
+ core: false,
388
408
  description: 'Run LLM-as-a-judge evaluations on unscored traces for continuous quality feedback',
389
- usage: 'construct llm-judge [--limit=N] [--model=NAME]',
390
- options: [
391
- { flag: '--limit=N', desc: 'Maximum traces to evaluate (default: 10)' },
392
- { flag: '--model=NAME', desc: 'LLM model to use for evaluation (default: claude-3-5-sonnet-20241022)' },
393
- ],
409
+ usage: 'construct llm-judge',
394
410
  },
395
411
  {
396
412
  name: 'efficiency',
397
413
  emoji: '🧮',
398
414
  category: 'Observability',
415
+ core: false,
399
416
  description: 'Show read efficiency, repeated files, and context-budget guidance',
400
417
  usage: 'construct efficiency [--json]',
401
- options: [
402
- { flag: '--json', desc: 'Output raw JSON' },
403
- ],
404
418
  },
405
419
  {
406
420
  name: 'evals',
407
421
  emoji: '🧪',
408
422
  category: 'Observability',
423
+ core: false,
409
424
  description: 'Show evaluator catalog for prompt and agent experiments',
410
- usage: 'construct evals [--json]',
411
- options: [
412
- { flag: '--json', desc: 'Output raw JSON' },
413
- ],
425
+ usage: 'construct evals <list|run>',
414
426
  },
415
427
  {
416
428
  name: 'cleanup',
417
429
  emoji: '🧹',
418
430
  category: 'Diagnostics',
431
+ core: false,
419
432
  description: 'Release dev-agent memory pressure by cleaning stale helper and bridge processes',
420
- usage: 'construct cleanup [--pressure-release] [--quiet]',
433
+ usage: 'construct cleanup [--dry-run] [--quiet] [--pressure-release] [--pressure-only] [--disk-only]',
421
434
  options: [
422
- { flag: '--pressure-release', desc: 'Also terminate stale cass index processes when swap is above threshold' },
423
- { flag: '--quiet', desc: 'Suppress per-process output and only act on the current policy' },
435
+ { flag: '--dry-run', desc: 'Show what would be cleaned without changing anything' },
436
+ { flag: '--quiet', desc: 'Minimal output' },
437
+ { flag: '--pressure-release', desc: 'Also kill stale dev-agent processes' },
438
+ { flag: '--pressure-only', desc: 'Pressure release only — skip disk cleanup' },
439
+ { flag: '--disk-only', desc: 'Disk cleanup only — skip pressure release' },
424
440
  ],
425
441
  },
426
-
427
- // ── Teams & Audit ────────────────────────────────────────────────────
428
442
  {
429
443
  name: 'team',
430
444
  emoji: '👥',
431
445
  category: 'Work',
446
+ core: false,
432
447
  description: 'Team review and template listing',
433
- usage: 'construct team <review|templates>',
434
- subcommands: [
435
- { name: 'review', desc: 'Run telemetry-backed team performance review' },
436
- { name: 'templates', desc: 'List available team templates from specialists/teams.json' },
437
- ],
448
+ usage: 'construct team <list|review>',
438
449
  },
439
450
  {
440
451
  name: 'audit',
441
452
  emoji: '🔍',
442
453
  category: 'Diagnostics',
454
+ core: false,
443
455
  description: 'Audit Construct internals and review the mutation trail',
444
- usage: 'construct audit <skills|trail>',
445
- subcommands: [
446
- { name: 'skills', desc: 'Audit skill files for stub headers, broken references, and missing content' },
447
- { name: 'trail', desc: 'Show the append-only audit trail of every mutation (agent, task, file, hash). Supports --verify, --agent, --tool, --since, --json.' },
448
- ],
456
+ usage: 'construct audit <events|trail>',
449
457
  },
450
458
  {
451
459
  name: 'doc',
452
460
  emoji: '🔏',
453
461
  category: 'Diagnostics',
462
+ core: false,
454
463
  description: 'Verify or inspect auditability stamps on Construct-generated markdown files',
455
- usage: 'construct doc <verify|install-hooks> [path] [--json]',
456
- subcommands: [
457
- { name: 'verify', desc: 'Check body_hash stamps on one file or all .md files under a path. Exits non-zero if any fail.' },
458
- { name: 'install-hooks', desc: 'Install the prepare-commit-msg git hook into .git/hooks/ for AI provenance trailers.' },
459
- ],
464
+ usage: 'construct doc <verify|inspect>',
465
+ },
466
+ {
467
+ name: 'bootstrap',
468
+ emoji: '🌱',
469
+ category: 'Work',
470
+ core: false,
471
+ description: 'Import seed observation corpus into local memory store for cold-start acceleration',
472
+ usage: 'construct bootstrap',
473
+ },
474
+ {
475
+ name: 'reflect',
476
+ emoji: '🪞',
477
+ category: 'Work',
478
+ core: false,
479
+ description: 'Capture improvement feedback from chat session and update Construct core',
480
+ usage: 'construct reflect',
460
481
  },
461
- {
462
- name: 'bootstrap',
463
- emoji: '🌱',
464
- category: 'Work',
465
- description: 'Import seed observation corpus into local memory store for cold-start acceleration',
466
- usage: 'construct bootstrap [--verbose]',
467
- options: [
468
- { flag: '--verbose', desc: 'Print each observation imported or skipped' },
469
- ],
470
- },
471
- {
472
- name: 'reflect',
473
- emoji: '🪞',
474
- category: 'Work',
475
- description: 'Capture improvement feedback from chat session and update Construct core',
476
- usage: 'construct reflect [--target=<internal|how-tos|decisions>] [--summary=<text>]',
477
- options: [
478
- { flag: '--target=<internal|how-tos|decisions>', desc: 'Knowledge subdir to store feedback (default: internal)' },
479
- { flag: '--summary=<text>', desc: 'Brief summary of the improvement feedback' },
480
- ],
481
- },
482
482
  {
483
483
  name: 'memory',
484
484
  emoji: '💡',
485
485
  category: 'Work',
486
486
  core: false,
487
487
  description: 'Inspect memory layer',
488
- usage: 'construct memory stats|consolidate',
488
+ usage: 'construct memory <status|search>',
489
489
  },
490
490
  {
491
491
  name: 'drop',
@@ -493,7 +493,7 @@ export const CLI_COMMANDS = [
493
493
  category: 'Work',
494
494
  core: false,
495
495
  description: 'Ingest file from Downloads/Desktop',
496
- usage: 'construct drop [--list]',
496
+ usage: 'construct drop <file>',
497
497
  },
498
498
  {
499
499
  name: 'wireframe',
@@ -501,7 +501,7 @@ export const CLI_COMMANDS = [
501
501
  category: 'Work',
502
502
  core: false,
503
503
  description: 'Generate wireframes from description',
504
- usage: 'construct wireframe "<description>"',
504
+ usage: 'construct wireframe <description>',
505
505
  },
506
506
  {
507
507
  name: 'ollama',
@@ -509,17 +509,15 @@ export const CLI_COMMANDS = [
509
509
  category: 'Integrations',
510
510
  core: false,
511
511
  description: 'Manage local Ollama models',
512
- usage: 'construct ollama status|pull|test',
512
+ usage: 'construct ollama <list|pull|run>',
513
513
  },
514
-
515
- // ── Advanced (hidden by default) ──────────────────────────────────────
516
514
  {
517
515
  name: 'beads',
518
516
  emoji: '📿',
519
517
  category: 'Advanced',
520
518
  core: false,
521
519
  description: 'Task queue management',
522
- usage: 'construct beads status|cleanup',
520
+ usage: 'construct beads <list|show|create|update|close|drift|stats>',
523
521
  },
524
522
  {
525
523
  name: 'config',
@@ -527,7 +525,7 @@ export const CLI_COMMANDS = [
527
525
  category: 'Advanced',
528
526
  core: false,
529
527
  description: 'Deployment mode configuration',
530
- usage: 'construct config mode',
528
+ usage: 'construct config <get|set>',
531
529
  },
532
530
  {
533
531
  name: 'uninstall',
@@ -535,7 +533,14 @@ export const CLI_COMMANDS = [
535
533
  category: 'Advanced',
536
534
  core: false,
537
535
  description: 'Remove Construct state',
538
- usage: 'construct uninstall',
536
+ usage: 'construct uninstall [--dry-run] [--yes] [--all] [--keep-state] [--scope=project|machine|all]',
537
+ options: [
538
+ { flag: '--dry-run', desc: 'Print the plan and exit; change nothing' },
539
+ { flag: '--yes', desc: 'Remove auto-risk (✓) categories without prompting' },
540
+ { flag: '--all', desc: 'Combined with --yes: also remove ask-risk (◐) categories (project data, machine config)' },
541
+ { flag: '--keep-state', desc: 'Only remove the launcher + adapters; preserve .cx/, ~/.construct, Postgres' },
542
+ { flag: '--scope=<...>', desc: 'Limit to project | machine | all (default: all)' },
543
+ ],
539
544
  },
540
545
  {
541
546
  name: 'update',
@@ -559,7 +564,7 @@ export const CLI_COMMANDS = [
559
564
  category: 'Advanced',
560
565
  core: false,
561
566
  description: 'Shell completion scripts',
562
- usage: 'construct completions',
567
+ usage: 'construct completions <bash|zsh|install>',
563
568
  },
564
569
  {
565
570
  name: 'list',
@@ -575,7 +580,7 @@ export const CLI_COMMANDS = [
575
580
  category: 'Advanced',
576
581
  core: false,
577
582
  description: 'Role framework management',
578
- usage: 'construct role list|status',
583
+ usage: 'construct role <list|set|latest>',
579
584
  },
580
585
  {
581
586
  name: 'embed',
@@ -719,7 +724,10 @@ export const CLI_COMMANDS = [
719
724
  category: 'Work',
720
725
  core: false,
721
726
  description: 'Instantiate workflow templates (PRD-to-review chains, onboarding, handoffs)',
722
- usage: 'construct workflow <list|show|new>',
727
+ usage: 'construct workflow <list|show|new|invoke>',
728
+ subcommands: [
729
+ { name: 'invoke --json --workflow-type <t> [--text|--file|<stdin>]', desc: 'Invoke a workflow (roles/skills) non-interactively with approval gating and provenance (embedded contract)' },
730
+ ],
723
731
  },
724
732
  {
725
733
  name: 'telemetry',
@@ -729,18 +737,143 @@ export const CLI_COMMANDS = [
729
737
  description: 'Query telemetry traces and latency data',
730
738
  usage: 'construct telemetry query <latency|top-slow|errors|trace>',
731
739
  },
740
+ {
741
+ name: 'ask',
742
+ emoji: '❓',
743
+ category: 'Work',
744
+ core: false,
745
+ description: 'One-shot ask against the active knowledge index',
746
+ usage: 'construct ask <query>',
747
+ },
748
+ {
749
+ name: 'handoffs',
750
+ emoji: '📦',
751
+ category: 'Work',
752
+ core: false,
753
+ description: 'List and inspect session handoff files in .cx/handoffs/',
754
+ usage: 'construct handoffs <list|show>',
755
+ },
756
+ {
757
+ name: 'feedback:record',
758
+ emoji: '📝',
759
+ category: 'Observability',
760
+ core: false,
761
+ description: 'Record an outcome rating for a recent specialist invocation',
762
+ usage: 'construct feedback:record <id> --score=<0-1> [--note="..."]',
763
+ },
764
+ {
765
+ name: 'feedback:history',
766
+ emoji: '📜',
767
+ category: 'Observability',
768
+ core: false,
769
+ description: 'Show recorded outcome ratings',
770
+ usage: 'construct feedback:history [--days=N]',
771
+ },
772
+ {
773
+ name: 'roles:list',
774
+ emoji: '🎭',
775
+ category: 'Advanced',
776
+ core: false,
777
+ description: 'List installed role contracts',
778
+ usage: 'construct roles:list',
779
+ },
780
+ {
781
+ name: 'roles:set',
782
+ emoji: '🎭',
783
+ category: 'Advanced',
784
+ core: false,
785
+ description: 'Activate a role contract',
786
+ usage: 'construct roles:set <role>',
787
+ },
788
+ {
789
+ name: 'docs:check',
790
+ emoji: '📄',
791
+ category: 'Diagnostics',
792
+ core: false,
793
+ description: 'Check for missing how-to guides (alias for `docs check`)',
794
+ usage: 'construct docs:check',
795
+ },
796
+ {
797
+ name: 'docs:verify',
798
+ emoji: '📄',
799
+ category: 'Diagnostics',
800
+ core: false,
801
+ description: 'Validate documentation quality (alias for `docs verify`)',
802
+ usage: 'construct docs:verify',
803
+ },
804
+ {
805
+ name: 'docs:update',
806
+ emoji: '📄',
807
+ category: 'Diagnostics',
808
+ core: false,
809
+ description: 'Regenerate AUTO-managed doc regions (alias for `docs update`)',
810
+ usage: 'construct docs:update',
811
+ },
812
+ {
813
+ name: 'docs:reconcile',
814
+ emoji: '📄',
815
+ category: 'Diagnostics',
816
+ core: false,
817
+ description: 'Reconcile docs against the registry',
818
+ usage: 'construct docs:reconcile',
819
+ },
820
+ {
821
+ name: 'docs:site',
822
+ emoji: '📄',
823
+ category: 'Diagnostics',
824
+ core: false,
825
+ description: 'Manage the docs static site build',
826
+ usage: 'construct docs:site <build|serve>',
827
+ },
828
+ {
829
+ name: 'beads:stats',
830
+ emoji: '📿',
831
+ category: 'Advanced',
832
+ core: false,
833
+ description: 'Show beads counters and drift summary',
834
+ usage: 'construct beads:stats',
835
+ },
836
+ {
837
+ name: 'telemetry-setup',
838
+ emoji: '🩹',
839
+ category: 'Observability',
840
+ core: false,
841
+ description: 'Configure Langfuse credentials and trace export',
842
+ usage: 'construct telemetry-setup',
843
+ },
844
+ // ── Internal — callable but not advertised in help or completions ────
845
+ { name: 'hook', category: 'Internal', core: false, internal: true, description: 'Hook dispatch — invoked by the harness, not by users', usage: 'construct hook <event>' },
846
+ { name: 'seed-traces', category: 'Internal', core: false, internal: true, description: 'Dev fixture: seed traces for testing', usage: 'construct seed-traces' },
847
+ { name: 'migrate', category: 'Internal', core: false, internal: true, description: 'Internal: run pending storage migrations', usage: 'construct migrate' },
848
+ { name: 'dashboard:sync', category: 'Internal', core: false, internal: true, description: 'Internal: refresh dashboard state from the registry', usage: 'construct dashboard:sync' },
849
+ { name: 'init:update', category: 'Internal', core: false, internal: true, description: 'Internal: re-run init scaffolding for an existing project', usage: 'construct init:update' },
850
+ { name: 'lint:agents', category: 'Internal', core: false, internal: true, description: 'Internal lint: agent definitions', usage: 'construct lint:agents' },
851
+ { name: 'lint:comments', category: 'Internal', core: false, internal: true, description: 'Internal lint: source comments', usage: 'construct lint:comments' },
852
+ { name: 'lint:contracts', category: 'Internal', core: false, internal: true, description: 'Internal lint: specialist contracts', usage: 'construct lint:contracts' },
853
+ { name: 'lint:research', category: 'Internal', core: false, internal: true, description: 'Internal lint: research artifacts', usage: 'construct lint:research' },
854
+ { name: 'lint:templates', category: 'Internal', core: false, internal: true, description: 'Internal lint: shipped templates', usage: 'construct lint:templates' },
855
+ { name: 'evaluator:rubrics', category: 'Internal', core: false, internal: true, description: 'Internal: list registered evaluator rubrics', usage: 'construct evaluator:rubrics' },
856
+ { name: 'activation:status', category: 'Internal', core: false, internal: true, description: 'Internal: agent activation telemetry', usage: 'construct activation:status' },
857
+ { name: 'prune', category: 'Internal', core: false, internal: true, description: 'Internal: prune ephemeral storage entries', usage: 'construct prune' },
858
+ { name: 'overrides', category: 'Internal', core: false, internal: true, description: 'Internal: list project overrides over the catalog', usage: 'construct overrides' },
859
+ { name: 'resources', category: 'Internal', core: false, internal: true, description: 'Internal: resource probe', usage: 'construct resources' },
732
860
  ];
733
861
 
734
862
  /** Flat list of all top-level command names (for completions). */
735
- export const COMMAND_NAMES = CLI_COMMANDS.map(c => c.name);
863
+ export const COMMAND_NAMES = CLI_COMMANDS.filter((c) => !c.internal).map((c) => c.name);
864
+
865
+ /** Every handler key (including internal) — used for catalog-parity tests. */
866
+ export const ALL_COMMAND_NAMES = CLI_COMMANDS.map((c) => c.name);
736
867
 
737
868
  /** Commands grouped by category, sorted alphabetically by name within each group. */
738
- export const CLI_COMMANDS_BY_CATEGORY = CLI_COMMANDS.reduce((acc, cmd) => {
739
- const cat = cmd.category ?? 'Other';
740
- if (!acc[cat]) acc[cat] = [];
741
- acc[cat].push(cmd);
742
- return acc;
743
- }, {});
869
+ export const CLI_COMMANDS_BY_CATEGORY = CLI_COMMANDS
870
+ .filter((c) => !c.internal)
871
+ .reduce((acc, cmd) => {
872
+ const cat = cmd.category ?? 'Other';
873
+ if (!acc[cat]) acc[cat] = [];
874
+ acc[cat].push(cmd);
875
+ return acc;
876
+ }, {});
744
877
  for (const cat of Object.keys(CLI_COMMANDS_BY_CATEGORY)) {
745
878
  CLI_COMMANDS_BY_CATEGORY[cat].sort((a, b) => a.name.localeCompare(b.name));
746
879
  }
@@ -758,13 +891,66 @@ export const CATEGORY_ORDER = [
758
891
 
759
892
  /** Check if a command should be shown by default (core: true) or hidden (core: false). */
760
893
  export function isCoreCommand(commandName) {
761
- const cmd = CLI_COMMANDS.find(c => c.name === commandName);
894
+ const cmd = CLI_COMMANDS.find((c) => c.name === commandName);
762
895
  return cmd?.core ?? false;
763
896
  }
764
897
 
898
+ /** Check if a command is internal (hidden from --help and --all). */
899
+ export function isInternalCommand(commandName) {
900
+ const cmd = CLI_COMMANDS.find((c) => c.name === commandName);
901
+ return cmd?.internal === true;
902
+ }
903
+
765
904
  /** Get commands filtered by visibility. */
766
905
  export function getCommands(options = {}) {
767
906
  const { showAll = false } = options;
768
- if (showAll) return CLI_COMMANDS;
769
- return CLI_COMMANDS.filter(cmd => cmd.core);
907
+ const visible = CLI_COMMANDS.filter((c) => !c.internal);
908
+ if (showAll) return visible;
909
+ return visible.filter((cmd) => cmd.core);
910
+ }
911
+
912
+ /** Look up a single command entry by name. */
913
+ export function getCommandSpec(name) {
914
+ return CLI_COMMANDS.find((c) => c.name === name) || null;
915
+ }
916
+
917
+ const ESC = String.fromCharCode(27);
918
+
919
+ // Render a per-command help block. Pulls usage, description, subcommands,
920
+ // and options from the CLI_COMMANDS entry so help stays consistent across
921
+ // every command. Internal commands fall back to a minimal block.
922
+
923
+ export function formatCommandHelp(name, { colors = false } = {}) {
924
+ const useColor = colors && process.stdout.isTTY && !process.env.NO_COLOR && process.env.TERM !== 'dumb';
925
+ const c = useColor
926
+ ? { bold: `${ESC}[1m`, dim: `${ESC}[2m`, reset: `${ESC}[0m` }
927
+ : { bold: '', dim: '', reset: '' };
928
+ const spec = getCommandSpec(name);
929
+ if (!spec) {
930
+ return `Unknown command: ${name}\n\nRun 'construct --help' for available commands.\n`;
931
+ }
932
+ const lines = [];
933
+ lines.push(`${c.bold}construct ${spec.name}${c.reset} — ${spec.description}`);
934
+ lines.push('');
935
+ if (spec.usage) {
936
+ lines.push(`${c.dim}Usage:${c.reset} ${spec.usage}`);
937
+ lines.push('');
938
+ }
939
+ if (spec.subcommands && spec.subcommands.length > 0) {
940
+ lines.push(`${c.bold}Subcommands${c.reset}`);
941
+ const width = Math.max(...spec.subcommands.map((s) => s.name.length));
942
+ for (const sub of spec.subcommands) {
943
+ lines.push(` ${sub.name.padEnd(width)} ${sub.desc}`);
944
+ }
945
+ lines.push('');
946
+ }
947
+ if (spec.options && spec.options.length > 0) {
948
+ lines.push(`${c.bold}Options${c.reset}`);
949
+ const width = Math.max(...spec.options.map((o) => o.flag.length));
950
+ for (const opt of spec.options) {
951
+ lines.push(` ${opt.flag.padEnd(width)} ${opt.desc}`);
952
+ }
953
+ lines.push('');
954
+ }
955
+ return lines.join('\n');
770
956
  }