/**
 * Acceptance / Verification layer — types.
 *
 * A task is NOT "done" because the model stops calling tools; it is done when
 * its Verification Contract passes. The contract is a small list of
 * deterministic, machine-runnable checks attached to the task.
 */

export type CheckKind =
  | "build" // code compiles (npm run build)
  | "typecheck" // no type errors (tsc --noEmit)
  | "test" // unit/integration tests pass (npm test)
  | "server_up" // dev server boots and returns 200
  | "route_ok" // a route/endpoint returns the expected status code
  | "console_clean" // no runtime JS console errors on a page
  | "content" // expected text/element present on a page
  | "flow" // a user journey works (navigate + assert)
  | "visual" // UI meets a design rubric (request_visual_qa)
  | "data"; // seed/records exist (a query returns expected rows)

export interface AcceptanceCheck {
  kind: CheckKind;
  /** Hard checks gate "done". Soft checks are advisory and never block. */
  hard: boolean;
  /** Human-readable description shown in build-health reports. */
  description: string;
  /** Kind-specific parameters (command, url, expectedStatus, etc.). */
  spec: Record<string, unknown>;
}

export interface CheckResult {
  check: AcceptanceCheck;
  pass: boolean;
  /** Redacted, truncated evidence — fed back to the model on failure. */
  evidence: string;
}

export interface VerificationReport {
  /** True only when every HARD check passed. */
  passed: boolean;
  results: CheckResult[];
  /** Hard failures only — these are what the model must fix. */
  failures: CheckResult[];
}

export interface VerificationTask {
  id: string;
  title: string;
  status: "open" | "in_progress" | "done" | "blocked";
  acceptanceChecks: AcceptanceCheck[];
  attempts: number;
  lastFailures?: CheckResult[];
  /** Tasks that can't be objectively verified (e.g. "make copy friendlier"). */
  requiresHumanConfirm?: boolean;
}

/**
 * Abstraction over the agent's tool execution. Returns the raw tool result
 * string (usually JSON). Injecting this makes every runner unit-testable.
 */
export type ToolExecutor = (
  name: string,
  args: Record<string, unknown>,
) => Promise<string>;

export interface ExecCtx {
  projectId: string;
  /** Preview URL of the running dev server, when known. */
  previewUrl?: string;
  exec: ToolExecutor;
}
