Skip to content

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 pattern determined-index already hand-rolls for fusing search+graph reads (“one walk, read, and frontmatter parse, feeding both”) — its WalkOpts { links, search_text, attachments } booleans and WalkedNote union 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::accept as a boxed closure isn’t Debug/Clone, unlike WalkOptions today. 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.


← Back to Backlog