Skip to content

fix(gate): doc-warnings documents private items, so broken pub(crate) doc links fail the gate (#2336) - #2354

Merged
macanderson merged 2 commits into
mainfrom
fix/2336-doc-warnings-private-items
Aug 8, 2026
Merged

fix(gate): doc-warnings documents private items, so broken pub(crate) doc links fail the gate (#2336)#2354
macanderson merged 2 commits into
mainfrom
fix/2336-doc-warnings-private-items

Conversation

@macanderson

@macanderson macanderson commented Aug 8, 2026

Copy link
Copy Markdown
Owner

What & why

Rustdoc does not check intra-doc links inside items it is not documenting, so the
doc-warnings gate step — cargo doc --no-deps under -D warnings — was blind to every
broken link in a private module, private function, or pub(crate) item. In a repository
where doc comments are load-bearing (invariants are cited by number from Rust doc
comments; type doc comments are the wire contract), that is the documented failure mode of
the citation scheme itself.

This PR turns the light on and fixes everything it reveals, in one atomic change so main
never has a red window between repairs and enforcement:

  • Adds --document-private-items to the gate command in its three normative homes:
    the Makefile doc-warnings target (still CARGO_SCOPE-aware), ci.yml's raw
    invocation, and CONTRIBUTING.md's gate block (check-gate-parity.sh stays green).
    This is the same posture rust-lang/cargo's CI takes for its internal docs.
  • Adds --keep-going to the same command: rustdoc bails at the first failing crate,
    which has repeatedly masked the next dependency layer's break (docs(stella-core): unbreak main — drop private intra-doc links in LoopVerdict::evidence #1823 was diagnosed one
    layer at a time). With it, one gate run reports every crate.
  • Repairs all 34 references the flag surfaces, across nine crates
    (stella-diag, stella-context, stella-store, stella-core, stella-graph,
    stella-observatory, stella-tools, stella-serve, stella-tui). The issue's
    estimate was right: the five known stella-context errors were one crate of a much
    larger population, including links whose targets had been renamed or deleted
    render_transcriptrender_transcript_window, RepoBackend::pushpush_branch,
    fetch_urlfetch_raw, RESUME_GRACE → the configured resume_grace /
    DEFAULT_RESUME_GRACE, and BlockDraft::without_local_content, a mechanism that no
    longer exists (the doc now describes the real one: decomposition maps
    AttachmentSource::Data to no local preimage).

Closes #2336

The repair rules (for review)

Rustdoc resolves intra-doc links with ordinary Rust name-resolution visibility from the
linking scope — --document-private-items does not change that. So:

  • A target that is pub/pub(crate) (or reachable through a pub(crate) use re-export,
    e.g. crate::store::domains_by_node) gets a real link target; display text is unchanged.
  • A fully-private item in a sibling module cannot be linked from anywhere outside its
    subtree (this is why stella-graph's already-qualified crate::store::index_one and
    crate::walk::DENY_DIRS failed). Those become prose backticks, usually with a link to
    the visible containing module — the same shape fix(stella-store,repo): unbreak main — rustdoc private-link + obsolete event.rs ratchet entry #1965/fix(stella-cli): unbreak main — unresolved SkipReason doc link in daemon::boot #1970 used.
  • [tests::…] references point into #[cfg(test)] modules that never exist in a doc
    build → prose backticks.
  • argv[0], agent[0], "sha256:<hex>" → backticked so rustdoc stops parsing them as
    links/HTML.
  • The accept.rs twins (stella-observatory / stella-serve) received byte-identical
    edits, keeping the_two_copies_of_this_policy_have_not_drifted green.
  • God files (driver.rs, deck_ui.rs, registry.rs, stella-store/lib.rs) were edited
    strictly in place — zero added lines.

The witness

  • This PR includes a witness (fails on main, passes here) — the gate command
    itself is the witness
    : RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items --keep-going exits 101 on main (34 errors, nine
    crates failing) and 0 on this branch (verified locally, full workspace).

The gate

  • cargo fmt --check (clean locally)
  • cargo clippy --workspace --all-targets -- -D warnings — left to CI (doc-comment-only
    Rust changes; this machine deliberately does not run workspace-wide builds)
  • cargo test --workspace — left to CI, same reason
  • Docs updated where behavior/flags changed (Makefile help text, ci.yml comment,
    CONTRIBUTING.md gate block)
  • CLA signed
  • Closes #2336 appears both above and as a commit trailer

Also run locally: the full flagged doc build (exit 0) and check-gate-parity.sh (OK).

Cost of the flag (the issue asked): on an identical warm cache, forcing a full re-doc
of all 21 workspace crates — old command 28.1s wall, new command 28.4s wall (~1%; the
extra rustdoc work hides inside build parallelism). Pre-push hook and CI impact is noise.

Nothing left behind

Ground-rule check

  • No I/O added to stella-core (doc comments only); no new deps

Anything reviewers should know?

  • make docs (the human browse target) deliberately keeps building without
    --document-private-items: whether browsed docs should include every private item is a
    reading-experience preference, and "now vs right" on that is the maintainer's call. The
    gate and CI are what must see private items, and now do.
  • One rustdoc quirk worth knowing: deck_ui/create.rs's module doc resolves some of its
    link fragments at the parent module's scope (rustdoc merges outer ///-on-mod docs
    with inner //! docs and loses the span). The three affected links now use
    crate-absolute targets, which resolve identically from either scope.
  • demo-scenario.sh and the ultra-audit skill config still use the plain command — both
    are stress/audit harnesses, not the gate, and were left alone on purpose.

Summary by Sourcery

Tighten the rustdoc gate to cover private items and keep running on multiple failures, and repair all intra-doc links and documentation references surfaced by the new checks across the workspace.

Enhancements:

  • Improve internal diagnostics and behavior descriptions in doc comments, including references to configuration fields and behavior summaries, without changing runtime code paths.

Build:

  • Update the Makefile doc-warnings target to run rustdoc with --document-private-items and --keep-going so the gate enforces clean docs for public and private items.
  • Adjust the CI workflow to use the stricter rustdoc invocation, ensuring private and pub(crate) docs are checked and multiple failing crates are reported in a single run.

Documentation:

  • Update CONTRIBUTING guidelines to reflect the strengthened doc gate command.
  • Clarify and correct numerous intra-doc links, references, and prose in rustdoc comments across multiple crates so they point at the current APIs and avoid links to private or test-only items.

…nks are checked

Rustdoc only checks intra-doc links inside items it documents, so the
doc-warnings gate step — cargo doc --no-deps with -D warnings — was
blind to every broken link in a private module, private function, or
pub(crate) item. Adding --document-private-items surfaced 34 broken
references across nine crates, all pre-existing on main: paths that do
not resolve from their scope, links to renamed or deleted items
(render_transcript, RepoBackend::push, fetch_url, RESUME_GRACE,
BlockDraft::without_local_content), links into #[cfg(test)] modules
that can never resolve in a doc build, and prose like argv[0] or
sha256:<hex> that rustdoc parses as links or HTML.

Every site is repaired in this commit — a resolving target where one
exists (rustdoc resolves links with normal visibility rules from the
linking scope, so only pub(crate)-or-wider targets are linkable across
modules), prose with backticks where none can (test modules,
fully-private items in sibling modules). The accept.rs twins stay
byte-identical for their drift test. The flag flips in the same commit
in all three normative homes (Makefile doc-warnings, ci.yml,
CONTRIBUTING.md), so main never sees a red window between repairs and
enforcement.

--keep-going rides along on the same command: rustdoc bails at the
first failing crate, which has repeatedly masked the next layer's
break (#1823); with it the gate reports every crate in one run.

Closes #2336

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stella-cli-docs Ready Ready Preview Aug 8, 2026 10:19pm

@sourcery-ai

sourcery-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR updates the Rustdoc gate to document and check private items, ensures the gate keeps running across all crates, and then fixes all intra-doc links and doc-comment references exposed by that stricter check across multiple crates without changing runtime behavior.

Sequence diagram for the updated rustdoc gate command checking private items

sequenceDiagram
    actor Dev
    participant Makefile
    participant CI
    participant Cargo
    participant Rustdoc

    Dev->>Makefile: make doc-warnings
    Makefile->>Cargo: cargo doc $(CARGO_SCOPE) --no-deps --document-private-items --keep-going

    Dev->>CI: push / PR
    CI->>Cargo: cargo doc --workspace --no-deps --document-private-items --keep-going

    Cargo->>Rustdoc: run with RUSTDOCFLAGS="-D warnings"

    loop each_crate_in_workspace
        Rustdoc->>Crate: build_docs_with_private_items
        Crate-->>Rustdoc: intra_doc_links (public + pub(crate) + private)
        alt doc_warnings_present
            Rustdoc-->>Cargo: emit_warning_as_error_for_crate
            note over Rustdoc,Cargo: command continues to next crate due to --keep-going
        else no_doc_warnings
            Rustdoc-->>Cargo: success_for_crate
        end
    end

    Cargo-->>Dev: exit 0 if all crates clean
    Cargo-->>CI: exit 101 if any crate fails gate
Loading

File-Level Changes

Change Details Files
Strengthen the rustdoc gate to include private items and continue through all crates, and reflect that in CI and contributor docs.
  • Add --document-private-items and --keep-going flags to the doc-warnings Makefile target while keeping CARGO_SCOPE support.
  • Update the CI workflow cargo doc step to use the same flags and expand the surrounding comment to explain the rationale.
  • Update CONTRIBUTING gate instructions to use the new rustdoc invocation with private items and keep-going semantics.
Makefile
.github/workflows/ci.yml
CONTRIBUTING.md
Repair broken or fragile intra-doc links in stella-context so they resolve correctly under private-item documentation.
  • Turn bare references to DEFAULT_RECENCY_WEIGHT and DEFAULT_MMR_CANDIDATE_MULTIPLE into fully-qualified intra-doc links from the ranking module.
  • Fix the link to SelectionReason::is_required to use a crate-absolute path.
  • Make references to domains_by_node, NODE_AS_OF, live_node_metas, and score_nodes_by_vector use crate-absolute paths where needed.
  • Change references to tests modules that are cfg(test) into prose rather than doc links to avoid unresolved targets.
crates/stella-context/src/retrieval/ranking.rs
crates/stella-context/src/candidates.rs
crates/stella-context/src/ann.rs
crates/stella-context/src/retrieval.rs
crates/stella-context/src/store/domain.rs
crates/stella-context/src/store/schema.rs
Fix intra-doc links and clarify documentation around driver, loop evidence, receipts, and step handling in stella-core.
  • Qualify references to LENGTH_CONTINUATION_NUDGE, recent_call_records, and Engine::apply_overflow_summary with proper module paths.
  • Turn a plain mention of loop_detect::same_record into prose rather than a broken link.
  • Update receipts docs to describe the current attachment handling mechanism instead of a removed BlockDraft::without_local_content API.
  • Adjust the step module doc to link to Engine::run_model_call via a crate-absolute type reference.
crates/stella-core/src/driver.rs
crates/stella-core/src/driver/loop_evidence.rs
crates/stella-core/src/receipts.rs
crates/stella-core/src/step.rs
Repair intra-doc links and doc comments in stella-serve to point at the correct types and functions and avoid references into test-only or private items.
  • Change ServerFrame link in the server module docs to reference crate::frame::ServerFrame explicitly.
  • Qualify SessionSpec::reverse_request_timeout with its module path.
  • Update resume grace documentation to refer to the configured resume_grace and DEFAULT_RESUME_GRACE rather than a removed RESUME_GRACE constant.
  • Ensure lifecycle and termination_signal docs link correctly to serve in the server module.
  • Clarify references to DrivenTurn and TurnState in session docs without creating invalid links.
  • Keep accept.rs copies in stella-serve and stella-observatory in sync while changing references to the drift-detection test name into prose.
crates/stella-serve/src/server.rs
crates/stella-serve/src/lifecycle.rs
crates/stella-serve/src/session.rs
crates/stella-serve/src/accept.rs
crates/stella-observatory/src/accept.rs
Fix doc links and prose in stella-tui for deck UI creation, rendering, and transcript UI behavior.
  • Change links to InstalledMode::Creating and settle_* functions to crate-absolute paths from deck_ui/create.
  • Reword the documentation around the transcript panel to avoid linking a now-renamed render_transcript function.
  • Qualify render_composer reference by naming its module explicitly.
  • Backtick agent[0] and agent[1] in deck_ui to avoid rustdoc interpreting them as links.
  • Qualify TranscriptEntry::Evicted with its module path in render/row docs.
crates/stella-tui/src/deck_ui/create.rs
crates/stella-tui/src/render.rs
crates/stella-tui/src/deck_ui.rs
crates/stella-tui/src/render/row.rs
Adjust doc comments and intra-doc links in stella-graph and stella-store to reflect current APIs and avoid linking to private items.
  • Replace links to private index_one and DENY_DIRS items with prose descriptions pointing at their containing modules in stella-graph.
  • Backtick sha256: in reconstruct docs and comments to avoid rustdoc treating them as links.
  • Update export_all_json link in Store docs to use an associated method path.
crates/stella-graph/src/generated.rs
crates/stella-store/src/reconstruct.rs
crates/stella-store/src/lib.rs
Repair intra-doc links and doc-comment references in stella-diag to use correct item paths and avoid broken links.
  • Remove an unnecessary crate::Filter link target and leave Filter as plain text.
  • Qualify note! macro reference with its crate path so the doc link resolves.
crates/stella-diag/src/dx.rs
crates/stella-diag/src/redact.rs
Fix doc links in stella-tools to match current function names and module structure and make literal arguments clearer to rustdoc.
  • Clarify that the drift-detection test marker_line_matches_the_pipeline_contract is a test and reference it in prose.
  • Qualify is_symbol_shaped link with its crate::code_map module path.
  • Clarify the relationship to scripts::resolve_command_for_gate using prose rather than a direct link to a private function.
  • Backtick argv[0] in registry docs to avoid rustdoc parsing it as a link.
  • Update RepoBackend::push reference to RepoBackend::push_branch to match the current API.
  • Update fetch_url reference to fetch_raw in web client docs.
crates/stella-tools/src/authored_diff.rs
crates/stella-tools/src/bash.rs
crates/stella-tools/src/project.rs
crates/stella-tools/src/registry.rs
crates/stella-tools/src/repo.rs
crates/stella-tools/src/web.rs

Assessment against linked issues

Issue Objective Addressed Explanation
#2336 Update the doc-warnings gate to run cargo doc with --document-private-items so that private and pub(crate) items’ intra-doc links are checked, keeping CARGO_SCOPE working and gate parity in CI/CONTRIBUTING.
#2336 Repair all broken intra-doc links surfaced when running RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items, including the stella-context links listed in the issue and any additional workspace-wide failures, so the new gate passes cleanly.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@macanderson
macanderson merged commit 298b270 into main Aug 8, 2026
16 of 17 checks passed
@macanderson
macanderson deleted the fix/2336-doc-warnings-private-items branch August 8, 2026 22:19
macanderson added a commit that referenced this pull request Aug 8, 2026
…e query actually narrowed (#2333) (#2356)

## What

Domain overlap becomes an admission channel again — this time against a
scope **the query itself narrowed**, which is the property that was
missing when it shipped and the reason it was removed.

A recall now carries two domain scopes (`RecallScope`):

| scope | source | filters | ranks | **admits** |
|---|---|---|---|---|
| `session` | the workspace vocabulary (`Domains::names()`) | ✅ | ✅ | ❌
|
| `query` | the domains owning the files **this goal named** | ❌ | ❌ |
✅, conditionally |

Admission requires `query` to be a **non-empty proper subset** of
`session` (`evidence::scope_is_query_conditional`).

## Why the proper-subset condition is the whole fix

If the two scopes are equal, "shares a domain with the query" and "is in
scope at all" are the *same predicate* — and the second is already the
filter every candidate passed to get here. The rung would admit the
entire in-scope corpus, which is precisely what it did: the session
hands recall its whole vocabulary and nothing narrowed it, so the gate
admitted every tagged node on every prompt, and reflection write-back
tags every episode whose turn touched files. That was #2289 reopened at
full width, and it is why PR #2298 removed the rung outright rather than
patching it.

**A scope must narrow to discriminate.** Narrowing `session` instead was
the tempting one-value version and is strictly worse: `session` also
drives `node_ids_excluded_by_scope`, so a narrower value silently starts
**suppressing** memories rather than merely declining to admit them.
Hence two fields, not one.

## How

- **`RecallScope`** (`crates/stella-context/src/retrieval/scope.rs`) —
the two-scope type. `recall_scoped_excluding` takes it; `recall` and
`recall_scoped` stay as conveniences and document that they can never
admit on domain, so a caller with no per-query scope gets the
conservative behavior *by construction* rather than by remembering to
ask.
- **Derivation** (`ScopedStore::query`,
`crates/stella-cli/src/contextgraph.rs`) — `query_domain_scope` maps the
goal's anchors through `Domains::domains_for_path`. Anchors are already
workspace-relative paths (`goal_path_anchors`), which is exactly what
that function consumes, so no URI parsing is involved. An anchor in any
other spelling matches no prefix and drops out — narrowing the scope
*less*, which can only make the gate more reluctant to admit. That is
the safe direction. `ScopedStore` now holds the `Domains` taxonomy
rather than just its names; `ContextQuery` stays workspace-agnostic, so
the wire contract is untouched.
- **No extra I/O.** A query scope that narrows a non-empty session scope
implies the corpus tag map was already loaded for the overlap ranking,
so the evidence projection is a filter over rows in hand, never a second
scan.

## Witness

**In the store** — one corpus, one prompt, a single variable changed:

| test | query scope | result |
|---|---|---|
| `a_full_vocabulary_domain_scope_is_not_evidence` | the whole
vocabulary | **0 frames**, `no_evidence_cut` 5 |
| `a_narrowed_domain_scope_is_evidence` | one domain of it | exactly
that domain's `note-0`, `note-3`; other three refused |

No note shares a distinctive term with the prompt, so domain overlap is
the only channel that can fire — these read the rung directly. The
narrowed case is a true fail→pass witness: with the channel disabled it
returns `[]` against the expected `["note-0", "note-3"]`, verified by
neutering `scope_is_query_conditional` and re-running.

`recall_scoped_alone_never_admits_on_domain` pins the convenience API's
posture. Four unit tests pin the predicate itself, including that
repeats cannot fake a narrowing (set semantics, not list length) and
that a scope reaching outside the vocabulary is not a subset.

**In the CLI** — six tests pin the derivation
(`query_domain_scope_derivation`), including the sweeping goal that
names a file in every domain and therefore narrows nothing. That
degenerate case is pinned on **both** sides of the boundary
deliberately: the two halves have to agree on it, and it is the exact
predicate that shipped inverted.

## File-size ratchet

`RecallScope` pushed `retrieval.rs` to 1519 lines, past the 1500 limit,
and the file is not grandfathered — so it was **split, not baselined**
(AGENTS.md § God files). 1444 now.

The split follows a real seam rather than the line count:
`retrieval::scope` owns domain scoping entire — the type plus the two
projections the corpus tag map feeds, `overlap_ranking` (ranks, against
`session`) and `evidence_ids` (admits, against `query`). Putting them
side by side is the point. They read the same map through different
scopes, that asymmetry is the subtlest thing in retrieval, and it has
already been got wrong once. Both are pure functions over loaded rows,
matching the `evidence` and `ranking` siblings; the parent keeps the
query that loads the map.

## Docs

The three prose sites that describe the channels move together, as they
must: the `evidence.rs` module doc, the `require_evidence` doc comment
in `crates/stella-cli/src/settings/context.rs`, and
`docs/spec/adaptive-context/adaptive-context.md` §6.1 — which now states
the general rule rather than just this instance: admission is strictly
narrower than ranking, and a predicate the query does not vary cannot be
an admission rung.

## Verification

- `cargo test -p stella-context` — 175 passed, 0 failed.
- `cargo test -p stella-cli` — 1500 unit + 12 integration binaries, 0
failed.
- `cargo clippy -p stella-context -p stella-cli --all-targets -- -D
warnings` — clean.
- `RUSTDOCFLAGS="-D warnings" cargo doc` — clean (exit 0).
- `cargo fmt --all --check` — clean.
- `make guards-fast` — all guards green, `check-file-size` and
`check-module-reachability` included.

## Notes on CI

**`main` is red independently of this branch.** `shellcheck` fails on
`scripts/test-arena-scripts.sh` (arrived via #2328/#2351), which reds
every open PR whatever it changed. Filed as **#2355** with the fix;
deliberately **not** folded in here, since a shared red gate that
several PRs each "helpfully" repair is its own failure mode. This diff
touches no shell script.

**Forward-checked against #2354.** That PR (open) tightens
`doc-warnings` to `--document-private-items`, which surfaces doc links
inside `pub(crate)` items. Ran this branch under the stricter flag:
**zero errors in any code this PR adds or touches** — `scope.rs`,
`evidence.rs`, `evidence_tests.rs`, `contextgraph.rs`, and every added
line of `retrieval.rs` are clean. The 9 that do fire are all
pre-existing on `main` in files this PR does not touch (`candidates.rs`,
`ranking.rs`, `ann.rs`, `store/domain.rs`, `store/schema.rs`, and
`retrieval.rs`'s own module doc), and are exactly what #2354 repairs. So
this merges green in either order.

Closes #2333
Refs #2289
@macanderson

Copy link
Copy Markdown
Owner Author

The failing check here is not this diff: main is red on shellcheck (issue #2355, introduced by the arena-lifecycle scripts from #2328/#2351 — this PR touches no shell script). The unbreak is PR #2363; once it merges, a branch update / re-run should turn this green.

macanderson added a commit that referenced this pull request Aug 8, 2026
…check and the gate are green again (#2355) (#2363)

## What & why

`main` is red: the `shellcheck` gate step fails on
`scripts/test-arena-scripts.sh`
(arrived with #2328, extended by #2351) with nine `SC2016`/`SC2028`
info-level findings,
and since `shellcheck` is a `GATE_STEPS` entry and a required check,
every open PR is red
regardless of its diff (observed on #2354, which touches no shell
script).

The findings are false positives about intent — the generator `echo`s
single-quoted lines
so that `$1`, `$STUB_LOG` and `\n` land literally in the generated stub.
This PR takes
issue #2355's preferred fix (option 1): emit the stub with a **quoted
heredoc**
(`cat <<'STUB'`), whose content is literal by construction, so both
codes stop applying
and the intent is self-evident to reader and linter alike. No disables,
no gate widening,
step name untouched (`check-gate-parity.sh` unaffected).

Bonus the heredoc buys for free: the old form was interpreter-dependent
— under `sh`
(XSI `echo`), the `\n` in the `printf` line expands and splits the
format string across
two lines, exactly the hazard `SC2028` names. Benign in practice (the
script runs under
bash, and `printf "%s<newline>"` behaves the same), but now it cannot
happen at all.

Closes #2355

## The witness

- [x] The gate step itself is the witness: `make shellcheck` **fails on
`main`** (exit 1,
nine findings) and **passes here** (verified locally). The generated
stub is proven
**byte-identical** under bash — both generator forms were run side by
side and
compared with `cmp` — and `bash scripts/test-arena-scripts.sh` passes
**20/20**,
      including the stub-consuming crash/handoff classification checks.

## The gate

- [x] `make shellcheck` green locally; `bash
scripts/test-arena-scripts.sh` 20/20
- [x] Shell-only diff — no Rust compiled; clippy/test unaffected and
left to CI
- [x] `Closes #2355` appears both above and as a commit trailer

## Nothing left behind

- [x] There is nothing: the fix is the issue's own prescribed option 1,
and the
interpreter-dependence observation above is fixed by the same change.
Related
      pre-existing alerts remain tracked in #2121.

## Anything reviewers should know?

Landed on its own from a fresh `main` per the issue's constraint (a red
shared gate must
not be repaired inside unrelated PRs — the #2004 merge-skew lesson).
Once this merges,
open PRs (e.g. #2354) need only a re-run / branch update to go green.

## Summary by Sourcery

Emit the arena launch stub using a quoted heredoc to restore shellcheck
gate success while preserving the generated script’s behavior.

Bug Fixes:
- Resolve shellcheck SC2016/SC2028 findings in
scripts/test-arena-scripts.sh that were causing the shared gate to fail
on main.

Enhancements:
- Generate the launcher stub via a quoted heredoc to make the intended
literal content clearer and avoid interpreter-dependent \n handling.
macanderson added a commit that referenced this pull request Aug 8, 2026
…ate one (#2365)

## What & why

**`main` is red, and every open PR is red with it.** One line fixes it.

`WorkspaceProbe::diff` is public and its doc comment linked
`[`Self::ignores`]`, which is private.
`rustdoc::private_intra_doc_links` is denied under `-D warnings`, so
`cargo doc` fails the required `fmt + clippy + test` job:

```
error: public documentation for `diff` links to private item `Self::ignores`
  --> crates/stella-tools/src/shell_touch.rs:349:39
error: could not document `stella-tools`
```

Reproduced on main's own runs at `ad92643b` and `298b2705`, not just on
a PR head.

## How it got in

#2344 introduced the link. Its branch predated #2354, so the `cargo doc`
gate that ran against it was the older command, and the failure it *did*
report was read as the pre-existing shellcheck breakage that #2363 was
already fixing.

## One thing worth a follow-up thought on #2336 / #2354

`--document-private-items` does **not** silence this lint for a public →
private link. rustdoc's own note says "this link will resolve properly
if you pass `--document-private-items`" — and both `make doc-warnings`
and `ci.yml` already pass it, at the exact commits that failed. So the
hint is misleading for this direction.

That does not weaken #2354; the gate caught a real defect. It just means
the working rule is narrower than the hint suggests: **a public item
cites a private helper in prose, never as an intra-doc link.**
`pub(crate) → pub(crate)` links, which #2354 was about, are unaffected.

## The fix

The link becomes prose. No API change, no behavior change — deliberately
the smallest possible diff, because an unbreak PR that also does
something else is how a red `main` stays red longer.

## Witness

- [ ] This PR includes a witness test

None, and none is possible: the failing check *is* the witness. `cargo
doc -D warnings` fails on `main` at this commit's parent and passes here
— a witness test cannot assert about a rustdoc lint, and the gate
already does.

## Gate

Not run locally — a Terminal-Bench match is executing on this machine
and a workspace build would contend for CPU, which is how a trial
acquires a false timeout. `make guards-fast` is green; the compile tiers
are CI's.

## Ground-rule check

- [x] No I/O added to `stella-core`; no new deps
- [x] No new outbound network calls
- [x] No new cross-boundary types

## Summary by Sourcery

Bug Fixes:
- Resolve rustdoc private_intra_doc_links failure by replacing a link to
the private ignores helper with plain prose in the diff method
documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gate: doc-warnings skips private items, so broken intra-doc links in pub(crate) code are invisible

1 participant