@@ -14,7 +14,7 @@ import type { PackageDotJson } from '../utils/package-json';
1414import type { WizardOptions } from '../utils/types' ;
1515import { WIZARD_INTERACTION_EVENT_NAME } from './constants' ;
1616import { analytics } from '../utils/analytics' ;
17- import { getUI } from '../ui' ;
17+ import { getUI , type SpinnerHandle } from '../ui' ;
1818import {
1919 initializeAgent ,
2020 runAgent ,
@@ -45,6 +45,7 @@ import {
4545 parseWorkflowStepsFromSkillMd ,
4646 type WizardWorkflowQueueItem ,
4747} from './workflow-queue' ;
48+ import { runSingleQueryFlow } from './legacy/single-query-runner' ;
4849
4950const WIZARD_SKILL_ID_SIGNAL = '[WIZARD-SKILL-ID]' ;
5051
@@ -276,114 +277,34 @@ export async function runAgentWizard(
276277 ? createBenchmarkPipeline ( spinner , sessionToOptions ( session ) )
277278 : undefined ;
278279
279- // ── Step 1: Bootstrap — install the skill and get its ID ──
280+ // ── Feature flag: queued workflow vs old single-query flow ──
281+ const useQueuedWorkflow = wizardFlags [ 'wizard-queued-workflow' ] === 'true' ;
282+ logToFile ( `[agent-runner] wizard-queued-workflow=${ useQueuedWorkflow } ` ) ;
280283
281- let agentResult = await runAgent (
282- agent ,
283- buildBootstrapPrompt ( config , promptContext , frameworkContext ) ,
284- sessionToOptions ( session ) ,
285- spinner ,
286- {
287- estimatedDurationMinutes : config . ui . estimatedDurationMinutes ,
288- spinnerMessage : 'Preparing integration...' ,
289- successMessage : 'Integration prepared' ,
290- errorMessage : 'Integration failed during bootstrap' ,
291- additionalFeatureQueue : [ ] ,
292- requestRemark : false ,
293- captureOutputText : true ,
294- captureSessionId : true ,
295- finalizeMiddleware : false ,
296- } ,
297- middleware ,
298- ) ;
299-
300- const queuedSessionId = agentResult . sessionId ;
301- const installedSkillId =
302- extractInstalledSkillId ( agentResult . outputText ?? '' ) ?? undefined ;
303-
304- if ( ! installedSkillId ) {
305- await wizardAbort ( {
306- message :
307- 'The wizard could not determine which integration skill was installed during bootstrap.' ,
308- error : new WizardError ( 'Bootstrap step did not emit installed skill id' ) ,
309- } ) ;
310- }
311-
312- // ── Step 2: Read SKILL.md and seed the queue from its frontmatter ──
313-
314- if ( ! agentResult . error && installedSkillId ) {
315- const skillMdPath = path . join (
316- session . installDir ,
317- '.claude' ,
318- 'skills' ,
319- installedSkillId ,
320- 'SKILL.md' ,
321- ) ;
322- const skillMdContent = fs . readFileSync ( skillMdPath , 'utf-8' ) ;
323- const workflowSteps = parseWorkflowStepsFromSkillMd ( skillMdContent ) ;
284+ let agentResult : Awaited < ReturnType < typeof runAgent > > ;
324285
325- if ( workflowSteps . length === 0 ) {
326- logToFile (
327- '[agent-runner] No workflow steps found in SKILL.md frontmatter, aborting' ,
328- ) ;
329- await wizardAbort ( {
330- message :
331- 'The installed skill does not contain workflow steps in its metadata.' ,
332- error : new WizardError ( 'No workflow steps in SKILL.md frontmatter' ) ,
333- } ) ;
334- }
335-
336- logToFile (
337- `[agent-runner] Seeded queue from SKILL.md: ${ workflowSteps
338- . map ( ( s ) => s . stepId )
339- . join ( ', ' ) } `,
286+ if ( useQueuedWorkflow ) {
287+ agentResult = await runQueuedWorkflow (
288+ agent ,
289+ config ,
290+ session ,
291+ promptContext ,
292+ frameworkContext ,
293+ spinner ,
294+ middleware ,
340295 ) ;
341-
342- // ── Step 3: Execute workflow steps + env-vars from the queue ──
343-
344- const queue = createPostBootstrapQueue ( workflowSteps ) ;
345- getUI ( ) . setWorkQueue ( queue ) ;
346-
347- while ( queue . length > 0 ) {
348- const queueItem = queue . dequeue ( ) ! ;
349-
350- getUI ( ) . setCurrentQueueItem ( { id : queueItem . id , label : queueItem . label } ) ;
351-
352- const prompt = buildQueuedPrompt (
353- queueItem ,
354- config ,
355- promptContext ,
356- installedSkillId ,
357- ) ;
358-
359- agentResult = await runAgent (
360- agent ,
361- prompt ,
362- sessionToOptions ( session ) ,
363- spinner ,
364- {
365- estimatedDurationMinutes : config . ui . estimatedDurationMinutes ,
366- spinnerMessage : getQueueSpinnerMessage ( queueItem ) ,
367- successMessage : getQueueSuccessMessage ( queueItem , config ) ,
368- errorMessage : `Integration failed during ${ queueItem . id } ` ,
369- additionalFeatureQueue :
370- queueItem . id === 'env-vars' ? session . additionalFeatureQueue : [ ] ,
371- resumeSessionId : queuedSessionId ,
372- requestRemark : queueItem . id === 'env-vars' ,
373- captureOutputText : false ,
374- captureSessionId : false ,
375- finalizeMiddleware : queue . length === 0 ,
376- } ,
377- middleware ,
378- ) ;
379-
380- getUI ( ) . completeQueueItem ( { id : queueItem . id , label : queueItem . label } ) ;
381-
382- if ( agentResult . error ) {
383- break ;
384- }
385- }
386- getUI ( ) . setCurrentQueueItem ( null ) ;
296+ } else {
297+ // OLD FLOW — single monolithic prompt (see legacy/ folder)
298+ agentResult = await runSingleQueryFlow ( {
299+ agent,
300+ config,
301+ session,
302+ options : sessionToOptions ( session ) ,
303+ spinner,
304+ promptContext,
305+ frameworkContext,
306+ middleware,
307+ } ) ;
387308 }
388309
389310 // Handle error cases detected in agent output
@@ -493,19 +414,141 @@ export async function runAgentWizard(
493414 await analytics . shutdown ( 'success' ) ;
494415}
495416
496- /**
497- * Build the integration prompt for the agent.
498- */
417+ // ── NEW FLOW: Queued workflow (wizard-queued-workflow=true) ──────────
418+
419+ type PromptContext = {
420+ frameworkVersion : string ;
421+ typescript : boolean ;
422+ projectApiKey : string ;
423+ host : string ;
424+ projectId : number ;
425+ } ;
426+
427+ async function runQueuedWorkflow (
428+ agent : Awaited < ReturnType < typeof initializeAgent > > ,
429+ config : FrameworkConfig ,
430+ session : WizardSession ,
431+ promptContext : PromptContext ,
432+ frameworkContext : Record < string , unknown > ,
433+ spinner : SpinnerHandle ,
434+ middleware ?: Parameters < typeof runAgent > [ 5 ] ,
435+ ) : Promise < Awaited < ReturnType < typeof runAgent > > > {
436+ // Step 1: Bootstrap — install the skill and get its ID
437+ let agentResult = await runAgent (
438+ agent ,
439+ buildBootstrapPrompt ( config , promptContext , frameworkContext ) ,
440+ sessionToOptions ( session ) ,
441+ spinner ,
442+ {
443+ estimatedDurationMinutes : config . ui . estimatedDurationMinutes ,
444+ spinnerMessage : 'Preparing integration...' ,
445+ successMessage : 'Integration prepared' ,
446+ errorMessage : 'Integration failed during bootstrap' ,
447+ additionalFeatureQueue : [ ] ,
448+ requestRemark : false ,
449+ captureOutputText : true ,
450+ captureSessionId : true ,
451+ finalizeMiddleware : false ,
452+ } ,
453+ middleware ,
454+ ) ;
455+
456+ const queuedSessionId = agentResult . sessionId ;
457+ const installedSkillId =
458+ extractInstalledSkillId ( agentResult . outputText ?? '' ) ?? undefined ;
459+
460+ if ( ! installedSkillId ) {
461+ await wizardAbort ( {
462+ message :
463+ 'The wizard could not determine which integration skill was installed during bootstrap.' ,
464+ error : new WizardError ( 'Bootstrap step did not emit installed skill id' ) ,
465+ } ) ;
466+ }
467+
468+ // Step 2: Read SKILL.md and seed the queue from its frontmatter
469+ if ( ! agentResult . error && installedSkillId ) {
470+ const skillMdPath = path . join (
471+ session . installDir ,
472+ '.claude' ,
473+ 'skills' ,
474+ installedSkillId ,
475+ 'SKILL.md' ,
476+ ) ;
477+ const skillMdContent = fs . readFileSync ( skillMdPath , 'utf-8' ) ;
478+ const workflowSteps = parseWorkflowStepsFromSkillMd ( skillMdContent ) ;
479+
480+ if ( workflowSteps . length === 0 ) {
481+ logToFile (
482+ '[agent-runner] No workflow steps found in SKILL.md frontmatter, aborting' ,
483+ ) ;
484+ await wizardAbort ( {
485+ message :
486+ 'The installed skill does not contain workflow steps in its metadata.' ,
487+ error : new WizardError ( 'No workflow steps in SKILL.md frontmatter' ) ,
488+ } ) ;
489+ }
490+
491+ logToFile (
492+ `[agent-runner] Seeded queue from SKILL.md: ${ workflowSteps
493+ . map ( ( s ) => s . stepId )
494+ . join ( ', ' ) } `,
495+ ) ;
496+
497+ // Step 3: Execute workflow steps + env-vars from the queue
498+ const queue = createPostBootstrapQueue ( workflowSteps ) ;
499+ getUI ( ) . setWorkQueue ( queue ) ;
500+
501+ while ( queue . length > 0 ) {
502+ const queueItem = queue . dequeue ( ) ! ;
503+
504+ getUI ( ) . setCurrentQueueItem ( { id : queueItem . id , label : queueItem . label } ) ;
505+
506+ const prompt = buildQueuedPrompt (
507+ queueItem ,
508+ config ,
509+ promptContext ,
510+ installedSkillId ,
511+ ) ;
512+
513+ agentResult = await runAgent (
514+ agent ,
515+ prompt ,
516+ sessionToOptions ( session ) ,
517+ spinner ,
518+ {
519+ estimatedDurationMinutes : config . ui . estimatedDurationMinutes ,
520+ spinnerMessage : getQueueSpinnerMessage ( queueItem ) ,
521+ successMessage : getQueueSuccessMessage ( queueItem , config ) ,
522+ errorMessage : `Integration failed during ${ queueItem . id } ` ,
523+ additionalFeatureQueue :
524+ queueItem . id === 'env-vars' ? session . additionalFeatureQueue : [ ] ,
525+ resumeSessionId : queuedSessionId ,
526+ requestRemark : queueItem . id === 'env-vars' ,
527+ captureOutputText : false ,
528+ captureSessionId : false ,
529+ finalizeMiddleware : queue . length === 0 ,
530+ } ,
531+ middleware ,
532+ ) ;
533+
534+ getUI ( ) . completeQueueItem ( { id : queueItem . id , label : queueItem . label } ) ;
535+
536+ if ( agentResult . error ) {
537+ break ;
538+ }
539+ }
540+ getUI ( ) . setCurrentQueueItem ( null ) ;
541+ }
542+
543+ return agentResult ;
544+ }
545+
546+ // ── Queued workflow prompt builders ─────────────────────────────────
547+
499548function buildQueuedPrompt (
500549 queueItem : WizardWorkflowQueueItem ,
501550 config : FrameworkConfig ,
502- context : {
503- frameworkVersion : string ;
504- typescript : boolean ;
505- projectApiKey : string ;
506- host : string ;
507- projectId : number ;
508- } ,
551+ context : PromptContext ,
509552 installedSkillId : string ,
510553) : string {
511554 if ( queueItem . kind === 'workflow' ) {
@@ -520,13 +563,7 @@ function buildQueuedPrompt(
520563
521564function buildProjectContextBlock (
522565 config : FrameworkConfig ,
523- context : {
524- frameworkVersion : string ;
525- typescript : boolean ;
526- projectApiKey : string ;
527- host : string ;
528- projectId : number ;
529- } ,
566+ context : PromptContext ,
530567 frameworkContext : Record < string , unknown > ,
531568) : string {
532569 const additionalLines = config . prompts . getAdditionalContextLines
@@ -552,13 +589,7 @@ function buildProjectContextBlock(
552589
553590function buildBootstrapPrompt (
554591 config : FrameworkConfig ,
555- context : {
556- frameworkVersion : string ;
557- typescript : boolean ;
558- projectApiKey : string ;
559- host : string ;
560- projectId : number ;
561- } ,
592+ context : PromptContext ,
562593 frameworkContext : Record < string , unknown > ,
563594) : string {
564595 return `You have access to the PostHog MCP server which provides skills to integrate PostHog into this ${
@@ -603,6 +634,8 @@ function buildWorkflowStepPrompt(
603634Read and follow this workflow reference:
604635\`.claude/skills/${ installedSkillId } /references/${ referenceFilename } \`
605636
637+ Before starting work, use TodoWrite to create your task plan. Update it as you complete each task.
638+
606639Important:
607640- Complete only this workflow step.
608641- Do NOT continue to any other workflow file.
@@ -612,13 +645,7 @@ Important:
612645
613646function buildEnvVarPrompt (
614647 config : FrameworkConfig ,
615- context : {
616- frameworkVersion : string ;
617- typescript : boolean ;
618- projectApiKey : string ;
619- host : string ;
620- projectId : number ;
621- } ,
648+ context : PromptContext ,
622649) : string {
623650 return `Continue the existing conversation.
624651
0 commit comments