@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,593 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Eval-specification lint — a gate on this package's own measurement inputs.
|
|
4
|
+
*
|
|
5
|
+
* `road-to-skill-ecosystem-eval-integrity` Phase 1. Every gate in this tree
|
|
6
|
+
* checks a shipped artifact; nothing checked the SPECIFICATIONS that decide
|
|
7
|
+
* whether a change helped. A malformed eval does not fail loudly — it measures
|
|
8
|
+
* less while reporting the same coverage, which is the worst available failure
|
|
9
|
+
* mode for a measurement.
|
|
10
|
+
*
|
|
11
|
+
* ── The four defect classes, and why each is invisible without a gate ───────
|
|
12
|
+
*
|
|
13
|
+
* `duplicate-key` — `JSON.parse` keeps the LAST value for a repeated key, so
|
|
14
|
+
* one case silently becomes a byte-identical clone of another and the intended
|
|
15
|
+
* fixture is never loaded. The file parses; the schema passes; the suite
|
|
16
|
+
* reports the same number of cases.
|
|
17
|
+
*
|
|
18
|
+
* `untracked-fixture` — a referenced fixture that is not in the git INDEX
|
|
19
|
+
* exists on the author's machine and nowhere else. Resolved from `git ls-files`
|
|
20
|
+
* deliberately: the plausible alternative, asking `git ls-tree HEAD`, counts a
|
|
21
|
+
* file staged for removal back as tracked and produces a false negative for
|
|
22
|
+
* exactly this bug class.
|
|
23
|
+
*
|
|
24
|
+
* `arithmetic-disagreement` — a fixture states the same number twice, once as
|
|
25
|
+
* the declared expectation and once inside the derivation, and the two
|
|
26
|
+
* disagree. A judge then prefers the declared value and scores a correct
|
|
27
|
+
* response as a loss. Both numbers are already in the file; they were simply
|
|
28
|
+
* never compared. Detail and the rounding rule: `_lib/arith_claims.ts`.
|
|
29
|
+
*
|
|
30
|
+
* `incomplete-grader` — an assertion whose configuration is absent parses
|
|
31
|
+
* cleanly and enforces NOTHING. `tool-choice` is the shape in this tree: its
|
|
32
|
+
* schema requires only `kind`, so `{"kind": "tool-choice"}` is valid and
|
|
33
|
+
* checks no tool at all. A scenario carrying it looks graded and is not.
|
|
34
|
+
*
|
|
35
|
+
* `declared-count-mismatch` — a description that says "3 positives" beside a
|
|
36
|
+
* query list that holds four. The prose is what a reader trusts when deciding
|
|
37
|
+
* whether a corpus is balanced, and nothing recomputes it.
|
|
38
|
+
*
|
|
39
|
+
* ── What this gate does NOT do ──────────────────────────────────────────────
|
|
40
|
+
* It never judges whether a fixture is GOOD. Every check above fires only on a
|
|
41
|
+
* malformed input and can be satisfied by well-written prose of any quality —
|
|
42
|
+
* that boundary is deliberate, because a gate that grades authorship produces
|
|
43
|
+
* findings nobody can act on and gets suppressed.
|
|
44
|
+
*
|
|
45
|
+
* ── Corpus, measured before promotion ───────────────────────────────────────
|
|
46
|
+
* Phase 1 Step 7 requires landing advisory, classifying every hit on the real
|
|
47
|
+
* corpus, and promoting only then. Measured 2026-08-26 over 170 specification
|
|
48
|
+
* files: **zero hits in every class.** That is an honest null and it is the
|
|
49
|
+
* reason this ships as an error gate on day one rather than advisory — there is
|
|
50
|
+
* no inherited debt to classify, so an advisory period would measure nothing
|
|
51
|
+
* and delay the protection. Discrimination is proven by `--self-test` instead,
|
|
52
|
+
* which is what a preventive gate over a clean corpus has to rest on.
|
|
53
|
+
*
|
|
54
|
+
* Exit codes: 0 ok · 1 finding(s) · 2 usage / unreadable corpus.
|
|
55
|
+
*/
|
|
56
|
+
import { execFileSync } from 'node:child_process';
|
|
57
|
+
import * as fs from 'node:fs';
|
|
58
|
+
import * as path from 'node:path';
|
|
59
|
+
import process from 'node:process';
|
|
60
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
61
|
+
|
|
62
|
+
import { findArithDisagreements, chainSupportsExpected } from './_lib/arith_claims.js';
|
|
63
|
+
import { GateLedger } from './_lib/gate_ledger.js';
|
|
64
|
+
import { runGateCli, runSelfTest } from './_lib/gate_self_test.js';
|
|
65
|
+
import { findDuplicateKeys } from './_lib/json_duplicate_keys.js';
|
|
66
|
+
import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
|
|
67
|
+
|
|
68
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
69
|
+
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
70
|
+
|
|
71
|
+
/** Where specification files live. Every root is a directory of `evals/`. */
|
|
72
|
+
export const SPEC_GLOB_ROOTS = ['src/skills', 'src/domains', 'src/agent-src/commands/evals'] as const;
|
|
73
|
+
|
|
74
|
+
/** Finding kinds, closed so the report and the tests cannot drift apart. */
|
|
75
|
+
export type FindingKind =
|
|
76
|
+
| 'duplicate-key'
|
|
77
|
+
| 'untracked-fixture'
|
|
78
|
+
| 'arithmetic-disagreement'
|
|
79
|
+
| 'incomplete-grader'
|
|
80
|
+
| 'declared-count-mismatch';
|
|
81
|
+
|
|
82
|
+
export interface Finding {
|
|
83
|
+
kind: FindingKind;
|
|
84
|
+
/** Repo-relative path of the specification. */
|
|
85
|
+
file: string;
|
|
86
|
+
/** 1-based line where the defect is, when the check knows one. */
|
|
87
|
+
line?: number | undefined;
|
|
88
|
+
message: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Every specification file under the declared roots. */
|
|
92
|
+
export function listSpecs(root: string): string[] {
|
|
93
|
+
const out: string[] = [];
|
|
94
|
+
const walk = (dir: string, depth: number): void => {
|
|
95
|
+
let entries: fs.Dirent[];
|
|
96
|
+
try {
|
|
97
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
98
|
+
} catch {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (const e of entries) {
|
|
102
|
+
const p = path.join(dir, e.name);
|
|
103
|
+
if (e.isDirectory()) {
|
|
104
|
+
if (e.name === 'node_modules' || e.name.startsWith('.')) continue;
|
|
105
|
+
if (depth > 6) continue;
|
|
106
|
+
walk(p, depth + 1);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (!e.name.endsWith('.json')) continue;
|
|
110
|
+
const rel = path.relative(root, p).split(path.sep).join('/');
|
|
111
|
+
// `evals/` is the marker, so a schema or a config next door is not
|
|
112
|
+
// mistaken for a specification. The commands root IS an evals dir.
|
|
113
|
+
if (rel.includes('/evals/') || rel.startsWith('src/agent-src/commands/evals/')) {
|
|
114
|
+
out.push(rel);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
for (const r of SPEC_GLOB_ROOTS) walk(path.join(root, r), 0);
|
|
119
|
+
return out.sort();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Paths tracked in the git INDEX, as a set.
|
|
124
|
+
*
|
|
125
|
+
* `git ls-files` and not `git ls-tree HEAD`: the index is what a commit will
|
|
126
|
+
* contain, and a file staged for removal is gone from the index while still
|
|
127
|
+
* present in the tree. Asking the tree would report it tracked and let exactly
|
|
128
|
+
* this bug class through.
|
|
129
|
+
*
|
|
130
|
+
* Returns `null` when git is unavailable — the caller then SKIPS the check
|
|
131
|
+
* with a ledger reason rather than reporting every fixture untracked, because a
|
|
132
|
+
* checker that cannot look must not manufacture findings.
|
|
133
|
+
*/
|
|
134
|
+
export function trackedPaths(root: string): Set<string> | null {
|
|
135
|
+
try {
|
|
136
|
+
const out = execFileSync('git', ['-C', root, 'ls-files', '-z'], {
|
|
137
|
+
encoding: 'utf-8',
|
|
138
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
139
|
+
});
|
|
140
|
+
return new Set(out.split('\0').filter((s) => s !== ''));
|
|
141
|
+
} catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** 1-based line of the first occurrence of `needle`, or undefined. */
|
|
147
|
+
function lineOf(source: string, needle: string): number | undefined {
|
|
148
|
+
const idx = source.indexOf(needle);
|
|
149
|
+
if (idx < 0) return undefined;
|
|
150
|
+
return source.slice(0, idx).split('\n').length;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const POSITIVE_COUNT = /(\d+)\s+positives?\b/i;
|
|
154
|
+
const NEGATIVE_COUNT = /(\d+)\s+(?:near-miss(?:es)?|negatives?)\b/i;
|
|
155
|
+
|
|
156
|
+
/** Check one specification. `tracked` of `null` skips the fixture check. */
|
|
157
|
+
export function checkSpec(
|
|
158
|
+
rel: string,
|
|
159
|
+
source: string,
|
|
160
|
+
tracked: Set<string> | null,
|
|
161
|
+
): Finding[] {
|
|
162
|
+
const findings: Finding[] = [];
|
|
163
|
+
|
|
164
|
+
for (const d of findDuplicateKeys(source)) {
|
|
165
|
+
findings.push({
|
|
166
|
+
kind: 'duplicate-key',
|
|
167
|
+
file: rel,
|
|
168
|
+
line: d.laterLine,
|
|
169
|
+
message:
|
|
170
|
+
`duplicate key "${d.key}" in ${d.container === '' ? 'the document root' : d.container} — ` +
|
|
171
|
+
`first at line ${String(d.firstLine)}, again at line ${String(d.laterLine)}. ` +
|
|
172
|
+
'JSON.parse keeps the LAST value, so the earlier entry is silently discarded.',
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let doc: unknown;
|
|
177
|
+
try {
|
|
178
|
+
doc = JSON.parse(source);
|
|
179
|
+
} catch {
|
|
180
|
+
// Unparseable JSON is the schema validator's finding, not this gate's.
|
|
181
|
+
return findings;
|
|
182
|
+
}
|
|
183
|
+
if (typeof doc !== 'object' || doc === null) return findings;
|
|
184
|
+
const d = doc as Record<string, unknown>;
|
|
185
|
+
|
|
186
|
+
// ── fixture tracking + grader completeness, over behavioural scenarios ──
|
|
187
|
+
const scenarios = Array.isArray(d['scenarios']) ? (d['scenarios'] as Record<string, unknown>[]) : [];
|
|
188
|
+
for (const sc of scenarios) {
|
|
189
|
+
const id = typeof sc['id'] === 'string' ? sc['id'] : '(unnamed)';
|
|
190
|
+
const assertions = Array.isArray(sc['assertions'])
|
|
191
|
+
? (sc['assertions'] as Record<string, unknown>[])
|
|
192
|
+
: [];
|
|
193
|
+
for (const a of assertions) {
|
|
194
|
+
if (a['kind'] === 'tool-choice') {
|
|
195
|
+
const must = Array.isArray(a['must_use']) ? a['must_use'] : [];
|
|
196
|
+
const mustNot = Array.isArray(a['must_not_use']) ? a['must_not_use'] : [];
|
|
197
|
+
if (must.length === 0 && mustNot.length === 0) {
|
|
198
|
+
findings.push({
|
|
199
|
+
kind: 'incomplete-grader',
|
|
200
|
+
file: rel,
|
|
201
|
+
line: lineOf(source, `"${id}"`),
|
|
202
|
+
message:
|
|
203
|
+
`scenario "${id}" carries a tool-choice assertion with neither must_use nor ` +
|
|
204
|
+
'must_not_use. It parses, it is schema-valid, and it checks no tool at all — ' +
|
|
205
|
+
'the scenario looks graded and is not.',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (a['kind'] === 'event-choice') {
|
|
210
|
+
const emit = Array.isArray(a['must_emit']) ? a['must_emit'] : [];
|
|
211
|
+
const notEmit = Array.isArray(a['must_not_emit']) ? a['must_not_emit'] : [];
|
|
212
|
+
if (emit.length === 0 && notEmit.length === 0) {
|
|
213
|
+
findings.push({
|
|
214
|
+
kind: 'incomplete-grader',
|
|
215
|
+
file: rel,
|
|
216
|
+
line: lineOf(source, `"${id}"`),
|
|
217
|
+
message:
|
|
218
|
+
`scenario "${id}" carries an event-choice assertion with neither must_emit ` +
|
|
219
|
+
'nor must_not_emit. The schema forbids it by construction, so reaching this ' +
|
|
220
|
+
'means the file was written against an older schema or validation was skipped.',
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (a['kind'] === 'file_exists' && tracked !== null) {
|
|
225
|
+
const p = typeof a['path'] === 'string' ? a['path'] : '';
|
|
226
|
+
// Only repo-rooted paths are checkable; a run-relative artifact
|
|
227
|
+
// is produced BY the run and cannot be in the index.
|
|
228
|
+
if (/^(?:tests|src|internal|docs|agents)\//.test(p) && !tracked.has(p)) {
|
|
229
|
+
findings.push({
|
|
230
|
+
kind: 'untracked-fixture',
|
|
231
|
+
file: rel,
|
|
232
|
+
line: lineOf(source, p),
|
|
233
|
+
message:
|
|
234
|
+
`scenario "${id}" references "${p}", which is not in the git index. ` +
|
|
235
|
+
'It exists on the author machine and nowhere else.',
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ── arithmetic claims, over domain-truth cases ─────────────────────────
|
|
243
|
+
const cases = Array.isArray(d['cases']) ? (d['cases'] as Record<string, unknown>[]) : [];
|
|
244
|
+
for (const c of cases) {
|
|
245
|
+
const id = typeof c['id'] === 'string' ? c['id'] : '(unnamed)';
|
|
246
|
+
const check = typeof c['check'] === 'object' && c['check'] !== null
|
|
247
|
+
? (c['check'] as Record<string, unknown>)
|
|
248
|
+
: null;
|
|
249
|
+
if (check === null) continue;
|
|
250
|
+
const rationale = typeof check['rationale'] === 'string' ? check['rationale'] : '';
|
|
251
|
+
if (rationale === '') continue;
|
|
252
|
+
for (const dis of findArithDisagreements(rationale)) {
|
|
253
|
+
findings.push({
|
|
254
|
+
kind: 'arithmetic-disagreement',
|
|
255
|
+
file: rel,
|
|
256
|
+
line: lineOf(source, rationale.slice(0, 40)),
|
|
257
|
+
message:
|
|
258
|
+
`case "${id}" derivation disagrees with itself: "${dis.leftSegment}" is ` +
|
|
259
|
+
`${String(dis.left)} but "${dis.rightSegment}" reads ${String(dis.right)} ` +
|
|
260
|
+
`(tolerance ${String(dis.tolerance)}).`,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
const expected = check['expected'];
|
|
264
|
+
if (typeof expected === 'number') {
|
|
265
|
+
const tol = typeof check['tolerance'] === 'number' ? check['tolerance'] : 0;
|
|
266
|
+
const supported = chainSupportsExpected(rationale, expected, tol);
|
|
267
|
+
if (supported === false) {
|
|
268
|
+
findings.push({
|
|
269
|
+
kind: 'arithmetic-disagreement',
|
|
270
|
+
file: rel,
|
|
271
|
+
line: lineOf(source, rationale.slice(0, 40)),
|
|
272
|
+
message:
|
|
273
|
+
`case "${id}" declares expected ${String(expected)} but no step of its own ` +
|
|
274
|
+
'derivation reaches that number. A judge prefers the declared value, so a ' +
|
|
275
|
+
'correct response scores as a loss.',
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ── declared corpus counts, over trigger specifications ────────────────
|
|
282
|
+
const queries = Array.isArray(d['queries']) ? (d['queries'] as Record<string, unknown>[]) : [];
|
|
283
|
+
const desc = typeof d['description'] === 'string' ? d['description'] : '';
|
|
284
|
+
if (queries.length > 0 && desc !== '') {
|
|
285
|
+
const pos = queries.filter((q) => q['trigger'] === true).length;
|
|
286
|
+
// Two vocabularies, and which one applies is read off the FILE.
|
|
287
|
+
//
|
|
288
|
+
// This gate was written when "near-miss" and "negative" were synonyms,
|
|
289
|
+
// so it compared a declared near-miss count against every non-triggering
|
|
290
|
+
// query. `lint_skill_trigger_corpus` has since introduced a three-class
|
|
291
|
+
// vocabulary — `exemplar | near-miss | counterexample` — in which a
|
|
292
|
+
// near-miss is a STRICT SUBSET of the negatives, the rest being
|
|
293
|
+
// counterexamples. Against a classed file the old comparison demands a
|
|
294
|
+
// description that contradicts the file's own classes.
|
|
295
|
+
//
|
|
296
|
+
// So a file that declares classes is counted by its declared near-miss
|
|
297
|
+
// class, and a file that declares none keeps the historical
|
|
298
|
+
// negative-count reading. That is a TIGHTENING, not a relaxation: a
|
|
299
|
+
// classed file must now state its true near-miss count instead of being
|
|
300
|
+
// forced to inflate it to the negative total, and the 175 unclassed
|
|
301
|
+
// files are unaffected.
|
|
302
|
+
const classed = queries.some((q) => typeof q['class'] === 'string' && q['class'] !== '');
|
|
303
|
+
const neg = classed
|
|
304
|
+
? queries.filter((q) => q['class'] === 'near-miss').length
|
|
305
|
+
: queries.filter((q) => q['trigger'] === false).length;
|
|
306
|
+
const mp = POSITIVE_COUNT.exec(desc);
|
|
307
|
+
const mn = NEGATIVE_COUNT.exec(desc);
|
|
308
|
+
if (mp !== null && Number(mp[1]) !== pos) {
|
|
309
|
+
findings.push({
|
|
310
|
+
kind: 'declared-count-mismatch',
|
|
311
|
+
file: rel,
|
|
312
|
+
line: lineOf(source, '"description"'),
|
|
313
|
+
message: `description claims ${mp[1]} positives; the query list holds ${String(pos)}.`,
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
if (mn !== null && Number(mn[1]) !== neg) {
|
|
317
|
+
findings.push({
|
|
318
|
+
kind: 'declared-count-mismatch',
|
|
319
|
+
file: rel,
|
|
320
|
+
line: lineOf(source, '"description"'),
|
|
321
|
+
message:
|
|
322
|
+
`description claims ${mn[1]} near-misses; the query list holds ${String(neg)}` +
|
|
323
|
+
`${classed ? ' case(s) classed `near-miss`' : ' non-triggering quer(ies)'}.`,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return findings;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export interface RunResult {
|
|
332
|
+
findings: Finding[];
|
|
333
|
+
scanned: number;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Scan a tree. */
|
|
337
|
+
export function run(root: string, ledger?: GateLedger): RunResult {
|
|
338
|
+
const specs = listSpecs(root);
|
|
339
|
+
const tracked = trackedPaths(root);
|
|
340
|
+
const findings: Finding[] = [];
|
|
341
|
+
for (const rel of specs) {
|
|
342
|
+
ledger?.plan(rel);
|
|
343
|
+
let source: string;
|
|
344
|
+
try {
|
|
345
|
+
source = fs.readFileSync(path.join(root, rel), 'utf-8');
|
|
346
|
+
} catch {
|
|
347
|
+
ledger?.skip(rel, 'check_did_not_run');
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const got = checkSpec(rel, source, tracked);
|
|
351
|
+
if (got.length > 0) {
|
|
352
|
+
findings.push(...got);
|
|
353
|
+
ledger?.fail(rel, `${String(got.length)} finding(s)`);
|
|
354
|
+
} else {
|
|
355
|
+
ledger?.complete(rel);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return { findings, scanned: specs.length };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** Self-test cases. Every rejecting case is one defect class. */
|
|
362
|
+
function selfTest(): number {
|
|
363
|
+
const tmp = fs.mkdtempSync(path.join(REPO_ROOT, '.lint-eval-specs-selftest-'));
|
|
364
|
+
const mk = (name: string, body: string): string => {
|
|
365
|
+
const dir = path.join(tmp, 'src', 'skills', name, 'evals');
|
|
366
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
367
|
+
fs.writeFileSync(path.join(dir, 'evals.json'), body, 'utf-8');
|
|
368
|
+
return tmp;
|
|
369
|
+
};
|
|
370
|
+
const fresh = (): string => {
|
|
371
|
+
fs.rmSync(path.join(tmp, 'src'), { recursive: true, force: true });
|
|
372
|
+
return tmp;
|
|
373
|
+
};
|
|
374
|
+
const invoke = (dir: string): number =>
|
|
375
|
+
runGateCli(REPO_ROOT, 'src/scripts/lint_eval_specs.ts', ['--root', dir, '--quiet'], REPO_ROOT);
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
return runSelfTest({
|
|
379
|
+
gate: 'lint_eval_specs',
|
|
380
|
+
minCases: 6,
|
|
381
|
+
minRejectCases: 4,
|
|
382
|
+
cases: [
|
|
383
|
+
{
|
|
384
|
+
name: 'a duplicate key is rejected (JSON.parse would discard the first silently)',
|
|
385
|
+
expect: 'reject',
|
|
386
|
+
run: () => {
|
|
387
|
+
fresh();
|
|
388
|
+
mk('dup', '{\n "skill": "a",\n "scenarios": [],\n "skill": "b"\n}\n');
|
|
389
|
+
return invoke(tmp);
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
name: 'a tool-choice assertion with no tool list is rejected',
|
|
394
|
+
expect: 'reject',
|
|
395
|
+
run: () => {
|
|
396
|
+
fresh();
|
|
397
|
+
mk(
|
|
398
|
+
'grader',
|
|
399
|
+
JSON.stringify({
|
|
400
|
+
skill: 'grader',
|
|
401
|
+
scenarios: [
|
|
402
|
+
{ id: 'x', prompt: 'p', assertions: [{ kind: 'tool-choice' }] },
|
|
403
|
+
],
|
|
404
|
+
}),
|
|
405
|
+
);
|
|
406
|
+
return invoke(tmp);
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'a derivation that disagrees with itself is rejected',
|
|
411
|
+
expect: 'reject',
|
|
412
|
+
run: () => {
|
|
413
|
+
fresh();
|
|
414
|
+
mk(
|
|
415
|
+
'arith',
|
|
416
|
+
JSON.stringify({
|
|
417
|
+
skill: 'arith',
|
|
418
|
+
cases: [
|
|
419
|
+
{
|
|
420
|
+
id: 'c',
|
|
421
|
+
check: {
|
|
422
|
+
kind: 'deterministic',
|
|
423
|
+
expected: 8.5,
|
|
424
|
+
tolerance: 0,
|
|
425
|
+
rationale: '4,200,000 / 560,000 = 8.5 months.',
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
],
|
|
429
|
+
}),
|
|
430
|
+
);
|
|
431
|
+
return invoke(tmp);
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: 'a declared positive count that the query list contradicts is rejected',
|
|
436
|
+
expect: 'reject',
|
|
437
|
+
run: () => {
|
|
438
|
+
fresh();
|
|
439
|
+
const dir = path.join(tmp, 'src', 'skills', 'count', 'evals');
|
|
440
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
441
|
+
fs.writeFileSync(
|
|
442
|
+
path.join(dir, 'triggers.json'),
|
|
443
|
+
JSON.stringify({
|
|
444
|
+
skill: 'count',
|
|
445
|
+
description: '3 positives + 2 near-misses.',
|
|
446
|
+
queries: [
|
|
447
|
+
{ q: 'a', trigger: true },
|
|
448
|
+
{ q: 'b', trigger: false },
|
|
449
|
+
{ q: 'c', trigger: false },
|
|
450
|
+
],
|
|
451
|
+
}),
|
|
452
|
+
'utf-8',
|
|
453
|
+
);
|
|
454
|
+
return invoke(tmp);
|
|
455
|
+
},
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
name: 'a well-formed chained derivation is accepted (intermediate steps are not claims)',
|
|
459
|
+
expect: 'accept',
|
|
460
|
+
run: () => {
|
|
461
|
+
fresh();
|
|
462
|
+
mk(
|
|
463
|
+
'ok',
|
|
464
|
+
JSON.stringify({
|
|
465
|
+
skill: 'ok',
|
|
466
|
+
cases: [
|
|
467
|
+
{
|
|
468
|
+
id: 'c',
|
|
469
|
+
check: {
|
|
470
|
+
kind: 'deterministic',
|
|
471
|
+
expected: 20000,
|
|
472
|
+
tolerance: 0,
|
|
473
|
+
rationale: '500 x 0.80 / 0.02 = 400 / 0.02 = 20,000.',
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
],
|
|
477
|
+
}),
|
|
478
|
+
);
|
|
479
|
+
return invoke(tmp);
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
name: 'a tool-choice assertion that names a tool is accepted',
|
|
484
|
+
expect: 'accept',
|
|
485
|
+
run: () => {
|
|
486
|
+
fresh();
|
|
487
|
+
mk(
|
|
488
|
+
'graded',
|
|
489
|
+
JSON.stringify({
|
|
490
|
+
skill: 'graded',
|
|
491
|
+
scenarios: [
|
|
492
|
+
{
|
|
493
|
+
id: 'x',
|
|
494
|
+
prompt: 'p',
|
|
495
|
+
assertions: [{ kind: 'tool-choice', must_use: ['Bash'] }],
|
|
496
|
+
},
|
|
497
|
+
],
|
|
498
|
+
}),
|
|
499
|
+
);
|
|
500
|
+
return invoke(tmp);
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
{
|
|
504
|
+
name: 'an empty corpus is REFUSED, not passed (exit 2 counts as a rejection)',
|
|
505
|
+
expect: 'reject',
|
|
506
|
+
run: () => {
|
|
507
|
+
fresh();
|
|
508
|
+
fs.mkdirSync(path.join(tmp, 'src', 'skills'), { recursive: true });
|
|
509
|
+
return invoke(tmp);
|
|
510
|
+
},
|
|
511
|
+
},
|
|
512
|
+
],
|
|
513
|
+
});
|
|
514
|
+
} finally {
|
|
515
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
520
|
+
if (argv.includes('--self-test')) {
|
|
521
|
+
if (process.env['GATE_SELF_TEST_CHILD'] === '1') {
|
|
522
|
+
process.stderr.write('lint_eval_specs: --self-test must not recurse\n');
|
|
523
|
+
return 2;
|
|
524
|
+
}
|
|
525
|
+
return selfTest();
|
|
526
|
+
}
|
|
527
|
+
const rootIdx = argv.indexOf('--root');
|
|
528
|
+
const rootArg = rootIdx >= 0 ? argv[rootIdx + 1] : undefined;
|
|
529
|
+
const root = rootArg === undefined ? REPO_ROOT : path.resolve(rootArg);
|
|
530
|
+
const quiet = argv.includes('--quiet');
|
|
531
|
+
const asJson = argv.includes('--json');
|
|
532
|
+
const isFixture = root !== REPO_ROOT;
|
|
533
|
+
|
|
534
|
+
const ledger = isFixture ? undefined : new GateLedger('lint_eval_specs');
|
|
535
|
+
const result = run(root, ledger);
|
|
536
|
+
|
|
537
|
+
try {
|
|
538
|
+
const sink = (chunk: string): boolean => {
|
|
539
|
+
if (!quiet) process.stdout.write(chunk);
|
|
540
|
+
return true;
|
|
541
|
+
};
|
|
542
|
+
reportScanned(
|
|
543
|
+
{
|
|
544
|
+
gate: 'lint_eval_specs',
|
|
545
|
+
scanned: result.scanned,
|
|
546
|
+
units: 'eval specification(s)',
|
|
547
|
+
roots: SPEC_GLOB_ROOTS,
|
|
548
|
+
},
|
|
549
|
+
sink,
|
|
550
|
+
);
|
|
551
|
+
} catch (e) {
|
|
552
|
+
if (e instanceof DeadScopeError) {
|
|
553
|
+
process.stderr.write(`❌ ${e.message}\n`);
|
|
554
|
+
return 2;
|
|
555
|
+
}
|
|
556
|
+
throw e;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (asJson) {
|
|
560
|
+
process.stdout.write(`${JSON.stringify({ findings: result.findings, scanned: result.scanned }, null, 2)}\n`);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
if (result.findings.length > 0) {
|
|
564
|
+
if (!quiet && !asJson) {
|
|
565
|
+
process.stderr.write(
|
|
566
|
+
`❌ lint_eval_specs: ${String(result.findings.length)} finding(s) in the measurement inputs:\n`,
|
|
567
|
+
);
|
|
568
|
+
for (const f of result.findings) {
|
|
569
|
+
const at = f.line === undefined ? f.file : `${f.file}:${String(f.line)}`;
|
|
570
|
+
process.stderr.write(` ${at} ${f.kind} ${f.message}\n`);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
ledger?.report(quiet ? () => undefined : undefined);
|
|
574
|
+
return 1;
|
|
575
|
+
}
|
|
576
|
+
ledger?.report(quiet ? () => undefined : undefined);
|
|
577
|
+
if (!quiet && !asJson) {
|
|
578
|
+
process.stdout.write(
|
|
579
|
+
`✅ lint_eval_specs: ${String(result.scanned)} specification(s) clean.\n`,
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
return 0;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/* c8 ignore start */
|
|
586
|
+
function isCliEntry(): boolean {
|
|
587
|
+
if (process.argv[1] === undefined) return false;
|
|
588
|
+
return pathToFileURL(path.resolve(process.argv[1])).href === pathToFileURL(_HERE).href;
|
|
589
|
+
}
|
|
590
|
+
if (isCliEntry()) {
|
|
591
|
+
process.exit(main());
|
|
592
|
+
}
|
|
593
|
+
/* c8 ignore stop */
|
|
@@ -29,6 +29,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
29
29
|
import { parse as parseYaml } from "yaml";
|
|
30
30
|
|
|
31
31
|
import { assertScanned, DeadScopeError } from "./_lib/scan_scope.js";
|
|
32
|
+
import { RE_ARM_EVENTS } from "./_lib/prefix_stable_surfaces.js";
|
|
32
33
|
|
|
33
34
|
// src/scripts/lint_hook_manifest.ts → two levels up is the repo root.
|
|
34
35
|
const REPO_ROOT = path.resolve(
|
|
@@ -214,6 +215,24 @@ function _check_concerns(manifest: YamlObject, errors: string[]): Set<string> {
|
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
}
|
|
218
|
+
// `re_arm:` — the named boundary at which a rebuilt prompt prefix is
|
|
219
|
+
// expected and paid for once (`road-to-runtime-context-floors` step 1.2).
|
|
220
|
+
// `check_prefix_stable_mutation` reads this key to decide whether a
|
|
221
|
+
// mid-session write into a declared prefix-stable surface is a violation or
|
|
222
|
+
// a declared, budgeted rebuild. Validated here for the same reason
|
|
223
|
+
// `needs_payload_bodies` is: the gate treats an unrecognised value as
|
|
224
|
+
// "undeclared" and fails, so a typo would look like a real violation and
|
|
225
|
+
// send the author hunting the wrong defect.
|
|
226
|
+
if ("re_arm" in spec) {
|
|
227
|
+
const ev = spec["re_arm"];
|
|
228
|
+
if (typeof ev !== "string" || !RE_ARM_EVENTS.includes(ev)) {
|
|
229
|
+
errors.push(
|
|
230
|
+
`concerns.${name}: 're_arm' must name a declared re-arm event ` +
|
|
231
|
+
`(${RE_ARM_EVENTS.join(" | ")}), got ${JSON.stringify(ev)} — ` +
|
|
232
|
+
`see docs/contracts/prefix-stable-surfaces.md`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
217
236
|
// `nudge_rank:` — the nudge-exclusivity ordering `injection_budget`
|
|
218
237
|
// arbitrates on. Validated here because `injection_budget._selectNudge`
|
|
219
238
|
// says so in as many words: "a tie is a manifest defect rather than a
|