@geraldmaron/construct 1.2.3 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -10
- package/bin/construct +235 -209
- package/bin/construct-postinstall.mjs +0 -21
- package/commands/work/optimize-prompts.md +1 -1
- package/examples/distribution/sources/adr.md +2 -2
- package/examples/seed-observations/decisions.md +1 -1
- package/lib/artifact-loop-core.mjs +412 -0
- package/lib/artifact-manifest.mjs +6 -0
- package/lib/artifact-release-gate.mjs +115 -49
- package/lib/audit-rules.mjs +2 -4
- package/lib/audit-skills.mjs +32 -20
- package/lib/audit-specialists.mjs +44 -26
- package/lib/auto-docs.mjs +6 -5
- package/lib/brand-prose.mjs +3 -3
- package/lib/brand-tokens.mjs +2 -2
- package/lib/certification/artifact-fixtures.mjs +4 -1
- package/lib/certification/demo-parity.mjs +6 -32
- package/lib/certification/real-llm-scenarios.mjs +58 -13
- package/lib/certification/role-cards.mjs +7 -6
- package/lib/certification/role-overlays.mjs +4 -4
- package/lib/certification/runner.mjs +9 -2
- package/lib/certification/skill-inventory.mjs +34 -22
- package/lib/certification/skill-scenarios.mjs +21 -8
- package/lib/certification/specialist-contracts.mjs +4 -3
- package/lib/certification/specialist-scenarios.mjs +7 -6
- package/lib/certification/status.mjs +5 -4
- package/lib/cli-commands.mjs +55 -54
- package/lib/comment-lint.mjs +1 -5
- package/lib/completions.mjs +20 -2
- package/lib/config/legacy-config-migration.mjs +90 -24
- package/lib/config/schema.mjs +5 -5
- package/lib/config/source-targets.mjs +80 -0
- package/lib/contracts/validate.mjs +119 -51
- package/lib/decisions/golden.mjs +3 -2
- package/lib/decisions/registry.mjs +11 -6
- package/lib/demo-project.mjs +188 -0
- package/lib/demo-recording.mjs +9 -34
- package/lib/demo-script.mjs +2 -2
- package/lib/demo-surface.mjs +13 -131
- package/lib/demo-tour-renderer.mjs +92 -0
- package/lib/demo.mjs +69 -54
- package/lib/diagram-export.mjs +63 -14
- package/lib/doctor/cli.mjs +12 -2
- package/lib/doctor/source-checkout.mjs +3 -4
- package/lib/doctor/watchers/consistency.mjs +148 -43
- package/lib/doctor/watchers/credential-parity.mjs +97 -0
- package/lib/doctor/watchers/mcp-protocol.mjs +1 -1
- package/lib/doctor/watchers/service-health.mjs +4 -32
- package/lib/document-export.mjs +73 -9
- package/lib/document-extract.mjs +10 -198
- package/lib/embed/artifact.mjs +2 -3
- package/lib/embed/cli.mjs +1 -1
- package/lib/embed/config.mjs +1 -2
- package/lib/embed/customer-profiles.mjs +1 -1
- package/lib/embed/daemon.mjs +5 -6
- package/lib/embed/demand-fetch.mjs +114 -2
- package/lib/embed/docs-lifecycle.mjs +9 -5
- package/lib/embed/intake-metrics.mjs +2 -2
- package/lib/embed/notifications.mjs +2 -3
- package/lib/embed/recommendation-store.mjs +25 -22
- package/lib/embed/role-framing.mjs +4 -9
- package/lib/embedded-contract/capability.mjs +4 -2
- package/lib/embedded-contract/contract-version.mjs +1 -1
- package/lib/env-config.mjs +2 -2
- package/lib/flavors/loader.mjs +21 -19
- package/lib/graph/build-from-registry.mjs +31 -7
- package/lib/graph/staleness.mjs +1 -1
- package/lib/headhunt.mjs +82 -35
- package/lib/hooks/agent-tracker.mjs +2 -2
- package/lib/hooks/config-protection.mjs +1 -1
- package/lib/hooks/registry-sync.mjs +3 -3
- package/lib/host-capabilities.mjs +5 -5
- package/lib/improvement/controller.mjs +2 -2
- package/lib/init-unified.mjs +19 -21
- package/lib/intake/classify.mjs +26 -0
- package/lib/intake/daemon.mjs +2 -3
- package/lib/intake/prepare.mjs +10 -3
- package/lib/intake/session-prelude.mjs +1 -1
- package/lib/intake/tables/creative.mjs +9 -9
- package/lib/intake/tables/operations.mjs +4 -4
- package/lib/intake/tables/research.mjs +2 -2
- package/lib/integrations/intake-integrations.mjs +9 -10
- package/lib/knowledge/research-store.mjs +2 -2
- package/lib/mcp/server.mjs +104 -61
- package/lib/mcp/tool-budget.mjs +1 -46
- package/lib/mcp/tool-recovery.mjs +44 -0
- package/lib/mcp/tools/artifact-author.mjs +36 -0
- package/lib/mcp/tools/find-tool.mjs +86 -0
- package/lib/mcp/tools/orchestration-run.mjs +107 -69
- package/lib/mcp/tools/project.mjs +4 -3
- package/lib/mcp/tools/{profile.mjs → scope.mjs} +54 -52
- package/lib/mcp/tools/skills.mjs +39 -22
- package/lib/mcp/tools/telemetry.mjs +2 -1
- package/lib/mcp/tools/workflow.mjs +1 -1
- package/lib/mcp-platform-config.mjs +7 -5
- package/lib/migrations/index.mjs +4 -2
- package/lib/migrations/v2-unified-registry.mjs +35 -0
- package/lib/model-router.mjs +203 -36
- package/lib/models/catalog.mjs +25 -9
- package/lib/models/execution-capability-profile.mjs +3 -3
- package/lib/models/execution-policy.mjs +7 -6
- package/lib/models/provider-poll.mjs +18 -4
- package/lib/opencode-config.mjs +56 -1
- package/lib/opencode-runtime-plugin.mjs +13 -10
- package/lib/oracle/artifact-gate.mjs +14 -4
- package/lib/oracle/cli.mjs +2 -0
- package/lib/oracle/dispatch.mjs +18 -1
- package/lib/oracle/execute.mjs +39 -7
- package/lib/oracle/index.mjs +1 -1
- package/lib/oracle/org-graph.mjs +10 -5
- package/lib/oracle/policy.mjs +6 -0
- package/lib/oracle/read-model.mjs +103 -6
- package/lib/oracle/reconcile.mjs +31 -4
- package/lib/oracle/remediation-dispatch.mjs +53 -0
- package/lib/oracle/routing.mjs +5 -0
- package/lib/oracle/synthesize.mjs +80 -3
- package/lib/orchestration/routing-tables.mjs +44 -10
- package/lib/orchestration/runtime.mjs +2 -0
- package/lib/orchestration/worker.mjs +1 -1
- package/lib/orchestration-policy.mjs +351 -62
- package/lib/overrides/resolver.mjs +1 -12
- package/lib/parity.mjs +37 -11
- package/lib/policy/engine.mjs +80 -15
- package/lib/prompt-composer.js +51 -15
- package/lib/prompt-metadata.mjs +3 -2
- package/lib/providers/connection-probe.mjs +58 -0
- package/lib/providers/copilot-auth.mjs +1 -1
- package/lib/providers/credential-bootstrap.mjs +1 -1
- package/lib/providers/op-run.mjs +3 -4
- package/lib/providers/secret-resolver.mjs +31 -0
- package/lib/publish-tooling.mjs +3 -11
- package/lib/publish.mjs +12 -29
- package/lib/reconcile/mcp-entry-reconcile.mjs +14 -9
- package/lib/reflect.mjs +2 -2
- package/lib/registry/agent-manifest.mjs +190 -0
- package/lib/registry/assemble.mjs +133 -0
- package/lib/registry/catalog.mjs +171 -0
- package/lib/registry/cli.mjs +590 -6
- package/lib/registry/consolidation.mjs +5 -4
- package/lib/registry/docs-sync.mjs +67 -0
- package/lib/registry/loader.mjs +147 -0
- package/lib/registry/org-io.mjs +76 -0
- package/lib/registry/retired-paths.mjs +71 -0
- package/lib/registry/surface-map.mjs +5 -7
- package/lib/registry/validator.mjs +438 -0
- package/lib/research-execution-policy.mjs +173 -0
- package/lib/roles/catalog.mjs +4 -9
- package/lib/roles/fence.mjs +107 -1
- package/lib/roles/flavor-bindings.mjs +68 -0
- package/lib/roles/gateway.mjs +140 -29
- package/lib/roles/manifest.mjs +22 -13
- package/lib/roles/router.mjs +1 -1
- package/lib/scopes/enrich.mjs +67 -0
- package/lib/scopes/hooks.mjs +12 -0
- package/lib/{profiles → scopes}/lifecycle.mjs +70 -70
- package/lib/scopes/loader.mjs +104 -0
- package/lib/scopes/rebrand.mjs +32 -0
- package/lib/scopes/research-profile.mjs +16 -0
- package/lib/scopes/teams.mjs +98 -0
- package/lib/service-manager.mjs +1 -117
- package/lib/setup-prompts.mjs +1 -1
- package/lib/setup.mjs +6 -26
- package/lib/skills/composition-graph.mjs +98 -0
- package/lib/skills/router.mjs +80 -0
- package/lib/specialist-contracts.mjs +17 -18
- package/lib/specialists/postconditions.mjs +2 -2
- package/lib/specialists/prompt-schema.mjs +6 -5
- package/lib/specialists/roster.mjs +7 -12
- package/lib/specialists/schema.mjs +9 -6
- package/lib/status.mjs +25 -90
- package/lib/storage/file-lock.mjs +6 -3
- package/lib/telemetry/skill-calls.mjs +1 -1
- package/lib/templates/doc-presentation.mjs +63 -0
- package/lib/templates/visual-requirements.mjs +35 -2
- package/lib/term-format.mjs +107 -2
- package/lib/test-env-setup.mjs +21 -0
- package/lib/ui/components.mjs +42 -0
- package/lib/ui/glyphs.mjs +58 -0
- package/lib/ui/links.mjs +115 -0
- package/lib/ui/theme.mjs +108 -0
- package/lib/uninstall/uninstall.mjs +2 -1
- package/lib/validator.mjs +45 -8
- package/lib/validators/skill-effectiveness.mjs +174 -0
- package/lib/validators/skills.mjs +1 -1
- package/package.json +12 -8
- package/personas/construct.md +12 -3
- package/platforms/claude/CLAUDE.md +1 -1
- package/rules/common/beads-hygiene.md +52 -0
- package/rules/common/neurodivergent-output.md +4 -7
- package/rules/common/research.md +2 -0
- package/scripts/sync-specialists.mjs +269 -51
- package/skills/ai/prompt-optimizer.md +3 -3
- package/skills/brand/output-vibe.md +48 -0
- package/skills/docs/adr-workflow.md +3 -0
- package/skills/docs/backlog-proposal-workflow.md +3 -0
- package/skills/docs/codebase-research-workflow.md +5 -2
- package/skills/docs/customer-profile-workflow.md +3 -0
- package/skills/docs/document-ingest-workflow.md +3 -0
- package/skills/docs/evidence-ingest-workflow.md +4 -1
- package/skills/docs/init-project.md +1 -1
- package/skills/docs/prd-workflow.md +1 -1
- package/skills/docs/prfaq-workflow.md +3 -0
- package/skills/docs/product-intelligence-workflow.md +4 -1
- package/skills/docs/product-signal-workflow.md +3 -0
- package/skills/docs/research-workflow.md +13 -6
- package/skills/docs/runbook-workflow.md +3 -0
- package/skills/docs/strategy-workflow.md +3 -0
- package/skills/docs/user-research-workflow.md +6 -3
- package/skills/operating/orchestration-reference.md +1 -1
- package/skills/roles/{engineer.ai.md → ai-engineer.md} +2 -2
- package/skills/roles/architect.ai-systems.md +1 -1
- package/skills/roles/architect.data.md +1 -1
- package/skills/roles/architect.enterprise.md +1 -1
- package/skills/roles/architect.integration.md +1 -1
- package/skills/roles/architect.md +1 -1
- package/skills/roles/architect.platform.md +1 -1
- package/skills/roles/{product-manager.business-strategy.md → business-strategist.md} +3 -3
- package/skills/roles/data-analyst.experiment.md +1 -1
- package/skills/roles/data-analyst.md +1 -1
- package/skills/roles/data-analyst.product-intelligence.md +1 -1
- package/skills/roles/data-analyst.product.md +1 -1
- package/skills/roles/data-analyst.telemetry.md +1 -1
- package/skills/roles/{engineer.data.md → data-engineer.md} +2 -2
- package/skills/roles/data-engineer.pipeline.md +2 -2
- package/skills/roles/data-engineer.vector-retrieval.md +2 -2
- package/skills/roles/data-engineer.warehouse.md +2 -2
- package/skills/roles/debugger.md +1 -1
- package/skills/roles/designer.accessibility.md +1 -1
- package/skills/roles/designer.md +1 -1
- package/skills/roles/{reviewer.devil-advocate.md → devil-advocate.md} +2 -2
- package/skills/roles/{operator.docs.md → docs-keeper.md} +3 -3
- package/skills/roles/engineer.md +3 -7
- package/skills/roles/{reviewer.evaluator.md → evaluator.md} +2 -2
- package/skills/roles/{researcher.explorer.md → explorer.md} +2 -2
- package/skills/roles/{operator.md → operations.md} +2 -5
- package/skills/roles/orchestrator.md +1 -1
- package/skills/roles/{engineer.platform.md → platform-engineer.md} +2 -2
- package/skills/roles/product-manager.ai-product.md +1 -1
- package/skills/roles/product-manager.enterprise.md +1 -1
- package/skills/roles/product-manager.growth.md +1 -2
- package/skills/roles/product-manager.md +1 -2
- package/skills/roles/product-manager.platform.md +1 -1
- package/skills/roles/product-manager.product.md +1 -1
- package/skills/roles/qa.ai-eval.md +1 -1
- package/skills/roles/qa.api-contract.md +1 -1
- package/skills/roles/qa.data-pipeline.md +1 -1
- package/skills/roles/qa.md +1 -1
- package/skills/roles/qa.web-ui.md +1 -1
- package/skills/roles/{operator.release.md → release-manager.md} +3 -3
- package/skills/roles/researcher.md +1 -1
- package/skills/roles/reviewer.md +1 -1
- package/skills/roles/security.ai.md +1 -1
- package/skills/roles/security.appsec.md +1 -1
- package/skills/roles/security.cloud.md +1 -1
- package/skills/roles/security.legal-compliance.md +1 -1
- package/skills/roles/security.md +1 -1
- package/skills/roles/security.privacy.md +1 -1
- package/skills/roles/security.supply-chain.md +1 -1
- package/skills/roles/{operator.sre.md → sre.md} +3 -3
- package/skills/roles/{qa.test-automation.md → test-automation.md} +2 -2
- package/skills/roles/{reviewer.trace.md → trace-reviewer.md} +2 -2
- package/skills/roles/{researcher.ux.md → ux-researcher.md} +2 -2
- package/skills/routing.json +18 -0
- package/skills/routing.md +1 -1
- package/specialists/artifact-manifest.json +2 -1
- package/specialists/audit-enrichments.json +14 -14
- package/specialists/org/contracts/accessibility-to-qa.json +37 -0
- package/specialists/org/contracts/any-to-business-strategist.json +57 -0
- package/specialists/org/contracts/any-to-debugger.json +38 -0
- package/specialists/org/contracts/any-to-designer.json +33 -0
- package/specialists/org/contracts/any-to-docs-keeper.json +34 -0
- package/specialists/org/contracts/any-to-explorer.json +39 -0
- package/specialists/org/contracts/any-to-sre-incident.json +33 -0
- package/specialists/org/contracts/any-to-trace-reviewer.json +32 -0
- package/specialists/org/contracts/architect-to-ai-engineer.json +32 -0
- package/specialists/org/contracts/architect-to-data-engineer.json +52 -0
- package/specialists/org/contracts/architect-to-devil-advocate.json +38 -0
- package/specialists/org/contracts/architect-to-engineer.json +34 -0
- package/specialists/org/contracts/architect-to-evaluator.json +59 -0
- package/specialists/org/contracts/architect-to-legal-compliance.json +55 -0
- package/specialists/org/contracts/architect-to-operations.json +45 -0
- package/specialists/org/contracts/architect-to-platform-engineer.json +42 -0
- package/specialists/org/contracts/business-strategist-to-product-manager.json +39 -0
- package/specialists/org/contracts/construct-to-orchestrator.json +36 -0
- package/specialists/org/contracts/construct-to-rd-lead.json +53 -0
- package/specialists/org/contracts/data-analyst-to-product-manager.json +43 -0
- package/specialists/org/contracts/data-engineer-to-platform-engineer.json +36 -0
- package/specialists/org/contracts/designer-to-accessibility.json +36 -0
- package/specialists/org/contracts/engineer-to-qa.json +34 -0
- package/specialists/org/contracts/engineer-to-reviewer.json +52 -0
- package/specialists/org/contracts/explorer-to-engineer.json +38 -0
- package/specialists/org/contracts/legal-compliance-to-release-manager.json +43 -0
- package/specialists/org/contracts/platform-engineer-to-engineer.json +31 -0
- package/specialists/org/contracts/product-manager-to-architect.json +71 -0
- package/specialists/org/contracts/product-manager-to-data-analyst.json +49 -0
- package/specialists/org/contracts/product-manager-to-ux-researcher.json +51 -0
- package/specialists/org/contracts/qa-to-release-manager.json +42 -0
- package/specialists/org/contracts/qa-to-test-automation.json +42 -0
- package/specialists/org/contracts/rd-lead-to-architect.json +38 -0
- package/specialists/org/contracts/researcher-to-architect.json +40 -0
- package/specialists/org/contracts/researcher-to-product-manager.json +57 -0
- package/specialists/org/contracts/reviewer-to-security.json +41 -0
- package/specialists/org/contracts/sre-to-release-manager.json +36 -0
- package/specialists/org/contracts/test-automation-to-engineer.json +34 -0
- package/specialists/org/contracts/trace-reviewer-to-sre.json +41 -0
- package/specialists/org/contracts/user-to-construct.json +30 -0
- package/specialists/org/groups/engineering-group.json +43 -0
- package/specialists/org/groups/governance-group.json +38 -0
- package/specialists/org/groups/operations-group.json +41 -0
- package/specialists/org/groups/product-group.json +46 -0
- package/specialists/org/groups/quality-group.json +42 -0
- package/specialists/org/groups/strategy-group.json +41 -0
- package/specialists/org/policies/action-approval.json +13 -0
- package/specialists/org/policies/agents-routing.json +13 -0
- package/specialists/org/policies/architecture.json +20 -0
- package/specialists/org/policies/bash-safety.json +13 -0
- package/specialists/org/policies/beads-hygiene.json +13 -0
- package/specialists/org/policies/bootstrap-state.json +13 -0
- package/specialists/org/policies/code-review.json +13 -0
- package/specialists/org/policies/coding-style.json +13 -0
- package/specialists/org/policies/comments.json +13 -0
- package/specialists/org/policies/commit-approval.json +13 -0
- package/specialists/org/policies/contract-preconditions.json +13 -0
- package/specialists/org/policies/deployment.json +20 -0
- package/specialists/org/policies/description.json +14 -0
- package/specialists/org/policies/design-approval.json +19 -0
- package/specialists/org/policies/doc-ownership.json +13 -0
- package/specialists/org/policies/file-path-fence.json +13 -0
- package/specialists/org/policies/framing.json +13 -0
- package/specialists/org/policies/git-workflow.json +13 -0
- package/specialists/org/policies/incident-response.json +15 -0
- package/specialists/org/policies/intake-triage.json +15 -0
- package/specialists/org/policies/neurodivergent-output.json +13 -0
- package/specialists/org/policies/no-fabrication.json +13 -0
- package/specialists/org/policies/patterns.json +13 -0
- package/specialists/org/policies/quality-gate-approval.json +17 -0
- package/specialists/org/policies/release-gates.json +13 -0
- package/specialists/org/policies/research-evidence.json +13 -0
- package/specialists/org/policies/review-before-change.json +13 -0
- package/specialists/org/policies/rollback.json +15 -0
- package/specialists/org/policies/scope-change.json +20 -0
- package/specialists/org/policies/secret-scan.json +13 -0
- package/specialists/org/policies/security-approval.json +17 -0
- package/specialists/org/policies/security.json +13 -0
- package/specialists/org/policies/session-efficiency.json +13 -0
- package/specialists/org/policies/skill-routing.json +13 -0
- package/specialists/org/policies/strategic-prioritization.json +17 -0
- package/specialists/org/policies/testing.json +13 -0
- package/specialists/org/policies/tool-invisibility.json +14 -0
- package/specialists/org/scopes/creative.json +54 -0
- package/specialists/org/scopes/operations.json +51 -0
- package/specialists/org/scopes/research.json +60 -0
- package/specialists/org/scopes/rnd.json +81 -0
- package/specialists/org/specialists/cx-accessibility.json +69 -0
- package/specialists/org/specialists/cx-ai-engineer.json +75 -0
- package/specialists/org/specialists/cx-architect.json +89 -0
- package/specialists/org/specialists/cx-business-strategist.json +72 -0
- package/specialists/org/specialists/cx-data-analyst.json +68 -0
- package/specialists/org/specialists/cx-data-engineer.json +71 -0
- package/specialists/org/specialists/cx-debugger.json +75 -0
- package/specialists/org/specialists/cx-designer.json +85 -0
- package/specialists/org/specialists/cx-devil-advocate.json +71 -0
- package/specialists/org/specialists/cx-docs-keeper.json +82 -0
- package/specialists/org/specialists/cx-engineer.json +106 -0
- package/specialists/org/specialists/cx-evaluator.json +69 -0
- package/specialists/org/specialists/cx-explorer.json +69 -0
- package/specialists/org/specialists/cx-legal-compliance.json +74 -0
- package/specialists/org/specialists/cx-operations.json +72 -0
- package/specialists/org/specialists/cx-oracle.json +46 -0
- package/specialists/org/specialists/cx-orchestrator.json +81 -0
- package/specialists/org/specialists/cx-platform-engineer.json +80 -0
- package/specialists/org/specialists/cx-product-manager.json +102 -0
- package/specialists/org/specialists/cx-qa.json +79 -0
- package/specialists/org/specialists/cx-rd-lead.json +73 -0
- package/specialists/org/specialists/cx-release-manager.json +77 -0
- package/specialists/org/specialists/cx-researcher.json +82 -0
- package/specialists/org/specialists/cx-reviewer.json +71 -0
- package/specialists/org/specialists/cx-security.json +91 -0
- package/specialists/org/specialists/cx-sre.json +94 -0
- package/specialists/org/specialists/cx-test-automation.json +69 -0
- package/specialists/org/specialists/cx-trace-reviewer.json +69 -0
- package/specialists/org/specialists/cx-ux-researcher.json +68 -0
- package/specialists/org/teams/accessibility-team.json +39 -0
- package/specialists/org/teams/design-team.json +40 -0
- package/specialists/org/teams/engineering-team.json +50 -0
- package/specialists/org/teams/governance-team.json +41 -0
- package/specialists/org/teams/operations-team.json +46 -0
- package/specialists/org/teams/product-management-team.json +45 -0
- package/specialists/org/teams/quality-team.json +49 -0
- package/specialists/org/teams/research-team.json +39 -0
- package/specialists/org/teams/strategy-team.json +48 -0
- package/specialists/org/teams/ux-research-team.json +39 -0
- package/specialists/prompts/_shared/validation-contract.md +1 -1
- package/specialists/prompts/_team-template.md +10 -0
- package/specialists/prompts/cx-accessibility.md +1 -0
- package/specialists/prompts/cx-ai-engineer.md +1 -1
- package/specialists/prompts/cx-business-strategist.md +1 -1
- package/specialists/prompts/cx-data-engineer.md +1 -1
- package/specialists/prompts/cx-designer.md +1 -0
- package/specialists/prompts/cx-devil-advocate.md +1 -1
- package/specialists/prompts/cx-docs-keeper.md +1 -1
- package/specialists/prompts/cx-evaluator.md +1 -1
- package/specialists/prompts/cx-explorer.md +1 -1
- package/specialists/prompts/cx-operations.md +1 -1
- package/specialists/prompts/cx-oracle.md +7 -3
- package/specialists/prompts/cx-orchestrator.md +17 -1
- package/specialists/prompts/cx-platform-engineer.md +1 -1
- package/specialists/prompts/cx-product-manager.md +2 -0
- package/specialists/prompts/cx-release-manager.md +1 -1
- package/specialists/prompts/cx-researcher.md +7 -4
- package/specialists/prompts/cx-sre.md +1 -1
- package/specialists/prompts/cx-test-automation.md +2 -2
- package/specialists/prompts/cx-trace-reviewer.md +3 -3
- package/specialists/prompts/cx-ux-researcher.md +2 -1
- package/templates/demos/scripts/architecture-review-adr.json +30 -0
- package/templates/demos/scripts/capability-contract.json +25 -0
- package/templates/demos/scripts/intake-triage.json +25 -0
- package/templates/demos/scripts/profile-doctor-health.json +25 -0
- package/templates/demos/tapes/agentic-platforms-prd.tape +2 -2
- package/templates/demos/tapes/architecture-review-adr.tape +44 -0
- package/templates/demos/tapes/capability-contract.tape +39 -0
- package/templates/demos/tapes/intake-triage.tape +39 -0
- package/templates/demos/tapes/profile-doctor-health.tape +39 -0
- package/templates/distribution/construct-brand.typ +23 -18
- package/templates/distribution/construct-decision.typ +1 -1
- package/templates/distribution/construct-pdf.typ +1 -1
- package/templates/distribution/construct-prd.typ +1 -1
- package/templates/distribution/construct-research.typ +1 -1
- package/templates/distribution/mermaid-puppeteer.json +8 -0
- package/templates/docs/persona-artifact.md +1 -1
- package/templates/docs/prd.md +6 -0
- package/apps/chat/engine/ai-sdk-agent.mjs +0 -183
- package/apps/chat/engine/loop-driver.mjs +0 -211
- package/apps/chat/engine/models.mjs +0 -122
- package/apps/chat/engine/provider-adapters.mjs +0 -171
- package/apps/chat/engine/tools/permission.mjs +0 -54
- package/apps/chat/engine/tools/primitives.mjs +0 -180
- package/apps/chat/engine/tools/registry.mjs +0 -122
- package/apps/chat/engine/turn-controls.mjs +0 -70
- package/lib/boundary.mjs +0 -127
- package/lib/certification/dashboard-api.mjs +0 -71
- package/lib/chat/cli.mjs +0 -333
- package/lib/chat/command-suggest.mjs +0 -161
- package/lib/chat/commands.mjs +0 -215
- package/lib/chat/config.mjs +0 -142
- package/lib/chat/context-compactor.mjs +0 -250
- package/lib/chat/context-continuation.mjs +0 -253
- package/lib/chat/continuation-source.mjs +0 -58
- package/lib/chat/demo-guide.mjs +0 -61
- package/lib/chat/design-tokens.mjs +0 -91
- package/lib/chat/desktop-binary.mjs +0 -81
- package/lib/chat/desktop-build.mjs +0 -130
- package/lib/chat/desktop-launcher.mjs +0 -133
- package/lib/chat/evidence.mjs +0 -145
- package/lib/chat/export.mjs +0 -74
- package/lib/chat/harness/driver.mjs +0 -91
- package/lib/chat/list-picker.mjs +0 -112
- package/lib/chat/model-picker.mjs +0 -356
- package/lib/chat/openrouter-fallback.mjs +0 -151
- package/lib/chat/permission-prompt.mjs +0 -33
- package/lib/chat/picker-catalog.mjs +0 -45
- package/lib/chat/policy-telemetry.mjs +0 -34
- package/lib/chat/present.mjs +0 -246
- package/lib/chat/session-context.mjs +0 -39
- package/lib/chat/session-persist.mjs +0 -73
- package/lib/chat/session-restore.mjs +0 -71
- package/lib/chat/session-settings.mjs +0 -53
- package/lib/chat/system-prompt.mjs +0 -52
- package/lib/chat/transparency.mjs +0 -93
- package/lib/chat/tui/color-scheme.mjs +0 -42
- package/lib/chat/tui/markdown.mjs +0 -123
- package/lib/chat/tui/presentation.mjs +0 -100
- package/lib/chat/tui/render.mjs +0 -500
- package/lib/chat/tui/turn-block.mjs +0 -284
- package/lib/chat/tui/turn-present.mjs +0 -18
- package/lib/chat/tui/turn-state.mjs +0 -88
- package/lib/chat/tui/usage.mjs +0 -122
- package/lib/chat/web-commands.mjs +0 -146
- package/lib/chat/web-launcher.mjs +0 -63
- package/lib/chat/web-picker-keys.mjs +0 -46
- package/lib/chat/web-session.mjs +0 -159
- package/lib/config/alias.mjs +0 -57
- package/lib/dashboard-demo.mjs +0 -71
- package/lib/dashboard-static.mjs +0 -175
- package/lib/install/desktop-binary-download.mjs +0 -88
- package/lib/profiles/loader.mjs +0 -123
- package/lib/profiles/rebrand.mjs +0 -46
- package/lib/server/auth.mjs +0 -169
- package/lib/server/chat-loop.mjs +0 -622
- package/lib/server/chat.mjs +0 -336
- package/lib/server/cors.mjs +0 -77
- package/lib/server/csrf.mjs +0 -103
- package/lib/server/demo-preview.mjs +0 -63
- package/lib/server/index.mjs +0 -2641
- package/lib/server/insights.mjs +0 -780
- package/lib/server/langfuse-login.mjs +0 -58
- package/lib/server/rate-limit.mjs +0 -93
- package/lib/server/telemetry-login.mjs +0 -100
- package/lib/server/webhook.mjs +0 -512
- package/specialists/contracts.json +0 -1032
- package/specialists/contracts.schema.json +0 -83
- package/specialists/policy-inventory.json +0 -188
- package/specialists/registry.json +0 -1412
- package/specialists/role-manifests.json +0 -217
- package/specialists/teams.json +0 -94
package/lib/demo.mjs
CHANGED
|
@@ -2,19 +2,23 @@
|
|
|
2
2
|
* lib/demo.mjs — `construct demo` terminal recordings via VHS `.tape` files.
|
|
3
3
|
*
|
|
4
4
|
* Shipped tapes live in templates/demos/tapes/; project overrides in
|
|
5
|
-
* .cx/demos/tapes/. Built-in scaffolds via `construct demo init --from
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* .cx/demos/tapes/. Built-in scaffolds via `construct demo init --from=`;
|
|
6
|
+
* `--from-project` scaffolds a project demo plug-in (manifest + script + tape)
|
|
7
|
+
* under .cx/demos/ seeded from real project signals (see lib/demo-project.mjs).
|
|
8
|
+
* Default run mode writes or records a VHS tape; use `tour` for a linear
|
|
9
|
+
* guided walkthrough and `--surface=playwright` for recording manifests.
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
11
13
|
import { spawnSync } from 'node:child_process';
|
|
12
14
|
import { join, resolve, dirname, basename, relative } from 'node:path';
|
|
13
15
|
import { fileURLToPath } from 'node:url';
|
|
14
|
-
import { listDemoScripts } from './demo-script.mjs';
|
|
16
|
+
import { listDemoScripts, loadDemoScript } from './demo-script.mjs';
|
|
15
17
|
import { DEMO_SURFACES } from './demo-surface.mjs';
|
|
18
|
+
import { renderTour } from './demo-tour-renderer.mjs';
|
|
16
19
|
import { listDemoRecordings, loadDemoRecording } from './demo-recording.mjs';
|
|
17
20
|
import { recordPlaywrightDemo } from './playwright-demo.mjs';
|
|
21
|
+
import { scaffoldProjectDemo } from './demo-project.mjs';
|
|
18
22
|
|
|
19
23
|
const REPO_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
24
|
|
|
@@ -219,7 +223,7 @@ export function initConstructCockpitRecording(name, { cwd, repoRoot = REPO_ROOT
|
|
|
219
223
|
...reference,
|
|
220
224
|
name,
|
|
221
225
|
title: reference.title,
|
|
222
|
-
output: { format: 'mp4', path: `.cx/demos
|
|
226
|
+
output: { format: 'mp4', path: `.cx/demos/${name}.mp4` },
|
|
223
227
|
_reference: 'agentic-platforms-prd',
|
|
224
228
|
};
|
|
225
229
|
delete recording.sourcePath;
|
|
@@ -228,7 +232,7 @@ export function initConstructCockpitRecording(name, { cwd, repoRoot = REPO_ROOT
|
|
|
228
232
|
return {
|
|
229
233
|
ok: true,
|
|
230
234
|
recordingPath: recPath,
|
|
231
|
-
message: `Scaffolded Construct cockpit recording ${recPath}
|
|
235
|
+
message: `Scaffolded Construct cockpit recording ${recPath}`,
|
|
232
236
|
};
|
|
233
237
|
}
|
|
234
238
|
|
|
@@ -306,10 +310,6 @@ export function listProjectTapes({ cwd = process.cwd(), repoRoot = REPO_ROOT } =
|
|
|
306
310
|
}
|
|
307
311
|
|
|
308
312
|
export function resolveTapeSource(name, { cwd, repoRoot = REPO_ROOT, artifactPath } = {}) {
|
|
309
|
-
if (name.startsWith('dashboard:')) {
|
|
310
|
-
return { kind: 'dashboard', name: name.slice('dashboard:'.length) };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
313
|
const tapePath = resolveTapeFile(name, { cwd, repoRoot });
|
|
314
314
|
if (tapePath) {
|
|
315
315
|
let source = readFileSync(tapePath, 'utf8');
|
|
@@ -402,10 +402,6 @@ export function runDemoRecord(name, {
|
|
|
402
402
|
required = false,
|
|
403
403
|
surface = null,
|
|
404
404
|
} = {}) {
|
|
405
|
-
if (name.startsWith('dashboard:')) {
|
|
406
|
-
return { ok: false, name, message: 'Use recordDashboardDemo for dashboard: demos' };
|
|
407
|
-
}
|
|
408
|
-
|
|
409
405
|
const recording = loadDemoRecording(name, { cwd, repoRoot });
|
|
410
406
|
const usePlaywright = surface !== 'tape'
|
|
411
407
|
&& (surface === 'playwright' || (recording && recording.engine === 'playwright'));
|
|
@@ -506,28 +502,28 @@ export function printHelp() {
|
|
|
506
502
|
Commands:
|
|
507
503
|
list List tapes, recordings, and demo scripts
|
|
508
504
|
init <name> [--from=T] Scaffold tape or Playwright recording
|
|
505
|
+
init <name> --from-project Scaffold a project demo plug-in under .cx/demos/
|
|
509
506
|
record <name> Record VHS tape or Playwright demo manifest
|
|
510
|
-
|
|
507
|
+
tour [name] Linear, screen-reader-friendly guided tour
|
|
508
|
+
<name> Record or print the demo (default: tape)
|
|
511
509
|
|
|
512
|
-
Default run uses
|
|
513
|
-
Falls back to web chat, VHS tape, Playwright, dashboard, or printed steps.
|
|
510
|
+
Default run uses VHS tape templates and falls back to printed script steps.
|
|
514
511
|
|
|
515
512
|
Options:
|
|
516
513
|
--surface=<s> ${surfaces}
|
|
517
|
-
--
|
|
518
|
-
--
|
|
519
|
-
--plain Linear chat renderer
|
|
520
|
-
--free OpenRouter free-router mode
|
|
514
|
+
--accessible Screen-reader-friendly linear renderer (tour)
|
|
515
|
+
--skip-input Tour: auto-advance without waiting for Enter (headless/CI)
|
|
521
516
|
--format <f> gif (default) | mp4 | webm
|
|
522
517
|
--out <path> Output path (recording)
|
|
518
|
+
--from-project init: scaffold a project demo plug-in under .cx/demos/
|
|
523
519
|
--source-only Tape: write .tape only; skip recording
|
|
524
520
|
-h, --help Show this message
|
|
525
521
|
|
|
526
522
|
Examples:
|
|
527
523
|
construct demo agentic-platforms-prd
|
|
524
|
+
construct demo tour agentic-platforms-prd --accessible
|
|
528
525
|
construct demo record agentic-platforms-prd --format mp4
|
|
529
526
|
construct demo init marketing --from=nextjs-static
|
|
530
|
-
construct demo dashboard:cockpit-tour
|
|
531
527
|
`);
|
|
532
528
|
}
|
|
533
529
|
|
|
@@ -539,22 +535,19 @@ function parseArgs(argv) {
|
|
|
539
535
|
from: 'quickstart',
|
|
540
536
|
command: null,
|
|
541
537
|
name: null,
|
|
542
|
-
surface: '
|
|
543
|
-
model: null,
|
|
544
|
-
plain: false,
|
|
538
|
+
surface: 'tape',
|
|
545
539
|
accessible: false,
|
|
546
|
-
|
|
547
|
-
|
|
540
|
+
skipInput: false,
|
|
541
|
+
fromProject: false,
|
|
548
542
|
};
|
|
549
543
|
const positional = [];
|
|
550
544
|
for (let i = 0; i < argv.length; i += 1) {
|
|
551
545
|
const arg = argv[i];
|
|
552
546
|
if (arg === '--help' || arg === '-h') { options.help = true; continue; }
|
|
547
|
+
if (arg === '--from-project') { options.fromProject = true; continue; }
|
|
553
548
|
if (arg === '--source-only') { options.sourceOnly = true; continue; }
|
|
554
|
-
if (arg === '--plain') { options.plain = true; continue; }
|
|
555
549
|
if (arg === '--accessible') { options.accessible = true; continue; }
|
|
556
|
-
if (arg === '--
|
|
557
|
-
if (arg === '--free') { options.free = true; continue; }
|
|
550
|
+
if (arg === '--skip-input') { options.skipInput = true; continue; }
|
|
558
551
|
if (arg === '--format') { options.format = argv[++i]; continue; }
|
|
559
552
|
if (arg.startsWith('--format=')) { options.format = arg.slice(9); continue; }
|
|
560
553
|
if (arg === '--out') { options.out = argv[++i]; continue; }
|
|
@@ -563,13 +556,12 @@ function parseArgs(argv) {
|
|
|
563
556
|
if (arg.startsWith('--from=')) { options.from = arg.slice(7); continue; }
|
|
564
557
|
if (arg === '--surface') { options.surface = argv[++i]; continue; }
|
|
565
558
|
if (arg.startsWith('--surface=')) { options.surface = arg.slice(10); continue; }
|
|
566
|
-
if (arg === '--model') { options.model = argv[++i]; continue; }
|
|
567
|
-
if (arg.startsWith('--model=')) { options.model = arg.slice(8); continue; }
|
|
568
559
|
positional.push(arg);
|
|
569
560
|
}
|
|
570
561
|
if (positional[0] === 'list') options.command = 'list';
|
|
571
562
|
else if (positional[0] === 'init') { options.command = 'init'; options.name = positional[1]; }
|
|
572
563
|
else if (positional[0] === 'record') { options.command = 'record'; options.name = positional[1]; }
|
|
564
|
+
else if (positional[0] === 'tour') { options.command = 'tour'; options.name = positional[1] || null; }
|
|
573
565
|
else options.name = positional[0] || null;
|
|
574
566
|
return options;
|
|
575
567
|
}
|
|
@@ -591,7 +583,7 @@ export async function runDemoCli(argv = [], { cwd = process.cwd(), repoRoot } =
|
|
|
591
583
|
console.log('\nPlaywright recordings (.cx/demos/recordings/ overrides templates/demos/recordings/):');
|
|
592
584
|
if (!recordings.length) console.log(' (none — run `construct demo init <name> --from=nextjs-static`)');
|
|
593
585
|
else for (const r of recordings) console.log(` ${r}`);
|
|
594
|
-
console.log('\nDemo scripts (
|
|
586
|
+
console.log('\nDemo scripts (tour steps; templates/demos/scripts/):');
|
|
595
587
|
if (!scripts.length) console.log(' (none)');
|
|
596
588
|
else for (const s of scripts) console.log(` ${s}`);
|
|
597
589
|
console.log(`\nScaffold templates: ${RECORDING_INIT_TEMPLATES.join(', ')}`);
|
|
@@ -599,8 +591,21 @@ export async function runDemoCli(argv = [], { cwd = process.cwd(), repoRoot } =
|
|
|
599
591
|
}
|
|
600
592
|
|
|
601
593
|
if (options.command === 'init') {
|
|
594
|
+
if (options.fromProject) {
|
|
595
|
+
if (!options.name) {
|
|
596
|
+
console.error('Usage: construct demo init <name> --from-project');
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
const result = scaffoldProjectDemo(options.name, { cwd, repoRoot });
|
|
600
|
+
if (!result.ok) {
|
|
601
|
+
console.error(result.message);
|
|
602
|
+
process.exit(1);
|
|
603
|
+
}
|
|
604
|
+
console.log(result.message);
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
602
607
|
if (!options.name) {
|
|
603
|
-
console.error(`Usage: construct demo init <name> [--from=${RECORDING_INIT_TEMPLATES.join('|')}]`);
|
|
608
|
+
console.error(`Usage: construct demo init <name> [--from=${RECORDING_INIT_TEMPLATES.join('|')}] | --from-project`);
|
|
604
609
|
process.exit(1);
|
|
605
610
|
}
|
|
606
611
|
const result = initProjectRecording(options.name, { cwd, from: options.from, repoRoot });
|
|
@@ -612,28 +617,45 @@ export async function runDemoCli(argv = [], { cwd = process.cwd(), repoRoot } =
|
|
|
612
617
|
return;
|
|
613
618
|
}
|
|
614
619
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
const
|
|
623
|
-
|
|
620
|
+
if (options.command === 'tour') {
|
|
621
|
+
const scripts = listDemoScripts({ cwd, repoRoot });
|
|
622
|
+
const tourName = options.name || scripts[0] || null;
|
|
623
|
+
if (!tourName) {
|
|
624
|
+
console.error('No demo scripts found. Add one under templates/demos/scripts/ or .cx/demos/scripts/.');
|
|
625
|
+
process.exit(1);
|
|
626
|
+
}
|
|
627
|
+
const script = loadDemoScript(tourName, { cwd, repoRoot });
|
|
628
|
+
if (!script) {
|
|
629
|
+
console.error(`Unknown demo: ${tourName}. Run \`construct demo list\` to see available scripts.`);
|
|
630
|
+
process.exit(1);
|
|
631
|
+
}
|
|
632
|
+
// A non-TTY stdout (pipe, file, CI) advances on its own even without --skip-input.
|
|
633
|
+
const skipInput = options.skipInput || !process.stdout.isTTY;
|
|
634
|
+
const result = await renderTour({
|
|
635
|
+
script,
|
|
636
|
+
output: process.stdout,
|
|
637
|
+
input: process.stdin,
|
|
638
|
+
env: process.env,
|
|
639
|
+
accessible: options.accessible,
|
|
640
|
+
skipInput,
|
|
641
|
+
});
|
|
624
642
|
if (!result.ok) {
|
|
625
643
|
console.error(result.message);
|
|
626
|
-
process.exit(
|
|
644
|
+
process.exit(1);
|
|
627
645
|
}
|
|
628
|
-
console.log(result.message);
|
|
629
|
-
for (const v of result.videos || []) console.log(` ${v}`);
|
|
630
646
|
return;
|
|
631
647
|
}
|
|
632
648
|
|
|
649
|
+
const demoName = options.command === 'record' ? options.name : options.name;
|
|
650
|
+
if (!demoName) {
|
|
651
|
+
printHelp();
|
|
652
|
+
process.exit(1);
|
|
653
|
+
}
|
|
654
|
+
|
|
633
655
|
const preferPlaywright = options.surface === 'playwright'
|
|
634
656
|
|| (options.command === 'record' && loadDemoRecording(demoName, { cwd, repoRoot })?.engine === 'playwright');
|
|
635
657
|
const useTape = options.surface === 'tape'
|
|
636
|
-
|| (options.command === 'record' && !preferPlaywright
|
|
658
|
+
|| (options.command === 'record' && !preferPlaywright);
|
|
637
659
|
if (useTape || (options.command === 'record' && preferPlaywright)) {
|
|
638
660
|
const result = runDemoRecord(demoName, {
|
|
639
661
|
cwd,
|
|
@@ -669,11 +691,7 @@ export async function runDemoCli(argv = [], { cwd = process.cwd(), repoRoot } =
|
|
|
669
691
|
format: options.format,
|
|
670
692
|
out: options.out,
|
|
671
693
|
sourceOnly: options.sourceOnly,
|
|
672
|
-
model: options.model,
|
|
673
|
-
plain: options.plain,
|
|
674
694
|
accessible: options.accessible,
|
|
675
|
-
web: options.web,
|
|
676
|
-
free: options.free,
|
|
677
695
|
});
|
|
678
696
|
|
|
679
697
|
if (!result.ok) {
|
|
@@ -684,9 +702,6 @@ export async function runDemoCli(argv = [], { cwd = process.cwd(), repoRoot } =
|
|
|
684
702
|
if (result.notices?.length) {
|
|
685
703
|
for (const n of result.notices) console.error(`note: ${n}`);
|
|
686
704
|
}
|
|
687
|
-
if (result.surface === 'chat' || result.surface === 'web') {
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
705
|
if (result.artifactPath) {
|
|
691
706
|
console.log(`Demo (${demoName}) [${result.surface}] recorded to:`);
|
|
692
707
|
console.log(` ${result.artifactPath}`);
|
package/lib/diagram-export.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
14
14
|
|
|
15
15
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
16
16
|
const ICON_DIR = path.join(REPO_ROOT, 'templates', 'distribution', 'icons');
|
|
17
|
+
const MERMAID_PPTR_CONFIG = path.join(REPO_ROOT, 'templates', 'distribution', 'mermaid-puppeteer.json');
|
|
17
18
|
|
|
18
19
|
// Monochrome diagram palette, mirroring the ink ramp in construct-brand.typ so
|
|
19
20
|
// embedded diagrams and surrounding body share one design language.
|
|
@@ -36,9 +37,9 @@ export const DISTRIBUTION_D2_SCALE = '0.72';
|
|
|
36
37
|
export const DISTRIBUTION_D2_SKETCH = '1';
|
|
37
38
|
export const DISTRIBUTION_D2_FONT_SIZE = '14';
|
|
38
39
|
export const DISTRIBUTION_MERMAID_MIME = 'image/png';
|
|
39
|
-
export const DISTRIBUTION_MERMAID_WIDTH = '
|
|
40
|
-
export const DISTRIBUTION_MERMAID_SCALE = '
|
|
41
|
-
export const DISTRIBUTION_FIGURE_MAX_WIDTH = '
|
|
40
|
+
export const DISTRIBUTION_MERMAID_WIDTH = '2400';
|
|
41
|
+
export const DISTRIBUTION_MERMAID_SCALE = '2';
|
|
42
|
+
export const DISTRIBUTION_FIGURE_MAX_WIDTH = '92%';
|
|
42
43
|
|
|
43
44
|
// Handwritten font for Mermaid labels so its hand-drawn look matches D2 sketch
|
|
44
45
|
// mode. Caveat ships bundled (templates/distribution/fonts/handwritten) and is
|
|
@@ -51,6 +52,9 @@ const MERMAID_INIT = `%%{init: {
|
|
|
51
52
|
'theme': 'base',
|
|
52
53
|
'look': 'handDrawn',
|
|
53
54
|
'fontFamily': '${MERMAID_FONT}',
|
|
55
|
+
'flowchart': {
|
|
56
|
+
'htmlLabels': false
|
|
57
|
+
},
|
|
54
58
|
'themeVariables': {
|
|
55
59
|
'fontFamily': '${MERMAID_FONT}',
|
|
56
60
|
'fontSize': '19px',
|
|
@@ -86,17 +90,8 @@ const MERMAID_INIT = `%%{init: {
|
|
|
86
90
|
}
|
|
87
91
|
}}%%`;
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
92
|
-
'/usr/bin/google-chrome',
|
|
93
|
-
'/usr/bin/chromium',
|
|
94
|
-
'/usr/bin/chromium-browser',
|
|
95
|
-
];
|
|
96
|
-
|
|
97
|
-
export function resolvePuppeteerExecutable(env = process.env) {
|
|
98
|
-
if (env.PUPPETEER_EXECUTABLE_PATH) return env.PUPPETEER_EXECUTABLE_PATH;
|
|
99
|
-
for (const candidate of CHROME_CANDIDATES) {
|
|
93
|
+
function firstExistingPath(paths = []) {
|
|
94
|
+
for (const candidate of paths) {
|
|
100
95
|
try {
|
|
101
96
|
if (fs.existsSync(candidate)) return candidate;
|
|
102
97
|
} catch {
|
|
@@ -106,6 +101,59 @@ export function resolvePuppeteerExecutable(env = process.env) {
|
|
|
106
101
|
return null;
|
|
107
102
|
}
|
|
108
103
|
|
|
104
|
+
function playwrightChromeCandidates(home = process.env.HOME || '') {
|
|
105
|
+
if (!home) return [];
|
|
106
|
+
const cacheRoot = path.join(home, 'Library', 'Caches', 'ms-playwright');
|
|
107
|
+
let entries = [];
|
|
108
|
+
try {
|
|
109
|
+
entries = fs.readdirSync(cacheRoot, { withFileTypes: true });
|
|
110
|
+
} catch {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
entries = entries
|
|
114
|
+
.filter((entry) => entry.isDirectory())
|
|
115
|
+
.sort((a, b) => {
|
|
116
|
+
const aHeadless = a.name.startsWith('chromium_headless_shell-') ? 0 : 1;
|
|
117
|
+
const bHeadless = b.name.startsWith('chromium_headless_shell-') ? 0 : 1;
|
|
118
|
+
if (aHeadless !== bHeadless) return aHeadless - bHeadless;
|
|
119
|
+
const aVer = Number((a.name.match(/-(\d+)/) || [])[1] || 0);
|
|
120
|
+
const bVer = Number((b.name.match(/-(\d+)/) || [])[1] || 0);
|
|
121
|
+
return bVer - aVer;
|
|
122
|
+
});
|
|
123
|
+
const candidates = [];
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
const base = path.join(cacheRoot, entry.name);
|
|
126
|
+
if (entry.name.startsWith('chromium_headless_shell-')) {
|
|
127
|
+
candidates.push(path.join(base, 'chrome-headless-shell-mac-arm64', 'chrome-headless-shell'));
|
|
128
|
+
candidates.push(path.join(base, 'chrome-headless-shell-mac', 'chrome-headless-shell'));
|
|
129
|
+
}
|
|
130
|
+
if (entry.name.startsWith('chromium-')) {
|
|
131
|
+
candidates.push(path.join(base, 'chrome-mac-arm64', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'));
|
|
132
|
+
candidates.push(path.join(base, 'chrome-mac-arm64', 'chrome'));
|
|
133
|
+
candidates.push(path.join(base, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'));
|
|
134
|
+
candidates.push(path.join(base, 'chrome-mac', 'chrome'));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return candidates;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function chromeCandidates(env = process.env) {
|
|
141
|
+
return [
|
|
142
|
+
...playwrightChromeCandidates(env.HOME),
|
|
143
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
144
|
+
'/Applications/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing',
|
|
145
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
146
|
+
'/usr/bin/google-chrome',
|
|
147
|
+
'/usr/bin/chromium',
|
|
148
|
+
'/usr/bin/chromium-browser',
|
|
149
|
+
];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function resolvePuppeteerExecutable(env = process.env) {
|
|
153
|
+
if (env.PUPPETEER_EXECUTABLE_PATH) return env.PUPPETEER_EXECUTABLE_PATH;
|
|
154
|
+
return firstExistingPath(chromeCandidates(env));
|
|
155
|
+
}
|
|
156
|
+
|
|
109
157
|
export function injectMermaidBrandTheme(code) {
|
|
110
158
|
const body = String(code || '').trim();
|
|
111
159
|
if (!body) return body;
|
|
@@ -170,6 +218,7 @@ export function buildDistributionDiagramEnv(baseEnv = process.env) {
|
|
|
170
218
|
CONSTRUCT_MERMAID_WIDTH: DISTRIBUTION_MERMAID_WIDTH,
|
|
171
219
|
CONSTRUCT_MERMAID_SCALE: DISTRIBUTION_MERMAID_SCALE,
|
|
172
220
|
};
|
|
221
|
+
if (fs.existsSync(MERMAID_PPTR_CONFIG)) env.CONSTRUCT_MERMAID_PPTR_CONFIG = MERMAID_PPTR_CONFIG;
|
|
173
222
|
const chrome = resolvePuppeteerExecutable(baseEnv);
|
|
174
223
|
if (chrome) env.PUPPETEER_EXECUTABLE_PATH = chrome;
|
|
175
224
|
return env;
|
package/lib/doctor/cli.mjs
CHANGED
|
@@ -101,16 +101,26 @@ export async function runCli(args) {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
if (sub === 'consistency') {
|
|
104
|
+
const strict = args.some((a) => a === '--strict' || a === '--all' || a === '--debug');
|
|
104
105
|
const { runAllChecks } = await import('./watchers/consistency.mjs');
|
|
105
106
|
const result = await runAllChecks();
|
|
106
107
|
const blocking = result.findings.filter((f) => f.severity === 'blocking');
|
|
107
108
|
const warnings = result.findings.filter((f) => f.severity === 'warning');
|
|
108
109
|
|
|
110
|
+
// Default output carries only user-actionable signal; package/maintainer drift
|
|
111
|
+
// (tier 'internal') is gated behind --strict so a clean install reads clean.
|
|
112
|
+
|
|
113
|
+
const visibleWarnings = strict ? warnings : warnings.filter((f) => f.tier !== 'internal');
|
|
114
|
+
const internalWarnings = warnings.filter((f) => f.tier === 'internal');
|
|
115
|
+
|
|
109
116
|
for (const p of result.passed) console.log(` ✓ ${p.category.padEnd(18)} ${p.summary}`);
|
|
110
|
-
for (const w of
|
|
117
|
+
for (const w of visibleWarnings) console.log(` ⚠ ${w.category.padEnd(18)} ${w.summary}`);
|
|
111
118
|
for (const b of blocking) console.log(` ✗ ${b.category.padEnd(18)} ${b.summary}`);
|
|
112
119
|
|
|
113
|
-
console.log(`\n${result.passed.length} category(s) clean, ${
|
|
120
|
+
console.log(`\n${result.passed.length} category(s) clean, ${visibleWarnings.length} warning(s), ${blocking.length} blocking finding(s)`);
|
|
121
|
+
if (!strict && internalWarnings.length > 0) {
|
|
122
|
+
console.log(` (+${internalWarnings.length} package-internal diagnostic(s) — run \`construct doctor consistency --strict\` to view)`);
|
|
123
|
+
}
|
|
114
124
|
return blocking.length > 0 ? 1 : 0;
|
|
115
125
|
}
|
|
116
126
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* lib/doctor/source-checkout.mjs — distinguish Construct source tree vs npm install.
|
|
3
3
|
*
|
|
4
4
|
* `isConstructPackageRepo` is true for both checkouts and consumer installs.
|
|
5
|
-
* Source-only doctor checks (
|
|
6
|
-
*
|
|
5
|
+
* Source-only doctor checks (certification role cards) should run only when this
|
|
6
|
+
* returns true.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import fs from 'node:fs';
|
|
@@ -11,6 +11,5 @@ import path from 'node:path';
|
|
|
11
11
|
|
|
12
12
|
export function isConstructSourceCheckout(rootDir) {
|
|
13
13
|
const root = path.resolve(rootDir);
|
|
14
|
-
return fs.existsSync(path.join(root, '
|
|
15
|
-
|| fs.existsSync(path.join(root, 'tests', 'certification', 'specialists'));
|
|
14
|
+
return fs.existsSync(path.join(root, 'tests', 'certification', 'specialists'));
|
|
16
15
|
}
|