feat(linkedin-studio): N23 — positioning-brief-motor (generering + konsum) [skip-docs]

Persistert posisjonering som alle drafts bindes mot. Innplassert i
/linkedin:setup (Step 3g) etter operatør-friksjonskriteriet — setup eier
allerede ${DATA}/profile/ og har menyen; telling forblir 30.

- config/positioning-brief.template.md (NY): fire seksjoner (Who I am ·
  Who this is for · What I hold · How I differ), hver med _Evidence:_-linje.
- setup.md Step 3g: DELEGERER til linkedin-studio:strategy-advisor.
  Brain-konsum-blokken forblir i én kopi (N21-lærdommen), lint-håndhevet.
- strategy-advisor.md: distillasjonen, kildepresedens, anti-flatteri
  (What I hold må bære påstander en leser kan være UENIG i) og
  evidensgulv ([insufficient evidence] framfor plausibel oppfinnelse).
- Distillat, ikke andre profil: briefen REFERERER user-profile.md framfor
  å gjenta den. Operatørens deklarasjon og daterte anker slår maskinens
  inferens; motstrid rapporteres som spenning, aldri stille anvendt.
- Konsum: post/quick/batch + newsletter Step 1 + differentiation-checker
  (scorer originalitet mot How I differ, ikke generisk nyhet).
- Regenerering er operatør-gatet: explicit go + seksjonsvis diff + aldri
  stille overskriving av operatørens egne redigeringer.

Lint: Section 16y, 17 nye ubetingede sjekker (self-test 1 akseptert /
4 underspesifiserte avvist). Floor 251 → 268. Alle ti suiter grønne:
test-runner 270→287/0 · trends 300 · analytics 202 · hooks 191 · brain 134
· editions 72 · render 63 · specifics-bank 45 · tests 35 · contract-gate 33.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbwkH8phPsgv9xFd8Qbq7E
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 21:01:55 +02:00
commit af80150019
10 changed files with 304 additions and 3 deletions

View file

@ -31,6 +31,7 @@ Load state and personalization:
- 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
- Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md` — the week's posts must add up to one position, not five unrelated takes. Use **What I hold** to keep the batch arguing from the same stance, and **How I differ** as the check on the plan as a whole: if the week could have been produced by any account in the niche, revise the plan before writing. Absent file: proceed silently
If a plan exists for this week, use it as the foundation. If not, create one first.

View file

@ -341,6 +341,16 @@ Establish the edition brief with **at most ~3 calibration questions**. Infer
everything you can from Step 0 (series brief, STATE.md, prior edition); only ask
what genuinely changes the work.
**Read the positioning brief first** —
`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md`.
A long-form edition is the format where a missing position shows most: 1,500 words of
competent survey that takes no stance is the failure mode. Use **What I hold** to fix
what this edition *argues* (not merely covers) and **How I differ** as the brief-level
test — if the edition as briefed could carry another author's byline unchanged, the
angle is not yet an angle. Where the brief and the operator's stated brief for THIS
edition disagree, the operator wins; note the tension in one line rather than quietly
steering to the file. Absent file: proceed silently on the other sources.
> **Trend intake (optional bridge — N7).** If this edition is being started from a
> `/linkedin:trends` candidate — the operator supplies a **trend id** (shown in the
> trends brief and via `CLI list --json`, where

View file

@ -45,6 +45,7 @@ Check weekly progress:
Check for existing assets:
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` - Match the user's natural voice
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md` - What the user stands for and how they differ. Write the angle AGAINST this: the "How I differ" section is the test for whether this post could have been written by anyone else on the topic. Absent file: proceed silently (nothing to anchor on yet).
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` - Study past successful posts and replicable patterns
- `${CLAUDE_PLUGIN_ROOT}/assets/frameworks/framework-template.md` - Reference user's documented frameworks for framework posts
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/templates/my-post-templates.md` - User's proven post templates with success rates. **Prefer these over generic structures.**

View file

@ -37,6 +37,12 @@ Read `${CLAUDE_PLUGIN_ROOT}/skills/linkedin-studio/SKILL.md` for:
- Core expertise areas (for topical alignment)
- Phrases they commonly use
Read `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md` for:
- **What I hold** — the positions to argue from, so a 5-minute post still says something the
user actually believes rather than something generically true
- **How I differ** — the one-line test before you present the draft: could any other account
in this niche have posted this? Absent file: proceed silently.
Read `${CLAUDE_PLUGIN_ROOT}/assets/quick-post-resources.md` for:
- Hooks bank
- CTAs bank

View file

@ -67,7 +67,7 @@ Use AskUserQuestion:
**What would you like to set up?**
Options (always show all 7):
Options (always show all 8):
1. **Voice samples** -- Paste 3-5 of your best posts so I can analyze your writing voice
2. **Case study** -- Walk through a guided interview to document a real case study
@ -75,7 +75,8 @@ Options (always show all 7):
4. **Post analysis** -- Add your high-engagement posts with metrics for pattern analysis
5. **Demographics** -- Guide you through LinkedIn Analytics to capture audience demographics
6. **User profile** -- Set up your personalization profile (name, expertise, goals, voice)
7. **Show score details** -- See detailed breakdown of what's missing in each category
7. **Positioning brief** -- Distil what you stand for and how you differ, so every draft is written against it
8. **Show score details** -- See detailed breakdown of what's missing in each category
Based on their answer, run the corresponding sub-workflow below.
@ -346,6 +347,29 @@ Guide through each section of the profile:
**Important:** This file is gitignored (`.local.md` pattern), so personal data stays private.
## Step 3g: Positioning Brief
**Goal:** Distil `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md` — the stance-and-difference layer every drafting surface reads before it writes.
This step **delegates**. Do not read the second brain yourself and do not restate its consumption rules here: invoke the agent that already owns them.
1. **Check what exists first.** Read the current `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md` if present, and note whether it carries operator edits (`## Provenance` → "Operator edits since generation").
2. **Invoke the distiller** via `Task` with `subagent_type: linkedin-studio:strategy-advisor`, asking it to distil the positioning brief. It reads `brain/profile.md`, `brain/operations.md`, `profile/user-profile.md` and the published corpus, and shapes the result on `${CLAUDE_PLUGIN_ROOT}/config/positioning-brief.template.md`.
3. **First run (no brief exists):** show the four distilled sections, ask for corrections, then write the file.
4. **Regeneration (a brief already exists):** this is **operator-gated**.
- Present a **diff**, section by section, of the proposed distillation against the current file.
- Ask for an **explicit go** per section — "keep mine / take the new one / merge".
- **Never overwrite** the existing brief wholesale, and never discard an operator edit because the distillation disagrees with it. Positioning is the operator's own; the machine's read of it is a proposal.
5. **Thin evidence is reported, not filled.** Sections the agent marks `[insufficient evidence — operator input needed]` stay marked. Offer to interview the operator for that section instead — an invented differentiator would propagate into every post written against the brief.
6. **If there is no brain yet** the agent will say there is **no brief yet** — point the user at options 1 (voice samples) and 6 (user profile) first, and exit this step without writing a placeholder file.
**Important:** This file lives in the per-user data dir, survives reinstalls, and is read by `/linkedin:post`, `/linkedin:quick`, `/linkedin:batch`, `/linkedin:newsletter` Step 1 and the `differentiation-checker`.
## Step 4: Recalculate Score
After completing any sub-workflow: