Skip to content

adopt(ntfy): ready to send: account sync undoes recent changes (reserved topic loses its messages; last unsubscribe never syncs) - #157

Open
MeharPro wants to merge 1 commit into
mainfrom
claude/awesome-hypatia-274vxq
Open

MeharPro wants to merge 1 commit into
mainfrom
claude/awesome-hypatia-274vxq

Conversation

@MeharPro

@MeharPro MeharPro commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Status: ready to send (after the by-hand items in docs/adoption/hunts/ntfy-issue.md, "Before sending").

What

I ran a race hunt on the ntfy web app (binwiederhier/ntfy main at 8ed8684, after v2.37.1), retargeted per the brief to the account-sync paths. It found two bugs in web/src/app/AccountApi.js sync(), both reproduced without GenClass:

  1. A sync applies an account fetched before a local change, and undoes it. Most visible case, in natural order on localhost with no GenClass and no delay: subscribe to a topic with "Reserve topic" on while the account has another subscription. The new topic's messages get deleted locally and the topic page shows it empty: 6 of 6 loads, and 0 of 4 with no other subscription. A reload restores them (reserve-reload.mjs, 3 of 3).
  2. An empty subscription list is never applied. The server's omitempty meets if (account.subscriptions), so unsubscribing from your last topic leaves it in other browsers, even after a reload: 3 of 3 runs, and 0 of 3 when a second topic is kept.

The fix is in one file (AccountApi.js +17 −3): a counter of local account changes, a skipped sync whenever the counter moved during its fetch, and ?? [] for the missing list. The patch adds two unit tests and three Playwright checks. Nothing was sent to ntfy.

Files

  • docs/adoption/hunts/ntfy.md: the report (setup, how the app was driven, the table of all six surfaces, the finding in causal order from genclass_explain, root cause with lines, fix, tests, fixed variant, GenClass problems, time, reproducing)
  • docs/adoption/hunts/ntfy.patch: git format-patch against 8ed8684, fix and tests in one commit; verified with git apply --check
  • docs/adoption/hunts/ntfy-issue.md: the issue in ntfy's bug template, the PR text, the disclosure paragraphs and the "before sending" checklist
  • docs/adoption/hunts/ntfy/: explore.mjs (the harness), last-subscription.mjs, reserve-reload.mjs, unsubscribe-delay.mjs, results/ (small summaries, 296 KB in all), README.md
  • docs/adoption/hunts/README.md: the new row

To send (a person, from a personal account)

ntfy's docs/ai-policy.md welcomes AI-assisted PRs only if a human reviewed, understood and tested them, and asks for issue and PR text that is written or edited by the human ("Keep it concise"). There is no CLA, DCO or PR template.

  1. Do the checklist in ntfy-issue.md:
    • search the tracker again;
    • reproduce the reserved-topic case and the two-browser case by hand;
    • read the diff;
    • git am the patch, set yourself as the author, and run npm test, npm run lint, npm run format:check and make web-e2e.
  2. Rewrite the issue in your own words and file it (label 🪲 bug).
  3. Fork, push the commit, and open the PR against main with Fixes #<issue> and your rewritten text, keeping the AI-assistance paragraph true.
  4. If asked:
    • the ?? [] part can be split out on its own;
    • the remaining window (local write before the counter increments, report §4.6) is offered as a follow-up.

Measured (all commands are in the report)

unfixed fixed
explore subscribe (6 seeded runs per session, 300/600/900 ms) RACE 1/6 in the first 300 ms session; rerun 0/18 (1 of 24 overall) 0/18
explore reserve 0/6, 1/6, 1/6 0/18
explore unsubscribe RACE 4/6, 2/6, 3/6; the browser disagrees with the server in 6/8, 6/8, 7/8 loads (baselines included) RACE 1/6, 0/6, 6/6 on the final page only; data agree 24/24 (§4.6)
explore rename 0/18 not run
explore prefs, prefs-twice "RACE" 6/6 in every session, all false (random Language flags); oracle 0/24 each not run
control, no GenClass (6 loads per surface) reserve 6/6 (messages lost), the other five 0/6 0/6 on all six
plain reproduction, no GenClass (one sync response held, 3 loads per surface) 3/3 on all six surfaces 0/3 on all six
new unit tests (3 runs each way) fail 3/3 pass 3/3
new and extended Playwright checks (3 runs each way) fail 3/3 pass 3/3
ntfy Vitest suite 125 passed, 2 failed (the new ones) 127 passed
ntfy Playwright suite 71 passed 73 passed
lint 8 warnings, all already there the same 8

False reports: explore flagged a RACE in all 36 reordered settings loads, and none of them was real.

Problems with GenClass itself (report §6)

  1. Per-load random page text (ntfy's Language flags) gives a false RACE in every session. data-genclass-ignore doesn't remove page text: the snapshot uses body.innerText (src/agent/index.ts:354).
  2. ~hedge keys for hedges GenClass never sent. schedule.ts:212 names any request whose causal parent has the same signature as a hedge, which shifted keys in one load.
  3. When the fifo baseline is the buggy state, the report lists the correct runs as the race.
  4. There is no way to say "hold this response until the next request of the same signature is answered". That is the overlap a push-triggered fetch needs: 0 of 36 settings loads overlapped.
  5. A bug present in every order (the natural-order message loss) is invisible to explore by design. Worth a line in AGENT.md §8.
  6. Minified React state lines are noise in the internal tier.

There were no tool errors.

Notes for the reviewer

  • This is a docs-only change under docs/adoption/. No runtime, MCP, test, dependency or model-visible change, so the template's checks (typecheck, unit tests, API/CHANGELOG) don't apply and weren't run.
  • Brief corrections:
    • the poll/WebSocket surface was skipped as advised;
    • the "45 s / 15 min sync" is the token-extension worker, not a sync;
    • ntfy's suite has 71 specs, not 56.
  • Not tested: a possible server-side lost update when two concurrent account requests each read-modify-write Prefs. Explore can't reorder the server's processing, so it's noted in the report, not claimed.
  • Branch: the session's designated branch claude/awesome-hypatia-274vxq instead of adopt/ntfy.
  • Time: about 1 h 20 min by the clock.

Generated by Claude Code

Report, harness, results, patch and draft issue/PR text for binwiederhier/ntfy (nothing sent).
Two bugs in AccountApi.sync(), both reproduced without GenClass: a sync applies an account fetched
before a local change and undoes it (a reserved subscribe loses its messages in natural order, 6 of
6 loads on localhost), and an empty subscription list is never applied (unsubscribing from the last
topic leaves it in other browsers, 3 of 3). The patch is against ntfy 8ed8684.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fqwfq2dLpSQotWNHzwrQcF

This branch has not been deployed

No deployments
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.

2 participants