@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
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Runtime event journal — the hook binding
|
|
4
|
+
* (road-to-runtime-event-journal Phase 1, step 1.4; AI council 2026-08-28,
|
|
5
|
+
* decision 3).
|
|
6
|
+
*
|
|
7
|
+
* ## Why this exists
|
|
8
|
+
*
|
|
9
|
+
* `_lib/runtime_journal.ts` shipped as a module bound in no hook slot, so
|
|
10
|
+
* production capture was **zero by construction** and step 1.4's measurement
|
|
11
|
+
* had no numerator AND no denominator. Both council seats read the honest
|
|
12
|
+
* `undefined` as correct and as NOT discharging 1.4: *"zero numerator does not
|
|
13
|
+
* establish 0 % when the population itself was not observed."* This concern is
|
|
14
|
+
* the population. Binding is inside Phase 1's own goal — the phase is titled
|
|
15
|
+
* "The journal, written by hooks that terminate" — not scope creep.
|
|
16
|
+
*
|
|
17
|
+
* ## Class A, and provably so
|
|
18
|
+
*
|
|
19
|
+
* Start, write, exit. No resident process, no listening socket, no timer, no
|
|
20
|
+
* shared in-memory state between invocations — `openJournal` … `close()` inside
|
|
21
|
+
* one call and nothing survives it. Identical shape to `_lib/test_red_state.ts`
|
|
22
|
+
* and to the sibling instruments (`tool_result_bytes_hook`,
|
|
23
|
+
* `subagent_ledger_hook`, `orchestration_record_hook`). AC-8 is checkable from
|
|
24
|
+
* this file alone.
|
|
25
|
+
*
|
|
26
|
+
* ## It never blocks and never fails a turn
|
|
27
|
+
*
|
|
28
|
+
* Exit code is ALWAYS `EXIT_ALLOW` (0) on every path — settings unreadable,
|
|
29
|
+
* `node:sqlite` unavailable, envelope malformed, database locked, disk full,
|
|
30
|
+
* contract violation raised by the writer. A journal write problem is swallowed
|
|
31
|
+
* and the turn proceeds; a hook `warn` (exit 2) is read as a hard BLOCK on this
|
|
32
|
+
* host and this concern has nothing to say to the model, so it never warns
|
|
33
|
+
* either. `fail_closed: false`, `severity: advisory` in the manifest.
|
|
34
|
+
*
|
|
35
|
+
* ## Default-OFF, and the cost of that choice is stated rather than hidden
|
|
36
|
+
*
|
|
37
|
+
* Gated on `hooks.runtime_journal.enabled` in `.agent-settings.yml`; absent or
|
|
38
|
+
* unreadable ⇒ off. Two conventions exist for a new concern in this tree and
|
|
39
|
+
* the choice is deliberate:
|
|
40
|
+
*
|
|
41
|
+
* - The append-a-JSONL-line instruments (`orchestration-record`,
|
|
42
|
+
* `tool-result-bytes`, `subagent-ledger`) ship ON with no setting at all.
|
|
43
|
+
* They write into `agents/runtime/state/`, a gitignored directory that
|
|
44
|
+
* already exists.
|
|
45
|
+
* - The journal creates a **new storage surface** — a SQLite database and a
|
|
46
|
+
* directory under `<git-common-dir>` — in every repository it runs in. That
|
|
47
|
+
* is engine-shaped, and ADR-124 § 3 ("falsifiability-first: every native
|
|
48
|
+
* engine ships default-off, activates via tripwire or explicit setting") is
|
|
49
|
+
* explicitly NOT superseded by ADR-249.
|
|
50
|
+
*
|
|
51
|
+
* So: OFF. **The honest consequence is that a default install still records
|
|
52
|
+
* nothing**, and 1.4's production number moves from *zero by construction* to
|
|
53
|
+
* *zero until opted in*. That is a change in kind — the path now exists, is
|
|
54
|
+
* bound, and is exercisable — and it is not yet a production capture rate. The
|
|
55
|
+
* evidence page says so in those words rather than reporting the dispatch-path
|
|
56
|
+
* figure as if it were the host one.
|
|
57
|
+
*
|
|
58
|
+
* ## What is recorded, and what is refused
|
|
59
|
+
*
|
|
60
|
+
* PRIVACY BY CONSTRUCTION — never widen this file to read or emit free text.
|
|
61
|
+
* The record type it writes has no field able to hold content
|
|
62
|
+
* (`JOURNAL_RECORD_KEYS`, bound to the type in both directions by a
|
|
63
|
+
* compile-time assertion). This concern additionally reads only:
|
|
64
|
+
*
|
|
65
|
+
* - the dispatcher's `event` — a member of a closed vocabulary;
|
|
66
|
+
* - `session_id` — an opaque host token, already recorded by
|
|
67
|
+
* `session_register` and stored here as an id, never parsed;
|
|
68
|
+
* - `task_id` / `prompt_id` where the host supplies them (Cline's `taskId` is
|
|
69
|
+
* the one observed source today — see § The task_id gap);
|
|
70
|
+
* - the TOOL NAME, reduced to a bounded identifier. `Read` / `Bash` / `Grep`
|
|
71
|
+
* is the id-shaped enum class `tool_result_bytes_hook` and
|
|
72
|
+
* `orchestration_record_hook` already record verbatim.
|
|
73
|
+
*
|
|
74
|
+
* It never reads `tool_input`, `tool_response`, a prompt, a path, or a diff —
|
|
75
|
+
* which is why it declares no `needs_payload_bodies` in the manifest and would
|
|
76
|
+
* be no more informed if it did.
|
|
77
|
+
*
|
|
78
|
+
* ## The task_id gap, stated because it bounds the episode spine
|
|
79
|
+
*
|
|
80
|
+
* The boundary rule opens an episode on the first event carrying a `task_id`
|
|
81
|
+
* (council 2026-08-28, envelope correlation). The DISPATCHER envelope carries
|
|
82
|
+
* no task id on Claude: `hooks/envelope.ts`'s documented shape is
|
|
83
|
+
* `{schema_version, platform, event, native_event, session_id, workspace_root,
|
|
84
|
+
* payload, settings}`. Cline's native payload carries `taskId` and is read.
|
|
85
|
+
* Everywhere else every record lands `boundary_status: session_fallback` —
|
|
86
|
+
* MARKED, never silently dropped, exactly as the blocker's resolution requires.
|
|
87
|
+
* Threading the outcome envelope's task id into the dispatcher envelope is
|
|
88
|
+
* Phase 3's, and inventing one here would fabricate the boundary provenance the
|
|
89
|
+
* spine exists to record.
|
|
90
|
+
*/
|
|
91
|
+
import * as fs from 'node:fs';
|
|
92
|
+
import * as path from 'node:path';
|
|
93
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
94
|
+
|
|
95
|
+
import { hookSectionEnabled } from '../_lib/hook_settings.js';
|
|
96
|
+
import {
|
|
97
|
+
RECORDED_EVENTS,
|
|
98
|
+
isJournalAvailable,
|
|
99
|
+
recordEvent,
|
|
100
|
+
withJournal,
|
|
101
|
+
} from '../_lib/runtime_journal.js';
|
|
102
|
+
import { readHookStdin } from './hook_stdin.js';
|
|
103
|
+
import { is_replay_mode } from './state_io.js';
|
|
104
|
+
|
|
105
|
+
const EXIT_ALLOW = 0;
|
|
106
|
+
|
|
107
|
+
/** The `.agent-settings.yml` section under `hooks:` that arms this concern. */
|
|
108
|
+
export const SETTINGS_SECTION = 'runtime_journal';
|
|
109
|
+
|
|
110
|
+
// Exported so the test constructs fixtures against THIS definition rather than
|
|
111
|
+
// a hand-copied twin: `tsconfig.scripts.json` is stricter than the base config
|
|
112
|
+
// and rejects `Record<string, unknown>` here, which is the drift a second copy
|
|
113
|
+
// would reintroduce the moment either side changed.
|
|
114
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | { [k: string]: JsonValue };
|
|
115
|
+
export type JsonObject = { [k: string]: JsonValue };
|
|
116
|
+
|
|
117
|
+
function isObject(v: unknown): v is JsonObject {
|
|
118
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function unwrapPayload(envelope: JsonObject): JsonObject {
|
|
122
|
+
const inner = envelope['payload'];
|
|
123
|
+
return isObject(inner) ? inner : envelope;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** First non-empty string under any of `keys`, searched envelope then payload. */
|
|
127
|
+
function firstString(envelope: JsonObject, payload: JsonObject, keys: readonly string[]): string | null {
|
|
128
|
+
for (const source of [envelope, payload]) {
|
|
129
|
+
for (const key of keys) {
|
|
130
|
+
const v = source[key];
|
|
131
|
+
if (typeof v === 'string' && v.trim() !== '') return v.trim();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Reduce a host string to the journal's bounded-identifier shape
|
|
139
|
+
* (`^[a-z0-9][a-z0-9._:-]{0,63}$`), or `null` when nothing survives.
|
|
140
|
+
*
|
|
141
|
+
* Lower-cases, folds every character outside the allowed set to `-`, collapses
|
|
142
|
+
* runs, trims to a legal first character, and truncates to 64. A value that
|
|
143
|
+
* cannot be reduced to a legal identifier is REFUSED rather than coerced into
|
|
144
|
+
* something shorter and wrong — the caller then falls back to the event name,
|
|
145
|
+
* which is always legal.
|
|
146
|
+
*/
|
|
147
|
+
export function toCapability(raw: string): string | null {
|
|
148
|
+
const folded = raw
|
|
149
|
+
.trim()
|
|
150
|
+
.toLowerCase()
|
|
151
|
+
.replace(/[^a-z0-9._:-]+/g, '-')
|
|
152
|
+
.replace(/-{2,}/g, '-')
|
|
153
|
+
.replace(/^[^a-z0-9]+/, '')
|
|
154
|
+
.slice(0, 64)
|
|
155
|
+
// Trailing separators are legal in the grammar and read as truncation
|
|
156
|
+
// damage, so they are trimmed rather than kept.
|
|
157
|
+
.replace(/[._:-]+$/, '');
|
|
158
|
+
return folded === '' ? null : folded;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** The tool name, read from the positions the sibling instruments read. */
|
|
162
|
+
export function toolName(envelope: JsonObject, payload: JsonObject): string | null {
|
|
163
|
+
return firstString(envelope, payload, ['tool_name', 'toolName', 'tool']);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** What this event invoked, as a bounded identifier. Never free text. */
|
|
167
|
+
export function capabilityFor(event: string, envelope: JsonObject, payload: JsonObject): string {
|
|
168
|
+
const tool = toolName(envelope, payload);
|
|
169
|
+
if (tool !== null) {
|
|
170
|
+
const reduced = toCapability(tool);
|
|
171
|
+
if (reduced !== null) return reduced;
|
|
172
|
+
}
|
|
173
|
+
// Always legal: every member of the event vocabulary is already
|
|
174
|
+
// lower-snake and inside the identifier grammar.
|
|
175
|
+
return toCapability(event) ?? 'unknown';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** One dispatcher envelope reduced to the fields the journal accepts. */
|
|
179
|
+
export interface JournalInput {
|
|
180
|
+
event: string;
|
|
181
|
+
session_id: string;
|
|
182
|
+
task_id: string | null;
|
|
183
|
+
prompt_id: string | null;
|
|
184
|
+
capability: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Reduce an envelope, or `null` when it cannot be recorded.
|
|
189
|
+
*
|
|
190
|
+
* `null` is returned for an event outside {@link RECORDED_EVENTS} (a host
|
|
191
|
+
* vocabulary this journal has not placed in one set or the other) and for an
|
|
192
|
+
* envelope carrying no session id — an event with no session cannot be keyed at
|
|
193
|
+
* all, and a synthesised key would be a fabricated boundary.
|
|
194
|
+
*/
|
|
195
|
+
export function reduceEnvelope(envelope: JsonObject): JournalInput | null {
|
|
196
|
+
const event = typeof envelope['event'] === 'string' ? envelope['event'] : '';
|
|
197
|
+
if (!RECORDED_EVENTS.has(event)) return null;
|
|
198
|
+
|
|
199
|
+
const payload = unwrapPayload(envelope);
|
|
200
|
+
const session_id = firstString(envelope, payload, ['session_id', 'sessionId']);
|
|
201
|
+
if (session_id === null) return null;
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
event,
|
|
205
|
+
session_id,
|
|
206
|
+
// `taskId` is Cline's native payload key; the dispatcher envelope
|
|
207
|
+
// carries none on Claude. Absent ⇒ session_fallback, marked.
|
|
208
|
+
task_id: firstString(envelope, payload, ['task_id', 'taskId']),
|
|
209
|
+
prompt_id: firstString(envelope, payload, ['prompt_id', 'promptId']),
|
|
210
|
+
capability: capabilityFor(event, envelope, payload),
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** The consumer repo root, same precedence as the sibling instruments. */
|
|
215
|
+
export function resolveConsumerRoot(envelope: JsonValue): string {
|
|
216
|
+
if (isObject(envelope)) {
|
|
217
|
+
for (const key of ['workspace_root', 'project_root']) {
|
|
218
|
+
const v = envelope[key];
|
|
219
|
+
if (typeof v === 'string' && v) return v;
|
|
220
|
+
}
|
|
221
|
+
const cwd = unwrapPayload(envelope)['cwd'];
|
|
222
|
+
if (typeof cwd === 'string' && cwd) return cwd;
|
|
223
|
+
}
|
|
224
|
+
return process.cwd();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Process an ALREADY-PARSED envelope. Always returns `EXIT_ALLOW`.
|
|
229
|
+
*
|
|
230
|
+
* Returns nothing about whether it wrote — deliberately. A concern that
|
|
231
|
+
* reported its own success to the dispatcher would be a channel the dispatcher
|
|
232
|
+
* has no use for; {@link recordedFor} is the test-facing answer.
|
|
233
|
+
*/
|
|
234
|
+
export function processEnvelope(envelope: JsonValue, consumerRoot: string): number {
|
|
235
|
+
try {
|
|
236
|
+
if (!isObject(envelope)) return EXIT_ALLOW;
|
|
237
|
+
if (is_replay_mode()) return EXIT_ALLOW;
|
|
238
|
+
if (!hookSectionEnabled(consumerRoot, SETTINGS_SECTION)) return EXIT_ALLOW;
|
|
239
|
+
if (!isJournalAvailable()) return EXIT_ALLOW;
|
|
240
|
+
|
|
241
|
+
const input = reduceEnvelope(envelope);
|
|
242
|
+
if (input === null) return EXIT_ALLOW;
|
|
243
|
+
|
|
244
|
+
withJournal(consumerRoot, (h) => {
|
|
245
|
+
recordEvent(h, {
|
|
246
|
+
event: input.event,
|
|
247
|
+
session_id: input.session_id,
|
|
248
|
+
task_id: input.task_id,
|
|
249
|
+
prompt_id: input.prompt_id,
|
|
250
|
+
capability: input.capability,
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
} catch {
|
|
254
|
+
// Locked database, unreadable settings, contract violation, full disk —
|
|
255
|
+
// never disturb the run. An instrument that can fail a turn is a
|
|
256
|
+
// mechanism, and this is not one.
|
|
257
|
+
return EXIT_ALLOW;
|
|
258
|
+
}
|
|
259
|
+
return EXIT_ALLOW;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Test-facing: did this envelope produce a record, and if not, why not?
|
|
264
|
+
*
|
|
265
|
+
* Exists so a capture measurement can state a DENOMINATOR. Counting only the
|
|
266
|
+
* records would make "the gate is off" and "the event is not in the vocabulary"
|
|
267
|
+
* and "the write failed" indistinguishable, which is the blind-zero class the
|
|
268
|
+
* roadmap's own 1.4 verify line refuses.
|
|
269
|
+
*/
|
|
270
|
+
export type SkipReason =
|
|
271
|
+
| 'not-an-envelope'
|
|
272
|
+
| 'replay-mode'
|
|
273
|
+
| 'disabled'
|
|
274
|
+
| 'sqlite-unavailable'
|
|
275
|
+
| 'event-not-recorded'
|
|
276
|
+
| 'no-session-id'
|
|
277
|
+
| 'write-failed';
|
|
278
|
+
|
|
279
|
+
export function recordedFor(envelope: JsonValue, consumerRoot: string): SkipReason | null {
|
|
280
|
+
if (!isObject(envelope)) return 'not-an-envelope';
|
|
281
|
+
if (is_replay_mode()) return 'replay-mode';
|
|
282
|
+
if (!hookSectionEnabled(consumerRoot, SETTINGS_SECTION)) return 'disabled';
|
|
283
|
+
if (!isJournalAvailable()) return 'sqlite-unavailable';
|
|
284
|
+
const input = reduceEnvelope(envelope);
|
|
285
|
+
if (input === null) {
|
|
286
|
+
const event = typeof envelope['event'] === 'string' ? envelope['event'] : '';
|
|
287
|
+
return RECORDED_EVENTS.has(event) ? 'no-session-id' : 'event-not-recorded';
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
withJournal(consumerRoot, (h) => {
|
|
291
|
+
recordEvent(h, {
|
|
292
|
+
event: input.event,
|
|
293
|
+
session_id: input.session_id,
|
|
294
|
+
task_id: input.task_id,
|
|
295
|
+
prompt_id: input.prompt_id,
|
|
296
|
+
capability: input.capability,
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
} catch {
|
|
300
|
+
return 'write-failed';
|
|
301
|
+
}
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/** The dispatcher's string-in entry point, kept for direct invocation. */
|
|
306
|
+
export function run(stdin_text: string, options: { consumer_root: string }): number {
|
|
307
|
+
let envelope: JsonValue;
|
|
308
|
+
try {
|
|
309
|
+
const raw = stdin_text.trim();
|
|
310
|
+
if (!raw) return EXIT_ALLOW;
|
|
311
|
+
envelope = JSON.parse(raw) as JsonValue;
|
|
312
|
+
} catch {
|
|
313
|
+
return EXIT_ALLOW;
|
|
314
|
+
}
|
|
315
|
+
return processEnvelope(envelope, options.consumer_root);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function main(): number {
|
|
319
|
+
const raw = readHookStdin();
|
|
320
|
+
let envelope: JsonValue = {};
|
|
321
|
+
try {
|
|
322
|
+
envelope = raw.trim() ? (JSON.parse(raw) as JsonValue) : {};
|
|
323
|
+
} catch {
|
|
324
|
+
return EXIT_ALLOW;
|
|
325
|
+
}
|
|
326
|
+
return processEnvelope(envelope, resolveConsumerRoot(envelope));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Bundle-safety: never auto-run when inlined into an esbuild bundle, where
|
|
330
|
+
// every module shares the bundle's `import.meta.url`.
|
|
331
|
+
declare const __AGENT_CONFIG_BUNDLE__: boolean | undefined;
|
|
332
|
+
function _isCliEntry(): boolean {
|
|
333
|
+
if (typeof __AGENT_CONFIG_BUNDLE__ !== 'undefined' && __AGENT_CONFIG_BUNDLE__) {
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
if (process.argv[1] === undefined) return false;
|
|
337
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
338
|
+
if (import.meta.url === argvUrl) return true;
|
|
339
|
+
try {
|
|
340
|
+
return fs.realpathSync(fileURLToPath(import.meta.url)) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
341
|
+
} catch {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (_isCliEntry()) process.exit(main());
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# road-to-source-silence Phase 4.3 — the local half of the metadata gate.
|
|
3
|
+
#
|
|
4
|
+
# `.github/workflows/pr-metadata-sources.yml` is the backstop, and by the time
|
|
5
|
+
# it runs the branch name and commit messages are already on the remote. This
|
|
6
|
+
# script gives the author the same verdict while the metadata is still private,
|
|
7
|
+
# which is the only point at which fixing it is free: a pushed branch ref and a
|
|
8
|
+
# pushed commit message are public, and the recorded decision of the
|
|
9
|
+
# `whether-history-gets-rewritten` blocker is that they are never rewritten.
|
|
10
|
+
#
|
|
11
|
+
# Checks the branch being pushed and the commit messages the push would add.
|
|
12
|
+
# The PR title and body do not exist yet locally, so those two surfaces are
|
|
13
|
+
# CI-only — stated rather than implied, because a local pass is not a full pass.
|
|
14
|
+
#
|
|
15
|
+
# Install (opt-in, a human action — this repo does not write to .git/hooks):
|
|
16
|
+
#
|
|
17
|
+
# ln -s ../../src/scripts/hooks/prepush_metadata_sources.sh .git/hooks/pre-push
|
|
18
|
+
#
|
|
19
|
+
# or, if a pre-push hook already exists, call this from it:
|
|
20
|
+
#
|
|
21
|
+
# src/scripts/hooks/prepush_metadata_sources.sh "$@" || exit 1
|
|
22
|
+
#
|
|
23
|
+
# Bypass, for a maintainer who needs it: AGENT_CONFIG_SKIP_METADATA_GATE=1.
|
|
24
|
+
# `git push --no-verify` also bypasses it and is blocked for agents by the
|
|
25
|
+
# `block-no-verify` guard; that asymmetry is deliberate — a human may bypass
|
|
26
|
+
# their own local hook, an agent may not.
|
|
27
|
+
set -euo pipefail
|
|
28
|
+
|
|
29
|
+
if [ -n "${AGENT_CONFIG_SKIP_METADATA_GATE:-}" ]; then
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
|
34
|
+
cd "${REPO_ROOT}"
|
|
35
|
+
|
|
36
|
+
if [ ! -x ./scripts-run ]; then
|
|
37
|
+
# No runner in this checkout: say so and let the push through rather than
|
|
38
|
+
# blocking on our own missing tooling. CI still gates the same surfaces.
|
|
39
|
+
echo "pre-push: ./scripts-run not found — skipping the source-metadata gate (CI still runs it)." >&2
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
44
|
+
RANGE=""
|
|
45
|
+
|
|
46
|
+
# git feeds pre-push `<local ref> <local sha> <remote ref> <remote sha>` on
|
|
47
|
+
# stdin, one line per ref. An all-zero remote sha means a new branch, for which
|
|
48
|
+
# there is no useful range — fall back to the merge base with the default trunk.
|
|
49
|
+
ZERO="0000000000000000000000000000000000000000"
|
|
50
|
+
while read -r _local_ref local_sha _remote_ref remote_sha; do
|
|
51
|
+
[ -z "${local_sha:-}" ] && continue
|
|
52
|
+
# An all-zero LOCAL sha is a branch DELETION: nothing is being added, so
|
|
53
|
+
# there is no commit range, and building one from zeros made `git log` fail
|
|
54
|
+
# and the failure read as a confidentiality finding.
|
|
55
|
+
[ "${local_sha}" = "0000000000000000000000000000000000000000" ] && continue
|
|
56
|
+
if [ "${remote_sha:-${ZERO}}" = "${ZERO}" ]; then
|
|
57
|
+
base="$(git merge-base "${local_sha}" origin/main 2>/dev/null || true)"
|
|
58
|
+
[ -n "${base}" ] && RANGE="${base}..${local_sha}"
|
|
59
|
+
else
|
|
60
|
+
RANGE="${remote_sha}..${local_sha}"
|
|
61
|
+
fi
|
|
62
|
+
done || true
|
|
63
|
+
|
|
64
|
+
ARGS=(--gate-metadata --branch "${BRANCH}")
|
|
65
|
+
if [ -n "${RANGE}" ]; then
|
|
66
|
+
ARGS+=(--commit-range "${RANGE}")
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Exit codes are NOT interchangeable and were being conflated: 1 is a real
|
|
70
|
+
# finding, 2 is a usage error or an unreadable config, and anything else is the
|
|
71
|
+
# tool failing rather than the change failing. Reporting all of them as
|
|
72
|
+
# "carries source attribution" told an author to rewrite a clean branch name.
|
|
73
|
+
set +e
|
|
74
|
+
./scripts-run src/scripts/sweep_source_surfaces "${ARGS[@]}"
|
|
75
|
+
rc=$?
|
|
76
|
+
set -e
|
|
77
|
+
|
|
78
|
+
if [ "${rc}" -eq 2 ]; then
|
|
79
|
+
echo "pre-push: the source-metadata gate could not RUN (exit 2 — usage or unreadable config)." >&2
|
|
80
|
+
echo " This is not a finding about your branch. CI runs the same check." >&2
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if [ "${rc}" -ne 0 ] && [ "${rc}" -ne 1 ]; then
|
|
85
|
+
echo "pre-push: the source-metadata gate exited ${rc} — unexpected, and not a finding." >&2
|
|
86
|
+
echo " Letting the push through; CI runs the same check." >&2
|
|
87
|
+
exit 0
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
if [ "${rc}" -eq 1 ]; then
|
|
91
|
+
cat >&2 <<'EOF'
|
|
92
|
+
|
|
93
|
+
pre-push: BLOCKED by the source-metadata gate.
|
|
94
|
+
|
|
95
|
+
A branch name or commit message in this push carries source attribution. Both
|
|
96
|
+
become public on push and are effectively permanent: the recorded decision is
|
|
97
|
+
that trunk history is NOT rewritten, so this is the last moment it is free to
|
|
98
|
+
fix.
|
|
99
|
+
|
|
100
|
+
branch -> git branch -m <opaque-name>
|
|
101
|
+
commit -> git commit --amend (or an interactive rebase for an older one)
|
|
102
|
+
|
|
103
|
+
Opaque forms: inbox-2026-08-h · round-a91f3c · S17
|
|
104
|
+
Rule: src/rules/source-confidentiality.md
|
|
105
|
+
Bypass, deliberately: AGENT_CONFIG_SKIP_METADATA_GATE=1 git push ...
|
|
106
|
+
EOF
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
exit 0
|
|
@@ -168,6 +168,13 @@ const EXIT_BLOCK = 1;
|
|
|
168
168
|
* same defect the next time one side is tuned.
|
|
169
169
|
*/
|
|
170
170
|
import { TRANSCRIPT_READ_MAX_BYTES } from './turn_end_gate_hook.js';
|
|
171
|
+
import {
|
|
172
|
+
atomicWriteJson,
|
|
173
|
+
readUnavailableDependency,
|
|
174
|
+
stallSignal,
|
|
175
|
+
type StallLevel,
|
|
176
|
+
type UnavailableDependency,
|
|
177
|
+
} from '../_lib/loop_guards.js';
|
|
171
178
|
|
|
172
179
|
/** Re-exported so a test can assert the IDENTITY, not two matching literals. */
|
|
173
180
|
export { TRANSCRIPT_READ_MAX_BYTES };
|
|
@@ -212,6 +219,11 @@ export interface RunState {
|
|
|
212
219
|
last_turn: number;
|
|
213
220
|
/** Open-step count recorded at each engagement, newest last. */
|
|
214
221
|
history: number[];
|
|
222
|
+
/**
|
|
223
|
+
* The derived stall level (Phase 6.6): `progressing` | `flat` | `stalled`.
|
|
224
|
+
* Written by the producer so a reader never re-derives it from `history`.
|
|
225
|
+
*/
|
|
226
|
+
stall?: StallLevel;
|
|
215
227
|
/**
|
|
216
228
|
* Set once the over-cap-transcript rung has reported this run inert.
|
|
217
229
|
*
|
|
@@ -341,7 +353,8 @@ export type LadderAction =
|
|
|
341
353
|
| 'blocked'
|
|
342
354
|
| 'halt-max-iterations'
|
|
343
355
|
| 'halt-wall-clock'
|
|
344
|
-
| 'halt-stall'
|
|
356
|
+
| 'halt-stall'
|
|
357
|
+
| 'halt-dependency-unavailable';
|
|
345
358
|
|
|
346
359
|
/** The terminal rungs — the set `RunState.halted` may hold. */
|
|
347
360
|
/**
|
|
@@ -356,6 +369,10 @@ export const HALT_ACTIONS: readonly LadderAction[] = [
|
|
|
356
369
|
'halt-max-iterations',
|
|
357
370
|
'halt-wall-clock',
|
|
358
371
|
'halt-stall',
|
|
372
|
+
// Phase 5.4. Checked BEFORE the counter rungs: a dependency the run cannot
|
|
373
|
+
// obtain is not something more iterations close, so consuming the budget
|
|
374
|
+
// against it is the waste the rung exists to stop.
|
|
375
|
+
'halt-dependency-unavailable',
|
|
359
376
|
];
|
|
360
377
|
|
|
361
378
|
/**
|
|
@@ -479,6 +496,9 @@ export function ladder(
|
|
|
479
496
|
wallClockMs: WALL_CLOCK_CAP_MS,
|
|
480
497
|
stallWindow: STALL_WINDOW,
|
|
481
498
|
},
|
|
499
|
+
// Phase 5.4. `null` when nothing unobtainable was detected. Optional so every
|
|
500
|
+
// existing caller and test keeps its meaning unchanged.
|
|
501
|
+
unavailable: UnavailableDependency | null = null,
|
|
482
502
|
): LadderAction {
|
|
483
503
|
// A halt is terminal for this run id. Checked BEFORE `complete` so a
|
|
484
504
|
// halted run whose roadmap later reads zero-open does not report a
|
|
@@ -488,6 +508,10 @@ export function ladder(
|
|
|
488
508
|
// with blocked steps left is exhaustion of runnable work, not completion —
|
|
489
509
|
// ADR-235's own terminal outcome, and never a sixth halt.
|
|
490
510
|
if (openCount === 0) return blockedCount > 0 ? 'blocked' : 'complete';
|
|
511
|
+
// BEFORE the counter rungs, deliberately: a missing credential, an absent
|
|
512
|
+
// binary or an exhausted quota is not closed by iterating, so spending the
|
|
513
|
+
// budget on it converts a nameable blocker into an anonymous cap-out.
|
|
514
|
+
if (unavailable !== null) return 'halt-dependency-unavailable';
|
|
491
515
|
if (state.iterations >= caps.maxIterations) return 'halt-max-iterations';
|
|
492
516
|
const started = Date.parse(state.started_at);
|
|
493
517
|
if (Number.isFinite(started) && nowMs - started >= caps.wallClockMs) {
|
|
@@ -576,13 +600,12 @@ export function readRunState(
|
|
|
576
600
|
* the ladder cannot bound the loop. Every other caller ignores it (fail-open).
|
|
577
601
|
*/
|
|
578
602
|
function writeState(file: string, state: RunState): boolean {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
603
|
+
// ATOMIC (runtime-enforcement Phase 5.2): temp beside the target, then
|
|
604
|
+
// rename. This file is the loop's ITERATION BUDGET — a torn direct write
|
|
605
|
+
// leaves a record `parseRecord` rejects, the counter restarts at zero, and
|
|
606
|
+
// the cap stops bounding anything. A non-atomic budget write fails as an
|
|
607
|
+
// UNBOUNDED loop, which is what the budget exists to prevent.
|
|
608
|
+
return atomicWriteJson(file, state);
|
|
586
609
|
}
|
|
587
610
|
|
|
588
611
|
/**
|
|
@@ -1377,7 +1400,19 @@ export function main(): number {
|
|
|
1377
1400
|
state.history_source = roadmapFile;
|
|
1378
1401
|
}
|
|
1379
1402
|
|
|
1380
|
-
|
|
1403
|
+
// Phase 5.4 — a dependency the run cannot obtain. Read from the transcript
|
|
1404
|
+
// TAIL only: an authentication failure from an hour ago that was then fixed
|
|
1405
|
+
// must not halt the run now. A read failure is `null` (fail-open), because a
|
|
1406
|
+
// detector that cannot read must not manufacture a halt.
|
|
1407
|
+
const unavailable = readUnavailableDependency(transcriptPath);
|
|
1408
|
+
|
|
1409
|
+
// Phase 6.6 — the stall signal, WRITTEN rather than re-derived. A consumer
|
|
1410
|
+
// asking "is this run still making progress" had to reconstruct it from the
|
|
1411
|
+
// history array and the window constant, so every reader could answer
|
|
1412
|
+
// differently. One producer, one definition.
|
|
1413
|
+
state.stall = stallSignal(state.history, STALL_WINDOW).level;
|
|
1414
|
+
|
|
1415
|
+
const action = ladder(state, scan.open, Date.now(), scan.blocked, undefined, unavailable);
|
|
1381
1416
|
|
|
1382
1417
|
if (action !== 'engage') {
|
|
1383
1418
|
// A run that is ALREADY stamped emits nothing further — round 6 finding 6.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Session-scoped shim installer — road-to-skill-ecosystem-runtime-enforcement
|
|
3
|
+
# Phase 1 Step 1.
|
|
4
|
+
#
|
|
5
|
+
# Prepends this directory to PATH **for the current shell session only**.
|
|
6
|
+
#
|
|
7
|
+
# WHY SESSION-ONLY, AND WHY THAT IS THE WHOLE DESIGN. This script never writes
|
|
8
|
+
# to a profile, a login file, or any shell rc. A shim changes what a developer's
|
|
9
|
+
# shell resolves, so an installer that persists it changes their machine until
|
|
10
|
+
# they find the line and remove it. Session scope makes the whole mechanism
|
|
11
|
+
# reversible by closing the terminal, which is the property that let the AI
|
|
12
|
+
# council scope Phase 1 to a shim at all: the reversible option is the one that
|
|
13
|
+
# ships first.
|
|
14
|
+
#
|
|
15
|
+
# USAGE — it must be SOURCED, not executed. A child process cannot alter its
|
|
16
|
+
# parent's PATH, so running it does nothing observable, and saying so is better
|
|
17
|
+
# than appearing to work:
|
|
18
|
+
#
|
|
19
|
+
# . src/scripts/hooks/shims/install.sh # sh / bash / zsh
|
|
20
|
+
#
|
|
21
|
+
# UNINSTALL: close the shell, or `. src/scripts/hooks/shims/install.sh --off`.
|
|
22
|
+
|
|
23
|
+
_shims_self() {
|
|
24
|
+
# BASH_SOURCE under bash, $0 under a POSIX sh that sourced us. Resolved to a
|
|
25
|
+
# physical path so a symlinked checkout does not produce a PATH entry that
|
|
26
|
+
# fails to match on removal.
|
|
27
|
+
if [ -n "${BASH_SOURCE:-}" ]; then
|
|
28
|
+
printf '%s' "${BASH_SOURCE[0]}"
|
|
29
|
+
else
|
|
30
|
+
printf '%s' "$0"
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_shims_dir=$(CDPATH= cd -- "$(dirname -- "$(_shims_self)")" && pwd -P)
|
|
35
|
+
|
|
36
|
+
# Rebuild PATH without this directory. Used by both paths: --off removes it, and
|
|
37
|
+
# the install path uses it so sourcing twice does not stack duplicates.
|
|
38
|
+
_shims_path_without() {
|
|
39
|
+
printf '%s' "${PATH:-}" | tr ':' '\n' | while IFS= read -r _p; do
|
|
40
|
+
[ -n "$_p" ] || continue
|
|
41
|
+
_rp=$(CDPATH= cd -- "$_p" 2>/dev/null && pwd -P) || _rp="$_p"
|
|
42
|
+
[ "$_rp" = "$_shims_dir" ] && continue
|
|
43
|
+
printf '%s:' "$_p"
|
|
44
|
+
done
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if [ "${1:-}" = "--off" ]; then
|
|
48
|
+
_clean=$(_shims_path_without)
|
|
49
|
+
PATH="${_clean%:}"
|
|
50
|
+
export PATH
|
|
51
|
+
printf 'shims: removed %s from PATH for this session\n' "$_shims_dir" >&2
|
|
52
|
+
else
|
|
53
|
+
_clean=$(_shims_path_without)
|
|
54
|
+
PATH="$_shims_dir:${_clean%:}"
|
|
55
|
+
export PATH
|
|
56
|
+
printf 'shims: %s is first on PATH for this session only.\n' "$_shims_dir" >&2
|
|
57
|
+
printf 'shims: nothing was written to a profile. Close the shell, or pass --off, to undo.\n' >&2
|
|
58
|
+
printf 'shims: AGENT_CONFIG_DISABLE_HOOKS=1 bypasses every shim for one command.\n' >&2
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
unset _clean
|