Skip to content

refactor: delete the dead trait mocks and four redundant docs - #543

Merged
Destynova2 merged 1 commit into
mainfrom
refactor/drop-dead-trait-mocks
Aug 6, 2026
Merged

refactor: delete the dead trait mocks and four redundant docs#543
Destynova2 merged 1 commit into
mainfrom
refactor/drop-dead-trait-mocks

Conversation

@Destynova2

Copy link
Copy Markdown
Contributor

Why

Two read-only audits, one on src/, one on docs/. This PR applies only the zero-risk findings; the rest are listed below for later.

Code

traits::mocks (151 LOC, 7 mock impls) has zero call sites outside its own file. Searching all seven names returns 14 matches, every one inside traits.rs. Modules that need a mock define their own locally (registry.rs:668, retry.rs:955, dispatch/mod.rs:1065).

The test-util feature stays: providers::mocks behind the same gate is used (registry.rs:657, dispatch/mod.rs:1216).

Docs

  • reference/openai-compatibility.md and reference/responses-api-compatibility.md are 60-73% duplicated into reference/api-compatibility.md, which already documents all three endpoints section by section, in the same order. Deleted, links redirected.
  • The two dci-report-*.md files were point-in-time audit notes whose content describes the creation of the files this PR deletes. Deleted.

Stale claims fixed

  • quickstart.md advertised four presets that do not exist: medium, cheap, fast, local. Real list is perf, ultra-cheap, eu-eco, eu-pro, eu-max, gdpr, eu-ai-act.
  • AGENTS.md told you to run preset apply medium, which fails.
  • README called grob a "6 MB single binary". 6 MB is the musl container image; the binary is 17 MB. The container figure is correct everywhere else and left alone.

Not done here, worth a look

  • Two circuit breaker implementations (security/circuit_breaker.rs 387 LOC + routing/circuit_breaker.rs 421 LOC), both live, overlapping concepts. Unifying is a behavioral change with two config surfaces to migrate. Needs its own PR.
  • 5 of 7 traits have exactly one impl that only delegates to the concrete type already stored in AppState (DlpPipeline, RequestRouter, AuditWriter, EventTap, SpendTracking). About 290 LOC. Tracer and ProviderAvailability are genuinely polymorphic and must stay.
  • GeminiProvider re-implements ProviderBase (is_oauth, supports_model, header loops), about 40 LOC.
  • ADR-0018 carries ~400 lines of pseudocode and sprint planning in an appendix.

Verification

1727 tests pass, clippy clean with all features, doctests pass, fmt clean, lychee link check passes.

@Destynova2
Destynova2 enabled auto-merge (squash) August 6, 2026 07:13
Two audits, one on src/ and one on docs/, both read-only.

Code: `traits::mocks` (151 LOC, 7 mock impls) has zero call sites outside
its own file. agentgrep for all seven names returns 14 matches, every one of
them inside traits.rs. Modules that need a mock define their own locally
(registry.rs:668, retry.rs:955, dispatch/mod.rs:1065). The `test-util`
feature stays because `providers::mocks` is genuinely used.

Docs: `openai-compatibility.md` and `responses-api-compatibility.md` are
60-73% duplicated into `api-compatibility.md`, which already documents all
three endpoints section by section. The two DCI reports were point-in-time
audit notes describing the creation of files this commit deletes.

Stale claims fixed: quickstart listed four presets that do not exist
(`medium`, `cheap`, `fast`, `local`); AGENTS.md told you to apply
`medium`. The README called grob a '6 MB single binary' -- 6 MB is the musl
container image, the binary is 17 MB.

Verified: 1727 tests pass, clippy clean, doctests pass, fmt clean.
@Destynova2
Destynova2 force-pushed the refactor/drop-dead-trait-mocks branch from 59c7739 to 84ffbc4 Compare August 6, 2026 07:14
@Destynova2
Destynova2 merged commit dd93017 into main Aug 6, 2026
42 checks passed
@Destynova2
Destynova2 deleted the refactor/drop-dead-trait-mocks branch August 6, 2026 07:29
Destynova2 added a commit that referenced this pull request Aug 6, 2026
## 🤖 New release

* `grob`: 0.36.95 -> 0.36.96

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

##
[0.36.96](v0.36.95...v0.36.96)
- 2026-08-06

### Other

- delete the dead trait mocks and four redundant docs
([#543](#543))
- *(compliance)* correct AI Act article numbers and scope NIS2 honestly
([#542](#542))
- *(agents)* guard the streaming attribution path
([#541](#541))
- *(agents)* record the request path and the mutation findings
([#540](#540))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
Destynova2 added a commit that referenced this pull request Aug 6, 2026
…pe docs (#544)

Second pass of the audit. #543 removed the dead mocks; this removes the
abstraction they existed to serve, fixes every broken doc link, and
collapses the duplicated docs.

## Code: the five single-impl traits

`DlpPipeline`, `RequestRouter`, `AuditWriter`, `EventTap`,
`SpendTracking` each had **exactly one implementation**, and every
method in it delegated straight to the concrete type.

Four of the five were never used as `dyn` or as a generic bound
anywhere. The concrete type was already the field type in `AppState`:

| Trait | `AppState` field | Actual type |
|---|---|---|
| `RequestRouter` | `router` | `Router` |
| `AuditWriter` | `audit_log` | `Option<Arc<AuditLog>>` |
| `EventTap` | `tap_sender` | `Option<Arc<TapSender>>` |
| `DlpPipeline` | (n/a) | `DlpEngine` |

`SpendTracking` was the one real `Box<dyn>`, at `server/mod.rs:152`, but
also had a single implementor. It becomes `Mutex<SpendTracker>`. Its
default method bodies existed only so test mocks could no-op, and those
mocks went in #543.

**`Tracer` and `ProviderAvailability` stay.** Each has two real
implementations and is genuinely polymorphic at `server/mod.rs:406-411`.

`traits.rs`: 458 to 120 lines.

## Docs: 49 broken intra-doc links to zero

Every one was a dead reference in published API documentation. Failure
modes: links from a module-level `//!` block to an item in that same
module (rustdoc needs an absolute path there), enum variants written as
bare names, links to private items from public docs, and two bare URLs
in clap help text. Two were simply wrong, pointing at functions on types
that do not exist.

Adds `deny(broken_intra_doc_links)` and `deny(private_intra_doc_links)`.
A warning nobody reads is not a signal; a dead link now fails the build
the way `missing_docs` already does.

## Docs: two entry points became one

- `docs/README.md` and `docs/index.md` were both indexes of the same
directory. Nothing linked to README, and the two had drifted. Merged the
eight links only README carried, then deleted it.
- `tutorials/quickstart.md` was a strict subset of `getting-started.md`
and had gone stale, claiming the `perf` preset configures "Anthropic +
OpenAI + Gemini" when it is Anthropic OAuth with no fallback. The
three-command path is now an "In a hurry" section of the one remaining
tutorial.
- The ADR table in `index.md` was hand-maintained and wrong in five
places (0018 and 0019 marked proposed though accepted, 0004 and 0028 not
shown as superseded, 0027/0028/0029 missing). Regenerated from each
ADR's `status` field.
- Linked four docs no index reached: protocol fidelity matrix, OTLP
exemplars, `design/`, and the hedge-billing protocol ADR-0020 depends
on.

## ADR-0018

Carried 378 lines of sprint material after the decision: target schemas
for a schema that does not exist, an RE-0..RE-8 flowchart, effort
estimates in LoC, pseudocode, migration examples. Nothing references any
of it. Kept context, drivers, options, decision, consequences,
references, glossary, open questions. 805 to 427 lines.

## Usage: one command instead of two

`grob completions <shell>` printed to stdout; `grob setup-completions`
detected the shell and installed. A new user had to read both help texts
to find out which they wanted. The shell argument is now optional.
`setup-completions` stays as a hidden alias, so nothing breaks. 25
visible root commands become 24.

## Deliberately not done

- **Unifying the two circuit breakers.** Not duplicates:
`security::CircuitBreakerRegistry` is per provider and backs
`ProviderAvailability`; `routing::circuit_breaker` is per endpoint with
lock-free atomics on the hot path. Different granularities, both live.
- **Embedding `ProviderBase` in `GeminiProvider`.** Worth ~40 LOC, but
Gemini's `api_key` is `Option<SecretString>` where `ProviderBase`'s is
`SecretString`. Making a shared field optional to suit one provider
costs more than the duplication.

## Verification

1727 tests pass; clippy clean with `--all-features --all-targets` and
`--no-default-features`; doctests pass; **`cargo doc` emits zero
warnings** (was 49); fmt and markdownlint clean; both completion paths
exercised by hand.
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