Skip to content

Make ask_user question cards idempotent on retry (CL-7248) - #621

Merged
TheGreatAxios merged 3 commits into
mainfrom
cl-7248-ask_user-a-crash-between-postquestion-and-suspendongates
Sep 4, 2026
Merged

TheGreatAxios merged 3 commits into
mainfrom
cl-7248-ask_user-a-crash-between-postquestion-and-suspendongates

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A crash between postQuestion and suspendOnGate used to mint a new question id and post a second card. ask_user now derives questionId from the tool-call id, and POST /participants/messages treats a re-post of the same id as a no-op that returns the existing card.

What changed

  • questionIdForCall(call.id) gives a stable q_<hex32> id across retries of the same tool call.
  • postQuestion stamps a caller-supplied questionId instead of always minting.
  • The workflow-participant messages route looks up an existing question block in the workbench and returns that message when the id matches.

Tests

  • Retrying ask_user for the same call reuses the question id.
  • Re-posting the same question id returns the existing card and does not insert a second message.
  • A different question id still posts a second card.

Linear: CL-7248

Fixes CL-7248

@TheGreatAxios
TheGreatAxios force-pushed the cl-7248-ask_user-a-crash-between-postquestion-and-suspendongates branch from 2f71d75 to b3e86fb Compare September 3, 2026 22:07
@TheGreatAxios
TheGreatAxios changed the base branch from main to cl-7298-read-the-canonical-usermessage-in-interaction-tools September 3, 2026 22:07
@TheGreatAxios

Copy link
Copy Markdown
Contributor Author

Fixes CL-7248

@TheGreatAxios

Copy link
Copy Markdown
Contributor Author

Self-review

Verdict: the idempotency mechanism is correct — deriving questionId from the tool-call id and treating a re-post of that id as a no-op closes the crash window described in CL-7248, and the new tests exercise both the retry and the different-id paths. No defects required a fix.

  • CONFIRMED-FIXED: none — no defects found.
  • DISMISSED: existingQuestionMessage paginates the workbench's full message history to check for an existing question id, on every ask_user post (not just retries). This is an O(n) scan per question rather than an indexed lookup, but it is a pre-existing pattern in this route (listMessages is the only read primitive available here) and bounded by one workbench's message count; not a correctness defect and out of scope for a minimal fix.
  • DISMISSED: the route returns 200 instead of 201 on the no-op retry path — postQuestion's caller only checks response.ok, so this doesn't break the client.
  • DISMISSED: questionIdForCall truncates a SHA-256 digest to 32 hex chars (128 bits) — collision risk is negligible and matches the existing q_<hex32> shape.
  • DISMISSED: no exactOptionalPropertyTypes, bare-catch, as T, or vendoring issues found in the diff.
  • CONFIRMED-OPEN: none.

Targeted tests run:

  • bun test src/client.test.ts src/tool.test.ts (packages/interaction-tools) — 16 pass
  • bun test test/workflow-participant-routes.test.ts (packages/chat) — 20 pass
  • bun run typecheck in both packages — clean

@linear-code

linear-code Bot commented Sep 4, 2026

Copy link
Copy Markdown

CL-7248

A crash between posting the question card and persisting the gate
must not mint a second card. These tests pin a stable questionId
on retry and a no-op re-post of the same id.
Derive the card id from the tool-call id so a retry of the same
ask_user call re-posts the same question. The participants/messages
route returns the existing card instead of inserting a second one.
@TheGreatAxios
TheGreatAxios force-pushed the cl-7248-ask_user-a-crash-between-postquestion-and-suspendongates branch from b3e86fb to 3ecea65 Compare September 4, 2026 05:49
@TheGreatAxios
TheGreatAxios changed the base branch from cl-7298-read-the-canonical-usermessage-in-interaction-tools to main September 4, 2026 05:49
@TheGreatAxios
TheGreatAxios merged commit 2190b5d into main Sep 4, 2026
7 checks passed
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.

1 participant