@@ -51,7 +51,10 @@ import {
5151import { isJSONString } from '@/executor/utils/json'
5252import { filterOutputForLog } from '@/executor/utils/output-filter'
5353import { projectResolvedSecretDiagnosticError } from '@/executor/utils/resolved-secret-content-projection'
54- import type { ResolvedSecretTraceProvenanceV1 } from '@/executor/utils/resolved-secret-trace-registry'
54+ import type {
55+ ResolvedSecretTraceProvenanceV1 ,
56+ ResolvedSecretTraceRegistry ,
57+ } from '@/executor/utils/resolved-secret-trace-registry'
5558import {
5659 buildBranchNodeId ,
5760 buildOuterBranchScopedId ,
@@ -104,6 +107,7 @@ export class BlockExecutor {
104107 const blockResolvedSecretTraceRegistry = parentResolvedSecretTraceRegistry ?. forkForInputPaths (
105108 [ ]
106109 )
110+ const inputDisplayRegistry = blockResolvedSecretTraceRegistry
107111 const blockCtx = blockResolvedSecretTraceRegistry
108112 ? { ...ctx , resolvedSecretTraceRegistry : blockResolvedSecretTraceRegistry }
109113 : ctx
@@ -195,7 +199,7 @@ export class BlockExecutor {
195199 }
196200
197201 if ( blockLog ) {
198- blockLog . input = this . sanitizeInputsForLog ( inputsForLog , block )
202+ blockLog . input = this . projectInputsForDisplay ( inputsForLog , block , inputDisplayRegistry )
199203 }
200204 } catch ( error ) {
201205 cleanupSelfReference ?.( )
@@ -209,6 +213,7 @@ export class BlockExecutor {
209213 startTime ,
210214 blockLog ,
211215 inputsForLog ,
216+ inputDisplayRegistry ,
212217 isSentinel ,
213218 'input_resolution'
214219 )
@@ -245,6 +250,8 @@ export class BlockExecutor {
245250 normalizeStringArray ( blockCtx . selectedOutputs )
246251 )
247252 } catch ( streamError ) {
253+ blockCtx . resolvedSecretTraceRegistry =
254+ blockCtx . resolvedSecretTraceRegistry ?. forkForPropagatedEntries ( )
248255 // Timeout / drain failures may still have projected answer text — keep it
249256 // for the failed block output so logs match what the client already saw.
250257 streamingPartialOutput = streamingExec . execution ?. output
@@ -337,7 +344,7 @@ export class BlockExecutor {
337344 const displayOutput = filterOutputForLog ( block . metadata ?. id || '' , normalizedOutput , {
338345 block,
339346 } )
340- const displayInput = this . sanitizeInputsForLog ( inputsForLog , block )
347+ const displayInput = this . projectInputsForDisplay ( inputsForLog , block , inputDisplayRegistry )
341348 blockLog . input = displayInput
342349 const displayProvenance = settledBlockRegistry ?. exportCommittedProvenanceForValue ( {
343350 input : displayInput ,
@@ -374,6 +381,7 @@ export class BlockExecutor {
374381 startTime ,
375382 blockLog ,
376383 inputsForLog ,
384+ inputDisplayRegistry ,
377385 isSentinel ,
378386 'execution' ,
379387 streamingPartialOutput
@@ -459,6 +467,7 @@ export class BlockExecutor {
459467 startTime : number ,
460468 blockLog : BlockLog | undefined ,
461469 inputsForLog : Record < string , any > ,
470+ inputDisplayRegistry : ResolvedSecretTraceRegistry | undefined ,
462471 isSentinel : boolean ,
463472 phase : 'input_resolution' | 'execution' ,
464473 streamingPartialOutput ?: Record < string , any >
@@ -495,7 +504,7 @@ export class BlockExecutor {
495504 blockLog . durationMs = duration
496505 blockLog . success = true
497506 blockLog . error = undefined
498- blockLog . input = this . sanitizeInputsForLog ( input , block )
507+ blockLog . input = this . projectInputsForDisplay ( input , block , inputDisplayRegistry )
499508 blockLog . output = filterOutputForLog ( block . metadata ?. id || '' , softOutput , { block } )
500509 }
501510
@@ -505,7 +514,7 @@ export class BlockExecutor {
505514 } )
506515
507516 if ( ! isSentinel && blockLog ) {
508- const displayInput = this . sanitizeInputsForLog ( input , block )
517+ const displayInput = this . projectInputsForDisplay ( input , block , inputDisplayRegistry )
509518 const displayOutput = filterOutputForLog ( block . metadata ?. id || '' , softOutput , { block } )
510519 const displayProvenance =
511520 ctx . resolvedSecretTraceRegistry ?. exportCommittedProvenanceForValue ( {
@@ -575,17 +584,25 @@ export class BlockExecutor {
575584 blockLog . durationMs = duration
576585 blockLog . success = false
577586 blockLog . error = errorMessage
578- blockLog . input = this . sanitizeInputsForLog ( input , block )
587+ blockLog . input = this . projectInputsForDisplay ( input , block , inputDisplayRegistry )
579588 blockLog . output = filterOutputForLog ( block . metadata ?. id || '' , errorOutput , { block } )
580589
581590 if ( ChildWorkflowError . isChildWorkflowError ( error ) && error . childTraceSpans . length > 0 ) {
582591 blockLog . childTraceSpans = error . childTraceSpans
583592 }
584593 }
585594
595+ const diagnosticRegistry = inputDisplayRegistry ?. forkForToolCall ( )
596+ if (
597+ diagnosticRegistry &&
598+ ctx . resolvedSecretTraceRegistry &&
599+ ctx . resolvedSecretTraceRegistry !== inputDisplayRegistry
600+ ) {
601+ diagnosticRegistry . mergeToolCallRegistry ( ctx . resolvedSecretTraceRegistry )
602+ }
586603 const errorDiagnostic = projectResolvedSecretDiagnosticError (
587604 error ,
588- ctx . resolvedSecretTraceRegistry
605+ diagnosticRegistry ?? ctx . resolvedSecretTraceRegistry
589606 )
590607
591608 this . execLogger . error (
@@ -602,7 +619,7 @@ export class BlockExecutor {
602619 ? error . childWorkflowInstanceId
603620 : undefined
604621 const displayOutput = filterOutputForLog ( block . metadata ?. id || '' , errorOutput , { block } )
605- const displayInput = this . sanitizeInputsForLog ( input , block )
622+ const displayInput = this . projectInputsForDisplay ( input , block , inputDisplayRegistry )
606623 const displayProvenance = ctx . resolvedSecretTraceRegistry ?. exportCommittedProvenanceForValue ( {
607624 input : displayInput ,
608625 output : displayOutput ,
@@ -729,6 +746,17 @@ export class BlockExecutor {
729746 return { result : output }
730747 }
731748
749+ /** Builds the log-facing input copy from resolver-recorded projections only. */
750+ private projectInputsForDisplay (
751+ inputs : Record < string , any > ,
752+ block : SerializedBlock | undefined ,
753+ registry : ResolvedSecretTraceRegistry | undefined
754+ ) : Record < string , any > {
755+ const projection = registry ?. projectResolvedInputSelection ( inputs )
756+ if ( projection && ! projection . complete ) return { }
757+ return this . sanitizeInputsForLog ( projection ?. value ?? inputs , block )
758+ }
759+
732760 /**
733761 * Sanitizes inputs for log display.
734762 * - Filters out system fields (UI-only, readonly, internal flags)
@@ -974,6 +1002,16 @@ export class BlockExecutor {
9741002 const piiEnabled = Boolean ( ctx . piiBlockOutputRedaction ?. enabled )
9751003 // Live-forward only when a client stream exists and PII redaction is off.
9761004 const forwardToClient = Boolean ( ctx . onStream ) && ! piiEnabled
1005+ const projectStreamDiagnosticError = ( error : unknown ) : Record < string , unknown > => {
1006+ const sourceRegistry = streamingExec . diagnosticResolvedSecretTraceRegistry
1007+ const resultRegistry = ctx . resolvedSecretTraceRegistry
1008+ if ( ! sourceRegistry || sourceRegistry === resultRegistry ) {
1009+ return projectResolvedSecretDiagnosticError ( error , resultRegistry )
1010+ }
1011+ const diagnosticRegistry = sourceRegistry . forkForToolCall ( )
1012+ if ( resultRegistry ) diagnosticRegistry . mergeToolCallRegistry ( resultRegistry )
1013+ return projectResolvedSecretDiagnosticError ( error , diagnosticRegistry )
1014+ }
9771015
9781016 const responseFormat =
9791017 resolvedInputs ?. responseFormat ??
@@ -993,6 +1031,10 @@ export class BlockExecutor {
9931031 let processedClientStream : ReadableStream < Uint8Array > | undefined
9941032
9951033 if ( forwardToClient && ctx . onStream && pump . textStream ) {
1034+ const {
1035+ diagnosticResolvedSecretTraceRegistry : _diagnosticRegistry ,
1036+ ...streamingExecutionForConsumer
1037+ } = streamingExec
9961038 processedClientStream = streamingResponseFormatProcessor . processStream (
9971039 pump . textStream ,
9981040 blockId ,
@@ -1005,7 +1047,7 @@ export class BlockExecutor {
10051047 // with `pump.run()`.
10061048 onStreamPromise = ctx
10071049 . onStream ( {
1008- ...streamingExec ,
1050+ ...streamingExecutionForConsumer ,
10091051 stream : processedClientStream ,
10101052 streamFormat : 'text' ,
10111053 subscribe : pump . subscribe ,
@@ -1018,7 +1060,7 @@ export class BlockExecutor {
10181060 . catch ( async ( error ) => {
10191061 this . execLogger . error ( 'Error in onStream callback' , {
10201062 blockId,
1021- ...projectResolvedSecretDiagnosticError ( error , ctx . resolvedSecretTraceRegistry ) ,
1063+ ...projectStreamDiagnosticError ( error ) ,
10221064 } )
10231065 await processedClientStream ?. cancel ( ) . catch ( ( ) => { } )
10241066 } )
@@ -1030,7 +1072,7 @@ export class BlockExecutor {
10301072 } catch ( error ) {
10311073 this . execLogger . error ( 'Error reading stream for block' , {
10321074 blockId,
1033- ...projectResolvedSecretDiagnosticError ( error , ctx . resolvedSecretTraceRegistry ) ,
1075+ ...projectStreamDiagnosticError ( error ) ,
10341076 } )
10351077 if ( onStreamPromise ) {
10361078 await onStreamPromise . catch ( ( ) => { } )
@@ -1121,7 +1163,7 @@ export class BlockExecutor {
11211163 } catch ( error ) {
11221164 this . execLogger . warn ( 'Failed to parse streamed content for response format' , {
11231165 blockId,
1124- ...projectResolvedSecretDiagnosticError ( error , ctx . resolvedSecretTraceRegistry ) ,
1166+ ...projectStreamDiagnosticError ( error ) ,
11251167 } )
11261168 }
11271169 }
@@ -1136,7 +1178,7 @@ export class BlockExecutor {
11361178 } catch ( error ) {
11371179 this . execLogger . error ( 'onFullContent callback failed' , {
11381180 blockId,
1139- ...projectResolvedSecretDiagnosticError ( error , ctx . resolvedSecretTraceRegistry ) ,
1181+ ...projectStreamDiagnosticError ( error ) ,
11401182 } )
11411183 }
11421184 }
0 commit comments