fix(team): use source runtime for live smoke

This commit is contained in:
777genius 2026-05-19 20:55:15 +03:00
parent 8b97f5c016
commit 0742bcc191
11 changed files with 148 additions and 27 deletions

View file

@ -26,6 +26,8 @@ Live team smoke runtime:
- Use the orchestrator source launcher by default for live/dev smoke loops: `/Users/belief/dev/projects/claude/agent_teams_orchestrator/cli-source`
- The source launcher runs `src/entrypoints/cli.tsx` through Bun, so it reflects local orchestrator source edits immediately and cannot accidentally test stale `dist` output.
- The source launcher normalizes inherited `NODE_ENV=production` to `NODE_ENV=development`. Release or production-like smoke must use the built wrapper instead of preserving production mode on source.
- Local live/prove scripts should use `scripts/lib/live-smoke-runtime.mjs`, which defaults to `cli-source` unless `CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH` is explicitly set.
- Source-mode teammate startup can be slower than bundled startup. Live smoke harnesses may raise `CLAUDE_TEAM_PROCESS_RUNTIME_READY_TIMEOUT_MS` and `CLAUDE_TEAM_PROCESS_INBOX_POLLER_READY_TIMEOUT_MS` when the test is validating source behavior instead of watchdog latency.
- Use the built wrapper only for release or production-like smoke checks. Build first in `/Users/belief/dev/projects/claude/agent_teams_orchestrator` with `bun run build`, then set `CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH=/Users/belief/dev/projects/claude/agent_teams_orchestrator/cli`.
- Do not use `cli-dev` or `bun run build:dev` as proof for the production wrapper. `cli` reads `dist/local-cli/cli.js`; `cli-dev` reads `dist/local-cli-dev/cli.js`.

View file

@ -95,6 +95,10 @@ export CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH=/Users/belief/dev/projects/claud
The source launcher executes `src/entrypoints/cli.tsx` through Bun. It is the right default for local
debug loops, live model/provider checks, and cross-repo runtime fixes.
It normalizes inherited `NODE_ENV=production` to `NODE_ENV=development`, because source smoke is a
dev/runtime validation path. If you need production semantics, run the release smoke path below.
Local live/prove scripts should resolve their default CLI through `scripts/lib/live-smoke-runtime.mjs`,
which points at `cli-source` unless `CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH` is explicitly set.
Source-mode teammate startup can be slower than bundled startup, so live smoke harnesses may set
`CLAUDE_TEAM_PROCESS_RUNTIME_READY_TIMEOUT_MS` and
`CLAUDE_TEAM_PROCESS_INBOX_POLLER_READY_TIMEOUT_MS` to larger values when they are validating source

View file

@ -0,0 +1,37 @@
import path from 'node:path';
export function resolveLiveSmokeOrchestratorCliPath({
env = process.env,
repoRoot,
} = {}) {
const explicitCliPath = env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim();
if (explicitCliPath) {
return explicitCliPath;
}
const configuredRuntimeRoot = env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const baseRepoRoot = repoRoot ? path.resolve(repoRoot) : process.cwd();
const runtimeRoot = configuredRuntimeRoot
? path.resolve(configuredRuntimeRoot)
: path.resolve(baseRepoRoot, '..', 'agent_teams_orchestrator');
return path.join(runtimeRoot, 'cli-source');
}
export function resolveReleaseSmokeOrchestratorCliPath({
env = process.env,
repoRoot,
} = {}) {
const explicitCliPath = env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim();
if (explicitCliPath) {
return explicitCliPath;
}
const configuredRuntimeRoot = env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const baseRepoRoot = repoRoot ? path.resolve(repoRoot) : process.cwd();
const runtimeRoot = configuredRuntimeRoot
? path.resolve(configuredRuntimeRoot)
: path.resolve(baseRepoRoot, '..', 'agent_teams_orchestrator');
return path.join(runtimeRoot, 'cli');
}

View file

@ -5,18 +5,24 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
AGENT_CLI_LAUNCH_LIVE_E2E: '1',
CLAUDE_TEAM_CLI_FLAVOR: process.env.CLAUDE_TEAM_CLI_FLAVOR || 'agent_teams_orchestrator',
CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH:
process.env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH || path.join(siblingOrchestrator, 'cli'),
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running agent CLI launch live smoke');
console.log(`Claude runtime: ${env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH}`);

View file

@ -5,6 +5,7 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import {
exitForSkippedPreflight,
preflightOpenCodeLiveEnvironment,
@ -12,8 +13,6 @@ import {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
@ -26,8 +25,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running OpenCode mixed recovery live smoke');

View file

@ -5,6 +5,7 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import {
exitForSkippedPreflight,
preflightOpenCodeLiveEnvironment,
@ -12,8 +13,6 @@ import {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
@ -33,8 +32,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running OpenCode semantic gauntlet live smoke');

View file

@ -5,6 +5,7 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import {
exitForSkippedPreflight,
preflightOpenCodeLiveEnvironment,
@ -12,8 +13,6 @@ import {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
@ -25,8 +24,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running OpenCode semantic messaging live smoke');

View file

@ -5,6 +5,7 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import {
exitForSkippedPreflight,
preflightOpenCodeLiveEnvironment,
@ -12,8 +13,6 @@ import {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
@ -24,8 +23,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running OpenCode semantic model matrix live smoke');

View file

@ -5,6 +5,7 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import {
exitForSkippedPreflight,
preflightOpenCodeLiveEnvironment,
@ -12,8 +13,6 @@ import {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const env = {
...process.env,
@ -25,8 +24,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running OpenCode team provisioning live smoke');

View file

@ -7,12 +7,11 @@ import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { resolveLiveSmokeOrchestratorCliPath } from './lib/live-smoke-runtime.mjs';
import { preflightOpenCodeLiveEnvironment } from './lib/opencode-live-preflight.mjs';
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(scriptDir, '..');
const orchestratorRoot = process.env.CLAUDE_DEV_RUNTIME_ROOT?.trim();
const siblingOrchestrator = path.resolve(repoRoot, '..', 'agent_teams_orchestrator');
const requestedOrder =
process.env.PROVIDER_LAUNCH_STRESS_ORDER?.trim() || 'anthropic,codex,opencode,mixed';
@ -31,8 +30,10 @@ const env = {
};
if (!env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH?.trim()) {
const runtimeRoot = orchestratorRoot ? path.resolve(orchestratorRoot) : siblingOrchestrator;
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = path.join(runtimeRoot, 'cli');
env.CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH = resolveLiveSmokeOrchestratorCliPath({
env,
repoRoot,
});
}
console.log('Running provider launch stress live smoke');

View file

@ -0,0 +1,66 @@
// @vitest-environment node
import * as path from 'path';
import { pathToFileURL } from 'url';
import { describe, expect, it } from 'vitest';
interface LiveSmokeRuntimeModule {
resolveLiveSmokeOrchestratorCliPath(input?: {
env?: NodeJS.ProcessEnv;
repoRoot?: string;
}): string;
resolveReleaseSmokeOrchestratorCliPath(input?: {
env?: NodeJS.ProcessEnv;
repoRoot?: string;
}): string;
}
describe('live smoke runtime launcher paths', () => {
const repoRoot = '/Users/belief/dev/projects/claude/claude_team';
const siblingRuntimeRoot = '/Users/belief/dev/projects/claude/agent_teams_orchestrator';
it('defaults live smoke to the source launcher', async () => {
const { resolveLiveSmokeOrchestratorCliPath } = await loadModule();
expect(resolveLiveSmokeOrchestratorCliPath({ env: {}, repoRoot })).toBe(
path.join(siblingRuntimeRoot, 'cli-source')
);
});
it('uses CLAUDE_DEV_RUNTIME_ROOT with cli-source for live smoke', async () => {
const { resolveLiveSmokeOrchestratorCliPath } = await loadModule();
expect(
resolveLiveSmokeOrchestratorCliPath({
env: { CLAUDE_DEV_RUNTIME_ROOT: '/tmp/runtime-source' },
repoRoot,
})
).toBe(path.join('/tmp/runtime-source', 'cli-source'));
});
it('keeps explicit CLI path overrides authoritative', async () => {
const { resolveLiveSmokeOrchestratorCliPath } = await loadModule();
expect(
resolveLiveSmokeOrchestratorCliPath({
env: { CLAUDE_AGENT_TEAMS_ORCHESTRATOR_CLI_PATH: ' /custom/runtime/cli ' },
repoRoot,
})
).toBe('/custom/runtime/cli');
});
it('keeps release smoke pointed at the built wrapper', async () => {
const { resolveReleaseSmokeOrchestratorCliPath } = await loadModule();
expect(resolveReleaseSmokeOrchestratorCliPath({ env: {}, repoRoot })).toBe(
path.join(siblingRuntimeRoot, 'cli')
);
});
});
async function loadModule(): Promise<LiveSmokeRuntimeModule> {
const moduleUrl = pathToFileURL(
path.join(process.cwd(), 'scripts/lib/live-smoke-runtime.mjs')
).href;
return (await import(`${moduleUrl}?t=${Date.now()}`)) as LiveSmokeRuntimeModule;
}