Skip to content

fix: bound, speed, and widen the probe's recursive file walk#145

Merged
REPPL merged 4 commits into
mainfrom
fix/iss-112-114-116-walkfiles-class
Jul 26, 2026
Merged

fix: bound, speed, and widen the probe's recursive file walk#145
REPPL merged 4 commits into
mainfrom
fix/iss-112-114-116-walkfiles-class

Conversation

@REPPL

@REPPL REPPL commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Fixes the WalkFiles class — ledger issues iss-112 + iss-114 + iss-116 (all minor, all from the itd-95/96 reviews), one probe-walk overhaul in internal/core/lifeboat/probe.go so the itd-88 coverage experiment's verdicts are trustworthy.

Chained PR: base is fix/iss-117-impact-write-paths (#136) — the ledger resolves use that branch's --impact verb. Sibling PR #144 (the marker-pattern fix) shares the same base; the two are disjoint files and were built by parallel worktree-isolated implementers.

What changed

  • iss-112: per-directory reads are bounded by the shared maxDirEntries guard (the ListDir bound — one canonical constant, not a second copy), so a single directory with millions of entries can no longer balloon memory before the file cap applies. Truncation stays loud through both consuming adapters.
  • iss-114: the walk now descends via a sub-root per directory (os.Root.OpenRoot), opening each child O(1) relative to its parent's already-open handle instead of re-resolving the whole path per component. Measured on a 48,000-directory depth-30 tree: 7.07s → 1.43s, and depth-independence proven (0.96s → 1.01s for depth 10 → 30, versus 1.57s → 4.34s before). The reviewer independently re-ran the benchmark (1.31s vs 6.50s baseline). The os.Root containment guarantee survives unchanged — verified empirically: every final-component symlink (escaping or in-root) is refused, no string re-resolution anywhere, fd peak O(depth).
  • iss-116: the skip set widens from Node/Go-only to twelve ecosystem names (.git .tox .venv Pods __pycache__ build dist generated node_modules target vendor venv), so a vendored dependency's TODO is no longer cited as the project's own open question and a large dot-prefixed tree can no longer eat the file cap before src/ is reached — both consequences reproduced pre-fix and killed post-fix.
  • spc-12's skip-set and walk-cost language amended in the same change (record and surface move together).

Verification

  • Every behaviour test-first with watched failures: the bounded-read assertion, the dot-prefixed-cap-eater reproduction, vendored-marker citations, sub-root containment at depth, and a preserved faithful baseline walk for like-for-like benchmarking.
  • Independent reviews, both PROMOTE/SHIP with zero blocking findings: security re-derived containment, TOCTOU refusal, O(depth) fd discipline, and confirmed no secrets/sanitize path shares this walk (skip-set evasion stays inside the trusted-worktree model); correctness reconstructed the traversal against fs.WalkDir semantics — identical ordering, cap points, and truncation reporting. Two prose-precision notes are queued for capture once the id-allocator fix (fix: mint record ids across git refs and add a spec-id uniqueness lint #137) merges.
  • Gate run independently by the orchestrator: make preflight exit 0, go test -race ./internal/core/lifeboat/ exit 0, record-lint exit 0.
  • iss-112, iss-114, iss-116 resolved open/ → resolved/ on this branch with impact: fix.

REPPL added 2 commits July 26, 2026 05:06
WalkFiles walked a foreign source tree with fs.WalkDir over os.Root.FS(),
which had three defects the itd-95/itd-96 reviews raised:

- iss-112: every directory was read with ReadDir(-1), so one directory of
  millions of entries ballooned memory before the file cap could apply. Each
  directory is now read with a bounded ReadDir, sharing maxDirEntries as the
  one canonical per-directory guard ListDir already uses.
- iss-114: os.Root.FS() re-resolved every path from the containment root one
  component at a time, so a walk cost O(entries x depth) opens (measured 10.5s
  for a 60000-dir depth-30 tree). The walk now holds a sub-root per directory
  (os.Root.OpenRoot) and opens each child in O(1), so cost is O(entries) and
  independent of depth: a 48000-dir depth-30 tree walks in ~1.4s versus ~7s.
  The os.Root containment guarantee is unchanged - a symlink is still refused,
  never followed out of the tree, verified from a sub-root at depth.
- iss-116: the skip set covered only Node and Go. It now also skips the common
  Python (.venv, venv, .tox, __pycache__), build/distribution (target, build,
  dist), and CocoaPods (Pods) trees, so a vendored TODO is not cited as the
  project's own open question and a large dot-prefixed dependency tree cannot
  exhaust the walk cap before the project's own src/ is reached.

The depth-cap, directory-cap, file-cap, skip, and containment semantics are
preserved; the pre-existing walk tests pin them unchanged. spc-12's skip-set
and walk-cost language is amended in the same change.

Assisted-by: Claude:claude-opus-4-8
The WalkFiles class fix lands the bounded per-directory read (iss-112), the
O(1)-per-directory sub-root walk (iss-114), and the widened dependency-tree
skip set (iss-116). Move all three from open/ to resolved/ with --impact fix.

Assisted-by: Claude:claude-opus-4-8
Base automatically changed from fix/iss-117-impact-write-paths to main July 26, 2026 07:49
@REPPL
REPPL merged commit 49b28e0 into main Jul 26, 2026
12 checks passed
@REPPL
REPPL deleted the fix/iss-112-114-116-walkfiles-class branch July 26, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant