docs: clear write-good.Passive hits in gateway/subagent/dashboard docs

Part of #4548 — rewriting the 353 hand-written-docs write-good.Passive
hits so #4546 can flip the rule to error. This batch: docs/networking/gateway.md
(27 hits), docs/tools/subagent.md (19), docs/web-ui/dashboard.md (18).

Minimal, meaning-preserving rewrites to active voice only — no
restructuring beyond what each flagged sentence needed. Genuine false
positives (predicate-adjective state descriptions like "is required",
"is broken", "is unchanged", adjectival past participles like "named
buckets", and one quoted literal UI string) are left in place; the
per-line reasoning is on the tracking issue.

Note: docs/tools/forge-cli.md (37 hits, would have been the single
biggest file) turned out to be generated from hive-forge's own clap
help text (see hive-forge/src/main.rs's `MarkdownDocs` verb) — same
category as the already-excluded hivectl-cli.md/swarmctl-cli.md, so
it's untouched here. Flagged on #4548.
This commit is contained in:
iris 2026-09-20 00:25:56 +02:00 committed by mara
commit cb504f6863
3 changed files with 54 additions and 54 deletions

View file

@ -37,8 +37,8 @@ that `start` is reachable from.
Neither signal tool takes a session name. **The URL is the identity.** At
each spawn the daemon mints that run an unguessable token, serves it at
`/signal/mcp/<token>`, and writes that one URL into that one subagent's own
`--mcp-config` — a file per session, not a shared one. A request is
resolved to a session before it's dispatched, and the tools read the
`--mcp-config` — a file per session, not a shared one. The daemon resolves
a request to a session before dispatching it, and the tools read the
session off the resolution.
A subagent therefore has no field in which to name a sibling, and knowing
@ -85,25 +85,25 @@ reaches. Read alongside the last-event age below, it's what separates a
subagent that's working from one that's wedged from one that's out of
turns — without `ps` and without opening a file.
Four things stop a run, and each is recorded distinctly, reported by
`status`, and appended to the one todo the daemon pushes when the run ends:
Four things stop a run; the daemon records each distinctly, reports it via
`status`, and appends it to the one todo it pushes when the run ends:
- **the turn ended and there was no goal** — the single-turn case;
- **`goal_reached`**, which the subagent calls itself;
- **`need_help`**, likewise;
- **the turn cap**, which says so rather than stopping quietly: the todo
states that the harness limit was reached and the goal was never
states that the run hit the harness limit and the goal was never
reported reached, so the work stopped where it had got to.
A killed or failed turn ends the run too, and keeps the records it already
had — see [A killed turn](#a-killed-turn). `interrupt` therefore stops a
whole goal run, not just the turn in flight.
When the session was told where its report goes — `start`'s `report_file`,
or the path the subagent names when it signals — the stop reason is
appended to that file as well, so the artifact you were going to read
anyway also says how the run ended. Nothing is inferred: with no path
given, no file is touched.
When the session knows where its report goes — `start`'s `report_file`,
or the path the subagent names when it signals — the daemon appends the
stop reason to that file as well, so the artifact you were going to read
anyway also says how the run ended. The daemon infers nothing: with no
path given, it touches no file.
## `goal_reached` is a label, not a gate
@ -125,8 +125,8 @@ parent that polls `status` sees the block without reading anything else.
## Is it working, or is it wedged?
`status` reporting **running** says a process is tracked, which a wedged
subagent satisfies as fully as a busy one. A running answer therefore
`status` reporting **running** says the daemon tracks a process, which a
wedged subagent satisfies as fully as a busy one. A running answer therefore
carries the age of that turn's last event too: seconds means it's working,
an age climbing into the minutes means it's stuck. That one number
replaces inferring the same thing from `ps` output and CPU-time deltas.
@ -164,7 +164,7 @@ continue error: claude error: no session matched the requested id or title (sear
The directory is the part claude's own message never names, and the part
that resolves the confusion: pass `dir` to point `continue` at the
directory the session was started in.
directory where the session began.
Nothing here is a fixed delay on the way to a successful turn. The wait
ends on whichever comes first — the turn's first stream event or its
@ -174,7 +174,7 @@ bounds the one case neither covers: a child that neither speaks nor
exits, reported as started, with the end-of-turn todo left to say how it
goes. That todo still carries every failure that happens later in the
turn, exactly as before; the only one it no longer repeats is the miss
the caller has just been handed to its face.
`continue` has just handed the caller directly.
## A killed turn
@ -185,11 +185,11 @@ than letting it settle back into `idle`:
- `status` reports the session **killed**, naming the signal, instead of
the `idle` it reports for a turn that ended on its own;
- the end-of-turn todo the daemon pushes without being asked says the
subagent was killed mid-turn, not that it finished;
- the end-of-turn todo the daemon pushes unprompted says something killed
the subagent mid-turn, not that it finished;
- `continue` still resumes such a session — often what you want — but
its reply says the previous turn was killed, so nobody carries on from
cut-off work believing it was complete.
its reply says something killed the previous turn, so nobody carries on
from cut-off work believing it was complete.
The record is per-name, in memory with the rest of this daemon's state,
and the next confirmed spawn under that name clears it. A daemon restart
@ -254,21 +254,21 @@ allowed it, and would diverge from the parent's on the first tool anyone
adds to either.
Everything else in claude's built-in set is absent, in particular the
tools that let a session act outside the run it was started for: peer and
tools that let a session act outside the run for which it began: peer and
operator messaging, nested agents (including the stop verb, which takes
an _agent_ id rather than a session), schedule and webhook creation, and
worktree switching. Before this flag was passed, a subagent reached all of
them — `--dangerously-skip-permissions` had removed the only thing that
would have asked, and `--allowedTools` would not have helped: it approves
prompts in advance rather than restricting anything.
worktree switching. Before the harness passed this flag, a subagent
reached all of them — `--dangerously-skip-permissions` had removed the
only thing that would have asked, and `--allowedTools` would not have
helped: it approves prompts in advance rather than restricting anything.
One rule worth knowing before editing any of this: **the daemon never
emits an empty `--tools` value**, and asserts rather than doing so. Not
because of what an empty value does — that's exactly the point. Our own
measurement and the installed `claude --help` disagree about whether
`--tools ""` means "no tools" or reads as the flag being absent, and the
answer belongs to whichever claude release is installed rather than to
this repo. Refusing the case is correct under either reading, so the code
answer belongs to whichever claude release the system has installed
rather than to this repo. Refusing the case is correct under either reading, so the code
never has to know which holds. Nothing here wants a subagent with no
built-in tools anyway.