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

@ -30,6 +30,17 @@ Ensure every post adds genuine value rather than echoing what has already been s
Core principle: **if someone else has already said it better, find the angle that only this creator can own.**
**What "only this creator can own" means is not yours to guess.** Read
`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md`
before scoring. Its **How I differ** section is the creator's own distilled differentiator
and its **What I hold** section the positions they argue from — score originality against
those, not against a generic notion of novelty. A post can be topically fresh and still
score low here if it argues from no position the creator holds; a post can restate a
familiar topic and score well if it carries the specific lived material only they have.
If the brief is missing, fall back to the profile and the published corpus and say in the
report that you scored without a positioning brief — never infer a differentiator and
present it as the creator's.
## Similarity Search Process
### Step 1: Extract Core Claims

View file

@ -75,6 +75,33 @@ The operations centre is the user-authored other half of the second brain (the b
**Graceful absence:** If `brain/operations.md` (or its anchor) is missing or empty, proceed silently on the other context sources — no error, and no note about a missing operations centre.
### Distilling the positioning brief
Invoked by `/linkedin:setup` Step 3g. You produce the **positioning brief** — the distilled answer to the four questions a draft cannot answer for itself — and write it to:
```
${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/profile/positioning-brief.md
```
Shape it on `${CLAUDE_PLUGIN_ROOT}/config/positioning-brief.template.md`: **Who I am** · **Who this is for** · **What I hold** · **How I differ**, each with an `_Evidence:_` line naming the consolidated facts, published pieces, or specifics-bank entries it rests on.
**Sources, in precedence order:**
1. `brain/operations.md` — the dated `## Who I am now` anchor (user-declared direction)
2. `profile/user-profile.md` — the declared identity: expertise areas, target audience, ranked goals
3. `brain/profile.md` — consolidated Static/Dynamic facts, weighted by `evidence_count` and `last_seen`
4. The published corpus + `specifics-bank` entries — what the user has actually said and actually has
**The brief distils; it does not re-declare.** Where `user-profile.md` already states a fact (role, the five expertise areas, the declared audience), the brief **references** it rather than restating it, and spends its own words on the two things no declared profile contains: the *stance* and the *difference*. **Positioning the operator has declared is never overridden by a distilled inference** — where an inference contradicts the anchor or the declared profile, the declaration stands and the inference is reported as a tension for the operator to resolve, never silently applied. This is the frozen-past-self guard extended from facts to positioning.
**Anti-flattery (binding, inherited):** "What I hold" must contain positions a reader could **disagree with**. If the distillation yields only descriptions ("works with X", "cares about quality"), say so and return fewer positions — a brief padded with uncontestable statements is worse than a short one, because every downstream draft will anchor on it.
**Evidence floor:** a section you cannot ground in the sources gets an explicit `[insufficient evidence — operator input needed]` marker, never an invented plausible answer. The brief is read by every create surface; a fabricated differentiator propagates into every post written against it.
**Regeneration is operator-gated.** When a brief already exists you **never overwrite** it without an **explicit go**: present a section-by-section **diff** of the proposed distillation against the current file (including any operator edits), and write only what the operator approves. The operator's own edits outrank your distillation by default.
**Graceful absence:** if `brain/profile.md` and the published corpus are both empty there is **no brief yet** — say that the second brain has nothing to distil and point to `/linkedin:setup` voice-samples and profile steps first. Never scaffold a brief out of the template's placeholders.
### New Creator Advantage Detection
From the state file, extract `first_post_date`. Calculate the creator window status: