@event4u/agent-config 14.12.0 → 14.14.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 +118 -155
- package/CONTRIBUTING.md +38 -0
- package/CREDITS.md +135 -0
- package/NOTICE +13 -0
- package/README.md +8 -6
- package/dist/agent-src/commands/analyze/inbox.md +145 -2
- package/dist/agent-src/commands/feature/dev.md +7 -2
- package/dist/agent-src/commands/ghostwriter/write.md +5 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/orchestrate.md +2 -2
- package/dist/agent-src/commands/post-as/me.md +5 -1
- package/dist/agent-src/commands/pr/merge.md +19 -6
- package/dist/agent-src/commands/roadmap/process-full.md +19 -5
- package/dist/agent-src/commands/tdd/red.md +12 -2
- package/dist/agent-src/commands/work.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
- package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
- package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
- package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/code-comment-discipline.md +6 -0
- package/dist/agent-src/rules/code-provenance.md +4 -0
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +4 -0
- package/dist/agent-src/rules/domain-safety-retention.md +4 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
- package/dist/agent-src/rules/improve-before-implement.md +6 -8
- package/dist/agent-src/rules/laravel-routing.md +1 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +12 -34
- package/dist/agent-src/rules/symfony-routing.md +1 -1
- package/dist/agent-src/rules/token-efficiency.md +14 -0
- package/dist/agent-src/rules/tool-safety.md +4 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
- package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
- package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/dist/agent-src/scripts/stub_queue.ts +82 -0
- package/dist/agent-src/scripts/stubs_due.ts +516 -0
- package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
- package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
- package/dist/agent-src/skills/database/SKILL.md +8 -0
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
- package/dist/agent-src/skills/design-review/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
- package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
- package/dist/agent-src/skills/laravel/SKILL.md +35 -0
- package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
- package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
- package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
- package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
- package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +97 -3
- package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
- package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/dist/cli/commands/uiAudit.js +124 -5
- package/dist/cli/registry.js +2 -0
- package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
- package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
- package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
- package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
- package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
- package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
- package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
- package/dist/cli-delegate/cmd_adr_effective.js +102 -0
- package/dist/cli-delegate/cmd_conformance.js +80 -11
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +3 -2
- package/dist/cli-delegate/cmd_fleet.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +3 -2
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
- package/dist/cli-delegate/cmd_settings_set.js +2 -2
- package/dist/cli-delegate/cmd_sync.js +3 -2
- package/dist/cli-delegate/cmd_uninstall.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +3 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +58 -58
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +2900 -1049
- package/dist/install/claudeRuleRewrite.js +254 -0
- package/dist/install/detect.js +29 -16
- package/dist/install/detect_php_shape.js +159 -0
- package/dist/install/install.mjs +634 -428
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +3 -3
- package/dist/mcp/server.mjs +4895 -2627
- package/dist/server/schemas/settings.js +3 -0
- package/dist/ui/assets/index-D0jaCRPM.js +29 -0
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/THIRD-PARTY-NOTICES.md +25 -0
- package/docs/contracts/provider-lifecycle.md +1 -1
- package/docs/contracts/settings-classes.md +10 -4
- package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
- package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
- package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
- package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
- package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
- package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
- package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
- package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
- package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
- package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
- package/docs/guidelines/agent-infra/first-principles.md +2 -2
- package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
- package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
- package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
- package/docs/guidelines/agent-infra/layered-settings.md +10 -10
- package/docs/guidelines/agent-infra/memory-access.md +1 -1
- package/docs/guidelines/agent-infra/mental-models.md +3 -3
- package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
- package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
- package/docs/guidelines/agent-infra/role-contracts.md +2 -2
- package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
- package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
- package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
- package/docs/guidelines/agent-infra/six-hats.md +3 -3
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
- package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
- package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +6 -4
- package/docs/guidelines/code-clarity.md +18 -0
- package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
- package/docs/guidelines/cross-role-handoff.md +2 -2
- package/docs/guidelines/design-fidelity-mechanics.md +1 -1
- package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
- package/docs/guidelines/php/database.md +90 -7
- package/docs/guidelines/prompt-templates.md +7 -7
- package/llms.txt +2 -2
- package/package.json +5 -2
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
- package/src/agent-src/scripts/guarded_baseline.ts +343 -0
- package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/src/agent-src/scripts/stub_queue.ts +82 -0
- package/src/agent-src/scripts/stubs_due.ts +516 -0
- package/src/agent-src/scripts/ticket_bundles.ts +84 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
- package/src/agent-src/templates/scripts/check_memory.ts +258 -17
- package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/src/config/agent-settings.template.yml +32 -3
- package/src/config/assurance-capability-registry.json +21 -9
- package/src/config/canonical-terms.yml +119 -0
- package/src/config/capability-native-outcome-bars.json +81 -0
- package/src/config/ci-local-parity.yml +80 -0
- package/src/config/drafting-channels.yml +43 -0
- package/src/config/estate-count-budget.json +57 -36
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +729 -63
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +42 -19
- package/src/config/harness-evolution-budget.json +25 -0
- package/src/config/lapsed-beta-baseline.json +96 -0
- package/src/config/memory-twin-verdicts.yml +129 -0
- package/src/config/metric-registry.yml +124 -0
- package/src/config/pack-size-budget.json +16 -15
- package/src/config/preamble-payload-budget.json +12 -4
- package/src/config/profiles/balanced.ini +27 -0
- package/src/config/profiles/full.ini +27 -0
- package/src/config/profiles/minimal.ini +27 -0
- package/src/config/publish-surface.json +9 -2
- package/src/config/routing-coverage-seed.json +16 -2
- package/src/config/rule-stub-ceilings.json +133 -112
- package/src/config/turnaround-budget.json +66 -0
- package/src/install/claudeRuleRewrite.ts +288 -0
- package/src/install/detect.ts +60 -17
- package/src/install/detect_php_shape.ts +191 -0
- package/src/scripts/_cli/cmd_doctor.ts +27 -112
- package/src/scripts/_dispatch.bash +23 -0
- package/src/scripts/_lib/activation_ladder.ts +255 -0
- package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
- package/src/scripts/_lib/activation_states.ts +88 -0
- package/src/scripts/_lib/adherence_detectors.ts +143 -0
- package/src/scripts/_lib/adr_frontmatter.ts +26 -0
- package/src/scripts/_lib/arith_claims.ts +181 -0
- package/src/scripts/_lib/arm_ranking.ts +62 -0
- package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
- package/src/scripts/_lib/audit_field_provenance.ts +54 -0
- package/src/scripts/_lib/auto_dispatch.ts +32 -3
- package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
- package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
- package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
- package/src/scripts/_lib/candidate_proposer.ts +402 -0
- package/src/scripts/_lib/candidate_record.ts +601 -0
- package/src/scripts/_lib/capture_rate.ts +319 -0
- package/src/scripts/_lib/carrier_status.ts +118 -0
- package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
- package/src/scripts/_lib/collector_denominator.ts +771 -0
- package/src/scripts/_lib/collector_record.ts +340 -0
- package/src/scripts/_lib/collector_store.ts +664 -0
- package/src/scripts/_lib/collector_supervision.ts +827 -0
- package/src/scripts/_lib/concern_estate.ts +77 -0
- package/src/scripts/_lib/config_chain.ts +477 -0
- package/src/scripts/_lib/config_cost.ts +209 -0
- package/src/scripts/_lib/corpus_manifest.ts +726 -0
- package/src/scripts/_lib/council_settings_block.ts +6 -0
- package/src/scripts/_lib/curator_ops.ts +172 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
- package/src/scripts/_lib/delivery_criticality.ts +126 -0
- package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
- package/src/scripts/_lib/empty_cycles.ts +88 -0
- package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
- package/src/scripts/_lib/eval_publication.ts +354 -0
- package/src/scripts/_lib/evaluation_cascade.ts +452 -0
- package/src/scripts/_lib/evaluation_vector.ts +283 -0
- package/src/scripts/_lib/evaluator_promotion.ts +225 -0
- package/src/scripts/_lib/evidence_basis.ts +118 -0
- package/src/scripts/_lib/evolution_roi.ts +562 -0
- package/src/scripts/_lib/exec_evidence.ts +8 -0
- package/src/scripts/_lib/experience_card.ts +272 -0
- package/src/scripts/_lib/experience_report.ts +151 -0
- package/src/scripts/_lib/experiment_freeze.ts +112 -0
- package/src/scripts/_lib/generated_by.ts +66 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
- package/src/scripts/_lib/hook_effect_probe.ts +141 -0
- package/src/scripts/_lib/host_denominator.ts +687 -0
- package/src/scripts/_lib/host_projection_reach.ts +157 -0
- package/src/scripts/_lib/ignored_blocker.ts +148 -0
- package/src/scripts/_lib/install_reach_checks.ts +495 -0
- package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
- package/src/scripts/_lib/judge_hygiene.ts +228 -0
- package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
- package/src/scripts/_lib/lexical_shortlist.ts +215 -0
- package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
- package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
- package/src/scripts/_lib/loop_guards.ts +299 -0
- package/src/scripts/_lib/loss_class.ts +129 -0
- package/src/scripts/_lib/machine_wake.ts +51 -0
- package/src/scripts/_lib/md_prose_lines.ts +177 -0
- package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
- package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
- package/src/scripts/_lib/orchestration_record.ts +253 -5
- package/src/scripts/_lib/outcome_envelope.ts +227 -0
- package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
- package/src/scripts/_lib/paired_stats.ts +245 -0
- package/src/scripts/_lib/paired_verdict.ts +226 -0
- package/src/scripts/_lib/pathology_archive.ts +393 -0
- package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
- package/src/scripts/_lib/privacy_class.ts +47 -0
- package/src/scripts/_lib/promotion_capability.ts +315 -0
- package/src/scripts/_lib/promotion_evidence.ts +414 -0
- package/src/scripts/_lib/promotion_review.ts +294 -0
- package/src/scripts/_lib/prompt_shape.ts +92 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
- package/src/scripts/_lib/release_highlights.ts +70 -1
- package/src/scripts/_lib/release_material.ts +125 -2
- package/src/scripts/_lib/repeated_failure.ts +105 -0
- package/src/scripts/_lib/repo_root.ts +111 -0
- package/src/scripts/_lib/review_skipped_record.ts +37 -0
- package/src/scripts/_lib/role_split.ts +338 -0
- package/src/scripts/_lib/routing_corpus.ts +307 -0
- package/src/scripts/_lib/routing_index_input.ts +104 -0
- package/src/scripts/_lib/rule_injection.ts +22 -1
- package/src/scripts/_lib/runtime_journal.ts +1499 -0
- package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
- package/src/scripts/_lib/semantic_noop.ts +167 -0
- package/src/scripts/_lib/skill_catalogue.ts +11 -1
- package/src/scripts/_lib/source_digest.ts +200 -0
- package/src/scripts/_lib/source_redact.ts +260 -0
- package/src/scripts/_lib/source_shape.ts +502 -0
- package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
- package/src/scripts/_lib/strip_comments.d.mts +8 -0
- package/src/scripts/_lib/strip_comments.mjs +65 -0
- package/src/scripts/_lib/test_red_state.ts +154 -0
- package/src/scripts/_lib/trigger_shift.ts +144 -0
- package/src/scripts/_lib/untrusted_content.ts +82 -7
- package/src/scripts/activation_receipt.ts +258 -0
- package/src/scripts/adoption_report.ts +1 -1
- package/src/scripts/adr/evidence_census.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +26 -2
- package/src/scripts/adr_cite_check.ts +164 -1
- package/src/scripts/ai_council/blind_review.ts +11 -1
- package/src/scripts/ai_council/clients.ts +4 -0
- package/src/scripts/ai_council/config.ts +3 -0
- package/src/scripts/ai_council/consensus.ts +28 -8
- package/src/scripts/ai_council/consensus_round.ts +226 -0
- package/src/scripts/ai_council/cross_exam.ts +128 -0
- package/src/scripts/ai_council/disagreement_signal.ts +338 -0
- package/src/scripts/ai_council/explain_route.ts +157 -0
- package/src/scripts/ai_council/information_gain.ts +293 -0
- package/src/scripts/ai_council/inline_findings.ts +340 -0
- package/src/scripts/ai_council/judge_position_bias.ts +197 -0
- package/src/scripts/ai_council/leakage_corpus.ts +385 -0
- package/src/scripts/ai_council/leakage_patterns.ts +453 -0
- package/src/scripts/ai_council/minority_retention.ts +171 -0
- package/src/scripts/ai_council/orchestrator.ts +16 -203
- package/src/scripts/ai_council/orchestrator_results.ts +23 -3
- package/src/scripts/ai_council/pricing.ts +106 -0
- package/src/scripts/ai_council/prompts.ts +74 -7
- package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
- package/src/scripts/ai_council/py_format.ts +14 -3
- package/src/scripts/ai_council/recouncil_guard.ts +293 -0
- package/src/scripts/ai_council/recouncil_savings.ts +299 -0
- package/src/scripts/ai_council/replay_route.ts +223 -0
- package/src/scripts/ai_council/response_record.ts +50 -0
- package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
- package/src/scripts/ai_council/routing_training_row.ts +197 -0
- package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
- package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
- package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
- package/src/scripts/asset_delivery_ledger.ts +157 -0
- package/src/scripts/attest_artifact.ts +193 -0
- package/src/scripts/audit_auto_rules.ts +2 -1
- package/src/scripts/audit_command_surface.ts +1 -1
- package/src/scripts/audit_mcp_tools.ts +2 -2
- package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
- package/src/scripts/audit_user_type_axis.ts +2 -1
- package/src/scripts/bench_ab_clone.ts +215 -10
- package/src/scripts/bench_ab_integrity.ts +119 -5
- package/src/scripts/bench_ab_v2_stats.ts +40 -213
- package/src/scripts/build_archive_index.ts +1 -1
- package/src/scripts/build_linear_digest.ts +1 -1
- package/src/scripts/build_proof.ts +11 -4
- package/src/scripts/build_rule_trigger_matrix.ts +1 -1
- package/src/scripts/build_source_digests.ts +157 -0
- package/src/scripts/cache_realization_report.ts +103 -0
- package/src/scripts/check_adr_frontmatter.ts +131 -10
- package/src/scripts/check_benchmark_report_fields.ts +207 -0
- package/src/scripts/check_beta_review_markers.ts +235 -6
- package/src/scripts/check_bundle_path_leakage.ts +34 -1
- package/src/scripts/check_claims.ts +576 -6
- package/src/scripts/check_composite_arming.ts +35 -0
- package/src/scripts/check_concern_admissions.ts +365 -0
- package/src/scripts/check_enforcement_coverage.ts +28 -0
- package/src/scripts/check_estate_count.ts +347 -25
- package/src/scripts/check_gate_reachability.ts +383 -0
- package/src/scripts/check_host_loadability.ts +104 -0
- package/src/scripts/check_loss_class_declared.ts +308 -0
- package/src/scripts/check_md_language.ts +15 -98
- package/src/scripts/check_memory_proposal.ts +18 -11
- package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
- package/src/scripts/check_no_external_sources.ts +281 -6
- package/src/scripts/check_pack_conformance_fixture.ts +11 -1
- package/src/scripts/check_pack_size.ts +59 -2
- package/src/scripts/check_preamble_payload_budget.ts +114 -3
- package/src/scripts/check_prefix_stable_mutation.ts +372 -0
- package/src/scripts/check_publish_surface.ts +10 -1
- package/src/scripts/check_references.ts +24 -1
- package/src/scripts/check_release_highlights.ts +96 -13
- package/src/scripts/check_roadmap_trackable.ts +17 -2
- package/src/scripts/check_rule_evidence_declaration.ts +316 -0
- package/src/scripts/check_rule_projection_integrity.ts +14 -4
- package/src/scripts/check_score_contract.ts +26 -3
- package/src/scripts/check_static_parity.ts +285 -0
- package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
- package/src/scripts/check_suppression_hygiene.ts +15 -0
- package/src/scripts/ci_settle.ts +39 -2
- package/src/scripts/code_graph/build.ts +60 -3
- package/src/scripts/code_graph/extract.ts +44 -0
- package/src/scripts/code_graph/types.ts +24 -0
- package/src/scripts/collector_daemon.ts +714 -0
- package/src/scripts/config_cost_report.ts +302 -0
- package/src/scripts/consumer_matrix.ts +74 -1
- package/src/scripts/corpus_manifest.ts +235 -0
- package/src/scripts/cost/budget.mjs +10 -3
- package/src/scripts/cost/track.mjs +10 -3
- package/src/scripts/council_cli.ts +37 -54
- package/src/scripts/dispatch_r2_reviewer.ts +46 -5
- package/src/scripts/evolution_lab.ts +1153 -0
- package/src/scripts/external_sources_denylist.json +5 -18
- package/src/scripts/extract_audit_patterns.ts +21 -0
- package/src/scripts/fold_intake.ts +12 -1
- package/src/scripts/gen_discovery_baseline.ts +1 -1
- package/src/scripts/generate_capabilities_index.ts +12 -5
- package/src/scripts/generate_capability_matrix.ts +3 -3
- package/src/scripts/generate_command_flows.ts +2 -2
- package/src/scripts/generate_cookbook.ts +2 -2
- package/src/scripts/generate_index.ts +8 -1
- package/src/scripts/generate_knowledge_index.ts +2 -1
- package/src/scripts/generate_ownership_matrix.ts +2 -1
- package/src/scripts/generate_pack_manifests.ts +10 -2
- package/src/scripts/generate_role_experiences_catalog.ts +2 -2
- package/src/scripts/generate_settings_reference.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +22 -1
- package/src/scripts/grade_target_readiness.ts +48 -5
- package/src/scripts/hook_effect_doctor.ts +261 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +125 -16
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
- package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
- package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
- package/src/scripts/hooks/concern_registry.ts +6 -0
- package/src/scripts/hooks/dispatch_hook.ts +32 -0
- package/src/scripts/hooks/journal_record_hook.ts +345 -0
- package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
- package/src/scripts/hooks/run_continuation_hook.ts +44 -9
- package/src/scripts/hooks/shims/install.sh +61 -0
- package/src/scripts/hooks/shims/php +101 -0
- package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
- package/src/scripts/hot_context_hook.ts +16 -0
- package/src/scripts/install-hooks.sh +20 -5
- package/src/scripts/install.ts +17 -35
- package/src/scripts/inventory_frontmatter.ts +2 -1
- package/src/scripts/language_mirror_hook.ts +14 -2
- package/src/scripts/lint_adr_sweep_routing.ts +12 -0
- package/src/scripts/lint_canonical_terms.ts +604 -0
- package/src/scripts/lint_carrier_integrity.ts +820 -0
- package/src/scripts/lint_code_comments.ts +643 -0
- package/src/scripts/lint_composition_review.ts +619 -0
- package/src/scripts/lint_consolidation_lineage.ts +666 -0
- package/src/scripts/lint_eval_specs.ts +593 -0
- package/src/scripts/lint_hook_manifest.ts +19 -0
- package/src/scripts/lint_host_portability.ts +373 -0
- package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
- package/src/scripts/lint_memory_twin_parity.ts +335 -0
- package/src/scripts/lint_metric_consumers.ts +355 -0
- package/src/scripts/lint_plan_risk_register.ts +39 -19
- package/src/scripts/lint_promotion_paths.ts +779 -0
- package/src/scripts/lint_skill_descriptions.ts +18 -1
- package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
- package/src/scripts/lint_skill_link_reach.ts +252 -0
- package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
- package/src/scripts/lint_ticket_buildable.ts +17 -1
- package/src/scripts/llm_propose.ts +256 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
- package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
- package/src/scripts/measure_delivery_sets.ts +361 -0
- package/src/scripts/measure_docs_dead_links.ts +348 -0
- package/src/scripts/measure_host_capture.ts +461 -0
- package/src/scripts/measure_routing_signal.ts +307 -0
- package/src/scripts/migration_status.ts +3 -3
- package/src/scripts/model_rule_injection.ts +76 -0
- package/src/scripts/orchestration_record.ts +14 -0
- package/src/scripts/preamble_byte_census.ts +139 -10
- package/src/scripts/prepack-check.mjs +4 -1
- package/src/scripts/probe_council_retention.ts +495 -0
- package/src/scripts/probe_turnaround.ts +384 -0
- package/src/scripts/probe_unblocked_ask.ts +279 -0
- package/src/scripts/release.ts +21 -37
- package/src/scripts/release_drill.ts +143 -0
- package/src/scripts/release_env.ts +35 -0
- package/src/scripts/release_publication.ts +84 -0
- package/src/scripts/render_benchmark_md.ts +1 -1
- package/src/scripts/rule_activation_census.ts +70 -9
- package/src/scripts/rule_backlinks.ts +1 -1
- package/src/scripts/run_lifecycle_suite.ts +208 -0
- package/src/scripts/run_skill_evals.ts +40 -0
- package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
- package/src/scripts/schemas/drafting-channels.schema.json +43 -0
- package/src/scripts/schemas/evals.schema.json +24 -1
- package/src/scripts/schemas/rule.schema.json +52 -1
- package/src/scripts/schemas/skill.schema.json +17 -2
- package/src/scripts/skill_overlap.ts +7 -1
- package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
- package/src/scripts/skill_usage_report.ts +2 -1
- package/src/scripts/stubs_due.ts +211 -0
- package/src/scripts/sweep_source_surfaces.ts +678 -0
- package/src/scripts/sync_pr_branch.ts +3 -3
- package/src/scripts/trigger_eval_grandfather.json +202 -222
- package/src/scripts/utilization_report.ts +22 -2
- package/src/server/schemas/settings.ts +5 -0
- package/src/templates/marketing-copy.yml +1 -1
- package/dist/ui/assets/index-Cxgy63kz.js +0 -26
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime-wiring checks for `agent-config doctor`.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-skill-ecosystem-runtime-enforcement` Phase 2, Steps 2-5. The gate
|
|
5
|
+
* estate checks ARTIFACTS — is the rule written, is the projection byte-exact,
|
|
6
|
+
* does the manifest parse. Nothing checked whether the wiring is LIVE: whether
|
|
7
|
+
* the settings resolver returns anything, whether the router artifact parses,
|
|
8
|
+
* whether each registered hook resolves to something executable, and whether an
|
|
9
|
+
* inherited git-discovery variable is silently re-pointing every gate at another
|
|
10
|
+
* repository.
|
|
11
|
+
*
|
|
12
|
+
* All four are REPORTS. `doctor` writes nothing and always exits zero, so a
|
|
13
|
+
* check here returns a verdict and never a refusal — the point is that a
|
|
14
|
+
* disabled or mis-wired estate becomes VISIBLE, not that a diagnostic starts
|
|
15
|
+
* failing builds. A gate that wanted to refuse would belong in the gate estate.
|
|
16
|
+
*
|
|
17
|
+
* Extracted into `_lib/` rather than added to `cmd_doctor.ts` for a stated
|
|
18
|
+
* reason: that file is 3,700 lines and `check_source_size_budget` counts every
|
|
19
|
+
* line above 1,500, so four checks written inline would be charged against a
|
|
20
|
+
* budget while the same code in a new module is free. The seam is also what
|
|
21
|
+
* makes them unit-testable without booting the CLI.
|
|
22
|
+
*/
|
|
23
|
+
import { spawnSync } from 'node:child_process';
|
|
24
|
+
import * as fs from 'node:fs';
|
|
25
|
+
import * as path from 'node:path';
|
|
26
|
+
import process from 'node:process';
|
|
27
|
+
|
|
28
|
+
import { parse as parseYaml } from 'yaml';
|
|
29
|
+
|
|
30
|
+
import { inheritedGitOverrides } from './repo_root.js';
|
|
31
|
+
|
|
32
|
+
/** The verdict shape `cmd_doctor` renders. Mirrors its internal `Dict` rows. */
|
|
33
|
+
export interface WiringCheck {
|
|
34
|
+
id: string;
|
|
35
|
+
/**
|
|
36
|
+
* The four the doctor's own report contract publishes. `info` was a fifth
|
|
37
|
+
* here for one commit and is gone: the MCP `doctor_report` tool asserts the
|
|
38
|
+
* published union, so a fifth value that never reached that contract failed
|
|
39
|
+
* the tool's shape test rather than appearing in a report. A vocabulary a
|
|
40
|
+
* consumer cannot receive is not a vocabulary.
|
|
41
|
+
*/
|
|
42
|
+
status: 'ok' | 'warn' | 'fail' | 'skipped';
|
|
43
|
+
message: string;
|
|
44
|
+
remedy: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Step 2 — the settings resolver returns something, and WHICH FILE won.
|
|
49
|
+
*
|
|
50
|
+
* The cascade is user-global then project, last write winning. Nearly twenty
|
|
51
|
+
* rules in this suite tell an agent to read `.agent-settings.yml` to learn
|
|
52
|
+
* whether a feature is on, and every one of them is wrong about a key set on
|
|
53
|
+
* another layer. Reporting the winning FILE per key is the part that makes the
|
|
54
|
+
* check worth running — a value alone cannot be argued with.
|
|
55
|
+
*/
|
|
56
|
+
export function checkSettingsResolution(
|
|
57
|
+
iterOverrides: () => Iterable<[string, unknown, string]>,
|
|
58
|
+
): WiringCheck {
|
|
59
|
+
let pairs: [string, unknown, string][];
|
|
60
|
+
try {
|
|
61
|
+
pairs = [...iterOverrides()];
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return {
|
|
64
|
+
id: 'settings-resolution',
|
|
65
|
+
status: 'fail',
|
|
66
|
+
message: `settings cascade did not resolve: ${e instanceof Error ? e.message : String(e)}`,
|
|
67
|
+
remedy: 'check the YAML in every layer `agent-config settings:get <key>` reports',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (pairs.length === 0) {
|
|
71
|
+
return {
|
|
72
|
+
id: 'settings-resolution',
|
|
73
|
+
// `skipped`, not `ok`: the cascade RESOLVED and there was nothing
|
|
74
|
+
// in it, which is a check that had nothing to inspect rather than a
|
|
75
|
+
// check that passed. Reporting `ok` here would read as "settings
|
|
76
|
+
// resolved fine" on a tree where no setting exists at all — the
|
|
77
|
+
// same conflation the reach check exists to remove elsewhere.
|
|
78
|
+
status: 'skipped',
|
|
79
|
+
message:
|
|
80
|
+
'settings cascade resolves, and NO layer sets any key — every read falls to the ' +
|
|
81
|
+
'template default. That is a valid state, not a failure: a fresh project has no settings.',
|
|
82
|
+
remedy: '',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
// Last writer wins, which is the resolver's own rule — so the winning file
|
|
86
|
+
// is the LAST occurrence of a key, not the first.
|
|
87
|
+
const winner = new Map<string, string>();
|
|
88
|
+
for (const [key, , file] of pairs) winner.set(key, file);
|
|
89
|
+
const byFile = new Map<string, number>();
|
|
90
|
+
for (const file of winner.values()) byFile.set(file, (byFile.get(file) ?? 0) + 1);
|
|
91
|
+
const summary = [...byFile.entries()]
|
|
92
|
+
.sort((a, b) => b[1] - a[1])
|
|
93
|
+
.map(([f, n]) => `${path.basename(f)}=${String(n)}`)
|
|
94
|
+
.join(' · ');
|
|
95
|
+
return {
|
|
96
|
+
id: 'settings-resolution',
|
|
97
|
+
status: 'ok',
|
|
98
|
+
message: `${String(winner.size)} key(s) resolved across ${String(byFile.size)} layer(s) — ${summary}`,
|
|
99
|
+
remedy: '',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Step 3 — the router artifact exists, PARSES, and reports its rule count.
|
|
105
|
+
*
|
|
106
|
+
* Parsing is the half that matters. A router file that exists but does not parse
|
|
107
|
+
* fails silently at load: the host reads no rules and behaves like a tree with
|
|
108
|
+
* none, which is indistinguishable from a correctly minimal configuration.
|
|
109
|
+
*/
|
|
110
|
+
export function checkRouterArtifact(repoRoot: string, rel = 'dist/router.json'): WiringCheck {
|
|
111
|
+
const abs = path.join(repoRoot, rel);
|
|
112
|
+
if (!fs.existsSync(abs)) {
|
|
113
|
+
return {
|
|
114
|
+
id: 'router-artifact',
|
|
115
|
+
status: 'warn',
|
|
116
|
+
message: `${rel} is absent — no rule router is deployed`,
|
|
117
|
+
remedy: 'task generate-tools',
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
let doc: unknown;
|
|
121
|
+
try {
|
|
122
|
+
doc = JSON.parse(fs.readFileSync(abs, 'utf8'));
|
|
123
|
+
} catch (e) {
|
|
124
|
+
return {
|
|
125
|
+
id: 'router-artifact',
|
|
126
|
+
status: 'fail',
|
|
127
|
+
message: `${rel} exists but does NOT parse: ${e instanceof Error ? e.message : String(e)}`,
|
|
128
|
+
remedy: 'task generate-tools (a present-but-unparseable router loads as zero rules)',
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const rules = _routerRuleCount(doc);
|
|
132
|
+
if (rules === 0) {
|
|
133
|
+
return {
|
|
134
|
+
id: 'router-artifact',
|
|
135
|
+
status: 'warn',
|
|
136
|
+
message: `${rel} parses and carries ZERO rules — a router with no rules routes nothing`,
|
|
137
|
+
remedy: 'task generate-tools',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return { id: 'router-artifact', status: 'ok', message: `${rel} parses · ${String(rules)} rule(s)`, remedy: '' };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Count routed rules across whichever shape the artifact uses. */
|
|
144
|
+
export function _routerRuleCount(doc: unknown): number {
|
|
145
|
+
if (doc === null || typeof doc !== 'object') return 0;
|
|
146
|
+
const d = doc as Record<string, unknown>;
|
|
147
|
+
if (Array.isArray(d['rules'])) return d['rules'].length;
|
|
148
|
+
let n = 0;
|
|
149
|
+
for (const v of Object.values(d)) {
|
|
150
|
+
if (Array.isArray(v)) n += v.length;
|
|
151
|
+
else if (v !== null && typeof v === 'object') n += _routerRuleCount(v);
|
|
152
|
+
}
|
|
153
|
+
return n;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface HookProbe {
|
|
157
|
+
id: string;
|
|
158
|
+
script: string;
|
|
159
|
+
resolves: boolean;
|
|
160
|
+
ms: number | null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Step 4 — every registered hook resolves to a real file, with its cost.
|
|
165
|
+
*
|
|
166
|
+
* Cost is reported PER HOOK rather than as a total, because a latency
|
|
167
|
+
* regression is only actionable where it is incurred: a 300 ms total tells you
|
|
168
|
+
* nothing, while one 280 ms concern names itself.
|
|
169
|
+
*
|
|
170
|
+
* `probe` defaults to a real invocation with `--help`, which every dispatcher
|
|
171
|
+
* entry point accepts and which does no work. Injectable so the unit tests do
|
|
172
|
+
* not spawn 53 processes.
|
|
173
|
+
*/
|
|
174
|
+
export function checkHookResolution(
|
|
175
|
+
repoRoot: string,
|
|
176
|
+
manifestRel = 'src/scripts/hook_manifest.yaml',
|
|
177
|
+
probe: ((script: string) => number | null) | null = null,
|
|
178
|
+
): { check: WiringCheck; probes: HookProbe[] } {
|
|
179
|
+
const abs = path.join(repoRoot, manifestRel);
|
|
180
|
+
if (!fs.existsSync(abs)) {
|
|
181
|
+
return {
|
|
182
|
+
check: {
|
|
183
|
+
id: 'hook-resolution',
|
|
184
|
+
status: 'fail',
|
|
185
|
+
message: `${manifestRel} is absent — the hook estate cannot be enumerated`,
|
|
186
|
+
remedy: 'restore the manifest; every hook is registered from it',
|
|
187
|
+
},
|
|
188
|
+
probes: [],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
let concerns: Record<string, { script?: unknown }>;
|
|
192
|
+
try {
|
|
193
|
+
const doc = parseYaml(fs.readFileSync(abs, 'utf8')) as { concerns?: unknown };
|
|
194
|
+
concerns = (doc.concerns ?? {}) as Record<string, { script?: unknown }>;
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return {
|
|
197
|
+
check: {
|
|
198
|
+
id: 'hook-resolution',
|
|
199
|
+
status: 'fail',
|
|
200
|
+
message: `${manifestRel} does not parse: ${e instanceof Error ? e.message : String(e)}`,
|
|
201
|
+
remedy: 'fix the manifest YAML',
|
|
202
|
+
},
|
|
203
|
+
probes: [],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
const probes: HookProbe[] = [];
|
|
207
|
+
for (const [id, c] of Object.entries(concerns)) {
|
|
208
|
+
const script = typeof c.script === 'string' ? c.script : '';
|
|
209
|
+
const resolves = script !== '' && fs.existsSync(path.join(repoRoot, script));
|
|
210
|
+
probes.push({ id, script, resolves, ms: resolves && probe !== null ? probe(script) : null });
|
|
211
|
+
}
|
|
212
|
+
const broken = probes.filter((p) => !p.resolves);
|
|
213
|
+
if (broken.length > 0) {
|
|
214
|
+
return {
|
|
215
|
+
check: {
|
|
216
|
+
id: 'hook-resolution',
|
|
217
|
+
status: 'fail',
|
|
218
|
+
message:
|
|
219
|
+
`${String(broken.length)} of ${String(probes.length)} registered hook(s) do NOT resolve to a file: ` +
|
|
220
|
+
broken.map((b) => b.id).join(', '),
|
|
221
|
+
remedy: 'a registered hook with no script silently no-ops every session — fix the path or drop the entry',
|
|
222
|
+
},
|
|
223
|
+
probes,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
const timed = probes.filter((p) => p.ms !== null).sort((a, b) => (b.ms ?? 0) - (a.ms ?? 0));
|
|
227
|
+
const slowest = timed.length > 0 ? ` · slowest ${timed[0]!.id} ${String(timed[0]!.ms)}ms` : '';
|
|
228
|
+
return {
|
|
229
|
+
check: {
|
|
230
|
+
id: 'hook-resolution',
|
|
231
|
+
status: 'ok',
|
|
232
|
+
message: `${String(probes.length)} registered hook(s), all resolving${slowest}`,
|
|
233
|
+
remedy: '',
|
|
234
|
+
},
|
|
235
|
+
probes,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** A real `--help` invocation, timed. `null` when it cannot be measured. */
|
|
240
|
+
export function probeHookCost(repoRoot: string, script: string): number | null {
|
|
241
|
+
const started = Date.now();
|
|
242
|
+
const r = spawnSync(process.execPath, [path.join(repoRoot, 'scripts-run'), script, '--help'], {
|
|
243
|
+
cwd: repoRoot,
|
|
244
|
+
encoding: 'utf8',
|
|
245
|
+
timeout: 10_000,
|
|
246
|
+
});
|
|
247
|
+
if (r.error) return null;
|
|
248
|
+
return Date.now() - started;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Step 5 — an inherited git-discovery variable.
|
|
253
|
+
*
|
|
254
|
+
* The recorded failure: a git hook exports `GIT_DIR` into every child, so a gate
|
|
255
|
+
* run inside one resolves against whatever that points at — inside a worktree,
|
|
256
|
+
* the parent checkout. The gate runs, reads the wrong tree, and PASSES. Nothing
|
|
257
|
+
* about the output says which repository answered.
|
|
258
|
+
*
|
|
259
|
+
* Reported as a warning rather than a failure because the variable is legitimate
|
|
260
|
+
* where git itself set it; what it is not is invisible.
|
|
261
|
+
*/
|
|
262
|
+
export function checkInheritedGitEnv(env: NodeJS.ProcessEnv = process.env): WiringCheck {
|
|
263
|
+
const found = inheritedGitOverrides(env);
|
|
264
|
+
if (found.length === 0) {
|
|
265
|
+
return {
|
|
266
|
+
id: 'inherited-git-env',
|
|
267
|
+
status: 'ok',
|
|
268
|
+
message: 'no git discovery override in the environment — git resolves from the working directory',
|
|
269
|
+
remedy: '',
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
id: 'inherited-git-env',
|
|
274
|
+
status: 'warn',
|
|
275
|
+
message:
|
|
276
|
+
`${String(found.length)} git discovery override(s) inherited: ` +
|
|
277
|
+
found.map((f) => `${f.name}=${f.value}`).join(' · ') +
|
|
278
|
+
' — every git call in this process answers for THAT repository, not the working directory',
|
|
279
|
+
remedy:
|
|
280
|
+
'unset them before running a gate from inside a git hook (`env -u GIT_DIR -u GIT_WORK_TREE …`), ' +
|
|
281
|
+
'or resolve the root with _lib/repo_root.ts, which refuses instead of guessing',
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* The four runtime-wiring runners, as one table.
|
|
287
|
+
*
|
|
288
|
+
* Returned as a map rather than registered inline at each of `cmd_doctor`'s TWO
|
|
289
|
+
* runner tables: written there it is ~20 lines duplicated, and every line of
|
|
290
|
+
* that file above 1,500 is charged by `check_source_size_budget`. One factory,
|
|
291
|
+
* two spreads.
|
|
292
|
+
*/
|
|
293
|
+
/** The four ids, in render order. Spread into `cmd_doctor`'s two id registries. */
|
|
294
|
+
export const WIRING_CHECK_IDS = ['settings-resolution', 'router-artifact', 'hook-resolution', 'inherited-git-env', 'hooks-kill-switch'] as const;
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* The estate kill switch, reported so a DISABLED estate is visible.
|
|
299
|
+
*
|
|
300
|
+
* `road-to-skill-ecosystem-runtime-enforcement` Phase 1 Step 7's second clause,
|
|
301
|
+
* which could not be satisfied until the Phase 2 diagnostic existed. The flag
|
|
302
|
+
* itself has been implemented since Phase 1; what was missing is that a session
|
|
303
|
+
* running with every guard switched off looked exactly like one running with
|
|
304
|
+
* them all armed.
|
|
305
|
+
*
|
|
306
|
+
* ONLY the exact value `1` disarms, and the check mirrors that rather than
|
|
307
|
+
* guessing: a truthy-ish test would report `=0` as disabled, which is the
|
|
308
|
+
* opposite of what it means.
|
|
309
|
+
*/
|
|
310
|
+
export function checkHooksDisabled(env: NodeJS.ProcessEnv = process.env): WiringCheck {
|
|
311
|
+
const raw = env['AGENT_CONFIG_DISABLE_HOOKS'];
|
|
312
|
+
if (raw !== '1') {
|
|
313
|
+
return {
|
|
314
|
+
id: 'hooks-kill-switch',
|
|
315
|
+
status: 'ok',
|
|
316
|
+
message:
|
|
317
|
+
raw === undefined || raw === ''
|
|
318
|
+
? 'AGENT_CONFIG_DISABLE_HOOKS is not set — the hook estate is armed'
|
|
319
|
+
: `AGENT_CONFIG_DISABLE_HOOKS=${raw} — only the exact value "1" disarms, so the estate is armed`,
|
|
320
|
+
remedy: '',
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
id: 'hooks-kill-switch',
|
|
325
|
+
status: 'warn',
|
|
326
|
+
message:
|
|
327
|
+
'AGENT_CONFIG_DISABLE_HOOKS=1 — EVERY hook and shim in this environment is disabled. ' +
|
|
328
|
+
'A run under this flag enforces nothing, and without this line it would look identical ' +
|
|
329
|
+
'to one with the whole estate armed.',
|
|
330
|
+
remedy: 'unset AGENT_CONFIG_DISABLE_HOOKS (it is intended for one command, not a session)',
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function wiringRunners(opts: {
|
|
335
|
+
packageRoot: string;
|
|
336
|
+
iterOverrides: () => Iterable<[string, unknown, string]>;
|
|
337
|
+
}): Record<string, () => WiringCheck> {
|
|
338
|
+
return {
|
|
339
|
+
'settings-resolution': () => checkSettingsResolution(opts.iterOverrides),
|
|
340
|
+
'router-artifact': () => checkRouterArtifact(opts.packageRoot),
|
|
341
|
+
// Per-hook COST is not probed on the default path: it spawns one process
|
|
342
|
+
// per registered concern (53 today), turning a read-only diagnostic into
|
|
343
|
+
// a multi-second one. `probeHookCost` is exported for a caller that wants it.
|
|
344
|
+
'hook-resolution': () => checkHookResolution(opts.packageRoot).check,
|
|
345
|
+
'inherited-git-env': () => checkInheritedGitEnv(),
|
|
346
|
+
'hooks-kill-switch': () => checkHooksDisabled(),
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Managed hook wiring (single-surface model): the deterministic hook matrix
|
|
352
|
+
* must be registered in ~/.claude/settings.json AND the dispatch target
|
|
353
|
+
* (`agent-config` binary) must resolve on PATH. Both halves are required —
|
|
354
|
+
* hooks without a binary silently no-op every session.
|
|
355
|
+
*/
|
|
356
|
+
export interface HookWiringDeps {
|
|
357
|
+
which: (bin: string) => string | null;
|
|
358
|
+
packageRoot: string;
|
|
359
|
+
homeDir: string;
|
|
360
|
+
buildMatrix: (manifestPath: string) => Record<string, unknown>;
|
|
361
|
+
managedSignature: string;
|
|
362
|
+
pluginInstalled: () => boolean;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export function checkHookWiring(deps: HookWiringDeps): WiringCheck {
|
|
366
|
+
const claude = deps.which('claude');
|
|
367
|
+
if (claude === null) {
|
|
368
|
+
return {
|
|
369
|
+
id: 'hook-wiring',
|
|
370
|
+
status: 'skipped',
|
|
371
|
+
message: 'Claude Code CLI not on PATH — hook-wiring check not applicable',
|
|
372
|
+
remedy: '',
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const settings_path = path.join(deps.homeDir, '.claude', 'settings.json');
|
|
376
|
+
let missing: string[];
|
|
377
|
+
try {
|
|
378
|
+
const matrix = deps.buildMatrix(path.join(deps.packageRoot, 'src', 'scripts', 'hook_manifest.yaml'));
|
|
379
|
+
const settings = fs.existsSync(settings_path)
|
|
380
|
+
? (JSON.parse(fs.readFileSync(settings_path, 'utf8')) as Record<string, unknown>)
|
|
381
|
+
: {};
|
|
382
|
+
const hooks = ((settings['hooks'] ?? {}) as Record<string, unknown>) || {};
|
|
383
|
+
missing = Object.keys(matrix).filter((ev) => {
|
|
384
|
+
const groups = hooks[ev];
|
|
385
|
+
if (!Array.isArray(groups)) return true;
|
|
386
|
+
return !JSON.stringify(groups).includes(deps.managedSignature);
|
|
387
|
+
});
|
|
388
|
+
} catch (e) {
|
|
389
|
+
return {
|
|
390
|
+
id: 'hook-wiring',
|
|
391
|
+
status: 'fail',
|
|
392
|
+
message: `cannot evaluate managed hooks: ${String(e)}`,
|
|
393
|
+
remedy: 'fix ~/.claude/settings.json (invalid JSON?), then agent-config refresh --global',
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
const binary_ok = deps.which('agent-config') !== null;
|
|
397
|
+
if (missing.length === 0 && binary_ok) {
|
|
398
|
+
return {
|
|
399
|
+
id: 'hook-wiring',
|
|
400
|
+
status: 'ok',
|
|
401
|
+
message: 'managed hooks registered in ~/.claude/settings.json; dispatch binary on PATH',
|
|
402
|
+
remedy: '',
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (missing.length > 0 && deps.pluginInstalled()) {
|
|
406
|
+
return {
|
|
407
|
+
id: 'hook-wiring',
|
|
408
|
+
status: 'warn',
|
|
409
|
+
message:
|
|
410
|
+
`managed hooks missing for: ${missing.join(', ')} — currently carried by the ` +
|
|
411
|
+
'installed plugin (deprecated surface)',
|
|
412
|
+
remedy: 'agent-config refresh --global (writes the managed settings.json block)',
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
const parts: string[] = [];
|
|
416
|
+
if (missing.length > 0) parts.push(`managed hooks missing for: ${missing.join(', ')}`);
|
|
417
|
+
if (!binary_ok) parts.push('`agent-config` not on PATH (hooks would silently no-op)');
|
|
418
|
+
if (parts.length === 0) {
|
|
419
|
+
// hooks complete, binary missing was the only issue → covered above.
|
|
420
|
+
parts.push('`agent-config` not on PATH');
|
|
421
|
+
}
|
|
422
|
+
return {
|
|
423
|
+
id: 'hook-wiring',
|
|
424
|
+
status: 'fail',
|
|
425
|
+
message: parts.join('; '),
|
|
426
|
+
remedy: binary_ok
|
|
427
|
+
? 'agent-config refresh --global'
|
|
428
|
+
: 'npm install -g @event4u/agent-config, then agent-config refresh --global',
|
|
429
|
+
};
|
|
430
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The semantic no-op gate — `road-to-harness-promotion-bridge` step 7.4.
|
|
3
|
+
*
|
|
4
|
+
* > *Reject semantic no-ops. A no-op detector plus a minimum
|
|
5
|
+
* > material-improvement threshold. The master kept the cooldown and lineage
|
|
6
|
+
* > from the same attack and dropped both gates.*
|
|
7
|
+
* > verify: **a paraphrase-only candidate is refused before the cascade.**
|
|
8
|
+
*
|
|
9
|
+
* ## "Before the cascade" — what that resolves to in this tree
|
|
10
|
+
*
|
|
11
|
+
* There is no artefact named "cascade" here; the evaluation cascade is the
|
|
12
|
+
* lifecycle spine, `proposed -> diagnostic-evaluated -> selection-evaluated ->
|
|
13
|
+
* …`. So "before the cascade" means: while the candidate is still `proposed`,
|
|
14
|
+
* before the first transition and before anything expensive runs.
|
|
15
|
+
* {@link screenSemanticNoOps} is that stage, and it is SYNCHRONOUS for the same
|
|
16
|
+
* reason `screenNearDuplicates` is — a synchronous function cannot await a
|
|
17
|
+
* network call, so the zero-model-call property follows from the signature
|
|
18
|
+
* rather than from a promise the body has to keep.
|
|
19
|
+
*
|
|
20
|
+
* ## Two gates, because the step asks for two
|
|
21
|
+
*
|
|
22
|
+
* 1. **The no-op detector.** {@link isSemanticNoOp} — a candidate whose text is
|
|
23
|
+
* a paraphrase of what it replaces. Measured with `shingleOverlap`, the same
|
|
24
|
+
* primitive `curator_ops`'s near-duplicate screen and `lint_originality` use.
|
|
25
|
+
* 2. **The minimum material-improvement threshold.** A candidate that is not a
|
|
26
|
+
* paraphrase can still be a rounding error;
|
|
27
|
+
* {@link MIN_MATERIAL_IMPROVEMENT_PERCENT} is the floor its measured delta
|
|
28
|
+
* must clear.
|
|
29
|
+
*
|
|
30
|
+
* Both are needed and neither implies the other: a total rewrite that changes
|
|
31
|
+
* nothing measurable passes (1) and fails (2); a one-word change with a large
|
|
32
|
+
* measured delta passes (2) and fails (1). Shipping one of the two is what the
|
|
33
|
+
* master did.
|
|
34
|
+
*/
|
|
35
|
+
import { NEAR_DUPLICATE_THRESHOLD } from './curator_ops.js';
|
|
36
|
+
import { shingleOverlap } from './shingle_similarity.js';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Containment-overlap percent at which a candidate is a paraphrase of what it
|
|
40
|
+
* replaces.
|
|
41
|
+
*
|
|
42
|
+
* **Measured bound, stated rather than left for a reader to discover.**
|
|
43
|
+
* `shingleOverlap` uses 8-word shingles, so ONE substitution breaks eight
|
|
44
|
+
* shingles. On a one-sentence candidate (~10 shingles) that is already a
|
|
45
|
+
* 45-point drop and no paraphrase can reach 70 %; on rule-body-sized text
|
|
46
|
+
* (~60 words, 56 shingles) the same edit measures 85.7 %. The detector is
|
|
47
|
+
* therefore meaningful for the corpus it will see — rule and skill bodies — and
|
|
48
|
+
* weak for one-liners. `revisit-if` candidates turn out to be short.
|
|
49
|
+
*
|
|
50
|
+
* Pinned EQUAL to {@link NEAR_DUPLICATE_THRESHOLD} rather than given its own
|
|
51
|
+
* number, and the equality is the argument: both questions are "is this text
|
|
52
|
+
* substantially the text we already have", measured on the same primitive, and
|
|
53
|
+
* two independently-tuned constants for one question is how they drift. If one
|
|
54
|
+
* moves, the reason has to cover both.
|
|
55
|
+
*/
|
|
56
|
+
export const PARAPHRASE_OVERLAP_THRESHOLD = NEAR_DUPLICATE_THRESHOLD;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The smallest measured improvement that counts as material, in percentage
|
|
60
|
+
* points.
|
|
61
|
+
*
|
|
62
|
+
* A STATED default, not a measured optimum — the honest label this repository
|
|
63
|
+
* uses for a number nobody has derived. `revisit-if` a real promotion is refused
|
|
64
|
+
* for a delta a human calls material, or admitted for one a human calls noise.
|
|
65
|
+
* It is deliberately small: the gate exists to reject ZERO, not to set a bar for
|
|
66
|
+
* ambition.
|
|
67
|
+
*/
|
|
68
|
+
export const MIN_MATERIAL_IMPROVEMENT_PERCENT = 1;
|
|
69
|
+
|
|
70
|
+
export interface NoOpVerdict {
|
|
71
|
+
readonly isNoOp: boolean;
|
|
72
|
+
/** Why, in one clause. Empty when it is not a no-op. */
|
|
73
|
+
readonly reason: string;
|
|
74
|
+
readonly overlapPercent: number;
|
|
75
|
+
/** Literal 0. This stage is deterministic; a model call here would be a defect. */
|
|
76
|
+
readonly modelCalls: 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Is this candidate a semantic no-op against the text it replaces?
|
|
81
|
+
*
|
|
82
|
+
* Two ways to be one, and the second is the one a paraphrase detector alone
|
|
83
|
+
* misses: the text barely moved, or the text moved and the measured effect did
|
|
84
|
+
* not.
|
|
85
|
+
*/
|
|
86
|
+
export function isSemanticNoOp(
|
|
87
|
+
baselineText: string,
|
|
88
|
+
candidateText: string,
|
|
89
|
+
deltaPercent: number,
|
|
90
|
+
overlapThreshold: number = PARAPHRASE_OVERLAP_THRESHOLD,
|
|
91
|
+
minDelta: number = MIN_MATERIAL_IMPROVEMENT_PERCENT,
|
|
92
|
+
): NoOpVerdict {
|
|
93
|
+
const overlapPercent = shingleOverlap(baselineText, candidateText);
|
|
94
|
+
if (overlapPercent >= overlapThreshold) {
|
|
95
|
+
return {
|
|
96
|
+
isNoOp: true,
|
|
97
|
+
reason:
|
|
98
|
+
`paraphrase-only: ${String(overlapPercent)}% shingle overlap with the text it replaces ` +
|
|
99
|
+
`(threshold ${String(overlapThreshold)}%)`,
|
|
100
|
+
overlapPercent,
|
|
101
|
+
modelCalls: 0,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (deltaPercent < minDelta) {
|
|
105
|
+
return {
|
|
106
|
+
isNoOp: true,
|
|
107
|
+
reason:
|
|
108
|
+
`no material improvement: measured delta ${String(deltaPercent)} pp is below the ` +
|
|
109
|
+
`${String(minDelta)} pp floor`,
|
|
110
|
+
overlapPercent,
|
|
111
|
+
modelCalls: 0,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return { isNoOp: false, reason: '', overlapPercent, modelCalls: 0 };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export class SemanticNoOpError extends Error {
|
|
118
|
+
readonly candidateId: string;
|
|
119
|
+
constructor(candidateId: string, reason: string) {
|
|
120
|
+
super(
|
|
121
|
+
`candidate '${candidateId}' is a semantic no-op and is refused before the cascade: ${reason}. ` +
|
|
122
|
+
'Evaluating it would spend trials to measure nothing, and promoting it would grow the ' +
|
|
123
|
+
'estate by an artefact that says what the estate already says.',
|
|
124
|
+
);
|
|
125
|
+
this.name = 'SemanticNoOpError';
|
|
126
|
+
this.candidateId = candidateId;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** @throws {SemanticNoOpError} when the candidate is a no-op. */
|
|
131
|
+
export function assertNotSemanticNoOp(candidateId: string, verdict: NoOpVerdict): void {
|
|
132
|
+
if (verdict.isNoOp) {
|
|
133
|
+
throw new SemanticNoOpError(candidateId, verdict.reason);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface NoOpScreenInput {
|
|
138
|
+
readonly id: string;
|
|
139
|
+
readonly baselineText: string;
|
|
140
|
+
readonly candidateText: string;
|
|
141
|
+
readonly deltaPercent: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface NoOpScreenResult {
|
|
145
|
+
readonly admitted: readonly string[];
|
|
146
|
+
readonly refused: readonly { readonly id: string; readonly reason: string }[];
|
|
147
|
+
/** Literal 0 — the whole point of a pre-stage is that it is cheaper than what follows. */
|
|
148
|
+
readonly modelCalls: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The pre-stage: refuse no-ops while every candidate is still `proposed`.
|
|
153
|
+
*
|
|
154
|
+
* Synchronous, and it takes TEXT rather than records on purpose — it must be
|
|
155
|
+
* callable before a candidate has any evaluation results attached, which is the
|
|
156
|
+
* whole meaning of "before the cascade".
|
|
157
|
+
*/
|
|
158
|
+
export function screenSemanticNoOps(candidates: readonly NoOpScreenInput[]): NoOpScreenResult {
|
|
159
|
+
const admitted: string[] = [];
|
|
160
|
+
const refused: { id: string; reason: string }[] = [];
|
|
161
|
+
for (const c of candidates) {
|
|
162
|
+
const verdict = isSemanticNoOp(c.baselineText, c.candidateText, c.deltaPercent);
|
|
163
|
+
if (verdict.isNoOp) refused.push({ id: c.id, reason: verdict.reason });
|
|
164
|
+
else admitted.push(c.id);
|
|
165
|
+
}
|
|
166
|
+
return { admitted, refused, modelCalls: 0 };
|
|
167
|
+
}
|
|
@@ -93,7 +93,17 @@ export function resolveSkillsRoot(workspaceRoot: string): string | null {
|
|
|
93
93
|
for (const candidate of DEFAULT_CATALOGUE_ROOTS) {
|
|
94
94
|
const abs = path.join(workspaceRoot, candidate);
|
|
95
95
|
try {
|
|
96
|
-
if (fs.existsSync(abs)
|
|
96
|
+
if (!fs.existsSync(abs) || !fs.statSync(abs).isDirectory()) continue;
|
|
97
|
+
// NON-EMPTY, and that qualifier is the whole fix. `.claude/skills`
|
|
98
|
+
// is a gitignored projection, so in a fresh worktree it EXISTS and
|
|
99
|
+
// holds nothing — and an empty root resolved as a match makes the
|
|
100
|
+
// ranker report an empty catalogue as an empty RESULT, which is the
|
|
101
|
+
// silent failure `road-to-inbox-harvest-2026-08-f-skill-selection-evidence`
|
|
102
|
+
// is about, arriving through a second door. Measured in that run: a
|
|
103
|
+
// worktree that had never run `generate-tools` ranked zero skills
|
|
104
|
+
// and exited 0 on a task that scores 47 against `src/skills`.
|
|
105
|
+
if (fs.readdirSync(abs).length === 0) continue;
|
|
106
|
+
return abs;
|
|
97
107
|
} catch {
|
|
98
108
|
// Unreadable candidate is not a match; try the next.
|
|
99
109
|
}
|