@geraldmaron/construct 1.4.1 → 1.5.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/.env.example +36 -0
- package/README.md +41 -7
- package/bin/construct +1029 -65
- package/bin/construct-postinstall.mjs +27 -2
- package/config/tag-vocabulary.json +264 -0
- package/examples/distribution/sources/deck-one-pager.md +1 -1
- package/lib/acp/server.mjs +21 -7
- package/lib/adapters-sync.mjs +2 -1
- package/lib/audit-trail.mjs +185 -2
- package/lib/beads/auto-close.mjs +2 -1
- package/lib/beads/drift.mjs +2 -1
- package/lib/bridges/copilot-proxy.mjs +20 -5
- package/lib/certification/skill-inventory.mjs +10 -1
- package/lib/cli/approvals.mjs +147 -0
- package/lib/cli-commands.mjs +105 -14
- package/lib/comment-lint.mjs +127 -8
- package/lib/config/schema.mjs +7 -30
- package/lib/config/source-target-registry.mjs +70 -0
- package/lib/config/source-targets.mjs +179 -205
- package/lib/contracts/coverage.mjs +77 -0
- package/lib/contracts/validate.mjs +102 -13
- package/lib/contracts/violation-log.mjs +50 -4
- package/lib/db/migrate.mjs +69 -0
- package/lib/db/migrations/001_orchestration_runs.sql +9 -0
- package/lib/db/migrations/002_queue_provider.sql +50 -0
- package/lib/db/migrations/003_worker_registry.sql +17 -0
- package/lib/db/migrations/004_trace_events.sql +16 -0
- package/lib/db/migrations/005_shared_memory.sql +15 -0
- package/lib/db/migrations/006_orchestration_runs_tenant.sql +5 -0
- package/lib/decisions/enforced-baseline.json +0 -2
- package/lib/decisions/registry.mjs +3 -2
- package/lib/deployment/parity-contract.mjs +1 -1
- package/lib/deployment-mode.mjs +78 -2
- package/lib/diagram-export.mjs +10 -1
- package/lib/distill.mjs +5 -2
- package/lib/docs-verify.mjs +2 -1
- package/lib/doctor/cli.mjs +1 -0
- package/lib/doctor/command-on-path.mjs +24 -0
- package/lib/doctor/diagnosis.mjs +109 -0
- package/lib/doctor/embedding-health.mjs +50 -0
- package/lib/doctor/engine-health.mjs +93 -0
- package/lib/doctor/graph-validate.mjs +47 -0
- package/lib/doctor/index.mjs +23 -4
- package/lib/doctor/sidecar-providers.mjs +56 -0
- package/lib/doctor/watchers/consistency.mjs +93 -1
- package/lib/doctor/watchers/cx-budget.mjs +1 -1
- package/lib/doctor/watchers/graph-staleness.mjs +1 -1
- package/lib/doctor/watchers/mcp-protocol.mjs +17 -0
- package/lib/doctor/watchers/oracle-liveness.mjs +92 -0
- package/lib/doctor/watchers/orchestration-runs.mjs +108 -0
- package/lib/doctor/watchers/provider-breaker.mjs +78 -0
- package/lib/document-export.mjs +52 -27
- package/lib/document-extract/docling-client.mjs +9 -5
- package/lib/document-extract/docling-sidecar.py +30 -0
- package/lib/document-extract.mjs +1 -1
- package/lib/document-ingest.mjs +9 -0
- package/lib/embed/approval-queue.mjs +184 -88
- package/lib/embed/authority-guard.mjs +65 -2
- package/lib/embed/capability-jobs.mjs +365 -0
- package/lib/embed/capability-lifecycle.mjs +219 -0
- package/lib/embed/capability-loader.mjs +303 -0
- package/lib/embed/capability-runtime.mjs +58 -0
- package/lib/embed/cli.mjs +185 -8
- package/lib/embed/config.mjs +4 -0
- package/lib/embed/daemon.mjs +125 -6
- package/lib/embed/demand-fetch.mjs +190 -54
- package/lib/embed/inbox.mjs +12 -10
- package/lib/embed/presets/ops-triage.mjs +236 -0
- package/lib/embed/presets/pm-feedback.mjs +341 -0
- package/lib/embed/presets/tpm.mjs +401 -0
- package/lib/embed/providers/jira.mjs +72 -1
- package/lib/embed/providers/registry.mjs +140 -33
- package/lib/embed/worker.mjs +5 -0
- package/lib/embedded-contract/capability.mjs +4 -0
- package/lib/embedded-contract/execution.mjs +1 -1
- package/lib/embedded-contract/model-resolve.mjs +53 -3
- package/lib/embedded-contract/workflow-defs.mjs +48 -73
- package/lib/embedded-contract/workflow-invoke.mjs +144 -4
- package/lib/embedded-contract/workflows/architecture-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/data-structure.manifest.json +14 -0
- package/lib/embedded-contract/workflows/evidence-ingest.manifest.json +14 -0
- package/lib/embedded-contract/workflows/memo-draft.manifest.json +14 -0
- package/lib/embedded-contract/workflows/operations-triage.manifest.json +18 -0
- package/lib/embedded-contract/workflows/operations.manifest.json +18 -0
- package/lib/embedded-contract/workflows/pm-feedback.manifest.json +18 -0
- package/lib/embedded-contract/workflows/prd-draft.manifest.json +15 -0
- package/lib/embedded-contract/workflows/proposal-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/research-synthesis.manifest.json +14 -0
- package/lib/embedded-contract/workflows/risk-review.manifest.json +15 -0
- package/lib/embedded-contract/workflows/structure-notes.manifest.json +14 -0
- package/lib/embedded-contract/workflows/transcript-process.manifest.json +14 -0
- package/lib/embedded-contract/workflows/triage.manifest.json +14 -0
- package/lib/env-config.mjs +60 -11
- package/lib/export-validate.mjs +34 -2
- package/lib/extensions/index.mjs +27 -0
- package/lib/extensions/loader.mjs +120 -0
- package/lib/extensions/manifest-schema.mjs +141 -0
- package/lib/extensions/manifests/anthropic.manifest.json +12 -0
- package/lib/extensions/manifests/atlassian-confluence.manifest.json +12 -0
- package/lib/extensions/manifests/atlassian-jira.manifest.json +53 -0
- package/lib/extensions/manifests/directory.manifest.json +12 -0
- package/lib/extensions/manifests/docling.manifest.json +37 -0
- package/lib/extensions/manifests/echo.manifest.json +8 -0
- package/lib/extensions/manifests/feedback.manifest.json +12 -0
- package/lib/extensions/manifests/github-copilot.manifest.json +12 -0
- package/lib/extensions/manifests/github.manifest.json +52 -0
- package/lib/extensions/manifests/linear.manifest.json +50 -0
- package/lib/extensions/manifests/local.manifest.json +12 -0
- package/lib/extensions/manifests/ollama.manifest.json +12 -0
- package/lib/extensions/manifests/openai.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-anthropic.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-deepseek.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-google.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-llama.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter-qwen.manifest.json +12 -0
- package/lib/extensions/manifests/openrouter.manifest.json +12 -0
- package/lib/extensions/manifests/postgres.manifest.json +12 -0
- package/lib/extensions/manifests/salesforce.manifest.json +12 -0
- package/lib/extensions/manifests/slack.manifest.json +58 -0
- package/lib/extensions/manifests/whisper.manifest.json +36 -0
- package/lib/extensions/validate.mjs +175 -0
- package/lib/features.mjs +13 -9
- package/lib/flows/checkpoint.mjs +184 -0
- package/lib/flows/constants.mjs +27 -0
- package/lib/flows/define.mjs +146 -0
- package/lib/flows/engine.mjs +249 -0
- package/lib/flows/errors.mjs +19 -0
- package/lib/flows/index.mjs +27 -0
- package/lib/flows/joins.mjs +18 -0
- package/lib/flows/schema.mjs +90 -0
- package/lib/flows/state.mjs +31 -0
- package/lib/frameworks/loader.mjs +99 -0
- package/lib/frameworks/schema.mjs +157 -0
- package/lib/graph/build-from-corpus.mjs +67 -0
- package/lib/graph/build-from-embed.mjs +82 -0
- package/lib/graph/build-from-registry.mjs +164 -3
- package/lib/graph/cli.mjs +456 -12
- package/lib/graph/gap-queries.mjs +156 -0
- package/lib/graph/gaps.mjs +41 -0
- package/lib/graph/impacted.mjs +129 -0
- package/lib/graph/runtime-evidence.mjs +177 -0
- package/lib/graph/security-coverage.mjs +113 -0
- package/lib/graph/staleness.mjs +241 -10
- package/lib/graph/store.mjs +24 -7
- package/lib/graph/validate.mjs +161 -0
- package/lib/headhunt.mjs +9 -8
- package/lib/health-check.mjs +15 -7
- package/lib/hook-health.mjs +1 -1
- package/lib/hooks/agent-tracker.mjs +10 -4
- package/lib/hooks/edit-guard.mjs +3 -3
- package/lib/hooks/graph-impact-advisory.mjs +2 -2
- package/lib/hooks/guard-bash.mjs +41 -15
- package/lib/hooks/mcp-health-check.mjs +11 -4
- package/lib/hooks/model-fallback.mjs +50 -6
- package/lib/hooks/orchestration-dispatch-guard.mjs +14 -3
- package/lib/hooks/pre-compact.mjs +181 -173
- package/lib/hooks/rule-verifier.mjs +2 -1
- package/lib/hooks/session-reflect.mjs +2 -1
- package/lib/hooks/session-start.mjs +3 -3
- package/lib/host/readiness.mjs +109 -0
- package/lib/host-capabilities.mjs +13 -2
- package/lib/host-disposition.mjs +29 -8
- package/lib/identity.mjs +92 -0
- package/lib/ingest/degraded-extract.mjs +96 -0
- package/lib/ingest/docling-remote.mjs +2 -1
- package/lib/ingest/provider-extract.mjs +7 -19
- package/lib/ingest/sidecar-providers.mjs +196 -0
- package/lib/ingest-tooling.mjs +11 -5
- package/lib/init-unified.mjs +55 -38
- package/lib/init-update.mjs +2 -1
- package/lib/install/legacy-global-cleanup.mjs +25 -0
- package/lib/install/stage-project.mjs +41 -4
- package/lib/intake/daemon.mjs +99 -8
- package/lib/intake/git-queue.mjs +110 -38
- package/lib/intake/prepare.mjs +2 -0
- package/lib/intake/queue-registry.mjs +50 -0
- package/lib/intake/queue.mjs +133 -17
- package/lib/intake/session-prelude.mjs +57 -8
- package/lib/integrations/intake-integrations.mjs +61 -111
- package/lib/intent-classifier.mjs +43 -5
- package/lib/libreoffice-export.mjs +8 -8
- package/lib/logging/rotate.mjs +5 -4
- package/lib/mcp/broker.mjs +332 -17
- package/lib/mcp/denied-store.mjs +95 -0
- package/lib/mcp/destructive-approval.mjs +57 -0
- package/lib/mcp/destructive-gate.mjs +30 -0
- package/lib/mcp/dispatch-envelope.mjs +199 -0
- package/lib/mcp/memory-bridge.mjs +2 -1
- package/lib/mcp/server.mjs +185 -1268
- package/lib/mcp/tool-definitions-memory.mjs +376 -0
- package/lib/mcp/tool-definitions-project.mjs +271 -0
- package/lib/mcp/tool-definitions-skills.mjs +311 -0
- package/lib/mcp/tool-definitions-workflow.mjs +398 -0
- package/lib/mcp/tool-definitions.mjs +25 -0
- package/lib/mcp/tool-rate-limit.mjs +47 -0
- package/lib/mcp/tool-registry.mjs +107 -0
- package/lib/mcp/tool-safety.mjs +95 -0
- package/lib/mcp/tool-surface-parity.mjs +60 -0
- package/lib/mcp/tools/orchestration-delegation-next.tool.mjs +68 -0
- package/lib/mcp/tools/orchestration-run.mjs +197 -19
- package/lib/mcp/tools/orchestration-task-result.tool.mjs +77 -0
- package/lib/mcp/tools/project.mjs +25 -8
- package/lib/mcp/tools/provider-write.mjs +187 -0
- package/lib/mcp/tools/scope.mjs +0 -3
- package/lib/mcp/tools/skills.mjs +1 -1
- package/lib/mcp/tools/storage.mjs +2 -2
- package/lib/mcp/tools/web-search-governance.mjs +96 -0
- package/lib/mcp/tools/web-search.mjs +5 -76
- package/lib/mcp/transport/auth.mjs +238 -0
- package/lib/mcp/transport/http.mjs +136 -0
- package/lib/mcp/transport/mode.mjs +31 -0
- package/lib/mcp/transport/stdio.mjs +22 -0
- package/lib/mcp-catalog.json +4 -4
- package/lib/mcp-manager.mjs +34 -23
- package/lib/mcp-platform-config.mjs +53 -20
- package/lib/mode-capabilities.mjs +109 -0
- package/lib/model-router.mjs +42 -9
- package/lib/models/catalog.mjs +40 -1
- package/lib/net-guard.mjs +247 -0
- package/lib/observation-store.mjs +6 -2
- package/lib/ollama/provision-context.mjs +2 -1
- package/lib/opencode-config.mjs +22 -3
- package/lib/opencode-runtime-plugin.mjs +120 -2
- package/lib/oracle/actions.mjs +204 -10
- package/lib/oracle/cli.mjs +24 -3
- package/lib/oracle/daemon-entry.mjs +6 -0
- package/lib/oracle/dispatch.mjs +2 -1
- package/lib/oracle/execute.mjs +2 -2
- package/lib/oracle/gaps.mjs +3 -3
- package/lib/oracle/heartbeat.mjs +53 -0
- package/lib/oracle/read-model.mjs +69 -13
- package/lib/oracle/reconcile.mjs +3 -46
- package/lib/oracle/routing.mjs +37 -31
- package/lib/oracle/synthesize.mjs +1 -1
- package/lib/orchestration/classification.mjs +434 -0
- package/lib/orchestration/delegation-flow.mjs +132 -0
- package/lib/orchestration/flow-selection.mjs +418 -0
- package/lib/orchestration/gates.mjs +244 -0
- package/lib/orchestration/host-sampling.mjs +121 -0
- package/lib/orchestration/policy-constants.mjs +48 -0
- package/lib/orchestration/provider-outcome.mjs +197 -0
- package/lib/orchestration/readiness.mjs +114 -13
- package/lib/orchestration/run-store-postgres.mjs +32 -26
- package/lib/orchestration/run-store-sqlite.mjs +8 -14
- package/lib/orchestration/run-store.mjs +25 -12
- package/lib/orchestration/runtime.mjs +508 -62
- package/lib/orchestration/store.mjs +87 -12
- package/lib/orchestration/trace-store.mjs +125 -0
- package/lib/orchestration/web-capability.mjs +60 -0
- package/lib/orchestration/worker-runtime.mjs +162 -0
- package/lib/orchestration/worker.mjs +763 -80
- package/lib/orchestration-policy.mjs +67 -1111
- package/lib/output-quality.mjs +61 -2
- package/lib/packs/cli.mjs +144 -0
- package/lib/packs/core-pack.mjs +112 -0
- package/lib/packs/enablement.mjs +187 -0
- package/lib/packs/index.mjs +23 -0
- package/lib/packs/loader.mjs +176 -0
- package/lib/packs/manifest-schema.mjs +58 -0
- package/lib/packs/prompts.mjs +120 -0
- package/lib/packs/validate.mjs +208 -0
- package/lib/path-policy.mjs +56 -0
- package/lib/plugin-registry.mjs +4 -5
- package/lib/policy/audit-gate.mjs +42 -0
- package/lib/policy/consumption-budget.mjs +149 -0
- package/lib/policy/engine.mjs +81 -6
- package/lib/policy/role-authority.mjs +89 -0
- package/lib/prompt-composer.js +19 -3
- package/lib/providers/contract/adapters/confluence/governed-write.mjs +215 -0
- package/lib/providers/contract/adapters/confluence/manifest.json +17 -0
- package/lib/providers/contract/adapters/confluence/transport.mjs +135 -0
- package/lib/providers/contract/adapters/github/governed-write.mjs +121 -0
- package/lib/providers/contract/adapters/github/index.mjs +38 -3
- package/lib/providers/contract/adapters/jira/adf.mjs +151 -0
- package/lib/providers/contract/adapters/jira/createmeta.mjs +143 -0
- package/lib/providers/contract/adapters/jira/governed-write.mjs +182 -0
- package/lib/providers/contract/adapters/jira/manifest.json +17 -0
- package/lib/providers/contract/adapters/jira/transport.mjs +119 -0
- package/lib/providers/contract.mjs +207 -0
- package/lib/providers/credential-bootstrap.mjs +7 -4
- package/lib/providers/credential-sources.mjs +14 -2
- package/lib/providers/directory/index.mjs +261 -0
- package/lib/providers/feedback/index.mjs +392 -0
- package/lib/providers/filter-audit.mjs +68 -0
- package/lib/providers/filter-schema.mjs +54 -0
- package/lib/providers/github/index.mjs +31 -0
- package/lib/providers/instance-config.mjs +215 -0
- package/lib/providers/op-locate.mjs +96 -0
- package/lib/providers/op-run.mjs +64 -9
- package/lib/providers/registry.mjs +26 -3
- package/lib/providers/secret-audit-wiring.mjs +41 -18
- package/lib/providers/secret-resolver.mjs +263 -31
- package/lib/publish-template.mjs +6 -3
- package/lib/publish-tooling.mjs +4 -0
- package/lib/publish.mjs +32 -4
- package/lib/queue/pg-queue.mjs +395 -0
- package/lib/reflect.mjs +2 -1
- package/lib/registry/assemble.mjs +28 -2
- package/lib/registry/catalog.mjs +6 -0
- package/lib/registry/consolidation.mjs +8 -1
- package/lib/registry/custom-scaffold.mjs +200 -0
- package/lib/registry/custom-schema.mjs +137 -0
- package/lib/registry/loader.mjs +15 -4
- package/lib/registry/manifests/format-engines.default.json +15 -0
- package/lib/registry/manifests/surface-map.default.json +46 -0
- package/lib/registry/retired-paths.mjs +1 -0
- package/lib/registry/surface-map.mjs +100 -50
- package/lib/registry/validate.mjs +3 -3
- package/lib/render-visual-check.mjs +240 -0
- package/lib/resources/budget.mjs +40 -17
- package/lib/roles/flavor-bindings.mjs +36 -14
- package/lib/roles/gateway.mjs +15 -8
- package/lib/roots.mjs +107 -0
- package/lib/runtime/uv-bootstrap.mjs +32 -6
- package/lib/runtime/whisper-bootstrap.mjs +11 -3
- package/lib/runtime-env.mjs +5 -2
- package/lib/sandbox.mjs +1 -1
- package/lib/scheduler/index.mjs +8 -20
- package/lib/schema-infer.mjs +31 -2
- package/lib/scopes/lifecycle.mjs +29 -25
- package/lib/scopes/loader.mjs +49 -12
- package/lib/scopes/teams.mjs +1 -1
- package/lib/security/ingest-boundary.mjs +80 -0
- package/lib/security/recall-wrapper.mjs +99 -0
- package/lib/security/trust.mjs +132 -0
- package/lib/service-manager.mjs +93 -24
- package/lib/setup.mjs +41 -23
- package/lib/skills-apply.mjs +4 -2
- package/lib/specialists/postconditions.mjs +2 -2
- package/lib/state-root.mjs +147 -0
- package/lib/status.mjs +597 -6
- package/lib/storage/admin.mjs +84 -7
- package/lib/storage/backend-registry.mjs +73 -0
- package/lib/storage/backend.mjs +63 -9
- package/lib/storage/embeddings-openai.mjs +12 -2
- package/lib/storage/hybrid-query.mjs +11 -3
- package/lib/storage/retrieval-hardening.mjs +384 -0
- package/lib/storage/shared-memory.mjs +158 -0
- package/lib/storage/vector-client.mjs +69 -2
- package/lib/team/health.mjs +72 -0
- package/lib/telemetry/backends/local.mjs +9 -3
- package/lib/telemetry/client.mjs +3 -7
- package/lib/template-registry.mjs +10 -12
- package/lib/tenant/context.mjs +82 -0
- package/lib/tenant/isolation.mjs +129 -0
- package/lib/test-corpus-inventory.mjs +103 -2
- package/lib/uninstall/uninstall.mjs +78 -12
- package/lib/validator.mjs +4 -6
- package/lib/worker/entrypoint.mjs +2 -1
- package/lib/worker/run.mjs +2 -2
- package/lib/worker/trace.mjs +5 -11
- package/lib/workflow-state.mjs +52 -8
- package/lib/workflows/liveness.mjs +203 -0
- package/lib/workflows/loader.mjs +177 -0
- package/lib/workflows/manifest-schema.mjs +71 -0
- package/lib/workflows/surface-parity.mjs +118 -0
- package/lib/workflows/validate.mjs +127 -0
- package/lib/writes/control-plane.mjs +140 -0
- package/lib/writes/envelope.mjs +206 -0
- package/lib/writes/sent-log.mjs +86 -0
- package/lib/writes/write-intent.mjs +109 -0
- package/package.json +20 -7
- package/personas/construct.md +12 -3
- package/registry/agent-manifest.json +117 -0
- package/registry/capabilities.json +1987 -0
- package/rules/common/comments.md +1 -0
- package/schemas/brand-voice.schema.json +24 -0
- package/schemas/capability-registry.schema.json +72 -0
- package/schemas/certification-run.schema.json +130 -0
- package/schemas/demo-recording.schema.json +46 -0
- package/schemas/eval-dataset.schema.json +79 -0
- package/schemas/execution-capability-profile.schema.json +46 -0
- package/schemas/execution-policy.schema.json +114 -0
- package/schemas/improvement-proposal.schema.json +65 -0
- package/schemas/mcp-tool-output.schema.json +61 -0
- package/schemas/platform-capabilities.schema.json +83 -0
- package/schemas/project-config.schema.json +215 -0
- package/schemas/project-demo.schema.json +60 -0
- package/schemas/provider-behavior-matrix.schema.json +91 -0
- package/schemas/scope.schema.json +197 -0
- package/schemas/specialist-trace.schema.json +107 -0
- package/schemas/team.schema.json +99 -0
- package/schemas/unified-registry.schema.json +546 -0
- package/scripts/sync-specialists.mjs +336 -106
- package/skills/docs/adr-workflow.md +1 -1
- package/skills/docs/codebase-research-workflow.md +3 -3
- package/skills/docs/prd-workflow.md +5 -6
- package/skills/docs/runbook-workflow.md +2 -2
- package/skills/docs/user-research-workflow.md +3 -3
- package/skills/operating/fleet-health-routing.md +77 -0
- package/skills/roles/ai-engineer.md +1 -1
- package/skills/roles/architect.md +0 -1
- package/skills/roles/business-strategist.md +1 -1
- package/skills/roles/data-analyst.telemetry.md +1 -1
- package/skills/roles/data-engineer.md +1 -1
- package/skills/roles/data-engineer.pipeline.md +1 -1
- package/skills/roles/data-engineer.vector-retrieval.md +1 -2
- package/skills/roles/data-engineer.warehouse.md +1 -1
- package/skills/roles/designer.accessibility.md +1 -1
- package/skills/roles/designer.md +0 -1
- package/skills/roles/devil-advocate.md +1 -1
- package/skills/roles/docs-keeper.md +1 -1
- package/skills/roles/evaluator.md +1 -1
- package/skills/roles/explorer.md +1 -1
- package/skills/roles/platform-engineer.md +1 -1
- package/skills/roles/qa.ai-eval.md +1 -2
- package/skills/roles/qa.api-contract.md +0 -1
- package/skills/roles/qa.data-pipeline.md +0 -1
- package/skills/roles/qa.md +0 -1
- package/skills/roles/qa.web-ui.md +0 -1
- package/skills/roles/release-manager.md +1 -1
- package/skills/roles/researcher.md +0 -2
- package/skills/roles/reviewer.md +0 -3
- package/skills/roles/security.ai.md +1 -1
- package/skills/roles/security.legal-compliance.md +1 -1
- package/skills/roles/security.md +0 -1
- package/skills/roles/security.privacy.md +0 -1
- package/skills/roles/security.supply-chain.md +1 -1
- package/skills/roles/sre.md +1 -1
- package/skills/roles/test-automation.md +1 -1
- package/skills/roles/trace-reviewer.md +1 -1
- package/skills/roles/ux-researcher.md +1 -1
- package/specialists/artifact-manifest.json +36 -36
- package/specialists/org/contracts/accessibility-to-qa.json +11 -3
- package/specialists/org/contracts/any-to-business-strategist.json +19 -7
- package/specialists/org/contracts/any-to-debugger.json +7 -1
- package/specialists/org/contracts/any-to-designer.json +7 -1
- package/specialists/org/contracts/any-to-docs-keeper.json +18 -4
- package/specialists/org/contracts/any-to-explorer.json +13 -4
- package/specialists/org/contracts/any-to-sre-incident.json +6 -2
- package/specialists/org/contracts/any-to-trace-reviewer.json +16 -4
- package/specialists/org/contracts/architect-to-ai-engineer.json +6 -2
- package/specialists/org/contracts/architect-to-data-engineer.json +17 -5
- package/specialists/org/contracts/architect-to-devil-advocate.json +11 -3
- package/specialists/org/contracts/architect-to-engineer.json +20 -4
- package/specialists/org/contracts/architect-to-evaluator.json +15 -5
- package/specialists/org/contracts/architect-to-legal-compliance.json +15 -5
- package/specialists/org/contracts/architect-to-operations.json +17 -4
- package/specialists/org/contracts/architect-to-platform-engineer.json +20 -4
- package/specialists/org/contracts/construct-to-orchestrator.json +10 -2
- package/specialists/org/contracts/data-analyst-to-product-manager.json +11 -2
- package/specialists/org/contracts/engineer-to-qa.json +20 -4
- package/specialists/org/contracts/engineer-to-reviewer.json +29 -5
- package/specialists/org/contracts/explorer-to-engineer.json +11 -3
- package/specialists/org/contracts/legal-compliance-to-release-manager.json +12 -4
- package/specialists/org/contracts/operations-to-user.json +53 -0
- package/specialists/org/contracts/operations-triage-output.json +53 -0
- package/specialists/org/contracts/pm-requirements-candidates.json +53 -0
- package/specialists/org/contracts/product-manager-to-architect.json +30 -10
- package/specialists/org/contracts/product-manager-to-data-analyst.json +13 -3
- package/specialists/org/contracts/product-manager-to-ux-researcher.json +15 -5
- package/specialists/org/contracts/qa-to-release-manager.json +11 -3
- package/specialists/org/contracts/researcher-to-architect.json +10 -2
- package/specialists/org/contracts/researcher-to-product-manager.json +16 -5
- package/specialists/org/contracts/reviewer-to-security.json +17 -3
- package/specialists/org/contracts/test-automation-to-engineer.json +11 -3
- package/specialists/org/contracts/trace-reviewer-to-sre.json +12 -4
- package/specialists/org/contracts/user-to-construct.json +11 -4
- package/specialists/org/frameworks/cx-architect-constraint-option-failure.md +66 -0
- package/specialists/org/frameworks/cx-engineer-feasibility-blast-radius.md +66 -0
- package/specialists/org/frameworks/cx-ops-dependency-sequencing.md +74 -0
- package/specialists/org/frameworks/cx-pm-value-tradeoff.md +66 -0
- package/specialists/org/frameworks/cx-qa-risk-based-coverage.md +69 -0
- package/specialists/org/groups/engineering-group.json +2 -6
- package/specialists/org/groups/governance-group.json +2 -3
- package/specialists/org/groups/operations-group.json +5 -8
- package/specialists/org/groups/product-group.json +4 -8
- package/specialists/org/groups/quality-group.json +3 -7
- package/specialists/org/groups/strategy-group.json +6 -9
- package/specialists/org/models.json.example +8 -0
- package/specialists/org/scopes/creative.json +6 -1
- package/specialists/org/scopes/operations.json +7 -1
- package/specialists/org/scopes/research.json +6 -1
- package/specialists/org/scopes/rnd.json +7 -1
- package/specialists/org/specialists/cx-architect.json +27 -8
- package/specialists/org/specialists/cx-designer.json +22 -8
- package/specialists/org/specialists/cx-engineer.json +71 -7
- package/specialists/org/specialists/cx-operations.json +89 -15
- package/specialists/org/specialists/cx-orchestrator.json +16 -4
- package/specialists/org/specialists/cx-product-manager.json +28 -9
- package/specialists/org/specialists/cx-qa.json +16 -6
- package/specialists/org/specialists/cx-researcher.json +41 -7
- package/specialists/org/specialists/cx-reviewer.json +61 -11
- package/specialists/org/specialists/cx-security.json +30 -10
- package/specialists/org/teams/design-team.json +3 -4
- package/specialists/org/teams/engineering-team.json +3 -10
- package/specialists/org/teams/governance-team.json +3 -5
- package/specialists/org/teams/operations-team.json +6 -12
- package/specialists/org/teams/product-management-team.json +2 -3
- package/specialists/org/teams/quality-team.json +4 -12
- package/specialists/org/teams/research-team.json +3 -3
- package/specialists/org/teams/strategy-team.json +7 -14
- package/specialists/prompts/cx-architect.md +20 -1
- package/specialists/prompts/cx-data-analyst.md +1 -1
- package/specialists/prompts/cx-designer.md +12 -4
- package/specialists/prompts/cx-engineer.md +15 -1
- package/specialists/prompts/cx-operations.md +14 -2
- package/specialists/prompts/cx-orchestrator.md +9 -5
- package/specialists/prompts/cx-product-manager.md +5 -1
- package/specialists/prompts/cx-qa.md +6 -2
- package/specialists/prompts/cx-researcher.md +27 -31
- package/specialists/prompts/cx-reviewer.md +19 -1
- package/specialists/prompts/cx-security.md +5 -1
- package/templates/distribution/construct-brand.typ +123 -59
- package/templates/distribution/construct-decision.typ +6 -3
- package/templates/distribution/construct-pdf.typ +11 -4
- package/templates/distribution/construct-prd.typ +6 -3
- package/templates/distribution/construct-research.typ +7 -4
- package/vendor/pandoc-ext/README.md +3 -0
- package/vendor/pandoc-ext/diagram.lua +687 -0
- package/lib/providers/contract/adapters/git/index.mjs +0 -115
- package/lib/providers/contract/adapters/slack/index.mjs +0 -175
- package/specialists/org/contracts/business-strategist-to-product-manager.json +0 -39
- package/specialists/org/contracts/construct-to-rd-lead.json +0 -53
- package/specialists/org/contracts/data-engineer-to-platform-engineer.json +0 -36
- package/specialists/org/contracts/designer-to-accessibility.json +0 -36
- package/specialists/org/contracts/platform-engineer-to-engineer.json +0 -31
- package/specialists/org/contracts/qa-to-test-automation.json +0 -42
- package/specialists/org/contracts/rd-lead-to-architect.json +0 -38
- package/specialists/org/contracts/sre-to-release-manager.json +0 -36
- package/specialists/org/specialists/cx-accessibility.json +0 -69
- package/specialists/org/specialists/cx-ai-engineer.json +0 -75
- package/specialists/org/specialists/cx-business-strategist.json +0 -72
- package/specialists/org/specialists/cx-data-engineer.json +0 -71
- package/specialists/org/specialists/cx-devil-advocate.json +0 -71
- package/specialists/org/specialists/cx-docs-keeper.json +0 -82
- package/specialists/org/specialists/cx-evaluator.json +0 -69
- package/specialists/org/specialists/cx-explorer.json +0 -69
- package/specialists/org/specialists/cx-legal-compliance.json +0 -74
- package/specialists/org/specialists/cx-oracle.json +0 -46
- package/specialists/org/specialists/cx-platform-engineer.json +0 -80
- package/specialists/org/specialists/cx-rd-lead.json +0 -73
- package/specialists/org/specialists/cx-release-manager.json +0 -77
- package/specialists/org/specialists/cx-sre.json +0 -94
- package/specialists/org/specialists/cx-test-automation.json +0 -69
- package/specialists/org/specialists/cx-trace-reviewer.json +0 -69
- package/specialists/org/specialists/cx-ux-researcher.json +0 -68
- package/specialists/org/teams/accessibility-team.json +0 -39
- package/specialists/org/teams/ux-research-team.json +0 -39
- package/specialists/prompts/cx-accessibility.md +0 -55
- package/specialists/prompts/cx-ai-engineer.md +0 -124
- package/specialists/prompts/cx-business-strategist.md +0 -58
- package/specialists/prompts/cx-data-engineer.md +0 -55
- package/specialists/prompts/cx-devil-advocate.md +0 -59
- package/specialists/prompts/cx-docs-keeper.md +0 -164
- package/specialists/prompts/cx-evaluator.md +0 -49
- package/specialists/prompts/cx-explorer.md +0 -71
- package/specialists/prompts/cx-legal-compliance.md +0 -58
- package/specialists/prompts/cx-oracle.md +0 -98
- package/specialists/prompts/cx-platform-engineer.md +0 -97
- package/specialists/prompts/cx-rd-lead.md +0 -59
- package/specialists/prompts/cx-release-manager.md +0 -54
- package/specialists/prompts/cx-sre.md +0 -111
- package/specialists/prompts/cx-test-automation.md +0 -55
- package/specialists/prompts/cx-trace-reviewer.md +0 -101
- package/specialists/prompts/cx-ux-researcher.md +0 -53
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/oracle/heartbeat.mjs — oracle producer liveness from the last-tick record.
|
|
3
|
+
*
|
|
4
|
+
* The oracle daemon records last-tick.json when a tick completes and idles itself
|
|
5
|
+
* out after a few no-work ticks, so a stale tick on its own is not death — it is a
|
|
6
|
+
* dead-producer signal only when oracle work is actually waiting (pending approvals
|
|
7
|
+
* or unaddressed gaps). Consumers therefore pair heartbeatFreshness with a pending
|
|
8
|
+
* count; this module owns only the age check. It is deliberately distinct from
|
|
9
|
+
* verdictFreshness in lib/intake/session-prelude.mjs, which ages the verdict's own
|
|
10
|
+
* `at` (is the answer current) rather than the producer's tick `at` (is anything
|
|
11
|
+
* still generating answers). formatAge is shared with the verdict path.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { readLastTick } from './index.mjs';
|
|
15
|
+
|
|
16
|
+
// Six missed 5-minute intervals clears the daemon's idle-shutdown window before a
|
|
17
|
+
// stale tick is treated as a stalled producer, so a briefly-quiet daemon is never
|
|
18
|
+
// mislabelled dead.
|
|
19
|
+
export const ORACLE_TICK_INTERVAL_MS = 5 * 60_000;
|
|
20
|
+
export const HEARTBEAT_STALE_MS = ORACLE_TICK_INTERVAL_MS * 6;
|
|
21
|
+
|
|
22
|
+
export function formatAge(ageMs) {
|
|
23
|
+
if (!Number.isFinite(ageMs)) return 'unknown';
|
|
24
|
+
const hours = Math.floor(ageMs / (60 * 60 * 1000));
|
|
25
|
+
if (hours < 1) return '<1h';
|
|
26
|
+
if (hours < 24) return `${hours}h`;
|
|
27
|
+
return `${Math.floor(hours / 24)}d`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Missing or unparseable `at` resolves to Infinity — stale, never fresh — so an
|
|
31
|
+
// absent tick record reads as a stalled producer rather than a healthy one.
|
|
32
|
+
|
|
33
|
+
export function heartbeatFreshness(lastTick, now = Date.now()) {
|
|
34
|
+
const at = lastTick?.at;
|
|
35
|
+
const parsed = at ? Date.parse(at) : NaN;
|
|
36
|
+
const ageMs = Number.isFinite(parsed) ? now - parsed : Infinity;
|
|
37
|
+
return {
|
|
38
|
+
ageMs,
|
|
39
|
+
stale: !Number.isFinite(ageMs) || ageMs > HEARTBEAT_STALE_MS,
|
|
40
|
+
asOf: Number.isFinite(parsed) ? new Date(parsed).toISOString() : null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Honors the oracle off-switch so a deliberately disabled daemon is never flagged.
|
|
45
|
+
|
|
46
|
+
export function readHeartbeatStatus({ homeDir, env = process.env } = {}) {
|
|
47
|
+
if (env?.CONSTRUCT_ORACLE === 'off' || env?.CONSTRUCT_ORACLE === '0') {
|
|
48
|
+
return { enabled: false, lastTick: null, ageMs: null, stale: false, asOf: null };
|
|
49
|
+
}
|
|
50
|
+
const lastTick = readLastTick(homeDir);
|
|
51
|
+
const { ageMs, stale, asOf } = heartbeatFreshness(lastTick);
|
|
52
|
+
return { enabled: true, lastTick, ageMs, stale, asOf };
|
|
53
|
+
}
|
|
@@ -22,7 +22,7 @@ import { collectArtifactGateSignals } from './artifact-gate.mjs';
|
|
|
22
22
|
import { loadGraph, nodesByType, dependentsOf } from '../graph/store.mjs';
|
|
23
23
|
import { hashFiles } from '../graph/build-from-registry.mjs';
|
|
24
24
|
import { GRAPH_SEED_FILES } from '../graph/staleness.mjs';
|
|
25
|
-
import {
|
|
25
|
+
import { recentViolations } from '../contracts/violation-log.mjs';
|
|
26
26
|
import { doctorRoot } from '../config/xdg.mjs';
|
|
27
27
|
|
|
28
28
|
const RECENT_MS = 24 * 60 * 60 * 1000;
|
|
@@ -109,14 +109,12 @@ function collectOutcomesSummary(projectDir) {
|
|
|
109
109
|
|
|
110
110
|
function collectContractViolations(projectDir) {
|
|
111
111
|
const file = path.join(projectDir, '.cx', 'contract-violations.jsonl');
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return true;
|
|
119
|
-
});
|
|
112
|
+
const recent = recentViolations({
|
|
113
|
+
windowMs: RECENT_MS,
|
|
114
|
+
repoRoot: projectDir,
|
|
115
|
+
excludeDevNoise: true,
|
|
116
|
+
limit: VIOLATION_LIMIT,
|
|
117
|
+
});
|
|
120
118
|
return {
|
|
121
119
|
present: fs.existsSync(file),
|
|
122
120
|
recentCount: recent.length,
|
|
@@ -243,7 +241,57 @@ function collectStructureSprawl(projectDir) {
|
|
|
243
241
|
// edge), and freshness (a capability whose realizing files changed after its
|
|
244
242
|
// lastValidated stamp). Never throws; an absent graph yields present:false.
|
|
245
243
|
|
|
246
|
-
|
|
244
|
+
// Freshness needs content identity, not mtime: any checkout, rebase, or touch
|
|
245
|
+
// rewrites file mtimes repo-wide without changing a single byte, so a pure
|
|
246
|
+
// mtime > stamp comparison flags every capability on every fresh clone. A
|
|
247
|
+
// file only "changed since lastValidated" if its working-tree bytes differ
|
|
248
|
+
// from HEAD (dirty edit) or a commit touching it landed after the stamp
|
|
249
|
+
// (`git log --since`). Both checks are batched into one spawnSync each so
|
|
250
|
+
// the cost stays O(1) per capability rather than O(realizers).
|
|
251
|
+
|
|
252
|
+
function gitDirtyFiles(rootDir) {
|
|
253
|
+
try {
|
|
254
|
+
const res = spawnSync('git', ['diff', '--name-only', 'HEAD'], { cwd: rootDir, encoding: 'utf8' });
|
|
255
|
+
if (res.status !== 0) return null;
|
|
256
|
+
return new Set(res.stdout.split('\n').map((l) => l.trim()).filter(Boolean));
|
|
257
|
+
} catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function gitFilesChangedSince(rootDir, sinceIso, rels) {
|
|
263
|
+
if (rels.length === 0) return new Set();
|
|
264
|
+
try {
|
|
265
|
+
const res = spawnSync(
|
|
266
|
+
'git',
|
|
267
|
+
['log', `--since=${sinceIso}`, '--name-only', '--pretty=format:', '--', ...rels],
|
|
268
|
+
{ cwd: rootDir, encoding: 'utf8' },
|
|
269
|
+
);
|
|
270
|
+
if (res.status !== 0) return null;
|
|
271
|
+
return new Set(res.stdout.split('\n').map((l) => l.trim()).filter(Boolean));
|
|
272
|
+
} catch {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Validation-grade freshness must not reuse the advisory `realizes` closure:
|
|
278
|
+
// build-import-graph.mjs deliberately widens that edge set for impact tracing
|
|
279
|
+
// (a broad edge only widens advisory reach, which is safe there). Reused
|
|
280
|
+
// here it would treat all 300+ files transitively reachable from a
|
|
281
|
+
// capability's tests as realizers, guaranteeing false positives. The
|
|
282
|
+
// freshness gate instead only trusts direct, declaration-sourced realizes
|
|
283
|
+
// edges (source: 'registry') — the curated implFiles list a capability
|
|
284
|
+
// actually declares — leaving the wide closure untouched for `construct
|
|
285
|
+
// trace`/`impact`.
|
|
286
|
+
|
|
287
|
+
function directRealizers(graph, capId) {
|
|
288
|
+
const edges = graph.in.get(capId) || [];
|
|
289
|
+
return edges
|
|
290
|
+
.filter((e) => e.rel === 'realizes' && (e.sources || []).includes('registry'))
|
|
291
|
+
.map((e) => e.from.slice('file:'.length));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function collectDependencyGraph(rootDir, projectDir) {
|
|
247
295
|
const graph = loadGraph(projectDir);
|
|
248
296
|
if (!graph.exists) {
|
|
249
297
|
return { present: false, applicable: isConstructPackageRepo(projectDir) };
|
|
@@ -271,18 +319,26 @@ function collectDependencyGraph(rootDir, projectDir) {
|
|
|
271
319
|
const orphanFileCount = nodesByType(graph, 'file')
|
|
272
320
|
.filter((f) => (graph.out.get(f.id) || []).every((e) => e.rel !== 'realizes')).length;
|
|
273
321
|
|
|
322
|
+
const dirtyFiles = gitDirtyFiles(rootDir);
|
|
274
323
|
const untested = [];
|
|
275
324
|
for (const cap of nodesByType(graph, 'capability')) {
|
|
276
325
|
const lastValidated = cap.attrs?.lastValidated;
|
|
277
326
|
if (!lastValidated) continue;
|
|
278
327
|
const stamp = Date.parse(lastValidated);
|
|
279
328
|
if (!Number.isFinite(stamp)) continue;
|
|
280
|
-
const realizers =
|
|
329
|
+
const realizers = directRealizers(graph, cap.id);
|
|
330
|
+
if (realizers.length === 0) continue;
|
|
331
|
+
const committedChanged = gitFilesChangedSince(rootDir, lastValidated, realizers);
|
|
281
332
|
let changed = 0;
|
|
282
333
|
for (const rel of realizers) {
|
|
283
334
|
try {
|
|
284
|
-
|
|
285
|
-
} catch {
|
|
335
|
+
fs.statSync(path.join(rootDir, rel));
|
|
336
|
+
} catch {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const dirty = dirtyFiles?.has(rel) ?? false;
|
|
340
|
+
const committed = committedChanged?.has(rel) ?? false;
|
|
341
|
+
if (dirty || committed) changed++;
|
|
286
342
|
}
|
|
287
343
|
if (changed > 0) untested.push({ capability: cap.id.slice('capability:'.length), changedFiles: changed, lastValidated });
|
|
288
344
|
}
|
package/lib/oracle/reconcile.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import fs from 'node:fs';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
|
|
11
11
|
import { runBd } from '../beads-client.mjs';
|
|
12
|
-
import { markContractViolationsSuperseded, recentViolations } from '../contracts/violation-log.mjs';
|
|
12
|
+
import { isDevSessionContractNoise, markContractViolationsSuperseded, recentViolations } from '../contracts/violation-log.mjs';
|
|
13
13
|
import { VERDICT_ONLY_GAP_IDS } from './policy.mjs';
|
|
14
14
|
import { oracleBeadTitlePrefix } from './issues.mjs';
|
|
15
15
|
|
|
@@ -91,55 +91,12 @@ function pruneRaisedIssues(projectDir, { dryRun = false } = {}) {
|
|
|
91
91
|
return { pruned };
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
const BARE_GOAL_FIELD_LABELS = ['intent', 'workCategory', 'riskFlags', 'acceptanceCriteria'];
|
|
95
|
-
|
|
96
|
-
const RESEARCHER_PROBE_MISSING = [
|
|
97
|
-
'artifact missing required field: question',
|
|
98
|
-
'artifact missing required field: method',
|
|
99
|
-
'artifact missing required field: sources',
|
|
100
|
-
'artifact missing required field: findings',
|
|
101
|
-
'artifact missing required field: confidence',
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
const A11Y_PROBE_MISSING = [
|
|
105
|
-
'artifact missing required field: findings',
|
|
106
|
-
'artifact missing required field: wcagCriterion',
|
|
107
|
-
'artifact missing required field: userImpact',
|
|
108
|
-
];
|
|
109
|
-
|
|
110
|
-
function missingBareGoalConstructFields(missing) {
|
|
111
|
-
if (!Array.isArray(missing) || missing.length !== BARE_GOAL_FIELD_LABELS.length) return false;
|
|
112
|
-
return BARE_GOAL_FIELD_LABELS.every((field) =>
|
|
113
|
-
missing.some((entry) => String(entry).includes(field)),
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function isBareGoalConstructViolation(row) {
|
|
118
|
-
if (row?.contractId !== 'construct-to-orchestrator') return false;
|
|
119
|
-
if (!missingBareGoalConstructFields(row.missing)) return false;
|
|
120
|
-
const keys = row.packet_keys ?? row.packetKeys;
|
|
121
|
-
return Array.isArray(keys) && keys.length === 1 && keys[0] === 'goal';
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function isEmptyProbeViolation(row, contractId, expectedMissing) {
|
|
125
|
-
if (row?.contractId !== contractId) return false;
|
|
126
|
-
const keys = row.packet_keys ?? row.packetKeys;
|
|
127
|
-
if (!Array.isArray(keys) || keys.length !== 0) return false;
|
|
128
|
-
return JSON.stringify(row.missing) === JSON.stringify(expectedMissing);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function isDevSessionContractNoise(row) {
|
|
132
|
-
return isBareGoalConstructViolation(row)
|
|
133
|
-
|| isEmptyProbeViolation(row, 'researcher-to-architect', RESEARCHER_PROBE_MISSING)
|
|
134
|
-
|| isEmptyProbeViolation(row, 'accessibility-to-qa', A11Y_PROBE_MISSING);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
94
|
/**
|
|
138
95
|
* @param {string} projectDir
|
|
139
96
|
* @returns {{ shouldSupersede: boolean, recentCount: number, reason: string }}
|
|
140
97
|
*/
|
|
141
|
-
export function planContractViolationSupersede(projectDir) {
|
|
142
|
-
const recent = recentViolations({ repoRoot: projectDir });
|
|
98
|
+
export function planContractViolationSupersede(projectDir, { now = Date.now() } = {}) {
|
|
99
|
+
const recent = recentViolations({ repoRoot: projectDir, now });
|
|
143
100
|
if (!recent.length) {
|
|
144
101
|
return { shouldSupersede: false, recentCount: 0, reason: 'no recent contract violations' };
|
|
145
102
|
}
|
package/lib/oracle/routing.mjs
CHANGED
|
@@ -1,54 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* lib/oracle/routing.mjs — deterministic gap → specialist routing table.
|
|
3
3
|
*
|
|
4
|
-
* Mirrors
|
|
5
|
-
*
|
|
4
|
+
* Mirrors skills/operating/fleet-health-routing.md (the fleet-health duty
|
|
5
|
+
* cx-oracle's retirement folded into cx-orchestrator, construct-rf26.11)
|
|
6
|
+
* without LLM involvement. Issue raising, approve execution, and routing
|
|
7
|
+
* artifact generation consume these mappings. Specialist ids reflect the
|
|
8
|
+
* post-consolidation 12-role roster; team-governance signals route to
|
|
9
|
+
* cx-operations (owns dependency/ownership mapping) rather than the retired
|
|
10
|
+
* cx-rd-lead.
|
|
6
11
|
*/
|
|
7
12
|
|
|
8
13
|
const GAP_ROUTES = {
|
|
9
|
-
'parity-drift': { primary: 'cx-
|
|
14
|
+
'parity-drift': { primary: 'cx-engineer', secondary: 'cx-operations' },
|
|
10
15
|
'contract-violations': { primary: 'cx-reviewer', secondary: 'cx-engineer' },
|
|
11
|
-
'doctor-escalation': { primary: 'cx-
|
|
12
|
-
'outcomes-degradation': { primary: 'cx-
|
|
13
|
-
'census-stale': { primary: 'cx-architect', secondary: 'cx-
|
|
14
|
-
'alignment-regression': { primary: 'cx-architect', secondary: 'cx-
|
|
15
|
-
'true-skill-orphan': { primary: 'cx-architect', secondary: 'cx-
|
|
16
|
-
'observations-empty': { primary: 'cx-
|
|
16
|
+
'doctor-escalation': { primary: 'cx-operations', secondary: 'cx-operations' },
|
|
17
|
+
'outcomes-degradation': { primary: 'cx-reviewer', secondary: null },
|
|
18
|
+
'census-stale': { primary: 'cx-architect', secondary: 'cx-operations' },
|
|
19
|
+
'alignment-regression': { primary: 'cx-architect', secondary: 'cx-operations' },
|
|
20
|
+
'true-skill-orphan': { primary: 'cx-architect', secondary: 'cx-operations' },
|
|
21
|
+
'observations-empty': { primary: 'cx-researcher', secondary: 'cx-engineer' },
|
|
17
22
|
'beads-hygiene': { primary: 'cx-operations', secondary: null },
|
|
18
|
-
'hook-failures': { primary: 'cx-
|
|
19
|
-
'registry-warn': { primary: 'cx-
|
|
20
|
-
'consistency-drift': { primary: 'cx-
|
|
21
|
-
'propagation-stale': { primary: 'cx-
|
|
23
|
+
'hook-failures': { primary: 'cx-operations', secondary: null },
|
|
24
|
+
'registry-warn': { primary: 'cx-engineer', secondary: null },
|
|
25
|
+
'consistency-drift': { primary: 'cx-engineer', secondary: null },
|
|
26
|
+
'propagation-stale': { primary: 'cx-engineer', secondary: 'cx-operations' },
|
|
22
27
|
'policy-coverage-gap': { primary: 'cx-architect', secondary: null },
|
|
23
28
|
'workflow-misaligned': { primary: 'cx-product-manager', secondary: null },
|
|
24
|
-
'legal-review-pending': { primary: 'cx-
|
|
25
|
-
'capability-unvalidated': { primary: 'cx-
|
|
29
|
+
'legal-review-pending': { primary: 'cx-security', secondary: null },
|
|
30
|
+
'capability-unvalidated': { primary: 'cx-engineer', secondary: null },
|
|
26
31
|
'dead-code-regression': { primary: 'cx-architect', secondary: null },
|
|
27
32
|
'structure-sprawl': { primary: 'cx-architect', secondary: null },
|
|
28
33
|
'init-duplicate-lanes': { primary: 'cx-architect', secondary: null },
|
|
29
|
-
'outcomes-missing': { primary: 'cx-
|
|
30
|
-
'repo-layout-legacy': { primary: 'cx-
|
|
31
|
-
'specialist-audit-drift': { primary: 'cx-architect', secondary: 'cx-
|
|
32
|
-
'artifact-gate-bypass': { primary: 'cx-reviewer', secondary: 'cx-
|
|
34
|
+
'outcomes-missing': { primary: 'cx-engineer', secondary: null },
|
|
35
|
+
'repo-layout-legacy': { primary: 'cx-engineer', secondary: 'cx-architect' },
|
|
36
|
+
'specialist-audit-drift': { primary: 'cx-architect', secondary: 'cx-operations' },
|
|
37
|
+
'artifact-gate-bypass': { primary: 'cx-reviewer', secondary: 'cx-operations' },
|
|
33
38
|
'artifact-reviewer-gap': { primary: 'cx-reviewer', secondary: null },
|
|
34
|
-
'dependency-graph-stale': { primary: 'cx-
|
|
39
|
+
'dependency-graph-stale': { primary: 'cx-engineer', secondary: null },
|
|
35
40
|
'matrix-coverage-gap': { primary: 'cx-architect', secondary: 'cx-qa' },
|
|
36
41
|
'impact-untested': { primary: 'cx-qa', secondary: 'cx-engineer' },
|
|
37
|
-
// Team governance signals —
|
|
38
|
-
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
+
// Team governance signals — rd-lead retired (construct-rf26.11); route to
|
|
43
|
+
// cx-operations (owns dependency/ownership mapping) for resolution.
|
|
44
|
+
'team-understaffed': { primary: 'cx-operations', secondary: 'cx-orchestrator' },
|
|
45
|
+
'escalation-path-broken': { primary: 'cx-operations', secondary: 'cx-architect' },
|
|
46
|
+
'team-decision-violation': { primary: 'cx-operations', secondary: 'cx-orchestrator' },
|
|
47
|
+
'cross-team-handoff-blocked': { primary: 'cx-operations', secondary: null },
|
|
42
48
|
};
|
|
43
49
|
|
|
44
50
|
const ACTION_ROUTES = {
|
|
45
51
|
'specialist-review': { primary: 'cx-reviewer', gateType: 'specialist-dispatch' },
|
|
46
|
-
'doctor-followup': { primary: 'cx-
|
|
47
|
-
'trace-review': { primary: 'cx-
|
|
48
|
-
'outcomes-aggregate': { primary: 'cx-
|
|
52
|
+
'doctor-followup': { primary: 'cx-operations', gateType: 'operational-followup' },
|
|
53
|
+
'trace-review': { primary: 'cx-reviewer', gateType: 'specialist-dispatch' },
|
|
54
|
+
'outcomes-aggregate': { primary: 'cx-engineer', gateType: 'maintenance' },
|
|
49
55
|
'executive-signoff-required': { primary: 'cx-product-manager', gateType: 'executive-gate' },
|
|
50
56
|
'structure-cleanup-proposal': { primary: 'cx-architect', gateType: 'human-approval' },
|
|
51
|
-
'graph-rebuild': { primary: 'cx-
|
|
57
|
+
'graph-rebuild': { primary: 'cx-engineer', gateType: 'maintenance' },
|
|
52
58
|
};
|
|
53
59
|
|
|
54
60
|
/**
|
|
@@ -59,14 +65,14 @@ export function routeGap(gap) {
|
|
|
59
65
|
const id = gap?.id ?? gap?.signal ?? '';
|
|
60
66
|
const row = GAP_ROUTES[id];
|
|
61
67
|
if (row) return { ...row, gateType: signOffGateForGap(id) };
|
|
62
|
-
return { primary: 'cx-
|
|
68
|
+
return { primary: 'cx-orchestrator', secondary: null, gateType: 'human-approval' };
|
|
63
69
|
}
|
|
64
70
|
|
|
65
71
|
/**
|
|
66
72
|
* @param {string} actionKind
|
|
67
73
|
*/
|
|
68
74
|
export function routeAction(actionKind) {
|
|
69
|
-
return ACTION_ROUTES[actionKind] ?? { primary: 'cx-
|
|
75
|
+
return ACTION_ROUTES[actionKind] ?? { primary: 'cx-orchestrator', gateType: 'human-approval' };
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
function signOffGateForGap(gapId) {
|
|
@@ -94,7 +94,7 @@ export function synthesizeVerdict(readModel) {
|
|
|
94
94
|
));
|
|
95
95
|
recommendedActions.push(action(
|
|
96
96
|
'trace-review',
|
|
97
|
-
'Dispatch cx-
|
|
97
|
+
'Dispatch cx-reviewer to inspect degraded specialist outcomes',
|
|
98
98
|
{ roles: degradedRoles, signOff: signOffMetadata({ id: 'outcomes-degradation' }, readModel.projectDir) },
|
|
99
99
|
));
|
|
100
100
|
}
|