@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.
Files changed (466) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +234 -0
  5. package/CONTRIBUTING.md +38 -0
  6. package/CREDITS.md +135 -0
  7. package/NOTICE +13 -0
  8. package/README.md +8 -6
  9. package/dist/agent-src/commands/analyze/inbox.md +109 -2
  10. package/dist/agent-src/commands/feature/dev.md +7 -2
  11. package/dist/agent-src/commands/ghostwriter/write.md +5 -1
  12. package/dist/agent-src/commands/implement-ticket.md +1 -1
  13. package/dist/agent-src/commands/mission/upgrade.md +1 -1
  14. package/dist/agent-src/commands/orchestrate.md +2 -2
  15. package/dist/agent-src/commands/post-as/me.md +5 -1
  16. package/dist/agent-src/commands/pr/merge.md +19 -6
  17. package/dist/agent-src/commands/roadmap/process-full.md +19 -5
  18. package/dist/agent-src/commands/tdd/red.md +12 -2
  19. package/dist/agent-src/commands/work.md +1 -1
  20. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
  21. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
  22. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
  23. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
  24. package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
  25. package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
  26. package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
  27. package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
  28. package/dist/agent-src/rules/broken-access-control.md +4 -0
  29. package/dist/agent-src/rules/code-provenance.md +4 -0
  30. package/dist/agent-src/rules/design-fidelity.md +1 -1
  31. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  32. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  33. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  34. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  35. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  36. package/dist/agent-src/rules/laravel-routing.md +1 -1
  37. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  38. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  39. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  40. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  41. package/dist/agent-src/rules/symfony-routing.md +1 -1
  42. package/dist/agent-src/rules/token-efficiency.md +14 -0
  43. package/dist/agent-src/rules/tool-safety.md +4 -0
  44. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  45. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  46. package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
  47. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  48. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  49. package/dist/agent-src/scripts/stubs_due.ts +400 -0
  50. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  51. package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
  52. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  53. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  54. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  55. package/dist/agent-src/skills/database/SKILL.md +8 -0
  56. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  57. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  58. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  60. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  61. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  62. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  63. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  64. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  65. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  66. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  67. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  68. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  69. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  70. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  71. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  72. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  73. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  74. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  75. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  76. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  77. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  78. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  79. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  80. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  81. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  82. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  83. package/dist/agent-src/templates/roadmaps.md +97 -3
  84. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  85. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  86. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  87. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  88. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  93. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  94. package/dist/cli/commands/uiAudit.js +124 -5
  95. package/dist/cli/registry.js +2 -0
  96. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  97. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  98. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  99. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  100. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  101. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  102. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  103. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  104. package/dist/cli-delegate/cmd_conformance.js +42 -10
  105. package/dist/cli-delegate/cmd_doctor.js +3 -3
  106. package/dist/cli-delegate/cmd_export.js +3 -2
  107. package/dist/cli-delegate/cmd_fleet.js +2 -2
  108. package/dist/cli-delegate/cmd_handoff.js +1 -1
  109. package/dist/cli-delegate/cmd_preflight.js +2 -2
  110. package/dist/cli-delegate/cmd_prune.js +3 -2
  111. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  112. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  113. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  114. package/dist/cli-delegate/cmd_sync.js +3 -2
  115. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  116. package/dist/cli-delegate/cmd_validate.js +3 -2
  117. package/dist/discovery/deprecation-report.md +1 -1
  118. package/dist/discovery/discovery-manifest.json +57 -57
  119. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  120. package/dist/discovery/discovery-manifest.summary.md +1 -1
  121. package/dist/discovery/dormancy-report.md +1 -1
  122. package/dist/discovery/orphan-report.md +1 -1
  123. package/dist/discovery/packs.json +2 -2
  124. package/dist/discovery/trust-report.md +1 -1
  125. package/dist/discovery/workspaces.json +2 -2
  126. package/dist/hooks/dispatch.js +1836 -712
  127. package/dist/install/claudeRuleRewrite.js +254 -0
  128. package/dist/install/detect.js +29 -16
  129. package/dist/install/detect_php_shape.js +159 -0
  130. package/dist/install/install.mjs +634 -428
  131. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  132. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  133. package/dist/mcp/registry-manifest.json +3 -3
  134. package/dist/mcp/server.json +3 -3
  135. package/dist/mcp/server.mjs +4818 -2645
  136. package/dist/server/schemas/settings.js +3 -0
  137. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  138. package/dist/ui/index.html +1 -1
  139. package/docs/MIGRATION.md +1 -1
  140. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  141. package/docs/contracts/provider-lifecycle.md +1 -1
  142. package/docs/contracts/settings-classes.md +10 -4
  143. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  144. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  145. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  146. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  147. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  148. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  149. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  150. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  151. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  152. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  153. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  154. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  155. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  156. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  157. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  158. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  159. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  160. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  161. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  162. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  163. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  164. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  165. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  166. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  167. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  168. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  169. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  170. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  171. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  172. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  173. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  174. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  175. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  176. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  177. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  178. package/docs/guidelines/augment-portability-patterns.md +6 -4
  179. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  180. package/docs/guidelines/cross-role-handoff.md +2 -2
  181. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  182. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  183. package/docs/guidelines/php/database.md +90 -7
  184. package/docs/guidelines/prompt-templates.md +7 -7
  185. package/llms.txt +2 -2
  186. package/package.json +5 -2
  187. package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
  188. package/src/agent-src/scripts/guarded_baseline.ts +328 -0
  189. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  190. package/src/agent-src/scripts/stub_queue.ts +82 -0
  191. package/src/agent-src/scripts/stubs_due.ts +400 -0
  192. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  193. package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
  194. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  195. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  196. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  197. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  198. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  199. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  202. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  203. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  204. package/src/config/agent-settings.template.yml +32 -3
  205. package/src/config/assurance-capability-registry.json +21 -9
  206. package/src/config/canonical-terms.yml +119 -0
  207. package/src/config/capability-native-outcome-bars.json +81 -0
  208. package/src/config/ci-local-parity.yml +80 -0
  209. package/src/config/drafting-channels.yml +43 -0
  210. package/src/config/estate-count-budget.json +38 -36
  211. package/src/config/evaluator-budgets.json +14 -14
  212. package/src/config/gate-coverage.yml +579 -63
  213. package/src/config/gate-reachability-exemptions.json +21 -0
  214. package/src/config/gate-violation-baselines.json +37 -19
  215. package/src/config/harness-evolution-budget.json +25 -0
  216. package/src/config/lapsed-beta-baseline.json +96 -0
  217. package/src/config/memory-twin-verdicts.yml +129 -0
  218. package/src/config/metric-registry.yml +124 -0
  219. package/src/config/pack-size-budget.json +16 -15
  220. package/src/config/preamble-payload-budget.json +8 -8
  221. package/src/config/profiles/balanced.ini +27 -0
  222. package/src/config/profiles/full.ini +27 -0
  223. package/src/config/profiles/minimal.ini +27 -0
  224. package/src/config/publish-surface.json +9 -2
  225. package/src/config/routing-coverage-seed.json +16 -2
  226. package/src/config/rule-stub-ceilings.json +126 -112
  227. package/src/config/turnaround-budget.json +66 -0
  228. package/src/install/claudeRuleRewrite.ts +288 -0
  229. package/src/install/detect.ts +60 -17
  230. package/src/install/detect_php_shape.ts +191 -0
  231. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  232. package/src/scripts/_dispatch.bash +27 -0
  233. package/src/scripts/_lib/activation_ladder.ts +211 -0
  234. package/src/scripts/_lib/activation_states.ts +88 -0
  235. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  236. package/src/scripts/_lib/arith_claims.ts +181 -0
  237. package/src/scripts/_lib/arm_ranking.ts +62 -0
  238. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  239. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  240. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  241. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  242. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  243. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  244. package/src/scripts/_lib/candidate_record.ts +601 -0
  245. package/src/scripts/_lib/capture_rate.ts +319 -0
  246. package/src/scripts/_lib/collector_denominator.ts +771 -0
  247. package/src/scripts/_lib/collector_record.ts +340 -0
  248. package/src/scripts/_lib/collector_store.ts +664 -0
  249. package/src/scripts/_lib/collector_supervision.ts +827 -0
  250. package/src/scripts/_lib/concern_estate.ts +77 -0
  251. package/src/scripts/_lib/config_chain.ts +477 -0
  252. package/src/scripts/_lib/config_cost.ts +209 -0
  253. package/src/scripts/_lib/council_settings_block.ts +6 -0
  254. package/src/scripts/_lib/curator_ops.ts +172 -0
  255. package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
  256. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  257. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  258. package/src/scripts/_lib/empty_cycles.ts +88 -0
  259. package/src/scripts/_lib/eval_publication.ts +354 -0
  260. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  261. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  262. package/src/scripts/_lib/evidence_basis.ts +118 -0
  263. package/src/scripts/_lib/exec_evidence.ts +8 -0
  264. package/src/scripts/_lib/experience_card.ts +272 -0
  265. package/src/scripts/_lib/experience_report.ts +151 -0
  266. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  267. package/src/scripts/_lib/generated_by.ts +66 -0
  268. package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
  269. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  270. package/src/scripts/_lib/host_denominator.ts +687 -0
  271. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  272. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  273. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  274. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  275. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  276. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  277. package/src/scripts/_lib/loop_guards.ts +299 -0
  278. package/src/scripts/_lib/loss_class.ts +129 -0
  279. package/src/scripts/_lib/machine_wake.ts +51 -0
  280. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  281. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  282. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  283. package/src/scripts/_lib/orchestration_record.ts +253 -5
  284. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  285. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  286. package/src/scripts/_lib/paired_stats.ts +245 -0
  287. package/src/scripts/_lib/paired_verdict.ts +226 -0
  288. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  289. package/src/scripts/_lib/privacy_class.ts +47 -0
  290. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  291. package/src/scripts/_lib/repeated_failure.ts +105 -0
  292. package/src/scripts/_lib/repo_root.ts +111 -0
  293. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  294. package/src/scripts/_lib/role_split.ts +338 -0
  295. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  296. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  297. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  298. package/src/scripts/_lib/source_digest.ts +200 -0
  299. package/src/scripts/_lib/source_redact.ts +260 -0
  300. package/src/scripts/_lib/source_shape.ts +502 -0
  301. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  302. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  303. package/src/scripts/_lib/strip_comments.mjs +65 -0
  304. package/src/scripts/_lib/test_red_state.ts +154 -0
  305. package/src/scripts/_lib/trigger_shift.ts +144 -0
  306. package/src/scripts/_lib/untrusted_content.ts +82 -7
  307. package/src/scripts/adoption_report.ts +1 -1
  308. package/src/scripts/adr/evidence_census.ts +1 -1
  309. package/src/scripts/adr/regenerate_index.ts +26 -2
  310. package/src/scripts/adr_cite_check.ts +164 -1
  311. package/src/scripts/ai_council/blind_review.ts +11 -1
  312. package/src/scripts/ai_council/clients.ts +4 -0
  313. package/src/scripts/ai_council/config.ts +3 -0
  314. package/src/scripts/ai_council/consensus.ts +28 -8
  315. package/src/scripts/ai_council/consensus_round.ts +226 -0
  316. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  317. package/src/scripts/ai_council/inline_findings.ts +340 -0
  318. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  319. package/src/scripts/ai_council/orchestrator.ts +16 -203
  320. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  321. package/src/scripts/ai_council/pricing.ts +106 -0
  322. package/src/scripts/ai_council/prompts.ts +74 -7
  323. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  324. package/src/scripts/ai_council/py_format.ts +14 -3
  325. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  326. package/src/scripts/ai_council/response_record.ts +50 -0
  327. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  328. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  329. package/src/scripts/asset_delivery_ledger.ts +157 -0
  330. package/src/scripts/attest_artifact.ts +193 -0
  331. package/src/scripts/audit_auto_rules.ts +2 -1
  332. package/src/scripts/audit_command_surface.ts +1 -1
  333. package/src/scripts/audit_mcp_tools.ts +2 -2
  334. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  335. package/src/scripts/audit_user_type_axis.ts +2 -1
  336. package/src/scripts/bench_ab_clone.ts +215 -10
  337. package/src/scripts/bench_ab_integrity.ts +119 -5
  338. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  339. package/src/scripts/build_archive_index.ts +1 -1
  340. package/src/scripts/build_linear_digest.ts +1 -1
  341. package/src/scripts/build_proof.ts +11 -4
  342. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  343. package/src/scripts/build_source_digests.ts +157 -0
  344. package/src/scripts/cache_realization_report.ts +103 -0
  345. package/src/scripts/check_adr_frontmatter.ts +126 -0
  346. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  347. package/src/scripts/check_beta_review_markers.ts +235 -6
  348. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  349. package/src/scripts/check_claims.ts +576 -6
  350. package/src/scripts/check_composite_arming.ts +35 -0
  351. package/src/scripts/check_concern_admissions.ts +365 -0
  352. package/src/scripts/check_enforcement_coverage.ts +28 -0
  353. package/src/scripts/check_estate_count.ts +142 -1
  354. package/src/scripts/check_gate_reachability.ts +383 -0
  355. package/src/scripts/check_host_loadability.ts +104 -0
  356. package/src/scripts/check_loss_class_declared.ts +308 -0
  357. package/src/scripts/check_md_language.ts +15 -98
  358. package/src/scripts/check_memory_proposal.ts +18 -11
  359. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  360. package/src/scripts/check_no_external_sources.ts +281 -6
  361. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  362. package/src/scripts/check_pack_size.ts +59 -2
  363. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  364. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  365. package/src/scripts/check_publish_surface.ts +10 -1
  366. package/src/scripts/check_references.ts +24 -1
  367. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  368. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  369. package/src/scripts/check_score_contract.ts +26 -3
  370. package/src/scripts/check_static_parity.ts +285 -0
  371. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  372. package/src/scripts/check_suppression_hygiene.ts +15 -0
  373. package/src/scripts/ci_settle.ts +39 -2
  374. package/src/scripts/code_graph/build.ts +60 -3
  375. package/src/scripts/code_graph/extract.ts +44 -0
  376. package/src/scripts/code_graph/types.ts +24 -0
  377. package/src/scripts/collector_daemon.ts +714 -0
  378. package/src/scripts/config_cost_report.ts +302 -0
  379. package/src/scripts/consumer_matrix.ts +74 -1
  380. package/src/scripts/cost/budget.mjs +10 -3
  381. package/src/scripts/cost/track.mjs +10 -3
  382. package/src/scripts/council_cli.ts +37 -54
  383. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  384. package/src/scripts/evolution_lab.ts +980 -0
  385. package/src/scripts/external_sources_denylist.json +5 -18
  386. package/src/scripts/extract_audit_patterns.ts +21 -0
  387. package/src/scripts/fold_intake.ts +12 -1
  388. package/src/scripts/gen_discovery_baseline.ts +1 -1
  389. package/src/scripts/generate_capabilities_index.ts +12 -5
  390. package/src/scripts/generate_capability_matrix.ts +3 -3
  391. package/src/scripts/generate_command_flows.ts +2 -2
  392. package/src/scripts/generate_cookbook.ts +2 -2
  393. package/src/scripts/generate_index.ts +8 -1
  394. package/src/scripts/generate_knowledge_index.ts +2 -1
  395. package/src/scripts/generate_ownership_matrix.ts +2 -1
  396. package/src/scripts/generate_pack_manifests.ts +10 -2
  397. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  398. package/src/scripts/generate_settings_reference.ts +1 -1
  399. package/src/scripts/git_authorization_hook.ts +22 -1
  400. package/src/scripts/grade_target_readiness.ts +48 -5
  401. package/src/scripts/hook_effect_doctor.ts +261 -0
  402. package/src/scripts/hook_manifest.json +1 -1
  403. package/src/scripts/hook_manifest.yaml +98 -11
  404. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  405. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  406. package/src/scripts/hooks/concern_registry.ts +4 -0
  407. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  408. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  409. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  410. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  411. package/src/scripts/hooks/shims/install.sh +61 -0
  412. package/src/scripts/hooks/shims/php +101 -0
  413. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  414. package/src/scripts/hot_context_hook.ts +16 -0
  415. package/src/scripts/install-hooks.sh +20 -5
  416. package/src/scripts/install.ts +17 -35
  417. package/src/scripts/inventory_frontmatter.ts +2 -1
  418. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  419. package/src/scripts/lint_canonical_terms.ts +604 -0
  420. package/src/scripts/lint_composition_review.ts +619 -0
  421. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  422. package/src/scripts/lint_eval_specs.ts +593 -0
  423. package/src/scripts/lint_hook_manifest.ts +19 -0
  424. package/src/scripts/lint_host_portability.ts +373 -0
  425. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  426. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  427. package/src/scripts/lint_metric_consumers.ts +355 -0
  428. package/src/scripts/lint_skill_descriptions.ts +18 -1
  429. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  430. package/src/scripts/lint_skill_link_reach.ts +252 -0
  431. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  432. package/src/scripts/lint_ticket_buildable.ts +17 -1
  433. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  434. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  435. package/src/scripts/measure_docs_dead_links.ts +348 -0
  436. package/src/scripts/measure_host_capture.ts +461 -0
  437. package/src/scripts/migration_status.ts +3 -3
  438. package/src/scripts/model_rule_injection.ts +60 -0
  439. package/src/scripts/orchestration_record.ts +14 -0
  440. package/src/scripts/preamble_byte_census.ts +139 -10
  441. package/src/scripts/prepack-check.mjs +4 -1
  442. package/src/scripts/probe_turnaround.ts +384 -0
  443. package/src/scripts/probe_unblocked_ask.ts +279 -0
  444. package/src/scripts/render_benchmark_md.ts +1 -1
  445. package/src/scripts/rule_activation_census.ts +70 -9
  446. package/src/scripts/rule_backlinks.ts +1 -1
  447. package/src/scripts/run_lifecycle_suite.ts +208 -0
  448. package/src/scripts/run_skill_evals.ts +40 -0
  449. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  450. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  451. package/src/scripts/schemas/evals.schema.json +24 -1
  452. package/src/scripts/schemas/rule.schema.json +52 -1
  453. package/src/scripts/schemas/skill.schema.json +17 -2
  454. package/src/scripts/skill_overlap.ts +7 -1
  455. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  456. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  457. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  458. package/src/scripts/skill_usage_report.ts +2 -1
  459. package/src/scripts/stubs_due.ts +211 -0
  460. package/src/scripts/sweep_source_surfaces.ts +678 -0
  461. package/src/scripts/sync_pr_branch.ts +3 -3
  462. package/src/scripts/trigger_eval_grandfather.json +202 -222
  463. package/src/scripts/utilization_report.ts +22 -2
  464. package/src/server/schemas/settings.ts +5 -0
  465. package/src/templates/marketing-copy.yml +1 -1
  466. 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