v0.19.0 Phase 3 Recursive Text Search Review
Result: passed (2026-08-28). This review covers the complete examples/text-search package, its exclusive use of public standard-library contracts, recursive resource lifetime, deterministic output, streaming storage bound, recoverable error path, native process behavior, test-fixture authority, and editor behavior introduced by v0.19.0 Phase 3.
Review Criteria
The review traced:
- every directory descriptor from open through iteration, explicit close, recursion, failure, and destruction;
- every discovered entry through classification, owned full and display paths, ordering, file opening, line buffering, matching, and output;
- argument absence, process encoding failure, traversal failure, file failure, invalid UTF-8, output failure, no match, and match exit paths;
- retained storage while discovery and file scanning proceed;
- imports and operation selection for every application dependency;
- package discovery plus hover and navigation through the ordinary language-server workspace;
- private standard-library escape hatches, compiler primitives, whole-file input, duplicated path or UTF-8 policy, compatibility wrappers, and application-specific compiler behavior.
Findings and Remediation
The public-example fixture assumed one flat input file
The existing execution contract could supply only one temporary file and identify it through a special argument variant. That model could compile the recursive package but could not prove its actual behavior. The fixture authority now represents a list of files, directories, and symbolic links, while arguments name paths relative to one temporary fixture root. Existing examples use the same generalized model. Materialization rejects empty, absolute, parent, and prefix-bearing entry paths before touching the filesystem; text-search receives no dedicated test runner or hidden setup path.
A body-only main was not an executable-module declaration
The first package placed main only in the seen implementation source. Executable selection correctly requires the root module to declare its entry. Making an omitted-body main public would have exposed implementation structure solely to satisfy contract/body matching. The completed root instead contains the trivial private main body and delegates to the directly visible private run implementation. This follows the index style rule: a trivial body may remain at the surface, while nontrivial implementation stays in its source file.
Parent directory streams must not remain open during recursion
Recursing directly from ReadDir.next would retain one open descriptor per tree depth. Discovery now collects child directories, reaches clean end, closes the stream explicitly, sorts those owned paths, and only then recurses. A step failure returns through ordinary destruction, which closes the same stream once. At most one directory descriptor is open during traversal.
Final Boundary Assessment
examples/text-search/README.mdexclusively owns the application's observable CLI contract. Language and standard-library behavior remain inspec/21-practical-standard-library.md.std/fsowns classification, symlink facts, path joining, entry encoding, and directory lifetime. The application switches onFileTypeand never reinterprets a target record.std/io/bufferowns partial reads, line delimiters, UTF-8 validation, and terminal input state. The application retains one reusable destination and never sees raw refill state.[T].sortowns ordering mechanics.Vec<SearchPath>reaches it through the existing readwrite coercion and oneSearchPathstrict-order declaration; the application has no second sort.- discovery retains exactly one full and one relative owned path per regular file plus pending directory paths. File scanning retains one fixed reader buffer and storage proportional to the largest line, not total file contents.
- successful match output is deterministic because complete relative file paths are sorted before scanning. Lines remain in source order. Symlinks and non-regular entries cannot enter either the file list or recursive directory list.
- failure context adds the relevant directory or relative file while preserving the standard root
code. Usage and failure reporting share public
stderrplusWriter; matches share one publicstdouthandle. - exact process acceptance covers all three status classes, nested path ordering, multiple matches, no match, missing root, invalid UTF-8, and a recursive symlink loop.
- the real package source is opened under ordinary package workspace analysis. Hover reaches the
authored
read_dirandread_line_intocontracts, while navigation for Vecsortreaches the slice contract. No editor-only declaration is constructed. - no compiler primitive, standard-library source, private import, compatibility behavior, or application-specific semantic branch was added.
No unresolved correctness or responsibility-boundary finding remains in Phase 3 scope.
Verification
The completed tree passed with /private/tmp/nocter-v019-phase3 as the external Cargo target:
cargo test --locked --manifest-path development/compiler/Cargo.toml --workspace
cargo clippy --locked --manifest-path development/compiler/Cargo.toml \
--workspace --all-targets -- -D warnings
cargo fmt --manifest-path development/compiler/Cargo.toml --all -- --check
node docs/build-docs.js
git diff --check