@jairodri/huckleberry-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/cos.json +20 -0
- package/agents/hermes/AGENTS.md +62 -0
- package/agents/hermes/SOUL.md +29 -0
- package/agents/hermes/fix-kimaki/SKILL.md +100 -0
- package/agents/hermes/hermes-fixer.md +115 -0
- package/agents/hermes.json +26 -0
- package/bin/huckleberry.js +4 -0
- package/kanban/SKILL.md +167 -0
- package/kanban/kanban +3 -0
- package/kanban/package.json +9 -0
- package/kanban/src/cli.mjs +553 -0
- package/kanban/src/dispatcher.mjs +479 -0
- package/kanban/src/server.mjs +108 -0
- package/kanban/templates/b2b-outreach.yaml +84 -0
- package/kanban/templates/blog-social-campaign.yaml +1161 -0
- package/kanban/templates/client-onboard.yaml +107 -0
- package/kanban/templates/cro-pipeline.yaml +296 -0
- package/kanban/templates/social-campaign.yaml +356 -0
- package/mcp/gemini-codegen-server.mjs +134 -0
- package/package.json +46 -0
- package/plugins/env-inject.ts +61 -0
- package/plugins/inkstone-gate.ts +55 -0
- package/scripts/heartbeat.sh +41 -0
- package/scripts/install-services.ps1 +82 -0
- package/scripts/install-services.sh +74 -0
- package/scripts/keep-awake.ps1 +48 -0
- package/scripts/keep-awake.sh +31 -0
- package/scripts/keepalive.sh +43 -0
- package/skills/curated.txt +68 -0
- package/src/cli.js +227 -0
- package/src/interview.js +78 -0
- package/src/postinstall.js +22 -0
- package/taskmaster/SKILL.md +78 -0
- package/taskmaster/dispatcher.mjs +146 -0
- package/taskmaster/next-task.js +123 -0
- package/taskmaster/update-status.js +118 -0
- package/templates/AGENTS.md +90 -0
- package/templates/COS_PROTOCOLS.md +71 -0
- package/templates/EXECUTIVE-MODE.md +29 -0
- package/templates/HEARTBEAT.md +42 -0
- package/templates/IDENTITY.md +22 -0
- package/templates/MEMORY.md +17 -0
- package/templates/ORG.md +33 -0
- package/templates/SOUL.md +43 -0
- package/templates/TOOLS.md +66 -0
- package/templates/business-context-gate.md +9 -0
- package/templates/evergreen.md +29 -0
- package/templates/opencode.json +80 -0
- package/wiki/discord.md +52 -0
- package/wiki/inkstone.md +64 -0
- package/wiki/kimaki.md +48 -0
- package/wiki/opencode.md +43 -0
|
@@ -0,0 +1,1161 @@
|
|
|
1
|
+
name: Content Campaign (NLM-Grounded + Full Quality Stack + Learning Loop)
|
|
2
|
+
description: >
|
|
3
|
+
Full content pipeline with NLM-grounded drafts, intent-driven outlines, structural variation,
|
|
4
|
+
SEO-ready images with metas, complete schema (Article+FAQ+Author+Breadcrumb), and a feedback
|
|
5
|
+
loop that learns from every approval/rejection.
|
|
6
|
+
14-layer pipeline: Load Lessons → Thesis → Research → Intent+Outline → NLM Draft → Hooks →
|
|
7
|
+
Polish → Enrich (images+schema) → Publish → Index → Distribute → Links → Track → Learn.
|
|
8
|
+
NLM writes from a structured intent outline (not freestyle). Harper agent enforces brand voice.
|
|
9
|
+
Every rejection feeds Inkstone + evergreen so the system improves with every article.
|
|
10
|
+
See: workspace/kimaki-kanban/content-quality-standard.md for the full spec.
|
|
11
|
+
Brand-agnostic.
|
|
12
|
+
|
|
13
|
+
variables:
|
|
14
|
+
- name: topic
|
|
15
|
+
required: true
|
|
16
|
+
description: The content topic or keyword focus
|
|
17
|
+
- name: tenant
|
|
18
|
+
required: true
|
|
19
|
+
description: Brand/project tenant name (maps to a kimaki project)
|
|
20
|
+
- name: audience
|
|
21
|
+
default: general
|
|
22
|
+
description: Target audience for the content
|
|
23
|
+
- name: platforms
|
|
24
|
+
default: twitter,linkedin,reddit,medium
|
|
25
|
+
description: Comma-separated list of social platforms
|
|
26
|
+
- name: article_type
|
|
27
|
+
default: standard
|
|
28
|
+
description: "Article type: standard, vs (comparison), alternatives (roundup), storytelling, how_to, guide"
|
|
29
|
+
- name: language
|
|
30
|
+
default: en
|
|
31
|
+
description: "Article language code: en, es, fr, etc."
|
|
32
|
+
- name: funnel_id
|
|
33
|
+
required: false
|
|
34
|
+
description: Funnel ID (A-M) from the brand's funnels/ directory.
|
|
35
|
+
- name: funnel_stage
|
|
36
|
+
default: MOFU
|
|
37
|
+
description: "Funnel stage: TOFU, MOFU, or BOFU. Determines narrative arc and CTA."
|
|
38
|
+
- name: narrative_arc
|
|
39
|
+
required: false
|
|
40
|
+
description: "Override narrative arc. Auto-selected by funnel_stage if not set."
|
|
41
|
+
- name: icp_segment
|
|
42
|
+
required: false
|
|
43
|
+
description: "ICP segment this article targets (e.g. backpackers, car-campers, resort-managers). Drives pain points, language, and CTA."
|
|
44
|
+
- name: cluster_node_id
|
|
45
|
+
required: false
|
|
46
|
+
description: "Node ID in brand/topic-clusters.json. Used for internal linking and status tracking."
|
|
47
|
+
|
|
48
|
+
tasks:
|
|
49
|
+
# ── LAYER -1: LOAD PAST LESSONS ────────────────────────────
|
|
50
|
+
|
|
51
|
+
- id: load_lessons
|
|
52
|
+
title: "Load quality lessons: {{topic}}"
|
|
53
|
+
assignee: build
|
|
54
|
+
skills: []
|
|
55
|
+
priority: 5
|
|
56
|
+
gate: true
|
|
57
|
+
body: |
|
|
58
|
+
Before ANY work on this article, load all past rejection and success patterns
|
|
59
|
+
for this brand. This prevents repeating mistakes and reinforces what works.
|
|
60
|
+
Every downstream task receives the compiled avoidance brief.
|
|
61
|
+
|
|
62
|
+
**1. Query Inkstone for failure patterns:**
|
|
63
|
+
inkstone_memory_failures(query="{{tenant}} article rejection content quality")
|
|
64
|
+
If Inkstone is unavailable, skip gracefully (soft dependency).
|
|
65
|
+
|
|
66
|
+
**2. Query Inkstone for success patterns:**
|
|
67
|
+
inkstone_memory_search(
|
|
68
|
+
query="{{tenant}} article approved what worked",
|
|
69
|
+
namespace="/business/{{tenant}}/content-quality",
|
|
70
|
+
limit=5
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
**3. Read brand evergreen content quality lessons:**
|
|
74
|
+
Read businesses/{{tenant}}/evergreen.md
|
|
75
|
+
Look for a "Content Quality Lessons" section.
|
|
76
|
+
|
|
77
|
+
**4. Compile AVOIDANCE BRIEF (save to content/_drafts/{slug}/avoidance-brief.md):**
|
|
78
|
+
```
|
|
79
|
+
BRAND: {{tenant}}
|
|
80
|
+
DATE: [today]
|
|
81
|
+
|
|
82
|
+
DO NOT (past rejections):
|
|
83
|
+
- [list each failure pattern with specific fix]
|
|
84
|
+
|
|
85
|
+
DO (past successes):
|
|
86
|
+
- [list each success pattern to reinforce]
|
|
87
|
+
|
|
88
|
+
WATCH FOR:
|
|
89
|
+
- [recurring issues that need monitoring]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**5. This brief is passed to EVERY downstream task.**
|
|
93
|
+
Every subagent sees it. No excuses for repeating past mistakes.
|
|
94
|
+
|
|
95
|
+
# ── LAYER 0: SHARP-THESIS VALIDATION ──────────────────────
|
|
96
|
+
|
|
97
|
+
- id: thesis_validation
|
|
98
|
+
title: "Validate sharp thesis: {{topic}}"
|
|
99
|
+
assignee: build
|
|
100
|
+
skills: [sharp-thesis-validator]
|
|
101
|
+
parents: [load_lessons]
|
|
102
|
+
priority: 4
|
|
103
|
+
gate: true
|
|
104
|
+
body: |
|
|
105
|
+
Validate that "{{topic}}" passes the Sharp-Thesis (Cerebras) Test before any work begins.
|
|
106
|
+
This is Layer 0 — blocks all downstream tasks until PASS.
|
|
107
|
+
|
|
108
|
+
Use the `sharp-thesis-validator` skill (already loaded by dispatcher).
|
|
109
|
+
Pass to the skill: topic="{{topic}}", brand="{{tenant}}", mode="long-form"
|
|
110
|
+
|
|
111
|
+
**On PASS:** Mark complete. Proceed to research.
|
|
112
|
+
**On FAIL:** BLOCK. Present reframing suggestions to user.
|
|
113
|
+
User must approve a reframed topic before proceeding.
|
|
114
|
+
Update the {{topic}} variable with the reframed title.
|
|
115
|
+
|
|
116
|
+
**Criteria checked:**
|
|
117
|
+
1. Single arguable claim (not "X is important" but "X does Y because Z")
|
|
118
|
+
2. Concrete number (dollar, percentage, timeframe, count)
|
|
119
|
+
3. Urgency / why now (time-bound trigger)
|
|
120
|
+
4. Title expressibility ≤80 chars (or thesis-config override)
|
|
121
|
+
|
|
122
|
+
Brand context loaded from: businesses/*/brand-assets/thesis-config.md (if exists)
|
|
123
|
+
Claims blacklist checked against: brand-overrides.md + landscape.md
|
|
124
|
+
|
|
125
|
+
# ── LAYER 1: INTELLIGENCE ───────────────────────────────────
|
|
126
|
+
|
|
127
|
+
- id: research
|
|
128
|
+
title: "Research: {{topic}}"
|
|
129
|
+
assignee: researcher
|
|
130
|
+
skills: [keyword-research, subreddit-pain-extraction, competitive-intel, audience-research]
|
|
131
|
+
parents: [thesis_validation]
|
|
132
|
+
priority: 3
|
|
133
|
+
body: |
|
|
134
|
+
Research keywords, content gaps, pain points, and audience language for "{{topic}}" targeting {{audience}}.
|
|
135
|
+
This is Layer 1 of the Content Quality Standard. Gather ALL intelligence before NLM drafting.
|
|
136
|
+
Reference: workspace/kimaki-kanban/content-quality-standard.md
|
|
137
|
+
|
|
138
|
+
Call load-business-context with include_funnels: true before starting.
|
|
139
|
+
{{#funnel_id}}
|
|
140
|
+
FUNNEL: This content serves funnel {{funnel_id}}. Read funnels/{{funnel_id}}-*.md for CTA, buyer stage, and ICP segment.
|
|
141
|
+
All research must align with this funnel's conversion path and ICP.{{/funnel_id}}
|
|
142
|
+
|
|
143
|
+
**1. Keyword research + intent classification**
|
|
144
|
+
Run keyword research for search volume, competition data, and SERP gaps.
|
|
145
|
+
Classify each keyword by intent:
|
|
146
|
+
- informational (how to, what is, best) → TOFU
|
|
147
|
+
- evaluation (comparison, review, vs) → MOFU
|
|
148
|
+
- transactional (buy, price, get) → BOFU
|
|
149
|
+
The intent classification determines the article structure (see below).
|
|
150
|
+
|
|
151
|
+
**2. PAA extraction (CRITICAL for AEO version)**
|
|
152
|
+
Extract ALL People Also Ask questions from Google SERPs for the primary keyword.
|
|
153
|
+
Save these verbatim. The AEO version of the article uses these EXACT questions as H2 headings.
|
|
154
|
+
If PAA questions are not available (new/niche keyword), generate 5-7 questions from related searches.
|
|
155
|
+
|
|
156
|
+
**3. Pain point extraction**
|
|
157
|
+
Mine Reddit for pain points around "{{topic}}". Extract verbatim "pain phrases" buyers actually use.
|
|
158
|
+
These phrases go directly into the article and into the NLM prompt.
|
|
159
|
+
|
|
160
|
+
**4. ICP language bank**
|
|
161
|
+
{{#icp_segment}}
|
|
162
|
+
Target ICP: {{icp_segment}}. Build a phrase bank of exact words/phrases
|
|
163
|
+
this specific segment uses to describe their problem.
|
|
164
|
+
{{/icp_segment}}
|
|
165
|
+
{{^icp_segment}}
|
|
166
|
+
Build a phrase bank of exact words/phrases the target audience uses.
|
|
167
|
+
{{/icp_segment}}
|
|
168
|
+
|
|
169
|
+
**5. Competitor gap analysis**
|
|
170
|
+
Check who ranks, what angles they take, what they miss.
|
|
171
|
+
Identify the content gap this article fills.
|
|
172
|
+
|
|
173
|
+
**6. Article structure guidance**
|
|
174
|
+
Based on funnel stage + keyword intent, determine the article structure:
|
|
175
|
+
- TOFU + informational → Educational explainer (what is X, how X works)
|
|
176
|
+
- TOFU + problem-aware → Problem-solution (pain → mechanism → resolution)
|
|
177
|
+
- MOFU + evaluation → Balanced comparison (criteria → evaluate → recommend)
|
|
178
|
+
- BOFU + transactional → Decision guide (use case → options → pick)
|
|
179
|
+
- BOFU + comparison → Head-to-head (overview → criteria → feature-by-feature → verdict)
|
|
180
|
+
The structure guides section headings and flow but MUST NOT inject framework labels
|
|
181
|
+
(like "The Problem", "The Agitation", "Attention:", "Desire:") into the content itself.
|
|
182
|
+
Content should read as natural educational prose, not formulaic sales copy.
|
|
183
|
+
|
|
184
|
+
**7. Topic cluster lookup**
|
|
185
|
+
Read brand/topic-clusters.json if it exists. Find the node matching this topic
|
|
186
|
+
(or create a new one). Note:
|
|
187
|
+
- Parent node (for WP category assignment and internal linking)
|
|
188
|
+
- Child nodes (for deep-dive candidates)
|
|
189
|
+
- Sibling nodes (for related content links)
|
|
190
|
+
{{#cluster_node_id}}
|
|
191
|
+
Cluster node ID: {{cluster_node_id}}. Update status to "in_progress" in topic-clusters.json.
|
|
192
|
+
{{/cluster_node_id}}
|
|
193
|
+
|
|
194
|
+
**8. Internal link map**
|
|
195
|
+
Read brand/link-map.json. Note which pages this article should link to
|
|
196
|
+
and which pages should link back to this article.
|
|
197
|
+
|
|
198
|
+
Produce a combined research brief with:
|
|
199
|
+
- Keywords with intent classification
|
|
200
|
+
- PAA questions (verbatim, for AEO structure)
|
|
201
|
+
- Pain phrases (verbatim, for article body)
|
|
202
|
+
- ICP language bank
|
|
203
|
+
- Competitive gaps
|
|
204
|
+
- Selected article structure + explanation
|
|
205
|
+
- Funnel metadata (stage, CTA, arc)
|
|
206
|
+
- Topic cluster node info (parent, children, siblings)
|
|
207
|
+
- Internal link targets
|
|
208
|
+
Save output to the brand's content directory.
|
|
209
|
+
|
|
210
|
+
# ── LAYER 1.5: INTENT + NLM OUTLINE ─────────────────────────
|
|
211
|
+
|
|
212
|
+
- id: intent_outline
|
|
213
|
+
title: "Intent + NLM outline: {{topic}}"
|
|
214
|
+
assignee: harper
|
|
215
|
+
skills: [nlm-cli, seo-content]
|
|
216
|
+
parents: [research]
|
|
217
|
+
priority: 3
|
|
218
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/intent-outline.md|500"
|
|
219
|
+
body: |
|
|
220
|
+
Infer search intent from the keyword and build a structured NLM outline
|
|
221
|
+
that DIRECTLY ANSWERS that intent. This outline is the blueprint for the NLM draft.
|
|
222
|
+
Without this step, NLM writes freestyle and misses what the searcher actually wants.
|
|
223
|
+
|
|
224
|
+
Load the nlm-cli skill for NLM concepts. Use the notebooklm CLI (notebooklm-py v0.7.3)
|
|
225
|
+
for all commands. Run `notebooklm doctor` to verify auth. Use the notebook from research.
|
|
226
|
+
|
|
227
|
+
**1. CLASSIFY SEARCH INTENT from the primary keyword:**
|
|
228
|
+
Read the research brief. Determine the user's actual goal:
|
|
229
|
+
- Informational ("what is", "how does") → wants to understand a concept
|
|
230
|
+
- Problem-solving ("how to fix", "why does") → has a specific pain needing resolution
|
|
231
|
+
- Comparison ("X vs Y", "best X for") → choosing between options
|
|
232
|
+
- Transactional ("buy", "cost", "hire") → ready to take action
|
|
233
|
+
- Navigational ("login", "dashboard") → looking for a specific resource
|
|
234
|
+
|
|
235
|
+
State the inferred intent explicitly:
|
|
236
|
+
"The user searching '[PRIMARY KEYWORD]' wants: [INFERRED NEED]"
|
|
237
|
+
|
|
238
|
+
**2. QUERY NLM for a structured article OUTLINE (not the article):**
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
notebooklm generate report --format custom --wait --json \
|
|
242
|
+
"A user searched: '[PRIMARY KEYWORD]'
|
|
243
|
+
Their intent is: [CLASSIFIED INTENT from step 1]
|
|
244
|
+
What they actually want to know: [INFERRED NEED from step 1]
|
|
245
|
+
|
|
246
|
+
Create a detailed article OUTLINE (NOT the article itself) that:
|
|
247
|
+
- Opens by acknowledging their specific situation or pain
|
|
248
|
+
- Each H2 section answers a distinct sub-question they have
|
|
249
|
+
- Flows logically: context → problem → understanding → solution → action
|
|
250
|
+
- Includes these PAA questions as H2 sections: [insert PAA questions from research]
|
|
251
|
+
- Identifies where data, examples, frameworks, or visuals are needed
|
|
252
|
+
- Marks which sections need AEO-style concise answer blocks
|
|
253
|
+
|
|
254
|
+
STRUCTURAL VARIATION IS MANDATORY in the outline:
|
|
255
|
+
- NOT every H2 section should be the same depth. Vary deliberately.
|
|
256
|
+
Some sections are 1-2 paragraphs. Others are 4-5 paragraphs.
|
|
257
|
+
One section might be a single punchy callout.
|
|
258
|
+
- Mark the expected depth for each section (short/medium/long).
|
|
259
|
+
- This variation creates natural reading rhythm. Uniform sections are artificial.
|
|
260
|
+
|
|
261
|
+
For EACH section in the outline, specify:
|
|
262
|
+
- H2 heading (in the user's language, not industry jargon)
|
|
263
|
+
- What question this section answers
|
|
264
|
+
- Key points to cover (grounded in your sources)
|
|
265
|
+
- Expected depth: short (1-2 para), medium (3-4 para), or long (5+ para)
|
|
266
|
+
- Whether this section needs an AEO answer block (concise citable answer)
|
|
267
|
+
- Any data points or examples to include"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**3. SAVE the outline:**
|
|
271
|
+
businesses/{{tenant}}/content/_drafts/{slug}/intent-outline.md
|
|
272
|
+
|
|
273
|
+
This outline is the BLUEPRINT. The NLM draft in Layer 2 follows it section by section.
|
|
274
|
+
The structural variation markers (short/medium/long) ensure the article reads naturally.
|
|
275
|
+
|
|
276
|
+
# ── LAYER 2: NLM GROUNDING ────────────────────────────────
|
|
277
|
+
|
|
278
|
+
- id: nlm_draft
|
|
279
|
+
title: "NLM draft: {{topic}}"
|
|
280
|
+
assignee: harper
|
|
281
|
+
skills: [nlm-cli]
|
|
282
|
+
parents: [intent_outline]
|
|
283
|
+
priority: 3
|
|
284
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/narrative-draft.md|5000;businesses/{{tenant}}/content/_drafts/{{topic_slug}}/aeo-draft.md|2000"
|
|
285
|
+
body: |
|
|
286
|
+
Use NLM to write a grounded article draft from real expert sources.
|
|
287
|
+
NLM produces raw content. Our skills layer (hooks, voice DNA, humanizer) shapes it later.
|
|
288
|
+
|
|
289
|
+
Use the notebooklm CLI (notebooklm-py v0.7.3). Run `notebooklm doctor` to verify auth.
|
|
290
|
+
|
|
291
|
+
**1. Find and add sources**
|
|
292
|
+
Find relevant sources for "{{topic}}":
|
|
293
|
+
- Search YouTube for expert videos on the topic
|
|
294
|
+
- Search for podcast episodes (Podscan API or web search)
|
|
295
|
+
- Find authoritative articles and studies
|
|
296
|
+
Target 5-10 quality sources.
|
|
297
|
+
|
|
298
|
+
**2. Create or reuse NLM notebook**
|
|
299
|
+
Check if a notebook exists for this cluster (read brand/topic-clusters.json for notebook_id).
|
|
300
|
+
If not, create one:
|
|
301
|
+
```
|
|
302
|
+
notebooklm create "{{tenant}}: {{topic}}" --use
|
|
303
|
+
```
|
|
304
|
+
Add all sources (type is auto-detected):
|
|
305
|
+
```
|
|
306
|
+
notebooklm source add "https://youtube.com/watch?v=..."
|
|
307
|
+
notebooklm source add "https://example.com/article"
|
|
308
|
+
notebooklm source add "path/to/transcript.txt"
|
|
309
|
+
```
|
|
310
|
+
Wait 30-60 seconds for indexing after adding sources.
|
|
311
|
+
Save notebook_id to brand/topic-clusters.json.
|
|
312
|
+
|
|
313
|
+
**3. Generate or update mindmap**
|
|
314
|
+
Run mindmap creation to extract topic clusters:
|
|
315
|
+
```
|
|
316
|
+
notebooklm generate mind-map --instructions "{{topic}} clusters" --json
|
|
317
|
+
```
|
|
318
|
+
Parse the mindmap output. Save new nodes to brand/topic-clusters.json
|
|
319
|
+
(status: not_started, depth_level based on tree position).
|
|
320
|
+
|
|
321
|
+
**4. Query NLM for NARRATIVE version**
|
|
322
|
+
Use --format blog-post with --append to inject quality instructions.
|
|
323
|
+
The built-in blog-post format produces engaging content. Our --append adds structure.
|
|
324
|
+
|
|
325
|
+
CRITICAL: Read the outline from intent-outline.md (Layer 1.5). The --append text MUST
|
|
326
|
+
instruct NLM to follow that outline section by section.
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
notebooklm generate report --format blog-post --wait --json \
|
|
330
|
+
--append "Target audience: {{audience}}. Article type: {{article_type}}.
|
|
331
|
+
|
|
332
|
+
FOLLOW THIS OUTLINE (from intent-outline.md):
|
|
333
|
+
[Paste the full outline here, section by section]
|
|
334
|
+
|
|
335
|
+
REQUIREMENTS:
|
|
336
|
+
- Primary keyword: [from research brief]
|
|
337
|
+
- Pain points to address: [verbatim pain phrases from research]
|
|
338
|
+
- Narrative arc: {{narrative_arc}}
|
|
339
|
+
- 1500-2500 words
|
|
340
|
+
- Follow the outline structure exactly. Each H2 from the outline becomes a section.
|
|
341
|
+
- Respect the depth markers from the outline (short/medium/long sections).
|
|
342
|
+
|
|
343
|
+
STRUCTURAL VARIATION IS MANDATORY:
|
|
344
|
+
- NOT every H2 section should be the same length. This is the #1 AI writing tell.
|
|
345
|
+
- Some sections are 1-2 paragraphs. Others are 5-6 paragraphs. One might be a single sentence.
|
|
346
|
+
- Vary paragraph lengths too: mix 1-sentence punchy paragraphs with 4-5 sentence deep paragraphs.
|
|
347
|
+
- Use short paragraphs for emphasis and transitions. Use long ones for evidence and depth.
|
|
348
|
+
- No two consecutive paragraphs should be the same length.
|
|
349
|
+
- This creates natural human rhythm. Uniform structure signals AI-generated content.
|
|
350
|
+
|
|
351
|
+
- Include named frameworks and specific data from your sources
|
|
352
|
+
- Include quotable insights and stats with citations
|
|
353
|
+
- End with 5 FAQ questions and answers
|
|
354
|
+
- Language: {{language}}"
|
|
355
|
+
```
|
|
356
|
+
Save the narrative draft output.
|
|
357
|
+
|
|
358
|
+
**5. Query NLM for AEO version**
|
|
359
|
+
Structure around the PAA questions extracted in research. This version targets AI answer engines.
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
notebooklm generate report --format custom --wait --json \
|
|
363
|
+
"Create an AEO (Answer Engine Optimization) version about {{topic}}.
|
|
364
|
+
This version is designed to be cited by AI answer engines (ChatGPT, Perplexity, Google AI Overviews).
|
|
365
|
+
|
|
366
|
+
Structure around these EXACT questions from Google People Also Ask:
|
|
367
|
+
[Insert PAA questions verbatim from research brief]
|
|
368
|
+
|
|
369
|
+
For each question:
|
|
370
|
+
- H2 = the exact PAA phrasing (word for word)
|
|
371
|
+
- Answer: 150-300 words, direct and citable
|
|
372
|
+
- Include specific data points and named frameworks from your sources
|
|
373
|
+
- Include quotable stats
|
|
374
|
+
- End with a summary sentence that captures the key takeaway
|
|
375
|
+
|
|
376
|
+
If there are fewer than 5 PAA questions, generate additional questions from your sources.
|
|
377
|
+
Language: {{language}}"
|
|
378
|
+
```
|
|
379
|
+
Save the AEO draft output.
|
|
380
|
+
|
|
381
|
+
**6. Save outputs**
|
|
382
|
+
Save to the brand's content directory:
|
|
383
|
+
- narrative-draft.md (from NLM narrative query)
|
|
384
|
+
- aeo-draft.md (from NLM AEO query)
|
|
385
|
+
- nlm-sources-used.json (sources NLM cited)
|
|
386
|
+
- nlm-notebook-id.txt (for future deep-dives)
|
|
387
|
+
|
|
388
|
+
These drafts are RAW. The hooks task generates titles, the polish task applies voice DNA and humanizer.
|
|
389
|
+
|
|
390
|
+
# ── LAYER 3: HOOKS (AFTER NLM OUTLINE) ──────────────────────
|
|
391
|
+
|
|
392
|
+
- id: hooks
|
|
393
|
+
title: "Generate hooks: {{topic}}"
|
|
394
|
+
assignee: harper
|
|
395
|
+
skills: [hook-generator]
|
|
396
|
+
parents: [nlm_draft]
|
|
397
|
+
priority: 3
|
|
398
|
+
body: |
|
|
399
|
+
Generate hooks that FIT the NLM-generated outline and incorporate SEO keywords.
|
|
400
|
+
This is Layer 3 of the Content Quality Standard.
|
|
401
|
+
Hooks come AFTER the NLM draft because titles must match the actual content.
|
|
402
|
+
|
|
403
|
+
Load the research brief (keywords, PAA questions, pain phrases) AND the NLM draft.
|
|
404
|
+
|
|
405
|
+
**Tournament mode**: Generate 5+ hook variants, run through 5 parallel quality-gate
|
|
406
|
+
judge personas (skeptic, scanner, buyer, expert, outsider). Winner proceeds to standard quality-gate.
|
|
407
|
+
See: Skill quality-gate tournament mode.
|
|
408
|
+
|
|
409
|
+
Load hook-generator skill and follow its full workflow:
|
|
410
|
+
1. Read the NLM narrative draft to understand the actual content and angle.
|
|
411
|
+
2. Feed the research brief as source context (keywords, pain phrases, ICP language).
|
|
412
|
+
3. Generate hooks that:
|
|
413
|
+
- Match the actual NLM content (not generic to the topic)
|
|
414
|
+
- Incorporate the primary SEO keyword naturally
|
|
415
|
+
- Work as the article title AND the first social post line
|
|
416
|
+
- Create curiosity without clickbait
|
|
417
|
+
4. Generate across all 6 Sentence Strategies + 6 Formulas with Spice Mixing.
|
|
418
|
+
5. Include Contrarian Angles where appropriate.
|
|
419
|
+
6. Platform-match hooks for {{platforms}}.
|
|
420
|
+
7. Score all options.
|
|
421
|
+
|
|
422
|
+
Present top 3-5 hooks to user in Discord ranked by score.
|
|
423
|
+
**BLOCK this task — do NOT proceed to polish until user picks a hook.**
|
|
424
|
+
|
|
425
|
+
Hook rules: No em dashes. No colons in hooks. Under 15 words preferred.
|
|
426
|
+
The approved hook becomes the article title and first social post line.
|
|
427
|
+
Also generate 2-3 subtitle/subheading variants for the approved hook.
|
|
428
|
+
|
|
429
|
+
# ── LAYER 4: POLISH (REPLACES write + validate) ─────────────
|
|
430
|
+
|
|
431
|
+
- id: polish
|
|
432
|
+
title: "Polish NLM draft: {{topic}}"
|
|
433
|
+
assignee: harper
|
|
434
|
+
skills: [seo-content, blog-publish-pipeline, schema-markup, marketing-psychology, voice-brand-alignment, humanizer, concreteness-fixer, quality-gate]
|
|
435
|
+
parents: [hooks, nlm_draft]
|
|
436
|
+
priority: 2
|
|
437
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/narrative-draft-polished.md|5000;businesses/{{tenant}}/content/_drafts/{{topic_slug}}/aeo-draft-polished.md|2000"
|
|
438
|
+
body: |
|
|
439
|
+
Polish the NLM-generated draft. Apply hooks, voice DNA, humanizer, and quality gate.
|
|
440
|
+
This is Layer 4 of the Content Quality Standard.
|
|
441
|
+
The agent does NOT write from scratch. The agent refines NLM output.
|
|
442
|
+
|
|
443
|
+
CRITICAL: Output to SEPARATE polished files. Do NOT overwrite the raw NLM drafts.
|
|
444
|
+
- Read: narrative-draft.md (raw NLM output)
|
|
445
|
+
- Write: narrative-draft-polished.md (polished version)
|
|
446
|
+
- Read: aeo-draft.md (raw NLM output)
|
|
447
|
+
- Write: aeo-draft-polished.md (polished version)
|
|
448
|
+
The publish task reads the POLISHED files, not the raw drafts.
|
|
449
|
+
|
|
450
|
+
**Inputs:**
|
|
451
|
+
- NLM narrative draft (from nlm_draft task)
|
|
452
|
+
- NLM AEO draft (from nlm_draft task)
|
|
453
|
+
- Approved hook + subtitles (from hooks task)
|
|
454
|
+
- Research brief (keywords, PAA questions, pain phrases, ICP language)
|
|
455
|
+
|
|
456
|
+
**POLISH SEQUENCE (run in order):**
|
|
457
|
+
|
|
458
|
+
1. **Apply hooks**
|
|
459
|
+
- Replace NLM title with approved hook
|
|
460
|
+
- Add approved subtitles as H2 where appropriate
|
|
461
|
+
- Ensure the hook works as the opening line (narrative version)
|
|
462
|
+
|
|
463
|
+
2. **Voice-brand-alignment pass**
|
|
464
|
+
Load voice-brand-alignment skill. Load brand voice DNA from brand/voice-profile.md
|
|
465
|
+
or brand/voice-dna.json (whichever exists).
|
|
466
|
+
Verify the article matches brand voice. Fix any voice drift.
|
|
467
|
+
NLM does not know the brand voice. Our voice DNA system enforces it here.
|
|
468
|
+
|
|
469
|
+
3. **Humanizer pass**
|
|
470
|
+
Load humanizer skill. Strip ALL 24 AI writing patterns:
|
|
471
|
+
- Content patterns: significance inflation, promotional language, vague attributions, rule of three, generic conclusions
|
|
472
|
+
- Language patterns: AI vocabulary, copula avoidance, negative parallelisms, elegant variation, false ranges, passive voice
|
|
473
|
+
- Style patterns: em dashes (ZERO TOLERANCE), bold overuse, title case in headings
|
|
474
|
+
- Communication patterns: chatbot artifacts, sycophantic tone, filler phrases
|
|
475
|
+
Verify: zero em dashes, average sentence length under 15 words.
|
|
476
|
+
|
|
477
|
+
4. **Concreteness fixer**
|
|
478
|
+
Load concreteness-fixer skill. Replace vague abstract NLM language with specific concrete details.
|
|
479
|
+
NLM tends toward generalities. Make everything specific.
|
|
480
|
+
|
|
481
|
+
4.5. **Flow check (read-aloud simulation)**
|
|
482
|
+
Simulate reading the draft aloud, sentence by sentence.
|
|
483
|
+
Flow is 10x more important than grammar and punctuation (source: @TheCopyTitan).
|
|
484
|
+
A reader should never stumble, re-read, or feel jarred.
|
|
485
|
+
|
|
486
|
+
Check:
|
|
487
|
+
- Every sentence-to-sentence transition flows naturally (no abrupt topic jumps)
|
|
488
|
+
- One-breath rule: no sentence exceeds ~25 words (if you can't say it in one breath, split it)
|
|
489
|
+
- Opening words of consecutive sentences are varied (no "The... The... The..." repetition)
|
|
490
|
+
- Rhythm variation: mix short punchy sentences (3-7 words) with medium ones (10-20 words)
|
|
491
|
+
- No clunky word order that sounds wrong when spoken
|
|
492
|
+
- First sentence of each paragraph pulls the reader into the next
|
|
493
|
+
|
|
494
|
+
Fix every flagged spot. If a sentence reads awkwardly when spoken, rewrite it.
|
|
495
|
+
This catches what the humanizer misses: humanizer strips AI patterns per-sentence,
|
|
496
|
+
but flow is about how sentences connect sequentially.
|
|
497
|
+
|
|
498
|
+
5. **Structure verification (Layer 3)**
|
|
499
|
+
- SEO heading hierarchy: H2 to H3, no skipped levels, keyword in first H2
|
|
500
|
+
- AEO pair exists (narrative + Q&A versions, both polished)
|
|
501
|
+
- AEO version uses PAA questions as H2 headings (verbatim from research)
|
|
502
|
+
- Schema markup: Article + FAQPage (HowTo for guides, ItemList for roundups)
|
|
503
|
+
- Internal links: insert per link-map.json and topic-clusters.json
|
|
504
|
+
- Link to parent WP category (= cornerstone/hub)
|
|
505
|
+
- Link to sibling nodes (related articles in same cluster branch)
|
|
506
|
+
|
|
507
|
+
6. **Story verification (Layer 4)**
|
|
508
|
+
- Narrative arc: {{narrative_arc}}
|
|
509
|
+
- Emotional engagement: pain to hope to proof progression
|
|
510
|
+
- ICP language from research used naturally (verbatim phrases)
|
|
511
|
+
- Named frameworks included for shareability
|
|
512
|
+
|
|
513
|
+
7. **Quality gate checklist (ALL must pass):**
|
|
514
|
+
- [ ] Approved hook is the title and opening line
|
|
515
|
+
- [ ] Narrative arc matches funnel stage spec
|
|
516
|
+
- [ ] AEO pair exists (narrative + Q&A versions)
|
|
517
|
+
- [ ] AEO H2s match PAA questions verbatim
|
|
518
|
+
- [ ] Schema markup present (Article + FAQPage + Author + BreadcrumbList)
|
|
519
|
+
- [ ] At least 1 proprietary/first-party data point
|
|
520
|
+
- [ ] Internal links match link-map.json + topic-clusters.json
|
|
521
|
+
- [ ] Zero em dashes in entire article
|
|
522
|
+
- [ ] Average sentence length under 15 words
|
|
523
|
+
- [ ] No AI vocabulary or patterns
|
|
524
|
+
- [ ] Brand voice DNA match verified
|
|
525
|
+
- [ ] H2 sections vary in length (at least 2x difference between longest and shortest)
|
|
526
|
+
- [ ] Paragraph lengths vary (mix of 1-sentence and 4+ sentence paragraphs)
|
|
527
|
+
- [ ] No two consecutive paragraphs are the same length
|
|
528
|
+
- [ ] Flow verified: read-aloud simulation passed (no clunky transitions)
|
|
529
|
+
- [ ] No sentence exceeds 25 words (one-breath rule)
|
|
530
|
+
- [ ] Opening words of consecutive sentences are varied
|
|
531
|
+
- [ ] SEO images generated with alt text, title attr, caption, keyword filenames
|
|
532
|
+
- [ ] Funnel metadata present (funnel_stage, buyer_stage, cta, icp_segment, narrative_arc)
|
|
533
|
+
|
|
534
|
+
If ANY check fails, fix it before proceeding to enrich.
|
|
535
|
+
Do NOT pass to enrich with validation failures.
|
|
536
|
+
|
|
537
|
+
Output: narrative-draft-polished.md + aeo-draft-polished.md
|
|
538
|
+
Save to the brand's content directory.
|
|
539
|
+
NEVER overwrite the raw narrative-draft.md or aeo-draft.md files.
|
|
540
|
+
|
|
541
|
+
# ── LAYER 4.5: INDEPENDENT QUALITY REVIEW ──────────────────
|
|
542
|
+
|
|
543
|
+
- id: quality_review
|
|
544
|
+
title: "Quality review: {{topic}}"
|
|
545
|
+
assignee: build
|
|
546
|
+
skills: [quality-gate, voice-brand-alignment, humanizer]
|
|
547
|
+
parents: [polish]
|
|
548
|
+
priority: 2
|
|
549
|
+
gate: true
|
|
550
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/quality-review.md|200"
|
|
551
|
+
body: |
|
|
552
|
+
INDEPENDENT quality review of the polished drafts. This is NOT the same agent that polished.
|
|
553
|
+
This task catches what the polish agent missed. It is the last gate before enrichment.
|
|
554
|
+
|
|
555
|
+
Read the POLISHED files (NOT the raw NLM drafts):
|
|
556
|
+
- narrative-draft-polished.md
|
|
557
|
+
- aeo-draft-polished.md
|
|
558
|
+
|
|
559
|
+
Also load:
|
|
560
|
+
- The avoidance brief (from load_lessons task)
|
|
561
|
+
- Brand voice DNA (brand/voice-profile.md or brand/voice-dna.json)
|
|
562
|
+
- Research brief (keywords, PAA questions, pain phrases)
|
|
563
|
+
|
|
564
|
+
**REVIEW CHECKLIST (score each item PASS/FAIL with evidence):**
|
|
565
|
+
|
|
566
|
+
1. **AI slop detection** — Does this read like AI-generated content?
|
|
567
|
+
- Check for: uniform paragraph lengths, generic transitions, vague language,
|
|
568
|
+
significance inflation, promotional tone, "delve/leverage/tapestry/navigate"
|
|
569
|
+
- If ANY AI pattern detected: FAIL with specific quote
|
|
570
|
+
|
|
571
|
+
2. **Framework label detection** — Are there visible copywriting framework labels?
|
|
572
|
+
- Check for: PAS/AIDA/BAB/Shocking Fact/Fascination Bullets/Quotable Insight labels
|
|
573
|
+
- Check for: "Before (", "After (", "The Bridge", "Attention:", "Desire:", "Action:"
|
|
574
|
+
- If ANY label found: FAIL with specific quote
|
|
575
|
+
|
|
576
|
+
3. **Em dash audit** — Count em dashes (—) in the entire article
|
|
577
|
+
- ZERO tolerance. Even one em dash = FAIL
|
|
578
|
+
|
|
579
|
+
4. **Sentence length audit** — Average sentence length must be under 15 words
|
|
580
|
+
- Flag any sentence over 25 words (one-breath rule)
|
|
581
|
+
|
|
582
|
+
5. **Voice DNA match** — Does the article sound like the brand?
|
|
583
|
+
- Compare against brand voice DNA
|
|
584
|
+
- Flag any voice drift
|
|
585
|
+
|
|
586
|
+
6. **Structural variation** — Are sections varied in length?
|
|
587
|
+
- Longest section should be 2x+ the shortest
|
|
588
|
+
- No two consecutive paragraphs the same length
|
|
589
|
+
- If all sections are uniform: FAIL
|
|
590
|
+
|
|
591
|
+
7. **Intent alignment** — Does the article answer what the searcher actually wants?
|
|
592
|
+
- Cross-check with the inferred intent from research
|
|
593
|
+
- If article misses the actual question: FAIL
|
|
594
|
+
|
|
595
|
+
8. **Hook verification** — Is the approved hook the title and opening line?
|
|
596
|
+
- If NLM's original title is still there: FAIL
|
|
597
|
+
|
|
598
|
+
9. **AEO verification** — Does the AEO version use PAA questions as H2 headings?
|
|
599
|
+
- Must be verbatim from research
|
|
600
|
+
|
|
601
|
+
10. **Concreteness** — Are there specific numbers, named examples, real data?
|
|
602
|
+
- If everything is vague/general: FAIL
|
|
603
|
+
|
|
604
|
+
**OUTPUT: quality-review.md**
|
|
605
|
+
```
|
|
606
|
+
ARTICLE: {{topic}}
|
|
607
|
+
DATE: [today]
|
|
608
|
+
REVIEWER: Independent quality review agent
|
|
609
|
+
|
|
610
|
+
RESULTS:
|
|
611
|
+
[For each check: PASS/FAIL + evidence]
|
|
612
|
+
|
|
613
|
+
OVERALL: PASS / FAIL
|
|
614
|
+
|
|
615
|
+
IF FAIL:
|
|
616
|
+
- Specific issues found (with quotes)
|
|
617
|
+
- Required fixes (what to change before enrich)
|
|
618
|
+
- Send back to polish task with fix instructions
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**GATE BEHAVIOR:**
|
|
622
|
+
- If OVERALL = PASS: proceed to enrich
|
|
623
|
+
- If OVERALL = FAIL: block enrich, send review back to polish task
|
|
624
|
+
with specific fix instructions. Polish agent re-runs and this review fires again.
|
|
625
|
+
|
|
626
|
+
# ── LAYER 5: ENRICHMENT ─────────────────────────────────────
|
|
627
|
+
|
|
628
|
+
- id: enrich
|
|
629
|
+
title: "Enrich: images + links + data: {{topic}}"
|
|
630
|
+
assignee: harper
|
|
631
|
+
skills: [image-gen, visual-style, creative]
|
|
632
|
+
parents: [quality_review]
|
|
633
|
+
priority: 2
|
|
634
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/schema.jsonld|200;businesses/{{tenant}}/content/_drafts/{{topic_slug}}/image-metadata.json|100"
|
|
635
|
+
body: |
|
|
636
|
+
Enrich the polished article with visuals, data, and links.
|
|
637
|
+
This is Layer 5 of the Content Quality Standard.
|
|
638
|
+
|
|
639
|
+
**1. Featured/Hero Image (MANDATORY — Gemini Web Interface Method)**
|
|
640
|
+
|
|
641
|
+
The featured image is MANDATORY for every article. No article publishes without one.
|
|
642
|
+
Generate via Gemini web interface (no API keys needed). This is the proven method:
|
|
643
|
+
|
|
644
|
+
PREREQUISITE: Chrome must be running with remote debugging:
|
|
645
|
+
Chrome --remote-debugging-port=9222 --user-data-dir="$HOME/.gemini-image-profile" \
|
|
646
|
+
--in-process-gpu --disable-gpu-sandbox --disable-gpu-compositing --disable-software-rasterizer
|
|
647
|
+
|
|
648
|
+
If Chrome is not logged into Google, inject cookies from the user's main Chrome profile:
|
|
649
|
+
pip3 install --break-system-packages browser_cookie3
|
|
650
|
+
python3 -c "import browser_cookie3,json; cj=browser_cookie3.chrome(domain_name='google.com'); ..."
|
|
651
|
+
Then inject via CDP Network.setCookie for each cookie.
|
|
652
|
+
|
|
653
|
+
GENERATION PIPELINE (via CDP WebSocket on ws://localhost:9222):
|
|
654
|
+
a) Read brand/DESIGN.md for the exact AI image prompt for this article's topic
|
|
655
|
+
b) Navigate to https://gemini.google.com/app (fresh conversation)
|
|
656
|
+
c) Focus the Quill editor: document.querySelector('div.ql-editor.textarea')?.focus()
|
|
657
|
+
d) Type prompt via CDP Input.dispatchKeyEvent (char by char — NOT JS .fill() or .value=)
|
|
658
|
+
e) Click Send: document.querySelector('button[aria-label="Send message"]')?.click()
|
|
659
|
+
f) Poll every 5s for up to 3min: querySelectorAll('img').filter(naturalWidth > 200 && !gstatic)
|
|
660
|
+
g) When image appears: draw to canvas, toDataURL('image/png'), extract via chunked CDP reads
|
|
661
|
+
h) Save raw PNG to /tmp/mg-images/post-{ID}-gemini.png
|
|
662
|
+
|
|
663
|
+
RESIZE to 1200x630 (featured image standard):
|
|
664
|
+
sips --resampleWidth 1200 input.png --out tmp.png && sips -c 630 1200 tmp.png --out final.png
|
|
665
|
+
|
|
666
|
+
UPLOAD to WordPress:
|
|
667
|
+
POST /wp-json/wp/v2/media (Content-Type: image/png, Content-Disposition: attachment)
|
|
668
|
+
Then POST /wp-json/wp/v2/posts/{ID} with { featured_media: mediaId }
|
|
669
|
+
|
|
670
|
+
Reference implementation: ~/.claude/skills/gemini-image/SKILL.md
|
|
671
|
+
Full pipeline tested and working as of 2026-07-17.
|
|
672
|
+
|
|
673
|
+
**2. In-content visuals (SEO-ready with full metadata)**
|
|
674
|
+
Read brand/creative-kit.md for visual identity. Read brand/DESIGN.md for exact tokens.
|
|
675
|
+
{{#icp_segment}}
|
|
676
|
+
Use the ICP-specific visual variant for {{icp_segment}} if defined in creative-kit.md.
|
|
677
|
+
{{/icp_segment}}
|
|
678
|
+
Generate 2-3 in-content visuals using the same Gemini web method or image-gen skill:
|
|
679
|
+
- Diagrams, infographics, data visualizations
|
|
680
|
+
- All images must match brand aesthetic from creative-kit.md and DESIGN.md
|
|
681
|
+
|
|
682
|
+
Image emphasis by funnel stage ({{funnel_stage}}):
|
|
683
|
+
- TOFU: Social share image + 1 in-content visual
|
|
684
|
+
- MOFU: Hero image + 2-3 in-content visuals (infographic preferred)
|
|
685
|
+
- BOFU: Product/lifestyle images
|
|
686
|
+
|
|
687
|
+
FOR EACH IMAGE generate full SEO metadata (save to image-metadata.json):
|
|
688
|
+
- alt_text: Descriptive, includes primary keyword naturally, under 125 chars.
|
|
689
|
+
Screen-reader friendly. Never keyword-stuffed.
|
|
690
|
+
- title_attr: Brief description of the image (different from alt text).
|
|
691
|
+
- caption: 1 sentence adding context for the reader.
|
|
692
|
+
- filename: primary-keyword-descriptor.jpg (hyphenated, lowercase, no spaces).
|
|
693
|
+
Hero: {primary-keyword}-hero.jpg. Infographic: {primary-keyword}-infographic.jpg.
|
|
694
|
+
- og_image: Hero image URL for Open Graph / Twitter Card meta.
|
|
695
|
+
- dimensions: 1200x630 for hero/OG. 1200x675 for in-content (16:9).
|
|
696
|
+
- compression: Target under 100KB per image for web performance.
|
|
697
|
+
|
|
698
|
+
**2. Schema markup generation (CRITICAL for rich snippets)**
|
|
699
|
+
Generate complete JSON-LD schema blocks. Save as schema.jsonld in the article directory.
|
|
700
|
+
|
|
701
|
+
a) Article schema:
|
|
702
|
+
{
|
|
703
|
+
"@context": "https://schema.org",
|
|
704
|
+
"@type": "Article",
|
|
705
|
+
"headline": "[approved hook/title]",
|
|
706
|
+
"datePublished": "[publish date ISO]",
|
|
707
|
+
"dateModified": "[publish date ISO]",
|
|
708
|
+
"author": { "@id": "[author schema URL]" },
|
|
709
|
+
"image": "[hero image URL]",
|
|
710
|
+
"publisher": { "@id": "[publisher URL]" },
|
|
711
|
+
"mainEntityOfPage": "[article URL]"
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
b) FAQPage schema (extract from the 5 FAQ Q&As in the article):
|
|
715
|
+
{
|
|
716
|
+
"@context": "https://schema.org",
|
|
717
|
+
"@type": "FAQPage",
|
|
718
|
+
"mainEntity": [
|
|
719
|
+
{ "@type": "Question", "name": "[Q1]", "acceptedAnswer": { "@type": "Answer", "text": "[A1]" } },
|
|
720
|
+
... (all 5 FAQs)
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
c) Person (Author) schema (read from brand/author-bio.md):
|
|
725
|
+
{
|
|
726
|
+
"@context": "https://schema.org",
|
|
727
|
+
"@type": "Person",
|
|
728
|
+
"name": "[author name]",
|
|
729
|
+
"jobTitle": "[title]",
|
|
730
|
+
"url": "[author page URL]",
|
|
731
|
+
"image": "[author headshot URL]",
|
|
732
|
+
"sameAs": ["[social profile URLs]"],
|
|
733
|
+
"description": "[1-2 sentence bio]"
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
d) BreadcrumbList schema:
|
|
737
|
+
{
|
|
738
|
+
"@context": "https://schema.org",
|
|
739
|
+
"@type": "BreadcrumbList",
|
|
740
|
+
"itemListElement": [
|
|
741
|
+
{ "position": 1, "name": "Home", "item": "[site URL]" },
|
|
742
|
+
{ "position": 2, "name": "[category]", "item": "[category URL]" },
|
|
743
|
+
{ "position": 3, "name": "[article title]", "item": "[article URL]" }
|
|
744
|
+
]
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
Also generate HowTo or ItemList schema if article_type is how_to or alternatives respectively.
|
|
748
|
+
|
|
749
|
+
**2. First-party data**
|
|
750
|
+
Verify at least 1 proprietary data point is present in the article.
|
|
751
|
+
If none exists, flag it and use the best available: specific number, named outcome, unique comparison.
|
|
752
|
+
|
|
753
|
+
**3. External authority links**
|
|
754
|
+
Add minimum 3 outbound links to primary sources (studies, official docs, original research).
|
|
755
|
+
No link farms, no aggregators. Link to the ORIGINAL source.
|
|
756
|
+
|
|
757
|
+
**4. Internal links verification**
|
|
758
|
+
Verify internal links from topic-clusters.json are present:
|
|
759
|
+
- Link to parent WP category page (hub/cornerstone) for link juice concentration
|
|
760
|
+
- Link to sibling articles in same cluster branch
|
|
761
|
+
- Verify the article has been assigned to the correct WP category (parent hub keyword)
|
|
762
|
+
|
|
763
|
+
**5. Backlink targets**
|
|
764
|
+
Produce a list of 5-10 sites that should link to this article (for off-page SEO outreach).
|
|
765
|
+
|
|
766
|
+
Output: enriched narrative-draft.md + enriched aeo-draft.md + image files + image-metadata.json + schema.jsonld + backlink-targets.md
|
|
767
|
+
|
|
768
|
+
# ── LAYER 6: PUBLISH ────────────────────────────────────────
|
|
769
|
+
|
|
770
|
+
- id: publish
|
|
771
|
+
title: "Publish to WordPress: {{topic}}"
|
|
772
|
+
assignee: harper
|
|
773
|
+
skills: [blog-publish-pipeline]
|
|
774
|
+
parents: [enrich]
|
|
775
|
+
priority: 1
|
|
776
|
+
body: |
|
|
777
|
+
Publish the validated article to WordPress.
|
|
778
|
+
This is Layer 6 of the Content Quality Standard.
|
|
779
|
+
|
|
780
|
+
CRITICAL: Read the POLISHED files, NOT the raw NLM drafts:
|
|
781
|
+
- Read: narrative-draft-polished.md (NOT narrative-draft.md)
|
|
782
|
+
- Read: aeo-draft-polished.md (NOT aeo-draft.md)
|
|
783
|
+
The raw drafts are unpolished NLM output. The polished files have hooks, voice DNA,
|
|
784
|
+
humanizer, schema, and quality gate applied. Publishing raw drafts = publishing slop.
|
|
785
|
+
|
|
786
|
+
Load the blog-publish-pipeline skill and follow its workflow.
|
|
787
|
+
|
|
788
|
+
**1. WP Category assignment**
|
|
789
|
+
Read brand/topic-clusters.json. Find this article's parent node.
|
|
790
|
+
The parent node's keyword = the WP category name.
|
|
791
|
+
If the category does not exist in WP, create it:
|
|
792
|
+
POST /wp-json/wp/v2/categories {"name": "<parent keyword>", "slug": "<parent-slug>"}
|
|
793
|
+
Assign the article to this category. NEVER use "uncategorized".
|
|
794
|
+
|
|
795
|
+
**2. Upload images with SEO metadata**
|
|
796
|
+
Read image-metadata.json from the enrich task.
|
|
797
|
+
Upload each image via WP REST API:
|
|
798
|
+
POST /wp-json/wp/v2/media (multipart form data)
|
|
799
|
+
For each image, set in the upload payload:
|
|
800
|
+
- alt_text: from image-metadata.json alt_text field
|
|
801
|
+
- title: from image-metadata.json title_attr field
|
|
802
|
+
- caption: from image-metadata.json caption field
|
|
803
|
+
- description: brief description for media library
|
|
804
|
+
Record the returned media IDs for in-content image references.
|
|
805
|
+
|
|
806
|
+
**3. Publish narrative version first**
|
|
807
|
+
- Post via WP REST API (POST /wp-json/wp/v2/posts)
|
|
808
|
+
- Set status `publish` (or `draft` for review)
|
|
809
|
+
- Article body rules: NO `<h1>` (WP adds its own), NO inline hero `<img>` at start,
|
|
810
|
+
inject scoped CSS for readability
|
|
811
|
+
- In-content images: use the media IDs from step 2 with proper alt_text attributes
|
|
812
|
+
- Set featured image (hero media ID from step 2)
|
|
813
|
+
- Set category to the parent hub category (from topic-clusters.json)
|
|
814
|
+
- If language is not `en`: append `-{lang}` to filename, set Polylang language term
|
|
815
|
+
- If slug conflicts (gets `-2` suffix), fix via WP REST API
|
|
816
|
+
|
|
817
|
+
**3. Publish AEO version second**
|
|
818
|
+
- Use narrative's URL in the AEO handshake div
|
|
819
|
+
- No featured image on AEO. No author box on AEO.
|
|
820
|
+
- Orange handshake div linking to narrative.
|
|
821
|
+
- Set AEO category (typically Guides or equivalent).
|
|
822
|
+
|
|
823
|
+
**4. Cross-link handshake divs**
|
|
824
|
+
Update both posts with real URLs (replace placeholders).
|
|
825
|
+
- Narrative: blue handshake div links to AEO
|
|
826
|
+
- AEO: orange handshake div links to narrative
|
|
827
|
+
|
|
828
|
+
**5. AIOSEO metadata** (MANDATORY on narrative version):
|
|
829
|
+
Set via WP REST API PATCH with `aioseo_meta_data`:
|
|
830
|
+
- `description`: 120-160 chars, include target keyword near start
|
|
831
|
+
- `keyphrases`: object (NOT string): `{ "focus": { "keyphrase": "primary keyword" }, "additional": ["secondary", "tertiary"] }`
|
|
832
|
+
- `og_title`, `og_description`, `twitter_title`, `twitter_description`
|
|
833
|
+
|
|
834
|
+
**6. Schema injection** (MANDATORY on narrative version):
|
|
835
|
+
Read schema.jsonld from the enrich task. Inject all JSON-LD blocks into the post:
|
|
836
|
+
- If AIOSEO is available: set via `aioseo_meta_data.schema` (base64-encoded JSON-LD)
|
|
837
|
+
- Otherwise: inject as raw HTML in a Custom HTML block at the end of the post content:
|
|
838
|
+
`<script type="application/ld+json">{ ... }</script>`
|
|
839
|
+
- Inject Article, FAQPage, Person (Author), and BreadcrumbList schemas
|
|
840
|
+
- Verify by fetching the published page and checking for the script tags
|
|
841
|
+
|
|
842
|
+
**7. Article CTA**
|
|
843
|
+
The article CTA links to the lead magnet (NOT a MailPoet form embedded in the article).
|
|
844
|
+
The lead magnet page has the MailPoet subscription form.
|
|
845
|
+
CTA text depends on funnel stage:
|
|
846
|
+
- TOFU: "Get the free [lead magnet name]" → links to lead magnet page
|
|
847
|
+
- MOFU: "See the full guide" → links to cornerstone
|
|
848
|
+
- BOFU: conversion action → links to landing page
|
|
849
|
+
|
|
850
|
+
**8. Update topic cluster status**
|
|
851
|
+
After successful publish, update brand/topic-clusters.json:
|
|
852
|
+
- Set node status to "published"
|
|
853
|
+
- Set article_url to the published narrative URL
|
|
854
|
+
- Set aeo_url to the published AEO URL
|
|
855
|
+
- Set wp_post_id and wp_category_id
|
|
856
|
+
|
|
857
|
+
Save the published article's post IDs and URLs.
|
|
858
|
+
|
|
859
|
+
# ── LAYER 7: INDEX ──────────────────────────────────────────
|
|
860
|
+
|
|
861
|
+
- id: indexing
|
|
862
|
+
title: "Submit to Google/Bing: {{topic}}"
|
|
863
|
+
assignee: harper
|
|
864
|
+
skills: [auto-indexing]
|
|
865
|
+
parents: [publish]
|
|
866
|
+
priority: 1
|
|
867
|
+
body: |
|
|
868
|
+
Submit the published articles to search engines for indexing.
|
|
869
|
+
This is Layer 7 of the Content Quality Standard.
|
|
870
|
+
|
|
871
|
+
1. Run the auto-indexing skill (IndexNow notifies Google, Bing, Yandex, Seznam + sitemap pings)
|
|
872
|
+
2. Submit BOTH the narrative and AEO version URLs
|
|
873
|
+
3. Verify submission succeeded (check API responses)
|
|
874
|
+
4. Note: full indexing takes 24-48h. Verify via Google Search Console URL Inspection after 48h.
|
|
875
|
+
|
|
876
|
+
# ── LAYER 8: DISTRIBUTE ─────────────────────────────────────
|
|
877
|
+
|
|
878
|
+
- id: socialize
|
|
879
|
+
title: "Social campaign: {{topic}}"
|
|
880
|
+
assignee: social
|
|
881
|
+
skills: [nlm-cli, hook-generator, voice-brand-alignment, humanizer, content-atomizer, social-campaign, content-repost-manager, medium-publisher, linkedin-publisher]
|
|
882
|
+
parents: [indexing]
|
|
883
|
+
priority: 1
|
|
884
|
+
body: |
|
|
885
|
+
Generate and distribute a balanced social campaign for this article.
|
|
886
|
+
This is Layer 8 of the Content Quality Standard.
|
|
887
|
+
Every social post links to the article as the path to solve the user's pain.
|
|
888
|
+
|
|
889
|
+
{{#funnel_id}}
|
|
890
|
+
FUNNEL: All social posts serve funnel {{funnel_id}}. Use the funnel's CTA.
|
|
891
|
+
Each post must include: funnel_id={{funnel_id}}, buyer_stage, cta, icp_segment.{{/funnel_id}}
|
|
892
|
+
|
|
893
|
+
**INPUTS:**
|
|
894
|
+
- icp_segment: {{icp_segment}} (or "general")
|
|
895
|
+
- funnel_stage: {{funnel_stage}}
|
|
896
|
+
- keyword_intent: from research brief (informational/evaluation/transactional)
|
|
897
|
+
- social_mix: read from brand/funnel-map.md (recommended TOFU/MOFU/BOFU ratio)
|
|
898
|
+
- blog_article_url: from publish task
|
|
899
|
+
- NLM notebook_id: from nlm_draft task (for querying social angles)
|
|
900
|
+
|
|
901
|
+
**STAGE 1: NLM generates raw social angles (per platform)**
|
|
902
|
+
|
|
903
|
+
NLM provides grounded insight angles. Our skills layer adds hooks, voice DNA, humanizer.
|
|
904
|
+
|
|
905
|
+
For EACH platform, query NLM for raw angles:
|
|
906
|
+
```
|
|
907
|
+
notebooklm generate report --format custom --wait --json \
|
|
908
|
+
"Create [N] social media post angles for [PLATFORM] about {{topic}}.
|
|
909
|
+
Target audience: {{icp_segment}}.
|
|
910
|
+
Funnel stage: {{funnel_stage}}.
|
|
911
|
+
|
|
912
|
+
For each angle provide:
|
|
913
|
+
- A hook (attention grabber)
|
|
914
|
+
- A key insight with data from your sources
|
|
915
|
+
- A CTA pointing to this URL: [blog_article_url]
|
|
916
|
+
|
|
917
|
+
Platform constraints:
|
|
918
|
+
[X/Twitter: 280 chars max, hook-first, include 1 data point, end with implied CTA]
|
|
919
|
+
[Threads: 500 chars max, conversational, observational tone]
|
|
920
|
+
[Bluesky: 300 chars max, community-oriented, share insights as observations]
|
|
921
|
+
[Reddit: value-first, genuine, NOT promotional. Include target subreddit suggestion.]
|
|
922
|
+
Language: {{language}}"
|
|
923
|
+
```
|
|
924
|
+
|
|
925
|
+
For LONG-FORM teaser platforms:
|
|
926
|
+
```
|
|
927
|
+
notebooklm generate report --format custom --wait --json \
|
|
928
|
+
"Create a [PLATFORM] teaser article about {{topic}}.
|
|
929
|
+
This is NOT the full article. It is a SHORTER-FORM TEASER (300-500 words for LinkedIn,
|
|
930
|
+
500-800 words for Medium, 300-500 words for Substack).
|
|
931
|
+
|
|
932
|
+
Share ONE key insight from your sources. Create a curiosity gap.
|
|
933
|
+
End with: 'Read the full breakdown: [blog_article_url]'
|
|
934
|
+
|
|
935
|
+
Platform tone:
|
|
936
|
+
[LinkedIn: professional, impact-focused for {{icp_segment}}]
|
|
937
|
+
[Medium: editorial, executive summary style]
|
|
938
|
+
[Substack: personal, conversational newsletter style]
|
|
939
|
+
Language: {{language}}"
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
**STAGE 2: Our system processes raw angles**
|
|
943
|
+
|
|
944
|
+
FOR EACH platform's raw angles:
|
|
945
|
+
1. hook-generator: craft platform-native hooks (tournament scored)
|
|
946
|
+
Select hooks that match funnel_stage + ICP + keyword intent
|
|
947
|
+
2. voice-brand-alignment: apply brand voice DNA
|
|
948
|
+
Load voice DNA from brand/voice-profile.md or brand/voice-dna.json
|
|
949
|
+
NLM does not know the brand voice. Our voice DNA system enforces it.
|
|
950
|
+
3. humanizer: strip any AI patterns from NLM-sourced language
|
|
951
|
+
4. Platform format verification (character limits, hashtag norms, link placement)
|
|
952
|
+
5. Flow check (read-aloud simulation): Read each post aloud (simulate).
|
|
953
|
+
Social copy lives or dies on flow. If it doesn't sound natural spoken, it won't land.
|
|
954
|
+
Flag and rewrite any post that feels clunky, has awkward word order, or exceeds one breath.
|
|
955
|
+
Check opening-word variety across consecutive posts in a thread.
|
|
956
|
+
|
|
957
|
+
**STAGE 3: Campaign assembly (balanced per social_mix)**
|
|
958
|
+
|
|
959
|
+
Assemble the balanced campaign using the ratio from the funnel map:
|
|
960
|
+
- TOFU posts (awareness): pain point hooks, stat callouts, "did you know" angles
|
|
961
|
+
- MOFU posts (evaluation): comparison angles, framework explanations, data-backed insights
|
|
962
|
+
- BOFU posts (conversion): social proof, product angle, urgency
|
|
963
|
+
|
|
964
|
+
Every post links to blog_article_url as the path to solve the user's pain.
|
|
965
|
+
|
|
966
|
+
**STAGE 4: Long-form publishing**
|
|
967
|
+
|
|
968
|
+
- LinkedIn: publish via linkedin-publisher skill
|
|
969
|
+
- Medium: publish via medium-publisher skill
|
|
970
|
+
- Substack: publish via API or manual
|
|
971
|
+
- Reddit: genuine community posts in targeted subreddits
|
|
972
|
+
Use the pain phrases from research as the hook
|
|
973
|
+
Share the key finding, mention the full breakdown with link
|
|
974
|
+
Frame as helping the community, not self-promotion
|
|
975
|
+
|
|
976
|
+
**STAGE 5: Repurposing schedule**
|
|
977
|
+
Load content-repost-manager skill. Create an evergreen reposting schedule.
|
|
978
|
+
|
|
979
|
+
# ── LAYER 9: LINK NETWORK ───────────────────────────────────
|
|
980
|
+
|
|
981
|
+
- id: linkbacks
|
|
982
|
+
title: "Build link network: {{topic}}"
|
|
983
|
+
assignee: linker
|
|
984
|
+
skills: [off-page-seo, link-building-seo]
|
|
985
|
+
parents: [socialize]
|
|
986
|
+
priority: 1
|
|
987
|
+
deliverables: "businesses/{{tenant}}/content/_drafts/{{topic_slug}}/link-building-action-plan.md|500"
|
|
988
|
+
body: |
|
|
989
|
+
Build internal and external links for the published article.
|
|
990
|
+
This is Layer 9 of the Content Quality Standard.
|
|
991
|
+
|
|
992
|
+
**1. Internal link verification**
|
|
993
|
+
Verify the article contains all internal links from topic-clusters.json:
|
|
994
|
+
- Links to parent WP category (hub/cornerstone) for link juice concentration
|
|
995
|
+
- Links to sibling articles in same cluster branch
|
|
996
|
+
Verify that the parent category page and sibling articles link back to this article.
|
|
997
|
+
|
|
998
|
+
**2. External backlinks**
|
|
999
|
+
Load off-page-seo and link-building-seo skills.
|
|
1000
|
+
From the backlink targets identified in the enrich task:
|
|
1001
|
+
- Directory submission opportunities
|
|
1002
|
+
- Guest post targets
|
|
1003
|
+
- Social profile link opportunities
|
|
1004
|
+
- Resource page link opportunities
|
|
1005
|
+
|
|
1006
|
+
**3. Produce link building action plan**
|
|
1007
|
+
For each target: site name, URL, link type, contact method, priority.
|
|
1008
|
+
|
|
1009
|
+
**4. Social signals**
|
|
1010
|
+
Ensure social posts from the socialize task are live and generating engagement signals.
|
|
1011
|
+
|
|
1012
|
+
**5. Topic cluster update**
|
|
1013
|
+
Update brand/topic-clusters.json: mark any deep-dive child nodes as candidates
|
|
1014
|
+
for future content production based on article performance.
|
|
1015
|
+
|
|
1016
|
+
Output: link-building-action-plan.md with prioritized targets.
|
|
1017
|
+
|
|
1018
|
+
# ── LAYER 10: TRACKING ──────────────────────────────────────
|
|
1019
|
+
|
|
1020
|
+
- id: tracking
|
|
1021
|
+
title: "Track article: {{topic}}"
|
|
1022
|
+
assignee: tracker
|
|
1023
|
+
skills: [analytics-tracking]
|
|
1024
|
+
parents: [linkbacks]
|
|
1025
|
+
priority: 1
|
|
1026
|
+
body: |
|
|
1027
|
+
Record this article in the brand's content tracking system.
|
|
1028
|
+
Update brand/topic-clusters.json with publication status.
|
|
1029
|
+
|
|
1030
|
+
**1. Update content-tracker.json:**
|
|
1031
|
+
Append entry:
|
|
1032
|
+
{
|
|
1033
|
+
"topic": "{{topic}}",
|
|
1034
|
+
"slug": "{slug}",
|
|
1035
|
+
"published_date": "[today]",
|
|
1036
|
+
"narrative_url": "[URL]",
|
|
1037
|
+
"aeo_url": "[URL]",
|
|
1038
|
+
"wp_post_id": [ID],
|
|
1039
|
+
"keyword": "[primary keyword]",
|
|
1040
|
+
"funnel_id": "{{funnel_id}}",
|
|
1041
|
+
"funnel_stage": "{{funnel_stage}}",
|
|
1042
|
+
"icp_segment": "{{icp_segment}}",
|
|
1043
|
+
"cluster_node_id": "{{cluster_node_id}}",
|
|
1044
|
+
"social_posts": { "twitter": "[URL]", "linkedin": "[URL]", "reddit": "[URL]", "medium": "[URL]" },
|
|
1045
|
+
"status": "published",
|
|
1046
|
+
"review_result": null,
|
|
1047
|
+
"learnings": null
|
|
1048
|
+
}
|
|
1049
|
+
Save to: businesses/{{tenant}}/content/content-tracker.json
|
|
1050
|
+
|
|
1051
|
+
**2. Update topic-clusters.json:**
|
|
1052
|
+
Set node status to "published" with article URLs.
|
|
1053
|
+
|
|
1054
|
+
**3. Set up Google Search Console tracking:**
|
|
1055
|
+
Note the URL for 30-day ranking check (automated follow-up).
|
|
1056
|
+
|
|
1057
|
+
# ── LAYER 11: LEARN + FEEDBACK LOOP ─────────────────────────
|
|
1058
|
+
|
|
1059
|
+
- id: learn
|
|
1060
|
+
title: "Learn from review: {{topic}}"
|
|
1061
|
+
assignee: reviewer
|
|
1062
|
+
skills: []
|
|
1063
|
+
parents: [tracking]
|
|
1064
|
+
priority: 1
|
|
1065
|
+
body: |
|
|
1066
|
+
Capture what worked or failed. Feed lessons into Inkstone + brand evergreen.
|
|
1067
|
+
This prevents repeating mistakes and reinforces winning patterns.
|
|
1068
|
+
This is the final layer — the system gets smarter with every article.
|
|
1069
|
+
|
|
1070
|
+
This task fires in TWO modes:
|
|
1071
|
+
- APPROVAL MODE: When Jairo approves the article during batch review
|
|
1072
|
+
- REJECTION MODE: When Jairo rejects or requests revisions
|
|
1073
|
+
|
|
1074
|
+
## IF REJECTED:
|
|
1075
|
+
|
|
1076
|
+
**1. CAPTURE rejection reason (structured):**
|
|
1077
|
+
Present to Jairo: "What was wrong with '{{topic}}'?"
|
|
1078
|
+
Common categories (Jairo picks or describes):
|
|
1079
|
+
- voice_drift: doesn't sound like the brand
|
|
1080
|
+
- thin_content: lacks depth or substance
|
|
1081
|
+
- ai_slop: detectable AI patterns despite humanizer
|
|
1082
|
+
- wrong_intent: doesn't answer what the searcher wants
|
|
1083
|
+
- uniform_structure: all sections same length (the Harper bug)
|
|
1084
|
+
- missing_schema: no FAQ/Author schema for snippets
|
|
1085
|
+
- poor_images: images missing or no SEO metadata
|
|
1086
|
+
- factual_error: wrong information
|
|
1087
|
+
- weak_hook: title/opening doesn't grab
|
|
1088
|
+
- other: [Jairo describes]
|
|
1089
|
+
|
|
1090
|
+
Specific issue: [what exactly was wrong]
|
|
1091
|
+
Example passage: [quote the offending section]
|
|
1092
|
+
Fix: [what should have been done instead]
|
|
1093
|
+
|
|
1094
|
+
**2. WRITE TO INKSTONE (failure pattern):**
|
|
1095
|
+
```
|
|
1096
|
+
inkstone_memory_write(
|
|
1097
|
+
text="REJECTION for {{tenant}}: [category].
|
|
1098
|
+
Article: {{topic}}. Date: [today].
|
|
1099
|
+
Issue: [specific issue].
|
|
1100
|
+
Example: [passage].
|
|
1101
|
+
Fix: [correction].
|
|
1102
|
+
This is the Nth occurrence of this pattern.",
|
|
1103
|
+
namespace="/business/{{tenant}}/content-quality",
|
|
1104
|
+
knowledgeType="failure_pattern",
|
|
1105
|
+
confidence=0.9
|
|
1106
|
+
)
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
**3. UPDATE BRAND EVERGREEN:**
|
|
1110
|
+
Append to businesses/{{tenant}}/evergreen.md under "## Content Quality Lessons":
|
|
1111
|
+
```
|
|
1112
|
+
- [date] [category]: [lesson] (Article: {{topic}})
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
**4. ESCALATE if recurring:**
|
|
1116
|
+
If this pattern has occurred 3+ times (check Inkstone), add a HARD RULE to:
|
|
1117
|
+
- businesses/{{tenant}}/brand/voice-profile.md (voice-related)
|
|
1118
|
+
- businesses/{{tenant}}/brand/skill-context.json (structural/quality)
|
|
1119
|
+
|
|
1120
|
+
**5. QUEUE for rework:**
|
|
1121
|
+
Add article to the rework queue with specific fix instructions.
|
|
1122
|
+
The avoidance brief (Layer -1) will catch this on the next run.
|
|
1123
|
+
|
|
1124
|
+
## IF APPROVED:
|
|
1125
|
+
|
|
1126
|
+
**1. CAPTURE what worked:**
|
|
1127
|
+
Ask Jairo: "What landed with '{{topic}}'?"
|
|
1128
|
+
- Which hook pattern won?
|
|
1129
|
+
- Which voice elements resonated?
|
|
1130
|
+
- Which framework drove the structure?
|
|
1131
|
+
- What data point or insight was strongest?
|
|
1132
|
+
- Was single article or thread better for socials?
|
|
1133
|
+
|
|
1134
|
+
**2. WRITE TO INKSTONE (success pattern):**
|
|
1135
|
+
```
|
|
1136
|
+
inkstone_memory_write(
|
|
1137
|
+
text="SUCCESS for {{tenant}}: [what worked].
|
|
1138
|
+
Article: {{topic}}. Date: [today].
|
|
1139
|
+
Hook: [pattern]. Framework: [name].
|
|
1140
|
+
Insight: [what resonated].
|
|
1141
|
+
Social format: [what worked].",
|
|
1142
|
+
namespace="/business/{{tenant}}/content-quality",
|
|
1143
|
+
knowledgeType="success_pattern",
|
|
1144
|
+
confidence=0.85
|
|
1145
|
+
)
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
**3. REINFORCE winning patterns:**
|
|
1149
|
+
- If a hook pattern won 3+ times: add to brand hook templates
|
|
1150
|
+
- If a voice element landed: reinforce in voice-profile.md
|
|
1151
|
+
- If a structure worked: prioritize in future article planning
|
|
1152
|
+
|
|
1153
|
+
## ALWAYS:
|
|
1154
|
+
|
|
1155
|
+
**4. UPDATE content-tracker.json:**
|
|
1156
|
+
Set review_result: "approved" or "rejected" + learnings field with summary.
|
|
1157
|
+
|
|
1158
|
+
**5. INTELLIGENCE OUTPUT:**
|
|
1159
|
+
The avoidance brief (Layer -1) on the NEXT article for this brand
|
|
1160
|
+
will automatically pick up these lessons from Inkstone.
|
|
1161
|
+
The system is now smarter than it was before this article.
|