/** FH-060 cumulative snapshots; absent fields preserve legacy state compatibility. */ export interface Usage { inputTokens: number; outputTokens: number; model?: string; source: "reported" | "metered"; at: string; } export interface UsageSources { reported: Usage | null; metered: Usage | null; } export type TokenBudgetState = "unchecked" | "within" | "near" | "over"; export interface BlockerResolution { at: string; by: "release" | "promote" | "owner"; reason?: string; } /** FH-048 public history. Missing fields on legacy records mean open/unknown. */ export interface WireBlocker { id: string; packet: string; claimingAgent: string; pushingAgent: string; repoName: string; sha: string; paths: string[]; resolved?: BlockerResolution | null; at?: string | null; pushingPacket?: string | null; } export interface BlockerView { id: string; agent: string; packet: string; paths: string[]; reason: string; resolved: boolean; resolution?: BlockerResolution | null; claimingAgent?: string; pushingAgent?: string; sha?: string; repoName?: string; at?: string | null; pushingPacket?: string | null; } /** View projection of the public FH-005 wire state; never includes credentials. */ export interface ProjectState { project: { id: string; repoName: string; defaultBranch: string; remote?: string; events?: "pending" | "active"; settings?: { requireReceipt: boolean }; }; canonicalHead?: string; recentActivity?: Activity[]; agents: { name: string; createdAt?: string | null }[]; forks: { agent: string; repoName: string; head: string; events?: "pending" | "active" }[]; packets: Packet[]; claims: { packet: string; agent: string; repoName: string; paths: string[]; active: boolean; usage?: UsageSources; createdAt?: string; }[]; blockers: BlockerView[]; races?: Race[]; reviews: Review[]; ledger: { id?: string; before?: string; review: string; sha: string; promotedAt: string; receiptDigest?: string | null; race?: string; }[]; reconcilerAlerts: { sha: string; message: string; id?: string; repoName?: string; ref?: string; before?: string; after?: string; }[]; promotionPending?: LedgerEntry | null; } export interface Packet { id: string; title: string; goal: string; paths: string[]; acceptance: string[]; mode?: "standard" | "race"; tokenBudget?: number | null; /** Absent legacy records are treated as null. */ archived?: null | { at: string; by: "owner" }; } export interface Review { id: string; repoName: string; agent: string; packet: string; sha: string; receiptDigest: string | null; requestedAt?: string; approvedAt?: string | null; base?: string; status: "pending" | "approved" | "stale" | "promoted"; /** Raw core flag, independent of the derived display status. */ promoted?: boolean; stale?: boolean; returned?: null | { reason: string; at: string }; approval?: { sha: string; receiptDigest: string | null } | null; receipt?: ReceiptSummary | null; usageAtReview?: UsageSources; } /** FH-032 fixed public wire summary: logs belong only to the owner receipt endpoint. */ export type ReceiptStatus = "running" | "passed" | "failed" | "infrastructure-error" | "timed-out"; export interface ReceiptSummary { status: ReceiptStatus; trigger: "review-created" | "before-promote"; digest: string | null; startedAt: string; finishedAt: string | null; durationMs: number | null; checks: { name: string; tier: "full" | "quick"; runtime?: "container" | "dynamic-worker"; message?: string; outcome: ReceiptStatus; durationMs: number | null; }[]; } /** Stored runner receipt returned by the owner-only endpoint. No bearer token plumbing. */ export interface OwnerReceipt { digest: string; receipt: { commit: string; checks: { check: { name: string }; logs: { stdout: string; stderr: string; truncated: boolean }; }[]; }; } /** FH-003 receive sequence is the cursor, not event time. */ export interface Activity { sequence: number; namespace: string; repoName: string; agent: string | null; ref: string; before: string; after: string; changedPaths: string[]; changedPathCount?: number; changedPathsTruncated?: boolean; eventTimestamp: string; recordedAt: string; } export interface ActivityPage { activity: Activity[]; nextAfter: number; } export interface ProjectOption { id: string; label: string; } export interface Brand { name: string; tagline: string; } /** An HTTP implementation today; a host may supply its Cap'n Web ui capability later. */ export interface DashboardTransport { /** Local connection state, separate from the Core wire snapshot. */ live?: { subscribe(listener: (paused: boolean) => void): () => void; reconnect(): Promise; }; getReview?(project: string, review: string): Promise; getDiff?(project: string, review: string, path: string): Promise; returnReview?( project: string, review: string, reason: string, ): Promise<{ review: StateResponse["reviews"][number] }>; archivePacket?(project: string, packet: string): Promise<{ packet: Packet }>; unarchivePacket?(project: string, packet: string): Promise<{ packet: Packet }>; resolveBlocker?(project: string, blocker: string, reason: string): Promise<{ blocker: WireBlocker }>; getState(project: string): Promise; getActivity(project: string, after?: number): Promise; approve(project: string, review: string): Promise; promote(project: string, review: string): Promise<{ sha: string }>; /** Optional because the read-only agent host has no owner capabilities. */ getReceipt?(project: string, review: string): Promise; setSettings?( project: string, settings: { requireReceipt: boolean }, ): Promise<{ settings: { requireReceipt: boolean } }>; /** Optional invalidations only. The authoritative snapshot still comes from getState. */ subscribe?(project: string, invalidate: () => void): () => void; } /** FH-005 JSON snapshot. Only live claims appear; blockers retain resolved history. */ export interface StateResponse { project: { id: string; namespace: string; repoName: string; remote: string; defaultBranch: string; events?: "pending" | "active"; settings?: { requireReceipt: boolean }; }; agents: { name: string; createdAt?: string | null }[]; forks: { agent: string; repoName: string; head: string; remote: string; createdAt: string; events?: "pending" | "active"; }[]; packets: ProjectState["packets"]; claims: { packet: string; agent: string; repoName: string; paths: string[]; createdAt: string; usage?: UsageSources }[]; blockers: WireBlocker[]; races?: Race[]; reviews: { approvedAt?: string | null; usageAtReview?: UsageSources; id: string; packet: string; agent: string; repoName: string; sha: string; base: string; receiptDigest: string | null; receipt?: ReceiptSummary | null; returned?: null | { reason: string; at: string }; approval: { sha: string; receiptDigest: string | null } | null; stale: boolean; promoted: boolean; createdAt: string; }[]; ledger: LedgerEntry[]; activity: Activity[]; reconcilerAlerts: { id: string; repoName: string; ref: string; before: string; after: string; reason: string; }[]; promotionPending: LedgerEntry | null; } export interface LedgerEntry { id: string; review: string; repoName: string; ref: string; before: string; after: string; receiptDigest: string | null; recordedAt: string; race?: string; } /** FH-039 fixed bounded detail contract. Public reads never contain logs or authentication credentials. */ export interface ReviewDetail { review: StateResponse["reviews"][number]; packet: ProjectState["packets"][number]; changes: { base: string; head: string; fileCount: number; truncated: boolean; files: { path: string; status: "added" | "modified" | "deleted" }[]; }; commits: { sha: string; subject: string; authorName: string; packetTrailer: string | null; agentTrailer: string | null; }[]; commitsTruncated: boolean; promotion: null | { before: string; after: string; recordedAt: string; receiptDigest: string | null; }; blockers: StateResponse["blockers"]; } export interface ReviewDiff { path: string; status: "added" | "modified" | "deleted"; binary: boolean; patch: string; truncated: boolean; } /** Optional FH-052/053 read projection; absent evidence is never synthesized. */ export interface RaceEntrant { usage?: UsageSources; budget?: TokenBudgetState; agent: string; repoName: string; claimedAt: string; firstPushAt: string | null; reviewRequestedAt: string | null; receiptPassedAt: string | null; approvedAt: string | null; promotedAt: string | null; place: number | null; closedAt: string | null; closedBy?: "release" | "owner" | "race-finished" | null; promoteRejected?: { at: string; expected: string; found: string } | null; } /** FH-063 fixed public read seam; absent fields preserve races created before judges. */ export interface RaceAdvice { ranking: string[]; rationale: string; at: string; } export interface Race { judge?: string | null; verdict?: RaceAdvice | null; packet: string; status: "open" | "finished"; tokenBudget?: number | null; entrants: RaceEntrant[]; finishedAt?: string | null; winner?: string | null; /** Exact string reference to ledger[].id; never an array position. */ ledgerEntryId?: string | null; places?: { agent: string; place: number }[]; }