Skip to content

Typing into your own idle chat reopens it instead of saying it's available - #2469

Draft
santoshkumarradha wants to merge 3 commits into
app/v3from
c27/idle-send-conflict
Draft

santoshkumarradha wants to merge 3 commits into
app/v3from
c27/idle-send-conflict

Conversation

@santoshkumarradha

Copy link
Copy Markdown
Member

Draft: this changes chat ownership, so it needs the owner's yes before merging.

What the user saw. A chat on this computer goes idle in the background and releases its hold cleanly. When you type into it again, you sometimes get "This chat is available to continue here." instead of the chat reopening. No other computer had taken it, and this computer was still the holder.

Cause. When an idle chat closed, the drive released its hold before stopping its own ownership watcher. The watcher could then read that release and treat it as losing ownership. It wrote a bare "available" location, with no holder, into the app. When that landed after the correct "here" location, Send's refusal check returned it before the reopen path ran. This came in with 8cca2fe, which reached app/v3 in #2009 together with the ownership follower from #1990.

Fix. The ownership watcher gets its own context and done channel, derived from the drive's run context, so an outer cancel still stops it. Drive.Close now:

  1. stops and joins only the watcher;
  2. runs the existing Batcher.Close, which still joins the final publish before cancelling its request;
  3. continues with the rest of the original order, unchanged.

The watcher needs its own lifetime because stopping it together with the upload interrupted the final publish and made the existing closing-upload guard panic (TestL4FixDriveCloseJoinsUpload).

No refusal rules change. A real takeover from another computer still shows "available" or "held elsewhere". A failed take still leaves the chat free. No new locks were needed: everything the watcher touches is already synchronized through the drive's and the batcher's existing locks, and the audit is in the review notes.

Validation.

  • Red on base: TestDriveOwnReleaseDoesNotBecomeViewer holds the watcher's lease check until the correct location has landed, then lets the stale write land last. It fails 20/20 on base and passes with the fix.
  • New test: TestDriveRunCancelStopsOwnershipWatcher checks that an outer cancel still stops the watcher.
  • Guards, 20/20 on base and with the fix: TestL4FixDriveCloseJoinsUpload, TestDriveSideSupersededStopsTools, TestReleasedFailedTakeKeepsSourceClosedAndAvailable and TestAppTakeInstallFailureS5.
  • App level: TestAppIdleReleaseI1I2BackgroundChatStaysReleasedUntilSend at -count=500 -cpu=4 gives 0 refused sends both with and without -race. Base gives 1/500 without -race.
  • Neighbours at -count=20:
    • All 40 drive, lease, ownership and release tests in internal/syncsetup pass. The hosted-proof test is skipped because it needs a hosted runner.
    • All TestAppTake* tests and the idle-release tests pass, except idle row-count failures that reproduce identically on base and are tracked separately.

🤖 Generated with Claude Code

santoshkumarradha and others added 3 commits November 6, 2026 11:02
Give the ownership watcher a child context and a separate join so its own
lease release cannot announce a viewer location after idle closure. Keep
final publication on the existing run context until Batcher.Close joins it.
Cancelling that shared context early breaks the closing-upload guard.

Reuse the deterministic release regression and add run-cancellation coverage.
Keep takeover, failed-take recovery and work refusal semantics unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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