export interface BoardTask { id: number; title: string; detail: string | null; state: "open" | "claimed" | "done" | "dropped"; /** Ids it waits on: claimable once each is done (a dropped one does not hold it). */ after: number[]; /** Who put it on the board: "user", "concierge", or a session's name (its job id when a job). */ by: { who: string; whoId: string | null; }; at: number; /** The session that holds it (claimed), or held it (done). */ owner: { id: string; name: string; } | null; claimedAt: number | null; doneAt: number | null; result: string | null; /** Handed to a session by the hub or the concierge (a message there); open until that session claims it. */ assigned: { id: string; name: string; at: number; } | null; /** M52: the project it is for (a repository's root, projectOf); null: any session's. */ project: string | null; /** M52: sessions told when it can be claimed (refused as blocked); at most TASK_WAITING_MAX. */ waiting: { id: string; name: string; }[]; /** M54: its own worktree and where it is in the loop (absent: a task without one). */ workspace?: TaskWorkspace | null; } /** * M54 (docs/plans/ade-roadmap.md): where a task with a workspace is, task → worktree → * verify → review → local merge. The stage is the truth for such a task; `state` follows * the claim as for any task, except that `merged` is `done`. */ export type WorkspaceStage = "working" | "verifying" | "review" | "merging" | "conflict" | "failed" | "shelved" | "merged"; export declare const WORKSPACE_STAGES: readonly WorkspaceStage[]; /** The stages that wait on a person. */ export declare const NEEDS_YOU_STAGES: ReadonlySet; /** A review comment on a line of the task's diff (M58). */ export interface ReviewComment { file: string; line: number; text: string; /** The line's text when it was written: the comment is outdated once it is not there. */ lineText: string; /** The branch tip it was written on. */ tip: string; at: number; } export interface TaskWorkspace { /** The worktree's top directory ("" when a damaged record lost it). */ path: string; branch: string; /** The base branch's name, e.g. "main". */ baseRef: string; /** The commit the worktree was made from (40 or 64 hex; "" when unknown). */ baseSha: string; stage: WorkspaceStage; /** Why it is where it is, for a person: "not verified (interrupted)", a git message. */ note: string | null; verify?: { ok: boolean; at: number; log: string; tail: string; rounds: number; }; /** Written before the merge (the tip and the base it starts from), `into` after it (M55). */ merge?: { tip: string; oldBase: string; at: number; into?: string; }; comments?: ReviewComment[]; /** M59: the branch tip its session's done sent to review (a merge by hand is of this tip). */ reviewTip?: string; /** M60: the pull request opened for it (the optional exit). */ pr?: { url: string; tip: string; at: number; }; } export declare const TASK_NOTE_MAX = 500; /** * A stored workspace, normalised: null when there is none; a damaged one (no path or * branch, an unknown stage) is kept as `failed` for a person to look at, never dropped * (its worktree and branch may hold work). */ export declare function parseWorkspace(raw: unknown): TaskWorkspace | null; /** How a stage reads in a line: `in review`, `conflict`. */ export declare function stageLabel(s: WorkspaceStage): string; /** The task needs a person (review, a conflict, a failure). */ export declare const needsYou: (t: BoardTask) => boolean; /** * M54: whether `d`, which `t` waits on, no longer holds it. Dropped: never holds. Of * another project: done (its code is not in this repository). With a workspace: merged * (its state is then done; a task marked done by hand without its merge still holds). * Otherwise: done. */ export declare function dependencyMet(d: BoardTask, t: Pick): boolean; export declare const TASK_MAX = 200; export declare const TASK_TITLE_MAX = 200; export declare const TASK_TEXT_MAX = 2000; export declare const TASK_WAITING_MAX = 20; /** * M52: the project a directory is in: the root of its git repository, a worktree's being * its repository's (roost's isolated sessions share the board of the repository they * branch); null outside a repository (such a session sees the tasks for anyone). */ export declare function projectOf(cwd: string | null | undefined): string | null; /** M52: a project's short name (its directory's), or "any" for the tasks for any session. */ export declare const projectLabel: (p: string | null) => string; /** M52: a task a session of `project` sees and may take: its project's, or one for any session. */ export declare const onBoardOf: (t: Pick, project: string | null) => boolean; export interface BoardSummary { open: number; claimed: number; blocked: number; done: number; /** M54: tasks in their workspaces (not merged, not dropped); not in the counts above. */ workspaces?: number; /** M54: of those, the ones waiting on a person (review, conflict, failed). */ needsYou?: number; } /** The ids a task still waits on: the ones that exist and still hold it (dependencyMet). */ export declare function blockedOn(t: BoardTask, all: Iterable): number[]; /** M54: a session can claim it now: open, waiting on nothing, without a workspace (one with a workspace is started: /tasks start). */ export declare const claimable: (t: BoardTask, all: Iterable) => boolean; /** Open, claimed, blocked (open but waiting on another), done; M54: in workspaces, needing you. */ export declare function boardSummary(all: BoardTask[]): BoardSummary; /** `3 open · 2 claimed · 1 blocked · 2 in workspaces (1 needs you) · 5 done` (zeros left out; "none" when empty). */ export declare function summaryLine(s: BoardSummary): string; export declare function taskLine(t: BoardTask, all: Iterable, now?: number, projects?: boolean): string; /** Open (claimable) first, then blocked, then claimed, then (M54) those in workspaces: the order the digest and the hub list live tasks in. */ export declare function liveOrder(t: BoardTask, all: BoardTask[]): number; /** The board for a digest: the summary line, then every task that is not done or dropped (open, blocked, claimed). */ /** M52: whether the tasks are of more than one project (then each line names its own). */ export declare const manyProjects: (all: BoardTask[]) => boolean; export declare function boardLines(all: BoardTask[], now?: number): string[]; /** The board for a tool's answer: boardLines, then the last `doneMax` done tasks (newest last). */ export declare function boardListing(all: BoardTask[], now?: number, doneMax?: number): string[]; /** M58: at most this many review comments on a task; a send-back's text at most this long. */ export declare const REVIEW_COMMENTS_MAX = 200; export declare const REVIEW_TEXT_MAX = 4000; /** * M58: the review comments as a message for the session: each with its place and the line * it is about, bounded (the rest counted). */ export declare function reviewText(comments: ReviewComment[], max?: number): { text: string; count: number; }; /** M55/M57: the first prompt of a task's session (the hub's /tasks start, the concierge's hub_task_start). */ export declare function taskPrompt(t: Pick): string;