@easysociable/cli 0.1.2 → 0.1.4

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 (148) hide show
  1. package/README.md +32 -21
  2. package/{skills/easysociable-content → content-engine}/scripts/starter.mjs +3 -1
  3. package/{skills/easysociable-content → content-engine}/scripts/workbench.mjs +13 -8
  4. package/{skills/easysociable-content → content-engine}/starter/CLAUDE.md +217 -128
  5. package/{skills/easysociable-content → content-engine}/starter/engine.json +3 -0
  6. package/content-engine/starter/needs/README.md +38 -0
  7. package/content-engine/starter/needs/_index.md +31 -0
  8. package/content-engine/starter/needs/_template.md +24 -0
  9. package/content-engine/starter/needs/entries/README.md +5 -0
  10. package/content-engine/starter/products/README.md +38 -0
  11. package/content-engine/starter/products/_index.md +24 -0
  12. package/content-engine/starter/products/_template.md +56 -0
  13. package/content-engine/starter/products/entries/P-001-easysociable.md +150 -0
  14. package/content-engine/starter/profiles/_index.md +16 -0
  15. package/{skills/easysociable-content → content-engine}/starter/profiles/default/README.md +4 -1
  16. package/content-engine/starter/profiles/default/boundaries.md +14 -0
  17. package/content-engine/starter/profiles/default/expression.md +18 -0
  18. package/content-engine/starter/profiles/default/lanes.md +12 -0
  19. package/content-engine/starter/profiles/default/stories.md +15 -0
  20. package/{skills/easysociable-content → content-engine}/starter/profiles/default/voice.md +14 -0
  21. package/content-engine/starter/recommendations/README.md +21 -0
  22. package/content-engine/starter/recommendations/_index.md +21 -0
  23. package/content-engine/starter/recommendations/_template.md +44 -0
  24. package/{skills/easysociable-content → content-engine}/starter/runs/_template/brief.md +1 -1
  25. package/{skills/easysociable-content → content-engine}/starter/runs/_template/pack.md +15 -7
  26. package/{skills/easysociable-content → content-engine}/starter/runs/_template/packet.md +6 -0
  27. package/{skills/easysociable-content → content-engine}/starter/swipe/_template.md +3 -1
  28. package/content-engine/starter/topics/README.md +21 -0
  29. package/{skills/easysociable-content → content-engine}/starter/topics/_index.md +12 -5
  30. package/content-engine/starter/topics/_template-item.md +103 -0
  31. package/{skills/easysociable-content → content-engine}/starter/topics/scoring.md +55 -4
  32. package/content-engine/workbench/__pycache__/build.cpython-310.pyc +0 -0
  33. package/{skills/easysociable-content → content-engine}/workbench/build.py +306 -97
  34. package/{skills/easysociable-content → content-engine}/workbench/serve.py +0 -0
  35. package/{skills/easysociable-content → content-engine}/workbench/template.html +173 -27
  36. package/dist/easysociable.js +629 -142
  37. package/dist/easysociable.js.map +1 -1
  38. package/package.json +15 -15
  39. package/skills/ONBOARDING.md +21 -18
  40. package/skills/easysociable-content/SKILL.md +104 -98
  41. package/skills/easysociable-content/workflows/INTERVIEW.md +70 -0
  42. package/skills/easysociable-content/workflows/NEEDS.md +82 -0
  43. package/skills/easysociable-slideshow/SKILL.md +79 -44
  44. package/skills/easysociable-slideshow/references/ARC.md +44 -0
  45. package/skills/easysociable-slideshow/references/CONTENT_PACK.md +34 -6
  46. package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +24 -5
  47. package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +3 -0
  48. package/skills/easysociable-template/SKILL.md +29 -30
  49. package/skills/easysociable-template/references/CATALOG_METADATA.md +23 -20
  50. package/skills/easysociable-template/references/DESIGN_V2_1.md +53 -2
  51. package/skills/easysociable-template/references/GATEWAY.md +7 -2
  52. package/skills/easysociable-template/references/PLATFORM_SPECS.md +11 -3
  53. package/skills/easysociable-template/references/THEME_TOKENS.md +1 -1
  54. package/skills/easysociable-template/references/fixtures/image-reference.design-plan.json +74 -0
  55. package/skills/easysociable-template/references/fixtures/image-reference.visual-qa.json +28 -0
  56. package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +0 -0
  57. package/skills/easysociable-template/scripts/validate-design-v2.mjs +97 -0
  58. package/skills/easysociable-template/workflows/ASSET_PLAN.md +2 -1
  59. package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +4 -4
  60. package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +66 -16
  61. package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +28 -15
  62. package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +4 -3
  63. package/skills/easysociable-template/workflows/FILL_AND_RENDER.md +4 -83
  64. package/skills/easysociable-template/workflows/MULTI_PLATFORM_FAMILY.md +81 -0
  65. package/skills/easysociable-template/workflows/OUT_OF_SCOPE.md +3 -2
  66. package/skills/easysociable-template/workflows/PUBLISH_FROM_DRAFT.md +1 -1
  67. package/skills/easysociable-template/workflows/VISUAL_QA.md +10 -0
  68. package/skills/easysociable-content/INSTALL.md +0 -60
  69. package/skills/easysociable-content/platforms/claude.md +0 -4
  70. package/skills/easysociable-content/platforms/codex.md +0 -4
  71. package/skills/easysociable-content/platforms/hermes.md +0 -4
  72. package/skills/easysociable-content/platforms/openclaw.md +0 -4
  73. package/skills/easysociable-content/references/CLI.md +0 -40
  74. package/skills/easysociable-content/references/CONTRACT_SYNC.md +0 -42
  75. package/skills/easysociable-content/references/MCP.md +0 -15
  76. package/skills/easysociable-content/references/PAGE_PACK.md +0 -129
  77. package/skills/easysociable-content/references/PLATFORM_GUIDE.md +0 -36
  78. package/skills/easysociable-content/references/RUN_LAYOUT.md +0 -73
  79. package/skills/easysociable-content/references/TROUBLESHOOTING.md +0 -13
  80. package/skills/easysociable-content/references/VAULT.md +0 -40
  81. package/skills/easysociable-content/references/VOICE.md +0 -16
  82. package/skills/easysociable-content/scripts/package-skill.mjs +0 -49
  83. package/skills/easysociable-content/scripts/setup.mjs +0 -200
  84. package/skills/easysociable-content/scripts/setup.test.mjs +0 -82
  85. package/skills/easysociable-content/starter/discovery/README.md +0 -18
  86. package/skills/easysociable-content/starter/discovery/_index.md +0 -27
  87. package/skills/easysociable-content/starter/discovery/_template.md +0 -41
  88. package/skills/easysociable-content/starter/profiles/_index.md +0 -13
  89. package/skills/easysociable-content/starter/topics/README.md +0 -25
  90. package/skills/easysociable-content/starter/topics/WATCHLIST.md +0 -65
  91. package/skills/easysociable-content/starter/topics/_template-item.md +0 -90
  92. package/skills/easysociable-content/starter/topics/watchlists/README.md +0 -10
  93. package/skills/easysociable-content/starter/topics/watchlists/_shared.md +0 -14
  94. package/skills/easysociable-content/starter/topics/watchlists/default.md +0 -6
  95. package/skills/easysociable-content/workflows/ANALYSIS_AND_COVERAGE.md +0 -17
  96. package/skills/easysociable-content/workflows/CONTENT_EXPORT.md +0 -24
  97. package/skills/easysociable-content/workflows/GETTING_STARTED.md +0 -40
  98. package/skills/easysociable-content/workflows/MCP_FIRST.md +0 -5
  99. package/skills/easysociable-content/workflows/OUT_OF_SCOPE.md +0 -18
  100. package/skills/easysociable-content/workflows/PACK_AUTHORING.md +0 -42
  101. package/skills/easysociable-content/workflows/SWIPE_CAPTURE.md +0 -18
  102. package/skills/easysociable-content/workflows/TOPIC_DRAFT.md +0 -29
  103. package/skills/easysociable-content/workflows/WORKING_DRAFT.md +0 -19
  104. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/draft.md +0 -0
  105. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/idea.md +0 -0
  106. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
  107. /package/{skills/easysociable-content → content-engine}/scripts/contracts.mjs +0 -0
  108. /package/{skills/easysociable-content → content-engine}/scripts/export-contracts.mjs +0 -0
  109. /package/{skills/easysociable-content → content-engine}/scripts/fixture.test.mjs +0 -0
  110. /package/{skills/easysociable-content → content-engine}/scripts/validate-export.mjs +0 -0
  111. /package/{skills/easysociable-content → content-engine}/scripts/validate-pack.mjs +0 -0
  112. /package/{skills/easysociable-content → content-engine}/scripts/validate-run.mjs +0 -0
  113. /package/{skills/easysociable-content → content-engine}/scripts/validate.test.mjs +0 -0
  114. /package/{skills/easysociable-content → content-engine}/starter/accounts/README.md +0 -0
  115. /package/{skills/easysociable-content → content-engine}/starter/accounts/_index.md +0 -0
  116. /package/{skills/easysociable-content → content-engine}/starter/accounts/overrides/README.md +0 -0
  117. /package/{skills/easysociable-content → content-engine}/starter/exports/README.md +0 -0
  118. /package/{skills/easysociable-content → content-engine}/starter/inbox/README.md +0 -0
  119. /package/{skills/easysociable-content → content-engine}/starter/inbox/_index.md +0 -0
  120. /package/{skills/easysociable-content → content-engine}/starter/inbox/entries/README.md +0 -0
  121. /package/{skills/easysociable-content → content-engine}/starter/platforms/README.md +0 -0
  122. /package/{skills/easysociable-content → content-engine}/starter/platforms/ig.md +0 -0
  123. /package/{skills/easysociable-content → content-engine}/starter/platforms/instagram.md +0 -0
  124. /package/{skills/easysociable-content → content-engine}/starter/platforms/linkedin.md +0 -0
  125. /package/{skills/easysociable-content → content-engine}/starter/platforms/threads.md +0 -0
  126. /package/{skills/easysociable-content → content-engine}/starter/platforms/tiktok.md +0 -0
  127. /package/{skills/easysociable-content → content-engine}/starter/platforms/x.md +0 -0
  128. /package/{skills/easysociable-content → content-engine}/starter/platforms/xiaohongshu.md +0 -0
  129. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/audience.md +0 -0
  130. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/pillars.md +0 -0
  131. /package/{skills/easysociable-content → content-engine}/starter/published/_index.md +0 -0
  132. /package/{skills/easysociable-content → content-engine}/starter/raw/README.md +0 -0
  133. /package/{skills/easysociable-content → content-engine}/starter/raw/_index.md +0 -0
  134. /package/{skills/easysociable-content → content-engine}/starter/runs/README.md +0 -0
  135. /package/{skills/easysociable-content → content-engine}/starter/runs/_index.md +0 -0
  136. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/draft.md +0 -0
  137. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/editor.md +0 -0
  138. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/feedback.md +0 -0
  139. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/idea.md +0 -0
  140. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/rubric.md +0 -0
  141. /package/{skills/easysociable-content → content-engine}/starter/swipe/_index.md +0 -0
  142. /package/{skills/easysociable-content → content-engine}/starter/topics/items/README.md +0 -0
  143. /package/{skills/easysociable-content → content-engine}/starter/wiki/README.md +0 -0
  144. /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_index.md +0 -0
  145. /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_template.md +0 -0
  146. /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_index.md +0 -0
  147. /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_template.md +0 -0
  148. /package/{skills/easysociable-content → content-engine}/starter/workbench/README.md +0 -0
@@ -2,83 +2,118 @@
2
2
  name: easysociable-slideshow
3
3
  description: >
4
4
  Create, list, update and review durable multi-page Slideshow Runs for
5
- EasySociable from a local Obsidian Content Pack. Use the unified
6
- `easysociable` CLI or MCP, open Studio for preview, and perform final PNG
7
- rendering only after confirmation. Runs remain in the owner dashboard until
8
- archive/trash. There is no Slideshow Template product, UGC publishing,
9
- social posting or separate Slideshow CLI/MCP in V1.
5
+ EasySociable from a local Content Pack. Name the argument (arc) first, then
6
+ pick a Page Template per page by platform, canvas, slotSummary and density —
7
+ never default Cover→Point→Steps→Recap→CTA. Page 1 must be a cover or hook
8
+ class template; those templates must not appear on later pages. Use the
9
+ unified `easysociable` CLI or MCP, open Studio to preview and edit, then
10
+ ask the user to click Download for a PNG ZIP. CLI/MCP must not call
11
+ render/export or create_render_job for final pixels. Runs remain in the
12
+ owner dashboard until archive or hard delete.
10
13
  ---
11
14
 
12
15
  # EasySociable Slideshow Skill
13
16
 
14
- A Slideshow Run is a temporary composition of explicit single-page Templates.
17
+ A Slideshow Run is a composition of explicit single-page Templates.
15
18
  It is not a reusable Carousel/Deck Template and it is not a public post.
19
+ Page order is the argument of **this pack**, not a catalog recipe.
16
20
 
17
21
  ## Rules
18
22
 
19
- 1. Read a local `content-pack.v1` from the Obsidian Content Engine.
23
+ 1. Read a local `content-pack.v1` from the Content Engine.
20
24
  2. Use the unified `easysociable` CLI or the unified MCP server. All hosted
21
25
  calls go through Gateway; never call Directus, R2, Stripe or private services.
22
- 3. The Agent must choose a Profile, one Theme and an explicit Page Template for
23
- every page. The server never silently chooses or replaces a Page Template.
24
- 4. A Run has 1–20 pages, one supported platform (`tiktok`, `instagram`,
25
- `linkedin` or `threads`) and one Profile/Theme across all pages.
26
- 5. Topology is fixed after creation: no add, copy, delete, reorder or template
26
+ 3. Choose a Brand (or Profile/Theme) and an explicit Page Template for every
27
+ page. The server never silently chooses or replaces a Page Template.
28
+ Select by **platform + canvas + slotSummary + density**. `role` is a weak
29
+ retrieval tag, not sequence position.
30
+ 4. **Cover / hook placement (hard):** a template is cover/hook class when
31
+ `supportedRoles` includes `cover` or `hook`. `pages[0]` must use one.
32
+ Cover/hook class templates must not appear on any later page. Later pages
33
+ use metric / quote / compare / value / steps / cta / etc. Do not put a
34
+ Point or metric-only template on page 1 to “open with a number” — pick a
35
+ cover or hook template whose slots fit the opening copy.
36
+ 5. A Run has up to 8 pages on Free and 20 on paid, one supported platform
37
+ (`tiktok`, `instagram`, `linkedin` or `threads`) and one Brand across pages.
38
+ 6. Topology is fixed after creation: no add, copy, delete, reorder or template
27
39
  switch. Page-instance slot/layout/type/style/decoration edits remain allowed
28
40
  in Studio.
29
- 6. Studio is preview-only. It has no final download, publish, unpublish, UGC,
30
- SEO/GEO or social-posting action.
31
- 7. Before creating a new Run for an existing content intent, list/find prior Runs
32
- by `contentSlug` and update the same Run when possible.
33
- 8. Preview is free but rate/concurrency limited. Final rendering is PNG-only,
34
- uses one atomic reservation for all pages and charges only when every page
35
- succeeds.
41
+ 7. Final pixels leave the product only from **Studio Download** (browser PNG
42
+ ZIP). Do not call `slideshows render`, `slideshows export`, `renders create`
43
+ or MCP `render_slideshow_run` / `create_render_job`. Those return
44
+ `HEADLESS_RENDER_DISABLED`.
45
+ 8. Before creating a new Run, list/find prior Runs by `contentSlug`. **Update**
46
+ the same Run only when page count, pageTemplateIds, and intended sequence
47
+ still match. A different arc or template set is a **new Run** — never PATCH
48
+ new copy into a locked Cover-Point-Steps-Recap-CTA skeleton.
49
+ 8b. **Knowledge hard gate (every create, not only the first Run):** before
50
+ `create_run` / `slideshows create`, read Identity (Role / What I build /
51
+ Point of view — no `(fill)`, non-empty) and `boundaries.md` (Not covering
52
+ and Never claim non-empty), or run
53
+ `easysociable engine validate --run <run-dir> --require-knowledge`.
54
+ If `needs/` exists, `needs/_index.md` ≥ 3 `N-` rows; if `needs/` is absent, skip that count. Fail → hand back to
55
+ **easysociable-content** / refuse create; list missing files. Do not add
56
+ Gateway or MCP params. User must say **强制继续** / **force continue**
57
+ to call Gateway.
58
+ 9. Preview is free. Free Download is 3 successful ZIPs per month and one
59
+ platform. Paid Download is unmetered.
60
+ 10. **Forbidden default:** do not assemble Cover → Point → Steps → Recap → CTA
61
+ because those are P0 family names. Name the arc first
62
+ (`references/ARC.md`). Page count follows the argument, not the catalog.
63
+ Rule 4 still applies: page 1 is cover/hook class, not “whatever family
64
+ is named Cover”.
36
65
 
37
66
  ## Workflow
38
67
 
39
- 1. Validate the Pack and platform/page count.
40
- 2. Resolve or create the user's Profile/Theme through the unified CLI/MCP.
41
- 3. Select a compatible published Page Template for every page.
42
- 4. List existing Runs when the Pack has a stable content slug:
68
+ 1. Write one arc line (`references/ARC.md`). Do not skip this for a five-family fill-in.
69
+ 2. Validate the Pack and platform/page count.
70
+ 3. Resolve or create the user's Brand through the unified CLI/MCP.
71
+ 4. List the published catalog. `pages[0]` must be cover/hook class
72
+ (`supportedRoles` includes `cover` or `hook`). Remaining pages: platform +
73
+ canvas + slot counts + density — not `beat name == family name`. Never
74
+ place a cover/hook class template after page 1.
75
+ 5. List existing Runs when the Pack has a stable content slug:
43
76
 
44
77
  ```bash
45
78
  easysociable slideshows list --content-slug my-post --json
46
79
  ```
47
80
 
48
- 5. Create or update:
81
+ 6. **Hard gate, then** create (new arc/templates) or update (same topology,
82
+ slot copy only). Check files or:
49
83
 
50
84
  ```bash
51
- easysociable slideshows create --file ./pack.json --json
85
+ easysociable engine validate --run <run-dir> --require-pack --require-knowledge
52
86
  ```
53
87
 
54
- 6. Open the returned `studioUrl` and inspect every page.
55
- 7. Save Studio edits and wait for the saved revision.
56
- 8. After explicit confirmation, call:
88
+ Fail → refuse; return to **easysociable-content**. **强制继续** / **force continue**
89
+ is the only override (conversational — not a CLI flag). Then:
57
90
 
58
91
  ```bash
59
- easysociable slideshows render --id run_xxx --idempotency-key run_xxx-final-1 --json
60
- easysociable slideshows export --id run_xxx --output ./exports/run_xxx/tiktok --json
92
+ easysociable slideshows create --file ./pack.json --json
61
93
  ```
62
94
 
63
- Hosted finals use one Run capture session + one Imagine deck screenshot
64
- (single browser load, N page PNGs). Require Studio Save (`layout.studioJson`
65
- + `themeSnapshot`) before render. Single-page Template jobs still use
66
- `renders create|wait|export`.
67
-
68
- 8. Verify checksums and the reconstruction `manifest.json` in the Obsidian
69
- Run export. The export is the local final deliverable; cloud artifacts expire
70
- after 24 hours while the Run remains listed for the owner.
95
+ 7. Open the returned `studioUrl` and inspect every page.
96
+ 8. Save Studio edits and wait for the saved revision.
97
+ 9. After explicit user confirmation, tell them to click **Download** in Studio.
98
+ Do not render or export from CLI/MCP.
71
99
 
72
100
  ## Failure handling
73
101
 
102
+ - If the knowledge hard gate fails, do not create the Run. Hand back to
103
+ easysociable-content and list missing files unless the user said
104
+ **强制继续** / **force continue**.
105
+ - If page 1 is not cover/hook class, or a later page uses a cover/hook
106
+ class template, stop and rebuild the Pack. Do not create the Run.
74
107
  - If a page template, slot or image is invalid, return the structured Gateway
75
108
  error to the Agent; do not substitute another template.
76
- - If any final page fails, there is no partial final set and no page charge.
77
- - Retry the same final request with the same idempotency key to reuse the Job.
78
- - If a Run was trashed, create a new Run from the Pack.
109
+ - If Download is exhausted (`USAGE_LIMIT_REACHED`) or past due, tell the user
110
+ to upgrade or update billing.
111
+ - If a Run was deleted, or Gateway returns `RUN_TOPOLOGY_LOCKED` because the
112
+ pack changed sequence/templates, create a new Run from the Pack.
79
113
 
80
114
  ## Handoff boundary
81
115
 
82
- The Content Skill owns semantic copy and Pack creation. The Template Skill owns
83
- single-page authoring and fill-slots. This Skill only composes explicit page
84
- instances and coordinates preview/final render.
116
+ The Content Engine owns semantic copy, Pack creation, and the arc.
117
+ The Template Skill owns single-page authoring and publish.
118
+ This Skill composes explicit page instances and opens Studio for review/Download.
119
+ It does not own a product-level story recipe.
@@ -0,0 +1,44 @@
1
+ # Arc (argument, then pages)
2
+
3
+ A Slideshow Run is an argument that only works if the viewer turns the page.
4
+ Page order is a property of **this piece of content**, not of the catalog.
5
+
6
+ Do **not** invent a product-level `arc` field, Deck SKU, or
7
+ `pageSequence: [cover, point, steps, recap, cta]`.
8
+
9
+ ## Forbidden default
10
+
11
+ Never default a Pack to Cover → Point → Steps → Recap → CTA
12
+ because those are P0 family names. That sequence is one possible recipe, not
13
+ the product shape. Page count follows the argument (TikTok often 4–8), not
14
+ the number of P0 families.
15
+
16
+ ## Before pages
17
+
18
+ Write one arc line, then map each beat to slots.
19
+
20
+ **Page 1 is cover/hook class.** A template is cover/hook class when
21
+ `supportedRoles` includes `cover` or `hook`. That class belongs only on
22
+ `pages[0]`. Opening copy may still be a cost, quote, or compare *line* —
23
+ fill a cover or hook template whose `slotSummary` fits. Do not open with a
24
+ metric/point/quote template.
25
+
26
+ Later pages pick by slot shape (metric, quote, compare, value, steps, cta).
27
+
28
+ ## Recipes (swipe formulas, not system enums)
29
+
30
+ Pick one, or name a new one-liner. Do not expand this into an official catalog.
31
+
32
+ | Recipe | Beats |
33
+ |---|---|
34
+ | cost-mechanism | cost → mechanism → method → close → action |
35
+ | listicle | hook + N items + CTA |
36
+ | mistakes | hook + errors + fix + CTA |
37
+ | claim-proof | claim → evidence → implication → CTA |
38
+ | compare | old way / new way / why / CTA |
39
+
40
+ ## After create
41
+
42
+ Topology is locked. Wrong arc or wrong templates → **new Run**.
43
+ Do not PATCH copy into a locked Cover-Point-Steps-Recap-CTA skeleton.
44
+ `contentSlug` finds prior drafts; it does not keep a bad sequence alive.
@@ -1,5 +1,36 @@
1
1
  # ContentPack v1
2
2
 
3
+ Page `role` is a **weak retrieval tag** (layout-ish), not sequence position.
4
+ `pageTemplateId` is the explicit published single-page template chosen by the
5
+ Agent. `slots` are public values only. Do not add a `deck_template_id`,
6
+ `bindingMap`, AST, ContentDocument, or product `arc` / `pageSequence`.
7
+
8
+ The Gateway validates each `role` against the closed enum and that slots exist.
9
+ It does not require Cover → Point → Steps → Recap → CTA.
10
+
11
+ This skill **does** require page 1 to be cover/hook class (`supportedRoles`
12
+ includes `cover` or `hook`) and forbids that class on later pages.
13
+
14
+ ## Example: cost → mechanism (TikTok)
15
+
16
+ Opening beat is cost; page 1 is still a hook-class template.
17
+
18
+ ```json
19
+ {
20
+ "schemaVersion": "content-pack.v1",
21
+ "platform": "tiktok",
22
+ "title": "Stop briefing a blank canvas",
23
+ "pages": [
24
+ { "role": "hook", "pageTemplateId": "tpl_hook_001", "slots": { "text_0": "You finish the copy. Then you start over.", "text_1": "The design file kept none of the argument." } },
25
+ { "role": "point", "pageTemplateId": "tpl_stack_001", "slots": { "text_0": "Roles, Brand, Layouts persist" } },
26
+ { "role": "steps", "pageTemplateId": "tpl_stair_001", "slots": { "text_0": "Use them in that order" } },
27
+ { "role": "cta", "pageTemplateId": "tpl_close_001", "slots": { "text_0": "Don't brief a blank canvas" } }
28
+ ]
29
+ }
30
+ ```
31
+
32
+ ## Example: hook → value → cta
33
+
3
34
  ```json
4
35
  {
5
36
  "schemaVersion": "content-pack.v1",
@@ -13,12 +44,9 @@
13
44
  }
14
45
  ```
15
46
 
16
- Page `role` is semantic and `pageTemplateId` is the explicit published
17
- single-page template chosen by the Agent. `slots` are public values only. Do not
18
- add a `deck_template_id`, `bindingMap`, AST or ContentDocument.
19
-
20
- The Gateway validates that each selected template supports the page role and
21
- belongs to the account-visible catalog. It never silently replaces a selection.
47
+ Pick templates by **platform + canvas + slotSummary + density**, not by matching
48
+ the beat name to a family named Cover / Point / Steps / Recap / CTA. Page 1
49
+ must still be cover/hook class.
22
50
 
23
51
  The renderer accepts any supported page count within the platform cap. A newly
24
52
  published Page Template can be selected in a new Run without creating a
@@ -1,7 +1,26 @@
1
1
  # Create Run
2
2
 
3
- 1. Build `content-pack.v1` from the agent's semantic outline.
4
- 2. Check platform hardMin/hardMax.
5
- 3. Call `create_run` or `run create` through Gateway.
6
- 4. Save `runId`, `studioUrl`, and `status=draft`.
7
- 5. Do not call a Deck API or create a carousel template.
3
+ 1. Write one arc line (`references/ARC.md`). Forbidden default:
4
+ Cover → Point → Steps → Recap → CTA.
5
+ 2. Build `content-pack.v1` from that argument. Page count follows the beats
6
+ (TikTok often 4–8), not the number of P0 families.
7
+ 3. Check platform hardMin/hardMax.
8
+ 4. List published Page Templates. `pages[0]` must be cover/hook class
9
+ (`supportedRoles` includes `cover` or `hook`). Do not use that class on
10
+ later pages. Remaining pages: platform + canvas + `slotSummary` + density.
11
+ `role` is a weak tag.
12
+ 5. If `contentSlug` already has a Run: update only when topology matches
13
+ (same page count and `pageTemplateId`s). Otherwise create a new Run.
14
+ 6. **Before** `create_run` / `slideshows create` (every create, not only the
15
+ first Run): check the knowledge hard gate — Identity Role / What I build /
16
+ Point of view have no `(fill)` and are non-empty; `boundaries.md` exists
17
+ with Not covering and Never claim non-empty; if `needs/` exists, ≥3 `N-`
18
+ rows, else skip. Read the files or run
19
+ `easysociable engine validate --run <run-dir> --require-knowledge`.
20
+ Fail → hand back to **easysociable-content** / refuse create; list missing
21
+ files. User must say **强制继续** / **force continue** to call Gateway.
22
+ No new Gateway or MCP params.
23
+ 7. Call `create_run` / `slideshows create` through Gateway.
24
+ 8. Save `runId`, `studioUrl`, and `status=draft`.
25
+ 9. Do not call a Deck API, create a carousel template, or send a product
26
+ `pageSequence` / `arc` field.
@@ -1,6 +1,9 @@
1
1
  # Out of scope
2
2
 
3
3
  - DeckTemplate creation, `list_decks`, `CREATE_DECK`, or `BIND_P0_DECKS`.
4
+ - Product-level `arc` / Deck `pageSequence` SKUs (ADR-0026). Structure stays in the Content Pack.
5
+ - Defaulting every Run to Cover → Point → Steps → Recap → CTA.
6
+ - Cover/hook class templates on page 2+ (they belong on `pages[0]` only).
4
7
  - ContentDocument as a render input (ADR-0021).
5
8
  - Client-side RenderPlan or AST compilation.
6
9
  - Full cross-platform Page Template coverage and ad-placement variants.
@@ -2,19 +2,15 @@
2
2
  name: easysociable-template
3
3
  description: >
4
4
  Create single-page social image templates for EasySociable via the unified
5
- Template MCP or `easysociable` CLI, and fill published template slots to Hosted Render
6
- (get_template → slots → create_render_job). Use when the user wants to author a
7
- page template from a reference image or text brief, write a shared visual design
8
- philosophy, explore 2–3 professional layout concepts as spatial expressions of that
9
- philosophy, plan or generate visual assets, co-create/reuse a Theme with brand-hex
10
- palette generation, choose a Surface (flat / Gateway gradient catalog / host
11
- Unsplash·Pexels·Pinterest photo), pull icons via Template Gateway
12
- search_icons/get_icon (internal Icon Catalog), run
13
- screenshot-based visual QA, attach catalog metadata (platforms including
14
- x/linkedin/threads, pageRoles, archetypes, density, slotSummary), open Authoring
15
- Studio, publish a single-page template, or render a published template by filling
16
- public slots. Do not use for multi-slide slideshow composition, ContentDocument as
17
- render input, local content library, or carousel packs.
5
+ Template MCP or `easysociable` CLI. Default create path is a Layout Family:
6
+ one master canvas plus derived multi-platform variants (e.g. XHS 3:4, IG/Threads 4:5,
7
+ TikTok 9:16, LinkedIn 1:1) with hand-tuned layouts per preset. Use when the user wants
8
+ to author a page template from a reference image or text brief, write a shared visual
9
+ design philosophy, explore layout concepts, co-create Theme/preview tokens, pull icons
10
+ via search_icons/get_icon, open Authoring Studio, or publish. Do not use for
11
+ fill-slots hosted PNG jobs (`create_render_job` is retired), multi-slide slideshow
12
+ composition, ContentDocument as render input, or carousel packs. Customer PNG packs
13
+ come from Slideshow Studio Download.
18
14
  ---
19
15
 
20
16
  # EasySociable Template Skill
@@ -23,12 +19,12 @@ The public entry points are the unified `easysociable` CLI and one unified MCP
23
19
  server. Do not install or invoke `easysociable-template`, `easysociable-slideshow`,
24
20
  `easysociable-content`, or a separate Content/Slideshow MCP in V1.
25
21
 
26
- **This skill owns two single-page paths:**
22
+ **This skill owns template authoring:**
27
23
 
28
- 1. **Author** templates (Studio + Publish).
29
- 2. **Fill slots → Hosted Render** for a published PageTemplate (`workflows/FILL_AND_RENDER.md`).
24
+ 1. **Author** templates as a **Layout Family** (master + multi-platform variants) → Studio + Publish (`workflows/MULTI_PLATFORM_FAMILY.md`).
25
+ 2. Fill-slots Hosted Render (`create_render_job`) is **retired** as a paid delivery path. Customer PNG packs come from Slideshow Studio Download.
30
26
 
31
- It is a template factory **and** the Agent surface for single-page fill-slots out图 (ADR-0021). It is **not** a multi-slide slideshow compositor.
27
+ It is a template factory. It is **not** a multi-slide slideshow compositor and it is **not** a PNG API.
32
28
 
33
29
  Every published page must carry **P0 catalog metadata** so Agents can filter and fill templates (`references/CATALOG_METADATA.md`).
34
30
 
@@ -45,22 +41,23 @@ Out of scope (hand off):
45
41
  2. Submit only public Gateway DTOs. Never invent or request private Safe AST / Binding Map / RenderPlan.
46
42
  3. Do not start Local Runtime, read content library SQLite, or call Content MCP/CLI for Template work.
47
43
  4. Catalog and create targets are **single-page** only. Never treat site Carousel packs as Agent templates.
48
- 5. After `create` / `createDraft`, the primary authoring path is `authoringStudioUrl` (`/authoring/{draftId}`). Always send the handoff message in `AUTHORING_STUDIO.md` (edit → **Save** → tell Agent to publish). Do not require a Hosted Preview Job for interactive authoring.
44
+ 5. After `create` / `createDraft`, the primary authoring path is `authoringStudioUrl` (`/authoring/{draftId}`). **Default:** run `workflows/MULTI_PLATFORM_FAMILY.md` (derive + hand-tune variants) before handoff unless the user asked for one platform only. Always send the handoff in `AUTHORING_STUDIO.md` (edit → **Save** → tell Agent to publish). Do not require a Hosted Preview Job for interactive authoring.
49
45
  6. Studio has **Save only** — no Publish button. Publish only after the user saves and **explicitly** asks to publish; then run `workflows/PUBLISH_FROM_DRAFT.md`.
50
- 7. **Do not Publish without complete P0 selection metadata** (`CATALOG_METADATA.md`). Gateway enforces this.
51
- 8. Theme: reuse `themeId` **or** co-create full `ThemeTokens`. Colors/fonts belong in Theme; page nodes use semantic `--es-*` tokens where possible.
46
+ 7. **Do not Publish without complete P0 selection metadata** (`CATALOG_METADATA.md`). Gateway enforces this. Each family variant carries its own `platforms` / `canvasPreset` / `canvas`.
47
+ 8. Theme/preview: co-create `ThemeTokens` on draft create (`theme.create`) → Family `preview_tokens` (ADR-0033). No authoring TemplateTheme row. Colors/fonts via semantic `--es-*` on page nodes.
52
48
  9. Layout model is **absolute positioning** on a **flat canvas tree** (see prior authoring rules / `AUTHORING_SOURCE.md`).
53
49
  10. **Runtime layout CSS:** put exact geometry in JSX inline `style={{...}}`. Never depend on Tailwind arbitrary-value classes for geometry.
54
50
  11. Run `scripts/validate-authoring-source.mjs` before every create/update.
55
- 12. `supportedRoles` uses closed **pageRoles**; `platforms` is a multi-select array.
51
+ 12. `supportedRoles` uses closed **pageRoles** as a **weak retrieval tag**, not sequence position. Family `name` describes **layout** (Poster / Stack / Count / Stair / Close), not a narrative beat. `platforms` is a multi-select array.
56
52
  13. Canvas sizes must follow `references/PLATFORM_SPECS.md`.
57
53
  14. **Text-only V2.1 authoring:** `DESIGN_BRIEF` → Philosophy → Concepts → assets/surface → author → Visual QA.
58
- 15. **Visual QA** before Studio handoff when authoring.
59
- 16. Prefer **reusable/brand assets**, Gateway gradient recipes, and catalog icons for deterministic visuals. Geometric chrome (hairlines, rails, discs) may use plain CSS shapes — **not** as a substitute for named icons.
54
+ 15. **Visual QA** before Studio handoff when authoring. For `image_reference`, QA **must** side-by-side compare Studio canvas to the reference (`VISUAL_QA.md` § Reference compare).
55
+ 16. Prefer **reusable/brand assets**, Gateway gradient recipes, and catalog icons for deterministic visuals. Geometric chrome (hairlines, rails, discs) may use plain CSS shapes — **not** as a substitute for named icons **or** for pictorial regions on a reference-image rebuild.
56
+ 16b. **Reference image → template (hard):** follow `workflows/AUTHORING_FROM_IMAGE.md` as SoT. **Read the reference with a vision tool**, write `referenceSpec` + `referenceImageInventory` into `design-plan.json`, and place pictorial regions as **`image` slots** (empty frames matching the boxes). `validate-design-v2.mjs` rejects `image_reference` plans missing those fields or using `css_svg` stand-ins for inventoried pictures. Do not mood-board a different layout.
60
57
  17. Preserve `draftId`, `templateId`, `themeId`, `jobId`, `authoringStudioUrl`, and `previewUrl` across steps.
61
58
  18. **Theme / Surface confirmation gates** unchanged for authoring (see `PALETTE_REVIEW`, `SURFACE_REVIEW`).
62
- 19. **Fill-slots render (primary consumption path):** `get_template` → fill `slots[]` → `create_render_job({ templateId, slots, output })` → poll Job/Manifest. Image slots always use an account-owned `imageId` from the existing Gateway → R2 + Directus `Image` flow. Never pass a third-party URL, local path, transient `renderAssetId`, ContentDocument or `contentDocumentHash`. See `workflows/FILL_AND_RENDER.md`.
63
- 20. **Hosted Capture first:** default delivery is Hosted Artifact. Local capture only when the error includes `fallback.capture` — follow `workflows/FILL_AND_RENDER.md` §5 (CLI `capture` or same-URL Playwright). Do not use page html-to-image buttons as the Agent primary path.
59
+ 19. **Consumption is Slideshow Studio Download**, not fill-slots Hosted Render. `create_render_job` / CLI `renders create` return `HEADLESS_RENDER_DISABLED`. See `workflows/FILL_AND_RENDER.md`.
60
+ 20. **Do not** treat Hosted Capture or local html-to-image as the Agent primary PNG path.
64
61
  21. **Icons (hard rule — no shortcuts):**
65
62
  - Any **recognizable icon** (arrows, chevrons, checkmarks, social glyphs, UI symbols, “next page” cues, etc.) **MUST** use Gateway Icon Catalog:
66
63
  `search_icons` / CLI `icons search` → show ≤8 candidates → **user confirm** (or explicit “你定 / 用第 N 个”) → `get_icon` / CLI `icons get --idempotency-key …` → embed returned **`canonicalSvg`** and record **`iconAssetId`** / `iconId` on the decoration node.
@@ -79,11 +76,12 @@ easysociable auth status --json
79
76
 
80
77
  | User intent | Workflow |
81
78
  |---|---|
82
- | Text description → template | `DESIGN_BRIEF.md` → … → `AUTHORING_STUDIO.md` |
83
- | Reference image → template | `AUTHORING_FROM_IMAGE.md` → … → `AUTHORING_STUDIO.md` |
79
+ | Text description → template (incl. multi-platform) | `DESIGN_BRIEF.md` → … → `AUTHORING_STUDIO.md` → **`MULTI_PLATFORM_FAMILY.md`** (derive + hand-tune) |
80
+ | Reference image → template | `AUTHORING_FROM_IMAGE.md` → … → `AUTHORING_STUDIO.md` → **`MULTI_PLATFORM_FAMILY.md`** + reference-compare QA on master |
81
+ | “只要某一个平台” | Same authoring path; skip derive / only named presets in `MULTI_PLATFORM_FAMILY.md` |
84
82
  | Need gradient / photo surface / icons only | `SURFACE_REVIEW.md` |
85
83
  | **Add / change an icon** (arrow, chevron, check, …) | **MUST** `SURFACE_REVIEW.md` § Icons — search → confirm → get_icon. **Do not** hand-draw SVG paths. |
86
- | Already have authoring payload / continue Studio | `workflows/AUTHORING_STUDIO.md` |
84
+ | Already have authoring payload / continue Studio | `workflows/AUTHORING_STUDIO.md` (+ family derive if variants still missing) |
87
85
  | User says publish / 发布该模板 (after Save) | `workflows/PUBLISH_FROM_DRAFT.md` |
88
86
  | Browse published single-page templates | `list` / `get_template` + public metadata |
89
87
  | **Fill a published template → PNG/JPEG** | `workflows/FILL_AND_RENDER.md` |
@@ -91,13 +89,14 @@ easysociable auth status --json
91
89
 
92
90
  ## Core model
93
91
 
92
+ - `workflows/MULTI_PLATFORM_FAMILY.md` — **default** multi-platform create (Family + derive + hand-tune)
94
93
  - `references/PLATFORM_SPECS.md`
95
94
  - `references/CATALOG_METADATA.md`
96
95
  - `references/SLOTS.md` — public slot contract for fill-slots render
97
96
  - `references/AUTHORING_SOURCE.md`
98
- - `references/THEME_TOKENS.md`
97
+ - `references/THEME_TOKENS.md` — Family `preview_tokens` (no TemplateTheme)
99
98
  - `references/EXTERNAL_RESOURCES.md`
100
- - `references/GATEWAY.md` — CLI / MCP including `render` / `create_render_job`
99
+ - `references/GATEWAY.md` — CLI / MCP including families derive + `render`
101
100
  - `workflows/FILL_AND_RENDER.md` — get_template → slots → Hosted Render
102
101
  - Authoring V2.1 workflows + validators as before
103
102
 
@@ -5,9 +5,10 @@ Private AST/bindings stay server-side; this document is the **public selection c
5
5
 
6
6
  ## Design choices (locked)
7
7
 
8
- 1. **One closed `pageRoles` set** (stored as `supportedRoles`) — narrative beat + layout kind in one enum. Do not maintain a second parallel taxonomy.
8
+ 1. **One closed `pageRoles` set** (stored as `supportedRoles`) — a **retrieval tag for layout kind**, not page position and not a story recipe. `cover` means poster-like slots, not “must be page 1”. Do not add a parallel `arc` / `pageSequence` taxonomy (ADR-0026).
9
9
  2. **`platforms` is a multi-select array**. Include `generic` when the page fits any platform at that aspect.
10
10
  3. **P0 fields are required to Publish.** P1 should be filled when known; P2 optional.
11
+ 4. **Family `name` describes layout**, not a narrative beat. Prefer Poster / Stack / Count / Stair / Close (plus platform). Do not name families Cover / Point / Steps / Recap / CTA — choosers will glue those five names into one default pack.
11
12
 
12
13
  Max **1–2** `supportedRoles` per page (primary + optional secondary).
13
14
 
@@ -33,25 +34,25 @@ Always also store exact `canvas: { width, height }`. Use `16:9` for X **1200×67
33
34
 
34
35
  ### Page roles (`supportedRoles` / pageRoles) — pick 1–2
35
36
 
36
- | Role | When to use |
37
+ | Role | Layout kind (not sequence position) |
37
38
  |---|---|
38
- | `cover` | Cover / first-frame poster |
39
- | `hook` | Scroll-stop hook (often with cover) |
40
- | `setup` | Setup / problem framing |
41
- | `context` | Background / context |
42
- | `value` | Single takeaway / value page |
39
+ | `cover` | Poster / first-frame-capable layout — may open a run, need not |
40
+ | `hook` | Scroll-stop / short-copy layout |
41
+ | `setup` | Problem-framing layout |
42
+ | `context` | Background / context layout |
43
+ | `value` | Single takeaway layout |
43
44
  | `point` | One sharp point (lighter than value) |
44
45
  | `checklist` | Fixed N text lines (no list binding type) |
45
- | `proof` | Proof / credibility |
46
+ | `proof` | Proof / credibility layout |
46
47
  | `evidence` | Evidence artifacts (data, case) |
47
- | `compare` | Before/after or A/B compare |
48
+ | `compare` | Before/after or A/B layout — valid as page 1 |
48
49
  | `screenshot` | App/web UI screenshot frame |
49
- | `metric` | Big number / KPI / milestone |
50
- | `quote` | Pull quote / testimonial |
51
- | `steps` | Fixed-step howto |
52
- | `cta` | Call to action |
53
- | `follow` | Follow / profile CTA |
54
- | `recap` | Summary / closing recap |
50
+ | `metric` | Big number / KPI — valid as page 1 |
51
+ | `quote` | Pull quote / testimonial — valid as page 1 |
52
+ | `steps` | Fixed-step howto layout |
53
+ | `cta` | Call to action layout |
54
+ | `follow` | Follow / profile CTA layout |
55
+ | `recap` | Summary / closing layout |
55
56
 
56
57
  Legacy-compatible: `cover`, `setup`, `value`, `proof`, `cta` remain valid.
57
58
 
@@ -98,7 +99,7 @@ hero | screenshot | avatar | product
98
99
 
99
100
  | Field | Type | Notes |
100
101
  |---|---|---|
101
- | `name` | string | Human title |
102
+ | `name` | string | Human title — **layout**, not beat (e.g. `P0 Poster TikTok`, not `P0 Cover TikTok`) |
102
103
  | `shortDescription` | string | One sentence for chooser UI |
103
104
  | `platforms` | `Platform[]` | Multi-select; use `generic` when truly cross-platform |
104
105
  | `canvasPreset` | preset enum | Plus exact `canvas` pixels |
@@ -134,11 +135,11 @@ Derived from the slot table in `SLOTS.md`.
134
135
  | `notFor` | string[1..3] | Honest exclusions |
135
136
  | `selectionHints` | string | Short Agent-only hint |
136
137
  | `visualStyle` | enum | Look affinity |
137
- | `defaultThemeId` | string? | Soft preview theme |
138
- | `compatibleThemeIds` | string[]? | Optional |
139
138
  | `locale` | `zh-CN` \| `en` \| `bilingual` | |
140
139
  | `exampleFilledPreviewUrl` | url? | Filled sample beats empty shell |
141
140
 
141
+ Do **not** put Theme FKs (`defaultThemeId`, `compatibleThemeIds`) on published selection metadata (ADR-0033). Runtime look comes from Brand `themeSnapshot`.
142
+
142
143
  ---
143
144
 
144
145
  ## P2 — optional
@@ -189,7 +190,7 @@ Agent must produce a `selection-metadata.json` (or equivalent fields on the draf
189
190
 
190
191
  ```json
191
192
  {
192
- "name": "XHS metric milestone 3:4",
193
+ "name": "XHS Count 3:4",
193
194
  "shortDescription": "大数字涨粉庆祝页,可选头像",
194
195
  "platforms": ["xiaohongshu", "generic"],
195
196
  "canvasPreset": "3:4",
@@ -207,7 +208,7 @@ Agent must produce a `selection-metadata.json` (or equivalent fields on the draf
207
208
  "visualStyle": "swiss",
208
209
  "bestFor": ["涨粉节点", "数据庆祝封面"],
209
210
  "notFor": ["长清单干货", "多步教程"],
210
- "selectionHints": "Prefer when slide.role is metric or cover and a single KPI dominates.",
211
+ "selectionHints": "Prefer when slotSummary has one number + short text (KPI / cost hook), any page index.",
211
212
  "locale": "zh-CN"
212
213
  }
213
214
  ```
@@ -219,3 +220,5 @@ Agent must produce a `selection-metadata.json` (or equivalent fields on the draf
219
220
  - Checklist without `fixedItemCount`
220
221
  - `requiresImage: true` but `imageRoles` empty
221
222
  - Platforms empty or inventing values outside the enum
223
+ - Naming a family Cover / Point / Steps / Recap / CTA so choosers assemble that sequence
224
+ - Treating `supportedRoles` as “this page must appear at this beat in every Run”
@@ -122,7 +122,8 @@ Rules:
122
122
 
123
123
  - `text_brief` requires 2–3 concepts; `image_reference` permits one.
124
124
  - `text_brief` requires root `philosophy` with non-empty `movementName`, `space`, `color`, `rhythm`, `composition`, `typographyAccent`, and `craftBar`.
125
- - `image_reference` should include a short reverse-engineered `philosophy` (same fields) so Visual QA has a craft bar.
125
+ - `image_reference` requires the same `philosophy` fields (short reverse-engineer from the reference).
126
+ - **`image_reference` also requires `referenceSpec` + `referenceImageInventory`** (see below). `validate-design-v2.mjs` enforces these.
126
127
  - Optional philosophy fields: `subtleReference`, `templateConstraints` (recommended).
127
128
  - Concepts must have unique IDs and all listed art-direction fields.
128
129
  - Every concept requires `philosophyExpression` (how this layout expresses the shared philosophy in space).
@@ -136,6 +137,48 @@ Rules:
136
137
  - Optional per concept: `paletteCandidates` — array of `{ brandHex, mode, name?, presetId?, bestFor?, notFor?, label? }` where `mode` is `light` or `dark`. Prefer `name` + `bestFor` when presenting choices.
137
138
  - Optional root: `themePreview` — `{ brandHex, activeMode, contrastPass, themeTokensPath, name?, presetId?, bestFor?, userConfirmed? }` after palette lock. Set `userConfirmed: true` only after explicit user choice (or waived).
138
139
  - Optional root: `surfacePreview` — `{ kind: flat|gradient|image, userConfirmed, … }`. When `kind` is `gradient` or `image`, require `userConfirmed: true` before authoring those nodes; `gradient` needs `recipeId`; `image` needs `imageId` (or documented pending import) and `imageMode` (`fixed` default for surface background).
140
+
141
+ ### `referenceSpec` + `referenceImageInventory` (`image_reference` only)
142
+
143
+ Required when `sourceKind` is `image_reference`. Rebuild to this measured spec; do not mood-board a different layout.
144
+
145
+ ```json
146
+ {
147
+ "referenceSpec": {
148
+ "stackOrder": ["title", "soft-card", "soft-card-2", "tip", "cta"],
149
+ "margins": "~48px outer",
150
+ "gaps": "~24px between cards",
151
+ "radii": "cards 16px; figure wells 12px",
152
+ "typeScale": "title ~42/bold; body ~22; tip ~18"
153
+ },
154
+ "referenceImageInventory": [
155
+ {
156
+ "label": "Left soft-card person illustration",
157
+ "slotKey": "image_0",
158
+ "imageRole": "hero",
159
+ "boxApprox": "left mid ~280×320"
160
+ }
161
+ ],
162
+ "assetPlan": [
163
+ {
164
+ "role": "hero",
165
+ "source": "user_upload",
166
+ "required": true,
167
+ "slotKey": "image_0",
168
+ "description": "Left soft-card person illustration — empty image-slot frame",
169
+ "treatment": "Match reference box; placeholder until account imageId fill"
170
+ }
171
+ ]
172
+ }
173
+ ```
174
+
175
+ Rules:
176
+
177
+ - `referenceSpec.stackOrder`: non-empty string array (region labels top→bottom or primary reading order).
178
+ - `referenceSpec.margins` / `gaps` / `radii` / `typeScale`: non-empty strings (measured or tightly estimated).
179
+ - `referenceImageInventory`: array required (empty only when the reference has **no** pictorial regions). Each item: `label`, `slotKey` (`image_N`), `imageRole` (`hero|screenshot|avatar|product`), `boxApprox`.
180
+ - Every inventory `slotKey` must appear on an `assetPlan` entry with the same `slotKey` and source in `user_upload|brand_kit|external_photo|generated` — never `css_svg` stand-ins for pictures.
181
+ - Procedure for filling these fields: `workflows/AUTHORING_FROM_IMAGE.md`.
139
182
  ## Companion `design-philosophy.md`
140
183
 
141
184
  Human-readable twin of `design-plan.json` → `philosophy`. Recommended structure:
@@ -246,7 +289,14 @@ Rules:
246
289
  "schemaVersion": "visual_qa_v2_1",
247
290
  "draftId": "draft_123",
248
291
  "iteration": 1,
292
+ "sourceKind": "image_reference",
249
293
  "screenshotEvidence": "/absolute/path/to/studio-render.png",
294
+ "referenceCompare": {
295
+ "performed": true,
296
+ "geometryMatch": true,
297
+ "imageSlotsMatchInventory": true,
298
+ "notes": "Card stack and image_0/image_1 frames match referenceSpec"
299
+ },
250
300
  "hardFailures": [],
251
301
  "scores": {
252
302
  "hierarchy": 18,
@@ -272,7 +322,8 @@ Score maxima total 100. `pass` requires:
272
322
  - no `hardFailures`
273
323
  - each score within its maximum
274
324
  - declared `total` equal to the calculated sum and at least 80
325
+ - when `sourceKind` is `image_reference`: `referenceCompare` with `performed`, `geometryMatch`, and `imageSlotsMatchInventory` all `true`
275
326
 
276
327
  Use `verdict: "revise"` below threshold while iterating. Do not hand off a `revise` result as a reviewed template unless the user explicitly accepts it.
277
328
 
278
- Craft Pass (behavior, not new score fields): when `iteration >= 1`, prefer tightening existing nodes over adding decoration; score against `philosophy.craftBar` and `philosophyExpression` of the selected concept.
329
+ Craft Pass (behavior, not new score fields): when `iteration >= 1`, prefer tightening existing nodes over adding decoration; score against `philosophy.craftBar` and `philosophyExpression` of the selected concept. Set `sourceKind` on `visual-qa.json` to match the design plan when authoring from a reference.