@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
|
@@ -7,35 +7,51 @@
|
|
|
7
7
|
* the corpus's expected skill per line". Building it surfaced two defects in
|
|
8
8
|
* that premise, and this file is written around them rather than over them.
|
|
9
9
|
*
|
|
10
|
-
* DEFECT A — the
|
|
11
|
-
* is keyed by `rule:` and every prompt
|
|
12
|
-
* activate. Scoring a skill ranker against it would need a skill label that
|
|
13
|
-
*
|
|
10
|
+
* DEFECT A — the routing matrix had no expected SKILL. `tests/eval/routing-matrix/`
|
|
11
|
+
* is keyed by `rule:` and every prompt was labelled with the RULE it should
|
|
12
|
+
* activate. Scoring a skill ranker against it would need a skill label that did
|
|
13
|
+
* not exist there, so a "hit rate" over it would be invented.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* **Defect A is CLOSED as of `road-to-a-menu-whose-precision-is-measured` 1.1.**
|
|
16
|
+
* Every case in the matrix now carries an `expected_skills` list, hand-written
|
|
17
|
+
* by seats that had not read this ranker's scoring (the protocol is in
|
|
18
|
+
* `tests/eval/routing-matrix/README.md`). An EMPTY list is a first-class value
|
|
19
|
+
* meaning "deliberately no skill expectation", and such a row is excluded from
|
|
20
|
+
* the accuracy denominator rather than counted as a miss. So the matrix arm now
|
|
21
|
+
* has ground truth; `--corpus routing-matrix` scores against it.
|
|
18
22
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* confident) with no ground truth and therefore no accuracy.
|
|
23
|
+
* DEFECT B — the published size is stale, repeatedly. 496 was published while
|
|
24
|
+
* the matrix held 499, and 499 is still published in several sites while the
|
|
25
|
+
* matrix holds more than that again. The size is therefore MEASURED on every run
|
|
26
|
+
* and printed, never asserted from a constant.
|
|
24
27
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
28
|
+
* THE INTERVAL, AND THE REFUSAL TO PRINT A VERDICT UNDER n = 100.
|
|
29
|
+
* A hit rate over 26 prompts
|
|
30
|
+
* moves ~4 points per prompt; quoting it as "61.5 %" invites a comparison the
|
|
31
|
+
* sample cannot carry. Both arms therefore report a 95 % Wilson score interval
|
|
32
|
+
* (`_lib/capture_rate.ts` — Wilson rather than the normal approximation for the
|
|
33
|
+
* same reason stated there: near p = 1 the normal one produces bounds above 1).
|
|
27
34
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
35
|
+
* Below {@link MIN_POWERED_N} labelled rows the arm's `verdict` is
|
|
36
|
+
* `underpowered`. That is not a failure and not an exit code — the point
|
|
37
|
+
* estimate and the interval are still printed, because suppressing them would
|
|
38
|
+
* replace a wide measurement with no measurement. It is a label that travels
|
|
39
|
+
* with the number so a later reader cannot quote the point estimate alone.
|
|
30
40
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
41
|
+
* Usage:
|
|
42
|
+
* ./scripts-run src/scripts/measure_skill_ranker_baseline
|
|
43
|
+
* ./scripts-run src/scripts/measure_skill_ranker_baseline --corpus routing-matrix
|
|
44
|
+
* ./scripts-run src/scripts/measure_skill_ranker_baseline --corpus all
|
|
45
|
+
* ./scripts-run src/scripts/measure_skill_ranker_baseline --ranker keyword-v2
|
|
46
|
+
* ./scripts-run src/scripts/measure_skill_ranker_baseline --corpus routing-matrix --slice sealed
|
|
33
47
|
*/
|
|
34
48
|
|
|
35
49
|
import * as fs from 'node:fs';
|
|
36
50
|
import * as path from 'node:path';
|
|
37
51
|
import { fileURLToPath } from 'node:url';
|
|
38
52
|
|
|
53
|
+
import { wilsonInterval } from './_lib/capture_rate.js';
|
|
54
|
+
import { fnv1a } from './_lib/fnv.js';
|
|
39
55
|
import { rank } from './skill_tools/score_skill_relevance.js';
|
|
40
56
|
import type { RankOptions } from '../shared/skillRanking.js';
|
|
41
57
|
|
|
@@ -45,6 +61,20 @@ const MATRIX_DIR = 'tests/eval/routing-matrix';
|
|
|
45
61
|
/** Where the projected skills live in this checkout. */
|
|
46
62
|
export const SKILLS_DIR = path.join(REPO, 'src', 'skills');
|
|
47
63
|
|
|
64
|
+
/**
|
|
65
|
+
* The smallest labelled corpus this report will call powered.
|
|
66
|
+
*
|
|
67
|
+
* 100 is the roadmap's number, not a derived optimum, and it is stated as such:
|
|
68
|
+
* at n = 100 a point estimate near 0.7 carries a 95 % Wilson half-width of
|
|
69
|
+
* roughly ±9 points, which is wide but no longer moves on a single prompt the
|
|
70
|
+
* way a 26-row denominator does. Raise it with a dated reason if a decision
|
|
71
|
+
* ever needs a tighter bound than that.
|
|
72
|
+
*/
|
|
73
|
+
export const MIN_POWERED_N = 100;
|
|
74
|
+
|
|
75
|
+
export type CorpusName = 'labelled' | 'routing-matrix' | 'all';
|
|
76
|
+
export const CORPUS_NAMES: readonly CorpusName[] = ['labelled', 'routing-matrix', 'all'];
|
|
77
|
+
|
|
48
78
|
export interface LabelledPrompt {
|
|
49
79
|
id: string;
|
|
50
80
|
corpus: string;
|
|
@@ -94,38 +124,275 @@ export function readLabelledPrompts(repo = REPO): LabelledPrompt[] {
|
|
|
94
124
|
return out;
|
|
95
125
|
}
|
|
96
126
|
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
export interface MatrixCase {
|
|
128
|
+
rule: string;
|
|
129
|
+
section: 'positives' | 'near_misses';
|
|
130
|
+
ordinal: number;
|
|
131
|
+
prompt: string;
|
|
132
|
+
/** `undefined` = the key is missing (a defect the lint catches); `[]` = deliberately unlabelled. */
|
|
133
|
+
expected?: string[];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Every case in the rule routing matrix, with its `expected_skills` label when
|
|
138
|
+
* one is present.
|
|
139
|
+
*
|
|
140
|
+
* Line-oriented for the same reason as the reader above, and because a YAML
|
|
141
|
+
* round-trip through this directory would reformat 100+ hand-kept fixtures.
|
|
142
|
+
* A case is `prompt:` plus the keys indented under it up to the next `- `.
|
|
143
|
+
*/
|
|
144
|
+
export function readMatrixCases(repo = REPO): MatrixCase[] {
|
|
99
145
|
const dir = path.join(repo, MATRIX_DIR);
|
|
100
146
|
if (!fs.existsSync(dir)) return [];
|
|
101
|
-
const out:
|
|
147
|
+
const out: MatrixCase[] = [];
|
|
102
148
|
for (const name of fs.readdirSync(dir).sort()) {
|
|
103
149
|
if (!name.endsWith('.yaml')) continue;
|
|
150
|
+
const rule = name.replace(/\.yaml$/, '');
|
|
151
|
+
let section: MatrixCase['section'] = 'positives';
|
|
152
|
+
let ordinal = 0;
|
|
153
|
+
let current: MatrixCase | undefined;
|
|
104
154
|
for (const raw of fs.readFileSync(path.join(dir, name), 'utf8').split('\n')) {
|
|
105
|
-
const
|
|
106
|
-
if (
|
|
155
|
+
const line = raw.replace(/\r$/, '');
|
|
156
|
+
if (/^positives:\s*$/.test(line)) {
|
|
157
|
+
section = 'positives';
|
|
158
|
+
ordinal = 0;
|
|
159
|
+
current = undefined;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (/^near_misses:\s*$/.test(line)) {
|
|
163
|
+
section = 'near_misses';
|
|
164
|
+
ordinal = 0;
|
|
165
|
+
current = undefined;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const mPrompt = /^\s*-?\s*prompt:\s*"(.*)"\s*$/.exec(line);
|
|
169
|
+
if (mPrompt && mPrompt[1] !== undefined) {
|
|
170
|
+
current = { rule, section, ordinal: ordinal++, prompt: mPrompt[1] };
|
|
171
|
+
out.push(current);
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const mExp = /^\s*expected_skills:\s*\[(.*)\]\s*$/.exec(line);
|
|
175
|
+
if (mExp && current) {
|
|
176
|
+
current.expected = mExp[1]!
|
|
177
|
+
.split(',')
|
|
178
|
+
.map((s) => s.trim())
|
|
179
|
+
.filter(Boolean);
|
|
180
|
+
}
|
|
107
181
|
}
|
|
108
182
|
}
|
|
109
183
|
return out;
|
|
110
184
|
}
|
|
111
185
|
|
|
186
|
+
/** Every `- prompt:` string in the rule routing matrix, label or no label. */
|
|
187
|
+
export function readMatrixPrompts(repo = REPO): string[] {
|
|
188
|
+
return readMatrixCases(repo).map((c) => c.prompt);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** The matrix rows that carry a NON-EMPTY label — the accuracy denominator. */
|
|
192
|
+
export function readMatrixLabelledPrompts(repo = REPO): LabelledPrompt[] {
|
|
193
|
+
return readMatrixCases(repo)
|
|
194
|
+
.filter((c) => (c.expected?.length ?? 0) > 0)
|
|
195
|
+
.map((c) => ({
|
|
196
|
+
id: `${c.rule}#${c.section}[${c.ordinal}]`,
|
|
197
|
+
corpus: 'routing-matrix',
|
|
198
|
+
prompt: c.prompt,
|
|
199
|
+
expected: c.expected!,
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function promptsForCorpus(corpus: CorpusName, repo = REPO): LabelledPrompt[] {
|
|
204
|
+
if (corpus === 'labelled') return readLabelledPrompts(repo);
|
|
205
|
+
if (corpus === 'routing-matrix') return readMatrixLabelledPrompts(repo);
|
|
206
|
+
return [...readLabelledPrompts(repo), ...readMatrixLabelledPrompts(repo)];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Which half of the corpus a row belongs to.
|
|
211
|
+
*
|
|
212
|
+
* `road-to-a-ranker-that-routes` 1.2. Tuning and reading on one corpus of 390
|
|
213
|
+
* overfits it: a signal chosen because it lifted the number on the rows it was
|
|
214
|
+
* chosen from will lift the number on exactly those rows, and the interval
|
|
215
|
+
* printed beside it then describes the fitting rather than the ranker. Every
|
|
216
|
+
* lift claim in Phases 2 and 3 is read on `sealed` only.
|
|
217
|
+
*/
|
|
218
|
+
export type SliceName = 'all' | 'tuning' | 'sealed';
|
|
219
|
+
export const SLICE_NAMES: readonly SliceName[] = ['all', 'tuning', 'sealed'];
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* One row in five — nominally 20 %, measured 19.2 % (75 of 390) on the live
|
|
223
|
+
* corpus, because a hash is not a shuffle and the exact count is a property of
|
|
224
|
+
* the ids.
|
|
225
|
+
*
|
|
226
|
+
* Stated as a modulus rather than a fraction because the partition has to be a
|
|
227
|
+
* pure function of the id: a share applied to a shuffled list would move every
|
|
228
|
+
* row the moment a prompt is added, and the sealed slice would stop being the
|
|
229
|
+
* same slice between two runs of the same measurement.
|
|
230
|
+
*/
|
|
231
|
+
export const SEALED_MODULUS = 5;
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* The slice one case id falls in — deterministic and order-independent.
|
|
235
|
+
*
|
|
236
|
+
* STABILITY UNDER CORPUS CHANGE IS PARTIAL, and an earlier version of this block
|
|
237
|
+
* claimed otherwise. The matrix id is `rule#section[ordinal]` and the ordinal is
|
|
238
|
+
* POSITIONAL — it counts `- prompt:` entries within a section. So:
|
|
239
|
+
*
|
|
240
|
+
* - APPENDING a prompt to the end of a section is stable: every existing row
|
|
241
|
+
* keeps its ordinal, its id, and its side of the seal. This is the workflow
|
|
242
|
+
* the matrix README documents, which is why the partition survives the
|
|
243
|
+
* release-to-release growth the `history` array is for.
|
|
244
|
+
* - INSERTING or DELETING mid-section renumbers every later row in THAT
|
|
245
|
+
* section, which re-hashes them and moves roughly one in five across the
|
|
246
|
+
* seal.
|
|
247
|
+
*
|
|
248
|
+
* A content key (`rule|section|prompt`) would close the second case and is the
|
|
249
|
+
* right shape for the next corpus version. It is deliberately NOT applied here:
|
|
250
|
+
* the signals in Phase 2 were chosen by reading the TUNING rows of this
|
|
251
|
+
* partition, so re-drawing the boundary now would move ~20 % of those rows into
|
|
252
|
+
* the sealed slice and silently contaminate the very claims the seal exists to
|
|
253
|
+
* protect. Changing a partition after choosing on it is worse than a partially
|
|
254
|
+
* stable partition, so the key moves when the corpus does, not before.
|
|
255
|
+
*/
|
|
256
|
+
export function sliceForId(id: string): Exclude<SliceName, 'all'> {
|
|
257
|
+
return fnv1a(id) % SEALED_MODULUS === 0 ? 'sealed' : 'tuning';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** The rows of `prompts` that fall in `slice`; `all` is the identity. */
|
|
261
|
+
export function partitionBySlice<T extends { id: string }>(
|
|
262
|
+
prompts: readonly T[],
|
|
263
|
+
slice: SliceName,
|
|
264
|
+
): T[] {
|
|
265
|
+
if (slice === 'all') return [...prompts];
|
|
266
|
+
return prompts.filter((p) => sliceForId(p.id) === slice);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** How the corpus divides, printed on every run so a reader never assumes it. */
|
|
270
|
+
export interface SliceSizes {
|
|
271
|
+
all: number;
|
|
272
|
+
tuning: number;
|
|
273
|
+
sealed: number;
|
|
274
|
+
sealed_modulus: number;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function sliceSizes(prompts: readonly { id: string }[]): SliceSizes {
|
|
278
|
+
const sealed = prompts.filter((p) => sliceForId(p.id) === 'sealed').length;
|
|
279
|
+
return {
|
|
280
|
+
all: prompts.length,
|
|
281
|
+
tuning: prompts.length - sealed,
|
|
282
|
+
sealed,
|
|
283
|
+
sealed_modulus: SEALED_MODULUS,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* The packs a skill declares, read from its own `packs:` frontmatter block.
|
|
289
|
+
*
|
|
290
|
+
* Line-oriented, and deliberately NOT read from `src/packs/*\/pack.yaml`: those
|
|
291
|
+
* manifests are generated FROM this frontmatter, and four of them
|
|
292
|
+
* (`analytics`, `core`, `memory`, `product-reasoning`) carry no skill at all.
|
|
293
|
+
* A pack with no skill can never own a labelled prompt, so a census over the
|
|
294
|
+
* manifest set would state a floor nothing could ever meet.
|
|
295
|
+
*/
|
|
296
|
+
export function packsForSkill(skillsDir: string, name: string): string[] {
|
|
297
|
+
const file = path.join(skillsDir, name, 'SKILL.md');
|
|
298
|
+
if (!fs.existsSync(file)) return [];
|
|
299
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
300
|
+
if (!text.startsWith('---')) return [];
|
|
301
|
+
const end = text.indexOf('\n---', 3);
|
|
302
|
+
if (end === -1) return [];
|
|
303
|
+
const lines = text.slice(3, end).split('\n');
|
|
304
|
+
const at = lines.findIndex((l) => /^packs:/u.test(l));
|
|
305
|
+
if (at === -1) return [];
|
|
306
|
+
const out: string[] = [];
|
|
307
|
+
for (let i = at + 1; i < lines.length; i += 1) {
|
|
308
|
+
const m = /^\s+-\s+(\S+)\s*$/u.exec(lines[i] as string);
|
|
309
|
+
if (!m) break;
|
|
310
|
+
out.push(m[1] as string);
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Every pack id that at least one shipped skill declares. The census domain. */
|
|
316
|
+
export function allPacks(skillsDir: string): string[] {
|
|
317
|
+
const packs = new Set<string>();
|
|
318
|
+
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
319
|
+
if (!entry.isDirectory()) continue;
|
|
320
|
+
for (const p of packsForSkill(skillsDir, entry.name)) packs.add(p);
|
|
321
|
+
}
|
|
322
|
+
return [...packs].sort();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* How many labelled prompts each pack owns, via the packs of its expected skills.
|
|
327
|
+
*
|
|
328
|
+
* A prompt counts ONCE per pack however many of that pack's skills it expects —
|
|
329
|
+
* otherwise a single prompt naming three `laravel` skills would satisfy a
|
|
330
|
+
* three-prompt floor on its own, which is the shape of coverage this census
|
|
331
|
+
* exists to refuse.
|
|
332
|
+
*/
|
|
333
|
+
export function packCensus(prompts: readonly LabelledPrompt[], skillsDir: string): Record<string, number> {
|
|
334
|
+
const out: Record<string, number> = {};
|
|
335
|
+
for (const p of allPacks(skillsDir)) out[p] = 0;
|
|
336
|
+
for (const prompt of prompts) {
|
|
337
|
+
const packs = new Set<string>();
|
|
338
|
+
for (const skill of prompt.expected) for (const pack of packsForSkill(skillsDir, skill)) packs.add(pack);
|
|
339
|
+
for (const pack of packs) out[pack] = (out[pack] ?? 0) + 1;
|
|
340
|
+
}
|
|
341
|
+
return out;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** Packs owning fewer than `floor` labelled prompts, sorted by pack id. */
|
|
345
|
+
export function packsBelow(census: Record<string, number>, floor: number): string[] {
|
|
346
|
+
return Object.keys(census)
|
|
347
|
+
.filter((p) => (census[p] ?? 0) < floor)
|
|
348
|
+
.sort();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** The per-pack floor `road-to-a-menu-whose-precision-is-measured` 1.1 states. */
|
|
352
|
+
export const MIN_PROMPTS_PER_PACK = 3;
|
|
353
|
+
|
|
354
|
+
export interface Interval {
|
|
355
|
+
lower: number;
|
|
356
|
+
upper: number;
|
|
357
|
+
}
|
|
358
|
+
|
|
112
359
|
export interface AccuracyArm {
|
|
360
|
+
corpus: CorpusName;
|
|
361
|
+
/** Which half of the corpus this arm read. `all` is the whole of it. */
|
|
362
|
+
slice: SliceName;
|
|
363
|
+
/** The division of the FULL corpus, printed whichever slice was read. */
|
|
364
|
+
slice_sizes: SliceSizes;
|
|
113
365
|
corpus_prompts: number;
|
|
114
366
|
top1: number;
|
|
367
|
+
top1_ci95: Interval;
|
|
115
368
|
top3: number;
|
|
369
|
+
top3_ci95: Interval;
|
|
370
|
+
/** `underpowered` below MIN_POWERED_N labelled rows; `measured` at or above. */
|
|
371
|
+
verdict: 'underpowered' | 'measured';
|
|
372
|
+
min_powered_n: number;
|
|
116
373
|
misses: string[];
|
|
117
374
|
denominator_note: string;
|
|
375
|
+
/** Pack ids at least one shipped skill declares — the census domain. */
|
|
376
|
+
packs_total: number;
|
|
377
|
+
min_prompts_per_pack: number;
|
|
378
|
+
/** Packs this corpus leaves under the floor. Empty is the passing shape. */
|
|
379
|
+
packs_below_floor: string[];
|
|
380
|
+
/** Full census, so a reader can see the distribution and not just the failures. */
|
|
381
|
+
pack_census: Record<string, number>;
|
|
118
382
|
}
|
|
119
383
|
|
|
120
384
|
export interface CoverageArm {
|
|
121
385
|
corpus_prompts: number;
|
|
386
|
+
labelled_prompts: number;
|
|
387
|
+
unlabelled_prompts: number;
|
|
388
|
+
missing_label_key: number;
|
|
122
389
|
prompts_with_any_result: number;
|
|
123
390
|
mean_top_score: number;
|
|
124
391
|
note: string;
|
|
125
392
|
}
|
|
126
393
|
|
|
127
394
|
export interface RankerBaseline {
|
|
128
|
-
schema:
|
|
395
|
+
schema: 2;
|
|
129
396
|
ranker: string;
|
|
130
397
|
commit: string;
|
|
131
398
|
skills_dir: string;
|
|
@@ -139,28 +406,150 @@ function hitAt(rows: readonly (readonly [string, number, string[]])[], n: number
|
|
|
139
406
|
return expected.some((e) => top.includes(e));
|
|
140
407
|
}
|
|
141
408
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
409
|
+
function round3(n: number): number {
|
|
410
|
+
return Math.round(n * 1000) / 1000;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function ci(successes: number, trials: number): Interval {
|
|
414
|
+
const raw = wilsonInterval(successes, trials);
|
|
415
|
+
return { lower: round3(raw.lower), upper: round3(raw.upper) };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const DENOMINATOR_NOTES: Record<CorpusName, string> = {
|
|
419
|
+
labelled:
|
|
420
|
+
'tests/eval/corpus-dev.yaml + corpus-non-dev.yaml — the two hand-written eval corpora. ' +
|
|
421
|
+
'Small; a single prompt moves each rate by ~4 points, which is why the interval is ' +
|
|
422
|
+
'printed beside the point estimate and not instead of it.',
|
|
423
|
+
'routing-matrix':
|
|
424
|
+
'tests/eval/routing-matrix/ rows whose expected_skills list is NON-EMPTY. A row with an ' +
|
|
425
|
+
'empty list is a deliberate "no skill expectation" and is excluded from the ' +
|
|
426
|
+
'denominator — never counted as a miss.',
|
|
427
|
+
all:
|
|
428
|
+
'Both labelled sources pooled. The two were written under different protocols, so a ' +
|
|
429
|
+
'pooled rate is a convenience reading and the per-corpus arms are the citable ones.',
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
export function measureAccuracy(opts: {
|
|
433
|
+
corpus: CorpusName;
|
|
434
|
+
repo: string;
|
|
435
|
+
skillsDir: string;
|
|
436
|
+
rankOpts: RankOptions;
|
|
437
|
+
slice?: SliceName;
|
|
438
|
+
}): AccuracyArm {
|
|
439
|
+
const slice = opts.slice ?? 'all';
|
|
440
|
+
const whole = promptsForCorpus(opts.corpus, opts.repo);
|
|
441
|
+
const labelled = partitionBySlice(whole, slice);
|
|
149
442
|
let top1 = 0;
|
|
150
443
|
let top3 = 0;
|
|
151
444
|
const misses: string[] = [];
|
|
152
445
|
for (const p of labelled) {
|
|
153
|
-
const rows = rank(p.prompt, skillsDir, rankOpts);
|
|
446
|
+
const rows = rank(p.prompt, opts.skillsDir, opts.rankOpts);
|
|
154
447
|
if (hitAt(rows, 1, p.expected)) top1++;
|
|
155
448
|
if (hitAt(rows, 3, p.expected)) top3++;
|
|
156
449
|
else misses.push(p.id);
|
|
157
450
|
}
|
|
451
|
+
const n = labelled.length;
|
|
452
|
+
const census = packCensus(labelled, opts.skillsDir);
|
|
453
|
+
return {
|
|
454
|
+
corpus: opts.corpus,
|
|
455
|
+
slice,
|
|
456
|
+
slice_sizes: sliceSizes(whole),
|
|
457
|
+
corpus_prompts: n,
|
|
458
|
+
top1: n ? round3(top1 / n) : 0,
|
|
459
|
+
top1_ci95: ci(top1, n),
|
|
460
|
+
top3: n ? round3(top3 / n) : 0,
|
|
461
|
+
top3_ci95: ci(top3, n),
|
|
462
|
+
verdict: n >= MIN_POWERED_N ? 'measured' : 'underpowered',
|
|
463
|
+
min_powered_n: MIN_POWERED_N,
|
|
464
|
+
misses,
|
|
465
|
+
denominator_note: DENOMINATOR_NOTES[opts.corpus],
|
|
466
|
+
packs_total: Object.keys(census).length,
|
|
467
|
+
min_prompts_per_pack: MIN_PROMPTS_PER_PACK,
|
|
468
|
+
packs_below_floor: packsBelow(census, MIN_PROMPTS_PER_PACK),
|
|
469
|
+
pack_census: census,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* The ranker label → the options it means.
|
|
475
|
+
*
|
|
476
|
+
* One table rather than a conditional at each call site, because a measurement
|
|
477
|
+
* harness that resolves `--ranker` differently from the report that quotes it
|
|
478
|
+
* is a comparison of two things under one name. Every entry past `keyword-v1`
|
|
479
|
+
* is a candidate configuration under `road-to-a-ranker-that-routes` Phase 2,
|
|
480
|
+
* each a single flag so it can be measured alone, plus the combinations the
|
|
481
|
+
* same phase names.
|
|
482
|
+
*
|
|
483
|
+
* AN UNKNOWN LABEL THROWS. It used to resolve to `keyword-v1` — the baseline —
|
|
484
|
+
* which is the exact failure this table exists to prevent: every consumer
|
|
485
|
+
* echoes the requested label back into its output, so a typo published a
|
|
486
|
+
* BASELINE number under another configuration's name, in the report's own title
|
|
487
|
+
* and in the regenerate command it prints beside it. The two sibling parsers in
|
|
488
|
+
* this file refuse an unknown value and so does the sweep; the lenient branch
|
|
489
|
+
* was the inconsistent one.
|
|
490
|
+
*/
|
|
491
|
+
export const RANKER_LABELS: Readonly<Record<string, RankOptions>> = {
|
|
492
|
+
'keyword-v1': {},
|
|
493
|
+
'keyword-v2': { includeTriggers: true },
|
|
494
|
+
'when-to-use': { includeWhenToUse: true },
|
|
495
|
+
headings: { includeHeadings: true },
|
|
496
|
+
idf: { idfWeighting: true },
|
|
497
|
+
'idf+when-to-use': { idfWeighting: true, includeWhenToUse: true },
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* The message carries NO tool name.
|
|
502
|
+
*
|
|
503
|
+
* Three scripts resolve `--ranker` through this module now, so a hardcoded
|
|
504
|
+
* prefix would print one tool's name when another was the failing command. The
|
|
505
|
+
* caller's own `process.stderr` line is where the command is identified.
|
|
506
|
+
*/
|
|
507
|
+
export class UnknownRankerLabel extends Error {
|
|
508
|
+
constructor(label: string) {
|
|
509
|
+
super(
|
|
510
|
+
`unknown --ranker ${label || '(nothing)'}; ` +
|
|
511
|
+
`known: ${Object.keys(RANKER_LABELS).join(' | ')}`,
|
|
512
|
+
);
|
|
513
|
+
this.name = 'UnknownRankerLabel';
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/** Whether `label` is one of the table's OWN keys — never an inherited one. */
|
|
518
|
+
export function isKnownRanker(label: string): boolean {
|
|
519
|
+
return Object.hasOwn(RANKER_LABELS, label);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export function rankOptionsFor(ranker: string): RankOptions {
|
|
523
|
+
// `Object.hasOwn`, not a truthiness check on the lookup: `RANKER_LABELS`
|
|
524
|
+
// is an object literal, so `constructor`, `toString` and `valueOf` resolve
|
|
525
|
+
// to inherited FUNCTIONS rather than to undefined. A plain `=== undefined`
|
|
526
|
+
// guard lets those three through, scores them as the baseline, and echoes
|
|
527
|
+
// the label into the report title — which is the whole defect this guard
|
|
528
|
+
// was added to close, surviving in its own fix.
|
|
529
|
+
if (!isKnownRanker(ranker)) throw new UnknownRankerLabel(ranker);
|
|
530
|
+
return RANKER_LABELS[ranker] as RankOptions;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export function measure(opts: {
|
|
534
|
+
ranker: string;
|
|
535
|
+
commit: string;
|
|
536
|
+
corpus?: CorpusName;
|
|
537
|
+
slice?: SliceName;
|
|
538
|
+
skillsDir?: string;
|
|
539
|
+
repo?: string;
|
|
540
|
+
}): RankerBaseline {
|
|
541
|
+
const repo = opts.repo ?? REPO;
|
|
542
|
+
const skillsDir = opts.skillsDir ?? SKILLS_DIR;
|
|
543
|
+
// Resolved through the one table, which throws on a label it does not know.
|
|
544
|
+
const rankOpts: RankOptions = rankOptionsFor(opts.ranker);
|
|
545
|
+
const corpus = opts.corpus ?? 'labelled';
|
|
546
|
+
const accuracy = measureAccuracy({ corpus, repo, skillsDir, rankOpts, slice: opts.slice ?? 'all' });
|
|
158
547
|
|
|
159
|
-
const
|
|
548
|
+
const cases = readMatrixCases(repo);
|
|
160
549
|
let withResult = 0;
|
|
161
550
|
let scoreSum = 0;
|
|
162
|
-
for (const
|
|
163
|
-
const rows = rank(prompt, skillsDir, rankOpts);
|
|
551
|
+
for (const c of cases) {
|
|
552
|
+
const rows = rank(c.prompt, skillsDir, rankOpts);
|
|
164
553
|
if (rows.length > 0) {
|
|
165
554
|
withResult++;
|
|
166
555
|
scoreSum += rows[0]![1];
|
|
@@ -172,37 +561,110 @@ export function measure(opts: { ranker: string; commit: string; skillsDir?: stri
|
|
|
172
561
|
: 0;
|
|
173
562
|
|
|
174
563
|
return {
|
|
175
|
-
schema:
|
|
564
|
+
schema: 2,
|
|
176
565
|
ranker: opts.ranker,
|
|
177
566
|
commit: opts.commit,
|
|
178
567
|
skills_dir: path.relative(repo, skillsDir),
|
|
179
568
|
skills_indexed: skillsIndexed,
|
|
180
|
-
accuracy
|
|
181
|
-
corpus_prompts: labelled.length,
|
|
182
|
-
top1: labelled.length ? Math.round((top1 / labelled.length) * 1000) / 1000 : 0,
|
|
183
|
-
top3: labelled.length ? Math.round((top3 / labelled.length) * 1000) / 1000 : 0,
|
|
184
|
-
misses,
|
|
185
|
-
denominator_note:
|
|
186
|
-
'tests/eval/corpus-dev.yaml + corpus-non-dev.yaml — the only expected-skill ground ' +
|
|
187
|
-
'truth in this tree. Small; a single prompt moves each rate by ~4 points.',
|
|
188
|
-
},
|
|
569
|
+
accuracy,
|
|
189
570
|
matrix_coverage: {
|
|
190
|
-
corpus_prompts:
|
|
571
|
+
corpus_prompts: cases.length,
|
|
572
|
+
labelled_prompts: cases.filter((c) => (c.expected?.length ?? 0) > 0).length,
|
|
573
|
+
unlabelled_prompts: cases.filter((c) => c.expected?.length === 0).length,
|
|
574
|
+
missing_label_key: cases.filter((c) => c.expected === undefined).length,
|
|
191
575
|
prompts_with_any_result: withResult,
|
|
192
576
|
mean_top_score: withResult ? Math.round((scoreSum / withResult) * 100) / 100 : 0,
|
|
193
577
|
note:
|
|
194
|
-
'
|
|
195
|
-
'
|
|
196
|
-
'
|
|
197
|
-
'and
|
|
578
|
+
'Coverage over EVERY matrix case, labelled or not: whether the ranker answers at ' +
|
|
579
|
+
'all and how confident its top answer is. Accuracy over the labelled subset is ' +
|
|
580
|
+
'the `accuracy` arm under `--corpus routing-matrix`. Size is measured here, never ' +
|
|
581
|
+
'asserted: 496 and 499 are both published elsewhere and both stale.',
|
|
198
582
|
},
|
|
199
583
|
};
|
|
200
584
|
}
|
|
201
585
|
|
|
586
|
+
function parseCorpus(argv: readonly string[]): CorpusName {
|
|
587
|
+
const i = argv.indexOf('--corpus');
|
|
588
|
+
if (i === -1) return 'labelled';
|
|
589
|
+
const raw = argv[i + 1];
|
|
590
|
+
if (!raw || !CORPUS_NAMES.includes(raw as CorpusName)) {
|
|
591
|
+
throw new Error(
|
|
592
|
+
`measure_skill_ranker_baseline: --corpus expects one of ${CORPUS_NAMES.join(' | ')}, got ${raw ?? '(nothing)'}`,
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
return raw as CorpusName;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* The `--ranker` value, or the baseline when the flag is absent.
|
|
600
|
+
*
|
|
601
|
+
* A PRESENT flag with no value after it is an error, not an omission — the
|
|
602
|
+
* sibling `--slice` has always refused that shape, and substituting the
|
|
603
|
+
* baseline for a malformed flag is the same silent-fallback defect one level
|
|
604
|
+
* up from the label table.
|
|
605
|
+
*/
|
|
606
|
+
export function parseRanker(argv: readonly string[]): string {
|
|
607
|
+
const i = argv.indexOf('--ranker');
|
|
608
|
+
if (i === -1) return 'keyword-v1';
|
|
609
|
+
const raw = argv[i + 1];
|
|
610
|
+
if (!raw || raw.startsWith('--')) {
|
|
611
|
+
throw new Error(
|
|
612
|
+
`--ranker expects one of ${Object.keys(RANKER_LABELS).join(' | ')}, got ${raw ?? '(nothing)'}`,
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
return raw;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* A flag's value, or `fallback` when the flag is absent.
|
|
620
|
+
*
|
|
621
|
+
* A PRESENT flag followed by nothing — or by the next flag — is an error. Both
|
|
622
|
+
* `--commit` and `--date` are echoed verbatim into published artifacts (the
|
|
623
|
+
* baseline's provenance field, the confusion report's own header), so
|
|
624
|
+
* `--commit --ranker idf` silently publishing `--ranker` as the commit is the
|
|
625
|
+
* same silent-substitution class `parseRanker` was written to close, two flags
|
|
626
|
+
* over in the same two functions.
|
|
627
|
+
*/
|
|
628
|
+
export function parseFlagValue(argv: readonly string[], flag: string, fallback: string): string {
|
|
629
|
+
const i = argv.indexOf(flag);
|
|
630
|
+
if (i === -1) return fallback;
|
|
631
|
+
const raw = argv[i + 1];
|
|
632
|
+
if (!raw || raw.startsWith('--')) {
|
|
633
|
+
throw new Error(`${flag} expects a value, got ${raw ?? '(nothing)'}`);
|
|
634
|
+
}
|
|
635
|
+
return raw;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export function parseSlice(argv: readonly string[]): SliceName {
|
|
639
|
+
const i = argv.indexOf('--slice');
|
|
640
|
+
if (i === -1) return 'all';
|
|
641
|
+
const raw = argv[i + 1];
|
|
642
|
+
if (!raw || !SLICE_NAMES.includes(raw as SliceName)) {
|
|
643
|
+
throw new Error(
|
|
644
|
+
`measure_skill_ranker_baseline: --slice expects one of ${SLICE_NAMES.join(' | ')}, got ${raw ?? '(nothing)'}`,
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
return raw as SliceName;
|
|
648
|
+
}
|
|
649
|
+
|
|
202
650
|
export function main(argv: readonly string[]): number {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
651
|
+
let corpus: CorpusName;
|
|
652
|
+
let slice: SliceName;
|
|
653
|
+
let ranker: string;
|
|
654
|
+
let commit: string;
|
|
655
|
+
let out: RankerBaseline;
|
|
656
|
+
try {
|
|
657
|
+
corpus = parseCorpus(argv);
|
|
658
|
+
slice = parseSlice(argv);
|
|
659
|
+
ranker = parseRanker(argv);
|
|
660
|
+
commit = parseFlagValue(argv, '--commit', 'unknown');
|
|
661
|
+
// Inside the same guard as the two parsers above: an unknown --ranker is
|
|
662
|
+
// the same class of mistake and now gets the same exit code.
|
|
663
|
+
out = measure({ ranker, commit, corpus, slice });
|
|
664
|
+
} catch (err) {
|
|
665
|
+
process.stderr.write(`${(err as Error).message}\n`);
|
|
666
|
+
return 2;
|
|
667
|
+
}
|
|
206
668
|
process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
|
|
207
669
|
return 0;
|
|
208
670
|
}
|