fix: session isolation + await cursor + cleanup#1
Open
marksverdhei wants to merge 13 commits intomainfrom
Open
fix: session isolation + await cursor + cleanup#1marksverdhei wants to merge 13 commits intomainfrom
marksverdhei wants to merge 13 commits intomainfrom
Conversation
Add global rooms (-g flag, ~/.chatfiles/), delete-room command, auto-resolution of .Chatfile extension, and install.sh reference. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5 confirmed bugs: 1. register crashes on first name collision (set -e + ((attempts++))) 2. await returns join/leave messages instead of waiting for new ones 3. await returns already-seen messages (no read cursor) 4. Newline injection in send breaks one-message-one-line invariant 5. Uniqueness check ignores join/leave format names Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. register crash on name collision: ((attempts++)) fails with set -e when attempts=0. Fixed with || true and added exhaustion error exit. 2. await returns join/leave lines: cut -d: misparses non-message format. Replaced with line cursor tracking that skips [...] lines. 3. await returns stale messages: no read cursor meant already-seen messages returned immediately. Added LASTLINE tracking to session. 4. newline injection in send: embedded newlines broke one-line invariant. Strip newlines from messages before appending. 5. uniqueness check blind to join format: grep only matched "name:" but not "[name joined]". Extended pattern to match both formats. Also fixed set -e interaction with LASTLINE default assignment ([ -z "$LASTLINE" ] && LASTLINE=0 fails when LASTLINE is "0"). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug reproduction tests should demonstrate the underlying vulnerability, not test the fix. The test proves grep "^name:" is blind to join format, which documents why the fix was needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes tail -f orphan leak and await not returning messages: - Use exec fd < <(tail -f) pattern instead of pipe subshell - tail PID captured via $! for proper cleanup on exit - send-await starts tail -f before sending to prevent race condition - Reverted test_bugs.sh bug5 to original form (tests the concept) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Since state was previously stored in a single '.cf_session' file, multiple agents running in the same directory (like in a shared tmux session) would overwrite each other's session file and end up with overlapping identities. This replaces the hardcoded '.cf_session' with a dynamic TTY-based filename (e.g., '.cf_session.pts_8') which properly isolates the session state down to the individual terminal pane or agent process. The implementation cleanly falls back to Session ID or PID if no TTY is available. A 'CF_SESSION_FILE' override was also added to 'cf' to ensure the test suite remains deterministic in its isolated temp directories.
- Fixed Bug 6 (Data Loss in await): When unread messages were processed, await was incorrectly setting LASTLINE to TOTAL instead of the line number of the specific message it just read, causing it to skip all subsequent unread messages on the next call. It now accurately tracks the exact line. - Expanded the bug reproduction test suite to include the 3 newly discovered bugs (await skipping messages, tail -f orphans, state isolation overlap) as regression tests to ensure they remain fixed in the future. - Restored Bug 5 test so it acts as a passing regression test rather than a hardcoded failure.
get_session_id() was using the script's own SID, which changes every invocation when there's no controlling terminal (agents, subshells). Use PPID instead — stable across all commands from the same parent shell. Also removes scratch files (sketch.py, PROMPT.md) from the branch. Closes #2 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Using wc -l to update the cursor during simultaneous sends caused messages to be permanently skipped. Replaced the unread loop and tail -f with a single tail -n +K -f stream for thread-safe consumption.
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 free
to 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.
Summary
get_session_id()now usesPPID(parent shell PID) instead of own SID when no TTY is available — session state persists acrosscfsubcommands in non-TTY contexts (agents, subshells,bash -c)awaitdoesn't return stale/already-seen messagessendto preserve one-message-one-line invariant[name joined]format((attempts++))crash underset -eon first collisionawait/send-awaitto prevent orphanedtail -fprocessesdelete-roomcommand, global room support (-g), auto-resolve.Chatfileextensiontest_bugs.shregression tests (8 bug scenarios, all pass)sketch.py,PROMPT.md)Test plan
test_cf.sh— 32/32 passtest_bugs.sh— 0/8 bugs reproduced (all fixed)🤖 Generated with Claude Code