@event4u/agent-config 16.3.0 → 16.5.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 +178 -78
- package/README.md +2 -2
- package/agents/templates/.ai-council.yml.example +26 -8
- package/dist/agent-src/commands/analyze/inbox.md +10 -7
- package/dist/agent-src/commands/bug/investigate.md +1 -1
- package/dist/agent-src/commands/commit/in-chunks.md +40 -31
- package/dist/agent-src/commands/commit.md +72 -33
- package/dist/agent-src/commands/condense.md +2 -8
- package/dist/agent-src/commands/council/debate.md +11 -7
- package/dist/agent-src/commands/council/default.md +10 -9
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/commands/estimate-ticket.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +3 -3
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +17 -3
- package/dist/agent-src/commands/fix/commit-messages.md +48 -23
- package/dist/agent-src/commands/fix/pr-comments.md +3 -6
- package/dist/agent-src/commands/implement-ticket.md +3 -3
- package/dist/agent-src/commands/memory/add.md +4 -16
- package/dist/agent-src/commands/memory/load.md +5 -6
- package/dist/agent-src/commands/memory/promote.md +3 -16
- package/dist/agent-src/commands/mission/upgrade.md +3 -2
- package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
- package/dist/agent-src/commands/optimize/deep.md +4 -2
- package/dist/agent-src/commands/optimize/rtk.md +4 -26
- package/dist/agent-src/commands/pr/create/description-only.md +18 -15
- package/dist/agent-src/commands/pr/create.md +42 -34
- package/dist/agent-src/commands/pr/merge.md +136 -9
- package/dist/agent-src/commands/prepare-for-review.md +13 -11
- package/dist/agent-src/commands/project/analyze.md +7 -35
- package/dist/agent-src/commands/refine-ticket.md +1 -1
- package/dist/agent-src/commands/review/changes.md +14 -19
- package/dist/agent-src/commands/roadmap/next.md +10 -1
- package/dist/agent-src/commands/roadmap/process-full.md +52 -38
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
- package/dist/agent-src/commands/worktree/create.md +7 -3
- package/dist/agent-src/commands/worktree/verify.md +2 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
- package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
- package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
- package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
- package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
- package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
- package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
- package/dist/agent-src/guidelines/php/git.md +15 -2
- package/dist/agent-src/rules/active-remediation.md +0 -1
- package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
- package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
- package/dist/agent-src/rules/autonomous-execution.md +0 -1
- package/dist/agent-src/rules/brand-consistency.md +0 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
- package/dist/agent-src/rules/broken-access-control.md +0 -1
- package/dist/agent-src/rules/cli-output-handling.md +0 -1
- package/dist/agent-src/rules/code-comment-discipline.md +0 -1
- package/dist/agent-src/rules/code-provenance.md +0 -1
- package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
- package/dist/agent-src/rules/commit-conventions.md +1 -2
- package/dist/agent-src/rules/communication-through-line.md +1 -2
- package/dist/agent-src/rules/content-quoting-floor.md +1 -2
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/copilot-routing.md +1 -2
- package/dist/agent-src/rules/council-availability.md +4 -4
- package/dist/agent-src/rules/cross-source-consistency.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
- package/dist/agent-src/rules/delegation-policy.md +2 -3
- package/dist/agent-src/rules/design-fidelity.md +0 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
- package/dist/agent-src/rules/devcontainer-routing.md +1 -2
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
- package/dist/agent-src/rules/docker-commands.md +0 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
- package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
- package/dist/agent-src/rules/domain-safety-pii.md +0 -1
- package/dist/agent-src/rules/domain-safety-retention.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +0 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/fix-what-you-see.md +6 -32
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +1 -2
- package/dist/agent-src/rules/guidelines.md +0 -1
- package/dist/agent-src/rules/history-discipline.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +0 -1
- package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
- package/dist/agent-src/rules/improve-before-implement.md +0 -1
- package/dist/agent-src/rules/invite-challenge.md +0 -1
- package/dist/agent-src/rules/laravel-routing.md +1 -2
- package/dist/agent-src/rules/laravel-translations.md +0 -1
- package/dist/agent-src/rules/legal-safety-floor.md +0 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/media-governance-routing.md +1 -2
- package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
- package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/model-recommendation.md +0 -1
- package/dist/agent-src/rules/neighbour-precedence.md +64 -0
- package/dist/agent-src/rules/no-attribution-footers.md +0 -1
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
- package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
- package/dist/agent-src/rules/no-roadmap-references.md +0 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
- package/dist/agent-src/rules/onboarding-gate.md +0 -1
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/package-ci-checks.md +0 -1
- package/dist/agent-src/rules/persona-governance.md +2 -3
- package/dist/agent-src/rules/php-coding.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
- package/dist/agent-src/rules/preservation-guard.md +0 -1
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
- package/dist/agent-src/rules/question-not-instruction.md +0 -1
- package/dist/agent-src/rules/reviewer-awareness.md +0 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -1
- package/dist/agent-src/rules/runtime-safety.md +0 -1
- package/dist/agent-src/rules/scale-discipline.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
- package/dist/agent-src/rules/self-repair-loop.md +0 -1
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
- package/dist/agent-src/rules/session-canary.md +0 -1
- package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
- package/dist/agent-src/rules/size-enforcement.md +0 -1
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
- package/dist/agent-src/rules/skill-quality.md +0 -1
- package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
- package/dist/agent-src/rules/source-confidentiality.md +0 -1
- package/dist/agent-src/rules/source-discovery-gate.md +0 -1
- package/dist/agent-src/rules/source-of-truth.md +0 -1
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
- package/dist/agent-src/rules/symfony-routing.md +1 -2
- package/dist/agent-src/rules/think-before-action.md +0 -1
- package/dist/agent-src/rules/token-budget-discipline.md +14 -48
- package/dist/agent-src/rules/token-efficiency.md +0 -1
- package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
- package/dist/agent-src/rules/upstream-proposal.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -1
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/scripts/gate_budget.ts +47 -23
- package/dist/agent-src/scripts/gate_execute.ts +12 -4
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
- package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
- package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
- package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
- package/dist/agent-src/skills/database/data/manifest.json +2 -2
- package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
- package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
- package/dist/agent-src/skills/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
- package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +46 -129
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +6 -1
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/commands/uiRender.js +201 -4
- package/dist/cli/commands/uiRenderAsset.js +1308 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
- package/dist/cli/main.js +47 -1
- package/dist/cli/registry.js +2 -1
- package/dist/cli-delegate/check_update_banner.js +195 -119
- package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
- package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
- package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
- package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
- package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
- package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
- package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
- package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
- package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
- package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
- package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
- package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
- package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
- package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
- package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
- package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
- package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
- package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
- package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
- package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
- package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
- package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
- package/dist/cli-delegate/cmd_analyze_session.js +223 -43
- package/dist/cli-delegate/cmd_brand_status.js +3 -2
- package/dist/cli-delegate/cmd_conformance.js +489 -238
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +15 -12
- package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
- package/dist/cli-delegate/cmd_explain.js +43 -19
- package/dist/cli-delegate/cmd_export.js +10 -10
- package/dist/cli-delegate/cmd_git_convention.js +1851 -0
- package/dist/cli-delegate/cmd_handoff.js +40 -21
- package/dist/cli-delegate/cmd_mcp_available.js +3 -2
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +4 -3
- package/dist/cli-delegate/cmd_prune.js +10 -10
- package/dist/cli-delegate/cmd_route_audit.js +7 -7
- package/dist/cli-delegate/cmd_route_explain.js +5 -5
- package/dist/cli-delegate/cmd_session_recycle.js +9 -7
- package/dist/cli-delegate/cmd_settings_check.js +54 -7
- package/dist/cli-delegate/cmd_settings_get.js +18 -8
- package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -10
- package/dist/cli-delegate/cmd_uninstall.js +10 -10
- package/dist/cli-delegate/cmd_update.js +7 -7
- package/dist/cli-delegate/cmd_upgrade.js +7 -7
- package/dist/cli-delegate/cmd_validate.js +10 -10
- package/dist/cli-delegate/cmd_versions.js +5 -5
- package/dist/cli-delegate/gate_budget.js +1 -1
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +171 -107
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +7 -7
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +41 -22
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -11
- package/dist/hooks/dispatch.js +2520 -1924
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/svg_rules.chunk.cjs +1626 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- package/dist/install/install.mjs +462 -431
- package/dist/install/installThinLayer.js +40 -12
- package/dist/install/installedRuleLinks.js +105 -19
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +5 -5
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +3063 -2160
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +15 -120
- package/dist/scripts/_lib/compile_time_toggles.js +12 -21
- package/dist/scripts/_lib/git_convention.js +232 -0
- package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
- package/dist/scripts/_lib/installed_layer.js +344 -18
- package/dist/scripts/_lib/package_root.js +68 -0
- package/dist/scripts/_lib/rule_law_section.js +1 -1
- package/dist/scripts/_lib/scan_scope.js +105 -0
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1337 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/_lib/thin_rules.js +80 -3
- package/dist/scripts/lint_svg_asset.js +324 -0
- package/dist/server/app.js +2 -1
- package/dist/server/gitKeysGate.js +105 -0
- package/dist/server/routes/settings.js +67 -8
- package/dist/server/routes/wizard.js +4 -0
- package/dist/server/schemas/settings.js +23 -81
- package/dist/shared/skillRanking.js +30 -4
- package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +72 -1
- package/docs/contracts/settings-classes.md +35 -65
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/docs/guidelines/agent-infra/layered-settings.md +13 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
- package/docs/guidelines/design-antipatterns.md +1 -1
- package/docs/guidelines/php/git.md +15 -2
- package/package.json +4 -3
- package/src/agent-src/scripts/gate_budget.ts +47 -23
- package/src/agent-src/scripts/gate_execute.ts +12 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/src/config/agent-settings.template.yml +79 -312
- package/src/config/agents-paths.yml +16 -0
- package/src/config/assurance-capability-registry.json +7 -3
- package/src/config/ci-local-parity.yml +3 -0
- package/src/config/continuity-surface.json +3 -3
- package/src/config/discovery/packs.yml +17 -1
- package/src/config/evaluator-budgets.json +19 -6
- package/src/config/gate-coverage.yml +65 -23
- package/src/config/gate-violation-baselines.json +56 -16
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-bundle-budget.json +1 -1
- package/src/config/release-gate-locality.yml +2 -1
- package/src/config/routing-coverage-seed.json +55 -6
- package/src/config/rule-law-ceilings.json +12 -6
- package/src/config/rule-obligations.json +833 -0
- package/src/install/installThinLayer.ts +76 -10
- package/src/install/installedRuleLinks.ts +105 -17
- package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
- package/src/scripts/_cli/cmd_conformance.ts +13 -2
- package/src/scripts/_cli/cmd_doctor.ts +10 -10
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
- package/src/scripts/_cli/cmd_explain.ts +72 -14
- package/src/scripts/_cli/cmd_git_convention.ts +637 -0
- package/src/scripts/_cli/cmd_settings_check.ts +66 -8
- package/src/scripts/_cli/cmd_settings_get.ts +18 -3
- package/src/scripts/_cli/doctor_execution.ts +72 -1
- package/src/scripts/_dispatch.bash +37 -2
- package/src/scripts/_lib/agent_settings.ts +15 -124
- package/src/scripts/_lib/blocked_by_marker.ts +1 -1
- package/src/scripts/_lib/compile_time_toggles.ts +12 -21
- package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
- package/src/scripts/_lib/git_base_ref.ts +92 -0
- package/src/scripts/_lib/git_convention.ts +291 -0
- package/src/scripts/_lib/git_convention_carrier.ts +389 -0
- package/src/scripts/_lib/git_convention_grammar.ts +246 -0
- package/src/scripts/_lib/git_convention_measure.ts +344 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
- package/src/scripts/_lib/graph_feeder_record.ts +236 -13
- package/src/scripts/_lib/installed_layer.ts +448 -23
- package/src/scripts/_lib/knowledge_global.ts +14 -1
- package/src/scripts/_lib/module_reach.ts +456 -0
- package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
- package/src/scripts/_lib/ratification_artifact.ts +220 -1
- package/src/scripts/_lib/ratification_subject.ts +92 -0
- package/src/scripts/_lib/release_findings_ingest.ts +15 -7
- package/src/scripts/_lib/release_highlights.ts +5 -0
- package/src/scripts/_lib/rule_law_section.ts +1 -1
- package/src/scripts/_lib/rule_obligations.ts +205 -0
- package/src/scripts/_lib/self_repair.ts +1 -1
- package/src/scripts/_lib/settings_removed_keys.ts +173 -0
- package/src/scripts/_lib/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1453 -0
- package/src/scripts/_lib/svg_urls.ts +72 -0
- package/src/scripts/_lib/test_red_state.ts +5 -0
- package/src/scripts/_lib/thin_rules.ts +83 -3
- package/src/scripts/_lib/touched_file_quality.ts +142 -6
- package/src/scripts/_lib/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +27 -17
- package/src/scripts/_lib/worker_budget.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +16 -1
- package/src/scripts/ai_council/config.ts +7 -7
- package/src/scripts/ai_council/modification_review.ts +100 -0
- package/src/scripts/ai_council/modification_review_questions.ts +90 -0
- package/src/scripts/ai_council/orchestrator.ts +5 -5
- package/src/scripts/ai_council/spend_gate.ts +18 -7
- package/src/scripts/ai_team/config.ts +11 -16
- package/src/scripts/audit_user_type_axis.ts +20 -8
- package/src/scripts/bench_ab_clone.ts +1 -2
- package/src/scripts/bench_concern_spawn_path.ts +129 -0
- package/src/scripts/bench_graph_feeder_latency.ts +584 -0
- package/src/scripts/check_agent_artifact_location.ts +36 -0
- package/src/scripts/check_branch_freshness.ts +147 -24
- package/src/scripts/check_enforcement_coverage.ts +130 -0
- package/src/scripts/check_evaluator_budgets.ts +4 -0
- package/src/scripts/check_finding_dispositions.ts +88 -25
- package/src/scripts/check_gate_coverage.ts +4 -3
- package/src/scripts/check_gate_reachability.ts +48 -1
- package/src/scripts/check_generator_sync.ts +48 -0
- package/src/scripts/check_hook_bundle_composition.ts +107 -0
- package/src/scripts/check_kernel_edit_ratified.ts +86 -6
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_release_manifest_content.ts +189 -0
- package/src/scripts/check_standing_rule_delivery.ts +96 -0
- package/src/scripts/check_suppression_hygiene.ts +2 -5
- package/src/scripts/ci_settle.ts +42 -5
- package/src/scripts/classify_merge_risk.ts +320 -0
- package/src/scripts/closure_scan.ts +91 -1
- package/src/scripts/command_suggester/settings.ts +8 -108
- package/src/scripts/command_suggester/types.ts +4 -5
- package/src/scripts/consumer_matrix.ts +102 -0
- package/src/scripts/context_hygiene_hook.ts +13 -23
- package/src/scripts/cost/preflight.mjs +12 -1
- package/src/scripts/council_cli.ts +7 -7
- package/src/scripts/dispatch_r2_reviewer.ts +24 -11
- package/src/scripts/explain_run.ts +8 -13
- package/src/scripts/generate_git_convention_grammar.ts +127 -0
- package/src/scripts/generate_host_cost_table.ts +20 -3
- package/src/scripts/handoff_context_hook.ts +86 -37
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +25 -6
- package/src/scripts/hooks/block_config_weakening.ts +48 -5
- package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/design_pass_hook.ts +157 -3
- package/src/scripts/hooks/evidence_independence.ts +12 -4
- package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
- package/src/scripts/hooks/push_settle_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +44 -3
- package/src/scripts/hooks/state_io.ts +8 -4
- package/src/scripts/hooks/svg_obligation.ts +497 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
- package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
- package/src/scripts/install-hooks.sh +42 -14
- package/src/scripts/install.ts +7 -31
- package/src/scripts/lint_blocker_citations.ts +198 -0
- package/src/scripts/lint_consolidation_lineage.ts +6 -3
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- package/src/scripts/lint_pack_boundaries.ts +406 -28
- package/src/scripts/lint_roadmap_blockers.ts +282 -29
- package/src/scripts/lint_roadmap_complexity.ts +4 -2
- package/src/scripts/lint_rule_law_section.ts +151 -21
- package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
- package/src/scripts/lint_settings_classes.ts +1 -1
- package/src/scripts/lint_svg_asset.ts +365 -0
- package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
- package/src/scripts/lint_workflow_security.ts +12 -1
- package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
- package/src/scripts/model_rule_injection.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +7 -6
- package/src/scripts/print_required_checks.ts +15 -3
- package/src/scripts/probe_host_compliance.ts +33 -5
- package/src/scripts/probe_turnaround.ts +183 -3
- package/src/scripts/ratification_header.ts +77 -0
- package/src/scripts/refusal_envelope.ts +138 -0
- package/src/scripts/release_publication.ts +29 -3
- package/src/scripts/report_dispatch_import_closure.ts +76 -0
- package/src/scripts/report_installed_rule_links.ts +118 -1
- package/src/scripts/report_module_reach.ts +212 -0
- package/src/scripts/report_obligation_mechanism.ts +16 -18
- package/src/scripts/report_parked_blockers.ts +222 -0
- package/src/scripts/report_required_checks_drift.ts +196 -0
- package/src/scripts/report_skill_ranker_confusion.ts +103 -2
- package/src/scripts/report_standing_payload_by_host.ts +1 -1
- package/src/scripts/routing_doctor.ts +2 -2
- package/src/scripts/schemas/agent-settings.schema.json +17 -31
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +1 -1
- package/src/scripts/self_review_gate.ts +39 -2
- package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
- package/src/scripts/sync_pr_branch.ts +403 -132
- package/src/scripts/trigger_eval_grandfather.json +0 -16
- package/src/server/schemas/settings.ts +33 -177
- package/src/shared/skillRanking.ts +53 -4
- package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
- package/src/scripts/_lib/config_chain.ts +0 -477
- package/src/scripts/_lib/conformance_report.ts +0 -403
- package/src/scripts/_lib/eval_discrimination.ts +0 -95
- package/src/scripts/_lib/evaluator_promotion.ts +0 -225
- package/src/scripts/_lib/file_slicer.ts +0 -117
- package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
- package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
- package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
- package/src/scripts/_lib/role_split.ts +0 -338
|
@@ -29,23 +29,11 @@
|
|
|
29
29
|
* settings file is how it learns it is off, the same as the artefact-
|
|
30
30
|
* engagement surface it mirrors.)
|
|
31
31
|
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* gating it on the org switch would print `0` everywhere (roadmap decision D9)
|
|
38
|
-
* — but it IS a file operation, so the guarantee now says which operations it
|
|
39
|
-
* covers. An unqualified claim this file's own code contradicts is worse than
|
|
40
|
-
* the narrower one it is replaced by.
|
|
41
|
-
*
|
|
42
|
-
* NOT REACHED YET, AND SAYING SO HERE BECAUSE THIS IS WHERE A READER LOOKS.
|
|
43
|
-
* The manifest entry for this concern carries `tools: [Skill]`, which the
|
|
44
|
-
* dispatcher matches exactly, so it is not invoked for an MCP call at all and
|
|
45
|
-
* the branch below is dead in production. Held as the
|
|
46
|
-
* `mcp-recorder-unreachable-behind-the-tools-filter` blocker on
|
|
47
|
-
* road-to-neighbours-that-pull-their-weight: the manifest is a gated
|
|
48
|
-
* governance surface and the council split on the edit rather than converging.
|
|
32
|
+
* The foreign-MCP tool-name recorder that once branched here lives in its own
|
|
33
|
+
* concern, `mcp-usage-observation` (road-to-neighbours-that-pull-their-weight
|
|
34
|
+
* D12): this concern's `tools: [Skill]` filter meant the dispatcher never
|
|
35
|
+
* called that branch, and default-on local collection does not belong under an
|
|
36
|
+
* opt-in telemetry name.
|
|
49
37
|
*
|
|
50
38
|
* NO OUTBOUND CALL EXISTS HERE, DELIBERATELY. Transport is Phase 2 and is
|
|
51
39
|
* blocked on `sink-choice`; org-wide enablement is Phase 3 and is blocked on
|
|
@@ -74,12 +62,7 @@ import {
|
|
|
74
62
|
FLUSH_SESSION_END,
|
|
75
63
|
spool_path_for,
|
|
76
64
|
} from '../../agent-src/templates/scripts/telemetry/transport.js';
|
|
77
|
-
import {
|
|
78
|
-
FOREIGN_TOOL_USE_REL,
|
|
79
|
-
MCP_TOOL_PREFIX,
|
|
80
|
-
usageDay,
|
|
81
|
-
} from '../_lib/neighbour_tool_use.js';
|
|
82
|
-
import { is_replay_mode, update_json_under_lock } from './state_io.js';
|
|
65
|
+
import { is_replay_mode } from './state_io.js';
|
|
83
66
|
import { readHookStdin } from './hook_stdin.js';
|
|
84
67
|
import { EXIT_ALLOW } from './exit_codes.js';
|
|
85
68
|
|
|
@@ -272,29 +255,7 @@ function processEnvelope(envelope: JsonValue, consumer_root: string): number {
|
|
|
272
255
|
|
|
273
256
|
const payload = unwrapPayload(envelope);
|
|
274
257
|
const tool = extractToolName(payload);
|
|
275
|
-
if (tool !== SKILL_TOOL_NAME)
|
|
276
|
-
// The other half of this slot's observation, and the only half a
|
|
277
|
-
// `post_tool_use` envelope can supply: the tool's NAME. The MCP
|
|
278
|
-
// fingerprint store wants a tool DEFINITION, which this envelope
|
|
279
|
-
// never carries (roadmap decision D2), so what is recorded here is
|
|
280
|
-
// what was actually seen. Rooted at the settings directory, not at
|
|
281
|
-
// the session cwd, for the same reason the Class-A log below is.
|
|
282
|
-
if (tool !== null && tool.startsWith(MCP_TOOL_PREFIX)) {
|
|
283
|
-
// The mutator's cast is safe at the only place that matters:
|
|
284
|
-
// the reader in `neighbour_tool_use` drops any value that is
|
|
285
|
-
// not a string, so a hand-edited store cannot widen this.
|
|
286
|
-
// Kept OUT of the argument list below — esbuild preserves a
|
|
287
|
-
// comment in that position and it would cost the shared
|
|
288
|
-
// bundle ~190 bytes of prose nothing executes.
|
|
289
|
-
const day = usageDay(new Date());
|
|
290
|
-
update_json_under_lock<Record<string, string>>(
|
|
291
|
-
path.join(readSettingsFor(consumer_root).root, FOREIGN_TOOL_USE_REL),
|
|
292
|
-
(seen) => (seen[tool] === day ? null : ({ ...seen, [tool]: day } as Record<string, string>)),
|
|
293
|
-
{ blocking: false },
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
return EXIT_ALLOW;
|
|
297
|
-
}
|
|
258
|
+
if (tool !== SKILL_TOOL_NAME) return EXIT_ALLOW;
|
|
298
259
|
|
|
299
260
|
const { settings, text, root } = readSettingsFor(consumer_root);
|
|
300
261
|
if (!settings.active) return EXIT_ALLOW;
|
|
@@ -197,7 +197,8 @@ import {
|
|
|
197
197
|
graphUntestedVerdict,
|
|
198
198
|
} from '../_lib/graph_feeder_record.js';
|
|
199
199
|
import { type GraphState, graphState } from '../code_graph/detect.js';
|
|
200
|
-
import { isVerificationCommand } from '../_lib/verification_command.js';
|
|
200
|
+
import { isVerificationAttempt, isVerificationCommand } from '../_lib/verification_command.js';
|
|
201
|
+
import { openSvgObligation } from './svg_obligation.js';
|
|
201
202
|
// Round 8 — the record path detector C prefers over its own regex. The regex
|
|
202
203
|
// reads a command's TEXT and `echo test` matches it; these read what the run
|
|
203
204
|
// exited with and what it printed.
|
|
@@ -761,7 +762,7 @@ export function detectUnverifiedEdit(
|
|
|
761
762
|
|
|
762
763
|
for (let i = lastEdit + 1; i < toolCalls.length; i += 1) {
|
|
763
764
|
const c = toolCalls[i]!;
|
|
764
|
-
if (c.name === 'Bash' && c.command !== undefined &&
|
|
765
|
+
if (c.name === 'Bash' && c.command !== undefined && isVerificationAttempt(c.command)) {
|
|
765
766
|
return null;
|
|
766
767
|
}
|
|
767
768
|
}
|
|
@@ -772,7 +773,7 @@ export function detectUnverifiedEdit(
|
|
|
772
773
|
evidence: edited,
|
|
773
774
|
reason:
|
|
774
775
|
'this turn changed a file and then ran no verification command — ' +
|
|
775
|
-
'no test, type-check, lint or
|
|
776
|
+
'no test, type-check, lint, build or asset render follows the last edit ' +
|
|
776
777
|
'(verify-before-complete: a claim without a fresh run is unverified)',
|
|
777
778
|
mode: 'transcript',
|
|
778
779
|
};
|
|
@@ -1281,6 +1282,7 @@ function runDetectors(inputs: DetectorInputs): Finding[] {
|
|
|
1281
1282
|
// on a completion CLAIM, and a turn waiting on a subagent has not
|
|
1282
1283
|
// finished — so its closing is not the claim F is about. Same slot,
|
|
1283
1284
|
// opposite trigger, opposite treatment of `dispatchOpen`.
|
|
1285
|
+
openSvgObligation(workspaceRoot, toolCalls),
|
|
1284
1286
|
dispatchOpen ? null : detectUntestedChange(lastAssistant, toolCalls, runState),
|
|
1285
1287
|
]) {
|
|
1286
1288
|
if (f) findings.push(f);
|
|
@@ -1333,6 +1335,7 @@ function recordGraphFeeder(
|
|
|
1333
1335
|
inputs.workspaceRoot,
|
|
1334
1336
|
inputs.sessionKey,
|
|
1335
1337
|
buildFeederRow({
|
|
1338
|
+
root: inputs.workspaceRoot,
|
|
1336
1339
|
turn: inputs.turnOrdinal,
|
|
1337
1340
|
layer,
|
|
1338
1341
|
state,
|
|
@@ -70,9 +70,13 @@ cat > "$HOOKS_DIR/pre-push" << 'EOF'
|
|
|
70
70
|
# belongs here; resolution belongs to a step run with the result in front of
|
|
71
71
|
# you. When this hook refuses for staleness, the thing that fixes it is
|
|
72
72
|
#
|
|
73
|
-
# task push-ready # fetch -> integrate the base SET -> regenerate
|
|
74
|
-
#
|
|
75
|
-
# task push-ready DRY=1 # the same six steps, read-only
|
|
73
|
+
# task push-ready BASE=<base> # fetch -> integrate the base SET -> regenerate
|
|
74
|
+
# # -> verify -> re-check freshness -> push
|
|
75
|
+
# task push-ready DRY=1 BASE=<base> # the same six steps, read-only
|
|
76
|
+
#
|
|
77
|
+
# `<base>` is the base the refusal names. Without BASE the base comes from the
|
|
78
|
+
# open pull request (gh pr view), and is the default branch only when there is
|
|
79
|
+
# no open pull request or no gh.
|
|
76
80
|
#
|
|
77
81
|
# The base is a SET: a branch targeting a release line or a stacked parent may
|
|
78
82
|
# also have to integrate the default branch, per the branch-convergence policy
|
|
@@ -141,23 +145,47 @@ fail=0
|
|
|
141
145
|
# no useful second finding to collect from a tree that is about to move.
|
|
142
146
|
#
|
|
143
147
|
# It never merges. `check_branch_freshness` asks the REMOTE (one `ls-remote`,
|
|
144
|
-
# measured 4.5s) and returns 1
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
# cannot
|
|
148
|
+
# measured 4.5s) and returns 1 on a VERIFIED behind state, or when the remote
|
|
149
|
+
# answered without the base at all (a misspelled or deleted base); offline, in
|
|
150
|
+
# CI, on a detached HEAD, or standing on the base itself it returns 0 and says
|
|
151
|
+
# so. So an unreachable network cannot block a push, and a stale local tracking
|
|
152
|
+
# ref cannot fake a green. The refusal below names which of the two it was, read
|
|
153
|
+
# from the gate's own lines, so a typo is never reported as staleness.
|
|
148
154
|
echo "🔍 Base freshness — is this branch behind the base it will merge into?"
|
|
149
155
|
if [ "${AGENT_CONFIG_SKIP_PREPUSH_FRESHNESS:-}" = "1" ]; then
|
|
150
156
|
echo "⏭️ skipped via AGENT_CONFIG_SKIP_PREPUSH_FRESHNESS=1"
|
|
151
157
|
elif [ ! -x ./scripts-run ]; then
|
|
152
158
|
echo "⚠️ ./scripts-run not found — skipping the freshness check for this push."
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
else
|
|
160
|
+
fresh_rc=0
|
|
161
|
+
fresh_out=$(./scripts-run src/scripts/check_branch_freshness --quiet 2>&1) || fresh_rc=$?
|
|
162
|
+
[ -z "$fresh_out" ] || printf '%s\n' "$fresh_out"
|
|
163
|
+
fi
|
|
164
|
+
if [ "${fresh_rc:-0}" -ne 0 ]; then
|
|
165
|
+
# The gate prints the base in the spelling `task push-ready` accepts.
|
|
166
|
+
base=$(printf '%s\n' "$fresh_out" | sed -n 's/^ *task push-ready BASE=\([^ ]*\).*/\1/p' | head -n 1)
|
|
167
|
+
absent=$(printf '%s\n' "$fresh_out" | sed -n 's/.*base `\([^`]*\)` does not exist on \([^ ]*\) .*/\2\/\1/p' | head -n 1)
|
|
157
168
|
echo ""
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
169
|
+
if [ -n "$base" ]; then
|
|
170
|
+
echo " Push blocked — the branch is behind its base, and the gates you just"
|
|
171
|
+
echo " passed were answered against a base that no longer exists."
|
|
172
|
+
echo ""
|
|
173
|
+
echo " task push-ready BASE=$base # fetch → integrate the base SET"
|
|
174
|
+
echo " # → regenerate → verify → re-check"
|
|
175
|
+
echo " task push-ready DRY=1 BASE=$base # the same steps, read-only"
|
|
176
|
+
elif printf '%s\n' "$fresh_out" | grep -q 'branch is BEHIND'; then
|
|
177
|
+
# A strategy that does not merge gets no push-ready line; its remedy
|
|
178
|
+
# is printed by the gate itself.
|
|
179
|
+
echo " Push blocked — the branch is behind its base. The remedy for this"
|
|
180
|
+
echo " project's update strategy is printed above."
|
|
181
|
+
elif [ -n "$absent" ]; then
|
|
182
|
+
echo " Push blocked — the base $absent does not exist on the remote: a"
|
|
183
|
+
echo " misspelled or deleted base, not a stale branch. Name a branch the"
|
|
184
|
+
echo " remote has (--base main and --base origin/main are the same branch)."
|
|
185
|
+
else
|
|
186
|
+
echo " Push blocked — the freshness gate refused without a verdict line;"
|
|
187
|
+
echo " its output is above."
|
|
188
|
+
fi
|
|
161
189
|
echo ""
|
|
162
190
|
echo " This hook refuses; it never merges. Bypass a genuine WIP push with"
|
|
163
191
|
echo " AGENT_CONFIG_SKIP_PREPUSH_FRESHNESS=1."
|
package/src/scripts/install.ts
CHANGED
|
@@ -334,15 +334,10 @@ const LEGACY_RENAME_MAP: Record<string, string> = {
|
|
|
334
334
|
open_edited_files: 'personal.open_edited_files',
|
|
335
335
|
user_name: 'personal.user_name',
|
|
336
336
|
rtk_installed: 'personal.rtk_installed',
|
|
337
|
-
minimal_output: 'personal.minimal_output',
|
|
338
|
-
play_by_play: 'personal.play_by_play',
|
|
339
|
-
pr_comment_bot_icon: 'project.pr_comment_bot_icon',
|
|
340
|
-
pr_template: 'project.pr_template',
|
|
341
337
|
upstream_repo: 'project.upstream_repo',
|
|
342
338
|
improvement_pr_branch_prefix: 'project.improvement_pr_branch_prefix',
|
|
343
339
|
github_pr_reply_method: 'github.pr_reply_method',
|
|
344
340
|
eloquent_access_style: 'eloquent.access_style',
|
|
345
|
-
skill_improvement_pipeline: 'pipelines.skill_improvement',
|
|
346
341
|
subagent_implementer_model: 'subagents.implementer_model',
|
|
347
342
|
subagent_judge_model: 'subagents.judge_model',
|
|
348
343
|
subagent_max_parallel: 'subagents.max_parallel',
|
|
@@ -3032,7 +3027,7 @@ function _deploy_global_content(
|
|
|
3032
3027
|
warn(`claude-code: thinned rule layer not written — ${String(e)}`);
|
|
3033
3028
|
}
|
|
3034
3029
|
}
|
|
3035
|
-
if (!state.QUIET) for (const l of installReceiptBudgetLines(package_root)) info(l);
|
|
3030
|
+
if (!state.QUIET) for (const l of installReceiptBudgetLines(package_root, undefined, { thisDeploy: new Map([[anchor, current_files]]) })) info(l);
|
|
3036
3031
|
}
|
|
3037
3032
|
|
|
3038
3033
|
const missing_targets = _verify_deploy_targets(anchor, plan);
|
|
@@ -4773,27 +4768,11 @@ function _read_consumer_auto_switch(project_root: string): string {
|
|
|
4773
4768
|
/**
|
|
4774
4769
|
* Team-mode setup hint (road-to-team-mode Phase 1 Step 2) — a one-line
|
|
4775
4770
|
* recommendation printed after a claude-code install/init pointing at the
|
|
4776
|
-
* doctor `team` section.
|
|
4777
|
-
*
|
|
4778
|
-
*
|
|
4779
|
-
* leniently). Pointer only: never auto-installs, never modifies
|
|
4780
|
-
* `~/.claude/plugins`.
|
|
4771
|
+
* doctor `team` section. Always shown: the `ai_team.suppress_setup_hint` key
|
|
4772
|
+
* that could silence it was retired with its default (false). Pointer only:
|
|
4773
|
+
* never auto-installs, never modifies `~/.claude/plugins`.
|
|
4781
4774
|
*/
|
|
4782
|
-
function _team_setup_hint_line(
|
|
4783
|
-
let data: Record<string, unknown>;
|
|
4784
|
-
try {
|
|
4785
|
-
data = load_agent_settings({ project_path: _resolve_settings_read(project_root) });
|
|
4786
|
-
} catch {
|
|
4787
|
-
data = {};
|
|
4788
|
-
}
|
|
4789
|
-
const ai_team = _isPlainObject(data) ? data['ai_team'] : null;
|
|
4790
|
-
const flag = _isPlainObject(ai_team)
|
|
4791
|
-
? (ai_team as Record<string, unknown>)['suppress_setup_hint']
|
|
4792
|
-
: null;
|
|
4793
|
-
const suppressed =
|
|
4794
|
-
flag === true ||
|
|
4795
|
-
(typeof flag === 'string' && ['true', 'yes', 'on', '1'].includes(flag.trim().toLowerCase()));
|
|
4796
|
-
if (suppressed) return null;
|
|
4775
|
+
function _team_setup_hint_line(): string {
|
|
4797
4776
|
return (
|
|
4798
4777
|
' • Claude Code team mode (optional cross-model review via the official ' +
|
|
4799
4778
|
'codex plugin): run `agent-config doctor --check team` for setup status.'
|
|
@@ -5006,11 +4985,8 @@ function _main_project_install(
|
|
|
5006
4985
|
}
|
|
5007
4986
|
mcp_consent.printResiduals(tools, state.QUIET);
|
|
5008
4987
|
if (_is_tool_enabled(tools, 'claude-code')) {
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
process.stdout.write(team_hint + '\n');
|
|
5012
|
-
process.stdout.write('\n');
|
|
5013
|
-
}
|
|
4988
|
+
process.stdout.write(_team_setup_hint_line() + '\n');
|
|
4989
|
+
process.stdout.write('\n');
|
|
5014
4990
|
}
|
|
5015
4991
|
}
|
|
5016
4992
|
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Every `path:line` a roadmap blocker cites must still point at a line.
|
|
4
|
+
*
|
|
5
|
+
* A blocker's `What to do` and `Resolved when` lean on citations like
|
|
6
|
+
* `src/scripts/foo.ts:120-134`. Line numbers move with every edit above them,
|
|
7
|
+
* and nothing re-reads a citation once it is written — `check_references`
|
|
8
|
+
* resolves names, not line numbers. A cited range that now runs past the end
|
|
9
|
+
* of its file sends the reader of the blocker to nothing.
|
|
10
|
+
*
|
|
11
|
+
* Scope: the `## Blockers` section of every active roadmap and every stub.
|
|
12
|
+
* Checked: the file exists and the last cited line is within its length.
|
|
13
|
+
* Not checked: what the line says — a content check would red on every
|
|
14
|
+
* harmless edit above it.
|
|
15
|
+
*
|
|
16
|
+
* A citation is a repository-relative path with a file extension, `:`, a line
|
|
17
|
+
* number and an optional `-<line>` end. A bare `:354-359` with no path is
|
|
18
|
+
* relative to prose above it and is not read.
|
|
19
|
+
*
|
|
20
|
+
* Existing misses are ratcheted (`gate-violation-baselines.json`, gate
|
|
21
|
+
* `lint_blocker_citations`): line numbers drift, so a miss already in the tree
|
|
22
|
+
* is drift rather than a new defect, and the count may only fall.
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 within the ratchet · 1 above it · 2 usage error.
|
|
25
|
+
*/
|
|
26
|
+
import * as fs from 'node:fs';
|
|
27
|
+
import * as path from 'node:path';
|
|
28
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
29
|
+
|
|
30
|
+
import { checkRatchet } from './_lib/gate_baseline.js';
|
|
31
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
32
|
+
|
|
33
|
+
type MissKind = 'missing-file' | 'beyond-end';
|
|
34
|
+
|
|
35
|
+
interface Citation {
|
|
36
|
+
roadmap: string;
|
|
37
|
+
line: number;
|
|
38
|
+
target: string;
|
|
39
|
+
first: number;
|
|
40
|
+
last: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface Miss extends Citation {
|
|
44
|
+
kind: MissKind;
|
|
45
|
+
length: number | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const BLOCKERS_SECTION_RE = /^##[ \t]+Blockers[ \t]*$/im;
|
|
49
|
+
const NEXT_H2_RE = /^##[ \t]+\S/m;
|
|
50
|
+
const CITATION_RE = /(?<![\w./:-])((?:[\w.-]+\/)*[\w-][\w.-]*\.[A-Za-z0-9]+):(\d+)(?:-(\d+))?(?!\d)/g;
|
|
51
|
+
|
|
52
|
+
/** Citations inside the `## Blockers` section, with their line in the roadmap. */
|
|
53
|
+
function citationsIn(text: string, roadmap: string): Citation[] {
|
|
54
|
+
const m = BLOCKERS_SECTION_RE.exec(text);
|
|
55
|
+
if (!m) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
const start = m.index + m[0].length;
|
|
59
|
+
const rest = text.slice(start);
|
|
60
|
+
const h2 = NEXT_H2_RE.exec(rest);
|
|
61
|
+
const section = h2 ? rest.slice(0, h2.index) : rest;
|
|
62
|
+
const lineOffset = text.slice(0, start).split('\n').length - 1;
|
|
63
|
+
const out: Citation[] = [];
|
|
64
|
+
section.split('\n').forEach((raw, i) => {
|
|
65
|
+
for (const c of raw.matchAll(CITATION_RE)) {
|
|
66
|
+
const first = Number(c[2]);
|
|
67
|
+
const last = c[3] === undefined ? first : Number(c[3]);
|
|
68
|
+
out.push({ roadmap, line: lineOffset + i + 1, target: c[1] as string, first, last });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Line count of the cited file, repo-relative first, then relative to the citing roadmap. */
|
|
75
|
+
function _lengthOf(root: string, c: Citation): number | null {
|
|
76
|
+
for (const abs of [path.join(root, c.target), path.join(root, path.dirname(c.roadmap), c.target)]) {
|
|
77
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isFile()) {
|
|
78
|
+
return fs.readFileSync(abs, 'utf8').replace(/\n$/, '').split('\n').length;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function checkCitation(root: string, c: Citation, lengths: Map<string, number | null>): Miss | null {
|
|
85
|
+
const key = `${path.dirname(c.roadmap)}\0${c.target}`;
|
|
86
|
+
let length = lengths.get(key);
|
|
87
|
+
if (length === undefined) {
|
|
88
|
+
length = _lengthOf(root, c);
|
|
89
|
+
lengths.set(key, length);
|
|
90
|
+
}
|
|
91
|
+
if (length === null) {
|
|
92
|
+
return { ...c, kind: 'missing-file', length };
|
|
93
|
+
}
|
|
94
|
+
return Math.max(c.first, c.last) > length ? { ...c, kind: 'beyond-end', length } : null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function roadmapFiles(root: string): string[] {
|
|
98
|
+
const out: string[] = [];
|
|
99
|
+
for (const sub of ['', 'stubs']) {
|
|
100
|
+
const dir = path.join(root, 'agents', 'roadmaps', sub);
|
|
101
|
+
let names: string[];
|
|
102
|
+
try {
|
|
103
|
+
names = fs.readdirSync(dir);
|
|
104
|
+
} catch {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
for (const n of names.sort()) {
|
|
108
|
+
const abs = path.join(dir, n);
|
|
109
|
+
if (n.endsWith('.md') && fs.statSync(abs).isFile()) {
|
|
110
|
+
out.push(path.relative(root, abs).split(path.sep).join('/'));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function scanTree(root: string): { misses: Miss[]; scanned: number; citations: number } {
|
|
118
|
+
const lengths = new Map<string, number | null>();
|
|
119
|
+
const files = roadmapFiles(root);
|
|
120
|
+
const misses: Miss[] = [];
|
|
121
|
+
let citations = 0;
|
|
122
|
+
for (const rel of files) {
|
|
123
|
+
for (const c of citationsIn(fs.readFileSync(path.join(root, rel), 'utf8'), rel)) {
|
|
124
|
+
citations += 1;
|
|
125
|
+
const miss = checkCitation(root, c, lengths);
|
|
126
|
+
if (miss) {
|
|
127
|
+
misses.push(miss);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return { misses, scanned: files.length, citations };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const _DEFAULT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
135
|
+
|
|
136
|
+
function main(argv: string[] = process.argv.slice(2)): number {
|
|
137
|
+
let root = _DEFAULT_ROOT;
|
|
138
|
+
let baselineRoot = _DEFAULT_ROOT;
|
|
139
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
140
|
+
const arg = argv[i];
|
|
141
|
+
if (arg === '--root') {
|
|
142
|
+
const v = argv[i + 1];
|
|
143
|
+
if (v === undefined) {
|
|
144
|
+
process.stderr.write('lint_blocker_citations: --root requires a value\n');
|
|
145
|
+
return 2;
|
|
146
|
+
}
|
|
147
|
+
root = path.resolve(v);
|
|
148
|
+
baselineRoot = root;
|
|
149
|
+
i += 1;
|
|
150
|
+
} else {
|
|
151
|
+
process.stderr.write(`lint_blocker_citations: unknown argument: ${String(arg)}\n`);
|
|
152
|
+
return 2;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const { misses, scanned, citations } = scanTree(root);
|
|
156
|
+
reportScanned({
|
|
157
|
+
gate: 'lint_blocker_citations',
|
|
158
|
+
scanned,
|
|
159
|
+
units: 'roadmap file(s)',
|
|
160
|
+
roots: ['agents/roadmaps', 'agents/roadmaps/stubs'],
|
|
161
|
+
allowEmpty: 'EMPTY_VALID: a checkout with no active roadmap cites nothing',
|
|
162
|
+
});
|
|
163
|
+
const verdict = checkRatchet({ gate: 'lint_blocker_citations', actual: misses.length, repoRoot: baselineRoot });
|
|
164
|
+
const lines = misses.map(
|
|
165
|
+
(m) =>
|
|
166
|
+
` ${m.roadmap}:${String(m.line)} · ${m.target}:${String(m.first)}${m.last !== m.first ? `-${String(m.last)}` : ''} · ` +
|
|
167
|
+
(m.kind === 'missing-file' ? 'file does not exist' : `file has ${String(m.length)} line(s)`),
|
|
168
|
+
);
|
|
169
|
+
if (!verdict.ok) {
|
|
170
|
+
process.stderr.write(`❌ ${verdict.message}\n`);
|
|
171
|
+
process.stderr.write(`${lines.join('\n')}\n`);
|
|
172
|
+
return 1;
|
|
173
|
+
}
|
|
174
|
+
process.stdout.write(
|
|
175
|
+
`✅ lint_blocker_citations: ${String(citations)} citation(s) in ${String(scanned)} roadmap file(s). ${verdict.message}\n`,
|
|
176
|
+
);
|
|
177
|
+
if (lines.length > 0) {
|
|
178
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (process.argv[1] !== undefined) {
|
|
184
|
+
try {
|
|
185
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
186
|
+
const argv1 = fs.realpathSync(path.resolve(process.argv[1]));
|
|
187
|
+
if (here === argv1) {
|
|
188
|
+
process.exit(main());
|
|
189
|
+
}
|
|
190
|
+
} catch {
|
|
191
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
192
|
+
process.exit(main());
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export { citationsIn, checkCitation, scanTree, main };
|
|
198
|
+
export type { Citation, Miss };
|
|
@@ -313,18 +313,21 @@ export function analyseFolder(
|
|
|
313
313
|
surface: Surface = 'inbox',
|
|
314
314
|
): Finding[] {
|
|
315
315
|
const findings: Finding[] = [];
|
|
316
|
-
let
|
|
316
|
+
let entries: string[];
|
|
317
317
|
try {
|
|
318
|
-
|
|
318
|
+
entries = fs.readdirSync(dir);
|
|
319
319
|
} catch {
|
|
320
320
|
return findings;
|
|
321
321
|
}
|
|
322
|
+
const names = entries.filter((n) => ROADMAP_RE.test(n)).sort();
|
|
322
323
|
const artifacts: Artifact[] = names.map((n) => ({
|
|
323
324
|
stem: n.replace(/\.md$/i, ''),
|
|
324
325
|
file: n,
|
|
325
326
|
decl: parseDeclaration(fs.readFileSync(path.join(dir, n), 'utf-8'), surface),
|
|
326
327
|
}));
|
|
327
|
-
|
|
328
|
+
// A parent need not be named road-to-*: a dated deep-dive plan is a parent
|
|
329
|
+
// too, and only its absence makes it missing.
|
|
330
|
+
const present = new Set(entries.filter((n) => /\.md$/i.test(n)).map((n) => n.replace(/\.md$/i, '')));
|
|
328
331
|
|
|
329
332
|
for (const a of artifacts) {
|
|
330
333
|
if (a.decl.unparseable) {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* DQ1 contrast — Text/background contrast < WCAG AA (4.5:1 normal, 3:1 large)
|
|
14
14
|
* DQ2 font-size — Body font-size < 14px (floor; 16px strongly preferred)
|
|
15
15
|
* DQ3 line-length — Prose line-length > 75ch without column constraint
|
|
16
|
-
* DQ4 reduced-motion — @keyframes / animation present without prefers-reduced-motion alt
|
|
16
|
+
* DQ4 reduced-motion — @keyframes / animation present without prefers-reduced-motion alt,
|
|
17
|
+
* and (for INLINE SVG in HTML) SMIL with no route or a CSS-only one
|
|
17
18
|
* DQ5 heading-skip — Heading levels skipped (h1 → h3 without h2)
|
|
18
19
|
* DQ6 focus-indicator— Interactive element with no :focus-visible indicator
|
|
19
20
|
*
|
|
@@ -45,6 +46,7 @@
|
|
|
45
46
|
import fs from "node:fs";
|
|
46
47
|
import path from "node:path";
|
|
47
48
|
import { assertScanned, DeadScopeError } from "./_lib/scan_scope.js";
|
|
49
|
+
import { firstSmilLine, smilVerdict } from "./_lib/svg_motion.js";
|
|
48
50
|
|
|
49
51
|
interface Finding {
|
|
50
52
|
rule: string;
|
|
@@ -94,25 +96,71 @@ function checkFontSize(lines: string[], filePath: string): Finding[] {
|
|
|
94
96
|
return findings;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
/**
|
|
99
|
+
/**
|
|
100
|
+
* DQ4: animation without a reduced-motion route.
|
|
101
|
+
*
|
|
102
|
+
* Two halves. The CSS half is the original rule. The SMIL half (step 1.3 of
|
|
103
|
+
* `road-to-svg-with-a-witness`) covers INLINE SVG inside an HTML document and
|
|
104
|
+
* closes a measured blind spot: an HTML file whose only animation is an
|
|
105
|
+
* infinite `<animate>` read "clean — 1 file(s) checked" here, because
|
|
106
|
+
* `@keyframes` and `animation:` are the only two things the CSS half looks
|
|
107
|
+
* for, and SMIL is neither (R10).
|
|
108
|
+
*
|
|
109
|
+
* It also reports the subtler case: SMIL whose ONLY reduced-motion route is a
|
|
110
|
+
* CSS declaration. Under an emulated `reduce`, a page-level
|
|
111
|
+
* `svg * { animation: none !important }` left an `<animate>` moving `cx` from
|
|
112
|
+
* 20.2 to 76.8 in 700 ms (R4) — CSS animation properties do not reach SMIL, so
|
|
113
|
+
* the file looks covered and is not.
|
|
114
|
+
*
|
|
115
|
+
* STANDALONE `.svg` IS DELIBERATELY NOT HERE. A file cannot see its host's
|
|
116
|
+
* `<picture>` route, so judging the route from inside it would red correct
|
|
117
|
+
* assets and break this linter's zero-false-positive promise (line 12). That
|
|
118
|
+
* case belongs to `lint_svg_asset`, which knows it is reading a whole asset.
|
|
119
|
+
* Both halves read the same `_lib/svg_motion.ts`, so the two cannot drift.
|
|
120
|
+
*/
|
|
98
121
|
function checkReducedMotion(content: string, filePath: string, lines: string[]): Finding[] {
|
|
99
|
-
const
|
|
100
|
-
if (!hasAnimation) return [];
|
|
122
|
+
const findings: Finding[] = [];
|
|
101
123
|
|
|
124
|
+
const hasAnimation = /@keyframes\s+\w+|animation\s*:/i.test(content);
|
|
102
125
|
const hasReducedMotion = /@media\s*\([^)]*prefers-reduced-motion/i.test(content);
|
|
103
|
-
if (hasReducedMotion)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const animLine = lines.findIndex((l) => /@keyframes\s+\w+|animation\s*:/.test(l));
|
|
107
|
-
return [
|
|
108
|
-
{
|
|
126
|
+
if (hasAnimation && !hasReducedMotion) {
|
|
127
|
+
const animLine = lines.findIndex((l) => /@keyframes\s+\w+|animation\s*:/.test(l));
|
|
128
|
+
findings.push({
|
|
109
129
|
rule: "dq4-reduced-motion",
|
|
110
130
|
file: filePath,
|
|
111
131
|
line: animLine + 1,
|
|
112
132
|
snippet: "@keyframes or animation present without @media (prefers-reduced-motion) alternative",
|
|
113
133
|
severity: "error",
|
|
114
|
-
}
|
|
115
|
-
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// The SMIL half runs for documents that can HOST an inline graphic. A `.css`
|
|
138
|
+
// file cannot carry one, and a standalone `.svg` is the other linter's.
|
|
139
|
+
if (!/\.(html|htm|vue|svelte|astro)$/i.test(filePath)) return findings;
|
|
140
|
+
|
|
141
|
+
const verdict = smilVerdict(content);
|
|
142
|
+
if (verdict === "no-route") {
|
|
143
|
+
findings.push({
|
|
144
|
+
rule: "dq4-reduced-motion",
|
|
145
|
+
file: filePath,
|
|
146
|
+
line: firstSmilLine(content),
|
|
147
|
+
snippet:
|
|
148
|
+
"inline SVG animates with SMIL (<animate>/<animateTransform>/<set>) and the document carries " +
|
|
149
|
+
"no @media (prefers-reduced-motion) route at all",
|
|
150
|
+
severity: "error",
|
|
151
|
+
});
|
|
152
|
+
} else if (verdict === "css-only") {
|
|
153
|
+
findings.push({
|
|
154
|
+
rule: "dq4-reduced-motion",
|
|
155
|
+
file: filePath,
|
|
156
|
+
line: firstSmilLine(content),
|
|
157
|
+
snippet:
|
|
158
|
+
"inline SVG animates with SMIL and the only reduced-motion route is a CSS animation/transition " +
|
|
159
|
+
"declaration — CSS does not reach SMIL, so the animation keeps running under `reduce`",
|
|
160
|
+
severity: "error",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return findings;
|
|
116
164
|
}
|
|
117
165
|
|
|
118
166
|
/** DQ5: heading levels skipped (h1 → h3 without h2) in HTML */
|
|
@@ -50,6 +50,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
50
50
|
|
|
51
51
|
import { GateLedger } from './_lib/gate_ledger.js';
|
|
52
52
|
import { resolveBaseRef } from './_lib/ratchet_base_ref.js';
|
|
53
|
+
import { parseExecutionMode } from './_lib/repeated_run.js';
|
|
53
54
|
import { reportScanned } from './_lib/scan_scope.js';
|
|
54
55
|
import { parseHonestNull, parseMarkerLine, parseSkipDeclaration } from './check_completion_review.js';
|
|
55
56
|
|
|
@@ -257,6 +258,14 @@ export function checkFiles(root: string, files: readonly string[], ledger?: Gate
|
|
|
257
258
|
});
|
|
258
259
|
continue;
|
|
259
260
|
}
|
|
261
|
+
// The contract's second axis (repeated-run / flaky), orthogonal to the
|
|
262
|
+
// type marker above — any artifact may declare it.
|
|
263
|
+
const mode = parseExecutionMode(contents);
|
|
264
|
+
if (mode.kind === 'invalid') {
|
|
265
|
+
ledger?.fail(rel, `invalid evidence-mode: ${mode.reason}`);
|
|
266
|
+
findings.push({ file: rel, reason: `evidence-mode: ${mode.reason}` });
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
260
269
|
ledger?.complete(rel);
|
|
261
270
|
}
|
|
262
271
|
return findings;
|