fix(linkedin): close dogfood friction (S14)

Close all 9 friction points from the S13 newsletter dogfood (operator
elected to fix F6-F9 rather than defer):

- F1: namespace all subagent_type calls in newsletter.md to
  linkedin-thought-leadership:<name> (4 sites + canonical note)
- F2: document agent invocation form + reload requirement in CLAUDE.md
  + README.md (reload itself is an operator action)
- F3: add edition-config / edition-delingstekst / edition-HANDOVER
  templates under config/ + wire into Steps 0 and 8 + footer
- F4: reconcile draft path to <serie>/NN-utkast.md (series root)
- F5: de-hardcode series root (explicit arg / LTL_SERIES_ROOT / default)
- F6: config-derive carousel editions (remove Seres CAROUSEL set);
  correct samle comment
- F7: build-html.mjs exits non-zero when zero HTML produced
- F8: guard parseDelingstekst (graceful ENOENT) + correct Step 8 wording
- F9: relocate agents/README.md -> docs/agents-capability-matrix.md

Re-tested: 87/87 plugin tests pass; build-html/build-linkedin behavior
re-verified live. Per-item outcomes logged in dogfood-S13-friction.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-27 23:37:39 +02:00
commit 92e0a0b4f5
11 changed files with 339 additions and 54 deletions

View file

@ -0,0 +1,158 @@
# Agent Capability Matrix
16 specialized agents for LinkedIn thought leadership. Each agent has a focused responsibility, defined model, and unique color for visual identification.
## Quick Reference
| Agent | Model | Color | Primary Responsibility |
|-------|-------|-------|----------------------|
| content-optimizer | Sonnet | Blue | Optimize posts against algorithm signals |
| strategy-advisor | Sonnet | Green | Growth strategy and phase-specific guidance |
| analytics-interpreter | Sonnet | Yellow | Pattern discovery from analytics data |
| engagement-coach | Haiku | Magenta | 5x5x5 method and engagement routines |
| content-planner | Sonnet | Cyan | Weekly/monthly content calendars |
| performance-reporter | Sonnet | Amber | Weekly/monthly performance reports |
| network-builder | Sonnet | Teal | Strategic networking and outreach |
| content-repurposer | Sonnet | Purple | Format conversion and evergreen refresh |
| comment-strategist | Sonnet | Red | CEA commenting and target selection |
| trend-spotter | Sonnet | White | Trending topics and opportunity scoring |
| voice-trainer | Sonnet | Pink | Voice profile building and drift detection |
| differentiation-checker | Sonnet | Gray | Originality scoring and commodity detection |
| video-scripter | Sonnet | Violet | Video script creation with pacing and visual cues |
| post-feedback-monitor | Haiku | Lime | Post-publish 48h monitoring and real-time interventions |
| fact-checker | Opus | Brown | Factual-claim verification against primary/credible sources (longform) |
| persona-reviewer | Opus | Olive | Reader-persona resonance + hook-conversion gate (longform) |
## Capability Matrix
Capabilities mapped across agents. **P** = Primary, **S** = Secondary/Supporting.
| Capability | optimizer | strategy | analytics | engage | planner | tracker | perf-rep | network | repurpose | comment | trends | voice | diff-check | video | post-monitor | pers-scorer |
|-----------|:---------:|:--------:|:---------:|:------:|:-------:|:-------:|:--------:|:-------:|:---------:|:-------:|:------:|:-----:|:----------:|:-----:|:------------:|:-----------:|
| Post optimization | **P** | | | | | | | | | | | | | | | |
| Hook analysis | **P** | | | | | | | | | | | | | S | | |
| Algorithm alignment | **P** | | | S | | | | | | | | | | S | S | |
| Growth strategy | | **P** | | | S | | | | | | | | | | | |
| Phase assessment | | **P** | | | | | | | | | | | | | | |
| Trajectory analysis | | **P** | S | | | | S | | | | | | | | | |
| Audience analysis | | S | **P** | | | | S | | | | | | | | | |
| Pattern discovery | | | **P** | | | | S | | | | | | | | | |
| Trend analysis | | | S | | | | **P** | | | | | | | | | |
| Engagement coaching | | | | **P** | | | | S | | S | | | | | | |
| 5x5x5 method | | | | **P** | | | | S | | S | | | | | | |
| Content planning | | | | | **P** | | | | | | S | | | | | |
| Mix enforcement | | | | | **P** | | | | | | | | | | | |
| Gap analysis | | | | | **P** | S | | | | | | | | | | |
| Accountability | | | | | | **P** | S | | | | | | | | | |
| Plan tracking | | | | | | **P** | | | | | | | | | | |
| Performance reports | | | S | | | S | **P** | | | | | | | | | |
| Content DNA | | | | | | | **P** | | | | | S | | | | |
| Network building | | | | S | | | | **P** | | | | | | | | |
| Connection scoring | | | | | | | | **P** | | | | | | | | |
| DM templates | | | | | | | | **P** | | | | | | | | |
| Format conversion | | | | | | | | | **P** | | | | | S | | |
| Evergreen scoring | | | | | | | | | **P** | | | | | | | |
| Content lifecycle | | | | | S | | | | **P** | | | | | | | |
| Comment strategy | | | | S | | | | | | **P** | | | | | | |
| CEA method | | | | S | | | | | | **P** | | | | | | |
| Target identification | | | | | | | | S | | **P** | | | | | | |
| Trend scanning | | | | | S | | | | | | **P** | | | | | |
| First-mover assessment | | | | | | | | | | | **P** | | | | | |
| Angle mapping | | | | | S | | | | S | | **P** | | | | | |
| Voice profiling | | | | | | | | | | | | **P** | | | | |
| Drift detection | | | | | | | | | | | | **P** | | | | |
| Quarterly audit | | | | | | | | | | | | **P** | | | | |
| Originality scoring | | | | | | | | | | | | | **P** | | | |
| Commodity detection | | | | | | | | | | | | | **P** | | | |
| Differentiation | | | | | | | | | | | | | **P** | | | |
| Video scripting | | | | | | | | | S | | | | | **P** | | |
| Script pacing | | | | | | | | | | | | | | **P** | | |
| Visual cue notation | | | | | | | | | | | | | | **P** | | |
| Post-publish monitoring | | | | | | | | | | | | | | | **P** | |
| Velocity analysis | | | | | | | | | | | | | | | **P** | |
| Asset completeness | | | | | | | | | | | | | | | | **P** |
| Setup recommendations | | | | | | | | | | | | | | | | **P** |
## Content Pipeline
How agents collaborate in the end-to-end content lifecycle:
```
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ trend-spotter│───▸│ content-planner │───▸│ diff-checker │
│ (find topics)│ │ (plan + schedule) │ │ (originality │
└─────────────┘ └──────────────────┘ │ gate ≥51/100) │
│ └────────┬────────┘
│ │
┌──────▼──────┐ ┌───────┴────────┐
│voice-trainer│ │ FORMAT SPLIT │
│(voice check)│ └──┬──────────┬──┘
└──────┬──────┘ │ │
│ ┌───────▼───┐ ┌────▼─────────┐
│ │video- │ │content- │
└────────────▸│scripter │ │optimizer │
│(scripts) │ │(text posts) │
└───────┬───┘ └──────┬───────┘
│ │
└─────┬──────┘
┌────────────────────────────┤
│ │
┌──────▼────────────┐ ┌────────▼───────┐
│performance-reporter│ │ [PUBLISH] │
│(weekly/monthly) │ └────────┬───────┘
└───────────────────┘ │
┌────────▼───────┐
│engagement-coach│
│(5x5x5 + first │
│ hour tactics) │
└──────┬─────────┘
┌──────▼─────────┐
│comment-strategist
│(CEA commenting) │
└────────────────┘
```
### Parallel Support Agents
These agents operate independently and feed into the pipeline at multiple points:
```
strategy-advisor ──────▸ Macro-level planning and phase guidance
analytics-interpreter ─▸ Pattern discovery feeding back into planning
network-builder ───────▸ Relationship building amplifying content reach
content-repurposer ────▸ Post-publish: extends content lifecycle
```
## Which Agent Do I Need?
| Scenario | Agent | Command |
|----------|-------|---------|
| "I want to write a post" | content-optimizer | `/linkedin:post` |
| "What should I post about?" | content-planner, trend-spotter | `/linkedin:pipeline` |
| "Make this post better" | content-optimizer | `/linkedin:post` |
| "Is this original enough?" | differentiation-checker | `/linkedin:pipeline` |
| "Plan my week's content" | content-planner | `/linkedin:batch` |
| "Am I on track this week?" | — | `/linkedin:calendar` |
| "How did I do this week?" | performance-reporter | `/linkedin:report` |
| "Analyze my LinkedIn data" | analytics-interpreter | `/linkedin:analyze` |
| "What's my LinkedIn strategy?" | strategy-advisor | `/linkedin:strategy` |
| "Help me engage more" | engagement-coach | `/linkedin:strategy` |
| "Who should I comment on?" | comment-strategist | `/linkedin:strategy` |
| "Build my network" | network-builder | `/linkedin:strategy` |
| "Does this sound like me?" | voice-trainer | `/linkedin:post` |
| "Repurpose my best post" | content-repurposer | `/linkedin:pipeline` |
| "What's trending in my field?" | trend-spotter | `/linkedin:pipeline` |
| "Audit my content strategy" | analytics-interpreter, strategy-advisor | `/linkedin:audit` |
| "How do I monetize?" | strategy-advisor | `/linkedin:monetize` |
| "Create a video script" | video-scripter | `/linkedin:video` |
| "Turn this post into a video" | video-scripter, content-repurposer | `/linkedin:video` |
| "Script a talking head video" | video-scripter | `/linkedin:video` |
## Model Selection Rationale
| Model | Agents | Why |
|-------|--------|-----|
| **Opus** | 2 agents (fact-checker, persona-reviewer) | Longform judgment: factual verification, reader-persona resonance |
| **Sonnet** | 12 agents | Complex reasoning: optimization, strategy, analysis, scoring, scripting |
| **Haiku** | 2 agents (engagement-coach, post-feedback-monitor) | Lighter tasks: coaching prompts, post monitoring |

View file

@ -177,19 +177,85 @@ missing delingstekst kills the whole build rather than degrading.
## Friction summary for Step 15 (revert/fix targets)
| # | Severity | Implicated file | Step 15 disposition |
|---|----------|-----------------|---------------------|
| F1 | BLOCKER | `commands/newsletter.md` | namespace agent calls |
| F2 | BLOCKER/env | env + `CLAUDE.md`/`README.md` | reload + document |
| F3 | MAJOR | `config/` + `commands/newsletter.md` | add 3 templates |
| F4 | MAJOR | `commands/newsletter.md` | reconcile draft path/name |
| F5 | MAJOR | `commands/newsletter.md` | de-hardcode series root |
| F6 | MINOR | `render/build-linkedin.mjs` | defer (generalization debt) |
| F7 | MINOR | `render/build-html.mjs` (+ Step 7) | exit non-zero on no output |
| F8 | MINOR | `render/build-linkedin.mjs` (+ Step 8) | guard delingstekst + fix wording |
| F9 | MINOR | `agents/README.md` | relocate / defer |
| # | Severity | Implicated file | Step 15 disposition | Status |
|---|----------|-----------------|---------------------|--------|
| F1 | BLOCKER | `commands/newsletter.md` | namespace agent calls | ✅ |
| F2 | BLOCKER/env | env + `CLAUDE.md`/`README.md` | reload + document | ✅ (doc) / 🔶 (reload = operator) |
| F3 | MAJOR | `config/` + `commands/newsletter.md` | add 3 templates | ✅ |
| F4 | MAJOR | `commands/newsletter.md` | reconcile draft path/name | ✅ |
| F5 | MAJOR | `commands/newsletter.md` | de-hardcode series root | ✅ |
| F6 | MINOR | `render/build-linkedin.mjs` | config-derive carousel; fix samle comment | ✅ |
| F7 | MINOR | `render/build-html.mjs` (+ Step 7) | exit non-zero on no output | ✅ |
| F8 | MINOR | `render/build-linkedin.mjs` (+ Step 8) | guard delingstekst + fix wording | ✅ |
| F9 | MINOR | `agents/README.md` | relocate out of `agents/` | ✅ (relocated) / 🔶 (de-register on reload) |
**Headline:** the long-form pipeline's deterministic backbone is sound, but its
**gate layer is currently un-runnable** (F1 + F2). Step 15 must close F1 (a concrete
one-line-per-call edit) and F2 (reload + a doc note) before the pre-lock persona
sweep can actually execute — the order is correctly wired, it just cannot fire yet.
---
## Step 15 (S14) — re-test outcomes
All nine friction points were closed (operator elected to fix F6F9 rather than
defer). Each was re-tested with a concrete check, not a self-asserted "fixed."
- **F1 — ✅ closed.** All four `Task` call sites in `commands/newsletter.md`
(content-repurposer Step 3, fact-checker Step 5, persona-reviewer Steps 6 + 9)
now use the namespaced `subagent_type: linkedin-thought-leadership:<name>`, plus a
canonical "Agent invocation form (required)" note near the foreground principle.
**Check:** `grep -nE 'subagent_type: (fact-checker|persona-reviewer|content-repurposer)' commands/newsletter.md`
→ zero bare names; `grep -nE 'linkedin-thought-leadership:(fact-checker|persona-reviewer|content-repurposer)'`
→ all 4 sites namespaced.
- **F2 — ✅ doc / 🔶 reload.** Documented in `CLAUDE.md` (Agents section: invocation
form + reload requirement) and `README.md` (Agent Architecture note). The
environmental half — registering a newly-added agent — inherently requires a
Claude Code **session reload**; that is an operator action, not a code change.
Confirmed F2 persists across `/clear`: `fact-checker`/`persona-reviewer` were
still absent from this fresh session's agent registry (only the 15 older agents +
README appeared), proving it is a reload gap, not a per-session fluke.
- **F3 — ✅ closed.** Added `config/edition-config.template.json`,
`config/edition-delingstekst.template.md`, `config/edition-HANDOVER.template.md`
(formats reverse-engineered from the render scripts, now shipped as reference).
Wired into `newsletter.md` Step 0 (HANDOVER), Step 8 (config + delingstekst), and
the Reference Files footer. **Check:** all three exist under `config/`;
`edition-config.template.json` parses as valid JSON.
- **F4 — ✅ closed.** Step 3 now writes the canonical `<serie>/NN-utkast.md` in the
series root (the exact file Steps 7/8 render), with an explicit "do NOT write
`linkedin/<article>.draft.md`" warning. **Check:** no `.draft.md`/`<article>` path
refs remain except the intentional anti-pattern warning.
- **F5 — ✅ closed.** Step 0 resolves a **series root** via an order (explicit path
arg → `${LTL_SERIES_ROOT:-…/maskinrommet/serier}/<slug>/` → ask once); maskinrommet
is the default, not the only path. The architecture preamble was aligned to match.
- **F6 — ✅ closed.** `CAROUSEL = new Set(["03","06"])` removed; carousel editions are
now config-derived (`config.carousel`, a list of NN strings) via `loadEditionConfig`
+ `EMPTY_CONFIG` + the new config template. Misleading "samle bygges alltid" comment
corrected (build has always been gated on `shareMap.samle`). **Check:** `grep -n
CAROUSEL render/build-linkedin.mjs` → none; 20/20 render tests pass (one assertion
updated to include the `carousel: []` default).
- **F7 — ✅ closed.** `build-html.mjs main()` now counts files written, prints
`Ingen HTML produsert …` and the CLI guard exits non-zero when zero files are
produced (no more silent exit-0 on a typo'd filename). Step 7 wording updated to
rely on the exit code AND verify the output file. **Re-tested live:** missing input
→ exit 1; valid input → exit 0 + `review/NN-utkast.html` written.
- **F8 — ✅ closed.** `parseDelingstekst()` wrapped in try/catch returning `{}` on
ENOENT, matching `loadEditionConfig`'s fail-soft contract; Step 8 wording corrected
("both inputs optional and graceful," not "either file throws"). **Re-tested live:**
no delingstekst → `build-linkedin.mjs` exit 0 + `linkedin/01/POST.html` still built.
- **F9 — ✅ relocated / 🔶 de-register on reload.** `git mv agents/README.md
docs/agents-capability-matrix.md` — the only reliable fix, since the file registers
by filename (it had no frontmatter yet still appeared as
`linkedin-thought-leadership:README`). The stale registration clears on the next
Claude Code reload (env, same as F2). **Check:** no README in `agents/`;
`docs/agents-capability-matrix.md` present.
### Finding (out of Step 15 scope — recorded, not actioned)
`plan.md` Steps 16, 17, 18 hard-code `agents/README.md` as an explicit `grep` search
path (plan.md:635, 727, 849). After F9's relocation that path no longer exists. The
explicit arg is **redundant** with the recursive `agents/` search those greps already
include, so dropping it (or repointing to `docs/agents-capability-matrix.md`) is
safe — but `plan.md` is outside Step 15's Files list (Hard Rule 2), so this is logged
for the operator/those steps rather than edited here. **Action for Steps 1618:** drop
the dangling `agents/README.md` arg from their Verify greps, or repoint to the new path.