@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.
Files changed (127) hide show
  1. package/README.md +61 -0
  2. package/package.json +2 -2
  3. package/ts-dist/mocks/init-theme/.claude/CLAUDE.md +6 -0
  4. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/SKILL.md +242 -0
  5. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/figma.md +81 -0
  6. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/screenshot.md +54 -0
  7. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/inputs/url.md +88 -0
  8. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/spec-table.md +102 -0
  9. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/accessibility.md +110 -0
  10. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/performance.md +127 -0
  11. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/tokens.md +87 -0
  12. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-section-from-design.20260528/verification/visual-diff.md +123 -0
  13. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/SKILL.md +605 -0
  14. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/design-tokens.md +105 -0
  15. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/page-json-contract.md +58 -0
  16. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/qa-accessibility.md +35 -0
  17. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/reference-lookup.md +94 -0
  18. package/ts-dist/mocks/init-theme/.claude/skills/.archive/zcommerce-theme-builder.20260528/section-anatomy.md +109 -0
  19. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/SKILL.md +313 -0
  20. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/agent-hierarchy.md +142 -0
  21. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/ask-developer.md +113 -0
  22. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/bootstrap.md +260 -0
  23. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/build-metrics.md +89 -0
  24. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/code-quality.md +186 -0
  25. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/common-pages-agent.md +97 -0
  26. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/dev-server-and-urls.md +127 -0
  27. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/exemplars.md +79 -0
  28. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-discovery.md +138 -0
  29. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/figma-extraction.md +132 -0
  30. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/image-sources.md +84 -0
  31. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/inputs/guidelines-frame.md +178 -0
  32. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-builder.md +322 -0
  33. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/page-orchestrator.md +199 -0
  34. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/parallel-fanout.md +152 -0
  35. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/a11y.mjs +129 -0
  36. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/lint-section.mjs +502 -0
  37. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/perf.mjs +134 -0
  38. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/pixel-diff.mjs +206 -0
  39. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/scripts/record-build-metrics.mjs +118 -0
  40. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/section-builder.md +131 -0
  41. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/subagent-escalation.md +75 -0
  42. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/transcription-rules.md +98 -0
  43. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/verification.md +227 -0
  44. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/visual-verify-loop.md +117 -0
  45. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/_index.md +4 -0
  46. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/assets.md +105 -0
  47. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/best-practices.md +212 -0
  48. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/custom-scripts.md +294 -0
  49. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/i18n.md +155 -0
  50. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/introduction.md +91 -0
  51. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/layouts.md +158 -0
  52. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/pages.md +156 -0
  53. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/_index.md +4 -0
  54. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/filters.md +419 -0
  55. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/global-objects.md +415 -0
  56. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/schema-types.md +926 -0
  57. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/reference/tags.md +259 -0
  58. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/sections.md +203 -0
  59. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/setup-guide.md +424 -0
  60. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/snippets.md +70 -0
  61. package/ts-dist/mocks/init-theme/.claude/skills/theme-from-figma/zcommerce-docs/theme-structure.md +252 -0
  62. package/ts-dist/mocks/init-theme/.cursor/PLAYBOOK.md +144 -0
  63. package/ts-dist/mocks/init-theme/.cursor/README.md +6 -0
  64. package/ts-dist/mocks/init-theme/.cursor/agents/figma-desktop-mobile-parallel.md +48 -0
  65. package/ts-dist/mocks/init-theme/.cursor/agents/visual-compare.md +221 -0
  66. package/ts-dist/mocks/init-theme/.cursor/commands/add-field.md +83 -0
  67. package/ts-dist/mocks/init-theme/.cursor/commands/add-theme-setting.md +200 -0
  68. package/ts-dist/mocks/init-theme/.cursor/commands/assemble-page.md +72 -0
  69. package/ts-dist/mocks/init-theme/.cursor/commands/audit-page.md +57 -0
  70. package/ts-dist/mocks/init-theme/.cursor/commands/build-page-sections.md +110 -0
  71. package/ts-dist/mocks/init-theme/.cursor/commands/build-section.md +418 -0
  72. package/ts-dist/mocks/init-theme/.cursor/commands/build-theme.md +307 -0
  73. package/ts-dist/mocks/init-theme/.cursor/commands/compare-section.md +358 -0
  74. package/ts-dist/mocks/init-theme/.cursor/commands/create-theme.md +77 -0
  75. package/ts-dist/mocks/init-theme/.cursor/commands/extract-tokens.md +43 -0
  76. package/ts-dist/mocks/init-theme/.cursor/commands/fix-section.md +92 -0
  77. package/ts-dist/mocks/init-theme/.cursor/commands/impact.md +50 -0
  78. package/ts-dist/mocks/init-theme/.cursor/commands/qa-a11y.md +66 -0
  79. package/ts-dist/mocks/init-theme/.cursor/commands/qa-i18n.md +110 -0
  80. package/ts-dist/mocks/init-theme/.cursor/commands/qa-layout.md +127 -0
  81. package/ts-dist/mocks/init-theme/.cursor/commands/qa-performance.md +72 -0
  82. package/ts-dist/mocks/init-theme/.cursor/commands/qa-section.md +84 -0
  83. package/ts-dist/mocks/init-theme/.cursor/commands/qa-sections.md +48 -0
  84. package/ts-dist/mocks/init-theme/.cursor/commands/qa-theme.md +85 -0
  85. package/ts-dist/mocks/init-theme/.cursor/commands/redesign-section.md +177 -0
  86. package/ts-dist/mocks/init-theme/.cursor/commands/refactor-section.md +185 -0
  87. package/ts-dist/mocks/init-theme/.cursor/commands/sync-theme-settings.md +132 -0
  88. package/ts-dist/mocks/init-theme/.cursor/commands/validate-page.md +60 -0
  89. package/ts-dist/mocks/init-theme/.cursor/commands/validate-section-group.md +88 -0
  90. package/ts-dist/mocks/init-theme/.cursor/commands/validate-theme-settings.md +119 -0
  91. package/ts-dist/mocks/init-theme/.cursor/examples/design-instructions-template.md +151 -0
  92. package/ts-dist/mocks/init-theme/.cursor/mcp.json +18 -0
  93. package/ts-dist/mocks/init-theme/.cursor/rules/README.md +160 -0
  94. package/ts-dist/mocks/init-theme/.cursor/rules/accessibility.mdc +24 -0
  95. package/ts-dist/mocks/init-theme/.cursor/rules/add-field.mdc +222 -0
  96. package/ts-dist/mocks/init-theme/.cursor/rules/add-theme-setting.mdc +39 -0
  97. package/ts-dist/mocks/init-theme/.cursor/rules/assemble-page.mdc +130 -0
  98. package/ts-dist/mocks/init-theme/.cursor/rules/audit-page.mdc +92 -0
  99. package/ts-dist/mocks/init-theme/.cursor/rules/build-section.mdc +178 -0
  100. package/ts-dist/mocks/init-theme/.cursor/rules/build-theme.mdc +47 -0
  101. package/ts-dist/mocks/init-theme/.cursor/rules/compare-section.mdc +94 -0
  102. package/ts-dist/mocks/init-theme/.cursor/rules/create-theme.mdc +78 -0
  103. package/ts-dist/mocks/init-theme/.cursor/rules/css.mdc +137 -0
  104. package/ts-dist/mocks/init-theme/.cursor/rules/design-spec-extraction.mdc +255 -0
  105. package/ts-dist/mocks/init-theme/.cursor/rules/extract-tokens.mdc +43 -0
  106. package/ts-dist/mocks/init-theme/.cursor/rules/figma-mcp-resolution.mdc +40 -0
  107. package/ts-dist/mocks/init-theme/.cursor/rules/fix-section.mdc +154 -0
  108. package/ts-dist/mocks/init-theme/.cursor/rules/general.mdc +30 -0
  109. package/ts-dist/mocks/init-theme/.cursor/rules/i18n.mdc +85 -0
  110. package/ts-dist/mocks/init-theme/.cursor/rules/javascript.mdc +85 -0
  111. package/ts-dist/mocks/init-theme/.cursor/rules/liquid-no-hardcoded-strings.mdc +42 -0
  112. package/ts-dist/mocks/init-theme/.cursor/rules/liquid.mdc +171 -0
  113. package/ts-dist/mocks/init-theme/.cursor/rules/mobile-desktop-setting-meta.mdc +34 -0
  114. package/ts-dist/mocks/init-theme/.cursor/rules/naming-convention.mdc +64 -0
  115. package/ts-dist/mocks/init-theme/.cursor/rules/pages.mdc +120 -0
  116. package/ts-dist/mocks/init-theme/.cursor/rules/performance.mdc +51 -0
  117. package/ts-dist/mocks/init-theme/.cursor/rules/qa-section.mdc +134 -0
  118. package/ts-dist/mocks/init-theme/.cursor/rules/redesign-section.mdc +147 -0
  119. package/ts-dist/mocks/init-theme/.cursor/rules/schema-sync.mdc +110 -0
  120. package/ts-dist/mocks/init-theme/.cursor/rules/schema.mdc +360 -0
  121. package/ts-dist/mocks/init-theme/.cursor/rules/share-urls.mdc +68 -0
  122. package/ts-dist/mocks/init-theme/.cursor/skills/browser-verify.md +128 -0
  123. package/ts-dist/mocks/init-theme/.cursor/skills/design-tokens.md +105 -0
  124. package/ts-dist/mocks/init-theme/.cursor/skills/page-json-contract.md +87 -0
  125. package/ts-dist/mocks/init-theme/.cursor/skills/qa-accessibility.md +35 -0
  126. package/ts-dist/mocks/init-theme/.cursor/skills/reference-lookup.md +88 -0
  127. 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); }