@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,155 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Warn when a captured judge prompt states an EXPECTATION of the outcome.
|
|
4
|
+
*
|
|
5
|
+
* Step 4.2 of `road-to-review-independence`, and the companion to
|
|
6
|
+
* `evidence_independence.ts`. That concern blocks a prompt carrying a pre-loaded
|
|
7
|
+
* **verdict**; this one reads the prompts that were actually sent and warns on the
|
|
8
|
+
* softer form — a statement of what the author thinks the answer will be.
|
|
9
|
+
*
|
|
10
|
+
* The distinction is not academic. *"NO-FINDINGS is expected and welcome"* names no
|
|
11
|
+
* verdict and supplies one; it steered a real review into an honest-null that a later
|
|
12
|
+
* unsteered pass refuted with five findings, one critical, already live on the trunk.
|
|
13
|
+
* `evaluator-independence.md` states the rule; this is the part a script can see.
|
|
14
|
+
*
|
|
15
|
+
* WHAT IT CANNOT SEE — stated here so the gate is not oversold, exactly as
|
|
16
|
+
* `evidence_independence.ts` states its own phrase-list limit:
|
|
17
|
+
*
|
|
18
|
+
* 1. **A paraphrase.** This is a PHRASE LIST. "no findings expected" is caught; "I'd be
|
|
19
|
+
* surprised if anything turns up" is not. It catches recurrences of known steering
|
|
20
|
+
* wording, never steering as such. Closing that needs a judgement, not a check.
|
|
21
|
+
* 2. **Omission.** A round that commits no `prompt.md` is not in the scanned set at all —
|
|
22
|
+
* the same cheapest-bypass `check_review_prompt_binding` records for itself. Nothing
|
|
23
|
+
* in the tree requires the package to exist.
|
|
24
|
+
* 3. **Substitution.** The party that writes a steered prompt also writes the file, so
|
|
25
|
+
* swapping a clean one in passes. What changes is that steering then requires an act
|
|
26
|
+
* of substitution rather than merely a careless sentence.
|
|
27
|
+
*
|
|
28
|
+
* WARN-ONLY, deliberately. A phrase list that can refuse a review would refuse the
|
|
29
|
+
* false positives too, and the shape it is looking for is one sentence in a long prompt.
|
|
30
|
+
* Exit is always 0; the finding is the output.
|
|
31
|
+
*/
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as path from 'node:path';
|
|
34
|
+
import process from 'node:process';
|
|
35
|
+
import { fileURLToPath } from 'node:url';
|
|
36
|
+
|
|
37
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
38
|
+
|
|
39
|
+
const _HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
40
|
+
const REPO_ROOT = path.resolve(_HERE, '..', '..');
|
|
41
|
+
const REVIEWS_DIR = path.join('agents', 'evidence', 'reviews');
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Phrases that state an expectation of the outcome.
|
|
45
|
+
*
|
|
46
|
+
* Each is a shape observed or narrowly derived from one, and the list is deliberately
|
|
47
|
+
* short: a long list of guesses produces false positives, and a warn nobody trusts is
|
|
48
|
+
* worse than no warn. The first entry is the measured one.
|
|
49
|
+
*/
|
|
50
|
+
export const EXPECTATION_PHRASES: readonly RegExp[] = [
|
|
51
|
+
/no[- ]findings\s+(?:is|are)\s+(?:expected|welcome)/i,
|
|
52
|
+
/\bexpect(?:ing)?\s+(?:no|zero)\s+(?:findings|issues|problems)/i,
|
|
53
|
+
/\bshould\s+be\s+(?:clean|fine|correct|green)\b/i,
|
|
54
|
+
/\bi\s+believe\s+this\s+is\s+(?:correct|clean|right)\b/i,
|
|
55
|
+
/\bjust\s+confirm\b/i,
|
|
56
|
+
/\bplease\s+confirm\s+(?:that\s+)?(?:there\s+are\s+)?no\b/i,
|
|
57
|
+
/\bthis\s+(?:should|ought\s+to)\s+pass\b/i,
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
export interface Finding {
|
|
61
|
+
readonly file: string;
|
|
62
|
+
readonly line: number;
|
|
63
|
+
readonly phrase: string;
|
|
64
|
+
readonly text: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Scan one prompt's text. Returns every match, not the first — a prompt can steer twice. */
|
|
68
|
+
export function scanPromptText(rel: string, text: string): Finding[] {
|
|
69
|
+
const out: Finding[] = [];
|
|
70
|
+
const lines = text.split('\n');
|
|
71
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
72
|
+
const line = lines[i]!;
|
|
73
|
+
for (const re of EXPECTATION_PHRASES) {
|
|
74
|
+
const m = re.exec(line);
|
|
75
|
+
if (m !== null) {
|
|
76
|
+
out.push({
|
|
77
|
+
file: rel,
|
|
78
|
+
line: i + 1,
|
|
79
|
+
phrase: m[0],
|
|
80
|
+
// Trimmed and capped: the finding names the sentence, and a prompt
|
|
81
|
+
// line can be very long.
|
|
82
|
+
text: line.trim().slice(0, 160),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Every `<slug>.review-input/prompt.md` under the reviews directory. */
|
|
91
|
+
export function collectPrompts(repoRoot: string): string[] {
|
|
92
|
+
const dir = path.join(repoRoot, REVIEWS_DIR);
|
|
93
|
+
if (!fs.existsSync(dir)) return [];
|
|
94
|
+
const out: string[] = [];
|
|
95
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) =>
|
|
96
|
+
a.name < b.name ? -1 : 1,
|
|
97
|
+
)) {
|
|
98
|
+
if (!entry.isDirectory() || !entry.name.endsWith('.review-input')) continue;
|
|
99
|
+
const p = path.join(dir, entry.name, 'prompt.md');
|
|
100
|
+
if (fs.existsSync(p)) out.push(p);
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function main(argv: readonly string[] = []): number {
|
|
106
|
+
const quiet = argv.includes('--quiet');
|
|
107
|
+
const rootIdx = argv.indexOf('--repo-root');
|
|
108
|
+
const repoRoot = rootIdx >= 0 ? (argv[rootIdx + 1] ?? REPO_ROOT) : REPO_ROOT;
|
|
109
|
+
|
|
110
|
+
const prompts = collectPrompts(repoRoot);
|
|
111
|
+
const findings: Finding[] = [];
|
|
112
|
+
for (const p of prompts) {
|
|
113
|
+
findings.push(...scanPromptText(path.relative(repoRoot, p), fs.readFileSync(p, 'utf-8')));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
reportScanned({
|
|
117
|
+
gate: 'lint_judge_prompt_expectation',
|
|
118
|
+
scanned: prompts.length,
|
|
119
|
+
units: 'captured judge prompt(s)',
|
|
120
|
+
roots: [REVIEWS_DIR],
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (findings.length === 0) {
|
|
124
|
+
if (!quiet) {
|
|
125
|
+
process.stdout.write(
|
|
126
|
+
'✅ lint_judge_prompt_expectation: no captured prompt states an expectation ' +
|
|
127
|
+
'of the outcome (phrase list only — a paraphrase is not caught).\n',
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
process.stdout.write(
|
|
133
|
+
`⚠️ lint_judge_prompt_expectation: ${String(findings.length)} prompt line(s) state an ` +
|
|
134
|
+
'expectation of the outcome. WARN ONLY — review them:\n',
|
|
135
|
+
);
|
|
136
|
+
for (const f of findings) {
|
|
137
|
+
process.stdout.write(` ${f.file}:${String(f.line)} — "${f.phrase}"\n ${f.text}\n`);
|
|
138
|
+
}
|
|
139
|
+
process.stdout.write(
|
|
140
|
+
'\n A prompt that says what the author thinks the answer is has authored the answer, ' +
|
|
141
|
+
'whatever mood it used. See src/rules/evaluator-independence.md.\n',
|
|
142
|
+
);
|
|
143
|
+
// Always 0. See the header: a phrase list that can refuse would refuse its false
|
|
144
|
+
// positives too.
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function _isCliEntry(): boolean {
|
|
149
|
+
const invoked = process.argv[1];
|
|
150
|
+
return invoked !== undefined && path.resolve(invoked) === path.resolve(fileURLToPath(import.meta.url));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (_isCliEntry()) {
|
|
154
|
+
process.exit(main(process.argv.slice(2)));
|
|
155
|
+
}
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* - owner must have name + email
|
|
16
16
|
* - metadata must have description + version
|
|
17
17
|
* - metadata.version must match package.json (single source of truth)
|
|
18
|
+
* - every version field in BOTH .augment-plugin/ manifests matches
|
|
19
|
+
* package.json too — see check_augment_manifests()
|
|
18
20
|
* - the union of plugins[].skills[] must be EXACTLY the pointer skill
|
|
19
21
|
* (./.claude-plugin/skills/install-agent-config) — a repopulated
|
|
20
22
|
* content-skill list FAILS by design
|
|
@@ -88,6 +90,87 @@ function require_key(
|
|
|
88
90
|
return true;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Every version field in both `.augment-plugin/` manifests must equal
|
|
95
|
+
* `package.json`'s.
|
|
96
|
+
*
|
|
97
|
+
* WHY THE AUGMENT TWIN IS IN SCOPE OF THIS GATE. Both files ship in the npm
|
|
98
|
+
* tarball — `src/config/publish-surface.json` lists `.augment-plugin/` as a
|
|
99
|
+
* publish root — and both carried `version: 1.0.0` while `package.json` moved
|
|
100
|
+
* to 14.x. Nothing in the tree ever claimed `1.0.0` was an independent
|
|
101
|
+
* plugin-API version: no comment, no test, no doc, and the only reader anywhere
|
|
102
|
+
* is `src/scripts/probe_skill_registration.ts:137`. `plugin.json` had not been
|
|
103
|
+
* touched since 2026-04-17. An unclaimed constant no reader interprets is
|
|
104
|
+
* drift, not a deliberate independent version — so the Augment manifests are
|
|
105
|
+
* treated as the projection counterpart of the `.claude-plugin` twin this gate
|
|
106
|
+
* already version-syncs, and are held to the same rule.
|
|
107
|
+
*
|
|
108
|
+
* Reversible in one commit if that reading is ever wrong, which is why
|
|
109
|
+
* `docs/CLAIMS.md` records the choice rather than leaving it implicit.
|
|
110
|
+
*
|
|
111
|
+
* The nesting differs between the two files, so the fields are enumerated
|
|
112
|
+
* rather than discovered: a recursive "every key named version" walk would
|
|
113
|
+
* silently start policing a future field that is legitimately independent.
|
|
114
|
+
*/
|
|
115
|
+
export function check_augment_manifests(
|
|
116
|
+
pkgVersion: string,
|
|
117
|
+
errors: string[],
|
|
118
|
+
base: string = ROOT,
|
|
119
|
+
): void {
|
|
120
|
+
const targets: Array<[string, string[][]]> = [
|
|
121
|
+
[path.join(base, ".augment-plugin", "plugin.json"), [["version"]]],
|
|
122
|
+
[
|
|
123
|
+
path.join(base, ".augment-plugin", "marketplace.json"),
|
|
124
|
+
[["version"], ["metadata", "version"], ["plugins", "*", "version"]],
|
|
125
|
+
],
|
|
126
|
+
];
|
|
127
|
+
for (const [file, paths] of targets) {
|
|
128
|
+
if (!_exists(file)) {
|
|
129
|
+
errors.push(`${file} not found (listed in publish-surface.json roots)`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
let data: JsonValue;
|
|
133
|
+
try {
|
|
134
|
+
data = JSON.parse(fs.readFileSync(file, "utf-8")) as JsonValue;
|
|
135
|
+
} catch (e) {
|
|
136
|
+
errors.push(`${file} is not valid JSON: ${e instanceof Error ? e.message : String(e)}`);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
for (const keys of paths) {
|
|
140
|
+
for (const [label, value] of _resolveVersionField(data, keys)) {
|
|
141
|
+
if (value !== pkgVersion) {
|
|
142
|
+
errors.push(
|
|
143
|
+
`${file}: ${label} \`${String(value)}\` does not match ` +
|
|
144
|
+
`package.json version \`${pkgVersion}\``,
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Resolve a key path, expanding `*` over array indices. Returns [label, value]. */
|
|
153
|
+
function _resolveVersionField(
|
|
154
|
+
data: JsonValue,
|
|
155
|
+
keys: readonly string[],
|
|
156
|
+
prefix = "",
|
|
157
|
+
): Array<[string, JsonValue | undefined]> {
|
|
158
|
+
if (keys.length === 0) {
|
|
159
|
+
return [[prefix.replace(/^\./, ""), data]];
|
|
160
|
+
}
|
|
161
|
+
const [head, ...rest] = keys as [string, ...string[]];
|
|
162
|
+
if (head === "*") {
|
|
163
|
+
if (!Array.isArray(data)) {
|
|
164
|
+
return [[`${prefix}[*]`.replace(/^\./, ""), undefined]];
|
|
165
|
+
}
|
|
166
|
+
return data.flatMap((item, i) => _resolveVersionField(item, rest, `${prefix}[${String(i)}]`));
|
|
167
|
+
}
|
|
168
|
+
if (!isObject(data)) {
|
|
169
|
+
return [[`${prefix}.${head}`.replace(/^\./, ""), undefined]];
|
|
170
|
+
}
|
|
171
|
+
return _resolveVersionField(data[head] ?? null, rest, `${prefix}.${head}`);
|
|
172
|
+
}
|
|
173
|
+
|
|
91
174
|
export function main(): number {
|
|
92
175
|
// No corpus to count — the shim is exactly one manifest plus one pointer
|
|
93
176
|
// skill, and every count the shape offers (plugins, skill entries, dirs under
|
|
@@ -100,6 +183,8 @@ export function main(): number {
|
|
|
100
183
|
gate: "lint_marketplace",
|
|
101
184
|
candidates: [
|
|
102
185
|
".claude-plugin/marketplace.json",
|
|
186
|
+
".augment-plugin/plugin.json",
|
|
187
|
+
".augment-plugin/marketplace.json",
|
|
103
188
|
"package.json",
|
|
104
189
|
`${POINTER_SKILL_ENTRY.replace(/^\.\//, "")}/SKILL.md`,
|
|
105
190
|
],
|
|
@@ -161,6 +246,9 @@ export function main(): number {
|
|
|
161
246
|
`package.json version \`${String(pkgVersion)}\``,
|
|
162
247
|
);
|
|
163
248
|
}
|
|
249
|
+
if (typeof pkgVersion === "string") {
|
|
250
|
+
check_augment_manifests(pkgVersion, errors);
|
|
251
|
+
}
|
|
164
252
|
}
|
|
165
253
|
} else {
|
|
166
254
|
errors.push("`metadata` must be an object");
|
|
@@ -18,7 +18,13 @@
|
|
|
18
18
|
* shallow and the referrer roots named the pre-ADR-051 container. Repaired
|
|
19
19
|
* 2026-08-02; see the constants below.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* SECOND PASS (skill-link-integrity Phase 3): adapter lifecycle parity. See
|
|
22
|
+
* {@link adapter_lifecycle_findings} — the nearest existing scope for a check
|
|
23
|
+
* `docs/contracts/provider-lifecycle.md` says in its own words that CI does not
|
|
24
|
+
* perform.
|
|
25
|
+
*
|
|
26
|
+
* Exit codes: 0 all policies linked and lifecycle tags agree, 1 one or more
|
|
27
|
+
* orphan policies or a lifecycle disagreement, 2 dead scope.
|
|
22
28
|
*/
|
|
23
29
|
|
|
24
30
|
import * as fs from 'node:fs';
|
|
@@ -186,6 +192,110 @@ function referrers_for(policy: string, scanFiles: readonly string[]): string[] {
|
|
|
186
192
|
return referrers;
|
|
187
193
|
}
|
|
188
194
|
|
|
195
|
+
// ── Adapter lifecycle parity ────────────────────────────────────────────────
|
|
196
|
+
// `docs/contracts/provider-lifecycle.md:101` states the obligation and its own
|
|
197
|
+
// gap in one sentence: "Editing an adapter and leaving its header `Lifecycle:`
|
|
198
|
+
// comment out of sync with `agents/templates/.ai-video.xml.example` → violation
|
|
199
|
+
// (CI does not catch this; the agent must)." This pass makes CI catch it.
|
|
200
|
+
//
|
|
201
|
+
// EXPECTED GREEN ON LANDING, and that is the point rather than a weakness. The
|
|
202
|
+
// premise this was drafted against claimed a live contradiction between the
|
|
203
|
+
// higgsfield adapter header and the contract; re-reading the tree refuted it —
|
|
204
|
+
// the two surfaces the contract actually obliges to agree DO agree at `stable`,
|
|
205
|
+
// and the surface reading `experimental` is § 5, a table that says in its own
|
|
206
|
+
// words that it lists the tiers "on the day this contract lands". So there is
|
|
207
|
+
// nothing to repair today; the check exists so the next divergence is caught.
|
|
208
|
+
// Its sensitivity is proven by a fixture that must be red, not by a finding.
|
|
209
|
+
//
|
|
210
|
+
// § 5 IS DELIBERATELY NOT AN INPUT. A historical record must not be able to
|
|
211
|
+
// fail a live check — wiring it in would make the gate demand that a
|
|
212
|
+
// day-one table be edited, which would destroy the record it is.
|
|
213
|
+
//
|
|
214
|
+
// DRIVEN FROM THE ADAPTERS, NOT FROM THE XML. The example declares providers
|
|
215
|
+
// that have no adapter at all (`allin1`, `whisperx`) and one that is a
|
|
216
|
+
// documentation placeholder inside a commented example block
|
|
217
|
+
// (`my-future-backend`); iterating the xml would demand adapters for all three.
|
|
218
|
+
// The reverse direction is still covered: an adapter with no provider entry is
|
|
219
|
+
// reported, because a shipped adapter the example never declares is exactly the
|
|
220
|
+
// drift this pass is for.
|
|
221
|
+
|
|
222
|
+
/** `# Lifecycle: <tier>` from an adapter header. */
|
|
223
|
+
const ADAPTER_LIFECYCLE_RE = /^#\s*Lifecycle:\s*([a-z]+)/m;
|
|
224
|
+
|
|
225
|
+
/** Repo-relative adapter dir and the xml example the contract pairs it with. */
|
|
226
|
+
const ADAPTER_DIR = path.join(REPO, 'src', 'scripts', 'ai-video', 'adapters');
|
|
227
|
+
const AI_VIDEO_EXAMPLE = path.join(REPO, 'agents', 'templates', '.ai-video.xml.example');
|
|
228
|
+
|
|
229
|
+
/** `<provider id="x" …> … <lifecycle>tier</lifecycle>` pairs, xml order. */
|
|
230
|
+
export function parse_example_lifecycles(xml: string): Map<string, string> {
|
|
231
|
+
const out = new Map<string, string>();
|
|
232
|
+
const re = /<provider\s+id="([^"]+)"[^>]*>([\s\S]*?)<\/provider>/g;
|
|
233
|
+
let m: RegExpExecArray | null;
|
|
234
|
+
while ((m = re.exec(xml)) !== null) {
|
|
235
|
+
const tier = /<lifecycle>\s*([a-z]+)\s*<\/lifecycle>/.exec(m[2] as string);
|
|
236
|
+
// First declaration wins: the example's commented "how to add one"
|
|
237
|
+
// block repeats an id shape, and a later placeholder must not overwrite
|
|
238
|
+
// a real entry.
|
|
239
|
+
if (tier && !out.has(m[1] as string)) {
|
|
240
|
+
out.set(m[1] as string, tier[1] as string);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return out;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Findings for adapter-vs-example lifecycle disagreement. `[]` = parity holds. */
|
|
247
|
+
export function adapter_lifecycle_findings(
|
|
248
|
+
adapterDir: string = ADAPTER_DIR,
|
|
249
|
+
examplePath: string = AI_VIDEO_EXAMPLE,
|
|
250
|
+
): string[] {
|
|
251
|
+
const findings: string[] = [];
|
|
252
|
+
let xml: string;
|
|
253
|
+
try {
|
|
254
|
+
xml = fs.readFileSync(examplePath, 'utf-8');
|
|
255
|
+
} catch {
|
|
256
|
+
return [`${_relToPosix(examplePath, REPO)} is unreadable — lifecycle parity cannot be checked`];
|
|
257
|
+
}
|
|
258
|
+
const declared = parse_example_lifecycles(xml);
|
|
259
|
+
let entries: string[];
|
|
260
|
+
try {
|
|
261
|
+
entries = fs.readdirSync(adapterDir).filter((f) => f.endsWith('.sh')).sort();
|
|
262
|
+
} catch {
|
|
263
|
+
return [`${_relToPosix(adapterDir, REPO)} is unreadable — lifecycle parity cannot be checked`];
|
|
264
|
+
}
|
|
265
|
+
for (const file of entries) {
|
|
266
|
+
const id = file.replace(/\.sh$/, '');
|
|
267
|
+
const header = ADAPTER_LIFECYCLE_RE.exec(fs.readFileSync(path.join(adapterDir, file), 'utf-8'));
|
|
268
|
+
if (header === null) {
|
|
269
|
+
findings.push(`adapters/${file}: no \`# Lifecycle:\` header comment`);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const inXml = declared.get(id);
|
|
273
|
+
if (inXml === undefined) {
|
|
274
|
+
findings.push(
|
|
275
|
+
`adapters/${file}: header says \`${header[1] as string}\` but no ` +
|
|
276
|
+
`<provider id="${id}"> exists in ${_relToPosix(examplePath, REPO)}`,
|
|
277
|
+
);
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (inXml !== header[1]) {
|
|
281
|
+
findings.push(
|
|
282
|
+
`adapters/${file}: header \`${header[1] as string}\` != ` +
|
|
283
|
+
`<provider id="${id}"><lifecycle>${inXml}</lifecycle>`,
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return findings;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Adapter count, for the dead-scope assertion. */
|
|
291
|
+
export function count_adapters(adapterDir: string = ADAPTER_DIR): number {
|
|
292
|
+
try {
|
|
293
|
+
return fs.readdirSync(adapterDir).filter((f) => f.endsWith('.sh')).length;
|
|
294
|
+
} catch {
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
189
299
|
function main(): number {
|
|
190
300
|
// Scope assertions replace the two silent early returns this gate used to
|
|
191
301
|
// take. Both are deliberately WITHOUT `allowEmpty`: "the policy directory
|
|
@@ -207,6 +317,13 @@ function main(): number {
|
|
|
207
317
|
units: 'referrer-candidate file(s)',
|
|
208
318
|
roots: SCAN_ROOTS.map((r) => _relToPosix(r, REPO)),
|
|
209
319
|
});
|
|
320
|
+
// Zero adapters means the adapter root moved, not that parity holds.
|
|
321
|
+
assertScanned({
|
|
322
|
+
gate: 'lint_media_policy_linkage',
|
|
323
|
+
scanned: count_adapters(),
|
|
324
|
+
units: 'ai-video adapter(s)',
|
|
325
|
+
roots: [_relToPosix(ADAPTER_DIR, REPO)],
|
|
326
|
+
});
|
|
210
327
|
} catch (exc) {
|
|
211
328
|
if (!(exc instanceof DeadScopeError)) {
|
|
212
329
|
throw exc;
|
|
@@ -227,6 +344,11 @@ function main(): number {
|
|
|
227
344
|
emit(`✅ ${rel} (${referrers.length} referrer(s))`);
|
|
228
345
|
}
|
|
229
346
|
|
|
347
|
+
const lifecycle = adapter_lifecycle_findings();
|
|
348
|
+
for (const f of lifecycle) {
|
|
349
|
+
emit(`❌ LIFECYCLE ${f}`);
|
|
350
|
+
}
|
|
351
|
+
|
|
230
352
|
if (orphans.length > 0) {
|
|
231
353
|
process.stderr.write(
|
|
232
354
|
`\nmedia-policy-linkage: ${orphans.length} orphan policy ` +
|
|
@@ -239,10 +361,27 @@ function main(): number {
|
|
|
239
361
|
return 1;
|
|
240
362
|
}
|
|
241
363
|
|
|
364
|
+
if (lifecycle.length > 0) {
|
|
365
|
+
process.stderr.write(
|
|
366
|
+
`\nadapter-lifecycle-parity: ${lifecycle.length} disagreement(s) ` +
|
|
367
|
+
`between an adapter header and agents/templates/.ai-video.xml.example. ` +
|
|
368
|
+
`The day-one table in docs/contracts/provider-lifecycle.md § 5 is NOT ` +
|
|
369
|
+
`an input here — it is a historical record.\n`,
|
|
370
|
+
);
|
|
371
|
+
for (const f of lifecycle) {
|
|
372
|
+
process.stderr.write(` - ${f}\n`);
|
|
373
|
+
}
|
|
374
|
+
return 1;
|
|
375
|
+
}
|
|
376
|
+
|
|
242
377
|
emit(
|
|
243
378
|
`media-policy-linkage: ${policies.length} policy file(s) — all ` +
|
|
244
379
|
`linked (${scanFiles.length} file(s) scanned for referrers).`,
|
|
245
380
|
);
|
|
381
|
+
emit(
|
|
382
|
+
`adapter-lifecycle-parity: ${count_adapters()} adapter(s) — every ` +
|
|
383
|
+
`\`# Lifecycle:\` header agrees with its <provider> entry.`,
|
|
384
|
+
);
|
|
246
385
|
return 0;
|
|
247
386
|
}
|
|
248
387
|
|
|
@@ -28,6 +28,7 @@ import * as fs from 'node:fs';
|
|
|
28
28
|
import * as path from 'node:path';
|
|
29
29
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
30
30
|
|
|
31
|
+
import { asOf, asOfBanner } from './_lib/as_of.js';
|
|
31
32
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
32
33
|
|
|
33
34
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -59,7 +60,7 @@ interface SimpleDate {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
function _today_utc(): SimpleDate {
|
|
62
|
-
const now =
|
|
63
|
+
const now = asOf();
|
|
63
64
|
return {
|
|
64
65
|
y: now.getUTCFullYear(),
|
|
65
66
|
m: now.getUTCMonth() + 1,
|
|
@@ -369,6 +370,10 @@ export function main(): number {
|
|
|
369
370
|
}));
|
|
370
371
|
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
371
372
|
} else {
|
|
373
|
+
// Text only: the JSON payload is consumed by tooling and must stay a
|
|
374
|
+
// bare array. A reviewer reading the text report needs to know which
|
|
375
|
+
// "now" produced these ages — see `_lib/as_of.ts`.
|
|
376
|
+
process.stdout.write(`${asOfBanner()}\n`);
|
|
372
377
|
process.stdout.write(format_text(findings) + '\n');
|
|
373
378
|
}
|
|
374
379
|
return findings.some((f) => f.severity === 'fail') ? 1 : 0;
|
|
@@ -184,21 +184,32 @@ export function classify_violations(input: {
|
|
|
184
184
|
return violations;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
/**
|
|
188
|
+
* @param overridesDir Directory of override files to audit. Defaults to the real
|
|
189
|
+
* `agents/overrides/rules/`; a caller passes a fixture directory so the
|
|
190
|
+
* reachability of the audit itself can be tested against a KNOWN pair rather
|
|
191
|
+
* than against whatever the tree happens to contain. Added by step 1.2 of
|
|
192
|
+
* `road-to-override-efficacy-proof`: with the path hardcoded, a test could only
|
|
193
|
+
* assert against the one real override, so a regression that stopped
|
|
194
|
+
* discovering files would still read clean on an empty directory.
|
|
195
|
+
*
|
|
196
|
+
* Additive, with a default, so no existing caller changes.
|
|
197
|
+
*/
|
|
198
|
+
export function audit(overridesDir: string = OVERRIDES_RULES): OverrideRow[] {
|
|
199
|
+
if (!fs.existsSync(overridesDir)) return [];
|
|
189
200
|
const floor = safety_floor_ids(RULES_DIR);
|
|
190
201
|
const registered = fs.existsSync(REGISTRY)
|
|
191
202
|
? registered_rules(fs.readFileSync(REGISTRY, 'utf-8'))
|
|
192
203
|
: new Set<string>();
|
|
193
204
|
|
|
194
205
|
const rows: OverrideRow[] = [];
|
|
195
|
-
for (const name of fs.readdirSync(
|
|
206
|
+
for (const name of fs.readdirSync(overridesDir).sort()) {
|
|
196
207
|
if (!name.endsWith('.md')) continue;
|
|
197
208
|
const rule = name.replace(/\.md$/, '');
|
|
198
209
|
const kernel = is_kernel_rule(rule);
|
|
199
210
|
const is_floor = floor.has(rule);
|
|
200
211
|
|
|
201
|
-
const text = fs.readFileSync(path.join(
|
|
212
|
+
const text = fs.readFileSync(path.join(overridesDir, name), 'utf-8');
|
|
202
213
|
const mode = parse_mode(text);
|
|
203
214
|
const cited = has_citation(text);
|
|
204
215
|
const is_registered = registered.has(rule);
|
|
@@ -206,7 +217,7 @@ export function audit(): OverrideRow[] {
|
|
|
206
217
|
|
|
207
218
|
rows.push({
|
|
208
219
|
rule,
|
|
209
|
-
file: path.relative(REPO_ROOT, path.join(
|
|
220
|
+
file: path.relative(REPO_ROOT, path.join(overridesDir, name)),
|
|
210
221
|
mode,
|
|
211
222
|
kernel,
|
|
212
223
|
safety_floor: is_floor,
|
|
@@ -218,9 +229,65 @@ export function audit(): OverrideRow[] {
|
|
|
218
229
|
return rows;
|
|
219
230
|
}
|
|
220
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Render the precedence table — step 1.4 of `road-to-override-efficacy-proof`.
|
|
234
|
+
*
|
|
235
|
+
* The audit's answer already existed as JSON nobody runs. This is the same answer
|
|
236
|
+
* in a form a reviewer reads, and it is GENERATED rather than written: regenerating
|
|
237
|
+
* it on an unchanged tree must produce no diff, so the table is a fact about the
|
|
238
|
+
* tree rather than a snapshot of when someone last looked.
|
|
239
|
+
*
|
|
240
|
+
* Rows are sorted by `rule` (the audit already reads its directory sorted), and no
|
|
241
|
+
* timestamp is emitted. A generated file carrying "last updated" changes on every
|
|
242
|
+
* run and makes `git diff --exit-code` useless as a freshness check — the check the
|
|
243
|
+
* step's verify actually performs.
|
|
244
|
+
*/
|
|
245
|
+
export function render_precedence_table(rows: readonly OverrideRow[]): string {
|
|
246
|
+
const L: string[] = [];
|
|
247
|
+
L.push('<!-- evidence-type: analysis -->');
|
|
248
|
+
L.push('');
|
|
249
|
+
L.push('<!-- GENERATED by `lint_override_kernel_guard --write-table`. Do not hand-edit. -->');
|
|
250
|
+
L.push('');
|
|
251
|
+
L.push('# Override precedence table');
|
|
252
|
+
L.push('');
|
|
253
|
+
L.push(
|
|
254
|
+
'Every override in the tree, with the rule it overrides and its audit state. ' +
|
|
255
|
+
'Generated from the same `audit()` the strict gate runs, so the table and the ' +
|
|
256
|
+
'gate cannot disagree.',
|
|
257
|
+
);
|
|
258
|
+
L.push('');
|
|
259
|
+
L.push(
|
|
260
|
+
'**This is a DELIVERY table, not an efficacy claim.** It says an override file ' +
|
|
261
|
+
'is discovered, resolves to a rule, and carries its citation. Whether the agent ' +
|
|
262
|
+
'then behaves differently is a separate question, and it is measured nowhere in ' +
|
|
263
|
+
'this table — see `road-to-override-efficacy-proof` Phase 2, deferred on ' +
|
|
264
|
+
'population validity.',
|
|
265
|
+
);
|
|
266
|
+
L.push('');
|
|
267
|
+
if (rows.length === 0) {
|
|
268
|
+
L.push('No override files are present. That is a real and common state, not a fault.');
|
|
269
|
+
L.push('');
|
|
270
|
+
return L.join('\n');
|
|
271
|
+
}
|
|
272
|
+
L.push('| rule | mode | kernel | safety floor | registered | cited | violations |');
|
|
273
|
+
L.push('|---|---|---|---|---|---|---|');
|
|
274
|
+
for (const r of rows) {
|
|
275
|
+
L.push(
|
|
276
|
+
`| \`${r.rule}\` | \`${r.mode}\` | ${r.kernel ? 'yes' : 'no'} | ` +
|
|
277
|
+
`${r.safety_floor ? 'yes' : 'no'} | ${r.registered ? 'yes' : 'no'} | ` +
|
|
278
|
+
`${r.cited ? 'yes' : 'no'} | ${r.violations.length === 0 ? '—' : r.violations.join('; ')} |`,
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
L.push('');
|
|
282
|
+
L.push(`${String(rows.length)} override(s).`);
|
|
283
|
+
L.push('');
|
|
284
|
+
return L.join('\n');
|
|
285
|
+
}
|
|
286
|
+
|
|
221
287
|
function main(argv: string[]): number {
|
|
222
288
|
const as_json = argv.includes('--json');
|
|
223
289
|
const strict = argv.includes('--strict');
|
|
290
|
+
const tableIdx = argv.indexOf('--write-table');
|
|
224
291
|
|
|
225
292
|
// Not the override corpus: an empty `agents/overrides/rules/` is a real and
|
|
226
293
|
// common state (the report says so in words). The scope that cannot be
|
|
@@ -252,6 +319,21 @@ function main(argv: string[]): number {
|
|
|
252
319
|
|
|
253
320
|
const rows = audit();
|
|
254
321
|
|
|
322
|
+
if (tableIdx >= 0) {
|
|
323
|
+
const rel = argv[tableIdx + 1];
|
|
324
|
+
if (rel === undefined || rel.startsWith('--')) {
|
|
325
|
+
process.stderr.write('--write-table needs a path\n');
|
|
326
|
+
return 2;
|
|
327
|
+
}
|
|
328
|
+
const out = path.join(REPO_ROOT, rel);
|
|
329
|
+
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
330
|
+
fs.writeFileSync(out, render_precedence_table(rows), 'utf-8');
|
|
331
|
+
process.stdout.write(
|
|
332
|
+
`override precedence table: ${String(rows.length)} row(s) → ${rel}\n`,
|
|
333
|
+
);
|
|
334
|
+
return 0;
|
|
335
|
+
}
|
|
336
|
+
|
|
255
337
|
if (as_json) {
|
|
256
338
|
process.stdout.write(JSON.stringify({ overrides: rows }, null, 2) + '\n');
|
|
257
339
|
return 0;
|