fix(linkedin-studio): S13 harden calendar — concrete Reschedule snippet + correct camelCase exports

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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qgzo6rxthw7KuxHjn5vyE
This commit is contained in:
Kjell Tore Guttormsen 2026-06-18 20:19:31 +02:00
commit 270e99d002
2 changed files with 59 additions and 3 deletions

View file

@ -165,9 +165,15 @@ First Hour:
If they choose to reschedule: If they choose to reschedule:
1. Ask which post (by number or hook preview) 1. Ask which post (by number or hook preview)
2. Ask for new date and time 2. Ask for the new date and time
3. Update queue.json via queue_update_status + queue_add with new date 3. Re-add the entry with the **same id** and new date/time — `queueAdd` replaces any
4. Show updated calendar 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 ### Action: Cancel

View file

@ -1074,3 +1074,53 @@ functionally safe but mis-labelled "(Step 3b)". Root cause: conflating "the phas
post-fix. 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 12: **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 110140,
> 1,2001,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:41112` 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:1227`); the "No posts scheduled" branch (`:106111`) 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 6090 min / first 1530 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 (`:164170`) was under-determined vs its sibling actions:
prose-only with NO bash snippet (unlike Cancel `:177180` and publish 3c `:116118`), 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 1530 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.
---