Skip to content

Tidy up after the cursor API, the boot sweep and the panel rework - #49

Merged
botre merged 3 commits into
masterfrom
chore/test-organization-and-tidy
Aug 9, 2026
Merged

Tidy up after the cursor API, the boot sweep and the panel rework#49
botre merged 3 commits into
masterfrom
chore/test-organization-and-tidy

Conversation

@botre

@botre botre commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

A cleanup pass over everything shipped in the last twelve hours: the cursor API (#47), the retention sweep at boot (#46) and the disclosure panel rework (#48).

Tests now sit beside their subject

routes_test.go held the tests for six subjects at once and had no source counterpart, so a handler's tests lived nowhere near it. Each suite moved to the file for the code it covers and is named after what it exercises (TestHandleListRequests, TestCaptureRequest, TestRenderEndpoint, TestRequireValidEndpoint, …). harness_test.go holds TestMain and the fixtures every request-driving test shares. AGENTS.md records the rule.

Gaps filled

Covering behaviour that shipped without a test:

  • startRetentionSweep sweeps at boot. The point of Sweep at boot, and stop rendering swept captures #46, previously only covered one layer down at sweepRetention.
  • hasMore on a full page, and a burst draining to false. It is the signal a poller throttles on, and the agent prompt tells agents to trust it.
  • A cursor is never handed back older than it was sent. Without the clamp a poller's cursor walks backwards and it reprocesses its history.
  • newestCreatedAt scans rather than reading an end, which is why the listing can flip its order safely.
  • A malformed inbound X-Request-Id is replaced, not echoed, so a caller cannot shape a log line.
  • The body limit, end to end (capture-api.spec.ts): over the limit is a 413, at the limit round-trips whole. Only a real socket can see this.
  • A swept capture stops being rendered, the page half of Sweep at boot, and stop rendering swept captures #46.
  • Each disclosure panel opens independently, and the send panel is collapsed by default like its neighbour.

Duplication removed

  • Both panels repeated the same 11-class summary string and the same body wrapper. They are now .panel-summary and .panel-body, which is what components.css and DESIGN.md already ask for: a template that re-spells a component as a utility string is the bug. Make the agent panel's copy button a secondary control #48 had to edit both copies in step, which is the drift this prevents.
  • Four SVGs appeared twice each. They are partials under views/partials/icons/.
  • pluralize replaces four hand-rolled n === 1 ? x : xs ternaries across the page scripts and the template.
  • The store built the same API route at three call sites; now one requestsUrl helper.
  • The capture UUID response header is a named constant rather than a literal in the handler and in tests.
  • The pages render the retention window from retentionWindow instead of typing "4 hours" in three places. agent.go already made this argument for the prompt; the copy the user reads deserves the same. Moving the constant now moves the promise.

Docs corrected

docs/api.md promised an unconditional 200 from the capture route, which the body limit has never honoured. PRODUCT.md described a listing that only ever ordered newest first, which stopped being true with the cursor. AGENTS.md had no entry for agent.go. A comment in render-body.js pointed at the file the header flattening used to live in.

Lint, types and spelling

Already at zero and still there: no eslint findings, no eslint-disable, no @ts-ignore or @ts-expect-error, no any annotations or unsafe assertions (the one Go type assertion uses the comma-ok form). No typos or doubled words found, and no em dashes were introduced.

Verification

go vet, go test ./src/... (206 assertions), gofmt, eslint, tsc --noEmit and prettier --check are all clean, and public/app.css matches a fresh build. The Playwright suite is 69/69.

Port 8080 was held by an unrelated process on the machine, so the app was driven on a temporary port for QA; the committed port constant and Playwright config are untouched. Against a real server: capture with UUID header, the full documented cursor loop draining a burst exactly once, malformed-ID 404s, a malformed since 400, the 413 and at-limit round trip, and the retention prose rendering from the constant. In Chrome: the landing page, both panels opening independently, a request sent from the send panel arriving live over the WebSocket, search across body/query/headers, singular and plural counts, delete-one and delete-all confirmation, the agent prompt quoting the serving host, and a swept capture disappearing on the next prune. No console errors. The rendered endpoint page was diffed against master and is byte-identical apart from the intended class and x-text swaps.

One thing found, not fixed

A body over 1 MiB answers 413, but the capture handler still runs and stores a capture with an empty body, so the endpoint page shows the request with "None" where the payload was. That predates this window and fixing it changes the capture path, so it is flagged rather than folded in here. Happy to open a follow-up.

🤖 Generated with Claude Code

https://claude.ai/code/session_017NsCXwruqBye5cySvFEFiB

botre added 3 commits August 9, 2026 11:30
routes_test.go held the tests for six subjects at once, so the tests for a
handler lived nowhere near it and the file had no source counterpart. Each
suite now sits beside the code it covers and is named after what it exercises,
and the shared request harness has a file of its own.

Claude-Session: https://claude.ai/code/session_017NsCXwruqBye5cySvFEFiB
Both panels repeated the same summary class string and the same four SVGs,
which is how two nominally identical controls drift apart. The summary and its
body are now component classes, the shared glyphs are partials, and the pages
render the retention window from the constant the sweep uses instead of typing
a figure that outlives it.

Claude-Session: https://claude.ai/code/session_017NsCXwruqBye5cySvFEFiB
The API doc still promised an unconditional 200, PRODUCT.md still described a
listing that only ever ordered newest first, AGENTS.md's file inventory had no
entry for the agent prompt, and a comment pointed at the file the header
flattening used to live in.

Claude-Session: https://claude.ai/code/session_017NsCXwruqBye5cySvFEFiB
@botre
botre merged commit 53b9cf6 into master Aug 9, 2026
4 checks passed
@botre
botre deleted the chore/test-organization-and-tidy branch August 9, 2026 09:59
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