Tracked slice docs for MR-F5: the poll->score->capture->brief loop made safe to fire with no operator present. Records the 2026-06-24 re-evaluation gate against v1.0.0 maturity and the operator's explicit decision to open it (2026-08-10), plus the Desktop Scheduled Tasks vs. hand-rolled cron design decision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2qHoS4FrkabuD1bCg8Nr2
113 lines
7.9 KiB
Markdown
113 lines
7.9 KiB
Markdown
# Plan — RE-R3f: unattended AI discovery (`--headless`, slice e)
|
||
|
||
> **Brief:** `docs/research-engine/brief-re-r3f.md`. **Slice:** RE-R3f (research-engine rung-2 — R3
|
||
> slice (e), the AI-capture unattended-run slice). No new source/test file: this is a prompt-file
|
||
> (`commands/trends.md`) contract change plus documentation. There is nothing here for
|
||
> `scripts/test-runner.sh` to gain a new floor for — the plan's "TDD" is a direct-read verification
|
||
> against the brief's SC1–SC5, not a unit-test suite.
|
||
|
||
## Files touched (exhaustive)
|
||
|
||
| File | Change | SC |
|
||
|---|---|---|
|
||
| `commands/trends.md` | EDIT — `--headless` flag row + new **Step 0.5** contract section; Step 1's missing-profile branch forks on `--headless`; Step 2D refuses `--demand --headless`; Step 5 header states the unconditional skip | SC1, SC2 |
|
||
| `scripts/trends/README.md` | EDIT — new `## Unattended AI discovery — --headless (RE-R3f, slice e)` section: Desktop Scheduled Tasks (recommended) + the fallback `claude -p` recipe + `ANTHROPIC_API_KEY` + wait-ceiling + artifact-grounded success check + cost visibility | SC3 |
|
||
| `CLAUDE.md` | EDIT — `/linkedin:trends` command-table row gains a `--headless` clause | SC4 |
|
||
| `CHANGELOG.md` | EDIT — `[Unreleased]` entry naming MR-F5 | SC4 |
|
||
| `docs/research-engine/{brief,plan}-re-r3f.md` | NEW — tracked slice docs (mirrors R3c/R3e/etc.) | — |
|
||
| `STATE.md` | EDIT at land — Telling-block reconcile (no new counts; note MR-F5 landed) | — |
|
||
|
||
**Not touched (scope fence):** `scripts/trends/src/*.ts` (no code — Desktop Scheduled Tasks is the
|
||
mechanism, not a repo-owned wrapper); `scripts/trends/run-daily.sh` (RE-R3c stays deterministic-only,
|
||
untouched); `agents/trend-spotter.md` (the agent's own contract — poll/score — is unchanged by who
|
||
fires it; `--headless` is a command-level concern); `config/*`; `references/*`; command/agent counts
|
||
(no new command, no new agent — `--headless` is a flag on an existing command); `scripts/test-runner.sh`
|
||
(no new floor — nothing here is `tsx`-tested source).
|
||
|
||
## Step 1 — `commands/trends.md`: the `--headless` contract
|
||
|
||
Edited already this session (verify against brief SC1/SC2 by direct read):
|
||
1. Step 0 flags table gains the `--headless` row.
|
||
2. New **Step 0.5** section states the full contract: `--demand --headless` refusal, Step 1
|
||
fail-fast, Step 5 unconditional skip, Steps 2–4/6 unchanged, artifact-grounded success.
|
||
3. Step 1's pillar-loading paragraph forks explicitly: `--headless` → error + stop; else → ask.
|
||
4. Step 2D gains the refusal clause for `--demand --headless` before its existing demand-sweep
|
||
delegation text.
|
||
5. Step 5's header and lead line state the `--headless` skip condition (not buried only in Step 0.5
|
||
— a reader working step-by-step must see it at the step itself).
|
||
|
||
**Verification:** `grep -n -- '--headless' commands/trends.md` shows the table row + Step 0.5 + the
|
||
three per-step cross-references (≥5 matches, SC1); re-read Steps 1/2D/5 end-to-end to confirm each
|
||
fork is unambiguous (no branch left to model inference under ambiguity, SC2).
|
||
|
||
## Step 2 — `scripts/trends/README.md`: the unattended-discovery section
|
||
|
||
Edited already this session. New section placed after the existing RE-R3c ("Autonomous trigger +
|
||
headless entry") section, explicit that RE-R3f is a **different mechanism** (full agent turn, not a
|
||
bash wrapper): Desktop Scheduled Tasks recommended; the fallback `claude -p …` recipe with all four
|
||
required flags; `ANTHROPIC_API_KEY` under `--bare`; `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`; the
|
||
artifact-grounded success check (never trust `$?`/prose); `total_cost_usd` cost-visibility note.
|
||
|
||
**Verification:** `grep -n -- '--bare\|--permission-mode dontAsk\|--allowedTools\|ANTHROPIC_API_KEY\|Desktop Scheduled Tasks' scripts/trends/README.md` — each present (SC3).
|
||
|
||
## Step 3 — `CLAUDE.md` + `CHANGELOG.md`
|
||
|
||
- `CLAUDE.md`: append a `--headless` clause to the existing `/linkedin:trends` row (one line, no
|
||
restructuring of the table).
|
||
- `CHANGELOG.md`: `[Unreleased]` gains an entry — MR-F5 landed, the gate-opening decision named, the
|
||
scope (command contract + docs, no new code), matching this repo's existing changelog voice (see
|
||
the 0.8.0 entries for tone/format).
|
||
|
||
**Verification:** `grep -n -- '--headless' CLAUDE.md`; `grep -n 'MR-F5' CHANGELOG.md`.
|
||
|
||
## Step 4 — gate + regression sanity
|
||
|
||
`bash scripts/test-runner.sh` → `FAIL=0`, every existing floor unchanged (no new source/test file to
|
||
raise a floor for); Section 17 de-niche green (no vendor/sector token in any edit — the README's
|
||
`claude -p` recipe names a placeholder plugin-dir path, never an operator-specific one);
|
||
command/agent/reference counts unchanged, recounted live (`--headless` is a flag, not a new
|
||
surface).
|
||
|
||
## Step 5 — land
|
||
|
||
Recount counts live; reconcile `STATE.md`'s Telling block (no count change; note MR-F5 landed at
|
||
commit); quit the feedback register kvittering per `CLAUDE.local.md`'s protocol ("landed
|
||
feedback:MR-F5 @ `<commit>`" — Maskinrommet flips 🔵→🟢 on relay, never written here). Commit order:
|
||
**(1)** docs commit — `docs/research-engine/{brief,plan}-re-r3f.md` (tracked, no suffix); **(2)** one
|
||
code^H^H^H^Hprompt commit — `commands/trends.md` + `scripts/trends/README.md` + `CLAUDE.md` +
|
||
`CHANGELOG.md` (there is no code in this slice — "code commit" here means the prompt-file + docs
|
||
edit, landed together since it is one coherent contract change). Push after operator go (public
|
||
`open/` remote — confirm before push per the repo's own push-topology memory).
|
||
|
||
## Verification (testable)
|
||
|
||
| SC | Check | Command | Expected |
|
||
|---|---|---|---|
|
||
| SC1 | `--headless` documented | `grep -c -- '--headless' commands/trends.md` | ≥ 5 |
|
||
| SC2 | Per-step forks unambiguous | direct read of Steps 1, 2D, 5 | each states the `--headless` branch explicitly, no inference required |
|
||
| SC3 | README recipe complete | `grep` for the four flags + `ANTHROPIC_API_KEY` + `Desktop Scheduled Tasks` | all present |
|
||
| SC4 | CLAUDE.md + CHANGELOG updated | `grep -- '--headless' CLAUDE.md`; `grep 'MR-F5' CHANGELOG.md` | both present |
|
||
| SC5 | Gate green, counts unchanged | `bash scripts/test-runner.sh` | `FAIL=0`; all floors unchanged; Section 17 green |
|
||
| SC6 | (explicitly deferred) | — | consumer-side unattended proof is NOT claimed this session (`plugin-runtime-is-consumer-side`) |
|
||
|
||
## Risks
|
||
|
||
- **R1 — a scheduled task on the operator's actual machine can't reach Desktop Scheduled Tasks
|
||
(older Claude Code version, disabled feature).** *Mitigated:* the fallback `claude -p` recipe is
|
||
fully documented in the README, so the operator has a working path either way; not built as repo
|
||
code because building an unused wrapper would be speculative (brief §3 D3).
|
||
- **R2 — the `--headless` contract is a prompt, so nothing enforces it mechanically; a future edit
|
||
to `commands/trends.md` could silently reintroduce a blocking `AskUserQuestion` on the headless
|
||
path.** *Accepted, stated honestly:* there is no code-level guard here (unlike RE-R3c's
|
||
gate-tested `schedule.ts`). Claude Code's own `dontAsk` permission mode is the real backstop —
|
||
`AskUserQuestion` is auto-denied unconditionally regardless of what the command file says — so a
|
||
regression fails safe (the run aborts) rather than silently hanging on a phantom prompt.
|
||
- **R3 — unattended weekly AI research has a real, currently-uncapped per-run cost.** *Mitigated by
|
||
visibility, not a cap* (brief §3 non-goal, D2): `--output-format json`'s `total_cost_usd` is
|
||
documented as the thing to log; enforcing a hard ceiling is deferred as a real design question
|
||
rather than an arbitrary number picked under this slice.
|
||
- **R4 — the gate-reopening decision itself is contestable** (research was explicitly deferred to
|
||
v1.0.0 by a prior operator decision). *Mitigated:* the conflict was surfaced explicitly
|
||
(AskUserQuestion, 2026-08-10) rather than silently built around or silently deferred; the operator
|
||
chose to open it with the trade-off stated plainly. Recorded in the brief's header for future
|
||
sessions reading this slice cold.
|