@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
|
@@ -42,6 +42,7 @@ import * as path from 'node:path';
|
|
|
42
42
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
43
43
|
|
|
44
44
|
import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
45
|
+
import { GateLedger } from './_lib/gate_ledger.js';
|
|
45
46
|
import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
|
|
46
47
|
|
|
47
48
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -292,6 +293,40 @@ function main(argv?: readonly string[]): number {
|
|
|
292
293
|
return 1;
|
|
293
294
|
}
|
|
294
295
|
const { readings, malformed } = parseStore(text);
|
|
296
|
+
|
|
297
|
+
// Per-line accounting. `malformed` is a COUNT, and a count cannot say WHICH
|
|
298
|
+
// lines were dropped — a store whose last 40 appends were malformed reads
|
|
299
|
+
// the same as one with 40 fewer readings, which is the "looked at almost
|
|
300
|
+
// nothing" case. The ledger names each dropped line.
|
|
301
|
+
const ledger = new GateLedger('check_composite_arming');
|
|
302
|
+
const storeLines = text.split('\n').map((l, i) => ({ n: i + 1, t: l.trim() })).filter((l) => l.t !== '');
|
|
303
|
+
ledger.plan(storeLines.map((l) => `line:${String(l.n)}`));
|
|
304
|
+
let parsedSeen = 0;
|
|
305
|
+
for (const l of storeLines) {
|
|
306
|
+
let ok = false;
|
|
307
|
+
try {
|
|
308
|
+
const o = JSON.parse(l.t) as { session?: unknown };
|
|
309
|
+
ok = typeof o.session === 'string' && 'composite_ms' in (o as object);
|
|
310
|
+
} catch {
|
|
311
|
+
ok = false;
|
|
312
|
+
}
|
|
313
|
+
if (ok) {
|
|
314
|
+
parsedSeen += 1;
|
|
315
|
+
ledger.complete(`line:${String(l.n)}`);
|
|
316
|
+
} else {
|
|
317
|
+
ledger.skip(`line:${String(l.n)}`, 'precondition_unmet');
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
ledger.report();
|
|
321
|
+
/* c8 ignore next 6 */
|
|
322
|
+
if (parsedSeen !== readings.length) {
|
|
323
|
+
process.stderr.write(
|
|
324
|
+
`❌ check_composite_arming: ledger counted ${String(parsedSeen)} parseable line(s) but ` +
|
|
325
|
+
`parseStore returned ${String(readings.length)} reading(s) — the accounting and the ` +
|
|
326
|
+
'parser disagree, which means one of them is wrong about what was read.\n',
|
|
327
|
+
);
|
|
328
|
+
return 2;
|
|
329
|
+
}
|
|
295
330
|
if (malformed > 0 && readings.length === 0) {
|
|
296
331
|
process.stderr.write(
|
|
297
332
|
`❌ ${path.relative(REPO_ROOT, store)}: ${String(malformed)} malformed line(s) and no usable ` +
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Every hook concern added from here on carries a recorded answer — or fails.
|
|
4
|
+
*
|
|
5
|
+
* The sibling of `check_skill_admissions.ts`, same shape and same reasons, with
|
|
6
|
+
* one structural difference that changes the mechanism rather than the policy.
|
|
7
|
+
*
|
|
8
|
+
* ## Forward-only, and why the scope is computed differently
|
|
9
|
+
*
|
|
10
|
+
* A skill is a FILE, so its gate reads `git diff --diff-filter=A` and the 299
|
|
11
|
+
* already in the tree are grandfathered by construction. A concern is a KEY
|
|
12
|
+
* INSIDE ONE FILE — `src/scripts/hook_manifest.yaml` — so a file-level diff
|
|
13
|
+
* says only "the manifest changed", which is true of every concern edit and
|
|
14
|
+
* discriminates nothing.
|
|
15
|
+
*
|
|
16
|
+
* The scope here is therefore a SET DIFFERENCE over the parsed ids: the
|
|
17
|
+
* concerns at HEAD minus the concerns at the base ref. Both sides go through
|
|
18
|
+
* the same scoped parser (`_lib/concern_estate.ts`), for the reason that module
|
|
19
|
+
* exists — two readings of one corpus is how a gate comes to compare a number
|
|
20
|
+
* against a differently-derived number.
|
|
21
|
+
*
|
|
22
|
+
* The grandfathering is identical in effect: the 55 already in the tree need no
|
|
23
|
+
* ledger row and cannot be forgotten off one.
|
|
24
|
+
*
|
|
25
|
+
* ## The questions are NOT the skill questions
|
|
26
|
+
*
|
|
27
|
+
* They are derived from `docs/contracts/hook-architecture-v1.md`, because what
|
|
28
|
+
* makes a concern risky is different from what makes a skill risky. A concern
|
|
29
|
+
* binds to a slot, on hosts that may or may not honour a deny, inside a
|
|
30
|
+
* per-event budget — and none of that has a skill analogue.
|
|
31
|
+
*
|
|
32
|
+
* ## A rejected row is first-class
|
|
33
|
+
*
|
|
34
|
+
* `decision: rejected` records a visible "no", and a rejected row naming a
|
|
35
|
+
* concern that EXISTS is itself a failure: it means the refusal was recorded
|
|
36
|
+
* and then overridden without the row being updated, which is worse than no
|
|
37
|
+
* record at all.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import * as fs from 'node:fs';
|
|
41
|
+
import * as path from 'node:path';
|
|
42
|
+
import { spawnSync } from 'node:child_process';
|
|
43
|
+
|
|
44
|
+
import { CONCERN_MANIFEST_POSIX, concernIds } from './_lib/concern_estate.js';
|
|
45
|
+
|
|
46
|
+
const REPO_ROOT = process.cwd();
|
|
47
|
+
|
|
48
|
+
export const LEDGER_REL = 'agents/decisions/concern-admissions.jsonl';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The five answers, each a non-empty sentence.
|
|
52
|
+
*
|
|
53
|
+
* Every one is a question `hook-architecture-v1.md` makes answerable and a
|
|
54
|
+
* reviewer would otherwise have to reconstruct from the manifest by hand.
|
|
55
|
+
*/
|
|
56
|
+
export const REQUIRED_ANSWERS = [
|
|
57
|
+
/** Which lifecycle slot it binds — `pre_tool_use`, `stop`, and so on. */
|
|
58
|
+
'slot',
|
|
59
|
+
/** Which hosts actually BIND it, as opposed to which declare the slot. */
|
|
60
|
+
'binding_hosts',
|
|
61
|
+
/** What it does where the host ignores a deny — the honest-coverage answer. */
|
|
62
|
+
'behaviour_where_deny_ignored',
|
|
63
|
+
/** Why an existing concern cannot carry this. */
|
|
64
|
+
'why_not_extend',
|
|
65
|
+
/** What it costs against the per-(platform,event) budget. */
|
|
66
|
+
'per_event_budget_impact',
|
|
67
|
+
] as const;
|
|
68
|
+
|
|
69
|
+
export const DECISIONS = ['admitted', 'rejected'] as const;
|
|
70
|
+
export type Decision = (typeof DECISIONS)[number];
|
|
71
|
+
|
|
72
|
+
export interface AdmissionRow {
|
|
73
|
+
concern: string;
|
|
74
|
+
decision: Decision;
|
|
75
|
+
date: string;
|
|
76
|
+
slot?: string;
|
|
77
|
+
binding_hosts?: string;
|
|
78
|
+
behaviour_where_deny_ignored?: string;
|
|
79
|
+
why_not_extend?: string;
|
|
80
|
+
per_event_budget_impact?: string;
|
|
81
|
+
/** Free-form; only meaningful on a `rejected` row. */
|
|
82
|
+
instead?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface Finding {
|
|
86
|
+
concern: string;
|
|
87
|
+
kind: 'missing_row' | 'incomplete_row' | 'rejected_but_present' | 'bad_decision' | 'duplicate_row';
|
|
88
|
+
message: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function isRow(v: unknown): v is AdmissionRow {
|
|
92
|
+
return typeof v === 'object' && v !== null && typeof (v as AdmissionRow).concern === 'string';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function readLedger(root = REPO_ROOT): AdmissionRow[] {
|
|
96
|
+
const p = path.join(root, LEDGER_REL);
|
|
97
|
+
if (!fs.existsSync(p)) {
|
|
98
|
+
// An absent ledger is not an empty corpus: it is a gate with nothing to
|
|
99
|
+
// read, and the forward-only scope means an absent ledger only matters
|
|
100
|
+
// once something has been added.
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
const out: AdmissionRow[] = [];
|
|
104
|
+
let n = 0;
|
|
105
|
+
for (const line of fs.readFileSync(p, 'utf-8').split('\n')) {
|
|
106
|
+
n += 1;
|
|
107
|
+
const t = line.trim();
|
|
108
|
+
if (t === '') continue;
|
|
109
|
+
let parsed: unknown;
|
|
110
|
+
try {
|
|
111
|
+
parsed = JSON.parse(t);
|
|
112
|
+
} catch {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`${LEDGER_REL}:${String(n)} is not valid JSON. A malformed ledger is a hard ` +
|
|
115
|
+
'failure, never a skipped line — a gate that silently drops rows admits by accident.',
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (isRow(parsed)) out.push(parsed);
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Concern ids declared at a git ref, or `null` when the manifest is unreadable there. */
|
|
124
|
+
export function concernsAt(root: string, ref: string): Set<string> | null {
|
|
125
|
+
const res = spawnSync('git', ['show', `${ref}:${CONCERN_MANIFEST_POSIX}`], {
|
|
126
|
+
cwd: root,
|
|
127
|
+
encoding: 'utf-8',
|
|
128
|
+
maxBuffer: 32 * 1024 * 1024,
|
|
129
|
+
});
|
|
130
|
+
if (res.status !== 0) return null;
|
|
131
|
+
return new Set(concernIds(res.stdout ?? ''));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** Concern ids in the working tree. */
|
|
135
|
+
export function liveConcerns(root = REPO_ROOT): Set<string> {
|
|
136
|
+
const p = path.join(root, CONCERN_MANIFEST_POSIX);
|
|
137
|
+
if (!fs.existsSync(p)) return new Set();
|
|
138
|
+
return new Set(concernIds(fs.readFileSync(p, 'utf-8')));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Concerns ADDED since `baseRef` — the forward-only scope.
|
|
143
|
+
*
|
|
144
|
+
* A set difference rather than a file diff, because a concern is a key inside
|
|
145
|
+
* one file. `null` from `concernsAt` means the manifest could not be read at
|
|
146
|
+
* the base, in which case NOTHING is treated as added: a ref that predates the
|
|
147
|
+
* file must not retroactively demand a row for all 55.
|
|
148
|
+
*/
|
|
149
|
+
export function addedConcerns(root: string, baseRef: string): string[] {
|
|
150
|
+
const base = concernsAt(root, baseRef);
|
|
151
|
+
if (base === null) return [];
|
|
152
|
+
return [...liveConcerns(root)].filter((id) => !base.has(id)).sort();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function evaluate(root = REPO_ROOT, baseRef: string | null): Finding[] {
|
|
156
|
+
const findings: Finding[] = [];
|
|
157
|
+
const rows = readLedger(root);
|
|
158
|
+
const live = liveConcerns(root);
|
|
159
|
+
|
|
160
|
+
const seen = new Map<string, number>();
|
|
161
|
+
for (const r of rows) {
|
|
162
|
+
seen.set(r.concern, (seen.get(r.concern) ?? 0) + 1);
|
|
163
|
+
if (!(DECISIONS as readonly string[]).includes(r.decision)) {
|
|
164
|
+
findings.push({
|
|
165
|
+
concern: r.concern,
|
|
166
|
+
kind: 'bad_decision',
|
|
167
|
+
message: `decision must be one of ${DECISIONS.join(' | ')}, got ${JSON.stringify(r.decision)}`,
|
|
168
|
+
});
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (r.decision === 'rejected' && live.has(r.concern)) {
|
|
172
|
+
findings.push({
|
|
173
|
+
concern: r.concern,
|
|
174
|
+
kind: 'rejected_but_present',
|
|
175
|
+
message:
|
|
176
|
+
'the ledger records a REJECTION and the concern exists in the manifest. A refusal that ' +
|
|
177
|
+
'was later overridden without updating its row is worse than no record at all.',
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
for (const [id, n] of seen) {
|
|
182
|
+
if (n > 1) {
|
|
183
|
+
findings.push({
|
|
184
|
+
concern: id,
|
|
185
|
+
kind: 'duplicate_row',
|
|
186
|
+
message: `${String(n)} rows name this concern; one decision per concern, amended in place`,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (baseRef === null) return findings;
|
|
192
|
+
|
|
193
|
+
const admitted = new Map(rows.filter((r) => r.decision === 'admitted').map((r) => [r.concern, r]));
|
|
194
|
+
for (const id of addedConcerns(root, baseRef)) {
|
|
195
|
+
const row = admitted.get(id);
|
|
196
|
+
if (row === undefined) {
|
|
197
|
+
findings.push({
|
|
198
|
+
concern: id,
|
|
199
|
+
kind: 'missing_row',
|
|
200
|
+
message: `added since ${baseRef} with no \`admitted\` row in ${LEDGER_REL}`,
|
|
201
|
+
});
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const blank = REQUIRED_ANSWERS.filter((k) => {
|
|
205
|
+
const v = row[k];
|
|
206
|
+
return typeof v !== 'string' || v.trim() === '';
|
|
207
|
+
});
|
|
208
|
+
if (blank.length > 0) {
|
|
209
|
+
findings.push({
|
|
210
|
+
concern: id,
|
|
211
|
+
kind: 'incomplete_row',
|
|
212
|
+
message: `row is missing a real answer for: ${blank.join(', ')}`,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return findings;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
// CLI
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
|
|
223
|
+
import { reportScanned } from './_lib/scan_scope.js';
|
|
224
|
+
import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
225
|
+
import * as os from 'node:os';
|
|
226
|
+
|
|
227
|
+
function resolveBase(root: string): string | null {
|
|
228
|
+
for (const ref of ['origin/main', 'main']) {
|
|
229
|
+
const r = spawnSync('git', ['rev-parse', '--verify', '--quiet', ref], { cwd: root, encoding: 'utf-8' });
|
|
230
|
+
if (r.status === 0) return ref;
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const MANIFEST = (ids: readonly string[]): string =>
|
|
236
|
+
['concerns:', ...ids.map((i) => ` ${i}:\n severity: advisory`), 'roles:', ' dev:', ''].join('\n');
|
|
237
|
+
|
|
238
|
+
const ROW = (concern: string, decision: Decision, blank?: string): string =>
|
|
239
|
+
JSON.stringify({
|
|
240
|
+
concern,
|
|
241
|
+
decision,
|
|
242
|
+
date: '2026-08-30',
|
|
243
|
+
...Object.fromEntries(REQUIRED_ANSWERS.map((k) => [k, k === blank ? '' : `a real answer for ${k}`])),
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
function selfTest(): number {
|
|
247
|
+
const roots: string[] = [];
|
|
248
|
+
const script = path.join('src', 'scripts', 'check_concern_admissions.ts');
|
|
249
|
+
|
|
250
|
+
/** A throwaway repo with a base commit and a working-tree change on top. */
|
|
251
|
+
const fixture = (opts: { base: readonly string[]; head: readonly string[]; ledger?: string }): number => {
|
|
252
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ca-selftest-'));
|
|
253
|
+
roots.push(dir);
|
|
254
|
+
const g = (...a: string[]): void => {
|
|
255
|
+
spawnSync('git', a, { cwd: dir, encoding: 'utf-8' });
|
|
256
|
+
};
|
|
257
|
+
const put = (rel: string, body: string): void => {
|
|
258
|
+
fs.mkdirSync(path.join(dir, path.dirname(rel)), { recursive: true });
|
|
259
|
+
fs.writeFileSync(path.join(dir, rel), body, 'utf-8');
|
|
260
|
+
};
|
|
261
|
+
g('init', '-q', '-b', 'main');
|
|
262
|
+
g('config', 'user.email', 'selftest@local');
|
|
263
|
+
g('config', 'user.name', 'selftest');
|
|
264
|
+
put(CONCERN_MANIFEST_POSIX, MANIFEST(opts.base));
|
|
265
|
+
put(LEDGER_REL, '');
|
|
266
|
+
g('add', '-A');
|
|
267
|
+
g('commit', '-q', '-m', 'base');
|
|
268
|
+
put(CONCERN_MANIFEST_POSIX, MANIFEST(opts.head));
|
|
269
|
+
if (opts.ledger !== undefined) put(LEDGER_REL, `${opts.ledger}\n`);
|
|
270
|
+
// repoRoot locates tsx AND resolves the relative script path, so it is
|
|
271
|
+
// THIS checkout; cwd and --root are the fixture.
|
|
272
|
+
return runGateCli(REPO_ROOT, script, ['--base', 'main', '--root', dir], dir);
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const cases: SelfTestCase[] = [
|
|
276
|
+
{
|
|
277
|
+
name: 'no concern added → accept',
|
|
278
|
+
expect: 'accept',
|
|
279
|
+
run: () => fixture({ base: ['one'], head: ['one'] }),
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
name: 'a concern added with no ledger row → reject',
|
|
283
|
+
expect: 'reject',
|
|
284
|
+
run: () => fixture({ base: ['one'], head: ['one', 'two'] }),
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
name: 'a concern added WITH a complete admitted row → accept',
|
|
288
|
+
expect: 'accept',
|
|
289
|
+
run: () => fixture({ base: ['one'], head: ['one', 'two'], ledger: ROW('two', 'admitted') }),
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
// A row that exists but answers nothing is the shape a gate is
|
|
293
|
+
// easiest to satisfy dishonestly, so it is tested explicitly.
|
|
294
|
+
name: 'an admitted row with a blank answer → reject',
|
|
295
|
+
expect: 'reject',
|
|
296
|
+
run: () =>
|
|
297
|
+
fixture({ base: ['one'], head: ['one', 'two'], ledger: ROW('two', 'admitted', 'why_not_extend') }),
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'a rejected row naming a LIVE concern → reject',
|
|
301
|
+
expect: 'reject',
|
|
302
|
+
run: () => fixture({ base: ['one', 'two'], head: ['one', 'two'], ledger: ROW('two', 'rejected') }),
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
// The grandfathering, asserted rather than assumed: pre-existing
|
|
306
|
+
// concerns must never demand a row.
|
|
307
|
+
name: 'the pre-existing set needs no rows → accept',
|
|
308
|
+
expect: 'accept',
|
|
309
|
+
run: () => fixture({ base: ['a', 'b', 'c'], head: ['a', 'b', 'c'] }),
|
|
310
|
+
},
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
return runSelfTest({ gate: 'check_concern_admissions', cases, minCases: 5, minRejectCases: 3 });
|
|
315
|
+
} finally {
|
|
316
|
+
for (const d of roots) fs.rmSync(d, { recursive: true, force: true });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function main(argv: string[] = process.argv.slice(2), rootIn = REPO_ROOT): number {
|
|
321
|
+
if (argv.includes('--self-test')) return selfTest();
|
|
322
|
+
const i = argv.indexOf('--base');
|
|
323
|
+
const j = argv.indexOf('--root');
|
|
324
|
+
const root = j >= 0 && argv[j + 1] !== undefined ? path.resolve(argv[j + 1] as string) : rootIn;
|
|
325
|
+
const baseRef = i >= 0 ? (argv[i + 1] as string) : resolveBase(root);
|
|
326
|
+
|
|
327
|
+
const rows = readLedger(root);
|
|
328
|
+
const added = baseRef === null ? [] : addedConcerns(root, baseRef);
|
|
329
|
+
reportScanned({
|
|
330
|
+
gate: 'check_concern_admissions',
|
|
331
|
+
scanned: rows.length + added.length,
|
|
332
|
+
units: 'admission row(s) + added concern(s)',
|
|
333
|
+
roots: [LEDGER_REL, CONCERN_MANIFEST_POSIX],
|
|
334
|
+
// The state this ships in: 55 concerns are grandfathered by the
|
|
335
|
+
// forward-only set-difference scope, so the first row arrives with the
|
|
336
|
+
// first new concern. `readLedger` throws on a MALFORMED ledger, so
|
|
337
|
+
// "moved" and "empty" stay different verdicts.
|
|
338
|
+
allowEmpty:
|
|
339
|
+
'EMPTY_VALID: no concern has been admitted or refused through this ledger yet — the ' +
|
|
340
|
+
'pre-existing 55 are grandfathered by the forward-only set-difference scope, and a ' +
|
|
341
|
+
'malformed ledger is a separate hard error in readLedger()',
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const findings = evaluate(root, baseRef);
|
|
345
|
+
if (baseRef === null) {
|
|
346
|
+
process.stdout.write(
|
|
347
|
+
' ⏭️ no base ref resolved — the added-concern scope could not be computed; ' +
|
|
348
|
+
'ledger consistency was still checked\n',
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
if (findings.length === 0) {
|
|
352
|
+
process.stdout.write(
|
|
353
|
+
`✅ check_concern_admissions: ${String(added.length)} concern(s) added since ` +
|
|
354
|
+
`${baseRef ?? '<no base>'}, each carrying a recorded answer.\n`,
|
|
355
|
+
);
|
|
356
|
+
return 0;
|
|
357
|
+
}
|
|
358
|
+
process.stderr.write(`❌ check_concern_admissions: ${String(findings.length)} finding(s):\n`);
|
|
359
|
+
for (const f of findings) process.stderr.write(` 🔴 ${f.concern} [${f.kind}] — ${f.message}\n`);
|
|
360
|
+
return 1;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (process.argv[1] !== undefined && process.argv[1].includes('check_concern_admissions')) {
|
|
364
|
+
process.exit(main());
|
|
365
|
+
}
|
|
@@ -852,6 +852,34 @@ function main(argv: string[]): number {
|
|
|
852
852
|
}
|
|
853
853
|
const base = JSON.parse(fs.readFileSync(BASELINE, 'utf-8')).summary as Summary;
|
|
854
854
|
const regressions: string[] = [];
|
|
855
|
+
|
|
856
|
+
// `undeclared` is the only counter here that is a TRUE shrink-only
|
|
857
|
+
// ratchet, and the asymmetry is worth stating because the two below it
|
|
858
|
+
// are not.
|
|
859
|
+
//
|
|
860
|
+
// A rule with no declaration has no carrier, so it can contribute to
|
|
861
|
+
// neither `frequency_gap` nor `local_only`. DECLARING one truthfully can
|
|
862
|
+
// therefore only RAISE both — the gap and the taskfile-only reach were
|
|
863
|
+
// always there, and the declaration is what made them computable. Both
|
|
864
|
+
// checks compare a number against a baseline taken when the rule was
|
|
865
|
+
// invisible, so an honest declaring change reds them by construction.
|
|
866
|
+
//
|
|
867
|
+
// Measured 2026-08-27, landing 14 declarations from
|
|
868
|
+
// `road-to-undeclared-obligation-disposition` Phase 1.3:
|
|
869
|
+
// `frequency gaps rose: 9 → 14` and `validators fell back to
|
|
870
|
+
// taskfile-only: 0 → 3`. Nothing fell back and no carrier fired less
|
|
871
|
+
// often. Both readings were new visibility.
|
|
872
|
+
//
|
|
873
|
+
// The sanctioned response is the one the failure message already names —
|
|
874
|
+
// regenerate the baseline — and the obligation this comment adds is that
|
|
875
|
+
// a change doing so SAYS WHY, because a regenerated baseline and a
|
|
876
|
+
// hidden regression look identical in a diff.
|
|
877
|
+
if (summary.undeclared > (base.undeclared ?? Number.POSITIVE_INFINITY)) {
|
|
878
|
+
regressions.push(
|
|
879
|
+
`undeclared rules rose: ${base.undeclared} → ${summary.undeclared} ` +
|
|
880
|
+
`(a rule lost its enforced_by, or a new rule landed without one)`,
|
|
881
|
+
);
|
|
882
|
+
}
|
|
855
883
|
if (summary.blocking < base.blocking) {
|
|
856
884
|
regressions.push(`blocking coverage fell: ${base.blocking} → ${summary.blocking}`);
|
|
857
885
|
}
|