@event4u/agent-config 14.12.0 → 14.14.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 (521) 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 +118 -155
  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 +145 -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-comment-discipline.md +6 -0
  30. package/dist/agent-src/rules/code-provenance.md +4 -0
  31. package/dist/agent-src/rules/design-fidelity.md +1 -1
  32. package/dist/agent-src/rules/domain-safety-pii.md +4 -0
  33. package/dist/agent-src/rules/domain-safety-retention.md +4 -0
  34. package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
  35. package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
  36. package/dist/agent-src/rules/improve-before-implement.md +6 -8
  37. package/dist/agent-src/rules/laravel-routing.md +1 -1
  38. package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
  39. package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
  40. package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
  41. package/dist/agent-src/rules/source-confidentiality.md +12 -34
  42. package/dist/agent-src/rules/symfony-routing.md +1 -1
  43. package/dist/agent-src/rules/token-efficiency.md +14 -0
  44. package/dist/agent-src/rules/tool-safety.md +4 -0
  45. package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
  46. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  47. package/dist/agent-src/scripts/guarded_baseline.ts +343 -0
  48. package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
  49. package/dist/agent-src/scripts/stub_queue.ts +82 -0
  50. package/dist/agent-src/scripts/stubs_due.ts +516 -0
  51. package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
  52. package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
  53. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
  54. package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
  55. package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
  56. package/dist/agent-src/skills/database/SKILL.md +8 -0
  57. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
  58. package/dist/agent-src/skills/design-review/SKILL.md +1 -1
  59. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  60. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +17 -1
  61. package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
  62. package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
  63. package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
  64. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
  65. package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
  66. package/dist/agent-src/skills/laravel/SKILL.md +35 -0
  67. package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
  68. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
  69. package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
  70. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +1 -1
  71. package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
  72. package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
  73. package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
  74. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
  75. package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
  76. package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
  77. package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
  78. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  79. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
  80. package/dist/agent-src/skills/ui-component-architect/SKILL.md +45 -2
  81. package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
  82. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
  83. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  84. package/dist/agent-src/templates/roadmaps.md +97 -3
  85. package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
  86. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  87. package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
  88. package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
  89. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  90. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  91. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  92. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  93. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  94. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  95. package/dist/cli/commands/uiAudit.js +124 -5
  96. package/dist/cli/registry.js +2 -0
  97. package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
  98. package/dist/cli-delegate/{chunk-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
  99. package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
  100. package/dist/cli-delegate/{chunk-JJA2QEWA.js → chunk-AKJGUQNO.js} +466 -285
  101. package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
  102. package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
  103. package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
  104. package/dist/cli-delegate/cmd_adr_effective.js +102 -0
  105. package/dist/cli-delegate/cmd_conformance.js +80 -11
  106. package/dist/cli-delegate/cmd_doctor.js +3 -3
  107. package/dist/cli-delegate/cmd_export.js +3 -2
  108. package/dist/cli-delegate/cmd_fleet.js +2 -2
  109. package/dist/cli-delegate/cmd_handoff.js +1 -1
  110. package/dist/cli-delegate/cmd_preflight.js +2 -2
  111. package/dist/cli-delegate/cmd_prune.js +3 -2
  112. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  113. package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
  114. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  115. package/dist/cli-delegate/cmd_sync.js +3 -2
  116. package/dist/cli-delegate/cmd_uninstall.js +3 -2
  117. package/dist/cli-delegate/cmd_validate.js +3 -2
  118. package/dist/discovery/deprecation-report.md +1 -1
  119. package/dist/discovery/discovery-manifest.json +58 -58
  120. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  121. package/dist/discovery/discovery-manifest.summary.md +1 -1
  122. package/dist/discovery/dormancy-report.md +1 -1
  123. package/dist/discovery/orphan-report.md +1 -1
  124. package/dist/discovery/packs.json +2 -2
  125. package/dist/discovery/trust-report.md +1 -1
  126. package/dist/discovery/workspaces.json +2 -2
  127. package/dist/hooks/dispatch.js +2900 -1049
  128. package/dist/install/claudeRuleRewrite.js +254 -0
  129. package/dist/install/detect.js +29 -16
  130. package/dist/install/detect_php_shape.js +159 -0
  131. package/dist/install/install.mjs +634 -428
  132. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  133. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  134. package/dist/mcp/registry-manifest.json +3 -3
  135. package/dist/mcp/server.json +3 -3
  136. package/dist/mcp/server.mjs +4895 -2627
  137. package/dist/server/schemas/settings.js +3 -0
  138. package/dist/ui/assets/index-D0jaCRPM.js +29 -0
  139. package/dist/ui/index.html +1 -1
  140. package/docs/MIGRATION.md +1 -1
  141. package/docs/THIRD-PARTY-NOTICES.md +25 -0
  142. package/docs/contracts/provider-lifecycle.md +1 -1
  143. package/docs/contracts/settings-classes.md +10 -4
  144. package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
  145. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
  146. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
  147. package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
  148. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
  149. package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
  150. package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
  151. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  152. package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
  153. package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
  154. package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
  155. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
  156. package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
  157. package/docs/guidelines/agent-infra/first-principles.md +2 -2
  158. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
  159. package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
  160. package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
  161. package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
  162. package/docs/guidelines/agent-infra/layered-settings.md +10 -10
  163. package/docs/guidelines/agent-infra/memory-access.md +1 -1
  164. package/docs/guidelines/agent-infra/mental-models.md +3 -3
  165. package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
  166. package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
  167. package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
  168. package/docs/guidelines/agent-infra/role-contracts.md +2 -2
  169. package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
  170. package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
  171. package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
  172. package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
  173. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
  174. package/docs/guidelines/agent-infra/six-hats.md +3 -3
  175. package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
  176. package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
  177. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  178. package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
  179. package/docs/guidelines/augment-portability-patterns.md +6 -4
  180. package/docs/guidelines/code-clarity.md +18 -0
  181. package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
  182. package/docs/guidelines/cross-role-handoff.md +2 -2
  183. package/docs/guidelines/design-fidelity-mechanics.md +1 -1
  184. package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
  185. package/docs/guidelines/php/database.md +90 -7
  186. package/docs/guidelines/prompt-templates.md +7 -7
  187. package/llms.txt +2 -2
  188. package/package.json +5 -2
  189. package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
  190. package/src/agent-src/scripts/guarded_baseline.ts +343 -0
  191. package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
  192. package/src/agent-src/scripts/stub_queue.ts +82 -0
  193. package/src/agent-src/scripts/stubs_due.ts +516 -0
  194. package/src/agent-src/scripts/ticket_bundles.ts +84 -0
  195. package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
  196. package/src/agent-src/templates/scripts/check_memory.ts +258 -17
  197. package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
  198. package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
  199. package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
  200. package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
  201. package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
  202. package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
  203. package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
  204. package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
  205. package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
  206. package/src/config/agent-settings.template.yml +32 -3
  207. package/src/config/assurance-capability-registry.json +21 -9
  208. package/src/config/canonical-terms.yml +119 -0
  209. package/src/config/capability-native-outcome-bars.json +81 -0
  210. package/src/config/ci-local-parity.yml +80 -0
  211. package/src/config/drafting-channels.yml +43 -0
  212. package/src/config/estate-count-budget.json +57 -36
  213. package/src/config/evaluator-budgets.json +14 -14
  214. package/src/config/gate-coverage.yml +729 -63
  215. package/src/config/gate-reachability-exemptions.json +21 -0
  216. package/src/config/gate-violation-baselines.json +42 -19
  217. package/src/config/harness-evolution-budget.json +25 -0
  218. package/src/config/lapsed-beta-baseline.json +96 -0
  219. package/src/config/memory-twin-verdicts.yml +129 -0
  220. package/src/config/metric-registry.yml +124 -0
  221. package/src/config/pack-size-budget.json +16 -15
  222. package/src/config/preamble-payload-budget.json +12 -4
  223. package/src/config/profiles/balanced.ini +27 -0
  224. package/src/config/profiles/full.ini +27 -0
  225. package/src/config/profiles/minimal.ini +27 -0
  226. package/src/config/publish-surface.json +9 -2
  227. package/src/config/routing-coverage-seed.json +16 -2
  228. package/src/config/rule-stub-ceilings.json +133 -112
  229. package/src/config/turnaround-budget.json +66 -0
  230. package/src/install/claudeRuleRewrite.ts +288 -0
  231. package/src/install/detect.ts +60 -17
  232. package/src/install/detect_php_shape.ts +191 -0
  233. package/src/scripts/_cli/cmd_doctor.ts +27 -112
  234. package/src/scripts/_dispatch.bash +23 -0
  235. package/src/scripts/_lib/activation_ladder.ts +255 -0
  236. package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
  237. package/src/scripts/_lib/activation_states.ts +88 -0
  238. package/src/scripts/_lib/adherence_detectors.ts +143 -0
  239. package/src/scripts/_lib/adr_frontmatter.ts +26 -0
  240. package/src/scripts/_lib/arith_claims.ts +181 -0
  241. package/src/scripts/_lib/arm_ranking.ts +62 -0
  242. package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
  243. package/src/scripts/_lib/audit_field_provenance.ts +54 -0
  244. package/src/scripts/_lib/auto_dispatch.ts +32 -3
  245. package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
  246. package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
  247. package/src/scripts/_lib/candidate_pair_delta.ts +349 -0
  248. package/src/scripts/_lib/candidate_proposer.ts +402 -0
  249. package/src/scripts/_lib/candidate_record.ts +601 -0
  250. package/src/scripts/_lib/capture_rate.ts +319 -0
  251. package/src/scripts/_lib/carrier_status.ts +118 -0
  252. package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -0
  253. package/src/scripts/_lib/collector_denominator.ts +771 -0
  254. package/src/scripts/_lib/collector_record.ts +340 -0
  255. package/src/scripts/_lib/collector_store.ts +664 -0
  256. package/src/scripts/_lib/collector_supervision.ts +827 -0
  257. package/src/scripts/_lib/concern_estate.ts +77 -0
  258. package/src/scripts/_lib/config_chain.ts +477 -0
  259. package/src/scripts/_lib/config_cost.ts +209 -0
  260. package/src/scripts/_lib/corpus_manifest.ts +726 -0
  261. package/src/scripts/_lib/council_settings_block.ts +6 -0
  262. package/src/scripts/_lib/curator_ops.ts +172 -0
  263. package/src/scripts/_lib/delivery_arm_experiment.ts +282 -0
  264. package/src/scripts/_lib/delivery_criticality.ts +126 -0
  265. package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
  266. package/src/scripts/_lib/empty_cycles.ts +88 -0
  267. package/src/scripts/_lib/estate_carrier_cases.ts +72 -0
  268. package/src/scripts/_lib/eval_publication.ts +354 -0
  269. package/src/scripts/_lib/evaluation_cascade.ts +452 -0
  270. package/src/scripts/_lib/evaluation_vector.ts +283 -0
  271. package/src/scripts/_lib/evaluator_promotion.ts +225 -0
  272. package/src/scripts/_lib/evidence_basis.ts +118 -0
  273. package/src/scripts/_lib/evolution_roi.ts +562 -0
  274. package/src/scripts/_lib/exec_evidence.ts +8 -0
  275. package/src/scripts/_lib/experience_card.ts +272 -0
  276. package/src/scripts/_lib/experience_report.ts +151 -0
  277. package/src/scripts/_lib/experiment_freeze.ts +112 -0
  278. package/src/scripts/_lib/generated_by.ts +66 -0
  279. package/src/scripts/_lib/harness_evolution_guards.ts +239 -0
  280. package/src/scripts/_lib/hook_effect_probe.ts +141 -0
  281. package/src/scripts/_lib/host_denominator.ts +687 -0
  282. package/src/scripts/_lib/host_projection_reach.ts +157 -0
  283. package/src/scripts/_lib/ignored_blocker.ts +148 -0
  284. package/src/scripts/_lib/install_reach_checks.ts +495 -0
  285. package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
  286. package/src/scripts/_lib/judge_hygiene.ts +228 -0
  287. package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
  288. package/src/scripts/_lib/lexical_shortlist.ts +215 -0
  289. package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
  290. package/src/scripts/_lib/llm_proposer_transport.ts +153 -0
  291. package/src/scripts/_lib/loop_guards.ts +299 -0
  292. package/src/scripts/_lib/loss_class.ts +129 -0
  293. package/src/scripts/_lib/machine_wake.ts +51 -0
  294. package/src/scripts/_lib/md_prose_lines.ts +177 -0
  295. package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
  296. package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
  297. package/src/scripts/_lib/orchestration_record.ts +253 -5
  298. package/src/scripts/_lib/outcome_envelope.ts +227 -0
  299. package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
  300. package/src/scripts/_lib/paired_stats.ts +245 -0
  301. package/src/scripts/_lib/paired_verdict.ts +226 -0
  302. package/src/scripts/_lib/pathology_archive.ts +393 -0
  303. package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
  304. package/src/scripts/_lib/privacy_class.ts +47 -0
  305. package/src/scripts/_lib/promotion_capability.ts +315 -0
  306. package/src/scripts/_lib/promotion_evidence.ts +414 -0
  307. package/src/scripts/_lib/promotion_review.ts +294 -0
  308. package/src/scripts/_lib/prompt_shape.ts +92 -0
  309. package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
  310. package/src/scripts/_lib/release_highlights.ts +70 -1
  311. package/src/scripts/_lib/release_material.ts +125 -2
  312. package/src/scripts/_lib/repeated_failure.ts +105 -0
  313. package/src/scripts/_lib/repo_root.ts +111 -0
  314. package/src/scripts/_lib/review_skipped_record.ts +37 -0
  315. package/src/scripts/_lib/role_split.ts +338 -0
  316. package/src/scripts/_lib/routing_corpus.ts +307 -0
  317. package/src/scripts/_lib/routing_index_input.ts +104 -0
  318. package/src/scripts/_lib/rule_injection.ts +22 -1
  319. package/src/scripts/_lib/runtime_journal.ts +1499 -0
  320. package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
  321. package/src/scripts/_lib/semantic_noop.ts +167 -0
  322. package/src/scripts/_lib/skill_catalogue.ts +11 -1
  323. package/src/scripts/_lib/source_digest.ts +200 -0
  324. package/src/scripts/_lib/source_redact.ts +260 -0
  325. package/src/scripts/_lib/source_shape.ts +502 -0
  326. package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
  327. package/src/scripts/_lib/strip_comments.d.mts +8 -0
  328. package/src/scripts/_lib/strip_comments.mjs +65 -0
  329. package/src/scripts/_lib/test_red_state.ts +154 -0
  330. package/src/scripts/_lib/trigger_shift.ts +144 -0
  331. package/src/scripts/_lib/untrusted_content.ts +82 -7
  332. package/src/scripts/activation_receipt.ts +258 -0
  333. package/src/scripts/adoption_report.ts +1 -1
  334. package/src/scripts/adr/evidence_census.ts +1 -1
  335. package/src/scripts/adr/regenerate_index.ts +26 -2
  336. package/src/scripts/adr_cite_check.ts +164 -1
  337. package/src/scripts/ai_council/blind_review.ts +11 -1
  338. package/src/scripts/ai_council/clients.ts +4 -0
  339. package/src/scripts/ai_council/config.ts +3 -0
  340. package/src/scripts/ai_council/consensus.ts +28 -8
  341. package/src/scripts/ai_council/consensus_round.ts +226 -0
  342. package/src/scripts/ai_council/cross_exam.ts +128 -0
  343. package/src/scripts/ai_council/disagreement_signal.ts +338 -0
  344. package/src/scripts/ai_council/explain_route.ts +157 -0
  345. package/src/scripts/ai_council/information_gain.ts +293 -0
  346. package/src/scripts/ai_council/inline_findings.ts +340 -0
  347. package/src/scripts/ai_council/judge_position_bias.ts +197 -0
  348. package/src/scripts/ai_council/leakage_corpus.ts +385 -0
  349. package/src/scripts/ai_council/leakage_patterns.ts +453 -0
  350. package/src/scripts/ai_council/minority_retention.ts +171 -0
  351. package/src/scripts/ai_council/orchestrator.ts +16 -203
  352. package/src/scripts/ai_council/orchestrator_results.ts +23 -3
  353. package/src/scripts/ai_council/pricing.ts +106 -0
  354. package/src/scripts/ai_council/prompts.ts +74 -7
  355. package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
  356. package/src/scripts/ai_council/py_format.ts +14 -3
  357. package/src/scripts/ai_council/recouncil_guard.ts +293 -0
  358. package/src/scripts/ai_council/recouncil_savings.ts +299 -0
  359. package/src/scripts/ai_council/replay_route.ts +223 -0
  360. package/src/scripts/ai_council/response_record.ts +50 -0
  361. package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
  362. package/src/scripts/ai_council/routing_training_row.ts +197 -0
  363. package/src/scripts/ai_council/synthesis_strategy.ts +159 -0
  364. package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
  365. package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
  366. package/src/scripts/asset_delivery_ledger.ts +157 -0
  367. package/src/scripts/attest_artifact.ts +193 -0
  368. package/src/scripts/audit_auto_rules.ts +2 -1
  369. package/src/scripts/audit_command_surface.ts +1 -1
  370. package/src/scripts/audit_mcp_tools.ts +2 -2
  371. package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
  372. package/src/scripts/audit_user_type_axis.ts +2 -1
  373. package/src/scripts/bench_ab_clone.ts +215 -10
  374. package/src/scripts/bench_ab_integrity.ts +119 -5
  375. package/src/scripts/bench_ab_v2_stats.ts +40 -213
  376. package/src/scripts/build_archive_index.ts +1 -1
  377. package/src/scripts/build_linear_digest.ts +1 -1
  378. package/src/scripts/build_proof.ts +11 -4
  379. package/src/scripts/build_rule_trigger_matrix.ts +1 -1
  380. package/src/scripts/build_source_digests.ts +157 -0
  381. package/src/scripts/cache_realization_report.ts +103 -0
  382. package/src/scripts/check_adr_frontmatter.ts +131 -10
  383. package/src/scripts/check_benchmark_report_fields.ts +207 -0
  384. package/src/scripts/check_beta_review_markers.ts +235 -6
  385. package/src/scripts/check_bundle_path_leakage.ts +34 -1
  386. package/src/scripts/check_claims.ts +576 -6
  387. package/src/scripts/check_composite_arming.ts +35 -0
  388. package/src/scripts/check_concern_admissions.ts +365 -0
  389. package/src/scripts/check_enforcement_coverage.ts +28 -0
  390. package/src/scripts/check_estate_count.ts +347 -25
  391. package/src/scripts/check_gate_reachability.ts +383 -0
  392. package/src/scripts/check_host_loadability.ts +104 -0
  393. package/src/scripts/check_loss_class_declared.ts +308 -0
  394. package/src/scripts/check_md_language.ts +15 -98
  395. package/src/scripts/check_memory_proposal.ts +18 -11
  396. package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
  397. package/src/scripts/check_no_external_sources.ts +281 -6
  398. package/src/scripts/check_pack_conformance_fixture.ts +11 -1
  399. package/src/scripts/check_pack_size.ts +59 -2
  400. package/src/scripts/check_preamble_payload_budget.ts +114 -3
  401. package/src/scripts/check_prefix_stable_mutation.ts +372 -0
  402. package/src/scripts/check_publish_surface.ts +10 -1
  403. package/src/scripts/check_references.ts +24 -1
  404. package/src/scripts/check_release_highlights.ts +96 -13
  405. package/src/scripts/check_roadmap_trackable.ts +17 -2
  406. package/src/scripts/check_rule_evidence_declaration.ts +316 -0
  407. package/src/scripts/check_rule_projection_integrity.ts +14 -4
  408. package/src/scripts/check_score_contract.ts +26 -3
  409. package/src/scripts/check_static_parity.ts +285 -0
  410. package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
  411. package/src/scripts/check_suppression_hygiene.ts +15 -0
  412. package/src/scripts/ci_settle.ts +39 -2
  413. package/src/scripts/code_graph/build.ts +60 -3
  414. package/src/scripts/code_graph/extract.ts +44 -0
  415. package/src/scripts/code_graph/types.ts +24 -0
  416. package/src/scripts/collector_daemon.ts +714 -0
  417. package/src/scripts/config_cost_report.ts +302 -0
  418. package/src/scripts/consumer_matrix.ts +74 -1
  419. package/src/scripts/corpus_manifest.ts +235 -0
  420. package/src/scripts/cost/budget.mjs +10 -3
  421. package/src/scripts/cost/track.mjs +10 -3
  422. package/src/scripts/council_cli.ts +37 -54
  423. package/src/scripts/dispatch_r2_reviewer.ts +46 -5
  424. package/src/scripts/evolution_lab.ts +1153 -0
  425. package/src/scripts/external_sources_denylist.json +5 -18
  426. package/src/scripts/extract_audit_patterns.ts +21 -0
  427. package/src/scripts/fold_intake.ts +12 -1
  428. package/src/scripts/gen_discovery_baseline.ts +1 -1
  429. package/src/scripts/generate_capabilities_index.ts +12 -5
  430. package/src/scripts/generate_capability_matrix.ts +3 -3
  431. package/src/scripts/generate_command_flows.ts +2 -2
  432. package/src/scripts/generate_cookbook.ts +2 -2
  433. package/src/scripts/generate_index.ts +8 -1
  434. package/src/scripts/generate_knowledge_index.ts +2 -1
  435. package/src/scripts/generate_ownership_matrix.ts +2 -1
  436. package/src/scripts/generate_pack_manifests.ts +10 -2
  437. package/src/scripts/generate_role_experiences_catalog.ts +2 -2
  438. package/src/scripts/generate_settings_reference.ts +1 -1
  439. package/src/scripts/git_authorization_hook.ts +22 -1
  440. package/src/scripts/grade_target_readiness.ts +48 -5
  441. package/src/scripts/hook_effect_doctor.ts +261 -0
  442. package/src/scripts/hook_manifest.json +1 -1
  443. package/src/scripts/hook_manifest.yaml +125 -16
  444. package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
  445. package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
  446. package/src/scripts/hooks/comment_discipline_hook.ts +146 -0
  447. package/src/scripts/hooks/concern_registry.ts +6 -0
  448. package/src/scripts/hooks/dispatch_hook.ts +32 -0
  449. package/src/scripts/hooks/journal_record_hook.ts +345 -0
  450. package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
  451. package/src/scripts/hooks/run_continuation_hook.ts +44 -9
  452. package/src/scripts/hooks/shims/install.sh +61 -0
  453. package/src/scripts/hooks/shims/php +101 -0
  454. package/src/scripts/hooks/suggestion_capture_hook.ts +10 -0
  455. package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
  456. package/src/scripts/hot_context_hook.ts +16 -0
  457. package/src/scripts/install-hooks.sh +20 -5
  458. package/src/scripts/install.ts +17 -35
  459. package/src/scripts/inventory_frontmatter.ts +2 -1
  460. package/src/scripts/language_mirror_hook.ts +14 -2
  461. package/src/scripts/lint_adr_sweep_routing.ts +12 -0
  462. package/src/scripts/lint_canonical_terms.ts +604 -0
  463. package/src/scripts/lint_carrier_integrity.ts +820 -0
  464. package/src/scripts/lint_code_comments.ts +643 -0
  465. package/src/scripts/lint_composition_review.ts +619 -0
  466. package/src/scripts/lint_consolidation_lineage.ts +666 -0
  467. package/src/scripts/lint_eval_specs.ts +593 -0
  468. package/src/scripts/lint_hook_manifest.ts +19 -0
  469. package/src/scripts/lint_host_portability.ts +373 -0
  470. package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
  471. package/src/scripts/lint_memory_twin_parity.ts +335 -0
  472. package/src/scripts/lint_metric_consumers.ts +355 -0
  473. package/src/scripts/lint_plan_risk_register.ts +39 -19
  474. package/src/scripts/lint_promotion_paths.ts +779 -0
  475. package/src/scripts/lint_skill_descriptions.ts +18 -1
  476. package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
  477. package/src/scripts/lint_skill_link_reach.ts +252 -0
  478. package/src/scripts/lint_skill_trigger_corpus.ts +426 -23
  479. package/src/scripts/lint_ticket_buildable.ts +17 -1
  480. package/src/scripts/llm_propose.ts +256 -0
  481. package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
  482. package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
  483. package/src/scripts/measure_delivery_sets.ts +361 -0
  484. package/src/scripts/measure_docs_dead_links.ts +348 -0
  485. package/src/scripts/measure_host_capture.ts +461 -0
  486. package/src/scripts/measure_routing_signal.ts +307 -0
  487. package/src/scripts/migration_status.ts +3 -3
  488. package/src/scripts/model_rule_injection.ts +76 -0
  489. package/src/scripts/orchestration_record.ts +14 -0
  490. package/src/scripts/preamble_byte_census.ts +139 -10
  491. package/src/scripts/prepack-check.mjs +4 -1
  492. package/src/scripts/probe_council_retention.ts +495 -0
  493. package/src/scripts/probe_turnaround.ts +384 -0
  494. package/src/scripts/probe_unblocked_ask.ts +279 -0
  495. package/src/scripts/release.ts +21 -37
  496. package/src/scripts/release_drill.ts +143 -0
  497. package/src/scripts/release_env.ts +35 -0
  498. package/src/scripts/release_publication.ts +84 -0
  499. package/src/scripts/render_benchmark_md.ts +1 -1
  500. package/src/scripts/rule_activation_census.ts +70 -9
  501. package/src/scripts/rule_backlinks.ts +1 -1
  502. package/src/scripts/run_lifecycle_suite.ts +208 -0
  503. package/src/scripts/run_skill_evals.ts +40 -0
  504. package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
  505. package/src/scripts/schemas/drafting-channels.schema.json +43 -0
  506. package/src/scripts/schemas/evals.schema.json +24 -1
  507. package/src/scripts/schemas/rule.schema.json +52 -1
  508. package/src/scripts/schemas/skill.schema.json +17 -2
  509. package/src/scripts/skill_overlap.ts +7 -1
  510. package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
  511. package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
  512. package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
  513. package/src/scripts/skill_usage_report.ts +2 -1
  514. package/src/scripts/stubs_due.ts +211 -0
  515. package/src/scripts/sweep_source_surfaces.ts +678 -0
  516. package/src/scripts/sync_pr_branch.ts +3 -3
  517. package/src/scripts/trigger_eval_grandfather.json +202 -222
  518. package/src/scripts/utilization_report.ts +22 -2
  519. package/src/server/schemas/settings.ts +5 -0
  520. package/src/templates/marketing-copy.yml +1 -1
  521. package/dist/ui/assets/index-Cxgy63kz.js +0 -26
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * No cost surface built by `road-to-delivered-cost-truth` prints a currency
4
+ * figure or a per-token rate (AC-7).
5
+ *
6
+ * WHY THIS IS A GATE AND NOT A CONVENTION
7
+ * ---------------------------------------
8
+ * The suite does not know a consumer's contract — subscription, per-token,
9
+ * committed spend, a reseller rate — so any monetary figure it printed would be
10
+ * extrapolated from a rate it invented. That is worse than no number, because it
11
+ * is actionable and wrong, and it is exactly the kind of thing that gets added
12
+ * back later by someone who reasonably thinks a cost report should show cost.
13
+ *
14
+ * SCOPE IS A NAMED LIST, NOT A PATTERN. The gate guards the surfaces this
15
+ * roadmap built, and nothing else: `cache_realization_report` legitimately
16
+ * carries a `cost_usd` block for back-compat with downstream consumers, and a
17
+ * gate that swept `src/scripts/*cost*` would fail on it and be neutered with an
18
+ * allowlist within a release.
19
+ *
20
+ * Exit codes: 0 clean · 1 a currency marker on a guarded surface · 2 misuse.
21
+ *
22
+ * Usage:
23
+ * ./scripts-run src/scripts/check_no_currency_in_cost_surfaces [--root <dir>] [--quiet]
24
+ * ./scripts-run src/scripts/check_no_currency_in_cost_surfaces --self-test
25
+ */
26
+ import * as fs from 'node:fs';
27
+ import * as os from 'node:os';
28
+ import * as path from 'node:path';
29
+
30
+ import { CURRENCY_MARKERS } from './_lib/config_cost.js';
31
+ import { GateLedger } from './_lib/gate_ledger.js';
32
+ import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
33
+ import { assertWatchlistResolves, DeadScopeError, reportScanned } from './_lib/scan_scope.js';
34
+
35
+ const HERE = path.dirname(new URL(import.meta.url).pathname);
36
+ const REPO_ROOT = path.resolve(HERE, '..', '..');
37
+
38
+ /** The surfaces this roadmap built. A named list, deliberately. */
39
+ export const GUARDED_SURFACES: readonly string[] = [
40
+ 'src/scripts/config_cost_report.ts',
41
+ 'src/scripts/asset_delivery_ledger.ts',
42
+ 'src/scripts/_lib/config_cost.ts',
43
+ 'src/scripts/_lib/asset_delivery_ledger.ts',
44
+ ];
45
+
46
+ /**
47
+ * Lines that may name a marker without printing one.
48
+ *
49
+ * A gate over currency SYMBOLS cannot read intent, and every guarded file has to
50
+ * be able to explain the ban — including `CURRENCY_MARKERS` itself, which is a
51
+ * list of the very strings being banned. Comments and the marker declaration are
52
+ * therefore out of scope, and the discriminator is whether the string can reach
53
+ * a rendered line.
54
+ */
55
+ function isExempt(line: string): boolean {
56
+ const t = line.trim();
57
+ return t.startsWith('*') || t.startsWith('//') || t.startsWith('/*') || t.includes('CURRENCY_MARKERS');
58
+ }
59
+
60
+ /**
61
+ * Source-level patterns, derived from {@link CURRENCY_MARKERS} with ONE
62
+ * exception that the self-test found and that matters more than it looks.
63
+ *
64
+ * A bare `$` substring matches TEMPLATE-LITERAL INTERPOLATION — `${value}` — so
65
+ * the first cut of this gate flagged every interpolated line in every guarded
66
+ * file, including its own ledger renderer. A gate whose first real run produces
67
+ * dozens of false positives gets an allowlist within a release, and then it
68
+ * guards nothing.
69
+ *
70
+ * Excluding `${` alone was not enough — a REGEX ANCHOR is also a bare `$`, and
71
+ * the second run flagged `/\.md$/`. Both false positives share a shape: `$`
72
+ * appears constantly in TypeScript for reasons that have nothing to do with
73
+ * money.
74
+ *
75
+ * So the pattern is positive rather than subtractive: a currency `$` is followed
76
+ * by a DIGIT (`$42`) or by an interpolated amount (`$${n}`). Anchors, plain
77
+ * interpolation and `$` inside identifiers all fall outside it. Both directions
78
+ * are pinned by self-test cases — a rejecting `$${n}` and an accepting anchor —
79
+ * because a positive pattern that is too narrow fails silently.
80
+ *
81
+ * The companion `isCurrencyFree` keeps plain substring matching, correctly: it
82
+ * reads RENDERED output, where no template or regex syntax survives and a `$` is
83
+ * a dollar sign.
84
+ */
85
+ export const SOURCE_PATTERNS: ReadonlyArray<{ marker: string; re: RegExp }> = CURRENCY_MARKERS.map((m) => ({
86
+ marker: m,
87
+ re: m === '$' ? /\$(?=\d|\$\{)/ : new RegExp(m.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')),
88
+ }));
89
+
90
+ export interface Finding {
91
+ file: string;
92
+ line: number;
93
+ marker: string;
94
+ text: string;
95
+ }
96
+
97
+ export function scanFile(source: string, rel: string): Finding[] {
98
+ const out: Finding[] = [];
99
+ source.split('\n').forEach((line, i) => {
100
+ if (isExempt(line)) return;
101
+ for (const p of SOURCE_PATTERNS) {
102
+ if (p.re.test(line)) out.push({ file: rel, line: i + 1, marker: p.marker, text: line.trim().slice(0, 100) });
103
+ }
104
+ });
105
+ return out;
106
+ }
107
+
108
+ export function evaluate(root: string = REPO_ROOT, ledger?: GateLedger): { scanned: number; findings: Finding[] } {
109
+ const findings: Finding[] = [];
110
+ let scanned = 0;
111
+ ledger?.plan(GUARDED_SURFACES);
112
+ for (const rel of GUARDED_SURFACES) {
113
+ const abs = path.join(root, rel);
114
+ if (!fs.existsSync(abs)) {
115
+ ledger?.skip(rel, 'no_applicable_files');
116
+ continue;
117
+ }
118
+ scanned += 1;
119
+ const hits = scanFile(fs.readFileSync(abs, 'utf-8'), rel);
120
+ findings.push(...hits);
121
+ if (hits.length > 0) ledger?.fail(rel, `${String(hits.length)} currency marker(s)`);
122
+ else ledger?.complete(rel);
123
+ }
124
+ return { scanned, findings };
125
+ }
126
+
127
+ // ---------------------------------------------------------------- self-test
128
+
129
+ function selfTestCases(): SelfTestCase[] {
130
+ const mk = (name: string, expect: 'reject' | 'accept', body: string): SelfTestCase => ({
131
+ name,
132
+ expect,
133
+ run: () => {
134
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'cur-'));
135
+ try {
136
+ fs.mkdirSync(path.join(dir, 'src', 'scripts', '_lib'), { recursive: true });
137
+ for (const rel of GUARDED_SURFACES) fs.writeFileSync(path.join(dir, rel), body);
138
+ return runGateCli(REPO_ROOT, 'src/scripts/check_no_currency_in_cost_surfaces.ts', ['--root', dir, '--quiet'], REPO_ROOT);
139
+ } finally {
140
+ fs.rmSync(dir, { recursive: true, force: true });
141
+ }
142
+ },
143
+ });
144
+ return [
145
+ mk('a dollar figure in rendered output → reject', 'reject', `out.push(\`cost: $\${n}\`);\n`),
146
+ mk('a euro figure → reject', 'reject', `out.push(\`Kosten: €\${n}\`);\n`),
147
+ mk('a per-token rate → reject', 'reject', `out.push('rate: 3.00 per token');\n`),
148
+ mk('a USD label → reject', 'reject', `out.push('total USD');\n`),
149
+ mk('tokens only → accept', 'accept', `out.push(\`\${n} tok\`);\n`),
150
+ // Both false positives the first two runs produced, pinned so a future
151
+ // widening of the pattern cannot reintroduce them silently.
152
+ mk('a regex end anchor is not a dollar sign → accept', 'accept', `const x = /\\.md$/.test(name);\n`),
153
+ mk('plain interpolation is not a dollar sign → accept', 'accept', 'out.push(`${a} of ${b}`);\n'),
154
+ mk('a comment explaining the ban → accept', 'accept', `// never print $ or EUR here\nout.push('tok');\n`),
155
+ mk('the marker declaration itself → accept', 'accept', `export const CURRENCY_MARKERS = ['$', 'EUR'] as const;\n`),
156
+ ];
157
+ }
158
+
159
+ // ---------------------------------------------------------------------- CLI
160
+
161
+ export function main(argv: string[] = process.argv.slice(2)): number {
162
+ if (argv.includes('--self-test')) {
163
+ return runSelfTest({ gate: 'check_no_currency_in_cost_surfaces', cases: selfTestCases(), minCases: 8, minRejectCases: 4 });
164
+ }
165
+ const quiet = argv.includes('--quiet');
166
+ const ri = argv.indexOf('--root');
167
+ const rootArg = ri !== -1 ? argv[ri + 1] : undefined;
168
+ const root = rootArg !== undefined ? path.resolve(rootArg) : REPO_ROOT;
169
+
170
+ const ledger = new GateLedger('check_no_currency_in_cost_surfaces');
171
+ let v: { scanned: number; findings: Finding[] };
172
+ try {
173
+ v = evaluate(root, ledger);
174
+ } catch (err) {
175
+ process.stderr.write(`❌ check_no_currency_in_cost_surfaces: ${(err as Error).message}\n`);
176
+ return 2;
177
+ }
178
+
179
+ try {
180
+ // Watchlist-driven: the corpus is a named list of files, not a tree walk,
181
+ // so an empty scan means the watchlist stopped resolving — which is a
182
+ // dead scope, not a clean run.
183
+ assertWatchlistResolves({
184
+ gate: 'check_no_currency_in_cost_surfaces',
185
+ candidates: GUARDED_SURFACES,
186
+ repoRoot: root,
187
+ });
188
+ reportScanned({
189
+ gate: 'check_no_currency_in_cost_surfaces',
190
+ scanned: v.scanned,
191
+ units: 'guarded cost surface(s)',
192
+ roots: GUARDED_SURFACES,
193
+ allowEmpty: 'WATCHLIST_DRIVEN: the corpus is the named surface list above, asserted by assertWatchlistResolves',
194
+ });
195
+ } catch (err) {
196
+ if (err instanceof DeadScopeError) {
197
+ process.stderr.write(`❌ check_no_currency_in_cost_surfaces: ${err.message}\n`);
198
+ return 2;
199
+ }
200
+ throw err;
201
+ }
202
+ ledger.report();
203
+
204
+ if (v.findings.length > 0) {
205
+ for (const f of v.findings) {
206
+ process.stderr.write(`❌ ${f.file}:${String(f.line)} renders '${f.marker}':\n ${f.text}\n`);
207
+ }
208
+ process.stderr.write(
209
+ '\n A cost surface here reports TOKENS. The suite does not know the consumer\'s\n' +
210
+ ' contract, so a monetary figure would be extrapolated from a rate it invented —\n' +
211
+ ' actionable and wrong, which is worse than absent.\n',
212
+ );
213
+ return 1;
214
+ }
215
+ if (!quiet) {
216
+ process.stdout.write(`✅ no currency figure or per-token rate on any cost surface (${String(v.scanned)} file(s)).\n`);
217
+ }
218
+ return 0;
219
+ }
220
+
221
+ if (process.env['GATE_SELF_TEST_CHILD'] !== '1' || process.argv.includes('--root')) {
222
+ if (process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`) {
223
+ process.exit(main());
224
+ }
225
+ }
@@ -23,11 +23,39 @@
23
23
  * - A retained source link must be stored encrypted via
24
24
  * src/scripts/_lib/link_crypto.ts, never in plaintext.
25
25
  *
26
+ * ## What `road-to-source-silence` added (Phase 3.1, 3.2, 3.3, and dormant 1.1)
27
+ *
28
+ * The name-list scan above is unchanged and still authoritative. Three surfaces
29
+ * were added around it, because a list can only catch a name somebody already
30
+ * wrote down:
31
+ *
32
+ * - **3.1 — paths are scanned like content.** A denied token in a FILENAME or
33
+ * directory name failed nothing before; `rel` reached the extension skip-list
34
+ * and the hit record and nothing else. It is now matched against the same
35
+ * deny set, and a hit blocks exactly like a content line. Measured at
36
+ * introduction: 0 hits, so this lands enforcing rather than baselined.
37
+ * - **3.2 — an attribution-SHAPE heuristic** (`_lib/source_shape.ts`), which is
38
+ * independent of any name list. Tiered per the resolved
39
+ * `how-loud-the-slug-heuristic-is` blocker: **block inside `agents/**`, warn
40
+ * elsewhere.** The warn tier is written to a machine-readable report
41
+ * (`--report`) rather than only printed, which is the council's own
42
+ * requirement — "warnings must be visible and RETAINED in CI artifacts …
43
+ * so the warn tier is auditable after the fact".
44
+ * - **3.3 — both new classes are ratcheted**, not allowlisted. Pre-existing
45
+ * shape debt is a committed count in `src/config/gate-violation-baselines.json`
46
+ * that may only shrink; a new occurrence raises the count and fails the gate.
47
+ * No individual violation is named or excused.
48
+ * - **1.1 — keyed-digest matching, DORMANT.** `deny_digests` ships empty and
49
+ * this code path does nothing until a maintainer performs the atomic cutover
50
+ * in `docs/maintainers/source-deny-digests.md`. The plaintext `deny` array
51
+ * stays in force and is NOT deleted.
52
+ *
26
53
  * Exit codes: 0 = clean, 1 = at least one denied token in a non-skipped tracked
27
- * file, 2 = usage / config error.
54
+ * file (or a shape-count regression), 2 = usage / config error, 3 = strict
55
+ * digest mode requested with no key (`_lib/source_digest.ts`).
28
56
  *
29
57
  * Usage:
30
- * node scripts/check_no_external_sources.ts [--json]
58
+ * node scripts/check_no_external_sources.ts [--json] [--report <path>]
31
59
  */
32
60
 
33
61
  import { spawnSync } from 'node:child_process';
@@ -36,7 +64,23 @@ import * as path from 'node:path';
36
64
  import process from 'node:process';
37
65
  import { fileURLToPath, pathToFileURL } from 'node:url';
38
66
 
67
+ import { checkRatchet } from './_lib/gate_baseline.js';
39
68
  import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
69
+ import { DigestMatcher, digestMode, EXIT_NO_KEY, KEY_ENV, STRICT_ENV } from './_lib/source_digest.js';
70
+ import {
71
+ legacySourceHeaderHits,
72
+ shapeHits as shapeHitsOf,
73
+ shapePathHits,
74
+ tierFor,
75
+ type ShapeClass,
76
+ } from './_lib/source_shape.js';
77
+ import {
78
+ dedupVerdict,
79
+ findingKey,
80
+ hunkTargets,
81
+ isSnapshotPatch,
82
+ isSnapshotPath,
83
+ } from './_lib/source_snapshot_dedup.js';
40
84
 
41
85
  const _HERE = fileURLToPath(import.meta.url);
42
86
  // parents[2] of src/scripts/<file> is the repo root.
@@ -52,17 +96,33 @@ const _SKIP_EXT = new Set([
52
96
 
53
97
  interface DenyConfig {
54
98
  deny: string[];
99
+ /** Phase 1.1 — HMAC-SHA256 digests of the deny set. Ships EMPTY (dormant). */
100
+ deny_digests?: string[];
55
101
  skip_paths?: string[];
56
102
  [k: string]: unknown;
57
103
  }
58
104
 
59
105
  interface Hit {
60
106
  file: string;
107
+ /** 0 for a PATH hit — there is no line to point at. */
61
108
  line: number;
62
109
  token: string;
63
110
  text: string;
64
111
  }
65
112
 
113
+ /** One attribution-shape finding (Phase 3.2). */
114
+ interface ShapeFinding {
115
+ file: string;
116
+ line: number;
117
+ cls: ShapeClass;
118
+ tier: 'block' | 'warn';
119
+ /** The offending value, truncated. Written to the report, never to stdout. */
120
+ value: string;
121
+ }
122
+
123
+ /** Baseline key for the block-tier shape count (Phase 3.3). */
124
+ export const SHAPE_GATE_KEY = 'check_no_external_sources:shape-block';
125
+
66
126
  /** Thrown to mirror Python `raise SystemExit(msg)` (exit code derived by caller). */
67
127
  class ExitError extends Error {}
68
128
 
@@ -297,12 +357,42 @@ function main(argv: readonly string[]): number {
297
357
  throw exc;
298
358
  }
299
359
 
360
+ // Phase 1.1 — dormant unless a maintainer has performed the atomic cutover.
361
+ const digests = cfg.deny_digests ?? [];
362
+ const strict = (process.env[STRICT_ENV] ?? '') !== '';
363
+ const mode = digestMode({ digests, key: process.env[KEY_ENV], strict });
364
+ if (mode.strict && !mode.active) {
365
+ process.stderr.write(`❌ ${mode.message}\n`);
366
+ return EXIT_NO_KEY;
367
+ }
368
+ if (mode.message !== '') {
369
+ process.stderr.write(`${mode.message}\n`);
370
+ }
371
+ const matcher = mode.active ? new DigestMatcher(digests, process.env[KEY_ENV] as string) : null;
372
+
300
373
  const hits: Hit[] = [];
374
+ const shapes: ShapeFinding[] = [];
375
+ /** Pre-narrowing `source-header` count. Reported, never enforced. */
376
+ let legacyHeaderShadow = 0;
301
377
  for (const rel of tracked) {
302
- if (_SKIP_EXT.has(_suffixLower(rel))) {
378
+ if (_skipped(rel, skipGlobs)) {
303
379
  continue;
304
380
  }
305
- if (_skipped(rel, skipGlobs)) {
381
+ // --- Phase 3.1: the PATH is scanned exactly like a content line. -----
382
+ for (const [raw, rx] of patterns) {
383
+ if (rx.test(rel)) {
384
+ hits.push({ file: rel, line: 0, token: raw, text: `(path) ${rel}`.slice(0, 160) });
385
+ }
386
+ }
387
+ if (matcher) {
388
+ for (const tok of matcher.hits(rel)) {
389
+ hits.push({ file: rel, line: 0, token: `digest:${tok}`, text: `(path) ${rel}`.slice(0, 160) });
390
+ }
391
+ }
392
+ for (const h of shapePathHits(rel)) {
393
+ shapes.push({ file: rel, line: 0, cls: h.cls, tier: tierFor(rel), value: h.value });
394
+ }
395
+ if (_SKIP_EXT.has(_suffixLower(rel))) {
306
396
  continue;
307
397
  }
308
398
  let text: string;
@@ -317,6 +407,7 @@ function main(argv: readonly string[]): number {
317
407
  continue;
318
408
  }
319
409
  const lines = _splitlines(text);
410
+ const tier = tierFor(rel);
320
411
  for (let idx = 0; idx < lines.length; idx += 1) {
321
412
  const line = lines[idx] as string;
322
413
  for (const [raw, rx] of patterns) {
@@ -329,11 +420,160 @@ function main(argv: readonly string[]): number {
329
420
  });
330
421
  }
331
422
  }
423
+ if (matcher) {
424
+ for (const tok of matcher.hits(line)) {
425
+ hits.push({
426
+ file: rel,
427
+ line: idx + 1,
428
+ token: `digest:${tok}`,
429
+ text: _pyStrip(line).slice(0, 160),
430
+ });
431
+ }
432
+ }
433
+ for (const h of shapeHitsOf(line)) {
434
+ shapes.push({ file: rel, line: idx + 1, cls: h.cls, tier, value: h.value });
435
+ }
436
+ // SHADOW METRIC, gating nothing. A council condition of the
437
+ // 2026-08-30 narrowing: "keep the old detector shadow-reporting
438
+ // until at least one subsequent corpus-changing release passes both
439
+ // detectors". It exists so the discontinuity from 243 to 148 stays
440
+ // visible and auditable rather than becoming a number nobody can
441
+ // reconstruct.
442
+ if (tier === 'block') {
443
+ legacyHeaderShadow += legacySourceHeaderHits(line).length;
444
+ }
332
445
  }
333
446
  }
334
447
 
448
+ // --- Phase 3.2 + 3.3: tier the shape findings and ratchet the block tier.
449
+ const blockShapesAll = shapes.filter((s2) => s2.tier === 'block');
450
+ const warnShapes = shapes.filter((s2) => s2.tier === 'warn');
451
+
452
+ // --- Phase 3.4: provenance-aware deduplication of R2 snapshot mirrors. ----
453
+ // A finding inside a review-input snapshot is excluded from the ratchet ONLY
454
+ // when an identical class+value is independently block-counted in the
455
+ // current tracked tree. Earned per finding; fails closed. The refused
456
+ // alternative (lower the tier for the whole snapshot corpus) and the two
457
+ // legs are documented in `_lib/source_snapshot_dedup.ts`.
458
+ const trackedPaths = new Set(tracked);
459
+ const blockIndex = new Map<string, Set<string>>();
460
+ for (const s2 of blockShapesAll) {
461
+ if (isSnapshotPath(s2.file)) {
462
+ continue;
463
+ }
464
+ const k = findingKey(s2.cls, s2.value);
465
+ let set = blockIndex.get(k);
466
+ if (!set) {
467
+ set = new Set();
468
+ blockIndex.set(k, set);
469
+ }
470
+ set.add(s2.file);
471
+ }
472
+ const targets = new Map<string, ReadonlyMap<number, string>>();
473
+ for (const rel of tracked) {
474
+ if (!isSnapshotPatch(rel)) {
475
+ continue;
476
+ }
477
+ try {
478
+ targets.set(rel, hunkTargets(fs.readFileSync(path.join(ROOT, rel), 'utf-8')));
479
+ } catch {
480
+ // Unreadable patch — no hunk targets, so no finding in it can take
481
+ // Leg 1. It does NOT follow that they fail closed: Leg 2 still
482
+ // excludes a finding whose value is block-counted elsewhere in the
483
+ // scanned tree. Corrected after the R2 review of this branch, which
484
+ // caught this comment claiming a guarantee the code does not give.
485
+ }
486
+ }
487
+ const dedupInput = { blockIndex, targets, trackedPaths };
488
+ const blockShapes: ShapeFinding[] = [];
489
+ const excluded: Array<ShapeFinding & { leg: string; matched: string }> = [];
490
+ for (const s2 of blockShapesAll) {
491
+ const v = isSnapshotPath(s2.file)
492
+ ? dedupVerdict({ file: s2.file, line: s2.line, cls: s2.cls, value: s2.value }, dedupInput)
493
+ : { excluded: false, leg: null, matchedPath: null, reason: 'not a snapshot finding' };
494
+ if (v.excluded) {
495
+ excluded.push({ ...s2, leg: v.leg ?? '?', matched: v.matchedPath ?? '' });
496
+ } else {
497
+ blockShapes.push(s2);
498
+ }
499
+ }
500
+ const dedupByLeg = {
501
+ hunk: excluded.filter((e) => e.leg === 'hunk').length,
502
+ tree: excluded.filter((e) => e.leg === 'tree').length,
503
+ };
504
+
505
+ const verdict = checkRatchet({ repoRoot: ROOT, gate: SHAPE_GATE_KEY, actual: blockShapes.length });
506
+
507
+ // The council's retention requirement: the warn tier is written where CI can
508
+ // keep it, not merely printed into a log that scrolls away.
509
+ const ri = argv.indexOf('--report');
510
+ if (ri >= 0 && argv[ri + 1] !== undefined) {
511
+ const out = path.resolve(ROOT, argv[ri + 1] as string);
512
+ fs.mkdirSync(path.dirname(out), { recursive: true });
513
+ fs.writeFileSync(
514
+ out,
515
+ _jsonDumps2({
516
+ deny_hits: hits.length,
517
+ digest_mode: { active: mode.active, digests: mode.digests, key_missing: mode.keyMissing },
518
+ shape: {
519
+ block: blockShapes.length,
520
+ warn: warnShapes.length,
521
+ baseline: verdict.baseline,
522
+ status: verdict.status,
523
+ // The council's shadow-metric condition, in the ARTEFACT
524
+ // rather than only on stdout (R2 finding 8): "keep the old
525
+ // detector shadow-reporting until at least one subsequent
526
+ // corpus-changing release passes both detectors" cannot be
527
+ // checked across releases by anything that is not written
528
+ // down. `pre_dedup` says why the two numbers differ, so a
529
+ // reader can reconstruct the comparison instead of being
530
+ // told it holds.
531
+ legacy_source_header: {
532
+ count: legacyHeaderShadow,
533
+ pre_dedup: true,
534
+ note: 'pre-2026-08-30 predicate; enforces nothing; not comparable to the audited delta, which was measured after snapshot deduplication',
535
+ },
536
+ },
537
+ // Phase 3.4 — every exclusion names its leg and the tracked
538
+ // file whose independent block-count justified it, so the
539
+ // weaker `tree` leg is auditable after the fact rather than
540
+ // invisible. The council required exactly this.
541
+ snapshot_dedup: {
542
+ excluded: excluded.length,
543
+ by_leg: dedupByLeg,
544
+ exclusions: excluded,
545
+ },
546
+ block_findings: blockShapes,
547
+ warn_findings: warnShapes,
548
+ }) + '\n',
549
+ 'utf-8',
550
+ );
551
+ }
552
+
553
+ const ok = hits.length === 0 && verdict.ok;
554
+
335
555
  if (asJson) {
336
- process.stdout.write(_jsonDumps2({ ok: hits.length === 0, hits }) + '\n');
556
+ // `ok` and `hits` keep their pinned meaning for the name-list scan; the
557
+ // shape block is additive so an existing consumer is unaffected.
558
+ process.stdout.write(
559
+ _jsonDumps2({
560
+ ok,
561
+ hits,
562
+ shape: {
563
+ block: blockShapes.length,
564
+ warn: warnShapes.length,
565
+ baseline: verdict.baseline,
566
+ status: verdict.status,
567
+ ok: verdict.ok,
568
+ snapshot_dedup: { excluded: excluded.length, by_leg: dedupByLeg },
569
+ legacy_source_header: {
570
+ count: legacyHeaderShadow,
571
+ pre_dedup: true,
572
+ note: 'pre-2026-08-30 predicate; enforces nothing; not comparable to the audited delta, which was measured after snapshot deduplication',
573
+ },
574
+ },
575
+ }) + '\n',
576
+ );
337
577
  } else {
338
578
  if (hits.length > 0) {
339
579
  process.stdout.write(`❌ ${hits.length} external-source reference(s) in the tracked tree:\n\n`);
@@ -350,8 +590,43 @@ function main(argv: readonly string[]): number {
350
590
  } else {
351
591
  process.stdout.write('✅ No external inspiration-source references in the tracked tree.\n');
352
592
  }
593
+ // The shape tier reports on every run — a count that is only printed
594
+ // when it fails is a count nobody watches shrink.
595
+ process.stdout.write(
596
+ `\nattribution shape — block(agents/**) ${String(blockShapes.length)}` +
597
+ ` / baseline ${String(verdict.baseline)} · warn(elsewhere) ${String(warnShapes.length)}\n`,
598
+ );
599
+ process.stdout.write(
600
+ `legacy source-header shadow — ${String(legacyHeaderShadow)} raw finding(s) under the` +
601
+ ` PRE-2026-08-30 predicate. Reported, enforces nothing, and NOT` +
602
+ ` comparable to the 95 audited: this count is pre-dedup, while the` +
603
+ ` audited delta was measured after snapshot deduplication. See the` +
604
+ ` check_no_external_sources:shape-block baseline note.\n`,
605
+ );
606
+ if (excluded.length > 0) {
607
+ process.stdout.write(
608
+ `snapshot dedup — ${String(excluded.length)} review-snapshot finding(s) excluded` +
609
+ ` (hunk-target ${String(dedupByLeg.hunk)} · tracked-tree ${String(dedupByLeg.tree)});` +
610
+ ' each matched an identical class+value block-counted in a scanned file.' +
611
+ ' Per-exclusion legs and matched paths: --report <path>.\n',
612
+ );
613
+ }
614
+ process.stdout.write(`${verdict.ok ? '✅' : '❌'} ${verdict.message}\n`);
615
+ if (!verdict.ok) {
616
+ process.stdout.write(
617
+ '\nThe shape heuristic flags attribution by FORM, not by name: a speaking\n' +
618
+ '`**Source:**` value, a quoted agents/tmp(.old)/<name>/ directory, or an\n' +
619
+ 'un-allowlisted github.com/<owner>/<repo> URL. Rewrite the reference to an\n' +
620
+ 'opaque round identifier or an ENC1: token (src/scripts/_lib/link_crypto.ts).\n' +
621
+ 'Run with --report <path> for the per-finding list. See rule:\n' +
622
+ 'source-confidentiality and roadmap road-to-source-silence Phase 3.\n',
623
+ );
624
+ }
353
625
  }
354
- return hits.length > 0 ? 1 : 0;
626
+ // No second `scanned:` line: `assertScanned` above already emits it, and this
627
+ // copy landed AFTER the --json payload, which made the pinned JSON output
628
+ // unparseable. Caught by the CLI-contract test, not by inspection.
629
+ return ok ? 0 : 1;
355
630
  }
356
631
 
357
632
  function _isCliEntry(): boolean {
@@ -374,7 +374,17 @@ export function renderDoc(): string {
374
374
  const proven = GATES.filter((g) => g.mechanism !== 'real-tree-only');
375
375
  const blocked = GATES.filter((g) => g.mechanism === 'real-tree-only');
376
376
  const L: string[] = [];
377
- L.push('<!-- GENERATED by src/scripts/check_pack_conformance_fixture.ts --emit-doc — DO NOT EDIT BY HAND -->');
377
+ // `stability:` frontmatter is MANDATORY for every file under docs/contracts/
378
+ // (STABILITY.md § Frontmatter requirement), and check_public_links reads it.
379
+ // It is emitted here rather than hand-added to the page, because the page is
380
+ // derived — a hand-added block is reverted by the next `--emit-doc` and
381
+ // reds this gate's own freshness check in the meantime.
382
+ L.push('---');
383
+ L.push('stability: beta');
384
+ L.push('keep-beta-until: 2026-11-24');
385
+ L.push('---');
386
+ L.push('');
387
+ L.push('<!-- GENERATED by check_pack_conformance_fixture --emit-doc — DO NOT EDIT BY HAND -->');
378
388
  L.push('');
379
389
  L.push(`# Pack conformance — partial: ${String(proven.length)} of ${String(GATES.length)} gates independently fixture-proven`);
380
390
  L.push('');