steid

@jamesgill /

docs: the section 1 wave, checked as one thing rather than five

Records the integration pass: the merged branches run against Steid's own history
and every cross-feature link followed in a browser, dark and light. Nothing was
broken at a seam — which is worth writing down, because five agents that could not
see each other agreed on URL shapes only because the shapes were settled in `ui.md`
and in the handovers before any code existed.

Two gaps found, both missing entry points rather than breaks: the sidebar's
Download links can only ever be the default branch, and blame is unhighlighted
while the blob is. Both are carried in `current.md` rather than fixed here.

Section 1 is now done apart from the per-file last-commit column, which is waiting
on 0006's kept-alive `cat-file --batch` by decision. The ladder in `ROADMAP.md` is
unchanged: this was forge-feature work on top of Milestone 5, and 5b is still the
active milestone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J18ViwAfdswUCMb2DXJZFG
JamesPatrickGill authored 14 hours agoparente63c831Browse filesfb216383cbff7c0cc8e7241cd9273aa7d5e04a4a

2 files changed+82 −18

plans/current.md+54 −16View file
@@ -194,9 +194,41 @@ instance, and Steid's own source is pushed to it and browsable there.
194194 thing to revisit.
195195 - **Blame is the most expensive read in `GitQuery`** and the likeliest to meet the 20 s
196196 timeout. Nothing but this page calls it.
197- **Cross-branch links were verified only after the merge**: blame's sha links to the
198 commit page, search's line links to `blob#L<n>`, and the branches page's Compare link
199 each landed on a different branch. See the integration check below.
197+- ~~Cross-branch links were verified only after the merge~~ — **walked, 2026-09-05**,
198+ see the integration pass below.
199+
200+#### The integration pass — 2026-09-05
201+
202+The five branches merged and run as one app, on a real instance holding Steid's own
203+history: 9 branches, 2 annotated tags, one public repository and one private. Every
204+link that crosses a feature boundary was followed in a browser, and **nothing was
205+broken at a seam.** Landing sha → commit page; log sha → commit; commit's "Browse
206+files" → tree at that sha and its parent sha → the parent's page; the counts and the
207+sidebar → branches and tags; a branch row → tree, log and a compare with a real diff
208+(a merged branch correctly says there is nothing to compare); a search hit's line
209+number → `blob#L<n>` with the anchor present and landing; `Code · Blame · Raw` in both
210+directions; blame's sha → the commit page and its line number → the blob anchor;
211+`zip` and `tar.gz` for `main` and for a tag, both extracting under `steid-<rev>/`.
212+**A private repository 404s on all eleven routes anonymously** — landing, log,
213+branches, tags, commit, search, tree, blame, raw, archive, compare. Highlighting still
214+renders after the blame toggle and the anchor edits landed on the same table: Rust and
215+TOML coloured, a plain file not. Screenshots of the whole flow in dark and light are
216+in `target/shots/`.
217+
218+Two things the pass found, neither a break:
219+
220+- **The sidebar's Download links can only ever offer the default branch.**
221+ `clone_block` takes a revision and its doc says the links are "for the revision being
222+ viewed", but the sidebar renders only on the landing page, which has no `{rev}` — and
223+ the tree and blob pages, which do, are single-column by design. So a tag's tarball is
224+ reachable only by typing `/archive/v0.2.0.zip`. Both formats work at both revisions;
225+ it is the entry point that is missing, and putting it on the tree page means deciding
226+ whether that page gets a sidebar, which [ui.md](ui.md#the-repository-page) settled the
227+ other way.
228+- **Blame renders its lines unhighlighted while the blob highlights them.**
229+ `highlight.rs` and `blame.rs` shipped on separate branches. `ui.md` says the two views
230+ are "two readings of one thing" with the same type and leading, and colour is now the
231+ one place they disagree.
200232
201233 ### Carried over — small, unblocked
202234
@@ -292,16 +324,19 @@ run several agents at once and the grouping is what decides what can run togethe
292324 browsing feature appends a method), `git_query.rs`, the repo sub-nav, and `plans/`
293325 itself. New tables touch `sqlite.rs` + `in_memory.rs` and should merge one at a time.
294326
295**Done from section 1:** the **two-column repository landing page** — a shared header
296and tab strip on every repository page, an About sidebar, a latest-commit bar, and
297branch/tag counts. See [ui.md](ui.md#the-repository-page) for the layout and the
298entry-point map, and [progress.md](progress.md) for what it cost.
299
3001. **Read-only browsing** (no DB; parallel-safe with each other): commit page with
301 diff · branches and tags pages · compare view (merge-base) · archive download ·
302 syntax highlighting · blame · per-file last-commit column (blocked on the
303 [0006](decisions/0006-git-binary-behind-narrow-ports.md) amendment: it is the trigger
304 for a kept-alive `cat-file --batch`) · code search via `git grep`.
327+**Section 1 is done**, apart from the per-file last-commit column — which is not a
328+gap but a deliberate wait for the kept-alive `cat-file --batch`
329+([0006](decisions/0006-git-binary-behind-narrow-ports.md)). Shipped: the two-column
330+repository landing page, syntax highlighting, branches and tags pages, archive
331+download, code search, the commit page, compare, and blame. All eight were merged and
332+then walked together as one app; see the integration pass above. See
333+[ui.md](ui.md#the-repository-page) for the layout and the entry-point map, and
334+[progress.md](progress.md) for what each cost.
335+
336+1. ~~**Read-only browsing**~~ — **done**, except the **per-file last-commit column**,
337+ which stays blocked on the
338+ [0006](decisions/0006-git-binary-behind-narrow-ports.md) amendment: wanting it is the
339+ trigger for a kept-alive `cat-file --batch`, not for reopening `gix`.
305340 2. **Repo model** (a column or use case each; merge serially): rename · default branch
306341 setting · archived flag · topics and pinned repos on the profile · orphan-directory
307342 reconciliation sweep on boot.
@@ -317,9 +352,12 @@ entry-point map, and [progress.md](progress.md) for what it cost.
317352 HTTP-level test harness plus security-header tests and `cargo audit` · `/api`
318353 coverage for existing use cases · styled auth pages, light mode, fonts.
319354
320Process decisions still open for parallel work: whether agents get worktrees and
321short-lived branches (bending the commit-to-main rule), and that agents do **not** edit
322`plans/` — it is updated once per wave at merge time.
355+Process decisions, now answered by the wave rather than open: agents **do** get
356+worktrees and short-lived branches, which is a deliberate bend in the commit-to-main
357+rule and worth keeping for a wave; and agents do **not** edit `plans/` — each writes a
358+handover the merging session folds in, because five agents appending to `current.md`
359+conflict every time. The integration pass afterwards is not optional: it is the only
360+place a cross-feature link is ever exercised.
323361
324362 ## Open questions
325363
plans/progress.md+28 −2View file
@@ -2,9 +2,9 @@
22
33 ## This attempt (#3, Topcoat)
44
5467 tests. Active milestone in [current.md](current.md).
5+598 tests. Active milestone in [current.md](current.md).
66
7### Section 1 wave — read-only browsing · in progress
7+### Section 1 wave — read-only browsing · done
88
99 **Every read-side `git` process is now bounded at 20 s** (`GIT_TIMEOUT` in
1010 `git_query.rs`), and the child is `kill_on_drop` so a cancelled request takes git with
@@ -136,6 +136,32 @@ file header of both views.
136136 dev` sometimes keeps printing "no changes; application up to date" while serving the
137137 previous binary; `pkill -f "topcoat dev"`, wait for the port, restart.
138138
139+**The integration pass (2026-09-05).** The five branches merged, run as one app against
140+Steid's own history — 9 branches, 2 annotated tags, a public repository and a private
141+one — and every link crossing a feature boundary followed in a browser, in dark and in
142+light. **Nothing was broken at a seam**, which is the finding: five agents that could
143+not see each other agreed on URL shapes because the shapes were written down in
144+`ui.md` and in each other's handovers before the code was.
145+
146+- **A private repository 404s on all eleven read routes anonymously** — landing, log,
147+ branches, tags, commit, search, tree, blame, raw, archive, compare. Every use case
148+ takes an `Actor` and answers `Ok(None)`, and each page turns that into `not_found()`;
149+ the uniformity is the architecture rule paying off rather than eleven separate
150+ decisions.
151+- **Two gaps found, both entry points rather than breaks.** The About sidebar's Download
152+ links can only ever offer the default branch, because the sidebar renders on the one
153+ repository page that has no `{rev}`. And blame renders its lines unhighlighted while
154+ the blob highlights them, `highlight.rs` and `blame.rs` having shipped on separate
155+ branches. Both are in [current.md](current.md).
156+- **A wave needs a divergent branch to test compare with.** Every feature branch was an
157+ ancestor of `main` after merging, so every branch row's Compare link correctly said
158+ there was nothing to compare and exercised none of the diff. `git commit-tree` makes
159+ one without a working tree.
160+- **Follow-ups the handovers named, done here:** blame's revision switcher (`Switch`
161+ gained a `Blame` arm), `web::context::timed_out` shared by three pages, `.jsx` aliased
162+ onto JavaScript, `token.rs`'s phantom `bg-muted`, and the two exit-status comments
163+ that each claimed to be the only one.
164+
139165 ### Milestone 0 — Skeleton · done
140166
141167 Topcoat 0.5 app serving pages, `AppConfig` from `STEID_*` env, SQLite pool in app