poetry-ui 0.1.1 → 0.1.3

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -0
  3. data/README.md +2 -2
  4. data/THIRD_PARTY_NOTICES.md +29 -0
  5. data/app/components/poetry/ui/dialog/component.rb +1 -1
  6. data/app/controllers/poetry/ui/llms_controller.rb +5 -1
  7. data/app/helpers/poetry/ui/components_helper.rb +4 -0
  8. data/app/helpers/poetry/ui/form_builder/type_inference.rb +5 -3
  9. data/app/helpers/poetry/ui/form_builder.rb +3 -0
  10. data/config/component_registry.yml +96 -1
  11. data/lib/generators/poetry/agents_section.rb +58 -21
  12. data/lib/generators/poetry/install/install_generator.rb +199 -17
  13. data/lib/generators/poetry/scaffold_templates/scaffold_templates_generator.rb +5 -3
  14. data/lib/generators/poetry/scaffold_templates/templates/_form.html.erb.tt +10 -56
  15. data/lib/generators/poetry/skill/templates/poetry-component/SKILL.md +25 -0
  16. data/lib/generators/poetry/skill/templates/poetry-design/references/audit.md +5 -3
  17. data/lib/generators/poetry/skills_section.rb +33 -5
  18. data/lib/poetry/ui/reset_floor.rb +199 -0
  19. data/lib/poetry/ui/version.rb +1 -1
  20. data/lib/poetry/ui.rb +51 -6
  21. data/lib/tasks/poetry/check.rake +74 -14
  22. data/lib/tasks/poetry/design.rake +12 -1
  23. data/lib/tasks/poetry/registry.rake +22 -0
  24. data/lib/tasks/poetry/stimulus.rake +29 -0
  25. data/lib/tasks/poetry/verify.rake +18 -1
  26. data/reset/reset.css +154 -0
  27. data/themes/default.css +0 -11
  28. data/themes/luma.css +0 -11
  29. data/themes/lyra.css +0 -11
  30. data/themes/maia.css +0 -11
  31. data/themes/mira.css +0 -11
  32. data/themes/nova.css +0 -11
  33. data/themes/rhea.css +0 -11
  34. data/themes/sera.css +0 -11
  35. data/themes/vega.css +0 -11
  36. metadata +7 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be9d330390d3bf48c36cd783dfaf4fdd00a0cf6073b9b8944caf10104abf66b7
4
- data.tar.gz: 99aa8e106788b9a8d597b149e68c8d6353c7a49876a32969f106327a7d1be813
3
+ metadata.gz: d60854dfc65e3eb23ea1bdb0541a9e6290d69d8712ec913e1df746667def08f2
4
+ data.tar.gz: ede37b77181f5842f3d6d484757d1c38a08d3b2883596dc9e65daf4d6f54e27b
5
5
  SHA512:
6
- metadata.gz: 6f60d8c522645d60374997d18bcea9ff4baaeb2f5fd888374966d008ef362f216b7cb0fa2f022f4f6b2127c10aa6750de2e37546c9aec380b37e79a909cee29a
7
- data.tar.gz: 1b8bf7807b8f0836d702577677038fd1d42a5b2a8283579eee0471bd20026de193487d42ebe5861615fa9b2b1969087e1201a7fb5791b6715c4d6cdec63824d9
6
+ metadata.gz: 8ca0c7adb7ee3844f1debc06a974b6103b3414fb79d9bc3a18ce237591d260b99352efd91337b90ec5cb6d840fc7cb2d3d8cb48eb2c0c8014cb2b7f55768ee37
7
+ data.tar.gz: c828928ac82441d518eaf35dc879eb8e134e070b88ca32c6559add9ec5d48786f126d4a3bfac5784a1413a4ee29328ff38707ae540a74b04c26ad50c7d770bdf
data/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.3] - 2026-09-13
4
+
5
+ ### Fixed
6
+
7
+ - `poetry_webmcp_form ... do |form|` is no longer a yieldless block to `poetry check`: the registry's helpers section now says the helper yields the form builder, as the helper's own example always showed.
8
+ - `bin/rails poetry:check` accepts the app's own `poetry_*` helper methods (the adapter `poetry:pagination` copies in, a wrapper of the host's own): their names come from `app/helpers` boot-free, their options and blocks are their own, and the wiring rules still apply. A composed trigger's `do |wiring|` is no longer flagged either (poetry-core 0.1.3).
9
+
10
+ ## [0.1.2] - 2026-09-13
11
+
12
+ ### Added
13
+
14
+ - The install names the theme it puts in the slot: on a first install or an explicit `--theme`, one line says which theme fills `poetry/style-default.css`, that the slot name never changes, and that the file's first line names the theme. The Theming and Installation guides say the same, for the reader who opens a file called default and finds vega.
15
+
16
+ - `poetry:install` and `poetry:skill` say so when the host gitignores `.claude/skills`: the skills still serve that checkout, and the note names the refresh command teammates and CI run (`bin/rails g poetry:skill`) or the alternative of un-ignoring the directory. Asked of git only; no git, no repository, or a tracked directory stay silent.
17
+
18
+ - App components are first-class on the booted surfaces. A component the app defines on the DSL with `helper :name` renders through that helper, `poetry:check` lints it under that name with its own contract, `/poetry/llms.txt` and `llms-full.txt` list it under an App components section with its agent rules, and `poetry:skill` writes a `references/app.md` with a menu line. The AGENTS.md section and the poetry-component skill teach the declaration. The MCP server's `check` tool learns the declared helpers from source, so it agrees the helper exists; its contracts and the runtime skill map stay gem-only (boot-free by design).
19
+
20
+ - `poetry:install --no-preflight`, for an app that imports Tailwind without preflight: vendors the reset floor (`poetry/reset.css`, Tailwind's preflight at zero specificity, generated from the pinned binary and gated against it) into `layer(base)` ahead of the theme, and on a fresh entry writes the split no-preflight import. A plain re-run keeps the floor once installed. Measured against the golden corpus: without preflight two thirds of the components render differently even behind a modern reset, so the floor is what keeps them whole; `POETRY_PREFLIGHT=0 rake test:visual` proves it. The installer and `poetry:check` warn (`preflight-missing`) when an entry imports neither preflight nor the floor.
21
+ - `poetry:design:overrides` counts only a rule against a theme-owned `cn-*` name (a gem dictionary's or the installed fragment's own) as an override. A host kit's own `cn-*` dictionary, or a page helper class in that namespace, is no longer reported as undeclared drift; a blanket declaration written to silence those now shows as stale.
22
+ - `bin/rails poetry:stimulus:manifest` writes the app's controllers manifest (`config/controllers_manifest.json`, the file a gem commits) from `app/javascript/controllers`; registered at boot, a host controller validates like poetry's (the DSL by Symbol at class load, template wiring in `poetry:check`, its API in the registry). A controller the reader cannot describe is named and stays unvalidated until its entry is written by hand in the same file, where regeneration keeps it. `poetry:check` warns (`manifest-stale`) and `poetry:verify` fails when the entries the reader produced no longer match the sources; hand-written entries never count.
23
+ - `bin/rails poetry:registry` writes the app's own components to `config/component_registry.yml`, the path a gem's registry lives at, so the MCP server and the runtime skill find them boot-free with full contracts and agent rules. Opt-in; once written, `poetry:check` warns (`registry-stale`) and `poetry:verify` fails when the file no longer matches the classes.
24
+
25
+ ### Changed
26
+
27
+ - The reset floor's header and the Installation guide say exactly what wins: an unlayered host rule always, a host rule in `layer(base)` when it comes after the floor's import, and `[hidden]` keeps preflight's `!important` on purpose. `poetry:verify` names the remedy when a kit's own `cn-*` class is not in the compiled CSS. The AGENTS.md section spells JSON output as `POETRY_CHECK_JSON=1`.
28
+
29
+ - The upgrade path holds on real hosts: `--charts` is remembered by the vendored `poetry/charts.css`, so a plain re-run refreshes the chart files and a theme switch swaps the chart fragment with the theme; the superseded 0.1.1 tokens import converges however it was written (indented, annotated, or with a carriage return, which it keeps); every `eval_gemfile` spelling is read before `herb` is added; the Claude Code skills are refreshed like the vendored CSS, without an overwrite prompt (`--skip` keeps a hand-edited one); an AGENTS.md begin marker without its end is an error naming the file, a byte-identical section reports `identical`, the section is written in the file's own line endings, and only the first section is replaced.
30
+
31
+ - `poetry:check` hands the runner the app root, so the mailer exemption and the design tier judge a template by its path inside the app; an unreadable file is a warning in the report, not a crash of the task.
32
+
33
+ - `poetry:check` reports `registry-invalid` when `config/component_registry.yml` exists but is not a registry (empty, malformed, the wrong shape), naming `bin/rails poetry:registry` as the fix; the committed registry regenerates with every helper named.
34
+
35
+ - The scaffold form template is the form builder's: `form_with(model:, builder: Poetry::Ui::FormBuilder)` and one `f.input` per attribute, the control inferred from the column, the name and the validations, with the template adding only what the generator knows and the model cannot say (`as: :text` for rich text, `multiple: true` for many attachments, `required: true` from `null: false`). The gem's reference CRUD form now follows the gem's own first rule about forms. A host that installed the templates before keeps its copy (re-runs never overwrite); delete `lib/templates/erb/scaffold/_form.html.erb.tt` and re-run `poetry:scaffold_templates` for the builder version. On the way, two inference gaps in the builder: `has_many_attached` attributes infer a file input (the plural responder), and `website` / `permalink` infer a URL input like `url` does.
36
+
37
+ - The form builder's agent rules say which parts a builder field renders (`field-label`, `field-description` for the hint, `field-error`), so llms.txt's Forms section, the registry, the MCP server and the skill all name the slots a wiring test asserts on; the Testing guide says the same.
38
+
39
+ - `poetry:check` treats mailer templates as email, not pages: under a `*_mailer/` directory or in the mailer layout the raw-color rule stays quiet (an inline hex is the only paint a mail client honours) and the design tier skips them; every other rule runs there as before. The AGENTS.md section says so.
40
+
41
+ - An off-list variant or a missing required option now raises at construction in development and test (poetry-core's runtime values tier) instead of rendering unstyled; the AGENTS.md section says so beside the check.
42
+ - poetry-ui pins its components to `css_mode :tailwind`, and the class-name merger follows: a host's global `BemMerger` (for a kit of its own) never reaches poetry-ui's utility conflict resolution. A host's global `css_mode = :bem` (for a kit of its own on the DSL) no longer strips poetry-ui's styling; the two render side by side. The seeded initializer's comment says so instead of offering `:bem` as a poetry-ui option.
43
+ - `poetry:check` and the AGENTS.md census find registry roots by convention (every loaded engine with a published registry, then the app's own file) and name no gem; poetry-charts is no longer special-cased, and any engine built on the DSL that commits a registry joins the check the same way.
44
+ - `poetry:install` imports `tokens.css` into `layer(theme)`, so a token the host already declares (`--primary`, `--accent`, `--muted`, ...) keeps its value whatever the order in the Tailwind entry, and that value now reaches Poetry's components too. Before, the appended import landed after the host's own `:root` and took the same names over: an app's brand color vanished before a single Poetry component rendered. A re-run rewrites the earlier unlayered import line in place.
45
+ - `poetry:install` reports, before writing anything, every Poetry token name and theme key the app's stylesheets already declare, with the file and line and what Poetry paints with that role. It never blocks. `poetry:check` repeats the report as `token-collision` warnings.
46
+
47
+ - The WebMCP agent-focus rules (`:tool-form-active`, `:tool-submit-active`) leave the nine theme fragments, where they were identical, for poetry-agent's own stylesheet; `poetry:install` vendors it into `layer(base)` when that gem is bundled. A host without poetry-agent no longer carries them, nor the two warnings the CSS optimizer printed for the origin-trial pseudo-classes on every minified build (the Rails Tailwind task minifies by default, so every build and watch run).
48
+
49
+ ### Fixed
50
+
51
+ - `poetry:install --force` no longer rewrites the four files the install seeds once for the host to own (`config/poetry_components.yml`, the initializer, `poetry/base.css`, `poetry/typeset.css`); a re-run with the flag used to reset a host's override declarations and settings to the seed. The vendored artifacts refresh on every run, so the flag is never needed on an upgrade.
52
+ - `poetry:install` no longer adds a second `herb` declaration when the gem is declared in a file the Gemfile pulls in with `eval_gemfile` (a shared Gemfile).
53
+
3
54
  ## [0.1.1] - 2026-09-08
4
55
 
5
56
  ### Added
data/README.md CHANGED
@@ -59,8 +59,8 @@ bin/rails g poetry:add <name> # adds newly-shipped files, never overwrites
59
59
  ```
60
60
 
61
61
  And `rails g scaffold` itself can produce poetry-composed views — a
62
- DataTable index with sanitized URL state, Field-composed forms, and a
63
- matching controller — by installing the app-owned template overrides once:
62
+ DataTable index with sanitized URL state, forms on the poetry form
63
+ builder, and a matching controller — by installing the app-owned template overrides once:
64
64
 
65
65
  ```bash
66
66
  bin/rails g poetry:scaffold_templates
@@ -33,6 +33,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
33
  SOFTWARE.
34
34
  ```
35
35
 
36
+ ## Tailwind CSS
37
+
38
+ - Source: https://github.com/tailwindlabs/tailwindcss (MIT)
39
+ - `reset/reset.css` (the reset floor `poetry:install --no-preflight` vendors) is preflight, generated from the pinned tailwindcss binary with every selector wrapped in `:where()`
40
+
41
+ ```
42
+ MIT License
43
+
44
+ Copyright (c) Tailwind Labs, Inc.
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining a copy
47
+ of this software and associated documentation files (the "Software"), to deal
48
+ in the Software without restriction, including without limitation the rights
49
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
50
+ copies of the Software, and to permit persons to whom the Software is
51
+ furnished to do so, subject to the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be included in all
54
+ copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
59
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
61
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
62
+ SOFTWARE.
63
+ ```
64
+
36
65
  ## Base UI
37
66
 
38
67
  - Source: https://github.com/mui/base-ui (MIT)
@@ -169,7 +169,7 @@ module Poetry
169
169
  # block--modifier tokens ARE the host's styling contract.
170
170
  # @api private
171
171
  def html_attributes
172
- return super unless Poetry::Core::Config.current.css_mode == :tailwind
172
+ return super unless css_mode == :tailwind
173
173
 
174
174
  @html_attributes.merge(class: classnames(@html_attributes[:class]))
175
175
  end
@@ -21,7 +21,11 @@ module Poetry
21
21
  # The shared builder (the llms construction rule, extended): the
22
22
  # served text uses the exact registry construction the committed
23
23
  # file is generated from - helpers and blocks sections included.
24
- Poetry::Core::LlmsText.new(registry: Poetry::Ui.registry)
24
+ # The app's own components ride along (their section follows the
25
+ # gem catalog), so an agent reading llms-full.txt sees their agent
26
+ # rules and helpers too.
27
+ Poetry::Core::LlmsText.new(registry: Poetry::Ui.registry,
28
+ host_registry: Poetry::Core::HostComponents.registry(root: Rails.root))
25
29
  end
26
30
  end
27
31
  end
@@ -982,6 +982,10 @@ module Poetry
982
982
  { "name" => "value", "type" => "object" }
983
983
  ]
984
984
  },
985
+ "poetry_webmcp_form" => {
986
+ "yields" => "the form builder (Poetry::Ui::FormBuilder unless builder: says otherwise) - " \
987
+ "form.field and form.input author the tool's parameters; every standard field helper works"
988
+ },
985
989
  "poetry_input_group_addon" => {
986
990
  "options" => [{ "name" => "align", "type" => "symbol", "default" => "inline-start",
987
991
  "variants" => INPUT_GROUP_ALIGNS.map(&:to_s) }]
@@ -17,7 +17,7 @@ module Poetry
17
17
  STRING_HEURISTICS = {
18
18
  /password/ => :password,
19
19
  /email/ => :email,
20
- /\burl\b|_url\b/ => :url,
20
+ /\burl\b|_url\b|website|permalink/ => :url,
21
21
  /phone|\btel\b/ => :tel,
22
22
  /search|query/ => :search
23
23
  }.freeze
@@ -43,9 +43,11 @@ module Poetry
43
43
  COLUMN_TYPES.fetch(column, :string)
44
44
  end
45
45
 
46
+ # has_one_attached answers to <name>_attachment, has_many_attached
47
+ # to <name>_attachments; the other two are the classic uploaders.
46
48
  def attachment_attribute?(method)
47
- object.respond_to?("#{method}_attachment") || object.respond_to?("#{method}_attacher") ||
48
- object.respond_to?("remote_#{method}_url")
49
+ object.respond_to?("#{method}_attachment") || object.respond_to?("#{method}_attachments") ||
50
+ object.respond_to?("#{method}_attacher") || object.respond_to?("remote_#{method}_url")
49
51
  end
50
52
 
51
53
  def enum_attribute?(method)
@@ -32,6 +32,9 @@ module Poetry
32
32
  "overrides the presence inference (aria only).",
33
33
  "Hints/placeholders resolve from poetry_form.* i18n (simple_form.* keys keep working " \
34
34
  "as a fallback); pass hint:/placeholder: to override.",
35
+ "Every builder field renders a Field, so wiring tests assert on its parts: the label is " \
36
+ "data-slot=field-label, the hint data-slot=field-description, the error data-slot=field-error, " \
37
+ "with the control inside (never a bare hint or description slot).",
35
38
  "f.submit renders a poetry Button with the Rails i18n label; f.fieldset(legend:)/" \
36
39
  "f.group lay out sections; boolean f.input renders the horizontal Field " \
37
40
  "(switch: true -> the setting row).",