From 123729880becc47f12e6eac89b64428c844eebda Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sat, 18 Apr 2026 19:22:32 +0900 Subject: [PATCH] refactor(team-mode): remove AI slop from team-mode feature files Bulk cleanup of AI-generated code smells across src/features/team-mode. Ran the ai-slop-remover skill on 35 added source files in this feature; this commit captures the subset that actually had safe slop to remove. Every change is behavior-preserving (typecheck + full test suite green: 4861 pass). Net removal: -28 lines. Categories cleaned: redundant wrapper abstractions (resolveHomeDir, getMemberName, cloneJsonRecord, serializeResult, resolveProjectRoot), redundant defensive guards (typed-status runtime re-check, nullish-vs-nullish-or-undefined, === true on optional chains, schema-already-validated array holes), duplication (identical switch cases, dup lead-only branches consolidated via template literal, repeated Set-has+find into Map-has), dead payload fields, and needless async wrappers (return await with no try/catch, spread before new Set). Skipped preserved: concurrency-sensitive lock files (locks.ts), input-normalization boundaries, explicit per-tool factory signatures that keep pattern consistency, and fixture helpers where micro-refactor would add abstraction. Anything ambiguous left untouched per minimal-diff rule. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- src/features/team-mode/member-parser.ts | 36 +++++++++---------- src/features/team-mode/team-registry/paths.ts | 6 +--- .../team-mode/team-registry/validator.ts | 2 +- src/features/team-mode/team-runtime/create.ts | 7 ++-- .../team-runtime/shutdown-helpers.ts | 3 +- .../team-runtime/shutdown-test-fixtures.ts | 2 +- .../team-mode/team-runtime/shutdown.ts | 20 +++++------ src/features/team-mode/team-runtime/status.ts | 6 ---- .../team-mode/team-state-store/resume.ts | 10 +++--- .../team-mode/team-state-store/store.ts | 6 +--- src/features/team-mode/team-tasklist/list.ts | 13 ++++--- src/features/team-mode/team-tasklist/store.ts | 2 +- src/features/team-mode/tools/lifecycle.ts | 20 ++++------- src/features/team-mode/tools/messaging.ts | 7 ++-- src/features/team-mode/tools/query.ts | 14 +++----- 15 files changed, 63 insertions(+), 91 deletions(-) diff --git a/src/features/team-mode/member-parser.ts b/src/features/team-mode/member-parser.ts index ebc04b5b4..3e4914a9a 100644 --- a/src/features/team-mode/member-parser.ts +++ b/src/features/team-mode/member-parser.ts @@ -9,17 +9,13 @@ export class MemberValidationError extends Error { } } -function getMemberName(input: Record): string { - return typeof input.name === "string" ? input.name : "" -} - function translateMemberError( input: Record, agentEligibilityRegistry: Readonly>, ): MemberValidationError { - const name = getMemberName(input) - const hasCategory = "category" in input && input.category != null - const hasSubagentType = "subagent_type" in input && input.subagent_type != null + const name = typeof input.name === "string" ? input.name : "" + const hasCategory = input.category != null + const hasSubagentType = input.subagent_type != null const hasKind = input.kind === "category" || input.kind === "subagent_type" if (hasCategory && hasSubagentType) { @@ -66,21 +62,21 @@ export function createParseMember( agentEligibilityRegistry: Readonly>, ): (input: unknown) => TMember { return function parseMember(input: unknown) { - if (input == null || typeof input !== "object") { - throw new MemberValidationError("Member must be an object") - } + if (input == null || typeof input !== "object") { + throw new MemberValidationError("Member must be an object") + } - const raw = input as Record - const result = memberSchema.safeParse( - raw.kind === undefined && (raw.category !== undefined || raw.subagent_type !== undefined) - ? { ...raw, kind: raw.category !== undefined ? "category" : "subagent_type" } - : raw, - ) + const raw = input as Record + const result = memberSchema.safeParse( + raw.kind === undefined && (raw.category !== undefined || raw.subagent_type !== undefined) + ? { ...raw, kind: raw.category !== undefined ? "category" : "subagent_type" } + : raw, + ) - if (!result.success) { - throw translateMemberError(raw, agentEligibilityRegistry) - } + if (!result.success) { + throw translateMemberError(raw, agentEligibilityRegistry) + } - return result.data + return result.data } } diff --git a/src/features/team-mode/team-registry/paths.ts b/src/features/team-mode/team-registry/paths.ts index 2a5e42dbc..c80032575 100644 --- a/src/features/team-mode/team-registry/paths.ts +++ b/src/features/team-mode/team-registry/paths.ts @@ -11,10 +11,6 @@ type TeamSpecEntry = { path: string } -function resolveHomeDir(): string { - return homedir() -} - function getTeamDirectory(baseDir: string, teamName: string, scope: "user" | "project", projectRoot?: string): string { if (scope === "project") { return path.join(projectRoot ?? "", ".omo", "teams", teamName) @@ -24,7 +20,7 @@ function getTeamDirectory(baseDir: string, teamName: string, scope: "user" | "pr } export function resolveBaseDir(config: TeamModeConfig): string { - return config.base_dir ?? path.join(resolveHomeDir(), ".omo") + return config.base_dir ?? path.join(homedir(), ".omo") } export function getTeamSpecPath( diff --git a/src/features/team-mode/team-registry/validator.ts b/src/features/team-mode/team-registry/validator.ts index 883b7e39c..ceea0a1f0 100644 --- a/src/features/team-mode/team-registry/validator.ts +++ b/src/features/team-mode/team-registry/validator.ts @@ -95,7 +95,7 @@ export function validateDualSupport(member: Member): void { ) } - if (member.kind === "category" && trimmedPrompt !== undefined && trimmedPrompt.length < 8) { + if (member.kind === "category" && member.prompt.trim().length < 8) { throw new TeamSpecValidationError( `Member '${member.name}' category prompt must be at least 8 characters long.`, "CATEGORY_PROMPT_TOO_SHORT", diff --git a/src/features/team-mode/team-runtime/create.ts b/src/features/team-mode/team-runtime/create.ts index 43d215a60..6ece5afff 100644 --- a/src/features/team-mode/team-runtime/create.ts +++ b/src/features/team-mode/team-runtime/create.ts @@ -108,8 +108,8 @@ export async function createTeamRun( const baseDir = resolveBaseDir(config) await ensureBaseDirs(baseDir) const runtimeState = await createRuntimeState(spec, leadSessionId, await resolveSpecSource(spec, ctx, config), config) - await Promise.all(spec.members.map(async (member) => mkdir(getInboxDir(baseDir, runtimeState.teamRunId, member.name), { recursive: true }))) - await Promise.all(spec.members.map(async (member) => ensureTeamMemberFifo(runtimeState.teamRunId, member.name))) + await Promise.all(spec.members.map((member) => mkdir(getInboxDir(baseDir, runtimeState.teamRunId, member.name), { recursive: true }))) + await Promise.all(spec.members.map((member) => ensureTeamMemberFifo(runtimeState.teamRunId, member.name))) const deadlineAt = Date.now() + (config.max_wall_clock_minutes * 60_000) const resources: SpawnedMemberResource[] = spec.members.map(() => ({})) @@ -127,8 +127,7 @@ export async function createTeamRun( failure = new Error("team creation exceeded max_wall_clock_minutes") return } - const memberIndex = nextMemberIndex - nextMemberIndex += 1 + const memberIndex = nextMemberIndex++ const member = spec.members[memberIndex] if (!member) return const resource = resources[memberIndex] diff --git a/src/features/team-mode/team-runtime/shutdown-helpers.ts b/src/features/team-mode/team-runtime/shutdown-helpers.ts index 1621bdefb..49bbecdc1 100644 --- a/src/features/team-mode/team-runtime/shutdown-helpers.ts +++ b/src/features/team-mode/team-runtime/shutdown-helpers.ts @@ -57,7 +57,6 @@ export function findLatestShutdownRequestIndex( ): number { for (let index = runtimeState.shutdownRequests.length - 1; index >= 0; index -= 1) { const shutdownRequest = runtimeState.shutdownRequests[index] - if (!shutdownRequest) continue if (shutdownRequest.memberId !== memberName) continue if (requesterName !== undefined && shutdownRequest.requesterName !== requesterName) continue return index @@ -69,7 +68,7 @@ export function findLatestShutdownRequestIndex( export async function removeWorktrees(memberPaths: Array): Promise { const removedWorktrees: string[] = [] - for (const memberPath of [...new Set(memberPaths)]) { + for (const memberPath of new Set(memberPaths)) { if (!memberPath) continue await rm(memberPath, { recursive: true, force: true }) removedWorktrees.push(memberPath) diff --git a/src/features/team-mode/team-runtime/shutdown-test-fixtures.ts b/src/features/team-mode/team-runtime/shutdown-test-fixtures.ts index a4bda9abe..0324872d4 100644 --- a/src/features/team-mode/team-runtime/shutdown-test-fixtures.ts +++ b/src/features/team-mode/team-runtime/shutdown-test-fixtures.ts @@ -128,7 +128,7 @@ export async function updateMemberStatuses( export async function readInboxMessages(teamRunId: string, memberName: string, config: TeamModeConfig) { const inboxDir = getInboxDir(resolveBaseDir(config), teamRunId, memberName) const fileNames = (await readdir(inboxDir)).filter((entry) => entry.endsWith(".json")).sort() - return await Promise.all(fileNames.map(async (fileName) => { + return Promise.all(fileNames.map(async (fileName) => { const content = await readFile(path.join(inboxDir, fileName), "utf8") return MessageSchema.parse(JSON.parse(content)) })) diff --git a/src/features/team-mode/team-runtime/shutdown.ts b/src/features/team-mode/team-runtime/shutdown.ts index 0f521a8fe..920dd04ba 100644 --- a/src/features/team-mode/team-runtime/shutdown.ts +++ b/src/features/team-mode/team-runtime/shutdown.ts @@ -21,11 +21,11 @@ export async function requestShutdownOfMember( getRuntimeMember(runtimeState, requesterName) const existingRequestIndex = findLatestShutdownRequestIndex(runtimeState, targetMemberName, requesterName) - if (existingRequestIndex >= 0) { - const existingRequest = runtimeState.shutdownRequests[existingRequestIndex] - if (existingRequest?.approvedAt === undefined && existingRequest?.rejectedAt === undefined) { - return - } + const existingRequest = existingRequestIndex >= 0 + ? runtimeState.shutdownRequests[existingRequestIndex] + : undefined + if (existingRequest && existingRequest.approvedAt === undefined && existingRequest.rejectedAt === undefined) { + return } await sendMessage( @@ -37,11 +37,11 @@ export async function requestShutdownOfMember( await transitionRuntimeState(teamRunId, (currentRuntimeState) => { const duplicateRequestIndex = findLatestShutdownRequestIndex(currentRuntimeState, targetMemberName, requesterName) - if (duplicateRequestIndex >= 0) { - const duplicateRequest = currentRuntimeState.shutdownRequests[duplicateRequestIndex] - if (duplicateRequest?.approvedAt === undefined && duplicateRequest?.rejectedAt === undefined) { - return currentRuntimeState - } + const duplicateRequest = duplicateRequestIndex >= 0 + ? currentRuntimeState.shutdownRequests[duplicateRequestIndex] + : undefined + if (duplicateRequest && duplicateRequest.approvedAt === undefined && duplicateRequest.rejectedAt === undefined) { + return currentRuntimeState } return { diff --git a/src/features/team-mode/team-runtime/status.ts b/src/features/team-mode/team-runtime/status.ts index 3c66df271..edaddc914 100644 --- a/src/features/team-mode/team-runtime/status.ts +++ b/src/features/team-mode/team-runtime/status.ts @@ -64,10 +64,6 @@ function getPrimaryModelKey(bgMgr: TeamBackgroundManager | undefined, leadSessio return `${firstModel.providerID}/${firstModel.modelID}` } -function isTaskStatus(status: string): status is Task["status"] { - return status === "pending" || status === "claimed" || status === "in_progress" || status === "completed" || status === "deleted" -} - function countTasks(tasks: Task[]): TeamStatus["tasks"] { const counts = { pending: 0, @@ -79,8 +75,6 @@ function countTasks(tasks: Task[]): TeamStatus["tasks"] { } for (const task of tasks) { - if (!isTaskStatus(task.status)) continue - counts[task.status] += 1 counts.total += 1 } diff --git a/src/features/team-mode/team-state-store/resume.ts b/src/features/team-mode/team-state-store/resume.ts index 5bf479953..142317123 100644 --- a/src/features/team-mode/team-state-store/resume.ts +++ b/src/features/team-mode/team-state-store/resume.ts @@ -36,7 +36,8 @@ function extractErrorStatus(error: unknown): number | undefined { function isSessionNotFoundError(error: unknown): boolean { if (extractErrorStatus(error) === 404) return true const message = extractErrorMessage(error)?.toLowerCase() - return message?.includes("not found") === true || message?.includes("missing") === true + if (!message) return false + return message.includes("not found") || message.includes("missing") } async function runtimeDirectoryExists(teamRunId: string, config: TeamModeConfig): Promise { @@ -70,7 +71,7 @@ async function leadSessionExists( try { const response = await ctx.client.session.get({ path: { id: leadSessionId } }) - if (response.error !== undefined && response.error !== null) { + if (response.error != null) { if (isSessionNotFoundError(response.error)) return false throw toError(response.error) } @@ -130,10 +131,6 @@ export async function resumeAllTeams( break } - case "shutdown_requested": { - break - } - case "deleting": { await cleanupMemberWorktrees(runtimeState) await transitionRuntimeState(runtimeState.teamRunId, (currentRuntimeState) => ({ @@ -154,6 +151,7 @@ export async function resumeAllTeams( break } + case "shutdown_requested": case "orphaned": { break } diff --git a/src/features/team-mode/team-state-store/store.ts b/src/features/team-mode/team-state-store/store.ts index 7a39ac242..79358c00b 100644 --- a/src/features/team-mode/team-state-store/store.ts +++ b/src/features/team-mode/team-state-store/store.ts @@ -43,10 +43,6 @@ function serializeRuntimeState(runtimeState: RuntimeState): string { return `${JSON.stringify(parsedRuntimeState, null, 2)}\n` } -function determineAgentType(spec: TeamSpec, memberName: string): "leader" | "general-purpose" { - return spec.leadAgentId === memberName ? "leader" : "general-purpose" -} - function validateRuntimeState(rawState: unknown, teamRunId: string): RuntimeState { const parsedRuntimeState = RuntimeStateSchema.safeParse(rawState) if (!parsedRuntimeState.success) { @@ -84,7 +80,7 @@ export async function createRuntimeState( leadSessionId, members: spec.members.map((member) => ({ name: member.name, - agentType: determineAgentType(spec, member.name), + agentType: spec.leadAgentId === member.name ? "leader" : "general-purpose", status: "pending", color: member.color, worktreePath: member.worktreePath, diff --git a/src/features/team-mode/team-tasklist/list.ts b/src/features/team-mode/team-tasklist/list.ts index f1269a3c6..d462a655e 100644 --- a/src/features/team-mode/team-tasklist/list.ts +++ b/src/features/team-mode/team-tasklist/list.ts @@ -29,9 +29,7 @@ export async function listTasks( const parsedTasks: Task[] = [] for (const entry of entries) { - if (entry.isDirectory()) continue - if (entry.name.startsWith(".")) continue - if (!entry.name.endsWith(".json")) continue + if (entry.isDirectory() || entry.name.startsWith(".") || !entry.name.endsWith(".json")) continue const taskPath = path.join(tasksDirectory, entry.name) try { @@ -56,7 +54,12 @@ export async function listTasks( } return parsedTasks - .filter((task) => filter?.status === undefined || task.status === filter.status) - .filter((task) => filter?.owner === undefined || task.owner === filter.owner) + .filter((task) => { + if (filter?.status !== undefined && task.status !== filter.status) { + return false + } + + return filter?.owner === undefined || task.owner === filter.owner + }) .sort((leftTask, rightTask) => Number.parseInt(leftTask.id, 10) - Number.parseInt(rightTask.id, 10)) } diff --git a/src/features/team-mode/team-tasklist/store.ts b/src/features/team-mode/team-tasklist/store.ts index ddc35bd78..9a703839b 100644 --- a/src/features/team-mode/team-tasklist/store.ts +++ b/src/features/team-mode/team-tasklist/store.ts @@ -29,7 +29,7 @@ export async function createTask( await mkdir(tasksDirectory, { recursive: true, mode: 0o700 }) await mkdir(path.join(tasksDirectory, "claims"), { recursive: true, mode: 0o700 }) - return await withLock(path.join(tasksDirectory, ".lock"), async () => { + return withLock(path.join(tasksDirectory, ".lock"), async () => { const watermarkPath = path.join(tasksDirectory, HIGH_WATERMARK_FILE) const nextTaskId = (await readHighWatermark(watermarkPath)) + 1 await atomicWrite(watermarkPath, String(nextTaskId)) diff --git a/src/features/team-mode/tools/lifecycle.ts b/src/features/team-mode/tools/lifecycle.ts index ac0e2816b..a0c523a4a 100644 --- a/src/features/team-mode/tools/lifecycle.ts +++ b/src/features/team-mode/tools/lifecycle.ts @@ -57,14 +57,6 @@ function sanitizeRuntimeState(runtimeState: RuntimeState): Omit): string { - return JSON.stringify(result) -} - function parseInlineTeamSpec(rawSpec: unknown): TeamSpec { let specObject: unknown = rawSpec if (typeof rawSpec === "string") { @@ -113,14 +105,14 @@ export function createTeamCreateTool( const runtimeContext = toolContext as TeamLifecycleToolContext const leadSessionId = args.leadSessionId ?? runtimeContext.sessionID if (!leadSessionId) throw new Error("team_create requires leadSessionId or tool context sessionID") - const projectRoot = resolveProjectRoot(runtimeContext) + const projectRoot = typeof runtimeContext.directory === "string" ? runtimeContext.directory : process.cwd() const spec = args.teamName ? await loadTeamSpec(args.teamName, config, projectRoot) : parseInlineTeamSpec(args.inline_spec) const participantRuntime = await findParticipantRuntime(runtimeContext.sessionID, config) if (participantRuntime && (participantRuntime.teamName !== spec.name || participantRuntime.leadSessionId !== leadSessionId)) { throw new Error(`team_create denied: session is already a participant of team ${participantRuntime.teamRunId}`) } const runtimeState = await createTeamRun(spec, leadSessionId, { client, manager: bgMgr, directory: projectRoot }, config, bgMgr, tmuxMgr) - return serializeResult({ teamRunId: runtimeState.teamRunId, runtimeState: sanitizeRuntimeState(runtimeState) }) + return JSON.stringify({ teamRunId: runtimeState.teamRunId, runtimeState: sanitizeRuntimeState(runtimeState) }) }, }) } @@ -141,7 +133,7 @@ export function createTeamDeleteTool( const runtimeContext = toolContext as TeamLifecycleToolContext const { runtimeState, participant } = await resolveParticipant(args.teamRunId, runtimeContext.sessionID, config) if (participant?.role !== "lead") throw new Error("team_delete is lead-only") - return serializeResult({ teamRunId: args.teamRunId, teamName: runtimeState.teamName, deleted: true, ...(await deleteTeam(args.teamRunId, config, tmuxMgr, backgroundManager)) }) + return JSON.stringify({ teamRunId: args.teamRunId, teamName: runtimeState.teamName, deleted: true, ...(await deleteTeam(args.teamRunId, config, tmuxMgr, backgroundManager)) }) }, }) } @@ -158,7 +150,7 @@ export function createTeamShutdownRequestTool(config: TeamModeConfig, client: Op const { participant } = await resolveParticipant(args.teamRunId, runtimeContext.sessionID, config) if (participant?.role !== "lead") throw new Error("team_shutdown_request is lead-only") await requestShutdownOfMember(args.teamRunId, args.targetMemberName, participant.memberName, config) - return serializeResult({ teamRunId: args.teamRunId, targetMemberName: args.targetMemberName, requesterName: participant.memberName, status: "shutdown_requested" }) + return JSON.stringify({ teamRunId: args.teamRunId, targetMemberName: args.targetMemberName, requesterName: participant.memberName, status: "shutdown_requested" }) }, }) } @@ -175,7 +167,7 @@ export function createTeamApproveShutdownTool(config: TeamModeConfig, client: Op const { participant } = await resolveParticipant(args.teamRunId, runtimeContext.sessionID, config) if (!participant || (participant.role !== "lead" && participant.memberName !== args.memberName)) throw new Error("team_approve_shutdown: caller must be target member or team lead") await approveShutdown(args.teamRunId, args.memberName, participant.memberName, config) - return serializeResult({ teamRunId: args.teamRunId, memberName: args.memberName, approverName: participant.memberName, status: "shutdown_approved" }) + return JSON.stringify({ teamRunId: args.teamRunId, memberName: args.memberName, approverName: participant.memberName, status: "shutdown_approved" }) }, }) } @@ -192,7 +184,7 @@ export function createTeamRejectShutdownTool(config: TeamModeConfig, client: Ope const { participant } = await resolveParticipant(args.teamRunId, runtimeContext.sessionID, config) if (!participant || (participant.role !== "lead" && participant.memberName !== args.memberName)) throw new Error("team_reject_shutdown: caller must be target member or team lead") await rejectShutdown(args.teamRunId, args.memberName, args.reason, config) - return serializeResult({ teamRunId: args.teamRunId, memberName: args.memberName, rejectedBy: participant.memberName, reason: args.reason, status: "shutdown_rejected" }) + return JSON.stringify({ teamRunId: args.teamRunId, memberName: args.memberName, rejectedBy: participant.memberName, reason: args.reason, status: "shutdown_rejected" }) }, }) } diff --git a/src/features/team-mode/tools/messaging.ts b/src/features/team-mode/tools/messaging.ts index 2f010d0c6..ece280c53 100644 --- a/src/features/team-mode/tools/messaging.ts +++ b/src/features/team-mode/tools/messaging.ts @@ -25,12 +25,15 @@ async function resolveTeamRuntimeDetails(teamRunId: string, sessionID: string, c if (team.teamRunId !== teamRunId) continue const runtimeState = await loadRuntimeState(team.teamRunId, config) - const leadMember = runtimeState.members.find((member) => member.agentType === "leader" && runtimeState.leadSessionId === sessionID) + const isLead = runtimeState.leadSessionId === sessionID + const leadMember = isLead + ? runtimeState.members.find((member) => member.agentType === "leader") + : undefined const member = runtimeState.members.find((entry) => entry.sessionId === sessionID) return { teamRunId: runtimeState.teamRunId, - isLead: Boolean(leadMember), + isLead, senderName: leadMember?.name ?? member?.name ?? "unknown", activeMembers: runtimeState.members .filter((entry) => entry.sessionId !== undefined) diff --git a/src/features/team-mode/tools/query.ts b/src/features/team-mode/tools/query.ts index ef477e970..7718a4231 100644 --- a/src/features/team-mode/tools/query.ts +++ b/src/features/team-mode/tools/query.ts @@ -17,10 +17,6 @@ type TeamListEntry = { memberCount: number } -function getProjectRoot(): string { - return process.cwd() -} - export function createTeamStatusTool( config: TeamModeConfig, client: OpencodeClient, @@ -51,7 +47,7 @@ export function createTeamListTool(config: TeamModeConfig, client: OpencodeClien }, execute: async (args: { scope?: TeamListScope }) => { const scope = args.scope ?? "all" - const projectRoot = getProjectRoot() + const projectRoot = process.cwd() const declaredTeamSpecs = await discoverTeamSpecs(config, projectRoot) const activeTeams = await listActiveTeams(config) @@ -62,7 +58,7 @@ export function createTeamListTool(config: TeamModeConfig, client: OpencodeClien const declaredTeamSpecsByName = new Map( await Promise.all(filteredDeclaredTeamSpecs.map(async (teamSpec) => { const loadedTeamSpec = await loadTeamSpec(teamSpec.name, config, projectRoot) - return [teamSpec.name, { scope: teamSpec.scope, memberCount: loadedTeamSpec.members.length }] as const + return [teamSpec.name, loadedTeamSpec.members.length] as const })), ) @@ -72,18 +68,18 @@ export function createTeamListTool(config: TeamModeConfig, client: OpencodeClien for (const declaredTeamSpec of filteredDeclaredTeamSpecs) { const activeTeam = activeTeamsByName.get(declaredTeamSpec.name) - const declaredTeamSpecDetails = declaredTeamSpecsByName.get(declaredTeamSpec.name) + const declaredTeamSpecMemberCount = declaredTeamSpecsByName.get(declaredTeamSpec.name) teamEntries.push({ name: declaredTeamSpec.name, scope: declaredTeamSpec.scope, status: activeTeam?.status ?? "not-started", teamRunId: activeTeam?.teamRunId, - memberCount: activeTeam?.memberCount ?? declaredTeamSpecDetails?.memberCount ?? 0, + memberCount: activeTeam?.memberCount ?? declaredTeamSpecMemberCount ?? 0, }) } for (const activeTeam of activeTeams) { - if (filteredDeclaredTeamSpecs.some((teamSpec) => teamSpec.name === activeTeam.teamName)) continue + if (declaredTeamSpecsByName.has(activeTeam.teamName)) continue teamEntries.push({ name: activeTeam.teamName,