@@ -111,6 +111,7 @@ export function enablePipelineStreaming(
111111 const deliverableRunId = String ( config . runId || '' ) ;
112112 const canPersistDeliverableHierarchy = uuidRe . test ( deliverableRunId ) ;
113113 let deliverableRunReady : Promise < boolean > | null = null ;
114+ let structuredWriteQueue : Promise < unknown > = Promise . resolve ( ) ;
114115
115116 const insertRow = async ( table : string , row : any , returningId = false ) => {
116117 const query = ( supabase as any ) . from ( table ) . insert ( row ) ;
@@ -222,7 +223,36 @@ export function enablePipelineStreaming(
222223 } , 'id' , deliverableRunId ) . catch ( ( ) => { } ) ;
223224 } ;
224225
225- streamer . subscribe ( async ( event : any ) => {
226+ const completeOpenHierarchyRows = async ( now : string ) => {
227+ if ( ! ( await ensureDeliverableRun ( ) ) ) return ;
228+ const { data : openPhases } = await ( supabase as any )
229+ . from ( 'deliverable_pipeline_phase_delegations' )
230+ . select ( 'id' )
231+ . eq ( 'run_id' , deliverableRunId )
232+ . eq ( 'status' , 'running' ) ;
233+ const openPhaseIds = Array . isArray ( openPhases )
234+ ? openPhases . map ( ( row : any ) => row ?. id ) . filter ( Boolean )
235+ : [ ] ;
236+ if ( ! openPhaseIds . length ) return ;
237+ await ( supabase as any )
238+ . from ( 'deliverable_pipeline_agent_steps' )
239+ . update ( {
240+ completed_at : now ,
241+ status : 'completed' ,
242+ } )
243+ . in ( 'phase_delegation_id' , openPhaseIds )
244+ . eq ( 'status' , 'running' ) ;
245+ await ( supabase as any )
246+ . from ( 'deliverable_pipeline_phase_delegations' )
247+ . update ( {
248+ completed_at : now ,
249+ status : 'completed' ,
250+ } )
251+ . in ( 'id' , openPhaseIds )
252+ . eq ( 'status' , 'running' ) ;
253+ } ;
254+
255+ const persistStructuredEvent = async ( event : any ) => {
226256 try {
227257 const type = String ( event ?. type || '' ) ;
228258 const context = normalizeEventContext ( event ) ;
@@ -414,13 +444,21 @@ export function enablePipelineStreaming(
414444
415445 // If Finish phase completes, mark run completed.
416446 if ( type === 'phase-complete' && phaseName === 'finish' ) {
447+ await completeOpenHierarchyRows ( now ) ;
417448 await markDeliverableRun ( 'completed' , event ?. data ?? event ) ;
418449 await updateRows ( 'executions' , { status : 'completed' , completed_at : now } , 'id' , config . runId ) . catch ( ( ) => { } ) ;
419450 }
420451 } catch ( err ) {
421452 console . error ( 'Structured stream persistence error' , err ) ;
422453 }
454+ } ;
455+
456+ streamer . subscribe ( ( event : any ) => {
457+ structuredWriteQueue = structuredWriteQueue
458+ . catch ( ( ) => { } )
459+ . then ( ( ) => persistStructuredEvent ( event ) ) ;
423460 } ) ;
461+ ( streamer as any ) . flushStructuredWrites = ( ) => structuredWriteQueue . catch ( ( ) => { } ) ;
424462 }
425463
426464 // Note: Cleanup should be handled by the pipeline implementation
0 commit comments