Repository navigation
fix(cli): history reads answer while another app has the project open - #5445
Merged
Merged
Conversation
Collaborator
Author
|
Fresh review: clean, three minors for a follow-up after merge: the busy refusal now says 'another app' even when the holder is another CLI run or a stale lock (and for begin/end), fallback reads report via 'direct' so they can't be counted, and the writes-nothing test compares names and contents one level deep only. |
somanshreddy
approved these changes
Oct 11, 2026
somanshreddy
left a comment
Contributor
There was a problem hiding this comment.
Approving at 32d284c3.
Checked
withReadercan't run its task twice. It tries the owner exactly as before, so a read still files pending writes when nobody owns the history. It falls back to the view only onHistoryBusyError, which is thrown at open, before the task runs.readProjectHistoryis read-only:- It takes no lock and starts no watcher.
- It replays through the engine's own
readLog, which skips a half-appended line, and applies the same hidden-path filter. listOfandpeekOfare shared with the engine, so the view and the owner can't drift.- Blob reads go through the shared
blobPath, which validates the 64-hex hash before joining, and a pruned blob becomes the "no longer kept" refusal.
- Writes still refuse.
undo/restore/pin/begin/endstill go throughwithOwner, and the busy message is reworded only inguarded.
Verification
- cli
history.test.ts: 34/34, after rebuilding studio-server'sdist. - studio-server
projectHistory.test.ts: 138 pass, 2 skipped (case-insensitive FS). - Mutants killed:
- no busy fallback (2 fail)
- no ENOENT → refusal mapping (1 fails)
- CI: the required checks that have reported are green.
Testand the edit-accuracy shards were still queued or running when I posted, none red. No CRs.
Should-fix (latency)
- A read only falls back after
openProjectHistorygives up taking ownership, and the CLI doesn't passownerWaitMsoutside tests, so it uses the default?? 5000(projectHistory.ts:1287). - So while Desktop has the project open, every
history/show/peekwaits about 5 s before answering. That's exactly the agent use case this PR targets. - Fix: check for a live owner first (e.g.
owner.pidalive and not ours), or pass a shortownerWaitMson the read path, keeping the full wait for writes.
Review by Somu
miguel-heygen
enabled auto-merge
October 11, 2026 01:25
Contributor
Edit accuracy: accurate 2061 (base branch 2061), smooth 1620 of thoseThe gate passes. Quarantined, measured but not gated (0) |
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.
What changed
When another app keeps a project open, it owns that project's history (
owner.pidin the project's history folder). Until now, everyhyperframes historycommand then refused with "This project's history is open in another process (pid N).", even commands that only read. So an agent working on that project could not runhyperframes history --json --limit 2.readProjectHistory({ projectDir, historyRoot })returns a read-only view of a project's history:list,peekandreadBlob.readLog, which already drops a half-appended last line, and applies the same hidden-path filter.listandpeeknow come from two small functions,listOfandpeekOf, shared with the engine.blobPathhelper, shared with the blob store.history(list),showandpeekgo through a newwithReader.peekandshow --diffrefuse with "That point is no longer kept" instead of a raw ENOENT.undo,restore,pin,beginandendstill refuse while another app owns the history. The message now reads "This project is open in another app (pid N), which keeps its history: undo, restore or pin there."What I measured
history.test.ts: 34 passed, exit 0, 3 runs in a row.history --json --limit 2lists the two newest entries,showprints the entry's files andpeek <id> index.htmlprints the old bytes.undoexits 2 with the new words and leaves the file alone.historyDeps.ownerWaitMs.projectHistory.test.ts: 138 passed, 2 skipped (the case-insensitive-disk tests on Linux), exit 0, 3 runs in a row. The new view test passed 3 runs in a row.listandpeekequal the owner's, andreadBlobreturns the old bytes.projectHistory.swap.test.ts7 passed andpruneHistories.test.ts15 passed.tsc --noEmitpassed in both packages,oxlintreported 0 warnings and 0 errors on the changed files, andoxfmt --checkwas clean.openProjectHistory, and a second ran the real CLI from source.history --json --limit 2returned both entries, exit 0.showandpeek start index.htmlprinted, exit 0.undo <id>andpin <id>exited 2 with the new message, andindex.htmlwas unchanged.history,showandpeekback on the owner path, the cli test fails:AssertionError: expected 2 to be +0on the exit code ofhistory --json --limit 2.TypeError: readProjectHistory is not a function. With the view parsing each log line itself instead of throughreadLog, it fails on the torn line:SyntaxError: Expected ',' or '}' after property value in JSON at position 36.ENOENT: no such file or directory, open '…/blobs/…'.What I did NOT exercise
openProjectHistoryhandle, the same open call that editor makes.