Commit graph

10 commits

Author SHA1 Message Date
e7276cf8bb fix(linkedin-studio): N20 — CLAUDE_PLUGIN_ROOT-normalisering av load-bearing ref-stier [skip-docs]
81 load-bearing stier i 16 kommandofiler pinnet til ${CLAUDE_PLUGIN_ROOT}/.
Rene prefikser: 81 inn / 81 ut, ingen linje lagt til eller fjernet.

FASIT-VERIFISERING (premiss-sjekk mot BASELINE, ikke bare HEAD): planens
68 linjer / 17 filer er RIKTIG mot sin egen baseline 882f6ee. HEAD ga 73/18 —
altså ekte kode-drift siden baseline (newsletter.md 11→15, calendar.md 0→1),
ikke en telle-feil som i N19.

SCOPE UTVIDET ETTER GO: planens grep (references|hooks/scripts|scripts) har en
blindsone — skills/ assets/ config/ render/ agents/ commands/ er samme defekt-
klasse og allerede anerkjent som pin-verdig av mønsteret (audit.md:24 og
competitive.md:22 pinner skills/, batch.md:214 og pipeline.md:211 pinner
assets/). Under planens scope kunne dens EGEN verifisering ikke passere:
quick.md:229-230 ville stått upinnet rett over en pinnet linje, og setup.md
(3 load-bearing Read, 0 pins) var ikke i settet i det hele tatt.
Full defektklasse: 117 linjer / 19 filer → 81 pinnet, 36 bevisst urørt.

KLASSIFISERINGSREGEL (utledet av mønsteret, ikke oppfunnet):
- PIN = stien skal åpnes/kjøres/skrives — Read/Reference/See-pekere,
  ref-fil-lister, Bash/node/npm, edit-mål.
- PROSA = stien står som sitat bak en påstand, eller som beskrivelse av
  oppførsel/plassering. Ingen inline «(see …)» er pinnet noe sted i repoet
  (0 av 25 filer) — den grensen er arvet, ikke satt her.

36 BEVISST URØRTE, tre klasser:
1. Inline sitat/attribusjon (17): carousel.md:37 · pipeline.md:70,75 ·
   newsletter.md:999,1082,1211,1433 · report.md:273 · video.md:69 ·
   react.md:115 · calendar.md:87 · profile.md:28,34 · firsthour.md:112 ·
   monetize.md:343,492 · outreach.md:922
2. Beskrivelse av oppførsel/plassering (10): newsletter.md:50,1097,1205,1694,
   1744,1944 · report.md:45 · linkedin.md:218 · import.md:121,200
3. newsletter.md fase-tabellens Tooling-kolonne (9): :100,102,105,106,111,112,
   113,115,116 — tabellen er et register, og hvert steg pinner sitt eget
   faktiske kall i brødteksten.

S13-LINTEN (M0 data-dir): alle assets/-stiene som ble pinnet står eksplisitt i
lintens NEGATIVE13-unntaksliste, og lintens egen kommentar (test-runner.sh:552)
sier at shipped read-only assets SKAL bære ${CLAUDE_PLUGIN_ROOT}.

VERIFISERING: 76 unike pinnede stier hentet ut og resolvet med cwd=/tmp —
75 finnes. Den ene som ikke gjør det, config/personas.local.md, er en
gitignored valgfri fallback («else personas.template.md») som var pinnet på
newsletter.md:205 før denne endringen. Re-grep: gjenstående 36 er utelukkende
prosa, listet over.

Alle ti suiter grønne, alle floors uendret: test-runner 270/0 (269 assertions
>= floor 251) · trends 300/0 · analytics 202/0 · hooks 191/0 · brain 134/0 ·
editions 72/0 · render 63/0 · specifics-bank 45/0 · tests 35/0 ·
contract-gate 33/0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M31cw43gqiSSDrKzcwUi7L
2026-07-31 17:21:22 +02:00
63506f7d5c feat(linkedin-studio): N16 — out-of-network-andel + patterns-oppdatering + boundary-map [skip-docs]
Reach-splitten (in/out-of-network) er native i LinkedIns post-analytics siden juni
2026, men vises som PROSENT og finnes ikke i CSV-eksporten. Planen antok to
manuelle antall; verifiseringen viste prosent, så modellen er ett felt —
outOfNetworkPct — og in-network er komplementet.

- parseOptionalPercent: egen parser, ikke parseOptionalCount. Komma er desimal
  (36,5 -> 36.5, aldri 365), og verdi >100 avvises: i én kolonne kan ikke et
  absolutt antall skilles fra en andel, så svaret er unknown, ikke en gjetning.
  Blank/ikke-numerisk/negativ -> unknown; ekte 0 beholdes.
- Ett lagret halvpart, kryssjekket: In-network godtas og lagres som komplement;
  et transkribert par som ikke summerer til ~100 (±1 avrunding) forkastes som
  unknown i stedet for å bli halvveis trodd.
- weightedOutOfNetworkPct: impressions-vektet roll-up (avgOutOfNetworkPct, uke +
  måned). Flatt snitt lar en 50-visnings-post slå en på 10 000; poster uten
  avlesning ekskluderes, og null vekt gir undefined — aldri 0, aldri NaN.
- Reach inngår ALDRI i engagementRate (distribusjon != engasjement). Rapporten
  leser den som akvisisjon (ut) vs resonans (inn), og sier «ikke ført for denne
  perioden» framfor å estimere. En reach-innsikt går inn i N15s do-next-kanal.
- Step 7c (A2-F11): rapporten tilbyr diff mot brukerens engagement-patterns.md
  med eksplisitt go — aldri stille skriving, aldri inn i den shippede malen.
- Boundary-map (E#9): dwell eksplisitt umålbar, saves partner-gated, reach
  native men CSV-eksport uverifisert.
- Reach-frie importer er byte-identiske med før, på skjerm og på disk.

TDD: rødt bevist først (10 feilende), analytics 119 -> 144 tester, tsc ren.
test-runner 232 -> 247 (Section 16w, gulv 213 -> 228). Alle suiter grønne.
CHANGELOG: N15-oppføringen manglet og er backfilt sammen med N16.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QxvWAjte7vPcF79QeSRvRJ
2026-07-25 15:56:04 +02:00
a413279c58 fix(linkedin-studio): S14 harden import — drop baseline/metadata over-promise, prose now matches CLI
import.md repeatedly promised baseline comparison, rolling 4-week averages, and
baselines.json/metadata.json the importer "creates" — but no code anywhere writes
either file; detectAlerts flags intra-batch std-dev from the batch's own mean, not
a stored baseline. Step 5b's `cat baselines.json` was always empty, so the command
fell forever to "first import — baselines will be established" on every import.
Rewrote 5 sections (Step 5, 5b, 7, State Tracking, Reference Files) to the truth:
real CLI fields + YYYY-MM-DD-<shortid> filename, honest intra-batch surfacing,
cross-week analysis deferred to /linkedin:report. Verified with a grounded run
against a throwaway fixture.
Axes a/b/c/d all PASS post-fix; lint 81/0/0, counts 29/19 unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016qgzo6rxthw7KuxHjn5vyE
2026-06-18 20:56:47 +02:00
6bd263144f docs(linkedin-studio): M0-15 — repoint remaining prose families + route ab-tests/plans 2026-06-18 13:04:18 +02:00
33aa3c4ca9 docs(linkedin-studio): M0-11 — drop in-plugin ANALYTICS_ROOT pins + repoint content-history (B1/B2) 2026-06-18 12:05:15 +02:00
b27ceb437b docs(linkedin-studio): honest dated API/auto-publish/analytics boundaries
Wave 3 / Step 10 of the remediation plan (Phase 1 — usable by a non-author), per
research/02.

State what the plugin can and cannot do for a PERSONAL profile, dated 'as of
2026-05', without replacing one false claim with another:
- README.md: new 'Boundaries (as of 2026-05)' section. (a) post-level analytics API
  EXISTS but is partner-gated (vetted Community Management app + verified org +
  Page) — not self-serve; CSV is the practical floor; saves visible natively
  (count-only, ~Sept 2025) with no self-serve API pull. (b) auto-publish is
  technically POSSIBLE self-serve (w_member_social) but deliberately NOT built — a
  design + ToS choice, explicitly 'not an impossibility' (avoids the new false
  'cannot auto-publish' claim). (c) dwell internal-only for organic, not exportable.
- commands/calendar.md: the publish action now states plainly it marks a post YOU
  posted manually as published — the tool does not post on your behalf.
- commands/report.md: dated the saves/no-self-serve-API note ('as of 2026-05').
- commands/import.md: dated 'Why CSV' note — API is partner-gated, CSV is the floor.

Verify: grep -niE 'cannot auto-publish|only way to (get|access)' README.md
commands/*.md -> no matches; grep -ni 'as of 2026' README.md -> 2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 00:58:05 +02:00
26cd1c1d6d 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>
2026-05-29 21:18:33 +02:00
52fa87a255 refactor(linkedin)!: rename plugin linkedin-thought-leadership → linkedin-studio (v3.0.0)
BREAKING CHANGE: the marketplace slug, the agent namespace
(linkedin-studio:<agent>), and the runtime state-file path
(~/.claude/linkedin-studio.local.md) all change. Reinstall required;
existing state migrated in place (post metrics, streak, history preserved).
The /linkedin:* commands are unchanged — the command namespace is set
per-command in frontmatter and was always independent of the plugin slug.
Functionality is byte-identical to v2.4.0; this release is pure identity.

- dir + manifests: plugins/linkedin-studio + plugin.json + root marketplace.json
- agent namespace updated in commands/newsletter.md (only functional invoker)
- state path updated in 4 hook scripts + topic-rotation prompt + state template
- catch-all skill dir renamed skills/linkedin-studio (5 functional skills unchanged)
- docs + version bump to 3.0.0 across README badge, CHANGELOG, root README/CLAUDE.md
- historical records (CHANGELOG past entries, docs/ build artifacts,
  config-audit v5.0.0 snapshots) intentionally retain the old slug

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 11:32:02 +02:00
0879243ca4 chore(linkedin): v2.0.0 — import trim, router gating, full doc pass (S20) 2026-05-28 06:53:55 +02:00
Kjell Tore Guttormsen
40986575b6 feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command
Add /ultraresearch-local for structured research combining local codebase
analysis with external knowledge via parallel agent swarms. Produces research
briefs with triangulation, confidence ratings, and source quality assessment.

New command: /ultraresearch-local with modes --quick, --local, --external, --fg.
New agents: research-orchestrator (opus), docs-researcher, community-researcher,
security-researcher, contrarian-researcher, gemini-bridge (all sonnet).
New template: research-brief-template.md.

Integration: --research flag in /ultraplan-local accepts pre-built research
briefs (up to 3), enriches the interview and exploration phases. Planning
orchestrator cross-references brief findings during synthesis.

Design principle: Context Engineering — right information to right agent at
right time. Research briefs are structured artifacts in the pipeline:
ultraresearch → brief → ultraplan --research → plan → ultraexecute.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 08:58:35 +02:00