Skip to content

Publish slash-command todo updates to observers (Fixes #3052) - #3101

Merged
acoliver merged 4 commits into
mainfrom
issue3052
Aug 6, 2026
Merged

Publish slash-command todo updates to observers (Fixes #3052)#3101
acoliver merged 4 commits into
mainfrom
issue3052

Conversation

@acoliver

@acoliver acoliver commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

TLDR

Publish every provider-originated todo mutation on the canonical todo event channel so JSP/jefe, Zed, and peer providers stop retaining stale lists after slash-command edits such as clear.

The originating provider skips only its exact publication object, preventing self-reentry without hiding matching peer or synchronously nested external events.

Dive Deeper

The TodoWrite tool already persisted and emitted TodoUpdateEvent, but TodoProvider.updateTodos only updated React state and started disk persistence. Every slash-command mutation funnels through that provider method, so the UI and TodoRead were correct while external observers retained the last tool-written list indefinitely.

This change keeps updateTodos synchronous and optimistic:

  1. Apply local provider state.
  2. Start the existing fire-and-forget persistence.
  3. Emit one canonical TodoUpdateEvent carrying the provider session, agent scope, complete replacement list, and timestamp.

A per-provider ref records the exact event object during synchronous emission. The origin listener skips only that object; external observers, matching peer providers, later external events, and synchronously nested external events remain authoritative. The ref is cleared in finally so a throwing listener cannot leave suppression armed.

Mount/session refresh reads deliberately do not publish. TodoStore.readTodos maps parse and I/O failures to an empty list, so the refresh path cannot distinguish an authoritative empty list from a failed read.

The Bun-native behavioral suite renders the real TodoProvider, drives real slash-command operations, and observes through createTodoObservationSubscription. It covers clear, every mutation family, empty replacements, session/agent identity, auto-clear, external-event filtering, peer-provider delivery, exact origin suppression, and nested synchronous events.

Open Code Review found one medium test-isolation issue: the future-dated archive used by the load test was not removed. The test now registers cleanup for it.

Reviewer Test Plan

  1. Run the focused behavioral suite:

    bun scripts/run_bun_tests.ts todoProvider.observation.bun.tsx
    
  2. Confirm all 25 tests pass.

  3. In an observed CLI session, create todos via TodoWrite, run /todo clear, and confirm the JSP consumer receives an empty todos.replaced transition.

  4. Exercise /todo add, set, unset, remove, undo, and load and confirm each mutation emits one complete replacement.

  5. Confirm a matching peer TodoProvider receives the update while the originating provider does not re-enter its own listener.

Full local verification performed on macOS:

  • npm run test: aggregate exposed four agents files failing only under the concurrent workspace run; all four pass individually with their configured Bun timeout. The issue-focused suite and all unrelated workspaces completed successfully.
  • npm run lint: pass
  • npm run typecheck: pass
  • npm run format: pass
  • npm run build: pass
  • stepfun-37 smoke test: pass

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

Fixes #3052

Summary by CodeRabbit

  • Bug Fixes

    • Improved todo update event handling across multiple providers.
    • Prevented originating providers from processing their own update events while preserving delivery to external observers and peer providers.
    • Ensured todo loading remains read-only and does not emit unnecessary refresh events.
  • Tests

    • Added comprehensive integration coverage for todo persistence, event delivery, filtering, scoping, auto-clear behavior, and duplicate publication prevention.
    • Added the TodoProvider observation tests to the CLI test workspace.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 10 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4db6a961-3123-4d57-9780-67e906b07e58

📥 Commits

Reviewing files that changed from the base of the PR and between ea57bfb and 546a5a9.

⛔ Files ignored due to path filters (1)
  • project-plans/issue3052/plan.md is excluded by !project-plans/**
📒 Files selected for processing (2)
  • packages/cli/src/ui/contexts/TodoProvider.tsx
  • packages/cli/src/ui/contexts/__tests__/todoProvider.observation.bun.tsx
📝 Walkthrough

Walkthrough

TodoProvider now publishes canonical events for local todo mutations, persists changes asynchronously, and suppresses only exact origin echoes. Bun integration tests cover mutation, scoping, delivery, and registration behavior.

Changes

Todo observation flow

Layer / File(s) Summary
Provider mutation publication
packages/cli/src/ui/contexts/TodoProvider.tsx
TodoProvider publishes synchronous mutation events, tracks event origin per provider, persists asynchronously, and ignores only its exact origin event.
Observation integration coverage
packages/cli/src/ui/contexts/__tests__/todoProvider.observation.bun.tsx, scripts/bun-test-manifest.ts
Bun tests cover todo mutations, event payloads, scoping, state replacement, peer delivery, origin suppression, nested events, and the registered isolated test workspace.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: publishing slash-command todo updates to observers, with the linked issue reference.
Description check ✅ Passed The description covers the change, design details, reviewer test plan, testing results, matrix, and linked issue.
Linked Issues check ✅ Passed The changes address issue #3052 through shared updateTodos publication, mutation coverage, agent scoping, and origin-event suppression.
Out of Scope Changes check ✅ Passed The implementation, behavioral tests, and Bun test manifest entry directly support the linked issue objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue3052

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the maintainer:e2e:ok Trusted contributor; maintainer-approved E2E run label Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR changes 4 file(s).

  • packages/cli/src/ui/contexts/TodoProvider.tsx: (per-file summary unavailable)
  • packages/cli/src/ui/contexts/__tests__/todoProvider.observation.bun.tsx: (per-file summary unavailable)
  • scripts/bun-test-manifest.ts: (per-file summary unavailable)
  • project-plans/issue3052/plan.md: (per-file summary unavailable)

Changes

Layer File(s) Summary
packages/cli/src/ui/contexts packages/cli/src/ui/contexts/TodoProvider.tsx Changes in packages/cli/src/ui/contexts
packages/cli/src/ui/contexts/tests packages/cli/src/ui/contexts/tests/todoProvider.observation.bun.tsx Changes in packages/cli/src/ui/contexts/tests
scripts scripts/bun-test-manifest.ts Changes in scripts
project-plans/issue3052 project-plans/issue3052/plan.md Changes in project-plans/issue3052

Magnitude

🎯 1 (S)
1207 additions, 20 deletions, 4 changed files across 1 package, 0 acceptance criteria

Related

No related items found.


Walkthrough generated by LLxprt PR Review. Planner issue: #2256

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

OpenCodeReview — automatic reviews suspended

Automatic OCR reviews are suspended for this PR after 2 of 2 automatic reviews.

To get more reviews you can:

  • Check the box below to re-enable automatic reviews (resets the counter), or

  • Comment /review, /ocr, or /open-code-review to request a single review on demand.

  • Re-enable automatic reviews

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/ui/contexts/TodoProvider.tsx`:
- Around line 52-56: Update the event publication logic around
originPublicationRef and emitTodoUpdated to save the current marker before
assigning eventData, then restore that saved value in finally instead of
clearing the ref unconditionally. Add a regression test with a prepended
listener that synchronously calls the originating provider’s updateTodos,
asserting the nested list remains the final persisted state.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fa7cfb8a-d7d5-4f90-9d8b-6f55cca4dca5

📥 Commits

Reviewing files that changed from the base of the PR and between 42ca2a9 and ea57bfb.

⛔ Files ignored due to path filters (1)
  • project-plans/issue3052/plan.md is excluded by !project-plans/**
📒 Files selected for processing (3)
  • packages/cli/src/ui/contexts/TodoProvider.tsx
  • packages/cli/src/ui/contexts/__tests__/todoProvider.observation.bun.tsx
  • scripts/bun-test-manifest.ts

Comment thread packages/cli/src/ui/contexts/TodoProvider.tsx Outdated
@acoliver

acoliver commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up on the nested-publication finding: CI proved the marker-stack fix preserved React state but the outer and nested fire-and-forget TodoStore writes could still finish out of order. Commit 546a5a9 now serializes persistence per provider while keeping updateTodos synchronous and starting the first write before publication. The deterministic regression holds the outer real write, proves the nested write is queued, releases the outer write, and verifies the nested list is final on disk. The focused Bun suite passes 26/26 repeatedly; lint, typecheck, format, build, and the stepfun-37 smoke test pass.

@acoliver
acoliver merged commit dbe864d into main Aug 6, 2026
60 of 62 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer:e2e:ok Trusted contributor; maintainer-approved E2E run

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slash-command todo edits are never published to observers, so JSP consumers keep a cleared list forever

1 participant