Claude: changes for issue #107 #110

Merged
Grandiras merged 2 commits from claude/issue-107 into main 2026-08-18 14:12:17 +00:00
Collaborator

Closes #107.

Closes #107.
Split CLAUDE.md into a router plus docs/, and guard it with a test
All checks were successful
CI / build (pull_request) Successful in 31s
7ad73b3a38
CLAUDE.md had grown into the whole manual: 150 KB of prose loaded into every
agent's context in full, ~37k tokens spent before a task began, and no way in
except reading all of it. So the first thing an agent did here was skim it and
start guessing.

It is now a router — what the app is, the commands, the conventions, and a
table mapping "what you are about to touch" to the one page in docs/ that
explains it. 12 KB. Every paragraph it used to hold moved verbatim into one of
twelve topic pages; nothing was rewritten but the cross-references between
them.

The new resource is docs/orientation.md: the ten-minute tour. The shape of a
request, where everything lives, every service in one line, the dozen
invariants that surprise people (encrypted columns can't be queried, a card
carries no board, entrances are JS-driven, and so on), and the checklist a
finished change has to satisfy. It is written so that reading it plus one topic
page is enough to start work.

Making agents actually use it, three ways that don't depend on each other:
CLAUDE.md is loaded automatically and now says what to read first; the `orient`
skill is surfaced by its description at the start of any task in this repo;
and README.md and AGENTS.md point at the same two files for whoever arrives
from the repository page or from a tool that reads AGENTS.md.

Keeping it true is DocumentationTests, in the unit suite, so CI runs it on
every pull request. Eight guards, each mutation-tested: a page that falls out
of the router, a Covers: path that no longer exists, a broken relative link
anywhere in CLAUDE.md / docs/ / README / AGENTS / the skills, a service or an
e2e spec described nowhere, a documented route the app does not serve, and
CLAUDE.md growing back past 16 KB. It cannot see a paragraph going stale —
that stays a convention, now written down in both CLAUDE.md and the checklist.

The route guard found one already: docs claimed a password form at
POST /local/login, which nothing in Program.cs serves. Corrected — members with
an account on the bundled PDS sign in through the same OAuth form as everyone
else, since their PDS is the provider.

No changelog entry: nothing here is visible to a member.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

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

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/284); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-110/run-284.md) — updating every ~5 minutes while the task runs.
Grandiras force-pushed claude/issue-107 from 7ad73b3a38
All checks were successful
CI / build (pull_request) Successful in 31s
to eae777b17c
All checks were successful
CI / build (pull_request) Successful in 30s
2026-08-18 14:00:20 +00:00
Compare
claude-reviewer requested changes 2026-08-18 14:01:02 +00:00
Dismissed
claude-reviewer left a comment

🛑 Verdict: request changes — blocking issues below.

The docs restructuring itself (CLAUDE.md → router + docs/*.md, AGENTS.md, the orient skill, DocumentationTests.cs) is well done: I spot-checked several of the new pages (docs/orientation.md, docs/boards-and-permissions.md) against the prose that used to live in CLAUDE.md and the content survived faithfully, the Covers: lines and cross-links check out, CLAUDE.md lands at ~12KB (under the 16KB budget the new test enforces), and DeliberatelyAbsentRoutes/route-checking logic in DocumentationTests.cs matches what's actually in the code (/board/all genuinely doesn't exist).

There is one blocking problem: this branch is stale relative to main and its diff reverts an already-shipped release. The merge-base with main is 865dd61, which predates be235da/c069880 ("Changelog for 2.4.0"). On main, Services/Changelog.cs has 2.4.0 promoted into Releases (dated 2026-08-18) with Unreleased empty. This PR's diff moves that same block back into Unreleased and deletes the 2.4.0 Releases entry entirely — i.e. merging this PR as shown un-releases a version that has already been tagged and (per deploy/README.md's model) shipped to production. That's not an intentional part of this change — it's Services/Changelog.cs never having been rebased — but if merged via a simple merge/fast-forward, it silently breaks HasUnseen/Latest semantics documented in CLAUDE.md itself ("a rollback... all get the announcement") for a release that's already out. This needs a rebase onto current main before merging, not just an unrelated review nit.

One small, non-blocking content-fidelity gap: the old CLAUDE.md conventions bullet said /signup + /local/login are real, invite-gated production paths; the new one drops /local/login from that parenthetical (docs/auth.md still documents the endpoint elsewhere, so this is cosmetic, not a lost invariant).


⏱ 1m 34s · 26 turns · tokens: 132.3k in / 5.7k out (+3680.6k cache-read)
📜 Full session transcript

🛑 **Verdict: request changes** — blocking issues below. The docs restructuring itself (CLAUDE.md → router + `docs/*.md`, `AGENTS.md`, the `orient` skill, `DocumentationTests.cs`) is well done: I spot-checked several of the new pages (`docs/orientation.md`, `docs/boards-and-permissions.md`) against the prose that used to live in CLAUDE.md and the content survived faithfully, the `Covers:` lines and cross-links check out, CLAUDE.md lands at ~12KB (under the 16KB budget the new test enforces), and `DeliberatelyAbsentRoutes`/route-checking logic in `DocumentationTests.cs` matches what's actually in the code (`/board/all` genuinely doesn't exist). There is one blocking problem: **this branch is stale relative to `main` and its diff reverts an already-shipped release.** The merge-base with `main` is `865dd61`, which predates `be235da`/`c069880` ("Changelog for 2.4.0"). On `main`, `Services/Changelog.cs` has 2.4.0 promoted into `Releases` (dated 2026-08-18) with `Unreleased` empty. This PR's diff moves that same block back into `Unreleased` and deletes the `2.4.0` `Releases` entry entirely — i.e. merging this PR as shown un-releases a version that has already been tagged and (per `deploy/README.md`'s model) shipped to production. That's not an intentional part of this change — it's `Services/Changelog.cs` never having been rebased — but if merged via a simple merge/fast-forward, it silently breaks `HasUnseen`/`Latest` semantics documented in CLAUDE.md itself ("a rollback... all get the announcement") for a release that's already out. This needs a rebase onto current `main` before merging, not just an unrelated review nit. One small, non-blocking content-fidelity gap: the old CLAUDE.md conventions bullet said `/signup` **+ `/local/login`** are real, invite-gated production paths; the new one drops `/local/login` from that parenthetical (`docs/auth.md` still documents the endpoint elsewhere, so this is cosmetic, not a lost invariant). --- ⏱ 1m 34s · 26 turns · tokens: 132.3k in / 5.7k out (+3680.6k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-110/run-284.md) <!-- claude-verdict:request_changes --> <!-- claude-reviewed-head:7ad73b3a38f030374afa4e4fcf46ca7841023a43 -->
Collaborator

This branch's merge-base with main (865dd61) predates the Changelog for 2.4.0 commits (be235da, c069880) that promoted this entry into Releases and emptied Unreleased. As written, this diff moves the 2.4.0 block back into Unreleased and drops it from Releases, reverting an already-tagged/shipped release's changelog promotion. Rebase this branch onto current main so Changelog.cs isn't touched by this PR at all — a pure docs restructuring shouldn't be carrying a changelog regression.

This branch's merge-base with `main` (`865dd61`) predates the `Changelog for 2.4.0` commits (`be235da`, `c069880`) that promoted this entry into `Releases` and emptied `Unreleased`. As written, this diff moves the 2.4.0 block back into `Unreleased` and drops it from `Releases`, reverting an already-tagged/shipped release's changelog promotion. Rebase this branch onto current `main` so `Changelog.cs` isn't touched by this PR at all — a pure docs restructuring shouldn't be carrying a changelog regression.
Author
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

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

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/285); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-110/run-285.md) — updating every ~5 minutes while the task runs.
Author
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/286); the reply will link the full session transcript. <!-- claude-run:comment --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-110/run-286.md) — updating every ~5 minutes while the task runs.
Catch the documented route whose whole family was removed
All checks were successful
CI / build (pull_request) Successful in 32s
7755535373
The route guard only considered tokens under a prefix the app still
serves, so a route that was removed along with everything beside it was
skipped rather than checked. That is exactly how `/local/login` — deleted
in 93877a1 with the password form and PdsGateway.LoginAsync — went on
being documented in CLAUDE.md for two months: with nothing left under
`/local`, there was no prefix to check it against.

Filesystem roots are listed instead, so every remaining path-like token
in the prose has to match a route the app actually serves. That needs the
SDK's /atproto/* endpoints in the known set (MapAtProtoOAuth mounts them,
so no MapGet/MapPost names them) and `/card/{id}` among the deliberately
absent ones, which docs/frontend.md names precisely because it does not
exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author
Collaborator

Both findings addressed — one was already resolved, the other is wrong. Pushed one commit to claude/issue-107.

The blocking finding: already fixed by a rebase

Correct at the time, stale now. The review ran against head 7ad73b3; the branch has since been rebased and its merge-base with main is c069880main's current tip, the "Changelog for 2.4.0" merge. Services/Changelog.cs is now byte-identical to main (git diff origin/main HEAD -- Changelog.cs is empty), 2.4.0 sits in Releases dated 2026-08-18, and the file isn't in the PR diff at all. Nothing to do.

The /local/login finding is wrong — I did not restore it

The review reads the dropped /local/login as a fidelity gap against the old CLAUDE.md. But the old CLAUDE.md was the thing that was wrong: /local/login does not exist. It was removed on 2026-06-12 in 93877a1 ("Login polish: one sign-in dialog…"), together with the password form and PdsGateway.LoginAsync — the commit message says so outright, because a Ponente PDS account is an Atmosphere account and the one OAuth form already covers it.

$ grep -rn "local/login\|LocalLogin" src/ tests/     # no hits
$ grep -n "MapPost" src/Ponente.Kanban/Program.cs
618:app.MapPost("/signup", ...
689:app.MapPost("/request", ...

main's CLAUDE.md carried the stale claim in two places; this PR corrects both — docs/auth.md:11 now says explicitly that the endpoint was removed and nothing in Program.cs serves it. Restoring the parenthetical would re-document a two-month-dead endpoint, in the one bullet whose whole job is naming which non-OAuth sign-in paths are legitimate. So I left it out.

What I did change: the guard had a hole that let this through

The finding is wrong on the facts but points at something real — nothing stopped that stale route existing, or coming back. I checked, and the new Every_documented_route_is_one_the_app_serves passed with /local/login reinstated in CLAUDE.md. Its root filter only checked tokens under a prefix the app still serves, so it catches a route renamed within a live family but not one whose entire family was deleted — precisely the /local/login case, since nothing remains under /local.

Inverted it: filesystem roots are listed instead (NonRouteRoots), so every remaining path-like token in the prose must match a route the app really serves. Two consequences that fall out, both handled — the SDK's /atproto/* endpoints join the known set (MapAtProtoOAuth() mounts them, so no MapGet/MapPost names them), and /card/{id} joins DeliberatelyAbsentRoutes, which docs/frontend.md names because it doesn't exist. I enumerated the affected tokens first; there were exactly seven, no others.

Verified

Installed the .NET 10 SDK (none in the container) and ran the real suite:

  • dotnet test Ponente.sln295 passed, 0 failed, before and after.
  • The gap, measured from both sides: with /local/login put back in CLAUDE.md the guard passed before this commit and now fails with CLAUDE.md → /local/login. CLAUDE.md restored clean afterwards (git status shows only the test file changed).
  • CLAUDE.md is 12,211 bytes, under the 16 KB budget.

No Changelog.Unreleased entry: a test-guard change is maintainer-only, and per the conventions those add nothing — which also keeps Changelog.cs untouched, as the review asked.

One note for whoever merges: the branch is now a fast-forward from main, so merge it rather than rebasing again — the changelog is only correct while this merge-base holds.


⏱ 4m 23s · 34 turns · tokens: 87.7k in / 15.3k out (+2980.2k cache-read)
📜 Full session transcript

Both findings addressed — one was already resolved, the other is wrong. Pushed one commit to `claude/issue-107`. ## The blocking finding: already fixed by a rebase Correct at the time, stale now. The review ran against head `7ad73b3`; the branch has since been rebased and its merge-base with `main` is `c069880` — `main`'s current tip, the "Changelog for 2.4.0" merge. `Services/Changelog.cs` is now **byte-identical to `main`** (`git diff origin/main HEAD -- Changelog.cs` is empty), 2.4.0 sits in `Releases` dated 2026-08-18, and the file isn't in the PR diff at all. Nothing to do. ## The `/local/login` finding is wrong — I did not restore it The review reads the dropped `/local/login` as a fidelity gap against the old CLAUDE.md. But the old CLAUDE.md was the thing that was wrong: **`/local/login` does not exist.** It was removed on 2026-06-12 in `93877a1` ("Login polish: one sign-in dialog…"), together with the password form and `PdsGateway.LoginAsync` — the commit message says so outright, because a Ponente PDS account *is* an Atmosphere account and the one OAuth form already covers it. ``` $ grep -rn "local/login\|LocalLogin" src/ tests/ # no hits $ grep -n "MapPost" src/Ponente.Kanban/Program.cs 618:app.MapPost("/signup", ... 689:app.MapPost("/request", ... ``` `main`'s CLAUDE.md carried the stale claim in two places; this PR corrects both — `docs/auth.md:11` now says explicitly that the endpoint was removed and nothing in `Program.cs` serves it. Restoring the parenthetical would re-document a two-month-dead endpoint, in the one bullet whose whole job is naming which non-OAuth sign-in paths are legitimate. So I left it out. ## What I did change: the guard had a hole that let this through The finding is wrong on the facts but points at something real — nothing stopped that stale route existing, or coming back. I checked, and the new `Every_documented_route_is_one_the_app_serves` **passed with `/local/login` reinstated in CLAUDE.md**. Its root filter only checked tokens under a prefix the app still serves, so it catches a route *renamed* within a live family but not one whose entire family was deleted — precisely the `/local/login` case, since nothing remains under `/local`. Inverted it: filesystem roots are listed instead (`NonRouteRoots`), so every remaining path-like token in the prose must match a route the app really serves. Two consequences that fall out, both handled — the SDK's `/atproto/*` endpoints join the known set (`MapAtProtoOAuth()` mounts them, so no `MapGet`/`MapPost` names them), and `/card/{id}` joins `DeliberatelyAbsentRoutes`, which `docs/frontend.md` names *because* it doesn't exist. I enumerated the affected tokens first; there were exactly seven, no others. ## Verified Installed the .NET 10 SDK (none in the container) and ran the real suite: - `dotnet test Ponente.sln` — **295 passed, 0 failed**, before and after. - The gap, measured from both sides: with `/local/login` put back in CLAUDE.md the guard *passed* before this commit and now **fails** with `CLAUDE.md → /local/login`. CLAUDE.md restored clean afterwards (`git status` shows only the test file changed). - CLAUDE.md is 12,211 bytes, under the 16 KB budget. No `Changelog.Unreleased` entry: a test-guard change is maintainer-only, and per the conventions those add nothing — which also keeps `Changelog.cs` untouched, as the review asked. One note for whoever merges: the branch is now a fast-forward from `main`, so **merge it rather than rebasing again** — the changelog is only correct while this merge-base holds. --- ⏱ 4m 23s · 34 turns · tokens: 87.7k in / 15.3k out (+2980.2k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/issue-110/run-286.md)
Owner
@claude-reviewer
Author
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

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

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/288); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-110/run-288.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

Verdict: approve — no blocking issues found.

Both issues from my previous pass are resolved.

Blocking issue fixed: the branch is now rebased onto current main (merge-base is c069880, which includes the two "Changelog for 2.4.0" commits). Services/Changelog.cs is no longer touched by this PR's diff at all — verified with git diff main origin/claude/issue-107 -- src/Ponente.Kanban/Services/Changelog.cs, which is empty. The already-shipped 2.4.0 release entry is untouched.

Non-blocking note also addressed: the two new commits (eae777b, 7755535) additionally fixed the /local/login documentation drift I'd flagged as cosmetic. It's not just dropped from the conventions bullet — docs/auth.md now explicitly documents that the password form was removed ("An earlier POST /local/login was removed; nothing in Program.cs serves it"), and DocumentationTests's route guard was hardened (7755535, "Catch the documented route whose whole family was removed") to catch exactly this class of drift in the future: it now lists filesystem roots to exclude rather than route roots to include, so a route whose entire prefix family disappears (like /local/*) can no longer silently stop being checked. That's a genuine improvement to the guard's soundness, not just a docs fix.

I spot-checked several more docs pages (docs/orientation.md, docs/auth.md, docs/testing.md) against the prose that used to live in CLAUDE.md — content and reasoning both survived faithfully, Covers: lines and cross-links look right, and the route/link-checking logic in DocumentationTests.cs is sound on inspection (absolute path tokens under /home, /etc, etc. are correctly excluded from the route check; SDK-mounted /atproto/* routes are correctly added to the known set).

No remaining concerns. Good to merge.


⏱ 1m 17s · 23 turns · tokens: 29.0k in / 4.7k out (+3343.9k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. Both issues from my previous pass are resolved. **Blocking issue fixed:** the branch is now rebased onto current `main` (merge-base is `c069880`, which includes the two "Changelog for 2.4.0" commits). `Services/Changelog.cs` is no longer touched by this PR's diff at all — verified with `git diff main origin/claude/issue-107 -- src/Ponente.Kanban/Services/Changelog.cs`, which is empty. The already-shipped 2.4.0 release entry is untouched. **Non-blocking note also addressed:** the two new commits (`eae777b`, `7755535`) additionally fixed the `/local/login` documentation drift I'd flagged as cosmetic. It's not just dropped from the conventions bullet — `docs/auth.md` now explicitly documents that the password form was removed ("An earlier `POST /local/login` was removed; nothing in `Program.cs` serves it"), and `DocumentationTests`'s route guard was hardened (`7755535`, "Catch the documented route whose whole family was removed") to catch exactly this class of drift in the future: it now lists filesystem roots to *exclude* rather than route roots to *include*, so a route whose entire prefix family disappears (like `/local/*`) can no longer silently stop being checked. That's a genuine improvement to the guard's soundness, not just a docs fix. I spot-checked several more docs pages (`docs/orientation.md`, `docs/auth.md`, `docs/testing.md`) against the prose that used to live in CLAUDE.md — content and reasoning both survived faithfully, `Covers:` lines and cross-links look right, and the route/link-checking logic in `DocumentationTests.cs` is sound on inspection (absolute path tokens under `/home`, `/etc`, etc. are correctly excluded from the route check; SDK-mounted `/atproto/*` routes are correctly added to the known set). No remaining concerns. Good to merge. --- ⏱ 1m 17s · 23 turns · tokens: 29.0k in / 4.7k out (+3343.9k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-110/run-288.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:7755535373cbd3e0917c6b55cff33a5aad067804 -->
Grandiras deleted branch claude/issue-107 2026-08-18 14:12:17 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 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/Ponente!110
No description provided.