mosaic-headless 1.19.0 → 1.20.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/README.ja.md +9 -7
- package/README.ko.md +9 -7
- package/README.md +48 -7
- package/README.zh-TW.md +41 -7
- package/SKILL.md +59 -28
- 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/accordion-verification.csv +1 -1
- package/data/browser-verification.csv +144 -0
- package/data/condition-subjects.csv +56 -56
- package/data/conversion-batch.csv +2 -2
- package/data/data-class-hierarchy.csv +4 -0
- package/data/dialog-verification.csv +20 -0
- package/data/interaction-types.csv +15 -12
- package/data/intro-verification.csv +6 -6
- package/data/loop-verification.csv +1 -1
- package/data/node-properties.csv +9 -0
- package/data/node-property-verification.csv +88 -79
- package/data/node-types.csv +13 -9
- package/data/node-verification.csv +99 -95
- package/data/placement-rules.csv +4 -0
- package/data/pluggables.csv +42 -0
- package/data/rest-routes.csv +2 -1
- package/data/rwd-verification.csv +2 -0
- package/data/style-properties.csv +6 -6
- package/data/style-verification.csv +79 -79
- package/data/theme-zip-verification.csv +5 -5
- package/data/variants.csv +12 -8
- package/package.json +6 -6
- package/references/dialog-and-triggers.md +234 -0
- package/{bin → scripts}/check-release.mjs +26 -11
- package/{bin → scripts}/sync-version.mjs +14 -2
- package/sites/_moksa.py +164 -1
- package/sites/moksa.json +358 -1
- package/tools/build_page.py +9 -1
- package/tools/sweep_node_properties.py +21 -5
- package/tools/sweep_node_types.py +85 -0
- package/tools/sweep_style_properties.py +10 -24
- package/tools/verify_dialog.py +329 -0
- package/tools/verify_rwd.py +11 -27
- /package/{bin → scripts}/install.mjs +0 -0
package/README.ja.md
CHANGED
|
@@ -137,17 +137,17 @@ commit の成功はページが動く証拠ではないし、正しいスタイ
|
|
|
137
137
|
|
|
138
138
|
## 何を、どう検証したか
|
|
139
139
|
|
|
140
|
-
すべて実際のインストールに対して実行 — WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.
|
|
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 → 描画 → 断言 → 削除:
|
|
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
|
-
| **ノードプロパティ** |
|
|
149
|
-
| **レスポンシブ** | 2 サイト計
|
|
150
|
-
| **ブラウザ** | 配信された 2 ページを Chromium の 3 つのビューポートで計算スタイル
|
|
148
|
+
| **ノードプロパティ** | 191 / 191 を各プロパティ自身のバリデータ連鎖から導いた値で再探査:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
|
|
149
|
+
| **レスポンシブ** | 2 サイト計 733 件の `_t`/`_m` 宣言を、サイトが実際に配信したスタイルシートに対して 1 件ずつ断言 — 全件検証済み |
|
|
150
|
+
| **ブラウザ** | 配信された 2 ページを Chromium の 3 つのビューポートで計算スタイル 4,132 件読み取り:2,929 件が一致、912 件は比較不能として明示、**上書き 0 件** |
|
|
151
151
|
| **デザイン監査** | コントラスト、フォントフォールバック、CJK の字送り、横溢れ、テキストの切れ、1 行の文字数 — ブラウザ上で実行、**指摘 26 件、すべて理由付きで裁定済み** — 理由のない容認はリリースゲートが拒否する |
|
|
152
152
|
| **コンポーネント** | コンポーネントシステムを端から端まで駆動、**8 件中 8 件**:カテゴリの下に作成、ドキュメントが自己修復、書き込み可能インスタンス経由でツリーを充填、読み取り専用インスタンスは同じ書き込みを拒否(ネガティブコントロール)、ページ上の 2 インスタンスが 1 つの定義を 2 度描画 |
|
|
153
153
|
| **スタイル状態** | 53 状態のうち 52 を実ページに書き、表が約束するセレクタと照合:**36 が完全一致**、13 NO_HOST、3 SKIPPED、0 BROKE_PAGE。擬似クラスは大文字で出力される(`.M_EL9:HOVER`) |
|
|
@@ -158,7 +158,8 @@ 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 ルート
|
|
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 つで済む |
|
|
162
163
|
| **カスタムフィールド** | ACF と Meta Box、1 ページに 40 フィールド、`@VAR` / `@LOOP` で配信 HTML から読み戻し:62 のうち 59 が解決、3 つの空は理由付き;複数値フィールドのループはフィールドの行数どおりに描画。`tools/list_fields.php` が Mosaic の実際の登録名を出す |
|
|
163
164
|
| **ライブ更新** | 1.0.7 → 1.0.8 をプラグイン自身の milestone ルートで wp-admin の外から駆動:6 milestone、4 テーブル改名、出力クラス名は全部変わり、`customStyles` は全部書き換え — その結果に対して上の計測をすべて再実行 |
|
|
164
165
|
|
|
@@ -239,6 +240,7 @@ loop grid、フォーム、カウントダウン、サードパーティ addon
|
|
|
239
240
|
| `theme_export.php` / `theme_import.php` | テーマ全体を JSON 行として WP-CLI で移動、id は不変 |
|
|
240
241
|
| `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | Mosaic 自身の ZIP 書き出し/読み込みをエディタの外から駆動、コピーを元とツリー単位で照合、ライブテーマを拒否する完全削除 |
|
|
241
242
|
| `list_fields.php` | ある投稿のカスタムフィールドが登録する `@VAR` / `@LOOP` 名をすべて、値付きで |
|
|
243
|
+
| `verify_dialog.py` | 1.0.9 の modal・トリガー・run rules・memory をブラウザで実操作 |
|
|
242
244
|
| `data_upgrade.py` | プラグイン更新後、Mosaic のデータ移行を自身の milestone ルートで実行 — 終わるまでエディタ API は存在しない |
|
|
243
245
|
| `sweep_*.py` / `probe_*.py` | 表を作った計測器そのもの |
|
|
244
246
|
| `bootstrap_probe_theme.php` / `mint_session.php` | ライセンス不要の実験用テーマと、WP-CLI から作る REST セッション |
|
|
@@ -267,7 +269,7 @@ npm version minor # package.json、SKILL.md、8 つのプラットフォー
|
|
|
267
269
|
# commit、tag、push;tag が release.yml を起動する
|
|
268
270
|
```
|
|
269
271
|
|
|
270
|
-
`
|
|
272
|
+
`scripts/check-release.mjs` がすべてのリリースを門番する。検査するのは「検査しやすいこと」ではなく
|
|
271
273
|
「間違えやすいこと」:版番号の一致、`files` の各 glob が何かに一致すること、各検証 CSV の行数が
|
|
272
274
|
SKILL.md と 4 つの README が引用する数と等しいこと、未裁定のデザイン監査指摘がないこと、eval
|
|
273
275
|
スイートが存在すること、そして **tarball そのものの検査** — npm の `files` 許可リストは
|
package/README.ko.md
CHANGED
|
@@ -133,17 +133,17 @@ commit 성공은 페이지가 동작한다는 증거가 아니고, 올바른 스
|
|
|
133
133
|
|
|
134
134
|
## 무엇을, 어떻게 검증했나
|
|
135
135
|
|
|
136
|
-
전부 실제 설치에서 실행 — WordPress 7.1, WooCommerce 11.1, Mosaic Pro 1.0.
|
|
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 → 렌더 → 단언 → 삭제:
|
|
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
|
-
| **노드 프로퍼티** |
|
|
145
|
-
| **반응형** | 두 사이트 합쳐
|
|
146
|
-
| **브라우저** | 전달된 두 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일
|
|
144
|
+
| **노드 프로퍼티** | 191 / 191을 각 프로퍼티 자신의 검증기 체인에서 도출한 값으로 재탐사: 35 APPLIED, 43 NO_EFFECT, 55 NO_HOST, 47 SKIPPED |
|
|
145
|
+
| **반응형** | 두 사이트 합쳐 733개의 `_t`/`_m` 선언을, 사이트가 실제로 내보낸 스타일시트에 대해 하나씩 단언 — 전부 검증됨 |
|
|
146
|
+
| **브라우저** | 전달된 두 페이지를 Chromium의 세 가지 뷰포트에서 계산 스타일 4,132건 판독: 2,929건 일치, 912건은 비교 불가로 명시, **덮어쓰기 0건** |
|
|
147
147
|
| **디자인 감사** | 명암비, 폰트 폴백, CJK 자간, 가로 넘침, 텍스트 잘림, 한 줄 글자 수 — 브라우저에서 실행, **지적 26건, 모두 서면으로 판정** — 이유 없는 승인은 릴리스 게이트가 거부한다 |
|
|
148
148
|
| **컴포넌트** | 컴포넌트 시스템을 끝에서 끝까지 구동, **8건 중 8건**: 카테고리 아래 생성, 문서 자가 치유, 쓰기 가능 인스턴스로 트리 채움, 읽기 전용 인스턴스는 같은 쓰기를 거부(네거티브 컨트롤), 페이지의 두 인스턴스가 하나의 정의를 두 번 렌더 |
|
|
149
149
|
| **스타일 상태** | 53개 상태 중 52개를 실제 페이지에 쓰고 표가 약속한 셀렉터와 대조: **36개 정확히 일치**, 13 NO_HOST, 3 SKIPPED, 0 BROKE_PAGE. 의사 클래스는 대문자로 출력된다(`.M_EL9:HOVER`) |
|
|
@@ -154,7 +154,8 @@ 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 라우트
|
|
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. "이탈 의도 팝업, 세션당 한 번"이 배선 없이 객체 하나 |
|
|
158
159
|
| **커스텀 필드** | ACF와 Meta Box, 한 페이지에 40개 필드, `@VAR` / `@LOOP`로 전달된 HTML에서 읽어냄: 62개 중 59개 해석, 빈 3개는 이유 있음; 다중값 필드 루프는 필드의 행 수 그대로 렌더링. `tools/list_fields.php`가 Mosaic이 실제 등록하는 이름을 출력 |
|
|
159
160
|
| **라이브 업그레이드** | 1.0.7 → 1.0.8을 플러그인 자체 milestone 라우트로 wp-admin 밖에서 구동: 6 milestone, 테이블 4개 이름 변경, 출력 클래스 이름 전부 변경, `customStyles` 전부 재작성 — 그 결과 위에서 위의 측정을 전부 다시 실행 |
|
|
160
161
|
|
|
@@ -233,6 +234,7 @@ loop grid, 폼, 카운트다운, 서드파티 addon — 은 동적이라 될 노
|
|
|
233
234
|
| `theme_export.php` / `theme_import.php` | 테마 전체를 JSON 행으로 WP-CLI를 통해 이동, id 그대로 |
|
|
234
235
|
| `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | Mosaic 자체 ZIP 내보내기/가져오기를 에디터 밖에서 구동, 사본을 원본과 트리 단위로 대조, 라이브 테마를 거부하는 깨끗한 삭제 |
|
|
235
236
|
| `list_fields.php` | 한 글의 커스텀 필드가 등록하는 모든 `@VAR` / `@LOOP` 이름을 값과 함께 |
|
|
237
|
+
| `verify_dialog.py` | 1.0.9의 modal·트리거·run rules·memory를 브라우저에서 실제 조작 |
|
|
236
238
|
| `data_upgrade.py` | 플러그인 업데이트 후 Mosaic의 데이터 이관을 자체 milestone 라우트로 실행 — 끝나기 전까지 에디터 API는 존재하지 않는다 |
|
|
237
239
|
| `sweep_*.py` / `probe_*.py` | 표를 만든 계측기 그 자체 |
|
|
238
240
|
| `bootstrap_probe_theme.php` / `mint_session.php` | 라이선스 없는 실험용 테마와 WP-CLI에서 만드는 REST 세션 |
|
|
@@ -261,7 +263,7 @@ npm version minor # package.json, SKILL.md, 8개 플랫폼 템플릿의 버
|
|
|
261
263
|
# commit, tag, push; tag가 release.yml을 트리거
|
|
262
264
|
```
|
|
263
265
|
|
|
264
|
-
`
|
|
266
|
+
`scripts/check-release.mjs`가 모든 릴리스를 지킨다. 검사하는 것은 "검사하기 쉬운 것"이 아니라
|
|
265
267
|
"틀리기 쉬운 것": 버전 번호 일치, `files`의 각 glob이 무언가와 매칭, 각 검증 CSV의 행 수가
|
|
266
268
|
SKILL.md와 네 README가 인용하는 수와 같음, 판정되지 않은 디자인 감사 지적 없음, eval 스위트
|
|
267
269
|
존재, 그리고 **tarball 자체 검사** — npm의 `files` 허용 목록은 `.gitignore`를 덮어쓰며, 한때
|
package/README.md
CHANGED
|
@@ -43,6 +43,45 @@ npx mosaic-headless@latest claude-code --global --force
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
## Install as a Claude plugin
|
|
47
|
+
|
|
48
|
+
The repository is also a Claude plugin: `.claude-plugin/plugin.json` at the root, and
|
|
49
|
+
the root `SKILL.md` loads as its one skill. Once the plugin is listed in the Claude
|
|
50
|
+
directory, install it from there. Until then, Claude Code can load a clone directly:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git clone https://github.com/Moksa1123/mosaic-headless
|
|
54
|
+
claude --plugin-dir ./mosaic-headless
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This is an independent project. It is not made by, endorsed by, or affiliated with
|
|
58
|
+
Nextend, the maker of Mosaic Pro.
|
|
59
|
+
|
|
60
|
+
## What this plugin runs and connects to
|
|
61
|
+
|
|
62
|
+
The plugin has no hooks, no MCP servers and no background processes. Everything
|
|
63
|
+
below runs only when Claude follows `SKILL.md` and you approve the command:
|
|
64
|
+
|
|
65
|
+
- **`tools/mo.py`** reads the CSV tables in `data/` and prints answers. It writes
|
|
66
|
+
nothing and contacts nothing.
|
|
67
|
+
- **`tools/*.php`** run inside your own WordPress through `wp eval-file`. They read
|
|
68
|
+
and write Mosaic's own tables and theme data on that site.
|
|
69
|
+
- **`tools/mint_session.php`** creates a logged-in WordPress session and a matching
|
|
70
|
+
REST nonce for an account on *your* site. You put them in a local config file
|
|
71
|
+
(`--config sweep.json`); they are printed to your terminal and sent nowhere else.
|
|
72
|
+
- **`tools/build_site.py`, `data_upgrade.py`, `theme_zip.py`, `probe_accordion.py` and the `sweep_*.py`
|
|
73
|
+
tools** call Mosaic's REST routes on the site in that config file, with that
|
|
74
|
+
session, to read and write pages, components and themes. They contact only that
|
|
75
|
+
site.
|
|
76
|
+
- **`tools/verify_*.py`** open pages of that same site with Playwright (Chromium) or
|
|
77
|
+
`urllib` and compare what was delivered with what was written.
|
|
78
|
+
- **`sites/`** holds the worked example (the author's own site) as data. Its design
|
|
79
|
+
loads Google Fonts, so pages built from it make visitors' browsers fetch fonts from
|
|
80
|
+
Google, as any page using Google Fonts does.
|
|
81
|
+
|
|
82
|
+
The tools need Python 3 and Playwright. Nothing is downloaded at install time, and no
|
|
83
|
+
data is sent to the author or any third party.
|
|
84
|
+
|
|
46
85
|
## What this is
|
|
47
86
|
|
|
48
87
|
Mosaic keeps a page in **23 custom database tables**, not in `post_content` and not
|
|
@@ -143,16 +182,16 @@ than any naive healthy-page floor.
|
|
|
143
182
|
## What was verified, and how
|
|
144
183
|
|
|
145
184
|
Everything ran against a live install — WordPress 7.1, WooCommerce 11.1, Mosaic Pro
|
|
146
|
-
1.0.
|
|
185
|
+
1.0.9, **unlicensed**: the licence gates the theme library and updates, not the node
|
|
147
186
|
factories, so Pro types register and render regardless.
|
|
148
187
|
|
|
149
188
|
| pass | result |
|
|
150
189
|
|---|---|
|
|
151
|
-
| **node types** | 122 / 122 swept one per document, committed → rendered → asserted → deleted:
|
|
190
|
+
| **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
191
|
| **style properties** | 98 / 98 written to a live page and checked against the compiled CSS: 58 COMPILED, 18 ABSENT, 21 SKIPPED |
|
|
153
|
-
| **node properties** |
|
|
154
|
-
| **responsive** |
|
|
155
|
-
| **browser** |
|
|
192
|
+
| **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 |
|
|
193
|
+
| **responsive** | 733 `_t`/`_m` declarations across two sites asserted against the stylesheet the site actually served — all verified |
|
|
194
|
+
| **browser** | 4,132 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
195
|
| **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 |
|
|
157
196
|
| **components** | the component system driven end to end, **8 of 8**: created under a category, document healed, tree filled through the writable instance, the read-only one refused the same write as a negative control, two instances on a page rendering one definition twice |
|
|
158
197
|
| **style states** | 52 of the 53 states written to a live page and matched against the selector the table promises: **36 compiled exactly**, 13 NO_HOST, 3 SKIPPED, 0 BROKE_PAGE. Pseudo-classes are emitted UPPERCASE (`.M_EL9:HOVER`) |
|
|
@@ -163,7 +202,8 @@ factories, so Pro types register and render regardless.
|
|
|
163
202
|
| **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
203
|
| **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
204
|
| **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** |
|
|
205
|
+
| **measured live** | 115 REST routes, 156 variants, 59 condition subjects, 23 tables / 210 columns |
|
|
206
|
+
| **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 |
|
|
167
207
|
| **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 |
|
|
168
208
|
| **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 |
|
|
169
209
|
|
|
@@ -248,6 +288,7 @@ and heading level — and it earned its place at once: it caught the converter l
|
|
|
248
288
|
| `theme_export.php` / `theme_import.php` | a whole theme as JSON rows over WP-CLI, ids intact |
|
|
249
289
|
| `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 |
|
|
250
290
|
| `list_fields.php` | every `@VAR` / `@LOOP` name a post's custom fields register, with values |
|
|
291
|
+
| `verify_dialog.py` | the 1.0.9 modal, triggers, run rules and memory, driven in a browser |
|
|
251
292
|
| `data_upgrade.py` | after a plugin update, Mosaic's data migration over its own milestone route - the editor API is gone until it runs |
|
|
252
293
|
| `sweep_*.py` / `probe_*.py` | the instruments the tables were made with |
|
|
253
294
|
| `bootstrap_probe_theme.php` / `mint_session.php` | a licence-free scratch theme and a REST session from WP-CLI |
|
|
@@ -278,7 +319,7 @@ npm version minor # bumps package.json, SKILL.md and eight platform templat
|
|
|
278
319
|
# commits, tags, pushes; the tag triggers release.yml
|
|
279
320
|
```
|
|
280
321
|
|
|
281
|
-
`
|
|
322
|
+
`scripts/check-release.mjs` gates every release on the things that are easy to get
|
|
282
323
|
wrong: the version numbers agree, every `files` glob matches, every verification
|
|
283
324
|
CSV still has the row count SKILL.md and the four READMEs quote, no design-audit
|
|
284
325
|
finding is unreviewed, the eval suite is present, and **the tarball itself is
|
package/README.zh-TW.md
CHANGED
|
@@ -41,6 +41,38 @@ npx mosaic-headless@latest claude-code --global --force
|
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
## 以 Claude plugin 安裝
|
|
45
|
+
|
|
46
|
+
這個 repo 同時也是一個 Claude plugin:根目錄有 `.claude-plugin/plugin.json`,根目錄的
|
|
47
|
+
`SKILL.md` 就是它唯一的技能。上架到 Claude 目錄之後可以直接從目錄安裝;在那之前,Claude
|
|
48
|
+
Code 可以直接載入 clone 下來的資料夾:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git clone https://github.com/Moksa1123/mosaic-headless
|
|
52
|
+
claude --plugin-dir ./mosaic-headless
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
這是獨立專案,不是 Mosaic Pro 開發商 Nextend 的產品,也沒有得到 Nextend 背書或與其合作。
|
|
56
|
+
|
|
57
|
+
## 這個 plugin 會執行什麼、連到哪裡
|
|
58
|
+
|
|
59
|
+
這個 plugin 沒有 hook、沒有 MCP 伺服器、沒有背景程序。下面這些都只在 Claude 依照
|
|
60
|
+
`SKILL.md` 執行、而且你核准指令時才會跑:
|
|
61
|
+
|
|
62
|
+
- **`tools/mo.py`**:讀 `data/` 裡的 CSV 表並印出答案,不寫入任何東西,也不連線。
|
|
63
|
+
- **`tools/*.php`**:透過 `wp eval-file` 在你自己的 WordPress 裡執行,讀寫該網站上 Mosaic
|
|
64
|
+
自己的資料表和主題資料。
|
|
65
|
+
- **`tools/mint_session.php`**:替*你自己網站*上的帳號建立登入 session 和對應的 REST
|
|
66
|
+
nonce。你把它們放進本機的設定檔(`--config sweep.json`);它們只印在你的終端機,不會送到別處。
|
|
67
|
+
- **`tools/build_site.py`、`data_upgrade.py`、`theme_zip.py`、`probe_accordion.py` 和 `sweep_*.py`**:用那份
|
|
68
|
+
session 呼叫設定檔裡那個網站的 Mosaic REST 路由,讀寫頁面、元件和主題。只連到那個網站。
|
|
69
|
+
- **`tools/verify_*.py`**:用 Playwright(Chromium)或 `urllib` 開同一個網站的頁面,比對實際
|
|
70
|
+
輸出和寫入的內容。
|
|
71
|
+
- **`sites/`**:工作範例(作者自己的網站)的資料。它的設計有載入 Google Fonts,所以用它建出來的
|
|
72
|
+
頁面,訪客的瀏覽器會向 Google 抓字型,跟任何使用 Google Fonts 的網頁一樣。
|
|
73
|
+
|
|
74
|
+
工具需要 Python 3 和 Playwright。安裝時不會下載任何東西,也不會把資料送給作者或第三方。
|
|
75
|
+
|
|
44
76
|
## 這是什麼
|
|
45
77
|
|
|
46
78
|
Mosaic 把一個頁面放在 **23 張自訂資料表**裡,不在 `post_content`,也不在 `postmeta`。
|
|
@@ -127,16 +159,16 @@ commit 成功不代表頁面能用,樣式表正確也不代表。這裡每個
|
|
|
127
159
|
|
|
128
160
|
## 驗證了什麼,怎麼驗的
|
|
129
161
|
|
|
130
|
-
全部在真實站台上跑——WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.
|
|
162
|
+
全部在真實站台上跑——WordPress 7.1、WooCommerce 11.1、Mosaic Pro 1.0.9,**未授權**:
|
|
131
163
|
授權鎖的是主題庫和更新,不是節點工廠,所以 Pro 型別照樣註冊、照樣渲染。
|
|
132
164
|
|
|
133
165
|
| 項目 | 結果 |
|
|
134
166
|
|---|---|
|
|
135
|
-
| **節點型別** | 122 / 122 逐一放進獨立文件,寫入 → 渲染 → 斷言 → 刪除:
|
|
167
|
+
| **節點型別** | 122 / 122 逐一放進獨立文件,寫入 → 渲染 → 斷言 → 刪除:74 RENDERED、25 COMMITTED、15 COMMIT_5xx、12 BROKE_PAGE。在 1.0.8 上重掃:五個以前默默寫入的型別,沒放對父節點現在會直接弄死頁面。未渲染的當中有三個是「沒給父層」的掃描方法產物,註記就在列旁 |
|
|
136
168
|
| **樣式屬性** | 98 / 98 寫進真實頁面、對照編譯出的 CSS:58 COMPILED、18 ABSENT、21 SKIPPED |
|
|
137
|
-
| **節點屬性** |
|
|
138
|
-
| **響應式** | 兩個站共
|
|
139
|
-
| **瀏覽器** | 在 Chromium 三個視窗寬度上對兩個交付頁面做
|
|
169
|
+
| **節點屬性** | 191 / 191 用各自驗證鏈推出的值重新探測:35 APPLIED、43 NO_EFFECT、55 NO_HOST、47 SKIPPED |
|
|
170
|
+
| **響應式** | 兩個站共 733 條 `_t`/`_m` 宣告,對照網站實際送出的樣式表逐條斷言——全數通過 |
|
|
171
|
+
| **瀏覽器** | 在 Chromium 三個視窗寬度上對兩個交付頁面做 4,132 次計算樣式讀取:2,929 條比對相符、912 條標為無法比對、**0 條被覆蓋** |
|
|
140
172
|
| **設計稽核** | 對比度、字體回退、CJK 字距、水平溢出、文字裁切、每行字數——在瀏覽器裡跑,**26 項發現,每一項都有書面裁定**——沒寫理由的 acknowledge 會被發布閘門拒絕 |
|
|
141
173
|
| **元件** | 元件系統從頭驅動到尾,**8 之 8**:在分類下建立、文件自癒、透過可寫實例填入樹、唯讀實例拒絕同一筆寫入作為負控制、頁面上兩個實例渲染同一個定義 |
|
|
142
174
|
| **樣式狀態** | 53 個狀態中的 52 個寫進真實頁面,對照表格承諾的選擇器:**36 個完全吻合**、13 NO_HOST、3 SKIPPED、0 BROKE_PAGE。偽類是大寫輸出的(`.M_EL9:HOVER`) |
|
|
@@ -147,7 +179,8 @@ commit 成功不代表頁面能用,樣式表正確也不代表。這裡每個
|
|
|
147
179
|
| **Elementor 轉換** | 一個正式站的全部 Elementor 頁面——19 頁、3,292 個元素——轉換、建置、對照來源檢查:**19 之 19**,3,281 個元素搬過去、11 個書面宣告。再把轉出的頁面跑過響應式、瀏覽器和稽核,每一項發現都分類為「繼承」或「引入」:**引入 0 個** |
|
|
148
180
|
| **主題匯出/匯入** | 兩條路徑,都來回驗證過。`theme_export.php` 用 WP-CLI 把資料列搬成 JSON、ID 不變。`theme_zip.py` 驅動 Mosaic **自己**的 ZIP 匯出匯入——匯入預設進 test mode,要 `--activate` 才上線,因為它的預設是直接切換 live 站——**22 項檢查**逐表、逐樹比對副本與來源 |
|
|
149
181
|
| **技能本身** | `claude plugin eval .`——五個使用者真的會問的問題,各跑三次,有載技能和沒載各一臂,每次三個 LLM 裁判。**有:五題全 1.00。沒有:五題全 0.00。** 基準線最好的回答是拒答 |
|
|
150
|
-
| **線上量測** |
|
|
182
|
+
| **線上量測** | 115 條 REST 路由、156 個 variant、59 個條件主體、23 張表 / 210 個欄位 |
|
|
183
|
+
| **1.0.9 新功能** | modal(`<dialog>`)、OpenStreetMap、exit-intent 與 scroll-depth 觸發、run rules、memory action 與 modal shorthand,全部建在真實頁面上並用瀏覽器實際操作:19 之 19。「離開意圖彈窗、每個 session 只出現一次」只需要一個物件,不用接線 |
|
|
151
184
|
| **自訂欄位** | ACF 與 Meta Box,一頁四十個欄位,透過 `@VAR` / `@LOOP` 從送達的 HTML 讀回:62 個裡 59 個解析正確、3 個空值有解釋;多值欄位的迴圈剛好渲染出欄位的列數。`tools/list_fields.php` 列出 Mosaic 真正註冊的名字 |
|
|
152
185
|
| **線上升級** | 1.0.7 → 1.0.8 走外掛自己的 milestone 路由、在 wp-admin 之外驅動:6 個 milestone、四張表改名、每個輸出 class 名稱都變、每個 `customStyles` 都重寫——然後上面每一項掃描在結果上重跑 |
|
|
153
186
|
|
|
@@ -222,6 +255,7 @@ button / html / icon-list / divider / image 佔了全部元素的 99.6%。長尾
|
|
|
222
255
|
| `theme_export.php` / `theme_import.php` | 整個主題以 JSON 資料列透過 WP-CLI 搬移,ID 不變 |
|
|
223
256
|
| `theme_zip.py` / `theme_zip_compare.php` / `theme_delete.php` | 在編輯器外驅動 Mosaic 自己的 ZIP 匯出匯入、副本對來源逐樹比對、以及拒絕刪 live 主題的乾淨刪除 |
|
|
224
257
|
| `list_fields.php` | 一篇文章的自訂欄位註冊了哪些 `@VAR` / `@LOOP` 名字,連值一起列出 |
|
|
258
|
+
| `verify_dialog.py` | 在瀏覽器裡實際操作 1.0.9 的 modal、觸發、run rules 與 memory |
|
|
225
259
|
| `data_upgrade.py` | 外掛更新後,走 Mosaic 自己的 milestone 路由跑資料遷移——沒跑完之前編輯器 API 是不存在的 |
|
|
226
260
|
| `sweep_*.py` / `probe_*.py` | 那些表格是用這些儀器量出來的 |
|
|
227
261
|
| `bootstrap_probe_theme.php` / `mint_session.php` | 免授權的實驗主題,以及從 WP-CLI 鑄出 REST session |
|
|
@@ -250,7 +284,7 @@ npm version minor # 更新 package.json、SKILL.md 和八個平台模板的
|
|
|
250
284
|
# commit、打 tag、push;tag 觸發 release.yml
|
|
251
285
|
```
|
|
252
286
|
|
|
253
|
-
`
|
|
287
|
+
`scripts/check-release.mjs` 把關每一次發版,檢查的是容易出錯而不是容易檢查的事:版號一致、
|
|
254
288
|
`files` 的每個 glob 都對到東西、每張驗證表的列數仍然等於 SKILL.md 和四份 README 引用的數字、
|
|
255
289
|
沒有未裁定的設計稽核發現、eval 套件在場,以及**直接檢查 tarball 本身**——npm 的 `files` 白名單
|
|
256
290
|
會蓋過 `.gitignore`,曾經把一個真實客戶的網站放進即將發布的套件裡。
|
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 (
|
|
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.
|
|
7
|
+
version: "1.20.1"
|
|
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.
|
|
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:
|
|
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.
|
|
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
|
|
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
|
-
|
|
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,18 @@ 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
|
+
|
|
174
187
|
FIELDS ACF 6.8 and Meta Box 5.15, forty fields registered in code on a page,
|
|
175
188
|
read back off the delivered HTML: 59 of 62 expressions resolve to the
|
|
176
189
|
value expected, the 3 empties explained (select label needs ACF's
|
|
@@ -301,7 +314,7 @@ ACCORDION 7 checks that resolve a wrong entry in this skill's own tables.
|
|
|
301
314
|
version of the probe destroyed the positive result it had just
|
|
302
315
|
produced. data/accordion-verification.csv
|
|
303
316
|
|
|
304
|
-
BROWSER
|
|
317
|
+
BROWSER 4,132 computed-style readings on the delivered pages in Chromium, at
|
|
305
318
|
three viewports: every declared property vs `getComputedStyle` on the
|
|
306
319
|
node it targets. 2,929 compared and agreed, 912 not-comparable and
|
|
307
320
|
labelled as such, 0 overridden. Plus a design audit that only a browser
|
|
@@ -313,7 +326,7 @@ BROWSER 3,988 computed-style readings on the delivered pages in Chromium, a
|
|
|
313
326
|
sweep's NO_EFFECT on `processShortcodes` was the sweep, not the flag.
|
|
314
327
|
data/browser-verification.csv, data/design-audit.csv
|
|
315
328
|
|
|
316
|
-
RWD
|
|
329
|
+
RWD 733 responsive declarations across two sites asserted against the
|
|
317
330
|
stylesheet the site actually served - each `_t`/`_m` property matched
|
|
318
331
|
to its element's generated class inside that breakpoint's own media
|
|
319
332
|
query. All verified; the checker is itself checked against a poisoned
|
|
@@ -336,7 +349,7 @@ EVAL the skill itself, put in front of the model with and without it loa
|
|
|
336
349
|
don't have reliable knowledge of Mosaic Pro's spec format"), which is
|
|
337
350
|
the right thing for a model with no data to do. evals/
|
|
338
351
|
|
|
339
|
-
MEASURED
|
|
352
|
+
MEASURED 115 REST routes, 156 variants, 59 condition subjects,
|
|
340
353
|
23 tables / 210 columns - read off the running site.
|
|
341
354
|
|
|
342
355
|
UPGRADE 1.0.7 -> 1.0.8 driven over the plugin's own milestone route from
|
|
@@ -346,9 +359,9 @@ UPGRADE 1.0.7 -> 1.0.8 driven over the plugin's own milestone route from
|
|
|
346
359
|
one selector on the worked example that named an emitted class
|
|
347
360
|
stopped matching until it was rewritten. references/upgrading.md
|
|
348
361
|
|
|
349
|
-
FROM SOURCE
|
|
350
|
-
|
|
351
|
-
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.
|
|
352
365
|
```
|
|
353
366
|
|
|
354
367
|
**Coverage, stated as a fraction rather than as a headline.** The verification
|
|
@@ -357,8 +370,8 @@ the difference is worth being exact about:
|
|
|
357
370
|
|
|
358
371
|
```
|
|
359
372
|
node types 122 / 122 swept live, one per document
|
|
360
|
-
node properties
|
|
361
|
-
own validator chain:
|
|
373
|
+
node properties 191 / 191 re-probed with a value shaped by each property's
|
|
374
|
+
own validator chain: 38 APPLIED, 45 NO_EFFECT,
|
|
362
375
|
2 EDITOR_ONLY, 55 NO_HOST (no rendering type
|
|
363
376
|
declares them), 2 INSTRUMENT, 45 SKIPPED
|
|
364
377
|
style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
|
|
@@ -367,7 +380,7 @@ style properties 98 / 98 swept live; 58 COMPILED, 18 ABSENT, 1 NO_ELEMENT,
|
|
|
367
380
|
```
|
|
368
381
|
|
|
369
382
|
**A same-value probe measures the probe, not the surface.** The first property run
|
|
370
|
-
sent the string `MPROP0000X` to all 181 properties (
|
|
383
|
+
sent the string `MPROP0000X` to all 181 properties (191 by 1.0.9) regardless of what each wanted,
|
|
371
384
|
and reported 91 NO_EFFECT. The tell was that `tagName` was in that list while the
|
|
372
385
|
entire demo site is built on it. Re-probed with a value derived from the declared
|
|
373
386
|
validator chain - array for `ValidatorArray`, boolean for `ValidatorBoolean`, a legal
|
|
@@ -459,7 +472,9 @@ so the pattern is in the data, not just in this paragraph.
|
|
|
459
472
|
12. `references/custom-fields.md` — ACF and Meta Box fields as `@VAR` / `@LOOP`:
|
|
460
473
|
the names, what each field type resolves to, and the loop element that walks
|
|
461
474
|
a multi-value field. Measured, 62 rows.
|
|
462
|
-
13. `references/
|
|
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
|
|
463
478
|
delivered page, measured on 1.0.7 -> 1.0.8; how to drive the migration and what
|
|
464
479
|
to re-verify afterwards.
|
|
465
480
|
|
|
@@ -469,20 +484,20 @@ so the pattern is in the data, not just in this paragraph.
|
|
|
469
484
|
|---|---|---|
|
|
470
485
|
| `data/node-verification.csv` | 122 | **swept live** — outcome, rendered tag and classes, page bytes, failure detail |
|
|
471
486
|
| `data/node-types.csv` | 122 | source — slug, label, edition, aliases, data class |
|
|
472
|
-
| `data/node-properties.csv` |
|
|
487
|
+
| `data/node-properties.csv` | 191 | source — property, validator chain, **accepted enum values**, `supportsInherit` |
|
|
473
488
|
| `data/placement-rules.csv` | 122 | source — which children each type accepts |
|
|
474
489
|
| `data/default-children.csv` | 10 | source — what a composite type needs **inside** it |
|
|
475
490
|
| `data/style-properties.csv` | 98 | source — every settable CSS property and its value shape |
|
|
476
491
|
| `data/style-value-shapes.csv` | 22 | **probed live** — the exact JSON shape for each structured value, and what it compiled to |
|
|
477
492
|
| `data/style-states.csv` | 53 | source — state IDs with their exact CSS selector templates |
|
|
478
493
|
| `data/property-verification.csv` | 170 | **probed live** — per-property effect on markup vs CSS, with unprovable enums marked INCONCLUSIVE |
|
|
479
|
-
| `data/node-property-verification.csv` |
|
|
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 |
|
|
480
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 |
|
|
481
|
-
| `data/rwd-verification.csv` |
|
|
482
|
-
| `data/browser-verification.csv` |
|
|
496
|
+
| `data/rwd-verification.csv` | 733 | **checked live** - every `_t`/`_m` declaration vs the served stylesheet, with status per row |
|
|
497
|
+
| `data/browser-verification.csv` | 4132 | **computed in Chromium** - declared vs `getComputedStyle` at three viewports, `not-comparable` labelled per row |
|
|
483
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 |
|
|
484
499
|
| `data/design-audit.csv` | 26 | **computed in Chromium** - contrast, font fallback, CJK tracking, overflow, measure. Empty means it ran and found nothing |
|
|
485
|
-
| `data/data-class-hierarchy.csv` |
|
|
500
|
+
| `data/data-class-hierarchy.csv` | 125 | source - every data class and its parent, so a type's inherited properties can be resolved |
|
|
486
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 |
|
|
487
502
|
| `data/component-verification.csv` | 8 | **driven live** - the component lifecycle, each step asserted against the row or the delivered HTML |
|
|
488
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 |
|
|
@@ -490,20 +505,21 @@ so the pattern is in the data, not just in this paragraph.
|
|
|
490
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 |
|
|
491
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 |
|
|
492
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 |
|
|
493
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 |
|
|
494
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 |
|
|
495
511
|
| `data/node-type-notes.csv` | 8 | where a sweep outcome is true but misleading on its own, why. Surfaced by `mo.py type` |
|
|
496
512
|
| `data/interaction-verification.csv` | 7 | **probed live** - interaction animation shapes, with negative controls and the stored row beside the payload |
|
|
497
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 |
|
|
498
|
-
| `data/variants.csv` |
|
|
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 |
|
|
499
515
|
| `data/dynamic-variables.csv` | 74 | source — every `@VAR('ns/name')` expression, by namespace |
|
|
500
516
|
| `data/evaluator-functions.csv` | 19 | source — the `@` functions with their arity |
|
|
501
|
-
| `data/interaction-types.csv` |
|
|
517
|
+
| `data/interaction-types.csv` | 15 | source — trigger types, `timed` vs `progress`; 1.0.9 adds exitIntent, scrollDepth and modal |
|
|
502
518
|
| `data/animatable-properties.csv` | 22 | source — what a keyframe can drive (**not** the same set as the style properties) |
|
|
503
519
|
| `data/condition-subjects.csv` | 59 | **live** — condition subjects per context |
|
|
504
520
|
| `data/condition-comparators.csv` | 12 | **live** — comparators and their operator sets |
|
|
505
|
-
| `data/pluggables.csv` |
|
|
506
|
-
| `data/rest-routes.csv` |
|
|
521
|
+
| `data/pluggables.csv` | 249 | source — every `setID()` by registry |
|
|
522
|
+
| `data/rest-routes.csv` | 115 | **live** — method, path, args |
|
|
507
523
|
| `data/db-columns.csv` | 210 | **live** — every column of all 23 tables |
|
|
508
524
|
|
|
509
525
|
## Building a page
|
|
@@ -593,7 +609,7 @@ post — `build_all.py` resets first for that reason.
|
|
|
593
609
|
|
|
594
610
|
## Facts worth knowing before you look anything up
|
|
595
611
|
|
|
596
|
-
- **The REST namespace contains the plugin version** (`/wp-json/mosaic/v1.0.
|
|
612
|
+
- **The REST namespace contains the plugin version** (`/wp-json/mosaic/v1.0.9`). Read
|
|
597
613
|
it from `mosaicOptions.rest_api_url`, never hardcode. After a plugin update the
|
|
598
614
|
editor namespace is GONE until the data upgrade has run; only
|
|
599
615
|
`mosaic/<dataVersion>/<version>/upgrade` answers. `tools/data_upgrade.py`.
|
|
@@ -651,7 +667,21 @@ post — `build_all.py` resets first for that reason.
|
|
|
651
667
|
set (masters not reached from a bound template, their templates, their nodes)
|
|
652
668
|
the same import took under two minutes and compared 22 of 22. Prune before you
|
|
653
669
|
export; `wp_mosaic_template_assigns.parentID` -> template -> `masterID` is the
|
|
654
|
-
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".
|
|
655
685
|
- **A custom field is `@VAR('post/meta_<key>')`, and a multi-value one is a LOOP.**
|
|
656
686
|
ACF and Meta Box both, plus bare post meta. Derived properties hang off the
|
|
657
687
|
name with two underscores (`meta_k__label`, `__url`, `__id`); an ACF group is
|
|
@@ -719,6 +749,7 @@ post — `build_all.py` resets first for that reason.
|
|
|
719
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` |
|
|
720
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 |
|
|
721
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 |
|
|
722
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`) |
|
|
723
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 |
|
|
724
755
|
| `copy_styles.py` | push one node's style onto others, by attrID or prefix |
|
|
@@ -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.
|
|
23
|
+
"version": "1.20.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.
|
|
23
|
+
"version": "1.20.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.
|
|
23
|
+
"version": "1.20.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.
|
|
23
|
+
"version": "1.20.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.
|
|
23
|
+
"version": "1.20.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,
|
|
@@ -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,
|
|
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
|