@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
|
@@ -476,10 +476,81 @@ const HOOK_MANIFEST_TRIPLE: Triple = {
|
|
|
476
476
|
},
|
|
477
477
|
};
|
|
478
478
|
|
|
479
|
+
const HOST_LOWERING_YAML = 'src/scripts/hooks/host_lowering.yaml';
|
|
480
|
+
const HOST_LOWERING_JSON = 'src/scripts/hooks/host_lowering.json';
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* The second compiled plumbing table, and it is here for the reason the first
|
|
484
|
+
* one is: the fingerprint hashes the YAML TEXT, so a comment-only edit to
|
|
485
|
+
* `host_lowering.yaml` invalidates the committed JSON while every parsed field
|
|
486
|
+
* stays byte-identical. That file is mostly comments — 16.8 kB of source
|
|
487
|
+
* compiling to 5.9 kB of data — so the comment-only case is the LIKELY one
|
|
488
|
+
* here, not the corner case.
|
|
489
|
+
*
|
|
490
|
+
* A stale sibling is slow, never wrong: `loadHostLowering` falls through to the
|
|
491
|
+
* YAML source on a fingerprint mismatch. So what this row protects is the
|
|
492
|
+
* measured 9 ms per dispatch, which would otherwise be given back silently and
|
|
493
|
+
* would surface only as the hook-latency gate flapping again.
|
|
494
|
+
*/
|
|
495
|
+
const HOST_LOWERING_TRIPLE: Triple = {
|
|
496
|
+
id: 'host-lowering-compiled',
|
|
497
|
+
output: HOST_LOWERING_JSON,
|
|
498
|
+
remedy: './scripts-run src/scripts/compile_hook_manifest --table host-lowering',
|
|
499
|
+
why:
|
|
500
|
+
'the compiled lowering table carries a fingerprint hashed over the YAML TEXT, so even a ' +
|
|
501
|
+
'comment-only edit to the source invalidates it — and no `task` target regenerates it',
|
|
502
|
+
sourcesOf() {
|
|
503
|
+
return { ok: true, sources: [{ kind: 'file', value: HOST_LOWERING_YAML }] };
|
|
504
|
+
},
|
|
505
|
+
regenerate(root, workDir) {
|
|
506
|
+
const outFile = path.join(workDir, 'host_lowering.json');
|
|
507
|
+
const tsx = path.join(
|
|
508
|
+
root,
|
|
509
|
+
'node_modules',
|
|
510
|
+
'.bin',
|
|
511
|
+
process.platform === 'win32' ? 'tsx.cmd' : 'tsx',
|
|
512
|
+
);
|
|
513
|
+
if (!fs.existsSync(tsx)) {
|
|
514
|
+
return {
|
|
515
|
+
ok: false,
|
|
516
|
+
reason: `no tsx at ${path.relative(root, tsx)} — run \`npm ci\` before this gate`,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
const res = spawnSync(
|
|
520
|
+
tsx,
|
|
521
|
+
[
|
|
522
|
+
path.join(root, 'src', 'scripts', 'compile_hook_manifest.ts'),
|
|
523
|
+
'--table',
|
|
524
|
+
'host-lowering',
|
|
525
|
+
'--out',
|
|
526
|
+
outFile,
|
|
527
|
+
],
|
|
528
|
+
{ cwd: root, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 },
|
|
529
|
+
);
|
|
530
|
+
if (res.status !== 0) {
|
|
531
|
+
return {
|
|
532
|
+
ok: false,
|
|
533
|
+
reason:
|
|
534
|
+
`compile_hook_manifest --table host-lowering exited ${String(res.status)}: ` +
|
|
535
|
+
`${(res.stderr ?? '').trim()}`,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
try {
|
|
539
|
+
return { ok: true, text: fs.readFileSync(outFile, 'utf8') };
|
|
540
|
+
} catch (e) {
|
|
541
|
+
return {
|
|
542
|
+
ok: false,
|
|
543
|
+
reason: `compile_hook_manifest reported success but wrote no readable file (${String(e)})`,
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
};
|
|
548
|
+
|
|
479
549
|
export const REGISTRY: readonly Triple[] = [
|
|
480
550
|
CENSUS_TRIPLE,
|
|
481
551
|
INSTALL_BUNDLE_TRIPLE,
|
|
482
552
|
HOOK_MANIFEST_TRIPLE,
|
|
553
|
+
HOST_LOWERING_TRIPLE,
|
|
483
554
|
];
|
|
484
555
|
|
|
485
556
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Composition gate for the self-hosted hook bundle: ONE YAML reader, and a
|
|
4
|
+
* byte ceiling.
|
|
5
|
+
*
|
|
6
|
+
* WHY THIS EXISTS — measured, not hypothetical.
|
|
7
|
+
*
|
|
8
|
+
* Every concern is inlined into one `dist/hooks/dispatch.js` that every hook
|
|
9
|
+
* event loads, so a dependency added for ONE concern is paid by all of them on
|
|
10
|
+
* every dispatch. On 2026-10-01 the bundle carried two YAML parsers: `yaml`,
|
|
11
|
+
* pulled by six modules including the dispatcher itself, and `js-yaml`, pulled
|
|
12
|
+
* by one call site in `block_config_weakening.ts` — 95,846 bytes, 6.13 % of a
|
|
13
|
+
* 1,564,211-byte bundle. Beside it, `host_lowering.ts`'s own header said the
|
|
14
|
+
* `yaml` reader was "the ONLY remaining YAML reader on that path".
|
|
15
|
+
*
|
|
16
|
+
* Nothing in this tree could see either fact. The freshness gate compares
|
|
17
|
+
* mtimes, the content gate compares digests, and neither has an opinion about
|
|
18
|
+
* what is INSIDE the bundle. So the second parser reached a release and was
|
|
19
|
+
* found by an external rescore counting bytes — a review finding where it
|
|
20
|
+
* should have been a red check. This gate is that red check.
|
|
21
|
+
*
|
|
22
|
+
* WHAT IT CHECKS
|
|
23
|
+
*
|
|
24
|
+
* 1. At most `max_yaml_packages` YAML packages contribute bytes to the
|
|
25
|
+
* bundle. The package set is {@link YAML_PACKAGES} — a closed list, so a
|
|
26
|
+
* third parser arriving under a name nobody listed is NOT caught here, and
|
|
27
|
+
* that limit is stated rather than implied.
|
|
28
|
+
* 2. The bundle's byte count is at or under `max_bytes`.
|
|
29
|
+
*
|
|
30
|
+
* Both bounds live in `src/config/hook-bundle-budget.json`, never in this file:
|
|
31
|
+
* a number a reviewer has to read a script to find is a number nobody reviews.
|
|
32
|
+
*
|
|
33
|
+
* WHY IT BUILDS RATHER THAN READS. `dist/hooks/` is untracked, so a gate that
|
|
34
|
+
* read the bundle on disk would be local-only like `check_hook_bundle_content`
|
|
35
|
+
* — and the thing being bounded is what the SOURCE produces, which is a
|
|
36
|
+
* property of the commit rather than of a machine. So this builds its own
|
|
37
|
+
* bundle with `--metafile` and measures that. It runs identically in CI and
|
|
38
|
+
* locally, and it never touches the live bundle.
|
|
39
|
+
*
|
|
40
|
+
* The esbuild invocation is NOT duplicated here: it is read from
|
|
41
|
+
* `package.json`'s `build:hooks` script with only `--outfile=` rewritten, via
|
|
42
|
+
* the same `rewriteOutfile` helper `rebuild_hook_bundle` and
|
|
43
|
+
* `check_hook_bundle_content` use, so the flag set has exactly one home. The
|
|
44
|
+
* trailing `&& node src/scripts/write_bundle_digest.mjs` is stripped — this
|
|
45
|
+
* gate must not write a sidecar for a probe bundle nobody executes.
|
|
46
|
+
*
|
|
47
|
+
* WHAT IT DOES NOT DO. It says nothing about LATENCY. A smaller bundle is not
|
|
48
|
+
* a measured speed-up; `src/config/hook-latency-budget.json` owns that axis and
|
|
49
|
+
* no number here is derived from it. It says nothing about the install or MCP
|
|
50
|
+
* bundles, which carry their own module graphs.
|
|
51
|
+
*
|
|
52
|
+
* Usage:
|
|
53
|
+
* ./scripts-run src/scripts/check_hook_bundle_composition
|
|
54
|
+
* ./scripts-run src/scripts/check_hook_bundle_composition --metafile <path>
|
|
55
|
+
* ./scripts-run src/scripts/check_hook_bundle_composition --self-test
|
|
56
|
+
*
|
|
57
|
+
* Exit codes: 0 = within budget · 1 = over the ceiling or a second reader ·
|
|
58
|
+
* 2 = the build or the budget file failed.
|
|
59
|
+
*/
|
|
60
|
+
// ledger-exempt: single-artefact transaction — one bundle build yielding one
|
|
61
|
+
// aggregate verdict. The per-source accounting lives in
|
|
62
|
+
// check_hook_bundle_freshness, which carries the ledger.
|
|
63
|
+
import { spawnSync } from 'node:child_process';
|
|
64
|
+
import * as fs from 'node:fs';
|
|
65
|
+
import * as os from 'node:os';
|
|
66
|
+
import * as path from 'node:path';
|
|
67
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
68
|
+
|
|
69
|
+
import { runGateCli, runSelfTest } from './_lib/gate_self_test.js';
|
|
70
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
71
|
+
import { buildScript } from './check_hook_bundle_content.js';
|
|
72
|
+
import { rewriteOutfile } from './rebuild_hook_bundle.js';
|
|
73
|
+
|
|
74
|
+
const _HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
75
|
+
export const REPO_ROOT = path.resolve(_HERE, '..', '..');
|
|
76
|
+
export const SELF_REL = path.join('src', 'scripts', 'check_hook_bundle_composition.ts');
|
|
77
|
+
export const BUDGET_REL = path.join('src', 'config', 'hook-bundle-budget.json');
|
|
78
|
+
const LIVE_REL = path.join('dist', 'hooks', 'dispatch.js');
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The YAML readers this tree has ever carried, by package name.
|
|
82
|
+
*
|
|
83
|
+
* A CLOSED LIST, and the consequence is worth stating: a fourth parser arriving
|
|
84
|
+
* under a name not listed here contributes bytes the ceiling catches and the
|
|
85
|
+
* parser cap does not. The alternative — treating any package whose name
|
|
86
|
+
* contains "yaml" as a reader — would match a YAML-adjacent utility that is not
|
|
87
|
+
* a parser, and a cap that fires on the wrong package is worse than one that
|
|
88
|
+
* misses an unlisted one, because the first teaches people to raise the cap.
|
|
89
|
+
*/
|
|
90
|
+
export const YAML_PACKAGES: readonly string[] = ['yaml', 'js-yaml', 'yaml-js', 'yamljs'];
|
|
91
|
+
|
|
92
|
+
export interface Budget {
|
|
93
|
+
readonly maxBytes: number;
|
|
94
|
+
readonly maxYamlPackages: number;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface Analysis {
|
|
98
|
+
/** Bytes of the bundle esbuild produced. */
|
|
99
|
+
readonly bytes: number;
|
|
100
|
+
/** Modules that contributed to it — the unit `scanned:` reports. */
|
|
101
|
+
readonly modules: number;
|
|
102
|
+
/** Bytes in the output, summed per owning npm package. */
|
|
103
|
+
readonly packageBytes: ReadonlyMap<string, number>;
|
|
104
|
+
/** Listed YAML packages contributing more than zero bytes, sorted. */
|
|
105
|
+
readonly yamlPackages: readonly string[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The npm package a bundled module path belongs to, or `null` for this tree's
|
|
110
|
+
* own sources.
|
|
111
|
+
*
|
|
112
|
+
* Reads the INNERMOST `node_modules/` segment: a transitively nested copy
|
|
113
|
+
* (`node_modules/a/node_modules/yaml/…`) is still `yaml`'s bytes, and
|
|
114
|
+
* attributing it to `a` would let a second parser hide one level down.
|
|
115
|
+
*/
|
|
116
|
+
export function owningPackage(modulePath: string): string | null {
|
|
117
|
+
const marker = 'node_modules/';
|
|
118
|
+
const at = modulePath.lastIndexOf(marker);
|
|
119
|
+
if (at < 0) return null;
|
|
120
|
+
const parts = modulePath.slice(at + marker.length).split('/');
|
|
121
|
+
const head = parts[0] ?? '';
|
|
122
|
+
if (head === '') return null;
|
|
123
|
+
return head.startsWith('@') ? `${head}/${parts[1] ?? ''}` : head;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Parse an esbuild metafile and attribute its one entry-point output. */
|
|
127
|
+
export function analyzeMetafile(json: string): Analysis {
|
|
128
|
+
const meta = JSON.parse(json) as {
|
|
129
|
+
outputs?: Record<string, { entryPoint?: string; bytes?: number; inputs?: Record<string, { bytesInOutput?: number }> }>;
|
|
130
|
+
};
|
|
131
|
+
const outputs = Object.values(meta.outputs ?? {});
|
|
132
|
+
const out = outputs.find((o) => typeof o.entryPoint === 'string');
|
|
133
|
+
if (out === undefined) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
'metafile carries no entry-point output — refusing to report a composition for a build that produced nothing',
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const packageBytes = new Map<string, number>();
|
|
139
|
+
const inputs = out.inputs ?? {};
|
|
140
|
+
for (const [p, v] of Object.entries(inputs)) {
|
|
141
|
+
const pkg = owningPackage(p);
|
|
142
|
+
if (pkg === null) continue;
|
|
143
|
+
packageBytes.set(pkg, (packageBytes.get(pkg) ?? 0) + (v.bytesInOutput ?? 0));
|
|
144
|
+
}
|
|
145
|
+
const yamlPackages = YAML_PACKAGES.filter((p) => (packageBytes.get(p) ?? 0) > 0).sort();
|
|
146
|
+
return {
|
|
147
|
+
bytes: out.bytes ?? 0,
|
|
148
|
+
modules: Object.keys(inputs).length,
|
|
149
|
+
packageBytes,
|
|
150
|
+
yamlPackages,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** Read the committed budget. Throws rather than defaulting — a guessed ceiling bounds nothing. */
|
|
155
|
+
export function readBudget(root: string): Budget {
|
|
156
|
+
const abs = path.join(root, BUDGET_REL);
|
|
157
|
+
const raw = JSON.parse(fs.readFileSync(abs, 'utf-8')) as Record<string, unknown>;
|
|
158
|
+
const maxBytes = raw['max_bytes'];
|
|
159
|
+
const maxYaml = raw['max_yaml_packages'];
|
|
160
|
+
if (typeof maxBytes !== 'number' || !Number.isInteger(maxBytes) || maxBytes <= 0) {
|
|
161
|
+
throw new Error(`${BUDGET_REL}: max_bytes must be a positive integer, got ${JSON.stringify(maxBytes)}`);
|
|
162
|
+
}
|
|
163
|
+
if (typeof maxYaml !== 'number' || !Number.isInteger(maxYaml) || maxYaml < 1) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`${BUDGET_REL}: max_yaml_packages must be an integer >= 1, got ${JSON.stringify(maxYaml)}`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
return { maxBytes, maxYamlPackages: maxYaml };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Findings, one line each. Empty means within budget. */
|
|
172
|
+
export function verdict(a: Analysis, budget: Budget): string[] {
|
|
173
|
+
const findings: string[] = [];
|
|
174
|
+
if (a.yamlPackages.length > budget.maxYamlPackages) {
|
|
175
|
+
const detail = a.yamlPackages
|
|
176
|
+
.map((p) => `${p} (${String(a.packageBytes.get(p) ?? 0)} B)`)
|
|
177
|
+
.join(', ');
|
|
178
|
+
findings.push(
|
|
179
|
+
`${String(a.yamlPackages.length)} YAML readers in the bundle, cap is ` +
|
|
180
|
+
`${String(budget.maxYamlPackages)}: ${detail}. Every dispatch loads all of them. ` +
|
|
181
|
+
'Move the odd caller onto the reader the dispatcher already uses.',
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if (a.bytes > budget.maxBytes) {
|
|
185
|
+
findings.push(
|
|
186
|
+
`bundle is ${String(a.bytes)} bytes, ceiling is ${String(budget.maxBytes)} ` +
|
|
187
|
+
`(over by ${String(a.bytes - budget.maxBytes)}). Shrink the bundle, or raise ` +
|
|
188
|
+
`max_bytes in ${BUDGET_REL} WITH an entry in its raise_log naming what was added.`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
return findings;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Build the hook bundle to a throwaway path and return its metafile JSON.
|
|
196
|
+
*
|
|
197
|
+
* Throws on any failure rather than returning a sentinel: a composition read off
|
|
198
|
+
* a build that did not happen is the silent-green this gate exists to replace.
|
|
199
|
+
*/
|
|
200
|
+
export function buildMetafile(root: string): string {
|
|
201
|
+
const script = buildScript(root);
|
|
202
|
+
if (script === null) {
|
|
203
|
+
throw new Error('package.json has no `build:hooks` script — refusing to guess the flag set');
|
|
204
|
+
}
|
|
205
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'hook-bundle-composition-'));
|
|
206
|
+
const outFile = path.join(dir, 'dispatch.js');
|
|
207
|
+
const metaFile = path.join(dir, 'meta.json');
|
|
208
|
+
try {
|
|
209
|
+
const rewritten = rewriteOutfile(script, outFile);
|
|
210
|
+
if (rewritten === null) {
|
|
211
|
+
throw new Error(`\`build:hooks\` no longer writes ${LIVE_REL} — refusing to build to a guessed path`);
|
|
212
|
+
}
|
|
213
|
+
// Strip the digest sidecar step: it would write `dispatch.sha256` beside
|
|
214
|
+
// a probe bundle nobody executes, and on failure it would mask the build
|
|
215
|
+
// error with a file-not-found.
|
|
216
|
+
const esbuildOnly = rewritten.split('&& node ')[0] ?? rewritten;
|
|
217
|
+
const built = spawnSync('sh', ['-c', `${esbuildOnly.trim()} --metafile=${metaFile}`], {
|
|
218
|
+
cwd: root,
|
|
219
|
+
encoding: 'utf-8',
|
|
220
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
221
|
+
env: {
|
|
222
|
+
...process.env,
|
|
223
|
+
PATH: `${path.join(root, 'node_modules', '.bin')}:${process.env['PATH'] ?? ''}`,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
if (built.status !== 0 || !fs.existsSync(metaFile)) {
|
|
227
|
+
throw new Error(`esbuild failed (exit ${String(built.status)})\n${built.stderr ?? ''}`);
|
|
228
|
+
}
|
|
229
|
+
return fs.readFileSync(metaFile, 'utf-8');
|
|
230
|
+
} finally {
|
|
231
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function selfTest(): number {
|
|
236
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'hook-bundle-composition-selftest-'));
|
|
237
|
+
const write = (name: string, body: unknown): string => {
|
|
238
|
+
const p = path.join(dir, name);
|
|
239
|
+
fs.writeFileSync(p, JSON.stringify(body));
|
|
240
|
+
return p;
|
|
241
|
+
};
|
|
242
|
+
const meta = (bytes: number, inputs: Record<string, number>): unknown => ({
|
|
243
|
+
inputs: {},
|
|
244
|
+
outputs: {
|
|
245
|
+
'dist/hooks/dispatch.js': {
|
|
246
|
+
entryPoint: 'src/scripts/hooks/dispatch_entry.ts',
|
|
247
|
+
bytes,
|
|
248
|
+
inputs: Object.fromEntries(
|
|
249
|
+
Object.entries(inputs).map(([k, v]) => [k, { bytesInOutput: v }]),
|
|
250
|
+
),
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
const budget = readBudget(REPO_ROOT);
|
|
255
|
+
const clean = write('clean.json', meta(budget.maxBytes, { 'node_modules/yaml/dist/index.js': 10 }));
|
|
256
|
+
const twoReaders = write(
|
|
257
|
+
'two-readers.json',
|
|
258
|
+
meta(1000, {
|
|
259
|
+
'node_modules/yaml/dist/index.js': 600,
|
|
260
|
+
'node_modules/js-yaml/dist/js-yaml.mjs': 400,
|
|
261
|
+
}),
|
|
262
|
+
);
|
|
263
|
+
const oneOver = write('one-over.json', meta(budget.maxBytes + 1, { 'src/x.ts': 1 }));
|
|
264
|
+
const empty = write('empty.json', { inputs: {}, outputs: {} });
|
|
265
|
+
|
|
266
|
+
const drive = (fixture: string): number =>
|
|
267
|
+
runGateCli(REPO_ROOT, SELF_REL, ['--metafile', fixture], REPO_ROOT);
|
|
268
|
+
|
|
269
|
+
try {
|
|
270
|
+
return runSelfTest({
|
|
271
|
+
gate: 'check_hook_bundle_composition',
|
|
272
|
+
minCases: 4,
|
|
273
|
+
minRejectCases: 3,
|
|
274
|
+
cases: [
|
|
275
|
+
{
|
|
276
|
+
name: 'one YAML reader, exactly at the ceiling → accepted',
|
|
277
|
+
expect: 'accept',
|
|
278
|
+
run: () => drive(clean),
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
name: 'a second YAML reader → rejected',
|
|
282
|
+
expect: 'reject',
|
|
283
|
+
run: () => drive(twoReaders),
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
name: 'one byte over the ceiling → rejected',
|
|
287
|
+
expect: 'reject',
|
|
288
|
+
run: () => drive(oneOver),
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: 'a metafile with no entry-point output → rejected, never reported as 0 bytes',
|
|
292
|
+
expect: 'reject',
|
|
293
|
+
run: () => drive(empty),
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
});
|
|
297
|
+
} finally {
|
|
298
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export function main(argv: readonly string[] = process.argv.slice(2), root: string = REPO_ROOT): number {
|
|
303
|
+
if (argv.includes('--self-test')) {
|
|
304
|
+
return selfTest();
|
|
305
|
+
}
|
|
306
|
+
const at = argv.indexOf('--metafile');
|
|
307
|
+
const fixture = at >= 0 ? argv[at + 1] : undefined;
|
|
308
|
+
|
|
309
|
+
let budget: Budget;
|
|
310
|
+
try {
|
|
311
|
+
budget = readBudget(root);
|
|
312
|
+
} catch (e) {
|
|
313
|
+
process.stderr.write(`check_hook_bundle_composition: ${String(e instanceof Error ? e.message : e)}\n`);
|
|
314
|
+
return 2;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
let json: string;
|
|
318
|
+
try {
|
|
319
|
+
json = fixture === undefined ? buildMetafile(root) : fs.readFileSync(fixture, 'utf-8');
|
|
320
|
+
} catch (e) {
|
|
321
|
+
process.stderr.write(`check_hook_bundle_composition: ${String(e instanceof Error ? e.message : e)}\n`);
|
|
322
|
+
return 2;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
let analysis: Analysis;
|
|
326
|
+
try {
|
|
327
|
+
analysis = analyzeMetafile(json);
|
|
328
|
+
} catch (e) {
|
|
329
|
+
process.stderr.write(`check_hook_bundle_composition: ${String(e instanceof Error ? e.message : e)}\n`);
|
|
330
|
+
return 1;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
const findings = verdict(analysis, budget);
|
|
334
|
+
// Reported on BOTH paths, red included: a census that goes quiet exactly
|
|
335
|
+
// when the gate fires is the shape `reportScanned` exists to prevent.
|
|
336
|
+
reportScanned({
|
|
337
|
+
gate: 'check_hook_bundle_composition',
|
|
338
|
+
scanned: analysis.modules,
|
|
339
|
+
units: 'bundled module(s)',
|
|
340
|
+
roots: [LIVE_REL],
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
if (findings.length === 0) {
|
|
344
|
+
process.stdout.write(
|
|
345
|
+
`✅ hook bundle: ${String(analysis.bytes)} B / ${String(budget.maxBytes)} B ceiling, ` +
|
|
346
|
+
`${String(analysis.yamlPackages.length)} YAML reader(s) ` +
|
|
347
|
+
`[${analysis.yamlPackages.join(', ')}], ${String(analysis.modules)} modules\n`,
|
|
348
|
+
);
|
|
349
|
+
return 0;
|
|
350
|
+
}
|
|
351
|
+
process.stderr.write('❌ hook bundle composition is out of budget\n');
|
|
352
|
+
for (const f of findings) process.stderr.write(` - ${f}\n`);
|
|
353
|
+
process.stderr.write(` Budget: ${BUDGET_REL}\n`);
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function _isCliEntry(): boolean {
|
|
358
|
+
const argv1 = process.argv[1];
|
|
359
|
+
if (argv1 === undefined) return false;
|
|
360
|
+
if (import.meta.url === pathToFileURL(path.resolve(argv1)).href) return true;
|
|
361
|
+
try {
|
|
362
|
+
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(argv1));
|
|
363
|
+
} catch {
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (_isCliEntry()) {
|
|
369
|
+
process.exit(main());
|
|
370
|
+
}
|