@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
|
@@ -37,8 +37,9 @@ import {
|
|
|
37
37
|
type QuorumCommand,
|
|
38
38
|
type QuorumDispatch,
|
|
39
39
|
type QuorumEventPhase,
|
|
40
|
+
type StanceAgreement,
|
|
40
41
|
} from './events_log.js';
|
|
41
|
-
import { evaluateQuorum, SOLO_FLOOR_MIN_PRESENT, type QuorumResult } from './quorum.js';
|
|
42
|
+
import { evaluateQuorum, formatAttendanceCaveats, SOLO_FLOOR_MIN_PRESENT, withUnparsed, type QuorumResult } from './quorum.js';
|
|
42
43
|
import { absentReasonFromCliFailure, classifyCliFailure } from './transport_resolver.js';
|
|
43
44
|
|
|
44
45
|
type Dict = Record<string, unknown>;
|
|
@@ -117,6 +118,12 @@ export function _emitQuorumEvent(
|
|
|
117
118
|
* absence is what the `false` on every line honestly records.
|
|
118
119
|
*/
|
|
119
120
|
minPresent?: number;
|
|
121
|
+
/**
|
|
122
|
+
* Phase 3 — whether the seats agreed, when a stance tally ran.
|
|
123
|
+
* Omitted by every caller that ran none, which `appendQuorumEvent`
|
|
124
|
+
* records as `not_tallied` rather than as a bare `false`.
|
|
125
|
+
*/
|
|
126
|
+
stanceAgreement?: StanceAgreement;
|
|
120
127
|
},
|
|
121
128
|
): void {
|
|
122
129
|
appendQuorumEvent({
|
|
@@ -128,6 +135,7 @@ export function _emitQuorumEvent(
|
|
|
128
135
|
configuredTotal: ctx.configuredTotal ?? quorum.total,
|
|
129
136
|
result: quorum,
|
|
130
137
|
...(ctx.minPresent !== undefined ? { minPresent: ctx.minPresent } : {}),
|
|
138
|
+
...(ctx.stanceAgreement !== undefined ? { stanceAgreement: ctx.stanceAgreement } : {}),
|
|
131
139
|
absent: absent.map(
|
|
132
140
|
(a): QuorumAbsence => ({
|
|
133
141
|
member: String(a['member'] ?? ''),
|
|
@@ -154,9 +162,11 @@ export function _postRunQuorum(
|
|
|
154
162
|
members: ExternalAIClient[],
|
|
155
163
|
responses: CouncilResponse[],
|
|
156
164
|
ai_cfg: Dict,
|
|
165
|
+
parse_outcomes?: ReadonlyMap<string, string>,
|
|
157
166
|
): { quorum: QuorumResult; absent: Dict[] } {
|
|
158
167
|
const absent: Dict[] = [];
|
|
159
168
|
let present = 0;
|
|
169
|
+
let unparsed = 0;
|
|
160
170
|
for (let i = 0; i < members.length; i++) {
|
|
161
171
|
const m = members[i] as ExternalAIClient;
|
|
162
172
|
const r = responses[i];
|
|
@@ -167,7 +177,33 @@ export function _postRunQuorum(
|
|
|
167
177
|
// banner printed `2/2 present` — a single-voice verdict presented as
|
|
168
178
|
// convergence, on a paid run. An empty answer contributes nothing to a
|
|
169
179
|
// quorum by definition, whatever the transport thought of it.
|
|
180
|
+
// Step 2.3 — the same argument, one rung further in. The byte check
|
|
181
|
+
// below settles "did the transport deliver anything"; it cannot settle
|
|
182
|
+
// "was what it delivered usable content", and a prose refusal passes it
|
|
183
|
+
// unchanged. So a member whose findings answer reached `parse_failed`
|
|
184
|
+
// is pulled out of `present` into its own bucket rather than folded
|
|
185
|
+
// into `N/N present`. It is NOT merged with the error cases: those are
|
|
186
|
+
// transport failures with an `AbsentReason` taxonomy the absent-member
|
|
187
|
+
// table renders, and re-labelling one of them `unparsed` would lose the
|
|
188
|
+
// auth/timeout/quota distinction. Hence the error branch below wins for
|
|
189
|
+
// a member that both errored and parsed badly — the transport failure
|
|
190
|
+
// is the stronger fact.
|
|
191
|
+
//
|
|
192
|
+
// `parse_outcomes` is optional because the run path derives it AFTER
|
|
193
|
+
// the post-run attendance event is emitted: the event stays a
|
|
194
|
+
// transport-level reading by design, and the rendered artefact is where
|
|
195
|
+
// AC-2 asks for the distinction. A caller with no map gets the exact
|
|
196
|
+
// pre-2.3 behaviour, key-for-key.
|
|
170
197
|
if (r !== undefined && !r.error && r.text.trim() !== '') {
|
|
198
|
+
if (parse_outcomes?.get(m.name) === 'parse_failed') {
|
|
199
|
+
unparsed += 1;
|
|
200
|
+
absent.push({
|
|
201
|
+
member: m.name,
|
|
202
|
+
reason: 'unparsed',
|
|
203
|
+
detail: 'answer present, no parser could read it',
|
|
204
|
+
});
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
171
207
|
present += 1;
|
|
172
208
|
continue;
|
|
173
209
|
}
|
|
@@ -179,7 +215,46 @@ export function _postRunQuorum(
|
|
|
179
215
|
detail: raw,
|
|
180
216
|
});
|
|
181
217
|
}
|
|
182
|
-
return { quorum: evaluateQuorum(members.length, present, _quorum_setting_from(ai_cfg)), absent };
|
|
218
|
+
return { quorum: evaluateQuorum(members.length, present, _quorum_setting_from(ai_cfg), unparsed), absent };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Which of the three agreement states a stance tally represents.
|
|
223
|
+
*
|
|
224
|
+
* `undefined` when no tally ran — the emitter records that as `not_tallied`,
|
|
225
|
+
* which is a fact ("nobody asked"), not a `false` that reads as disagreement.
|
|
226
|
+
* Returned as an optional rather than a nullable so the caller can spread it
|
|
227
|
+
* under `exactOptionalPropertyTypes`, where an explicit `undefined` and an
|
|
228
|
+
* absent key are different things.
|
|
229
|
+
*/
|
|
230
|
+
export function stanceAgreementOf(
|
|
231
|
+
tally: { consensus: unknown } | null,
|
|
232
|
+
): StanceAgreement | undefined {
|
|
233
|
+
if (tally === null) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
return tally.consensus !== null ? 'consensus' : 'split';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Re-derive the rendered attendance line once the findings parser has spoken.
|
|
241
|
+
*
|
|
242
|
+
* Lives here rather than at the call site because it is the second half of the
|
|
243
|
+
* split `withUnparsed` documents: the post-run event stays a TRANSPORT-level
|
|
244
|
+
* reading so every rate over `events.log` keeps its denominator, and the
|
|
245
|
+
* rendered artefact is where AC-2 asks for the unparsed distinction. Counting
|
|
246
|
+
* `parse_failed` outcomes is the whole derivation; keeping it next to
|
|
247
|
+
* `_postRunQuorum` keeps both readings in one file.
|
|
248
|
+
*/
|
|
249
|
+
export function annotateRenderedQuorum(
|
|
250
|
+
quorum: QuorumResult | null,
|
|
251
|
+
parse_outcomes: ReadonlyMap<string, string> | null | undefined,
|
|
252
|
+
): QuorumResult | null {
|
|
253
|
+
if (quorum === null || parse_outcomes === null || parse_outcomes === undefined) {
|
|
254
|
+
return quorum;
|
|
255
|
+
}
|
|
256
|
+
const unparsed = Array.from(parse_outcomes.values()).filter((o) => o === 'parse_failed').length;
|
|
257
|
+
return withUnparsed(quorum, unparsed);
|
|
183
258
|
}
|
|
184
259
|
|
|
185
260
|
/**
|
|
@@ -205,7 +280,9 @@ export function _format_quorum_line(q: QuorumResult, phase?: QuorumEventPhase):
|
|
|
205
280
|
// a solo answer concludes, and nothing in the line distinguishes "both
|
|
206
281
|
// members agreed" from "one member answered". The counts were always there;
|
|
207
282
|
// what was missing is the word that stops a reader inferring convergence.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
283
|
+
// Step 2.3 moved the wording into `formatAttendanceCaveats` so this line and
|
|
284
|
+
// its mirror in `orchestrator.ts` cannot drift apart, and added the
|
|
285
|
+
// present-unparsed clause there — see that function for why the two counts
|
|
286
|
+
// are disjoint.
|
|
287
|
+
return `council:quorum · ${tag}${q.present}/${q.total} present, needed ${q.threshold} — ${verdict}.${formatAttendanceCaveats(q)}`;
|
|
211
288
|
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who is seated for a run, decided once and frozen.
|
|
3
|
+
*
|
|
4
|
+
* Selection today is config-static ask-all: every enabled member, every
|
|
5
|
+
* question, no per-question seating. This adds an OPTIONAL declaration of what
|
|
6
|
+
* a run wants from its seats, and computes the answer once.
|
|
7
|
+
*
|
|
8
|
+
* FAMILY DIVERSITY ONLY — no band ordering. `blocker: b-ladder-order-benchmark-spend`
|
|
9
|
+
* was resolved (b) on 2026-08-22: nothing in this tree establishes that a higher
|
|
10
|
+
* capability band reviews better, the archived benchmark substrate would have to
|
|
11
|
+
* be re-run to support it, and the council that would have decided otherwise had
|
|
12
|
+
* no quota. So `tier` keeps its single documented meaning — a capability rank
|
|
13
|
+
* read only as a chairman-selection input — and nothing here reads it. A seat
|
|
14
|
+
* declaration carries MISSION, never RANK.
|
|
15
|
+
*
|
|
16
|
+
* "Family" is the PROVIDER, not a capability band. For a council, diversity means
|
|
17
|
+
* independent providers: two Claude bands share a vendor, a training pipeline and
|
|
18
|
+
* a failure mode, so seating `opus` beside `sonnet` buys none of what a second
|
|
19
|
+
* opinion is for. (`MODEL_FAMILIES` in the orchestration-record hook enumerates
|
|
20
|
+
* Claude bands for a different purpose — token attribution — and is deliberately
|
|
21
|
+
* not reused here.)
|
|
22
|
+
*
|
|
23
|
+
* Absent declaration ⇒ today's behaviour, byte-identical. That is asserted by a
|
|
24
|
+
* test rather than intended.
|
|
25
|
+
*/
|
|
26
|
+
import type { MemberConfig } from './config.js';
|
|
27
|
+
|
|
28
|
+
/** A member's provider family. The map key IS the provider in this config shape. */
|
|
29
|
+
export function familyOf(member: MemberConfig): string {
|
|
30
|
+
return member.name;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Read the optional `seat_constraints:` block out of a raw council config.
|
|
35
|
+
*
|
|
36
|
+
* DELIBERATELY NOT A FIELD ON `CouncilConfig`, and the reason is a ratchet
|
|
37
|
+
* rather than a design preference. `config.ts` is 2,205 lines — 705 over the
|
|
38
|
+
* 1,500-line source-size line — and `check_source_size_budget` counts only the
|
|
39
|
+
* excess above that line, so the 39 lines this feature first added there were a
|
|
40
|
+
* straight +39 against a shrink-only baseline. The gate's own message is
|
|
41
|
+
* explicit that raising the baseline is "a defect, not a fix". Extraction is the
|
|
42
|
+
* sanctioned repair, and this file is 169 lines, so the same code costs nothing
|
|
43
|
+
* here.
|
|
44
|
+
*
|
|
45
|
+
* THE TRADE-OFF, stated rather than buried: validation moves from LOAD time to
|
|
46
|
+
* READ time. A malformed `min_families` no longer fails the moment the config
|
|
47
|
+
* is parsed; it fails when a caller asks for the constraints. Today that
|
|
48
|
+
* difference is unobservable — Phase 2 ships the DECLARATION and no caller
|
|
49
|
+
* reads it yet — but it is a real change in when a bad config is caught, and
|
|
50
|
+
* whoever wires the first caller should call this at run start so the failure
|
|
51
|
+
* lands before any seat is used.
|
|
52
|
+
*
|
|
53
|
+
* Fails CLOSED on a malformed value rather than falling back to absent: a run
|
|
54
|
+
* that declared a diversity floor and silently got none is the exact silent
|
|
55
|
+
* fallback the degradation line exists to prevent.
|
|
56
|
+
*/
|
|
57
|
+
export function readSeatConstraints(raw: unknown, label = 'seat_constraints'): SeatConstraints {
|
|
58
|
+
if (raw === null || raw === undefined) return {};
|
|
59
|
+
if (typeof raw !== 'object' || Array.isArray(raw)) {
|
|
60
|
+
throw new TypeError(`${label} must be a mapping (got ${typeof raw}).`);
|
|
61
|
+
}
|
|
62
|
+
const block = (raw as Record<string, unknown>)['seat_constraints'] ?? raw;
|
|
63
|
+
if (block === null || block === undefined) return {};
|
|
64
|
+
if (typeof block !== 'object' || Array.isArray(block)) {
|
|
65
|
+
throw new TypeError(`${label} must be a mapping (got ${typeof block}).`);
|
|
66
|
+
}
|
|
67
|
+
const mf = (block as Record<string, unknown>)['min_families'];
|
|
68
|
+
if (mf === null || mf === undefined) return {};
|
|
69
|
+
if (typeof mf !== 'number' || !Number.isInteger(mf) || mf < 1) {
|
|
70
|
+
throw new TypeError(`${label}.min_families must be an integer >= 1 when set (got ${String(mf)}).`);
|
|
71
|
+
}
|
|
72
|
+
return { min_families: mf };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface SeatConstraints {
|
|
76
|
+
/**
|
|
77
|
+
* Minimum distinct provider families the run wants seated.
|
|
78
|
+
*
|
|
79
|
+
* Absent (or 1) ⇒ no constraint and no degradation line: ask-all, unchanged.
|
|
80
|
+
*/
|
|
81
|
+
readonly min_families?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface Seating {
|
|
85
|
+
/** The seated members, in deterministic config order. */
|
|
86
|
+
readonly seats: readonly MemberConfig[];
|
|
87
|
+
/** Distinct families actually seated. */
|
|
88
|
+
readonly families: readonly string[];
|
|
89
|
+
/**
|
|
90
|
+
* Exactly ONE line when the constraint could not be met, `null` otherwise.
|
|
91
|
+
*
|
|
92
|
+
* One line, not a wall: a degradation nobody reads is the same as a silent
|
|
93
|
+
* fallback, and N warnings is how a reader learns to skip the header.
|
|
94
|
+
*/
|
|
95
|
+
readonly degraded: string | null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Compute the seating once.
|
|
100
|
+
*
|
|
101
|
+
* Deterministic and side-effect-free: the same members and constraints always
|
|
102
|
+
* produce the same seats, which is what makes freezing it meaningful. Seating
|
|
103
|
+
* that changed between round 1 and round 3 would silently invalidate the
|
|
104
|
+
* anonymised-peer-reply contract the council skill depends on — a "reviewer B"
|
|
105
|
+
* in round 3 that is not the "reviewer B" of round 1 makes every cross-reference
|
|
106
|
+
* in the synthesis wrong while looking fine.
|
|
107
|
+
*/
|
|
108
|
+
export function resolveSeating(
|
|
109
|
+
members: readonly MemberConfig[],
|
|
110
|
+
constraints: SeatConstraints = {},
|
|
111
|
+
): Seating {
|
|
112
|
+
const enabled = members.filter((m) => m.enabled);
|
|
113
|
+
const families = [...new Set(enabled.map(familyOf))];
|
|
114
|
+
const want = constraints.min_families ?? 1;
|
|
115
|
+
|
|
116
|
+
if (want <= 1 || families.length >= want) {
|
|
117
|
+
return { seats: enabled, families, degraded: null };
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
seats: enabled,
|
|
121
|
+
families,
|
|
122
|
+
degraded:
|
|
123
|
+
`tier-degraded: asked for ${String(want)} model families, seated ${String(families.length)} ` +
|
|
124
|
+
`(${families.join(', ')}). The run proceeds with what is enabled — a council that refused to ` +
|
|
125
|
+
`convene on a diversity shortfall would fail closed on the common single-provider install, ` +
|
|
126
|
+
`which is worse than a stated shortfall.`,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Freeze a seating so a later config mutation cannot change it.
|
|
132
|
+
*
|
|
133
|
+
* Returns a structurally frozen snapshot. This is the mechanism behind "resolve
|
|
134
|
+
* once per run": the caller resolves at run start, freezes, and passes the
|
|
135
|
+
* snapshot down — so there is no path by which round 3 re-reads the config.
|
|
136
|
+
*/
|
|
137
|
+
export function freezeSeating(s: Seating): Seating {
|
|
138
|
+
return Object.freeze({
|
|
139
|
+
seats: Object.freeze([...s.seats]),
|
|
140
|
+
families: Object.freeze([...s.families]),
|
|
141
|
+
degraded: s.degraded,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Vendor sentinels and "latest in band" aliases — an id that cannot go stale.
|
|
147
|
+
*
|
|
148
|
+
* Read from the providers' own CLI surfaces on 2026-08-22, never from recall:
|
|
149
|
+
* `claude --help` documents 'fable', 'opus' and 'sonnet' as aliases for the
|
|
150
|
+
* latest model in their band, and `codex-default` is the openai transport's
|
|
151
|
+
* documented "let the CLI choose".
|
|
152
|
+
*/
|
|
153
|
+
export const ADMISSIBLE_SENTINELS: ReadonlySet<string> = new Set([
|
|
154
|
+
'codex-default',
|
|
155
|
+
'fable',
|
|
156
|
+
'opus',
|
|
157
|
+
'sonnet',
|
|
158
|
+
'haiku',
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
export interface AdmissibilityResult {
|
|
162
|
+
readonly admissible: boolean;
|
|
163
|
+
readonly reason: string | null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Is this member's `model:` id from an admissible SOURCE?
|
|
168
|
+
*
|
|
169
|
+
* THE CRITERION AS WRITTEN COULD NOT BE IMPLEMENTED, and the deviation is
|
|
170
|
+
* recorded here rather than papered over. The roadmap step says a declared seat
|
|
171
|
+
* "resolves through the shipped `model_tier` bands; a model id that no tier maps
|
|
172
|
+
* to is rejected at config load". But `TIER_TO_CLAUDE_MODEL`
|
|
173
|
+
* (`_lib/model_tier.ts:36-41`) maps tiers onto CLAUDE aliases only — there is no
|
|
174
|
+
* entry any `gemini-*`, `grok-*` or `sonar-*` id could resolve through. Taken
|
|
175
|
+
* literally, that rule rejects every non-anthropic member in the shipped starter
|
|
176
|
+
* config, i.e. it fails closed on a valid config.
|
|
177
|
+
*
|
|
178
|
+
* What the step is actually protecting is stated in its own title: "including
|
|
179
|
+
* the host's own recall". The failure mode is a plausible-sounding model id
|
|
180
|
+
* TYPED FROM MEMORY, which is indistinguishable from a real one at review time
|
|
181
|
+
* and would silently undo the pin refresh. So admissibility is checked against
|
|
182
|
+
* the SOURCE of the id, over the two things this tree can actually verify:
|
|
183
|
+
*
|
|
184
|
+
* 1. a vendor sentinel or documented "latest in band" alias — cannot go stale,
|
|
185
|
+
* and read from the provider's own surface; or
|
|
186
|
+
* 2. a dated pin carrying a `verified_at` stamp — which records that a human
|
|
187
|
+
* looked at the provider's surface on a named date, and which
|
|
188
|
+
* `check_council_pin_staleness` ages out.
|
|
189
|
+
*
|
|
190
|
+
* An id that is neither is exactly the recall case: a bare dated id nobody
|
|
191
|
+
* recorded checking.
|
|
192
|
+
*/
|
|
193
|
+
export function checkModelAdmissibility(member: MemberConfig): AdmissibilityResult {
|
|
194
|
+
const id = member.model.trim().toLowerCase();
|
|
195
|
+
if (ADMISSIBLE_SENTINELS.has(id)) {
|
|
196
|
+
return { admissible: true, reason: null };
|
|
197
|
+
}
|
|
198
|
+
if (member.verified_at !== null && member.verified_at !== undefined) {
|
|
199
|
+
return { admissible: true, reason: null };
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
admissible: false,
|
|
203
|
+
reason:
|
|
204
|
+
`members.${member.name}.model is '${member.model}' — a dated id with no verified_at stamp. ` +
|
|
205
|
+
`An id must come from a source this tree can check: a vendor sentinel or documented ` +
|
|
206
|
+
`"latest in band" alias (${[...ADMISSIBLE_SENTINELS].join(', ')} — see src/scripts/_lib/model_tier.ts ` +
|
|
207
|
+
`for the tier vocabulary these bands come from), or a pin carrying verified_at: "YYYY-MM-DD" ` +
|
|
208
|
+
`recorded from the provider's own surface. A model id remembered rather than read is not an ` +
|
|
209
|
+
`admissible source, and is indistinguishable from a real one at review time.`,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -218,6 +218,28 @@ export function tally_stances(
|
|
|
218
218
|
* Render the **Vote Tally** verdict section: one line per option, the threshold,
|
|
219
219
|
* and a cleared-or-escalated line. Deterministic — pure projection of the tally.
|
|
220
220
|
*/
|
|
221
|
+
/**
|
|
222
|
+
* Tally the stance lines of a finished round, or `null` when tallying is off.
|
|
223
|
+
*
|
|
224
|
+
* Wraps the member-shape mapping so a caller does not re-derive it: an errored
|
|
225
|
+
* response has no stance line to read, and the member key is
|
|
226
|
+
* `provider:model` because that is what `parse_stance_line` records. Exists so
|
|
227
|
+
* ONE tally is computed per pass and reused — two tallies over the same
|
|
228
|
+
* responses are two chances to disagree, and the attendance event and the
|
|
229
|
+
* handoff envelope both consume this one.
|
|
230
|
+
*/
|
|
231
|
+
export function tallyFromResponses(
|
|
232
|
+
responses: ReadonlyArray<{ provider: string; model: string; text: string; error?: string | null }>,
|
|
233
|
+
enabled: boolean,
|
|
234
|
+
): StanceTallyResult | null {
|
|
235
|
+
if (!enabled) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
return tally_stances(
|
|
239
|
+
responses.filter((r) => !r.error).map((r) => ({ member: `${r.provider}:${r.model}`, text: r.text })),
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
221
243
|
export function render_vote_tally(result: StanceTallyResult): string {
|
|
222
244
|
const lines: string[] = ['### Vote Tally'];
|
|
223
245
|
if (result.options.length === 0) {
|
|
@@ -580,6 +580,58 @@ export function perTurnComposite(
|
|
|
580
580
|
};
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
+
/**
|
|
584
|
+
* A1.1 — append ONE composite reading to the durable store.
|
|
585
|
+
*
|
|
586
|
+
* The bench used to print the composite and discard it, which made
|
|
587
|
+
* `per_turn_composite.arming_precondition` ("at least 10 CI gate readings … from
|
|
588
|
+
* at least 2 distinct runner sessions") impossible to evaluate at all. This is
|
|
589
|
+
* the write half; `check_composite_arming.ts` is the read half.
|
|
590
|
+
*
|
|
591
|
+
* THE SESSION DISCRIMINATOR IS THE LOAD-BEARING FIELD, not the count. The
|
|
592
|
+
* precondition asks for two distinct runner SESSIONS because the instability it
|
|
593
|
+
* excludes was measured on ONE machine — a sibling metric read 44-157 % at n=12
|
|
594
|
+
* and 69-74 % at n=50 there — so twelve readings from one session is exactly the
|
|
595
|
+
* shape the floor rejects, and a bare counter cannot see the difference.
|
|
596
|
+
*
|
|
597
|
+
* A null composite is written as null rather than skipped. Dropping it silently
|
|
598
|
+
* would make the store's own length a lie about how many runs contributed, and
|
|
599
|
+
* the reader needs to distinguish "no run" from "a run whose slots were
|
|
600
|
+
* incomplete" — `perTurnComposite` returns null exactly because a composite over
|
|
601
|
+
* a subset reads LOW, and low is the direction that makes a ceiling look met.
|
|
602
|
+
*/
|
|
603
|
+
export function composeReadingRecord(
|
|
604
|
+
composite: { ms: number; parts: Record<string, number> } | null,
|
|
605
|
+
tool_calls: number,
|
|
606
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
607
|
+
): Record<string, unknown> {
|
|
608
|
+
// In CI a session is the workflow run on a given runner; locally it is the
|
|
609
|
+
// host plus the process's own start, so two consecutive local runs are
|
|
610
|
+
// distinguishable while one run's records stay grouped.
|
|
611
|
+
const ciRun = env['GITHUB_RUN_ID'];
|
|
612
|
+
const session =
|
|
613
|
+
ciRun !== undefined && ciRun !== ''
|
|
614
|
+
? `gh-${ciRun}-${env['RUNNER_OS'] ?? os.platform()}-${env['GITHUB_RUN_ATTEMPT'] ?? '1'}`
|
|
615
|
+
: `local-${os.hostname()}-${String(process.pid)}`;
|
|
616
|
+
return {
|
|
617
|
+
composite_ms: composite === null ? null : composite.ms,
|
|
618
|
+
parts: composite === null ? null : composite.parts,
|
|
619
|
+
tool_calls,
|
|
620
|
+
session,
|
|
621
|
+
platform: `${os.platform()}-${os.arch()}`,
|
|
622
|
+
node: process.version,
|
|
623
|
+
commit: env['GITHUB_SHA'] ?? null,
|
|
624
|
+
run_id: ciRun ?? null,
|
|
625
|
+
recorded_at: new Date().toISOString(),
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/** Append one JSONL record. Creates the file and its directory if absent. */
|
|
630
|
+
export function appendReading(storePath: string, record: Record<string, unknown>): void {
|
|
631
|
+
fs.mkdirSync(path.dirname(storePath), { recursive: true });
|
|
632
|
+
fs.appendFileSync(storePath, `${JSON.stringify(record)}\n`, 'utf-8');
|
|
633
|
+
}
|
|
634
|
+
|
|
583
635
|
interface HistoryEntry {
|
|
584
636
|
recorded_at: string;
|
|
585
637
|
invocation_path: InvocationPath;
|
|
@@ -895,6 +947,16 @@ export function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
895
947
|
: perTurnComposite(results, compositeCfg.tool_calls ?? 10);
|
|
896
948
|
if (compositeCfg !== undefined) {
|
|
897
949
|
const calls = compositeCfg.tool_calls ?? 10;
|
|
950
|
+
// A1.1: persist the reading BEFORE the ceiling comparison below, so a run
|
|
951
|
+
// that fails the gate still contributes its number. A store that only
|
|
952
|
+
// gets the passing runs is biased in the direction that makes a ceiling
|
|
953
|
+
// look met, which is the same bias the null-composite rule guards.
|
|
954
|
+
const recIdx = argv.indexOf('--record-composite');
|
|
955
|
+
if (recIdx >= 0) {
|
|
956
|
+
const dest = argv[recIdx + 1] ?? path.join(REPO_ROOT, 'agents', 'evidence', 'hook-composite-readings.jsonl');
|
|
957
|
+
appendReading(dest, composeReadingRecord(composite, calls));
|
|
958
|
+
process.stdout.write(`recorded composite reading → ${path.relative(REPO_ROOT, dest)}\n`);
|
|
959
|
+
}
|
|
898
960
|
if (composite === null) {
|
|
899
961
|
process.stdout.write(
|
|
900
962
|
`ℹ️ per-turn composite not computed — a slot the definition needs is missing from this run\n`,
|
|
@@ -24,7 +24,11 @@ import * as path from 'node:path';
|
|
|
24
24
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
25
25
|
|
|
26
26
|
import { REPO, LEDGER_REL, load_ledger, pointer_unresolved } from './check_claims.js';
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
collect as collectEnforcement,
|
|
29
|
+
denominator_line as enforcementDenominatorLine,
|
|
30
|
+
summarise as summariseEnforcement,
|
|
31
|
+
} from './check_enforcement_coverage.js';
|
|
28
32
|
import { collectSkillGaps } from './check_skill_gaps.js';
|
|
29
33
|
import { loadRows as loadComparisonRows } from './check_comparison.js';
|
|
30
34
|
import { computeStatus as domainSoundnessStatus } from './domain_soundness_status.js';
|
|
@@ -415,6 +419,13 @@ function render(): string {
|
|
|
415
419
|
`${s.local_only} local-only · ${s.undeclared} undeclared (no \`enforced_by\` yet).`,
|
|
416
420
|
);
|
|
417
421
|
L.push('');
|
|
422
|
+
// The denominator, WITH the frame that produced it. Until 2026-08-23 the
|
|
423
|
+
// tree published five figures for this one property because every one was
|
|
424
|
+
// quoted without saying which population it was taken over. This line is
|
|
425
|
+
// the single sanctioned statement of it, and `check_enforcement_denominator`
|
|
426
|
+
// reds when a published doc restates a count instead of citing this block.
|
|
427
|
+
L.push(`\`${enforcementDenominatorLine(s.frames)}\``);
|
|
428
|
+
L.push('');
|
|
418
429
|
L.push('| Rule | Effective level | Declared backstop(s) |');
|
|
419
430
|
L.push('|---|---|---|');
|
|
420
431
|
const declared = rows
|
|
@@ -434,11 +434,32 @@ function runLimitsMode(): number {
|
|
|
434
434
|
/** The package's two projection-mode counts, one walk. Shared by both modes. */
|
|
435
435
|
function projectionModeCounts(): ProjectionModeCounts {
|
|
436
436
|
const stats = scoped_projection_stats(REPO, iter_skills());
|
|
437
|
+
// The tier split is a per-machine runtime artefact (gitignored), so absent is
|
|
438
|
+
// the normal state and must read as "unmeasured", never as zero.
|
|
439
|
+
let tierACount: number | null = null;
|
|
440
|
+
let tierBCount: number | null = null;
|
|
441
|
+
const tiersFile = path.join(REPO, 'agents', 'runtime', 'state', 'skill-tiers.json');
|
|
442
|
+
if (fs.existsSync(tiersFile)) {
|
|
443
|
+
try {
|
|
444
|
+
const parsed = JSON.parse(fs.readFileSync(tiersFile, 'utf-8')) as {
|
|
445
|
+
tier_a?: unknown;
|
|
446
|
+
tier_b?: unknown;
|
|
447
|
+
};
|
|
448
|
+
if (Array.isArray(parsed.tier_a) && Array.isArray(parsed.tier_b)) {
|
|
449
|
+
tierACount = parsed.tier_a.length;
|
|
450
|
+
tierBCount = parsed.tier_b.length;
|
|
451
|
+
}
|
|
452
|
+
} catch {
|
|
453
|
+
/* a malformed split is an absent split — never a partial count */
|
|
454
|
+
}
|
|
455
|
+
}
|
|
437
456
|
return {
|
|
438
457
|
scoped: stats.projected,
|
|
439
458
|
legacyAll: stats.total,
|
|
440
459
|
prunedUnderScoped: stats.pruned,
|
|
441
460
|
activePacks: stats.active_packs,
|
|
461
|
+
tierACount,
|
|
462
|
+
tierBCount,
|
|
442
463
|
};
|
|
443
464
|
}
|
|
444
465
|
|
|
@@ -29,6 +29,7 @@ import process from 'node:process';
|
|
|
29
29
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
30
30
|
import YAML from 'yaml';
|
|
31
31
|
|
|
32
|
+
import { asOf } from './_lib/as_of.js';
|
|
32
33
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
33
34
|
|
|
34
35
|
// src/scripts/check_always_budget.ts → parents[2] is the repo root
|
|
@@ -435,7 +436,7 @@ function recordTrend(totalExt: number, sizes: Array<[string, number, number]>):
|
|
|
435
436
|
|
|
436
437
|
/** datetime.now(timezone.utc).isoformat(timespec="seconds") → ...+00:00. */
|
|
437
438
|
function isoSeconds(): string {
|
|
438
|
-
const d =
|
|
439
|
+
const d = asOf();
|
|
439
440
|
const pad = (v: number): string => String(v).padStart(2, '0');
|
|
440
441
|
return (
|
|
441
442
|
`${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}` +
|
|
@@ -24,6 +24,7 @@ import * as fs from 'node:fs';
|
|
|
24
24
|
import * as path from 'node:path';
|
|
25
25
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
26
26
|
|
|
27
|
+
import { asOfMs } from './_lib/as_of.js';
|
|
27
28
|
import { assertWatchlistResolves, DeadScopeError } from './_lib/scan_scope.js';
|
|
28
29
|
|
|
29
30
|
const QUIET = process.argv.slice(2).includes('--quiet');
|
|
@@ -76,7 +77,7 @@ function check(): number {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
const mtimeMs = fs.statSync(target).mtimeMs;
|
|
79
|
-
const age_days = (
|
|
80
|
+
const age_days = (asOfMs() - mtimeMs) / 86400000;
|
|
80
81
|
if (age_days > STALE_DAYS) {
|
|
81
82
|
notes.push(
|
|
82
83
|
`ℹ️ .augmentignore is ${Math.trunc(age_days)} days old (threshold: ${STALE_DAYS}) — ` +
|
|
@@ -19,6 +19,7 @@ import * as fs from 'node:fs';
|
|
|
19
19
|
import * as path from 'node:path';
|
|
20
20
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
21
21
|
|
|
22
|
+
import { asOf } from './_lib/as_of.js';
|
|
22
23
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
23
24
|
|
|
24
25
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -185,7 +186,7 @@ function parse_args(argv: readonly string[]): ParsedArgs {
|
|
|
185
186
|
|
|
186
187
|
/** Today's date as an ordinal, in local time (mirrors date.today()). */
|
|
187
188
|
function _todayOrdinal(): number {
|
|
188
|
-
const now =
|
|
189
|
+
const now = asOf();
|
|
189
190
|
return _dateOrdinal(now.getFullYear(), now.getMonth() + 1, now.getDate());
|
|
190
191
|
}
|
|
191
192
|
|