fix(cli): persist what the server answered for a captured page - #3553
Open
miguel-heygen wants to merge 2 commits into
Open
fix(cli): persist what the server answered for a captured page#3553miguel-heygen wants to merge 2 commits into
miguel-heygen wants to merge 2 commits into
Conversation
A page that renders is not a page that succeeded. An error page has a title, a palette, typefaces and a DOM, so every extractor downstream reads it happily and produces a design system belonging to whoever wrote the error page rather than to the site's owner. The status was already read, once, to feed `detectBlockedPage`, and then dropped. That helper cannot stand in for it: it decides whether the rendered document LOOKS like a protection wall, over a minimal-DOM heuristic that a rich error page passes. "Was this blocked?" and "what did the server answer?" are two questions, and widening the first to carry the second would leave a heuristic owning a fact. So the response status is persisted plainly, as its own record, and every consumer decides for itself what a non-success response means for its product. Written before the blocked-page check runs, so the record's absence means "navigation never produced a response" — a third state distinct from a status of 404 and from a status of null.
…tput The status reached `CaptureResult` and was then dropped at the CLI boundary, which is the same read-once-and-discard that made the error page harvestable in the first place. `--json` is the documented programmatic surface, and an agent reading `ok: true` off a capture of a 404 has no way to see it there.
jerrai-bot-heygen
approved these changes
Aug 30, 2026
jerrai-bot-heygen
left a comment
There was a problem hiding this comment.
Reviewed at c3f279d299e299170882fc0a40bda07379caf216.
response.json, the in-process result, and the JSON CLI output preserve the same final navigation status without conflating null, 0, and a response status. The record is written before the independent blocked-page heuristic, so callers retain the server fact even when the capture produces a rich non-success document. Focused CLI/type/lint checks are green and no inline threads are open.
— Jerrai
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The failure
hyperframes captureagainst a URL that answers 404 completes successfully. The error page has a title, a palette, typefaces, sections and a DOM, so every extractor downstream reads it happily, and the capture returnsok: truewith a full design token set. Nothing in the output says the server refused.Reproduced against a local server that answers 404 with a styled error page — 11 colours and 4 typefaces extracted,
lastPhase: complete:The status was already read, once, to feed
detectBlockedPage, and then dropped on the floor. A consumer of a capture directory therefore had no way to learn it.Why not widen
detectBlockedPageAdding 404 to its status set looks like a one-line fix and is the wrong one. That helper answers "does the rendered document look like an access-protection wall?" — a heuristic gated on a minimal DOM, which a rich error page fails anyway. "Was this blocked?" and "what did the server answer?" are two different questions, and making the heuristic the carrier for the second leaves a fact owned by a guess.
The change
The status is persisted plainly, as its own record:
extracted/response.json→{ "status": 404 }, written from the same valuedetectBlockedPagealready receives.CaptureResult.httpStatus, so an in-process caller does not have to read a file the function just wrote.httpStatusincapture --json, the documented programmatic surface. Leaving it out would repeat the same read-once-and-discard one boundary later: an agent readingok: trueoff a capture of a 404 could not see it.Written before the blocked-page check, so the record's absence means "navigation never produced a response" — a third state, distinct from a status of
404and from a status ofnull. Those three are not collapsed:nullis "we never learned what the server said", which is not "fine".No behaviour changes here. Deciding what a non-success response means is left to each consumer, which is why this ships as a fact rather than a refusal.
Verification
bun run --cwd packages/cli test— 197 files, 2867 passed, 3 skipped, 0 failed.bun run --cwd packages/cli typecheck— clean (afterpackages/corebuild).oxlint/oxfmt --checkon the changed files — clean.{"status": 404}; the same page served as 200 persists{"status": 200}.nullto0in the writer fails it withexpected +0 to be null; restored byte-exact and it passes again.