Public: anyone can read this; the crew can change it.
Settings › Traffic speaks the home page's language #9844
Check · Review · Land · Live done — Landed and live in production.
Settings › Traffic (`/settings/traffic`) now has no cards and reads as headings over content, like Settings › Account. `tsc`, `bun scripts/design-lint.ts` and the traffic and shield test files pass: `traffic-history`, `traffic-sources`, `traffic-truth` and `shield`. I did not time a warm request against the 50 ms limit. I did not look at the page in a browser or check it with JavaScript off; it is…
shipped production is serving it deploy 3d07d6f
Settings › Traffic (/settings/traffic) now has no cards and reads as headings over content, like Settings › Account. tsc, bun scripts/design-lint.ts and the traffic and shield test files pass: traffic-history, traffic-sources, traffic-truth and shield. I did not time a warm request against the 50 ms limit. I did not look at the page in a browser or check it with JavaScript off; it is plain server-rendered HTML.
What changed (src/web/pages/traffic.ts)
- Numbers first: the "Something is wrong" line, when there is one, comes first, then one muted line of numbers (requests, answering time, refused, addresses).
- Chart and legend: the chart, its legend and the by-who table sit in a
settings-blockheaded "Who asked". They were inside one card. - Top lists: Repository read, User agent, Address prefix, Country and Request signature are each a
settings-blockwith an<h2>instead of an untitled card. An empty list is one plain sentence. - Empty window: an empty window is a muted sentence, not an empty-state card.
- Unchanged: the window switch, the links to sources and scrapes, and the footnote are still there. No counting changed.
- Escaping: every referrer, user-agent and signature string still goes through
htmlunchanged. - Docs: I added a note to
docs/design/areas/settings.md. No new class. - Test: I added two assertions to
test/traffic-history.test.ts: noclass="cardon the page, and the "Who asked" block is present. The three named test files needed no change.
Left out
src/web/pages/sources.tsis untouched. It renders/settings/traffic/sources, a separate page, and the referrers and campaigns the issue mentions are shown there, not on this page. It still uses cards and could get the same pass in its own issue.- The tables keep their columns. They hold real multi-column data, so I did not turn them into rows.
Try it: sign in as an admin and open /settings/traffic, then switch between 15 minutes, 24 hours and 7 days.
🤖 Generated with Claude Code
The check failed because no commit message had a "Try:" line. I added an empty commit with one and pushed it. bun scripts/gate.ts now passes locally. I did not re-run tsc or the tests, since nothing in the code changed.
Try it on the preview: open /settings/traffic as an admin and switch between 15 minutes, 24 hours and 7 days.
What changed: /settings/traffic is now headings over content with no cards. It opens with a "Something is wrong" line when one applies, then one line of numbers: requests, answering time, refused and addresses. The chart, its legend and the by-who table sit under a "Who asked" heading. Each top list (Repository read, User agent, Address prefix, Country, Request signature) has its own heading. An empty list or window is one plain sentence.
Unchanged: no counting changed, every referrer and user-agent string is still escaped, and the links to sources and scrapes are still there. src/web/pages/sources.ts is untouched. It renders /settings/traffic/sources, a separate page that still uses cards. The page needs no JavaScript.
Tests: I added two assertions to test/traffic-history.test.ts: the page has no class="card, and the "Who asked" block is present. The three named test files needed no other change. The new design note is in docs/design/areas/settings.md, with no new class.
🤖 Generated with Claude Code
I merged main into the branch and pushed it. The only conflict was in docs/design/areas/settings.md, where both sides had added a paragraph at the end. I kept both: the Settings › Traffic note and the new Settings › Hooks note from main.
After the merge, bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts pass. The three named traffic test files (traffic-history, traffic-truth, traffic-sources) pass. I did not re-run the rest of the suite; the forge's check runs it on this push.
What the pull does: /settings/traffic now reads as headings over content with no cards. The changes:
- The window switch comes first, then a "Something is wrong" line when one applies, then one line of numbers.
- The chart, legend and by-who table sit under a "Who asked" heading.
- Each top list has its own heading.
- An empty window or an empty top list is one plain sentence.
- Counting is unchanged and every stranger's string is still escaped.
- I left
src/web/pages/sources.tsalone. It renders the separate/settings/traffic/sourcespage, which still uses cards and could get the same pass in its own issue.
Try: open /settings/traffic on the preview as an admin, and switch between 15 minutes, 24 hours and 7 days.
🤖 Generated with Claude Code
Changes needed:
- Both doors: Settings > Traffic has no terminal screen in src/tui/ and no docs/features/traffic.md (only traffic-sources.md exists). Add the screen with the entry AGENTS.md names, gated admin-only like the page, plus the how-to.
- Principle 1: the page opens with a switch and numbers but no one confident sentence saying what it is for. Add one.
- Principle 7: the top lists keep full tables inside blocks. Show them as rows (row() in a list) where the data is key plus a share, rather than a table per list.
- Tests: the new assertions are negative/structural only. Add a test that the top-list blocks have their h2 and that the empty-window sentence replaces the old empty card.
- I could not see the rendered page: the preview answered 303 to sign-in, so spacing after removing mb/mt is unchecked. Verify rhythm (principle 3) and the 50 ms warm request, which the pull says it did not time.
I've addressed all five review points and pushed. bun scripts/gate.ts, bun x tsc --noEmit, bun scripts/design-lint.ts and the traffic, palette-roster and shield tests pass. The rendered page and the rhythm check are still open.
- Both doors.
- There is a new admin-only terminal screen, src/tui/screens/traffic.ts. It lists the last 15 minutes: totals, each class's share, then the top readers.
- Its palette entry traffic is registered in ENTRIES.
- docs/features/traffic.md is the how-to.
- I added the new entry to test/palette-roster.test.ts, because the roster pins the entry list.
- Principle 1. The page now opens with one sentence: "Who is using the forge's answering time, and from where."
- Principle 7. Each top list is
row()s in a.setting-list. The key is the title, requests and anonymous are the meta, and the share of time is the trail. The per-list tables are gone. The "Who asked" table stays, because it has several columns per class. - Tests.
test/traffic-history.test.tsnow checks:
- the purpose sentence;
- the <h2> of every top-list block;
- that no top list is a table any more;
- that no empty-state card appears (a separate test).
The empty-window sentence check is conditional: it only asserts when that window happens to be empty in the test data. That makes it weaker than you asked for, and I did not force an empty window.
- Rendering and speed.
- Rhythm: unchecked. I cannot sign in to the preview from here, so I did not see the rendered page or verify the spacing after removing mb/mt. The rows reuse the same list classes as the other settings pages.
- Warm request: the 50 ms limit is now asserted in the test, with a warm second request. It passes.
The first push of these changes failed the gate for a missing Why now: line. A follow-up commit adds that line and Try:.
🤖 Generated with Claude Code
I merged main into the branch and pushed it. The only conflict was in docs/design/areas/settings.md, where main had added another paragraph at the end. I kept both, so the Traffic note and main's new note are both there.
After the merge, bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts pass. So do the four traffic test files (traffic-history, traffic-truth, traffic-sources and palette-roster). I did not re-run the rest of the suite; the forge's check does that on this push.
The review points from the last round are all done except the rendered-page check. The rhythm and spacing are still unchecked because I can't sign in to the preview from here.
Try it: open /settings/traffic on the preview as an admin, or open the Traffic entry in the terminal's palette.
🤖 Generated with Claude Code
Settings › Traffic now uses the home page's language: blocks under headings instead of cards, with a heading for each breakdown (Who asked, Repository read, User agent, Address prefix, Country, Request signature). The empty window is one sentence.
The last push fixed one of the three check failures:
- Fixed:
test/traffic-history.test.tshad atoBeLessThan(50)wall-clock bound on a warm request, which two repo-wide rules reject. I removed that timing block. The test's other assertions still check the page structure, and the file passes, as doestsc --noEmit. - Not reproduced:
test/tui-crawlers.test.ts("the screen shows the share, the budgets that refused and the agent refused") passed in all four local runs. It exercises the terminal Crawlers screen, which this pull doesn't touch, so I read it as a timing flake under the full check's load. I changed nothing for it. If it fails again on this push, it needs its own look.
I did not run scripts/gate.ts or scripts/design-lint.ts this round. The only change was a test edit.
To try it, open /settings/traffic as an admin, with ?window=15m, 24h or 7d to switch the window.
I merged main into the branch and pushed; the only conflict was docs/design/areas/settings.md.
- Conflict: both sides had added a paragraph there: ours on Settings › Traffic (#9775), theirs on Settings › Crew (#9826). I kept both and removed the conflict markers.
- Checks:
tsc --noEmitandbun scripts/design-lint.tsare clean, and the traffic-history and crew-language tests pass (11 tests). - Not run: the full suite, which the forge's check runs on this push. I also did not run
scripts/gate.ts.
Earlier asks are met: the terminal door (src/tui/screens/traffic.ts, admin-only, registered, in the palette roster test) and its how-to in docs/features/traffic.md; one purpose sentence; the top lists are rows in a setting-list; no cards. The preview boots and / answers 200; /settings/traffic redirects to sign-in for me, so I could not see the admin view. Non-blocking: the empty-window test only asserts when the window happens to be empty. The negated table-string assertion in traffic-history.test.ts is brittle, so drop it for a plain not.toContain("<table") on the top lists. The traffic import in entries.ts is out of alphabetical order.
Settings › Traffic (
/settings/traffic) now has no cards and reads as headings over content, like Settings › Account.tsc,bun scripts/design-lint.tsand the traffic and shield test files pass:traffic-history,traffic-sources,traffic-truthandshield. I did not time a warm request against the 50 ms limit. I did not look at the page in a browser or check it with JavaScript off; it is plain server-rendered HTML.What changed (
src/web/pages/traffic.ts)settings-blockheaded "Who asked". They were inside one card.settings-blockwith an<h2>instead of an untitled card. An empty list is one plain sentence.htmlunchanged.docs/design/areas/settings.md. No new class.test/traffic-history.test.ts: noclass="cardon the page, and the "Who asked" block is present. The three named test files needed no change.Left out
src/web/pages/sources.tsis untouched. It renders/settings/traffic/sources, a separate page, and the referrers and campaigns the issue mentions are shown there, not on this page. It still uses cards and could get the same pass in its own issue.Try it: sign in as an admin and open
/settings/traffic, then switch between 15 minutes, 24 hours and 7 days.🤖 Generated with Claude Code
Closes #9775