@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
|
@@ -39,11 +39,14 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
39
39
|
// a second copy (road-to-skill-delivery-over-mcp risk 6). Everything below is
|
|
40
40
|
// the disk half — globbing, frontmatter, the CLI — which stays here.
|
|
41
41
|
import {
|
|
42
|
+
buildTermStats,
|
|
42
43
|
scoreSkill,
|
|
43
44
|
skillTerms as _sharedSkillTerms,
|
|
44
45
|
tokenize as _sharedTokenize,
|
|
45
46
|
triggerTextFromFlatLines,
|
|
47
|
+
widensTermSource,
|
|
46
48
|
type RankOptions,
|
|
49
|
+
type TermStats,
|
|
47
50
|
} from '../../shared/skillRanking.js';
|
|
48
51
|
|
|
49
52
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -67,6 +70,20 @@ export const ROOT = path.resolve(path.dirname(_HERE), '..', '..', '..');
|
|
|
67
70
|
* CLI turns that into a distinct exit code rather than an empty list.
|
|
68
71
|
*/
|
|
69
72
|
import { DEFAULT_CATALOGUE_ROOTS, resolveSkillCatalogueRoots } from '../_lib/skill_catalogue.js';
|
|
73
|
+
// Authorship + scan primitives only. Deliberately NOT `neighbour_census.js`,
|
|
74
|
+
// whose module graph reaches the host-hook merger, the secret detector and the
|
|
75
|
+
// install-ownership reader — this module is inlined into the shared hook bundle,
|
|
76
|
+
// where every byte is paid by every concern on every dispatch.
|
|
77
|
+
import {
|
|
78
|
+
fileDigest,
|
|
79
|
+
makeSkillOriginResolver,
|
|
80
|
+
qualifiedSkillName,
|
|
81
|
+
readScanCache,
|
|
82
|
+
scanCachePath,
|
|
83
|
+
scanVerdict,
|
|
84
|
+
type ScanCache,
|
|
85
|
+
type SkillOrigin,
|
|
86
|
+
} from '../_lib/skill_origin.js';
|
|
70
87
|
|
|
71
88
|
/**
|
|
72
89
|
* Every readable catalogue root, in precedence order — possibly empty.
|
|
@@ -100,7 +117,17 @@ export interface Frontmatter {
|
|
|
100
117
|
export function _parse_frontmatter(filePath: string): Frontmatter {
|
|
101
118
|
// text.read_text(errors="replace") — Node `utf-8` decode replaces the same
|
|
102
119
|
// way for the inputs these tools see (well-formed SKILL.md files).
|
|
103
|
-
|
|
120
|
+
return _parse_frontmatter_text(fs.readFileSync(filePath, 'utf-8'));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The same reader over text already in hand.
|
|
125
|
+
*
|
|
126
|
+
* The loader needs the body as well as the frontmatter, and reading each
|
|
127
|
+
* SKILL.md twice to get them would double the per-call I/O of a ranker that
|
|
128
|
+
* runs on a hook path.
|
|
129
|
+
*/
|
|
130
|
+
export function _parse_frontmatter_text(text: string): Frontmatter {
|
|
104
131
|
if (!text.startsWith('---')) {
|
|
105
132
|
return {};
|
|
106
133
|
}
|
|
@@ -164,38 +191,204 @@ function _rstrip(s: string): string {
|
|
|
164
191
|
|
|
165
192
|
export interface Skill {
|
|
166
193
|
name: string;
|
|
194
|
+
/**
|
|
195
|
+
* Where the skill came from — `package` for ours, `project` / `home` for a
|
|
196
|
+
* neighbour another installer put in a root this ranker unions in.
|
|
197
|
+
*/
|
|
198
|
+
origin: SkillOrigin;
|
|
199
|
+
/** What a route line prints: `name` for ours, `origin:name` otherwise. */
|
|
200
|
+
qualified: string;
|
|
201
|
+
/**
|
|
202
|
+
* Finding kind when a neighbour body did not pass the shape scan, else
|
|
203
|
+
* `null`. Such a skill is still ranked — by its NAME only; see
|
|
204
|
+
* {@link _load_skills}.
|
|
205
|
+
*/
|
|
206
|
+
unscanned: string | null;
|
|
167
207
|
description: string;
|
|
168
208
|
personas: string[];
|
|
169
209
|
terms: Set<string>;
|
|
170
210
|
/** `triggers[].keyword` / `.phrase` prose. Indexed only under keyword-v2. */
|
|
171
211
|
triggerText: string[];
|
|
212
|
+
/** The body's `## When to use` section. Indexed only behind its own flag. */
|
|
213
|
+
whenToUseText: string;
|
|
214
|
+
/** The body's `##` / `###` heading lines. Indexed only behind its own flag. */
|
|
215
|
+
headingText: string[];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Everything after the frontmatter block, or the whole text when there is none. */
|
|
219
|
+
export function _body_of(text: string): string {
|
|
220
|
+
if (!text.startsWith('---')) return text;
|
|
221
|
+
const end = text.indexOf('\n---', 3);
|
|
222
|
+
if (end === -1) return text;
|
|
223
|
+
return text.slice(end + 4);
|
|
172
224
|
}
|
|
173
225
|
|
|
174
226
|
/**
|
|
175
|
-
*
|
|
227
|
+
* The `## When to use` section, and every `##` / `###` heading, out of a body.
|
|
228
|
+
*
|
|
229
|
+
* Line-oriented, and bounded in two ways that a first version got wrong in the
|
|
230
|
+
* same direction — it indexed something other than what this block describes,
|
|
231
|
+
* which makes a measurement of the FLAG a measurement of the PARSER:
|
|
176
232
|
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
233
|
+
* - the section ends at the next heading of the SAME OR A HIGHER level, so a
|
|
234
|
+
* `###` subsection of `## When to use` stays inside it. Ending at any
|
|
235
|
+
* heading truncated the capture at the first subsection;
|
|
236
|
+
* - a line inside a fenced code block is never a heading. These skills are
|
|
237
|
+
* documentation and routinely fence markdown samples, so a `## …` line in a
|
|
238
|
+
* fence was both harvested as a topic and used to terminate the section.
|
|
239
|
+
*
|
|
240
|
+
* Without the first bound a skill whose whole file is one section could still
|
|
241
|
+
* not put its procedure into an index whose flag says "when to use", because a
|
|
242
|
+
* sibling `##` ends it.
|
|
243
|
+
*/
|
|
244
|
+
export function _body_signals(body: string): { whenToUse: string; headings: string[] } {
|
|
245
|
+
const headings: string[] = [];
|
|
246
|
+
const when: string[] = [];
|
|
247
|
+
let whenLevel = 0;
|
|
248
|
+
let fenceMark: string | null = null;
|
|
249
|
+
let fenceLen = 0;
|
|
250
|
+
for (const raw of body.split('\n')) {
|
|
251
|
+
const line = raw.trimEnd();
|
|
252
|
+
const f = /^\s*(`{3,}|~{3,})(.*)$/.exec(line);
|
|
253
|
+
if (f) {
|
|
254
|
+
const run = f[1] as string;
|
|
255
|
+
const mark = run[0] as string;
|
|
256
|
+
if (fenceMark === null) {
|
|
257
|
+
fenceMark = mark;
|
|
258
|
+
fenceLen = run.length;
|
|
259
|
+
// The DELIMITER and its info string are not prose. Pushing them
|
|
260
|
+
// put the language tag of every fenced sample (`bash`, `yaml`)
|
|
261
|
+
// into the index, which is the parser leaking into the signal in
|
|
262
|
+
// the opposite direction from the truncation this block fixed.
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
// A closing fence has to be at least as long as the opening one and
|
|
266
|
+
// use the same marker; otherwise a ``` inside a ```` block would
|
|
267
|
+
// close it early.
|
|
268
|
+
if (mark === fenceMark && run.length >= fenceLen && (f[2] as string).trim() === '') {
|
|
269
|
+
fenceMark = null;
|
|
270
|
+
fenceLen = 0;
|
|
271
|
+
}
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (fenceMark !== null) {
|
|
275
|
+
if (whenLevel > 0) when.push(raw);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
// `#{1,6}`, not `#{2,6}`: a level-1 heading is strictly HIGHER than the
|
|
279
|
+
// section and must close it. Matching only `##`+ let a `# New Section`
|
|
280
|
+
// and everything after it leak into an open capture.
|
|
281
|
+
const h = /^(#{1,6})\s+(.*)$/.exec(line);
|
|
282
|
+
if (h) {
|
|
283
|
+
const level = (h[1] as string).length;
|
|
284
|
+
const title = (h[2] as string).trim();
|
|
285
|
+
if (level >= 2 && level <= 3) headings.push(title);
|
|
286
|
+
if (whenLevel > 0 && level <= whenLevel) {
|
|
287
|
+
whenLevel = 0;
|
|
288
|
+
} else if (whenLevel > 0) {
|
|
289
|
+
// A SUBSECTION TITLE inside `## When to use` is part of that
|
|
290
|
+
// section's text. Skipping it indexed the prose under a `### Do
|
|
291
|
+
// NOT use when` while dropping the words that say what it is.
|
|
292
|
+
when.push(title);
|
|
293
|
+
}
|
|
294
|
+
// Only OPEN a section when none is open. Assigning unconditionally
|
|
295
|
+
// let a `### When to use it on a monorepo` overwrite the outer
|
|
296
|
+
// level 2 with 3, after which the next sibling `###` satisfied
|
|
297
|
+
// `level <= whenLevel` and closed the section early — silently
|
|
298
|
+
// dropping everything from that sibling to the real end.
|
|
299
|
+
if (whenLevel === 0 && /^when to use\b/i.test(title)) whenLevel = level;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (whenLevel > 0) when.push(raw);
|
|
303
|
+
}
|
|
304
|
+
return { whenToUse: when.join(' ').trim(), headings };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Everything a load needs to know about who owns a file and whether its body was
|
|
309
|
+
* scanned. Built once per `rank` call, never per file.
|
|
181
310
|
*/
|
|
182
|
-
|
|
311
|
+
export interface NeighbourContext {
|
|
312
|
+
origin: (skillMdPath: string) => SkillOrigin;
|
|
313
|
+
scans: ScanCache | null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* The context for a workspace: manifest-backed origins plus the scan cache.
|
|
318
|
+
*
|
|
319
|
+
* Built once per `rank` call rather than per file — one manifest read and one
|
|
320
|
+
* cache read for a catalogue of several hundred entries.
|
|
321
|
+
*/
|
|
322
|
+
export function defaultNeighbourContext(workspaceRoot: string = ROOT): NeighbourContext {
|
|
323
|
+
return {
|
|
324
|
+
origin: makeSkillOriginResolver(workspaceRoot, { packageRoot: ROOT }),
|
|
325
|
+
scans: readScanCache(scanCachePath(workspaceRoot)),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Load one root, or several, with the FIRST occurrence of a QUALIFIED name winning.
|
|
331
|
+
*
|
|
332
|
+
* **It used to dedupe on the bare name, and that was the defect.** Every root is
|
|
333
|
+
* read, so a second package's `design-system` in `~/.claude/skills` and ours both
|
|
334
|
+
* reached this loop — and whichever root came second was dropped, silently, with
|
|
335
|
+
* the surviving row printing one bare name. The reader could not tell which skill
|
|
336
|
+
* the route line meant, and in the direction where the neighbour came first, ours
|
|
337
|
+
* was simply gone.
|
|
338
|
+
*
|
|
339
|
+
* Deduping on the qualified name keeps the only collision that is genuinely a
|
|
340
|
+
* duplicate — the same PACKAGE skill reached through two roots, which is the
|
|
341
|
+
* authored tree beside its own projection — and lets a collision between two
|
|
342
|
+
* different owners rank twice, which is the thing a reader needs to see. A
|
|
343
|
+
* no-manifest tree labels everything `package` (`makeOriginResolver`), so there
|
|
344
|
+
* the behavior is byte-identical to the bare-name dedupe it replaced.
|
|
345
|
+
*/
|
|
346
|
+
function _load_skills_across(
|
|
347
|
+
roots: readonly string[],
|
|
348
|
+
opts: RankOptions = {},
|
|
349
|
+
ctx?: NeighbourContext,
|
|
350
|
+
): Skill[] {
|
|
351
|
+
const context = ctx ?? defaultNeighbourContext();
|
|
183
352
|
const out: Skill[] = [];
|
|
184
353
|
const seen = new Set<string>();
|
|
185
354
|
for (const root of roots) {
|
|
186
|
-
for (const s of _load_skills(root)) {
|
|
187
|
-
if (seen.has(s.
|
|
188
|
-
seen.add(s.
|
|
355
|
+
for (const s of _load_skills(root, opts, context)) {
|
|
356
|
+
if (seen.has(s.qualified)) continue;
|
|
357
|
+
seen.add(s.qualified);
|
|
189
358
|
out.push(s);
|
|
190
359
|
}
|
|
191
360
|
}
|
|
192
361
|
return out;
|
|
193
362
|
}
|
|
194
363
|
|
|
195
|
-
|
|
364
|
+
/**
|
|
365
|
+
* One root's skills.
|
|
366
|
+
*
|
|
367
|
+
* A NEIGHBOUR whose body did not pass the shape scan is loaded with every term
|
|
368
|
+
* source but its name emptied — description, triggers, `## When to use`,
|
|
369
|
+
* headings and personas — so it ranks by name and nothing from the file can
|
|
370
|
+
* reach the index or, through it, the injected route line. It is NOT dropped:
|
|
371
|
+
* a skill hidden for a finding is a skill the reader cannot weigh, and the
|
|
372
|
+
* finding kind rides along on `unscanned` instead.
|
|
373
|
+
*
|
|
374
|
+
* "Did not pass" includes "was never scanned". `scanVerdict` refuses a missing
|
|
375
|
+
* census record and a stale digest as firmly as a real finding, which is what
|
|
376
|
+
* makes this a floor rather than a preference — a gate that passes on missing
|
|
377
|
+
* evidence is satisfied by deleting the evidence.
|
|
378
|
+
*/
|
|
379
|
+
function _load_skills(
|
|
380
|
+
skillsDir: string,
|
|
381
|
+
opts: RankOptions = {},
|
|
382
|
+
ctx: NeighbourContext = defaultNeighbourContext(),
|
|
383
|
+
): Skill[] {
|
|
384
|
+
// The body is parsed only when a flag indexes it. Under keyword-v1 the
|
|
385
|
+
// loader's work is exactly what it always was, which is what keeps the
|
|
386
|
+
// default path's per-prompt cost comparable to the pre-flag reading.
|
|
387
|
+
const wantsBody = Boolean(opts.includeWhenToUse || opts.includeHeadings);
|
|
196
388
|
const skills: Skill[] = [];
|
|
197
389
|
for (const skillMd of _globSkillMd(skillsDir)) {
|
|
198
|
-
const
|
|
390
|
+
const text = fs.readFileSync(skillMd, 'utf-8');
|
|
391
|
+
const fm = _parse_frontmatter_text(text);
|
|
199
392
|
const rawName = fm['name'];
|
|
200
393
|
const name = _truthyStr(rawName) ? String(rawName) : path.basename(path.dirname(skillMd));
|
|
201
394
|
const rawDesc = fm['description'];
|
|
@@ -209,12 +402,41 @@ function _load_skills(skillsDir: string): Skill[] {
|
|
|
209
402
|
const triggerText = Array.isArray(rawTriggers)
|
|
210
403
|
? triggerTextFromFlatLines(rawTriggers as string[])
|
|
211
404
|
: [];
|
|
405
|
+
const { whenToUse, headings } = wantsBody
|
|
406
|
+
? _body_signals(_body_of(text))
|
|
407
|
+
: { whenToUse: '', headings: [] as string[] };
|
|
408
|
+
const origin = ctx.origin(skillMd);
|
|
409
|
+
const qualified = qualifiedSkillName(name, origin);
|
|
410
|
+
const verdict =
|
|
411
|
+
origin === 'package'
|
|
412
|
+
? ({ ok: true } as const)
|
|
413
|
+
: scanVerdict(ctx.scans, qualified, fileDigest(skillMd));
|
|
414
|
+
if (!verdict.ok) {
|
|
415
|
+
skills.push({
|
|
416
|
+
name,
|
|
417
|
+
origin,
|
|
418
|
+
qualified,
|
|
419
|
+
unscanned: verdict.kind,
|
|
420
|
+
description: '',
|
|
421
|
+
personas: [],
|
|
422
|
+
terms: _tokenize(name),
|
|
423
|
+
triggerText: [],
|
|
424
|
+
whenToUseText: '',
|
|
425
|
+
headingText: [],
|
|
426
|
+
});
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
212
429
|
skills.push({
|
|
213
430
|
name,
|
|
431
|
+
origin,
|
|
432
|
+
qualified,
|
|
433
|
+
unscanned: null,
|
|
214
434
|
description: desc,
|
|
215
435
|
personas: personaList,
|
|
216
436
|
terms: _tokenize(name + ' ' + desc),
|
|
217
437
|
triggerText,
|
|
438
|
+
whenToUseText: whenToUse,
|
|
439
|
+
headingText: headings,
|
|
218
440
|
});
|
|
219
441
|
}
|
|
220
442
|
return skills;
|
|
@@ -234,7 +456,7 @@ function _truthyStr(v: string | string[] | undefined): boolean {
|
|
|
234
456
|
* Python sorts `Path` objects component-wise. Since every match is
|
|
235
457
|
* `<dir>/SKILL.md`, sorting by the directory component reproduces that order.
|
|
236
458
|
*/
|
|
237
|
-
function _globSkillMd(root: string): string[] {
|
|
459
|
+
export function _globSkillMd(root: string): string[] {
|
|
238
460
|
let names: string[];
|
|
239
461
|
try {
|
|
240
462
|
names = fs.readdirSync(root);
|
|
@@ -257,38 +479,81 @@ function _globSkillMd(root: string): string[] {
|
|
|
257
479
|
return dirs.map((name) => path.join(root, name, 'SKILL.md'));
|
|
258
480
|
}
|
|
259
481
|
|
|
260
|
-
function
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
482
|
+
function _rankable(skill: Skill): {
|
|
483
|
+
name: string;
|
|
484
|
+
description: string;
|
|
485
|
+
personas: string[];
|
|
486
|
+
triggerText: string[];
|
|
487
|
+
whenToUseText: string;
|
|
488
|
+
headingText: string[];
|
|
489
|
+
} {
|
|
490
|
+
return {
|
|
266
491
|
name: skill.name,
|
|
267
492
|
description: skill.description,
|
|
268
493
|
personas: skill.personas,
|
|
269
494
|
triggerText: skill.triggerText,
|
|
495
|
+
whenToUseText: skill.whenToUseText,
|
|
496
|
+
headingText: skill.headingText,
|
|
270
497
|
};
|
|
271
|
-
|
|
272
|
-
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* The indexed term set for one skill.
|
|
502
|
+
*
|
|
503
|
+
* With no term-source flag set, `skill.terms` is already
|
|
504
|
+
* `tokenize(name + ' ' + description)` and the precomputed set is reused
|
|
505
|
+
* unchanged; a flag that widens the source re-derives it with that source
|
|
506
|
+
* folded in. Separated from `_score` so the caller can build each set ONCE and
|
|
507
|
+
* share it between the document-frequency pass and the scoring loop.
|
|
508
|
+
*/
|
|
509
|
+
function _terms(skill: Skill, opts: RankOptions): ReadonlySet<string> {
|
|
510
|
+
return widensTermSource(opts) ? _sharedSkillTerms(_rankable(skill), opts) : skill.terms;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function _score(
|
|
514
|
+
taskTerms: Set<string>,
|
|
515
|
+
skill: Skill,
|
|
516
|
+
terms: ReadonlySet<string>,
|
|
517
|
+
opts: RankOptions = {},
|
|
518
|
+
stats?: TermStats,
|
|
519
|
+
): number {
|
|
520
|
+
// Single-sourced in `src/shared/skillRanking.ts`.
|
|
521
|
+
return scoreSkill(taskTerms, _rankable(skill), terms, opts, stats);
|
|
273
522
|
}
|
|
274
523
|
|
|
275
524
|
export type RankRow = [string, number, string[]];
|
|
276
525
|
|
|
277
526
|
/**
|
|
278
527
|
* @param skillsDir one root, or several to rank across (see `_load_skills_across`).
|
|
528
|
+
* @param ctx origin + scan context; omitted, it is built from {@link ROOT}.
|
|
529
|
+
*
|
|
530
|
+
* Row names are QUALIFIED (`project:design-system`) for a neighbour and bare for
|
|
531
|
+
* ours, so two same-named skills are two distinguishable rows rather than one
|
|
532
|
+
* ambiguous one. On a tree with no installed-tools manifest every skill resolves
|
|
533
|
+
* to `package` and every row is bare, which is what it was before.
|
|
279
534
|
*/
|
|
280
535
|
export function rank(
|
|
281
536
|
task: string,
|
|
282
537
|
skillsDir: string | readonly string[],
|
|
283
538
|
opts: RankOptions = {},
|
|
539
|
+
ctx?: NeighbourContext,
|
|
284
540
|
): RankRow[] {
|
|
285
541
|
const taskTerms = _tokenize(task);
|
|
286
|
-
const skills = _load_skills_across(
|
|
542
|
+
const skills = _load_skills_across(
|
|
543
|
+
typeof skillsDir === 'string' ? [skillsDir] : skillsDir,
|
|
544
|
+
opts,
|
|
545
|
+
ctx,
|
|
546
|
+
);
|
|
547
|
+
// ONE term set per skill, shared between the document-frequency pass and the
|
|
548
|
+
// scoring loop — the two used to tokenize the whole catalogue separately.
|
|
549
|
+
const termSets = skills.map((s) => _terms(s, opts));
|
|
550
|
+
const stats = opts.idfWeighting ? buildTermStats(skills.map(_rankable), termSets) : undefined;
|
|
287
551
|
const rows: RankRow[] = [];
|
|
288
|
-
for (
|
|
289
|
-
const
|
|
552
|
+
for (let i = 0; i < skills.length; i += 1) {
|
|
553
|
+
const s = skills[i] as Skill;
|
|
554
|
+
const score = _score(taskTerms, s, termSets[i] as ReadonlySet<string>, opts, stats);
|
|
290
555
|
if (score > 0) {
|
|
291
|
-
rows.push([s.
|
|
556
|
+
rows.push([s.qualified, score, [...s.personas]]);
|
|
292
557
|
}
|
|
293
558
|
}
|
|
294
559
|
// rows.sort(key=lambda r: (-r[1], r[0])) — Python stable tuple sort.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* sweep_skill_ranker_signals — every candidate signal, alone, on both slices.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-a-ranker-that-routes` 2.2 asks for top-1, top-3 and MRR with
|
|
6
|
+
* intervals for each candidate flag measured ALONE, and the flags are a table in
|
|
7
|
+
* `measure_skill_ranker_baseline.RANKER_LABELS`. This script is the thing that
|
|
8
|
+
* produces that table, and it exists as a committed script rather than a
|
|
9
|
+
* one-off because a number nobody can regenerate is a claim rather than a
|
|
10
|
+
* measurement.
|
|
11
|
+
*
|
|
12
|
+
* IT PRINTS BOTH SLICES, and the two are read for different purposes. The
|
|
13
|
+
* TUNING reading is what a signal may be CHOSEN on. The SEALED reading is the
|
|
14
|
+
* only one a lift may be CLAIMED on. Printing only the sealed column would
|
|
15
|
+
* invite choosing on it, which is the one thing the partition exists to stop;
|
|
16
|
+
* printing only the tuning column would leave the claim unsupported.
|
|
17
|
+
*
|
|
18
|
+
* Usage:
|
|
19
|
+
* ./scripts-run src/scripts/sweep_skill_ranker_signals
|
|
20
|
+
* ./scripts-run src/scripts/sweep_skill_ranker_signals keyword-v1 idf
|
|
21
|
+
* ./scripts-run src/scripts/sweep_skill_ranker_signals --json
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import * as path from 'node:path';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
|
|
27
|
+
import { wilsonInterval } from './_lib/capture_rate.js';
|
|
28
|
+
import {
|
|
29
|
+
RANKER_LABELS,
|
|
30
|
+
REPO,
|
|
31
|
+
SKILLS_DIR,
|
|
32
|
+
type SliceName,
|
|
33
|
+
isKnownRanker,
|
|
34
|
+
partitionBySlice,
|
|
35
|
+
readMatrixLabelledPrompts,
|
|
36
|
+
} from './measure_skill_ranker_baseline.js';
|
|
37
|
+
import { meanReciprocalRank, readRows } from './report_skill_ranker_confusion.js';
|
|
38
|
+
|
|
39
|
+
export interface SweepRow {
|
|
40
|
+
label: string;
|
|
41
|
+
slice: SliceName;
|
|
42
|
+
n: number;
|
|
43
|
+
top1: number;
|
|
44
|
+
top1_ci95: { lower: number; upper: number };
|
|
45
|
+
top3: number;
|
|
46
|
+
top3_ci95: { lower: number; upper: number };
|
|
47
|
+
mrr: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function round3(n: number): number {
|
|
51
|
+
return Math.round(n * 1000) / 1000;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function ci(successes: number, trials: number): { lower: number; upper: number } {
|
|
55
|
+
const raw = wilsonInterval(successes, trials);
|
|
56
|
+
return { lower: round3(raw.lower), upper: round3(raw.upper) };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Every configuration on both slices, ONE ranking pass per prompt.
|
|
61
|
+
*
|
|
62
|
+
* `rank()` re-globs and re-reads the whole SKILL.md catalogue on every call, so
|
|
63
|
+
* it is the dominant cost by a wide margin and ranking each prompt twice doubles
|
|
64
|
+
* the whole sweep. The earlier shape took top-1/top-3 from `measureAccuracy` and
|
|
65
|
+
* MRR from a second pass in `readRows`, which also derived the row set from two
|
|
66
|
+
* independent corpus reads — so a future divergence between them would have been
|
|
67
|
+
* silent rather than loud. All three rates now come off the same readings of the
|
|
68
|
+
* same rows.
|
|
69
|
+
*/
|
|
70
|
+
export function sweep(labels: readonly string[], repo = REPO, skillsDir = SKILLS_DIR): SweepRow[] {
|
|
71
|
+
const whole = readMatrixLabelledPrompts(repo);
|
|
72
|
+
const out: SweepRow[] = [];
|
|
73
|
+
for (const label of labels) {
|
|
74
|
+
for (const slice of ['tuning', 'sealed'] as const) {
|
|
75
|
+
const rows = partitionBySlice(whole, slice);
|
|
76
|
+
const readings = readRows(rows, skillsDir, label);
|
|
77
|
+
const n = readings.length;
|
|
78
|
+
const t1 = readings.filter((r) => r.rankOfExpected === 1).length;
|
|
79
|
+
const t3 = readings.filter((r) => r.rankOfExpected >= 1 && r.rankOfExpected <= 3).length;
|
|
80
|
+
out.push({
|
|
81
|
+
label,
|
|
82
|
+
slice,
|
|
83
|
+
n,
|
|
84
|
+
top1: n ? round3(t1 / n) : 0,
|
|
85
|
+
top1_ci95: ci(t1, n),
|
|
86
|
+
top3: n ? round3(t3 / n) : 0,
|
|
87
|
+
top3_ci95: ci(t3, n),
|
|
88
|
+
mrr: round3(meanReciprocalRank(readings)),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function renderTable(rows: readonly SweepRow[]): string {
|
|
96
|
+
const L = ['| configuration | slice | n | top-1 | 95 % CI | top-3 | 95 % CI | MRR |', '|---|---|---:|---:|---|---:|---|---:|'];
|
|
97
|
+
for (const r of rows) {
|
|
98
|
+
L.push(
|
|
99
|
+
`| \`${r.label}\` | ${r.slice} | ${String(r.n)} | ${r.top1.toFixed(3)} | ` +
|
|
100
|
+
`${r.top1_ci95.lower.toFixed(3)} – ${r.top1_ci95.upper.toFixed(3)} | ${r.top3.toFixed(3)} | ` +
|
|
101
|
+
`${r.top3_ci95.lower.toFixed(3)} – ${r.top3_ci95.upper.toFixed(3)} | ${r.mrr.toFixed(3)} |`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return `${L.join('\n')}\n`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function main(argv: readonly string[]): number {
|
|
108
|
+
const json = argv.includes('--json');
|
|
109
|
+
const named = argv.filter((a) => !a.startsWith('--'));
|
|
110
|
+
const labels = named.length > 0 ? named : Object.keys(RANKER_LABELS);
|
|
111
|
+
// `isKnownRanker` (Object.hasOwn), not `in`: `in` walks the prototype chain,
|
|
112
|
+
// so `constructor` and `toString` would pass here while `Object.keys` below
|
|
113
|
+
// prints a set that does not contain them — two answers to one question.
|
|
114
|
+
const unknown = labels.filter((l) => !isKnownRanker(l));
|
|
115
|
+
if (unknown.length > 0) {
|
|
116
|
+
process.stderr.write(
|
|
117
|
+
`sweep_skill_ranker_signals: unknown configuration(s) ${unknown.join(', ')}; ` +
|
|
118
|
+
`known: ${Object.keys(RANKER_LABELS).join(', ')}\n`,
|
|
119
|
+
);
|
|
120
|
+
return 2;
|
|
121
|
+
}
|
|
122
|
+
const rows = sweep(labels);
|
|
123
|
+
process.stdout.write(json ? `${JSON.stringify(rows, null, 2)}\n` : renderTable(rows));
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) {
|
|
128
|
+
process.exit(main(process.argv.slice(2)));
|
|
129
|
+
}
|