fix(linkedin-studio): S14 harden import — drop baseline/metadata over-promise, prose now matches CLI

import.md repeatedly promised baseline comparison, rolling 4-week averages, and
baselines.json/metadata.json the importer "creates" — but no code anywhere writes
either file; detectAlerts flags intra-batch std-dev from the batch's own mean, not
a stored baseline. Step 5b's `cat baselines.json` was always empty, so the command
fell forever to "first import — baselines will be established" on every import.
Rewrote 5 sections (Step 5, 5b, 7, State Tracking, Reference Files) to the truth:
real CLI fields + YYYY-MM-DD-<shortid> filename, honest intra-batch surfacing,
cross-week analysis deferred to /linkedin:report. Verified with a grounded run
against a throwaway fixture.
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:56:47 +02:00
commit a413279c58
2 changed files with 102 additions and 83 deletions

View file

@ -1124,3 +1124,59 @@ functionally safe but mis-labelled "(Step 3b)". Root cause: conflating "the phas
- Disposition: **FIXED** (1 edit in `commands/calendar.md`) · 0 deferrals · axes a/b/c/d all PASS post-fix.
---
## Session 14 — Hardening (`import`)
> S14 status: read-and-show of the analytics CLI (`csv-parser.ts`, `cli.ts handleImport`,
> `storage.ts`, `alerts.ts`) BEFORE simulate, then a GROUNDED run against a throwaway fixture
> (`ANALYTICS_ROOT=/private/tmp/…`, 5-row CSV, discarded after). Class agreed steps 12:
> **analytics ingest** — CSV export → structured weekly JSON via `cli.ts import`, delegating all
> analysis to `/linkedin:report` (Step 6). **NOT post-emitting** → the feed-format predicates
> (hook 110140, length band, no-body-link, buzzwords, rotation) do NOT apply. Axis-a/d heavy
> (path-seam consistency + graceful degradation + the over-promise).
### /linkedin:import — CSV export → structured weekly JSON, intra-batch anomaly surface, analysis delegated to report
**WHAT VERIFIED CLEAN (no change).**
- Path-seam (axis-a): `getAnalyticsRoot()` (`storage.ts:6772`) → `getDataRoot("analytics")`
(`:5459`) = `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics` = the exact path
the prose tells the user to use (`import.md:37,62,91`); identical `LINKEDIN_STUDIO_DATA` override.
`ANALYTICS_ROOT` back-compat override (`storage.ts:68`) confirmed (validates the throwaway isolation).
- saves/dwell honesty (axis-c): grounded run → EU `"5.234"`→5234, US `"8,710"`→8710;
`parseOptionalCount` (`csv-parser.ts:7185`) kept saves 42/128 on data rows, **blank → no `saves`
field** (unknown, not 0); `engagementRate` excludes saves (`:203208`); **0 dwell field** anywhere.
README boundary blockquote (`import.md:2630`) intact.
- Wiring (axis-d): `/linkedin:report``commands/report.md` present; **0** `subagent_type`
(CLI-delegating, correct); state-file Step 6b = `~/.claude/linkedin-studio.local.md`.
- Degradation (axis-d): `npm install` pre-step (`:114121`) covers fresh-clone `ERR_MODULE_NOT_FOUND`;
file-not-found exit 1 (`cli.ts:6771`) ↔ Error Handling; empty title (file line 5) + bad date
(line 6) **skipped** in the run (`csv-parser.ts:186195`).
**THE FIX (1 finding, 5 surgical edits, all in `commands/import.md`).**
1. [REWORK · axis-a/d] **Over-promise: baseline / metadata infrastructure the code never had.**
import.md repeatedly promised baseline comparison + rolling 4-week averages + a `baselines.json` /
`metadata.json` the importer "creates" + ">2 sigma from baseline" alerts. Grep over the whole repo
(`scripts/analytics/src` + all `*.mjs/ts/py/js`) = **NONE writes either file**; `saveBatch` writes
only `posts/*.json` (`storage.ts:157`); `detectAlerts` (`alerts.ts:1869`) flags **intra-batch**
std-dev from the batch's own mean, not a stored baseline. Concrete bug: Step 5b's
`cat baselines.json 2>/dev/null` is always empty → the command falls forever to "first import —
baselines will be established", on every import. Fix: rewrote 5 sections to the truth — Step 5
(real CLI fields + `YYYY-MM-DD-<shortid>.json` filename; dropped "Duplicates skipped" / "340% above
baseline" / "Viral threshold"), Step 5b (honest intra-batch surfacing; cross-week analysis deferred
to `/linkedin:report`), Step 7 (Next-Steps conditioned on the report's trend, not a local baseline),
State Tracking + Reference Files (no `baselines.json` / `metadata.json`; correct batch filename).
**VERIFY.**
- Re-grepped the final file: `metadata.json` / `YYYY-WXX.json` (filename) / "Duplicates skipped" /
"340%" / "Viral threshold" all GONE; the only `YYYY-WXX` left is `:226` (`last_import_week` ISO-week
state field — legitimate); the 3 remaining "baseline" hits are the new honest negations ("keeps no
baseline file", "no persisted baseline").
- `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).
- Grounded simulation passes the failing axis: the rewritten prose matches the observed CLI output
verbatim (filename `2026-06-02-batch-17.json`, "No anomalies detected in imported data.",
"Saves entered: 170 across 2 post(s) (manual)").
- Disposition: **FIXED** (5 edits, all in `commands/import.md`) · 0 deferrals · axes a/b/c/d all PASS
post-fix.
---