@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
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* or merges one in the same change — or the added file carries an explicit
|
|
48
48
|
* `estate_offset_exempt:` reason in its frontmatter, which costs a visible line
|
|
49
49
|
* in the diff of the very commit that claims it. This half is diff-scoped: it
|
|
50
|
-
* reads `<base>...HEAD` over `agents/roadmaps/`, so on a branch that adds no
|
|
50
|
+
* reads `<base>...HEAD` over `agents/roadmaps/`, so on a branch that adds no code-comment-allow provenance-comment -- the path is this script's operand, not where the code came from
|
|
51
51
|
* roadmap it legitimately finds nothing to weigh.
|
|
52
52
|
*
|
|
53
53
|
* THE THREE WAYS THE ESTATE MAY LEGITIMATELY GROW
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
* estate rather than creating it, so it needs no authorisation; what the
|
|
66
66
|
* allowance does NOT cover is a `later/` file appearing from nowhere.
|
|
67
67
|
* 3. **Anything else** — `estate_growth_exempt: <reason>` added, in this change,
|
|
68
|
-
* to the frontmatter of any roadmap under `agents/roadmaps/`. The canonical
|
|
68
|
+
* to the frontmatter of any roadmap under `agents/roadmaps/`. The canonical code-comment-allow provenance-comment -- the path is this script's operand, not where the code came from
|
|
69
69
|
* case is a blocker discovered while doing the work: `open_blockers` rises,
|
|
70
70
|
* nothing was archived, and the reason belongs next to the blocker.
|
|
71
71
|
*
|
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
* which one lied.
|
|
118
118
|
*
|
|
119
119
|
* The same function measures the BASE side, over a scratch copy of the base
|
|
120
|
-
* ref's `agents/roadmaps/` (`_lib/base_tree.ts`). Re-deriving the floor with a
|
|
120
|
+
* ref's `agents/roadmaps/` (`_lib/base_tree.ts`). Re-deriving the floor with a code-comment-allow provenance-comment -- the path is this script's operand, not where the code came from
|
|
121
121
|
* second implementation would let the two sides disagree about one tree, which
|
|
122
122
|
* is the failure this section already argues against, one level up.
|
|
123
123
|
*
|
|
@@ -143,7 +143,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
143
143
|
|
|
144
144
|
import {
|
|
145
145
|
collect,
|
|
146
|
-
|
|
146
|
+
is_unscheduled as isUnscheduled,
|
|
147
147
|
is_roadmap_candidate as isRoadmapCandidate,
|
|
148
148
|
parse_frontmatter as parseFrontmatter,
|
|
149
149
|
parse_roadmap as parseRoadmap,
|
|
@@ -153,7 +153,10 @@ import { GateLedger } from './_lib/gate_ledger.js';
|
|
|
153
153
|
import { resolveBaseRef } from './_lib/ratchet_base_ref.js';
|
|
154
154
|
import { materialiseSubtree } from './_lib/base_tree.js';
|
|
155
155
|
import { SKILLS_POSIX, measureSkillEstate } from './_lib/skill_estate.js';
|
|
156
|
+
import { CONCERN_MANIFEST_POSIX, countConcerns } from './_lib/concern_estate.js';
|
|
156
157
|
import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
158
|
+
import { countDeclaredCarriers, declaresCarrier } from './_lib/carrier_status.js';
|
|
159
|
+
import { carrierEstateCases } from './_lib/estate_carrier_cases.js';
|
|
157
160
|
|
|
158
161
|
const GATE = 'check_estate_count';
|
|
159
162
|
const BUDGET_REL = path.join('src', 'config', 'estate-count-budget.json');
|
|
@@ -190,6 +193,23 @@ export interface EstateCounts {
|
|
|
190
193
|
* "no tokens" — see `tokensExact`.
|
|
191
194
|
*/
|
|
192
195
|
skill_description_tokens: number;
|
|
196
|
+
/**
|
|
197
|
+
* Hook concerns declared in `src/scripts/hook_manifest.yaml`.
|
|
198
|
+
*
|
|
199
|
+
* A FIFTH corpus on the same machinery, and the same argument that admitted
|
|
200
|
+
* skills: the floor-from-the-base-ref work is the expensive part and should
|
|
201
|
+
* not be written a third time, and a separate ratchet is a separate place to
|
|
202
|
+
* forget.
|
|
203
|
+
*
|
|
204
|
+
* Read with the SCOPED parser in `_lib/concern_estate.ts`, not the
|
|
205
|
+
* whole-file grep the originating roadmap reproduces its series with. That
|
|
206
|
+
* grep over-counts by exactly 16 at every one of its six pins, because
|
|
207
|
+
* `roles:`, `platforms:` and `native_event_aliases:` sit at the same indent.
|
|
208
|
+
* The growth finding survives the correction — the delta is constant — but
|
|
209
|
+
* the absolute figure does not: the axis stands at 55, not 71, and a floor
|
|
210
|
+
* of 71 is one this gate's own parser could never reproduce.
|
|
211
|
+
*/
|
|
212
|
+
concern_count: number;
|
|
193
213
|
}
|
|
194
214
|
|
|
195
215
|
export type MetricName = keyof EstateCounts;
|
|
@@ -200,6 +220,7 @@ export const METRICS: readonly MetricName[] = [
|
|
|
200
220
|
'open_blockers',
|
|
201
221
|
'skill_count',
|
|
202
222
|
'skill_description_tokens',
|
|
223
|
+
'concern_count',
|
|
203
224
|
];
|
|
204
225
|
|
|
205
226
|
export interface EstateBudget {
|
|
@@ -213,6 +234,63 @@ export interface EstateBudget {
|
|
|
213
234
|
* number here is how it gets a threshold.
|
|
214
235
|
*/
|
|
215
236
|
one_in_one_out: { applies_above_active: number | null };
|
|
237
|
+
/**
|
|
238
|
+
* The capped provisional-promotion path — specified, and DECLINED.
|
|
239
|
+
*
|
|
240
|
+
* READ ITS NULLS THE OTHER WAY ROUND FROM THE KEY ABOVE. There `null` means
|
|
241
|
+
* UNCONDITIONAL; here `max_live: null` and `expires_after_days: null` mean
|
|
242
|
+
* NOT REGISTERED, PATH INACTIVE. The two keys sit a few lines apart in one
|
|
243
|
+
* file and their nulls mean opposite things, so a reader who transfers the
|
|
244
|
+
* sibling's semantics reads a declined path as an uncapped one.
|
|
245
|
+
*/
|
|
246
|
+
provisional_promotion: ProvisionalPromotion;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* The `provisional_promotion` object as the budget file carries it.
|
|
251
|
+
*
|
|
252
|
+
* `status` is optional so that a file which registered the two integers without
|
|
253
|
+
* restating a status is still readable — the integers are what activate the
|
|
254
|
+
* path, and a declination that dropped its own marker would fall to
|
|
255
|
+
* `unregistered`, which is the safe direction.
|
|
256
|
+
*/
|
|
257
|
+
export interface ProvisionalPromotion {
|
|
258
|
+
status?: string;
|
|
259
|
+
max_live: number | null;
|
|
260
|
+
expires_after_days: number | null;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Three states, and the reason there are three rather than two.
|
|
265
|
+
*
|
|
266
|
+
* The 2026-09-01 council that declined the path attached one obligation to the
|
|
267
|
+
* decline: the checker must distinguish an intentional declination from missing
|
|
268
|
+
* configuration. Two states cannot — `null` would read the same either way, and
|
|
269
|
+
* "nobody has written this yet" would be indistinguishable from "this was
|
|
270
|
+
* specified in full and refused on 2026-09-01".
|
|
271
|
+
*/
|
|
272
|
+
export type ProvisionalPromotionState = 'declined' | 'unregistered' | 'registered';
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Classify the path's state. NEVER activates it, in any state.
|
|
276
|
+
*
|
|
277
|
+
* A half-registered object — one integer, one null — throws rather than
|
|
278
|
+
* resolving to either neighbour: a cap with no expiry and an expiry with no cap
|
|
279
|
+
* are different mechanisms, and guessing which half was meant is how a bounded
|
|
280
|
+
* path becomes an unbounded one by omission.
|
|
281
|
+
*/
|
|
282
|
+
export function provisionalPromotionState(pp: ProvisionalPromotion): ProvisionalPromotionState {
|
|
283
|
+
const live = pp.max_live;
|
|
284
|
+
const days = pp.expires_after_days;
|
|
285
|
+
if (typeof live === 'number' && typeof days === 'number') return 'registered';
|
|
286
|
+
if ((live === null) !== (days === null)) {
|
|
287
|
+
throw new Error(
|
|
288
|
+
`${BUDGET_REL} "provisional_promotion" is half-registered ` +
|
|
289
|
+
`(max_live=${JSON.stringify(live)}, expires_after_days=${JSON.stringify(days)}). ` +
|
|
290
|
+
'Both integers activate the path; both null leave it inactive. One of each is neither.',
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
return pp.status === 'declined' ? 'declined' : 'unregistered';
|
|
216
294
|
}
|
|
217
295
|
|
|
218
296
|
/** One gated count that rose above the floor measured at the base ref. */
|
|
@@ -286,6 +364,15 @@ export interface EstateVerdict {
|
|
|
286
364
|
offsets: OffsetLedger | null;
|
|
287
365
|
offsetSkipReason: string | null;
|
|
288
366
|
unpaid: number;
|
|
367
|
+
/**
|
|
368
|
+
* The provisional-promotion path's state, reported and never acted on.
|
|
369
|
+
*
|
|
370
|
+
* Carried in the verdict so a `--json` consumer can tell a declined path
|
|
371
|
+
* from an unwritten one without re-reading the budget file, which is the
|
|
372
|
+
* distinction the 2026-09-01 decline was conditioned on. It contributes
|
|
373
|
+
* nothing to `withinBudget` in any state: reading is not activation.
|
|
374
|
+
*/
|
|
375
|
+
provisionalPromotion: ProvisionalPromotionState;
|
|
289
376
|
withinBudget: boolean;
|
|
290
377
|
}
|
|
291
378
|
|
|
@@ -303,6 +390,29 @@ function repoRootFrom(start: string): string {
|
|
|
303
390
|
}
|
|
304
391
|
}
|
|
305
392
|
|
|
393
|
+
/** File contents, or `null` when it is absent. Absent is a real state here. */
|
|
394
|
+
function readIfPresent(file: string): string | null {
|
|
395
|
+
try {
|
|
396
|
+
return fs.readFileSync(file, 'utf-8');
|
|
397
|
+
} catch {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Concern count at a git ref, or `null` when the manifest is unreadable there.
|
|
404
|
+
*
|
|
405
|
+
* `null` is NOT zero, and the distinction is the whole reason this returns an
|
|
406
|
+
* option. A missing manifest read as 0 makes the floor 0, which makes the
|
|
407
|
+
* ratchet inert on that path while still printing a green line — "a gate that
|
|
408
|
+
* read nothing has not passed", in this repository's own words. The caller
|
|
409
|
+
* turns `null` into a floor-skip, which this gate already treats as a failure.
|
|
410
|
+
*/
|
|
411
|
+
function concernCountAt(repoRoot: string, ref: string): number | null {
|
|
412
|
+
const res = git(['show', `${ref}:${CONCERN_MANIFEST_POSIX}`], repoRoot);
|
|
413
|
+
return res.ok ? countConcerns(res.stdout) : null;
|
|
414
|
+
}
|
|
415
|
+
|
|
306
416
|
function git(args: readonly string[], cwd: string): { ok: boolean; stdout: string } {
|
|
307
417
|
const res = spawnSync('git', [...args], { cwd, encoding: 'utf-8', maxBuffer: 32 * 1024 * 1024 });
|
|
308
418
|
return { ok: res.status === 0, stdout: res.stdout ?? '' };
|
|
@@ -328,7 +438,39 @@ function countIn(roadmapRoot: string, sub: string): number {
|
|
|
328
438
|
}
|
|
329
439
|
}
|
|
330
440
|
|
|
331
|
-
/**
|
|
441
|
+
/**
|
|
442
|
+
* Top-level roadmaps `collect()` drops for declaring `status: carrier`, added
|
|
443
|
+
* back so that FLIPPING a status is count-neutral.
|
|
444
|
+
*
|
|
445
|
+
* Measured before this: flipping one file to `carrier` moved `active_roadmaps
|
|
446
|
+
* 3 → 2` and the gate printed "estate within its ratchet", because a count
|
|
447
|
+
* below the floor is a drawdown and free. The floor is measured at the base
|
|
448
|
+
* ref, so once such a flip merges the lowered number becomes the next floor —
|
|
449
|
+
* the file cannot be flipped back without paying, and any roadmap can be
|
|
450
|
+
* laundered out of the count by adding one word.
|
|
451
|
+
*
|
|
452
|
+
* A reclassification is not a disposal, so the metric counts the file on both
|
|
453
|
+
* sides. Same argument `open_blockers` makes below for spanning `later/`.
|
|
454
|
+
* Deleting a carrier is still a shrink and still earns no offset
|
|
455
|
+
* (`classifyDiff`); adding one is growth that takes the claim path.
|
|
456
|
+
*
|
|
457
|
+
* This is therefore the one roadmap metric that does NOT equal the dashboard
|
|
458
|
+
* header, stated here rather than left to be tripped over.
|
|
459
|
+
*/
|
|
460
|
+
function countActiveCarriers(roadmapRoot: string): number {
|
|
461
|
+
return countDeclaredCarriers(roadmapRoot, isRoadmapCandidate, fs, path.join);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Roadmaps parked in `later/` whose blockers count, parsed for them.
|
|
466
|
+
*
|
|
467
|
+
* Skips a draft AND a carrier, which is the same pair `collect()` skips on the
|
|
468
|
+
* active side. It used to skip only the draft, so parking a carrier moved its
|
|
469
|
+
* blockers INTO the gated count while the identical file at the top level kept
|
|
470
|
+
* them out — a ratchet verdict that moved on a relocation, for no stated
|
|
471
|
+
* reason. Three of the four status readers learned `carrier` when the status
|
|
472
|
+
* shipped; this is the fourth.
|
|
473
|
+
*/
|
|
332
474
|
function laterRoadmaps(roadmapRoot: string): Array<{ open_blockers: readonly unknown[] }> {
|
|
333
475
|
const dir = path.join(roadmapRoot, 'later');
|
|
334
476
|
let names: string[];
|
|
@@ -344,7 +486,7 @@ function laterRoadmaps(roadmapRoot: string): Array<{ open_blockers: readonly unk
|
|
|
344
486
|
// `collect()` cannot be reused here: it filters through the same
|
|
345
487
|
// path-based predicate and would reject its own root.
|
|
346
488
|
const text = fs.readFileSync(abs, 'utf-8');
|
|
347
|
-
if (
|
|
489
|
+
if (isUnscheduled(parseFrontmatter(text))) continue;
|
|
348
490
|
const stats = parseRoadmap(abs, dir);
|
|
349
491
|
if (stats !== null) out.push(stats as unknown as { open_blockers: readonly unknown[] });
|
|
350
492
|
}
|
|
@@ -354,8 +496,11 @@ function laterRoadmaps(roadmapRoot: string): Array<{ open_blockers: readonly unk
|
|
|
354
496
|
/**
|
|
355
497
|
* Count the estate, three ways.
|
|
356
498
|
*
|
|
357
|
-
* `active_roadmaps`
|
|
358
|
-
*
|
|
499
|
+
* `active_roadmaps` is `collect()` PLUS the top-level carriers `collect()`
|
|
500
|
+
* drops, so the parser is shared with the dashboard while a status flip stays
|
|
501
|
+
* count-neutral — see `countActiveCarriers` for why that beats parity here, and
|
|
502
|
+
* for the one number on this gate that the dashboard header does not print.
|
|
503
|
+
* `later_roadmaps` is a directory listing because parked files are
|
|
359
504
|
* outside that corpus by design — filtered through the same `is_roadmap_candidate`
|
|
360
505
|
* predicate as the active side, so `later/README.md` is not a roadmap here either.
|
|
361
506
|
*
|
|
@@ -379,7 +524,7 @@ export function countEstate(repoRoot: string): EstateCounts {
|
|
|
379
524
|
rows.reduce((n, r) => n + r.open_blockers.length, 0);
|
|
380
525
|
const skills = measureSkillEstate(repoRoot);
|
|
381
526
|
return {
|
|
382
|
-
active_roadmaps: stats.length,
|
|
527
|
+
active_roadmaps: stats.length + countActiveCarriers(roadmapRoot),
|
|
383
528
|
later_roadmaps: countIn(roadmapRoot, 'later'),
|
|
384
529
|
open_blockers: openOf(stats) + openOf(laterRoadmaps(roadmapRoot)),
|
|
385
530
|
skill_count: skills.skill_count,
|
|
@@ -389,6 +534,7 @@ export function countEstate(repoRoot: string): EstateCounts {
|
|
|
389
534
|
// against a proxy one — they differ by more than the growth a ratchet
|
|
390
535
|
// is trying to catch.
|
|
391
536
|
skill_description_tokens: skills.skill_description_tokens ?? 0,
|
|
537
|
+
concern_count: countConcerns(readIfPresent(path.join(repoRoot, CONCERN_MANIFEST_POSIX)) ?? ''),
|
|
392
538
|
};
|
|
393
539
|
}
|
|
394
540
|
|
|
@@ -397,7 +543,7 @@ export function skillTokensExact(root: string): boolean {
|
|
|
397
543
|
return measureSkillEstate(root).skill_description_tokens !== null;
|
|
398
544
|
}
|
|
399
545
|
|
|
400
|
-
/** `agents/roadmaps/<name>.md` — the active top level,
|
|
546
|
+
/** `agents/roadmaps/<name>.md` — the active top level. code-comment-allow provenance-comment -- operand, not provenance */
|
|
401
547
|
function isActiveTopLevel(rel: string): boolean {
|
|
402
548
|
const norm = rel.split(path.sep).join('/');
|
|
403
549
|
if (!norm.startsWith('agents/roadmaps/') || !norm.endsWith('.md')) {
|
|
@@ -444,6 +590,9 @@ export function exemptionReason(text: string): string | null {
|
|
|
444
590
|
return reason === '' ? null : reason;
|
|
445
591
|
}
|
|
446
592
|
|
|
593
|
+
/** Re-export; `_lib/carrier_status.ts` holds the one implementation. */
|
|
594
|
+
export const isCarrierText = declaresCarrier;
|
|
595
|
+
|
|
447
596
|
/**
|
|
448
597
|
* Classify the change's effect on the active roadmap tree.
|
|
449
598
|
*
|
|
@@ -452,7 +601,17 @@ export function exemptionReason(text: string): string | null {
|
|
|
452
601
|
* `later/road-to-x.md` → `road-to-x.md` is an un-parking and counts as an
|
|
453
602
|
* addition. A top-level-to-top-level rename is neither.
|
|
454
603
|
*/
|
|
455
|
-
export function classifyDiff(
|
|
604
|
+
export function classifyDiff(
|
|
605
|
+
nameStatus: string,
|
|
606
|
+
readFile: (rel: string) => string | null,
|
|
607
|
+
/**
|
|
608
|
+
* The file's content at the BASE ref, for paths this change removed — a
|
|
609
|
+
* deleted carrier cannot be read from the working tree and its status
|
|
610
|
+
* decides whether the deletion earns an offset. Defaults to null, which
|
|
611
|
+
* reproduces the previous scoring for any caller without a pre-image.
|
|
612
|
+
*/
|
|
613
|
+
readBase: (rel: string) => string | null = () => null,
|
|
614
|
+
): OffsetLedger {
|
|
456
615
|
const added: string[] = [];
|
|
457
616
|
const offsets: string[] = [];
|
|
458
617
|
const exempt: Array<{ file: string; reason: string }> = [];
|
|
@@ -465,8 +624,10 @@ export function classifyDiff(nameStatus: string, readFile: (rel: string) => stri
|
|
|
465
624
|
const from = cols[1] ?? '';
|
|
466
625
|
const to = cols[2] ?? '';
|
|
467
626
|
if (isActiveTopLevel(from) && isDisposed(to)) {
|
|
468
|
-
|
|
469
|
-
|
|
627
|
+
if (!isCarrierText(readBase(from))) {
|
|
628
|
+
offsets.push(from);
|
|
629
|
+
if (isParked(to)) parked.push(to);
|
|
630
|
+
}
|
|
470
631
|
} else if (isDisposed(from) && isActiveTopLevel(to)) {
|
|
471
632
|
added.push(to);
|
|
472
633
|
}
|
|
@@ -477,7 +638,10 @@ export function classifyDiff(nameStatus: string, readFile: (rel: string) => stri
|
|
|
477
638
|
if (status === 'A') {
|
|
478
639
|
added.push(file);
|
|
479
640
|
} else if (status === 'D') {
|
|
480
|
-
|
|
641
|
+
// A carrier's removal is never an offset. See `readBase`.
|
|
642
|
+
if (!isCarrierText(readBase(file))) {
|
|
643
|
+
offsets.push(file);
|
|
644
|
+
}
|
|
481
645
|
}
|
|
482
646
|
}
|
|
483
647
|
for (const file of added) {
|
|
@@ -544,6 +708,18 @@ export function evaluate(
|
|
|
544
708
|
if (budget.one_in_one_out === undefined) {
|
|
545
709
|
throw new Error(`${BUDGET_REL} carries no "one_in_one_out" object.`);
|
|
546
710
|
}
|
|
711
|
+
// Same shape, same reason: an absent policy object is a could-not-run, not a
|
|
712
|
+
// pass. Here it also carries a second job — with the key required, "the path
|
|
713
|
+
// was declined on 2026-09-01" and "nobody has configured this" cannot
|
|
714
|
+
// collapse into the same reading, which is the condition the council
|
|
715
|
+
// attached to the decline.
|
|
716
|
+
if (budget.provisional_promotion === undefined) {
|
|
717
|
+
throw new Error(
|
|
718
|
+
`${BUDGET_REL} carries no "provisional_promotion" object. ` +
|
|
719
|
+
'Absent is misconfiguration, never an inactive path — a declination is recorded, not implied.',
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
const provisionalPromotion = provisionalPromotionState(budget.provisional_promotion);
|
|
547
723
|
|
|
548
724
|
const counts = countEstate(repoRoot);
|
|
549
725
|
const baseRef = opts.baseRef ?? resolveBaseRef(repoRoot);
|
|
@@ -554,6 +730,15 @@ export function evaluate(
|
|
|
554
730
|
// property, and unlike a number nobody has to remember to update it.
|
|
555
731
|
let floor: EstateCounts | null = null;
|
|
556
732
|
let floorSkipReason: string | null = null;
|
|
733
|
+
/**
|
|
734
|
+
* Does the WORKING TREE carry a manifest at all?
|
|
735
|
+
*
|
|
736
|
+
* The base-ref read only matters when it does. A repository with no manifest
|
|
737
|
+
* on either side has no concern axis to ratchet, and failing there would
|
|
738
|
+
* turn every unrelated fixture red — which is how the first version of this
|
|
739
|
+
* clause was caught.
|
|
740
|
+
*/
|
|
741
|
+
const headHasManifest = fs.existsSync(path.join(repoRoot, CONCERN_MANIFEST_POSIX));
|
|
557
742
|
/** Set when the base ref carries no `src/skills` — the skill metrics drop. */
|
|
558
743
|
let skillFloorSkipReason: string | null = null;
|
|
559
744
|
/** Set when either side's tokeniser did not resolve — that ONE metric drops. */
|
|
@@ -584,7 +769,14 @@ export function evaluate(
|
|
|
584
769
|
if (baseSkills.error !== null || baseSkills.files === 0) {
|
|
585
770
|
// Roadmap floor stands; the skill floor is stated as
|
|
586
771
|
// unavailable and its metrics are dropped from the compare.
|
|
587
|
-
|
|
772
|
+
const cf = concernCountAt(repoRoot, baseRef);
|
|
773
|
+
floor = { ...roadmapFloor, concern_count: cf ?? 0 };
|
|
774
|
+
if (cf === null && headHasManifest) {
|
|
775
|
+
floorSkipReason =
|
|
776
|
+
`could not read ${CONCERN_MANIFEST_POSIX} at ${baseRef} while HEAD ` +
|
|
777
|
+
'carries one. A floor of 0 would make the concern ratchet inert while ' +
|
|
778
|
+
'still printing green, so this fails rather than skips.';
|
|
779
|
+
}
|
|
588
780
|
skillFloorSkipReason =
|
|
589
781
|
`could not read ${SKILLS_POSIX} at ${baseRef} — ` +
|
|
590
782
|
`${baseSkills.error ?? 'no files'}`;
|
|
@@ -594,7 +786,23 @@ export function evaluate(
|
|
|
594
786
|
...roadmapFloor,
|
|
595
787
|
skill_count: s.skill_count,
|
|
596
788
|
skill_description_tokens: s.skill_description_tokens ?? 0,
|
|
789
|
+
// A SINGLE FILE, so `git show` rather than a third
|
|
790
|
+
// `materialiseSubtree` — stated because the roadmap asks
|
|
791
|
+
// which of the two this uses. Materialising a subtree to
|
|
792
|
+
// reach one known path would spend a temp tree and a
|
|
793
|
+
// recursive ls-tree on a `git cat-file` in disguise.
|
|
794
|
+
//
|
|
795
|
+
// `?? 0` never stands for "unreadable": the branch below
|
|
796
|
+
// turns that into a floor-skip, which fails. This
|
|
797
|
+
// coalesce only satisfies the type.
|
|
798
|
+
concern_count: concernCountAt(repoRoot, baseRef) ?? 0,
|
|
597
799
|
};
|
|
800
|
+
if (concernCountAt(repoRoot, baseRef) === null && headHasManifest) {
|
|
801
|
+
floorSkipReason =
|
|
802
|
+
`could not read ${CONCERN_MANIFEST_POSIX} at ${baseRef} while HEAD ` +
|
|
803
|
+
'carries one. A floor of 0 would make the concern ratchet inert while ' +
|
|
804
|
+
'still printing green, so this fails rather than skips.';
|
|
805
|
+
}
|
|
598
806
|
if (s.skill_description_tokens === null) {
|
|
599
807
|
skillTokenSkipReason =
|
|
600
808
|
`the tokeniser did not resolve at ${baseRef}; an exact reading may ` +
|
|
@@ -624,13 +832,20 @@ export function evaluate(
|
|
|
624
832
|
if (!diff.ok) {
|
|
625
833
|
offsetSkipReason = `git diff against ${baseRef} failed — one-in-one-out not evaluated`;
|
|
626
834
|
} else {
|
|
627
|
-
offsets = classifyDiff(
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
835
|
+
offsets = classifyDiff(
|
|
836
|
+
diff.stdout,
|
|
837
|
+
(rel) => {
|
|
838
|
+
try {
|
|
839
|
+
return fs.readFileSync(path.join(repoRoot, rel), 'utf-8');
|
|
840
|
+
} catch {
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
(rel) => {
|
|
845
|
+
const show = git(['show', `${baseRef}:${rel}`], repoRoot);
|
|
846
|
+
return show.ok ? show.stdout : null;
|
|
847
|
+
},
|
|
848
|
+
);
|
|
634
849
|
}
|
|
635
850
|
const patch = git(
|
|
636
851
|
['diff', '--unified=0', '--find-renames', `${baseRef}...HEAD`, '--', ROADMAPS_REL],
|
|
@@ -663,6 +878,14 @@ export function evaluate(
|
|
|
663
878
|
// claim path — a recorded reason in the diff — or it fails.
|
|
664
879
|
skill_count: 0,
|
|
665
880
|
skill_description_tokens: 0,
|
|
881
|
+
// Step 1.2: NO new allowance key. The concern axis joins `skill_count`
|
|
882
|
+
// in taking the claim path or nothing, for the reason the budget file
|
|
883
|
+
// already records for skills — an allowance reopens the gaming path the
|
|
884
|
+
// dimension exists to close. Eight concerns spread across eight events
|
|
885
|
+
// violate the existing per-event cap zero times, which is exactly why a
|
|
886
|
+
// total-growth ratchet was needed and exactly why it must not carry a
|
|
887
|
+
// per-change freebie.
|
|
888
|
+
concern_count: 0,
|
|
666
889
|
};
|
|
667
890
|
|
|
668
891
|
/** Metrics dropped from the compare, with the reason, never silently. */
|
|
@@ -707,6 +930,7 @@ export function evaluate(
|
|
|
707
930
|
offsets,
|
|
708
931
|
offsetSkipReason,
|
|
709
932
|
unpaid,
|
|
933
|
+
provisionalPromotion,
|
|
710
934
|
// No floor is a FAILURE, not a skip, and it is the one place this gate
|
|
711
935
|
// convicts on a missing input. The other halves can report "unproven" and
|
|
712
936
|
// still leave a meaningful verdict behind; the count half IS the verdict,
|
|
@@ -717,7 +941,7 @@ export function evaluate(
|
|
|
717
941
|
}
|
|
718
942
|
|
|
719
943
|
/** Floors for `--self-test`, declared here so a truncation is a visible diff. */
|
|
720
|
-
const SELF_TEST_MIN_CASES =
|
|
944
|
+
const SELF_TEST_MIN_CASES = 13;
|
|
721
945
|
const SELF_TEST_MIN_REJECT = 8;
|
|
722
946
|
|
|
723
947
|
/**
|
|
@@ -742,11 +966,32 @@ function selfTest(): number {
|
|
|
742
966
|
* the baseline with no reason" is not a state a change can reach.
|
|
743
967
|
*/
|
|
744
968
|
const budgetJson = (): string =>
|
|
745
|
-
`${JSON.stringify(
|
|
969
|
+
`${JSON.stringify(
|
|
970
|
+
{
|
|
971
|
+
one_in_one_out: { applies_above_active: null },
|
|
972
|
+
// Required since the path was specified and declined: the gate
|
|
973
|
+
// refuses a budget that carries no `provisional_promotion`, so a
|
|
974
|
+
// fixture without it exits 2 on every case rather than on the one
|
|
975
|
+
// case testing that refusal.
|
|
976
|
+
provisional_promotion: { status: 'declined', max_live: null, expires_after_days: null },
|
|
977
|
+
},
|
|
978
|
+
null,
|
|
979
|
+
4,
|
|
980
|
+
)}\n`;
|
|
746
981
|
|
|
747
982
|
const roadmap = (name: string, extra = ''): string =>
|
|
748
983
|
`# Roadmap: ${name}\n\n## Phase 1\n\n- [ ] **1.1** s\n${extra}`;
|
|
749
984
|
|
|
985
|
+
/** A `status: carrier` roadmap — counted as estate, and never an offset. */
|
|
986
|
+
const CARRIER = `---\nstatus: carrier\n---\n# Roadmap: carrier\n\n## Phase 1\n\n- [~] **1.1** s\n`;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* A `status: draft` roadmap — invisible to `collect()`, so adding one cannot
|
|
990
|
+
* move `active_roadmaps`. That is what makes it the fixture for a case that
|
|
991
|
+
* must be decided by the offset scoring and by nothing else.
|
|
992
|
+
*/
|
|
993
|
+
const DRAFT = `---\nstatus: draft\n---\n# Roadmap: draft\n\n## Phase 1\n\n- [ ] **1.1** s\n`;
|
|
994
|
+
|
|
750
995
|
/** An open blocker — no `Status: resolved` prefix, so it counts as open. */
|
|
751
996
|
const BLOCKER = '\n## Blockers\n\n### Blocker: fixture\n\n- **Status:** open\n';
|
|
752
997
|
|
|
@@ -808,6 +1053,64 @@ function selfTest(): number {
|
|
|
808
1053
|
expect: 'accept',
|
|
809
1054
|
run: () => fixture({ roadmaps: 3, base: 'main', after: () => undefined }),
|
|
810
1055
|
},
|
|
1056
|
+
{
|
|
1057
|
+
// The concern axis, both directions. Seeded into the BASE tree so
|
|
1058
|
+
// the floor is a real reading of the fixture's own manifest rather
|
|
1059
|
+
// than this repository's -- the whole point of measuring the floor
|
|
1060
|
+
// from the base ref.
|
|
1061
|
+
name: 'concern count grows above the base-tree floor → reject',
|
|
1062
|
+
expect: 'reject',
|
|
1063
|
+
run: () =>
|
|
1064
|
+
fixture({
|
|
1065
|
+
roadmaps: 3,
|
|
1066
|
+
base: 'main',
|
|
1067
|
+
before: (dir) =>
|
|
1068
|
+
write(dir, CONCERN_MANIFEST_POSIX, 'concerns:\n one:\n severity: advisory\n'),
|
|
1069
|
+
after: (dir) =>
|
|
1070
|
+
write(
|
|
1071
|
+
dir,
|
|
1072
|
+
CONCERN_MANIFEST_POSIX,
|
|
1073
|
+
'concerns:\n one:\n severity: advisory\n two:\n severity: advisory\n',
|
|
1074
|
+
),
|
|
1075
|
+
}),
|
|
1076
|
+
},
|
|
1077
|
+
{
|
|
1078
|
+
// AC-3's explicit clause, and it corrects the first implementation
|
|
1079
|
+
// of this metric: an unreadable manifest at the base ref must FAIL,
|
|
1080
|
+
// never read as 0. A floor of 0 makes the ratchet inert on that
|
|
1081
|
+
// path while still printing a green line, which is the shape this
|
|
1082
|
+
// repository calls "a gate that read nothing has not passed".
|
|
1083
|
+
name: 'base ref carries no manifest → reject (a 0 floor is not a floor)',
|
|
1084
|
+
expect: 'reject',
|
|
1085
|
+
run: () =>
|
|
1086
|
+
fixture({
|
|
1087
|
+
roadmaps: 3,
|
|
1088
|
+
base: 'main',
|
|
1089
|
+
after: (dir) =>
|
|
1090
|
+
write(dir, CONCERN_MANIFEST_POSIX, 'concerns:\n one:\n severity: advisory\n'),
|
|
1091
|
+
}),
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
// The half that proves the parser is SCOPED rather than a grep: a
|
|
1095
|
+
// top-level map gaining members at the same two-space indent is not
|
|
1096
|
+
// concern growth, and the roadmap's own reproduce command would
|
|
1097
|
+
// have counted it as such.
|
|
1098
|
+
name: 'a non-concern top-level map growing is not concern growth → accept',
|
|
1099
|
+
expect: 'accept',
|
|
1100
|
+
run: () =>
|
|
1101
|
+
fixture({
|
|
1102
|
+
roadmaps: 3,
|
|
1103
|
+
base: 'main',
|
|
1104
|
+
before: (dir) =>
|
|
1105
|
+
write(dir, CONCERN_MANIFEST_POSIX, 'concerns:\n one:\n severity: advisory\nroles:\n dev:\n'),
|
|
1106
|
+
after: (dir) =>
|
|
1107
|
+
write(
|
|
1108
|
+
dir,
|
|
1109
|
+
CONCERN_MANIFEST_POSIX,
|
|
1110
|
+
'concerns:\n one:\n severity: advisory\nroles:\n dev:\n ops:\n sre:\n',
|
|
1111
|
+
),
|
|
1112
|
+
}),
|
|
1113
|
+
},
|
|
811
1114
|
{
|
|
812
1115
|
// The floor is now exact, so this case no longer depends on anyone
|
|
813
1116
|
// having typed the right number at the base commit.
|
|
@@ -894,6 +1197,14 @@ function selfTest(): number {
|
|
|
894
1197
|
after: (dir) => write(dir, 'agents/roadmaps/later/road-to-parked.md', roadmap('P')),
|
|
895
1198
|
}),
|
|
896
1199
|
},
|
|
1200
|
+
...carrierEstateCases({
|
|
1201
|
+
fixture,
|
|
1202
|
+
write,
|
|
1203
|
+
remove: (dir, rel) => fs.rmSync(path.join(dir, rel)),
|
|
1204
|
+
roadmap,
|
|
1205
|
+
CARRIER,
|
|
1206
|
+
DRAFT,
|
|
1207
|
+
}),
|
|
897
1208
|
{
|
|
898
1209
|
name: 'a new open blocker with no claim → reject',
|
|
899
1210
|
expect: 'reject',
|
|
@@ -1019,7 +1330,7 @@ export function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
1019
1330
|
return 2;
|
|
1020
1331
|
}
|
|
1021
1332
|
|
|
1022
|
-
// A ratchet over an empty estate always passes. Move `agents/roadmaps/` and
|
|
1333
|
+
// A ratchet over an empty estate always passes. Move `agents/roadmaps/` and code-comment-allow provenance-comment -- the path is this script's operand, not where the code came from
|
|
1023
1334
|
// every count is 0, which is trivially under any baseline — exit 2 (could
|
|
1024
1335
|
// not run), never 1, which would assert the estate actually grew.
|
|
1025
1336
|
try {
|
|
@@ -1096,6 +1407,17 @@ export function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
1096
1407
|
} else if (verdict.offsetSkipReason !== null) {
|
|
1097
1408
|
process.stdout.write(` ⚠️ ${verdict.offsetSkipReason}\n`);
|
|
1098
1409
|
}
|
|
1410
|
+
// Printed unconditionally so the state is visible without `--json`. It never
|
|
1411
|
+
// changes the exit code — a declined path and a registered one both leave
|
|
1412
|
+
// the ratchet exactly as it was, and the allowance a registered path would
|
|
1413
|
+
// grant is deliberately unwired (the owner registers the numbers; wiring
|
|
1414
|
+
// what they buy is a separate, separately authorised change).
|
|
1415
|
+
process.stdout.write(
|
|
1416
|
+
` ${'provisional'.padEnd(18)} ${verdict.provisionalPromotion.padStart(5)}` +
|
|
1417
|
+
`${verdict.provisionalPromotion === 'declined' ? ' (specified and declined 2026-09-01 — path inactive by decision)' : ''}` +
|
|
1418
|
+
`${verdict.provisionalPromotion === 'unregistered' ? ' (no numbers registered — path inactive)' : ''}` +
|
|
1419
|
+
`${verdict.provisionalPromotion === 'registered' ? ' (numbers registered by the owner; this gate grants no allowance for them)' : ''}\n`,
|
|
1420
|
+
);
|
|
1099
1421
|
for (const c of verdict.claims) {
|
|
1100
1422
|
process.stdout.write(` ↑ growth claimed in ${c.file}: ${c.reason.slice(0, 120)}\n`);
|
|
1101
1423
|
}
|