Repository navigation
test(browser): let a late publication land after its page closed - #2565
Conversation
…ok journey ends ## Problem WebKit's `nested-replies.spec.mjs:434` "branch hooks land on each reply's avatar across sides and row shapes" failed on attempt 1 on branch codex/security-history-records, and the same SHA passed on rerun. Every test step passed. The failure was a fixture fault thrown from a timer after the test body ended: - run 41727340697 (webkit 9/14), https://github.com/block/buzz-app/actions/runs/41727340697/job/126236093768 Error: event must traverse an explicit production channel REQ at Object.publish (policy-relay.mjs:799) at acceptPublication (fixture.mjs:1916) at Timeout._onTimeout (policy-relay.mjs:618) At that SHA, fixture.mjs:1916 is the `relay.publish` for kinds 7, 5 and 40003. ## Cause The journey ends by reacting 👍 to the emoji reply. The UI shows the reaction chip optimistically, so `toBeVisible` passes before the signed kind-7 publish reaches the relay. The test then measures the hook and ends, and the `app` fixture closes the page. If the frame reaches the policy relay just before close, its acceptance timer fires after the sockets have closed. `relay.publish` then finds no channel REQ and faults. The trace shows this order. The 👍 click took 1.67 s to land (158701 to 160369 ms). `toBeVisible` passed at 160400 and the page closed at 160568. Locally the publish is late on every run. The broker logs "Socket connection interrupted" for each kind-7 publication, because the frame usually doesn't reach the relay before close at all. The fault needs the narrower ordering seen in CI: the frame lands, then the page closes before the acceptance timer fires. ## Fix After the chip shows, poll `app.report.publications` for the kind-7 event tagged with the reply's id, as `message-actions.spec.mjs` does for its reaction and this file's first journey does for its final send. The fixture records the publication and calls `relay.publish` in the same synchronous step, so once the report has it, delivery has run while the page was still open. The other journeys in this file are not exposed in this way. The first already waits for its final send. The touch journey opens and dismisses the emoji picker without reacting. The crowded-branch journeys only make trial clicks, and the linked-reply journey only follows a link. Only the test changes (+11 lines). No assertions are loosened, and no product code changes or browser cases are added or removed. It merges cleanly with draft #2177 (which edits the crowded-branch journey) and with #2422 and #2256. ## Validation Local Linux workstation, Playwright 1.63.0, `--no-deps --retries=0`: - Adversarial ordering, using temporary, uncommitted changes: the `app` teardown waited until the relay had received the kind-7 frame before closing, the relay held that frame's acceptance for 600 ms, and the worker stayed alive for 1 s after close, as a CI worker does for its next test. Without the fix: 10/10 failed (5 WebKit, 5 Chromium) with the CI stack (`publish` from `acceptPublication` from `Timeout._onTimeout`). With the fix: 10/10 passed, and the acceptance ran while the socket was still open. - `bin/pnpm test:browser tests/browser/nested-replies.spec.mjs --project webkit --project chromium --no-deps --workers=4 --repeat-each=15 --grep "branch hooks land"`: 30/30 passed. - Full `nested-replies.spec.mjs`, both engines: 18/18 passed. - `biome check` and `git diff --check` are clean. A green run doesn't prove the flake is gone. Hosted CI covers broad validation. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: mtoohey <[email protected]> (cherry picked from commit ba5fd893f8fef8ec5ae8c5ec79b615a58cdfbad9)
… page has closed ## Problem Code review of "test(threads): wait for the reaction to reach the relay before the hook journey ends" (suggestion, `tests/browser/policy-relay.mjs`): that commit fixed one journey, but the risk is fixture-wide. The policy relay accepts each publication on a `setTimeout` after its frame arrives. If the page closes in between, the acceptance still runs. `acceptPublication` then calls `relay.publish` for kinds 9, 7, 5 and 40003, and `publish`'s `requireSubscriber` check throws "event must traverse an explicit production channel REQ", because every socket has closed. Any journey that ends right after an optimistic publish can hit this. It fails from a timer after the test body passed, with the stack `publish` ← `acceptPublication` ← `Timeout._onTimeout`. ## Fix When the acceptance timer fires and no socket in the publishing community is open (`readyState` 1), `publish` skips the delivery check for that community for the duration of that acceptance. The acceptance itself still runs: the fixture records and stores the event, as a relay accepts a frame it already received. Journeys that interrupt the connection may rely on that. With any socket in the community still open, and for every `publish` outside an acceptance, the check is unchanged. `tests/integration/policy-relay.test.mjs` adds a case with mocked timers: - A kind-7 frame whose socket closes before the timer fires is accepted, and no fault is recorded. - The same frame with a socket still open in the community, but no channel REQ, still throws. - A direct `publish` with no socket open still throws. The explicit wait in `nested-replies.spec.mjs` stays: that journey should still confirm its reaction reached the relay before it ends. ## Validation Local Linux workstation, Node `--test` and Playwright 1.63.0 (`--no-deps --retries=0`): - `node --test tests/integration/policy-relay.test.mjs`: 2/2 passed. Against the previous relay, the new case fails with "event must traverse an explicit production channel REQ", the CI error. - `nested-replies.spec.mjs` and `message-actions.spec.mjs`, WebKit and Chromium, `--workers=4`: 38/38 passed. - `biome check --error-on-warnings` and `git diff --check` are clean. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: mtoohey <[email protected]> (cherry picked from commit ede7da817ce67c5aa905be55fa06f770ec50c9d2)
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One non-blocking documentation finding; no functional or security blocker found.
The comment above the reaction poll in the branch-hook journey still mentioned the delivery fault after close, which this branch removed from the policy relay. It now states what the poll asserts: the reaction chip renders optimistically, so the poll confirms a signed kind-7 tagged with the reply's id actually reached the relay. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: mtoohey <[email protected]>
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord — consolidated Guardians source review.
Reviewed head 84f61d58b6c7ff6a6c6597dc05bb5f72e0e4cf3f against base f4805605f56a2f60bd25b966464f07f0c3292a41.
No actionable findings; recommend approval of the reviewed change.
The late-acceptance exception is limited to the publishing community with no open socket, and resets in finally. Supported fixture callbacks deliver synchronously; the held-join promise delays only acknowledgement. Authentication, signature and event validation remain intact, and open-socket/direct-publication delivery checks remain strict. The timer-controlled regression covers those boundaries. The nested-replies wait confirms a signed reaction targeting the reply before continuing, preserving the geometry assertions. The earlier comment-wording feedback is addressed.
Source-only review: no tests, builds or app execution. The author's adversarial/repeat results and original CI trace were not independently reproduced. Rocket, Mantis, Groot and Star Lord completed their independent lanes and integration.
Hosted run 41967248121 at this head passed all 10 changed-journey repetitions per engine. Chromium command wall/summed execution/slowest repetition: 100.381/106.177/10.983 seconds; WebKit: 217.385/331.973/37.219 seconds. The sole selected file was nested-replies.spec.mjs. No comparable before-change timing was inspected, so these figures do not establish a cost improvement or prove all fixture callers.
…leanup * origin/main: test(mentions): serve the mentions fixture as a build so cold loads fit (#2776) test(browser): let a late publication land after its page closed (#2565) test(relay): wait for the verified owner before a guest edits an agent (#2413) test: wait for the companion default width measurement (#2750) test(browser): preserve conversation scroll while revealing actions (#2715) test(browser): wait for link hit-testing after thread close (#2792) perf(messages): skip micromark for plain prose bodies (#2780) perf(inbox): load the emoji name table on first use (#2774) perf(messages): cut main-thread work while a busy channel is open (#2729) Refine agent Attention cards, watch details, and status controls (#2717) fix(bestie): remove a Bestie from its agent card on any device (#2720) feat(agents): preview Builderlab agent card links with Add to Buzz (#2719)
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz> Co-authored-by: Tyler Longwell <[email protected]> Signed-off-by: Tyler Longwell <[email protected]> * origin/main: test(messages): wait for the row measurement frame before thread catch-up dwell (#2837) Keep agent coordination history readable after work finishes (#2454) test(mentions): serve the mentions fixture as a build so cold loads fit (#2776) test(browser): let a late publication land after its page closed (#2565) test(relay): wait for the verified owner before a guest edits an agent (#2413) test: wait for the companion default width measurement (#2750) test(browser): preserve conversation scroll while revealing actions (#2715) test(browser): wait for link hit-testing after thread close (#2792) perf(messages): skip micromark for plain prose bodies (#2780) perf(inbox): load the emoji name table on first use (#2774) perf(messages): cut main-thread work while a busy channel is open (#2729) Refine agent Attention cards, watch details, and status controls (#2717) fix(bestie): remove a Bestie from its agent card on any device (#2720) feat(agents): preview Builderlab agent card links with Add to Buzz (#2719) Restore macOS Cmd-W window closing when no tab handles it (#2443) Make agent transcripts quieter and link finished replies to activity (#2424)
…ve-enter * origin/main: (21 commits) Make drafts and sent part of Messages (#2728) fix(canvas): render every Canvas within the save limit (#2839) test(messages): wait for the row measurement frame before thread catch-up dwell (#2837) Keep agent coordination history readable after work finishes (#2454) test(mentions): serve the mentions fixture as a build so cold loads fit (#2776) test(browser): let a late publication land after its page closed (#2565) test(relay): wait for the verified owner before a guest edits an agent (#2413) test: wait for the companion default width measurement (#2750) test(browser): preserve conversation scroll while revealing actions (#2715) test(browser): wait for link hit-testing after thread close (#2792) perf(messages): skip micromark for plain prose bodies (#2780) perf(inbox): load the emoji name table on first use (#2774) perf(messages): cut main-thread work while a busy channel is open (#2729) Refine agent Attention cards, watch details, and status controls (#2717) fix(bestie): remove a Bestie from its agent card on any device (#2720) feat(agents): preview Builderlab agent card links with Add to Buzz (#2719) Restore macOS Cmd-W window closing when no tab handles it (#2443) Make agent transcripts quieter and link finished replies to activity (#2424) fix(channels): wrap unread conversation stepping around the sidebar (#2682) fix(navigation): let bare buzz:// open Buzz without a broken-link notice (#2718) ...
Co-authored-by: BuzzPRReviewAssistant1 <a581a7e8115222acdc32ffb14bfce55d48c24478d98e155f8eba126b69b83c7b@buzz.block.builderlab.xyz> * origin/main: (71 commits) test(activity): scope preview assertions to the request row (#2843) perf(search): fold people names once across palette keystrokes (#2570) fix(github): keep PR watches running when localStorage is full (#2699) Make drafts and sent part of Messages (#2728) fix(canvas): render every Canvas within the save limit (#2839) test(messages): wait for the row measurement frame before thread catch-up dwell (#2837) Keep agent coordination history readable after work finishes (#2454) test(mentions): serve the mentions fixture as a build so cold loads fit (#2776) test(browser): let a late publication land after its page closed (#2565) test(relay): wait for the verified owner before a guest edits an agent (#2413) test: wait for the companion default width measurement (#2750) test(browser): preserve conversation scroll while revealing actions (#2715) test(browser): wait for link hit-testing after thread close (#2792) perf(messages): skip micromark for plain prose bodies (#2780) perf(inbox): load the emoji name table on first use (#2774) perf(messages): cut main-thread work while a busy channel is open (#2729) Refine agent Attention cards, watch details, and status controls (#2717) fix(bestie): remove a Bestie from its agent card on any device (#2720) feat(agents): preview Builderlab agent card links with Add to Buzz (#2719) Restore macOS Cmd-W window closing when no tab handles it (#2443) ... Signed-off-by: Ravneet Arora <[email protected]>
…ime-hint * upstream/main: (26 commits) Make drafts and sent part of Messages (block#2728) fix(canvas): render every Canvas within the save limit (block#2839) test(messages): wait for the row measurement frame before thread catch-up dwell (block#2837) Keep agent coordination history readable after work finishes (block#2454) test(mentions): serve the mentions fixture as a build so cold loads fit (block#2776) test(browser): let a late publication land after its page closed (block#2565) test(relay): wait for the verified owner before a guest edits an agent (block#2413) test: wait for the companion default width measurement (block#2750) test(browser): preserve conversation scroll while revealing actions (block#2715) test(browser): wait for link hit-testing after thread close (block#2792) perf(messages): skip micromark for plain prose bodies (block#2780) perf(inbox): load the emoji name table on first use (block#2774) perf(messages): cut main-thread work while a busy channel is open (block#2729) Refine agent Attention cards, watch details, and status controls (block#2717) fix(bestie): remove a Bestie from its agent card on any device (block#2720) feat(agents): preview Builderlab agent card links with Add to Buzz (block#2719) Restore macOS Cmd-W window closing when no tab handles it (block#2443) Make agent transcripts quieter and link finished replies to activity (block#2424) fix(channels): wrap unread conversation stepping around the sidebar (block#2682) fix(navigation): let bare buzz:// open Buzz without a broken-link notice (block#2718) ... Signed-off-by: Cheng Peng <[email protected]> Co-authored-by: Cursor <[email protected]>
Summary
The policy relay fixture accepts each publication on a timer after its frame arrives, and if the page closes in between, the acceptance still calls
relay.publish. Its delivery check then throws "event must traverse an explicit production channel REQ" from a timer, after the test body has already passed. This branch makes the nested-replies hook journey wait for its reaction to reach the relay before it ends. It also makes the relay skip only that delivery check for an acceptance whose community has no open socket, so the fault can't hit any other journey that ends right after an optimistic publish.test(threads): wait for the reaction to reach the relay before the hook journey ends
Problem
WebKit's
nested-replies.spec.mjs:434"branch hooks land on each reply's avatar across sides and row shapes" failed on attempt 1 on branch codex/security-history-records, and the same SHA passed on rerun. Every test step passed. The failure was a fixture fault thrown from a timer after the test body ended:Cause
The journey ends by reacting 👍 to the emoji reply. The UI shows the reaction chip optimistically, so
toBeVisiblepasses before the signed kind-7 publish reaches the relay. Theappfixture then closes the page. If the frame reaches the relay just before the close, its acceptance timer fires after the sockets have closed, andrelay.publishfaults. In the trace, the 👍 click took 1.67 s to land (158701 to 160369 ms).toBeVisiblepassed at 160400 ms and the page closed at 160568 ms.Fix
app.report.publicationsfor the kind-7 event tagged with the reply's id, asmessage-actions.spec.mjsdoes.relay.publishin the same synchronous step, so once the report has the event, delivery has already run while the page was open.Validation
Local Linux workstation, Playwright 1.63.0,
--no-deps --retries=0:Adversarial ordering, using temporary, uncommitted changes:
appteardown waited until the relay had received the kind-7 frame before closingWithout the fix: 10/10 failed (5 WebKit, 5 Chromium) with the CI stack. With the fix: 10/10 passed.
nested-replies.spec.mjs, "branch hooks land", both engines,--workers=4 --repeat-each=15: 30/30 passed.Full
nested-replies.spec.mjs, both engines: 18/18 passed.test(browser): accept a publication without a delivery check once its page has closed
Problem
Found in code review. The previous commit fixed one journey, but the risk is fixture-wide. For kinds 9, 7, 5 and 40003, an acceptance that fires after the page closed calls
relay.publish, whoserequireSubscribercheck throws because every socket has closed. Any journey that ends right after an optimistic publish can hit this.Fix
readyState1),publishskips the delivery check for that community, for the duration of that acceptance only.publishoutside an acceptance.tests/integration/policy-relay.test.mjsadds a case with mocked timers:publishwith no socket open still throwsnested-replies.spec.mjsstays, so that journey still confirms its reaction reached the relay before it ends.Validation
node --test tests/integration/policy-relay.test.mjs: 2/2 passed. Against the previous relay, the new case fails with the CI error.nested-replies.spec.mjsandmessage-actions.spec.mjs, both engines,--workers=4: 38/38 passed.biome check --error-on-warningsandgit diff --checkare clean.f4805605f5:tsc --noEmit, biome andgit diff --checkare clean.node --test tests/integration/policy-relay.test.mjspasses 2/2.nested-replies.spec.mjsandmessage-actions.spec.mjsin full, WebKit and Chromium,--workers=4 --retries=0: 38/38 passed.Only test code changes. No assertions are loosened, and no browser cases are added or removed. A green run doesn't prove the flake is gone. Hosted CI covers broad validation.
Coordination
nested-replies.spec.mjsnear :695 only. Its head merges with this branch without conflicts.🤖 Generated with Claude Code