@easysociable/cli 0.1.0

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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/bin/easysociable.js +15 -0
  4. package/dist/easysociable.js +35464 -0
  5. package/dist/easysociable.js.map +1 -0
  6. package/package.json +58 -0
  7. package/skills/ONBOARDING.md +61 -0
  8. package/skills/easysociable-content/SKILL.md +115 -0
  9. package/skills/easysociable-content/platforms/claude.md +5 -0
  10. package/skills/easysociable-content/platforms/codex.md +5 -0
  11. package/skills/easysociable-content/platforms/hermes.md +5 -0
  12. package/skills/easysociable-content/platforms/openclaw.md +5 -0
  13. package/skills/easysociable-content/references/CLI.md +27 -0
  14. package/skills/easysociable-content/references/MCP.md +20 -0
  15. package/skills/easysociable-content/references/PAGE_PACK.md +6 -0
  16. package/skills/easysociable-content/references/TROUBLESHOOTING.md +11 -0
  17. package/skills/easysociable-content/references/VAULT.md +20 -0
  18. package/skills/easysociable-content/scripts/setup.mjs +156 -0
  19. package/skills/easysociable-content/scripts/setup.test.mjs +71 -0
  20. package/skills/easysociable-content/scripts/starter.mjs +53 -0
  21. package/skills/easysociable-content/workflows/ANALYSIS_AND_COVERAGE.md +8 -0
  22. package/skills/easysociable-content/workflows/CONTENT_EXPORT.md +19 -0
  23. package/skills/easysociable-content/workflows/DEVICE_TASKS.md +5 -0
  24. package/skills/easysociable-content/workflows/EXPERIMENTS.md +6 -0
  25. package/skills/easysociable-content/workflows/MCP_FIRST.md +10 -0
  26. package/skills/easysociable-content/workflows/PUBLICATION.md +5 -0
  27. package/skills/easysociable-content/workflows/TOPIC_DRAFT.md +5 -0
  28. package/skills/easysociable-content/workflows/WORKING_DRAFT.md +10 -0
  29. package/skills/easysociable-slideshow/SKILL.md +77 -0
  30. package/skills/easysociable-slideshow/references/CONTENT_PACK.md +25 -0
  31. package/skills/easysociable-slideshow/references/GATEWAY.md +16 -0
  32. package/skills/easysociable-slideshow/references/PLATFORM_CAPS.md +17 -0
  33. package/skills/easysociable-slideshow/references/VAULT.md +18 -0
  34. package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +7 -0
  35. package/skills/easysociable-slideshow/workflows/MCP_FIRST.md +14 -0
  36. package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +8 -0
  37. package/skills/easysociable-slideshow/workflows/PUBLISH_RUN.md +4 -0
  38. package/skills/easysociable-slideshow/workflows/RENDER_RUN.md +6 -0
  39. package/skills/easysociable-template/SKILL.md +106 -0
  40. package/skills/easysociable-template/references/AUTHORING_SOURCE.md +129 -0
  41. package/skills/easysociable-template/references/CATALOG_METADATA.md +221 -0
  42. package/skills/easysociable-template/references/DESIGN_INTELLIGENCE.md +69 -0
  43. package/skills/easysociable-template/references/DESIGN_V2_1.md +278 -0
  44. package/skills/easysociable-template/references/EXTERNAL_RESOURCES.md +52 -0
  45. package/skills/easysociable-template/references/GATEWAY.md +25 -0
  46. package/skills/easysociable-template/references/PLATFORM_SPECS.md +134 -0
  47. package/skills/easysociable-template/references/SLOTS.md +104 -0
  48. package/skills/easysociable-template/references/THEME_PRESETS.md +48 -0
  49. package/skills/easysociable-template/references/THEME_TOKENS.md +89 -0
  50. package/skills/easysociable-template/references/fixtures/surface-gradient.design-plan.json +74 -0
  51. package/skills/easysociable-template/references/theme-presets.json +95 -0
  52. package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +402 -0
  53. package/skills/easysociable-template/scripts/validate-authoring-source.mjs +228 -0
  54. package/skills/easysociable-template/scripts/validate-design-v2.mjs +318 -0
  55. package/skills/easysociable-template/workflows/ASSET_PLAN.md +34 -0
  56. package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +52 -0
  57. package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +52 -0
  58. package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +122 -0
  59. package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +92 -0
  60. package/skills/easysociable-template/workflows/DESIGN_CONCEPTS.md +41 -0
  61. package/skills/easysociable-template/workflows/DESIGN_PHILOSOPHY.md +69 -0
  62. package/skills/easysociable-template/workflows/FILL_AND_RENDER.md +86 -0
  63. package/skills/easysociable-template/workflows/MCP_FIRST.md +9 -0
  64. package/skills/easysociable-template/workflows/OUT_OF_SCOPE.md +15 -0
  65. package/skills/easysociable-template/workflows/PALETTE_REVIEW.md +71 -0
  66. package/skills/easysociable-template/workflows/PUBLISH_FROM_DRAFT.md +60 -0
  67. package/skills/easysociable-template/workflows/SURFACE_REVIEW.md +178 -0
  68. package/skills/easysociable-template/workflows/THEME_FROM_BRAND.md +73 -0
  69. package/skills/easysociable-template/workflows/VISUAL_QA.md +55 -0
@@ -0,0 +1,221 @@
1
+ # Catalog / selection metadata (single-page template)
2
+
3
+ Metadata that makes a published page template **discoverable and choosable** when Content Skill builds a slideshow.
4
+ Private AST/bindings stay server-side; this document is the **public selection contract** Agents must fill before Publish.
5
+
6
+ ## Design choices (locked)
7
+
8
+ 1. **One closed `pageRoles` set** (stored as `supportedRoles`) — narrative beat + layout kind in one enum. Do not maintain a second parallel taxonomy.
9
+ 2. **`platforms` is a multi-select array**. Include `generic` when the page fits any platform at that aspect.
10
+ 3. **P0 fields are required to Publish.** P1 should be filled when known; P2 optional.
11
+
12
+ Max **1–2** `supportedRoles` per page (primary + optional secondary).
13
+
14
+ ---
15
+
16
+ ## Closed enums
17
+
18
+ ### Platforms (`platforms: Platform[]`)
19
+
20
+ ```text
21
+ xiaohongshu | tiktok | instagram | threads | x | linkedin | wechat_cover | generic
22
+ ```
23
+
24
+ Multi-select. Use `x` for X/Twitter. See **exact recommended pixels** in `references/PLATFORM_SPECS.md` before choosing `canvasPreset`.
25
+
26
+ ### Canvas preset (`canvasPreset`)
27
+
28
+ ```text
29
+ 3:4 | 4:5 | 9:16 | 16:9 | 1:1 | 21:9 | custom
30
+ ```
31
+
32
+ Always also store exact `canvas: { width, height }`. Use `16:9` for X **1200×675** in-stream; use `custom` for non-standard boards like link cards **1200×628**. Prefer the platform **Recommended** row in `PLATFORM_SPECS.md`.
33
+
34
+ ### Page roles (`supportedRoles` / pageRoles) — pick 1–2
35
+
36
+ | Role | When to use |
37
+ |---|---|
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 |
43
+ | `point` | One sharp point (lighter than value) |
44
+ | `checklist` | Fixed N text lines (no list binding type) |
45
+ | `proof` | Proof / credibility |
46
+ | `evidence` | Evidence artifacts (data, case) |
47
+ | `compare` | Before/after or A/B compare |
48
+ | `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 |
55
+
56
+ Legacy-compatible: `cover`, `setup`, `value`, `proof`, `cta` remain valid.
57
+
58
+ ### Content family (`contentFamily`) — pick one
59
+
60
+ ```text
61
+ narrative | utility | social_proof | conversion
62
+ ```
63
+
64
+ ### Content archetypes (`contentArchetypes`) — pick ≥1 from closed set
65
+
66
+ ```text
67
+ product_review | tool_demo | tutorial | listicle
68
+ personal_story | opinion | news_explainer
69
+ lifestyle | travel | fitness | food_recipe
70
+ career | finance_lite | ai_update
71
+ launch | changelog | milestone_celebrate
72
+ ugc_repost | quote_card
73
+ ```
74
+
75
+ ### Density (`density`)
76
+
77
+ ```text
78
+ low | medium | high
79
+ ```
80
+
81
+ Align with `textDensityRange` when both are set (e.g. low → `[0, 0.34]`, medium → `[0.33, 0.67]`, high → `[0.66, 1]`).
82
+
83
+ ### Visual style (`visualStyle`) — P1
84
+
85
+ ```text
86
+ swiss | editorial | bold_promo | minimal | dark
87
+ ```
88
+
89
+ ### Image roles (`imageRoles`) — when any image slot exists
90
+
91
+ ```text
92
+ hero | screenshot | avatar | product
93
+ ```
94
+
95
+ ---
96
+
97
+ ## P0 — required before Publish / must appear on Catalog summary
98
+
99
+ | Field | Type | Notes |
100
+ |---|---|---|
101
+ | `name` | string | Human title |
102
+ | `shortDescription` | string | One sentence for chooser UI |
103
+ | `platforms` | `Platform[]` | Multi-select; use `generic` when truly cross-platform |
104
+ | `canvasPreset` | preset enum | Plus exact `canvas` pixels |
105
+ | `canvas` | `{ width, height }` | Exact board |
106
+ | `supportedRoles` | pageRole[1..2] | Closed set above |
107
+ | `contentFamily` | enum | Narrows before archetype |
108
+ | `contentArchetypes` | archetype[] | ≥1 from closed set |
109
+ | `density` | low/medium/high | |
110
+ | `textDensityRange` | `[number, number]` | Keep in sync with density |
111
+ | `requiresImage` | boolean | |
112
+ | `imageRoles` | imageRole[] | Required if `requiresImage` or any image slot |
113
+ | `mediaRequirements` | string[] | Normalized hints, e.g. `image`, `screenshot` |
114
+ | `slotSummary` | `{ text, number, image }` | Counts of slots by type |
115
+ | `fixedItemCount` | number? | Set for `checklist` / `steps` (absolute layout) |
116
+ | `previewImageUrl` | url? | Required when Gateway/Studio can supply; block Publish if product requires it |
117
+ | `tier` | `free` \| `paid` | From entitlement / owner; do not invent paid for free users |
118
+
119
+ ### `slotSummary` example
120
+
121
+ ```json
122
+ { "text": 4, "number": 1, "image": 1 }
123
+ ```
124
+
125
+ Derived from the slot table in `SLOTS.md`.
126
+
127
+ ---
128
+
129
+ ## P1 — fill when known (strongly recommended)
130
+
131
+ | Field | Type | Notes |
132
+ |---|---|---|
133
+ | `bestFor` | string[2..4] | “适合…” bullets for users |
134
+ | `notFor` | string[1..3] | Honest exclusions |
135
+ | `selectionHints` | string | Short Agent-only hint |
136
+ | `visualStyle` | enum | Look affinity |
137
+ | `defaultThemeId` | string? | Soft preview theme |
138
+ | `compatibleThemeIds` | string[]? | Optional |
139
+ | `locale` | `zh-CN` \| `en` \| `bilingual` | |
140
+ | `exampleFilledPreviewUrl` | url? | Filled sample beats empty shell |
141
+
142
+ ---
143
+
144
+ ## P2 — optional
145
+
146
+ | Field | Notes |
147
+ |---|---|
148
+ | `safeAreaProfile` | e.g. `xhs_default`, `ig_feed` |
149
+ | `featured` | Catalog boost |
150
+ | `colorDependency` | `theme_only` (preferred for new templates) \| `has_hardcoded_accents` |
151
+ | `tags` | Free-form search aides only — never replace closed enums |
152
+
153
+ ---
154
+
155
+ ## Agent selection order (for Content → slideshow)
156
+
157
+ Content Skill exports a template-neutral `ContentDocument` (slide roles + fields only).
158
+ **Compose** (Template Skill / Desktop / render workflow) then selects pages:
159
+
160
+ ```text
161
+ 1. platforms ∩ aspect/canvasPreset
162
+ 2. slide needs role ∈ supportedRoles
163
+ 3. contentFamily / contentArchetypes match topic
164
+ 4. requiresImage / imageRoles vs available assets
165
+ 5. density + slotSummary (+ fixedItemCount) fit copy
166
+ 6. Present 3–5 candidates: preview + name + shortDescription + bestFor
167
+ 7. User confirms, or accept account/system default Look (Theme) separately
168
+ 8. createRender with selected pageTemplateIds (never dump AST to the agent)
169
+ ```
170
+
171
+ Example list call:
172
+
173
+ ```bash
174
+ easysociable templates list --platforms x --roles metric --density low --limit 5 --json
175
+ # MCP: list_templates({ platforms:['xiaohongshu'], roles:['metric'], density:'low', limit:5 })
176
+ ```
177
+
178
+ **Catalog rules**
179
+
180
+ - Only **published** pages with complete P0 `selection_metadata` appear in `list`.
181
+ - Do **not** list every PageTemplate AST. Explain choices with this public metadata only.
182
+ - Content Skill must not call Directus / TemplatePage; keep ADR-0019 surface split.
183
+
184
+ ---
185
+
186
+ ## Authoring checklist (before create / before Publish)
187
+
188
+ Agent must produce a `selection-metadata.json` (or equivalent fields on the draft) containing **all P0** keys. Confirm with the user when roles/platforms were inferred from a brief or reference image.
189
+
190
+ ```json
191
+ {
192
+ "name": "XHS metric milestone 3:4",
193
+ "shortDescription": "大数字涨粉庆祝页,可选头像",
194
+ "platforms": ["xiaohongshu", "generic"],
195
+ "canvasPreset": "3:4",
196
+ "canvas": { "width": 1080, "height": 1440 },
197
+ "supportedRoles": ["metric", "cover"],
198
+ "contentFamily": "conversion",
199
+ "contentArchetypes": ["milestone_celebrate", "launch"],
200
+ "density": "low",
201
+ "textDensityRange": [0, 0.34],
202
+ "requiresImage": false,
203
+ "imageRoles": ["avatar"],
204
+ "mediaRequirements": [],
205
+ "slotSummary": { "text": 2, "number": 1, "image": 1 },
206
+ "fixedItemCount": null,
207
+ "visualStyle": "swiss",
208
+ "bestFor": ["涨粉节点", "数据庆祝封面"],
209
+ "notFor": ["长清单干货", "多步教程"],
210
+ "selectionHints": "Prefer when slide.role is metric or cover and a single KPI dominates.",
211
+ "locale": "zh-CN"
212
+ }
213
+ ```
214
+
215
+ ## Anti-patterns
216
+
217
+ - Tagging five roles on one page “just in case”
218
+ - Using only free-form `tags` instead of `supportedRoles` / archetypes
219
+ - Checklist without `fixedItemCount`
220
+ - `requiresImage: true` but `imageRoles` empty
221
+ - Platforms empty or inventing values outside the enum
@@ -0,0 +1,69 @@
1
+ # Design intelligence (lightweight)
2
+
3
+ Curated hints for philosophy, concept, and palette phases when the user has no brand hex. Not a replacement for `DESIGN_PHILOSOPHY.md` or `DESIGN_CONCEPTS.md` — use to seed `movementName`, `paletteCandidates`, and font pairing.
4
+
5
+ ## Movement seeds (adapted from canvas-design; template-safe)
6
+
7
+ Use these as philosophy starters. Rewrite into `design-plan.json` `philosophy` fields; keep required slots readable.
8
+
9
+ | Seed movement | Space / composition | Rhythm / motif | Color mood | Font voice | Suggested hex |
10
+ |---------------|---------------------|----------------|------------|------------|---------------|
11
+ | Editorial Monument | One oversized focal; quiet gutters; thin attribution rail | Ledger rules, folio marks | Warm paper, dark ink, one accent | Editorial (serif display + Inter body) | `#0D9488` light |
12
+ | Terminal Pulse | Compact header; centered status metric; tabular footer | Prompt glyph, status dot, hairline grid | Near-black canvas, electric accent | Terminal (JetBrains Mono + Inter) | `#14B8A6` dark |
13
+ | Quiet Proof | Centered claim; generous negative space; small evidence row | Thin rules, soft dividers | Off-white, muted slate, restrained accent | Premium / editorial | `#475569` light |
14
+ | Warm Folio | Asymmetric author block; hero quote or metric; soft margin marks | Paper edge, soft rules | Cream-warm canvas, amber or deep ink | Premium | `#B45309` light |
15
+ | Signal Strip | Strong horizontal bands; one CTA or metric band dominates | Bars, ticks, progress marks | Neutral canvas, semantic green/blue sparingly | Modern SaaS (Inter/Inter) | `#2563EB` light |
16
+ | Creator Spark | Playful asymmetry; one bold gesture type; sparse stickers as siblings | Blobs/dots as CSS only | Light canvas, saturated accent | Playful | `#DB2777` light |
17
+
18
+ Map seed → `philosophy`:
19
+
20
+ - `movementName` ← seed name
21
+ - `space` / `composition` ← Space / composition column
22
+ - `rhythm` ← Rhythm / motif
23
+ - `color` ← Color mood (no final hex)
24
+ - `typographyAccent` ← Font voice + display/body ratio intent
25
+ - `craftBar` ← always include: one focal; no overlap; refine before adding decoration
26
+
27
+ ## Archetype → style hints
28
+
29
+ | Archetype | Prefer movement seed | Layout bias | Palette mood |
30
+ |-----------|----------------------|-------------|--------------|
31
+ | Editorial / report | Editorial Monument | author rail, oversized metric | warm canvas, dark ink, one accent |
32
+ | Terminal / indie hacker | Terminal Pulse | compact header, centered metric | dark canvas, electric accent |
33
+ | Playful / creator | Creator Spark | asymmetric blocks | light canvas, saturated accent |
34
+ | Luxury / premium | Warm Folio / Quiet Proof | centered hero, small caps metadata | off-white canvas, gold or deep accent |
35
+ | Data / dashboard | Signal Strip | grid of metrics (still one primary focal) | neutral canvas, semantic green/red sparingly |
36
+
37
+ ## Suggested brand hex (no user color)
38
+
39
+ Prefer curated presets in `references/THEME_PRESETS.md` / `theme-presets.json`, then generate with `--preset`. Fall back to mood hexes below only when presets do not fit.
40
+
41
+ | Mood | Light mode hex | Dark mode hex | Notes | Close preset |
42
+ |------|----------------|---------------|-------|--------------|
43
+ | Trust / finance | `#0D9488` | `#14B8A6` | teal — readable on white and near-black | `ocean-depths` |
44
+ | Energy / growth | `#16A34A` | `#22C55E` | green — watch muted contrast on light gray | `botanical-garden` |
45
+ | Tech / product | `#2563EB` | `#3B82F6` | blue — strong default for SaaS | `tech-innovation` |
46
+ | Bold / creator | `#DB2777` | `#EC4899` | pink — verify muted text on canvas | `desert-rose` (softer) |
47
+ | Premium | `#B45309` | `#D97706` | amber — pair with warm off-white canvas | `golden-hour` |
48
+ | Neutral authority | `#475569` | `#94A3B8` | slate — safe when accent must stay subtle | `modern-minimalist` |
49
+
50
+ ## Font pairing (Gateway `themeTokens.fonts`)
51
+
52
+ | Voice | heading | body |
53
+ |-------|---------|------|
54
+ | Editorial | Georgia, serif stack | Inter |
55
+ | Terminal | JetBrains Mono | Inter |
56
+ | Modern SaaS | Inter | Inter |
57
+ | Playful | Fredoka | Nunito |
58
+ | Premium | Playfair Display | Source Sans 3 |
59
+
60
+ Use platform-safe stacks if custom fonts are not loaded — default to `Inter` for both when unsure. Do **not** vendor canvas-design’s `canvas-fonts` TTFs into this skill.
61
+
62
+ ## Workflow tie-in
63
+
64
+ 1. After Brief, run `DESIGN_PHILOSOPHY.md` and seed `movementName` from the table above when needed.
65
+ 2. During `DESIGN_CONCEPTS.md`, attach `philosophyExpression` + named `paletteCandidates` (`name`, `brandHex`, `mode`, `bestFor`, optional `presetId`) per concept.
66
+ 3. After selection, run `PALETTE_REVIEW.md`: showcase swatches → wait for explicit confirmation → lock winner.
67
+ 4. Run `THEME_FROM_BRAND.md` (`--preset` or hex) to produce `theme-tokens.json`; do not `theme.create` until confirmed.
68
+
69
+ Do not treat this table as exhaustive — adjust hex when contrast fails.
@@ -0,0 +1,278 @@
1
+ # V2.1 design and visual-QA contracts
2
+
3
+ Use these local artifacts to make art direction and screenshot review explicit. They are workflow artifacts, not Gateway DTOs.
4
+
5
+ ## Contents
6
+
7
+ - `design-philosophy.md`: human-readable visual philosophy (optional companion to the JSON field)
8
+ - `design-plan.json`: philosophy, art direction, concept selection, asset decisions, and theme preview
9
+ - `theme-tokens.json`: generated brand scale, semantic colors, and WCAG contrast report
10
+ - `visual-qa.json`: screenshot evidence, fixed scores, and pass/revise verdict
11
+
12
+ ## `design-plan.json`
13
+
14
+ ```json
15
+ {
16
+ "schemaVersion": "design_plan_v2_1",
17
+ "sourceKind": "text_brief",
18
+ "intent": {
19
+ "jobToBeDone": "Make monthly revenue understandable in one glance",
20
+ "primaryPlatform": "x",
21
+ "canvas": { "width": 1200, "height": 675 }
22
+ },
23
+ "philosophy": {
24
+ "movementName": "Editorial Ledger",
25
+ "space": "Generous top margin; one monumental metric zone; quiet side gutters",
26
+ "color": "Warm paper canvas, near-black ink, one teal accent; decoration stays ink-weight",
27
+ "rhythm": "Horizontal ledger rules and folio marks at a fixed cadence",
28
+ "composition": "Author rail top; oversized metric center-left; breakdown as a thin footer band",
29
+ "typographyAccent": "Display metric ~4x body; metadata in small caps or mono; no paragraph stacks",
30
+ "craftBar": "Museum-grade spacing; no overlap; one focal; refine before adding decoration",
31
+ "subtleReference": "Monthly close / ledger credibility without literal spreadsheet chrome",
32
+ "templateConstraints": "Required brief slots stay bindable; flat absolute siblings; Theme owns color; never flatten copy into a generated poster"
33
+ },
34
+ "concepts": [
35
+ {
36
+ "id": "editorial-ledger",
37
+ "name": "Editorial ledger",
38
+ "rationale": "Use report-like credibility and one oversized metric",
39
+ "philosophyExpression": "Monumental metric left of center; rules as quiet rhythm; author attribution as a thin top rail",
40
+ "visualMotif": "ledger rules and folio marks",
41
+ "layout": "author rail at top, metric center-left, breakdown footer",
42
+ "hierarchy": "revenue > period/title > author > breakdown",
43
+ "typography": "display metric at roughly 4x body scale",
44
+ "colorStrategy": "warm canvas, dark ink, one green accent",
45
+ "paletteCandidates": [
46
+ {
47
+ "name": "Ocean Depths",
48
+ "presetId": "ocean-depths",
49
+ "brandHex": "#1A6B6B",
50
+ "mode": "light",
51
+ "bestFor": "Finance, consulting, trust-building metric cards",
52
+ "label": "teal editorial"
53
+ }
54
+ ],
55
+ "assetStrategy": "avatar plus CSS/SVG rules; no hero illustration",
56
+ "risks": ["long currency strings"]
57
+ },
58
+ {
59
+ "id": "terminal-scorecard",
60
+ "name": "Terminal scorecard",
61
+ "rationale": "Give an indie-hacker technical voice",
62
+ "philosophyExpression": "Same ledger philosophy expressed as a compact prompt header and centered status metric",
63
+ "visualMotif": "terminal prompt and status light",
64
+ "layout": "compact author header, centered metric, tabular footer",
65
+ "hierarchy": "revenue > growth > author",
66
+ "typography": "large grotesk metric with monospace metadata",
67
+ "colorStrategy": "near-black canvas and one electric accent",
68
+ "paletteCandidates": [
69
+ { "brandHex": "#0D9488", "mode": "dark", "label": "teal terminal" }
70
+ ],
71
+ "assetStrategy": "avatar and CSS grid",
72
+ "risks": ["neon contrast can become harsh"]
73
+ }
74
+ ],
75
+ "selectedConceptId": "editorial-ledger",
76
+ "selectionReason": "Best matches a trustworthy monthly report",
77
+ "themePreview": {
78
+ "name": "Ocean Depths",
79
+ "presetId": "ocean-depths",
80
+ "brandHex": "#1A6B6B",
81
+ "activeMode": "light",
82
+ "contrastPass": true,
83
+ "bestFor": "Finance, consulting, trust-building metric cards",
84
+ "themeTokensPath": "theme-tokens.json",
85
+ "userConfirmed": true
86
+ },
87
+ "surfacePreview": {
88
+ "kind": "gradient",
89
+ "userConfirmed": true,
90
+ "recipeId": "grad_001_warm-flame",
91
+ "name": "Warm Flame",
92
+ "provider": "webgradients",
93
+ "textSafeZone": "light_end",
94
+ "contrastAnchor": "#FAD0C4",
95
+ "placement": "full_bleed"
96
+ },
97
+ "assetPlan": [
98
+ {
99
+ "role": "avatar",
100
+ "source": "user_upload",
101
+ "required": true,
102
+ "description": "X profile avatar",
103
+ "treatment": "circular crop; retain face focal point"
104
+ },
105
+ {
106
+ "role": "background",
107
+ "source": "gradient_catalog",
108
+ "required": false,
109
+ "description": "Warm Flame wash under metric"
110
+ },
111
+ {
112
+ "role": "decorative",
113
+ "source": "css_svg",
114
+ "required": false,
115
+ "description": "ledger rules and small folio marks"
116
+ }
117
+ ]
118
+ }
119
+ ```
120
+
121
+ Rules:
122
+
123
+ - `text_brief` requires 2–3 concepts; `image_reference` permits one.
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.
126
+ - Optional philosophy fields: `subtleReference`, `templateConstraints` (recommended).
127
+ - Concepts must have unique IDs and all listed art-direction fields.
128
+ - Every concept requires `philosophyExpression` (how this layout expresses the shared philosophy in space).
129
+ - Concept `layout` / `hierarchy` / `typography` must be traceable to philosophy fields (documented rule; not NLP-checked).
130
+ - Concepts are spatial expressions of **one** shared philosophy — not unrelated slogans. Changing only colors is not a different concept.
131
+ - `selectedConceptId` must reference a concept.
132
+ - `selectionReason` is required.
133
+ - `assetPlan` may be empty when the concept intentionally uses typography only.
134
+ - Allowed asset roles: `background`, `hero`, `decorative`, `avatar`, `logo`, `icon`.
135
+ - Allowed sources: `user_upload`, `brand_kit`, `css_svg`, `gradient_catalog`, `asset_library`, `template_icon_catalog` (legacy alias `better_icons`), `external_photo`, `generated`, `none`.
136
+ - 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
+ - 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
+ - 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).
139
+ ## Companion `design-philosophy.md`
140
+
141
+ Human-readable twin of `design-plan.json` → `philosophy`. Recommended structure:
142
+
143
+ ```markdown
144
+ # Design Philosophy — <movementName>
145
+
146
+ ## Space
147
+ ...
148
+
149
+ ## Color
150
+ ...
151
+
152
+ ## Rhythm
153
+ ...
154
+
155
+ ## Composition
156
+ ...
157
+
158
+ ## Typography as accent
159
+ ...
160
+
161
+ ## Craft bar
162
+ ...
163
+
164
+ ## Template constraints
165
+ - Required brief slots stay bindable
166
+ - Flat absolute siblings only
167
+ - Theme owns color; never flatten copy into a generated poster
168
+ ```
169
+
170
+ ## `theme-tokens.json`
171
+
172
+ ```json
173
+ {
174
+ "schemaVersion": "theme_tokens_v2",
175
+ "brandHex": "#0D9488",
176
+ "scale": {
177
+ "50": "#F2FCFC",
178
+ "500": "#14E1D0",
179
+ "600": "#10BCAD",
180
+ "950": "#042F2B"
181
+ },
182
+ "semantic": {
183
+ "light": {
184
+ "canvas": "#FFFFFF",
185
+ "text": "#042F2B",
186
+ "accent": "#10BCAD",
187
+ "muted": "#10BCAD",
188
+ "primary": "#10BCAD",
189
+ "border": "#C6F5F1"
190
+ },
191
+ "dark": {
192
+ "canvas": "#042F2B",
193
+ "text": "#F2FCFC",
194
+ "accent": "#14E1D0",
195
+ "muted": "#51ECDF",
196
+ "primary": "#14E1D0",
197
+ "border": "#0B7F75"
198
+ }
199
+ },
200
+ "activeMode": "light",
201
+ "themeTokens": {
202
+ "colors": {
203
+ "canvas": "#FFFFFF",
204
+ "text": "#042F2B",
205
+ "accent": "#10BCAD",
206
+ "muted": "#10BCAD",
207
+ "primary": "#10BCAD",
208
+ "border": "#C6F5F1"
209
+ },
210
+ "fonts": { "heading": "Inter", "body": "Inter" },
211
+ "surfaces": { "radius": "12px", "shadow": "0 8px 24px rgba(0,0,0,.12)" },
212
+ "palette": {}
213
+ },
214
+ "themeTokensLight": {},
215
+ "themeTokensDark": {},
216
+ "contrast": [
217
+ {
218
+ "pair": "text/canvas",
219
+ "mode": "light",
220
+ "foreground": "#042F2B",
221
+ "background": "#FFFFFF",
222
+ "ratio": 16.2,
223
+ "wcagAA": true,
224
+ "wcagAAA": true
225
+ }
226
+ ],
227
+ "contrastPass": true
228
+ }
229
+ ```
230
+
231
+ Rules:
232
+
233
+ - `scale` must include shades `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `950`.
234
+ - `brandHex` must be `#` + 6 hex digits.
235
+ - `activeMode` is `light` or `dark`; `themeTokens` must match the active semantic palette.
236
+ - `themeTokens.colors` requires `canvas`, `text`, `accent`, `muted` (hex strings). Prefer also `primary` and `border` when co-creating v2.
237
+ - `themeTokens.fonts` requires `heading` and `body`.
238
+ - `themeTokens.surfaces` requires `radius` and `shadow`.
239
+ - `contrast` entries require `pair`, `mode`, `foreground`, `background`, `ratio`, `wcagAA`, `wcagAAA`.
240
+ - `contrastPass` must be `true` before authoring when co-creating a new theme.
241
+
242
+ ## `visual-qa.json`
243
+
244
+ ```json
245
+ {
246
+ "schemaVersion": "visual_qa_v2_1",
247
+ "draftId": "draft_123",
248
+ "iteration": 1,
249
+ "screenshotEvidence": "/absolute/path/to/studio-render.png",
250
+ "hardFailures": [],
251
+ "scores": {
252
+ "hierarchy": 18,
253
+ "composition": 13,
254
+ "spacingAlignment": 13,
255
+ "typography": 13,
256
+ "colorContrast": 9,
257
+ "assetRelevance": 8,
258
+ "contentResilience": 8,
259
+ "editability": 5
260
+ },
261
+ "total": 87,
262
+ "verdict": "pass",
263
+ "issues": [],
264
+ "changesMade": ["Increased metric size", "Reduced footer density"]
265
+ }
266
+ ```
267
+
268
+ Score maxima total 100. `pass` requires:
269
+
270
+ - inspectable `screenshotEvidence`
271
+ - `iteration` from 0 to 2
272
+ - no `hardFailures`
273
+ - each score within its maximum
274
+ - declared `total` equal to the calculated sum and at least 80
275
+
276
+ 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
+
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.
@@ -0,0 +1,52 @@
1
+ # External resources & Surface routing
2
+
3
+ Template Skill **orchestrates** discovery; EasySociable **owns** materialization.
4
+
5
+ ## Boundary
6
+
7
+ | Phase | Who | Tools |
8
+ |---|---|---|
9
+ | Discover photos | Host Agent MCPs | Pinterest, Unsplash, Pexels |
10
+ | Discover icons | Template product | MCP/CLI `search_icons` / `get_icon` → Gateway Icon Catalog (ADR-0023) |
11
+ | Discover gradients | Template product | MCP/CLI `gradients list\|search\|get` → Gateway |
12
+ | Materialize | Template Gateway only | Image import (R2 + Directus `Image`), icon materialize (`TemplateIconAsset`), inline gradient CSS, Draft update, Preview, Publish |
13
+
14
+ Template MCP/CLI must **not** expose Unsplash/Pexels/Pinterest search tools. Icons are **not** discovered via Better Icons MCP — use the internal catalog only.
15
+
16
+ ## Decision order
17
+
18
+ ```text
19
+ user_upload / brand_kit
20
+ → Design Primitive / CSS-SVG
21
+ → gradients (Gateway catalog)
22
+ → search_icons / get_icon (Gateway Icon Catalog)
23
+ → Pinterest / Unsplash / Pexels (host MCP)
24
+ → generated topic image (last resort)
25
+ → omit
26
+ ```
27
+
28
+ ## Degradation
29
+
30
+ | Missing | Agent behavior |
31
+ |---|---|
32
+ | Unsplash/Pexels/Pinterest MCP | Say so; offer flat / gradient / user upload; continue without photo |
33
+ | Icon Catalog / Gateway auth | Return Gateway error (`ICON_*` / `TEMPLATE_API_KEY_REQUIRED`); offer CSS/SVG mark or omit icon — do **not** install or call Better Icons |
34
+ | Gradients API / auth | Fall back to `flat` or simple CSS two-stop only if user supplies hexes; do not scrape WebGradients at runtime |
35
+ | Draft image import unavailable | Keep confirmed photo out of Publish path; do not embed temp URLs; ask user to upload in Studio |
36
+
37
+ ## Rights
38
+
39
+ - Record provider, source URL, creator, query, license/Attribution, rights state when importing images.
40
+ - Pinterest often starts `reference_only` / needs explicit publish-rights confirmation.
41
+ - Unsplash/Pexels follow provider license + Attribution rules.
42
+ - Gradients: record `provider` + `license` from catalog detail; inline CSS only.
43
+ - Icons: use `iconAssetId` + provenance from `get_icon`; Theme colors via `currentColor` / `--es-*` — never bake Theme hex into canonical SVG.
44
+ - Publish must reject unresolved rights (product gate); Skill must not pretend rights are cleared.
45
+
46
+ ## Modes
47
+
48
+ - Surface background image → default **`fixed`**
49
+ - Slot image → ask **`fixed`** or **`slot_default`**
50
+ - Rights state is orthogonal to mode
51
+
52
+ See `workflows/SURFACE_REVIEW.md` for the confirmation loop.
@@ -0,0 +1,25 @@
1
+ # Unified Gateway reference
2
+
3
+ The public executable is `easysociable`; the public MCP is the unified server.
4
+ Template operations use these command families:
5
+
6
+ ```bash
7
+ easysociable auth status --json
8
+ easysociable templates list --json
9
+ easysociable templates get --id <id> --json
10
+ easysociable templates create-draft --file ./draft.json --json
11
+ easysociable templates update --id <id> --file ./patch.json --json
12
+ easysociable templates validate --id <id> --json
13
+ easysociable templates publish --id <id> --json
14
+ easysociable icons search --query "arrow" --json
15
+ easysociable icons get --icon-id <id> --idempotency-key <key> --json
16
+ easysociable renders create --template-id <id> --slots ./slots.json --format png --idempotency-key render_1 --json
17
+ easysociable renders wait --id <id> --json
18
+ ```
19
+
20
+ All requests go through Gateway. The client receives public summaries, slot
21
+ contracts, stable Image references and render Manifests only. It never receives
22
+ AST, Binding Maps, private RenderPlans or provider credentials.
23
+
24
+ External Pexels/Unsplash/Pinterest MCPs remain optional host capabilities for
25
+ discovery. They are not auto-installed and are not EasySociable API paths.