@@ -491,14 +491,6 @@ export class WaitpointSystem {
491491 } ;
492492 }
493493
494- // The record set rides the wait cycle's key once per resume, so build it here rather
495- // than at each append site. Nothing mints a store-format waitpoint yet, so
496- // #completedWaitpointRecordsFor returns undefined on every live path today.
497- const completedWaitpointRecords = await this . #completedWaitpointRecordsFor(
498- runId ,
499- blockingWaitpoints
500- ) ;
501-
502494 // 3. Get the run (run-ops scalars) + resolve its environment via the control-plane resolver,
503495 // so the run-ops DB can split without a cross-provider join.
504496 const run = await this . $ . runStore . findRun (
@@ -616,6 +608,13 @@ export class WaitpointSystem {
616608 } ;
617609 }
618610 case "EXECUTING_WITH_WAITPOINTS" : {
611+ // Built inside the branch, not before the switch: the statuses above return without
612+ // appending, and they must not pay an envelope read to do it.
613+ const completedWaitpointRecords = await this . #completedWaitpointRecordsFor(
614+ runId ,
615+ blockingWaitpoints
616+ ) ;
617+
619618 const newSnapshot = await this . executionSnapshotSystem . createExecutionSnapshot (
620619 this . $ . prisma ,
621620 {
@@ -684,6 +683,11 @@ export class WaitpointSystem {
684683 ) ;
685684 }
686685
686+ const completedWaitpointRecords = await this . #completedWaitpointRecordsFor(
687+ runId ,
688+ blockingWaitpoints
689+ ) ;
690+
687691 //put it back in the queue, with the original timestamp (w/ priority)
688692 //this prioritizes dequeuing waiting runs over new runs
689693 const newSnapshot = await this . enqueueSystem . enqueueRun ( {
@@ -761,31 +765,36 @@ export class WaitpointSystem {
761765 }
762766
763767 /**
764- * The record set for one resume, or undefined when this wait has no store-resident half.
768+ * The record set for one resume, or undefined when no blocking waitpoint carries a store-format
769+ * id.
770+ *
771+ * Gated on id FORMAT, not residency. The two are not the same during a migration: a
772+ * store-format id can still be served by the Postgres arm, exactly as run-ops ids were for
773+ * runs. Whichever arm owns it answers, so the gate only decides whether to ask at all.
765774 *
766- * The classification gate is what keeps this inert. `parseWaitpointId` reports legacy for
767- * every id minted today, so no live resume reads an envelope or writes a record until a
768- * waitpoint mints in store format.
775+ * That gate is what keeps this inert. `parseWaitpointId` reports legacy for every id minted
776+ * today, so no live resume reads an envelope or writes a record until a waitpoint mints in
777+ * store format.
769778 */
770779 async #completedWaitpointRecordsFor(
771780 runId : string ,
772781 blockingWaitpoints : RunBlockEdge [ ]
773782 ) : Promise < CompletedWaitpointRecord [ ] | undefined > {
774- const storeResidentIds = [
783+ const storeFormatIds = [
775784 ...new Set (
776785 blockingWaitpoints
777786 . map ( ( b ) => b . waitpoint . id )
778787 . filter ( ( id ) => parseWaitpointId ( id ) . format === "b32hexW" )
779788 ) ,
780789 ] ;
781790
782- if ( storeResidentIds . length === 0 ) {
791+ if ( storeFormatIds . length === 0 ) {
783792 return undefined ;
784793 }
785794
786795 const sources = await this . coordinator . readCompletionEnvelopes ( {
787796 runId,
788- waitpointIds : storeResidentIds ,
797+ waitpointIds : storeFormatIds ,
789798 } ) ;
790799
791800 return buildCompletedWaitpointRecords ( sources ) ;
0 commit comments