import { LAB_REPRESENTATIVE_AGENT, isLabRepresentativeAgent } from "../../agents/identity.js";
import { assertLabMeetingAllowsInternalWork } from "../../features/lab-meeting/index.js";
import { appendEvent } from "../../features/observability/index.js";
import { acceptTeamSpec, addTeamMemberToRuntime, appendTeamConversationEntry, createDynamicTeamRuntime, finishDynamicTeamLaunch, buildDynamicMemberContract, appendTeamLaunchLedgerEntry, createTeamLaunchId, isReplaceableDefaultTeamRuntime, loadTeamRuntime, recordTeamMemberLaunch, sendTeamMessage, validateTeamSpec, } from "../../features/team-mode/index.js";
import { compactModelRoute, currentModelFromRun, resolveModelRoute } from "../../features/model-routing/index.js";
import { planContextInjection, renderContextAttachments, upsertContextBundle } from "../../features/context-ledger/index.js";
import { nowIso } from "../../shared/index.js";
import { executeDelegate } from "./delegation.js";
import { jsonToolOutput, requireSeedRun } from "./common.js";
export async function executeTeamCreate(store, args, context, runtime) {
    const run = await requireSeedRun(store, context, args.run_id);
    const gate = await assertLabMeetingAllowsInternalWork(store, run.run_id, "seed_team_create");
    if (!gate.allowed) {
        await appendEvent(store, run.run_id, {
            type: "lab_meeting_internal_work_blocked",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: gate.reason,
            metadata: { action: "seed_team_create", meeting_path: gate.meeting_path },
        });
        return jsonToolOutput("SEED team create paused for Lab Meeting", {
            run_id: run.run_id,
            status: "blocked",
            reason: gate.reason,
            meeting_path: gate.meeting_path,
        });
    }
    if (!isLabRepresentativeAgent(context.agent)) {
        await appendEvent(store, run.run_id, {
            type: "team_create_rejected",
            actor: context.agent,
            session_id: context.sessionID,
            summary: "seed_team_create is restricted to Lab-Representative.",
        });
        throw new Error("seed_team_create is Lab-Representative-only; ask Lab-Representative to create the team.");
    }
    if (!context.sessionID)
        throw new Error("seed_team_create requires an OpenCode parent session id.");
    if (!store.config.team_mode.enabled)
        throw new Error("seed_team_create is disabled by team_mode.enabled=false.");
    const rawArgs = args;
    if (rawArgs.workflow_template !== undefined) {
        throw new Error("seed_team_create requires inline_spec. workflow_template may appear only as metadata inside inline_spec.workflow_template.");
    }
    if (args.inline_spec === undefined) {
        throw new Error("seed_team_create requires inline_spec.");
    }
    const specInput = args.inline_spec;
    const existingRuntime = await loadTeamRuntime(store, run.run_id);
    if (existingRuntime && (existingRuntime.status === "creating" || existingRuntime.status === "active" || existingRuntime.status === "failed") && !isReplaceableDefaultTeamRuntime(existingRuntime)) {
        await appendEvent(store, run.run_id, {
            type: "team_create_rejected",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: `Existing team runtime blocks launch: ${existingRuntime.status}`,
            metadata: { team_id: existingRuntime.team_id, status: existingRuntime.status },
        });
        throw new Error(`team runtime already exists for run ${run.run_id}: ${existingRuntime.status}`);
    }
    if (existingRuntime && isReplaceableDefaultTeamRuntime(existingRuntime)) {
        await appendEvent(store, run.run_id, {
            type: "team_default_runtime_replaced",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: "Replacing the default Lab-Representative-only runtime with a dynamic team runtime.",
            metadata: {
                previous_member_count: existingRuntime.members.length,
                previous_status: existingRuntime.status,
            },
        });
    }
    const accepted = await acceptTeamSpec(store, run.run_id, specInput, {
        actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
        sessionId: context.sessionID,
    });
    if (!accepted.accepted) {
        const issueSummary = accepted.validation.issues.map((issue) => `${issue.code}: ${issue.message}`).join("; ");
        throw new Error(`seed_team_create rejected invalid team spec: ${issueSummary}`);
    }
    const specRef = relativeRunPath(accepted.json_path, store, run.run_id);
    const specMarkdownRef = relativeRunPath(accepted.markdown_path, store, run.run_id);
    await createDynamicTeamRuntime(store, run.run_id, {
        spec: accepted.spec,
        parentSessionId: context.sessionID,
        specRef,
        specMarkdownRef,
    });
    await appendEvent(store, run.run_id, {
        type: "team_create_started",
        actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
        session_id: context.sessionID,
        summary: `${accepted.spec.team_name}: launching ${accepted.spec.members.length} member(s)`,
        metadata: { team_id: accepted.spec.team_id, spec_ref: specRef },
    });
    const launches = await launchMembersBounded(store, run, accepted.spec, context, runtime, [specRef, specMarkdownRef]);
    const failures = launches.filter((launch) => launch.status === "failed");
    const cleanupInstructions = failures.length
        ? [
            "Run /seed-status to inspect partial team state.",
            "Use seed_background_cancel for any queued child sessions that should not continue.",
            "Fix the launch blocker, then rerun seed_team_create with a new team id or stop/cleanup the current team runtime.",
        ]
        : undefined;
    const runtimeState = await finishDynamicTeamLaunch(store, run.run_id, {
        status: failures.length ? "failed" : "active",
        launchError: failures.length ? `${failures.length} member launch(es) failed.` : undefined,
        cleanupInstructions,
    });
    await appendEvent(store, run.run_id, {
        type: failures.length ? "team_create_failed" : "team_create_completed",
        actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
        session_id: context.sessionID,
        summary: failures.length
            ? `${accepted.spec.team_name}: ${failures.length} member launch(es) failed`
            : `${accepted.spec.team_name}: all member launches queued`,
        metadata: {
            team_id: accepted.spec.team_id,
            launches,
            cleanup_instructions: cleanupInstructions,
        },
    });
    return jsonToolOutput("SEED team create", {
        run_id: run.run_id,
        team_id: accepted.spec.team_id,
        status: runtimeState.status,
        runtime: runtimeState,
        launches,
        cleanup_instructions: cleanupInstructions,
    });
}
export async function executeTeamMemberAdd(store, args, context, runtime) {
    const run = await requireSeedRun(store, context, args.run_id);
    const gate = await assertLabMeetingAllowsInternalWork(store, run.run_id, "seed_team_member_add");
    if (!gate.allowed) {
        await appendEvent(store, run.run_id, {
            type: "lab_meeting_internal_work_blocked",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: gate.reason,
            metadata: { action: "seed_team_member_add", meeting_path: gate.meeting_path },
        });
        return jsonToolOutput("SEED team member add paused for Lab Meeting", {
            run_id: run.run_id,
            status: "blocked",
            reason: gate.reason,
            meeting_path: gate.meeting_path,
        });
    }
    if (!isLabRepresentativeAgent(context.agent)) {
        await appendEvent(store, run.run_id, {
            type: "team_member_add_rejected",
            actor: context.agent,
            session_id: context.sessionID,
            summary: "seed_team_member_add is restricted to Lab-Representative.",
        });
        throw new Error("seed_team_member_add is Lab-Representative-only; ask Lab-Representative to expand the team.");
    }
    if (!context.sessionID)
        throw new Error("seed_team_member_add requires an OpenCode parent session id.");
    if (!store.config.team_mode.enabled)
        throw new Error("seed_team_member_add is disabled by team_mode.enabled=false.");
    const existingRuntime = await loadTeamRuntime(store, run.run_id);
    if (!existingRuntime || existingRuntime.status !== "active") {
        return jsonToolOutput("SEED team member add", {
            run_id: run.run_id,
            status: "blocked",
            reason: "No active team runtime exists for this run.",
        });
    }
    if (!existingRuntime.team_id) {
        return jsonToolOutput("SEED team member add", {
            run_id: run.run_id,
            status: "blocked",
            reason: "The active runtime is the default roster, not a dynamic team. Create a dynamic team before adding members.",
        });
    }
    const memberCount = existingRuntime.members.filter((member) => member.role === "member").length;
    if (memberCount >= store.config.team_mode.max_members) {
        return jsonToolOutput("SEED team member add", {
            run_id: run.run_id,
            status: "blocked",
            reason: `team_mode.max_members=${store.config.team_mode.max_members} would be exceeded`,
        });
    }
    const specInput = buildExpandedTeamSpec(existingRuntime, args.member, store.config.default_run_agent);
    const validation = validateTeamSpec(specInput, store.config);
    if (!validation.ok) {
        await appendEvent(store, run.run_id, {
            type: "team_member_add_rejected",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: `Rejected dynamic member add: ${validation.issues.map((issue) => issue.code).join(", ")}`,
            metadata: { issues: validation.issues },
        });
        return jsonToolOutput("SEED team member add", {
            run_id: run.run_id,
            status: "blocked",
            reason: "member spec failed validation",
            issues: validation.issues,
        });
    }
    const newMember = validation.spec.members.at(-1);
    if (!newMember)
        throw new Error("seed_team_member_add could not normalize member spec.");
    const timestamp = nowIso();
    await addTeamMemberToRuntime(store, run.run_id, runtimeMemberFromSpec(newMember, existingRuntime, context.sessionID, timestamp));
    await appendEvent(store, run.run_id, {
        type: "team_member_add_started",
        actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
        session_id: context.sessionID,
        summary: `${newMember.role_id}: ${newMember.role_label}`,
        metadata: { team_id: validation.spec.team_id, role_id: newMember.role_id, capability_profile: newMember.capability_profile },
    });
    const contextRefs = [existingRuntime.spec_ref, existingRuntime.spec_markdown_ref].filter((ref) => Boolean(ref));
    const launch = await launchMember(store, run, validation.spec, newMember, context, runtime, contextRefs);
    const recipients = existingRuntime.members.map((member) => member.name).filter((name) => name !== newMember.role_id);
    await Promise.all(recipients.map((to) => sendTeamMessage(store, run.run_id, {
        from: validation.spec.lead_owner,
        to,
        kind: "announcement",
        body: `New team member joined: ${newMember.role_id} (${newMember.role_label}).`,
        metadata: { team_id: validation.spec.team_id, role_id: newMember.role_id, launch_status: launch.status },
    })));
    await appendEvent(store, run.run_id, {
        type: launch.status === "failed" ? "team_member_add_failed" : "team_member_added",
        actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
        session_id: context.sessionID,
        summary: `${newMember.role_id}: ${launch.status}`,
        related_agent_call_id: launch.agent_call_id,
        metadata: { team_id: validation.spec.team_id, launch },
    });
    const updatedRuntime = await loadTeamRuntime(store, run.run_id);
    return jsonToolOutput("SEED team member add", {
        run_id: run.run_id,
        status: launch.status === "failed" ? "failed" : "queued",
        member: newMember,
        launch,
        runtime: updatedRuntime,
    });
}
async function launchMembersBounded(store, run, spec, context, runtime, contextRefs = []) {
    const launches = [];
    let nextIndex = 0;
    const workerCount = Math.min(Math.max(1, store.config.team_mode.max_parallel_members), spec.members.length);
    await Promise.all(Array.from({ length: workerCount }, async () => {
        while (nextIndex < spec.members.length) {
            const index = nextIndex;
            nextIndex += 1;
            const member = spec.members[index];
            if (!member)
                return;
            launches[index] = await launchMember(store, run, spec, member, context, runtime, contextRefs);
        }
    }));
    return launches.filter(Boolean);
}
async function launchMember(store, run, spec, member, context, runtime, contextRefs = []) {
    const runId = run.run_id;
    const launchId = createTeamLaunchId();
    const handoff = await sendTeamMessage(store, runId, {
        from: spec.lead_owner,
        to: member.role_id,
        kind: "handoff",
        body: `Mission assigned to ${member.role_label}: ${member.mission_prompt}`,
        metadata: { team_id: spec.team_id, role_id: member.role_id },
    });
    const contract = buildDynamicMemberContract({
        runId,
        spec,
        member,
        config: store.config,
        handoffMessageId: handoff.message_id,
        contextRefs,
    });
    const stableContext = await upsertContextBundle(store, runId, {
        bundle_id: `member-contract-${member.role_id}`,
        category: "stable",
        scope: "agent_thread",
        title: `${member.role_id} stable member contract`,
        body: stableContextBodyForContract(contract),
        owner_agent: member.role_id,
        owner_thread_id: member.role_id,
        metadata: {
            team_id: spec.team_id,
            role_id: member.role_id,
            capability_profile: member.capability_profile,
            allowed_tools: member.tool_policy.allowed_tools,
            denied_tools: member.tool_policy.denied_tools,
            allowed_mcps: member.mcp_policy.allowed_mcps,
            denied_mcps: member.mcp_policy.denied_mcps,
            allowed_skills: member.skill_policy.allowed_skills,
            denied_skills: member.skill_policy.denied_skills,
            native_tools: contract.execution_surface.native_tools,
            write_surface: contract.execution_surface.write_surface,
        },
    });
    const stableContextRef = `context:${stableContext.bundle_id}`;
    const finalContextRefs = uniqueStrings([...contextRefs, stableContextRef]);
    const finalContract = buildDynamicMemberContract({
        runId,
        spec,
        member,
        config: store.config,
        handoffMessageId: handoff.message_id,
        contextRefs: finalContextRefs,
    });
    const resolvedAgent = finalContract.opencode_agent;
    const launchContextPlan = await planContextInjection(store, {
        turn_kind: "member_launch",
        run_id: runId,
        actor: spec.lead_owner,
        target_agent: member.role_id,
        target_thread_id: member.role_id,
        bundle_ids: [stableContextRef],
    });
    const launchContextBlock = renderContextAttachments(launchContextPlan);
    const launchPrompt = [finalContract.prompt, launchContextBlock].filter((part) => part.trim()).join("\n\n");
    await appendTeamLaunchLedgerEntry(store, runId, {
        launch_id: launchId,
        run_id: runId,
        team_id: spec.team_id,
        role_id: member.role_id,
        role_label: member.role_label,
        capability_profile: member.capability_profile,
        status: "requested",
        target_agent: member.role_id,
        opencode_agent: finalContract.opencode_agent,
        parent_session_id: context.sessionID,
        prompt_preview: launchPrompt.slice(0, 1200),
        stable_context_ref: stableContextRef,
        stable_context_hash: stableContext.body_sha256,
        context_refs: finalContract.context_refs,
        allowed_tools: member.tool_policy.allowed_tools,
        denied_tools: member.tool_policy.denied_tools,
        read_paths: finalContract.read_paths,
        write_paths: finalContract.write_paths,
        lease_requirements: finalContract.lease_requirements,
        write_surface: finalContract.execution_surface.write_surface,
        native_tools: finalContract.execution_surface.native_tools,
        model_route: compactModelRoute(resolveModelRoute(store.config, resolvedAgent, currentModelFromRun(run))),
    });
    await appendTeamConversationEntry(store, runId, {
        type: "member_launch_requested",
        from: spec.lead_owner,
        to: member.role_id,
        launch_id: launchId,
        message_id: handoff.message_id,
        prompt_summary: `${spec.team_name}/${member.role_id}: ${member.role_label}`,
        status: "requested",
        metadata: {
            team_id: spec.team_id,
            role_id: member.role_id,
            role_label: member.role_label,
            capability_profile: member.capability_profile,
            resolved_agent: resolvedAgent,
            opencode_agent: finalContract.opencode_agent,
            parent_session_id: context.sessionID,
            prompt_preview: launchPrompt.slice(0, 1200),
            stable_context_ref: stableContextRef,
            stable_context_hash: stableContext.body_sha256,
            context_refs: finalContract.context_refs,
            allowed_tools: member.tool_policy.allowed_tools,
            denied_tools: member.tool_policy.denied_tools,
            allowed_mcps: member.mcp_policy.allowed_mcps,
            denied_mcps: member.mcp_policy.denied_mcps,
            allowed_skills: member.skill_policy.allowed_skills,
            denied_skills: member.skill_policy.denied_skills,
            allow_user_skills: member.skill_policy.allow_user_skills,
            read_paths: finalContract.read_paths,
            write_paths: finalContract.write_paths,
            lease_requirements: finalContract.lease_requirements,
            write_surface: finalContract.execution_surface.write_surface,
            native_tools: finalContract.execution_surface.native_tools,
            spawn_policy: member.spawn_policy,
            launch_policy: member.launch_policy,
            model_route: compactModelRoute(resolveModelRoute(store.config, resolvedAgent, currentModelFromRun(run))),
        },
    });
    try {
        const output = await executeDelegate(store, {
            target_agent: member.role_id,
            prompt: launchPrompt,
            prompt_summary: `${spec.team_name}/${member.role_id}: ${member.role_label}`,
            auto_skills: false,
        }, context, "background", runtime);
        const payload = parseToolOutput(output);
        const launch = {
            role_id: member.role_id,
            role_label: member.role_label,
            capability_profile: member.capability_profile,
            resolved_agent: resolvedAgent,
            status: "queued",
            child_session_id: stringValue(payload.child_session_id),
            background_id: stringValue(payload.background_id),
            agent_call_id: stringValue(payload.agent_call_id),
            prompt_ref: stringValue(payload.prompt_ref),
            launch_id: launchId,
            stable_context_ref: stableContextRef,
            stable_context_hash: stableContext.body_sha256,
            opencode_agent: finalContract.opencode_agent,
            write_surface: finalContract.execution_surface.write_surface,
            lease_requirements: finalContract.lease_requirements,
            pending_message_ids: [handoff.message_id],
            model_attempts: Array.isArray(payload.model_attempts) ? payload.model_attempts : plannedAttempts(store, resolvedAgent, run),
        };
        await recordTeamMemberLaunch(store, runId, member.role_id, {
            status: "active",
            launch_status: "queued",
            session_id: launch.child_session_id,
            background_id: launch.background_id,
            agent_call_id: launch.agent_call_id,
            prompt_ref: launch.prompt_ref,
            resolved_agent: resolvedAgent,
            opencode_agent: finalContract.opencode_agent,
            write_surface: finalContract.execution_surface.write_surface,
        });
        await appendEvent(store, runId, {
            type: "team_member_launch_queued",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: `${member.role_id} queued as ${resolvedAgent}`,
            related_agent_call_id: launch.agent_call_id,
            metadata: {
                team_id: spec.team_id,
                launch_id: launchId,
                role_id: member.role_id,
                capability_profile: member.capability_profile,
                model_route: compactModelRoute(resolveModelRoute(store.config, resolvedAgent, currentModelFromRun(run))),
                opencode_agent: finalContract.opencode_agent,
                write_surface: finalContract.execution_surface.write_surface,
                native_tools: finalContract.execution_surface.native_tools,
                lease_requirements: finalContract.lease_requirements,
                handoff_message_id: handoff.message_id,
                stable_context_ref: stableContextRef,
                stable_context_hash: stableContext.body_sha256,
            },
        });
        await appendTeamLaunchLedgerEntry(store, runId, {
            launch_id: launchId,
            run_id: runId,
            team_id: spec.team_id,
            role_id: member.role_id,
            role_label: member.role_label,
            capability_profile: member.capability_profile,
            status: "queued",
            target_agent: member.role_id,
            opencode_agent: finalContract.opencode_agent,
            parent_session_id: context.sessionID,
            child_session_id: launch.child_session_id,
            background_id: launch.background_id,
            agent_call_id: launch.agent_call_id,
            prompt_ref: launch.prompt_ref,
            prompt_preview: launchPrompt.slice(0, 1200),
            stable_context_ref: stableContextRef,
            stable_context_hash: stableContext.body_sha256,
            context_refs: finalContract.context_refs,
            allowed_tools: member.tool_policy.allowed_tools,
            denied_tools: member.tool_policy.denied_tools,
            read_paths: finalContract.read_paths,
            write_paths: finalContract.write_paths,
            lease_requirements: finalContract.lease_requirements,
            write_surface: finalContract.execution_surface.write_surface,
            native_tools: finalContract.execution_surface.native_tools,
            model_route: compactModelRoute(resolveModelRoute(store.config, resolvedAgent, currentModelFromRun(run))),
            model_attempts: launch.model_attempts,
        });
        await appendTeamConversationEntry(store, runId, {
            type: "member_launch_queued",
            from: spec.lead_owner,
            to: member.role_id,
            launch_id: launchId,
            message_id: handoff.message_id,
            agent_call_id: launch.agent_call_id,
            child_session_id: launch.child_session_id,
            background_id: launch.background_id,
            prompt_ref: launch.prompt_ref,
            prompt_summary: `${spec.team_name}/${member.role_id}: ${member.role_label}`,
            status: "queued",
            metadata: {
                team_id: spec.team_id,
                role_id: member.role_id,
                role_label: member.role_label,
                capability_profile: member.capability_profile,
                resolved_agent: resolvedAgent,
                opencode_agent: finalContract.opencode_agent,
                parent_session_id: context.sessionID,
                allowed_tools: member.tool_policy.allowed_tools,
                denied_tools: member.tool_policy.denied_tools,
                stable_context_ref: stableContextRef,
                stable_context_hash: stableContext.body_sha256,
                context_refs: finalContract.context_refs,
                read_paths: finalContract.read_paths,
                write_paths: finalContract.write_paths,
                lease_requirements: finalContract.lease_requirements,
                write_surface: finalContract.execution_surface.write_surface,
                native_tools: finalContract.execution_surface.native_tools,
                model_attempts: launch.model_attempts,
            },
        });
        return launch;
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        await recordTeamMemberLaunch(store, runId, member.role_id, {
            status: "failed",
            launch_status: "failed",
            launch_error: message,
            resolved_agent: resolvedAgent,
            opencode_agent: finalContract.opencode_agent,
            write_surface: finalContract.execution_surface.write_surface,
        });
        await appendEvent(store, runId, {
            type: "team_member_launch_failed",
            actor: context.agent ?? LAB_REPRESENTATIVE_AGENT,
            session_id: context.sessionID,
            summary: `${member.role_id} failed to launch: ${message.slice(0, 160)}`,
            metadata: {
                team_id: spec.team_id,
                launch_id: launchId,
                role_id: member.role_id,
                resolved_agent: resolvedAgent,
                opencode_agent: finalContract.opencode_agent,
                write_surface: finalContract.execution_surface.write_surface,
                stable_context_ref: stableContextRef,
                stable_context_hash: stableContext.body_sha256,
            },
        });
        await appendTeamLaunchLedgerEntry(store, runId, {
            launch_id: launchId,
            run_id: runId,
            team_id: spec.team_id,
            role_id: member.role_id,
            role_label: member.role_label,
            capability_profile: member.capability_profile,
            status: "failed",
            target_agent: member.role_id,
            opencode_agent: finalContract.opencode_agent,
            parent_session_id: context.sessionID,
            prompt_preview: launchPrompt.slice(0, 1200),
            stable_context_ref: stableContextRef,
            stable_context_hash: stableContext.body_sha256,
            context_refs: finalContract.context_refs,
            allowed_tools: member.tool_policy.allowed_tools,
            denied_tools: member.tool_policy.denied_tools,
            read_paths: finalContract.read_paths,
            write_paths: finalContract.write_paths,
            lease_requirements: finalContract.lease_requirements,
            write_surface: finalContract.execution_surface.write_surface,
            native_tools: finalContract.execution_surface.native_tools,
            model_route: compactModelRoute(resolveModelRoute(store.config, resolvedAgent, currentModelFromRun(run))),
            model_attempts: plannedAttempts(store, resolvedAgent, run),
            error: message,
        });
        await appendTeamConversationEntry(store, runId, {
            type: "member_launch_failed",
            from: spec.lead_owner,
            to: member.role_id,
            launch_id: launchId,
            message_id: handoff.message_id,
            prompt_summary: `${spec.team_name}/${member.role_id}: ${member.role_label}`,
            status: "failed",
            metadata: {
                team_id: spec.team_id,
                role_id: member.role_id,
                role_label: member.role_label,
                capability_profile: member.capability_profile,
                resolved_agent: resolvedAgent,
                opencode_agent: finalContract.opencode_agent,
                parent_session_id: context.sessionID,
                allowed_tools: member.tool_policy.allowed_tools,
                denied_tools: member.tool_policy.denied_tools,
                stable_context_ref: stableContextRef,
                stable_context_hash: stableContext.body_sha256,
                context_refs: finalContract.context_refs,
                read_paths: finalContract.read_paths,
                write_paths: finalContract.write_paths,
                lease_requirements: finalContract.lease_requirements,
                write_surface: finalContract.execution_surface.write_surface,
                native_tools: finalContract.execution_surface.native_tools,
                model_attempts: plannedAttempts(store, resolvedAgent, run),
                error: message,
            },
        });
        return {
            role_id: member.role_id,
            role_label: member.role_label,
            capability_profile: member.capability_profile,
            resolved_agent: resolvedAgent,
            launch_id: launchId,
            stable_context_ref: stableContextRef,
            stable_context_hash: stableContext.body_sha256,
            opencode_agent: finalContract.opencode_agent,
            write_surface: finalContract.execution_surface.write_surface,
            lease_requirements: finalContract.lease_requirements,
            status: "failed",
            pending_message_ids: [handoff.message_id],
            model_attempts: plannedAttempts(store, resolvedAgent, run),
            error: message,
        };
    }
}
function stableContextBodyForContract(contract) {
    return JSON.stringify({
        schema_version: 1,
        kind: "seed_member_stable_contract",
        run_id: contract.run_id,
        team_id: contract.team_id,
        team_name: contract.team_name,
        role_id: contract.role_id,
        role_label: contract.role_label,
        capability_profile: contract.capability_profile,
        opencode_agent: contract.opencode_agent,
        mission_prompt: contract.mission_prompt,
        model_route: contract.model_route,
        launch_policy: contract.launch_policy,
        tool_policy: contract.tool_policy,
        mcp_policy: contract.mcp_policy,
        skill_policy: contract.skill_policy,
        spawn_policy: contract.spawn_policy,
        read_paths: contract.read_paths,
        write_paths: contract.write_paths,
        lease_requirements: contract.lease_requirements,
        authoritative_inputs: contract.authoritative_inputs,
        evidence_inputs: contract.evidence_inputs,
        evidence_contract: contract.evidence_contract,
        expected_outputs: contract.expected_outputs,
        stop_condition: contract.stop_condition,
        coverage: contract.coverage,
        subplan_ids: contract.subplan_ids,
        professor_facing_language: contract.professor_facing_language,
        execution_surface: contract.execution_surface,
    }, null, 2);
}
function buildExpandedTeamSpec(runtime, rawMember, defaultLead) {
    const existingMembers = runtime.members.filter((member) => member.role === "member").map(memberSpecFromRuntime);
    const incoming = recordValue(rawMember);
    const members = [...existingMembers, incoming];
    const authoritativeInputs = uniqueStrings(members.flatMap((member) => stringArray(member.authoritative_inputs)));
    const expectedOutputs = uniqueStrings(members.flatMap((member) => stringArray(member.expected_outputs)));
    return {
        team_id: runtime.team_id,
        team_name: runtime.team_name ?? runtime.team_id ?? "dynamic-team",
        objective: `Expand active team ${runtime.team_name ?? runtime.team_id ?? ""}`.trim(),
        lead_owner: runtime.members.find((member) => member.role === "lead")?.name ?? defaultLead,
        authoritative_inputs: authoritativeInputs.length ? authoritativeInputs : ["professor request"],
        expected_state_version: 1,
        expected_outputs: expectedOutputs.length ? expectedOutputs : ["expanded team output"],
        stop_condition: "The expanded team member completes its explicit output or reports a blocker.",
        members,
    };
}
function memberSpecFromRuntime(member) {
    return {
        role_id: member.name,
        role_label: member.role_label ?? String(member.name),
        coverage: member.coverage ?? ["executor"],
        capability_profile: member.capability_profile ?? "research",
        resolved_agent: LAB_REPRESENTATIVE_AGENT,
        opencode_agent: LAB_REPRESENTATIVE_AGENT,
        mission_prompt: member.mission_prompt ?? `${member.role_label ?? member.name}: continue your assigned team role.`,
        tool_policy: member.tool_policy ?? { allowed_tools: [], denied_tools: [] },
        mcp_policy: member.mcp_policy ?? { allowed_mcps: [], denied_mcps: [] },
        skill_policy: member.skill_policy ?? { allowed_skills: [], denied_skills: [], allow_user_skills: false },
        prompt_budget: member.prompt_budget ?? { max_prompt_chars: 4000 },
        model_route: member.model_route ?? { fallback_profiles: [] },
        spawn_policy: member.spawn_policy,
        launch_policy: member.launch_policy ?? { mode: "background", wait_for_dependencies: true },
        delivery_policy: member.delivery_policy ?? { report_to: LAB_REPRESENTATIVE_AGENT, expected_artifact_paths: [] },
        evidence_contract: member.evidence_contract ?? { required_refs: [], required_artifacts: [], oracle_scope: [] },
        authoritative_inputs: member.authoritative_inputs ?? [],
        expected_state_version: member.expected_state_version ?? 1,
        read_paths: member.read_paths ?? [],
        write_paths: member.write_paths ?? [],
        evidence_paths: member.evidence_paths ?? [],
        artifact_paths: member.artifact_paths ?? [],
        expected_outputs: member.expected_outputs ?? [],
        stop_condition: member.stop_condition ?? "Done.",
        dependencies: member.dependencies ?? [],
        artifact_inputs: member.artifact_inputs ?? [],
        evidence_inputs: member.evidence_inputs ?? [],
        verifier_obligations: member.verifier_obligations ?? [],
        oracle_scope: member.oracle_scope ?? [],
        semantic_conflict_policy: member.semantic_conflict_policy ?? "exclusive",
        human_in_the_loop: member.human_in_the_loop ?? { risk_tier: "low", escalation_triggers: [] },
    };
}
function runtimeMemberFromSpec(member, runtime, parentSessionId, timestamp) {
    return {
        name: member.role_id,
        role: "member",
        status: "launching",
        joined_at: timestamp,
        last_seen_at: timestamp,
        role_label: member.role_label,
        capability_profile: member.capability_profile,
        resolved_agent: member.resolved_agent,
        parent_session_id: runtime.members.find((candidate) => candidate.role === "lead")?.parent_session_id ?? parentSessionId,
        coverage: member.coverage,
        mission_prompt: member.mission_prompt,
        prompt_budget: member.prompt_budget,
        model_route: member.model_route,
        spawn_policy: member.spawn_policy,
        launch_policy: member.launch_policy,
        delivery_policy: member.delivery_policy,
        evidence_contract: member.evidence_contract,
        authoritative_inputs: member.authoritative_inputs,
        expected_state_version: member.expected_state_version,
        read_paths: member.read_paths,
        write_paths: member.write_paths,
        evidence_paths: member.evidence_paths,
        artifact_paths: member.artifact_paths,
        expected_outputs: member.expected_outputs,
        stop_condition: member.stop_condition,
        dependencies: member.dependencies,
        artifact_inputs: member.artifact_inputs,
        evidence_inputs: member.evidence_inputs,
        verifier_obligations: member.verifier_obligations,
        oracle_scope: member.oracle_scope,
        semantic_conflict_policy: member.semantic_conflict_policy,
        human_in_the_loop: member.human_in_the_loop,
        tool_policy: member.tool_policy,
        mcp_policy: member.mcp_policy,
        skill_policy: member.skill_policy,
        pending_message_ids: [],
        launch_status: "pending",
    };
}
function plannedAttempts(store, targetAgent, run) {
    const route = resolveModelRoute(store.config, targetAgent, run ? currentModelFromRun(run) : undefined);
    return route.attempts.map((attempt, index) => ({
        attempt: index + 1,
        source: attempt.source,
        model: attempt.model,
        providerID: attempt.providerID,
        modelID: attempt.modelID,
        variant: attempt.variant,
        model_profile: attempt.model_profile,
        status: "pending",
    }));
}
function parseToolOutput(value) {
    const output = typeof value === "object" && value !== null && "output" in value ? value.output : value;
    if (typeof output !== "string")
        return {};
    try {
        const parsed = JSON.parse(output);
        return typeof parsed === "object" && parsed !== null ? parsed : {};
    }
    catch {
        return {};
    }
}
function relativeRunPath(file, store, runId) {
    const root = `${store.config.trace.artifact_root}/${runId}`;
    const marker = file.indexOf(root);
    return marker >= 0 ? file.slice(marker + root.length + 1).replaceAll("\\", "/") : file;
}
function stringValue(value) {
    return typeof value === "string" && value.length > 0 ? value : undefined;
}
function recordValue(input) {
    return typeof input === "object" && input !== null && !Array.isArray(input) ? input : {};
}
function stringArray(input) {
    return Array.isArray(input) ? input.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean) : [];
}
function uniqueStrings(values) {
    return Array.from(new Set(values));
}
//# sourceMappingURL=team-create.js.map