-[x] C1 **Working-copy writes hold the workspace lock** (oxygen#36). Checkout, bookmark switch (with --carry), pull's checkout, undo, discard and commit hold the lock from reading the head until their operation is recorded. `merge_views` never lets a working-copy change based on a replaced one win. Test: a snapshot concurrent with a checkout never records the checkout's writes as edits.
83
- [x] C2 **`bookmark create NAME CHANGE` refuses a partial state** (oxygen#37). When CHANGE is one of the current state's heads but not all of them, it refuses and explains, unless given --only. `bookmark switch` summarises a wide tree difference. The guide explains that bookmarks name states, not ancestry.
84
- [x] C3 **A parent's switch never rolls a subrepo's bookmark back** (oxygen#38).
85
- [x] C4 **`pull` says "Already up to date" while one behind** (oxygen#29). Reproduce it with a test, then fix it.
- 2026-09-29 **C1 to C4 done** (the metalgear findings in ~/oxygen_feedback.md, items 22 and 25 to 26). The gate passes: 205 tests, clippy clean.
162
-**C1** (e8e51993, closes #36): the working-copy lock now covers checkout, switch (and --carry), merge, commit, amend and rewrites, discard and pull. It is re-entrant per thread, waits up to a minute, and a live process's lock is never taken over. A workspace changed by two concurrent operations is now an error. A race test runs twenty switches against a snapshot thread; without the lock it failed one run in three.
163
-**C2** (bf423e78, closes #37): `bookmark create NAME CHANGE` refuses when it would leave out earlier work, unless given --upto or --only. `bookmark switch` says how many changes the new state lacks. The guide explains states for people coming from Git.
164
-**C3** (6b582c4c, closes #38): a parent's checkout moves a subrepo's bookmark only forward, and the pin is read from the nested working copy. `--carry` leaves a subrepo whose pin is carried work as it is.
165
-**C4** (5dfea7b7, closes #29): not a sync bug. rstar-api's operation log shows each such pull ran on a feature bookmark, while main, which the fetch had just updated, was the one behind. pull now names the bookmark it pulled and the others left behind.
166
-**For Andy:** metalgear's working copy is sound, on develop and clean. `logo-25` holds just the logo change and its dependencies; delete it if it is not wanted.
- 2026-09-30 **M0 and M1 done; M4, S2 and S3 part way** (oxygen#35 and oxygen#39). The tests and clippy pass after each step. Each step was measured on the Linux tip and is recorded in docs/benchmarks.md.
168
-**M0** (f11e81a1): a counting allocator behind the `alloc-stats` feature; with `OXY_TIMINGS` it reports memory per phase.
169
-**M1**, with these steps:
170
- history-only loads read no text (22b70898), then read only a change's skeleton (39c6adea);
171
- graph keys are written at commit (22b70898);
172
- a clean status is answered from the manifest (b4fefa1e) with a parallel walk (e19aa6c5).
173
- Clean status: killed at 14 GB before, now 0.44 s and 123 MB (Git: 0.22 s).
174
-**History-only loads where no graph is needed** (26f81555): bookmark, merge, pull, tags, bisect, doctor and most history rewrites.
175
-**Checkout**: a batch at a time (921fa890), without a snapshot when clean (d1b480f0), and against the manifest without the base state (2b7ce2c6).
176
- One-file switch: killed before, now 2.1 s and 455 MB (Git: 0.2 s).
177
- Local clone: killed before, now 110 s and 8 GB (Git: 9.6 s).
178
-**log, blame and fsck** (34ea4ace), with metadata-only change reads:
179
- log -n 100: 28 s and 4.7 GB before, now 2.0 s;
180
- blame: killed before, now 1.1 s;
181
- fsck: killed before, now 123 s and 4.5 GB.
182
-**Snapshot**: a parallel walk with stats carried into the manifest (a578fa19), and a cached tree view (de3f07f8). Status with one file changed: 4.1 s before, now 2.3 s (Git: 0.23 s).
183
-**Still far from Git**: one-file and 1 000-file status, diff and commit (2 to 5 s); switch (2 s); log (2 s); clone (110 s, 8 GB); first commit (56 s, 10 GB); fsck (4.5 GB).
184
- The common cost is loading the first change's history (0.5 s) and building the tree view (0.4 s).
185
- Next: a persistent per-state cache (tree view, graph keys and change set), Git's index in effect, then compact graphs (M2) and a streaming commit (M3).
- 2026-09-30 **M2 done, M3 and S1 part way** (oxygen#35). The first commit of the Linux tip now takes 40.7 to 41.6 s on a quiet Earth (S1 target: 50 s; Git: 34 to 38 s) and 4.9 GB RSS (from 10 GB).
187
-**Encoding** (b7103633): each change is encoded once, the working copy's edits are moved rather than copied, and text blobs and chunk compression run on every core.
188
-**Storing** (b7a090c7): texts go to the store a batch at a time.
189
-**M2, lines** (086641a8): an insert's lines are one shared buffer, into which graph atoms point.
190
-**Clone** (5d62fa66, 11bf3b00, 397d9f98): a local clone takes 48 s and 3.9 GB (from 96 s and 5.2 GB, and killed before that; Git: 9.6 s). The changes behind it:
191
- an unedited file's graph is read off as a chain;
192
- a bundle carries its changes' hashes;
193
- a large change is read once per checkout;
194
- a local fetch moves changes as stored.
195
-**Hub and runner**: re-pinned to oxygen 397d9f98 and deployed (oxygenhub#58, a6f006ba; oxygenflow#15, 630b7fd6). The hub reads metadata or skeletons where it lists changes. Checked: /health, and the log, file history, tree and file pages.
196
-**Note**: my pushes start Flow jobs on Earth, so timings under load are marked in benchmarks.md.
- 2026-09-30 **H1 done** (oxygen#30). Three causes, each from Git having no identity for a directory:
198
- a directory deleted and made again became a second node;
199
- a placement under a removed directory was out of reach;
200
- orphans could not be seen.
201
- The fix: an import revives the directory, and a merge retires a kept node's other placements and every orphan. There is a Git-built test for each cause; each reproduces the vscode symptom without its fix. Spec §23.
202
- The vscode slice now verifies: all 1 747 commits and 3.3 million files.
203
-`oxy git verify` is cached by graph key and blob: 115 s instead of 1 400 s.
- 2026-09-30 **H2, first part**: an import builds graphs only for the files a commit may change, from history-only states. The first 5 000 vscode commits: 309 s and 2.3 GB (from 412 s and 6.3 GB), and all verified. Next: verify and import reuse each commit's history instead of loading it again, before H3 to H5.