/**
 * `Crew` — the swarm coordinator that ties the domain services together.
 *
 * A crew is a roster of teammate agents working a shared board of tickets,
 * talking over one channel, with every coordination step narrated to an activity
 * log. This module is the conductor that wires those services into a single
 * driveable object:
 *
 *   - a {@link CrewManifest} — who is on the crew (the roster);
 *   - a {@link TicketBoard}  — the shared, dependency-aware to-do list;
 *   - a {@link Channel}      — the cursor-based mailbox teammates post on;
 *   - an {@link ActivityLog} — the append-only transcript of what happened;
 *   - optionally a {@link Workspace} — git-worktree isolation per teammate.
 *
 * The crew owns no `node:fs` locking, temp renames, or coercion of its own — all
 * of that lives in the kernel under the services. What the coordinator adds is
 * the *policy*: how ready tickets are matched to idle members, how a teammate
 * agent is spawned to work a ticket, and how its result is folded back onto the
 * board and the channel.
 *
 * The agent spawner is **injectable**. By default a member is backed by a real
 * {@link createAgent} bound to the member's model and tool collection; tests pass
 * a scripted fake agent so a round runs deterministically with no model or
 * network. The coordinator only depends on the {@link Agent} handle's `submit`
 * and `snapshot` surface, so a fake need only implement those.
 *
 * One round of work — {@link Crew.runRound} — is the heartbeat:
 *   1. read the board's ready tickets and the idle members;
 *   2. pair each ready ticket with an idle member;
 *   3. for each pair: claim the ticket, spawn the member's agent, let it work the
 *      ticket, post a `result` envelope, complete (or fail) the ticket, and
 *      narrate every step to the activity log.
 */
import type { Agent } from "../runtime";
import type { CrewMember, MemberDraft } from "./roster";
import type { Ticket } from "./workboard";
import type { CrewEvent } from "./telemetry/activity";
import { Workspace } from "./isolation";
/**
 * The injectable factory that brings a teammate agent up for a member.
 *
 * The default ({@link defaultSpawnAgent}) builds a real {@link createAgent} bound
 * to the member's model and {@link toolBox} collection. Tests substitute a
 * scripted fake whose `submit` resolves to a canned snapshot, exercising the
 * coordination logic without a model or the network.
 */
export type SpawnAgent = (member: CrewMember) => Agent;
/** What a caller may set when standing up a crew. */
export interface CrewOptions {
    /**
     * Root directory the crew persists under. The manifest, board, channel, and
     * activity log are all rooted here; the directory is created lazily by the
     * underlying kernel services.
     */
    readonly dir: string;
    /**
     * Optional git repository the crew isolates teammates into via a
     * {@link Workspace}. When present the workspace is constructed (and exposed on
     * {@link Crew.workspace}) so a host can provision per-teammate worktrees; the
     * coordinator itself does not force isolation on every round.
     */
    readonly baseRepo?: string;
    /**
     * Override the agent spawner. Defaults to {@link defaultSpawnAgent} (a real
     * {@link createAgent}); tests inject a scripted fake.
     */
    readonly spawnAgent?: SpawnAgent;
    /** Injected clock, epoch ms — threaded into the board and activity log for tests. */
    readonly now?: () => number;
}
/**
 * A point-in-time aggregate of the crew's state, assembled from the board, the
 * roster, and the activity log. This is what a status pane renders.
 */
export interface CrewStatus {
    /** The crew id from the manifest (empty until {@link Crew.create}). */
    readonly crewId: string;
    /** The full roster, in enrollment order. */
    readonly members: readonly CrewMember[];
    /** Every ticket on the board, in insertion order. */
    readonly tickets: readonly Ticket[];
    /** The ticket ids currently workable (open, all deps done). */
    readonly ready: readonly string[];
    /** Count of tickets in each lifecycle state. */
    readonly counts: {
        readonly open: number;
        readonly claimed: number;
        readonly blocked: number;
        readonly done: number;
        readonly failed: number;
    };
    /** The full activity timeline, oldest first. */
    readonly activity: readonly CrewEvent[];
}
/**
 * The swarm coordinator. Construct with {@link createCrew}; it owns the four
 * domain services and the agent spawner, and exposes the small set of verbs a
 * host drives a crew through.
 */
export declare class Crew {
    private readonly manifest;
    private readonly board;
    private readonly channel;
    private readonly activity;
    private readonly spawnAgent;
    /** The optional git-worktree isolation seam (present only with a `baseRepo`). */
    readonly workspace: Workspace | null;
    /** The base repository worktrees are provisioned against, if any. */
    readonly baseRepo: string | null;
    private constructor();
    /**
     * Stand up a crew rooted at `dir`, wiring up the manifest, board, channel, and
     * activity log (and a {@link Workspace} when `baseRepo` is given). The crew
     * record is created eagerly so a fresh crew is immediately usable by
     * {@link addMember}.
     */
    static open(opts: CrewOptions): Promise<Crew>;
    /**
     * Enroll a teammate and narrate the spawn to the activity log.
     *
     * Delegates the roster edit to the {@link CrewManifest}; on success a
     * `member_spawned` event is recorded so the transcript reflects the new member.
     */
    addMember(draft: MemberDraft): Promise<CrewMember>;
    /**
     * Post a unit of work to the board and narrate it.
     *
     * Accepts the same draft shape the board's {@link TicketBoard.add} takes
     * (title, optional body, optional deps); returns the admitted ticket. A
     * `ticket_posted` event is recorded on success.
     */
    postTask(draft: TaskDraft): Promise<Ticket>;
    /**
     * Drive one round of work, returning the tickets that reached a terminal state
     * this round.
     *
     * Reads the board's ready tickets and pairs each with an idle member (one
     * ticket per member per round). For each pair it: claims the ticket for the
     * member, spawns the member's agent, lets the agent work the ticket, posts a
     * `result` envelope on the channel, completes (or, on a thrown error, fails)
     * the ticket, and records the corresponding activity events. A round with no
     * ready work or no idle members is a no-op that returns an empty list.
     */
    runRound(): Promise<RoundOutcome>;
    /**
     * Assemble the crew's current state from the board, roster, and activity log.
     * A pure read across the three services — it takes no locks and mutates
     * nothing.
     */
    status(): Promise<CrewStatus>;
    /**
     * Work a single ticket with a single member, end to end.
     *
     * Claims the ticket (recording `ticket_claimed`), spawns the member's agent and
     * runs it over the ticket brief, posts a `result` envelope back to the
     * coordinator (recording `message_sent`), then completes the ticket (recording
     * `ticket_done`). Any throw while the agent runs fails the ticket instead
     * (recording `ticket_failed`), so one bad teammate cannot wedge the round.
     */
    private workOne;
    /** The set of member ids currently holding a claimed (or blocked) ticket. */
    private busyMemberIds;
}
/** The result of one {@link Crew.runRound}: which tickets settled and how. */
export interface RoundOutcome {
    /** Tickets that reached `done` this round. */
    readonly completed: readonly Ticket[];
    /** Tickets that reached `failed` this round. */
    readonly failed: readonly Ticket[];
}
/** A ticket draft accepted by {@link Crew.postTask} (mirrors the board's draft). */
export interface TaskDraft {
    /** Short human-facing summary (required). */
    readonly title: string;
    /** Full task description; defaults to empty. */
    readonly body?: string;
    /** Ids of tickets that must complete first; defaults to none. */
    readonly deps?: readonly string[];
}
/**
 * Stand up a crew. The host-facing factory; see {@link CrewOptions} for the knobs
 * and {@link Crew} for the verbs.
 */
export declare function createCrew(opts: CrewOptions): Promise<Crew>;
/**
 * The default agent spawner: a real {@link createAgent} bound to the member's
 * model and tool collection. The member's `toolCollection` (a structural twin of
 * the capabilities {@link ToolCollection}) is handed straight to {@link toolBox};
 * an unset collection defaults to `read-only` (the safe floor). The member's
 * pinned model — or {@link DEFAULT_MEMBER_MODEL} — backs the run.
 */
export declare function defaultSpawnAgent(member: CrewMember): Agent;
