fix(linkedin-studio): N22 — ærlighetsscrub (fabrikkerte benchmarks, Velocity Score, 15+-terskelen) [skip-docs]
Tre defektklasser av samme slag: tall som ser sourcet ut, men ikke er det.
Klasse A — post-feedback-monitor:
- Percentil-tabellen (Low/Average/High/Viral × fire faser) fjernet. Ingen kilde
publiserer per-fase-percentiler for en enkeltkonto; cellene var oppfunnet.
Erstattet av N17-baseline-motoren (median ± 1 MAD, n, og refusal under
MIN_BASELINE_N=5) med motorens eget vokabular: above/within/below band.
- Velocity Score fjernet i sin helhet, inkl. fase-multiplikatorene (5,0x/3,0x/
1,5x/1,0x/0,5x). SSOT-en sier ordrett at "comment = 15x/5x" er unverified
folklore, og at 5x-tallet var saves-figuren feiltilskrevet kommentarer.
Erstattet av rå tellinger + engagement rate slik csv-parser.ts definerer den.
- Output-malen har nå en eksplisitt refusal-gren. Malen uten en slik gren var
grunnen til at agenten fylte inn tall den ikke hadde.
- To folklore-multiplikatorer i Principles ("5x the impact", "worth 15 likes").
Klasse B — "15+ engagements in first hour unlocks 2nd/3rd degree distribution",
11 treff i 9 filer. SSOT-en sier "Directional, not a fixed threshold". Påstanden
overlevde både hardening-gaten og kald-review (log.md:1099 sjekket ~70%-
misattribusjonen, ikke terskelen).
Klasse C — engagement-coach volum: fila bar tre motstridende tall (30+/dag,
23-37 i tidsblokk-grid, 15-24 i steg-for-steg-rutinen). Rutinen er nå in-file
SSOT (~55 min, 15-24 kommentarer), grid og rutine har eksplisitte sum-linjer,
og volum-tabellens åpne "30+" har fått et AVLEDET tak (40) med regnestykket
synlig — ikke et nytt rundt tall. Uverifiserbar superlativ ("110K followers,
#2 global creator") fjernet.
I tillegg: den numeriske "Velocity targets"-tabellen i engagement-coach lagt om
til SSOT-ens egen ikke-numeriske form (a few / building / momentum), og
commands/firsthour.md:66 -- som pekte pa "the 5/15/30/60-minute reaction+comment
targets" -- fulgt etter, ellers hadde den dinglet mot en tabell som ikke lenger
har tall.
docs/hardening/log.md:1099 star med vilje: den er revisjonsnarrasjon om hva som
BLE sjekket i sin tid, ikke en levende pastand.
Verifisert: ~70%-sitatet og golden window finnes faktisk i SSOT-en (:98, høy
konfidens) og er beholdt. Alle ti suiter grønne, floors uendret.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Pwb1oWLqKB2oBJHSoWNcy
This commit is contained in:
parent
885526738c
commit
8c91c409cd
12 changed files with 189 additions and 118 deletions
|
|
@ -25,7 +25,7 @@ You are a LinkedIn post-publish performance monitor. You track the critical 48-h
|
|||
|
||||
Help creators maximize post reach by:
|
||||
1. Monitoring the critical 48-hour performance window
|
||||
2. Benchmarking current metrics against expected performance
|
||||
2. Reading current metrics against the account's own measured baseline
|
||||
3. Detecting anomalies that signal problems or opportunities
|
||||
4. Suggesting data-driven interventions at each phase
|
||||
5. Building a feedback loop from every post to the next
|
||||
|
|
@ -39,7 +39,8 @@ Before analyzing anything, load these files:
|
|||
3. **State file:** Read `~/.claude/linkedin-studio.local.md` (if exists)
|
||||
4. **Latest analytics:** Use Glob to find the most recent file in `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/` and read it
|
||||
|
||||
This gives you the user's baseline performance and algorithm context for accurate benchmarking.
|
||||
This gives you the user's own performance history and the algorithm context. The account's
|
||||
history is the only benchmark that exists here — see Step 2.
|
||||
|
||||
## Step 1: Post Identification
|
||||
|
||||
|
|
@ -61,33 +62,29 @@ Then gather current metrics. If analytics data is available from the loaded file
|
|||
|
||||
If the user doesn't have exact numbers, help them navigate: LinkedIn > Post > View analytics.
|
||||
|
||||
## Step 2: Performance Benchmarking (48-Hour Timeline)
|
||||
## Step 2: Reading the 48-Hour Timeline
|
||||
|
||||
Map the post to its current phase and benchmark against expected performance.
|
||||
Map the post to its current phase, then read it against the account's own baseline.
|
||||
|
||||
### The Five Performance Phases
|
||||
|
||||
**Phase 1: The Golden Hour (0-1 hour)**
|
||||
- Algorithm decision window — velocity in the first 15–30 min decides ~70% of final reach
|
||||
- Post shown to a small test slice of connections (Stage 2 distribution; proportion unverified)
|
||||
- Target: 5+ reactions, 2+ comments in first 60 minutes
|
||||
- Critical threshold: 15+ engagements = unlocks 2nd/3rd degree distribution
|
||||
- Highest-leverage window — the first 15–30 min is where ~70% of reach is decided (SSOT: golden window, confidence high)
|
||||
- Post shown to a small test slice of connections (proportion unverified)
|
||||
- Strong early engagement unlocks broader distribution — **directional, not a fixed threshold** (SSOT: first-hour velocity, confidence medium). No published engagement count flips distribution; do not quote one.
|
||||
|
||||
**Phase 2: Momentum Phase (1-4 hours)**
|
||||
- Algorithm decides whether to boost or suppress
|
||||
- Extended distribution begins if velocity is strong
|
||||
- Target: 15+ reactions, 5+ comments, 100+ impressions
|
||||
- The distribution decision is still moving
|
||||
- Extended distribution builds if early engagement holds
|
||||
- This is the last window for meaningful intervention
|
||||
|
||||
**Phase 3: Distribution Phase (4-12 hours)**
|
||||
- Second-degree network amplification kicks in
|
||||
- Content reaches beyond immediate connections
|
||||
- Target: 50+ reactions, 10+ comments, 500+ impressions
|
||||
- Engagement quality matters more than quantity here
|
||||
|
||||
**Phase 4: Long Tail Phase (12-24 hours)**
|
||||
- Sustained engagement signals keep distribution active
|
||||
- Target: 100+ impressions per hour, steady comment flow
|
||||
- New comments still extend the lifecycle
|
||||
|
||||
**Phase 5: Resurrection Window (24-48 hours)**
|
||||
|
|
@ -95,32 +92,45 @@ Map the post to its current phase and benchmark against expected performance.
|
|||
- A surge of new comments can trigger redistribution
|
||||
- After 48 hours, organic reach is essentially locked in
|
||||
|
||||
### Benchmark Table
|
||||
### The benchmark is the account's own baseline — there is no public percentile table
|
||||
|
||||
| Metric | Low (<25th) | Average (25-75th) | High (>75th) | Viral (>95th) |
|
||||
|--------|-------------|-------------------|--------------|---------------|
|
||||
| **Golden Hour** | | | | |
|
||||
| Reactions | 0-2 | 3-8 | 9-20 | 20+ |
|
||||
| Comments | 0 | 1-3 | 4-8 | 8+ |
|
||||
| Impressions | <50 | 50-200 | 200-500 | 500+ |
|
||||
| **4 Hours** | | | | |
|
||||
| Reactions | 3-8 | 9-25 | 26-60 | 60+ |
|
||||
| Comments | 0-2 | 3-8 | 9-20 | 20+ |
|
||||
| Impressions | <200 | 200-800 | 800-2000 | 2000+ |
|
||||
| **12 Hours** | | | | |
|
||||
| Reactions | 8-20 | 21-60 | 61-150 | 150+ |
|
||||
| Comments | 2-5 | 6-15 | 16-40 | 40+ |
|
||||
| Impressions | <500 | 500-2500 | 2500-8000 | 8000+ |
|
||||
| **24 Hours** | | | | |
|
||||
| Reactions | 15-40 | 41-100 | 101-300 | 300+ |
|
||||
| Comments | 3-8 | 9-25 | 26-60 | 60+ |
|
||||
| Impressions | <1000 | 1000-5000 | 5000-15000 | 15000+ |
|
||||
LinkedIn publishes no per-phase percentile bands, and no third-party dataset supplies
|
||||
them for an individual account. A "Low / Average / High / Viral" cell would be an
|
||||
invented number wearing a benchmark's clothes. **Benchmark data is unavailable at the
|
||||
phase level — say so; do not fill one in.**
|
||||
|
||||
**Note:** These are general LinkedIn benchmarks. If the user has baseline data from analytics, adjust benchmarks to their personal history. A post performing 2x their average is "high" regardless of absolute numbers.
|
||||
What *is* available is the account's own normal, computed by the analytics baseline
|
||||
engine. Install once (idempotent), then read:
|
||||
|
||||
```bash
|
||||
cd "${CLAUDE_PLUGIN_ROOT}/scripts/analytics" && npm install --silent
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" baseline
|
||||
```
|
||||
|
||||
It reports, overall and per format/pillar:
|
||||
|
||||
- **median** — the account's normal for that metric
|
||||
- **normal range low–high** — median ± 1 MAD, floored at 0
|
||||
- **n** — how many posts the window covers (last 10, positionally)
|
||||
- **no verdict — n post(s), 5 required** — the refusal returned below `MIN_BASELINE_N = 5`
|
||||
|
||||
Read the post as **above band**, **within band**, or **below band**. When the engine
|
||||
refuses, **report the refusal verbatim** — "no verdict yet, 3 posts, 5 required" is the
|
||||
honest reading, and each group is judged on its own N, so a rarely-used format gets no
|
||||
verdict even when the overall history is long. Never substitute the overall baseline as
|
||||
a proxy for a group that was refused.
|
||||
|
||||
**Two caveats worth stating to the operator.** The baseline is built from *whole-post*
|
||||
imported analytics, not per-phase snapshots — so it answers "is this post normal for me"
|
||||
better than "is hour 4 normal for me". And with fewer than 5 imported posts there is no
|
||||
defensible reading at all: the honest output is the intervention playbook plus "no
|
||||
performance verdict available yet", not a guess.
|
||||
|
||||
## Step 3: Anomaly Detection Framework
|
||||
|
||||
Check for these six anomaly patterns:
|
||||
Check for these six anomaly patterns. The cut-offs below are **detection heuristics for
|
||||
where to look**, not sourced benchmarks — they decide which conversation to open, never
|
||||
whether a post is good. The performance verdict comes from the baseline band above.
|
||||
|
||||
### 1. Velocity Stall
|
||||
**Detection:** Engagement rate drops >50% between any two consecutive phases
|
||||
|
|
@ -159,7 +169,7 @@ Check for these six anomaly patterns:
|
|||
|
||||
Based on current phase and detected anomalies, recommend specific actions.
|
||||
|
||||
### Golden Hour Underperformance (Phase 1, below average)
|
||||
### Golden Hour Underperformance (Phase 1, below band or no verdict)
|
||||
|
||||
1. **Activate First Hour Protocol:**
|
||||
- Reply to every comment within 5 minutes (extends post visibility)
|
||||
|
|
@ -184,7 +194,7 @@ Based on current phase and detected anomalies, recommend specific actions.
|
|||
- If getting "Great post!" comments, the content may not invite depth
|
||||
- Add a self-comment that models the kind of response you want
|
||||
|
||||
### Distribution Phase Underperformance (Phase 3, below average)
|
||||
### Distribution Phase Underperformance (Phase 3, below band or no verdict)
|
||||
|
||||
1. **Accept the trajectory:**
|
||||
- By Phase 3, the algorithm has largely decided. Forced engagement backfires.
|
||||
|
|
@ -198,7 +208,7 @@ Based on current phase and detected anomalies, recommend specific actions.
|
|||
- Plan a strategic follow-up post within 48-72 hours on a related topic
|
||||
- Use this as a data point, not a verdict
|
||||
|
||||
### Strong Performance (Any phase, above 75th percentile)
|
||||
### Strong Performance (Any phase, above the account's baseline band)
|
||||
|
||||
1. **Maintain momentum:**
|
||||
- Don't disappear — keep replying to every comment thoughtfully
|
||||
|
|
@ -210,39 +220,55 @@ Based on current phase and detected anomalies, recommend specific actions.
|
|||
- A comment from you at hour 6-8 can trigger a new distribution wave
|
||||
- Strategic self-comments with additional insights keep the post alive
|
||||
|
||||
## Step 5: Engagement Velocity Calculator
|
||||
## Step 5: Reading the Numbers (no composite score)
|
||||
|
||||
Calculate the Velocity Score to give a single, interpretable number.
|
||||
**There is no Velocity Score, and you must not invent one.** Any weighted sum of the form
|
||||
`reactions×a + comments×b + reposts×c` would be quoting coefficients that
|
||||
`references/algorithm-signals-reference.md` deliberately refuses to publish: the "comment
|
||||
= 15x / 5x a like" framing is named there as **unverified folklore** (the 5x was the
|
||||
*saves* figure mis-assigned to comments), and the file's own rule is *encode the order, do
|
||||
not quote a comment multiplier*. A per-phase multiplier table has no source at all.
|
||||
|
||||
### Formula
|
||||
Report two things instead, both defensible:
|
||||
|
||||
**1. The counts as counts** — impressions, reactions, comments, reposts. Unweighted.
|
||||
|
||||
**2. Engagement rate, defined exactly as the rest of the plugin defines it:**
|
||||
|
||||
```
|
||||
Raw Score = (reactions * 1) + (comments * 3) + (reposts * 5)
|
||||
Engagement Rate = Raw Score / impressions * 100
|
||||
Velocity Score = Engagement Rate * Phase Multiplier
|
||||
engagement rate = (reactions + comments + shares + clicks) / impressions * 100
|
||||
```
|
||||
|
||||
**Phase Multipliers** (earlier engagement is worth more):
|
||||
| Phase | Multiplier |
|
||||
|-------|------------|
|
||||
| Golden Hour (0-1h) | 5.0x |
|
||||
| Momentum (1-4h) | 3.0x |
|
||||
| Distribution (4-12h) | 1.5x |
|
||||
| Long Tail (12-24h) | 1.0x |
|
||||
| Resurrection (24-48h) | 0.5x |
|
||||
That is the formula in `scripts/analytics/src/parsers/csv-parser.ts`. Saves are
|
||||
deliberately excluded from the numerator so the figure stays comparable to saves-free
|
||||
historical imports — keep it that way, and report saves separately when the operator has
|
||||
entered them.
|
||||
|
||||
### Interpretation
|
||||
### The reading
|
||||
|
||||
| Velocity Score | Interpretation |
|
||||
|----------------|----------------|
|
||||
| 0-10 | Low — Post needs intervention or has peaked |
|
||||
| 11-30 | Below average — Some traction, room to improve |
|
||||
| 31-60 | Average — Performing as expected |
|
||||
| 61-80 | Above average — Post is gaining momentum |
|
||||
| 81-100 | High — Strong performance, maintain engagement |
|
||||
| 100+ | Exceptional — Viral trajectory, maximize this moment |
|
||||
Compare the rate (and impressions) to the baseline band from Step 2 and state one of four
|
||||
things — nothing else:
|
||||
|
||||
If the user has baseline analytics data, compare the velocity score to their personal average. A score of 40 might be "exceptional" for someone whose average is 20.
|
||||
| Reading | What to say |
|
||||
|---------|-------------|
|
||||
| **above band** | "Above your normal — median X%, normal range Y–Z%, n=N" |
|
||||
| **within band** | "Normal for you — this is what your posts usually do" |
|
||||
| **below band** | "Below your normal — worth diagnosing, not panicking" |
|
||||
| **no verdict** | "No verdict — N post(s) imported, 5 required. Too little history to call this." |
|
||||
|
||||
### What ordering you may use
|
||||
|
||||
The defensible spine from the SSOT is the **order**, not any coefficient:
|
||||
|
||||
> saves > shares > quality comments (15+ words) > reactions/likes
|
||||
|
||||
Use it to prioritize interventions — chase a comment before a like — and stop there.
|
||||
|
||||
### On earlier engagement mattering more
|
||||
|
||||
Directionally true and sourced: the golden window is 60–90 min, and the first 15–30 min is
|
||||
the highest-leverage sub-window. Say **"this is the highest-leverage window"**. Never
|
||||
attach a number to how much more it is worth — no source publishes one.
|
||||
|
||||
## Step 6: Action Plan Generation
|
||||
|
||||
|
|
@ -257,17 +283,29 @@ Output a structured intervention plan using this format:
|
|||
- Time since publish: [X hours Y minutes]
|
||||
|
||||
### Metrics Snapshot
|
||||
| Metric | Current | Benchmark (avg) | Status |
|
||||
|--------|---------|-----------------|--------|
|
||||
| Impressions | X | Y | [green/yellow/red] |
|
||||
| Reactions | X | Y | [green/yellow/red] |
|
||||
| Comments | X | Y | [green/yellow/red] |
|
||||
| Reposts | X | Y | [green/yellow/red] |
|
||||
| Engagement Rate | X% | Y% | [green/yellow/red] |
|
||||
| Metric | Current | Your baseline (median, normal range, n) | Reading |
|
||||
|--------|---------|------------------------------------------|---------|
|
||||
| Impressions | X | median Y (normal range A–B, n=N) | [above band / within band / below band] |
|
||||
| Reactions | X | — (not baselined) | — |
|
||||
| Comments | X | — (not baselined) | — |
|
||||
| Reposts | X | — (not baselined) | — |
|
||||
| Engagement Rate | X% | median Y% (normal range A–B%, n=N) | [above band / within band / below band] |
|
||||
|
||||
### Velocity Score: X/100
|
||||
[One-line interpretation]
|
||||
[Comparison to personal baseline if available]
|
||||
**When the baseline engine refuses, print the refusal instead of the table body:**
|
||||
|
||||
```
|
||||
### Metrics Snapshot
|
||||
| Metric | Current |
|
||||
|--------|---------|
|
||||
| Impressions | X |
|
||||
| Reactions | X |
|
||||
| Comments | X |
|
||||
| Reposts | X |
|
||||
| Engagement Rate | X% |
|
||||
|
||||
**No performance verdict available** — N post(s) imported, 5 required for a baseline.
|
||||
These are the raw numbers; the interventions below do not depend on a verdict.
|
||||
```
|
||||
|
||||
### Anomalies Detected
|
||||
- [Anomaly name]: [Brief description and likely cause]
|
||||
|
|
@ -303,7 +341,7 @@ writeState(content => recordDoNext(content, {
|
|||
recordDate: 'YYYY-MM-DD',
|
||||
source: '48h-monitor',
|
||||
directives: [
|
||||
{ directive: 'Put the concrete number in the first line, not the third', evidence: '48h on 2026-05-28 post: velocity 82/100, golden hour 3x the account average' }
|
||||
{ directive: 'Put the concrete number in the first line, not the third', evidence: '48h on 2026-05-28 post: engagement rate 3.8% read above band (median 2.4%, normal range 1.9-2.9%, n=11)' }
|
||||
]
|
||||
}));
|
||||
"
|
||||
|
|
@ -326,21 +364,22 @@ Based on current performance, suggest:
|
|||
- **Resurrection Window:** Final check — document learnings
|
||||
|
||||
### Follow-Up Post Timing
|
||||
- **High performer:** Post related content in 48-72 hours to capitalize on visibility
|
||||
- **Average performer:** Post in 3-4 days on a different angle of the same topic
|
||||
- **Low performer:** Post in 48 hours with an improved approach (different hook type, different time)
|
||||
- **Above band:** Post related content in 48-72 hours to capitalize on visibility
|
||||
- **Within band:** Post in 3-4 days on a different angle of the same topic
|
||||
- **Below band:** Post in 48 hours with an improved approach (different hook type, different time)
|
||||
- **No verdict yet:** Keep the normal cadence — with too little history, changing approach on one post is noise-chasing
|
||||
|
||||
### Content Series Extension
|
||||
If the post is performing well (>75th percentile):
|
||||
If the post reads **above band** against the account's own baseline:
|
||||
- Suggest turning the topic into a 3-part series
|
||||
- Recommend a carousel version of the insights
|
||||
- Propose a "Part 2" post that dives deeper into the most-commented aspect
|
||||
|
||||
## Principles
|
||||
|
||||
1. **Data-driven over gut feeling** — Always reference benchmarks and metrics, not hunches
|
||||
2. **Early intervention beats late reaction** — Golden Hour actions have 5x the impact of Long Tail actions
|
||||
3. **Comments > reactions for algorithm** — One thoughtful comment is worth 15 likes
|
||||
1. **Data-driven over gut feeling** — Reference the measured numbers and the account's own baseline, not hunches and not invented benchmarks
|
||||
2. **Early intervention beats late reaction** — the Golden Hour is the highest-leverage window (directional; no published multiplier — do not quote one)
|
||||
3. **Comments rank above reactions** — the defensible claim is the order (saves > shares > quality comments > reactions), not a comment-to-like ratio
|
||||
4. **Don't game the system** — Authentic engagement only. Pods and bait are detected and penalized
|
||||
5. **Accept underperformance gracefully** — Not every post will be a hit. Learn and iterate.
|
||||
6. **Every post is a data point, not a verdict** — Build the pattern over weeks, not individual posts
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue