Uh oh!
There was an error while loading. Please reload this page.
Conversation
…losed page
Two things an agent parked on the queue could not see.
**A review going out.** Nothing wakes for a submit, so an agent could
answer a question about a finding already on the pull request and word it
as though it were not. `await` now reports, on the way back, how many
findings went out while it was parked, against a per-session watermark.
Reported rather than raised: it is worth knowing, not worth interrupting
for.
Both stamps carry milliseconds. `datetime('now')` is whole seconds, and a
submit landing in the same second as the watermark compares equal and is
never mentioned — which is exactly when it is most likely, since the
agent has just been handed a question about it.
**A closed tab.** The page holds no connection, it polls, so its requests
are the only evidence a window is open; the agent marks its own with a
header so it is not mistaken for one. A wait now ends as soon as a window
that was open stops asking, and `await` exits 4 so the loop stops instead
of re-arming every few minutes into a page nobody has open.
A window that has never been open is deliberately different: an agent is
usually armed before the reader opens the page, and stopping then would
end the loop before it began. `viewerGone` says which, because
`viewerPresent` alone cannot.
v0.9.14.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018PkYQzbsnMihHesafWvXKsSelf-review. Presence was inferred from the page polling, and react query stops polling a hidden tab — `refetchIntervalInBackground` defaults to false. So switching to another window for twenty seconds read as a closed page and stopped the loop, which is the flow this was built for. Silence was the wrong signal. A closed tab has a precise one: `pagehide` with `sendBeacon`, delivered during unload where a normal request is abandoned. That now ends a wait, at once. The page also beats every fifteen seconds and again whenever it is looked at, as the fallback for a crash or a kill, and the idle window is three minutes so a throttled background timer still counts. The wait also knows why it ended. `listenerGone` is aborted both by the agent hanging up and by the reader leaving, and those need opposite responses — one has no socket left to write to, the other is waiting for an answer. The watcher sets a flag rather than the handler guessing from state that may have moved since. v0.9.15. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PkYQzbsnMihHesafWvXKs
fiddur added a commit
that referenced
this pull request
Aug 27, 2026
Both open branches bumped from develop at 0.9.13, so this one took 0.9.14 while #37 took 0.9.15 — and whichever merged second would have sent the version backwards. The message on the previous commit named 0.9.16 on that assumption; this makes it true. The rule in AGENTS.md says to bump inside the pull request, which cannot be right for two branches at once. Worth a line there about the second one to merge needing a re-bump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018PkYQzbsnMihHesafWvXKs
fiddur
marked this pull request as ready for review
August 27, 2026 08:25
fiddur added a commit
that referenced
this pull request
Aug 27, 2026
…38) Both tweaks. ### The count was one list short The bell was fed `unseenAlerts` — what a note leaves behind *after* its ten seconds run out. So an answer was invisible to the bell while its bubble was on screen, and then the number rose at the moment nothing had actually happened. Both lists reach it now, deduplicated by thread, so it means "answers waiting" rather than "notes that have timed out". ### The tab now says so A red mark on the favicon while anything is unread. That is the case that matters most: a reader in another window cannot see the bell at all, which is also the case #37 is about. Built as SVG text rather than drawn on a canvas, because the icon already is an SVG — the mark inherits its scaling, and its ring can use the same `prefers-color-scheme` rule the icon already uses, so it stays legible on a light tab strip and a dark one. The icon is fetched once and kept, and if it cannot be read the tab is simply left alone. Checked the geometry rather than eyeballing it: the badged icon parses as XML, and the ring spans x 200–400, y 10–210 in a 411×395 canvas, so nothing clips. My first coordinates put the ring 5 units past the right edge. ### Verified parser 43, git 44, github 21, ui 414, cli 190. Typecheck 0. **One honest gap:** the one-line prop wiring in `diff-page.tsx` has no test, because `DiffPage` is rendered by no test in the repo — it is the hub, with router and loader dependencies. The *behaviour* is pinned (a note moving from shown to expired leaves the count unchanged) via `unreadAlerts` and the bell; only the literal pass-through is not. Same structural gap I noted on #35. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_018PkYQzbsnMihHesafWvXKs --------- 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 freeto 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 two things you asked about, and they turned out to need different mechanisms.
A review going out
Nothing wakes an agent for a submit, so it could answer a question about a finding already on the pull request and word it as though it were not.
awaitnow reports what happened while it was parked, against a per-session watermark (agent_seen_at), and the skill tells it to read that before answering.Reported on the way back rather than raised as an event — you said it should not disconnect for this, and it does not.
One thing that only showed up in a test:
datetime('now')is whole seconds, so a submit landing in the same second as the watermark compares equal and is silently never mentioned. That is precisely when it is most likely, since the agent has just been handed a question about it. Both stamps carry milliseconds now.A closed tab
The page holds no connection — it polls — so its requests are the only evidence a window is open. The agent marks its own requests with
x-diffity-agent: 1so its polling is not mistaken for a window, and/api/live/claimnever counts regardless.A wait ends as soon as a window that was open stops asking, and
awaitexits 4 so the loop stops rather than re-arming forever.The distinction that matters: a window that has never been open is not the same as one that closed. An agent is usually armed before the reader opens the page, and treating "nobody watching" as "stop" would end the loop before it began. My first version got this wrong —
viewerPresent: falsereads identically in both cases — so the protocol now carriesviewerGoneexplicitly.Verified
Three cases end to end against a real server and a real
await: never opened holds the wait (exit 3), a page seen then quiet stops at 20s (exit 4), a page still polling holds (exit 3). Plus HTTP-level tests for the claim route and unit tests for both pure pieces.parser 43, git 44, github 21, ui 395, cli 209. Typecheck 0. v0.9.14.
🤖 Generated with Claude Code
https://claude.ai/code/session_018PkYQzbsnMihHesafWvXKs