Skip to content

Conversation

@FUDCo
Copy link
Contributor

@FUDCo FUDCo commented Feb 5, 2026

Summary

  • Implements receive-side deduplication and transactional message processing (Issue Fill receive-side message handling gaps in Ken support #808)
  • Changes the handleRemoteMessage "no response" convention from empty string to null
  • Updates the Ken protocol assessment document to reflect completed implementation

With issue #786 (crank buffering) already merged, this PR completes our Ken protocol implementation. All Ken protocol properties are now achieved:

Ken Property Status
Transactional turns
Output validity
Deferred transmission
Atomic checkpoint
Consistent frontier
Local recovery
Sender-based logging
Exactly-once delivery
FIFO ordering

Changes

Receive-side deduplication and transactional processing

RemoteHandle.handleRemoteMessage() now:

  1. Checks seq <= highestReceivedSeq to skip duplicate messages
  2. Wraps message processing in a database savepoint
  3. Persists highestReceivedSeq at the end, inside the transaction
  4. Rolls back both state and in-memory seq tracking on error

Return type convention change

Changed the "no response needed" return value from empty string ('') to null across the handleRemoteMessage pathway (10 files).

Documentation

Updated docs/ken-protocol-assessment.md to reflect that all Ken protocol properties are now implemented.

Test plan

  • All unit tests pass (1779 in ocap-kernel, 203 in kernel-browser-runtime, 44 in nodejs)
  • Build succeeds
  • CI passes

🤖 Generated with Claude Code


Note

Medium Risk
Touches core remote messaging delivery/ACK sequencing and RPC return-type conventions; regressions could cause dropped messages, duplicate processing, or broken RPC interop despite added tests.

Overview
Completes receive-side Ken semantics by adding duplicate detection (seq <= highestReceivedSeq) and wrapping inbound RemoteHandle.handleRemoteMessage() processing in a database savepoint, persisting highestReceivedSeq only on commit and deferring redeemURL/redeemURLReply side effects until after commit.

Changes the remote-message RPC contract to return string | null (rather than empty string for “no response”) across browser runtime, Node platform services, RemoteManager, and RPC remoteDeliver validation, and updates/extends tests accordingly. Documentation in docs/ken-protocol-assessment.md is revised to mark all Ken protocol properties as implemented.

Written by Cursor Bugbot for commit 210ff11. This will update automatically on new commits. Configure here.

FUDCo and others added 4 commits February 5, 2026 13:42
Identified bugs in handleRemoteMessage: no dedup check and wrong
persistence order. Recommended fix: wrap in database transaction.

Refs #808

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements issue #808: wrap handleRemoteMessage in a database transaction
and add duplicate detection to ensure exactly-once delivery semantics.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…pty string to null

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@FUDCo FUDCo changed the title feat: Complete Ken protocol implementation (Issues #786, #808) feat: Complete Ken protocol implementation Feb 5, 2026
@FUDCo FUDCo changed the title feat: Complete Ken protocol implementation Complete Ken protocol implementation Feb 5, 2026
@FUDCo FUDCo marked this pull request as ready for review February 5, 2026 21:47
@FUDCo FUDCo requested a review from a team as a code owner February 5, 2026 21:47
@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 78.18%
⬆️ +0.04%
6110 / 7815
🔵 Statements 78.14%
⬆️ +0.04%
6208 / 7944
🔵 Functions 76.62%
⬆️ +0.05%
1564 / 2041
🔵 Branches 78.38%
🟰 ±0%
2237 / 2854
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/kernel-browser-runtime/src/PlatformServicesClient.ts 96.66%
🟰 ±0%
81.48%
🟰 ±0%
89.47%
🟰 ±0%
96.66%
🟰 ±0%
106, 128
packages/kernel-browser-runtime/src/PlatformServicesServer.ts 95.23%
🟰 ±0%
88.88%
🟰 ±0%
80.95%
🟰 ±0%
95.23%
🟰 ±0%
140, 163, 194, 407
packages/nodejs/src/kernel/PlatformServices.ts 93.97%
🟰 ±0%
90.47%
🟰 ±0%
88.23%
🟰 ±0%
93.97%
🟰 ±0%
143-146, 184, 214-219
packages/ocap-kernel/src/remotes/types.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/remotes/kernel/RemoteHandle.ts 84.9%
⬆️ +0.48%
81%
⬇️ -0.70%
85.1%
⬆️ +0.66%
85.55%
⬆️ +0.43%
338, 357-418, 453, 496, 506-508, 549-562, 891, 958, 1004
packages/ocap-kernel/src/remotes/kernel/RemoteManager.ts 98.3%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
98.3%
🟰 ±0%
133
packages/ocap-kernel/src/rpc/kernel-remote/remoteDeliver.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/ocap-kernel/src/store/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
Generated in workflow #3592 for commit 210ff11 by the Vitest Coverage Report Action

- Move #highestReceivedSeq update after savepoint release to prevent
  ACKs for uncommitted message receipts
- Add validation for seq field to prevent state corruption from
  malformed messages
- Update tests to reflect that replies during transaction don't
  piggyback ACKs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a reply is sent during message processing (e.g., redeemURLReply),
#sendRemoteCommand clears the delayed ACK timer. Since the reply can't
piggyback the ACK (transaction hasn't committed), we must restart the
timer after commit to ensure ACK is eventually sent.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Split #handleRedeemURLReply into #prepareRedeemURLReply (validates and
translates inside transaction) and #completeRedeemURLReply (modifies
in-memory state after commit). This prevents promise resolution and
pendingRedemptions deletion from escaping a rolled-back transaction.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
FUDCo and others added 2 commits February 5, 2026 17:04
The kernel-remote.ts file contained a stale duplicate of remoteDeliverSpec
that didn't accept null results. Since index.ts imports from remoteDeliver.ts
(which has the correct spec), kernel-remote.ts and its test were dead code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Spread ...remoteDeliverSpec instead of duplicating method, params, and
result fields. This ensures the handler stays in sync with the spec.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move #sendRemoteCommand call for redeemURL replies to after the
savepoint commits. This prevents in-memory state (#nextSendSeq,
#startSeq, timers) from diverging from the database if the transaction
rolls back.

Also refactor redeemURL and redeemURLReply handling into parallel
prepare/complete phases for consistency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Post-commit operations (deferred completions, in-memory state updates)
now execute outside the try-catch block. This prevents attempting to
rollback an already-released savepoint if a completion operation fails.

Also adds exemptFromCapacityLimit parameter to #sendRemoteCommand so
redeemURLReply can bypass capacity checks - it's a kernel-initiated
reply that must be sent to avoid leaving the remote hanging.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

@sirtimid sirtimid left a comment

Choose a reason for hiding this comment

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

LGTM!

@FUDCo FUDCo added this pull request to the merge queue Feb 6, 2026
Merged via the queue into main with commit c7820f0 Feb 6, 2026
32 checks passed
@FUDCo FUDCo deleted the chip/finish-ken branch February 6, 2026 18:44
sirtimid added a commit that referenced this pull request Feb 9, 2026
Move the #remoteGcRequested in-memory state change after the savepoint
commit, consistent with the transactional message processing pattern
from #811. Also consolidate test assertions to use toStrictEqual on
parsed objects per project convention, and fix return value expectation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
github-merge-queue bot pushed a commit that referenced this pull request Feb 9, 2026
…814)

## Summary

Implements the DGC (Distributed Garbage Collection) protocol for remote
kernel communication (Issue #779).

- `deliverBringOutYourDead()` on `RemoteHandle` now sends a
`['bringOutYourDead']` wire message to the remote kernel instead of
being a no-op
- The remote kernel schedules a local reap, runs GC, and sends back
drops/retires
- A ping-pong prevention flag (`#remoteGcRequested`) prevents infinite
BOYD loops between kernels

## Changes

**GC store widening (`gc.ts`, `garbage-collection.ts`):**
- Widen `scheduleReap` to accept `EndpointId` (union of `VatId |
RemoteId`) instead of just `VatId`
- Update `addGCActions` and `processGCActionSet` to use
`insistEndpointId` instead of `insistVatId`
- Rename internal variables from `vatId`/`actionsByVat` to
`endpointId`/`actionsByEndpoint` for clarity

**BOYD protocol (`RemoteHandle.ts`):**
- Add `BringOutYourDeadDelivery` to the `DeliveryParams` union type
- Implement `deliverBringOutYourDead()` to send BOYD over the wire via
`#sendRemoteCommand`
- Add `'bringOutYourDead'` case to `#handleRemoteDeliver` that calls
`scheduleReap`
- Add `#remoteGcRequested` flag: set after the savepoint commit
(consistent with the transactional message processing pattern from
#811), when BOYD was triggered by an incoming remote request the
subsequent local BOYD is suppressed

**Tests:**
- Unit tests for GC with remote endpoints and reap scheduling
- Unit tests for BOYD send/receive, ping-pong prevention, seq/ack
tracking, and persistence
- E2E tests for distributed GC across two kernels via libp2p

## Test plan

- [x] All ocap-kernel unit tests pass (1800+)
- [x] All nodejs e2e tests pass (35)
- [x] All extension e2e tests pass (19)
- [x] CI passes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds a new cross-kernel `bringOutYourDead` control message and widens
GC scheduling from vats to all endpoints, which can affect remote
message flow and garbage-collection behavior if mis-triggered, but
changes are mostly additive and well-covered by new unit/e2e tests.
> 
> **Overview**
> Implements **distributed garbage collection** across kernels by
turning `RemoteHandle.deliverBringOutYourDead()` into a real wire-level
`deliver` message (`['bringOutYourDead']`) that causes the receiving
kernel to `scheduleReap` its remote endpoint and run GC, with a
`#remoteGcRequested` flag to prevent infinite BOYD ping-pong and to
reset on peer restart.
> 
> Widens GC plumbing from vat-only to **endpoint-wide** operation by
treating GC actions and reap scheduling as `EndpointId` (vat or remote)
rather than `VatId`, and adds `Kernel.reapRemotes()` /
`RemoteManager.reapRemotes()` debugging/test hooks to trigger remote
reaping.
> 
> Adds extensive coverage: new RemoteHandle unit tests for BOYD
send/receive, seq/ack/persistence, ping-pong prevention, RemoteManager
tests for reap scheduling, GC store tests for remote endpoint IDs, and
nodejs e2e scenarios validating BOYD exchange and continued
bidirectional messaging after DGC.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ae4b9cc. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 <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.

2 participants