docs: restructure into topic subdirectories, collapse duplicated index
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.
This commit is contained in:
parent
e4a22b4190
commit
07b62612b0
124 changed files with 301 additions and 377 deletions
|
|
@ -18,12 +18,12 @@
|
|||
//! **Multi-source**: always the internal Forgejo, plus github.com when the
|
||||
//! agent has a PAT. Each source polls independently behind
|
||||
//! [`Source`]; everything below is shared. Rationale
|
||||
//! + host differences: [`docs/forge.md::Sources`](../../../docs/forge.md).
|
||||
//! + host differences: [`docs/integrations/forge.md::Sources`](../../../docs/integrations/forge.md).
|
||||
//!
|
||||
//! Activation gates, self-notification filtering, body excerpt +
|
||||
//! truncation + heading escape, wrapper formats (comment / review /
|
||||
//! new-item / state-change), meta suffix, and review-request override
|
||||
//! all live in [`docs/forge.md::Notification poller`](../../../docs/forge.md).
|
||||
//! all live in [`docs/integrations/forge.md::Notification poller`](../../../docs/integrations/forge.md).
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt::Write as _;
|
||||
|
|
@ -63,7 +63,7 @@ pub const TOKEN_RETRY_MAX: u32 = 20;
|
|||
/// a `new <kind>` label. Later activity that lands on the state-change
|
||||
/// path because it carries no `latest_comment_url` (e.g. a bodiless
|
||||
/// review submission) fires well outside this window, so we must not
|
||||
/// claim it's "new" — see docs/forge.md, "new vs activity on".
|
||||
/// claim it's "new" — see docs/integrations/forge.md, "new vs activity on".
|
||||
const NEW_ITEM_TOLERANCE_SECS: i64 = 120;
|
||||
|
||||
/// Fetch the account's own login for self-notification filtering.
|
||||
|
|
@ -111,7 +111,7 @@ fn notif_type_label(t: Option<NotifySubjectType>) -> &'static str {
|
|||
/// Escape strict-ATX markdown headings in a body before embedding it
|
||||
/// inside the forge-notify wrapper, so a leading `## title` line
|
||||
/// doesn't blow into an h2 in the dashboard render. See
|
||||
/// `docs/forge.md::Body excerpt + truncation + heading escape` for
|
||||
/// `docs/integrations/forge.md::Body excerpt + truncation + heading escape` for
|
||||
/// the strict-ATX-vs-`#tag` rationale and the `split_inclusive`
|
||||
/// trailing-newline contract.
|
||||
fn escape_md_headings(body: &str) -> String {
|
||||
|
|
@ -196,7 +196,7 @@ fn is_username_byte(b: u8) -> bool {
|
|||
/// `@username` mention AND aren't already present (as a substring) in
|
||||
/// `included_excerpt`. Surfaces tags that fell outside the truncation
|
||||
/// window so addressed agents never silently miss a mention on a long
|
||||
/// body. See `docs/forge.md::Body excerpt + truncation + heading
|
||||
/// body. See `docs/integrations/forge.md::Body excerpt + truncation + heading
|
||||
/// escape` for the truncate-before-escape ordering rule.
|
||||
fn extract_truncated_mention_lines<'a>(full_body: &'a str, included_excerpt: &str) -> Vec<&'a str> {
|
||||
full_body
|
||||
|
|
@ -253,7 +253,7 @@ fn review_state_label(state: &str) -> Option<&str> {
|
|||
/// Build a human-readable wake message for one Forgejo notification,
|
||||
/// or `None` for a self-echo the caller should mark-read without
|
||||
/// delivery. Wrapper format table + meta-suffix shape + number/repo
|
||||
/// extraction live in `docs/forge.md::Wrapper format` +
|
||||
/// extraction live in `docs/integrations/forge.md::Wrapper format` +
|
||||
/// `::Meta suffix`.
|
||||
async fn format_notification<S: Source>(
|
||||
client: &reqwest::Client,
|
||||
|
|
@ -305,7 +305,7 @@ async fn format_notification<S: Source>(
|
|||
|
||||
// Always fetch subject detail for assignee/reviewer metadata so
|
||||
// the meta suffix can show current ownership without a follow-up
|
||||
// fetch (see `docs/forge.md::Meta suffix`).
|
||||
// fetch (see `docs/integrations/forge.md::Meta suffix`).
|
||||
let subject = if subject_api_url.is_empty() {
|
||||
None
|
||||
} else {
|
||||
|
|
@ -361,7 +361,7 @@ async fn format_notification<S: Source>(
|
|||
// that comment was genuinely posted AFTER the close — a comment
|
||||
// racing the merge inside the state-change tolerance window — append
|
||||
// it so it isn't lost (best of both worlds; see
|
||||
// `docs/forge.md::Merge racing a comment`). The ordinary pre-merge
|
||||
// `docs/integrations/forge.md::Merge racing a comment`). The ordinary pre-merge
|
||||
// last comment (created before `closed_at`) is left off.
|
||||
let comment_tail = if has_comment {
|
||||
fresh_post_close_comment_tail(
|
||||
|
|
@ -413,7 +413,7 @@ struct NotifMeta<'a> {
|
|||
|
||||
/// Build the `\nassignee: ...` (and optionally `\nreviewer: ...`)
|
||||
/// suffix appended to every wrapper. Shape + presence rules live in
|
||||
/// `docs/forge.md::Meta suffix`.
|
||||
/// `docs/integrations/forge.md::Meta suffix`.
|
||||
fn build_meta_suffix(subject: Option<&serde_json::Value>, is_pr: bool) -> String {
|
||||
let assignees: Vec<&str> = subject
|
||||
.and_then(|s| s["assignees"].as_array())
|
||||
|
|
@ -675,7 +675,7 @@ fn format_state_change_notification(
|
|||
// time. A review submitted with no body carries no
|
||||
// `latest_comment_url`, so it lands here instead of on the comment
|
||||
// path — and its event time is well after `created_at`. Labeling
|
||||
// that "new PR" is misleading (see docs/forge.md, "new vs activity
|
||||
// that "new PR" is misleading (see docs/integrations/forge.md, "new vs activity
|
||||
// on"): agents dismiss it as a
|
||||
// duplicate of the original open notification. When we can't confirm
|
||||
// creation, fall back to a neutral "activity on" label.
|
||||
|
|
@ -707,7 +707,7 @@ fn format_state_change_notification(
|
|||
// Review-request override: Forgejo doesn't reliably set
|
||||
// `reason == "review_requested"` (often null), so we check the
|
||||
// subject payload's `requested_reviewers` list directly. See
|
||||
// `docs/forge.md::Review-request override`.
|
||||
// `docs/integrations/forge.md::Review-request override`.
|
||||
let is_review_request = is_new
|
||||
&& *is_pr
|
||||
&& !own_login.is_empty()
|
||||
|
|
@ -751,7 +751,7 @@ fn format_state_change_notification(
|
|||
/// `created_at`: within `NEW_ITEM_TOLERANCE_SECS` ⇒ creation. When
|
||||
/// either timestamp is missing or unparseable we default to `true`,
|
||||
/// preserving the prior "new" behavior rather than masking a genuine
|
||||
/// new item behind the neutral fallback. See docs/forge.md, "new vs
|
||||
/// new item behind the neutral fallback. See docs/integrations/forge.md, "new vs
|
||||
/// activity on".
|
||||
fn notification_is_creation(
|
||||
event: Option<OffsetDateTime>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue