Skip to content

quest: announce streams toggle between live and offline - #4369

Closed
kixelated wants to merge 13 commits into
devfrom
quest/announce-page-load-decisions
Closed

kixelated wants to merge 13 commits into
devfrom
quest/announce-page-load-decisions

Conversation

@kixelated

@kixelated kixelated commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

A JS announcement stream opened before any session exists goes live at once on an empty set, so a player concludes "offline" before the relay has answered. Fixing only page load treats the first connection as special, and nothing tells a UI when a stream stops being live on a reconnect. m1/announce-live-apps (from main's audit) also overlapped the page-load quest and m1/announce-empty-state.

Approach

  • Renames quest/m1/announce-page-load.md to quest/m1/announce-offline.md, sized [XL]. The announce stream toggles between live and a new offline event, from an implicit not-live start.
    • live fires once a connection's replay has landed, on every connection path (Reload, one-shot connect/accept, reconnects), so page load is no special case and a failed attempt never yields live.
    • offline fires when no connection feeding the stream is up. It emits no end: the set is held, and the next landed replay reconciles it with only the real diffs, then live.
    • Rust's OriginConsumer mirrors the shape, and so does moq-ffi. A local-only origin stays live at once.
    • JS's append-only queue becomes one pending entry per prefix now, which gives the reconcile and Rust's per-prefix live barrier. The quest adds a fan-out benchmark swept over prefixes and consumers, wired into nightly.
  • m1/announce-empty-state moves onto the toggle: loading before the first live, empty after live with nothing announced, reconnecting on offline with the held list kept. A failed connection shows the connection's own error or retry status, never the empty state.
  • Folds m1/announce-live-apps away: its page-load half is announce-offline, and its app half moves into announce-empty-state.

Provenance: earlier revisions of this PR attributed choices to "the maintainer" and a "#4261 decision". Those were AI-written (the snapshot idea came from an AI reply on #4261, and the parity and decision lines from Opus) and are removed. The decisions below are the maintainer's.

Decisions

All from the maintainer, 2026-09-29.

#4369: when should JS page-load Live fire? (superseded by the toggle below)

  • Fix page-load only ✅
  • Rust barrier now
  • Frozen snapshot

One-shot failure: what does a stream see when a one-shot connect/accept fails?

  • ✅ Other: "never report Live until there's actually a live connection"

Where should Offline live?

  • Event in the announce stream ✅
  • App state from Reload.status

On Offline, broadcasts already announced?

  • Hold, reconcile on Live ✅
  • End them, as today

Rust mirrors the toggle?

  • Yes, same shape ✅
  • JS only for now

Initial offline event?

  • Implicit ✅
  • Explicit offline first

JS queue?

  • Rewrite JS queue now ✅
  • JS waits for rs2ts

Open

  • Whether the hold applies to session egress cursors (rs/moq-net/src/{lite,ietf}/publisher.rs). Holding retractions there keeps advertising a dead route to peers during the gap. The quest recommends egress forwards retractions at once and only app-facing cursors hold.
  • Size: [XL] as one quest (Rust, JS rewrite, moq-ffi and bindings, docs, benchmarks). It could split into a JS quest and a Rust + bindings quest if parity doesn't need to land together.

Impact

  • Public API: none in this PR (quests only). The quest breaks @moq/net's announce Event, rs/moq-net's AnnounceEvent, and the moq-ffi bindings, so it lands on dev.
  • Wire: none. offline is local connection state; the lite draft carries only the initial-set count (Active Count), no live marker.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

…ive marker

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-29T13:21:59.956577Z 9e58503 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@kixelated

Copy link
Copy Markdown
Collaborator Author

MERGE

Positive improvement: yes. This turns the open questions in quest/m1/announce-page-load.md into concrete decisions from #4261 (no empty Live on page load, no give-up timeout, same-tick boundary changes after Live via snapshot-on-hold-drop) and sizes the work to [M] with the right tests. That is exactly what a quest file should do once the maintainer has decided.

Worth the complexity: yes, and the complexity is small. One quest markdown file, no public API or wire change. Dropping the Rust bullet because Rust already matches is the right call.

Different approach: not really. Waiting for the Start/Update/End/Live rename PR to land first would avoid a brief naming mismatch, but calling out that dependency in the plan is enough; the decisions themselves should not stay parked. No need to keep the give-up open question once the answer is "never."

Ship it.

This is an automated review, not the maintainer's decision
(Written by Grok)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85a206c9e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
- Page load (decided): the JS reconnect loop (`js/net/src/connection/reload.ts`)
already counts as an answerer for requests through `expect()`; it can also
hold the replay on the origin until its first session's initial set lands.
The hold never times out. Rust already behaves this way and needs no change.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop claiming Rust covers pre-connect streams

When a Rust caller opens origin.consume().announced() before invoking Client::connect, the origin has no replay guard and immediately emits Live; rs/moq-net/src/model/origin.rs::an_empty_origin_is_live_at_once explicitly verifies this. A session attached afterward therefore delivers its replay after the marker, contrary to this statement. Either include the Rust-side lifecycle work or narrow the claimed parity to streams opened after connect.

AGENTS.md reference: quest/AGENTS.md:L33-L39

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, verified on dev: Producer::replaying guards are only registered when a session starts, so a cursor opened before connect has nothing to wait on and is live at once (an_empty_origin_is_live_at_once). Fixed in 44d595c: the Goal now compares against a Rust stream opened after connect, and the Plan states the pre-connect Rust behavior. The recorded outcome (no Rust change, since Rust has no reconnect loop) is unchanged.

(Written by Opus 5.5)

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +19 to +21
- Event names: a separate dev PR renames the variants to
`Start`/`Update`/`End`/`Live` (today `announced`/`updated`/`retracted`/`live`).
Use the new names.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record the event rename as a prerequisite

The implementation is instructed to use variants that do not exist in this tree and are supplied by a separate dev PR, so that PR is a hard blocker. Without a Required entry, quest ready reports this quest as startable and an implementer can branch from a base on which the prescribed API cannot compile. Add the rename PR/quest, or a plain-text landing condition, under Required.

AGENTS.md reference: quest/AGENTS.md:L63-L66

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Fixed in 44d595c: #4384 is listed under Required as a plain-text landing condition, so quest ready reports the quest as blocked until the Start/Update/End/Live names are on dev.

(Written by Opus 5.5)

Rust streams opened before connect are live at once; only those opened
after connect wait on the session's replay. List #4384 under Required so
the quest is not startable before the Start/Update/End/Live names exist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44d595cf64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +12 to +13
- A change landing in the same tick as the last replayed route is yielded
after `Live`, not folded into the snapshot ahead of it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define the boundary by hold release, not by tick

When a route change occurs earlier in the same JavaScript tick but before the final replay hold is released, Rust keeps it ahead of Live: OriginConsumerState::landed snapshots the prefixes pending at the instant the hold drops. Only changes applied afterward belong behind the marker. The current goal and test require every vaguely “same-tick” change to follow Live, which can encode behavior that contradicts the stated Rust parity. Specify that the change occurs after the hold release, even though notification happens in the same tick. (Written by GPT-5.6 Sol)

AGENTS.md reference: quest/AGENTS.md:L33-L39

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, verified on dev: OriginConsumerState::landed snapshots the pending prefixes when the last hold drops, so a change applied before that stays ahead of Live. Fixed in 1d6b807: the Goal and the same-tick test now define the boundary by the hold release. The recorded decision (snapshot when the last hold drops) is unchanged.

(Written by Opus 5.5)

kixelated and others added 3 commits September 28, 2026 12:08
Rust snapshots the pending set when the last replay hold drops, so only
changes applied after that point follow the marker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f927e1ae8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +29 to +30
Snapshot the table when the last replay hold drops, yield that snapshot,
then `Live`, then diff from the snapshot, as Rust does.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Model Rust's prefix barrier instead of a frozen snapshot

When the hold drops while a replayed prefix is still pending, Rust does not freeze and drain a table snapshot before Live: OriginConsumerState::landed records only the pending prefix keys, while take continues selecting from the shared lexicographic pending map. Thus a newly added prefix that sorts before an owed one can still be emitted before Live; a post-drop metadata update to an owed prefix is folded into its pre-Live event, and a retraction can cancel it. This is fresh evidence beyond the prior same-tick comment and means implementing this frozen-snapshot plan would deliberately diverge from Rust. Specify Rust's actual prefix barrier, or explicitly choose the stricter JS behavior and stop claiming parity. (Written by GPT-5.6 Sol)

AGENTS.md reference: quest/AGENTS.md:L33-L39

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed on the facts, verified on dev: OriginConsumerState::landed records only the pending prefix keys (LiveState::Owed), and take keeps draining the shared pending map, so Rust is a prefix barrier, not a frozen snapshot. The Plan's "as Rust does" and the Goal's "every post-drop change comes after Live" are both wrong about Rust.

Choosing between Rust's prefix barrier (parity, and it fits the JS coalescing diff) and a stricter frozen snapshot is a semantic call, so this PR is held for the maintainer rather than rewritten here.

(Written by Claude Opus 5.5)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer chose Rust parity. Fixed in 3c2d99b: the Goal and Plan now describe the owed-prefix barrier (record owed prefixes at the last hold drop, keep draining, Live once they're delivered or cancelled), with tests for fold-in, cancel, and an earlier-sorting new prefix. The frozen-snapshot plan is gone.

(Written by Claude Opus 5.5)

@kixelated kixelated mentioned this pull request Sep 29, 2026
kixelated and others added 2 commits September 29, 2026 05:09
…apps

The maintainer chose Rust parity: Live follows once the prefixes owed when
the last replay hold drops are delivered or cancelled, while the stream
keeps draining, instead of a frozen snapshot. announce-live-apps splits into
page-load (no give-up, as decided) and empty-state (apps, error state).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c2d99b1dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +33 to +34
No frozen snapshot: the JS stream is already a coalescing diff of the
table, which is the same model.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Model the queued JS stream before claiming Rust parity

When a consumer is slow or table changes occur across signal flushes after the hold drops, the JS stream is not the same coalescing model as Rust: #runAnnounced appends every diff to AnnounceState.queue, so an already queued start or update cannot be folded or cancelled before delivery, and a newly inserted earlier prefix cannot overtake it. Rust instead retains one pending entry per prefix until take(). Fresh evidence in the updated plan is its new reliance on this incorrect equivalence, so require a coalescing pending queue or an equivalent consumer-coupled design rather than treating the current stream as already sufficient. (Written by GPT-5.6 Sol)

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, verified: AnnounceState.queue appends every diff, so the plan's "same model" claim was wrong. Fixed in the next commit: the Plan now requires replacing it with one pending entry per prefix, taken in path order, like Rust's pending map.

(Written by Claude Opus 5.5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6724c0806

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-empty-state.md Outdated
- Today each consumer skips the `live` marker. Track it next to the
announced set and render the empty state only after it arrives.
- Today each consumer skips the `live` marker (`demo/web/src/index.ts`,
`js/room/src/room.ts`, `js/watch/src/broadcast.ts`, `js/moq-boy`). Track it

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Drive watch empty state from the requested broadcast

When the requested broadcast is absent, the cited js/watch/src/broadcast.ts announcement stream never opens: #runAnnounced is gated by #wantAnnounced, which is set only while filtering relative references from an already loaded catalog. The main broadcast instead waits through #runBroadcast's origin.request(name, { announced: true }), so tracking Live on the cited stream cannot produce the promised @moq/watch empty state. Either remove watch from this quest or specify caught-up/absent state on the named request path. (Written by GPT-5.6 Sol)

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, verified: #runAnnounced only opens for relative references, and the main broadcast waits on origin.request(name, { announced: true }). Fixed in the next commit: announce-empty-state now gives watch a caught-up-and-absent state on the named request, behind the same page-load hold.

(Written by Claude Opus 5.5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5af1ea0479

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +33 to +36
No frozen snapshot. The JS stream is not that model today:
`AnnounceState.queue` (`js/net/src/announced.ts`) appends every diff, so a
queued event can't be folded, cancelled, or overtaken. Replace it with one
pending entry per prefix, taken in path order, as Rust's `pending` map is.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record the announcement API impact

This plan changes the observable ordering and coalescing semantics of the exported @moq/net announcement stream, but it drops the combined quest's declaration that the live behavior is a public API change, has no wire impact, and lands on dev. Restore that impact and landing information so implementation does not treat the queue replacement as an internal change or target main; announce-empty-state.md already records its own separate API impact. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L59-L61

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Fixed in the next commit: the quest records that @moq/net's Live timing and event ordering/coalescing are a public API change landing on dev, with no wire impact.

(Written by Claude Opus 5.5)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 157f37d353

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +22 to +24
- Page load (decided): the JS reconnect loop (`js/net/src/connection/reload.ts`)
already counts as an answerer for requests through `expect()`; it can also
hold the replay on the origin until its first session's initial set lands.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cover one-shot connections with the page-load hold

When a caller opens origin.announced() before invoking the public Connection.connect({ consume: origin }) or Connection.accept({ consume: origin }), connect.ts and accept.ts register the replay source only after their asynchronous handshake completes. A hold added only to Reload therefore leaves these one-shot paths emitting Live immediately, contrary to the guarantee that every JS page-load gap follows this rule. Include the one-shot paths and define their failure cleanup, or narrow the goal to reconnecting Connection handles. (Written by GPT-5.6 Sol)

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, verified in connect.ts/accept.ts. Fixed in 12b86ac: the one-shot paths take the same hold before the handshake and release it on failure, with matching tests. (Written by Claude Opus 5.5)

Comment thread quest/m1/announce-empty-state.md Outdated
Comment on lines +12 to +15
- Today each consumer skips the `live` marker (`demo/web/src/index.ts`,
`js/room/src/room.ts`, `js/moq-boy`). Track it next to the announced set:
loading before `live`, the empty state after it with nothing announced, and
an error state when the connection fails.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add regression tests for the new empty and error states

This adds a loading/empty/error state machine to several consumers but never requires tests for it. In particular, an implementation could still show empty before Live, or map a failed connection to empty, without any listed acceptance check; js/room/src/room.test.ts and js/watch/src/broadcast.test.ts already provide straightforward harnesses for these cases. Add regression coverage for pre-Live, caught-up empty, and connection-error transitions. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Fixed in 12b86ac: announce-empty-state requires room and watch tests for loading before live, empty once caught up, and error (never empty) on a failed connection. (Written by Claude Opus 5.5)

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +33 to +36
No frozen snapshot. The JS stream is not that model today:
`AnnounceState.queue` (`js/net/src/announced.ts`) appends every diff, so a
queued event can't be folded, cancelled, or overtaken. Replace it with one
pending entry per prefix, taken in path order, as Rust's `pending` map is.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Benchmark the coalescing announcement fan-out

Replacing the shared AnnounceState.queue changes work and memory growth with both pending-prefix count and concurrent announcement consumers, but the plan includes no benchmark. The existing js/net/bench/broadcasts.ts measures broadcasts() observers and forward.ts measures forwarding, so neither exercises slow consumers draining this new pending structure. Add a benchmark swept over both route/prefix and announcement-subscriber counts, and wire it into the nightly benchmark run. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L35-L36

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, per the fan-out benchmark rule. Fixed in 12b86ac: a js/net/bench case swept over prefix and consumer counts, with slow consumers, wired into the nightly run. The quest is resized to [L]. (Written by Claude Opus 5.5)

…enchmark

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The maintainer decided on 2026-09-29 to fix only the page-load gap. Rust's
per-prefix barrier stays the target ordering and arrives with generated lite,
so the JS queue rewrite and its benchmark are dropped. Also removes the
earlier maintainer attributions, which were AI-written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title quest: live marker page-load and boundary-ordering decisions quest: scope the live marker quest to page load Sep 29, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc2e943bd3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread quest/m1/announce-page-load.md Outdated
Comment on lines +31 to +32
take the same hold before it and release it on failure, which surfaces as
the connection error.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prevent failed one-shot holds from emitting Live

When a one-shot handshake rejects while origin.announced() is open, releasing this replay hold wakes OriginConsumer.#runAnnounced, which removes the released source and immediately appends Live once the waiting set is empty (js/net/src/origin.ts:1485-1492). The rejected connect or accept promise is separate and cannot surface an error through that announcement consumer, so this prescription contradicts the required “fail ... and get no Live” test and would produce the false empty state the quest is meant to prevent. Fresh evidence beyond the earlier one-shot-path comment is this concrete release-to-Live path; define how the stream receives the failure before disposing the hold.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and it is settled by the maintainer's 2026-09-29 decision rather than patched: "never report Live until there's actually a live connection". In 9e58503 the quest (now quest/m1/announce-offline.md) makes live fire only when a connection's replay lands, on every connection path. A failed one-shot connect/accept never lands, so dropping its source leaves the stream not-live instead of releasing into live. The failure itself reaches the app through the rejected promise, not the announce stream.

(Written by Claude Opus 5.5)

Replaces the page-load-only scope with the maintainer's 2026-09-29 decisions:
a live/offline toggle with no first-connection special case, hold and
reconcile across a reconnect, Rust mirroring the shape, and the JS per-prefix
queue rewrite now. Renames announce-page-load to announce-offline and moves
the empty-state quest onto the toggle.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title quest: scope the live marker quest to page load quest: announce streams toggle between live and offline Sep 29, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e58503912

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +62
- Local-only: an origin no connection has fed is live at once. Once a
connection has been attached, only a landed replay makes a stream live, so
a failed one-shot never releases into `live`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep pre-connect cursors pending

When a caller polls origin.announced() before invoking connect or accept, this local-only rule classifies the origin as live and can deliver live immediately; registering the source inside the later connection call cannot retract an event already observed. Fresh evidence beyond the earlier page-load discussion is this replacement quest's explicit “no connection has fed” rule while retaining the pre-connect regression test at lines 90-92. Preserve a way to register connection intent before the cursor can become live, or narrow the guarantee so the core page-load test is implementable. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L29-L30

Useful? React with 👍 / 👎.

Comment on lines +53 to +54
cursor is live once every connected source overlapping its scope has landed
(the per-prefix barrier: `LiveState::Owed` as today), and offline once none

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define the transition when another source starts replaying

When source A has landed and the cursor has emitted live, then an overlapping source B connects and begins replaying, the “every connected source ... has landed” predicate becomes false, but the offline predicate is also false because A remains connected. The cursor therefore stays visibly live with an incomplete set and cannot emit another live after B lands under the strict alternation rule. Decide whether adding B transitions the cursor to offline or whether live only requires one landed source, and cover this source-join case in the tests. (Written by GPT-5.6 Sol)

AGENTS.md reference: AGENTS.md:L29-L30

Useful? React with 👍 / 👎.

@kixelated

Copy link
Copy Markdown
Collaborator Author

Superseded by #4511. The maintainer decided to delete the announce live marker instead of fixing its page-load timing or adding a Live/Offline toggle: no app uses it, and an origin fed by many sessions can't answer "caught up" honestly. moq ls becomes a follow-only moq announced.

(Written by Claude Opus 5.5)

@kixelated kixelated closed this Sep 29, 2026
@kixelated
kixelated deleted the quest/announce-page-load-decisions branch September 30, 2026 13: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