@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
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a consumer's own code-graph file, in the shape another tool wrote it.
|
|
3
|
+
*
|
|
4
|
+
* The defect this closes: `detect.ts` already ACCEPTS a `links`-shaped
|
|
5
|
+
* graph.json — `looksLikeGraph` passes anything with `nodes[]` and
|
|
6
|
+
* `edges`-or-`links[]` carrying `source`/`target` — and then `query.ts`
|
|
7
|
+
* `loadGraph` throws on it, because `validateGraph` demands `edges`,
|
|
8
|
+
* `schema_version`, `source_checksum` and a per-edge `resolved_via` and
|
|
9
|
+
* `provider`. So a consumer who ships a graph got told it was detected and
|
|
10
|
+
* then watched every verb crash on it. Detected-but-unloadable is the worst
|
|
11
|
+
* of both answers.
|
|
12
|
+
*
|
|
13
|
+
* What this module does NOT do is make those edges trustworthy. A foreign
|
|
14
|
+
* relation vocabulary is another tool's, and mapping it is an interpretation:
|
|
15
|
+
* their `calls` may be our `calls` or may be their build graph's dependency
|
|
16
|
+
* arrow. So every adapted edge is tagged `resolved_via: 'foreign'`, which
|
|
17
|
+
* joins the GUESS set — the same set `name-lookup` and `dynamic` are in — and
|
|
18
|
+
* the gate verbs refuse a graph made only of guesses rather than answering
|
|
19
|
+
* from one.
|
|
20
|
+
*
|
|
21
|
+
* A relation this module cannot map is COUNTED and DROPPED, never guessed
|
|
22
|
+
* into the nearest native relation. A wrong edge that reads as a real one is
|
|
23
|
+
* worse than a missing edge that reads as a number.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { createHash } from 'node:crypto';
|
|
27
|
+
|
|
28
|
+
import type { CodeGraph, CodeEdge, CodeNode, EdgeConfidence, Relation } from './types.js';
|
|
29
|
+
import { SCHEMA_VERSION } from './types.js';
|
|
30
|
+
|
|
31
|
+
/** What a foreign load produced, including what it could not use. */
|
|
32
|
+
export interface ForeignLoadResult {
|
|
33
|
+
graph: CodeGraph;
|
|
34
|
+
/** Edges dropped because their relation has no native counterpart. */
|
|
35
|
+
unmapped_relations: Record<string, number>;
|
|
36
|
+
/** Edges dropped because an endpoint was missing or not a string. */
|
|
37
|
+
malformed_edges: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Foreign relation vocabulary → ours.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately small and literal. Every entry is a word whose meaning is the
|
|
44
|
+
* same in both vocabularies; a word that is merely SIMILAR is left out, so it
|
|
45
|
+
* lands in `unmapped_relations` and is reported rather than mapped on a hunch.
|
|
46
|
+
* This is a list of OUR relation names and their obvious synonyms, not a table
|
|
47
|
+
* of any particular tool's schema.
|
|
48
|
+
*/
|
|
49
|
+
const RELATION_MAP: Readonly<Record<string, Relation>> = {
|
|
50
|
+
calls: 'calls',
|
|
51
|
+
call: 'calls',
|
|
52
|
+
invokes: 'calls',
|
|
53
|
+
imports: 'imports',
|
|
54
|
+
import: 'imports',
|
|
55
|
+
requires: 'imports',
|
|
56
|
+
uses: 'uses',
|
|
57
|
+
use: 'uses',
|
|
58
|
+
references: 'uses',
|
|
59
|
+
inherits: 'inherits',
|
|
60
|
+
extends: 'inherits',
|
|
61
|
+
implements: 'inherits',
|
|
62
|
+
member: 'member',
|
|
63
|
+
contains: 'member',
|
|
64
|
+
tests: 'tests',
|
|
65
|
+
test: 'tests',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const KINDS = new Set([
|
|
69
|
+
'file',
|
|
70
|
+
'class',
|
|
71
|
+
'interface',
|
|
72
|
+
'trait',
|
|
73
|
+
'function',
|
|
74
|
+
'method',
|
|
75
|
+
'constant',
|
|
76
|
+
'type',
|
|
77
|
+
'enum',
|
|
78
|
+
'skipped',
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
function isObject(v: unknown): v is Record<string, unknown> {
|
|
82
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Does this document look like a foreign graph rather than one of ours?
|
|
87
|
+
*
|
|
88
|
+
* `links` in place of `edges` is the clearest tell and is the shape
|
|
89
|
+
* `detect.ts` already accepts. A document carrying `edges` but no
|
|
90
|
+
* `schema_version` is foreign too — ours always writes one.
|
|
91
|
+
*/
|
|
92
|
+
export function looksForeign(doc: unknown): boolean {
|
|
93
|
+
if (!isObject(doc)) return false;
|
|
94
|
+
if (!Array.isArray(doc['nodes'])) return false;
|
|
95
|
+
if (Array.isArray(doc['links'])) return true;
|
|
96
|
+
return Array.isArray(doc['edges']) && typeof doc['schema_version'] !== 'number';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Adapt a foreign graph document into the native shape.
|
|
101
|
+
*
|
|
102
|
+
* `schema_version` and `source_checksum` are SYNTHESISED: the first is ours
|
|
103
|
+
* by definition once the document is in our shape, and the second is a digest
|
|
104
|
+
* of the document itself, so a changed foreign file produces a changed
|
|
105
|
+
* checksum and the cache layer behaves as it does for a native graph. Neither
|
|
106
|
+
* is read off the foreign file — a number another tool wrote under the same
|
|
107
|
+
* key would mean something else.
|
|
108
|
+
*/
|
|
109
|
+
export function adaptForeignGraph(doc: unknown): ForeignLoadResult | null {
|
|
110
|
+
if (!isObject(doc)) return null;
|
|
111
|
+
const rawNodes = doc['nodes'];
|
|
112
|
+
const rawEdges = doc['links'] ?? doc['edges'];
|
|
113
|
+
if (!Array.isArray(rawNodes) || !Array.isArray(rawEdges)) return null;
|
|
114
|
+
|
|
115
|
+
const nodes: CodeNode[] = [];
|
|
116
|
+
const ids = new Set<string>();
|
|
117
|
+
for (const n of rawNodes) {
|
|
118
|
+
if (!isObject(n)) continue;
|
|
119
|
+
const id = n['id'];
|
|
120
|
+
if (typeof id !== 'string' || id === '') continue;
|
|
121
|
+
const kind = typeof n['kind'] === 'string' && KINDS.has(n['kind']) ? n['kind'] : 'skipped';
|
|
122
|
+
const sourceFile =
|
|
123
|
+
typeof n['source_file'] === 'string'
|
|
124
|
+
? n['source_file']
|
|
125
|
+
: typeof n['file'] === 'string'
|
|
126
|
+
? n['file']
|
|
127
|
+
: '';
|
|
128
|
+
nodes.push({
|
|
129
|
+
id,
|
|
130
|
+
label: typeof n['label'] === 'string' ? n['label'] : id,
|
|
131
|
+
kind,
|
|
132
|
+
source_file: sourceFile,
|
|
133
|
+
// A foreign node rarely carries a span. An empty one is honest —
|
|
134
|
+
// it says "no location recorded", where a fabricated [1,1] would
|
|
135
|
+
// point a reader at the top of a file for no reason.
|
|
136
|
+
source_location: Array.isArray(n['source_location']) ? n['source_location'] : [],
|
|
137
|
+
} as CodeNode);
|
|
138
|
+
ids.add(id);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const edges: CodeEdge[] = [];
|
|
142
|
+
const unmapped: Record<string, number> = {};
|
|
143
|
+
let malformed = 0;
|
|
144
|
+
for (const e of rawEdges) {
|
|
145
|
+
if (!isObject(e)) {
|
|
146
|
+
malformed += 1;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const source = e['source'];
|
|
150
|
+
const target = e['target'];
|
|
151
|
+
if (typeof source !== 'string' || typeof target !== 'string' || !ids.has(source)) {
|
|
152
|
+
malformed += 1;
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const rawRelation = typeof e['relation'] === 'string' ? e['relation'] : '';
|
|
156
|
+
const relation = RELATION_MAP[rawRelation.toLowerCase()];
|
|
157
|
+
if (relation === undefined) {
|
|
158
|
+
const key = rawRelation === '' ? '(none)' : rawRelation;
|
|
159
|
+
unmapped[key] = (unmapped[key] ?? 0) + 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
edges.push({
|
|
163
|
+
source,
|
|
164
|
+
target,
|
|
165
|
+
relation,
|
|
166
|
+
// Not EXTRACTED: this package did not extract it and cannot say
|
|
167
|
+
// how the tool that did arrived at it.
|
|
168
|
+
confidence: 'AMBIGUOUS' as EdgeConfidence,
|
|
169
|
+
resolved_via: 'foreign',
|
|
170
|
+
provider: 'foreign',
|
|
171
|
+
} as CodeEdge);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const counts: Record<string, number> = { EXTRACTED: 0, INFERRED: 0, AMBIGUOUS: edges.length };
|
|
175
|
+
const graph = {
|
|
176
|
+
schema_version: SCHEMA_VERSION,
|
|
177
|
+
source_checksum: createHash('sha256')
|
|
178
|
+
.update(JSON.stringify(doc), 'utf-8')
|
|
179
|
+
.digest('hex'),
|
|
180
|
+
languages: [],
|
|
181
|
+
grammar_abi: 0,
|
|
182
|
+
edge_confidence_counts: counts,
|
|
183
|
+
suppressed_edge_counts: { dynamic_no_candidate: 0 },
|
|
184
|
+
nodes,
|
|
185
|
+
edges,
|
|
186
|
+
} as unknown as CodeGraph;
|
|
187
|
+
|
|
188
|
+
return { graph, unmapped_relations: unmapped, malformed_edges: malformed };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** True when every edge in `g` came from a foreign file. */
|
|
192
|
+
export function isAllForeign(g: CodeGraph): boolean {
|
|
193
|
+
return g.edges.length > 0 && g.edges.every((e) => e.resolved_via === 'foreign');
|
|
194
|
+
}
|
|
@@ -16,8 +16,9 @@ import {
|
|
|
16
16
|
loadSerializedFromTwin,
|
|
17
17
|
openGraphIndex,
|
|
18
18
|
} from './sqlite_store.js';
|
|
19
|
-
import type { CodeEdge, CodeGraph, CodeNode } from './types.js';
|
|
19
|
+
import type { CodeEdge, CodeGraph, CodeNode, Relation } from './types.js';
|
|
20
20
|
import { validateGraph } from './validate.js';
|
|
21
|
+
import { adaptForeignGraph, looksForeign } from './foreign.js';
|
|
21
22
|
|
|
22
23
|
const APPROX_CHARS_PER_TOKEN = 4;
|
|
23
24
|
|
|
@@ -145,10 +146,27 @@ export function loadGraph(graphPath: string, source = graphPath): LoadedGraph {
|
|
|
145
146
|
const fromTwin = loadSerializedFromTwin(graphPath);
|
|
146
147
|
const raw = fromTwin ?? fs.readFileSync(graphPath, 'utf-8');
|
|
147
148
|
const parsed = JSON.parse(raw) as unknown;
|
|
148
|
-
|
|
149
|
+
// A consumer's own graph file, written by another tool, is DETECTED by
|
|
150
|
+
// `detect.ts` and used to throw here — detected-but-unloadable, the worst
|
|
151
|
+
// of both answers. Adapt it instead: its edges carry `resolved_via:
|
|
152
|
+
// 'foreign'`, which is in the guess set, so the gate verbs refuse it by
|
|
153
|
+
// name rather than answering from it.
|
|
154
|
+
let foreignAdapted = false;
|
|
155
|
+
let candidate = parsed;
|
|
156
|
+
if (looksForeign(parsed)) {
|
|
157
|
+
const adapted = adaptForeignGraph(parsed);
|
|
158
|
+
if (adapted !== null) {
|
|
159
|
+
candidate = adapted.graph;
|
|
160
|
+
foreignAdapted = true;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const v = validateGraph(candidate);
|
|
149
164
|
if (!v.ok) throw new Error(`invalid graph at ${graphPath}: ${v.errors.slice(0, 3).join('; ')}`);
|
|
150
|
-
const graph =
|
|
151
|
-
|
|
165
|
+
const graph = candidate as CodeGraph;
|
|
166
|
+
// The twin is a cache of a file's bytes keyed on its own checksum. An
|
|
167
|
+
// adapted graph's bytes are not the file's, so emitting one would cache a
|
|
168
|
+
// derivation under the source's identity.
|
|
169
|
+
if (fromTwin === null && !foreignAdapted) {
|
|
152
170
|
emitSqliteTwin(graph, raw, graphPath);
|
|
153
171
|
}
|
|
154
172
|
const byId = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
@@ -203,6 +221,47 @@ function resolveSeedsTiered(g: LoadedGraph, seed: string, limit = 5): SeedResolu
|
|
|
203
221
|
return { ids: ranked.slice(0, limit).map((r) => r.id), weak: true };
|
|
204
222
|
}
|
|
205
223
|
|
|
224
|
+
/**
|
|
225
|
+
* The EXACT half of the ladder above — id, then label — with no BM25 tier.
|
|
226
|
+
*
|
|
227
|
+
* `graph_node` is a node tool: every field it returns (location, degree, the
|
|
228
|
+
* edge lists) is a statement about ONE node, so answering about a best-guess
|
|
229
|
+
* node is worse than refusing. D4 of `road-to-a-graph-that-feeds-the-gate` makes
|
|
230
|
+
* that explicit for this tool — free-text retrieval is the row the graph lost,
|
|
231
|
+
* so a node answer never rests on a score.
|
|
232
|
+
*
|
|
233
|
+
* Still the same ladder and not a second resolver: this calls
|
|
234
|
+
* {@link resolveSeedsTiered} and reads its `weak` flag, so a change to the
|
|
235
|
+
* exact tiers reaches both callers.
|
|
236
|
+
*
|
|
237
|
+
* `ambiguous` carries the candidates when a LABEL resolves to several nodes.
|
|
238
|
+
* Picking the first would be the silent guess this function exists to avoid; the
|
|
239
|
+
* caller re-asks with one of the ids.
|
|
240
|
+
*/
|
|
241
|
+
export function resolveExactNode(
|
|
242
|
+
g: LoadedGraph,
|
|
243
|
+
seed: string,
|
|
244
|
+
): { id: string | null; ambiguous: string[]; more: boolean } {
|
|
245
|
+
// The ladder's default limit is 5, and inheriting it made the refusal LIE:
|
|
246
|
+
// a label on twelve nodes refused with "is a label on 5 nodes" and listed
|
|
247
|
+
// five of them with nothing saying the list was cut. A completion review
|
|
248
|
+
// reproduced it. Ask for one more than we will show, so truncation is
|
|
249
|
+
// detectable rather than invisible.
|
|
250
|
+
const r = resolveSeedsTiered(g, seed, AMBIGUITY_SHOWN + 1);
|
|
251
|
+
if (r.weak || r.ids.length === 0) return { id: null, ambiguous: [], more: false };
|
|
252
|
+
if (r.ids.length > 1) {
|
|
253
|
+
return {
|
|
254
|
+
id: null,
|
|
255
|
+
ambiguous: r.ids.slice(0, AMBIGUITY_SHOWN),
|
|
256
|
+
more: r.ids.length > AMBIGUITY_SHOWN,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
return { id: r.ids[0] as string, ambiguous: [], more: false };
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** How many candidate ids an ambiguity refusal lists before it says "and more". */
|
|
263
|
+
const AMBIGUITY_SHOWN = 25;
|
|
264
|
+
|
|
206
265
|
/** Resolve a free-text seed to node ids: exact id → exact label → BM25. */
|
|
207
266
|
export function resolveSeeds(g: LoadedGraph, seed: string, limit = 5): string[] {
|
|
208
267
|
return resolveSeedsTiered(g, seed, limit).ids;
|
|
@@ -421,3 +480,157 @@ export function mergeRecommendedReads(results: readonly QueryResult[]): Recommen
|
|
|
421
480
|
for (const r of results) for (const rr of r.recommended_reads) merged.set(readKey(rr), rr);
|
|
422
481
|
return [...merged.values()];
|
|
423
482
|
}
|
|
483
|
+
|
|
484
|
+
// ---------------------------------------------------------------------------
|
|
485
|
+
// `node` — one node, its location, its edges, its degree (3.1)
|
|
486
|
+
// ---------------------------------------------------------------------------
|
|
487
|
+
|
|
488
|
+
/** One edge as the node view renders it: who, how, which way, how far. */
|
|
489
|
+
export interface NodeEdgeLine {
|
|
490
|
+
/** The node at the OTHER end — the caller for an in-edge, the callee for an out-edge. */
|
|
491
|
+
id: string;
|
|
492
|
+
label: string;
|
|
493
|
+
relation: Relation;
|
|
494
|
+
confidence: string;
|
|
495
|
+
hops: number;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export interface NodeResult {
|
|
499
|
+
source: string;
|
|
500
|
+
/** The resolved id, or `''` when nothing resolved and `refusal` is set. */
|
|
501
|
+
id: string;
|
|
502
|
+
label: string;
|
|
503
|
+
kind: string;
|
|
504
|
+
/** File + 1-based inclusive line range, or `null` for a placeholder node. */
|
|
505
|
+
location: RecommendedRead | null;
|
|
506
|
+
/** DIRECT edge counts, always 1-hop — a degree is not a property of a walk. */
|
|
507
|
+
in_degree: number;
|
|
508
|
+
out_degree: number;
|
|
509
|
+
in: NodeEdgeLine[];
|
|
510
|
+
out: NodeEdgeLine[];
|
|
511
|
+
truncated: boolean;
|
|
512
|
+
/** Set when the seed did not resolve exactly; every other field is empty. */
|
|
513
|
+
refusal?: string;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
export interface NodeOptions {
|
|
517
|
+
direction?: 'in' | 'out' | 'both';
|
|
518
|
+
/** 1-3. Anything outside the range is clamped rather than refused. */
|
|
519
|
+
depth?: number;
|
|
520
|
+
/** Restrict to one relation of the closed vocabulary. */
|
|
521
|
+
relation?: Relation;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
/** Hard cap per direction, so one hub node cannot return an unbounded payload. */
|
|
525
|
+
const NODE_EDGE_CAP = 200;
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Walk one direction from `start`, recording each edge once, breadth-first.
|
|
529
|
+
*
|
|
530
|
+
* `seen` is keyed on the NODE, so a cycle terminates; the edge list can still
|
|
531
|
+
* carry two lines into the same node by different relations, which is a real
|
|
532
|
+
* distinction a caller asked for when it passed no `relation`.
|
|
533
|
+
*/
|
|
534
|
+
function walkDirection(
|
|
535
|
+
g: LoadedGraph,
|
|
536
|
+
start: string,
|
|
537
|
+
dir: 'in' | 'out',
|
|
538
|
+
depth: number,
|
|
539
|
+
relation: Relation | undefined,
|
|
540
|
+
): { lines: NodeEdgeLine[]; truncated: boolean } {
|
|
541
|
+
const lines: NodeEdgeLine[] = [];
|
|
542
|
+
const seen = new Set<string>([start]);
|
|
543
|
+
let frontier = [start];
|
|
544
|
+
let truncated = false;
|
|
545
|
+
for (let hop = 1; hop <= depth && frontier.length > 0; hop += 1) {
|
|
546
|
+
const next: string[] = [];
|
|
547
|
+
for (const cur of frontier) {
|
|
548
|
+
for (const e of (dir === 'out' ? g.out : g.in).get(cur) ?? []) {
|
|
549
|
+
if (relation !== undefined && e.relation !== relation) continue;
|
|
550
|
+
const other = dir === 'out' ? e.target : e.source;
|
|
551
|
+
if (lines.length >= NODE_EDGE_CAP) {
|
|
552
|
+
truncated = true;
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
lines.push({
|
|
556
|
+
id: sanitizeLabel(other),
|
|
557
|
+
label: label(g, other),
|
|
558
|
+
relation: e.relation,
|
|
559
|
+
confidence: e.confidence,
|
|
560
|
+
hops: hop,
|
|
561
|
+
});
|
|
562
|
+
if (!seen.has(other)) {
|
|
563
|
+
seen.add(other);
|
|
564
|
+
next.push(other);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
if (truncated) break;
|
|
568
|
+
}
|
|
569
|
+
if (truncated) break;
|
|
570
|
+
frontier = next;
|
|
571
|
+
}
|
|
572
|
+
return { lines, truncated };
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* `node <seed>` — what one node IS, rather than what a walk from it reaches.
|
|
577
|
+
*
|
|
578
|
+
* The five readers before it all answer a question about a neighbourhood
|
|
579
|
+
* (`query`, `explain`, `affected`, `path`) or about a set (`dead`, `untested`).
|
|
580
|
+
* None answers "where does this live, who reaches it, what does it reach, how
|
|
581
|
+
* connected is it" — which is the question an agent asks first and had to
|
|
582
|
+
* assemble from two calls and a file read.
|
|
583
|
+
*
|
|
584
|
+
* Nothing new is walked: the edge maps are the ones `affected` already uses, so
|
|
585
|
+
* this adds a view, not an index.
|
|
586
|
+
*/
|
|
587
|
+
export function node(g: LoadedGraph, seed: string, opts: NodeOptions = {}): NodeResult {
|
|
588
|
+
const empty = {
|
|
589
|
+
source: g.source,
|
|
590
|
+
id: '',
|
|
591
|
+
label: '',
|
|
592
|
+
kind: '',
|
|
593
|
+
location: null,
|
|
594
|
+
in_degree: 0,
|
|
595
|
+
out_degree: 0,
|
|
596
|
+
in: [] as NodeEdgeLine[],
|
|
597
|
+
out: [] as NodeEdgeLine[],
|
|
598
|
+
truncated: false,
|
|
599
|
+
};
|
|
600
|
+
const { id, ambiguous, more } = resolveExactNode(g, seed);
|
|
601
|
+
if (id === null) {
|
|
602
|
+
return {
|
|
603
|
+
...empty,
|
|
604
|
+
refusal:
|
|
605
|
+
ambiguous.length > 0
|
|
606
|
+
? `'${sanitizeLabel(seed)}' is a label on ${more ? 'more than ' : ''}` +
|
|
607
|
+
`${String(ambiguous.length)} nodes — re-ask with one id: ` +
|
|
608
|
+
`${ambiguous.map((a) => sanitizeLabel(a)).join(', ')}` +
|
|
609
|
+
(more ? ' (list truncated)' : '')
|
|
610
|
+
: `'${sanitizeLabel(seed)}' matches no node id and no node label. This tool ` +
|
|
611
|
+
'resolves exactly (id, then label) and does not score free text — use ' +
|
|
612
|
+
'`query` if a best-guess match is what you want.',
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
const n = g.byId.get(id);
|
|
616
|
+
const direction = opts.direction ?? 'both';
|
|
617
|
+
const depth = Math.min(3, Math.max(1, Math.trunc(opts.depth ?? 1)));
|
|
618
|
+
const inWalk =
|
|
619
|
+
direction === 'out' ? { lines: [], truncated: false } : walkDirection(g, id, 'in', depth, opts.relation);
|
|
620
|
+
const outWalk =
|
|
621
|
+
direction === 'in' ? { lines: [], truncated: false } : walkDirection(g, id, 'out', depth, opts.relation);
|
|
622
|
+
const degreeOf = (edges: readonly CodeEdge[] | undefined): number =>
|
|
623
|
+
opts.relation === undefined ? (edges?.length ?? 0) : (edges ?? []).filter((e) => e.relation === opts.relation).length;
|
|
624
|
+
return {
|
|
625
|
+
source: g.source,
|
|
626
|
+
id: sanitizeLabel(id),
|
|
627
|
+
label: label(g, id),
|
|
628
|
+
kind: n?.kind ?? '',
|
|
629
|
+
location: recommendedReadFor(g, id),
|
|
630
|
+
in_degree: degreeOf(g.in.get(id)),
|
|
631
|
+
out_degree: degreeOf(g.out.get(id)),
|
|
632
|
+
in: inWalk.lines,
|
|
633
|
+
out: outWalk.lines,
|
|
634
|
+
truncated: inWalk.truncated || outWalk.truncated,
|
|
635
|
+
};
|
|
636
|
+
}
|
|
@@ -66,7 +66,16 @@ export type ResolvedVia =
|
|
|
66
66
|
| 'route-table'
|
|
67
67
|
| 'test-import'
|
|
68
68
|
| 'name-lookup'
|
|
69
|
-
| 'dynamic'
|
|
69
|
+
| 'dynamic'
|
|
70
|
+
/**
|
|
71
|
+
* Read from a consumer's own graph file, written by another tool.
|
|
72
|
+
*
|
|
73
|
+
* Not a mechanism THIS package used — a statement that it used none. The
|
|
74
|
+
* relation came from someone else's vocabulary and was mapped, which is
|
|
75
|
+
* an interpretation, so the value belongs in the guess set below and the
|
|
76
|
+
* gate verbs refuse a graph made only of these.
|
|
77
|
+
*/
|
|
78
|
+
| 'foreign';
|
|
70
79
|
|
|
71
80
|
/**
|
|
72
81
|
* WHICH engine produced the edge.
|
|
@@ -77,7 +86,17 @@ export type ResolvedVia =
|
|
|
77
86
|
* apart. Kill register K2 forbids an external provider entering `src/`, so this
|
|
78
87
|
* stays a single-member union until a decision changes that.
|
|
79
88
|
*/
|
|
80
|
-
export type EdgeProvider =
|
|
89
|
+
export type EdgeProvider =
|
|
90
|
+
| 'native'
|
|
91
|
+
/**
|
|
92
|
+
* The edge was read from a graph file this package did not build.
|
|
93
|
+
*
|
|
94
|
+
* This is a DATA tag on an edge, not an engine in `src/`: no foreign
|
|
95
|
+
* extractor is vendored, imported or executed anywhere, and K2 is about
|
|
96
|
+
* the latter. The field exists precisely so a mixed graph can be told
|
|
97
|
+
* apart, and a consumer-shipped graph is the first case where it is.
|
|
98
|
+
*/
|
|
99
|
+
| 'foreign';
|
|
81
100
|
|
|
82
101
|
/**
|
|
83
102
|
* The two mechanisms that are GUESSES rather than statements.
|
|
@@ -99,6 +118,11 @@ export type EdgeProvider = 'native';
|
|
|
99
118
|
export const GUESS_RESOLVED_VIA: ReadonlySet<ResolvedVia> = new Set<ResolvedVia>([
|
|
100
119
|
'name-lookup',
|
|
101
120
|
'dynamic',
|
|
121
|
+
// The accepted-edge filter is a DENYLIST, so a new value is accepted by
|
|
122
|
+
// default — which is exactly backwards for this one. `foreign` must be
|
|
123
|
+
// listed here or a consumer's graph would silently answer the gate verbs
|
|
124
|
+
// as if this package had resolved its edges.
|
|
125
|
+
'foreign',
|
|
102
126
|
]);
|
|
103
127
|
|
|
104
128
|
/** Does this edge's target rest on a stated fact rather than a guess? */
|
|
@@ -19,8 +19,10 @@ const RESOLVED_VIA = new Set([
|
|
|
19
19
|
'test-import',
|
|
20
20
|
'name-lookup',
|
|
21
21
|
'dynamic',
|
|
22
|
+
// Adapted from a consumer's own graph file; see `foreign.ts`.
|
|
23
|
+
'foreign',
|
|
22
24
|
]);
|
|
23
|
-
const PROVIDERS = new Set(['native']);
|
|
25
|
+
const PROVIDERS = new Set(['native', 'foreign']);
|
|
24
26
|
const KINDS = new Set([
|
|
25
27
|
'file',
|
|
26
28
|
'class',
|
|
@@ -52,6 +52,38 @@ export function isAcceptedEdge(e: CodeEdge): boolean {
|
|
|
52
52
|
return isStatedResolution(e.resolved_via);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/** Why a gate verb refused. A closed set so a caller can branch on it. */
|
|
56
|
+
export type RefusalReason = 'foreign-edges-not-accepted' | 'entry-points-unavailable';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A graph whose every edge came from a file this package did not build.
|
|
60
|
+
*
|
|
61
|
+
* Those edges are tagged `foreign` and sit in the guess set, so a gate verb
|
|
62
|
+
* walking one would accept nothing and report an empty answer — and an empty
|
|
63
|
+
* answer from a gate reads as "nothing to worry about", which is the wrong
|
|
64
|
+
* reading and the dangerous one. The verbs refuse instead, by name, so the
|
|
65
|
+
* consumer learns that their graph is readable but not gate-grade rather than
|
|
66
|
+
* being told their diff impacts nothing.
|
|
67
|
+
*
|
|
68
|
+
* A MIXED graph is not refused: it carries edges this package did resolve, and
|
|
69
|
+
* the guess filter already excludes the foreign ones from the walk.
|
|
70
|
+
*/
|
|
71
|
+
export function foreignRefusal(g: LoadedGraph): string | null {
|
|
72
|
+
// `graph` is null on the index-backed read path, which answers per-node
|
|
73
|
+
// from the twin and never materialises the edge list. Nothing to classify
|
|
74
|
+
// there, and an index-backed graph is one this package built.
|
|
75
|
+
const edges: readonly CodeEdge[] = g.graph?.edges ?? [];
|
|
76
|
+
if (edges.length === 0) return null;
|
|
77
|
+
if (!edges.every((e) => e.resolved_via === 'foreign')) return null;
|
|
78
|
+
return (
|
|
79
|
+
'every edge in this graph was read from a file this package did not build, so all of them ' +
|
|
80
|
+
'are guesses and none is gate-grade. A gate verb would accept no edge and report an empty ' +
|
|
81
|
+
'answer, which reads as "nothing found" rather than "nothing trusted". Build a native graph ' +
|
|
82
|
+
'(`agent-config graph build`) to use this verb, or use `query` and `explain`, which answer ' +
|
|
83
|
+
'from foreign edges and say so.'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
55
87
|
/**
|
|
56
88
|
* Relations that constitute a REFERENCE to the target, as opposed to
|
|
57
89
|
* containment of it.
|
|
@@ -132,6 +164,10 @@ export interface ReachedNode {
|
|
|
132
164
|
}
|
|
133
165
|
|
|
134
166
|
export interface ImpactResult extends VerbReport {
|
|
167
|
+
/** Non-null when the verb REFUSED to answer. Every list is then empty. */
|
|
168
|
+
refusal: string | null;
|
|
169
|
+
/** Machine-readable reason, when `refusal` is set. */
|
|
170
|
+
refusal_reason: RefusalReason | null;
|
|
135
171
|
/** Node ids the diff touched that the graph knows. */
|
|
136
172
|
seeds: string[];
|
|
137
173
|
/**
|
|
@@ -219,6 +255,26 @@ export function impact(
|
|
|
219
255
|
depth = 2,
|
|
220
256
|
isTest: (relPath: string) => boolean = () => false,
|
|
221
257
|
): ImpactResult {
|
|
258
|
+
const foreign = foreignRefusal(g);
|
|
259
|
+
if (foreign !== null) {
|
|
260
|
+
return {
|
|
261
|
+
source: g.source,
|
|
262
|
+
state,
|
|
263
|
+
accepted_via: '(none)',
|
|
264
|
+
rejected_via: '(none)',
|
|
265
|
+
refusal: foreign,
|
|
266
|
+
refusal_reason: 'foreign-edges-not-accepted',
|
|
267
|
+
seeds: [],
|
|
268
|
+
unresolved_files: [],
|
|
269
|
+
not_indexed_files: [],
|
|
270
|
+
dependents: [],
|
|
271
|
+
reached: [],
|
|
272
|
+
test_files: [],
|
|
273
|
+
producing_edges: [],
|
|
274
|
+
lines: [],
|
|
275
|
+
recommended_reads: [],
|
|
276
|
+
};
|
|
277
|
+
}
|
|
222
278
|
const { seeds, unresolved, not_indexed } = seedsForFiles(g, files);
|
|
223
279
|
const accepted: CodeEdge[] = [];
|
|
224
280
|
const rejected: CodeEdge[] = [];
|
|
@@ -258,6 +314,8 @@ export function impact(
|
|
|
258
314
|
state,
|
|
259
315
|
accepted_via: viaHistogram(accepted),
|
|
260
316
|
rejected_via: viaHistogram(rejected),
|
|
317
|
+
refusal: null,
|
|
318
|
+
refusal_reason: null,
|
|
261
319
|
seeds,
|
|
262
320
|
unresolved_files: unresolved,
|
|
263
321
|
not_indexed_files: not_indexed,
|
|
@@ -334,6 +392,10 @@ export function testsFor(g: LoadedGraph, symbol: string, state: GraphState): Tes
|
|
|
334
392
|
}
|
|
335
393
|
|
|
336
394
|
export interface UntestedResult extends VerbReport {
|
|
395
|
+
/** Non-null when the verb REFUSED to answer. Every list is then empty. */
|
|
396
|
+
refusal: string | null;
|
|
397
|
+
/** Machine-readable reason, when `refusal` is set. */
|
|
398
|
+
refusal_reason: RefusalReason | null;
|
|
337
399
|
seeds: string[];
|
|
338
400
|
unresolved_files: string[];
|
|
339
401
|
not_indexed_files: string[];
|
|
@@ -351,6 +413,24 @@ export interface UntestedResult extends VerbReport {
|
|
|
351
413
|
* count and make the ratio meaningless.
|
|
352
414
|
*/
|
|
353
415
|
export function untested(g: LoadedGraph, files: readonly string[], state: GraphState): UntestedResult {
|
|
416
|
+
const foreign = foreignRefusal(g);
|
|
417
|
+
if (foreign !== null) {
|
|
418
|
+
return {
|
|
419
|
+
source: g.source,
|
|
420
|
+
state,
|
|
421
|
+
accepted_via: '(none)',
|
|
422
|
+
rejected_via: '(none)',
|
|
423
|
+
refusal: foreign,
|
|
424
|
+
refusal_reason: 'foreign-edges-not-accepted',
|
|
425
|
+
seeds: [],
|
|
426
|
+
unresolved_files: [],
|
|
427
|
+
not_indexed_files: [],
|
|
428
|
+
untested: [],
|
|
429
|
+
tested: [],
|
|
430
|
+
lines: [],
|
|
431
|
+
recommended_reads: [],
|
|
432
|
+
};
|
|
433
|
+
}
|
|
354
434
|
const { seeds, unresolved, not_indexed } = seedsForFiles(g, files);
|
|
355
435
|
const accepted: CodeEdge[] = [];
|
|
356
436
|
const rejected: CodeEdge[] = [];
|
|
@@ -375,6 +455,8 @@ export function untested(g: LoadedGraph, files: readonly string[], state: GraphS
|
|
|
375
455
|
state,
|
|
376
456
|
accepted_via: viaHistogram(accepted),
|
|
377
457
|
rejected_via: viaHistogram(rejected),
|
|
458
|
+
refusal: null,
|
|
459
|
+
refusal_reason: null,
|
|
378
460
|
seeds,
|
|
379
461
|
unresolved_files: unresolved,
|
|
380
462
|
not_indexed_files: not_indexed,
|
|
@@ -403,6 +485,8 @@ export interface DeadResult extends VerbReport {
|
|
|
403
485
|
sources: EntryPointSource[];
|
|
404
486
|
/** Non-null when the verb REFUSED to answer. The list is then empty. */
|
|
405
487
|
refusal: string | null;
|
|
488
|
+
/** Machine-readable reason, when `refusal` is set. */
|
|
489
|
+
refusal_reason: RefusalReason | null;
|
|
406
490
|
dead: string[];
|
|
407
491
|
/** Entry points excluded from `dead` — the audit trail for the exclusion. */
|
|
408
492
|
excluded: string[];
|
|
@@ -448,6 +532,23 @@ export function dead(
|
|
|
448
532
|
state,
|
|
449
533
|
sources: [...sources],
|
|
450
534
|
};
|
|
535
|
+
// Checked BEFORE the entry-point sources: on an all-foreign graph every
|
|
536
|
+
// in-edge is a guess, so every symbol would report dead — the confident
|
|
537
|
+
// false "dead" this verb's own header calls worse than no verb at all.
|
|
538
|
+
const foreign = foreignRefusal(g);
|
|
539
|
+
if (foreign !== null) {
|
|
540
|
+
return {
|
|
541
|
+
...base,
|
|
542
|
+
accepted_via: '(none)',
|
|
543
|
+
rejected_via: '(none)',
|
|
544
|
+
refusal: foreign,
|
|
545
|
+
refusal_reason: 'foreign-edges-not-accepted',
|
|
546
|
+
dead: [],
|
|
547
|
+
excluded: [],
|
|
548
|
+
lines: [],
|
|
549
|
+
recommended_reads: [],
|
|
550
|
+
};
|
|
551
|
+
}
|
|
451
552
|
if (unavailable.length > 0 && opts.acceptMissingExports !== true) {
|
|
452
553
|
return {
|
|
453
554
|
...base,
|
|
@@ -460,6 +561,7 @@ export function dead(
|
|
|
460
561
|
'A symbol they would have declared an entry point is indistinguishable from a dead one, ' +
|
|
461
562
|
'so no list is produced. Supply the missing source with --entry-points <file>, or state ' +
|
|
462
563
|
'that you accept the gap with --accept-missing-exports.',
|
|
564
|
+
refusal_reason: 'entry-points-unavailable',
|
|
463
565
|
dead: [],
|
|
464
566
|
excluded: [],
|
|
465
567
|
lines: [],
|
|
@@ -496,6 +598,7 @@ export function dead(
|
|
|
496
598
|
accepted_via: viaHistogram(accepted),
|
|
497
599
|
rejected_via: viaHistogram(rejected),
|
|
498
600
|
refusal: null,
|
|
601
|
+
refusal_reason: null,
|
|
499
602
|
dead: list,
|
|
500
603
|
excluded: excluded.sort(),
|
|
501
604
|
lines: list,
|