fix(team): materialize recovered opencode lane manifests
This commit is contained in:
parent
7dc4a1976d
commit
752ae9ea4b
2 changed files with 106 additions and 99 deletions
|
|
@ -18477,6 +18477,16 @@ export class TeamProvisioningService {
|
|||
`[${params.teamName}] Failed to recover missing OpenCode lane index ${params.laneId}: ${getErrorMessage(error)}`
|
||||
);
|
||||
});
|
||||
await setOpenCodeRuntimeActiveRunManifest({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
teamName: params.teamName,
|
||||
laneId: params.laneId,
|
||||
runId: params.persistedMember.runtimeRunId ?? null,
|
||||
}).catch((error: unknown) => {
|
||||
logger.warn(
|
||||
`[${params.teamName}] Failed to materialize recovered OpenCode lane manifest ${params.laneId}: ${getErrorMessage(error)}`
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
...runtimeEvidence,
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const second = await secondPromise;
|
||||
expect(second.runId).toBeTruthy();
|
||||
expect(second.runId).not.toBe(firstRunId);
|
||||
await waitForCondition(() => adapter.launchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.launchInputs.length === 2);
|
||||
|
||||
expect(svc.isTeamAlive(teamName)).toBe(true);
|
||||
expect(svc.getAliveTeams()).toEqual([teamName]);
|
||||
|
|
@ -1372,7 +1372,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
() => undefined
|
||||
);
|
||||
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
const cancelledRunId = adapter.pendingLaunchInputs.find(
|
||||
(input) => input.teamName === cancelledTeamName
|
||||
)?.runId;
|
||||
|
|
@ -1461,7 +1461,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
() => undefined
|
||||
);
|
||||
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
const cancelledRunId = adapter.pendingLaunchInputs.find(
|
||||
(input) => input.teamName === cancelledTeamName
|
||||
)?.runId;
|
||||
|
|
@ -1805,7 +1805,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
},
|
||||
() => undefined
|
||||
);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
const firstRunId = adapter.pendingLaunchInputs.find(
|
||||
(input) => input.teamName === firstTeamName
|
||||
)?.runId;
|
||||
|
|
@ -1817,7 +1817,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
svc.stopAllTeams();
|
||||
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
expect(adapter.stopInputs.map((input) => input.teamName).sort()).toEqual([
|
||||
firstTeamName,
|
||||
secondTeamName,
|
||||
|
|
@ -1867,7 +1867,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
expect(svc.getAliveTeams()).toEqual([]);
|
||||
|
||||
adapter.releaseStops();
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await expect(
|
||||
readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), firstTeamName)
|
||||
).resolves.toMatchObject({
|
||||
|
|
@ -1909,7 +1909,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
},
|
||||
() => undefined
|
||||
);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
const firstRunId = adapter.pendingLaunchInputs.find(
|
||||
(input) => input.teamName === firstTeamName
|
||||
)?.runId;
|
||||
|
|
@ -1921,7 +1921,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
svc.stopAllTeams();
|
||||
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
expect(adapter.stopInputs.map((input) => input.teamName).sort()).toEqual([
|
||||
firstTeamName,
|
||||
secondTeamName,
|
||||
|
|
@ -1941,7 +1941,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
adapter.releaseLaunches();
|
||||
await expect(firstPromise).resolves.toEqual({ runId: firstRunId });
|
||||
await expect(secondPromise).resolves.toEqual({ runId: secondRunId });
|
||||
await waitForCondition(() => adapter.launchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.launchInputs.length === 2);
|
||||
|
||||
expect(svc.getAliveTeams()).toEqual([]);
|
||||
await expect(
|
||||
|
|
@ -2198,11 +2198,11 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(firstRun);
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(secondRun);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
|
||||
svc.stopAllTeams();
|
||||
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
expect(adapter.stopInputs.map((input) => input.teamName).sort()).toEqual([
|
||||
firstTeamName,
|
||||
secondTeamName,
|
||||
|
|
@ -2214,7 +2214,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
expect(svc.getAliveTeams()).toEqual([]);
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 1);
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 2);
|
||||
|
||||
await expect(
|
||||
readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), firstTeamName)
|
||||
|
|
@ -2598,17 +2598,13 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
}),
|
||||
},
|
||||
});
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:tom',
|
||||
state: 'active',
|
||||
});
|
||||
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -5613,14 +5609,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await svc.getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'spawning',
|
||||
launchState: 'starting',
|
||||
bootstrapConfirmed: false,
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
hardFailure: false,
|
||||
livenessSource: 'heartbeat',
|
||||
});
|
||||
expect(statuses.statuses.bob?.livenessSource).not.toBe('heartbeat');
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -5736,14 +5732,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await new TeamProvisioningService().getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
status: 'spawning',
|
||||
launchState: 'starting',
|
||||
bootstrapConfirmed: false,
|
||||
hardFailure: false,
|
||||
livenessSource: 'heartbeat',
|
||||
});
|
||||
expect(statuses.statuses.bob?.lastHeartbeatAt).toBeUndefined();
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -6381,14 +6377,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await new TeamProvisioningService().getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
bootstrapConfirmed: false,
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
hardFailure: false,
|
||||
lastHeartbeatAt: newerSignalAt,
|
||||
});
|
||||
expect(statuses.statuses.bob?.lastHeartbeatAt).not.toBe(newerSignalAt);
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -6524,14 +6520,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await svc.getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
bootstrapConfirmed: false,
|
||||
hardFailure: false,
|
||||
lastHeartbeatAt: newerSignalAt,
|
||||
});
|
||||
expect(statuses.statuses.bob?.lastHeartbeatAt).toBeUndefined();
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -6666,14 +6662,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await new TeamProvisioningService().getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
bootstrapConfirmed: false,
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
hardFailure: false,
|
||||
lastHeartbeatAt: signalAt,
|
||||
});
|
||||
expect(statuses.statuses.bob?.lastHeartbeatAt).not.toBe(signalAt);
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -6807,14 +6803,14 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const statuses = await svc.getMemberSpawnStatuses(teamName);
|
||||
|
||||
expect(statuses.expectedMembers).toEqual(['alice', 'bob']);
|
||||
expect(statuses.teamLaunchState).toBe('clean_success');
|
||||
expect(statuses.teamLaunchState).toBe('partial_pending');
|
||||
expect(statuses.statuses.bob).toMatchObject({
|
||||
status: 'online',
|
||||
launchState: 'confirmed_alive',
|
||||
bootstrapConfirmed: true,
|
||||
status: 'waiting',
|
||||
launchState: 'runtime_pending_bootstrap',
|
||||
bootstrapConfirmed: false,
|
||||
hardFailure: false,
|
||||
lastHeartbeatAt: signalAt,
|
||||
});
|
||||
expect(statuses.statuses.bob?.lastHeartbeatAt).toBeUndefined();
|
||||
expect(statuses.statuses['bob-2']).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -10075,7 +10071,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await svc.cancelProvisioning(cancelledRun.runId);
|
||||
|
||||
await waitForCondition(
|
||||
() => adapter.stopInputs.filter((input) => input.teamName === cancelledTeamName).length === 2
|
||||
() => adapter.stopInputs.filter((input) => input.teamName === cancelledTeamName).length === 1
|
||||
);
|
||||
expect(adapter.stopInputs.some((input) => input.teamName === survivingTeamName)).toBe(false);
|
||||
|
||||
|
|
@ -10195,7 +10191,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(cancelledRun);
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(survivingRun);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(cancelledRun.runId);
|
||||
|
||||
|
|
@ -10998,7 +10994,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await waitForCondition(() => adapter.launchInputs.length === 2);
|
||||
|
||||
svc.stopTeam(teamName);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => !svc.isTeamAlive(teamName));
|
||||
expect((await readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), teamName)).lanes).toEqual({});
|
||||
|
||||
|
|
@ -11594,11 +11590,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
)}\n`,
|
||||
'utf8'
|
||||
);
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:tom',
|
||||
state: 'active',
|
||||
});
|
||||
const inboxDir = path.join(getTeamsBasePath(), teamName, 'inboxes');
|
||||
await fs.mkdir(inboxDir, { recursive: true });
|
||||
|
|
@ -12158,11 +12152,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await writeMixedTeamConfig({ teamName, projectPath });
|
||||
await writeTeamMeta(teamName, projectPath);
|
||||
await writeMembersMeta(teamName);
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -12202,11 +12194,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
state: 'active',
|
||||
diagnostics: ['stale removed bob lane index entry'],
|
||||
});
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:tom',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -12257,11 +12247,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
state: 'active',
|
||||
diagnostics: ['stale active lane index while members meta removed bob'],
|
||||
});
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:tom',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -12312,11 +12300,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
state: 'active',
|
||||
diagnostics: ['orphan active lane index entry without roster member'],
|
||||
});
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:tom',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -12360,11 +12346,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await writeMixedTeamConfig({ teamName, projectPath });
|
||||
await writeTeamMeta(teamName, projectPath);
|
||||
await writeMembersMeta(teamName);
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const restartedService = new TeamProvisioningService();
|
||||
|
|
@ -12398,11 +12382,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await writeMixedTeamConfig({ teamName, projectPath, removedMembers: ['bob'] });
|
||||
await writeTeamMeta(teamName, projectPath);
|
||||
await writeMembersMeta(teamName, { removedMembers: ['bob'] });
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
diagnostics: ['stale active lane index while bob was removed'],
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
|
|
@ -12451,11 +12433,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await writeMixedTeamConfig({ teamName, projectPath });
|
||||
await writeTeamMeta(teamName, projectPath);
|
||||
await writeMembersMeta(teamName);
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const svc = new TeamProvisioningService();
|
||||
|
|
@ -12488,11 +12468,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
const teamName = 'mixed-opencode-direct-message-meta-only-recovered-safe-e2e';
|
||||
await writeTeamMeta(teamName, projectPath);
|
||||
await writeMembersMeta(teamName, { memberCwd: projectPath });
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
const adapter = new FakeOpenCodeRuntimeAdapter();
|
||||
const svc = new TeamProvisioningService();
|
||||
|
|
@ -12529,11 +12507,9 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
await fs.mkdir(degradedProjectPath, { recursive: true });
|
||||
await writeTeamMeta(activeTeamName, activeProjectPath);
|
||||
await writeMembersMeta(activeTeamName, { memberCwd: activeProjectPath });
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
await upsertActiveOpenCodeRuntimeLaneForTest({
|
||||
teamName: activeTeamName,
|
||||
laneId: 'secondary:opencode:bob',
|
||||
state: 'active',
|
||||
});
|
||||
await writeTeamMeta(degradedTeamName, degradedProjectPath);
|
||||
await writeMembersMeta(degradedTeamName, { memberCwd: degradedProjectPath });
|
||||
|
|
@ -15165,7 +15141,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(stoppedRun);
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(survivingRun);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
svc.stopTeam(stoppedTeamName);
|
||||
|
||||
|
|
@ -15481,7 +15457,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
});
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.launchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.launchInputs.length === 1);
|
||||
|
||||
const statuses = await svc.getMemberSpawnStatuses(teamName);
|
||||
expect(statuses.teamLaunchState).toBe('partial_failure');
|
||||
|
|
@ -15677,18 +15653,18 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, run);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(run);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(run.runId);
|
||||
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
expect(adapter.stopInputs.map((input) => input.laneId).sort()).toEqual([
|
||||
'secondary:opencode:bob',
|
||||
]);
|
||||
expect(svc.isTeamAlive(teamName)).toBe(false);
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.launchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.launchInputs.length === 1);
|
||||
|
||||
const statuses = await svc.getMemberSpawnStatuses(teamName);
|
||||
expect(statuses.teamLaunchState).not.toBe('clean_success');
|
||||
|
|
@ -15709,11 +15685,11 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, run);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(run);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(run.runId);
|
||||
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
expect(adapter.stopInputs.map((input) => input.laneId).sort()).toEqual([
|
||||
'secondary:opencode:bob',
|
||||
]);
|
||||
|
|
@ -15808,7 +15784,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, cancelledRun);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(cancelledRun);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(cancelledRun.runId);
|
||||
|
||||
|
|
@ -15888,7 +15864,7 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(cancelledRun);
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(survivingRun);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(cancelledRun.runId);
|
||||
|
||||
|
|
@ -16218,13 +16194,13 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, run);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(run);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(run.runId);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 2);
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 1);
|
||||
|
||||
await expect(readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), teamName)).resolves.toMatchObject(
|
||||
{
|
||||
|
|
@ -16255,13 +16231,13 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, run);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(run);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(run.runId);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 2);
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 1);
|
||||
|
||||
await expect(readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), teamName)).resolves.toMatchObject(
|
||||
{
|
||||
|
|
@ -16306,13 +16282,13 @@ describe('Team agent launch matrix safe e2e', () => {
|
|||
trackLiveRun(svc, run);
|
||||
|
||||
await (svc as any).launchMixedSecondaryLaneIfNeeded(run);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 2);
|
||||
await waitForCondition(() => adapter.pendingLaunchInputs.length === 1);
|
||||
|
||||
await svc.cancelProvisioning(run.runId);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 2);
|
||||
await waitForCondition(() => adapter.stopInputs.length === 1);
|
||||
|
||||
adapter.releaseLaunches();
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 2);
|
||||
await waitForCondition(() => adapter.rejectedLaunchCount === 1);
|
||||
|
||||
await expect(readOpenCodeRuntimeLaneIndex(getTeamsBasePath(), teamName)).resolves.toMatchObject(
|
||||
{
|
||||
|
|
@ -17108,6 +17084,27 @@ class RejectingBlockingOpenCodeRuntimeAdapter extends FakeOpenCodeRuntimeAdapter
|
|||
}
|
||||
}
|
||||
|
||||
async function upsertActiveOpenCodeRuntimeLaneForTest(input: {
|
||||
teamName: string;
|
||||
laneId: string;
|
||||
runId?: string | null;
|
||||
diagnostics?: string[];
|
||||
}): Promise<void> {
|
||||
await upsertOpenCodeRuntimeLaneIndexEntry({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
teamName: input.teamName,
|
||||
laneId: input.laneId,
|
||||
state: 'active',
|
||||
diagnostics: input.diagnostics,
|
||||
});
|
||||
await setOpenCodeRuntimeActiveRunManifest({
|
||||
teamsBasePath: getTeamsBasePath(),
|
||||
teamName: input.teamName,
|
||||
laneId: input.laneId,
|
||||
runId: input.runId ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
async function waitForCondition(assertion: () => boolean | Promise<boolean>): Promise<void> {
|
||||
const startedAt = Date.now();
|
||||
while (Date.now() - startedAt < 5_000) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue