hecks 3.10.0 → 3.11.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 (481) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/bluebook/pizzas.bluebook +29 -0
  3. data/examples/pizzas/bluebook/pizzas.hecksagon +7 -0
  4. data/exe/hecks +4 -4
  5. data/lib/hecks/adapters/driven/d1.rb +2 -10
  6. data/lib/hecks/adapters/driven/heki.adapter +1 -1
  7. data/lib/hecks/adapters/driven/heki.rb +2 -12
  8. data/lib/hecks/adapters/driven/lambda.adapter +1 -1
  9. data/lib/hecks/adapters/driven/lambda.rb +3 -18
  10. data/lib/hecks/adapters/driven/postgres.rb +4 -11
  11. data/lib/hecks/adapters/driven/sqlite.adapter +1 -1
  12. data/lib/hecks/adapters/driven/sqlite.rb +2 -10
  13. data/lib/hecks/adapters/driving/admission.rb +46 -0
  14. data/lib/hecks/adapters/driving/cli/nesting.rb +36 -0
  15. data/lib/hecks/adapters/driving/cli/shorthand.rb +88 -0
  16. data/lib/hecks/adapters/driving/cli.rb +127 -0
  17. data/lib/hecks/adapters/driving/cli_runner/answers.rb +160 -0
  18. data/lib/hecks/adapters/driving/cli_runner/resolution.rb +155 -0
  19. data/lib/hecks/adapters/driving/cli_runner/settling.rb +120 -0
  20. data/lib/hecks/adapters/driving/cli_runner/streaming.rb +93 -0
  21. data/lib/hecks/adapters/driving/cli_runner/suggestions.rb +47 -0
  22. data/lib/hecks/adapters/driving/cli_runner.rb +69 -0
  23. data/lib/hecks/adapters/driving/command_request.rb +121 -0
  24. data/lib/hecks/adapters/driving/handle.rb +214 -0
  25. data/lib/hecks/adapters/driving/json.rb +136 -0
  26. data/lib/hecks/adapters/driving/launcher_options.rb +267 -0
  27. data/lib/hecks/adapters/driving/mcp/properties.rb +49 -0
  28. data/lib/hecks/adapters/driving/mcp/tool_calls.rb +116 -0
  29. data/lib/hecks/adapters/driving/mcp/tool_definitions/auditing.rb +53 -0
  30. data/lib/hecks/adapters/driving/mcp/tool_definitions/calling.rb +71 -0
  31. data/lib/hecks/adapters/driving/mcp/tool_definitions/reading.rb +99 -0
  32. data/lib/hecks/adapters/driving/mcp/tool_definitions.rb +18 -0
  33. data/lib/hecks/adapters/driving/mcp.rb +159 -0
  34. data/lib/hecks/adapters/driving/mcp_guide_cache.rb +78 -0
  35. data/lib/hecks/adapters/driving/mcp_scope/argument_policy.rb +97 -0
  36. data/lib/hecks/adapters/driving/mcp_scope/env_problems.rb +69 -0
  37. data/lib/hecks/adapters/driving/mcp_scope/presenter.rb +83 -0
  38. data/lib/hecks/adapters/driving/mcp_scope.rb +213 -0
  39. data/lib/hecks/adapters/driving/ruby/aggregate_module.rb +171 -0
  40. data/lib/hecks/adapters/driving/ruby/chapter.rb +91 -0
  41. data/lib/hecks/adapters/driving/ruby.rb +83 -0
  42. data/lib/hecks/adapters/driving/usage_cache.rb +144 -0
  43. data/lib/hecks/{doors.rb → adapters/driving.rb} +10 -6
  44. data/lib/hecks/behaviors/expectations/boot.rb +1 -1
  45. data/lib/hecks/bench/ruby_runner.rb +1 -1
  46. data/lib/hecks/bluebook/ask_resolution.rb +130 -0
  47. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +8 -2
  48. data/lib/hecks/bluebook/assembly/contracts/rules.rb +4 -2
  49. data/lib/hecks/bluebook/assembly/contracts/structure.rb +3 -1
  50. data/lib/hecks/bluebook/assembly/marks.rb +1 -0
  51. data/lib/hecks/bluebook/attribute.rb +1 -1
  52. data/lib/hecks/bluebook/behaviour/command.rb +13 -8
  53. data/lib/hecks/bluebook/behaviour/policy.rb +30 -0
  54. data/lib/hecks/bluebook/capabilities/attribute_values.rb +72 -0
  55. data/lib/hecks/bluebook/capabilities.rb +91 -9
  56. data/lib/hecks/bluebook/domain_port.rb +16 -4
  57. data/lib/hecks/bluebook/dsl/adapter_builder.rb +18 -6
  58. data/lib/hecks/bluebook/dsl/binding_proxy.rb +13 -0
  59. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/computed_sources.rb +98 -0
  60. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/fan_out_rows.rb +42 -0
  61. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/projected_fields.rb +14 -2
  62. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/provisions.rb +69 -3
  63. data/lib/hecks/bluebook/dsl/bluebook_builder/validation/with_projections.rb +17 -10
  64. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +5 -0
  65. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
  66. data/lib/hecks/bluebook/dsl/command_builder/mutations.rb +8 -1
  67. data/lib/hecks/bluebook/dsl/command_builder/operands.rb +121 -0
  68. data/lib/hecks/bluebook/dsl/command_builder.rb +2 -0
  69. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +10 -1
  70. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +45 -2
  71. data/lib/hecks/bluebook/dsl/policy_builder.rb +47 -10
  72. data/lib/hecks/bluebook/dsl/rule_reference.rb +7 -4
  73. data/lib/hecks/bluebook/dsl/world_builder.rb +1 -1
  74. data/lib/hecks/bluebook/expression/ast_json/emitters.rb +6 -0
  75. data/lib/hecks/bluebook/expression/ast_json.rb +9 -6
  76. data/lib/hecks/bluebook/expression/ast_reader.rb +14 -9
  77. data/lib/hecks/bluebook/expression/projection.json +36 -0
  78. data/lib/hecks/bluebook/expression/resolver/operations.rb +31 -0
  79. data/lib/hecks/bluebook/expression/resolver/parsing.rb +38 -5
  80. data/lib/hecks/bluebook/expression/resolver/scanning.rb +22 -5
  81. data/lib/hecks/bluebook/expression/resolver/values.rb +10 -0
  82. data/lib/hecks/bluebook/expression/resolver.rb +20 -1
  83. data/lib/hecks/bluebook/hecksagon.rb +23 -3
  84. data/lib/hecks/bluebook/lifecycle.rb +22 -3
  85. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +13 -1
  86. data/lib/hecks/bluebook/meta_validator/modes.rb +4 -1
  87. data/lib/hecks/bluebook/meta_validator/readings.rb +18 -1
  88. data/lib/hecks/bluebook/meta_validator/reconstruction/heads.rb +2 -1
  89. data/lib/hecks/bluebook/meta_validator/shapes.rb +5 -0
  90. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +1 -1
  91. data/lib/hecks/bluebook/meta_validator.rb +12 -12
  92. data/lib/hecks/bluebook/model_check/ask_checks.rb +71 -0
  93. data/lib/hecks/bluebook/model_check/policy_checks.rb +2 -1
  94. data/lib/hecks/bluebook/model_check/reference_checks.rb +70 -0
  95. data/lib/hecks/bluebook/model_check.rb +8 -2
  96. data/lib/hecks/bluebook/policy.rb +4 -2
  97. data/lib/hecks/bluebook/smoke_test.rb +1 -1
  98. data/lib/hecks/bluebook/synthesizer.rb +2 -0
  99. data/lib/hecks/bluebook.rb +1 -0
  100. data/lib/hecks/cli/command_table.rb +1 -1
  101. data/lib/hecks/cli/console.rb +2 -1
  102. data/lib/hecks/cli/document.rb +1 -1
  103. data/lib/hecks/cli/launcher_words.rb +4 -4
  104. data/lib/hecks/cli/mcp.rb +4 -4
  105. data/lib/hecks/cli/project_cli/launcher_source.rb +2 -2
  106. data/lib/hecks/cli/project_cli/templates.rb +5 -5
  107. data/lib/hecks/cli/project_cli.rb +9 -6
  108. data/lib/hecks/cli/run.rb +2 -2
  109. data/lib/hecks/cli/smoke_http/checks.rb +4 -1
  110. data/lib/hecks/cli/smoke_http/transport.rb +3 -3
  111. data/lib/hecks/cli/smoke_http.rb +3 -0
  112. data/lib/hecks/codemod.rb +5 -2
  113. data/lib/hecks/corpus/routes.rb +7 -0
  114. data/lib/hecks/corpus/rust.rb +3 -2
  115. data/lib/hecks/deploy/bluebook/deploy.bluebook +18 -2
  116. data/lib/hecks/doc/reference/rendering.rb +6 -3
  117. data/lib/hecks/forms/app/commands.rb +8 -7
  118. data/lib/hecks/forms/app/queries.rb +2 -1
  119. data/lib/hecks/forms/app.rb +1 -1
  120. data/lib/hecks/forms/record_renderer.rb +1 -1
  121. data/lib/hecks/framework/bluebook/privacy.bluebook +11 -0
  122. data/lib/hecks/fuzzing/concurrent_dispatch.rb +4 -1
  123. data/lib/hecks/fuzzing/failure_triage.rb +2 -1
  124. data/lib/hecks/fuzzing/mutation/run.rb +11 -4
  125. data/lib/hecks/fuzzing/properties/catalog.rb +6 -4
  126. data/lib/hecks/fuzzing/properties/guaranteed_by_construction.rb +18 -11
  127. data/lib/hecks/fuzzing/properties/guards.rb +1 -1
  128. data/lib/hecks/fuzzing/self_consistency/saga_redelivery.rb +1 -1
  129. data/lib/hecks/fuzzing/self_consistency.rb +6 -2
  130. data/lib/hecks/fuzzing/shrinker.rb +3 -1
  131. data/lib/hecks/fuzzing/value_generator.rb +19 -5
  132. data/lib/hecks/gate/stages.yml +4 -10
  133. data/lib/hecks/grammar/evolve.rb +1 -1
  134. data/lib/hecks/grammar/expression_operators.json +372 -0
  135. data/lib/hecks/grammar/operators.rb +3 -1
  136. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +10 -10
  137. data/lib/hecks/hecks/adapters/codebase/inspection/rubycritic.rb +35 -0
  138. data/lib/hecks/hecks/adapters/codebase/inspection.rb +104 -0
  139. data/lib/hecks/hecks/adapters/codebase/publishing.rb +2 -1
  140. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +12 -2
  141. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +2 -1
  142. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +1 -1
  143. data/lib/hecks/hecks/adapters/cost_explorer.rb +8 -5
  144. data/lib/hecks/hecks/adapters/deploy_toolchain/statuses.rb +2 -1
  145. data/lib/hecks/hecks/adapters/finding_github.rb +13 -6
  146. data/lib/hecks/hecks/adapters/first_admin.rb +2 -2
  147. data/lib/hecks/hecks/adapters/github_rulesets.rb +6 -3
  148. data/lib/hecks/hecks/adapters/in_process_boot.rb +1 -1
  149. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +1 -1
  150. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +10 -20
  151. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +28 -5
  152. data/lib/hecks/hecks/adapters/local_files.rb +2 -2
  153. data/lib/hecks/hecks/adapters/rehearsal/audit_report.rb +107 -0
  154. data/lib/hecks/hecks/adapters/rehearsal/census.rb +71 -0
  155. data/lib/hecks/hecks/adapters/rehearsal/declaration.rb +133 -0
  156. data/lib/hecks/hecks/adapters/rehearsal/environment.rb +83 -0
  157. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +142 -0
  158. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +96 -0
  159. data/lib/hecks/hecks/adapters/rehearsal/postgres_census.rb +100 -0
  160. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +69 -0
  161. data/lib/hecks/hecks/adapters/rehearsal/postgres_store.rb +129 -0
  162. data/lib/hecks/hecks/adapters/rehearsal/rows.rb +41 -0
  163. data/lib/hecks/hecks/adapters/rehearsal/rust_audit.rb +83 -0
  164. data/lib/hecks/hecks/adapters/rehearsal/subject.rb +104 -0
  165. data/lib/hecks/hecks/adapters/rehearsal.rb +54 -0
  166. data/lib/hecks/hecks/adapters/rehearsal_store.adapter +7 -0
  167. data/lib/hecks/hecks/adapters/rehearsal_store.rb +81 -0
  168. data/lib/hecks/hecks/adapters/terminal.rb +13 -11
  169. data/lib/hecks/hecks/codebase.behaviors +13 -1
  170. data/lib/hecks/hecks/codebase.bluebook +239 -5
  171. data/lib/hecks/hecks/custodian.behaviors +24 -6
  172. data/lib/hecks/hecks/custodian.bluebook +6 -1227
  173. data/lib/hecks/hecks/deploy.behaviors +1 -1
  174. data/lib/hecks/hecks/deploy.world +1 -3
  175. data/lib/hecks/hecks/hecks.behaviors +1 -1
  176. data/lib/hecks/hecks/hecks.hecksagon +53 -18
  177. data/lib/hecks/hecks/hecks.world +10 -10
  178. data/lib/hecks/hecks/rehearsal.bluebook +477 -0
  179. data/lib/hecks/hecks/site.behaviors +1 -1
  180. data/lib/hecks/hecks/site.world +0 -1
  181. data/lib/hecks/hecks/tooling.bluebook +1238 -0
  182. data/lib/hecks/indifferent_key.rb +20 -0
  183. data/lib/hecks/language/adapter.bluebook +13 -3
  184. data/lib/hecks/language/bluebook/aggregate.bluebook +23 -0
  185. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -0
  186. data/lib/hecks/language/bluebook/entity.bluebook +18 -0
  187. data/lib/hecks/language/bluebook/policy.bluebook +9 -1
  188. data/lib/hecks/language/bluebook/query.bluebook +1 -1
  189. data/lib/hecks/language/bluebook/vocabulary.bluebook +11 -4
  190. data/lib/hecks/language/hecksagon/domain_port.bluebook +1 -1
  191. data/lib/hecks/language/hecksagon/hecksagon.bluebook +22 -0
  192. data/lib/hecks/language/oidc.json +10 -0
  193. data/lib/hecks/language/port.bluebook +4 -4
  194. data/lib/hecks/literal.rb +12 -3
  195. data/lib/hecks/ports/key_vault.rb +7 -2
  196. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +21 -10
  197. data/lib/hecks/ports/persistence/plugins/era/postgres_era/boot.rb +4 -2
  198. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +2 -1
  199. data/lib/hecks/ports/persistence/repository_factory.rb +6 -3
  200. data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +29 -0
  201. data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +1 -1
  202. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  203. data/lib/hecks/projections/deploy/shared.rb +5 -2
  204. data/lib/hecks/projections/model/deviations.rb +2 -2
  205. data/lib/hecks/projections/model.rb +2 -2
  206. data/lib/hecks/projections/oidc.rb +13 -1
  207. data/lib/hecks/projections/shape.rb +5 -2
  208. data/lib/hecks/projections/site/cms_editor/attributes.rb +26 -6
  209. data/lib/hecks/projections/site/cms_editor/blocks.rb +157 -0
  210. data/lib/hecks/projections/site/cms_editor/checks.rb +14 -1
  211. data/lib/hecks/projections/site/cms_editor/clearing.rb +70 -0
  212. data/lib/hecks/projections/site/cms_editor/color.rb +124 -0
  213. data/lib/hecks/projections/site/cms_editor/composition.rb +42 -0
  214. data/lib/hecks/projections/site/cms_editor/destructive.rb +61 -0
  215. data/lib/hecks/projections/site/cms_editor/drafts.rb +102 -0
  216. data/lib/hecks/projections/site/cms_editor/hints.rb +74 -0
  217. data/lib/hecks/projections/site/cms_editor/icons.rb +86 -0
  218. data/lib/hecks/projections/site/cms_editor/key_kinds.rb +31 -0
  219. data/lib/hecks/projections/site/cms_editor/limits.rb +72 -0
  220. data/lib/hecks/projections/site/cms_editor/media.rb +1 -1
  221. data/lib/hecks/projections/site/cms_editor/moment.rb +34 -0
  222. data/lib/hecks/projections/site/cms_editor/palette.rb +115 -0
  223. data/lib/hecks/projections/site/cms_editor/pickers.rb +85 -0
  224. data/lib/hecks/projections/site/cms_editor/preview.rb +91 -0
  225. data/lib/hecks/projections/site/cms_editor/relations.rb +92 -0
  226. data/lib/hecks/projections/site/cms_editor/scale_checks.rb +66 -0
  227. data/lib/hecks/projections/site/cms_editor/scheduling.rb +150 -0
  228. data/lib/hecks/projections/site/cms_editor/schema.rb +96 -19
  229. data/lib/hecks/projections/site/cms_editor/setting.rb +52 -9
  230. data/lib/hecks/projections/site/cms_editor/targets.rb +86 -0
  231. data/lib/hecks/projections/site/cms_editor/templates/package.json.tmpl +18 -1
  232. data/lib/hecks/projections/site/cms_editor/templates/src/app.ts.tmpl +251 -57
  233. data/lib/hecks/projections/site/cms_editor/templates/src/assets.ts.tmpl +98 -0
  234. data/lib/hecks/projections/site/cms_editor/templates/src/auth/membership.ts.tmpl +32 -24
  235. data/lib/hecks/projections/site/cms_editor/templates/src/browser/app.css.tmpl +412 -0
  236. data/lib/hecks/projections/site/cms_editor/templates/src/browser/autosave.js.tmpl +144 -0
  237. data/lib/hecks/projections/site/cms_editor/templates/src/browser/blocks.js.tmpl +500 -0
  238. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_doc.js.tmpl +175 -0
  239. data/lib/hecks/projections/site/cms_editor/templates/src/browser/body_editor.js.tmpl +418 -0
  240. data/lib/hecks/projections/site/cms_editor/templates/src/browser/epoch.js.tmpl +61 -0
  241. data/lib/hecks/projections/site/cms_editor/templates/src/browser/forms.js.tmpl +210 -0
  242. data/lib/hecks/projections/site/cms_editor/templates/src/browser/lists.js.tmpl +40 -0
  243. data/lib/hecks/projections/site/cms_editor/templates/src/browser/main.js.tmpl +26 -0
  244. data/lib/hecks/projections/site/cms_editor/templates/src/browser/media_picker.js.tmpl +232 -0
  245. data/lib/hecks/projections/site/cms_editor/templates/src/browser/moments.js.tmpl +73 -0
  246. data/lib/hecks/projections/site/cms_editor/templates/src/browser/pickers.js.tmpl +152 -0
  247. data/lib/hecks/projections/site/cms_editor/templates/src/browser/preview.js.tmpl +98 -0
  248. data/lib/hecks/projections/site/cms_editor/templates/src/browser/shell.js.tmpl +140 -0
  249. data/lib/hecks/projections/site/cms_editor/templates/src/browser/toast.js.tmpl +66 -0
  250. data/lib/hecks/projections/site/cms_editor/templates/src/choices.ts.tmpl +99 -0
  251. data/lib/hecks/projections/site/cms_editor/templates/src/commands.ts.tmpl +78 -24
  252. data/lib/hecks/projections/site/cms_editor/templates/src/config.ts.tmpl +6 -0
  253. data/lib/hecks/projections/site/cms_editor/templates/src/flash.ts.tmpl +52 -0
  254. data/lib/hecks/projections/site/cms_editor/templates/src/host.ts.tmpl +19 -2
  255. data/lib/hecks/projections/site/cms_editor/templates/src/media/handler.ts.tmpl +31 -8
  256. data/lib/hecks/projections/site/cms_editor/templates/src/names.ts.tmpl +36 -0
  257. data/lib/hecks/projections/site/cms_editor/templates/src/schema.ts.tmpl +131 -2
  258. data/lib/hecks/projections/site/cms_editor/templates/src/ui/availability.ts.tmpl +15 -0
  259. data/lib/hecks/projections/site/cms_editor/templates/src/ui/block_list.js.tmpl +213 -0
  260. data/lib/hecks/projections/site/cms_editor/templates/src/ui/blocks.ts.tmpl +275 -0
  261. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_model.js.tmpl +8 -5
  262. data/lib/hecks/projections/site/cms_editor/templates/src/ui/detail.ts.tmpl +88 -0
  263. data/lib/hecks/projections/site/cms_editor/templates/src/ui/dialogs.ts.tmpl +43 -0
  264. data/lib/hecks/projections/site/cms_editor/templates/src/ui/fields.ts.tmpl +229 -34
  265. data/lib/hecks/projections/site/cms_editor/templates/src/ui/html.ts.tmpl +40 -81
  266. data/lib/hecks/projections/site/cms_editor/templates/src/ui/icons.ts.tmpl +15 -0
  267. data/lib/hecks/projections/site/cms_editor/templates/src/ui/input.ts.tmpl +29 -12
  268. data/lib/hecks/projections/site/cms_editor/templates/src/ui/links.ts.tmpl +100 -0
  269. data/lib/hecks/projections/site/cms_editor/templates/src/ui/moments.ts.tmpl +44 -0
  270. data/lib/hecks/projections/site/cms_editor/templates/src/ui/outline.ts.tmpl +53 -17
  271. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pages.ts.tmpl +178 -88
  272. data/lib/hecks/projections/site/cms_editor/templates/src/ui/paging.ts.tmpl +82 -0
  273. data/lib/hecks/projections/site/cms_editor/templates/src/ui/pickers.ts.tmpl +110 -0
  274. data/lib/hecks/projections/site/cms_editor/templates/src/ui/preview.ts.tmpl +87 -0
  275. data/lib/hecks/projections/site/cms_editor/templates/src/ui/related.ts.tmpl +97 -0
  276. data/lib/hecks/projections/site/cms_editor/templates/src/ui/schedule.ts.tmpl +160 -0
  277. data/lib/hecks/projections/site/cms_editor/templates/src/ui/shell.ts.tmpl +211 -0
  278. data/lib/hecks/projections/site/cms_editor/templates/src/ui/table.ts.tmpl +151 -0
  279. data/lib/hecks/projections/site/cms_editor/templates/src/ui/theme.js.tmpl +16 -0
  280. data/lib/hecks/projections/site/cms_editor/templates/src/ui/values.ts.tmpl +69 -0
  281. data/lib/hecks/projections/site/cms_editor/templates/src/ui/words.ts.tmpl +97 -0
  282. data/lib/hecks/projections/site/cms_editor/templates/src/ui/world.ts.tmpl +35 -0
  283. data/lib/hecks/projections/site/cms_editor/templates/tsconfig.json.tmpl +2 -1
  284. data/lib/hecks/projections/site/cms_editor/theme.rb +29 -0
  285. data/lib/hecks/projections/site/cms_editor/theme_checks.rb +57 -0
  286. data/lib/hecks/projections/site/cms_editor.rb +49 -23
  287. data/lib/hecks/projections/site/role_probe.rb +2 -0
  288. data/lib/hecks/projector/cli_audience.rb +2 -1
  289. data/lib/hecks/projector/cli_projector/listing.rb +1 -1
  290. data/lib/hecks/projector/cli_projector/option_specs.rb +1 -1
  291. data/lib/hecks/projector/docs_projector/closing.rb +1 -1
  292. data/lib/hecks/projector/docs_projector.rb +1 -1
  293. data/lib/hecks/projector/exporter/bindings.rb +40 -10
  294. data/lib/hecks/projector/exporter/capability_values.rb +55 -0
  295. data/lib/hecks/projector/narrate_projector/reactions.rb +1 -1
  296. data/lib/hecks/projector/target.rb +11 -0
  297. data/lib/hecks/projector.rb +32 -5
  298. data/lib/hecks/quality_control/adapters/github_checks.rb +12 -8
  299. data/lib/hecks/quality_control/adapters/github_issues.rb +8 -4
  300. data/lib/hecks/quality_control/cli/qa_open_pr.rb +2 -2
  301. data/lib/hecks/quality_control/cli/qa_sweep/checks/shrinking.rb +1 -1
  302. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +1 -1
  303. data/lib/hecks/quality_control/cli/qa_sweep.rb +1 -1
  304. data/lib/hecks/quality_control/quality_control.bluebook +6 -2
  305. data/lib/hecks/release/approval.rb +64 -0
  306. data/lib/hecks/router/{door.rb → aggregate_reader.rb} +5 -4
  307. data/lib/hecks/router/namespace_installer.rb +16 -16
  308. data/lib/hecks/router.rb +1 -1
  309. data/lib/hecks/runtime/best_effort.rb +22 -0
  310. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -2
  311. data/lib/hecks/runtime/command_interpreter.rb +3 -2
  312. data/lib/hecks/runtime/command_rules/emission.rb +1 -1
  313. data/lib/hecks/runtime/dispatcher.rb +4 -4
  314. data/lib/hecks/runtime/entity_element/location.rb +1 -1
  315. data/lib/hecks/runtime/event.rb +5 -0
  316. data/lib/hecks/runtime/identity.rb +7 -6
  317. data/lib/hecks/runtime/interpreting.rb +2 -1
  318. data/lib/hecks/runtime/invocation_builder.rb +1 -1
  319. data/lib/hecks/runtime/loader/boot_steps.rb +8 -5
  320. data/lib/hecks/runtime/loader.rb +10 -10
  321. data/lib/hecks/runtime/policy_interpreter/arguments.rb +7 -4
  322. data/lib/hecks/runtime/policy_interpreter/fan_out.rb +3 -3
  323. data/lib/hecks/runtime/policy_interpreter.rb +6 -6
  324. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -1
  325. data/lib/hecks/runtime/reaction_invocation.rb +1 -1
  326. data/lib/hecks/runtime/rebuild_sweep.rb +11 -1
  327. data/lib/hecks/runtime/registry/ask_verification.rb +35 -0
  328. data/lib/hecks/runtime/registry/hecksagon_rules.rb +10 -0
  329. data/lib/hecks/runtime/registry/merging.rb +1 -1
  330. data/lib/hecks/runtime/registry/providers.rb +16 -0
  331. data/lib/hecks/runtime/registry/read_repository.rb +6 -4
  332. data/lib/hecks/runtime/registry/verification.rb +4 -1
  333. data/lib/hecks/runtime/registry/world_defaults.rb +29 -0
  334. data/lib/hecks/runtime/registry.rb +1 -1
  335. data/lib/hecks/runtime/saga_interpreter/compensation.rb +1 -1
  336. data/lib/hecks/runtime/saga_interpreter/delivery.rb +4 -4
  337. data/lib/hecks/runtime/saga_interpreter/transitions.rb +1 -1
  338. data/lib/hecks/runtime/saga_interpreter.rb +3 -3
  339. data/lib/hecks/runtime/tenant_check.rb +5 -4
  340. data/lib/hecks/runtime/value/coercion.rb +2 -2
  341. data/lib/hecks/runtime/value/validation.rb +16 -4
  342. data/lib/hecks/runtime.rb +9 -9
  343. data/lib/hecks/rust_build/project_rust/target_ir.rb +1 -1
  344. data/lib/hecks/rust_build/wasm.rb +1 -1
  345. data/lib/hecks/rust_build/wasm_browser.rb +1 -1
  346. data/lib/hecks/rust_build.rb +11 -0
  347. data/lib/hecks/served_options.rb +53 -0
  348. data/lib/hecks/site/bluebook/site.bluebook +1 -0
  349. data/lib/hecks/storehouse/audit.rb +1 -1
  350. data/lib/hecks/storehouse/dispatching.rb +8 -6
  351. data/lib/hecks/storehouse/introspection.rb +2 -2
  352. data/lib/hecks/storehouse/querying.rb +6 -4
  353. data/lib/hecks/storehouse.rb +4 -4
  354. data/lib/hecks/tools/comment_style/source_file.rb +4 -1
  355. data/lib/hecks/tools/deploy_recipe_lint/fixtures.rb +4 -1
  356. data/lib/hecks/tools/lanes/rows.rb +6 -0
  357. data/lib/hecks/tools/oidc_manifests.rb +4 -5
  358. data/lib/hecks/tools/regeneration_run.rb +11 -4
  359. data/lib/hecks/tools/site_routes/editor_files.rb +12 -5
  360. data/lib/hecks/tools/tenant_provisioning.rb +2 -2
  361. data/lib/hecks/tools/tools_doc.rb +4 -4
  362. data/lib/hecks/version.rb +1 -1
  363. data/lib/hecks/vocabulary.rb +4 -4
  364. data/lib/hecks.rb +15 -15
  365. data/lib/rubocop/cop/hecks/env_dump.rb +69 -0
  366. data/lib/rubocop/cop/hecks/monotonic_duration.rb +53 -0
  367. data/lib/rubocop/cop/hecks/no_wall_clock_in_runtime.rb +34 -0
  368. data/lib/rubocop/cop/hecks/raw_shell_interpolation.rb +79 -0
  369. data/lib/rubocop/cop/hecks/sleep_in_spec.rb +34 -0
  370. data/lib/rubocop/cop/hecks/swallowed_rescue.rb +37 -0
  371. data/lib/rubocop/cop/hecks/symbol_string_key_mix.rb +50 -0
  372. data/lib/rubocop/cop/hecks/untyped_raise.rb +37 -0
  373. data/prebuilt/05c358d38d661a3774f813d49c66f5b68939af94432d66257a56f49ee2598994.marshal +0 -0
  374. data/prebuilt/26c40c61f09b09b11651c64668eda3ceb180f83cf2a3802d3033d2fd99ac841b.marshal +0 -0
  375. data/prebuilt/verdicts-230ac18c25abfd3d92ede032bee2661a4c2cd2773ab0cf0e2ae52546ba2f7af9.json +1 -0
  376. data/rust/.gitignore +6 -0
  377. data/rust/Cargo.toml +6 -0
  378. data/rust/build/src/binding_pass.rs +103 -0
  379. data/rust/build/src/cargo_sync.rs +6 -0
  380. data/rust/build/src/lineage_pass.rs +3 -3
  381. data/rust/build/src/main.rs +17 -5
  382. data/rust/build/src/pipeline.rs +48 -5
  383. data/rust/build/src/seams_pass.rs +123 -0
  384. data/rust/build/src/translation_pass.rs +167 -0
  385. data/rust/codegen/src/asks.rs +103 -0
  386. data/rust/codegen/src/commands.rs +13 -8
  387. data/rust/codegen/src/constraints.rs +25 -0
  388. data/rust/codegen/src/domain_generator.rs +2 -0
  389. data/rust/codegen/src/expr_emitter.rs +13 -0
  390. data/rust/codegen/src/json_codec.rs +54 -15
  391. data/rust/codegen/src/main.rs +1 -0
  392. data/rust/codegen/src/mutations.rs +128 -3
  393. data/rust/codegen/src/queries.rs +11 -2
  394. data/rust/codegen/src/reactions.rs +1 -1
  395. data/rust/codegen/src/types.rs +166 -8
  396. data/rust/host/HECKS_RELEASE +1 -1
  397. data/rust/host/src/api.rs +4 -4
  398. data/rust/host/src/bin/validate_harness.rs +43 -0
  399. data/rust/host/src/boundary_fuzz/expr_json.rs +2 -2
  400. data/rust/host/src/boundary_fuzz/ir.rs +1 -0
  401. data/rust/host/src/boundary_fuzz/server.rs +1 -1
  402. data/rust/host/src/checkout.rs +35 -19
  403. data/rust/host/src/commerce_ir.rs +408 -2
  404. data/rust/host/src/expr_json.rs +118 -0
  405. data/rust/host/src/mint.rs +1 -1
  406. data/rust/host/src/payments/tests.rs +27 -1
  407. data/rust/host/src/payments.rs +12 -4
  408. data/rust/host/src/query_step.rs +22 -4
  409. data/rust/host/src/reference_validate.rs +653 -108
  410. data/rust/host/src/resend.rs +2 -0
  411. data/rust/host/src/server.rs +19 -6
  412. data/rust/host/src/ui_schema.rs +132 -5
  413. data/rust/host/src/web/newsletter.rs +7 -8
  414. data/rust/host/src/web/newsletter_send.rs +38 -13
  415. data/rust/host/src/web/registrations.rs +229 -26
  416. data/rust/host/src/web.rs +3 -3
  417. data/rust/parser/src/emit.rs +38 -6
  418. data/rust/parser/src/expr/ast_json.rs +7 -1
  419. data/rust/parser/src/expr/resolver.rs +171 -6
  420. data/rust/parser/src/ir.rs +7 -0
  421. data/rust/parser/src/keywords.rs +24 -0
  422. data/rust/parser/src/main.rs +3 -0
  423. data/rust/parser/src/parse/aggregate.rs +2 -1
  424. data/rust/parser/src/parse/chapter.rs +2 -2
  425. data/rust/parser/src/parse/command.rs +2 -0
  426. data/rust/parser/src/parse/hecksagon.rs +5 -2
  427. data/rust/parser/src/parse/lifecycle.rs +81 -0
  428. data/rust/parser/src/parse/mod.rs +15 -1
  429. data/rust/parser/src/parse/policy.rs +13 -2
  430. data/rust/parser/src/parse/value_object.rs +13 -8
  431. data/rust/parser/src/ruby_value.rs +1 -1
  432. data/rust/src/exemplar/commands.rs +4 -4
  433. data/rust/src/exemplar/constraints.rs +1 -1
  434. data/rust/src/exemplar/json.rs +43 -1
  435. data/rust/src/kernel/cli.rs +7 -5
  436. data/rust/src/kernel/dispatch.rs +2 -2
  437. data/rust/src/kernel/dispatch_guard_tests.rs +1 -1
  438. data/rust/src/kernel/expr.rs +66 -3
  439. data/rust/src/kernel/expression_operators/arithmetic.rs +130 -5
  440. data/rust/src/kernel/expression_operators/text.rs +26 -2
  441. data/rust/src/kernel/json.rs +15 -0
  442. data/rust/src/kernel/mod.rs +1 -1
  443. data/rust/src/kernel/orchestrate.rs +54 -5
  444. data/rust/src/kernel/orchestrate_guard_tests.rs +67 -0
  445. data/rust/src/kernel/pattern.rs +60 -0
  446. data/rust/src/kernel/reference_lookup.rs +90 -7
  447. metadata +140 -38
  448. data/lib/hecks/doors/cli_door/nesting.rb +0 -34
  449. data/lib/hecks/doors/cli_door/shorthand.rb +0 -85
  450. data/lib/hecks/doors/cli_door.rb +0 -124
  451. data/lib/hecks/doors/cli_runner/answers.rb +0 -138
  452. data/lib/hecks/doors/cli_runner/resolution.rb +0 -146
  453. data/lib/hecks/doors/cli_runner/settling.rb +0 -115
  454. data/lib/hecks/doors/cli_runner/streaming.rb +0 -90
  455. data/lib/hecks/doors/cli_runner/suggestions.rb +0 -43
  456. data/lib/hecks/doors/cli_runner.rb +0 -66
  457. data/lib/hecks/doors/command_request.rb +0 -119
  458. data/lib/hecks/doors/handle.rb +0 -208
  459. data/lib/hecks/doors/json_door.rb +0 -132
  460. data/lib/hecks/doors/launcher_options.rb +0 -247
  461. data/lib/hecks/doors/mcp_door/properties.rb +0 -47
  462. data/lib/hecks/doors/mcp_door/tool_calls.rb +0 -113
  463. data/lib/hecks/doors/mcp_door/tool_definitions/auditing.rb +0 -51
  464. data/lib/hecks/doors/mcp_door/tool_definitions/calling.rb +0 -69
  465. data/lib/hecks/doors/mcp_door/tool_definitions/reading.rb +0 -97
  466. data/lib/hecks/doors/mcp_door/tool_definitions.rb +0 -15
  467. data/lib/hecks/doors/mcp_door.rb +0 -156
  468. data/lib/hecks/doors/mcp_door_scope/argument_policy.rb +0 -92
  469. data/lib/hecks/doors/mcp_door_scope/env_problems.rb +0 -55
  470. data/lib/hecks/doors/mcp_door_scope/presenter.rb +0 -78
  471. data/lib/hecks/doors/mcp_door_scope.rb +0 -201
  472. data/lib/hecks/doors/mcp_guide_cache.rb +0 -75
  473. data/lib/hecks/doors/ruby_door/aggregate_door.rb +0 -162
  474. data/lib/hecks/doors/ruby_door/chapter.rb +0 -89
  475. data/lib/hecks/doors/ruby_door.rb +0 -80
  476. data/lib/hecks/doors/usage_cache.rb +0 -139
  477. data/lib/hecks/projections/site/cms_editor/templates/src/ui/body_widget.js.tmpl +0 -282
  478. data/lib/hecks/projections/site/cms_editor/templates/src/ui/media_picker.js.tmpl +0 -109
  479. data/prebuilt/c28d6d9db14eea3e17161e9d9c262efee30b256cf97693a7cfd552bce24b2f7f.marshal +0 -0
  480. data/prebuilt/cb375cba61ca0dbe8ddb9739c306510fe05e5f4b7a9b6955caff8224c63ea0e0.marshal +0 -0
  481. data/prebuilt/verdicts-d6d584ad43b5f3cebf88aafbbdbf024c38574acf18e06adffbc555f7786b1c2f.json +0 -1
@@ -0,0 +1,98 @@
1
+ __BANNER__
2
+
3
+ // The editor's static files, for a signed-in editor only: its theme script (read from `src/ui/`),
4
+ // the stylesheet and script `npm run build` writes to `dist/`, and the Editor row's logo.
5
+ //
6
+ // Every file is sent with an ETag made from its bytes. A page asks for it as `name?v=<version>`
7
+ // where the version is the same hash, so a changed file has a new address and a request that names
8
+ // the current version may be kept for a year (`immutable`); any other request is revalidated and
9
+ // answered 304 when nothing changed. Files are `private`: they are behind the session, and a
10
+ // shared cache must not hold them for someone who has not signed in.
11
+ import { createHash } from "node:crypto";
12
+ import { existsSync, readFileSync, statSync } from "node:fs";
13
+ import { extname } from "node:path";
14
+
15
+ import { EDITOR } from "./config.ts";
16
+
17
+ const SOURCE = new URL("./ui/", import.meta.url);
18
+ const DIST = new URL("../dist/", import.meta.url);
19
+
20
+ /** The files read from `src/ui/`; everything else comes from `dist/`. */
21
+ const SOURCES = ["theme.js"];
22
+
23
+ /** A built file's name: plain characters and a `.js` or `.css` ending, so no path leaves `dist/`. */
24
+ const BUILT = /^[A-Za-z0-9][A-Za-z0-9._-]*\.(js|css)$/;
25
+
26
+ const TYPES: Record<string, string> = {
27
+ js: "text/javascript; charset=utf-8",
28
+ css: "text/css; charset=utf-8",
29
+ png: "image/png",
30
+ jpg: "image/jpeg",
31
+ jpeg: "image/jpeg",
32
+ webp: "image/webp",
33
+ gif: "image/gif",
34
+ avif: "image/avif",
35
+ svg: "image/svg+xml",
36
+ };
37
+
38
+ interface Held {
39
+ bytes: Buffer;
40
+ type: string;
41
+ version: string;
42
+ stamp: number;
43
+ }
44
+
45
+ const held = new Map<string, Held>();
46
+
47
+ function locate(name: string): URL | null {
48
+ if (SOURCES.includes(name)) return new URL(name, SOURCE);
49
+ if (!BUILT.test(name)) return null;
50
+ const built = new URL(name, DIST);
51
+ return existsSync(built) ? built : null;
52
+ }
53
+
54
+ function load(name: string): Held | null {
55
+ const where = name === "logo" ? logoPath() : locate(name);
56
+ if (!where || !existsSync(where)) return null;
57
+ const stamp = statSync(where).mtimeMs;
58
+ const known = held.get(name);
59
+ if (known && known.stamp === stamp) return known;
60
+ const bytes = readFileSync(where);
61
+ const type = TYPES[extname(String(where)).slice(1).toLowerCase()] ?? "application/octet-stream";
62
+ const made = { bytes, type, version: createHash("sha256").update(bytes).digest("hex").slice(0, 12), stamp };
63
+ held.set(name, made);
64
+ return made;
65
+ }
66
+
67
+ /** Where the row's logo is kept: a path from the server's working directory, or null when none is named. */
68
+ function logoPath(): string | null {
69
+ return EDITOR.logo === "" ? null : EDITOR.logo;
70
+ }
71
+
72
+ /** Whether `npm run build` has written the stylesheet and the script. */
73
+ export const isBuilt = (): boolean => existsSync(new URL("editor.css", DIST)) && existsSync(new URL("editor.js", DIST));
74
+
75
+ /** Whether the row names a logo that is there to be shown. */
76
+ export const hasLogo = (): boolean => load("logo") !== null;
77
+
78
+ /** The address of a file, with the version that makes it cacheable for good. */
79
+ export function assetUrl(name: string): string {
80
+ const version = load(name)?.version;
81
+ return `${EDITOR.basePath}/assets/${name}${version ? `?v=${version}` : ""}`;
82
+ }
83
+
84
+ /** Answers a request for one asset: the bytes, a 304 when the browser holds them, or a 404. */
85
+ export function serveAsset(name: string, request: Request): Response {
86
+ const file = load(name);
87
+ if (!file) return new Response("Not found.", { status: 404, headers: { "Content-Type": "text/plain" } });
88
+ const etag = `"${file.version}"`;
89
+ const headers = new Headers({
90
+ "Content-Type": file.type,
91
+ ETag: etag,
92
+ "X-Content-Type-Options": "nosniff",
93
+ "Cache-Control": new URL(request.url).searchParams.get("v") === file.version ? "private, max-age=31536000, immutable" : "private, no-cache",
94
+ });
95
+ if (name === "logo") headers.set("Content-Security-Policy", "sandbox");
96
+ if (request.headers.get("if-none-match") === etag) return new Response(null, { status: 304, headers });
97
+ return new Response(new Uint8Array(file.bytes), { headers });
98
+ }
@@ -24,6 +24,8 @@ export function authSecret(): string {
24
24
  export interface Membership {
25
25
  /** True while `email` holds an editor role on the host; false when it does not, or cannot be asked. */
26
26
  isAdmitted(email: string): Promise<boolean>;
27
+ /** The role `email` holds, for the header to show; null when it holds none. Answered from the same memory. */
28
+ roleOf?(email: string): Promise<string | null>;
27
29
  }
28
30
 
29
31
  export interface MembershipOptions {
@@ -33,47 +35,53 @@ export interface MembershipOptions {
33
35
  now?: () => number;
34
36
  }
35
37
 
36
- /** True when the host's members list holds `email` with an editor role and not disabled. */
37
- export function holdsRole(rows: unknown, email: string): boolean {
38
+ /** The editor role the host's members list gives `email`, or null when it holds none or is disabled. */
39
+ export function roleHeld(rows: unknown, email: string): string | null {
38
40
  const roles: readonly string[] = EDITOR.roles;
39
- return (
40
- Array.isArray(rows) &&
41
- rows.some(
42
- (row: any) =>
43
- typeof row?.email === "string" && row.email.trim().toLowerCase() === email && roles.includes(row.role) && row.disabled !== true,
44
- )
45
- );
41
+ const row = Array.isArray(rows)
42
+ ? rows.find(
43
+ (candidate: any) =>
44
+ typeof candidate?.email === "string" &&
45
+ candidate.email.trim().toLowerCase() === email &&
46
+ roles.includes(candidate.role) &&
47
+ candidate.disabled !== true,
48
+ )
49
+ : undefined;
50
+ return row ? String(row.role) : null;
46
51
  }
47
52
 
53
+ /** True when the host's members list holds `email` with an editor role and not disabled. */
54
+ export const holdsRole = (rows: unknown, email: string): boolean => roleHeld(rows, email) !== null;
55
+
48
56
  /** A membership check with its own one-minute memory. */
49
57
  export function membershipCheck(options: MembershipOptions = {}): Membership {
50
- const remembered = new Map<string, { admitted: boolean; until: number }>();
58
+ const remembered = new Map<string, { role: string | null; until: number }>();
51
59
  const now = options.now ?? Date.now;
52
60
  const send = options.fetch ?? fetch;
53
61
 
54
- async function ask(email: string): Promise<boolean> {
62
+ async function ask(email: string): Promise<string | null> {
55
63
  const secret = options.secret ?? authSecret();
56
- if (!secret) return false;
64
+ if (!secret) return null;
57
65
  const cookieName = resolveAccountCookieName(process.env.HECKS_SESSION_COOKIE || EDITOR.hostCookie);
58
66
  try {
59
67
  const res = await send(`${hostUrl({ url: options.url })}${EDITOR.membersPath}`, {
60
68
  headers: { Cookie: `${cookieName}=${accountToken(secret, email, TOKEN_TTL_SECONDS)}` },
61
69
  signal: AbortSignal.timeout(EDITOR.timeoutMs),
62
70
  });
63
- return res.ok && holdsRole(await res.json().catch(() => null), email);
71
+ return res.ok ? roleHeld(await res.json().catch(() => null), email) : null;
64
72
  } catch {
65
- return false;
73
+ return null;
66
74
  }
67
75
  }
68
76
 
69
- return {
70
- async isAdmitted(email: string): Promise<boolean> {
71
- const key = email.trim().toLowerCase();
72
- const hit = remembered.get(key);
73
- if (hit && hit.until > now()) return hit.admitted;
74
- const admitted = await ask(key);
75
- remembered.set(key, { admitted, until: now() + EDITOR.rememberMs });
76
- return admitted;
77
- },
78
- };
77
+ async function roleOf(email: string): Promise<string | null> {
78
+ const key = email.trim().toLowerCase();
79
+ const hit = remembered.get(key);
80
+ if (hit && hit.until > now()) return hit.role;
81
+ const role = await ask(key);
82
+ remembered.set(key, { role, until: now() + EDITOR.rememberMs });
83
+ return role;
84
+ }
85
+
86
+ return { roleOf, isAdmitted: async (email: string): Promise<boolean> => (await roleOf(email)) !== null };
79
87
  }
@@ -0,0 +1,412 @@
1
+ __CSS_BANNER__
2
+
3
+ /*
4
+ * The editor's stylesheet source. `npm run build` runs it through Tailwind, which finds the class
5
+ * names the pages and the browser code use (every class is written out whole, never built by
6
+ * joining strings, so the scanner sees it), and emits the daisyUI components those classes name.
7
+ *
8
+ * Colours come from the Editor row's accent (the generator's Palette moves each pair until it
9
+ * reaches WCAG AA) and are declared once, as two daisyUI themes: `editor-light`, and `editor-dark`
10
+ * for a visitor whose system prefers dark. The theme button sets `data-theme` on the root element.
11
+ */
12
+ @import "tailwindcss";
13
+ @plugin "daisyui" {
14
+ themes: false;
15
+ logs: false;
16
+ }
17
+ @plugin "@tailwindcss/typography";
18
+ @source "../ui";
19
+ @source ".";
20
+
21
+ @plugin "daisyui/theme" {
22
+ name: "editor-light";
23
+ default: true;
24
+ prefersdark: false;
25
+ color-scheme: light;
26
+ __LIGHT__
27
+ --radius-selector: 2rem;
28
+ --radius-field: 0.375rem;
29
+ --radius-box: 0.625rem;
30
+ --size-selector: 0.25rem;
31
+ --size-field: 0.225rem;
32
+ --border: 1px;
33
+ --depth: 0;
34
+ --noise: 0;
35
+ }
36
+
37
+ @plugin "daisyui/theme" {
38
+ name: "editor-dark";
39
+ default: false;
40
+ prefersdark: true;
41
+ color-scheme: dark;
42
+ __DARK__
43
+ --radius-selector: 2rem;
44
+ --radius-field: 0.375rem;
45
+ --radius-box: 0.625rem;
46
+ --size-selector: 0.25rem;
47
+ --size-field: 0.225rem;
48
+ --border: 1px;
49
+ --depth: 0;
50
+ --noise: 0;
51
+ }
52
+
53
+ @theme {
54
+ --font-sans: ui-sans-serif, "Avenir Next", "Segoe UI", Roboto, system-ui, sans-serif;
55
+ --font-serif: Charter, "Iowan Old Style", "Palatino Linotype", Georgia, serif;
56
+ --text-xs: 0.8125rem;
57
+ --text-sm: 0.9375rem;
58
+ --text-base: 1.0625rem;
59
+ --text-lg: 1.25rem;
60
+ --text-xl: 1.5rem;
61
+ --text-2xl: 1.875rem;
62
+ }
63
+
64
+ @theme inline {
65
+ --color-muted: var(--ed-muted);
66
+ --color-edge: var(--ed-edge);
67
+ --color-soft: var(--ed-soft);
68
+ --color-ok-bg: var(--ed-ok-bg);
69
+ --color-warn-bg: var(--ed-warn-bg);
70
+ --color-danger-bg: var(--ed-danger-bg);
71
+ }
72
+
73
+ @layer base {
74
+ html {
75
+ -webkit-text-size-adjust: 100%;
76
+ scroll-padding-top: 4.5rem;
77
+ }
78
+
79
+ body {
80
+ font-family: var(--font-sans);
81
+ font-size: var(--text-sm);
82
+ line-height: 1.5;
83
+ -webkit-font-smoothing: antialiased;
84
+ }
85
+
86
+ h1, h2, h3, h4 {
87
+ font-family: var(--font-sans);
88
+ font-weight: 650;
89
+ letter-spacing: -0.015em;
90
+ line-height: 1.2;
91
+ }
92
+
93
+ :focus-visible {
94
+ outline: 2px solid var(--color-primary);
95
+ outline-offset: 2px;
96
+ }
97
+
98
+ main:focus {
99
+ outline: none;
100
+ }
101
+
102
+ [hidden] {
103
+ display: none !important;
104
+ }
105
+
106
+ main a:not([class]) {
107
+ color: var(--color-primary);
108
+ text-underline-offset: 0.18em;
109
+ }
110
+
111
+ .icon {
112
+ width: 1.125rem;
113
+ height: 1.125rem;
114
+ flex: none;
115
+ fill: none;
116
+ stroke: currentColor;
117
+ stroke-width: 1.75;
118
+ stroke-linecap: round;
119
+ stroke-linejoin: round;
120
+ }
121
+
122
+ table {
123
+ font-variant-numeric: tabular-nums;
124
+ }
125
+
126
+ /* A fieldset will not shrink below its content by default, so one row that does not wrap (the
127
+ writing surface's toolbar, which scrolls on a phone) would widen the whole page. */
128
+ fieldset {
129
+ min-inline-size: 0;
130
+ }
131
+ }
132
+
133
+ @layer components {
134
+ /* Read-only and written text share one typeface and one rhythm: a serif page, a sans interface. */
135
+ .prose {
136
+ --tw-prose-body: var(--color-base-content);
137
+ --tw-prose-headings: var(--color-base-content);
138
+ --tw-prose-lead: var(--ed-muted);
139
+ --tw-prose-links: var(--color-primary);
140
+ --tw-prose-bold: var(--color-base-content);
141
+ --tw-prose-counters: var(--ed-muted);
142
+ --tw-prose-bullets: var(--ed-muted);
143
+ --tw-prose-hr: var(--ed-edge);
144
+ --tw-prose-quotes: var(--ed-muted);
145
+ --tw-prose-quote-borders: var(--ed-edge);
146
+ --tw-prose-captions: var(--ed-muted);
147
+ --tw-prose-code: var(--color-base-content);
148
+ --tw-prose-th-borders: var(--ed-edge);
149
+ --tw-prose-td-borders: var(--color-base-300);
150
+ max-width: 66ch;
151
+ font-family: var(--font-serif);
152
+ font-size: 1.125rem;
153
+ line-height: 1.65;
154
+ overflow-wrap: anywhere;
155
+ }
156
+
157
+ .prose :where(h1, h2, h3, h4, figcaption) {
158
+ font-family: var(--font-sans);
159
+ }
160
+
161
+ .prose :where(h1) { font-size: 1.875rem; }
162
+ .prose :where(h2) { font-size: 1.5rem; }
163
+ .prose :where(h3) { font-size: 1.25rem; }
164
+ .prose :where(h4) { font-size: 1.0625rem; }
165
+
166
+ .prose :where(code)::before,
167
+ .prose :where(code)::after {
168
+ content: none;
169
+ }
170
+
171
+ .prose :where(code) {
172
+ padding: 0.1em 0.35em;
173
+ border-radius: 4px;
174
+ background: color-mix(in srgb, var(--color-base-content) 8%, var(--color-base-100));
175
+ font-size: 0.85em;
176
+ font-weight: 500;
177
+ }
178
+
179
+ .prose :where(blockquote) {
180
+ font-weight: 400;
181
+ }
182
+
183
+ .prose :where(blockquote p:first-of-type)::before,
184
+ .prose :where(blockquote p:last-of-type)::after {
185
+ content: none;
186
+ }
187
+
188
+ .prose [data-align="left"] { text-align: left; }
189
+ .prose [data-align="center"] { text-align: center; }
190
+ .prose [data-align="right"] { text-align: right; }
191
+ .prose [data-align="justify"] { text-align: justify; }
192
+ .prose [data-indent="1"] { margin-left: 2rem; }
193
+ .prose [data-indent="2"] { margin-left: 4rem; }
194
+ .prose [data-indent="3"] { margin-left: 6rem; }
195
+ .prose [data-indent="4"] { margin-left: 8rem; }
196
+ .prose [data-indent="5"] { margin-left: 10rem; }
197
+ .prose [data-indent="6"] { margin-left: 12rem; }
198
+ .prose [data-indent="7"] { margin-left: 14rem; }
199
+ .prose [data-indent="8"] { margin-left: 16rem; }
200
+ .prose li[data-depth="1"] { margin-left: 1.5rem; }
201
+ .prose li[data-depth="2"] { margin-left: 3rem; }
202
+ .prose li[data-depth="3"] { margin-left: 4.5rem; }
203
+ .prose li[data-depth="4"] { margin-left: 6rem; }
204
+ .prose li[data-depth="5"] { margin-left: 7.5rem; }
205
+
206
+ .prose .body-media {
207
+ display: inline-block;
208
+ padding: 0.2em 0.6em;
209
+ border: 1px dashed var(--ed-edge);
210
+ border-radius: 4px;
211
+ color: var(--ed-muted);
212
+ font-family: var(--font-sans);
213
+ font-size: 0.85em;
214
+ }
215
+
216
+ /* ProseMirror's own rules, written here because the editor is told to inject none (a strict
217
+ content security policy blocks a style element the script adds). */
218
+ .ProseMirror {
219
+ position: relative;
220
+ outline: none;
221
+ word-wrap: break-word;
222
+ white-space: pre-wrap;
223
+ white-space: break-spaces;
224
+ font-variant-ligatures: none;
225
+ font-feature-settings: "liga" 0;
226
+ }
227
+
228
+ .ProseMirror pre {
229
+ white-space: pre-wrap;
230
+ }
231
+
232
+ .ProseMirror li {
233
+ position: relative;
234
+ }
235
+
236
+ .ProseMirror-hideselection *::selection,
237
+ .ProseMirror-hideselection *::-moz-selection {
238
+ background: transparent;
239
+ }
240
+
241
+ .ProseMirror-hideselection {
242
+ caret-color: transparent;
243
+ }
244
+
245
+ .ProseMirror .ProseMirror-selectednode {
246
+ outline: 2px solid var(--color-primary);
247
+ outline-offset: 3px;
248
+ }
249
+
250
+ .ProseMirror-gapcursor {
251
+ position: absolute;
252
+ display: none;
253
+ pointer-events: none;
254
+ }
255
+
256
+ .ProseMirror-gapcursor::after {
257
+ content: "";
258
+ display: block;
259
+ position: absolute;
260
+ top: -2px;
261
+ width: 20px;
262
+ border-top: 1px solid var(--color-base-content);
263
+ animation: caret 1.1s steps(2, start) infinite;
264
+ }
265
+
266
+ .ProseMirror-focused .ProseMirror-gapcursor {
267
+ display: block;
268
+ }
269
+
270
+ img.ProseMirror-separator {
271
+ display: inline !important;
272
+ border: none !important;
273
+ margin: 0 !important;
274
+ }
275
+
276
+ .ProseMirror p.is-editor-empty:first-child::before {
277
+ content: attr(data-placeholder);
278
+ float: left;
279
+ height: 0;
280
+ color: var(--ed-muted);
281
+ pointer-events: none;
282
+ }
283
+
284
+ .ProseMirror :where(ul, ol) {
285
+ margin: 0;
286
+ padding-left: 1.5em;
287
+ }
288
+
289
+ .ProseMirror :where(ul, ol)[data-list-indent="1"] { margin-left: 1.5em; }
290
+ .ProseMirror :where(ul, ol)[data-list-indent="2"] { margin-left: 3em; }
291
+ .ProseMirror :where(ul, ol)[data-list-indent="3"] { margin-left: 4.5em; }
292
+ .ProseMirror :where(ul, ol)[data-list-indent="4"] { margin-left: 6em; }
293
+ .ProseMirror :where(ul, ol)[data-list-indent="5"] { margin-left: 7.5em; }
294
+ .ProseMirror ul { list-style: disc; }
295
+ .ProseMirror ul[data-list-indent="1"] { list-style: circle; }
296
+ .ProseMirror ul[data-list-indent="2"] { list-style: square; }
297
+ .ProseMirror ol { list-style: decimal; }
298
+ .ProseMirror ol[data-list-indent="1"] { list-style: lower-alpha; }
299
+ .ProseMirror ol[data-list-indent="2"] { list-style: lower-roman; }
300
+
301
+ .ProseMirror [data-align="left"] { text-align: left; }
302
+ .ProseMirror [data-align="center"] { text-align: center; }
303
+ .ProseMirror [data-align="right"] { text-align: right; }
304
+ .ProseMirror [data-align="justify"] { text-align: justify; }
305
+ .ProseMirror [data-indent="1"] { margin-left: 2rem; }
306
+ .ProseMirror [data-indent="2"] { margin-left: 4rem; }
307
+ .ProseMirror [data-indent="3"] { margin-left: 6rem; }
308
+ .ProseMirror [data-indent="4"] { margin-left: 8rem; }
309
+ .ProseMirror [data-indent="5"] { margin-left: 10rem; }
310
+ .ProseMirror [data-indent="6"] { margin-left: 12rem; }
311
+ .ProseMirror [data-indent="7"] { margin-left: 14rem; }
312
+ .ProseMirror [data-indent="8"] { margin-left: 16rem; }
313
+
314
+ @keyframes caret {
315
+ to {
316
+ visibility: hidden;
317
+ }
318
+ }
319
+
320
+ /* Motion answers an action: a dialog opening, a notice arriving, a row that just changed. */
321
+ @keyframes settle {
322
+ from {
323
+ background-color: var(--ed-soft);
324
+ }
325
+ }
326
+
327
+ .just-changed {
328
+ animation: settle 1.6s ease-out;
329
+ }
330
+
331
+ /* The current item of the navigation: the accent marks where you are. */
332
+ .menu li > a[aria-current="page"] {
333
+ background: var(--ed-soft) !important;
334
+ color: var(--color-primary) !important;
335
+ font-weight: 600;
336
+ }
337
+
338
+ .menu a[aria-current="page"] .text-muted {
339
+ color: inherit;
340
+ }
341
+
342
+ /* A toggle button of the writing surface's toolbar that is on. */
343
+ .btn[aria-pressed="true"] {
344
+ background: var(--ed-soft);
345
+ color: var(--color-primary);
346
+ }
347
+ }
348
+
349
+ /* Outside the layers, so they win over the component library's own: a plain button is a ruled outline
350
+ on the page; the filled ones are the primary action and the dangerous one. */
351
+ .btn:not([class*="btn-"]) {
352
+ --btn-bg: var(--color-base-100);
353
+ --btn-border: var(--ed-edge);
354
+ }
355
+
356
+ /* The component library fades an inactive tab to half its ink, which is under 4.5:1 on a light page. */
357
+ .tab:not(.tab-active):not(:hover) {
358
+ color: var(--ed-muted);
359
+ }
360
+
361
+ /* On a phone or any touch screen a control is at least 44 by 44 CSS pixels (a fingertip, and past the
362
+ 24 pixel floor of WCAG 2.2's target size): buttons, fields, tabs, menu rows, the sort buttons of a
363
+ table's head and the links in its rows. */
364
+ @media (pointer: coarse), (max-width: 40rem) {
365
+ .btn,
366
+ .tab,
367
+ .menu a {
368
+ min-height: 2.75rem;
369
+ }
370
+
371
+ .input,
372
+ .select,
373
+ .file-input {
374
+ height: 2.75rem;
375
+ }
376
+
377
+ .btn-square,
378
+ .tab {
379
+ min-width: 2.75rem;
380
+ justify-content: center;
381
+ }
382
+
383
+ header a,
384
+ th button,
385
+ th a,
386
+ td a {
387
+ display: inline-flex;
388
+ align-items: center;
389
+ min-height: 2.75rem;
390
+ min-width: 2.75rem;
391
+ }
392
+ }
393
+
394
+ /* The picture picker stands in the window, never taller than the part of it the page's bars leave
395
+ (the script narrows this to the sticky action bar's top edge and the on-screen keyboard), scrolls
396
+ inside itself, and keeps clear of the notch and the home bar. */
397
+ .picker-panel {
398
+ max-height: calc(100dvh - 5rem - env(safe-area-inset-bottom, 0px));
399
+ max-width: min(42rem, calc(100vw - 1rem - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)));
400
+ box-sizing: border-box;
401
+ }
402
+
403
+ @media (prefers-reduced-motion: reduce) {
404
+ *,
405
+ *::before,
406
+ *::after {
407
+ animation-duration: 0.01ms !important;
408
+ animation-iteration-count: 1 !important;
409
+ transition-duration: 0.01ms !important;
410
+ scroll-behavior: auto !important;
411
+ }
412
+ }