@mikode13/harness 9.1.0 → 9.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -6
- package/dist/engines/domain/model/commandLoops.d.ts +59 -0
- package/dist/engines/domain/model/commandLoops.js +143 -0
- package/dist/engines/domain/model/commandLoops.js.map +1 -0
- package/dist/engines/domain/model/llmAgent.d.ts +6 -0
- package/dist/engines/domain/model/llmAgent.js +154 -42
- package/dist/engines/domain/model/llmAgent.js.map +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.d.ts +2 -2
- package/dist/factory/infrastructure/agentLLMFactory.js +2 -2
- package/dist/factory/infrastructure/agentLLMFactory.js.map +1 -1
- package/dist/recovery/domain/recoveryStore.d.ts +8 -0
- package/dist/recovery/domain/recoveryStore.js.map +1 -1
- package/dist/recovery/infrastructure/fileRecoveryStore.js +38 -2
- package/dist/recovery/infrastructure/fileRecoveryStore.js.map +1 -1
- package/dist/tools/domain/editResponse.d.ts +7 -2
- package/dist/tools/domain/editResponse.js +33 -11
- package/dist/tools/domain/editResponse.js.map +1 -1
- package/dist/tools/domain/preparedCall.d.ts +26 -4
- package/dist/tools/domain/preparedCall.js +1 -1
- package/dist/tools/domain/preparedCall.js.map +1 -1
- package/dist/tools/domain/v4aPatch.d.ts +6 -6
- package/dist/tools/domain/v4aPatch.js +59 -21
- package/dist/tools/domain/v4aPatch.js.map +1 -1
- package/dist/tools/infrastructure/commandOutput.d.ts +14 -0
- package/dist/tools/infrastructure/commandOutput.js +99 -0
- package/dist/tools/infrastructure/commandOutput.js.map +1 -0
- package/dist/tools/infrastructure/commandProcess.d.ts +3 -1
- package/dist/tools/infrastructure/commandProcess.js +3 -1
- package/dist/tools/infrastructure/commandProcess.js.map +1 -1
- package/dist/tools/infrastructure/commandTool.js +25 -11
- package/dist/tools/infrastructure/commandTool.js.map +1 -1
- package/dist/tools/infrastructure/trackedEdits.d.ts +3 -3
- package/dist/tools/infrastructure/trackedEdits.js +17 -11
- package/dist/tools/infrastructure/trackedEdits.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recoveryStore.js","sourceRoot":"","sources":["../../../src/recovery/domain/recoveryStore.ts"],"names":[],"mappings":"AAwHA,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAsCpC,2FAA2F;AAC3F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC5C,YAAY,SAA0B;QACrC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IAClC,CAAC;CACD;AA4DD,uFAAuF;AACvF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC7C,uEAAuE;IAC9D,QAAQ,CAAS;IAC1B,wDAAwD;IAC/C,MAAM,CAAS;IAExB,YAAY,QAAgB,EAAE,MAAc;QAC3C,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;QACxF,KAAK,CAAC,iCAAiC,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,KAAK,CAAS;IAEvB,YAAY,KAAa;QACxB,KAAK,CAAC,0BAA0B,KAAK,mBAAmB,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;CACD","sourcesContent":["/**\n * What one path held at one moment: nothing, or a regular file with this content and mode.\n * `hash` names the content in the store, so the bytes themselves never travel in a record.\n */\nexport type FileState = { exists: false } | { exists: true; hash: string; mode: number };\n\n/**\n * One change to one file. It is recorded as `prepared` before the file is touched, and only\n * then applied, so a run that stops halfway always leaves a record of what it may have done.\n * `abandoned` means the change was prepared but never happened.\n */\nexport interface JournalEntry {\n\tsequence: number;\n\t/** The file's real path, absolute: a run may write to more than one root of its workspace. */\n\tpath: string;\n\tbefore: FileState;\n\tafter: FileState;\n\t/** Folders the change creates for a new file, outermost first: undo removes them if empty. */\n\tcreatedFolders?: string[];\n\t/**\n\t * The command whose run the change was seen around, for a change no tool of the harness made\n\t * itself. It was found by comparing the file before and after, not journaled before it was made.\n\t */\n\tobservedBy?: string;\n\tstatus: 'prepared' | 'applied' | 'abandoned';\n}\n\n/**\n * What a group of files held right before something outside the journal ran, such as a\n * command: the content of each, by its real path, absolute. It is stored as content, and the\n * journal names its hash before the command starts.\n */\nexport interface Manifest {\n\tfiles: Record<string, FileState>;\n}\n\n/** What one observation cost: before and after together. */\nexport interface ObservationMeasure {\n\t/** Files captured before, and compared after. */\n\tfiles: number;\n\tbytesRead: number;\n\t/** New content stored, which the store did not hold already. */\n\tbytesStored: number;\n\t/** Spent capturing and comparing, not running what was observed. */\n\tdurationMs: number;\n}\n\n/**\n * `interrupted` is a run whose process died while it was writing. The next run to take the\n * workspace settles each change it left `prepared`, from what the file holds now.\n */\nexport type RunStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface RunRecord {\n\trunId: string;\n\t/** The real path of the workspace root the run wrote to. */\n\troot: string;\n\t/**\n\t * The run the workspace was at when this one started, so runs form a tree: going back to an\n\t * earlier run and writing again starts a new branch. Absent for the first run.\n\t */\n\tparentRunId?: string;\n\t/**\n\t * Runs whose changes retention chained into this one, oldest first. They are no longer in\n\t * the history: this run now goes back to where the oldest of them started.\n\t */\n\tabsorbed?: string[];\n\t/** The journal file that holds the run's changes. Absent while it is the first one written. */\n\tjournal?: string;\n\tstartedAt: string;\n\tfinishedAt?: string;\n\tstatus: RunStatus;\n\t/** The process that ran it, so a run whose process died can be told from a live one. */\n\tpid: number;\n}\n\n/**\n * The recovery record of one run that writes. Every method returns only once what it records\n * is on disk: a change is never made before the record that would undo it exists. Once a step\n * fails to reach the journal, the journal refuses every later step, because a line written\n * after a broken one could not be read back.\n */\nexport interface RunJournal {\n\treadonly runId: string;\n\t/** Stores `content` and returns the hash that names it. Content stored before is reused. */\n\tsaveContent(content: Buffer): Promise<string>;\n\t/** Records a change about to be made, and returns its sequence number. */\n\tprepare(change: Omit<JournalEntry, 'sequence' | 'status'>): Promise<number>;\n\t/** The change was made. */\n\tapplied(sequence: number): Promise<void>;\n\t/** The change was not made, and the file still holds its `before`. */\n\tabandoned(sequence: number): Promise<void>;\n\t/**\n\t * Records that `by`, such as a command, is about to change files the journal cannot see it\n\t * change, and that the stored `manifest` holds what they hold now. Each change it makes is\n\t * then recorded as its own entry, prepared and applied at once, before `observed`. If the run\n\t * stops first, the next run settles it: every file of the manifest that changed since is\n\t * recorded as changed by `by`. A file it created is not in the manifest, and is then missed.\n\t */\n\tobserve(manifest: string, by: string): Promise<number>;\n\t/**\n\t * Every change the observation found is recorded. `measure`, what capturing and comparing the\n\t * files cost, is kept with it.\n\t */\n\tobserved(sequence: number, measure?: ObservationMeasure): Promise<void>;\n\t/** How many bytes of content this run stored that the store did not hold yet. */\n\treadonly storedBytes: number;\n\t/**\n\t * Whether a change it recorded may have reached a file: one prepared and not abandoned. It\n\t * holds whatever happens to the record afterwards.\n\t */\n\treadonly changed: boolean;\n\t/**\n\t * Ends the run and releases the workspace for the next writer. A run that `changed` nothing\n\t * leaves the history, and the workspace is back at the run before it. If removing it fails,\n\t * the store still treats it as gone, and the next run or move finishes removing it.\n\t */\n\tfinish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void>;\n}\n\n/** The point before any run: going there takes the workspace back to how it was. */\nexport const historyStart = 'start';\n\n/** A file a move left as it was, because it did not hold what the history expected there. */\nexport interface MoveConflict {\n\tpath: string;\n\t/** The run whose change could not be undone or redone. */\n\trunId: string;\n}\n\n/**\n * One move of the workspace through its history, kept so an agent that runs next can tell\n * that its conversation is about a state the workspace has left.\n */\nexport interface Revision {\n\t/** Counts the moves of this workspace, from 1. */\n\trevision: number;\n\t/** The run the workspace was at; absent for the start of the history. */\n\tfrom?: string;\n\t/** The run the workspace is at now; absent for the start of the history. */\n\tto?: string;\n\tat: string;\n\t/** Why the user went there, when the host asked. */\n\treason?: string;\n\t/** Every file reached the state the history expected. Otherwise `conflicts` names those that did not. */\n\tcomplete: boolean;\n\tconflicts: MoveConflict[];\n}\n\nexport interface MoveOptions {\n\t/** Why the user is moving the workspace, recorded with the move. */\n\treason?: string;\n\t/**\n\t * Where the workspace must be for the move to happen: a run, or `historyStart`. Checked under\n\t * the workspace lock, so a move confirmed against one state never runs from another.\n\t */\n\tfrom?: string;\n}\n\n/** There is nothing to undo at the start of the history, or nothing to redo at its tip. */\nexport class NothingToMoveError extends Error {\n\tconstructor(direction: 'undo' | 'redo') {\n\t\tsuper(direction === 'undo' ? 'There is no run to undo' : 'There is no run to redo');\n\t\tthis.name = 'NothingToMoveError';\n\t}\n}\n\n/**\n * Where the runs that write to one workspace keep what is needed to undo them, outside the\n * workspace itself. Only one run writes to a workspace at a time.\n */\nexport interface RecoveryStore {\n\t/**\n\t * Starts recording a run and holds the workspace for it until `finish`. The new run's parent\n\t * is the run the workspace is at, and the workspace is at the new run from then on. Runs a\n\t * dead process left `running` are settled first.\n\t *\n\t * @throws {WorkspaceBusyError} when another live run is writing to the workspace.\n\t */\n\tstartRun(): Promise<RunJournal>;\n\t/**\n\t * Every run, oldest first, and the run the workspace is at (`head`), absent before the first.\n\t * A run still recorded as `running` whose process is gone is listed as `interrupted`.\n\t */\n\tlistRuns(): Promise<{ head?: string; runs: RunRecord[] }>;\n\t/**\n\t * Moves the workspace to the state right after `target`, or to how it was before any run\n\t * with `historyStart`. It undoes runs one by one back to the closest common ancestor, then\n\t * redoes runs one by one forward to `target`. Each file is written only if it holds the\n\t * state the history expects there; one that does not is left as it is and reported, and the\n\t * move is then not `complete`. A move the process did not finish is finished by the next\n\t * move or run.\n\t *\n\t * @throws {WorkspaceBusyError} when a run or another move holds the workspace.\n\t * @throws {WorkspaceMovedError} when `from` was given and the workspace is elsewhere.\n\t * @throws {UnknownRunError} when `target` is not in the history.\n\t * @throws {HistoryExpiredError} when retention chained `target` into a later run.\n\t */\n\tgoTo(target: string, options?: MoveOptions): Promise<Revision>;\n\t/**\n\t * Moves the workspace to the run before the one it is at.\n\t *\n\t * @throws {NothingToMoveError} at the start of the history.\n\t */\n\tundo(options?: MoveOptions): Promise<Revision>;\n\t/**\n\t * Moves the workspace to the next run: towards where it was most recently, or the newest\n\t * branch.\n\t *\n\t * @throws {NothingToMoveError} when no run follows the one it is at.\n\t */\n\tredo(options?: MoveOptions): Promise<Revision>;\n\t/** Every move of the workspace, oldest first. */\n\tlistRevisions(): Promise<Revision[]>;\n\t/**\n\t * A run's record and its changes, in the order they were prepared.\n\t *\n\t * @throws {UnknownRunError} when `runId` was never a run of this workspace.\n\t * @throws {HistoryExpiredError} when retention removed `runId` or chained it into a later run.\n\t */\n\treadRun(runId: string): Promise<{ record: RunRecord; entries: JournalEntry[] }>;\n\t/** The bytes a hash names. */\n\treadContent(hash: string): Promise<Buffer>;\n}\n\n/** A move was asked from one point of the history, and the workspace is at another. */\nexport class WorkspaceMovedError extends Error {\n\t/** Where the move expected the workspace: a run, or `historyStart`. */\n\treadonly expected: string;\n\t/** Where the workspace is: a run, or `historyStart`. */\n\treadonly actual: string;\n\n\tconstructor(expected: string, actual: string) {\n\t\tconst name = (point: string) => (point === historyStart ? 'the start' : `run ${point}`);\n\t\tsuper(`The workspace is no longer at ${name(expected)}: it is at ${name(actual)}`);\n\t\tthis.name = 'WorkspaceMovedError';\n\t\tthis.expected = expected;\n\t\tthis.actual = actual;\n\t}\n}\n\nexport class WorkspaceBusyError extends Error {\n\treadonly runId: string;\n\n\tconstructor(runId: string) {\n\t\tsuper(`The workspace is busy: ${runId} is writing to it`);\n\t\tthis.name = 'WorkspaceBusyError';\n\t\tthis.runId = runId;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recoveryStore.js","sourceRoot":"","sources":["../../../src/recovery/domain/recoveryStore.ts"],"names":[],"mappings":"AAgIA,oFAAoF;AACpF,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC;AAsCpC,2FAA2F;AAC3F,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC5C,YAAY,SAA0B;QACrC,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IAClC,CAAC;CACD;AA4DD,uFAAuF;AACvF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC7C,uEAAuE;IAC9D,QAAQ,CAAS;IAC1B,wDAAwD;IAC/C,MAAM,CAAS;IAExB,YAAY,QAAgB,EAAE,MAAc;QAC3C,MAAM,IAAI,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;QACxF,KAAK,CAAC,iCAAiC,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACnC,KAAK,CAAS;IAEvB,YAAY,KAAa;QACxB,KAAK,CAAC,0BAA0B,KAAK,mBAAmB,CAAC,CAAC;QAC1D,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;CACD","sourcesContent":["/**\n * What one path held at one moment: nothing, or a regular file with this content and mode.\n * `hash` names the content in the store, so the bytes themselves never travel in a record.\n */\nexport type FileState = { exists: false } | { exists: true; hash: string; mode: number };\n\n/**\n * One change to one file. It is recorded as `prepared` before the file is touched, and only\n * then applied, so a run that stops halfway always leaves a record of what it may have done.\n * `abandoned` means the change was prepared but never happened.\n */\nexport interface JournalEntry {\n\tsequence: number;\n\t/** The file's real path, absolute: a run may write to more than one root of its workspace. */\n\tpath: string;\n\tbefore: FileState;\n\tafter: FileState;\n\t/** Folders the change creates for a new file, outermost first: undo removes them if empty. */\n\tcreatedFolders?: string[];\n\t/**\n\t * The command whose run the change was seen around, for a change no tool of the harness made\n\t * itself. It was found by comparing the file before and after, not journaled before it was made.\n\t */\n\tobservedBy?: string;\n\tstatus: 'prepared' | 'applied' | 'abandoned';\n}\n\n/**\n * What a group of files held right before something outside the journal ran, such as a\n * command: the content of each, by its real path, absolute. It is stored as content, and the\n * journal names its hash before the command starts.\n */\nexport interface Manifest {\n\tfiles: Record<string, FileState>;\n}\n\n/** What one observation cost: before and after together. */\nexport interface ObservationMeasure {\n\t/** Files captured before, and compared after. */\n\tfiles: number;\n\tbytesRead: number;\n\t/** New content stored, which the store did not hold already. */\n\tbytesStored: number;\n\t/** Spent capturing and comparing, not running what was observed. */\n\tdurationMs: number;\n}\n\n/**\n * `interrupted` is a run whose process died while it was writing. The next run to take the\n * workspace settles each change it left `prepared`, from what the file holds now.\n */\nexport type RunStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'interrupted';\n\nexport interface RunRecord {\n\trunId: string;\n\t/** The real path of the workspace root the run wrote to. */\n\troot: string;\n\t/**\n\t * The run the workspace was at when this one started, so runs form a tree: going back to an\n\t * earlier run and writing again starts a new branch. Absent for the first run.\n\t */\n\tparentRunId?: string;\n\t/**\n\t * Runs whose changes retention chained into this one, oldest first. They are no longer in\n\t * the history: this run now goes back to where the oldest of them started.\n\t */\n\tabsorbed?: string[];\n\t/** The journal file that holds the run's changes. Absent while it is the first one written. */\n\tjournal?: string;\n\tstartedAt: string;\n\tfinishedAt?: string;\n\tstatus: RunStatus;\n\t/** The process that ran it, so a run whose process died can be told from a live one. */\n\tpid: number;\n}\n\n/**\n * The recovery record of one run that writes. Every method returns only once what it records\n * is on disk: a change is never made before the record that would undo it exists. Once a step\n * fails to reach the journal, the journal refuses every later step, because a line written\n * after a broken one could not be read back.\n */\nexport interface RunJournal {\n\treadonly runId: string;\n\t/** Stores `content` and returns the hash that names it. Content stored before is reused. */\n\tsaveContent(content: Buffer): Promise<string>;\n\t/** Records a change about to be made, and returns its sequence number. */\n\tprepare(change: Omit<JournalEntry, 'sequence' | 'status'>): Promise<number>;\n\t/** The change was made. */\n\tapplied(sequence: number): Promise<void>;\n\t/** The change was not made, and the file still holds its `before`. */\n\tabandoned(sequence: number): Promise<void>;\n\t/**\n\t * Records that `by`, such as a command, is about to change files the journal cannot see it\n\t * change, and that the stored `manifest` holds what they hold now. Each change it makes is\n\t * then recorded as its own entry, prepared and applied at once, before `observed`. If the run\n\t * stops first, the next run settles it: every file of the manifest that changed since is\n\t * recorded as changed by `by`. A file it created is not in the manifest, and is then missed.\n\t */\n\tobserve(manifest: string, by: string): Promise<number>;\n\t/**\n\t * Every change the observation found is recorded. `measure`, what capturing and comparing the\n\t * files cost, is kept with it.\n\t */\n\tobserved(sequence: number, measure?: ObservationMeasure): Promise<void>;\n\t/** How many bytes of content this run stored that the store did not hold yet. */\n\treadonly storedBytes: number;\n\t/** The path of every change it recorded as applied, in order: each one reached a file. */\n\treadonly appliedPaths: readonly string[];\n\t/**\n\t * What the files this run changed hold now, as one hash of their paths and states. A file back\n\t * to what it held before the run's first change to it counts as unchanged, so a change undone\n\t * gives the state from before it.\n\t */\n\tcontentState(): string;\n\t/**\n\t * Whether a change it recorded may have reached a file: one prepared and not abandoned. It\n\t * holds whatever happens to the record afterwards.\n\t */\n\treadonly changed: boolean;\n\t/**\n\t * Ends the run and releases the workspace for the next writer. A run that `changed` nothing\n\t * leaves the history, and the workspace is back at the run before it. If removing it fails,\n\t * the store still treats it as gone, and the next run or move finishes removing it.\n\t */\n\tfinish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void>;\n}\n\n/** The point before any run: going there takes the workspace back to how it was. */\nexport const historyStart = 'start';\n\n/** A file a move left as it was, because it did not hold what the history expected there. */\nexport interface MoveConflict {\n\tpath: string;\n\t/** The run whose change could not be undone or redone. */\n\trunId: string;\n}\n\n/**\n * One move of the workspace through its history, kept so an agent that runs next can tell\n * that its conversation is about a state the workspace has left.\n */\nexport interface Revision {\n\t/** Counts the moves of this workspace, from 1. */\n\trevision: number;\n\t/** The run the workspace was at; absent for the start of the history. */\n\tfrom?: string;\n\t/** The run the workspace is at now; absent for the start of the history. */\n\tto?: string;\n\tat: string;\n\t/** Why the user went there, when the host asked. */\n\treason?: string;\n\t/** Every file reached the state the history expected. Otherwise `conflicts` names those that did not. */\n\tcomplete: boolean;\n\tconflicts: MoveConflict[];\n}\n\nexport interface MoveOptions {\n\t/** Why the user is moving the workspace, recorded with the move. */\n\treason?: string;\n\t/**\n\t * Where the workspace must be for the move to happen: a run, or `historyStart`. Checked under\n\t * the workspace lock, so a move confirmed against one state never runs from another.\n\t */\n\tfrom?: string;\n}\n\n/** There is nothing to undo at the start of the history, or nothing to redo at its tip. */\nexport class NothingToMoveError extends Error {\n\tconstructor(direction: 'undo' | 'redo') {\n\t\tsuper(direction === 'undo' ? 'There is no run to undo' : 'There is no run to redo');\n\t\tthis.name = 'NothingToMoveError';\n\t}\n}\n\n/**\n * Where the runs that write to one workspace keep what is needed to undo them, outside the\n * workspace itself. Only one run writes to a workspace at a time.\n */\nexport interface RecoveryStore {\n\t/**\n\t * Starts recording a run and holds the workspace for it until `finish`. The new run's parent\n\t * is the run the workspace is at, and the workspace is at the new run from then on. Runs a\n\t * dead process left `running` are settled first.\n\t *\n\t * @throws {WorkspaceBusyError} when another live run is writing to the workspace.\n\t */\n\tstartRun(): Promise<RunJournal>;\n\t/**\n\t * Every run, oldest first, and the run the workspace is at (`head`), absent before the first.\n\t * A run still recorded as `running` whose process is gone is listed as `interrupted`.\n\t */\n\tlistRuns(): Promise<{ head?: string; runs: RunRecord[] }>;\n\t/**\n\t * Moves the workspace to the state right after `target`, or to how it was before any run\n\t * with `historyStart`. It undoes runs one by one back to the closest common ancestor, then\n\t * redoes runs one by one forward to `target`. Each file is written only if it holds the\n\t * state the history expects there; one that does not is left as it is and reported, and the\n\t * move is then not `complete`. A move the process did not finish is finished by the next\n\t * move or run.\n\t *\n\t * @throws {WorkspaceBusyError} when a run or another move holds the workspace.\n\t * @throws {WorkspaceMovedError} when `from` was given and the workspace is elsewhere.\n\t * @throws {UnknownRunError} when `target` is not in the history.\n\t * @throws {HistoryExpiredError} when retention chained `target` into a later run.\n\t */\n\tgoTo(target: string, options?: MoveOptions): Promise<Revision>;\n\t/**\n\t * Moves the workspace to the run before the one it is at.\n\t *\n\t * @throws {NothingToMoveError} at the start of the history.\n\t */\n\tundo(options?: MoveOptions): Promise<Revision>;\n\t/**\n\t * Moves the workspace to the next run: towards where it was most recently, or the newest\n\t * branch.\n\t *\n\t * @throws {NothingToMoveError} when no run follows the one it is at.\n\t */\n\tredo(options?: MoveOptions): Promise<Revision>;\n\t/** Every move of the workspace, oldest first. */\n\tlistRevisions(): Promise<Revision[]>;\n\t/**\n\t * A run's record and its changes, in the order they were prepared.\n\t *\n\t * @throws {UnknownRunError} when `runId` was never a run of this workspace.\n\t * @throws {HistoryExpiredError} when retention removed `runId` or chained it into a later run.\n\t */\n\treadRun(runId: string): Promise<{ record: RunRecord; entries: JournalEntry[] }>;\n\t/** The bytes a hash names. */\n\treadContent(hash: string): Promise<Buffer>;\n}\n\n/** A move was asked from one point of the history, and the workspace is at another. */\nexport class WorkspaceMovedError extends Error {\n\t/** Where the move expected the workspace: a run, or `historyStart`. */\n\treadonly expected: string;\n\t/** Where the workspace is: a run, or `historyStart`. */\n\treadonly actual: string;\n\n\tconstructor(expected: string, actual: string) {\n\t\tconst name = (point: string) => (point === historyStart ? 'the start' : `run ${point}`);\n\t\tsuper(`The workspace is no longer at ${name(expected)}: it is at ${name(actual)}`);\n\t\tthis.name = 'WorkspaceMovedError';\n\t\tthis.expected = expected;\n\t\tthis.actual = actual;\n\t}\n}\n\nexport class WorkspaceBusyError extends Error {\n\treadonly runId: string;\n\n\tconstructor(runId: string) {\n\t\tsuper(`The workspace is busy: ${runId} is writing to it`);\n\t\tthis.name = 'WorkspaceBusyError';\n\t\tthis.runId = runId;\n\t}\n}\n"]}
|
|
@@ -935,6 +935,13 @@ class FileRunJournal {
|
|
|
935
935
|
release;
|
|
936
936
|
sequence = 0;
|
|
937
937
|
stored = 0;
|
|
938
|
+
// For the content state: what each change will leave, what each file held before the run first
|
|
939
|
+
// changed it, and what it holds since its last applied change.
|
|
940
|
+
pendingStates = new Map();
|
|
941
|
+
firstStates = new Map();
|
|
942
|
+
currentStates = new Map();
|
|
943
|
+
appliedInOrder = [];
|
|
944
|
+
state;
|
|
938
945
|
// The changes recorded as prepared and not abandoned: those that may have reached a file. One
|
|
939
946
|
// whose `prepared` line failed is not here, since nothing writes a file before that line.
|
|
940
947
|
effects = new Set();
|
|
@@ -965,17 +972,27 @@ class FileRunJournal {
|
|
|
965
972
|
const sequence = ++this.sequence;
|
|
966
973
|
await this.append({ type: 'prepared', sequence, ...change });
|
|
967
974
|
this.effects.add(sequence);
|
|
975
|
+
this.pendingStates.set(sequence, { path: change.path, after: change.after });
|
|
976
|
+
if (!this.firstStates.has(change.path))
|
|
977
|
+
this.firstStates.set(change.path, change.before);
|
|
968
978
|
return sequence;
|
|
969
979
|
}
|
|
970
|
-
applied(sequence) {
|
|
980
|
+
async applied(sequence) {
|
|
971
981
|
this.assertOpen();
|
|
972
|
-
|
|
982
|
+
await this.append({ type: 'applied', sequence });
|
|
983
|
+
const change = this.pendingStates.get(sequence);
|
|
984
|
+
if (!change)
|
|
985
|
+
return;
|
|
986
|
+
this.pendingStates.delete(sequence);
|
|
987
|
+
this.currentStates.set(change.path, change.after);
|
|
988
|
+
this.appliedInOrder.push(change.path);
|
|
973
989
|
}
|
|
974
990
|
async abandoned(sequence) {
|
|
975
991
|
this.assertOpen();
|
|
976
992
|
await this.append({ type: 'abandoned', sequence });
|
|
977
993
|
// Only once recorded: a change whose abandonment was not may still count as made.
|
|
978
994
|
this.effects.delete(sequence);
|
|
995
|
+
this.pendingStates.delete(sequence);
|
|
979
996
|
}
|
|
980
997
|
async observe(manifest, by) {
|
|
981
998
|
this.assertOpen();
|
|
@@ -994,6 +1011,25 @@ class FileRunJournal {
|
|
|
994
1011
|
get storedBytes() {
|
|
995
1012
|
return this.stored;
|
|
996
1013
|
}
|
|
1014
|
+
get appliedPaths() {
|
|
1015
|
+
return this.appliedInOrder;
|
|
1016
|
+
}
|
|
1017
|
+
// Computed again only after a change was applied.
|
|
1018
|
+
contentState() {
|
|
1019
|
+
if (this.state?.applied !== this.appliedInOrder.length) {
|
|
1020
|
+
const changed = [...this.currentStates]
|
|
1021
|
+
.filter(([path, current]) => {
|
|
1022
|
+
const first = this.firstStates.get(path);
|
|
1023
|
+
return !first || !sameState(first, current);
|
|
1024
|
+
})
|
|
1025
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
1026
|
+
this.state = {
|
|
1027
|
+
applied: this.appliedInOrder.length,
|
|
1028
|
+
hash: hashOf(Buffer.from(JSON.stringify(changed))),
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
return this.state.hash;
|
|
1032
|
+
}
|
|
997
1033
|
get changed() {
|
|
998
1034
|
return this.effects.size > 0;
|
|
999
1035
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileRecoveryStore.js","sourceRoot":"","sources":["../../../src/recovery/infrastructure/fileRecoveryStore.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from 'node:crypto';\nimport {\n\tlink,\n\tmkdir,\n\topen,\n\treaddir,\n\treadFile,\n\trealpath,\n\trename,\n\trm,\n\tstat,\n\ttruncate,\n\tunlink,\n} from 'node:fs/promises';\nimport type { FileHandle } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { type FileChange, fileChanges, sameState } from '../domain/fileChanges.ts';\nimport {\n\thistoryStart,\n\ttype FileState,\n\ttype JournalEntry,\n\ttype Manifest,\n\ttype ObservationMeasure,\n\ttype MoveConflict,\n\ttype MoveOptions,\n\tNothingToMoveError,\n\ttype Revision,\n\ttype RecoveryStore,\n\ttype RunJournal,\n\ttype RunRecord,\n\ttype RunStatus,\n\tWorkspaceBusyError,\n\tWorkspaceMovedError,\n} from '../domain/recoveryStore.ts';\nimport { chainEntries, nextPruneStep } from '../domain/retention.ts';\nimport { HistoryExpiredError, redoTarget, route, UnknownRunError } from '../domain/runTree.ts';\nimport {\n\tcurrentState,\n\thasRealParents,\n\tremoveEmptyFolders,\n\tremoveFile,\n\tremoveTemporary,\n\ttemporaryPath,\n\twriteFileState,\n} from './workspaceFiles.ts';\n\nconst appName = 'mikode-harness';\n// The store holds source code the agent touched: only its owner may read it.\nconst privateDirectory = 0o700;\nconst privateFile = 0o600;\n\nconst firstJournal = 'journal.jsonl';\n\n// A run is roughly one prompt: enough to go back through a working session, not a project's life.\nconst defaultKeepRuns = 25;\n\nconst runIdPattern = /^\\d{8}T\\d{9}Z-[0-9a-f]{6}$/;\nconst hashPattern = /^[0-9a-f]{64}$/;\n\n/** Where an application keeps state that is neither configuration nor cache, per platform. */\nexport function defaultStateDirectory(\n\tenv: NodeJS.ProcessEnv = process.env,\n\tplatform: NodeJS.Platform = process.platform,\n\thome: string = homedir(),\n): string {\n\t// The XDG spec says to ignore a relative path, which here could land inside the repository.\n\tconst xdg = env.XDG_STATE_HOME;\n\tif (xdg && isAbsolute(xdg)) return join(xdg, appName);\n\tif (platform === 'darwin') return join(home, 'Library', 'Application Support', appName);\n\treturn join(home, '.local', 'state', appName);\n}\n\n/** Sorts by start time as text, so the latest run is the last one listed. */\nfunction newRunId(): string {\n\treturn `${new Date().toISOString().replace(/[-:.]/g, '')}-${randomBytes(3).toString('hex')}`;\n}\n\nfunction hashOf(content: Buffer): string {\n\treturn createHash('sha256').update(content).digest('hex');\n}\n\nfunction isNotFound(error: unknown): boolean {\n\treturn (error as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * The runs and moves this process holds a workspace lock for and has not ended. A lock naming\n * this process and none of these was left by one whose release failed: it is as stale as a dead\n * process's, which a process that lives on would otherwise keep until it exits.\n */\nconst heldHere = new Set<string>();\n\n/** Whether the holder of a lock is still at work. */\nfunction isLiveHolder(holder: { runId: string; pid?: number }): boolean {\n\t// A holder that cannot be named cannot be shown to be gone.\n\tif (holder.pid === undefined) return true;\n\tif (holder.pid === process.pid) return heldHere.has(holder.runId);\n\treturn isAlive(holder.pid);\n}\n\n/** Whether a process still exists. One we may not signal exists too. */\nfunction isAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn (error as NodeJS.ErrnoException).code === 'EPERM';\n\t}\n}\n\nasync function syncDirectory(path: string): Promise<void> {\n\tconst directory = await open(path, 'r');\n\ttry {\n\t\tawait directory.sync();\n\t} finally {\n\t\tawait directory.close();\n\t}\n}\n\n/**\n * Creates a private folder and any missing parents. A new folder only survives a crash once\n * its parent's entry for it is synced too, so each parent that gained one is.\n */\nasync function makeDirectory(path: string): Promise<void> {\n\tconst first = await mkdir(path, { recursive: true, mode: privateDirectory });\n\tif (first === undefined) return;\n\tfor (let created = path; ; created = dirname(created)) {\n\t\tawait syncDirectory(dirname(created));\n\t\tif (created === first) return;\n\t}\n}\n\n/**\n * Puts `content` at `path` all at once: a crash leaves either the old file or the new one, never\n * half of the new one. It returns only once the new file is on disk. With `exclusive`, it fails\n * with `EEXIST` instead of replacing a file already there.\n */\nasync function writeDurably(\n\tpath: string,\n\tcontent: string | Buffer,\n\t{ exclusive = false }: { exclusive?: boolean } = {},\n): Promise<void> {\n\tconst temporary = `${path}.${randomBytes(6).toString('hex')}.tmp`;\n\ttry {\n\t\tconst handle = await open(temporary, 'wx', privateFile);\n\t\ttry {\n\t\t\tawait handle.writeFile(content);\n\t\t\tawait handle.sync();\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\t// A link fails if the path is taken; a rename would replace it.\n\t\tawait (exclusive ? link : rename)(temporary, path);\n\t} finally {\n\t\tawait rm(temporary, { force: true });\n\t}\n\tawait syncDirectory(dirname(path));\n}\n\n/** A move not finished yet: the next move or run finishes it before anything else. */\ninterface PendingMove {\n\trevision: number;\n\tfrom?: string;\n\tto?: string;\n\treason?: string;\n\t/** Found by the steps already taken. */\n\tconflicts: MoveConflict[];\n\t/**\n\t * The temporary a file is being restored through, named before it is created, so finishing\n\t * the move removes this one and no file of the user's.\n\t */\n\ttemporary?: string;\n}\n\n/** `head.json`: the run the workspace is at, the moves made so far, and one in progress. */\ninterface Head {\n\trunId?: string;\n\trevision: number;\n\tpending?: PendingMove;\n}\n\ntype JournalLine =\n\t| ({ type: 'prepared'; sequence: number } & Omit<JournalEntry, 'sequence' | 'status'>)\n\t| { type: 'applied' | 'abandoned'; sequence: number }\n\t| { type: 'observing'; sequence: number; manifest: string; by: string }\n\t| { type: 'observed'; sequence: number; measure?: ObservationMeasure };\n\n/** An observation a run began and never finished: what its command changed is not recorded yet. */\ninterface OpenObservation {\n\tsequence: number;\n\tmanifest: string;\n\tby: string;\n}\n\n/**\n * Stores `content` under its hash, unless it is stored already, and returns the hash and whether\n * it was new. It returns only once the content is on disk.\n */\nasync function storeContent(\n\tcontentDirectory: string,\n\tcontent: Buffer,\n): Promise<{ hash: string; written: boolean }> {\n\tconst hash = hashOf(content);\n\tconst path = contentPath(contentDirectory, hash);\n\tconst stored = await stat(path).then(\n\t\t() => true,\n\t\t(error: unknown) => {\n\t\t\tif (isNotFound(error)) return false;\n\t\t\tthrow error;\n\t\t},\n\t);\n\tif (!stored) {\n\t\tawait makeDirectory(dirname(path));\n\t\tawait writeDurably(path, content);\n\t}\n\treturn { hash, written: !stored };\n}\n\n/**\n * The recovery store on disk, in a private directory per workspace under the platform's state\n * directory:\n *\n * ```text\n * <directory>/workspaces/<hash of the root>/\n * workspace.json the root it belongs to\n * lock the run writing now, if any\n * head.json the run the workspace is at, and a move in progress\n * revisions.jsonl every move of the workspace through its history\n * content/<ab>/<hash> file contents, named by their SHA-256\n * runs/<runId>/run.json the run's record\n * runs/<runId>/journal.jsonl its changes, one line per step, appended and synced\n * ```\n *\n * The lock only keeps a second run of this harness from writing at the same time. It does not\n * stop an editor or another program, and two processes taking over a dead run's lock in the\n * same instant could both believe they hold it.\n */\nexport class FileRecoveryStore implements RecoveryStore {\n\tprivate readonly root: string;\n\tprivate readonly directory: string;\n\tprivate readonly keepRuns: number;\n\n\tprivate constructor(root: string, directory: string, keepRuns: number) {\n\t\tthis.root = root;\n\t\tthis.directory = directory;\n\t\tthis.keepRuns = keepRuns;\n\t}\n\n\tstatic async open({\n\t\troot,\n\t\tdirectory = defaultStateDirectory(),\n\t\tkeepRuns = defaultKeepRuns,\n\t}: {\n\t\troot: string;\n\t\t/** Defaults to the platform's state directory. */\n\t\tdirectory?: string;\n\t\t/**\n\t\t * The most runs kept per workspace, the one being recorded included. Defaults to 25. At\n\t\t * least 3: the run the workspace is at is never removed, and the last run of its line has\n\t\t * no next run to be chained into, so pruning can leave two runs besides the new one.\n\t\t */\n\t\tkeepRuns?: number;\n\t}): Promise<FileRecoveryStore> {\n\t\tif (!Number.isInteger(keepRuns) || keepRuns < 3) {\n\t\t\tthrow new RangeError(`keepRuns must be an integer of at least 3; got ${String(keepRuns)}`);\n\t\t}\n\t\t// Two spellings of one folder, such as a symlinked path, are one workspace.\n\t\tconst realRoot = await realpath(root);\n\t\tconst workspace = join(\n\t\t\tdirectory,\n\t\t\t'workspaces',\n\t\t\tcreateHash('sha256').update(realRoot).digest('hex').slice(0, 16),\n\t\t);\n\t\tawait makeDirectory(join(workspace, 'runs'));\n\t\tawait makeDirectory(join(workspace, 'content'));\n\t\tawait writeDurably(join(workspace, 'workspace.json'), JSON.stringify({ root: realRoot }));\n\n\t\treturn new FileRecoveryStore(realRoot, workspace, keepRuns);\n\t}\n\n\tasync startRun(): Promise<RunJournal> {\n\t\tconst runId = newRunId();\n\t\ttry {\n\t\t\t// Inside, because taking the lock can fail after publishing it. Unlocking removes only a\n\t\t\t// lock naming this run, never another run's.\n\t\t\tawait this.lock(runId);\n\t\t\tawait this.settleInterrupted(runId);\n\t\t\t// A run starts where the user last sent the workspace.\n\t\t\tawait this.finishPendingMove();\n\t\t\t// Before the new run exists, so it is never pruned, and after the move, so no run on its\n\t\t\t// route is.\n\t\t\tawait this.prune();\n\t\t\tconst head = await this.readHead();\n\t\t\tconst parentRunId = head.runId;\n\t\t\tconst runDirectory = join(this.directory, 'runs', runId);\n\t\t\tawait makeDirectory(runDirectory);\n\t\t\tconst record: RunRecord = {\n\t\t\t\trunId,\n\t\t\t\troot: this.root,\n\t\t\t\t...(parentRunId ? { parentRunId } : {}),\n\t\t\t\tstartedAt: new Date().toISOString(),\n\t\t\t\tstatus: 'running',\n\t\t\t\tpid: process.pid,\n\t\t\t};\n\t\t\tawait writeDurably(join(runDirectory, 'run.json'), JSON.stringify(record));\n\t\t\t// After the record, so the head never names a run that does not exist.\n\t\t\tawait this.writeHead({ runId, revision: head.revision });\n\t\t\tconst journal = await open(join(runDirectory, firstJournal), 'a', privateFile);\n\t\t\tawait syncDirectory(runDirectory);\n\n\t\t\treturn new FileRunJournal({\n\t\t\t\trecord,\n\t\t\t\trunDirectory,\n\t\t\t\tcontentDirectory: join(this.directory, 'content'),\n\t\t\t\tjournal,\n\t\t\t\tdiscard: () => this.discardRun(record),\n\t\t\t\trelease: () => this.unlock(runId),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tawait this.unlock(runId);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync listRuns(): Promise<{ head?: string; runs: RunRecord[] }> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(id => runIdPattern.test(id));\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\tconst runs: RunRecord[] = [];\n\t\tfor (const runId of ids.sort()) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\t// A crash between creating a run's folder and writing its record leaves the folder\n\t\t\t\t// empty: that run never changed anything.\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record) runs.push(withLiveStatus(record, holder));\n\t\t}\n\t\t// A run retention removed or chained into a later one, whose folder a crash left behind, is\n\t\t// not in the history.\n\t\tconst gone = new Set([\n\t\t\t...runs.flatMap(run => run.absorbed ?? []),\n\t\t\t...(await this.listPruned()),\n\t\t]);\n\t\t// A dead run that changed nothing is not in the history either, though its removal did not\n\t\t// finish. No run follows it: the next run or move removes it before starting.\n\t\tfor (const run of runs) {\n\t\t\tif (run.status !== 'interrupted') continue;\n\t\t\t// A journal it cannot read leaves the run listed: whether it changed anything is unknown.\n\t\t\tconst entries = await this.readEntries(run.runId, run.journal).catch(() => undefined);\n\t\t\tif (entries && changedNothing(entries)) gone.add(run.runId);\n\t\t}\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet { runId: head } = await this.readHead();\n\t\twhile (head !== undefined && gone.has(head)) head = parents.get(head);\n\n\t\treturn { ...(head ? { head } : {}), runs: runs.filter(run => !gone.has(run.runId)) };\n\t}\n\n\tasync readRun(runId: string): Promise<{ record: RunRecord; entries: JournalEntry[] }> {\n\t\t// An id from outside is checked before it names a folder.\n\t\tif (!runIdPattern.test(runId)) throw new UnknownRunError(runId);\n\t\t// The lock first: a run that finishes between the two reads then shows as finished, not as\n\t\t// a `running` record nobody holds.\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\t// Before the record: a crash can leave the folder of a run retention already took.\n\t\tawait this.assertNotAbsorbed(runId);\n\t\tconst record = await this.readRecord(runId).catch(async (error: unknown) => {\n\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t// Retention may have taken it since the check above.\n\t\t\tawait this.assertNotAbsorbed(runId);\n\t\t\tthrow new UnknownRunError(runId);\n\t\t});\n\t\treturn {\n\t\t\trecord: withLiveStatus(record, holder),\n\t\t\tentries: await this.readEntries(runId, record.journal),\n\t\t};\n\t}\n\n\tprivate async readRecord(runId: string): Promise<RunRecord> {\n\t\treturn JSON.parse(\n\t\t\tawait readFile(join(this.runDirectory(runId), 'run.json'), 'utf8'),\n\t\t) as RunRecord;\n\t}\n\n\tprivate runDirectory(runId: string): string {\n\t\t// The id names a folder, so it must never be a path of its own.\n\t\tif (!runIdPattern.test(runId)) throw new Error(`Not a run id: ${runId}`);\n\t\treturn join(this.directory, 'runs', runId);\n\t}\n\n\tprivate async readHead(): Promise<Head> {\n\t\ttry {\n\t\t\tconst head = JSON.parse(\n\t\t\t\tawait readFile(join(this.directory, 'head.json'), 'utf8'),\n\t\t\t) as Partial<Head>;\n\t\t\treturn { ...head, revision: head.revision ?? 0 };\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return { revision: 0 };\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async writeHead(head: Head): Promise<void> {\n\t\tawait writeDurably(join(this.directory, 'head.json'), JSON.stringify(head));\n\t}\n\n\tgoTo(target: string, options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(() => (target === historyStart ? undefined : target), options);\n\t}\n\n\tundo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head }) => {\n\t\t\tif (head === undefined) throw new NothingToMoveError('undo');\n\t\t\treturn runs.find(run => run.runId === head)?.parentRunId;\n\t\t}, options);\n\t}\n\n\tredo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head, revisions }) => {\n\t\t\tconst target = redoTarget(runs, revisions, head);\n\t\t\tif (target === undefined) throw new NothingToMoveError('redo');\n\t\t\treturn target;\n\t\t}, options);\n\t}\n\n\tasync listRevisions(): Promise<Revision[]> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.directory, 'revisions.jsonl'), 'utf8');\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\t\treturn lines.flatMap((line, index) => {\n\t\t\tif (line === '') return [];\n\t\t\ttry {\n\t\t\t\treturn [JSON.parse(line) as Revision];\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// move is still pending, and finishing it records it again.\n\t\t\t\tif (index === lines.length - 1) return [];\n\t\t\t\tthrow new Error(`The history of this workspace is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Holds the workspace like a run does, then moves it to the run `resolve` picks. */\n\tprivate async move(\n\t\tresolve: (history: {\n\t\t\truns: RunRecord[];\n\t\t\thead: string | undefined;\n\t\t\trevisions: Revision[];\n\t\t}) => string | undefined,\n\t\t{ reason, from }: MoveOptions,\n\t): Promise<Revision> {\n\t\tconst moveId = `move-${newRunId()}`;\n\t\ttry {\n\t\t\tawait this.lock(moveId);\n\t\t\tawait this.settleInterrupted(moveId);\n\t\t\tawait this.finishPendingMove();\n\t\t\tconst head = await this.readHead();\n\t\t\t// Only now, under the lock and once nothing is left unsettled, is the head the one the\n\t\t\t// move would start from.\n\t\t\tconst at = head.runId ?? historyStart;\n\t\t\tif (from !== undefined && from !== at) throw new WorkspaceMovedError(from, at);\n\t\t\tconst { runs } = await this.listRuns();\n\t\t\tconst to = resolve({ runs, head: head.runId, revisions: await this.listRevisions() });\n\t\t\tif (to !== undefined && !runs.some(run => run.runId === to)) {\n\t\t\t\tawait this.assertNotAbsorbed(to);\n\t\t\t}\n\n\t\t\treturn await this.takeSteps(head, runs, {\n\t\t\t\trevision: head.revision + 1,\n\t\t\t\t...(head.runId ? { from: head.runId } : {}),\n\t\t\t\t...(to ? { to } : {}),\n\t\t\t\t...(reason === undefined ? {} : { reason }),\n\t\t\t\tconflicts: [],\n\t\t\t});\n\t\t} finally {\n\t\t\tawait this.unlock(moveId);\n\t\t}\n\t}\n\n\t/** Finishes a move whose process stopped halfway, from the run its last step reached. */\n\tprivate async finishPendingMove(): Promise<void> {\n\t\tconst head = await this.readHead();\n\t\tconst { pending } = head;\n\t\tif (!pending) return;\n\t\t// It was recorded, and only clearing it from the head was missing.\n\t\tif ((await this.listRevisions()).some(revision => revision.revision === pending.revision)) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\t\trevision: pending.revision,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this.takeSteps(head, (await this.listRuns()).runs, pending);\n\t}\n\n\t/**\n\t * Undoes, then redoes, one run at a time from where the head is to `pending.to`. After each\n\t * step the head names the run reached, with the move still pending, so a crash loses at\n\t * most the step in progress, and that step is safe to take again.\n\t */\n\tprivate async takeSteps(head: Head, runs: RunRecord[], pending: PendingMove): Promise<Revision> {\n\t\tconst { undo, redo } = route(runs, head.runId, pending.to);\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet reached = head.runId;\n\t\tconst save = () =>\n\t\t\tthis.writeHead({ ...(reached ? { runId: reached } : {}), revision: head.revision, pending });\n\n\t\t// What a write the crash interrupted left beside its file.\n\t\tif (pending.temporary) {\n\t\t\tawait removeTemporary(pending.temporary);\n\t\t\tdelete pending.temporary;\n\t\t}\n\t\tawait save();\n\t\tconst announce = async (temporary: string | undefined) => {\n\t\t\tif (temporary === undefined) delete pending.temporary;\n\t\t\telse pending.temporary = temporary;\n\t\t\tawait save();\n\t\t};\n\t\tfor (const runId of undo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'undo', announce)));\n\t\t\treached = parents.get(runId);\n\t\t\tawait save();\n\t\t}\n\t\tfor (const runId of redo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'redo', announce)));\n\t\t\treached = runId;\n\t\t\tawait save();\n\t\t}\n\n\t\t// Every write that started has finished, so no temporary is left to name.\n\t\tdelete pending.temporary;\n\t\tconst { conflicts, ...rest } = pending;\n\t\tconst revision: Revision = {\n\t\t\t...rest,\n\t\t\tat: new Date().toISOString(),\n\t\t\tcomplete: conflicts.length === 0,\n\t\t\tconflicts,\n\t\t};\n\t\tawait this.appendRevision(revision);\n\t\tawait this.writeHead({\n\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\trevision: pending.revision,\n\t\t});\n\t\treturn revision;\n\t}\n\n\t/** Takes one run's changes back to its parent, or forward again, file by file. */\n\tprivate async step(\n\t\trunId: string,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<MoveConflict[]> {\n\t\tconst { entries } = await this.readRun(runId);\n\t\tconst changes = fileChanges(entries, true);\n\t\tconst conflicts: MoveConflict[] = [];\n\t\t// Undone newest first, so a folder the run created is empty by the time its file goes.\n\t\tfor (const change of direction === 'undo' ? changes.reverse() : changes) {\n\t\t\tif (!(await this.moveFile(change, direction, announce))) {\n\t\t\t\tconflicts.push({ path: change.path, runId });\n\t\t\t}\n\t\t}\n\t\treturn conflicts;\n\t}\n\n\t/**\n\t * Writes the state the step leads to, only if the file holds the state it leaves. A file\n\t * already there is left alone, so taking a step again is safe. Returns whether the file\n\t * ends where the step leads.\n\t */\n\tprivate async moveFile(\n\t\tchange: FileChange,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<boolean> {\n\t\tconst [source, destination] =\n\t\t\tdirection === 'undo' ? [change.after, change.before] : [change.before, change.after];\n\t\t// First, so a file reached through a folder that became a link is never taken for the\n\t\t// destination, and nothing is read or removed through it.\n\t\tif (!(await hasRealParents(change.path))) return false;\n\t\tconst current = await currentState(change.path);\n\n\t\tif (current && sameState(current, destination)) {\n\t\t\tif (direction === 'undo' && !destination.exists) {\n\t\t\t\tawait removeEmptyFolders(change.createdFolders);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (!current || !sameState(current, source)) return false;\n\t\t// Someone wrote to the file between two of the run's changes, and going back to before\n\t\t// the first would discard that.\n\t\tif (direction === 'undo' && !change.continuous) return false;\n\n\t\tif (destination.exists) {\n\t\t\tconst temporary = temporaryPath(change.path);\n\t\t\tawait announce(temporary);\n\t\t\tawait writeFileState(\n\t\t\t\tchange.path,\n\t\t\t\tawait this.readContent(destination.hash),\n\t\t\t\tdestination.mode,\n\t\t\t\ttemporary,\n\t\t\t);\n\t\t\tawait announce(undefined);\n\t\t} else {\n\t\t\tawait removeFile(change.path);\n\t\t\tif (direction === 'undo') await removeEmptyFolders(change.createdFolders);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** Throws `HistoryExpiredError` if retention removed `runId` or chained it into a later run. */\n\tprivate async assertNotAbsorbed(runId: string): Promise<void> {\n\t\tconst { runs } = await this.listRuns();\n\t\tconst keptIn = runs.find(run => run.absorbed?.includes(runId));\n\t\tif (keptIn) throw new HistoryExpiredError(runId, keptIn.runId);\n\t\tif ((await this.listPruned()).includes(runId)) throw new HistoryExpiredError(runId);\n\t}\n\n\tprivate async listPruned(): Promise<string[]> {\n\t\ttry {\n\t\t\tconst text = await readFile(join(this.directory, 'pruned.jsonl'), 'utf8');\n\t\t\treturn text.split('\\n').flatMap(line => {\n\t\t\t\ttry {\n\t\t\t\t\treturn [JSON.parse(line) as string];\n\t\t\t\t} catch {\n\t\t\t\t\t// Half a line a crash left, whose removal never happened.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Brings the history down to `keepRuns - 1`, so the run about to start makes `keepRuns`, then\n\t * frees the contents no run kept refers to.\n\t */\n\tprivate async prune(): Promise<void> {\n\t\tawait this.finishChains();\n\t\tconst revisions = await this.listRevisions();\n\t\tfor (;;) {\n\t\t\tconst { head, runs } = await this.listRuns();\n\t\t\tconst step = nextPruneStep(runs, revisions, head, this.keepRuns - 1);\n\t\t\tif (!step) break;\n\t\t\tif (step.kind === 'remove') await this.removeRun(step.runId);\n\t\t\telse await this.chain(step.runId, step.into);\n\t\t}\n\t\tawait this.collectContent();\n\t}\n\n\t/**\n\t * Chains the changes of `older` into `newer`, its child: `newer` then hangs from `older`'s\n\t * parent and goes back to where `older` started. The new record is the commit point. Before\n\t * it, the history is as it was; after it, `finishChains` removes what is left of `older`.\n\t */\n\tprivate async chain(older: string, newer: string): Promise<void> {\n\t\tconst olderRecord = await this.readRecord(older);\n\t\tconst newerRecord = await this.readRecord(newer);\n\t\tconst entries = chainEntries(\n\t\t\tawait this.readEntries(older, olderRecord.journal),\n\t\t\tawait this.readEntries(newer, newerRecord.journal),\n\t\t);\n\t\tconst journal = `journal-${randomBytes(4).toString('hex')}.jsonl`;\n\t\tconst lines = entries.flatMap(({ status, sequence, ...change }): JournalLine[] => [\n\t\t\t{ type: 'prepared', sequence, ...change },\n\t\t\t...(status === 'prepared' ? [] : [{ type: status, sequence } as const]),\n\t\t]);\n\t\tawait writeDurably(\n\t\t\tjoin(this.runDirectory(newer), journal),\n\t\t\tlines.map(line => `${JSON.stringify(line)}\\n`).join(''),\n\t\t);\n\n\t\tconst record: RunRecord = {\n\t\t\t...newerRecord,\n\t\t\tabsorbed: [...(olderRecord.absorbed ?? []), older, ...(newerRecord.absorbed ?? [])],\n\t\t\tjournal,\n\t\t};\n\t\t// It now hangs where `older` did: from its parent, or from the start.\n\t\tif (olderRecord.parentRunId) record.parentRunId = olderRecord.parentRunId;\n\t\telse delete record.parentRunId;\n\t\tawait writeDurably(join(this.runDirectory(newer), 'run.json'), JSON.stringify(record));\n\t\tawait this.finishChains();\n\t}\n\n\t/**\n\t * Removes what a chain or a removal a crash interrupted left behind: the folders of runs\n\t * pruned or absorbed by a kept run, and journals a run no longer reads.\n\t */\n\tprivate async finishChains(): Promise<void> {\n\t\tfor (const runId of await this.listPruned()) {\n\t\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t\t}\n\t\tconst { runs } = await this.listRuns();\n\t\tfor (const run of runs) {\n\t\t\tfor (const absorbed of run.absorbed ?? []) {\n\t\t\t\tawait rm(this.runDirectory(absorbed), { recursive: true, force: true });\n\t\t\t}\n\t\t\tconst current = run.journal ?? firstJournal;\n\t\t\tfor (const name of await readdir(this.runDirectory(run.runId))) {\n\t\t\t\tif (name.startsWith('journal') && name.endsWith('.jsonl') && name !== current) {\n\t\t\t\t\tawait rm(join(this.runDirectory(run.runId), name), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes a run whole, recording its id first so a move to it reports an expired history.\n\t * Its record goes next, so a crash halfway leaves no run behind.\n\t */\n\tprivate async removeRun(runId: string): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'pruned.jsonl'), [runId]);\n\t\t// The log may be new: its entry in the folder must last before the run it names goes.\n\t\tawait syncDirectory(this.directory);\n\t\tawait rm(join(this.runDirectory(runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(runId));\n\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t}\n\n\t/**\n\t * Takes a run that changed nothing out of the history, under the lock: the workspace goes back\n\t * to its parent first, so the head never names a run that is gone. Until the run is removed,\n\t * `listRuns` already hides it, and the next run or move finishes removing it. The contents it\n\t * saved are freed by the next prune.\n\t */\n\tprivate async discardRun(record: RunRecord): Promise<void> {\n\t\tconst { runId: headRunId, ...head } = await this.readHead();\n\t\tif (headRunId === record.runId) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...head,\n\t\t\t\t...(record.parentRunId ? { runId: record.parentRunId } : {}),\n\t\t\t});\n\t\t}\n\t\tawait rm(join(this.runDirectory(record.runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(record.runId));\n\t\tawait rm(this.runDirectory(record.runId), { recursive: true, force: true });\n\t}\n\n\t/** Removes the stored contents no kept run refers to. */\n\tprivate async collectContent(): Promise<void> {\n\t\tconst referenced = new Set<string>();\n\t\tfor (const run of (await this.listRuns()).runs) {\n\t\t\tfor (const entry of await this.readEntries(run.runId, run.journal)) {\n\t\t\t\tfor (const state of [entry.before, entry.after]) {\n\t\t\t\t\tif (state.exists) referenced.add(state.hash);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst contentDirectory = join(this.directory, 'content');\n\t\tfor (const prefix of await readdir(contentDirectory)) {\n\t\t\tfor (const hash of await readdir(join(contentDirectory, prefix))) {\n\t\t\t\tif (hashPattern.test(hash) && !referenced.has(hash)) {\n\t\t\t\t\tawait rm(join(contentDirectory, prefix, hash), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async appendRevision(revision: Revision): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'revisions.jsonl'), [revision]);\n\t\tawait syncDirectory(this.directory);\n\t}\n\n\t/**\n\t * Marks every other run still recorded as `running` as `interrupted`: this run holds the lock,\n\t * so their processes are gone. Each change one left `prepared` is settled from what its file\n\t * holds now: its `after` means it was made, its `before` that it was not. A file that holds\n\t * neither stays `prepared`, because nothing tells whether the change reached it.\n\t */\n\tprivate async settleInterrupted(ownRunId: string): Promise<void> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(\n\t\t\tid => runIdPattern.test(id) && id !== ownRunId,\n\t\t);\n\t\tfor (const runId of ids) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record?.status !== 'running') continue;\n\n\t\t\tconst journal = await this.readJournal(runId, record.journal);\n\t\t\tconst settled: JournalLine[] = [];\n\t\t\tfor (const entry of journal.entries) {\n\t\t\t\tif (entry.status !== 'prepared' || !isAbsolute(entry.path)) continue;\n\t\t\t\tconst state = await currentState(entry.path);\n\t\t\t\tif (state && sameState(state, entry.after)) {\n\t\t\t\t\tsettled.push({ type: 'applied', sequence: entry.sequence });\n\t\t\t\t} else if (state && sameState(state, entry.before)) {\n\t\t\t\t\tsettled.push({ type: 'abandoned', sequence: entry.sequence });\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet sequence = journal.lastSequence;\n\t\t\tfor (const observation of journal.observations) {\n\t\t\t\tconst lines = await this.settleObservation(observation, journal.entries, sequence);\n\t\t\t\tsequence += lines.length;\n\t\t\t\tsettled.push(...lines);\n\t\t\t}\n\t\t\tawait appendWhole(join(this.runDirectory(runId), record.journal ?? firstJournal), settled);\n\t\t\tif (changedNothing(await this.readEntries(runId, record.journal))) {\n\t\t\t\tawait this.discardRun(record);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Last, so a crash before it leaves a run that is settled again, and settling is idempotent.\n\t\t\tawait writeDurably(\n\t\t\t\tjoin(this.runDirectory(runId), 'run.json'),\n\t\t\t\tJSON.stringify({ ...record, status: 'interrupted' } satisfies RunRecord),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * The lines that record what a command an interrupted run was observing changed: every file of\n\t * its manifest that holds something else now, as changed by that command, and then the end of\n\t * the observation. A file recorded after the observation began is left alone: the run\n\t * recorded it itself. One that is now a folder, a link or too large to record is left out.\n\t */\n\tprivate async settleObservation(\n\t\tobservation: OpenObservation,\n\t\tentries: JournalEntry[],\n\t\tlastSequence: number,\n\t): Promise<JournalLine[]> {\n\t\tconst stored = await this.readContent(observation.manifest).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\t// Its manifest was never stored whole: the command it was saved for never started.\n\t\tif (!stored) return [{ type: 'observed', sequence: observation.sequence }];\n\t\tconst manifest = JSON.parse(stored.toString('utf8')) as Manifest;\n\t\tconst recorded = new Set(\n\t\t\tentries.filter(entry => entry.sequence > observation.sequence).map(entry => entry.path),\n\t\t);\n\t\tconst lines: JournalLine[] = [];\n\t\tlet sequence = lastSequence;\n\t\tfor (const [path, before] of Object.entries(manifest.files)) {\n\t\t\tif (!isAbsolute(path) || recorded.has(path)) continue;\n\t\t\tconst after = await this.saveState(path);\n\t\t\tif (!after || sameState(after, before)) continue;\n\t\t\tsequence++;\n\t\t\tlines.push(\n\t\t\t\t{ type: 'prepared', sequence, path, before, after, observedBy: observation.by },\n\t\t\t\t{ type: 'applied', sequence },\n\t\t\t);\n\t\t}\n\t\tlines.push({ type: 'observed', sequence: observation.sequence });\n\t\treturn lines;\n\t}\n\n\t/** What `path` holds now, with its content stored, or `undefined` for what no entry records. */\n\tprivate async saveState(path: string): Promise<FileState | undefined> {\n\t\tconst state = await currentState(path);\n\t\tif (!state?.exists) return state;\n\t\tconst content = await readFile(path).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\tif (!content) return { exists: false };\n\t\tconst { hash } = await storeContent(join(this.directory, 'content'), content);\n\t\t// Read again: the file may have changed between hashing it and storing it.\n\t\treturn hash === state.hash ? state : this.saveState(path);\n\t}\n\n\tprivate async readEntries(runId: string, journal = firstJournal): Promise<JournalEntry[]> {\n\t\treturn (await this.readJournal(runId, journal)).entries;\n\t}\n\n\t/**\n\t * A run's changes, the observations it began and never finished, and the highest sequence\n\t * number its journal uses, which the next line it gets must exceed.\n\t */\n\tprivate async readJournal(\n\t\trunId: string,\n\t\tjournal = firstJournal,\n\t): Promise<{ entries: JournalEntry[]; observations: OpenObservation[]; lastSequence: number }> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.runDirectory(runId), journal), 'utf8');\n\t\t} catch (error) {\n\t\t\t// A run that stopped before opening its journal never changed anything.\n\t\t\tif (isNotFound(error)) return { entries: [], observations: [], lastSequence: 0 };\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\n\t\tconst entries = new Map<number, JournalEntry>();\n\t\tconst observations = new Map<number, OpenObservation>();\n\t\tlet lastSequence = 0;\n\t\tlines.forEach((text, index) => {\n\t\t\tif (text === '') return;\n\t\t\tlet line: JournalLine;\n\t\t\ttry {\n\t\t\t\tline = JSON.parse(text) as JournalLine;\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// step never returned, so no change was made after it.\n\t\t\t\tif (index === lines.length - 1) return;\n\t\t\t\tthrow new Error(`The journal of run ${runId} is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t\tlastSequence = Math.max(lastSequence, line.sequence);\n\t\t\tif (line.type === 'prepared') {\n\t\t\t\tconst { sequence, path, before, after, createdFolders, observedBy } = line;\n\t\t\t\tentries.set(sequence, {\n\t\t\t\t\tsequence,\n\t\t\t\t\tpath,\n\t\t\t\t\tbefore,\n\t\t\t\t\tafter,\n\t\t\t\t\t...(createdFolders ? { createdFolders } : {}),\n\t\t\t\t\t...(observedBy === undefined ? {} : { observedBy }),\n\t\t\t\t\tstatus: 'prepared',\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observing') {\n\t\t\t\tconst { sequence, manifest, by } = line;\n\t\t\t\tobservations.set(sequence, { sequence, manifest, by });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observed') {\n\t\t\t\tobservations.delete(line.sequence);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entry = entries.get(line.sequence);\n\t\t\tif (entry) entry.status = line.type;\n\t\t});\n\n\t\treturn {\n\t\t\tentries: [...entries.values()],\n\t\t\tobservations: [...observations.values()],\n\t\t\tlastSequence,\n\t\t};\n\t}\n\n\tasync readContent(hash: string): Promise<Buffer> {\n\t\tif (!hashPattern.test(hash)) throw new Error(`Not a content hash: ${hash}`);\n\t\treturn readFile(contentPath(join(this.directory, 'content'), hash));\n\t}\n\n\tprivate async lock(runId: string): Promise<void> {\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Twice at most: once as it is, and once more after clearing a dead run's lock.\n\t\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\t\ttry {\n\t\t\t\t// Written whole before it appears, so a lock that exists always names its holder.\n\t\t\t\tawait writeDurably(path, JSON.stringify({ runId, pid: process.pid }), { exclusive: true });\n\t\t\t\theldHere.add(runId);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n\t\t\t}\n\n\t\t\tconst holder = await readLock(path);\n\t\t\t// Released meanwhile: try again.\n\t\t\tif (!holder) continue;\n\t\t\tif (isLiveHolder(holder)) throw new WorkspaceBusyError(holder.runId);\n\t\t\t// Its process died, or its run ended, without releasing it. Read again just before\n\t\t\t// removing, so a lock another run has just taken is left alone.\n\t\t\tconst again = await readLock(path);\n\t\t\tif (again !== undefined && again.pid === holder.pid && again.runId === holder.runId) {\n\t\t\t\tawait unlink(path).catch((error: unknown) => {\n\t\t\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthrow new WorkspaceBusyError((await readLock(path))?.runId ?? 'unknown');\n\t}\n\n\tprivate async unlock(runId: string): Promise<void> {\n\t\t// First: the run has ended even if removing its lock fails, so that lock is stale.\n\t\theldHere.delete(runId);\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Only its own lock: one cleared as stale and taken by another run is not this run's.\n\t\tif ((await readLock(path))?.runId === runId) await unlink(path);\n\t}\n}\n\n/** No change it recorded may have reached a file: it recorded none, or abandoned each one. */\nfunction changedNothing(entries: JournalEntry[]): boolean {\n\treturn entries.every(entry => entry.status === 'abandoned');\n}\n\n/**\n * A run recorded as `running` only runs while it holds the lock, its process lives, and, in this\n * process, it has not ended. Any other is reported as `interrupted`, before the next run settles\n * it.\n */\nfunction withLiveStatus(\n\trecord: RunRecord,\n\tholder: { runId: string; pid?: number } | undefined,\n): RunRecord {\n\tif (record.status !== 'running') return record;\n\tconst live = holder?.runId === record.runId && holder.pid !== undefined && isLiveHolder(holder);\n\treturn live ? record : { ...record, status: 'interrupted' };\n}\n\n/**\n * Appends `lines`, as JSON, to a file of one line each, created private if missing. A crash may\n * have left its last line without a newline. A whole line, which the readers already count, is\n * kept and ended. Half a line would join the first new line, so it is cut off: whatever was\n * writing it never returned.\n */\nasync function appendWhole(path: string, lines: unknown[]): Promise<void> {\n\tif (lines.length === 0) return;\n\tlet text = '';\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (!isNotFound(error)) throw error;\n\t}\n\tconst last = text.slice(text.lastIndexOf('\\n') + 1);\n\tlet separator = '';\n\tif (last !== '') {\n\t\tif (isWholeLine(last)) separator = '\\n';\n\t\telse await truncate(path, Buffer.byteLength(text) - Buffer.byteLength(last));\n\t}\n\tconst journal = await open(path, 'a', privateFile);\n\ttry {\n\t\tawait journal.appendFile(separator + lines.map(line => `${JSON.stringify(line)}\\n`).join(''));\n\t\tawait journal.sync();\n\t} finally {\n\t\tawait journal.close();\n\t}\n}\n\nfunction isWholeLine(text: string): boolean {\n\ttry {\n\t\tJSON.parse(text);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Who holds the lock, or `undefined` when nobody does. A lock this store did not write whole\n * has no `pid`, so it is never taken for a dead run's.\n */\nasync function readLock(path: string): Promise<{ runId: string; pid?: number } | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (isNotFound(error)) return undefined;\n\t\tthrow error;\n\t}\n\ttry {\n\t\tconst { runId, pid } = JSON.parse(text) as { runId?: unknown; pid?: unknown };\n\t\tif (typeof runId === 'string' && Number.isInteger(pid)) return { runId, pid: pid as number };\n\t} catch {\n\t\t// Not JSON: named below as unknown.\n\t}\n\treturn { runId: 'unknown' };\n}\n\nfunction contentPath(contentDirectory: string, hash: string): string {\n\t// Two levels, so no folder holds every file a workspace ever stored.\n\treturn join(contentDirectory, hash.slice(0, 2), hash);\n}\n\nclass FileRunJournal implements RunJournal {\n\treadonly runId: string;\n\tprivate readonly record: RunRecord;\n\tprivate readonly runDirectory: string;\n\tprivate readonly contentDirectory: string;\n\tprivate readonly journal: FileHandle;\n\tprivate readonly discard: () => Promise<void>;\n\tprivate readonly release: () => Promise<void>;\n\tprivate sequence = 0;\n\tprivate stored = 0;\n\t// The changes recorded as prepared and not abandoned: those that may have reached a file. One\n\t// whose `prepared` line failed is not here, since nothing writes a file before that line.\n\tprivate readonly effects = new Set<number>();\n\t// Appends run one after another, so the lines never interleave.\n\tprivate pending: Promise<unknown> = Promise.resolve();\n\tprivate finished = false;\n\t// Set when an append fails: it may have left part of a line, and anything after it would be\n\t// joined to that part and unreadable.\n\tprivate broken: unknown;\n\n\tconstructor({\n\t\trecord,\n\t\trunDirectory,\n\t\tcontentDirectory,\n\t\tjournal,\n\t\tdiscard,\n\t\trelease,\n\t}: {\n\t\trecord: RunRecord;\n\t\trunDirectory: string;\n\t\tcontentDirectory: string;\n\t\tjournal: FileHandle;\n\t\tdiscard: () => Promise<void>;\n\t\trelease: () => Promise<void>;\n\t}) {\n\t\tthis.runId = record.runId;\n\t\tthis.record = record;\n\t\tthis.runDirectory = runDirectory;\n\t\tthis.contentDirectory = contentDirectory;\n\t\tthis.journal = journal;\n\t\tthis.discard = discard;\n\t\tthis.release = release;\n\t}\n\n\tasync saveContent(content: Buffer): Promise<string> {\n\t\tthis.assertOpen();\n\t\tconst { hash, written } = await storeContent(this.contentDirectory, content);\n\t\tif (written) this.stored += content.length;\n\t\treturn hash;\n\t}\n\n\tasync prepare(change: Omit<JournalEntry, 'sequence' | 'status'>): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'prepared', sequence, ...change });\n\t\tthis.effects.add(sequence);\n\t\treturn sequence;\n\t}\n\n\tapplied(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\treturn this.append({ type: 'applied', sequence });\n\t}\n\n\tasync abandoned(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'abandoned', sequence });\n\t\t// Only once recorded: a change whose abandonment was not may still count as made.\n\t\tthis.effects.delete(sequence);\n\t}\n\n\tasync observe(manifest: string, by: string): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'observing', sequence, manifest, by });\n\t\t// Until it is observed, whatever ran may have changed a file.\n\t\tthis.effects.add(sequence);\n\t\treturn sequence;\n\t}\n\n\tasync observed(sequence: number, measure?: ObservationMeasure): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'observed', sequence, ...(measure ? { measure } : {}) });\n\t\t// Its changes, if any, are entries of their own now.\n\t\tthis.effects.delete(sequence);\n\t}\n\n\tget storedBytes(): number {\n\t\treturn this.stored;\n\t}\n\n\tget changed(): boolean {\n\t\treturn this.effects.size > 0;\n\t}\n\n\tasync finish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.finished = true;\n\t\ttry {\n\t\t\tawait this.pending;\n\t\t\tawait this.journal.close();\n\t\t\t// Its record is left `running`: if removing it fails, readers already take it as gone.\n\t\t\tif (!this.changed) {\n\t\t\t\tawait this.discard();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst record: RunRecord = { ...this.record, status, finishedAt: new Date().toISOString() };\n\t\t\tawait writeDurably(join(this.runDirectory, 'run.json'), JSON.stringify(record));\n\t\t} finally {\n\t\t\tawait this.release();\n\t\t}\n\t}\n\n\tprivate append(line: JournalLine): Promise<void> {\n\t\tconst write = this.pending.then(async () => {\n\t\t\tif (this.broken !== undefined) {\n\t\t\t\tthrow new Error(`The journal of run ${this.runId} stopped after a failed write`, {\n\t\t\t\t\tcause: this.broken,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.journal.appendFile(`${JSON.stringify(line)}\\n`);\n\t\t\t\tawait this.journal.sync();\n\t\t\t} catch (error) {\n\t\t\t\tthis.broken = error ?? new Error('Unknown write failure');\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t\t// The chain goes on, so each later append reports the broken journal to its own caller.\n\t\tthis.pending = write.catch(() => undefined);\n\t\treturn write;\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.finished) throw new Error(`Run ${this.runId} has already finished`);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fileRecoveryStore.js","sourceRoot":"","sources":["../../../src/recovery/infrastructure/fileRecoveryStore.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomBytes } from 'node:crypto';\nimport {\n\tlink,\n\tmkdir,\n\topen,\n\treaddir,\n\treadFile,\n\trealpath,\n\trename,\n\trm,\n\tstat,\n\ttruncate,\n\tunlink,\n} from 'node:fs/promises';\nimport type { FileHandle } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, isAbsolute, join } from 'node:path';\nimport { type FileChange, fileChanges, sameState } from '../domain/fileChanges.ts';\nimport {\n\thistoryStart,\n\ttype FileState,\n\ttype JournalEntry,\n\ttype Manifest,\n\ttype ObservationMeasure,\n\ttype MoveConflict,\n\ttype MoveOptions,\n\tNothingToMoveError,\n\ttype Revision,\n\ttype RecoveryStore,\n\ttype RunJournal,\n\ttype RunRecord,\n\ttype RunStatus,\n\tWorkspaceBusyError,\n\tWorkspaceMovedError,\n} from '../domain/recoveryStore.ts';\nimport { chainEntries, nextPruneStep } from '../domain/retention.ts';\nimport { HistoryExpiredError, redoTarget, route, UnknownRunError } from '../domain/runTree.ts';\nimport {\n\tcurrentState,\n\thasRealParents,\n\tremoveEmptyFolders,\n\tremoveFile,\n\tremoveTemporary,\n\ttemporaryPath,\n\twriteFileState,\n} from './workspaceFiles.ts';\n\nconst appName = 'mikode-harness';\n// The store holds source code the agent touched: only its owner may read it.\nconst privateDirectory = 0o700;\nconst privateFile = 0o600;\n\nconst firstJournal = 'journal.jsonl';\n\n// A run is roughly one prompt: enough to go back through a working session, not a project's life.\nconst defaultKeepRuns = 25;\n\nconst runIdPattern = /^\\d{8}T\\d{9}Z-[0-9a-f]{6}$/;\nconst hashPattern = /^[0-9a-f]{64}$/;\n\n/** Where an application keeps state that is neither configuration nor cache, per platform. */\nexport function defaultStateDirectory(\n\tenv: NodeJS.ProcessEnv = process.env,\n\tplatform: NodeJS.Platform = process.platform,\n\thome: string = homedir(),\n): string {\n\t// The XDG spec says to ignore a relative path, which here could land inside the repository.\n\tconst xdg = env.XDG_STATE_HOME;\n\tif (xdg && isAbsolute(xdg)) return join(xdg, appName);\n\tif (platform === 'darwin') return join(home, 'Library', 'Application Support', appName);\n\treturn join(home, '.local', 'state', appName);\n}\n\n/** Sorts by start time as text, so the latest run is the last one listed. */\nfunction newRunId(): string {\n\treturn `${new Date().toISOString().replace(/[-:.]/g, '')}-${randomBytes(3).toString('hex')}`;\n}\n\nfunction hashOf(content: Buffer): string {\n\treturn createHash('sha256').update(content).digest('hex');\n}\n\nfunction isNotFound(error: unknown): boolean {\n\treturn (error as NodeJS.ErrnoException).code === 'ENOENT';\n}\n\n/**\n * The runs and moves this process holds a workspace lock for and has not ended. A lock naming\n * this process and none of these was left by one whose release failed: it is as stale as a dead\n * process's, which a process that lives on would otherwise keep until it exits.\n */\nconst heldHere = new Set<string>();\n\n/** Whether the holder of a lock is still at work. */\nfunction isLiveHolder(holder: { runId: string; pid?: number }): boolean {\n\t// A holder that cannot be named cannot be shown to be gone.\n\tif (holder.pid === undefined) return true;\n\tif (holder.pid === process.pid) return heldHere.has(holder.runId);\n\treturn isAlive(holder.pid);\n}\n\n/** Whether a process still exists. One we may not signal exists too. */\nfunction isAlive(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0);\n\t\treturn true;\n\t} catch (error) {\n\t\treturn (error as NodeJS.ErrnoException).code === 'EPERM';\n\t}\n}\n\nasync function syncDirectory(path: string): Promise<void> {\n\tconst directory = await open(path, 'r');\n\ttry {\n\t\tawait directory.sync();\n\t} finally {\n\t\tawait directory.close();\n\t}\n}\n\n/**\n * Creates a private folder and any missing parents. A new folder only survives a crash once\n * its parent's entry for it is synced too, so each parent that gained one is.\n */\nasync function makeDirectory(path: string): Promise<void> {\n\tconst first = await mkdir(path, { recursive: true, mode: privateDirectory });\n\tif (first === undefined) return;\n\tfor (let created = path; ; created = dirname(created)) {\n\t\tawait syncDirectory(dirname(created));\n\t\tif (created === first) return;\n\t}\n}\n\n/**\n * Puts `content` at `path` all at once: a crash leaves either the old file or the new one, never\n * half of the new one. It returns only once the new file is on disk. With `exclusive`, it fails\n * with `EEXIST` instead of replacing a file already there.\n */\nasync function writeDurably(\n\tpath: string,\n\tcontent: string | Buffer,\n\t{ exclusive = false }: { exclusive?: boolean } = {},\n): Promise<void> {\n\tconst temporary = `${path}.${randomBytes(6).toString('hex')}.tmp`;\n\ttry {\n\t\tconst handle = await open(temporary, 'wx', privateFile);\n\t\ttry {\n\t\t\tawait handle.writeFile(content);\n\t\t\tawait handle.sync();\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\t// A link fails if the path is taken; a rename would replace it.\n\t\tawait (exclusive ? link : rename)(temporary, path);\n\t} finally {\n\t\tawait rm(temporary, { force: true });\n\t}\n\tawait syncDirectory(dirname(path));\n}\n\n/** A move not finished yet: the next move or run finishes it before anything else. */\ninterface PendingMove {\n\trevision: number;\n\tfrom?: string;\n\tto?: string;\n\treason?: string;\n\t/** Found by the steps already taken. */\n\tconflicts: MoveConflict[];\n\t/**\n\t * The temporary a file is being restored through, named before it is created, so finishing\n\t * the move removes this one and no file of the user's.\n\t */\n\ttemporary?: string;\n}\n\n/** `head.json`: the run the workspace is at, the moves made so far, and one in progress. */\ninterface Head {\n\trunId?: string;\n\trevision: number;\n\tpending?: PendingMove;\n}\n\ntype JournalLine =\n\t| ({ type: 'prepared'; sequence: number } & Omit<JournalEntry, 'sequence' | 'status'>)\n\t| { type: 'applied' | 'abandoned'; sequence: number }\n\t| { type: 'observing'; sequence: number; manifest: string; by: string }\n\t| { type: 'observed'; sequence: number; measure?: ObservationMeasure };\n\n/** An observation a run began and never finished: what its command changed is not recorded yet. */\ninterface OpenObservation {\n\tsequence: number;\n\tmanifest: string;\n\tby: string;\n}\n\n/**\n * Stores `content` under its hash, unless it is stored already, and returns the hash and whether\n * it was new. It returns only once the content is on disk.\n */\nasync function storeContent(\n\tcontentDirectory: string,\n\tcontent: Buffer,\n): Promise<{ hash: string; written: boolean }> {\n\tconst hash = hashOf(content);\n\tconst path = contentPath(contentDirectory, hash);\n\tconst stored = await stat(path).then(\n\t\t() => true,\n\t\t(error: unknown) => {\n\t\t\tif (isNotFound(error)) return false;\n\t\t\tthrow error;\n\t\t},\n\t);\n\tif (!stored) {\n\t\tawait makeDirectory(dirname(path));\n\t\tawait writeDurably(path, content);\n\t}\n\treturn { hash, written: !stored };\n}\n\n/**\n * The recovery store on disk, in a private directory per workspace under the platform's state\n * directory:\n *\n * ```text\n * <directory>/workspaces/<hash of the root>/\n * workspace.json the root it belongs to\n * lock the run writing now, if any\n * head.json the run the workspace is at, and a move in progress\n * revisions.jsonl every move of the workspace through its history\n * content/<ab>/<hash> file contents, named by their SHA-256\n * runs/<runId>/run.json the run's record\n * runs/<runId>/journal.jsonl its changes, one line per step, appended and synced\n * ```\n *\n * The lock only keeps a second run of this harness from writing at the same time. It does not\n * stop an editor or another program, and two processes taking over a dead run's lock in the\n * same instant could both believe they hold it.\n */\nexport class FileRecoveryStore implements RecoveryStore {\n\tprivate readonly root: string;\n\tprivate readonly directory: string;\n\tprivate readonly keepRuns: number;\n\n\tprivate constructor(root: string, directory: string, keepRuns: number) {\n\t\tthis.root = root;\n\t\tthis.directory = directory;\n\t\tthis.keepRuns = keepRuns;\n\t}\n\n\tstatic async open({\n\t\troot,\n\t\tdirectory = defaultStateDirectory(),\n\t\tkeepRuns = defaultKeepRuns,\n\t}: {\n\t\troot: string;\n\t\t/** Defaults to the platform's state directory. */\n\t\tdirectory?: string;\n\t\t/**\n\t\t * The most runs kept per workspace, the one being recorded included. Defaults to 25. At\n\t\t * least 3: the run the workspace is at is never removed, and the last run of its line has\n\t\t * no next run to be chained into, so pruning can leave two runs besides the new one.\n\t\t */\n\t\tkeepRuns?: number;\n\t}): Promise<FileRecoveryStore> {\n\t\tif (!Number.isInteger(keepRuns) || keepRuns < 3) {\n\t\t\tthrow new RangeError(`keepRuns must be an integer of at least 3; got ${String(keepRuns)}`);\n\t\t}\n\t\t// Two spellings of one folder, such as a symlinked path, are one workspace.\n\t\tconst realRoot = await realpath(root);\n\t\tconst workspace = join(\n\t\t\tdirectory,\n\t\t\t'workspaces',\n\t\t\tcreateHash('sha256').update(realRoot).digest('hex').slice(0, 16),\n\t\t);\n\t\tawait makeDirectory(join(workspace, 'runs'));\n\t\tawait makeDirectory(join(workspace, 'content'));\n\t\tawait writeDurably(join(workspace, 'workspace.json'), JSON.stringify({ root: realRoot }));\n\n\t\treturn new FileRecoveryStore(realRoot, workspace, keepRuns);\n\t}\n\n\tasync startRun(): Promise<RunJournal> {\n\t\tconst runId = newRunId();\n\t\ttry {\n\t\t\t// Inside, because taking the lock can fail after publishing it. Unlocking removes only a\n\t\t\t// lock naming this run, never another run's.\n\t\t\tawait this.lock(runId);\n\t\t\tawait this.settleInterrupted(runId);\n\t\t\t// A run starts where the user last sent the workspace.\n\t\t\tawait this.finishPendingMove();\n\t\t\t// Before the new run exists, so it is never pruned, and after the move, so no run on its\n\t\t\t// route is.\n\t\t\tawait this.prune();\n\t\t\tconst head = await this.readHead();\n\t\t\tconst parentRunId = head.runId;\n\t\t\tconst runDirectory = join(this.directory, 'runs', runId);\n\t\t\tawait makeDirectory(runDirectory);\n\t\t\tconst record: RunRecord = {\n\t\t\t\trunId,\n\t\t\t\troot: this.root,\n\t\t\t\t...(parentRunId ? { parentRunId } : {}),\n\t\t\t\tstartedAt: new Date().toISOString(),\n\t\t\t\tstatus: 'running',\n\t\t\t\tpid: process.pid,\n\t\t\t};\n\t\t\tawait writeDurably(join(runDirectory, 'run.json'), JSON.stringify(record));\n\t\t\t// After the record, so the head never names a run that does not exist.\n\t\t\tawait this.writeHead({ runId, revision: head.revision });\n\t\t\tconst journal = await open(join(runDirectory, firstJournal), 'a', privateFile);\n\t\t\tawait syncDirectory(runDirectory);\n\n\t\t\treturn new FileRunJournal({\n\t\t\t\trecord,\n\t\t\t\trunDirectory,\n\t\t\t\tcontentDirectory: join(this.directory, 'content'),\n\t\t\t\tjournal,\n\t\t\t\tdiscard: () => this.discardRun(record),\n\t\t\t\trelease: () => this.unlock(runId),\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tawait this.unlock(runId);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync listRuns(): Promise<{ head?: string; runs: RunRecord[] }> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(id => runIdPattern.test(id));\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\tconst runs: RunRecord[] = [];\n\t\tfor (const runId of ids.sort()) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\t// A crash between creating a run's folder and writing its record leaves the folder\n\t\t\t\t// empty: that run never changed anything.\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record) runs.push(withLiveStatus(record, holder));\n\t\t}\n\t\t// A run retention removed or chained into a later one, whose folder a crash left behind, is\n\t\t// not in the history.\n\t\tconst gone = new Set([\n\t\t\t...runs.flatMap(run => run.absorbed ?? []),\n\t\t\t...(await this.listPruned()),\n\t\t]);\n\t\t// A dead run that changed nothing is not in the history either, though its removal did not\n\t\t// finish. No run follows it: the next run or move removes it before starting.\n\t\tfor (const run of runs) {\n\t\t\tif (run.status !== 'interrupted') continue;\n\t\t\t// A journal it cannot read leaves the run listed: whether it changed anything is unknown.\n\t\t\tconst entries = await this.readEntries(run.runId, run.journal).catch(() => undefined);\n\t\t\tif (entries && changedNothing(entries)) gone.add(run.runId);\n\t\t}\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet { runId: head } = await this.readHead();\n\t\twhile (head !== undefined && gone.has(head)) head = parents.get(head);\n\n\t\treturn { ...(head ? { head } : {}), runs: runs.filter(run => !gone.has(run.runId)) };\n\t}\n\n\tasync readRun(runId: string): Promise<{ record: RunRecord; entries: JournalEntry[] }> {\n\t\t// An id from outside is checked before it names a folder.\n\t\tif (!runIdPattern.test(runId)) throw new UnknownRunError(runId);\n\t\t// The lock first: a run that finishes between the two reads then shows as finished, not as\n\t\t// a `running` record nobody holds.\n\t\tconst holder = await readLock(join(this.directory, 'lock'));\n\t\t// Before the record: a crash can leave the folder of a run retention already took.\n\t\tawait this.assertNotAbsorbed(runId);\n\t\tconst record = await this.readRecord(runId).catch(async (error: unknown) => {\n\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t// Retention may have taken it since the check above.\n\t\t\tawait this.assertNotAbsorbed(runId);\n\t\t\tthrow new UnknownRunError(runId);\n\t\t});\n\t\treturn {\n\t\t\trecord: withLiveStatus(record, holder),\n\t\t\tentries: await this.readEntries(runId, record.journal),\n\t\t};\n\t}\n\n\tprivate async readRecord(runId: string): Promise<RunRecord> {\n\t\treturn JSON.parse(\n\t\t\tawait readFile(join(this.runDirectory(runId), 'run.json'), 'utf8'),\n\t\t) as RunRecord;\n\t}\n\n\tprivate runDirectory(runId: string): string {\n\t\t// The id names a folder, so it must never be a path of its own.\n\t\tif (!runIdPattern.test(runId)) throw new Error(`Not a run id: ${runId}`);\n\t\treturn join(this.directory, 'runs', runId);\n\t}\n\n\tprivate async readHead(): Promise<Head> {\n\t\ttry {\n\t\t\tconst head = JSON.parse(\n\t\t\t\tawait readFile(join(this.directory, 'head.json'), 'utf8'),\n\t\t\t) as Partial<Head>;\n\t\t\treturn { ...head, revision: head.revision ?? 0 };\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return { revision: 0 };\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async writeHead(head: Head): Promise<void> {\n\t\tawait writeDurably(join(this.directory, 'head.json'), JSON.stringify(head));\n\t}\n\n\tgoTo(target: string, options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(() => (target === historyStart ? undefined : target), options);\n\t}\n\n\tundo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head }) => {\n\t\t\tif (head === undefined) throw new NothingToMoveError('undo');\n\t\t\treturn runs.find(run => run.runId === head)?.parentRunId;\n\t\t}, options);\n\t}\n\n\tredo(options: MoveOptions = {}): Promise<Revision> {\n\t\treturn this.move(({ runs, head, revisions }) => {\n\t\t\tconst target = redoTarget(runs, revisions, head);\n\t\t\tif (target === undefined) throw new NothingToMoveError('redo');\n\t\t\treturn target;\n\t\t}, options);\n\t}\n\n\tasync listRevisions(): Promise<Revision[]> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.directory, 'revisions.jsonl'), 'utf8');\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\t\treturn lines.flatMap((line, index) => {\n\t\t\tif (line === '') return [];\n\t\t\ttry {\n\t\t\t\treturn [JSON.parse(line) as Revision];\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// move is still pending, and finishing it records it again.\n\t\t\t\tif (index === lines.length - 1) return [];\n\t\t\t\tthrow new Error(`The history of this workspace is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\n\t/** Holds the workspace like a run does, then moves it to the run `resolve` picks. */\n\tprivate async move(\n\t\tresolve: (history: {\n\t\t\truns: RunRecord[];\n\t\t\thead: string | undefined;\n\t\t\trevisions: Revision[];\n\t\t}) => string | undefined,\n\t\t{ reason, from }: MoveOptions,\n\t): Promise<Revision> {\n\t\tconst moveId = `move-${newRunId()}`;\n\t\ttry {\n\t\t\tawait this.lock(moveId);\n\t\t\tawait this.settleInterrupted(moveId);\n\t\t\tawait this.finishPendingMove();\n\t\t\tconst head = await this.readHead();\n\t\t\t// Only now, under the lock and once nothing is left unsettled, is the head the one the\n\t\t\t// move would start from.\n\t\t\tconst at = head.runId ?? historyStart;\n\t\t\tif (from !== undefined && from !== at) throw new WorkspaceMovedError(from, at);\n\t\t\tconst { runs } = await this.listRuns();\n\t\t\tconst to = resolve({ runs, head: head.runId, revisions: await this.listRevisions() });\n\t\t\tif (to !== undefined && !runs.some(run => run.runId === to)) {\n\t\t\t\tawait this.assertNotAbsorbed(to);\n\t\t\t}\n\n\t\t\treturn await this.takeSteps(head, runs, {\n\t\t\t\trevision: head.revision + 1,\n\t\t\t\t...(head.runId ? { from: head.runId } : {}),\n\t\t\t\t...(to ? { to } : {}),\n\t\t\t\t...(reason === undefined ? {} : { reason }),\n\t\t\t\tconflicts: [],\n\t\t\t});\n\t\t} finally {\n\t\t\tawait this.unlock(moveId);\n\t\t}\n\t}\n\n\t/** Finishes a move whose process stopped halfway, from the run its last step reached. */\n\tprivate async finishPendingMove(): Promise<void> {\n\t\tconst head = await this.readHead();\n\t\tconst { pending } = head;\n\t\tif (!pending) return;\n\t\t// It was recorded, and only clearing it from the head was missing.\n\t\tif ((await this.listRevisions()).some(revision => revision.revision === pending.revision)) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\t\trevision: pending.revision,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tawait this.takeSteps(head, (await this.listRuns()).runs, pending);\n\t}\n\n\t/**\n\t * Undoes, then redoes, one run at a time from where the head is to `pending.to`. After each\n\t * step the head names the run reached, with the move still pending, so a crash loses at\n\t * most the step in progress, and that step is safe to take again.\n\t */\n\tprivate async takeSteps(head: Head, runs: RunRecord[], pending: PendingMove): Promise<Revision> {\n\t\tconst { undo, redo } = route(runs, head.runId, pending.to);\n\t\tconst parents = new Map(runs.map(run => [run.runId, run.parentRunId]));\n\t\tlet reached = head.runId;\n\t\tconst save = () =>\n\t\t\tthis.writeHead({ ...(reached ? { runId: reached } : {}), revision: head.revision, pending });\n\n\t\t// What a write the crash interrupted left beside its file.\n\t\tif (pending.temporary) {\n\t\t\tawait removeTemporary(pending.temporary);\n\t\t\tdelete pending.temporary;\n\t\t}\n\t\tawait save();\n\t\tconst announce = async (temporary: string | undefined) => {\n\t\t\tif (temporary === undefined) delete pending.temporary;\n\t\t\telse pending.temporary = temporary;\n\t\t\tawait save();\n\t\t};\n\t\tfor (const runId of undo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'undo', announce)));\n\t\t\treached = parents.get(runId);\n\t\t\tawait save();\n\t\t}\n\t\tfor (const runId of redo) {\n\t\t\tpending.conflicts.push(...(await this.step(runId, 'redo', announce)));\n\t\t\treached = runId;\n\t\t\tawait save();\n\t\t}\n\n\t\t// Every write that started has finished, so no temporary is left to name.\n\t\tdelete pending.temporary;\n\t\tconst { conflicts, ...rest } = pending;\n\t\tconst revision: Revision = {\n\t\t\t...rest,\n\t\t\tat: new Date().toISOString(),\n\t\t\tcomplete: conflicts.length === 0,\n\t\t\tconflicts,\n\t\t};\n\t\tawait this.appendRevision(revision);\n\t\tawait this.writeHead({\n\t\t\t...(pending.to ? { runId: pending.to } : {}),\n\t\t\trevision: pending.revision,\n\t\t});\n\t\treturn revision;\n\t}\n\n\t/** Takes one run's changes back to its parent, or forward again, file by file. */\n\tprivate async step(\n\t\trunId: string,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<MoveConflict[]> {\n\t\tconst { entries } = await this.readRun(runId);\n\t\tconst changes = fileChanges(entries, true);\n\t\tconst conflicts: MoveConflict[] = [];\n\t\t// Undone newest first, so a folder the run created is empty by the time its file goes.\n\t\tfor (const change of direction === 'undo' ? changes.reverse() : changes) {\n\t\t\tif (!(await this.moveFile(change, direction, announce))) {\n\t\t\t\tconflicts.push({ path: change.path, runId });\n\t\t\t}\n\t\t}\n\t\treturn conflicts;\n\t}\n\n\t/**\n\t * Writes the state the step leads to, only if the file holds the state it leaves. A file\n\t * already there is left alone, so taking a step again is safe. Returns whether the file\n\t * ends where the step leads.\n\t */\n\tprivate async moveFile(\n\t\tchange: FileChange,\n\t\tdirection: 'undo' | 'redo',\n\t\tannounce: (temporary: string | undefined) => Promise<void>,\n\t): Promise<boolean> {\n\t\tconst [source, destination] =\n\t\t\tdirection === 'undo' ? [change.after, change.before] : [change.before, change.after];\n\t\t// First, so a file reached through a folder that became a link is never taken for the\n\t\t// destination, and nothing is read or removed through it.\n\t\tif (!(await hasRealParents(change.path))) return false;\n\t\tconst current = await currentState(change.path);\n\n\t\tif (current && sameState(current, destination)) {\n\t\t\tif (direction === 'undo' && !destination.exists) {\n\t\t\t\tawait removeEmptyFolders(change.createdFolders);\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t\tif (!current || !sameState(current, source)) return false;\n\t\t// Someone wrote to the file between two of the run's changes, and going back to before\n\t\t// the first would discard that.\n\t\tif (direction === 'undo' && !change.continuous) return false;\n\n\t\tif (destination.exists) {\n\t\t\tconst temporary = temporaryPath(change.path);\n\t\t\tawait announce(temporary);\n\t\t\tawait writeFileState(\n\t\t\t\tchange.path,\n\t\t\t\tawait this.readContent(destination.hash),\n\t\t\t\tdestination.mode,\n\t\t\t\ttemporary,\n\t\t\t);\n\t\t\tawait announce(undefined);\n\t\t} else {\n\t\t\tawait removeFile(change.path);\n\t\t\tif (direction === 'undo') await removeEmptyFolders(change.createdFolders);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/** Throws `HistoryExpiredError` if retention removed `runId` or chained it into a later run. */\n\tprivate async assertNotAbsorbed(runId: string): Promise<void> {\n\t\tconst { runs } = await this.listRuns();\n\t\tconst keptIn = runs.find(run => run.absorbed?.includes(runId));\n\t\tif (keptIn) throw new HistoryExpiredError(runId, keptIn.runId);\n\t\tif ((await this.listPruned()).includes(runId)) throw new HistoryExpiredError(runId);\n\t}\n\n\tprivate async listPruned(): Promise<string[]> {\n\t\ttry {\n\t\t\tconst text = await readFile(join(this.directory, 'pruned.jsonl'), 'utf8');\n\t\t\treturn text.split('\\n').flatMap(line => {\n\t\t\t\ttry {\n\t\t\t\t\treturn [JSON.parse(line) as string];\n\t\t\t\t} catch {\n\t\t\t\t\t// Half a line a crash left, whose removal never happened.\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isNotFound(error)) return [];\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t/**\n\t * Brings the history down to `keepRuns - 1`, so the run about to start makes `keepRuns`, then\n\t * frees the contents no run kept refers to.\n\t */\n\tprivate async prune(): Promise<void> {\n\t\tawait this.finishChains();\n\t\tconst revisions = await this.listRevisions();\n\t\tfor (;;) {\n\t\t\tconst { head, runs } = await this.listRuns();\n\t\t\tconst step = nextPruneStep(runs, revisions, head, this.keepRuns - 1);\n\t\t\tif (!step) break;\n\t\t\tif (step.kind === 'remove') await this.removeRun(step.runId);\n\t\t\telse await this.chain(step.runId, step.into);\n\t\t}\n\t\tawait this.collectContent();\n\t}\n\n\t/**\n\t * Chains the changes of `older` into `newer`, its child: `newer` then hangs from `older`'s\n\t * parent and goes back to where `older` started. The new record is the commit point. Before\n\t * it, the history is as it was; after it, `finishChains` removes what is left of `older`.\n\t */\n\tprivate async chain(older: string, newer: string): Promise<void> {\n\t\tconst olderRecord = await this.readRecord(older);\n\t\tconst newerRecord = await this.readRecord(newer);\n\t\tconst entries = chainEntries(\n\t\t\tawait this.readEntries(older, olderRecord.journal),\n\t\t\tawait this.readEntries(newer, newerRecord.journal),\n\t\t);\n\t\tconst journal = `journal-${randomBytes(4).toString('hex')}.jsonl`;\n\t\tconst lines = entries.flatMap(({ status, sequence, ...change }): JournalLine[] => [\n\t\t\t{ type: 'prepared', sequence, ...change },\n\t\t\t...(status === 'prepared' ? [] : [{ type: status, sequence } as const]),\n\t\t]);\n\t\tawait writeDurably(\n\t\t\tjoin(this.runDirectory(newer), journal),\n\t\t\tlines.map(line => `${JSON.stringify(line)}\\n`).join(''),\n\t\t);\n\n\t\tconst record: RunRecord = {\n\t\t\t...newerRecord,\n\t\t\tabsorbed: [...(olderRecord.absorbed ?? []), older, ...(newerRecord.absorbed ?? [])],\n\t\t\tjournal,\n\t\t};\n\t\t// It now hangs where `older` did: from its parent, or from the start.\n\t\tif (olderRecord.parentRunId) record.parentRunId = olderRecord.parentRunId;\n\t\telse delete record.parentRunId;\n\t\tawait writeDurably(join(this.runDirectory(newer), 'run.json'), JSON.stringify(record));\n\t\tawait this.finishChains();\n\t}\n\n\t/**\n\t * Removes what a chain or a removal a crash interrupted left behind: the folders of runs\n\t * pruned or absorbed by a kept run, and journals a run no longer reads.\n\t */\n\tprivate async finishChains(): Promise<void> {\n\t\tfor (const runId of await this.listPruned()) {\n\t\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t\t}\n\t\tconst { runs } = await this.listRuns();\n\t\tfor (const run of runs) {\n\t\t\tfor (const absorbed of run.absorbed ?? []) {\n\t\t\t\tawait rm(this.runDirectory(absorbed), { recursive: true, force: true });\n\t\t\t}\n\t\t\tconst current = run.journal ?? firstJournal;\n\t\t\tfor (const name of await readdir(this.runDirectory(run.runId))) {\n\t\t\t\tif (name.startsWith('journal') && name.endsWith('.jsonl') && name !== current) {\n\t\t\t\t\tawait rm(join(this.runDirectory(run.runId), name), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes a run whole, recording its id first so a move to it reports an expired history.\n\t * Its record goes next, so a crash halfway leaves no run behind.\n\t */\n\tprivate async removeRun(runId: string): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'pruned.jsonl'), [runId]);\n\t\t// The log may be new: its entry in the folder must last before the run it names goes.\n\t\tawait syncDirectory(this.directory);\n\t\tawait rm(join(this.runDirectory(runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(runId));\n\t\tawait rm(this.runDirectory(runId), { recursive: true, force: true });\n\t}\n\n\t/**\n\t * Takes a run that changed nothing out of the history, under the lock: the workspace goes back\n\t * to its parent first, so the head never names a run that is gone. Until the run is removed,\n\t * `listRuns` already hides it, and the next run or move finishes removing it. The contents it\n\t * saved are freed by the next prune.\n\t */\n\tprivate async discardRun(record: RunRecord): Promise<void> {\n\t\tconst { runId: headRunId, ...head } = await this.readHead();\n\t\tif (headRunId === record.runId) {\n\t\t\tawait this.writeHead({\n\t\t\t\t...head,\n\t\t\t\t...(record.parentRunId ? { runId: record.parentRunId } : {}),\n\t\t\t});\n\t\t}\n\t\tawait rm(join(this.runDirectory(record.runId), 'run.json'), { force: true });\n\t\tawait syncDirectory(this.runDirectory(record.runId));\n\t\tawait rm(this.runDirectory(record.runId), { recursive: true, force: true });\n\t}\n\n\t/** Removes the stored contents no kept run refers to. */\n\tprivate async collectContent(): Promise<void> {\n\t\tconst referenced = new Set<string>();\n\t\tfor (const run of (await this.listRuns()).runs) {\n\t\t\tfor (const entry of await this.readEntries(run.runId, run.journal)) {\n\t\t\t\tfor (const state of [entry.before, entry.after]) {\n\t\t\t\t\tif (state.exists) referenced.add(state.hash);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconst contentDirectory = join(this.directory, 'content');\n\t\tfor (const prefix of await readdir(contentDirectory)) {\n\t\t\tfor (const hash of await readdir(join(contentDirectory, prefix))) {\n\t\t\t\tif (hashPattern.test(hash) && !referenced.has(hash)) {\n\t\t\t\t\tawait rm(join(contentDirectory, prefix, hash), { force: true });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async appendRevision(revision: Revision): Promise<void> {\n\t\tawait appendWhole(join(this.directory, 'revisions.jsonl'), [revision]);\n\t\tawait syncDirectory(this.directory);\n\t}\n\n\t/**\n\t * Marks every other run still recorded as `running` as `interrupted`: this run holds the lock,\n\t * so their processes are gone. Each change one left `prepared` is settled from what its file\n\t * holds now: its `after` means it was made, its `before` that it was not. A file that holds\n\t * neither stays `prepared`, because nothing tells whether the change reached it.\n\t */\n\tprivate async settleInterrupted(ownRunId: string): Promise<void> {\n\t\tconst ids = (await readdir(join(this.directory, 'runs'))).filter(\n\t\t\tid => runIdPattern.test(id) && id !== ownRunId,\n\t\t);\n\t\tfor (const runId of ids) {\n\t\t\tconst record = await this.readRecord(runId).catch((error: unknown) => {\n\t\t\t\tif (isNotFound(error)) return undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\t\tif (record?.status !== 'running') continue;\n\n\t\t\tconst journal = await this.readJournal(runId, record.journal);\n\t\t\tconst settled: JournalLine[] = [];\n\t\t\tfor (const entry of journal.entries) {\n\t\t\t\tif (entry.status !== 'prepared' || !isAbsolute(entry.path)) continue;\n\t\t\t\tconst state = await currentState(entry.path);\n\t\t\t\tif (state && sameState(state, entry.after)) {\n\t\t\t\t\tsettled.push({ type: 'applied', sequence: entry.sequence });\n\t\t\t\t} else if (state && sameState(state, entry.before)) {\n\t\t\t\t\tsettled.push({ type: 'abandoned', sequence: entry.sequence });\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet sequence = journal.lastSequence;\n\t\t\tfor (const observation of journal.observations) {\n\t\t\t\tconst lines = await this.settleObservation(observation, journal.entries, sequence);\n\t\t\t\tsequence += lines.length;\n\t\t\t\tsettled.push(...lines);\n\t\t\t}\n\t\t\tawait appendWhole(join(this.runDirectory(runId), record.journal ?? firstJournal), settled);\n\t\t\tif (changedNothing(await this.readEntries(runId, record.journal))) {\n\t\t\t\tawait this.discardRun(record);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// Last, so a crash before it leaves a run that is settled again, and settling is idempotent.\n\t\t\tawait writeDurably(\n\t\t\t\tjoin(this.runDirectory(runId), 'run.json'),\n\t\t\t\tJSON.stringify({ ...record, status: 'interrupted' } satisfies RunRecord),\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * The lines that record what a command an interrupted run was observing changed: every file of\n\t * its manifest that holds something else now, as changed by that command, and then the end of\n\t * the observation. A file recorded after the observation began is left alone: the run\n\t * recorded it itself. One that is now a folder, a link or too large to record is left out.\n\t */\n\tprivate async settleObservation(\n\t\tobservation: OpenObservation,\n\t\tentries: JournalEntry[],\n\t\tlastSequence: number,\n\t): Promise<JournalLine[]> {\n\t\tconst stored = await this.readContent(observation.manifest).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\t// Its manifest was never stored whole: the command it was saved for never started.\n\t\tif (!stored) return [{ type: 'observed', sequence: observation.sequence }];\n\t\tconst manifest = JSON.parse(stored.toString('utf8')) as Manifest;\n\t\tconst recorded = new Set(\n\t\t\tentries.filter(entry => entry.sequence > observation.sequence).map(entry => entry.path),\n\t\t);\n\t\tconst lines: JournalLine[] = [];\n\t\tlet sequence = lastSequence;\n\t\tfor (const [path, before] of Object.entries(manifest.files)) {\n\t\t\tif (!isAbsolute(path) || recorded.has(path)) continue;\n\t\t\tconst after = await this.saveState(path);\n\t\t\tif (!after || sameState(after, before)) continue;\n\t\t\tsequence++;\n\t\t\tlines.push(\n\t\t\t\t{ type: 'prepared', sequence, path, before, after, observedBy: observation.by },\n\t\t\t\t{ type: 'applied', sequence },\n\t\t\t);\n\t\t}\n\t\tlines.push({ type: 'observed', sequence: observation.sequence });\n\t\treturn lines;\n\t}\n\n\t/** What `path` holds now, with its content stored, or `undefined` for what no entry records. */\n\tprivate async saveState(path: string): Promise<FileState | undefined> {\n\t\tconst state = await currentState(path);\n\t\tif (!state?.exists) return state;\n\t\tconst content = await readFile(path).catch((error: unknown) => {\n\t\t\tif (isNotFound(error)) return undefined;\n\t\t\tthrow error;\n\t\t});\n\t\tif (!content) return { exists: false };\n\t\tconst { hash } = await storeContent(join(this.directory, 'content'), content);\n\t\t// Read again: the file may have changed between hashing it and storing it.\n\t\treturn hash === state.hash ? state : this.saveState(path);\n\t}\n\n\tprivate async readEntries(runId: string, journal = firstJournal): Promise<JournalEntry[]> {\n\t\treturn (await this.readJournal(runId, journal)).entries;\n\t}\n\n\t/**\n\t * A run's changes, the observations it began and never finished, and the highest sequence\n\t * number its journal uses, which the next line it gets must exceed.\n\t */\n\tprivate async readJournal(\n\t\trunId: string,\n\t\tjournal = firstJournal,\n\t): Promise<{ entries: JournalEntry[]; observations: OpenObservation[]; lastSequence: number }> {\n\t\tlet text: string;\n\t\ttry {\n\t\t\ttext = await readFile(join(this.runDirectory(runId), journal), 'utf8');\n\t\t} catch (error) {\n\t\t\t// A run that stopped before opening its journal never changed anything.\n\t\t\tif (isNotFound(error)) return { entries: [], observations: [], lastSequence: 0 };\n\t\t\tthrow error;\n\t\t}\n\t\tconst lines = text.split('\\n');\n\n\t\tconst entries = new Map<number, JournalEntry>();\n\t\tconst observations = new Map<number, OpenObservation>();\n\t\tlet lastSequence = 0;\n\t\tlines.forEach((text, index) => {\n\t\t\tif (text === '') return;\n\t\t\tlet line: JournalLine;\n\t\t\ttry {\n\t\t\t\tline = JSON.parse(text) as JournalLine;\n\t\t\t} catch (error) {\n\t\t\t\t// A crash in the middle of an append leaves half a line, always the last one. Its\n\t\t\t\t// step never returned, so no change was made after it.\n\t\t\t\tif (index === lines.length - 1) return;\n\t\t\t\tthrow new Error(`The journal of run ${runId} is corrupt at line ${String(index + 1)}`, {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\t\t\tlastSequence = Math.max(lastSequence, line.sequence);\n\t\t\tif (line.type === 'prepared') {\n\t\t\t\tconst { sequence, path, before, after, createdFolders, observedBy } = line;\n\t\t\t\tentries.set(sequence, {\n\t\t\t\t\tsequence,\n\t\t\t\t\tpath,\n\t\t\t\t\tbefore,\n\t\t\t\t\tafter,\n\t\t\t\t\t...(createdFolders ? { createdFolders } : {}),\n\t\t\t\t\t...(observedBy === undefined ? {} : { observedBy }),\n\t\t\t\t\tstatus: 'prepared',\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observing') {\n\t\t\t\tconst { sequence, manifest, by } = line;\n\t\t\t\tobservations.set(sequence, { sequence, manifest, by });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (line.type === 'observed') {\n\t\t\t\tobservations.delete(line.sequence);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst entry = entries.get(line.sequence);\n\t\t\tif (entry) entry.status = line.type;\n\t\t});\n\n\t\treturn {\n\t\t\tentries: [...entries.values()],\n\t\t\tobservations: [...observations.values()],\n\t\t\tlastSequence,\n\t\t};\n\t}\n\n\tasync readContent(hash: string): Promise<Buffer> {\n\t\tif (!hashPattern.test(hash)) throw new Error(`Not a content hash: ${hash}`);\n\t\treturn readFile(contentPath(join(this.directory, 'content'), hash));\n\t}\n\n\tprivate async lock(runId: string): Promise<void> {\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Twice at most: once as it is, and once more after clearing a dead run's lock.\n\t\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\t\ttry {\n\t\t\t\t// Written whole before it appears, so a lock that exists always names its holder.\n\t\t\t\tawait writeDurably(path, JSON.stringify({ runId, pid: process.pid }), { exclusive: true });\n\t\t\t\theldHere.add(runId);\n\t\t\t\treturn;\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n\t\t\t}\n\n\t\t\tconst holder = await readLock(path);\n\t\t\t// Released meanwhile: try again.\n\t\t\tif (!holder) continue;\n\t\t\tif (isLiveHolder(holder)) throw new WorkspaceBusyError(holder.runId);\n\t\t\t// Its process died, or its run ended, without releasing it. Read again just before\n\t\t\t// removing, so a lock another run has just taken is left alone.\n\t\t\tconst again = await readLock(path);\n\t\t\tif (again !== undefined && again.pid === holder.pid && again.runId === holder.runId) {\n\t\t\t\tawait unlink(path).catch((error: unknown) => {\n\t\t\t\t\tif (!isNotFound(error)) throw error;\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthrow new WorkspaceBusyError((await readLock(path))?.runId ?? 'unknown');\n\t}\n\n\tprivate async unlock(runId: string): Promise<void> {\n\t\t// First: the run has ended even if removing its lock fails, so that lock is stale.\n\t\theldHere.delete(runId);\n\t\tconst path = join(this.directory, 'lock');\n\t\t// Only its own lock: one cleared as stale and taken by another run is not this run's.\n\t\tif ((await readLock(path))?.runId === runId) await unlink(path);\n\t}\n}\n\n/** No change it recorded may have reached a file: it recorded none, or abandoned each one. */\nfunction changedNothing(entries: JournalEntry[]): boolean {\n\treturn entries.every(entry => entry.status === 'abandoned');\n}\n\n/**\n * A run recorded as `running` only runs while it holds the lock, its process lives, and, in this\n * process, it has not ended. Any other is reported as `interrupted`, before the next run settles\n * it.\n */\nfunction withLiveStatus(\n\trecord: RunRecord,\n\tholder: { runId: string; pid?: number } | undefined,\n): RunRecord {\n\tif (record.status !== 'running') return record;\n\tconst live = holder?.runId === record.runId && holder.pid !== undefined && isLiveHolder(holder);\n\treturn live ? record : { ...record, status: 'interrupted' };\n}\n\n/**\n * Appends `lines`, as JSON, to a file of one line each, created private if missing. A crash may\n * have left its last line without a newline. A whole line, which the readers already count, is\n * kept and ended. Half a line would join the first new line, so it is cut off: whatever was\n * writing it never returned.\n */\nasync function appendWhole(path: string, lines: unknown[]): Promise<void> {\n\tif (lines.length === 0) return;\n\tlet text = '';\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (!isNotFound(error)) throw error;\n\t}\n\tconst last = text.slice(text.lastIndexOf('\\n') + 1);\n\tlet separator = '';\n\tif (last !== '') {\n\t\tif (isWholeLine(last)) separator = '\\n';\n\t\telse await truncate(path, Buffer.byteLength(text) - Buffer.byteLength(last));\n\t}\n\tconst journal = await open(path, 'a', privateFile);\n\ttry {\n\t\tawait journal.appendFile(separator + lines.map(line => `${JSON.stringify(line)}\\n`).join(''));\n\t\tawait journal.sync();\n\t} finally {\n\t\tawait journal.close();\n\t}\n}\n\nfunction isWholeLine(text: string): boolean {\n\ttry {\n\t\tJSON.parse(text);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Who holds the lock, or `undefined` when nobody does. A lock this store did not write whole\n * has no `pid`, so it is never taken for a dead run's.\n */\nasync function readLock(path: string): Promise<{ runId: string; pid?: number } | undefined> {\n\tlet text: string;\n\ttry {\n\t\ttext = await readFile(path, 'utf8');\n\t} catch (error) {\n\t\tif (isNotFound(error)) return undefined;\n\t\tthrow error;\n\t}\n\ttry {\n\t\tconst { runId, pid } = JSON.parse(text) as { runId?: unknown; pid?: unknown };\n\t\tif (typeof runId === 'string' && Number.isInteger(pid)) return { runId, pid: pid as number };\n\t} catch {\n\t\t// Not JSON: named below as unknown.\n\t}\n\treturn { runId: 'unknown' };\n}\n\nfunction contentPath(contentDirectory: string, hash: string): string {\n\t// Two levels, so no folder holds every file a workspace ever stored.\n\treturn join(contentDirectory, hash.slice(0, 2), hash);\n}\n\nclass FileRunJournal implements RunJournal {\n\treadonly runId: string;\n\tprivate readonly record: RunRecord;\n\tprivate readonly runDirectory: string;\n\tprivate readonly contentDirectory: string;\n\tprivate readonly journal: FileHandle;\n\tprivate readonly discard: () => Promise<void>;\n\tprivate readonly release: () => Promise<void>;\n\tprivate sequence = 0;\n\tprivate stored = 0;\n\t// For the content state: what each change will leave, what each file held before the run first\n\t// changed it, and what it holds since its last applied change.\n\tprivate readonly pendingStates = new Map<number, { path: string; after: FileState }>();\n\tprivate readonly firstStates = new Map<string, FileState>();\n\tprivate readonly currentStates = new Map<string, FileState>();\n\tprivate readonly appliedInOrder: string[] = [];\n\tprivate state: { applied: number; hash: string } | undefined;\n\t// The changes recorded as prepared and not abandoned: those that may have reached a file. One\n\t// whose `prepared` line failed is not here, since nothing writes a file before that line.\n\tprivate readonly effects = new Set<number>();\n\t// Appends run one after another, so the lines never interleave.\n\tprivate pending: Promise<unknown> = Promise.resolve();\n\tprivate finished = false;\n\t// Set when an append fails: it may have left part of a line, and anything after it would be\n\t// joined to that part and unreadable.\n\tprivate broken: unknown;\n\n\tconstructor({\n\t\trecord,\n\t\trunDirectory,\n\t\tcontentDirectory,\n\t\tjournal,\n\t\tdiscard,\n\t\trelease,\n\t}: {\n\t\trecord: RunRecord;\n\t\trunDirectory: string;\n\t\tcontentDirectory: string;\n\t\tjournal: FileHandle;\n\t\tdiscard: () => Promise<void>;\n\t\trelease: () => Promise<void>;\n\t}) {\n\t\tthis.runId = record.runId;\n\t\tthis.record = record;\n\t\tthis.runDirectory = runDirectory;\n\t\tthis.contentDirectory = contentDirectory;\n\t\tthis.journal = journal;\n\t\tthis.discard = discard;\n\t\tthis.release = release;\n\t}\n\n\tasync saveContent(content: Buffer): Promise<string> {\n\t\tthis.assertOpen();\n\t\tconst { hash, written } = await storeContent(this.contentDirectory, content);\n\t\tif (written) this.stored += content.length;\n\t\treturn hash;\n\t}\n\n\tasync prepare(change: Omit<JournalEntry, 'sequence' | 'status'>): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'prepared', sequence, ...change });\n\t\tthis.effects.add(sequence);\n\t\tthis.pendingStates.set(sequence, { path: change.path, after: change.after });\n\t\tif (!this.firstStates.has(change.path)) this.firstStates.set(change.path, change.before);\n\t\treturn sequence;\n\t}\n\n\tasync applied(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'applied', sequence });\n\t\tconst change = this.pendingStates.get(sequence);\n\t\tif (!change) return;\n\t\tthis.pendingStates.delete(sequence);\n\t\tthis.currentStates.set(change.path, change.after);\n\t\tthis.appliedInOrder.push(change.path);\n\t}\n\n\tasync abandoned(sequence: number): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'abandoned', sequence });\n\t\t// Only once recorded: a change whose abandonment was not may still count as made.\n\t\tthis.effects.delete(sequence);\n\t\tthis.pendingStates.delete(sequence);\n\t}\n\n\tasync observe(manifest: string, by: string): Promise<number> {\n\t\tthis.assertOpen();\n\t\tconst sequence = ++this.sequence;\n\t\tawait this.append({ type: 'observing', sequence, manifest, by });\n\t\t// Until it is observed, whatever ran may have changed a file.\n\t\tthis.effects.add(sequence);\n\t\treturn sequence;\n\t}\n\n\tasync observed(sequence: number, measure?: ObservationMeasure): Promise<void> {\n\t\tthis.assertOpen();\n\t\tawait this.append({ type: 'observed', sequence, ...(measure ? { measure } : {}) });\n\t\t// Its changes, if any, are entries of their own now.\n\t\tthis.effects.delete(sequence);\n\t}\n\n\tget storedBytes(): number {\n\t\treturn this.stored;\n\t}\n\n\tget appliedPaths(): readonly string[] {\n\t\treturn this.appliedInOrder;\n\t}\n\n\t// Computed again only after a change was applied.\n\tcontentState(): string {\n\t\tif (this.state?.applied !== this.appliedInOrder.length) {\n\t\t\tconst changed = [...this.currentStates]\n\t\t\t\t.filter(([path, current]) => {\n\t\t\t\t\tconst first = this.firstStates.get(path);\n\t\t\t\t\treturn !first || !sameState(first, current);\n\t\t\t\t})\n\t\t\t\t.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n\t\t\tthis.state = {\n\t\t\t\tapplied: this.appliedInOrder.length,\n\t\t\t\thash: hashOf(Buffer.from(JSON.stringify(changed))),\n\t\t\t};\n\t\t}\n\t\treturn this.state.hash;\n\t}\n\n\tget changed(): boolean {\n\t\treturn this.effects.size > 0;\n\t}\n\n\tasync finish(status: Exclude<RunStatus, 'running' | 'interrupted'>): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.finished = true;\n\t\ttry {\n\t\t\tawait this.pending;\n\t\t\tawait this.journal.close();\n\t\t\t// Its record is left `running`: if removing it fails, readers already take it as gone.\n\t\t\tif (!this.changed) {\n\t\t\t\tawait this.discard();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst record: RunRecord = { ...this.record, status, finishedAt: new Date().toISOString() };\n\t\t\tawait writeDurably(join(this.runDirectory, 'run.json'), JSON.stringify(record));\n\t\t} finally {\n\t\t\tawait this.release();\n\t\t}\n\t}\n\n\tprivate append(line: JournalLine): Promise<void> {\n\t\tconst write = this.pending.then(async () => {\n\t\t\tif (this.broken !== undefined) {\n\t\t\t\tthrow new Error(`The journal of run ${this.runId} stopped after a failed write`, {\n\t\t\t\t\tcause: this.broken,\n\t\t\t\t});\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.journal.appendFile(`${JSON.stringify(line)}\\n`);\n\t\t\t\tawait this.journal.sync();\n\t\t\t} catch (error) {\n\t\t\t\tthis.broken = error ?? new Error('Unknown write failure');\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t\t// The chain goes on, so each later append reports the broken journal to its own caller.\n\t\tthis.pending = write.catch(() => undefined);\n\t\treturn write;\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.finished) throw new Error(`Run ${this.runId} has already finished`);\n\t}\n}\n"]}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* What a modification returns: its path, then the lines around each change as the file now
|
|
3
|
-
* reads them
|
|
4
|
-
* the file again. What does not fit is counted, not shown.
|
|
3
|
+
* reads them. The model can check its edit without reading the file again.
|
|
5
4
|
*/
|
|
6
5
|
export declare function describeModification(path: string, before: string, after: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* What an edit adds to its response when the formatter rewrote what the model sent: that the file
|
|
8
|
+
* must be read again, and those lines as it now reads them. Nothing when the formatter left the
|
|
9
|
+
* file as written.
|
|
10
|
+
*/
|
|
11
|
+
export declare function describeFormatting(path: string, written: string, formatted: string): string;
|
|
7
12
|
/**
|
|
8
13
|
* An edit as a git-style unified diff, for the person watching it happen. A missing side is a
|
|
9
14
|
* file that did not exist, or no longer does. Too long a diff is cut, and says so.
|