@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
|
@@ -63,8 +63,26 @@
|
|
|
63
63
|
* means reusing `nextState`, which is a larger change than a measurement
|
|
64
64
|
* correction and would itself need re-measuring.
|
|
65
65
|
*
|
|
66
|
+
* · THE RETRY-CONDITIONED RE-REFUSAL SHARE, which every bullet above is
|
|
67
|
+
* silent about because until 2026-09-30 nothing produced it. It does NOT
|
|
68
|
+
* come from the corpus: it is read from the gate's own shadow records under
|
|
69
|
+
* `agents/runtime/state/turn-end-gate/*.shadow.json`, written live on an
|
|
70
|
+
* allow path by the instrument `turn-end-detector-demotion.md` registers as
|
|
71
|
+
* instrument 1. Reported per LAYER and then per detector, never pooled, and
|
|
72
|
+
* never as `0.0%` where it has no denominator — see `renderQ1`.
|
|
73
|
+
* · It does NOT print that contract's **Q1**, and the distinction is in the
|
|
74
|
+
* report's own header rather than only here. Q1 conditions BOTH its halves
|
|
75
|
+
* on the detector; the shadow record cannot, because it never stores which
|
|
76
|
+
* refusal produced a retry. The two disagree in direction and neither
|
|
77
|
+
* bounds the other, so no number this prints may be read against a bar.
|
|
78
|
+
* · It does not report promissory, completion or untested at all. Those three
|
|
79
|
+
* are skipped by the gate when a dispatch is open and the shadow record
|
|
80
|
+
* carries no dispatch flag, so their denominators would absorb silences
|
|
81
|
+
* nobody observed. The contract's attribution clause already forbids it.
|
|
82
|
+
*
|
|
66
83
|
* Usage:
|
|
67
84
|
* ./scripts-run src/scripts/measure_turn_end_gate --store <dir> [--limit N] [--show-fires]
|
|
85
|
+
* ./scripts-run src/scripts/measure_turn_end_gate --q1 [--workspace <dir>]
|
|
68
86
|
*/
|
|
69
87
|
import * as fs from 'node:fs';
|
|
70
88
|
import * as path from 'node:path';
|
|
@@ -82,6 +100,14 @@ import {
|
|
|
82
100
|
extractToolCalls,
|
|
83
101
|
type ToolCall,
|
|
84
102
|
} from './hooks/turn_end_gate_hook.js';
|
|
103
|
+
import {
|
|
104
|
+
DETECTOR_IDS,
|
|
105
|
+
DISPATCH_CENSORED_DETECTORS,
|
|
106
|
+
SHADOW_LAYERS,
|
|
107
|
+
collectShadowStats,
|
|
108
|
+
retryConditionedShare,
|
|
109
|
+
type ShadowStats,
|
|
110
|
+
} from './_lib/turn_end_refusals.js';
|
|
85
111
|
|
|
86
112
|
interface Counts {
|
|
87
113
|
/**
|
|
@@ -495,16 +521,169 @@ export function render(c: Counts): string {
|
|
|
495
521
|
].join('\n');
|
|
496
522
|
}
|
|
497
523
|
|
|
524
|
+
/** `n` with a unit that agrees with it. One place, so no line has to remember. */
|
|
525
|
+
function plural(n: number, one: string, many = `${one}s`): string {
|
|
526
|
+
return `${String(n)} ${n === 1 ? one : many}`;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* The retry-conditioned re-refusal share, read from the shadow records rather
|
|
531
|
+
* than from a transcript. `road-to-a-stop-that-holds` step 2.2; the producer is
|
|
532
|
+
* step 2.1.
|
|
533
|
+
*
|
|
534
|
+
* ```
|
|
535
|
+
* THIS IS NOT THE Q1 `turn-end-detector-demotion.md` REGISTERS BARS AGAINST,
|
|
536
|
+
* AND THE REPORT SAYS SO IN ITS OWN HEADER.
|
|
537
|
+
* ```
|
|
538
|
+
*
|
|
539
|
+
* The first version of this renderer called the number Q1 outright. An
|
|
540
|
+
* independent review (2026-10-01) showed the two are different quantities that
|
|
541
|
+
* disagree in direction, not one quantity with a looser denominator — see
|
|
542
|
+
* `retryConditionedShare` for the worked ten-retry example. The rename and this
|
|
543
|
+
* header are that finding, acted on rather than noted.
|
|
544
|
+
*
|
|
545
|
+
* A DIFFERENT SOURCE FROM EVERY OTHER NUMBER THIS SCRIPT PRINTS, which is why
|
|
546
|
+
* it is a separate renderer rather than another line in `render`. The fire
|
|
547
|
+
* rates above are replayed out of a transcript corpus; this comes out of
|
|
548
|
+
* `agents/runtime/state/turn-end-gate/*.shadow.json`, written live by the gate
|
|
549
|
+
* on an allow path. The two cannot be joined — a shadow record carries no
|
|
550
|
+
* transcript and a transcript carries no shadow record — so printing them from
|
|
551
|
+
* one `Counts` object would invite exactly the cross-instrument arithmetic R2
|
|
552
|
+
* finding 7 removed from the language totals.
|
|
553
|
+
*
|
|
554
|
+
* NULL IS PRINTED AS `—`, NEVER AS `0.0%`. The two mean opposite things and
|
|
555
|
+
* `retryConditionedShare` keeps them apart for that reason; collapsing them at
|
|
556
|
+
* the render layer would undo the distinction one line before a human reads it.
|
|
557
|
+
*
|
|
558
|
+
* THE RESOLVED WORKSPACE IS PRINTED, because the one failure mode here is quiet:
|
|
559
|
+
* `--workspace` takes any path, a worktree carries no `agents/runtime/`, and the
|
|
560
|
+
* report for a wrong directory is a confident "no shadow record". A reading
|
|
561
|
+
* pasted into an evidence file must carry the directory that produced it.
|
|
562
|
+
*/
|
|
563
|
+
export function renderQ1(stats: ShadowStats, today: string, workspace?: string): string {
|
|
564
|
+
const lines: string[] = [
|
|
565
|
+
`measure-turn-end-gate · retry-conditioned re-refusal share · ${plural(stats.files, 'shadow record')} · read ${today}`,
|
|
566
|
+
' NOT the Q1 `turn-end-detector-demotion.md` registers bars against — see',
|
|
567
|
+
' the note below the table before comparing any number here to a bar.',
|
|
568
|
+
];
|
|
569
|
+
if (workspace !== undefined) {
|
|
570
|
+
lines.push(` workspace: ${path.resolve(workspace)}`);
|
|
571
|
+
}
|
|
572
|
+
lines.push('');
|
|
573
|
+
if (stats.files === 0) {
|
|
574
|
+
lines.push(
|
|
575
|
+
' No readable shadow record under this workspace. The share has no',
|
|
576
|
+
' denominator and is not reported as zero — a gate that has never been',
|
|
577
|
+
' retried is not a gate whose retries all came back clean.',
|
|
578
|
+
);
|
|
579
|
+
if (stats.unreadable > 0) {
|
|
580
|
+
lines.push(
|
|
581
|
+
'',
|
|
582
|
+
` ${plural(stats.unreadable, 'shadow file')} present but UNREADABLE, so "none" above`,
|
|
583
|
+
' means none could be parsed rather than none exists. That is a defect to',
|
|
584
|
+
' investigate, not an empty sample.',
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
return lines.join('\n');
|
|
588
|
+
}
|
|
589
|
+
for (const layer of SHADOW_LAYERS) {
|
|
590
|
+
const bucket = stats.byLayer.find((b) => b.layer === layer);
|
|
591
|
+
if (bucket === undefined) continue;
|
|
592
|
+
lines.push(
|
|
593
|
+
` layer ${layer} — ${plural(bucket.retries, 'retry', 'retries')} observed, ${plural(bucket.rows, 'shadow row')}`,
|
|
594
|
+
);
|
|
595
|
+
if (bucket.retries === 0) {
|
|
596
|
+
lines.push(' (no retry on this layer; every share below would have no denominator)');
|
|
597
|
+
}
|
|
598
|
+
for (const id of DETECTOR_IDS) {
|
|
599
|
+
if (DISPATCH_CENSORED_DETECTORS.has(id)) {
|
|
600
|
+
lines.push(` ${id.padEnd(17)} censored (dispatch-suppressed retries are indistinguishable)`);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const share = retryConditionedShare(stats, layer, id);
|
|
604
|
+
// A dash denies a measurement; a count beside it reads like one. The
|
|
605
|
+
// `(0 / 0)` the first version printed there was the denial and the
|
|
606
|
+
// measurement on the same line.
|
|
607
|
+
if (share === null) {
|
|
608
|
+
lines.push(` ${id.padEnd(17)} —`);
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
const shown = `${(100 * share).toFixed(1)}%`.padStart(6);
|
|
612
|
+
lines.push(` ${id.padEnd(17)} ${shown} (${String(bucket.byDetector[id])} / ${String(bucket.retries)})`);
|
|
613
|
+
}
|
|
614
|
+
lines.push('');
|
|
615
|
+
}
|
|
616
|
+
lines.push(
|
|
617
|
+
' WHAT THIS IS, precisely, because the contract defines a DIFFERENT number',
|
|
618
|
+
' under a similar name. Printed here: of the retries observed on a layer,',
|
|
619
|
+
" the share a detector would have refused. The contract's Q1: of a",
|
|
620
|
+
" DETECTOR'S OWN initial refusals, the share whose retry that same detector",
|
|
621
|
+
' refuses again. Both halves of the contract definition are conditioned on',
|
|
622
|
+
' the detector; neither half here is, because `ShadowRecord` does not record',
|
|
623
|
+
' which refusal produced a retry. The two disagree in direction and neither',
|
|
624
|
+
' bounds the other, so no number above may be read against a bar in',
|
|
625
|
+
" `turn-end-detector-demotion.md` § The bars. Closing that needs the",
|
|
626
|
+
' PRODUCER to record the originating detector.',
|
|
627
|
+
'',
|
|
628
|
+
' THREE DETECTORS ARE CENSORED, and the contract requires it rather than',
|
|
629
|
+
' this renderer choosing it. `runDetectors` skips promissory, completion and',
|
|
630
|
+
" untested when a dispatch is open, and the shadow record carries no dispatch",
|
|
631
|
+
' flag — so those retries would enter their denominators as observations of',
|
|
632
|
+
' silence that nobody made. The attribution clause already forbids reporting',
|
|
633
|
+
' a detector a rollup cannot separate that way.',
|
|
634
|
+
'',
|
|
635
|
+
' GROUPED BY LAYER FIRST, and the grouping is load-bearing rather than',
|
|
636
|
+
' cosmetic. A `stop_hook_active` retry follows ANY stop concern\'s block, not',
|
|
637
|
+
' only this gate\'s, so a pooled share divides another concern\'s retries into',
|
|
638
|
+
' this gate\'s refusals. `retries_observed` is keyed by layer so the',
|
|
639
|
+
' denominator splits with the numerator.',
|
|
640
|
+
'',
|
|
641
|
+
' TWO FURTHER BOUNDS ON EVERY NUMBER ABOVE, both properties of the instrument:',
|
|
642
|
+
' 1. A retry whose transcript is absent, oversized or textless records',
|
|
643
|
+
' NOTHING — no row and no retry. Numerator and denominator shrink',
|
|
644
|
+
' together, so each share is an UPPER bound, never a point estimate.',
|
|
645
|
+
' 2. On a host that sends no `session_id` every session shares one record.',
|
|
646
|
+
' The record count above is FILES; it equals sessions only where the',
|
|
647
|
+
' host sends an id.',
|
|
648
|
+
'',
|
|
649
|
+
' A share above may be well-formed and still unreadable as a rate if the',
|
|
650
|
+
' record count is small. The count is printed first for that reason.',
|
|
651
|
+
);
|
|
652
|
+
if (stats.dropped > 0) {
|
|
653
|
+
lines.push(
|
|
654
|
+
'',
|
|
655
|
+
` ${plural(stats.dropped, 'row')} dropped to the per-session cap: every numerator above is a FLOOR.`,
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
if (stats.unreadable > 0) {
|
|
659
|
+
lines.push(
|
|
660
|
+
'',
|
|
661
|
+
` ${plural(stats.unreadable, 'shadow file')} present but unreadable — same reading, same direction.`,
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
if (stats.earliest !== null && stats.latest !== null) {
|
|
665
|
+
lines.push('', ` Window observed: ${stats.earliest} … ${stats.latest}`);
|
|
666
|
+
}
|
|
667
|
+
return lines.join('\n');
|
|
668
|
+
}
|
|
669
|
+
|
|
498
670
|
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
499
671
|
let store = '';
|
|
500
672
|
let limit = 30;
|
|
501
673
|
let showFires = false;
|
|
674
|
+
let q1Only = false;
|
|
675
|
+
let workspace = process.cwd();
|
|
502
676
|
for (let i = 0; i < argv.length; i += 1) {
|
|
503
677
|
if (argv[i] === '--store' && argv[i + 1] !== undefined) {
|
|
504
678
|
store = argv[i + 1]!;
|
|
505
679
|
i += 1;
|
|
506
680
|
} else if (argv[i] === '--show-fires') {
|
|
507
681
|
showFires = true;
|
|
682
|
+
} else if (argv[i] === '--q1') {
|
|
683
|
+
q1Only = true;
|
|
684
|
+
} else if (argv[i] === '--workspace' && argv[i + 1] !== undefined) {
|
|
685
|
+
workspace = argv[i + 1]!;
|
|
686
|
+
i += 1;
|
|
508
687
|
} else if (argv[i] === '--limit' && argv[i + 1] !== undefined) {
|
|
509
688
|
// R2 finding 15: an unvalidated parseInt made `--limit abc` yield
|
|
510
689
|
// NaN, `slice(0, NaN)` return nothing, and the script exit 2 with
|
|
@@ -521,6 +700,16 @@ export function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
521
700
|
i += 1;
|
|
522
701
|
}
|
|
523
702
|
}
|
|
703
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
704
|
+
// `--q1` needs no transcript corpus: the shadow records are the source, and
|
|
705
|
+
// requiring a `--store` for them would make the one reading this roadmap
|
|
706
|
+
// asks for contingent on an unrelated input. Deliberately NOT a silent
|
|
707
|
+
// default of the store path — a reading over the wrong workspace is the
|
|
708
|
+
// failure mode here, and it is quiet.
|
|
709
|
+
if (q1Only) {
|
|
710
|
+
process.stdout.write(`${renderQ1(collectShadowStats(workspace), today, workspace)}\n`);
|
|
711
|
+
return 0;
|
|
712
|
+
}
|
|
524
713
|
if (!store) {
|
|
525
714
|
process.stderr.write('measure-turn-end-gate: --store <transcript dir> is required\n');
|
|
526
715
|
return 2;
|
|
@@ -533,6 +722,10 @@ export function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
533
722
|
return 2;
|
|
534
723
|
}
|
|
535
724
|
process.stdout.write(`${render(counts)}\n`);
|
|
725
|
+
// Q1 rides on the default report because step 2.2 asks that
|
|
726
|
+
// `measure_turn_end_gate` PRINT it, not that it offer to. A reader who
|
|
727
|
+
// never learns the flag exists still sees the number.
|
|
728
|
+
process.stdout.write(`\n${renderQ1(collectShadowStats(workspace), today, workspace)}\n`);
|
|
536
729
|
if (showFires) {
|
|
537
730
|
process.stdout.write(`\n detector F fired here — read these turns before\n calling any of them a false positive:\n${renderFires(counts)}\n`);
|
|
538
731
|
process.stdout.write(`\n detector E fired here — same reading, same reason:\n${renderDroppedFires(counts)}\n`);
|
|
@@ -22,6 +22,11 @@
|
|
|
22
22
|
* PROMOTED lesson is surfaced as a one-line visibility marker pointing
|
|
23
23
|
* at the existing /memory:propose flow. Nothing auto-writes curated
|
|
24
24
|
* `agents/memory/*.yml`.
|
|
25
|
+
* - Measured: every run appends one line to the gitignored dogfood ledger
|
|
26
|
+
* (`agents/runtime/state/learning-dogfood.jsonl`) BEFORE the early
|
|
27
|
+
* returns, so the 30-day window the default flip is gated on can read a
|
|
28
|
+
* zero rather than a silence. See `runLearn` for why that distinction is
|
|
29
|
+
* the whole point.
|
|
25
30
|
*
|
|
26
31
|
* Exit codes (dispatcher contract): 0 always (allow).
|
|
27
32
|
*/
|
|
@@ -44,8 +49,9 @@ import type { SettingsClass } from '../shared/settingsClasses.js';
|
|
|
44
49
|
import { consentVerdict, type ConsentVerdict } from '../shared/settingsConsent.js';
|
|
45
50
|
|
|
46
51
|
import {
|
|
47
|
-
|
|
52
|
+
buildSidecarFromSignals,
|
|
48
53
|
LESSONS_NAME,
|
|
54
|
+
readSignals,
|
|
49
55
|
renderLessonsMd,
|
|
50
56
|
SIDECAR_NAME,
|
|
51
57
|
} from './learning_sidecar.js';
|
|
@@ -175,23 +181,102 @@ export function enabled(root: string): boolean {
|
|
|
175
181
|
return learnConsent(root) === 'granted';
|
|
176
182
|
}
|
|
177
183
|
|
|
178
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* The dogfood ledger: repo-relative POSIX path, one JSON object per line.
|
|
186
|
+
*
|
|
187
|
+
* Under `agents/runtime/` — gitignored wholesale — because it is one machine's
|
|
188
|
+
* timings and counts, not a shared artefact. Its continuity-surface row records
|
|
189
|
+
* it as `excluded`: nothing restores a session from it.
|
|
190
|
+
*/
|
|
191
|
+
export const DOGFOOD_LEDGER_POSIX = 'agents/runtime/state/learning-dogfood.jsonl';
|
|
192
|
+
|
|
193
|
+
/** One session end, as the ledger records it. */
|
|
194
|
+
export interface DogfoodLine {
|
|
195
|
+
/** The `now` the aggregation ran against. */
|
|
196
|
+
at: string;
|
|
197
|
+
/** Wall-clock ms for read + aggregate — the portion the 2 s budget governs. */
|
|
198
|
+
wall_ms: number;
|
|
199
|
+
/** Well-formed signal records read from the intake. */
|
|
200
|
+
signals_in: number;
|
|
201
|
+
/** Lessons the aggregation produced. */
|
|
202
|
+
lessons_out: number;
|
|
203
|
+
/** Of those, how many carry the `preferred` verdict. */
|
|
204
|
+
preferred: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Append one measurement line. Never throws: the ledger is a measurement, and
|
|
209
|
+
* a measurement that can break the thing it measures is worse than no ledger.
|
|
210
|
+
*/
|
|
211
|
+
export function appendDogfoodLine(root: string, line: DogfoodLine): void {
|
|
212
|
+
try {
|
|
213
|
+
const file = path.join(root, ...DOGFOOD_LEDGER_POSIX.split('/'));
|
|
214
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
215
|
+
fs.appendFileSync(file, `${JSON.stringify(line)}\n`, 'utf8');
|
|
216
|
+
} catch {
|
|
217
|
+
// fail-open, same contract as the aggregation itself.
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Read the ledger back. Malformed lines are skipped, an absent file is empty. */
|
|
222
|
+
export function readDogfoodLines(root: string): DogfoodLine[] {
|
|
223
|
+
let text: string;
|
|
224
|
+
try {
|
|
225
|
+
text = fs.readFileSync(path.join(root, ...DOGFOOD_LEDGER_POSIX.split('/')), 'utf8');
|
|
226
|
+
} catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
const out: DogfoodLine[] = [];
|
|
230
|
+
for (const raw of text.split('\n')) {
|
|
231
|
+
const line = raw.trim();
|
|
232
|
+
if (!line) continue;
|
|
233
|
+
try {
|
|
234
|
+
out.push(JSON.parse(line) as DogfoodLine);
|
|
235
|
+
} catch {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Run the aggregation. Returns the one-line marker to emit, or null.
|
|
244
|
+
*
|
|
245
|
+
* MEASURE FIRST, THEN DECIDE. The flip condition this hook's default is gated
|
|
246
|
+
* on (`src/config/agent-settings.template.yml:1376-1378`) names two numbers —
|
|
247
|
+
* non-trivial signal AND session-end p95 < 2 s — and until the ledger below
|
|
248
|
+
* existed, neither was recorded: every early return here fired before any
|
|
249
|
+
* measurement point, so a checkout with an empty intake produced an unbroken
|
|
250
|
+
* silence. A silence and a measured zero read identically to whoever opens the
|
|
251
|
+
* window, which is the one failure a 30-day window cannot recover from. So the
|
|
252
|
+
* read, the aggregation and the ledger line all happen before the first return.
|
|
253
|
+
*/
|
|
179
254
|
export function runLearn(root: string, nowIso: string, budgetMs: number = BUDGET_MS): string | null {
|
|
180
255
|
const started = Date.now();
|
|
181
256
|
const intakeDir = path.join(root, 'agents', 'memory', 'intake');
|
|
182
257
|
const outDir = path.join(root, 'agents', 'memory');
|
|
183
|
-
|
|
184
|
-
const
|
|
258
|
+
// An absent intake directory is a zero-signal session, not an absent one.
|
|
259
|
+
const haveIntake = fs.existsSync(intakeDir);
|
|
260
|
+
const signals = haveIntake ? readSignals(intakeDir) : [];
|
|
261
|
+
const sidecar = buildSidecarFromSignals(signals, nowIso);
|
|
262
|
+
const preferred = sidecar.lessons.filter((l) => l.verdict === 'preferred').length;
|
|
263
|
+
appendDogfoodLine(root, {
|
|
264
|
+
at: nowIso,
|
|
265
|
+
wall_ms: Date.now() - started,
|
|
266
|
+
signals_in: signals.length,
|
|
267
|
+
lessons_out: sidecar.lessons.length,
|
|
268
|
+
preferred,
|
|
269
|
+
});
|
|
270
|
+
if (!haveIntake) return null;
|
|
185
271
|
if (Date.now() - started > budgetMs) return null; // over budget — skip the write
|
|
186
272
|
if (sidecar.lessons.length === 0) return null;
|
|
187
273
|
fs.writeFileSync(path.join(outDir, SIDECAR_NAME), `${JSON.stringify(sidecar, null, 2)}\n`, 'utf8');
|
|
188
274
|
fs.writeFileSync(path.join(outDir, LESSONS_NAME), renderLessonsMd(sidecar), 'utf8');
|
|
189
|
-
const promoted = sidecar.lessons.filter((l) => l.verdict === 'preferred').length;
|
|
190
275
|
const deadEnds = sidecar.lessons.filter((l) => l.verdict === 'dead_end').length;
|
|
191
276
|
// Memory-visibility contract shape: one line, ids/counters only, no bodies.
|
|
192
277
|
return (
|
|
193
278
|
`🧠 Memory: sidecar refreshed — ${sidecar.lessons.length} lesson(s) ` +
|
|
194
|
-
`(${
|
|
279
|
+
`(${preferred} preferred · ${deadEnds} dead-end); promote via /memory:propose`
|
|
195
280
|
);
|
|
196
281
|
}
|
|
197
282
|
|
|
@@ -35,7 +35,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
35
35
|
import { createRequire } from 'node:module';
|
|
36
36
|
import YAML, { parseDocument } from 'yaml';
|
|
37
37
|
|
|
38
|
-
import { sanitize_entry } from './_lib/retrieval_sanitize.js';
|
|
38
|
+
import { sanitize_entry } from './_lib/retrieval_sanitize.js'; // read-surface: ingested-corpus
|
|
39
39
|
import { LexicalIndex, tokenize as _lexTokenize } from './_lib/lexical_index.js';
|
|
40
40
|
import {
|
|
41
41
|
ensureIndex as _ftsEnsureIndex,
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
triggerlessRuleIds,
|
|
66
66
|
type Router,
|
|
67
67
|
} from './_lib/rule_injection.js';
|
|
68
|
+
import { ruleBody } from './_lib/rule_law_section.js';
|
|
68
69
|
import {
|
|
69
70
|
renderArmExperiment,
|
|
70
71
|
runArmExperiment,
|
|
@@ -682,6 +683,34 @@ export function runEndpoints(corpusDir: string): EndpointResult[] {
|
|
|
682
683
|
]);
|
|
683
684
|
const thinnedAndPathOnly = pathOnlyReach.filter((id) => !alwaysEager.has(id));
|
|
684
685
|
|
|
686
|
+
// PROMPT-LEVEL beside RULE-LEVEL — step 0.4 of
|
|
687
|
+
// `road-to-a-rule-carrier-that-works-outside-the-repo`.
|
|
688
|
+
//
|
|
689
|
+
// The two numbers above are per RULE: a rule counts as reachable when ANY
|
|
690
|
+
// of its labelled positives matches. That is the right unit for the bar —
|
|
691
|
+
// "no labelled rule left unreachable" — and it is the wrong unit for the
|
|
692
|
+
// question a reader actually asks next, which is how much of the corpus the
|
|
693
|
+
// shipped binding delivers. A rule reachable on one of twelve prompts and a
|
|
694
|
+
// rule reachable on all twelve are the same row in `byRule`.
|
|
695
|
+
//
|
|
696
|
+
// So the pair is reported in both units. The SUMMARY view has computed the
|
|
697
|
+
// prompt-level figures since the two-readings split landed; what was missing
|
|
698
|
+
// is that `--endpoints`, which is the view a claim cites, printed only the
|
|
699
|
+
// rule-level half. A reader comparing the two views saw 99/102 and 305/335
|
|
700
|
+
// and had no way to tell they measure different things.
|
|
701
|
+
const promptHonoured = positives.filter((c) => reach(c, true)).length;
|
|
702
|
+
const promptIgnored = positives.filter((c) => reach(c, false)).length;
|
|
703
|
+
|
|
704
|
+
// The SUMMARY view prints a LOWER pair over the same corpus, and the gap is
|
|
705
|
+
// not noise. `scoreExact` calls `matchTierRules(router, c.prompt, of)` with
|
|
706
|
+
// three arguments and drops the case's `command`, so a positive whose rule
|
|
707
|
+
// is reached by a `command:` trigger scores as a miss there and as a hit
|
|
708
|
+
// here. Recorded rather than repaired: this phase changes no behaviour, and
|
|
709
|
+
// the SUMMARY figures are cited in a roadmap and in the prereg. Both
|
|
710
|
+
// readings are printed so neither view has to be trusted over the other.
|
|
711
|
+
const summaryHonoured = scoreExact(router, cases, true);
|
|
712
|
+
const summaryIgnored = scoreExact(router, cases, false);
|
|
713
|
+
|
|
685
714
|
// (c) A near-miss must never deliver its labelled rule.
|
|
686
715
|
const exact = scoreExact(router, cases, true);
|
|
687
716
|
|
|
@@ -716,7 +745,15 @@ export function runEndpoints(corpusDir: string): EndpointResult[] {
|
|
|
716
745
|
`${byRule.size - pathOnlyReach.length}/${byRule.size}; reachable only via a ` +
|
|
717
746
|
`path trigger: ${pathOnlyReach.length === 0 ? 'none' : pathOnlyReach.join(', ')}` +
|
|
718
747
|
` (of which thinned, i.e. at no scope on that route: ` +
|
|
719
|
-
`${thinnedAndPathOnly.length === 0 ? 'none' : thinnedAndPathOnly.join(', ')})
|
|
748
|
+
`${thinnedAndPathOnly.length === 0 ? 'none' : thinnedAndPathOnly.join(', ')})` +
|
|
749
|
+
` | per-prompt reach: ${promptIgnored}/${positives.length} with open_files ` +
|
|
750
|
+
`IGNORED against ${promptHonoured}/${positives.length} honoured — the same ` +
|
|
751
|
+
`corpus in prompts rather than in rules, because a rule reachable on one of ` +
|
|
752
|
+
`twelve positives and one reachable on all twelve are one row above` +
|
|
753
|
+
` | SUMMARY prints ${summaryIgnored.hits}/${summaryIgnored.positives} and ` +
|
|
754
|
+
`${summaryHonoured.hits}/${summaryHonoured.positives} for the same corpus: ` +
|
|
755
|
+
`scoreExact drops the case's command trigger, so a command-reached positive ` +
|
|
756
|
+
`misses there and hits here`,
|
|
720
757
|
bar: 'unreachable == 0 (a rule with zero matched positives is a rule the mode removed)',
|
|
721
758
|
passed: unreachable.length === 0,
|
|
722
759
|
},
|
|
@@ -781,13 +818,23 @@ export function runSelftest(corpusDir: string): SelftestCase[] {
|
|
|
781
818
|
});
|
|
782
819
|
} else {
|
|
783
820
|
const id = injection.rules[0] as string;
|
|
784
|
-
|
|
785
|
-
|
|
821
|
+
// THE DELIVERED FORM, not the raw file. Since step 1.4 the concern emits
|
|
822
|
+
// `ruleBody` of the projection — frontmatter and HTML comments stripped
|
|
823
|
+
// by the same parser `project_thin_rules` uses — so comparing against
|
|
824
|
+
// the raw file asserts a substring the payload no longer contains. The
|
|
825
|
+
// endpoint's claim is unchanged: the payload carries the body verbatim
|
|
826
|
+
// and rejects a mutation of it. What "the body" means moved, and this
|
|
827
|
+
// moved with it.
|
|
828
|
+
const projected = ruleBody(loadRuleBody(REPO_ROOT, id) ?? '');
|
|
829
|
+
const mutated = `${projected.slice(0, -1)}~MUTATED~`;
|
|
786
830
|
out.push({
|
|
787
831
|
endpoint: 'a-delivery',
|
|
788
832
|
name: 'one-byte mutation rejected',
|
|
789
|
-
passed:
|
|
790
|
-
|
|
833
|
+
passed:
|
|
834
|
+
projected !== ''
|
|
835
|
+
&& injection.body.includes(projected)
|
|
836
|
+
&& !injection.body.includes(mutated),
|
|
837
|
+
detail: `${id}: the concern's payload carries the delivered body verbatim and rejects a mutation of it`,
|
|
791
838
|
});
|
|
792
839
|
}
|
|
793
840
|
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* Skip with PREPACK_SKIP_BUILD_CHECK=1 only for local `npm pack` dry-runs
|
|
24
24
|
* that intentionally test the failure mode.
|
|
25
25
|
*/
|
|
26
|
+
import { createHash } from 'node:crypto';
|
|
26
27
|
import { readFileSync, statSync } from 'node:fs';
|
|
27
28
|
import { resolve } from 'node:path';
|
|
28
29
|
import { argv, env, exit } from 'node:process';
|
|
@@ -66,6 +67,58 @@ if (head !== SHEBANG) {
|
|
|
66
67
|
|
|
67
68
|
process.stderr.write(`prepack-check: ${BIN} OK\n`);
|
|
68
69
|
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Bundle-digest sidecar: `dist/hooks/dispatch.js` must ship with the
|
|
72
|
+
// `dist/hooks/dispatch.sha256` its build wrote, and the digest must still
|
|
73
|
+
// describe the bundle beside it.
|
|
74
|
+
//
|
|
75
|
+
// Risk 3 of road-to-a-kernel-that-guards-its-plumbing: the runtime integrity
|
|
76
|
+
// check treats a MISSING sidecar as `unverifiable` and allows, deliberately,
|
|
77
|
+
// so that a consumer install predating the sidecar is not wedged. That safety
|
|
78
|
+
// property has a cost — a bundle shipped without its sidecar silently disables
|
|
79
|
+
// the check for every consumer who installs it, and nothing at runtime can
|
|
80
|
+
// tell that apart from the legitimate old-package case. The place to catch it
|
|
81
|
+
// is here, in the one step that knows a bundle is being packaged NOW and
|
|
82
|
+
// therefore had no excuse for the sidecar's absence.
|
|
83
|
+
//
|
|
84
|
+
// A stale digest is treated exactly like a missing one: both mean the two
|
|
85
|
+
// files were not produced by the same `npm run build:hooks`.
|
|
86
|
+
const HOOK_BUNDLE = resolve('dist/hooks/dispatch.js');
|
|
87
|
+
const HOOK_SIDECAR = resolve('dist/hooks/dispatch.sha256');
|
|
88
|
+
let hookBundleBytes = null;
|
|
89
|
+
try {
|
|
90
|
+
hookBundleBytes = readFileSync(HOOK_BUNDLE);
|
|
91
|
+
} catch {
|
|
92
|
+
// No hook bundle in this tree at all — `npm run build` builds it, and gate
|
|
93
|
+
// 1 above has already failed if the build did not run. Nothing to check.
|
|
94
|
+
}
|
|
95
|
+
if (hookBundleBytes !== null) {
|
|
96
|
+
let sidecarText;
|
|
97
|
+
try {
|
|
98
|
+
sidecarText = readFileSync(HOOK_SIDECAR, 'utf8');
|
|
99
|
+
} catch {
|
|
100
|
+
die(
|
|
101
|
+
`dist/hooks/dispatch.js ships without dist/hooks/dispatch.sha256. The runtime ` +
|
|
102
|
+
`integrity check reads a missing sidecar as "unverifiable" and ALLOWS, so ` +
|
|
103
|
+
`publishing this tarball would silently disable it for every consumer. Run ` +
|
|
104
|
+
`\`npm run build:hooks\`, which writes both.`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const claimed = /^([0-9a-f]{64})\s/u.exec(sidecarText.trim())?.[1] ?? null;
|
|
108
|
+
if (claimed === null) {
|
|
109
|
+
die(`dist/hooks/dispatch.sha256 is malformed — expected "<64 hex> dispatch.js".`);
|
|
110
|
+
}
|
|
111
|
+
const actual = createHash('sha256').update(hookBundleBytes).digest('hex');
|
|
112
|
+
if (actual !== claimed) {
|
|
113
|
+
die(
|
|
114
|
+
`dist/hooks/dispatch.sha256 does not describe dist/hooks/dispatch.js ` +
|
|
115
|
+
`(sidecar ${claimed.slice(0, 12)}…, bundle ${actual.slice(0, 12)}…). The two were ` +
|
|
116
|
+
`not produced by the same build. Run \`npm run build:hooks\`.`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
process.stderr.write(`prepack-check: dist/hooks/dispatch.sha256 OK (${actual.slice(0, 12)}…)\n`);
|
|
120
|
+
}
|
|
121
|
+
|
|
69
122
|
// ---------------------------------------------------------------------------
|
|
70
123
|
// Import-completeness guard: every relative import reachable from the
|
|
71
124
|
// SHIPPED src/ trees must itself resolve to a shipped file. Catches the
|