@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
|
@@ -126,12 +126,13 @@ const _PATH_KEYS: readonly string[] = ['file_path', 'path', 'target_file', 'file
|
|
|
126
126
|
export type ConfigKind = 'allowlist' | 'advisory' | 'class-c' | null;
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* Project settings files
|
|
129
|
+
* Project settings files, and the committed git-convention carrier (ADR-283),
|
|
130
|
+
* whose keys this guard fences. User-global files are
|
|
130
131
|
* never in reach — the hook only sees a path a tool call named, and the writes
|
|
131
132
|
* that reach `~/.event4u/` go through `settings:set`, which applies its own
|
|
132
133
|
* per-key refusal.
|
|
133
134
|
*/
|
|
134
|
-
const CLASS_C_BASENAMES: readonly string[] = ['.agent-settings.yml', '.agent-settings.yaml', 'settings.json'];
|
|
135
|
+
const CLASS_C_BASENAMES: readonly string[] = ['.agent-settings.yml', '.agent-settings.yaml', '.git-convention.yml', 'settings.json'];
|
|
135
136
|
|
|
136
137
|
/** Where the class contract lives, relative to the package root. */
|
|
137
138
|
export const SETTINGS_CLASSES_RELATIVE = 'docs/contracts/settings-classes.md';
|
|
@@ -382,10 +383,25 @@ export interface Decision {
|
|
|
382
383
|
* unreadable for the length of one tool call, which is a bypass with no
|
|
383
384
|
* authorisation step in it.
|
|
384
385
|
*
|
|
386
|
+
* The edit forms it models: `Write` (`content`), `Edit` (`old_string` /
|
|
387
|
+
* `new_string`, with `replace_all`) and `MultiEdit` (an `edits` list of those
|
|
388
|
+
* pairs, applied in order).
|
|
389
|
+
*
|
|
385
390
|
* WHAT IT CANNOT SEE: an edit applied through a shell redirect rather than an
|
|
386
391
|
* edit tool — `EDIT_TOOLS` is the corpus, and the shell shapes are
|
|
387
392
|
* `block_plumbing_writes`' subject, not this one.
|
|
388
393
|
*/
|
|
394
|
+
/** The host writes `new_string` verbatim; `String.replace` would expand `$&`-style tokens. */
|
|
395
|
+
function _replaceFirstLiteral(text: string, from: string, to: string): string {
|
|
396
|
+
const at = text.indexOf(from);
|
|
397
|
+
return text.slice(0, at) + to + text.slice(at + from.length);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/** An empty `old_string` is the host's create form, which `split('')` does not model. */
|
|
401
|
+
function _applyEdit(text: string, from: string, to: string, all: unknown): string {
|
|
402
|
+
return all === true && from !== '' ? text.split(from).join(to) : _replaceFirstLiteral(text, from, to);
|
|
403
|
+
}
|
|
404
|
+
|
|
389
405
|
export function classCVerdict(
|
|
390
406
|
ti: JsonObject,
|
|
391
407
|
on_disk: string | null,
|
|
@@ -397,11 +413,22 @@ export function classCVerdict(
|
|
|
397
413
|
const content = ti['content'];
|
|
398
414
|
const oldStr = ti['old_string'];
|
|
399
415
|
const newStr = ti['new_string'];
|
|
416
|
+
const forms = [content !== undefined, oldStr !== undefined || newStr !== undefined, ti['edits'] !== undefined];
|
|
417
|
+
if (forms.filter(Boolean).length > 1) {
|
|
418
|
+
return (
|
|
419
|
+
`${rel_path}: this edit carries more than one edit form (content, old_string/new_string, edits), ` +
|
|
420
|
+
'so the guard cannot tell which one the host will run and no key can be cleared. ' +
|
|
421
|
+
'Re-send it as one form, or write the change through `agent-config settings:set`.'
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
// A file that does not exist yet is created by an edit with an empty
|
|
425
|
+
// `old_string`, so it is modelled as empty text rather than left unchecked.
|
|
426
|
+
const current = on_disk ?? '';
|
|
400
427
|
let afterText: string | null = null;
|
|
401
428
|
if (typeof content === 'string') {
|
|
402
429
|
afterText = content;
|
|
403
|
-
} else if (typeof oldStr === 'string' && typeof newStr === 'string'
|
|
404
|
-
if (!
|
|
430
|
+
} else if (typeof oldStr === 'string' && typeof newStr === 'string') {
|
|
431
|
+
if (!current.includes(oldStr)) return null; // the edit will not apply
|
|
405
432
|
// `replace_all` is the host's own flag and it changes WHICH text the
|
|
406
433
|
// edit produces. Modelling only the first occurrence let a
|
|
407
434
|
// `replace_all` edit whose SECOND occurrence is the Class C one pass
|
|
@@ -417,7 +444,23 @@ export function classCVerdict(
|
|
|
417
444
|
'`agent-config settings:set`.'
|
|
418
445
|
);
|
|
419
446
|
}
|
|
420
|
-
afterText =
|
|
447
|
+
afterText = _applyEdit(current, oldStr, newStr, all);
|
|
448
|
+
} else if (ti['edits'] !== undefined && !Array.isArray(ti['edits'])) {
|
|
449
|
+
return `${rel_path}: this MultiEdit carries an edit the guard cannot interpret, so the text it would produce is unknown and no key can be cleared. Re-send it as plain edits, or write the change through \`agent-config settings:set\`.`;
|
|
450
|
+
} else if (Array.isArray(ti['edits'])) {
|
|
451
|
+
// MultiEdit applies its pairs in order and applies none when one misses.
|
|
452
|
+
let text = current;
|
|
453
|
+
for (const e of ti['edits']) {
|
|
454
|
+
const o = _isObject(e) ? e['old_string'] : undefined;
|
|
455
|
+
const n = _isObject(e) ? e['new_string'] : undefined;
|
|
456
|
+
const a = _isObject(e) ? e['replace_all'] : undefined;
|
|
457
|
+
if (typeof o !== 'string' || typeof n !== 'string' || (a !== undefined && typeof a !== 'boolean')) {
|
|
458
|
+
return `${rel_path}: this MultiEdit carries an edit the guard cannot interpret, so the text it would produce is unknown and no key can be cleared. Re-send it as plain edits, or write the change through \`agent-config settings:set\`.`;
|
|
459
|
+
}
|
|
460
|
+
if (!text.includes(o)) return null;
|
|
461
|
+
text = _applyEdit(text, o, n, a);
|
|
462
|
+
}
|
|
463
|
+
afterText = text;
|
|
421
464
|
}
|
|
422
465
|
if (afterText === null) return null;
|
|
423
466
|
|
|
@@ -5,10 +5,14 @@
|
|
|
5
5
|
* road-to-a-kernel-that-guards-its-plumbing 1.2 — the other half of a
|
|
6
6
|
* deliberate split, and the split is the whole design:
|
|
7
7
|
*
|
|
8
|
-
* · plumbing SOURCES
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* · plumbing SOURCES are edited legitimately all the time. They carry a
|
|
9
|
+
* RECORD — the ADR-268 § 4 ratification gate — not a deny. Which files
|
|
10
|
+
* count is NOT listed here: it is `check_kernel_edit_ratified`'s
|
|
11
|
+
* `PLUMBING_SOURCE_RE` plus the verdict-deciding modules of the
|
|
12
|
+
* dispatcher's import closure (`derivedPlumbing`), computed at run time.
|
|
13
|
+
* A copy of that list here drifted once already — it named the pattern
|
|
14
|
+
* and missed the policy module a refactor moved out of the dispatcher —
|
|
15
|
+
* so this header points at the set instead of restating it.
|
|
12
16
|
* · plumbing BUILD OUTPUTS have no legitimate hand edit at all. They carry a
|
|
13
17
|
* DENY, which is this file.
|
|
14
18
|
*
|
|
@@ -149,11 +149,26 @@ function isGlobOverAcceptableInboxDir(name: string): boolean {
|
|
|
149
149
|
if (!/[*?[\]]/.test(name)) {
|
|
150
150
|
return false;
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
// Only a generic class is stripped. Any other bracket payload stays in the
|
|
153
|
+
// literal and is judged: `[acme]` names a source, and so does a run of
|
|
154
|
+
// singleton ranges like `[a-a][c-c]`.
|
|
155
|
+
const literal = name.replace(/[*?]|\[(?:a-z|0-9|a-f|0-9a-f|a-z0-9)\]/gi, '');
|
|
156
|
+
if (OPAQUE_FAMILY_WILDCARD_RE.test(name)) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
153
159
|
const trimmed = literal.replace(/-+$/, '');
|
|
154
160
|
return trimmed !== '' && isAcceptableInboxDir(trimmed);
|
|
155
161
|
}
|
|
156
162
|
|
|
163
|
+
/**
|
|
164
|
+
* The fixed head of an opaque identifier family followed by wildcards only.
|
|
165
|
+
* `round-*` lists hex rounds; as a literal it would create `round-*`, which
|
|
166
|
+
* carries no source. Brackets are excluded because their payload survives as
|
|
167
|
+
* literal text: `round-[acme]-*` must not pass by stripping to `round`.
|
|
168
|
+
*/
|
|
169
|
+
const OPAQUE_FAMILY_WILDCARD_RE =
|
|
170
|
+
/^(?:(?:inbox|round|src-set|source-set)(?:-\d{4}(?:-\d{2})?)?|set)-[*?]+$/i;
|
|
171
|
+
|
|
157
172
|
/**
|
|
158
173
|
* The paths a redirect inside one segment would create.
|
|
159
174
|
*
|
|
@@ -65,6 +65,7 @@ import { main as suggestionCaptureMain } from './suggestion_capture_hook.js';
|
|
|
65
65
|
import { main as uiRouteNudgeMain } from './ui_route_nudge_hook.js';
|
|
66
66
|
import { main as orchestrationRecordMain } from './orchestration_record_hook.js';
|
|
67
67
|
import { main as telemetryUsageMain } from './telemetry_usage_hook.js';
|
|
68
|
+
import { main as mcpUsageObservationMain } from './mcp_usage_observation_hook.js';
|
|
68
69
|
import { main as telemetryFlushMain } from './telemetry_flush_hook.js';
|
|
69
70
|
import { main as delegationNudgeMain } from './delegation_nudge_hook.js';
|
|
70
71
|
import { main as skillRouteMain } from './skill_route_hook.js';
|
|
@@ -132,6 +133,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
|
|
|
132
133
|
'src/scripts/hooks/ui_route_nudge_hook.ts': uiRouteNudgeMain as ConcernMain,
|
|
133
134
|
'src/scripts/hooks/orchestration_record_hook.ts': orchestrationRecordMain as ConcernMain,
|
|
134
135
|
'src/scripts/hooks/telemetry_usage_hook.ts': telemetryUsageMain as ConcernMain,
|
|
136
|
+
'src/scripts/hooks/mcp_usage_observation_hook.ts': mcpUsageObservationMain as ConcernMain,
|
|
135
137
|
'src/scripts/hooks/telemetry_flush_hook.ts': telemetryFlushMain as ConcernMain,
|
|
136
138
|
'src/scripts/hooks/delegation_nudge_hook.ts': delegationNudgeMain as ConcernMain,
|
|
137
139
|
'src/scripts/hooks/skill_route_hook.ts': skillRouteMain as ConcernMain,
|
|
@@ -320,11 +320,10 @@ export function resolveActivation(
|
|
|
320
320
|
const emergency = (settings["emergency"] ?? {}) as Record<string, unknown>;
|
|
321
321
|
const halted = emergency["orchestration_halt"] === true;
|
|
322
322
|
const host_manifest = probeHostCapabilities(hostId);
|
|
323
|
-
const sub = (settings["subagents"] ?? {}) as Record<string, unknown>;
|
|
324
|
-
const downshift = sub["downshift"] !== false;
|
|
325
323
|
return {
|
|
326
324
|
activation: { halted, subagent_spawn: host_manifest.subagent_spawn },
|
|
327
|
-
downshift
|
|
325
|
+
// Fixed on: the `subagents.downshift` key was retired with this default.
|
|
326
|
+
downshift: true,
|
|
328
327
|
separate_quota_pool: host_manifest.separate_quota_pool,
|
|
329
328
|
agentTeams: host_manifest.agent_teams,
|
|
330
329
|
};
|
|
@@ -48,6 +48,37 @@
|
|
|
48
48
|
* reason instead of passing silently. `src/rules/design-review-after-ui-write.md`
|
|
49
49
|
* already required that in prose with nothing to read it; this emits it.
|
|
50
50
|
*
|
|
51
|
+
* SVG ROUTING, AND HOW TO REVERT IT. Step 1.3 of
|
|
52
|
+
* `road-to-svg-rules-in-the-dispatch-path`. An `.svg` write reaches
|
|
53
|
+
* `lint_svg_asset`'s rules from here, inside or outside a UI tree, through
|
|
54
|
+
* `svg_rules_loader` — a CJS chunk beside the dispatch bundle, required only
|
|
55
|
+
* for a path ending in `.svg`. The review that withdrew the first attempt
|
|
56
|
+
* named the gap plainly: a statically bundled rule set has no off switch, so
|
|
57
|
+
* the triggers and the mechanism are written down before they are needed.
|
|
58
|
+
*
|
|
59
|
+
* REVERT WHEN any of these is read:
|
|
60
|
+
* · the composition gate exceeds its ceiling attributable to this routing
|
|
61
|
+
* (`check_hook_bundle_composition`; measured 2,128 B on 2026-10-11, with
|
|
62
|
+
* 16,910 B of headroom left);
|
|
63
|
+
* · a non-`.svg` hook event is observed failing with a stack that passes
|
|
64
|
+
* through the chunk — the containment case
|
|
65
|
+
* `design_pass_svg.test.ts > rule-failure-does-not-reach-an-unrelated-event`
|
|
66
|
+
* exists to make impossible, so one observation is enough;
|
|
67
|
+
* · an operator reports SVG false positives on files they accept, at a rate
|
|
68
|
+
* that would make them switch the carrier off — Risk 1 of the parent
|
|
69
|
+
* roadmap, and the failure this whole concern is shaped around.
|
|
70
|
+
*
|
|
71
|
+
* THE MECHANISM, in increasing order of blast radius:
|
|
72
|
+
* 1. Delete `dist/hooks/svg_rules.chunk.cjs`. The loader returns `null`,
|
|
73
|
+
* the pass reports `verification: degraded` naming the missing file,
|
|
74
|
+
* and every other finding family is unaffected. This is the per-install
|
|
75
|
+
* off switch the static import could not have had.
|
|
76
|
+
* 2. Drop `isSvgAsset` from `isPassSurface` below. An `.svg` outside a UI
|
|
77
|
+
* tree stops reaching the pass at all; one inside it reads as it did
|
|
78
|
+
* before this step.
|
|
79
|
+
* 3. Turn the concern off entirely (`hooks.design_pass.enabled: false`),
|
|
80
|
+
* which was already the default.
|
|
81
|
+
*
|
|
51
82
|
* Default-OFF (`hooks.design_pass.enabled`), fail_closed: false.
|
|
52
83
|
*
|
|
53
84
|
* Exit codes (dispatcher contract): 0 allow · 1 block · 2 warn + JSON reason.
|
|
@@ -62,6 +93,7 @@ import { trigger_matches, type Trigger } from '../_lib/router_match.js';
|
|
|
62
93
|
import { isUiPath, isUiTreePath } from '../_lib/ui_surface.js';
|
|
63
94
|
import { loadDesignContext, scanFile } from '../lint_design_slop.js';
|
|
64
95
|
import { readHookStdin } from './hook_stdin.js';
|
|
96
|
+
import { CHUNK_BASENAME, loadSvgScan } from './svg_rules_loader.js';
|
|
65
97
|
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
66
98
|
|
|
67
99
|
const SETTINGS_FILE = '.agent-settings.yml';
|
|
@@ -129,8 +161,42 @@ export function enabled(root: string, key = 'design_pass'): boolean {
|
|
|
129
161
|
return false;
|
|
130
162
|
}
|
|
131
163
|
|
|
164
|
+
/**
|
|
165
|
+
* True for a path this pass should look at.
|
|
166
|
+
*
|
|
167
|
+
* `.svg` is admitted HERE and nowhere else — step 1.2 of
|
|
168
|
+
* `road-to-svg-rules-in-the-dispatch-path`. The obvious way to reach an `.svg`
|
|
169
|
+
* from this pass was to add `svg` to `UI_EXTENSIONS`, and that is the thing the
|
|
170
|
+
* parent roadmap's decision E10 and `design_pass_svg.test.ts` forbid: the same
|
|
171
|
+
* predicate backs `ui_route_nudge_hook`'s `isUiWrite`, so widening it would
|
|
172
|
+
* draw a UI routing nudge and its tokens on every icon dropped into `public/`.
|
|
173
|
+
* A local disjunct reaches the asset without touching the shared predicate, in
|
|
174
|
+
* either direction.
|
|
175
|
+
*/
|
|
176
|
+
export const isSvgAsset = (p: string): boolean => /\.svg$/i.test(p);
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* UNCHANGED, and that is the point of the predicate below it.
|
|
180
|
+
*
|
|
181
|
+
* Finding 6 of this change's own completion review: widening THIS predicate to
|
|
182
|
+
* admit every `.svg` would have moved the UI-turn denominator the
|
|
183
|
+
* consultation-rate measurement is defined against — which the
|
|
184
|
+
* `HANDOVER_TRIGGERS` note further down reserves, in writing, as a different
|
|
185
|
+
* decision than any routing change. It was widened and is widened no longer.
|
|
186
|
+
*/
|
|
132
187
|
export const isUiSurface = (p: string): boolean => isUiPath(p) || isUiTreePath(p);
|
|
133
188
|
|
|
189
|
+
/**
|
|
190
|
+
* What this PASS looks at — a UI surface, or any `.svg`.
|
|
191
|
+
*
|
|
192
|
+
* The routing step 1.2 of `road-to-svg-rules-in-the-dispatch-path` asked for,
|
|
193
|
+
* in the one place it belongs: the pass's own entry gate. Keeping it out of
|
|
194
|
+
* `isUiSurface` leaves every other reading that predicate feeds — the
|
|
195
|
+
* conformance verdict's noteworthy test, the denominator above — reading
|
|
196
|
+
* exactly what it read before.
|
|
197
|
+
*/
|
|
198
|
+
export const isPassSurface = (p: string): boolean => isUiSurface(p) || isSvgAsset(p);
|
|
199
|
+
|
|
134
200
|
/**
|
|
135
201
|
* The shadow read of `ui-conformance.json` — Phase 5 of
|
|
136
202
|
* `road-to-behaviour-evidence-over-pixels`.
|
|
@@ -441,6 +507,53 @@ function renderAvailable(root: string): boolean {
|
|
|
441
507
|
}
|
|
442
508
|
}
|
|
443
509
|
|
|
510
|
+
/**
|
|
511
|
+
* SVG severity → this pass's severity.
|
|
512
|
+
*
|
|
513
|
+
* `error` and `warning` become P1 and P2; `inert` is dropped. Deliberately NOT
|
|
514
|
+
* P0: the P0 set above is a closed list of objective floors and it is the only
|
|
515
|
+
* thing that computes a block at stop. Routing a new rule family into it would
|
|
516
|
+
* change the block surface, which is a different decision than making the
|
|
517
|
+
* findings visible — and the one Risk 1 of the parent roadmap warns about.
|
|
518
|
+
*/
|
|
519
|
+
export function svgSeverity(s: 'error' | 'warning' | 'inert'): Finding['severity'] | null {
|
|
520
|
+
if (s === 'error') return 'P1';
|
|
521
|
+
if (s === 'warning') return 'P2';
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export interface SvgRuleFinding {
|
|
526
|
+
rule: string;
|
|
527
|
+
file: string;
|
|
528
|
+
line: number;
|
|
529
|
+
snippet: string;
|
|
530
|
+
severity: 'error' | 'warning' | 'inert';
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Map the SVG rule set's findings onto this pass's shape.
|
|
535
|
+
*
|
|
536
|
+
* Pure, and exported, so the routing can be proven without building a bundle:
|
|
537
|
+
* the half that is expensive to exercise end-to-end is the chunk load, and that
|
|
538
|
+
* has its own test in `svg_rules_loader`.
|
|
539
|
+
*/
|
|
540
|
+
export function svgFindings(raw: readonly SvgRuleFinding[], rel: string): Finding[] {
|
|
541
|
+
const out: Finding[] = [];
|
|
542
|
+
for (const f of raw) {
|
|
543
|
+
const severity = svgSeverity(f.severity);
|
|
544
|
+
if (severity === null) continue;
|
|
545
|
+
out.push({
|
|
546
|
+
file: rel,
|
|
547
|
+
severity,
|
|
548
|
+
catalogId: 'SVG',
|
|
549
|
+
rule: f.rule,
|
|
550
|
+
line: f.line,
|
|
551
|
+
message: `${f.rule}${f.snippet ? ` — ${f.snippet}` : ''}`,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
return out;
|
|
555
|
+
}
|
|
556
|
+
|
|
444
557
|
/** Extracts the written path from a tool payload, whichever key the host uses. */
|
|
445
558
|
export function targetPath(payload: unknown): string | null {
|
|
446
559
|
if (typeof payload !== 'object' || payload === null) return null;
|
|
@@ -499,7 +612,7 @@ function main(): number {
|
|
|
499
612
|
targets = state.touched;
|
|
500
613
|
} else {
|
|
501
614
|
const t = targetPath(payload);
|
|
502
|
-
if (!t || !
|
|
615
|
+
if (!t || !isPassSurface(t)) return EXIT_ALLOW;
|
|
503
616
|
targets = [t];
|
|
504
617
|
if (!state.touched.includes(t)) state.touched.push(t);
|
|
505
618
|
}
|
|
@@ -508,6 +621,7 @@ function main(): number {
|
|
|
508
621
|
// Findings come from the shipped registry, via the same entrypoint CI uses.
|
|
509
622
|
const findings: Finding[] = [];
|
|
510
623
|
let scanFailed: string | null = null;
|
|
624
|
+
let svgRulesUnavailable = false;
|
|
511
625
|
try {
|
|
512
626
|
const ctx = loadDesignContext(root);
|
|
513
627
|
for (const rel of targets) {
|
|
@@ -517,6 +631,17 @@ function main(): number {
|
|
|
517
631
|
// itself rather than handing over a path, which is also what lets a
|
|
518
632
|
// post-write pass see the bytes that were just written.
|
|
519
633
|
const content = fs.readFileSync(abs, 'utf-8');
|
|
634
|
+
if (isSvgAsset(rel)) {
|
|
635
|
+
// The conditional chunk. Loaded only here, so a hook event that
|
|
636
|
+
// never touched an `.svg` pays none of its bytes and runs none
|
|
637
|
+
// of its code — the containment `design_pass_svg.test.ts` pins.
|
|
638
|
+
// A null load is reported through `svgRulesUnavailable`, never
|
|
639
|
+
// thrown: a consumer whose install is missing the chunk must
|
|
640
|
+
// lose the SVG findings, not the whole dispatch.
|
|
641
|
+
const scan = loadSvgScan();
|
|
642
|
+
if (scan === null) svgRulesUnavailable = true;
|
|
643
|
+
else findings.push(...svgFindings(scan(content, rel) as SvgRuleFinding[], rel));
|
|
644
|
+
}
|
|
520
645
|
for (const f of scanFile(content, rel, ctx)) {
|
|
521
646
|
findings.push({
|
|
522
647
|
file: rel,
|
|
@@ -532,11 +657,40 @@ function main(): number {
|
|
|
532
657
|
scanFailed = String(err);
|
|
533
658
|
}
|
|
534
659
|
|
|
535
|
-
|
|
536
|
-
|
|
660
|
+
// The audit question is asked of UI SURFACES, never of the pass surface.
|
|
661
|
+
// Findings 1 and 2 of the third completion review, both reproduced by
|
|
662
|
+
// running the hook: round one split the entry gate from the UI predicate,
|
|
663
|
+
// and `targets` carried the `.svg` past the split anyway. So a clean
|
|
664
|
+
// conformant icon write exited WARN with "no ui-audit.json newer than
|
|
665
|
+
// public/icon.svg" — an asset has no component inventory to be audited
|
|
666
|
+
// against — and, worse, `recordAuditDischarge` returns early on a non-empty
|
|
667
|
+
// `auditMissing`, so writing ONE `.svg` in a turn silently suppressed the
|
|
668
|
+
// ui-audit discharge row for every real UI file in that same turn.
|
|
669
|
+
const auditTargets = targets.filter((t) => isUiSurface(t));
|
|
670
|
+
const auditMissing = auditTargets.filter((t) => !auditIsFresh(root, t));
|
|
671
|
+
recordAuditDischarge(root, auditTargets, auditMissing);
|
|
537
672
|
let result = decide(slot, findings, auditMissing, new Set(state.surfaced), renderAvailable(root));
|
|
538
673
|
if (scanFailed) {
|
|
539
674
|
result = { ...result, verification: 'unverified', degradation_reason: `detector unavailable: ${scanFailed}` };
|
|
675
|
+
} else if (svgRulesUnavailable) {
|
|
676
|
+
// Degraded, not unverified: the rest of the pass ran. An absent chunk
|
|
677
|
+
// is reported rather than silently producing a clean SVG verdict —
|
|
678
|
+
// "absent is not clean" is the same rule the conformance verdict keeps.
|
|
679
|
+
// APPENDED, never overwritten. Finding 6 of the fourth completion
|
|
680
|
+
// review: `decide` may already have set a reason — the renderer being
|
|
681
|
+
// absent is the one it sets — and assigning here threw it away, so a
|
|
682
|
+
// turn where both degradations held reported only the newer one. Two
|
|
683
|
+
// degradations are two facts; the operator needs both or they fix one
|
|
684
|
+
// and are surprised by the other.
|
|
685
|
+
const svgReason = `the SVG rule set could not be loaded (expected dist/hooks/${CHUNK_BASENAME} beside the dispatch bundle) — the .svg files in this turn were not checked`;
|
|
686
|
+
result = {
|
|
687
|
+
...result,
|
|
688
|
+
verification: 'degraded',
|
|
689
|
+
degradation_reason:
|
|
690
|
+
result.degradation_reason === undefined || result.degradation_reason === ''
|
|
691
|
+
? svgReason
|
|
692
|
+
: `${result.degradation_reason}; ${svgReason}`,
|
|
693
|
+
};
|
|
540
694
|
}
|
|
541
695
|
|
|
542
696
|
for (const f of result.findings) state.surfaced.push(`${f.file}::${f.rule}::${f.line}`);
|
|
@@ -53,6 +53,7 @@ import { atomic_write_json } from "./state_io.js";
|
|
|
53
53
|
import { readHookStdin } from "./hook_stdin.js";
|
|
54
54
|
import { isCodePath, isTestPath } from "../_lib/test_delta.js";
|
|
55
55
|
import { EXIT_ALLOW, EXIT_BLOCK } from './exit_codes.js';
|
|
56
|
+
import { ledgerFileFor } from "../git_authorization_hook.js";
|
|
56
57
|
|
|
57
58
|
// MUST equal dispatch_hook.EXIT_BLOCK. The dispatcher's internal ladder is
|
|
58
59
|
// 0 allow / 1 block / 2 warn — NOT the 2-means-block shape a PreToolUse guard
|
|
@@ -198,11 +199,18 @@ interface DispatchState extends JsonObject {
|
|
|
198
199
|
evaluations: JsonValue[];
|
|
199
200
|
}
|
|
200
201
|
|
|
201
|
-
/**
|
|
202
|
-
|
|
202
|
+
/**
|
|
203
|
+
* The current user turn's stamp, or "" when no ledger exists yet.
|
|
204
|
+
*
|
|
205
|
+
* Reads the ledger through the writer's own `ledgerFileFor(session_id)`
|
|
206
|
+
* rather than the legacy session-less path: with a session id the writer
|
|
207
|
+
* never touches that path, so reading it unconditionally found an empty or
|
|
208
|
+
* stale file and the stamp never changed per turn.
|
|
209
|
+
*/
|
|
210
|
+
function _ledgerStamp(consumer_root: string, session_id: string): string {
|
|
203
211
|
try {
|
|
204
212
|
const raw = fs.readFileSync(
|
|
205
|
-
path.join(consumer_root,
|
|
213
|
+
path.join(consumer_root, ledgerFileFor(session_id)),
|
|
206
214
|
"utf8",
|
|
207
215
|
);
|
|
208
216
|
const d = JSON.parse(raw) as Record<string, unknown>;
|
|
@@ -421,7 +429,7 @@ export function run(stdin_text: string, options: { consumer_root: string }): num
|
|
|
421
429
|
// in a session blocked every later one. The only per-user-turn stamp that
|
|
422
430
|
// actually exists is `detected_at` in the authorization ledger, which
|
|
423
431
|
// `git_authorization_hook` rewrites on every `user_prompt_submit`.
|
|
424
|
-
const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root)}`;
|
|
432
|
+
const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root, session_id)}`;
|
|
425
433
|
if (state.session_id !== turnMarker) {
|
|
426
434
|
state.session_id = turnMarker;
|
|
427
435
|
state.turn_started_at = new Date().toISOString();
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Foreign MCP tool names, observed on `post_tool_use`
|
|
4
|
+
* (road-to-neighbours-that-pull-their-weight step 3.3, decision D12).
|
|
5
|
+
*
|
|
6
|
+
* DEFAULT-ON LOCAL OBSERVATION, AND IT BYPASSES THE TELEMETRY OPT-IN. Stated
|
|
7
|
+
* here first because it is the one property a reader must not have to infer.
|
|
8
|
+
* This concern writes on every install, whether or not the org telemetry switch
|
|
9
|
+
* was ever enabled, because the file it writes feeds `doctor neighbours` — a
|
|
10
|
+
* report the consumer runs on their own tree — and gating it on an org switch
|
|
11
|
+
* would publish `0` on every install that never enabled one. Nothing here is
|
|
12
|
+
* telemetry: no transport reads the file, it is never spooled, and it lives
|
|
13
|
+
* under gitignored `agents/runtime/` (decision D9).
|
|
14
|
+
*
|
|
15
|
+
* WHAT IS RECORDED: the tool NAME, `mcp__<server>__<tool>`, and the UTC day it
|
|
16
|
+
* was last seen. Nothing else — no arguments, no response, no session id, no
|
|
17
|
+
* host. The dispatcher serves this concern a REDUCED payload: its manifest
|
|
18
|
+
* entry declares no `needs_payload_bodies`, so `tool_input` and `tool_response`
|
|
19
|
+
* arrive as size-only stubs and cannot be recorded even by mistake.
|
|
20
|
+
*
|
|
21
|
+
* RETENTION. A map keyed by tool name, rewritten in place at most once per day
|
|
22
|
+
* per name — bounded by the neighbour's tool surface, so it needs no TTL job.
|
|
23
|
+
* The reader applies a 30-day window; older entries stop counting. Deleting
|
|
24
|
+
* `agents/runtime/neighbour-tool-use.json` erases all of it.
|
|
25
|
+
*
|
|
26
|
+
* Why a concern of its own rather than a branch of `telemetry-usage`: that
|
|
27
|
+
* concern's dispatcher filter is `tools: [Skill]` and matches exactly, so a
|
|
28
|
+
* branch there was never called for an MCP tool; and a concern named for
|
|
29
|
+
* opt-in telemetry should not also carry default-on local collection. Both
|
|
30
|
+
* were the AI council's findings (2026-10-02); the owner chose this shape.
|
|
31
|
+
*
|
|
32
|
+
* No `tools:` filter on the manifest entry, deliberately: MCP tool names are
|
|
33
|
+
* not enumerable and matching is exact. The prefix test below is the filter.
|
|
34
|
+
*
|
|
35
|
+
* Exit code is ALWAYS 0 and nothing is printed — it observes, never gates.
|
|
36
|
+
*/
|
|
37
|
+
import * as path from 'node:path';
|
|
38
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
39
|
+
import * as fs from 'node:fs';
|
|
40
|
+
|
|
41
|
+
import { FOREIGN_TOOL_USE_REL, MCP_TOOL_PREFIX, resolveStoreRoot, usageDay } from '../_lib/neighbour_tool_use.js';
|
|
42
|
+
import { update_json_under_lock } from './state_io.js';
|
|
43
|
+
import { readHookStdin } from './hook_stdin.js';
|
|
44
|
+
import { EXIT_ALLOW } from './exit_codes.js';
|
|
45
|
+
|
|
46
|
+
type JsonObject = { [k: string]: unknown };
|
|
47
|
+
|
|
48
|
+
function isObject(v: unknown): v is JsonObject {
|
|
49
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** The MCP tool name off the envelope, or null for anything else. */
|
|
53
|
+
export function mcpToolName(envelope: unknown): string | null {
|
|
54
|
+
if (!isObject(envelope)) return null;
|
|
55
|
+
const payload = isObject(envelope['payload']) ? envelope['payload'] : envelope;
|
|
56
|
+
const v = payload['tool_name'] ?? payload['toolName'] ?? payload['tool'];
|
|
57
|
+
return typeof v === 'string' && v.startsWith(MCP_TOOL_PREFIX) && v.length > MCP_TOOL_PREFIX.length ? v : null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function record(envelope: unknown, consumer_root: string): number {
|
|
61
|
+
try {
|
|
62
|
+
const tool = mcpToolName(envelope);
|
|
63
|
+
if (tool === null) return EXIT_ALLOW;
|
|
64
|
+
const day = usageDay(new Date());
|
|
65
|
+
update_json_under_lock<Record<string, string>>(
|
|
66
|
+
path.join(resolveStoreRoot(consumer_root), FOREIGN_TOOL_USE_REL),
|
|
67
|
+
(seen) => (seen[tool] === day ? null : ({ ...seen, [tool]: day } as Record<string, string>)),
|
|
68
|
+
{ blocking: false },
|
|
69
|
+
);
|
|
70
|
+
} catch {
|
|
71
|
+
return EXIT_ALLOW;
|
|
72
|
+
}
|
|
73
|
+
return EXIT_ALLOW;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function run(stdin_text: string, options: { consumer_root: string }): number {
|
|
77
|
+
let envelope: unknown;
|
|
78
|
+
try {
|
|
79
|
+
const raw = stdin_text.trim();
|
|
80
|
+
if (!raw) return EXIT_ALLOW;
|
|
81
|
+
envelope = JSON.parse(raw);
|
|
82
|
+
} catch {
|
|
83
|
+
return EXIT_ALLOW;
|
|
84
|
+
}
|
|
85
|
+
return record(envelope, options.consumer_root);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function _root(envelope: unknown): string {
|
|
89
|
+
if (isObject(envelope)) {
|
|
90
|
+
const v = envelope['cwd'] ?? envelope['workspace_root'] ?? envelope['project_root'];
|
|
91
|
+
if (typeof v === 'string' && v) return v;
|
|
92
|
+
}
|
|
93
|
+
return process.cwd();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function main(): number {
|
|
97
|
+
const raw = readHookStdin();
|
|
98
|
+
let envelope: unknown = {};
|
|
99
|
+
try {
|
|
100
|
+
envelope = raw.trim() ? JSON.parse(raw) : {};
|
|
101
|
+
} catch {
|
|
102
|
+
return EXIT_ALLOW;
|
|
103
|
+
}
|
|
104
|
+
return record(envelope, _root(envelope));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Bundle-safety: guarded at the call site so esbuild drops the whole entry
|
|
108
|
+
// check inside the shared hook bundle (see telemetry_usage_hook.ts, D11).
|
|
109
|
+
declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
|
|
110
|
+
function _isCliEntry(): boolean {
|
|
111
|
+
if (process.argv[1] === undefined) return false;
|
|
112
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) return true;
|
|
113
|
+
try {
|
|
114
|
+
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (typeof __AGENT_CONFIG_BUNDLE__ === 'undefined' || !__AGENT_CONFIG_BUNDLE__) {
|
|
120
|
+
if (_isCliEntry()) process.exit(main());
|
|
121
|
+
}
|
|
@@ -195,9 +195,10 @@ export function buildReminder(branch: string, pr: number | null): { reason: stri
|
|
|
195
195
|
` 2. Red? Read only the failing part:\n` +
|
|
196
196
|
` gh run view --job <id> --log-failed | grep -E '×|FAIL|Error'\n` +
|
|
197
197
|
` then fix it and push again (fix-what-you-see: the author is irrelevant).\n` +
|
|
198
|
-
` 3.
|
|
199
|
-
`
|
|
200
|
-
`
|
|
198
|
+
` 3. 3 attempts on the same target triggers autonomous-execution's ` +
|
|
199
|
+
`execution.fix_loop_max strategy shift — change approach, never stop. ` +
|
|
200
|
+
`Blocked on something only the user can decide is the one branch that halts: ` +
|
|
201
|
+
`say so, with what was tried named.\n\n` +
|
|
201
202
|
`Handing the user a red PR with its cause named and unfixed is not a delivery ` +
|
|
202
203
|
`either. If you are deliberately leaving this WIP, say that in the reply — ` +
|
|
203
204
|
`silence is what this hook exists to stop.`;
|
|
@@ -147,7 +147,11 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
147
147
|
|
|
148
148
|
import { hookSectionEnabled } from '../_lib/hook_settings.js';
|
|
149
149
|
import * as user_global_paths from '../_lib/user_global_paths.js';
|
|
150
|
-
import {
|
|
150
|
+
import {
|
|
151
|
+
deliversBodies,
|
|
152
|
+
installerThinsHost,
|
|
153
|
+
resolveLeanProjection,
|
|
154
|
+
} from '../_lib/lean_projection_mode.js';
|
|
151
155
|
import { enforcement_class_from_frontmatter } from '../_lib/obligation_frequency.js';
|
|
152
156
|
import {
|
|
153
157
|
appendDelivered,
|
|
@@ -168,7 +172,8 @@ import {
|
|
|
168
172
|
} from '../_lib/rule_injection.js';
|
|
169
173
|
import { readConsequenceClass, stubLawIds } from '../_lib/rule_consequence_class.js';
|
|
170
174
|
import { lawText, ruleBody } from '../_lib/rule_law_section.js';
|
|
171
|
-
import { hostRuleLayerIds } from '../_lib/rule_layer_overlap.js';
|
|
175
|
+
import { hostRuleLayerDirs, hostRuleLayerIds } from '../_lib/rule_layer_overlap.js';
|
|
176
|
+
import { is_thin_entry } from '../_lib/thin_rules.js';
|
|
172
177
|
import { readHookStdin } from './hook_stdin.js';
|
|
173
178
|
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
174
179
|
|
|
@@ -853,6 +858,9 @@ export function buildInjection(
|
|
|
853
858
|
openFiles: string[] | null,
|
|
854
859
|
command: string | null,
|
|
855
860
|
seen: Set<string>,
|
|
861
|
+
// `false` only for an offline measurement of WHAT the concern delivers,
|
|
862
|
+
// which must not read the measuring machine's installed rule files.
|
|
863
|
+
servedOnce = true,
|
|
856
864
|
): Injection | null {
|
|
857
865
|
let router;
|
|
858
866
|
try {
|
|
@@ -878,14 +886,47 @@ export function buildInjection(
|
|
|
878
886
|
// `hostRuleLayerIds`. No filter then, because scoping to an empty set would
|
|
879
887
|
// re-create the silence step 1.1 repaired.
|
|
880
888
|
const scope = hostRuleLayerIds(root);
|
|
881
|
-
|
|
889
|
+
let matches = matchTierRules(router, prompt, openFiles, command).filter(
|
|
882
890
|
(m) => !seen.has(m.id) && (scope === null || scope.has(m.id)),
|
|
883
891
|
);
|
|
884
892
|
if (matches.length === 0) return null;
|
|
893
|
+
// ONE COPY (`road-to-a-default-install-served-once` 1.1). The gate opens on
|
|
894
|
+
// the template's `delivery`, but the installer thins only on an explicit
|
|
895
|
+
// user-global choice, so a default install carries every routed body in
|
|
896
|
+
// its rule files already. A rule whose installed copy is a full body gets
|
|
897
|
+
// nothing; a stub still gets its body. Asked only off the consent path, so
|
|
898
|
+
// an opted-in install's delivery is unchanged byte for byte.
|
|
899
|
+
if (servedOnce && scope !== null && !installerThinsHost(DELIVERY_HOST, { packageRoot: ruleSources(root).pkg })) {
|
|
900
|
+
const full = installedFullIds(root, matches.map((m) => m.id));
|
|
901
|
+
matches = matches.filter((m) => !full.has(m.id));
|
|
902
|
+
if (matches.length === 0) return null;
|
|
903
|
+
}
|
|
885
904
|
const sel = selectForInjection(root, matches, CAP_BYTES);
|
|
886
905
|
return compose(root, sel, highConsequenceIds(root));
|
|
887
906
|
}
|
|
888
907
|
|
|
908
|
+
/**
|
|
909
|
+
* Ids among `ids` whose copy in EITHER host rule layer is a full body rather
|
|
910
|
+
* than a stub. Either, because the host loads both: one full copy is enough
|
|
911
|
+
* for the body to be standing in context already. Reads only matched ids,
|
|
912
|
+
* never the whole layer, because this runs on the per-prompt path.
|
|
913
|
+
*/
|
|
914
|
+
export function installedFullIds(root: string, ids: readonly string[]): Set<string> {
|
|
915
|
+
const out = new Set<string>();
|
|
916
|
+
for (const dir of hostRuleLayerDirs(root)) {
|
|
917
|
+
for (const id of ids) {
|
|
918
|
+
let text: string;
|
|
919
|
+
try {
|
|
920
|
+
text = fs.readFileSync(path.join(dir, `${id}.md`), 'utf-8');
|
|
921
|
+
} catch {
|
|
922
|
+
continue;
|
|
923
|
+
}
|
|
924
|
+
if (!is_thin_entry(text)) out.add(id);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return out;
|
|
928
|
+
}
|
|
929
|
+
|
|
889
930
|
// ── main ─────────────────────────────────────────────────────────────────
|
|
890
931
|
|
|
891
932
|
/**
|