Skip to content

fix(workspace): ignore empty outgoing messages in durable acks - #114

Merged
Programcode merged 2 commits into
mainfrom
fix/workspace-durable-ack
Oct 7, 2026
Merged

Programcode merged 2 commits into
mainfrom
fix/workspace-durable-ack

Conversation

@Programcode

@Programcode Programcode commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

What

  • Fix. Hocuspocus passes empty outgoing messages to onOutgoingMessage. The workspace editor sent each one to durableMutationFromMessage, which tried to decode it and threw Unexpected end of array as an uncaught page error. Empty messages carry no document write, so it now returns null for them (src/lib/workspace/durable-ack.ts).
  • Regression test. src/test/workspace/durable-ack.test.ts has one case: an empty message resolves to null. The file was removed in the test diet (b9ef0b3); this brings back only the case for the fixed bug.
  • New verify recipe. recipes/workspace-autosave.spec.ts proves the autosave ordering fix from Fix section regeneration and workspace autosave ordering #89. It opens Crossfire and Sparring from a workspace, holds one save_workspace_artifact call in flight while typing continues, checks that the page sends no other save meanwhile, releases it, and checks that workspace_artifacts keeps the newest text.
  • Skip without collaboration. Workspaces need the collaboration service, which only verify.sh up --collab starts. up now writes VERIFY_COLLAB into drive.env, and the recipe skips with the reason Workspaces need the collaboration service: run verify.sh up --collab on any other stack, so drive all on a plain up stays green.
  • Skill docs. New features/workspace-autosave.md, an index line in features/README.md, and SKILL.md notes that contrast this recipe (needs --collab) with e2e/workspace-collaboration (starts its own service, must not use --collab).

Workspaces are hidden in production (no VITE_COLLABORATION_URL), so this can't be exercised live.

Evidence

Unit test on current main (f9f3efc), before the guard:

FAIL  src/test/workspace/durable-ack.test.ts > workspace durable acknowledgements > ignores the empty messages the provider reports as outgoing
AssertionError: promise rejected "Error: Unexpected end of array" instead of resolving
Caused by: Error: Unexpected end of array
 ❯ node_modules/lib0/decoding.js:36:41
 ❯ src/lib/workspace/durable-ack.ts:1:1
 Tests  1 failed (1)

With the guard: Tests 1 passed (1).

GitHub Actions is out of minutes: every job stopped after 2 to 4 seconds with no steps or logs. Local npm run verify at abacb96 exited 0: unit tests 274/274, collaboration tests 30/30, Edge Function tests 318/318, the build and the desktop Chromium smoke set 29/29. fd542e8 changes only the recipe and its doc; lint and the docs check pass on it. These are local results, not a CI pass.

Without --collab, the recipe skips all four tests (two recipes on two viewports) with its reason, so drive all stays green (see the PR comment).

Not verified here: the recipe's passing run under verify.sh up --collab. The shared local stack was in use by PR #111, and Adam chose to merge without that run. Codex reviewed two rounds; the round 1 finding was fixed in fd542e8 and round 2 had no findings.

🤖 Generated with Claude Code

Hocuspocus passes empty outgoing messages to onOutgoingMessage. The
workspace editor decoded each one in durableMutationFromMessage, which
threw "Unexpected end of array" as an uncaught page error. Empty
messages carry no document write, so the function now returns null.

Adds the workspace-autosave verify recipe, which holds one
save_workspace_artifact call in flight while typing continues in
Crossfire and Sparring opened from a workspace, and checks that the
page sends no other save meanwhile and that Postgres keeps the newest
text (the ordering fix from #89). Workspaces need the collaboration
service, so `verify.sh up` now records VERIFY_COLLAB in drive.env and
the recipe skips with a reason unless the stack ran `up --collab`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 14:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vercel

vercel Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
debate-navigator Ready Ready Preview Oct 7, 2026 3:03pm UTC
debatelab-staging Ready Ready Preview Oct 7, 2026 3:03pm UTC

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

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).

Next included review available in 54 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Free
  • Run ID: bd0f59df-8cc3-4335-8764-2fe63d82bc9f
📥 Commits

Reviewing files that changed from the base of the PR and between abacb96 and fd542e8.

📒 Files selected for processing (2)
  • .claude/skills/verify-debatelab/features/workspace-autosave.md
  • .claude/skills/verify-debatelab/recipes/workspace-autosave.spec.ts
ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository YAML (base), Organization UI (inherited)
  • Review profile: CHILL
  • Plan: Free
  • Run ID: 7d5c46b2-e7a0-4c60-a6f4-6e84ca0c6399
📥 Commits

Reviewing files that changed from the base of the PR and between f9f3efc and abacb96.

📒 Files selected for processing (7)
  • .claude/skills/verify-debatelab/SKILL.md
  • .claude/skills/verify-debatelab/bin/verify.sh
  • .claude/skills/verify-debatelab/features/README.md
  • .claude/skills/verify-debatelab/features/workspace-autosave.md
  • .claude/skills/verify-debatelab/recipes/workspace-autosave.spec.ts
  • src/lib/workspace/durable-ack.ts
  • src/test/workspace/durable-ack.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Adds collaboration-gated Playwright checks for Crossfire and Sparring workspace autosave. Records collaboration mode for verification recipes and changes durable mutation decoding to return null for empty messages.

Changes

Workspace Autosave

Layer / File(s) Summary
Collaboration-aware recipe setup
.claude/skills/verify-debatelab/bin/verify.sh, .claude/skills/verify-debatelab/SKILL.md, .claude/skills/verify-debatelab/features/README.md
verify.sh writes the collaboration setting to VERIFY_COLLAB. The Drive guidance and feature index list the autosave recipe and its collaboration-mode requirement.
Empty-message handling
src/lib/workspace/durable-ack.ts, src/test/workspace/durable-ack.test.ts
durableMutationFromMessage returns null for empty messages. A test covers an empty Uint8Array.
Crossfire and Sparring autosave checks
.claude/skills/verify-debatelab/recipes/workspace-autosave.spec.ts, .claude/skills/verify-debatelab/features/workspace-autosave.md
The recipe holds an older save, checks that no other save is sent while it is held, then verifies the newest text in the stored artifact. The feature guide documents the scenarios, setup, and collaboration requirement.

Estimated code review effort: 3 (Moderate) | ~20 minutes

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

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

The save queue keeps only the newest pending save, so typing straight
past the held value could merge it away and fail wasHeld() on a
correct app. Type up to the value, wait until it is held, then type
the rest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Programcode

Copy link
Copy Markdown
Owner Author

Codex review round 1 (abacb96): one finding, fixed in fd542e8.

  • Medium, workspace-autosave.spec.ts: the hold matched an exact in-between value ( n / Coding). The save queue keeps only the newest pending save, so typing straight past that value could merge it away, and wasHeld() would fail on a correct app. Fixed: each test now types up to the held value, waits until that save is held, and then types the rest. The feature doc explains why.

CI: none of the GitHub Actions jobs actually ran. Each ended after 2 to 4 seconds with no steps or logs, which means the account is out of Actions minutes. Per AGENTS.md I ran npm run verify locally at abacb96 and it exited 0: unit tests 274/274, collaboration tests 30/30, Edge Function tests 318/318, the build and the desktop Chromium smoke set 29/29. fd542e8 changes only the recipe and its doc; lint and the docs check pass on it. This is a local result, not a CI pass.

@Programcode

Copy link
Copy Markdown
Owner Author

Codex review round 2 (fd542e8): no findings. The round 1 finding is confirmed fixed. Stack runs of the recipe are still pending because another worktree holds the shared local stack.

@Programcode

Copy link
Copy Markdown
Owner Author

Skip without collaboration, proven at fd542e8. I ran the recipe through playwright.verify.config.ts with VERIFY_COLLAB=false. The stack env vars pointed at a closed port, so the shared fixtures counted as ready and nothing could reach another worktree's stack.

  -  1 [desktop-chromium] › recipes/workspace-autosave.spec.ts:77:1 › ws-crossfire-autosave: a slow Crossfire save does not overwrite newer text
  -  2 [desktop-chromium] › recipes/workspace-autosave.spec.ts:103:1 › ws-sparring-autosave: a slow Sparring save does not overwrite a newer draft
  -  3 [mobile-chromium] › recipes/workspace-autosave.spec.ts:77:1 › ws-crossfire-autosave: …
  -  4 [mobile-chromium] › recipes/workspace-autosave.spec.ts:103:1 › ws-sparring-autosave: …
  4 skipped

In report.json, every test has the annotation skip: "Workspaces need the collaboration service: run verify.sh up --collab" (recipe line 9). A skip produces no failure, so drive all on a plain up stays green.

Still pending: the up --collab pass on desktop and mobile. The shared local stack is held by PR #111's agentic suite run, which has about 40 minutes left.

@Programcode
Programcode merged commit cbd5e39 into main Oct 7, 2026
8 of 15 checks passed
@Programcode
Programcode deleted the fix/workspace-durable-ack branch October 7, 2026 15:46

This branch was successfully deployed

2 active deployments
Preview – debate-navigator — fd542e80 Deployed Oct 7, 2026 by vercel[bot]
Preview – debatelab-staging — fd542e80 Deployed Oct 7, 2026 by vercel[bot]
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