mosaic-headless 1.18.0 → 1.20.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 (41) hide show
  1. package/README.ja.md +8 -4
  2. package/README.ko.md +8 -4
  3. package/README.md +8 -4
  4. package/README.zh-TW.md +8 -4
  5. package/SKILL.md +77 -24
  6. package/assets/templates/platforms/claude-ai.json +1 -1
  7. package/assets/templates/platforms/claude-code.json +1 -1
  8. package/assets/templates/platforms/codex-cli.json +1 -1
  9. package/assets/templates/platforms/copilot.json +1 -1
  10. package/assets/templates/platforms/gemini-cli.json +1 -1
  11. package/bin/check-release.mjs +5 -3
  12. package/data/accordion-verification.csv +1 -1
  13. package/data/condition-subjects.csv +56 -56
  14. package/data/conversion-batch.csv +2 -2
  15. package/data/custom-fields-verification.csv +63 -0
  16. package/data/data-class-hierarchy.csv +4 -0
  17. package/data/dialog-verification.csv +20 -0
  18. package/data/interaction-types.csv +15 -12
  19. package/data/intro-verification.csv +7 -7
  20. package/data/loop-verification.csv +1 -1
  21. package/data/node-properties.csv +9 -0
  22. package/data/node-property-verification.csv +88 -79
  23. package/data/node-types.csv +13 -9
  24. package/data/node-verification.csv +99 -95
  25. package/data/placement-rules.csv +4 -0
  26. package/data/pluggables.csv +42 -0
  27. package/data/rest-routes.csv +2 -1
  28. package/data/style-properties.csv +6 -6
  29. package/data/style-verification.csv +79 -79
  30. package/data/theme-zip-verification.csv +5 -5
  31. package/data/variants.csv +12 -8
  32. package/package.json +1 -1
  33. package/references/custom-fields.md +112 -0
  34. package/references/dialog-and-triggers.md +201 -0
  35. package/tools/build_page.py +9 -1
  36. package/tools/list_fields.php +88 -0
  37. package/tools/sweep_node_properties.py +21 -5
  38. package/tools/sweep_node_types.py +85 -0
  39. package/tools/sweep_style_properties.py +10 -24
  40. package/tools/verify_dialog.py +302 -0
  41. package/tools/verify_rwd.py +11 -27
package/README.ja.md CHANGED
@@ -137,15 +137,15 @@ commit の成功はページが動く証拠ではないし、正しいスタイ
137
137
 
138
138
  ## 何を、どう検証したか
139
139
 
140
- すべて実際のインストールに対して実行 — WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.8、
140
+ すべて実際のインストールに対して実行 — WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.9、
141
141
  **ライセンスなし**:ライセンスが制限するのはテーマライブラリと更新であってノードファクトリ
142
142
  ではないので、Pro の型も登録・描画される。
143
143
 
144
144
  | 項目 | 結果 |
145
145
  |---|---|
146
- | **ノード型** | 122 / 122 を 1 型 1 ドキュメントでスイープ、commit → 描画 → 断言 → 削除:70 RENDERED、25 COMMITTED、15 COMMIT_5xx、12 BROKE_PAGE。1.0.8 で再スイープ:以前は黙って commit されていた 5 型が、親なしではページを落とすようになった。描画されなかった行のうち 3 つは「必要な親なしで commit した」というスイープ手法の産物で、その旨が行の横にある |
146
+ | **ノード型** | 122 / 122 を 1 型 1 ドキュメントでスイープ、commit → 描画 → 断言 → 削除:74 RENDERED、25 COMMITTED、15 COMMIT_5xx、12 BROKE_PAGE。1.0.8 で再スイープ:以前は黙って commit されていた 5 型が、親なしではページを落とすようになった。描画されなかった行のうち 3 つは「必要な親なしで commit した」というスイープ手法の産物で、その旨が行の横にある |
147
147
  | **スタイルプロパティ** | 98 / 98 を実ページに書き、コンパイル済み CSS と照合:58 COMPILED、18 ABSENT、21 SKIPPED |
148
- | **ノードプロパティ** | 182 / 182 を各プロパティ自身のバリデータ連鎖から導いた値で再探査:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
148
+ | **ノードプロパティ** | 191 / 191 を各プロパティ自身のバリデータ連鎖から導いた値で再探査:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
149
149
  | **レスポンシブ** | 2 サイト計 731 件の `_t`/`_m` 宣言を、サイトが実際に配信したスタイルシートに対して 1 件ずつ断言 — 全件検証済み |
150
150
  | **ブラウザ** | 配信された 2 ページを Chromium の 3 つのビューポートで計算スタイル 3,988 件読み取り:2,929 件が一致、912 件は比較不能として明示、**上書き 0 件** |
151
151
  | **デザイン監査** | コントラスト、フォントフォールバック、CJK の字送り、横溢れ、テキストの切れ、1 行の文字数 — ブラウザ上で実行、**指摘 26 件、すべて理由付きで裁定済み** — 理由のない容認はリリースゲートが拒否する |
@@ -158,7 +158,9 @@ commit の成功はページが動く証拠ではないし、正しいスタイ
158
158
  | **Elementor 変換** | 本番サイトの全 Elementor ページ — 19 ページ、3,292 要素 — を変換・構築し、元と照合:**19 件中 19 件**、3,281 要素を運び、11 要素を明示的に除外。さらに変換後ページをレスポンシブ・ブラウザ・監査にかけ、指摘をすべて「継承」か「導入」かに分類:**導入 0 件** |
159
159
  | **テーマの書き出し/読み込み** | 経路は二つ、どちらも往復検証済み。`theme_export.php` は WP-CLI で行を JSON として移し、id は不変。`theme_zip.py` は Mosaic **自身**の ZIP 書き出し/読み込みを駆動 — 読み込みは `--activate` を付けない限りテストモードに入る、既定がライブサイトの切り替えだからだ — **22 項目**でコピーを元とツリー単位で突き合わせる |
160
160
  | **スキル自身** | `claude plugin eval .` — ユーザーが実際に尋ねる 5 問を各 3 回、スキルあり/なしの 2 腕、1 回ごとに LLM 審査 3 名。**あり:5 問すべて 1.00。なし:5 問すべて 0.00。** ベースラインの最善の回答は回答拒否だった |
161
- | **ライブ計測** | REST ルート 114、variant 152、条件サブジェクト 59、23 テーブル / 210 カラム |
161
+ | **ライブ計測** | REST ルート 115、variant 156、条件サブジェクト 59、23 テーブル / 210 カラム |
162
+ | **1.0.9 の新機能** | modal(`<dialog>`)、OpenStreetMap、exit-intent と scroll-depth のトリガー、run rules、memory アクション、modal ショートハンド — すべて実ページに作り、ブラウザで実際に操作:19 / 19。「離脱時ポップアップを 1 セッション 1 回」が配線なしのオブジェクト 1 つで済む |
163
+ | **カスタムフィールド** | ACF と Meta Box、1 ページに 40 フィールド、`@VAR` / `@LOOP` で配信 HTML から読み戻し:62 のうち 59 が解決、3 つの空は理由付き;複数値フィールドのループはフィールドの行数どおりに描画。`tools/list_fields.php` が Mosaic の実際の登録名を出す |
162
164
  | **ライブ更新** | 1.0.7 → 1.0.8 をプラグイン自身の milestone ルートで wp-admin の外から駆動:6 milestone、4 テーブル改名、出力クラス名は全部変わり、`customStyles` は全部書き換え — その結果に対して上の計測をすべて再実行 |
163
165
 
164
166
  `SKIPPED`、`NO_HOST`、`INCONCLUSIVE` は合格率に決して繰り込まない。自らの盲点を成功として
@@ -237,6 +239,8 @@ loop grid、フォーム、カウントダウン、サードパーティ addon
237
239
  | `verify_intro.py` / `verify_loop.py` | 「終わる」ロードアニメーション;ループし、何も隠さず、開く常時アニメーション |
238
240
  | `theme_export.php` / `theme_import.php` | テーマ全体を JSON 行として WP-CLI で移動、id は不変 |
239
241
  | `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | Mosaic 自身の ZIP 書き出し/読み込みをエディタの外から駆動、コピーを元とツリー単位で照合、ライブテーマを拒否する完全削除 |
242
+ | `list_fields.php` | ある投稿のカスタムフィールドが登録する `@VAR` / `@LOOP` 名をすべて、値付きで |
243
+ | `verify_dialog.py` | 1.0.9 の modal・トリガー・run rules・memory をブラウザで実操作 |
240
244
  | `data_upgrade.py` | プラグイン更新後、Mosaic のデータ移行を自身の milestone ルートで実行 — 終わるまでエディタ API は存在しない |
241
245
  | `sweep_*.py` / `probe_*.py` | 表を作った計測器そのもの |
242
246
  | `bootstrap_probe_theme.php` / `mint_session.php` | ライセンス不要の実験用テーマと、WP-CLI から作る REST セッション |
package/README.ko.md CHANGED
@@ -133,15 +133,15 @@ commit 성공은 페이지가 동작한다는 증거가 아니고, 올바른 스
133
133
 
134
134
  ## 무엇을, 어떻게 검증했나
135
135
 
136
- 전부 실제 설치에서 실행 — WordPress 7.1, WooCommerce 11.1, Mosaic Pro 1.0.8, **라이선스 없음**:
136
+ 전부 실제 설치에서 실행 — WordPress 7.1, WooCommerce 11.1, Mosaic Pro 1.0.9, **라이선스 없음**:
137
137
  라이선스가 막는 것은 테마 라이브러리와 업데이트지 노드 팩토리가 아니라서 Pro 타입도 등록되고
138
138
  렌더링된다.
139
139
 
140
140
  | 항목 | 결과 |
141
141
  |---|---|
142
- | **노드 타입** | 122 / 122를 문서당 하나씩 스윕, commit → 렌더 → 단언 → 삭제: 70 RENDERED, 25 COMMITTED, 15 COMMIT_5xx, 12 BROKE_PAGE. 1.0.8에서 재스윕: 전에는 조용히 commit되던 5개 타입이 부모 없이는 페이지를 죽인다. 렌더되지 않은 행 중 셋은 "필요한 부모 없이 commit"한 스윕 방식의 산물이며, 그 사실이 행 옆에 적혀 있다 |
142
+ | **노드 타입** | 122 / 122를 문서당 하나씩 스윕, commit → 렌더 → 단언 → 삭제: 74 RENDERED, 25 COMMITTED, 15 COMMIT_5xx, 12 BROKE_PAGE. 1.0.8에서 재스윕: 전에는 조용히 commit되던 5개 타입이 부모 없이는 페이지를 죽인다. 렌더되지 않은 행 중 셋은 "필요한 부모 없이 commit"한 스윕 방식의 산물이며, 그 사실이 행 옆에 적혀 있다 |
143
143
  | **스타일 프로퍼티** | 98 / 98을 실제 페이지에 쓰고 컴파일된 CSS와 대조: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
144
- | **노드 프로퍼티** | 182 / 182을 각 프로퍼티 자신의 검증기 체인에서 도출한 값으로 재탐사: 35 APPLIED, 43 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
144
+ | **노드 프로퍼티** | 191 / 191을 각 프로퍼티 자신의 검증기 체인에서 도출한 값으로 재탐사: 35 APPLIED, 43 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
145
145
  | **반응형** | 두 사이트 합쳐 731개의 `_t`/`_m` 선언을, 사이트가 실제로 내보낸 스타일시트에 대해 하나씩 단언 — 전부 검증됨 |
146
146
  | **브라우저** | 전달된 두 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일 3,988건 판독: 2,929건 일치, 912건은 비교 불가로 명시, **덮어쓰기 0건** |
147
147
  | **디자인 감사** | 명암비, 폰트 폴백, CJK 자간, 가로 넘침, 텍스트 잘림, 한 줄 글자 수 — 브라우저에서 실행, **지적 26건, 모두 서면으로 판정** — 이유 없는 승인은 릴리스 게이트가 거부한다 |
@@ -154,7 +154,9 @@ commit 성공은 페이지가 동작한다는 증거가 아니고, 올바른 스
154
154
  | **Elementor 변환** | 운영 사이트의 모든 Elementor 페이지 — 19페이지, 3,292 요소 — 를 변환·구축하고 원본과 대조: **19건 중 19건**, 3,281 요소 이전, 11 요소 명시적 제외. 이어 변환된 페이지를 반응형·브라우저·감사에 통과시키고 모든 지적을 "상속"과 "도입"으로 분류: **도입 0건** |
155
155
  | **테마 내보내기/가져오기** | 두 경로, 모두 왕복 검증. `theme_export.php`는 WP-CLI로 행을 JSON으로 옮기며 id는 그대로. `theme_zip.py`는 Mosaic **자체**의 ZIP 내보내기/가져오기를 구동 — 가져오기는 `--activate`가 없으면 테스트 모드에 놓이는데, 기본값이 라이브 사이트 전환이기 때문이다 — **22개 검사**로 사본을 원본과 트리 단위로 대조 |
156
156
  | **스킬 자체** | `claude plugin eval .` — 사용자가 실제로 묻는 5문항을 각 3회, 스킬 있음/없음 두 팔로, 매회 LLM 심사 3명. **있음: 5문항 모두 1.00. 없음: 5문항 모두 0.00.** 베이스라인의 최선은 답변 거부였다 |
157
- | **라이브 측정** | REST 라우트 114, variant 152, 조건 subject 59, 23 테이블 / 210 컬럼 |
157
+ | **라이브 측정** | REST 라우트 115, variant 156, 조건 subject 59, 23 테이블 / 210 컬럼 |
158
+ | **1.0.9 신기능** | modal(`<dialog>`), OpenStreetMap, exit-intent·scroll-depth 트리거, run rules, memory 액션, modal 숏핸드를 실제 페이지에 만들고 브라우저에서 직접 조작: 19/19. "이탈 의도 팝업, 세션당 한 번"이 배선 없이 객체 하나 |
159
+ | **커스텀 필드** | ACF와 Meta Box, 한 페이지에 40개 필드, `@VAR` / `@LOOP`로 전달된 HTML에서 읽어냄: 62개 중 59개 해석, 빈 3개는 이유 있음; 다중값 필드 루프는 필드의 행 수 그대로 렌더링. `tools/list_fields.php`가 Mosaic이 실제 등록하는 이름을 출력 |
158
160
  | **라이브 업그레이드** | 1.0.7 → 1.0.8을 플러그인 자체 milestone 라우트로 wp-admin 밖에서 구동: 6 milestone, 테이블 4개 이름 변경, 출력 클래스 이름 전부 변경, `customStyles` 전부 재작성 — 그 결과 위에서 위의 측정을 전부 다시 실행 |
159
161
 
160
162
  `SKIPPED`, `NO_HOST`, `INCONCLUSIVE`는 결코 합격률에 섞지 않는다. 자기 사각지대를 성공으로
@@ -231,6 +233,8 @@ loop grid, 폼, 카운트다운, 서드파티 addon — 은 동적이라 될 노
231
233
  | `verify_intro.py` / `verify_loop.py` | "끝나는" 로드 애니메이션; 루프하고, 아무것도 가리지 않고, 열리는 상시 애니메이션 |
232
234
  | `theme_export.php` / `theme_import.php` | 테마 전체를 JSON 행으로 WP-CLI를 통해 이동, id 그대로 |
233
235
  | `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | Mosaic 자체 ZIP 내보내기/가져오기를 에디터 밖에서 구동, 사본을 원본과 트리 단위로 대조, 라이브 테마를 거부하는 깨끗한 삭제 |
236
+ | `list_fields.php` | 한 글의 커스텀 필드가 등록하는 모든 `@VAR` / `@LOOP` 이름을 값과 함께 |
237
+ | `verify_dialog.py` | 1.0.9의 modal·트리거·run rules·memory를 브라우저에서 실제 조작 |
234
238
  | `data_upgrade.py` | 플러그인 업데이트 후 Mosaic의 데이터 이관을 자체 milestone 라우트로 실행 — 끝나기 전까지 에디터 API는 존재하지 않는다 |
235
239
  | `sweep_*.py` / `probe_*.py` | 표를 만든 계측기 그 자체 |
236
240
  | `bootstrap_probe_theme.php` / `mint_session.php` | 라이선스 없는 실험용 테마와 WP-CLI에서 만드는 REST 세션 |
package/README.md CHANGED
@@ -143,14 +143,14 @@ than any naive healthy-page floor.
143
143
  ## What was verified, and how
144
144
 
145
145
  Everything ran against a live install — WordPress 7.1, WooCommerce 11.1, Mosaic Pro
146
- 1.0.8, **unlicensed**: the licence gates the theme library and updates, not the node
146
+ 1.0.9, **unlicensed**: the licence gates the theme library and updates, not the node
147
147
  factories, so Pro types register and render regardless.
148
148
 
149
149
  | pass | result |
150
150
  |---|---|
151
- | **node types** | 122 / 122 swept one per document, committed → rendered → asserted → deleted: 70 RENDERED, 25 COMMITTED, 15 COMMIT_5xx, 12 BROKE_PAGE. Re-swept on 1.0.8: five types that used to commit silently now kill the page unparented. The non-rendering rows that are artefacts of committing without the required parent say so beside the row |
151
+ | **node types** | 122 / 122 swept one per document, committed → rendered → asserted → deleted: 74 RENDERED, 25 COMMITTED, 15 COMMIT_5xx, 12 BROKE_PAGE. Re-swept on 1.0.8: five types that used to commit silently now kill the page unparented. The non-rendering rows that are artefacts of committing without the required parent say so beside the row |
152
152
  | **style properties** | 98 / 98 written to a live page and checked against the compiled CSS: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
153
- | **node properties** | 182 / 182 re-probed with a value shaped by each property's own validator chain: 35 APPLIED, 43 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
153
+ | **node properties** | 191 / 191 re-probed with a value shaped by each property's own validator chain: 35 APPLIED, 43 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
154
154
  | **responsive** | 731 `_t`/`_m` declarations across two sites asserted against the stylesheet the site actually served — all verified |
155
155
  | **browser** | 3,988 computed-style readings on two delivered pages in Chromium at three viewports: 2,929 compared and agreed, 912 not-comparable and labelled, **0 overridden** |
156
156
  | **design audit** | contrast, font fallback, CJK tracking, overflow, clipped text, line measure — run in the browser, **26 findings, every one ruled on in writing** — an acknowledgement without a reason is refused by the release gate |
@@ -163,7 +163,9 @@ factories, so Pro types register and render regardless.
163
163
  | **Elementor conversion** | every Elementor page of a production site — 19 pages, 3,292 elements — converted, built and checked against its source: **19 of 19**, 3,281 elements carried, 11 declared. Then the converted page through rwd, browser and the audit, with every finding classified inherited-or-introduced: **0 introduced** |
164
164
  | **theme export/import** | two paths, both round-tripped. `theme_export.php` moves rows as JSON over WP-CLI, ids intact. `theme_zip.py` drives Mosaic's **own** ZIP export/import — import lands in test mode unless told `--activate`, because the default is to switch the live site — and **22 checks** hold the copy against the source tree for tree |
165
165
  | **the skill itself** | `claude plugin eval .` — five cases a user would ask, three runs each, with and without the skill loaded, three LLM judges a run. **With: 1.00 on all five. Without: 0.00 on all five.** The baseline's best answer was to refuse |
166
- | **measured live** | 114 REST routes, 152 variants, 59 condition subjects, 23 tables / 210 columns |
166
+ | **measured live** | 115 REST routes, 156 variants, 59 condition subjects, 23 tables / 210 columns |
167
+ | **1.0.9 features** | the modal (`<dialog>`), OpenStreetMap, the exit-intent and scroll-depth triggers, run rules, memory actions and the modal shorthand, each built on a live page and exercised in a real browser: 19 of 19. An exit-intent popup that fires once a session is one object, no wiring |
168
+ | **custom fields** | ACF and Meta Box, forty fields on a page, read back through `@VAR` / `@LOOP` off the delivered HTML: 59 of 62 resolve, 3 empties explained; loops over multi-value fields rendered exactly the field's rows. `tools/list_fields.php` prints the names Mosaic actually registers |
167
169
  | **upgraded live** | 1.0.7 -> 1.0.8 over the plugin's own milestone route, from outside wp-admin: 6 milestones, four tables renamed, every emitted class name changed, every `customStyles` rewritten - then every sweep above re-run on the result |
168
170
 
169
171
  `SKIPPED`, `NO_HOST` and `INCONCLUSIVE` are never folded into a pass rate. A sweep
@@ -246,6 +248,8 @@ and heading level — and it earned its place at once: it caught the converter l
246
248
  | `verify_intro.py` / `verify_loop.py` | a page-load sequence that ENDS; a perpetual one that loops, hides nothing, and opens |
247
249
  | `theme_export.php` / `theme_import.php` | a whole theme as JSON rows over WP-CLI, ids intact |
248
250
  | `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | Mosaic's own ZIP export/import from outside the editor, the copy held against the source, and a clean delete that refuses the live theme |
251
+ | `list_fields.php` | every `@VAR` / `@LOOP` name a post's custom fields register, with values |
252
+ | `verify_dialog.py` | the 1.0.9 modal, triggers, run rules and memory, driven in a browser |
249
253
  | `data_upgrade.py` | after a plugin update, Mosaic's data migration over its own milestone route - the editor API is gone until it runs |
250
254
  | `sweep_*.py` / `probe_*.py` | the instruments the tables were made with |
251
255
  | `bootstrap_probe_theme.php` / `mint_session.php` | a licence-free scratch theme and a REST session from WP-CLI |
package/README.zh-TW.md CHANGED
@@ -127,14 +127,14 @@ commit 成功不代表頁面能用,樣式表正確也不代表。這裡每個
127
127
 
128
128
  ## 驗證了什麼,怎麼驗的
129
129
 
130
- 全部在真實站台上跑——WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.8,**未授權**:
130
+ 全部在真實站台上跑——WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.9,**未授權**:
131
131
  授權鎖的是主題庫和更新,不是節點工廠,所以 Pro 型別照樣註冊、照樣渲染。
132
132
 
133
133
  | 項目 | 結果 |
134
134
  |---|---|
135
- | **節點型別** | 122 / 122 逐一放進獨立文件,寫入 → 渲染 → 斷言 → 刪除:70 RENDERED、25 COMMITTED、15 COMMIT_5xx、12 BROKE_PAGE。在 1.0.8 上重掃:五個以前默默寫入的型別,沒放對父節點現在會直接弄死頁面。未渲染的當中有三個是「沒給父層」的掃描方法產物,註記就在列旁 |
135
+ | **節點型別** | 122 / 122 逐一放進獨立文件,寫入 → 渲染 → 斷言 → 刪除:74 RENDERED、25 COMMITTED、15 COMMIT_5xx、12 BROKE_PAGE。在 1.0.8 上重掃:五個以前默默寫入的型別,沒放對父節點現在會直接弄死頁面。未渲染的當中有三個是「沒給父層」的掃描方法產物,註記就在列旁 |
136
136
  | **樣式屬性** | 98 / 98 寫進真實頁面、對照編譯出的 CSS:58 COMPILED、18 ABSENT、21 SKIPPED |
137
- | **節點屬性** | 182 / 182 用各自驗證鏈推出的值重新探測:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
137
+ | **節點屬性** | 191 / 191 用各自驗證鏈推出的值重新探測:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
138
138
  | **響應式** | 兩個站共 731 條 `_t`/`_m` 宣告,對照網站實際送出的樣式表逐條斷言——全數通過 |
139
139
  | **瀏覽器** | 在 Chromium 三個視窗寬度上對兩個交付頁面做 3,988 次計算樣式讀取:2,929 條比對相符、912 條標為無法比對、**0 條被覆蓋** |
140
140
  | **設計稽核** | 對比度、字體回退、CJK 字距、水平溢出、文字裁切、每行字數——在瀏覽器裡跑,**26 項發現,每一項都有書面裁定**——沒寫理由的 acknowledge 會被發布閘門拒絕 |
@@ -147,7 +147,9 @@ commit 成功不代表頁面能用,樣式表正確也不代表。這裡每個
147
147
  | **Elementor 轉換** | 一個正式站的全部 Elementor 頁面——19 頁、3,292 個元素——轉換、建置、對照來源檢查:**19 之 19**,3,281 個元素搬過去、11 個書面宣告。再把轉出的頁面跑過響應式、瀏覽器和稽核,每一項發現都分類為「繼承」或「引入」:**引入 0 個** |
148
148
  | **主題匯出/匯入** | 兩條路徑,都來回驗證過。`theme_export.php` 用 WP-CLI 把資料列搬成 JSON、ID 不變。`theme_zip.py` 驅動 Mosaic **自己**的 ZIP 匯出匯入——匯入預設進 test mode,要 `--activate` 才上線,因為它的預設是直接切換 live 站——**22 項檢查**逐表、逐樹比對副本與來源 |
149
149
  | **技能本身** | `claude plugin eval .`——五個使用者真的會問的問題,各跑三次,有載技能和沒載各一臂,每次三個 LLM 裁判。**有:五題全 1.00。沒有:五題全 0.00。** 基準線最好的回答是拒答 |
150
- | **線上量測** | 114 條 REST 路由、152 個 variant、59 個條件主體、23 張表 / 210 個欄位 |
150
+ | **線上量測** | 115 條 REST 路由、156 個 variant、59 個條件主體、23 張表 / 210 個欄位 |
151
+ | **1.0.9 新功能** | modal(`<dialog>`)、OpenStreetMap、exit-intent 與 scroll-depth 觸發、run rules、memory action 與 modal shorthand,全部建在真實頁面上並用瀏覽器實際操作:19 之 19。「離開意圖彈窗、每個 session 只出現一次」只需要一個物件,不用接線 |
152
+ | **自訂欄位** | ACF 與 Meta Box,一頁四十個欄位,透過 `@VAR` / `@LOOP` 從送達的 HTML 讀回:62 個裡 59 個解析正確、3 個空值有解釋;多值欄位的迴圈剛好渲染出欄位的列數。`tools/list_fields.php` 列出 Mosaic 真正註冊的名字 |
151
153
  | **線上升級** | 1.0.7 → 1.0.8 走外掛自己的 milestone 路由、在 wp-admin 之外驅動:6 個 milestone、四張表改名、每個輸出 class 名稱都變、每個 `customStyles` 都重寫——然後上面每一項掃描在結果上重跑 |
152
154
 
153
155
  `SKIPPED`、`NO_HOST`、`INCONCLUSIVE` 從不折算進通過率。把自己的盲點算成成功的掃描,
@@ -220,6 +222,8 @@ button / html / icon-list / divider / image 佔了全部元素的 99.6%。長尾
220
222
  | `verify_intro.py` / `verify_loop.py` | 會「結束」的載入動畫;會循環、不遮東西、能打開的永續動畫 |
221
223
  | `theme_export.php` / `theme_import.php` | 整個主題以 JSON 資料列透過 WP-CLI 搬移,ID 不變 |
222
224
  | `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | 在編輯器外驅動 Mosaic 自己的 ZIP 匯出匯入、副本對來源逐樹比對、以及拒絕刪 live 主題的乾淨刪除 |
225
+ | `list_fields.php` | 一篇文章的自訂欄位註冊了哪些 `@VAR` / `@LOOP` 名字,連值一起列出 |
226
+ | `verify_dialog.py` | 在瀏覽器裡實際操作 1.0.9 的 modal、觸發、run rules 與 memory |
223
227
  | `data_upgrade.py` | 外掛更新後,走 Mosaic 自己的 milestone 路由跑資料遷移——沒跑完之前編輯器 API 是不存在的 |
224
228
  | `sweep_*.py` / `probe_*.py` | 那些表格是用這些儀器量出來的 |
225
229
  | `bootstrap_probe_theme.php` / `mint_session.php` | 免授權的實驗主題,以及從 WP-CLI 鑄出 REST session |
package/SKILL.md CHANGED
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: "mosaic-headless"
3
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 with `mo.py`, which joins every source table to the live sweeps so a lookup leads with the measured verdict rather than the declaration (122 node types, 182 properties, 98 style properties with 20 structured value shapes pinned down, 53 style states, 152 variants, 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, 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.8, with the 1.0.7 -> 1.0.8 migration (variants, universal classes, `m-` class names, customDeclarations) run and re-verified.
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 (126 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.18.0"
7
+ version: "1.20.0"
8
8
  ---
9
9
 
10
10
  # Headless Mosaic
@@ -131,11 +131,11 @@ measured.
131
131
  ## What was verified, and how
132
132
 
133
133
  Everything ran against a live install: WordPress 7.1, WooCommerce 11.1,
134
- Mosaic Pro 1.0.8, **unlicensed** — the licence gates the theme library and updates,
134
+ Mosaic Pro 1.0.9, **unlicensed** — the licence gates the theme library and updates,
135
135
  not the node factories, so the Pro types register and render regardless. The
136
- site was built on 1.0.7 and upgraded in place: the 1.0.8 data migration
136
+ site was built on 1.0.7 and upgraded in place twice: both data migrations
137
137
  (`tools/data_upgrade.py`) ran over the real theme, and every sweep below was
138
- re-run on the result, so the tables describe 1.0.8 as delivered, not as declared.
138
+ re-run on the result, so the tables describe 1.0.9 as delivered, not as declared.
139
139
 
140
140
  ```
141
141
  WRITE PATH verified end to end over REST
@@ -143,11 +143,12 @@ WRITE PATH verified end to end over REST
143
143
 
144
144
  NODE SWEEP 122 of 122 node types, ONE PER DOCUMENT, committed then rendered then
145
145
  deleted, asserting each type's attrID against the delivered HTML:
146
- RENDERED 70 id found; tag and classes recorded
146
+ RENDERED 74 id found; tag and classes recorded
147
147
  COMMITTED 25 row exists, nothing reached the page
148
148
  COMMIT_5xx 15 PHP fatal on commit
149
149
  BROKE_PAGE 12 committed, then the whole page died
150
- Free 74: 43/18/6/7. Pro 48: 27/7/9/5. data/node-verification.csv
150
+ data/node-verification.csv. 1.0.9's four new types - modal,
151
+ modal-window, modal-overlay, openstreetmap - all render.
151
152
  Re-swept on 1.0.8: five types that used to commit and render
152
153
  nothing (accordion-title, loop-pagination and its two buttons,
153
154
  multi-steps-form-step) now kill the page instead - the render
@@ -171,6 +172,28 @@ DESIGN SYS variants and collection variables both verified against compiled
171
172
  :root{--brand: rgb(9, 99, 199)} with background-color:var(--brand).
172
173
  references/design-system.md
173
174
 
175
+ DIALOG 1.0.9's features built on a live page and read back out of the
176
+ browser, 19 of 19: the modal renders a real <dialog> (aria-modal
177
+ appears only with an overlay child), a modalOpen action opens it and
178
+ modalClose closes it, closedby=everything is answered by Esc,
179
+ remember/forget write and clear mos:v1:r:<name> in local AND session
180
+ storage, scrollDepth fires, and an exitIntent modal opened by the
181
+ interaction SHORTHAND alone - nothing in the page points at it -
182
+ runs once a session and again in a new one, which is the cap rule
183
+ holding. The OpenStreetMap element carries the coordinates only in
184
+ the {"v": ...} object form. data/dialog-verification.csv,
185
+ references/dialog-and-triggers.md
186
+
187
+ FIELDS ACF 6.8 and Meta Box 5.15, forty fields registered in code on a page,
188
+ read back off the delivered HTML: 59 of 62 expressions resolve to the
189
+ value expected, the 3 empties explained (select label needs ACF's
190
+ array format; oEmbed dies in a text node, lives in a code node).
191
+ Loops over relationship / checkbox / taxonomy / gallery / clone /
192
+ group fields rendered exactly the rows the field holds. The names
193
+ are not guessable (meta_k, meta_k__label, loopk, loop-k for a
194
+ group, item/value_sub) - tools/list_fields.php prints them.
195
+ data/custom-fields-verification.csv, references/custom-fields.md
196
+
174
197
  DYNAMIC the @VAR('namespace/name') language verified against rendered output -
175
198
  @VAR('post/title') produced the real post title, @concat/@substr/
176
199
  @fallback all compose over it. 74 variables in
@@ -326,7 +349,7 @@ EVAL the skill itself, put in front of the model with and without it loa
326
349
  don't have reliable knowledge of Mosaic Pro's spec format"), which is
327
350
  the right thing for a model with no data to do. evals/
328
351
 
329
- MEASURED 114 REST routes, 152 variants, 59 condition subjects,
352
+ MEASURED 115 REST routes, 156 variants, 59 condition subjects,
330
353
  23 tables / 210 columns - read off the running site.
331
354
 
332
355
  UPGRADE 1.0.7 -> 1.0.8 driven over the plugin's own milestone route from
@@ -336,9 +359,9 @@ UPGRADE 1.0.7 -> 1.0.8 driven over the plugin's own milestone route from
336
359
  one selector on the worked example that named an emitted class
337
360
  stopped matching until it was rewritten. references/upgrading.md
338
361
 
339
- FROM SOURCE 122 node types, 182 properties (61 with enums), 207 pluggable IDs,
340
- 122 placement rules, 10 composite default structures, 98 style
341
- properties, 53 style states.
362
+ FROM SOURCE 126 node types, 191 properties (61 with enums), 249 pluggable IDs,
363
+ 126 placement rules, 10 composite default structures, 98 style
364
+ properties, 53 style states, 15 interaction triggers.
342
365
  ```
343
366
 
344
367
  **Coverage, stated as a fraction rather than as a headline.** The verification
@@ -347,8 +370,8 @@ the difference is worth being exact about:
347
370
 
348
371
  ```
349
372
  node types 122 / 122 swept live, one per document
350
- node properties 182 / 182 re-probed with a value shaped by each property's
351
- own validator chain: 35 APPLIED, 43 NO_EFFECT,
373
+ node properties 191 / 191 re-probed with a value shaped by each property's
374
+ own validator chain: 38 APPLIED, 45 NO_EFFECT,
352
375
  2 EDITOR_ONLY, 55 NO_HOST (no rendering type
353
376
  declares them), 2 INSTRUMENT, 45 SKIPPED
354
377
  style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
@@ -357,7 +380,7 @@ style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
357
380
  ```
358
381
 
359
382
  **A same-value probe measures the probe, not the surface.** The first property run
360
- sent the string `MPROP0000X` to all 181 properties (182 since 1.0.8) regardless of what each wanted,
383
+ sent the string `MPROP0000X` to all 181 properties (191 by 1.0.9) regardless of what each wanted,
361
384
  and reported 91 NO_EFFECT. The tell was that `tagName` was in that list while the
362
385
  entire demo site is built on it. Re-probed with a value derived from the declared
363
386
  validator chain - array for `ValidatorArray`, boolean for `ValidatorBoolean`, a legal
@@ -446,7 +469,12 @@ so the pattern is in the data, not just in this paragraph.
446
469
  10. `references/interactions.md` — the JavaScript animation system, and how far it is
447
470
  verified.
448
471
  11. `references/vs-elementor-gutenberg.md` — which builder habits transfer.
449
- 12. `references/upgrading.md` — what a plugin update does to the data and to the
472
+ 12. `references/custom-fields.md` — ACF and Meta Box fields as `@VAR` / `@LOOP`:
473
+ the names, what each field type resolves to, and the loop element that walks
474
+ a multi-value field. Measured, 62 rows.
475
+ 13. `references/dialog-and-triggers.md` — 1.0.9's modal, OpenStreetMap, the
476
+ exit-intent / scroll-depth triggers, run rules, memory and the shorthand.
477
+ 14. `references/upgrading.md` — what a plugin update does to the data and to the
450
478
  delivered page, measured on 1.0.7 -> 1.0.8; how to drive the migration and what
451
479
  to re-verify afterwards.
452
480
 
@@ -456,20 +484,20 @@ so the pattern is in the data, not just in this paragraph.
456
484
  |---|---|---|
457
485
  | `data/node-verification.csv` | 122 | **swept live** — outcome, rendered tag and classes, page bytes, failure detail |
458
486
  | `data/node-types.csv` | 122 | source — slug, label, edition, aliases, data class |
459
- | `data/node-properties.csv` | 182 | source — property, validator chain, **accepted enum values**, `supportsInherit` |
487
+ | `data/node-properties.csv` | 191 | source — property, validator chain, **accepted enum values**, `supportsInherit` |
460
488
  | `data/placement-rules.csv` | 122 | source — which children each type accepts |
461
489
  | `data/default-children.csv` | 10 | source — what a composite type needs **inside** it |
462
490
  | `data/style-properties.csv` | 98 | source — every settable CSS property and its value shape |
463
491
  | `data/style-value-shapes.csv` | 22 | **probed live** — the exact JSON shape for each structured value, and what it compiled to |
464
492
  | `data/style-states.csv` | 53 | source — state IDs with their exact CSS selector templates |
465
493
  | `data/property-verification.csv` | 170 | **probed live** — per-property effect on markup vs CSS, with unprovable enums marked INCONCLUSIVE |
466
- | `data/node-property-verification.csv` | 182 | **swept live** — each property probed with a value shaped by its own validator chain, on a type that declares it |
494
+ | `data/node-property-verification.csv` | 191 | **swept live** — each property probed with a value shaped by its own validator chain, on a type that declares it |
467
495
  | `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 |
468
496
  | `data/rwd-verification.csv` | 731 | **checked live** - every `_t`/`_m` declaration vs the served stylesheet, with status per row |
469
497
  | `data/browser-verification.csv` | 3988 | **computed in Chromium** - declared vs `getComputedStyle` at three viewports, `not-comparable` labelled per row |
470
498
  | `data/design-audit-acknowledged.csv` | 3 | reviewed findings that will not be fixed, each with a written reason. An acknowledgement without a reason is a suppression wearing a better name, and the release gate refuses one |
471
499
  | `data/design-audit.csv` | 26 | **computed in Chromium** - contrast, font fallback, CJK tracking, overflow, measure. Empty means it ran and found nothing |
472
- | `data/data-class-hierarchy.csv` | 121 | source - every data class and its parent, so a type's inherited properties can be resolved |
500
+ | `data/data-class-hierarchy.csv` | 125 | source - every data class and its parent, so a type's inherited properties can be resolved |
473
501
  | `data/style-state-verification.csv` | 52 | **swept live** - each state written on a host of its own type and matched against its promised selector |
474
502
  | `data/component-verification.csv` | 8 | **driven live** - the component lifecycle, each step asserted against the row or the delivered HTML |
475
503
  | `data/loop-verification.csv` | 28 | **measured live** - a perpetual animation: periodicity by scrubbing a paused timeline, per-element occlusion of both text and controls at five widths, and the enlarged view opened by pointer and by keyboard |
@@ -477,19 +505,21 @@ so the pattern is in the data, not just in this paragraph.
477
505
  | `data/conversion-verification.csv` | 8 | **converted then checked live** - an Elementor page rebuilt as Mosaic and held against its source (text, images, links, heading levels), then put through rwd, browser and the design audit with every finding classified inherited-or-introduced |
478
506
  | `data/conversion-batch.csv` | 19 | **converted, built and checked live, one page after another** - every Elementor page of a production site through the converter, with per-page element and content counts |
479
507
  | `data/token-benchmark.csv` | 6 | **measured with tiktoken** - the same six lookups priced three ways: reading the plugin source, loading every table, querying `mo.py`. 71-99.5% fewer tokens than the source and 99.6%+ fewer than the tables, which total 259,539 - never load them, query them |
508
+ | `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 |
509
+ | `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 |
480
510
  | `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 |
481
511
  | `data/node-type-notes.csv` | 8 | where a sweep outcome is true but misleading on its own, why. Surfaced by `mo.py type` |
482
512
  | `data/interaction-verification.csv` | 7 | **probed live** - interaction animation shapes, with negative controls and the stored row beside the payload |
483
513
  | `data/intro-verification.csv` | 8 + 15 | **sampled live** - the entrance sequence over fifteen timestamps on a monotonic clock, plus the eight assertions about it |
484
- | `data/variants.csv` | 152 | **live** — the variant catalog (Mosaic's built-in element classes); their IDs are what a `variant` record must use, and `class_name` is what the element emits |
514
+ | `data/variants.csv` | 156 | **live** — the variant catalog (Mosaic's built-in element classes); their IDs are what a `variant` record must use, and `class_name` is what the element emits |
485
515
  | `data/dynamic-variables.csv` | 74 | source — every `@VAR('ns/name')` expression, by namespace |
486
516
  | `data/evaluator-functions.csv` | 19 | source — the `@` functions with their arity |
487
- | `data/interaction-types.csv` | 12 | source — trigger types, `timed` vs `progress` |
517
+ | `data/interaction-types.csv` | 15 | source — trigger types, `timed` vs `progress`; 1.0.9 adds exitIntent, scrollDepth and modal |
488
518
  | `data/animatable-properties.csv` | 22 | source — what a keyframe can drive (**not** the same set as the style properties) |
489
519
  | `data/condition-subjects.csv` | 59 | **live** — condition subjects per context |
490
520
  | `data/condition-comparators.csv` | 12 | **live** — comparators and their operator sets |
491
- | `data/pluggables.csv` | 207 | source — every `setID()` by registry |
492
- | `data/rest-routes.csv` | 114 | **live** — method, path, args |
521
+ | `data/pluggables.csv` | 249 | source — every `setID()` by registry |
522
+ | `data/rest-routes.csv` | 115 | **live** — method, path, args |
493
523
  | `data/db-columns.csv` | 210 | **live** — every column of all 23 tables |
494
524
 
495
525
  ## Building a page
@@ -579,7 +609,7 @@ post — `build_all.py` resets first for that reason.
579
609
 
580
610
  ## Facts worth knowing before you look anything up
581
611
 
582
- - **The REST namespace contains the plugin version** (`/wp-json/mosaic/v1.0.8`). Read
612
+ - **The REST namespace contains the plugin version** (`/wp-json/mosaic/v1.0.9`). Read
583
613
  it from `mosaicOptions.rest_api_url`, never hardcode. After a plugin update the
584
614
  editor namespace is GONE until the data upgrade has run; only
585
615
  `mosaic/<dataVersion>/<version>/upgrade` answers. `tools/data_upgrade.py`.
@@ -637,7 +667,28 @@ post — `build_all.py` resets first for that reason.
637
667
  set (masters not reached from a bound template, their templates, their nodes)
638
668
  the same import took under two minutes and compared 22 of 22. Prune before you
639
669
  export; `wp_mosaic_template_assigns.parentID` -> template -> `masterID` is the
640
- bound set, plus any `assign="auto"` template.
670
+ bound set, plus any `assign="auto"` template. Then sweep ORPHANS: a probe run
671
+ that half-failed, or a prune that removed a parent, leaves nodes whose parent id
672
+ points at nothing. The export skips them, so the copy is short by exactly those
673
+ rows and `theme_zip_compare.php` reports a tree that does not match - delete
674
+ nodes with a missing parent REPEATEDLY until none are left, because each pass
675
+ orphans the next level down.
676
+ - **An interaction that targets another element stores that element's NODE id**,
677
+ not its attrID, so both have to be written in one pass (`nodeID` on a spec
678
+ node pins it). The id must be unique in the THEME - `wp_mosaic_nodes`' primary
679
+ key is `(ID, themeID)` - so mint it per run rather than hard-coding one.
680
+ - **Since 1.0.9 the three per-breakpoint stylesheets are one.**
681
+ `mosaic-theme-document-styles-inline-css` carries the base rules and the
682
+ `@media` blocks together; the old `mosaic-theme-block-editor-styles_<bp>-inline-css`
683
+ ids are gone. And an element whose styles compile to nothing is emitted with
684
+ no generated class at all, so "no `_token`" no longer means "did not render".
685
+ - **A custom field is `@VAR('post/meta_<key>')`, and a multi-value one is a LOOP.**
686
+ ACF and Meta Box both, plus bare post meta. Derived properties hang off the
687
+ name with two underscores (`meta_k__label`, `__url`, `__id`); an ACF group is
688
+ `loop-k` (hyphen) with `item/value_<sub>` rows; ACF puts the ID in a
689
+ reference's primary slot where Meta Box puts the title. Run
690
+ `tools/list_fields.php` on the post rather than guessing - a name it does not
691
+ print does not exist. references/custom-fields.md
641
692
  - **A variant row cannot be deleted, only emptied.** `status:"delete"` on a
642
693
  variant is accepted and ignored - the row is catalog-backed. Commit it back with
643
694
  `{"states": {"&": {"_": {}}}}` and the rule disappears; measured on Heading 2.
@@ -698,6 +749,8 @@ post — `build_all.py` resets first for that reason.
698
749
  | `theme_zip.py` | drive Mosaic's OWN export/import - the ZIP the editor makes, attachments included, over the milestone protocol; import lands in test mode unless told `--activate` |
699
750
  | `theme_zip_compare.php` | hold an imported copy against its source, tree for tree - every scoped table, the (parentType, type) shape, which ids survive, and orphans named rather than counted |
700
751
  | `theme_delete.php` | remove a theme completely through the plugin's own routine; refuses the live one |
752
+ | `verify_dialog.py` | the 1.0.9 modal in a real browser: does it open, close, answer Esc, remember, cap - and does an OpenStreetMap carry the coordinates it was given |
753
+ | `list_fields.php` | every `@VAR` / `@LOOP` name Mosaic registers for one post - custom fields, their derived `__label` / `__url` / `__id` properties, the row variables of each loop - with the value each resolves to (`wp eval-file`) |
701
754
  | `data_upgrade.py` | after a plugin update, run Mosaic's data migration over its own milestone route - the step wp-admin does from a screen - and set the config's version when the editor API is back |
702
755
  | `copy_styles.py` | push one node's style onto others, by attrID or prefix |
703
756
  | `bootstrap_probe_theme.php` | a licence-free scratch theme |
@@ -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.18.0"
23
+ "version": "1.20.0"
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.18.0"
23
+ "version": "1.20.0"
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.18.0"
23
+ "version": "1.20.0"
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.18.0"
23
+ "version": "1.20.0"
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.18.0"
23
+ "version": "1.20.0"
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,
@@ -75,14 +75,16 @@ if (!fs.existsSync(path.join(ROOT, pkg.bin["mosaic-headless"])))
75
75
 
76
76
  const rows = (p) => read(p).trim().split("\n").length - 1; // minus the header
77
77
  const counts = {
78
- "data/node-verification.csv": 122,
78
+ "data/node-verification.csv": 126,
79
79
  "data/style-verification.csv": 98,
80
- "data/node-property-verification.csv": 182,
80
+ "data/node-property-verification.csv": 191,
81
81
  "data/rwd-verification.csv": 731,
82
82
  "data/browser-verification.csv": 3988,
83
83
  "data/style-state-verification.csv": 52,
84
84
  "data/interaction-verification.csv": 7,
85
- "data/data-class-hierarchy.csv": 121,
85
+ "data/data-class-hierarchy.csv": 125,
86
+ "data/custom-fields-verification.csv": 62,
87
+ "data/dialog-verification.csv": 19,
86
88
  };
87
89
  for (const [file, expected] of Object.entries(counts)) {
88
90
  if (!fs.existsSync(path.join(ROOT, file))) { fail(`${file} missing`); continue; }
@@ -1,6 +1,6 @@
1
1
  step,result,detail
2
2
  nested commit accepted,PASS,no exception from the commit
3
- page still renders,PASS,28783 bytes delivered
3
+ page still renders,PASS,28743 bytes delivered
4
4
  title rendered,PASS,the accordion title is in the delivered HTML
5
5
  content rendered,PASS,the accordion content is in the delivered HTML
6
6
  carries plugin markup,PASS,found 'mosaic-accordion' in the output