Convert the following plan into an executable plan, using the subagents available to you to perform research, execution, coding, and verification at each step.
At the end of each step the current progress should be used to evaluate the following steps of the plan, before continuing on with the determined next steps.
Execution Plan
- Define RPC durability contract (no storage changes yet)
- Work: Extend packages/opencode/src/share/rpc-contract.ts and packages/cloudsession/src/rpc-contract.ts with durable op envelope types: op_id, batch_id, seq, depends_on, expected_cursor, capability_epoch, plus ack type (cursor, applied, duplicates, rejected).
- Work: Add new RPC methods to ShareRpc: redeemShare(...), appendOps(...), revokeCapability(...) (prototype can keep revoke as epoch bump).
- Validation target: bun --cwd packages/cloudsession tsc --noEmit and bun --cwd packages/opencode run typecheck both pass.
- Exit criteria: both packages compile with shared contract and no behavior changes yet.
- Add cloudsession state model for durable replay
- Work: Extend packages/cloudsession/src/types.ts metadata with prototype RPC state: cursor, capabilityEpoch, and a bounded dedupe ledger (applied_recent ring/list of op IDs).
- Work: Keep compatibility for existing REST APIs (/api/share*) by defaulting missing fields during read.
- Validation target: existing tests remain green: bun --cwd packages/cloudsession test --preload ./src/preload.ts src/api.test.ts src/index.test.ts.
- Exit criteria: no regression in current REST behavior.
- Implement redeemShare and capability epoch checks in RPC server
- Work: Implement in packages/cloudsession/src/rpc.ts:
- redeemShare(shareID, secret) -> returns cursor, capabilityEpoch, and basic share metadata.
- Reject calls with stale capability_epoch.
- Work: Keep createShare and syncShare unchanged.
- Validation target: new test file packages/cloudsession/src/rpc.persistence.test.ts:
- redeem returns stable cursor for same share;
- stale epoch rejected.
- Exit criteria: redemption + epoch auth semantics proven.
- Implement idempotent appendOps with cursor advancement
- Work: Add appendOps(shareID, secret, capabilityEpoch, ops) in packages/cloudsession/src/rpc.ts.
- Work: Per op:
- if op_id already seen -> mark duplicate;
- if dependency missing (depends_on) -> reject op;
- else apply mutation and advance cursor.
- Work: Return ack payload with cursor/applied/duplicates/rejected.
- Validation target: rpc.persistence.test.ts cases:
- replay same batch does not double-apply;
- dependency order enforced;
- mixed applied+duplicate+rejected ack shape stable.
- Exit criteria: exactly-once effect via idempotent apply is demonstrated.
- Add opencode durable outbox schema + migration
- Work: Extend packages/opencode/src/share/share.sql.ts with:
- outbox table (pending ops, retry metadata),
- per-session sync state table (cursor, capability_epoch, last acked batch).
- Work: Export in packages/opencode/src/storage/schema.ts.
- Work: Generate migration from packages/opencode: bun run db generate --name share_outbox_prototype.
- Validation target: migration compiles and DB opens in tests; bun --cwd packages/opencode test test/storage/json-migration.test.ts.
- Exit criteria: schema exists and migrates without breaking existing storage migration tests.
- Implement outbox repository API (opencode)
- Work: Add persistence helpers in packages/opencode/src/share/share-next.ts (or a new helper module under same folder) to enqueue, reserve, ack, retry, and recover pending ops.
- Work: Keep deterministic batch_id + seq so replay preserves original pipeline order.
- Validation target: new tests packages/opencode/test/share/share-outbox.test.ts:
- enqueue creates durable rows;
- reserve/ack transitions;
- failed send increments attempts and schedules retry.
- Exit criteria: durable queue semantics are validated independently from transport.
- Wire ShareNext to outbox + RPC replay loop
- Work: Replace in-memory queue path in packages/opencode/src/share/share-next.ts with:
- bus events -> enqueue ops;
- flusher -> redeemShare then appendOps;
- ack handling -> mark rows acked and update cursor.
- Work: Keep HTTP fallback path unchanged for safety.
- Validation target: packages/opencode/test/share/share-replay.test.ts:
- simulated transport failure leaves pending ops;
- next flush replays same batch and drains queue;
- restart/re-init resumes pending ops.
- Exit criteria: reconnect + replay behavior proven in client package.
- Failure-injection tests for “lost response, successful apply”
- Work: Add cloudsession mock behavior in tests to simulate: server applies batch but client does not receive response.
- Work: Client retries same batch; server returns duplicate ack; state unchanged.
- Validation target:
- cloudsession: duplicate ack correctness test;
- opencode: retry after ambiguous failure produces one final state.
- Exit criteria: strongest persistence claim (idempotent replay under ambiguous delivery) proven.
- Capability-security prototype tests (sturdy-ref semantics)
- Work: Add tests for capability patterns using share secret + epoch:
- revoked/epoch-bumped token fails;
- redeemed current token succeeds;
- optional scope test (if implemented) read-only cannot append.
- Validation target: packages/cloudsession/src/rpc.capability.test.ts.
- Exit criteria: capability revocation and redemption semantics are demonstrably enforceable.
- Regression + package-level verification
- Work: Run full cloudsession tests and targeted opencode tests.
- Validation target:
- bun --cwd packages/cloudsession test --preload ./src/preload.ts src/**/*.test.ts
- bun --cwd packages/cloudsession tsc --noEmit
- bun --cwd packages/opencode test --preload ./test/preload.ts test/share/*.test.ts
- bun --cwd packages/opencode run typecheck
- Exit criteria: prototype features pass and no existing core regressions.
Feature-to-Test Mapping (What this proves) - Reconnection redemption -> redeemShare cursor continuity tests.
- Replay in original batch/pipeline order -> deterministic batch_id/seq replay tests.
- “Dropped response” safety -> duplicate apply prevention tests.
- Capability/sturdy-ref behavior -> epoch/revocation redemption tests.
- Slip prevention under retries -> outbox + idempotent server apply tests.
Orchestrator Dependency Graph - Parallel start: Step 1 (contracts) and test scaffolding.
- Then: Steps 2-4 (cloudsession RPC durability core).
- In parallel after Step 1: Step 5 (opencode schema/migration).
- Then: Steps 6-7 (outbox + wiring) depend on Steps 4 and 5.
- Final: Steps 8-10 as integration and hardening gates.
Recommended default choices for prototype - Dedupe ledger: bounded recent-op window (fast to ship), not infinite history.
- Cursor policy: monotonic per-share cursor advanced on applied ops only.
- Replay unit: persisted op-intents, not persisted JS RpcPromise state.
One design choice to confirm before implementation: do you want prototype dedupe to be bounded window (faster) or full permanent op-id log (stronger, more storage)? I recommend bounded window for v1; full log changes storage growth and compaction strategy.