Repository navigation
chore(void): drop no-op backslash normalization on pathe relative() paths - #252
Merged
Brooooooklyn merged 1 commit intoJul 4, 2026
Conversation
Brooooooklyn
approved these changes
Jul 4, 2026
Brooooooklyn
deleted the
07-04-chore_void_drop_no-op_backslash_normalization_on_pathe_relative_paths
branch
July 4, 2026 12:30
cpojer
pushed a commit
that referenced
this pull request
Sep 11, 2026
* fix(api): preserve container build log tails * fix(api): serialize terminal log pulls with teardown * fix(api): reconcile concurrent terminal teardown * fix(api): neutralize unknown teardown outcomes * fix(api): finalize recovered terminal checks * test(api): cover recovered check finalization * fix(api): align recovered teardown markers * fix(api): retry the terminal log drain inside the agent barrier onError is the one terminalizer that does not force-stop, so its single best-effort pull was also the last one: a transiently unavailable agent port swallowed the failure and the check run was finalized with no diagnostic tail, even though the agent was still holding its control server open waiting for our cursor acknowledgement. The scheduled pollLogs backstop does not save it either - it either joins the same failed single-flight request or makes one terminal, non-rearming attempt of its own. Retry on that live-terminal path within the agent's idle window (LOG_TERMINAL_DRAIN_RETRY_WINDOW_MS = 7000, one POLL_SECONDS of margin inside the 8s barrier). runLogPull now reports whether it reached a successful terminal/acknowledgement page, and pullLogsOnce accepts a caller budget so a retry cannot open a fresh whole-drain budget just before the outer deadline. teardownInFlight is rechecked after every awaited pull - including a successful one - so finalization cannot outrun a teardown that began during the I/O. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011fMATP1nmroN12aKoX2EzJ * fix(api): bound log ingestion with a deterministic work budget LOG_DRAIN_BUDGET_MS cannot bound a pull callback's CPU. A deployed Worker's clock advances on I/O, not during CPU work, so it measures the agent's response latency and scores every JSON parse, SQLite insert and WebSocket fan-out between the fetches as free. MAX_LOG_PULL_PAGES bounds the response SIZE a callback may take, and bounding the size of the data does not bound the work done on it: 32 maximum pages is 64 MiB copied once per subscriber plus one, and all of it sits in front of the SIGTERM a cancel or timeout depends on, against the invocation's CPU allowance. Charge each ingested row (1 + subscribers) * max(1, ceil(len / LOG_SINK_OP_PAYLOAD_BYTES)) sink operations and stop the callback once MAX_LOG_SINK_OPS_PER_DRAIN is spent. The cap is MAX_STORED_LOG_LINES because that is the DO's retained window - rows ingested past it in the same callback are deleted by that same batch's eviction, so a larger budget could only buy work whose result is immediately discarded. Checked between pages, never inside one: a page is ingested atomically, so the cursor never advances past rows that did not reach the sink and one maximum page may overshoot. A callback stopped by the budget skips its final acknowledgement request; the next one's since=<advanced cursor> is that acknowledgement, and onError's retry loop supplies it on the terminal path that has no next callback. Regressions freeze Date.now() for the whole drain, so the wall-clock deadline can never expire and only the work bound can stop the loop. Each covers a dimension the others do not: page rows, WebSocket fan-out width, row payload bytes, and the teardown path reaching its SIGTERM. All four take 32 pages without the budget. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011fMATP1nmroN12aKoX2EzJ * docs(meta): record the clock-cannot-bound-work lesson Pairs with the existing "a page cap bounds WORK, not LATENCY" entry. The whole-drain deadline added for that one turned out to bound nothing on the work axis: a Worker's clock advances on I/O and stands still during CPU. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011fMATP1nmroN12aKoX2EzJ --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
What
This removes the
.replace(/\\/g, '/')calls that were applied to the results of patherelative()andjoin()across seven files. The source files are codegen/env-types.ts, codegen/project-tsconfig.ts, drizzle/config.ts, drizzle/discover.ts, ssr/entry.ts, and sveltekit.ts, and the same no-op appeared in a test/unit/prerender.test.ts assertion, for nine occurrences in total.Why
pathe returns POSIX forward slash paths on every platform, including Windows, so calling
.replace(/\\/g, '/')on a patherelative()orjoin()result can never match anything. It is dead defensive code. codegen/route-types.ts and codegen/queue-types.ts already follow this convention and omit the call, so this brings the rest of the package in line.Safety
There is no behavior change. It was verified empirically that pathe
relative()returns forward slashes for both POSIX and Windows backslash inputs, sorelative('C:\\a\\b\\.void', 'C:\\a\\b\\src\\env.ts')returns../src/env.ts. The six other.replace(/\\/g, '/')calls in the package operate on raw path parameters rather than pathe output. Those live in shared/utils.ts (the slash helper), router/parse-filename.ts, router/websocket.ts, cli/package.ts, and prerender.ts, and they are intentionally left untouched because they normalize real OS separators.Verification
The void package typechecks cleanly with tsgo and passes oxlint. The net change is nine insertions and nine deletions across seven files with no functional effect.