@event4u/agent-config 14.10.0 → 14.12.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 (667) 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 +161 -208
  5. package/README.md +1 -1
  6. package/dist/agent-src/commands/design.md +88 -0
  7. package/dist/agent-src/commands/project/analyze.md +47 -0
  8. package/dist/agent-src/commands/review/changes.md +67 -6
  9. package/dist/agent-src/commands/roadmap/create.md +49 -0
  10. package/dist/agent-src/commands/roadmap/next.md +27 -11
  11. package/dist/agent-src/commands/roadmap/process-full.md +14 -0
  12. package/dist/agent-src/commands/video/from-script.md +60 -3
  13. package/dist/agent-src/commands/video/stitch.md +14 -0
  14. package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
  15. package/dist/agent-src/contexts/execution/evidence-discipline.md +26 -0
  16. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  17. package/dist/agent-src/rules/active-remediation.md +3 -3
  18. package/dist/agent-src/rules/code-provenance.md +2 -2
  19. package/dist/agent-src/rules/context-hygiene.md +13 -33
  20. package/dist/agent-src/rules/council-availability.md +2 -2
  21. package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
  22. package/dist/agent-src/rules/design-fidelity.md +18 -0
  23. package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
  24. package/dist/agent-src/rules/evaluator-independence.md +56 -44
  25. package/dist/agent-src/rules/fix-what-you-see.md +9 -1
  26. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
  27. package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
  28. package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
  29. package/dist/agent-src/rules/playbook-precedence.md +105 -0
  30. package/dist/agent-src/rules/recurring-criticism.md +3 -1
  31. package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
  32. package/dist/agent-src/rules/scale-discipline.md +24 -0
  33. package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
  34. package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
  35. package/dist/agent-src/rules/ui-audit-gate.md +27 -15
  36. package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
  37. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  38. package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
  39. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
  40. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
  41. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
  42. package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
  43. package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
  44. package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
  45. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
  46. package/dist/agent-src/skills/brand/SKILL.md +3 -0
  47. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
  48. package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
  49. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
  50. package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
  51. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
  52. package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
  53. package/dist/agent-src/skills/code-refactoring/SKILL.md +45 -1
  54. package/dist/agent-src/skills/code-review/SKILL.md +75 -5
  55. package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
  56. package/dist/agent-src/skills/command-writing/SKILL.md +35 -0
  57. package/dist/agent-src/skills/condense-memory/SKILL.md +3 -0
  58. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +3 -0
  60. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
  61. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
  62. package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
  63. package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
  64. package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
  65. package/dist/agent-src/skills/design-review/SKILL.md +79 -1
  66. package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
  67. package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
  68. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
  69. package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
  70. package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
  71. package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
  72. package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
  73. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +28 -4
  74. package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
  75. package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
  76. package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
  77. package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
  78. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
  79. package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
  80. package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
  81. package/dist/agent-src/skills/iconography/SKILL.md +3 -0
  82. package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
  83. package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
  84. package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
  85. package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
  86. package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
  87. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
  88. package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
  89. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
  90. package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
  91. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
  92. package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
  93. package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
  94. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
  95. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
  96. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -0
  97. package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
  98. package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
  99. package/dist/agent-src/skills/override-management/SKILL.md +3 -0
  100. package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
  101. package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
  102. package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
  103. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
  104. package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
  105. package/dist/agent-src/skills/project-analysis-core/SKILL.md +23 -0
  106. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
  107. package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
  108. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +81 -33
  109. package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
  110. package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
  111. package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
  112. package/dist/agent-src/skills/receiving-code-review/SKILL.md +2 -2
  113. package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
  114. package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
  115. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  116. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  117. package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
  118. package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
  119. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
  120. package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
  121. package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
  122. package/dist/agent-src/skills/secrets-management/SKILL.md +4 -0
  123. package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
  124. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
  125. package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
  126. package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
  127. package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
  128. package/dist/agent-src/skills/skill-writing/references/procedure.md +24 -2
  129. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
  130. package/dist/agent-src/skills/storybook-workshop/SKILL.md +203 -0
  131. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
  132. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  133. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
  134. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
  135. package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
  136. package/dist/agent-src/skills/terraform/SKILL.md +3 -0
  137. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
  138. package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
  139. package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
  140. package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
  141. package/dist/agent-src/skills/ui-component-architect/SKILL.md +17 -1
  142. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
  143. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
  144. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
  145. package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
  146. package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
  147. package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
  148. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  149. package/dist/agent-src/templates/playbook.md +75 -0
  150. package/dist/agent-src/templates/roadmaps.md +37 -0
  151. package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  152. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  153. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  154. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  155. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  156. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  157. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  158. package/dist/cli/commands/uiAudit.js +221 -0
  159. package/dist/cli/commands/uiRender.js +206 -0
  160. package/dist/cli/main.js +22 -1
  161. package/dist/cli/mcp/content.js +64 -1
  162. package/dist/cli/mcp/dispatch.js +175 -10
  163. package/dist/cli/registry.js +3 -0
  164. package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
  165. package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
  166. package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-JCW7ZLHK.js} +10 -0
  167. package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-JJA2QEWA.js} +413 -391
  168. package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
  169. package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
  170. package/dist/cli-delegate/cmd_brand_status.js +8 -6
  171. package/dist/cli-delegate/cmd_conformance.js +3 -3
  172. package/dist/cli-delegate/cmd_doctor.js +3 -3
  173. package/dist/cli-delegate/cmd_export.js +4 -4
  174. package/dist/cli-delegate/cmd_handoff.js +1 -1
  175. package/dist/cli-delegate/cmd_preflight.js +2 -2
  176. package/dist/cli-delegate/cmd_prune.js +4 -4
  177. package/dist/cli-delegate/cmd_session_recycle.js +70 -9
  178. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  179. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  180. package/dist/cli-delegate/cmd_sync.js +4 -4
  181. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  182. package/dist/cli-delegate/cmd_validate.js +4 -4
  183. package/dist/discovery/deprecation-report.md +1 -1
  184. package/dist/discovery/discovery-manifest.json +362 -127
  185. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  186. package/dist/discovery/discovery-manifest.summary.md +4 -4
  187. package/dist/discovery/dormancy-report.md +1 -1
  188. package/dist/discovery/orphan-report.md +1 -1
  189. package/dist/discovery/packs.json +18 -8
  190. package/dist/discovery/trust-report.md +3 -3
  191. package/dist/discovery/workspaces.json +16 -6
  192. package/dist/hooks/dispatch.js +2575 -1472
  193. package/dist/install/install.mjs +800 -708
  194. package/dist/mcp/registry-manifest.json +3 -3
  195. package/dist/mcp/server.json +2 -2
  196. package/dist/mcp/server.mjs +1685 -1250
  197. package/dist/router.json +1 -1
  198. package/dist/scripts/_lib/lean_projection_mode.js +40 -0
  199. package/dist/scripts/_lib/scoped_projection.js +84 -0
  200. package/dist/scripts/_lib/ui_surface.js +89 -0
  201. package/dist/scripts/condense.js +6 -10
  202. package/dist/scripts/project_thin_rules.js +40 -2
  203. package/dist/server/schemas/settings.js +6 -0
  204. package/dist/shared/skillRanking.js +159 -0
  205. package/docs/contracts/provider-lifecycle.md +47 -18
  206. package/docs/contracts/settings-classes.md +35 -5
  207. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
  208. package/docs/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
  209. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  210. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
  211. package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  212. package/docs/guidelines/code-clarity.md +21 -0
  213. package/docs/guidelines/design-antipatterns.md +4 -2
  214. package/docs/guidelines/design-asset-discipline.md +38 -0
  215. package/docs/guidelines/design-fidelity-mechanics.md +45 -29
  216. package/docs/guidelines/design-handover-extraction.md +35 -5
  217. package/docs/guidelines/design-modes.md +41 -1
  218. package/docs/guidelines/monorepo-antipatterns.md +141 -0
  219. package/docs/guidelines/redundancy-taxonomy.md +180 -0
  220. package/llms.txt +50 -39
  221. package/package.json +6 -2
  222. package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  223. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  224. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  225. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  226. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  227. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  228. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  229. package/src/config/agent-settings.template.yml +44 -0
  230. package/src/config/assurance-capability-registry.json +223 -0
  231. package/src/config/assurance-threshold-budget.json +65 -0
  232. package/src/config/budgets.yml +19 -0
  233. package/src/config/ci-local-parity.yml +29 -0
  234. package/src/config/discovery/prompt-patterns.yml +56 -0
  235. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  236. package/src/config/dispatch-economy-metrics.json +4 -2
  237. package/src/config/estate-count-budget.json +8 -3
  238. package/src/config/evaluator-budgets.json +14 -14
  239. package/src/config/gate-coverage.yml +392 -8
  240. package/src/config/gate-violation-baselines.json +76 -72
  241. package/src/config/hook-latency-budget.json +1 -0
  242. package/src/config/hook-token-budget.json +137 -125
  243. package/src/config/pack-size-budget.json +39 -10
  244. package/src/config/preamble-payload-budget.json +97 -71
  245. package/src/config/quorum-attendance-budget.json +12 -4
  246. package/src/config/routing-coverage-seed.json +29 -0
  247. package/src/config/rule-activation-census.json +7 -3
  248. package/src/config/rule-enforcement-baseline.json +0 -1
  249. package/src/config/rule-stub-ceilings.json +112 -91
  250. package/src/config/suggestion-capture.json +28 -0
  251. package/src/config/surface-matrix.yml +21 -2
  252. package/src/config/web-launch-readiness.json +188 -0
  253. package/src/scripts/_cli/cmd_doctor.ts +15 -16
  254. package/src/scripts/_cli/doctor_install_mode.ts +49 -0
  255. package/src/scripts/_cli/doctor_overrides.ts +154 -0
  256. package/src/scripts/_dispatch.bash +17 -0
  257. package/src/scripts/_lib/as_of.ts +412 -0
  258. package/src/scripts/_lib/exec_evidence.ts +7 -0
  259. package/src/scripts/_lib/gate_baseline.ts +150 -1
  260. package/src/scripts/_lib/hook_settings.ts +33 -0
  261. package/src/scripts/_lib/host_listing_model.ts +192 -0
  262. package/src/scripts/_lib/lean_projection_mode.ts +44 -0
  263. package/src/scripts/_lib/mcp_bridge.ts +199 -0
  264. package/src/scripts/_lib/review_independence.ts +62 -10
  265. package/src/scripts/_lib/rule_injection.ts +239 -0
  266. package/src/scripts/_lib/run_checkpoint.ts +54 -1
  267. package/src/scripts/_lib/scoped_projection.ts +96 -0
  268. package/src/scripts/_lib/session_register.ts +44 -2
  269. package/src/scripts/_lib/skill_catalogue.ts +38 -2
  270. package/src/scripts/_lib/skill_estate.ts +115 -0
  271. package/src/scripts/_lib/transcript_reads.ts +207 -0
  272. package/src/scripts/_lib/ui_authority.ts +343 -0
  273. package/src/scripts/ai-video/adapters/fal.sh +8 -3
  274. package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
  275. package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
  276. package/src/scripts/ai-video/adapters/kling.sh +10 -0
  277. package/src/scripts/ai-video/adapters/sora.sh +10 -0
  278. package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
  279. package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
  280. package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
  281. package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
  282. package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
  283. package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
  284. package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
  285. package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
  286. package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
  287. package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
  288. package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
  289. package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
  290. package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
  291. package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
  292. package/src/scripts/ai-video/smoke-trace.sh +450 -2
  293. package/src/scripts/ai-video/stitch.sh +191 -10
  294. package/src/scripts/ai-video/test-pipeline.sh +84 -6
  295. package/src/scripts/ai_council/argument_exhaustion.ts +130 -0
  296. package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
  297. package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
  298. package/src/scripts/ai_council/clients.ts +3 -2
  299. package/src/scripts/ai_council/consensus.ts +63 -6
  300. package/src/scripts/ai_council/events_log.ts +46 -1
  301. package/src/scripts/ai_council/orchestrator.ts +103 -108
  302. package/src/scripts/ai_council/orchestrator_results.ts +166 -0
  303. package/src/scripts/ai_council/prompts.ts +12 -5
  304. package/src/scripts/ai_council/quorum.ts +82 -1
  305. package/src/scripts/ai_council/quorum_wiring.ts +82 -5
  306. package/src/scripts/ai_council/stance_tally.ts +22 -0
  307. package/src/scripts/bench_hook_latency.ts +62 -0
  308. package/src/scripts/build_proof.ts +12 -1
  309. package/src/scripts/capture_skill_catalogue.ts +21 -0
  310. package/src/scripts/check_always_budget.ts +2 -1
  311. package/src/scripts/check_augmentignore.ts +2 -1
  312. package/src/scripts/check_beta_review_markers.ts +2 -1
  313. package/src/scripts/check_bundle_path_leakage.ts +162 -7
  314. package/src/scripts/check_command_examples.ts +557 -0
  315. package/src/scripts/check_composite_arming.ts +364 -0
  316. package/src/scripts/check_corpus_staleness.ts +2 -1
  317. package/src/scripts/check_council_pin_staleness.ts +3 -1
  318. package/src/scripts/check_enforcement_coverage.ts +116 -3
  319. package/src/scripts/check_enforcement_denominator.ts +365 -0
  320. package/src/scripts/check_estate_count.ts +122 -3
  321. package/src/scripts/check_gate_coverage.ts +2 -1
  322. package/src/scripts/check_hook_bundle_freshness.ts +13 -1
  323. package/src/scripts/check_knowledge_cards.ts +2 -1
  324. package/src/scripts/check_knowledge_pages.ts +3 -2
  325. package/src/scripts/check_memory.ts +2 -1
  326. package/src/scripts/check_no_automerge_key.ts +287 -0
  327. package/src/scripts/check_pack_conformance_fixture.ts +565 -0
  328. package/src/scripts/check_preamble_payload_budget.ts +30 -3
  329. package/src/scripts/check_proposal.ts +2 -1
  330. package/src/scripts/check_reach_staleness.ts +2 -1
  331. package/src/scripts/check_release_adjacent_health.ts +2 -1
  332. package/src/scripts/check_release_pr_shape.ts +5 -0
  333. package/src/scripts/check_review_schema.ts +34 -1
  334. package/src/scripts/check_roadmap_trackable.ts +48 -3
  335. package/src/scripts/check_routing_coverage.ts +352 -0
  336. package/src/scripts/check_score_contract.ts +505 -0
  337. package/src/scripts/check_skill_admissions.ts +514 -0
  338. package/src/scripts/check_source_size_budget.ts +2 -1
  339. package/src/scripts/check_standing_payload_delta.ts +505 -0
  340. package/src/scripts/check_trigger_evals.ts +2 -1
  341. package/src/scripts/check_web_launch_readiness.ts +705 -0
  342. package/src/scripts/classify_change_risk.ts +281 -0
  343. package/src/scripts/compute_skill_tiers.ts +186 -0
  344. package/src/scripts/condense.ts +8 -13
  345. package/src/scripts/council_attendance_metrics.ts +183 -0
  346. package/src/scripts/council_cli.ts +10 -8
  347. package/src/scripts/council_parse_rate.ts +116 -0
  348. package/src/scripts/derive_playbooks.ts +406 -0
  349. package/src/scripts/description_route_check.ts +494 -0
  350. package/src/scripts/design_slop_rules.ts +56 -2
  351. package/src/scripts/dispatch_r2_reviewer.ts +16 -0
  352. package/src/scripts/frontend_corpus_hash.ts +116 -0
  353. package/src/scripts/grade_target_readiness.ts +478 -0
  354. package/src/scripts/hook_manifest.json +1 -1
  355. package/src/scripts/hook_manifest.yaml +124 -16
  356. package/src/scripts/hooks/concern_registry.ts +6 -0
  357. package/src/scripts/hooks/design_pass_hook.ts +356 -0
  358. package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
  359. package/src/scripts/hooks/rule_inject_hook.ts +318 -0
  360. package/src/scripts/hooks/suggestion_capture_hook.ts +368 -0
  361. package/src/scripts/hot_context_hook.ts +74 -7
  362. package/src/scripts/install.ts +40 -89
  363. package/src/scripts/lint_adapter_tier.ts +663 -0
  364. package/src/scripts/lint_archived_skills.ts +93 -0
  365. package/src/scripts/lint_budget_ownership.ts +56 -5
  366. package/src/scripts/lint_deterministic_time.ts +470 -0
  367. package/src/scripts/lint_framework_leakage.ts +5 -0
  368. package/src/scripts/lint_handoffs.ts +525 -1
  369. package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
  370. package/src/scripts/lint_marketplace.ts +88 -0
  371. package/src/scripts/lint_media_policy_linkage.ts +140 -1
  372. package/src/scripts/lint_one_off_age.ts +6 -1
  373. package/src/scripts/lint_override_kernel_guard.ts +87 -5
  374. package/src/scripts/lint_roadmap_complexity.ts +56 -0
  375. package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
  376. package/src/scripts/lint_rule_norm_pin.ts +321 -0
  377. package/src/scripts/lint_skill_trigger_corpus.ts +349 -0
  378. package/src/scripts/lint_spawn_payload.ts +42 -5
  379. package/src/scripts/lint_symptom_intake.ts +2 -1
  380. package/src/scripts/mcp_parity_smoke.ts +30 -4
  381. package/src/scripts/mcp_render.ts +66 -1
  382. package/src/scripts/mcp_tool_fingerprint.ts +241 -0
  383. package/src/scripts/measure_risk_class_drift.ts +140 -0
  384. package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
  385. package/src/scripts/media/lib/adapter-common.sh +211 -1
  386. package/src/scripts/media/lib/adapter-contract.md +74 -6
  387. package/src/scripts/model_rule_injection.ts +907 -0
  388. package/src/scripts/pack_install_smoke.ts +363 -0
  389. package/src/scripts/pr_conflict_census.ts +187 -0
  390. package/src/scripts/project_thin_rules.ts +45 -2
  391. package/src/scripts/release.ts +66 -860
  392. package/src/scripts/release_drill.ts +59 -3
  393. package/src/scripts/release_env.ts +298 -0
  394. package/src/scripts/release_publication.ts +720 -0
  395. package/src/scripts/report_pack_delta.ts +204 -0
  396. package/src/scripts/roadmap_context.ts +778 -0
  397. package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
  398. package/src/scripts/schemas/rule.schema.json +24 -2
  399. package/src/scripts/schemas/skill.schema.json +39 -0
  400. package/src/scripts/schemas/ui-authority.schema.json +114 -0
  401. package/src/scripts/select_analysis_mode.ts +112 -0
  402. package/src/scripts/session_register_hook.ts +29 -3
  403. package/src/scripts/sessions_cli.ts +67 -3
  404. package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
  405. package/src/scripts/sync_pr_branch.ts +40 -1
  406. package/src/scripts/token_sink_report.ts +239 -0
  407. package/src/scripts/trigger_coverage.ts +122 -3
  408. package/src/scripts/update_counts.ts +7 -3
  409. package/src/scripts/validate_frontmatter.ts +66 -0
  410. package/src/server/schemas/settings.ts +10 -0
  411. package/src/shared/skillRanking.ts +183 -0
  412. package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +0 -15
  413. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +0 -52
  414. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +0 -52
  415. package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +0 -13
  416. package/dist/agent-src/skills/brand/evals/triggers.json +0 -17
  417. package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +0 -17
  418. package/dist/agent-src/skills/brand-audit/evals/triggers.json +0 -17
  419. package/dist/agent-src/skills/brand-identity/evals/triggers.json +0 -17
  420. package/dist/agent-src/skills/brand-strategy/evals/triggers.json +0 -17
  421. package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +0 -17
  422. package/dist/agent-src/skills/bug-analyzer/evals/evals.json +0 -13
  423. package/dist/agent-src/skills/canvas-design/evals/triggers.json +0 -17
  424. package/dist/agent-src/skills/character-consistency/evals/evals.json +0 -16
  425. package/dist/agent-src/skills/code-intelligence/evals/triggers.json +0 -52
  426. package/dist/agent-src/skills/code-review/evals/evals.json +0 -100
  427. package/dist/agent-src/skills/command-routing/evals/evals.json +0 -14
  428. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +0 -17
  429. package/dist/agent-src/skills/contract-review/evals/triggers.json +0 -17
  430. package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +0 -15
  431. package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +0 -17
  432. package/dist/agent-src/skills/dashboard-design/evals/evals.json +0 -16
  433. package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +0 -29
  434. package/dist/agent-src/skills/dcf-modeling/evals/evals.json +0 -20
  435. package/dist/agent-src/skills/decision-record/evals/evals.json +0 -20
  436. package/dist/agent-src/skills/decision-record/evals/triggers.json +0 -87
  437. package/dist/agent-src/skills/design-intelligence/evals/evals.json +0 -14
  438. package/dist/agent-src/skills/design-intelligence/evals/triggers.json +0 -17
  439. package/dist/agent-src/skills/design-system-capture/evals/evals.json +0 -15
  440. package/dist/agent-src/skills/design-tokens/evals/triggers.json +0 -17
  441. package/dist/agent-src/skills/design-variations/evals/triggers.json +0 -17
  442. package/dist/agent-src/skills/developer-like-execution/evals/evals.json +0 -16
  443. package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +0 -16
  444. package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +0 -17
  445. package/dist/agent-src/skills/docx-authoring/evals/triggers.json +0 -52
  446. package/dist/agent-src/skills/dpa-review/evals/triggers.json +0 -17
  447. package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +0 -16
  448. package/dist/agent-src/skills/editorial-calendar/evals/evals.json +0 -16
  449. package/dist/agent-src/skills/eloquent/evals/triggers.json +0 -17
  450. package/dist/agent-src/skills/estimate-ticket/evals/evals.json +0 -16
  451. package/dist/agent-src/skills/estimate-ticket/evals/output-schema.yml +0 -20
  452. package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +0 -19
  453. package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +0 -52
  454. package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +0 -47
  455. package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +0 -27
  456. package/dist/agent-src/skills/experiment-loop/evals/triggers.json +0 -17
  457. package/dist/agent-src/skills/fe-design/evals/triggers.json +0 -55
  458. package/dist/agent-src/skills/forecasting/evals/domain-truth.json +0 -29
  459. package/dist/agent-src/skills/forecasting/evals/evals.json +0 -20
  460. package/dist/agent-src/skills/forensics-report/evals/triggers.json +0 -17
  461. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +0 -52
  462. package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +0 -16
  463. package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +0 -16
  464. package/dist/agent-src/skills/gated-reach/evals/triggers.json +0 -72
  465. package/dist/agent-src/skills/github-ci/evals/evals.json +0 -25
  466. package/dist/agent-src/skills/history-design/evals/triggers.json +0 -17
  467. package/dist/agent-src/skills/html-deck/evals/triggers.json +0 -17
  468. package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +0 -57
  469. package/dist/agent-src/skills/humanizer/evals/triggers.json +0 -17
  470. package/dist/agent-src/skills/iconography/evals/triggers.json +0 -17
  471. package/dist/agent-src/skills/image-analyser/evals/triggers.json +0 -17
  472. package/dist/agent-src/skills/image-creator/evals/triggers.json +0 -17
  473. package/dist/agent-src/skills/image-editing/evals/triggers.json +0 -17
  474. package/dist/agent-src/skills/image-generation/evals/triggers.json +0 -17
  475. package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +0 -17
  476. package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +0 -16
  477. package/dist/agent-src/skills/incident-commander/evals/evals.json +0 -20
  478. package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +0 -17
  479. package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +0 -17
  480. package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +0 -17
  481. package/dist/agent-src/skills/launch-readiness/evals/evals.json +0 -21
  482. package/dist/agent-src/skills/learning-tutor/evals/triggers.json +0 -52
  483. package/dist/agent-src/skills/legal-intake-triage/evals/triggers.json +0 -17
  484. package/dist/agent-src/skills/legal-practice-profile/evals/triggers.json +0 -17
  485. package/dist/agent-src/skills/license-compliance-audit/evals/triggers.json +0 -52
  486. package/dist/agent-src/skills/license-compliance-borrow-check/evals/triggers.json +0 -52
  487. package/dist/agent-src/skills/license-compliance-credits/evals/triggers.json +0 -52
  488. package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +0 -20
  489. package/dist/agent-src/skills/logging-monitoring/evals/evals.json +0 -16
  490. package/dist/agent-src/skills/logo-generation/evals/triggers.json +0 -17
  491. package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +0 -16
  492. package/dist/agent-src/skills/messaging-architecture/evals/evals.json +0 -16
  493. package/dist/agent-src/skills/nda-triage/evals/triggers.json +0 -17
  494. package/dist/agent-src/skills/pdf-tools/evals/triggers.json +0 -52
  495. package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +0 -16
  496. package/dist/agent-src/skills/persona-improvement/evals/triggers.json +0 -52
  497. package/dist/agent-src/skills/php-coder/evals/triggers.json +0 -17
  498. package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +0 -21
  499. package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +0 -17
  500. package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +0 -16
  501. package/dist/agent-src/skills/prompt-validator/evals/triggers.json +0 -17
  502. package/dist/agent-src/skills/quality-tools/evals/evals.json +0 -15
  503. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +0 -17
  504. package/dist/agent-src/skills/refine-prompt/evals/evals.json +0 -16
  505. package/dist/agent-src/skills/refine-ticket/evals/evals.json +0 -16
  506. package/dist/agent-src/skills/refine-ticket/evals/output-schema.yml +0 -16
  507. package/dist/agent-src/skills/refine-ticket/evals/triggers.json +0 -17
  508. package/dist/agent-src/skills/release-comms/evals/evals.json +0 -16
  509. package/dist/agent-src/skills/rice-prioritization/evals/evals.json +0 -20
  510. package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +0 -29
  511. package/dist/agent-src/skills/runway-cognition/evals/evals.json +0 -20
  512. package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +0 -29
  513. package/dist/agent-src/skills/scenario-modeling/evals/evals.json +0 -20
  514. package/dist/agent-src/skills/schema-review/evals/triggers.json +0 -17
  515. package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +0 -52
  516. package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +0 -52
  517. package/dist/agent-src/skills/skill-writing/evals/triggers.json +0 -17
  518. package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +0 -47
  519. package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +0 -60
  520. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +0 -52
  521. package/dist/agent-src/skills/systematic-debugging/evals/evals.json +0 -20
  522. package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +0 -52
  523. package/dist/agent-src/skills/test-driven-development/evals/evals.json +0 -16
  524. package/dist/agent-src/skills/threat-modeling/evals/evals.json +0 -21
  525. package/dist/agent-src/skills/typography-system/evals/evals.json +0 -14
  526. package/dist/agent-src/skills/typography-system/evals/triggers.json +0 -17
  527. package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +0 -40
  528. package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +0 -24
  529. package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +0 -16
  530. package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +0 -20
  531. package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +0 -17
  532. package/dist/agent-src/skills/vision-articulation/evals/evals.json +0 -16
  533. package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +0 -16
  534. package/dist/agent-src/skills/wireframe/evals/triggers.json +0 -17
  535. package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +0 -38
  536. package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +0 -52
  537. package/dist/cli/agent-config.js.map +0 -1
  538. package/dist/cli/bash/runBash.js.map +0 -1
  539. package/dist/cli/commands/commands.js.map +0 -1
  540. package/dist/cli/commands/config.js.map +0 -1
  541. package/dist/cli/commands/doctorShell.js.map +0 -1
  542. package/dist/cli/commands/mcpServer.js.map +0 -1
  543. package/dist/cli/commands/packs.js.map +0 -1
  544. package/dist/cli/commands/profiles.js.map +0 -1
  545. package/dist/cli/commands/recordTriggerEval.js.map +0 -1
  546. package/dist/cli/commands/rtkDetect.js.map +0 -1
  547. package/dist/cli/commands/settings.js.map +0 -1
  548. package/dist/cli/commands/uiServe.js.map +0 -1
  549. package/dist/cli/commands/versions.js.map +0 -1
  550. package/dist/cli/commands/workspaces.js.map +0 -1
  551. package/dist/cli/configRoot.js.map +0 -1
  552. package/dist/cli/discovery/loadManifest.js.map +0 -1
  553. package/dist/cli/firstRunNotice.js.map +0 -1
  554. package/dist/cli/help.js.map +0 -1
  555. package/dist/cli/initRouting.js.map +0 -1
  556. package/dist/cli/log/logger.js.map +0 -1
  557. package/dist/cli/main.js.map +0 -1
  558. package/dist/cli/mcp/content.js.map +0 -1
  559. package/dist/cli/mcp/dispatch.js.map +0 -1
  560. package/dist/cli/mcp/stdio.js.map +0 -1
  561. package/dist/cli/paths.js.map +0 -1
  562. package/dist/cli/python/knowledge_ingest.js.map +0 -1
  563. package/dist/cli/python/workspace_analytics.js.map +0 -1
  564. package/dist/cli/python/workspace_crypto.js.map +0 -1
  565. package/dist/cli/python/workspace_documents.js.map +0 -1
  566. package/dist/cli/python/workspace_drive.js.map +0 -1
  567. package/dist/cli/python/workspace_drive_health.js.map +0 -1
  568. package/dist/cli/python/workspace_explain.js.map +0 -1
  569. package/dist/cli/python/workspace_hosts.js.map +0 -1
  570. package/dist/cli/python/workspace_inbox.js.map +0 -1
  571. package/dist/cli/python/workspace_render.js.map +0 -1
  572. package/dist/cli/python/workspace_roles.js.map +0 -1
  573. package/dist/cli/python/workspace_secrets.js.map +0 -1
  574. package/dist/cli/python/workspace_sessions.js.map +0 -1
  575. package/dist/cli/python/workspace_skills.js.map +0 -1
  576. package/dist/cli/registry.js.map +0 -1
  577. package/dist/install/agentSwitchDetection.js.map +0 -1
  578. package/dist/install/agentSwitchProfile.js.map +0 -1
  579. package/dist/install/atomic.js.map +0 -1
  580. package/dist/install/claudePathsPlan.js.map +0 -1
  581. package/dist/install/conflict.js.map +0 -1
  582. package/dist/install/detect.js.map +0 -1
  583. package/dist/install/emit_host_rules_cli.js.map +0 -1
  584. package/dist/install/globalRuleLayers.js.map +0 -1
  585. package/dist/install/hostLayerFingerprint.js.map +0 -1
  586. package/dist/install/partitionEligibility.js.map +0 -1
  587. package/dist/install/paths.js.map +0 -1
  588. package/dist/install/plan.js.map +0 -1
  589. package/dist/install/preflight.js.map +0 -1
  590. package/dist/install/rtkDetection.js.map +0 -1
  591. package/dist/install/ruleInScope.js.map +0 -1
  592. package/dist/install/ruleLayerPartition.js.map +0 -1
  593. package/dist/install/rule_scope.js.map +0 -1
  594. package/dist/install/rule_scope_cli.js.map +0 -1
  595. package/dist/install/selectedTools.js.map +0 -1
  596. package/dist/install/toolDetection.js.map +0 -1
  597. package/dist/install/txlog.js.map +0 -1
  598. package/dist/install/types.js.map +0 -1
  599. package/dist/install/wizard-plan.js.map +0 -1
  600. package/dist/install/wizardDismissals.js.map +0 -1
  601. package/dist/scripts/_lib/agent_settings.js.map +0 -1
  602. package/dist/scripts/_lib/agent_src.js.map +0 -1
  603. package/dist/scripts/_lib/claude_builtin_names.js.map +0 -1
  604. package/dist/scripts/_lib/claude_plugin.js.map +0 -1
  605. package/dist/scripts/_lib/claude_settings_hooks.js.map +0 -1
  606. package/dist/scripts/_lib/compile_time_toggles.js.map +0 -1
  607. package/dist/scripts/_lib/environment_detector.js.map +0 -1
  608. package/dist/scripts/_lib/host_launch.js.map +0 -1
  609. package/dist/scripts/_lib/install_layout.js.map +0 -1
  610. package/dist/scripts/_lib/installed_lock.js.map +0 -1
  611. package/dist/scripts/_lib/model_tier.js.map +0 -1
  612. package/dist/scripts/_lib/prune_empty_dirs.js.map +0 -1
  613. package/dist/scripts/_lib/scoped_projection.js.map +0 -1
  614. package/dist/scripts/_lib/script_output.js.map +0 -1
  615. package/dist/scripts/_lib/spawn_env.js.map +0 -1
  616. package/dist/scripts/_lib/surface_tiers.js.map +0 -1
  617. package/dist/scripts/_lib/token_count.js.map +0 -1
  618. package/dist/scripts/_lib/trigger_eval_floors.js.map +0 -1
  619. package/dist/scripts/_lib/user_global_paths.js.map +0 -1
  620. package/dist/scripts/ai_council/modes.js.map +0 -1
  621. package/dist/scripts/ai_council/transport_resolver.js.map +0 -1
  622. package/dist/scripts/condense.js.map +0 -1
  623. package/dist/scripts/project_thin_rules.js.map +0 -1
  624. package/dist/server/app.js.map +0 -1
  625. package/dist/server/io/atomicMultiWrite.js.map +0 -1
  626. package/dist/server/io/atomicWrite.js.map +0 -1
  627. package/dist/server/io/sharedWriteCheck.js.map +0 -1
  628. package/dist/server/io/substituteTemplate.js.map +0 -1
  629. package/dist/server/io/yamlIO.js.map +0 -1
  630. package/dist/server/nicknameResolver.js.map +0 -1
  631. package/dist/server/port.js.map +0 -1
  632. package/dist/server/routes/discovery.js.map +0 -1
  633. package/dist/server/routes/install.js.map +0 -1
  634. package/dist/server/routes/ping.js.map +0 -1
  635. package/dist/server/routes/schema.js.map +0 -1
  636. package/dist/server/routes/settings.js.map +0 -1
  637. package/dist/server/routes/settingsChanges.js.map +0 -1
  638. package/dist/server/routes/userMd.js.map +0 -1
  639. package/dist/server/routes/wizard.js.map +0 -1
  640. package/dist/server/routes/workspace.js.map +0 -1
  641. package/dist/server/schemas/settings.js.map +0 -1
  642. package/dist/server/serverInfo.js.map +0 -1
  643. package/dist/server/token.js.map +0 -1
  644. package/dist/server/writeRoot.js.map +0 -1
  645. package/dist/shared/capabilities.js.map +0 -1
  646. package/dist/shared/interactiveContext.js.map +0 -1
  647. package/dist/shared/nicknamePrefill.js.map +0 -1
  648. package/dist/shared/settingsAsks.js.map +0 -1
  649. package/dist/shared/settingsCarveOut.js.map +0 -1
  650. package/dist/shared/settingsClasses.js.map +0 -1
  651. package/dist/shared/settingsConsent.js.map +0 -1
  652. package/dist/shared/settingsSurface.js.map +0 -1
  653. package/dist/shared/userMd/formAdapter.js.map +0 -1
  654. package/dist/shared/userMd/schema.js.map +0 -1
  655. package/dist/shared/userMd/utils.js.map +0 -1
  656. package/dist/ui/assets/index-Cxgy63kz.js.map +0 -1
  657. package/src/scripts/_lib/adr_frontmatter.test.ts +0 -365
  658. package/src/scripts/_lib/adversarial_council_gate.test.ts +0 -112
  659. package/src/scripts/_lib/adversarial_reconcile.test.ts +0 -197
  660. package/src/scripts/_lib/auto_dispatch.corpus.test.ts +0 -150
  661. package/src/scripts/_lib/secret_detector.test.ts +0 -108
  662. package/src/scripts/_lib/secret_detector_adversarial.test.ts +0 -116
  663. package/src/scripts/_lib/untrusted_content.test.ts +0 -175
  664. package/src/scripts/check_secret_leak.test.ts +0 -90
  665. package/src/scripts/design_slop_rules.test.ts +0 -239
  666. package/src/scripts/self_review_gate.test.ts +0 -296
  667. package/src/shared/capabilities.test.ts +0 -43
@@ -19,17 +19,21 @@
19
19
  * 4. No archived slug still has a live SKILL.md (no zombies).
20
20
  * 5. No live SKILL.md cites an archived slug as a router target in its
21
21
  * frontmatter `replaced_by:` field.
22
+ * 6. A slug that had a `SKILL.md` at the base ref and has none in the
23
+ * working tree carries an archive note. See {@link removed_without_note}.
22
24
  *
23
25
  * Exit codes:
24
26
  * 0 contract holds
25
27
  * 1 one or more violations
26
28
  */
27
29
 
30
+ import { spawnSync } from 'node:child_process';
28
31
  import * as fs from 'node:fs';
29
32
  import * as path from 'node:path';
30
33
  import { fileURLToPath, pathToFileURL } from 'node:url';
31
34
 
32
35
  import { artefact_roots } from './_lib/agent_src.js';
36
+ import { resolveBaseRef } from './_lib/ratchet_base_ref.js';
33
37
  import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
34
38
 
35
39
  const _HERE = fileURLToPath(import.meta.url);
@@ -243,6 +247,19 @@ function main(): number {
243
247
  }
244
248
  }
245
249
 
250
+ // Rule 6 — removals that never entered the ledger.
251
+ const removalCheck = removed_without_note(REPO, archivedKeys, live);
252
+ if ('skipped' in removalCheck) {
253
+ process.stdout.write(`rule 6 skipped: ${removalCheck.skipped}\n`);
254
+ } else {
255
+ for (const slug of removalCheck.removed) {
256
+ errors.push(
257
+ `${slug}: SKILL.md removed since the base ref with no ` +
258
+ `agents/evidence/archived-skills/${slug}.md note`,
259
+ );
260
+ }
261
+ }
262
+
246
263
  if (errors.length) {
247
264
  process.stderr.write(
248
265
  `❌ lint_archived_skills: ${errors.length} violation(s) across ${notes.length} note(s)\n`,
@@ -261,6 +278,82 @@ function main(): number {
261
278
  return 0;
262
279
  }
263
280
 
281
+ /**
282
+ * Rule 6 — a slug that left the tree without entering the ledger.
283
+ *
284
+ * WHY THIS LIVES IN THE GATE AND NOT IN A SCAFFOLDER. The roadmap step that
285
+ * asked for this (`road-to-skill-link-integrity-and-manifest-sync` Phase 1
286
+ * Step 3) named `src/scripts/new_skill.ts --archive` as the extension point,
287
+ * on the premise that it is "a creation path with no symmetric removal path".
288
+ * That premise is false: `new_skill.ts` scaffolds into a `packages/<pack>/`
289
+ * container that ADR-051 retired, and its `main()` returns exit 2 with
290
+ * `error: no packages/ tree found` in this tree, because skill authoring moved
291
+ * to `src/skills/`. A mode added there could not run.
292
+ *
293
+ * The obligation is a CI property, not a tool property, and the distinction is
294
+ * the reason the ledger is empty: nothing forces a maintainer or an agent to
295
+ * delete a directory *through* a tool, so a scaffolder mode is a bypass by
296
+ * construction. Three slugs left this tree without a note while
297
+ * `agents/evidence/archived-skills/` held only a README.
298
+ *
299
+ * A RENAME IS A REMOVAL HERE, DELIBERATELY. Git would call
300
+ * `verify-before-complete` → `verify-completion-evidence` a rename; every link
301
+ * to the old slug still broke, and repairing eight of them is what produced
302
+ * this rule. So the old slug owes a note.
303
+ *
304
+ * THE COMPARISON IS AGAINST THE MERGE BASE, NOT THE TIP OF MAIN, and this was
305
+ * found the hard way: the first run of this rule reported `js-library-packaging`
306
+ * and `storybook-workshop` as unnoted removals. Neither had been removed — both
307
+ * were ADDED on main after this branch forked, so a branch that is merely
308
+ * BEHIND its base read every new skill as a deletion. That is the false-red
309
+ * class `_lib/ratchet_base_ref.ts` warns about in its own docstring ("the gate
310
+ * gets a reputation for false reds, and someone turns it off"). `git merge-base`
311
+ * answers the question the rule actually asks — did THIS branch remove it —
312
+ * because a skill added on main after the fork is not in the merge base at all.
313
+ *
314
+ * THE SKIP IS STATED, NEVER SILENT. With no resolvable base ref there is no
315
+ * "before" side, and comparing against an assumed-empty base would report every
316
+ * skill in the tree as removed. `resolveBaseRef` returns null in that case and
317
+ * this returns a `skipped` reason the caller prints — the honest default named
318
+ * in that helper's own contract. It is also blind to an uncommitted removal;
319
+ * CI is the authoritative gate and CI only ever sees committed work.
320
+ */
321
+ export function removed_without_note(
322
+ repoRoot: string = REPO,
323
+ archived: ReadonlySet<string> = new Set(archived_slugs()),
324
+ liveSlugs: ReadonlySet<string> = new Set(live_skill_slugs()),
325
+ ): { skipped: string } | { removed: string[] } {
326
+ const base = resolveBaseRef(repoRoot);
327
+ if (base === null) {
328
+ return { skipped: 'no base ref resolved — nothing to compare against' };
329
+ }
330
+ const mb = spawnSync('git', ['merge-base', 'HEAD', base], {
331
+ cwd: repoRoot,
332
+ encoding: 'utf-8',
333
+ });
334
+ // A missing merge base is not "compare against the tip instead" — that is
335
+ // the false-red above. It is no comparable before-side at all.
336
+ const forkPoint = mb.status === 0 ? String(mb.stdout).trim() : '';
337
+ if (!forkPoint) {
338
+ return { skipped: `no merge base between HEAD and ${base}` };
339
+ }
340
+ const res = spawnSync(
341
+ 'git',
342
+ ['ls-tree', '-r', '--name-only', forkPoint, '--', 'src/skills'],
343
+ { cwd: repoRoot, encoding: 'utf-8' },
344
+ );
345
+ if (res.status !== 0) {
346
+ return { skipped: `git ls-tree ${forkPoint} failed — base ref is not readable here` };
347
+ }
348
+ const atBase = new Set<string>();
349
+ for (const line of String(res.stdout).split('\n')) {
350
+ const m = /^src\/skills\/([^/]+)\/SKILL\.md$/.exec(line.trim());
351
+ if (m) atBase.add(m[1] as string);
352
+ }
353
+ const removed = [...atBase].filter((slug) => !liveSlugs.has(slug) && !archived.has(slug)).sort();
354
+ return { removed };
355
+ }
356
+
264
357
  // --- helpers --------------------------------------------------------------
265
358
 
266
359
  function _exists(p: string): boolean {
@@ -28,9 +28,11 @@
28
28
  * Exit codes: 0 clean · 1 findings · 2 internal error.
29
29
  */
30
30
  import * as fs from 'node:fs';
31
+ import { parse as parseYaml } from 'yaml';
31
32
  import * as path from 'node:path';
32
33
  import { fileURLToPath } from 'node:url';
33
34
 
35
+ import { asOf } from './_lib/as_of.js';
34
36
  import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
35
37
 
36
38
  const REPO_ROOT = path.resolve(fileURLToPath(import.meta.url), '..', '..', '..');
@@ -121,20 +123,69 @@ export function checkBudgetRows(relPath: string, doc: Record<string, unknown>):
121
123
  return errors;
122
124
  }
123
125
 
126
+ /**
127
+ * Non-JSON budget files this gate governs, named ONE BY ONE.
128
+ *
129
+ * road-to-standing-payload-truth `b-budgets-yml-outside-ownership`: `budgets.yml`
130
+ * carries a `standing_rule_delivery` entry that gates the larger of the two red
131
+ * payload numbers, and it had no `owner` and no `review_by` because this gate
132
+ * filtered on `.json`.
133
+ *
134
+ * **An explicit list, NOT a widened glob**, and both council seats (2026-08-24)
135
+ * refused the glob for the same two reasons:
136
+ *
137
+ * 1. `*budget*.json` **IS** this gate's corpus definition (see `main`'s note), so
138
+ * widening it to `*budget*.{json,yml}` means any future `*budget*.yml` dropped
139
+ * into `src/config/` joins the governed set **silently**. A governed file
140
+ * should be a decision, not a filename coincidence.
141
+ * 2. It could not have worked as written anyway: the read below was an
142
+ * unconditional `JSON.parse`, so a YAML file entering through a widened glob
143
+ * would have been reported as `unparseable JSON` — a red gate blaming the
144
+ * file for the gate's own bug. Parsing is now dispatched on extension.
145
+ *
146
+ * Adding a row here is the whole cost of governing a new non-JSON budget, and
147
+ * `lint_budget_ownership.test.ts` asserts an unlisted `*budget*.yml` stays OUT.
148
+ */
149
+ export const GOVERNED_NON_JSON: readonly string[] = ['budgets.yml'];
150
+
124
151
  export function budgetFiles(dir: string = CONFIG_DIR): string[] {
125
152
  try {
126
- return fs
153
+ const globbed = fs
127
154
  .readdirSync(dir)
128
155
  .filter((f) => f.endsWith('.json') && f.toLowerCase().includes('budget'))
129
156
  .map((f) => path.join(dir, f));
157
+ const named = GOVERNED_NON_JSON.map((f) => path.join(dir, f)).filter((abs) =>
158
+ fs.existsSync(abs),
159
+ );
160
+ return [...globbed, ...named];
130
161
  } catch {
131
162
  return [];
132
163
  }
133
164
  }
134
165
 
166
+ /**
167
+ * Parse a budget file by EXTENSION.
168
+ *
169
+ * The previous unconditional `JSON.parse` is the defect that made a widened glob
170
+ * unworkable; keeping it while adding a `.yml` row would have turned this gate
171
+ * red on the very file it was extended to govern.
172
+ */
173
+ export function parseBudgetDoc(abs: string): Record<string, unknown> {
174
+ const text = fs.readFileSync(abs, 'utf-8');
175
+ if (abs.endsWith('.yml') || abs.endsWith('.yaml')) {
176
+ const doc = parseYaml(text) as unknown;
177
+ if (doc === null || typeof doc !== 'object' || Array.isArray(doc)) {
178
+ throw new Error('top level is not a mapping');
179
+ }
180
+ return doc as Record<string, unknown>;
181
+ }
182
+ return JSON.parse(text) as Record<string, unknown>;
183
+ }
184
+
135
185
  export function main(): number {
136
186
  const files = budgetFiles();
137
- // `*budget*.json` IS this gate's corpus definition, not a content-derived
187
+ // `*budget*.json` PLUS the explicitly named `GOVERNED_NON_JSON` rows IS this
188
+ // gate's corpus definition, not a content-derived
138
189
  // subset: zero matches means src/config/ moved or the budgets were deleted,
139
190
  // and the old "nothing to lint" exit 0 could not tell either from a healthy
140
191
  // tree. Of the two documented failure codes, 1 is the one the gate actually
@@ -154,14 +205,14 @@ export function main(): number {
154
205
  throw exc;
155
206
  }
156
207
  const errors: string[] = [];
157
- const today = new Date().toISOString().slice(0, 10);
208
+ const today = asOf().toISOString().slice(0, 10);
158
209
  for (const abs of files) {
159
210
  const rel = path.relative(REPO_ROOT, abs);
160
211
  let doc: Record<string, unknown>;
161
212
  try {
162
- doc = JSON.parse(fs.readFileSync(abs, 'utf-8')) as Record<string, unknown>;
213
+ doc = parseBudgetDoc(abs);
163
214
  } catch (e) {
164
- errors.push(`${rel}: unparseable JSON (${(e as Error).message})`);
215
+ errors.push(`${rel}: unparseable budget file (${(e as Error).message})`);
165
216
  continue;
166
217
  }
167
218
  errors.push(...checkBudgetDoc(rel, doc));
@@ -0,0 +1,470 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * CI gate: a gate script does not read the wall clock directly.
4
+ *
5
+ * WHY. A gate's verdict should be a function of the tree, not of the hour it
6
+ * ran. Measured on 2026-08-23, before this gate existed, **17** of the
7
+ * `check_*` / `lint_*` scripts under `src/scripts/` read the clock inline, every
8
+ * one of them to make an age or staleness judgement. None of those 17 verdicts
9
+ * was reproducible from the commit alone: the same tree greens on Monday and
10
+ * reds on Friday, and a reviewer cannot recover which "now" produced the verdict
11
+ * CI published.
12
+ *
13
+ * `src/scripts/_lib/as_of.ts` is the seam that fixes it — one resolver, four
14
+ * rungs (`--as-of` argv, `AC_AS_OF` env, the commit date under CI, and the wall
15
+ * clock with an explicit non-reproducibility WARN). This gate is what stops the
16
+ * defect coming back: substituting the seam once is a diff, keeping it
17
+ * substituted is a ratchet.
18
+ *
19
+ * SCOPE is deliberately the gate prefixes only (`check_*`, `lint_*` under
20
+ * `src/scripts/`). A generator, a bench runner, or a hook legitimately reads
21
+ * real time; a *verdict* should not. Widening this to the whole tree would turn
22
+ * a determinism ratchet into a style rule and earn the suppressions that come
23
+ * with one.
24
+ *
25
+ * WHY THE MATCH RUNS OVER STRIPPED SOURCE. This file's own docstring names the
26
+ * construct it forbids, and its self-test fixtures are string literals
27
+ * containing it. A gate whose scope includes its own filename (`lint_*` does)
28
+ * and which matched raw text would refuse itself — so comments and string /
29
+ * template literals are blanked to spaces (line numbers preserved) before the
30
+ * patterns run. The same reason `check_no_automerge_key` anchors on a key rather
31
+ * than a word.
32
+ *
33
+ * THE ESCAPE HATCH, AND WHY IT IS NARROW. `// wall-clock-required: <reason>` on
34
+ * the offending line exempts it, and the reason is mandatory — a bare marker is
35
+ * still a finding. It exists for the one legitimate case this ratchet must not
36
+ * break: measuring *elapsed duration* inside a single run, where real time is
37
+ * the subject rather than a threshold input. Prefer `performance.now()` there;
38
+ * the marker is for when a `Date` is genuinely what the API needs.
39
+ *
40
+ * Exit codes:
41
+ * 0 — no gate script reads the wall clock directly
42
+ * 1 — at least one raw wall-clock read (or a marker with no reason)
43
+ * 2 — the gate could not run (dead scan scope, bad args)
44
+ */
45
+ import * as fs from 'node:fs';
46
+ import * as os from 'node:os';
47
+ import * as path from 'node:path';
48
+ import { fileURLToPath, pathToFileURL } from 'node:url';
49
+
50
+ import { GateLedger, LedgerUsageError } from './_lib/gate_ledger.js';
51
+ import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
52
+ import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
53
+
54
+ const _HERE = fileURLToPath(import.meta.url);
55
+ const DEFAULT_ROOT = path.join(path.dirname(_HERE), '..', '..');
56
+
57
+ /** This script's repo-relative path, for the self-test's CLI invocations. */
58
+ const SELF = 'src/scripts/lint_deterministic_time.ts';
59
+
60
+ const SELF_TEST_MIN_CASES = 6;
61
+ const SELF_TEST_MIN_REJECT = 3;
62
+
63
+ /** The directory the gate walks, and the prefixes that make a file a gate. */
64
+ const SCAN_DIR = 'src/scripts';
65
+ const GATE_PREFIXES = ['check_', 'lint_'] as const;
66
+
67
+ /**
68
+ * The single sanctioned reader of the wall clock. Repo-relative, and outside
69
+ * {@link GATE_PREFIXES} by construction, so it is never in the scan set — named
70
+ * here so the failure message can point at it.
71
+ */
72
+ const SEAM = 'src/scripts/_lib/as_of.ts';
73
+
74
+ /** Same-line exemption. The reason after the colon must be non-empty. */
75
+ const MARKER = 'wall-clock-required:';
76
+
77
+ /**
78
+ * The forbidden constructs. Written as tolerant regexes rather than literals so
79
+ * this file's own source does not contain the strings it bans — see the
80
+ * docstring's note on stripped source; belt and braces, and the belt is cheap.
81
+ */
82
+ const PATTERNS: readonly { id: string; re: RegExp; shown: string }[] = [
83
+ { id: 'date-now', re: /\bDate\s*\.\s*now\s*\(\s*\)/g, shown: 'Date' + '.now()' },
84
+ { id: 'new-date', re: /\bnew\s+Date\s*\(\s*\)/g, shown: 'new ' + 'Date()' },
85
+ ];
86
+
87
+ /**
88
+ * Neutralise every non-code region, preserving line numbers and line lengths so
89
+ * a match's line number is still the source's.
90
+ *
91
+ * Two details are load-bearing and were both found by running this gate against
92
+ * the real corpus before trusting it:
93
+ *
94
+ * 1. **Comments become spaces, string bodies become `x`.** Blanking a string to
95
+ * spaces collapses `new Date("2026-01-01")` into `new Date( )`,
96
+ * which the empty-parens pattern then matches — a false positive on a
97
+ * perfectly deterministic parse. `check_knowledge_pages.ts:103` is exactly
98
+ * that shape. Filling with a non-space keeps the argument visible as *an*
99
+ * argument without keeping its content.
100
+ * 2. **`${...}` inside a template literal is code.** Blanking it wholesale hid a
101
+ * real finding: `check_gate_coverage.ts:982` reads the clock inside a
102
+ * template substitution, and the first draft of this gate reported it clean.
103
+ *
104
+ * Regex literals are left alone deliberately: a regex describing the forbidden
105
+ * construct (this file's own {@link PATTERNS}) does not itself match it, so
106
+ * there is nothing to hide, and detecting a regex literal from a `/` needs
107
+ * expression context this scanner does not have.
108
+ */
109
+ export function stripNonCode(src: string): string {
110
+ const out = src.split('');
111
+ const n = src.length;
112
+ const put = (i: number, ch: string): void => {
113
+ if (out[i] !== '\n') out[i] = ch;
114
+ };
115
+
116
+ /** `//` to end of line. */
117
+ function lineComment(i: number): number {
118
+ while (i < n && src[i] !== '\n') put(i++, ' ');
119
+ return i;
120
+ }
121
+ /** `/*` to the closing delimiter. */
122
+ function blockComment(i: number): number {
123
+ put(i++, ' ');
124
+ put(i++, ' ');
125
+ while (i < n && !(src[i] === '*' && src[i + 1] === '/')) put(i++, ' ');
126
+ if (i < n) {
127
+ put(i++, ' ');
128
+ put(i++, ' ');
129
+ }
130
+ return i;
131
+ }
132
+ /** A `'` or `"` literal; an unterminated one stops at the newline. */
133
+ function simpleString(i: number): number {
134
+ const quote = src[i];
135
+ put(i++, 'x');
136
+ while (i < n) {
137
+ if (src[i] === '\\') {
138
+ put(i++, 'x');
139
+ if (i < n) put(i++, 'x');
140
+ continue;
141
+ }
142
+ if (src[i] === quote) {
143
+ put(i++, 'x');
144
+ break;
145
+ }
146
+ if (src[i] === '\n') break;
147
+ put(i++, 'x');
148
+ }
149
+ return i;
150
+ }
151
+ /** A `\`` literal, recursing into every `${...}` as code. */
152
+ function template(i: number): number {
153
+ put(i++, 'x');
154
+ while (i < n) {
155
+ if (src[i] === '\\') {
156
+ put(i++, 'x');
157
+ if (i < n) put(i++, 'x');
158
+ continue;
159
+ }
160
+ if (src[i] === '`') {
161
+ put(i++, 'x');
162
+ break;
163
+ }
164
+ if (src[i] === '$' && src[i + 1] === '{') {
165
+ i = substitution(i + 2);
166
+ continue;
167
+ }
168
+ put(i++, 'x');
169
+ }
170
+ return i;
171
+ }
172
+ /** Code inside `${ ... }`, up to the brace that closes it. */
173
+ function substitution(i: number): number {
174
+ let depth = 1;
175
+ while (i < n && depth > 0) {
176
+ const c = src[i];
177
+ const next = src[i + 1];
178
+ if (c === '/' && next === '/') {
179
+ i = lineComment(i);
180
+ continue;
181
+ }
182
+ if (c === '/' && next === '*') {
183
+ i = blockComment(i);
184
+ continue;
185
+ }
186
+ if (c === "'" || c === '"') {
187
+ i = simpleString(i);
188
+ continue;
189
+ }
190
+ if (c === '`') {
191
+ i = template(i);
192
+ continue;
193
+ }
194
+ if (c === '{') depth += 1;
195
+ if (c === '}') depth -= 1;
196
+ i += 1;
197
+ }
198
+ return i;
199
+ }
200
+
201
+ let i = 0;
202
+ while (i < n) {
203
+ const c = src[i];
204
+ const next = src[i + 1];
205
+ if (c === '/' && next === '/') {
206
+ i = lineComment(i);
207
+ continue;
208
+ }
209
+ if (c === '/' && next === '*') {
210
+ i = blockComment(i);
211
+ continue;
212
+ }
213
+ if (c === "'" || c === '"') {
214
+ i = simpleString(i);
215
+ continue;
216
+ }
217
+ if (c === '`') {
218
+ i = template(i);
219
+ continue;
220
+ }
221
+ i += 1;
222
+ }
223
+ return out.join('');
224
+ }
225
+
226
+ export interface Finding {
227
+ file: string;
228
+ line: number;
229
+ construct: string;
230
+ /** `raw` — an unmarked read. `bare-marker` — a marker with no reason. */
231
+ kind: 'raw' | 'bare-marker';
232
+ }
233
+
234
+ /** Does this raw line carry a marker, and does the marker carry a reason? */
235
+ function markerOn(rawLine: string): 'none' | 'bare' | 'reasoned' {
236
+ const at = rawLine.indexOf(MARKER);
237
+ if (at < 0) return 'none';
238
+ return rawLine.slice(at + MARKER.length).trim() === '' ? 'bare' : 'reasoned';
239
+ }
240
+
241
+ export function scanSource(relPath: string, src: string): Finding[] {
242
+ const rawLines = src.split('\n');
243
+ const codeLines = stripNonCode(src).split('\n');
244
+ const findings: Finding[] = [];
245
+ for (let n = 0; n < codeLines.length; n += 1) {
246
+ const code = codeLines[n] ?? '';
247
+ for (const pat of PATTERNS) {
248
+ pat.re.lastIndex = 0;
249
+ if (!pat.re.test(code)) continue;
250
+ const marker = markerOn(rawLines[n] ?? '');
251
+ if (marker === 'reasoned') continue;
252
+ findings.push({
253
+ file: relPath,
254
+ line: n + 1,
255
+ construct: pat.shown,
256
+ kind: marker === 'bare' ? 'bare-marker' : 'raw',
257
+ });
258
+ }
259
+ }
260
+ return findings;
261
+ }
262
+
263
+ /** Repo-relative paths of every gate script under {@link SCAN_DIR}. */
264
+ export function gateScripts(root: string): string[] {
265
+ const dir = path.join(root, SCAN_DIR);
266
+ let entries: string[];
267
+ try {
268
+ entries = fs.readdirSync(dir);
269
+ } catch {
270
+ return [];
271
+ }
272
+ return entries
273
+ .filter(
274
+ (name) =>
275
+ name.endsWith('.ts') &&
276
+ !name.endsWith('.test.ts') &&
277
+ GATE_PREFIXES.some((p) => name.startsWith(p)),
278
+ )
279
+ .sort()
280
+ .map((name) => `${SCAN_DIR}/${name}`);
281
+ }
282
+
283
+ export function check(root: string): { code: number; findings: Finding[]; scanned: number } {
284
+ const files = gateScripts(root);
285
+ const findings: Finding[] = [];
286
+ const ledger = new GateLedger('lint_deterministic_time');
287
+
288
+ try {
289
+ reportScanned({
290
+ gate: 'lint_deterministic_time',
291
+ scanned: files.length,
292
+ units: 'gate script(s)',
293
+ roots: [SCAN_DIR],
294
+ });
295
+ } catch (err) {
296
+ if (err instanceof DeadScopeError) {
297
+ process.stderr.write(`❌ ${err.message}\n`);
298
+ return { code: 2, findings, scanned: files.length };
299
+ }
300
+ throw err;
301
+ }
302
+
303
+ try {
304
+ ledger.plan(files);
305
+ for (const rel of files) {
306
+ const found = scanSource(rel, fs.readFileSync(path.join(root, rel), 'utf-8'));
307
+ if (found.length > 0) {
308
+ findings.push(...found);
309
+ ledger.fail(rel, `${String(found.length)} raw wall-clock read(s)`);
310
+ } else {
311
+ ledger.complete(rel);
312
+ }
313
+ }
314
+ } catch (err) {
315
+ if (err instanceof LedgerUsageError) {
316
+ process.stderr.write(`❌ ${err.message}\n`);
317
+ return { code: 2, findings, scanned: files.length };
318
+ }
319
+ throw err;
320
+ }
321
+ ledger.report();
322
+
323
+ return { code: findings.length > 0 ? 1 : 0, findings, scanned: files.length };
324
+ }
325
+
326
+ /* ------------------------------------------------------------------ *
327
+ * Self-test
328
+ * ------------------------------------------------------------------ */
329
+
330
+ function fixtureRoot(files: Record<string, string>): string {
331
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'det-time-'));
332
+ fs.mkdirSync(path.join(dir, SCAN_DIR), { recursive: true });
333
+ for (const [name, body] of Object.entries(files)) {
334
+ fs.writeFileSync(path.join(dir, SCAN_DIR, name), body);
335
+ }
336
+ return dir;
337
+ }
338
+
339
+ const CLEAN_GATE = ['import { asOf } from ', "'./_lib/as_of.js';", '\nconst now = asOf();\n'].join('');
340
+
341
+ export function selfTest(): number {
342
+ const made: string[] = [];
343
+ const run = (files: Record<string, string>): number => {
344
+ const d = fixtureRoot(files);
345
+ made.push(d);
346
+ return runGateCli(DEFAULT_ROOT, SELF, ['--quiet', '--root', d], DEFAULT_ROOT);
347
+ };
348
+ // Built by concatenation so this file's own source stays clean.
349
+ const rawNow = 'const t = ' + 'Date' + '.now();\n';
350
+ const rawNew = 'const d = new ' + 'Date();\n';
351
+
352
+ const cases: SelfTestCase[] = [
353
+ {
354
+ name: `rejects a planted ${PATTERNS[0]?.shown ?? ''} in a check_ script`,
355
+ expect: 'reject',
356
+ run: () => run({ 'check_planted.ts': rawNow }),
357
+ },
358
+ {
359
+ name: `rejects a planted bare ${PATTERNS[1]?.shown ?? ''} in a lint_ script`,
360
+ expect: 'reject',
361
+ run: () => run({ 'lint_planted.ts': rawNew }),
362
+ },
363
+ {
364
+ name: 'rejects a marker with no reason',
365
+ expect: 'reject',
366
+ run: () => run({ 'check_planted.ts': rawNow.trimEnd() + ' // ' + MARKER + '\n' }),
367
+ },
368
+ {
369
+ name: 'accepts a marker carrying a reason',
370
+ expect: 'accept',
371
+ run: () =>
372
+ run({
373
+ 'check_ok.ts': rawNow.trimEnd() + ' // ' + MARKER + ' elapsed-duration probe\n',
374
+ }),
375
+ },
376
+ {
377
+ name: 'accepts a mention inside a comment or a string literal',
378
+ expect: 'accept',
379
+ run: () =>
380
+ run({
381
+ 'check_prose.ts':
382
+ '// forbids ' + 'Date' + '.now()\nconst s = "new ' + 'Date()";\n',
383
+ }),
384
+ },
385
+ {
386
+ name: 'accepts a gate that routes through the seam',
387
+ expect: 'accept',
388
+ run: () => run({ 'check_ok.ts': CLEAN_GATE }),
389
+ },
390
+ {
391
+ name: 'rejects a moved scan root rather than reporting clean (exit 2)',
392
+ expect: 'reject',
393
+ run: () =>
394
+ runGateCli(
395
+ DEFAULT_ROOT,
396
+ SELF,
397
+ ['--quiet', '--root', path.join(DEFAULT_ROOT, 'no-such-root')],
398
+ DEFAULT_ROOT,
399
+ ),
400
+ },
401
+ ];
402
+
403
+ try {
404
+ return runSelfTest({
405
+ gate: 'lint_deterministic_time',
406
+ cases,
407
+ minCases: SELF_TEST_MIN_CASES,
408
+ minRejectCases: SELF_TEST_MIN_REJECT,
409
+ });
410
+ } finally {
411
+ for (const d of made) fs.rmSync(d, { recursive: true, force: true });
412
+ }
413
+ }
414
+
415
+ export function main(argv?: readonly string[]): number {
416
+ const args = argv ?? process.argv.slice(2);
417
+ if (args.includes('--self-test')) return selfTest();
418
+ const quiet = args.includes('--quiet');
419
+ const rootIdx = args.indexOf('--root');
420
+ const root = rootIdx >= 0 ? (args[rootIdx + 1] ?? DEFAULT_ROOT) : DEFAULT_ROOT;
421
+
422
+ const { code, findings, scanned } = check(root);
423
+ if (code === 2) return 2;
424
+
425
+ if (findings.length > 0) {
426
+ process.stdout.write('❌ gate script(s) read the wall clock directly:\n\n');
427
+ for (const f of findings) {
428
+ const why =
429
+ f.kind === 'bare-marker'
430
+ ? `\`${MARKER}\` with no reason`
431
+ : `raw \`${f.construct}\``;
432
+ process.stdout.write(` ${f.file}:${String(f.line)} — ${why}\n`);
433
+ }
434
+ process.stdout.write(
435
+ `\nA verdict that depends on the hour it ran is not reproducible from the\n` +
436
+ `commit. Route through \`asOf()\` in ${SEAM} — it resolves --as-of, AC_AS_OF,\n` +
437
+ `the commit date under CI, and the wall clock with an explicit WARN.\n` +
438
+ `If real elapsed time IS the subject, say so on the line:\n` +
439
+ ` // ${MARKER} <reason>\n`,
440
+ );
441
+ return 1;
442
+ }
443
+
444
+ if (!quiet) {
445
+ process.stdout.write(
446
+ `✅ no raw wall-clock read in ${String(scanned)} gate script(s) under ${SCAN_DIR}/.\n`,
447
+ );
448
+ }
449
+ return 0;
450
+ }
451
+
452
+ function _isCliEntry(): boolean {
453
+ if (process.argv[1] === undefined) return false;
454
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
455
+ if (import.meta.url === argvUrl) return true;
456
+ try {
457
+ return (
458
+ fs.realpathSync(fileURLToPath(import.meta.url)) ===
459
+ fs.realpathSync(path.resolve(process.argv[1]))
460
+ );
461
+ } catch {
462
+ return false;
463
+ }
464
+ }
465
+
466
+ if (_isCliEntry() || process.argv[1] === _HERE) {
467
+ process.exit(main());
468
+ }
469
+
470
+ export { SCAN_DIR, GATE_PREFIXES, SEAM, MARKER };