Skip to content

Harden distributed writes for work-sdk v0.4 - #3

Merged
arturict merged 1 commit into
mainfrom
codex/v0.4-api-safety
Jul 24, 2026
Merged

arturict merged 1 commit into
mainfrom
codex/v0.4-api-safety

Conversation

@arturict

Copy link
Copy Markdown
Owner

What changed

  • replace the non-atomic idempotency get/set recipe with an atomic acquire/complete/abandon protocol
  • add explicit in-flight and ambiguous commit errors and action-specific concurrency guarantees
  • make prepared changes discriminated by action and export missing public types
  • fix assignee round-tripping and exact normalized state filtering
  • fail closed for unsafe GitLab create states, ambiguous Jira transitions, and ambiguous Azure state mappings
  • validate Linear/Jira configuration earlier and add localized Jira priority mappings
  • rewrite the safety, API, provider, testing, machine-readable, and landing-page documentation for the real guarantees

Why

Two workers could previously both read an empty durable store and perform the same provider mutation. Several provider state and identity mappings also looked portable but were not safely round-trippable. v0.4 makes those boundaries explicit and blocks blind retries when a provider outcome cannot be proven.

Validation

  • 185 SDK tests
  • 10 website tests
  • approval CLI and webhook bot tests
  • strict TypeScript checks across the workspace
  • Next.js production build
  • publint and Are the Types Wrong checks
  • packed consumer smoke test for ESM, CommonJS, and every subpath
  • production dependency audit: no known vulnerabilities

@arturict
arturict merged commit 78ff19d into main Jul 24, 2026
7 of 8 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e29ccb53a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (change.action === "update") {
if (change.changes.length === 0) item = current;
else {
mutationStarted = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve atomic update conflicts

When an Azure DevOps update races with another writer after the client's preflight read, the adapter's JSON Patch /rev test rejects with WorkConflictError before applying any mutation; setting mutationStarted before adapter.update means the catch path below converts that safe atomic conflict into WorkAmbiguousCommitError and marks the idempotency claim ambiguous. Callers then have to reconcile and the key stays blocked even though no provider write succeeded, so atomic update conflicts should remain retryable conflicts instead of being treated as uncertain outcomes.

Useful? React with 👍 / 👎.

let mutationStarted = false;
try {
if (change.action === "create") {
mutationStarted = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep create preflights from poisoning idempotency keys

For creates, this flag is set before the adapter has finished its own preflight work, so safe validation failures are reported as ambiguous writes. For example, gitlabWorkAdapter.create validates labels before issuing the POST; through WorkClient.commit, an unknown label now throws WorkAmbiguousCommitError and abandons the key as ambiguous even though no issue creation was attempted, leaving callers unable to fix the input and retry the same business key.

Useful? React with 👍 / 👎.

const normalized = requested.toLowerCase();
const canonical = ["backlog", "unstarted", "started", "completed", "canceled", "unknown"].includes(normalized);
if (!canonical) {
return [...states.keys()].find((name) => name.toLowerCase() === normalized) ?? requested;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve Azure state-name casing

When callers pass a provider-native Azure state that is present in the built-in or custom stateMap, this returns the lower-cased map key instead of the exact state name the caller supplied. For example the docs' Ready for validation custom state is normalized to ready for validation before the JSON Patch is sent, so tenants with cased/custom state names can reject the transition even though the input used the correct provider-native value.

Useful? React with 👍 / 👎.

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