@@ -15,7 +15,7 @@ import {
1515 type ParkedMockCall ,
1616} from '@/lib/workflow-tests/mock-channel'
1717import type { TestCaseStatus , TestEvent , TestTarget } from '@/lib/workflow-tests/protocol'
18- import { type EnteredWorkflow , readDraftUpdatedAt } from '@/lib/workflow-tests/repository'
18+ import { type EnteredWorkflow , readDraftTimestamps } from '@/lib/workflow-tests/repository'
1919import {
2020 runWorkflowForTest ,
2121 type WorkflowTestRunResult ,
@@ -251,10 +251,7 @@ class RunMatcher implements MockMatcher {
251251 constructor (
252252 targets : TestTarget [ ] ,
253253 private readonly loadChildBlocks : ( workflowId : string ) => Promise < Record < string , BlockState > > ,
254- private readonly onEnter : (
255- workflowId : string ,
256- deploymentVersionId : string | null
257- ) => Promise < void >
254+ private readonly onEnter : ( workflowId : string , deploymentVersionId : string | null ) => void
258255 ) {
259256 this . targets = [ ...targets ] . sort (
260257 ( a , b ) => Number ( a . workflow === null ) - Number ( b . workflow === null )
@@ -276,7 +273,7 @@ class RunMatcher implements MockMatcher {
276273 this . entered = true
277274 this . outputRegistry = resolvedSecretTraceRegistry
278275 }
279- await this . onEnter ( workflowId , deploymentVersionId )
276+ this . onEnter ( workflowId , deploymentVersionId )
280277 const workflowName = await this . workflowName ( workflowId )
281278 for ( const block of blocks ) this . blocks . set ( block . id , block )
282279 await this . learnWorkflow (
@@ -527,7 +524,7 @@ class TestWorkflowRun {
527524export class WorkflowTestSession {
528525 private readonly runs = new Map < string , TestWorkflowRun > ( )
529526 /** Every workflow version this file's runs executed, children included, as each loaded it. */
530- private readonly enteredVersions = new Map < string , Promise < EnteredWorkflow > > ( )
527+ private readonly enteredVersions = new Map < string , EnteredWorkflow > ( )
531528 /** Set when the sandbox run ends; a start still awaiting its lookups then starts nothing. */
532529 private closed = false
533530 /** Stops `toMatchRubric` model calls still in flight when the sandbox run ends. */
@@ -546,9 +543,10 @@ export class WorkflowTestSession {
546543 const blocks = await loadWorkflowBlocks ( workflowId , workspaceId , version )
547544 const triggerBlockId = chooseTrigger ( args . workflow , blocks , args . trigger )
548545 const targets = await resolveToolTargets ( workspaceId , args . targets )
546+ const draftsBeforeLoad = version === 'draft' ? await readDraftTimestamps ( workspaceId ) : null
549547 if ( this . closed ) throw new Error ( 'This workflow test run has ended' )
550548 const matcher = new RunMatcher ( targets , loadChildBlockNames , ( id , deploymentVersionId ) =>
551- this . recordEntered ( id , deploymentVersionId )
549+ this . recordEntered ( id , deploymentVersionId , draftsBeforeLoad )
552550 )
553551 const channel = createMockChannel ( matcher )
554552 const abort = new AbortController ( )
@@ -592,23 +590,28 @@ export class WorkflowTestSession {
592590 }
593591 }
594592
595- /** The first entry of a draft keeps its timestamp, so an edit between runs leaves the file stale. */
596- private async recordEntered ( workflowId : string , deploymentVersionId : string | null ) {
593+ /**
594+ * A draft records its timestamp from before the run loaded it, so any edit after that point,
595+ * including one the load may have missed, leaves the run stale. The first run to enter a
596+ * workflow keeps its entry, the earliest timestamp.
597+ */
598+ private recordEntered (
599+ workflowId : string ,
600+ deploymentVersionId : string | null ,
601+ draftsBeforeLoad : Map < string , string > | null
602+ ) : void {
597603 const key = `${ workflowId } :${ deploymentVersionId ?? 'draft' } `
598- let entry = this . enteredVersions . get ( key )
599- if ( ! entry ) {
600- entry = ( async ( ) => ( {
601- workflowId,
602- deploymentVersionId,
603- draftUpdatedAt : deploymentVersionId === null ? await readDraftUpdatedAt ( workflowId ) : null ,
604- } ) ) ( )
605- this . enteredVersions . set ( key , entry )
606- }
607- await entry
604+ if ( this . enteredVersions . has ( key ) ) return
605+ this . enteredVersions . set ( key , {
606+ workflowId,
607+ deploymentVersionId,
608+ draftUpdatedAt :
609+ deploymentVersionId === null ? ( draftsBeforeLoad ?. get ( workflowId ) ?? null ) : null ,
610+ } )
608611 }
609612
610- enteredWorkflows ( ) : Promise < EnteredWorkflow [ ] > {
611- return Promise . all ( this . enteredVersions . values ( ) )
613+ enteredWorkflows ( ) : EnteredWorkflow [ ] {
614+ return [ ... this . enteredVersions . values ( ) ]
612615 }
613616
614617 close ( ) : void {
0 commit comments