From d3efe326b4a5bf6e18073370343658e9663188bf Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Thu, 18 Jun 2026 14:28:07 +0200 Subject: [PATCH] =?UTF-8?q?fix(linkedin-studio):=20S5=20harden=20carousel?= =?UTF-8?q?=20=E2=80=94=20Step-5=20caption=20buzzword=20gate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- commands/carousel.md | 2 +- docs/hardening/log.md | 79 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/commands/carousel.md b/commands/carousel.md index 85a8254..e607987 100644 --- a/commands/carousel.md +++ b/commands/carousel.md @@ -120,7 +120,7 @@ If any item fails, fix before presenting. ### De-AI / Differentiation Gate -The caption is the feed text, and it rides the same low-substance down-rank LinkedIn confirmed. Confirm the caption and cover slide carry the signals LinkedIn named — **personal substance, original thinking, concrete specifics, genuine voice** — and use no mechanical-response engagement bait ("Comment YES", "Like for Part 2"); a genuine question is fine. (The voice-guardian hook scores the caption on save.) +The caption is the feed text, and it rides the same low-substance down-rank LinkedIn confirmed. Confirm the caption and cover slide carry the signals LinkedIn named — **personal substance, original thinking, concrete specifics, genuine voice** — and use no mechanical-response engagement bait ("Comment YES", "Like for Part 2"); a genuine question is fine. **Strip corporate buzzwords** from the caption (Content Quality Rule #4: leverage, synergy, paradigm shift, thought leader, disruptive, value proposition, ecosystem, holistic approach) — caption generation can slip them in, and they trip the same low-substance signal. (The voice-guardian hook scores the caption on save.) If the deck's premise is a list the audience has seen many times — commodity content — delegate an originality pass to the `differentiation-checker` agent: invoke it via `Task` with `subagent_type: linkedin-studio:differentiation-checker` (foreground, from this command layer), then sharpen the angle before generating slides. diff --git a/docs/hardening/log.md b/docs/hardening/log.md index 104a50b..8d7d719 100644 --- a/docs/hardening/log.md +++ b/docs/hardening/log.md @@ -463,3 +463,82 @@ the value-add is adaptation fidelity (each platform's own rules) + correct routi confirmed non-post-emitting (no LinkedIn predicate imposed). --- + +## Session 5 — Create II (`carousel`) + +> S5 status: re-grounded the proposed predicates against the actual `carousel.md` lines BEFORE +> talk (jerndisiplin: assert-after-read). Field-notes inbox **absent** at S5 → graceful no-op (SC-I). +> All `file:line` below are tool-grounded against the FINAL (post-edit) file. +> **Class call (operator-agreed):** hybrid **guided/stateful + post-emitting on the caption** — the +> deck/images are the guided artifact, but the caption IS LinkedIn feed text, so the post predicates +> apply *to the caption* (not to the slides). Slides are bound by mobile-readability rules, not the +> feed bar. + +### /linkedin:carousel — template→slide-by-slide deck + caption + optional mcp-image, full deck to clipboard + +**INTENT.** `carousel` is the Create journey's **document-post path**: from a chosen template +(How-To / Listicle / Story / Comparison / Framework) + a topic, produce a publish-ready carousel — +structured slide-by-slide copy (header + body + visual note per slide) + a feed caption + optional +slide images (mcp-image), all assembled into ONE clipboard payload. Carousels/documents are the +top organic format (~7%; `references/algorithm-signals-reference.md`). Hybrid class: the deck is the +guided/stateful artifact; the **caption is post-emitting** and must honor the content bar mechanically +on the caption (hook **110–140**, no banned buzzword, topic→5 pillars) + graceful mcp-image degradation. + +**SIMULATE.** +- **Persona (ICP):** the author — 1048 followers, "Validation", 5 pillars; direct/technical NO/EN voice. + Builds a **How-To Guide** carousel on a pillar topic; tested both mcp-image-available and -unavailable. +- **Invocation:** `/linkedin:carousel` → pick template 1 (How-To) → topic + audience. +- **Walk:** Step 0 (`:24`) load state/voice/recent → Step 1 (`:30`) AskUserQuestion template → Step 2 + (`:50`) topic+audience → Step 3 (`:58`) slide copy → Step 4 (`:94`) caption (hook 110–140 `:97`, band + 300–500 `:103`) → **Step 5 quality + De-AI gate (the gap)** → Step 5.5 (`:127`) mcp-image (graceful) + → Step 6 (`:156`) present full deck → clipboard one-payload (`:191–213`) → Step 7 (`:218`) state. +- **CONCRETE friction (spec-level, anchored — not a generated deck):** at **Step 5** the De-AI / + Differentiation gate (pre-edit `:121–123`) confirmed *personal substance · original thinking · + concrete specifics · genuine voice* and banned mechanical engagement-bait, but had **no buzzword + line** — `grep -niE "buzzword|leverage|synergy|paradigm"` over the whole file = **NONE**. So a + caption opening *"How to leverage AI to drive synergy across the public-sector ecosystem…"* would + pass Step 5 unflagged; content rule #4 (`CLAUDE.md:124`) was never enforced at the caption gate. + Same failure class S2/S3 fixed in `post`/`react`. (Caption generation in Step 4 is exactly where a + rewrite can slip buzzwords in.) +- **No dead-ends:** all 5 referenced files exist (`agents/differentiation-checker.md`, + `assets/templates/carousel-templates.md`, `references/algorithm-signals-reference.md`, + `hooks/scripts/clipboard-helper.mjs`, `hooks/scripts/state-updater.mjs` — `[ -f ]` all FINNES). + +**EVALUATE (4 axes).** +- **(a) intention fidelity — PASS.** Template→slides→caption→full-deck-clipboard-as-one-payload + (`:191–213`, explicitly "the whole carousel, not just the caption") + state — delivers the promise. +- **(b) algorithm bar — PASS.** ~7% (`:37`) matches the ref exactly (`algorithm-signals-reference.md:55`, + "Documents / carousels | Top organic format (~7%…)"); "document post" framing correct (`:170`, LinkedIn + removed native carousels Dec 2023); caption hook 110–140 (`:97`). +- **(c) MECHANICAL predicate (post-emitting, on the caption) — GAP → fixed.** hook band ✓ (`:97`) · + caption band 300–500 ✓ (`:103`) · topic→pillars ✓ (`:26/:56`) · subagent resolves ✓ (`:125`) · + **buzzword ✗** (grep NONE; De-AI gate had no rule-#4 line). *no-body-link not imposed: a carousel + caption is not a typical link site and the command never asks for links — minor, deferred (matches + S2–S4 which left it untouched).* +- **(d) agent-wiring + graceful degradation — PASS.** `differentiation-checker` resolves, namespaced, + conditional (`:125`, `subagent_type: linkedin-studio:differentiation-checker`). **mcp-image graceful + degradation solid:** "If mcp-image is unavailable or fails, skip… degrades to text-only" (`:129`), + per-call failure logged + continue, all-fail → text-only Step-6 design-guide branch (`:154`, `:176`). + `state-updater` exports `updatePostTracking` (`:55`) + `writeState` (`:346`) — Step-7 wiring correct. + +**HARDEN (surgical — 1 edit, 1 file, grep-confirmed landed).** +- `commands/carousel.md:123` — **extended** the Step-5 De-AI gate with content rule #4: + `**Strip corporate buzzwords** from the caption (Content Quality Rule #4: leverage, synergy, + paradigm shift, thought leader, disruptive, value proposition, ecosystem, holistic approach) — + caption generation can slip them in, and they trip the same low-substance signal.` +- **Deferrals:** *no-body-link on the caption* (low risk, command never emits links; S2–S4 precedent) + + two cosmetic notes recorded, not edited (slide line-count 5 vs 7 between `:73–77` and `:87`; both + are NICE-only, below the stopping-rule's axis-pass bar). +- **CONCRETE after:** the "leverage…synergy…ecosystem" caption now trips the Step-5 buzzword line + before the deck is presented. + +**VERIFY.** +- `bash scripts/test-runner.sh` → `Passed: 81 · Failed: 0 · Warnings: 0`; counts **29/19/26/6** + unchanged (`ls commands/*.md|wc -l` == 29, `ls agents/*.md|wc -l` == 19; `git diff --stat` = + `carousel.md` only, 1 line changed). Only `.md` touched → hooks/analytics `node --test` not needed. +- Before/after delta: axis (c) buzzword sub-check now enforced at the load-bearing Step-5 caption gate. + The 1 edit is the cause. +- Disposition: **HARDENED** (1 edit, axis-c) · 2 recorded deferrals (no-body-link + cosmetic) · axes + a/b/d PASS. + +---