feat(plan): file-based revisions, free-form status, and optimistic locking#3274
Merged
Conversation
…cking Implements the three improvements requested in issue #3263. File-based revisions: - export_plan_to_file writes a plan's content to disk and returns only metadata, never the body, so materialising a plan costs no output tokens. - update_plan_from_file commits new content read from a file. File reads reject directories, non-regular files (devices, named pipes) and oversized files, and are bounded by an io.LimitReader. Free-form status: - Plan and Summary gain a free-form status string (no fixed vocabulary). - set_plan_status and get_plan_status read and write the status without the body; status is also accepted on write_plan and update_plan_from_file. - A new TUI renderer surfaces the status and title next to single-plan calls. Optimistic locking: - The existing auto-incremented revision is the version number. Reads return it; write_plan, update_plan_from_file, set_plan_status and delete_plan accept an optional last_known_revision that rejects the write with a conflict error on mismatch. The compare-and-set is atomic under the storage mutex. Storage.Upsert now takes an UpsertRequest (nil fields preserve their previous value) and Storage.Delete takes an optional expected revision. Docs and the shared_plan example are updated to cover the new tools.
dgageot
approved these changes
Jun 26, 2026
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
Implements the three plan-toolset improvements from #3263: file-based plan revisions, a free-form status field, and version-based optimistic locking. The existing auto-incremented
revisionis reused as the version number.New tools
export_plan_to_fileupdate_plan_from_fileset_plan_statusget_plan_statusread_planandlist_plansnow also reportstatus;write_plan,update_plan_from_file,set_plan_statusanddelete_planaccept an optionallast_known_revision.Issue expectations mapped
update_plan_from_fileaccepting a file pathupdate_plan_from_filetoolexport_plan_to_filewriting content without returning itexport_plan_to_filereturns metadata onlyPlan.Statusstring, no validationset_plan_status/get_plan_status(lightweightStatusView)plantoolrenderer on single-plan callsrevisionlast_known_revisionon every write tool,VersionConflictErrorread_plan,get_plan_statusandexport_plan_to_filereturnrevisionSafety
io.LimitReaderTests
-race; lint is clean on the changed packages; the tree cross-compiles for Windows (the named-pipe test is//go:build unix).Note for reviewers
The optimistic-lock parameter is named
last_known_revisionrather than the issue'slast_known_version, for coherence with the existingrevisionfield that reads already return (a caller readsrevisionand passes the same value back). Iflast_known_versionis preferred, it is a small rename.Implements #3263.