linkedin-studio/docs/hardening/plan.md
Kjell Tore Guttormsen 2b9ed1cf0b fix(linkedin-studio): S27 ref-consistency A — "penalty/penalizes" framing → SSOT
Reconcile external-link and topic-relevance reach-loss framing to the algorithm-signals
SSOT across 6 files (10 edits): body links "correlate with lower reach" (LinkedIn denies
an intentional penalty), topic relevance is a positive ranking input with no quantified
off-topic figure. 3 plan-cited lines + 7 same-class siblings surfaced during verify.

Bucket B (link-penalty lines in linkedin-formats.md) folded into S28; Bucket D (other
unsourced reach-coefficients: -68%/-25%/-15-25%/-30-50%/55%) queued as new S30. Engagement-
pod + AI-slop "penalized" framing left intact (officially confirmed). Gate 81/0/0; counts
29/19 unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qgzo6rxthw7KuxHjn5vyE
2026-06-19 22:06:39 +02:00

10 KiB
Raw Blame History

LinkedIn Studio — Command Hardening Plan v2 (interactive quality gate)

Supersedes the v1 autonomous plan (recoverable in git history: commit 2f90880). Motivated by the 2026-05-31 S2 fabrication incident: the v1 method (autonomous, prose-heavy 5-step per command, per-command Opus reviewer swarm, /trekreview gate) produced confident fabrications (Claude wrote SIMULATE/EVALUATE/HARDEN narratives — char counts, line numbers, before/after — for files it had not actually observed) and burned context without value (full-file re-reads + long logs + reviewer agents for what are usually 01-line edits). A large parallel tool-batch also destabilized the tool-result stream (out-of-order / duplicated / truncated returns). Nothing false shipped — the failed edits + empty greps + real reads caught it, and it was reverted — but the method had to change.

v2 is a slow, dialogic, human-in-the-loop gate: ONE command per session, the operator as the truth source, every mechanical claim tool-grounded.

Intent

Harden each of the 29 commands to its own intent — one command per session — with the operator in the loop. Last quality gate before GUI/M0. Brief: brief.md.

The locked interactive method (identical every session)

Per command, 8 steps. Claude STOPS and waits at each "agree" point — no autonomous run-ahead:

  1. Agree intention — show the command's own description + its journey role; agree in one line.
  2. Agree test-method — the class predicates (below) + what the simulation must prove.
  3. Agree persona — who invokes + with what input.
  4. Run the test — tool-grounded mechanical facts (each with file:line) + a GROUNDED persona simulation (a real invocation → concrete output, anchored to the shown file region).
  5. Talk — the operator's judgment is the truth source.
  6. Agree improvements — surgical, or "no change".
  7. Implement — Edit → grep-confirm landed → show the confirmed diff.
  8. Move on — run the end-of-session ritual; the next command is its own session.

Two guards (non-negotiable)

  • Read-and-show BEFORE simulate — the simulation is anchored to observed text, shown to the operator.
  • Every mechanical claim from a tool — char count, ✓/✗, line number: shown from a tool before stated.

Anti-drift through dialogue

The per-command dialogue IS the drift-reduction mechanism: Claude proposes at each agree-point (intention / test-method / persona / improvement) and waits for the operator to confirm or correct before proceeding. Frequent grounding checkpoints are what keep Claude from confabulating — never race past an agree-point.

Execution discipline (the S1+S2 incident lessons)

  • ONE command per session. Never hold multiple command files in context at once.
  • Never batch dependent tool calls in parallel. Read→Edit→grep→log is strictly sequential. Large parallel batches destabilize the tool-result stream.
  • Guard greps: grep/grep -c exit non-zero on zero matches → append || echo NONE so a batch sibling isn't torn down.
  • Never write a HARDEN/after claim before the edit is grep-confirmed landed.
  • If the tool layer degrades (slow / truncated / empty / replayed returns): PAUSE and resume in a fresh session. Do not push through a degraded window.

Command classes & mechanical predicates (the testmethod per class)

  • post-emitting — hook 110140 present · length band present · no-body-link present · buzzword check present · topic→5 pillars present · every subagent_type: linkedin-studio:X resolves to agents/X.md.
  • routing — every emitted /linkedin:Y resolves to commands/Y.md.
  • guided/stateful — primary promised artifact actually produced · subagent targets resolve · graceful degradation present.
  • analytics — graceful degradation present · saves/dwell honesty intact.

Synthetic test data (fixtures) — for data-dependent commands

Some commands cannot be meaningfully tested without input data — analytics (import, report, analyze, audit, ab-test) need a CSV/JSON; stateful commands (calendar, firsthour) need a queue/state. For these, step 2 (agree test-method) includes agreeing a small fictitious dataset that exercises the command's real path:

  • Isolated + throwaway — built in a temp/scratch location (e.g. /tmp/… or a gitignored path), NEVER the real analytics/state dirs, NEVER committed.
  • Minimal but realistic — just enough rows/fields to trigger the behavior under test (e.g. a 35-row CSV with the real column names; a 2-experiment ab-test file).
  • Clearly fictitious — obviously-fake values, impossible to mistake for real data.
  • Discarded after the test — the fixture proves the command works; it is not a deliverable.

Session queue (ONE command each)

S1 ✅ quick · onboarding · first-post · setup — DONE under v1; do NOT re-harden.

S2 post S9 newsletter* S16 analyze S23 profile
S3 react S10 headless-review S17 audit S24 create
S4 multiplatform S11 pivot S18 ab-test S25 measure
S5 carousel S12 firsthour S19 strategy S26 linkedin
S6 video S13 calendar S20 competitive S27 ref-consistency A
S7 batch S14 import S21 monetize S28 ref-consistency B
S8 pipeline S15 report S22 outreach S29 terminology-scrub
S30 magnitude-scrub

*S9 newsletter (16-phase) may split into S9a/S9b. Otherwise one command = one session.

S27/S28 — reference-consistency pass (added 2026-06-19, operator-approved; promotes open follow-up #1 to scheduled work). NOT full re-hardening of already- commands — surgical SSOT-reconciliation of the documented divergences, same tool-grounded discipline (read-and-show → grep-confirm → re-grep final):

  • S27 (A) — "penalty/penalizes" framing → SSOT DONE (2026-06-19, 10 edits/6 files; see log.md). The 3 cited lines (troubleshooting-guide.md:127, analyze.md:101, audit.md:60 — nr drifted ±1) + 7 same-class siblings (trend-spotter topic-relevance ×2, troubleshooting-guide :15, first-comment-strategy ×3, url-processing-templates :396) reconciled to "correlate with lower reach" / "topic relevance is a ranking input — off-topic gets lower reach". Bucket B (link-penalty lines in linkedin-formats.md) folded into S28; Bucket D (other unsourced magnitudes) promoted to S30.
  • S28 (B) — format magnitudes → SSOT: commands/video.md:69 + references/linkedin-formats.md (the "30% zero-distribution" claim vs SSOT native-video framing) + the 6 link-penalty lines folded in from S27 Bucket B (linkedin-formats.md:52,:91,:194,:198,:200,:432) — reconcile link + format framing in one pass over that file.

S29 — terminology scrub: "thought leadership" → "LinkedIn Studio" / neutral (added 2026-06-19, operator-approved during S26). The phrase must not appear anywhere in the plugin (it is named LinkedIn Studio; see auto-memory no-thought-leadership-phrase). S26 fixed the 2 occurrences in commands/linkedin.md; ~85 lines across ~45 files remain (commands, agents, references — incl. the filename references/thought-leadership-angles.md — skills, plus historical CHANGELOG/docs). Open scoping questions for this pass: (a) user-facing surface only, or include historical CHANGELOG/docs too? (b) the thought-leadership-angles.md rename is its own sub-step — every pointer to the filename must update with it. Same tool-grounded discipline (read-and-show → grep-confirm → re-grep final); hardening-class.

S30 — magnitude scrub: unsourced reach-coefficients → SSOT (surfaced during S27, 2026-06-19). A different class from S27's link/topic-relevance framing: discrete percentage penalties with no primary source in the SSOT68% (5+ hashtags: linkedin-growth-playbook:166, ab-testing-framework:66), 25% (<1000 chars: linkedin-growth-playbook:224), 15-25% (topic-gap: glossary:235), 30-50% (engagement-bait: glossary:91), 55%/45% (AI-comment: engagement-coach:195, firsthour:112 — SSOT carries ~45% correlational engagement gap at medium confidence, not a 55% reach penalty), 25%/post (multiple posts/3h: post-feedback-monitor:330), poll-overuse (poll-strategy-guide:20,:205). Leave intact (officially confirmed, high confidence): engagement-pod + AI-slop "penalized" framing. Full grep catalog in log.md S27 entry, Bucket D. Same discipline; hardening-class.

Run after S26; order adjustable (S27 → S28 → S29 → S30). These edit already-hardened files surgically and are hardening-class (commit local, no push).

End-of-session ritual (every session — STATE.md handoff baked in)

  1. bash scripts/test-runner.shFailed: 0 + counts 29/19/25/6.
  2. Terse, tool-grounded log.md line for the command (ONLY after verify): PASS / edit + file:line.
  3. Commit own file(s) only, LOCALLY (fix: for command edits; explicit git add <path>, never -u/-A). Do NOT push hardening work — see Push policy.
  4. Overwrite STATE.md: mark this command ; point at the NEXT single command + its class; carry the method + discipline rules → ready for the next "Les STATE.md og følg instruksjonene".
  5. (Optional) update Voyage .session-state.local.json next-label for /trekcontinue coherence.

Defaults (adjustable between sessions)

  1. Log: keep, terse, tool-grounded, after-verify only.
  2. Persona: ICP author default; fresh-adopter for onboarding/first-post/setup; deviate explicitly elsewhere.
  3. Gate/commit: once per session = per command.

Push policy (operator rule, 2026-05-31)

Hardening work — "det vi GJØR": command edits + log.md entries — is committed locally only, never pushed. Only method / process / tooling improvements (this plan, a future checker, STATE conventions) may be pushed, and only on explicit operator OK ("eventuelle forbedringer").

Amendment policy

Improve the method/plan between sessions if a session surfaces a gap (operator-approved). This plan is a living contract, not frozen.