docs: fix genuine passive-voice hits in docs/integrations
Sixth batch of the ongoing write-good.Passive pass (hyperhive#4042):
read all 52 hits across knowledge.md/github.md/matrix.md/forge.md in
context and rewrote 39 with a clearly nameable actor -- mostly
hive-c0re, forge_notify, or a specific fn named right there or a
sentence or two earlier. forge.md's notification poller is the
densest yet (19/20 hits rewritten): forge_notify is established as
the section's sole actor early and reused throughout, the shape
that's produced the highest catch rates all along.
Left 13 alone: the "no X is needed" negative-capability idiom (x2),
a container-lifecycle state descriptor ("when container is stopped"),
a false-positive tokenization ("read-only" split across a line wrap,
vale matches "is read" inside it -- not a real passive at all), the
"X can't be Yed" idiom, a generic "before the ids are minted" timing
clause with no natural actor to name, a room-join policy-state
descriptor, an "is enabled"/"is trusted" pair describing a config/
trust state (predicate-adjective-copula bucket, same family as
"is privileged" from an earlier batch), three "**X is required**"
bolded requirement-list labels (structural convention, not really
mid-sentence passives), and a contrastive "are shared" clause
mirrored against an active sibling clause exactly like
claude-invocation.md's "everything else is shared" from the
turn-loop batch -- left alone there for the same reason.
One sibling-inconsistency catch worth flagging: forge.md's merge-
racing-comment paragraph had two passive clauses ("is left off",
"is dropped") sitting next to a third, already-active clause
("appends nothing") in the same three-item parallel list -- rewrote
all three under one active subject (forge_notify) for consistency.
Verified via vale before/after: 52 -> 13 write-good.Passive hits,
exactly the 13 left alone above; error count and other warning
categories unchanged (still on TooWordy since #4097 hasn't merged to
this branch yet). Re-read every changed line in full surrounding
context after editing, matching the diff to intent before running
the final vale check.
This commit is contained in:
parent
c41c67c949
commit
060f325716
4 changed files with 62 additions and 62 deletions
|
|
@ -48,8 +48,8 @@ hive-c0re to re-mint with the new scopes.
|
|||
|
||||
Each agent gets its own Forgejo user + access token, provisioned at
|
||||
boot by `hive-c0re::forge`. The provisioning flow is idempotent:
|
||||
existing accounts + tokens are reused, so container destroy/recreate
|
||||
doesn't lose forge identity. The token is written to
|
||||
`hive-c0re::forge` reuses existing accounts + tokens, so container destroy/recreate
|
||||
doesn't lose forge identity. It writes the token to
|
||||
`<state>/forge-token` (one line, no trailing newline) inside the
|
||||
agent container so `hive-forge` CLI + `forge_notify` poller can
|
||||
read it without touching c0re's host-side credential store.
|
||||
|
|
@ -63,7 +63,7 @@ Two things live in the `agent-configs` Forgejo organization:
|
|||
`hive-c0re/src/forge/config_pr_poll.rs` re-scans every 5 minutes as a
|
||||
fault-tolerance backstop) — but
|
||||
`main` is branch-protected core-only: only hive-c0re's verify-and-ff-push
|
||||
merge handler lands on `main`, an operator-team approval is required, and
|
||||
merge handler lands on `main`, the operator team must approve first, and
|
||||
the agent can neither push `main` directly nor self-merge. `main` is
|
||||
fast-forward-only — hive-c0re never force-pushes (the merge handler's ff
|
||||
push lands fine; the `push_config` mirror pushes `main` + the add-only
|
||||
|
|
@ -126,7 +126,7 @@ That size property is the whole point. A container rebuild starts the
|
|||
poller with no memory of what it delivered, re-scans `?all=false`, and
|
||||
finds nothing stale — the delivered threads are already read on forge.
|
||||
Forge's own read-state is thus the durable, cross-rebuild record of
|
||||
what's been delivered; there is **no persisted cursor**.
|
||||
what `forge_notify` has delivered; there is **no persisted cursor**.
|
||||
|
||||
**Gotcha:** don't reintroduce a persisted dedup cursor here. A design
|
||||
that leaves threads unread and tracks delivery via a separately persisted
|
||||
|
|
@ -149,10 +149,10 @@ re-fire the wake. it's **not persisted** and resets on restart (forge
|
|||
read-state covers the durable case). Each poll prunes it to the ids in
|
||||
the single `limit=UNREAD_FETCH_LIMIT` (50) fetch page, so it can never
|
||||
exceed that many entries (a debug assertion pins the invariant; the
|
||||
fetch limit and the bound are the same constant). A failed _delivery_
|
||||
is left unread and out of the map, so it resurfaces next tick.
|
||||
fetch limit and the bound are the same constant). `forge_notify` leaves
|
||||
a failed _delivery_ unread and out of the map, so it resurfaces next tick.
|
||||
|
||||
Self-echo notifications (the agent's own writes, see below) are marked
|
||||
`forge_notify` marks self-echo notifications (the agent's own writes, see below)
|
||||
read directly without a delivery — same `mark_read` call, no wake.
|
||||
|
||||
### Activation gates (graceful no-ops)
|
||||
|
|
@ -176,17 +176,17 @@ best-effort: logged at debug/warn and retried next tick.
|
|||
|
||||
Forgejo fires notifications for the agent's own actions (it opened a
|
||||
PR, posted a comment, submitted a review). Surfacing those would
|
||||
loop claude on its own writes. The comment/review case is dropped
|
||||
loop claude on its own writes. `forge_notify` drops the comment/review case
|
||||
silently (mark-read without delivery):
|
||||
|
||||
- **Self-authored comments / reviews** — comment payload's
|
||||
`user.login` matches `own_login`.
|
||||
- **Self-authored creations** (an agent opening its own PR/issue) — the
|
||||
already-fetched subject payload's poster `user.login` matches
|
||||
`own_login`. Only _creations_ are dropped; a later state change on the
|
||||
agent's own subject is driven by someone else and still surfaces.
|
||||
`own_login`. `forge_notify` drops only _creations_ this way; a later state
|
||||
change on the agent's own subject comes from someone else, so it still surfaces.
|
||||
|
||||
`own_login` is fetched at startup via `GET /api/v1/user`. On fetch
|
||||
`forge_notify` fetches `own_login` at startup via `GET /api/v1/user`. On fetch
|
||||
failure the filter degrades open (no filtering) rather than crashing
|
||||
the task — a noisy inbox beats a silently stuck poller — but the fetch
|
||||
is **re-attempted on each poll tick** until it succeeds, so a boot-time
|
||||
|
|
@ -246,7 +246,7 @@ not context (mara, triage: "just the issue title should be enough").
|
|||
|
||||
Review labels come from the Forgejo `state` field: `APPROVED` →
|
||||
`approved`, `REQUEST_CHANGES` → `changes requested`, `COMMENT` →
|
||||
`review comment`. `PENDING` is dropped (review saved but not
|
||||
`review comment`. `forge_notify` drops `PENDING` (review saved but not
|
||||
submitted yet — no peer-visible event). Unknown states fall back to
|
||||
the generic comment wrapper.
|
||||
|
||||
|
|
@ -276,17 +276,17 @@ hidden behind a stale comment.
|
|||
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 and its body would be dropped. Best of both worlds:
|
||||
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
|
||||
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
|
||||
`comment by <author>: <excerpt>` block before the meta suffix
|
||||
(`fresh_post_close_comment_tail`). The wake carries **both** `[PR merged]`
|
||||
and the racing comment. The kept pre-merge comment (created before
|
||||
`closed_at`) is left off, a self-authored racing comment is dropped (don't
|
||||
echo the agent's own write), and a missing/unparseable `created_at`/
|
||||
`closed_at` appends nothing (conservative — only surface a comment we can
|
||||
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
|
||||
positively place after the close). Cost: one extra comment fetch on
|
||||
merge/close notifications, acceptable given how rare they are.
|
||||
|
||||
|
|
@ -299,15 +299,15 @@ so it misses the comment path and lands on the state-change path with
|
|||
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`. Anything later is labeled `activity on <kind>`
|
||||
subject's `created_at`. `forge_notify` labels anything later `activity on <kind>`
|
||||
— neutral and non-misleading, since we 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). Timestamps are parsed by a small dependency-free
|
||||
RFC 3339 helper (`parse_rfc3339`).
|
||||
genuine new item). A small dependency-free
|
||||
RFC 3339 helper (`parse_rfc3339`) parses timestamps.
|
||||
|
||||
Number is extracted from `subject.html_url`'s last path segment
|
||||
(strips `#anchor` first); repo slug from `repository.full_name`.
|
||||
`forge_notify` extracts the number from `subject.html_url`'s last path segment
|
||||
(strips `#anchor` first), and the repo slug from `repository.full_name`.
|
||||
Both degrade gracefully when absent (number → blank, repo → blank)
|
||||
so unexpected Forgejo shapes don't crash the formatter.
|
||||
|
||||
|
|
@ -326,15 +326,15 @@ For new PRs, the kind label flips to `[review requested #N
|
|||
owner/repo]` when `own_login` appears in `requested_reviewers`,
|
||||
regardless of the Forgejo `reason` field. Forgejo doesn't reliably
|
||||
set `reason == "review_requested"` (often null instead), so the
|
||||
fallback checks the subject payload directly. Detection is gated on
|
||||
`is_new` so the label only fires once on PR creation, not on every
|
||||
fallback checks the subject payload directly. `is_new` gates detection
|
||||
so the label only fires once on PR creation, not on every
|
||||
subsequent comment.
|
||||
|
||||
### Subscription management
|
||||
|
||||
The poller does **not** autounsubscribe from repo watches — it
|
||||
delivers every unread notification it's handed. Bounding the
|
||||
firehose (dropping broad repo watches an agent doesn't need) is done
|
||||
explicitly via a hive-forge CLI subscription verb, not by the poller
|
||||
guessing which watches to drop. See the `subscription` verb in
|
||||
delivers every unread notification it's handed. A hive-forge CLI
|
||||
subscription verb bounds the firehose explicitly (dropping broad repo
|
||||
watches an agent doesn't need) — the poller never guesses which
|
||||
watches to drop. See the `subscription` verb in
|
||||
[`docs/tools/forge.md`](../tools/forge.md).
|
||||
|
|
|
|||
Loading…
Reference in a new issue