@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,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fail-closed delivery ladder (`road-to-runtime-context-floors` step 2.3).
|
|
3
|
+
*
|
|
4
|
+
* An obligation moved out of the always-loaded prefix onto a runtime carrier is
|
|
5
|
+
* cheaper and can be MISSING. This module is the single encoding of what happens
|
|
6
|
+
* then; the prose lives in `docs/contracts/resident-process-floors.md` § 3 and
|
|
7
|
+
* the wire shape in `src/scripts/schemas/delivery-manifest.schema.json`.
|
|
8
|
+
*
|
|
9
|
+
* Three values, not a boolean, because "may this migrate" and "what if the
|
|
10
|
+
* carrier is down" are different questions and collapsing them loses the middle
|
|
11
|
+
* case that matters:
|
|
12
|
+
*
|
|
13
|
+
* critical-A never migrates; stays in standing context
|
|
14
|
+
* critical-B may migrate; carrier down ⇒ delivered EAGERLY, never dropped
|
|
15
|
+
* standard may migrate; carrier down ⇒ may fail open
|
|
16
|
+
*
|
|
17
|
+
* THE DEFAULT IS `critical-B`. An obligation whose class nobody declared is one
|
|
18
|
+
* nobody classified, and the cheap reading of an unclassified obligation must not
|
|
19
|
+
* be "droppable" — that is the same fail-closed choice
|
|
20
|
+
* `check_prefix_stable_mutation` makes for an undecidable write target.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const DELIVERY_CRITICALITY = ['critical-A', 'critical-B', 'standard'] as const;
|
|
24
|
+
export type DeliveryCriticality = (typeof DELIVERY_CRITICALITY)[number];
|
|
25
|
+
|
|
26
|
+
/** What nobody declared. Deliberately the middle rung, never the cheap one. */
|
|
27
|
+
export const DEFAULT_CRITICALITY: DeliveryCriticality = 'critical-B';
|
|
28
|
+
|
|
29
|
+
export interface DeliveryEntry {
|
|
30
|
+
/** Logical obligation id — the rule, gate or floor being delivered. */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Omitted ⇒ {@link DEFAULT_CRITICALITY}. */
|
|
33
|
+
criticality?: DeliveryCriticality;
|
|
34
|
+
/** The runtime carrier that would deliver it. */
|
|
35
|
+
carrier?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type DeliveryOutcome =
|
|
39
|
+
/** Never left standing context; the carrier is irrelevant to it. */
|
|
40
|
+
| 'standing'
|
|
41
|
+
/** The carrier delivered it. */
|
|
42
|
+
| 'carrier'
|
|
43
|
+
/** The carrier is unavailable and the obligation was delivered the expensive way. */
|
|
44
|
+
| 'eager-fallback'
|
|
45
|
+
/** The carrier is unavailable and the obligation may be omitted. */
|
|
46
|
+
| 'fail-open';
|
|
47
|
+
|
|
48
|
+
export interface DeliveryDecision {
|
|
49
|
+
id: string;
|
|
50
|
+
criticality: DeliveryCriticality;
|
|
51
|
+
/** True when the value was defaulted rather than declared. */
|
|
52
|
+
defaulted: boolean;
|
|
53
|
+
outcome: DeliveryOutcome;
|
|
54
|
+
reason: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isDeliveryCriticality(v: unknown): v is DeliveryCriticality {
|
|
58
|
+
return typeof v === 'string' && (DELIVERY_CRITICALITY as readonly string[]).includes(v);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolve one obligation against carrier availability.
|
|
63
|
+
*
|
|
64
|
+
* An UNRECOGNISED declared value is not honoured and does not throw: it
|
|
65
|
+
* defaults, exactly as an omitted one does. A typo must not be able to buy a
|
|
66
|
+
* weaker rung than the default — which is the direction a throw would also
|
|
67
|
+
* prevent, but a throw would take the whole delivery down with it, and losing
|
|
68
|
+
* every obligation to protect one is the wrong trade.
|
|
69
|
+
*/
|
|
70
|
+
export function resolveDelivery(entry: DeliveryEntry, carrierAvailable: boolean): DeliveryDecision {
|
|
71
|
+
const declared = entry.criticality;
|
|
72
|
+
const known = isDeliveryCriticality(declared);
|
|
73
|
+
const criticality: DeliveryCriticality = known ? declared : DEFAULT_CRITICALITY;
|
|
74
|
+
const defaulted = !known;
|
|
75
|
+
|
|
76
|
+
if (criticality === 'critical-A') {
|
|
77
|
+
return {
|
|
78
|
+
id: entry.id,
|
|
79
|
+
criticality,
|
|
80
|
+
defaulted,
|
|
81
|
+
outcome: 'standing',
|
|
82
|
+
reason: 'critical-A never migrates off standing context, so carrier availability cannot reach it',
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (carrierAvailable) {
|
|
86
|
+
return {
|
|
87
|
+
id: entry.id,
|
|
88
|
+
criticality,
|
|
89
|
+
defaulted,
|
|
90
|
+
outcome: 'carrier',
|
|
91
|
+
reason: `delivered by carrier ${entry.carrier ?? '(unnamed)'}`,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (criticality === 'critical-B') {
|
|
95
|
+
return {
|
|
96
|
+
id: entry.id,
|
|
97
|
+
criticality,
|
|
98
|
+
defaulted,
|
|
99
|
+
outcome: 'eager-fallback',
|
|
100
|
+
reason:
|
|
101
|
+
`carrier ${entry.carrier ?? '(unnamed)'} is unavailable and this obligation is critical-B` +
|
|
102
|
+
(defaulted ? ' by default (its class was not declared)' : '') +
|
|
103
|
+
' — delivered eagerly rather than dropped',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
id: entry.id,
|
|
108
|
+
criticality,
|
|
109
|
+
defaulted,
|
|
110
|
+
outcome: 'fail-open',
|
|
111
|
+
reason: `carrier ${entry.carrier ?? '(unnamed)'} is unavailable and this obligation is standard — may fail open`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Resolve a whole manifest. Order is preserved so a report reads deterministically. */
|
|
116
|
+
export function resolveDeliveryManifest(
|
|
117
|
+
entries: readonly DeliveryEntry[],
|
|
118
|
+
carrierAvailable: boolean,
|
|
119
|
+
): DeliveryDecision[] {
|
|
120
|
+
return entries.map((e) => resolveDelivery(e, carrierAvailable));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The obligations a carrier failure must NOT silently drop. */
|
|
124
|
+
export function droppedObligations(decisions: readonly DeliveryDecision[]): DeliveryDecision[] {
|
|
125
|
+
return decisions.filter((d) => d.outcome === 'fail-open');
|
|
126
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two runtime-presence checks of `agent-config doctor`.
|
|
3
|
+
*
|
|
4
|
+
* PURE MOVE out of `cmd_doctor.ts`, made under the extraction discipline that
|
|
5
|
+
* file's own `_lib` siblings follow: it is ~3,700 lines and
|
|
6
|
+
* `check_source_size_budget` counts every line above 1,500, so a change that
|
|
7
|
+
* adds lines there must pay for them by taking lines away. Wiring the Phase-1
|
|
8
|
+
* install-reach checks in (`road-to-consumer-repo-reality` 1.1) charged five
|
|
9
|
+
* lines; this move returns more than that.
|
|
10
|
+
*
|
|
11
|
+
* Both checks are cohesive with each other and with nothing else in that file:
|
|
12
|
+
* each answers "is a runtime present, and what does the package do when it is
|
|
13
|
+
* not", and neither reads the manifest, the drift sets, or the project root.
|
|
14
|
+
* Their one dependency is a `which` lookup, and it is passed IN rather than
|
|
15
|
+
* imported: `shutilWhich` lives in `cmd_doctor.ts` and importing it back would
|
|
16
|
+
* make the two modules circular. A parameter is cheaper than moving a shared
|
|
17
|
+
* utility that four other call sites already resolve from there.
|
|
18
|
+
*
|
|
19
|
+
* Behaviour is unchanged — same ids, same statuses, same message strings.
|
|
20
|
+
*/
|
|
21
|
+
/** The doctor's structured check row. Mirrors `cmd_doctor`'s internal `Dict`. */
|
|
22
|
+
export interface RuntimeCheck {
|
|
23
|
+
id: string;
|
|
24
|
+
status: 'ok' | 'warn' | 'fail' | 'skipped';
|
|
25
|
+
message: string;
|
|
26
|
+
remedy: string;
|
|
27
|
+
/** Structural compatibility with `cmd_doctor`'s `Dict` row type. */
|
|
28
|
+
[k: string]: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function checkPythonRuntime(): RuntimeCheck {
|
|
32
|
+
// Post-teardown: the package runtime is TypeScript-on-`tsx`. python3 is no
|
|
33
|
+
// longer a runtime dependency, so this check no longer probes for an
|
|
34
|
+
// interpreter (spawning python3 here would be misleading in a python-free
|
|
35
|
+
// package). The check id is retained for the doctor's stable report shape;
|
|
36
|
+
// it always reports `ok`.
|
|
37
|
+
return {
|
|
38
|
+
id: 'python-runtime',
|
|
39
|
+
status: 'ok',
|
|
40
|
+
message: 'python3 is not a runtime dependency (TS runtime via tsx)',
|
|
41
|
+
remedy: '',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function checkHumanizerRuntime(which: (name: string) => string | null): RuntimeCheck {
|
|
46
|
+
// Write-engine step 4b (humanize audit) runs `detect_ai_tells.ts` via a
|
|
47
|
+
// Node/tsx runtime "when available", degrading to a prose-only audit
|
|
48
|
+
// otherwise. This check surfaces which path a consumer install gets so the
|
|
49
|
+
// default-on behavior is not a silent surprise. Either state is healthy —
|
|
50
|
+
// the fallback is graceful by design — so it never fails the run.
|
|
51
|
+
const node = which('node');
|
|
52
|
+
if (node === null) {
|
|
53
|
+
return {
|
|
54
|
+
id: 'humanizer-runtime',
|
|
55
|
+
status: 'ok',
|
|
56
|
+
message:
|
|
57
|
+
'no Node runtime on PATH — write-engine step 4b uses the ' +
|
|
58
|
+
'prose-only humanize audit (graceful fallback)',
|
|
59
|
+
remedy:
|
|
60
|
+
'install Node to enable the mechanical detect_ai_tells.ts pass; ' +
|
|
61
|
+
'the prose audit runs regardless',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
id: 'humanizer-runtime',
|
|
66
|
+
status: 'ok',
|
|
67
|
+
message: `Node runtime present (${node}) — step 4b runs the mechanical detect_ai_tells.ts pass`,
|
|
68
|
+
remedy: '',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A double trigger is one event, not two outcomes.
|
|
3
|
+
*
|
|
4
|
+
* Hosts fire the same slot more than once for a single logical event —
|
|
5
|
+
* `run_continuation_hook.ts` documents the same quirk on `stop` and dedupes it
|
|
6
|
+
* with an ordinal + open-count + short-window key. The consequence here is
|
|
7
|
+
* arithmetic rather than cosmetic: if a duplicate fire writes a second outcome
|
|
8
|
+
* record, every per-asset rate computed over the stream is inflated by exactly
|
|
9
|
+
* the duplication rate, and nothing downstream can separate the two.
|
|
10
|
+
*
|
|
11
|
+
* But a duplicate is not nothing, and discarding it silently is the other
|
|
12
|
+
* failure. The number of times a trigger fired without producing new work is
|
|
13
|
+
* itself a signal — it is how an idle loop looks from the outside. So a
|
|
14
|
+
* duplicate produces NO second outcome and DOES increment an empty-cycle
|
|
15
|
+
* counter, which is reported as its own quantity rather than folded into
|
|
16
|
+
* either the numerator or the denominator of a success rate.
|
|
17
|
+
*
|
|
18
|
+
* Pure and host-free on purpose: this is the seam the hook consumes, so the
|
|
19
|
+
* arithmetic can be tested without constructing a host payload.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** Default coincidence window. Same value the stop-slot dedupe uses. */
|
|
23
|
+
export const DUPLICATE_WINDOW_MS = 60 * 1000;
|
|
24
|
+
|
|
25
|
+
export interface TriggerFire {
|
|
26
|
+
/**
|
|
27
|
+
* Identity of the logical event. Two fires sharing a key inside the window
|
|
28
|
+
* are the same event seen twice. Id-shaped — never free-form text.
|
|
29
|
+
*/
|
|
30
|
+
key: string;
|
|
31
|
+
/** Epoch milliseconds. */
|
|
32
|
+
at: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CycleState {
|
|
36
|
+
/** The most recent fire that produced an outcome, or `null` before any. */
|
|
37
|
+
last: TriggerFire | null;
|
|
38
|
+
/** Fires suppressed as duplicates so far. */
|
|
39
|
+
empty_cycles: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function initialCycleState(): CycleState {
|
|
43
|
+
return { last: null, empty_cycles: 0 };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface CycleDecision {
|
|
47
|
+
/** Whether this fire should produce an outcome record. */
|
|
48
|
+
emit_outcome: boolean;
|
|
49
|
+
/** The state to carry forward. */
|
|
50
|
+
state: CycleState;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Decide what one fire means.
|
|
55
|
+
*
|
|
56
|
+
* A fire is a duplicate when it carries the SAME key as the last
|
|
57
|
+
* outcome-producing fire AND lands inside the window. Both conjuncts are
|
|
58
|
+
* required and neither is sufficient:
|
|
59
|
+
*
|
|
60
|
+
* - Key alone would collapse a genuine repeat of the same work an hour later
|
|
61
|
+
* into an empty cycle, erasing a real outcome.
|
|
62
|
+
* - Window alone would collapse two DIFFERENT events that happen to be close
|
|
63
|
+
* together, which is the common case under any kind of fan-out.
|
|
64
|
+
*
|
|
65
|
+
* A duplicate does not advance `last`. That is deliberate: three fires inside
|
|
66
|
+
* one window are one outcome and two empty cycles, not one outcome, one empty
|
|
67
|
+
* cycle, and a third fire that has drifted out of the window and looks new.
|
|
68
|
+
*/
|
|
69
|
+
export function observeFire(
|
|
70
|
+
state: CycleState,
|
|
71
|
+
fire: TriggerFire,
|
|
72
|
+
windowMs: number = DUPLICATE_WINDOW_MS,
|
|
73
|
+
): CycleDecision {
|
|
74
|
+
const prev = state.last;
|
|
75
|
+
const isDuplicate =
|
|
76
|
+
prev !== null && prev.key === fire.key && fire.at - prev.at < windowMs;
|
|
77
|
+
|
|
78
|
+
if (isDuplicate) {
|
|
79
|
+
return {
|
|
80
|
+
emit_outcome: false,
|
|
81
|
+
state: { last: prev, empty_cycles: state.empty_cycles + 1 },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
emit_outcome: true,
|
|
86
|
+
state: { last: fire, empty_cycles: state.empty_cycles },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comparison arms that can discriminate, and results honest enough to publish.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-skill-ecosystem-eval-integrity` Phases 4 and 5. Every function here
|
|
5
|
+
* exists because a benchmark can be run correctly and still produce a number
|
|
6
|
+
* nobody should act on — and each of those routes is a separate mechanism, not
|
|
7
|
+
* a matter of care.
|
|
8
|
+
*/
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
|
|
11
|
+
// ── Phase 4.2 — a fixture the control arm cannot also satisfy ───────────────
|
|
12
|
+
|
|
13
|
+
export interface PlantedItem {
|
|
14
|
+
id: string;
|
|
15
|
+
/**
|
|
16
|
+
* True when this item is recoverable ONLY via the behaviour the artifact
|
|
17
|
+
* under test prescribes. At least one such item must exist, or the control
|
|
18
|
+
* arm scores the same and the eval adjudicates nothing.
|
|
19
|
+
*/
|
|
20
|
+
requires_artifact_behaviour: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Can this fixture set discriminate at all?
|
|
25
|
+
*
|
|
26
|
+
* The check runs BEFORE a run rather than after, because the answer does not
|
|
27
|
+
* depend on the outcome: a fixture set where every item is recoverable by
|
|
28
|
+
* general competence measures general competence, whatever the arms score. A
|
|
29
|
+
* run over such a set is not a weak result — it is not a result.
|
|
30
|
+
*/
|
|
31
|
+
export function discriminationDeficit(items: readonly PlantedItem[]): string | null {
|
|
32
|
+
if (items.length === 0) return 'no fixture items — nothing to recover';
|
|
33
|
+
if (!items.some((i) => i.requires_artifact_behaviour)) {
|
|
34
|
+
return (
|
|
35
|
+
`none of ${String(items.length)} fixture item(s) is recoverable only via the behaviour ` +
|
|
36
|
+
'under test, so the control arm can score identically and the eval cannot adjudicate'
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ── Phase 4.3 — a missed plant is a zero, never an absence ──────────────────
|
|
43
|
+
|
|
44
|
+
export interface RubricScoreInput {
|
|
45
|
+
/** Items the run actually reported on. */
|
|
46
|
+
reported: readonly { id: string; score: number }[];
|
|
47
|
+
/** Every item that was planted, whether reported or not. */
|
|
48
|
+
planted: readonly string[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface RubricScore {
|
|
52
|
+
/** Sum over PLANTED items, missing ones counted as zero. */
|
|
53
|
+
total: number;
|
|
54
|
+
/** Denominator is the planted count, never the reported count. */
|
|
55
|
+
denominator: number;
|
|
56
|
+
ratio: number;
|
|
57
|
+
missed: readonly string[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Score a rubric with missed plants counted as implicit zeros.
|
|
62
|
+
*
|
|
63
|
+
* Dividing by what was REPORTED is the defect: a run that finds one item and
|
|
64
|
+
* says nothing about the other nine scores 100 %, so under-reporting buys a
|
|
65
|
+
* higher ratio. The denominator has to be the plant.
|
|
66
|
+
*/
|
|
67
|
+
export function scoreWithImplicitZeros(input: RubricScoreInput): RubricScore {
|
|
68
|
+
const byId = new Map(input.reported.map((r) => [r.id, r.score]));
|
|
69
|
+
const missed = input.planted.filter((p) => !byId.has(p));
|
|
70
|
+
const total = input.planted.reduce((a, id) => a + (byId.get(id) ?? 0), 0);
|
|
71
|
+
const denominator = input.planted.length;
|
|
72
|
+
return {
|
|
73
|
+
total,
|
|
74
|
+
denominator,
|
|
75
|
+
ratio: denominator === 0 ? 0 : total / denominator,
|
|
76
|
+
missed,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ── Phase 4.4 — did the run read what it was denied? ────────────────────────
|
|
81
|
+
|
|
82
|
+
export interface LeakScanInput {
|
|
83
|
+
/** Paths the run must not have read: ground truth, generator, scorers, prior trials. */
|
|
84
|
+
denied: readonly string[];
|
|
85
|
+
/** Every tool input the run recorded, in order. */
|
|
86
|
+
toolInputs: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface LeakFinding {
|
|
90
|
+
denied: string;
|
|
91
|
+
/** The tool input that matched. */
|
|
92
|
+
evidence: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Walk a run transcript for reads of denied paths.
|
|
97
|
+
*
|
|
98
|
+
* Runs AFTER the trial, on the recorded transcript, because a denial that is
|
|
99
|
+
* only configured is a denial nobody verified. Matching is substring on a
|
|
100
|
+
* path with separators normalised — a leak arriving through a symlink or a
|
|
101
|
+
* parent-directory hop is not something this catches, and saying so is cheaper
|
|
102
|
+
* than implying it does.
|
|
103
|
+
*/
|
|
104
|
+
export function scanLeaks(input: LeakScanInput): LeakFinding[] {
|
|
105
|
+
const out: LeakFinding[] = [];
|
|
106
|
+
const norm = (s: string): string => s.split('\\').join('/');
|
|
107
|
+
for (const d of input.denied) {
|
|
108
|
+
const needle = norm(d);
|
|
109
|
+
if (needle === '') continue;
|
|
110
|
+
for (const t of input.toolInputs) {
|
|
111
|
+
if (norm(t).includes(needle)) {
|
|
112
|
+
out.push({ denied: d, evidence: t.slice(0, 200) });
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ── Phase 4.5 — a cache key that includes the CRITERIA ──────────────────────
|
|
121
|
+
|
|
122
|
+
/** Field delimiter for the identity hash. An escape, never a raw byte. */
|
|
123
|
+
const FIELD_SEP = '\u001e';
|
|
124
|
+
/** Element delimiter inside one array field. Different from FIELD_SEP on purpose. */
|
|
125
|
+
const ELEMENT_SEP = '\u001f';
|
|
126
|
+
|
|
127
|
+
export interface BaselineIdentity {
|
|
128
|
+
prompt: string;
|
|
129
|
+
fixtures: readonly string[];
|
|
130
|
+
/** The half most likely to be omitted, which is why it is required here. */
|
|
131
|
+
rubric: readonly string[];
|
|
132
|
+
assertions: readonly string[];
|
|
133
|
+
toolExpectations: readonly string[];
|
|
134
|
+
turnLimit: number;
|
|
135
|
+
tokenLimit: number;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Composite identity hash for a cached baseline.
|
|
140
|
+
*
|
|
141
|
+
* Keying on prompt and fixtures alone is the common shape and the wrong one: an
|
|
142
|
+
* edited rubric changes what a pass MEANS while the key stays identical, so the
|
|
143
|
+
* cache serves a baseline scored under criteria that no longer exist. The
|
|
144
|
+
* criteria half is required by the type rather than optional, because an
|
|
145
|
+
* optional field that is easy to omit is a field that gets omitted.
|
|
146
|
+
*/
|
|
147
|
+
export function baselineIdentity(id: BaselineIdentity): string {
|
|
148
|
+
const h = createHash('sha256');
|
|
149
|
+
const feed = (label: string, v: string | readonly string[] | number): void => {
|
|
150
|
+
// The separators are ESCAPES, never raw control bytes: a raw U+1F in a
|
|
151
|
+
// text source makes grep, file(1) and git treat the file as binary and
|
|
152
|
+
// skip it silently, which `lint_hidden_unicode` refuses. A field
|
|
153
|
+
// delimiter and an element delimiter that differ are what keep two
|
|
154
|
+
// fields concatenating to the same text from producing one hash.
|
|
155
|
+
h.update(FIELD_SEP + label + FIELD_SEP);
|
|
156
|
+
h.update(Array.isArray(v) ? [...v].join(ELEMENT_SEP) : String(v));
|
|
157
|
+
};
|
|
158
|
+
feed('prompt', id.prompt);
|
|
159
|
+
feed('fixtures', id.fixtures);
|
|
160
|
+
feed('rubric', id.rubric);
|
|
161
|
+
feed('assertions', id.assertions);
|
|
162
|
+
feed('tools', id.toolExpectations);
|
|
163
|
+
feed('turns', id.turnLimit);
|
|
164
|
+
feed('tokens', id.tokenLimit);
|
|
165
|
+
return h.digest('hex');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ── Phase 5.1 / 5.2 — first attempts, and the completeness precondition ─────
|
|
169
|
+
|
|
170
|
+
export interface Receipt {
|
|
171
|
+
caseId: string;
|
|
172
|
+
configuration: string;
|
|
173
|
+
/** 1 for the first attempt. A later correction carries 2, 3, … */
|
|
174
|
+
attempt: number;
|
|
175
|
+
outcome: 'pass' | 'fail' | 'aborted';
|
|
176
|
+
/** Required when `outcome` is `aborted`, and must be an allow-listed reason. */
|
|
177
|
+
failureReason?: string | undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Reasons an aborted run may record. A closed set on purpose.
|
|
182
|
+
*
|
|
183
|
+
* The alternative to an allow-list is free text, and free text lets an abort be
|
|
184
|
+
* recorded as anything — including something that reads like a result. A run
|
|
185
|
+
* that stopped is a truthful receipt with its gates marked not-run, never a
|
|
186
|
+
* dropped run and never a fabricated artifact.
|
|
187
|
+
*/
|
|
188
|
+
export const ABORT_REASONS = [
|
|
189
|
+
'quota-exhausted',
|
|
190
|
+
'credential-missing',
|
|
191
|
+
'dependency-unavailable',
|
|
192
|
+
'timeout',
|
|
193
|
+
'harness-error',
|
|
194
|
+
'operator-cancelled',
|
|
195
|
+
] as const;
|
|
196
|
+
export type AbortReason = (typeof ABORT_REASONS)[number];
|
|
197
|
+
|
|
198
|
+
/** Attempt-one-only accounting: a later correction is diagnosis, never a result. */
|
|
199
|
+
export function firstAttempts(receipts: readonly Receipt[]): Receipt[] {
|
|
200
|
+
const best = new Map<string, Receipt>();
|
|
201
|
+
for (const r of receipts) {
|
|
202
|
+
// The separator is load-bearing, not cosmetic: without one, a
|
|
203
|
+
// configuration "ab" with case "c" collides with "a" and "bc", which
|
|
204
|
+
// silently drops a receipt — and the completeness precondition below
|
|
205
|
+
// would then report a missing first attempt for a case that has one.
|
|
206
|
+
const key = r.configuration + FIELD_SEP + r.caseId;
|
|
207
|
+
const seen = best.get(key);
|
|
208
|
+
if (seen === undefined || r.attempt < seen.attempt) best.set(key, r);
|
|
209
|
+
}
|
|
210
|
+
return [...best.values()];
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface CompletenessVerdict {
|
|
214
|
+
publishable: boolean;
|
|
215
|
+
/** Every reason it is not, so one fix does not reveal the next one a day later. */
|
|
216
|
+
reasons: string[];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* May this result be published?
|
|
221
|
+
*
|
|
222
|
+
* The precondition is exact and deliberately unforgiving: every configuration
|
|
223
|
+
* has exactly ONE first-attempt receipt for every case. A missing receipt is the
|
|
224
|
+
* shape that produces a published number over a silently smaller denominator,
|
|
225
|
+
* and a duplicate first attempt means two runs disagree about which one counted.
|
|
226
|
+
*/
|
|
227
|
+
export function completenessVerdict(
|
|
228
|
+
receipts: readonly Receipt[],
|
|
229
|
+
configurations: readonly string[],
|
|
230
|
+
cases: readonly string[],
|
|
231
|
+
): CompletenessVerdict {
|
|
232
|
+
const reasons: string[] = [];
|
|
233
|
+
const firsts = receipts.filter((r) => r.attempt === 1);
|
|
234
|
+
for (const cfg of configurations) {
|
|
235
|
+
for (const c of cases) {
|
|
236
|
+
const n = firsts.filter((r) => r.configuration === cfg && r.caseId === c).length;
|
|
237
|
+
if (n === 0) reasons.push(`${cfg} / ${c}: no first-attempt receipt`);
|
|
238
|
+
else if (n > 1) reasons.push(`${cfg} / ${c}: ${String(n)} first-attempt receipts`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
for (const r of receipts) {
|
|
242
|
+
if (r.outcome !== 'aborted') continue;
|
|
243
|
+
const reason = r.failureReason;
|
|
244
|
+
if (reason === undefined || !(ABORT_REASONS as readonly string[]).includes(reason)) {
|
|
245
|
+
reasons.push(
|
|
246
|
+
`${r.configuration} / ${r.caseId}: aborted with ` +
|
|
247
|
+
`${reason === undefined ? 'no reason' : `an unlisted reason "${reason}"`} — ` +
|
|
248
|
+
`allowed: ${ABORT_REASONS.join(', ')}`,
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { publishable: reasons.length === 0, reasons };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ── Phase 5.7 — a denominator that excludes what cannot self-activate ───────
|
|
256
|
+
|
|
257
|
+
export interface CoverageInput {
|
|
258
|
+
/** Every artifact in the population. */
|
|
259
|
+
artifacts: readonly { id: string; can_self_activate: boolean; covered: boolean }[];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface CoverageReport {
|
|
263
|
+
/** Coverage over artifacts that CAN self-activate. */
|
|
264
|
+
rate: number | null;
|
|
265
|
+
denominator: number;
|
|
266
|
+
/** Reported separately, never folded into the rate. */
|
|
267
|
+
dependency_level: readonly string[];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Coverage, with non-self-activating artifacts excluded from the denominator.
|
|
272
|
+
*
|
|
273
|
+
* An arm that loads only an artifact which cannot activate itself runs
|
|
274
|
+
* treatment-equals-control by construction, so its score is judge noise. Folding
|
|
275
|
+
* such artifacts into a coverage rate publishes that noise as coverage. They are
|
|
276
|
+
* still reported — as dependency-level coverage, which is a real and different
|
|
277
|
+
* claim.
|
|
278
|
+
*/
|
|
279
|
+
export function coverageExcludingNonActivating(input: CoverageInput): CoverageReport {
|
|
280
|
+
const activating = input.artifacts.filter((a) => a.can_self_activate);
|
|
281
|
+
const dependency = input.artifacts.filter((a) => !a.can_self_activate).map((a) => a.id);
|
|
282
|
+
return {
|
|
283
|
+
rate:
|
|
284
|
+
activating.length === 0
|
|
285
|
+
? null
|
|
286
|
+
: activating.filter((a) => a.covered).length / activating.length,
|
|
287
|
+
denominator: activating.length,
|
|
288
|
+
dependency_level: dependency,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// ── Phase 5.8 — the indeterminate branch, declared before the run ───────────
|
|
293
|
+
|
|
294
|
+
export interface ThresholdDeclaration {
|
|
295
|
+
metric: string;
|
|
296
|
+
/** At or above this, the pre-registered claim is supported. */
|
|
297
|
+
pass: number;
|
|
298
|
+
/** At or below this, it is refuted. */
|
|
299
|
+
refute: number;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export type ThresholdOutcome = 'supported' | 'refuted' | 'indeterminate';
|
|
303
|
+
|
|
304
|
+
export interface ThresholdVerdict {
|
|
305
|
+
outcome: ThresholdOutcome;
|
|
306
|
+
/** What a null here does and does not license, stated at declaration time. */
|
|
307
|
+
interpretation_limit: string;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Evaluate a measurement against a pre-registered threshold with a DECLARED
|
|
312
|
+
* indeterminate band.
|
|
313
|
+
*
|
|
314
|
+
* A single cut point forces every measurement into support or refutation, so a
|
|
315
|
+
* value that lands between them is read as whichever the reader hoped for. This
|
|
316
|
+
* package's own honest-null history is the argument: naming the indeterminate
|
|
317
|
+
* outcome BEFORE the run is what makes a null reportable rather than
|
|
318
|
+
* embarrassing.
|
|
319
|
+
*
|
|
320
|
+
* Throws when the band is inverted, because a declaration that cannot produce an
|
|
321
|
+
* indeterminate outcome is the single cut point wearing two numbers.
|
|
322
|
+
*/
|
|
323
|
+
export function evaluateThreshold(d: ThresholdDeclaration, measured: number): ThresholdVerdict {
|
|
324
|
+
if (d.refute >= d.pass) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`threshold declaration for "${d.metric}" has refute (${String(d.refute)}) >= pass ` +
|
|
327
|
+
`(${String(d.pass)}) — that leaves no indeterminate band, which is a single cut ` +
|
|
328
|
+
'point with two numbers written on it',
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
if (measured >= d.pass) {
|
|
332
|
+
return {
|
|
333
|
+
outcome: 'supported',
|
|
334
|
+
interpretation_limit:
|
|
335
|
+
'supports the pre-registered claim at the declared bar; it does not license a claim ' +
|
|
336
|
+
'about any metric that was not measured',
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
if (measured <= d.refute) {
|
|
340
|
+
return {
|
|
341
|
+
outcome: 'refuted',
|
|
342
|
+
interpretation_limit:
|
|
343
|
+
'refutes the pre-registered claim at the declared bar; it does not establish that ' +
|
|
344
|
+
'the opposite claim holds',
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
outcome: 'indeterminate',
|
|
349
|
+
interpretation_limit:
|
|
350
|
+
`landed between the declared bars (${String(d.refute)} .. ${String(d.pass)}): the run ` +
|
|
351
|
+
'neither supports nor refutes. A null here licenses NO directional reading — it says ' +
|
|
352
|
+
'the instrument could not separate the arms at this sample size.',
|
|
353
|
+
};
|
|
354
|
+
}
|