/** * The Agents page's readings per seat (DES-seats-page §7, asks A2–A6): what crew can say about a * seat's readiness as FACTS and CODES, so studio owns every word (one copy table per code) and * never re-derives an engine or crew rule. * * - `account` (A2): the account KIND only, never an identifier (`seat-scrub.ts`); * - `recent_bench` (A3): the engine's bench of the seat that is ACTIVE now, not the week's history * (`/roster/record` keeps that); * - `work_admission` (A5): per scope kind, whether a job would give the seat work, with ONE reason * code and where the refusal comes from (`auth`, `launcher`, `scope`). It reads the same standing * the launch does, plus the engine's own worktree bench through `Core.worktreeBenched` (core#920). * Without that predicate (an older addon) it is ABSENT: crew does not restate the engine's rule; * - `qe_reviewer` (A4): whether the seat can run the isolated QE review. Since wicked-core#917 the * engine starts the reviewer as a fresh session on ANY run seat it ADMITS, so the rule is: signed * in, kept by a run bound to one repository (QE runs only there), and admitted by the host's skill * routing to the QE skill (`Core.qeReviewerAdmitted`, wicked-core#923: a Claude-only skills root admits claude * seats only). A reviewer-only seat counts: the engine's reviewer pool is the run's seats, not * its workers. Absent unless the engine answers both predicates; * - `issues` (A6): one entry per thing the page shows, most important first. * * Pure: no IO, no clock. */ import type { SeatRecentBench } from './seat-health.js'; import type { GovernanceScopeKind, SeatGovernanceMode } from './seat-governance.js'; import type { SeatAccount } from './seat-scrub.js'; import { type ChatAdmission, type SeatStanding } from './seat-standing.js'; import type { SeatVersion } from './seat-version.js'; /** `RosterSeat.recent_bench` (api-types 0.115.0). */ export interface RecentBenchWire { /** The engine's cause token (`quota_exhausted`, `not_logged_in`, `not_installed`, * `approval_unavailable`, `timed_out`, …). */ kind: string; /** Runs that benched the seat while this bench was active. */ runs: number; /** ISO-8601 of the latest bench. */ last_at: string; /** ISO-8601 of when crew stops carrying the bench to new launches (sooner on an ok turn). (J4) For a * quota bench it is the engine's lift time (`until_source: 'engine'`: the provider's reset time when * the refusal stated one, else the engine's backoff) or crew's backoff of 15, 30, then 60 minutes * by `strikes` (`'backoff'`); any other kind keeps crew's 30-minute window (`'window'`). */ lifts_at: string; /** (J4) Where `lifts_at` came from. */ until_source: 'engine' | 'backoff' | 'window'; /** (J4) The seat's quota benches in a row with no good turn between (the backoff step); 0 on a * non-quota bench. */ strikes: number; /** Who benched it in the run: `worker`, `judge`, or (J4) `reprobe` — its quota bench fell due and * it did not answer the engine's re-probe. */ source: string; /** The engine's own reason, verbatim (Technical details). */ reason: string; } /** The engine's cause token: the reason up to its first parenthesis. */ export declare function benchKind(reason: string): string; export declare function recentBenchWire(bench: SeatRecentBench): RecentBenchWire; /** Whether the seat's live sign-in check, answered AFTER the bench, lifts it. */ export declare function liveCheckLiftsBench(bench: SeatRecentBench, probe: { signedIn: boolean | null; check: string; probedAt: string; } | undefined): boolean; /** `RosterSeat.account`: absent unless the seat can take a turn on its sign-in. */ export declare function seatAccount(auth: SeatStanding['auth'], stated: SeatAccount | undefined): SeatAccount | undefined; export type WorkRefusalSource = 'auth' | 'launcher' | 'scope'; /** One reason code per refusal (studio's copy table keys on it). */ export type WorkReasonCode = 'signed_out' | 'not_enabled' | 'reviewer_only' | 'recent_bench' | 'login_pending' | 'worktree_bench' | 'host_floor_bench' | 'scope_ungoverned'; export type WorkAdmission = { ok: true; } | { ok: false; reason_code: WorkReasonCode; source: WorkRefusalSource; reason: string; }; /** `RosterSeat.qe_reviewer` (api-types 0.115.0). */ export type QeReviewerReasonCode = Exclude | 'skill_not_admitted'; export type QeReviewer = { ok: true; } | { ok: false; reason_code: QeReviewerReasonCode; reason: string; }; export interface WorkInputs { enabled_for_council?: boolean | undefined; seat_eligible_for_work?: boolean | undefined; standing: SeatStanding; /** The engine's bench crew carries to new launches (`SeatHealthTracker.recentBenchFor`). */ recentBench: SeatRecentBench | null; /** The seat's login check has not answered yet (a launch would wait, then leave it out). */ loginPending: boolean; /** The chat admission per scope kind the roster already serves (ASK-C2). */ chatAdmission: Record; /** The engine's worktree bench reason for THIS seat on a bound run, `null` for none. */ worktreeBench: string | null; /** wicked-core#976: the engine's host-floor bench reason for THIS seat (any run), `null` or * absent for none. */ hostFloorBench?: string | null; } /** `RosterSeat.work_admission` (see the module doc). */ export declare function workAdmission(i: WorkInputs): Record; /** `RosterSeat.qe_reviewer` (see the module doc). `skillAdmitted` is the engine's answer. */ export declare function qeReviewer(i: WorkInputs, skillAdmitted: boolean): QeReviewer; export type IssueSeverity = 'problem' | 'warning' | 'note'; export interface SeatIssueCommand { purpose: 'sign_in' | 'sign_out' | 'version'; /** The safe rendering: the home directory written `$HOME` (it expands inside the double quotes * the engine puts around the seat's root; `~` would not). The command to RUN stays the roster's * `login_invocation` / `logout_invocation`. */ display: string; } export interface SeatIssue { code: string; severity: IssueSeverity; /** Only names, versions, counts and ISO times — never free text from a CLI. */ params: Record; /** Crew's own one line, for a client that does not know the code (Technical details). */ message: string; commands?: SeatIssueCommand[]; } /** Everything the issue list reads, all already computed by the roster accessor. */ export interface IssueInputs { key: string; display_name: string; binary: string; login_invocation?: string; logout_invocation?: string; optIn: boolean; standing: SeatStanding; version?: SeatVersion; governance: Record; /** `/diagnostics.seatGovernance.hostBoundary`: the OS launcher the repository boundary arms * with, `null` when the host has none. */ hostBoundary: string | null; recentBench: RecentBenchWire | undefined; /** wicked-core#976: the engine's host-floor bench reason for the seat (`null`/absent: none). */ hostFloorBench?: string | null; /** wicked-core#976: the sentence when that bench could not be read (fail closed). */ hostFloorUnknown?: string | null; workAdmission?: Record; qeReviewer?: QeReviewer; /** Whether ANY seat on the roster can run QE now (`undefined` when that is not known). */ rosterQe: boolean | undefined; /** Present for a container seat (`containerLoginReading`): how its live check was read. The * container floor sends no live request; its seat's own last step is the check, so only a step * that did not answer (`no_answer`) warns, and a seat no step ran on yet (`broker`) does not. */ containerCheck?: 'step' | 'no_answer' | 'broker'; home?: string; } /** A command for display: the home directory as `$HOME`. */ export declare function displayCommand(cmd: string, home?: string): string; /** `RosterSeat.issues` (A6), most important first. */ export declare function seatIssues(i: IssueInputs): SeatIssue[]; //# sourceMappingURL=seat-agents.d.ts.map