import { createHash, randomUUID } from "node:crypto";
import type { KanboardParams, KanboardRpcClient, KanboardResult } from "./kanboard-client";
import { KanboardRpcError } from "./kanboard-client";
import { assembleDispatchBrief, BriefAssemblyError, type BriefDeps } from "./dispatch-brief";
import { IncidentOptionsError, InvalidIncidentDispatchError, InvalidIncidentTypeError, validateIncidentDispatchSelection, validateIncidentType, type LoadedIncidentOptions, type ValidatedIncidentDispatchSelection } from "./dispatch-options";
import { IncidentLaunchError, type IncidentDispatchLauncher, type IncidentLaunchReceipt } from "./incident-launcher";
import { IncidentMutationLeaseError, type IncidentMutationStore, type LaunchPhase, type PendingResolutionRecord } from "./incident-mutation-store";
import type { VerifiedResolutionEvidence } from "./resolution-learning";
import type { IncidentStatusUpdate } from "./status-writer";
import {
  INCIDENTS_COLUMNS,
  INCIDENTS_SWIMLANES,
  type IncidentsReadiness,
} from "./bootstrap";

export type IncidentPriority = "P0" | "P1" | "P2" | "P3";
export type IncidentState = "filed" | "dispatching" | "running" | "needs-attention" | "resolved";
export interface IncidentCoverage {
  stale: boolean;
  detail?: string;
}

type DispatchState =
  | "starting"
  | "running"
  | "resolved"
  | "needs-attention"
  | "rate-limited"
  | "timed-out"
  | "engine-down"
  | "interrupted"
  | "invalid-result";

export interface IncidentDispatch {
  state: IncidentState;
  dispatchId: string | null;
  cli: string | null;
  model: string | null;
  wrapperModel: string | null;
  reasoningEffort: string | null;
  account: string | null;
  requestSha256: string | null;
  statusRevision: number | null;
  startedAt: string | null;
  heartbeatAt: string | null;
  completedAt: string | null;
  exitCode: number | null;
  failureClass: string | null;
  resultSummary: string | null;
}

export interface IncidentActivity {
  id: number;
  at: string | null;
  comment: string;
  username: string;
}

export interface Incident {
  id: string;
  kanboardTaskId: number;
  title: string;
  description: string;
  priority: IncidentPriority | null;
  incidentType: string | null;
  dispatchBrief: string | null;
  dispatchBriefProvenance: string | null;
  state: IncidentState;
  active: boolean;
  createdAt: string | null;
  updatedAt: string | null;
  resolvedAt: string | null;
  dispatch: IncidentDispatch;
  activity: IncidentActivity[];
  coverage: IncidentCoverage;
}

export type IncidentScope = "active" | "resolved" | "all";

export interface ListIncidentsQuery {
  scope: IncidentScope;
  query?: string;
  priority?: IncidentPriority;
  limit?: number;
  cursor?: number;
  highWater?: number;
}

export interface IncidentPage {
  highWater: number;
  nextCursor: number | null;
  exhausted: boolean;
  order: "id_desc";
}

export interface ListIncidentsResult {
  incidents: Incident[];
  coverage: IncidentCoverage;
  page: IncidentPage;
}

export interface FileIncidentRequest {
  requestId: string;
  title: string;
  description: string;
  cli: string;
  model: string;
  reasoningEffort: string;
  account: string;
  unsafe: boolean;
  priority: IncidentPriority;
  incidentType?: string;
  /** Authoritative wrapper model resolved server-side during POST validation. */
  wrapperModel?: string;
}

export class IncidentIdempotencyConflictError extends Error {}

export class IncidentResolutionConflictError extends Error {
  constructor(public readonly detail: string) {
    super(detail);
    this.name = "IncidentResolutionConflictError";
  }
}

export class IncidentResolutionArtifactError extends Error {
  constructor(public readonly detail: string) {
    super(detail);
    this.name = "IncidentResolutionArtifactError";
  }
}

export class IncidentMutationError extends Error {
  constructor(public readonly code: "invalid-request" | "idempotency-conflict" | "not-found" | "not-filed" | "incident-dispatch-options-stale") {
    super(code);
    this.name = "IncidentMutationError";
  }
}

export interface IncidentService {
  listIncidents(query: ListIncidentsQuery): Promise<ListIncidentsResult>;
  getIncident(incidentId: string): Promise<Incident | null>;
  fileIncident(request: FileIncidentRequest): Promise<Incident>;
  dispatchIncident(incidentId: string, options?: DispatchOptions): Promise<Incident>;
  stopIncident(incidentId: string): Promise<Incident>;
  deleteIncident(incidentId: string): Promise<void>;
  resolveIncident(incidentId: string, artifact: string, summary?: string): Promise<Incident>;
  resumeResolution(operation: PendingResolutionRecord): Promise<Incident>;
  getDispatchLauncher(): IncidentDispatchLauncher | null;

}

export interface DispatchOptions {
  withoutBrief?: boolean;
}

export interface BriefConfig {
  deps: BriefDeps;
  provenance(): string;
}

interface CreateIncidentServiceOptions {
  client: KanboardRpcClient;
  readiness: IncidentsReadiness;
  brief?: BriefConfig;
  now?: () => number;
  loadIncidentOptions?: () => Promise<LoadedIncidentOptions>;
  mutationStore?: IncidentMutationStore;
  launcher?: IncidentDispatchLauncher;
  workspaceFor?(incidentId: string): string;
  wrapperFor?(relativeWrapper: string): string;
  recordStatus?(update: IncidentStatusUpdate): Promise<void>;
  verifyResolutionArtifact?(request: { incidentId: string; incidentType: string | null; artifact: string; summary?: string }): Promise<VerifiedResolutionEvidence>;
  recordResolutionLearning?(evidence: VerifiedResolutionEvidence): Promise<void>;

}

type TaskRecord = KanboardResult<"getTask">;
type TaskMetadata = KanboardResult<"getTaskMetadata">;
type TaskComment = KanboardResult<"getAllComments">[number];

type StateByColumn = Map<number, IncidentState>;
type PriorityBySwimlane = Map<number, IncidentPriority>;

type MetadataByTask = Map<number, TaskMetadata>;
type CommentListByTask = Map<number, IncidentActivity[]>;

type ScopeStateQuery = readonly ["active" | "resolved" | "all", number[]];

const STATUS_BY_SCOPE: ScopeStateQuery[] = [
  ["active", [1]],
  ["resolved", [0]],
  ["all", [1, 0]],
];

const PRIORITY_BY_NUMBER: IncidentPriority[] = ["P0", "P1", "P2", "P3"];
const PRIORITY_NUMBER: Record<IncidentPriority, number> = { P0: 0, P1: 1, P2: 2, P3: 3 };
const SWIMLANE_NAME_BY_PRIORITY: Record<IncidentPriority, (typeof INCIDENTS_SWIMLANES)[number]> = {
  P0: "P0 · Critical",
  P1: "P1 · High",
  P2: "P2 · Normal",
  P3: "P3 · Low",
};

const STATE_BY_COLUMN_NAME: Record<(typeof INCIDENTS_COLUMNS)[number], IncidentState> = {
  Filed: "filed",
  Dispatching: "dispatching",
  Running: "running",
  "Needs attention": "needs-attention",
  Resolved: "resolved",
};

const DISPATCH_STATE_BY_METADATA: Record<string, IncidentState> = {
  starting: "dispatching",
  running: "running",
  resolved: "resolved",
  "needs-attention": "needs-attention",
  "rate-limited": "needs-attention",
  "timed-out": "needs-attention",
  "engine-down": "needs-attention",
  interrupted: "needs-attention",
  "invalid-result": "needs-attention",
};
const RUNNING_HEARTBEAT_STALE_MS = 45_000;
const RUNNING_HEARTBEAT_MAX_FUTURE_MS = 5_000;
const HISTORICAL_BACKFILL_KEY = "overdeck.historical_backfill";

function isTaskMissing(error: unknown): boolean {
  return error instanceof KanboardRpcError && error.code === "RPC_NULL_RESULT";
}

function unixToIso(value: number | null | undefined): string | null {
  if (value === null || value === undefined || value <= 0 || !Number.isFinite(value)) {
    return null;
  }
  const date = new Date(value * 1000);
  if (Number.isNaN(date.getTime())) {
    return null;
  }
  return date.toISOString();
}

function mapPriority(numberValue: number): IncidentPriority | null {
  return PRIORITY_BY_NUMBER[numberValue] ?? null;
}

function resolvePriorityBySwimlane(swimlaneId: number, swimlaneMap: PriorityBySwimlane): IncidentPriority | null {
  return swimlaneMap.get(swimlaneId) ?? null;
}

function toIsoOrNull(raw: string | undefined): string | null {
  const value = raw?.trim();
  if (!value) {
    return null;
  }
  const parsed = new Date(value);
  return Number.isNaN(parsed.getTime()) ? null : parsed.toISOString();
}

function stripMarker(description: string): string {
  const normalized = description.replace(/\r\n/g, "\n").trimEnd();
  const lines = normalized.split("\n");
  const last = lines.at(-1);
  if (!last || !/^Overdeck-Incident:\s+.+$/.test(last)) {
    return normalized;
  }
  return lines.slice(0, -1).join("\n").trimEnd();
}

function toDispatchMetadata(raw: string | undefined): string | null {
  if (!raw) {
    return null;
  }
  const next = raw.trim();
  return next.length === 0 ? null : next;
}

function toDispatchNumber(raw: string | undefined): number | null {
  if (!raw) {
    return null;
  }
  const parsed = Number(raw);
  if (!Number.isFinite(parsed)) {
    return null;
  }
  return Math.trunc(parsed);
}

function buildDispatchState(metadata: TaskMetadata): IncidentState {
  const raw = toDispatchMetadata(metadata["overdeck.dispatch_state"]);
  if (!raw) {
    return "filed";
  }
  return DISPATCH_STATE_BY_METADATA[raw] ?? "needs-attention";
}

function buildDispatch(metadata: TaskMetadata, state: IncidentState): IncidentDispatch {
  return {
    state,
    dispatchId: toDispatchMetadata(metadata["overdeck.dispatch_id"]),
    cli: toDispatchMetadata(metadata["overdeck.cli"]),
    model: toDispatchMetadata(metadata["overdeck.model"]),
    wrapperModel: toDispatchMetadata(metadata["overdeck.wrapper_model"]),
    reasoningEffort: toDispatchMetadata(metadata["overdeck.reasoning_effort"]),
    account: toDispatchMetadata(metadata["overdeck.account"]),
    requestSha256: toDispatchMetadata(metadata["overdeck.request_sha256"]),
    statusRevision: toDispatchNumber(metadata["overdeck.status_revision"]),
    startedAt: toIsoOrNull(metadata["overdeck.started_at"]),
    heartbeatAt: toIsoOrNull(metadata["overdeck.heartbeat_at"]),
    completedAt: toIsoOrNull(metadata["overdeck.completed_at"]),
    exitCode: toDispatchNumber(metadata["overdeck.exit_code"]),
    failureClass: toDispatchMetadata(metadata["overdeck.failure_class"]),
    resultSummary: toDispatchMetadata(metadata["overdeck.result_summary"]),
  };
}

function buildCoverage(details: string[] = []): IncidentCoverage {
  const detail = details.filter((entry) => entry.length > 0).join("; ");
  return {
    stale: detail.length > 0,
    ...(detail.length > 0 ? { detail } : {}),
  };
}

function buildState(
  task: TaskRecord,
  stateByColumn: StateByColumn,
  metadata: TaskMetadata,
  nowMs: number,
): { state: IncidentState; coverage: IncidentCoverage } {
  const columnState = stateByColumn.get(task.column_id);
  const rawDispatchState = toDispatchMetadata(metadata["overdeck.dispatch_state"]);
  const dispatchState = buildDispatchState(metadata);
  const details: string[] = [];
  if (metadata[HISTORICAL_BACKFILL_KEY] === "failed") details.push("historical-backfill-failed");

  if (!columnState) {
    details.push(`state-column-unmapped:${task.column_id}`);
  }
  if (rawDispatchState !== null && DISPATCH_STATE_BY_METADATA[rawDispatchState] === undefined) {
    details.push("state-metadata-unrecognized");
  }

  const disagreement = columnState !== undefined && dispatchState !== columnState;
  if (disagreement) {
    details.push(`state-column-metadata-mismatch:${columnState}:${dispatchState}`);
  }

  const heartbeatAt = toIsoOrNull(metadata["overdeck.heartbeat_at"]);
  const heartbeatAgeMs = heartbeatAt === null ? null : nowMs - Date.parse(heartbeatAt);
  const heartbeatMissing = dispatchState === "running" && heartbeatAt === null;
  const heartbeatStale = dispatchState === "running"
    && heartbeatAgeMs !== null
    && (heartbeatAgeMs > RUNNING_HEARTBEAT_STALE_MS || heartbeatAgeMs < -RUNNING_HEARTBEAT_MAX_FUTURE_MS);
  if (heartbeatMissing) {
    details.push("agent heartbeat absent-or-invalid");
  } else if (heartbeatStale) {
    details.push(`agent heartbeat stale:last-confirmed=${heartbeatAt}`);
  }

  return {
    state: disagreement || !columnState || heartbeatMissing || heartbeatStale ? "needs-attention" : dispatchState,
    coverage: buildCoverage(details),
  };
}

function buildIncidentId(task: TaskRecord, metadata: TaskMetadata): string {
  return metadata["overdeck.incident_id"]?.trim() || task.reference.trim() || String(task.id);
}

function buildActivity(taskComments: TaskComment[]): IncidentActivity[] {
  return taskComments
    .map((comment) => ({
      id: comment.id,
      at: unixToIso(comment.date_creation),
      comment: comment.comment,
      username: comment.username,
    }));
}

function sortByDate(a: TaskRecord, b: TaskRecord): number {
  return (a.date_modification ?? 0) - (b.date_modification ?? 0);
}

function identityStateMap(readiness: IncidentsReadiness): StateByColumn {
  const map = new Map<number, IncidentState>();
  for (const [name, id] of Object.entries(readiness.columnIds) as Array<[keyof typeof readiness.columnIds, number]>) {
    map.set(id, STATE_BY_COLUMN_NAME[name]);
  }
  return map;
}

function identityPriorityMap(readiness: IncidentsReadiness): PriorityBySwimlane {
  const map = new Map<number, IncidentPriority>();
  for (const [index, name] of INCIDENTS_SWIMLANES.entries()) {
    const mapped = PRIORITY_BY_NUMBER[index];
    const swimlaneId = readiness.swimlaneIds[name];
    if (!mapped) {
      continue;
    }
    map.set(swimlaneId, mapped);
  }
  return map;
}

async function readTasks(
  client: KanboardRpcClient,
  readiness: IncidentsReadiness,
  query: ListIncidentsQuery,
): Promise<KanboardResult<"overdeck.listTasksBounded">> {
  const limit = Math.min(query.limit ?? 50, 100);
  const page = await client.call("overdeck.listTasksBounded", {
    projectId: readiness.projectId,
    statusId: query.scope === "active" ? 1 : query.scope === "resolved" ? 0 : null,
    limit,
    cursor: query.cursor ?? null,
    highWater: query.highWater ?? null,
    query: query.query?.trim() ?? "",
    priority: query.priority === undefined ? null : PRIORITY_NUMBER[query.priority],
  });
  if (!page.complete || page.order !== "id_desc") {
    throw new KanboardRpcError("RESPONSE_SCHEMA_INVALID", "bounded task listing is incomplete or unstable");
  }
  return page;
}

async function readMetadataBatch(
  client: KanboardRpcClient,
  tasks: readonly TaskRecord[],
): Promise<MetadataByTask> {
  if (tasks.length === 0) {
    return new Map();
  }
  const payload = tasks.map((task) => ({
    method: "getTaskMetadata" as const,
    params: { task_id: task.id },
  }));

  const results = await client.batch(payload);
  const map = new Map<number, TaskMetadata>();
  for (let i = 0; i < tasks.length; i += 1) {
    const task = tasks[i];
    const metadata = results[i];
    if (task && metadata) {
      map.set(task.id, metadata);
    }
  }
  return map;
}

async function readCommentsBatch(
  client: KanboardRpcClient,
  tasks: readonly number[],
): Promise<CommentListByTask> {
  if (tasks.length === 0) {
    return new Map();
  }
  const payload = tasks.map((taskId) => ({
    method: "getAllComments" as const,
    params: { task_id: taskId },
  }));
  const results = await client.batch(payload);
  const map = new Map<number, IncidentActivity[]>();
  for (let i = 0; i < tasks.length; i += 1) {
    const taskId = tasks[i];
    if (taskId === undefined) continue;
    const comments = results[i] ?? [];
    map.set(taskId, buildActivity(comments));
  }
  return map;
}

function buildIncident(
  task: TaskRecord,
  metadata: TaskMetadata,
  stateByColumn: StateByColumn,
  priorityBySwimlane: PriorityBySwimlane,
  activity: IncidentActivity[] = [],
  nowMs: number = Date.now(),
): Incident {
  const numericPriority = mapPriority(task.priority);
  const priorityFromSwimlane = resolvePriorityBySwimlane(task.swimlane_id, priorityBySwimlane);
  const { state, coverage } = buildState(task, stateByColumn, metadata, nowMs);
  const extraCoverage: string[] = [];

  if (numericPriority === null) {
    extraCoverage.push(`priority-unmapped:${task.priority}`);
  }
  if (priorityFromSwimlane === null) {
    extraCoverage.push(`priority-swimlane-unmapped:${task.swimlane_id}`);
  } else if (numericPriority !== null && priorityFromSwimlane !== numericPriority) {
    extraCoverage.push(`priority-swimlane-mismatch:${priorityFromSwimlane}:${numericPriority}`);
  }

  const priority = numericPriority !== null && priorityFromSwimlane === numericPriority
    ? numericPriority
    : null;

  const mergedCoverage = buildCoverage([
    ...(coverage.detail ? [coverage.detail] : []),
    ...extraCoverage,
  ]);

  return {
    id: buildIncidentId(task, metadata),
    kanboardTaskId: task.id,
    title: task.title,
    description: stripMarker(task.description),
    priority,
    incidentType: toDispatchMetadata(metadata["overdeck.incident_type"]),
    dispatchBrief: metadata["overdeck.dispatch_brief"] ?? null,
    dispatchBriefProvenance: toDispatchMetadata(metadata["overdeck.dispatch_brief_provenance"]),
    state,
    active: task.is_active,
    createdAt: unixToIso(task.date_creation),
    updatedAt: unixToIso(task.date_modification),
    resolvedAt: unixToIso(task.date_completed),
    dispatch: buildDispatch(metadata, state),
    activity,
    coverage: mergedCoverage,
  };
}

function matchesTaskQuery(
  task: TaskRecord,
  query: string | undefined,
  priority: IncidentPriority | undefined,
  priorityBySwimlane: PriorityBySwimlane,
): boolean {
  if (priority !== undefined && priorityBySwimlane.get(task.swimlane_id) !== priority) {
    return false;
  }
  if (!query) {
    return true;
  }
  const haystack = `${task.title}\n${task.description}`.toLowerCase();
  return haystack.includes(query.toLowerCase());
}

function filingMarker(requestId: string): string {
  return `Overdeck-Incident: ${requestId}`;
}

function matchesFilingProvenance(task: TaskRecord, request: FileIncidentRequest): boolean {
  const reference = task.reference.trim();
  if (reference.length > 0 && reference !== request.requestId) return false;
  const marker = filingMarker(request.requestId);
  const normalized = task.description.replace(/\r\n/g, "\n").trimEnd();
  if (!normalized.endsWith(marker)) return false;
  return task.title === request.title && stripMarker(task.description) === request.description.trim();
}

function isAdoptableOrphan(task: TaskRecord, request: FileIncidentRequest, readiness: IncidentsReadiness): boolean {
  if (!task.is_active) return false;
  if (task.column_id === readiness.columnIds.Resolved) return false;
  if (task.column_id !== readiness.columnIds.Filed) return false;
  return matchesFilingProvenance(task, request);
}

function isDispatchable(
  metadata: TaskMetadata,
  task: TaskRecord,
  readiness: IncidentsReadiness,
  mutationStore?: IncidentMutationStore,
): boolean {
  const incidentId = metadata["overdeck.incident_id"]?.trim();
  if (metadata["overdeck.dispatch_state"] === "starting") {
    if (task.column_id === readiness.columnIds.Filed) return true;
    if (
      task.column_id === readiness.columnIds.Dispatching
      && mutationStore
      && incidentId
    ) {
      const claim = mutationStore.getLaunchClaim(incidentId);
      return claim !== null && claim.phase !== "started";
    }
    return false;
  }
  return task.column_id === readiness.columnIds.Filed && buildDispatchState(metadata) === "filed";
}

export function createIncidentService({ client, readiness, brief, now = Date.now, loadIncidentOptions, mutationStore, launcher, workspaceFor, wrapperFor, recordStatus, verifyResolutionArtifact, recordResolutionLearning }: CreateIncidentServiceOptions): IncidentService {

  const stateByColumn = identityStateMap(readiness);
  const priorityBySwimlane = identityPriorityMap(readiness);
  const emptyMetadata: TaskMetadata = {};

  function requestHash(request: FileIncidentRequest): string {
    return createHash("sha256").update(JSON.stringify(request)).digest("hex");
  }

  function requestMetadata(request: FileIncidentRequest, hash: string, wrapperModel = ""): Record<string, string> {
    return {
      "overdeck.schema": "incident/v1",
      "overdeck.incident_id": request.requestId,
      "overdeck.request_sha256": hash,
      "overdeck.cli": request.cli,
      "overdeck.model": request.model,
      "overdeck.wrapper_model": wrapperModel,
      "overdeck.reasoning_effort": request.reasoningEffort,
      "overdeck.account": request.account,
      "overdeck.unsafe": request.unsafe ? "1" : "0",
      "overdeck.priority": request.priority,
      "overdeck.dispatch_id": "",
      "overdeck.dispatch_state": "",
      "overdeck.status_revision": "",
      ...(request.incidentType ? { "overdeck.incident_type": request.incidentType } : {}),
    };
  }

  async function requireIncidentOptions(): Promise<LoadedIncidentOptions> {
    if (!loadIncidentOptions) throw new IncidentMutationError("incident-dispatch-options-stale");
    return loadIncidentOptions();
  }

  async function validatePersistedIncidentType(metadata: TaskMetadata): Promise<void> {
    const incidentType = metadata["overdeck.incident_type"];
    if (incidentType === undefined) return;
    const options = await requireIncidentOptions();
    try {
      validateIncidentType(incidentType, options);
    } catch (error) {
      if (error instanceof InvalidIncidentTypeError) throw new IncidentMutationError("incident-dispatch-options-stale");
      throw error;
    }
  }

  async function validatePersistedSelection(metadata: TaskMetadata): Promise<ValidatedIncidentDispatchSelection> {
    const unsafe = metadata["overdeck.unsafe"];
    if (unsafe !== "0") throw new IncidentMutationError("incident-dispatch-options-stale");
    const options = await requireIncidentOptions();
    try {
      const selection = validateIncidentDispatchSelection({ cli: metadata["overdeck.cli"] ?? "", model: metadata["overdeck.model"] ?? "", reasoningEffort: metadata["overdeck.reasoning_effort"] ?? "", account: metadata["overdeck.account"] ?? "", unsafe: false }, options);
      if (metadata["overdeck.wrapper_model"] && metadata["overdeck.wrapper_model"] !== selection.wrapperModel) throw new IncidentMutationError("incident-dispatch-options-stale");
      return selection;
    } catch (error) {
      if (error instanceof IncidentOptionsError || error instanceof IncidentMutationError) throw error;
      if (error instanceof InvalidIncidentDispatchError) throw new IncidentMutationError("incident-dispatch-options-stale");
      throw error;
    }
  }

  interface LeaseContext {
    key: string;
    holder: string;
    lost: boolean;
  }

  function renewLease(lease: LeaseContext | null): void {
    if (mutationStore && lease) {
      if (lease.lost || !mutationStore.renewLease(lease.key, lease.holder, now())) {
        lease.lost = true;
        throw new IncidentMutationLeaseError("incident mutation lease lost");
      }
    }
  }

  async function withLeaseFence<T>(lease: LeaseContext | null, sideEffect: () => Promise<T>): Promise<T> {
    renewLease(lease);
    const result = await sideEffect();
    renewLease(lease);
    return result;
  }

  function advanceLaunchPhase(
    lease: LeaseContext | null,
    incidentId: string,
    fromPhase: LaunchPhase,
    toPhase: LaunchPhase,
  ): boolean {
    if (!mutationStore) return true;
    if (!lease) throw new IncidentMutationError("invalid-request");
    return mutationStore.advanceLaunchPhase(
      incidentId,
      fromPhase,
      toPhase,
      lease.key,
      lease.holder,
      now(),
    );
  }

  function completedLaunchReceipt(incidentId: string, dispatchId: string): IncidentLaunchReceipt {
    return {
      dispatchId,
      unit: `overdeck-incident-${incidentId}.service`,
      acceptedAt: new Date(now()).toISOString(),
    };
  }

  function assembleLaunchBrief(task: TaskRecord, metadata: TaskMetadata): TaskMetadata {
    if (metadata["overdeck.dispatch_brief"]) return metadata;
    if (!brief) throw new BriefAssemblyError("brief dependencies are not configured on this collector");
    const assembled = assembleDispatchBrief(buildIncident(task, metadata, stateByColumn, priorityBySwimlane), brief.deps);
    return {
      ...metadata,
      "overdeck.dispatch_brief": assembled.text,
      "overdeck.dispatch_brief_provenance": brief.provenance(),
    };
  }

  async function launchTask(lease: LeaseContext | null, task: TaskRecord, metadata: TaskMetadata, selection: ValidatedIncidentDispatchSelection): Promise<IncidentLaunchReceipt> {
    if (!launcher || !workspaceFor || !wrapperFor || !recordStatus || !selection.wrapper || !selection.timeoutSeconds) throw new IncidentMutationError("invalid-request");
    const wrapper = selection.wrapper;
    const timeoutSeconds = selection.timeoutSeconds;
    if (metadata["overdeck.unsafe"] !== "0" || selection.permissionMode !== "safe") throw new IncidentMutationError("incident-dispatch-options-stale");
    metadata = assembleLaunchBrief(task, metadata);
    const persistedBrief = metadata["overdeck.dispatch_brief"]!;
    const incidentId = metadata["overdeck.incident_id"] ?? task.reference;
    const preferredDispatchId = metadata["overdeck.dispatch_state"] === "starting" && metadata["overdeck.dispatch_id"]
      ? metadata["overdeck.dispatch_id"]
      : null;
    let dispatchId = preferredDispatchId ?? randomUUID();
    let launchPhase: LaunchPhase = "claimed";
    if (mutationStore) {
      const claim = mutationStore.claimLaunch(incidentId, task.id, preferredDispatchId, now());
      if (claim.result === "lost") throw new IncidentMutationError("not-filed");
      dispatchId = claim.dispatchId;
      launchPhase = claim.phase;
    }
    const starting = { ...metadata, "overdeck.dispatch_id": dispatchId, "overdeck.dispatch_state": "starting", "overdeck.status_revision": "1" };

    if (launchPhase === "claimed") {
      await withLeaseFence(lease, () => client.call("saveTaskMetadata", { task_id: task.id, values: starting }));
      if (mutationStore) {
        if (!advanceLaunchPhase(lease, incidentId,"claimed", "metadata")) {
          launchPhase = mutationStore.getLaunchClaim(incidentId)?.phase ?? "metadata";
        } else {
          launchPhase = "metadata";
        }
      } else {
        launchPhase = "metadata";
      }
    }

    if (launchPhase === "metadata") {
      const current = await withLeaseFence(lease, () => client.call("getTask", { task_id: task.id }));
      if (current.column_id !== readiness.columnIds.Dispatching) {
        try {
          await withLeaseFence(lease, () => client.call("moveTaskPosition", { project_id: readiness.projectId, task_id: task.id, column_id: readiness.columnIds.Dispatching, position: 1, swimlane_id: task.swimlane_id }));
        } catch (error) {
          throw new IncidentLaunchError("start", `dispatch transition incomplete: ${String(error)}`);
        }
      }
      if (mutationStore) {
        if (!advanceLaunchPhase(lease, incidentId,"metadata", "board")) {
          launchPhase = mutationStore.getLaunchClaim(incidentId)?.phase ?? "board";
        } else {
          launchPhase = "board";
        }
      } else {
        launchPhase = "board";
      }
    }

    if (launchPhase === "board") {
      try {
        const receipt = await withLeaseFence(lease, () => launcher.launch({ incidentId: metadata["overdeck.incident_id"] ?? task.reference, taskId: task.id, dispatchId, brief: persistedBrief, workspace: workspaceFor(metadata["overdeck.incident_id"] ?? task.reference), wrapper: wrapperFor(wrapper), wrapperModel: selection.wrapperModel, account: metadata["overdeck.account"] ?? "", accountMode: selection.fixed ? "fixed" : "profile", permissionMode: "safe", timeoutSeconds, initialRevision: 1, priority: (metadata["overdeck.priority"] as IncidentPriority) || "P2" }));
        if (!advanceLaunchPhase(lease, incidentId, "board", "started")) {
          launchPhase = mutationStore?.getLaunchClaim(incidentId)?.phase ?? "started";
          if (launchPhase !== "started") throw new IncidentMutationError("invalid-request");
        }
        return receipt;
      } catch (error) {
        if (error instanceof IncidentMutationLeaseError) throw error;
        const at = new Date(now()).toISOString();
        try {
          await withLeaseFence(lease, () => recordStatus({ incidentId: metadata["overdeck.incident_id"] ?? task.reference, taskId: task.id, dispatchId, revision: 2, state: "needs-attention", at, completedAt: at, failureClass: `${error instanceof IncidentLaunchError ? error.stage : "start"}-refused`, comment: "Incident launch refused; operator attention is required. No retry was started." }));
        } catch (statusProjectionError) {
          if (error instanceof Error) {
            Object.defineProperty(error, "statusProjectionError", { value: statusProjectionError, enumerable: false });
          }
        }
        throw error;
      }
    }

    return completedLaunchReceipt(incidentId, dispatchId);
  }

  const mutationLocks = new Map<string, Promise<unknown>>();

  async function sleep(ms: number): Promise<void> {
    await new Promise((resolve) => setTimeout(resolve, ms));
  }

  async function withDurableMutationLock<T>(key: string, fn: (lease: LeaseContext | null) => Promise<T>): Promise<T> {
    if (!mutationStore) {
      return withMutationLock(key, () => fn(null));
    }
    const holder = randomUUID();
    const deadline = now() + 30_000;
    while (now() < deadline) {
      if (mutationStore.acquire(key, holder, now())) {
        const lease: LeaseContext = { key, holder, lost: false };
        const renewEveryMs = 30_000;
        let renewTimer: ReturnType<typeof setInterval> | undefined;
        try {
          renewTimer = setInterval(() => {
            if (!mutationStore.renewLease(key, holder, now())) lease.lost = true;
          }, renewEveryMs);
          return await fn(lease);
        } finally {
          if (renewTimer !== undefined) clearInterval(renewTimer);
          mutationStore.release(key, holder);
        }
      }
      await sleep(10);
    }
    throw new IncidentMutationError("invalid-request");
  }

  function withMutationLock<T>(key: string, fn: () => Promise<T>): Promise<T> {
    const prev = mutationLocks.get(key) ?? Promise.resolve();
    const run = prev.then(fn, fn);
    const tail = run.then(
      () => undefined,
      () => undefined,
    );
    mutationLocks.set(key, tail);
    void tail.then(() => {
      if (mutationLocks.get(key) === tail) {
        mutationLocks.delete(key);
      }
    });
    return run;
  }

  function withTaskMutationLock<T>(task: TaskRecord, fn: (lease: LeaseContext | null) => Promise<T>): Promise<T> {
    return withDurableMutationLock(`task:${task.project_id}:${task.id}`, fn);
  }

  function withIncidentMutationLock<T>(incidentId: string, fn: (lease: LeaseContext | null) => Promise<T>): Promise<T> {
    return withDurableMutationLock(`incident:${incidentId}`, fn);
  }

  async function requireBoundUnitInactive(incidentId: string, dispatchId: string | null | undefined): Promise<void> {
    if (!dispatchId || !launcher?.isActive) throw new IncidentMutationError("invalid-request");
    if (await launcher.isActive({ incidentId, dispatchId })) throw new IncidentMutationError("invalid-request");
  }

  async function getTaskOrNull(taskId: number): Promise<TaskRecord | null> {
    try {
      return await client.call("getTask", { task_id: taskId });
    } catch (error) {
      if (isTaskMissing(error)) return null;
      throw error;
    }
  }

  async function findTask(incidentId: string): Promise<TaskRecord | null> {
    try {
      return await client.call("getTaskByReference", {
        project_id: readiness.projectId,
        reference: incidentId,
      });
    } catch (error) {
      if (!isTaskMissing(error)) {
        throw error;
      }
    }
    if (!/^\d+$/.test(incidentId)) {
      return null;
    }
    try {
      return await client.call("getTask", { task_id: Number(incidentId) });
    } catch (error) {
      if (isTaskMissing(error)) {
        return null;
      }
      throw error;
    }
  }

  async function findTaskForFiling(incidentId: string): Promise<TaskRecord | null> {
    return findTask(incidentId);
  }

  async function hydrateAndAssemble(tasks: readonly TaskRecord[]): Promise<Incident[]> {
    const metadataByTask = await readMetadataBatch(client, tasks);
    return tasks.map((task) =>
      buildIncident(
        task,
        metadataByTask.get(task.id) ?? emptyMetadata,
        stateByColumn,
        priorityBySwimlane,
        [],
        now(),
      ),
    );
  }

  async function hydrateOne(task: TaskRecord): Promise<Incident> {
    const metadata = await client.call("getTaskMetadata", { task_id: task.id });
    const activity = (await readCommentsBatch(client, [task.id])).get(task.id) ?? [];
    return buildIncident(task, metadata, stateByColumn, priorityBySwimlane, activity, now());
  }

  async function closeResolvedTask(taskId: number): Promise<TaskRecord> {
    const result = await client.call("closeTask", { task_id: taskId });
    const refreshed = await client.call("getTask", { task_id: taskId });
    if (result !== true && refreshed.is_active) throw new IncidentMutationError("invalid-request");
    if (refreshed.is_active) throw new IncidentMutationError("invalid-request");
    return refreshed;
  }

  async function completeResolution(resolvedTask: TaskRecord, operation: PendingResolutionRecord, existingLease?: LeaseContext): Promise<Incident> {
    const evidence = JSON.parse(operation.evidenceJson) as VerifiedResolutionEvidence;
    const run = async (lease: LeaseContext | null): Promise<Incident> => {
      if (!lease) throw new IncidentMutationError("invalid-request");
      renewLease(lease);
      const task = await client.call("getTask", { task_id: resolvedTask.id });
      if (task.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      const metadata = await client.call("getTaskMetadata", { task_id: task.id });
      const canonicalIncidentId = metadata["overdeck.incident_id"] ?? task.reference;
      if (task.id !== operation.taskId
        || task.project_id !== readiness.projectId
        || canonicalIncidentId !== operation.incidentId
        || evidence.incidentId !== operation.incidentId
        || createHash("sha256").update(operation.evidenceJson).digest("hex") !== operation.evidenceSha256) {
        throw new IncidentResolutionConflictError("persisted resolution identity does not match the canonical incident");
      }
      let current = operation;
      if (current.phase === "verified") {
        const revision = Number(metadata["overdeck.status_revision"]);
        const alreadyResolved = metadata["overdeck.dispatch_state"] === "resolved" && metadata["overdeck.resolution_artifact"] === evidence.artifact;
        const expectedRevision = Number.isSafeInteger(revision) && revision > 0 ? revision : 0;
        const nextRevision = alreadyResolved ? expectedRevision : expectedRevision + 1;
        const at = metadata["overdeck.completed_at"] || new Date(now()).toISOString();
        await withLeaseFence(lease, () => recordStatus!({
          incidentId: canonicalIncidentId, taskId: task.id, dispatchId: metadata["overdeck.dispatch_id"] || `resolve:${canonicalIncidentId}`,
          revision: nextRevision, expectedRevision: alreadyResolved ? Math.max(0, nextRevision - 1) : expectedRevision,
          state: "resolved", at, completedAt: at, resolutionArtifact: evidence.artifact,
          resolutionSummary: evidence.howSolved, resolutionOperatorNote: evidence.operatorNote ?? "",
          comment: `Resolved via Overdeck — artifact: ${evidence.artifact}\n${evidence.howSolved}`,
        }));
        if (!mutationStore!.advanceResolutionPhase(canonicalIncidentId, "verified", "closed", lease.key, lease.holder, now())) {
          current = { ...mutationStore!.claimResolution(canonicalIncidentId, task.id, current.evidenceSha256, current.evidenceJson), incidentId: canonicalIncidentId };
          if (current.phase === "verified") throw new IncidentMutationLeaseError("resolution phase advance failed");
        } else {
          current = { ...current, phase: "closed" };
        }
      }
      if (current.phase === "closed") {
        await withLeaseFence(lease, () => recordResolutionLearning!(evidence));
        if (!mutationStore!.advanceResolutionPhase(canonicalIncidentId, "closed", "learned", lease.key, lease.holder, now())) {
          current = { ...mutationStore!.claimResolution(canonicalIncidentId, task.id, current.evidenceSha256, current.evidenceJson), incidentId: canonicalIncidentId };
          if (current.phase !== "learned") throw new IncidentMutationLeaseError("resolution phase advance failed");
        }
      }
      return hydrateOne(await client.call("getTask", { task_id: task.id }));
    };
    return existingLease ? run(existingLease) : withTaskMutationLock(resolvedTask, run);
  }

  return {
    async listIncidents(query): Promise<ListIncidentsResult> {
      const page = await readTasks(client, readiness, query);
      const mapped = await hydrateAndAssemble(page.tasks);

      return {
        incidents: mapped,
        page: {
          highWater: page.high_water,
          nextCursor: page.next_cursor,
          exhausted: page.exhausted,
          order: page.order,
        },
        coverage: buildCoverage([
          ...(readiness.status === "degraded"
            ? [`bootstrap-degraded:${readiness.drift.join(",")}`]
            : []),
          ...(mapped.some((incident) => incident.coverage.stale) ? ["incident-drift"] : []),
        ]),
      };
    },
    async getIncident(incidentId: string): Promise<Incident | null> {
      const task = await findTask(incidentId);
      if (!task || task.project_id !== readiness.projectId) {
        return null;
      }
      return hydrateOne(task);
    },
    async dispatchIncident(incidentId, options = {}): Promise<Incident> {
      const resolvedTask = await findTask(incidentId);
      if (!resolvedTask || resolvedTask.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      return withTaskMutationLock(resolvedTask, async (lease) => {
        if (readiness.status !== "ready") throw new IncidentMutationError("invalid-request");
        const task = await client.call("getTask", { task_id: resolvedTask.id });
        if (task.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
        const metadata = await client.call("getTaskMetadata", { task_id: task.id });
        if (!isDispatchable(metadata, task, readiness, mutationStore)) throw new IncidentMutationError("not-filed");
        if (metadata["overdeck.unsafe"] !== "0") throw new IncidentMutationError("incident-dispatch-options-stale");
        await validatePersistedIncidentType(metadata);
        const selection = await validatePersistedSelection(metadata);

        let briefValues: Record<string, string>;
        let comment: string;
        if (options.withoutBrief === true) {
          briefValues = { "overdeck.dispatch_brief_skipped": "1" };
          comment = "Dispatch requested from Overdeck WITHOUT a brief (owner override).";
        } else {
          if (brief === undefined) {
            throw new BriefAssemblyError("brief dependencies are not configured on this collector");
          }
          const assembled = assembleDispatchBrief(
            buildIncident(task, metadata, stateByColumn, priorityBySwimlane),
            brief.deps,
          );
          briefValues = {
            "overdeck.dispatch_brief": assembled.text,
            "overdeck.dispatch_brief_provenance": brief.provenance(),
          };
          comment = "Dispatch requested from Overdeck.";
        }

        const launchMetadata = { ...metadata, ...briefValues };
        if (launcher && workspaceFor && wrapperFor && recordStatus) {
          await launchTask(lease,task, launchMetadata, selection);
        } else {
          await client.call("saveTaskMetadata", { task_id: task.id, values: { ...launchMetadata, "overdeck.dispatch_id": randomUUID(), "overdeck.dispatch_state": "starting", "overdeck.status_revision": "1" } });
          await client.call("moveTaskPosition", { project_id: readiness.projectId, task_id: task.id, column_id: readiness.columnIds.Dispatching, position: 1, swimlane_id: task.swimlane_id });
        }
        await client.call("createComment", { task_id: task.id, content: comment, user_id: readiness.agentUserId });
        const updated = await client.call("getTask", { task_id: task.id });
        return hydrateOne(updated);
      });
    },
    async resumeResolution(operation): Promise<Incident> {
      if (!recordStatus || !mutationStore || !recordResolutionLearning) throw new IncidentMutationError("invalid-request");
      const task = await client.call("getTask", { task_id: operation.taskId });
      if (task.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      return completeResolution(task, operation);

    },
    async stopIncident(incidentId): Promise<Incident> {
      const resolvedTask = await findTask(incidentId);
      if (!resolvedTask || resolvedTask.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      return withTaskMutationLock(resolvedTask, async (lease) => {
        const task = await client.call("getTask", { task_id: resolvedTask.id });
        if (task.project_id !== readiness.projectId || task.id !== resolvedTask.id) throw new IncidentMutationError("not-found");
        const metadata = await client.call("getTaskMetadata", { task_id: task.id });
        const canonicalIncidentId = metadata["overdeck.incident_id"] ?? task.reference;
        const dispatchId = metadata["overdeck.dispatch_id"];
        const incident = buildIncident(task, metadata, stateByColumn, priorityBySwimlane);
        if (!incident.active || !dispatchId || !launcher?.stop || canonicalIncidentId !== incidentId) throw new IncidentMutationError("invalid-request");
        await withLeaseFence(lease, () => launcher.stop!({ incidentId: canonicalIncidentId, dispatchId }));
        const stoppedAt = new Date(now()).toISOString();
        const revision = Number(metadata["overdeck.status_revision"]);
        if (recordStatus) await withLeaseFence(lease, () => recordStatus({ incidentId: canonicalIncidentId, taskId: task.id, dispatchId, revision: Number.isSafeInteger(revision) ? revision + 1 : 1, expectedRevision: Number.isSafeInteger(revision) ? revision : 0, state: "needs-attention", at: stoppedAt, completedAt: stoppedAt, failureClass: "operator-stopped", comment: "Incident work stopped by operator." }));
        return hydrateOne(await closeResolvedTask(task.id));
      });
    },
    async deleteIncident(incidentId): Promise<void> {
      if (!mutationStore) throw new IncidentMutationError("invalid-request");
      let pending = mutationStore.getDeletion(incidentId);
      if (pending?.phase === "finalized") {
        const current = await findTask(incidentId);
        if (!current) return;
        if (current.id === pending.taskId) return;
        mutationStore.retireFinalizedDeletion(incidentId, pending.taskId);
        pending = null;
      }
      const resolvedTask = pending ? null : await findTask(incidentId);
      if (!resolvedTask && !pending) throw new IncidentMutationError("not-found");
      const lockTask = resolvedTask ?? { id: pending!.taskId, project_id: readiness.projectId } as TaskRecord;
      if (lockTask.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      await withTaskMutationLock(lockTask, async (lease) => {
        if (!lease) throw new IncidentMutationError("invalid-request");
        const currentPending = mutationStore.getDeletion(incidentId);
        if (currentPending?.phase === "finalized") return;
        const currentTask = await getTaskOrNull(lockTask.id);
        let task = currentTask;
        if (currentPending && !currentTask) {
          const successor = await findTask(incidentId);
          if (successor) {
            const successorMetadata = await client.call("getTaskMetadata", { task_id: successor.id });
            const successorCanonicalId = successorMetadata["overdeck.incident_id"] ?? successor.reference;
            const successorIncident = buildIncident(successor, successorMetadata, stateByColumn, priorityBySwimlane);
            const quarantined = successor.id !== currentPending.taskId
              && successor.project_id === readiness.projectId
              && successorCanonicalId === incidentId
              && !successorIncident.active
              && mutationStore.quarantineDeletion(incidentId, currentPending.taskId, currentPending.holder, lease.key, lease.holder, now());
            if (!quarantined) throw new IncidentMutationError("invalid-request");
            throw new IncidentMutationError("invalid-request");
          }
        }
        if (currentPending && currentTask) {
          const currentMetadata = await client.call("getTaskMetadata", { task_id: currentTask.id });
          const currentCanonicalId = currentMetadata["overdeck.incident_id"] ?? currentTask.reference;
          if (currentTask.id !== currentPending.taskId || currentTask.project_id !== readiness.projectId || currentCanonicalId !== incidentId || buildIncident(currentTask, currentMetadata, stateByColumn, priorityBySwimlane).active) {
            if (!mutationStore.quarantineDeletion(incidentId, currentPending.taskId, currentPending.holder, lease.key, lease.holder, now())) throw new IncidentMutationError("invalid-request");
            throw new IncidentMutationError("invalid-request");
          }
        }
        let phase = currentPending ? mutationStore.adoptDeletion(incidentId, currentPending.taskId, currentPending.phase, currentPending.holder, lease.key, lease.holder, now()) : null;
        let boundDispatchId: string | null = null;
        if (!phase) {
          if (!task || task.project_id !== readiness.projectId || task.id !== lockTask.id) throw new IncidentMutationError("not-found");
          const metadata = await client.call("getTaskMetadata", { task_id: task.id });
          const canonicalIncidentId = metadata["overdeck.incident_id"] ?? task.reference;
          if (canonicalIncidentId !== incidentId || buildIncident(task, metadata, stateByColumn, priorityBySwimlane).active) throw new IncidentMutationError("invalid-request");
          boundDispatchId = metadata["overdeck.dispatch_id"]?.trim() || null;
          const launchClaim = mutationStore.getLaunchClaim(canonicalIncidentId);
          if (launchClaim && (launchClaim.taskId !== task.id || launchClaim.dispatchId !== boundDispatchId)) throw new IncidentMutationError("invalid-request");
          phase = mutationStore.claimDeletion(canonicalIncidentId, task.id, lease.key, lease.holder, now());
        } else {
          const launchClaim = mutationStore.getLaunchClaim(incidentId);
          if (launchClaim) {
            if (launchClaim.taskId !== lockTask.id) throw new IncidentMutationError("invalid-request");
            boundDispatchId = launchClaim.dispatchId;
          }
        }
        if (boundDispatchId) await requireBoundUnitInactive(incidentId, boundDispatchId);
        if (phase === "intent" && task) {
          try {
            const removed = await withLeaseFence(lease, () => client.call("removeTask", { task_id: task!.id }));
            if (removed !== true) throw new IncidentMutationError("invalid-request");
          } catch (error) {
            const absentAfterError = await client.call("getTask", { task_id: task.id }).then(() => false, isTaskMissing);
            if (!absentAfterError) throw error;
          }
        }
        const absent = await client.call("getTask", { task_id: lockTask.id }).then(() => false, isTaskMissing);
        if (!absent) throw new IncidentMutationError("invalid-request");
        if (boundDispatchId) await requireBoundUnitInactive(incidentId, boundDispatchId);
        if (phase === "intent" && !mutationStore.markDeletionRemoved(incidentId, lockTask.id, lease.key, lease.holder, now())) throw new IncidentMutationError("invalid-request");
        if (!mutationStore.finalizeDeletion(incidentId, lockTask.id, lease.key, lease.holder, now())) throw new IncidentMutationError("invalid-request");
      });
    },
    async resolveIncident(incidentId, artifact, summary): Promise<Incident> {
      if (readiness.status !== "ready") throw new IncidentMutationError("invalid-request");
      if (!recordStatus || !mutationStore) throw new IncidentMutationError("invalid-request");
      const resolvedTask = await findTask(incidentId);
      if (!resolvedTask || resolvedTask.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
      return withTaskMutationLock(resolvedTask, async (lease) => {
        if (!lease) throw new IncidentMutationError("invalid-request");
        renewLease(lease);
        const task = await client.call("getTask", { task_id: resolvedTask.id });
        if (task.project_id !== readiness.projectId) throw new IncidentMutationError("not-found");
        const metadata = await client.call("getTaskMetadata", { task_id: task.id });
        const canonicalIncidentId = metadata["overdeck.incident_id"] ?? task.reference;
        if (metadata["overdeck.dispatch_state"] === "resolved" && metadata["overdeck.resolution_artifact"] !== artifact) {
          throw new IncidentResolutionConflictError(`incident is already resolved with artifact "${metadata["overdeck.resolution_artifact"] || "(none recorded)"}" — refusing to overwrite it with "${artifact}"`);
        }
        if (!verifyResolutionArtifact || !recordResolutionLearning) throw new IncidentResolutionArtifactError("resolution artifact verifier is not configured");
        let verifiedEvidence: VerifiedResolutionEvidence;
        try {
          verifiedEvidence = await verifyResolutionArtifact({ incidentId: canonicalIncidentId, incidentType: toDispatchMetadata(metadata["overdeck.incident_type"]), artifact, ...(summary === undefined ? {} : { summary }) });
        } catch (error) {
          throw new IncidentResolutionArtifactError(error instanceof Error ? error.message : "resolution artifact is not verified");
        }
        const evidenceJson = JSON.stringify(verifiedEvidence);
        let operation;
        try {
          operation = mutationStore.claimResolution(canonicalIncidentId, task.id, createHash("sha256").update(evidenceJson).digest("hex"), evidenceJson);
        } catch (error) {
          throw new IncidentResolutionConflictError(error instanceof Error ? error.message : "conflicting resolution evidence");
        }
        return completeResolution(task, { ...operation, incidentId: canonicalIncidentId }, lease);
      });
    },
    fileIncident(request: FileIncidentRequest): Promise<Incident> {
      return withIncidentMutationLock(request.requestId, async (lease) => {
        const options = await requireIncidentOptions();
        validateIncidentType(request.incidentType, options);
        const hash = requestHash(request);
        const selection = validateIncidentDispatchSelection(request, options);
        if (request.unsafe && selection.permissionMode !== "unsafe") throw new IncidentMutationError("incident-dispatch-options-stale");
        const values = requestMetadata(request, hash, selection.wrapperModel);
        const existing = await findTaskForFiling(request.requestId);
        if (existing) {
          const metadata = await client.call("getTaskMetadata", { task_id: existing.id });
          const storedHash = metadata["overdeck.request_sha256"];
          if (storedHash === hash) {
            if (launcher && workspaceFor && wrapperFor && recordStatus && !metadata["overdeck.dispatch_id"]) {
              await launchTask(lease,existing, metadata, selection);
              return hydrateOne(await client.call("getTask", { task_id: existing.id }));
            }
            return buildIncident(existing, metadata, stateByColumn, priorityBySwimlane);
          }
          if (storedHash !== undefined && storedHash !== "") {
            throw new IncidentIdempotencyConflictError("incident request id was already used");
          }
          if (!isAdoptableOrphan(existing, request, readiness)) {
            throw new IncidentIdempotencyConflictError("incident request id was already used");
          }
          await client.call("saveTaskMetadata", { task_id: existing.id, values });
          const repaired = await client.call("getTask", { task_id: existing.id });
          if (launcher && workspaceFor && wrapperFor && recordStatus) await launchTask(lease,repaired, values, selection);
          return launcher ? hydrateOne(await client.call("getTask", { task_id: repaired.id })) : buildIncident(repaired, values, stateByColumn, priorityBySwimlane);
        }

        const taskId = await client.call("createTask", {
          project_id: readiness.projectId,
          column_id: readiness.columnIds.Filed,
          title: request.title,
          description: `${request.description}\n\n${filingMarker(request.requestId)}`,
          swimlane_id: readiness.swimlaneIds[SWIMLANE_NAME_BY_PRIORITY[request.priority]],
          priority: PRIORITY_NUMBER[request.priority],
          reference: request.requestId,
        });
        await client.call("saveTaskMetadata", { task_id: taskId, values });
        const task = await client.call("getTask", { task_id: taskId });
        if (launcher && workspaceFor && wrapperFor && recordStatus) {
          await launchTask(lease,task, values, selection);
          return hydrateOne(await client.call("getTask", { task_id: taskId }));
        }
        return buildIncident(task, values, stateByColumn, priorityBySwimlane);
      });
    },
    getDispatchLauncher(): IncidentDispatchLauncher | null {
      return launcher ?? null;
    },
  };
}
