@easysociable/cli 0.1.3 → 0.1.5
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.
- package/README.md +13 -10
- package/content-engine/scripts/starter.mjs +3 -1
- package/content-engine/scripts/workbench.mjs +13 -8
- package/content-engine/starter/CLAUDE.md +217 -128
- package/content-engine/starter/engine.json +3 -0
- package/content-engine/starter/needs/README.md +38 -0
- package/content-engine/starter/needs/_index.md +31 -0
- package/content-engine/starter/needs/_template.md +24 -0
- package/content-engine/starter/needs/entries/README.md +5 -0
- package/content-engine/starter/products/README.md +38 -0
- package/content-engine/starter/products/_index.md +24 -0
- package/content-engine/starter/products/_template.md +56 -0
- package/content-engine/starter/products/entries/P-001-easysociable.md +150 -0
- package/content-engine/starter/profiles/_index.md +6 -3
- package/content-engine/starter/profiles/default/README.md +4 -1
- package/content-engine/starter/profiles/default/boundaries.md +14 -0
- package/content-engine/starter/profiles/default/expression.md +18 -0
- package/content-engine/starter/profiles/default/lanes.md +12 -0
- package/content-engine/starter/profiles/default/stories.md +15 -0
- package/content-engine/starter/profiles/default/voice.md +14 -0
- package/content-engine/starter/recommendations/README.md +21 -0
- package/content-engine/starter/recommendations/_index.md +21 -0
- package/content-engine/starter/recommendations/_template.md +44 -0
- package/content-engine/starter/runs/_template/brief.md +1 -1
- package/content-engine/starter/runs/_template/pack.md +15 -7
- package/content-engine/starter/runs/_template/packet.md +6 -0
- package/content-engine/starter/swipe/_template.md +3 -1
- package/content-engine/starter/topics/README.md +4 -8
- package/content-engine/starter/topics/_index.md +12 -5
- package/content-engine/starter/topics/_template-item.md +64 -51
- package/content-engine/starter/topics/scoring.md +55 -4
- package/content-engine/workbench/build.py +315 -97
- package/content-engine/workbench/serve.py +0 -0
- package/content-engine/workbench/template.html +172 -94
- package/dist/easysociable.js +191 -133
- package/dist/easysociable.js.map +1 -1
- package/package.json +13 -14
- package/skills/ONBOARDING.md +14 -15
- package/skills/easysociable-content/SKILL.md +100 -19
- package/skills/easysociable-content/workflows/INTERVIEW.md +70 -0
- package/skills/easysociable-content/workflows/NEEDS.md +82 -0
- package/skills/easysociable-slideshow/SKILL.md +79 -45
- package/skills/easysociable-slideshow/references/ARC.md +44 -0
- package/skills/easysociable-slideshow/references/CONTENT_PACK.md +34 -6
- package/skills/easysociable-slideshow/workflows/CREATE_RUN.md +24 -5
- package/skills/easysociable-slideshow/workflows/OUT_OF_SCOPE.md +3 -0
- package/skills/easysociable-template/SKILL.md +13 -16
- package/skills/easysociable-template/references/CATALOG_METADATA.md +21 -18
- package/skills/easysociable-template/scripts/generate-theme-from-hex.mjs +0 -0
- package/skills/easysociable-template/workflows/FILL_AND_RENDER.md +4 -83
- package/skills/easysociable-template/workflows/OUT_OF_SCOPE.md +3 -2
- package/content-engine/starter/discovery/README.md +0 -18
- package/content-engine/starter/discovery/_index.md +0 -27
- package/content-engine/starter/discovery/_template.md +0 -41
- package/content-engine/starter/topics/WATCHLIST.md +0 -65
- package/content-engine/starter/topics/watchlists/README.md +0 -10
- package/content-engine/starter/topics/watchlists/_shared.md +0 -14
- package/content-engine/starter/topics/watchlists/default.md +0 -6
package/README.md
CHANGED
|
@@ -13,22 +13,22 @@ Requires Node.js 20+. Content Engine workbench also needs `python3`.
|
|
|
13
13
|
## Quick start
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
#
|
|
16
|
+
# Default skills + MCP for Codex / Claude Code (template + slideshow)
|
|
17
17
|
easysociable install --yes
|
|
18
|
-
|
|
19
|
-
# Local content engine (markdown + workbench) — no Agent host required
|
|
20
|
-
easysociable engine init --root /workspace --yes
|
|
21
|
-
easysociable engine serve --engine /workspace/Content Engine --no-open
|
|
22
18
|
```
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Optional pointer skill for hosts that discover work via SKILL.md:
|
|
20
|
+
Default install does **not** include `easysociable-content`. Add it when you want the Content Engine pointer skill:
|
|
27
21
|
|
|
28
22
|
```bash
|
|
29
23
|
easysociable install --skills content,template,slideshow --yes
|
|
24
|
+
easysociable engine init --root /workspace --yes
|
|
25
|
+
easysociable engine serve --engine /workspace/Content Engine --no-open
|
|
30
26
|
```
|
|
31
27
|
|
|
28
|
+
Then tell the Agent to follow `Content Engine/CLAUDE.md`. The starter includes
|
|
29
|
+
separate `products/` (owned offers) and `recommendations/` (third-party review
|
|
30
|
+
subjects) libraries; neither is a substitute for `needs/`.
|
|
31
|
+
|
|
32
32
|
Lazy-auth guidance lives in the package at `skills/ONBOARDING.md`.
|
|
33
33
|
|
|
34
34
|
## Content Engine
|
|
@@ -36,12 +36,15 @@ Lazy-auth guidance lives in the package at `skills/ONBOARDING.md`.
|
|
|
36
36
|
| Command | Purpose |
|
|
37
37
|
|---------|---------|
|
|
38
38
|
| `easysociable engine init [--root] [--yes] [--serve]` | Scaffold starter (never overwrites) |
|
|
39
|
-
| `easysociable engine serve [--engine] [--no-open]` |
|
|
40
|
-
| `easysociable engine build [--engine]` |
|
|
39
|
+
| `easysociable engine serve [--engine] [--no-open]` | Sync workbench runtime from CLI, rebuild, start on `:8765` |
|
|
40
|
+
| `easysociable engine build [--engine]` | Sync workbench runtime from CLI, then rebuild `workbench/index.html` |
|
|
41
41
|
| `easysociable engine detect` | Find engines under search roots |
|
|
42
42
|
| `easysociable engine validate --root …` | Starter completeness |
|
|
43
43
|
| `easysociable engine validate --run …` | Run / pack checks before render |
|
|
44
44
|
|
|
45
|
+
The Workbench exposes Products and Recommendations as separate read-only
|
|
46
|
+
indexes. Topics can cite either one without forcing a product connection.
|
|
47
|
+
|
|
45
48
|
Default `--root` / `--engine` parent is `/workspace` when that directory exists, otherwise the current working directory.
|
|
46
49
|
|
|
47
50
|
## Authentication
|
|
@@ -11,7 +11,9 @@ export const ENGINE_PATHS = {
|
|
|
11
11
|
runs: 'runs',
|
|
12
12
|
exports: 'exports',
|
|
13
13
|
topics: 'topics',
|
|
14
|
-
|
|
14
|
+
needs: 'needs',
|
|
15
|
+
products: 'products',
|
|
16
|
+
recommendations: 'recommendations',
|
|
15
17
|
swipe: 'swipe',
|
|
16
18
|
profiles: 'profiles',
|
|
17
19
|
inbox: 'inbox',
|
|
@@ -30,21 +30,26 @@ export function portInUse(port = WORKBENCH_PORT) {
|
|
|
30
30
|
})
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
/** `update: false` = init (missing only). `update: true` = build/serve refresh from package. */
|
|
34
|
+
export function ensureWorkbench(engine, { update = false } = {}) {
|
|
34
35
|
const destDir = join(engine, 'workbench')
|
|
35
36
|
mkdirSync(destDir, { recursive: true })
|
|
36
37
|
const copied = []
|
|
38
|
+
const updated = []
|
|
37
39
|
const skipped = []
|
|
38
40
|
for (const name of WORKBENCH_FILES) {
|
|
39
41
|
const dest = join(destDir, name)
|
|
40
|
-
|
|
42
|
+
const from = join(WORKBENCH_SRC, name)
|
|
43
|
+
if (existsSync(dest) && !update) {
|
|
41
44
|
skipped.push(name)
|
|
42
45
|
continue
|
|
43
46
|
}
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
const existed = existsSync(dest)
|
|
48
|
+
copyFileSync(from, dest)
|
|
49
|
+
if (existed) updated.push(name)
|
|
50
|
+
else copied.push(name)
|
|
46
51
|
}
|
|
47
|
-
return { destDir, copied, skipped }
|
|
52
|
+
return { destDir, copied, updated, skipped }
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
export function buildWorkbench(engine) {
|
|
@@ -68,7 +73,7 @@ export async function startWorkbench(engine, { noOpen = false } = {}) {
|
|
|
68
73
|
if (!python) {
|
|
69
74
|
return { ok: false, code: 'PYTHON3_REQUIRED', message: 'python3 is required for the workbench. Install Python 3 and retry.' }
|
|
70
75
|
}
|
|
71
|
-
ensureWorkbench(engine)
|
|
76
|
+
ensureWorkbench(engine, { update: true })
|
|
72
77
|
const built = buildWorkbench(engine)
|
|
73
78
|
if (!built.ok) return built
|
|
74
79
|
const url = WORKBENCH_URL
|
|
@@ -112,9 +117,9 @@ async function main() {
|
|
|
112
117
|
if (!options.engine) throw new Error('--engine is required')
|
|
113
118
|
const engine = resolve(options.engine)
|
|
114
119
|
if (options.command === 'build') {
|
|
115
|
-
ensureWorkbench(engine)
|
|
120
|
+
const workbench = ensureWorkbench(engine, { update: true })
|
|
116
121
|
const built = buildWorkbench(engine)
|
|
117
|
-
output(built, options.json)
|
|
122
|
+
output({ workbench, ...built }, options.json)
|
|
118
123
|
if (!built.ok) process.exitCode = 2
|
|
119
124
|
return
|
|
120
125
|
}
|
|
@@ -9,7 +9,6 @@ This folder is the local **Content Engine** for EasySociable.
|
|
|
9
9
|
|
|
10
10
|
- Folder tree: **English** (`Content Engine/`). Do not ask language.
|
|
11
11
|
- Default **account:** first **active** handle in `accounts/_index.md` (starter: `your-handle` — replace it)
|
|
12
|
-
- Default **platform:** `x` (watchlist / catalog filter when unset)
|
|
13
12
|
- **开一单:** do **not** silent-default platform — **ask**; multi-select → **N runs**
|
|
14
13
|
- Do not invent metrics, customers, or quotes the user did not provide
|
|
15
14
|
|
|
@@ -18,10 +17,17 @@ This folder is the local **Content Engine** for EasySociable.
|
|
|
18
17
|
1. Read **`accounts/_index.md`** for the handle (default: first active row)
|
|
19
18
|
2. Get `profile_id`, `voice`, `platforms`, `default_platform`, `overrides`
|
|
20
19
|
3. Load **`profiles/<profile_id>/pillars.md`** + **`audience.md`** (core + current platform section)
|
|
21
|
-
4. Voice: if account `voice` is `profile` or empty → **`profiles/<profile_id>/voice.md`** (
|
|
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.
|
|
22
24
|
5. If `overrides` is **non-empty**, read that path (e.g. `accounts/overrides/<handle>.md`) and apply last
|
|
23
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.
|
|
24
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.
|
|
25
31
|
|
|
26
32
|
## File map
|
|
27
33
|
|
|
@@ -31,21 +37,26 @@ This folder is the local **Content Engine** for EasySociable.
|
|
|
31
37
|
| `profiles/_index.md` | Profile registry |
|
|
32
38
|
| `profiles/<id>/pillars.md` | Topic pillars (what to talk about) |
|
|
33
39
|
| `profiles/<id>/audience.md` | Readers + platform emphasis |
|
|
34
|
-
| `profiles/<id>/voice.md` | Identity +
|
|
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 |
|
|
35
45
|
| `accounts/_index.md` | handle → profile, platforms, voice, overrides |
|
|
36
46
|
| `accounts/overrides/<handle>.md` | Optional account deltas |
|
|
37
47
|
| `platforms/*.md` | Platform craft only |
|
|
38
48
|
| `inbox/_index.md` | Capture registry |
|
|
39
49
|
| `inbox/entries/C-*.md` | Per-capture working notes |
|
|
50
|
+
| `needs/_index.md` | Audience-quote registry |
|
|
51
|
+
| `needs/entries/N-*.md` | Per-need quote + sightings |
|
|
52
|
+
| `products/_index.md` | Owned product registry and lifecycle |
|
|
53
|
+
| `products/entries/P-*.md` | Owned product facts, boundaries, pricing and claims |
|
|
54
|
+
| `recommendations/_index.md` | Third-party tool/product registry and Profile associations |
|
|
55
|
+
| `recommendations/R-*.md` | Review subject facts, evidence and disclosure |
|
|
40
56
|
| `raw/_index.md` | Authoritative source registry |
|
|
41
57
|
| `raw/*.md` | Source bodies |
|
|
42
58
|
| `topics/_index.md` | Topic queue (one row per topic + `item` + src engagement) |
|
|
43
|
-
| `topics/items/T-*.md` |
|
|
44
|
-
| `topics/WATCHLIST.md` | Watchlist router (per-profile files) |
|
|
45
|
-
| `discovery/_index.md` | Analyzed watchlist signals and promotion status |
|
|
46
|
-
| `discovery/D-*.md` | Readable Source Digest, source limits, and workflow state |
|
|
47
|
-
| `topics/watchlists/<profile_id>.md` | Profile-scoped radar handles |
|
|
48
|
-
| `topics/watchlists/_shared.md` | Shared radar (`*`, all profiles) |
|
|
59
|
+
| `topics/items/T-*.md` | Opportunity card (human half) + Score/Trace appendix |
|
|
49
60
|
| `topics/scoring.md` | Scout gate + opportunity five-dim (context/audience/conflict/insight/evidence) |
|
|
50
61
|
| `swipe/_index.md` | Structures (+ `profiles` column) |
|
|
51
62
|
| `wiki/atoms/_index.md` | Atoms (+ `profiles`) |
|
|
@@ -60,22 +71,23 @@ This folder is the local **Content Engine** for EasySociable.
|
|
|
60
71
|
| User intent | Action |
|
|
61
72
|
|-------------|--------|
|
|
62
73
|
| capture / 记一下 (+ link) | **§ Capture** only — **not** topics by default |
|
|
63
|
-
|
|
|
64
|
-
|
|
|
65
|
-
| 扫 TikTok/LinkedIn/… watchlist | Same; only rows where `platform` matches (after profile resolve) |
|
|
74
|
+
| 记需求 / 用户原话 / 评论导出 | **§ Needs** only |
|
|
75
|
+
| **扫需求选题** | **§ Topics** from `needs/` where `status=captured`; max 5 `produce` |
|
|
66
76
|
| 扫 inbox 选题 | **§ Topics** — from captures without topic yet (max 5) |
|
|
67
|
-
|
|
|
68
|
-
| 生成 topic (no source specified) | **§ Topics** — ask for the input/source; never choose an existing Discovery silently |
|
|
77
|
+
| 生成 topic (no source specified) | **§ Topics** — offer captured needs or ask which explicit input to use |
|
|
69
78
|
| 链接直接选题 / 把 C-xxx 做成选题 | **§ Topics** — create T- (may link capture) |
|
|
70
|
-
|
|
|
79
|
+
| 采访我 / 完善人设 / interview me / who am I as a creator / 建立 profile | **§ Interview** — persist after each dimension; no slideshow |
|
|
80
|
+
| 开一单 / 用 T-xxx 开一单 | **Hard gate first**, then **§ Open a run** — **ask platform(s)** if unset; multi-select → **N runs** (bind `topic_id` if from T-) |
|
|
71
81
|
| Quick draft | Resolve profile; selection; draft in chat |
|
|
72
82
|
| 收成 swipe/atom/claim | **§ Library ingest** after approval |
|
|
73
83
|
| 选题后同意进 inbox | Capture that URL/C-link then optional library offer |
|
|
74
84
|
| Post URL after ship | feedback + **§ Published index** |
|
|
75
85
|
| 复盘 / 批准晋级 | Claims promote + published index |
|
|
76
86
|
| Update pillars/audience | Edit **`profiles/<id>/…`** |
|
|
87
|
+
| 更新产品 / 产品库 | Edit **`products/`**; keep dates and source of truth |
|
|
88
|
+
| 推荐 / 评测第三方产品 | Edit **`recommendations/`**; record evidence and disclosure |
|
|
77
89
|
| Update account binding | Edit **`accounts/_index.md`** |
|
|
78
|
-
| 出图 | **§ PagePack + render** |
|
|
90
|
+
| 出图 | **Hard gate first**, then **§ PagePack + render**. Fail → list missing files; no handoff unless user says **强制继续** / **force continue** |
|
|
79
91
|
|
|
80
92
|
---
|
|
81
93
|
|
|
@@ -171,72 +183,91 @@ Optional: if user also says「同时选题/打分」, run **§ Topics** for this
|
|
|
171
183
|
|
|
172
184
|
---
|
|
173
185
|
|
|
174
|
-
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## § Products (offer facts)
|
|
189
|
+
|
|
190
|
+
### When
|
|
175
191
|
|
|
176
|
-
|
|
192
|
+
User defines, updates, prices, retires, or asks about a product or offer.
|
|
177
193
|
|
|
178
|
-
###
|
|
194
|
+
### Role
|
|
195
|
+
|
|
196
|
+
Products are the **supply-side fact layer**. They are not audience needs,
|
|
197
|
+
external discoveries, or content opportunities.
|
|
179
198
|
|
|
180
199
|
```text
|
|
181
|
-
|
|
200
|
+
Need (demand evidence) + Profile (identity) + optional Product (offer facts)
|
|
201
|
+
→ Topic (editorial judgment)
|
|
202
|
+
→ Run
|
|
182
203
|
```
|
|
183
204
|
|
|
184
|
-
###
|
|
205
|
+
### Rules
|
|
185
206
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
207
|
+
- Read the cited `products/entries/P-*.md` before using product facts in a
|
|
208
|
+
Topic, brief, draft, CTA, or product answer.
|
|
209
|
+
- A Topic may cite `product_ids: none`; do not force a product connection.
|
|
210
|
+
- A Topic may cite `recommendation_ids: none`; recommendations are third-party
|
|
211
|
+
review subjects, not owned products.
|
|
212
|
+
- `product_fit` describes relevance, not a readiness verdict. Product fit never
|
|
213
|
+
replaces `need_ids`, evidence, audience, or opportunity scoring.
|
|
214
|
+
- Do not turn a product promise into a Need quote. Do not turn a Need quote
|
|
215
|
+
into a product capability.
|
|
216
|
+
- Keep exact pricing and entitlements in the dated product entry. Do not copy
|
|
217
|
+
stale prices into other files.
|
|
218
|
+
- Do not invent proof, customers, outcomes, metrics, or testimonials.
|
|
192
219
|
|
|
193
|
-
###
|
|
220
|
+
### Product fit
|
|
194
221
|
|
|
195
|
-
|
|
222
|
+
Use one of:
|
|
196
223
|
|
|
197
|
-
|
|
224
|
+
| fit | Meaning | Typical CTA |
|
|
225
|
+
|-----|---------|-------------|
|
|
226
|
+
| `direct` | The Topic directly addresses a problem the product solves | `educate` / `invite` / `sell` |
|
|
227
|
+
| `adjacent` | The Topic builds context but is not a product pitch | `educate` / `mention` |
|
|
228
|
+
| `none` | No honest product connection is needed | `none` |
|
|
198
229
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
【Limits】 what the source does not establish …
|
|
204
|
-
【Status】 unread | read | saved | promoted | rejected
|
|
205
|
-
【Next】 none / revisit / promote to Topic
|
|
206
|
-
```
|
|
230
|
+
Product fit is written on the Topic human card and inherited by the Brief.
|
|
231
|
+
For third-party reviews, use `recommendation_ids`, not `product_ids`. Load the
|
|
232
|
+
recommendation entry and disclose affiliate, sponsorship, or other commercial
|
|
233
|
+
relationships before drafting.
|
|
207
234
|
|
|
208
|
-
###
|
|
235
|
+
### Topic generation modes
|
|
209
236
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
237
|
+
Use the smallest honest mode:
|
|
238
|
+
|
|
239
|
+
| mode | Required inputs |
|
|
240
|
+
|------|-----------------|
|
|
241
|
+
| `demand` | Needs + Profile |
|
|
242
|
+
| `demand_to_offer` | Needs + Product + Profile |
|
|
243
|
+
| `demand_to_review` | Needs + Recommendation + Profile |
|
|
244
|
+
| `review` | Recommendation + Profile + evidence |
|
|
245
|
+
| `offer_education` | Product + Profile + mechanism |
|
|
246
|
+
| `profile_thesis` | Profile + Pillar |
|
|
247
|
+
|
|
248
|
+
Needs are the default source. Product or Recommendation presence never proves
|
|
249
|
+
audience demand and never raises a Topic to `ready` by itself.
|
|
215
250
|
|
|
216
251
|
---
|
|
217
252
|
|
|
218
253
|
## § Topics (Opportunity evaluation)
|
|
219
254
|
|
|
220
255
|
**Role:** Evaluate **Content Opportunities** — whether a topic deserves to exist as content. Does not replace capture or runs.
|
|
221
|
-
**Principle:** Topics are not titles. They are
|
|
256
|
+
**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.
|
|
222
257
|
|
|
223
258
|
### Layout
|
|
224
259
|
|
|
225
260
|
| Path | Role |
|
|
226
261
|
|------|------|
|
|
227
262
|
| `topics/scoring.md` | Scout → opportunity **15/20/25/25/15** (context/audience/conflict/insight/evidence); ready = opp≥**7.5** **and** aud≥**6** |
|
|
228
|
-
| `topics/WATCHLIST.md` | Watchlist router |
|
|
229
|
-
| `topics/watchlists/<profile_id>.md` | Per-profile radar (**scheme B**) |
|
|
230
|
-
| `topics/watchlists/_shared.md` | Shared rows for all profiles (`*`) |
|
|
231
263
|
| `topics/_index.md` | Queue: one row per topic, **`item`** link, **`src_*` engagement** |
|
|
232
|
-
| `topics/items/T-YYYYMMDD-XX.md` |
|
|
264
|
+
| `topics/items/T-YYYYMMDD-XX.md` | Decision card (summary + judgment) + Score/Trace/Constraints (appendix) |
|
|
233
265
|
| `topics/_template-item.md` | Template |
|
|
234
266
|
|
|
235
267
|
### Defaults
|
|
236
268
|
|
|
237
|
-
-
|
|
238
|
-
-
|
|
239
|
-
- Opportunity dims (produce only): `context` `audience` `conflict` `insight` `evidence` (0–10 + note each) → `opp_score`
|
|
269
|
+
- Scout first: `purpose` = `discard` | `library` | `produce`; `scout_label` = `demand` | `ally` | `foil` | `craft_only`. Needs default `scout_label=demand`.
|
|
270
|
+
- 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.
|
|
240
271
|
- `ready` requires **opp_score ≥ 7.5 and audience ≥ 6**
|
|
241
272
|
- `src_likes` / `src_replies` / `src_bookmarks` (+ views if known) + `engagement_at` on **index** when source is external
|
|
242
273
|
- Do **not** fold `src_*` into opp_score; among **ready** only, prefer replies/bookmarks over views
|
|
@@ -246,85 +277,57 @@ watchlist signal → Discovery → Topic (only when explicitly promoted) → Bri
|
|
|
246
277
|
| User intent | inbox/raw | topics |
|
|
247
278
|
|-------------|-----------|--------|
|
|
248
279
|
| `记一下` + URL | **Yes** (default) | Only if also asked to score as topic |
|
|
249
|
-
|
|
|
280
|
+
| `扫需求选题` | **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` |
|
|
250
281
|
| `扫 inbox 选题` | Existing only | Scout + score ≤5 produce; set `capture_id`; skip captures already linked to a T- |
|
|
251
282
|
| `把 C-xxx 做成选题` | Keep | Create T- with `capture_id` (still Scout + opportunity score) |
|
|
252
283
|
| `链接直接选题` | Default NO unless user agrees capture | Create T- + src engagement |
|
|
253
284
|
| `把 T-xx 收进 inbox` | Yes for that source | Backfill `capture_id` on T- |
|
|
254
285
|
|
|
255
|
-
After a Discovery batch, report **unread / read / saved / promoted / rejected** counts. Topic promotion is explicit and happens after Discovery, not during the scan.
|
|
256
|
-
|
|
257
286
|
### Create topic steps
|
|
258
287
|
|
|
259
|
-
**Input gate:** A Topic must have an explicit input. Accept
|
|
288
|
+
**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:
|
|
289
|
+
|
|
290
|
+
1. If needs exist with `status=captured`, offer **扫需求选题**.
|
|
291
|
+
2. Otherwise ask which explicit input to use.
|
|
260
292
|
|
|
261
293
|
1. Hard filters (`scoring.md`); else skip.
|
|
262
294
|
2. **Scout gate** — set `purpose` + `scout_label`; if `discard`, do not create T-.
|
|
263
295
|
3. If `produce` (or user forces score):
|
|
264
|
-
a.
|
|
265
|
-
b. Score all 5 opportunity dims (0–10
|
|
266
|
-
c. Write `topics/items/T-….md`.
|
|
267
|
-
4. If `library`: optional light item with `status: library`, or capture offer only.
|
|
268
|
-
5. Add row on `topics/_index.md` (`item` + `src_*` when external).
|
|
269
|
-
6.
|
|
296
|
+
a. Write the **decision card** first (`topics/_template-item.md` upper half): 结论, 状态原因, 适合谁, 核心判断, 下一步, then the readable judgment sections: 要解决的问题, 受众当前相信什么, 我们准备讲哪一刀, 为什么现在, 看完后的改变, 依据, 当前缺口, 建议形式. Keep the summary short; no enum lists, heat, or weighted arithmetic in the readable layer.
|
|
297
|
+
b. Score all 5 opportunity dims (0–10) → `opp_score`. Put **numbers only** in `## Score`. Do not repeat the card as table notes.
|
|
298
|
+
c. Fill `## Trace` (ids, src heat) and `## Constraints` (writer must-nots). Write `topics/items/T-….md`.
|
|
299
|
+
4. If `library`: optional light item with `status: library`, or capture offer only. Source needs stay `captured` (or `retired` if the user discards).
|
|
300
|
+
5. Add row on `topics/_index.md` (`item` + `src_*` when external). `one_liner` = the card title sentence.
|
|
301
|
+
6. 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`).
|
|
302
|
+
7. Output the **Decision Card** in chat — same shape as the readable layer, not a score walkthrough.
|
|
270
303
|
|
|
271
|
-
**Important:**
|
|
304
|
+
**Important:** 「他们现在相信什么」must name the false belief. If you cannot, conflict cannot score above 5. Brief inherits the readable judgment layer, not the Score table.
|
|
272
305
|
|
|
273
306
|
### Opportunity Card
|
|
274
307
|
|
|
308
|
+
Paste the decision summary and readable judgment sections. Do not walk five scores in the main body.
|
|
309
|
+
|
|
275
310
|
```text
|
|
276
|
-
📋
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
【Verdict】 ready | backlog | parked | library
|
|
291
|
-
【Weak dims】 (any dim < 6 → name it + suggest: research / reframe / discard)
|
|
292
|
-
【Suggested selection】 swipe/atoms/claim (none OK)
|
|
293
|
-
【Next】 开一单 / 改 angle 重打分 / 研究 evidence / 放弃 / 收进 inbox / 入库
|
|
311
|
+
📋 选题判断卡 T-YYYYMMDD-XX
|
|
312
|
+
【结论】 ready | backlog | parked
|
|
313
|
+
【状态原因】 …
|
|
314
|
+
【适合谁】 …
|
|
315
|
+
【核心判断】 …
|
|
316
|
+
【下一步】 开始生成 / 补需求 / 补证据 / 修改角度 / 放弃
|
|
317
|
+
【要解决的问题】 …
|
|
318
|
+
【他们现在相信什么】 以为 X → 其实 Y
|
|
319
|
+
【我们准备讲哪一刀】 …
|
|
320
|
+
【为什么现在值得讲】 …
|
|
321
|
+
【看完后的改变】 之前 … → 之后 …
|
|
322
|
+
【依据】 …
|
|
323
|
+
【当前缺口】 …
|
|
324
|
+
【建议形式】 …
|
|
294
325
|
```
|
|
295
326
|
|
|
296
327
|
### Topic → run
|
|
297
328
|
|
|
298
329
|
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.
|
|
299
330
|
|
|
300
|
-
### Watchlist (scheme B — per profile)
|
|
301
|
-
|
|
302
|
-
**Layout:** `topics/WATCHLIST.md` (router) + `topics/watchlists/<profile_id>.md` + `topics/watchlists/_shared.md`.
|
|
303
|
-
|
|
304
|
-
**Resolve profile before scan or add:**
|
|
305
|
-
|
|
306
|
-
1. User gives **profile_id** → use it.
|
|
307
|
-
2. User gives **account** → `accounts/_index` → `profile_id`.
|
|
308
|
-
3. **Neither → ask** (list profiles from `profiles/_index`; do **not** silently default).
|
|
309
|
-
|
|
310
|
-
**Load set:** active rows in `_shared.md` ∪ `watchlists/<profile_id>.md`.
|
|
311
|
-
**Platform filter:** user-specified, else default **`x`**; `全部平台` = all platforms in the set.
|
|
312
|
-
**Always set `platform` on each row.** Same brand on two networks → two rows.
|
|
313
|
-
**Shared across all profiles** → `_shared.md` (ids `#S-01…`). Two profiles only → copy row into both files.
|
|
314
|
-
**Add handle:** write to the chosen profile file (or `_shared` if user says shared / 全 profile).
|
|
315
|
-
|
|
316
|
-
### Do not
|
|
317
|
-
|
|
318
|
-
- Auto-dump watchlist scans into inbox
|
|
319
|
-
- Skip Scout gate or opportunity scoring on `produce` topics
|
|
320
|
-
- Skip structured opportunity fields (context/audience/conflict/insight/evidence) on `produce`
|
|
321
|
-
- Skip per-dimension notes on `produce`
|
|
322
|
-
- Exceed 5 **produce** topics per scan
|
|
323
|
-
- Mark `ready` on high `src_*` or high opp_score alone (need audience ≥ 6 too)
|
|
324
|
-
- Score conflict > 5 without articulating the `current_belief` and `belief_gap` in writing
|
|
325
|
-
- Scan wrong network for a row (e.g. X tools on a `tiktok` handle)
|
|
326
|
-
- Silently assume profile when user did not name profile or account
|
|
327
|
-
|
|
328
331
|
---
|
|
329
332
|
|
|
330
333
|
## § Swipe / atom library
|
|
@@ -338,12 +341,91 @@ On `用 T-xxx 开一单`: **ask platform(s)** if unset (multi-select OK). Create
|
|
|
338
341
|
|
|
339
342
|
---
|
|
340
343
|
|
|
344
|
+
## § Interview
|
|
345
|
+
|
|
346
|
+
Triggers: 采访我 / 完善人设 / interview me / who am I as a creator / 建立 profile.
|
|
347
|
+
|
|
348
|
+
Follow `easysociable-content/workflows/INTERVIEW.md` for questions. Persist after each dimension; do not wait until the end.
|
|
349
|
+
|
|
350
|
+
- Append `## Experience` / `## Values` to existing `voice.md` if those headings are missing. Do not rewrite filled Identity rows.
|
|
351
|
+
- Missing `boundaries.md` → write empty starter, then interview. **Never invent boundaries.**
|
|
352
|
+
- Do not scan the watchlist. Do not create a slideshow. Do not ingest needs in this section.
|
|
353
|
+
|
|
354
|
+
### Hard gate (refuse 出图 / PagePack / `create_run`)
|
|
355
|
+
|
|
356
|
+
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.
|
|
357
|
+
|
|
358
|
+
Fail → list missing files; stay here. User must say **强制继续** / **force continue**. Optional check:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
easysociable engine validate --root . --require-knowledge
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Completion
|
|
365
|
+
|
|
366
|
+
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**.
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## § Needs (audience quotes)
|
|
371
|
+
|
|
372
|
+
Triggers: 记需求 / 用户原话 / 评论导出 / capture audience quotes / user needs.
|
|
373
|
+
扫需求选题 → **§ Topics** (this section only writes `N-` records).
|
|
374
|
+
|
|
375
|
+
Follow `easysociable-content/workflows/NEEDS.md` when this engine's copy of the workflow is the newer one; this section wins if both exist.
|
|
376
|
+
|
|
377
|
+
### Layout
|
|
378
|
+
|
|
379
|
+
| Path | Role |
|
|
380
|
+
|------|------|
|
|
381
|
+
| `needs/_index.md` | Quote registry |
|
|
382
|
+
| `needs/entries/N-YYYYMMDD-XX.md` | Verbatim quote + sightings + optional gloss |
|
|
383
|
+
| `needs/_template.md` | Entry shape |
|
|
384
|
+
|
|
385
|
+
### Status machine (only these words)
|
|
386
|
+
|
|
387
|
+
```text
|
|
388
|
+
captured → just written, or still captured after a synonym merge (frequency ≥ 1)
|
|
389
|
+
promoted → and only when a T- exists whose need_ids contain this N-; topic_ids lists that T-
|
|
390
|
+
retired → user discarded
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
- Never `clustered`. Merge is not a status.
|
|
394
|
+
- Never mark `promoted` without that `T-`. `topic_ids` non-empty ≡ `promoted`.
|
|
395
|
+
- 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`.
|
|
396
|
+
- Scan input: `status=captured` (`topic_ids` empty). Max 5 `produce`.
|
|
397
|
+
- Quote cell = verbatim. Gloss is optional and separate.
|
|
398
|
+
- Do not invent quotes. Do not treat watchlist hooks as needs.
|
|
399
|
+
- `N-` never goes in topic `capture_id`.
|
|
400
|
+
|
|
401
|
+
### Ingest
|
|
402
|
+
|
|
403
|
+
1. New entry from `_template.md` + row at top of `_index.md`.
|
|
404
|
+
2. Chat card:
|
|
405
|
+
|
|
406
|
+
```text
|
|
407
|
+
✅ Need N-YYYYMMDD-XX
|
|
408
|
+
【Quote】 …
|
|
409
|
+
【Source】 comment | dm | consult | faq | student | other
|
|
410
|
+
【Frequency】 1
|
|
411
|
+
【Stored】 needs/_index + needs/entries/N-….md
|
|
412
|
+
【Merge】 new | merged into N-… (frequency now k, status still captured)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
3. Synonym merge: propose → user yes → same `N-` stays `captured`, `frequency += 1`, append sighting. Retire a mistaken duplicate.
|
|
416
|
+
|
|
417
|
+
Hard gate: `needs/_index.md` ≥ **3** `N-` rows once `needs/` exists (empty index fails). Target **5**. Prefer scanning needs before inbox.
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
341
421
|
## § Open a run
|
|
342
422
|
|
|
343
423
|
### When
|
|
344
424
|
|
|
345
425
|
User wants a tracked job: "开一单", "open a run", "按完整流程", or a multi-step post with gates.
|
|
346
426
|
|
|
427
|
+
**Hard gate first** (same as § Interview). Fail → list missing files; do not create `runs/<slug>/` unless **强制继续** / **force continue**.
|
|
428
|
+
|
|
347
429
|
### Model (one platform = one Run)
|
|
348
430
|
|
|
349
431
|
- **One folder = one platform draft** (native rewrite).
|
|
@@ -438,13 +520,15 @@ The brief inherits reasoning from the Topic Opportunity and focuses on **what to
|
|
|
438
520
|
|
|
439
521
|
**Step 1 — Inherit from Topic Opportunity**
|
|
440
522
|
|
|
441
|
-
When the run is from T-xxx, copy the
|
|
442
|
-
- `context`
|
|
443
|
-
- `audience`
|
|
444
|
-
- `conflict`
|
|
445
|
-
- `insight`
|
|
523
|
+
When the run is from T-xxx, copy the **readable judgment layer** into `brief.md` `## Inherited`:
|
|
524
|
+
- `context` ← 「为什么现在值得讲」
|
|
525
|
+
- `audience` ← 「适合谁」
|
|
526
|
+
- `conflict` ← 「他们现在相信什么」
|
|
527
|
+
- `insight` ← 「我们准备讲哪一刀」
|
|
528
|
+
- `outcome` ← 「看完后的改变」
|
|
529
|
+
- `evidence` ← 「凭什么这么判断」 + 「当前缺口」
|
|
446
530
|
|
|
447
|
-
Sharpen these for the specific platform/angle — do not re-derive from scratch. If T-xxx
|
|
531
|
+
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.
|
|
448
532
|
|
|
449
533
|
**Step 2 — Walk the decision tree**
|
|
450
534
|
|
|
@@ -625,25 +709,29 @@ Planned platform needs multi-page images (linkedin / ig / tiktok), not pure X te
|
|
|
625
709
|
|
|
626
710
|
### Preconditions
|
|
627
711
|
|
|
712
|
+
0. **Hard gate** (same as § Interview). Fail → list missing files; no slideshow/template handoff unless **强制继续** / **force continue**.
|
|
628
713
|
1. Run exists; brief OK; editor OK; **rubric SHIP**.
|
|
629
|
-
2. Per-platform `page_count` / `deck_hint`
|
|
630
|
-
3. Prefer swipe
|
|
714
|
+
2. Per-platform `page_count` / `deck_hint` follows the **arc**, not a five-family catalog.
|
|
715
|
+
3. Prefer a swipe whose beats are an argument; else name a one-line arc from the brief.
|
|
716
|
+
4. **Forbidden default:** Cover → Point → Steps → Recap → CTA (those are P0 family names, not a pack recipe).
|
|
631
717
|
|
|
632
718
|
### Agent steps
|
|
633
719
|
|
|
634
720
|
1. Write **`runs/<slug>/pack.md`** (from `_template/pack.md`; `pack-<platform>.md` OK):
|
|
635
721
|
- this run is already one platform
|
|
722
|
+
- **Arc** one-liner + recipe **before** Pages
|
|
636
723
|
- slots, language, pillar, swipe_id, claim_id
|
|
724
|
+
- page 1 `role` is not automatically `cover`
|
|
637
725
|
2. **Pack Card** in chat — user may `改 pack:…`.
|
|
638
|
-
3. **
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
4. User **图 OK** or revise slots and re-render.
|
|
726
|
+
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.
|
|
727
|
+
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**.
|
|
728
|
+
5. User **图 OK** or revise slots (same topology) / new Run (different arc).
|
|
642
729
|
|
|
643
730
|
### Pack Card
|
|
644
731
|
|
|
645
732
|
```text
|
|
646
733
|
📑 Pack RUN-… platform=linkedin|tiktok|ig
|
|
734
|
+
【Arc】 one-liner / recipe
|
|
647
735
|
【Pages】 N
|
|
648
736
|
【deck_hint】 …
|
|
649
737
|
【Outline】 P1… Pn
|
|
@@ -659,6 +747,8 @@ Planned platform needs multi-page images (linkedin / ig / tiktok), not pure X te
|
|
|
659
747
|
- Invent metrics in slots
|
|
660
748
|
- Skip SHIP before quality pack
|
|
661
749
|
- Store binaries inside `runs/` (use **exports/**)
|
|
750
|
+
- Default Cover → Point → Steps → Recap → CTA
|
|
751
|
+
- Skip the Arc line and fill P0 family names as a tutorial
|
|
662
752
|
|
|
663
753
|
---
|
|
664
754
|
|
|
@@ -725,13 +815,12 @@ Reply 批准 … / 否决 / 再观察
|
|
|
725
815
|
|
|
726
816
|
### Self-check (Topic / Opportunity)
|
|
727
817
|
|
|
728
|
-
- [ ]
|
|
729
|
-
- [ ]
|
|
730
|
-
- [ ]
|
|
731
|
-
- [ ]
|
|
732
|
-
- [ ]
|
|
733
|
-
- [ ]
|
|
734
|
-
- [ ] Opportunity Card output in chat
|
|
818
|
+
- [ ] Decision card filled (结论 / 状态原因 / 适合谁 / 核心判断 / 下一步)
|
|
819
|
+
- [ ] Readable judgment filled (问题 / 当前相信什么 / 我们的角度 / 为什么现在 / 看完后的改变 / 依据 / 缺口 / 形式)
|
|
820
|
+
- [ ] False belief named in 「他们现在相信什么」 (not just a conflict score)
|
|
821
|
+
- [ ] Readable sections are concise; heat and arithmetic only under `## 评分与追踪附录`
|
|
822
|
+
- [ ] Score table is numbers only; opp + aud + verdict line present
|
|
823
|
+
- [ ] Opportunity Card in chat matches the human half (not a five-score walkthrough)
|
|
735
824
|
|
|
736
825
|
### Self-check (Run)
|
|
737
826
|
|