`matrix.md` documents the exact text of every inbound matrix signal —
three wake-body shapes and the invite loose-end — and none of them
mention that the daemon prefixes `[acct:<name>] ` when it serves more
than one account.
`wake::tag_account` is live on both documented paths (`timeline.rs:75`
for unread wakes, `:139` for invite todos), so an agent with an extra
account receives `[acct:ccc] [matrix] @a:s in #x: hi` where the page
promises a body starting `[matrix]`. The example is not hypothetical:
the matrix module uses `matrix-token-ccc` on dmatrix as its worked
example of an extra account.
It stayed invisible because the `None` arm returns the body unchanged,
so every single-account agent sees the documented format exactly. The
page is right for almost every reader and wrong for precisely the
readers its "Multiple accounts" section is written for.
Two placements rather than one. The prefix itself goes next to the wake
formats it corrects, with the worked example and the reason a leading
`[matrix]` match works until a second account exists. A forward pointer
goes in "Multiple accounts", because that is the section someone
configuring extra accounts actually lands on, and it previously covered
only the outbound `account` parameter — the half you pass, not the half
you parse.
Closes#4243.
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).
Fixed 72 hyphenated 'auto-X' compounds across the docs by deleting
the hyphen to match Microsoft style guide (autogenerated, autoregistration,
autodiscovery, etc). Preserved original capitalization throughout.
Covered 26 documentation files in docs/, including README.md, agent-lifecycle,
integrations, scheduler, networking, process, tools, trust-boundary,
turn-loop, and web-ui sections.
Substitutes 'for example' for 'e.g.' and 'that is' for 'i.e.' per
Microsoft style, with no comma after the replacement -- this repo
never puts a comma after e.g./i.e. either, so the substituted phrase
matches that house style instead of vale's literal 'for example,'
suggestion.
Covers all 77 real hits (72 from the initial vale pass + 5 more of the
same pattern found on a follow-up vale run). None of the flagged
instances were sentence-initial, so there's no capitalization concern
here.
Verified via a fresh vale run: 0 remaining Microsoft.Foreign hits.
Full accounting in /agents/iris/state/haiku-batches/foreign-report.md.
Per mara's go-ahead on hyperhive#3902 ("getting started is good, but
terminal rendering does not go in there i think"):
Moved 21 top-level docs/*.md files into 7 new topic subdirectories
(existing web-ui/, turn-loop/, swarm/, tools/, crates/ untouched):
getting-started/ setup.md
agent-lifecycle/ agent-hierarchy.md, approvals.md, persistence.md
trust-boundary/ boundary.md, security.md
integrations/ forge.md, matrix.md, github.md, knowledge.md
networking/ gateway.md, network.md, snapshot-store.md
scheduler/ jobq.md, coordinator.md, ci.md, observability.md
process/ conventions.md, gotchas.md, pr-review-gate.md
web-ui/ terminal-rendering.md (moved into the EXISTING dir,
per mara's correction to the original getting-started
guess -- it's UI implementation detail, not onboarding)
The physical layout now matches docs/README.md's own topical headers,
which already amounted to this taxonomy -- see the scoping comment on
the issue for the two findings that motivated this (a genuine
duplication between CLAUDE.md's old "Reading paths" list and
docs/README.md's grouped one, since drifted out of sync with each
other; and the flat layout not matching the grouping we already had).
Fixed every cross-reference this moved across the whole repo (~120
files: docs/ internal links at every depth, Rust doc comments, nix
module option docs, crate READMEs) -- verified two ways: a grep sweep
confirming zero remaining references to any old path, and a script
that resolves every markdown link in docs/**/*.md + CLAUDE.md +
README.md against the filesystem and reports anything that doesn't
exist (zero broken links).
Collapsed CLAUDE.md's "Reading paths" section (the duplicate) down to
a pointer at docs/README.md, now the single index. Rewrote
docs/README.md itself to use the new subdirectory paths and added the
one doc it was missing that CLAUDE.md's old copy had (pr-review-gate.md).
Classified all 22 docs/*.md files first via a haiku subagent (mara's
suggestion) on two axes -- proposed grouping and operator-vs-
implementation focus -- before finalizing the taxonomy; spot-checked
the report and found internal inconsistencies (its classification
table disagreed with its own summary section for a few files), so this
taxonomy is my original proposal + the one correction mara gave
directly, not a blind application of the subagent's table. The
operator-focus data it gathered is still useful for a follow-up
content pass (docs skewing 'mixed' rather than pure operator-facing),
not addressed in this PR -- structure only.
nix fmt clean, both pre-push lints clean.
Per mara on hyperhive#1898: the top-level README should not go into
details about impl details or specific subsystems. Trims the
Multi-account Matrix support and GitHub account sections down to a
one-line pointer each.
The matrixAccounts option detail that was only ever documented in the
README (checked: docs/matrix.md is entirely about the host hive-matrix
container, not this per-agent option) moves to docs/tools/matrix.md
instead, next to the account parameter every matrix tool already
takes - the natural home, not a link to a page that never covered it.
open_dm(user_id) resolves (find-or-create) the DM room and returns
its room id without sending anything. It is the counterpart to
send_dm for cases where you need a room id to pass to a room-based
tool such as send_file or send_message.
The tool was present in hive-matrix-mcp (mcp.rs, handlers.rs,
protocol.rs) and the terminal-rendering icon table but was missing
from the tools/matrix.md reference doc.
The human-readable matrix MCP reference was missing three behaviours
documented only in the MCP server instructions string:
- send_file / download_file tools (issues 1829, 1830)
- [file:]/[image:]/[audio:]/[video:] attachment markers in read_room (issue 1830)
- unread guard: send_message, send_dm, send_file, send_reply all
reject if the room has unread messages (issue 1828)
- send_redact (omitted from the tool list entirely)
Add all four to docs/tools/matrix.md to match the MCP server
instructions added in the previous commit.
The daemon does not call join_room_by_id. It fires a wake and writes
to mcp-loose-ends/matrix.json; the agent calls list_invites + join_room.
Replace the inaccurate 'Auto-accept invites' paragraph with 'Invite
wakes' describing the actual flow. Merge the pending-invites paragraph
into a single accurate block.
The matrix wake body description said '[matrix] <sender> in <room>:
<first-100c>...' (old single-line teaser). After feat(#1137) it's now
a richer format:
- Single room, 1 message: terse one-liner with sender + body
- Single room, N messages: count + room name
- Multi-room: bulleted list with per-room summaries
Also note that the same breakdown appears in get_loose_ends via the
UnreadMatrix entry.