docs: fix genuine passive-voice hits in docs/tools (hand-written files)

Read all 62 write-good.Passive hits across the 6 hand-written files in
docs/tools/ (bash.md, lifecycle.md, forge.md, hivectl.md, matrix.md,
scheduling.md) in context. Excludes forge-cli.md/hivectl-cli.md/
swarmctl-cli.md (57 more hits) -- those are CI-generated from the
clap doc-comment strings in hive-forge/hivectl/swarmctl, freshness-
checked against the committed markdown, so a fix there has to go in
the Rust source and get regenerated -- separate batch.

33 rewritten to active, actor usually already established in the same
paragraph or given via a 'by X' clause (the daemon, hive-c0re,
hive-forge, hivectl, hyperhive itself, or an established module name
like nix/agent-modules/mcp.nix). Several sibling-inconsistency fixes:
a passive clause next to an already-active sibling stating the same
fact (lifecycle.md's server-scoping sentence, forge.md's clone-derives
sentence, hivectl.md's daemon-hashes-passwords sentence, matrix.md's
daemon-upserts-a-todo paragraph).

29 left alone: no-X-is-Y / no-X-is-needed invariant idioms, config-state
conditionals (whenever/when X is set/configured/given), requirement-
list idiom, a false-positive tokenization (vale matching 'are read'
inside 'read-only'), definitional facts about CLI/attrset structure
with no real actor, hypothetical/counterfactual clauses describing a
rejected design alternative, a forward-looking not-yet-real removal,
compressed bullet-fragment conventions, and one deliberately-parallel
sentence structure left both halves alone to avoid breaking the
symmetry.

Verified via vale on the 6 touched files, diffed against main's exact
baseline (not just the Passive count): write-good.Passive 62 -> 29
exactly, every other category unchanged in count AND location
(TooWordy 16, Microsoft.We 1, Microsoft.FirstPerson 1, and the same
4 pre-existing Microsoft.Contractions errors at the same 4 lines).
This commit is contained in:
iris 2026-09-08 14:21:11 +02:00 committed by mara
commit 97e2a993e3
6 changed files with 49 additions and 49 deletions

View file

@ -25,14 +25,14 @@ delivered the terminal result inline, in which case no todo is created
- `wait_seconds` — inline poll before returning (capped at 30). - `wait_seconds` — inline poll before returning (capped at 30).
When the task finishes within the window the full status is When the task finishes within the window the full status is
returned immediately and no todo is created; when the window expires returned immediately and no todo is created; when the window expires
the task keeps running and the normal `task started: id=<id>` the task keeps running and the daemon returns the normal
response is returned. **Defaults to 3** — pass `wait_seconds: 0` `task started: id=<id>` response. **Defaults to 3** — pass `wait_seconds: 0`
to disable inline waiting and always get the immediate response. to disable inline waiting and always get the immediate response.
- `name` — optional caller-chosen task id. When set it replaces the - `name` — optional caller-chosen task id. When set it replaces the
autogenerated hex id, so it surfaces in `status(<name>)` lookups and autogenerated hex id, so it surfaces in `status(<name>)` lookups and
the loose-ends list — a memorable label instead of an opaque id. A name the loose-ends list — a memorable label instead of an opaque id. A name
is **reusable once its previous task has finished**; submitting a is **reusable once its previous task has finished**; the daemon
name whose task is still `pending`/`running` is rejected. Allowed rejects a name whose task is still `pending`/`running`. Allowed
characters: `[a-z0-9-]` (a valid identifier — lowercase, digits, characters: `[a-z0-9-]` (a valid identifier — lowercase, digits,
hyphen; max 63). Omit for the autogenerated id. hyphen; max 63). Omit for the autogenerated id.
@ -48,7 +48,7 @@ Poll the status of a task submitted with `run`. Returns:
- last 4 KiB of stdout and stderr (full output in the `.out` / `.err` files) - last 4 KiB of stdout and stderr (full output in the `.out` / `.err` files)
`wait_seconds` — optional inline poll (capped at 30): when the task `wait_seconds` — optional inline poll (capped at 30): when the task
finishes within the window the full status is returned immediately. finishes within the window the call returns the full status immediately.
Useful to avoid a separate round-trip when the task is expected to Useful to avoid a separate round-trip when the task is expected to
finish soon. finish soon.
@ -77,7 +77,7 @@ in the agent's loose-ends; handle it on a future turn.
- `force: true` — SIGKILL. - `force: true` — SIGKILL.
If a SIGINT'd task doesn't exit, call `kill` again with `force: true`. If a SIGINT'd task doesn't exit, call `kill` again with `force: true`.
A still-pending task is cancelled before it starts. The task ends as The daemon cancels a still-pending task before it starts. The task ends as
`killed` and surfaces in the loose-ends like any completion. `killed` and surfaces in the loose-ends like any completion.
Exposed as `mcp__bash__kill`. Exposed as `mcp__bash__kill`.
@ -86,7 +86,7 @@ Exposed as `mcp__bash__kill`.
`run` and `status` live in the `bash` MCP server, not `hyperhive`. The `run` and `status` live in the `bash` MCP server, not `hyperhive`. The
tool names in claude are `mcp__bash__run` and `mcp__bash__status`. tool names in claude are `mcp__bash__run` and `mcp__bash__status`.
The `Bash` built-in tool is blocked — all shell execution goes through hyperhive blocks the `Bash` built-in tool — all shell execution goes through
this structured path so tasks get task-id tracking and structured output. this structured path so tasks get task-id tracking and structured output.
## Architecture ## Architecture
@ -109,8 +109,8 @@ When a bash task changes state, `hive-bash-daemon` upserts a single keyed
todo (`key = task id`) on the harness's in-agent socket (`HIVE_AGENT_SOCKET`) todo (`key = task id`) on the harness's in-agent socket (`HIVE_AGENT_SOCKET`)
— "running" at start, then the completion summary when it finishes. The — "running" at start, then the completion summary when it finishes. The
summary change signals the harness turn loop directly (in-process, no broker summary change signals the harness turn loop directly (in-process, no broker
round-trip), so the agent is driven a turn to handle it via `get_loose_ends`, round-trip), so the harness drives a turn for the agent to handle it via
then clears the todo with `cancel_loose_end(kind: "todo", id: N)` (dials the `get_loose_ends`, then clears the todo with `cancel_loose_end(kind: "todo", id: N)` (dials the
in-container socket directly — no bash task involved, so clearing doesn't in-container socket directly — no bash task involved, so clearing doesn't
spawn another todo; see #2639). Same mechanism the matrix daemon uses for spawn another todo; see #2639). Same mechanism the matrix daemon uses for
unread rooms. An inline `wait_seconds` / `status` observation that already unread rooms. An inline `wait_seconds` / `status` observation that already
@ -123,5 +123,5 @@ loose-end follows.
`tools()` returns `["run", "status"]` which the harness expands to `tools()` returns `["run", "status"]` which the harness expands to
`mcp__hyperhive__run` / `mcp__hyperhive__status` — tools that don't `mcp__hyperhive__run` / `mcp__hyperhive__status` — tools that don't
exist in the hyperhive MCP server (dead entries). Removing `execution` exist in the hyperhive MCP server (dead entries). Removing `execution`
from an agent's groups has no effect on bash availability. Bash is from an agent's groups has no effect on bash availability.
registered separately via the `extraMcpServers` path described above. `nix/agent-modules/mcp.nix` registers Bash separately via the `extraMcpServers` path described above.

View file

@ -22,7 +22,7 @@ markdown-docs > docs/tools/forge-cli.md`.
## Verbs ## Verbs
**Kind-namespaced commands (preferred):** issue/PR operations are grouped **Kind-namespaced commands (preferred):** hive-forge groups issue/PR operations
under `issue` and `pr` parent commands — `hive-forge pr close 42`, under `issue` and `pr` parent commands — `hive-forge pr close 42`,
`hive-forge issue create --title …`, `hive-forge pr status --pr 42`. The `hive-forge issue create --title …`, `hive-forge pr status --pr 42`. The
`pr <verb>` / `issue <verb>` forms validate the number's kind (for example `pr close` `pr <verb>` / `issue <verb>` forms validate the number's kind (for example `pr close`
@ -172,7 +172,7 @@ hive-forge -r internal/knowledge pr-create --agit \
``` ```
`clone` derives the dest dir from the repo basename (override with a `clone` derives the dest dir from the repo basename (override with a
positional arg); `--branch` / `--depth` are passed through. The clone positional arg); it passes `--branch` / `--depth` through. The clone
URL and the `origin` remote it leaves behind carry no credentials — URL and the `origin` remote it leaves behind carry no credentials —
`clone` instead configures `origin`'s `credential.helper` to invoke `clone` instead configures `origin`'s `credential.helper` to invoke
`hive-forge credential-helper` (a hidden verb, not meant to be run by `hive-forge credential-helper` (a hidden verb, not meant to be run by
@ -224,8 +224,8 @@ scope. Two paths exist depending on where the repo should live:
**Agent repos (`agents/<name>`)** — Use the `mcp__hyperhive__create_repo` **Agent repos (`agents/<name>`)** — Use the `mcp__hyperhive__create_repo`
MCP tool (requires the `forge` tool group). hive-c0re creates the repo in MCP tool (requires the `forge` tool group). hive-c0re creates the repo in
the c0re-owned `agents/` org, adds you as a write collaborator (not the c0re-owned `agents/` org, adds you as a write collaborator (not
owner), and enables branch protection (operator-team merge approval owner), enables branch protection (operator-team merge approval
required — you can't self-merge). Clone URL is returned immediately. required — you can't self-merge), and returns the clone URL immediately.
This is the standard path for agents that need a working repo. This is the standard path for agents that need a working repo.
**Other repos** — Use the CLI verbs below (`repo-create` / `repo-add-collaborator`). **Other repos** — Use the CLI verbs below (`repo-create` / `repo-add-collaborator`).
@ -245,8 +245,8 @@ and print its URL. Key flags:
active repo (see the repo-resolution chain above). Companion to active repo (see the repo-resolution chain above). Companion to
`repo-create`. The `repo-create`. The
`--permission` flag accepts `read` / `write` (default) / `admin`. `--permission` flag accepts `read` / `write` (default) / `admin`.
`hive-c0re` uses this internally when an agent's config repo is `hive-c0re` uses this internally when it initialises an agent's config
initialised. repo.
**`repo-labels [PATTERN]`** — list every label defined on the repo, **`repo-labels [PATTERN]`** — list every label defined on the repo,
optionally filtered by a name substring (case-sensitive). Distinct from optionally filtered by a name substring (case-sensitive). Distinct from
@ -272,7 +272,7 @@ to discover valid label names before triaging or to audit the label set.
- `artifact-get <name> --run <n>` downloads a CI Actions artifact. `<n>` - `artifact-get <name> --run <n>` downloads a CI Actions artifact. `<n>`
is the run number from the run-page URL (`/actions/runs/<n>`, which is the run number from the run-page URL (`/actions/runs/<n>`, which
`pr-status` surfaces as a CI context's target_url). Forgejo 15 serves `pr-status` surfaces as a CI context's target_url). Forgejo 15 serves
artifacts only via the web route, not REST, and that route is keyed by artifacts only via the web route, not REST, and keys that route by
the run's internal global id, so the verb translates the run number the run's internal global id, so the verb translates the run number
first. Saves a zip to `/tmp/forge-artifact-<name>.zip` by default; pass first. Saves a zip to `/tmp/forge-artifact-<name>.zip` by default; pass
`-o -` to stream to stdout. `-o -` to stream to stdout.
@ -280,9 +280,9 @@ to discover valid label names before triaging or to audit the label set.
run's job step logs. `<n>` is the run number from the run-page URL run's job step logs. `<n>` is the run number from the run-page URL
(same value `artifact-get` takes; `pr-status` surfaces it as a CI (same value `artifact-get` takes; `pr-status` surfaces it as a CI
context's target_url). Two log sources, tried in **completeness context's target_url). Two log sources, tried in **completeness
order**: the **durable persisted-log download** the run page's "view order**: the verb tries the **durable persisted-log download** the run page's "view
raw logs" link uses (`…/runs/<n>/jobs/<job>/attempt/<a>/logs`, a flat raw logs" link uses (`…/runs/<n>/jobs/<job>/attempt/<a>/logs`, a flat
whole-job log) is tried first — complete once it exists, which covers whole-job log) first — complete once it exists, which covers
any run that has already finished; it's only absent while the job is any run that has already finished; it's only absent while the job is
still running, in which case the verb falls back to the web run-view still running, in which case the verb falls back to the web run-view
**streamer** the run page polls (rich per-step framing, but only a **streamer** the run page polls (rich per-step framing, but only a
@ -324,7 +324,7 @@ to discover valid label names before triaging or to audit the label set.
extra request per comment, no server-side inline count). `reaction extra request per comment, no server-side inline count). `reaction
<n> --list-allowed` prints the instance's actual configured shortcode <n> --list-allowed` prints the instance's actual configured shortcode
list (`GET /settings/ui`'s `allowed_reactions`) instead of guessing — list (`GET /settings/ui`'s `allowed_reactions`) instead of guessing —
instance-global, `<n>`/`--comment` are ignored on this path. instance-global, this path ignores `<n>`/`--comment`.
- Do NOT use raw `curl` for forge access -- the CLI handles auth, - Do NOT use raw `curl` for forge access -- the CLI handles auth,
error checking, and output formatting. error checking, and output formatting.
- `issue-create --label <name>` / `pr-create --label <name>` are - `issue-create --label <name>` / `pr-create --label <name>` are
@ -332,8 +332,8 @@ to discover valid label names before triaging or to audit the label set.
unknown name is an error, not a silent drop** — the command fails unknown name is an error, not a silent drop** — the command fails
listing the names that didn't resolve plus every label the repo has, listing the names that didn't resolve plus every label the repo has,
so it's fixable from the message without a second call. On so it's fixable from the message without a second call. On
`pr-create --agit`, labels are applied as a follow-up call once the `pr-create --agit`, hive-forge applies labels as a follow-up call once
PR number is parsed back out of the push output (the AGit push it parses the PR number back out of the push output (the AGit push
itself has no label field), so they're silently skipped if that itself has no label field), so they're silently skipped if that
parse fails — same fallback as the deferred multi-line body. parse fails — same fallback as the deferred multi-line body.
- `list --label <name>` / `list --milestone <name>` are repeatable and - `list --label <name>` / `list --milestone <name>` are repeatable and

View file

@ -40,13 +40,13 @@ hivectl forge reconcile-config iris --verbose # include the full diff, not
``` ```
- For **agents** (name has a state dir under `/var/lib/hyperhive/agents/`): - For **agents** (name has a state dir under `/var/lib/hyperhive/agents/`):
token is persisted to `<state>/forge-token`. Re-running refreshes the `create-user` persists the token to `<state>/forge-token`. Re-running refreshes the
token (idempotent — scope always matches current `TOKEN_SCOPES`). token (idempotent — scope always matches current `TOKEN_SCOPES`).
- For **non-agents** (humans): creates the account and prints the token to - For **non-agents** (humans): creates the account and prints the token to
stdout; no state dir is created. Re-running after account already exists stdout; no state dir is created. Re-running after account already exists
re-mints the token and prints it again — safe for password resets. re-mints the token and prints it again — safe for password resets.
- Without `--password` / `--password-stdin` a random throwaway password - Without `--password` / `--password-stdin` `create-user` uses a random
is used (fine for agents — they auth by token). throwaway password (fine for agents — they auth by token).
- `reconcile-config <agent>` shows the divergence between the agent's local - `reconcile-config <agent>` shows the divergence between the agent's local
applied config checkout and its forge `agent-configs/<agent>` `main`, then applied config checkout and its forge `agent-configs/<agent>` `main`, then
reconciles. `--from forge` resets the local checkout to forge `main` (takes reconciles. `--from forge` resets the local checkout to forge `main` (takes
@ -125,8 +125,8 @@ hivectl gateway delete-user bob # remove user
hivectl gateway list-users # list all usernames, one per line hivectl gateway list-users # list all usernames, one per line
``` ```
Passwords are hashed with BCrypt (cost 12) by the daemon. The file is The daemon hashes passwords with BCrypt (cost 12). It creates the file
created if it doesn't exist. Re-running `create-user` with the same if it doesn't exist. Re-running `create-user` with the same
username updates the password hash in place. username updates the password hash in place.
## Agents ## Agents
@ -175,8 +175,8 @@ resume drains the backlog rather than dropping it. Points worth knowing:
_stopped_ agent makes it come up parked. _stopped_ agent makes it come up parked.
- **Not a DAG.** Unlike `restart`/`stop`, there's no container operation - **Not a DAG.** Unlike `restart`/`stop`, there's no container operation
to sequence, so it applies immediately with nothing to wait on. to sequence, so it applies immediately with nothing to wait on.
- **Stopping a paused agent is still fast.** The graceful-stop - **Stopping a paused agent is still fast.** hivectl skips the graceful-stop
handshake is skipped for a paused agent (it would never answer), which handshake for a paused agent (it would never answer), which
is safe precisely because the pause check sits at the top of the loop: is safe precisely because the pause check sits at the top of the loop:
a paused agent has no turn in flight to checkpoint. a paused agent has no turn in flight to checkpoint.
- Visible as ` paused` in `list-agents`'s STATUS column, as a `paused` - Visible as ` paused` in `list-agents`'s STATUS column, as a `paused`
@ -196,15 +196,15 @@ Overrides the hive-wide `services.hyperhive.c0re.agentCpuQuota` /
[`persistence.md`](../agent-lifecycle/persistence.md)). Values are systemd's [`persistence.md`](../agent-lifecycle/persistence.md)). Values are systemd's
`CPUQuota=` / `MemoryMax=` syntax: a percentage (`400%` = four full `CPUQuota=` / `MemoryMax=` syntax: a percentage (`400%` = four full
cores) for CPU; a size (`8G`), a percentage of physical RAM, or cores) for CPU; a size (`8G`), a percentage of physical RAM, or
`infinity` for memory. Both are validated before they're persisted `infinity` for memory. `set-limits` validates both before persisting them
they go into a systemd drop-in verbatim, and a typo there makes the they go into a systemd drop-in verbatim, and a typo there makes the
unit fail to start. unit fail to start.
**Declarative, not incremental**: each invocation replaces the agent's **Declarative, not incremental**: each invocation replaces the agent's
whole entry. `set-limits sock --memory-max 8G` leaves `sock` with _only_ whole entry. `set-limits sock --memory-max 8G` leaves `sock` with _only_
a memory override, reverting any previously set CPU quota to the hive a memory override, reverting any previously set CPU quota to the hive
default. To avoid a forgotten flag silently wiping an override, a bare default. To avoid a forgotten flag silently wiping an override, hivectl
`set-limits <name>` with no flags is rejected — clearing requires the rejects a bare `set-limits <name>` with no flags — clearing requires the
explicit `--reset`. explicit `--reset`.
The command rewrites the container's drop-in and reloads systemd, so The command rewrites the container's drop-in and reloads systemd, so
@ -226,7 +226,7 @@ before you were added to `hive-admin` won't see it until you log back in
It also needs the daemon socket, unlike the other exec-into-a-container It also needs the daemon socket, unlike the other exec-into-a-container
paths: the "is this actually an agent?" pre-flight reads the agents root, paths: the "is this actually an agent?" pre-flight reads the agents root,
which is owned by the daemon's user and not group-readable, so the check which the daemon's user owns and which isn't group-readable, so the check
is a `HostRequest` rather than a local `stat`. A rootless `choom` therefore is a `HostRequest` rather than a local `stat`. A rootless `choom` therefore
tells you it needs root, instead of reporting a permission problem with tells you it needs root, instead of reporting a permission problem with
the state dir. the state dir.
@ -308,13 +308,13 @@ hivectl open forge # the forge (Forgejo) web UI
hivectl open matrix # the matrix GUI (fluffychat) hivectl open matrix # the matrix GUI (fluffychat)
``` ```
The URL is resolved from the running daemon (`HostRequest::Urls`), which hivectl resolves the URL from the running daemon (`HostRequest::Urls`), which
reads the per-surface public URLs from c0re's service env — so custom reads the per-surface public URLs from c0re's service env — so custom
forge / matrix domains resolve correctly instead of assuming forge / matrix domains resolve correctly instead of assuming
`forge.<domain>`. The URL is **always printed** (the reliable core, since `forge.<domain>`. The URL is **always printed** (the reliable core, since
the host is typically headless / driven over SSH), then `xdg-open` is tried the host is typically headless / driven over SSH), then hivectl tries
as a convenience — a missing or failing opener is reported as a note, not `xdg-open` as a convenience, reporting a missing or failing opener as a
an error. note, not an error.
A surface has no URL when it isn't browser-reachable: `home` needs A surface has no URL when it isn't browser-reachable: `home` needs
`services.hyperhive.domain`; `forge` needs `services.hyperhive.domain`; `forge` needs

View file

@ -1,8 +1,8 @@
# Lifecycle and approvals tools # Lifecycle and approvals tools
Two tool groups govern agent lifecycle management and config changes. Two tool groups govern agent lifecycle management and config changes.
Both are scoped to **direct children only** (topology-enforced: the The server scopes both to **direct children only** (topology-enforced: it
server rejects any name that's not a direct child of the calling rejects any name that's not a direct child of the calling
agent per `topology.json`). Privileged agents (for example ruth) may operate agent per `topology.json`). Privileged agents (for example ruth) may operate
on any sub-agent — the topology scope applies to all others. on any sub-agent — the topology scope applies to all others.

View file

@ -110,8 +110,8 @@ Incoming room events wake the agent via `AgentRequest::Wake` with
bulleted list (`- <room>: <sender>: <body>` or `- <room>: N unread` bulleted list (`- <room>: <sender>: <body>` or `- <room>: N unread`
per room) per room)
The same per-room breakdown is included in the `UnreadMatrix` entry hive-matrix-daemon includes the same per-room breakdown in the `UnreadMatrix`
returned by `get_loose_ends` so unread rooms surface in the entry `get_loose_ends` returns, so unread rooms surface in the
loose-ends list between turns. loose-ends list between turns.
**Invite wakes**: the daemon sweeps `invited_rooms()` after every sync **Invite wakes**: the daemon sweeps `invited_rooms()` after every sync
@ -123,8 +123,8 @@ in-agent socket, which drives a turn. The daemon does **not**
autojoin — the agent calls `list_invites` to see pending invites and autojoin — the agent calls `list_invites` to see pending invites and
`resolve_invite` to accept or reject them. `resolve_invite` to accept or reject them.
**Pending invites as loose ends**: pending invites are upserted as **Pending invites as loose ends**: the daemon upserts pending invites as
keyed todos and appear in `get_loose_ends` output as keyed todos, which appear in `get_loose_ends` output as
`[matrix] invited to <room> (<room_id>) — use list_invites to see `[matrix] invited to <room> (<room_id>) — use list_invites to see
pending invites, resolve_invite to accept or reject`. The keyed todo pending invites, resolve_invite to accept or reject`. The keyed todo
is cleared when a `resolve_invite` (or `join_room`) call resolves the is cleared when a `resolve_invite` (or `join_room`) call resolves the
@ -146,8 +146,8 @@ merges every entry into `--mcp-config` (under `mcpServers.<key>`)
and `--allowedTools` (as `mcp__<key>__<pattern>`). and `--allowedTools` (as `mcp__<key>__<pattern>`).
The agent's `flake.nix` forwards every flake input to `agent.nix` as The agent's `flake.nix` forwards every flake input to `agent.nix` as
the `flakeInputs` module arg, so external MCP-server flakes are pulled the `flakeInputs` module arg, so you pull in external MCP-server flakes
in by adding them to `inputs.*` and referenced as by adding them to `inputs.*` and reference them as
`flakeInputs.<name>.packages.${pkgs.system}.default` — the resolved `flakeInputs.<name>.packages.${pkgs.system}.default` — the resolved
sha lands in the agent's own `flake.lock` and rolls up to meta's. sha lands in the agent's own `flake.lock` and rolls up to meta's.

View file

@ -12,7 +12,7 @@ your topology subtree.
### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)` ### `request_schedule_prompt(targets, body, first_fire_at_unix, interval_seconds?, description?)`
Queue an operator-approval for a scheduled prompt. On approve, Queue an operator-approval for a scheduled prompt. On approve,
`body` is fanned out to each agent in `targets` at hive-c0re fans `body` out to each agent in `targets` at
`first_fire_at_unix` (Unix timestamp). Recurring when `interval_seconds` `first_fire_at_unix` (Unix timestamp). Recurring when `interval_seconds`
is set, one-shot otherwise. is set, one-shot otherwise.
@ -42,8 +42,8 @@ autocancels when every target is removed).
### `fire_schedule_now(id)` ### `fire_schedule_now(id)`
Fire a scheduled prompt out of band immediately. Recurring schedules Fire a scheduled prompt out of band immediately. Recurring schedules
keep their cadence — the manual fire is additive. One-shot schedules keep their cadence — the manual fire is additive. The manual fire
are consumed by the manual fire and cancelled afterwards. consumes one-shot schedules and cancels them afterwards.
### `list_schedules()` ### `list_schedules()`