feat(linkedin-studio): N15 — do-next-kontrakt (recordDoNext + skrivere/lesere + forrige-utgave-kalibrering) [skip-docs]
Måling som ikke endrer neste utgave er teater: report/analyze/ab-test/48h-monitor endte alle i chat (grep do.next = 0 i hele repoet). N15 gjør kanalen til en kontrakt. - recordDoNext i hooks/scripts/state-updater.mjs (TDD, 17 nye tester): seksjonen Do-Next Directives, rader "[dato] (kilde) direktiv — evidence: peker". Levetid = erstatt-per-kilde + 60-dagers aldersgulv, maks 3 per skriv, additiv scalar last_donext_date, $-sikre replacement-funksjoner. CLI: --record-do-next. - Skrivere: report Step 7b, analyze Step 6b, ab-test 2c.6 (kun Adopt), post-feedback-monitor (kun 48h-sjekken); analytics-interpreter emitterer nå anbefalinger på do-next-form (imperativ + evidens). - Lesere: post/quick/batch/create Step 0 + newsletter Step 1, som i tillegg kalibrerer på forrige utgaves MÅLTE tall via queue-id-match (queue.json → analytics/posts) med eksplisitt honest-miss — aldri estimert. - Guards: test-runner Section 16v (15 ubetingede sjekker, floor 198 → 213), $-safety-batteriet dekker recordDoNext (coverage-gate fanget den nye eksporten). Suiter: test-runner 232/0, hooks 191/0, trends 300/0, brain 134/0, editions 72/0, specifics-bank 45/0, contract-gate 33/0, tests 35/0, render 60/0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QxvWAjte7vPcF79QeSRvRJ
This commit is contained in:
parent
f0532dce3f
commit
b45fdad911
16 changed files with 713 additions and 6 deletions
|
|
@ -342,6 +342,32 @@ handful of posts per variant a creator realistically gathers (well under the
|
|||
|
||||
Update the test file status from ACTIVE to COMPLETED. Add the conclusion and recommended actions to the file.
|
||||
|
||||
### 2c.6: Persist an Adopt verdict as a do-next directive
|
||||
|
||||
An **Adopt** verdict (and only Adopt — "Keep A", "Inconclusive" and "Extend test" change nothing
|
||||
about the next draft) is a decision the next post must inherit. Write it to the same do-next
|
||||
channel `/linkedin:report` and `/linkedin:analyze` use, so every create surface picks it up at
|
||||
its Step 0 instead of the test result sitting unread in a file:
|
||||
|
||||
```bash
|
||||
node --input-type=module -e "
|
||||
import { writeState, recordDoNext } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/state-updater.mjs';
|
||||
writeState(content => recordDoNext(content, {
|
||||
recordDate: 'YYYY-MM-DD',
|
||||
source: 'ab-test',
|
||||
directives: [
|
||||
{ directive: 'Open with a question hook by default', evidence: 'test hook-form (6 posts): B +38% comments, directional-strong' }
|
||||
]
|
||||
}));
|
||||
"
|
||||
```
|
||||
|
||||
Carry the **directional** framing into the evidence pointer (see 2c.4 — organic volume rarely
|
||||
reaches significance); a directive that reads as proven when the signal was weak is how one
|
||||
outlier becomes a permanent rule. `recordDoNext` replaces this source's previous adopt row, so
|
||||
a newer verdict supersedes an older one automatically — and the `report`/`analyze` slots are
|
||||
untouched.
|
||||
|
||||
---
|
||||
|
||||
## Step 2d: Review Test History
|
||||
|
|
|
|||
|
|
@ -220,6 +220,31 @@ Quick triage if a full audit can wait:
|
|||
- [ ] Monitor metrics closely
|
||||
- [ ] Continue high engagement activity
|
||||
|
||||
## Step 6b: Persist the plan as do-next directives (the measurement→creation contract)
|
||||
|
||||
The recovery plan above is worth nothing if the next drafting session never sees it. Turn the
|
||||
**2–3 load-bearing corrections** into do-next directives — the same channel `/linkedin:report`,
|
||||
`/linkedin:ab-test` and the 48h monitor write to, and the one every create surface reads at its
|
||||
Step 0:
|
||||
|
||||
```bash
|
||||
node --input-type=module -e "
|
||||
import { writeState, recordDoNext } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/state-updater.mjs';
|
||||
writeState(content => recordDoNext(content, {
|
||||
recordDate: 'YYYY-MM-DD',
|
||||
source: 'analyze',
|
||||
directives: [
|
||||
{ directive: 'Keep every post inside the 3 core pillars for 14 days', evidence: 'diagnosis: profile-content mismatch, reach -55% since off-topic run' },
|
||||
{ directive: 'No external links in the post body until reach recovers', evidence: 'diagnosis: link-in-body correlates with the drop window' }
|
||||
]
|
||||
}));
|
||||
"
|
||||
```
|
||||
|
||||
Write the corrections that change the NEXT draft — not the whole checklist. `recordDoNext`
|
||||
replaces this source's previous rows and expires anything older than 60 days, so a superseded
|
||||
diagnosis cannot keep steering drafts. Confirm in one line what was persisted.
|
||||
|
||||
## Step 7: Timeline Expectations
|
||||
|
||||
Set realistic expectations:
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ You are a LinkedIn batch content creator. Help the user create an entire week's
|
|||
|
||||
Load state and personalization:
|
||||
- Read `~/.claude/linkedin-studio.local.md` for recent topics and weekly goals
|
||||
- **Read `## Do-Next Directives` in the same file** — the last measurement pass's directives
|
||||
(report / analyze / A/B Adopt / 48h monitor) with their evidence pointers. A batch is where
|
||||
they bite hardest: apply them across the week's posts and name which post carries which
|
||||
directive in the plan. Never edit or clear the section (lifetime is managed per source)
|
||||
- Read `${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md` for profile and preferences
|
||||
- Check `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/plans/` for existing weekly plan
|
||||
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` for proven templates — vary templates across the batch for format diversity
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ If `~/.claude/linkedin-studio.local.md` exists, you may glance at the planned ne
|
|||
topic and recent pillars to make a smarter suggestion — but keep it to one line and
|
||||
do not block on it.
|
||||
|
||||
If `## Do-Next Directives` in that file is non-empty, mention the top directive in that same
|
||||
line ("last report says: lead with the number") — it often decides which format to route to.
|
||||
You do not apply it here; the command you route to reads the section itself at its Step 0.
|
||||
|
||||
## Step 1: Identify what they want to create
|
||||
|
||||
If the user's message already names a format (e.g. "a carousel about X", "react to
|
||||
|
|
|
|||
|
|
@ -371,6 +371,39 @@ what genuinely changes the work.
|
|||
> discovery→production loop automatically at Step 10 (scheduling flips the trend to
|
||||
> `acted`).
|
||||
|
||||
> **Calibration from measurement (A2-F14 — the do-next contract).** Two reads, both
|
||||
> cheap, both BEFORE the dimensions below. Neither asks the operator anything.
|
||||
>
|
||||
> 1. **`## Do-Next Directives` in `~/.claude/linkedin-studio.local.md`.** What the last
|
||||
> measurement pass (`/linkedin:report`, `/linkedin:analyze`, an A/B Adopt verdict, the
|
||||
> 48h monitor) decided the next piece should do differently, each row carrying its
|
||||
> evidence pointer. Apply the ones that apply to long-form and **name them in the brief**
|
||||
> — a directive that shaped this edition must be visible in the brief, not silently
|
||||
> absorbed. Never edit or clear the section here (each source manages its own rows).
|
||||
> 2. **The previous edition's MEASURED numbers — queue-id match.** The prior edition of
|
||||
> this series was registered at its Step 10 under the stable queue id
|
||||
> `<series-slug>-<NN−1>`. Resolve its numbers:
|
||||
> - read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json`,
|
||||
> take the entry whose `id` is `<series-slug>-<NN−1>` → its `scheduled_date`,
|
||||
> `hook_preview` and `status`;
|
||||
> - read the analytics batches in
|
||||
> `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/*.json` and
|
||||
> select the `.posts[]` row whose `publishedDate` equals that `scheduled_date`
|
||||
> (a rescheduled edition may be a day or two off — widen to ±2 days and disambiguate
|
||||
> on a `title` that matches `hook_preview`);
|
||||
> - carry forward `impressions`, `engagementRate`, `comments` and `saves` (when present).
|
||||
>
|
||||
> Read them as calibration, not as a verdict: **low impressions** points at hook /
|
||||
> topic-relevance (a Step 9 problem for this edition), **decent impressions with weak
|
||||
> comments** points at resonance (a Step 6 persona problem), and a strong prior edition
|
||||
> says keep the structure that worked. State the comparison in one line in the brief.
|
||||
>
|
||||
> **Honest miss.** No queue entry, no analytics match, or the edition simply is not measured
|
||||
> yet (`status: scheduled`, or the import has not been run) → say so in one line — *"forrige
|
||||
> utgave er ikke målt ennå; kalibrerer på skjelett og persona alene"* — and continue.
|
||||
> **Never estimate** the previous edition's numbers, and never let a missing measurement
|
||||
> block the brief. This is edition NN=1 of a new series' normal state.
|
||||
|
||||
Settle these dimensions (most should come from context, not questions):
|
||||
|
||||
- **Angle** — the one premise this edition argues.
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ First, load persistent state and personalization:
|
|||
- Read `~/.claude/linkedin-studio.local.md` for posting state (streak, weekly progress, recent topics)
|
||||
- Read `skills/linkedin-studio/SKILL.md` for user profile, voice settings, and preferences
|
||||
|
||||
**Read `## Do-Next Directives` in the state file and apply them to this draft.** This is what the
|
||||
last measurement pass (`/linkedin:report`, `/linkedin:analyze`, an A/B Adopt verdict, the 48h
|
||||
monitor) decided the next post should do differently — each row carries its evidence pointer.
|
||||
Apply the ones that fit this post, and **name the applied directive in one line** when you
|
||||
present the draft ("applied: lead with the number — report 2026-W22"). A directive that does not
|
||||
fit this topic is skipped silently, not argued with. Directives are already lifetime-managed
|
||||
(each source replaces its own; >60 days expire) — never edit or clear the section here.
|
||||
|
||||
Check state for topic planning:
|
||||
- Compare intended topic against "Recent Posts" in state file
|
||||
- If a similar topic was posted in the last 7 days, suggest a different angle or topic
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ Read `~/.claude/linkedin-studio.local.md` for:
|
|||
- Weekly posting progress (show "X/Y posts this week")
|
||||
- Recent topics (avoid repetition within 7 days)
|
||||
- Current streak status
|
||||
- **`## Do-Next Directives`** — what the last measurement pass (report / analyze / A/B Adopt /
|
||||
48h monitor) decided the next post should do differently, each with its evidence pointer.
|
||||
Apply the ones that fit and name the applied directive in one line with the draft. Never edit
|
||||
or clear the section (each source manages its own rows; rows older than 60 days expire).
|
||||
|
||||
Read `skills/linkedin-studio/SKILL.md` for:
|
||||
- User's voice profile and tone preferences
|
||||
|
|
|
|||
|
|
@ -336,6 +336,40 @@ Delegate interpretation to the `analytics-interpreter` agent (report mode) — i
|
|||
3. **Test carousel format**: Your one carousel got 3x more shares than text posts. Create a carousel for your top-performing topic this week.
|
||||
```
|
||||
|
||||
## Step 7b: Persist them as do-next directives (the measurement→creation contract)
|
||||
|
||||
A recommendation that only lands in chat dies there — the next post is drafted in a fresh
|
||||
session that never saw it. **Persist the 2–3 recommendations above as do-next directives**, so
|
||||
`/linkedin:post`, `/linkedin:quick`, `/linkedin:batch`, `/linkedin:create` and
|
||||
`/linkedin:newsletter` read them at their Step 0 and the next piece is actually shaped by this
|
||||
report. This step is not optional when a report produced recommendations.
|
||||
|
||||
Each directive is an **imperative the next draft can act on** plus an **evidence pointer** —
|
||||
the measured number it came from, so the create surface can tell a directive backed by 12 posts
|
||||
from one backed by 2:
|
||||
|
||||
```bash
|
||||
node --input-type=module -e "
|
||||
import { writeState, recordDoNext } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/state-updater.mjs';
|
||||
writeState(content => recordDoNext(content, {
|
||||
recordDate: 'YYYY-MM-DD',
|
||||
source: 'report',
|
||||
directives: [
|
||||
{ directive: 'Plan 2 AI-agent posts this week', evidence: 'weekly 2026-W22: 3 AI posts avg 2400 impressions vs 1200 baseline (n=12)' },
|
||||
{ directive: 'Move Tuesday posts to 08:00', evidence: 'weekly 2026-W22: Tuesday -40% impressions' }
|
||||
]
|
||||
}));
|
||||
"
|
||||
```
|
||||
|
||||
**Lifetime (do not hand-manage it):** `recordDoNext` replaces this source's own previous rows on
|
||||
every write and drops any row older than 60 days, so the section stays a live steering signal
|
||||
rather than a growing backlog. Directives from other sources (`ab-test`, `analyze`,
|
||||
`48h-monitor`) are left alone — never clear the section by hand.
|
||||
|
||||
Then confirm in one line what was persisted, e.g. "2 do-next directives written to state — the
|
||||
next post/newsletter will read them at Step 0."
|
||||
|
||||
## Step 8: Offer Deep Dive Options
|
||||
|
||||
After presenting the report, ask:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue