@easysociable/cli 0.1.2 → 0.1.3

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 (120) hide show
  1. package/README.md +29 -21
  2. package/dist/easysociable.js +481 -52
  3. package/dist/easysociable.js.map +1 -1
  4. package/package.json +3 -2
  5. package/skills/ONBOARDING.md +20 -16
  6. package/skills/easysociable-content/SKILL.md +29 -104
  7. package/skills/easysociable-slideshow/SKILL.md +4 -3
  8. package/skills/easysociable-template/SKILL.md +26 -24
  9. package/skills/easysociable-template/references/CATALOG_METADATA.md +2 -2
  10. package/skills/easysociable-template/references/DESIGN_V2_1.md +53 -2
  11. package/skills/easysociable-template/references/GATEWAY.md +7 -2
  12. package/skills/easysociable-template/references/PLATFORM_SPECS.md +11 -3
  13. package/skills/easysociable-template/references/THEME_TOKENS.md +1 -1
  14. package/skills/easysociable-template/references/fixtures/image-reference.design-plan.json +74 -0
  15. package/skills/easysociable-template/references/fixtures/image-reference.visual-qa.json +28 -0
  16. package/skills/easysociable-template/scripts/validate-design-v2.mjs +97 -0
  17. package/skills/easysociable-template/workflows/ASSET_PLAN.md +2 -1
  18. package/skills/easysociable-template/workflows/AUTHORING_FROM_BRIEF.md +4 -4
  19. package/skills/easysociable-template/workflows/AUTHORING_FROM_IMAGE.md +66 -16
  20. package/skills/easysociable-template/workflows/AUTHORING_STUDIO.md +28 -15
  21. package/skills/easysociable-template/workflows/DESIGN_BRIEF.md +4 -3
  22. package/skills/easysociable-template/workflows/MULTI_PLATFORM_FAMILY.md +81 -0
  23. package/skills/easysociable-template/workflows/PUBLISH_FROM_DRAFT.md +1 -1
  24. package/skills/easysociable-template/workflows/VISUAL_QA.md +10 -0
  25. package/skills/easysociable-content/INSTALL.md +0 -60
  26. package/skills/easysociable-content/platforms/claude.md +0 -4
  27. package/skills/easysociable-content/platforms/codex.md +0 -4
  28. package/skills/easysociable-content/platforms/hermes.md +0 -4
  29. package/skills/easysociable-content/platforms/openclaw.md +0 -4
  30. package/skills/easysociable-content/references/CLI.md +0 -40
  31. package/skills/easysociable-content/references/CONTRACT_SYNC.md +0 -42
  32. package/skills/easysociable-content/references/MCP.md +0 -15
  33. package/skills/easysociable-content/references/PAGE_PACK.md +0 -129
  34. package/skills/easysociable-content/references/PLATFORM_GUIDE.md +0 -36
  35. package/skills/easysociable-content/references/RUN_LAYOUT.md +0 -73
  36. package/skills/easysociable-content/references/TROUBLESHOOTING.md +0 -13
  37. package/skills/easysociable-content/references/VAULT.md +0 -40
  38. package/skills/easysociable-content/references/VOICE.md +0 -16
  39. package/skills/easysociable-content/scripts/package-skill.mjs +0 -49
  40. package/skills/easysociable-content/scripts/setup.mjs +0 -200
  41. package/skills/easysociable-content/scripts/setup.test.mjs +0 -82
  42. package/skills/easysociable-content/workflows/ANALYSIS_AND_COVERAGE.md +0 -17
  43. package/skills/easysociable-content/workflows/CONTENT_EXPORT.md +0 -24
  44. package/skills/easysociable-content/workflows/GETTING_STARTED.md +0 -40
  45. package/skills/easysociable-content/workflows/MCP_FIRST.md +0 -5
  46. package/skills/easysociable-content/workflows/OUT_OF_SCOPE.md +0 -18
  47. package/skills/easysociable-content/workflows/PACK_AUTHORING.md +0 -42
  48. package/skills/easysociable-content/workflows/SWIPE_CAPTURE.md +0 -18
  49. package/skills/easysociable-content/workflows/TOPIC_DRAFT.md +0 -29
  50. package/skills/easysociable-content/workflows/WORKING_DRAFT.md +0 -19
  51. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/draft.md +0 -0
  52. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/idea.md +0 -0
  53. /package/{skills/easysociable-content → content-engine}/fixtures/golden-run-en/pack-tiktok.json +0 -0
  54. /package/{skills/easysociable-content → content-engine}/scripts/contracts.mjs +0 -0
  55. /package/{skills/easysociable-content → content-engine}/scripts/export-contracts.mjs +0 -0
  56. /package/{skills/easysociable-content → content-engine}/scripts/fixture.test.mjs +0 -0
  57. /package/{skills/easysociable-content → content-engine}/scripts/starter.mjs +0 -0
  58. /package/{skills/easysociable-content → content-engine}/scripts/validate-export.mjs +0 -0
  59. /package/{skills/easysociable-content → content-engine}/scripts/validate-pack.mjs +0 -0
  60. /package/{skills/easysociable-content → content-engine}/scripts/validate-run.mjs +0 -0
  61. /package/{skills/easysociable-content → content-engine}/scripts/validate.test.mjs +0 -0
  62. /package/{skills/easysociable-content → content-engine}/scripts/workbench.mjs +0 -0
  63. /package/{skills/easysociable-content → content-engine}/starter/CLAUDE.md +0 -0
  64. /package/{skills/easysociable-content → content-engine}/starter/accounts/README.md +0 -0
  65. /package/{skills/easysociable-content → content-engine}/starter/accounts/_index.md +0 -0
  66. /package/{skills/easysociable-content → content-engine}/starter/accounts/overrides/README.md +0 -0
  67. /package/{skills/easysociable-content → content-engine}/starter/discovery/README.md +0 -0
  68. /package/{skills/easysociable-content → content-engine}/starter/discovery/_index.md +0 -0
  69. /package/{skills/easysociable-content → content-engine}/starter/discovery/_template.md +0 -0
  70. /package/{skills/easysociable-content → content-engine}/starter/engine.json +0 -0
  71. /package/{skills/easysociable-content → content-engine}/starter/exports/README.md +0 -0
  72. /package/{skills/easysociable-content → content-engine}/starter/inbox/README.md +0 -0
  73. /package/{skills/easysociable-content → content-engine}/starter/inbox/_index.md +0 -0
  74. /package/{skills/easysociable-content → content-engine}/starter/inbox/entries/README.md +0 -0
  75. /package/{skills/easysociable-content → content-engine}/starter/platforms/README.md +0 -0
  76. /package/{skills/easysociable-content → content-engine}/starter/platforms/ig.md +0 -0
  77. /package/{skills/easysociable-content → content-engine}/starter/platforms/instagram.md +0 -0
  78. /package/{skills/easysociable-content → content-engine}/starter/platforms/linkedin.md +0 -0
  79. /package/{skills/easysociable-content → content-engine}/starter/platforms/threads.md +0 -0
  80. /package/{skills/easysociable-content → content-engine}/starter/platforms/tiktok.md +0 -0
  81. /package/{skills/easysociable-content → content-engine}/starter/platforms/x.md +0 -0
  82. /package/{skills/easysociable-content → content-engine}/starter/platforms/xiaohongshu.md +0 -0
  83. /package/{skills/easysociable-content → content-engine}/starter/profiles/_index.md +0 -0
  84. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/README.md +0 -0
  85. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/audience.md +0 -0
  86. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/pillars.md +0 -0
  87. /package/{skills/easysociable-content → content-engine}/starter/profiles/default/voice.md +0 -0
  88. /package/{skills/easysociable-content → content-engine}/starter/published/_index.md +0 -0
  89. /package/{skills/easysociable-content → content-engine}/starter/raw/README.md +0 -0
  90. /package/{skills/easysociable-content → content-engine}/starter/raw/_index.md +0 -0
  91. /package/{skills/easysociable-content → content-engine}/starter/runs/README.md +0 -0
  92. /package/{skills/easysociable-content → content-engine}/starter/runs/_index.md +0 -0
  93. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/brief.md +0 -0
  94. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/draft.md +0 -0
  95. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/editor.md +0 -0
  96. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/feedback.md +0 -0
  97. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/idea.md +0 -0
  98. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/pack.md +0 -0
  99. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/packet.md +0 -0
  100. /package/{skills/easysociable-content → content-engine}/starter/runs/_template/rubric.md +0 -0
  101. /package/{skills/easysociable-content → content-engine}/starter/swipe/_index.md +0 -0
  102. /package/{skills/easysociable-content → content-engine}/starter/swipe/_template.md +0 -0
  103. /package/{skills/easysociable-content → content-engine}/starter/topics/README.md +0 -0
  104. /package/{skills/easysociable-content → content-engine}/starter/topics/WATCHLIST.md +0 -0
  105. /package/{skills/easysociable-content → content-engine}/starter/topics/_index.md +0 -0
  106. /package/{skills/easysociable-content → content-engine}/starter/topics/_template-item.md +0 -0
  107. /package/{skills/easysociable-content → content-engine}/starter/topics/items/README.md +0 -0
  108. /package/{skills/easysociable-content → content-engine}/starter/topics/scoring.md +0 -0
  109. /package/{skills/easysociable-content → content-engine}/starter/topics/watchlists/README.md +0 -0
  110. /package/{skills/easysociable-content → content-engine}/starter/topics/watchlists/_shared.md +0 -0
  111. /package/{skills/easysociable-content → content-engine}/starter/topics/watchlists/default.md +0 -0
  112. /package/{skills/easysociable-content → content-engine}/starter/wiki/README.md +0 -0
  113. /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_index.md +0 -0
  114. /package/{skills/easysociable-content → content-engine}/starter/wiki/atoms/_template.md +0 -0
  115. /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_index.md +0 -0
  116. /package/{skills/easysociable-content → content-engine}/starter/wiki/claims/_template.md +0 -0
  117. /package/{skills/easysociable-content → content-engine}/starter/workbench/README.md +0 -0
  118. /package/{skills/easysociable-content → content-engine}/workbench/build.py +0 -0
  119. /package/{skills/easysociable-content → content-engine}/workbench/serve.py +0 -0
  120. /package/{skills/easysociable-content → content-engine}/workbench/template.html +0 -0
@@ -1,82 +0,0 @@
1
- import assert from 'node:assert/strict'
2
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
3
- import { tmpdir } from 'node:os'
4
- import { join } from 'node:path'
5
- import { spawnSync } from 'node:child_process'
6
-
7
- const script = new URL('./setup.mjs', import.meta.url).pathname
8
- const fixture = mkdtempSync(join(tmpdir(), 'easysociable-content-'))
9
- const root = join(fixture, 'Workspace')
10
- mkdirSync(root)
11
- const env = { ...process.env, EASYSOCIABLE_NO_OPEN: 'true' }
12
-
13
- function run(args) {
14
- return spawnSync(process.execPath, [script, ...args, '--json'], { encoding: 'utf8', env })
15
- }
16
-
17
- try {
18
- const missingRoot = run(['--preview'])
19
- assert.equal(missingRoot.status, 2)
20
- assert.equal(JSON.parse(missingRoot.stdout).code, 'ROOT_REQUIRED')
21
-
22
- const preview = run(['--root', root, '--preview'])
23
- assert.equal(preview.status, 0)
24
- const previewReport = JSON.parse(preview.stdout)
25
- assert.equal(previewReport.created.length, 0)
26
- assert.equal(previewReport.valid, true)
27
- assert.equal(previewReport.rootName, 'Content Engine')
28
-
29
- const apply = run(['--root', root, '--apply', '--no-open'])
30
- assert.equal(apply.status, 0, apply.stdout + apply.stderr)
31
- const applied = JSON.parse(apply.stdout)
32
- assert.equal(applied.action, 'applied')
33
- assert.equal(applied.created.length > 10, true)
34
- const engine = join(root, 'Content Engine')
35
- assert.equal(readFileSync(join(engine, 'CLAUDE.md'), 'utf8').includes('one platform = one Run') || readFileSync(join(engine, 'CLAUDE.md'), 'utf8').includes('One folder = one platform'), true)
36
- const engineJson = JSON.parse(readFileSync(join(engine, 'engine.json'), 'utf8'))
37
- assert.equal(engineJson.schemaVersion, 'content-engine.v1')
38
- assert.equal(engineJson.root, 'Content Engine')
39
- assert.equal(engineJson.paths.runs, 'runs')
40
- assert.equal(existsSync(join(engine, 'runs', '_template', 'idea.md')), true)
41
- assert.equal(existsSync(join(engine, 'runs', '_template', 'run.md')), false)
42
- assert.equal(existsSync(join(engine, 'platforms', 'ig.md')), true)
43
- assert.equal(existsSync(join(engine, 'discovery', '_template.md')), true)
44
- assert.equal(existsSync(join(engine, 'discovery', '_index.md')), true)
45
- assert.equal(readFileSync(join(engine, 'CLAUDE.md'), 'utf8').includes('§ Discovery'), true)
46
- assert.equal(existsSync(join(engine, 'workbench', 'build.py')), true)
47
- assert.equal(existsSync(join(engine, 'workbench', 'template.html')), true)
48
- assert.equal(existsSync(join(engine, 'workbench', 'index.html')), true)
49
- const sentinel = join(engine, 'runs', 'user-note.md')
50
- writeFileSync(sentinel, 'keep me', 'utf8')
51
- const customTemplate = join(engine, 'workbench', 'template.html')
52
- const before = readFileSync(customTemplate, 'utf8')
53
- writeFileSync(customTemplate, `${before}\n<!-- user-custom -->\n`, 'utf8')
54
- const second = run(['--root', root, '--apply', '--no-open'])
55
- assert.equal(second.status, 0)
56
- assert.equal(readFileSync(sentinel, 'utf8'), 'keep me')
57
- assert.equal(readFileSync(customTemplate, 'utf8').includes('user-custom'), true)
58
- assert.equal(JSON.parse(second.stdout).created.includes('CLAUDE.md'), false)
59
-
60
- const detectRoot = join(fixture, 'DetectRoot')
61
- const detectEngine = join(detectRoot, 'MyFolder', 'Content Engine')
62
- mkdirSync(detectEngine, { recursive: true })
63
- const detect = spawnSync(process.execPath, [script, '--detect', '--json'], {
64
- encoding: 'utf8',
65
- env: { ...env, EASYSOCIABLE_ENGINE_SEARCH_ROOTS: detectRoot },
66
- })
67
- assert.equal(detect.status, 0, detect.stdout + detect.stderr)
68
- const detectReport = JSON.parse(detect.stdout)
69
- assert.equal(detectReport.action, 'detect')
70
- assert.equal(detectReport.engines.includes(detectEngine), true)
71
-
72
- const validateOk = run(['--root', root, '--validate'])
73
- assert.equal(validateOk.status, 0)
74
- rmSync(join(engine, 'engine.json'))
75
- const validateMissing = run(['--root', root, '--validate'])
76
- assert.equal(validateMissing.status, 2)
77
-
78
- console.log('Content Skill setup smoke passed.')
79
- }
80
- finally {
81
- rmSync(fixture, { recursive: true, force: true })
82
- }
@@ -1,17 +0,0 @@
1
- # Local analysis notes
2
-
3
- Research before a topic or run exists. Capture still follows engine `CLAUDE.md` § Capture when the user is storing a source.
4
-
5
- ## Workflow
6
-
7
- 1. Save sources under `raw/` + `raw/_index.md` when the capture has a URL / structure / media.
8
- 2. Working notes: `inbox/entries/C-….md` + `inbox/_index.md`.
9
- 3. Do not silent-write swipe/atoms/claims.
10
- 4. Network tools are optional; never block on search.
11
-
12
- ## Done when
13
-
14
- - Capture Card returned (if this was a capture)
15
- - Gaps listed as checklist items the user can answer
16
-
17
- Next: topics or 开一单 per `CLAUDE.md` — not a multi-platform draft in one folder.
@@ -1,24 +0,0 @@
1
- # Pack and export workflow
2
-
3
- The Content Skill records the run and verifies the local export. It does not render.
4
-
5
- ```text
6
- one-platform run
7
- → pack.md (slideshow, after SHIP)
8
- → Slideshow/Template skill writes pack JSON / fill-slots
9
- → Studio preview
10
- → user confirmation
11
- → PNG export
12
- → {engine}/exports/<run-slug>/01.png + manifest.json
13
- ```
14
-
15
- After export:
16
-
17
- ```bash
18
- node scripts/validate-export.mjs \
19
- --export <engine>/exports/<run-slug> \
20
- --expected-pages <N> --json
21
- node scripts/validate-run.mjs --run <run-dir> --require-export --json
22
- ```
23
-
24
- Set `runs/_index` `export=yes` only when the directory validates. Preview never consumes Render Page allowance; final rendering does.
@@ -1,40 +0,0 @@
1
- # Getting started
2
-
3
- After setup, the observatory is `http://127.0.0.1:8765/workbench/`. The user works in chat. The Agent writes markdown. Follow engine `CLAUDE.md`.
4
-
5
- ## 1. Confirm the engine
6
-
7
- Read `Content Engine/engine.json` and `CLAUDE.md`. Replace starter `your-handle` / `profiles/default/` before the first serious draft.
8
-
9
- ## 2. Optional local voice (skip allowed)
10
-
11
- Ask once whether to fill `profiles/default/voice.md`. This is **local copy persona** — not the hosted Brand Profile (`references/VOICE.md`). Setup must not call `easysociable profiles create`.
12
-
13
- ## 3. One platform = one run (tracer)
14
-
15
- Walk one local loop before any hosted render:
16
-
17
- 1. **Ask platform** if unset. One platform this time (e.g. `x` or `tiktok`).
18
- 2. Copy `runs/_template/` → `runs/<YYYY-MM-DD-slug[-platform]>/`.
19
- 3. Fill `idea.md` (platform + `swipe_id` / `atoms` / `claim_id`, `none` OK).
20
- 4. Append a row on `runs/_index.md` (`status=open`).
21
- 5. Read `platforms/<platform>.md`, then brief → packet → draft → editor → rubric.
22
- 6. **x text:** stop at SHIP / READY_TO_POST. No Pack JSON.
23
- 7. **Slideshow platform:** after SHIP write `pack.md`. Pack JSON waits for Slideshow handoff.
24
-
25
- Rebuild workbench after writes: `python3 workbench/build.py`.
26
-
27
- Watchlist scans write **Discovery** (`discovery/D-*.md`), not Topics. Promote a Discovery to a Topic only when the user names it.
28
-
29
- ## 4. First render (when ready)
30
-
31
- - **Multi-page** → `easysociable-slideshow` writes `pack-<platform>.json`, then Studio → PNG.
32
- - **Single-page** → `easysociable-template`.
33
-
34
- PNGs land at `{engine}/exports/<run-slug>/`.
35
-
36
- ## Done when
37
-
38
- - Workbench opens and shows the new run row.
39
- - User knows 开一单 asks platform(s) and splits N platforms into N folders.
40
- - User knows Pack JSON is a render handoff, not the default run file.
@@ -1,5 +0,0 @@
1
- # Filesystem-first, then hosted MCP
2
-
3
- There is no Content MCP in V1. Use filesystem tools to write the engine, then the unified EasySociable MCP for hosted Template/Slideshow operations. If MCP is unavailable, use equivalent `easysociable` CLI commands.
4
-
5
- Never start a Local API or open SQLite. Do not require Obsidian.
@@ -1,18 +0,0 @@
1
- # Out of scope (V1)
2
-
3
- This skill does not do:
4
-
5
- | Area | V1 boundary |
6
- |---|---|
7
- | Publication / social posting | User posts; Agent records URL + result |
8
- | UGC / SEO / PublicPiece | Deferred |
9
- | Hosted metrics backends | User-provided numbers in `feedback.md` only |
10
- | Device / iPhone automation | Not part of Content Skill |
11
- | Desktop app / browser extensions | Not part of Content Skill |
12
- | Content CLI / Content MCP / Local API | Use filesystem + workbench |
13
- | SQLite Content Engine | Not supported |
14
- | Obsidian install / vault detection | Not required |
15
- | Hosted Profile at setup | Create on first render via Slideshow/Template skill |
16
- | One run folder with many platform drafts | One platform = one run folder |
17
-
18
- If the user asks for any of the above, explain the boundary and offer the local Markdown alternative or hand off to the correct skill.
@@ -1,42 +0,0 @@
1
- # Pack authoring
2
-
3
- Vault-native pack is `pack.md` after rubric SHIP (slideshow platforms only).
4
- `content-pack.v1` JSON is written by **easysociable-slideshow** at render handoff — not during draft.
5
-
6
- Full rules: engine `CLAUDE.md` § PagePack + render.
7
-
8
- ## Vault pack
9
-
10
- 1. This run is already one platform. Copy `_template/pack.md` → `pack.md` (or `pack-<platform>.md`).
11
- 2. Public slots only. No private AST. No fake images.
12
- 3. Show a Pack Card in chat.
13
-
14
- ## Handoff JSON
15
-
16
- Slideshow selects a published Page Template per page, then writes:
17
-
18
- ```json
19
- {
20
- "schemaVersion": "content-pack.v1",
21
- "platform": "tiktok",
22
- "title": "From idea.md",
23
- "pages": []
24
- }
25
- ```
26
-
27
- Validate:
28
-
29
- ```bash
30
- node scripts/validate-pack.mjs --file <run-dir>/pack-<platform>.json --platform <platform> --json
31
- node scripts/validate-run.mjs --run <run-dir> --require-pack --json
32
- ```
33
-
34
- Pure X text: no pack. `x` / `xiaohongshu` image → Template skill, not a Content Pack.
35
-
36
- ## Routing after SHIP
37
-
38
- | Condition | Hand off to |
39
- |---|---|
40
- | Single-page intent | `easysociable-template` |
41
- | Multi-page + slideshow platform | `easysociable-slideshow` |
42
- | `platform ∈ {x, xiaohongshu}` images | `easysociable-template` only |
@@ -1,18 +0,0 @@
1
- # Swipe capture
2
-
3
- Turn a reference post into a reusable **structure** under `swipe/`. Full rules: engine `CLAUDE.md` § Library ingest + § Swipe / atom library.
4
-
5
- ## When
6
-
7
- User shares a URL / pattern **and** approves 入库 as swipe. Never silent-seed from a run.
8
-
9
- ## Workflow
10
-
11
- 1. Copy `swipe/_template.md` → `swipe/<slug>.md`. Default `status: trial`, n=win=loss=0.
12
- 2. Add a row on `swipe/_index.md` (`profiles`, `platforms`, `form`, `one_liner`).
13
- 3. **No Evidence table** in the swipe file. Use history = `published/_index`.
14
- 4. Hit-status is `trial | working | dead` — not claim epistemology.
15
-
16
- If the user only said 记一下: **§ Capture** only, then library offer. Do not also open a run unless asked.
17
-
18
- Hand off to topics / 开一单 when the user wants production, not when capturing.
@@ -1,29 +0,0 @@
1
- # Topic draft
2
-
3
- Score **what to produce**. Full rules: engine `CLAUDE.md` § Topics + `topics/scoring.md`.
4
-
5
- Watchlist scans do **not** create Topics. They create Discovery records (`CLAUDE.md` § Discovery). Topic scoring starts only when the user names an explicit input (Discovery ID, Capture ID, URL, or idea).
6
-
7
- ## Pipeline
8
-
9
- ```text
10
- explicit input → hard filters → Scout → (produce only) opportunity 5-dim → dual-gate verdict
11
- ```
12
-
13
- 1. Hard filters (`topics/scoring.md`). Fail → skip or `parked`.
14
- 2. **Scout gate** — set `purpose` (`discard` \| `library` \| `produce`) + `scout_label`.
15
- Default bias: **discard**. Cap **5 `produce`** per promotion session.
16
- 3. If `produce`: fill context / audience / conflict / insight / evidence fields, then score those five dims → `opp_score`.
17
- `ready` = opp ≥ **7.5** **and** audience ≥ **6**.
18
- Conflict > 5 requires a written `current_belief` and `belief_gap`.
19
- 4. If `library`: optional light item with `status: library`, or capture offer only — never `ready`.
20
- 5. Write `topics/items/T-YYYYMMDD-XX.md` from `_template-item.md`; add row on `topics/_index.md` (`opp` `aud` `purpose` `scout` + `src_*` when external).
21
- 6. Output **Opportunity Card** in chat.
22
-
23
- Suggested swipe/atoms/claim on the topic are **not** citations. Citations happen in `idea.md` when a run opens.
24
-
25
- ## Topic → run
26
-
27
- On `用 T-xxx 开一单`: **ask platform(s)** if unset. Create **one run per platform**, same `topic_id`. Mark topic `promoted`. List all RUN ids on the topic `run` column. Inherit opportunity fields into `brief.md`.
28
-
29
- Do not put multiple platforms in one run folder.
@@ -1,19 +0,0 @@
1
- # Working draft
2
-
3
- Write copy for **this run’s platform only**. Full gates: engine `CLAUDE.md` § Open a run.
4
-
5
- ## Path
6
-
7
- ```text
8
- Content Engine/runs/<YYYY-MM-DD-slug[-platform]>/
9
- ```
10
-
11
- ## Workflow
12
-
13
- 1. Load `platforms/<platform>.md` (required; `instagram` → `ig.md`).
14
- 2. Selection already in `idea.md` (`none` allowed with why).
15
- 3. Brief OK → `packet.md` → `draft.md` (this platform) → `editor.md` → `rubric.md`.
16
- 4. Align with `profiles/<id>/voice.md` + audience **core + this platform**.
17
- 5. Do **not** write `pack-<platform>.json` here. Image decks: `pack.md` only after SHIP.
18
-
19
- Sibling runs for the same topic each re-read their own craft file. No paste-across.