jacquardSnapshot

← snapshot

4837 bytes
/** Wire types mirroring jac-serve's DTOs (crates/jac-serve/src/dto.rs). */

export type ProvenanceLabel = "human" | "agent" | "mixed";

export interface ActorView {
  kind: "human" | "agent" | "unknown";
  id: string;
  display_name?: string;
}

export interface SnapshotDto {
  id: string;
  short: string;
  tree: string;
  parents: string[];
  author: ActorView;
  provenance: ProvenanceLabel;
  message: string;
  at: number;
}

export interface RefDto {
  name: string;
  head: string;
}

export interface RepoSummary {
  slug: string;
  org: { id: string; name: string };
  default_ref: string;
  refs: number;
  decisions: { unsettled: number; settled: number };
  head: SnapshotDto | null;
  created_at: number;
}

export interface RepoDetail {
  slug: string;
  org: { id: string; name: string };
  default_ref: string;
  refs: RefDto[];
  humans: ActorView[];
  agents: ActorView[];
  decisions: { unsettled: number; settled: number };
  object_count: number;
  created_at: number;
}

export interface AttestationDto {
  id: string;
  decision: string;
  attestor: ActorView;
  statement: string;
  at: number;
}

export interface DecisionDto {
  id: string;
  short: string;
  title: string;
  rationale: string;
  families: string[];
  proposed_by: ActorView;
  scope: string[];
  at: number;
  state: "unsettled" | "settled";
  attestation?: AttestationDto;
}

export type VerdictDto =
  | {
      verdict: "admitted";
      decisions_checked: number;
      ungoverned: boolean;
      ref_moved: boolean;
      into_head?: string;
    }
  | {
      verdict: "blocked";
      reason: string;
      unsettled: string[];
      ref_moved: boolean;
    };

export interface PromotePreview {
  verdict: VerdictDto;
  changed: string[];
  fast_forward: boolean;
}

export interface FileEntry {
  path: string;
  blob: string;
  size: number;
}

export interface SnapshotDetail {
  snapshot: SnapshotDto;
  files: FileEntry[];
  changed_from_parent: string[];
}

export interface TreeEntryDto {
  name: string;
  kind: "blob" | "tree";
  id: string;
  size?: number;
}

export interface BlobDto {
  id: string;
  size: number;
  content: string | null;
  binary: boolean;
}

export interface PublicationRow {
  org: string;
  kind: "content" | "decision";
  at: number;
}

export interface IntroductionRow {
  token: string;
  parties: [string, string];
  at: number;
}

export interface SketchMatchRow {
  publication: string;
  org: string;
  similarity_permille: number;
  similarity_percent: string;
}

export interface ApiErrorBody {
  error: { code: string; message: string };
}

/** The init request — the whole ceremony in one POST. */
export interface InitRepoRequest {
  name: string;
  founder: { display_name: string };
  default_ref?: string;
  agents?: { model: string }[];
  initial_commit?: {
    message: string;
    files: { path: string; content: string }[];
    provenance?: ProvenanceLabel;
  };
  founding_decision?: {
    title: string;
    rationale: string;
    families?: string[];
    scope?: string[];
    attestation?: { statement: string };
  };
}

export interface InitRepoResponse {
  slug: string;
  org: { id: string; name: string };
  founder: ActorView;
  agents: ActorView[];
  default_ref: string;
  head: SnapshotDto | null;
  founding_decision: DecisionDto | null;
  created_at: number;
  honesty: string;
}

export const RATIONALE_FAMILIES: { label: string; hint: string }[] = [
  { label: "alternatives", hint: "Alternatives considered and what ruled them out." },
  { label: "constraints", hint: "The constraint that forced this shape." },
  {
    label: "missed-abstraction",
    hint: "An abstraction within reach that was skipped — deliberately or not.",
  },
  { label: "deferred-work", hint: "Known debt: what another week would have changed." },
  {
    label: "confidence-risk",
    hint: "The part the author is least sure will hold up.",
  },
];

/** What a reviewer meant by speaking up. */
export type RemarkKind = "suggestion" | "question" | "note";

/** What they were looking at when they said it. */
export interface RemarkAnchorDto {
  kind: "decision" | "file" | "snapshot" | "gate";
  id: string;
  /** The exact span they had selected, when they had one. */
  quote: string | null;
}

/**
 * Something a reviewer said that should be acted on.
 *
 * Not an engine object: a remark is conversation about the work, not an
 * attestable claim about it. The path to something durable is to draft it
 * into a decision, which a human then attests.
 */
export interface RemarkDto {
  id: string;
  anchor: RemarkAnchorDto;
  /** The reviewer's own words, verbatim. */
  body: string;
  kind: RemarkKind;
  by: { id: string; display_name: string | null };
  at: number;
  state: "open" | "drafted" | "declined";
  outcome: { decision?: string; because?: string } | null;
}