feat(linkedin-studio): N17 — baseline-motor (median + variansbånd + minimum-N-refusal) [skip-docs]
Every reading now leads with "vs your own baseline", and no verdict is given when N is too small to carry one. - stats.ts: median + medianAbsoluteDeviation (robust pair; mean/stddev stay for the alert engine, which wants outlier sensitivity), rollingBaseline with a 10-post positional window, median ± 1·MAD band floored at 0, and a typed insufficient-data refusal below MIN_BASELINE_N=5. readAgainstBaseline returns above/within/below-band, or no-verdict when the baseline was refused. - baselineByGroup + buildBaselineBlock: per-format/per-pillar baselines, each judged on its own N; the reported period is excluded from its own baseline and compared on its median, not its mean. - queue-join.ts (new): read-only date join supplying format/pillar from the post queue. Every ambiguity resolves to unlabelled, an entry labels at most one post, and a missing/broken queue degrades to no labels. - weekly/monthly reports attach the block unconditionally (refusal included); optional in the types, so pre-N17 reports load unchanged. - CLI: report output leads with the baseline; new `baseline [--by format|pillar]` verb with coverage reporting. - report.md leads with baseline framing and prints the code's reading rather than judging the band by eye; WoW loses to the baseline on disagreement. analyze.md Step 2a tests whether the drop is real before diagnosing it. TDD: 58 analytics tests written red first (144 -> 202). test-runner Section 16x, 23 unconditional checks + self-test (247 -> 270; anti-erosion floor 228 -> 251). tsc clean. All suites green: trends 300, brain 134, editions 72, specifics-bank 45, contract-gate 33, hooks 191, tests 35, render 60. Also closes the OKF phase-4 scope follow-up in docs/okf-ingestion/plan.md §8 (coord round 2026-07-25): phase 4 tracks the contract, parse is in scope, and our claim on read_concept/navigate_bundle is withdrawn as unnecessary. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QxvWAjte7vPcF79QeSRvRJ
This commit is contained in:
parent
63506f7d5c
commit
e2ad190dda
15 changed files with 1723 additions and 14 deletions
|
|
@ -38,7 +38,34 @@ Use AskUserQuestion to understand the situation:
|
|||
|
||||
## Step 2: Gather Data
|
||||
|
||||
If imported analytics data exists (`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/`), delegate audience-pattern discovery to the `analytics-interpreter` agent (interpret mode) — invoke it via `Task` with `subagent_type: linkedin-studio:analytics-interpreter` (foreground, from this command layer) — to ground the diagnosis in what the data actually shows before relying on self-report.
|
||||
**Step 2a — first, establish whether there is a problem at all.** This command is
|
||||
invoked because something *feels* wrong, and the operator's own framing ("my reach
|
||||
dropped") is a hypothesis, not a measurement. Diagnosing a drop that never happened
|
||||
sends them chasing a phantom and teaches them to distrust their own numbers.
|
||||
|
||||
If imported analytics exist, generate the current report and read its `baseline`
|
||||
block (see `/linkedin:report` Step 4):
|
||||
|
||||
```bash
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report
|
||||
```
|
||||
|
||||
Read `baseline.period.<metric>.reading` and lead the diagnosis with it:
|
||||
|
||||
- **`within-band`** — the numbers are inside the operator's own normal range. Say so
|
||||
before going further: *"Your last posts are inside your normal range (median X,
|
||||
normal range Y–Z). This looks like ordinary variation rather than a drop."* Then ask
|
||||
whether they still want the diagnostic pass. Often the honest answer is that nothing
|
||||
is wrong and the fix is to keep publishing — do not manufacture a diagnosis to
|
||||
justify the command having been run.
|
||||
- **`below-band`** — the drop is real and measured. Proceed, and use the band figures
|
||||
as the size of the problem instead of a remembered percentage.
|
||||
- **`no-verdict`** — print `baseline.<metric>.reason` and say plainly that there is not
|
||||
enough history to tell a drop from variation. Continue on **self-report only**, and
|
||||
label the diagnosis as provisional. Never upgrade a refusal into a verdict because
|
||||
the operator sounds worried.
|
||||
|
||||
If imported analytics exist (`${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/`), delegate audience-pattern discovery to the `analytics-interpreter` agent (interpret mode) — invoke it via `Task` with `subagent_type: linkedin-studio:analytics-interpreter` (foreground, from this command layer) — to ground the diagnosis in what the data actually shows before relying on self-report.
|
||||
|
||||
Based on their answer, ask relevant follow-up questions:
|
||||
|
||||
|
|
@ -150,7 +177,11 @@ Run through this checklist:
|
|||
|
||||
## Step 5: Reach Drop Severity Assessment
|
||||
|
||||
Based on how much reach dropped:
|
||||
Based on how much reach dropped. **Measure the drop against the baseline band from
|
||||
Step 2a, not against the single best week the operator remembers** — a percentage
|
||||
computed from a remembered peak is a comparison with an outlier, and it will class
|
||||
ordinary variation as suppression. When the band says `within-band`, the severity is
|
||||
"normal fluctuation" regardless of what the percentage says.
|
||||
|
||||
### Down <25%
|
||||
**Diagnosis:** Normal fluctuation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue