@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,383 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Which gate-shaped task targets can CI actually reach?
|
|
4
|
+
*
|
|
5
|
+
* A gate nobody invokes is not a gate. It can be written, registered,
|
|
6
|
+
* documented and red for months while every pipeline stays green — which is
|
|
7
|
+
* exactly what happened to `lint_positioning`, whose closing roadmap step
|
|
8
|
+
* recorded CI wiring that never existed.
|
|
9
|
+
*
|
|
10
|
+
* ## What "reachable" means here
|
|
11
|
+
*
|
|
12
|
+
* A target is reachable when it is in the transitive closure of `task ci`, or
|
|
13
|
+
* when a workflow under `.github/workflows/` invokes it directly. Both halves
|
|
14
|
+
* are needed and neither is sufficient: a workflow-only target never runs in a
|
|
15
|
+
* local `task ci`, and a `task ci`-only target never runs on a PR that skips
|
|
16
|
+
* that job.
|
|
17
|
+
*
|
|
18
|
+
* ## What "gate-shaped" means, and why the predicate is deliberately loose
|
|
19
|
+
*
|
|
20
|
+
* A target whose command runs a `check_*` / `lint_*` / `verify_*` script, or
|
|
21
|
+
* whose name starts with `check-` / `lint-` / `verify-`. Loose on purpose: the
|
|
22
|
+
* cost of a false positive is one classified row saying "variant of X", and the
|
|
23
|
+
* cost of a false negative is precisely the silence this script exists to end.
|
|
24
|
+
*
|
|
25
|
+
* ## Stability
|
|
26
|
+
*
|
|
27
|
+
* Everything is sorted and the parse is line-based over committed files, so two
|
|
28
|
+
* runs on one tree print the same set. That is asserted rather than assumed —
|
|
29
|
+
* the 1.1 verify line asks for it.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as path from 'node:path';
|
|
34
|
+
|
|
35
|
+
import * as os from 'node:os';
|
|
36
|
+
|
|
37
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
38
|
+
import { runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
39
|
+
|
|
40
|
+
const REPO_ROOT = process.cwd();
|
|
41
|
+
const TASKFILES_DIR = 'taskfiles';
|
|
42
|
+
const ROOT_TASKFILE = 'Taskfile.yml';
|
|
43
|
+
const WORKFLOWS_DIR = '.github/workflows';
|
|
44
|
+
|
|
45
|
+
/** ` <name>:` at two-space indent inside a `tasks:` map — one target. */
|
|
46
|
+
const TARGET_DECL = /^ {2}([a-z_][a-z0-9:_-]*):\s*$/;
|
|
47
|
+
/** `- task: <name>` — a dependency edge. */
|
|
48
|
+
const TASK_EDGE = /^\s*-\s*task:\s*([a-z_][a-z0-9:_-]*)\s*$/;
|
|
49
|
+
/** `defer: { task: <name> }` — also an edge. */
|
|
50
|
+
const DEFER_EDGE = /defer:\s*\{\s*task:\s*([a-z_][a-z0-9:_-]*)\s*\}/;
|
|
51
|
+
/**
|
|
52
|
+
* `deps: [a, b]` — a THIRD edge kind, and one it is easy to miss.
|
|
53
|
+
*
|
|
54
|
+
* Missing it does not merely undercount: it reports a target as unreachable
|
|
55
|
+
* when CI does run it, which is the one error this script must not make. Found
|
|
56
|
+
* by the count disagreeing with the roadmap's own two-command reading.
|
|
57
|
+
*/
|
|
58
|
+
const DEPS_EDGE = /^\s*deps:\s*\[([^\]]*)\]/;
|
|
59
|
+
/** `task <name>` inside a workflow `run:` line. */
|
|
60
|
+
const WORKFLOW_CALL = /\btask\s+([a-z_][a-z0-9:_-]*)/g;
|
|
61
|
+
|
|
62
|
+
/** A target is gate-shaped by NAME or by the script its command runs. */
|
|
63
|
+
const GATE_NAME = /^(check|lint|verify)[-:]/;
|
|
64
|
+
const GATE_CMD = /\b(check|lint|verify)_[a-z0-9_]+/;
|
|
65
|
+
|
|
66
|
+
export interface TargetDef {
|
|
67
|
+
name: string;
|
|
68
|
+
/** Targets it depends on. */
|
|
69
|
+
edges: string[];
|
|
70
|
+
/** Raw command lines, for the gate-shape predicate. */
|
|
71
|
+
cmds: string[];
|
|
72
|
+
/** Which file declared it. */
|
|
73
|
+
file: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function taskfilePaths(root: string): string[] {
|
|
77
|
+
const out = [path.join(root, ROOT_TASKFILE)];
|
|
78
|
+
const dir = path.join(root, TASKFILES_DIR);
|
|
79
|
+
if (fs.existsSync(dir)) {
|
|
80
|
+
for (const f of fs.readdirSync(dir).sort()) {
|
|
81
|
+
if (f.endsWith('.yml') || f.endsWith('.yaml')) out.push(path.join(dir, f));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out.filter((p) => fs.existsSync(p));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse targets and their edges.
|
|
89
|
+
*
|
|
90
|
+
* A hand parse rather than a YAML load, deliberately: `task` merges several
|
|
91
|
+
* files into one namespace and the includes carry prefixes, so a structural
|
|
92
|
+
* load would have to reimplement `task`'s own resolution to be more correct
|
|
93
|
+
* than this — and would still be a second implementation of it. Line-based
|
|
94
|
+
* keeps the failure mode legible: a target this misses is absent from BOTH
|
|
95
|
+
* sides of the diff, so it cannot create a false unreachable.
|
|
96
|
+
*/
|
|
97
|
+
export function parseTargets(root = REPO_ROOT): Map<string, TargetDef> {
|
|
98
|
+
const defs = new Map<string, TargetDef>();
|
|
99
|
+
for (const file of taskfilePaths(root)) {
|
|
100
|
+
const rel = path.relative(root, file);
|
|
101
|
+
let current: TargetDef | null = null;
|
|
102
|
+
for (const line of fs.readFileSync(file, 'utf-8').split('\n')) {
|
|
103
|
+
const decl = TARGET_DECL.exec(line);
|
|
104
|
+
if (decl !== null) {
|
|
105
|
+
current = { name: decl[1] as string, edges: [], cmds: [], file: rel };
|
|
106
|
+
// Later files win, matching `task`'s own override order.
|
|
107
|
+
defs.set(current.name, current);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (current === null) continue;
|
|
111
|
+
// A column-0 key ends the tasks block.
|
|
112
|
+
if (/^[a-z_]/.test(line)) {
|
|
113
|
+
current = null;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const deps = DEPS_EDGE.exec(line);
|
|
117
|
+
if (deps !== null) {
|
|
118
|
+
for (const d of (deps[1] as string).split(',')) {
|
|
119
|
+
const t = d.trim().replace(/^["']|["']$/g, '');
|
|
120
|
+
if (t !== '') current.edges.push(t);
|
|
121
|
+
}
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const edge = TASK_EDGE.exec(line) ?? DEFER_EDGE.exec(line);
|
|
125
|
+
if (edge !== null) current.edges.push(edge[1] as string);
|
|
126
|
+
else current.cmds.push(line);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return defs;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Transitive closure from a set of roots, following `task:` edges. */
|
|
133
|
+
export function closure(defs: Map<string, TargetDef>, roots: readonly string[]): Set<string> {
|
|
134
|
+
const seen = new Set<string>();
|
|
135
|
+
const stack = [...roots];
|
|
136
|
+
while (stack.length > 0) {
|
|
137
|
+
const n = stack.pop() as string;
|
|
138
|
+
if (seen.has(n)) continue;
|
|
139
|
+
seen.add(n);
|
|
140
|
+
for (const e of defs.get(n)?.edges ?? []) if (!seen.has(e)) stack.push(e);
|
|
141
|
+
}
|
|
142
|
+
return seen;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Every `task <name>` a workflow invokes. */
|
|
146
|
+
export function workflowCalls(root = REPO_ROOT): Set<string> {
|
|
147
|
+
const out = new Set<string>();
|
|
148
|
+
const dir = path.join(root, WORKFLOWS_DIR);
|
|
149
|
+
if (!fs.existsSync(dir)) return out;
|
|
150
|
+
for (const f of fs.readdirSync(dir).sort()) {
|
|
151
|
+
if (!f.endsWith('.yml') && !f.endsWith('.yaml')) continue;
|
|
152
|
+
const text = fs.readFileSync(path.join(dir, f), 'utf-8');
|
|
153
|
+
for (const m of text.matchAll(WORKFLOW_CALL)) out.add(m[1] as string);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Every workflow file's text, concatenated — for direct-script detection. */
|
|
159
|
+
function workflowSources(root: string): string {
|
|
160
|
+
const dir = path.join(root, WORKFLOWS_DIR);
|
|
161
|
+
if (!fs.existsSync(dir)) return '';
|
|
162
|
+
return fs
|
|
163
|
+
.readdirSync(dir)
|
|
164
|
+
.filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'))
|
|
165
|
+
.sort()
|
|
166
|
+
.map((f) => fs.readFileSync(path.join(dir, f), 'utf-8'))
|
|
167
|
+
.join('\n');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function isGateShaped(d: TargetDef): boolean {
|
|
171
|
+
if (GATE_NAME.test(d.name)) return true;
|
|
172
|
+
return d.cmds.some((c) => GATE_CMD.test(c));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface Reachability {
|
|
176
|
+
/** Gate-shaped targets reachable from `task ci` or a `task <name>` workflow call. */
|
|
177
|
+
reachable: string[];
|
|
178
|
+
/**
|
|
179
|
+
* Target unwired, but the SCRIPT it runs is invoked directly by a workflow.
|
|
180
|
+
*
|
|
181
|
+
* This distinction is the difference between "this gate does not run" and
|
|
182
|
+
* "this convenience alias is not wired", and conflating them overstates the
|
|
183
|
+
* hole by a factor of two on this tree. A workflow step that calls
|
|
184
|
+
* `./scripts-run src/scripts/foo` runs the gate whether or not any task
|
|
185
|
+
* target points at it — the target is then a local ergonomic, not a hole.
|
|
186
|
+
*/
|
|
187
|
+
scriptInWorkflow: string[];
|
|
188
|
+
/** Neither the target nor its script is reached. THE SET THIS EXISTS FOR. */
|
|
189
|
+
unreachable: string[];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** The script a target runs, as a repo-relative path, or `null`. */
|
|
193
|
+
export function scriptOf(d: TargetDef): string | null {
|
|
194
|
+
const m = d.cmds.join(' ').match(/src\/scripts\/[a-z0-9_/]+/);
|
|
195
|
+
return m === null ? null : m[0];
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function analyse(root = REPO_ROOT): Reachability {
|
|
199
|
+
const defs = parseTargets(root);
|
|
200
|
+
const fromCi = closure(defs, ['ci']);
|
|
201
|
+
const fromWorkflows = workflowCalls(root);
|
|
202
|
+
// A workflow may call a target that itself has dependencies.
|
|
203
|
+
const viaWorkflows = closure(defs, [...fromWorkflows].filter((n) => defs.has(n)));
|
|
204
|
+
|
|
205
|
+
const workflowText = workflowSources(root);
|
|
206
|
+
const reachable: string[] = [];
|
|
207
|
+
const scriptInWorkflow: string[] = [];
|
|
208
|
+
const unreachable: string[] = [];
|
|
209
|
+
for (const [name, d] of [...defs].sort(([a], [b]) => a.localeCompare(b))) {
|
|
210
|
+
if (!isGateShaped(d)) continue;
|
|
211
|
+
if (fromCi.has(name) || viaWorkflows.has(name)) {
|
|
212
|
+
reachable.push(name);
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const script = scriptOf(d);
|
|
216
|
+
if (script !== null && workflowText.includes(script)) scriptInWorkflow.push(name);
|
|
217
|
+
else unreachable.push(name);
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
reachable: reachable.sort(),
|
|
221
|
+
scriptInWorkflow: scriptInWorkflow.sort(),
|
|
222
|
+
unreachable: unreachable.sort(),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export const EXEMPTIONS_REL = 'src/config/gate-reachability-exemptions.json';
|
|
227
|
+
|
|
228
|
+
/** Targets recorded as deliberately unreachable, id → reason. */
|
|
229
|
+
export function readExemptions(root = REPO_ROOT): Map<string, string> {
|
|
230
|
+
const p = path.join(root, EXEMPTIONS_REL);
|
|
231
|
+
if (!fs.existsSync(p)) return new Map();
|
|
232
|
+
const doc = JSON.parse(fs.readFileSync(p, 'utf-8')) as { exempt?: Record<string, string> };
|
|
233
|
+
return new Map(Object.entries(doc.exempt ?? {}));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface GateVerdict {
|
|
237
|
+
/** Unreachable and NOT recorded — the failure. */
|
|
238
|
+
unreasoned: string[];
|
|
239
|
+
/** Recorded exemptions that are no longer unreachable — stale rows. */
|
|
240
|
+
stale: string[];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The gate verdict.
|
|
245
|
+
*
|
|
246
|
+
* Both directions, because a one-way check rots. An unreachable target with no
|
|
247
|
+
* row is the defect this roadmap is about; a row for a target that is now
|
|
248
|
+
* reachable is an exemption nobody withdrew, and a registry full of those stops
|
|
249
|
+
* being read.
|
|
250
|
+
*/
|
|
251
|
+
export function gateVerdict(root = REPO_ROOT): GateVerdict {
|
|
252
|
+
const r = analyse(root);
|
|
253
|
+
const exempt = readExemptions(root);
|
|
254
|
+
const unreachable = new Set(r.unreachable);
|
|
255
|
+
return {
|
|
256
|
+
unreasoned: r.unreachable.filter((n) => !exempt.has(n)).sort(),
|
|
257
|
+
stale: [...exempt.keys()].filter((n) => !unreachable.has(n)).sort(),
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function runGate(root: string): number {
|
|
262
|
+
const v = gateVerdict(root);
|
|
263
|
+
const exempt = readExemptions(root);
|
|
264
|
+
reportScanned({
|
|
265
|
+
gate: 'check_gate_reachability',
|
|
266
|
+
scanned: exempt.size + analyse(root).unreachable.length,
|
|
267
|
+
units: 'exemption row(s) + unreachable target(s)',
|
|
268
|
+
roots: [EXEMPTIONS_REL, ROOT_TASKFILE, TASKFILES_DIR],
|
|
269
|
+
});
|
|
270
|
+
if (v.unreasoned.length === 0 && v.stale.length === 0) {
|
|
271
|
+
process.stdout.write(
|
|
272
|
+
`✅ check_gate_reachability: every unreachable gate target carries a recorded reason ` +
|
|
273
|
+
`(${String(exempt.size)} exempt).\n`,
|
|
274
|
+
);
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
for (const n of v.unreasoned) {
|
|
278
|
+
process.stderr.write(
|
|
279
|
+
`❌ ${n} is gate-shaped, unreachable from \`task ci\` and every workflow, and carries ` +
|
|
280
|
+
`no row in ${EXEMPTIONS_REL}. Wire it, or record why it is manual AND what would make it run.\n`,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
for (const n of v.stale) {
|
|
284
|
+
process.stderr.write(
|
|
285
|
+
`❌ ${n} is exempt in ${EXEMPTIONS_REL} but is now reachable. Remove the row — an ` +
|
|
286
|
+
'exemption nobody withdrew is how a registry stops being read.\n',
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
return 1;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* The self-test builds throwaway trees rather than touching this one, so both
|
|
294
|
+
* directions are proven without a canary that has to be removed again.
|
|
295
|
+
*/
|
|
296
|
+
function selfTest(): number {
|
|
297
|
+
const roots: string[] = [];
|
|
298
|
+
const fixture = (opts: { target: string; wired: boolean; exempt: Record<string, string> }): number => {
|
|
299
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gr-selftest-'));
|
|
300
|
+
roots.push(dir);
|
|
301
|
+
fs.mkdirSync(path.join(dir, TASKFILES_DIR), { recursive: true });
|
|
302
|
+
fs.mkdirSync(path.join(dir, 'src', 'config'), { recursive: true });
|
|
303
|
+
fs.mkdirSync(path.join(dir, WORKFLOWS_DIR), { recursive: true });
|
|
304
|
+
fs.writeFileSync(
|
|
305
|
+
path.join(dir, ROOT_TASKFILE),
|
|
306
|
+
['tasks:', ' ci:', ' cmds:', ...(opts.wired ? [` - task: ${opts.target}`] : [])].join('\n'),
|
|
307
|
+
'utf-8',
|
|
308
|
+
);
|
|
309
|
+
fs.writeFileSync(
|
|
310
|
+
path.join(dir, TASKFILES_DIR, 'a.yml'),
|
|
311
|
+
['tasks:', ` ${opts.target}:`, ' cmd: ./scripts-run src/scripts/check_thing'].join('\n'),
|
|
312
|
+
'utf-8',
|
|
313
|
+
);
|
|
314
|
+
fs.writeFileSync(
|
|
315
|
+
path.join(dir, EXEMPTIONS_REL),
|
|
316
|
+
JSON.stringify({ exempt: opts.exempt }, null, 2),
|
|
317
|
+
'utf-8',
|
|
318
|
+
);
|
|
319
|
+
const v = gateVerdict(dir);
|
|
320
|
+
return v.unreasoned.length === 0 && v.stale.length === 0 ? 0 : 1;
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const cases: SelfTestCase[] = [
|
|
324
|
+
{
|
|
325
|
+
name: 'a wired gate target → accept',
|
|
326
|
+
expect: 'accept',
|
|
327
|
+
run: () => fixture({ target: 'check-x', wired: true, exempt: {} }),
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
name: 'an unreachable gate target with no row → reject',
|
|
331
|
+
expect: 'reject',
|
|
332
|
+
run: () => fixture({ target: 'check-x', wired: false, exempt: {} }),
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
name: 'an unreachable gate target WITH a row → accept',
|
|
336
|
+
expect: 'accept',
|
|
337
|
+
run: () => fixture({ target: 'check-x', wired: false, exempt: { 'check-x': 'a stated reason' } }),
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
// The other direction. Without it a registry accumulates rows for
|
|
341
|
+
// targets that were wired long ago, and stops being read.
|
|
342
|
+
name: 'a row for a target that IS reachable → reject (stale exemption)',
|
|
343
|
+
expect: 'reject',
|
|
344
|
+
run: () => fixture({ target: 'check-x', wired: true, exempt: { 'check-x': 'stale' } }),
|
|
345
|
+
},
|
|
346
|
+
];
|
|
347
|
+
try {
|
|
348
|
+
return runSelfTest({ gate: 'check_gate_reachability', cases, minCases: 4, minRejectCases: 2 });
|
|
349
|
+
} finally {
|
|
350
|
+
for (const d of roots) fs.rmSync(d, { recursive: true, force: true });
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function main(argv: string[] = process.argv.slice(2), root = REPO_ROOT): number {
|
|
355
|
+
if (argv.includes('--self-test')) return selfTest();
|
|
356
|
+
if (argv.includes('--gate')) return runGate(root);
|
|
357
|
+
const r = analyse(root);
|
|
358
|
+
if (argv.includes('--json')) {
|
|
359
|
+
process.stdout.write(`${JSON.stringify(r, null, 2)}\n`);
|
|
360
|
+
return 0;
|
|
361
|
+
}
|
|
362
|
+
// Emitted on the DEFAULT invocation too, not only under `--gate`: the
|
|
363
|
+
// coverage gate reads a bare run, and a gate that reports what it inspected
|
|
364
|
+
// only in one mode is a gate that reports nothing in the other.
|
|
365
|
+
reportScanned({
|
|
366
|
+
gate: 'check_gate_reachability',
|
|
367
|
+
scanned: readExemptions(root).size + r.unreachable.length,
|
|
368
|
+
units: 'exemption row(s) + unreachable target(s)',
|
|
369
|
+
roots: [EXEMPTIONS_REL, ROOT_TASKFILE, TASKFILES_DIR],
|
|
370
|
+
});
|
|
371
|
+
const total = r.reachable.length + r.scriptInWorkflow.length + r.unreachable.length;
|
|
372
|
+
process.stdout.write(
|
|
373
|
+
`gate-shaped targets: ${String(total)} · target-reachable ${String(r.reachable.length)} · ` +
|
|
374
|
+
`script-runs-in-workflow ${String(r.scriptInWorkflow.length)} · ` +
|
|
375
|
+
`UNREACHABLE ${String(r.unreachable.length)}\n`,
|
|
376
|
+
);
|
|
377
|
+
for (const n of r.unreachable) process.stdout.write(` · ${n}\n`);
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (process.argv[1] !== undefined && process.argv[1].includes('check_gate_reachability')) {
|
|
382
|
+
process.exit(main());
|
|
383
|
+
}
|
|
@@ -16,8 +16,13 @@ import * as path from 'node:path';
|
|
|
16
16
|
|
|
17
17
|
import { parse as parseYaml } from 'yaml';
|
|
18
18
|
|
|
19
|
+
import { GateLedger } from './_lib/gate_ledger.js';
|
|
20
|
+
import { runGateCli, runSelfTest } from './_lib/gate_self_test.js';
|
|
21
|
+
import { HOST_SURFACES, measureReach } from './_lib/host_projection_reach.js';
|
|
19
22
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
20
23
|
|
|
24
|
+
const REPO_ROOT = path.resolve(path.dirname(new URL(import.meta.url).pathname), '..', '..');
|
|
25
|
+
|
|
21
26
|
/** @returns how many skill directories were examined. */
|
|
22
27
|
export function check_claude_skills(root: string, errors: string[]): number {
|
|
23
28
|
const dir = path.join(root, '.claude', 'skills');
|
|
@@ -84,11 +89,110 @@ export function run(root: string): string[] {
|
|
|
84
89
|
return errors;
|
|
85
90
|
}
|
|
86
91
|
|
|
92
|
+
/**
|
|
93
|
+
* `--reach`: per-host projection reach, with a NAMED reason for every host that
|
|
94
|
+
* carries nothing (road-to-skill-ecosystem-runtime-enforcement Phase 3 Step 1).
|
|
95
|
+
*
|
|
96
|
+
* The shape checks above answer "is what exists well-formed". This answers "does
|
|
97
|
+
* anything exist, and if not, is the tool absent or the projection dead" — two
|
|
98
|
+
* findings the shape checks report as the same green, because a checker that
|
|
99
|
+
* returns early on a missing tree cannot distinguish them.
|
|
100
|
+
*
|
|
101
|
+
* A dead projection for a PRESENT tool fails. An absent tool is a ledger SKIP
|
|
102
|
+
* with its detection signals named, never a silent zero.
|
|
103
|
+
*/
|
|
104
|
+
export function runReach(root: string): { failures: string[]; scanned: number } {
|
|
105
|
+
const ledger = new GateLedger('check_host_loadability:reach');
|
|
106
|
+
ledger.plan(HOST_SURFACES.map((s) => s.id));
|
|
107
|
+
const failures: string[] = [];
|
|
108
|
+
for (const r of measureReach(root)) {
|
|
109
|
+
if (r.status === 'ok') {
|
|
110
|
+
ledger.complete(r.id);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (r.status === 'skipped-tool-absent') {
|
|
114
|
+
// `precondition_unmet` rather than a new code: the closed union in
|
|
115
|
+
// `_lib/gate_ledger.ts` is the audit surface, and an absent host
|
|
116
|
+
// tool IS a precondition that settled the verdict before the
|
|
117
|
+
// projection could be inspected. Widening the union for one caller
|
|
118
|
+
// would make the ledger's vocabulary grow per gate, which is the
|
|
119
|
+
// property that keeps `SKIP_REASON_MESSAGE` readable.
|
|
120
|
+
ledger.skip(r.id, 'precondition_unmet');
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
ledger.fail(r.id, r.reason);
|
|
124
|
+
failures.push(`${r.id}: ${r.reason}`);
|
|
125
|
+
}
|
|
126
|
+
ledger.report();
|
|
127
|
+
return { failures, scanned: HOST_SURFACES.length };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Self-test — proof that the reach mode's REJECTIONS still fire.
|
|
133
|
+
*
|
|
134
|
+
* Required by the `gate-self-test:registered-non-adopters` ratchet, and worth
|
|
135
|
+
* having independently: an enforced `scanned:` floor proves the gate READ
|
|
136
|
+
* something, and only a self-test proves the reading changes the verdict.
|
|
137
|
+
*
|
|
138
|
+
* **One case is deliberately absent and the reason is a real limit.** The
|
|
139
|
+
* verdict this mode exists for — an INSTALLED tool whose projection directory
|
|
140
|
+
* is empty — cannot be built from a fixture root, because presence is read from
|
|
141
|
+
* the machine (`PATH` and `$HOME`), not from the tree under test. A fixture can
|
|
142
|
+
* make a projection empty; it cannot make a tool installed. The rejecting case
|
|
143
|
+
* below is therefore the dead-scope one, and the discriminating half rests on
|
|
144
|
+
* the live measurement, which reports every surface with its own verdict.
|
|
145
|
+
*/
|
|
146
|
+
function reachSelfTest(): number {
|
|
147
|
+
const tmp = fs.mkdtempSync(path.join(REPO_ROOT, '.host-reach-selftest-'));
|
|
148
|
+
const invoke = (dir: string): number =>
|
|
149
|
+
runGateCli(
|
|
150
|
+
REPO_ROOT,
|
|
151
|
+
'src/scripts/check_host_loadability.ts',
|
|
152
|
+
['--reach', '--root', dir],
|
|
153
|
+
REPO_ROOT,
|
|
154
|
+
);
|
|
155
|
+
try {
|
|
156
|
+
return runSelfTest({
|
|
157
|
+
gate: 'check_host_loadability',
|
|
158
|
+
minCases: 2,
|
|
159
|
+
minRejectCases: 1,
|
|
160
|
+
cases: [
|
|
161
|
+
{
|
|
162
|
+
name: 'a root carrying no host projection at all is REFUSED, never passed',
|
|
163
|
+
expect: 'reject',
|
|
164
|
+
run: () => invoke(tmp),
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'this repository accounts for every host surface',
|
|
168
|
+
expect: 'accept',
|
|
169
|
+
run: () => invoke(REPO_ROOT),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
} finally {
|
|
174
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
87
178
|
const isMain = process.argv[1] !== undefined
|
|
88
179
|
&& path.resolve(process.argv[1]) === path.resolve(new URL(import.meta.url).pathname);
|
|
89
180
|
if (isMain) {
|
|
90
181
|
const rootIdx = process.argv.indexOf('--root');
|
|
91
182
|
const root = rootIdx !== -1 ? process.argv[rootIdx + 1] ?? '.' : '.';
|
|
183
|
+
if (process.argv.includes('--self-test')) {
|
|
184
|
+
process.exit(reachSelfTest());
|
|
185
|
+
}
|
|
186
|
+
if (process.argv.includes('--reach')) {
|
|
187
|
+
const { failures, scanned } = runReach(root);
|
|
188
|
+
process.stdout.write(`scanned: ${String(scanned)}\n`);
|
|
189
|
+
if (failures.length > 0) {
|
|
190
|
+
for (const f of failures) process.stderr.write(`❌ ${f}\n`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
process.stdout.write(`✅ host projection reach: ${String(scanned)} host surface(s) accounted for\n`);
|
|
194
|
+
process.exit(0);
|
|
195
|
+
}
|
|
92
196
|
let errors: string[];
|
|
93
197
|
try {
|
|
94
198
|
errors = run(root);
|