Commit graph

116 commits

Author SHA1 Message Date
d3efe326b4 fix(linkedin-studio): S5 harden carousel — Step-5 caption buzzword gate
S5 close-out (1 edit / 1 file · lint 81/0 · counts 29/19/26/6):
- carousel.md:123 Step 5 De-AI gate: add content rule #4 buzzword line to the caption gate (was missing; grep NONE pre-edit; caption is post-emitting feed text)

Axis-c (buzzword on the caption) closed; axes a/b/d PASS. Class: hybrid guided/stateful + post-emitting on the caption. mcp-image graceful degradation + differentiation-checker wiring verified. 2 deferrals (no-body-link on caption + cosmetic slide line-count). Local-only per push policy.
2026-06-18 14:28:07 +02:00
a3d26b223c fix(linkedin-studio): S4 harden multiplatform — Step-0 empty-source fallback + cross-platform buzzword line
S4 close-out (2 edits / 1 command file · lint 81/0 · counts 29/19/26/6):
- multiplatform.md:28 Step 0: empty-source fallback (drafts empty + no recent posts + nothing pasted -> stop, ask user to paste; never fabricate source)
- multiplatform.md:45 Adaptation Templates: cross-platform voice-hygiene line (banned buzzwords = content rule #4; adaptation rewrites can introduce them)

Class call: NOT post-emitting (output is Twitter/slides/YouTube) -> no LinkedIn predicate imposed; tested as guided/cross-format + routing sub-predicate. Routing (/linkedin:newsletter) + both reference files resolve; no subagents. Axis-c (buzzword) + axis-d (degradation) closed; axes a/b PASS. Local-only per push policy.
2026-06-18 14:10:17 +02:00
b8c2155003 fix(linkedin-studio): S3 harden react — Step-6 buzzword gate + WebFetch-failure fallback (both paths)
S3 close-out (3 edits / 1 file · lint 81/0 · counts 29/19/26/6):
- react.md:131 Step 6: add no-buzzword checklist line (was missing; banned list = content rule #4; covers Step 6b via "Same as Step 6")
- react.md:60 Step 2: WebFetch-failure fallback (paywall/JS/YouTube-no-transcript -> ask user to paste or pick another; never fabricate)
- react.md:194 Step 2b: same fallback pointer for the multi-URL comparison path

Axis-c (buzzword) + axis-d (graceful degradation) closed on both paths; axes a/b PASS. Shared scorecard already clean post-S2. Local-only per push policy.
2026-06-18 13:44:00 +02:00
69840e7a94 fix(linkedin-studio): S2 harden post — Step-5 buzzword gate + scorecard hook-band consistency
P4 close-out (4 edits / 2 files · lint 81/0 · counts 29/19/26/6):
- post.md Step 5: add no-buzzword checklist line (was missing; banned list = content rule #4)
- quality-scorecard.md l.32/114: one-sided "140" hook bound -> "110-140" (matches l.128, resolves self-contradiction)
- quality-scorecard.md: add no-buzzword line to Pre-Publish Basic Checklist

Shared scorecard fix benefits 8 consumers; only post hardened this session (react/batch/video/pipeline get own EVALUATE in S3/S5/S6/S8). Local-only per push policy.
2026-06-18 13:32:56 +02:00
68f7701d74 feat(linkedin-studio): M0 — per-user external data dir (v0.5.0) 2026-06-18 13:17:35 +02:00
ef3fa939d1 test(linkedin-studio): M0-17 — full green gate (SC1–SC7 verified): lint 81/0 · hooks 128/0 · analytics 119/0 + tsc clean 2026-06-18 13:13:06 +02:00
8275159aad test(linkedin-studio): M0-16 — lint: EXPECT_REFS=26 + no-bare-path + no-pin + SC2 dry-run (R1) + drop 5 ANALYTICS_ROOT pins it caught 2026-06-18 13:11:50 +02:00
6bd263144f docs(linkedin-studio): M0-15 — repoint remaining prose families + route ab-tests/plans 2026-06-18 13:04:18 +02:00
c0abb82d9c docs(linkedin-studio): M0-14 — D3 path-convention + voice-readers prototype 2026-06-18 12:38:17 +02:00
1d985991d1 chore(linkedin-studio): M0-13 — 4 D2 templates + scrub leak + scaffold fallback 2026-06-18 12:19:48 +02:00
5c1e1800f0 refactor(linkedin-studio): M0-12 — wire + run migrateData (data externalized before scrub) 2026-06-18 12:11:11 +02:00
33aa3c4ca9 docs(linkedin-studio): M0-11 — drop in-plugin ANALYTICS_ROOT pins + repoint content-history (B1/B2) 2026-06-18 12:05:15 +02:00
c35e9fc9d3 refactor(linkedin-studio): M0-10 — content-filter recognizes external drafts (after negatives, before infraDirs) 2026-06-18 11:50:04 +02:00
629ff7ff58 refactor(linkedin-studio): M0-9 — REMEMBER.md materializes external (anti-pattern fix) 2026-06-18 11:48:24 +02:00
289eab498e refactor(linkedin-studio): M0-8 — voice read via getDataRoot (SC7) 2026-06-18 11:45:14 +02:00
3ddf9c5ffa refactor(linkedin-studio): M0-7 — scorer reads external instance (mirrors MOVE/COPY_FILES), plugin fallback (HIGH #3) 2026-06-18 11:42:50 +02:00
abc19b5641 refactor(linkedin-studio): M0-6 — quick-import.mjs via getDataRoot + fix printed path 2026-06-18 11:35:14 +02:00
7f386943c6 refactor(linkedin-studio): M0-5 — queue-manager.mjs via getDataRoot('drafts') 2026-06-18 11:31:56 +02:00
9e059f8a7f refactor(linkedin-studio): M0-4 — migrate-data.mjs atomic+locked+idempotent (created, not wired) 2026-06-18 11:21:00 +02:00
e5806b3890 test(linkedin-studio): M0-3 — resolver twin-consistency test (R2) 2026-06-18 11:12:50 +02:00
760d4c9101 refactor(linkedin-studio): M0-2 — storage.ts getDataRoot + external default (ANALYTICS_ROOT alias kept) 2026-06-18 11:12:11 +02:00
dc294495d6 refactor(linkedin-studio): M0-1 — data-root.mjs resolver twin + test 2026-06-18 11:08:52 +02:00
49eb346812 chore(gitignore): add session/local-state baseline (polyrepo split) 2026-06-18 10:21:12 +02:00
4a60abec7f docs(linkedin-studio): M0 implementation plan (18 steps, adversarially reviewed + revised)
/trekplan on docs/m0/brief.md -> docs/m0/plan.md. 8 exploration agents.
plan-critic REPLAN on v1 (3 blockers + 5 majors + 5 minors); all 13 closed.
scope-guardian ALIGNED (SC1-SC7 + D1-D6 covered). Validator 18 steps / 0 errors.
Local only - not pushed (planning push-policy).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 09:46:28 +02:00
a9d86005f5 docs(linkedin-studio): M0 per-user data-dir migration brief (ratified)
Grounds the architecture-first M0 workstream (v0.4.0 -> v1.0.0). Three
read-only mapping passes corrected the surface from STATE.md's stale 108
to 195 references (~138 in commands/), of which ~186 are .md prose and
only ~3 executable seams do real I/O. Six decisions (D1-D6) ratified.

Brief only; M0 is not implemented. Next step is /trekplan in a fresh
session. Local commit, not pushed (operator-decided).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-01 14:34:55 +02:00
d7c5cdc487 docs(linkedin-studio): simplify README 663 → 260 lines
Trim the front-door README to essentials: value prop, two engines, quick start, full command overview, compact 19-agent roster (lint-required model surface), merged boundaries, quality rules, 2 examples, license. Deep reference (knowledge base, hooks/skills/personalization/config/analytics internals, agent pipeline) now points to references/ and CLAUDE.md; full version history points to CHANGELOG. The pre-1.0 note is gap-framed (what is not done yet), not a promised roadmap. No functionality changed; lint green (74/0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 19:40:25 +02:00
3a7b0a1872 chore(linkedin-studio): re-baseline 4.1.0 → 0.4.0 (honest pre-1.0 maturity)
Reset version declarations to v0.4.0 across plugin.json, README badge + version-history, CLAUDE.md header, and the root marketplace README entry. The 1.0.0–4.1.0 numbering reflected ambition, not maturity: user data still lives inside the plugin tree (.gitignore-defended), no command has passed the hardening quality-gate, command testing is incomplete, and there is no GUI. A deliberate marketplace downgrade (existing installs will not auto-pull a lower number). Path to v1.0.0 = architecture (M0 per-user data-dir migration) + hardening + command testing + GUI. No functionality changed — only version declarations; all prior changelog/history preserved. Lint green (Passed 74 / Failed 0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 19:13:35 +02:00
c3ea883833 docs(linkedin-studio): replace v1 autonomous hardening plan with v2 interactive
v1 (autonomous 5-step + reviewer swarm + /trekreview gate) produced confident
fabrications and burned context for what are usually 0-1 line edits. v2 is a
slow, dialogic, one-command-per-session gate with the operator as truth source
and every mechanical claim tool-grounded. Method, command-class predicates,
session queue, and STATE.md end-of-session handoff are documented in plan.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 07:47:17 +02:00
94760cde90 fix(linkedin-studio): S1 hardening — method calibration (quick) + Start journey
Hardening phase S1. Tightened the hook character bound from one-sided
(under 140) to the full canonical 110-140 band across the Start-journey
creation surfaces, matching hooks/prompts/content-quality-gate.md:
- quick.md: hook band on Step 2 + Step 5 checklist; added a buzzword check
  and a 150-500 length-band check; checklist tally 6 -> 7.
- onboarding.md: hook band in Phase 3.2 + 3.3 (length + no-links already present).
- first-post.md: hook band in Step 4 + Step 5 (length + no-links already present).
- setup.md: zero-edit pass (all four axes already satisfied).

Adds docs/hardening/log.md (per-command audit trail, 5-step method) and
docs/hardening/review.md (cold /trekreview: ALLOW, 0 BLOCKER/0 MAJOR/1 MINOR).
Lint Failed:0, counts 29/19/25/6 unchanged. No structural/version churn.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 06:46:11 +02:00
78409306ca docs(linkedin-studio): hardening-phase foundation (brief + adversarially-reviewed plan)
New phase after the baseline-audit remediation (S1-S17, bf9d432, complete):
a command-hardening pass that simulates each of the 29 commands and tightens
it to its stated intention (intention-fidelity + prompt-quality only — no
structural redesign, no new features, no GUI/M0). Runs over ~8 journey-grouped
Voyage sessions, gated by lint + /trekreview ALLOW before push.

Foundation laid this session (execution starts next session):
- docs/hardening/brief.md (valid; 3 locked forks: hybrid simulation,
  intention-fidelity+prompt-quality, per-journey cadence; research skipped —
  the 2026 bar is frozen in algorithm-signals-reference.md)
- docs/hardening/plan.md (8 sessions, Grade B+ 87)

Adversarial review: brief-reviewer PROCEED_WITH_RISKS (3 findings folded:
self-graded quality axis, SC-H deferral contradiction, no stopping rule);
plan-critic REVISE (2 blockers + 10 major — all addressed: anchored coverage
predicate kills substring false-positives, full-session cold-reviewer oracle
on concrete before/after output, per-type mechanical predicate, Failed:0 gate
not literal-74, S1 HALT circuit-breaker); scope-guardian ALIGNED.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 05:31:52 +02:00
bf9d4327bd docs(linkedin-studio): S17 — C13–C46 triage (0 still-real) closes audit remediation
Cold-read triage of the ~34 uncalibrated baseline-audit findings (C13–C46)
that never got a second hostile pass. An independent Opus reader classified
each against the current code; every disposition was grep-verified in the
main session.

Result: 0 still-real, 23 already-fixed, 1 outdated-drop (24 grouped/sub-claim
entries). No inline code fix needed — the v4.0.0 + S13–S16 remediation had
already closed every still-real item (dead lint, 11 orphan agents, carousel
full-deck clipboard, router tiering, onboarding inline, de-AI gate, video gate,
post-feedback-monitor->Opus, series-path parameterization, SKILL roster).

Deliverable: docs/remediation/c13-c46-triage.md (disposition record) +
docs/remediation/review.md (S17 review, ALLOW). /trekreview: brief-conformance
0 findings; code-correctness 2 MAJOR in the triage doc's own prose (one
overclaim, one line-pointer) FIXED in-session — no false-green disposition.

Gate: test-runner.sh 74/0/0, hooks node --test 98/98, analytics 116/116.
M0 (per-user data-dir migration) deferred to the UI track. Remediation COMPLETE.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 04:45:11 +02:00
69fec21f43 feat(linkedin-studio): S16 — optional manual saves in analytics + close deferred onboarding Write MAJOR
Lifts the original v4.0.0 Non-Goal: an optional, manually-entered `saves`
metric through the analytics layer, built location-agnostic (option c) so
UI-brief §9b/M0 relocates the data dir in one place later.

- types: PostMetrics.saves? + Weekly/Monthly summary.totalSaves? (optional);
  new RankableMetric type for the always-numeric index-access whitelist
- parser: dedicated parseOptionalCount() — blank/non-numeric/negative -> undefined
  ("unknown != 0"), genuine 0 kept; saves NOT folded into engagementRate
- reports: totalSaves set only when >=1 post carries saves (backward-compat)
- cli: saves surfaced in import summary + weekly/monthly totals + per-post
- S16-pre: onboarding.md allowed-tools gains Write (closes S15-deferred MAJOR)
- docs (three-doc rule): plugin README boundary + analytics README + root README
  + plugin CLAUDE.md + CHANGELOG; dwell stays explicitly unmeasurable

Independent /trekreview: brief-conformance 0 findings; code-correctness 2 MAJOR
(own lockstep misses) FIXED in-session (parseOptionalCount + edge tests). Gate:
tsc clean, analytics 116/116, lint 74/0/0, hooks 98/98. Within-v4.1.0 refinement
(no surface/count/version change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:23:12 +02:00
e36efe9944 fix(linkedin-studio): S15 — UX finish §6c (B1 onboarding inline-draft + B3 carousel full-deck clipboard)
B2 (router tiering) was already delivered in S14, so S15 = B1 + B3 only.
No surface/count/version change -> within-v4.1.0 refinement (S11-S13 precedent).

- B1 (commands/onboarding.md): replace the "Run /linkedin:first-post" dead-end
  hand-off in Phase 3 with the first-post drafting steps embedded inline (3.1 topic
  -> 3.2 3-line draft -> 3.3 QC -> 3.4 present+clipboard -> 3.5 state-update that sets
  first_post_date). Wizard now yields a draft in-flow; 0 dead-end strings. Stays within
  the existing allowed-tools (Read/Bash/AskUserQuestion); UI-brief §12b scope-guard
  honored (no provider seams / progressive-disclosure added).
- B3 (commands/carousel.md): Step 6 now assembles the ENTIRE deck (every slide's copy
  + the caption) into the clipboard payload, not just the caption; full-deck assembly
  precedes the clipboard-helper.mjs call.

Independent /trekreview (2 Opus reviewers): brief-conformance 0 findings; code-correctness
1 MAJOR that is PRE-EXISTING and out of S15 scope (onboarding Phase 2 saves need Write in
allowed-tools; lines 142/157, untouched by the S15 diff) -> DEFERRED to next session per
"ekte design-funn -> neste sesjon". Verdict ALLOW for the delivered scope (not a WARN-override).

Gate: test-runner.sh 74/0/0; node --test 98/98; commands=29; v4.1.0 unchanged.
See docs/remediation/review.md for the full record (ALLOW + 1 deferred MAJOR).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:44:34 +02:00
52df229dfc feat(linkedin-studio): S14 — journey layer (create/measure front-doors + 5-journey router), v4.1.0
14a's cold command-rationalization found ZERO redundancy across the 27 commands
(no defensible merge/cut), so the operator reframed S14 from "merge/cut" to
"add a journey layer over the kept atomics".

- Add /linkedin:create + /linkedin:measure — delegate-only guided front-doors
  (Read/Glob/AskUserQuestion only; route to the command that owns the work)
- Re-tier commands/linkedin.md into 5 journeys (Start/Create/Engage/Measure/Grow);
  onboarding/strategy elevated as Start/Grow front-doors; Engage = calendar+firsthour tier
- 14a honesty nits: router now lists firsthour; calendar cross-links to firsthour;
  competitive confirmed UNGATED (the claimed 1K-gating inconsistency was unfounded)
- Lockstep: EXPECT_COMMANDS 27->29, v4.0.0->4.1.0 across plugin.json / README badges /
  plugin+root CLAUDE.md / README / CHANGELOG; new README commands-badge lint guard
- 14a deliverable corrected: multiplatform entry added (26/27 -> 27/27), header counts,
  competitive nit withdrawn
- Independent /trekreview (2 Opus reviewers) raised 3 MAJORs (stale commands badge,
  router competitive self-contradiction, STATE.md count) — ALL remediated in-session;
  verdict ALLOW

Gate: test-runner.sh 74/0/0; node --test 98/98; commands=29; v4.1.0 consistent.
Additive/minor — no command removed/renamed/behavior-changed; reload registers create+measure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:27:06 +02:00
3383abd3b6 fix(linkedin-studio): S13 — close S12 WARN ($-scalar + false-green test) + $-safety lint guard
Closes the 2 grep/Read-verified findings from the S12 cold full-brief re-review
(docs/remediation/review.md, WARN 0/1/1/0, 0 dropped) and closes the $-injection
CLASS — not the line — across the whole state-updater.mjs mutation surface.

See docs/remediation/review.md (S13 ALLOW, 0/0/0/0) for the full closure record:
replaceField -> replacement function; the 3 additive-insert sites -> functions
(m === $1, behavior-preserving); a scalar assert.match pins last_post_topic; and a
behavioral, coverage-complete, self-testing Section 12 guard (check-replace-safety.mjs)
that is mutation-proven. Docs three-doc + residuals updated. test-runner.sh 71/0/0,
node --test 98/98.
2026-05-30 19:12:45 +02:00
90cf98d287 fix(linkedin-studio): S12 — close S11 re-review + render-chain-propagation lint guard
Closes the 2 grep-verified findings from the S11 cold full-brief re-review
(docs/remediation/review.md, BLOCK 1/0/1/0, 0 dropped). Both were the NEXT
RING of the meta-class S10/S11 converged: a propagation miss — the fix had
landed where the SC named the file, not in the render-source it depends on.

BLOCKER (command->reference propagation): references/ab-testing-framework.md:166
still shipped the banned A/B "Significant? (>20%)" Yes/No verdict column while
commands/ab-test.md (which RENDERS from it, inlined at :30, presented at :69)
had been cleaned to the honest "Directional?" framing. Re-framed the reference
result template to match the command verbatim (header + the directional note)
and retuned :38 "20% significance threshold" -> "minimum-meaningful-difference
threshold". The whole render chain is now significance-verdict-free.

MINOR ($-replacement, class-closed not line-patched): the newest-first section
appends/rewrites in hooks/scripts/state-updater.mjs passed a replacement STRING
embedding untrusted user content to String.replace, so dollar-sequences
($1 / $& / dollar-backtick / dollar-apostrophe / $$) in a topic/hook/partner
(e.g. "$100 budget cut") re-injected the captured heading and dropped
characters, silently corrupting state. Converted all 5 content-bearing sites
(Recent Posts, prune, Milestone Log, First-Hour, Outreach) to replacement
FUNCTIONS; the 3 remaining $1 sites only interpolate date scalars. +4
$-bearing regression tests — incl. the prune fixture, which itself had to
switch to a function (the bug bit the fixture as it was being written).

META (generalize the lint to the propagation-miss class): new test-runner.sh
Section 11 — render-chain propagation guard. Forbids the significance-verdict
column (Significant? adjacent to "(" or a table pipe) across the WHOLE render
chain (commands + every inlined reference + adjacent surfaces), with a
permanent non-vacuity self-test (3 verdict forms caught, 6 legitimate
Significant/significance/Directional? forms ignored) and an e2e mutation-proof.
Generalizes S10/S11's "fix the class, not the line" to command->reference.

Pre-patch render-chain sweep confirmed ab-testing-framework.md was the SOLE
propagation survivor (so a 6th review finds no 3rd). test-runner.sh 70/0/0;
node --test 98/98. CLAUDE.md lint enumeration synced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:42:25 +02:00
be8c9b01fb fix(linkedin-studio): S11 — model-name declaration drift + model-consistency lint guard
Cold full-brief re-review (S10) reached a class the S7->S9 algorithm-stat lens
never did:

BLOCKER — post-feedback-monitor published as Haiku in four surfaces
(README:259, skills/linkedin-studio:159 with wrong color Green too,
skills/linkedin-analytics:41, agents-capability-matrix:20) while
agents/post-feedback-monitor.md runs Opus. v4.0.0's Opus promotion never
reached the user-facing tables. Synced all to Opus/Lime. Refreshed
agents-capability-matrix.md (frozen at the v2.0 14-agent era): header 14->19,
+5 missing longform agents, tier counts Opus 2->8 / Haiku 1->0, longform-gate
diagram updated to the real 8-Opus-agent chain.

MAJOR — de-branded docs/plan-fullspektrum-innholdsmotor.md:70 (model brand +
jan-2026 asserted as fact -> no-name/no-month relevance-model phrasing). It was
the only tracked survivor; the rest live in gitignored ROADMAP.md /
.claude/research/ (not shipped, out of honesty scope).

META — added Section 10 model-consistency guard
(scripts/check-model-consistency.mjs): each agents/*.md model: must match every
surface declaration AND the canonical rosters must list all 19 agents.
Permanent non-vacuity self-test + e2e mutation-proven.

Pre-patch sweep confirmed post-feedback-monitor was the sole drifted agent
(89 model rows, 0 other mismatches). test-runner.sh 68/0/0, node --test 94/94.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 15:05:37 +02:00
bfdae744f9 fix(linkedin-studio): S10 — generalize stale-stat lint to the pattern class + permanent non-vacuity self-test
Closes the S9 re-review (1 BLOCKER + 2 MAJOR, all grep-verified). The survivor
set converged 8 -> 6 -> 2; this closes the meta-problem behind the convergence,
not just the two lines.

BLOCKER — references/glossary.md:10: drop the fabricated "150-parameter
foundation model" (a garbled 150B that the S9 enumerative grep/lint, requiring a
"B"/"billion", could not match). Reframe to "a real input to LinkedIn's 2026
relevance-ranking model" with no parameter count, citing
algorithm-signals-reference.md inline — which makes the :12 "Used in" provenance
accurate (the reference does state the relevance-ranking framing; it never stated
"150-parameter").

MAJOR — CHANGELOG.md:308: de-brand "360Brew profile optimization (January 2026
algorithm update)" -> "Profile/topic-relevance optimization". Removes the
unpublishable brand + asserted Jan-2026 date, honouring v4.0.0's "removed
everywhere" claim. It was the only STALE_STATS hit in CHANGELOG.

MAJOR — scripts/test-runner.sh: the rebuilt lint was enumerative on surface form.
Generalize it to the PATTERN CLASS so the same grep that defines the SC fails on
any surface form, present or future:
  - STALE_STATS model token: "150 ?B param|150 billion param"
      -> "[0-9]+[ -]?(B|billion)?[ -]?param"
    (covers 150-parameter / 150B param / 150 billion param). This robustifies the
    review's literal suggestion "[0-9]+[ -]?(B|billion )?param", which missed the
    space form "150B param"; the separator is moved out of the group.
  - STAT_HITS grep scope += CHANGELOG.md (the 360Brew survivor lived outside it).
  - Permanent non-vacuity SELF-TEST before the real scan: 13 forbidden probes must
    match (incl. the exact "150-parameter" survivor), 8 legitimate probes must not
    ("Language parameter", "parameterized", "different parameters",
    "175-milliarders parametermodell", 5x5x5, cadence, pixel dims, "10x your
    reach"). S7->S9 each shipped a green lint because the proof was run by hand and
    never committed; this makes narrowing STALE_STATS fail the suite.

Verification: test-runner.sh 67/0/0 exit 0 (was 66/0/0; +1 self-test);
node --test 94/94; broadened exhaustive grep across the tree -> zero survivors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:48:37 +02:00
0e4466b893 fix(linkedin-studio): S9 — full algorithm-magnitude sweep + lint rebuilt to the criterion
Closes the S8 re-review (BLOCK 3/4/1). The S8 fix patched only the 2 strings S7 named; the re-review found 6 more same-class survivors. Per the systemic read, this is a comprehensive sweep, not a per-line patch.

Reconciled every retired engagement-coefficient + model-fact survivor against the canonical references/algorithm-signals-reference.md (order, not coefficients; comment ≈ 2x a like; no model name/params):
- glossary.md: coefficient table + Save-Signal '10x weight' → canonical ordering (citation now true)
- engagement-frameworks.md, analytics-interpreter.md, content-optimizer.md, pipeline.md, engagement-coach.md: the 10x/8x/7-9x/2.5x/0.2x system (incl. 4 survivors the re-review did not cite) → ordering
- playbook: '15x more algorithmic boost' + video '5x more conversations' → directional, sourced
- profile.md + linkedin-voice/SKILL.md: '150B parameter foundation model' → '2026 relevance-ranking model'
- quality-scorecard.md: '360Brew Validation' → topic-relevance framing
- setup.md: 'thought leadership plugin' → 'LinkedIn Studio plugin'

Lint (MAJOR 4): rebuilt scripts/test-runner.sh STALE_STATS to forbid EVERY retired-class phrasing (not the 2 S7 strings) + widened scope to assets/checklists/. Targets retired phrasings (7-9x, (10x), '10x weight', '5x more conversations'), NOT bare 10x/15x/5x (legit 5x5x5 / cadence / pixel-dims / '10x your reach' hyperbole). Proven non-vacuous: catches all 10 retired strings, ignores all 10 legit uses.

Tests (MAJOR 7): added no-anchor fall-through tests for recordFirstHourPlan + recordOutreachContact (date scalar not written/reported, section still appended). MINOR 8: reflowed newsletter.md content-repurposer wiring onto one line.

test-runner.sh 66/0/0; node --test 94/94 (was 92, +2). NO push until /trekreview re-clears the gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 09:56:49 +02:00
b48e1305e6 fix(linkedin-studio): close v4.0.0 audit review findings (S8)
Close the 5 findings from the S7 /trekreview release gate (review.md, verdict BLOCK):

- BLOCKER: comment-multiplier "5x" reconciled to the canonical order-only framing
  (no fixed multiplier) in agents/engagement-coach.md, linkedin-growth-playbook,
  linkedin-formats.md — per algorithm-signals-reference.md ("do not quote a comment
  multiplier").
- BLOCKER: carousel rate "6.60%/6.6% (highest)" reconciled to "~7% top organic
  format" in linkedin-formats.md:42 (was self-contradicting :50) and
  assets/templates/carousel-templates.md.
- Lint hardening: test-runner.sh STALE_STATS now matches 6.60% + the 5x comment
  folklore and scans agents/ + assets/templates/ — the grep that defines the
  Phase-0 criterion now catches both BLOCKERs.
- MAJOR: onboarding.md command count 26 -> 27.
- MAJOR: add section-append-branch (production-path) tests for recordFirstHourPlan
  + recordOutreachContact against a template-layout fixture.
- MINOR: move date-scalar changes.push inside the write branch in state-updater.mjs.

Verify: node --test hooks/scripts/__tests__/*.test.mjs -> 92/92; bash
scripts/test-runner.sh -> 66/0/0. NO push until /trekreview re-confirms ALLOW/WARN.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 09:27:15 +02:00
cc4a81f583 chore(linkedin-studio): release v4.0.0 — counts, three-doc, CHANGELOG (clears [skip-docs] debt)
Step 21 (remediation Wave 4 / S6, SOLO): finalize the audit-remediation as
v4.0.0. Version 3.1.0 -> 4.0.0 across all current-version declarations; counts
reconciled to the ls-derived source of truth (19 agents / 27 commands / 6 skills
/ 9 hooks / 25 reference docs / 16 newsletter phases — Step 20 confirmed NO
TRIM); three-doc sync (plugin README + plugin CLAUDE.md + root README) clears the
[skip-docs] debt accumulated across Wave 1-4; CHANGELOG v4.0.0 entry summarizing
Steps 1-20.

Scope additions beyond the plan's literal Files list, all version-sync or
[skip-docs]-debt in nature (flagged, not feature creep):
- ../../CLAUDE.md (root marketplace): linkedin-studio entry v3.1.0 -> v4.0.0
  (the version-sync invariant mandates updating every version reference; leaving
  it stale is a real inconsistency).
- scripts/test-runner.sh: added the version-consistency grep the file's own
  Step-1 comment promised ("added in Step 21") — plugin.json version must match
  the README badge, the CLAUDE.md header, and the CHANGELOG top entry — and
  folded the Wave 2 lint gap (plugin.json now covered by the stat-consistency
  scan). 66/0/0, exit 0.
- plugin README: added the missing /linkedin:firsthour command row (Step 16
  [skip-docs] debt) and the 25th reference doc (longform-quality-rules.md) to
  the knowledge-base table; fixed body counts ("All 26 commands" -> 27, "24
  reference documents" -> 25); badges + intro 26 -> 27 commands, 24 -> 25 refs.
- root README + marketplace.json: dropped the unpublishable model brand/date
  ("360Brew" / "January 2026") the algorithm-signal reconciliation already
  removed everywhere inside the plugin.

Surviving "3.1.0" strings are intentional history, not stale declarations: the
README version-history table row, the "vX added Y" attributions in
plugin.json/CLAUDE.md, and the headless-review reload caveat are all
changelog-genre. Every current-version declaration (plugin.json version, README
badge, CLAUDE.md header, root README marker, marketplace.json) reads 4.0.0.

The major bump reflects the remediation's scope plus the reinstall/reload the
newly-wired agents need to register, and consolidates — does not repeat — the
v3.0.0 identity break; it is not a fresh breaking API change (locked operator
decision).

Pre-existing and out of scope (flagged, untouched): a duplicate /linkedin:setup
row in the README command tables.

Verify: bash scripts/test-runner.sh exit 0 (66/0/0); plugin.json + marketplace.json
parse; counts consistent README == CLAUDE.md == root README; stale-count sweep
clean. NO push — /trekreview (S7) is the release gate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 07:49:48 +02:00
8522651ec5 docs(linkedin-studio): measure long-form review-pass overlap, trim where unjustified
Steg 20 (remediation Wave 4 / S5, SOLO): measure whether the 7-agent long-form
review stack carries redundant gates. Method: cross-reference each agent's check
taxonomy against its in-repo fasit fixture; four fixtures (editorial, content,
language, fact-reviewer) target the SAME Del 4 edition, enabling a real
cross-gate overlap comparison on one piece (not a live run — fixtures' own
live-run notes require a reload + cross-repo Maskinrommet access, out of scope).

Finding: every gate has >=1 unique catch on Del 4. The four genuine overlaps
(verbatim repetition, the Vi/Vi-i-Nav quote, the postulated number, the
small-orgs thread) are each justified — a cold re-take (Endring 9's reason to
exist), the same symptom via a different operation (flag-absence vs web-verify),
or two distinct defects sharing a surface topic — with no subsumption either way.
The fact-checker <-> fact-reviewer overlap is load-bearing (the pivot premise
arrived after Step 5, so only the cold re-run caught it).

Decision: NO TRIM. voice-scrubber has no fixture -> inconclusive; redundancy
retained (Step 20 On-failure = skip). Counts unchanged 19 agents / 27 commands;
count contract (EXPECT_AGENTS=19) untouched. test-runner 62/62 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 07:17:55 +02:00
3893985ebd docs(linkedin-studio): add multi-session/effort banner to newsletter
Step 19 (Wave 4 S4). Adds an expectation banner at the very top of
/linkedin:newsletter: a multi-session, multi-gate process (16 phases),
~4-8+ hours across several sessions, state maintained between sessions, with
a pointer to the short-form commands for feed posts. Sets realistic
expectations before the user starts. Pure docs/content.

Verify: grep -niE 'multi-session|multi-gate|16 phases|~[0-9].*hour' near top
→ matches; test-runner.sh exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 07:08:26 +02:00
b0e7866d95 feat(linkedin-studio): honest newsletter distribution + profile-SEO + outreach pipeline
Step 17 (Wave 4 S4) of the audit remediation. Applies research/03 §D5 + the
two S2 residual fixes folded in. No new commands/agents (counts stay 27/19).

Newsletter (commands/newsletter.md): new "Distribution channel" section after
Step 10 teaching the HONEST native-newsletter mechanics — bypasses organic feed
ranking via ONE deduplicated notification per subscriber per edition (NOT a
three-touchpoint blast); the mass invite fires once → ~1-2K follower floor
(wait until you can spend it); realistic cold-start 0-100 subs months 1-3;
discloses non-export / no-canonical / no-read-analytics / per-subscriber decay;
explicit below-vs-above-floor decision rule. Sourced to research/03 D5.

Profile (commands/profile.md): new "Profile SEO" section — headline as the
highest-weight search field + a per-section keyword-target table
(headline/about/experience/skills/featured), consistency-over-stuffing rule.

Outreach (commands/outreach.md): Step 8c persists the pipeline board to tracked
state via the new recordOutreachContact mutation (mirrors Step 16's
recordFirstHourPlan): additive last_outreach_date/outreach_active scalars + a
non-R-initial ## Outreach Pipeline section in state-updater.mjs +
config/state-file.template.md + --record-outreach CLI branch. +7 tests
(state-updater 26→33, full hook suite 83→90).

Residual 1 (growth-playbook:216): 9:16 "distribution boost" → 4:5/1:1 guidance
(9:16 mobile-only opt-in; "immersive distribution" = uncorroborated heuristic).
Residual 2 (video-strategy-guide:300): "3-second test determines 70% retention"
→ "front-load value for muted autoplay" (three-second hook is folklore, not a
LinkedIn signal).

Verify: grep checks 1-5 pass; test-runner.sh exit 0 (stat-consistency green);
state-updater 33/33. [skip-docs] — tre-doc + version bump deferred to Step 21.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 07:07:41 +02:00
ad5bb702f6 fix(linkedin-studio): promote post-feedback-monitor to Opus (Opus-default)
post-feedback-monitor was the lone non-Opus/Sonnet agent (model: haiku). It
does human-facing, real-time post-publish coaching — exactly the workload the
standing Opus-default targets — so the Haiku setting both contradicts the
default and underpowers the surface the new /linkedin:firsthour command hands
off to (remediation Step 18).

- agents/post-feedback-monitor.md: model haiku -> opus.
- CLAUDE.md: agent-table model column Haiku -> Opus. No Haiku agent remains.

Verify: grep 'model: haiku' agents/ -> none; CLAUDE.md row shows Opus;
structure lint -> 62/62, counts unchanged.

Plan Step 18 (Wave 4 S3). Counts unchanged.
[skip-docs]: tre-doc + version bump deferred to Step 21 per remediation plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 05:36:30 +02:00
b0e8c7b19e feat(linkedin-studio): first-hour/reply-loop command with tracked state
Wire orphan agent #11 (engagement-coach) by giving it a command surface, and
add the tracked first-hour state the plan calls for (remediation Step 16).

- commands/firsthour.md (new, 27th command): post-publish first-hour /
  reply-loop sprint. Delegates plan construction to engagement-coach via
  Task (subagent_type: linkedin-studio:engagement-coach) — returns a grouped
  target list (whales/inner-circle/ICPs/new connections), 2-3 seed
  self-comments + 3-5 CEA replies in the user's voice, and a minute-by-minute
  timeline anchored to publish time. Presents timeline/targets/drafts +
  velocity checkpoints, auto-copies the drafts to clipboard, persists the
  plan, then hands off to post-feedback-monitor for the 48h window.
- hooks/scripts/state-updater.mjs: new pure mutation recordFirstHourPlan()
  mirroring updatePostTracking — additive by contract (inserts
  last_firsthour_date after last_post_date when absent, creates the
  ## First-Hour Plans section when absent, never touches existing fields).
  Section name is deliberately non-R-initial so it stays outside
  pruneContentHistory's "## Recent Posts ... (?=\n## [^R])" capture window.
  + a --record-firsthour CLI branch for parity with the other mutations.
- config/state-file.template.md: additive scalars (last_firsthour_date,
  firsthour_active) + the ## First-Hour Plans section.
- hooks/scripts/__tests__/state-updater.test.mjs: extend (existing file) with
  7 recordFirstHourPlan tests — section creation, field insertion vs in-place
  update (no duplication), round-trip non-interference, graceful empty
  defaults, changes array.
- CLAUDE.md: register the command (## Commands 26 -> 27, table row).
- scripts/test-runner.sh: EXPECT_COMMANDS 26 -> 27 (registration guard).

Verify: grep 'subagent_type: linkedin-studio:engagement-coach' commands/ ->
firsthour.md; node --test state-updater -> 26/26; full hook suite -> 83/83;
bash scripts/test-runner.sh -> exit 0 (62 passed, commands 27/27).

Plan Step 16 (Wave 4 S3).
[skip-docs]: tre-doc + version bump deferred to Step 21 per remediation plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 05:35:44 +02:00
900a959c0b feat(linkedin-studio): video quality gate (captions + aspect guidance, drop 9:16 mandate)
Resolve the video-advice contradiction on the two surfaces this step owns
(research/03 D1-D3):

- commands/video.md: rename the "3-Second Test" to a "Muted-Autoplay Test"
  (front-load value for ~85% muted viewing; the "three-second hook" is
  cross-platform folklore, not a LinkedIn signal); make captions the
  enforceable spec (SRT or native auto-captions, indexed for search);
  aspect ratio as guidance (4:5/1:1 preferred for broad distribution,
  9:16 opt-in for the vertical video tab, crops to 1:1 on desktop); add
  MP4-default + warn-only MOV/AVI + official upload limits to the
  pre-recording reminder.
- references/linkedin-formats.md: reframe the 9:16 "distribution boost"
  as uncorroborated heuristic; 4:5 "deprioritized" -> 4:5/1:1 preferred;
  drop the "3-second hook"; MP4 safe-default + warn-only MOV/AVI; replace
  "good video rewarded more than ever" with the honest "per-video reach
  declining; documents/carousels out-engage video."

algorithm-signals-reference.md (the canonical magnitude source) was
already reconciled in Phase 0 (line 56 reads "declining ... 4:5/1:1
preferred, captions are the enforceable spec") and carries no boost copy,
so it is intentionally untouched here — and it is not in this step's
manifest.

Verify: grep 'must be 9:16|9:16 (1080|3-second hook' video.md
linkedin-formats.md -> none; 'captions' video.md -> 5; 'deprioritized'
linkedin-formats.md -> none; structure lint 61/61.

KNOWN RESIDUAL (flagged for follow-up, NOT in this step's scope):
- references/linkedin-growth-playbook-2025-2026.md:216 still carries a
  "9:16 ... distribution boost" line. That file is owned by Step 17, but
  Step 17's changes are newsletter-distribution — the video line would
  fall through. Fold this into Step 17 or the review gate.
- references/video-strategy-guide.md:300 still says "the 3-second test
  determines 70% of retention." That file is owned by NO plan step
  (orphaned) — needs a home. Surface at session end for an operator
  decision.

Plan Step 15 (Wave 4 S2). Counts unchanged.
[skip-docs]: tre-doc + version bump deferred to Step 21 per remediation plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 02:37:51 +02:00
5584ae1cb8 feat(linkedin-studio): short-form de-AI gate via differentiation-checker + voice-guardian
Wire the orphan differentiation-checker (#10) into the five short-form
creation commands (post/quick/react/carousel/video) as a De-AI /
Differentiation Gate at each command's quality-check step: confirm the
LinkedIn-named substance signals (personal substance, original thinking,
concrete specifics, genuine voice) + a soft engagement-bait check, and
delegate an originality pass to linkedin-studio:differentiation-checker
when the angle risks commodity content. Add Task to allowed-tools in
quick/react/carousel (post/video already had it from Step 13).

Extend (not duplicate) hooks/prompts/voice-guardian.md's AI-pattern
section with the same named signals from research/01 D8 + research/03 D4.
Runtime-loaded prompt — no compile-hooks.py, no hooks.json change
(verified: compile-hooks --check reports no drift).

Test: new hooks/scripts/__tests__/linkedin-content-filter.test.mjs pins
the content/non-content boundary the gate is scoped by (14 tests).
Full hook suite 76/76, structure lint 61/61.

Plan Step 14 (Wave 4 S2). Counts unchanged (26 commands / 19 agents).
[skip-docs]: tre-doc + version bump deferred to Step 21 per remediation plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 02:31:41 +02:00
570b163bbe refactor(linkedin-studio): wire or delete 11 orphan agents (case-by-case) — 9 here, 2 in Steps 14/16
Resolves the orphan-agent audit finding by the locked default: wire all, no deletions, so the agent count stays 19. Per agent, added Task to the target command's allowed-tools and a coherent 'subagent_type: linkedin-studio:<name>' delegation at a real point in the command's flow (not a token grep-match).

Wired (agents 1-9 of 11): video-scripter -> video.md (Step 4); content-optimizer -> post.md (Step 7 refinement) + ab-test.md (2a.4 optimized challenger); analytics-interpreter -> report.md (Step 7, report mode) + analyze.md (Step 2, interpret mode); content-planner -> batch.md (Step 2) + pipeline.md (Step 1); trend-spotter -> batch.md (Step 1) + pipeline.md (Step 1); network-builder -> outreach.md (Step 3a); strategy-advisor -> strategy.md (Step 3); voice-trainer -> setup.md (Step 3a); post-feedback-monitor -> calendar.md (publish action, 48h monitor).

Deferred to their dedicated steps: #10 differentiation-checker -> Step 14 (short-form de-AI gate), #11 engagement-coach -> Step 16 (first-hour command). Namespaced subagent_type form requires a session reload before the wired agents are invokable.

Verify: each of the 9 has >=1 invocation in commands/; structural lint 61/61 (counts 19/26/25/6 intact); agent-fixtures 35/35; hook tests 62/62. Three-doc + version reconciliation deferred to Step 21 per the locked plan [skip-docs].

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 01:26:36 +02:00
0e04bbc662 docs(linkedin-studio): reconcile discoverability surfaces + skill naming
Wave 3 / Step 12 of the remediation plan (Phase 1 — usable by a non-author).

Fix the discoverability defects the audit flagged:
- skills/linkedin-studio/SKILL.md (the auto-activating router): self-naming 'the
  LinkedIn thought leadership plugin' -> 'LinkedIn Studio' (v3.0 rename leftover);
  the 'All Agents' table corrected from 14 to the real 19 (added editorial-reviewer,
  voice-scrubber, content-reviewer, language-reviewer, fact-reviewer); the 'All
  Commands' table completed to 26 (added headless-review, pivot, carousel) so it
  routes to newsletter/headless-review/pivot/react.
- commands/onboarding.md: '25 commands' -> '26 commands' (x2); pillar count '3-5
  expertise areas' -> '5 expertise areas' (reconciles onboarding's 3-5 with
  setup.md's '5 core topics' and the CLAUDE.md '5 core expertise areas' rule).
- commands/linkedin.md: router table + numbered option list gain headless-review
  and pivot.

Scope note (operator decision, this session): the plan's Verify grep
'grep -rni "thought leadership" skills/ -> no matches' is broader than the brief's
actual criterion (which targets only the router skill's self-naming). 'thought
leadership' is a plugin-wide DOMAIN term — the '8 Thought Leadership Angles'
framework lives in references/thought-leadership-angles.md and is referenced by ~40
files (glossary, agents, post/video/batch commands). Renaming it only inside skills/
would create cross-file inconsistency; renaming it plugin-wide is a separate
vocabulary migration outside Step 12's discoverability scope. Per operator choice,
the router SELF-NAMING is fixed (brief criterion met) and the 4 remaining skills/
hits (linkedin-content-creation headings + one linkedin-strategy phase cell) are
legitimate domain usage kept consistent with the rest of the tree.

setup.md needed no edit: its pillar number was already '5'; reconciliation was a
one-sided fix in onboarding.

Verify: router no longer says 'thought leadership plugin'; grep -nc 'headless-review'
commands/linkedin.md -> 2; onboarding pillar count '5' matches setup.md; SKILL.md
agent table 19 rows, command table 26 rows; structural lint exit 0 (61 passed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 01:05:19 +02:00