@event4u/agent-config 14.9.0 → 14.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +384 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/design.md +88 -0
- package/dist/agent-src/commands/project/analyze.md +47 -0
- package/dist/agent-src/commands/review/changes.md +67 -6
- package/dist/agent-src/commands/roadmap/create.md +49 -0
- package/dist/agent-src/commands/roadmap/next.md +27 -11
- package/dist/agent-src/commands/roadmap/process-full.md +14 -0
- package/dist/agent-src/commands/video/from-script.md +60 -3
- package/dist/agent-src/commands/video/stitch.md +14 -0
- package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
- package/dist/agent-src/rules/active-remediation.md +3 -3
- package/dist/agent-src/rules/code-provenance.md +2 -2
- package/dist/agent-src/rules/context-hygiene.md +13 -33
- package/dist/agent-src/rules/council-availability.md +2 -2
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
- package/dist/agent-src/rules/design-fidelity.md +18 -0
- package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
- package/dist/agent-src/rules/evaluator-independence.md +56 -44
- package/dist/agent-src/rules/fix-what-you-see.md +9 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
- package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
- package/dist/agent-src/rules/playbook-precedence.md +105 -0
- package/dist/agent-src/rules/recurring-criticism.md +3 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
- package/dist/agent-src/rules/scale-discipline.md +24 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
- package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
- package/dist/agent-src/rules/ui-audit-gate.md +27 -15
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
- package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
- package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
- package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +17 -0
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
- package/dist/agent-src/skills/brand/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
- package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
- package/dist/agent-src/skills/code-refactoring/SKILL.md +1 -1
- package/dist/agent-src/skills/code-review/SKILL.md +11 -0
- package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
- package/dist/agent-src/skills/condense-memory/SKILL.md +4 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +4 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
- package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
- package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
- package/dist/agent-src/skills/design-review/SKILL.md +80 -2
- package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
- package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
- package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
- package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
- package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
- package/dist/agent-src/skills/discovery-interview/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +20 -3
- package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
- package/dist/agent-src/skills/fe-design/evals/triggers.json +65 -53
- package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
- package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
- package/dist/agent-src/skills/github-ci/SKILL.md +1 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
- package/dist/agent-src/skills/iconography/SKILL.md +3 -0
- package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
- package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
- package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
- package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +17 -0
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
- package/dist/agent-src/skills/laravel-validation/SKILL.md +1 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
- package/dist/agent-src/skills/legal-intake-triage/SKILL.md +1 -1
- package/dist/agent-src/skills/legal-practice-profile/SKILL.md +1 -1
- package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
- package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
- package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +1 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +1 -1
- package/dist/agent-src/skills/module-management/SKILL.md +1 -1
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
- package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +17 -0
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +7 -1
- package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
- package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
- package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
- package/dist/agent-src/skills/operational-readiness/evals/triggers.json +17 -0
- package/dist/agent-src/skills/override-management/SKILL.md +3 -0
- package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
- package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
- package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
- package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
- package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
- package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +52 -21
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
- package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
- package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
- package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
- package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
- package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
- package/dist/agent-src/skills/scene-expander/SKILL.md +1 -1
- package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
- package/dist/agent-src/skills/secrets-management/SKILL.md +5 -1
- package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
- package/dist/agent-src/skills/server-hardening/evals/triggers.json +17 -0
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
- package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +194 -0
- package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +17 -0
- package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
- package/dist/agent-src/skills/terraform/SKILL.md +3 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
- package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
- package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
- package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
- package/dist/agent-src/skills/workspace-link/evals/triggers.json +17 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/playbook.md +75 -0
- package/dist/agent-src/templates/roadmaps.md +37 -0
- package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
- package/dist/cli/commands/uiAudit.js +221 -0
- package/dist/cli/commands/uiAudit.js.map +1 -0
- package/dist/cli/commands/uiRender.js +206 -0
- package/dist/cli/commands/uiRender.js.map +1 -0
- package/dist/cli/main.js +22 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/content.js +64 -1
- package/dist/cli/mcp/content.js.map +1 -1
- package/dist/cli/mcp/dispatch.js +175 -10
- package/dist/cli/mcp/dispatch.js.map +1 -1
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-236PNQZK.js} +413 -391
- package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
- package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
- package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
- package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-L43NCYPB.js} +5 -0
- package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +8 -6
- package/dist/cli-delegate/cmd_conformance.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +70 -9
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +380 -145
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +18 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -6
- package/dist/hooks/dispatch.js +2337 -1436
- package/dist/install/install.mjs +795 -708
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1685 -1250
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/lean_projection_mode.js +40 -0
- package/dist/scripts/_lib/lean_projection_mode.js.map +1 -0
- package/dist/scripts/_lib/scoped_projection.js +84 -0
- package/dist/scripts/_lib/scoped_projection.js.map +1 -1
- package/dist/scripts/_lib/ui_surface.js +89 -0
- package/dist/scripts/_lib/ui_surface.js.map +1 -0
- package/dist/scripts/condense.js +6 -10
- package/dist/scripts/condense.js.map +1 -1
- package/dist/scripts/project_thin_rules.js +40 -2
- package/dist/scripts/project_thin_rules.js.map +1 -1
- package/dist/server/schemas/settings.js +3 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/skillRanking.js +159 -0
- package/dist/shared/skillRanking.js.map +1 -0
- package/docs/contracts/provider-lifecycle.md +47 -18
- package/docs/contracts/settings-classes.md +14 -4
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
- package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
- package/docs/guidelines/design-antipatterns.md +4 -2
- package/docs/guidelines/design-asset-discipline.md +38 -0
- package/docs/guidelines/design-fidelity-mechanics.md +45 -29
- package/docs/guidelines/design-handover-extraction.md +35 -5
- package/docs/guidelines/design-modes.md +41 -1
- package/docs/guidelines/monorepo-antipatterns.md +141 -0
- package/llms.txt +50 -39
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
- package/src/config/agent-settings.template.yml +28 -0
- package/src/config/assurance-capability-registry.json +223 -0
- package/src/config/assurance-threshold-budget.json +65 -0
- package/src/config/ci-local-parity.yml +14 -0
- package/src/config/discovery/unassigned-artefacts.yml +2 -0
- package/src/config/dispatch-economy-metrics.json +4 -2
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +227 -8
- package/src/config/gate-violation-baselines.json +76 -72
- package/src/config/hook-latency-budget.json +1 -0
- package/src/config/hook-token-budget.json +137 -125
- package/src/config/pack-size-budget.json +4 -2
- package/src/config/preamble-payload-budget.json +71 -67
- package/src/config/quorum-attendance-budget.json +12 -4
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/config/rule-stub-ceilings.json +112 -91
- package/src/scripts/_cli/cmd_doctor.ts +15 -16
- package/src/scripts/_cli/doctor_install_mode.ts +49 -0
- package/src/scripts/_cli/doctor_overrides.ts +154 -0
- package/src/scripts/_dispatch.bash +17 -0
- package/src/scripts/_lib/as_of.ts +412 -0
- package/src/scripts/_lib/exec_evidence.ts +7 -0
- package/src/scripts/_lib/hook_settings.ts +33 -0
- package/src/scripts/_lib/host_listing_model.ts +192 -0
- package/src/scripts/_lib/lean_projection_mode.ts +44 -0
- package/src/scripts/_lib/mcp_bridge.ts +199 -0
- package/src/scripts/_lib/review_independence.ts +62 -10
- package/src/scripts/_lib/rule_injection.ts +239 -0
- package/src/scripts/_lib/run_checkpoint.ts +54 -1
- package/src/scripts/_lib/scoped_projection.ts +96 -0
- package/src/scripts/_lib/session_register.ts +44 -2
- package/src/scripts/_lib/skill_catalogue.ts +38 -2
- package/src/scripts/_lib/transcript_reads.ts +207 -0
- package/src/scripts/_lib/ui_authority.test.ts +251 -0
- package/src/scripts/_lib/ui_authority.ts +343 -0
- package/src/scripts/ai-video/adapters/fal.sh +8 -3
- package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
- package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
- package/src/scripts/ai-video/adapters/kling.sh +10 -0
- package/src/scripts/ai-video/adapters/sora.sh +10 -0
- package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
- package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
- package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
- package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
- package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
- package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
- package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
- package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
- package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
- package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
- package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
- package/src/scripts/ai-video/smoke-trace.sh +450 -2
- package/src/scripts/ai-video/stitch.sh +191 -10
- package/src/scripts/ai-video/test-pipeline.sh +84 -6
- package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
- package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
- package/src/scripts/ai_council/clients.ts +3 -2
- package/src/scripts/ai_council/consensus.ts +63 -6
- package/src/scripts/ai_council/events_log.ts +46 -1
- package/src/scripts/ai_council/orchestrator.ts +103 -108
- package/src/scripts/ai_council/orchestrator_results.ts +166 -0
- package/src/scripts/ai_council/prompts.ts +12 -5
- package/src/scripts/ai_council/quorum.ts +82 -1
- package/src/scripts/ai_council/quorum_wiring.ts +82 -5
- package/src/scripts/ai_council/seating.ts +211 -0
- package/src/scripts/ai_council/stance_tally.ts +22 -0
- package/src/scripts/bench_hook_latency.ts +62 -0
- package/src/scripts/build_proof.ts +12 -1
- package/src/scripts/capture_skill_catalogue.ts +21 -0
- package/src/scripts/check_always_budget.ts +2 -1
- package/src/scripts/check_augmentignore.ts +2 -1
- package/src/scripts/check_beta_review_markers.ts +2 -1
- package/src/scripts/check_composite_arming.ts +364 -0
- package/src/scripts/check_corpus_staleness.ts +2 -1
- package/src/scripts/check_council_pin_staleness.ts +3 -1
- package/src/scripts/check_enforcement_coverage.ts +116 -3
- package/src/scripts/check_enforcement_denominator.ts +365 -0
- package/src/scripts/check_gate_coverage.ts +2 -1
- package/src/scripts/check_hook_bundle_freshness.ts +13 -1
- package/src/scripts/check_knowledge_cards.ts +2 -1
- package/src/scripts/check_knowledge_pages.ts +3 -2
- package/src/scripts/check_memory.ts +2 -1
- package/src/scripts/check_no_automerge_key.ts +287 -0
- package/src/scripts/check_pack_conformance_fixture.ts +565 -0
- package/src/scripts/check_pack_passport_reconciliation.ts +274 -0
- package/src/scripts/check_proposal.ts +2 -1
- package/src/scripts/check_reach_staleness.ts +2 -1
- package/src/scripts/check_release_adjacent_health.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +5 -0
- package/src/scripts/check_review_schema.ts +34 -1
- package/src/scripts/check_roadmap_trackable.ts +48 -3
- package/src/scripts/check_source_size_budget.ts +2 -1
- package/src/scripts/check_standing_payload_delta.ts +505 -0
- package/src/scripts/check_trigger_evals.ts +2 -1
- package/src/scripts/classify_change_risk.ts +281 -0
- package/src/scripts/compute_skill_tiers.ts +186 -0
- package/src/scripts/condense.ts +8 -13
- package/src/scripts/council_attendance_metrics.ts +183 -0
- package/src/scripts/council_cli.ts +10 -8
- package/src/scripts/council_parse_rate.ts +116 -0
- package/src/scripts/derive_playbooks.ts +406 -0
- package/src/scripts/design_slop_rules.test.ts +7 -0
- package/src/scripts/design_slop_rules.ts +56 -2
- package/src/scripts/dispatch_r2_reviewer.ts +16 -0
- package/src/scripts/frontend_corpus_hash.ts +116 -0
- package/src/scripts/generate_pack_manifests.ts +78 -0
- package/src/scripts/grade_target_readiness.ts +478 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +97 -16
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/design_pass_hook.ts +356 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
- package/src/scripts/hooks/rule_inject_hook.ts +318 -0
- package/src/scripts/hot_context_hook.ts +74 -7
- package/src/scripts/install.ts +40 -89
- package/src/scripts/lint_adapter_tier.ts +663 -0
- package/src/scripts/lint_archived_skills.ts +93 -0
- package/src/scripts/lint_budget_ownership.ts +2 -1
- package/src/scripts/lint_deterministic_time.ts +470 -0
- package/src/scripts/lint_framework_leakage.ts +5 -0
- package/src/scripts/lint_handoffs.ts +525 -1
- package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
- package/src/scripts/lint_marketplace.ts +88 -0
- package/src/scripts/lint_media_policy_linkage.ts +140 -1
- package/src/scripts/lint_one_off_age.ts +6 -1
- package/src/scripts/lint_override_kernel_guard.ts +87 -5
- package/src/scripts/lint_roadmap_complexity.ts +56 -0
- package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
- package/src/scripts/lint_rule_norm_pin.ts +321 -0
- package/src/scripts/lint_spawn_payload.ts +42 -5
- package/src/scripts/lint_symptom_intake.ts +2 -1
- package/src/scripts/mcp_parity_smoke.ts +30 -4
- package/src/scripts/mcp_render.ts +66 -1
- package/src/scripts/mcp_tool_fingerprint.ts +241 -0
- package/src/scripts/measure_risk_class_drift.ts +140 -0
- package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
- package/src/scripts/media/lib/adapter-common.sh +211 -1
- package/src/scripts/media/lib/adapter-contract.md +74 -6
- package/src/scripts/model_rule_injection.ts +907 -0
- package/src/scripts/project_thin_rules.ts +45 -2
- package/src/scripts/release.ts +66 -860
- package/src/scripts/release_drill.ts +59 -3
- package/src/scripts/release_env.ts +298 -0
- package/src/scripts/release_publication.ts +720 -0
- package/src/scripts/roadmap_context.ts +778 -0
- package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
- package/src/scripts/schemas/pack.schema.json +62 -4
- package/src/scripts/schemas/rule.schema.json +24 -2
- package/src/scripts/schemas/skill.schema.json +41 -2
- package/src/scripts/schemas/ui-authority.schema.json +114 -0
- package/src/scripts/session_register_hook.ts +29 -3
- package/src/scripts/sessions_cli.ts +67 -3
- package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
- package/src/scripts/tighten_skill_descriptions.ts +264 -0
- package/src/scripts/token_sink_report.ts +239 -0
- package/src/scripts/trigger_coverage.ts +122 -3
- package/src/scripts/update_counts.ts +7 -3
- package/src/scripts/validate_frontmatter.ts +66 -0
- package/src/server/schemas/settings.ts +5 -0
- package/src/shared/skillRanking.ts +183 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
#!/usr/bin/env -S npx tsx
|
|
2
|
+
/**
|
|
3
|
+
* Per-PR standing-payload delta against the merge-base — a REPORT, not a gate.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-standing-payload-diet` Phase 0 steps 0.3 / 0.4 / 0.5.
|
|
6
|
+
*
|
|
7
|
+
* ## Why a report and not a second failing gate
|
|
8
|
+
*
|
|
9
|
+
* `check_preamble_payload_budget` already ratchets the same number and already
|
|
10
|
+
* fails on growth. A second blocking gate on one measurement double-fails every
|
|
11
|
+
* legitimate rule addition, which is how a reporting surface becomes noise
|
|
12
|
+
* people route around. So this script **never fails on the delta**, in either
|
|
13
|
+
* direction. It fails only when it cannot measure: a bad ref (exit 2) or a dead
|
|
14
|
+
* scan scope (exit 3). That split is what makes its self-test honest — there are
|
|
15
|
+
* real reject cases, and none of them is "the number moved".
|
|
16
|
+
*
|
|
17
|
+
* ## The ledger is TWO-SIDED, and that is step 0.5
|
|
18
|
+
*
|
|
19
|
+
* Steps 0.3/0.4 measured only the debit — what a change ADDS. A one-sided
|
|
20
|
+
* ledger can only ever report drift: a change that REMOVES standing payload
|
|
21
|
+
* scores zero and reads as neutral, which is exactly backwards for a roadmap
|
|
22
|
+
* whose whole purpose is removal. So every bucket reports debit and credit
|
|
23
|
+
* separately, and the credit side carries a standing booking that is already
|
|
24
|
+
* measured and already shipped — the ADR-236 one-rule-one-layer partition. See
|
|
25
|
+
* {@link partitionCredit}.
|
|
26
|
+
*
|
|
27
|
+
* ## Parity with the gate it reports beside
|
|
28
|
+
*
|
|
29
|
+
* The bucket definitions are IMPORTED from `preamble_byte_census`, never
|
|
30
|
+
* re-implemented, so the delta cannot drift from the ratchet it explains. The
|
|
31
|
+
* basis is therefore the census's own `chars/4` proxy for the bucket totals —
|
|
32
|
+
* stated in every rendering, because this tree ships an exact tokenizer and a
|
|
33
|
+
* report that hides which one it used is not evidence. `--rank` additionally
|
|
34
|
+
* publishes an EXACT-BPE per-rule ranking, and labels it as the other basis.
|
|
35
|
+
* The two are never mixed inside one subtraction.
|
|
36
|
+
*
|
|
37
|
+
* Modes:
|
|
38
|
+
* --base <ref> measure the same buckets at <ref> and print the signed delta
|
|
39
|
+
* --rank additionally print the exact-BPE per-rule ranking at HEAD
|
|
40
|
+
* --json machine-readable, for the PR-comment renderer
|
|
41
|
+
* --quiet verdict lines only
|
|
42
|
+
* --self-test prove the gate discriminates
|
|
43
|
+
*
|
|
44
|
+
* Exit codes: 0 measured (any delta) · 2 usage / unreadable ref · 3 dead scope.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
import { execFileSync } from 'node:child_process';
|
|
48
|
+
import * as fs from 'node:fs';
|
|
49
|
+
import * as os from 'node:os';
|
|
50
|
+
import * as path from 'node:path';
|
|
51
|
+
import process from 'node:process';
|
|
52
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
53
|
+
|
|
54
|
+
import { GateLedger } from './_lib/gate_ledger.js';
|
|
55
|
+
import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
56
|
+
import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
|
|
57
|
+
import { gpt_tokens, method_note } from './_lib/token_count.js';
|
|
58
|
+
import { measureDeterministicPayload } from './check_preamble_payload_budget.js';
|
|
59
|
+
import { censusRuleDir } from './preamble_byte_census.js';
|
|
60
|
+
|
|
61
|
+
const PROG = 'check_standing_payload_delta';
|
|
62
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
63
|
+
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
64
|
+
const SCRIPT_REL = 'src/scripts/check_standing_payload_delta.ts';
|
|
65
|
+
const SELF_TEST_MIN_CASES = 4;
|
|
66
|
+
const SELF_TEST_MIN_REJECT = 2;
|
|
67
|
+
|
|
68
|
+
/** The three buckets `check_preamble_payload_budget` gates, by ledger name. */
|
|
69
|
+
const BUCKETS = [
|
|
70
|
+
'project-scope rules',
|
|
71
|
+
'preloaded skills catalog',
|
|
72
|
+
'CLAUDE.md hierarchy (project only)',
|
|
73
|
+
] as const;
|
|
74
|
+
|
|
75
|
+
export interface Bucket {
|
|
76
|
+
readonly name: string;
|
|
77
|
+
readonly tokens: number;
|
|
78
|
+
readonly files: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** `chars/4`, the census's own basis — kept identical so the delta cannot drift. */
|
|
82
|
+
function proxyTokens(chars: number): number {
|
|
83
|
+
return Math.round(chars / 4);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Measure the three gated buckets over a checkout root.
|
|
88
|
+
*
|
|
89
|
+
* Delegates to `check_preamble_payload_budget.measureDeterministicPayload`, the
|
|
90
|
+
* ratchet's OWN bucket builder, rather than re-deriving the definitions. A
|
|
91
|
+
* second implementation would be free to drift from the number it explains, and
|
|
92
|
+
* the drift would look like a real delta.
|
|
93
|
+
*
|
|
94
|
+
* That function already pins the user half of the CLAUDE.md hierarchy to a
|
|
95
|
+
* non-existent home directory, so a ref-side measurement cannot read the
|
|
96
|
+
* measuring machine's home and attribute it to a past commit — the property this
|
|
97
|
+
* function needed, inherited rather than re-stated.
|
|
98
|
+
*/
|
|
99
|
+
export function measureBuckets(root: string): Bucket[] {
|
|
100
|
+
return measureDeterministicPayload(root);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Raw bytes of one tracked path at `ref`, or `null` when it does not exist there. */
|
|
104
|
+
function catBlob(repoRoot: string, ref: string, rel: string): Buffer | null {
|
|
105
|
+
try {
|
|
106
|
+
return execFileSync('git', ['show', `${ref}:${rel}`], {
|
|
107
|
+
cwd: repoRoot,
|
|
108
|
+
maxBuffer: 1 << 28,
|
|
109
|
+
encoding: 'buffer',
|
|
110
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
111
|
+
});
|
|
112
|
+
} catch {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Git's file mode for one tracked path at `ref` (`'120000'` = symlink), or null. */
|
|
118
|
+
function blobMode(repoRoot: string, ref: string, rel: string): string | null {
|
|
119
|
+
try {
|
|
120
|
+
const line = execFileSync('git', ['ls-tree', ref, '--', rel], {
|
|
121
|
+
cwd: repoRoot,
|
|
122
|
+
encoding: 'utf-8',
|
|
123
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
124
|
+
}).trim();
|
|
125
|
+
return line === '' ? null : (line.split(/\s+/)[0] ?? null);
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* One tracked file's CONTENT at `ref`, following a tracked symlink.
|
|
133
|
+
*
|
|
134
|
+
* `CLAUDE.md` in this repo is a symlink to `AGENTS.md` (mode `120000`,
|
|
135
|
+
* verified), so `git show <ref>:CLAUDE.md` yields the nine-byte link TARGET
|
|
136
|
+
* rather than the file. Measured on the first run: the base side reported 2
|
|
137
|
+
* tokens against a real 746, fabricating a +744 debit out of the symlink. A
|
|
138
|
+
* checkout resolves the link transparently; a blob read does not, so the hop is
|
|
139
|
+
* taken here. Bounded to two hops — this repo has one level and a cycle must not
|
|
140
|
+
* become a hang.
|
|
141
|
+
*/
|
|
142
|
+
function readBlob(repoRoot: string, ref: string, rel: string): Buffer | null {
|
|
143
|
+
let target = rel;
|
|
144
|
+
for (let hop = 0; hop < 2; hop += 1) {
|
|
145
|
+
const raw = catBlob(repoRoot, ref, target);
|
|
146
|
+
if (raw === null) return null;
|
|
147
|
+
if (blobMode(repoRoot, ref, target) !== '120000') return raw;
|
|
148
|
+
const link = raw.toString('utf-8').trim();
|
|
149
|
+
target = path.posix.normalize(path.posix.join(path.posix.dirname(target), link));
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Materialise `<ref>`'s gated tree into a temp dir. Returns the root. */
|
|
155
|
+
export function checkoutRefTree(ref: string, repoRoot: string = REPO_ROOT): string {
|
|
156
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'spd-base-'));
|
|
157
|
+
// `git archive | tar -x` is one round trip and honours `export-ignore`;
|
|
158
|
+
// `dist/` carries no `export-ignore` entry (verified: .gitattributes has no
|
|
159
|
+
// `/dist` line), so the gated buckets survive the tarball intact.
|
|
160
|
+
try {
|
|
161
|
+
const tar = execFileSync('git', ['archive', ref, 'dist/agent-src/rules', 'dist/agent-src/skills'], {
|
|
162
|
+
cwd: repoRoot,
|
|
163
|
+
maxBuffer: 1 << 30,
|
|
164
|
+
encoding: 'buffer',
|
|
165
|
+
});
|
|
166
|
+
execFileSync('tar', ['-x', '-C', dir], { input: tar, maxBuffer: 1 << 30 });
|
|
167
|
+
// `CLAUDE.md` carries `export-ignore` (`.gitattributes:26`), so `git
|
|
168
|
+
// archive` omits it SILENTLY — measured here on the first run, which
|
|
169
|
+
// reported a fabricated 104-token movement in the wrong bucket. It is
|
|
170
|
+
// therefore fetched by blob, not by tarball. A missing project CLAUDE.md
|
|
171
|
+
// at `ref` is a real state (the file may not have existed), so absence
|
|
172
|
+
// is left absent rather than defaulted.
|
|
173
|
+
const claudeMd = readBlob(repoRoot, ref, 'CLAUDE.md');
|
|
174
|
+
if (claudeMd !== null) fs.writeFileSync(path.join(dir, 'CLAUDE.md'), claudeMd);
|
|
175
|
+
const claudeLocal = readBlob(repoRoot, ref, 'CLAUDE.local.md');
|
|
176
|
+
if (claudeLocal !== null) fs.writeFileSync(path.join(dir, 'CLAUDE.local.md'), claudeLocal);
|
|
177
|
+
} catch (err) {
|
|
178
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
179
|
+
throw new Error(`${PROG}: cannot read tree at ref '${ref}': ${String(err)}`);
|
|
180
|
+
}
|
|
181
|
+
return dir;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export interface DeltaRow {
|
|
185
|
+
readonly name: string;
|
|
186
|
+
/** Positive tokens the change ADDS to this bucket. */
|
|
187
|
+
readonly debit: number;
|
|
188
|
+
/** Positive tokens the change REMOVES from this bucket. */
|
|
189
|
+
readonly credit: number;
|
|
190
|
+
readonly base: number;
|
|
191
|
+
readonly head: number;
|
|
192
|
+
readonly baseFiles: number;
|
|
193
|
+
readonly headFiles: number;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Split each bucket's signed movement into a debit and a credit column.
|
|
198
|
+
*
|
|
199
|
+
* A signed number collapses the two sides into one cell, and the whole point of
|
|
200
|
+
* step 0.5 is that a removal must be legible as a removal rather than as a
|
|
201
|
+
* smaller positive.
|
|
202
|
+
*/
|
|
203
|
+
export function diffBuckets(base: readonly Bucket[], head: readonly Bucket[]): DeltaRow[] {
|
|
204
|
+
const byName = new Map(base.map((b) => [b.name, b]));
|
|
205
|
+
return head.map((h) => {
|
|
206
|
+
const b = byName.get(h.name) ?? { name: h.name, tokens: 0, files: 0 };
|
|
207
|
+
const signed = h.tokens - b.tokens;
|
|
208
|
+
return {
|
|
209
|
+
name: h.name,
|
|
210
|
+
debit: signed > 0 ? signed : 0,
|
|
211
|
+
credit: signed < 0 ? -signed : 0,
|
|
212
|
+
base: b.tokens,
|
|
213
|
+
head: h.tokens,
|
|
214
|
+
baseFiles: b.files,
|
|
215
|
+
headFiles: h.files,
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface CreditBooking {
|
|
221
|
+
readonly what: string;
|
|
222
|
+
readonly gate: string;
|
|
223
|
+
readonly tokens: number;
|
|
224
|
+
readonly note: string;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* The standing credit booking — ADR-236's one-rule-one-layer partition.
|
|
229
|
+
*
|
|
230
|
+
* `check_rule_layer_partition` publishes, per host directory, how many rules the
|
|
231
|
+
* project layer WITHHELD because the global layer already carries them. Those
|
|
232
|
+
* withheld files are a saving that is already measured and already shipped, and
|
|
233
|
+
* a debit-only ledger books it at zero.
|
|
234
|
+
*
|
|
235
|
+
* It is a **standing** booking, not a per-PR one: it does not move with the diff
|
|
236
|
+
* under review, and it is rendered as such. Its purpose is that a reader of the
|
|
237
|
+
* comment sees net movement against a real credit floor rather than inflow
|
|
238
|
+
* alone. The number is read from the live gate on the measuring machine; where
|
|
239
|
+
* the gate cannot run (no projections in a fresh CI checkout, which is the
|
|
240
|
+
* normal case) the booking reports as unavailable rather than as zero — a
|
|
241
|
+
* credit of zero and a credit nobody could read are different facts.
|
|
242
|
+
*/
|
|
243
|
+
export function partitionCredit(repoRoot: string = REPO_ROOT): CreditBooking | null {
|
|
244
|
+
const globalDir = path.join(os.homedir(), '.claude', 'rules');
|
|
245
|
+
const projectDir = path.join(repoRoot, '.claude', 'rules');
|
|
246
|
+
if (!fs.existsSync(globalDir) || !fs.existsSync(projectDir)) return null;
|
|
247
|
+
const globalCensus = censusRuleDir(globalDir);
|
|
248
|
+
const projectCensus = censusRuleDir(projectDir);
|
|
249
|
+
if (globalCensus.files === 0) return null;
|
|
250
|
+
const globalNames = new Set(fs.readdirSync(globalDir).filter((f) => f.endsWith('.md')));
|
|
251
|
+
const projectNames = new Set(fs.readdirSync(projectDir).filter((f) => f.endsWith('.md')));
|
|
252
|
+
// Withheld = a global-owned rule the project layer did NOT re-emit. Under a
|
|
253
|
+
// duplicating emitter this set is empty and the credit is honestly zero.
|
|
254
|
+
let withheldChars = 0;
|
|
255
|
+
let withheld = 0;
|
|
256
|
+
for (const name of globalNames) {
|
|
257
|
+
if (projectNames.has(name)) continue;
|
|
258
|
+
try {
|
|
259
|
+
withheldChars += fs.statSync(path.join(globalDir, name)).size;
|
|
260
|
+
withheld += 1;
|
|
261
|
+
} catch {
|
|
262
|
+
/* unreadable entry — not counted, so the credit under-reports */
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
what: `ADR-236 partition: ${String(withheld)} global-owned rule(s) withheld from .claude/rules`,
|
|
267
|
+
gate: 'check_rule_layer_partition',
|
|
268
|
+
tokens: proxyTokens(withheldChars),
|
|
269
|
+
note:
|
|
270
|
+
`project layer carries ${String(projectCensus.files)} file(s); global layer ` +
|
|
271
|
+
`${String(globalCensus.files)}. A duplicating emitter would book 0 here.`,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface PerRule {
|
|
276
|
+
readonly rule: string;
|
|
277
|
+
readonly tokens: number;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/** Exact-BPE per-rule ranking at HEAD — the other basis, labelled as such. */
|
|
281
|
+
export function rankRules(dir: string): PerRule[] {
|
|
282
|
+
let entries: string[];
|
|
283
|
+
try {
|
|
284
|
+
entries = fs.readdirSync(dir);
|
|
285
|
+
} catch {
|
|
286
|
+
return [];
|
|
287
|
+
}
|
|
288
|
+
const rows: PerRule[] = [];
|
|
289
|
+
for (const name of entries) {
|
|
290
|
+
if (!name.endsWith('.md')) continue;
|
|
291
|
+
try {
|
|
292
|
+
rows.push({ rule: name, tokens: gpt_tokens(fs.readFileSync(path.join(dir, name), 'utf-8')).tokens });
|
|
293
|
+
} catch {
|
|
294
|
+
/* unreadable entry — skipped rather than failing the whole ranking */
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
rows.sort((a, b) => b.tokens - a.tokens);
|
|
298
|
+
return rows;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
export interface Report {
|
|
302
|
+
readonly base_ref: string | null;
|
|
303
|
+
readonly basis: string;
|
|
304
|
+
readonly rank_basis: string;
|
|
305
|
+
readonly buckets: Bucket[];
|
|
306
|
+
readonly rows: DeltaRow[];
|
|
307
|
+
readonly total_debit: number;
|
|
308
|
+
readonly total_credit: number;
|
|
309
|
+
readonly net: number;
|
|
310
|
+
readonly credit_bookings: CreditBooking[];
|
|
311
|
+
readonly ranking: PerRule[];
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function buildReport(opts: { base: string | null; rank: boolean }): Report {
|
|
315
|
+
const head = measureBuckets(REPO_ROOT);
|
|
316
|
+
let rows: DeltaRow[] = [];
|
|
317
|
+
if (opts.base !== null) {
|
|
318
|
+
const dir = checkoutRefTree(opts.base);
|
|
319
|
+
try {
|
|
320
|
+
rows = diffBuckets(measureBuckets(dir), head);
|
|
321
|
+
} finally {
|
|
322
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const booking = partitionCredit();
|
|
326
|
+
return {
|
|
327
|
+
base_ref: opts.base,
|
|
328
|
+
basis: 'chars/4 proxy over the projected tree (identical to preamble_byte_census)',
|
|
329
|
+
rank_basis: method_note(),
|
|
330
|
+
buckets: head,
|
|
331
|
+
rows,
|
|
332
|
+
total_debit: rows.reduce((s, r) => s + r.debit, 0),
|
|
333
|
+
total_credit: rows.reduce((s, r) => s + r.credit, 0),
|
|
334
|
+
net: rows.reduce((s, r) => s + r.debit - r.credit, 0),
|
|
335
|
+
credit_bookings: booking === null ? [] : [booking],
|
|
336
|
+
ranking: opts.rank ? rankRules(path.join(REPO_ROOT, 'dist', 'agent-src', 'rules')) : [],
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function renderMarkdown(r: Report): string {
|
|
341
|
+
const sign = (n: number): string => (n > 0 ? `+${String(n)}` : String(n));
|
|
342
|
+
const out: string[] = ['## Standing payload — per-PR delta (report only)', ''];
|
|
343
|
+
out.push(`**Basis:** ${r.basis}. This step **reports**; \`check_preamble_payload_budget\` is the gate.`, '');
|
|
344
|
+
if (r.base_ref === null) {
|
|
345
|
+
out.push('_No base ref given — HEAD buckets only._', '');
|
|
346
|
+
} else {
|
|
347
|
+
out.push(`**Merge-base:** \`${r.base_ref}\``, '');
|
|
348
|
+
out.push('| Bucket | base | head | debit | credit |', '|---|---:|---:|---:|---:|');
|
|
349
|
+
for (const row of r.rows) {
|
|
350
|
+
out.push(
|
|
351
|
+
`| ${row.name} (${String(row.baseFiles)} → ${String(row.headFiles)} files) ` +
|
|
352
|
+
`| ${String(row.base)} | ${String(row.head)} | ` +
|
|
353
|
+
`${row.debit === 0 ? '—' : `+${String(row.debit)}`} | ` +
|
|
354
|
+
`${row.credit === 0 ? '—' : `−${String(row.credit)}`} |`,
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
out.push(
|
|
358
|
+
`| **total** | | | **+${String(r.total_debit)}** | **−${String(r.total_credit)}** |`,
|
|
359
|
+
'',
|
|
360
|
+
`**Net:** \`${sign(r.net)}\` tok on the gated per-spawn payload.`,
|
|
361
|
+
'',
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
out.push('### Credit side (standing bookings)', '');
|
|
365
|
+
if (r.credit_bookings.length === 0) {
|
|
366
|
+
out.push(
|
|
367
|
+
'_Unavailable in this environment: no host rule projection to read, so the ' +
|
|
368
|
+
'partition credit cannot be measured here. Unavailable is reported as ' +
|
|
369
|
+
'unavailable, never as zero._',
|
|
370
|
+
'',
|
|
371
|
+
);
|
|
372
|
+
} else {
|
|
373
|
+
out.push('| Booking | measured by | tokens |', '|---|---|---:|');
|
|
374
|
+
for (const b of r.credit_bookings) {
|
|
375
|
+
out.push(`| ${b.what} | \`${b.gate}\` | −${String(b.tokens)} |`);
|
|
376
|
+
}
|
|
377
|
+
out.push('', ...r.credit_bookings.map((b) => `_${b.note}_`), '');
|
|
378
|
+
}
|
|
379
|
+
if (r.ranking.length > 0) {
|
|
380
|
+
out.push(`### Heaviest projected rules (${r.rank_basis})`, '');
|
|
381
|
+
out.push('| tokens | rule |', '|---:|---|');
|
|
382
|
+
for (const p of r.ranking.slice(0, 20)) out.push(`| ${String(p.tokens)} | \`${p.rule}\` |`);
|
|
383
|
+
out.push('');
|
|
384
|
+
}
|
|
385
|
+
return out.join('\n');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function parse(argv: readonly string[]): { base: string | null; rank: boolean; json: boolean; quiet: boolean } {
|
|
389
|
+
let base: string | null = null;
|
|
390
|
+
let rank = false;
|
|
391
|
+
let json = false;
|
|
392
|
+
let quiet = false;
|
|
393
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
394
|
+
const a = argv[i];
|
|
395
|
+
if (a === '--base') {
|
|
396
|
+
const v = argv[i + 1];
|
|
397
|
+
if (v === undefined || v.startsWith('--')) throw new Error(`${PROG}: --base needs a ref`);
|
|
398
|
+
base = v;
|
|
399
|
+
i += 1;
|
|
400
|
+
} else if (a === '--rank') rank = true;
|
|
401
|
+
else if (a === '--json') json = true;
|
|
402
|
+
else if (a === '--quiet') quiet = true;
|
|
403
|
+
else throw new Error(`${PROG}: unknown argument '${String(a)}'`);
|
|
404
|
+
}
|
|
405
|
+
return { base, rank, json, quiet };
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
409
|
+
if (argv.includes('--self-test')) return selfTest();
|
|
410
|
+
let opts: ReturnType<typeof parse>;
|
|
411
|
+
try {
|
|
412
|
+
opts = parse(argv);
|
|
413
|
+
} catch (err) {
|
|
414
|
+
process.stderr.write(`${String((err as Error).message)}\n`);
|
|
415
|
+
return 2;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let report: Report;
|
|
419
|
+
try {
|
|
420
|
+
report = buildReport({ base: opts.base, rank: opts.rank });
|
|
421
|
+
} catch (err) {
|
|
422
|
+
process.stderr.write(`${String((err as Error).message)}\n`);
|
|
423
|
+
return 2;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Ledger: one target per gated bucket, so "measured nothing" and "measured
|
|
427
|
+
// one of three" stop being the same green line.
|
|
428
|
+
const ledger = new GateLedger(PROG);
|
|
429
|
+
ledger.plan([...BUCKETS]);
|
|
430
|
+
for (const b of report.buckets) {
|
|
431
|
+
if (b.files === 0) ledger.skip(b.name, 'no_applicable_files');
|
|
432
|
+
else ledger.complete(b.name);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (opts.json) {
|
|
436
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
437
|
+
} else if (!opts.quiet) {
|
|
438
|
+
process.stdout.write(`${renderMarkdown(report)}\n`);
|
|
439
|
+
} else {
|
|
440
|
+
const sign = report.net > 0 ? `+${String(report.net)}` : String(report.net);
|
|
441
|
+
process.stdout.write(
|
|
442
|
+
`${PROG}: net ${sign} tok (debit +${String(report.total_debit)} / ` +
|
|
443
|
+
`credit −${String(report.total_credit)}) vs ${report.base_ref ?? '(no base)'}\n`,
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const scanned = report.buckets.filter((b) => b.files > 0).length;
|
|
448
|
+
try {
|
|
449
|
+
reportScanned({ gate: PROG, scanned, units: 'gated payload bucket(s)', roots: ['dist/agent-src'] });
|
|
450
|
+
} catch (err) {
|
|
451
|
+
if (err instanceof DeadScopeError) {
|
|
452
|
+
process.stderr.write(`❌ ${err.message}\n`);
|
|
453
|
+
return 3;
|
|
454
|
+
}
|
|
455
|
+
throw err;
|
|
456
|
+
}
|
|
457
|
+
ledger.report();
|
|
458
|
+
// Report-only by contract: a moved number is never a failure here.
|
|
459
|
+
return 0;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Prove the gate discriminates.
|
|
464
|
+
*
|
|
465
|
+
* The reject cases are deliberately NOT "the delta is large" — a report that
|
|
466
|
+
* failed on its own number would be the second blocking gate this script exists
|
|
467
|
+
* not to be. They are the two ways it can fail to MEASURE: an unreadable ref and
|
|
468
|
+
* a usage error. The accept cases prove a real delta and a no-base run both
|
|
469
|
+
* still exit 0.
|
|
470
|
+
*/
|
|
471
|
+
function selfTest(): number {
|
|
472
|
+
const cases: SelfTestCase[] = [
|
|
473
|
+
{
|
|
474
|
+
name: 'unreadable base ref → exit 2',
|
|
475
|
+
expect: 'reject',
|
|
476
|
+
run: () => runGateCli(REPO_ROOT, SCRIPT_REL, ['--base', 'no-such-ref-xyzzy', '--quiet'], REPO_ROOT),
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
name: 'unknown argument → exit 2',
|
|
480
|
+
expect: 'reject',
|
|
481
|
+
run: () => runGateCli(REPO_ROOT, SCRIPT_REL, ['--nonsense'], REPO_ROOT),
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
name: 'no base ref → HEAD-only report, exit 0',
|
|
485
|
+
expect: 'accept',
|
|
486
|
+
run: () => runGateCli(REPO_ROOT, SCRIPT_REL, ['--quiet'], REPO_ROOT),
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: 'real base ref → measured delta, still exit 0',
|
|
490
|
+
expect: 'accept',
|
|
491
|
+
run: () => runGateCli(REPO_ROOT, SCRIPT_REL, ['--base', 'HEAD', '--quiet'], REPO_ROOT),
|
|
492
|
+
},
|
|
493
|
+
];
|
|
494
|
+
return runSelfTest({ gate: PROG, cases, minCases: SELF_TEST_MIN_CASES, minRejectCases: SELF_TEST_MIN_REJECT });
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function invokedDirectly(): boolean {
|
|
498
|
+
const entry = process.argv[1];
|
|
499
|
+
if (entry === undefined) return false;
|
|
500
|
+
return import.meta.url === pathToFileURL(path.resolve(entry)).href;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (invokedDirectly()) {
|
|
504
|
+
process.exit(main());
|
|
505
|
+
}
|
|
@@ -27,6 +27,7 @@ import * as fs from 'node:fs';
|
|
|
27
27
|
import * as path from 'node:path';
|
|
28
28
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
29
29
|
|
|
30
|
+
import { asOf } from './_lib/as_of.js';
|
|
30
31
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
31
32
|
|
|
32
33
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
@@ -99,7 +100,7 @@ function _days_between(a: PyDate, b: PyDate): number {
|
|
|
99
100
|
|
|
100
101
|
/** Today's local date, matching `date.today()`. */
|
|
101
102
|
function _today_local(): PyDate {
|
|
102
|
-
const now =
|
|
103
|
+
const now = asOf();
|
|
103
104
|
return { year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() };
|
|
104
105
|
}
|
|
105
106
|
|