/** * The peer footprint board (change: add-peer-footprint-board). * * One small JSON file per live agent, in the clone's git common directory * (`/openlore/board/`), so every worktree of one clone reads the same entries with * no server and no network. An entry holds structured fields only — the agent's declared write-set * and read-set resolved to symbols (with a content hash at declaration), the symbols or files it * intends to create, its worktree and branch, and a short screened title. * * Entries end on evidence, never by guesswork: released, not refreshed within the panic-state * session expiry, worktree removed, branch deleted, or branch merged into the default branch. * Reads are fail-open (an unreadable entry is counted, not fatal); writes are atomic and bounded. * * The end predicates are the clone's single lifecycle decider ({@link judgeLifecycle}), so anything * else recorded per branch and worktree — the fleet verification records next door — ends on the * same evidence rather than on a copy of these rules. A subject that does not carry what a * predicate needs reports that predicate `unknown`; a missing field never means "ended". */ /** Live entries the board holds at most. */ export declare const MAX_BOARD_ENTRIES = 64; /** Symbols per set recorded at most. */ export declare const MAX_SET_SYMBOLS = 200; export interface BoardSymbol { id: string; name: string; file: string; /** Character span of the symbol in its file at declaration, and the hash of that text. */ start?: number; end?: number; hash?: string; /** The symbol's first characters, to find it again after edits above it. */ head?: string; } export interface BoardEntry { version: 1; actorId: string; /** Absolute path of the worktree the agent works in. */ worktree: string; branch: string; /** Screened title (≤120 chars), absent when none or withheld. */ title?: string; titleWithheld?: boolean; /** The seeds as declared (symbol ids, names, or files). */ writeSeeds: string[]; readSeeds: string[]; writes: BoardSymbol[]; reads: BoardSymbol[]; /** Write seeds that resolve to nothing yet: symbols or files the agent intends to create. */ creates: string[]; /** Existing files with no symbols that the agent will write. */ fileWrites?: string[]; /** The analysis root the symbol paths are relative to (default: the worktree). */ root?: string; /** The declared write mode (default `modify`). */ writeMode?: 'append' | 'modify'; /** The branch's merge-base with the default branch at declaration. */ baseAtDeclare?: string; declaredAt: string; lastSeenAt: string; } export type EndReason = 'expired' | 'worktree-removed' | 'branch-deleted' | 'branch-merged'; /** * Why a predicate could not be evaluated. A predicate the subject does not carry the evidence for * is reported here and skipped — never resolved as "ended" by the absence of a field. */ export type LifecycleUnknown = 'expiry-unknown-no-timestamp' | 'worktree-unknown-not-recorded' | 'branch-unknown-detached-or-unrecorded' | 'branch-unknown-unusable-name' | 'branch-unknown-git-could-not-be-asked' | 'branch-unknown-never-a-known-branch' | 'branch-merged-unknown-no-default-branch' | 'branch-merged-unknown-no-base-commit'; /** What the lifecycle predicates read. Every field is optional: an absent one is `unknown`. */ export interface LifecycleSubject { /** When the subject was last refreshed (ISO). Absent → the idle-expiry predicate is unknown. */ lastSeenAt?: string; /** The worktree top this subject belongs to. Absent → it is not matched against the clone's worktrees. */ worktree?: string; /** The directory the subject's paths are relative to; must exist, and sit inside `worktree`. */ root?: string; /** The branch. Empty or absent → a detached HEAD, or not recorded. */ branch?: string; /** * Evidence that `branch` really named a local branch when the subject was recorded. Without it a * name absent from the clone's branches proves nothing — it may be a task id that never was a * branch — so the branch predicates report unknown instead of "deleted". */ branchKnownRef?: boolean; /** The merge-base with the default branch when the subject was recorded. A commit id only. */ baseAtDeclare?: string; } /** A lifecycle verdict for one subject: why it ended (or null), and the predicates left unknown. */ export interface LifecycleVerdict { reason: EndReason | null; unknown: LifecycleUnknown[]; } export interface BoardRead { live: Array<{ entry: BoardEntry; moved: string[]; }>; ended: Array<{ actorId: string; reason: EndReason; file: string; lastSeenAt: string; }>; /** Entry files that could not be read or parsed. */ unreadable: number; boundaries: string[]; } /** The board directory of the clone `root` belongs to, or null outside a git work tree. */ export declare function boardDir(root: string): Promise; export declare const symbolHash: (text: string) => string; export declare function writeEntry(root: string, entry: BoardEntry): Promise; /** Remove an entry. Returns whether one existed. */ export declare function removeEntry(root: string, actorId: string): Promise; /** Whether `name` is a local branch of this clone right now; null when git could not be asked. */ export declare function isLocalBranch(root: string, name: string): Promise; /** * Judge many lifecycle subjects at once, resolving the default branch, the clone's worktree set and * its branch tips ONCE for the batch. The batched wrapper every other record store reaches the * board's end predicates through — there is no second copy of the rules. Git work per batch is * bounded by the number of distinct branches, not by the number of subjects. */ export declare function judgeLifecycle(root: string, items: readonly T[], subjectOf: (item: T) => LifecycleSubject, opts?: { now?: number; }): Promise>; /** * Read the board. Read-only: entries that ended are listed with the reason and left for * {@link pruneEnded} (called by the writing tool). An unreadable entry is counted and skipped. */ export declare function readBoard(root: string, opts?: { now?: number; }): Promise; /** The current branch name and merge-base with the default branch, for a new entry. */ export declare function worktreeIdentity(root: string): Promise<{ worktree: string; branch: string; baseAtDeclare?: string; }>; /** Live board entries as task descriptors for the coordination tools (write seeds only). */ export declare function liveTaskDescriptors(root: string): Promise>; /** * Remove the entry files of ended entries (best effort). An entry refreshed since it was judged * ended (its `lastSeenAt` changed) is kept. */ export declare function pruneEnded(ended: BoardRead['ended']): Promise; //# sourceMappingURL=footprint-board.d.ts.map