@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
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { spawnSync } from 'node:child_process';
|
|
22
|
-
import { existsSync, statSync, readFileSync } from 'node:fs';
|
|
22
|
+
import { existsSync, statSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
23
23
|
import path from 'node:path';
|
|
24
24
|
import { fileURLToPath } from 'node:url';
|
|
25
25
|
|
|
@@ -109,13 +109,19 @@ if (consumerPkg.name === '@geraldmaron/construct') {
|
|
|
109
109
|
process.exit(0);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// Track every project mutation for the itemized receipt written at the end.
|
|
113
|
+
// npm has no uninstall lifecycle hook so the manifest is the only machine-readable
|
|
114
|
+
// record of what the hook touched and how to revert it (CX-AUDIT-PACKAGE-004).
|
|
115
|
+
const mutations = [];
|
|
116
|
+
|
|
112
117
|
try {
|
|
113
|
-
stageProjectAdapters({
|
|
118
|
+
const stageResult = stageProjectAdapters({
|
|
114
119
|
projectRoot: initCwd,
|
|
115
120
|
packageRoot: PKG_ROOT,
|
|
116
121
|
pkgVersion: PKG_VERSION,
|
|
117
122
|
log,
|
|
118
123
|
});
|
|
124
|
+
mutations.push({ path: '.construct', type: 'stage', synced: stageResult.synced });
|
|
119
125
|
|
|
120
126
|
// ADR-0027: Ensure .gitignore covers the newly staged adapters (construct-f6l6).
|
|
121
127
|
// Idempotent: missingIgnorePatterns returns only patterns not already present.
|
|
@@ -129,8 +135,27 @@ try {
|
|
|
129
135
|
const block = `${prefix}\n${HEADER}\n${SUBHEADER}\n${missing.join('\n')}\n`;
|
|
130
136
|
const { appendFileSync } = await import('node:fs');
|
|
131
137
|
appendFileSync(giPath, block, 'utf8');
|
|
138
|
+
mutations.push({ path: '.gitignore', type: 'append', patterns: missing });
|
|
132
139
|
log(`appended ${missing.length} Construct ignore pattern(s) to .gitignore`);
|
|
133
140
|
}
|
|
141
|
+
|
|
142
|
+
// Write the itemized mutation receipt so consumers can audit and revert what the
|
|
143
|
+
// hook touched. Write is best-effort: a manifest failure must never break an install.
|
|
144
|
+
try {
|
|
145
|
+
mkdirSync(path.join(initCwd, '.construct'), { recursive: true });
|
|
146
|
+
const manifest = {
|
|
147
|
+
pkgVersion: PKG_VERSION,
|
|
148
|
+
ts: new Date().toISOString(),
|
|
149
|
+
files: mutations.map((m) => m.path),
|
|
150
|
+
mutations,
|
|
151
|
+
recovery: 'npx construct init --repair',
|
|
152
|
+
};
|
|
153
|
+
writeFileSync(
|
|
154
|
+
path.join(initCwd, '.construct', 'install-manifest.json'),
|
|
155
|
+
JSON.stringify(manifest, null, 2) + '\n',
|
|
156
|
+
);
|
|
157
|
+
log('wrote .construct/install-manifest.json');
|
|
158
|
+
} catch { /* manifest write must not fail the install */ }
|
|
134
159
|
} catch (err) {
|
|
135
160
|
fail(`Adapter staging failed: ${err.message}`, 'The package is installed; run `npx construct init` in this project to complete setup.');
|
|
136
161
|
// Intentionally exit 0: staging is best-effort completion, and a non-zero exit
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"facets": {
|
|
4
|
+
"intake-type": { "exclusive": true, "auto_threshold": 0.80 },
|
|
5
|
+
"lifecycle": { "exclusive": true, "auto_threshold": 0.90 },
|
|
6
|
+
"priority": { "exclusive": true, "auto_threshold": 0.90 },
|
|
7
|
+
"signal-strength": { "exclusive": false, "auto_threshold": 0.95 },
|
|
8
|
+
"reversibility": { "exclusive": true, "auto_threshold": 0.85 },
|
|
9
|
+
"doctype": { "exclusive": true, "auto_threshold": 0.90 }
|
|
10
|
+
},
|
|
11
|
+
"tags": [
|
|
12
|
+
{
|
|
13
|
+
"id": "intake/bug",
|
|
14
|
+
"facet": "intake-type",
|
|
15
|
+
"label": "Bug",
|
|
16
|
+
"synonyms": ["defect", "regression", "error"],
|
|
17
|
+
"promote_to_graph": false,
|
|
18
|
+
"status": "active"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"id": "intake/user-signal",
|
|
22
|
+
"facet": "intake-type",
|
|
23
|
+
"label": "User Signal",
|
|
24
|
+
"synonyms": ["feedback", "user-feedback", "customer-signal"],
|
|
25
|
+
"promote_to_graph": false,
|
|
26
|
+
"status": "active"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "intake/experiment",
|
|
30
|
+
"facet": "intake-type",
|
|
31
|
+
"label": "Experiment",
|
|
32
|
+
"synonyms": ["ab-test", "test", "trial"],
|
|
33
|
+
"promote_to_graph": false,
|
|
34
|
+
"status": "active"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": "intake/architecture",
|
|
38
|
+
"facet": "intake-type",
|
|
39
|
+
"label": "Architecture",
|
|
40
|
+
"synonyms": ["design", "system-design", "arch"],
|
|
41
|
+
"promote_to_graph": false,
|
|
42
|
+
"status": "active"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "intake/incident",
|
|
46
|
+
"facet": "intake-type",
|
|
47
|
+
"label": "Incident",
|
|
48
|
+
"synonyms": ["outage", "postmortem", "production-issue"],
|
|
49
|
+
"promote_to_graph": false,
|
|
50
|
+
"status": "active"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"id": "intake/security",
|
|
54
|
+
"facet": "intake-type",
|
|
55
|
+
"label": "Security",
|
|
56
|
+
"synonyms": ["vulnerability", "cve", "threat"],
|
|
57
|
+
"promote_to_graph": false,
|
|
58
|
+
"status": "active"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "intake/requirement",
|
|
62
|
+
"facet": "intake-type",
|
|
63
|
+
"label": "Requirement",
|
|
64
|
+
"synonyms": ["spec", "specification", "acceptance-criteria"],
|
|
65
|
+
"promote_to_graph": false,
|
|
66
|
+
"status": "active"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"id": "intake/research",
|
|
70
|
+
"facet": "intake-type",
|
|
71
|
+
"label": "Research",
|
|
72
|
+
"synonyms": ["study", "literature-review"],
|
|
73
|
+
"promote_to_graph": false,
|
|
74
|
+
"status": "active"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "intake/ops",
|
|
78
|
+
"facet": "intake-type",
|
|
79
|
+
"label": "Ops",
|
|
80
|
+
"synonyms": ["operational", "runbook", "infra"],
|
|
81
|
+
"promote_to_graph": false,
|
|
82
|
+
"status": "active"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"id": "intake/eval-finding",
|
|
86
|
+
"facet": "intake-type",
|
|
87
|
+
"label": "Eval Finding",
|
|
88
|
+
"synonyms": ["evaluation", "eval", "benchmark-result"],
|
|
89
|
+
"promote_to_graph": false,
|
|
90
|
+
"status": "active"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "intake/launch-asset",
|
|
94
|
+
"facet": "intake-type",
|
|
95
|
+
"label": "Launch Asset",
|
|
96
|
+
"synonyms": ["launch", "go-to-market", "release-material"],
|
|
97
|
+
"promote_to_graph": false,
|
|
98
|
+
"status": "active"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "intake/legal-compliance",
|
|
102
|
+
"facet": "intake-type",
|
|
103
|
+
"label": "Legal Compliance",
|
|
104
|
+
"synonyms": ["legal", "compliance", "regulatory"],
|
|
105
|
+
"promote_to_graph": false,
|
|
106
|
+
"status": "active"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"id": "lifecycle/draft",
|
|
110
|
+
"facet": "lifecycle",
|
|
111
|
+
"label": "Draft",
|
|
112
|
+
"synonyms": ["wip", "in-progress"],
|
|
113
|
+
"promote_to_graph": false,
|
|
114
|
+
"status": "active"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"id": "lifecycle/approved",
|
|
118
|
+
"facet": "lifecycle",
|
|
119
|
+
"label": "Approved",
|
|
120
|
+
"synonyms": ["accepted", "ratified"],
|
|
121
|
+
"promote_to_graph": false,
|
|
122
|
+
"status": "active"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "lifecycle/deprecated",
|
|
126
|
+
"facet": "lifecycle",
|
|
127
|
+
"label": "Deprecated",
|
|
128
|
+
"synonyms": ["sunset", "retiring"],
|
|
129
|
+
"promote_to_graph": false,
|
|
130
|
+
"status": "active"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "lifecycle/superseded",
|
|
134
|
+
"facet": "lifecycle",
|
|
135
|
+
"label": "Superseded",
|
|
136
|
+
"synonyms": ["replaced", "obsolete"],
|
|
137
|
+
"promote_to_graph": false,
|
|
138
|
+
"status": "active"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"id": "lifecycle/archived",
|
|
142
|
+
"facet": "lifecycle",
|
|
143
|
+
"label": "Archived",
|
|
144
|
+
"synonyms": ["closed", "done"],
|
|
145
|
+
"promote_to_graph": false,
|
|
146
|
+
"status": "active"
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"id": "priority/p0",
|
|
150
|
+
"facet": "priority",
|
|
151
|
+
"label": "P0 - Critical",
|
|
152
|
+
"synonyms": ["critical", "blocker", "sev0"],
|
|
153
|
+
"promote_to_graph": true,
|
|
154
|
+
"status": "active"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"id": "priority/p1",
|
|
158
|
+
"facet": "priority",
|
|
159
|
+
"label": "P1 - High",
|
|
160
|
+
"synonyms": ["high", "urgent", "sev1"],
|
|
161
|
+
"promote_to_graph": true,
|
|
162
|
+
"status": "active"
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"id": "priority/p2",
|
|
166
|
+
"facet": "priority",
|
|
167
|
+
"label": "P2 - Medium",
|
|
168
|
+
"synonyms": ["medium", "normal", "sev2"],
|
|
169
|
+
"promote_to_graph": false,
|
|
170
|
+
"status": "active"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"id": "priority/p3",
|
|
174
|
+
"facet": "priority",
|
|
175
|
+
"label": "P3 - Low",
|
|
176
|
+
"synonyms": ["low", "nice-to-have", "sev3"],
|
|
177
|
+
"promote_to_graph": false,
|
|
178
|
+
"status": "active"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"id": "signal/high-customer-interest",
|
|
182
|
+
"facet": "signal-strength",
|
|
183
|
+
"label": "High Customer Interest",
|
|
184
|
+
"synonyms": ["customer-demand", "high-demand", "top-request"],
|
|
185
|
+
"promote_to_graph": true,
|
|
186
|
+
"anchor_entities": ["customer-feedback"],
|
|
187
|
+
"expected_cardinality": 100,
|
|
188
|
+
"cardinality_window_days": 90,
|
|
189
|
+
"status": "active"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"id": "signal/internal-alignment",
|
|
193
|
+
"facet": "signal-strength",
|
|
194
|
+
"label": "Internal Alignment",
|
|
195
|
+
"synonyms": ["aligned", "consensus", "cross-team"],
|
|
196
|
+
"promote_to_graph": false,
|
|
197
|
+
"status": "active"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "signal/blocked",
|
|
201
|
+
"facet": "signal-strength",
|
|
202
|
+
"label": "Blocked",
|
|
203
|
+
"synonyms": ["dependency", "waiting", "stalled"],
|
|
204
|
+
"promote_to_graph": false,
|
|
205
|
+
"status": "active"
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"id": "reversibility/irreversible",
|
|
209
|
+
"facet": "reversibility",
|
|
210
|
+
"label": "Irreversible",
|
|
211
|
+
"synonyms": ["one-way-door", "permanent"],
|
|
212
|
+
"promote_to_graph": true,
|
|
213
|
+
"status": "active"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"id": "reversibility/reversible",
|
|
217
|
+
"facet": "reversibility",
|
|
218
|
+
"label": "Reversible",
|
|
219
|
+
"synonyms": ["two-way-door", "rollback"],
|
|
220
|
+
"promote_to_graph": false,
|
|
221
|
+
"status": "active"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "reversibility/quasi-reversible",
|
|
225
|
+
"facet": "reversibility",
|
|
226
|
+
"label": "Quasi-Reversible",
|
|
227
|
+
"synonyms": ["partially-reversible", "conditional-rollback"],
|
|
228
|
+
"promote_to_graph": false,
|
|
229
|
+
"status": "active"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "doctype/prd",
|
|
233
|
+
"facet": "doctype",
|
|
234
|
+
"label": "PRD",
|
|
235
|
+
"synonyms": ["product-requirements", "product-spec"],
|
|
236
|
+
"promote_to_graph": false,
|
|
237
|
+
"status": "active"
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"id": "doctype/adr",
|
|
241
|
+
"facet": "doctype",
|
|
242
|
+
"label": "ADR",
|
|
243
|
+
"synonyms": ["architecture-decision", "decision-record"],
|
|
244
|
+
"promote_to_graph": false,
|
|
245
|
+
"status": "active"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"id": "doctype/rfc",
|
|
249
|
+
"facet": "doctype",
|
|
250
|
+
"label": "RFC",
|
|
251
|
+
"synonyms": ["request-for-comments", "proposal"],
|
|
252
|
+
"promote_to_graph": false,
|
|
253
|
+
"status": "active"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
"id": "doctype/postmortem",
|
|
257
|
+
"facet": "doctype",
|
|
258
|
+
"label": "Postmortem",
|
|
259
|
+
"synonyms": ["incident-review", "retrospective"],
|
|
260
|
+
"promote_to_graph": false,
|
|
261
|
+
"status": "active"
|
|
262
|
+
}
|
|
263
|
+
]
|
|
264
|
+
}
|
|
@@ -60,6 +60,6 @@ One token set across all distributable formats:
|
|
|
60
60
|
|
|
61
61
|
- Export: `construct export … --to=pptx`
|
|
62
62
|
- Regenerate: `npm run examples:deck`
|
|
63
|
-
- Matrix: [Document I/O reference](/guides/reference/document-io)
|
|
63
|
+
- Matrix: [Document I/O reference](../../../docs/guides/reference/document-io.md)
|
|
64
64
|
|
|
65
65
|
Review outputs in `.tmp/distribution-examples/`.
|
package/lib/acp/server.mjs
CHANGED
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
* methods: `initialize`, `session/new`, `session/prompt`, `session/cancel`;
|
|
13
13
|
* progress streams as `session/update` notifications. The prompt bridges to
|
|
14
14
|
* planRun/executeRun and forwards run-lifecycle events as agent message chunks.
|
|
15
|
+
*
|
|
16
|
+
* `fetchImpl` is injectable (mirrors lib/orchestration/worker.mjs) and threads
|
|
17
|
+
* straight through to executeRun, so a test can drive the provider backend
|
|
18
|
+
* without a live key or a real network call.
|
|
15
19
|
*/
|
|
16
20
|
|
|
17
21
|
import { createInterface } from 'node:readline';
|
|
@@ -20,16 +24,26 @@ const PROTOCOL_VERSION = 1;
|
|
|
20
24
|
|
|
21
25
|
function describeEvent(event) {
|
|
22
26
|
if (event.type === 'planned') return `Planned ${event.tasks ?? ''} specialist task(s).`;
|
|
23
|
-
if (event.type === 'running') return
|
|
24
|
-
if (event.type === 'task') return `· ${event.role ?? 'task'} — ${event.status ?? ''}`;
|
|
25
|
-
if (event.type === 'completed')
|
|
27
|
+
if (event.type === 'running') return `Running orchestration… (workerBackend=${event.workerBackend ?? 'inline'})`;
|
|
28
|
+
if (event.type === 'task') return `· ${event.role ?? 'task'} — ${event.status ?? ''}${event.executor ? ` (${event.executor})` : ''}`;
|
|
29
|
+
if (event.type === 'completed') {
|
|
30
|
+
const status = event.status ?? 'done';
|
|
31
|
+
if (status === 'completed') return 'Completed (specialist tasks executed).';
|
|
32
|
+
if (status === 'completed-prepare-only') return 'Completed (tasks prepared only — no specialist execution).';
|
|
33
|
+
if (status === 'completed-with-failures') return 'Completed with failures (some tasks failed).';
|
|
34
|
+
if (status === 'degraded') return 'Degraded — the run could not fully execute; see the summary.';
|
|
35
|
+
if (status === 'cancelled') return 'Cancelled.';
|
|
36
|
+
return `Completed: ${status}.`;
|
|
37
|
+
}
|
|
26
38
|
if (event.type === 'error') return `Error: ${event.error?.message ?? 'run failed'}.`;
|
|
27
39
|
return null;
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
function summarize(run) {
|
|
31
|
-
const tasks = (run.tasks || []).map((t) => `- ${t.role} (${t.status})`).join('\n');
|
|
32
|
-
|
|
43
|
+
const tasks = (run.tasks || []).map((t) => `- ${t.role} (${t.status}${t.executor ? `, ${t.executor}` : ''})`).join('\n');
|
|
44
|
+
const exec = run.execution || {};
|
|
45
|
+
const degraded = run.degraded ? ` — degraded: ${run.degradationReason}` : '';
|
|
46
|
+
return `Orchestration ${run.status} — executionMode=${exec.executionMode}, workerBackend=${run.workerBackend}${degraded}.\n${tasks}`;
|
|
33
47
|
}
|
|
34
48
|
|
|
35
49
|
function textFromPrompt(prompt) {
|
|
@@ -37,7 +51,7 @@ function textFromPrompt(prompt) {
|
|
|
37
51
|
return prompt.filter((b) => b && b.type === 'text' && typeof b.text === 'string').map((b) => b.text).join('\n').trim();
|
|
38
52
|
}
|
|
39
53
|
|
|
40
|
-
export function runAcpServer({ input, output, env = process.env, defaultCwd = process.cwd() } = {}) {
|
|
54
|
+
export function runAcpServer({ input, output, env = process.env, defaultCwd = process.cwd(), fetchImpl } = {}) {
|
|
41
55
|
const sessions = new Map();
|
|
42
56
|
let sessionCounter = 0;
|
|
43
57
|
|
|
@@ -63,7 +77,7 @@ export function runAcpServer({ input, output, env = process.env, defaultCwd = pr
|
|
|
63
77
|
const line = describeEvent(event);
|
|
64
78
|
if (line) update(sessionId, line);
|
|
65
79
|
});
|
|
66
|
-
const run = await executeRun(session.cwd, planned.runId, { env,
|
|
80
|
+
const run = await executeRun(session.cwd, planned.runId, { env, fetchImpl });
|
|
67
81
|
off();
|
|
68
82
|
update(sessionId, summarize(run));
|
|
69
83
|
respond(id, { stopReason: isCancelRequested(planned.runId) ? 'cancelled' : 'end_turn' });
|
package/lib/adapters-sync.mjs
CHANGED
|
@@ -12,6 +12,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
12
12
|
import { detectHostCapabilities } from './host-capabilities.mjs';
|
|
13
13
|
import { isConstructPackageRepo } from './host-disposition.mjs';
|
|
14
14
|
import { stageProjectAdapters } from './install/stage-project.mjs';
|
|
15
|
+
import { isMainModule } from './roots.mjs';
|
|
15
16
|
|
|
16
17
|
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
const PKG_ROOT = path.resolve(MODULE_DIR, '..');
|
|
@@ -58,7 +59,7 @@ export function runAdaptersScript({ cwd = process.cwd(), hosts = null } = {}) {
|
|
|
58
59
|
return result.synced ? 0 : 1;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
if (import.meta.url
|
|
62
|
+
if (isMainModule(import.meta.url)) {
|
|
62
63
|
const args = new Set(process.argv.slice(2));
|
|
63
64
|
const forceAll = args.has('--all-hosts');
|
|
64
65
|
const hosts = forceAll ? resolveAdapterHosts({ forceAll: true }) : null;
|
package/lib/audit-trail.mjs
CHANGED
|
@@ -17,14 +17,31 @@
|
|
|
17
17
|
* the damaged prefix as immutable legacy and re-bases the live chain;
|
|
18
18
|
* verifyChain validates only from the last boundary forward. See
|
|
19
19
|
* docs/guides/concepts/observability.md.
|
|
20
|
+
*
|
|
21
|
+
* Every record passes through redactRecord before the chain hash is computed
|
|
22
|
+
* (redact-then-sign), so prev_line_hash always chains off the redacted form —
|
|
23
|
+
* a secret can never enter the signed chain even transiently. Redaction
|
|
24
|
+
* covers: (a) values resolved by lib/providers/secret-resolver.mjs, consulted
|
|
25
|
+
* read-only via its resolved-cache snapshot; (b) common token shapes (Bearer,
|
|
26
|
+
* ghp_, xoxb/xoxp/xoxa, sk-, op://); (c) custom patterns registered with
|
|
27
|
+
* configureRedactionPatterns. Matches are replaced with `<redacted:kind>`;
|
|
28
|
+
* the pass itself is audited as a count, never the matched text.
|
|
29
|
+
*
|
|
30
|
+
* LMCP-H5: checkAuditSinkAvailable performs a real write-probe against the
|
|
31
|
+
* audit directory (mkdir + append + unlink a sidecar file) so a caller can
|
|
32
|
+
* distinguish "sink healthy" from "sink down" (read-only filesystem, missing
|
|
33
|
+
* mount, permissions) before deciding whether to proceed. Enterprise mode's
|
|
34
|
+
* mandatory-audit gate (lib/policy/audit-gate.mjs) fails closed on this
|
|
35
|
+
* check; solo/team never call it.
|
|
20
36
|
*/
|
|
21
|
-
import { readFileSync, existsSync, statSync, mkdirSync } from 'node:fs';
|
|
37
|
+
import { readFileSync, existsSync, statSync, mkdirSync, appendFileSync, unlinkSync } from 'node:fs';
|
|
22
38
|
import { createHash } from 'node:crypto';
|
|
23
39
|
import { join, dirname } from 'node:path';
|
|
24
40
|
|
|
25
41
|
import { appendBounded, readLastLineAcrossSegments } from './logging/rotate.mjs';
|
|
26
42
|
import { withFileLockSync } from './storage/file-lock.mjs';
|
|
27
43
|
import { doctorRoot } from './config/xdg.mjs';
|
|
44
|
+
import { __resolvedSecretValues } from './providers/secret-resolver.mjs';
|
|
28
45
|
|
|
29
46
|
const AUDIT_FILE = join(doctorRoot(), 'audit-trail.jsonl');
|
|
30
47
|
|
|
@@ -32,17 +49,183 @@ function sha256(input) {
|
|
|
32
49
|
return createHash('sha256').update(input).digest('hex');
|
|
33
50
|
}
|
|
34
51
|
|
|
52
|
+
export class AuditSinkUnavailableError extends Error {
|
|
53
|
+
constructor(message, { file, reason } = {}) {
|
|
54
|
+
super(message);
|
|
55
|
+
this.name = 'AuditSinkUnavailableError';
|
|
56
|
+
this.file = file ?? null;
|
|
57
|
+
this.reason = reason ?? null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A real write-probe, not a stat/existsSync check: a directory can exist and
|
|
62
|
+
// still refuse writes (read-only remount, quota, permission drop after
|
|
63
|
+
// mkdir). Writing and removing a sidecar file physically exercises the same
|
|
64
|
+
// path appendAuditRecord will take next, so "available" here means the next
|
|
65
|
+
// real append is actually expected to succeed.
|
|
66
|
+
|
|
67
|
+
export function checkAuditSinkAvailable({ file = AUDIT_FILE } = {}) {
|
|
68
|
+
const dir = dirname(file);
|
|
69
|
+
const probePath = join(dir, `.audit-sink-probe-${process.pid}-${Date.now()}`);
|
|
70
|
+
try {
|
|
71
|
+
mkdirSync(dir, { recursive: true });
|
|
72
|
+
appendFileSync(probePath, 'probe\n', 'utf8');
|
|
73
|
+
unlinkSync(probePath);
|
|
74
|
+
return { available: true, reason: null };
|
|
75
|
+
} catch (err) {
|
|
76
|
+
return { available: false, reason: err?.code || err?.message || 'unknown-error' };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Built-in token shapes seen in the wild across providers: generic Bearer
|
|
81
|
+
// headers, GitHub PATs (ghp_), Slack bot/user/app tokens (xoxb/xoxp/xoxa),
|
|
82
|
+
// OpenAI-style secret keys (sk-), and 1Password references (op://...). Each
|
|
83
|
+
// pattern is tagged with a `kind` so the replacement reads `<redacted:kind>`
|
|
84
|
+
// rather than a single opaque marker, which keeps audit records diagnosable.
|
|
85
|
+
|
|
86
|
+
const BUILTIN_PATTERNS = [
|
|
87
|
+
{ kind: 'bearer-token', re: /\bBearer\s+[A-Za-z0-9\-._~+/]+=*/g },
|
|
88
|
+
{ kind: 'github-token', re: /\bghp_[A-Za-z0-9]{20,}\b/g },
|
|
89
|
+
{ kind: 'slack-token', re: /\bxox[bpa]-[A-Za-z0-9-]{10,}\b/g },
|
|
90
|
+
{ kind: 'api-key', re: /\bsk-[A-Za-z0-9]{16,}\b/g },
|
|
91
|
+
{ kind: 'op-reference', re: /\bop:\/\/[^\s'"]+/g },
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
// Custom patterns a caller wires in at startup (e.g. an org-specific token
|
|
95
|
+
// shape). Kept process-local and additive over BUILTIN_PATTERNS; never
|
|
96
|
+
// persisted, so a test or embedder can register/reset freely.
|
|
97
|
+
|
|
98
|
+
let customPatterns = [];
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Register additional redaction patterns beyond the built-in token shapes.
|
|
102
|
+
* Each entry is `{ kind, re }` where `re` is a global RegExp. Replaces the
|
|
103
|
+
* full custom set on every call so a caller can reconfigure cleanly.
|
|
104
|
+
*
|
|
105
|
+
* @param {{kind:string, re:RegExp}[]} patterns
|
|
106
|
+
*/
|
|
107
|
+
export function configureRedactionPatterns(patterns = []) {
|
|
108
|
+
customPatterns = Array.isArray(patterns) ? patterns.filter((p) => p && p.re instanceof RegExp && typeof p.kind === 'string') : [];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function __resetRedactionPatterns() {
|
|
112
|
+
customPatterns = [];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Secret values below this length are excluded from the known-value pass:
|
|
116
|
+
// short resolved values (flags, single-char tokens) produce false-positive
|
|
117
|
+
// redactions in ordinary prose.
|
|
118
|
+
|
|
119
|
+
const MIN_KNOWN_SECRET_LENGTH = 8;
|
|
120
|
+
|
|
121
|
+
function escapeRegExp(str) {
|
|
122
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// A resolved secret is redacted by exact substring match, not by first
|
|
126
|
+
// hashing the haystack — a hash comparison can only ever confirm equality of
|
|
127
|
+
// two already-known values, never locate an unknown-length substring inside
|
|
128
|
+
// arbitrary free text. Instead, the "hashed comparison" the caller performs
|
|
129
|
+
// (recorded in the audit count, see below) is against sha256(value) so the
|
|
130
|
+
// count event that leaves the process never carries a byte of the plaintext,
|
|
131
|
+
// even though the in-process match itself must touch the plaintext to redact
|
|
132
|
+
// it — the same value already lives in secret-resolver's own cache in-process.
|
|
133
|
+
|
|
134
|
+
function knownSecretPatterns() {
|
|
135
|
+
const values = __resolvedSecretValues().filter(
|
|
136
|
+
(v) => typeof v === 'string' && v.length >= MIN_KNOWN_SECRET_LENGTH,
|
|
137
|
+
);
|
|
138
|
+
return values.map((value) => ({
|
|
139
|
+
kind: 'known-secret',
|
|
140
|
+
re: new RegExp(escapeRegExp(value), 'g'),
|
|
141
|
+
hash: sha256(value),
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// lib/providers/secret-audit-wiring.mjs already records the op:// reference
|
|
146
|
+
// itself (never the resolved value) under these exact key names as its
|
|
147
|
+
// value-free diagnostic contract — a bare op://vault/item/field pointer is
|
|
148
|
+
// not a secret, so the op-reference pattern must not clobber it there. Any
|
|
149
|
+
// other field carrying an op:// string (a tool result body, a raw env dump)
|
|
150
|
+
// is still redacted.
|
|
151
|
+
|
|
152
|
+
const OP_REF_EXEMPT_KEYS = new Set(['ref']);
|
|
153
|
+
|
|
154
|
+
// Walk every string reachable in `value`, applying every pattern in turn and
|
|
155
|
+
// replacing matches with `<redacted:kind>`. Returns the redacted clone plus a
|
|
156
|
+
// count-only tally (kind → number of matches) so the caller can audit that
|
|
157
|
+
// redaction occurred without ever recording the matched text.
|
|
158
|
+
|
|
159
|
+
function redactString(str, patterns, tally) {
|
|
160
|
+
let out = str;
|
|
161
|
+
for (const { kind, re } of patterns) {
|
|
162
|
+
re.lastIndex = 0;
|
|
163
|
+
const matches = out.match(re);
|
|
164
|
+
if (matches && matches.length) {
|
|
165
|
+
tally[kind] = (tally[kind] || 0) + matches.length;
|
|
166
|
+
out = out.replace(re, `<redacted:${kind}>`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function redactValue(value, patterns, tally, key = null) {
|
|
173
|
+
if (typeof value === 'string') {
|
|
174
|
+
if (key && OP_REF_EXEMPT_KEYS.has(key)) {
|
|
175
|
+
const rest = patterns.filter((p) => p.kind !== 'op-reference');
|
|
176
|
+
return redactString(value, rest, tally);
|
|
177
|
+
}
|
|
178
|
+
return redactString(value, patterns, tally);
|
|
179
|
+
}
|
|
180
|
+
if (Array.isArray(value)) return value.map((v) => redactValue(v, patterns, tally));
|
|
181
|
+
if (value && typeof value === 'object') {
|
|
182
|
+
const out = {};
|
|
183
|
+
for (const [k, v] of Object.entries(value)) {
|
|
184
|
+
// Schema-marked redacted:true fields are already elided upstream by the
|
|
185
|
+
// caller's own schema; this pass is a second, pattern-based net over
|
|
186
|
+
// whatever free-text fields (detail, args, result, payload) remain.
|
|
187
|
+
out[k] = redactValue(v, patterns, tally, k);
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
return value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Redact known secret values and token-shaped strings from an audit record.
|
|
196
|
+
* Runs BEFORE the chain hash is computed so the signature always covers the
|
|
197
|
+
* redacted form (redact-then-sign). Returns `{ record, tally }` where tally
|
|
198
|
+
* is a count-only map of kind → matches (never the matched text).
|
|
199
|
+
*
|
|
200
|
+
* @param {object} partial
|
|
201
|
+
* @returns {{record: object, tally: Record<string, number>}}
|
|
202
|
+
*/
|
|
203
|
+
export function redactRecord(partial) {
|
|
204
|
+
const patterns = [...BUILTIN_PATTERNS, ...customPatterns, ...knownSecretPatterns()];
|
|
205
|
+
const tally = {};
|
|
206
|
+
const record = redactValue(partial, patterns, tally);
|
|
207
|
+
return { record, tally };
|
|
208
|
+
}
|
|
209
|
+
|
|
35
210
|
// prev_line_hash and the append must be one atomic step or concurrent writers
|
|
36
211
|
// race; the file lock serializes them across processes.
|
|
37
212
|
|
|
38
213
|
export function appendAuditRecord(partial, { file = AUDIT_FILE } = {}) {
|
|
214
|
+
const { record: redacted, tally } = redactRecord(partial);
|
|
215
|
+
|
|
216
|
+
// Redaction is itself audited as a count only — never the secret — folded
|
|
217
|
+
// into the record's own field before it is hashed and written, so the
|
|
218
|
+
// signed line and the returned record always agree.
|
|
219
|
+
|
|
220
|
+
if (Object.keys(tally).length) redacted.redaction_counts = tally;
|
|
221
|
+
|
|
39
222
|
return withFileLockSync(file, () => {
|
|
40
223
|
let prev = null;
|
|
41
224
|
try {
|
|
42
225
|
const last = readLastLineAcrossSegments(file);
|
|
43
226
|
if (last !== null) prev = sha256(last);
|
|
44
227
|
} catch { /* first record, or unreadable tail */ }
|
|
45
|
-
const record = { ...
|
|
228
|
+
const record = { ...redacted, prev_line_hash: prev };
|
|
46
229
|
mkdirSync(dirname(file), { recursive: true });
|
|
47
230
|
appendBounded('audit-trail', file, JSON.stringify(record) + '\n');
|
|
48
231
|
return record;
|
package/lib/beads/auto-close.mjs
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
23
|
import { spawnSync } from 'node:child_process';
|
|
24
|
+
import { isMainModule } from '../roots.mjs';
|
|
24
25
|
|
|
25
26
|
const CLOSES_RE = /\b(?:closes?|close|fix(?:es)?|fixed|resolves?|resolved)\s+(construct-[a-z0-9]+)/gi;
|
|
26
27
|
|
|
@@ -105,7 +106,7 @@ export async function runAutoClose({ range, runner = spawnSync } = {}) {
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
// CLI entry: read --range, run, print summary.
|
|
108
|
-
const invokedDirectly = import.meta.url
|
|
109
|
+
const invokedDirectly = isMainModule(import.meta.url);
|
|
109
110
|
if (invokedDirectly) {
|
|
110
111
|
const args = process.argv.slice(2);
|
|
111
112
|
const rangeArg = args.find((a) => a.startsWith('--range='));
|
package/lib/beads/drift.mjs
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
27
|
import { spawnSync } from 'node:child_process';
|
|
28
|
+
import { isMainModule } from '../roots.mjs';
|
|
28
29
|
|
|
29
30
|
const DEFAULT_STALE_OPEN_DAYS = 14;
|
|
30
31
|
const DEFAULT_STUCK_IN_PROGRESS_DAYS = 3;
|
|
@@ -166,7 +167,7 @@ export function formatDriftReport(report) {
|
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
// CLI: print report, exit non-zero when thresholds breached unless --report-only.
|
|
169
|
-
const invokedDirectly = import.meta.url
|
|
170
|
+
const invokedDirectly = isMainModule(import.meta.url);
|
|
170
171
|
if (invokedDirectly) {
|
|
171
172
|
const args = process.argv.slice(2);
|
|
172
173
|
const json = args.includes('--json');
|