diff --git a/commands/video.md b/commands/video.md index 05891dd..86a3ca9 100644 --- a/commands/video.md +++ b/commands/video.md @@ -39,9 +39,11 @@ Load video-specific references: - Read `references/linkedin-formats.md` (Video Content Deep Dive section) for algorithm data and technical specs Check for existing assets: -- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` — Match the user's natural voice (REQUIRED before scripting) +- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/voice-samples/` — Match the user's natural voice (read before scripting) - `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/examples/high-engagement-posts.md` — Study successful patterns +**Graceful degradation (fresh adopter):** if `voice-samples/` is empty or absent, don't block — fall back to the voice settings in `skills/linkedin-studio/SKILL.md` (or neutral defaults), note that the script uses a default voice, and proceed. The voice-guardian is suppressed under 5 samples, so there is no hard gate to satisfy. + ## Step 1: Choose Video Type Use AskUserQuestion: @@ -124,7 +126,7 @@ Before presenting, verify the script passes the video quality gate: ### De-AI / Differentiation Gate -The post caption rides the same low-substance down-rank LinkedIn confirmed for text. Confirm the script's core idea and caption 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 post caption rides the same low-substance down-rank LinkedIn confirmed for text. Confirm the script's core idea and caption 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.) **Strip corporate buzzwords** from the post caption (Content Quality Rule #4: leverage, synergy, paradigm shift, thought leader, disruptive, value proposition, ecosystem, holistic approach) — re-shaping a text idea into a video caption can slip them in, and they trip the same low-substance signal. If the idea is a take 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 presenting. diff --git a/docs/hardening/log.md b/docs/hardening/log.md index 8d7d719..55a5f6a 100644 --- a/docs/hardening/log.md +++ b/docs/hardening/log.md @@ -542,3 +542,93 @@ on the caption (hook **110–140**, no banned buzzword, topic→5 pillars) + gra a/b/d PASS. --- + +## Session 6 — Create II (`video`) + +> S6 status: re-grounded the proposed predicates against the actual `video.md` lines BEFORE +> talk (jerndisiplin: assert-after-read). Field-notes inbox **absent** at S6 → 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 post caption** — +> the script / captions / thumbnail are the guided artifact (bound by video rules: muted-autoplay, +> 2.5 wps, completion-rate), but the **POST CAPTION (200–400) IS LinkedIn feed text**, so the post +> predicates apply *to the caption* (not the script). **Hook 110–140 deliberately NOT imposed on the +> caption (operator-agreed):** the caption accompanies the video; the primary hook discipline is the +> muted-autoplay opening (`:100`), not a standalone-post hook — imposing it would be S4's category error. + +### /linkedin:video — type→length→angle→video-scripter script + captions + 200–400 post caption + first comment + +**INTENT.** `video` is the Create journey's **video-script path**: from type (talking-head / screen-rec / +slideshow / convert-a-text-post) + length (30/60/90/120 s) produce a production-ready script via the +`video-scripter` agent — timing markers, visual/energy cues, captions, thumbnail, a 200–400-char post +caption, and a first comment — then save to drafts + deterministic state update. Hybrid class: the script +is the guided/stateful artifact; the **post caption is post-emitting** and must honor the content bar +mechanically on the caption (no banned buzzword, topic→5 pillars, no body link) + 2.5-wps pacing + +graceful degradation when voice samples are absent. + +**SIMULATE.** +- **Persona (ICP):** the author — 1048 followers, "Validation", 5 pillars; direct/technical NO/EN voice. + Builds a 60-s talking-head on a pillar topic. **+ fresh-adopter path** (no voice samples) reasoned to + exercise graceful degradation (relevant here because of the pre-edit "REQUIRED before scripting"). +- **Invocation:** `/linkedin:video` → talking-head → 60 s → pillar topic. +- **Walk:** Step 0 load state/voice/refs → Step 1 type → Step 2 length (2.5-wps budgets) → Step 3 angle + (topic→pillars) → Step 4 `video-scripter` generates → **Step 5 quality + De-AI gate (the gap)** → + Step 6 present + clipboard post caption → Step 7 refine → Step 8 save + state. +- **CONCRETE friction (spec-level, anchored — not a generated script):** + - **(axis c)** at **Step 5** the only buzzword line (`:106`, pre-edit) sat under the **"Natural Speech + Test"** = the *script's spoken language*; the **caption** De-AI gate (`:129`) carried **no rule-#4 + line** (`grep buzzword` → single hit at `:106`). A caption opening *"How to leverage AI to drive + synergy across the public-sector ecosystem…"* would pass the caption gate unflagged. Same failure + class S2/S3/S5 fixed in `post`/`react`/`carousel` (the caption is re-shaped from a text idea in + Step 4 — exactly where a rewrite slips buzzwords in). + - **(axis d)** `:42` (pre-edit) "voice-samples … **(REQUIRED before scripting)**" + `:90` "Match voice + against voice-samples/" had **no fallback** for a fresh adopter with an empty/absent samples dir — + "REQUIRED" reads as a hard block / dead-end. Same failure class as S3 (WebFetch-no-extraction) / S4 + (empty-source). + +**EVALUATE (4 axes).** +- **(a) intention fidelity — PASS.** 8-step workflow delivers the description's promise (script + pacing + + cues + captions + thumbnail + 200–400 caption + first comment + refine + save + state). +- **(b) algorithm bar — PASS.** Muted-autoplay correctly de-mythologized (`:100`, "three-second hook = + folklore; LinkedIn's only official 3 s = minimum length"); captions = the enforceable spec (`:120`); + 60 s sweet spot; 2.5-wps budgets exact (`:64/:66`, 75/30 = 150/60 = 225/90 = 300/120 = 2.5). *Honesty + note (deferred, operator-agreed):* `:69` "LinkedIn requires 30 % completion or **zero distribution**" + is more absolute than the declared SSOT `algorithm-signals-reference.md:56` (no 30 %, confidence + *medium*); it is consistent with `linkedin-formats.md` (cited at `:39`, l.58). Inter-reference tension, + NOT a video-command gap — deferred (brief Non-Goal: no re-litigation of the bar). +- **(c) MECHANICAL predicate (post-emitting, on the caption) — GAP → fixed.** no-body-link ✓ (`:125`) · + topic→pillars ✓ (`:124` + Step 3) · caption band 200–400 ✓ (`:121`) · subagent resolves ✓ (`:83/:131`) · + **buzzword ✗** (grep: single hit `:106`, under Natural Speech = script not caption; caption De-AI gate + had no rule-#4 line). **hook 110–140 deliberately not imposed** on the accompanying caption (class + boundary, operator-agreed; primary hook = muted-autoplay `:100`). +- **(d) agent-wiring + graceful degradation — wiring PASS; degradation GAP → fixed.** `video-scripter` + (`:83`) + `differentiation-checker` (`:131`, conditional) both resolve to real `agents/*.md`, both + `subagent_type: linkedin-studio:`-namespaced. **Graceful degradation:** the "REQUIRED before scripting" + voice-samples dead-end closed → fresh-adopter fallback to SKILL.md/defaults. (mcp-image n/a — video + generates no images.) + +**HARDEN (surgical — 2 edits, 1 file, both grep-confirmed landed).** +- `commands/video.md:129` — **extended** the Step-5 De-AI caption gate with Content Quality Rule #4: + *"**Strip corporate buzzwords** from the post caption (… leverage, synergy, paradigm shift, thought + leader, disruptive, value proposition, ecosystem, holistic approach) — re-shaping a text idea into a + video caption can slip them in, and they trip the same low-substance signal."* +- `commands/video.md:42 + :45` — softened "(REQUIRED before scripting)" → "(read before scripting)" and + **added** a Step-0 graceful-degradation line: *"if `voice-samples/` is empty or absent, don't block — + fall back to the voice settings in SKILL.md (or neutral defaults) … the voice-guardian is suppressed + under 5 samples, so there is no hard gate to satisfy."* +- **Deferrals (2, recorded):** (1) hook 110–140 on the caption — deliberate class boundary, not a gap + (operator-agreed); (2) `:69` "zero distribution" honesty — inter-reference tension, brief Non-Goal (no + re-litigation of the algorithm bar); leave to a future reference-consistency pass if desired. +- **CONCRETE after:** the "leverage…synergy…ecosystem" caption now trips the Step-5 buzzword line before + the script is presented; a fresh adopter with no voice samples now degrades to SKILL.md/defaults instead + of hitting a "REQUIRED" dead-end. + +**VERIFY.** +- `bash scripts/test-runner.sh` → `Passed: 81 · Failed: 0 · Warnings: 0`, exit 0; counts **29/19/26/6** + unchanged (`ls commands/*.md|wc -l` == 29, `ls agents/*.md|wc -l` == 19; `git diff --stat` = + `video.md` only, +4/−2). 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; + axis (d) the voice-samples dead-end now degrades gracefully. The 2 edits are the cause. +- Disposition: **HARDENED** (2 edits, axis-c + axis-d) · 2 recorded deferrals (caption-hook boundary + + :69 honesty) · axes a/b PASS. + +---