Skip to content

feat: Generate a status-discriminated action attempt union - #1022

Merged
razor-x merged 1 commit into
mainfrom
claude/action-attempt-status-annotations-f216kn
Aug 27, 2026
Merged

feat: Generate a status-discriminated action attempt union#1022
razor-x merged 1 commit into
mainfrom
claude/action-attempt-status-annotations-f216kn

Conversation

@razor-x

@razor-x razor-x commented Aug 27, 2026

Copy link
Copy Markdown
Member

What this means for SDK users

ActionAttempt is now a union with one member per action_type × status, so TypeScript knows exactly when error and result are real objects and when they are null:

const attempt = await seam.locks.lockDoor(
  { device_id },
  { waitForActionAttempt: false },
)

// Before: this compiled and crashed at runtime (result is null while pending).
// Now: it does not compile.
attempt.result.was_confirmed_by_device

// Narrow on status — no null checks needed:
if (attempt.status === 'success') {
  attempt.result.was_confirmed_by_device // ok, result is an object here
}
if (attempt.status === 'error') {
  attempt.error.message // ok, error is an object here
}
if (attempt.status === 'pending') {
  attempt.error  // typed null
  attempt.result // typed null
}

SucceededActionAttempt<T> / FailedActionAttempt<T> now actually extract those members:

type Succeeded = SucceededActionAttempt<ActionAttempt>
// = every { status: 'success' } member, with non-null result

Runtime behavior is unchanged — the API always sent null; the types just stopped lying about it.

How

Bumps @seamapi/blueprint to ^1.10.0. Blueprint now annotates each action-attempt property with the statuses that populate it (error['error'], result['success']). Codegen expands each action attempt into one union member per status: status becomes the literal, annotated properties keep their type in listed statuses and render as null otherwise. Nothing is keyed off the names error/result. Supersedes #1007.

Verification

Type-level tests cover the four snippets above plus resolveActionAttempt returning the success type. 177 tests, typecheck, lint green. Regeneration from a clean install reproduces the diff exactly; tsc time and editor completion latency are unchanged (generated file 61 KB → 79 KB).

🤖 Generated with Claude Code

https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp

Bump @seamapi/blueprint to 1.10.0 and consume the new
actionAttemptStatuses property annotation. Each action attempt now
generates one union member per status from its status enum: the status
property is rendered as the status literal, and any property annotated
with actionAttemptStatuses is rendered as null for statuses it does not
list. SucceededActionAttempt and FailedActionAttempt extract the real
success and error members from the union instead of intersecting with
a status that recovered nothing.

Code that dereferences error or result without narrowing on status
stops typechecking; runtime API behavior is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdWS7o3htQ9cNxhCWL5Frp
@razor-x
razor-x requested a review from a team as a code owner August 27, 2026 01:47
@razor-x
razor-x merged commit 0f35921 into main Aug 27, 2026
16 checks passed
@razor-x
razor-x deleted the claude/action-attempt-status-annotations-f216kn branch August 27, 2026 02:51
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