@zohofinance/commerce 1.0.0 → 1.0.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.md +61 -0
- package/package.json +2 -2
- package/ts-dist/mocks/init-theme/.claude/CLAUDE.md +6 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/SKILL.md +242 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/figma.md +81 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/screenshot.md +54 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/url.md +88 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/spec-table.md +102 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/accessibility.md +110 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/performance.md +127 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/tokens.md +87 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/visual-diff.md +123 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/SKILL.md +605 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/page-json-contract.md +58 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/reference-lookup.md +94 -0
- package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/section-anatomy.md +109 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +313 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/agent-hierarchy.md +142 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +113 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/bootstrap.md +260 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/build-metrics.md +89 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/code-quality.md +186 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/common-pages-agent.md +97 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +127 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/exemplars.md +79 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-discovery.md +138 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-extraction.md +132 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/image-sources.md +84 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/inputs/guidelines-frame.md +178 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-builder.md +322 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-orchestrator.md +199 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/parallel-fanout.md +152 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/a11y.mjs +129 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/lint-section.mjs +502 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/perf.mjs +134 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/pixel-diff.mjs +206 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/record-build-metrics.mjs +118 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/section-builder.md +131 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +75 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/transcription-rules.md +98 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/verification.md +227 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +117 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/assets.md +105 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/best-practices.md +212 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/custom-scripts.md +294 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/i18n.md +155 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/introduction.md +91 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/layouts.md +158 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/pages.md +156 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/_index.md +4 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/filters.md +419 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/global-objects.md +415 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/schema-types.md +926 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/tags.md +259 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/sections.md +203 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/setup-guide.md +424 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/snippets.md +70 -0
- package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/theme-structure.md +252 -0
- package/ts-dist/mocks/init-theme/.cursor/PLAYBOOK.md +144 -0
- package/ts-dist/mocks/init-theme/.cursor/README.md +6 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/figma-desktop-mobile-parallel.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +221 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-field.md +83 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/add-theme-setting.md +200 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/assemble-page.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/audit-page.md +57 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-page-sections.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-section.md +418 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +307 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +358 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/create-theme.md +77 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/extract-tokens.md +43 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/fix-section.md +92 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/impact.md +50 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-a11y.md +66 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-i18n.md +110 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-layout.md +127 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-performance.md +72 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-section.md +84 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-sections.md +48 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/qa-theme.md +85 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/redesign-section.md +177 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/refactor-section.md +185 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/sync-theme-settings.md +132 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-page.md +60 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-section-group.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/commands/validate-theme-settings.md +119 -0
- package/ts-dist/mocks/init-theme/.cursor/examples/design-instructions-template.md +151 -0
- package/ts-dist/mocks/init-theme/.cursor/mcp.json +18 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/README.md +160 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/accessibility.mdc +24 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-field.mdc +222 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/add-theme-setting.mdc +39 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/assemble-page.mdc +130 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/audit-page.mdc +92 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-section.mdc +178 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/build-theme.mdc +47 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/compare-section.mdc +94 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/create-theme.mdc +78 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/css.mdc +137 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/design-spec-extraction.mdc +255 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/extract-tokens.mdc +43 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/figma-mcp-resolution.mdc +40 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/fix-section.mdc +154 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/general.mdc +30 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/i18n.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/javascript.mdc +85 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid-no-hardcoded-strings.mdc +42 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/liquid.mdc +171 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/mobile-desktop-setting-meta.mdc +34 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/naming-convention.mdc +64 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/pages.mdc +120 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/performance.mdc +51 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/qa-section.mdc +134 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/redesign-section.mdc +147 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema-sync.mdc +110 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/schema.mdc +360 -0
- package/ts-dist/mocks/init-theme/.cursor/rules/share-urls.mdc +68 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +128 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/design-tokens.md +105 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/page-json-contract.md +87 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/qa-accessibility.md +35 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/reference-lookup.md +88 -0
- package/ts-dist/mocks/init-theme/.cursor/skills/section-anatomy.md +173 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Level A — Page orchestrator (identifies sections, spawns Level B)
|
|
2
|
+
|
|
3
|
+
One Level A agent per page. **Does not write section Liquid.** Identifies sections from the page Figma frame, spawns **Level B** (section builder) per section in parallel, assembles `pages/<page>.json`, runs whole-page visual verify.
|
|
4
|
+
|
|
5
|
+
See `agent-hierarchy.md`.
|
|
6
|
+
|
|
7
|
+
Five page orchestrators run (Stage 1a + Stage 1b). The common-pages orchestrator (Stage 1c) follows the same pattern for cart/checkout/account.
|
|
8
|
+
|
|
9
|
+
## Read first
|
|
10
|
+
|
|
11
|
+
- `dev-server-and-urls.md` — confirmed storeUrl + page URLs before browser verify.
|
|
12
|
+
- `subagent-escalation.md` — escalate all blockers/questions to main agent screen.
|
|
13
|
+
- `zcommerce-docs/pages.md` — page JSON contract (section order, settings shape).
|
|
14
|
+
- `zcommerce-docs/sections.md` — section structure (because you'll be giving subagents specs).
|
|
15
|
+
- `section-builder.md` — what the subagents you spawn will do.
|
|
16
|
+
- `ask-developer.md` — when to surface ambiguity to the developer vs decide.
|
|
17
|
+
|
|
18
|
+
## Inputs
|
|
19
|
+
|
|
20
|
+
From the main orchestrator:
|
|
21
|
+
- Page name and Figma URL(s) (desktop + mobile).
|
|
22
|
+
- Theme folder path.
|
|
23
|
+
- Scratchpad path at `.claude/scratchpad/<theme>/pages/<page>/`.
|
|
24
|
+
- Locked files: `theme.json`, `tailwind.config.js`, `figma-variables.json`.
|
|
25
|
+
- For page agents other than `index`: wait for `header-footer-ready` marker before starting verification.
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### Phase 1 — Page intake (~45s)
|
|
30
|
+
|
|
31
|
+
Pull from Figma in parallel:
|
|
32
|
+
- `get_screenshot` desktop frame
|
|
33
|
+
- `get_screenshot` mobile frame
|
|
34
|
+
- `get_design_context` desktop frame
|
|
35
|
+
- `get_design_context` mobile frame
|
|
36
|
+
|
|
37
|
+
Save raw artefacts to scratchpad. **Do not** start identifying sections from the screenshot alone — use `get_design_context` to get the structured node tree which tells you the real boundaries.
|
|
38
|
+
|
|
39
|
+
### Phase 2 — Section identification (~30s)
|
|
40
|
+
|
|
41
|
+
Walk the design context top to bottom. Identify distinct sections by:
|
|
42
|
+
- Top-level frame children that look like full-width content blocks
|
|
43
|
+
- Visual whitespace breaks between groups of elements
|
|
44
|
+
- Repeated patterns (3 cards → likely one "card grid" section, not 3 sections)
|
|
45
|
+
|
|
46
|
+
Produce a section plan:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
SECTION 1 header (top region, frame node 1234:5)
|
|
50
|
+
SECTION 2 hero-banner (full-width banner, node 1234:8)
|
|
51
|
+
SECTION 3 feature-row (3-column feature highlights, node 1234:12)
|
|
52
|
+
SECTION 4 featured-products (product grid, node 1234:20)
|
|
53
|
+
SECTION 5 cta-banner (single CTA strip, node 1234:30)
|
|
54
|
+
SECTION 6 newsletter-signup (form + heading, node 1234:35)
|
|
55
|
+
SECTION 7 footer (bottom region, node 1234:40)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For each, record:
|
|
59
|
+
- Section name (snake-case, used as filename)
|
|
60
|
+
- Figma node ID (for the section subagent's `get_screenshot` crop)
|
|
61
|
+
- Archetype (hero, product-grid, etc. — for exemplar lookup)
|
|
62
|
+
- Estimated complexity (small / medium / large — for time budgeting)
|
|
63
|
+
|
|
64
|
+
**Ambiguity check:** If a region's identity is unclear (two adjacent banners — is it one section with 2 blocks or 2 separate sections?), add it to the `pending_questions.md` file in scratchpad. Don't decide yet.
|
|
65
|
+
|
|
66
|
+
**Hard rule — the section list matches the Figma 1:1.** Every section in `sections.plan.md` must correspond to a region visible in the Figma frame. Do NOT include sections you "think would be useful" or "are pre-existing in sibling themes" if they aren't shown in the Figma. The bug that shipped in a prior build (a "Why families pick us" / value-props block appearing on the rendered page despite not being in the Figma) was caused by the agent including a section from its memory of sibling themes rather than from the Figma. The plan must be visually grounded in the Figma frame — no inventions, no carryovers.
|
|
67
|
+
|
|
68
|
+
If a section type seems useful but isn't in the Figma, write a NEEDS_REVIEW item explaining what's missing. Let the developer decide. Don't add silently.
|
|
69
|
+
|
|
70
|
+
### Phase 3 — Snippet planning (~1min)
|
|
71
|
+
|
|
72
|
+
Identify shared snippets needed across multiple sections on this page:
|
|
73
|
+
- `product-card` — used by listing and featured-products
|
|
74
|
+
- `cart-row` — used by cart-list and cart-popup
|
|
75
|
+
- `pagination` — used by listing and blog-list
|
|
76
|
+
- `pricing-display` — used by product-card and product-details
|
|
77
|
+
|
|
78
|
+
For each shared snippet, build FRESH from the docs (`zcommerce-docs/snippets.md`) using the theme tokens. Save to `snippets/<name>.liquid`.
|
|
79
|
+
|
|
80
|
+
Run lint on each snippet before continuing. Snippets must pass lint just like sections.
|
|
81
|
+
|
|
82
|
+
Record the snippet registry in `<scratchpad>/snippets.md`:
|
|
83
|
+
```
|
|
84
|
+
- product-card.liquid (params: product, show_price=true) — usable by hero, featured-products, listing
|
|
85
|
+
- pricing-display.liquid (params: price, compare_at_price) — usable by product-card, product-details
|
|
86
|
+
- pagination.liquid (params: paginate_obj) — usable by listing, blog-list
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This registry is passed to every section subagent. Subagents render existing snippets via `{% render '<name>' %}`; they do NOT redefine.
|
|
90
|
+
|
|
91
|
+
### Phase 4 — Spawn Level B subagents (PARALLEL)
|
|
92
|
+
|
|
93
|
+
One subagent per section. **Level A must not build sections itself.**
|
|
94
|
+
|
|
95
|
+
Send N `Task` / `Agent` calls in one message. Each prompt MUST state:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
You are LEVEL B — section builder.
|
|
99
|
+
Scope: section "<section_name>" ONLY. Figma node: <desktop_node_id>.
|
|
100
|
+
Do NOT call get_design_context on the parent page frame.
|
|
101
|
+
Follow: section-builder.md, figma-extraction.md, transcription-rules.md.
|
|
102
|
+
Verify: lint-section.mjs + Chrome DevTools visual vs section Figma crop.
|
|
103
|
+
PASS = visual-diff.md with 0 CRITICAL.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Pass to each Level B:
|
|
107
|
+
- `section_name`, `figma_node_id` (desktop + mobile if different)
|
|
108
|
+
- `scratchpad` path: `pages/<page>/sections/<section_name>/`
|
|
109
|
+
- `page_url` from `dev-config.json` (for browser verify scroll target)
|
|
110
|
+
- `snippets.md` registry (render only, do not redefine)
|
|
111
|
+
- Lock: other sections' files, theme.json, figma-variables.json
|
|
112
|
+
|
|
113
|
+
### Phase 5 — Wait + collect (varies, ~3-5min)
|
|
114
|
+
|
|
115
|
+
Wait for all section subagents to finish. Each writes a report to `<scratchpad>/sections/<name>/report.md` with:
|
|
116
|
+
- Verdict (PASS / FAIL / NEEDS_REVIEW)
|
|
117
|
+
- Lint results
|
|
118
|
+
- Per-section pixel-diff result (vs the section's Figma crop)
|
|
119
|
+
- Per-section axe result
|
|
120
|
+
- List of unresolved questions for the developer (if any)
|
|
121
|
+
|
|
122
|
+
### Phase 6 — Batch developer questions (one round)
|
|
123
|
+
|
|
124
|
+
Collect all `pending_questions.md` files (from phase 2) + `unresolved.md` from each section subagent.
|
|
125
|
+
|
|
126
|
+
If there are questions, present them as ONE batched `AskUserQuestion` call. Group similar questions. Cap at 4 questions per batch (AskUserQuestion's limit); if more, ask the most consequential 4 and defer the rest with sensible defaults logged in NEEDS_REVIEW.
|
|
127
|
+
|
|
128
|
+
After the developer answers, propagate answers to the affected section subagents OR (if they've already finished) edit the produced files directly and re-run gates.
|
|
129
|
+
|
|
130
|
+
### Phase 7 — Assemble page JSON (~30s)
|
|
131
|
+
|
|
132
|
+
Write `pages/<page>.json` with the section order from phase 2 and each section's default settings.
|
|
133
|
+
|
|
134
|
+
**Hard rule — populate every multi-block section's blocks with distinct, Figma-transcribed content.** For sections that have multiple block instances of the same type (e.g., a blog-highlights section with `post_1`, `post_2`, `post_3` blocks), the page JSON must transcribe each block's specific content from the Figma:
|
|
135
|
+
|
|
136
|
+
- Each block's `settings` object must be non-empty (not `{}`).
|
|
137
|
+
- Each block's settings must be distinct from sibling blocks of the same type — no two blocks with byte-identical settings unless the Figma actually shows duplicates.
|
|
138
|
+
- Headlines, body copy, image filenames, dates, button labels, link handles — all from the Figma frame for that specific card, NOT inherited from the schema's `default` field.
|
|
139
|
+
|
|
140
|
+
Why this matters: schema defaults are fallbacks for when the customizer admin clears a value. They're not intended to fill multiple blocks with the same content. If the agent leaves `settings: {}` for `post_2` and `post_3`, all three cards render the schema's `post_title` default identically — the bug that shipped in a prior build. `verify-theme.mjs`'s `block_settings_populated` check catches this.
|
|
141
|
+
|
|
142
|
+
For the listing agent: also write `pages/collection.json`, `pages/category.json`, `pages/search.json` (all relative to the theme root) — all three use the same sections.
|
|
143
|
+
|
|
144
|
+
### Phase 8 — WHOLE-PAGE verification via Chrome DevTools MCP (~2min)
|
|
145
|
+
|
|
146
|
+
Section subagents verified their pieces. The page orchestrator verifies the **assembled whole** using the same 3-gate workflow (see `visual-verify-loop.md` §Per-page loop):
|
|
147
|
+
|
|
148
|
+
1. `emulate` desktop 1440×900 → `navigate_page` → full-page `take_screenshot`
|
|
149
|
+
2. `emulate` mobile 375×812 → `take_screenshot`
|
|
150
|
+
3. Figma `get_screenshot` on page-level desktop + mobile node IDs
|
|
151
|
+
4. Agent vision → `pages/<page>/visual-diff.md` (focus: section order, gaps, missing/extra blocks)
|
|
152
|
+
5. `lighthouse_audit` navigation mobile — a11y ≥ 90, perf ≥ 85
|
|
153
|
+
6. `list_console_messages` + `list_network_requests`
|
|
154
|
+
|
|
155
|
+
**PASS:** 0 CRITICAL in page `visual-diff.md`.
|
|
156
|
+
|
|
157
|
+
**If sections passed but page fails:** fix inter-section spacing/order in `pages/<page>.json` or offending section padding. Max **2 iterations**.
|
|
158
|
+
|
|
159
|
+
Optional: run `pixel-diff.mjs` for CI JSON artefacts — not required when MCP visual compare passes.
|
|
160
|
+
|
|
161
|
+
### Phase 9 — Report + escalate to main agent
|
|
162
|
+
|
|
163
|
+
Write final page report to `<scratchpad>/pages/<page>/report.md`.
|
|
164
|
+
|
|
165
|
+
Include an **ESCALATION** block (see `subagent-escalation.md`) in the return message so the main orchestrator posts it to the developer chat — even if you already used `AskUserQuestion` during the build.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
PAGE: index
|
|
169
|
+
SECTIONS BUILT: 7
|
|
170
|
+
SHARED SNIPPETS BUILT: 2 (product-card, pricing-display)
|
|
171
|
+
|
|
172
|
+
PER-SECTION VERIFY (all PASS):
|
|
173
|
+
header pixel-diff 1.2 / a11y pass / lint pass
|
|
174
|
+
hero-banner pixel-diff 1.8 / a11y pass / lint pass
|
|
175
|
+
feature-row pixel-diff 1.4 / a11y pass / lint pass
|
|
176
|
+
featured-products pixel-diff 2.1 / a11y pass / lint pass (1 iteration)
|
|
177
|
+
cta-banner pixel-diff 1.6 / a11y pass / lint pass
|
|
178
|
+
newsletter-signup pixel-diff 1.9 / a11y pass / lint pass
|
|
179
|
+
footer pixel-diff 1.5 / a11y pass / lint pass
|
|
180
|
+
|
|
181
|
+
WHOLE-PAGE VERIFY:
|
|
182
|
+
desktop pixel-diff mean 1.7, max 4.2 — PASS
|
|
183
|
+
mobile pixel-diff mean 2.0, max 5.8 — PASS
|
|
184
|
+
axe 0 critical, 0 serious, 1 moderate
|
|
185
|
+
lighthouse mobile perf 93, LCP 1.9s, CLS 0.02
|
|
186
|
+
|
|
187
|
+
DEVELOPER QUESTIONS ASKED: 2 (frame mapping for feature-row, hover color for CTA)
|
|
188
|
+
ITERATIONS: 1 (featured-products padding)
|
|
189
|
+
NEEDS_REVIEW: 0
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Things to NOT do
|
|
193
|
+
|
|
194
|
+
- Don't build sections yourself — that's the subagents' job.
|
|
195
|
+
- Don't approve a page where section-level verify passed but whole-page failed without iterating.
|
|
196
|
+
- Don't ask the developer per-section — batch at phase 6.
|
|
197
|
+
- Don't skip whole-page verify even if every section passed individually.
|
|
198
|
+
- Don't write shared snippets after spawning subagents — that creates race conditions. Write them in phase 3.
|
|
199
|
+
- Don't modify locked files (theme.json, etc., or other sections' files).
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Stage 1 — Level A fan-out (page orchestrators)
|
|
2
|
+
|
|
3
|
+
Stage 1 uses the **Level 0 → A → B** hierarchy from `agent-hierarchy.md`.
|
|
4
|
+
|
|
5
|
+
- **Level 0** spawns **Level A** agents (one per page).
|
|
6
|
+
- **Level A** spawns **Level B** agents (one per section on that page).
|
|
7
|
+
- **Level B** builds and verifies sections — Level A never writes section Liquid.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Phase 1a — Index Level A (serial, ~4–6 min)
|
|
12
|
+
|
|
13
|
+
The index Level A runs **first and alone**. It identifies sections on the home page, spawns Level B for header + footer + all index sections, assembles `pages/index.json`, and publishes the `header-footer-ready` marker.
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
Phase 1a: Level A (index) → Level B × N sections ────████████████ ~4–6min
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Spawn one Level A agent:**
|
|
20
|
+
|
|
21
|
+
- **`subagent_type`**: `generalPurpose`
|
|
22
|
+
- **`description`**: `Level A: index page`
|
|
23
|
+
- **`prompt`**: see template below with `PAGE_NAME=index`
|
|
24
|
+
|
|
25
|
+
After index Level A finishes and writes `.claude/scratchpad/<theme>/header-footer-ready`, proceed to Phase 1b.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Phase 1b — Four parallel Level A agents (~4–6 min)
|
|
30
|
+
|
|
31
|
+
Spawn four Level A agents in one message (concurrent):
|
|
32
|
+
|
|
33
|
+
| Level A agent | Page | Page JSON |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| listing | `listing` | `collection.json`, `category.json`, `search.json` |
|
|
36
|
+
| product | `product` | `product.json` |
|
|
37
|
+
| blog_list | `blog_list` | `blogs.json` |
|
|
38
|
+
| blog_detail | `blog_detail` | `blog.json` |
|
|
39
|
+
|
|
40
|
+
Each Level A:
|
|
41
|
+
1. Identifies sections → `sections.plan.md`
|
|
42
|
+
2. Spawns Level B per section (parallel)
|
|
43
|
+
3. Assembles page JSON
|
|
44
|
+
4. Whole-page visual verify vs Figma page frame
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Phase 1b: listing ─────────────████████ ~4min
|
|
48
|
+
product ─────────────██████████ ~5min
|
|
49
|
+
blog_list ─────────────████ ~3min
|
|
50
|
+
blog_detail ───────────████ ~3min
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Wall-clock ≈ slowest Level A agent (~5–7 min after index).
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Level A spawn template
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
You are LEVEL A — page orchestrator for the <PAGE_NAME> page.
|
|
61
|
+
You do NOT write section Liquid. You identify sections and spawn Level B agents.
|
|
62
|
+
|
|
63
|
+
THEME: <theme_name>
|
|
64
|
+
THEME FOLDER: <theme_name>/
|
|
65
|
+
SCRATCHPAD: .claude/scratchpad/<theme_name>/pages/<page_name>/
|
|
66
|
+
FIGMA: desktop node <desktop_node_id>, mobile node <mobile_node_id>
|
|
67
|
+
PAGE URL: read from .claude/scratchpad/<theme>/dev-config.json — never guess
|
|
68
|
+
|
|
69
|
+
WORKFLOW: Follow page-orchestrator.md exactly.
|
|
70
|
+
HIERARCHY: agent-hierarchy.md — scope = page frame for identification only.
|
|
71
|
+
SECTION SPAWN: For each section in sections.plan.md, spawn one Level B agent
|
|
72
|
+
(see Level B template below). All Level B in one parallel message.
|
|
73
|
+
|
|
74
|
+
LOCKED (do not modify):
|
|
75
|
+
- settings/theme.json, tailwind.config.js, figma-variables.json
|
|
76
|
+
- header.liquid, footer.liquid (after header-footer-ready marker exists)
|
|
77
|
+
|
|
78
|
+
OUTPUT:
|
|
79
|
+
- sections.plan.md (section list + Figma node IDs)
|
|
80
|
+
- pages/<page_json>.json assembled after all Level B PASS
|
|
81
|
+
- report.md with whole-page visual verify result
|
|
82
|
+
- ESCALATION block per subagent-escalation.md
|
|
83
|
+
|
|
84
|
+
Return summary + ESCALATION block. Main agent surfaces questions on screen.
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Level B spawn template (used BY Level A, not Level 0)
|
|
90
|
+
|
|
91
|
+
Level A sends N `Task` calls in one message — one per section:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
You are LEVEL B — section builder.
|
|
95
|
+
Scope: section "<section_name>" ONLY.
|
|
96
|
+
Figma node: <desktop_node_id> (mobile: <mobile_node_id> if different).
|
|
97
|
+
|
|
98
|
+
Do NOT call get_design_context on the parent page frame.
|
|
99
|
+
Do NOT read other sections' Figma or Liquid files for visual values.
|
|
100
|
+
|
|
101
|
+
THEME FOLDER: <theme_name>/
|
|
102
|
+
SCRATCHPAD: .claude/scratchpad/<theme_name>/pages/<page_name>/sections/<section_name>/
|
|
103
|
+
PAGE URL: <from dev-config.json> — scroll to this section for browser verify
|
|
104
|
+
|
|
105
|
+
WORKFLOW: section-builder.md, figma-extraction.md, transcription-rules.md
|
|
106
|
+
VERIFY:
|
|
107
|
+
1. lint-section.mjs PASS (syntax / docs)
|
|
108
|
+
2. Chrome DevTools visual vs Figma SECTION crop
|
|
109
|
+
3. visual-diff.md with 0 CRITICAL
|
|
110
|
+
|
|
111
|
+
LOCKED: all other sections/*.liquid, theme.json, figma-variables.json
|
|
112
|
+
|
|
113
|
+
Return PASS/FAIL + ESCALATION block.
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Coordination rules
|
|
119
|
+
|
|
120
|
+
1. **One section file = one Level B agent.** No two agents write the same `.liquid`.
|
|
121
|
+
2. **Level A never builds sections.** If tempted to "quickly fix" a section, re-spawn Level B.
|
|
122
|
+
3. **Level B scope = one Figma section node.** Prevents border-radius/color/card-height hallucination.
|
|
123
|
+
4. **i18n append-only** with section-scoped keys: `sections.<section_name>.*`
|
|
124
|
+
5. **Locked files** — see `agent-hierarchy.md` scope table.
|
|
125
|
+
6. **Scratchpad isolation** — Level B writes to `pages/<page>/sections/<section>/`
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Race detection (after all Level A finish)
|
|
130
|
+
|
|
131
|
+
Confirm:
|
|
132
|
+
- Each `sections/*.liquid` touched by exactly one Level B
|
|
133
|
+
- Each Level B wrote `figma-spec.json` + `visual-diff.md`
|
|
134
|
+
- Each Level A wrote `sections.plan.md` + `report.md`
|
|
135
|
+
- No Level A/B modified locked files
|
|
136
|
+
- `header-footer-ready` exists before non-index Level A started
|
|
137
|
+
|
|
138
|
+
If any fail → stop before Stage 2.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## When NOT to fan out
|
|
143
|
+
|
|
144
|
+
- Single-page iteration after initial build — run one Level A directly.
|
|
145
|
+
- Previous fan-out failed mid-flight — investigate before retry.
|
|
146
|
+
- Theme has < 3 pages — overhead may not be worth it.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Deprecated
|
|
151
|
+
|
|
152
|
+
`page-builder.md` described the old flat page-agent model (one agent builds entire page). **Do not use.** Use `page-orchestrator.md` (Level A) + `section-builder.md` (Level B).
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* a11y.mjs — run axe-core (WCAG 2.1 AA) against a URL via headless Chrome.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node a11y.mjs \
|
|
7
|
+
* --url http://localhost:3000/home \
|
|
8
|
+
* --selector "#section-hero" (optional — scope axe to one section)
|
|
9
|
+
* --out /path/to/axe.json
|
|
10
|
+
*
|
|
11
|
+
* Output JSON shape:
|
|
12
|
+
* {
|
|
13
|
+
* "url": "...",
|
|
14
|
+
* "selector": null | "...",
|
|
15
|
+
* "tags": ["wcag2a","wcag2aa","wcag21a","wcag21aa"],
|
|
16
|
+
* "summary": {
|
|
17
|
+
* "critical": 0, "serious": 1, "moderate": 2, "minor": 1
|
|
18
|
+
* },
|
|
19
|
+
* "violations": [
|
|
20
|
+
* { "id":"color-contrast", "impact":"serious", "nodes":[...], "help":"..." },
|
|
21
|
+
* ...
|
|
22
|
+
* ],
|
|
23
|
+
* "verdict": "PASS" | "FAIL"
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* Pass threshold: zero critical AND zero serious violations.
|
|
27
|
+
*
|
|
28
|
+
* Dependencies: puppeteer, axe-core
|
|
29
|
+
* npm install --no-save puppeteer axe-core
|
|
30
|
+
* (reuse this theme's node_modules if axe-core is already installed.)
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import puppeteer from 'puppeteer';
|
|
34
|
+
import { createRequire } from 'node:module';
|
|
35
|
+
import fs from 'node:fs';
|
|
36
|
+
import path from 'node:path';
|
|
37
|
+
|
|
38
|
+
const require = createRequire(import.meta.url);
|
|
39
|
+
|
|
40
|
+
const args = parseArgs(process.argv.slice(2));
|
|
41
|
+
const url = required(args, 'url');
|
|
42
|
+
const selector = args.selector || null;
|
|
43
|
+
const outPath = required(args, 'out');
|
|
44
|
+
|
|
45
|
+
const axeCorePath = (() => {
|
|
46
|
+
const candidates = [
|
|
47
|
+
'axe-core',
|
|
48
|
+
path.resolve(process.cwd(), 'node_modules/axe-core'),
|
|
49
|
+
];
|
|
50
|
+
for (const c of candidates) {
|
|
51
|
+
try { return require.resolve(`${c}/axe.min.js`); } catch {}
|
|
52
|
+
}
|
|
53
|
+
fail('Could not locate axe-core. Run: npm install --no-save axe-core');
|
|
54
|
+
})();
|
|
55
|
+
|
|
56
|
+
(async () => {
|
|
57
|
+
const browser = await puppeteer.launch({
|
|
58
|
+
headless: 'new',
|
|
59
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
const page = await browser.newPage();
|
|
63
|
+
await page.goto(url, { waitUntil: 'networkidle2', timeout: 60_000 });
|
|
64
|
+
await page.addScriptTag({ path: axeCorePath });
|
|
65
|
+
|
|
66
|
+
const results = await page.evaluate(async (scopeSelector) => {
|
|
67
|
+
const opts = {
|
|
68
|
+
runOnly: { type: 'tag', values: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'] },
|
|
69
|
+
resultTypes: ['violations'],
|
|
70
|
+
};
|
|
71
|
+
const context = scopeSelector ? document.querySelector(scopeSelector) : document;
|
|
72
|
+
if (scopeSelector && !context) {
|
|
73
|
+
return { error: `Selector not found: ${scopeSelector}` };
|
|
74
|
+
}
|
|
75
|
+
// eslint-disable-next-line no-undef
|
|
76
|
+
return await axe.run(context, opts);
|
|
77
|
+
}, selector);
|
|
78
|
+
|
|
79
|
+
if (results?.error) fail(results.error);
|
|
80
|
+
|
|
81
|
+
const violations = (results.violations || []).map((v) => ({
|
|
82
|
+
id: v.id,
|
|
83
|
+
impact: v.impact,
|
|
84
|
+
help: v.help,
|
|
85
|
+
help_url: v.helpUrl,
|
|
86
|
+
tags: v.tags,
|
|
87
|
+
node_count: v.nodes.length,
|
|
88
|
+
sample_nodes: v.nodes.slice(0, 5).map((n) => ({
|
|
89
|
+
target: n.target,
|
|
90
|
+
html: n.html,
|
|
91
|
+
failure_summary: n.failureSummary,
|
|
92
|
+
})),
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
const summary = { critical: 0, serious: 0, moderate: 0, minor: 0 };
|
|
96
|
+
for (const v of violations) summary[v.impact] = (summary[v.impact] ?? 0) + v.node_count;
|
|
97
|
+
|
|
98
|
+
const verdict = summary.critical === 0 && summary.serious === 0 ? 'PASS' : 'FAIL';
|
|
99
|
+
|
|
100
|
+
const report = {
|
|
101
|
+
url,
|
|
102
|
+
selector,
|
|
103
|
+
tags: ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'],
|
|
104
|
+
summary,
|
|
105
|
+
violations,
|
|
106
|
+
verdict,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
110
|
+
fs.writeFileSync(outPath, JSON.stringify(report, null, 2));
|
|
111
|
+
console.log(JSON.stringify(report, null, 2));
|
|
112
|
+
} finally {
|
|
113
|
+
await browser.close();
|
|
114
|
+
}
|
|
115
|
+
})().catch((e) => fail(e.message ?? String(e)));
|
|
116
|
+
|
|
117
|
+
function parseArgs(argv) {
|
|
118
|
+
const out = {};
|
|
119
|
+
for (let i = 0; i < argv.length; i++) {
|
|
120
|
+
if (argv[i].startsWith('--')) {
|
|
121
|
+
const key = argv[i].slice(2);
|
|
122
|
+
const val = argv[i + 1] && !argv[i + 1].startsWith('--') ? argv[++i] : 'true';
|
|
123
|
+
out[key] = val;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
function required(args, k) { if (!args[k]) fail(`Missing --${k}`); return args[k]; }
|
|
129
|
+
function fail(msg) { console.error('a11y error:', msg); process.exit(2); }
|