feat(linkedin-studio): S16 — optional manual saves in analytics + close deferred onboarding Write MAJOR

Lifts the original v4.0.0 Non-Goal: an optional, manually-entered `saves`
metric through the analytics layer, built location-agnostic (option c) so
UI-brief §9b/M0 relocates the data dir in one place later.

- types: PostMetrics.saves? + Weekly/Monthly summary.totalSaves? (optional);
  new RankableMetric type for the always-numeric index-access whitelist
- parser: dedicated parseOptionalCount() — blank/non-numeric/negative -> undefined
  ("unknown != 0"), genuine 0 kept; saves NOT folded into engagementRate
- reports: totalSaves set only when >=1 post carries saves (backward-compat)
- cli: saves surfaced in import summary + weekly/monthly totals + per-post
- S16-pre: onboarding.md allowed-tools gains Write (closes S15-deferred MAJOR)
- docs (three-doc rule): plugin README boundary + analytics README + root README
  + plugin CLAUDE.md + CHANGELOG; dwell stays explicitly unmeasurable

Independent /trekreview: brief-conformance 0 findings; code-correctness 2 MAJOR
(own lockstep misses) FIXED in-session (parseOptionalCount + edge tests). Gate:
tsc clean, analytics 116/116, lint 74/0/0, hooks 98/98. Within-v4.1.0 refinement
(no surface/count/version change).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-30 22:23:12 +02:00
commit 55c94ee964
18 changed files with 417 additions and 118 deletions

View file

@ -9,6 +9,25 @@ This directory contains imported analytics data from LinkedIn CSV exports.
3. Save the CSV file to `exports/` directory
4. Run `/linkedin:import` in Claude Code
### Optional: add per-post saves (manual)
LinkedIn's CSV export does **not** include saves, and there is no self-serve API
to pull them — but the per-post save **count** is visible in your native post
analytics (since ~Sept 2025). To track it, add a `Saves` column to the CSV and
type the count you read off LinkedIn. The importer picks it up automatically when
the column is present:
```
"Content","Date","Impressions","Reactions","Comments","Shares","Clicks","Saves"
"My post...",2026-02-10,5000,100,30,15,200,42
```
A missing column — or a blank `Saves` cell — leaves saves **unknown** (never
counted as 0), and saves is **not** folded into the engagement rate (which stays
comparable to older imports). Saves is the strongest organic engagement signal,
so the reports surface it as its own line. **Dwell time stays unmeasurable**
it is internal to LinkedIn for organic posts, with no count to transcribe.
## Directory Structure
```
@ -50,6 +69,10 @@ Each file contains a batch of imported posts:
}
```
`metrics.saves` is **optional** — present only on posts where you supplied a
`Saves` column value (see "Optional: add per-post saves" above). Posts without
it omit the field entirely, so older imports round-trip unchanged.
### Weekly Reports (weekly-reports/*.json)
Generated via `/linkedin:report`. Contains: