From 270e99d0021dda59bf715c3d3c399d3d535e7137 Mon Sep 17 00:00:00 2001 From: Kjell Tore Guttormsen Date: Thu, 18 Jun 2026 20:19:31 +0200 Subject: [PATCH] =?UTF-8?q?fix(linkedin-studio):=20S13=20harden=20calendar?= =?UTF-8?q?=20=E2=80=94=20concrete=20Reschedule=20snippet=20+=20correct=20?= =?UTF-8?q?camelCase=20exports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reschedule action was under-determined vs its sibling actions: prose-only with no bash snippet, referencing snake_case queue_update_status/queue_add that don't match the exports (queueUpdateStatus/queueAdd). Replaced with a concrete queueAdd one-liner using the same id (re-add moves the post in place, no duplicate). Axes a/b/c/d all PASS post-fix; lint 81/0/0, counts 29/19 unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_016qgzo6rxthw7KuxHjn5vyE --- commands/calendar.md | 12 ++++++++--- docs/hardening/log.md | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/commands/calendar.md b/commands/calendar.md index 9cad07d..3ca7a94 100644 --- a/commands/calendar.md +++ b/commands/calendar.md @@ -165,9 +165,15 @@ First Hour: If they choose to reschedule: 1. Ask which post (by number or hook preview) -2. Ask for new date and time -3. Update queue.json via queue_update_status + queue_add with new date -4. Show updated calendar +2. Ask for the new date and time +3. Re-add the entry with the **same id** and new date/time — `queueAdd` replaces any + existing entry with that id, so the post moves in place (no duplicate). Carry the + unchanged fields (draft_path, pillar, format, hook preview, char count) from the + entry shown in Step 2: +```bash +node --input-type=module -e "import { queueAdd } from '${CLAUDE_PLUGIN_ROOT}/hooks/scripts/queue-manager.mjs'; console.log(queueAdd('[post-id]', '[draft_path]', '[new-YYYY-MM-DD]', '[new-HH:MM]', '[pillar]', '[format]', '[hook preview]', [charCount]));" +``` +4. Show the updated calendar ### Action: Cancel diff --git a/docs/hardening/log.md b/docs/hardening/log.md index 9c4d334..6d74c78 100644 --- a/docs/hardening/log.md +++ b/docs/hardening/log.md @@ -1074,3 +1074,53 @@ functionally safe but mis-labelled "(Step 3b)". Root cause: conflating "the phas post-fix. --- + +## Session 13 — Hardening (`calendar`) + +> S13 status: read-and-show of every mechanical dependency against the actual `queue-manager.mjs` + +> `state-updater.mjs` BEFORE talk. Class agreed steps 1–2: **stateful queue / publish command** — +> view + manage the scheduling queue + run the publish action. **NOT post-emitting / feed-draft.** +> It loads the queue (`queueToday/Upcoming/Overdue/Count/FormatSummary`), renders a 14-day view, +> offers actions (mark-published / reschedule / cancel / view-draft), and on publish does +> `queueUpdateStatus('published')` → `updatePostTracking` (state) → a quick first-hour plan that +> defers the full sprint to `/linkedin:firsthour` + `post-feedback-monitor`. It DISPLAYS hook previews +> of already-queued drafts → it emits no feed content → the feed-format predicates (hook 110–140, +> 1,200–1,800 band, no-body-link, buzzwords, rotation) do NOT apply. Axis-a/d heavy. + +**WHAT VERIFIED CLEAN (no change).** +- Queue wiring (axis-a/d): Step 1 (`queueToday/Upcoming/Overdue/Count/FormatSummary`), 3c + Cancel + (`queueUpdateStatus`) all match exports in `queue-manager.mjs:41–112` exactly. +- State-writer (axis-d): `updatePostTracking(stateContent, { postDate, postTopic, hookText, charCount, + format })` (`state-updater.mjs:55`) + `writeState` (`:346`) — signature matches Step 3d's call verbatim. +- Agent wiring (axis-d): `subagent_type: linkedin-studio:post-feedback-monitor` (`:156`) namespaced, + agent file present, `Task` in `allowed-tools`. Hand-off to `/linkedin:firsthour` (`:138`) = S12 chain. +- Graceful degradation (axis-d): missing/corrupt queue → `ensureQueue()` + `readQueue()` try/catch → `[]` + (`queue-manager.mjs:12–27`); the "No posts scheduled" branch (`:106–111`) covers the empty case. +- Algorithm bar (axis-b): the quick first-hour plan (`:151` "15+ engagements in first 60 min", check at + 30/60) is deliberately light and delegates the full sprint to `/linkedin:firsthour`. No ~70%-reach + misattribution (the S12 bug is absent here). SSOT `:81` golden window 60–90 min / first 15–30 min — not + contradicted. PASS. +- Content-quality (axis-c): emits no feed content; the hook "preview" is a truncated display of an + existing draft, not a generated hook → feed predicates N/A → PASS. + +**THE FIX (1 finding, 1 surgical edit, confined to the Reschedule action).** +1. [REWORK · axis-a/d] The **Reschedule** action (`:164–170`) was under-determined vs its sibling actions: + prose-only with NO bash snippet (unlike Cancel `:177–180` and publish 3c `:116–118`), and it referenced + `queue_update_status + queue_add` — **snake_case that does not match the exports** `queueUpdateStatus` / + `queueAdd` (`queue-manager.mjs:63,82`). An agent executing it had no concrete command and the names + would not resolve if copied literally. Fix: replaced step 3 with a concrete `queueAdd` one-liner using + the **same id** (since `queueAdd` filters out the prior id first, `:64`, re-adding moves the post in + place — no duplicate), carrying the unchanged fields from the Step-2 entry. Mirrors the Cancel snippet + pattern. + +**VERIFY.** +- Re-grepped the final file: no `queue_update_status` / `queue_add` remains; the `queueAdd` reschedule + snippet is at `:174`; every `queue*` reference in the file is now camelCase and matches an export. +- `bash scripts/test-runner.sh` → `Passed: 81 · Failed: 0 · Warnings: 0`, **exit 0**; counts **29/19** + unchanged (.md-only edit, node/analytics tests not triggered — unchanged from S12). +- **One NICE left (anti-gold-plating):** the quick first-hour plan could name the SSOT "first 15–30 min" + sub-window, but it deliberately defers to `/linkedin:firsthour`; duplicating it would be scope creep — + left. +- Disposition: **FIXED** (1 edit in `commands/calendar.md`) · 0 deferrals · axes a/b/c/d all PASS post-fix. + +---