2 Commits

Author SHA1 Message Date
Zecheng Zhang 186804d5f7 chore(daemon): MIRAGE_HOME is the single root; mirror the disk-store default in TS (#551) 2026-07-18 01:59:25 -07:00
Zecheng Zhang 7adc1c4ff8 feat(version): workspace versioning over the server API + CLI (#90)
* build: add dulwich as optional version extra

* feat(version): scaffold module

* feat(version): VersionStore.open inits bare repo

* feat(version): blob write/read with content dedup

* feat(version): nested tree write/read

* feat(version): commit, head, read_commit + HEAD ref

* feat(version): branches + log

* feat(version): file-level tree diff

* feat(version): to_tree_inputs maps workspace content to tree entries + meta

* feat(version): to_state reverse-maps entries+meta to workspace state

* feat(version): meta sidecar serialization (meta_to_blob/blob_to_meta)

* feat(version): snapshot_tree writes blobs + meta sidecar to a git tree

* feat(version): commit composes snapshot_tree + parent linkage

* refactor(version): drop unused META_FORMAT sidecar field

* feat(version): version_log + version_diff + status (meta sidecar excluded)

* feat(version): branch creates a new line at a branch head

* feat(version): materialize reads a version tree back to entries + meta

* refactor(snapshot): extract install_fingerprints from Workspace.load for reuse

* refactor(version): rename materialize -> read_version

* feat(version): checkout rebuilds workspace content in place (cache cleared)

* refactor(version): commit/snapshot from state (enables CLI commit from daemon snapshot)

* feat(version): guard dulwich import so core/CLI load without the version extra

* refactor(version): move version engine under cli; dulwich -> cli extra

* feat(version): store top-level config in meta; add status_state + resolve_ref

* feat(cli): wire workspace commit/log/diff/branch/status/checkout to local .mirage store

* feat(version): commit file cache + remote revision pins + sessions

* refactor(version): rename mapping.py -> state_tree.py

* feat(version): CAS commit (reject stale head) instead of clobbering the ref

* feat(version): versioning server API + CLI (commit/log/diff/branch/checkout/clone)

Engine moved under server/ and exposed over HTTP; mirrored in TypeScript.
Adds branching examples (py + ts) checked against one shared truth file,
brings the CLI tests to parity, and documents the verbs.

* style(schemas): use # isort: skip for the long workspaces re-export

Match the convention already used in routers/workspaces.py and
routers/versions.py instead of a one-off # yapf: disable.

* ci(ts): run the CLI e2e suite isolated from the other packages

The cli e2e tests spawn a real daemon + a CLI subprocess per call (blocking
spawnSync). Running them in parallel with the other packages' vitest (pnpm -r)
starved CPU on CI, so the cli worker's onTaskUpdate RPC timed out (all 51 tests
passed, but the run errored). Run libraries in parallel, then cli alone.

* fix(ts/cli): make e2e CLI calls async to stop blocking the vitest worker

Root cause: the e2e helpers used blocking spawnSync, freezing the vitest
worker's event loop for the whole 103s suite. vitest's onTaskUpdate RPC has a
fixed 60s birpc timeout, so the parent's ack couldn't be processed in time and
the run errored (all 51 tests passed). Isolating the package didn't help (still
one continuously-blocked worker). Switch spawnSync -> async spawn so the loop
stays responsive between calls; revert the now-unneeded CI step split.
2026-05-24 04:35:29 -07:00