Core package emits 1114 CS1591 warnings — public API ships with empty IntelliSense tooltips #72

Closed
opened 2026-07-25 22:54:03 +00:00 by Grandiras · 2 comments
Owner

Summary

src/ATProtoNet ships with <GenerateDocumentationFile>true</GenerateDocumentationFile> but emits 1114 unique CS1591 warnings ("Missing XML comment for publicly visible type or member"). Every one of them is a public API surface that arrives in a consumer's IntelliSense with an empty tooltip.

This is not a build failure — <TreatWarningsAsErrors> is deliberately false on the core project — but it is the single largest source of noise in the build (CS1591 is 1114 of the ~1120 warnings the solution produces), which means a genuinely new warning on a touched file is easy to miss.

Observed on main at v0.5.0 (fab0e9f), via:

dotnet build -p:EnableSourceControlManagerQueries=false -c Release --no-incremental

Scope

All 1114 are in ATProtoNet.csproj. The other three doc-generating projects — ATProtoNet.Server, ATProtoNet.Blazor, ATProtoNet.Aspire.Hosting — are clean, so this is contained to the core package.

Roughly 1080 are undocumented members (mostly DTO properties) and ~30 are undocumented types.

By area

Area Warnings
Lexicon/App/Bsky 406
Lexicon/Com/AtProto 297
Lexicon/Tools/Ozone 202
Lexicon/Chat/Bsky 72
Identity 64
Auth/OAuth 58
Lexicon/Site/Standard 9
Auth, Http, Serialization 6

1044 of 1114 (94%) are in *Models.cs files — the per-Lexicon DTO files. The remaining 70 are spread thinly across Identity/ (the Did, Handle, AtUri, Nsid, Tid, Cid, RecordKey, AtIdentifier value types, 7-9 each), Auth/Session.cs, Http/AtProtoHttpException.cs, and Serialization/LexiconPlugin.cs.

Worst files

File Warnings
Lexicon/Tools/Ozone/Moderation/ModerationModels.cs 124
Lexicon/App/Bsky/Feed/FeedModels.cs 117
Lexicon/App/Bsky/Graph/GraphModels.cs 115
Lexicon/Com/AtProto/Server/ServerModels.cs 105
Lexicon/Chat/Bsky/Convo/ConvoModels.cs 67
Lexicon/Com/AtProto/Repo/RepoModels.cs 65
Auth/OAuth/OAuthModels.cs 58
Lexicon/App/Bsky/Actor/ActorModels.cs 56

Notes on the shape of the work

The models files are not uniformly undocumented — they are partially documented, which is why this reads worse than it is. PostRecord in FeedModels.cs documents Text, Facets, Reply, Embed, and Langs but not the $type discriminator property, so a mostly-good file still contributes warnings. Any fix should preserve the existing prose rather than bulk-regenerate over it.

Most of these members map one-to-one onto fields in the upstream Lexicon JSON, which carries a description for many of them — that is the natural source of truth for the summary text rather than inventing prose. tools/ATProtoNet.LexiconGenerator already emits <summary> from Lexicon descriptions when generating C#, so there may be leverage in reusing that path for the hand-written models.

The $type discriminator properties are a large, mechanical subset: they are all the same concept and could take a single boilerplate summary.

Suggested approach

Worth deciding before anyone starts, since "document 1114 members" is not a single sitting:

  1. Per-area, incrementally — one PR per Lexicon domain (App/Bsky, Com/AtProto, Tools/Ozone, …), which keeps diffs reviewable and lets the count drop visibly.
  2. Non-Lexicon first — the 70 warnings outside *Models.cs (Identity/ especially, since Did/Handle/AtUri are core public types users touch constantly) are the highest value-per-edit and could be one small PR.
  3. Once an area is clean, consider <WarningsNotAsErrors> / a targeted #pragma-free ratchet so it cannot regress — or simply flip TreatWarningsAsErrors on for the project when the count hits zero.

Acceptance

  • dotnet build -c Release emits zero CS1591 from ATProtoNet.csproj
  • No existing XML documentation is lost or degraded in the process
  • Ideally a mechanism that prevents the count from creeping back up

Non-goals

  • The 2 RZ10012 warnings in samples/ServerIntegrationSample (a missing @using for ReconnectModal) and the 2 CS1573 / 2 CS0419 warnings — unrelated, and small enough to fold into whatever touches them next.
## Summary `src/ATProtoNet` ships with `<GenerateDocumentationFile>true</GenerateDocumentationFile>` but emits **1114 unique CS1591 warnings** ("Missing XML comment for publicly visible type or member"). Every one of them is a public API surface that arrives in a consumer's IntelliSense with an empty tooltip. This is not a build failure — `<TreatWarningsAsErrors>` is deliberately `false` on the core project — but it is the single largest source of noise in the build (CS1591 is 1114 of the ~1120 warnings the solution produces), which means a genuinely new warning on a touched file is easy to miss. Observed on `main` at v0.5.0 (`fab0e9f`), via: ```bash dotnet build -p:EnableSourceControlManagerQueries=false -c Release --no-incremental ``` ## Scope All 1114 are in **`ATProtoNet.csproj`**. The other three doc-generating projects — `ATProtoNet.Server`, `ATProtoNet.Blazor`, `ATProtoNet.Aspire.Hosting` — are clean, so this is contained to the core package. Roughly 1080 are undocumented **members** (mostly DTO properties) and ~30 are undocumented **types**. ### By area | Area | Warnings | |---|---| | `Lexicon/App/Bsky` | 406 | | `Lexicon/Com/AtProto` | 297 | | `Lexicon/Tools/Ozone` | 202 | | `Lexicon/Chat/Bsky` | 72 | | `Identity` | 64 | | `Auth/OAuth` | 58 | | `Lexicon/Site/Standard` | 9 | | `Auth`, `Http`, `Serialization` | 6 | **1044 of 1114 (94%) are in `*Models.cs` files** — the per-Lexicon DTO files. The remaining 70 are spread thinly across `Identity/` (the `Did`, `Handle`, `AtUri`, `Nsid`, `Tid`, `Cid`, `RecordKey`, `AtIdentifier` value types, 7-9 each), `Auth/Session.cs`, `Http/AtProtoHttpException.cs`, and `Serialization/LexiconPlugin.cs`. ### Worst files | File | Warnings | |---|---| | `Lexicon/Tools/Ozone/Moderation/ModerationModels.cs` | 124 | | `Lexicon/App/Bsky/Feed/FeedModels.cs` | 117 | | `Lexicon/App/Bsky/Graph/GraphModels.cs` | 115 | | `Lexicon/Com/AtProto/Server/ServerModels.cs` | 105 | | `Lexicon/Chat/Bsky/Convo/ConvoModels.cs` | 67 | | `Lexicon/Com/AtProto/Repo/RepoModels.cs` | 65 | | `Auth/OAuth/OAuthModels.cs` | 58 | | `Lexicon/App/Bsky/Actor/ActorModels.cs` | 56 | ## Notes on the shape of the work The models files are not uniformly undocumented — they are *partially* documented, which is why this reads worse than it is. `PostRecord` in `FeedModels.cs` documents `Text`, `Facets`, `Reply`, `Embed`, and `Langs` but not the `$type` discriminator property, so a mostly-good file still contributes warnings. Any fix should preserve the existing prose rather than bulk-regenerate over it. Most of these members map one-to-one onto fields in the upstream Lexicon JSON, which carries a `description` for many of them — that is the natural source of truth for the summary text rather than inventing prose. `tools/ATProtoNet.LexiconGenerator` already emits `<summary>` from Lexicon descriptions when generating C#, so there may be leverage in reusing that path for the hand-written models. The `$type` discriminator properties are a large, mechanical subset: they are all the same concept and could take a single boilerplate summary. ## Suggested approach Worth deciding before anyone starts, since "document 1114 members" is not a single sitting: 1. **Per-area, incrementally** — one PR per Lexicon domain (`App/Bsky`, `Com/AtProto`, `Tools/Ozone`, …), which keeps diffs reviewable and lets the count drop visibly. 2. **Non-Lexicon first** — the 70 warnings outside `*Models.cs` (`Identity/` especially, since `Did`/`Handle`/`AtUri` are core public types users touch constantly) are the highest value-per-edit and could be one small PR. 3. Once an area is clean, consider `<WarningsNotAsErrors>` / a targeted `#pragma`-free ratchet so it cannot regress — or simply flip `TreatWarningsAsErrors` on for the project when the count hits zero. ## Acceptance - `dotnet build -c Release` emits zero CS1591 from `ATProtoNet.csproj` - No existing XML documentation is lost or degraded in the process - Ideally a mechanism that prevents the count from creeping back up ## Non-goals - The 2 `RZ10012` warnings in `samples/ServerIntegrationSample` (a missing `@using` for `ReconnectModal`) and the 2 `CS1573` / 2 `CS0419` warnings — unrelated, and small enough to fold into whatever touches them next.
Collaborator

🤖 On it — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 On it — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/87); the reply will link the full session transcript. 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/issue-72/run-87.md) — updating every ~5 minutes while the task runs.
Collaborator

Pushed to claude/issue-72open a PR.

What changed

All 1114 CS1591 warnings are goneATProtoNet.csproj builds clean, and so does the rest of the solution.

Documentation (1114 members, 45 files). I generated the doc comments mechanically but wrote the vocabulary by hand — a curated map of ~450 AT Protocol field semantics keyed by property name, with per-owner overrides where a bare name is ambiguous. So the summaries describe the protocol field rather than restating the C# identifier:

  • Cursor"Pagination cursor; pass this back on the next request to continue where this page ended."
  • SwapCommit"Compare-and-swap guard: the commit CID the repository must currently be at for the write to succeed."
  • FollowRecord.Subject"The DID of the account being followed", while ModEventView.Subject"The subject the event applies to"
  • $type discriminators carry the Lexicon ID they return: "The Lexicon type discriminator (app.bsky.feed.post)."
  • Constants render their wire value: "The com.atproto.moderation.defs#reasonSpam report reason."
  • The Did/Handle/AtUri/Nsid/Tid/Cid/RecordKey/AtIdentifier conversion operators and ==/!= got real docs with <param>/<returns>; Equals(object), GetHashCode, ToString, CompareTo got <inheritdoc />, which is the honest answer there.

No existing prose was lost. The diff is insert-only — 1620 insertions, 1 deletion, and that one deletion is the deliberate cref fix below. Partially-documented types like PostRecord kept every line they had; only the undocumented members gained one.

Ratchet. All four doc-generating packages now set <WarningsAsErrors>$(WarningsAsErrors);CS1591</WarningsAsErrors>. TreatWarningsAsErrors stays false, so this is narrowly scoped to undocumented public members.

Folded in the non-goals, since they were one line each and got the solution to zero warnings: the missing <param name="proxyOverride"> on XrpcClient.SendWithDPoPRetryAsync (CS1573), the ambiguous <see cref="PlcClient.SubmitOperationAsync"/> in PlcOperationBuilder (CS0419), and the missing @using ServerIntegrationSample.Components.Layout for ReconnectModal (RZ10012).

Verified

  • dotnet build -c Release --no-incremental (whole solution) — 0 warnings, 0 errors
  • dotnet test tests/ATProtoNet.Tests/1103 passed, 0 failed, 5 skipped (the Aspire manifest tests, gated as usual)
  • dotnet pack succeeds; the emitted ATProtoNet.xml parses as XML with 2670 documented members
  • The ratchet actually fires: I dropped a probe file with an undocumented public class into src/ATProtoNet/, confirmed the build failed with error CS1591 on both the type and its property, then removed it

One judgement call worth flagging

The issue suggested splitting this per-Lexicon-domain across several PRs. I did it in one commit instead, because the value is concentrated in the ratchet — and the ratchet can only go in once the count is zero everywhere. The diff is large but uniform; reviewing one *Models.cs file gives you a fair sample of the other 30. If you'd rather land it in slices, say so and I'll split the branch by domain.


⏱ 13m 16s · 84 turns · tokens: 138.7k in / 54.2k out (+7971.9k cache-read)
📜 Full session transcript
→ Opened PR: #75

Pushed to **`claude/issue-72`** — [open a PR](https://git.grandiras.net/Grandiras/ATProto.NET/compare/main...claude/issue-72). ## What changed All **1114 CS1591 warnings are gone** — `ATProtoNet.csproj` builds clean, and so does the rest of the solution. **Documentation (1114 members, 45 files).** I generated the doc comments mechanically but wrote the vocabulary by hand — a curated map of ~450 AT Protocol field semantics keyed by property name, with per-owner overrides where a bare name is ambiguous. So the summaries describe the protocol field rather than restating the C# identifier: - `Cursor` → *"Pagination cursor; pass this back on the next request to continue where this page ended."* - `SwapCommit` → *"Compare-and-swap guard: the commit CID the repository must currently be at for the write to succeed."* - `FollowRecord.Subject` → *"The DID of the account being followed"*, while `ModEventView.Subject` → *"The subject the event applies to"* - `$type` discriminators carry the Lexicon ID they return: *"The Lexicon type discriminator (`app.bsky.feed.post`)."* - Constants render their wire value: *"The `com.atproto.moderation.defs#reasonSpam` report reason."* - The `Did`/`Handle`/`AtUri`/`Nsid`/`Tid`/`Cid`/`RecordKey`/`AtIdentifier` conversion operators and `==`/`!=` got real docs with `<param>`/`<returns>`; `Equals(object)`, `GetHashCode`, `ToString`, `CompareTo` got `<inheritdoc />`, which is the honest answer there. **No existing prose was lost.** The diff is insert-only — 1620 insertions, 1 deletion, and that one deletion is the deliberate `cref` fix below. Partially-documented types like `PostRecord` kept every line they had; only the undocumented members gained one. **Ratchet.** All four doc-generating packages now set `<WarningsAsErrors>$(WarningsAsErrors);CS1591</WarningsAsErrors>`. `TreatWarningsAsErrors` stays `false`, so this is narrowly scoped to undocumented public members. **Folded in the non-goals**, since they were one line each and got the solution to zero warnings: the missing `<param name="proxyOverride">` on `XrpcClient.SendWithDPoPRetryAsync` (CS1573), the ambiguous `<see cref="PlcClient.SubmitOperationAsync"/>` in `PlcOperationBuilder` (CS0419), and the missing `@using ServerIntegrationSample.Components.Layout` for `ReconnectModal` (RZ10012). ## Verified - `dotnet build -c Release --no-incremental` (whole solution) — **0 warnings, 0 errors** - `dotnet test tests/ATProtoNet.Tests/` — **1103 passed, 0 failed, 5 skipped** (the Aspire manifest tests, gated as usual) - `dotnet pack` succeeds; the emitted `ATProtoNet.xml` parses as XML with 2670 documented members - **The ratchet actually fires**: I dropped a probe file with an undocumented public class into `src/ATProtoNet/`, confirmed the build failed with `error CS1591` on both the type and its property, then removed it ## One judgement call worth flagging The issue suggested splitting this per-Lexicon-domain across several PRs. I did it in one commit instead, because the value is concentrated in the ratchet — and the ratchet can only go in once the count is zero everywhere. The diff is large but uniform; reviewing one `*Models.cs` file gives you a fair sample of the other 30. If you'd rather land it in slices, say so and I'll split the branch by domain. --- ⏱ 13m 16s · 84 turns · tokens: 138.7k in / 54.2k out (+7971.9k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/ATProto.NET/issue-72/run-87.md) → Opened PR: https://git.grandiras.net/Grandiras/ATProto.NET/pulls/75
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/ATProto.NET#72
No description provided.