Repository navigation
fix(training): persist synchronous media buys before acknowledgement - #8759
Conversation
There was a problem hiding this comment.
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
A package-mode
create_media_buycan return itsmedia_buy_idover 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 reportNOT_FOUNDfor 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_FOUNDafter 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:
15d1be02fail 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.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.