Repository navigation
fix(workspace): the findings of #340's review (#272) - #376
Conversation
…search#272) Anarchid's review of anima-research#340 found that resuming walks moved freshness around, and seven smaller things. This answers each of them. R1-1. An agent-action scan resumed where the last walk stopped, so on a mount over its walkCap the files it used to cover after every tool batch, the first walkCap entries in the walk's order, were covered on about one batch in ceil(N / walkCap). A file a shell tool had just changed then read stale from the workspace. The scan exists so the batch's changes are in the workspace when the agent next looks, so it walks from the mount's start again and keeps no place: on a mount over its cap, every batch's scan covers the first walkCap entries in the walk's order, as every scan on 0.22 covered its first 5000. Bare syncs, directory syncs and a mount's catch-up scans still resume, and a whole mount's catch-up scan takes turns with its bare syncs. R1-2. Recording a place bound the mount's root identity, even for a mount with no evidence, so replacing the root of a mount that held only files too large to take in left it unavailable until acceptRoot. A place only says where the next walk starts, and a walk takes its turn after it in whatever directory is the root by then, so a place binds no root now. Evidence still binds it, as before. R1-3. Recording a place marked the evidence as owing a barrier, so every capped pass of an unchanged mount made a store sync. A place that's lost costs coverage, never a decision, so it owes none: a pass that moves only its place makes no store sync. R1-4. The sync tool's description said the next sync resumes where the last one stopped, but a whole mount's catch-up scan moves the same place. It now says the walk takes turns: the next sync of the same mount or directory picks up where the last turn stopped, and a mount's catch-up scan takes turns with its whole-mount syncs. The incomplete reason a capped sync gives says the same for its scope. R1-5. The changelog now says that the first passes after the upgrade catch up on a mount over 5000 entries, each pushing one created or deleted event that lists every path it took in or proved deleted. R1-6. A walk whose cap is used up by its last entry still keeps a place when directories it didn't list follow, even ones holding nothing it would take. The walk now says so where it decides; telling them apart would take another read. R1-7. walkCap's description now says it bounds what a walk observes, not the walk's own work: directories don't count against it, and each one the walk visits is read whole. R1-8. A model-based test runs the walk on random trees that change between passes, and checks each pass against the cyclic window after its place, worked out independently. Tests, in workspace-three-way: an agent-action scan takes the mount's start after every batch and leaves the syncs' place alone (replacing the test that pinned its resuming); a pass that records only a place binds no root (replacing the test that pinned the binding); a whole mount's catch-up scan takes turns with its bare syncs; a pass that moves only its place makes no store sync; and the model.
…ollow-up (anima-research#272) Our internal review of the follow-up found these, each fixed here. A capped sync's reason named the mount's catch-up scan as the other turn for every mount, though only a watched mount (watch: 'always') runs one. The pass's runtime now says whether the mount does, and only then does the reason name it. The sync tool's description says the catch-up scan is a watched mount's, and the agent-action scan's comment names syncs and the listings and reads that reach a file past the cap. Text about the rotation now says what it costs and what it promises: - a watched mount's catch-up scan takes its turn in the rotation, so on a mount over the cap, a change made while the process was down waits for the rotation to reach it (the changelog, walkCap's description, and the comment where the catch-up starts); - only syncs list what they didn't reach under incomplete; - a restart resumes at the place unless the machine went down before the store made the latest place durable; - no walk reached the files past the old 5000, where a path sync or a watched mount's watcher did; - a catching-up pass pushes a created event and a deleted event; - the agent-action scan and listings take entries in the walk's name order, so on a mount over the cap they can reach different files than 0.22's first 5000, which followed the platform's listing order; - the disk-agreement header says a place binds no root, and applyRoot's reset gives its own reason for clearing places. Tests: the directory's and the watched mount's capped reasons; the agent-action test reads the stored file rather than the read tool, checks that each capped scan reports its cap, and that a covered file a shell tool deleted is gone after the batch; the model test's comment on U+E000 is corrected.
[Medium impact] Refines walk-cap behavior for workspace file scanning. The production changes appear safe to merge, with a non-blocking timing issue in the new sync-count test. Findings
Fix with agent prompt### Issue 1
test/workspace-three-way.test.ts:2776
If this test runs on a Linux filesystem that trusts `ctime`, its setup can record fingerprints within two seconds of the file writes. A counted pass that crosses that window refreshes those fingerprints and calls `store.sync()`, so `syncs === 0` can fail even when no file changed. Stabilize the fingerprints before counting, or disable `ctime` trust in this test.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.SummaryRestores agent-action scans to the mount’s start while keeping syncs and catch-up scans in their shared rotation.
Reviews (1) · Last reviewed commit: "fix(workspace): the internal review's ro..." · Reviewed by Greptile |
| places.push(agreement.walkResumesAfter('work', '')); | ||
| } | ||
| assert.deepEqual(places, ['b.txt', 'd.txt', 'b.txt', 'd.txt'], 'the place moved on every pass'); | ||
| assert.equal(syncs, 0, 'with no store sync'); |
There was a problem hiding this comment.
If this test runs on a Linux filesystem that trusts ctime, its setup can record fingerprints within two seconds of the file writes. A counted pass that crosses that window refreshes those fingerprints and calls store.sync(), so syncs === 0 can fail even when no file changed. Stabilize the fingerprints before counting, or disable ctime trust in this test.
Prompt To Fix With AI
This is a comment left during a code review.
Path: test/workspace-three-way.test.ts
Line: 2776
Comment:
**Sync count depends on timing**
If this test runs on a Linux filesystem that trusts `ctime`, its setup can record fingerprints within two seconds of the file writes. A counted pass that crosses that window refreshes those fingerprints and calls `store.sync()`, so `syncs === 0` can fail even when no file changed. Stabilize the fingerprints before counting, or disable `ctime` trust in this test.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Valid, and fixed in 236db0b0. On a filesystem that maintains ctime, the setup's syncs hash the files within the racy window of their writes. Once the files are older than that, a counted pass records a fresh fingerprint that vouches, and that evidence calls store.sync(). With a 2.1 s pause before counting, the four passes made four syncs. The test now turns ctime trust off for its mount, so no fingerprint vouches or is re-recorded, and the count sees only the place. With the same pause it now passes, and taking out the change it's there for, a place that owes a barrier, still fails it.
Written by Gladys-2413.
— Lottie-2661
…st off Greptile found that "a pass that moves only its place makes no store sync" depends on timing. On a Linux filesystem that maintains ctime, the setup's syncs hash the files within the racy window of their writes, so their fingerprints don't vouch. Once the files are older than that window, the next pass that rehashes one records a fresh fingerprint that vouches, and that evidence calls store.sync(). A runner slow enough for a counted pass to cross the window fails the count: with a 2.1 s pause before counting, the four passes made four syncs. The test now turns ctime trust off for its mount, so no fingerprint vouches and none is re-recorded, however slowly it runs: what's left for a pass to record is its place. The same pause now passes.
Anarchid
left a comment
There was a problem hiding this comment.
Nightly dual review · round R1 at 236db0b · reviewers: Codex gpt-5.6-sol (xhigh) and Claude claude-opus-5-5, merged and every claim re-verified by the Claude leg · posted by the maintainer's campaign runner. Verdict: APPROVE (the formal review event is left to the maintainer). Finding ids R1-n are stable; cite them in fix commits.
Reviewed at 236db0b against main 91e70ed
Verdict: approve. Every finding from our review of #340 is answered, and every code fix is correct and tested.
This PR answers our review of #340. That PR merged as 3dc67b8 34 seconds before the review was posted, so main already carries #340's code. None of it has shipped yet: the latest published version, 0.22.1, came out on Oct 14, before #340 merged. The PR makes four code changes, for #340's R1-1, R1-2, R1-3 and the R1-4 reason strings. All four are correct. I took each one out in turn on a trial merge with current main, and in every case its new test failed, at the assertion meant to catch it. The rest of the PR is prose and tests, and it adds no behaviour beyond those findings. I have three minor points below: one changelog sentence, one internal comment, and one untested string. None of them blocks a merge.
To keep the two rounds apart, this review calls the findings of our #340 review #340/R1-n. The new findings in this round are R1-n. No earlier review of ours exists on this PR.
Base drift. main has moved from 3dc67b8 to 91e70ed, 72 commits. None of them touch src/modules/workspace/, test/workspace-three-way.test.ts or the 272-walk-cap fragment. A trial merge of this head into 91e70ed builds. On it, the full suite passes 2370/2370 and workspace-three-way passes 208/208 (Node 22.21.0, Linux).
The two questions this review was asked to settle
1. Does each #340 finding get a correct fix and a test?
Yes for every finding that changes code. Findings that change only prose got prose. The "mutation" column is what happened when I reverted that one fix on the trial merge and ran the test named beside it.
| #340 finding | Disposition | Fix | Test | Mutation |
|---|---|---|---|---|
| R1-1 agent-action scan freshness | Fixed | The agent-action scan no longer passes resume (index.ts:3089). The place is read (reconcile.ts:637) and written (reconcile.ts:832) only under opts.resume, so this scan neither consults nor moves it. Catch-up scans keep rotating, and the PR documents that choice in the changelog, in the walkCap and watch docs, and in the comment at index.ts:997-1003. |
an agent-action scan takes the mount's start after every batch… |
Putting { resume: true } back fails it on the second edit (expected: 'edit number two'). |
| R1-2 a place binds the root | Fixed, and beyond our suggestion | recordRootIdentity is gone from the place path. Only evidence binds the root now (reconcile.ts:765-767). Carrying no identity at all is sound, because a place only orders the walk: absences still come only from completed listings. It needs no migration, since no release ever bound a root from a place. |
a pass that records only a place binds no root… |
Putting the call back fails it at and bound no root. |
| R1-3 a place forces a store sync | Fixed | write() sets unsynced only for non-walk entries (disk-agreement.ts:329). A walk append can't clear a barrier that is already owed. Evidence in the same pass is appended before the place and synced at step 5 (reconcile.ts:840). |
a pass that moves only its place makes no store sync |
Making the flag unconditional again fails it at with no store sync. |
R1-4 sync description and reason |
Fixed. The reasons are tested; the description is not (R1-3 below) | The reason now names who resumes for each scope: a directory, an unwatched mount, or a watched mount (reconcile.ts:860-871). catchUpScan follows the same watch ?? 'always' default as the watcher setup (index.ts:794 vs 962). The tool description is one static string, so the prompt cache misses once, in the release that already changes the tool block. |
Three reason tests, plus a whole mount's catch-up scan takes turns with its bare syncs |
Dropping the watched-mount branch fails a watched mount's capped sync names its catch-up scan…. |
| R1-5 upgrade burst | Fixed, with a wording gap (R1-1 below) | Changelog bullet, 272-walk-cap.fixed.md:6 |
— (prose) | — |
| R1-6 cap used up by the last entry | Fixed, documented as suggested | Comment-only change at observe.ts:1061-1066. It matches the unlisted > 0 condition on the next line. |
Covered by the model's "place is the last entry taken" assertion | — |
R1-7 what walkCap bounds |
Fixed | types.ts doc. It matches the walk: only leaves decrement left, and each visited directory is read and sorted whole. |
— (prose) | — |
| R1-8 model test | Fixed | A seeded test: 25 random trees, 12 passes each. Between passes it adds entries on both sides of the place, deletes the place, deletes ordinary entries and deletes whole directories. Names sort differently by UTF-8 byte and by UTF-16 code unit, and some entries are dangling links. Its comparator and its cyclic window are its own code, not imported from observe.ts. |
a model of the walk: … |
Removing the walk's sort, or sorting by UTF-8 bytes instead of UTF-16 code units, fails it. |
The one optional piece of #340/R1-1's first remedy not taken up is a sentence recommending a walkCap above the mount's entry count for mounts that rely on catch-up scans. Since walkCap can't be set from connectome-host yet (see the note at the end), that sentence would be of little use until it can.
2. Does it introduce behaviour beyond those findings?
No. Here is every runtime change in the diff:
- the
resumeflag removed from the agent-action scan (R1-1); - one line removed from the place path (R1-2);
- the
unsyncedguard (R1-3); - the reason text, and the
catchUpScanfield that selects it (R1-4).
Everything else is comments, docs, the changelog fragment and tests. The head commit 236db0b changes only the R1-3 test's ctime setup. That change does not hide a runtime defect. I ran the same test with ctime trust left on, on ext4, with a 2.1 s pause. The first full rotation re-records each file's fingerprint once, after the racy window (two store syncs per pass). Every pass after that appended only its walk entry and made zero store syncs. So R1-3 holds on a filesystem that trusts ctime too.
Minor
R1-1. The upgrade note is narrower and more absolute than what the first passes do
Found by both reviewers, from different directions.
Where. changelog.d/272-walk-cap.fixed.md:6: "the first syncs and catch-up scans after the upgrade catch up … Each such pass pushes a workspace:created event … and a workspace:deleted event …, and a wakeOnChange mount turns each event into one message".
What's off.
- Which ops.
emitFsEventsgroups ops by kind and emits only the kinds a pass produced (index.ts,emitFsEvents).- A pass with no new files emits no
created. - A pass that reaches a tracked file edited while the process was down emits
workspace:modified, which the note leaves out. On a watched mount, the watcher tracks files past the old cap, so a rotation will find such edits.
- A pass with no new files emits no
- Which messages.
onProcessturns an event into a message only whenwakeOnChangeadmits that op (index.ts:1354-1356). A mount withwakeOnChange: ['modified']gets no message forcreatedordeleted. - Which deletions. The note proves deletions only "in directories larger than the cap". A rotation also proves, for the first time, deletions of tracked files in ordinary directories past the old cap. 0.22's walks never visited those directories.
- Which passes. Since every directory is now read whole, an agent-action scan, or an
ls/glob/grepthat lists a directory larger than the cap, also proves deletions there that 0.22 never proved.
Fix. Reword along these lines: "the first passes after the upgrade that reach what 0.22's walks never did push one event for each kind of change they find (created, modified, deleted), each listing every path, and a mount whose wakeOnChange admits that kind turns each into one message". Keep the note on deletions in large directories, but say it applies to any pass that lists one.
R1-2. The agent-action scan's comment says reads bring in files past the cap; for a tracked file they don't
Found by Claude only.
Where. index.ts:3013-3016: "files past them come in through syncs, and the listings and reads that reach them".
What's off. read re-observes a path only when the workspace doesn't hold it (ensureSynced, index.ts:2028-2033). Listings do re-observe what they take, through the fingerprint check. On an on-agent-action mount over its cap, then:
- a shell tool edits a tracked file past the first
walkCapentries; readserves the old copy until a sync or a listing reaches the file.
This is #340/R1-1's hazard again, for the files past the cap. 0.22 behaved the same, so this is not a regression. But this comment is where a maintainer will look to learn what keeps those files fresh, and it overstates the answer. The user-facing watch doc in types.ts gets it right: it defers to walkCap's description, which names only syncs and catch-up scans.
Fix. "files past them come in through syncs and the listings that reach them; a read takes in only a file the workspace doesn't hold yet".
R1-3. The corrected sync description has no test
Found by Sol only.
Where. index.ts:1228-1235.
What's off. The new tests pin all three reason variants, but nothing reads the sync tool's description. You could put #340's wording back ("resumes where it stopped") and every test would still pass. #340's description wasn't pinned either. Other modules do pin theirs in places, for example workspace-read-image.test.ts:313 and code-execution.test.ts:453.
Fix. Add one assert.match on the two phrases that carry the semantics, "where the last turn stopped" and the catch-up scan taking turns with whole-mount syncs. Don't snapshot the whole string.
Verified fine
-
Which passes resume. Exactly three: the bare or whole-mount sync (
index.ts:2876), a directory sync (2889), andinitialScan(1023), which runs at start and on watcher reattach (983-1004). None of these resume:- agent-action scans (
3089); - watcher path passes (
3006); - lazy reads and
settleBeforeMutation(2019,2031); - listings (
2369,2421,2499).
That matches the changelog, the
walkCapdoc and thePassOptions.resumecomment.withMountserialises every pass on a mount, so a catch-up scan and a bare sync really do alternate. - agent-action scans (
-
R1-2's edge cases.
- A mount bound by evidence and then given a new root still goes unavailable. The pass finds
rootUnavailable, so there is no walk and no place. acceptRooton a bound mount clears its places (applyRoot,reset).acceptRooton an unbound mount records the root without a reset, so its place stays. That is consistent with "a place binds no root", and the place only orders the next walk.
- A mount bound by evidence and then given a new root still goes unavailable. The pass finds
-
The durability wording. "unless the machine went down before the store made the latest place durable" holds.
RecordJournaldocuments that an append reaches the OS before it returns, so it survives a killed process (record-journal.ts:13-16). Chronicle 0.4.0'sRecordLog::appendwrites straight to the logFile. -
Journal growth (#340/R1-3's other half). It remains, as the PR body says. Each changed place appends one entry, and those entries count toward the checkpoint threshold. After R1-1, though, they come only from syncs and catch-up scans, no longer from every tool batch.
-
The changelog's other claims.
- A path sync is the immediate remedy for a change outside the window.
- "0.22's first 5000 followed the order the platform lists a directory in": 0.22 took files in
readdirorder, then subdirectories, and stopped at a file cap that didn't count links. "can reach different files" is accurate. - Going back to 0.22: a
walkentry is a no-op in 0.22's replay, its checkpoints drop places, and this version reads a snapshot withoutwalks.
-
The model test is genuinely independent. It sorts with its own
ordercomparator, computes the window itself, and asserts that nothing on disk is ever proven absent. It is seeded and fixed, so a failure replays. It runs on all four CI legs. -
CI. Run 38811805477 on this head passed all four legs: Ubuntu and macOS, each on Node 20 and 24.
A note outside this PR
walkCap still can't be set from connectome-host recipes, as the PR body says. buildWorkspaceMounts copies only ignore, maxFileSize, wakeOnChange and autoMaterialize onto each mount. The host's unknown-key check doesn't look inside workspace.mounts[], so a recipe that sets walkCap has it dropped without any warning. A recipe mount that doesn't set watch gets 'never' there. For such mounts the rotation runs only through syncs, and #340/R1-1's agent-action path never runs unless a recipe sets watch.
Method. Two independent passes. I re-verified every finding against the source before keeping it.
Sol (Codex gpt-5.6-sol, reasoning effort xhigh, read-only sandbox, no network) read the diff at this head, our #340 review, the PR body, the pre-#340 source at 3dc67b8^1, and connectome-host's main. It took 8.6 minutes and 130 commands, with 2.87M input tokens (2.68M cached) and 29.4k output tokens. It couldn't run tests, because it had no dependencies and no network. It reported three minor findings:
• the changelog's unconditional wording became part of R1-1, which both passes found;
• the untested description became R1-3;
• the connectome-host walkCap gap was inherited, and is the note above.
Claude did everything that needed a build or the network:
• built a trial merge with current main and ran the full suite there;
• ran six mutation runs, one per fix plus two on the walk's sort;
• probed store syncs with ctime trust on;
• checked the published versions on npm, the CI run, and connectome-host's recipe validation.
R1-2 and the deletion and pass-coverage parts of R1-1 came from this pass only.
…rch#376 (anima-research#272) R1-1. The changelog's upgrade note said each catching-up pass pushes a created event and a deleted event, and that a wakeOnChange mount turns each into a message. A pass pushes one event for each kind of change it finds, created, modified or deleted, and a mount turns into a message only the kinds its wakeOnChange admits. The note now says so, names the edits and deletions of tracked files past the old cap that the first passes find, and says that any pass listing a directory larger than the cap, a listing or an agent-action scan included, proves deletions there that 0.22 never proved. R1-2. The agent-action scan's comment said files past the cap come in through the reads that reach them, but a read takes in only a file the workspace doesn't hold yet (ensureSynced). It now names syncs and the listings that reach them. R1-3. Nothing read the sync tool's description, so anima-research#340's wording could come back unnoticed. A test now matches its two sentences about turns: the next sync of the same mount or directory picks up where the last turn stopped, and a watched mount's catch-up scan takes turns with its whole-mount syncs. With anima-research#340's sentence put back, it fails.
…in a large directory The changelog's upgrade note says that any pass listing a directory larger than the cap, a listing or an agent-action scan included, proves deletions there that 0.22 never proved. A test pinned it for a bare sync only; it now covers an ls and an agent-action scan the same way.
|
Replying to this review. @Anarchid All three minor points are taken in
Thank you for the trial-merge mutations and the ctime probe. Written by Gladys-2413. — Lottie-2661 |
TL;DR: the eight findings of Anarchid's review of #340 (R1-1 to R1-8), for #272's walk cap. An agent-action scan walks from the mount's start again, so what a tool batch did to the files it covers is in the workspace when the agent next looks, as it was before #340. Bare syncs, and a watched mount's catch-up scans, keep taking turns through a mount over its cap. A place binds no root and owes no store sync, the
synctool's text says how the turns go, the changelog says what the first passes after the upgrade do, and a model-based test checks the walk on random trees that change between passes.We'll merge this no earlier than 2026-10-16 12:00 UTC, after our pre-merge checks pass on its merge with
mainas it is then, unless you ask for changes before then.This PR carries the
no-changeloglabel because the changelog check counts only added fragments. Its changelog entry is its edit to #340's pendingchangelog.d/272-walk-cap.fixed.md, so 0.22.2's notes describe the walk cap once, as it ships.What changes
index.ts). It no longer resumes: it walks from the mount's start and keeps no place, as a listing does. On a mount over itswalkCap, every batch's scan covers the firstwalkCapentries in the walk's order, as every scan on 0.22 covered its first 5000 in the order the platform lists a directory in, so a file among them that a shell tool just changed is current when the agent next looks. On fix(workspace): a per-mount walk cap, and syncs and scans that resume past it (#272) #340's head, such a file was covered on about one batch in ⌈N/walkCap⌉. Bare syncs, directory syncs and a watched mount's catch-up scans (at start and when its watcher reattaches) still resume, and a watched mount's catch-up scan takes turns with its bare syncs. So on a mount over its cap, a change made while the process was down waits for the rotation to reach it, or for a sync of its path; on 0.22, the catch-up at start took such a change among the first 5000 files every time, and never one past them.reconcile.ts). Recording a place no longer binds the mount's root identity. A place only says where the next walk starts, and that walk takes its turn after it in whatever directory is the root by then. So a mount with no evidence, such as one holding only files too large to take in, is never bound, as before fix(workspace): a per-mount walk cap, and syncs and scans that resume past it (#272) #340, and replacing its root no longer leaves it unavailable untilacceptRoot. Evidence binds the root as before.disk-agreement.ts). It owes no barrier: a pass that moves only its place appends one entry and makes no store sync of its own, and the place becomes durable with the store's next sync. A lost place costs coverage, never a decision: if the machine goes down before then, the next walk starts at an earlier place. Place entries still count toward the journal's checkpoint threshold, since replay reads them; after R1-1 they come only from syncs and catch-up scans.synctool's description and the capped reason. The description says the walk takes turns: the next sync of the same mount or directory picks up where the last turn stopped, and on a mount watched continuously, its catch-up scan takes turns with its whole-mount syncs. A capped sync's reason names who resumes for its scope: for a directory, "the next sync of this directory"; for a mount, "the next sync of the mount", and on a watched mount "the next sync of the mount, or its catch-up scan if that comes first". This changes the tool block once more, in the same release that already changes it.wakeOnChangeadmits that kind turns each into one message to the agent. Any pass that lists a directory larger than the cap, a listing or an agent-action scan included, also proves deletions there that 0.22 never proved.observe.ts). Unchanged in behaviour: a directory the walk didn't list counts as left, even one holding nothing it would take, since telling them apart would take another read. The walk then keeps its place and reports the directory as not visited, and the next walk lists it on its way to the wrap. The comment where the walk decides now says so.walkCap's description (types.ts). It bounds what a walk observes, not the walk's own work: directories don't count against it, and each one the walk visits is read whole, so a tree of many directories that hold nothing is walked in full. Thewatch: 'on-agent-action'description says which entries the scan covers.Tests
All in
workspace-three-way. Each fix in code has a test that fails without it: with the rest of the change in place, each was taken out in turn.an agent-action scan takes the mount's start after every batch, and leaves the syncs' place alonereplaces the test that pinned its resuming. It edits the first file in walk order before each of three batches and reads the stored copy after each, checks that each capped scan reports its cap, that a batch's scan between two bare syncs leaves their place where it was, and that a covered file a shell tool deleted is gone after the batch. A scan that resumes again fails it.a pass that records only a place binds no root, so a replaced root is read as it isreplaces the test that pinned the binding. It follows Anarchid's probe: a pass under the cap and one over it bind no root, and after the root is replaced, the next sync reads the new directory. Binding the root for a place fails it.a pass that moves only its place makes no store synccounts the store's syncs over four passes of an unchanged mount whose place moves on each. A place that owes a barrier fails it. It runs with ctime trust off for its mount, so its count doesn't depend on how fast the test runs.the capped pass says once where the next resumes, …pins an unwatched mount's reason,a watched mount's capped sync names its catch-up scan as the other turna watched one's, anda directory sync resumes for its own scopea directory's.a whole mount's catch-up scan takes turns with its bare syncschecks the turns the description describes, andthe sync tool's description says how the walk takes turnsmatches the description's two sentences about them. With fix(workspace): a per-mount walk cap, and syncs and scans that resume past it (#272) #340's sentence put back, that test fails.a model of the walk: …. Taking out the walk's own sort, letting the stretch after the place take the place itself, or leaving a directory that holds the place off both stretches each fails it, beside the older tests that also catch them.The full suite at
7e31e2a9, on Linux, with membrane 0.5.87, context-manager 0.14.1 and chronicle 0.4.0 installed:tscis clean, Node 20.20.2 passes 2278/2278 in 144 files, and Node 24.21.0 passes 2259/2259, where--test-force-exitends some files before all their tests report (#294). This head,16f3e026, adds one test since then, which checks that a listing and an agent-action scan prove a deletion in a directory larger than the cap, and GitHub's CI run at it passes all four Build & Test legs: Ubuntu and macOS, each on Node 20 and 24.Not verified
walkCapthrough to its mounts yet, so its mounts take the default cap of 5000.Written by Gladys-2413 (Claude Opus 5.5), from Anarchid's review of #340 and Ada-1017's calls on it. Ansel-2428 reviewed its code and this description, after a round of our internal review.