Wave 2 / Step 6 of the remediation plan.
Organic personal-post A/B tests gather a handful of posts per variant — far below
the volume a significance test needs — so the tool must not imply statistical
significance:
- Rename the results-table "Significant?" column to "Directional?" and define it
as "clears the ~20% minimum-meaningful-difference AND points the same way across
most posts" — a direction to test further, not a significant result.
- Reword the "20% significance rule" to a minimum-meaningful-difference effect-size
heuristic (explicitly NOT statistical significance).
- Replace the "3 = Medium, 5+ = High" confidence ladder with a directional-only
confidence section: treat every result as directional (not significant) given
realistic volume is well under ~50 conversions/variant; name a direction, not a
winner.
The 20% minimum-meaningful-difference threshold itself stays — it is a legitimate
effect-size heuristic; only the significance framing was the false claim.
Verify: no "Significant?"/"20% significance" remain; "directional" present;
structural lint 0 failed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wave 2 / Step 5 of the remediation plan (coupled criticals: voice-leak +
placeholder-detection).
Voice profile (the adopter-default leak):
- Ship a PII-free placeholder at authentic-voice-samples.md carrying a
<!-- VOICE_PLACEHOLDER --> sentinel + neutral default voice principles.
- Migrate the author's real profile to gitignored authentic-voice-samples.local.md
(already matched by *.local.md; added an explicit, commented .gitignore entry so
the intent is unmissable). NO git-history rewrite — the historical file is
attributed authorship, not a secret (per the plan threat model).
- Add authentic-voice-samples.template.md — a clean fill-in template for adopters.
- personalization-score.mjs: detect the sentinel (deterministic) instead of the
unreliable `[Your Name]` heuristic, so the placeholder scores 0 voice points and
a populated profile (sentinel removed) earns the 25.
- Both voice writers replace-not-append on the placeholder: setup.md (merge ->
replace-if-placeholder) and onboarding.md (append -> replace-if-placeholder), so
populating removes the sentinel; updated setup.md's stale heuristic table.
Operator decisions (deviations from plan-literal, approved this session):
- KEEP the plugin.json author name. The plan said scrub author -> neutral/org, but
that contradicts its own LICENSE reasoning (intentional MIT attribution) and all
5 sibling plugins keep author = the author; scrubbing only this one would create
inconsistency for zero security gain (the name is public-by-design). The voice
placeholder fully fixes the adopter-inheritance bug.
- Scrub the stale "January 2026 360Brew" brand from the plugin.json description and
the "360brew" keyword (locked decision: no publishable model name/date). This is
a Wave-1 propagation miss surfaced here because plugin.json was in Step 5's
touch-scope.
Flagged for follow-up (NOT done here — out of Session 2 scope):
- The lint's stat-consistency grep (scripts/test-runner.sh) scans references/,
commands/, skills/, hooks/prompts/, CLAUDE.md, README.md — but NOT
.claude-plugin/plugin.json, which is why the 360Brew brand slipped Wave 1.
Needs a Session-1-scoped lint extension to add plugin.json to the scan set.
- Readers (user-prompt-context.mjs, voice-guardian.md, state-update-reminder.md)
read the tracked .md (placeholder), per the plan. The operator's real voice now
lives in the gitignored .local.md, which nothing reads. To use it, readers + the
voice score should prefer .local.md (matching the user-profile.local.md
precedent). Deferred as a coherence follow-up for operator review.
Test-first: hooks/scripts/__tests__/personalization-score.test.mjs (red on the
placeholder scoring 25 under the old heuristic, green after the sentinel fix). Hook
suite 62/62, structural lint 0 failed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wave 2 / Step 4 of the remediation plan (docs/remediation/plan.md).
PRIMARY (the real fresh-clone failure):
- scripts/analytics/node_modules is gitignored, so a fresh clone has neither
tsx nor csv-parse. Surface an idempotent `npm install --silent` prerequisite
at point-of-use in report.md (Step 1b) and import.md (Step 4).
DEVIATION FROM PLAN (correction-in-scope, to satisfy the plan's own Verify gate):
- The plan assumed prepending `npm install` was sufficient. Verified it is NOT:
the commands invoke the CLI with an absolute src/cli.ts path but from the
user's arbitrary CWD, and `node --import tsx` resolves the `tsx` specifier
relative to CWD, not the script. There is no global tsx, so the call still
fails with ERR_MODULE_NOT_FOUND from any CWD other than scripts/analytics.
- Complete fix: invoke the locally-installed tsx by its absolute
node_modules/.bin/tsx path in all CLI calls (report.md x10, import.md x3), so
they resolve from any working directory once the install above has run.
Verified: 0 ERR_MODULE_NOT_FOUND running `report` from /tmp.
SECONDARY (latent correctness / hardening):
- Add findPluginRoot(): walks up to the dir holding .claude-plugin/plugin.json
and anchors getAnalyticsRoot() on it, falling back to the legacy 4-up count.
MEASURED that ../../../../ already resolved to the plugin root from BOTH
src/utils and build/utils (both 4 levels deep), so the plan's "src-vs-build
depth miscalibration" premise was false — this is correct-by-construction
hardening (survives a future source move), not a live-bug fix.
- Reconcile cli.ts usage/help text: `node build/cli.js` -> `node --import tsx
src/cli.ts` (the real runtime).
- Fix report.md troubleshooting: "Verify tsx is available" -> the actual
install command on ERR_MODULE_NOT_FOUND.
Test-first: scripts/analytics/tests/storage-root.test.ts (red on missing
findPluginRoot export, green after). Full suite 106/106, tsc --noEmit clean,
structural lint 0 failed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Set expectations up front: the plugin systematizes the work, it doesn't
substitute for the human effort. Letting AI drive lands you in the
forgettable middle; the judgment, genuine engagement, and effort that
make content worth reading stay with the user. Reinforces the README's
no-hype tone and filters for serious adopters over a viral shortcut.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The standalone "What's New in v3.1.0" section opened with internal
development narrative (Endring 9, Del 4 run, framing-bias) that means
nothing to a prospective adopter — still leading with a changelog, the
exact pattern the rewrite set out to fix. Follow llm-security: motivation
first, version detail only in the Version History table at the bottom.
- Remove the "## What's New in v3.1.0" section and its TOC entry
- README now flows intro → Why LinkedIn Studio Exists → What Is This?
→ Two Engines → Quick Start
- Nothing lost: v3.1.0 remains in the Version History table
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The README led with a ~600-word version-by-version wall and stacked
seven "What's New in vX.Y.Z" sections before reaching "What Is This?",
reading as a changelog rather than motivating adoption.
Restructure to the sibling-plugin pattern (config-audit / llm-security
/ voyage):
- Concise motivating intro paragraph (no version enumeration)
- Keep only the latest "What's New" (v3.1.0); full history stays in the
Version History table at the bottom
- New "Why LinkedIn Studio Exists" section: the real pain (blank-page
paralysis, inconsistency, algorithm opacity, generic AI slop, the
360Brew shift) mapped to what the plugin does about each
- New "Two Engines" section framing feed vs. long-form, with the
pre-lock quality gauntlet as the long-form differentiator
- Refresh "What Is This?" to the LinkedIn Studio / content-engine framing
- Swap the unverified "40+ ideas / Content Matrix" claim for the
documented "8 universal angles" (verification duty)
All accurate tables (26 commands, 19 agents, 9 hooks, 24 reference
docs) and the full Version History preserved verbatim.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cold, adversarial review package for the long-form pipeline + configurable
per-edition personas. Motivated by Del 4 (Security Champions pivot): the
in-session editor + persona sweep shared the drafting session's framing-bias,
so the shipped version was never independently re-reviewed.
Headless package (9a/9b):
- New Step 6.5 (headless-review) in /linkedin:newsletter, after the persona
sweep, before lock — the independence layer the in-session gates can't be.
- New standalone /linkedin:headless-review command (run in a fresh session for
maximum isolation; reconstructs frozen draft + contract + personas from disk).
- 3 new Opus archetypes, each with a cardinal context-isolation block that
refuses drafting-session framing as "context pollution":
- content-reviewer (argument integrity C1–C5, ≤8 flags)
- language-reviewer (Norwegian language L1–L5, ≤10 flags)
- fact-reviewer (cold re-verification F1–F4, risk-sort + pivot-risk, WebSearch)
- Deliberate redundancy with fact-checker / editorial-reviewer documented so
the pairs are never de-duplicated.
Pivot-reopen (9c):
- New /linkedin:pivot command: logs articles.NN.pivots[], resets currentPhase,
un-locks, marks gates to re-run.
- Pivot-detection gate in Step 8 lock precondition (>20% word-count change or
>2 new sections re-opens cleared gates). Del 4 v8→v11 worked example.
Per-artifact personas (new requirement):
- articles.NN.personas with resolution order (edition-state → series file →
plugin library → interactive). One or more readers configurable per edition.
Schema/docs:
- edition-state.template.json: additive personas[], pivots[], headlessReview,
headless-review phase (16 phases); personaSweep.resonance.wordCount baseline.
- 3 fasit fixtures + 3 structural lint tests (Del 4 worked cases).
- Counts: 24→26 commands, 16→19 agents, 15→16 newsletter phases.
- README + CLAUDE.md (plugin + root) + CHANGELOG synced.
Verification: 35 agent-fixture + 59 hook + 20 render tests green. Backward-
compatible (additive state); reload required before the 3 new agents resolve.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
BREAKING CHANGE: the marketplace slug, the agent namespace
(linkedin-studio:<agent>), and the runtime state-file path
(~/.claude/linkedin-studio.local.md) all change. Reinstall required;
existing state migrated in place (post metrics, streak, history preserved).
The /linkedin:* commands are unchanged — the command namespace is set
per-command in frontmatter and was always independent of the plugin slug.
Functionality is byte-identical to v2.4.0; this release is pure identity.
- dir + manifests: plugins/linkedin-studio + plugin.json + root marketplace.json
- agent namespace updated in commands/newsletter.md (only functional invoker)
- state path updated in 4 hook scripts + topic-rotation prompt + state template
- catch-all skill dir renamed skills/linkedin-studio (5 functional skills unchanged)
- docs + version bump to 3.0.0 across README badge, CHANGELOG, root README/CLAUDE.md
- historical records (CHANGELOG past entries, docs/ build artifacts,
config-audit v5.0.0 snapshots) intentionally retain the old slug
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>