mosaic-headless 1.29.0 → 1.29.1
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/SKILL.md +5 -5
- package/assets/templates/platforms/claude-ai.json +1 -1
- package/assets/templates/platforms/claude-code.json +1 -1
- package/assets/templates/platforms/codex-cli.json +1 -1
- package/assets/templates/platforms/copilot.json +1 -1
- package/assets/templates/platforms/gemini-cli.json +1 -1
- package/data/component-wall-verification.csv +1 -0
- package/data/content-loop-verification.csv +2 -1
- package/data/form-surface-verification.csv +3 -0
- package/data/mobile-audit.csv +3 -2
- package/data/navigation-verification.csv +9 -9
- package/package.json +1 -1
- package/references/failure-modes.md +45 -0
- package/scripts/check-release.mjs +4 -4
- package/sites/moksa.json +1639 -99
- package/tools/build_page.py +17 -0
- package/tools/verify_components.py +30 -0
package/SKILL.md
CHANGED
|
@@ -4,7 +4,7 @@ description: |
|
|
|
4
4
|
Build and modify Mosaic Pro (Nextend) sites by writing the underlying data model directly - no visual editor, no DOM. Query the real surface with `mo.py`, which joins every source table to the live sweeps so a lookup leads with the measured verdict rather than the declaration (128 node types, 191 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 156 variants, 74 dynamic variables, 15 interaction triggers, 115 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, nine designed pages built through the tables themselves, and the delivered pages re-read in Chromium at three viewports so a rule that is present, correct and still wrong cannot pass. Drives Mosaic's own theme export/import and its plugin data upgrade from outside the editor and holds the copy against the source tree for tree. Measured on Mosaic Pro 1.0.9: the modal (`<dialog>`), OpenStreetMap, the exit-intent and scroll-depth triggers, run rules and the memory actions all built on a live page and read back, and the 1.0.7 -> 1.0.8 -> 1.0.9 migrations driven from outside wp-admin.
|
|
5
5
|
license: "MIT"
|
|
6
6
|
author: "moksa (https://moksaweb.com)"
|
|
7
|
-
version: "1.29.
|
|
7
|
+
version: "1.29.1"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Headless Mosaic
|
|
@@ -535,10 +535,10 @@ so the pattern is in the data, not just in this paragraph.
|
|
|
535
535
|
| `data/dialog-verification.csv` | 19 | **driven live** - the 1.0.9 modal, its triggers, its run rules and the memory actions, each exercised in a real browser |
|
|
536
536
|
| `data/dialog-form-verification.csv` | 49 | **driven live** - the same three nodes made into five FORMS (sheet, drawer, corner, takeover, gate), each re-opened at 390px and 768px; also where `pickOne` on a click turned out to be a latch rather than a lottery |
|
|
537
537
|
| `data/token-verification.csv` | 15 | **driven live** - every `:root` custom property declared once, non-empty, and resolved by something on the page; a token nothing points at is a token that is not working |
|
|
538
|
-
| `data/mobile-audit.csv` |
|
|
539
|
-
| `data/component-wall-verification.csv` |
|
|
540
|
-
| `data/form-surface-verification.csv` |
|
|
541
|
-
| `data/content-loop-verification.csv` |
|
|
538
|
+
| `data/mobile-audit.csv` | 64 | **driven live** - what a sideways-scroll check cannot see: type under the legible floor, controls too small to hit, a grid that never collapsed, content escaping its box |
|
|
539
|
+
| `data/component-wall-verification.csv` | 20 | **driven live** - tabs switched, an accordion opened, a form's fields and Mosaic's own honeypot, and an OpenStreetMap asserted on the coordinates it was GIVEN rather than the default it falls back to |
|
|
540
|
+
| `data/form-surface-verification.csv` | 15 | **driven live** - every field type Mosaic ships in one form: select with labelled options, radio and checkbox groups, file upload, and the browser's own validation refusing an empty submit |
|
|
541
|
+
| `data/content-loop-verification.csv` | 12 | **driven live** - a slider, a tab bar, a list and a paginated archive whose children all come from one authored template repeated per post; the pagination is clicked and the rows asserted to CHANGE |
|
|
542
542
|
| `data/custom-fields-verification.csv` | 62 | **rendered live** - ACF and Meta Box fields of every common type read back through `@VAR` / `@LOOP` off the delivered page, loops included |
|
|
543
543
|
| `data/theme-zip-verification.csv` | 22 | **round-tripped live** - Mosaic's own ZIP export imported in test mode and compared to its source, table by table and tree by tree |
|
|
544
544
|
| `data/node-type-notes.csv` | 8 | where a sweep outcome is true but misleading on its own, why. Surfaced by `mo.py type` |
|
|
@@ -20,7 +20,7 @@
|
|
|
20
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
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.29.
|
|
23
|
+
"version": "1.29.1"
|
|
24
24
|
},
|
|
25
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
26
|
"uploadSteps": [
|
|
@@ -20,7 +20,7 @@
|
|
|
20
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
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.29.
|
|
23
|
+
"version": "1.29.1"
|
|
24
24
|
},
|
|
25
25
|
"loaderBehaviour": "Auto-loads on session start when SKILL.md frontmatter parses successfully.",
|
|
26
26
|
"verified": true,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
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
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.29.
|
|
23
|
+
"version": "1.29.1"
|
|
24
24
|
},
|
|
25
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
26
|
"verified": true,
|
|
@@ -20,7 +20,7 @@
|
|
|
20
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
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.29.
|
|
23
|
+
"version": "1.29.1"
|
|
24
24
|
},
|
|
25
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
26
|
"fallback": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
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
21
|
"license": "MIT",
|
|
22
22
|
"author": "moksa (https://moksaweb.com)",
|
|
23
|
-
"version": "1.29.
|
|
23
|
+
"version": "1.29.1"
|
|
24
24
|
},
|
|
25
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
26
|
"verified": true,
|
|
@@ -10,6 +10,7 @@ FORM/required,PASS,required is set on 3 of them
|
|
|
10
10
|
FORM/honeypot,PASS,"Mosaic adds its own spam trap: ['mosaic_hp_url', 'mosaic_hp_ts']"
|
|
11
11
|
FORM/option_labels,SKIPPED,no select on this form
|
|
12
12
|
FORM/required_blocks,PASS,"empty form reports invalid: ['name', 'email', 'message']"
|
|
13
|
+
MULTISTEP,SKIPPED,not on this page
|
|
13
14
|
COMPONENT/instances,PASS,"3 instances: ['cs-0-cs-card', 'cs-1-cs-card', 'cs-2-cs-card']"
|
|
14
15
|
COMPONENT/one_definition,PASS,"all share the generated class ['_fm'] - one definition, not 3 copies"
|
|
15
16
|
COMPONENT/content_differs,PASS,"3 instances, 3 distinct bodies - the overrides are per-instance"
|
|
@@ -2,11 +2,12 @@ check,result,detail
|
|
|
2
2
|
TABS,SKIPPED,not on this page
|
|
3
3
|
ACCORDION,SKIPPED,not on this page
|
|
4
4
|
FORM,SKIPPED,not on this page
|
|
5
|
+
MULTISTEP,SKIPPED,not on this page
|
|
5
6
|
COMPONENT/instances,SKIPPED,fewer than two on this page
|
|
6
7
|
LOOP/slider,PASS,6 slides from one authored slider-slide
|
|
7
8
|
LOOP/tabs,PASS,4 tabs from one authored tabs-tab
|
|
8
9
|
LOOP/tab_labels_intact,PASS,"no replacement characters - @substr counts bytes, so a length that is not a multiple of the encoding cuts a glyph in half"
|
|
9
|
-
LOOP/pagination_links,PASS,"3 page links: ['v=
|
|
10
|
+
LOOP/pagination_links,PASS,"3 page links: ['v=18823¬es=1', 'v=18823¬es=2', 'v=18823¬es=3']"
|
|
10
11
|
LOOP/pagination_key_is_safe,PASS,paginationKey does not collide with a WordPress query var
|
|
11
12
|
LOOP/pagination_changes_rows,PASS,page 1 3 -> page 2 3
|
|
12
13
|
MAP,SKIPPED,not on this page
|
|
@@ -6,6 +6,9 @@ FORM/required,PASS,required is set on 8 of them
|
|
|
6
6
|
FORM/honeypot,PASS,"Mosaic adds its own spam trap: ['mosaic_hp_url', 'mosaic_hp_ts']"
|
|
7
7
|
FORM/option_labels,PASS,"5 options, all labelled"
|
|
8
8
|
FORM/required_blocks,PASS,"empty form reports invalid: ['name', 'email', 'kind', 'kind']"
|
|
9
|
+
MULTISTEP/one_at_rest,PASS,visible steps: [0]
|
|
10
|
+
MULTISTEP/next,PASS,NEXT -> [1]
|
|
11
|
+
MULTISTEP/back,PASS,BACK -> [0]
|
|
9
12
|
COMPONENT/instances,SKIPPED,fewer than two on this page
|
|
10
13
|
LOOP/slider,SKIPPED,not on this page
|
|
11
14
|
LOOP/tabs,SKIPPED,not on this page
|
package/data/mobile-audit.csv
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
path,width,finding,element,detail
|
|
2
|
+
forms/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
2
3
|
components/,390,GRID_NOT_COLLAPSED,cp-tabs-menu,2 columns at 390px
|
|
3
4
|
components/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
4
5
|
content/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
5
|
-
forms/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
6
6
|
dialogs/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
7
7
|
sliders/,390,SMALL_TARGET,sl-main-nav-dot,34x28:
|
|
8
8
|
sliders/,390,SMALL_TARGET,sl-main-nav-dot,34x28:
|
|
@@ -18,11 +18,12 @@ sliders/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
|
18
18
|
tokens/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
19
19
|
dynamic/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
20
20
|
conversion/,390,GRID_NOT_COLLAPSED,mk-f-links,2 columns at 390px
|
|
21
|
+
forms/,768,LONG_MEASURE,m-text,59 chars/line
|
|
22
|
+
forms/,768,LONG_MEASURE,m-text,59 chars/line
|
|
21
23
|
components/,768,LONG_MEASURE,m-text,44 chars/line
|
|
22
24
|
components/,768,LONG_MEASURE,m-text,56 chars/line
|
|
23
25
|
content/,768,LONG_MEASURE,m-text,43 chars/line
|
|
24
26
|
content/,768,LONG_MEASURE,m-text,58 chars/line
|
|
25
|
-
forms/,768,LONG_MEASURE,m-text,59 chars/line
|
|
26
27
|
dialogs/,768,LONG_MEASURE,m-text,46 chars/line
|
|
27
28
|
dialogs/,768,LONG_MEASURE,m-text,45 chars/line
|
|
28
29
|
dialogs/,768,LONG_MEASURE,m-text,45 chars/line
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
check,result,detail
|
|
2
|
-
FRONT_PAGE,PASS,"HTTP 200,
|
|
2
|
+
FRONT_PAGE,PASS,"HTTP 200, 240832 bytes"
|
|
3
3
|
MENU_IS_LINKS,PASS,1 real <a href> in #mk-nav
|
|
4
|
-
NAV 首頁,PASS,"/ -> HTTP 200,
|
|
5
|
-
PAGE moksa,PASS,"HTTP 200,
|
|
6
|
-
PAGE my-account,PASS,"HTTP 200,
|
|
7
|
-
PAGE intro,PASS,"HTTP 200,
|
|
4
|
+
NAV 首頁,PASS,"/ -> HTTP 200, 240832 bytes"
|
|
5
|
+
PAGE moksa,PASS,"HTTP 200, 240833 bytes"
|
|
6
|
+
PAGE my-account,PASS,"HTTP 200, 101037 bytes"
|
|
7
|
+
PAGE intro,PASS,"HTTP 200, 134746 bytes"
|
|
8
8
|
PAGE content,PASS,"HTTP 200, 102378 bytes"
|
|
9
|
-
PAGE forms,PASS,"HTTP 200,
|
|
10
|
-
PAGE components,PASS,"HTTP 200,
|
|
11
|
-
PAGE conversion,PASS,"HTTP 200,
|
|
9
|
+
PAGE forms,PASS,"HTTP 200, 126731 bytes"
|
|
10
|
+
PAGE components,PASS,"HTTP 200, 119522 bytes"
|
|
11
|
+
PAGE conversion,PASS,"HTTP 200, 103205 bytes"
|
|
12
12
|
PAGE dynamic,PASS,"HTTP 200, 112622 bytes"
|
|
13
|
-
PAGE tokens,PASS,"HTTP 200,
|
|
13
|
+
PAGE tokens,PASS,"HTTP 200, 125794 bytes"
|
|
14
14
|
PAGE sliders,PASS,"HTTP 200, 151809 bytes"
|
|
15
15
|
PAGE dialogs,PASS,"HTTP 200, 207347 bytes"
|
|
16
16
|
ANCHORS moksa,PASS,every in-page link resolves
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mosaic-headless",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.1",
|
|
4
4
|
"description": "AI-agent skill: build Mosaic Pro (Nextend) WordPress sites by writing the underlying data model directly - 23 custom tables, no visual editor, no DOM. Every node type, style property and node property swept against a live install and asserted on the delivered HTML and compiled CSS. Installs into Claude Code, Cursor, Codex CLI, Gemini CLI, Copilot, Continue, Windsurf and Claude.ai.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wordpress",
|
|
@@ -399,3 +399,48 @@ The through-line is the one this file keeps recording: Mosaic accepts a write it
|
|
|
399
399
|
cannot use and says nothing. The defence is to read the delivered page back and
|
|
400
400
|
count what arrived — `verify_components.py` now asserts the control count, the option
|
|
401
401
|
labels and that an empty required form is actually refused.
|
|
402
|
+
|
|
403
|
+
## `display` on an element whose visibility the plugin owns — twice now
|
|
404
|
+
|
|
405
|
+
A `<dialog>`'s open state is its `display`, so `display:flex` on a modal host pins
|
|
406
|
+
every modal open. The same mistake, in a different family: `multi-steps-form-step`
|
|
407
|
+
is shown and hidden by the plugin moving `m-form-step--active`, and a `display:flex`
|
|
408
|
+
on the step wins the cascade, so all three steps sit on the page at once with three
|
|
409
|
+
sets of Next buttons.
|
|
410
|
+
|
|
411
|
+
The rule that comes out of it: **if something other than you decides when an
|
|
412
|
+
element is visible, do not set `display` on that element.** Put the layout on a
|
|
413
|
+
child. The families to watch are the ones whose markup carries an `--active` /
|
|
414
|
+
`--opened` class: `modal`, `multi-steps-form-step`, `tabs-tab-pane`,
|
|
415
|
+
`dropdown-wrapper`, `success-screen`, `loop-no-result`.
|
|
416
|
+
|
|
417
|
+
`tabs-tab-pane` is the one that does NOT bite, and the reason is instructive — the
|
|
418
|
+
plugin hides it with `!important`:
|
|
419
|
+
|
|
420
|
+
```css
|
|
421
|
+
.m-tab-pane:not(.m-tab-pane--active){display:none !important}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Nothing an author writes can beat that. The two that bite are precisely the two
|
|
425
|
+
where the plugin relies on the UA default or on the theme instead.
|
|
426
|
+
|
|
427
|
+
## Mosaic ships no visibility CSS for a form step
|
|
428
|
+
|
|
429
|
+
Measured: the step navigation works — `m-form-step--active` moves, the step tabs
|
|
430
|
+
change state, Next and Back fire — and **every panel stays on screen**, because
|
|
431
|
+
hiding the inactive ones was never the plugin's job. The variant catalog carries a
|
|
432
|
+
`Form step` entry (`.m-form-step`), and that is where the rule is meant to live.
|
|
433
|
+
A theme that never styles that variant gets a multi-step form that is one long
|
|
434
|
+
page.
|
|
435
|
+
|
|
436
|
+
So a multi-step form needs one rule the author supplies:
|
|
437
|
+
|
|
438
|
+
```css
|
|
439
|
+
.m-form-step:not(.m-form-step--active){display:none}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
On a theme that cannot use the variant layer, a `code` node with
|
|
443
|
+
`insertLocation: "head"` is the escape hatch — and **it emits its content
|
|
444
|
+
verbatim**: it does not wrap anything, so the `<style>` tags are yours to write.
|
|
445
|
+
Without them the rule lands in `<head>` as bare text between `</style>` and
|
|
446
|
+
`</head>`, renders nothing, and reads as a CSS specificity problem.
|
|
@@ -101,10 +101,10 @@ const counts = {
|
|
|
101
101
|
"data/dialog-verification.csv": 19,
|
|
102
102
|
"data/slider-verification.csv": 30,
|
|
103
103
|
"data/token-verification.csv": 15,
|
|
104
|
-
"data/mobile-audit.csv":
|
|
105
|
-
"data/component-wall-verification.csv":
|
|
106
|
-
"data/form-surface-verification.csv":
|
|
107
|
-
"data/content-loop-verification.csv":
|
|
104
|
+
"data/mobile-audit.csv": 64,
|
|
105
|
+
"data/component-wall-verification.csv": 20,
|
|
106
|
+
"data/form-surface-verification.csv": 15,
|
|
107
|
+
"data/content-loop-verification.csv": 12,
|
|
108
108
|
"data/navigation-verification.csv": 36,
|
|
109
109
|
"data/page-modal-verification.csv": 19,
|
|
110
110
|
"data/interaction-rules-verification.csv": 17,
|