import { getTranscriptArchiveRoot } from "./paths/paths.js"; import { type IndexEntry, type ProjectsRegistry, type RunManifest } from "./transcript-archive-types.js"; export interface ProjectIdentity { prefix: string; name: string; projectDir: string; } /** * Read `{prefix, name, projectDir}` from a `.forge/config.json`. Defaults on * any failure (missing file, malformed JSON, absent fields) — never throws. * `projectDir` is derived from the config path itself (`/.forge/config.json`). */ export declare function readProjectIdentity(configPath: string): ProjectIdentity; /** * `-` — prefix alone can * collide across projects (two repos both named "FORGE"); the path hash * disambiguates. Falls back to the raw path when realpath throws (deleted * or unmounted project dir — archive entries must remain addressable). */ export declare function computeProjectKey(projectDir: string, prefix: string): string; interface PhaseFileInfo { /** Absolute path to the project-local phase transcript JSON. */ absPath: string; /** Basename, e.g. "20260601T100100Z__CART-BUG-001__triage.json". */ file: string; /** Compact ISO prefix from the filename. */ ts: string; /** Role segment from the filename (third "__" part onward). */ role: string; } /** One discovered run: source files + the manifest built from them. */ export interface DiscoveredRun { runId: string; jsonlPath: string; phaseFiles: PhaseFileInfo[]; /** Live tail-view logs (`*.tail.jsonl`) belonging to this run. */ tailFiles: PhaseFileInfo[]; manifest: RunManifest; } interface BuildOptions { /** Sprint back-reference stamped onto the manifest (run-sprint wiring). */ sprintId?: string; } /** * Discover every run in a project-local entity transcript dir * (`.forge/transcripts//`) and build a RunManifest for each. * * A "run" is one orchestrator JSONL file; its runId is the compact-ISO * pipeline-start timestamp (falling back to the filename prefix). Phase * transcript files are assigned to the latest run whose start precedes * them — compact ISO prefixes compare lexicographically as timestamps. */ export declare function buildRunsForEntityDir(entityDir: string, identity: ProjectIdentity, projectKey: string, opts?: BuildOptions): DiscoveredRun[]; export interface ArchiveRunResult { archived: boolean; runDir?: string; error?: string; } export interface ArchiveRunOptions { /** Project dir (the dir containing `.forge/`). */ cwd: string; /** Project-local orchestrator JSONL path for the run to archive. */ orchestratorJsonlPath: string; /** Sprint back-reference for sprint-nested task runs. */ sprintId?: string; /** Override for `/.forge/config.json` (tests). */ configPath?: string; } /** * Archive the run identified by its project-local orchestrator transcript. * Called by orchestrators after the pipeline result is known. Best-effort, * never throws. */ export declare function archiveRun(opts: ArchiveRunOptions): ArchiveRunResult; export interface SweepResult { adopted: number; errors: number; } /** * Adopt orphans: archive every project-local run whose runId isn't in the * central index. Covers crash recovery (pipeline died before its archive * call) and adoption of pre-existing history (transcripts written before * this feature shipped). Called best-effort at pipeline start; never throws. */ export declare function sweepProjectTranscripts(cwd: string, configPath?: string): SweepResult; /** Read index.jsonl — skips malformed/truncated lines, never throws. */ export declare function readIndex(): IndexEntry[]; /** Read projects.json — empty registry on any failure, never throws. */ export declare function readProjects(): ProjectsRegistry; /** Read `/manifest.json` — null on missing/truncated/mismatched. */ export declare function readManifest(runDir: string): RunManifest | null; /** * Gunzip + parse an archived phase transcript. `file` is the manifest's * phase `file` field (without `.gz`). Null on any failure, never throws. */ export declare function gunzipPhase(runDir: string, file: string): Record | null; /** One persisted live tail-view line (see viewport/events.ts TailLogEntry). */ export interface ArchivedTailEntry { line: string; warning?: boolean; } /** * Gunzip + parse an archived live tail log (`*.tail.jsonl.gz`). Returns the * exact lines the dashboard rendered during the run, in order. Tolerant of * truncated tails; null when the file is missing/unreadable. Never throws. */ export declare function gunzipTailLog(runDir: string, file: string): ArchivedTailEntry[] | null; /** Resolve the archive dir for an index entry. */ export declare function runDirForEntry(entry: IndexEntry): string; /** * Per-turn digest of a gunzipped phase payload — never a raw JSON dump. * Each assistant message is a turn: first text line + tool-call names; * toolResult messages render as compact result markers. */ export declare function digestPhasePayload(payload: Record): string[]; /** * VERBOSE digest of a gunzipped phase payload — the replay-dashboard feed. * Unlike digestPhasePayload (compact markers for the `show` table), this * carries the actual transcript content so a replayed run is readable: * full assistant text (capped per turn), thinking first-lines, tool-call * argument previews, and tool-result first-line previews. * * Multi-line assistant text is pushed as ONE entry — the dashboard splits * lines at display time, and the tree's per-entry char cap still applies. */ export declare function digestPhasePayloadVerbose(payload: Record): string[]; export { getTranscriptArchiveRoot };