@easysociable/cli 0.1.17 → 0.1.19

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 (25) hide show
  1. package/README.md +2 -1
  2. package/dist/easysociable.js +11408 -9432
  3. package/dist/easysociable.js.map +1 -1
  4. package/package.json +20 -17
  5. package/skills/ONBOARDING.md +2 -3
  6. package/skills/easysociable-slideshow/SKILL.md +254 -152
  7. package/skills/easysociable-slideshow/references/CONTENT_PACK.md +12 -15
  8. package/skills/easysociable-slideshow/references/PLATFORM_CAPS.md +1 -1
  9. package/skills/easysociable-slideshow/references/REFERENCES.md +97 -0
  10. package/skills/easysociable-slideshow/scripts/check-pages.mjs +136 -0
  11. package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +12 -43
  12. package/skills/easysociable-slideshow/workflows/MCP_FIRST.md +1 -3
  13. package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +1 -1
  14. package/skills/easysociable-template/SKILL.md +14 -14
  15. package/skills/easysociable-template/references/CATALOG_METADATA.md +2 -2
  16. package/skills/easysociable-template/references/GATEWAY.md +1 -3
  17. package/skills/easysociable-template/references/PLATFORM_SPECS.md +7 -9
  18. package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +0 -0
  19. package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +4 -4
  20. package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +1 -1
  21. package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +4 -4
  22. package/skills/easysociable-template/workflows/BIND_FORMULA_LOOK.md +39 -0
  23. package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +2 -3
  24. package/skills/easysociable-tweet-image/SKILL.md +57 -0
  25. package/skills/easysociable-template/workflows/MULTI_PLATFORM_FAMILY.md +0 -81
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easysociable/cli",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Agent-first CLI for EasySociable: Content Engine, Template, Slideshow, and MCP",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -8,11 +8,10 @@
8
8
  "homepage": "https://easysociable.com",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/murphywuwu/8MRR-Project.git",
12
- "directory": "apps/cli"
11
+ "url": "git+https://github.com/murphywuwu/easysociable-mcp.git"
13
12
  },
14
13
  "bugs": {
15
- "url": "https://github.com/murphywuwu/8MRR-Project/issues"
14
+ "url": "https://github.com/murphywuwu/easysociable-mcp/issues"
16
15
  },
17
16
  "keywords": [
18
17
  "easysociable",
@@ -51,27 +50,31 @@
51
50
  "LICENSE",
52
51
  "README.md"
53
52
  ],
53
+ "scripts": {
54
+ "typecheck": "tsc --noEmit",
55
+ "test": "vitest run",
56
+ "build": "tsup",
57
+ "prepack": "node scripts/prepack.mjs && pnpm build",
58
+ "pack:check": "npm pack --dry-run"
59
+ },
54
60
  "publishConfig": {
55
61
  "access": "public",
56
62
  "registry": "https://registry.npmjs.org/"
57
63
  },
58
64
  "dependencies": {
59
- "commander": "^11.1.0"
65
+ "@resvg/resvg-wasm": "^2.6.2",
66
+ "commander": "^11.1.0",
67
+ "satori": "^0.36.0"
60
68
  },
61
69
  "devDependencies": {
70
+ "@easysociable/mcp-server": "workspace:*",
71
+ "@easysociable/template-gateway-client": "workspace:*",
72
+ "@easysociable/tsconfig": "workspace:*",
73
+ "@easysociable/tweet-card": "workspace:*",
74
+ "@easysociable/vitest-config": "workspace:*",
62
75
  "@types/node": "^22.14.0",
63
76
  "tsup": "^8.0.2",
64
77
  "typescript": "^5.8.3",
65
- "vitest": "^1.3.1",
66
- "@easysociable/mcp-server": "0.0.0",
67
- "@easysociable/tsconfig": "0.0.0",
68
- "@easysociable/template-gateway-client": "0.0.0",
69
- "@easysociable/vitest-config": "0.0.0"
70
- },
71
- "scripts": {
72
- "typecheck": "tsc --noEmit",
73
- "test": "vitest run",
74
- "build": "tsup",
75
- "pack:check": "npm pack --dry-run"
78
+ "vitest": "^1.3.1"
76
79
  }
77
- }
80
+ }
@@ -19,14 +19,13 @@ V1 expects an Agent (Grok Bot, Codex, Claude Code, …) to drive setup. The webs
19
19
 
20
20
  Default skills:
21
21
 
22
- - `easysociable-slideshow` — turns a draft into slideshow pages you preview and download in the dashboard
23
- - `easysociable-template` — creates page templates
22
+ - `easysociable-slideshow` — turns a topic into carousel pages you edit and download in Studio
24
23
 
25
24
  Optional Content Engine skill (install via CLI only — not in the public
26
25
  content-engine git repo; operations still follow that engine’s `CLAUDE.md`):
27
26
 
28
27
  ```bash
29
- easysociable install --skills content,template,slideshow --yes
28
+ easysociable install --skills content,slideshow --yes
30
29
  ```
31
30
 
32
31
  Get a Content Engine core (preferred):
@@ -1,178 +1,280 @@
1
1
  ---
2
2
  name: easysociable-slideshow
3
3
  description: >
4
- Create, list, update and review durable multi-page Slideshow Runs for
5
- EasySociable from a local Content Pack. Name the argument (arc) first, then
6
- pick a Layout Family per page (one layout, adapted to every platform) by
7
- role, slotSummary and density — never default Cover→Point→Steps→Recap→CTA.
8
- A Formula with a Look already fixes each page's Layout Family. Page 1 must
9
- be a cover or hook class family; those must not appear on later pages. Use the
10
- unified `easysociable` CLI or MCP, open Studio to preview and edit, then
11
- ask the user to click Download for a PNG ZIP. CLI/MCP must not call
12
- render/export or create_render_job for final pixels. Runs remain in the
13
- owner dashboard until archive or hard delete.
4
+ Turn a topic into an editable, ready-to-post carousel (Slideshow Run) in
5
+ EasySociable Studio. Research facts, pick a proven hook and structure
6
+ (Formula), lay pages out from reference designs (the user's, a Formula's,
7
+ or the catalog's, shuffled), render-check every page locally, then create the Run and hand the user a Studio link.
8
+ Ask the user only for what only they know (their Brand, once; their own
9
+ images/screenshots). Final pixels come only from Studio Download.
14
10
  ---
15
11
 
16
12
  # EasySociable Slideshow Skill
17
13
 
18
- A Slideshow Run is a composition of explicit Layout Families, one per page.
19
- A Layout Family is one layout whose templates differ only by platform canvas,
20
- so one Run yields the carousel for every platform (Studio switches variants).
21
- It is not a reusable Carousel/Deck Template and it is not a public post.
22
- Page order is the argument of **this pack**, not a catalog recipe.
14
+ The user gives a topic. You return a Studio link to a carousel that is good
15
+ enough to post, where every word is still editable. The output is editable,
16
+ so **a wrong guess is cheap and a question is expensive**: decide platform,
17
+ page count, arc, style and copy yourself; the user fixes details in Studio.
23
18
 
24
- ## Rules
19
+ Ask only for what only the user knows:
25
20
 
26
- 1. Read a local `content-pack.v1` from the Content Engine.
27
- 2. Use the unified `easysociable` CLI or the unified MCP server. All hosted
28
- calls go through Gateway; never call Directus, R2, Stripe or private services.
29
- 3. Choose a Brand (or Profile/Theme) and an explicit Layout Family for every
30
- page, sent as `layoutFamilyId` in the pack (Gateway resolves it to the
31
- family's template on the Run's native canvas; `pageTemplateId` is still
32
- accepted). The server never silently chooses or replaces a layout.
33
- Order of precedence: (a) a Formula **Look** (see Formula handoff),
34
- (b) families already chosen on the Content Engine pack (**Template
35
- Selection** after **Page Contracts**), (c) a shortlist from
36
- `easysociable slideshows recommend --file contracts.json --seed <slug>`
37
- (MCP `recommend_slideshow_templates`) — pick one `familyId` per page with a reason.
38
- The recommender filters platform + native canvas + slotSummary + cover rule,
39
- demotes Layout Families used in the owner's recent Runs, and keeps one
40
- unused family per page. `role` / `supportedRoles` are weak retrieval tags,
41
- not sequence position. Never browse with bare `templates list` (first 20
42
- ids only); use `--platform <p> --all` if you must see the full catalog.
43
- Do not copy a previous pack's Template Selection as the default.
44
- 4. **Cover / hook placement (hard):** a template is cover/hook class when
45
- `supportedRoles` includes `cover` or `hook`. `pages[0]` must use one.
46
- Cover/hook class templates must not appear on any later page. Later pages
47
- use metric / quote / compare / value / steps / cta / etc. Do not put a
48
- Point or metric-only template on page 1 to “open with a number” — pick a
49
- cover or hook template whose slots fit the opening copy.
50
- 5. A Run has up to 8 pages on Free and 20 on paid, one native platform
51
- (`tiktok`, `instagram`, `linkedin` or `threads`; it sets the page cap and
52
- the canvas edited first) and one Brand across pages. Studio renders the
53
- same Run for every platform its Layout Families support.
54
- 6. Topology is fixed after creation: no add, copy, delete, reorder or template
55
- switch. Page-instance slot/layout/type/style/decoration edits remain allowed
56
- in Studio.
57
- 7. Final pixels leave the product only from **Studio Download** (browser PNG
58
- ZIP). Do not call `slideshows render`, `slideshows export`, `renders create`
59
- or MCP `render_slideshow_run` / `create_render_job`. Those return
60
- `HEADLESS_RENDER_DISABLED`.
61
- 8. Before creating a new Run, list/find prior Runs by `contentSlug`. **Update**
62
- the same Run only when page count, Layout Families, and intended sequence
63
- still match. A different arc or family set is a **new Run** — never PATCH
64
- new copy into a locked Cover-Point-Steps-Recap-CTA skeleton.
65
- 8b. **Knowledge hard gate (every create, not only the first Run):** before
66
- `create_run` / `slideshows create`, read Identity (Role / What I build /
67
- Point of view — no `(fill)`, non-empty) and `boundaries.md` (Not covering
68
- and Never claim non-empty), or run
69
- `easysociable engine validate --run <run-dir> --require-knowledge`.
70
- If `needs/` exists, `needs/_index.md` ≥ 3 `N-` rows; if `needs/` is absent, skip that count. Fail → hand back to
71
- **easysociable-content** / refuse create; list missing files. Do not add
72
- Gateway or MCP params. User must say **强制继续** / **force continue**
73
- to call Gateway. **Exempt:** Formula handoff Runs (prompt names
74
- `Formula: F-…`) — the Formula supplies the arc and the user supplies the
75
- topic, so a first-time user with no Content Engine is not blocked.
76
- 8c. **Identity chain (ADR-0036, hard):** before create, the CLI must be
77
- logged in with the **user's Dashboard Workspace API key** (same account
78
- that will open Studio). Refuse fixture `workspace_local` / local
79
- `test-key` unless the user explicitly asked for a local fixture
80
- (`--allow-local-fixture`). Order: `easysociable auth login` (opens the
81
- browser; the user approves once and the key is stored — use
82
- `--api-key <key>` only when headless) → create Run → open
83
- `studioUrl` while logged in as that user. If Studio shows “belongs to
84
- another account”, recreate with the current key — do not invent
85
- cross-workspace access.
86
- 9. Preview is free. Free Download is 3 successful ZIPs per month and one
87
- platform. Paid Download is unmetered.
88
- 10. **Forbidden default:** do not assemble Cover → Point → Steps → Recap → CTA
89
- because those are P0 family names. Name the arc first
90
- (`references/ARC.md`). Page count follows the argument, not the catalog.
91
- Rule 4 still applies: page 1 is cover/hook class, not “whatever family
92
- is named Cover”.
21
+ - their Brand (IP name, handle, avatar) — once, ever;
22
+ - their own material (screenshots, photos) when a page needs it.
93
23
 
94
24
  ## Workflow
95
25
 
96
- 1. Write one arc line (`references/ARC.md`). Do not skip this for a five-family fill-in.
97
- 2. Validate Page Contracts / pack when present:
98
- `python3 scripts/validate-pack.py runs/<slug>/pack.md` (in the Content Engine).
99
- Refuse create if contracts are empty or contain `templateId`.
100
- 3. Resolve or create the user's Brand through the unified CLI/MCP.
101
- 4. Use the Formula Look's families, else pack **Template Selection**. Otherwise run
102
- `easysociable slideshows recommend --file contracts.json --seed <slug> --json`
103
- and choose a `familyId` from each page's `candidates`; never place a cover/hook class
104
- family after page 1. Report `gaps` (pages with < 2 role-matching
105
- templates) to the user as authoring backlog. Record Layout Family evidence
106
- as `hypothesis` unless published comparable results support `tested` /
107
- `supported` — a template having been used before is not evidence.
108
- 5. List existing Runs when the Pack has a stable content slug:
26
+ ### 0. Login (once per session)
109
27
 
110
- ```bash
111
- easysociable slideshows list --content-slug my-post --json
112
- ```
28
+ `easysociable auth status --json`.
113
29
 
114
- 6. **Hard gate, then** create (new arc/templates) or update (same topology,
115
- slot copy only). Check files or:
30
+ - `authenticated: false` → stop; ask the user to run `easysociable auth login`
31
+ (one browser approval covers CLI and Studio). Draft nothing while logged out.
32
+ - `authenticated: true` → say once: "This Run will be created as
33
+ `<account.email>` — open Studio with the same account."
116
34
 
117
- ```bash
118
- easysociable engine validate --run <run-dir> --require-pack --require-knowledge
119
- ```
35
+ ### 1. Brand (ask once, ever)
36
+
37
+ `easysociable brands list --json`.
38
+
39
+ - A Brand exists → use it (the most recently updated if several), silently.
40
+ - None → ask in **one** message, everything skippable:
41
+ "What name and @handle should appear on your carousels? (Optional: an
42
+ avatar/logo image path.) Reply 'skip' to post without a signature."
43
+ Create it with `easysociable brands create --file brand.json`
44
+ (`{ "name", "handle", "colors", "logoAssetId" }`) using the default palette
45
+ that matches the deck's style (`references/REFERENCES.md`). An avatar: upload
46
+ it first (step 5's `images upload`) and pass the returned `asset.id` as
47
+ `logoAssetId`; `brands get` then returns its `logoUrl`.
48
+ Skipped → no Brand: header shows the topic, the CTA has no handle, and that
49
+ palette goes in `theme.json` (without a Brand or theme Studio falls back to
50
+ its dark default).
51
+
52
+ ### 2. Facts
53
+
54
+ Research the topic from primary sources (official announcement, docs,
55
+ reputable press). Keep a source URL for every fact. Drop claims you can only
56
+ find in secondary blogs. Never invent numbers, dates, quotes or features.
57
+
58
+ When the user started from a Content Engine run, facts come from its knowledge
59
+ pages instead (see `easysociable-content`).
60
+
61
+ ### 3. Hook and structure
62
+
63
+ Both catalogs are hosted cards distilled from real viral posts, with evidence
64
+ pooled across niches (a hook or structure works by its mechanism, not its
65
+ niche). Use a card when it fits; otherwise write your own. Never force one.
66
+
67
+ - Decide the content's **shape** from your facts: N tips → `tip-list`, a
68
+ procedure → `steps`, a transformation → `before-after`, errors →
69
+ `mistake-list`, a single piece of news or a claim → no list recipe.
70
+ - `easysociable hooks recommend --json` → one mold per hook type (list-tease,
71
+ contrast, number, identity, …), ranked by evidence.
72
+ - **Always** look for a structure first:
73
+ `easysociable formulas recommend [--recipe <recipe>] --platform <p> --fact-count <n> --json`
74
+ (`--recipe` when the shape is a list recipe; without it you see every
75
+ structure and judge fit yourself). Near-equal cards come back shuffled.
76
+ When the user asked for something different from last time, add
77
+ `--exclude <formulaId>` for the Formula that Run used.
78
+ - Use a card only if `stop` is false **and** it fits this content (a news
79
+ explainer is not an "N things" list). Prefer `published`; a `hypothesis`
80
+ card is thin evidence: use it only when it clearly fits.
81
+ - Hook: fill the mold's `format` with the topic (never copy its example).
82
+ Formula: its `swipe` is the page order and each `beat.fill` guides the copy.
83
+ - No fitting card → write the hook and arc yourself (`references/ARC.md`):
84
+ draft 3 hooks of different types, keep the most specific one the carousel
85
+ fully pays off.
86
+ - Platform: what the user said, else the one their Brand/history uses, else
87
+ Instagram 4:5. Page count follows the argument (usually 6–9), within
88
+ `references/PLATFORM_CAPS.md`.
89
+ - One idea per page, ≤ 45 words per page. Page 1 is the hook. Last page asks
90
+ for one action (comment, save or follow).
91
+
92
+ ### 4. Look and pages
93
+
94
+ Structure (step 3) and look are chosen separately. The look comes from a
95
+ **reference**; the first rule that applies wins:
96
+
97
+ 1. The user names a Run or says "same as last time / like this one" →
98
+ "Reuse a Run" below.
99
+ 2. The user shares a post (screenshot or link) → study its grid, type scale,
100
+ background, density and decoration; take the closest catalog references as
101
+ structure and restyle them to match the post. Never copy its words or images.
102
+ 3. A Formula with a Look → the Look's designs (Formula handoff below).
103
+ 4. The user asks for a different look ("换个样子", "something else") → first
104
+ write 3–5 art directions that differ from each other and from this Brand's
105
+ previous Run (one line each: grid, type treatment, background, density,
106
+ decoration). Drop any the previous Run used, take the least conventional
107
+ one, and pick references whose `style` fits it.
108
+ 5. Otherwise → the content decides: get candidates for the cover with
109
+ `easysociable templates references --role hook,cover [--no-image] --json`
110
+ (results are shuffled) and take the first that fits the content. Its
111
+ `style` is the deck's style; for each other page ask for that page's roles
112
+ with `--style <style>`. A number → `metric,proof`; a list item →
113
+ `point,value,steps`; a comparison → `compare`; a real product →
114
+ `screenshot`. No match in that style → any style, keeping the cover's chrome.
115
+
116
+ `--no-image` unless you have (or will leave a placeholder for) a real image.
117
+ Read each chosen design with `easysociable templates source --family <familyId> --json`
118
+ and adapt it as in `references/REFERENCES.md` ("Adapting a reference" and
119
+ "Avoid"). Put the result in the pack as a generated page:
120
+
121
+ ```json
122
+ { "role": "hook", "slots": { "text_0": "…", "text_1": "…" },
123
+ "layout": { "studioJson": "<div id=\"Graphic\" data-type=\"post\" …>…</div>",
124
+ "canvas": { "width": 1080, "height": 1350 } } }
125
+ ```
126
+
127
+ `slots` maps each `data-variable` to its plain text. Generated pages carry no
128
+ `layoutFamilyId` / `pageTemplateId`.
129
+
130
+ In the final message, add one line: "Want future carousels to look like this?
131
+ Say 'same as this'. Want another look? Say 'different look'."
120
132
 
121
- Fail → refuse; return to **easysociable-content**. **强制继续** / **force continue**
122
- is the only override (conversational — not a CLI flag). Formula handoff
123
- Runs skip this knowledge check (rule 8b) but not the identity gate. Then:
133
+ ### 5. Images
124
134
 
135
+ - Real products, apps, people, data → real screenshots or photos only. Never
136
+ an AI-generated picture of a real product UI.
137
+ - Concept / mood / background → generate one if this environment has an
138
+ image-generation tool; otherwise leave the page text-only.
139
+ - Images never contain text: all words stay in editable text layers.
140
+ - **Every page whose content needs a real image you don't have gets a
141
+ placeholder slot** (as many pages as need one), never a text-only layout. Size it into the composition (usually the
142
+ lower half of the page) and label it with exactly what belongs there, e.g.
143
+ "Add: Grok Bot app screenshot". The user selects it in Studio and clicks
144
+ the upload button to replace it. Markup and SVG in `references/REFERENCES.md`
145
+ ("Image placeholder").
146
+ - An image you do have: upload it
147
+ (`easysociable images upload --file body.json` with
148
+ `{ "file": "data:image/png;base64,…", "filename": "x.png" }`) and use the
149
+ returned `asset.url` as `src`.
150
+ - List every placeholder in the final message ("page 2: app screenshot").
151
+
152
+ ### 6. Check (hard gate)
153
+
154
+ ```bash
155
+ easysociable brands get --id <brandId> --json > brand.json
156
+ node <skill>/scripts/check-pages.mjs pack.json --out ./check --brand brand.json
157
+ # no Brand: --theme theme.json instead of --brand brand.json
158
+ ```
159
+
160
+ - Exit 1 → fix every ERROR (overflow, off-canvas, text overlap, contrast) and
161
+ re-run. Do not create the Run with errors.
162
+ - Warnings (small text, too many words, empty band) → fix unless deliberate.
163
+ - Open `check/grid.png` and review it as a designer: one clear focal point per
164
+ page, nothing cramped, no two adjacent pages alike, reads in 2 seconds.
165
+ At most two fix rounds.
166
+ - Exit 2 (no Chrome) → continue, and tell the user the visual check was skipped.
167
+
168
+ ### 7. Create and hand off
169
+
170
+ ```bash
171
+ easysociable slideshows create --file pack.json --brand-id <brandId> --json
172
+ # no Brand: --theme theme.json instead of --brand-id
173
+ ```
174
+
175
+ Reply once with: the `studioUrl`, the arc in one line, the sources, and each
176
+ image placeholder to replace (page + what to upload). Tell them to edit in
177
+ Studio and click **Download** for the PNG ZIP.
178
+
179
+ ### 8. Revise (same Run, never a copy)
180
+
181
+ Feedback on an existing Run ("page 3 looks off", "shorter hook") edits that Run.
182
+
183
+ 1. `easysociable slideshows get --id <runId> --json > revisions/<runId>-r<revision>.json`
184
+ — the saved Run is the source of truth (it holds the user's Studio edits);
185
+ never rebuild from your local pack.json. The file is also the backup.
186
+ 2. Change only the pages the user named. Start from each page's saved `layout`
187
+ and `slots`, adapt as in step 4, and run step 6 on the changed pages.
188
+ 3. Write `patch.json` and apply it:
189
+ ```json
190
+ { "baseRevision": <run.revision>,
191
+ "pages": [{ "pageIndex": 2, "layout": { "studioJson": "…", "canvas": { "width": 1080, "height": 1350 } }, "slots": { … } }] }
192
+ ```
125
193
  ```bash
126
- easysociable slideshows create --file ./pack.json --json
194
+ easysociable slideshows update --id <runId> --file patch.json --json
127
195
  ```
196
+ `slots` replaces the page's slots, so send the full set for that page.
197
+ Unlisted pages stay untouched.
198
+ 4. `RUN_REVISION_CONFLICT` → the user saved in Studio meanwhile: `get` again,
199
+ re-apply your change on top, retry once.
200
+ 5. "Go back to the previous version" → take those pages' `layout` / `slots`
201
+ from the newest `revisions/<runId>-r*.json` before the change and send them
202
+ as a normal patch with the current `baseRevision`. The original generated
203
+ pages are in the Run's `packSnapshot`.
204
+
205
+ Same `studioUrl`; tell the user to reload Studio. A new Run only for a
206
+ different topic, or when the user asks for an alternative version to compare.
207
+
208
+ ## Formula handoff (prompt names `Formula: F-…`)
209
+
210
+ `easysociable formulas get --id <id> --json`. Its `beats` are the pages (same
211
+ order and roles); `title_template` with `{X}` = the topic is the arc. Write copy
212
+ from each `beat.fill` and your facts; never copy the formula's example posts.
213
+ With `Look: L-…` (else the formula's first `looks` entry) the page source is
214
+ `look.slides["<n>"]` or `look.layouts[beat.role]` (a design's `familyId`):
215
+ read it with `templates source --family` and adapt it as in step 4. The Look
216
+ wins over rule 5 of step 4 but not over a Run or post the user named.
217
+ Then continue at step 5.
218
+
219
+ ## Reuse a Run (prompt names a `run_…` for a new topic)
220
+
221
+ A new topic → a **new** Run; the source Run is never changed. Never ask which
222
+ mode; decide from the words and the content:
223
+
224
+ - **Template** — "using run_x as the template", "same as last time", "like
225
+ this one" (last time = the newest Run of this Brand, `slideshows list`).
226
+ Keep every page's look: only slot content changes.
227
+ - **Style** — "in the style / feel / vibe of run_x", or Template was asked but
228
+ the new content does not fit its page roles (a "N tips" Run for an "A vs B"
229
+ topic). Take its colours, type treatment, chrome and spacing; lay pages out
230
+ fresh in step 4.
231
+
232
+ Template steps:
233
+
234
+ 1. `easysociable slideshows get --id <runId> --json`. Its pages' `role`,
235
+ `layout` and `slots` are the source (they include the user's Studio edits).
236
+ 2. Write facts and the arc for the new topic (steps 2–3, no Formula search).
237
+ 3. Pages by role: one-off roles (hook, cta) copy that page's `layout`
238
+ verbatim; repeated roles (point, step) reuse the source page of that role
239
+ **as many times as the new content needs** (4 tips → 4 pages, 6 → 6). Drop
240
+ roles the new content has none of.
241
+ 4. Change only text inside `data-variable` elements and send matching
242
+ `slots`. Too long → rewrite shorter; never resize boxes or move elements.
243
+ Every source image becomes a placeholder for the new topic (step 5);
244
+ Brand avatar/logo stay.
245
+ 5. Step 6 check, then create (step 7). In the reply, say in one line what
246
+ differs from the source ("6 tips, so 6 point pages instead of 4") and that
247
+ the user can say "back to 4 pages" or "different layout".
248
+
249
+ ## Rules
128
250
 
129
- 7. Open the returned `studioUrl` and inspect every page.
130
- 8. Save Studio edits and wait for the saved revision.
131
- 9. After explicit user confirmation, tell them to click **Download** in Studio.
132
- Do not render or export from CLI/MCP.
133
-
134
- ## Formula handoff (prompt names a `Formula: F-…` id)
135
-
136
- 1. `easysociable formulas get --id <id> --json` (falls back to the hosted
137
- catalog). Not found → tell the user; do not guess a structure.
138
- 2. The formula's `beats` are the page order: one page per beat, same roles,
139
- same count. Its `title_template` with `{X}` = the user's topic is the arc
140
- line, so rule 10 is satisfied by the formula, not by P0 family names.
141
- 3. Write each page's copy from `beat.fill` and the user's topic. Ask at most
142
- one question when tip/point pages need facts the topic doesn't supply.
143
- Never copy sentences from the formula's viral example posts.
144
- 4. **Look = copy the layout.** If the prompt names `Look: L-…` (else use the
145
- formula's first entry in `looks`), set each page's `layoutFamilyId` to
146
- `look.slides["<1-based slide number>"]` if present, else
147
- `look.layouts[beat.role]`. Do not run `slideshows recommend` for those
148
- pages and ignore the "demote recently used families" preference — the
149
- user asked for this layout. Only roles missing from the Look fall back to
150
- the recommender. Copy layout only: colours and fonts come from the user's
151
- Brand. If a Look family has image slots, ask the user for images (or say
152
- which slots are empty) instead of delivering blank image slots.
153
- 5. Turn beats into Page Contracts, then continue at Workflow step 3
154
- (Brand → families → identity gate → create → Studio). The knowledge gate
155
- (rule 8b) does not apply to Formula handoff Runs.
251
+ 1. All hosted calls go through the `easysociable` CLI or the unified MCP
252
+ server (Gateway). Never call Directus, R2, Stripe or private services.
253
+ 2. Final pixels leave only via Studio **Download**. Do not call
254
+ `slideshows render`, `slideshows export`, `renders create`, or MCP
255
+ `render_slideshow_run` / `create_render_job` (`HEADLESS_RENDER_DISABLED`).
256
+ 3. Revisions edit the same Run page by page (step 8): layout, text and images
257
+ can all change. Page count and order are fixed for now (no add, delete,
258
+ reorder) — if the user needs that, say so; create a new Run only when they agree.
259
+ 4. Every plan: up to 20 pages. Free: 3 Downloads per month and 1 Brand; Creator: unlimited, 3 Brands; Studio: unlimited, 25 Brands. `BRAND_LIMIT_REACHED` → tell the user their plan's limit and the suggested action; never create a Run without the Brand silently.
260
+ 5. Identity: create with the user's own login, not `workspace_local` /
261
+ `test-key` (unless they asked for `--allow-local-fixture`). Studio says
262
+ "belongs to another account" → recreate with the current login.
263
+ 6. Content Engine runs keep their knowledge gate:
264
+ `easysociable engine validate --run <run-dir> --require-knowledge`.
265
+ Topic-only requests (no Content Engine) use researched, sourced facts.
156
266
 
157
267
  ## Failure handling
158
268
 
159
- - If the knowledge hard gate fails, do not create the Run. Hand back to
160
- easysociable-content and list missing files unless the user said
161
- **强制继续** / **force continue**.
162
- - If page 1 is not cover/hook class, or a later page uses a cover/hook
163
- class template, stop and rebuild the Pack. Do not create the Run.
164
- - If a page template, slot or image is invalid, return the structured Gateway
165
- error to the Agent; do not substitute another template.
166
- - `LAYOUT_FAMILY_NOT_FOUND`: the family has no template for the Run's
167
- platform. Tell the user and pick another platform or family; do not guess.
168
- - If Download is exhausted (`USAGE_LIMIT_REACHED`) or past due, tell the user
169
- to upgrade or update billing.
170
- - If a Run was deleted, or Gateway returns `RUN_TOPOLOGY_LOCKED` because the
171
- pack changed sequence/templates, create a new Run from the Pack.
269
+ - `CONTENT_PACK_INVALID` → fix the pack field it names; do not drop pages silently.
270
+ - `BRAND_NOT_FOUND` → the Brand belongs to another account; list Brands again.
271
+ - `USAGE_LIMIT_REACHED` / past due → tell the user to upgrade or update billing.
272
+ - `RUN_REVISION_CONFLICT` → `slideshows get`, re-apply on the latest revision, retry once.
273
+ - `RUN_TOPOLOGY_LOCKED` → you sent a full `pack` or a `pageTemplateId`; send
274
+ page `layout` / `slots` instead (step 8).
172
275
 
173
276
  ## Handoff boundary
174
277
 
175
- The Content Engine owns semantic copy, Pack creation, and the arc.
176
- The Template Skill owns single-page authoring and publish.
177
- This Skill composes explicit page instances and opens Studio for review/Download.
178
- It does not own a product-level story recipe.
278
+ The Content Engine owns knowledge pages and Formula research. Reference
279
+ designs are authored internally (Template skill); this skill only reads them. This skill turns a topic into a Run
280
+ and opens Studio.
@@ -1,18 +1,19 @@
1
1
  # ContentPack v1
2
2
 
3
- Page `role` is a **weak retrieval tag** (layout-ish), not sequence position.
4
- `layoutFamilyId` is the explicit Layout Family chosen by the Agent (from a
5
- Formula Look or the recommender's `familyId`); Gateway resolves it to that
6
- family's template on the pack platform's canvas, and Studio derives the other
7
- platforms from the same family. `pageTemplateId` (one exact template) is still
8
- accepted and wins when both are sent. `slots` are public values only. Do not add a `deck_template_id`,
9
- `bindingMap`, AST, ContentDocument, or product `arc` / `pageSequence`.
3
+ A page is **generated**: `layout: { studioJson, canvas }` adapted from a
4
+ reference design (see `REFERENCES.md`). Catalog pages (`layoutFamilyId` /
5
+ `pageTemplateId`) are legacy; do not create new Runs with them. `role` is a weak tag from the closed enum, not a
6
+ sequence position. `slots` are public values only. Do not add a
7
+ `deck_template_id`, `bindingMap`, AST, ContentDocument, or product `arc` /
8
+ `pageSequence`.
10
9
 
11
- The Gateway validates each `role` against the closed enum and that slots exist.
12
- It does not require Cover → Point → Steps → Recap → CTA.
10
+ Generated page:
13
11
 
14
- This skill **does** require page 1 to be cover/hook class (`supportedRoles`
15
- includes `cover` or `hook`) and forbids that class on later pages.
12
+ ```json
13
+ { "role": "hook", "slots": { "text_0": "Meta's new AI doesn't chat." },
14
+ "layout": { "studioJson": "<div id=\"Graphic\" data-type=\"post\" …>…</div>",
15
+ "canvas": { "width": 1080, "height": 1350 } } }
16
+ ```
16
17
 
17
18
  ## Example: cost → mechanism (TikTok)
18
19
 
@@ -47,10 +48,6 @@ Opening beat is cost; page 1 is still a hook-class template.
47
48
  }
48
49
  ```
49
50
 
50
- Pick families by **slotSummary + density** (or take them from a Formula Look),
51
- not by matching the beat name to a family named Cover / Point / Steps / Recap /
52
- CTA. Page 1 must still be cover/hook class.
53
-
54
51
  The renderer accepts any supported page count within the platform cap. A newly
55
52
  published Layout Family can be selected in a new Run without creating a
56
53
  carousel asset.
@@ -1,4 +1,4 @@
1
- # Platform page caps (ADR-0026)
1
+ # Platform page caps
2
2
 
3
3
  The Run validates only the actual `content-pack.v1.pages.length`. There is no
4
4
  `designMax`, full-page deck skeleton, or deck catalog to clone.