avorelo 0.3.8 → 0.4.0-rc.2
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/LICENSE +16 -23
- package/README.md +62 -72
- package/bin/avorelo +9 -0
- package/package.json +147 -139
- package/scripts/README.md +40 -0
- package/scripts/avorelo-session-collision-guard.js +540 -0
- package/scripts/avorelo-workstream-preflight.js +918 -0
- package/scripts/cco-dashboard.js +346 -0
- package/scripts/cco-posttooluse.js +504 -0
- package/scripts/cco-pretooluse.js +381 -0
- package/scripts/cco-status.js +540 -0
- package/scripts/cco-stop.js +77 -0
- package/scripts/cco-userprompt-submit.js +83 -0
- package/scripts/lib/activation/account-state.js +37 -0
- package/scripts/lib/activation/activate-command.js +114 -0
- package/scripts/lib/activation/activation-runner.js +607 -0
- package/scripts/lib/activation/activation-self-healing.js +481 -0
- package/scripts/lib/activation/activation-state.js +96 -0
- package/scripts/lib/activation/activation-summary.js +241 -0
- package/scripts/lib/activation/adapters/claude-code.js +77 -0
- package/scripts/lib/activation/adapters/codex-cli.js +52 -0
- package/scripts/lib/activation/adapters/cursor.js +37 -0
- package/scripts/lib/activation/adapters/github-agent.js +39 -0
- package/scripts/lib/activation/adapters/terminal.js +42 -0
- package/scripts/lib/activation/adapters/vscode.js +39 -0
- package/scripts/lib/activation/adapters/windsurf.js +37 -0
- package/scripts/lib/activation/ai-surface-detector.js +151 -0
- package/scripts/lib/activation/connect-account.js +145 -0
- package/scripts/lib/activation/detect-environment.js +75 -0
- package/scripts/lib/activation/detect-hosts.js +62 -0
- package/scripts/lib/activation/format-activation-output.js +109 -0
- package/scripts/lib/activation/next-action.js +43 -0
- package/scripts/lib/activation/repair-engine.js +219 -0
- package/scripts/lib/activation/run-entry.js +346 -0
- package/scripts/lib/activation-distribution-readiness.js +507 -0
- package/scripts/lib/adapter-conformance.js +176 -0
- package/scripts/lib/adapter-readiness.js +428 -0
- package/scripts/lib/adapter-safety-boundaries.js +335 -0
- package/scripts/lib/adapter-technical-readiness-gate.js +205 -0
- package/scripts/lib/agent-access-governance.js +455 -0
- package/scripts/lib/agent-activation-readiness.js +878 -0
- package/scripts/lib/agent-enforcement.js +765 -0
- package/scripts/lib/agent-evolution-loop.js +479 -0
- package/scripts/lib/agent-policy-profile.js +210 -0
- package/scripts/lib/agent-security/action-evaluator.js +507 -0
- package/scripts/lib/agent-security/adapter-registry.js +98 -0
- package/scripts/lib/agent-security/auto-policy.js +139 -0
- package/scripts/lib/agent-security/bounded-scan.js +93 -0
- package/scripts/lib/agent-security/enforcement-adapter.js +174 -0
- package/scripts/lib/agent-security/enforcement-engine.js +1129 -0
- package/scripts/lib/agent-security/file-write-adapter.js +183 -0
- package/scripts/lib/agent-security/file-write-rules.js +178 -0
- package/scripts/lib/agent-security/index.js +3342 -0
- package/scripts/lib/agent-security/instruction-risk.js +181 -0
- package/scripts/lib/agent-security/mcp-action-adapter.js +185 -0
- package/scripts/lib/agent-security/mcp-action-rules.js +184 -0
- package/scripts/lib/agent-security/package-action-adapter.js +175 -0
- package/scripts/lib/agent-security/package-action-rules.js +233 -0
- package/scripts/lib/agent-security/performance.js +148 -0
- package/scripts/lib/agent-security/permission-minimizer.js +403 -0
- package/scripts/lib/agent-security/scan-cache.js +74 -0
- package/scripts/lib/agent-security/source-trust.js +146 -0
- package/scripts/lib/ai-efficiency-dogfood-pack.js +437 -0
- package/scripts/lib/ai-efficiency-eval.js +207 -0
- package/scripts/lib/ai-efficiency-guard-contract.js +209 -0
- package/scripts/lib/ai-efficiency-measured-value.js +106 -0
- package/scripts/lib/ai-install-prompt.js +293 -0
- package/scripts/lib/ai-task-inference.js +155 -0
- package/scripts/lib/ai-value-ledger.js +121 -0
- package/scripts/lib/ai-value-proof-table.js +151 -0
- package/scripts/lib/ai-work-efficiency-routing.js +623 -0
- package/scripts/lib/ai-workspace-hygiene.js +1499 -0
- package/scripts/lib/alpha-activation.js +520 -0
- package/scripts/lib/alpha-feedback.js +263 -0
- package/scripts/lib/alpha-readiness-gate.js +332 -0
- package/scripts/lib/anti-gaming.js +169 -0
- package/scripts/lib/artifact-health.js +431 -0
- package/scripts/lib/artifact-receipt-hygiene.js +619 -0
- package/scripts/lib/attribution.js +180 -0
- package/scripts/lib/audit.js +289 -0
- package/scripts/lib/avorelo-skill-registry.js +810 -0
- package/scripts/lib/batch-jobs.js +71 -0
- package/scripts/lib/brain-pack.js +578 -0
- package/scripts/lib/brand-boundary.js +424 -0
- package/scripts/lib/brand.js +74 -0
- package/scripts/lib/browser-capability.js +1048 -0
- package/scripts/lib/browser-proof-governed-workflow.js +1020 -0
- package/scripts/lib/browser-proof-preflight.js +321 -0
- package/scripts/lib/cache-readiness.js +296 -0
- package/scripts/lib/canonical-reentry.js +162 -0
- package/scripts/lib/capability-contract-validator.js +177 -0
- package/scripts/lib/capability-hygiene.js +504 -0
- package/scripts/lib/capability-intake-quarantine.js +789 -0
- package/scripts/lib/capability-kernel-registry.js +566 -0
- package/scripts/lib/capability-kernel.js +202 -0
- package/scripts/lib/capability-manifest.js +255 -0
- package/scripts/lib/capability-outcome-normalizer.js +104 -0
- package/scripts/lib/capability-packs.js +314 -0
- package/scripts/lib/capability-recommender.js +513 -0
- package/scripts/lib/capability-registry.js +1062 -0
- package/scripts/lib/carry-forward-surfacing.js +194 -0
- package/scripts/lib/ccusage-adapter.js +188 -0
- package/scripts/lib/claude-session-evidence/index.js +1027 -0
- package/scripts/lib/cli-output-sanitizer.js +118 -0
- package/scripts/lib/company-loop.js +1149 -0
- package/scripts/lib/config.js +641 -0
- package/scripts/lib/context-acquisition-plan.js +359 -0
- package/scripts/lib/context-authority-rules.js +138 -0
- package/scripts/lib/context-budget-guard.js +170 -0
- package/scripts/lib/context-budget-scanner.js +257 -0
- package/scripts/lib/context-budget.js +167 -0
- package/scripts/lib/context-claim-safety.js +116 -0
- package/scripts/lib/context-compiler.js +236 -0
- package/scripts/lib/context-optimizer.js +715 -0
- package/scripts/lib/context-packet.js +121 -0
- package/scripts/lib/context-receipt.js +57 -0
- package/scripts/lib/context-reduction-plan.js +179 -0
- package/scripts/lib/context-safety.js +88 -0
- package/scripts/lib/context-savings-engine.js +158 -0
- package/scripts/lib/context-source-registry.js +393 -0
- package/scripts/lib/context-task-profiles.js +147 -0
- package/scripts/lib/cost-abuse-guard.js +975 -0
- package/scripts/lib/cost-evidence.js +287 -0
- package/scripts/lib/cost-to-outcome-signals.js +639 -0
- package/scripts/lib/cross-host-install-plan.js +308 -0
- package/scripts/lib/cross-host-install-readiness.js +242 -0
- package/scripts/lib/cross-host-value-flow.js +268 -0
- package/scripts/lib/dashboard.js +1056 -0
- package/scripts/lib/data-permissions-guard.js +1187 -0
- package/scripts/lib/deployment-environment-guard.js +1236 -0
- package/scripts/lib/design-partner-feedback.js +346 -0
- package/scripts/lib/dogfood-evidence-freshness.js +567 -0
- package/scripts/lib/efficiency-receipt.js +354 -0
- package/scripts/lib/entitlements.js +100 -0
- package/scripts/lib/execution-packet.js +559 -0
- package/scripts/lib/execution-route-governor.js +179 -0
- package/scripts/lib/experimentation-events.js +547 -0
- package/scripts/lib/external-capability-compliance.js +107 -0
- package/scripts/lib/external-readiness/ai-visibility/ai-visibility-runner.js +322 -0
- package/scripts/lib/external-readiness/calibration/benchmark-site-catalog.js +121 -0
- package/scripts/lib/external-readiness/calibration/completion-gate.js +112 -0
- package/scripts/lib/external-readiness/calibration/real-site-benchmark-runner.js +284 -0
- package/scripts/lib/external-readiness/drift-detector.js +100 -0
- package/scripts/lib/external-readiness/endpoint-prober.js +332 -0
- package/scripts/lib/external-readiness/external-readiness-runner.js +112 -0
- package/scripts/lib/external-readiness/full-agent-readiness-scorer.js +220 -0
- package/scripts/lib/external-readiness/golden-path-runner.js +333 -0
- package/scripts/lib/external-readiness/inside-out-runner.js +118 -0
- package/scripts/lib/external-readiness/proof-receipt-writer.js +112 -0
- package/scripts/lib/external-readiness/safe-fix-executor.js +117 -0
- package/scripts/lib/external-readiness/skills/category-boundary-guard.js +30 -0
- package/scripts/lib/external-readiness/skills/pmm-positioning-guard.js +69 -0
- package/scripts/lib/external-readiness/skills/safe-fix-policy.js +35 -0
- package/scripts/lib/external-user-simulation.js +166 -0
- package/scripts/lib/failure-recovery-readiness.js +81 -0
- package/scripts/lib/failure-recovery.js +419 -0
- package/scripts/lib/feedback-intelligence.js +537 -0
- package/scripts/lib/feedback-signals.js +205 -0
- package/scripts/lib/file-integrity.js +68 -0
- package/scripts/lib/fsx.js +129 -0
- package/scripts/lib/full-readiness-gate.js +451 -0
- package/scripts/lib/governed-action-exposure-primitives.js +1514 -0
- package/scripts/lib/governed-exposure-planner.js +186 -0
- package/scripts/lib/governed-workspace-hygiene.js +946 -0
- package/scripts/lib/guard-suite-common.js +412 -0
- package/scripts/lib/guidance-builder.js +174 -0
- package/scripts/lib/hook-apply.js +1075 -0
- package/scripts/lib/hook-baseline.js +310 -0
- package/scripts/lib/hook-config-preview.js +275 -0
- package/scripts/lib/hook-contracts.js +290 -0
- package/scripts/lib/hook-safety-boundary-readiness.js +80 -0
- package/scripts/lib/host-capability-matrix.js +351 -0
- package/scripts/lib/host-support-context.js +254 -0
- package/scripts/lib/http-hook-action.js +538 -0
- package/scripts/lib/install-ai-readiness.js +84 -0
- package/scripts/lib/install-intake-risk.js +1051 -0
- package/scripts/lib/install-journey-intelligence.js +329 -0
- package/scripts/lib/intervention-guidance.js +57 -0
- package/scripts/lib/known-limitations.js +115 -0
- package/scripts/lib/l8-path-truth.js +146 -0
- package/scripts/lib/launch-hardening-gate.js +436 -0
- package/scripts/lib/launch-readiness.js +635 -0
- package/scripts/lib/learning-experimentation-foundation.js +1484 -0
- package/scripts/lib/learning-memory.js +686 -0
- package/scripts/lib/lifecycle-hooks.js +982 -0
- package/scripts/lib/local-package-smoke.js +436 -0
- package/scripts/lib/local-pricing.js +299 -0
- package/scripts/lib/mcp-enforcement.js +311 -0
- package/scripts/lib/mcp-least-privilege-policy.js +303 -0
- package/scripts/lib/mcp-tool-inventory.js +388 -0
- package/scripts/lib/mcp-tool-risk.js +0 -0
- package/scripts/lib/memory.js +335 -0
- package/scripts/lib/metrics.js +699 -0
- package/scripts/lib/micro-proof.js +133 -0
- package/scripts/lib/model-work-class-routing.js +79 -0
- package/scripts/lib/next-run-context.js +436 -0
- package/scripts/lib/next-run-continuity.js +1207 -0
- package/scripts/lib/observability-recovery-guard.js +1030 -0
- package/scripts/lib/operating-value.js +1662 -0
- package/scripts/lib/optimization-v3.js +122 -0
- package/scripts/lib/orchestration/adapters/_shared.js +49 -0
- package/scripts/lib/orchestration/adapters/aider.js +18 -0
- package/scripts/lib/orchestration/adapters/claude-code.js +35 -0
- package/scripts/lib/orchestration/adapters/codex.js +35 -0
- package/scripts/lib/orchestration/adapters/gemini-cli.js +18 -0
- package/scripts/lib/orchestration/adapters/git.js +25 -0
- package/scripts/lib/orchestration/adapters/index.js +31 -0
- package/scripts/lib/orchestration/adapters/lm-studio.js +18 -0
- package/scripts/lib/orchestration/adapters/ollama.js +18 -0
- package/scripts/lib/orchestration/adapters/opencode.js +18 -0
- package/scripts/lib/orchestration/adapters/openrouter.js +18 -0
- package/scripts/lib/orchestration/adapters/test-runner.js +25 -0
- package/scripts/lib/orchestration/cli.js +438 -0
- package/scripts/lib/orchestration/execution-manager.js +279 -0
- package/scripts/lib/orchestration/handoff.js +314 -0
- package/scripts/lib/orchestration/index.js +456 -0
- package/scripts/lib/orchestration/inventory.js +47 -0
- package/scripts/lib/orchestration/model-discovery.js +498 -0
- package/scripts/lib/orchestration/model-profiler.js +170 -0
- package/scripts/lib/orchestration/model-profiles.js +252 -0
- package/scripts/lib/orchestration/model-refresh-policy.js +72 -0
- package/scripts/lib/orchestration/proof-writer.js +349 -0
- package/scripts/lib/orchestration/provider-discovery/aider.js +49 -0
- package/scripts/lib/orchestration/provider-discovery/claude-code.js +56 -0
- package/scripts/lib/orchestration/provider-discovery/codex.js +49 -0
- package/scripts/lib/orchestration/provider-discovery/common.js +186 -0
- package/scripts/lib/orchestration/provider-discovery/gemini.js +106 -0
- package/scripts/lib/orchestration/provider-discovery/lm-studio.js +118 -0
- package/scripts/lib/orchestration/provider-discovery/models-dev.js +12 -0
- package/scripts/lib/orchestration/provider-discovery/ollama.js +100 -0
- package/scripts/lib/orchestration/provider-discovery/opencode.js +47 -0
- package/scripts/lib/orchestration/provider-discovery/openrouter.js +44 -0
- package/scripts/lib/orchestration/risk-classifier.js +130 -0
- package/scripts/lib/orchestration/routing-policy.js +486 -0
- package/scripts/lib/orchestration/settings.js +95 -0
- package/scripts/lib/orchestration/state.js +165 -0
- package/scripts/lib/orchestration/verification-manager.js +138 -0
- package/scripts/lib/outcome-evidence-stack.js +1083 -0
- package/scripts/lib/output-profiles.js +146 -0
- package/scripts/lib/package-content-audit.js +368 -0
- package/scripts/lib/package-runtime.js +278 -0
- package/scripts/lib/plan-surface.js +53 -0
- package/scripts/lib/plans.js +2327 -0
- package/scripts/lib/policy-provider.js +27 -0
- package/scripts/lib/prelaunch-activation-readiness.js +409 -0
- package/scripts/lib/prelaunch-evidence-store.js +816 -0
- package/scripts/lib/prelaunch-intelligence.js +869 -0
- package/scripts/lib/pricing-experiment.js +118 -0
- package/scripts/lib/pro-moment-events.js +77 -0
- package/scripts/lib/pro-moment-state.js +227 -0
- package/scripts/lib/pro-moments.js +1216 -0
- package/scripts/lib/product-home-receipt.js +1790 -0
- package/scripts/lib/product-learning-events.js +696 -0
- package/scripts/lib/production-confidence-control-tower.js +1209 -0
- package/scripts/lib/production-confidence.js +1858 -0
- package/scripts/lib/project-profile.js +555 -0
- package/scripts/lib/prompt-compiler-plan.js +94 -0
- package/scripts/lib/prompt-compiler.js +280 -0
- package/scripts/lib/prompt-lint.js +32 -0
- package/scripts/lib/prompt-suggestions.js +52 -0
- package/scripts/lib/proof-canonical.js +398 -0
- package/scripts/lib/proof-drilldown.js +383 -0
- package/scripts/lib/proof-e2e/promise-completion.js +141 -0
- package/scripts/lib/proof-e2e/promise-dashboard-claims.js +135 -0
- package/scripts/lib/proof-e2e/promise-local-proof.js +156 -0
- package/scripts/lib/proof-e2e/promise-provider-neutral.js +136 -0
- package/scripts/lib/proof-e2e/promise-registry.js +219 -0
- package/scripts/lib/proof-e2e/promise-security-trust.js +141 -0
- package/scripts/lib/proof-e2e/promise-skills-risk.js +163 -0
- package/scripts/lib/proof-e2e/promise-token-savings.js +112 -0
- package/scripts/lib/proof-e2e/promise-work-management.js +126 -0
- package/scripts/lib/proof-events.js +342 -0
- package/scripts/lib/proof-history.js +243 -0
- package/scripts/lib/proof-metrics.js +296 -0
- package/scripts/lib/proof-outcome-evidence.js +134 -0
- package/scripts/lib/proof-receipt.js +335 -0
- package/scripts/lib/proof-record.js +461 -0
- package/scripts/lib/proof-savings-report.js +1549 -0
- package/scripts/lib/public-activation-distribution-gate.js +266 -0
- package/scripts/lib/public-cli.js +5631 -0
- package/scripts/lib/public-distribution-truth.js +211 -0
- package/scripts/lib/public-distribution.js +73 -0
- package/scripts/lib/public-install-claim-checker.js +300 -0
- package/scripts/lib/publish-provenance-readiness.js +287 -0
- package/scripts/lib/readiness-delta.js +218 -0
- package/scripts/lib/readiness-evidence-closure.js +196 -0
- package/scripts/lib/reentry-memory-capture.js +241 -0
- package/scripts/lib/reentry-memory-retrieval.js +302 -0
- package/scripts/lib/reentry-memory-status.js +147 -0
- package/scripts/lib/reentry-memory-store.js +183 -0
- package/scripts/lib/reentry-state.js +66 -0
- package/scripts/lib/release-candidate-bundle.js +166 -0
- package/scripts/lib/remediation.js +81 -0
- package/scripts/lib/repo-map.js +391 -0
- package/scripts/lib/run-action-policy.js +104 -0
- package/scripts/lib/run-contract-receipt.js +48 -0
- package/scripts/lib/run-contract.js +288 -0
- package/scripts/lib/run-cost-to-verified-outcome.js +87 -0
- package/scripts/lib/run-improvements-lifecycle.js +330 -0
- package/scripts/lib/run-improvements.js +789 -0
- package/scripts/lib/run-proof-contract.js +116 -0
- package/scripts/lib/run-risk-classifier.js +131 -0
- package/scripts/lib/run-task-classifier.js +216 -0
- package/scripts/lib/runtime-decision-policy.js +387 -0
- package/scripts/lib/safe-path-engine.js +705 -0
- package/scripts/lib/safe-repair.js +877 -0
- package/scripts/lib/safe-run-controller.js +887 -0
- package/scripts/lib/scope-repair-before-approval.js +865 -0
- package/scripts/lib/score.js +262 -0
- package/scripts/lib/seamless-enforcement.js +329 -0
- package/scripts/lib/seamless-outcome.js +689 -0
- package/scripts/lib/seamless-reality-gate.js +5053 -0
- package/scripts/lib/security-confidence/activation-safety.js +78 -0
- package/scripts/lib/security-confidence/adapters/adapter-contract.js +125 -0
- package/scripts/lib/security-confidence/adapters/mock-claude-bughunter-adapter.js +36 -0
- package/scripts/lib/security-confidence/adapters/mock-decepticon-adapter.js +34 -0
- package/scripts/lib/security-confidence/adapters/mock-mcp-scan-adapter.js +35 -0
- package/scripts/lib/security-confidence/adapters/mock-snyk-agent-scan-adapter.js +35 -0
- package/scripts/lib/security-confidence/adapters/mock-tank-adapter.js +34 -0
- package/scripts/lib/security-confidence/adapters/reference-registry.js +63 -0
- package/scripts/lib/security-confidence/auth-rbac-plan.js +39 -0
- package/scripts/lib/security-confidence/component-inventory.js +151 -0
- package/scripts/lib/security-confidence/constants.js +191 -0
- package/scripts/lib/security-confidence/dependency-script-risk.js +95 -0
- package/scripts/lib/security-confidence/evidence-hygiene.js +127 -0
- package/scripts/lib/security-confidence/feature-impact-classifier.js +80 -0
- package/scripts/lib/security-confidence/file-utils.js +161 -0
- package/scripts/lib/security-confidence/finding-triage.js +90 -0
- package/scripts/lib/security-confidence/findings.js +115 -0
- package/scripts/lib/security-confidence/index.js +29 -0
- package/scripts/lib/security-confidence/permission-budget.js +93 -0
- package/scripts/lib/security-confidence/redaction.js +82 -0
- package/scripts/lib/security-confidence/redteam-fixtures.js +53 -0
- package/scripts/lib/security-confidence/reference-adoption.js +229 -0
- package/scripts/lib/security-confidence/reference-taxonomy.js +155 -0
- package/scripts/lib/security-confidence/report-quality.js +99 -0
- package/scripts/lib/security-confidence/report-writer.js +79 -0
- package/scripts/lib/security-confidence/risk-classifier.js +187 -0
- package/scripts/lib/security-confidence/runner.js +179 -0
- package/scripts/lib/security-confidence/schema.js +188 -0
- package/scripts/lib/security-confidence/secret-safety.js +74 -0
- package/scripts/lib/security-confidence/security-capability-router.js +98 -0
- package/scripts/lib/security-confidence/web-security-smoke-plan.js +46 -0
- package/scripts/lib/security-risk-classifier.js +511 -0
- package/scripts/lib/security-scan.js +396 -0
- package/scripts/lib/session-context-optimizer.js +1211 -0
- package/scripts/lib/session-timing.js +322 -0
- package/scripts/lib/skill-hygiene.js +805 -0
- package/scripts/lib/skill-packs.js +161 -0
- package/scripts/lib/skills-operating-layer-v1.js +1023 -0
- package/scripts/lib/skills-operating-layer.js +629 -0
- package/scripts/lib/smallest-safe-plan.js +214 -0
- package/scripts/lib/smart-routing-plan.js +115 -0
- package/scripts/lib/smart-work-routing.js +768 -0
- package/scripts/lib/source-catalog.js +1022 -0
- package/scripts/lib/status-value-summary.js +32 -0
- package/scripts/lib/supply-chain-dependency-guard.js +1333 -0
- package/scripts/lib/supply-chain-guard.js +219 -0
- package/scripts/lib/support-bundle.js +561 -0
- package/scripts/lib/support-redaction.js +66 -0
- package/scripts/lib/task-continuation.js +440 -0
- package/scripts/lib/test-helpers.js +15 -0
- package/scripts/lib/tier.js +38 -0
- package/scripts/lib/token-context-quality-gate.js +370 -0
- package/scripts/lib/token-cost-capture.js +187 -0
- package/scripts/lib/token-cost-evidence.js +862 -0
- package/scripts/lib/token-cost-intelligence.js +358 -0
- package/scripts/lib/token-efficiency-evidence.js +213 -0
- package/scripts/lib/token-efficiency-map.js +110 -0
- package/scripts/lib/token-evidence.js +703 -0
- package/scripts/lib/tokenish.js +17 -0
- package/scripts/lib/tool-output-sandbox.js +559 -0
- package/scripts/lib/trust-audit.js +136 -0
- package/scripts/lib/unified-events.js +396 -0
- package/scripts/lib/upgrade-interruption-recovery.js +407 -0
- package/scripts/lib/usage-ledger.js +201 -0
- package/scripts/lib/value-ledger.js +130 -0
- package/scripts/lib/value-proof-calibration.js +531 -0
- package/scripts/lib/visual-qa.js +231 -0
- package/scripts/lib/voice-alpha.js +29 -0
- package/scripts/lib/webhook-idempotency-guard.js +990 -0
- package/scripts/lib/work-aware-orchestration.js +976 -0
- package/scripts/lib/work-control-receipts.js +577 -0
- package/scripts/lib/work-ledger.js +1123 -0
- package/scripts/lib/work-panel-preview.js +352 -0
- package/scripts/lib/workflow-discipline.js +280 -0
- package/scripts/lib/workflow-intelligence-radar.js +804 -0
- package/scripts/lib/workflow-signals.js +419 -0
- package/scripts/lib/workspace-map.js +281 -0
- package/scripts/lib/workspace-registry.js +1367 -0
- package/scripts/lib/workspace-resolver.js +542 -0
- package/scripts/wuz-doctor.js +315 -0
- package/bin/avorelo.mjs +0 -7
- package/dist/avorelo.mjs +0 -24678
|
@@ -0,0 +1,918 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Avorelo Workstream Preflight v1
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Internal-only workflow guard. Given a proposed workstream description, it
|
|
6
|
+
// returns a deterministic decision about whether the work is safe to start,
|
|
7
|
+
// already tracked, parallel-owned, blocked by an open PR, or needs an audit.
|
|
8
|
+
//
|
|
9
|
+
// Architecture boundary (hard):
|
|
10
|
+
// - deterministic-first, local-first, source-of-truth driven
|
|
11
|
+
// - read-only against roadmap / ownership / follow-up files
|
|
12
|
+
// - NO model calls, NO network calls, NO GitHub API calls
|
|
13
|
+
// - NO runtime / hook / dashboard / redaction / routing / verify imports
|
|
14
|
+
// - compact text output by default; stable JSON with --json
|
|
15
|
+
//
|
|
16
|
+
// It CONSUMES (read-only) the governance sources owned by other PRs. It does
|
|
17
|
+
// NOT reimplement capability hygiene (#212), dogfood freshness (#212),
|
|
18
|
+
// artifact/receipt hygiene (#212), the roadmap ledger or follow-up register
|
|
19
|
+
// (#213). It only reads them and renders a preflight verdict.
|
|
20
|
+
//
|
|
21
|
+
// The ONLY runtime dependencies are the Node core `fs` and `path` modules.
|
|
22
|
+
|
|
23
|
+
const fs = require("fs");
|
|
24
|
+
const path = require("path");
|
|
25
|
+
|
|
26
|
+
const SCHEMA_VERSION = "avorelo.workstreamPreflight.v1";
|
|
27
|
+
|
|
28
|
+
const DECISIONS = Object.freeze({
|
|
29
|
+
SAFE_TO_START: "safe_to_start",
|
|
30
|
+
PARALLEL_OWNED: "parallel_owned",
|
|
31
|
+
BLOCKED_BY_OPEN_PR: "blocked_by_open_pr",
|
|
32
|
+
NEEDS_AUDIT: "needs_audit",
|
|
33
|
+
ALREADY_TRACKED: "already_tracked",
|
|
34
|
+
ALREADY_SHIPPED: "already_shipped",
|
|
35
|
+
UNCLEAR: "unclear",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Repo root resolved relative to this file so the tool works regardless of cwd.
|
|
39
|
+
const REPO_ROOT = path.resolve(__dirname, "..");
|
|
40
|
+
|
|
41
|
+
// Source-of-truth files (read-only). Relative paths are also used as evidenceRefs.
|
|
42
|
+
const SOURCES = Object.freeze({
|
|
43
|
+
ownershipRegistry: "docs/internal/capability-ownership-registry.md",
|
|
44
|
+
integrationChecklist: "docs/internal/feature-integration-checklist.md",
|
|
45
|
+
roadmapLedgerMd: "docs/internal/roadmap-state-ledger.md",
|
|
46
|
+
roadmapLedgerJson: "artifacts/roadmap/roadmap-state-ledger.v1.json",
|
|
47
|
+
followUpRegisterMd: "docs/internal/follow-up-debt-register.md",
|
|
48
|
+
followUpRegisterJson: "artifacts/roadmap/follow-up-debt-register.v1.json",
|
|
49
|
+
roadmapLedgerDogfood: "artifacts/roadmap/avorelo-roadmap-ledger-dogfood.v1.json",
|
|
50
|
+
// Consumed read-only by the proof-plan layer (registry-backed validator selection).
|
|
51
|
+
validationRegistry: "artifacts/roadmap/validation-registry.v1.json",
|
|
52
|
+
packageJson: "package.json",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Stable schema for the registry-backed proof plan attached to every decision.
|
|
56
|
+
const PROOF_PLAN_SCHEMA_VERSION = "avorelo.preflightProofPlan.v1";
|
|
57
|
+
|
|
58
|
+
// Decision-keyed safe next action for the proof plan. Advisory only.
|
|
59
|
+
const PROOF_PLAN_NEXT_ACTION = Object.freeze({
|
|
60
|
+
safe_to_start: "Proceed in a clean isolated worktree; rerun guard before commit/push.",
|
|
61
|
+
already_shipped: "Do not rebuild; inspect existing merged feature before proposing changes.",
|
|
62
|
+
already_tracked: "Continue only if this session owns the tracked follow-up; otherwise stop and report.",
|
|
63
|
+
blocked_by_open_pr: "Do not duplicate; inspect the active PR or ask user to assign ownership.",
|
|
64
|
+
parallel_owned: "Do not touch owner's files; coordinate with owning workstream.",
|
|
65
|
+
needs_audit: "Stop implementation until audit scope is explicit.",
|
|
66
|
+
unclear: "Clarify scope or add source-of-truth before implementation.",
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Deterministic mapping tables (local, static, no I/O).
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
// Known open-PR domains. Matching any phrase => blocked_by_open_pr.
|
|
74
|
+
const OPEN_PR_DOMAINS = [
|
|
75
|
+
{
|
|
76
|
+
pr: 166,
|
|
77
|
+
domain: "public-web/articles",
|
|
78
|
+
ownerDomain: "Public Narrative",
|
|
79
|
+
riskLevel: "medium",
|
|
80
|
+
phrases: [
|
|
81
|
+
"public articles",
|
|
82
|
+
"public article",
|
|
83
|
+
"articles",
|
|
84
|
+
"knowledge hub",
|
|
85
|
+
"public launch hub",
|
|
86
|
+
"public launch articles",
|
|
87
|
+
"launch hub",
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
pr: 77,
|
|
92
|
+
domain: "tool-output-redaction",
|
|
93
|
+
ownerDomain: "Tool-Output Redaction (open PR)",
|
|
94
|
+
riskLevel: "high",
|
|
95
|
+
phrases: [
|
|
96
|
+
"secret redaction",
|
|
97
|
+
"tool output redaction",
|
|
98
|
+
"posttooluse redaction",
|
|
99
|
+
"post tool use redaction",
|
|
100
|
+
"output redaction",
|
|
101
|
+
"redaction",
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
pr: 34,
|
|
106
|
+
domain: "smart-routing",
|
|
107
|
+
ownerDomain: "Smart-Routing Checks (open PR)",
|
|
108
|
+
riskLevel: "high",
|
|
109
|
+
phrases: ["smart routing", "routing checks", "routing check", "smart route", "routing"],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
pr: 29,
|
|
113
|
+
domain: "verify-policy",
|
|
114
|
+
ownerDomain: "Verify Policy Runtime Contract (open PR)",
|
|
115
|
+
riskLevel: "high",
|
|
116
|
+
phrases: [
|
|
117
|
+
"verify policy",
|
|
118
|
+
"verify runtime",
|
|
119
|
+
"verify runtime policy",
|
|
120
|
+
"suggest lighter run",
|
|
121
|
+
"suggest_lighter_run",
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
// Known parallel-owned domains (owned by parallel sessions / PR #212 hygiene pack).
|
|
127
|
+
// Matching any phrase => parallel_owned.
|
|
128
|
+
const PARALLEL_OWNED_DOMAINS = [
|
|
129
|
+
{
|
|
130
|
+
key: "capability-hygiene",
|
|
131
|
+
ownerDomain: "Capability Inventory and Contracts",
|
|
132
|
+
phrases: ["capability hygiene", "over skilling", "overskilling", "over-skilling"],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "dogfood-freshness",
|
|
136
|
+
ownerDomain: "Capability Inventory and Contracts",
|
|
137
|
+
phrases: ["dogfood freshness", "dogfood evidence freshness", "evidence freshness"],
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
key: "artifact-receipt-hygiene",
|
|
141
|
+
ownerDomain: "Proof Evidence",
|
|
142
|
+
phrases: [
|
|
143
|
+
"artifact receipt hygiene",
|
|
144
|
+
"artifact and receipt hygiene",
|
|
145
|
+
"receipt hygiene",
|
|
146
|
+
"local artifact hygiene",
|
|
147
|
+
"artifact hygiene",
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
// Known needs-audit domains: runtime/product-surface wiring that must be audited
|
|
153
|
+
// before implementation. Matching any phrase => needs_audit.
|
|
154
|
+
const NEEDS_AUDIT_DOMAINS = [
|
|
155
|
+
{
|
|
156
|
+
key: "run-contract-dashboard",
|
|
157
|
+
ownerDomain: "Dashboard / Status Aggregation",
|
|
158
|
+
phrases: ["wire run contract into dashboard", "run contract dashboard", "dashboard wiring", "dashboard"],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "run-contract-next-run",
|
|
162
|
+
ownerDomain: "Next-Run Continuity",
|
|
163
|
+
phrases: [
|
|
164
|
+
"wire run contract into next run",
|
|
165
|
+
"run contract next run",
|
|
166
|
+
"next run wiring",
|
|
167
|
+
"next-run wiring",
|
|
168
|
+
"next run continuity wiring",
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
key: "safe-run-controller",
|
|
173
|
+
ownerDomain: "Action Policy",
|
|
174
|
+
phrases: ["safe run controller", "safe-run-controller integration", "run controller integration"],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
key: "runtime-hook-wiring",
|
|
178
|
+
ownerDomain: "Action Policy",
|
|
179
|
+
phrases: ["runtime hook wiring", "hook wiring", "runtime hook", "hook controller", "runtime controller"],
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
key: "browser-proof-runtime",
|
|
183
|
+
ownerDomain: "Proof Evidence",
|
|
184
|
+
phrases: ["browser proof runtime", "live browser proof", "browser proof qa"],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
key: "deploy-publish-runtime",
|
|
188
|
+
ownerDomain: "Action Policy",
|
|
189
|
+
phrases: ["deploy controller", "publish controller", "deploy publish runtime", "runtime wiring"],
|
|
190
|
+
},
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
// Safe internal-governance work. Matching any phrase => safe_to_start.
|
|
194
|
+
const SAFE_INTERNAL_DOMAINS = [
|
|
195
|
+
"roadmap ownership reconciliation",
|
|
196
|
+
"ownership reconciliation",
|
|
197
|
+
"internal docs consistency",
|
|
198
|
+
"ownership registry cleanup",
|
|
199
|
+
"registry cleanup",
|
|
200
|
+
"follow up debt reconciliation",
|
|
201
|
+
"follow-up debt reconciliation",
|
|
202
|
+
"validator docs for governance",
|
|
203
|
+
"validator docs",
|
|
204
|
+
"governance docs",
|
|
205
|
+
"internal docs",
|
|
206
|
+
];
|
|
207
|
+
|
|
208
|
+
// Baseline areas this internal guard workstream must never touch.
|
|
209
|
+
const BASELINE_FORBIDDEN_AREAS = Object.freeze([
|
|
210
|
+
"runtime",
|
|
211
|
+
"hooks / controllers",
|
|
212
|
+
"dashboard",
|
|
213
|
+
"public web / articles / design",
|
|
214
|
+
"secret redaction runtime",
|
|
215
|
+
"smart routing",
|
|
216
|
+
"verify policy runtime",
|
|
217
|
+
"next-run wiring",
|
|
218
|
+
"safe-run-controller",
|
|
219
|
+
"billing / pricing / version / deploy / publish",
|
|
220
|
+
"package.json / package-lock",
|
|
221
|
+
]);
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Source loading (read-only, fail-open).
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
function readJsonSafe(relPath) {
|
|
228
|
+
try {
|
|
229
|
+
const abs = path.join(REPO_ROOT, relPath);
|
|
230
|
+
if (!fs.existsSync(abs)) return null;
|
|
231
|
+
return JSON.parse(fs.readFileSync(abs, "utf8"));
|
|
232
|
+
} catch (_err) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function loadSources() {
|
|
238
|
+
const ledger = readJsonSafe(SOURCES.roadmapLedgerJson);
|
|
239
|
+
const register = readJsonSafe(SOURCES.followUpRegisterJson);
|
|
240
|
+
// Read-only consumption of the Validation Registry catalogue (#217) and the
|
|
241
|
+
// package.json script map. Both are fail-open: a missing/corrupt source must
|
|
242
|
+
// never break the preflight decision, only the proof plan availability.
|
|
243
|
+
const registry = readJsonSafe(SOURCES.validationRegistry);
|
|
244
|
+
const pkg = readJsonSafe(SOURCES.packageJson);
|
|
245
|
+
return {
|
|
246
|
+
features: ledger && Array.isArray(ledger.features) ? ledger.features : [],
|
|
247
|
+
followUps: register && Array.isArray(register.followUps) ? register.followUps : [],
|
|
248
|
+
ledgerPresent: !!ledger,
|
|
249
|
+
registerPresent: !!register,
|
|
250
|
+
registry: registry || null,
|
|
251
|
+
registryEntries: registry && Array.isArray(registry.entries) ? registry.entries : null,
|
|
252
|
+
registryPresent: !!registry,
|
|
253
|
+
pkgScripts: pkg && pkg.scripts && typeof pkg.scripts === "object" ? pkg.scripts : {},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function repoFileExists(relPath) {
|
|
258
|
+
try {
|
|
259
|
+
return fs.existsSync(path.join(REPO_ROOT, relPath));
|
|
260
|
+
} catch (_err) {
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
// Matching helpers (pure).
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
|
|
269
|
+
function normalize(text) {
|
|
270
|
+
return String(text || "")
|
|
271
|
+
.toLowerCase()
|
|
272
|
+
.replace(/[^a-z0-9]+/g, " ")
|
|
273
|
+
.trim()
|
|
274
|
+
.replace(/\s+/g, " ");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function stripVersion(phrase) {
|
|
278
|
+
return phrase.replace(/\bv\d+\b/g, "").replace(/\s+/g, " ").trim();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function matchAny(normInput, phrases) {
|
|
282
|
+
for (const p of phrases) {
|
|
283
|
+
const np = normalize(p);
|
|
284
|
+
if (np && normInput.includes(np)) return p;
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function slugify(text) {
|
|
290
|
+
return normalize(text).replace(/\s+/g, "-").slice(0, 60).replace(/^-+|-+$/g, "");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// Core decision (deterministic, precedence-ordered).
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
|
|
297
|
+
function classify(rawInput, sourcesOverride) {
|
|
298
|
+
const input = String(rawInput == null ? "" : rawInput).trim();
|
|
299
|
+
const normInput = normalize(input);
|
|
300
|
+
const sources = sourcesOverride || loadSources();
|
|
301
|
+
|
|
302
|
+
const base = {
|
|
303
|
+
schemaVersion: SCHEMA_VERSION,
|
|
304
|
+
input,
|
|
305
|
+
decision: DECISIONS.UNCLEAR,
|
|
306
|
+
matchedDomains: [],
|
|
307
|
+
matchedFeatures: [],
|
|
308
|
+
matchedFollowUps: [],
|
|
309
|
+
blockedByOpenPRs: [],
|
|
310
|
+
parallelOwned: false,
|
|
311
|
+
ownerDomain: null,
|
|
312
|
+
riskLevel: "unknown",
|
|
313
|
+
safeBranchName: input ? `avorelo-${slugify(input)}-v1` : null,
|
|
314
|
+
requiredValidators: [],
|
|
315
|
+
forbiddenAreas: BASELINE_FORBIDDEN_AREAS.slice(),
|
|
316
|
+
safeNextAction: null,
|
|
317
|
+
confidence: "estimated",
|
|
318
|
+
evidenceRefs: [],
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
// Empty / too-vague input => unclear immediately.
|
|
322
|
+
if (!input || normInput.split(" ").filter(Boolean).length === 0) {
|
|
323
|
+
base.safeNextAction =
|
|
324
|
+
"Describe the proposed workstream in concrete terms (domain, files, intent) and re-run preflight.";
|
|
325
|
+
return base;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 1) blocked_by_open_pr — highest precedence (hard external conflict).
|
|
329
|
+
for (const d of OPEN_PR_DOMAINS) {
|
|
330
|
+
const hit = matchAny(normInput, d.phrases);
|
|
331
|
+
if (hit) {
|
|
332
|
+
return Object.assign(base, {
|
|
333
|
+
decision: DECISIONS.BLOCKED_BY_OPEN_PR,
|
|
334
|
+
matchedDomains: [d.domain],
|
|
335
|
+
blockedByOpenPRs: [d.pr],
|
|
336
|
+
ownerDomain: d.ownerDomain,
|
|
337
|
+
riskLevel: d.riskLevel,
|
|
338
|
+
confidence: "measured",
|
|
339
|
+
requiredValidators: validatorsForOpenPr(d),
|
|
340
|
+
evidenceRefs: [SOURCES.roadmapLedgerJson, SOURCES.followUpRegisterJson],
|
|
341
|
+
safeNextAction: `Reconcile open PR #${d.pr} (${d.domain}) before starting new ${d.domain} work; do not open a parallel change to this domain.`,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// 2) parallel_owned — owned by a parallel session / hygiene pack.
|
|
347
|
+
for (const d of PARALLEL_OWNED_DOMAINS) {
|
|
348
|
+
const hit = matchAny(normInput, d.phrases);
|
|
349
|
+
if (hit) {
|
|
350
|
+
const followUp = findParallelFollowUp(sources.followUps, d.key);
|
|
351
|
+
return Object.assign(base, {
|
|
352
|
+
decision: DECISIONS.PARALLEL_OWNED,
|
|
353
|
+
matchedDomains: [d.key],
|
|
354
|
+
matchedFollowUps: followUp ? [followUp.followUpId] : [],
|
|
355
|
+
parallelOwned: true,
|
|
356
|
+
ownerDomain: d.ownerDomain,
|
|
357
|
+
riskLevel: "medium",
|
|
358
|
+
confidence: followUp ? "measured" : "inferred",
|
|
359
|
+
requiredValidators: ["npm run validate:follow-up-debt"],
|
|
360
|
+
evidenceRefs: [SOURCES.followUpRegisterJson, SOURCES.followUpRegisterMd],
|
|
361
|
+
safeNextAction:
|
|
362
|
+
"Continue only in the owning parallel workstream (Capability & Evidence Hygiene Pack), not here. Do not duplicate.",
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// 3) needs_audit — runtime / product-surface wiring.
|
|
368
|
+
for (const d of NEEDS_AUDIT_DOMAINS) {
|
|
369
|
+
const hit = matchAny(normInput, d.phrases);
|
|
370
|
+
if (hit) {
|
|
371
|
+
const followUp = findNeedsAuditFollowUp(sources.followUps, normInput);
|
|
372
|
+
return Object.assign(base, {
|
|
373
|
+
decision: DECISIONS.NEEDS_AUDIT,
|
|
374
|
+
matchedDomains: [d.key],
|
|
375
|
+
matchedFollowUps: followUp ? [followUp.followUpId] : [],
|
|
376
|
+
ownerDomain: d.ownerDomain,
|
|
377
|
+
riskLevel: d.key === "safe-run-controller" ? "critical" : "high",
|
|
378
|
+
confidence: followUp ? "measured" : "inferred",
|
|
379
|
+
requiredValidators: ["npm run validate:run-contract", "runtime audit (separate workstream)"],
|
|
380
|
+
evidenceRefs: [SOURCES.followUpRegisterJson, SOURCES.roadmapLedgerJson],
|
|
381
|
+
safeNextAction:
|
|
382
|
+
"Open a separate runtime audit before any implementation; this touches runtime/product surface and must not be wired here.",
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// 4) already_shipped — matches a merged feature in the roadmap ledger.
|
|
388
|
+
const feature = matchFeature(normInput, sources.features);
|
|
389
|
+
if (feature) {
|
|
390
|
+
return Object.assign(base, {
|
|
391
|
+
decision: DECISIONS.ALREADY_SHIPPED,
|
|
392
|
+
matchedFeatures: [feature.featureId],
|
|
393
|
+
matchedDomains: feature.ownerDomain ? [feature.ownerDomain] : [],
|
|
394
|
+
ownerDomain: feature.ownerDomain || null,
|
|
395
|
+
riskLevel: "low",
|
|
396
|
+
confidence: "measured",
|
|
397
|
+
requiredValidators: ["npm run validate:roadmap-state", "npm run validate:capability-ownership"],
|
|
398
|
+
evidenceRefs: [SOURCES.roadmapLedgerJson, SOURCES.roadmapLedgerMd],
|
|
399
|
+
safeNextAction: `"${feature.featureName}" (PR #${feature.pr}) is already merged and owned by ${feature.ownerDomain}. Extend via its owner; do not rebuild.`,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// 5) already_tracked — matches a non-blocking follow-up already registered.
|
|
404
|
+
const followUp = matchTrackedFollowUp(normInput, sources.followUps);
|
|
405
|
+
if (followUp) {
|
|
406
|
+
return Object.assign(base, {
|
|
407
|
+
decision: DECISIONS.ALREADY_TRACKED,
|
|
408
|
+
matchedFollowUps: [followUp.followUpId],
|
|
409
|
+
matchedDomains: followUp.ownerDomain ? [followUp.ownerDomain] : [],
|
|
410
|
+
ownerDomain: followUp.ownerDomain || null,
|
|
411
|
+
riskLevel: followUp.riskLevel || "low",
|
|
412
|
+
confidence: "measured",
|
|
413
|
+
requiredValidators: ["npm run validate:follow-up-debt"],
|
|
414
|
+
evidenceRefs: [SOURCES.followUpRegisterJson, SOURCES.followUpRegisterMd],
|
|
415
|
+
safeNextAction: `Already tracked as follow-up "${followUp.title}" (status: ${followUp.status}). Advance it per the register; do not open a duplicate workstream.`,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// 6) safe_to_start — internal governance with no overlap.
|
|
420
|
+
const safeHit = matchAny(normInput, SAFE_INTERNAL_DOMAINS);
|
|
421
|
+
if (safeHit) {
|
|
422
|
+
return Object.assign(base, {
|
|
423
|
+
decision: DECISIONS.SAFE_TO_START,
|
|
424
|
+
matchedDomains: ["internal-governance"],
|
|
425
|
+
ownerDomain: "Internal Governance",
|
|
426
|
+
riskLevel: "low",
|
|
427
|
+
confidence: "inferred",
|
|
428
|
+
requiredValidators: [
|
|
429
|
+
"npm run validate:capability-ownership",
|
|
430
|
+
"npm run validate:roadmap-state",
|
|
431
|
+
"npm run validate:follow-up-debt",
|
|
432
|
+
],
|
|
433
|
+
evidenceRefs: [SOURCES.ownershipRegistry, SOURCES.roadmapLedgerJson, SOURCES.followUpRegisterJson],
|
|
434
|
+
safeNextAction:
|
|
435
|
+
"Safe to start. Begin with ownership registry and roadmap ledger checks; keep changes internal and read-only against runtime/public surfaces.",
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// 7) unclear — fallback.
|
|
440
|
+
return Object.assign(base, {
|
|
441
|
+
decision: DECISIONS.UNCLEAR,
|
|
442
|
+
confidence: "estimated",
|
|
443
|
+
safeNextAction:
|
|
444
|
+
"Not matched against any known domain, feature, or follow-up. Narrow the description (which subsystem, which files) and re-run, or run a manual ownership check.",
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ---------------------------------------------------------------------------
|
|
449
|
+
// Public entry point: classify, then attach a registry-backed proof plan.
|
|
450
|
+
//
|
|
451
|
+
// The proof plan is ADVISORY. It recommends which validators/checks should be
|
|
452
|
+
// run to prove the work is safe to proceed — it NEVER runs a validator, never
|
|
453
|
+
// claims a validator passed, and never invents a validator. Every registry-
|
|
454
|
+
// backed item is sourced from the Validation Registry (#217). The classification
|
|
455
|
+
// decision is computed first and is never changed by the proof plan.
|
|
456
|
+
// ---------------------------------------------------------------------------
|
|
457
|
+
|
|
458
|
+
function preflight(rawInput, sourcesOverride) {
|
|
459
|
+
const sources = sourcesOverride || loadSources();
|
|
460
|
+
const result = classify(rawInput, sources);
|
|
461
|
+
result.proofPlan = buildProofPlan(result, sources);
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// ---------------------------------------------------------------------------
|
|
466
|
+
// Deterministic, registry-backed proof-plan selection.
|
|
467
|
+
// ---------------------------------------------------------------------------
|
|
468
|
+
|
|
469
|
+
function buildProofPlan(result, sources) {
|
|
470
|
+
const decision = result.decision;
|
|
471
|
+
const safeNextAction = PROOF_PLAN_NEXT_ACTION[decision] || PROOF_PLAN_NEXT_ACTION.unclear;
|
|
472
|
+
const registryRef = SOURCES.validationRegistry;
|
|
473
|
+
|
|
474
|
+
// --- fail-open: no usable registry -> decision preserved, plan not_available.
|
|
475
|
+
const rawEntries =
|
|
476
|
+
sources && Array.isArray(sources.registryEntries)
|
|
477
|
+
? sources.registryEntries
|
|
478
|
+
: sources && sources.registry && Array.isArray(sources.registry.entries)
|
|
479
|
+
? sources.registry.entries
|
|
480
|
+
: null;
|
|
481
|
+
|
|
482
|
+
const byId = new Map();
|
|
483
|
+
if (rawEntries) {
|
|
484
|
+
for (const e of rawEntries) {
|
|
485
|
+
if (
|
|
486
|
+
e &&
|
|
487
|
+
typeof e.validatorId === "string" &&
|
|
488
|
+
typeof e.command === "string" &&
|
|
489
|
+
!byId.has(e.validatorId)
|
|
490
|
+
) {
|
|
491
|
+
byId.set(e.validatorId, e);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
if (!rawEntries || byId.size === 0) {
|
|
497
|
+
return {
|
|
498
|
+
schemaVersion: PROOF_PLAN_SCHEMA_VERSION,
|
|
499
|
+
status: "not_available",
|
|
500
|
+
required: [],
|
|
501
|
+
recommended: [],
|
|
502
|
+
notRequired: [],
|
|
503
|
+
notes: [
|
|
504
|
+
"Validation Registry is missing, unreadable, or has no usable entries; proof plan unavailable. The preflight decision above is unaffected — do not block solely because the proof plan is unavailable.",
|
|
505
|
+
],
|
|
506
|
+
safeNextAction,
|
|
507
|
+
evidenceRefs: [registryRef],
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const pkgScripts = (sources && sources.pkgScripts) || {};
|
|
512
|
+
const normInput = normalize(result.input);
|
|
513
|
+
const has = (s) => normInput.includes(normalize(s));
|
|
514
|
+
|
|
515
|
+
// Deterministic signal flags derived from the workstream description.
|
|
516
|
+
const sig = {
|
|
517
|
+
registry: has("validation registry") || has("validator") || has("run matrix") || has("proof plan"),
|
|
518
|
+
roadmap:
|
|
519
|
+
has("roadmap") ||
|
|
520
|
+
has("ledger") ||
|
|
521
|
+
has("follow up") ||
|
|
522
|
+
has("debt") ||
|
|
523
|
+
has("stale pr") ||
|
|
524
|
+
has("open workstream"),
|
|
525
|
+
governance:
|
|
526
|
+
has("governance") ||
|
|
527
|
+
has("ownership") ||
|
|
528
|
+
has("source of truth") ||
|
|
529
|
+
has("internal docs") ||
|
|
530
|
+
has("reconciliation") ||
|
|
531
|
+
has("preflight") ||
|
|
532
|
+
has("workstream"),
|
|
533
|
+
context: has("context compiler") || has("project knowledge") || has("context") || has("memory"),
|
|
534
|
+
capability: has("capability") || has("capability kernel") || has("capability contract") || has("skill contract"),
|
|
535
|
+
sessionCollision:
|
|
536
|
+
has("session collision") ||
|
|
537
|
+
has("force push") ||
|
|
538
|
+
has("dirty tree") ||
|
|
539
|
+
has("worktree") ||
|
|
540
|
+
has("branch") ||
|
|
541
|
+
has("push"),
|
|
542
|
+
activation: has("activation") || has("always on") || has("activate") || has("run entry"),
|
|
543
|
+
publicWeb:
|
|
544
|
+
has("public web") ||
|
|
545
|
+
has("article") ||
|
|
546
|
+
has("landing") ||
|
|
547
|
+
has("pricing") ||
|
|
548
|
+
has("signup") ||
|
|
549
|
+
has("visual") ||
|
|
550
|
+
has("design") ||
|
|
551
|
+
has("public"),
|
|
552
|
+
runtime:
|
|
553
|
+
has("runtime") ||
|
|
554
|
+
has("hook") ||
|
|
555
|
+
has("controller") ||
|
|
556
|
+
has("redaction") ||
|
|
557
|
+
has("routing") ||
|
|
558
|
+
has("verify") ||
|
|
559
|
+
has("policy"),
|
|
560
|
+
};
|
|
561
|
+
|
|
562
|
+
const required = [];
|
|
563
|
+
const recommended = [];
|
|
564
|
+
const notRequired = [];
|
|
565
|
+
const notes = [];
|
|
566
|
+
const seen = new Set();
|
|
567
|
+
|
|
568
|
+
// Add a registry-backed validator. Returns false (and adds nothing) if the
|
|
569
|
+
// validator does not exist in the registry — we never invent validators.
|
|
570
|
+
function addReg(list, validatorId, reason) {
|
|
571
|
+
const e = byId.get(validatorId);
|
|
572
|
+
if (!e) return false;
|
|
573
|
+
if (seen.has(validatorId)) return false;
|
|
574
|
+
seen.add(validatorId);
|
|
575
|
+
list.push({ validatorId, command: e.command, reason, source: "validation-registry" });
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Add a non-registry check that is verified to exist (npm script or repo test).
|
|
580
|
+
function addVerified(list, validatorId, command, reason, source) {
|
|
581
|
+
if (seen.has(validatorId)) return false;
|
|
582
|
+
seen.add(validatorId);
|
|
583
|
+
list.push({ validatorId, command, reason, source });
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const governanceContext = sig.governance || sig.roadmap || sig.registry || sig.capability || sig.context;
|
|
588
|
+
|
|
589
|
+
// Rule 1 — minimal governance checks for internal governance/source-of-truth work.
|
|
590
|
+
if (governanceContext) {
|
|
591
|
+
addReg(
|
|
592
|
+
required,
|
|
593
|
+
"capability-ownership",
|
|
594
|
+
"Confirm one owner per decision domain before extending governance source-of-truth."
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
if (sig.registry) {
|
|
598
|
+
addReg(
|
|
599
|
+
required,
|
|
600
|
+
"validation-registry",
|
|
601
|
+
"Confirm the Validation Registry catalogue is well-formed before relying on it for a proof plan."
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
if (sig.roadmap || sig.governance) {
|
|
605
|
+
addReg(
|
|
606
|
+
required,
|
|
607
|
+
"roadmap-ownership-reconciliation",
|
|
608
|
+
"Confirm roadmap ledger, debt register, and ownership registry reconcile before workstream/PR tracking changes."
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Rule 2 — roadmap / ledger / follow-up / debt / open-workstream work.
|
|
613
|
+
if (sig.roadmap) {
|
|
614
|
+
addReg(required, "roadmap-state", "Confirm the roadmap feature inventory is well-formed.");
|
|
615
|
+
addReg(required, "follow-up-debt", "Confirm follow-up/debt items are well-formed and deduplicated.");
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// Rule 4 — context compiler / context / project knowledge / memory.
|
|
619
|
+
if (sig.context) {
|
|
620
|
+
addReg(
|
|
621
|
+
required,
|
|
622
|
+
"context-compiler",
|
|
623
|
+
"Confirm source-of-truth context selection, authority ranking, and claim-safety filtering behave as specified."
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Rule 5 — capability / capability kernel / capability-or-skill contract.
|
|
628
|
+
if (sig.capability) {
|
|
629
|
+
addReg(required, "capability-contracts", "Confirm capability manifests carry required contract fields.");
|
|
630
|
+
addReg(required, "capability-ownership", "Confirm a single, non-duplicate owner for the capability domain.");
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Rule 6 — session collision / branch / push / worktree (not in registry).
|
|
634
|
+
if (sig.sessionCollision && !sig.activation) {
|
|
635
|
+
if (!addReg(recommended, "session-collision-guard", "Re-check branch/worktree collision state before push.")) {
|
|
636
|
+
if (pkgScripts["validate:session-collision-guard"]) {
|
|
637
|
+
addVerified(
|
|
638
|
+
recommended,
|
|
639
|
+
"session-collision-guard",
|
|
640
|
+
"npm run validate:session-collision-guard",
|
|
641
|
+
"Re-check branch/worktree collision state before push (registry has no entry; npm script verified present).",
|
|
642
|
+
"package-script"
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Rule 7 — activation / always-on / activate / run entry.
|
|
649
|
+
if (sig.activation) {
|
|
650
|
+
if (!addReg(required, "session-collision-guard", "Confirm no session collision before activation-adjacent work.")) {
|
|
651
|
+
if (pkgScripts["validate:session-collision-guard"]) {
|
|
652
|
+
addVerified(
|
|
653
|
+
required,
|
|
654
|
+
"session-collision-guard",
|
|
655
|
+
"npm run validate:session-collision-guard",
|
|
656
|
+
"Activation work shares branches/worktrees; confirm no session collision before proceeding.",
|
|
657
|
+
"package-script"
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
if (repoFileExists("tests/workstream-preflight.test.js")) {
|
|
662
|
+
addVerified(
|
|
663
|
+
required,
|
|
664
|
+
"workstream-preflight",
|
|
665
|
+
"node --test tests/workstream-preflight.test.js",
|
|
666
|
+
"Confirm preflight classification still holds for activation-adjacent work.",
|
|
667
|
+
"repo-check"
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
notes.push(
|
|
671
|
+
"Activation work may be active in another session; use an isolated worktree and do not touch activation-owned files."
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Rule 8 — public-web / article / landing / pricing / signup / visual / design.
|
|
676
|
+
if (sig.publicWeb) {
|
|
677
|
+
notes.push(
|
|
678
|
+
"Public/design work requires current public-web source-of-truth and visual QA; this proof plan is NOT design or launch approval and must not be treated as such."
|
|
679
|
+
);
|
|
680
|
+
addReg(
|
|
681
|
+
recommended,
|
|
682
|
+
"public-narrative",
|
|
683
|
+
"Claim-safety check for public language. Does not prove the site is deployed, design-approved, or production-ready."
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Rule 9 — runtime / hook / controller / redaction / routing / verify / policy.
|
|
688
|
+
if (sig.runtime) {
|
|
689
|
+
addReg(
|
|
690
|
+
required,
|
|
691
|
+
"capability-ownership",
|
|
692
|
+
"Governance ownership check only; runtime wiring needs a separate audit, not this proof plan."
|
|
693
|
+
);
|
|
694
|
+
notes.push(
|
|
695
|
+
"Runtime-adjacent work (runtime/hook/controller/redaction/routing/verify/policy) requires a separate runtime/security audit before implementation; this proof plan does not authorize runtime changes."
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Rule 10 — no specific mapping: generic safe checks only.
|
|
700
|
+
if (required.length === 0 && recommended.length === 0) {
|
|
701
|
+
addReg(
|
|
702
|
+
recommended,
|
|
703
|
+
"capability-ownership",
|
|
704
|
+
"Generic ownership safety check; proceed only if scope is clear and Session Collision Guard is safe."
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
return {
|
|
709
|
+
schemaVersion: PROOF_PLAN_SCHEMA_VERSION,
|
|
710
|
+
status: "available",
|
|
711
|
+
required,
|
|
712
|
+
recommended,
|
|
713
|
+
notRequired,
|
|
714
|
+
notes,
|
|
715
|
+
safeNextAction,
|
|
716
|
+
evidenceRefs: [registryRef],
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// --- match helpers against loaded sources ---
|
|
721
|
+
|
|
722
|
+
function validatorsForOpenPr(d) {
|
|
723
|
+
switch (d.pr) {
|
|
724
|
+
case 166:
|
|
725
|
+
return ["npm run validate:public-narrative"];
|
|
726
|
+
case 29:
|
|
727
|
+
return ["npm run validate:run-contract"];
|
|
728
|
+
default:
|
|
729
|
+
return ["npm run validate:capability-ownership"];
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
function findParallelFollowUp(followUps, key) {
|
|
734
|
+
const keyTokens = {
|
|
735
|
+
"capability-hygiene": "capability-hygiene",
|
|
736
|
+
"dogfood-freshness": "dogfood-evidence-freshness",
|
|
737
|
+
"artifact-receipt-hygiene": "artifact-receipt-hygiene",
|
|
738
|
+
}[key];
|
|
739
|
+
return (
|
|
740
|
+
followUps.find(
|
|
741
|
+
(f) => f.parallelSessionOwned === true && keyTokens && String(f.followUpId).includes(keyTokens)
|
|
742
|
+
) || followUps.find((f) => f.parallelSessionOwned === true && key && String(f.followUpId).includes(key)) || null
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
function findNeedsAuditFollowUp(followUps, normInput) {
|
|
747
|
+
return (
|
|
748
|
+
followUps.find((f) => {
|
|
749
|
+
if (f.status !== "needs-audit") return false;
|
|
750
|
+
const t = normalize(f.title);
|
|
751
|
+
// crude overlap: share a distinctive token like dashboard / next run / controller
|
|
752
|
+
return (
|
|
753
|
+
(normInput.includes("dashboard") && t.includes("dashboard")) ||
|
|
754
|
+
(normInput.includes("next run") && t.includes("next-run")) ||
|
|
755
|
+
(normInput.includes("next run") && t.includes("next run")) ||
|
|
756
|
+
(normInput.includes("controller") && t.includes("controller")) ||
|
|
757
|
+
(normInput.includes("browser proof") && t.includes("browser-proof"))
|
|
758
|
+
);
|
|
759
|
+
}) || null
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
function matchFeature(normInput, features) {
|
|
764
|
+
for (const f of features) {
|
|
765
|
+
const candidates = [stripVersion(normalize(f.featureName)), stripVersion(normalize(f.featureId))];
|
|
766
|
+
for (const c of candidates) {
|
|
767
|
+
const words = c.split(" ").filter(Boolean);
|
|
768
|
+
if (words.length >= 2 && normInput.includes(c)) return f;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return null;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function matchTrackedFollowUp(normInput, followUps) {
|
|
775
|
+
for (const f of followUps) {
|
|
776
|
+
if (f.parallelSessionOwned === true) continue; // parallel handled earlier
|
|
777
|
+
if (f.status === "needs-audit" || f.status === "blocked") continue; // handled earlier
|
|
778
|
+
const t = normalize(f.title);
|
|
779
|
+
const tokens = t.split(" ").filter((w) => w.length >= 4);
|
|
780
|
+
// require at least 2 distinctive tokens to co-occur to avoid loose matches
|
|
781
|
+
const overlap = tokens.filter((w) => normInput.includes(w));
|
|
782
|
+
if (overlap.length >= 2) return f;
|
|
783
|
+
}
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// ---------------------------------------------------------------------------
|
|
788
|
+
// Rendering.
|
|
789
|
+
// ---------------------------------------------------------------------------
|
|
790
|
+
|
|
791
|
+
function formatText(result) {
|
|
792
|
+
const lines = [];
|
|
793
|
+
lines.push(`Workstream Preflight: ${result.decision}`);
|
|
794
|
+
lines.push(`Reason: ${reasonFor(result)}`);
|
|
795
|
+
lines.push(`Safe next action: ${result.safeNextAction}`);
|
|
796
|
+
// compact detail line
|
|
797
|
+
const detail = [];
|
|
798
|
+
if (result.ownerDomain) detail.push(`owner=${result.ownerDomain}`);
|
|
799
|
+
detail.push(`risk=${result.riskLevel}`);
|
|
800
|
+
if (result.blockedByOpenPRs.length) detail.push(`openPRs=${result.blockedByOpenPRs.join(",")}`);
|
|
801
|
+
if (result.safeBranchName) detail.push(`branch=${result.safeBranchName}`);
|
|
802
|
+
detail.push(`confidence=${result.confidence}`);
|
|
803
|
+
lines.push(detail.join(" "));
|
|
804
|
+
appendProofPlanText(lines, result.proofPlan);
|
|
805
|
+
return lines.join("\n");
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
// Compact proof-plan rendering. Full plan (reasons, notes, evidence) lives in
|
|
809
|
+
// --json; the text view caps visible validators to stay terminal-friendly.
|
|
810
|
+
function appendProofPlanText(lines, plan, cap = 4) {
|
|
811
|
+
if (!plan) return;
|
|
812
|
+
if (plan.status !== "available") {
|
|
813
|
+
lines.push("Proof plan: not_available (Validation Registry unavailable; decision unaffected)");
|
|
814
|
+
lines.push(`Proof next action: ${plan.safeNextAction}`);
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
lines.push("Proof plan: available");
|
|
818
|
+
const fmt = (items) => {
|
|
819
|
+
const ids = items.map((i) => i.validatorId);
|
|
820
|
+
const shown = ids.slice(0, cap).join(", ");
|
|
821
|
+
const extra = ids.length > cap ? ` (+${ids.length - cap} more — see --json)` : "";
|
|
822
|
+
return shown + extra;
|
|
823
|
+
};
|
|
824
|
+
if (plan.required.length) lines.push(`- Required: ${fmt(plan.required)}`);
|
|
825
|
+
if (plan.recommended.length) lines.push(`- Recommended: ${fmt(plan.recommended)}`);
|
|
826
|
+
if (!plan.required.length && !plan.recommended.length) lines.push("- Required: none");
|
|
827
|
+
lines.push(`Proof next action: ${plan.safeNextAction}`);
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function reasonFor(result) {
|
|
831
|
+
switch (result.decision) {
|
|
832
|
+
case DECISIONS.BLOCKED_BY_OPEN_PR:
|
|
833
|
+
return `${result.matchedDomains[0]} work is represented by open PR #${result.blockedByOpenPRs[0]}.`;
|
|
834
|
+
case DECISIONS.PARALLEL_OWNED:
|
|
835
|
+
return `${result.matchedDomains[0]} is owned by a parallel session (Capability & Evidence Hygiene Pack) / tracked as parallel-owned.`;
|
|
836
|
+
case DECISIONS.NEEDS_AUDIT:
|
|
837
|
+
return `this touches runtime/product surface (${result.matchedDomains[0]}) and requires an audit first.`;
|
|
838
|
+
case DECISIONS.ALREADY_SHIPPED:
|
|
839
|
+
return `this matches a merged feature already recorded in the roadmap ledger (${result.matchedFeatures[0]}).`;
|
|
840
|
+
case DECISIONS.ALREADY_TRACKED:
|
|
841
|
+
return `this matches a follow-up already in the debt register (${result.matchedFollowUps[0]}).`;
|
|
842
|
+
case DECISIONS.SAFE_TO_START:
|
|
843
|
+
return "internal governance work does not overlap open PRs or runtime-sensitive domains.";
|
|
844
|
+
default:
|
|
845
|
+
return "input did not match any known domain, merged feature, or tracked follow-up.";
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
// ---------------------------------------------------------------------------
|
|
850
|
+
// CLI.
|
|
851
|
+
// ---------------------------------------------------------------------------
|
|
852
|
+
|
|
853
|
+
function parseArgs(argv) {
|
|
854
|
+
let json = false;
|
|
855
|
+
const rest = [];
|
|
856
|
+
for (const a of argv) {
|
|
857
|
+
if (a === "--json") json = true;
|
|
858
|
+
else if (a === "--help" || a === "-h") return { help: true };
|
|
859
|
+
else rest.push(a);
|
|
860
|
+
}
|
|
861
|
+
return { json, input: rest.join(" ").trim() };
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
function helpText() {
|
|
865
|
+
return [
|
|
866
|
+
"Avorelo Workstream Preflight v1 (internal)",
|
|
867
|
+
"",
|
|
868
|
+
"Usage:",
|
|
869
|
+
' node scripts/avorelo-workstream-preflight.js "<proposed workstream>"',
|
|
870
|
+
' node scripts/avorelo-workstream-preflight.js --json "<proposed workstream>"',
|
|
871
|
+
"",
|
|
872
|
+
"Decisions: safe_to_start | parallel_owned | blocked_by_open_pr | needs_audit |",
|
|
873
|
+
" already_tracked | already_shipped | unclear",
|
|
874
|
+
"",
|
|
875
|
+
"Read-only. No network, no model, no GitHub API calls.",
|
|
876
|
+
].join("\n");
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
function main(argv) {
|
|
880
|
+
const args = parseArgs(argv);
|
|
881
|
+
if (args.help) {
|
|
882
|
+
process.stdout.write(helpText() + "\n");
|
|
883
|
+
return 0;
|
|
884
|
+
}
|
|
885
|
+
const result = preflight(args.input);
|
|
886
|
+
if (args.json) {
|
|
887
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
888
|
+
} else {
|
|
889
|
+
process.stdout.write(formatText(result) + "\n");
|
|
890
|
+
}
|
|
891
|
+
return 0;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (require.main === module) {
|
|
895
|
+
process.exit(main(process.argv.slice(2)));
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
module.exports = {
|
|
899
|
+
SCHEMA_VERSION,
|
|
900
|
+
PROOF_PLAN_SCHEMA_VERSION,
|
|
901
|
+
PROOF_PLAN_NEXT_ACTION,
|
|
902
|
+
DECISIONS,
|
|
903
|
+
SOURCES,
|
|
904
|
+
REPO_ROOT,
|
|
905
|
+
OPEN_PR_DOMAINS,
|
|
906
|
+
PARALLEL_OWNED_DOMAINS,
|
|
907
|
+
NEEDS_AUDIT_DOMAINS,
|
|
908
|
+
SAFE_INTERNAL_DOMAINS,
|
|
909
|
+
BASELINE_FORBIDDEN_AREAS,
|
|
910
|
+
preflight,
|
|
911
|
+
classify,
|
|
912
|
+
buildProofPlan,
|
|
913
|
+
formatText,
|
|
914
|
+
loadSources,
|
|
915
|
+
normalize,
|
|
916
|
+
parseArgs,
|
|
917
|
+
main,
|
|
918
|
+
};
|