feat(linkedin-studio): N7 — trend->newsletter-bro (sourceTrendId + Step 1-inntak + auto-act) + F7 band-cap-gate [skip-docs]
Del 2 (broen): commands/newsletter.md Step 1 trend-intake pre-fills brief (angle/targetLevel/key-points/source-URLs) from a /linkedin:trends candidate via the trends CLI; sourceTrendId persisted at Step 1.5; Step 10 auto-act flips the source trend to acted (closes the discovery->production loop deterministically); Step 2 external fact-package intake path (kilde-så-draft with finished research). edition-state.template.json: per-article sourceTrendId (additive-optional, no schemaVersion bump). A1-8: grep -ci trend commands/newsletter.md 0 -> 18. Del 2.5 (F7 gate, TDD): score.ts capForActionability — a candidate whose reader-grip is explicitly not formulated (actionability.formulated=false) caps to at most High regardless of composite. Pure; overrides the composite->band derivation downward only (composite/dimensions/mode preserved, score stays etterprøvbar); absent actionability left uncapped (legacy-safe). Wired into the item.ts capture path so the PERSISTED priority is gated; store carries the envelope verbatim (re-capture safe). No KTG values hardcoded — the N6 field carries the verdict, the gate only enforces it. Suites (all green): trends 276/0 (was 266, +10), test-runner 139/0, brain 134/0, hooks 140/0, tests 35/0, render 60/0; tsc --noEmit clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014bE7VbkmR3cqHFEeGfzgwb
This commit is contained in:
parent
bace49f8c2
commit
1adb7f4361
6 changed files with 204 additions and 8 deletions
|
|
@ -271,6 +271,33 @@ Establish the edition brief with **at most ~3 calibration questions**. Infer
|
|||
everything you can from Step 0 (series brief, STATE.md, prior edition); only ask
|
||||
what genuinely changes the work.
|
||||
|
||||
> **Trend intake (optional bridge — N7).** If this edition is being started from a
|
||||
> `/linkedin:trends` candidate — the operator supplies a **trend id** (shown in the
|
||||
> trends brief and via `CLI list --json`, where
|
||||
> `CLI` = `cd "${CLAUDE_PLUGIN_ROOT}/scripts/trends" && node --import tsx src/cli.ts`)
|
||||
> — read that record and **pre-fill the brief from it** instead of asking from
|
||||
> scratch. Without a trend id, skip this block entirely: the flow below is
|
||||
> unchanged (the bridge is an offer, never a requirement).
|
||||
>
|
||||
> 1. **Read the candidate.** Run `CLI list --json` (or `CLI query --topics <edition
|
||||
> topics> --json`) and select the entry whose `id` equals the supplied trend id.
|
||||
> 2. **Pre-fill from the record's proposal layer (N6 fields)** — each is a *starting
|
||||
> point the operator confirms or edits* in the dimensions below, not a bypass of
|
||||
> calibration:
|
||||
> - `angle` → the edition **Angle**.
|
||||
> - `targetLevel` → the audience/tone calibration (**Audience** / **Tone**).
|
||||
> - `summary` + `rationale` + `readerQuestion` / `painPoint` → seed the **Key
|
||||
> points** and the **Leader-takeaway** (the reader-side framing this bridge
|
||||
> exists to carry: what the reader would DO with it).
|
||||
> - `url` (+ any URLs in `rationale`) → seed **source URLs** for Step 2 research /
|
||||
> the `NN-kilder.md` ledger (they land as `ekstern` slots at Step 1.5).
|
||||
> - `actionability` / `verdict` (BÆRENDE/STØTTE/NYHET) → frame the takeaway; a
|
||||
> candidate the operator selected already cleared the F7 reader-grip gate.
|
||||
> 3. **Bind the provenance.** Note the trend id — it is persisted as
|
||||
> `articles.NN.sourceTrendId` at the **Step 1.5 checkpoint** (below) and closes the
|
||||
> discovery→production loop automatically at Step 10 (scheduling flips the trend to
|
||||
> `acted`).
|
||||
|
||||
Settle these dimensions (most should come from context, not questions):
|
||||
|
||||
- **Angle** — the one premise this edition argues.
|
||||
|
|
@ -416,6 +443,9 @@ Edition brief
|
|||
- Persist the resolved **brief** (Step 1) and **personas** (the set + primær)
|
||||
into `articles.NN` — this is the first durable write of both (Step 2 then adds
|
||||
the research notes).
|
||||
- If Step 1 ran the **trend-intake bridge**, persist `articles.NN.sourceTrendId`
|
||||
(the trend id) here too — the durable provenance link Step 10 reads to auto-`act`
|
||||
the trend. Omit it (leave `null`) for a manually-started edition.
|
||||
- Write `articles.NN.livedSpecifics` (the slot-map above, `status: "pending"`).
|
||||
- Set `currentPhase: "lived-specifics"` in `edition-state.json`.
|
||||
- Write a "lived-specifics bound → next: research (scoped by the binding)" line
|
||||
|
|
@ -451,6 +481,26 @@ Next: Step 2 — Research (scoped by the binding: fill ekstern/unresolved, verif
|
|||
against a primary source (regel 6/7). This is what makes research *fill* the
|
||||
draft instead of re-deriving what the operator already knows.
|
||||
|
||||
0.5. **External fact-package intake (optional — kilde-så-draft with finished
|
||||
research).** If the operator already has a **deep-research report** — a file the
|
||||
operator supplies by path (e.g. a Gemini Deep Research export, a consultant brief,
|
||||
a prior research pass; markdown / text / PDF) — ingest it as a research input
|
||||
instead of researching those slots from zero:
|
||||
- **Read the file** and extract the same structure the fan-out returns: findings
|
||||
(each with its source), data points (figures + source + date), and anything the
|
||||
report itself flags as uncertain.
|
||||
- **Map onto the binding.** Attribute each finding to the `ekstern`/`unresolved`
|
||||
slot (or unverified number) it resolves; its sources become the `source` on
|
||||
those slots and land in `NN-kilder.md` at persist (step 5).
|
||||
- **Same guilty-until-disproven discipline.** A packaged claim is NOT
|
||||
pre-verified: label anything you cannot corroborate `UNVERIFIED` and carry it to
|
||||
the Step 5 fact-check sweep as 🟡 — a polished report is not a primary source.
|
||||
- **Then scope the fan-out to the GAP only.** Slots the package covers need no
|
||||
`Task` call; run steps 1–3 below **only for the slots the package leaves open**.
|
||||
If the package covers every `ekstern`/`unresolved` slot, the fan-out may reduce
|
||||
to zero calls — note that explicitly (don't fabricate a fan-out that added
|
||||
nothing). With no package supplied, this sub-step is a no-op: proceed to step 1.
|
||||
|
||||
1. **Decompose** the binding's `ekstern`/`unresolved` slots + unverified numbers
|
||||
(step 0) into 2–5 *scoped, orthogonal* research sub-questions. Each sub-question
|
||||
must be answerable independently so the calls can run in parallel without
|
||||
|
|
@ -1749,7 +1799,22 @@ now a first-class scheduled post.
|
|||
The function appends to `${LINKEDIN_STUDIO_DATA:-$HOME/.claude/linkedin-studio}/drafts/queue.json` with `status:
|
||||
"scheduled"` and returns the new entry.
|
||||
|
||||
3. **Persist + close the edition.** Set the article's `status: "scheduled"`,
|
||||
3. **Close the discovery loop (auto-`act` — N7).** If `articles.NN.sourceTrendId`
|
||||
is set (this edition was started from a `/linkedin:trends` candidate), flip that
|
||||
trend's store status to `acted` so it drops out of future discovery triage — the
|
||||
discovery→production loop closes deterministically, not from memory:
|
||||
|
||||
```bash
|
||||
cd "${CLAUDE_PLUGIN_ROOT}/scripts/trends" && node --import tsx src/cli.ts act --id "<sourceTrendId>"
|
||||
```
|
||||
|
||||
A present id flips to `acted` (exit 0). If the id is no longer in the store the
|
||||
call errors (all-miss → exit 2, store untouched) — that is **not fatal** to
|
||||
scheduling (the edition is already registered in step 2): note it and proceed.
|
||||
Skip this step entirely when `sourceTrendId` is `null` (a manually-started
|
||||
edition has no trend to close).
|
||||
|
||||
4. **Persist + close the edition.** Set the article's `status: "scheduled"`,
|
||||
`scheduled: "<YYYY-MM-DD HH:MM>"`, and `currentPhase: "scheduling"` in
|
||||
`edition-state.json`. Write a closing "edition scheduled → mark live via
|
||||
`/linkedin:calendar` on <date>" line to `<serie>/STATE.md` (overwrite). The
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue