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,359 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// ── Context Acquisition Plan ──────────────────────────────────────────────────
|
|
4
|
+
//
|
|
5
|
+
// Determines what context to acquire for a task — without loading it all.
|
|
6
|
+
// Selects the minimal sufficient context strategy, budget, and fallback.
|
|
7
|
+
//
|
|
8
|
+
// Contract: avorelo.contextAcquisitionPlan.v1
|
|
9
|
+
//
|
|
10
|
+
// Strategy order:
|
|
11
|
+
// 1. project profile / activation facts
|
|
12
|
+
// 2. repo map / symbol map
|
|
13
|
+
// 3. selected package scope
|
|
14
|
+
// 4. git diff summary (if relevant)
|
|
15
|
+
// 5. file slices
|
|
16
|
+
// 6. full file (only if necessary and within budget)
|
|
17
|
+
// 7. fallback + warn if confidence low
|
|
18
|
+
//
|
|
19
|
+
// Non-goals: loading full repo, selecting secrets/sensitive files,
|
|
20
|
+
// automatic full-file fallback without reason.
|
|
21
|
+
|
|
22
|
+
const fs = require("node:fs");
|
|
23
|
+
const path = require("node:path");
|
|
24
|
+
const { nowIso } = require("./fsx");
|
|
25
|
+
const { appendProductLearningEvent } = require("./product-learning-events");
|
|
26
|
+
|
|
27
|
+
const CONTRACT = "avorelo.contextAcquisitionPlan.v1";
|
|
28
|
+
const SCHEMA_VERSION = 1;
|
|
29
|
+
|
|
30
|
+
const PLAN_DIR_REL = ".claude/cco/orchestration/context-acquisition";
|
|
31
|
+
const LATEST_PLAN_REL = `${PLAN_DIR_REL}/latest-plan.json`;
|
|
32
|
+
|
|
33
|
+
const DEFAULT_CONTEXT_BUDGET_TOKENS = 8000;
|
|
34
|
+
const MAX_CONTEXT_BUDGET_TOKENS = 16384;
|
|
35
|
+
|
|
36
|
+
// ── Task classification ───────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
const TASK_PATTERNS = {
|
|
39
|
+
docs: /\b(docs?|documentation|readme|changelog|guide|tutorial|write up|update docs?)\b/i,
|
|
40
|
+
test: /\b(test|spec|jest|vitest|mocha|pytest|unit test|integration test)\b/i,
|
|
41
|
+
// security checked before bugfix so "fix auth vulnerability" classifies as security
|
|
42
|
+
security: /\b(auth(?:entication|orization)?|security|secret|password|rbac|csrf|xss|sql injection|vulnerability|privilege|injection)\b/i,
|
|
43
|
+
bugfix: /\b(fix|bug|broken|regression|error|crash|fail|patch)\b/i,
|
|
44
|
+
refactor: /\b(refactor|cleanup|clean up|restructure|rename|reorganize|simplify)\b/i,
|
|
45
|
+
feature: /\b(add|implement|build|create|new feature|support)\b/i,
|
|
46
|
+
explore: /\b(understand|explore|survey|overview|what does|explain|analyze)\b/i,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
function classifyTask(taskText) {
|
|
50
|
+
if (!taskText) return "unknown";
|
|
51
|
+
for (const [kind, re] of Object.entries(TASK_PATTERNS)) {
|
|
52
|
+
if (re.test(taskText)) return kind;
|
|
53
|
+
}
|
|
54
|
+
return "unknown";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ── Strategy selection ────────────────────────────────────────────────────────
|
|
58
|
+
|
|
59
|
+
function selectContextStrategy(cwd, taskText, repoMap, executionPacket, options = {}) {
|
|
60
|
+
const taskKind = classifyTask(taskText);
|
|
61
|
+
const budget = options.contextBudget || DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
62
|
+
|
|
63
|
+
const strategy = {
|
|
64
|
+
taskKind,
|
|
65
|
+
useProjectProfile: true,
|
|
66
|
+
useRepoMap: true,
|
|
67
|
+
usePackageScope: false,
|
|
68
|
+
useGitDiff: false,
|
|
69
|
+
useFileSlices: false,
|
|
70
|
+
useFullFiles: false,
|
|
71
|
+
requiresApproval: false,
|
|
72
|
+
conservative: false,
|
|
73
|
+
confidence: "medium",
|
|
74
|
+
qualityRisks: [],
|
|
75
|
+
nextAction: null,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Docs task: profile + repo map only, no source
|
|
79
|
+
if (taskKind === "docs") {
|
|
80
|
+
strategy.useFileSlices = false;
|
|
81
|
+
strategy.useFullFiles = false;
|
|
82
|
+
strategy.confidence = "high";
|
|
83
|
+
strategy.nextAction = "Load project profile and repo map; read only doc files.";
|
|
84
|
+
return strategy;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Security task: caution + approval
|
|
88
|
+
if (taskKind === "security") {
|
|
89
|
+
strategy.requiresApproval = true;
|
|
90
|
+
strategy.useFileSlices = true;
|
|
91
|
+
strategy.qualityRisks.push("security_sensitive: do not compress security-critical config");
|
|
92
|
+
strategy.confidence = "low";
|
|
93
|
+
strategy.nextAction = "Review selected files carefully. Approval required before proceeding.";
|
|
94
|
+
return strategy;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Explore task: repo map first, no full dump
|
|
98
|
+
if (taskKind === "explore") {
|
|
99
|
+
strategy.useRepoMap = true;
|
|
100
|
+
strategy.useFileSlices = false;
|
|
101
|
+
strategy.useFullFiles = false;
|
|
102
|
+
strategy.confidence = "medium";
|
|
103
|
+
strategy.nextAction = "Use repo map for overview. Load slices only if specific question requires it.";
|
|
104
|
+
return strategy;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Bug fix: repo map + slices + git diff
|
|
108
|
+
if (taskKind === "bugfix") {
|
|
109
|
+
strategy.useGitDiff = true;
|
|
110
|
+
strategy.useFileSlices = true;
|
|
111
|
+
strategy.confidence = "medium";
|
|
112
|
+
strategy.nextAction = "Load git diff first. Select likely relevant file slices.";
|
|
113
|
+
return strategy;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Test / refactor / feature: slices with optional full file fallback
|
|
117
|
+
if (["test", "refactor", "feature"].includes(taskKind)) {
|
|
118
|
+
strategy.useFileSlices = true;
|
|
119
|
+
strategy.useFullFiles = false; // only if slice insufficient
|
|
120
|
+
strategy.confidence = "medium";
|
|
121
|
+
strategy.nextAction = "Select relevant file slices via repo map symbols.";
|
|
122
|
+
return strategy;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Unknown: conservative
|
|
126
|
+
strategy.conservative = true;
|
|
127
|
+
strategy.useFileSlices = false;
|
|
128
|
+
strategy.confidence = "low";
|
|
129
|
+
strategy.qualityRisks.push("task_unclear: conservative context to avoid quality regression");
|
|
130
|
+
strategy.nextAction = "Task unclear. Use repo map only. Escalate if more context needed.";
|
|
131
|
+
return strategy;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ── Tool/MCP tax — no-connect governor ────────────────────────────────────────
|
|
135
|
+
//
|
|
136
|
+
// Before loading an external tool/MCP, decide deterministically whether local
|
|
137
|
+
// evidence already suffices. Avoids the "tool tax" (loading connectors just in
|
|
138
|
+
// case). Advisory only (claimType heuristic) — records the decision, never hard
|
|
139
|
+
// blocks. Local read tools are always allowed.
|
|
140
|
+
|
|
141
|
+
const LOCAL_EVIDENCE_TOOLS = new Set(["Read", "Grep", "Glob", "LS", "NotebookRead"]);
|
|
142
|
+
const EXTERNAL_TOOL_RE = /^(mcp__|WebFetch|WebSearch|browser|Computer|Fetch)/i;
|
|
143
|
+
// Task kinds where local repo evidence is typically sufficient (no external connect).
|
|
144
|
+
const LOCAL_SUFFICIENT_KINDS = new Set(["docs", "explore", "refactor", "test", "bugfix"]);
|
|
145
|
+
|
|
146
|
+
function hasLocalRepoEvidence(cwd) {
|
|
147
|
+
try {
|
|
148
|
+
const mapPath = path.join(cwd, ".claude/cco/orchestration/repo-map/latest-map.json");
|
|
149
|
+
if (fs.existsSync(mapPath)) return true;
|
|
150
|
+
} catch {}
|
|
151
|
+
try {
|
|
152
|
+
// Any source files present is weak local evidence.
|
|
153
|
+
return fs.existsSync(path.join(cwd, "package.json")) || fs.existsSync(path.join(cwd, "scripts"));
|
|
154
|
+
} catch {}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function buildToolTaxDecision(cwd, input = {}, options = {}) {
|
|
159
|
+
const { toolName = "", taskText = "" } = input;
|
|
160
|
+
const taskKind = classifyTask(taskText);
|
|
161
|
+
const localEvidence =
|
|
162
|
+
typeof input.localEvidenceSufficient === "boolean"
|
|
163
|
+
? input.localEvidenceSufficient
|
|
164
|
+
: hasLocalRepoEvidence(cwd);
|
|
165
|
+
|
|
166
|
+
// Local read tools never incur tool tax.
|
|
167
|
+
if (LOCAL_EVIDENCE_TOOLS.has(toolName)) {
|
|
168
|
+
return { contract: CONTRACT, toolName, taskKind, decision: "local_tool", reasonCode: "local_tool_no_tax", connect: true, claimType: "heuristic", nextAction: null, redacted: true };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const isExternal = EXTERNAL_TOOL_RE.test(toolName);
|
|
172
|
+
if (!isExternal) {
|
|
173
|
+
// Unknown/internal tool — allow, no tax claim.
|
|
174
|
+
return { contract: CONTRACT, toolName, taskKind, decision: "tool_load_required", reasonCode: "non_external_tool", connect: true, claimType: "heuristic", nextAction: null, redacted: true };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// External/MCP tool: avoid the connect when local evidence already covers the task.
|
|
178
|
+
if (localEvidence && LOCAL_SUFFICIENT_KINDS.has(taskKind)) {
|
|
179
|
+
return {
|
|
180
|
+
contract: CONTRACT,
|
|
181
|
+
toolName,
|
|
182
|
+
taskKind,
|
|
183
|
+
decision: "no_connect",
|
|
184
|
+
reasonCode: "tool_load_avoided",
|
|
185
|
+
connect: false,
|
|
186
|
+
claimType: "heuristic",
|
|
187
|
+
nextAction: `Local repo evidence is sufficient for a ${taskKind} task; skip loading ${toolName}.`,
|
|
188
|
+
redacted: true,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
contract: CONTRACT,
|
|
194
|
+
toolName,
|
|
195
|
+
taskKind,
|
|
196
|
+
decision: "tool_load_required",
|
|
197
|
+
reasonCode: localEvidence ? "task_needs_external_evidence" : "no_local_evidence",
|
|
198
|
+
connect: true,
|
|
199
|
+
claimType: "heuristic",
|
|
200
|
+
nextAction: `External evidence needed for ${taskKind || "this"} task; ${toolName} load is justified.`,
|
|
201
|
+
redacted: true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ── Plan builder ──────────────────────────────────────────────────────────────
|
|
206
|
+
|
|
207
|
+
function buildContextAcquisitionPlan(cwd, taskText, options = {}) {
|
|
208
|
+
const budget = options.contextBudget || DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
209
|
+
|
|
210
|
+
// Try to read repo map
|
|
211
|
+
let repoMap = null;
|
|
212
|
+
try {
|
|
213
|
+
const mapPath = path.join(cwd, ".claude/cco/orchestration/repo-map/latest-map.json");
|
|
214
|
+
if (fs.existsSync(mapPath)) {
|
|
215
|
+
repoMap = JSON.parse(fs.readFileSync(mapPath, "utf8"));
|
|
216
|
+
}
|
|
217
|
+
} catch {}
|
|
218
|
+
|
|
219
|
+
// Try to read execution packet
|
|
220
|
+
let executionPacket = null;
|
|
221
|
+
try {
|
|
222
|
+
const packetPath = path.join(cwd, ".claude/cco/orchestration/execution-packet/latest-packet.json");
|
|
223
|
+
if (fs.existsSync(packetPath)) {
|
|
224
|
+
executionPacket = JSON.parse(fs.readFileSync(packetPath, "utf8"));
|
|
225
|
+
}
|
|
226
|
+
} catch {}
|
|
227
|
+
|
|
228
|
+
const strategy = selectContextStrategy(cwd, taskText, repoMap, executionPacket, options);
|
|
229
|
+
const taskKind = strategy.taskKind;
|
|
230
|
+
|
|
231
|
+
// Select relevant files via repo map
|
|
232
|
+
let selectedFiles = [];
|
|
233
|
+
let selectedSymbols = [];
|
|
234
|
+
let fullFileFallbacks = [];
|
|
235
|
+
|
|
236
|
+
if (repoMap && strategy.useFileSlices) {
|
|
237
|
+
try {
|
|
238
|
+
const { selectLikelyRelevantFiles } = require("./repo-map");
|
|
239
|
+
const relevant = selectLikelyRelevantFiles(cwd, taskText, repoMap, options);
|
|
240
|
+
selectedFiles = relevant.slice(0, 10).map((f) => ({ path: f.path, reason: "relevance_score", estimatedTokens: f.estimatedTokens }));
|
|
241
|
+
selectedSymbols = relevant.flatMap((f) => (f.symbols || []).slice(0, 3)).slice(0, 20);
|
|
242
|
+
} catch {}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Slices are symbolic; actual slicing happens in execution
|
|
246
|
+
const slices = strategy.useFileSlices ? selectedFiles.map((f) => ({ path: f.path, type: "slice" })) : [];
|
|
247
|
+
|
|
248
|
+
// Full file fallbacks: only listed if necessary
|
|
249
|
+
if (strategy.useFullFiles) {
|
|
250
|
+
for (const f of selectedFiles.slice(0, 3)) {
|
|
251
|
+
if (f.estimatedTokens && f.estimatedTokens < 2000) {
|
|
252
|
+
fullFileFallbacks.push({ path: f.path, reason: "small_file_full_read_safe" });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const contextBudget = {
|
|
258
|
+
targetTokens: budget,
|
|
259
|
+
maxTokens: MAX_CONTEXT_BUDGET_TOKENS,
|
|
260
|
+
estimatedSelected: selectedFiles.reduce((s, f) => s + (f.estimatedTokens || 0), 0),
|
|
261
|
+
withinBudget: selectedFiles.reduce((s, f) => s + (f.estimatedTokens || 0), 0) < budget,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const excluded = [];
|
|
265
|
+
if (taskKind === "docs") excluded.push({ reason: "docs_task_no_source_context_needed" });
|
|
266
|
+
if (strategy.conservative) excluded.push({ reason: "unknown_task_conservative" });
|
|
267
|
+
if (repoMap && repoMap.sensitiveExcluded > 0) excluded.push({ reason: "sensitive_files_excluded", count: repoMap.sensitiveExcluded });
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
contract: CONTRACT,
|
|
271
|
+
schemaVersion: SCHEMA_VERSION,
|
|
272
|
+
createdAt: nowIso(),
|
|
273
|
+
taskSummary: taskText ? taskText.slice(0, 200) : null,
|
|
274
|
+
taskKind,
|
|
275
|
+
strategy: {
|
|
276
|
+
useProjectProfile: strategy.useProjectProfile,
|
|
277
|
+
useRepoMap: strategy.useRepoMap,
|
|
278
|
+
useGitDiff: strategy.useGitDiff,
|
|
279
|
+
useFileSlices: strategy.useFileSlices,
|
|
280
|
+
useFullFiles: strategy.useFullFiles,
|
|
281
|
+
requiresApproval: strategy.requiresApproval,
|
|
282
|
+
conservative: strategy.conservative,
|
|
283
|
+
},
|
|
284
|
+
selectedFiles,
|
|
285
|
+
selectedSymbols,
|
|
286
|
+
slices,
|
|
287
|
+
excluded,
|
|
288
|
+
fullFileFallbacks,
|
|
289
|
+
contextBudget,
|
|
290
|
+
confidence: strategy.confidence,
|
|
291
|
+
qualityRisks: strategy.qualityRisks,
|
|
292
|
+
nextAction: strategy.nextAction,
|
|
293
|
+
redacted: true,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function writeContextAcquisitionPlan(cwd, plan) {
|
|
298
|
+
const dir = path.join(cwd, PLAN_DIR_REL);
|
|
299
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
300
|
+
const abs = path.join(cwd, LATEST_PLAN_REL);
|
|
301
|
+
fs.writeFileSync(abs, JSON.stringify(plan, null, 2), "utf8");
|
|
302
|
+
try {
|
|
303
|
+
appendProductLearningEvent(cwd, "context_acquisition_plan_generated", {
|
|
304
|
+
taskKind: plan.taskKind,
|
|
305
|
+
confidence: plan.confidence,
|
|
306
|
+
selectedFiles: plan.selectedFiles.length,
|
|
307
|
+
withinBudget: plan.contextBudget.withinBudget,
|
|
308
|
+
requiresApproval: plan.strategy.requiresApproval,
|
|
309
|
+
});
|
|
310
|
+
} catch {}
|
|
311
|
+
return abs;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function buildContextPlanSurface(cwd, options = {}) {
|
|
315
|
+
const abs = path.join(cwd, LATEST_PLAN_REL);
|
|
316
|
+
if (!fs.existsSync(abs)) {
|
|
317
|
+
return { status: "not_available", artifactPath: LATEST_PLAN_REL };
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
const plan = JSON.parse(fs.readFileSync(abs, "utf8"));
|
|
321
|
+
return {
|
|
322
|
+
status: "available",
|
|
323
|
+
taskKind: plan.taskKind,
|
|
324
|
+
confidence: plan.confidence,
|
|
325
|
+
selectedFiles: plan.selectedFiles.length,
|
|
326
|
+
withinBudget: plan.contextBudget.withinBudget,
|
|
327
|
+
artifactPath: LATEST_PLAN_REL,
|
|
328
|
+
};
|
|
329
|
+
} catch {
|
|
330
|
+
return { status: "error", artifactPath: LATEST_PLAN_REL };
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function formatContextPlanText(plan, options = {}) {
|
|
335
|
+
const lines = [`Context Acquisition Plan [${plan.taskKind}]`];
|
|
336
|
+
lines.push(` Confidence: ${plan.confidence} | Approval required: ${plan.strategy.requiresApproval}`);
|
|
337
|
+
lines.push(` Strategy: profile=${plan.strategy.useProjectProfile} repoMap=${plan.strategy.useRepoMap} gitDiff=${plan.strategy.useGitDiff} slices=${plan.strategy.useFileSlices} fullFile=${plan.strategy.useFullFiles}`);
|
|
338
|
+
if (plan.selectedFiles.length) {
|
|
339
|
+
lines.push(` Selected files (${plan.selectedFiles.length}): ${plan.selectedFiles.slice(0, 5).map((f) => f.path).join(", ")}`);
|
|
340
|
+
}
|
|
341
|
+
lines.push(` Budget: ~${plan.contextBudget.estimatedSelected}/${plan.contextBudget.targetTokens} tokens (${plan.contextBudget.withinBudget ? "within" : "over"} budget)`);
|
|
342
|
+
if (plan.qualityRisks.length) lines.push(` Quality risks: ${plan.qualityRisks.join("; ")}`);
|
|
343
|
+
if (plan.nextAction) lines.push(` Next: ${plan.nextAction}`);
|
|
344
|
+
return lines.join("\n");
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = {
|
|
348
|
+
CONTRACT,
|
|
349
|
+
SCHEMA_VERSION,
|
|
350
|
+
PLAN_DIR_REL,
|
|
351
|
+
LATEST_PLAN_REL,
|
|
352
|
+
classifyTask,
|
|
353
|
+
selectContextStrategy,
|
|
354
|
+
buildToolTaxDecision,
|
|
355
|
+
buildContextAcquisitionPlan,
|
|
356
|
+
writeContextAcquisitionPlan,
|
|
357
|
+
buildContextPlanSurface,
|
|
358
|
+
formatContextPlanText,
|
|
359
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const AUTHORITY_ORDER = { high: 3, medium: 2, low: 1 };
|
|
4
|
+
|
|
5
|
+
const RULES = [
|
|
6
|
+
{
|
|
7
|
+
id: "release-beats-planning",
|
|
8
|
+
description: "Release docs beat planning docs",
|
|
9
|
+
apply(refs) {
|
|
10
|
+
return refs.map((r) => {
|
|
11
|
+
if (r.type === "release_doc") return { ...r, authorityBoost: 2 };
|
|
12
|
+
if (r.type === "planning_doc") return { ...r, authorityPenalty: 1 };
|
|
13
|
+
return r;
|
|
14
|
+
});
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "dogfood-beats-claim",
|
|
19
|
+
description: "Dogfood artifact / proof receipt beats claim in prose",
|
|
20
|
+
apply(refs) {
|
|
21
|
+
return refs.map((r) => {
|
|
22
|
+
if (r.type === "proof_artifact" || r.type === "dogfood_artifact") {
|
|
23
|
+
return { ...r, authorityBoost: (r.authorityBoost || 0) + 1 };
|
|
24
|
+
}
|
|
25
|
+
return r;
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "source-beats-screenshot",
|
|
31
|
+
description: "Current source code beats old screenshots",
|
|
32
|
+
apply(refs) {
|
|
33
|
+
return refs.map((r) => {
|
|
34
|
+
if (r.type === "screenshot_ref" && r.freshness !== "fresh") {
|
|
35
|
+
return { ...r, authorityPenalty: (r.authorityPenalty || 0) + 2 };
|
|
36
|
+
}
|
|
37
|
+
if (r.type === "source_code" || r.type === "public_web_source") {
|
|
38
|
+
return { ...r, authorityBoost: (r.authorityBoost || 0) + 1 };
|
|
39
|
+
}
|
|
40
|
+
return r;
|
|
41
|
+
});
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "kernel-beats-scattered",
|
|
46
|
+
description: "Capability Kernel registry beats scattered assumptions",
|
|
47
|
+
apply(refs) {
|
|
48
|
+
return refs.map((r) => {
|
|
49
|
+
if (r.type === "capability_manifest") {
|
|
50
|
+
return { ...r, authorityBoost: (r.authorityBoost || 0) + 1 };
|
|
51
|
+
}
|
|
52
|
+
return r;
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "memory-cannot-override",
|
|
58
|
+
description: "Reentry Memory cannot override source of truth",
|
|
59
|
+
apply(refs) {
|
|
60
|
+
return refs.map((r) => {
|
|
61
|
+
if (r.type === "reentry_memory") {
|
|
62
|
+
return { ...r, authorityPenalty: (r.authorityPenalty || 0) + 1, cannotOverride: true };
|
|
63
|
+
}
|
|
64
|
+
return r;
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "public-needs-public-safe",
|
|
70
|
+
description: "Public copy needs public-safe sources",
|
|
71
|
+
apply(refs, context) {
|
|
72
|
+
if (!context || !context.requiresPublicSafe) return refs;
|
|
73
|
+
return refs.map((r) => {
|
|
74
|
+
if (r.internalOnly && !r.publicSafe) {
|
|
75
|
+
return { ...r, excludedByPublicSafety: true };
|
|
76
|
+
}
|
|
77
|
+
return r;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "evidence-refs-must-be-real",
|
|
83
|
+
description: "Evidence refs must point to real files",
|
|
84
|
+
apply(refs, context) {
|
|
85
|
+
const fs = require("fs");
|
|
86
|
+
const path = require("path");
|
|
87
|
+
const repoRoot = (context && context.repoRoot) || process.cwd();
|
|
88
|
+
return refs.map((r) => {
|
|
89
|
+
if (!r.evidenceRefs || !r.evidenceRefs.length) return r;
|
|
90
|
+
const verified = [];
|
|
91
|
+
for (const ev of r.evidenceRefs) {
|
|
92
|
+
const abs = path.join(repoRoot, ev);
|
|
93
|
+
try { fs.accessSync(abs); verified.push(ev); } catch { /* skip fake */ }
|
|
94
|
+
}
|
|
95
|
+
return { ...r, evidenceRefs: verified };
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "freshness-matters",
|
|
101
|
+
description: "Stale sources get penalties",
|
|
102
|
+
apply(refs) {
|
|
103
|
+
return refs.map((r) => {
|
|
104
|
+
if (r.freshness === "stale") return { ...r, authorityPenalty: (r.authorityPenalty || 0) + 3 };
|
|
105
|
+
if (r.freshness === "possibly_stale") return { ...r, authorityPenalty: (r.authorityPenalty || 0) + 1 };
|
|
106
|
+
return r;
|
|
107
|
+
});
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
function computeAuthorityScore(ref) {
|
|
113
|
+
const base = AUTHORITY_ORDER[ref.authority] || 1;
|
|
114
|
+
const boost = ref.authorityBoost || 0;
|
|
115
|
+
const penalty = ref.authorityPenalty || 0;
|
|
116
|
+
const proofBonus = (ref.evidenceRefs && ref.evidenceRefs.length > 0) ? 1 : 0;
|
|
117
|
+
return base + boost - penalty + proofBonus;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function applyAllRules(refs, context) {
|
|
121
|
+
let result = refs;
|
|
122
|
+
for (const rule of RULES) {
|
|
123
|
+
result = rule.apply(result, context);
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function rankByAuthority(refs) {
|
|
129
|
+
return refs.slice().sort((a, b) => computeAuthorityScore(b) - computeAuthorityScore(a));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = {
|
|
133
|
+
AUTHORITY_ORDER,
|
|
134
|
+
RULES,
|
|
135
|
+
computeAuthorityScore,
|
|
136
|
+
applyAllRules,
|
|
137
|
+
rankByAuthority,
|
|
138
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const BUDGET_REL = ".claude/cco/state/context-budget.json";
|
|
7
|
+
|
|
8
|
+
const DEFAULT_BUDGETS = {
|
|
9
|
+
"cost-saver": {
|
|
10
|
+
maxContextChars: 40000,
|
|
11
|
+
warnAtPercent: 70,
|
|
12
|
+
blockAtPercent: 90,
|
|
13
|
+
maxToolOutputBytes: 12000,
|
|
14
|
+
maxSingleFileBytes: 20000,
|
|
15
|
+
},
|
|
16
|
+
balanced: {
|
|
17
|
+
maxContextChars: 80000,
|
|
18
|
+
warnAtPercent: 70,
|
|
19
|
+
blockAtPercent: 90,
|
|
20
|
+
maxToolOutputBytes: 24000,
|
|
21
|
+
maxSingleFileBytes: 40000,
|
|
22
|
+
},
|
|
23
|
+
quality: {
|
|
24
|
+
maxContextChars: 160000,
|
|
25
|
+
warnAtPercent: 75,
|
|
26
|
+
blockAtPercent: 92,
|
|
27
|
+
maxToolOutputBytes: 48000,
|
|
28
|
+
maxSingleFileBytes: 80000,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DEFAULT_PROFILE = "balanced";
|
|
33
|
+
|
|
34
|
+
function getBudgetForProfile(profile) {
|
|
35
|
+
return DEFAULT_BUDGETS[profile] || DEFAULT_BUDGETS[DEFAULT_PROFILE];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizeBudgetConfig(raw) {
|
|
39
|
+
if (!raw || raw.enabled === false) {
|
|
40
|
+
return { enabled: false };
|
|
41
|
+
}
|
|
42
|
+
const rawProfile = String(raw.profile || DEFAULT_PROFILE);
|
|
43
|
+
const profile = DEFAULT_BUDGETS[rawProfile] ? rawProfile : DEFAULT_PROFILE;
|
|
44
|
+
const base = DEFAULT_BUDGETS[profile];
|
|
45
|
+
return {
|
|
46
|
+
enabled: raw.enabled !== false,
|
|
47
|
+
profile,
|
|
48
|
+
maxContextChars: Number.isFinite(Number(raw.maxContextChars)) ? Math.max(8000, Number(raw.maxContextChars)) : base.maxContextChars,
|
|
49
|
+
warnAtPercent: Number.isFinite(Number(raw.warnAtPercent)) ? Math.min(99, Math.max(10, Number(raw.warnAtPercent))) : base.warnAtPercent,
|
|
50
|
+
blockAtPercent: Number.isFinite(Number(raw.blockAtPercent)) ? Math.min(100, Math.max(50, Number(raw.blockAtPercent))) : base.blockAtPercent,
|
|
51
|
+
maxToolOutputBytes: Number.isFinite(Number(raw.maxToolOutputBytes)) ? Number(raw.maxToolOutputBytes) : base.maxToolOutputBytes,
|
|
52
|
+
maxSingleFileBytes: Number.isFinite(Number(raw.maxSingleFileBytes)) ? Number(raw.maxSingleFileBytes) : base.maxSingleFileBytes,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function estimateChars(text) {
|
|
57
|
+
return typeof text === "string" ? text.length : String(text || "").length;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function computeBudgetState(usedChars, budget) {
|
|
61
|
+
const { maxContextChars, warnAtPercent, blockAtPercent } = budget;
|
|
62
|
+
const usedPercent = maxContextChars > 0 ? (usedChars / maxContextChars) * 100 : 0;
|
|
63
|
+
const isOverWarn = usedPercent >= warnAtPercent;
|
|
64
|
+
const isOverBlock = usedPercent >= blockAtPercent;
|
|
65
|
+
const remainingChars = Math.max(0, maxContextChars - usedChars);
|
|
66
|
+
|
|
67
|
+
let status = "ok";
|
|
68
|
+
if (isOverBlock) status = "critical";
|
|
69
|
+
else if (isOverWarn) status = "warn";
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
usedChars,
|
|
73
|
+
maxContextChars,
|
|
74
|
+
usedPercent: Math.round(usedPercent * 10) / 10,
|
|
75
|
+
remainingChars,
|
|
76
|
+
status,
|
|
77
|
+
warnAtPercent,
|
|
78
|
+
blockAtPercent,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function checkToolOutputSize(outputText, budget) {
|
|
83
|
+
const bytes = Buffer.byteLength(String(outputText || ""), "utf8");
|
|
84
|
+
const isOversized = bytes > budget.maxToolOutputBytes;
|
|
85
|
+
return {
|
|
86
|
+
bytes,
|
|
87
|
+
maxBytes: budget.maxToolOutputBytes,
|
|
88
|
+
isOversized,
|
|
89
|
+
truncateHint: isOversized ? `Output exceeds ${budget.maxToolOutputBytes} bytes. Store out-of-band and reference by path.` : null,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function checkSingleFileSize(fileSizeBytes, budget) {
|
|
94
|
+
const isOversized = fileSizeBytes > budget.maxSingleFileBytes;
|
|
95
|
+
return {
|
|
96
|
+
bytes: fileSizeBytes,
|
|
97
|
+
maxBytes: budget.maxSingleFileBytes,
|
|
98
|
+
isOversized,
|
|
99
|
+
truncateHint: isOversized ? `File exceeds ${budget.maxSingleFileBytes} bytes. Read in chunks or summarize.` : null,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function loadBudgetState(cwd) {
|
|
104
|
+
try {
|
|
105
|
+
const p = path.join(cwd, BUDGET_REL);
|
|
106
|
+
return JSON.parse(fs.readFileSync(p, "utf8"));
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function saveBudgetState(cwd, state) {
|
|
113
|
+
const p = path.join(cwd, BUDGET_REL);
|
|
114
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
115
|
+
fs.writeFileSync(p, JSON.stringify(state, null, 2), "utf8");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function buildBudgetStatus(cwd, rawBudgetConfig) {
|
|
119
|
+
const budget = normalizeBudgetConfig(rawBudgetConfig);
|
|
120
|
+
if (!budget.enabled) {
|
|
121
|
+
return { enabled: false, status: "off" };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const stored = loadBudgetState(cwd);
|
|
125
|
+
const usedChars = stored?.usedChars || 0;
|
|
126
|
+
const budgetState = computeBudgetState(usedChars, budget);
|
|
127
|
+
|
|
128
|
+
const warnings = [];
|
|
129
|
+
if (budgetState.status === "critical") {
|
|
130
|
+
warnings.push(`Context at ${budgetState.usedPercent}% of limit — consider /cco-optimize or summarize large outputs.`);
|
|
131
|
+
} else if (budgetState.status === "warn") {
|
|
132
|
+
warnings.push(`Context at ${budgetState.usedPercent}% of limit — approaching budget.`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
enabled: true,
|
|
137
|
+
status: budgetState.status,
|
|
138
|
+
usedChars: budgetState.usedChars,
|
|
139
|
+
maxContextChars: budgetState.maxContextChars,
|
|
140
|
+
usedPercent: budgetState.usedPercent,
|
|
141
|
+
remainingChars: budgetState.remainingChars,
|
|
142
|
+
warnAtPercent: budgetState.warnAtPercent,
|
|
143
|
+
blockAtPercent: budgetState.blockAtPercent,
|
|
144
|
+
warnings,
|
|
145
|
+
budgetPath: BUDGET_REL,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatBudgetStatusText(budgetStatus) {
|
|
150
|
+
if (!budgetStatus || !budgetStatus.enabled || budgetStatus.status === "off") return null;
|
|
151
|
+
const { status, usedPercent, remainingChars, warnings } = budgetStatus;
|
|
152
|
+
if (status === "ok" && warnings.length === 0) return null;
|
|
153
|
+
const lines = [`Context budget: ${usedPercent}% used, ${remainingChars} chars remaining`];
|
|
154
|
+
warnings.forEach((w) => lines.push(` ⚠ ${w}`));
|
|
155
|
+
return lines.join("\n");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = {
|
|
159
|
+
DEFAULT_BUDGETS,
|
|
160
|
+
getBudgetForProfile,
|
|
161
|
+
normalizeBudgetConfig,
|
|
162
|
+
estimateChars,
|
|
163
|
+
computeBudgetState,
|
|
164
|
+
checkToolOutputSize,
|
|
165
|
+
checkSingleFileSize,
|
|
166
|
+
loadBudgetState,
|
|
167
|
+
saveBudgetState,
|
|
168
|
+
buildBudgetStatus,
|
|
169
|
+
formatBudgetStatusText,
|
|
170
|
+
};
|