Add append mode to WriteFile - #72
Open
Otávio Carvalho (otaviocarvalho) wants to merge 1 commit into
Open
Otávio Carvalho (otaviocarvalho) wants to merge 1 commit into
Otávio Carvalho (otaviocarvalho) wants to merge 1 commit into
Conversation
WriteFile currently opens the target with O_TRUNC on every stream, so guest-side transcript files cannot be grown across writes. Add a bool append field to WriteFileRequest (proto field 4): when set on the first message the guest opens O_CREATE|O_WRONLY|O_APPEND instead of O_CREATE|O_WRONLY|O_TRUNC; the file is created if it does not exist. The api proxies WriteFileRequest opaquely, so no api-side change is needed.
Otávio Carvalho (otaviocarvalho)
marked this pull request as ready for review
October 2, 2026 12:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an optional
appendflag toWriteFileRequest(field 4, additive). When set on the first stream message, the guest opens the target withO_CREATE|O_WRONLY|O_APPENDinstead ofO_CREATE|O_WRONLY|O_TRUNC, creating the file if absent. Default behavior is unchanged: the flag defaults tofalse, and truncate remains the pinned, regression-tested path.The flag follows the same first-message-open semantics as
pathandmode: the open happens once on the first chunk; subsequent messages are payload-only.Use case
I operate a small fleet of autonomous agents on a self-hosted single-node k3s cluster (a NUC). The agents execute inside
envguests and persist session state as append-only JSONL transcripts — one line per event (tool calls, outputs, checkpoints) — while a host-side supervisor tails those transcripts for resume-after-restart, dashboards, and off-cluster log shipping.The workload is strictly incremental, which is where whole-file
WriteFilesemantics break down:O_APPENDmakes each write an atomic tail placement, so concurrent writers compose without external coordination.bytes_written, unstructured errors), or handled with client-side segment ledgers that drift from filesystem state.Append restores stream semantics for a file at minimal surface cost: one bool on an existing message. Checkpoint journals and other event-sourced state have the same access shape.
Deliberately out of scope here: directory enumeration — tracked separately in #74.
Compatibility
false→ truncate. No behavior change for existing callers.apiproxiesWriteFileRequestopaquely, so no api-side change; the flag traverses every proxy/route transparently (covered end-to-end through the real router + guest).Tests
TestAppendPreservesExistingContent— append retains prior bytes; multiple chunks arrive in order;bytes_writtencounts only new bytesTestAppendCreatesNewFile— append to a missing path creates it with the requested modeTestDefaultWriteStillTruncates— regression guard: unset flag preserves truncate semanticsTestProxyAppendWrite— flag survives client → api → router → guest (real guest server behind the router)All green:
go test ./guest/filesystem/ ./internal/apiservice/ -count=1.Notes for reviewers
path/mode); later messages carry chunks.