@event4u/agent-config 16.2.0 → 16.4.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 +337 -234
- package/README.md +15 -13
- package/agents/templates/.ai-council.yml.example +26 -8
- package/dist/agent-src/commands/analyze/inbox.md +11 -8
- package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
- package/dist/agent-src/commands/bug/fix.md +17 -2
- 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/estimate-ticket.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +3 -3
- package/dist/agent-src/commands/feature/plan.md +2 -2
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +18 -4
- 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 +4 -4
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- 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/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/next.md +10 -1
- package/dist/agent-src/commands/roadmap/process-full.md +56 -42
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +411 -0
- package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
- package/dist/agent-src/commands/roadmap.md +18 -4
- package/dist/agent-src/commands/tests/create.md +17 -3
- package/dist/agent-src/commands/tests/execute.md +22 -5
- 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/authority/decision-revisit-gate-enforcement.md +43 -0
- package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
- 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 +7 -7
- 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 +99 -54
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- 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 +95 -7
- 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/php/git.md +15 -2
- package/dist/agent-src/rules/active-remediation.md +1 -2
- 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 +1 -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 +1 -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 +1 -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 +6 -6
- 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 +17 -35
- package/dist/agent-src/rules/delegation-policy.md +2 -3
- package/dist/agent-src/rules/design-fidelity.md +12 -16
- 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 +1 -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 +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/domain-safety-retention.md +1 -1
- package/dist/agent-src/rules/downstream-changes.md +0 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -1
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- 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 +2 -2
- package/dist/agent-src/rules/finance-safety-floor.md +1 -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 +2 -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 +1 -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 +3 -3
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -1
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -1
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/media-governance-routing.md +13 -17
- 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 +4 -5
- 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 +3 -4
- package/dist/agent-src/rules/question-not-instruction.md +1 -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 +4 -7
- 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 +1 -1
- package/dist/agent-src/rules/scale-discipline.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -3
- 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 +7 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +6 -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 +1 -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 +1 -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 +12 -46
- 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 +1 -1
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -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 +1 -1
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/dist/agent-src/scripts/deferral_carry.ts +339 -0
- package/dist/agent-src/scripts/gate_budget.ts +47 -23
- package/dist/agent-src/scripts/gate_execute.ts +12 -4
- package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
- 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/api-design/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -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-system-capture/SKILL.md +0 -3
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- 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 +1 -1
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
- package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
- package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
- package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +4 -2
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
- package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +2 -2
- 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/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/directives/ui/apply.ts +48 -6
- 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/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/registry.js +2 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +207 -120
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-5GPULQBE.js} +2797 -338
- package/dist/cli-delegate/{chunk-IGD6ERX6.js → chunk-6SRJTYJS.js} +42 -176
- package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- 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-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-AED2VQGM.js} +1245 -249
- package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
- package/dist/cli-delegate/chunk-F3QDG2GT.js +2569 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-G5VVIZRC.js} +3 -3
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-H76PHZBI.js} +149 -61
- package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-KXXWJTDO.js} +6 -11
- package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-MDPPKQCQ.js} +58 -9
- package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-MSUL5NYP.js} +5 -5
- package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
- package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
- package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-PWX7CKMD.js} +4 -4
- package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
- package/dist/cli-delegate/{chunk-7XGBX6ZH.js → chunk-T7XSJSUQ.js} +1144 -589
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- package/dist/cli-delegate/chunk-WQWXGIWB.js +1779 -0
- package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-XQTPXKFA.js} +1 -1
- package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
- package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
- package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
- 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 +1252 -249
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +19 -9
- package/dist/cli-delegate/cmd_doctor_neighbours.js +30 -0
- package/dist/cli-delegate/cmd_explain.js +45 -21
- package/dist/cli-delegate/cmd_export.js +13 -10
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_git_convention.js +1851 -0
- package/dist/cli-delegate/cmd_handoff.js +44 -22
- package/dist/cli-delegate/cmd_mcp_available.js +3 -2
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +5 -4
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +14 -11
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +10 -8
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +10 -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 +13 -10
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +14 -11
- package/dist/cli-delegate/cmd_uninstall.js +15 -12
- package/dist/cli-delegate/cmd_update.js +7 -7
- package/dist/cli-delegate/cmd_upgrade.js +9 -8
- package/dist/cli-delegate/cmd_validate.js +15 -12
- package/dist/cli-delegate/cmd_versions.js +5 -5
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_budget.js +1 -1
- package/dist/cli-delegate/gate_execute.js +3 -3
- package/dist/cli-delegate/roadmap_gates.js +6 -6
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +232 -141
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +26 -9
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +7 -4
- package/dist/hooks/dispatch.js +5655 -6623
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/install/claudePathsPlan.js +47 -6
- package/dist/install/claudeRuleRewrite.js +7 -0
- package/dist/install/emit_host_rules_cli.js +39 -36
- package/dist/install/globalRuleScope.js +87 -0
- package/dist/install/host_rule_ownership.js +160 -0
- package/dist/install/install.mjs +2336 -1249
- package/dist/install/installThinLayer.js +289 -0
- package/dist/install/installedRuleLinks.js +262 -0
- package/dist/install/wizard-plan.js +24 -0
- 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 +36504 -30986
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +26 -120
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- 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 +704 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- package/dist/scripts/_lib/package_root.js +68 -0
- package/dist/scripts/_lib/rule_consequence_class.js +45 -0
- package/dist/scripts/_lib/rule_injection.js +67 -10
- package/dist/scripts/_lib/rule_law_section.js +122 -0
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/thin_rules.js +535 -0
- package/dist/scripts/_lib/windsurf_render.js +60 -0
- package/dist/scripts/condense.js +14 -26
- package/dist/scripts/project_thin_rules.js +14 -294
- 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 +29 -81
- package/dist/shared/skillRanking.js +103 -16
- 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 +39 -67
- 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/php/git.md +15 -2
- package/package.json +1 -1
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/src/agent-src/scripts/deferral_carry.ts +339 -0
- package/src/agent-src/scripts/gate_budget.ts +47 -23
- package/src/agent-src/scripts/gate_execute.ts +12 -4
- package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
- 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/directives/ui/apply.ts +48 -6
- 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/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/config/agent-settings.template.yml +141 -334
- 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 +10 -3
- package/src/config/discovery/packs.yml +17 -1
- package/src/config/evaluator-budgets.json +23 -10
- package/src/config/gate-coverage.yml +138 -3
- package/src/config/gate-violation-baselines.json +64 -16
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-token-budget.json +6 -1
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/release-gate-locality.yml +2 -1
- package/src/config/routing-coverage-seed.json +67 -4
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-consequence-class.json +161 -0
- package/src/config/rule-law-ceilings.json +105 -0
- package/src/config/rule-obligations.json +833 -0
- package/src/install/claudePathsPlan.ts +46 -4
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/emit_host_rules_cli.ts +43 -34
- package/src/install/globalRuleScope.ts +109 -0
- package/src/install/host_rule_ownership.ts +170 -0
- package/src/install/installThinLayer.ts +378 -0
- package/src/install/installedRuleLinks.ts +308 -0
- package/src/install/wizard-plan.ts +24 -0
- 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 +33 -81
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +426 -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 +53 -4
- package/src/scripts/_lib/agent_settings.ts +26 -124
- package/src/scripts/_lib/blocked_by_marker.ts +1 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/compile_time_toggles.ts +12 -21
- package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
- package/src/scripts/_lib/estate_offsets.ts +241 -0
- package/src/scripts/_lib/exemption_shape.ts +143 -0
- package/src/scripts/_lib/fnv.ts +23 -0
- package/src/scripts/_lib/foreign_scan.ts +106 -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/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +106 -0
- package/src/scripts/_lib/graph_feeder_record.ts +437 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +963 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/knowledge_global.ts +14 -1
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/module_reach.ts +456 -0
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +187 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- 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/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/review_coverage.ts +134 -0
- package/src/scripts/_lib/rule_consequence_class.ts +71 -0
- package/src/scripts/_lib/rule_injection.ts +130 -10
- package/src/scripts/_lib/rule_law_section.ts +147 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
- 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/skill_origin.ts +254 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/test_red_state.ts +5 -0
- package/src/scripts/_lib/thin_rules.ts +620 -0
- package/src/scripts/_lib/touched_file_quality.ts +570 -0
- package/src/scripts/_lib/turn_end_refusals.ts +77 -2
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- package/src/scripts/_lib/worker_budget.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +16 -1
- package/src/scripts/ai_council/cli_call_budget.ts +13 -5
- package/src/scripts/ai_council/clients.ts +26 -57
- package/src/scripts/ai_council/config.ts +8 -8
- 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_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/config.ts +11 -16
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/audit_user_type_axis.ts +20 -8
- package/src/scripts/before_complete_hook.ts +243 -12
- 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/bench_touched_file_quality.ts +238 -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_enforcement_matrix.ts +377 -20
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_evaluator_budgets.ts +4 -0
- package/src/scripts/check_finding_dispositions.ts +196 -21
- 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 +477 -0
- package/src/scripts/check_kernel_edit_ratified.ts +132 -14
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_manifest_content.ts +189 -0
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_standing_rule_delivery.ts +129 -13
- package/src/scripts/check_suppression_hygiene.ts +2 -5
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- 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/code_graph/detect.ts +127 -7
- package/src/scripts/code_graph/foreign.ts +194 -0
- package/src/scripts/code_graph/query.ts +217 -4
- package/src/scripts/code_graph/types.ts +26 -2
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +103 -0
- package/src/scripts/command_suggester/settings.ts +8 -108
- package/src/scripts/command_suggester/types.ts +4 -5
- package/src/scripts/compile_hook_manifest.ts +33 -1
- package/src/scripts/condense.ts +14 -27
- 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/estate_exemption_shape.ts +202 -0
- 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 +21 -4
- package/src/scripts/handoff_context_hook.ts +86 -37
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +175 -15
- package/src/scripts/hooks/block_config_weakening.ts +115 -7
- package/src/scripts/hooks/block_plumbing_writes.ts +37 -5
- package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/dispatch_hook.ts +52 -52
- package/src/scripts/hooks/evidence_independence.ts +12 -4
- package/src/scripts/hooks/exit_codes.ts +2 -1
- package/src/scripts/hooks/host_lowering.json +1 -1
- package/src/scripts/hooks/host_lowering.ts +19 -1
- package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
- package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/push_settle_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +795 -60
- package/src/scripts/hooks/state_io.ts +8 -4
- package/src/scripts/hooks/table_fingerprint.ts +21 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +24 -7
- package/src/scripts/hooks/turn_end_gate_hook.ts +85 -0
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install-hooks.sh +42 -14
- package/src/scripts/install.ts +78 -215
- package/src/scripts/installed_layer_report.ts +103 -0
- package/src/scripts/language_mirror_hook.ts +15 -6
- package/src/scripts/learning_sidecar.ts +119 -8
- package/src/scripts/lint_blocker_citations.ts +198 -0
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_hook_manifest.ts +53 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +465 -29
- 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 +647 -0
- package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
- package/src/scripts/lint_settings_classes.ts +1 -1
- package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
- package/src/scripts/lint_workflow_security.ts +173 -6
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +221 -8
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/model_rule_injection.ts +55 -8
- 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/project_thin_rules.ts +34 -327
- 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_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +274 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_module_reach.ts +212 -0
- package/src/scripts/report_obligation_mechanism.ts +228 -0
- package/src/scripts/report_parked_blockers.ts +222 -0
- package/src/scripts/report_required_checks_drift.ts +196 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_ranker_confusion.ts +543 -0
- package/src/scripts/report_standing_payload_by_host.ts +188 -15
- package/src/scripts/report_verification_record_coverage.ts +306 -0
- package/src/scripts/routing_doctor.ts +2 -2
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/agent-settings.schema.json +17 -31
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/review-findings.schema.json +3 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +1 -1
- package/src/scripts/self_review_gate.ts +101 -9
- package/src/scripts/skill_tools/score_skill_relevance.ts +314 -40
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/sync_pr_branch.ts +403 -132
- package/src/scripts/trigger_eval_grandfather.json +0 -21
- package/src/server/schemas/settings.ts +42 -176
- package/src/shared/skillRanking.ts +169 -14
- package/dist/cli-delegate/chunk-5R7HOLAF.js +0 -99
- package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- 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
|
@@ -65,8 +65,16 @@ import {
|
|
|
65
65
|
owns_session_state,
|
|
66
66
|
} from "./hooks/state_io.js";
|
|
67
67
|
import { readHookStdin } from "./hooks/hook_stdin.js";
|
|
68
|
+
import { hookSectionValue } from "./_lib/hook_settings.js";
|
|
68
69
|
import { isVerificationCommand, mightBeVerification } from "./_lib/verification_command.js";
|
|
70
|
+
import {
|
|
71
|
+
advisoryLine,
|
|
72
|
+
runTouchedFileQuality,
|
|
73
|
+
touchedFilesAtStop,
|
|
74
|
+
type QualityRun,
|
|
75
|
+
} from "./_lib/touched_file_quality.js";
|
|
69
76
|
import { runnerOf } from "./_lib/verification_evidence.js";
|
|
77
|
+
import { resolve_toolchain } from "../agent-src/templates/scripts/work_engine/stack/runner.js";
|
|
70
78
|
|
|
71
79
|
// NOTE: the Python docstring says `agents/runtime/state/`, but the code
|
|
72
80
|
// constant is `agents/state/`. Replicated verbatim — latent docstring/code
|
|
@@ -179,10 +187,87 @@ function _empty_state(): StateDict {
|
|
|
179
187
|
// a reader must never have to distinguish "no runs yet" from "key absent".
|
|
180
188
|
verification_runs: [],
|
|
181
189
|
edits_this_turn: 0,
|
|
190
|
+
// NOTE — `quality_runs` and `quality_files_source` are deliberately ABSENT
|
|
191
|
+
// here, against the convention `verification_runs` above follows.
|
|
192
|
+
//
|
|
193
|
+
// That convention ("present in the empty state so a reader never has to tell
|
|
194
|
+
// 'no runs yet' from 'key absent'") is the right default and it loses to a
|
|
195
|
+
// stronger one: the roadmap's first acceptance criterion is that with
|
|
196
|
+
// `touched_file_quality: off` the record is BYTE-IDENTICAL to the base ref.
|
|
197
|
+
// Seeding two keys would break that for every install that never opted in,
|
|
198
|
+
// and "the default-off feature changed my state file" is exactly the kind of
|
|
199
|
+
// silent shape drift a consumer cannot audit. The convention's cost here is
|
|
200
|
+
// zero, because the only reader of these keys is 2.1's analysis, which counts
|
|
201
|
+
// stops — and a stop with no key is a stop where the pass did not run, which
|
|
202
|
+
// is a distinction it needs rather than one it must not make.
|
|
182
203
|
checked_at: _now(),
|
|
183
204
|
};
|
|
184
205
|
}
|
|
185
206
|
|
|
207
|
+
/** The three values `hooks.verify_before_complete.touched_file_quality` may take. */
|
|
208
|
+
export type TouchedFileQualityMode = "off" | "shadow" | "warn";
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* The configured mode, defaulting to `off`.
|
|
212
|
+
*
|
|
213
|
+
* FAIL-CLOSED ON THE FLAG, FAIL-OPEN ON THE READ, exactly as
|
|
214
|
+
* `hookSectionEnabled` does: an unreadable settings file, a missing key, or a
|
|
215
|
+
* value outside the enum all resolve to `off`. A typo must never turn a pass
|
|
216
|
+
* ON — `warn` emits a line the operator did not ask for, and `shadow` spawns
|
|
217
|
+
* processes, so an unrecognised string is the one case where guessing is
|
|
218
|
+
* strictly worse than doing nothing.
|
|
219
|
+
*/
|
|
220
|
+
export function readTouchedFileQualityMode(consumer_root: string): TouchedFileQualityMode {
|
|
221
|
+
const raw = hookSectionValue(consumer_root, "verify_before_complete", "touched_file_quality");
|
|
222
|
+
return raw === "shadow" || raw === "warn" ? raw : "off";
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Run the shadow quality pass for this stop, or return nothing.
|
|
227
|
+
*
|
|
228
|
+
* Kept OUTSIDE the state lock on purpose. `update_json_under_lock` holds a lock
|
|
229
|
+
* around its mutator, and a mutator that spawns `tsc` would hold it for the
|
|
230
|
+
* whole typecheck — every concurrent concern writing this session's state would
|
|
231
|
+
* block behind a linter. The pass runs first, the result is handed to `_update`
|
|
232
|
+
* as data, and the lock stays as short as it was.
|
|
233
|
+
*/
|
|
234
|
+
export function collectTouchedFileQuality(
|
|
235
|
+
consumer_root: string,
|
|
236
|
+
session_id: string,
|
|
237
|
+
): { runs: QualityRun[]; source: string } | null {
|
|
238
|
+
let touched: { files: readonly string[]; source: string };
|
|
239
|
+
try {
|
|
240
|
+
touched = touchedFilesAtStop(consumer_root, session_id);
|
|
241
|
+
} catch {
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
if (touched.files.length === 0) {
|
|
245
|
+
// Nothing to measure. Recorded as an empty run list with its source, not as
|
|
246
|
+
// silence: 2.1 counts "stops with edits" against "stops with at least one
|
|
247
|
+
// entry", and a stop that produced no entry has to be distinguishable from
|
|
248
|
+
// a stop where the pass never ran.
|
|
249
|
+
return { runs: [], source: touched.source };
|
|
250
|
+
}
|
|
251
|
+
let commands: readonly string[] = [];
|
|
252
|
+
try {
|
|
253
|
+
commands = resolve_toolchain(consumer_root).quality;
|
|
254
|
+
} catch {
|
|
255
|
+
commands = [];
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
return {
|
|
259
|
+
runs: runTouchedFileQuality({
|
|
260
|
+
root: consumer_root,
|
|
261
|
+
commands,
|
|
262
|
+
files: touched.files,
|
|
263
|
+
}),
|
|
264
|
+
source: touched.source,
|
|
265
|
+
};
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
186
271
|
|
|
187
272
|
/** Return [tool_name, command_text] from a tool-event payload. */
|
|
188
273
|
function _extract_command(payload: StateDict): [string | null, string | null] {
|
|
@@ -402,6 +487,21 @@ function _cap_runs(runs: unknown[]): unknown[] {
|
|
|
402
487
|
*/
|
|
403
488
|
const _ERROR_EXIT_PREFIX = /^Error:\s*Exit code\s*(\d+)/i;
|
|
404
489
|
|
|
490
|
+
/**
|
|
491
|
+
* The same statement without the `Error:` word, which is how the host words it
|
|
492
|
+
* on its FAILURE event.
|
|
493
|
+
*
|
|
494
|
+
* Measured 2026-10-01 on Claude Code 2.1.286: a failing `Bash` call fires
|
|
495
|
+
* `PostToolUseFailure`, whose envelope carries NO `tool_response` at all. The
|
|
496
|
+
* exit status is a top-level `error` string whose first line reads
|
|
497
|
+
* `Exit code N`, with the command's own diagnostics on the lines after it. The
|
|
498
|
+
* prefix above never matches that, so for as long as only the success event was
|
|
499
|
+
* bound this recorder could not have written a non-zero exit even once — which
|
|
500
|
+
* is exactly what 24 consecutive all-zero records on this host turned out to
|
|
501
|
+
* mean.
|
|
502
|
+
*/
|
|
503
|
+
const _BARE_EXIT_PREFIX = /^\s*Exit code\s*(\d+)/i;
|
|
504
|
+
|
|
405
505
|
/** The status a post-tool payload actually reports, and HOW it reported it. */
|
|
406
506
|
interface ExitReading {
|
|
407
507
|
readonly code: number | null;
|
|
@@ -450,27 +550,91 @@ function _numeric_exit_field(obj: StateDict): number | null {
|
|
|
450
550
|
* record path was inert — found by an independent review of the branch that
|
|
451
551
|
* introduced it, against 1,077 real tool results.
|
|
452
552
|
*/
|
|
453
|
-
|
|
553
|
+
/**
|
|
554
|
+
* Did the HOST say this call failed, independently of anything in its text?
|
|
555
|
+
*
|
|
556
|
+
* Read from the native event name, which the host writes in two places and the
|
|
557
|
+
* agent in neither: `hook_event_name` inside the payload, and `native_event` on
|
|
558
|
+
* the dispatcher envelope. Either is authoritative; both are checked because a
|
|
559
|
+
* raw-payload invocation carries only the first and a synthesised envelope only
|
|
560
|
+
* the second.
|
|
561
|
+
*
|
|
562
|
+
* An explicit set of OBSERVED names, with a suffix match behind it as a declared
|
|
563
|
+
* fallback rather than as the primary rule. A reviewer called the suffix-only
|
|
564
|
+
* form a maintenance trap and was right about the direction: the set is what a
|
|
565
|
+
* reader checks against the manifest, and `PostToolUseFailure` is the one
|
|
566
|
+
* spelling this package has actually seen a host send.
|
|
567
|
+
*
|
|
568
|
+
* The fallback is kept, and keeping it is the deliberate half. A host whose
|
|
569
|
+
* failure event this tree has never observed is exactly the case where guessing
|
|
570
|
+
* wrong is cheapest in one direction and expensive in the other: a false
|
|
571
|
+
* positive costs a refusal to record a zero, a false negative costs a
|
|
572
|
+
* manufactured pass on a red run. So the set is the rule and the suffix is the
|
|
573
|
+
* safe default for a name nobody here has met yet.
|
|
574
|
+
*/
|
|
575
|
+
export const FAILURE_EVENT_NAMES: ReadonlySet<string> = new Set(["PostToolUseFailure"]);
|
|
576
|
+
|
|
577
|
+
function _is_failure_event(payload: StateDict, envelope: StateDict): boolean {
|
|
578
|
+
for (const v of [payload["hook_event_name"], envelope["native_event"]]) {
|
|
579
|
+
if (typeof v !== "string" || v === "") continue;
|
|
580
|
+
if (FAILURE_EVENT_NAMES.has(v)) return true;
|
|
581
|
+
if (/failure$/i.test(v)) return true;
|
|
582
|
+
}
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function _extract_exit_reading(payload: StateDict, failure_event = false): ExitReading {
|
|
587
|
+
// On an event the host itself named a FAILURE, a zero is never recorded —
|
|
588
|
+
// from any of the three readings. The host has already stated the call did not
|
|
589
|
+
// succeed, so a `0` arrived at by parsing its text would contradict the only
|
|
590
|
+
// authoritative thing in the envelope, and it would do so in the single most
|
|
591
|
+
// dangerous direction: manufacturing the strongest possible pass evidence out
|
|
592
|
+
// of a red run. `null` instead, which the classifier already treats as an
|
|
593
|
+
// instrument gap and never as a pass.
|
|
594
|
+
//
|
|
595
|
+
// Raised by an independent reviewer who asked what happens when a command's
|
|
596
|
+
// own error text begins `Exit code 0`. Nothing observed produces that, which
|
|
597
|
+
// is exactly why it is worth closing before something does.
|
|
598
|
+
const seal = (r: ExitReading): ExitReading =>
|
|
599
|
+
failure_event && r.code === 0 ? { code: null, source: null, interrupted: r.interrupted } : r;
|
|
600
|
+
|
|
454
601
|
const direct = _numeric_exit_field(payload);
|
|
455
|
-
if (direct !== null) return { code: direct, source: "field", interrupted: false };
|
|
602
|
+
if (direct !== null) return seal({ code: direct, source: "field", interrupted: false });
|
|
603
|
+
|
|
604
|
+
// The FAILURE envelope, read before the success keys because it carries none
|
|
605
|
+
// of them: no `tool_response`, the status in a top-level `error` string, and
|
|
606
|
+
// the interrupt flag spelled `is_interrupt` rather than the nested
|
|
607
|
+
// `interrupted` below. Interruption is checked FIRST — a killed call is a
|
|
608
|
+
// statement about the kill and not a verdict on the work, so a host that
|
|
609
|
+
// sends both must not have its kill read as a failing exit.
|
|
610
|
+
const interrupted_top = payload["is_interrupt"] === true;
|
|
611
|
+
const err = payload["error"];
|
|
612
|
+
if (typeof err === "string") {
|
|
613
|
+
if (interrupted_top) return { code: null, source: null, interrupted: true };
|
|
614
|
+
const bare = _BARE_EXIT_PREFIX.exec(err) ?? _ERROR_EXIT_PREFIX.exec(err);
|
|
615
|
+
if (bare?.[1] !== undefined) {
|
|
616
|
+
return seal({ code: Number(bare[1]), source: "error_prefix", interrupted: false });
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
if (interrupted_top) return { code: null, source: null, interrupted: true };
|
|
456
620
|
|
|
457
621
|
for (const key of ["tool_response", "toolResponse", "result", "output"]) {
|
|
458
622
|
const v = payload[key];
|
|
459
623
|
if (typeof v === "string") {
|
|
460
624
|
const m = _ERROR_EXIT_PREFIX.exec(v);
|
|
461
625
|
if (m?.[1] !== undefined) {
|
|
462
|
-
return { code: Number(m[1]), source: "error_prefix", interrupted: false };
|
|
626
|
+
return seal({ code: Number(m[1]), source: "error_prefix", interrupted: false });
|
|
463
627
|
}
|
|
464
628
|
continue;
|
|
465
629
|
}
|
|
466
630
|
if (v === null || typeof v !== "object" || Array.isArray(v)) continue;
|
|
467
631
|
const obj = v as StateDict;
|
|
468
632
|
const nested = _numeric_exit_field(obj);
|
|
469
|
-
if (nested !== null) return { code: nested, source: "field", interrupted: false };
|
|
633
|
+
if (nested !== null) return seal({ code: nested, source: "field", interrupted: false });
|
|
470
634
|
if (obj["interrupted"] === true) return { code: null, source: null, interrupted: true };
|
|
471
635
|
const hasStream = typeof obj["stdout"] === "string" || typeof obj["stderr"] === "string";
|
|
472
636
|
if (obj["interrupted"] === false && hasStream) {
|
|
473
|
-
return { code: 0, source: "response_shape", interrupted: false };
|
|
637
|
+
return seal({ code: 0, source: "response_shape", interrupted: false });
|
|
474
638
|
}
|
|
475
639
|
}
|
|
476
640
|
return _NO_EXIT;
|
|
@@ -504,10 +668,21 @@ function _extract_run_streams(payload: StateDict): { stdout: string; stderr: str
|
|
|
504
668
|
}
|
|
505
669
|
const topOut = payload["stdout"] ?? payload["output"];
|
|
506
670
|
const topErr = payload["stderr"];
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
671
|
+
if (typeof topOut === "string" || typeof topErr === "string") {
|
|
672
|
+
return {
|
|
673
|
+
stdout: typeof topOut === "string" ? topOut : "",
|
|
674
|
+
stderr: typeof topErr === "string" ? topErr : "",
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
// The failure envelope's one text field. Recorded as `stdout` because the
|
|
678
|
+
// host collapses both streams into it and says nothing about which was
|
|
679
|
+
// which — a recorder that split them would be inventing a fact — and because
|
|
680
|
+
// every parser in `verification_evidence` is line-anchored over stdout. The
|
|
681
|
+
// alternative, dropping it, would leave a red run recorded with its exit code
|
|
682
|
+
// and no reason, which is the half the reader actually needs.
|
|
683
|
+
const errText = payload["error"];
|
|
684
|
+
if (typeof errText === "string") return { stdout: errText, stderr: "" };
|
|
685
|
+
return { stdout: "", stderr: "" };
|
|
511
686
|
}
|
|
512
687
|
|
|
513
688
|
function _reset_turn(state: StateDict, session_id: string): StateDict {
|
|
@@ -521,6 +696,12 @@ function _reset_turn(state: StateDict, session_id: string): StateDict {
|
|
|
521
696
|
// turn's edits, which is the freshness argument `verify-before-complete` makes.
|
|
522
697
|
state["verification_runs"] = [];
|
|
523
698
|
state["edits_this_turn"] = 0;
|
|
699
|
+
// TURN-scoped for the same reason as its neighbour: a quality verdict from
|
|
700
|
+
// the previous turn describes files this turn may already have changed, and a
|
|
701
|
+
// stale PASS is the direction that misleads. DELETED rather than emptied, so
|
|
702
|
+
// that a turn boundary restores the base-ref shape — see `_empty_state`.
|
|
703
|
+
delete state["quality_runs"];
|
|
704
|
+
delete state["quality_files_source"];
|
|
524
705
|
// FC-3b turn-scoped counters: a CI settle must be witnessed within the same
|
|
525
706
|
// turn that claims it, so the in-flight observation does not survive a turn.
|
|
526
707
|
state["ci_saw_pending"] = false;
|
|
@@ -539,7 +720,19 @@ function _asInt(v: unknown): number {
|
|
|
539
720
|
return Number.isFinite(n) ? Math.trunc(n) : 0;
|
|
540
721
|
}
|
|
541
722
|
|
|
542
|
-
|
|
723
|
+
/**
|
|
724
|
+
* Apply one event to the state.
|
|
725
|
+
*
|
|
726
|
+
* `quality` is the shadow pass's already-computed result, handed in rather than
|
|
727
|
+
* fetched: this function runs INSIDE the state lock, and a spawn in here would
|
|
728
|
+
* hold that lock for the duration of a typecheck.
|
|
729
|
+
*/
|
|
730
|
+
function _update(
|
|
731
|
+
state: StateDict,
|
|
732
|
+
event: string,
|
|
733
|
+
envelope: StateDict,
|
|
734
|
+
quality: { runs: QualityRun[]; source: string } | null = null,
|
|
735
|
+
): StateDict {
|
|
543
736
|
const session_id = (envelope["session_id"] || state["session_id"] || "") as string;
|
|
544
737
|
if (session_id && session_id !== state["session_id"]) {
|
|
545
738
|
// Session boundary — reset session-scoped counters.
|
|
@@ -558,6 +751,16 @@ function _update(state: StateDict, event: string, envelope: StateDict): StateDic
|
|
|
558
751
|
state = _reset_turn(state, session_id);
|
|
559
752
|
}
|
|
560
753
|
|
|
754
|
+
// The host that wrote this file. Recorded because the instrument-gap reading
|
|
755
|
+
// is a PER-HOST question and the witness carried no answer to it: every
|
|
756
|
+
// coverage number had to be attributed by hand, and a file from an unknown
|
|
757
|
+
// host is indistinguishable from a host with nothing to report. Written on
|
|
758
|
+
// every update rather than once, so a file predating this field acquires it
|
|
759
|
+
// the first time the host touches it; until then a reader sees it absent,
|
|
760
|
+
// which is the honest reading and not a default.
|
|
761
|
+
const platform = envelope["platform"];
|
|
762
|
+
if (typeof platform === "string" && platform) state["platform"] = platform;
|
|
763
|
+
|
|
561
764
|
let payload = envelope["payload"];
|
|
562
765
|
if (!(typeof payload === "object" && payload !== null && !Array.isArray(payload))) {
|
|
563
766
|
payload = {};
|
|
@@ -668,7 +871,7 @@ function _update(state: StateDict, event: string, envelope: StateDict): StateDic
|
|
|
668
871
|
// own count is short.
|
|
669
872
|
if (cmd && mightBeVerification(cmd)) {
|
|
670
873
|
const streams = _extract_run_streams(pl);
|
|
671
|
-
const exit = _extract_exit_reading(pl);
|
|
874
|
+
const exit = _extract_exit_reading(pl, _is_failure_event(pl, envelope));
|
|
672
875
|
const runs = Array.isArray(state["verification_runs"])
|
|
673
876
|
? [...(state["verification_runs"] as unknown[])]
|
|
674
877
|
: [];
|
|
@@ -699,6 +902,10 @@ function _update(state: StateDict, event: string, envelope: StateDict): StateDic
|
|
|
699
902
|
}
|
|
700
903
|
} else if (event === "stop") {
|
|
701
904
|
state["last_stop_at"] = _now();
|
|
905
|
+
if (quality !== null) {
|
|
906
|
+
state["quality_runs"] = quality.runs;
|
|
907
|
+
state["quality_files_source"] = quality.source;
|
|
908
|
+
}
|
|
702
909
|
}
|
|
703
910
|
|
|
704
911
|
state["checked_at"] = _now();
|
|
@@ -760,6 +967,15 @@ export function run(
|
|
|
760
967
|
|
|
761
968
|
const target = path.join(consumer_root, statePathFor(session_id));
|
|
762
969
|
|
|
970
|
+
// The shadow quality pass, computed BEFORE the lock (see `_update`'s header)
|
|
971
|
+
// and only at `stop`. `off` is the template default and the resolved value of
|
|
972
|
+
// every unreadable or unrecognised setting, so an install that never opted in
|
|
973
|
+
// spawns nothing, reads no manifest and writes no new field — the acceptance
|
|
974
|
+
// criterion is that its record is byte-identical to the base ref.
|
|
975
|
+
const quality_mode = event === "stop" ? readTouchedFileQualityMode(consumer_root) : "off";
|
|
976
|
+
const quality =
|
|
977
|
+
quality_mode === "off" ? null : collectTouchedFileQuality(consumer_root, session_id);
|
|
978
|
+
|
|
763
979
|
// LOAD → UPDATE → PUBLISH under ONE lock, not three separate steps.
|
|
764
980
|
//
|
|
765
981
|
// This was `_load_state` / `_update` / `atomic_write_json`, which makes the
|
|
@@ -790,7 +1006,7 @@ export function run(
|
|
|
790
1006
|
// treats a missing counter as 0 and the `=== true` guards treat a missing
|
|
791
1007
|
// flag as false, so every assertion would still pass while `schema_version`
|
|
792
1008
|
// and an explicit `ci_last: null` vanished from a freshly created file.
|
|
793
|
-
state = _update({ ..._empty_state(), ...loaded } as StateDict, event, envelope);
|
|
1009
|
+
state = _update({ ..._empty_state(), ...loaded } as StateDict, event, envelope, quality);
|
|
794
1010
|
return state;
|
|
795
1011
|
});
|
|
796
1012
|
if (outcome === "failed") {
|
|
@@ -811,6 +1027,21 @@ export function run(
|
|
|
811
1027
|
);
|
|
812
1028
|
}
|
|
813
1029
|
|
|
1030
|
+
// `warn` — ONE advisory line, and the exit code does not move.
|
|
1031
|
+
//
|
|
1032
|
+
// In this tree a warn is conventionally an exit of 2, and on the one host that
|
|
1033
|
+
// honours a deny that reads as a BLOCK. D3 of the roadmap settles it the other
|
|
1034
|
+
// way for this field: shadow → warn only, never a block, on the strength of
|
|
1035
|
+
// this hook's own contract ("the hook itself never blocks — it is
|
|
1036
|
+
// observability infra, not control flow"). So the line goes to stderr and the
|
|
1037
|
+
// function returns 0 on this path exactly as on every other.
|
|
1038
|
+
if (quality_mode === "warn" && quality !== null) {
|
|
1039
|
+
const line = advisoryLine(quality.runs);
|
|
1040
|
+
if (line !== null) {
|
|
1041
|
+
process.stderr.write(`${line}\n`);
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
|
|
814
1045
|
if (verbose) {
|
|
815
1046
|
process.stderr.write(
|
|
816
1047
|
`verify-before-complete-hook: event=${event} ` +
|
|
@@ -199,8 +199,7 @@ export function write_clone_settings(variant: string, target: string): void {
|
|
|
199
199
|
'# Generated by bench_ab_clone.py for the A/B/C value benchmark.\n' +
|
|
200
200
|
'# Only the RDP toggle is set here; everything else uses package defaults.\n' +
|
|
201
201
|
'reasoning:\n' +
|
|
202
|
-
` enabled: ${enabled}\n
|
|
203
|
-
' auto_gate: true\n';
|
|
202
|
+
` enabled: ${enabled}\n`;
|
|
204
203
|
fs.writeFileSync(path.join(target, '.agent-settings.yml'), settings, 'utf-8');
|
|
205
204
|
}
|
|
206
205
|
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Wall time of one blocking `pre_tool_use` concern through the SPAWN path —
|
|
4
|
+
* interpreter start included — as p50 and p95.
|
|
5
|
+
*
|
|
6
|
+
* `road-to-a-ratification-fence-that-follows-its-imports` 4.1, the receiver for
|
|
7
|
+
* the half of the archived plumbing roadmap's AC-3 that was carried "as the
|
|
8
|
+
* narrowing it is". `concern_sla_ms` measures in-process concern work only, so
|
|
9
|
+
* `sla_ms x 3` could not be judged as a spawn timeout: the tree had no
|
|
10
|
+
* spawn-path number. This produces one.
|
|
11
|
+
*
|
|
12
|
+
* It replicates `dispatch_hook._run_concern`'s isolated branch rather than
|
|
13
|
+
* calling it (that function is private plumbing and editing it to export a
|
|
14
|
+
* helper would be a gated change for a measurement): the same `tsx` binary the
|
|
15
|
+
* dispatcher resolves from `node_modules/.bin`, the same envelope builder
|
|
16
|
+
* (`_build_envelope`), the same hardened env, the envelope on stdin, and the
|
|
17
|
+
* concern's own `--platform` argument. What it does not include is the
|
|
18
|
+
* dispatcher's own start-up, which happens once per event, not once per
|
|
19
|
+
* concern.
|
|
20
|
+
*
|
|
21
|
+
* It gates nothing and wires nothing. Whether a timeout of `sla_ms x 3` is
|
|
22
|
+
* tenable is a READING of its output, made by whoever reads it, and one
|
|
23
|
+
* machine's p95 is that machine's.
|
|
24
|
+
*
|
|
25
|
+
* Usage:
|
|
26
|
+
* npx tsx src/scripts/bench_concern_spawn_path.ts [--runs 20] [--concern block-no-verify]
|
|
27
|
+
*
|
|
28
|
+
* Exit 0 on a measurement, 2 when the concern or `tsx` cannot be found.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { spawnSync } from 'node:child_process';
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as os from 'node:os';
|
|
34
|
+
import * as path from 'node:path';
|
|
35
|
+
import { performance } from 'node:perf_hooks';
|
|
36
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
37
|
+
|
|
38
|
+
import { parse as parseYaml } from 'yaml';
|
|
39
|
+
|
|
40
|
+
import { hardenedSpawnEnv } from './_lib/spawn_env.js';
|
|
41
|
+
import { _build_envelope } from './hooks/dispatch_hook.js';
|
|
42
|
+
|
|
43
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
44
|
+
const REPO = path.resolve(path.dirname(_HERE), '..', '..');
|
|
45
|
+
|
|
46
|
+
/** Nearest-rank percentile over a sorted copy. */
|
|
47
|
+
export function percentile(samples: readonly number[], p: number): number {
|
|
48
|
+
if (samples.length === 0) {
|
|
49
|
+
return Number.NaN;
|
|
50
|
+
}
|
|
51
|
+
const sorted = [...samples].sort((a, b) => a - b);
|
|
52
|
+
const rank = Math.max(1, Math.ceil((p / 100) * sorted.length));
|
|
53
|
+
return sorted[Math.min(rank, sorted.length) - 1] as number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function concernScript(name: string): string | null {
|
|
57
|
+
const manifest = parseYaml(fs.readFileSync(path.join(REPO, 'src/scripts/hook_manifest.yaml'), 'utf8')) as {
|
|
58
|
+
concerns?: Record<string, { script?: string; severity?: string }>;
|
|
59
|
+
};
|
|
60
|
+
const def = manifest.concerns?.[name];
|
|
61
|
+
return def?.script === undefined ? null : path.join(REPO, def.script);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
65
|
+
let runs = 20;
|
|
66
|
+
let concern = 'block-no-verify';
|
|
67
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
68
|
+
if (argv[i] === '--runs') {
|
|
69
|
+
runs = Number(argv[i + 1] ?? runs);
|
|
70
|
+
i += 1;
|
|
71
|
+
} else if (argv[i] === '--concern') {
|
|
72
|
+
concern = argv[i + 1] ?? concern;
|
|
73
|
+
i += 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const script = concernScript(concern);
|
|
77
|
+
const tsx = path.join(REPO, 'node_modules', '.bin', process.platform === 'win32' ? 'tsx.cmd' : 'tsx');
|
|
78
|
+
if (script === null || !fs.existsSync(script) || !fs.existsSync(tsx)) {
|
|
79
|
+
process.stderr.write(`bench_concern_spawn_path: concern ${concern} or ${tsx} not found\n`);
|
|
80
|
+
return 2;
|
|
81
|
+
}
|
|
82
|
+
const payload = JSON.stringify({
|
|
83
|
+
session_id: 'bench',
|
|
84
|
+
hook_event_name: 'PreToolUse',
|
|
85
|
+
tool_name: 'Bash',
|
|
86
|
+
tool_input: { command: 'ls' },
|
|
87
|
+
});
|
|
88
|
+
const envelope = _build_envelope(
|
|
89
|
+
{
|
|
90
|
+
platform: 'claude',
|
|
91
|
+
event: 'pre_tool_use',
|
|
92
|
+
native_event: 'PreToolUse',
|
|
93
|
+
} as Parameters<typeof _build_envelope>[0],
|
|
94
|
+
payload,
|
|
95
|
+
);
|
|
96
|
+
const input = JSON.stringify(envelope);
|
|
97
|
+
const env = hardenedSpawnEnv({ AGENT_CONFIG_PACKAGE_ROOT: REPO });
|
|
98
|
+
|
|
99
|
+
const samples: number[] = [];
|
|
100
|
+
const codes = new Set<number | null>();
|
|
101
|
+
for (let i = 0; i < runs; i += 1) {
|
|
102
|
+
const t0 = performance.now();
|
|
103
|
+
const proc = spawnSync(tsx, [script, '--platform', 'claude'], {
|
|
104
|
+
input,
|
|
105
|
+
encoding: 'utf-8',
|
|
106
|
+
cwd: REPO,
|
|
107
|
+
env,
|
|
108
|
+
timeout: 30_000,
|
|
109
|
+
});
|
|
110
|
+
samples.push(performance.now() - t0);
|
|
111
|
+
codes.add(proc.status);
|
|
112
|
+
}
|
|
113
|
+
const cpu = os.cpus()[0]?.model ?? 'unknown cpu';
|
|
114
|
+
process.stdout.write(
|
|
115
|
+
[
|
|
116
|
+
`concern: ${concern} (${path.relative(REPO, script)})`,
|
|
117
|
+
`runner: ${os.platform()} ${os.arch()} · ${cpu} · ${String(os.cpus().length)} cpus · node ${process.version}`,
|
|
118
|
+
`runs: ${String(runs)} · exit codes: ${[...codes].join(', ')}`,
|
|
119
|
+
`p50: ${percentile(samples, 50).toFixed(1)} ms`,
|
|
120
|
+
`p95: ${percentile(samples, 95).toFixed(1)} ms`,
|
|
121
|
+
`max: ${Math.max(...samples).toFixed(1)} ms`,
|
|
122
|
+
].join('\n') + '\n',
|
|
123
|
+
);
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
128
|
+
process.exit(main());
|
|
129
|
+
}
|