Skip to content

fix(gate): unbreak main — a public item may not intra-doc-link a private one - #2365

Merged
macanderson merged 1 commit into
mainfrom
fix/unbreak-main-doc-link
Aug 8, 2026
Merged

fix(gate): unbreak main — a public item may not intra-doc-link a private one#2365
macanderson merged 1 commit into
mainfrom
fix/unbreak-main-doc-link

Conversation

@macanderson

@macanderson macanderson commented Aug 8, 2026

Copy link
Copy Markdown
Owner

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

  • No I/O added to stella-core; no new deps
  • No new outbound network calls
  • 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.

…ate one

`WorkspaceProbe::diff` (pub) linked [`Self::ignores`] (private), which
`rustdoc::private_intra_doc_links` rejects under `-D warnings`. Every PR
opened against main is red until this lands.

Landed by #2344 and not caught locally: the branch predated #2354, so the
`cargo doc` gate it ran was the older command.

Worth noting for #2336/#2354: `--document-private-items` does NOT silence
this lint for a pub → private link. rustdoc's own hint says it will, and
that hint is what made the link look safe. The gate is doing its job; the
rule is simply that public docs cite private helpers in prose, not as links.

Refs #2344
@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
stella-cli-docs Ignored Ignored Aug 8, 2026 10:40pm

@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

@sourcery-ai

sourcery-ai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fixes a failing rustdoc gate by removing an intra-doc link from a public method’s documentation to a private helper, converting the reference to plain prose instead.

File-Level Changes

Change Details Files
Resolve rustdoc private intra-doc link lint by changing the public method’s doc comment to stop linking to a private item.
  • Updated WorkspaceProbe::diff doc comment to replace the intra-doc link to the private ignores helper with a plain-text reference.
  • Ensured there are no API or behavioral changes; only documentation was modified to satisfy the cargo doc -D warnings gate.
crates/stella-tools/src/shell_touch.rs

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

Copy link
Copy Markdown
Owner Author

Independently verified this is the complete unbreak, not just the one CI showed: I ran the full strengthened gate command (RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items --keep-going) on main's tip (8b80519) — with --keep-going so no crate can mask another — and the shell_touch.rs [Self::ignores] link is the only error in the whole workspace (exit 101 → this diff removes the sole finding). make shellcheck is also green on the tip, so #2361 + #2363 composed fine and this PR turns the whole gate green.

One note for the record: --document-private-items does not suppress rustdoc::private_intra_doc_links — a public item's doc may still not link a private item (rustdoc warns the link "will break without" the flag). Prose, as done here, is the right shape.

@macanderson
macanderson enabled auto-merge (squash) August 8, 2026 22:49
@macanderson
macanderson disabled auto-merge August 8, 2026 22:53
@macanderson
macanderson merged commit 71949c6 into main Aug 8, 2026
15 checks passed
@macanderson
macanderson deleted the fix/unbreak-main-doc-link branch August 8, 2026 22:53
macanderson added a commit that referenced this pull request Aug 8, 2026
`cargo doc -D warnings` fails this branch:

    error: public documentation for `workspace_ignore` links to private
           item `crate::walk`
      --> crates/stella-graph/src/workspace_ignore.rs:4
    error: could not document `stella-graph`

`workspace_ignore` is `pub mod`; `walk` is a private `mod`.
`rustdoc::private_intra_doc_links` denies that under `-D warnings`, and
`--document-private-items` does not silence it for a public → private
link — the same rule and the same fix shape as #2365.

The link becomes prose. No API change, no behavior change.
macanderson added a commit that referenced this pull request Aug 8, 2026
…gnore rules (#2360) (#2366)

## What & why

Closes #2360.

`crates/stella-graph/src/walk.rs` has carried this in its own module doc
for two releases:

> **Documented gap (task brief, ignore-discipline clause):** custom
`.gitignore` patterns (per-directory ignore files, negations, glob
rules) are *not* honored — only the built-in deny-list is.

So a generated directory whose name the deny-list has never heard of —
`generated-sdk/`, a sibling checkout, anything project-specific — was
indexed into the code graph and paid for on every recall. #2344 closed
the same gap for the *workspace probe*; this closes it for the *index*,
and makes the two share one answer instead of two approximations.

## The design: ask git, don't reimplement it

New `stella-graph::workspace_ignore` resolves the rules once per walk
with `git ls-files -z --others --ignored --directory
--exclude-standard`. Per-directory ignore files, negations, globs,
`.git/info/exclude`, and the user's global excludesfile therefore behave
exactly as they do at the command line — because the answer **is**
git's. A hand-rolled matcher would be a second ignore engine to keep
correct forever, and its failure mode is silent: a file quietly indexed,
or quietly not.

**Where it lives, and why that is not arbitrary.** `stella-tools`
already depends on `stella-graph` and not the reverse, so putting the
resolver here lets one implementation serve both walkers with **no new
crate and no new dependency edge** — and it costs `stella-graph` nothing
but `std`. The alternative considered and rejected was pulling ripgrep's
`ignore` crate: it would give this crate a dependency *and* leave
`stella-tools` on a different mechanism, so the two could disagree about
the same tree. `stella-tools`' private copy from #2344 is deleted in
this PR.

**The deny-list survives beside the rules, not under them.** They answer
different questions: the rules say what *this repository does not
track*, the deny-list says what is *never worth parsing*. A
Terminal-Bench task directory is not a repository, so it has no rules to
consult — and there the deny-list is the only thing keeping a vendored
bundle out of the index. Witnessed both ways.

**The watcher resolves once at construction**, not per event. The
relevance filter runs on every saved file; resolving per call would be
one `git` invocation per write. The window that opens is a `.gitignore`
edited while a session is live, whose new rules are not seen until the
next full index pass — one wasted re-index, never a wrong row, and the
same direction every other bound in this subsystem fails.

## A defect #2344 shipped, fixed here

`HostDataIsolation::ProcessFree` promises that the registry "omit[s]
every built-in tool that launches a child process". #2344's probe
spawned `git` unconditionally to resolve ignore rules — including under
that attestation. It now resolves to `IgnorePolicy::WalkAll` whenever
the registry is process-free, whatever the `ignore_gitignore` setting
says. Losing the filter there costs walk time, which
`MAX_RECORDED_TOUCHES` already bounds; honoring the setting instead
would cost the guarantee.

This is the "a field's second consumer arms what the first never
checked" shape: `process_free` was consulted at construction for tools
and for exploration coverage, and the probe's new subprocess simply
never asked.

## The witness

- [x] This PR includes witness tests (fail on `main`, pass here)

| Test | File | Proves |
|---|---|---|
|
`a_repositorys_own_ignore_rules_are_honored_including_globs_and_negations`
| `stella-graph/src/walk.rs` | the closed gap — an ignored dir, a glob,
**and** a negation re-admitting one file |
| `the_deny_list_still_applies_when_there_are_no_rules_to_consult` |
`stella-graph/src/walk.rs` | the non-repository posture is unchanged |
| `a_watcher_event_for_an_ignored_path_is_not_relevant` |
`stella-graph/src/walk.rs` | live re-index honors the same answer |
| `a_repositorys_own_rules_are_resolved_including_a_collapsed_directory`
| `stella-graph/src/workspace_ignore.rs` | `--directory` collapsing, and
`excludes` vs `excludes_dir` |
| `a_non_repository_ignores_nothing_even_inside_a_repository` |
`stella-graph/src/workspace_ignore.rs` | the repo-root gate: a `$HOME`
dotfiles repo ignoring `*` cannot blind a scratch dir under it |
| `a_process_free_registry_never_consults_the_repositorys_ignore_rules`
| `stella-tools/src/registry/tests/file_change.rs` | the isolation fix,
**with a control** asserting the same option is honored outside
isolation |

The pre-existing `dist_standalone_and_next_directories_are_never_walked`
is unchanged and still green — that is the non-repository posture stated
as a test that predates this PR.

## God-file accounting

`registry.rs` sat at its exact ratchet ceiling again, so the
process-free resolution went to
`RegistryOptions::effective_probe_ignore_policy` in
`registry/options.rs` and the accessor to `registry/turn_probe.rs`.
`registry.rs` nets **−7**; `shell_touch.rs` nets **−42** from deleting
the duplicated resolver. `file-size` is green and reports "none grew by
this change".

## Docs

`crates/stella-graph/README.md`'s "Gotchas" entry claimed the gap; it
now describes the two-filter arrangement. The `.gitattributes` half of
that entry is genuinely still unresolved and is now stated separately
rather than bundled with a gap that is closed.

## The gate

Not run locally — a Terminal-Bench match is executing on this machine
(`harbor run … sqlite-with-gcov`) and a workspace build would contend
for CPU, which is how a trial acquires a false timeout. `make
guards-fast` is green, including `file-size`, `god-files`,
`module-reachability` and `fmt --check`. The compile tiers are
deliberately CI's.

**Opened as a draft on purpose**: it is unverified until CI compiles it,
and this repository merges PRs fast. Marking it ready is the signal that
the build is green.

- [ ] `cargo fmt --check` · [ ] `cargo clippy --workspace --all-targets
-- -D warnings` · [ ] `cargo test --workspace`
- [x] Docs updated where behavior changed

## Depends on

**#2365** unbreaks `main` (a public item intra-doc-linking a private
one, landed by #2344). Until that merges, this PR is red for a reason
that has nothing to do with it. This branch already carries the
equivalent fix, so expect a one-line conflict on rebase.

## Ground-rule check

- [x] No I/O added to `stella-core`; **no new dependencies in any
crate**
- [x] No new outbound network calls
- [x] No new cross-boundary types (`WorkspaceIgnore` is internal to the
tool/graph layer, not a protocol type)

## Nothing left behind

- `.gitattributes` per-directory merging remains unresolved and is now
named on its own in the README gotcha rather than hidden inside a gap
that is closed. It is pre-existing, unrelated to the walk, and already
visible to a reader of that section.

## Summary by Sourcery

Unify and harden workspace ignore handling by introducing a shared
git-backed WorkspaceIgnore resolver used by both the code-graph walk and
workspace probes, ensuring repository .gitignore rules are honored
alongside the existing deny-list while preserving process-free isolation
guarantees.

New Features:
- Honor repository-specific .gitignore rules when walking and indexing
the code graph, including per-directory files, globs, negations, and
standard git exclude sources.
- Expose a shared WorkspaceIgnore resolver in stella-graph for reuse by
both the code-graph walk and stella-tools' workspace probe.

Bug Fixes:
- Ensure process-free tool registries never spawn git by forcing an
unfiltered walk policy regardless of the configured ignore setting,
restoring HostDataIsolation::ProcessFree guarantees.

Enhancements:
- Combine repository ignore rules with the existing deny-list so
non-repository workspaces still avoid indexing vendored or build output
while repositories respect their own tracked/untracked state.
- Apply repository ignore rules to filesystem watcher events so live
re-indexing uses the same exclusion semantics as full walks.
- Refactor workspace probe ignore handling to use WorkspaceIgnore
instead of an ad hoc path set, simplifying diff logic and making ignore
behavior consistent across tools.

Documentation:
- Update stella-graph README gotchas to describe the new dual-filter
behavior for ignores and to clarify that .gitattributes handling remains
root-level only.

Tests:
- Add integration tests validating that repository ignore rules, globs,
and negations are honored by the index and watcher, that the deny-list
still applies in non-repository workspaces, that WorkspaceIgnore
resolution behavior is correct, and that process-free registries use an
unfiltered ignore policy.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant