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
7.9 KiB
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 forscripts/test-runner.shto 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):
- Step 0 flags table gains the
--headlessrow. - New Step 0.5 section states the full contract:
--demand --headlessrefusal, Step 1 fail-fast, Step 5 unconditional skip, Steps 2–4/6 unchanged, artifact-grounded success. - Step 1's pillar-loading paragraph forks explicitly:
--headless→ error + stop; else → ask. - Step 2D gains the refusal clause for
--demand --headlessbefore its existing demand-sweep delegation text. - Step 5's header and lead line state the
--headlessskip 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--headlessclause to the existing/linkedin:trendsrow (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 -precipe 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
--headlesscontract is a prompt, so nothing enforces it mechanically; a future edit tocommands/trends.mdcould silently reintroduce a blockingAskUserQuestionon the headless path. Accepted, stated honestly: there is no code-level guard here (unlike RE-R3c's gate-testedschedule.ts). Claude Code's owndontAskpermission mode is the real backstop —AskUserQuestionis 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'stotal_cost_usdis 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.