@geraldmaron/construct 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -18
- package/bin/construct +392 -91
- package/bin/construct-postinstall.mjs +30 -2
- package/examples/distribution/README.md +42 -0
- package/examples/distribution/manifest.json +53 -0
- package/examples/distribution/sources/adr.md +84 -0
- package/examples/distribution/sources/deck-one-pager.md +65 -0
- package/examples/distribution/sources/prd-platform.md +161 -0
- package/examples/distribution/sources/research-brief.md +80 -0
- package/examples/distribution/sources/rfc-platform.md +82 -0
- package/examples/distribution/sources/runbook.md +103 -0
- package/examples/distribution/sources/strategy.md +88 -0
- package/lib/adapters-sync.mjs +67 -0
- package/lib/artifact-gate-notice.mjs +38 -0
- package/lib/artifact-manifest.mjs +112 -0
- package/lib/artifact-release-gate.mjs +171 -0
- package/lib/artifact-reviewers.mjs +68 -0
- package/lib/artifact-type-from-path.mjs +79 -0
- package/lib/audit-skills.mjs +4 -0
- package/lib/audit-specialists.mjs +285 -0
- package/lib/audit-trail.mjs +77 -10
- package/lib/auto-docs.mjs +87 -18
- package/lib/beads/drift.mjs +27 -6
- package/lib/beads-client.mjs +49 -121
- package/lib/beads-optimistic.mjs +5 -12
- package/lib/brand-fonts.mjs +93 -0
- package/lib/brand-prose.mjs +214 -0
- package/lib/brand-tokens.mjs +92 -0
- package/lib/bridges/copilot-proxy.mjs +13 -26
- package/lib/capability-ledger.mjs +156 -0
- package/lib/certification/artifact-fixtures.mjs +132 -0
- package/lib/certification/artifact-gates.mjs +63 -0
- package/lib/certification/artifact-provenance.mjs +97 -0
- package/lib/certification/canonical-scenarios.mjs +78 -0
- package/lib/certification/cli.mjs +191 -0
- package/lib/certification/dashboard-api.mjs +71 -0
- package/lib/certification/demo-parity.mjs +116 -0
- package/lib/certification/document-io-fixtures.mjs +246 -0
- package/lib/certification/document-workflow.mjs +97 -0
- package/lib/certification/eval-bridge.mjs +77 -0
- package/lib/certification/model-routing.mjs +149 -0
- package/lib/certification/prompt-budget.mjs +119 -0
- package/lib/certification/rc-gate.mjs +206 -0
- package/lib/certification/real-llm-scenarios.mjs +303 -0
- package/lib/certification/role-cards.mjs +113 -0
- package/lib/certification/role-overlays.mjs +117 -0
- package/lib/certification/run.mjs +122 -0
- package/lib/certification/runner.mjs +323 -0
- package/lib/certification/scenarios.mjs +51 -0
- package/lib/certification/skill-inventory.mjs +289 -0
- package/lib/certification/skill-scenarios.mjs +147 -0
- package/lib/certification/specialist-contracts.mjs +85 -0
- package/lib/certification/specialist-scenarios.mjs +175 -0
- package/lib/certification/stale-impact.mjs +146 -0
- package/lib/certification/status.mjs +252 -0
- package/lib/certification/store.mjs +77 -0
- package/lib/chat/cli.mjs +333 -0
- package/lib/chat/command-suggest.mjs +161 -0
- package/lib/chat/commands.mjs +215 -0
- package/lib/chat/config.mjs +142 -0
- package/lib/chat/context-compactor.mjs +250 -0
- package/lib/chat/context-continuation.mjs +253 -0
- package/lib/chat/continuation-source.mjs +58 -0
- package/lib/chat/demo-guide.mjs +61 -0
- package/lib/chat/design-tokens.mjs +91 -0
- package/lib/chat/desktop-binary.mjs +79 -0
- package/lib/chat/desktop-build.mjs +130 -0
- package/lib/chat/desktop-launcher.mjs +133 -0
- package/lib/chat/evidence.mjs +145 -0
- package/lib/chat/export.mjs +74 -0
- package/lib/chat/harness/driver.mjs +91 -0
- package/lib/chat/list-picker.mjs +112 -0
- package/lib/chat/model-picker.mjs +356 -0
- package/lib/chat/openrouter-fallback.mjs +151 -0
- package/lib/chat/permission-prompt.mjs +33 -0
- package/lib/chat/picker-catalog.mjs +45 -0
- package/lib/chat/policy-telemetry.mjs +34 -0
- package/lib/chat/present.mjs +245 -0
- package/lib/chat/session-context.mjs +39 -0
- package/lib/chat/session-persist.mjs +73 -0
- package/lib/chat/session-restore.mjs +71 -0
- package/lib/chat/session-settings.mjs +53 -0
- package/lib/chat/system-prompt.mjs +52 -0
- package/lib/chat/transparency.mjs +93 -0
- package/lib/chat/tui/color-scheme.mjs +42 -0
- package/lib/chat/tui/markdown.mjs +123 -0
- package/lib/chat/tui/presentation.mjs +100 -0
- package/lib/chat/tui/render.mjs +500 -0
- package/lib/chat/tui/turn-block.mjs +284 -0
- package/lib/chat/tui/turn-present.mjs +18 -0
- package/lib/chat/tui/turn-state.mjs +88 -0
- package/lib/chat/tui/usage.mjs +122 -0
- package/lib/chat/web-commands.mjs +146 -0
- package/lib/chat/web-launcher.mjs +63 -0
- package/lib/chat/web-picker-keys.mjs +46 -0
- package/lib/chat/web-session.mjs +159 -0
- package/lib/cli-commands.mjs +232 -11
- package/lib/comment-lint.mjs +6 -4
- package/lib/config/schema.mjs +36 -5
- package/lib/contract-schemas/decision.json +50 -0
- package/lib/contract-schemas/implementation.json +51 -0
- package/lib/contract-schemas/review-report.json +32 -0
- package/lib/contract-schemas/test-report.json +43 -0
- package/lib/contracts/construct-handoff.mjs +60 -0
- package/lib/contracts/validate.mjs +32 -3
- package/lib/contracts/violation-log.mjs +58 -5
- package/lib/dashboard-demo.mjs +71 -0
- package/lib/dashboard-static.mjs +19 -5
- package/lib/decisions/registry.mjs +5 -3
- package/lib/deck-export-pptx.mjs +1152 -0
- package/lib/demo-recording.mjs +142 -0
- package/lib/demo-script.mjs +114 -0
- package/lib/demo-surface.mjs +249 -0
- package/lib/demo.mjs +703 -0
- package/lib/diagram-export.mjs +192 -0
- package/lib/diagram.mjs +302 -0
- package/lib/docs-verify.mjs +25 -7
- package/lib/doctor/index.mjs +4 -2
- package/lib/doctor/project-adapters.mjs +44 -0
- package/lib/doctor/watchers/cx-budget.mjs +98 -0
- package/lib/doctor/watchers/graph-staleness.mjs +52 -0
- package/lib/doctor/watchers/process-pressure.mjs +4 -3
- package/lib/doctor/watchers/service-health.mjs +1 -1
- package/lib/document-export.mjs +360 -36
- package/lib/document-extract.mjs +88 -0
- package/lib/document-ingest.mjs +32 -18
- package/lib/embed/cli.mjs +2 -2
- package/lib/embed/daemon.mjs +18 -46
- package/lib/embed/semantic.mjs +5 -2
- package/lib/embed/worker.mjs +2 -2
- package/lib/embedded-contract/model-resolve.mjs +10 -9
- package/lib/env-config.mjs +26 -0
- package/lib/evals/dataset.mjs +137 -0
- package/lib/evals/gates.mjs +175 -0
- package/lib/graph/build-co-change.mjs +54 -0
- package/lib/graph/build-from-registry.mjs +136 -0
- package/lib/graph/build-import-graph.mjs +153 -0
- package/lib/graph/cli.mjs +110 -0
- package/lib/graph/impact-cli.mjs +89 -0
- package/lib/graph/impact.mjs +108 -0
- package/lib/graph/staleness.mjs +44 -0
- package/lib/graph/store.mjs +172 -0
- package/lib/handoffs/cleanup.mjs +1 -1
- package/lib/health-check.mjs +90 -76
- package/lib/hooks/artifact-release-gate.mjs +43 -0
- package/lib/hooks/audit-trail.mjs +14 -28
- package/lib/hooks/brand-prose-lint.mjs +38 -0
- package/lib/hooks/graph-impact-advisory.mjs +62 -0
- package/lib/hooks/session-optimize.mjs +84 -207
- package/lib/hooks/session-start.mjs +4 -5
- package/lib/host-disposition.mjs +7 -0
- package/lib/improvement/cli.mjs +189 -0
- package/lib/improvement/controller.mjs +137 -0
- package/lib/improvement/proposal.mjs +120 -0
- package/lib/improvement/specialist-loop.mjs +192 -0
- package/lib/improvement/store.mjs +89 -0
- package/lib/improvement/surface.mjs +219 -0
- package/lib/ingest-tooling.mjs +97 -0
- package/lib/init/doc-lanes.mjs +165 -0
- package/lib/init-docs.mjs +31 -178
- package/lib/init-unified.mjs +27 -97
- package/lib/init-update-guide.mjs +102 -0
- package/lib/init-update.mjs +32 -1
- package/lib/init.mjs +8 -0
- package/lib/install/desktop-binary-download.mjs +85 -0
- package/lib/install/legacy-global-cleanup.mjs +189 -0
- package/lib/intake/daemon.mjs +2 -0
- package/lib/intake/git-queue.mjs +9 -8
- package/lib/intake/queue.mjs +2 -1
- package/lib/intake/session-prelude.mjs +90 -1
- package/lib/libreoffice-export.mjs +97 -0
- package/lib/logging/rotate.mjs +9 -0
- package/lib/maintenance/docker-reclaim.mjs +206 -0
- package/lib/mcp/external-schema-cost.mjs +74 -0
- package/lib/mcp/server.mjs +84 -9
- package/lib/mcp/stdio-mcp-probe.mjs +188 -0
- package/lib/mcp/tool-budget.mjs +55 -4
- package/lib/mcp/tools/document.mjs +18 -4
- package/lib/mcp/tools/skills.mjs +32 -3
- package/lib/mcp/tools/workflow.mjs +13 -1
- package/lib/model-free-selector.mjs +18 -0
- package/lib/model-registry.mjs +13 -229
- package/lib/model-router.mjs +425 -93
- package/lib/models/behavior-matrix.mjs +289 -0
- package/lib/models/catalog.mjs +209 -0
- package/lib/models/execution-capability-profile.mjs +196 -0
- package/lib/models/execution-policy.mjs +307 -0
- package/lib/models/provider-poll.mjs +383 -0
- package/lib/npm-spawn-env.mjs +17 -0
- package/lib/ollama/installed-models.mjs +129 -0
- package/lib/oracle/actions.mjs +187 -0
- package/lib/oracle/artifact-gate.mjs +99 -0
- package/lib/oracle/cli.mjs +204 -0
- package/lib/oracle/daemon-entry.mjs +14 -0
- package/lib/oracle/dispatch.mjs +81 -0
- package/lib/oracle/execute.mjs +143 -0
- package/lib/oracle/gaps.mjs +76 -0
- package/lib/oracle/index.mjs +84 -0
- package/lib/oracle/issues.mjs +164 -0
- package/lib/oracle/org-graph.mjs +170 -0
- package/lib/oracle/policy.mjs +80 -0
- package/lib/oracle/read-model.mjs +398 -0
- package/lib/oracle/reconcile.mjs +191 -0
- package/lib/oracle/routing.mjs +89 -0
- package/lib/oracle/synthesize.mjs +384 -0
- package/lib/oracle/verdicts.mjs +51 -0
- package/lib/orchestration/worker.mjs +88 -27
- package/lib/orchestration-policy.mjs +50 -0
- package/lib/parity.mjs +96 -2
- package/lib/persona-sections.mjs +66 -0
- package/lib/playwright-demo.mjs +252 -0
- package/lib/project-init-shared.mjs +4 -1
- package/lib/prompt-composer.js +9 -4
- package/lib/prompt-validation-contract.mjs +24 -0
- package/lib/provider-capabilities.js +57 -11
- package/lib/providers/contract/adapters/confluence/index.mjs +181 -0
- package/lib/providers/contract/adapters/git/index.mjs +115 -0
- package/lib/providers/contract/adapters/github/index.mjs +166 -0
- package/lib/providers/contract/adapters/jira/index.mjs +187 -0
- package/lib/providers/contract/adapters/slack/index.mjs +175 -0
- package/lib/providers/contract/contract-tests.mjs +57 -0
- package/lib/providers/contract/errors.mjs +48 -0
- package/lib/providers/contract/interface.mjs +50 -0
- package/lib/providers/contract/registry.mjs +102 -0
- package/lib/providers/copilot-auth.mjs +297 -0
- package/lib/providers/credential-bootstrap.mjs +178 -0
- package/lib/providers/credential-catalog.mjs +46 -0
- package/lib/providers/credential-sources.mjs +63 -0
- package/lib/providers/creds.mjs +5 -2
- package/lib/providers/op-run.mjs +59 -0
- package/lib/providers/secret-resolver.mjs +159 -0
- package/lib/publish-template.mjs +163 -0
- package/lib/publish-tooling.mjs +119 -0
- package/lib/publish.mjs +305 -0
- package/lib/registry/cli.mjs +82 -0
- package/lib/registry/consolidation.mjs +147 -0
- package/lib/registry/generate-docs.mjs +75 -0
- package/lib/registry/skill-verification.mjs +57 -0
- package/lib/registry/surface-map.mjs +76 -0
- package/lib/registry/validate.mjs +135 -0
- package/lib/resources/budget.mjs +82 -0
- package/lib/resources/process-budget.mjs +45 -0
- package/lib/rules-delivery.mjs +9 -2
- package/lib/rules-read.mjs +26 -0
- package/lib/runtime-env.mjs +23 -0
- package/lib/runtime-pressure.mjs +51 -7
- package/lib/schema-infer.mjs +13 -2
- package/lib/server/chat-loop.mjs +622 -0
- package/lib/server/demo-preview.mjs +63 -0
- package/lib/server/index.mjs +229 -8
- package/lib/server/langfuse-login.mjs +3 -3
- package/lib/service-manager.mjs +61 -9
- package/lib/session-store.mjs +1 -1
- package/lib/setup.mjs +102 -2
- package/lib/specialists/prompt-schema.mjs +19 -10
- package/lib/specialists/roster.mjs +43 -0
- package/lib/specialists/scaffold.mjs +56 -0
- package/lib/storage/backend.mjs +6 -6
- package/lib/storage/embeddings-local.mjs +6 -3
- package/lib/storage/file-lock.mjs +18 -11
- package/lib/storage/hybrid-query.mjs +7 -4
- package/lib/storage/state-source.mjs +5 -5
- package/lib/storage/sync.mjs +2 -3
- package/lib/telemetry/rule-calls.mjs +52 -0
- package/lib/template-registry.mjs +2 -2
- package/lib/templates/visual-requirements.mjs +27 -51
- package/lib/test-corpus-inventory.mjs +313 -0
- package/lib/uninstall/uninstall.mjs +19 -7
- package/lib/update.mjs +12 -0
- package/lib/upgrade.mjs +14 -0
- package/lib/wireframe.mjs +20 -14
- package/lib/worker/run.mjs +17 -4
- package/lib/worker/trace.mjs +11 -3
- package/package.json +29 -13
- package/personas/construct.md +13 -13
- package/platforms/claude/settings.template.json +36 -0
- package/rules/common/patterns.md +1 -1
- package/rules/common/release-gates.md +4 -3
- package/scripts/sync-specialists.mjs +187 -60
- package/skills/devops/data-engineering.md +1 -1
- package/skills/docs/adr-workflow.md +1 -0
- package/skills/docs/backlog-proposal-workflow.md +1 -0
- package/skills/docs/codebase-research-workflow.md +40 -0
- package/skills/docs/customer-profile-workflow.md +1 -0
- package/skills/docs/document-ingest-workflow.md +1 -0
- package/skills/docs/evidence-ingest-workflow.md +1 -0
- package/skills/docs/init-docs.md +2 -2
- package/skills/docs/init-project.md +8 -3
- package/skills/docs/prd-workflow.md +24 -1
- package/skills/docs/prfaq-workflow.md +1 -0
- package/skills/docs/product-intelligence-workflow.md +1 -0
- package/skills/docs/product-signal-workflow.md +1 -0
- package/skills/docs/research-workflow.md +54 -37
- package/skills/docs/runbook-workflow.md +1 -0
- package/skills/docs/strategy-workflow.md +1 -0
- package/skills/docs/user-research-workflow.md +40 -0
- package/skills/operating/orchestration-reference.md +1 -1
- package/skills/roles/architect.md +5 -0
- package/skills/roles/operator.docs.md +4 -0
- package/skills/routing.md +4 -2
- package/specialists/artifact-manifest.json +480 -0
- package/specialists/artifact-manifest.schema.json +53 -0
- package/specialists/audit-enrichments.json +454 -0
- package/specialists/contracts.json +37 -25
- package/specialists/prompts/_shared/validation-contract.md +26 -0
- package/specialists/prompts/cx-accessibility.md +21 -2
- package/specialists/prompts/cx-ai-engineer.md +24 -1
- package/specialists/prompts/cx-architect.md +4 -1
- package/specialists/prompts/cx-business-strategist.md +23 -2
- package/specialists/prompts/cx-data-analyst.md +22 -1
- package/specialists/prompts/cx-data-engineer.md +23 -2
- package/specialists/prompts/cx-debugger.md +21 -2
- package/specialists/prompts/cx-designer.md +26 -3
- package/specialists/prompts/cx-devil-advocate.md +19 -2
- package/specialists/prompts/cx-docs-keeper.md +28 -1
- package/specialists/prompts/cx-engineer.md +22 -1
- package/specialists/prompts/cx-evaluator.md +18 -1
- package/specialists/prompts/cx-explorer.md +21 -2
- package/specialists/prompts/cx-legal-compliance.md +21 -2
- package/specialists/prompts/cx-operations.md +21 -2
- package/specialists/prompts/cx-oracle.md +94 -0
- package/specialists/prompts/cx-orchestrator.md +20 -1
- package/specialists/prompts/cx-platform-engineer.md +25 -2
- package/specialists/prompts/cx-product-manager.md +32 -1
- package/specialists/prompts/cx-qa.md +24 -2
- package/specialists/prompts/cx-rd-lead.md +23 -2
- package/specialists/prompts/cx-release-manager.md +23 -2
- package/specialists/prompts/cx-researcher.md +22 -2
- package/specialists/prompts/cx-reviewer.md +18 -1
- package/specialists/prompts/cx-security.md +22 -2
- package/specialists/prompts/cx-sre.md +30 -3
- package/specialists/prompts/cx-test-automation.md +7 -1
- package/specialists/prompts/cx-trace-reviewer.md +22 -3
- package/specialists/prompts/cx-ux-researcher.md +21 -2
- package/specialists/registry.json +52 -173
- package/specialists/tone-profiles.json +42 -0
- package/templates/demos/playwright/demo-recording.config.mjs +47 -0
- package/templates/demos/recordings/agentic-platforms-prd.json +19 -0
- package/templates/demos/scripts/agentic-platforms-prd.json +44 -0
- package/templates/demos/specs/_helpers/scroll-artifact.ts +89 -0
- package/templates/demos/tapes/agentic-platforms-prd.tape +49 -0
- package/templates/demos/tapes/resource-guard-rails.tape +49 -0
- package/templates/demos/vhs/construct-cockpit.json +24 -0
- package/templates/distribution/construct-brand.typ +446 -0
- package/templates/distribution/construct-decision.typ +38 -0
- package/templates/distribution/construct-deck.html +95 -0
- package/templates/distribution/construct-pdf.typ +38 -0
- package/templates/distribution/construct-prd.typ +38 -0
- package/templates/distribution/construct-research.typ +38 -0
- package/templates/distribution/construct-web.html +92 -0
- package/templates/distribution/fonts/Geist-Bold.ttf +0 -0
- package/templates/distribution/fonts/Geist-Medium.ttf +0 -0
- package/templates/distribution/fonts/Geist-Regular.ttf +0 -0
- package/templates/distribution/fonts/Geist-SemiBold.ttf +0 -0
- package/templates/distribution/fonts/GeistMono-Medium.ttf +0 -0
- package/templates/distribution/fonts/GeistMono-Regular.ttf +0 -0
- package/templates/distribution/fonts/GeistMono-SemiBold.ttf +0 -0
- package/templates/distribution/fonts/IBMPlexMono-Regular.otf +0 -0
- package/templates/distribution/fonts/JetBrainsMono-Medium.ttf +0 -0
- package/templates/distribution/fonts/JetBrainsMono-Regular.ttf +0 -0
- package/templates/distribution/fonts/JetBrainsMono-SemiBold.ttf +0 -0
- package/templates/distribution/fonts/PlusJakartaSans-Bold.ttf +0 -0
- package/templates/distribution/fonts/PlusJakartaSans-Medium.ttf +0 -0
- package/templates/distribution/fonts/PlusJakartaSans-Regular.ttf +0 -0
- package/templates/distribution/fonts/PlusJakartaSans-SemiBold.ttf +0 -0
- package/templates/distribution/fonts/README.md +36 -0
- package/templates/distribution/fonts/SpaceGrotesk-Variable.ttf +0 -0
- package/templates/distribution/fonts/handwritten/Caveat.ttf +0 -0
- package/templates/distribution/fonts/legacy/IBMPlexMono-Regular.otf +0 -0
- package/templates/distribution/fonts/legacy/Inter-Medium.otf +0 -0
- package/templates/distribution/fonts/legacy/Inter-Regular.otf +0 -0
- package/templates/distribution/fonts/legacy/Inter-SemiBold.otf +0 -0
- package/templates/distribution/fonts/legacy/InterDisplay-SemiBold.otf +0 -0
- package/templates/distribution/fonts/legacy/SourceSerif4-Regular.otf +0 -0
- package/templates/distribution/fonts/legacy/SourceSerif4-Semibold.otf +0 -0
- package/templates/distribution/icons/activity.svg +15 -0
- package/templates/distribution/icons/alert-triangle.svg +17 -0
- package/templates/distribution/icons/book-open.svg +16 -0
- package/templates/distribution/icons/bot.svg +20 -0
- package/templates/distribution/icons/brain.svg +22 -0
- package/templates/distribution/icons/circle-check.svg +16 -0
- package/templates/distribution/icons/clipboard-check.svg +17 -0
- package/templates/distribution/icons/cpu.svg +28 -0
- package/templates/distribution/icons/database.svg +17 -0
- package/templates/distribution/icons/eye.svg +16 -0
- package/templates/distribution/icons/file-text.svg +19 -0
- package/templates/distribution/icons/gauge.svg +16 -0
- package/templates/distribution/icons/git-branch.svg +17 -0
- package/templates/distribution/icons/key.svg +17 -0
- package/templates/distribution/icons/layers.svg +17 -0
- package/templates/distribution/icons/list-checks.svg +19 -0
- package/templates/distribution/icons/lock.svg +16 -0
- package/templates/distribution/icons/message-square.svg +15 -0
- package/templates/distribution/icons/network.svg +19 -0
- package/templates/distribution/icons/route.svg +17 -0
- package/templates/distribution/icons/scale.svg +19 -0
- package/templates/distribution/icons/search.svg +16 -0
- package/templates/distribution/icons/send.svg +16 -0
- package/templates/distribution/icons/server.svg +18 -0
- package/templates/distribution/icons/shield-check.svg +16 -0
- package/templates/distribution/icons/users.svg +18 -0
- package/templates/distribution/icons/webhook.svg +17 -0
- package/templates/distribution/icons/workflow.svg +17 -0
- package/templates/distribution/icons/wrench.svg +15 -0
- package/templates/distribution/run.mjs +18 -1
- package/templates/docs/adr.md +7 -0
- package/templates/docs/construct_guide.md +10 -10
- package/templates/docs/customer-profile.md +4 -0
- package/templates/docs/one-pager.md +4 -0
- package/templates/docs/postmortem.md +31 -0
- package/templates/docs/prd-platform.md +19 -0
- package/templates/docs/prd.md +15 -0
- package/templates/docs/prfaq.md +7 -0
- package/templates/docs/qa-strategy.md +103 -0
- package/templates/docs/research-brief.md +8 -0
- package/templates/docs/rfc-platform.md +12 -0
- package/templates/docs/test-plan.md +7 -0
- package/lib/ingest/chunker.mjs +0 -94
- package/lib/ingest/pipeline.mjs +0 -53
- package/lib/ingest/store.mjs +0 -82
- package/lib/mode-commands.mjs +0 -122
- package/lib/policy/unified-gates.mjs +0 -96
- package/lib/profiles/validate-custom.mjs +0 -114
- package/lib/services/telemetry-backend.mjs +0 -177
- package/lib/storage/fusion.mjs +0 -95
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* global so hooks fire in every Claude Code session.
|
|
14
14
|
*
|
|
15
15
|
* Project scope (`<project>/.claude/`, `<project>/.codex/`, `<project>/.github/`, …)
|
|
16
|
-
* - `construct`
|
|
17
|
-
* wiring.
|
|
16
|
+
* - `construct` front door only (Single Front Door), slash commands, skills, MCP
|
|
17
|
+
* wiring. Specialists dispatch internally via orchestration MCP tools.
|
|
18
18
|
*
|
|
19
19
|
* Flags:
|
|
20
20
|
* --dry-run Print a diff of what would change without writing anything.
|
|
@@ -44,9 +44,11 @@ import {
|
|
|
44
44
|
writeCodexConfig,
|
|
45
45
|
} from "../lib/codex-config.mjs";
|
|
46
46
|
import { findOpenCodeConfigPath, readOpenCodeConfig, writeOpenCodeConfig } from "../lib/opencode-config.mjs";
|
|
47
|
-
import { HEAVY_EXTERNAL_MCP_IDS, LOCAL_SURFACE_MODES, decideTrim } from "../lib/mcp/tool-budget.mjs";
|
|
47
|
+
import { HEAVY_EXTERNAL_MCP_IDS, LOCAL_SURFACE_MODES, decideTrim, isLocalModel } from "../lib/mcp/tool-budget.mjs";
|
|
48
48
|
import { emitCursorRules } from "../lib/rules-delivery.mjs";
|
|
49
|
-
import { resolvePromptContract } from "../lib/prompt-composer.js";
|
|
49
|
+
import { resolvePromptContract, readPromptBody } from "../lib/prompt-composer.js";
|
|
50
|
+
import { renderPersonaForTier } from "../lib/persona-sections.mjs";
|
|
51
|
+
import { getModelVerdict } from "../lib/ollama/capability-store.mjs";
|
|
50
52
|
import {
|
|
51
53
|
buildClaudeMcpEntry,
|
|
52
54
|
buildOpenCodeMcpEntry,
|
|
@@ -54,9 +56,10 @@ import {
|
|
|
54
56
|
} from "../lib/mcp-platform-config.mjs";
|
|
55
57
|
import { loadConstructEnv } from "../lib/env-config.mjs";
|
|
56
58
|
import { inlineRoleAntiPatterns, PROMPT_WORD_CAP } from "../lib/role-preload.mjs";
|
|
59
|
+
import { inlineValidationContract } from "../lib/prompt-validation-contract.mjs";
|
|
57
60
|
import { loadManifest } from "../lib/roles/manifest.mjs";
|
|
58
61
|
import { resolveActiveProfile } from "../lib/profiles/loader.mjs";
|
|
59
|
-
import { resolveTiersForPrimary } from "../lib/model-router.mjs";
|
|
62
|
+
import { resolveTiersForPrimary, resolveCapabilityTier, selectLocalEditorModel } from "../lib/model-router.mjs";
|
|
60
63
|
import { stampFrontmatter } from "../lib/doc-stamp.mjs";
|
|
61
64
|
import { buildSkillFrontmatter, stripLeadingFrontmatter } from "../lib/sync/skill-frontmatter.mjs";
|
|
62
65
|
|
|
@@ -152,6 +155,16 @@ if (validationErrors.length > 0) {
|
|
|
152
155
|
}
|
|
153
156
|
}
|
|
154
157
|
|
|
158
|
+
{
|
|
159
|
+
const { validatePromptFiles } = await import("../lib/specialists/prompt-schema.mjs");
|
|
160
|
+
const promptResult = validatePromptFiles({ rootDir: root, registry });
|
|
161
|
+
if (promptResult.errors.length > 0) {
|
|
162
|
+
console.error("Specialist prompt validation failed:");
|
|
163
|
+
for (const err of promptResult.errors) console.error(` - ${err}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
155
168
|
// --- Dry-run + lockfile + two-phase write infrastructure ---
|
|
156
169
|
|
|
157
170
|
const DRY_RUN = process.argv.includes("--dry-run");
|
|
@@ -516,10 +529,6 @@ function loadPersonaPrompt(persona) {
|
|
|
516
529
|
return prompt;
|
|
517
530
|
}
|
|
518
531
|
|
|
519
|
-
export function buildAgentRoster(allEntries) {
|
|
520
|
-
return allEntries.map((e) => `- ${adapterName(e)}: ${e.when_to_use || e.description}`).join("\n");
|
|
521
|
-
}
|
|
522
|
-
|
|
523
532
|
function buildModelGuidanceBlock(entry) {
|
|
524
533
|
const merged = { ...globalModelGuidance, ...(entry.modelGuidance ?? {}) };
|
|
525
534
|
const families = Object.keys(merged);
|
|
@@ -602,7 +611,83 @@ export function renderRoleFrameworkSection(entry) {
|
|
|
602
611
|
return `\n\n${lines.join("\n")}`;
|
|
603
612
|
}
|
|
604
613
|
|
|
605
|
-
|
|
614
|
+
// The native-subagent orchestration micro-prompt. A worked tool-call example lifts
|
|
615
|
+
// small local models' tool-use reliability sharply (bead construct-c16l). Shared by the
|
|
616
|
+
// full path and the capability-tiered local path so both stay in sync.
|
|
617
|
+
|
|
618
|
+
const ORCHESTRATION_MICRO_PROMPT =
|
|
619
|
+
`You are the primary orchestrator. To discover available specialist agents, you MUST call the \`orchestration_policy\` MCP tool. Do not guess agent names.\n\n` +
|
|
620
|
+
`Example — the user says "add rate limiting to the API". Your first action is a tool call, not prose:\n` +
|
|
621
|
+
` call orchestration_policy { "task": "add rate limiting to the API" }\n` +
|
|
622
|
+
`Then dispatch the specialists it returns. Always call the tool before answering.`;
|
|
623
|
+
|
|
624
|
+
// Directive for the local editor agent (construct-local). It executes bounded work on
|
|
625
|
+
// the cheap local model and hands planning/reasoning back to the construct architect —
|
|
626
|
+
// the aider architect/editor split. Kept short: a small model must actually obey it.
|
|
627
|
+
|
|
628
|
+
const LOCAL_EDITOR_DIRECTIVE =
|
|
629
|
+
`You are a focused execution agent running on a local model, dispatched by construct to do one bounded job. Do well-scoped edits for the current task and verify them; make the smallest correct change, never a broad rewrite.\n` +
|
|
630
|
+
`You do NOT plan, classify, orchestrate, or spawn other agents. For anything needing multi-file design, architecture or security judgment, dependency or contract changes, or research, STOP and return control to construct — report what needs deeper work and why, rather than attempting it yourself.`;
|
|
631
|
+
|
|
632
|
+
// Warn-and-emit capability advisory. Sizing already consumes the probe verdict
|
|
633
|
+
// (COLLAPSED → floor tier via resolveCapabilityTier); this only nudges the user toward a
|
|
634
|
+
// measured verdict and never suppresses emission. Notice-only, so it auto-suppresses in
|
|
635
|
+
// CI / test / non-TTY per the repo's wrong-context rule — no skip env var.
|
|
636
|
+
|
|
637
|
+
const localAdvisorySeen = new Set();
|
|
638
|
+
function adviseLocalModelCapability(model) {
|
|
639
|
+
if (!model || !isLocalModel(model)) return;
|
|
640
|
+
if (process.env.CI === "true" || process.env.NODE_ENV === "test" || !process.stderr.isTTY) return;
|
|
641
|
+
if (localAdvisorySeen.has(model)) return;
|
|
642
|
+
localAdvisorySeen.add(model);
|
|
643
|
+
const verdict = getModelVerdict(model)?.verdict ?? null;
|
|
644
|
+
if (verdict === "COLLAPSED") {
|
|
645
|
+
console.warn(`[sync] ${model} probed COLLAPSED — emitting at the floor tier with escalation to construct. Re-probe after a Modelfile change: construct doctor --probe-local`);
|
|
646
|
+
} else if (!verdict) {
|
|
647
|
+
console.warn(`[sync] ${model} is local with no coherence verdict — tier inferred from parameter count. For a measured tier: construct doctor --probe-local`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function enforcePromptWordCap(prompt, entry) {
|
|
652
|
+
const wordCount = prompt.split(/\s+/).filter(Boolean).length;
|
|
653
|
+
const effectiveCap = Number(entry.wordCapOverride) > 0 ? entry.wordCapOverride : PROMPT_WORD_CAP;
|
|
654
|
+
if (wordCount > effectiveCap) {
|
|
655
|
+
const msg = `[sync] ${entry.name}: prompt is ${wordCount} words (cap ${effectiveCap})`;
|
|
656
|
+
if (process.env.CONSTRUCT_SYNC_FORCE === '1' || process.argv.includes('--force')) {
|
|
657
|
+
console.warn(`${msg} — proceeding due to --force / CONSTRUCT_SYNC_FORCE=1.`);
|
|
658
|
+
} else {
|
|
659
|
+
console.error(`${msg}`);
|
|
660
|
+
console.error(
|
|
661
|
+
`[sync] Hard cap exceeded. Options:\n` +
|
|
662
|
+
` - trim the prompt body or move detail to a skill (preferred)\n` +
|
|
663
|
+
` - set "wordCapOverride": <N> on this entry in specialists/registry.json with a written reason\n` +
|
|
664
|
+
` - re-run with --force or CONSTRUCT_SYNC_FORCE=1 as a temporary escape hatch\n` +
|
|
665
|
+
`Prompt budget is a hard contract because every over-cap agent degrades every session that dispatches it.`,
|
|
666
|
+
);
|
|
667
|
+
process.exit(1);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return prompt;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function buildPrompt(entry, allEntries, platform, { capabilityTier = 'full' } = {}) {
|
|
674
|
+
const capabilities = { hasNativeSubagents: HOST_KEYS.includes(platform) ? hostHasNativeSubagents(platform) : false };
|
|
675
|
+
|
|
676
|
+
// Capability-tiered local path. A small local model follows a long multi-instruction
|
|
677
|
+
// persona poorly (instruction-following degrades before the window fills), so emit
|
|
678
|
+
// only the persona sections at/below its tier plus the orchestration micro-prompt, and
|
|
679
|
+
// skip the role footer, role-framework, operating-guidance, and model-family blocks —
|
|
680
|
+
// those add instruction load the model cannot track. Cloud models resolve to 'full'
|
|
681
|
+
// and take the unchanged path below, so cloud configs are never slimmed.
|
|
682
|
+
|
|
683
|
+
if (capabilityTier && capabilityTier !== 'full' && entry.promptFile) {
|
|
684
|
+
let slim = renderPersonaForTier(readPromptBody(entry.promptFile, root), capabilityTier);
|
|
685
|
+
if (entry.injectAgentRoster) {
|
|
686
|
+
slim = `${ORCHESTRATION_MICRO_PROMPT}\n\n${slim}`;
|
|
687
|
+
}
|
|
688
|
+
return enforcePromptWordCap(slim, entry);
|
|
689
|
+
}
|
|
690
|
+
|
|
606
691
|
let prompt = resolvePromptContract(entry, {
|
|
607
692
|
rootDir: root,
|
|
608
693
|
registry,
|
|
@@ -610,29 +695,18 @@ function buildPrompt(entry, allEntries, platform) {
|
|
|
610
695
|
}).prompt;
|
|
611
696
|
|
|
612
697
|
prompt = inlineRoleAntiPatterns(prompt, root, entry.name, console.warn, { preload: entry.preloadRoleGuidance === true });
|
|
698
|
+
prompt = inlineValidationContract(prompt, root, entry.name);
|
|
613
699
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
//
|
|
617
|
-
//
|
|
618
|
-
// injected — on a small-context local model the roster alone is ~3-4k tokens and,
|
|
619
|
-
// combined with MCP tool schemas, overruns the model's real context window and
|
|
620
|
-
// collapses output. Those hosts get a tool-bound micro-prompt instead and resolve
|
|
621
|
-
// the chain at runtime via the orchestration_policy MCP tool. Hosts without native
|
|
622
|
-
// routing (Claude Code, Codex) still need the roster to simulate handoffs in text.
|
|
700
|
+
// Platform-Native Orchestration Alignment (ADR-0002). All hosts receive the
|
|
701
|
+
// tool-bound micro-prompt when injectAgentRoster is set; the static 29-line
|
|
702
|
+
// roster was removed (construct-ymp5). Specialists resolve at runtime via
|
|
703
|
+
// orchestration_policy, which returns a lazy specialistCatalog.
|
|
623
704
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
prompt = `Available specialist agents:\n${roster}\n\n${prompt}`;
|
|
627
|
-
} else if (entry.injectAgentRoster && capabilities.hasNativeSubagents) {
|
|
628
|
-
// A worked tool-call example lifts small local models' tool-use reliability
|
|
629
|
-
// sharply (bead construct-c16l). Keep it to one compact turn so it stays within
|
|
630
|
-
// the prompt word cap; native-subagent hosts are exactly where local models run.
|
|
705
|
+
// Single Front Door: all hosts resolve specialists at runtime via
|
|
706
|
+
// orchestration_policy / orchestration_run — never inject the static roster.
|
|
631
707
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
` call orchestration_policy { "task": "add rate limiting to the API" }\n` +
|
|
635
|
-
`Then dispatch the specialists it returns. Always call the tool before answering.\n\n${prompt}`;
|
|
708
|
+
if (entry.injectAgentRoster) {
|
|
709
|
+
prompt = `${ORCHESTRATION_MICRO_PROMPT}\n\n${prompt}`;
|
|
636
710
|
}
|
|
637
711
|
|
|
638
712
|
prompt += buildRoleFooter(entry);
|
|
@@ -648,26 +722,7 @@ function buildPrompt(entry, allEntries, platform) {
|
|
|
648
722
|
|
|
649
723
|
prompt += buildModelGuidanceBlock(entry);
|
|
650
724
|
|
|
651
|
-
|
|
652
|
-
const effectiveCap = Number(entry.wordCapOverride) > 0 ? entry.wordCapOverride : PROMPT_WORD_CAP;
|
|
653
|
-
if (wordCount > effectiveCap) {
|
|
654
|
-
const msg = `[sync] ${entry.name}: prompt is ${wordCount} words (cap ${effectiveCap})`;
|
|
655
|
-
if (process.env.CONSTRUCT_SYNC_FORCE === '1' || process.argv.includes('--force')) {
|
|
656
|
-
console.warn(`${msg} — proceeding due to --force / CONSTRUCT_SYNC_FORCE=1.`);
|
|
657
|
-
} else {
|
|
658
|
-
console.error(`${msg}`);
|
|
659
|
-
console.error(
|
|
660
|
-
`[sync] Hard cap exceeded. Options:\n` +
|
|
661
|
-
` - trim the prompt body or move detail to a skill (preferred)\n` +
|
|
662
|
-
` - set "wordCapOverride": <N> on this entry in specialists/registry.json with a written reason\n` +
|
|
663
|
-
` - re-run with --force or CONSTRUCT_SYNC_FORCE=1 as a temporary escape hatch\n` +
|
|
664
|
-
`Prompt budget is a hard contract because every over-cap agent degrades every session that dispatches it.`,
|
|
665
|
-
);
|
|
666
|
-
process.exit(1);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
return prompt;
|
|
725
|
+
return enforcePromptWordCap(prompt, entry);
|
|
671
726
|
}
|
|
672
727
|
|
|
673
728
|
function escapeRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }
|
|
@@ -1382,12 +1437,10 @@ function syncCursor(targetDir = null, wants = true) {
|
|
|
1382
1437
|
|
|
1383
1438
|
if (targetDir) {
|
|
1384
1439
|
const rulesPath = path.join(targetDir, ".cursor", "rules", "construct.mdc");
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
fs.writeFileSync(rulesPath, body);
|
|
1390
|
-
}
|
|
1440
|
+
const body = `---\ndescription: Construct front-door — invoke \`construct\` for orchestration\nalwaysApply: false\n---\n\n<!-- Generated by construct sync — do not edit; re-run \`construct sync\` -->\n\nThis project uses Construct (\`@geraldmaron/construct\`) as the single agent\nentry point. Route work through the \`construct\` persona; specialists are\ninternal and dispatched via MCP \`orchestration_run\` (start \`construct dashboard\`).\n\nSkills load via MCP \`get_skill\`; see \`.claude/skills/\` for synced playbooks.\n`;
|
|
1441
|
+
if (!DRY_RUN) {
|
|
1442
|
+
mkdirp(path.dirname(rulesPath));
|
|
1443
|
+
fs.writeFileSync(rulesPath, body);
|
|
1391
1444
|
}
|
|
1392
1445
|
|
|
1393
1446
|
// Glob-scoped language rules land as managed per-rule .mdc files only when
|
|
@@ -1596,7 +1649,8 @@ function syncOpencode(entries, targetDir = null, wants = true) {
|
|
|
1596
1649
|
}
|
|
1597
1650
|
}
|
|
1598
1651
|
|
|
1599
|
-
// Heavy external MCP servers serialize ~
|
|
1652
|
+
// Heavy external MCP servers serialize a measured ~37k tokens of tool schema
|
|
1653
|
+
// into EVERY agent's request — github ~30k alone (fixtures 2026-06-22) —
|
|
1600
1654
|
// agent's request — including the built-in Build/Plan agents the per-agent
|
|
1601
1655
|
// permission prune cannot reach. OpenCode 1.15.4 has no per-session tool
|
|
1602
1656
|
// filter (chat.params carries no tool list), so disabling the whole server in
|
|
@@ -1638,6 +1692,20 @@ function syncOpencode(entries, targetDir = null, wants = true) {
|
|
|
1638
1692
|
}
|
|
1639
1693
|
|
|
1640
1694
|
// Write agents — no model/modelFallback set; agents inherit the global model.
|
|
1695
|
+
//
|
|
1696
|
+
// Capability tier for the orchestrator prompt. Keyed ONLY to an EXPLICIT local default
|
|
1697
|
+
// model — that is a clear intent signal we can size against at sync time. With no
|
|
1698
|
+
// explicit default (the orchestrator runs whatever model the user picks at runtime) or
|
|
1699
|
+
// a cloud default, resolveCapabilityTier returns 'full', so cloud configs and unknown
|
|
1700
|
+
// selections are never slimmed. Per-model slimming of a known pinned model lands on the
|
|
1701
|
+
// construct-local editor agent.
|
|
1702
|
+
|
|
1703
|
+
const orchestratorDefaultModel = config.model || config.defaultModel || "";
|
|
1704
|
+
adviseLocalModelCapability(orchestratorDefaultModel);
|
|
1705
|
+
const orchestratorTier = resolveCapabilityTier({
|
|
1706
|
+
model: orchestratorDefaultModel,
|
|
1707
|
+
verdict: orchestratorDefaultModel ? (getModelVerdict(orchestratorDefaultModel)?.verdict ?? null) : null,
|
|
1708
|
+
});
|
|
1641
1709
|
|
|
1642
1710
|
for (const entry of writeEntries) {
|
|
1643
1711
|
const name = adapterName(entry);
|
|
@@ -1647,7 +1715,9 @@ function syncOpencode(entries, targetDir = null, wants = true) {
|
|
|
1647
1715
|
? `${entry.role} — ${entry.description}`
|
|
1648
1716
|
: entry.description,
|
|
1649
1717
|
mode: entry.isOrchestrator ? "all" : "subagent",
|
|
1650
|
-
prompt: buildPrompt(entry, entries, "opencode"
|
|
1718
|
+
prompt: buildPrompt(entry, entries, "opencode", {
|
|
1719
|
+
capabilityTier: entry.isOrchestrator ? orchestratorTier : "full",
|
|
1720
|
+
}),
|
|
1651
1721
|
permission: {
|
|
1652
1722
|
...perms,
|
|
1653
1723
|
task: opencodeTaskPermissions(entry),
|
|
@@ -1655,18 +1725,75 @@ function syncOpencode(entries, targetDir = null, wants = true) {
|
|
|
1655
1725
|
};
|
|
1656
1726
|
}
|
|
1657
1727
|
|
|
1728
|
+
// Hybrid split (aider architect/editor). When the fast tier is a LOCAL model, emit a
|
|
1729
|
+
// narrow `construct-local` editor: it does bounded edits on a cheap local model and hands
|
|
1730
|
+
// planning/reasoning back to `construct` (the architect, which stays on the user's chosen
|
|
1731
|
+
// model — we never pin it). The editor's model is NOT the generic fast-tier default
|
|
1732
|
+
// (which for an Ollama family resolves to a non-code generalist); it is the best-installed
|
|
1733
|
+
// CODE model from this config's DECLARED local inventory (OpenCode only uses declared
|
|
1734
|
+
// models), excluding probe-COLLAPSED ones, with the fast tier as a last resort. Its prompt
|
|
1735
|
+
// is sized to the chosen model's capability tier. Deterministic name, so manage it
|
|
1736
|
+
// explicitly: emit when fast is local, delete otherwise, so switching to cloud cleans up.
|
|
1737
|
+
|
|
1738
|
+
const orchestratorEntry = writeEntries.find((e) => e.isOrchestrator) || registry.orchestrator;
|
|
1739
|
+
const orchestratorName = orchestratorEntry ? adapterName(orchestratorEntry) : "construct";
|
|
1740
|
+
const localEditorName = `${orchestratorName}-local`;
|
|
1741
|
+
if (orchestratorEntry?.promptFile && isLocalModel(resolvedModels.fast)) {
|
|
1742
|
+
const declaredLocal = Object.entries(config.provider || {})
|
|
1743
|
+
.flatMap(([pid, pv]) => Object.keys(pv?.models || {}).map((mk) => `${pid}/${mk}`))
|
|
1744
|
+
.filter((id) => isLocalModel(id) && getModelVerdict(id)?.verdict !== "COLLAPSED");
|
|
1745
|
+
const editorModel = selectLocalEditorModel(declaredLocal) || resolvedModels.fast;
|
|
1746
|
+
adviseLocalModelCapability(editorModel);
|
|
1747
|
+
const editorVerdict = getModelVerdict(editorModel)?.verdict ?? null;
|
|
1748
|
+
const editorTier = resolveCapabilityTier({ model: editorModel, verdict: editorVerdict });
|
|
1749
|
+
const editorBody = renderPersonaForTier(readPromptBody(orchestratorEntry.promptFile, root), editorTier);
|
|
1750
|
+
config.agent[localEditorName] = {
|
|
1751
|
+
description: "Local execution agent — bounded edits on the local model; escalates planning and reasoning to construct.",
|
|
1752
|
+
mode: "subagent",
|
|
1753
|
+
model: editorModel,
|
|
1754
|
+
prompt: `${LOCAL_EDITOR_DIRECTIVE}\n\n${editorBody}`,
|
|
1755
|
+
permission: {
|
|
1756
|
+
edit: "allow",
|
|
1757
|
+
bash: { "*": "allow", "rm -rf *": "deny", "git push *": "ask", "git push --force*": "ask", "git reset --hard *": "ask" },
|
|
1758
|
+
"mcp__construct-mcp__orchestration_policy": "deny",
|
|
1759
|
+
"mcp__construct-mcp__agent_contract": "deny",
|
|
1760
|
+
"mcp__construct-mcp__broker_check": "deny",
|
|
1761
|
+
"mcp__github__*": "deny",
|
|
1762
|
+
"mcp__context7__*": "deny",
|
|
1763
|
+
"mcp__sequential-thinking__*": "deny",
|
|
1764
|
+
"mcp__memory__*": "deny",
|
|
1765
|
+
// OpenCode 1.15.4 disables the `task` tool entirely for any restrictive task map
|
|
1766
|
+
// (verified in a sterile run). For an editor that is exactly right: it spawns no
|
|
1767
|
+
// subagents and escalates by RETURNING to the construct agent that dispatched it,
|
|
1768
|
+
// not by dispatching. Deny-all states that intent directly.
|
|
1769
|
+
task: { "*": "deny" },
|
|
1770
|
+
},
|
|
1771
|
+
};
|
|
1772
|
+
} else {
|
|
1773
|
+
delete config.agent[localEditorName];
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1658
1776
|
// Pass current Construct model tiers to OpenCode config for native routing.
|
|
1659
1777
|
config.construct = config.construct || {};
|
|
1660
1778
|
config.construct.models = { ...resolvedModels };
|
|
1661
1779
|
|
|
1662
1780
|
// Seed a cheap auxiliary model for titles and summaries when the user has not
|
|
1663
|
-
// chosen one — a cost lever only.
|
|
1664
|
-
// and is never written. Global scope only; project configs inherit it.
|
|
1781
|
+
// chosen one — a cost lever only. Global scope only; project configs inherit it.
|
|
1665
1782
|
|
|
1666
1783
|
if (!targetDir && config.small_model === undefined) {
|
|
1667
1784
|
config.small_model = resolvedModels.fast || "anthropic/claude-haiku-4-5-20251001";
|
|
1668
1785
|
}
|
|
1669
1786
|
|
|
1787
|
+
// Seed a text-capable primary model when the user has not pinned one, so chat
|
|
1788
|
+
// and routing never fall through to a host provider-default that happens to be
|
|
1789
|
+
// an image/non-text model. Seeds only when absent; an explicit user choice is
|
|
1790
|
+
// never overwritten. resolvedModels.standard is family-/registry-aware and
|
|
1791
|
+
// free-biased. Global scope only; project configs inherit it.
|
|
1792
|
+
|
|
1793
|
+
if (!targetDir && (config.model === undefined || config.model === null || config.model === "")) {
|
|
1794
|
+
config.model = resolvedModels.standard || resolvedModels.reasoning || resolvedModels.fast || "openrouter/qwen/qwen3-coder:free";
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1670
1797
|
writeOpenCodeConfig(config, configPath);
|
|
1671
1798
|
|
|
1672
1799
|
const sourcePluginsDir = path.join(root, "platforms", "opencode", "plugins");
|
|
@@ -17,7 +17,7 @@ artifactType: data-pipeline
|
|
|
17
17
|
|
|
18
18
|
### ELT over ETL
|
|
19
19
|
|
|
20
|
-
Modern data platforms (BigQuery, Snowflake, Redshift) are
|
|
20
|
+
Modern data platforms (BigQuery, Snowflake, Redshift) are capable enough to transform inside the warehouse. Prefer **ELT** (Extract → Load raw → Transform in warehouse):
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
Source → Airbyte/Fivetran → Raw tables → dbt models → Mart/API
|
|
@@ -3,6 +3,7 @@ name: docs-adr-workflow
|
|
|
3
3
|
description: "Use when: an architectural decision is made that affects the system structure, data model, API contracts, or technology choices."
|
|
4
4
|
inputs: [decision-context]
|
|
5
5
|
artifactType: adr
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# ADR Workflow
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@ name: docs-backlog-proposal-workflow
|
|
|
3
3
|
description: "Use when: product evidence should create or update Jira, Linear, GitHub Issues, or another tracker."
|
|
4
4
|
inputs: [evidence-brief, prd, signal]
|
|
5
5
|
artifactType: backlog-proposal
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Backlog Proposal Workflow
|
|
8
9
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docs-codebase-research-workflow
|
|
3
|
+
description: "Use when: cx-explorer maps the repo — entry points, dependencies, hot paths, or unfamiliar subsystems."
|
|
4
|
+
inputs: [repository-path]
|
|
5
|
+
artifactType: research-brief
|
|
6
|
+
toneDefault: pedagogical
|
|
7
|
+
toneAllowed: [pedagogical, direct]
|
|
8
|
+
verificationBar: "Every claim cites file:line or command output; no assumed architecture."
|
|
9
|
+
---
|
|
10
|
+
# Codebase Research Workflow
|
|
11
|
+
|
|
12
|
+
Use when: cx-explorer investigates **this repository** — structure, dependencies, behavior. Not for external vendor research or user interviews.
|
|
13
|
+
|
|
14
|
+
Call `get_skill("roles/researcher.explorer")` and `get_skill("exploration/repo-map")` before deep dives.
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
|
|
18
|
+
1. **Clarify the map question**: what subsystem, entry point, or data flow must be understood?
|
|
19
|
+
2. **Read before concluding**: grep, glob, read implicated files. No claims from memory.
|
|
20
|
+
3. **Produce artifacts**:
|
|
21
|
+
- `.cx/codebase-map.md` for broad orientation (repo-map skill)
|
|
22
|
+
- `.cx/research/{slug}.md` for focused investigations using `get_template("research-brief")`
|
|
23
|
+
4. **Source classes** (codebase-primary):
|
|
24
|
+
|
|
25
|
+
| Source | Class |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Source file at commit | primary |
|
|
28
|
+
| Test asserting behavior | primary |
|
|
29
|
+
| Config / schema in repo | primary |
|
|
30
|
+
| Comment or doc in repo | secondary |
|
|
31
|
+
| External blog about the repo | tertiary — locate code, do not cite alone |
|
|
32
|
+
|
|
33
|
+
5. **Cite as** `[source: path#Lnn]` or `[source: commit-sha]`.
|
|
34
|
+
6. **Tone**: default `pedagogical` — teach the next reader the shape of the system.
|
|
35
|
+
|
|
36
|
+
## Verification bar
|
|
37
|
+
|
|
38
|
+
- Every architectural claim traceable to file:line.
|
|
39
|
+
- Unknown paths marked `[unverified]` until read.
|
|
40
|
+
- cx-explorer must **not** answer product prioritization or user preference questions.
|
|
@@ -3,6 +3,7 @@ name: docs-customer-profile-workflow
|
|
|
3
3
|
description: "Use when: customer evidence should update durable product memory."
|
|
4
4
|
inputs: [signal, customer-profile]
|
|
5
5
|
artifactType: customer-profile
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Customer Profile Workflow
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@ name: docs-document-ingest-workflow
|
|
|
3
3
|
description: "Use when: the user points at a PDF, Word doc, spreadsheet, slide deck, export, or mixed document folder and wants a markdown version that Construct can search efficiently later."
|
|
4
4
|
inputs: [document]
|
|
5
5
|
artifactType: ingested-markdown
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Document Ingest Workflow
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@ name: docs-evidence-ingest-workflow
|
|
|
3
3
|
description: "Use when: the user pastes customer notes, Slack threads, support tickets, sales notes, research snippets, RFCs, analytics summaries, or competitor signals."
|
|
4
4
|
inputs: [signal, document]
|
|
5
5
|
artifactType: evidence-brief
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Evidence Ingest Workflow
|
|
8
9
|
|
package/skills/docs/init-docs.md
CHANGED
|
@@ -46,7 +46,7 @@ docs/
|
|
|
46
46
|
|
|
47
47
|
## Interactive UX (TTY)
|
|
48
48
|
|
|
49
|
-
When run interactively, `construct init-
|
|
49
|
+
When run interactively, `construct init --docs-preset=*` renders a keyboard-driven **full-screen checkbox picker**: all available lanes listed with the default set pre-checked and context-suggested lanes highlighted in the UI. No typing required.
|
|
50
50
|
|
|
51
51
|
- **↑ / ↓**: move cursor (details shown in a dedicated panel)
|
|
52
52
|
- **Space**: toggle lane on/off
|
|
@@ -54,7 +54,7 @@ When run interactively, `construct init-docs` renders a keyboard-driven **full-s
|
|
|
54
54
|
- **Enter**: confirm and scaffold
|
|
55
55
|
- Follow-up choices use the same menu pattern instead of free-text answers
|
|
56
56
|
|
|
57
|
-
If the user selects the `intake` lane, `construct init
|
|
57
|
+
If the user selects the `intake` lane, `construct init` should also create `.cx/inbox/`. Both `.cx/inbox/` and `docs/intake/` act as drop zones for ingestable files, while `docs/intake/` also serves as the durable paper trail lane.
|
|
58
58
|
|
|
59
59
|
When run non-interactively (`--yes` or piped stdin), the lean default set is used unless `--docs=` is supplied. `--docs=lean|product|full` or `--docs=adrs,prds,rfcs` both work.
|
|
60
60
|
|
|
@@ -10,9 +10,14 @@ Use when: starting work on a new project or joining an existing one without doc
|
|
|
10
10
|
|
|
11
11
|
## Command
|
|
12
12
|
```bash
|
|
13
|
-
construct init-
|
|
13
|
+
construct init --docs-preset=lean [path] # defaults to current directory; presets: lean | product | full
|
|
14
|
+
# or lane-specific init:
|
|
15
|
+
construct init [path] [--docs-preset=lean|product|full] # unified bootstrap (preferred)
|
|
16
|
+
construct init --docs-preset=lean [path] # docs-only lean preset
|
|
14
17
|
```
|
|
15
18
|
|
|
19
|
+
`npm run docs:init` is deprecated — use `construct init --docs-preset=*` instead.
|
|
20
|
+
|
|
16
21
|
## What it creates
|
|
17
22
|
```
|
|
18
23
|
.cx/ ← agent session memory and decisions
|
|
@@ -32,10 +37,10 @@ docs/ ← human-readable project documentation
|
|
|
32
37
|
1. Treat `.cx/context.md`, `.cx/context.json`, `.cx/workflow.json`, `docs/README.md`, and `docs/architecture.md` as required project state.
|
|
33
38
|
2. Read them at the start of every meaningful session.
|
|
34
39
|
3. Update them whenever work changes active reality: decisions, workflow phase, architecture assumptions, or documentation contract.
|
|
35
|
-
4. Run `construct
|
|
40
|
+
4. Run `construct dashboard` to see the project in the dashboard.
|
|
36
41
|
|
|
37
42
|
## For cx-docs-keeper
|
|
38
|
-
At session start, check the core docs set. If missing, suggest running `construct init-docs
|
|
43
|
+
At session start, check the core docs set. If missing, suggest running `construct init --docs-preset=lean` (or `construct init --docs-preset=full` for the full lane set).
|
|
39
44
|
At session end, update the affected core docs so the next LLM session inherits current project reality.
|
|
40
45
|
|
|
41
46
|
## For all LLMs working in the repo
|
|
@@ -3,6 +3,7 @@ name: docs-prd-workflow
|
|
|
3
3
|
description: "Use when: the user asks to create a PRD, platform spec, business case, RFC, or requirements document."
|
|
4
4
|
inputs: [research-question, evidence-brief]
|
|
5
5
|
artifactType: prd
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# PRD Workflow
|
|
8
9
|
|
|
@@ -10,6 +11,8 @@ Use when: the user asks to create a PRD, platform spec, business case, RFC, or r
|
|
|
10
11
|
|
|
11
12
|
Choose the document type before drafting:
|
|
12
13
|
|
|
14
|
+
Resolve tone from `specialists/tone-profiles.json` and optional `.cx/brand-voice.json` override for the selected template.
|
|
15
|
+
|
|
13
16
|
| Template | Use when |
|
|
14
17
|
|---|---|
|
|
15
18
|
| `prd` | Customer-facing product capabilities, user workflows, end-user requirements |
|
|
@@ -36,7 +39,10 @@ Style constraint: do not produce a wall of bullets. Use paragraphs for reasoning
|
|
|
36
39
|
| `meta-prd` | `docs/meta-prd/{YYYY-MM-DD}-{slug}.md` |
|
|
37
40
|
| `rfc` | `docs/rfc/{YYYY-MM-DD}-{slug}.md` |
|
|
38
41
|
| `rfc-platform` | `docs/rfc/{YYYY-MM-DD}-{slug}.md` |
|
|
39
|
-
5. **cx-
|
|
42
|
+
5. **cx-devil-advocate** runs the FMEA challenge pass (`roles/reviewer.devil-advocate`) on the draft; highest-RPN failure modes need a mitigation or explicit accept-with-rationale before ship. Their specialist id must appear in `.cx/agent-log.jsonl` (manifest `releaseGate.requiredReviewers` for PRD-family types).
|
|
43
|
+
6. **cx-docs-keeper** updates `.cx/context.md` with a link to the PRD
|
|
44
|
+
|
|
45
|
+
Run `construct artifact validate <path> --type=<type>` before marking the artifact approved.
|
|
40
46
|
|
|
41
47
|
## File naming
|
|
42
48
|
- `docs/{template-type}/{YYYY-MM-DD}-{slug}.md`
|
|
@@ -54,3 +60,20 @@ Style constraint: do not produce a wall of bullets. Use paragraphs for reasoning
|
|
|
54
60
|
## After approval → beads
|
|
55
61
|
|
|
56
62
|
Once the PRD is approved, run `/plan feature {feature-slug}` to produce a structured implementation plan and import it as workflow task packets (beads) into `.cx/workflow.json`. Link the resulting `.cx/plans/` file back in the PRD as the implementation reference.
|
|
63
|
+
|
|
64
|
+
## Distribution (publish pipeline)
|
|
65
|
+
|
|
66
|
+
**`construct workflow invoke` returns a plan only** — it does not draft the PRD. Run the listed specialists (cx-product-manager, cx-researcher, cx-ux-researcher as needed) to author the artifact from the template. **Do not hand-write a stub and publish.**
|
|
67
|
+
|
|
68
|
+
Before distribution:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
node bin/construct artifact validate docs/prd-platform/<slug>.md --type=prd-platform
|
|
72
|
+
node bin/construct publish docs/prd-platform/<slug>.md --strict --figures
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`construct publish` runs the artifact release gate by default. Thin or unscaffolded docs **exit 2** with remediation hints. Do not use `--no-gate` or `--no-strict` in demos or ship paths.
|
|
76
|
+
|
|
77
|
+
**Presentation is part of done.** Published PDFs use type-specific Typst templates (`construct-prd.typ`, `construct-research.typ`, `construct-decision.typ`) with violet editorial branding and Inter body typography. Lead with an `::: executive-summary` narrative paragraph — not a bullet wall. Diagrams on the publish path use D2 `--sketch` and Mermaid `handDrawn` styling with Construct violet accent.
|
|
78
|
+
|
|
79
|
+
`--strict` means **toolchain and release gate** both pass. Invoke alone is not "done."
|
|
@@ -3,6 +3,7 @@ name: docs-prfaq-workflow
|
|
|
3
3
|
description: "Use when: the user asks for a PRFAQ, working-backwards doc, launch narrative, or FAQ grounded in product evidence."
|
|
4
4
|
inputs: [prd, evidence-brief]
|
|
5
5
|
artifactType: prfaq
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# PRFAQ Workflow
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@ name: docs-product-intelligence-workflow
|
|
|
3
3
|
description: "Use when: the request involves customer evidence, PM synthesis, product requirements, PRDs, PRFAQs, customer profiles, product signals, or backlog proposals."
|
|
4
4
|
inputs: [signal, evidence-brief]
|
|
5
5
|
artifactType: prd
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Product Intelligence Workflow
|
|
8
9
|
|
|
@@ -3,6 +3,7 @@ name: docs-product-signal-workflow
|
|
|
3
3
|
description: "Use when: the user asks what customers are asking for, what themes are emerging, whether evidence is strong enough, or what should become a PRD."
|
|
4
4
|
inputs: [signal, evidence-brief]
|
|
5
5
|
artifactType: signal-brief
|
|
6
|
+
verificationBar: "Every load-bearing claim cites a verifiable source; label inference confidence; satisfy template structure requirements."
|
|
6
7
|
---
|
|
7
8
|
# Product Signal Workflow
|
|
8
9
|
|