docs: fix genuine passive-voice hits in docs/process
Fourth batch of hyperhive#4042's Passive pass (see #4098/#4099/#4100 for the first three and the read-every-hit discipline this pass uses). 44 hits across pr-review-gate.md (4), conventions.md (18), and gotchas.md (22) -- highest genuine-catch rate so far, 23/44 (~52%), because this architecture/mechanism documentation has a lot of "X does Y via Z" sentences where the actor is already named parenthetically or in a nearby clause -- the single most productive rewrite shape across every batch so far. Recurring rewrite shapes this batch: - Actor already named in the same sentence, just not as the grammatical subject: "X is configured per repo in its branch-protection settings" -> "Each repo's branch-protection settings configure X" (pr-review-gate.md); "the broker" (reserved names), "rsvg-convert" (PNG rendering), "the website repo" (HTML/CSS rendering), "systemd.globalEnvironment" (D-Bus address export), and several more -- all the same shape. - Subject already established one clause or one sentence earlier, just needs continuing rather than restarting with a new passive subject: "the harness reads HIVE_TOOL_GROUPS (...). Unrecognised tokens are logged and skipped." -> "...logging and skipping unrecognised tokens" (continues "the harness"), same pattern twice more (job_queue::templates::rebuild, HIVE_CAPABILITIES resolution). - Sibling-inconsistency: a bolded lead-in bullet was the one passive sentence in an otherwise-active paragraph/table (the read_host_journal capability row sat between two "may X" rows; the HTML+CSS bullet's own tail clauses were already active voice around the one passive lead phrase). - One caught-and-fixed authoring mistake worth noting for future passes: the first attempt at the "Nix treats X as a package" rewrite landed in the wrong sentence (a similarly-worded but unrelated passage two paragraphs up) -- caught by re-reading the diff before running vale, not by vale itself (which would have shown 0 remaining hits either way, since the intended sentence's hit just wouldn't have been touched -- a silently-wrong edit vale's own count can't catch). Re-reading the actual diff, not just trusting the before/ after hit count, is what caught it. 21 of 44 left alone -- same recurring legitimate shapes as prior batches (predicate-adjective copulas, quoted/literal text, generic- actor statements, negative-capability invariants, "is tracked/rooted/ scoped at X" property-description idioms, and two more thesis- statement headings matching the "Ownership is declared, not repaired" precedent from #4100). Verified: vale docs/process before/after -- 44 -> 21 write-good.Passive hits, exactly the 23 rewritten, re-read every changed line's full surrounding context after editing (not just the vale count) to catch exactly the kind of misplaced-edit mistake described above.
This commit is contained in:
parent
461c599e09
commit
c41c67c949
3 changed files with 37 additions and 38 deletions
|
|
@ -77,7 +77,7 @@ namespace, not the wire surface.
|
||||||
|
|
||||||
## Recipient sentinels
|
## Recipient sentinels
|
||||||
|
|
||||||
A few recipient names are reserved by the broker and have special
|
The broker reserves a few recipient names, which have special
|
||||||
meaning that ordinary agent labels can never collide with — agent
|
meaning that ordinary agent labels can never collide with — agent
|
||||||
name validation rejects any character outside `[a-z0-9_-]`, so the
|
name validation rejects any character outside `[a-z0-9_-]`, so the
|
||||||
angle-bracket and asterisk shapes below are structurally safe.
|
angle-bracket and asterisk shapes below are structurally safe.
|
||||||
|
|
@ -94,7 +94,7 @@ angle-bracket and asterisk shapes below are structurally safe.
|
||||||
propagates with zero agent-side restart.
|
propagates with zero agent-side restart.
|
||||||
- `<children>` — fan-out to every direct descendant of the sender per
|
- `<children>` — fan-out to every direct descendant of the sender per
|
||||||
`topology.json`. Resolved in `socket_server::handle_send` via
|
`topology.json`. Resolved in `socket_server::handle_send` via
|
||||||
`topology::children_of(sender)`: one message is delivered to each
|
`topology::children_of(sender)`: it delivers one message to each
|
||||||
child, bypassing the allow-list check (structural fan-out targets are
|
child, bypassing the allow-list check (structural fan-out targets are
|
||||||
never user-listed peers). No-op for leaf agents (returns `Ok` when the
|
never user-listed peers). No-op for leaf agents (returns `Ok` when the
|
||||||
child set is empty). Lets a sub-manager nudge its subtree without
|
child set is empty). Lets a sub-manager nudge its subtree without
|
||||||
|
|
@ -211,8 +211,8 @@ Per-variant fields:
|
||||||
and not counted.
|
and not counted.
|
||||||
- `UnreadMatrix { rooms, summary }` — unread matrix notifications.
|
- `UnreadMatrix { rooms, summary }` — unread matrix notifications.
|
||||||
Informational + not cancellable (clear with `mark_read`). Unlike
|
Informational + not cancellable (clear with `mark_read`). Unlike
|
||||||
the others this is injected by the in-container harness, not
|
the others, the in-container harness injects this, not hive-c0re,
|
||||||
hive-c0re, because the matrix daemon lives inside the agent.
|
because the matrix daemon lives inside the agent.
|
||||||
|
|
||||||
`age_seconds` saturates at zero on any clock anomaly (back-step,
|
`age_seconds` saturates at zero on any clock anomaly (back-step,
|
||||||
unsynchronised wall clock, etc.) so the bulleted list never
|
unsynchronised wall clock, etc.) so the bulleted list never
|
||||||
|
|
@ -299,8 +299,8 @@ JSON-line protocol with their own result types; RFC 9457 is an HTTP format.
|
||||||
|
|
||||||
## Tool groups
|
## Tool groups
|
||||||
|
|
||||||
The MCP tool surface an agent receives is derived from a set of named
|
A set of named `ToolGroup` values (`hive_sh4re::permissions::ToolGroup`)
|
||||||
`ToolGroup` values (`hive_sh4re::permissions::ToolGroup`), not from a hardcoded
|
determines the MCP tool surface an agent receives, not a hardcoded
|
||||||
binary flavor.
|
binary flavor.
|
||||||
|
|
||||||
| Group | Tools |
|
| Group | Tools |
|
||||||
|
|
@ -316,9 +316,9 @@ binary flavor.
|
||||||
| `forge` | `create_repo` — create git repos through hive-c0re (operator-gated merge) |
|
| `forge` | `create_repo` — create git repos through hive-c0re (operator-gated merge) |
|
||||||
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
|
| `web_tools` | none (gates the Claude built-ins `WebFetch`/`WebSearch`, not an MCP tool) |
|
||||||
|
|
||||||
**Always-on tools** — `set_status`, `compact`, and `mark_todos_done` are
|
**Always-on tools** — `ToolGroup::ALWAYS_ON_TOOLS` exposes `set_status`,
|
||||||
exposed to every agent regardless of which groups it holds
|
`compact`, and `mark_todos_done` to every agent regardless of which
|
||||||
(`ToolGroup::ALWAYS_ON_TOOLS`). The operator dashboard depends on every agent
|
groups it holds. The operator dashboard depends on every agent
|
||||||
being able to report its status chip, and the server-side `SetStatus` handler
|
being able to report its status chip, and the server-side `SetStatus` handler
|
||||||
has no tool-group check (only length validation), so gating it would only
|
has no tool-group check (only length validation), so gating it would only
|
||||||
desync the `--allowedTools` list from what the host actually accepts.
|
desync the `--allowedTools` list from what the host actually accepts.
|
||||||
|
|
@ -343,11 +343,11 @@ the new `HIVE_TOOL_GROUPS` env var. Agents with no entry get no var.
|
||||||
|
|
||||||
**Runtime resolution** — at session start the harness reads `HIVE_TOOL_GROUPS`
|
**Runtime resolution** — at session start the harness reads `HIVE_TOOL_GROUPS`
|
||||||
(a comma-separated list of snake_case group names injected by the meta renderer
|
(a comma-separated list of snake_case group names injected by the meta renderer
|
||||||
from `tool-groups.json`). Unrecognised tokens are logged and skipped. Falls back
|
from `tool-groups.json`), logging and skipping unrecognised tokens. Falls back
|
||||||
to `ToolGroup::AGENT_DEFAULT` (`messaging`, `meta`, `inbox`, `execution`) when
|
to `ToolGroup::AGENT_DEFAULT` (`messaging`, `meta`, `inbox`, `execution`) when
|
||||||
the var is absent or empty.
|
the var is absent or empty.
|
||||||
|
|
||||||
**Updating the surface** — when a new `#[tool]` fn is added to `AgentServer`
|
**Updating the surface** — when you add a new `#[tool]` fn to `AgentServer`
|
||||||
in `hive-agent-mcp/src/mcp/mod.rs`, add its name to the matching `ToolGroup::tools()`
|
in `hive-agent-mcp/src/mcp/mod.rs`, add its name to the matching `ToolGroup::tools()`
|
||||||
slice in `hive-sh4re/src/permissions.rs`. That's the single source of truth;
|
slice in `hive-sh4re/src/permissions.rs`. That's the single source of truth;
|
||||||
`mcp_config::allowed_mcp_tools` (in `hive-agent/src/mcp_config.rs`) reads it at
|
`mcp_config::allowed_mcp_tools` (in `hive-agent/src/mcp_config.rs`) reads it at
|
||||||
|
|
@ -363,7 +363,7 @@ that allows the underlying resource access.
|
||||||
| Capability | Effect |
|
| Capability | Effect |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `manage_root_agent` | may lifecycle-manage the root/manager agent via `kill`/`start`/`restart` |
|
| `manage_root_agent` | may lifecycle-manage the root/manager agent via `kill`/`start`/`restart` |
|
||||||
| `read_host_journal` | `get_host_journal` MCP tool is registered + `GET /journal-host` requests are served |
|
| `read_host_journal` | registers the `get_host_journal` MCP tool + serves `GET /journal-host` requests |
|
||||||
| `query_agent_state` | may call `get_loose_ends` / `CountPendingReminders` targeting non-child agents |
|
| `query_agent_state` | may call `get_loose_ends` / `CountPendingReminders` targeting non-child agents |
|
||||||
|
|
||||||
**Config storage** — per-agent capabilities live in
|
**Config storage** — per-agent capabilities live in
|
||||||
|
|
@ -381,8 +381,8 @@ After a change `meta::sync_agents` commits the updated file; the next agent
|
||||||
rebuild picks up the new `HIVE_CAPABILITIES` env var.
|
rebuild picks up the new `HIVE_CAPABILITIES` env var.
|
||||||
|
|
||||||
**Runtime resolution** — at session start the harness reads `HIVE_CAPABILITIES`
|
**Runtime resolution** — at session start the harness reads `HIVE_CAPABILITIES`
|
||||||
and resolves each token to a `Capability` variant. Unrecognised tokens are
|
and resolves each token to a `Capability` variant, logging and skipping
|
||||||
logged and skipped. An absent or empty var means no extra capabilities.
|
unrecognised ones. An absent or empty var means no extra capabilities.
|
||||||
|
|
||||||
**Capability NOT configurable from `agent.nix`** — same reasoning as tool
|
**Capability NOT configurable from `agent.nix`** — same reasoning as tool
|
||||||
groups: an agent that could grant its own capabilities via a config commit would
|
groups: an agent that could grant its own capabilities via a config commit would
|
||||||
|
|
@ -416,11 +416,11 @@ via `snapshotOpenDetails` / `restoreOpenDetails`.
|
||||||
## `rebuild` is the reconcile verb
|
## `rebuild` is the reconcile verb
|
||||||
|
|
||||||
`job_queue::templates::rebuild` builds the DAG that reconciles a
|
`job_queue::templates::rebuild` builds the DAG that reconciles a
|
||||||
container to its wanted state: `write_dropins` (the nspawn-conf
|
container to its wanted state: it folds `write_dropins` (the nspawn-conf
|
||||||
rewrite — `PRIVATE_NETWORK=1`, `HOST_ADDRESS` = the bridge gateway IP,
|
rewrite — `PRIVATE_NETWORK=1`, `HOST_ADDRESS` = the bridge gateway IP,
|
||||||
sets `EXTRA_NSPAWN_FLAGS` — plus the systemd resource-limits drop-in)
|
sets `EXTRA_NSPAWN_FLAGS` — plus the systemd resource-limits drop-in)
|
||||||
is folded into the `Swap` node, then `nixos-container update` + stop +
|
into the `Swap` node, then runs `nixos-container update` + stop +
|
||||||
start runs across the `StopForUpdate → Swap → RebuildBookkeeping`
|
start across the `StopForUpdate → Swap → RebuildBookkeeping`
|
||||||
brace and the tail `Reconcile` node. `flake.nix` itself is no longer
|
brace and the tail `Reconcile` node. `flake.nix` itself is no longer
|
||||||
regenerated host-side on rebuild — it's tracked in the agent's
|
regenerated host-side on rebuild — it's tracked in the agent's
|
||||||
proposed/applied repos and rides along on every fetch (see
|
proposed/applied repos and rides along on every fetch (see
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ Two things to get right when a daemon needs outbound TCP:
|
||||||
works until DNS hands back the other family;
|
works until DNS hands back the other family;
|
||||||
- list `AF_NETLINK` too. glibc's `getaddrinfo` opens a netlink socket to
|
- list `AF_NETLINK` too. glibc's `getaddrinfo` opens a netlink socket to
|
||||||
enumerate local addresses before it returns any, so name resolution
|
enumerate local addresses before it returns any, so name resolution
|
||||||
fails without it even when `AF_INET` is allowed.
|
fails without it even when the unit allows `AF_INET`.
|
||||||
|
|
||||||
**The directive is a claim about what the program does, and nothing
|
**The directive is a claim about what the program does, and nothing
|
||||||
re-checks it when the program changes.** A unit that only served a unix
|
re-checks it when the program changes.** A unit that only served a unix
|
||||||
|
|
@ -143,15 +143,15 @@ to options the operator writes: **any** option of type `package` fed a
|
||||||
store-path _string_ coerces through `lib.toDerivation`, i.e.
|
store-path _string_ coerces through `lib.toDerivation`, i.e.
|
||||||
`builtins.storePath`. `environment.systemPackages` and
|
`builtins.storePath`. `environment.systemPackages` and
|
||||||
`systemd.services.<name>.path` both do it (the latter takes plain
|
`systemd.services.<name>.path` both do it (the latter takes plain
|
||||||
strings like `/run/wrappers` happily, but anything under
|
strings like `/run/wrappers` happily, but Nix treats anything under
|
||||||
`builtins.storeDir` is treated as a package). A path handed to the
|
`builtins.storeDir` as a package). A path handed to the
|
||||||
container as text has to be wrapped in a real derivation — a symlink
|
container as text has to be wrapped in a real derivation — a symlink
|
||||||
farm built from the interpolated string — before it can go anywhere a
|
farm built from the interpolated string — before it can go anywhere a
|
||||||
package is expected.
|
package is expected.
|
||||||
|
|
||||||
The catch is that a path written into a generated flake is text, not a
|
The catch is that a path written into a generated flake is text, not a
|
||||||
reference — the container's closure doesn't keep the binary alive.
|
reference — the container's closure doesn't keep the binary alive.
|
||||||
The **host** does: the package is interpolated into
|
The **host** does: it interpolates the package into
|
||||||
`/etc/hyperhive/serve.json`, so it lands in the host's system closure
|
`/etc/hyperhive/serve.json`, so it lands in the host's system closure
|
||||||
and is gc-rooted by the running generation. `builtins.toJSON` preserves
|
and is gc-rooted by the running generation. `builtins.toJSON` preserves
|
||||||
string context, which is the load-bearing detail; discard the context
|
string context, which is the load-bearing detail; discard the context
|
||||||
|
|
@ -204,14 +204,14 @@ the `TIME_WAIT` case from a clean previous exit; retry covers the
|
||||||
genuine "previous process is still alive during a systemd restart
|
genuine "previous process is still alive during a systemd restart
|
||||||
overlap" case. REUSEADDR does **not** allow two simultaneous
|
overlap" case. REUSEADDR does **not** allow two simultaneous
|
||||||
`LISTEN` sockets on the same port (that would be `SO_REUSEPORT`,
|
`LISTEN` sockets on the same port (that would be `SO_REUSEPORT`,
|
||||||
which we don't use) — exclusivity is preserved.
|
which we don't use) — it preserves exclusivity.
|
||||||
|
|
||||||
## Approvals
|
## Approvals
|
||||||
|
|
||||||
### Orphan approvals
|
### Orphan approvals
|
||||||
|
|
||||||
If state dirs are wiped out from under a pending approval (test
|
If test scripts or a manual `rm -rf` wipe state dirs out from under a
|
||||||
scripts, manual `rm -rf`), the dashboard's next render marks them
|
pending approval, the dashboard's next render marks them
|
||||||
`failed` with note `"agent state dir missing"` so they fall out of
|
`failed` with note `"agent state dir missing"` so they fall out of
|
||||||
`pending`. They stay in sqlite for audit.
|
`pending`. They stay in sqlite for audit.
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ rust build's `src` was the whole repo tree, any tweak to
|
||||||
invalidated the cargo cache and forced a full rebuild. crane (and
|
invalidated the cargo cache and forced a full rebuild. crane (and
|
||||||
naersk before it) couldn't see "these inputs are unused by rust" on
|
naersk before it) couldn't see "these inputs are unused by rust" on
|
||||||
its own — the split breaks the coupling at the derivation boundary.
|
its own — the split breaks the coupling at the derivation boundary.
|
||||||
The agent-configs PNG is rendered from the SVG via `rsvg-convert` at
|
`rsvg-convert` renders the agent-configs PNG from the SVG at
|
||||||
build time; librsvg dependency lives here, not in the rust
|
build time; librsvg dependency lives here, not in the rust
|
||||||
derivation's `nativeBuildInputs`.
|
derivation's `nativeBuildInputs`.
|
||||||
|
|
||||||
|
|
@ -400,10 +400,9 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
|
||||||
= invisible window even though CDP works). The fix is **not** to wrap
|
= invisible window even though CDP works). The fix is **not** to wrap
|
||||||
each client in its own `dbus-run-session` (a private throwaway bus per
|
each client in its own `dbus-run-session` (a private throwaway bus per
|
||||||
process — that's a _separate_ session, defeating the one-session
|
process — that's a _separate_ session, defeating the one-session
|
||||||
model); it's this one shared bus, whose address is exported as
|
model); it's this one shared bus; `systemd.globalEnvironment` exports
|
||||||
`DBUS_SESSION_BUS_ADDRESS=unix:path=/run/gui/bus` via
|
its address as `DBUS_SESSION_BUS_ADDRESS=unix:path=/run/gui/bus` so
|
||||||
`systemd.globalEnvironment` so weston, the harness and every GUI client
|
weston, the harness and every GUI client inherit it.
|
||||||
inherit it.
|
|
||||||
- **Fixed Wayland socket name (`--socket=wayland-0`)**: weston is
|
- **Fixed Wayland socket name (`--socket=wayland-0`)**: weston is
|
||||||
launched with `--socket=wayland-0` so the socket path is
|
launched with `--socket=wayland-0` so the socket path is
|
||||||
deterministic. `nix/agent-modules/weston-vnc.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
deterministic. `nix/agent-modules/weston-vnc.nix` exports `WAYLAND_DISPLAY=wayland-0`
|
||||||
|
|
@ -471,12 +470,12 @@ Pipeline:
|
||||||
|
|
||||||
- CommonMark from `nixosOptionsDoc.optionsCommonMark` is the only
|
- CommonMark from `nixosOptionsDoc.optionsCommonMark` is the only
|
||||||
output — the source of truth, emitted as `.md`.
|
output — the source of truth, emitted as `.md`.
|
||||||
- **HTML + CSS is rendered downstream by the website repo**
|
- **The website repo renders HTML + CSS downstream**
|
||||||
(its own `options.nix`), which consumes this bundle's `host.md` /
|
(its own `options.nix`), consuming this bundle's `host.md` /
|
||||||
`agent.md`, renders them with `cmark-gfm`, and shares one
|
`agent.md`, rendering them with `cmark-gfm`, and sharing one
|
||||||
stylesheet (`docs.css`) across `/options/` and the prose `/docs/`
|
stylesheet (`docs.css`) across `/options/` and the prose `/docs/`
|
||||||
tree. Keeping rendering in the website means the theme has a single
|
tree. Keeping rendering in the website means the theme has a single
|
||||||
home and the colours are shared.
|
home, sharing colours across both trees.
|
||||||
- `transformOptions` strips the nix-store prefix from option
|
- `transformOptions` strips the nix-store prefix from option
|
||||||
declaration paths and rewrites them as forge URLs, so the
|
declaration paths and rewrites them as forge URLs, so the
|
||||||
rendered docs link back to the source.
|
rendered docs link back to the source.
|
||||||
|
|
@ -512,7 +511,7 @@ The fix (`nix/docs/default.nix`):
|
||||||
never forces a package — no stubs needed, and the Rust/frontend
|
never forces a package — no stubs needed, and the Rust/frontend
|
||||||
build closure stays out of the eval.
|
build closure stays out of the eval.
|
||||||
|
|
||||||
3. Both `hostEval` and `agentEval` are evaluated from `nixSrc` paths
|
3. Nix evaluates both `hostEval` and `agentEval` from `nixSrc` paths
|
||||||
(not `self`), so the docs drv dependency chain ends at `nixSrc`.
|
(not `self`), so the docs drv dependency chain ends at `nixSrc`.
|
||||||
|
|
||||||
Why `builtins.unsafeDiscardStringContext`? The path string
|
Why `builtins.unsafeDiscardStringContext`? The path string
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ human review that already happened.
|
||||||
|
|
||||||
## The gate has (up to) three parts, and they're per-repo settings
|
## The gate has (up to) three parts, and they're per-repo settings
|
||||||
|
|
||||||
Whether a PR can merge, and what counts toward "can," is configured
|
Each repo's branch-protection settings configure whether a PR can
|
||||||
per repo in its branch-protection settings — not a fact true of every
|
merge, and what counts toward "can" — not a fact true of every hive or
|
||||||
hive or every repo. The pieces a repo _can_ require:
|
every repo. The pieces a repo _can_ require:
|
||||||
|
|
||||||
- **CI is green** — the repo's required status checks pass on the
|
- **CI is green** — the repo's required status checks pass on the
|
||||||
PR's current head commit, if the repo requires any.
|
PR's current head commit, if the repo requires any.
|
||||||
|
|
@ -21,7 +21,7 @@ hive or every repo. The pieces a repo _can_ require:
|
||||||
(merges automatically the moment the other required conditions are
|
(merges automatically the moment the other required conditions are
|
||||||
met).
|
met).
|
||||||
|
|
||||||
Where these are required, they're independent of each other. A
|
Where a repo requires these, they're independent of each other. A
|
||||||
reviewer only ever owns the review-approval piece — CI resolves (or
|
reviewer only ever owns the review-approval piece — CI resolves (or
|
||||||
doesn't) on its own regardless of what a review says, and merge-arming
|
doesn't) on its own regardless of what a review says, and merge-arming
|
||||||
is someone else's call.
|
is someone else's call.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue