Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix: daemon bugs — flush race, readline leak, timeline lock, client retry, file-request scope#117

Open
gusye1234 wants to merge 1 commit into
main from
fix/cli-daemon-bugs
Open

fix: daemon bugs — flush race, readline leak, timeline lock, client retry, file-request scope #117
gusye1234 wants to merge 1 commit into
main from
fix/cli-daemon-bugs

Conversation

@gusye1234

@gusye1234 gusye1234 commented May 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Test plan

  • All 662 CLI tests pass
  • All 241 shared tests pass
  • Lint passes (warnings only, pre-existing)
  • Manual test: verify daemon handles concurrent message flush without loss
  • Manual test: verify timeline entries are updated when lock contention occurs

Closes #107, #108, #109, #110, #115

...e lock, client retry)
1. session-runner: Add isFlushing guard to prevent concurrent
 flushMessages calls from racing and dropping messages (#108)
2. agent backends (claude, codex, opencode): Add rl.close() in
 process close handlers to prevent readline memory leaks (#109)
3. timeline: Add retry loop (2 retries with spin-wait) in
 updateEntry when lock acquisition fails, reducing silent
 update drops (#110)
4. client: Initialize lastError with a meaningful Error instead
 of undefined, preventing throw-undefined edge case (#115)
5. workspace-file-request: Add optional workspaceId parameter to
 getRequest for defense-in-depth scoping (#107)
Closes #107, #108, #109, #110, #115 
@gusye1234 gusye1234 requested a review from a team as a code owner May 25, 2026 04:39

@gusye1234 gusye1234 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Code Review — PR #117: fix: daemon bugs — flush race, readline leak, timeline lock, client retry, file-request scope

What it does

Fixes five independent daemon bugs:

  1. Readline leak — closes readline interfaces on process exit across all agent backends
  2. Flush race — adds an isFlushing guard to prevent concurrent message batch flushes
  3. Timeline lock — retries lock acquisition with short spin-waits before giving up
  4. Client retry — initializes lastError with a descriptive Error so the throw path always has a meaningful message
  5. File-request scope — scopes getRequest lookup by workspaceId so one workspace can't access another's file requests

Code Quality Checklist

Functionality

  • Code does what it's supposed to do
  • Edge cases handled
  • Error handling appropriate
  • No logic errors

Code Quality

  • Readable and well-structured
  • Functions are small and focused
  • No code duplication
  • Follows project conventions

Code Simplification

  • Changes are minimal and targeted
  • One concern: The spin-wait in timeline.ts (lines 157-161) uses a busy loop (while (Date.now() - start < 50 * (retry + 1)) {}) which blocks the Node.js event loop. Since this appears to be in a synchronous file-lock context, it's likely acceptable for 50-100ms, but worth noting. If this ever becomes a hot path, consider Atomics.wait or restructuring to async.

Security

  • No security vulnerabilities
  • Good catch: The workspaceId scoping on file requests closes a potential cross-workspace data access bug
  • No hardcoded secrets

Tests Coverage

  • No new tests added for these fixes. The flush race guard, timeline retry, and workspace-scoped query would benefit from unit tests, especially:
    • Concurrent flush prevention
    • Lock retry behavior (acquired on 2nd/3rd try vs. still failing)
    • getRequest with/without workspaceId

Project Syncing

  • All three agent backends (claude, codex, opencode) updated consistently for rl.close()
  • Both retry paths in client.ts updated

Observations

  1. Flush race — lost messages on failure: When reportMessages throws, the spliced batch is silently lost (only logged at debug level). The previous code had the same issue, so this PR doesn't regress it — but it's worth considering a re-queue or at least a warning-level log for dropped messages.

  2. Spin-wait justification: The spin-wait is a pragmatic choice for a sync file-lock path, but 50-100ms of event-loop blocking could stall other timers. Since this only triggers under contention (lock already held), it's probably fine in practice.

  3. and(...conditions) — when workspaceId is undefined, conditions has only one element. Verify that and() with a single argument works correctly in your Drizzle version (it should, but worth a quick check).

Verdict

Solid set of targeted bug fixes. All changes are low-risk and improve correctness. Would be stronger with unit tests for the new behaviors, but the fixes themselves are clean and well-scoped. Looks ready to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Security: Missing workspace scoping in getRequest (workspace-file-request)

1 participant

AltStyle によって変換されたページ (->オリジナル) /