Skip to content

fix(workspace): the findings of #340's review (#272) - #376

Merged
nissa-seru merged 5 commits into
anima-research:mainfrom
nissa-seru:gladys/340-followups
Oct 16, 2026
Merged

nissa-seru merged 5 commits into
anima-research:mainfrom
nissa-seru:gladys/340-followups

Conversation

@nissa-seru

@nissa-seru nissa-seru commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

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 sync tool'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 main as it is then, unless you ask for changes before then.

This PR carries the no-changelog label because the changelog check counts only added fragments. Its changelog entry is its edit to #340's pending changelog.d/272-walk-cap.fixed.md, so 0.22.2's notes describe the walk cap once, as it ships.

What changes

  • R1-1, the agent-action scan (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 its walkCap, every batch's scan covers the first walkCap entries 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.
  • R1-2, a place and the root (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 until acceptRoot. Evidence binds the root as before.
  • R1-3, a place's journal entry (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.
  • R1-4, the sync tool'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.
  • R1-5, the changelog. It says that on a mount over 5000 entries, the first syncs and catch-up scans after the upgrade catch up on what 0.22's walks never reached: files past the old cap, and edits and deletions of tracked files there. Each such pass pushes one event for each kind of change it finds, each listing every path, and a mount whose wakeOnChange admits 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.
  • R1-6, a cap used up by the last entry (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.
  • R1-7, 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. The watch: 'on-agent-action' description says which entries the scan covers.
  • R1-8, a model of the walk. A test runs the walk on 25 seeded random trees for 12 passes each, with entries added and removed, the place itself removed and whole directories removed between passes, names that sort apart by UTF-8 byte and by UTF-16 code unit, and dangling links. Each pass must take exactly the cyclic window after its place, worked out independently, prove nothing on disk absent, and keep a place whenever it left anything untaken, the place always being the last entry it took.

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.

  • R1-1: an agent-action scan takes the mount's start after every batch, and leaves the syncs' place alone replaces 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.
  • R1-2: a pass that records only a place binds no root, so a replaced root is read as it is replaces 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.
  • R1-3: a pass that moves only its place makes no store sync counts 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.
  • R1-4: 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 turn a watched one's, and a directory sync resumes for its own scope a directory's. a whole mount's catch-up scan takes turns with its bare syncs checks the turns the description describes, and the sync tool's description says how the walk takes turns matches 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.
  • R1-8: 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: tsc is clean, Node 20.20.2 passes 2278/2278 in 144 files, and Node 24.21.0 passes 2259/2259, where --test-force-exit ends 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

  • No host ran this change. connectome-host doesn't pass walkCap through 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.

Gladys-2413 added 2 commits October 15, 2026 09:24
…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.
@nissa-seru nissa-seru added the no-changelog Exempts this PR from the changelog check (internal-only change) label Oct 15, 2026
@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5 Tier: apex

[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

  1. P2 Sync count depends on timing ▶
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.

Summary

Restores agent-action scans to the mount’s start while keeping syncs and catch-up scans in their shared rotation.

  • Agent-action scans start over while syncs share a rotating place.
  • A walk’s saved place no longer binds the mount’s root.
  • Place-only passes stop forcing a store sync.

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');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 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.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Anarchid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 resume flag removed from the agent-action scan (R1-1);
  • one line removed from the place path (R1-2);
  • the unsynced guard (R1-3);
  • the reason text, and the catchUpScan field 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. emitFsEvents groups 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.
  • Which messages. onProcess turns an event into a message only when wakeOnChange admits that op (index.ts:1354-1356). A mount with wakeOnChange: ['modified'] gets no message for created or deleted.
  • 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/grep that 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 walkCap entries;
  • read serves 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), and initialScan (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 walkCap doc and the PassOptions.resume comment. withMount serialises every pass on a mount, so a catch-up scan and a bare sync really do alternate.

  • 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.
    • acceptRoot on a bound mount clears its places (applyRoot, reset).
    • acceptRoot on 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.
  • The durability wording. "unless the machine went down before the store made the latest place durable" holds. RecordJournal documents that an append reaches the OS before it returns, so it survives a killed process (record-journal.ts:13-16). Chronicle 0.4.0's RecordLog::append writes straight to the log File.

  • 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 readdir order, 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 walk entry is a no-op in 0.22's replay, its checkpoints drop places, and this version reads a snapshot without walks.
  • The model test is genuinely independent. It sorts with its own order comparator, 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.

Gladys-2413 added 2 commits October 15, 2026 22:59
…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.
@nissa-seru

Copy link
Copy Markdown
Contributor Author

Replying to this review.

@Anarchid All three minor points are taken in 7e31e2a9, with one more test in 16f3e026.

  • R1-1. The upgrade note now says each catching-up pass pushes one event for each kind of change it finds (workspace:created, workspace:modified or workspace:deleted), each listing every path. A mount whose wakeOnChange admits that kind turns each into one message, and the first passes find edits and deletions of tracked files past the old cap too. It also 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 now names syncs and the listings that reach a file past the cap, and says a read takes in only a file the workspace doesn't hold yet.
  • R1-3. A test now matches the sync description's two sentences about turns. With fix(workspace): a per-mount walk cap, and syncs and scans that resume past it (#272) #340's sentence put back, it fails.

Thank you for the trial-merge mutations and the ctime probe.

Written by Gladys-2413.

— Lottie-2661

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog Exempts this PR from the changelog check (internal-only change)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants