Skip to content

fix(training): persist synchronous media buys before acknowledgement - #8759

Merged
bokelley merged 1 commit into
mainfrom
fix/training-media-buy-durable-ack
Nov 6, 2026
Merged

bokelley merged 1 commit into
mainfrom
fix/training-media-buy-durable-ack

Conversation

@bokelley

@bokelley bokelley commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

A package-mode create_media_buy can return its media_buy_id over MCP before the dirty session is persisted: the tenant router's fallback flush runs after the transport sends the response. An immediate controller request on another web process can therefore report NOT_FOUND for an acknowledged buy. Await session persistence for translated synchronous results carrying a media-buy ID before returning to the SDK or emitting the 3.0 completion webhook. The submitted handoff branch is unchanged.

The deployed 3.1.32 product-filter flow now passes all ten steps after #8754. The broader deterministic flow exposed simulate_delivery: NOT_FOUND after a successful package create; both controller wire payloads validated against 3.1.32. Its recording does not identify the responding machines, so the controlled regression establishes the ordering defect without claiming a directly observed cross-machine trace.

Validation:

  • Three real HTTP/MCP 3.1 cases hold the state write and require the response to remain unpublished, reject persistence and require no successful acknowledgement or phantom replay, and inject a failure into the configured SDK replay adapter while retaining its uncertain error and immediate retry fence.
  • The exact tests against unmodified 15d1be02 fail the first two cases; the replay-failure control already passes. All three pass with this change. These are controlled in-memory ordering tests, not PostgreSQL or deployed qualification.
  • Four focused suites pass 124 tests, including submitted handoff, forced task completion and existing idempotency cases. Production and fixed-trace test-aware typechecks pass.
  • Full normal commit hooks pass: 1,282 root tests and 13,698 server tests, with 31 existing skips in the unchanged router/database-schema suites; production and fixed-trace typechecks pass. Fresh exact-head CI remains required.

Session persistence and SDK replay publication remain separate operations. Replay-publication failure still requires the existing reconciliation procedure; this change does not promise exactly-once crash recovery or safe blind retries after the temporary claim expires. No global idempotency, ownership, session-lookup, schema, corpus, fixture, validator or gate changes. App-only repair; no protocol changeset.

A fresh normal deployment and the unchanged strict external flow remain required before complete hosted qualification.

Accepted review limitation (not fixed): the per-request flush can partially persist related state. In the 3.2 one-shot hold path, the buy may commit before consuming an alternate controller-session hold fails; the response then remains an uncertain error with immediate retry fencing, and a blind post-expiry retry can duplicate the buy. Prior requests and read-only session loads do not join this write set. Flushing only the buy would leave the consumed hold armed; safe prevention requires atomic related writes and a recoverable create receipt. The new ordering tests do not qualify that multi-session fault.

@aao-secretariat aao-secretariat Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ladon verdict: Approve

Approve.

App-only fix to the training sales platform: awaits flushDirtySessions() before returning a synchronous create_media_buy result carrying a media_buy_id, closing a cross-web-process read-after-write gap (an acknowledged buy returning NOT_FOUND on a follow-up controller request). Flush precedes both the SDK return and the 3.0 compatibility webhook; failure fails closed (isError, no ack, immediate retry fenced). Three new HTTP/MCP tests validate hold/reject/replay-failure ordering.

No protocol surface, schema, dist artifact, or changeset scope touched — no changeset required (app-only change). No high-risk paths, gated paths, or author-team gates apply.

Medium findings

  • server/src/training-agent/v6-sales-platform.ts:1734 — Synchronous flush couples media-buy ack to unrelated co-dirty sessions (an unrelated session's persistence failure can fail the ack for an already-committed buy).

Decision: no critical/high findings. gated_paths is false (row 2 does not fire). high_risk is false. The single medium finding's category is not data-loss/schema/infra. Only 1 medium finding (< 3). No prior escalation, no team gate. Falls through to row 9 → approve.

Medium findings

  • server/src/training-agent/v6-sales-platform.ts:1734 — Synchronous flush couples media-buy ack to unrelated co-dirty sessions

@bokelley
bokelley merged commit 4fd89ac into main Nov 6, 2026
57 checks passed
@bokelley
bokelley deleted the fix/training-media-buy-durable-ack branch November 6, 2026 00:35
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