@event4u/agent-config 16.1.0 → 16.3.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 +98 -257
- package/README.md +14 -12
- package/dist/agent-src/commands/analyze/inbox.md +1 -1
- 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/feature/plan.md +1 -1
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +1 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- 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/process-full.md +5 -5
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -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/work.md +4 -0
- 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/execution/auto-dispatch-classification.md +6 -6
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -0
- package/dist/agent-src/rules/broken-access-control.md +1 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
- package/dist/agent-src/rules/context-hygiene.md +1 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
- package/dist/agent-src/rules/design-fidelity.md +13 -16
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/domain-safety-retention.md +1 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +1 -0
- package/dist/agent-src/rules/git-history-discipline.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -2
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +14 -17
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
- package/dist/agent-src/rules/session-canary.md +8 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- 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/update_roadmap_progress.ts +4 -1
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
- 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/code-intelligence/SKILL.md +14 -2
- package/dist/agent-src/skills/design-review/SKILL.md +30 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- 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/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- 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/ui-component-architect/SKILL.md +25 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +30 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/dist/cli/python/knowledge_ingest.js +1 -1
- package/dist/cli/python/workspace_drive.js +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
- package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
- package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
- 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-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
- package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- 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 +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +1862 -809
- package/dist/cli-delegate/cmd_doctor.js +13 -6
- package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
- package/dist/cli-delegate/cmd_explain.js +5 -5
- package/dist/cli-delegate/cmd_export.js +11 -8
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +10 -7
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +11 -8
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +8 -6
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +4 -3
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +11 -8
- package/dist/cli-delegate/cmd_uninstall.js +11 -8
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +11 -8
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +5 -5
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +132 -80
- 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 +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +7972 -5186
- package/dist/hooks/dispatch.sha256 +1 -0
- 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 +2226 -1055
- package/dist/install/installThinLayer.js +261 -0
- package/dist/install/installedRuleLinks.js +176 -0
- package/dist/install/wizard-plan.js +24 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +40913 -34865
- package/dist/scripts/_lib/agent_settings.js +11 -0
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- package/dist/scripts/_lib/installed_layer.js +378 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- 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/thin_rules.js +458 -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/schemas/settings.js +29 -0
- package/dist/shared/skillRanking.js +74 -13
- package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
- package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
- package/dist/ui/index.html +2 -2
- package/docs/contracts/settings-classes.md +10 -6
- package/package.json +4 -4
- 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/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/src/config/agent-settings.template.yml +91 -22
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/continuity-surface.json +9 -2
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +327 -3
- package/src/config/gate-violation-baselines.json +21 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +8 -3
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/routing-coverage-seed.json +38 -3
- 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 +99 -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 +312 -0
- package/src/install/installedRuleLinks.ts +220 -0
- package/src/install/wizard-plan.ts +24 -0
- package/src/scripts/_cli/cmd_doctor.ts +28 -90
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_cli/doctor_execution.ts +100 -17
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/concern_sla_window.ts +200 -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/forge_protection.ts +114 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
- package/src/scripts/_lib/graph_feeder_record.ts +214 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +538 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
- package/src/scripts/_lib/obligations.ts +119 -8
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +2 -1
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- 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/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/skill_origin.ts +254 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/thin_rules.ts +540 -0
- package/src/scripts/_lib/touched_file_quality.ts +434 -0
- package/src/scripts/_lib/turn_end_refusals.ts +600 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/verification_command.ts +324 -0
- package/src/scripts/_lib/verification_evidence.ts +647 -0
- package/src/scripts/_lib/verify_clause.ts +280 -0
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- 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 +1 -1
- package/src/scripts/ai_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +573 -25
- package/src/scripts/bench_hook_latency.ts +412 -5
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/cache_realization_report.ts +61 -1
- package/src/scripts/check_argument_hint.ts +287 -0
- package/src/scripts/check_claims.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +38 -9
- package/src/scripts/check_enforcement_matrix.ts +621 -22
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +138 -7
- package/src/scripts/check_generator_sync.ts +71 -0
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_host_docs_digest.ts +786 -0
- package/src/scripts/check_host_format_column.ts +559 -0
- package/src/scripts/check_input_references.ts +228 -0
- package/src/scripts/check_inputs_parity.ts +235 -0
- package/src/scripts/check_kernel_edit_ratified.ts +89 -9
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_holds.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +115 -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/compile_hook_manifest.ts +90 -14
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +192 -14
- package/src/scripts/hooks/block_config_weakening.ts +294 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
- package/src/scripts/hooks/bundle_integrity.ts +291 -0
- package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
- package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/concern_timings.ts +94 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
- package/src/scripts/hooks/design_pass_hook.ts +100 -9
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +77 -71
- package/src/scripts/hooks/edit_shape_hook.ts +1 -2
- package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
- package/src/scripts/hooks/evidence_independence.ts +1 -2
- package/src/scripts/hooks/exit_codes.ts +129 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +146 -3
- package/src/scripts/hooks/host_lowering.yaml +262 -46
- package/src/scripts/hooks/host_semantics.ts +30 -2
- package/src/scripts/hooks/injection_budget.ts +9 -2
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
- package/src/scripts/hooks/journal_record_hook.ts +1 -2
- package/src/scripts/hooks/memory_recall_hook.ts +1 -2
- package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
- package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/permission_gate.ts +1 -2
- package/src/scripts/hooks/push_settle_hook.ts +1 -3
- package/src/scripts/hooks/replay_hook.ts +2 -1
- package/src/scripts/hooks/reread_guard_hook.ts +1 -2
- package/src/scripts/hooks/review_baseline_hook.ts +1 -2
- package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
- package/src/scripts/hooks/rule_inject_hook.ts +765 -68
- package/src/scripts/hooks/run_continuation_hook.ts +13 -15
- package/src/scripts/hooks/skill_route_hook.ts +1 -2
- package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
- package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
- package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
- package/src/scripts/hooks/table_fingerprint.ts +70 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +75 -189
- 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_deny_text.ts +419 -0
- package/src/scripts/lint_exit_codes.ts +262 -0
- package/src/scripts/lint_hook_manifest.ts +108 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_roadmap_blockers.ts +78 -12
- package/src/scripts/lint_rule_law_section.ts +517 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/lint_workflow_security.ts +161 -5
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/release_publication.ts +13 -1
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_skill_ranker_confusion.ts +442 -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/roadmap_verify_share.ts +213 -0
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/command.schema.json +44 -0
- package/src/scripts/schemas/review-findings.schema.json +7 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/self_review_gate.ts +421 -17
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/trigger_eval_grandfather.json +0 -7
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +156 -4
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +41 -0
- package/src/shared/skillRanking.ts +117 -11
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
- package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- package/dist/ui/assets/index-DH1xc62v.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* concern_timings — the per-concern latency sink the bench reads.
|
|
5
|
+
*
|
|
6
|
+
* Step 3.2 of `road-to-a-kernel-that-guards-its-plumbing`. The dispatcher has
|
|
7
|
+
* always timed each concern — `_run_concern` returns a duration and the
|
|
8
|
+
* feedback record carries it — but nothing could READ that distribution: the
|
|
9
|
+
* feedback dir keeps one file per concern and every dispatch OVERWRITES it, so
|
|
10
|
+
* the only survivor is the last run. A p95 needs every sample, and the bench
|
|
11
|
+
* harness that produces the samples runs with `AGENT_CONFIG_REPLAY=1`, where
|
|
12
|
+
* the feedback write returns before writing anything at all.
|
|
13
|
+
*
|
|
14
|
+
* So this sink is separate from the feedback dir on purpose, and deliberately
|
|
15
|
+
* not derived from it:
|
|
16
|
+
*
|
|
17
|
+
* - it APPENDS, so N runs leave N samples rather than one;
|
|
18
|
+
* - it is written in replay mode, because the measurement harness is the
|
|
19
|
+
* caller that needs it;
|
|
20
|
+
* - it is off unless the variable is set, so the cost on a real dispatch is
|
|
21
|
+
* one `process.env` lookup.
|
|
22
|
+
*
|
|
23
|
+
* It carries a concern name, an integer, an event and a platform. There is no
|
|
24
|
+
* field that can hold a payload, a path or a prompt — the same shape-level
|
|
25
|
+
* privacy floor `payload_stubs` keeps one row up.
|
|
26
|
+
*
|
|
27
|
+
* It lives in its own file rather than inside `dispatch_hook.ts` because that
|
|
28
|
+
* file sits against the 1,500-line source budget, and `check_source_size_budget`
|
|
29
|
+
* refused the inline version.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** Environment variable naming the JSONL sink. Registered in the kill-switch table. */
|
|
33
|
+
export const TIMINGS_SINK_ENV = "AGENT_CONFIG_HOOK_TIMINGS";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* One measurement.
|
|
37
|
+
*
|
|
38
|
+
* MICROseconds, not milliseconds. The dispatcher's `duration_ms` is floored,
|
|
39
|
+
* and since the in-process fast path landed every registry concern finishes in
|
|
40
|
+
* well under a millisecond — so the floored field reads exactly `0` for all of
|
|
41
|
+
* them. That was invisible while nothing consumed the number and stops being
|
|
42
|
+
* invisible the moment a p95 is reported and a timeout derived from it.
|
|
43
|
+
*/
|
|
44
|
+
export interface ConcernTimingSample {
|
|
45
|
+
concern: string;
|
|
46
|
+
duration_us: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Append one JSONL row per concern, when the sink is armed.
|
|
51
|
+
*
|
|
52
|
+
* Never throws and never blocks the dispatch: a measurement sink that can fail
|
|
53
|
+
* a hook would be a new way for the plumbing to refuse, which is the opposite
|
|
54
|
+
* of what this roadmap is for.
|
|
55
|
+
*/
|
|
56
|
+
export function writeConcernTimings(
|
|
57
|
+
event: string,
|
|
58
|
+
platform: string,
|
|
59
|
+
samples: readonly ConcernTimingSample[],
|
|
60
|
+
sinkPath: string | undefined = process.env[TIMINGS_SINK_ENV],
|
|
61
|
+
): void {
|
|
62
|
+
if (!sinkPath) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
const lines: string[] = [];
|
|
67
|
+
for (const sample of samples) {
|
|
68
|
+
// A concern the dispatcher never timed is OMITTED rather than recorded
|
|
69
|
+
// as 0. A zero here would read as "instantaneous" and would be
|
|
70
|
+
// indistinguishable from a real sub-millisecond run — the exact
|
|
71
|
+
// substitution the report's `not_measured` requirement forbids one layer
|
|
72
|
+
// up, reintroduced at the source instead of at the report.
|
|
73
|
+
if (!Number.isFinite(sample.duration_us)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
lines.push(
|
|
77
|
+
JSON.stringify({
|
|
78
|
+
concern: sample.concern,
|
|
79
|
+
// Rounded HERE rather than at the call site: the caller holds a
|
|
80
|
+
// float millisecond reading and the sink is the one place that has
|
|
81
|
+
// to decide the recorded unit.
|
|
82
|
+
duration_us: Math.round(sample.duration_us),
|
|
83
|
+
event,
|
|
84
|
+
platform,
|
|
85
|
+
}),
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (lines.length > 0) {
|
|
89
|
+
fs.appendFileSync(sinkPath, lines.join("\n") + "\n", "utf-8");
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
// Non-fatal by construction — see the header.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -102,15 +102,14 @@ import { classifyLadder, type LadderRung } from "../_lib/judgment_ladder.js";
|
|
|
102
102
|
import { resolveSessionRole } from "../_lib/session_role.js";
|
|
103
103
|
import { resolveSubagentRouting, type Tier } from "../_lib/subagent_routing.js";
|
|
104
104
|
import { isSyntheticPrompt } from "../_lib/prompt_shape.js";
|
|
105
|
+
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
105
106
|
|
|
106
|
-
const EXIT_ALLOW = 0;
|
|
107
107
|
// Severity is taken from the EXIT CODE, not from the `decision` field in the
|
|
108
108
|
// stdout payload — mirrors `language_mirror_hook.ts`'s own note (found the
|
|
109
109
|
// same way: by tracing delivery, not by re-reading the unit tests). A warn
|
|
110
110
|
// verdict is reported at exit 2 so `host_semantics.emitFor` reduces it to
|
|
111
111
|
// severity `"warn"` and forwards `additional_context`; see the file header
|
|
112
112
|
// for why this exit code never actually blocks the turn.
|
|
113
|
-
const EXIT_WARN = 2;
|
|
114
113
|
|
|
115
114
|
type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
|
|
116
115
|
type JsonObject = { [k: string]: JsonValue };
|
|
@@ -57,12 +57,13 @@ import path from 'node:path';
|
|
|
57
57
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
58
58
|
|
|
59
59
|
import { appendDischarge, stamp } from '../_lib/obligations.js';
|
|
60
|
+
import { compareInputs } from '../_lib/probe_inputs.js';
|
|
61
|
+
import { trigger_matches, type Trigger } from '../_lib/router_match.js';
|
|
60
62
|
import { isUiPath, isUiTreePath } from '../_lib/ui_surface.js';
|
|
61
63
|
import { loadDesignContext, scanFile } from '../lint_design_slop.js';
|
|
62
64
|
import { readHookStdin } from './hook_stdin.js';
|
|
65
|
+
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
63
66
|
|
|
64
|
-
const EXIT_ALLOW = 0;
|
|
65
|
-
const EXIT_WARN = 2;
|
|
66
67
|
const SETTINGS_FILE = '.agent-settings.yml';
|
|
67
68
|
const STATE_REL = path.join('agents', 'runtime', 'state', 'design-pass-hook.json');
|
|
68
69
|
const AUDIT_REL = path.join('agents', 'runtime', 'state', 'ui-audit.json');
|
|
@@ -150,27 +151,94 @@ export interface ConformanceVerdict {
|
|
|
150
151
|
* write is the noise that gets a carrier switched off — Risk 1 of the parent
|
|
151
152
|
* roadmap. Absent is still reported honestly whenever the pass speaks for
|
|
152
153
|
* another reason.
|
|
154
|
+
*
|
|
155
|
+
* The ONE exception is a turn that actually touched a provided design
|
|
156
|
+
* handover. There, the probe is the evidence the turn was supposed to
|
|
157
|
+
* produce, and its absence is the noteworthy kind.
|
|
153
158
|
*/
|
|
154
159
|
noteworthy: boolean;
|
|
155
160
|
line: string;
|
|
156
161
|
}
|
|
157
162
|
|
|
158
|
-
export
|
|
163
|
+
export interface ConformanceOptions {
|
|
164
|
+
/**
|
|
165
|
+
* Whether a provided design handover was among the files this turn wrote.
|
|
166
|
+
* Decided by `handoverTouched` from the shipped routing triggers, never by a
|
|
167
|
+
* matcher invented here.
|
|
168
|
+
*/
|
|
169
|
+
handoverDetected?: boolean;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The file-based half of `src/rules/design-fidelity.md`'s `triggers:` set — the
|
|
174
|
+
* shipped answer to "is this file a provided design handover?".
|
|
175
|
+
*
|
|
176
|
+
* COPIED AS A CONSTANT, MATCHED BY THE SHIPPED MATCHER. Reading and parsing the
|
|
177
|
+
* rule's frontmatter here would put a YAML load on `post_tool_use`, the hottest
|
|
178
|
+
* slot this concern binds, and would depend on a rule path that differs between
|
|
179
|
+
* this repository and an installed consumer. The drift that a constant invites
|
|
180
|
+
* is closed by a test instead: `design_pass.test.ts` asserts this list equals the
|
|
181
|
+
* rule's file-based triggers in BOTH directions, so a trigger added to the rule
|
|
182
|
+
* and not here fails CI.
|
|
183
|
+
*
|
|
184
|
+
* THE HONEST REACH. Only the two HTML patterns are reachable through this
|
|
185
|
+
* carrier. `.claude/design-system/` names JSON and token files, which
|
|
186
|
+
* `isUiSurface` does not admit, so `main` returns before the verdict is
|
|
187
|
+
* computed. Widening `isUiSurface` to admit them would change the UI-turn
|
|
188
|
+
* denominator that the consultation-rate measurement is defined against, which
|
|
189
|
+
* is a different decision than this one. The prefix stays for parity with the
|
|
190
|
+
* rule and is stated as unreachable rather than quietly dropped.
|
|
191
|
+
*/
|
|
192
|
+
export const HANDOVER_TRIGGERS: readonly Trigger[] = [
|
|
193
|
+
{ file_pattern: '*design.html' },
|
|
194
|
+
{ file_pattern: '*.dc.html' },
|
|
195
|
+
{ path_prefix: '.claude/design-system/' },
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
/** True when any of the paths this turn wrote is a provided design handover. */
|
|
199
|
+
export function handoverTouched(paths: readonly string[]): boolean {
|
|
200
|
+
if (!paths.length) return false;
|
|
201
|
+
return HANDOVER_TRIGGERS.some((t) => trigger_matches(t, '', paths, null));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function conformanceVerdict(root: string, opts: ConformanceOptions = {}): ConformanceVerdict {
|
|
159
205
|
let raw: string;
|
|
160
206
|
try {
|
|
161
207
|
raw = fs.readFileSync(path.join(root, CONFORMANCE_REL), 'utf-8');
|
|
162
208
|
} catch {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
209
|
+
const base =
|
|
210
|
+
'ui-conformance: absent — no probe artefact for this change (run `ui_conformance_probe --target <file> --reference <file>`). Absent is not clean.';
|
|
211
|
+
return opts.handoverDetected
|
|
212
|
+
? {
|
|
213
|
+
noteworthy: true,
|
|
214
|
+
line: `${base} A provided design handover was touched this turn, so this is the absence worth naming.`,
|
|
215
|
+
}
|
|
216
|
+
: { noteworthy: false, line: base };
|
|
167
217
|
}
|
|
168
218
|
try {
|
|
169
219
|
const a = JSON.parse(raw) as {
|
|
170
220
|
structure_gate?: string;
|
|
221
|
+
inputs?: unknown;
|
|
171
222
|
dimensions?: { dimension: string; status: string; findings: number | null; reason?: string }[];
|
|
172
|
-
findings?:
|
|
223
|
+
findings?: { dimension?: string; probe_id?: string; expected?: string; observed?: string }[];
|
|
173
224
|
};
|
|
225
|
+
|
|
226
|
+
// Before anything is counted. A finding count measured against inputs
|
|
227
|
+
// that have since moved is the misleading half of a stale artefact, so
|
|
228
|
+
// the count is withheld rather than printed beside a warning.
|
|
229
|
+
const inputs = compareInputs(a.inputs, (p) => (path.isAbsolute(p) ? p : path.join(root, p)));
|
|
230
|
+
if (inputs.verdict === 'moved') {
|
|
231
|
+
return {
|
|
232
|
+
noteworthy: true,
|
|
233
|
+
line: [
|
|
234
|
+
`ui-conformance: stale — ${inputs.moved.join(', ')} changed since the probe ran, so its findings ` +
|
|
235
|
+
'describe inputs that no longer exist. The count is withheld rather than reported against ' +
|
|
236
|
+
'them; re-run `ui_conformance_probe --target <file> --reference <file>`.',
|
|
237
|
+
' (shadow verdict: reported, never enforced — this pass does not block on it)',
|
|
238
|
+
].join('\n'),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
174
242
|
const rows = a.dimensions ?? [];
|
|
175
243
|
const exercised = rows.filter((r) => r.status === 'exercised');
|
|
176
244
|
const notApplicable = rows.filter((r) => r.status !== 'exercised');
|
|
@@ -188,6 +256,29 @@ export function conformanceVerdict(root: string): ConformanceVerdict {
|
|
|
188
256
|
if (a.structure_gate === 'stopped') {
|
|
189
257
|
parts.push(' · structure gate stopped on at least one node — style comparison was skipped for it');
|
|
190
258
|
}
|
|
259
|
+
// The added-element half. This line already said "Absent is not clean"
|
|
260
|
+
// about a missing artefact; the probe's structure dimension could only
|
|
261
|
+
// ever show the omit half of "never omit or add an element", so this is
|
|
262
|
+
// the one number the verdict could not print. Derived from the findings
|
|
263
|
+
// the probe already writes — no new artefact field is read.
|
|
264
|
+
const addedElements = (a.findings ?? []).filter(
|
|
265
|
+
(f) => f.dimension === 'structure' && f.expected === 'absent' && f.observed === 'present',
|
|
266
|
+
);
|
|
267
|
+
if (addedElements.length) {
|
|
268
|
+
parts.push(
|
|
269
|
+
` · ${addedElements.length} element(s) present in the target and absent from the reference: ` +
|
|
270
|
+
`${addedElements.map((f) => f.probe_id ?? '?').join(', ')} — added, not ported`,
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
parts.push(
|
|
274
|
+
inputs.verdict === 'unchanged'
|
|
275
|
+
? ' · inputs: unchanged since the probe ran'
|
|
276
|
+
: // Unknown is a version skew, not evidence of movement — and
|
|
277
|
+
// equally not evidence of freshness. Saying so is the whole
|
|
278
|
+
// point: an artefact from before the digests existed must read
|
|
279
|
+
// neither stale nor fresh.
|
|
280
|
+
` · inputs: unknown — ${inputs.reason}`,
|
|
281
|
+
);
|
|
191
282
|
parts.push(' (shadow verdict: reported, never enforced — this pass does not block on it)');
|
|
192
283
|
return {
|
|
193
284
|
noteworthy: (a.findings ?? []).length > 0 || a.structure_gate === 'stopped' || notApplicable.length > 0,
|
|
@@ -456,7 +547,7 @@ function main(): number {
|
|
|
456
547
|
// be silent — a behavioural finding is exactly the thing no static scan can
|
|
457
548
|
// see — but it cannot make it refuse. `result.blocked` above is computed
|
|
458
549
|
// without it and the exit code below is unchanged.
|
|
459
|
-
const conformance = conformanceVerdict(root);
|
|
550
|
+
const conformance = conformanceVerdict(root, { handoverDetected: handoverTouched(targets) });
|
|
460
551
|
|
|
461
552
|
if (
|
|
462
553
|
!result.findings.length &&
|
|
@@ -26,10 +26,9 @@ import { type DesignContext } from "../design_slop_rules.js";
|
|
|
26
26
|
import { UI_EXT } from "../_lib/ui_surface.js";
|
|
27
27
|
import { loadDesignContext, scanFile } from "../lint_design_slop.js";
|
|
28
28
|
import { readHookStdin } from "./hook_stdin.js";
|
|
29
|
+
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
29
30
|
|
|
30
31
|
const SETTINGS_FILE = ".agent-settings.yml";
|
|
31
|
-
const EXIT_ALLOW = 0;
|
|
32
|
-
const EXIT_WARN = 2;
|
|
33
32
|
const DEGRADE_AFTER = 3; // surfaces of the same file::rule signature before going silent
|
|
34
33
|
|
|
35
34
|
type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Per `docs/contracts/hook-architecture-v1.md`. Reads `src/scripts/hook_manifest.yaml`,
|
|
13
13
|
* resolves which concerns fire on the given (platform, event) tuple, and runs each
|
|
14
14
|
* sequentially with the stdin envelope contract. Reduces concern exit codes per the
|
|
15
|
-
* spec (0=allow, 1=block, 2=warn, ≥3=error →
|
|
15
|
+
* spec (0=allow, 1=block, 2=warn, ≥3=error → resolved by declared `severity`).
|
|
16
16
|
*
|
|
17
17
|
* Invocation:
|
|
18
18
|
*
|
|
@@ -34,6 +34,10 @@ import * as tty from "node:tty";
|
|
|
34
34
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
35
35
|
import { parse as parseYaml } from "yaml";
|
|
36
36
|
|
|
37
|
+
import { runBundleIntegrityGate } from "./bundle_integrity.js";
|
|
38
|
+
import { writeConcernTimings, type ConcernTimingSample } from "./concern_timings.js";
|
|
39
|
+
import { tableFingerprint } from "./table_fingerprint.js";
|
|
40
|
+
|
|
37
41
|
import { hardenedSpawnEnv } from "../_lib/spawn_env.js";
|
|
38
42
|
import {
|
|
39
43
|
atomic_write_json,
|
|
@@ -55,10 +59,19 @@ import { _concern_body_classes, planPayloadShapes } from "./payload_stub.js";
|
|
|
55
59
|
import { resolveSessionRole, type SessionRole } from "../_lib/session_role.js";
|
|
56
60
|
import { stdinReadFailure, denyOnStdinFailure } from './stdin_failure_policy.js';
|
|
57
61
|
export { stdinReadFailure, denyOnStdinFailure, _is_fail_closed_blocking } from './stdin_failure_policy.js';
|
|
62
|
+
// Severity policy — what a declaration means when the concern said nothing.
|
|
63
|
+
// Re-exported so the move out of this file left every importer unaffected.
|
|
64
|
+
import {
|
|
65
|
+
_is_advisory, _is_blocking, _resolve_execution_failure,
|
|
66
|
+
classifySpawnResult, noVerdictRefusalNotice, SPAWN_TIMEOUT_MS,
|
|
67
|
+
} from './concern_failure_policy.js';
|
|
68
|
+
export { _is_advisory, _is_blocking, _resolve_execution_failure };
|
|
58
69
|
import { _py_json_dumps } from './py_json_dumps.js';
|
|
59
70
|
import { _fallback_yaml } from './fallback_yaml.js';
|
|
60
71
|
import { detectSurface } from '../_lib/surface.js';
|
|
61
72
|
import { recordCapture, recordOpportunity } from "../_lib/collector_denominator.js";
|
|
73
|
+
import { EXIT_ALLOW, EXIT_BLOCK, EXIT_WARN, EXIT_USAGE } from './exit_codes.js';
|
|
74
|
+
export { EXIT_ALLOW, EXIT_BLOCK, EXIT_WARN };
|
|
62
75
|
export { _fallback_yaml } from './fallback_yaml.js';
|
|
63
76
|
|
|
64
77
|
// Free-form JSON values flow through every helper here; a documented
|
|
@@ -84,10 +97,6 @@ const REPO_ROOT = path.resolve(
|
|
|
84
97
|
);
|
|
85
98
|
const MANIFEST_PATH = path.join(REPO_ROOT, "src", "scripts", "hook_manifest.yaml");
|
|
86
99
|
|
|
87
|
-
export const EXIT_ALLOW = 0;
|
|
88
|
-
export const EXIT_BLOCK = 1;
|
|
89
|
-
export const EXIT_WARN = 2;
|
|
90
|
-
|
|
91
100
|
// Per Council Round 2 (Q3): `agent_error` covers agent-level crashes
|
|
92
101
|
// that are not concern-triggered, so chat-history can checkpoint
|
|
93
102
|
// partial sessions on abnormal exit.
|
|
@@ -126,18 +135,6 @@ export function _severity_for(rc: number): string {
|
|
|
126
135
|
return _SEVERITY_BY_EXIT[rc] ?? "error";
|
|
127
136
|
}
|
|
128
137
|
|
|
129
|
-
/**
|
|
130
|
-
* P0.2 (road-to-rule-coherence) — is this concern declared advisory?
|
|
131
|
-
*
|
|
132
|
-
* An advisory concern MUST never produce a BLOCK verdict on any host. Four
|
|
133
|
-
* PreToolUse concerns document themselves as advisory in prose
|
|
134
|
-
* (`design_slop_hook`: "FLAGS, NEVER A BLOCK") while the transport happily
|
|
135
|
-
* turned their WARN into a host-level deny. Prose is not enforcement: the
|
|
136
|
-
* manifest now declares severity and the dispatcher enforces the ceiling.
|
|
137
|
-
*/
|
|
138
|
-
export function _is_advisory(concern: JsonObject): boolean {
|
|
139
|
-
return String(concern["severity"] ?? "").trim().toLowerCase() === "advisory";
|
|
140
|
-
}
|
|
141
138
|
|
|
142
139
|
function _now_iso(): string {
|
|
143
140
|
// Python: datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ").
|
|
@@ -196,37 +193,25 @@ export function _parse_concern_stdout(stdout_text: string): JsonObject {
|
|
|
196
193
|
* path (`yaml.safe_load(text) or {}`); version 1.1 matches PyYAML.safe_load.
|
|
197
194
|
*/
|
|
198
195
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
196
|
+
* Content fingerprint of a manifest source — delegated to `tableFingerprint`,
|
|
197
|
+
* which owns the algorithm and the measurement.
|
|
201
198
|
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
* source, not resist an adversary — a wrong answer costs the slow path, never
|
|
206
|
-
* correctness.
|
|
199
|
+
* road-to-blocking-severities 3.1: this comment used to argue against a crypto
|
|
200
|
+
* hash for a function that already used one. The retired argument and the
|
|
201
|
+
* numbers that retired it live there now.
|
|
207
202
|
*/
|
|
208
203
|
export function _manifest_fingerprint(text: string): string {
|
|
209
|
-
|
|
210
|
-
for (let i = 0; i < text.length; i += 1) {
|
|
211
|
-
h ^= text.charCodeAt(i);
|
|
212
|
-
h = Math.imul(h, 0x01000193) >>> 0;
|
|
213
|
-
}
|
|
214
|
-
return `${h.toString(16)}:${String(text.length)}`;
|
|
204
|
+
return tableFingerprint(text);
|
|
215
205
|
}
|
|
216
206
|
|
|
217
207
|
export function _load_yaml(p: string): JsonObject {
|
|
218
|
-
// Precompiled fast path. The manifest is ~61 kB of YAML
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
208
|
+
// Precompiled fast path. The manifest is ~61 kB of YAML parsed on EVERY
|
|
209
|
+
// dispatch — 12 ms of a ~103 ms dispatch, plus 8 ms to load the `yaml` module
|
|
210
|
+
// itself. The sibling `.json` is the same data with comments stripped,
|
|
211
|
+
// 14.7 kB, and JSON.parse of it is sub-millisecond.
|
|
222
212
|
//
|
|
223
|
-
// Freshness is
|
|
224
|
-
//
|
|
225
|
-
// one: on a fresh `actions/checkout` both files get the checkout timestamp in
|
|
226
|
-
// whatever order git wrote them, so whether the optimisation applied at all
|
|
227
|
-
// was a coin flip. It won on the PR (p95 129 ms) and lost on the trunk
|
|
228
|
-
// (p95 186 ms) for the same commit. A fingerprint is deterministic wherever
|
|
229
|
-
// the tree came from.
|
|
213
|
+
// Freshness is SOURCE CONTENT, never mtime — the measured defect behind that
|
|
214
|
+
// is in `table_fingerprint.ts`, told once rather than in all three readers.
|
|
230
215
|
//
|
|
231
216
|
// Reading the YAML unconditionally costs ~0 ms (it is the PARSE that is
|
|
232
217
|
// expensive), so the fast path still skips ~20 ms.
|
|
@@ -238,7 +223,14 @@ export function _load_yaml(p: string): JsonObject {
|
|
|
238
223
|
if (
|
|
239
224
|
_isObject(raw) &&
|
|
240
225
|
raw["fingerprint"] === _manifest_fingerprint(text) &&
|
|
241
|
-
_isObject(raw["manifest"])
|
|
226
|
+
_isObject(raw["manifest"]) &&
|
|
227
|
+
// road-to-blocking-severities 2.3, the manifest twin of the check in
|
|
228
|
+
// `host_lowering.resolveTable`, which carries the full reasoning. In
|
|
229
|
+
// one line: the label above binds this file to the YAML SOURCE and says
|
|
230
|
+
// nothing about the body underneath, so an edited `manifest` body with
|
|
231
|
+
// an untouched label was served — on the table that decides which
|
|
232
|
+
// concern runs on which slot at all. Absent field → fall through.
|
|
233
|
+
raw["body_fingerprint"] === _manifest_fingerprint(JSON.stringify(raw["manifest"]))
|
|
242
234
|
) {
|
|
243
235
|
return raw["manifest"];
|
|
244
236
|
}
|
|
@@ -251,12 +243,10 @@ export function _load_yaml(p: string): JsonObject {
|
|
|
251
243
|
return _isObject(data) ? data : {};
|
|
252
244
|
}
|
|
253
245
|
|
|
254
|
-
|
|
255
246
|
interface ConcernDef extends JsonObject {
|
|
256
247
|
name: string;
|
|
257
248
|
}
|
|
258
249
|
|
|
259
|
-
|
|
260
250
|
/**
|
|
261
251
|
* Per-concern tool filter — the `tools:` key.
|
|
262
252
|
*
|
|
@@ -424,7 +414,6 @@ export function _resolve_concerns(
|
|
|
424
414
|
return out;
|
|
425
415
|
}
|
|
426
416
|
|
|
427
|
-
|
|
428
417
|
/**
|
|
429
418
|
* Write the raw stdin payload to a capture directory when
|
|
430
419
|
* `AGENT_HOOK_CAPTURE_DIR` is set. Fail-silent: any IO / JSON error must
|
|
@@ -506,6 +495,7 @@ interface RunResult {
|
|
|
506
495
|
rc: number;
|
|
507
496
|
stderr: string;
|
|
508
497
|
stdout: string;
|
|
498
|
+
/** Elapsed ms, NOT floored — floored where STORED. See `concern_timings.ts`. */
|
|
509
499
|
duration_ms: number;
|
|
510
500
|
}
|
|
511
501
|
|
|
@@ -570,10 +560,10 @@ function _resolve_tsx_invocation(
|
|
|
570
560
|
* Escape hatch: AGENT_CONFIG_HOOKS_ISOLATED=1 forces the historical
|
|
571
561
|
* spawn-per-concern path (also used by the bench harness for A/B numbers).
|
|
572
562
|
*
|
|
573
|
-
* Known trade-off vs the spawn path:
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
563
|
+
* Known trade-off vs the spawn path: a kill-timeout cannot preempt in-process
|
|
564
|
+
* synchronous code, so a slow concern is bounded on neither route — see
|
|
565
|
+
* `SPAWN_TIMEOUT_MS`. A CRASH is caught here, surfaces as rc 3, and the caller
|
|
566
|
+
* resolves it by declared severity.
|
|
577
567
|
*/
|
|
578
568
|
/**
|
|
579
569
|
* ## Why this still re-serialises the envelope per concern (step 1.1, MEASURED NULL)
|
|
@@ -680,10 +670,10 @@ function _run_concern_inproc(
|
|
|
680
670
|
}
|
|
681
671
|
clearHookStdinOverride();
|
|
682
672
|
}
|
|
683
|
-
|
|
684
|
-
return { rc, stderr: err, stdout: out, duration_ms: elapsed };
|
|
673
|
+
return { rc, stderr: err, stdout: out, duration_ms: performance.now() - started };
|
|
685
674
|
}
|
|
686
675
|
|
|
676
|
+
|
|
687
677
|
function _run_concern(concern: ConcernDef, envelope: JsonObject): RunResult {
|
|
688
678
|
// In-process fast path — the default whenever the concern is in the
|
|
689
679
|
// static registry (all manifest concerns; parity is CI-enforced).
|
|
@@ -734,31 +724,31 @@ function _run_concern(concern: ConcernDef, envelope: JsonObject): RunResult {
|
|
|
734
724
|
encoding: "utf-8",
|
|
735
725
|
cwd: workspace,
|
|
736
726
|
env: concern_env,
|
|
737
|
-
timeout:
|
|
727
|
+
timeout: SPAWN_TIMEOUT_MS, // historical bound; `SPAWN_TIMEOUT_MS` says why
|
|
738
728
|
});
|
|
739
|
-
const elapsed =
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
const typeName =
|
|
745
|
-
err.code === "ETIMEDOUT" ? "TimeoutExpired" : err.name || "OSError";
|
|
729
|
+
const elapsed = performance.now() - started;
|
|
730
|
+
// Three ways a spawn produces no verdict; `classifySpawnResult` owns the
|
|
731
|
+
// reading, this writes the record and carries the code.
|
|
732
|
+
const outcome = classifySpawnResult(proc.error, proc.status, proc.signal);
|
|
733
|
+
if (outcome.issueDetail !== null) {
|
|
746
734
|
log_dispatch_issue(
|
|
747
735
|
workspace,
|
|
748
736
|
String(concern["name"] || "unknown"),
|
|
749
737
|
"execution_failed",
|
|
750
|
-
|
|
738
|
+
outcome.issueDetail,
|
|
751
739
|
fix_hint(),
|
|
752
740
|
);
|
|
741
|
+
}
|
|
742
|
+
if (outcome.noVerdict) {
|
|
753
743
|
return {
|
|
754
|
-
rc:
|
|
755
|
-
stderr: `${String(concern["name"])}: ${
|
|
744
|
+
rc: outcome.rc,
|
|
745
|
+
stderr: `${String(concern["name"])}: ${String(outcome.stderrNote)}\n${proc.stderr || ""}`,
|
|
756
746
|
stdout: "",
|
|
757
747
|
duration_ms: elapsed,
|
|
758
748
|
};
|
|
759
749
|
}
|
|
760
750
|
return {
|
|
761
|
-
rc:
|
|
751
|
+
rc: outcome.rc,
|
|
762
752
|
stderr: proc.stderr || "",
|
|
763
753
|
stdout: proc.stdout || "",
|
|
764
754
|
duration_ms: elapsed,
|
|
@@ -796,6 +786,7 @@ interface FeedbackEntry extends JsonObject {
|
|
|
796
786
|
concern: string;
|
|
797
787
|
}
|
|
798
788
|
|
|
789
|
+
|
|
799
790
|
/**
|
|
800
791
|
* Write per-concern feedback files + summary rollup.
|
|
801
792
|
*
|
|
@@ -1064,7 +1055,7 @@ function _parse_args(argv: string[]): Args {
|
|
|
1064
1055
|
process.stderr.write(
|
|
1065
1056
|
`dispatch_hook: the following arguments are required: ${missing.join(", ")}\n`,
|
|
1066
1057
|
);
|
|
1067
|
-
process.exit(
|
|
1058
|
+
process.exit(EXIT_USAGE);
|
|
1068
1059
|
}
|
|
1069
1060
|
return args;
|
|
1070
1061
|
}
|
|
@@ -1251,6 +1242,15 @@ export function main(argv?: string[]): number {
|
|
|
1251
1242
|
}
|
|
1252
1243
|
}
|
|
1253
1244
|
|
|
1245
|
+
// Step 3.1 — the bundle we execute must be the bundle the build produced.
|
|
1246
|
+
// Beside `denyOnStdinFailure` for its reason: the verdict needs the resolved
|
|
1247
|
+
// concern list. Rules: `bundle_integrity.ts`.
|
|
1248
|
+
if (_IN_BUNDLE) {
|
|
1249
|
+
const stop = runBundleIntegrityGate(fileURLToPath(import.meta.url), args.platform,
|
|
1250
|
+
args.event, concerns.some((c) => !_is_advisory(c)));
|
|
1251
|
+
if (stop !== null) return stop;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
1254
|
const envelope = _build_envelope(args, payload_text);
|
|
1255
1255
|
const session_id = _resolve_session_id(envelope);
|
|
1256
1256
|
const started_at = _now_iso();
|
|
@@ -1286,6 +1286,7 @@ export function main(argv?: string[]): number {
|
|
|
1286
1286
|
// classes are present, which any concern loses, the single measurement pass,
|
|
1287
1287
|
// and the at-most-four envelope shapes — so the loop below reads a shape
|
|
1288
1288
|
// rather than re-deriving one. Rationale and cost model: payload_stub.ts.
|
|
1289
|
+
const timing_samples: ConcernTimingSample[] = [];
|
|
1289
1290
|
const keep_by_concern = concerns.map(
|
|
1290
1291
|
(c) => [c, _concern_body_classes(c)] as const,
|
|
1291
1292
|
);
|
|
@@ -1308,17 +1309,22 @@ export function main(argv?: string[]): number {
|
|
|
1308
1309
|
const concern_started = _now_iso();
|
|
1309
1310
|
const { rc: rawRcResult, stderr: stderr_text, stdout: stdout_text, duration_ms } =
|
|
1310
1311
|
_run_concern(concern, concern_envelope);
|
|
1312
|
+
timing_samples.push({ concern: String(concern["name"]), duration_us: duration_ms * 1000 });
|
|
1311
1313
|
let rc = rawRcResult;
|
|
1312
1314
|
const raw_rc = rc;
|
|
1313
1315
|
if (rc >= 3) {
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
}
|
|
1316
|
+
// Resolved by DECLARED SEVERITY, no longer by `fail_closed:`. Every
|
|
1317
|
+
// crash path has already written an `execution_failed` row, so a refusal
|
|
1318
|
+
// here is traceable to a named failure. See `_resolve_execution_failure`.
|
|
1319
|
+
rc = _resolve_execution_failure(concern, refusal_retry);
|
|
1319
1320
|
if (stderr_text) {
|
|
1320
1321
|
process.stderr.write(stderr_text);
|
|
1321
1322
|
}
|
|
1323
|
+
// The escape, printed only where a denial can repeat — `stop` is bounded
|
|
1324
|
+
// by the one-retry clause above. Reasoning: `noVerdictRefusalNotice`.
|
|
1325
|
+
if (rc === EXIT_BLOCK && !refusal_retry) {
|
|
1326
|
+
process.stderr.write(noVerdictRefusalNotice(String(concern["name"])));
|
|
1327
|
+
}
|
|
1322
1328
|
}
|
|
1323
1329
|
// P0.2 severity ceiling: an advisory concern can never block, on any host.
|
|
1324
1330
|
// This covers BOTH the concern emitting EXIT_BLOCK directly and the
|
|
@@ -1376,7 +1382,7 @@ export function main(argv?: string[]): number {
|
|
|
1376
1382
|
severity: _severity_for(rc),
|
|
1377
1383
|
decision: (reply["decision"] || _severity_for(rc)) as JsonValue,
|
|
1378
1384
|
reason: (reply["reason"] ?? null) as JsonValue,
|
|
1379
|
-
duration_ms,
|
|
1385
|
+
duration_ms: Math.floor(duration_ms),
|
|
1380
1386
|
started_at: concern_started,
|
|
1381
1387
|
completed_at: _now_iso(),
|
|
1382
1388
|
fail_closed: Boolean(concern["fail_closed"]),
|
|
@@ -1392,6 +1398,7 @@ export function main(argv?: string[]): number {
|
|
|
1392
1398
|
});
|
|
1393
1399
|
}
|
|
1394
1400
|
const final_rc = _reduce(rcs);
|
|
1401
|
+
writeConcernTimings(String(envelope["event"] ?? ""), String(envelope["platform"] ?? ""), timing_samples);
|
|
1395
1402
|
_write_feedback(envelope, session_id, feedback_entries, final_rc, started_at);
|
|
1396
1403
|
_record_rule_trips(envelope, feedback_entries);
|
|
1397
1404
|
if (context_blocks.length > 0 && final_rc === EXIT_ALLOW) {
|
|
@@ -1459,7 +1466,6 @@ function _sortedRepr(s: ReadonlySet<string>): string {
|
|
|
1459
1466
|
*/
|
|
1460
1467
|
let _stdin_read_failed: string | null = null;
|
|
1461
1468
|
|
|
1462
|
-
|
|
1463
1469
|
// Bundle-safety: never auto-run when inlined into an esbuild bundle, where
|
|
1464
1470
|
// every module shares the bundle's `import.meta.url` (declare at top of file).
|
|
1465
1471
|
function _isCliEntry(): boolean {
|
|
@@ -86,11 +86,10 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
86
86
|
import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
|
|
87
87
|
import { readHookStdin } from './hook_stdin.js';
|
|
88
88
|
import { atomic_write_json } from './state_io.js';
|
|
89
|
+
import { EXIT_ALLOW, EXIT_WARN } from './exit_codes.js';
|
|
89
90
|
|
|
90
|
-
const EXIT_ALLOW = 0;
|
|
91
91
|
// Severity is taken from the EXIT CODE, not from the `decision` field in the
|
|
92
92
|
// stdout payload — see the file header for why this never blocks on `claude`.
|
|
93
|
-
const EXIT_WARN = 2;
|
|
94
93
|
|
|
95
94
|
/** Committed threshold (roadmap 5.1): minimum current line count of the
|
|
96
95
|
* replaced file before this concern has anything to say. */
|
|
@@ -253,6 +253,7 @@ import {
|
|
|
253
253
|
import { unwrap, type JsonObject, type JsonValue } from './envelope.js';
|
|
254
254
|
import { readHookStdin } from './hook_stdin.js';
|
|
255
255
|
import { atomic_write_json, is_replay_mode } from './state_io.js';
|
|
256
|
+
import { EXIT_WARN } from './exit_codes.js';
|
|
256
257
|
|
|
257
258
|
/** Default fire threshold — the council's high-risk shape (roadmap 5.1). */
|
|
258
259
|
export const MUTATION_LINE_THRESHOLD = 50;
|
|
@@ -319,7 +320,6 @@ export function isSafeTranscriptPath(
|
|
|
319
320
|
// reported at exit 2 so `host_semantics.emitFor` reduces it to severity
|
|
320
321
|
// `"warn"` and forwards `additional_context`; see the file header for why
|
|
321
322
|
// this exit code never actually blocks the turn on `claude`.
|
|
322
|
-
const EXIT_WARN = 2;
|
|
323
323
|
|
|
324
324
|
/** One `git diff --numstat` row: added/deleted line counts + the path. */
|
|
325
325
|
export interface NumstatRow {
|
|
@@ -52,8 +52,8 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
52
52
|
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
|
+
import { EXIT_ALLOW, EXIT_BLOCK } from './exit_codes.js';
|
|
55
56
|
|
|
56
|
-
const EXIT_ALLOW = 0;
|
|
57
57
|
// MUST equal dispatch_hook.EXIT_BLOCK. The dispatcher's internal ladder is
|
|
58
58
|
// 0 allow / 1 block / 2 warn — NOT the 2-means-block shape a PreToolUse guard
|
|
59
59
|
// reads naturally from Claude's own native contract. This constant was 2 when
|
|
@@ -61,7 +61,6 @@ const EXIT_ALLOW = 0;
|
|
|
61
61
|
// and the gate emitted advisory context while the operation went through.
|
|
62
62
|
// Pinned against the dispatcher's export by
|
|
63
63
|
// tests/hooks/concern_block_exit_parity.test.ts.
|
|
64
|
-
const EXIT_BLOCK = 1;
|
|
65
64
|
|
|
66
65
|
export const STATE_FILE = path.join("agents", "state", "evidence-dispatch.json");
|
|
67
66
|
|