@@ -13,6 +13,7 @@ const publicWorkflowSurface = workflow.slice(0, workflow.indexOf("jobs:"))
1313assert . match ( workflow , / ^ n a m e : R u n A g e n t T a s k \( r e u s a b l e \) $ / m)
1414assert . match ( workflow , / w o r k f l o w _ c a l l : / )
1515assert . match ( workflow , / r u n n e r _ r e c i p e : / )
16+ assert . match ( workflow , / r u n n e r _ r e c i p e : \n \s + d e s c r i p t i o n : [ ^ \n ] * t e m p o r a r y [ ^ \n ] * \n \s + t y p e : s t r i n g \n \s + r e q u i r e d : f a l s e / )
1617assert . match ( workflow , / a g e n t _ b u n d l e : / )
1718assert . match ( workflow , / r u n n e r _ w o r k s p a c e : / )
1819assert . match ( workflow , / a r t i f a c t _ d e c l a r a t i o n s : / )
@@ -31,12 +32,14 @@ const docs = await readFile(new URL("../docs/agent-task-reusable-workflow.md", i
3132assert . match ( docs , / ^ # A g e n t T a s k R e u s a b l e W o r k f l o w / m)
3233assert . match ( docs , / A u t o m a t t i c \/ w p - c o d e b o x \/ .g i t h u b \/ w o r k f l o w s \/ r u n - a g e n t - t a s k .y m l @ m a i n / )
3334assert . match ( docs , / r u n n e r _ r e c i p e / )
35+ assert . match ( docs , / t e m p o r a r y o p t i o n a l i n p u t / )
36+ assert . match ( docs , / f a i l s c l o s e d u n t i l t h e e x e c u t a b l e \s + \[ w p - c o d e b o x # 1 7 5 1 \] / )
3437assert . match ( docs , / a g e n t _ b u n d l e / )
3538assert . match ( docs , / r u n n e r _ w o r k s p a c e / )
3639assert . match ( docs , / a c c e s s _ t o k e n _ r e p o s / )
3740assert . match ( docs , / r e q u i r e _ a c c e s s _ t o k e n / )
38- assert . match ( docs , / i m p l e m e n t a t i o n - s p e c i f i c \s + r u n t i m e w i r i n g , w o r k s p a c e a d a p t e r s , p l u g i n s , a n d m o d e l s e t u p s t a y b e h i n d t h e W P \s + C o d e b o x b o u n d a r y / )
39- assert . doesNotMatch ( docs , / d o c s - a g e n t | w p - c o d e b o x \/ d o c s - a g e n t - r u n n e r - r e c i p e \/ v 1 | r e c i p e _ p a t h | r e c i p e _ j s o n | w p _ c o d e b o x _ r e f | d a t a m a c h i n e | d a t a m a c h i n e | d a t a - m a c h i n e | a g e n t s a p i | s a n d b o x m o u n t s | a b i l i t y i d s | p r o v i d e r i n t e r n a l s | h o m e b o y | r e q u i r e _ a p p _ t o k e n / i)
41+ assert . match ( docs , / i m p l e m e n t a t i o n - s p e c i f i c \s + r u n t i m e \s + w i r i n g , \s + w o r k s p a c e \s + a d a p t e r s , \s + p l u g i n s , \s + a n d \s + m o d e l \s + s e t u p \s + s t a y \s + b e h i n d \s + t h e \s + W P \s + C o d e b o x \s + b o u n d a r y / )
42+ assert . doesNotMatch ( docs , / w p - c o d e b o x \/ d o c s - a g e n t - r u n n e r - r e c i p e \/ v 1 | r e c i p e _ p a t h | r e c i p e _ j s o n | w p _ c o d e b o x _ r e f | d a t a m a c h i n e | d a t a m a c h i n e | d a t a - m a c h i n e | a g e n t s a p i | s a n d b o x m o u n t s | a b i l i t y i d s | p r o v i d e r i n t e r n a l s | h o m e b o y | r e q u i r e _ a p p _ t o k e n / i)
4043
4144const tmp = await mkdtemp ( join ( tmpdir ( ) , "wp-codebox-agent-task-workflow-" ) )
4245const outputPath = join ( tmp , "github-output.txt" )
@@ -60,7 +63,7 @@ await execFileAsync("node", [new URL("../.github/scripts/run-agent-task/build-co
6063 WRITABLE_PATHS : "README.md,docs/**" ,
6164 PROVIDER : "openai" ,
6265 MODEL : "gpt-5.5" ,
63- RUNNER_WORKSPACE : '{"enabled":true,"repo":"Automattic/example-target"}' ,
66+ RUNNER_WORKSPACE_CONFIG : '{"enabled":true,"repo":"Automattic/example-target"}' ,
6467 VALIDATION_DEPENDENCIES : "" ,
6568 CONTEXT_REPOSITORIES : "[]" ,
6669 VERIFICATION_COMMANDS : '[{"command":"npm test","description":"Run checks"}]' ,
@@ -105,4 +108,57 @@ assert.match(outputs, /credential_mode<<__WP_CODEBOX_OUTPUT__\napp-token\n__WP_C
105108assert . match ( outputs , / r e q u e s t _ p a t h < < _ _ W P _ C O D E B O X _ O U T P U T _ _ \n \. c o d e b o x \/ a g e n t - t a s k - r e q u e s t \. j s o n \n _ _ W P _ C O D E B O X _ O U T P U T _ _ / )
106109assert . match ( outputs , / r e s u l t _ p a t h < < _ _ W P _ C O D E B O X _ O U T P U T _ _ \n \. c o d e b o x \/ a g e n t - t a s k - w o r k f l o w - r e s u l t \. j s o n \n _ _ W P _ C O D E B O X _ O U T P U T _ _ / )
107110
111+ async function runTaskRequest ( runnerRecipe , runAgent , dryRun ) {
112+ const cwd = await mkdtemp ( join ( tmpdir ( ) , "wp-codebox-agent-task-workflow-no-recipe-" ) )
113+ const outputPath = join ( cwd , "github-output.txt" )
114+ await writeFile ( outputPath , "" )
115+
116+ const run = execFileAsync ( "node" , [ new URL ( "../.github/scripts/run-agent-task/build-codebox-task-request.mjs" , import . meta. url ) . pathname ] , {
117+ cwd,
118+ env : {
119+ ...process . env ,
120+ GITHUB_OUTPUT : outputPath ,
121+ RUNNER_RECIPE : runnerRecipe ,
122+ AGENT_BUNDLE : "bundles/example-agent" ,
123+ TARGET_REPO : "Automattic/example-target" ,
124+ PROMPT : "Update the configured surface." ,
125+ MAX_TURNS : "12" ,
126+ STEP_BUDGET : "16" ,
127+ TIME_BUDGET_MS : "600000" ,
128+ RUN_AGENT : String ( runAgent ) ,
129+ DRY_RUN : String ( dryRun ) ,
130+ } ,
131+ } )
132+
133+ return { cwd, outputPath, run }
134+ }
135+
136+ for ( const { runAgent, dryRun, status } of [
137+ { runAgent : false , dryRun : false , status : "skipped" } ,
138+ { runAgent : false , dryRun : true , status : "skipped" } ,
139+ { runAgent : true , dryRun : true , status : "dry-run" } ,
140+ ] ) {
141+ const omittedRecipe = await runTaskRequest ( "" , runAgent , dryRun )
142+ await omittedRecipe . run
143+
144+ const omittedRecipeRequest = JSON . parse ( await readFile ( join ( omittedRecipe . cwd , ".codebox" , "agent-task-request.json" ) , "utf8" ) )
145+ const omittedRecipeResult = JSON . parse ( await readFile ( join ( omittedRecipe . cwd , ".codebox" , "agent-task-workflow-result.json" ) , "utf8" ) )
146+ assert . equal ( Object . hasOwn ( omittedRecipeRequest , "runner_recipe" ) , false )
147+ assert . equal ( omittedRecipeResult . status , status )
148+ assert . match ( await readFile ( omittedRecipe . outputPath , "utf8" ) , new RegExp ( `job_status<<__WP_CODEBOX_OUTPUT__\\n${ status } \\n__WP_CODEBOX_OUTPUT__` ) )
149+ }
150+
151+ const recipeBackedLiveRun = await runTaskRequest ( "Automattic/example-runner@abc123:ci/runner-recipe.json" , true , false )
152+ await recipeBackedLiveRun . run
153+ const recipeBackedLiveResult = JSON . parse ( await readFile ( join ( recipeBackedLiveRun . cwd , ".codebox" , "agent-task-workflow-result.json" ) , "utf8" ) )
154+ assert . equal ( recipeBackedLiveResult . status , "planned" )
155+
156+ const omittedRecipeLiveRun = await runTaskRequest ( "" , true , false )
157+ await assert . rejects ( omittedRecipeLiveRun . run , ( error : { stderr : string } ) => {
158+ assert . match ( error . stderr , / R U N N E R _ R E C I P E m a y b e o m i t t e d o n l y w h e n R U N _ A G E N T = f a l s e o r D R Y _ R U N = t r u e / )
159+ assert . match ( error . stderr , / e x e c u t a b l e w o r k f l o w i n w p - c o d e b o x P R # 1 7 5 1 m u s t l a n d / )
160+ return true
161+ } )
162+ assert . equal ( await readFile ( omittedRecipeLiveRun . outputPath , "utf8" ) , "" )
163+
108164console . log ( "agent task reusable workflow ok" )
0 commit comments