feat(linkedin-studio): N14 — foldIns-fangst + Step 11 retro + background-headless + språkregel-akkumulering [skip-docs]
Lukker sløyfen pluginen manglet: en rettelse operatøren gjør i utgave N håndheves i N+1 i stedet for å bli gjenoppdaget. Maskineriet fantes (foldIns-skjema + promote→ratify siden fix #1); det som manglet var wiring — ingenting skrev til køen og ingen fase tømte den. - Fangst (A2-F7): Steps 2.5/3a/5.5/6.5 appender rettelsen ordrett med trigger, decision "pending". Ubetinget og bevisst dum — å avgjøre ved fangst om noe "fortjener" en regel er nettopp slik køen holder seg tom og sløyfen dør. - Step 11 retro (A2-F8), ≤5 min ETTER scheduling: promoter køen med eksplisitt JA/NEI (mekanisk → atomisk contract-gate-promotering, teller kun med grønn --ratify; dømmekraft → operatørens språkregelfil; NEI → rejected, beholdes), effort-oppsummering fra MÅLT phaseLog (aldri re-estimert), og ÉN friksjons-spørring som besvares tilbake til operatøren. Faser 18 → 19; resumption-tabellen ruter scheduling → Step 11, retro → complete. - articles.NN.retro: additiv-valgfri (default null), schemaVersion forblir 1. - Background-headless (A2-F6): --background kjører pakken i en bakgrunnsagent som skriver rapporten til disk; drafting-sesjonen leser fila. Samme isolasjon som fersk sesjon, uten copy-paste-sømmen. Inline fan-out = eksplisitt fallback. - Språkregler (C-10): ${DATA}/language-rules/<lang>.md (opt-in, template). Leses TO ganger — av language-reviewer (fanger) og av Step 4 (forebygger). Shippet banliste forblir baseline; brukerfila utvider. - references/fold-in-loop.md (A2-F9): loopen dokumentert domene-generelt in-tree, så en adopter uten ekstern skrivekontrakt har hele sløyfen. Refs 28 → 29. Suiter (alle grønne): test-runner 197 → 217 (Section 16u: 18 ubetingede greps + non-vacuity self-test; fase-sveip 16 → 17 faser; floor 179 → 198) · hooks 174 · trends 300 · brain 134 · editions 72 · specifics-bank 45 · contract-gate 33 · tests 35 · render 60. 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
677eab9294
commit
f0532dce3f
9 changed files with 711 additions and 30 deletions
|
|
@ -13,9 +13,10 @@ Full-spectrum LinkedIn content engine — short-form feed posts, carousels, vide
|
|||
- **Analytics:** CLI `scripts/analytics/` (TypeScript, needs `tsx` + `npm install`); data `assets/analytics/` (gitignored)
|
||||
- **Specifics-bank:** `scripts/specifics-bank/` (TypeScript, needs `tsx` + `npm install`) — deterministic, topic-tagged store of the operator's lived specifics (real numbers, named cases, held opinions) in the per-user data dir; elicited/bound by `/linkedin:newsletter` Step 1.5 so drafts draw from real inventory, never invented filler. Consumption is logged back at Step 8 lock (`record-usage` → `usedIn`), so cross-edition re-use of the same material is visible rather than silently encouraged by the dedupe
|
||||
- **Series distillate:** `scripts/editions/` (TypeScript, needs `tsx` + `npm install`) — series-level memory: each locked edition's spent narrative units (anecdotes/arguments/hooks) in `<serie>/linkedin/series-distillate.json`; written at `/linkedin:newsletter` Step 8 (`distil-append`), checked against the next skeleton at Step 2.5 (`distil-check`, advisory). Deterministic character-trigram similarity — AI extracts, code compares
|
||||
- **Editions register:** `scripts/editions/` (same package) — one row per edition in production in the per-user data dir (`editions/register.json`): series, edition, path, current phase, next action, slot, `startedAt`/`completedAt`. Each of the 16 canonical `/linkedin:newsletter` phase transitions runs `register-upsert --edition-state <path>`, which appends `articles.NN.phaseLog` (lead-time telemetry, additive — schemaVersion stays 1) **and** mirrors the row in one call; Step 10 runs `register-complete`. `register-list` is the work-in-progress view. The register is a **mirror** — deterministic resumption reads `edition-state.json` only, and a lost register is rebuilt by the next transition
|
||||
- **Editions register:** `scripts/editions/` (same package) — one row per edition in production in the per-user data dir (`editions/register.json`): series, edition, path, current phase, next action, slot, `startedAt`/`completedAt`. Each of the 17 canonical `/linkedin:newsletter` phase transitions runs `register-upsert --edition-state <path>`, which appends `articles.NN.phaseLog` (lead-time telemetry, additive — schemaVersion stays 1) **and** mirrors the row in one call; Step 10 runs `register-complete`. `register-list` is the work-in-progress view. The register is a **mirror** — deterministic resumption reads `edition-state.json` only, and a lost register is rebuilt by the next transition
|
||||
- **Publishing slots:** `hooks/scripts/slots.mjs` — the weekly production grid. Slots are **operator config** in the per-user data dir (`profile/publishing-slots.json`, schema + opt-in template in `config/publishing-slots.template.json`); absent config ⇒ every slot surface stays silent, and the plugin hardcodes no publishing times. Coverage of a slot counts the short-form queue (`scheduled`/`published`) **and** editions-register rows claiming that date, so long-form and short-form cannot be double-booked. Zero-dep (SessionStart may not spawn tsx) and imported identically by the hook and by the commands (`queue-manager.mjs` pattern), so session-start's vacancy warning and `/linkedin:newsletter` Step 10's slot default are the same computation
|
||||
- **Contract-gate:** `scripts/contract-gate/` (TypeScript, needs `tsx` + `npm install`) — deterministic §B/§C1 rule-gate on the full draft (`/linkedin:newsletter` Step 4.5, before the AI sweeps); ratifies `rules.ts` against the edition's §E-manifest, then gates with BLOCK/WARN
|
||||
- **Fold-in loop:** capture → classify → promote → enforce, documented domain-generally in `references/fold-in-loop.md`. The four `/linkedin:newsletter` steps where operator judgment enters the text (2.5, 3a, 5.5, 6.5) append corrections to `articles.NN.foldIns[]` (`decision: "pending"`); **Step 11 (retro)** empties the queue with an explicit operator JA/NEI — mechanical → an atomic contract-gate promotion (only counts when `--ratify` is green), judgment → the operator's opt-in language-rules file (`${DATA}/language-rules/<lang>.md`, template `config/language-rules.template.md`), which Step 4 reads while drafting (prevent) and `language-reviewer` reads at Step 6.5 (catch). Rejected rows are kept, never deleted. Step 11 also reports effort from the **measured** `phaseLog` and asks one friction question whose answer goes back to the operator — the plugin never writes their register
|
||||
- **Analytics metrics (S16):** parsed CSV columns + an optional, manually-entered `saves` count (count-only in native LinkedIn analytics since ~Sept 2025, no CSV export; the Marketing API exposes `POST_SAVE` on `/memberCreatorPostAnalytics` from v202604, but access is partner-gated — so manual entry remains the right UX). `parseOptionalCount()`: blank / non-numeric / negative → `undefined` (`unknown`, never 0), a genuine `0` is kept; saves surfaced per-post + as `totalSaves`, but **not** folded into `engagementRate`. `dwell` stays **explicitly unmeasurable** (internal to LinkedIn, no export/API). All analytics I/O routes through the `getAnalyticsRoot()` seam (M0 per-user data-dir).
|
||||
|
||||
## Hooks
|
||||
|
|
@ -55,8 +56,8 @@ All content commands auto-copy output to clipboard via `clipboard-helper.mjs`; i
|
|||
| `/linkedin:quick` | 5-minute quick post (3-line formula) + 8 post-type templates |
|
||||
| `/linkedin:pipeline` | Full end-to-end content pipeline |
|
||||
| `/linkedin:trends` | Trend discovery pass — delegates to `trend-spotter` (default long-form mode), persists to trend store + dated morning brief, triage per id (act/skip) |
|
||||
| `/linkedin:newsletter` | Long-form orchestrator (newsletter / essay / series article) — multi-session 18-phase pipeline with gates before prose (skeleton + spine), fact-check, editorial-review (Step 5.5), persona sweep, headless adversarial review (Step 6.5), and visual-assets — all before lock |
|
||||
| `/linkedin:headless-review` | Cold adversarial review package — 3 headless archetypes (`content-reviewer`, `language-reviewer`, `fact-reviewer`) + `persona-reviewer` on a FROZEN draft, no drafting-session context; operator-gated report (Step 6.5 standalone surface) |
|
||||
| `/linkedin:newsletter` | Long-form orchestrator (newsletter / essay / series article) — multi-session 19-phase pipeline with gates before prose (skeleton + spine), fact-check, editorial-review (Step 5.5), persona sweep, headless adversarial review (Step 6.5), and visual-assets — all before lock; closes with the Step 11 retro that promotes this edition's corrections so the next one starts with them enforced |
|
||||
| `/linkedin:headless-review` | Cold adversarial review package — 3 headless archetypes (`content-reviewer`, `language-reviewer`, `fact-reviewer`) + `persona-reviewer` on a FROZEN draft, no drafting-session context; operator-gated report (Step 6.5 standalone surface). `--background` runs the package in a background agent that writes the report to disk — fresh-session isolation without the paste-back seam |
|
||||
| `/linkedin:pivot` | Re-open a long-form edition after a late substantive change so cleared gates re-run before lock (pivot heuristic: >20% word-count or >2 new sections) |
|
||||
| `/linkedin:batch` | Create a full week of content |
|
||||
| `/linkedin:calendar` | View/manage post scheduling queue + publish action |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue