docs: name the actor instead of the vague 'we'/'our'

Per mara's ruling on hyperhive#4041 (Microsoft.We): keep the rule enabled,
same treatment as the 'backend' rewrites. Traced all 21 genuine hits (4
gateway.md 'Let's Encrypt' hits are a substring-match false positive, left
alone) to their actual referent: some name a specific component already
established nearby in the same doc (forge_notify, hive-github-notify's
poller, hive-forge, hive-agent/the harness, colors.css, the dashboard),
others were pure filler that adds nothing once dropped.
This commit is contained in:
iris 2026-09-09 18:10:52 +02:00 committed by mara
commit 9d02d81144
10 changed files with 44 additions and 43 deletions

View file

@ -277,7 +277,7 @@ The one gap the timestamp cut leaves: a genuine comment posted **within
`NEW_ITEM_TOLERANCE_SECS` of the merge** bumps `updated_at` close enough
to `closed_at` that `state_change_is_current` returns `true` — so it takes
the state-change path, dropping its body. Best of both worlds:
on the merge/close path we fetch the `latest_comment_url` comment and, when
on the merge/close path `forge_notify` fetches the `latest_comment_url` comment and, when
its `created_at` is strictly **after** the subject's `closed_at`
(`comment_is_after_close`) — that is it raced the merge rather than being the
pre-merge last comment the subject keeps — append it as a
@ -286,7 +286,7 @@ pre-merge last comment the subject keeps — append it as a
and the racing comment. `forge_notify` leaves the kept pre-merge comment (created before
`closed_at`) off, drops a self-authored racing comment (don't
echo the agent's own write), and appends nothing for a missing/unparseable `created_at`/
`closed_at` (conservative — only surface a comment we can
`closed_at` (conservative — only surface a comment it can
positively place after the close). Cost: one extra comment fetch on
merge/close notifications, acceptable given how rare they are.
@ -300,7 +300,7 @@ original open notification and miss the review. The `open`
state only earns the `new <kind>` label when the notification's event
time (`updated_at`) is within `NEW_ITEM_TOLERANCE_SECS` (120s) of the
subject's `created_at`. `forge_notify` labels anything later `activity on <kind>`
— neutral and non-misleading, since we can't cheaply say _what_ the
— neutral and non-misleading, since it can't cheaply say _what_ the
activity was without an extra reviews fetch. Missing/unparseable
timestamps default to `new` (preserve prior behavior rather than mask a
genuine new item). A small dependency-free

View file

@ -128,10 +128,10 @@ application/vnd.github+json`, `X-GitHub-Api-Version` and a
header: `x-ratelimit-remaining` near 5000 is an authenticated user,
near 60 is anonymous.
- **GitHub sets the cadence.** It returns `X-Poll-Interval` (60s in
practice, slower than our own tick) and rate-limits callers who ignore
it, so the loop re-arms to the server's interval whenever that's
_slower_ than ours. A hint faster than our own tick isn't a reason to
poll harder.
practice, slower than the poller's own tick) and rate-limits callers who
ignore it, so the loop re-arms to the server's interval whenever that's
_slower_ than the poller's. A hint faster than the poller's own tick
isn't a reason to poll harder.
⚠️ **This needs the `notifications` scope on the PAT.** A token minted
for `gh` + `git push` typically carries `repo` only, which is enough to

View file

@ -279,7 +279,7 @@ straight to `new Date(s)` for display.
Every HTTP API in this repo answers failures with **RFC 9457
`application/problem+json`** (`{ type, title, status, detail }`), with the
human-readable cause in `detail`. An endpoint of ours returning a bare string
human-readable cause in `detail`. An endpoint returning a bare string
or a bespoke error shape is a **bug to file against the daemon that
returned it**, not something for the caller to work around.

View file

@ -1,6 +1,6 @@
# Gotchas
NixOS + nspawn quirks and lessons we hit the hard way. If something
NixOS + nspawn quirks and hard-won lessons. If something
here looks unmotivated in the code, there's probably a story underneath.
Grouped by area — jump to the section that matches what you're
touching.
@ -30,7 +30,7 @@ Not `boot.isContainer = true`. Renamed in nixos-25.11+.
…in the `.conf`. The start script's `if HOST_ADDRESS set →
--network-veth` branch then forces a private netns — silently fatal
for our web UIs (the bind is invisible from the host). Every agent
for the web UIs (the bind is invisible from the host). Every agent
container runs isolated: `hive-priv`'s `write_nspawn_flags` writes
`PRIVATE_NETWORK=1` plus a veth pair onto the host bridge, `HOST_ADDRESS`
set to the bridge gateway IP (so `nixos-container`'s in-container init
@ -204,7 +204,7 @@ the `TIME_WAIT` case from a clean previous exit; retry covers the
genuine "previous process is still alive during a systemd restart
overlap" case. REUSEADDR does **not** allow two simultaneous
`LISTEN` sockets on the same port (that would be `SO_REUSEPORT`,
which we don't use) — it preserves exclusivity.
not used here) — it preserves exclusivity.
## Approvals
@ -417,8 +417,8 @@ connects to the compositor at `127.0.0.1:<vnc_port>`.
bind-address flag (unlike the `rdp-backend`'s `--address`), so the
listener binds `0.0.0.0`. The harness relay only connects via
`127.0.0.1`; the host firewall blocks the per-agent VNC port range
from external access. A future weston.ini `[vnc] address=` will
let us restrict the bind directly once upstream supports it.
from external access. A future weston.ini `[vnc] address=` would
restrict the bind directly, once upstream supports it.
- **PAM service name**: literal `weston-remote-access` — that's the
string libweston passes to `pam_start()` in `libweston/auth.c`.
Using `weston` falls back to the system default PAM stack and

View file

@ -143,7 +143,7 @@ The store's **first reader** is the matrix registration token, and it's worth
saying why that one: it's an opaque 32-byte value with no second file and no
format. Authelia's OIDC secret needs a `.secret` _and_ a matching `.digest`, so
starting there would have meant debugging "can a reader authenticate and get
bytes back" and "did we write authelia's file format right" at once, with an
bytes back" and "is authelia's file format right" at once, with an
SSO outage as the failure mode.
`glue-matrix-bao-token.nix` fetches it and writes the file `hive-matrix.nix`

View file

@ -265,8 +265,8 @@ to discover valid label names before triaging or to audit the label set.
- `comment --body "..."` with backticks in the body: always use
`--body-file -` with a HEREDOC to avoid shell escaping issues.
- `pr-create --push` also runs `git push forge <head>` and suppresses
the post-push "Create a pull request" hint (we print the canonical
URL ourselves).
the post-push "Create a pull request" hint (hive-forge prints the
canonical URL itself).
- `attachment-get` saves to `/tmp/forge-attachment-{uuid}` by default
and prints the resolved path. Pass `-o -` to stream to stdout.
- `artifact-get <name> --run <n>` downloads a CI Actions artifact. `<n>`

View file

@ -81,11 +81,11 @@ file. Because the
title is constant, `/compact` and its post-compact retry provably target
the same session (killing the old "compact ran on a different/empty
session" bug), and a `choom` invocation in the same cwd can't hijack the
context (it won't carry our title). claude stores sessions in
context (it won't carry that title). claude stores sessions in
`~/.claude/projects/<cwd-slug>/<uuid>.jsonl` (bind-mounted persistently);
`--name` writes the title into the file as a `custom-title` event, which
is what `--resume <title>` resolves against. We never pass bare
`--continue` (it resumes the _latest_ session in the cwd — the hijack
is what `--resume <title>` resolves against. The harness never passes
bare `--continue` (it resumes the _latest_ session in the cwd — the hijack
vector). The managed settings at `/etc/claude-code/managed-settings.json`
disable automemory and dynamic workflows (the `/workflows` feature):
`disableWorkflows` keeps the `/workflows` machinery from spawning sub-runs

View file

@ -123,13 +123,13 @@ color: var(--green); /* ok */
## Theme swapping — the base16 contract
**The swap interface is `colors.css` — the 16 base16 slots, not our
**The swap interface is `colors.css` — the 16 base16 slots, not the
semantic names.** A theme generator (for example one reading a stylix base16
scheme) overrides only `colors.css`; the semantic layer in `theme.css`
derives everything else, so the whole UI re-themes with nothing else to
template or regenerate. The base16 slot → semantic mapping is _internal_
to `theme.css` (the "Derives from" column above) — a generator never
needs to know our var names, and `theme.css` + the page bundles stay
needs to know the semantic var names, and `theme.css` + the page bundles stay
untouched.
**Two palettes, one contract.** `colors.css` ships both a dark default
@ -142,24 +142,24 @@ wholesale (for example the stylix path, which writes a single unconditional
`colors.css` base16 slot defaults (Catppuccin Mocha, dark default):
| Slot | Default | Standard base16 role | Mapped to |
| -------- | --------- | -------------------- | --------------------------------------------------- |
| `base00` | `#1e1e2e` | default bg | `--bg`, (darkened) `--crust` |
| `base01` | `#181825` | lighter bg | `--bg-elev` |
| `base02` | `#313244` | selection/surface | `--border` |
| `base03` | `#45475a` | comments/dim surface | `--purple-dim` |
| `base04` | `#585b70` | dark foreground | _(unused; kept for completeness)_ |
| `base05` | `#cdd6f4` | default foreground | `--fg`, (blended) `--muted`/`--subtext0` |
| `base06` | `#f5e0dc` | light foreground | _(unused)_ |
| `base07` | `#b4befe` | lightest | _(unused)_ |
| `base08` | `#f38ba8` | red | `--red` |
| `base09` | `#fab387` | orange | `--amber` |
| `base0A` | `#f9e2af` | yellow | `--yellow` |
| `base0B` | `#a6e3a1` | green | `--green` |
| `base0C` | `#89dceb` | cyan | `--cyan` (our _sky_; Catppuccin's `base0C` is teal) |
| `base0D` | `#89b4fa` | blue | `--blue` |
| `base0E` | `#cba6f7` | magenta | `--purple` |
| `base0F` | `#f5c2e7` | extra accent | `--pink` |
| Slot | Default | Standard base16 role | Mapped to |
| -------- | --------- | -------------------- | ---------------------------------------------------------- |
| `base00` | `#1e1e2e` | default bg | `--bg`, (darkened) `--crust` |
| `base01` | `#181825` | lighter bg | `--bg-elev` |
| `base02` | `#313244` | selection/surface | `--border` |
| `base03` | `#45475a` | comments/dim surface | `--purple-dim` |
| `base04` | `#585b70` | dark foreground | _(unused; kept for completeness)_ |
| `base05` | `#cdd6f4` | default foreground | `--fg`, (blended) `--muted`/`--subtext0` |
| `base06` | `#f5e0dc` | light foreground | _(unused)_ |
| `base07` | `#b4befe` | lightest | _(unused)_ |
| `base08` | `#f38ba8` | red | `--red` |
| `base09` | `#fab387` | orange | `--amber` |
| `base0A` | `#f9e2af` | yellow | `--yellow` |
| `base0B` | `#a6e3a1` | green | `--green` |
| `base0C` | `#89dceb` | cyan | `--cyan` (named _sky_ here; Catppuccin's `base0C` is teal) |
| `base0D` | `#89b4fa` | blue | `--blue` |
| `base0E` | `#cba6f7` | magenta | `--purple` |
| `base0F` | `#f5c2e7` | extra accent | `--pink` |
Notes for theme authors:
@ -167,8 +167,9 @@ Notes for theme authors:
derived via `color-mix()` over base16 (`--crust` = a darkened `base00`;
`--muted`/`--subtext0` = `base05``base00` blends). They still track a
swap automatically; no generator action needed.
- A standard Catppuccin base16 scheme uses **teal** for `base0C`; we
default it to **sky** (`#89dceb`) to preserve the historical accent. A
- A standard Catppuccin base16 scheme uses **teal** for `base0C`;
`colors.css` defaults it to **sky** (`#89dceb`) to preserve the historical
accent. A
stylix Catppuccin scheme will shift `--cyan` to teal — that's the
operator's chosen scheme, working as intended.
- `base04`/`base06`/`base07` aren't consumed by a semantic var today;

View file

@ -1107,7 +1107,7 @@ the toggle and silences dispatch without revoking the OS
permission. Requires a secure context (HTTPS or localhost); on
other origins the controls hide themselves. Browsers typically
suppress notifications while the originating tab is focused —
that's a browser-level decision, not ours.
that's a browser-level decision, not the dashboard's.
## Dashboard endpoints

View file

@ -199,7 +199,7 @@ carry raw HTML. Rendered `<a>`s get the same target rewrite.
The JS app handles all `form[data-async]` submissions via a delegated
listener: read `data-confirm`, swap the button to a spinner, POST
`application/x-www-form-urlencoded`, re-enable the button on success
(refreshState may keep the form mounted, so we don't rely on a
(refreshState may keep the form mounted, so the handler doesn't rely on a
re-render), call `refreshState()`. State shapes live in
`hive-c0re/src/dashboard/state_snapshot.rs::StateSnapshot` and
`web_ui/state.rs::StateSnapshot` — when