@event4u/agent-config 16.2.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 +89 -237
- 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 +4 -4
- 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/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/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/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/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-system-capture/references/import-procedure.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/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/monorepo-workspace/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/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 +2 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- 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-IGD6ERX6.js → chunk-JQVYKIZA.js} +10 -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-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-NQ7WT43P.js} +1186 -244
- 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-7XGBX6ZH.js → chunk-RQNNW7IF.js} +1314 -560
- package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-TRI6DQZ6.js} +2781 -340
- 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 +1167 -234
- 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 +127 -75
- 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 +5357 -6656
- 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 +2080 -1024
- 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 +31965 -27154
- 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 +6 -0
- package/dist/shared/skillRanking.js +74 -13
- package/docs/contracts/settings-classes.md +7 -5
- 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/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/config/agent-settings.template.yml +62 -22
- package/src/config/continuity-surface.json +7 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +96 -3
- package/src/config/gate-violation-baselines.json +17 -9
- 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/routing-coverage-seed.json +24 -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 +23 -71
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- 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/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_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/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/prompt_shape.ts +46 -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/skill_origin.ts +254 -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 +77 -2
- 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/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +243 -12
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/check_enforcement_matrix.ts +377 -20
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +116 -4
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_kernel_edit_ratified.ts +49 -11
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- 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 +33 -1
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +150 -9
- package/src/scripts/hooks/block_config_weakening.ts +67 -2
- package/src/scripts/hooks/block_plumbing_writes.ts +29 -1
- 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/dispatch_hook.ts +52 -52
- 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/one_question_per_ask_hook.ts +41 -25
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/rule_inject_hook.ts +757 -63
- package/src/scripts/hooks/table_fingerprint.ts +21 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +64 -8
- package/src/scripts/hooks/turn_end_gate_hook.ts +84 -0
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +72 -185
- 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_hook_manifest.ts +53 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_rule_law_section.ts +517 -0
- 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/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +216 -8
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_single_token_triggers.ts +277 -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/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/review-findings.schema.json +3 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/self_review_gate.ts +62 -7
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- 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 -5
- package/src/server/schemas/settings.ts +10 -0
- package/src/shared/skillRanking.ts +117 -11
- package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
|
@@ -9,6 +9,27 @@ import { createHash } from 'node:crypto';
|
|
|
9
9
|
* dispatcher: `dispatch_hook` → `host_semantics` → `host_lowering` is a live
|
|
10
10
|
* import chain, so the reverse edge would be a cycle.
|
|
11
11
|
*
|
|
12
|
+
* THE RETIRED ARGUMENT, kept because both callers point here for it rather
|
|
13
|
+
* than restating it. `dispatch_hook._manifest_fingerprint` argued AGAINST a
|
|
14
|
+
* cryptographic hash on two grounds, and by the time road-to-blocking-
|
|
15
|
+
* severities 3.1 read that header the body had already been delegating here for
|
|
16
|
+
* a release — so a reader checking whether the dispatcher resists a CRAFTED
|
|
17
|
+
* sibling met a disclaimer the code had stopped making. Both grounds were
|
|
18
|
+
* re-measured when this module was extracted, and both were stale:
|
|
19
|
+
*
|
|
20
|
+
* - "`require('node:crypto')` costs 8 ms of process start, which is most of
|
|
21
|
+
* what the precompiled manifest exists to save." The module is already
|
|
22
|
+
* loaded: `dist/hooks/dispatch.js` carries 23 top-level
|
|
23
|
+
* `import … from "node:crypto"` statements from other parts of the graph,
|
|
24
|
+
* so the cost is paid whether this function uses it or not.
|
|
25
|
+
* - "An FNV-1a loop runs in about 0.2 ms and is the right trade." SHA-256
|
|
26
|
+
* measured FASTER — 0.106 ms against 0.113 ms over the 99,792-byte
|
|
27
|
+
* manifest — because Node's digest is native and the loop was that many
|
|
28
|
+
* interpreted `charCodeAt` calls.
|
|
29
|
+
*
|
|
30
|
+
* Both readers now point here instead of restating it, so the argument and the
|
|
31
|
+
* numbers that retired it cannot part company again.
|
|
32
|
+
*
|
|
12
33
|
* DELIBERATELY CONTENT-DERIVED, NOT MTIME. The first version of the manifest
|
|
13
34
|
* fast path compared mtimes and that was a measured defect, not a theoretical
|
|
14
35
|
* one: on a fresh `actions/checkout` both files carry the checkout timestamp in
|
|
@@ -22,12 +22,31 @@
|
|
|
22
22
|
* activates only when `enabled` is true AND the org pack supplied an
|
|
23
23
|
* endpoint, an org id, and a salt. An external clone of this repository
|
|
24
24
|
* carries the key names and no values, so copying the tree cannot reach the
|
|
25
|
-
* write path. When inactive this concern performs zero
|
|
26
|
-
* operations — no log write, no
|
|
25
|
+
* write path. When inactive this concern performs zero TELEMETRY file
|
|
26
|
+
* operations — no log write, no spool, no directory under the configured
|
|
27
|
+
* output path — and zero network calls.
|
|
27
28
|
* (It does read `.agent-settings.yml`, once per process and memoised: the
|
|
28
29
|
* settings file is how it learns it is off, the same as the artefact-
|
|
29
30
|
* engagement surface it mirrors.)
|
|
30
31
|
*
|
|
32
|
+
* THAT SENTENCE USED TO READ "no directory creation", UNQUALIFIED, AND IS
|
|
33
|
+
* NARROWED RATHER THAN QUIETLY LEFT STANDING. The foreign-MCP recorder below
|
|
34
|
+
* writes `agents/runtime/neighbour-tool-use.json` on an install that never
|
|
35
|
+
* enabled telemetry, and creates that directory and a lock sentinel beside it.
|
|
36
|
+
* That is deliberate — the store is a local census input, not telemetry, and
|
|
37
|
+
* gating it on the org switch would print `0` everywhere (roadmap decision D9)
|
|
38
|
+
* — but it IS a file operation, so the guarantee now says which operations it
|
|
39
|
+
* covers. An unqualified claim this file's own code contradicts is worse than
|
|
40
|
+
* the narrower one it is replaced by.
|
|
41
|
+
*
|
|
42
|
+
* NOT REACHED YET, AND SAYING SO HERE BECAUSE THIS IS WHERE A READER LOOKS.
|
|
43
|
+
* The manifest entry for this concern carries `tools: [Skill]`, which the
|
|
44
|
+
* dispatcher matches exactly, so it is not invoked for an MCP call at all and
|
|
45
|
+
* the branch below is dead in production. Held as the
|
|
46
|
+
* `mcp-recorder-unreachable-behind-the-tools-filter` blocker on
|
|
47
|
+
* road-to-neighbours-that-pull-their-weight: the manifest is a gated
|
|
48
|
+
* governance surface and the council split on the edit rather than converging.
|
|
49
|
+
*
|
|
31
50
|
* NO OUTBOUND CALL EXISTS HERE, DELIBERATELY. Transport is Phase 2 and is
|
|
32
51
|
* blocked on `sink-choice`; org-wide enablement is Phase 3 and is blocked on
|
|
33
52
|
* `dpo-signoff`. This concern appends to a local JSONL file and stops.
|
|
@@ -55,7 +74,12 @@ import {
|
|
|
55
74
|
FLUSH_SESSION_END,
|
|
56
75
|
spool_path_for,
|
|
57
76
|
} from '../../agent-src/templates/scripts/telemetry/transport.js';
|
|
58
|
-
import {
|
|
77
|
+
import {
|
|
78
|
+
FOREIGN_TOOL_USE_REL,
|
|
79
|
+
MCP_TOOL_PREFIX,
|
|
80
|
+
usageDay,
|
|
81
|
+
} from '../_lib/neighbour_tool_use.js';
|
|
82
|
+
import { is_replay_mode, update_json_under_lock } from './state_io.js';
|
|
59
83
|
import { readHookStdin } from './hook_stdin.js';
|
|
60
84
|
import { EXIT_ALLOW } from './exit_codes.js';
|
|
61
85
|
|
|
@@ -247,7 +271,30 @@ function processEnvelope(envelope: JsonValue, consumer_root: string): number {
|
|
|
247
271
|
if (!isObject(envelope)) return EXIT_ALLOW;
|
|
248
272
|
|
|
249
273
|
const payload = unwrapPayload(envelope);
|
|
250
|
-
|
|
274
|
+
const tool = extractToolName(payload);
|
|
275
|
+
if (tool !== SKILL_TOOL_NAME) {
|
|
276
|
+
// The other half of this slot's observation, and the only half a
|
|
277
|
+
// `post_tool_use` envelope can supply: the tool's NAME. The MCP
|
|
278
|
+
// fingerprint store wants a tool DEFINITION, which this envelope
|
|
279
|
+
// never carries (roadmap decision D2), so what is recorded here is
|
|
280
|
+
// what was actually seen. Rooted at the settings directory, not at
|
|
281
|
+
// the session cwd, for the same reason the Class-A log below is.
|
|
282
|
+
if (tool !== null && tool.startsWith(MCP_TOOL_PREFIX)) {
|
|
283
|
+
// The mutator's cast is safe at the only place that matters:
|
|
284
|
+
// the reader in `neighbour_tool_use` drops any value that is
|
|
285
|
+
// not a string, so a hand-edited store cannot widen this.
|
|
286
|
+
// Kept OUT of the argument list below — esbuild preserves a
|
|
287
|
+
// comment in that position and it would cost the shared
|
|
288
|
+
// bundle ~190 bytes of prose nothing executes.
|
|
289
|
+
const day = usageDay(new Date());
|
|
290
|
+
update_json_under_lock<Record<string, string>>(
|
|
291
|
+
path.join(readSettingsFor(consumer_root).root, FOREIGN_TOOL_USE_REL),
|
|
292
|
+
(seen) => (seen[tool] === day ? null : ({ ...seen, [tool]: day } as Record<string, string>)),
|
|
293
|
+
{ blocking: false },
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
return EXIT_ALLOW;
|
|
297
|
+
}
|
|
251
298
|
|
|
252
299
|
const { settings, text, root } = readSettingsFor(consumer_root);
|
|
253
300
|
if (!settings.active) return EXIT_ALLOW;
|
|
@@ -339,11 +386,18 @@ export function main(): number {
|
|
|
339
386
|
|
|
340
387
|
// Bundle-safety: never auto-run when inlined into an esbuild bundle, where
|
|
341
388
|
// every module shares the bundle's `import.meta.url` (see cmd_migrate.ts).
|
|
389
|
+
//
|
|
390
|
+
// The bundle test is at the CALL SITE rather than at the top of
|
|
391
|
+
// `_isCliEntry`, and that placement is the whole point. Inside the function
|
|
392
|
+
// esbuild folds the condition to `if (true) return false` and then emits the
|
|
393
|
+
// nine unreachable lines below it anyway — measured at 475 bytes of dead code
|
|
394
|
+
// in a bundle `check_hook_bundle_composition` caps. Guarding the call instead
|
|
395
|
+
// makes the whole statement `if (false)`, which esbuild drops, taking the now
|
|
396
|
+
// unreferenced function with it. Behavior outside the bundle is unchanged:
|
|
397
|
+
// `__AGENT_CONFIG_BUNDLE__` is undeclared there, the first operand is true,
|
|
398
|
+
// and `!__AGENT_CONFIG_BUNDLE__` is never evaluated — so no ReferenceError.
|
|
342
399
|
declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
|
|
343
400
|
function _isCliEntry(): boolean {
|
|
344
|
-
if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) {
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
401
|
if (process.argv[1] === undefined) return false;
|
|
348
402
|
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
349
403
|
if (import.meta.url === argvUrl) return true;
|
|
@@ -353,4 +407,6 @@ function _isCliEntry(): boolean {
|
|
|
353
407
|
return false;
|
|
354
408
|
}
|
|
355
409
|
}
|
|
356
|
-
if (
|
|
410
|
+
if (typeof __AGENT_CONFIG_BUNDLE__ === 'undefined' || !__AGENT_CONFIG_BUNDLE__) {
|
|
411
|
+
if (_isCliEntry()) process.exit(main());
|
|
412
|
+
}
|
|
@@ -186,6 +186,17 @@ export { readTurnRunState };
|
|
|
186
186
|
// Detector E, extracted to `_lib` where its prose costs no ratchet debt.
|
|
187
187
|
// Re-exported so every existing importer of this module is unchanged.
|
|
188
188
|
import { detectDroppedDecision } from '../_lib/dropped_decision.js';
|
|
189
|
+
// Step 3.2 of `road-to-a-graph-that-feeds-the-gate` — the shadow feeder. It
|
|
190
|
+
// lives in `_lib` for the reason every other extraction here does: this file
|
|
191
|
+
// sits against a 1,500-line shrink-only source budget, and the module it would
|
|
192
|
+
// otherwise grow into is one a recall reading has to be able to open on its own.
|
|
193
|
+
import {
|
|
194
|
+
appendFeederRow,
|
|
195
|
+
buildFeederRow,
|
|
196
|
+
type FeederLayer,
|
|
197
|
+
graphUntestedVerdict,
|
|
198
|
+
} from '../_lib/graph_feeder_record.js';
|
|
199
|
+
import { type GraphState, graphState } from '../code_graph/detect.js';
|
|
189
200
|
import { isVerificationCommand } from '../_lib/verification_command.js';
|
|
190
201
|
// Round 8 — the record path detector C prefers over its own regex. The regex
|
|
191
202
|
// reads a command's TEXT and `echo test` matches it; these read what the run
|
|
@@ -215,6 +226,7 @@ import {
|
|
|
215
226
|
readInstallBoundary,
|
|
216
227
|
sessionRefusalFile,
|
|
217
228
|
sessionShadowFile,
|
|
229
|
+
shadowSetBy,
|
|
218
230
|
type RefusalRecord,
|
|
219
231
|
type ShadowLayer,
|
|
220
232
|
type ShadowRecord,
|
|
@@ -1276,6 +1288,65 @@ function runDetectors(inputs: DetectorInputs): Finding[] {
|
|
|
1276
1288
|
return findings;
|
|
1277
1289
|
}
|
|
1278
1290
|
|
|
1291
|
+
/**
|
|
1292
|
+
* Write the graph feeder row for ONE stop (step 3.2).
|
|
1293
|
+
*
|
|
1294
|
+
* Called from both stop paths with the findings that path already computed, so
|
|
1295
|
+
* the F verdict in the row is the SAME verdict the gate acted on — never a
|
|
1296
|
+
* second evaluation written beside it, which is the shape
|
|
1297
|
+
* `obligation_settle_hook.ts` names as measuring nothing.
|
|
1298
|
+
*
|
|
1299
|
+
* It changes no exit code, and the whole body is wrapped: a stop that crashed on
|
|
1300
|
+
* its own instrument would be a new failure mode on a path that is supposed to
|
|
1301
|
+
* cost nothing. The graph half is skipped outright unless the state is `fresh`
|
|
1302
|
+
* or `edited` — an answer from an index that predates the change is not evidence
|
|
1303
|
+
* about the change.
|
|
1304
|
+
*/
|
|
1305
|
+
function recordGraphFeeder(
|
|
1306
|
+
inputs: DetectorInputs,
|
|
1307
|
+
findings: readonly Finding[],
|
|
1308
|
+
layer: FeederLayer,
|
|
1309
|
+
): void {
|
|
1310
|
+
if (is_replay_mode()) return;
|
|
1311
|
+
try {
|
|
1312
|
+
let state: GraphState;
|
|
1313
|
+
try {
|
|
1314
|
+
state = graphState(inputs.workspaceRoot);
|
|
1315
|
+
} catch {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
// No graph at all is the silent case, exactly as it is for the context
|
|
1319
|
+
// hook: a consumer who never builds one never grows this file.
|
|
1320
|
+
if (state === 'absent') return;
|
|
1321
|
+
// The SAME path set detector F reads, filtered by the SAME predicate.
|
|
1322
|
+
// A completion review found the two arms running over different inputs:
|
|
1323
|
+
// the feeder passed every edit path while F filters to production
|
|
1324
|
+
// source, so the graph arm would have fired on precisely the turns F is
|
|
1325
|
+
// silent for — a recall comparison between two detectors answering
|
|
1326
|
+
// different questions, which is worse than no comparison.
|
|
1327
|
+
const paths = inputs.toolCalls
|
|
1328
|
+
.filter((c) => _EDIT_TOOLS.has(c.name) && c.path !== undefined)
|
|
1329
|
+
.map((c) => c.path as string)
|
|
1330
|
+
.filter(_isProductionSource);
|
|
1331
|
+
const f = findings.find((x) => x.detector === 'untested');
|
|
1332
|
+
appendFeederRow(
|
|
1333
|
+
inputs.workspaceRoot,
|
|
1334
|
+
inputs.sessionKey,
|
|
1335
|
+
buildFeederRow({
|
|
1336
|
+
turn: inputs.turnOrdinal,
|
|
1337
|
+
layer,
|
|
1338
|
+
state,
|
|
1339
|
+
fFired: f !== undefined,
|
|
1340
|
+
fMode: f?.mode ?? null,
|
|
1341
|
+
paths,
|
|
1342
|
+
graph: graphUntestedVerdict(inputs.workspaceRoot, state, paths),
|
|
1343
|
+
}),
|
|
1344
|
+
);
|
|
1345
|
+
} catch {
|
|
1346
|
+
// An instrument is never a reason to change what the gate does.
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1279
1350
|
/**
|
|
1280
1351
|
* Record what this retry WOULD have been refused for, then let it end.
|
|
1281
1352
|
*
|
|
@@ -1289,6 +1360,14 @@ function recordShadow(inputs: DetectorInputs, layer: ShadowLayer): void {
|
|
|
1289
1360
|
if (is_replay_mode()) return;
|
|
1290
1361
|
try {
|
|
1291
1362
|
const findings = runDetectors(inputs);
|
|
1363
|
+
// On `refused_turn` the answer is `ours` by construction — that marker
|
|
1364
|
+
// is this gate's own and nothing else writes it. On `stop_hook_active`
|
|
1365
|
+
// the host sets the flag for ANY stop hook's block, so it has to be
|
|
1366
|
+
// read from our own refusal record rather than assumed.
|
|
1367
|
+
const setBy = layer === 'refused_turn'
|
|
1368
|
+
? 'ours'
|
|
1369
|
+
: shadowSetBy(inputs.workspaceRoot, inputs.sessionKey);
|
|
1370
|
+
recordGraphFeeder(inputs, findings, layer);
|
|
1292
1371
|
const file = sessionShadowFile(inputs.workspaceRoot, inputs.sessionKey);
|
|
1293
1372
|
let prev: ShadowRecord | null = null;
|
|
1294
1373
|
try {
|
|
@@ -1303,6 +1382,7 @@ function recordShadow(inputs: DetectorInputs, layer: ShadowLayer): void {
|
|
|
1303
1382
|
turnOrdinal: inputs.turnOrdinal,
|
|
1304
1383
|
at: new Date().toISOString(),
|
|
1305
1384
|
layer,
|
|
1385
|
+
setBy,
|
|
1306
1386
|
}) as unknown as Record<string, unknown>,
|
|
1307
1387
|
);
|
|
1308
1388
|
} catch {
|
|
@@ -1361,6 +1441,10 @@ export function main(): number {
|
|
|
1361
1441
|
// warranted"; there is no second, configurable notion of warranted layered
|
|
1362
1442
|
// on top of it.
|
|
1363
1443
|
const findings = runDetectors(inputs);
|
|
1444
|
+
// The live verdict's own row. It is written BEFORE the branch below, so a
|
|
1445
|
+
// turn the gate allows and a turn it refuses are both in the record — a
|
|
1446
|
+
// recall reading needs the allowed turns as its negative arm.
|
|
1447
|
+
recordGraphFeeder(inputs, findings, 'live');
|
|
1364
1448
|
if (findings.length === 0) return EXIT_ALLOW;
|
|
1365
1449
|
|
|
1366
1450
|
markRefusedTurn(
|
|
@@ -23,11 +23,14 @@ import fs from "node:fs";
|
|
|
23
23
|
import path from "node:path";
|
|
24
24
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
25
25
|
|
|
26
|
+
import { enforcementFor } from "./check_enforcement_matrix.js";
|
|
26
27
|
import {
|
|
27
28
|
type JsonObject,
|
|
28
29
|
type JsonValue,
|
|
29
30
|
_load_yaml,
|
|
30
31
|
} from "./hooks/dispatch_hook.js";
|
|
32
|
+
import { loadHostLowering } from "./hooks/host_lowering.js";
|
|
33
|
+
import { type SlotReading, readSlots } from "./report_enforcement_drift.js";
|
|
31
34
|
|
|
32
35
|
// src/scripts/hooks_status.ts → parents[1] is the repo root (.../parents[2]
|
|
33
36
|
// in the Python which lives one level deeper relative computation).
|
|
@@ -90,6 +93,18 @@ export interface PlatformRow {
|
|
|
90
93
|
*/
|
|
91
94
|
ask: AskShape;
|
|
92
95
|
bindings: Record<string, string[]>;
|
|
96
|
+
/**
|
|
97
|
+
* For each slot that binds at least one `blocking` concern, what that host's
|
|
98
|
+
* slot can actually carry — `refusal`, `warning-only`, `unverified` or
|
|
99
|
+
* `proof-expired` (road-to-blocking-severities 1.2).
|
|
100
|
+
*
|
|
101
|
+
* Slots with no blocking concern are ABSENT rather than present with a
|
|
102
|
+
* value, so a reader cannot mistake "nothing here claims to refuse" for a
|
|
103
|
+
* capability reading. Derived from `host_lowering.yaml`, never from the
|
|
104
|
+
* manifest: the manifest declares intent and only the lowering table records
|
|
105
|
+
* whether a refusal can land.
|
|
106
|
+
*/
|
|
107
|
+
blocking_enforcement: Record<string, string>;
|
|
93
108
|
hint: string | null;
|
|
94
109
|
}
|
|
95
110
|
|
|
@@ -123,10 +138,79 @@ function _bridge_status(project_root: string, rel_path: string): string {
|
|
|
123
138
|
return stat && stat.isFile() ? "installed" : "missing";
|
|
124
139
|
}
|
|
125
140
|
|
|
141
|
+
/**
|
|
142
|
+
* `severity` per concern, read off the manifest this report already loaded.
|
|
143
|
+
*
|
|
144
|
+
* `(undeclared)` is folded into "not blocking": this report publishes the
|
|
145
|
+
* enforcement of concerns that CLAIM to refuse, and a concern that claims
|
|
146
|
+
* nothing has nothing to reconcile. `lint_hook_manifest` is what refuses an
|
|
147
|
+
* undeclared severity; duplicating that judgement here would put two answers
|
|
148
|
+
* in the tree.
|
|
149
|
+
*/
|
|
150
|
+
function _severities(manifest: JsonObject): Map<string, string> {
|
|
151
|
+
const out = new Map<string, string>();
|
|
152
|
+
const concerns = manifest["concerns"];
|
|
153
|
+
if (!_isObject(concerns)) {
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
for (const [name, spec] of Object.entries(concerns)) {
|
|
157
|
+
const sev = _isObject(spec) ? spec["severity"] : undefined;
|
|
158
|
+
if (typeof sev === "string") {
|
|
159
|
+
out.set(name, sev);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return out;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* What each slot carrying a `blocking` concern can actually do on this host.
|
|
167
|
+
*
|
|
168
|
+
* road-to-blocking-severities 1.2, the third surface. The decision and the
|
|
169
|
+
* vocabulary live in `check_enforcement_matrix`; this reads them rather than
|
|
170
|
+
* restating them, so the published document and this report cannot drift into
|
|
171
|
+
* two different answers to one question.
|
|
172
|
+
*
|
|
173
|
+
* Failure is SILENT and the field is simply absent. This is a read-only status
|
|
174
|
+
* report that the post-install smoke probe runs, and a malformed or missing
|
|
175
|
+
* lowering table must degrade it, never abort it — the gate is where a broken
|
|
176
|
+
* lowering table is supposed to fail.
|
|
177
|
+
*/
|
|
178
|
+
function _blocking_enforcement(
|
|
179
|
+
platform: string,
|
|
180
|
+
bindings: Record<string, string[]>,
|
|
181
|
+
severities: Map<string, string>,
|
|
182
|
+
): Record<string, string> {
|
|
183
|
+
const out: Record<string, string> = {};
|
|
184
|
+
let slots: SlotReading[];
|
|
185
|
+
try {
|
|
186
|
+
slots = readSlots(loadHostLowering(), platform).slots;
|
|
187
|
+
} catch {
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
const bySlot = new Map(slots.map((s) => [s.slot, s]));
|
|
191
|
+
for (const [event, concerns] of Object.entries(bindings)) {
|
|
192
|
+
if (!concerns.some((c) => severities.get(c) === "blocking")) {
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const row = bySlot.get(event);
|
|
196
|
+
out[event] = enforcementFor(
|
|
197
|
+
row === undefined
|
|
198
|
+
? "unlowerable"
|
|
199
|
+
: row.literal === null
|
|
200
|
+
? "null-block"
|
|
201
|
+
: row.effective === null
|
|
202
|
+
? "stale-proof"
|
|
203
|
+
: null,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
|
|
126
209
|
/** Build the runtime matrix as a plain object — JSON-serialisable. */
|
|
127
210
|
export function collect(project_root: string, manifest: JsonObject): StatusMatrix {
|
|
128
211
|
const platformsRaw = manifest["platforms"];
|
|
129
212
|
const platforms = _isObject(platformsRaw) ? platformsRaw : {};
|
|
213
|
+
const severities = _severities(manifest);
|
|
130
214
|
const rows: PlatformRow[] = [];
|
|
131
215
|
for (const platform of Object.keys(PLATFORM_BRIDGES)) {
|
|
132
216
|
const [rel, hint] = PLATFORM_BRIDGES[platform] as [string, string];
|
|
@@ -148,6 +232,7 @@ export function collect(project_root: string, manifest: JsonObject): StatusMatri
|
|
|
148
232
|
rows.push({
|
|
149
233
|
platform,
|
|
150
234
|
status,
|
|
235
|
+
blocking_enforcement: _blocking_enforcement(platform, bindings, severities),
|
|
151
236
|
bridge_path: rel || null,
|
|
152
237
|
fallback_only,
|
|
153
238
|
ask,
|
|
@@ -160,6 +245,23 @@ export function collect(project_root: string, manifest: JsonObject): StatusMatri
|
|
|
160
245
|
return { schema_version: 1, platforms: rows };
|
|
161
246
|
}
|
|
162
247
|
|
|
248
|
+
/**
|
|
249
|
+
* One short line per enforcement value, for the table.
|
|
250
|
+
*
|
|
251
|
+
* `unverified` says what is MISSING, never what the host cannot do — the same
|
|
252
|
+
* wording discipline `docs/enforcement-by-host.md` carries, and the reason this
|
|
253
|
+
* report distinguishes the two values at all.
|
|
254
|
+
*/
|
|
255
|
+
const _ENFORCEMENT_NOTE: Record<string, string> = {
|
|
256
|
+
refusal: "the slot denies, so a blocking verdict stops the call",
|
|
257
|
+
"proof-expired":
|
|
258
|
+
"the slot can deny; this package's `verified` citation has lapsed",
|
|
259
|
+
"warning-only":
|
|
260
|
+
"`block_exit` is null here — they run and warn, they cannot refuse",
|
|
261
|
+
unverified:
|
|
262
|
+
"no lowering row for this slot — nothing bound natively, nothing established",
|
|
263
|
+
};
|
|
264
|
+
|
|
163
265
|
const _STATUS_MARKER: Record<string, string> = {
|
|
164
266
|
installed: "✅ ",
|
|
165
267
|
missing: "❌ ",
|
|
@@ -199,6 +301,16 @@ export function _render_table(matrix: StatusMatrix): string {
|
|
|
199
301
|
for (const event of Object.keys(row.bindings).sort()) {
|
|
200
302
|
const concerns = row.bindings[event]?.join(", ") || "—";
|
|
201
303
|
lines.push(` ${event.padEnd(22)} → ${concerns}`);
|
|
304
|
+
// road-to-blocking-severities 1.2 — printed only where a concern on this
|
|
305
|
+
// slot DECLARES `blocking`, and worded so `unverified` never reads as a
|
|
306
|
+
// claim about the host.
|
|
307
|
+
const enforcement = row.blocking_enforcement[event];
|
|
308
|
+
if (enforcement !== undefined) {
|
|
309
|
+
lines.push(
|
|
310
|
+
` ${" ".repeat(22)} blocking concerns here: ${enforcement} — ` +
|
|
311
|
+
`${_ENFORCEMENT_NOTE[enforcement] ?? "see docs/enforcement-by-host.md"}`,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
202
314
|
}
|
|
203
315
|
if (row.hint) {
|
|
204
316
|
lines.push(` hint: ${row.hint}`);
|
|
@@ -214,6 +214,13 @@ export const OUTPUT_KEYS: readonly string[] = [
|
|
|
214
214
|
"toolResponse",
|
|
215
215
|
"tool_result",
|
|
216
216
|
"toolUseResult",
|
|
217
|
+
// The failure event's result body. A FAILING command on claude carries its
|
|
218
|
+
// stdout and stderr here and carries no `tool_response` at all, so without
|
|
219
|
+
// this line a failed `curl` of a hostile page would reach the model with
|
|
220
|
+
// nothing scanned — the one direction where the output is most likely to be
|
|
221
|
+
// attacker-shaped. Caught by this concern's own coverage test, which pins
|
|
222
|
+
// OUTPUT_KEYS as a superset of what the dispatcher serves.
|
|
223
|
+
"error",
|
|
217
224
|
// Generic spellings accepted since this concern shipped.
|
|
218
225
|
"output",
|
|
219
226
|
"result",
|