Skip to content

Add actionId vocabulary to CanonicalDiff (back-compat with diffId)#21

Merged
chubes4 merged 1 commit intomainfrom
add-action-id-alias
Apr 24, 2026
Merged

Add actionId vocabulary to CanonicalDiff (back-compat with diffId)#21
chubes4 merged 1 commit intomainfrom
add-action-id-alias

Conversation

@chubes4
Copy link
Copy Markdown
Member

@chubes4 chubes4 commented Apr 24, 2026

Summary

Data Machine unified its preview primitive on a generic "pending action" model (DM #1171, editor #5). Any tool invocation can now stage → preview → resolve through a single /actions/resolve endpoint and a single action_id — not just the three content-diff tools (edit_post_blocks / replace_post_blocks / insert_content) that originally drove the v0.7 diff primitive in this package.

Server-side CanonicalDiffPreview::build() now emits actionId on the diff payload. This package was only reading diffId / diff_id, so:

  • parseCanonicalDiff returns diffId: '' on every fresh preview payload.
  • DiffCard's onAccept / onReject callbacks fire with an empty string.
  • Every consumer that wires those callbacks to a resolve endpoint silently breaks.

Fix

  • Add actionId as the canonical field on CanonicalDiffData.

  • Keep diffId as a deprecated alias, always populated with the same value as actionId, so consumers still reading diff.diffId keep working through one more major version.

  • parseCanonicalDiff reads, in priority order:

    1. rawDiff.actionId
    2. rawDiff.action_id
    3. container.action_id
    4. rawDiff.diffId
    5. rawDiff.diff_id
    6. container.diff_id

    The resolved string populates both actionId and diffId on the returned CanonicalDiffData.

  • DiffCard's onAccept / onReject now fire with diff.actionId || diff.diffId so the right id gets delivered regardless of which field the consumer wrote.

  • Docblock example updated to show the new /actions/resolve + action_id shape.

Compat

  • Additive only. No existing consumer breaks.
  • Consumers reading diff.diffId keep working.
  • Consumers receiving the onAccept(id) / onReject(id) callback keep working — they now get the right id even when the backend sent actionId.
  • Consumers should migrate to diff.actionId on their schedule. The diffId alias can be removed in a future major.

Validation

  • npm run build (tsc) passes cleanly.
  • No test suite in the repo; behaviour verified by reading each call site for diffId / action_id / diff_id.

Downstream

  • data-machine-frontend-chat has a companion PR that updates its resolve call to /actions/resolve with action_id and bumps the chat dep — depends on this PR.
  • Data Machine admin ChatSidebar.jsx only uses copyChatAsMarkdown / useChat, not the diff primitives, so no change needed there.

AI assistance

  • AI assistance: Yes
  • Tool(s): Claude Code (Opus 4.7)
  • Used for: Traced the vocabulary drift from DM's unified preview primitive (PR #1171) through CanonicalDiffPreview::build() to this package's parser, drafted the additive alias design, and verified no other internal call sites reference diffId. Chris flagged the audit target.

Data Machine unified its preview primitive on a generic
"pending action" model (DM PR #1171, editor PR #5): any tool
invocation can now stage → preview → resolve through a single
/actions/resolve endpoint and a single action_id, not just the
three content-diff tools (edit_post_blocks / replace_post_blocks /
insert_content) that originally drove the v0.7 diff primitive here.

The chat package was only reading `diffId` / `diff_id` from tool
result payloads, so preview cards now render with an empty id and
Accept/Reject callbacks deliver an empty string. This breaks every
consumer that wires those callbacks to a resolve endpoint.

Fix:
- Add `actionId` as the canonical field on CanonicalDiffData.
- Keep `diffId` as a deprecated alias, always populated with the
  same value as `actionId`, so consumers still reading `diff.diffId`
  keep working through one more major version.
- parseCanonicalDiff now reads, in priority order:
  actionId → action_id → container.action_id → diffId → diff_id →
  container.diff_id. The result populates BOTH actionId and diffId
  with the same resolved string.
- DiffCard's onAccept / onReject callbacks fire with
  `diff.actionId || diff.diffId` so the right id gets delivered
  regardless of which field the consumer wrote.

Docblock example updated to show the new /actions/resolve + action_id
shape. No breaking changes — strictly additive.
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