77 */
88
99import { execSync } from "node:child_process" ;
10- import { existsSync , readFileSync } from "node:fs" ;
11- import { join } from "node:path" ;
1210import type { ApiClient , Task } from "./api-client.js" ;
1311import * as ui from "./ui.js" ;
1412import { logError , CLI_ERR } from "./error-logger.js" ;
@@ -27,7 +25,7 @@ import { handleFetchRecentChanges, handleRecordChanges } from "./handlers/contex
2725/** An action executed before or after the agent runs */
2826export interface TemplateAction {
2927 /** Action type */
30- type : "update_task" | "update_agent" | "git_merge" | "git_push" | "git_auth_check" | "review_changes" | "spawn_reviewer" | "submit_retro" | "notify_user" | "shell" | "inject_memory" | "collect_memory" | "build_check" | " fetch_recent_changes" | "record_changes" ;
28+ type : "update_task" | "update_agent" | "git_merge" | "git_push" | "git_auth_check" | "review_changes" | "spawn_reviewer" | "submit_retro" | "notify_user" | "shell" | "inject_memory" | "collect_memory" | "fetch_recent_changes" | "record_changes" ;
3129 /** Parameters passed to the action */
3230 params ?: Record < string , unknown > ;
3331 /** Human-readable description */
@@ -86,7 +84,6 @@ const DEFAULT_TEMPLATES: AgentTemplate[] = [
8684 post_actions : [
8785 { type : "collect_memory" , when : "success" , label : "Collect agent memory" } ,
8886 { type : "record_changes" , when : "success" , label : "Record change summary for other agents" } ,
89- { type : "build_check" , when : "success" , label : "Typecheck before merge" } ,
9087 { type : "git_merge" , when : "success" , label : "Merge branch to base" } ,
9188 { type : "git_push" , when : "success" , label : "Push main to remote" } ,
9289 { type : "spawn_reviewer" , when : "success" , label : "Spawn Reviewer agent for code review" } ,
@@ -353,8 +350,6 @@ export interface ActionContext {
353350 preMergeHash ?: string ;
354351 /** Set to true if git_merge was skipped (no agent commits or metadata-only) */
355352 mergeSkipped ?: boolean ;
356- /** Set to true if build_check failed (typecheck/lint errors) — blocks merge */
357- buildFailed ?: boolean ;
358353 /** Parsed COMPLETION_JSON from agent output (set by cli.ts after agent finishes) */
359354 completionJson ?: { review_comment ?: string ; commits ?: string } ;
360355 /** Parsed RETRO_JSON from agent output (Builder's self-assessment: what went well, what to improve) */
@@ -382,10 +377,10 @@ export async function executeActions(
382377 ctx : ActionContext ,
383378 phase : "pre" | "post"
384379) : Promise < void > {
380+ const isSuccess = ctx . exitCode === 0 || ctx . exitCode === undefined ;
381+
385382 ui . info ( `[template] Executing ${ phase } _actions (${ actions . length } actions, exitCode=${ ctx . exitCode } )` ) ;
386383 for ( const action of actions ) {
387- // Re-evaluate success on each iteration (build_check may flip exitCode mid-loop)
388- const isSuccess = ctx . exitCode === 0 || ctx . exitCode === undefined ;
389384 // Check `when` condition
390385 if ( action . when === "success" && ! isSuccess ) { ui . info ( `[template] skip: ${ action . label } (when=success, but failed)` ) ; continue ; }
391386 if ( action . when === "failure" && isSuccess ) continue ;
@@ -510,41 +505,6 @@ export async function executeActions(
510505 } catch { /* non-fatal */ }
511506 break ;
512507 }
513- case "build_check" : {
514- if ( ctx . mergeSkipped || ctx . buildFailed ) { ui . info ( `[${ phase } ] ${ label } : skipped` ) ; break ; }
515- const worktreeDir = ctx . config . workingDir ;
516- try {
517- // Detect available checks from package.json
518- const pkgPath = join ( worktreeDir , "package.json" ) ;
519- if ( existsSync ( pkgPath ) ) {
520- const pkg = JSON . parse ( readFileSync ( pkgPath , "utf-8" ) ) ;
521- const scripts = pkg . scripts ?? { } ;
522- if ( scripts . typecheck ) {
523- execSync ( "npm run typecheck" , { cwd : worktreeDir , stdio : "pipe" , timeout : 120_000 } ) ;
524- ui . info ( `[${ phase } ] ${ label } : typecheck passed` ) ;
525- } else if ( scripts . build ) {
526- execSync ( "npm run build" , { cwd : worktreeDir , stdio : "pipe" , timeout : 120_000 } ) ;
527- ui . info ( `[${ phase } ] ${ label } : build passed` ) ;
528- } else {
529- ui . info ( `[${ phase } ] ${ label } : no typecheck/build script found — skipped` ) ;
530- }
531- } else {
532- ui . info ( `[${ phase } ] ${ label } : no package.json — skipped` ) ;
533- }
534- } catch ( buildErr ) {
535- const msg = buildErr instanceof Error ? buildErr . message : String ( buildErr ) ;
536- const stderr = ( buildErr as { stderr ?: Buffer } ) ?. stderr ?. toString ( ) ?? "" ;
537- const errorLines = stderr . split ( "\n" ) . filter ( ( l : string ) => l . includes ( "error TS" ) ) . slice ( 0 , 10 ) . join ( "\n" ) ;
538- ui . error ( `[${ phase } ] ${ label } : FAILED — blocking merge` ) ;
539- if ( errorLines ) ui . error ( errorLines ) ;
540- logError ( CLI_ERR . ACTION_FAILED , `build_check failed: ${ msg } ` , { taskId : ctx . task . id } , buildErr ) ;
541- ctx . buildFailed = true ;
542- ctx . mergeSkipped = true ;
543- // Treat as failure so remaining success-only actions skip and failure actions run
544- ctx . exitCode = 1 ;
545- }
546- break ;
547- }
548508 case "shell" : {
549509 const cmd = action . params ?. command as string | undefined ;
550510 if ( cmd ) {
0 commit comments