@@ -367,9 +367,11 @@ const taskInput = {
367367 metadata : { workload : request . workload , ...( materializedPackage ? { imported_agent : materializedPackage . identity } : { } ) , runtime_sources : materializedRuntimeSources ?. descriptors ?? [ ] } ,
368368 } ,
369369 } ,
370- } ,
371- workspaces : request . runner_workspace ?. enabled ? [ { target : "/workspace" , mode : "readwrite" , sourceMode : "repo-backed" , seed : { type : "directory" , source : workspace , excludePaths : [ ".git/**" , ".codebox/**" , "node_modules/**" , "vendor/**" , "dist/**" , "build/**" , "coverage/**" , ".cache/**" ] } } ] : [ ] ,
372- }
370+ // agent-task-run unwraps task_input before building the recipe. Keep the
371+ // runner seed on that canonical input rather than on the request envelope.
372+ workspaces : request . runner_workspace ?. enabled ? [ { target : "/workspace" , mode : "readwrite" , sourceMode : "repo-backed" , seed : { type : "directory" , source : workspace , excludePaths : [ ".git/**" , ".codebox/**" , "node_modules/**" , "vendor/**" , "dist/**" , "build/**" , "coverage/**" , ".cache/**" ] } } ] : [ ] ,
373+ } ,
374+ }
373375
374376await writeFile ( executionInputPath , `${ JSON . stringify ( taskInput , null , 2 ) } \n` )
375377
@@ -389,20 +391,25 @@ const runtimeResult = sanitizeRuntimeSourceValue(nativeRuntimeResult, privateRun
389391assertNoRuntimeSourcePaths ( runtimeResult , privateRuntimeSourceRootForSanitization )
390392let workspaceApply = { status : "no-op" , changedFiles : [ ] }
391393let runnerWorkspaceCore = null
394+ let downstreamFailure = null
392395if ( execution . code === 0 && runtimeResult . success === true && request . runner_workspace ?. enabled ) {
393- runnerWorkspaceCore = await import ( pathToFileURL ( join ( codeboxRoot , "packages/runtime-core/dist/runner-workspace-apply.js" ) ) . href )
394- const publicCore = await import ( pathToFileURL ( join ( codeboxRoot , "packages/runtime-core/dist/public.js" ) ) . href )
395- const refs = publicCore . normalizePublicArtifactRefDTOs ( runtimeResult )
396- . filter ( ( ref ) => ref . kind === "codebox-patch" || ref . kind === "codebox-changed-files" )
397- workspaceApply = await runnerWorkspaceCore . applyRunnerWorkspacePatch ( { artifactRoot : artifactsPath , artifactRefs : refs , workspaceRoot : workspace , writablePaths : String ( request . writable_paths || "" ) . split ( "," ) . map ( ( value ) => value . trim ( ) ) . filter ( Boolean ) } )
396+ try {
397+ runnerWorkspaceCore = await import ( pathToFileURL ( join ( codeboxRoot , "packages/runtime-core/dist/runner-workspace-apply.js" ) ) . href )
398+ const publicCore = await import ( pathToFileURL ( join ( codeboxRoot , "packages/runtime-core/dist/public.js" ) ) . href )
399+ const refs = publicCore . normalizePublicArtifactRefDTOs ( runtimeResult )
400+ . filter ( ( ref ) => ref . kind === "codebox-patch" || ref . kind === "codebox-changed-files" )
401+ workspaceApply = await runnerWorkspaceCore . applyRunnerWorkspacePatch ( { artifactRoot : artifactsPath , artifactRefs : refs , workspaceRoot : workspace , writablePaths : String ( request . writable_paths || "" ) . split ( "," ) . map ( ( value ) => value . trim ( ) ) . filter ( Boolean ) } )
402+ } catch ( error ) {
403+ downstreamFailure = { stage : "apply" , message : bounded ( error instanceof Error ? error . message : String ( error ) , MAX_OUTPUT_CHARS ) }
404+ }
398405}
399406await cleanupPrivateRuntimeSources ( )
400407assertNoRuntimeSourcePaths ( runtimeResult , privateRuntimeSourceRootForSanitization )
401408
402409await redactArtifactFiles ( artifactsPath )
403410
404411const verification = [ ]
405- if ( execution . code === 0 && request . run_agent && ! request . dry_run ) {
412+ if ( execution . code === 0 && request . run_agent && ! request . dry_run && ! downstreamFailure ) {
406413 const validationDependencies = string ( request . validation_dependencies )
407414 if ( validationDependencies ) {
408415 const checkResult = await command ( "bash" , [ "-lc" , validationDependencies ] , workspace )
@@ -419,21 +426,30 @@ if (execution.code === 0 && request.run_agent && !request.dry_run) {
419426}
420427
421428const verificationPassed = verification . every ( ( check ) => check . success )
429+ if ( ! verificationPassed ) {
430+ downstreamFailure ??= { stage : "verification" , message : "Runner workspace verification did not pass." }
431+ }
422432const runtimeRecord = record ( runtimeResult )
423433const agentResult = record ( runtimeRecord . agent_task_run_result )
424434let publication = resultValue ( runtimeRecord , "metadata.runner_workspace_publication" )
425435if ( execution . code === 0 && runtimeRecord . success === true && verificationPassed && workspaceApply . status === "applied" ) {
426- await runnerWorkspaceCore . verifyRunnerWorkspaceIntegrity ( workspaceApply . integrity )
427- const testPublisher = string ( process . env . WP_CODEBOX_TEST_PUBLISHER_MODULE )
428- const publisher = testPublisher ? ( await import ( pathToFileURL ( resolve ( testPublisher ) ) . href ) ) . publishRunnerWorkspace : publishRunnerWorkspace
429- const testHook = testPublisher && process . env . WP_CODEBOX_TEST_PUBLISHER_HOOK
430- ? JSON . parse ( process . env . WP_CODEBOX_TEST_PUBLISHER_HOOK )
431- : undefined
432- publication = await publisher ( { request, changedFiles : workspaceApply . changedFiles , publicationFiles : workspaceApply . publicationFiles , token : process . env . ACCESS_TOKEN || process . env . GITHUB_TOKEN , ...( testHook ? { testHook } : { } ) } )
433- runtimeRecord . metadata = { ...record ( runtimeRecord . metadata ) , runner_workspace_publication : publication }
434- runtimeRecord . outputs = { ...record ( runtimeRecord . outputs ) , runner_workspace_publication : publication }
435- }
436- if ( request . success ?. requires_pr === true && workspaceApply . status === "no-op" && ! publication ) throw new Error ( "success_requires_pr cannot succeed for a no-op runner workspace task." )
436+ try {
437+ await runnerWorkspaceCore . verifyRunnerWorkspaceIntegrity ( workspaceApply . integrity )
438+ const testPublisher = string ( process . env . WP_CODEBOX_TEST_PUBLISHER_MODULE )
439+ const publisher = testPublisher ? ( await import ( pathToFileURL ( resolve ( testPublisher ) ) . href ) ) . publishRunnerWorkspace : publishRunnerWorkspace
440+ const testHook = testPublisher && process . env . WP_CODEBOX_TEST_PUBLISHER_HOOK
441+ ? JSON . parse ( process . env . WP_CODEBOX_TEST_PUBLISHER_HOOK )
442+ : undefined
443+ publication = await publisher ( { request, changedFiles : workspaceApply . changedFiles , publicationFiles : workspaceApply . publicationFiles , token : process . env . ACCESS_TOKEN || process . env . GITHUB_TOKEN , ...( testHook ? { testHook } : { } ) } )
444+ runtimeRecord . metadata = { ...record ( runtimeRecord . metadata ) , runner_workspace_publication : publication }
445+ runtimeRecord . outputs = { ...record ( runtimeRecord . outputs ) , runner_workspace_publication : publication }
446+ } catch ( error ) {
447+ downstreamFailure = { stage : "publication" , message : bounded ( error instanceof Error ? error . message : String ( error ) , MAX_OUTPUT_CHARS ) }
448+ }
449+ }
450+ if ( request . success ?. requires_pr === true && workspaceApply . status === "no-op" && ! publication ) {
451+ downstreamFailure ??= { stage : "no-op" , message : "success_requires_pr cannot succeed for a no-op runner workspace task." }
452+ }
437453let evaluatedProjections = { }
438454let projectionError = ""
439455try {
@@ -446,8 +462,11 @@ const publicationVerification = publicationRequired && execution.code === 0 && r
446462 ? await verifyPublishedPullRequest ( publication , request . target_repo , workspace )
447463 : { valid : ! publicationRequired , error : "" }
448464const publicationPassed = publicationVerification . valid
465+ if ( publicationRequired && ! publicationPassed ) {
466+ downstreamFailure ??= { stage : "publication" , message : publicationVerification . error || "Runner workspace publication did not pass verification." }
467+ }
449468const success = request . run_agent && ! request . dry_run
450- ? execution . code === 0 && runtimeRecord . success === true && verificationPassed && publicationPassed && ! projectionError
469+ ? execution . code === 0 && runtimeRecord . success === true && verificationPassed && publicationPassed && ! projectionError && ! downstreamFailure
451470 : true
452471const status = request . run_agent && ! request . dry_run ? ( success ? "succeeded" : "failed" ) : "skipped"
453472const result = {
@@ -470,6 +489,7 @@ const result = {
470489 access : { authorized : true , credential_mode : process . env . GITHUB_TOKEN ? "runner-access-token" : ( process . env . OPENAI_API_KEY ? "runner-provider-credentials" : "runner-default-credentials" ) , policy : { allowed_repos : request . access . allowed_repos } } ,
471490 ...( publicationRequired ? { publication_verification : publicationVerification } : { } ) ,
472491 ...( publicationRequired && ! publicationPassed ? { publication_error : "success_requires_pr requires a valid published runner-workspace pull request for target_repo." } : { } ) ,
492+ ...( downstreamFailure ? { failure : { code : "wp-codebox.agent-task.downstream" , classification : "downstream" , ...downstreamFailure } } : { } ) ,
473493 ...( projectionError ? { projection_error : projectionError } : { } ) ,
474494}
475495
0 commit comments