@event4u/agent-config 14.12.0 → 14.13.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 +234 -0
- 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 +109 -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-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 +247 -3
- package/dist/agent-src/scripts/guarded_baseline.ts +328 -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 +400 -0
- package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
- 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 +42 -10
- 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 +57 -57
- 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 +1836 -712
- 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 +4818 -2645
- 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/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 +247 -3
- package/src/agent-src/scripts/guarded_baseline.ts +328 -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 +400 -0
- package/src/agent-src/scripts/ticket_bundles.ts +84 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
- 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 +38 -36
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +579 -63
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +37 -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 +8 -8
- 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 +126 -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 +27 -0
- package/src/scripts/_lib/activation_ladder.ts +211 -0
- package/src/scripts/_lib/activation_states.ts +88 -0
- package/src/scripts/_lib/adherence_detectors.ts +143 -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_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/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/council_settings_block.ts +6 -0
- package/src/scripts/_lib/curator_ops.ts +172 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +266 -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/eval_publication.ts +354 -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/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 +229 -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/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/prefix_stable_surfaces.ts +123 -0
- package/src/scripts/_lib/privacy_class.ts +47 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
- 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/runtime_journal.ts +1499 -0
- package/src/scripts/_lib/runtime_wiring_checks.ts +430 -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/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/disagreement_signal.ts +338 -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/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/response_record.ts +50 -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 +126 -0
- 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 +142 -1
- 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_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/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 +980 -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 +98 -11
- 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/concern_registry.ts +4 -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/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/lint_adr_sweep_routing.ts +12 -0
- package/src/scripts/lint_canonical_terms.ts +604 -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_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/mcp_server/consumer_tool_catalog.json +1 -1
- package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
- package/src/scripts/measure_docs_dead_links.ts +348 -0
- package/src/scripts/measure_host_capture.ts +461 -0
- package/src/scripts/migration_status.ts +3 -3
- package/src/scripts/model_rule_injection.ts +60 -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_turnaround.ts +384 -0
- package/src/scripts/probe_unblocked_ask.ts +279 -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
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
projectStoreSlug,
|
|
27
27
|
scanTranscripts,
|
|
28
28
|
weightedInputUnits
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-KPBWFOPZ.js";
|
|
30
30
|
import {
|
|
31
31
|
git_common_dir
|
|
32
32
|
} from "./chunk-E4XIZDIB.js";
|
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
ProjectRootError,
|
|
59
59
|
ROOT_OVERRIDE_ENV,
|
|
60
60
|
find_project_root_with_trace,
|
|
61
|
+
iter_setting_overrides,
|
|
61
62
|
project_settings_path,
|
|
62
63
|
resolve_project_root
|
|
63
64
|
} from "./chunk-NLP54U3J.js";
|
|
@@ -73,11 +74,11 @@ import {
|
|
|
73
74
|
// src/scripts/_cli/cmd_doctor.ts
|
|
74
75
|
var YAML2 = __toESM(require_dist(), 1);
|
|
75
76
|
import * as crypto2 from "node:crypto";
|
|
76
|
-
import * as
|
|
77
|
+
import * as fs14 from "node:fs";
|
|
77
78
|
import * as os3 from "node:os";
|
|
78
|
-
import * as
|
|
79
|
-
import
|
|
80
|
-
import { fileURLToPath as fileURLToPath5, pathToFileURL as
|
|
79
|
+
import * as path19 from "node:path";
|
|
80
|
+
import process3 from "node:process";
|
|
81
|
+
import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
81
82
|
|
|
82
83
|
// src/scripts/_cli/doctor_overrides.ts
|
|
83
84
|
import * as fs from "node:fs";
|
|
@@ -255,21 +256,23 @@ function censusDuplicateScope(userRulesDir, projectRulesDir) {
|
|
|
255
256
|
var preamble_byte_census_exports = {};
|
|
256
257
|
__export(preamble_byte_census_exports, {
|
|
257
258
|
buildByteCensus: () => buildByteCensus,
|
|
258
|
-
buildReport: () =>
|
|
259
|
+
buildReport: () => buildReport3,
|
|
259
260
|
censusClaudeMdHierarchy: () => censusClaudeMdHierarchy,
|
|
261
|
+
censusDeliveredRulePayload: () => censusDeliveredRulePayload,
|
|
260
262
|
censusGlobalProfile: () => censusGlobalProfile,
|
|
261
263
|
censusRuleDir: () => censusRuleDir,
|
|
262
264
|
censusSkillsCatalog: () => censusSkillsCatalog,
|
|
263
|
-
main: () =>
|
|
264
|
-
parseArgs: () =>
|
|
265
|
-
|
|
265
|
+
main: () => main4,
|
|
266
|
+
parseArgs: () => parseArgs4,
|
|
267
|
+
parseFrontmatter: () => parseFrontmatter,
|
|
268
|
+
renderText: () => renderText4,
|
|
266
269
|
topRulesByCost: () => topRulesByCost
|
|
267
270
|
});
|
|
268
271
|
var YAML = __toESM(require_dist(), 1);
|
|
269
|
-
import * as
|
|
272
|
+
import * as fs8 from "node:fs";
|
|
270
273
|
import { homedir as homedir2 } from "node:os";
|
|
271
|
-
import * as
|
|
272
|
-
import { fileURLToPath as fileURLToPath3, pathToFileURL as
|
|
274
|
+
import * as path12 from "node:path";
|
|
275
|
+
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL4 } from "node:url";
|
|
273
276
|
|
|
274
277
|
// src/scripts/_lib/agent_user_profile.ts
|
|
275
278
|
import * as path6 from "node:path";
|
|
@@ -357,14 +360,348 @@ function censusRuleDir(dir) {
|
|
|
357
360
|
|
|
358
361
|
// src/scripts/cache_realization_report.ts
|
|
359
362
|
import { execFileSync } from "node:child_process";
|
|
360
|
-
import * as
|
|
363
|
+
import * as fs7 from "node:fs";
|
|
361
364
|
import { homedir } from "node:os";
|
|
365
|
+
import * as path11 from "node:path";
|
|
366
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL3 } from "node:url";
|
|
367
|
+
|
|
368
|
+
// src/scripts/orchestration_payload_hash_drift.ts
|
|
362
369
|
import * as path9 from "node:path";
|
|
363
|
-
import {
|
|
370
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
364
371
|
|
|
365
|
-
// src/scripts/
|
|
372
|
+
// src/scripts/_lib/payload_hash_drift.ts
|
|
373
|
+
function emptyCohort() {
|
|
374
|
+
return { n: 0, hit_count: 0, hit_rate: null };
|
|
375
|
+
}
|
|
376
|
+
function aggregatePayloadHashDrift(lines) {
|
|
377
|
+
const withData = lines.filter((l) => l.payload_hash !== null && l.cache_hit !== null);
|
|
378
|
+
const byHash = /* @__PURE__ */ new Map();
|
|
379
|
+
for (const l of withData) {
|
|
380
|
+
const hash = l.payload_hash;
|
|
381
|
+
const arr = byHash.get(hash) ?? [];
|
|
382
|
+
arr.push(l.cache_hit);
|
|
383
|
+
byHash.set(hash, arr);
|
|
384
|
+
}
|
|
385
|
+
const groups = [];
|
|
386
|
+
const stable = emptyCohort();
|
|
387
|
+
const unstable = emptyCohort();
|
|
388
|
+
for (const [hash, hits] of byHash) {
|
|
389
|
+
const hitCount = hits.filter(Boolean).length;
|
|
390
|
+
groups.push({
|
|
391
|
+
payload_hash: hash,
|
|
392
|
+
occurrences: hits.length,
|
|
393
|
+
hit_count: hitCount,
|
|
394
|
+
hit_rate: hitCount / hits.length
|
|
395
|
+
});
|
|
396
|
+
if (hits.length === 1) {
|
|
397
|
+
unstable.n += 1;
|
|
398
|
+
if (hits[0] === true) unstable.hit_count += 1;
|
|
399
|
+
} else {
|
|
400
|
+
const repeats = hits.slice(1);
|
|
401
|
+
stable.n += repeats.length;
|
|
402
|
+
stable.hit_count += repeats.filter(Boolean).length;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
groups.sort((a, b) => b.occurrences - a.occurrences || a.payload_hash.localeCompare(b.payload_hash));
|
|
406
|
+
stable.hit_rate = stable.n > 0 ? stable.hit_count / stable.n : null;
|
|
407
|
+
unstable.hit_rate = unstable.n > 0 ? unstable.hit_count / unstable.n : null;
|
|
408
|
+
const driftVisible = stable.hit_rate !== null && unstable.hit_rate !== null && stable.hit_rate > unstable.hit_rate;
|
|
409
|
+
return {
|
|
410
|
+
total_lines: lines.length,
|
|
411
|
+
lines_with_data: withData.length,
|
|
412
|
+
groups,
|
|
413
|
+
stable_cohort: stable,
|
|
414
|
+
unstable_cohort: unstable,
|
|
415
|
+
drift_visible: driftVisible
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// src/scripts/orchestration_savings_report.ts
|
|
366
420
|
import * as fs5 from "node:fs";
|
|
367
421
|
import * as path8 from "node:path";
|
|
422
|
+
import { pathToFileURL } from "node:url";
|
|
423
|
+
|
|
424
|
+
// src/scripts/_lib/orchestration_savings.ts
|
|
425
|
+
var DEFAULT_TIER_WEIGHTS = { lite: 1, medium: 5, high: 15 };
|
|
426
|
+
function emptyProvenance() {
|
|
427
|
+
return { dispatches: 0, net_token_delta: 0 };
|
|
428
|
+
}
|
|
429
|
+
function aggregateOrchestrationSavings(lines, weights = DEFAULT_TIER_WEIGHTS) {
|
|
430
|
+
const report = {
|
|
431
|
+
dispatches: 0,
|
|
432
|
+
total_spawns: 0,
|
|
433
|
+
net_token_delta: 0,
|
|
434
|
+
tokens_saved: 0,
|
|
435
|
+
tokens_added: 0,
|
|
436
|
+
by_provenance: { measured: emptyProvenance(), estimated: emptyProvenance() },
|
|
437
|
+
by_tier: {},
|
|
438
|
+
by_task_class: {},
|
|
439
|
+
measured_share: 0,
|
|
440
|
+
modeled_cost: { covered_dispatches: 0, baseline_cost_units: 0, delegated_cost_units: 0, cost_reduction_pct: null, weights },
|
|
441
|
+
quality: {
|
|
442
|
+
quality_lines: 0,
|
|
443
|
+
first_pass_lines: 0,
|
|
444
|
+
first_pass_success_count: 0,
|
|
445
|
+
first_pass_success_rate: null,
|
|
446
|
+
escalated_lines: 0,
|
|
447
|
+
escalated_count: 0,
|
|
448
|
+
escalation_rate: null
|
|
449
|
+
},
|
|
450
|
+
notes: []
|
|
451
|
+
};
|
|
452
|
+
for (const line of lines) {
|
|
453
|
+
const o = line.orchestration;
|
|
454
|
+
if (!o) continue;
|
|
455
|
+
const spawns = o.spawn_count ?? 0;
|
|
456
|
+
if (!(spawns > 0)) continue;
|
|
457
|
+
report.dispatches += 1;
|
|
458
|
+
report.total_spawns += spawns;
|
|
459
|
+
const delta = o.token_delta ?? 0;
|
|
460
|
+
report.net_token_delta += delta;
|
|
461
|
+
if (delta < 0) report.tokens_saved += -delta;
|
|
462
|
+
else report.tokens_added += delta;
|
|
463
|
+
const prov = o.token_delta_provenance === "measured" ? "measured" : "estimated";
|
|
464
|
+
report.by_provenance[prov].dispatches += 1;
|
|
465
|
+
report.by_provenance[prov].net_token_delta += delta;
|
|
466
|
+
const tier = o.tier_chosen ?? "unknown";
|
|
467
|
+
report.by_tier[tier] = (report.by_tier[tier] ?? 0) + delta;
|
|
468
|
+
const cls = o.task_class ?? "unclassified";
|
|
469
|
+
report.by_task_class[cls] = (report.by_task_class[cls] ?? 0) + delta;
|
|
470
|
+
const dt = o.dispatch_tokens ?? 0;
|
|
471
|
+
const wChosen = o.tier_chosen != null ? weights[o.tier_chosen] : void 0;
|
|
472
|
+
const wSession = o.session_tier != null ? weights[o.session_tier] : void 0;
|
|
473
|
+
if (dt > 0 && wChosen !== void 0 && wSession !== void 0) {
|
|
474
|
+
report.modeled_cost.covered_dispatches += 1;
|
|
475
|
+
report.modeled_cost.baseline_cost_units += dt * wSession;
|
|
476
|
+
report.modeled_cost.delegated_cost_units += dt * wChosen;
|
|
477
|
+
}
|
|
478
|
+
const q2 = report.quality;
|
|
479
|
+
const fps = typeof o.first_pass_success === "boolean";
|
|
480
|
+
const esc = typeof o.escalated === "boolean";
|
|
481
|
+
if (fps || esc) q2.quality_lines += 1;
|
|
482
|
+
if (fps) {
|
|
483
|
+
q2.first_pass_lines += 1;
|
|
484
|
+
if (o.first_pass_success === true) q2.first_pass_success_count += 1;
|
|
485
|
+
}
|
|
486
|
+
if (esc) {
|
|
487
|
+
q2.escalated_lines += 1;
|
|
488
|
+
if (o.escalated === true) q2.escalated_count += 1;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
report.measured_share = report.dispatches === 0 ? 0 : report.by_provenance.measured.dispatches / report.dispatches;
|
|
492
|
+
const mc = report.modeled_cost;
|
|
493
|
+
mc.cost_reduction_pct = mc.baseline_cost_units > 0 ? (mc.baseline_cost_units - mc.delegated_cost_units) / mc.baseline_cost_units : null;
|
|
494
|
+
const q = report.quality;
|
|
495
|
+
q.first_pass_success_rate = q.first_pass_lines > 0 ? q.first_pass_success_count / q.first_pass_lines : null;
|
|
496
|
+
q.escalation_rate = q.escalated_lines > 0 ? q.escalated_count / q.escalated_lines : null;
|
|
497
|
+
if (report.dispatches === 0) {
|
|
498
|
+
report.notes.push("No orchestration telemetry yet (0 dispatches). Data accrues as delegable slices dispatch (always-on orchestration; recorded via orchestration_record).");
|
|
499
|
+
} else {
|
|
500
|
+
report.notes.push("Token counts are MEASURED but blind to the downshift rate win (same tokens on a cheaper tier \u2248 same count). The MODELED cost-% below captures that axis.");
|
|
501
|
+
if (report.by_provenance.estimated.dispatches > 0) {
|
|
502
|
+
report.notes.push(`${report.by_provenance.estimated.dispatches}/${report.dispatches} dispatch(es) use ESTIMATED token_delta (chars/4, lossy). Prefer measured (host usage metadata).`);
|
|
503
|
+
}
|
|
504
|
+
if (mc.covered_dispatches > 0 && mc.cost_reduction_pct !== null) {
|
|
505
|
+
report.notes.push(`MODELED cost reduction ${(mc.cost_reduction_pct * 100).toFixed(0)}% over ${mc.covered_dispatches}/${report.dispatches} dispatch(es) that carry tier data \u2014 from provider-neutral tier weights ${JSON.stringify(mc.weights)} + a same-token-count assumption. A MODEL, NOT a measured $ figure; tune with --weights.`);
|
|
506
|
+
} else {
|
|
507
|
+
report.notes.push("MODELED cost-% unavailable: no dispatch yet carries dispatch_tokens + session_tier + tier_chosen. Record those (orchestration_record --dispatch-tokens/--session-tier/--tier-chosen) to populate it.");
|
|
508
|
+
}
|
|
509
|
+
if (q.quality_lines === 0) {
|
|
510
|
+
report.notes.push("QUALITY columns empty: no dispatch yet carries first_pass_success / escalated. Record them (orchestration_record --first-pass-success/--escalated) \u2014 cost and quality are reported as a PAIR, never savings alone.");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return report;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// src/scripts/orchestration_savings_report.ts
|
|
517
|
+
var DEFAULT_DIR = "agents/runtime/state/audit";
|
|
518
|
+
function parseWeights(spec) {
|
|
519
|
+
if (!spec) return void 0;
|
|
520
|
+
const w = {};
|
|
521
|
+
for (const pair of spec.split(",")) {
|
|
522
|
+
const [k, v] = pair.split("=");
|
|
523
|
+
const n = Number(v);
|
|
524
|
+
if (k && Number.isFinite(n)) w[k.trim()] = n;
|
|
525
|
+
}
|
|
526
|
+
return Object.keys(w).length ? w : void 0;
|
|
527
|
+
}
|
|
528
|
+
function parseArgs(argv) {
|
|
529
|
+
const opts = { dir: DEFAULT_DIR, format: "text", weights: DEFAULT_TIER_WEIGHTS };
|
|
530
|
+
for (let i = 0; i < argv.length; i++) {
|
|
531
|
+
const a = argv[i];
|
|
532
|
+
if (a === void 0) continue;
|
|
533
|
+
if (a === "--dir") opts.dir = argv[++i] ?? opts.dir;
|
|
534
|
+
else if (a.startsWith("--dir=")) opts.dir = a.slice("--dir=".length);
|
|
535
|
+
else if (a === "--format") opts.format = argv[++i] ?? opts.format;
|
|
536
|
+
else if (a.startsWith("--format=")) opts.format = a.slice("--format=".length);
|
|
537
|
+
else if (a === "--weights") opts.weights = parseWeights(argv[++i]) ?? opts.weights;
|
|
538
|
+
else if (a.startsWith("--weights=")) opts.weights = parseWeights(a.slice("--weights=".length)) ?? opts.weights;
|
|
539
|
+
}
|
|
540
|
+
if (opts.format !== "text" && opts.format !== "json") opts.format = "text";
|
|
541
|
+
return opts;
|
|
542
|
+
}
|
|
543
|
+
function readAuditLines(dir) {
|
|
544
|
+
if (!fs5.existsSync(dir)) return [];
|
|
545
|
+
const lines = [];
|
|
546
|
+
for (const entry of fs5.readdirSync(dir).sort()) {
|
|
547
|
+
if (!entry.endsWith(".jsonl")) continue;
|
|
548
|
+
const raw = fs5.readFileSync(path8.join(dir, entry), "utf8");
|
|
549
|
+
for (const ln of raw.split("\n")) {
|
|
550
|
+
const trimmed = ln.trim();
|
|
551
|
+
if (!trimmed) continue;
|
|
552
|
+
try {
|
|
553
|
+
lines.push(JSON.parse(trimmed));
|
|
554
|
+
} catch {
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
return lines;
|
|
559
|
+
}
|
|
560
|
+
var QUALITY_GATE_MIN_LINES = 20;
|
|
561
|
+
function pct(v) {
|
|
562
|
+
return `${(v * 100).toFixed(0)}%`;
|
|
563
|
+
}
|
|
564
|
+
function renderPairedCostQuality(r) {
|
|
565
|
+
const q = r.quality;
|
|
566
|
+
const gated = q.quality_lines >= QUALITY_GATE_MIN_LINES;
|
|
567
|
+
const fps = gated && q.first_pass_success_rate !== null ? `${pct(q.first_pass_success_rate)} (n=${q.first_pass_lines})` : `n/a (n=${q.first_pass_lines})`;
|
|
568
|
+
const esc = gated && q.escalation_rate !== null ? `${pct(q.escalation_rate)} (n=${q.escalated_lines})` : `n/a (n=${q.escalated_lines})`;
|
|
569
|
+
return [
|
|
570
|
+
" cost \xD7 quality (paired \u2014 never savings alone):",
|
|
571
|
+
` net token_delta: ${r.net_token_delta} (negative = net saved) | first_pass_success_rate: ${fps}`,
|
|
572
|
+
` tokens saved: ${r.tokens_saved} \xB7 tokens added: ${r.tokens_added} | escalation_rate: ${esc}`
|
|
573
|
+
];
|
|
574
|
+
}
|
|
575
|
+
function renderText(r, dir) {
|
|
576
|
+
const out = [];
|
|
577
|
+
out.push("Orchestration savings report");
|
|
578
|
+
out.push(` source: ${dir}`);
|
|
579
|
+
out.push(` dispatches: ${r.dispatches} (total spawns: ${r.total_spawns})`);
|
|
580
|
+
out.push(...renderPairedCostQuality(r));
|
|
581
|
+
out.push(` provenance: measured ${r.by_provenance.measured.dispatches} (\u0394 ${r.by_provenance.measured.net_token_delta}) \xB7 estimated ${r.by_provenance.estimated.dispatches} (\u0394 ${r.by_provenance.estimated.net_token_delta})`);
|
|
582
|
+
out.push(` measured share: ${(r.measured_share * 100).toFixed(0)}%`);
|
|
583
|
+
if (Object.keys(r.by_tier).length) {
|
|
584
|
+
out.push(" by tier (\u0394 tokens):");
|
|
585
|
+
for (const [tier, d] of Object.entries(r.by_tier).sort()) out.push(` ${tier}: ${d}`);
|
|
586
|
+
}
|
|
587
|
+
if (Object.keys(r.by_task_class).length) {
|
|
588
|
+
out.push(" by task_class (\u0394 tokens):");
|
|
589
|
+
for (const [cls, d] of Object.entries(r.by_task_class).sort()) out.push(` ${cls}: ${d}`);
|
|
590
|
+
}
|
|
591
|
+
const mc = r.modeled_cost;
|
|
592
|
+
if (mc.cost_reduction_pct !== null) {
|
|
593
|
+
out.push(` MODELED cost reduction: ${(mc.cost_reduction_pct * 100).toFixed(0)}% (over ${mc.covered_dispatches}/${r.dispatches} dispatch(es) with tier data)`);
|
|
594
|
+
out.push(` weights ${JSON.stringify(mc.weights)} \xB7 baseline ${mc.baseline_cost_units} \u2192 delegated ${mc.delegated_cost_units} cost-units \xB7 MODEL, not measured $`);
|
|
595
|
+
} else {
|
|
596
|
+
out.push(" MODELED cost reduction: n/a (needs dispatch_tokens + session_tier + tier_chosen on a dispatch)");
|
|
597
|
+
}
|
|
598
|
+
out.push(" notes:");
|
|
599
|
+
for (const n of r.notes) out.push(` - ${n}`);
|
|
600
|
+
return out.join("\n");
|
|
601
|
+
}
|
|
602
|
+
function main(argv = process.argv.slice(2)) {
|
|
603
|
+
const opts = parseArgs(argv);
|
|
604
|
+
const lines = readAuditLines(opts.dir);
|
|
605
|
+
const report = aggregateOrchestrationSavings(lines, opts.weights);
|
|
606
|
+
if (opts.format === "json") {
|
|
607
|
+
process.stdout.write(JSON.stringify({ ...report, source: opts.dir }, null, 2) + "\n");
|
|
608
|
+
} else {
|
|
609
|
+
process.stdout.write(renderText(report, opts.dir) + "\n");
|
|
610
|
+
}
|
|
611
|
+
return 0;
|
|
612
|
+
}
|
|
613
|
+
if (process.argv[1] !== void 0) {
|
|
614
|
+
const invokedUrl = pathToFileURL(path8.resolve(process.argv[1])).href;
|
|
615
|
+
if (import.meta.url === invokedUrl) process.exit(main());
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// src/scripts/orchestration_payload_hash_drift.ts
|
|
619
|
+
var DEFAULT_DIR2 = "agents/runtime/state/audit";
|
|
620
|
+
function parseArgs2(argv) {
|
|
621
|
+
const opts = { dir: DEFAULT_DIR2, format: "text" };
|
|
622
|
+
for (let i = 0; i < argv.length; i++) {
|
|
623
|
+
const a = argv[i];
|
|
624
|
+
if (a === void 0) continue;
|
|
625
|
+
if (a === "--dir") opts.dir = argv[++i] ?? opts.dir;
|
|
626
|
+
else if (a.startsWith("--dir=")) opts.dir = a.slice("--dir=".length);
|
|
627
|
+
else if (a === "--format") opts.format = argv[++i] ?? opts.format;
|
|
628
|
+
else if (a.startsWith("--format=")) opts.format = a.slice("--format=".length);
|
|
629
|
+
}
|
|
630
|
+
if (opts.format !== "text" && opts.format !== "json") opts.format = "text";
|
|
631
|
+
return opts;
|
|
632
|
+
}
|
|
633
|
+
function toPayloadHashLine(raw) {
|
|
634
|
+
const line = raw ?? {};
|
|
635
|
+
if (line.input_kind !== "orchestration" || !line.orchestration) {
|
|
636
|
+
return { payload_hash: null, cache_hit: null };
|
|
637
|
+
}
|
|
638
|
+
const hash = line.orchestration.payload_hash;
|
|
639
|
+
const hit = line.orchestration.cache_hit;
|
|
640
|
+
return {
|
|
641
|
+
payload_hash: typeof hash === "string" && hash.length > 0 ? hash : null,
|
|
642
|
+
cache_hit: typeof hit === "boolean" ? hit : null
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function buildReport(dir) {
|
|
646
|
+
const rawLines = readAuditLines(dir);
|
|
647
|
+
const lines = rawLines.map(toPayloadHashLine);
|
|
648
|
+
return aggregatePayloadHashDrift(lines);
|
|
649
|
+
}
|
|
650
|
+
function pct2(v) {
|
|
651
|
+
return `${(v * 100).toFixed(1)}%`;
|
|
652
|
+
}
|
|
653
|
+
function renderText2(r) {
|
|
654
|
+
const out = [];
|
|
655
|
+
out.push("Payload-hash \xD7 cache-hit drift report");
|
|
656
|
+
out.push(` total audit-log-v1 lines seen: ${r.total_lines}`);
|
|
657
|
+
out.push(` lines carrying BOTH payload_hash and cache_hit: ${r.lines_with_data}`);
|
|
658
|
+
out.push("");
|
|
659
|
+
if (r.lines_with_data === 0) {
|
|
660
|
+
out.push(
|
|
661
|
+
"No recorded lines carry both fields yet \u2014 this is the CURRENT expected state (both are lean-init"
|
|
662
|
+
);
|
|
663
|
+
out.push(
|
|
664
|
+
"extensions; no caller wires a real value into them today). The reader works; there is nothing to"
|
|
665
|
+
);
|
|
666
|
+
out.push("report on. This is NOT presented as a green pass \u2014 it is an honest empty state.");
|
|
667
|
+
} else {
|
|
668
|
+
out.push(
|
|
669
|
+
`stable cohort (repeat occurrences of a hash \u2014 the prior write should already be cached): n=${r.stable_cohort.n} hit_rate=${r.stable_cohort.hit_rate !== null ? pct2(r.stable_cohort.hit_rate) : "n/a"}`
|
|
670
|
+
);
|
|
671
|
+
out.push(
|
|
672
|
+
`unstable cohort (hashes seen exactly once \u2014 a payload that never repeats): n=${r.unstable_cohort.n} hit_rate=${r.unstable_cohort.hit_rate !== null ? pct2(r.unstable_cohort.hit_rate) : "n/a"}`
|
|
673
|
+
);
|
|
674
|
+
out.push(`drift_visible (stable hit_rate > unstable hit_rate): ${r.drift_visible ? "YES" : "no"}`);
|
|
675
|
+
out.push("");
|
|
676
|
+
out.push("Per-hash breakdown (most-occurrences first):");
|
|
677
|
+
for (const g of r.groups) {
|
|
678
|
+
out.push(` ${g.payload_hash}: occurrences=${g.occurrences} hit_rate=${pct2(g.hit_rate)}`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
out.push("");
|
|
682
|
+
out.push("REFUSAL (report, never act): cache_hit is a proxy for host-controlled cache behaviour, not a");
|
|
683
|
+
out.push("metric this package controls. Per ADR-118 \xA71, a host-controlled proxy fails the direct-measure");
|
|
684
|
+
out.push("condition outright \u2014 this report never wires a measure\u2192adjust step off these two fields.");
|
|
685
|
+
return out.join("\n");
|
|
686
|
+
}
|
|
687
|
+
function main2(argv = process.argv.slice(2)) {
|
|
688
|
+
const opts = parseArgs2(argv);
|
|
689
|
+
const report = buildReport(opts.dir);
|
|
690
|
+
if (opts.format === "json") {
|
|
691
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
692
|
+
} else {
|
|
693
|
+
process.stdout.write(renderText2(report) + "\n");
|
|
694
|
+
}
|
|
695
|
+
return 0;
|
|
696
|
+
}
|
|
697
|
+
if (process.argv[1] !== void 0) {
|
|
698
|
+
const invokedUrl = pathToFileURL2(path9.resolve(process.argv[1])).href;
|
|
699
|
+
if (import.meta.url === invokedUrl) process.exit(main2());
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/scripts/ai_council/pricing.ts
|
|
703
|
+
import * as fs6 from "node:fs";
|
|
704
|
+
import * as path10 from "node:path";
|
|
368
705
|
import { fileURLToPath } from "node:url";
|
|
369
706
|
|
|
370
707
|
// src/scripts/ai_council/_default_prices.ts
|
|
@@ -409,8 +746,8 @@ function as_rows() {
|
|
|
409
746
|
|
|
410
747
|
// src/scripts/ai_council/pricing.ts
|
|
411
748
|
var _HERE = fileURLToPath(import.meta.url);
|
|
412
|
-
var REPO_ROOT =
|
|
413
|
-
var PRICES_FILE =
|
|
749
|
+
var REPO_ROOT = path10.resolve(path10.dirname(_HERE), "..", "..", "..");
|
|
750
|
+
var PRICES_FILE = path10.join(REPO_ROOT, "agents", "runtime", ".agent-prices.md");
|
|
414
751
|
function lookup(table, provider, model) {
|
|
415
752
|
const exact = table.prices.get(priceKey(provider, model));
|
|
416
753
|
if (exact !== void 0) {
|
|
@@ -469,16 +806,16 @@ function reprice_with_cache(provider, model, tokens, table, ttl = "5m") {
|
|
|
469
806
|
};
|
|
470
807
|
}
|
|
471
808
|
function load_prices(p = PRICES_FILE) {
|
|
472
|
-
if (!
|
|
809
|
+
if (!fs6.existsSync(p)) {
|
|
473
810
|
bootstrap_from_defaults(p);
|
|
474
811
|
}
|
|
475
|
-
return _parse(
|
|
812
|
+
return _parse(fs6.readFileSync(p, "utf-8"));
|
|
476
813
|
}
|
|
477
814
|
function bootstrap_from_defaults(p = PRICES_FILE) {
|
|
478
|
-
|
|
815
|
+
fs6.mkdirSync(path10.dirname(p), { recursive: true });
|
|
479
816
|
const rows = as_rows();
|
|
480
817
|
const body = _render_markdown(LAST_UPDATED, "shipped-default", rows);
|
|
481
|
-
|
|
818
|
+
fs6.writeFileSync(p, body, "utf-8");
|
|
482
819
|
}
|
|
483
820
|
function _fmt62f(x) {
|
|
484
821
|
const s = x.toFixed(2);
|
|
@@ -598,7 +935,7 @@ function _pyFloat(s) {
|
|
|
598
935
|
|
|
599
936
|
// src/scripts/cache_realization_report.ts
|
|
600
937
|
var _HERE2 = fileURLToPath2(import.meta.url);
|
|
601
|
-
var REPO_ROOT2 =
|
|
938
|
+
var REPO_ROOT2 = path11.resolve(path11.dirname(_HERE2), "..", "..");
|
|
602
939
|
var C1_COLD_START_DOMINANCE_THRESHOLD = 0.5;
|
|
603
940
|
var C2_DUPLICATE_SCOPE_THRESHOLD = 0.25;
|
|
604
941
|
var C4_COUNCIL_MISPRICING_THRESHOLD = 0.05;
|
|
@@ -703,20 +1040,20 @@ function computeDuplicateScope(userRulesDir, projectRulesDir, subagentWriteVolum
|
|
|
703
1040
|
};
|
|
704
1041
|
}
|
|
705
1042
|
function findDebateRoundFiles(councilRoot) {
|
|
706
|
-
const base =
|
|
707
|
-
if (!
|
|
1043
|
+
const base = path11.join(councilRoot, "agents", "runtime", "council", "responses");
|
|
1044
|
+
if (!fs7.existsSync(base)) return [];
|
|
708
1045
|
const out = [];
|
|
709
1046
|
const stack = [base];
|
|
710
1047
|
while (stack.length > 0) {
|
|
711
1048
|
const dir = stack.pop();
|
|
712
1049
|
let entries;
|
|
713
1050
|
try {
|
|
714
|
-
entries =
|
|
1051
|
+
entries = fs7.readdirSync(dir, { withFileTypes: true });
|
|
715
1052
|
} catch {
|
|
716
1053
|
continue;
|
|
717
1054
|
}
|
|
718
1055
|
for (const entry of entries) {
|
|
719
|
-
const full =
|
|
1056
|
+
const full = path11.join(dir, entry.name);
|
|
720
1057
|
if (entry.isDirectory()) {
|
|
721
1058
|
stack.push(full);
|
|
722
1059
|
continue;
|
|
@@ -739,7 +1076,7 @@ function computeCouncilMispricing(councilRoot) {
|
|
|
739
1076
|
}
|
|
740
1077
|
const groups = /* @__PURE__ */ new Map();
|
|
741
1078
|
for (const f of files) {
|
|
742
|
-
const dir =
|
|
1079
|
+
const dir = path11.dirname(f);
|
|
743
1080
|
const arr = groups.get(dir) ?? [];
|
|
744
1081
|
arr.push(f);
|
|
745
1082
|
groups.set(dir, arr);
|
|
@@ -760,7 +1097,7 @@ function computeCouncilMispricing(councilRoot) {
|
|
|
760
1097
|
for (const f of groupFiles) {
|
|
761
1098
|
let data;
|
|
762
1099
|
try {
|
|
763
|
-
data = JSON.parse(
|
|
1100
|
+
data = JSON.parse(fs7.readFileSync(f, "utf-8"));
|
|
764
1101
|
} catch {
|
|
765
1102
|
continue;
|
|
766
1103
|
}
|
|
@@ -800,7 +1137,7 @@ function computeCouncilMispricing(councilRoot) {
|
|
|
800
1137
|
const status = Math.abs(deltaPct) >= C4_COUNCIL_MISPRICING_THRESHOLD ? "confirmed" : "falsified";
|
|
801
1138
|
return {
|
|
802
1139
|
status,
|
|
803
|
-
session:
|
|
1140
|
+
session: path11.relative(councilRoot, best.dir) || "(top-level)",
|
|
804
1141
|
rounds: best.rounds,
|
|
805
1142
|
recorded_cost_usd: best.recorded,
|
|
806
1143
|
cache_aware_cost_usd: best.cacheAware,
|
|
@@ -828,8 +1165,8 @@ function computeWorktreeFragmentation(projectsRoot, worktreePaths, maxAgeDays) {
|
|
|
828
1165
|
}
|
|
829
1166
|
const established = worktreePaths[0];
|
|
830
1167
|
const encodedEstablished = encodeProjectPath(established);
|
|
831
|
-
const worktreeDirs = worktreePaths.slice(1).map(encodeProjectPath).filter((d) =>
|
|
832
|
-
if (!
|
|
1168
|
+
const worktreeDirs = worktreePaths.slice(1).map(encodeProjectPath).filter((d) => fs7.existsSync(path11.join(projectsRoot, d)));
|
|
1169
|
+
if (!fs7.existsSync(path11.join(projectsRoot, encodedEstablished)) || worktreeDirs.length === 0) {
|
|
833
1170
|
return {
|
|
834
1171
|
status: "pending",
|
|
835
1172
|
reason: "no transcript directory found for both an established and a fresh-worktree checkout of this repo"
|
|
@@ -945,11 +1282,12 @@ function defaultOptions() {
|
|
|
945
1282
|
maxAgeDays: 14,
|
|
946
1283
|
repoRoot: REPO_ROOT2,
|
|
947
1284
|
councilRoot: REPO_ROOT2,
|
|
948
|
-
userRulesDir:
|
|
949
|
-
projectRulesDir:
|
|
1285
|
+
userRulesDir: path11.join(homedir(), ".claude", "rules"),
|
|
1286
|
+
projectRulesDir: path11.join(REPO_ROOT2, "dist", "agent-src", "rules"),
|
|
1287
|
+
auditDir: path11.join(REPO_ROOT2, "agents", "runtime", "state", "audit")
|
|
950
1288
|
};
|
|
951
1289
|
}
|
|
952
|
-
function
|
|
1290
|
+
function parseArgs3(argv) {
|
|
953
1291
|
const opts = defaultOptions();
|
|
954
1292
|
for (let i = 0; i < argv.length; i++) {
|
|
955
1293
|
const a = argv[i];
|
|
@@ -968,11 +1306,44 @@ function parseArgs(argv) {
|
|
|
968
1306
|
else if (a.startsWith("--user-rules-dir=")) opts.userRulesDir = a.slice("--user-rules-dir=".length);
|
|
969
1307
|
else if (a === "--project-rules-dir") opts.projectRulesDir = argv[++i] ?? opts.projectRulesDir;
|
|
970
1308
|
else if (a.startsWith("--project-rules-dir=")) opts.projectRulesDir = a.slice("--project-rules-dir=".length);
|
|
1309
|
+
else if (a === "--audit-dir") opts.auditDir = argv[++i] ?? opts.auditDir;
|
|
1310
|
+
else if (a.startsWith("--audit-dir=")) opts.auditDir = a.slice("--audit-dir=".length);
|
|
971
1311
|
}
|
|
972
1312
|
if (opts.format !== "text" && opts.format !== "json") opts.format = "text";
|
|
973
1313
|
return opts;
|
|
974
1314
|
}
|
|
975
|
-
function
|
|
1315
|
+
function computePrefixStability(drift) {
|
|
1316
|
+
const stable = { n: drift.stable_cohort.n, read_share: drift.stable_cohort.hit_rate };
|
|
1317
|
+
const unstable = { n: drift.unstable_cohort.n, read_share: drift.unstable_cohort.hit_rate };
|
|
1318
|
+
if (stable.read_share === null || unstable.read_share === null) {
|
|
1319
|
+
const empty = [stable.read_share === null ? "stable" : null, unstable.read_share === null ? "unstable" : null].filter((x) => x !== null).join(" and ");
|
|
1320
|
+
const plural = empty.includes(" and ") ? "cohorts are" : "cohort is";
|
|
1321
|
+
return {
|
|
1322
|
+
verdict: "insufficient-data",
|
|
1323
|
+
reason: `the ${empty} ${plural} empty (${drift.lines_with_data} audit line(s) carry both payload_hash and cache_hit) \u2014 no comparison exists, and a share is not reported for one`,
|
|
1324
|
+
stable_cohort: stable,
|
|
1325
|
+
unstable_cohort: unstable,
|
|
1326
|
+
lines_with_data: drift.lines_with_data
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
if (stable.read_share < unstable.read_share) {
|
|
1330
|
+
return {
|
|
1331
|
+
verdict: "inverted",
|
|
1332
|
+
reason: `repeat dispatches of the same payload shape hit the cache LESS often (${(stable.read_share * 100).toFixed(1)}%) than one-off shapes (${(unstable.read_share * 100).toFixed(1)}%) \u2014 a prefix-stable surface is being rewritten between repeats`,
|
|
1333
|
+
stable_cohort: stable,
|
|
1334
|
+
unstable_cohort: unstable,
|
|
1335
|
+
lines_with_data: drift.lines_with_data
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
return {
|
|
1339
|
+
verdict: "stable-higher",
|
|
1340
|
+
reason: `repeat dispatches hit the cache at ${(stable.read_share * 100).toFixed(1)}% against ${(unstable.read_share * 100).toFixed(1)}% for one-off shapes, which is the expected ordering`,
|
|
1341
|
+
stable_cohort: stable,
|
|
1342
|
+
unstable_cohort: unstable,
|
|
1343
|
+
lines_with_data: drift.lines_with_data
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
function buildReport2(opts) {
|
|
976
1347
|
const scan = scanTranscripts({ root: opts.root, maxAgeDays: opts.maxAgeDays });
|
|
977
1348
|
const buckets = aggregateByBucket(scan.records);
|
|
978
1349
|
const subagentColdStart = computeColdStarts(scan.records);
|
|
@@ -986,6 +1357,18 @@ function buildReport(opts) {
|
|
|
986
1357
|
const councilMispricing = computeCouncilMispricing(opts.councilRoot);
|
|
987
1358
|
const worktreePaths = listGitWorktrees(opts.repoRoot);
|
|
988
1359
|
const worktreeFragmentation = computeWorktreeFragmentation(opts.root, worktreePaths, opts.maxAgeDays);
|
|
1360
|
+
let prefixStability;
|
|
1361
|
+
try {
|
|
1362
|
+
prefixStability = computePrefixStability(buildReport(opts.auditDir));
|
|
1363
|
+
} catch (err) {
|
|
1364
|
+
prefixStability = {
|
|
1365
|
+
verdict: "insufficient-data",
|
|
1366
|
+
reason: `the audit ledger at ${opts.auditDir} could not be read: ${err.message}`,
|
|
1367
|
+
stable_cohort: { n: 0, read_share: null },
|
|
1368
|
+
unstable_cohort: { n: 0, read_share: null },
|
|
1369
|
+
lines_with_data: 0
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
989
1372
|
const claims = buildClaims({ subagentColdStart, duplicateScope, councilMispricing, worktreeFragmentation });
|
|
990
1373
|
return {
|
|
991
1374
|
schema: "cache-realization-report/v1",
|
|
@@ -1005,13 +1388,14 @@ function buildReport(opts) {
|
|
|
1005
1388
|
duplicate_scope: duplicateScope,
|
|
1006
1389
|
council_mispricing: councilMispricing,
|
|
1007
1390
|
worktree_fragmentation: worktreeFragmentation,
|
|
1391
|
+
prefix_stability: prefixStability,
|
|
1008
1392
|
claims
|
|
1009
1393
|
};
|
|
1010
1394
|
}
|
|
1011
|
-
function
|
|
1395
|
+
function pct3(v) {
|
|
1012
1396
|
return `${(v * 100).toFixed(1)}%`;
|
|
1013
1397
|
}
|
|
1014
|
-
function
|
|
1398
|
+
function renderText3(r) {
|
|
1015
1399
|
const out = [];
|
|
1016
1400
|
out.push("Cache-realization report");
|
|
1017
1401
|
out.push(` host_version: ${r.host_version}`);
|
|
@@ -1019,12 +1403,21 @@ function renderText(r) {
|
|
|
1019
1403
|
out.push(` root: ${r.root}`);
|
|
1020
1404
|
out.push(` metric: billable_input = ${r.metric_definition.billable_input}`);
|
|
1021
1405
|
out.push(` ${r.metric_definition.note}`);
|
|
1022
|
-
out.push(` dedup: ${r.deduped_count}/${r.total_seen} unique records kept (dedup_ratio ${
|
|
1406
|
+
out.push(` dedup: ${r.deduped_count}/${r.total_seen} unique records kept (dedup_ratio ${pct3(r.dedup_ratio)})`);
|
|
1407
|
+
out.push("");
|
|
1408
|
+
const ps = r.prefix_stability;
|
|
1409
|
+
const share = (v) => v === null ? "insufficient data" : pct3(v);
|
|
1410
|
+
const mark = ps.verdict === "inverted" ? "\u26A0\uFE0F " : "";
|
|
1411
|
+
out.push("Prefix stability (payload_hash \xD7 cache_hit):");
|
|
1412
|
+
out.push(` ${mark}verdict: ${ps.verdict}`);
|
|
1413
|
+
out.push(` stable cohort: n=${ps.stable_cohort.n} read_share=${share(ps.stable_cohort.read_share)}`);
|
|
1414
|
+
out.push(` unstable cohort: n=${ps.unstable_cohort.n} read_share=${share(ps.unstable_cohort.read_share)}`);
|
|
1415
|
+
out.push(` ${ps.reason}`);
|
|
1023
1416
|
out.push("");
|
|
1024
1417
|
out.push("By bucket:");
|
|
1025
1418
|
for (const bucket of ["main", "subagent"]) {
|
|
1026
1419
|
const b = r.buckets[bucket];
|
|
1027
|
-
out.push(` ${bucket}: calls=${b.calls} read_share=${
|
|
1420
|
+
out.push(` ${bucket}: calls=${b.calls} read_share=${pct3(b.read_share)} weighted_input_units=${Math.round(b.weighted_input_units)}`);
|
|
1028
1421
|
out.push(
|
|
1029
1422
|
` input=${b.input_tokens} cache_read=${b.cache_read_input_tokens} cache_creation=${b.cache_creation_input_tokens} (5m=${b.ephemeral_5m_input_tokens} 1h=${b.ephemeral_1h_input_tokens}) output=${b.output_tokens}`
|
|
1030
1423
|
);
|
|
@@ -1035,21 +1428,21 @@ function renderText(r) {
|
|
|
1035
1428
|
out.push(
|
|
1036
1429
|
` legs=${cs.legs} median_written_or_uncached=${Math.round(cs.median_first_call_written_or_uncached)} mean=${Math.round(cs.mean_first_call_written_or_uncached)}`
|
|
1037
1430
|
);
|
|
1038
|
-
out.push(` first_call_cache_read_share=${
|
|
1039
|
-
out.push(` cold_start_share_of_subagent_write_volume=${
|
|
1431
|
+
out.push(` first_call_cache_read_share=${pct3(cs.first_call_cache_read_share)}`);
|
|
1432
|
+
out.push(` cold_start_share_of_subagent_write_volume=${pct3(cs.cold_start_share_of_write_volume)}`);
|
|
1040
1433
|
out.push(
|
|
1041
|
-
` write_share=${
|
|
1434
|
+
` write_share=${pct3(cs.write_share_of_billable)} read_share=${pct3(cs.read_share_of_billable)} uncached_share=${pct3(cs.uncached_share_of_billable)} (of billable input, all subagent records)`
|
|
1042
1435
|
);
|
|
1043
1436
|
out.push("");
|
|
1044
1437
|
out.push(`Per-agent breakdown: ${r.by_agent.length} distinct subagent legs (--format json carries all; top 10 by weighted_input_units below)`);
|
|
1045
1438
|
const top10 = [...r.by_agent].sort((a, b) => b.weighted_input_units - a.weighted_input_units).slice(0, 10);
|
|
1046
1439
|
for (const a of top10) {
|
|
1047
|
-
out.push(` ${a.agentId}: calls=${a.calls} read_share=${
|
|
1440
|
+
out.push(` ${a.agentId}: calls=${a.calls} read_share=${pct3(a.read_share)} weighted_input_units=${Math.round(a.weighted_input_units)}`);
|
|
1048
1441
|
}
|
|
1049
1442
|
out.push("");
|
|
1050
1443
|
out.push("Pre-registered claims:");
|
|
1051
1444
|
for (const c of r.claims) {
|
|
1052
|
-
const measured = c.measured !== void 0 ? ` (measured ${
|
|
1445
|
+
const measured = c.measured !== void 0 ? ` (measured ${pct3(c.measured)})` : "";
|
|
1053
1446
|
const reasonSuffix = c.verdict === "pending" && c.reason ? ` \u2014 ${c.reason}` : "";
|
|
1054
1447
|
out.push(` ${c.id} [${c.verdict}]${measured}: ${c.description}${reasonSuffix}`);
|
|
1055
1448
|
}
|
|
@@ -1058,28 +1451,28 @@ function renderText(r) {
|
|
|
1058
1451
|
out.push(" command: ./scripts-run src/scripts/cache_realization_report --format text");
|
|
1059
1452
|
out.push(` host_version at this run: ${r.host_version}`);
|
|
1060
1453
|
out.push(
|
|
1061
|
-
` re-run + restamp this report if: read_share drops below ${
|
|
1454
|
+
` re-run + restamp this report if: read_share drops below ${pct3(DRIFT_READ_SHARE_FLOOR)}, OR cold-start share drops below ${pct3(DRIFT_COLD_START_SHARE_FLOOR)}`
|
|
1062
1455
|
);
|
|
1063
1456
|
return out.join("\n");
|
|
1064
1457
|
}
|
|
1065
|
-
function
|
|
1066
|
-
const opts =
|
|
1067
|
-
const report =
|
|
1458
|
+
function main3(argv = process.argv.slice(2)) {
|
|
1459
|
+
const opts = parseArgs3(argv);
|
|
1460
|
+
const report = buildReport2(opts);
|
|
1068
1461
|
if (opts.format === "json") {
|
|
1069
1462
|
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
1070
1463
|
} else {
|
|
1071
|
-
process.stdout.write(
|
|
1464
|
+
process.stdout.write(renderText3(report) + "\n");
|
|
1072
1465
|
}
|
|
1073
1466
|
return 0;
|
|
1074
1467
|
}
|
|
1075
1468
|
if (process.argv[1] !== void 0) {
|
|
1076
|
-
const invokedUrl =
|
|
1077
|
-
if (import.meta.url === invokedUrl) process.exit(
|
|
1469
|
+
const invokedUrl = pathToFileURL3(path11.resolve(process.argv[1])).href;
|
|
1470
|
+
if (import.meta.url === invokedUrl) process.exit(main3());
|
|
1078
1471
|
}
|
|
1079
1472
|
|
|
1080
1473
|
// src/scripts/preamble_byte_census.ts
|
|
1081
1474
|
var _HERE3 = fileURLToPath3(import.meta.url);
|
|
1082
|
-
var REPO_ROOT3 =
|
|
1475
|
+
var REPO_ROOT3 = path12.resolve(path12.dirname(_HERE3), "..", "..");
|
|
1083
1476
|
var CHARS_PER_TOKEN = 4;
|
|
1084
1477
|
var SUM_TOLERANCE_PCT = 0.1;
|
|
1085
1478
|
function tokensFromChars(chars) {
|
|
@@ -1087,19 +1480,47 @@ function tokensFromChars(chars) {
|
|
|
1087
1480
|
}
|
|
1088
1481
|
function readCharsIfExists(p) {
|
|
1089
1482
|
try {
|
|
1090
|
-
return
|
|
1483
|
+
return fs8.statSync(p).size;
|
|
1091
1484
|
} catch {
|
|
1092
1485
|
return 0;
|
|
1093
1486
|
}
|
|
1094
1487
|
}
|
|
1488
|
+
var MAINTAINER_WORKSPACE = "agent-config-maintainer";
|
|
1489
|
+
function censusDeliveredRulePayload(projectionDir) {
|
|
1490
|
+
const empty = () => ({ files: 0, chars: 0 });
|
|
1491
|
+
const delivered = empty();
|
|
1492
|
+
const packageOnly = empty();
|
|
1493
|
+
let names;
|
|
1494
|
+
try {
|
|
1495
|
+
names = fs8.readdirSync(projectionDir).filter((f) => f.endsWith(".md"));
|
|
1496
|
+
} catch {
|
|
1497
|
+
return { delivered, packageOnly };
|
|
1498
|
+
}
|
|
1499
|
+
for (const name of names) {
|
|
1500
|
+
const abs = path12.join(projectionDir, name);
|
|
1501
|
+
let text;
|
|
1502
|
+
try {
|
|
1503
|
+
text = fs8.readFileSync(abs, "utf8");
|
|
1504
|
+
} catch {
|
|
1505
|
+
continue;
|
|
1506
|
+
}
|
|
1507
|
+
const m = /^workspaces:\s*\[([^\]]*)\]/m.exec(text);
|
|
1508
|
+
const listed = m === null ? [] : m[1].split(",").map((x) => x.trim()).filter((x) => x !== "");
|
|
1509
|
+
const isPackageOnly = listed.length > 0 && listed.every((w) => w === MAINTAINER_WORKSPACE);
|
|
1510
|
+
const bucket = isPackageOnly ? packageOnly : delivered;
|
|
1511
|
+
bucket.files += 1;
|
|
1512
|
+
bucket.chars += Buffer.byteLength(text, "utf8");
|
|
1513
|
+
}
|
|
1514
|
+
return { delivered, packageOnly };
|
|
1515
|
+
}
|
|
1095
1516
|
function topRulesByCost(dir, limit = 10) {
|
|
1096
|
-
if (!
|
|
1517
|
+
if (!fs8.existsSync(dir)) return [];
|
|
1097
1518
|
const entries = [];
|
|
1098
|
-
for (const name of
|
|
1519
|
+
for (const name of fs8.readdirSync(dir)) {
|
|
1099
1520
|
if (!name.endsWith(".md")) continue;
|
|
1100
1521
|
let chars;
|
|
1101
1522
|
try {
|
|
1102
|
-
chars =
|
|
1523
|
+
chars = fs8.statSync(path12.join(dir, name)).size;
|
|
1103
1524
|
} catch {
|
|
1104
1525
|
continue;
|
|
1105
1526
|
}
|
|
@@ -1112,33 +1533,33 @@ var IMPORT_LINE_RE = /^@(\S+)\s*$/;
|
|
|
1112
1533
|
function parseClaudeMdImports(claudeMdPath) {
|
|
1113
1534
|
let text;
|
|
1114
1535
|
try {
|
|
1115
|
-
text =
|
|
1536
|
+
text = fs8.readFileSync(claudeMdPath, "utf-8");
|
|
1116
1537
|
} catch {
|
|
1117
1538
|
return [];
|
|
1118
1539
|
}
|
|
1119
|
-
const base =
|
|
1540
|
+
const base = path12.dirname(claudeMdPath);
|
|
1120
1541
|
const out = [];
|
|
1121
1542
|
for (const line of text.split("\n")) {
|
|
1122
1543
|
const m = IMPORT_LINE_RE.exec(line.trim());
|
|
1123
1544
|
if (!m) continue;
|
|
1124
1545
|
const rel = m[1];
|
|
1125
|
-
const resolved =
|
|
1546
|
+
const resolved = path12.isAbsolute(rel) ? rel : path12.join(base, rel);
|
|
1126
1547
|
const chars = readCharsIfExists(resolved);
|
|
1127
1548
|
if (chars > 0) out.push({ file: rel, chars });
|
|
1128
1549
|
}
|
|
1129
1550
|
return out;
|
|
1130
1551
|
}
|
|
1131
1552
|
function censusClaudeMdHierarchy(repoRoot, userHome) {
|
|
1132
|
-
const projectClaudeMd =
|
|
1133
|
-
const projectClaudeLocalMd =
|
|
1134
|
-
const userClaudeMd =
|
|
1553
|
+
const projectClaudeMd = path12.join(repoRoot, "CLAUDE.md");
|
|
1554
|
+
const projectClaudeLocalMd = path12.join(repoRoot, "CLAUDE.local.md");
|
|
1555
|
+
const userClaudeMd = path12.join(userHome, ".claude", "CLAUDE.md");
|
|
1135
1556
|
return {
|
|
1136
1557
|
project_claude_md_chars: readCharsIfExists(projectClaudeMd),
|
|
1137
|
-
project_claude_md_present:
|
|
1558
|
+
project_claude_md_present: fs8.existsSync(projectClaudeMd),
|
|
1138
1559
|
project_claude_local_md_chars: readCharsIfExists(projectClaudeLocalMd),
|
|
1139
|
-
project_claude_local_md_present:
|
|
1560
|
+
project_claude_local_md_present: fs8.existsSync(projectClaudeLocalMd),
|
|
1140
1561
|
user_claude_md_chars: readCharsIfExists(userClaudeMd),
|
|
1141
|
-
user_claude_md_present:
|
|
1562
|
+
user_claude_md_present: fs8.existsSync(userClaudeMd),
|
|
1142
1563
|
user_imports: parseClaudeMdImports(userClaudeMd)
|
|
1143
1564
|
};
|
|
1144
1565
|
}
|
|
@@ -1160,15 +1581,15 @@ function parseFrontmatter(text) {
|
|
|
1160
1581
|
}
|
|
1161
1582
|
}
|
|
1162
1583
|
function censusSkillsCatalog(skillsDir) {
|
|
1163
|
-
if (!
|
|
1584
|
+
if (!fs8.existsSync(skillsDir)) return { skills: 0, chars: 0 };
|
|
1164
1585
|
let skills = 0;
|
|
1165
1586
|
let chars = 0;
|
|
1166
|
-
for (const entry of
|
|
1587
|
+
for (const entry of fs8.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
1167
1588
|
if (!entry.isDirectory()) continue;
|
|
1168
|
-
const skillMd =
|
|
1589
|
+
const skillMd = path12.join(skillsDir, entry.name, "SKILL.md");
|
|
1169
1590
|
let text;
|
|
1170
1591
|
try {
|
|
1171
|
-
text =
|
|
1592
|
+
text = fs8.readFileSync(skillMd, "utf-8");
|
|
1172
1593
|
} catch {
|
|
1173
1594
|
continue;
|
|
1174
1595
|
}
|
|
@@ -1187,14 +1608,14 @@ function defaultOptions2() {
|
|
|
1187
1608
|
format: "text",
|
|
1188
1609
|
repoRoot: REPO_ROOT3,
|
|
1189
1610
|
userHome,
|
|
1190
|
-
userRulesDir:
|
|
1191
|
-
projectRulesDir:
|
|
1192
|
-
skillsDir:
|
|
1611
|
+
userRulesDir: path12.join(userHome, ".claude", "rules"),
|
|
1612
|
+
projectRulesDir: path12.join(REPO_ROOT3, "dist", "agent-src", "rules"),
|
|
1613
|
+
skillsDir: path12.join(REPO_ROOT3, "dist", "agent-src", "skills"),
|
|
1193
1614
|
root: DEFAULT_PROJECTS_ROOT,
|
|
1194
1615
|
maxAgeDays: 14
|
|
1195
1616
|
};
|
|
1196
1617
|
}
|
|
1197
|
-
function
|
|
1618
|
+
function parseArgs4(argv) {
|
|
1198
1619
|
const opts = defaultOptions2();
|
|
1199
1620
|
for (let i = 0; i < argv.length; i++) {
|
|
1200
1621
|
const a = argv[i];
|
|
@@ -1228,7 +1649,7 @@ function buildByteCensus(opts) {
|
|
|
1228
1649
|
files: opts.userRules.files,
|
|
1229
1650
|
chars: opts.userRules.chars,
|
|
1230
1651
|
tokens_estimate: tokensFromChars(opts.userRules.chars),
|
|
1231
|
-
provenance: "
|
|
1652
|
+
provenance: "measured",
|
|
1232
1653
|
basis: "\u03A3 byte size of every .md file in the user-scope rules directory, chars/4."
|
|
1233
1654
|
},
|
|
1234
1655
|
{
|
|
@@ -1236,7 +1657,7 @@ function buildByteCensus(opts) {
|
|
|
1236
1657
|
files: opts.projectRules.files,
|
|
1237
1658
|
chars: opts.projectRules.chars,
|
|
1238
1659
|
tokens_estimate: tokensFromChars(opts.projectRules.chars),
|
|
1239
|
-
provenance: "
|
|
1660
|
+
provenance: "measured",
|
|
1240
1661
|
basis: "\u03A3 byte size of every .md file in the project-scope rules directory, chars/4."
|
|
1241
1662
|
},
|
|
1242
1663
|
{
|
|
@@ -1244,7 +1665,7 @@ function buildByteCensus(opts) {
|
|
|
1244
1665
|
files: claudeMdFiles,
|
|
1245
1666
|
chars: claudeMdChars,
|
|
1246
1667
|
tokens_estimate: tokensFromChars(claudeMdChars),
|
|
1247
|
-
provenance: "
|
|
1668
|
+
provenance: "measured",
|
|
1248
1669
|
basis: 'Byte size of project CLAUDE.md + project CLAUDE.local.md (if present) + user ~/.claude/CLAUDE.md + every file pulled in by a top-level "@<path>" import line in the user CLAUDE.md, chars/4.'
|
|
1249
1670
|
},
|
|
1250
1671
|
{
|
|
@@ -1252,7 +1673,7 @@ function buildByteCensus(opts) {
|
|
|
1252
1673
|
files: opts.globalProfile.present ? 1 : 0,
|
|
1253
1674
|
chars: opts.globalProfile.chars,
|
|
1254
1675
|
tokens_estimate: tokensFromChars(opts.globalProfile.chars),
|
|
1255
|
-
provenance: "
|
|
1676
|
+
provenance: "measured",
|
|
1256
1677
|
basis: opts.globalProfile.present ? `Byte size of ${opts.globalProfile.path}, chars/4.` : "Layer not written yet on this machine (resolveGlobalProfilePath() returned null) \u2014 treated as 0, per the roadmap's own honesty caveat."
|
|
1257
1678
|
},
|
|
1258
1679
|
{
|
|
@@ -1260,7 +1681,7 @@ function buildByteCensus(opts) {
|
|
|
1260
1681
|
files: opts.skillsCatalog.skills,
|
|
1261
1682
|
chars: opts.skillsCatalog.chars,
|
|
1262
1683
|
tokens_estimate: tokensFromChars(opts.skillsCatalog.chars),
|
|
1263
|
-
provenance: "
|
|
1684
|
+
provenance: "measured",
|
|
1264
1685
|
basis: `\u03A3 "- <name>: <description>\\n" over every SKILL.md frontmatter, chars/4 \u2014 the description-text component only; the host's exact on-wire catalog format is not independently file-measurable.`
|
|
1265
1686
|
}
|
|
1266
1687
|
];
|
|
@@ -1273,7 +1694,7 @@ function buildByteCensus(opts) {
|
|
|
1273
1694
|
files: 0,
|
|
1274
1695
|
chars: 0,
|
|
1275
1696
|
tokens_estimate: residualTokens,
|
|
1276
|
-
provenance: "
|
|
1697
|
+
provenance: "estimated",
|
|
1277
1698
|
basis: "measured_cold_start_median minus the sum of the file-measurable buckets above. No local transcript or file carries the request's raw tool-definition JSON or the per-spawn dispatch-prompt text (verified: ~/.claude/projects/**/*.jsonl records only message.usage counts and response content, never the request system/tool payload) \u2014 this bucket exists so the gap is named rather than silently dropped."
|
|
1278
1699
|
});
|
|
1279
1700
|
}
|
|
@@ -1296,6 +1717,15 @@ function buildByteCensus(opts) {
|
|
|
1296
1717
|
}
|
|
1297
1718
|
return {
|
|
1298
1719
|
sources,
|
|
1720
|
+
derived_user_scope: {
|
|
1721
|
+
delivered_files: opts.deliveredRules.delivered.files,
|
|
1722
|
+
delivered_chars: opts.deliveredRules.delivered.chars,
|
|
1723
|
+
delivered_tokens: tokensFromChars(opts.deliveredRules.delivered.chars),
|
|
1724
|
+
package_only_files: opts.deliveredRules.packageOnly.files,
|
|
1725
|
+
package_only_chars: opts.deliveredRules.packageOnly.chars,
|
|
1726
|
+
package_only_tokens: tokensFromChars(opts.deliveredRules.packageOnly.chars),
|
|
1727
|
+
basis: `\u03A3 byte size of every dist/agent-src/rules/*.md whose \`workspaces:\` does not restrict it to the ${MAINTAINER_WORKSPACE} workspace, chars/4 \u2014 computed without reading ~/.claude at all. This is the bucket src/config/preamble-payload-budget.json excludes as "machine-dependent, not CI-checkable", and computing it here is what falsifies that reason. A gap against the measured user-scope row is INSTALL DRIFT (the machine carries an older release), never a defect in either number.`
|
|
1728
|
+
},
|
|
1299
1729
|
measurable_tokens_total: measurableTokensTotal,
|
|
1300
1730
|
grand_total_tokens: grandTotal,
|
|
1301
1731
|
measured_cold_start_median: median3,
|
|
@@ -1317,7 +1747,7 @@ function buildByteCensus(opts) {
|
|
|
1317
1747
|
}
|
|
1318
1748
|
};
|
|
1319
1749
|
}
|
|
1320
|
-
function
|
|
1750
|
+
function buildReport3(opts) {
|
|
1321
1751
|
const userRules = censusRuleDir(opts.userRulesDir);
|
|
1322
1752
|
const projectRules = censusRuleDir(opts.projectRulesDir);
|
|
1323
1753
|
const claudeMd = censusClaudeMdHierarchy(opts.repoRoot, opts.userHome);
|
|
@@ -1325,6 +1755,7 @@ function buildReport2(opts) {
|
|
|
1325
1755
|
const skillsCatalog = censusSkillsCatalog(opts.skillsDir);
|
|
1326
1756
|
const topRules = topRulesByCost(opts.projectRulesDir, 10);
|
|
1327
1757
|
const duplicateScope = censusDuplicateScope(opts.userRulesDir, opts.projectRulesDir);
|
|
1758
|
+
const deliveredRules = censusDeliveredRulePayload(opts.projectRulesDir);
|
|
1328
1759
|
const scan = scanTranscripts({ root: opts.root, maxAgeDays: opts.maxAgeDays });
|
|
1329
1760
|
const coldStart = computeColdStarts(scan.records);
|
|
1330
1761
|
const measuredColdStartMedian = coldStart.legs > 0 ? coldStart.median_first_call_written_or_uncached : null;
|
|
@@ -1336,14 +1767,15 @@ function buildReport2(opts) {
|
|
|
1336
1767
|
skillsCatalog,
|
|
1337
1768
|
topRules,
|
|
1338
1769
|
duplicateScope,
|
|
1770
|
+
deliveredRules,
|
|
1339
1771
|
measuredColdStartMedian,
|
|
1340
1772
|
coldStartLegs: coldStart.legs
|
|
1341
1773
|
});
|
|
1342
1774
|
}
|
|
1343
|
-
function
|
|
1775
|
+
function pct4(v) {
|
|
1344
1776
|
return `${(v * 100).toFixed(1)}%`;
|
|
1345
1777
|
}
|
|
1346
|
-
function
|
|
1778
|
+
function renderText4(r) {
|
|
1347
1779
|
const out = [];
|
|
1348
1780
|
out.push("Preamble byte census (road-to-cache-economy Phase 3, steps 1-2)");
|
|
1349
1781
|
out.push("");
|
|
@@ -1354,11 +1786,22 @@ function renderText2(r) {
|
|
|
1354
1786
|
out.push(` basis: ${s.basis}`);
|
|
1355
1787
|
}
|
|
1356
1788
|
out.push("");
|
|
1789
|
+
const d = r.derived_user_scope;
|
|
1790
|
+
out.push("");
|
|
1791
|
+
out.push("User-scope bucket, DERIVED from the projection (NOT summed \u2014 a second view of a row above):");
|
|
1792
|
+
out.push(
|
|
1793
|
+
` delivered to the global layer: files=${String(d.delivered_files)} chars=${String(d.delivered_chars)} tokens_estimate=${String(d.delivered_tokens)}`
|
|
1794
|
+
);
|
|
1795
|
+
out.push(
|
|
1796
|
+
` package-only (never delivered): files=${String(d.package_only_files)} chars=${String(d.package_only_chars)} tokens_estimate=${String(d.package_only_tokens)}`
|
|
1797
|
+
);
|
|
1798
|
+
out.push(` basis: ${d.basis}`);
|
|
1799
|
+
out.push("");
|
|
1357
1800
|
out.push(`measurable_tokens_total (excludes residual): ${Math.round(r.measurable_tokens_total)}`);
|
|
1358
1801
|
out.push(`grand_total_tokens (includes residual): ${Math.round(r.grand_total_tokens)}`);
|
|
1359
1802
|
if (r.measured_cold_start_median !== null) {
|
|
1360
1803
|
out.push(`measured_cold_start_median: ${Math.round(r.measured_cold_start_median)} (${r.cold_start_legs} legs, this window)`);
|
|
1361
|
-
out.push(`measurable_share_of_median: ${
|
|
1804
|
+
out.push(`measurable_share_of_median: ${pct4(r.measurable_share_of_median)} (the honest, non-tautological number)`);
|
|
1362
1805
|
out.push(
|
|
1363
1806
|
`sum check (grand_total vs median, \xB110%): ${r.within_tolerance ? "PASS" : "FAIL"} \u2014 trivially PASS by construction once the residual bucket exists; see the module doc comment for why.`
|
|
1364
1807
|
);
|
|
@@ -1383,7 +1826,7 @@ function renderText2(r) {
|
|
|
1383
1826
|
out.push("Modelled duplicate-copy removal (MODELLED, not measured):");
|
|
1384
1827
|
if (r.modelled_duplicate_removal.applicable) {
|
|
1385
1828
|
out.push(` modelled_new_median: ${Math.round(r.modelled_duplicate_removal.modelled_new_median)}`);
|
|
1386
|
-
out.push(` modelled_reduction_pct: ${
|
|
1829
|
+
out.push(` modelled_reduction_pct: ${pct4(r.modelled_duplicate_removal.modelled_reduction_pct)}`);
|
|
1387
1830
|
} else {
|
|
1388
1831
|
out.push(` not applicable \u2014 ${r.modelled_duplicate_removal.reason ?? "unknown reason"}`);
|
|
1389
1832
|
}
|
|
@@ -1393,20 +1836,20 @@ function renderText2(r) {
|
|
|
1393
1836
|
out.push("docs/contracts/load-context-budget-model.md. This report does NOT enforce it.");
|
|
1394
1837
|
return out.join("\n");
|
|
1395
1838
|
}
|
|
1396
|
-
function
|
|
1397
|
-
const opts =
|
|
1398
|
-
const report =
|
|
1839
|
+
function main4(argv = process.argv.slice(2)) {
|
|
1840
|
+
const opts = parseArgs4(argv);
|
|
1841
|
+
const report = buildReport3(opts);
|
|
1399
1842
|
if (opts.format === "json") {
|
|
1400
1843
|
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
1401
1844
|
} else {
|
|
1402
|
-
process.stdout.write(
|
|
1845
|
+
process.stdout.write(renderText4(report) + "\n");
|
|
1403
1846
|
}
|
|
1404
1847
|
return 0;
|
|
1405
1848
|
}
|
|
1406
1849
|
var _isBundled = true;
|
|
1407
1850
|
if (!_isBundled && process.argv[1] !== void 0) {
|
|
1408
|
-
const invokedUrl =
|
|
1409
|
-
if (import.meta.url === invokedUrl) process.exit(
|
|
1851
|
+
const invokedUrl = pathToFileURL4(path12.resolve(process.argv[1])).href;
|
|
1852
|
+
if (import.meta.url === invokedUrl) process.exit(main4());
|
|
1410
1853
|
}
|
|
1411
1854
|
|
|
1412
1855
|
// src/scripts/dispatch_economy_report.ts
|
|
@@ -1414,20 +1857,20 @@ var dispatch_economy_report_exports = {};
|
|
|
1414
1857
|
__export(dispatch_economy_report_exports, {
|
|
1415
1858
|
DEFAULT_AUDIT_DIR: () => DEFAULT_AUDIT_DIR,
|
|
1416
1859
|
DEFAULT_PROJECTS_ROOT: () => DEFAULT_PROJECTS_ROOT,
|
|
1417
|
-
buildReport: () =>
|
|
1860
|
+
buildReport: () => buildReport4,
|
|
1418
1861
|
computeLegs: () => computeLegs,
|
|
1419
|
-
main: () =>
|
|
1862
|
+
main: () => main5,
|
|
1420
1863
|
median: () => median2,
|
|
1421
1864
|
readAuditOrchestrations: () => readAuditOrchestrations,
|
|
1422
|
-
renderText: () =>
|
|
1865
|
+
renderText: () => renderText5
|
|
1423
1866
|
});
|
|
1424
|
-
import * as
|
|
1425
|
-
import * as
|
|
1426
|
-
import { fileURLToPath as fileURLToPath4, pathToFileURL as
|
|
1867
|
+
import * as fs9 from "node:fs";
|
|
1868
|
+
import * as path13 from "node:path";
|
|
1869
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL5 } from "node:url";
|
|
1427
1870
|
var _HERE4 = fileURLToPath4(import.meta.url);
|
|
1428
|
-
var REPO_ROOT4 =
|
|
1429
|
-
var REGISTRATION_FILE =
|
|
1430
|
-
var DEFAULT_AUDIT_DIR =
|
|
1871
|
+
var REPO_ROOT4 = path13.resolve(path13.dirname(_HERE4), "..", "..");
|
|
1872
|
+
var REGISTRATION_FILE = path13.join(REPO_ROOT4, "src", "config", "dispatch-economy-metrics.json");
|
|
1873
|
+
var DEFAULT_AUDIT_DIR = path13.join("agents", "runtime", "state", "audit");
|
|
1431
1874
|
var REVIEWER_TYPE_RE = /review|judge|validator/i;
|
|
1432
1875
|
function median2(values) {
|
|
1433
1876
|
if (values.length === 0) return null;
|
|
@@ -1473,19 +1916,19 @@ function isFiniteNonNegInt(v) {
|
|
|
1473
1916
|
return typeof v === "number" && Number.isInteger(v) && v >= 0;
|
|
1474
1917
|
}
|
|
1475
1918
|
function readAuditOrchestrations(auditDir, opts = {}) {
|
|
1476
|
-
if (!
|
|
1919
|
+
if (!fs9.existsSync(auditDir)) return [];
|
|
1477
1920
|
const out = [];
|
|
1478
1921
|
const cutoffMs = opts.maxAgeDays !== void 0 ? (opts.now ?? /* @__PURE__ */ new Date()).getTime() - opts.maxAgeDays * 24 * 60 * 60 * 1e3 : null;
|
|
1479
1922
|
let entries;
|
|
1480
1923
|
try {
|
|
1481
|
-
entries =
|
|
1924
|
+
entries = fs9.readdirSync(auditDir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
1482
1925
|
} catch {
|
|
1483
1926
|
return [];
|
|
1484
1927
|
}
|
|
1485
1928
|
if (cutoffMs !== null) {
|
|
1486
1929
|
entries = entries.filter((f) => {
|
|
1487
1930
|
try {
|
|
1488
|
-
return
|
|
1931
|
+
return fs9.statSync(path13.join(auditDir, f)).mtimeMs >= cutoffMs;
|
|
1489
1932
|
} catch {
|
|
1490
1933
|
return false;
|
|
1491
1934
|
}
|
|
@@ -1494,7 +1937,7 @@ function readAuditOrchestrations(auditDir, opts = {}) {
|
|
|
1494
1937
|
for (const f of entries) {
|
|
1495
1938
|
let text;
|
|
1496
1939
|
try {
|
|
1497
|
-
text =
|
|
1940
|
+
text = fs9.readFileSync(path13.join(auditDir, f), "utf8");
|
|
1498
1941
|
} catch {
|
|
1499
1942
|
continue;
|
|
1500
1943
|
}
|
|
@@ -1515,8 +1958,8 @@ function readAuditOrchestrations(auditDir, opts = {}) {
|
|
|
1515
1958
|
}
|
|
1516
1959
|
return out;
|
|
1517
1960
|
}
|
|
1518
|
-
function
|
|
1519
|
-
const registrationRaw =
|
|
1961
|
+
function buildReport4(opts) {
|
|
1962
|
+
const registrationRaw = fs9.readFileSync(REGISTRATION_FILE, "utf8");
|
|
1520
1963
|
const registration = JSON.parse(registrationRaw);
|
|
1521
1964
|
const scanOpts = {
|
|
1522
1965
|
root: opts.root,
|
|
@@ -1617,7 +2060,7 @@ function fmtTokens(n) {
|
|
|
1617
2060
|
if (n === null) return "\u2014";
|
|
1618
2061
|
return n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : String(Math.round(n));
|
|
1619
2062
|
}
|
|
1620
|
-
function
|
|
2063
|
+
function renderText5(r) {
|
|
1621
2064
|
const lines = [];
|
|
1622
2065
|
lines.push("dispatch-economy report (registered: " + r.registration.registered_at + " \xB7 review by: " + r.registration.review_by + ")");
|
|
1623
2066
|
lines.push(`window: ${r.window.max_age_days}d \xB7 ${r.window.transcript_records} deduped records \xB7 ${r.window.legs} legs`);
|
|
@@ -1651,10 +2094,10 @@ function renderText3(r) {
|
|
|
1651
2094
|
for (const n of r.notes) lines.push(`note: ${n}`);
|
|
1652
2095
|
return lines.join("\n") + "\n";
|
|
1653
2096
|
}
|
|
1654
|
-
function
|
|
2097
|
+
function main5(argv) {
|
|
1655
2098
|
let format = "text";
|
|
1656
2099
|
let root = DEFAULT_PROJECTS_ROOT;
|
|
1657
|
-
let auditDir =
|
|
2100
|
+
let auditDir = path13.join(process.cwd(), DEFAULT_AUDIT_DIR);
|
|
1658
2101
|
let maxAgeDays = 14;
|
|
1659
2102
|
for (let i = 0; i < argv.length; i++) {
|
|
1660
2103
|
const a = argv[i];
|
|
@@ -1665,38 +2108,572 @@ function main3(argv) {
|
|
|
1665
2108
|
}
|
|
1666
2109
|
let report;
|
|
1667
2110
|
try {
|
|
1668
|
-
report =
|
|
2111
|
+
report = buildReport4({ root, auditDir, maxAgeDays });
|
|
1669
2112
|
} catch (err) {
|
|
1670
2113
|
process.stderr.write(`dispatch_economy_report: ${err instanceof Error ? err.message : String(err)}
|
|
1671
2114
|
`);
|
|
1672
2115
|
return 2;
|
|
1673
2116
|
}
|
|
1674
|
-
process.stdout.write(format === "json" ? JSON.stringify(report, null, 2) + "\n" :
|
|
2117
|
+
process.stdout.write(format === "json" ? JSON.stringify(report, null, 2) + "\n" : renderText5(report));
|
|
1675
2118
|
return 0;
|
|
1676
2119
|
}
|
|
1677
2120
|
function _isCliEntry() {
|
|
1678
2121
|
if (true) return false;
|
|
1679
2122
|
if (process.argv[1] === void 0) return false;
|
|
1680
|
-
const argvUrl =
|
|
2123
|
+
const argvUrl = pathToFileURL5(path13.resolve(process.argv[1])).href;
|
|
1681
2124
|
if (import.meta.url === argvUrl) return true;
|
|
1682
2125
|
try {
|
|
1683
|
-
return
|
|
2126
|
+
return fs9.realpathSync(fileURLToPath4(import.meta.url)) === fs9.realpathSync(path13.resolve(process.argv[1]));
|
|
2127
|
+
} catch {
|
|
2128
|
+
return false;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
if (_isCliEntry()) process.exit(main5(process.argv.slice(2)));
|
|
2132
|
+
|
|
2133
|
+
// src/scripts/_lib/runtime_wiring_checks.ts
|
|
2134
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
2135
|
+
import * as fs10 from "node:fs";
|
|
2136
|
+
import * as path14 from "node:path";
|
|
2137
|
+
import process2 from "node:process";
|
|
2138
|
+
|
|
2139
|
+
// src/scripts/_lib/repo_root.ts
|
|
2140
|
+
var GIT_DISCOVERY_OVERRIDES = [
|
|
2141
|
+
"GIT_DIR",
|
|
2142
|
+
"GIT_WORK_TREE",
|
|
2143
|
+
"GIT_INDEX_FILE",
|
|
2144
|
+
"GIT_COMMON_DIR"
|
|
2145
|
+
];
|
|
2146
|
+
function inheritedGitOverrides(env = process.env) {
|
|
2147
|
+
const out = [];
|
|
2148
|
+
for (const name of GIT_DISCOVERY_OVERRIDES) {
|
|
2149
|
+
const value = env[name];
|
|
2150
|
+
if (typeof value === "string" && value !== "") out.push({ name, value });
|
|
2151
|
+
}
|
|
2152
|
+
return out;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
// src/scripts/_lib/runtime_wiring_checks.ts
|
|
2156
|
+
function checkSettingsResolution(iterOverrides) {
|
|
2157
|
+
let pairs;
|
|
2158
|
+
try {
|
|
2159
|
+
pairs = [...iterOverrides()];
|
|
2160
|
+
} catch (e) {
|
|
2161
|
+
return {
|
|
2162
|
+
id: "settings-resolution",
|
|
2163
|
+
status: "fail",
|
|
2164
|
+
message: `settings cascade did not resolve: ${e instanceof Error ? e.message : String(e)}`,
|
|
2165
|
+
remedy: "check the YAML in every layer `agent-config settings:get <key>` reports"
|
|
2166
|
+
};
|
|
2167
|
+
}
|
|
2168
|
+
if (pairs.length === 0) {
|
|
2169
|
+
return {
|
|
2170
|
+
id: "settings-resolution",
|
|
2171
|
+
// `skipped`, not `ok`: the cascade RESOLVED and there was nothing
|
|
2172
|
+
// in it, which is a check that had nothing to inspect rather than a
|
|
2173
|
+
// check that passed. Reporting `ok` here would read as "settings
|
|
2174
|
+
// resolved fine" on a tree where no setting exists at all — the
|
|
2175
|
+
// same conflation the reach check exists to remove elsewhere.
|
|
2176
|
+
status: "skipped",
|
|
2177
|
+
message: "settings cascade resolves, and NO layer sets any key \u2014 every read falls to the template default. That is a valid state, not a failure: a fresh project has no settings.",
|
|
2178
|
+
remedy: ""
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
const winner = /* @__PURE__ */ new Map();
|
|
2182
|
+
for (const [key, , file] of pairs) winner.set(key, file);
|
|
2183
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
2184
|
+
for (const file of winner.values()) byFile.set(file, (byFile.get(file) ?? 0) + 1);
|
|
2185
|
+
const summary = [...byFile.entries()].sort((a, b) => b[1] - a[1]).map(([f, n]) => `${path14.basename(f)}=${String(n)}`).join(" \xB7 ");
|
|
2186
|
+
return {
|
|
2187
|
+
id: "settings-resolution",
|
|
2188
|
+
status: "ok",
|
|
2189
|
+
message: `${String(winner.size)} key(s) resolved across ${String(byFile.size)} layer(s) \u2014 ${summary}`,
|
|
2190
|
+
remedy: ""
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
function checkRouterArtifact(repoRoot, rel = "dist/router.json") {
|
|
2194
|
+
const abs = path14.join(repoRoot, rel);
|
|
2195
|
+
if (!fs10.existsSync(abs)) {
|
|
2196
|
+
return {
|
|
2197
|
+
id: "router-artifact",
|
|
2198
|
+
status: "warn",
|
|
2199
|
+
message: `${rel} is absent \u2014 no rule router is deployed`,
|
|
2200
|
+
remedy: "task generate-tools"
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
let doc;
|
|
2204
|
+
try {
|
|
2205
|
+
doc = JSON.parse(fs10.readFileSync(abs, "utf8"));
|
|
2206
|
+
} catch (e) {
|
|
2207
|
+
return {
|
|
2208
|
+
id: "router-artifact",
|
|
2209
|
+
status: "fail",
|
|
2210
|
+
message: `${rel} exists but does NOT parse: ${e instanceof Error ? e.message : String(e)}`,
|
|
2211
|
+
remedy: "task generate-tools (a present-but-unparseable router loads as zero rules)"
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
const rules = _routerRuleCount(doc);
|
|
2215
|
+
if (rules === 0) {
|
|
2216
|
+
return {
|
|
2217
|
+
id: "router-artifact",
|
|
2218
|
+
status: "warn",
|
|
2219
|
+
message: `${rel} parses and carries ZERO rules \u2014 a router with no rules routes nothing`,
|
|
2220
|
+
remedy: "task generate-tools"
|
|
2221
|
+
};
|
|
2222
|
+
}
|
|
2223
|
+
return { id: "router-artifact", status: "ok", message: `${rel} parses \xB7 ${String(rules)} rule(s)`, remedy: "" };
|
|
2224
|
+
}
|
|
2225
|
+
function _routerRuleCount(doc) {
|
|
2226
|
+
if (doc === null || typeof doc !== "object") return 0;
|
|
2227
|
+
const d = doc;
|
|
2228
|
+
if (Array.isArray(d["rules"])) return d["rules"].length;
|
|
2229
|
+
let n = 0;
|
|
2230
|
+
for (const v of Object.values(d)) {
|
|
2231
|
+
if (Array.isArray(v)) n += v.length;
|
|
2232
|
+
else if (v !== null && typeof v === "object") n += _routerRuleCount(v);
|
|
2233
|
+
}
|
|
2234
|
+
return n;
|
|
2235
|
+
}
|
|
2236
|
+
function checkHookResolution(repoRoot, manifestRel = "src/scripts/hook_manifest.yaml", probe = null) {
|
|
2237
|
+
const abs = path14.join(repoRoot, manifestRel);
|
|
2238
|
+
if (!fs10.existsSync(abs)) {
|
|
2239
|
+
return {
|
|
2240
|
+
check: {
|
|
2241
|
+
id: "hook-resolution",
|
|
2242
|
+
status: "fail",
|
|
2243
|
+
message: `${manifestRel} is absent \u2014 the hook estate cannot be enumerated`,
|
|
2244
|
+
remedy: "restore the manifest; every hook is registered from it"
|
|
2245
|
+
},
|
|
2246
|
+
probes: []
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
let concerns;
|
|
2250
|
+
try {
|
|
2251
|
+
const doc = (0, import_yaml.parse)(fs10.readFileSync(abs, "utf8"));
|
|
2252
|
+
concerns = doc.concerns ?? {};
|
|
2253
|
+
} catch (e) {
|
|
2254
|
+
return {
|
|
2255
|
+
check: {
|
|
2256
|
+
id: "hook-resolution",
|
|
2257
|
+
status: "fail",
|
|
2258
|
+
message: `${manifestRel} does not parse: ${e instanceof Error ? e.message : String(e)}`,
|
|
2259
|
+
remedy: "fix the manifest YAML"
|
|
2260
|
+
},
|
|
2261
|
+
probes: []
|
|
2262
|
+
};
|
|
2263
|
+
}
|
|
2264
|
+
const probes = [];
|
|
2265
|
+
for (const [id, c] of Object.entries(concerns)) {
|
|
2266
|
+
const script = typeof c.script === "string" ? c.script : "";
|
|
2267
|
+
const resolves = script !== "" && fs10.existsSync(path14.join(repoRoot, script));
|
|
2268
|
+
probes.push({ id, script, resolves, ms: resolves && probe !== null ? probe(script) : null });
|
|
2269
|
+
}
|
|
2270
|
+
const broken = probes.filter((p) => !p.resolves);
|
|
2271
|
+
if (broken.length > 0) {
|
|
2272
|
+
return {
|
|
2273
|
+
check: {
|
|
2274
|
+
id: "hook-resolution",
|
|
2275
|
+
status: "fail",
|
|
2276
|
+
message: `${String(broken.length)} of ${String(probes.length)} registered hook(s) do NOT resolve to a file: ` + broken.map((b) => b.id).join(", "),
|
|
2277
|
+
remedy: "a registered hook with no script silently no-ops every session \u2014 fix the path or drop the entry"
|
|
2278
|
+
},
|
|
2279
|
+
probes
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
const timed = probes.filter((p) => p.ms !== null).sort((a, b) => (b.ms ?? 0) - (a.ms ?? 0));
|
|
2283
|
+
const slowest = timed.length > 0 ? ` \xB7 slowest ${timed[0].id} ${String(timed[0].ms)}ms` : "";
|
|
2284
|
+
return {
|
|
2285
|
+
check: {
|
|
2286
|
+
id: "hook-resolution",
|
|
2287
|
+
status: "ok",
|
|
2288
|
+
message: `${String(probes.length)} registered hook(s), all resolving${slowest}`,
|
|
2289
|
+
remedy: ""
|
|
2290
|
+
},
|
|
2291
|
+
probes
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2294
|
+
function checkInheritedGitEnv(env = process2.env) {
|
|
2295
|
+
const found = inheritedGitOverrides(env);
|
|
2296
|
+
if (found.length === 0) {
|
|
2297
|
+
return {
|
|
2298
|
+
id: "inherited-git-env",
|
|
2299
|
+
status: "ok",
|
|
2300
|
+
message: "no git discovery override in the environment \u2014 git resolves from the working directory",
|
|
2301
|
+
remedy: ""
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
return {
|
|
2305
|
+
id: "inherited-git-env",
|
|
2306
|
+
status: "warn",
|
|
2307
|
+
message: `${String(found.length)} git discovery override(s) inherited: ` + found.map((f) => `${f.name}=${f.value}`).join(" \xB7 ") + " \u2014 every git call in this process answers for THAT repository, not the working directory",
|
|
2308
|
+
remedy: "unset them before running a gate from inside a git hook (`env -u GIT_DIR -u GIT_WORK_TREE \u2026`), or resolve the root with _lib/repo_root.ts, which refuses instead of guessing"
|
|
2309
|
+
};
|
|
2310
|
+
}
|
|
2311
|
+
var WIRING_CHECK_IDS = ["settings-resolution", "router-artifact", "hook-resolution", "inherited-git-env", "hooks-kill-switch"];
|
|
2312
|
+
function checkHooksDisabled(env = process2.env) {
|
|
2313
|
+
const raw = env["AGENT_CONFIG_DISABLE_HOOKS"];
|
|
2314
|
+
if (raw !== "1") {
|
|
2315
|
+
return {
|
|
2316
|
+
id: "hooks-kill-switch",
|
|
2317
|
+
status: "ok",
|
|
2318
|
+
message: raw === void 0 || raw === "" ? "AGENT_CONFIG_DISABLE_HOOKS is not set \u2014 the hook estate is armed" : `AGENT_CONFIG_DISABLE_HOOKS=${raw} \u2014 only the exact value "1" disarms, so the estate is armed`,
|
|
2319
|
+
remedy: ""
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
return {
|
|
2323
|
+
id: "hooks-kill-switch",
|
|
2324
|
+
status: "warn",
|
|
2325
|
+
message: "AGENT_CONFIG_DISABLE_HOOKS=1 \u2014 EVERY hook and shim in this environment is disabled. A run under this flag enforces nothing, and without this line it would look identical to one with the whole estate armed.",
|
|
2326
|
+
remedy: "unset AGENT_CONFIG_DISABLE_HOOKS (it is intended for one command, not a session)"
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
function wiringRunners(opts) {
|
|
2330
|
+
return {
|
|
2331
|
+
"settings-resolution": () => checkSettingsResolution(opts.iterOverrides),
|
|
2332
|
+
"router-artifact": () => checkRouterArtifact(opts.packageRoot),
|
|
2333
|
+
// Per-hook COST is not probed on the default path: it spawns one process
|
|
2334
|
+
// per registered concern (53 today), turning a read-only diagnostic into
|
|
2335
|
+
// a multi-second one. `probeHookCost` is exported for a caller that wants it.
|
|
2336
|
+
"hook-resolution": () => checkHookResolution(opts.packageRoot).check,
|
|
2337
|
+
"inherited-git-env": () => checkInheritedGitEnv(),
|
|
2338
|
+
"hooks-kill-switch": () => checkHooksDisabled()
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
function checkHookWiring(deps) {
|
|
2342
|
+
const claude = deps.which("claude");
|
|
2343
|
+
if (claude === null) {
|
|
2344
|
+
return {
|
|
2345
|
+
id: "hook-wiring",
|
|
2346
|
+
status: "skipped",
|
|
2347
|
+
message: "Claude Code CLI not on PATH \u2014 hook-wiring check not applicable",
|
|
2348
|
+
remedy: ""
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
2351
|
+
const settings_path = path14.join(deps.homeDir, ".claude", "settings.json");
|
|
2352
|
+
let missing;
|
|
2353
|
+
try {
|
|
2354
|
+
const matrix = deps.buildMatrix(path14.join(deps.packageRoot, "src", "scripts", "hook_manifest.yaml"));
|
|
2355
|
+
const settings = fs10.existsSync(settings_path) ? JSON.parse(fs10.readFileSync(settings_path, "utf8")) : {};
|
|
2356
|
+
const hooks = (settings["hooks"] ?? {}) || {};
|
|
2357
|
+
missing = Object.keys(matrix).filter((ev) => {
|
|
2358
|
+
const groups = hooks[ev];
|
|
2359
|
+
if (!Array.isArray(groups)) return true;
|
|
2360
|
+
return !JSON.stringify(groups).includes(deps.managedSignature);
|
|
2361
|
+
});
|
|
2362
|
+
} catch (e) {
|
|
2363
|
+
return {
|
|
2364
|
+
id: "hook-wiring",
|
|
2365
|
+
status: "fail",
|
|
2366
|
+
message: `cannot evaluate managed hooks: ${String(e)}`,
|
|
2367
|
+
remedy: "fix ~/.claude/settings.json (invalid JSON?), then agent-config refresh --global"
|
|
2368
|
+
};
|
|
2369
|
+
}
|
|
2370
|
+
const binary_ok = deps.which("agent-config") !== null;
|
|
2371
|
+
if (missing.length === 0 && binary_ok) {
|
|
2372
|
+
return {
|
|
2373
|
+
id: "hook-wiring",
|
|
2374
|
+
status: "ok",
|
|
2375
|
+
message: "managed hooks registered in ~/.claude/settings.json; dispatch binary on PATH",
|
|
2376
|
+
remedy: ""
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
if (missing.length > 0 && deps.pluginInstalled()) {
|
|
2380
|
+
return {
|
|
2381
|
+
id: "hook-wiring",
|
|
2382
|
+
status: "warn",
|
|
2383
|
+
message: `managed hooks missing for: ${missing.join(", ")} \u2014 currently carried by the installed plugin (deprecated surface)`,
|
|
2384
|
+
remedy: "agent-config refresh --global (writes the managed settings.json block)"
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
const parts = [];
|
|
2388
|
+
if (missing.length > 0) parts.push(`managed hooks missing for: ${missing.join(", ")}`);
|
|
2389
|
+
if (!binary_ok) parts.push("`agent-config` not on PATH (hooks would silently no-op)");
|
|
2390
|
+
if (parts.length === 0) {
|
|
2391
|
+
parts.push("`agent-config` not on PATH");
|
|
2392
|
+
}
|
|
2393
|
+
return {
|
|
2394
|
+
id: "hook-wiring",
|
|
2395
|
+
status: "fail",
|
|
2396
|
+
message: parts.join("; "),
|
|
2397
|
+
remedy: binary_ok ? "agent-config refresh --global" : "npm install -g @event4u/agent-config, then agent-config refresh --global"
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
// src/scripts/_lib/install_reach_checks.ts
|
|
2402
|
+
import * as fs11 from "node:fs";
|
|
2403
|
+
import * as path15 from "node:path";
|
|
2404
|
+
var ROOT_INSTRUCTION_FILES = [
|
|
2405
|
+
"AGENTS.md",
|
|
2406
|
+
"CLAUDE.md",
|
|
2407
|
+
"GEMINI.md",
|
|
2408
|
+
".github/copilot-instructions.md"
|
|
2409
|
+
];
|
|
2410
|
+
var UNRESOLVABLE_REASONS = [
|
|
2411
|
+
{ test: (s) => /^[a-z][a-z0-9+.-]*:\/\//i.test(s), reason: "a URL, not a repository path" },
|
|
2412
|
+
{ test: (s) => s.startsWith("/"), reason: "absolute \u2014 outside the repository root this checker resolves against" },
|
|
2413
|
+
{ test: (s) => s.startsWith("~"), reason: "home-relative \u2014 resolves per machine, not per repository" },
|
|
2414
|
+
{ test: (s) => s.includes("*") || s.includes("?") || s.includes("["), reason: "a glob, which names a set rather than a path" },
|
|
2415
|
+
{ test: (s) => s.includes("<") || s.includes(">") || s.includes("{"), reason: "carries a placeholder, so no single path is named" },
|
|
2416
|
+
{ test: (s) => s.startsWith(".."), reason: "escapes the repository root" },
|
|
2417
|
+
{
|
|
2418
|
+
// `archive/`, `skipped/` — written inside prose that already established
|
|
2419
|
+
// a parent directory. Read from the repository root they are wrong, and
|
|
2420
|
+
// reporting them dangling would blame the tree for the checker's missing
|
|
2421
|
+
// context. Their parent is knowable to a reader and not to this parser.
|
|
2422
|
+
test: (s) => /^[^/]+\/$/.test(s),
|
|
2423
|
+
reason: "a bare directory reference \u2014 the prose around it names the parent, this parser does not"
|
|
2424
|
+
}
|
|
2425
|
+
];
|
|
2426
|
+
var BACKTICKED = /`([^`\n]+)`/g;
|
|
2427
|
+
var LINK_TARGET = /\]\(([^)\s]+)\)/g;
|
|
2428
|
+
var EXTENSION = /\.[A-Za-z0-9]{1,8}$/;
|
|
2429
|
+
function _isAnchored(projectRoot, token) {
|
|
2430
|
+
if (token.startsWith("./") || token.startsWith("../") || token.startsWith("/") || token.startsWith(".")) return true;
|
|
2431
|
+
if (token.endsWith("/")) return true;
|
|
2432
|
+
if (EXTENSION.test(token)) return true;
|
|
2433
|
+
const first = token.split("/")[0];
|
|
2434
|
+
if (first === void 0 || first === "" || first === token) return false;
|
|
2435
|
+
try {
|
|
2436
|
+
return fs11.statSync(path15.join(projectRoot, first)).isDirectory();
|
|
1684
2437
|
} catch {
|
|
1685
2438
|
return false;
|
|
1686
2439
|
}
|
|
1687
2440
|
}
|
|
1688
|
-
|
|
2441
|
+
function _looksLikePath(projectRoot, token) {
|
|
2442
|
+
const t = token.trim();
|
|
2443
|
+
if (t === "") return false;
|
|
2444
|
+
if (/\s/.test(t)) return false;
|
|
2445
|
+
if (t.startsWith("-")) return false;
|
|
2446
|
+
if (!t.includes("/")) return false;
|
|
2447
|
+
return _isAnchored(projectRoot, t);
|
|
2448
|
+
}
|
|
2449
|
+
function extractNamedPaths(projectRoot, source, text) {
|
|
2450
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2451
|
+
const out = [];
|
|
2452
|
+
for (const re of [BACKTICKED, LINK_TARGET]) {
|
|
2453
|
+
re.lastIndex = 0;
|
|
2454
|
+
let m;
|
|
2455
|
+
while ((m = re.exec(text)) !== null) {
|
|
2456
|
+
if (re === BACKTICKED && text.slice(m.index + m[0].length, m.index + m[0].length + 2) === "](") continue;
|
|
2457
|
+
const raw = (m[1] ?? "").trim();
|
|
2458
|
+
if (!_looksLikePath(projectRoot, raw) || seen.has(raw)) continue;
|
|
2459
|
+
seen.add(raw);
|
|
2460
|
+
out.push({ source, raw, normalised: null, outcome: "unresolvable" });
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
return out;
|
|
2464
|
+
}
|
|
2465
|
+
function classifyNamedPath(projectRoot, entry) {
|
|
2466
|
+
for (const { test, reason } of UNRESOLVABLE_REASONS) {
|
|
2467
|
+
if (test(entry.raw)) return { ...entry, normalised: null, outcome: "unresolvable", reason };
|
|
2468
|
+
}
|
|
2469
|
+
const rel = entry.raw.replace(/^\.\//, "").replace(/\/$/, "");
|
|
2470
|
+
if (rel === "") {
|
|
2471
|
+
return { ...entry, normalised: null, outcome: "unresolvable", reason: "empty after normalisation" };
|
|
2472
|
+
}
|
|
2473
|
+
const abs = path15.join(projectRoot, rel);
|
|
2474
|
+
if (!path15.resolve(abs).startsWith(path15.resolve(projectRoot))) {
|
|
2475
|
+
return { ...entry, normalised: rel, outcome: "unresolvable", reason: "escapes the repository root" };
|
|
2476
|
+
}
|
|
2477
|
+
return { ...entry, normalised: rel, outcome: fs11.existsSync(abs) ? "present" : "dangling" };
|
|
2478
|
+
}
|
|
2479
|
+
function resolveInstructionPaths(projectRoot) {
|
|
2480
|
+
const out = [];
|
|
2481
|
+
for (const rel of ROOT_INSTRUCTION_FILES) {
|
|
2482
|
+
const abs = path15.join(projectRoot, rel);
|
|
2483
|
+
let text;
|
|
2484
|
+
try {
|
|
2485
|
+
text = fs11.readFileSync(abs, "utf8");
|
|
2486
|
+
} catch {
|
|
2487
|
+
continue;
|
|
2488
|
+
}
|
|
2489
|
+
for (const entry of extractNamedPaths(projectRoot, rel, text)) {
|
|
2490
|
+
out.push(classifyNamedPath(projectRoot, entry));
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
return out;
|
|
2494
|
+
}
|
|
2495
|
+
function checkInstructionPaths(projectRoot) {
|
|
2496
|
+
const id = "instruction-path-reach";
|
|
2497
|
+
const named = resolveInstructionPaths(projectRoot);
|
|
2498
|
+
if (named.length === 0) {
|
|
2499
|
+
return {
|
|
2500
|
+
id,
|
|
2501
|
+
status: "skipped",
|
|
2502
|
+
message: "no root instruction file names a repository path \u2014 nothing to resolve",
|
|
2503
|
+
remedy: ""
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
const dangling = named.filter((n) => n.outcome === "dangling");
|
|
2507
|
+
const unresolvable = named.filter((n) => n.outcome === "unresolvable");
|
|
2508
|
+
const present = named.length - dangling.length - unresolvable.length;
|
|
2509
|
+
const tail = unresolvable.length === 0 ? "" : ` ${unresolvable.length} path(s) THIS CHECKER could not interpret, which is not the same as absent: ` + unresolvable.map((n) => `${n.source} \u2192 ${n.raw} (${n.reason ?? "no reason recorded"})`).join("; ");
|
|
2510
|
+
if (dangling.length === 0) {
|
|
2511
|
+
return {
|
|
2512
|
+
id,
|
|
2513
|
+
status: "ok",
|
|
2514
|
+
message: `${present} instruction-file path(s) resolve.${tail}`,
|
|
2515
|
+
remedy: ""
|
|
2516
|
+
};
|
|
2517
|
+
}
|
|
2518
|
+
return {
|
|
2519
|
+
id,
|
|
2520
|
+
status: "fail",
|
|
2521
|
+
message: `${dangling.length} path(s) named by a root instruction file do NOT exist: ` + dangling.map((n) => `${n.source} \u2192 ${n.raw}`).join("; ") + `. ${present} resolved.${tail} An instruction file that over-reports is read as fact: every routing decision downstream of a dangling path is made against a layer that is not there. See rule \`instruction-path-verification\`.`,
|
|
2522
|
+
remedy: "install the missing layer, or delete the claim from the instruction file \u2014 a path named is a promise"
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
var SETTINGS_PIN_FILES = [
|
|
2526
|
+
{ rel: path15.join("agents", "settings", ".agent-settings.yml"), legacy: false },
|
|
2527
|
+
{ rel: ".agent-settings.yml", legacy: true },
|
|
2528
|
+
{ rel: ".agent-project-settings.yml", legacy: true },
|
|
2529
|
+
{ rel: "agent-settings.yml", legacy: true }
|
|
2530
|
+
];
|
|
2531
|
+
var PIN_RE = /^\s*(?:agent_config_version|version)\s*:\s*"?([^"'\s]+)"?\s*$/m;
|
|
2532
|
+
var LOCK_VERSION_RE = /^\s*agent_config_version\s*:\s*"?([^"\s]+)"?\s*$/m;
|
|
2533
|
+
function readVersionPins(projectRoot) {
|
|
2534
|
+
const out = [];
|
|
2535
|
+
for (const { rel, legacy } of SETTINGS_PIN_FILES) {
|
|
2536
|
+
let text;
|
|
2537
|
+
try {
|
|
2538
|
+
text = fs11.readFileSync(path15.join(projectRoot, rel), "utf8");
|
|
2539
|
+
} catch {
|
|
2540
|
+
continue;
|
|
2541
|
+
}
|
|
2542
|
+
const m = PIN_RE.exec(text);
|
|
2543
|
+
if (m?.[1] !== void 0) out.push({ file: rel, legacy, version: m[1] });
|
|
2544
|
+
}
|
|
2545
|
+
return out;
|
|
2546
|
+
}
|
|
2547
|
+
function readInstalledVersion(projectRoot) {
|
|
2548
|
+
try {
|
|
2549
|
+
const text = fs11.readFileSync(path15.join(projectRoot, "agents", "installed-tools.lock"), "utf8");
|
|
2550
|
+
return LOCK_VERSION_RE.exec(text)?.[1] ?? null;
|
|
2551
|
+
} catch {
|
|
2552
|
+
return null;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
function checkVersionAxis(projectRoot, resolvableNow) {
|
|
2556
|
+
const id = "version-axis";
|
|
2557
|
+
const pins = readVersionPins(projectRoot);
|
|
2558
|
+
const installed = readInstalledVersion(projectRoot);
|
|
2559
|
+
if (pins.length === 0 && installed === null) {
|
|
2560
|
+
return { id, status: "skipped", message: "no version pin and no install lockfile in this tree", remedy: "" };
|
|
2561
|
+
}
|
|
2562
|
+
const pinText = pins.length === 0 ? "pinned: none" : `pinned: ${pins.map((p) => `${p.version} (${p.file}${p.legacy ? ", LEGACY filename" : ""})`).join(" \xB7 ")}`;
|
|
2563
|
+
const line = `${pinText} \xB7 installed: ${installed ?? "unknown"} \xB7 resolvable now: ${resolvableNow ?? "unknown"}`;
|
|
2564
|
+
const divergent = pins.filter((p) => installed !== null && p.version !== installed);
|
|
2565
|
+
if (divergent.length === 0) {
|
|
2566
|
+
return { id, status: "ok", message: line, remedy: "" };
|
|
2567
|
+
}
|
|
2568
|
+
return {
|
|
2569
|
+
id,
|
|
2570
|
+
status: "warn",
|
|
2571
|
+
message: `${line} \u2014 ${divergent.length} pin(s) disagree with the installed projection. A pin behind the installed tree is ordinary manifest-versus-lockfile drift, and it is only visible as a comparison: each number alone reads as correct.`,
|
|
2572
|
+
remedy: "reconcile the pin with the installed version, or migrate a legacy settings file into the canonical location"
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2575
|
+
var OVERRIDE_LAYERS = [
|
|
2576
|
+
path15.join("agents", "overrides"),
|
|
2577
|
+
path15.join(".agent", "overrides")
|
|
2578
|
+
];
|
|
2579
|
+
var KIND_DIRS = [
|
|
2580
|
+
{ dir: "rules", kind: "rule" },
|
|
2581
|
+
{ dir: "skills", kind: "skill" },
|
|
2582
|
+
{ dir: "commands", kind: "command" }
|
|
2583
|
+
];
|
|
2584
|
+
function collectOverrideSet(projectRoot) {
|
|
2585
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2586
|
+
for (const layer of OVERRIDE_LAYERS) {
|
|
2587
|
+
for (const { dir, kind } of KIND_DIRS) {
|
|
2588
|
+
let entries;
|
|
2589
|
+
try {
|
|
2590
|
+
entries = fs11.readdirSync(path15.join(projectRoot, layer, dir));
|
|
2591
|
+
} catch {
|
|
2592
|
+
continue;
|
|
2593
|
+
}
|
|
2594
|
+
for (const entry of entries) {
|
|
2595
|
+
const name = entry.replace(/\.md$/, "");
|
|
2596
|
+
if (name === "" || name.startsWith(".")) continue;
|
|
2597
|
+
const key = `${kind}:${name}`;
|
|
2598
|
+
const prev = counts.get(key);
|
|
2599
|
+
counts.set(key, { kind, name, layers: (prev?.layers ?? 0) + 1 });
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
return [...counts.values()].sort((a, b) => `${a.kind}:${a.name}`.localeCompare(`${b.kind}:${b.name}`));
|
|
2604
|
+
}
|
|
2605
|
+
function repeatedOverrides(set) {
|
|
2606
|
+
return set.filter((s) => s.layers > 1);
|
|
2607
|
+
}
|
|
2608
|
+
function checkOverrideSet(projectRoot) {
|
|
2609
|
+
const id = "override-set";
|
|
2610
|
+
const set = collectOverrideSet(projectRoot);
|
|
2611
|
+
if (set.length === 0) {
|
|
2612
|
+
return { id, status: "skipped", message: "no shipped artifact is overridden in this tree", remedy: "" };
|
|
2613
|
+
}
|
|
2614
|
+
const repeated = repeatedOverrides(set);
|
|
2615
|
+
const names = set.map((s) => `${s.kind}:${s.name}\xD7${s.layers}`).join(" \xB7 ");
|
|
2616
|
+
if (repeated.length === 0) {
|
|
2617
|
+
return {
|
|
2618
|
+
id,
|
|
2619
|
+
status: "ok",
|
|
2620
|
+
message: `${set.length} shipped artifact(s) overridden locally, each once: ${names}`,
|
|
2621
|
+
remedy: ""
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
return {
|
|
2625
|
+
id,
|
|
2626
|
+
status: "warn",
|
|
2627
|
+
message: `${repeated.length} shipped artifact(s) overridden in more than one layer: ${names}. A repeatedly overridden default is a candidate for an upstream proposal \u2014 but ONE tree is not evidence about a default. It is one input to an aggregate across independent consumers.`,
|
|
2628
|
+
remedy: "route it through the upstream-contribution path, never by changing a shipped default on one install"
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
var REACH_CHECK_IDS = ["instruction-path-reach", "version-axis", "override-set"];
|
|
2632
|
+
function reachRunners(opts) {
|
|
2633
|
+
return {
|
|
2634
|
+
"instruction-path-reach": () => checkInstructionPaths(opts.projectRoot),
|
|
2635
|
+
"version-axis": () => checkVersionAxis(opts.projectRoot, opts.resolvableVersion),
|
|
2636
|
+
"override-set": () => checkOverrideSet(opts.projectRoot)
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
// src/scripts/_lib/doctor_runtime_checks.ts
|
|
2641
|
+
function checkPythonRuntime() {
|
|
2642
|
+
return {
|
|
2643
|
+
id: "python-runtime",
|
|
2644
|
+
status: "ok",
|
|
2645
|
+
message: "python3 is not a runtime dependency (TS runtime via tsx)",
|
|
2646
|
+
remedy: ""
|
|
2647
|
+
};
|
|
2648
|
+
}
|
|
2649
|
+
function checkHumanizerRuntime(which) {
|
|
2650
|
+
const node = which("node");
|
|
2651
|
+
if (node === null) {
|
|
2652
|
+
return {
|
|
2653
|
+
id: "humanizer-runtime",
|
|
2654
|
+
status: "ok",
|
|
2655
|
+
message: "no Node runtime on PATH \u2014 write-engine step 4b uses the prose-only humanize audit (graceful fallback)",
|
|
2656
|
+
remedy: "install Node to enable the mechanical detect_ai_tells.ts pass; the prose audit runs regardless"
|
|
2657
|
+
};
|
|
2658
|
+
}
|
|
2659
|
+
return {
|
|
2660
|
+
id: "humanizer-runtime",
|
|
2661
|
+
status: "ok",
|
|
2662
|
+
message: `Node runtime present (${node}) \u2014 step 4b runs the mechanical detect_ai_tells.ts pass`,
|
|
2663
|
+
remedy: ""
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
1689
2666
|
|
|
1690
2667
|
// src/scripts/_lib/environment_detector.ts
|
|
1691
2668
|
import { spawnSync } from "node:child_process";
|
|
1692
|
-
import * as
|
|
2669
|
+
import * as fs12 from "node:fs";
|
|
1693
2670
|
import * as os from "node:os";
|
|
1694
|
-
import * as
|
|
2671
|
+
import * as path16 from "node:path";
|
|
1695
2672
|
|
|
1696
2673
|
// src/install/toolDetection.ts
|
|
1697
|
-
import { existsSync as
|
|
2674
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
1698
2675
|
import { homedir as homedir3 } from "node:os";
|
|
1699
|
-
import { delimiter, join as
|
|
2676
|
+
import { delimiter, join as join15 } from "node:path";
|
|
1700
2677
|
var TOOL_SIGNALS = {
|
|
1701
2678
|
"claude-code": { bins: ["claude"], homePaths: [".claude", ".claude.json", ".config/claude"] },
|
|
1702
2679
|
"claude-desktop": { absPaths: ["/Applications/Claude.app"], homePaths: ["Library/Application Support/Claude", ".config/Claude"] },
|
|
@@ -1741,8 +2718,8 @@ function resolveBinaryPath(name, pathEnv) {
|
|
|
1741
2718
|
for (const dir of pathEnv.split(delimiter)) {
|
|
1742
2719
|
if (dir.length === 0) continue;
|
|
1743
2720
|
for (const candidate of [name, `${name}.exe`, `${name}.cmd`]) {
|
|
1744
|
-
const full =
|
|
1745
|
-
if (
|
|
2721
|
+
const full = join15(dir, candidate);
|
|
2722
|
+
if (existsSync9(full)) return full;
|
|
1746
2723
|
}
|
|
1747
2724
|
}
|
|
1748
2725
|
return null;
|
|
@@ -1752,10 +2729,10 @@ function binOnPath(name, pathEnv) {
|
|
|
1752
2729
|
}
|
|
1753
2730
|
function isToolInstalled(signal, home, pathEnv) {
|
|
1754
2731
|
for (const rel of signal.homePaths ?? []) {
|
|
1755
|
-
if (
|
|
2732
|
+
if (existsSync9(join15(home, rel))) return true;
|
|
1756
2733
|
}
|
|
1757
2734
|
for (const abs of signal.absPaths ?? []) {
|
|
1758
|
-
if (
|
|
2735
|
+
if (existsSync9(abs)) return true;
|
|
1759
2736
|
}
|
|
1760
2737
|
for (const bin of signal.bins ?? []) {
|
|
1761
2738
|
if (binOnPath(bin, pathEnv)) return true;
|
|
@@ -1814,7 +2791,7 @@ function classifyBilling(provider, source) {
|
|
|
1814
2791
|
function codexHome(env) {
|
|
1815
2792
|
const map = env ?? process.env;
|
|
1816
2793
|
const override = (map["CODEX_HOME"] ?? "").trim();
|
|
1817
|
-
return override !== "" ? override :
|
|
2794
|
+
return override !== "" ? override : path16.join(homeOf(env), ".codex");
|
|
1818
2795
|
}
|
|
1819
2796
|
function homeOf(env) {
|
|
1820
2797
|
const map = env ?? process.env;
|
|
@@ -1855,14 +2832,14 @@ ${res.stderr ?? ""}`;
|
|
|
1855
2832
|
}
|
|
1856
2833
|
function isFile3(p) {
|
|
1857
2834
|
try {
|
|
1858
|
-
return
|
|
2835
|
+
return fs12.statSync(p).isFile();
|
|
1859
2836
|
} catch {
|
|
1860
2837
|
return false;
|
|
1861
2838
|
}
|
|
1862
2839
|
}
|
|
1863
2840
|
function exists(p) {
|
|
1864
2841
|
try {
|
|
1865
|
-
return
|
|
2842
|
+
return fs12.existsSync(p);
|
|
1866
2843
|
} catch {
|
|
1867
2844
|
return false;
|
|
1868
2845
|
}
|
|
@@ -1870,7 +2847,7 @@ function exists(p) {
|
|
|
1870
2847
|
function classifyCodexAuth(authPath) {
|
|
1871
2848
|
let data;
|
|
1872
2849
|
try {
|
|
1873
|
-
data = JSON.parse(
|
|
2850
|
+
data = JSON.parse(fs12.readFileSync(authPath, "utf-8"));
|
|
1874
2851
|
} catch {
|
|
1875
2852
|
return "cli-api-key";
|
|
1876
2853
|
}
|
|
@@ -1887,7 +2864,7 @@ function cliSubscriptionEvidence(provider, home, env, claudeConfigDir, probeKeyc
|
|
|
1887
2864
|
if (provider === "anthropic") {
|
|
1888
2865
|
const configDir = claudeConfigDir;
|
|
1889
2866
|
for (const rel of [".credentials.json", "credentials.json"]) {
|
|
1890
|
-
const p =
|
|
2867
|
+
const p = path16.join(configDir, rel);
|
|
1891
2868
|
if (isFile3(p)) return { source: "cli-subscription", evidence: p };
|
|
1892
2869
|
}
|
|
1893
2870
|
if (probeKeychain(CLAUDE_KEYCHAIN_SERVICE)) {
|
|
@@ -1896,12 +2873,12 @@ function cliSubscriptionEvidence(provider, home, env, claudeConfigDir, probeKeyc
|
|
|
1896
2873
|
return null;
|
|
1897
2874
|
}
|
|
1898
2875
|
if (provider === "openai") {
|
|
1899
|
-
const p =
|
|
2876
|
+
const p = path16.join(codexHome(env), "auth.json");
|
|
1900
2877
|
if (isFile3(p)) return { source: classifyCodexAuth(p), evidence: p };
|
|
1901
2878
|
return null;
|
|
1902
2879
|
}
|
|
1903
2880
|
if (provider === "gemini") {
|
|
1904
|
-
const p =
|
|
2881
|
+
const p = path16.join(home, ".gemini", "oauth_creds.json");
|
|
1905
2882
|
if (isFile3(p)) return { source: "cli-subscription", evidence: p };
|
|
1906
2883
|
return null;
|
|
1907
2884
|
}
|
|
@@ -1933,7 +2910,7 @@ function detectHosts(opts) {
|
|
|
1933
2910
|
function detectAuth(opts) {
|
|
1934
2911
|
const env = opts.env ?? process.env;
|
|
1935
2912
|
const home = opts.home ?? homeOf(opts.env);
|
|
1936
|
-
const claudeConfigDir = opts.home === void 0 && opts.env === void 0 ? claude_config_dir() : (env["CLAUDE_CONFIG_DIR"] ?? "").trim() ||
|
|
2913
|
+
const claudeConfigDir = opts.home === void 0 && opts.env === void 0 ? claude_config_dir() : (env["CLAUDE_CONFIG_DIR"] ?? "").trim() || path16.join(home, ".claude");
|
|
1937
2914
|
const probeKeychain = opts.probeKeychain ?? defaultProbeKeychain;
|
|
1938
2915
|
const auth = [];
|
|
1939
2916
|
const keys = [];
|
|
@@ -1988,7 +2965,7 @@ function detectEnvironment(opts = {}) {
|
|
|
1988
2965
|
}
|
|
1989
2966
|
|
|
1990
2967
|
// src/scripts/_cli/detection_report.ts
|
|
1991
|
-
import * as
|
|
2968
|
+
import * as path17 from "node:path";
|
|
1992
2969
|
|
|
1993
2970
|
// src/scripts/ai_council/transport_resolver.ts
|
|
1994
2971
|
var VALID_TRANSPORT_MODES = /* @__PURE__ */ new Set([
|
|
@@ -2007,11 +2984,11 @@ function cliBinary(report, provider) {
|
|
|
2007
2984
|
if (meta === void 0) return null;
|
|
2008
2985
|
const binaryName = meta[0];
|
|
2009
2986
|
const host = report.hosts.find(
|
|
2010
|
-
(h) => h.binary !== null && stripExeSuffix(
|
|
2987
|
+
(h) => h.binary !== null && stripExeSuffix(basename2(h.binary)) === binaryName
|
|
2011
2988
|
);
|
|
2012
2989
|
return host?.binary ?? null;
|
|
2013
2990
|
}
|
|
2014
|
-
function
|
|
2991
|
+
function basename2(p) {
|
|
2015
2992
|
const parts = p.split(/[/\\]/);
|
|
2016
2993
|
return parts[parts.length - 1] ?? p;
|
|
2017
2994
|
}
|
|
@@ -2190,7 +3167,7 @@ function cliBinaryPresent(environment, provider, binaryOverride) {
|
|
|
2190
3167
|
const expected = PROVIDER_CLI_META[provider]?.[0];
|
|
2191
3168
|
if (expected === void 0) return false;
|
|
2192
3169
|
return environment.hosts.some(
|
|
2193
|
-
(h) => h.binary !== null && stripExe(
|
|
3170
|
+
(h) => h.binary !== null && stripExe(path17.basename(h.binary)) === expected
|
|
2194
3171
|
);
|
|
2195
3172
|
}
|
|
2196
3173
|
function stripExe(name) {
|
|
@@ -2351,9 +3328,9 @@ function absentCouncilFacts(configPath) {
|
|
|
2351
3328
|
|
|
2352
3329
|
// src/scripts/ai_team/review_gate.ts
|
|
2353
3330
|
import * as crypto from "node:crypto";
|
|
2354
|
-
import * as
|
|
3331
|
+
import * as fs13 from "node:fs";
|
|
2355
3332
|
import * as os2 from "node:os";
|
|
2356
|
-
import * as
|
|
3333
|
+
import * as path18 from "node:path";
|
|
2357
3334
|
|
|
2358
3335
|
// src/scripts/ai_team/config.ts
|
|
2359
3336
|
var AI_TEAM_REVIEW_GATE_DEFAULTS = Object.freeze({
|
|
@@ -2369,16 +3346,16 @@ var AI_TEAM_DEFAULTS = Object.freeze({
|
|
|
2369
3346
|
});
|
|
2370
3347
|
|
|
2371
3348
|
// src/scripts/ai_team/review_gate.ts
|
|
2372
|
-
var GATE_LEDGER_RELPATH =
|
|
3349
|
+
var GATE_LEDGER_RELPATH = path18.join("agents", "runtime", "team", "events.log");
|
|
2373
3350
|
var _CODEX_PLUGIN_DATA_DIRNAME = `${CODEX_PLUGIN_ID}-${CODEX_MARKETPLACE_NAME}`;
|
|
2374
3351
|
function _workspace_state_segment(workspace_root) {
|
|
2375
3352
|
let canonical = workspace_root;
|
|
2376
3353
|
try {
|
|
2377
|
-
canonical =
|
|
3354
|
+
canonical = fs13.realpathSync.native(workspace_root);
|
|
2378
3355
|
} catch {
|
|
2379
3356
|
canonical = workspace_root;
|
|
2380
3357
|
}
|
|
2381
|
-
const slug_source =
|
|
3358
|
+
const slug_source = path18.basename(workspace_root) || "workspace";
|
|
2382
3359
|
const slug = slug_source.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "workspace";
|
|
2383
3360
|
const hash = crypto.createHash("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
2384
3361
|
return `${slug}-${hash}`;
|
|
@@ -2388,19 +3365,19 @@ function upstream_state_dir_candidates(workspace_root) {
|
|
|
2388
3365
|
const candidates = [];
|
|
2389
3366
|
const env = (process.env["CLAUDE_PLUGIN_DATA"] ?? "").trim();
|
|
2390
3367
|
if (env !== "") {
|
|
2391
|
-
candidates.push(
|
|
3368
|
+
candidates.push(path18.join(env, "state", segment));
|
|
2392
3369
|
}
|
|
2393
3370
|
candidates.push(
|
|
2394
|
-
|
|
3371
|
+
path18.join(claude_config_dir(), "plugins", "data", _CODEX_PLUGIN_DATA_DIRNAME, "state", segment)
|
|
2395
3372
|
);
|
|
2396
|
-
candidates.push(
|
|
3373
|
+
candidates.push(path18.join(os2.tmpdir(), "codex-companion", segment));
|
|
2397
3374
|
return candidates;
|
|
2398
3375
|
}
|
|
2399
3376
|
function upstream_gate_enabled(workspace_root) {
|
|
2400
3377
|
for (const dir of upstream_state_dir_candidates(workspace_root)) {
|
|
2401
3378
|
let parsed;
|
|
2402
3379
|
try {
|
|
2403
|
-
parsed = JSON.parse(
|
|
3380
|
+
parsed = JSON.parse(fs13.readFileSync(path18.join(dir, "state.json"), "utf-8"));
|
|
2404
3381
|
} catch {
|
|
2405
3382
|
continue;
|
|
2406
3383
|
}
|
|
@@ -2460,13 +3437,13 @@ var ArgparseExit = class extends Error {
|
|
|
2460
3437
|
function expanduser(p) {
|
|
2461
3438
|
if (p === "~") return os3.homedir();
|
|
2462
3439
|
if (p.startsWith("~/") || p.startsWith("~\\")) {
|
|
2463
|
-
return
|
|
3440
|
+
return path19.join(os3.homedir(), p.slice(2));
|
|
2464
3441
|
}
|
|
2465
3442
|
return p;
|
|
2466
3443
|
}
|
|
2467
3444
|
function pathExists(p) {
|
|
2468
3445
|
try {
|
|
2469
|
-
|
|
3446
|
+
fs14.statSync(p);
|
|
2470
3447
|
return true;
|
|
2471
3448
|
} catch {
|
|
2472
3449
|
return false;
|
|
@@ -2474,27 +3451,27 @@ function pathExists(p) {
|
|
|
2474
3451
|
}
|
|
2475
3452
|
function isFile4(p) {
|
|
2476
3453
|
try {
|
|
2477
|
-
return
|
|
3454
|
+
return fs14.statSync(p).isFile();
|
|
2478
3455
|
} catch {
|
|
2479
3456
|
return false;
|
|
2480
3457
|
}
|
|
2481
3458
|
}
|
|
2482
3459
|
function isDir3(p) {
|
|
2483
3460
|
try {
|
|
2484
|
-
return
|
|
3461
|
+
return fs14.statSync(p).isDirectory();
|
|
2485
3462
|
} catch {
|
|
2486
3463
|
return false;
|
|
2487
3464
|
}
|
|
2488
3465
|
}
|
|
2489
3466
|
function resolvePath(p) {
|
|
2490
3467
|
try {
|
|
2491
|
-
return
|
|
3468
|
+
return fs14.realpathSync(path19.resolve(p));
|
|
2492
3469
|
} catch {
|
|
2493
|
-
return
|
|
3470
|
+
return path19.resolve(p);
|
|
2494
3471
|
}
|
|
2495
3472
|
}
|
|
2496
3473
|
function readText(p) {
|
|
2497
|
-
return
|
|
3474
|
+
return fs14.readFileSync(p, "utf-8");
|
|
2498
3475
|
}
|
|
2499
3476
|
function _jsonStrAscii(s) {
|
|
2500
3477
|
let out = '"';
|
|
@@ -2592,10 +3569,10 @@ function yamlSafeLoad(text) {
|
|
|
2592
3569
|
}
|
|
2593
3570
|
}
|
|
2594
3571
|
function print(line = "") {
|
|
2595
|
-
|
|
3572
|
+
process3.stdout.write(line + "\n");
|
|
2596
3573
|
}
|
|
2597
3574
|
function eprint(line = "") {
|
|
2598
|
-
|
|
3575
|
+
process3.stderr.write(line + "\n");
|
|
2599
3576
|
}
|
|
2600
3577
|
var _Sentinel = class {
|
|
2601
3578
|
};
|
|
@@ -2605,7 +3582,7 @@ function _resolve_project_root(arg) {
|
|
|
2605
3582
|
}
|
|
2606
3583
|
var _INSTALL_MODE_MARKER_REL = "agents/.agent-state/install-mode.txt";
|
|
2607
3584
|
function _detect_install_mode(project_root) {
|
|
2608
|
-
const marker =
|
|
3585
|
+
const marker = path19.join(project_root, _INSTALL_MODE_MARKER_REL);
|
|
2609
3586
|
if (isFile4(marker)) {
|
|
2610
3587
|
let value;
|
|
2611
3588
|
try {
|
|
@@ -2617,9 +3594,9 @@ function _detect_install_mode(project_root) {
|
|
|
2617
3594
|
return [value, "marker-file"];
|
|
2618
3595
|
}
|
|
2619
3596
|
}
|
|
2620
|
-
const has_agents_md = pathExists(
|
|
3597
|
+
const has_agents_md = pathExists(path19.join(project_root, "AGENTS.md"));
|
|
2621
3598
|
const has_copilot = pathExists(
|
|
2622
|
-
|
|
3599
|
+
path19.join(project_root, ".github", "copilot-instructions.md")
|
|
2623
3600
|
);
|
|
2624
3601
|
if (has_agents_md && has_copilot) {
|
|
2625
3602
|
return ["full", "heuristic"];
|
|
@@ -2639,7 +3616,7 @@ function _settings_layer_chain(project_root) {
|
|
|
2639
3616
|
return layers;
|
|
2640
3617
|
}
|
|
2641
3618
|
function _detect_wrapper(project_root) {
|
|
2642
|
-
const wrapper =
|
|
3619
|
+
const wrapper = path19.join(project_root, "agent-config");
|
|
2643
3620
|
if (!pathExists(wrapper)) {
|
|
2644
3621
|
return { path: String(wrapper), exists: false, embedded_root: null };
|
|
2645
3622
|
}
|
|
@@ -2650,7 +3627,7 @@ function _detect_wrapper(project_root) {
|
|
|
2650
3627
|
};
|
|
2651
3628
|
}
|
|
2652
3629
|
function _emit_trace_text(root, anchor, trace, origin) {
|
|
2653
|
-
print(` \u{1F4CD} start: ${
|
|
3630
|
+
print(` \u{1F4CD} start: ${process3.cwd()}`);
|
|
2654
3631
|
print(` \u{1F4CD} origin: ${origin}`);
|
|
2655
3632
|
if (trace.length > 0) {
|
|
2656
3633
|
print(" trace:");
|
|
@@ -2670,7 +3647,7 @@ function _emit_trace_text(root, anchor, trace, origin) {
|
|
|
2670
3647
|
}
|
|
2671
3648
|
function _emit_trace_json(root, anchor, trace, origin) {
|
|
2672
3649
|
const payload = {
|
|
2673
|
-
start:
|
|
3650
|
+
start: process3.cwd(),
|
|
2674
3651
|
origin,
|
|
2675
3652
|
resolved_root: root !== null ? String(root) : null,
|
|
2676
3653
|
anchor,
|
|
@@ -2706,14 +3683,14 @@ function _emit_context_text(ctx) {
|
|
|
2706
3683
|
}
|
|
2707
3684
|
function _resolve_path(project_root, raw) {
|
|
2708
3685
|
let p = expanduser(raw);
|
|
2709
|
-
if (!
|
|
2710
|
-
p =
|
|
3686
|
+
if (!path19.isAbsolute(p)) {
|
|
3687
|
+
p = path19.join(project_root, p);
|
|
2711
3688
|
}
|
|
2712
3689
|
return p;
|
|
2713
3690
|
}
|
|
2714
3691
|
function _sha256(p) {
|
|
2715
3692
|
try {
|
|
2716
|
-
const data =
|
|
3693
|
+
const data = fs14.readFileSync(p);
|
|
2717
3694
|
return crypto2.createHash("sha256").update(data).digest("hex");
|
|
2718
3695
|
} catch {
|
|
2719
3696
|
return null;
|
|
@@ -2722,7 +3699,7 @@ function _sha256(p) {
|
|
|
2722
3699
|
var PACKAGE_TAG_ID = "event4u/agent-config";
|
|
2723
3700
|
var _FRONTMATTER_PACKAGE_RE = /^package:\s*(.+?)\s*$/m;
|
|
2724
3701
|
function _read_inline_package_tag(p) {
|
|
2725
|
-
if (
|
|
3702
|
+
if (path19.extname(p) !== ".md") {
|
|
2726
3703
|
return NO_FRONTMATTER;
|
|
2727
3704
|
}
|
|
2728
3705
|
let text;
|
|
@@ -2851,13 +3828,13 @@ function rglob(root) {
|
|
|
2851
3828
|
const walk = (dir) => {
|
|
2852
3829
|
let entries;
|
|
2853
3830
|
try {
|
|
2854
|
-
entries =
|
|
3831
|
+
entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
2855
3832
|
} catch {
|
|
2856
3833
|
return;
|
|
2857
3834
|
}
|
|
2858
3835
|
entries.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
2859
3836
|
for (const ent of entries) {
|
|
2860
|
-
const full =
|
|
3837
|
+
const full = path19.join(dir, ent.name);
|
|
2861
3838
|
out.push(full);
|
|
2862
3839
|
let dirLike = ent.isDirectory();
|
|
2863
3840
|
if (ent.isSymbolicLink()) {
|
|
@@ -2932,9 +3909,9 @@ function _foreign_records(project_root, foreign) {
|
|
|
2932
3909
|
return out;
|
|
2933
3910
|
}
|
|
2934
3911
|
function relativeTo(p, base) {
|
|
2935
|
-
const rel =
|
|
3912
|
+
const rel = path19.relative(base, p);
|
|
2936
3913
|
if (rel === "") return rel;
|
|
2937
|
-
if (rel.startsWith("..") ||
|
|
3914
|
+
if (rel.startsWith("..") || path19.isAbsolute(rel)) {
|
|
2938
3915
|
return null;
|
|
2939
3916
|
}
|
|
2940
3917
|
return rel;
|
|
@@ -2947,6 +3924,8 @@ var CHECK_IDS = [
|
|
|
2947
3924
|
"claude-command-wrappers",
|
|
2948
3925
|
"surface-state",
|
|
2949
3926
|
"hook-wiring",
|
|
3927
|
+
...WIRING_CHECK_IDS,
|
|
3928
|
+
...REACH_CHECK_IDS,
|
|
2950
3929
|
"stale-orphans",
|
|
2951
3930
|
"overrides",
|
|
2952
3931
|
"rule-scope-drift",
|
|
@@ -2976,6 +3955,8 @@ var GLOBAL_CHECK_IDS = /* @__PURE__ */ new Set([
|
|
|
2976
3955
|
"claude-command-wrappers",
|
|
2977
3956
|
"surface-state",
|
|
2978
3957
|
"hook-wiring",
|
|
3958
|
+
...WIRING_CHECK_IDS,
|
|
3959
|
+
...REACH_CHECK_IDS,
|
|
2979
3960
|
"stale-orphans",
|
|
2980
3961
|
"overrides",
|
|
2981
3962
|
"rule-scope-drift",
|
|
@@ -3016,7 +3997,7 @@ var STATUS_SYMBOLS = {
|
|
|
3016
3997
|
var MIN_PYTHON = [3, 10];
|
|
3017
3998
|
function _check_scope(project_root) {
|
|
3018
3999
|
for (const marker of ["pnpm-workspace.yaml", "lerna.json"]) {
|
|
3019
|
-
if (pathExists(
|
|
4000
|
+
if (pathExists(path19.join(project_root, marker))) {
|
|
3020
4001
|
return {
|
|
3021
4002
|
id: "scope",
|
|
3022
4003
|
status: "warn",
|
|
@@ -3025,7 +4006,7 @@ function _check_scope(project_root) {
|
|
|
3025
4006
|
};
|
|
3026
4007
|
}
|
|
3027
4008
|
}
|
|
3028
|
-
const pkg =
|
|
4009
|
+
const pkg = path19.join(project_root, "package.json");
|
|
3029
4010
|
if (pathExists(pkg)) {
|
|
3030
4011
|
try {
|
|
3031
4012
|
const data = JSON.parse(readText(pkg));
|
|
@@ -3051,7 +4032,7 @@ var _PLACEHOLDER_EMAIL_RE = /^(t@t\.t|.*@example\.(com|org)|.*@localhost)$/i;
|
|
|
3051
4032
|
var _PLACEHOLDER_NAME_RE = /^(t|test|user|nobody|x)$/i;
|
|
3052
4033
|
function _git_config_path(project_root) {
|
|
3053
4034
|
const common = git_common_dir(project_root);
|
|
3054
|
-
return common === null ? null :
|
|
4035
|
+
return common === null ? null : path19.join(common, "config");
|
|
3055
4036
|
}
|
|
3056
4037
|
function _parse_git_user(configText) {
|
|
3057
4038
|
let inUser = false;
|
|
@@ -3081,7 +4062,7 @@ function _check_git_identity(project_root) {
|
|
|
3081
4062
|
}
|
|
3082
4063
|
let ident = _parse_git_user(readText(cfgPath));
|
|
3083
4064
|
if (ident.name === null && ident.email === null) {
|
|
3084
|
-
const globalCfg =
|
|
4065
|
+
const globalCfg = path19.join(os3.homedir(), ".gitconfig");
|
|
3085
4066
|
if (pathExists(globalCfg)) {
|
|
3086
4067
|
ident = _parse_git_user(readText(globalCfg));
|
|
3087
4068
|
}
|
|
@@ -3142,7 +4123,7 @@ function _package_root() {
|
|
|
3142
4123
|
}
|
|
3143
4124
|
function _current_package_version() {
|
|
3144
4125
|
try {
|
|
3145
|
-
const data = JSON.parse(readText(
|
|
4126
|
+
const data = JSON.parse(readText(path19.join(_package_root(), "package.json")));
|
|
3146
4127
|
const v = data["version"];
|
|
3147
4128
|
if (typeof v === "string" && v.trim()) {
|
|
3148
4129
|
return v.trim();
|
|
@@ -3186,25 +4167,25 @@ function _check_lockfile_freshness(manifest) {
|
|
|
3186
4167
|
};
|
|
3187
4168
|
}
|
|
3188
4169
|
function shutilWhich(name) {
|
|
3189
|
-
if (
|
|
4170
|
+
if (path19.dirname(name) !== "." && (name.includes("/") || name.includes("\\"))) {
|
|
3190
4171
|
return isExecutableFile(name) ? name : null;
|
|
3191
4172
|
}
|
|
3192
|
-
const pathEnv =
|
|
3193
|
-
const sep2 =
|
|
4173
|
+
const pathEnv = process3.env["PATH"] || "";
|
|
4174
|
+
const sep2 = process3.platform === "win32" ? ";" : ":";
|
|
3194
4175
|
const dirs = pathEnv.split(sep2);
|
|
3195
|
-
const exts =
|
|
4176
|
+
const exts = process3.platform === "win32" ? (process3.env["PATHEXT"] || ".COM;.EXE;.BAT;.CMD").split(";") : [""];
|
|
3196
4177
|
const seenDirs = /* @__PURE__ */ new Set();
|
|
3197
4178
|
for (const dir of dirs) {
|
|
3198
4179
|
const d = dir === "" ? "." : dir;
|
|
3199
4180
|
if (seenDirs.has(d)) continue;
|
|
3200
4181
|
seenDirs.add(d);
|
|
3201
4182
|
for (const ext of exts) {
|
|
3202
|
-
const candidate =
|
|
4183
|
+
const candidate = path19.join(d, name + (ext === "" ? "" : ext.toLowerCase() === ext ? ext : ext));
|
|
3203
4184
|
if (isExecutableFile(candidate)) {
|
|
3204
4185
|
return candidate;
|
|
3205
4186
|
}
|
|
3206
4187
|
if (ext !== "") {
|
|
3207
|
-
const upper =
|
|
4188
|
+
const upper = path19.join(d, name + ext);
|
|
3208
4189
|
if (isExecutableFile(upper)) return upper;
|
|
3209
4190
|
}
|
|
3210
4191
|
}
|
|
@@ -3213,10 +4194,10 @@ function shutilWhich(name) {
|
|
|
3213
4194
|
}
|
|
3214
4195
|
function isExecutableFile(p) {
|
|
3215
4196
|
try {
|
|
3216
|
-
const st =
|
|
4197
|
+
const st = fs14.statSync(p);
|
|
3217
4198
|
if (!st.isFile()) return false;
|
|
3218
|
-
if (
|
|
3219
|
-
|
|
4199
|
+
if (process3.platform === "win32") return true;
|
|
4200
|
+
fs14.accessSync(p, fs14.constants.X_OK);
|
|
3220
4201
|
return true;
|
|
3221
4202
|
} catch {
|
|
3222
4203
|
return false;
|
|
@@ -3280,7 +4261,7 @@ function _check_claude_plugin() {
|
|
|
3280
4261
|
remedy: ""
|
|
3281
4262
|
};
|
|
3282
4263
|
}
|
|
3283
|
-
const projection =
|
|
4264
|
+
const projection = path19.join(os3.homedir(), ".claude", "skills");
|
|
3284
4265
|
const projection_present = isDir3(projection);
|
|
3285
4266
|
if (projection_present) {
|
|
3286
4267
|
return {
|
|
@@ -3317,8 +4298,8 @@ function _check_claude_command_wrappers() {
|
|
|
3317
4298
|
remedy: ""
|
|
3318
4299
|
};
|
|
3319
4300
|
}
|
|
3320
|
-
const anchor =
|
|
3321
|
-
const commands_dir =
|
|
4301
|
+
const anchor = path19.join(os3.homedir(), ".claude");
|
|
4302
|
+
const commands_dir = path19.join(anchor, "commands");
|
|
3322
4303
|
if (!isDir3(commands_dir)) {
|
|
3323
4304
|
return {
|
|
3324
4305
|
id: "claude-command-wrappers",
|
|
@@ -3327,8 +4308,8 @@ function _check_claude_command_wrappers() {
|
|
|
3327
4308
|
remedy: ""
|
|
3328
4309
|
};
|
|
3329
4310
|
}
|
|
3330
|
-
const flat_probe =
|
|
3331
|
-
const wrapper_probe =
|
|
4311
|
+
const flat_probe = fs14.existsSync(path19.join(commands_dir, "commit.md"));
|
|
4312
|
+
const wrapper_probe = fs14.existsSync(path19.join(anchor, "skills", "commit", "SKILL.md"));
|
|
3332
4313
|
if (wrapper_probe) {
|
|
3333
4314
|
return {
|
|
3334
4315
|
id: "claude-command-wrappers",
|
|
@@ -3353,7 +4334,7 @@ function _check_claude_command_wrappers() {
|
|
|
3353
4334
|
};
|
|
3354
4335
|
}
|
|
3355
4336
|
function _check_surface_state() {
|
|
3356
|
-
const matrix_path =
|
|
4337
|
+
const matrix_path = path19.join(_package_root(), "src", "config", "surface-matrix.yml");
|
|
3357
4338
|
if (!isFile4(matrix_path)) {
|
|
3358
4339
|
return {
|
|
3359
4340
|
id: "surface-state",
|
|
@@ -3377,7 +4358,7 @@ function _check_surface_state() {
|
|
|
3377
4358
|
remedy: "agent-config upgrade (reinstalls the package data files)"
|
|
3378
4359
|
};
|
|
3379
4360
|
}
|
|
3380
|
-
const _expand = (p) => p.startsWith("~/") ?
|
|
4361
|
+
const _expand = (p) => p.startsWith("~/") ? path19.join(os3.homedir(), p.slice(2)) : path19.join(_package_root(), p);
|
|
3381
4362
|
const violations = [];
|
|
3382
4363
|
const remedies = [];
|
|
3383
4364
|
let checked = 0;
|
|
@@ -3419,72 +4400,21 @@ function _check_surface_state() {
|
|
|
3419
4400
|
}
|
|
3420
4401
|
function pathExistsAny(p) {
|
|
3421
4402
|
try {
|
|
3422
|
-
|
|
4403
|
+
fs14.statSync(p);
|
|
3423
4404
|
return true;
|
|
3424
4405
|
} catch {
|
|
3425
4406
|
return false;
|
|
3426
4407
|
}
|
|
3427
4408
|
}
|
|
3428
4409
|
function _check_hook_wiring() {
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
}
|
|
3438
|
-
const settings_path = path15.join(os3.homedir(), ".claude", "settings.json");
|
|
3439
|
-
let missing;
|
|
3440
|
-
try {
|
|
3441
|
-
const matrix = build_claude_hook_matrix(
|
|
3442
|
-
path15.join(_package_root(), "src", "scripts", "hook_manifest.yaml")
|
|
3443
|
-
);
|
|
3444
|
-
const settings = pathExists(settings_path) ? JSON.parse(fs11.readFileSync(settings_path, "utf8")) : {};
|
|
3445
|
-
const hooks = (settings["hooks"] ?? {}) || {};
|
|
3446
|
-
missing = Object.keys(matrix).filter((ev) => {
|
|
3447
|
-
const groups = hooks[ev];
|
|
3448
|
-
if (!Array.isArray(groups)) return true;
|
|
3449
|
-
return !JSON.stringify(groups).includes(MANAGED_SIGNATURE);
|
|
3450
|
-
});
|
|
3451
|
-
} catch (e) {
|
|
3452
|
-
return {
|
|
3453
|
-
id: "hook-wiring",
|
|
3454
|
-
status: "fail",
|
|
3455
|
-
message: `cannot evaluate managed hooks: ${String(e)}`,
|
|
3456
|
-
remedy: "fix ~/.claude/settings.json (invalid JSON?), then agent-config refresh --global"
|
|
3457
|
-
};
|
|
3458
|
-
}
|
|
3459
|
-
const binary_ok = shutilWhich("agent-config") !== null;
|
|
3460
|
-
if (missing.length === 0 && binary_ok) {
|
|
3461
|
-
return {
|
|
3462
|
-
id: "hook-wiring",
|
|
3463
|
-
status: "ok",
|
|
3464
|
-
message: "managed hooks registered in ~/.claude/settings.json; dispatch binary on PATH",
|
|
3465
|
-
remedy: ""
|
|
3466
|
-
};
|
|
3467
|
-
}
|
|
3468
|
-
if (missing.length > 0 && claude_plugin_installed()) {
|
|
3469
|
-
return {
|
|
3470
|
-
id: "hook-wiring",
|
|
3471
|
-
status: "warn",
|
|
3472
|
-
message: `managed hooks missing for: ${missing.join(", ")} \u2014 currently carried by the installed plugin (deprecated surface)`,
|
|
3473
|
-
remedy: "agent-config refresh --global (writes the managed settings.json block)"
|
|
3474
|
-
};
|
|
3475
|
-
}
|
|
3476
|
-
const parts = [];
|
|
3477
|
-
if (missing.length > 0) parts.push(`managed hooks missing for: ${missing.join(", ")}`);
|
|
3478
|
-
if (!binary_ok) parts.push("`agent-config` not on PATH (hooks would silently no-op)");
|
|
3479
|
-
if (parts.length === 0) {
|
|
3480
|
-
parts.push("`agent-config` not on PATH");
|
|
3481
|
-
}
|
|
3482
|
-
return {
|
|
3483
|
-
id: "hook-wiring",
|
|
3484
|
-
status: "fail",
|
|
3485
|
-
message: parts.join("; "),
|
|
3486
|
-
remedy: binary_ok ? "agent-config refresh --global" : "npm install -g @event4u/agent-config, then agent-config refresh --global"
|
|
3487
|
-
};
|
|
4410
|
+
return checkHookWiring({
|
|
4411
|
+
which: shutilWhich,
|
|
4412
|
+
packageRoot: _package_root(),
|
|
4413
|
+
homeDir: os3.homedir(),
|
|
4414
|
+
buildMatrix: (mp) => build_claude_hook_matrix(mp),
|
|
4415
|
+
managedSignature: MANAGED_SIGNATURE,
|
|
4416
|
+
pluginInstalled: () => claude_plugin_installed()
|
|
4417
|
+
});
|
|
3488
4418
|
}
|
|
3489
4419
|
function _check_bridge_drift(missing, modified, foreign, tag_drift) {
|
|
3490
4420
|
const total = missing.length + modified.length + foreign.length + tag_drift.length;
|
|
@@ -3516,7 +4446,7 @@ function _check_mcp_mode(project_root) {
|
|
|
3516
4446
|
];
|
|
3517
4447
|
const found = [];
|
|
3518
4448
|
for (const [rel, label] of candidates) {
|
|
3519
|
-
const p =
|
|
4449
|
+
const p = path19.join(project_root, rel);
|
|
3520
4450
|
if (!pathExists(p)) {
|
|
3521
4451
|
continue;
|
|
3522
4452
|
}
|
|
@@ -3548,7 +4478,7 @@ function _check_mcp_mode(project_root) {
|
|
|
3548
4478
|
};
|
|
3549
4479
|
}
|
|
3550
4480
|
function _check_offline_readiness() {
|
|
3551
|
-
const script =
|
|
4481
|
+
const script = path19.join(_package_root(), "src", "scripts", "hermetic-install.sh");
|
|
3552
4482
|
if (!pathExists(script)) {
|
|
3553
4483
|
return {
|
|
3554
4484
|
id: "offline-readiness",
|
|
@@ -3606,7 +4536,7 @@ function _check_stale_orphans() {
|
|
|
3606
4536
|
(a, b) => a < b ? -1 : a > b ? 1 : 0
|
|
3607
4537
|
);
|
|
3608
4538
|
for (const root_name of ownedSorted) {
|
|
3609
|
-
const root =
|
|
4539
|
+
const root = path19.join(anchor, root_name);
|
|
3610
4540
|
if (!isDir3(root)) {
|
|
3611
4541
|
continue;
|
|
3612
4542
|
}
|
|
@@ -3621,7 +4551,7 @@ function _check_stale_orphans() {
|
|
|
3621
4551
|
if (rel === null) {
|
|
3622
4552
|
continue;
|
|
3623
4553
|
}
|
|
3624
|
-
const relPosix = rel.split(
|
|
4554
|
+
const relPosix = rel.split(path19.sep).join("/");
|
|
3625
4555
|
if (recorded_set.has(relPosix)) {
|
|
3626
4556
|
continue;
|
|
3627
4557
|
}
|
|
@@ -3676,14 +4606,14 @@ function _check_rule_scope_drift(project_root) {
|
|
|
3676
4606
|
let rules_dir = null;
|
|
3677
4607
|
let found = 0;
|
|
3678
4608
|
for (const rel of _RULE_PROJECTION_DIRS) {
|
|
3679
|
-
const cand =
|
|
4609
|
+
const cand = path19.join(project_root, rel);
|
|
3680
4610
|
if (!isDir3(cand)) {
|
|
3681
4611
|
continue;
|
|
3682
4612
|
}
|
|
3683
4613
|
let count = 0;
|
|
3684
4614
|
try {
|
|
3685
|
-
for (const name of
|
|
3686
|
-
if (name.endsWith(".md") && isFile4(
|
|
4615
|
+
for (const name of fs14.readdirSync(cand)) {
|
|
4616
|
+
if (name.endsWith(".md") && isFile4(path19.join(cand, name))) {
|
|
3687
4617
|
count += 1;
|
|
3688
4618
|
}
|
|
3689
4619
|
}
|
|
@@ -3737,14 +4667,14 @@ function _check_rule_scope_drift(project_root) {
|
|
|
3737
4667
|
};
|
|
3738
4668
|
}
|
|
3739
4669
|
function _check_duplicate_scope_rules(project_root, userRulesDirOverride) {
|
|
3740
|
-
const user_rules_dir = userRulesDirOverride ??
|
|
4670
|
+
const user_rules_dir = userRulesDirOverride ?? path19.join(os3.homedir(), ".claude", "rules");
|
|
3741
4671
|
let project_rules_dir = null;
|
|
3742
4672
|
if (_is_source_repo(project_root)) {
|
|
3743
|
-
const cand =
|
|
4673
|
+
const cand = path19.join(project_root, "dist", "agent-src", "rules");
|
|
3744
4674
|
if (isDir3(cand)) project_rules_dir = cand;
|
|
3745
4675
|
} else {
|
|
3746
4676
|
for (const rel of _RULE_PROJECTION_DIRS) {
|
|
3747
|
-
const cand =
|
|
4677
|
+
const cand = path19.join(project_root, rel);
|
|
3748
4678
|
if (isDir3(cand)) {
|
|
3749
4679
|
project_rules_dir = cand;
|
|
3750
4680
|
break;
|
|
@@ -3777,31 +4707,8 @@ function _check_duplicate_scope_rules(project_root, userRulesDirOverride) {
|
|
|
3777
4707
|
remedy: "detection only \u2014 no file is modified. If the duplication is unwanted, refresh the user-scope copy (e.g. `agent-config global`) to re-sync it with the project-scope version."
|
|
3778
4708
|
};
|
|
3779
4709
|
}
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
id: "python-runtime",
|
|
3783
|
-
status: "ok",
|
|
3784
|
-
message: "python3 is not a runtime dependency (TS runtime via tsx)",
|
|
3785
|
-
remedy: ""
|
|
3786
|
-
};
|
|
3787
|
-
}
|
|
3788
|
-
function _check_humanizer_runtime() {
|
|
3789
|
-
const node = shutilWhich("node");
|
|
3790
|
-
if (node === null) {
|
|
3791
|
-
return {
|
|
3792
|
-
id: "humanizer-runtime",
|
|
3793
|
-
status: "ok",
|
|
3794
|
-
message: "no Node runtime on PATH \u2014 write-engine step 4b uses the prose-only humanize audit (graceful fallback)",
|
|
3795
|
-
remedy: "install Node to enable the mechanical detect_ai_tells.ts pass; the prose audit runs regardless"
|
|
3796
|
-
};
|
|
3797
|
-
}
|
|
3798
|
-
return {
|
|
3799
|
-
id: "humanizer-runtime",
|
|
3800
|
-
status: "ok",
|
|
3801
|
-
message: `Node runtime present (${node}) \u2014 step 4b runs the mechanical detect_ai_tells.ts pass`,
|
|
3802
|
-
remedy: ""
|
|
3803
|
-
};
|
|
3804
|
-
}
|
|
4710
|
+
var _check_python_runtime = () => checkPythonRuntime();
|
|
4711
|
+
var _check_humanizer_runtime = () => checkHumanizerRuntime(shutilWhich);
|
|
3805
4712
|
function _check_mcp_beta_readiness(project_root) {
|
|
3806
4713
|
if (!_is_source_repo(project_root)) {
|
|
3807
4714
|
return {
|
|
@@ -3813,7 +4720,7 @@ function _check_mcp_beta_readiness(project_root) {
|
|
|
3813
4720
|
}
|
|
3814
4721
|
const pending = [];
|
|
3815
4722
|
for (const [gate_id, rel] of MCP_BETA_GATES) {
|
|
3816
|
-
if (!pathExists(
|
|
4723
|
+
if (!pathExists(path19.join(project_root, rel))) {
|
|
3817
4724
|
pending.push(`${gate_id} (${rel})`);
|
|
3818
4725
|
}
|
|
3819
4726
|
}
|
|
@@ -3834,7 +4741,7 @@ function _check_mcp_beta_readiness(project_root) {
|
|
|
3834
4741
|
}
|
|
3835
4742
|
function _check_tier_usage_readiness(project_root) {
|
|
3836
4743
|
const settings_file = project_settings_path(project_root);
|
|
3837
|
-
let log_path =
|
|
4744
|
+
let log_path = path19.join(project_root, ".agent-tier-usage.jsonl");
|
|
3838
4745
|
let enabled = false;
|
|
3839
4746
|
if (isFile4(settings_file)) {
|
|
3840
4747
|
let raw;
|
|
@@ -3853,7 +4760,7 @@ function _check_tier_usage_readiness(project_root) {
|
|
|
3853
4760
|
const outputRaw = tu["output"];
|
|
3854
4761
|
const output = typeof outputRaw === "object" && outputRaw !== null && !Array.isArray(outputRaw) ? outputRaw : {};
|
|
3855
4762
|
if (typeof output["path"] === "string" && output["path"].trim()) {
|
|
3856
|
-
log_path =
|
|
4763
|
+
log_path = path19.join(project_root, output["path"].trim());
|
|
3857
4764
|
}
|
|
3858
4765
|
const val = tu["enabled"];
|
|
3859
4766
|
if (typeof val === "boolean") {
|
|
@@ -3878,7 +4785,7 @@ function _check_tier_usage_readiness(project_root) {
|
|
|
3878
4785
|
return {
|
|
3879
4786
|
id: "tier-usage-readiness",
|
|
3880
4787
|
status: "warn",
|
|
3881
|
-
message: `tier-usage telemetry on but ${
|
|
4788
|
+
message: `tier-usage telemetry on but ${path19.basename(log_path)} not yet written \u2014 no signal accumulated`,
|
|
3882
4789
|
remedy: "run any tracked command to seed the log; the dispatcher writes one record per invocation"
|
|
3883
4790
|
};
|
|
3884
4791
|
}
|
|
@@ -3893,7 +4800,7 @@ function _check_tier_usage_readiness(project_root) {
|
|
|
3893
4800
|
return {
|
|
3894
4801
|
id: "tier-usage-readiness",
|
|
3895
4802
|
status: "fail",
|
|
3896
|
-
message: `cannot read ${
|
|
4803
|
+
message: `cannot read ${path19.basename(log_path)}: ${osErrorStr(exc)}`,
|
|
3897
4804
|
remedy: "fix permissions on the tier-usage log"
|
|
3898
4805
|
};
|
|
3899
4806
|
}
|
|
@@ -3924,7 +4831,7 @@ function _check_tier_usage_readiness(project_root) {
|
|
|
3924
4831
|
return {
|
|
3925
4832
|
id: "tier-usage-readiness",
|
|
3926
4833
|
status: "fail",
|
|
3927
|
-
message: `${total} record(s) in ${
|
|
4834
|
+
message: `${total} record(s) in ${path19.basename(log_path)} but 0 passed the privacy floor \u2014 report would refuse to render`,
|
|
3928
4835
|
remedy: "inspect the log; the dispatcher is writing records the contract forbids (paths, argv, message bodies)"
|
|
3929
4836
|
};
|
|
3930
4837
|
}
|
|
@@ -3932,19 +4839,19 @@ function _check_tier_usage_readiness(project_root) {
|
|
|
3932
4839
|
return {
|
|
3933
4840
|
id: "tier-usage-readiness",
|
|
3934
4841
|
status: "warn",
|
|
3935
|
-
message: `${
|
|
4842
|
+
message: `${path19.basename(log_path)} present but empty \u2014 no signal yet`,
|
|
3936
4843
|
remedy: "run any tracked command to seed the log"
|
|
3937
4844
|
};
|
|
3938
4845
|
}
|
|
3939
4846
|
return {
|
|
3940
4847
|
id: "tier-usage-readiness",
|
|
3941
4848
|
status: "ok",
|
|
3942
|
-
message: `${valid} record(s) past the privacy floor in ${
|
|
4849
|
+
message: `${valid} record(s) past the privacy floor in ${path19.basename(log_path)} \u2014 retiering signal available`,
|
|
3943
4850
|
remedy: ""
|
|
3944
4851
|
};
|
|
3945
4852
|
}
|
|
3946
4853
|
function readText0(p) {
|
|
3947
|
-
return
|
|
4854
|
+
return fs14.readFileSync(p, "utf-8");
|
|
3948
4855
|
}
|
|
3949
4856
|
function osErrorStr(exc) {
|
|
3950
4857
|
if (exc && typeof exc === "object" && "message" in exc) {
|
|
@@ -4117,7 +5024,7 @@ function _epoch_seconds(value) {
|
|
|
4117
5024
|
function _codex_auth_expiry(auth_path) {
|
|
4118
5025
|
let data;
|
|
4119
5026
|
try {
|
|
4120
|
-
data = JSON.parse(
|
|
5027
|
+
data = JSON.parse(fs14.readFileSync(auth_path, "utf-8"));
|
|
4121
5028
|
} catch {
|
|
4122
5029
|
return null;
|
|
4123
5030
|
}
|
|
@@ -4263,7 +5170,7 @@ function _check_team(project_root) {
|
|
|
4263
5170
|
if (binary_missing) {
|
|
4264
5171
|
remedies.push("install the codex CLI: `npm install -g @openai/codex`");
|
|
4265
5172
|
}
|
|
4266
|
-
const auth_path =
|
|
5173
|
+
const auth_path = path19.join(_codex_home(), "auth.json");
|
|
4267
5174
|
const authed = pathExists(auth_path);
|
|
4268
5175
|
let auth_str;
|
|
4269
5176
|
if (!authed) {
|
|
@@ -4351,7 +5258,7 @@ function _check_unsupported_combos(manifest) {
|
|
|
4351
5258
|
};
|
|
4352
5259
|
}
|
|
4353
5260
|
function _wizard_state_path() {
|
|
4354
|
-
return
|
|
5261
|
+
return path19.join(event4u_root(), "state", "wizard-state.json");
|
|
4355
5262
|
}
|
|
4356
5263
|
function _check_wizard_state() {
|
|
4357
5264
|
const state_pth = _wizard_state_path();
|
|
@@ -4431,7 +5338,7 @@ function _check_wizard_state() {
|
|
|
4431
5338
|
};
|
|
4432
5339
|
}
|
|
4433
5340
|
function _check_settings_review_pending() {
|
|
4434
|
-
const delta_pth =
|
|
5341
|
+
const delta_pth = path19.join(event4u_root(), "state", "settings-delta.json");
|
|
4435
5342
|
if (!pathExists(delta_pth)) {
|
|
4436
5343
|
return {
|
|
4437
5344
|
id: "settings-review-pending",
|
|
@@ -4457,7 +5364,7 @@ function _check_settings_review_pending() {
|
|
|
4457
5364
|
}
|
|
4458
5365
|
function _check_memory_merge_union(project_root) {
|
|
4459
5366
|
const remedy = "run: npx tsx src/scripts/sync_gitattributes.ts (or `agent-config refresh --project`)";
|
|
4460
|
-
const target =
|
|
5367
|
+
const target = path19.join(project_root, DEFAULT_GITATTRIBUTES);
|
|
4461
5368
|
if (!pathExists(target)) {
|
|
4462
5369
|
return {
|
|
4463
5370
|
id: "memory-merge-union",
|
|
@@ -4574,6 +5481,8 @@ function _run_checks(project_root, manifest, drift, only = null) {
|
|
|
4574
5481
|
"claude-command-wrappers": _check_claude_command_wrappers,
|
|
4575
5482
|
"surface-state": _check_surface_state,
|
|
4576
5483
|
"hook-wiring": _check_hook_wiring,
|
|
5484
|
+
...wiringRunners({ packageRoot: _package_root(), iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }),
|
|
5485
|
+
...reachRunners({ projectRoot: project_root, resolvableVersion: _current_package_version() }),
|
|
4577
5486
|
"stale-orphans": _check_stale_orphans,
|
|
4578
5487
|
overrides: () => _check_overrides(project_root),
|
|
4579
5488
|
"rule-scope-drift": () => _check_rule_scope_drift(project_root),
|
|
@@ -4642,6 +5551,8 @@ function _run_checks_no_manifest(project_root, bridge_present, only = null) {
|
|
|
4642
5551
|
"claude-command-wrappers": _check_claude_command_wrappers,
|
|
4643
5552
|
"surface-state": _check_surface_state,
|
|
4644
5553
|
"hook-wiring": _check_hook_wiring,
|
|
5554
|
+
...wiringRunners({ packageRoot: _package_root(), iterOverrides: () => iter_setting_overrides({ cwd: project_root }) }),
|
|
5555
|
+
...reachRunners({ projectRoot: project_root, resolvableVersion: _current_package_version() }),
|
|
4645
5556
|
"stale-orphans": _check_stale_orphans,
|
|
4646
5557
|
// BOTH registries need the id. Registering only the first one crashed with
|
|
4647
5558
|
// `runners[cid] is not a function` on a global-only consumer, which is the
|
|
@@ -4806,8 +5717,8 @@ var _VALUE_FLAGS = {
|
|
|
4806
5717
|
"--repair": "repair"
|
|
4807
5718
|
};
|
|
4808
5719
|
function _argError(msg) {
|
|
4809
|
-
|
|
4810
|
-
|
|
5720
|
+
process3.stderr.write(USAGE);
|
|
5721
|
+
process3.stderr.write(`${PROG}: error: ${msg}
|
|
4811
5722
|
`);
|
|
4812
5723
|
throw new ArgparseExit(2);
|
|
4813
5724
|
}
|
|
@@ -4827,7 +5738,7 @@ function _parse2(argv) {
|
|
|
4827
5738
|
while (i < argv.length) {
|
|
4828
5739
|
const a = argv[i];
|
|
4829
5740
|
if (a === "-h" || a === "--help") {
|
|
4830
|
-
|
|
5741
|
+
process3.stdout.write(USAGE);
|
|
4831
5742
|
throw new ArgparseExit(0);
|
|
4832
5743
|
}
|
|
4833
5744
|
const eq = a.startsWith("--") ? a.indexOf("=") : -1;
|
|
@@ -4885,14 +5796,14 @@ function argMetaName(flag) {
|
|
|
4885
5796
|
return flag;
|
|
4886
5797
|
}
|
|
4887
5798
|
function _run_trace_root(opts) {
|
|
4888
|
-
const start =
|
|
5799
|
+
const start = process3.cwd();
|
|
4889
5800
|
const [root, anchor, trace] = find_project_root_with_trace(start);
|
|
4890
5801
|
let origin;
|
|
4891
|
-
if (
|
|
5802
|
+
if (process3.env[ROOT_OVERRIDE_ENV] === "1" && process3.env[PROJECT_ROOT_ENV]) {
|
|
4892
5803
|
origin = "root-flag";
|
|
4893
5804
|
} else if (opts.project) {
|
|
4894
5805
|
origin = "explicit";
|
|
4895
|
-
} else if (
|
|
5806
|
+
} else if (process3.env[PROJECT_ROOT_ENV]) {
|
|
4896
5807
|
origin = "env";
|
|
4897
5808
|
} else if (root !== null) {
|
|
4898
5809
|
origin = anchor || "unknown";
|
|
@@ -4924,8 +5835,8 @@ function _run_context(opts) {
|
|
|
4924
5835
|
origin,
|
|
4925
5836
|
install_mode: mode,
|
|
4926
5837
|
install_mode_source: mode_source,
|
|
4927
|
-
env_pin:
|
|
4928
|
-
root_override:
|
|
5838
|
+
env_pin: process3.env[PROJECT_ROOT_ENV] || null,
|
|
5839
|
+
root_override: process3.env[ROOT_OVERRIDE_ENV] === "1",
|
|
4929
5840
|
settings_layers: _settings_layer_chain(project_root),
|
|
4930
5841
|
wrapper: _detect_wrapper(project_root)
|
|
4931
5842
|
};
|
|
@@ -4945,7 +5856,7 @@ function _run_anatomy(opts) {
|
|
|
4945
5856
|
try {
|
|
4946
5857
|
economyReport = economy.buildReport({
|
|
4947
5858
|
root: economy.DEFAULT_PROJECTS_ROOT,
|
|
4948
|
-
auditDir:
|
|
5859
|
+
auditDir: path19.join(process3.cwd(), economy.DEFAULT_AUDIT_DIR),
|
|
4949
5860
|
maxAgeDays: 14
|
|
4950
5861
|
});
|
|
4951
5862
|
} catch (err) {
|
|
@@ -4984,7 +5895,7 @@ function _run_repair(opts) {
|
|
|
4984
5895
|
};
|
|
4985
5896
|
if (exists2) {
|
|
4986
5897
|
try {
|
|
4987
|
-
|
|
5898
|
+
fs14.unlinkSync(state_pth);
|
|
4988
5899
|
} catch (exc) {
|
|
4989
5900
|
payload["action"] = "error";
|
|
4990
5901
|
payload["error"] = osErrorStr(exc);
|
|
@@ -5010,8 +5921,8 @@ function _run_repair(opts) {
|
|
|
5010
5921
|
eprint(`\u274C doctor: unknown repair target ${pyRepr(target)}`);
|
|
5011
5922
|
return 2;
|
|
5012
5923
|
}
|
|
5013
|
-
function
|
|
5014
|
-
const opts = _parse2(argv !== null ? Array.from(argv) :
|
|
5924
|
+
function main6(argv = null) {
|
|
5925
|
+
const opts = _parse2(argv !== null ? Array.from(argv) : process3.argv.slice(2));
|
|
5015
5926
|
if (opts.ci) {
|
|
5016
5927
|
opts.json = true;
|
|
5017
5928
|
}
|
|
@@ -5084,32 +5995,32 @@ function _isCliEntry2() {
|
|
|
5084
5995
|
if (bundled && !cliDelegate) {
|
|
5085
5996
|
return false;
|
|
5086
5997
|
}
|
|
5087
|
-
if (
|
|
5998
|
+
if (process3.argv[1] === void 0) {
|
|
5088
5999
|
return false;
|
|
5089
6000
|
}
|
|
5090
6001
|
if (cliDelegate) {
|
|
5091
|
-
if (
|
|
6002
|
+
if (path19.basename(process3.argv[1], ".js") === "cmd_doctor") {
|
|
5092
6003
|
return true;
|
|
5093
6004
|
}
|
|
5094
6005
|
}
|
|
5095
|
-
const argvUrl =
|
|
6006
|
+
const argvUrl = pathToFileURL6(path19.resolve(process3.argv[1])).href;
|
|
5096
6007
|
if (import.meta.url === argvUrl) {
|
|
5097
6008
|
return true;
|
|
5098
6009
|
}
|
|
5099
6010
|
try {
|
|
5100
|
-
const here =
|
|
5101
|
-
const argv =
|
|
6011
|
+
const here = fs14.realpathSync(fileURLToPath5(import.meta.url));
|
|
6012
|
+
const argv = fs14.realpathSync(path19.resolve(process3.argv[1]));
|
|
5102
6013
|
return here === argv;
|
|
5103
6014
|
} catch {
|
|
5104
6015
|
return false;
|
|
5105
6016
|
}
|
|
5106
6017
|
}
|
|
5107
|
-
if (_isCliEntry2() ||
|
|
6018
|
+
if (_isCliEntry2() || process3.argv[1] === _HERE5) {
|
|
5108
6019
|
try {
|
|
5109
|
-
|
|
6020
|
+
process3.exitCode = main6(process3.argv.slice(2));
|
|
5110
6021
|
} catch (e) {
|
|
5111
6022
|
if (e instanceof ArgparseExit) {
|
|
5112
|
-
|
|
6023
|
+
process3.exitCode = e.code;
|
|
5113
6024
|
} else {
|
|
5114
6025
|
throw e;
|
|
5115
6026
|
}
|
|
@@ -5186,5 +6097,5 @@ export {
|
|
|
5186
6097
|
_run_trace_root,
|
|
5187
6098
|
_run_context,
|
|
5188
6099
|
_run_repair,
|
|
5189
|
-
|
|
6100
|
+
main6 as main
|
|
5190
6101
|
};
|