@easysociable/cli 0.1.8 → 0.1.10

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 (93) hide show
  1. package/README.md +30 -9
  2. package/dist/easysociable.js +234 -98
  3. package/dist/easysociable.js.map +1 -1
  4. package/package.json +2 -2
  5. package/scripts/engine/migrate-split-vault.py +75 -0
  6. package/skills/ONBOARDING.md +19 -4
  7. package/skills/easysociable-content/SKILL.md +25 -9
  8. package/content-engine/scripts/fixture.test.mjs +0 -24
  9. package/content-engine/scripts/starter.mjs +0 -58
  10. package/content-engine/scripts/validate.test.mjs +0 -101
  11. package/content-engine/scripts/workbench.mjs +0 -140
  12. package/content-engine/starter/CLAUDE.md +0 -908
  13. package/content-engine/starter/accounts/README.md +0 -9
  14. package/content-engine/starter/accounts/_index.md +0 -31
  15. package/content-engine/starter/accounts/overrides/README.md +0 -3
  16. package/content-engine/starter/engine.json +0 -23
  17. package/content-engine/starter/exports/README.md +0 -28
  18. package/content-engine/starter/hits/README.md +0 -5
  19. package/content-engine/starter/hits/_index.md +0 -30
  20. package/content-engine/starter/hits/_template.md +0 -46
  21. package/content-engine/starter/hits/entries/README.md +0 -3
  22. package/content-engine/starter/inbox/README.md +0 -9
  23. package/content-engine/starter/inbox/_index.md +0 -24
  24. package/content-engine/starter/inbox/entries/README.md +0 -3
  25. package/content-engine/starter/needs/README.md +0 -38
  26. package/content-engine/starter/needs/_index.md +0 -31
  27. package/content-engine/starter/needs/_template.md +0 -24
  28. package/content-engine/starter/needs/entries/README.md +0 -5
  29. package/content-engine/starter/platforms/README.md +0 -19
  30. package/content-engine/starter/platforms/ig.md +0 -69
  31. package/content-engine/starter/platforms/instagram.md +0 -5
  32. package/content-engine/starter/platforms/linkedin.md +0 -72
  33. package/content-engine/starter/platforms/threads.md +0 -69
  34. package/content-engine/starter/platforms/tiktok.md +0 -71
  35. package/content-engine/starter/platforms/x.md +0 -78
  36. package/content-engine/starter/platforms/xiaohongshu.md +0 -19
  37. package/content-engine/starter/products/README.md +0 -38
  38. package/content-engine/starter/products/_index.md +0 -25
  39. package/content-engine/starter/products/_template.md +0 -56
  40. package/content-engine/starter/products/entries/P-001-easysociable.md +0 -150
  41. package/content-engine/starter/products/entries/P-002-content-engine.md +0 -136
  42. package/content-engine/starter/profiles/_index.md +0 -16
  43. package/content-engine/starter/profiles/default/README.md +0 -17
  44. package/content-engine/starter/profiles/default/audience.md +0 -38
  45. package/content-engine/starter/profiles/default/boundaries.md +0 -14
  46. package/content-engine/starter/profiles/default/expression.md +0 -18
  47. package/content-engine/starter/profiles/default/handles.md +0 -8
  48. package/content-engine/starter/profiles/default/keywords.md +0 -31
  49. package/content-engine/starter/profiles/default/lanes.md +0 -12
  50. package/content-engine/starter/profiles/default/pillars.md +0 -33
  51. package/content-engine/starter/profiles/default/stories.md +0 -15
  52. package/content-engine/starter/profiles/default/voice.md +0 -38
  53. package/content-engine/starter/published/_index.md +0 -20
  54. package/content-engine/starter/raw/README.md +0 -4
  55. package/content-engine/starter/raw/_index.md +0 -12
  56. package/content-engine/starter/recommendations/README.md +0 -21
  57. package/content-engine/starter/recommendations/_index.md +0 -21
  58. package/content-engine/starter/recommendations/_template.md +0 -44
  59. package/content-engine/starter/runs/README.md +0 -22
  60. package/content-engine/starter/runs/_index.md +0 -41
  61. package/content-engine/starter/runs/_template/brief.md +0 -76
  62. package/content-engine/starter/runs/_template/draft.md +0 -11
  63. package/content-engine/starter/runs/_template/editor.md +0 -18
  64. package/content-engine/starter/runs/_template/feedback.md +0 -15
  65. package/content-engine/starter/runs/_template/idea.md +0 -27
  66. package/content-engine/starter/runs/_template/pack.md +0 -55
  67. package/content-engine/starter/runs/_template/packet.md +0 -31
  68. package/content-engine/starter/runs/_template/rubric.md +0 -19
  69. package/content-engine/starter/swipe/_index.md +0 -27
  70. package/content-engine/starter/swipe/_template.md +0 -36
  71. package/content-engine/starter/topics/README.md +0 -21
  72. package/content-engine/starter/topics/_index.md +0 -51
  73. package/content-engine/starter/topics/_template-item.md +0 -106
  74. package/content-engine/starter/topics/items/README.md +0 -4
  75. package/content-engine/starter/topics/scoring.md +0 -255
  76. package/content-engine/starter/wiki/README.md +0 -13
  77. package/content-engine/starter/wiki/atoms/_index.md +0 -23
  78. package/content-engine/starter/wiki/atoms/_template.md +0 -31
  79. package/content-engine/starter/wiki/claims/_index.md +0 -26
  80. package/content-engine/starter/wiki/claims/_template.md +0 -38
  81. package/content-engine/starter/workbench/README.md +0 -17
  82. package/content-engine/workbench/__pycache__/build.cpython-310.pyc +0 -0
  83. package/content-engine/workbench/build.py +0 -1467
  84. package/content-engine/workbench/serve.py +0 -53
  85. package/content-engine/workbench/template.html +0 -2683
  86. /package/{content-engine/scripts → scripts/engine}/contracts.mjs +0 -0
  87. /package/{content-engine/scripts → scripts/engine}/export-contracts.mjs +0 -0
  88. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/draft.md +0 -0
  89. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/idea.md +0 -0
  90. /package/{content-engine → scripts/engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
  91. /package/{content-engine/scripts → scripts/engine}/validate-export.mjs +0 -0
  92. /package/{content-engine/scripts → scripts/engine}/validate-pack.mjs +0 -0
  93. /package/{content-engine/scripts → scripts/engine}/validate-run.mjs +0 -0
@@ -1,908 +0,0 @@
1
- # Content Engine — Agent operating manual
2
-
3
- This folder is the local **Content Engine** for EasySociable.
4
-
5
- **Human interface:** conversation only. The user does **not** edit markdown by hand. Observatory UI: `workbench/` at `http://127.0.0.1:8765/workbench/`.
6
- **Agent interface:** you create/update files; always return a structured result card in chat. After markdown writes, run `python3 workbench/build.py` (leave `serve.py` running if already up).
7
-
8
- ## Defaults (v1)
9
-
10
- - Folder tree: **English** (`Content Engine/`). Do not ask language.
11
- - Default **account:** first **active** handle in `accounts/_index.md` (starter: `your-handle` — replace it)
12
- - **开一单:** do **not** silent-default platform — **ask**; multi-select → **N runs**
13
- - Do not invent metrics, customers, or quotes the user did not provide
14
-
15
- ### Resolve account → profile (required)
16
-
17
- 1. Read **`accounts/_index.md`** for the handle (default: first active row)
18
- 2. Get `profile_id`, `voice`, `platforms`, `default_platform`, `overrides`
19
- 3. Load **`profiles/<profile_id>/pillars.md`** + **`audience.md`** (core + current platform section)
20
- 4. Voice: if account `voice` is `profile` or empty → **`profiles/<profile_id>/voice.md`** (Identity + **Experience** + **Values** + Persona); else load the explicit path. Never invent bio facts not in Identity / Experience.
21
- `boundaries.md`: missing → **hard-gate fail**. Write empty starter (`## Not covering` / `## Never claim` headings), then interview; **never invent boundaries**.
22
- `stories.md` / `expression.md`: missing → `profile: partial`, continue.
23
- Do not invent bio / stories / values absent from those files. Topics listed in `boundaries.md` → stop; do not write.
24
- 5. If `overrides` is **non-empty**, read that path (e.g. `accounts/overrides/<handle>.md`) and apply last
25
- 6. Craft: **always** load `platforms/<platform>.md` for the active platform (see `platforms/README.md` for id → file; `instagram` → `ig.md`). Missing file → stop and tell the user; do not invent craft rules.
26
- 7. Catalog filter: swipe/atoms/claims where `platforms` matches **and** (`profiles` is `*` **or** contains `profile_id`)
27
- 8. If a Topic or draft mentions an offer, load `products/_index.md` and the
28
- cited `products/entries/P-*.md`. Never invent product pricing, entitlements,
29
- proof, or outcomes. Product fit is optional; educational content may have no
30
- product.
31
-
32
- ## File map
33
-
34
- | Path | Role |
35
- |------|------|
36
- | `CLAUDE.md` | Operating manual |
37
- | `profiles/_index.md` | Profile registry |
38
- | `profiles/<id>/pillars.md` | Topic pillars (what to talk about) |
39
- | `profiles/<id>/audience.md` | Readers + platform emphasis |
40
- | `profiles/<id>/voice.md` | Identity + Experience + Values + Persona |
41
- | `profiles/<id>/stories.md` | Story inventory (cite or none) |
42
- | `profiles/<id>/boundaries.md` | Creator must-avoid (Not covering / Never claim) |
43
- | `profiles/<id>/expression.md` | Expression likes / dislikes |
44
- | `profiles/<id>/lanes.md` | Publishing lanes; distinct from pillars |
45
- | `profiles/<id>/keywords.md` | Search recipes; scan may stage `hits/` |
46
- | `profiles/<id>/handles.md` | ≤8 ally/foil/competitor handles |
47
- | `hits/_index.md` | Research triage (not Topics) |
48
- | `accounts/_index.md` | handle → profile, platforms, voice, overrides |
49
- | `accounts/overrides/<handle>.md` | Optional account deltas |
50
- | `platforms/*.md` | Platform craft only |
51
- | `inbox/_index.md` | Capture registry |
52
- | `inbox/entries/C-*.md` | Per-capture working notes |
53
- | `needs/_index.md` | Audience-quote registry |
54
- | `needs/entries/N-*.md` | Per-need quote + sightings |
55
- | `products/_index.md` | Owned product registry and lifecycle |
56
- | `products/entries/P-*.md` | Owned product facts, boundaries, pricing and claims |
57
- | `recommendations/_index.md` | Third-party tool/product registry and Profile associations |
58
- | `recommendations/R-*.md` | Review subject facts, evidence and disclosure |
59
- | `raw/_index.md` | Authoritative source registry |
60
- | `raw/*.md` | Source bodies |
61
- | `topics/_index.md` | Topic queue (one row per topic + `item` + src engagement) |
62
- | `topics/items/T-*.md` | Opportunity card (human half) + Score/Trace appendix |
63
- | `topics/scoring.md` | Scout gate + opportunity five-dim (context/audience/conflict/insight/evidence) |
64
- | `swipe/_index.md` | Structures (+ `profiles` column) |
65
- | `wiki/atoms/_index.md` | Atoms (+ `profiles`) |
66
- | `wiki/claims/_index.md` | Claims (+ `profiles`) |
67
- | `runs/_index.md` | Job queue (one row per **platform run**) |
68
- | `runs/<slug>/` | One platform draft → pack → feedback |
69
- | `published/_index.md` | One row per **shipped URL** (one run → usually one row) |
70
- | `exports/<slug>/` | Rendered images for that run (optional `<platform>/` subfolder) |
71
-
72
- ## Routing
73
-
74
- | User intent | Action |
75
- |-------------|--------|
76
- | capture / 记一下 (+ link) | **§ Capture** only — **not** topics by default |
77
- | 记需求 / 用户原话 / 评论导出 | **§ Needs** only |
78
- | 加关键词 / 更新关键词库 | Edit `profiles/<id>/keywords.md` (**ask profile** if unset) |
79
- | 从需求生成关键词 / 生成 listen\|search\|ask 词 | **§ Keywords · Generate** (chat → confirm → write) |
80
- | 加/改 handles | Edit `profiles/<id>/handles.md`; keep **≤8** |
81
- | 扫关键词 / 扫 K-xx / 看 @handle | **§ Keywords** scan (**listen** default) → **§ Hits** |
82
- | 路由 Hit / H-xx | **§ Hits** → Needs or Capture+library / discard |
83
- | **扫需求选题** | **§ Topics** from `needs/` where `status=captured`; max 5 `produce` |
84
- | 扫 inbox 选题 | **§ Topics** — from captures without topic yet (max 5) |
85
- | 生成 topic (no source specified) | **§ Topics** — offer captured needs or ask which explicit input to use |
86
- | 链接直接选题 / 把 C-xxx 做成选题 | **§ Topics** — create T- (may link capture) |
87
- | 采访我 / 完善人设 / interview me / who am I as a creator / 建立 profile | **§ Interview** — persist after each dimension; no slideshow |
88
- | 开一单 / 用 T-xxx 开一单 | **Hard gate first**, then **§ Open a run** — **ask platform(s)** if unset; multi-select → **N runs** (bind `topic_id` if from T-) |
89
- | Quick draft | Resolve profile; selection; draft in chat |
90
- | 收成 swipe/atom/claim | **§ Library ingest** after approval |
91
- | 选题后同意进 inbox | Capture that URL/C-link then optional library offer |
92
- | Post URL after ship | feedback + **§ Published index** |
93
- | 复盘 / 批准晋级 | Claims promote + published index |
94
- | Update pillars/audience | Edit **`profiles/<id>/…`** |
95
- | 更新产品 / 产品库 | Edit **`products/`**; keep dates and source of truth |
96
- | 推荐 / 评测第三方产品 | Edit **`recommendations/`**; record evidence and disclosure |
97
- | Update account binding | Edit **`accounts/_index.md`** |
98
- | 出图 | **Hard gate first**, then **§ PagePack + render**. Fail → list missing files; no handoff unless user says **强制继续** / **force continue** |
99
-
100
- ---
101
-
102
- ## § Capture (inbox + raw indexes)
103
-
104
- ### When
105
-
106
- User stores an idea, link, competitor structure, or source — not a pure Q&A.
107
-
108
- ### Always write (scheme B)
109
-
110
- 1. **`inbox/entries/C-YYYYMMDD-XX.md`** — working notes (our understanding; not necessarily full source text)
111
- 2. **Row at top of `inbox/_index.md`** — registry (id, type, one_liner, profile, entry path, raw path, library, status)
112
-
113
- Id: `C-YYYYMMDD-XX` sequential per day (`01`, `02`, …).
114
- Default `profile`: current account’s `profile_id`.
115
-
116
- ### Also write raw when
117
-
118
- - URL worth revisiting, multi-step structure, media, or user says important
119
-
120
- Then:
121
-
122
- 1. Body: `raw/YYYY-MM-DD-short-slug.md` (authoritative text/structure/media links)
123
- 2. Row in **`raw/_index.md`** with `capture_id`
124
- 3. Set inbox row `raw` column to that file
125
-
126
- ### Do not
127
-
128
- - Use deprecated `inbox/capture.md` (removed)
129
- - Silent-write swipe/atoms/claims
130
- - Treat capture as a finished run
131
- - Reply “saved” without **Capture Card**
132
- - Invent facts not in the user message / source
133
-
134
- ### entry file (minimal shape)
135
-
136
- ```markdown
137
- ---
138
- id: C-YYYYMMDD-XX
139
- date: YYYY-MM-DD
140
- type: structure | link | insight | product | other
141
- profile: default
142
- ---
143
-
144
- # C-… — short title
145
-
146
- ## One-liner
147
- ## User intent / source
148
- ## Key points (our notes)
149
- ## Links (raw if any)
150
- ## Status
151
- ```
152
-
153
- ### Capture Card (chat)
154
-
155
- ```text
156
- ✅ Captured [C-YYYYMMDD-XX]
157
-
158
- 【One-liner】 …
159
- 【Type】 …
160
- 【Profile】 (resolved profile_id)
161
- 【Key points】
162
- - …
163
-
164
- 【Stored】
165
- - inbox/_index: yes
166
- - entry: inbox/entries/C-….md
167
- - raw: no | raw/….md + raw/_index
168
-
169
- 【Refine】
170
- A) OK as stored
171
- B) Refine notes
172
- ```
173
-
174
- ### Library offer (required if type is structure or link)
175
-
176
- ```text
177
- 【入库?(需点头)】
178
- 1) 不入库 — index library=none
179
- 2) 收成 swipe
180
- 3) 收成 atom (type: hook|reframe|proof|process|cta|other)
181
- 4) 收成 claim
182
- 5) 组合 …
183
-
184
- Reply number(s) or 不入库.
185
- ```
186
-
187
- On approval: create catalog files per **§ Library ingest**, set inbox `library` column (e.g. `swipe:S2`).
188
- Path A (capture): **no** engagement gates on *your* posts.
189
-
190
- Optional: if user also says「同时选题/打分」, run **§ Topics** for this capture.
191
-
192
- ---
193
-
194
- ---
195
-
196
- ## § Products (offer facts)
197
-
198
- ### When
199
-
200
- User defines, updates, prices, retires, or asks about a product or offer.
201
-
202
- ### Role
203
-
204
- Products are the **supply-side fact layer**. They are not audience needs,
205
- external discoveries, or content opportunities.
206
-
207
- ```text
208
- Need (demand evidence) + Profile (identity) + optional Product (offer facts)
209
- → Topic (editorial judgment)
210
- → Run
211
- ```
212
-
213
- ### Rules
214
-
215
- - Read the cited `products/entries/P-*.md` before using product facts in a
216
- Topic, brief, draft, CTA, or product answer.
217
- - A Topic may cite `product_ids: none`; do not force a product connection.
218
- - A Topic may cite `recommendation_ids: none`; recommendations are third-party
219
- review subjects, not owned products.
220
- - `product_fit` describes relevance, not a readiness verdict. Product fit never
221
- replaces `need_ids`, evidence, audience, or opportunity scoring.
222
- - Do not turn a product promise into a Need quote. Do not turn a Need quote
223
- into a product capability.
224
- - Keep exact pricing and entitlements in the dated product entry. Do not copy
225
- stale prices into other files.
226
- - Do not invent proof, customers, outcomes, metrics, or testimonials.
227
-
228
- ### Product fit
229
-
230
- Use one of:
231
-
232
- | fit | Meaning | Typical CTA |
233
- |-----|---------|-------------|
234
- | `direct` | The Topic directly addresses a problem the product solves | `educate` / `invite` / `sell` |
235
- | `adjacent` | The Topic builds context but is not a product pitch | `educate` / `mention` |
236
- | `none` | No honest product connection is needed | `none` |
237
-
238
- Product fit is written on the Topic human card and inherited by the Brief.
239
- For third-party reviews, use `recommendation_ids`, not `product_ids`. Load the
240
- recommendation entry and disclose affiliate, sponsorship, or other commercial
241
- relationships before drafting.
242
-
243
- ### Topic generation modes
244
-
245
- | mode | Required inputs |
246
- |------|-----------------|
247
- | `demand` | Needs + Profile |
248
- | `demand_to_offer` | Needs + Product + Profile |
249
- | `demand_to_review` | Needs + Recommendation + Profile |
250
- | `review` | Recommendation + Profile + evidence |
251
- | `offer_education` | Product + Profile + mechanism |
252
- | `profile_thesis` | Profile + Pillar |
253
-
254
- **Mode pick (hard):** Before any `produce` Topic write (扫需求选题 / 做成选题 / 生成 topic / 把 N-|C- 做成选题), **ask the user to choose `generation_mode`**. Recommend `demand` when the input is Need-led; do **not** silently assume. Enforce that mode’s required inputs. Product or Recommendation presence never proves audience demand and never raises a Topic to `ready` by itself.
255
-
256
- ---
257
-
258
- ## § Topics (Opportunity evaluation)
259
-
260
- **Role:** Evaluate **Content Opportunities** — whether a topic deserves to exist as content. Does not replace capture or runs.
261
- **Principle:** Topics are not titles. They are a judgment card the content owner can read in one minute. Five-dim scores are a gate in the appendix, not the reading surface.
262
-
263
- ### Layout
264
-
265
- | Path | Role |
266
- |------|------|
267
- | `topics/scoring.md` | Scout → opportunity **15/20/25/25/15** (context/audience/conflict/insight/evidence); ready = opp≥**7.5** **and** aud≥**6** |
268
- | `topics/_index.md` | Queue: one row per topic, **`item`** link, **`src_*` engagement** |
269
- | `topics/items/T-YYYYMMDD-XX.md` | Decision card (summary + judgment) + Score/Trace/Constraints (appendix) |
270
- | `topics/_template-item.md` | Template |
271
-
272
- ### Defaults
273
-
274
- - Scout first: `purpose` = `discard` | `library` | `produce`; `scout_label` = `demand` | `ally` | `foil` | `craft_only`. Needs default `scout_label=demand`.
275
- - Opportunity dims (produce only): `context` `audience` `conflict` `insight` `evidence` (0–10) → `opp_score`. Reasons live in the readable judgment layer, not in a score-table note column.
276
- - `ready` requires **opp_score ≥ 7.5 and audience ≥ 6**
277
- - `src_likes` / `src_replies` / `src_bookmarks` (+ views if known) + `engagement_at` on **index** when source is external
278
- - Do **not** fold `src_*` into opp_score; among **ready** only, prefer replies/bookmarks over views
279
- - **Language (hard):** Readable judgment + `one_liner` + Decision Card body = profile public language from `voice.md` **Language** (else pillars “Primary public language”, else `engine.json` locale). Verbatim Needs/Capture quotes stay untranslated. Operator chat may add a short gloss in another language; the Topic file and `ready` card body do not. Wrong-language prose → fix before `ready`.
280
-
281
- ### Signal paths
282
-
283
- | User intent | inbox/raw | topics |
284
- |-------------|-----------|--------|
285
- | `记一下` + URL | **Yes** (default) | Only if also asked to score as topic |
286
- | `扫需求选题` | **Default NO** | Scout + score ≤5 produce from `needs/` `status=captured`; `source_type=need`; set `need_ids`; **never** put `N-` in `capture_id`. After a `produce` T- is written, set those `N-` to `promoted` and append the T- on `topic_ids` (index + entry). Discard / library: leave `captured` or `retired` |
287
- | `扫 inbox 选题` | Existing only | Scout + score ≤5 produce; set `capture_id`; skip captures already linked to a T- |
288
- | `把 C-xxx 做成选题` | Keep | Create T- with `capture_id` (still Scout + opportunity score) |
289
- | `链接直接选题` | Default NO unless user agrees capture | Create T- + src engagement |
290
- | `把 T-xx 收进 inbox` | Yes for that source | Backfill `capture_id` on T- |
291
-
292
- ### Create topic steps
293
-
294
- **Input gate:** A Topic must have an explicit input. Accept: user idea/brief, Capture `C-…`, Need `N-…`, Product `P-…`, Recommendation `R-…`, or a profile thesis. If the user only says “generate a topic” without naming a source:
295
-
296
- 1. If needs exist with `status=captured`, offer **扫需求选题**.
297
- 2. Otherwise ask which explicit input to use.
298
-
299
- 0. Resolve profile **Language** (`voice.md` → pillars → `engine.json` locale).
300
- 1. Hard filters (`scoring.md`); else skip.
301
- 2. **Scout gate** — set `purpose` + `scout_label`; if `discard`, do not create T-. Needs-sourced default `scout_label=demand` (ally/foil/craft_only still allowed when honest).
302
- 3. **Mode pick** — if proceeding toward `produce`, **ask** `generation_mode` (six modes). Recommend `demand` for Need-led input; wait for user choice. Do not write a `produce` T- before the choice. Validate required ids for that mode.
303
- 4. If `produce` (or user forces score):
304
- a. Write the **decision card** first (`topics/_template-item.md` upper half), in profile Language: Verdict, Why this status, Who it’s for, Core judgment, Next step, then What problem / What they believe / What cut / Why now / What should change / Based on / Gaps / Suggested form. Keep the summary short; no enum lists, heat, or weighted arithmetic in the readable layer. Set frontmatter `generation_mode` to the chosen mode.
305
- b. Score all 5 opportunity dims (0–10) → `opp_score`. Put **numbers only** in `## Score`. Do not repeat the card as table notes.
306
- c. Fill `## Trace` (ids, src heat) and `## Constraints` (writer must-nots). Write `topics/items/T-….md`.
307
- 5. If `library`: optional light item with `status: library`, or capture offer only. Source needs stay `captured` (or `retired` if the user discards).
308
- 6. Add row on `topics/_index.md` (`item` + `src_*` when external). `one_liner` = the card’s core-judgment sentence, same language.
309
- 7. If this T- was `produce` from `N-` ids: update each `needs/_index.md` row + entry to `status=promoted` and `topic_ids` containing this T-. Skip if no T- was written (`discard`).
310
- 8. Output the **Decision Card** in chat — same shape and language as the file’s readable layer, not a score walkthrough. Optional operator gloss in another language is chat-only.
311
-
312
- **Important:** “What do they believe now?” must name the false belief. If you cannot, conflict cannot score above 5. Brief inherits the readable judgment layer, not the Score table.
313
-
314
- ### Decision Card
315
-
316
- Paste the decision summary and readable judgment sections. Do not walk five scores in the main body.
317
-
318
- ```text
319
- 📋 Decision card T-YYYYMMDD-XX
320
- 【Verdict】 ready | backlog | parked
321
- 【Why this status】 …
322
- 【Who it’s for】 …
323
- 【Core judgment】 …
324
- 【Next step】 open a run / fill needs / fill evidence / re-angle / kill
325
- 【What problem】 …
326
- 【What they believe】 believe X → actually Y
327
- 【What cut】 …
328
- 【Why now】 …
329
- 【After reading】 before … → after …
330
- 【Based on】 …
331
- 【Gaps】 …
332
- 【Suggested form】 …
333
- ```
334
-
335
- ### Topic → run
336
-
337
- On `用 T-xxx 开一单`: **ask platform(s)** if unset (multi-select OK). Create **one run per platform**, same `topic_id`, prefill selection per platform, mark topic `promoted` + list run ids on `topics/_index` `run` column.
338
-
339
- ### Do not (Topics)
340
-
341
- - Create a Topic from a Hit, a scan, or from heat alone
342
- - Silently pick `generation_mode` (always ask before `produce`)
343
- - Skip Scout gate or opportunity scoring on `produce` topics
344
- - Skip the decision card readable layer on `produce`
345
- - Put `N-` in `capture_id` (needs go in `need_ids` only)
346
-
347
- ---
348
-
349
- ## § Swipe / atom library
350
-
351
- - **Catalog:** `swipe/_index.md` / `wiki/atoms/_index.md` are the selection entrypoints (Approach B).
352
- - **Hit-status:** `trial` | `working` | `dead` (not claim epistemology).
353
- - **Hits cache:** index columns `n` `win` `loss` from **our** `published.result`.
354
- - **Use history:** `published/_index.md` (columns `swipe` / `atoms`). **Do not** put an Evidence table in swipe/atom files.
355
- - **New item:** template + index row; default `trial`, n=win=loss=0.
356
- - **From capture / run:** only via **§ Library ingest**. Never silent seed from runs.
357
-
358
- ---
359
-
360
- ## § Interview
361
-
362
- Triggers: 采访我 / 完善人设 / interview me / who am I as a creator / 建立 profile.
363
-
364
- Follow `easysociable-content/workflows/INTERVIEW.md` for questions. Persist after each dimension; do not wait until the end.
365
-
366
- - Append `## Experience` / `## Values` to existing `voice.md` if those headings are missing. Do not rewrite filled Identity rows.
367
- - Missing `boundaries.md` → write empty starter, then interview. **Never invent boundaries.**
368
- - Do not scan the watchlist. Do not create a slideshow. Do not ingest needs in this section.
369
-
370
- ### Hard gate (refuse 出图 / PagePack / `create_run`)
371
-
372
- Identity **only** Role / What I build / Point of view — no `(fill)`, non-empty. Public handle MAY stay `(fill)`. `boundaries.md` exists with Not covering **and** Never claim non-empty. If `needs/` exists, also `needs/_index.md` ≥ 3 `N-` rows; if `needs/` is absent, skip that count.
373
-
374
- Fail → list missing files; stay here. User must say **强制继续** / **force continue**. Optional check:
375
-
376
- ```bash
377
- easysociable engine validate --root . --require-knowledge
378
- ```
379
-
380
- ### Completion
381
-
382
- Hard gate vs first-session (`profile: partial`) vs complete seven dimensions (`profile: complete`) — same table as INTERVIEW.md. Experience / Values / expression are not the hard gate. Needs hard gate is ≥ **3** original quotes; first-session **target** is **5**.
383
-
384
- ---
385
-
386
- ## § Keywords & handles
387
-
388
- `keywords.md` is **three-track**: `listen` (social → Hits), `search` (SEO), `ask` (GEO questions).
389
- `handles.md` ≤8 ally/foil/competitor.
390
-
391
- **Generate:** from Needs/audience/pillars → chat candidates (max 10) → user confirm → append row with `track` + `seed_from`.
392
- **Scan「扫关键词」:** `track=listen` + `active` only (unless user names other ids). Stage **§ Hits**; never Topic; never invent heat/quotes.
393
- **search/ask:** not default social scan. Volume/kd optional on search only.
394
-
395
- ## § Hits (research triage)
396
-
397
- **Role:** Sort research hits → **need** | **library** (swipe/atom via Capture+ingest) | **discard**. Not a Topic queue.
398
-
399
- | Path | Role |
400
- |------|------|
401
- | `hits/_index.md` | Registry |
402
- | `hits/_template.md` | Entry shape |
403
- | `hits/entries/H-*.md` | Per-hit files |
404
-
405
- Id `H-YYYYMMDD-XX`. Status: `triage` → `routed_need` | `routed_library` | `discarded`.
406
-
407
- ```text
408
- 🔎 Hit H-…
409
- 【Keyword】 K-xx
410
- 【Source】 @handle · url
411
- 【Kind】 author_post | comment | thread
412
- 【Signal】 demand_language | structure | foil | mixed | noise
413
- 【Heat】 likes … · replies … · bookmarks … · views … @ date
414
- 【Excerpt】 verbatim
415
- 【Suggest】 need | library | discard
416
- ```
417
-
418
- On scan: `keyword_id` + `src_*` when known. Route need → **§ Needs**. Route library → **§ Capture** + library offer. Never Hit → Topic.
419
-
420
- ---
421
-
422
- ## § Needs (audience quotes)
423
-
424
- Triggers: 记需求 / 用户原话 / 评论导出 / capture audience quotes / user needs.
425
- Hits → Needs **only after route confirm** (**§ Hits**).
426
- 扫需求选题 → **§ Topics** (this section only writes `N-` records).
427
-
428
- Follow `easysociable-content/workflows/NEEDS.md` when this engine's copy of the workflow is the newer one; this section wins if both exist.
429
-
430
- ### Layout
431
-
432
- | Path | Role |
433
- |------|------|
434
- | `needs/_index.md` | Quote registry |
435
- | `needs/entries/N-YYYYMMDD-XX.md` | Verbatim quote + sightings + optional gloss |
436
- | `needs/_template.md` | Entry shape |
437
-
438
- ### Status machine (only these words)
439
-
440
- ```text
441
- captured → just written, or still captured after a synonym merge (frequency ≥ 1)
442
- promoted → and only when a T- exists whose need_ids contain this N-; topic_ids lists that T-
443
- retired → user discarded
444
- ```
445
-
446
- - Never `clustered`. Merge is not a status.
447
- - Never mark `promoted` without that `T-`. `topic_ids` non-empty ≡ `promoted`.
448
- - After § Topics writes a `produce` T- from this `N-`, flip this row + entry to `promoted` and append the T- on `topic_ids`. Discard / library stay `captured` or `retired`.
449
- - Scan input: `status=captured` (`topic_ids` empty). Max 5 `produce`.
450
- - Quote cell = verbatim. Gloss is optional and separate.
451
- - Do not invent quotes. Do not treat watchlist hooks as needs.
452
- - `N-` never goes in topic `capture_id`.
453
-
454
- ### Ingest
455
-
456
- 1. New entry from `_template.md` + row at top of `_index.md`.
457
- 2. Chat card:
458
-
459
- ```text
460
- ✅ Need N-YYYYMMDD-XX
461
- 【Quote】 …
462
- 【Source】 comment | dm | consult | faq | student | other
463
- 【Frequency】 1
464
- 【Stored】 needs/_index + needs/entries/N-….md
465
- 【Merge】 new | merged into N-… (frequency now k, status still captured)
466
- ```
467
-
468
- 3. Synonym merge: propose → user yes → same `N-` stays `captured`, `frequency += 1`, append sighting. Retire a mistaken duplicate.
469
-
470
- Hard gate: `needs/_index.md` ≥ **3** `N-` rows once `needs/` exists (empty index fails). Target **5**. Prefer scanning needs before inbox.
471
-
472
- ---
473
-
474
- ## § Open a run
475
-
476
- ### When
477
-
478
- User wants a tracked job: "开一单", "open a run", "按完整流程", or a multi-step post with gates.
479
-
480
- **Hard gate first** (same as § Interview). Fail → list missing files; do not create `runs/<slug>/` unless **强制继续** / **force continue**.
481
-
482
- ### Model (one platform = one Run)
483
-
484
- - **One folder = one platform draft** (native rewrite).
485
- - **Same Topic, different platforms** → **N runs**, shared `topic_id` — **not** one folder with many platform sections.
486
- - `idea.md`: `primary_platform` = this run’s platform; `platforms` = **same single value** (column kept for index compat).
487
- - `draft.md`: copy for **this platform only**.
488
- - Image deck: **`pack.md`** (or `pack-<platform>.md`); pixels under **`exports/<slug>/`**.
489
- - Ship → one `published/_index` row for this `run_id`.
490
- - Cross-platform progress lives on the **Topic** (`run` column lists all RUN ids), not inside one run.
491
-
492
- ### Platform gate (required before folder create)
493
-
494
- 1. User already named platform(s) → use them.
495
- 2. Else **stop and ask a required multi-select platform question**. Offer the account’s `platforms` from `accounts/_index` plus any supported platforms the user may name: `x`, `linkedin`, `instagram`, `tiktok`, `threads`, `xiaohongshu`. The user must be able to select one or more.
496
- 3. Do not create a folder, row, brief, or draft before the platform selection is answered.
497
- 4. **Do not** silently default to `x` when opening a run (default `x` still applies to other flows, e.g. watchlist filter).
498
- 5. **N platforms selected → N runs** (same topic/goal/pillar; independent platform craft, brief, draft, editor, rubric, and ship state).
499
- 6. Slug: include the platform when N>1 or always OK — e.g. `2026-08-26-angle-x`, `…-linkedin`.
500
-
501
- ### Load platform craft (required — every run, every draft stage)
502
-
503
- For **each** run, before brief / packet / draft / editor / rubric / pack:
504
-
505
- 1. Resolve craft file via `platforms/README.md` (`x` → `x.md`, `instagram`/`ig` → `ig.md`, …).
506
- 2. **Read** that file end-to-end. Apply length, hooks, anti-slop, quality checklist.
507
- 3. Also load profile `audience.md` **core + this platform’s section**.
508
- 4. Cite the craft path in `brief.md` / `packet.md` (not hardcoded `platforms/x`).
509
- 5. **Do not** paste another platform’s copy unchanged. Sibling runs each re-read their own craft file.
510
- 6. If the craft file is missing → ask user / create stub; **do not draft** from memory.
511
-
512
- ### State machine (do not skip)
513
-
514
- ```text
515
- RUN_OPEN → BRIEF_WAIT → DRAFTED → EDIT_WAIT
516
- → SCORED → SHIP|HOLD → READY_TO_POST
517
- → PUBLISHED feedback
518
- ```
519
-
520
- Also mirror high-level status on **`runs/_index.md`**:
521
- `open` → `brief` → `draft` → `scored` → `ready` → `published` | `hold` | `killed`.
522
- (`partial` = **legacy** only; do not use for new multi-platform planning.)
523
-
524
- Human gates (chat only):
525
-
526
- 1. **简报 OK** / Brief OK
527
- 2. **编辑 OK** / Editor OK
528
- 3. After SHIP: user posts **this** platform, then URL + result → feedback + published row
529
- 4. If images: **图 OK** after render (when skill available)
530
-
531
- ### Folder setup
532
-
533
- 1. Resolve platform list (gate above). For **each** platform:
534
- 2. **Load** `platforms/<platform>.md` (required; see above).
535
- 3. Create `runs/YYYY-MM-DD-short-slug[-platform]/` from `runs/_template/`.
536
- 4. Fill `idea.md` (pillar, **platform**, **selection ids**, optional `topic_id`).
537
- 5. **Append row** on `runs/_index.md` (`status=open`).
538
- 6. If from **T-…**: prefill from topic; mark topic `promoted`; append all new run ids to `topics/_index` `run`.
539
- 7. Never leave production only in chat when in run mode.
540
-
541
- ### Selection inside a run (required step; **none allowed**)
542
-
543
- Before brief body, evaluate catalogs (Approach B + **profile + this run’s platform**).
544
-
545
- Filter every catalog row:
546
-
547
- - `platforms` includes this run’s platform (or `*`)
548
- - `profiles` is `*` **or** includes current `profile_id`
549
- - Swipe/atom: drop `dead`. Claim: drop `retired`.
550
-
551
- Rank:
552
-
553
- - Swipe/atom: `working` before `trial`; then higher `win/n` (if n=0, treat as unranked trial).
554
- - Claim: **do not** rank by `hypothesis` vs `supported`. Rank remaining by `win/n`. `hypothesis` is valid to pick. `weakened` only if the user wants that tension.
555
-
556
- Then: swipe 0–1 → atoms by role → claim 0–1. **`none` always allowed** with why.
557
- Sibling runs for the same topic may pick different swipe/atoms (native rewrite).
558
-
559
- **Write the pick into `idea.md` (this is the citation).** Chat card alone does not count.
560
-
561
- | Field | Required form |
562
- |-------|----------------|
563
- | `swipe_id` | `none` or `S1` (one id) |
564
- | `atoms` | `none` or `hook:A-… cta:A-…` (real `A-` ids) |
565
- | `claim_id` | `none` or catalog `C-…` — **not** the `hypothesis:` one-off line |
566
-
567
- If the user later changes the pick, **overwrite** those three fields. Do **not** bump catalog `n`/`win`/`loss` here — that is ship-only (§ Catalog evidence).
568
-
569
- **引用** = how many **runs** currently name this id in `idea.md` (killed runs still count unless selection was cleared). The workbench derives it by scanning runs; it is not a column the agent increments. Observatory numbers update on `workbench/build.py`, not at the moment of chat.
570
-
571
- ### Brief Engine (decision tree → quality gate → stop rule)
572
-
573
- The brief inherits reasoning from the Topic Opportunity and focuses on **what to say and how**.
574
-
575
- **Step 1 — Inherit from Topic Opportunity**
576
-
577
- When the run is from T-xxx, copy the **readable judgment layer** into `brief.md` `## Inherited`:
578
- - `context` ← 「为什么现在值得讲」
579
- - `audience` ← 「适合谁」
580
- - `conflict` ← 「他们现在相信什么」
581
- - `insight` ← 「我们准备讲哪一刀」
582
- - `outcome` ← 「看完后的改变」
583
- - `evidence` ← 「凭什么这么判断」 + 「当前缺口」
584
-
585
- Sharpen these for the specific platform/angle — do not re-derive from scratch. If T-xxx is a legacy five-section score sheet, derive the readable judgment layer before proceeding. Do not inherit the Score table as prose.
586
-
587
- **Step 2 — Walk the decision tree**
588
-
589
- ```text
590
- 1. Read inherited context/conflict/insight
591
- 2. Can you state a thesis in one sentence?
592
- → No → reframe or stop
593
- 3. Can you name specific evidence?
594
- → No evidence at all → stop, suggest research
595
- → Weak but mechanism is provable → continue
596
- 4. What's the angle? (How does this conflict become content?)
597
- 5. What changes for the reader after consuming this?
598
- → "They'll learn something" is not specific enough
599
- → Name the belief before and after
600
- 6. → Fill brief → Self-score → Gate
601
- ```
602
-
603
- **Step 3 — Fill brief.md**
604
-
605
- The brief has two layers. The **reading surface** (top) is what a human reviews in 30 seconds. The **appendix** (bottom) is machine handoff data.
606
-
607
- Reading surface — fill in this order:
608
-
609
- 1. **Thesis** — one sentence a stranger can understand.
610
- 2. **For whom → what changes** — reader, their false belief, the after state.
611
- 3. **Evidence** — named sources, type, quality, and what we cannot prove.
612
- 4. **Platform and expression** — platform, form, hook, structure outline.
613
- 5. **Boundaries** — must include / must avoid.
614
-
615
- Appendix — fill after the reading surface:
616
-
617
- 6. **Inherited from Topic** — context, audience, conflict, insight, outcome, evidence (sharpened, not copied).
618
- 7. **Selection** — swipe, atoms, claim ids.
619
- 8. **Quality gate** — 6 × 1–5 scores.
620
-
621
- **Step 4 — Brief quality gate (self-scoring)**
622
-
623
- Score `brief.md` quality gate (6 × 1–5, max 30):
624
-
625
- | # | Gate | Question |
626
- |---|------|----------|
627
- | 1 | Thesis clarity | Can the thesis be one sentence a stranger understands? |
628
- | 2 | Evidence strength | Is there at least one specific, named source or mechanism? |
629
- | 3 | Angle originality | Is this angle different from what's already in the conversation? |
630
- | 4 | Structure coherence | Does the narrative flow from hook → conflict → thesis → proof → outcome? |
631
- | 5 | Outcome specificity | Can you name the belief change in before/after form? |
632
- | 6 | Tension preservation | Does the brief still carry the topic's conflict, or did it dilute? |
633
-
634
- | Result | Action |
635
- |--------|--------|
636
- | **≥ 24** (PASS) | Present Brief Card to human for OK |
637
- | **20–23** (REVISE) | Flag weak dimensions, self-revise once, re-score |
638
- | **< 20** (STOP) | Trigger stop rule |
639
-
640
- Update `brief.md` frontmatter: `gate_score`, `gate_pass`.
641
-
642
- **Step 5 — Stop rule**
643
-
644
- When the brief cannot pass the quality gate:
645
-
646
- ```text
647
- ⚠️ Weak Brief — RUN-…
648
- 【Failing gates】 gate … score … · gate … score …
649
- 【Reason】 one line why
650
- 【Suggestion】 reframe angle / research evidence / kill topic
651
- Reply: 用 reframe / 研究 / 换 topic / 强制继续
652
- ```
653
-
654
- The agent may reject a brief. "强制继续" overrides the gate (user decision). The stop rule is not a hard block — it is structured feedback that makes weakness visible.
655
-
656
- ### Packet
657
-
658
- After brief OK: short `packet.md` — pillar slice + voice + audience (**core + this platform**) + **craft notes distilled from the loaded `platforms/<platform>.md`** + **thesis sentence from brief**.
659
-
660
- ### Writer → Editor
661
-
662
- - Writer **re-reads** `platforms/<platform>.md`, then fills `draft.md` (**this platform only**) + full text in chat.
663
- - Editor → `editor.md`; check against that craft file’s quality bar; REVISE until APPROVE or user override.
664
-
665
- ### Rubric gate
666
-
667
- Score `rubric.md` (6 × 0–2, max 12).
668
-
669
- - **≥ 8 → SHIP** — 发布包 in chat; `runs/_index` → `ready`.
670
- - **< 8 → HOLD**.
671
- - Carousel/slideshow platforms: after SHIP → **§ PagePack + render**.
672
- - Pure X text: no multi-page pack.
673
-
674
- ### Required chat cards (run mode)
675
-
676
- **Open card** (one card per run; if N>1, list all opened)
677
-
678
- ```text
679
- ✅ Run opened RUN-YYYYMMDD-slug
680
- 【Account】 (from accounts/_index)
681
- 【Profile】 (resolved profile_id)
682
- 【Voice】 profile | path
683
- 【Platform】 x | linkedin | … → craft `platforms/<file>.md` loaded
684
- 【Topic】 none | T-… (sibling runs: RUN-…, RUN-…)
685
- 【Goal】 …
686
- 【Pillar】 P?
687
- 【Selection】 (profile + platform; drop dead/retired; prefer working; none OK)
688
- swipe: S? | none — why
689
- atoms: …
690
- claim: C? | none — why
691
- 【Index】 runs/_index updated
692
- 【State】 open → next: brief
693
- ```
694
-
695
- **Brief card** (after quality gate passes — mirrors brief.md reading surface)
696
-
697
- ```text
698
- 📋 Brief RUN-…
699
- 【Thesis】 one sentence
700
- 【For whom】 reader · false belief → after state
701
- 【Evidence】 sources · type · quality · what we cannot prove
702
- 【Platform】 platform · form · hook · structure outline
703
- 【Boundaries】 must include · must avoid
704
- 【Gate】 Thesis … · Evi … · Angle … · Struct … · Outcome … · Tension … = …/30 ✓
705
- Reply 简报 OK / 改 …
706
- ```
707
-
708
- **Draft / Editor / Rubric** — as before; draft is single-platform and must follow the loaded craft file.
709
-
710
- **Publish pack** (SHIP)
711
-
712
- ```text
713
- 📦 READY_TO_POST RUN-…
714
- 【Platform】 x | …
715
- 【Copy】 …
716
- 【Pack】 n/a | ready | blocked
717
- 【After post】 URL + win/flat/loss → feedback + published row
718
- ```
719
-
720
- ### Feedback
721
-
722
- `feedback.md` + **§ Published index** on ship.
723
- Update `runs/_index` → `published`.
724
- Then **§ Catalog evidence**. Never auto-`supported` / auto-`working`; never silent catalog ingest.
725
-
726
- ### § Published index (Step 6)
727
-
728
- On confirmed ship for this run:
729
-
730
- 1. Row on **`published/_index.md`** (date, **platform**, url, run, pillar, swipe, atoms, claim, result, notes).
731
- 2. Optional stub.
732
- 3. `runs/_index` status → `published`.
733
- 4. **§ Catalog evidence** for every cited swipe / atom / claim id (skip `none`).
734
- 5. Weekly 复盘: start from **published** `_index`. Same topic’s other platforms = other runs / other published rows.
735
-
736
- ### § Catalog evidence (required on ship)
737
-
738
- Hits cache lives on the **index row** (`n` `win` `loss`). This is **not** 引用. 引用 is run selection in `idea.md` (already true once the run exists). `n`/`win`/`loss` only move **on ship**.
739
-
740
- **Swipe / atom — no Evidence file.**
741
- The ledger is the **published row** (`swipe` / `atoms` / `result` / `notes`). Why a post flopped stays in `feedback.md` or that published `notes` cell. Do **not** add `## Evidence` to swipe/atom bodies.
742
-
743
- **Claim — Evidence table in the claim file.**
744
- That table answers “does the sentence still hold?” (`vs claim`), which is not `result`.
745
-
746
- For each cited id:
747
-
748
- 1. `n += 1`
749
- 2. `win += 1` if `result=win`; `loss += 1` if `result=loss`; `flat`/`unknown` bump `n` only.
750
- 3. Sync file frontmatter `status` if you change index status (only after user 批准).
751
- 4. **Claim only:** append the run to the claim file **Evidence** table (`result` + **vs claim**).
752
-
753
- Propose status change (user must 批准; never auto):
754
-
755
- | Object | Propose | Gate |
756
- |--------|---------|------|
757
- | swipe / atom | `trial` → `working` | `n≥2` AND `win≥2` AND `win>loss` |
758
- | swipe / atom | → `dead` | user says stop, **or** `n≥3` AND `win=0` AND `loss≥2` |
759
- | claim | → `supported` | ≥3 runs **support the proposition** (not merely `result=win`) AND user 批准 |
760
- | claim | → `weakened` / `retired` | user 批准; hits do not flip epistemology |
761
-
762
- Single win never promotes. n=1 is recorded, not celebrated.
763
- ---
764
-
765
- ## § PagePack + render (Step 7)
766
-
767
- Bridge to **easysociable-slideshow** (when skill exists). Vault owns pack slots; product owns templates + pixels.
768
-
769
- ### When
770
-
771
- Planned platform needs multi-page images (linkedin / ig / tiktok), not pure X text.
772
-
773
- ### Preconditions
774
-
775
- 0. **Hard gate** (same as § Interview). Fail → list missing files; no slideshow/template handoff unless **强制继续** / **force continue**.
776
- 1. Run exists; brief OK; editor OK; **rubric SHIP**.
777
- 2. Per-platform `page_count` / `deck_hint` follows the **arc**, not a five-family catalog.
778
- 3. Prefer a swipe whose beats are an argument; else name a one-line arc from the brief.
779
- 4. **Forbidden default:** Cover → Point → Steps → Recap → CTA (those are P0 family names, not a pack recipe).
780
-
781
- ### Agent steps
782
-
783
- 1. Write **`runs/<slug>/pack.md`** (from `_template/pack.md`; `pack-<platform>.md` OK):
784
- - this run is already one platform
785
- - **Arc** one-liner + recipe **before** Pages
786
- - slots, language, pillar, swipe_id, claim_id
787
- - page 1 `role` is not automatically `cover`
788
- 2. **Pack Card** in chat — user may `改 pack:…`.
789
- 3. Hand off to **easysociable-slideshow**: it picks templates by platform + canvas + slot shape, then opens Studio. Topology lock means a wrong arc needs a **new Run**, not slot rewrite.
790
- 4. **Render / Download:** pixels leave the product from Studio Download (not CLI render). After the user downloads, copy files under **`exports/<slug>/`** if needed; set pack `job_id`, `export_path`, status `done`; set `runs/_index` `pack`/`export` to yes. If slideshow skill is **not** available: status `not_requested` / blocked — **do not fake images**.
791
- 5. User **图 OK** or revise slots (same topology) / new Run (different arc).
792
-
793
- ### Pack Card
794
-
795
- ```text
796
- 📑 Pack RUN-… platform=linkedin|tiktok|ig
797
- 【Arc】 one-liner / recipe
798
- 【Pages】 N
799
- 【deck_hint】 …
800
- 【Outline】 P1… Pn
801
- 【export_path】 exports/<slug>/
802
- 【Render】 done | blocked (no skill) | failed
803
- ```
804
-
805
- ### Do not
806
-
807
- - Cram multiple platforms into one run / one pack
808
- - Pack for pure X text
809
- - Private template AST — public slots only
810
- - Invent metrics in slots
811
- - Skip SHIP before quality pack
812
- - Store binaries inside `runs/` (use **exports/**)
813
- - Default Cover → Point → Steps → Recap → CTA
814
- - Skip the Arc line and fill P0 family names as a tutorial
815
-
816
- ---
817
-
818
- ## § Library ingest — swipe / atoms / claims (strict)
819
-
820
- **Runs never auto-enter catalogs.** Ship → feedback + published + **§ Catalog evidence** if ids already used. New catalog rows still need user approval.
821
-
822
- ### Two ingest paths
823
-
824
- | Path | When | Your-post metrics? |
825
- |------|------|--------------------|
826
- | **A. Capture offer** | structure/link capture → user picks 入库 options | **No** (source heat is prior, not our n/win) |
827
- | **B. Post-publish** | In `published/_index` + gates → Agent proposes → user approves | **Yes** |
828
-
829
- ### Hard bans
830
-
831
- | Forbidden |
832
- |-----------|
833
- | Unpublished run → new swipe/atom/claim |
834
- | Silent seed while scaffolding |
835
- | Catalog write without user approval |
836
- | Single win → claim `supported` or swipe/atom `working` |
837
- | Mixing claim epistemology with swipe/atom hit-status |
838
- | `## Evidence` table in a swipe or atom file |
839
- | Auto-changing `status` when bumping `n`/`win`/`loss` |
840
-
841
- ### Engagement gates (path B only)
842
-
843
- At least one of: **replies ≥ 2** | bookmarks ≥ 5 | likes ≥ 10 | user override “这条可收”.
844
- These gates are for **new ingest**, not for promoting `working` (that uses our `win`/`loss` counts).
845
-
846
- ### After user approval
847
-
848
- | Ask | Create |
849
- |-----|--------|
850
- | 收成 swipe | `swipe/` + index, `trial`, n=win=loss=0 |
851
- | 收成 atom | `wiki/atoms/`, set `type`, `trial`, n=win=loss=0 |
852
- | 收成 claim | `wiki/claims/`, `hypothesis`, n=win=loss=0 |
853
-
854
- ### § Claims promote
855
-
856
- - Epistemic Evidence on existing claims when used (separate from hits).
857
- - `supported` only if ≥3 runs support the **proposition** **and** user 批准.
858
- - A `win` that does not actually support the sentence does **not** count toward `supported`.
859
-
860
- ### 复盘 card
861
-
862
- ```text
863
- 📈 Review
864
- 【Run】 …
865
- 【Result】 …
866
- 【Hits updated】 swipe S? n/win/loss … · atoms … · claim …
867
- 【Hit-status propose】 none | S?/A-… trial→working | →dead
868
- 【Path B ingest】 not eligible | eligible → propose swipe/atom/claim
869
- 【Claim promote】 none | suggest C-… hypothesis→supported|weakened
870
- Reply 批准 … / 否决 / 再观察
871
- ```
872
-
873
- ### Self-check (Capture)
874
-
875
- - [ ] `inbox/_index.md` row + `inbox/entries/C-….md`
876
- - [ ] `raw/` file + `raw/_index.md` only if criteria matched
877
- - [ ] Capture Card + library offer when structure/link
878
-
879
- ### Self-check (Topic / Opportunity)
880
-
881
- - [ ] Decision card filled (结论 / 状态原因 / 适合谁 / 核心判断 / 下一步)
882
- - [ ] Readable judgment filled (问题 / 当前相信什么 / 我们的角度 / 为什么现在 / 看完后的改变 / 依据 / 缺口 / 形式)
883
- - [ ] False belief named in 「他们现在相信什么」 (not just a conflict score)
884
- - [ ] Readable sections are concise; heat and arithmetic only under `## 评分与追踪附录`
885
- - [ ] Score table is numbers only; opp + aud + verdict line present
886
- - [ ] Opportunity Card in chat matches the human half (not a five-score walkthrough)
887
-
888
- ### Self-check (Run)
889
-
890
- - [ ] Folder exists under `runs/` with template files filled
891
- - [ ] `runs/_index.md` row created/updated
892
- - [ ] Platform gate done; one run per selected platform; `primary_platform` = that platform
893
- - [ ] `platforms/<platform>.md` **read** before brief/draft/editor; cited in brief + packet
894
- - [ ] Brief `## Inherited` populated from Topic Opportunity (not re-derived)
895
- - [ ] Brief decision tree walked; quality gate scored (6 × 1–5)
896
- - [ ] Brief gate ≥ 24 before presenting to human (or stop rule triggered)
897
- - [ ] No skip of brief / editor / rubric when user asked for full run
898
- - [ ] HOLD never presented as final publish pack
899
- - [ ] Image pack only for this run’s platform; exports under `exports/<slug>/`
900
- - [ ] Each ship → published row; this run → `published`
901
- - [ ] `idea.md` has `swipe_id` / `atoms` / `claim_id` matching the Open card (not only chat)
902
- - [ ] Cited swipe/atom/claim index `n`/`win`/`loss` bumped **on ship only**; status unchanged unless user 批准
903
- - [ ] Swipe/atom: no Evidence section; claim Evidence table updated if claim used
904
- - [ ] Selection dropped `dead`/`retired`; did not treat claim `supported` as a hit-rank
905
- - [ ] Same topic multi-platform = sibling runs sharing `topic_id`, not one multi-section folder
906
- - [ ] Packet includes thesis sentence from brief
907
- - [ ] No invented metrics
908
- - [ ] No cross-platform paste without re-applying that platform’s craft file