Files
orca/src/shared/remote-runtime-shared-control-socket-generation.ts
T
Neil 699b9a0637 feat(files): guarded file writes that refuse to overwrite a changed file (#30605)
* feat(files): guarded file writes that refuse to overwrite a changed file

Adds an optional disk precondition to file writes: the writer compares the file
on disk with an expected signature inside the write, serialized per file (path
then inode), and refuses with a typed changed/missing result instead of writing.
Remote hosts serve it as files.writeIfUnchanged behind a capability; older
hosts get a client-side compare that fails closed, pinned to the probed runtime
and connection. Undo of a delete and the MCP starter config use it to write only
into a missing or identical file. Groundwork for guarding editor saves.

* fix(files): pin guarded writes on the sending socket; keep refused undo; narrow not-found and pinning

* fix(files): pin a guarded save to one pairing; keep only refused undo steps

* fix(files): ENOENT by code only; resolve symlink chains fully; pin lost-reply recovery to the save's pairing
2026-10-19 01:27:53 -07:00

49 lines
1.2 KiB
TypeScript

import type { RemoteRuntimeClientError } from './remote-runtime-client-error'
import type { SharedControlLogicalSubscription } from './remote-runtime-shared-control-types'
export class SharedControlSocketGeneration {
private current = 0
peek(): number {
return this.current
}
isCurrent(generation: number): boolean {
return generation === this.current
}
begin(): number {
this.current += 1
return this.current
}
invalidate(): void {
this.current += 1
}
acceptClose(args: {
generation: number
error: RemoteRuntimeClientError
everReady: boolean
subscriptions: Map<string, SharedControlLogicalSubscription<unknown>>
closeSocket: () => void
}): boolean {
if (!this.isCurrent(args.generation)) {
return false
}
// Why: error, close, and liveness callbacks can race for one socket; only its first callback owns recovery.
this.current += 1
args.closeSocket()
if (args.everReady) {
for (const subscription of Array.from(args.subscriptions.values())) {
try {
subscription.callbacks.onError(args.error)
} catch {
// Why: one consumer callback cannot block sibling notification or reconnect scheduling.
}
}
}
return true
}
}