@geraldmaron/construct 1.0.7 → 1.0.9

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 (147) hide show
  1. package/README.md +20 -17
  2. package/bin/construct +1199 -69
  3. package/commands/work/optimize-prompts.md +1 -1
  4. package/db/schema/007_tags.sql +30 -0
  5. package/db/schema/008_skill_usage.sql +24 -0
  6. package/db/schema/009_scheduler.sql +14 -0
  7. package/examples/internal/roles/architect/bad/clever-plan-without-contracts.md +1 -1
  8. package/examples/internal/roles/architect/golden/explicit-tradeoff-before-plan.md +1 -1
  9. package/examples/internal/roles/engineer/bad/speculative-abstraction.md +1 -1
  10. package/examples/internal/roles/engineer/golden/read-before-write.md +1 -1
  11. package/examples/internal/roles/qa/bad/coverage-theater.md +1 -1
  12. package/examples/internal/roles/qa/golden/regression-gate.md +1 -1
  13. package/examples/seed-observations/decisions.md +1 -1
  14. package/lib/audit-skills.mjs +3 -3
  15. package/lib/auto-docs.mjs +2 -2
  16. package/lib/cli-commands.mjs +276 -122
  17. package/lib/comment-lint.mjs +5 -1
  18. package/lib/completions.mjs +1 -1
  19. package/lib/config/schema.mjs +15 -1
  20. package/lib/contracts/validate.mjs +65 -17
  21. package/lib/distill.mjs +22 -4
  22. package/lib/doc-stamp.mjs +48 -0
  23. package/lib/doctor/watchers/consistency.mjs +62 -12
  24. package/lib/document-extract.mjs +221 -28
  25. package/lib/document-ingest.mjs +2 -0
  26. package/lib/embed/inbox.mjs +48 -3
  27. package/lib/embed/role-framing.mjs +3 -3
  28. package/lib/env-config.mjs +9 -3
  29. package/lib/extractors/calendar.mjs +173 -0
  30. package/lib/extractors/shared/drop-info.mjs +22 -0
  31. package/lib/extractors/transcript.mjs +0 -0
  32. package/lib/gates-audit.mjs +8 -2
  33. package/lib/git-hooks/prepare-commit-msg +1 -1
  34. package/lib/headhunt.mjs +2 -2
  35. package/lib/hooks/agent-tracker.mjs +6 -11
  36. package/lib/hooks/guard-bash.mjs +35 -14
  37. package/lib/hooks/mcp-audit.mjs +12 -0
  38. package/lib/hooks/pre-compact.mjs +92 -5
  39. package/lib/hooks/pre-push-gate.mjs +41 -8
  40. package/lib/hooks/registry-sync.mjs +2 -2
  41. package/lib/hooks/stop-notify.mjs +7 -6
  42. package/lib/host-capabilities.mjs +10 -1
  43. package/lib/hygiene/scan.mjs +141 -0
  44. package/lib/init-unified.mjs +18 -0
  45. package/lib/install/stage-project.mjs +4 -4
  46. package/lib/intake/classify.mjs +222 -55
  47. package/lib/intake/filesystem-queue.mjs +25 -5
  48. package/lib/intake/postgres-queue.mjs +45 -3
  49. package/lib/intake/prepare.mjs +3 -0
  50. package/lib/intake/quarantine.mjs +205 -0
  51. package/lib/knowledge/postgres-search.mjs +132 -0
  52. package/lib/knowledge/search.mjs +14 -4
  53. package/lib/mcp/server.mjs +9 -3
  54. package/lib/mcp/tools/skills.mjs +32 -11
  55. package/lib/mcp/tools/workflow.mjs +1 -1
  56. package/lib/migrations/index.mjs +1 -1
  57. package/lib/model-registry.mjs +1 -1
  58. package/lib/opencode-runtime-plugin.mjs +1 -1
  59. package/lib/orchestration-policy.mjs +4 -4
  60. package/lib/overrides/resolver.mjs +3 -3
  61. package/lib/parity.mjs +4 -4
  62. package/lib/policy/engine.mjs +2 -2
  63. package/lib/profiles/lifecycle.mjs +1 -1
  64. package/lib/prompt-metadata.mjs +4 -4
  65. package/lib/providers/circuit-breaker.mjs +14 -0
  66. package/lib/providers/contract.mjs +67 -3
  67. package/lib/providers/creds.mjs +219 -0
  68. package/lib/providers/scaffold.mjs +107 -0
  69. package/lib/role-preload.mjs +5 -0
  70. package/lib/roles/catalog.mjs +1 -1
  71. package/lib/roles/manifest.mjs +2 -2
  72. package/lib/scheduler/index.mjs +112 -0
  73. package/lib/scheduler/solo.mjs +183 -0
  74. package/lib/server/index.mjs +7 -1
  75. package/lib/server/insights.mjs +14 -12
  76. package/lib/server/langfuse-login.mjs +58 -0
  77. package/lib/server/static/assets/index-ab25c707.js +1 -1
  78. package/lib/{agent-contracts-enforce.mjs → specialist-contracts-enforce.mjs} +4 -4
  79. package/lib/{agent-contracts.mjs → specialist-contracts.mjs} +9 -8
  80. package/lib/{agents → specialists}/postconditions.mjs +3 -3
  81. package/lib/{agents → specialists}/schema.mjs +6 -6
  82. package/lib/status.mjs +13 -11
  83. package/lib/storage/backup.mjs +2 -2
  84. package/lib/tags/lifecycle.mjs +278 -0
  85. package/lib/tags/vocabulary.mjs +140 -0
  86. package/lib/telemetry/otel-tracer.mjs +184 -0
  87. package/lib/telemetry/skill-calls.mjs +73 -12
  88. package/lib/uninstall/uninstall.mjs +1 -1
  89. package/lib/update.mjs +1 -1
  90. package/lib/validator.mjs +57 -56
  91. package/lib/workflows/instantiate.mjs +320 -0
  92. package/package.json +13 -3
  93. package/personas/construct.md +2 -2
  94. package/platforms/claude/CLAUDE.md +1 -1
  95. package/rules/common/no-fabrication.md +1 -1
  96. package/scripts/{sync-agents.mjs → sync-specialists.mjs} +130 -58
  97. package/skills/ai/prompt-optimizer.md +3 -3
  98. package/skills/exploration/dependency-graph-reading.md +98 -0
  99. package/skills/exploration/tracer-bullet-method.md +71 -0
  100. package/skills/exploration/unknown-codebase-onboarding.md +91 -0
  101. package/skills/operating/change-management.md +91 -0
  102. package/skills/operating/incident-response.md +75 -0
  103. package/skills/operating/oncall-rotation.md +95 -0
  104. package/skills/operating/orchestration-reference.md +2 -2
  105. package/skills/strategy/competitive-landscape.md +75 -0
  106. package/skills/strategy/market-research-methods.md +87 -0
  107. package/skills/strategy/narrative-arc.md +77 -0
  108. package/skills/strategy/pricing-positioning.md +94 -0
  109. package/{agents → specialists}/contracts.schema.json +1 -1
  110. package/specialists/policy-inventory.json +160 -0
  111. package/{agents → specialists}/prompts/cx-accessibility.md +1 -1
  112. package/{agents → specialists}/prompts/cx-ai-engineer.md +1 -1
  113. package/{agents → specialists}/prompts/cx-architect.md +1 -1
  114. package/{agents → specialists}/prompts/cx-business-strategist.md +1 -1
  115. package/{agents → specialists}/prompts/cx-data-analyst.md +1 -1
  116. package/{agents → specialists}/prompts/cx-data-engineer.md +1 -1
  117. package/{agents → specialists}/prompts/cx-debugger.md +1 -1
  118. package/{agents → specialists}/prompts/cx-designer.md +1 -1
  119. package/{agents → specialists}/prompts/cx-devil-advocate.md +1 -1
  120. package/{agents → specialists}/prompts/cx-docs-keeper.md +2 -2
  121. package/{agents → specialists}/prompts/cx-engineer.md +2 -2
  122. package/{agents → specialists}/prompts/cx-evaluator.md +1 -1
  123. package/{agents → specialists}/prompts/cx-explorer.md +1 -1
  124. package/{agents → specialists}/prompts/cx-legal-compliance.md +1 -1
  125. package/{agents → specialists}/prompts/cx-operations.md +1 -1
  126. package/{agents → specialists}/prompts/cx-orchestrator.md +2 -2
  127. package/{agents → specialists}/prompts/cx-platform-engineer.md +1 -1
  128. package/{agents → specialists}/prompts/cx-product-manager.md +1 -1
  129. package/{agents → specialists}/prompts/cx-qa.md +1 -1
  130. package/{agents → specialists}/prompts/cx-rd-lead.md +1 -1
  131. package/{agents → specialists}/prompts/cx-release-manager.md +1 -1
  132. package/{agents → specialists}/prompts/cx-researcher.md +1 -1
  133. package/{agents → specialists}/prompts/cx-reviewer.md +2 -2
  134. package/{agents → specialists}/prompts/cx-security.md +1 -1
  135. package/{agents → specialists}/prompts/cx-sre.md +2 -2
  136. package/{agents → specialists}/prompts/cx-test-automation.md +1 -1
  137. package/{agents → specialists}/prompts/cx-trace-reviewer.md +3 -3
  138. package/{agents → specialists}/prompts/cx-ux-researcher.md +1 -1
  139. package/{agents → specialists}/registry.json +651 -423
  140. package/{agents → specialists}/role-manifests.json +8 -8
  141. package/templates/provider-scaffold/health.test.mjs +30 -0
  142. package/templates/provider-scaffold/index.mjs +48 -0
  143. package/templates/workflows/cross-team-handoff.yml +85 -0
  144. package/templates/workflows/engineering-onboarding.yml +77 -0
  145. package/templates/workflows/new-feature.yml +53 -0
  146. /package/{agents → specialists}/contracts.json +0 -0
  147. /package/{agents → specialists}/teams.json +0 -0
@@ -199,14 +199,6 @@ export const CLI_COMMANDS = [
199
199
  { name: 'update', desc: 'Regenerate AUTO-managed regions' },
200
200
  ],
201
201
  },
202
- {
203
- name: 'models',
204
- emoji: '🧠',
205
- category: 'Core',
206
- core: true,
207
- description: 'Manage AI model assignments',
208
- usage: 'construct models [--apply|--poll]',
209
- },
210
202
  {
211
203
  name: 'doctor',
212
204
  emoji: '🩺',
@@ -273,145 +265,251 @@ export const CLI_COMMANDS = [
273
265
  description: 'Task graph management',
274
266
  usage: 'construct graph list|show|from-intake',
275
267
  },
268
+
269
+ // ── Models & Integrations ─────────────────────────────────────────────
276
270
  {
277
- name: 'memory',
278
- emoji: '💡',
279
- category: 'Work',
280
- core: false,
281
- description: 'Inspect memory layer',
282
- usage: 'construct memory stats|consolidate',
283
- },
284
- {
285
- name: 'reflect',
286
- emoji: '🪞',
287
- category: 'Work',
288
- core: false,
289
- description: 'Capture improvement feedback',
290
- usage: 'construct reflect [--summary=<text>]',
291
- },
292
- {
293
- name: 'drop',
294
- emoji: '📥',
295
- category: 'Work',
296
- core: false,
297
- description: 'Ingest file from Downloads/Desktop',
298
- usage: 'construct drop [--list]',
299
- },
300
- {
301
- name: 'wireframe',
302
- emoji: '✏️',
303
- category: 'Work',
304
- core: false,
305
- description: 'Generate wireframes from description',
306
- usage: 'construct wireframe "<description>"',
307
- },
308
- {
309
- name: 'bootstrap',
310
- emoji: '🌱',
311
- category: 'Work',
312
- core: false,
313
- description: 'Import seed observations',
314
- usage: 'construct bootstrap',
315
- },
316
- {
317
- name: 'team',
318
- emoji: '👥',
319
- category: 'Work',
320
- core: false,
321
- description: 'Team review and templates',
322
- usage: 'construct team review|templates',
271
+ name: 'models',
272
+ emoji: '🧠',
273
+ category: 'Models & Integrations',
274
+ 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' },
284
+ ],
323
285
  },
324
-
325
- // ── Integrations ──────────────────────────────────────────────────────
326
286
  {
327
287
  name: 'mcp',
328
288
  emoji: '🔌',
329
- category: 'Integrations',
330
- core: false,
289
+ category: 'Models & Integrations',
331
290
  description: 'Manage MCP integrations',
332
- usage: 'construct mcp list|add|remove',
333
- },
334
- {
335
- name: 'ollama',
336
- emoji: '🦙',
337
- category: 'Integrations',
338
- core: false,
339
- description: 'Manage local Ollama models',
340
- usage: 'construct ollama status|pull|test',
291
+ usage: 'construct mcp <list|add|remove|info> [name]',
292
+ 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' },
297
+ ],
341
298
  },
342
299
  {
343
300
  name: 'plugin',
344
301
  emoji: '🧩',
345
- category: 'Integrations',
346
- core: false,
347
- description: 'Manage plugin manifests',
348
- usage: 'construct plugin list|validate',
302
+ category: 'Models & Integrations',
303
+ description: 'Manage external Construct plugin manifests',
304
+ usage: 'construct plugin <list|info|validate|init> [name]',
305
+ 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/' },
310
+ ],
349
311
  },
350
312
  {
351
313
  name: 'hosts',
352
314
  emoji: '🖥️',
353
- category: 'Integrations',
354
- core: false,
355
- description: 'Check host capabilities',
315
+ category: 'Models & Integrations',
316
+ description: 'Show host support for Construct orchestration',
356
317
  usage: 'construct hosts',
357
318
  },
358
319
  {
359
320
  name: 'claude:allow',
360
321
  emoji: '🔓',
361
- category: 'Integrations',
362
- core: false,
363
- description: 'Manage Claude Code permissions',
364
- usage: 'construct claude:allow list|add|check',
322
+ category: 'Models & Integrations',
323
+ 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
+ ],
365
331
  },
366
-
332
+
367
333
  // ── Observability ─────────────────────────────────────────────────────
368
334
  {
369
- name: 'cost',
370
- emoji: '💰',
335
+ name: 'review',
336
+ emoji: '📈',
371
337
  category: 'Observability',
372
- core: false,
373
- description: 'Token usage and cost breakdown',
374
- usage: 'construct cost [--days=N]',
338
+ 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
+ ],
375
348
  },
376
349
  {
377
- name: 'efficiency',
378
- emoji: '🧮',
350
+ name: 'optimize',
351
+ emoji: '⚙️',
379
352
  category: 'Observability',
380
- core: false,
381
- description: 'Read efficiency metrics',
382
- usage: 'construct efficiency',
353
+ 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
+ ],
383
362
  },
384
363
  {
385
- name: 'review',
386
- emoji: '📈',
364
+ name: 'telemetry-backfill',
365
+ emoji: '🩹',
387
366
  category: 'Observability',
388
- core: false,
389
- description: 'Agent performance review',
390
- usage: 'construct review [--days=N]',
367
+ 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
+ ],
391
373
  },
392
374
  {
393
- name: 'optimize',
394
- emoji: '⚙️',
375
+ name: 'eval-datasets',
376
+ emoji: '📊',
395
377
  category: 'Observability',
396
- core: false,
397
- description: 'Prompt optimization',
398
- usage: 'construct optimize <agent>',
378
+ 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
+ ],
383
+ },
384
+ {
385
+ name: 'llm-judge',
386
+ emoji: '⚖️',
387
+ category: 'Observability',
388
+ 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
+ ],
394
+ },
395
+ {
396
+ name: 'efficiency',
397
+ emoji: '🧮',
398
+ category: 'Observability',
399
+ description: 'Show read efficiency, repeated files, and context-budget guidance',
400
+ usage: 'construct efficiency [--json]',
401
+ options: [
402
+ { flag: '--json', desc: 'Output raw JSON' },
403
+ ],
399
404
  },
400
405
  {
401
406
  name: 'evals',
402
407
  emoji: '🧪',
403
408
  category: 'Observability',
409
+ description: 'Show evaluator catalog for prompt and agent experiments',
410
+ usage: 'construct evals [--json]',
411
+ options: [
412
+ { flag: '--json', desc: 'Output raw JSON' },
413
+ ],
414
+ },
415
+ {
416
+ name: 'cleanup',
417
+ emoji: '🧹',
418
+ category: 'Diagnostics',
419
+ description: 'Release dev-agent memory pressure by cleaning stale helper and bridge processes',
420
+ usage: 'construct cleanup [--pressure-release] [--quiet]',
421
+ 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' },
424
+ ],
425
+ },
426
+
427
+ // ── Teams & Audit ────────────────────────────────────────────────────
428
+ {
429
+ name: 'team',
430
+ emoji: '👥',
431
+ category: 'Work',
432
+ 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
+ ],
438
+ },
439
+ {
440
+ name: 'audit',
441
+ emoji: '🔍',
442
+ category: 'Diagnostics',
443
+ 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
+ ],
449
+ },
450
+ {
451
+ name: 'doc',
452
+ emoji: '🔏',
453
+ category: 'Diagnostics',
454
+ 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
+ ],
460
+ },
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
+ {
483
+ name: 'memory',
484
+ emoji: '💡',
485
+ category: 'Work',
404
486
  core: false,
405
- description: 'Evaluator catalog',
406
- usage: 'construct evals',
487
+ description: 'Inspect memory layer',
488
+ usage: 'construct memory stats|consolidate',
407
489
  },
408
490
  {
409
- name: 'llm-judge',
410
- emoji: '⚖️',
411
- category: 'Observability',
491
+ name: 'drop',
492
+ emoji: '📥',
493
+ category: 'Work',
494
+ core: false,
495
+ description: 'Ingest file from Downloads/Desktop',
496
+ usage: 'construct drop [--list]',
497
+ },
498
+ {
499
+ name: 'wireframe',
500
+ emoji: '✏️',
501
+ category: 'Work',
502
+ core: false,
503
+ description: 'Generate wireframes from description',
504
+ usage: 'construct wireframe "<description>"',
505
+ },
506
+ {
507
+ name: 'ollama',
508
+ emoji: '🦙',
509
+ category: 'Integrations',
412
510
  core: false,
413
- description: 'LLM-as-judge evaluations',
414
- usage: 'construct llm-judge',
511
+ description: 'Manage local Ollama models',
512
+ usage: 'construct ollama status|pull|test',
415
513
  },
416
514
 
417
515
  // ── Advanced (hidden by default) ──────────────────────────────────────
@@ -487,14 +585,6 @@ export const CLI_COMMANDS = [
487
585
  description: 'Embed mode management',
488
586
  usage: 'construct embed start|stop|status',
489
587
  },
490
- {
491
- name: 'audit',
492
- emoji: '🔍',
493
- category: 'Advanced',
494
- core: false,
495
- description: 'Audit Construct internals',
496
- usage: 'construct audit skills|trail',
497
- },
498
588
  {
499
589
  name: 'backup',
500
590
  emoji: '💾',
@@ -527,14 +617,6 @@ export const CLI_COMMANDS = [
527
617
  description: 'Show version',
528
618
  usage: 'construct version | construct --version',
529
619
  },
530
- {
531
- name: 'cleanup',
532
- emoji: '🧹',
533
- category: 'Advanced',
534
- core: false,
535
- description: 'Clean stale processes',
536
- usage: 'construct cleanup',
537
- },
538
620
  {
539
621
  name: 'skills',
540
622
  emoji: '🎯',
@@ -559,6 +641,30 @@ export const CLI_COMMANDS = [
559
641
  description: 'Audit policy gates',
560
642
  usage: 'construct gates:audit',
561
643
  },
644
+ {
645
+ name: 'policy',
646
+ emoji: '🔒',
647
+ category: 'Advanced',
648
+ core: false,
649
+ description: 'Show active policy gates with enforcement details',
650
+ usage: 'construct policy show',
651
+ options: [
652
+ { flag: '--json', desc: 'Output as JSON' },
653
+ ],
654
+ },
655
+ {
656
+ name: 'ci',
657
+ emoji: '⚙️',
658
+ category: 'Advanced',
659
+ core: false,
660
+ description: 'Local CI mirror: run CI jobs locally or view recent run status',
661
+ usage: 'construct ci <preview|status|list>',
662
+ options: [
663
+ { flag: '--job=<name>', desc: 'Run a single CI job by id or name fragment' },
664
+ { flag: '--list', desc: 'List all jobs without running them' },
665
+ { flag: '--full', desc: 'Include Docker/Trivy steps (requires Docker daemon)' },
666
+ ],
667
+ },
562
668
  {
563
669
  name: 'provider',
564
670
  emoji: '🔌',
@@ -575,6 +681,54 @@ export const CLI_COMMANDS = [
575
681
  description: 'Check auth status',
576
682
  usage: 'construct auth:status',
577
683
  },
684
+ {
685
+ name: 'tags',
686
+ emoji: '🏷',
687
+ category: 'Work',
688
+ core: false,
689
+ description: 'Manage the controlled tag vocabulary (propose, add, deprecate, audit)',
690
+ usage: 'construct tags <audit|propose|add|deprecate|archive|list|proposed>',
691
+ },
692
+ {
693
+ name: 'scheduler',
694
+ emoji: '⏰',
695
+ category: 'Advanced',
696
+ core: false,
697
+ description: 'Manage scheduled background jobs (tag-mining, doc-hygiene, skill-rollup)',
698
+ usage: 'construct scheduler <list|run|runner>',
699
+ },
700
+ {
701
+ name: 'creds',
702
+ emoji: '🔑',
703
+ category: 'Integrations',
704
+ core: false,
705
+ description: 'Manage provider credentials (set, rotate, revoke, list)',
706
+ usage: 'construct creds <list|set|rotate|revoke|test>',
707
+ },
708
+ {
709
+ name: 'providers',
710
+ emoji: '🔌',
711
+ category: 'Integrations',
712
+ core: false,
713
+ description: 'Provider status, circuit-breaker reset, and resource discovery',
714
+ usage: 'construct providers <status|discover>',
715
+ },
716
+ {
717
+ name: 'workflow',
718
+ emoji: '🔄',
719
+ category: 'Work',
720
+ core: false,
721
+ description: 'Instantiate workflow templates (PRD-to-review chains, onboarding, handoffs)',
722
+ usage: 'construct workflow <list|show|new>',
723
+ },
724
+ {
725
+ name: 'telemetry',
726
+ emoji: '📊',
727
+ category: 'Observability',
728
+ core: false,
729
+ description: 'Query telemetry traces and latency data',
730
+ usage: 'construct telemetry query <latency|top-slow|errors|trace>',
731
+ },
578
732
  ];
579
733
 
580
734
  /** Flat list of all top-level command names (for completions). */
@@ -18,7 +18,7 @@ const JS_HEADER_GLOBS = [
18
18
  /^lib\/server\//,
19
19
  /^lib\/mcp\//,
20
20
  /^lib\/metrics\//,
21
- /^sync-agents\.mjs$/,
21
+ /^sync-specialists\.mjs$/,
22
22
  /^tests\//,
23
23
  ];
24
24
 
@@ -61,6 +61,10 @@ function requiresHeader(rel) {
61
61
  if (rel.startsWith('lib/server/static/')) {
62
62
  return { required: false, type: null };
63
63
  }
64
+ // Exclude test fixture data files — these are project artifacts, not source files.
65
+ if (rel.startsWith('tests/fixtures/projects/')) {
66
+ return { required: false, type: null };
67
+ }
64
68
  // Markdown files always get markdown-style headers, even if the directory
65
69
  // glob (e.g. ^tests/) primarily targets JS sources. Without this, .md docs
66
70
  // co-located with .mjs tests were forced into /** */ format.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * completions.mjs — generates bash and zsh completion scripts for construct.
3
3
  *
4
- * Called by scripts/sync-agents.mjs after each sync.
4
+ * Called by scripts/sync-specialists.mjs after each sync.
5
5
  * Outputs to a platform-appropriate per-user completions directory.
6
6
  */
7
7
 
@@ -6,7 +6,7 @@
6
6
  * before npm install completes in some bootstrap paths.
7
7
  *
8
8
  * Schema v1 covers: alias, deployment, providers, autoEmbed, telemetry.
9
- * Tier model selection lives in `agents/registry.json` only — this config
9
+ * Tier model selection lives in `specialists/registry.json` only — this config
10
10
  * file is intentionally not a second edit surface for model assignments.
11
11
  * Later phases (6, 7b) extend it with `resources` and `costs` blocks
12
12
  * without bumping the version — additive keys are allowed.
@@ -22,6 +22,8 @@ export const DEPLOYMENT_MODES = ['solo', 'team', 'enterprise'];
22
22
  export const MCP_BROKER_VALUES = ['auto', 'on', 'off'];
23
23
  export const DEFAULT_PROFILE_ID = 'rnd';
24
24
 
25
+ export const SURFACES = ['claude', 'opencode', 'codex', 'copilot', 'vscode', 'cursor'];
26
+
25
27
  export const DEFAULT_PROJECT_CONFIG = Object.freeze({
26
28
  version: CONFIG_SCHEMA_VERSION,
27
29
  alias: 'Construct',
@@ -42,6 +44,7 @@ export const DEFAULT_PROJECT_CONFIG = Object.freeze({
42
44
  secondary: null,
43
45
  perConversationOverride: true,
44
46
  }),
47
+ hosts: Object.freeze(Object.fromEntries(SURFACES.map((s) => [s, Object.freeze({ enabled: true })]))),
45
48
  resources: Object.freeze({
46
49
  disk: Object.freeze({
47
50
  tracesMaxDays: 30,
@@ -98,6 +101,17 @@ export const FIELD_RULES = {
98
101
  },
99
102
  },
100
103
  resources: { type: 'object', required: false },
104
+ hosts: {
105
+ type: 'object',
106
+ required: false,
107
+ fields: Object.fromEntries(SURFACES.map((s) => [s, {
108
+ type: 'object',
109
+ required: false,
110
+ fields: {
111
+ enabled: { type: 'boolean', required: false },
112
+ },
113
+ }])),
114
+ },
101
115
  costs: {
102
116
  type: 'object',
103
117
  required: false,