@bettercms-ai/convert 0.10.0 → 0.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # @bettercms-ai/convert
2
2
 
3
+ ## 0.12.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a243594: Every pending path leaves with an exact fix, and a locator resolves each path sharing a literal.
8
+
9
+ `paths.pending[]` rows now carry `fix: { file, line, col?, snippet, action, why? }` — one action
10
+ out of a closed set (`wrap-span`, `declare-attr`, `bind-expression`, `declare-richtext`,
11
+ `bind-data`, `manual`), so "rerun until nothing is pending" is a loop an agent can finish instead
12
+ of a list of category names. A literal one element renders on several routes is named as shared
13
+ chrome rather than sent for an attribute that could only ever be one route's.
14
+
15
+ Positional resolution is now per PATH rather than per literal: one path with no locator used to
16
+ refuse the whole literal, so a page whose rows carried locators converted none of them.
17
+
18
+ Two paths whose locators cannot be told apart now place NEITHER. Resolution counts the targets
19
+ wanting each element before it assigns any, so it no longer depends on brief order: `plan` runs
20
+ per file, and claiming greedily let the first of two indistinguishable paths win in every file —
21
+ writing one path's `data-bcms-field` onto the other's element and reporting it bound.
22
+
23
+ An action that edits an element (`wrap-span`, `declare-attr`, `declare-richtext`) is never issued
24
+ at a position inside a frontmatter array or a `<script>`; there is no element there, so the fix is
25
+ `bind-data` on the row the copy actually lives in. A fix for a dynamic route names the template
26
+ that generates it instead of an empty file. Files that talk ABOUT the site — `*.test.*`,
27
+ `*.spec.*`, `__tests__/`, `__mocks__/`, root `*.config.*` — are no longer read, so a test
28
+ asserting on the hero line stops holding an already-declared path pending.
29
+
30
+ Fix positions are measured against the bytes the run WRITES, not the ones it read — the same run
31
+ inserts a helper import above most pending lines, so a receipt minted from the originals named a
32
+ line one or more short of the element on 616 of 948 Shatter rows.
33
+
34
+ ## 0.11.0
35
+
36
+ ### Minor Changes
37
+
38
+ - `--componentize` extracts FLAT field families (`wrap-h2-latest`, whose key is `h2_latest`), which were
39
+ refused as `PROP_MAP_INCONSISTENT`. The section reads its copy through the new helper `bcmsSectionPaths`
40
+ and addresses instance copy by the override key the plan names (`overrideKey`, including repeater rows).
41
+ - An Astro section carries the page's scoped plain-CSS `<style>` blocks, so it renders styled on its own —
42
+ for every newly extracted section, dotted families included (Astro scopes styles per file, so page CSS
43
+ never reached a moved section). `is:global`, `define:vars`, `lang="…"` and `@import`/`@use` blocks stay on
44
+ the page.
45
+ - The componentize receipt lists `componentFiles` (`{ slug, path, export }`): submit it with the MCP tool
46
+ `submit_componentize_receipt` so every extracted section is recorded as its component's source and the
47
+ dashboard's Output can build, validate and render it.
48
+ - Helper v7. A v6 helper is recognised and upgraded in place.
49
+
3
50
  ## 0.10.0
4
51
 
5
52
  ### Minor Changes
package/README.md CHANGED
@@ -184,6 +184,60 @@ the receipt's arithmetic is checked, not hoped for:
184
184
  paths.declared === paths.rewritten + paths.alreadyDeclared + paths.pending.length
185
185
  ```
186
186
 
187
+ ### What pending means — every row carries the edit, not the diagnosis
188
+
189
+ A reason is a diagnosis and nobody can act on one. So every `paths.pending[]` row also carries a
190
+ `fix`: the file, the 1-based line and column, the bytes that are there now, and ONE action out of
191
+ a closed set. That is what makes "run it again until nothing is pending" a loop an agent can
192
+ actually finish — and what `get_next_steps` prints, one line per path.
193
+
194
+ ```jsonc
195
+ { "route": "/about", "scope": "page", "path": "p-founded-in-2019-in", "kind": "text",
196
+ "reason": "DIALECT_UNSUPPORTED",
197
+ "fix": { "file": "src/data/facts.js", "line": 3, "col": 25,
198
+ "snippet": "export const founded = \"Founded in 2019 in Bristol.\";",
199
+ "action": "bind-data",
200
+ "why": "src/data/facts.js holds this copy as data — bind the element that renders it." } }
201
+ ```
202
+
203
+ | action | what to type |
204
+ |---|---|
205
+ | `wrap-span` | the value shares its element with something else, or is rendered in a position no attribute reaches — give it a `<span data-bcms-field="…">` of its own. |
206
+ | `declare-attr` | the element is there and nothing said which path it is — add `data-bcms-field` to it at `file:line`. |
207
+ | `declare-richtext` | the container is fed markup (`set:html`, `dangerouslySetInnerHTML`) — bind it with the richtext helper. |
208
+ | `bind-expression` | the value is computed in the markup (a ternary, a template literal) — read the path there instead. |
209
+ | `bind-data` | the copy lives in a data module, a frontmatter array or a content-collection entry — bind THAT field, and the element that renders it. |
210
+ | `manual` | none of the above is true; `why` says what a human has to decide. |
211
+
212
+ Reason → action, and the two places the answer is not the obvious one:
213
+
214
+ | reason | action |
215
+ |---|---|
216
+ | `AMBIGUOUS_LITERAL`, one route | `declare-attr` — `why` names every candidate file. |
217
+ | `AMBIGUOUS_LITERAL`, **several routes** | `manual` — one element cannot carry N routes' bindings. This is SHARED CHROME the derive lane did not promote: a Layout field is one value for the whole site, and an attribute here would bind one route and silently freeze the rest. |
218
+ | `IN_EXPRESSION` in the markup | `bind-expression`, or `declare-richtext` for a richtext value. |
219
+ | `IN_EXPRESSION` **in the frontmatter or a `<script>`** | `bind-data` — the copy is a row in the file's own data, and the array is what gets bound, not the `{l.label}` that reads it. |
220
+ | `DIALECT_UNSUPPORTED` on `.md`/`.mdx` | `bind-data` — a content-collection body is the entry's `document` field. |
221
+ | `NOT_IN_SOURCE` / `NO_ORIGINAL` | `bind-data` when the copy is in a data module, else `manual`: the built page formats it and the source holds the input. |
222
+ | `PROP_TARGET_NOT_FOUND`, `PROP_DRILLED_DEEP`, `SUBSTRING_ONLY` | `wrap-span`. |
223
+ | `REPEATER_AMBIGUOUS`, `REPEATER_FIXED_LENGTH` | `declare-attr` on the row's own element. |
224
+ | `IMAGE_ASSET_UNRESOLVED`, `IN_DATA_FILE` | `bind-data`. |
225
+ | `SUBTREE_NOT_HTML` | `declare-richtext`. |
226
+ | `KIND_MISMATCH`, `IN_SCRIPT_OR_COMMENT`, `DYNAMIC_PARAMS_UNAVAILABLE`, `BRIEF_META_UNPLACED`, `PARSE_ERROR`, `TIER3_UNVERIFIABLE`, `CANVAS_BRIDGE_MANUAL`, `SSR_DRAFT_ROUTE` | `manual`, with the reason quoted in `why` — read the row's `message` for what blocked it. |
227
+
228
+ **A file that talks ABOUT the site is not a source file.** A path is rewritten only when every
229
+ located occurrence was, so a test asserting on the hero line, or a build config quoting the font
230
+ stack, used to hold an already-declared path pending. `*.test.*`, `*.spec.*`, `__tests__/`,
231
+ `__mocks__/` and root-level `*.config.*` are never opened, alongside `node_modules/` and `dist/`.
232
+ A data module under `src/` — `src/site.config.ts` — is not a build config and stays bindable.
233
+
234
+ **`--xray` and the receipt exclude the same things.** The xray measures a BUILT site's visible
235
+ copy and the receipt measures the brief's paths in SOURCE, so they never have the same
236
+ denominator — but neither counts a decorative glyph, a `<script>` or a `<style>` as copy
237
+ (`isDecorativeGlyph` is the one reader), and the two lane rows `CANVAS_BRIDGE_MANUAL` and
238
+ `SSR_DRAFT_ROUTE` ride `paths.pending` without entering the arithmetic above. A path the receipt
239
+ calls pending is copy the xray will still count as unaddressed; a path it calls rewritten is not.
240
+
187
241
  A path counts as rewritten only when EVERY located occurrence of it was. A value rendered by both
188
242
  the home page and a shared header is two places a reader sees it, and converting one of them reads
189
243
  as a finished job.