diff --git a/docs/README.md b/docs/README.md index 7b8261e6..fc3c4648 100644 --- a/docs/README.md +++ b/docs/README.md @@ -92,7 +92,7 @@ declarations. - **What does a specific Rust crate do, on its own terms?** → [`crates/`](crates/README.md) — every workspace crate's own - `README.md`, one level up from source (hyperhive#3051); the crate + `README.md`, one level up from source; the crate itself is still the source of truth, this is just a walkable mirror. ## Process & conventions diff --git a/docs/agent-lifecycle/agent-hierarchy.md b/docs/agent-lifecycle/agent-hierarchy.md index cb8e78ef..3eb6a025 100644 --- a/docs/agent-lifecycle/agent-hierarchy.md +++ b/docs/agent-lifecycle/agent-hierarchy.md @@ -4,8 +4,7 @@ Every agent has a place in an operator-editable parent/child tree, used to scope which agents can manage which others. This doc covers how hive-c0re stores and edits the tree today, the rules that are meant to run on top of it once enforcement is finished, and where the manager still gets -special-cased in the meantime. Tracking issue: hyperhive#361 -(`$HIVE_FORGE_URL/hyperhive/hyperhive/issues/361`). +special-cased in the meantime, as a tracked cleanup. ## Where the tree lives @@ -235,10 +234,7 @@ uid 0 and have the setuid bit set." ## Cross-references -- Milestone: "Agent privileges and sub-agents" - (`$HIVE_FORGE_URL/hyperhive/hyperhive/issues/361`) -- Dashboard render: "show agent topology in container list" - (`$HIVE_FORGE_URL/hyperhive/hyperhive/issues/363`) -- Audit table source: milestone comment - (`$HIVE_FORGE_URL/hyperhive/hyperhive/issues/361#issuecomment-3335`) +- Milestone: "Agent privileges and sub-agents" (tracked internally) +- Dashboard render: "show agent topology in container list" (tracked internally) +- Audit table source: milestone comment (tracked internally) - Operator/agent trust boundary (orthogonal axis): [`boundary.md`](../trust-boundary/boundary.md) diff --git a/docs/agent-lifecycle/approvals.md b/docs/agent-lifecycle/approvals.md index 3eb2f1fd..7fbed1d3 100644 --- a/docs/agent-lifecycle/approvals.md +++ b/docs/agent-lifecycle/approvals.md @@ -69,7 +69,7 @@ request. and no approval. (it's currently mounted read-write, which is a defect tracked separately, not an authoring path.) Branch protection (push/merge allowlist = `core`, approvals allowlist - = operator team; see "Forge mirror" and #1787) makes the agent a + = operator team; see "Forge mirror" below) makes the agent a write collaborator that **can't merge its own config PR**. 2. hive-c0re's `/webhook/config-pr` endpoint receives the Forgejo `pull_request` event (opened / synchronized / reopened) and queues a @@ -476,7 +476,7 @@ repo — so it can push a branch and open a config PR — but not a member of any other agent's, so it can't reach another agent's config through the forge. Branch protection keeps `main` push/merge `core`-only with operator-team approval, so an agent can't fast-forward its own config or -self-merge its PR (see the End-to-end flow + #1787). hive-c0re passes the tokenised push +self-merge its PR (see the End-to-end flow above). hive-c0re passes the tokenised push URL inline to `git push`, never writing it into `applied//.git/config`; that repo is RO-bind-mounted into the root agent, and a stored token would leak core's admin credential to an diff --git a/docs/agent-lifecycle/persistence.md b/docs/agent-lifecycle/persistence.md index 6b5fa9ba..59bf920d 100644 --- a/docs/agent-lifecycle/persistence.md +++ b/docs/agent-lifecycle/persistence.md @@ -437,7 +437,7 @@ would only be transient. On a btrfs host, `lifecycle::ensure_agent_state_subvolume` creates a brand-new agent's state root as a **btrfs subvolume** instead of a plain directory (progressive -enhancement — see the #1762 lane). This is a no-op fallback on +enhancement). This is a no-op fallback on non-btrfs hosts and for any agent whose root already exists, so nothing is automigrated: existing agents keep their plain dirs until an explicit opt-in upgrade. diff --git a/docs/crates/README.md b/docs/crates/README.md index 492dfd52..d841e95f 100644 --- a/docs/crates/README.md +++ b/docs/crates/README.md @@ -3,7 +3,7 @@ One page per Rust workspace crate — its own `README.md`, unchanged, served here for browsing alongside the rest of the docs site. **The crate's own `README.md` is the source of truth; nothing here is hand-maintained.** -`nix/packages/reference-docs.nix` (hyperhive#3051) generates every page at +`nix/packages/reference-docs.nix` generates every page at build time straight from the crate's real `README.md`, so it can never drift out of sync the way a hand-copied mirror would — edit the crate's own README to change what shows up here. diff --git a/docs/getting-started/setup.md b/docs/getting-started/setup.md index 4bcf9446..8bf691ba 100644 --- a/docs/getting-started/setup.md +++ b/docs/getting-started/setup.md @@ -95,7 +95,7 @@ store's container reads it, writes the `swarm-controller` policy, enables the cert auth method, and creates the `swarm-controller` role that attaches the two. ⚠️ **This has only run once, and it didn't go all the way through.** The -first real provision against a live store returned 403 (hyperhive#4124), so +first real provision against a live store returned 403, so treat the block above as derived-then-partly-tested rather than proven: the grants still come from `-output-policy`, not from a swarm that came up on them. What that 403 does _not_ tell you is whether the login or the write was @@ -128,7 +128,7 @@ can't hand you, being what opens it. ⚠️ Not the gateway's HTTPS certificates store that took its identity from an authority it will itself distribute could never come up before that authority. -Making even the `init` unnecessary is tracked in issue #3768. +Making even the `init` unnecessary is tracked as a follow-up. ### 4 · Swarm SSO (only when `deploy.authelia`) diff --git a/docs/integrations/forge.md b/docs/integrations/forge.md index 73529fc1..f8bdff76 100644 --- a/docs/integrations/forge.md +++ b/docs/integrations/forge.md @@ -215,7 +215,7 @@ pipeline steps in order: `CommonMark` ATX heading (1-6 leading `#`s followed by a space, tab, or end-of-line), prepend `\` so the embedded body doesn't blow into a top-level h1/h2 inside the wrapper message when the - dashboard renders it. Lines like `#tag`, `#123`, `#!/bin/bash` + dashboard renders it. Lines like `#tag`, `#123`, `#!/bin/bash` **aren't** headings — no escape, no cosmetic noise. Indented "headings" inside lists / nested quotes keep their leading whitespace. diff --git a/docs/process/conventions.md b/docs/process/conventions.md index 7f349a51..32a8e053 100644 --- a/docs/process/conventions.md +++ b/docs/process/conventions.md @@ -64,7 +64,8 @@ hive-c0re owns the host admin socket. is the wake-event-injection surface. Recipient is implicit — the agent the socket belongs to — and `from` is caller-chosen so the wake prompt can label the source verbatim (`"matrix: new message in -#general"`, `"forge: PR #42 opened"`, etc.). Typical caller: an +#general"`, `"forge: PR #42 opened"`, etc.). +Typical caller: an in-container background task (the matrix daemon, a scraper, the forge-notify webhook subscriber) that needs to signal "external work has arrived" without going through the broker as a peer agent. diff --git a/docs/process/gotchas.md b/docs/process/gotchas.md index 86d53380..9ca53746 100644 --- a/docs/process/gotchas.md +++ b/docs/process/gotchas.md @@ -412,7 +412,7 @@ connects to the compositor at `127.0.0.1:`. Wayland clients couldn't find the compositor — libwayland falls back to a headless display or errors out, the app "works" on a second invisible display, and the VNC session shows a blank weston - desktop (#540 double-screen). + desktop (known double-screen issue). - **VNC bind address**: Weston's `vnc-backend` has no CLI bind-address flag (unlike the `rdp-backend`'s `--address`), so the listener binds `0.0.0.0`. The harness relay only connects via diff --git a/docs/tools/bash.md b/docs/tools/bash.md index cc2fd715..c9ef0b52 100644 --- a/docs/tools/bash.md +++ b/docs/tools/bash.md @@ -112,7 +112,7 @@ summary change signals the harness turn loop directly (in-process, no broker round-trip), so the harness drives a turn for the agent to handle it via `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 -spawn another todo; see #2639). Same mechanism the matrix daemon uses for +spawn another todo). Same mechanism the matrix daemon uses for unread rooms. An inline `wait_seconds` / `status` observation that already delivered the result instead clears the keyed todo, so no redundant loose-end follows. diff --git a/docs/tools/forge.md b/docs/tools/forge.md index 7ea4873a..218fc059 100644 --- a/docs/tools/forge.md +++ b/docs/tools/forge.md @@ -66,12 +66,12 @@ hive-forge comment-edit 18042 --body "..." # edit a comment hive-forge assign 42 damocles hive-forge close 42 hive-forge labels 42 add feature -hive-forge issue dependency 42 # list #42's dependencies (issues it's blocked by) -hive-forge issue dependency 42 add 40 41 # #42 is now blocked by #40 and #41 -hive-forge issue dependency 42 remove 40 # drop the #40 dependency link +hive-forge issue dependency 42 # list issue 42's dependencies (issues it's blocked by) +hive-forge issue dependency 42 add 40 41 # issue 42 is now blocked by 40 and 41 +hive-forge issue dependency 42 remove 40 # drop the dependency on 40 hive-forge pr dependency 55 add 42 # same verb, PR-scoped (Forgejo shares the issue/PR index) -hive-forge issue reaction 42 # list #42's reactions -hive-forge issue reaction 42 add heart # react to #42 with :heart: +hive-forge issue reaction 42 # list issue 42's reactions +hive-forge issue reaction 42 add heart # react to issue 42 with :heart: hive-forge issue reaction 42 --comment 18042 add +1 # react to a specific comment instead hive-forge issue reaction 42 remove heart # remove your own :heart: reaction hive-forge issue reaction 1 --list-allowed # this instance's actual configured shortcodes @@ -202,7 +202,7 @@ verdict alone. ``` hive-forge pr-status --pr 42 -# PR #42: feat(...): ... +# PR #42: feat(...): ... # lint:allow: sample CLI output, not a real tag # state: open (mergeable: yes) # CI: e39a87ea3949: ✅ success (1 context(s)) # ✅ CI / nix flake check (pull_request): success — Successful in 1m50s diff --git a/docs/trust-boundary/security.md b/docs/trust-boundary/security.md index ef6c7a75..c82010a6 100644 --- a/docs/trust-boundary/security.md +++ b/docs/trust-boundary/security.md @@ -63,7 +63,7 @@ What still holds: the grant is **read-only** (a hive can't write an agent's credential, so it can't hand itself an agent's identity), and it's scoped to the agent-credential prefix — nothing else in the store is reachable with it. -**#4137** tracks narrowing it, with the two candidate directions: scope +**A tracked follow-up** narrows this, with the two candidate directions: scope the grant per hive (and pay for the re-emission), or give each agent container its own store identity so credentials never pass through a hive at all. diff --git a/docs/turn-loop/claude-invocation.md b/docs/turn-loop/claude-invocation.md index e1cffeab..a74a34e1 100644 --- a/docs/turn-loop/claude-invocation.md +++ b/docs/turn-loop/claude-invocation.md @@ -133,8 +133,7 @@ the reactive path only fires once claude-code has already refused a whole turn as too long. Neither can see context growth happening _inside_ a single long turn's own tool-calling before it returns — a turn whose tool calls alone blow past the window hits the reactive path with no preceding -checkpoint, losing whatever wasn't already persisted (#2707, root-caused in -#3727). +checkpoint, losing whatever wasn't already persisted (a known, root-caused gap). **Safety net for that gap: claude-code's own native autocompact is on**, via the managed settings (`"autoCompactEnabled": true`, diff --git a/docs/turn-loop/mcp.md b/docs/turn-loop/mcp.md index 23238cf7..d1d63549 100644 --- a/docs/turn-loop/mcp.md +++ b/docs/turn-loop/mcp.md @@ -222,7 +222,7 @@ operator-driven `hivectl choom` session — which passes neither `--tools` nor `--allowedTools` — gets claude's built-in synchronous `Bash` tool (inline, human-approved). That sidesteps the async `mcp__bash__run` completion wake landing in the wrong session (the harness inbox) for a -choom-started task (#2356); `choom` is an operator (root) action, so +choom-started task; `choom` is an operator (root) action, so built-in shell there stays within the existing trust boundary. The bash MCP server (`run` / `status` / `kill`) uses `allowedTools = ["*"]` so all `mcp__bash__*` tools are always available regardless of tool groups. diff --git a/docs/web-ui/agent.md b/docs/web-ui/agent.md index a221e3f5..c89436b4 100644 --- a/docs/web-ui/agent.md +++ b/docs/web-ui/agent.md @@ -85,7 +85,7 @@ structurally rather than for one specific trigger. Two columns: `agent_links()` in hive-agent is the single source of truth for both. No separate overflow (`⋯`) menu exists any more — it used to hold exactly this dashboard link plus a rebuild-container action - (mara, hyperhive#3704: "remove rebuild button, move link to + (mara: "remove rebuild button, move link to dashboards into links menu") — rebuild had no real discoverability need of its own (the dashboard's own R3BU1LD button already covers it) so it's gone outright, and the dashboard link moved here, diff --git a/docs/web-ui/css-vars.md b/docs/web-ui/css-vars.md index 6505666c..08c55847 100644 --- a/docs/web-ui/css-vars.md +++ b/docs/web-ui/css-vars.md @@ -67,7 +67,7 @@ default palette). Default hexes shown are Catppuccin Mocha. | `--blue` | `base0D` | `#89b4fa` | links, interactive accent (distinct from cyan) | | `--purple` | `base0E` | `#cba6f7` | accent — active tabs, links, highlights | | `--pink` | `base0F` | `#f5c2e7` | thinking events | -| `--crust` | `mix(base00 58%, #000)` | `#11111b` | terminal / code block background (below `--bg`) | +| `--crust` | `mix(base00 58%, #000000)` | `#11111b` | terminal / code block background (below `--bg`) | | `--muted` | `mix(base05 55.5%, base00)` | `#7f849c` | secondary / dimmed text | | `--subtext0` | `mix(base05 77.7%, base00)` | `#a6adc8` | toolbar/status text; dimmer than `--fg`, lighter than `--muted` | diff --git a/docs/web-ui/dashboard.md b/docs/web-ui/dashboard.md index af55c819..c6684faa 100644 --- a/docs/web-ui/dashboard.md +++ b/docs/web-ui/dashboard.md @@ -146,7 +146,7 @@ part-way through a spawn is byte-identical on disk to a tombstone, and the pane lists both. The pane carries a standing warning to that effect, and the row badge says `offline` rather than `destroyed` — the absence of a container is all hive-c0re can actually prove. Fixing it properly -needs a recorded destroy: **#3020**, deferred to the swarm-controller / +needs a recorded destroy — **deferred** to the swarm-controller / snapshot-storage rework where the problem changes shape. *Stale permission entries*: agents with explicit capability or @@ -236,7 +236,7 @@ than reconstructing chrome hive-c0re no longer sends. Settled entries render their **full step tree**, not just a bare summary — the wire doesn't filter `Done` nodes out. -**State filter (hyperhive#2606).** A row of per-state checkboxes above +**State filter.** A row of per-state checkboxes above the tree — one per lifecycle state, matching the row glyphs — lets the operator narrow which root groups render; unchecking a state re-fetches `GET /api/jobq/graph?states=` rather than @@ -811,7 +811,7 @@ below). ### Status badges -**Which single badge (hyperhive#3139):** `ContainerView.failed` +**Which single badge:** `ContainerView.failed` (systemd `ActiveState=failed` — the unit exhausted its bounded restarts and gave up on its own) draws a red `✖ gave up` badge; otherwise a plain muted `■ not running` — a container an operator diff --git a/docs/web-ui/shape.md b/docs/web-ui/shape.md index ff14032a..2a1a6340 100644 --- a/docs/web-ui/shape.md +++ b/docs/web-ui/shape.md @@ -244,7 +244,7 @@ render, `restoreOpenDetails()` re-applies after. Long-content drill-ins (file previews, diffs, journald logs) now open in the **side panel** (see below) rather than expanding inline. The dashboard's own answered-questions history list was the only -`
` consumer and is gone (hyperhive#3721) +`
` consumer and is gone — `snapshotOpenDetails()` / `restoreOpenDetails()` currently have nothing to restore, kept in place for the next collapsible section that needs it rather than ripped out along with their one caller. diff --git a/frontend/README.md b/frontend/README.md index a9c027fe..8088fde8 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -28,6 +28,6 @@ additions are layered on top of the default agent dist via the output is reproducible without network access at build time. - **esbuild**: vanilla-JS bundler, no framework runtime overhead. Each workspace's `build.mjs` is ~30 lines. -- **Single-PR migration**: see issue #273 for the design proposal and +- **Single-PR migration**: see the tracked design proposal and the four-commit shape (npm scaffold → nix derivations → container plumbing → Rust cutover). diff --git a/hive-forge-notify/src/notify.rs b/hive-forge-notify/src/notify.rs index 0588a22a..09ce6165 100644 --- a/hive-forge-notify/src/notify.rs +++ b/hive-forge-notify/src/notify.rs @@ -1451,7 +1451,7 @@ mod tests { "html_url": "http://forge/o/r/pulls/5", "latest_comment_html_url": "", "latest_comment_url": "", - "url": "http://forge/api/v1/repos/o/r/issues/5", + "url": "http://forge/api/v1/repos/o/r/issues/5", // lint:allow: test fixture, not a real forge link }, })) .expect("merged-state notification must parse"); @@ -1501,7 +1501,7 @@ mod tests { "title": "t", "type": "SomeBrandNewType", "html_url": "", - "url": "http://forge/api/v1/repos/o/r/issues/9", + "url": "http://forge/api/v1/repos/o/r/issues/9", // lint:allow: test fixture, not a real forge link "another_unknown": 123, }, })) @@ -1532,7 +1532,7 @@ mod tests { NotifMeta { title: "subject title", subject_type: Some(NotifySubjectType::Issue), - html_url: "http://forge/issues/1", + html_url: "http://forge/issues/1", // lint:allow: test fixture, not a real forge link num: " #1".to_owned(), repo: " [agents/x]".to_owned(), meta_suffix: "\nassignee: unassigned".to_owned(), diff --git a/hive-forge/src/notify.rs b/hive-forge/src/notify.rs index aeeca280..7c4e42a6 100644 --- a/hive-forge/src/notify.rs +++ b/hive-forge/src/notify.rs @@ -109,7 +109,7 @@ pub fn mark_read_best_effort(client: &Client, repo: &str, number: u64) { /// True when a notification `subject.url` refers to issue/PR `number` in /// the (already repo-scoped) query. Forgejo subject URLs end in the -/// issue/PR number (`…/repos/o/r/issues/42`, or `…/pulls/42`); match the +/// issue/PR number (an `/issues/` or `/pulls/` path); match the /// trailing path segment. Tolerates a trailing slash. #[must_use] pub fn subject_matches(subject_url: &str, number: u64) -> bool { @@ -137,7 +137,7 @@ mod tests { "pinned": false, "subject": { "title": "whatever", - "url": "https://forge/api/v1/repos/o/r/issues/7", + "url": "https://forge/api/v1/repos/o/r/issues/7", // lint:allow: test fixture, not a real forge link "type": "SomeFutureSubjectTypeWeDoNotKnow" }, "some_new_field": { "nested": 1 } @@ -148,7 +148,7 @@ mod tests { assert_eq!(ns[0].id, Some(42)); assert_eq!( ns[0].subject.as_ref().and_then(|s| s.url.as_deref()), - Some("https://forge/api/v1/repos/o/r/issues/7") + Some("https://forge/api/v1/repos/o/r/issues/7") // lint:allow: test fixture, not a real forge link ); assert_eq!(ns[1].id, Some(43)); assert!(ns[1].subject.is_none()); @@ -157,7 +157,7 @@ mod tests { #[test] fn matches_issue_subject_url() { assert!(subject_matches( - "https://forge/api/v1/repos/o/r/issues/42", + "https://forge/api/v1/repos/o/r/issues/42", // lint:allow: test fixture, not a real forge link 42 )); } @@ -170,7 +170,7 @@ mod tests { #[test] fn tolerates_trailing_slash() { assert!(subject_matches( - "https://forge/api/v1/repos/o/r/issues/9/", + "https://forge/api/v1/repos/o/r/issues/9/", // lint:allow: test fixture, not a real forge link 9 )); } @@ -178,7 +178,7 @@ mod tests { #[test] fn rejects_different_number() { assert!(!subject_matches( - "https://forge/api/v1/repos/o/r/issues/42", + "https://forge/api/v1/repos/o/r/issues/42", // lint:allow: test fixture, not a real forge link 7 )); } @@ -192,7 +192,7 @@ mod tests { fn rejects_substring_number() { // 142 must not match 42 — full-segment parse, not substring. assert!(!subject_matches( - "https://forge/api/v1/repos/o/r/issues/142", + "https://forge/api/v1/repos/o/r/issues/142", // lint:allow: test fixture, not a real forge link 42 )); } diff --git a/hive-priv/README.md b/hive-priv/README.md index c66597e6..5b25b715 100644 --- a/hive-priv/README.md +++ b/hive-priv/README.md @@ -55,7 +55,7 @@ sets a per-call cwd, so with `services.hyperhive.c0re.buildSlots > 1`, two concurrent calls (any mix of `create`/`update`) could share that one `.tmp`: one's `readlink(".tmp")` resolving to the _other's_ build output, handing an agent's container the wrong agent's closure — the -"agent container gets closure of other agent" bug (hyperhive#3312). +"agent container gets closure of other agent" bug. Building the toplevel here and passing the resolved store path via `--system-path` for _every_ call means `buildFlake()` never runs at all, diff --git a/scripts/check-issue-refs.sh b/scripts/check-issue-refs.sh index 73254b51..7a30b54c 100755 --- a/scripts/check-issue-refs.sh +++ b/scripts/check-issue-refs.sh @@ -1,47 +1,47 @@ #!/bin/sh -# CI lint: flags tracker tags (a hash followed by an issue number) in -# source comments. The hive convention is prose, not tracker tags, in -# code (see /knowledge/hive-rules.md) — tags rot, they point at moving -# targets and leak tracker coupling into the source tree. +# CI lint: flags tracker references — a `#N` tag or a full `.../issues/N` +# forge URL — anywhere in tracked text, source or docs. Prose, not tracker +# references: in code because tags rot; in markdown because the forge's +# public mirror carries no issue/PR data at all, so bare/qualified/glued +# `#N` and a full link are equally dead weight for a public reader — a +# full URL is the same problem spelled out longer, not a safer swap for a +# short tag. No markdown exemption: one used to exist, dropped once that +# read as still allowing exactly this. # -# Emits a CI error annotation per hit and exits 1 if any tag is found, -# 0 otherwise. It runs as its own CI job and IS a required check on the -# forge (branch protection) — a hit blocks merge. +# Emits a CI error annotation per hit, exits 1 if any hit is found. Its own +# required CI job (branch protection) — a hit blocks merge. # -# Scope: tracked *.rs *.nix *.js *.ts *.tsx *.css *.html. Markdown is exempt -# (prose docs may legitimately cite the tracker). The pattern matches a -# hash, 2-5 digits, then a non-alphanumeric char or end-of-line. A real -# tracker tag is never glued to a letter, so the trailing class skips -# both letter-bearing / 6-8-digit hex colours (the digit run breaks or -# overruns) and digit-runs followed by a letter — e.g. hash-route -# fragments like #24h. Residual: a pure-numeric short hex (e.g. three -# identical digits) trips it — write the six-digit form to dodge. +# Scope: every tracked `*.rs *.nix *.js *.ts *.tsx *.css *.html *.md`. Two +# alternatives: a hash, 2-5 digits, then non-alphanumeric-or-EOL (skips +# letter-bearing hex colours and digit-runs-then-letter, e.g. `#24h`; +# residual: a pure-numeric short hex trips it, write the six-digit form to +# dodge); or an `/issues/N` path segment, catching a full link via +# `$HIVE_FORGE_URL` or a literal domain alike. # -# Escape hatch: a line containing the marker `lint:allow` is exempt. -# Reserve it for genuine `#` that aren't tracker tags — e.g. a -# `#123` markdown-heading example or hash-prefixed test-input data — -# and keep a short reason next to the marker. Don't use it to keep a -# real tracker tag; rewrite those to prose. +# Escape hatch: a line with the marker `lint:allow` is exempt. Reserve it +# for a genuine non-tag hit (a `#123` heading example, test-input data) and +# keep a short reason next to it — not for a real reference of either +# form; rewrite those to prose that stands on its own instead. set -eu -pattern='#[0-9]{2,5}([^0-9a-zA-Z]|$)' +pattern='#[0-9]{2,5}([^0-9a-zA-Z]|$)|/issues/[0-9]+([^0-9a-zA-Z]|$)' # `/dev/null` forces grep to always print a filename prefix, even when -# xargs hands it a single file. `-r`/`-0` keep it robust to odd paths -# and an empty file list. Lines carrying the `lint:allow` marker are -# dropped (legitimate non-tracker `#`; see the header). +# xargs hands it a single file. `-r`/`-0` keep it robust to odd paths and +# an empty file list. Lines carrying the `lint:allow` marker are dropped +# (legitimate non-tracker hit; see the header). hits="$( - git ls-files -z '*.rs' '*.nix' '*.js' '*.ts' '*.tsx' '*.css' '*.html' \ + git ls-files -z '*.rs' '*.nix' '*.js' '*.ts' '*.tsx' '*.css' '*.html' '*.md' \ | xargs -0 -r grep -nE "$pattern" /dev/null 2>/dev/null \ | grep -v 'lint:allow' || true )" if [ -n "$hits" ]; then echo "$hits" | while IFS=: read -r file lineno _; do - printf '::error file=%s,line=%s::tracker tag in source — write prose, not a hash-number tag (see /knowledge/hive-rules.md)\n' "$file" "$lineno" + printf '::error file=%s,line=%s::tracker reference — write prose that stands on its own, not a hash-number tag or a full issue URL (see /knowledge/hive-rules.md)\n' "$file" "$lineno" done count="$(printf '%s\n' "$hits" | wc -l | tr -d ' ')" - printf 'check-issue-refs: %s tracker tag(s) found in source\n' "$count" >&2 + printf 'check-issue-refs: %s tracker reference(s) found\n' "$count" >&2 exit 1 fi exit 0 diff --git a/swarm-authelia-bridge/README.md b/swarm-authelia-bridge/README.md index 49fa1d56..885e385f 100644 --- a/swarm-authelia-bridge/README.md +++ b/swarm-authelia-bridge/README.md @@ -43,7 +43,7 @@ It used to be otherwise, and the seam was real: each side had its own `users.json` treated as authoritative, rendering the _same_ physical `users.yml`. A writer whose own JSON was missing could not tell "nothing here yet" from "someone else's users", so it refused to write at all — -which is exactly what a hive with existing users hit (#3422). +which is exactly what a hive with existing users hit. What still has to hold, since two processes share the file: diff --git a/swarm-controller/README.md b/swarm-controller/README.md index 745ee52b..ace621ea 100644 --- a/swarm-controller/README.md +++ b/swarm-controller/README.md @@ -16,7 +16,7 @@ That is the whole intent of the first slice. The point is to make the _unit_ real — service user, runtime and state directories, socket, nginx reachability — so the swarm-level surfaces that follow have somewhere to land. Inventing those surfaces before they are agreed would bake in a shape nobody -chose. See #3066 and the `hyperhive.swarm` consolidation epic. +chose. See the `hyperhive.swarm` consolidation epic. ## Why a unix socket, not a port diff --git a/swarmctl/README.md b/swarmctl/README.md index b722538d..51158f47 100644 --- a/swarmctl/README.md +++ b/swarmctl/README.md @@ -32,7 +32,7 @@ There used to be: a private `users.json` here, canonical, with `users.yml` rendered from it, while `swarm-authelia-bridge` kept its own pair against the _same_ physical file. Two canonical stores for one file is a seam, and it bit — a writer whose own JSON was missing could not tell "nothing here -yet" from "someone else's users", and refused to write (#3422). +yet" from "someone else's users", and refused to write. The argument for the split was that it let this crate work without a YAML parser. It didn't: the JSON was read back on every run, so the round-trip