idle-draft: per-work-type allowed_tools; research must web-search for stories

Research and topic_ideas runs get --allowedTools WebSearch,WebFetch;
research template mandates >=1 web search for related stories with
full-URL + access-date citations under the dossier's status labels.

Claude-Session: https://claude.ai/code/session_01YQDoWNM7XPPii28khFWoMc
This commit is contained in:
Paul O'Reilly
2026-08-02 21:32:35 +12:00
parent cd5be1cf92
commit 75add58246
6 changed files with 158 additions and 8 deletions

View File

@@ -228,7 +228,12 @@ For the selected `(item_or_dossier, work_type, provider)`:
4. Build the argv: `claude -p --max-turns <N>` (`N` = 25 unless overridden), plus
`--model <id>` if `provider.env` sets `MODEL_ID`, plus `--add-dir <dir>` for each
entry in `config["evidence_dirs"]` **only** for `research` and `topic_ideas` work
types (the only ones that cite external evidence).
types (the only ones that cite external evidence), plus `--allowedTools
"<comma-joined list>"` if `config["work_types"][work_type]["allowed_tools"]` is
present and non-empty (see Config schema below). Headless `claude -p` runs cannot
answer permission prompts, so any tool beyond the CLI's defaults must be granted
this way or the child run stalls/fails; when the key is absent or an empty list,
the flag is omitted entirely (unchanged pre-existing behaviour).
5. Run the subprocess: `cwd=<repo>`, `env=<built env>`, prompt piped via **stdin**
(not as an argv element — avoids `ARG_MAX` on large rendered prompts, same lesson
`claude-profile` already applies to its system-prompt injection), timeout = per-task
@@ -311,6 +316,17 @@ already says) is never written here.
`idle-draft.config.json` — see `data/idle-draft/config.example.json` for the exact
structure. All top-level keys listed in §3 are required.
Each entry in `work_types` may carry an optional `allowed_tools` key: a list of Claude
Code tool names (e.g. `["WebSearch", "WebFetch"]`) granted to that work type's headless
child via `--allowedTools` (§11 step 4). Present-but-empty and absent are both treated
as "no extra tools" — the flag is omitted. If present, it must be a JSON array of
strings; any other shape (a string, a number, a list containing a non-string) is a
config validation failure — exit **2** at config load, same as a missing required key.
`config.example.json` sets `allowed_tools: ["WebSearch", "WebFetch"]` on `research` and
`topic_ideas` (the research prompt template requires at least one `WebSearch` call
before writing its Subjective stories section; the topic-ideas template requires one as
a lighter-touch check); `draft` and `review` carry no `allowed_tools` key.
## Failure classes
| Class | Examples | `attempts` effect | Item outcome |
@@ -344,6 +360,7 @@ structure. All top-level keys listed in §3 are required.
| `--probe-json` combined with `--dryrun` | Composes normally — no subprocess call either way |
| `--once` with no eligible work | Exits 0 immediately, no task dispatched |
| Config missing a required key | Exit 2 |
| `work_types[*].allowed_tools` present but not a list of strings | Exit 2 |
| `agent-subscriptions` subprocess fails entirely | Exit 1, loud log line, no dispatch attempted |
## Examples