/** * The daemon's record of each chat's ASK PATH (DES-ASK-TEAM-CHAT-001 §5.1): who was eligible when * the chat opened, the seat the operator chose (if any), and — once the first message launched it — * the run the conversation IS and the answer steps it has added. In memory, like the chat scope * index it sits beside: a chat is a session of this daemon; the run and its transcript are durable. * * Crew owns ELIGIBILITY and the launch COMMAND; the engine owns the PICK (`path.started.cli`, * `selection`) and every fact after it. `pa` here is what this daemon has seen of the engine's * pick (the relay fills it from `path.started`; a chosen seat is known at once). */ import { type GovernanceScopeKind, type GovernanceSeatInput, type SeatGovernanceMode } from './seat-governance.js'; import type { ChatWorkflow } from './chat-workflow.js'; export interface AskPath { chatId: string; /** Seats admitted to the chat at open (signed in, not benched, allowed for the scope). */ eligible: string[]; /** The operator's choice, one of `eligible`; `undefined` ⇒ the engine picks at random. */ primary?: string; /** The run the conversation is, once the first message launched it. */ runId?: string; /** crew#1020: the graph binding actually used at launch; a run cannot acquire a new one. */ launchGraphBinding?: string | null; /** crew#1034: the read roots the run was launched with (sorted). The engine fixes a run's read * boundary at launch, so a run cannot acquire a repository attached after it started either. */ launchReadRoots?: string[]; /** A message of this chat is in flight on this daemon — launching the run or continuing it * (status read → proposal → approval) — so a second one meanwhile is `turn_in_flight`. */ busy?: boolean; /** Bumped on open; a launch that resolves after the chat was closed and * reopened must not attach its run to the newcomer. */ generation: number; /** The answer steps added so far (`answer-1`, `answer-2`, …). */ steps: string[]; /** The engine's pick as this daemon has seen it. */ pa: string | null; selection: 'chosen' | 'random'; reviewer: string | null; helpers: string[]; /** IG1-crew-1: the eligible seats' records (as admitted) and the ask's scope kind — the PA's * governance mode is derived from them, with the engine's class as the run reports it. */ seats?: Record; scopeKind?: GovernanceScopeKind; /** The engine's class per seat, from `path.started.governance` / `member.joined.governance_class`. */ classes: Record; /** crew#1157: the read-only workflow every answer step of this chat runs (`POST /chats {workflow}`). */ workflow?: ChatWorkflow; } export declare class AskPathIndex { private readonly paths; /** Per chat id, across closes — a close-and-reopen must read as a NEW generation. */ private readonly generations; /** Record an opened chat's eligibility and the operator's choice. */ open(chatId: string, eligible: readonly string[], primary?: string, governance?: { seats: readonly GovernanceSeatInput[]; scopeKind: GovernanceScopeKind; }, workflow?: ChatWorkflow): AskPath; get(chatId: string): AskPath | undefined; /** The chat a run was launched from, if it is an ask path of this daemon. */ chatOf(runId: string): string | undefined; private nextGeneration; /** Reserve the chat for one message (a launch or a continuation): the lease (the chat's * generation) to hand back to {@link release}; `null` when a message is in flight. */ reserve(chatId: string): number | null; /** Give a lease back — only the generation that holds it (codex on #808 r2, 1: a request of a * closed-and-reopened chat must not free the newcomer's reservation). */ release(chatId: string, lease: number): void; /** The first message launched the run; `stepId` is its answer step. False when the chat was * closed (or closed and reopened) while the launch was in flight: the caller cancels the run. */ started(chatId: string, generation: number, runId: string, stepId: string, codeGraphDb?: string | null, readRoots?: readonly string[]): boolean; /** A later message added an answer step. Returns the new step id. */ /** A message of this chat is in flight right now (launching or continuing). */ busy(chatId: string): boolean; /** The continuation the engine accepted landed on the chat: records the step — only on the * generation that holds the lease (codex on #808 r3, 2: a continuation of a closed-and-reopened * chat must not write into the newcomer's record). */ continued(chatId: string, lease: number, stepId: string): boolean; /** The id the NEXT answer step takes (`answer-N`); nothing is recorded until {@link continued}. */ nextStep(chatId: string): string; /** A re-seat: the named seats are eligible (a sign-in fixed). */ admit(chatId: string, seats: readonly string[]): string[]; /** What the relay learned from the run's `path.started` / `member.joined` / `help.answered`. */ observe(runId: string, fact: { pa?: string; selection?: 'chosen' | 'random'; reviewer?: string | null; helper?: string; /** The engine's governance class per seat (`path.started.governance`, `member.joined`). */ classes?: Record; }): void; /** Every chat this daemon holds a path record for (`GET /chats`). */ list(): AskPath[]; /** The PA's governance mode for the ask's scope: its admitted record with the class the run's * frames report (the engine's, when it has spoken), else the roster's. Absent until the PA is * known, or on a path opened without seat records. */ private paMode; close(chatId: string): AskPath | undefined; /** The wire view (`ChatDetailResponse.path`). */ view(chatId: string): { runId: string; pa: string | null; selection: 'chosen' | 'random'; reviewer: string | null; helpers: string[]; stepId: string; governance_mode?: SeatGovernanceMode; } | undefined; } /** The one answer step shape an ask adds per message (DES-ASK-TEAM-CHAT-001 §3, §4.4). */ export declare const ASK_TURN_BUDGET_SECS = 600; export declare function answerStep(stepId: string, text: string): { catalog: string; id: string; [k: string]: unknown; }; /** * crew#854: does an ask's run wait at its TURN gate — `awaiting_human` after an answer step, every * unit on the run an answer step (`:answer-N`), every one done? That gate (the engine's * def / terminal HumanConfirm on the answer step, §4.7) is answered by the chat's next message, so it * is never a Needs-you gate. Anything else — a research or creator step, Continue in Build — fails * closed: the gate is a real one. */ export declare function isAskTurn(view: { session: { id: string; status: string; }; units: ReadonlyArray<{ id: string; status: string; }>; }): boolean; //# sourceMappingURL=ask-paths.d.ts.map