99 * - What MCP servers and package manager detector to use
1010 * - What happens after the agent completes
1111 *
12- * The pipeline itself is fixed:
13- * init → health check → settings → OAuth → [skill install] →
14- * agent init → prompt → run → errors → [postRun] → outro
12+ * The pipeline runs a shared bootstrap (logging, health check, settings, OAuth,
13+ * flags, MCP url), then forks. The `orchestrator` variant routes to the
14+ * experimental task-queue runner. Every other variant runs the fixed linear
15+ * pipeline:
16+ * [skill install] → agent init → prompt → run → errors → [postRun] → outro
1517 */
1618
1719import {
@@ -29,10 +31,12 @@ import {
2931 AgentErrorType ,
3032 AgentSignals ,
3133 buildWizardMetadata ,
34+ isOrchestratorVariant ,
3235 checkAllSettingsConflicts ,
3336 backupAndFixClaudeSettings ,
3437 restoreClaudeSettings ,
3538} from './agent-interface' ;
39+ import { runOrchestrator } from '../programs/orchestrator/orchestrator-runner' ;
3640import { getCloudUrlFromRegion } from '@utils/urls' ;
3741import {
3842 evaluateWizardReadiness ,
@@ -51,7 +55,7 @@ import { getSkillsBaseUrl } from '@lib/constants';
5155import { runtimeEnv } from '@env' ;
5256import { installSkillById , type InstallSkillResult } from '@lib/wizard-tools' ;
5357import { createWizardAskBridge } from '@lib/wizard-ask-bridge' ;
54- import type { WizardRunOptions } from '@utils/types' ;
58+ import type { WizardRunOptions , CloudRegion } from '@utils/types' ;
5559
5660import type { ProgramConfig } from '@lib/programs/program-step' ;
5761import { assemblePrompt , type PromptContext } from './agent-prompt' ;
@@ -106,7 +110,7 @@ export interface ProgramRun {
106110 buildOutroData ?: (
107111 session : WizardSession ,
108112 credentials : Credentials ,
109- cloudRegion : import ( '@utils/types' ) . CloudRegion | undefined ,
113+ cloudRegion : CloudRegion | undefined ,
110114 ) => WizardSession [ 'outroData' ] ;
111115 /**
112116 * Per-run cap on `wizard_ask` invocations. Defaults to 10. The 4th call
@@ -115,6 +119,23 @@ export interface ProgramRun {
115119 maxQuestions ?: number ;
116120}
117121
122+ /**
123+ * Result of the shared bootstrap, consumed by both the linear and the
124+ * orchestrator arm. Credentials, role, and user are already applied to the
125+ * session by `bootstrapProgram`; this carries the values both arms still need.
126+ */
127+ export interface BootstrapResult {
128+ skillsBaseUrl : string ;
129+ projectApiKey : Credentials [ 'projectApiKey' ] ;
130+ host : Credentials [ 'host' ] ;
131+ accessToken : Credentials [ 'accessToken' ] ;
132+ projectId : Credentials [ 'projectId' ] ;
133+ cloudRegion : CloudRegion ;
134+ mcpUrl : string ;
135+ wizardFlags : Record < string , string > ;
136+ wizardMetadata : Record < string , string > ;
137+ }
138+
118139// ── Helpers ──────────────────────────────────────────────────────────
119140
120141/**
@@ -170,16 +191,35 @@ export async function runAgent(
170191/**
171192 * Run a program's agent pipeline.
172193 *
173- * This is the single execution path for all programs — both skill-based
174- * (revenue analytics) and framework-based (core integration). The
175- * `ProgramRun` controls what varies between them; `programConfig` carries
176- * the program-level static metadata (tool allow/disallow lists, etc.).
194+ * Runs the shared bootstrap, then forks on the `wizard-variant` flag. The
195+ * `orchestrator` variant routes to the experimental task-queue runner; every
196+ * other variant runs the linear pipeline.
177197 */
178198export async function runProgram (
179199 session : WizardSession ,
180200 config : ProgramRun ,
181201 programConfig : ProgramConfig ,
182202) : Promise < void > {
203+ const boot = await bootstrapProgram ( session , config , programConfig ) ;
204+
205+ if ( isOrchestratorVariant ( boot . wizardFlags ) ) {
206+ return runOrchestrator ( session , programConfig , boot ) ;
207+ }
208+
209+ return runLinearProgram ( session , config , programConfig , boot ) ;
210+ }
211+
212+ /**
213+ * Shared setup for both arms: logging, health check, settings conflicts, OAuth
214+ * and credentials, then the feature flags, variant metadata, and MCP url. Sets
215+ * `session.credentials`, role, and user as a side effect. Returns the values the
216+ * arms still need.
217+ */
218+ async function bootstrapProgram (
219+ session : WizardSession ,
220+ config : ProgramRun ,
221+ programConfig : ProgramConfig ,
222+ ) : Promise < BootstrapResult > {
183223 // 1. Init logging + debug
184224 initLogFile ( ) ;
185225 session . skillId = config . skillId ?? config . integrationLabel ;
@@ -283,6 +323,55 @@ export async function runProgram(
283323
284324 analytics . setGroups ( groupsFromUser ( user , host ) ) ;
285325
326+ // Feature flags, variant metadata, and MCP url. Both arms need these, and the
327+ // fork decision reads the flags.
328+ const wizardFlags = await analytics . getAllFlagsForWizard ( ) ;
329+ const wizardMetadata = buildWizardMetadata ( wizardFlags ) ;
330+
331+ const mcpUrl = session . localMcp
332+ ? 'http://localhost:8787/mcp'
333+ : runtimeEnv ( 'MCP_URL' ) ||
334+ ( cloudRegion === 'eu'
335+ ? 'https://mcp-eu.posthog.com/mcp'
336+ : 'https://mcp.posthog.com/mcp' ) ;
337+
338+ return {
339+ skillsBaseUrl,
340+ projectApiKey,
341+ host,
342+ accessToken,
343+ projectId,
344+ cloudRegion,
345+ mcpUrl,
346+ wizardFlags,
347+ wizardMetadata,
348+ } ;
349+ }
350+
351+ /**
352+ * The linear pipeline. Single execution path for all non-orchestrator programs,
353+ * both skill-based (revenue analytics) and framework-based (core integration).
354+ * The `ProgramRun` controls what varies between them; `programConfig` carries the
355+ * program-level static metadata (tool allow/disallow lists, etc.).
356+ */
357+ async function runLinearProgram (
358+ session : WizardSession ,
359+ config : ProgramRun ,
360+ programConfig : ProgramConfig ,
361+ boot : BootstrapResult ,
362+ ) : Promise < void > {
363+ const {
364+ skillsBaseUrl,
365+ projectApiKey,
366+ host,
367+ accessToken,
368+ projectId,
369+ cloudRegion,
370+ mcpUrl,
371+ wizardFlags,
372+ wizardMetadata,
373+ } = boot ;
374+
286375 // 5. Skill install (if skillId provided)
287376 let skillPath : string | undefined ;
288377 if ( config . skillId ) {
@@ -302,15 +391,6 @@ export async function runProgram(
302391
303392 // 6. Initialize agent
304393 const spinner = getUI ( ) . spinner ( ) ;
305- const wizardFlags = await analytics . getAllFlagsForWizard ( ) ;
306- const wizardMetadata = buildWizardMetadata ( wizardFlags ) ;
307-
308- const mcpUrl = session . localMcp
309- ? 'http://localhost:8787/mcp'
310- : runtimeEnv ( 'MCP_URL' ) ||
311- ( cloudRegion === 'eu'
312- ? 'https://mcp-eu.posthog.com/mcp'
313- : 'https://mcp.posthog.com/mcp' ) ;
314394
315395 const restoreSettings = ( ) => restoreClaudeSettings ( session . installDir ) ;
316396 getUI ( ) . onEnterScreen ( 'outro' , restoreSettings ) ;
0 commit comments