mosaic-headless 1.2.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 (77) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +94 -0
  3. package/README.md +133 -0
  4. package/README.zh-CN.md +87 -0
  5. package/README.zh-TW.md +87 -0
  6. package/SKILL.md +353 -0
  7. package/assets/templates/platforms/claude-ai.json +34 -0
  8. package/assets/templates/platforms/claude-code.json +28 -0
  9. package/assets/templates/platforms/codex-cli.json +33 -0
  10. package/assets/templates/platforms/continue.json +31 -0
  11. package/assets/templates/platforms/copilot.json +46 -0
  12. package/assets/templates/platforms/cursor.json +36 -0
  13. package/assets/templates/platforms/gemini-cli.json +33 -0
  14. package/assets/templates/platforms/windsurf.json +34 -0
  15. package/bin/check-release.mjs +143 -0
  16. package/bin/install.mjs +452 -0
  17. package/bin/sync-version.mjs +63 -0
  18. package/data/animatable-properties.csv +23 -0
  19. package/data/condition-comparators.csv +13 -0
  20. package/data/condition-subjects.csv +60 -0
  21. package/data/db-columns.csv +207 -0
  22. package/data/default-children.csv +11 -0
  23. package/data/dynamic-variables.csv +75 -0
  24. package/data/element-classes.csv +152 -0
  25. package/data/evaluator-functions.csv +20 -0
  26. package/data/interaction-types.csv +13 -0
  27. package/data/node-properties.csv +182 -0
  28. package/data/node-property-verification.csv +182 -0
  29. package/data/node-types.csv +123 -0
  30. package/data/node-verification.csv +123 -0
  31. package/data/placement-rules.csv +123 -0
  32. package/data/pluggables.csv +208 -0
  33. package/data/property-verification.csv +171 -0
  34. package/data/rest-routes.csv +115 -0
  35. package/data/rwd-verification.csv +570 -0
  36. package/data/style-properties.csv +99 -0
  37. package/data/style-states.csv +54 -0
  38. package/data/style-value-shapes.csv +23 -0
  39. package/data/style-verification.csv +99 -0
  40. package/package.json +59 -0
  41. package/references/data-model.md +95 -0
  42. package/references/design-system.md +118 -0
  43. package/references/dynamic-content.md +113 -0
  44. package/references/failure-modes.md +182 -0
  45. package/references/interactions.md +126 -0
  46. package/references/placement.md +117 -0
  47. package/references/responsive.md +174 -0
  48. package/references/styling.md +172 -0
  49. package/references/templates-and-conditions.md +122 -0
  50. package/references/vs-elementor-gutenberg.md +73 -0
  51. package/references/write-protocol.md +79 -0
  52. package/sites/_moksa.py +1165 -0
  53. package/sites/moksa.json +8685 -0
  54. package/tools/bootstrap_probe_theme.php +68 -0
  55. package/tools/build_all.py +55 -0
  56. package/tools/build_page.py +352 -0
  57. package/tools/build_report.py +221 -0
  58. package/tools/build_site.py +174 -0
  59. package/tools/capture_live.py +130 -0
  60. package/tools/check_placement_predicts.py +72 -0
  61. package/tools/copy_styles.py +204 -0
  62. package/tools/extract_default_children.py +94 -0
  63. package/tools/extract_dynamic_variables.py +104 -0
  64. package/tools/extract_interactions.py +98 -0
  65. package/tools/extract_node_types.py +165 -0
  66. package/tools/extract_placement.py +135 -0
  67. package/tools/extract_pluggables.py +90 -0
  68. package/tools/extract_style_properties.py +163 -0
  69. package/tools/mint_session.php +52 -0
  70. package/tools/probe.py +144 -0
  71. package/tools/sweep_node_properties.py +271 -0
  72. package/tools/sweep_node_types.py +318 -0
  73. package/tools/sweep_properties.py +215 -0
  74. package/tools/sweep_style_properties.py +254 -0
  75. package/tools/theme_export.php +91 -0
  76. package/tools/theme_import.php +113 -0
  77. package/tools/verify_rwd.py +278 -0
package/SKILL.md ADDED
@@ -0,0 +1,353 @@
1
+ ---
2
+ name: "mosaic-headless"
3
+ description: |
4
+ Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 151 element classes, 74 dynamic variables, 12 interaction triggers, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, the design-token and element-class layers verified against compiled CSS, the @VAR() dynamic language verified against rendered output, and nine designed pages built through the tables themselves.
5
+ license: "MIT"
6
+ author: "moksa (https://moksaweb.com)"
7
+ version: "1.2.0"
8
+ ---
9
+
10
+ # Headless Mosaic
11
+
12
+ Build Mosaic pages by writing the data model directly. The visual builder is one
13
+ client of that model; it is not the format, and you do not need it.
14
+
15
+ **Scope: page and template construction on a Mosaic site.** Not WordPress site
16
+ health, not plugin audits. If the site is not running Mosaic, this skill does not
17
+ apply — `references/vs-elementor-gutenberg.md` says which skill does.
18
+
19
+ ## The one rule that overrides everything
20
+
21
+ **Never write a node type, property name, enum value, style key or Free/Pro claim
22
+ from memory. Look it up in `data/`.**
23
+
24
+ Then check the page. Mosaic has four failure modes and **only one of them changes the
25
+ HTTP status code**:
26
+
27
+ ```
28
+ clean validator rejection HTTP 200 + an `exceptions` array in the body
29
+ PHP fatal during commit HTTP 500 (15 of 122 types do this from a plain div)
30
+ structurally invalid node HTTP 200, committed, row in the DB, and the whole
31
+ public page becomes a 54-byte error string
32
+ wrong value SHAPE HTTP 200, stored, and the CSS rule is simply absent -
33
+ or worse, compiles to `transform:none`
34
+ no template for the URL HTTP 406 with an EMPTY BODY for anyone not logged in
35
+ ```
36
+
37
+ **406 is Mosaic's "no template matched".** `FrontendRenderer` answers
38
+ `TemplateNotFoundException` with `status_header(406)` and prints the explanation
39
+ only for an admin, so a logged-out visitor gets a blank page and a status code
40
+ that looks like a server problem. Two things make it easy to hit:
41
+
42
+ - **There are TWO ways to bind a template, and `createManualTemplate` is only one
43
+ of them.** That endpoint takes `resourceQuery=post/<id>` and `post` is the only
44
+ resource type it registers (`setResourceType('post')`, three call sites), so
45
+ through it there is no catch-all. But `assign` and `path` are first-class columns
46
+ on `wp_mosaic_templates`, and a template row committed with `assign:"auto"` and
47
+ `path:"index.php"` binds to a template PATH instead of a post. Measured A/B on a
48
+ URL with no template of its own: 406 with no such row, handled with it, 406 again
49
+ after deleting it. `X-Mosaic-Paths` on any 406 names the paths Mosaic looked for,
50
+ and `index.php` is in every list.
51
+
52
+ **Two limits, both measured.** `adminTemplateEditorInstance` does not return auto
53
+ templates at all - it listed only the three manual ones - so the admin surface
54
+ hides them. And an auto template's document has a `node/template/<id>` key but no
55
+ `template-internal` root: `heal()` builds that skeleton only for templates made
56
+ through `createManualTemplate`, and committing one directly answers HTTP 500. So
57
+ the row removes the 406 and I could not then put content in it. Not deployed on
58
+ the demo site for that reason - a 200 with an empty body is worse signal than a
59
+ 406.
60
+
61
+ For `/` specifically the WordPress-side fix is the sound one: point the front page
62
+ at a post that has a template (`show_on_front=page`, `page_on_front=<id>`).
63
+ - **Activating a theme is not the same as populating it.** A fresh theme has no
64
+ templates, so between `wp theme activate` and a successful build the whole site
65
+ is 406 - and if the build fails, it stays that way. Never activate a new theme
66
+ as a step that can be separated from the commit that fills it.
67
+
68
+ A successful commit is not evidence of a working page. Fetch the page and check its
69
+ size. `references/failure-modes.md` has all of them, measured.
70
+
71
+ ## What was verified, and how
72
+
73
+ Everything ran against a live install: WordPress 7.1, WooCommerce 11.1,
74
+ Mosaic Pro 1.0.7, **unlicensed** — the licence gates the theme library and updates,
75
+ not the node factories, so the Pro types register and render regardless.
76
+
77
+ ```
78
+ WRITE PATH verified end to end over REST
79
+ theme -> master -> healed node tree -> template -> nodes -> public HTML
80
+
81
+ NODE SWEEP 122 of 122 node types, ONE PER DOCUMENT, committed then rendered then
82
+ deleted, asserting each type's attrID against the delivered HTML:
83
+ RENDERED 70 id found; tag and classes recorded
84
+ COMMITTED 30 row exists, nothing reached the page
85
+ COMMIT_5xx 15 PHP fatal on commit
86
+ BROKE_PAGE 7 committed, then the whole page died
87
+ Free 74: 43/22/6/3. Pro 48: 27/8/9/4. data/node-verification.csv
88
+
89
+ STYLE the states[state][breakpoint][property] shape confirmed by writing it
90
+ and reading back the compiled CSS; 20 of 22 structured value shapes
91
+ pinned down the same way. data/style-value-shapes.csv
92
+
93
+ DESIGN SYS element classes and collection variables both verified against compiled
94
+ CSS: an elementClass on the Heading 2 meta emitted a site-wide
95
+ h2,.M_EL_Text__Heading2{...} rule, and a collection variable emitted
96
+ :root{--brand: rgb(9, 99, 199)} with background-color:var(--brand).
97
+ references/design-system.md
98
+
99
+ DYNAMIC the @VAR('namespace/name') language verified against rendered output -
100
+ @VAR('post/title') produced the real post title, @concat/@substr/
101
+ @fallback all compose over it. 74 variables in
102
+ data/dynamic-variables.csv. references/dynamic-content.md
103
+
104
+ PROPERTIES 170 probes over the declared property surface, each value asserted
105
+ against the delivered markup and the compiled CSS separately.
106
+ data/property-verification.csv
107
+
108
+ RWD 569 responsive declarations across two sites asserted against the
109
+ stylesheet the site actually served - each `_t`/`_m` property matched
110
+ to its element's generated class inside that breakpoint's own media
111
+ query. All verified; the checker is itself checked against a poisoned
112
+ spec so a pass means something. data/rwd-verification.csv
113
+
114
+ BUILD nine complete designed pages built through the tables alone and checked
115
+ in a real browser, hover states included - the ninth uses only design
116
+ tokens, element-class typography and dynamic content, no hard-coded
117
+ colour anywhere, plus a real studio homepage rebuilt from the
118
+ live moksaweb.com. sites/_moksa.py is the one that ships.
119
+
120
+ MEASURED 114 REST routes, 151 element classes, 59 condition subjects,
121
+ 23 tables / 206 columns - read off the running site.
122
+
123
+ FROM SOURCE 122 node types, 181 properties (61 with enums), 207 pluggable IDs,
124
+ 122 placement rules, 10 composite default structures, 98 style
125
+ properties, 53 style states.
126
+ ```
127
+
128
+ **Coverage, stated as a fraction rather than as a headline.** The verification
129
+ counts above are real, but they are not the same as "the surface is verified", and
130
+ the difference is worth being exact about:
131
+
132
+ ```
133
+ node types 122 / 122 swept live, one per document
134
+ node properties 181 / 181 re-probed with a value shaped by each property's
135
+ own validator chain: 35 APPLIED, 42 NO_EFFECT,
136
+ 2 EDITOR_ONLY, 55 NO_HOST (no rendering type
137
+ declares them), 47 SKIPPED
138
+ style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
139
+ 21 SKIPPED (no test value could be synthesised, and
140
+ SKIPPED is never counted as a pass)
141
+ ```
142
+
143
+ **A same-value probe measures the probe, not the surface.** The first property run
144
+ sent the string `MPROP0000X` to all 181 properties regardless of what each wanted,
145
+ and reported 91 NO_EFFECT. The tell was that `tagName` was in that list while the
146
+ entire demo site is built on it. Re-probed with a value derived from the declared
147
+ validator chain - array for `ValidatorArray`, boolean for `ValidatorBoolean`, a legal
148
+ enum member for `ValidatorAcceptedValues` - six of those NO_EFFECTs turn out to work:
149
+ `tagName`, `target`, `rel`, `height`, `size`, `insertLocation`.
150
+
151
+ **Some properties are gated by a companion.** `target` and `rel` did nothing until
152
+ the node also carried a `url`: `button` and `menu-link` render a `<span>` without one
153
+ and an `<a href>` with it, so an anchor-only attribute has nothing to attach to. A
154
+ NO_EFFECT is only meaningful once the property has been given the context it needs.
155
+
156
+ Twelve remain NO_EFFECT with a correctly shaped value, `cssClasses` and `attributes`
157
+ among them - recorded as measured-inert-with-this-shape rather than as dead, because
158
+ a third shape may yet be the right one.
159
+
160
+ **A property that belongs to a `group` is inert when you set it on its own.** This is
161
+ the sweep's one big result and it is exact:
162
+
163
+ ```
164
+ ungrouped 78 properties 58 COMPILED 0 ABSENT (20 SKIPPED)
165
+ grouped 20 properties 0 COMPILED 18 ABSENT (1 NO_ELEMENT, 1 SKIPPED)
166
+ ```
167
+
168
+ Zero exceptions in either direction. The 20 are the `borderStyle` per-side longhands
169
+ (12), `outlineStyle` (4) and `gridChildPosition` (4) — so `borderLeftWidth`,
170
+ `outlineColor` and `gridColumnStart` are all instances of one rule rather than three
171
+ oddities. Set the grouped shape instead (`border` takes `{width, style, color}`), or
172
+ use `customStyles`. `data/style-verification.csv` carries the group beside the result
173
+ so the pattern is in the data, not just in this paragraph.
174
+
175
+ **Known gaps, stated rather than papered over.**
176
+
177
+ - `backgroundStyle` is the one style property whose shape resisted every attempt — it
178
+ accepts what you send and emits `background-image:none`. Use `customStyles` for
179
+ gradients, as the glass and darkglow pages do.
180
+ - **`gridColumnStart` / `gridColumnEnd` / `gridRowStart` / `gridRowEnd` emit nothing.**
181
+ All four are real entries in `data/style-properties.csv`, under `gridChildPosition`.
182
+ Measured: 16 `gridColumnStart` declarations committed, zero occurrences of
183
+ `grid-column` in the delivered CSS. Change the template; you cannot place a child.
184
+ - **Interaction property binding is unsolved.** The trigger, action slot and keyframe
185
+ timing all reach the browser; `propertyMetas` and per-keyframe `properties` do not.
186
+ Animate with the CSS transition/state path, which is fully verified.
187
+ - Committing a **condition** has not been driven end to end. The grammar in
188
+ `references/templates-and-conditions.md` is read from source and from the live
189
+ metas; an element carrying one rendered as hidden, which is consistent with the
190
+ condition evaluating false but is not proof the shape was understood.
191
+
192
+ ## Orient yourself in this order
193
+
194
+ 1. `references/data-model.md` — where a page actually lives. Read this first even if
195
+ you know Elementor; the answer is not `postmeta` and not `post_content`.
196
+ 2. `references/write-protocol.md` — the checkout/check/commit sequence and envelopes.
197
+ 3. `references/failure-modes.md` — how Mosaic fails, measured. Read before writing.
198
+ 4. `references/placement.md` — what may go inside what, and what that table cannot
199
+ tell you.
200
+ 5. `references/styling.md` — how a style value becomes CSS, and the shapes that are
201
+ silently inert if you write a string.
202
+ 6. `references/responsive.md` - the state/breakpoint/property axis, the two
203
+ breakpoint rows, and the override that can change a property but never remove
204
+ one. **Read before writing any `_t` or `_m` value.**
205
+ 7. `references/design-system.md` — element classes and design tokens. **Read this
206
+ before styling anything beyond a one-off page**; per-node style is the wrong layer
207
+ for a real site.
208
+ 8. `references/dynamic-content.md` — the `@VAR()` language. The syntax is not
209
+ guessable, and a wrong guess renders as literal text rather than an error.
210
+ 9. `references/templates-and-conditions.md` — how Mosaic picks a template, and the
211
+ condition grammar shared by templates, elements, interactions and form actions.
212
+ 10. `references/interactions.md` — the JavaScript animation system, and how far it is
213
+ verified.
214
+ 11. `references/vs-elementor-gutenberg.md` — which builder habits transfer.
215
+
216
+ ## The data files
217
+
218
+ | file | rows | source |
219
+ |---|---|---|
220
+ | `data/node-verification.csv` | 122 | **swept live** — outcome, rendered tag and classes, page bytes, failure detail |
221
+ | `data/node-types.csv` | 122 | source — slug, label, edition, aliases, data class |
222
+ | `data/node-properties.csv` | 181 | source — property, validator chain, **accepted enum values**, `supportsInherit` |
223
+ | `data/placement-rules.csv` | 122 | source — which children each type accepts |
224
+ | `data/default-children.csv` | 10 | source — what a composite type needs **inside** it |
225
+ | `data/style-properties.csv` | 98 | source — every settable CSS property and its value shape |
226
+ | `data/style-value-shapes.csv` | 22 | **probed live** — the exact JSON shape for each structured value, and what it compiled to |
227
+ | `data/style-states.csv` | 53 | source — state IDs with their exact CSS selector templates |
228
+ | `data/property-verification.csv` | 170 | **probed live** — per-property effect on markup vs CSS, with unprovable enums marked INCONCLUSIVE |
229
+ | `data/node-property-verification.csv` | 181 | **swept live** — each property probed with a value shaped by its own validator chain, on a type that declares it |
230
+ | `data/style-verification.csv` | 98 | **swept live** — every style property written to a page and checked against the compiled CSS, with its group beside the result |
231
+ | `data/rwd-verification.csv` | 569 | **checked live** - every `_t`/`_m` declaration vs the served stylesheet, with status per row |
232
+ | `data/element-classes.csv` | 151 | **live** — the built-in class metas; their IDs are what an `elementClass` record must use |
233
+ | `data/dynamic-variables.csv` | 74 | source — every `@VAR('ns/name')` expression, by namespace |
234
+ | `data/evaluator-functions.csv` | 19 | source — the `@` functions with their arity |
235
+ | `data/interaction-types.csv` | 12 | source — trigger types, `timed` vs `progress` |
236
+ | `data/animatable-properties.csv` | 22 | source — what a keyframe can drive (**not** the same set as the style properties) |
237
+ | `data/condition-subjects.csv` | 59 | **live** — condition subjects per context |
238
+ | `data/condition-comparators.csv` | 12 | **live** — comparators and their operator sets |
239
+ | `data/pluggables.csv` | 207 | source — every `setID()` by registry |
240
+ | `data/rest-routes.csv` | 114 | **live** — method, path, args |
241
+ | `data/db-columns.csv` | 206 | **live** — every column of all 23 tables |
242
+
243
+ ## Building a page
244
+
245
+ `tools/build_page.py` consumes a declarative spec and commits it through the verified
246
+ write path, refusing anything the tables say is unsafe. `tools/build_site.py` does the
247
+ same for a whole site: one master carrying the header and footer, one template document
248
+ per page.
249
+
250
+ **`sites/_moksa.py` is the worked example** - a real studio homepage (hero, statistics,
251
+ services, a nine-item work list, products, testimonials, CTA, footer) generated as a
252
+ spec and committed entirely through the tables. Read it for the shape of a real build:
253
+ the `bp()` breakpoint helper, the `code` node that carries the keyframes, the glass
254
+ header, and `apply_type()`.
255
+
256
+ A spec can carry a `theme` block, which is how a real site should be styled — design
257
+ tokens and element-class typography rather than per-node values:
258
+
259
+ ```jsonc
260
+ "theme": {
261
+ "variables": {"--brand": {"type": "color", "value": "rgb(13,108,102)"}},
262
+ "elementClasses": {"Heading 1": {"&": {"_": {"color": {"token": "--brand"}}}}}
263
+ }
264
+ ```
265
+
266
+ `{"token": "--brand"}` anywhere in a style resolves to the `{"var": "<uuid>"}`
267
+ reference the compiler wants.
268
+
269
+ **Two brands in one theme need namespaced tokens and no element classes at all.**
270
+ Collection variables and element classes are both theme-global: two specs that each
271
+ declare `--ink` produce one `:root` with duplicate declarations, and two specs that
272
+ each style `Heading 1` produce one set of rules. Whichever committed last wins, for
273
+ every page. `sites/_moksa.py` namespaces its tokens (`--mk-*`) and bakes the type
274
+ system onto the nodes with `apply_type()` instead of using element classes, which is
275
+ what lets it share an install with a completely different design.
276
+
277
+ Whole themes move between installs with `theme_export.php` / `theme_import.php`.
278
+ A theme is a themeID scattered across nineteen tables, and every one of them has a
279
+ COMPOSITE primary key of `(themeID, ID)` — so an import can keep every internal id
280
+ and rewrite nothing but the theme, which means no id remapping and nothing left
281
+ dangling. Round-tripped and verified: a full theme exported, re-imported as a copy,
282
+ and the copy served byte-identical pages.
283
+
284
+ `copy_styles.py` pushes one node's style onto others by attrID or prefix, optionally
285
+ only certain `state.breakpoint` slices, and shows the diff before writing.
286
+
287
+ ```bash
288
+ wp eval-file tools/bootstrap_probe_theme.php # licence-free scratch theme
289
+ python tools/build_all.py --config sweep.json # reset + build every design
290
+ ```
291
+
292
+ Rebuilding a single page without a reset leaves an orphan template bound to the same
293
+ post — `build_all.py` resets first for that reason.
294
+
295
+ ## Facts worth knowing before you look anything up
296
+
297
+ - **The REST namespace contains the plugin version** (`/wp-json/mosaic/v1.0.7`). Read
298
+ it from `mosaicOptions.rest_api_url`, never hardcode.
299
+ - **`ordering` is a fractional-index string**, not a number.
300
+ - **The tree is a `parentID` column**, not nesting. There is no page-level JSON blob.
301
+ - **Everything is scoped to a `themeID`**, breakpoints included.
302
+ - **A post is a target, not a container.** Templates bind to posts through
303
+ `mosaic_template_assigns`; one template serves many posts.
304
+ - **Only `wp_mosaic_locks` existing** means a half-installed Mosaic. The other 22
305
+ tables appear when an admin loads `/wp-admin/admin.php?page=mosaic`.
306
+ - **Commit has side effects.** `heal()` runs inside it and creates breakpoints,
307
+ collections and child nodes you never sent. Take every revision in the response.
308
+ - **`modified_gmt` is server-assigned.**
309
+ - **Styling hangs on the generated `.M_EL<n>` class, not your `attrID`**, and that
310
+ number is not stable. The sibling `M_EL_<Type>` class is.
311
+ - **`body{opacity:0}`** — the theme reveals itself from JavaScript. Screenshot tooling
312
+ must let scripts run or it captures a blank page.
313
+
314
+ ## Rendered-tag facts you would otherwise guess wrong
315
+
316
+ - **`button` renders as `<span>`**, not `<button>`. So do `menu-link` and `wysiwyg-link`.
317
+ - **`text` renders as `<div>` by default** — set `tagName` for `<h1>`, `<p>` and so on.
318
+ - **Eight types emit custom elements**: `<mosaic-dropdown>`, `<mosaic-navbar>`,
319
+ `<mosaic-tabs>`, `<mosaic-accordion>`, `<mosaic-vimeo>`, `<mosaic-youtube>` and
320
+ friends. A selector written against `div`/`nav` misses all of them.
321
+ - **`icon` renders inline `<svg>`.**
322
+
323
+ ## Regenerating everything
324
+
325
+ ```bash
326
+ python tools/extract_node_types.py <plugin-root> data/
327
+ python tools/extract_pluggables.py <plugin-root> data/
328
+ python tools/extract_placement.py <plugin-root> data/
329
+ python tools/extract_default_children.py <plugin-root> data/
330
+ python tools/extract_style_properties.py <plugin-root> data/
331
+ python tools/extract_interactions.py <plugin-root> data/
332
+ python tools/extract_dynamic_variables.py <plugin-root> data/
333
+ python tools/capture_live.py data/ # from data/raw/*.json
334
+ # (raw dumps are gitignored;
335
+ # re-capture from a live site)
336
+
337
+ # against a scratch site - DESTRUCTIVE, never point at production
338
+ python tools/sweep_node_types.py --config sweep.json --setup
339
+ python tools/sweep_node_types.py --config sweep.json --sweep --edition all
340
+ python tools/sweep_properties.py --config sweep.json
341
+ python tools/verify_rwd.py --config sweep.json --site sites/moksa.json --csv data/rwd-verification.csv
342
+ python tools/sweep_style_properties.py --config sweep.json --page moksa --csv data/style-verification.csv
343
+ python tools/sweep_node_properties.py --config sweep.json --page moksa --csv data/node-property-verification.csv
344
+ wp eval-file tools/theme_export.php active > theme.json
345
+ wp eval-file tools/theme_import.php theme.json "Copy" rebind activate
346
+ python tools/probe.py --config lab.json --cases cases.json # ad-hoc measurement
347
+ python tools/check_placement_predicts.py
348
+ ```
349
+
350
+ `bootstrap_probe_theme.php` exists because Mosaic's own new-theme flow calls
351
+ `account.mosaicbuilder.com` and needs a licence. `EditorInstanceWithNewTheme->heal()`
352
+ does not — which is what made a licence-free fixture, and therefore this whole
353
+ verification, possible.
@@ -0,0 +1,34 @@
1
+ {
2
+ "platform": "claude-ai",
3
+ "displayName": "Claude.ai (web app)",
4
+ "installType": "zip-upload",
5
+ "folderStructure": {
6
+ "projectRoot": null,
7
+ "globalRoot": null,
8
+ "skillPath": "mosaic-headless.zip",
9
+ "filename": "SKILL.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": true,
14
+ "tools": false,
15
+ "data": true,
16
+ "sites": true
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "license": "MIT",
22
+ "author": "moksa (https://moksaweb.com)",
23
+ "version": "1.2.0"
24
+ },
25
+ "loaderBehaviour": "Upload via Settings -> Skills -> Upload. Claude.ai parses SKILL.md frontmatter and surfaces the skill in your library. The extraction tool (extract-block-schema.php) needs a live WP-CLI connection and won't run in the sandbox; use it from a local terminal against your own site instead.",
26
+ "uploadSteps": [
27
+ "1. Run: python tools/install-skill.py claude-ai --to ./build (creates elementor-headless.zip)",
28
+ "2. Open Claude.ai -> Settings -> Skills -> Upload",
29
+ "3. Pick the generated zip; the skill appears in your library",
30
+ "4. New chats auto-invoke when you ask to build/modify an Elementor page programmatically"
31
+ ],
32
+ "verified": true,
33
+ "verifiedAsOf": "2026-09-06"
34
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "platform": "claude-code",
3
+ "displayName": "Claude Code",
4
+ "installType": "full",
5
+ "folderStructure": {
6
+ "projectRoot": ".claude",
7
+ "globalRoot": "~/.claude",
8
+ "skillPath": "skills/mosaic-headless",
9
+ "filename": "SKILL.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": true,
14
+ "tools": true,
15
+ "data": true,
16
+ "sites": true
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "license": "MIT",
22
+ "author": "moksa (https://moksaweb.com)",
23
+ "version": "1.2.0"
24
+ },
25
+ "loaderBehaviour": "Auto-loads on session start when SKILL.md frontmatter parses successfully.",
26
+ "verified": true,
27
+ "verifiedAsOf": "2026-09-06"
28
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "platform": "codex-cli",
3
+ "displayName": "OpenAI Codex CLI",
4
+ "installType": "full",
5
+ "folderStructure": {
6
+ "projectRoot": ".codex",
7
+ "globalRoot": "~/.codex",
8
+ "skillPath": "skills/mosaic-headless",
9
+ "filename": "SKILL.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": true,
14
+ "tools": true,
15
+ "data": true,
16
+ "sites": true
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "license": "MIT",
22
+ "author": "moksa (https://moksaweb.com)",
23
+ "version": "1.2.0"
24
+ },
25
+ "loaderBehaviour": "Confirmed (2026-07-11): Codex CLI natively supports the SKILL.md spec. Place SKILL.md under .codex/skills/<name>/ (project) or ~/.codex/skills/<name>/ (personal) and Codex loads the name+description at session start, then the full body on demand. A parallel, broader convention .agents/skills/ (searched from cwd up to repo root, then ~/.agents/skills/) also exists across multiple tools - if your Codex CLI version prioritizes that path instead, mirror the same SKILL.md there.",
26
+ "verified": true,
27
+ "verifiedAsOf": "2026-09-06",
28
+ "verificationNote": "Upgraded from unverified: as of 2026-07-11 this is documented, native behaviour, not best-effort. Still confirm against your specific Codex CLI version since .agents/skills/ vs .codex/skills/ precedence can vary by build.",
29
+ "embedReferences": [
30
+ "data-model.md",
31
+ "failure-modes.md"
32
+ ]
33
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "platform": "continue",
3
+ "displayName": "Continue (continue.dev)",
4
+ "installType": "rule",
5
+ "folderStructure": {
6
+ "projectRoot": ".continue",
7
+ "globalRoot": "~/.continue",
8
+ "skillPath": "rules",
9
+ "filename": "mosaic-headless.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": false,
14
+ "tools": false,
15
+ "data": false,
16
+ "sites": false
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "alwaysApply": false
22
+ },
23
+ "loaderBehaviour": "Continue reads .continue/rules/*.md as Rules. Set alwaysApply: true to attach to every chat, or leave false and rely on the description for relevance matching. Rule files load in lexicographic order if you split this into several numbered files. References must be embedded inline; the installer concatenates key reference files into the rule body.",
24
+ "embedReferences": [
25
+ "data-model.md",
26
+ "failure-modes.md",
27
+ "responsive.md"
28
+ ],
29
+ "verified": true,
30
+ "verifiedAsOf": "2026-09-06"
31
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ "platform": "copilot",
3
+ "displayName": "GitHub Copilot",
4
+ "installType": "full",
5
+ "folderStructure": {
6
+ "projectRoot": ".github",
7
+ "globalRoot": null,
8
+ "skillPath": "skills/mosaic-headless",
9
+ "filename": "SKILL.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": true,
14
+ "tools": true,
15
+ "data": true,
16
+ "sites": true
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "license": "MIT",
22
+ "author": "moksa (https://moksaweb.com)",
23
+ "version": "1.2.0"
24
+ },
25
+ "loaderBehaviour": "CHANGED as of 2026-07-11: GitHub Copilot added a proper '.github/skills/' Agent Skills directory (December 2025), alongside the older single-file .github/copilot-instructions.md convention. This config targets the new skills-directory form. If your Copilot version predates this (pre Dec 2025), use the instructions-append fallback instead (see fallback below).",
26
+ "fallback": {
27
+ "installType": "instructions-append",
28
+ "projectRoot": ".github",
29
+ "filename": "copilot-instructions.md",
30
+ "appendMarker": "<!-- BEGIN: elementor-headless -->",
31
+ "appendMarkerEnd": "<!-- END: elementor-headless -->",
32
+ "embedReferences": [
33
+ "data-model.md",
34
+ "control-types.md",
35
+ "responsive.md"
36
+ ],
37
+ "note": "Use this if your Copilot version does not support .github/skills/ Agent Skills yet."
38
+ },
39
+ "verified": true,
40
+ "verifiedAsOf": "2026-09-06",
41
+ "verificationNote": "The exact frontmatter/loading contract for .github/skills/ SKILL.md was not independently confirmed byte-for-byte at write time - verify against current GitHub Copilot docs before relying on it for a production install.",
42
+ "embedReferences": [
43
+ "data-model.md",
44
+ "failure-modes.md"
45
+ ]
46
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "platform": "cursor",
3
+ "displayName": "Cursor",
4
+ "installType": "rule",
5
+ "folderStructure": {
6
+ "projectRoot": ".cursor",
7
+ "globalRoot": "~/.cursor",
8
+ "skillPath": "rules",
9
+ "filename": "mosaic-headless.mdc"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": false,
14
+ "tools": false,
15
+ "data": false,
16
+ "sites": false
17
+ },
18
+ "frontmatter": {
19
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
20
+ "globs": [
21
+ "**/*.php",
22
+ "**/wp-content/**",
23
+ "**/*.json",
24
+ "**/*.py"
25
+ ],
26
+ "alwaysApply": false
27
+ },
28
+ "loaderBehaviour": "Cursor reads .cursor/rules/*.mdc as Project Rules. Set alwaysApply: true to auto-attach to every chat, or leave false to attach when filename globs match. Cursor does NOT load referenced files automatically - embed key content inline; keep the rule under ~6KB. Subdirectories are supported (.cursor/rules/wp/x.mdc) if you want to split this up further.",
29
+ "embedReferences": [
30
+ "data-model.md",
31
+ "failure-modes.md",
32
+ "responsive.md"
33
+ ],
34
+ "verified": true,
35
+ "verifiedAsOf": "2026-09-06"
36
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ "platform": "gemini-cli",
3
+ "displayName": "Gemini CLI",
4
+ "installType": "full",
5
+ "folderStructure": {
6
+ "projectRoot": ".gemini",
7
+ "globalRoot": "~/.gemini",
8
+ "skillPath": "skills/mosaic-headless",
9
+ "filename": "SKILL.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": true,
14
+ "tools": true,
15
+ "data": true,
16
+ "sites": true
17
+ },
18
+ "frontmatter": {
19
+ "name": "mosaic-headless",
20
+ "description": "Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface (122 node types, 181 node properties, 98 style properties, 53 style states, 151 element classes, 74 dynamic variables, 114 REST routes, 23 tables) instead of guessing, with every node type placed on a live site one at a time and asserted against the delivered HTML, every style and node property swept against the compiled CSS and markup, and 569 responsive declarations checked against the stylesheet the site actually served.",
21
+ "license": "MIT",
22
+ "author": "moksa (https://moksaweb.com)",
23
+ "version": "1.2.0"
24
+ },
25
+ "loaderBehaviour": "CHANGED as of 2026-07-11: Gemini CLI now natively supports the same SKILL.md standard as Claude Code and Codex CLI - the same directory-based skill works unmodified. Gemini CLI discovers skills in this precedence order: built-in, extension skills, ~/.gemini/skills/ (personal), .gemini/skills/ (project, shared via version control). At session start Gemini injects each discovered skill's name+description into the system prompt and calls activate_skill when a task matches.",
26
+ "verified": true,
27
+ "verifiedAsOf": "2026-09-06",
28
+ "verificationNote": "This is a DIFFERENT convention than the older .gemini/extensions/<name>/GEMINI.md extension-wrapper approach some skills still ship - that approach still works for bundling a skill inside a distributable extension, but is no longer the simplest or only path for a standalone skill install. Re-check before assuming either convention if this drifts again.",
29
+ "embedReferences": [
30
+ "data-model.md",
31
+ "failure-modes.md"
32
+ ]
33
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "platform": "windsurf",
3
+ "displayName": "Windsurf (now Devin Desktop)",
4
+ "installType": "rule",
5
+ "folderStructure": {
6
+ "projectRoot": ".devin",
7
+ "globalRoot": null,
8
+ "skillPath": "rules",
9
+ "filename": "mosaic-headless.md"
10
+ },
11
+ "sections": {
12
+ "skill": true,
13
+ "references": false,
14
+ "tools": false,
15
+ "data": false,
16
+ "sites": false
17
+ },
18
+ "frontmatter": null,
19
+ "loaderBehaviour": "CHANGED as of 2026-07-11: Cognition rebranded Windsurf to 'Devin Desktop' on 2026-06-02 (windsurf.com now redirects to devin.ai). New installs should target .devin/rules/*.md as plain markdown (no special frontmatter - group related content with XML-style tags like <workflow>...</workflow>). The old .windsurf/rules/*.md path is kept working as a fallback for pre-rebrand setups. Character limits apply: keep each rule file under ~12,000 characters. References must be embedded inline since Windsurf/Devin does not load referenced files automatically.",
20
+ "fallback": {
21
+ "projectRoot": ".windsurf",
22
+ "skillPath": "rules",
23
+ "filename": "elementor-headless.md",
24
+ "note": "Use this path instead if your installation predates the Devin Desktop rebrand and .devin/rules/ is not recognised."
25
+ },
26
+ "embedReferences": [
27
+ "data-model.md",
28
+ "failure-modes.md",
29
+ "responsive.md"
30
+ ],
31
+ "verified": true,
32
+ "verifiedAsOf": "2026-09-06",
33
+ "verificationNote": "Verify which product name/path applies to your install before running - this is the platform most likely to keep shifting given the recent rebrand."
34
+ }