fix(linkedin-studio): anchor analytics root on plugin marker + surface npm install

Wave 2 / Step 4 of the remediation plan (docs/remediation/plan.md).

PRIMARY (the real fresh-clone failure):
- scripts/analytics/node_modules is gitignored, so a fresh clone has neither
  tsx nor csv-parse. Surface an idempotent `npm install --silent` prerequisite
  at point-of-use in report.md (Step 1b) and import.md (Step 4).

DEVIATION FROM PLAN (correction-in-scope, to satisfy the plan's own Verify gate):
- The plan assumed prepending `npm install` was sufficient. Verified it is NOT:
  the commands invoke the CLI with an absolute src/cli.ts path but from the
  user's arbitrary CWD, and `node --import tsx` resolves the `tsx` specifier
  relative to CWD, not the script. There is no global tsx, so the call still
  fails with ERR_MODULE_NOT_FOUND from any CWD other than scripts/analytics.
- Complete fix: invoke the locally-installed tsx by its absolute
  node_modules/.bin/tsx path in all CLI calls (report.md x10, import.md x3), so
  they resolve from any working directory once the install above has run.
  Verified: 0 ERR_MODULE_NOT_FOUND running `report` from /tmp.

SECONDARY (latent correctness / hardening):
- Add findPluginRoot(): walks up to the dir holding .claude-plugin/plugin.json
  and anchors getAnalyticsRoot() on it, falling back to the legacy 4-up count.
  MEASURED that ../../../../ already resolved to the plugin root from BOTH
  src/utils and build/utils (both 4 levels deep), so the plan's "src-vs-build
  depth miscalibration" premise was false — this is correct-by-construction
  hardening (survives a future source move), not a live-bug fix.
- Reconcile cli.ts usage/help text: `node build/cli.js` -> `node --import tsx
  src/cli.ts` (the real runtime).
- Fix report.md troubleshooting: "Verify tsx is available" -> the actual
  install command on ERR_MODULE_NOT_FOUND.

Test-first: scripts/analytics/tests/storage-root.test.ts (red on missing
findPluginRoot export, green after). Full suite 106/106, tsc --noEmit clean,
structural lint 0 failed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-29 21:18:33 +02:00
commit 798484bf0c
5 changed files with 159 additions and 29 deletions

View file

@ -37,6 +37,22 @@ You need to import your LinkedIn analytics first:
1. Run `/linkedin:import` to import CSV data
2. Then come back to generate reports
## Step 1b: Ensure analytics CLI dependencies (first run)
The analytics CLI runs under `tsx` and depends on `csv-parse`. Both live in
`scripts/analytics/node_modules/`, which is **gitignored** — so on a fresh clone
they are absent and the CLI calls below would crash with `ERR_MODULE_NOT_FOUND`.
Install them once (idempotent — a fast no-op when already present):
```bash
cd "${CLAUDE_PLUGIN_ROOT}/scripts/analytics" && npm install --silent
```
The CLI calls below invoke the locally-installed `tsx` by its absolute
`node_modules/.bin/tsx` path (not bare `tsx`/`node --import tsx`), so they resolve
from whatever working directory the command runs in — but only after the install
above has created that binary.
## Step 2: Choose Report Type
**Ask the user** using AskUserQuestion:
@ -81,7 +97,7 @@ date +%Y-W%V
If the user chose monthly:
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --month <YYYY-MM>
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --month <YYYY-MM>
```
Read the generated JSON from `assets/analytics/monthly-reports/<YYYY-MM>.json`. Present the monthly summary with MoM comparison deltas, weekly breakdown, and top performers. Then jump to Step 7 for deep-dive options.
@ -91,7 +107,7 @@ Read the generated JSON from `assets/analytics/monthly-reports/<YYYY-MM>.json`.
If the user chose heatmap:
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" heatmap
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" heatmap
```
Present the day-of-week matrix and best-day findings. Then jump to Step 7 for deep-dive options.
@ -101,12 +117,12 @@ Present the day-of-week matrix and best-day findings. Then jump to Step 7 for de
Execute the report CLI command:
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --week <YYYY-WXX>
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --week <YYYY-WXX>
```
**Example:**
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --week 2026-W05
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" report --week 2026-W05
```
The CLI will generate:
@ -134,7 +150,7 @@ The report contains:
Get additional context with trend analysis:
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric impressions
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric impressions
```
This provides:
@ -149,11 +165,11 @@ After the initial trend data, automatically run trend analysis for the key metri
**Run trends CLI for key metrics:**
```bash
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" \
node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" \
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" \
trends --period month --metric impressions
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" \
node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" \
"${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" \
trends --period month --metric engagement_rate
```
@ -339,13 +355,13 @@ If user wants more trend analysis:
```bash
# Analyze comments trend
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric comments
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric comments
# Analyze shares trend
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric shares
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric shares
# Analyze engagement rate trend
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" node --import tsx "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric engagementRate
ANALYTICS_ROOT="${CLAUDE_PLUGIN_ROOT}/assets/analytics" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/node_modules/.bin/tsx" "${CLAUDE_PLUGIN_ROOT}/scripts/analytics/src/cli.ts" trends --period month --metric engagementRate
```
Present additional insights from these trends.
@ -377,7 +393,7 @@ Show detailed metrics for that post and suggest what made it perform well/poorly
3. **CLI error**: Technical failure
- Show error message
- Check file permissions
- Verify Node.js and tsx are available
- On `ERR_MODULE_NOT_FOUND` (missing `tsx`/`csv-parse` on a fresh clone), install the analytics CLI dependencies: `cd "${CLAUDE_PLUGIN_ROOT}/scripts/analytics" && npm install --silent`
## State Integration