fix(linkedin-studio): S15 harden report — drop baselines/metadata phantom, fix engagement_rate flag + JSON schema fields

S15 report through the v2 interactive quality gate (analytics class). 3 findings,
6 surgical edits in commands/report.md, all grep-confirmed + grounded against a
throwaway-root CLI run:

- FUNN 1 (S14 twin): Step 5c baseline/std-dev mechanism + Reference Files referenced
  baselines.json/metadata.json that no code writes (storage.ts writes only
  posts/weekly-reports/monthly-reports). Rewrote Step 5c to read the report's own
  alerts[] (detectAlerts + detectWeeklyAlerts); fixed posts filename to
  YYYY-MM-DD-<shortid>.json; added real monthly-reports file.
- FUNN 2: trends --metric engagement_rate (snake_case) → exit 1 'Invalid metric';
  CLI accepts only engagementRate (cli.ts:47,202-209). Fixed report.md:172.
- FUNN 3: Step 4/Step 6 claimed JSON fields dateRange/postCount/aggregateMetrics that
  don't exist; real schema is summary/topPerformers/underperformers/trends/alerts.
  Rewrote to real fields; fixed Deep-Dive post-search path.

Gate: test-runner 81/0/0 exit 0; counts 29/19 unchanged (.md-only).

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-19 06:18:44 +02:00
commit 060ce8a371
2 changed files with 82 additions and 21 deletions

View file

@ -139,12 +139,11 @@ cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-repo
The report contains:
- **week**: ISO week identifier
- **dateRange**: Start and end dates
- **postCount**: Number of posts published
- **aggregateMetrics**: Totals and averages across all metrics
- **topPerformers**: Best posts by each metric
- **alerts**: Anomalies and significant events
- **trends**: Week-over-week changes
- **generatedAt**: ISO timestamp when the report was generated
- **summary**: Totals and averages — `totalPosts`, `totalImpressions`, `totalReactions`, `totalComments`, `totalShares`, `totalClicks`, optional `totalSaves` (manual entry only), `avgEngagementRate`, `avgImpressionsPerPost`
- **topPerformers** / **underperformers**: Best / weakest posts by engagement rate
- **trends**: Week-over-week change — `impressionsTrend`, `engagementTrend`, `comparedTo`, `percentChange`
- **alerts**: Anomalies and significant events (intra-week + week-over-week)
## Step 5: Run Trend Analysis
@ -169,7 +168,7 @@ After the initial trend data, automatically run trend analysis for the key metri
trends --period month --metric impressions
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" \
trends --period month --metric engagement_rate
trends --period month --metric engagementRate
```
**Present trend summary as a 4-week comparison table:**
@ -218,15 +217,19 @@ Automatically flag these conditions based on the report data and trend analysis:
- 🟡 Hook length violation: Posts with hooks >140 chars underperforming (>140 chars truncated on mobile "see more")
- 🟢 Engagement velocity improving: First-hour engagement trending up (15+ engagements in first hour unlocks 2nd/3rd degree distribution)
**Detect alerts by comparing current week data against baselines:**
**Surface the alerts the report already computed.** The weekly-report JSON's `alerts[]`
is generated by the CLI itself — intra-week anomaly detection across the week's posts
(`detectAlerts`) plus a week-over-week comparison (`detectWeeklyAlerts`) that fires once
the previous week's report exists. There is no separate baselines file to consult; read
`alerts[]` straight from the report you generated in Step 3:
```bash
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json 2>/dev/null
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/<YYYY-WXX>.json 2>/dev/null \
| python3 -c "import json,sys; [print(a['severity'].upper(), '—', a['message']) for a in json.load(sys.stdin).get('alerts', [])]"
```
Compare current week's `aggregateMetrics` against baseline means and standard deviations. Flag any metric that is:
- >2 standard deviations above mean → 🟢 Positive alert
- >2 standard deviations below mean → 🔴 Critical alert
- Between 1-2 standard deviations below → 🟡 Warning alert
Each alert carries a `severity` (`critical` / `warning` / `info`); map it to an icon
(🔴 / 🟡 / 🟢) and pair it with an action below. Week-over-week alerts appear only after a
prior week's report has been generated.
**Present alerts as:**
```
@ -253,7 +256,7 @@ Format the data into a readable report using this template:
```
# LinkedIn Performance Report
## Week {week} ({dateRange})
## Week {week}
### 📊 Key Metrics
@ -265,8 +268,8 @@ Format the data into a readable report using this template:
| Shares | {total} | {avg} | {trend} |
| Engagement Rate | - | {rate}% | {trend} |
**Posts published:** {postCount}
**Engagement rate:** {totalEngagements / totalImpressions * 100}%
**Posts published:** {summary.totalPosts}
**Engagement rate:** {summary.avgEngagementRate}%
### 🏆 Top Performers
@ -372,7 +375,9 @@ If user wants to analyze specific posts:
Read the weekly post data directly:
```bash
cat ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/<YYYY-WXX>.json | jq '.posts[] | select(.title | contains("search term"))'
for f in ${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/*.json; do
jq '.posts[] | select(.title | contains("search term"))' "$f"
done
```
Show detailed metrics for that post and suggest what made it perform well/poorly.
@ -406,10 +411,9 @@ Read `~/.claude/linkedin-studio.local.md` and suggest:
## Reference Files
Reports use data from:
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/YYYY-WXX.json` - Raw weekly post data
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX.json` - Computed report
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/baselines.json` - Statistical baselines for comparison
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/metadata.json` - Import history and tracking
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/posts/YYYY-MM-DD-<shortid>.json` - Raw imported batches (one file per import; rows live under `.posts[]`)
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/weekly-reports/YYYY-WXX.json` - Computed weekly report
- `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/analytics/monthly-reports/YYYY-MM.json` - Computed monthly report
## Step 8b: Export Options