B-9DTY-a-vaultsource-trait-separate-the-walk-contract-from-its
determined-fs::walk today is a concrete implementation (walkdir + a policy struct) with no interface in front of it. The walk-convergence work (#1344) unified selection across the fleet’s two vault walks but left ordering hardcoded to callers and per-entry work unaddressed — both were sketched as a follow-up design in that PR’s review comments and never captured as a task.
The sketch has three pieces:
- A source trait. Enumerate entries under a scope, with a filesystem impl behind it — opening the door to in-memory test vaults, a git tree, an archive, without touching real disk.
- Selection and ordering, declared in the contract. Not baked into the walk function the way they are today — a comparator becomes something a caller states rather than inherits silently.
- A visitor/responder hook over a memoised per-entry
Body, so N readers of one entry cost one read. This is the patterndetermined-indexalready hand-rolls for fusing search+graph reads (“one walk, read, and frontmatter parse, feeding both”) — itsWalkOpts { links, search_text, attachments }booleans andWalkedNoteunion struct are exactly what a visitor seam would replace, and it’s the only call site with a measured, proven fusion to generalize from rather than a hypothetical one.
Recommended first migration target: determined-index, for the reason above. Worth an early
look too: the Search + Graph capabilities’ pending accessor-wiring work (tracked in the
node-to-rust migration plan) is probably the best next place to apply this lens, since
determined-index’s own walk already fuses multiple readers over one traversal — the exact shape
the trait is meant to generalize.
Open questions from the sketch, not yet answered:
- Is
&mut [&mut dyn Visit](object-safe, dynamic dispatch per entry) fast enough, or does a generic/tuple form pay for itself? Needs measuring on a real vault before choosing. - Who decides “survive one unreadable file” — the walk, or each visitor?
Select::acceptas a boxed closure isn’tDebug/Clone, unlikeWalkOptionstoday. Worth a small enum for the common cases with an escape hatch, or is losing those derives acceptable?
Not proposed: a cross-capability responder registry fusing OCR/media/photos into one traversal —
they run at different times on separate user actions and their expensive work isn’t shared anyway
(Vision, pixel hashing). The visitor seam is worth building where a fusion is already proven
(determined-index), not speculatively across capabilities.