Programming Language

Nocter

A self-contained systems language built around simplicity, encapsulation, and foolproof design.

/development/reviews/v0.19.0-phase-0.md

v0.19.0 Phase 0 Filesystem Traversal Review

Result: passed (2026-08-28). This review covers the public ReadDir and DirEntry contracts, Darwin directory-entry ABI boundary, stream ownership, record validation, public error mapping, native behavior, and editor behavior introduced by v0.19.0 Phase 0.

Review Criteria

The review traced:

  • every descriptor transition from successful open through end of stream, explicit close, step failure, and destruction;
  • every native record length, name length, terminator, type, and UTF-8 decision before a borrowed view or owned entry can be created;
  • ownership of syscall values, open flags, record offsets, record kinds, errno classification, public error codes, path construction, and entry storage;
  • source dependencies added to the standard-library module graph;
  • public contract and implementation-source hover, imported completion, and navigation;
  • duplicate ABI facts, path decoders, error policy, compatibility wrappers, and new compiler primitives.

Findings and Remediation

The first OS wrapper leaked syscall argument representation

The initial ordinary Darwin wrapper accepted buffer and position addresses as usize. That kept the compiler primitive private but required std/fs to construct the exact getdirentries64 pointer arguments. The accepted wrapper now takes &+[u8] and &+u64; only std/internal/os/darwin converts those values to syscall addresses. std/fs owns stream policy and record interpretation without knowing the syscall's raw argument representation.

Invalid native names were not portable filesystem fixtures

The host filesystem used during development rejected creation of an invalid UTF-8 filename before Nocter could observe it. Treating that host behavior as a skipped case would leave the required failure path unproved. The native-session test now uses the compiler's immutable source overlay to add a test source to the standard package for one generation. It constructs malformed and invalid UTF-8 record bytes through existing package-internal memory contracts, executes the real ReadDir.next body, verifies the public error codes, and verifies terminal state. No test hook or test declaration enters the shipped standard library.

New module edges triggered the reviewed-dependency guard

The public DirEntry.path contract adds fs -> path. Moving address conversion behind the Darwin contract adds internal/os/darwin -> ptr. The standard-library architecture test rejected both edges until they were reviewed and added to its explicit dependency set. The set was moved to a module constant when the additions crossed the lint's function-size boundary; dependency selection remains a single test authority.

Final Boundary Assessment

  • spec/21-practical-standard-library.md exclusively owns observable stream, entry, ordering, UTF-8, symlink, error, and terminal behavior.
  • std/internal/os/darwin exclusively owns the Darwin syscall word, open flags, record offsets, record type values, and conversion of typed arguments to raw addresses.
  • std/internal/os owns errno classification, while std/internal/io owns the stable public error code mapping. Neither decision is repeated in std/fs.
  • std/fs exclusively owns descriptor state, retry policy, native-record validation, entry ownership, UTF-8 conversion, path joining, filtering, and public stream behavior.
  • ReadDir has one terminal transition. The is_open guard issues at most one close syscall; is_finished makes every later next return none.
  • record bounds and the terminating byte are validated before constructing a slice. The offset advances before any later fallible conversion, and every failure closes the stream.
  • entry name and path storage are owned independently of the reusable native buffer.
  • LSP tests consume the same checked standard-library declarations and bodies as compilation; no editor-only declaration reconstruction was added.
  • the implementation uses the existing private generic syscall primitive. No compiler primitive, compatibility parse, duplicate decoder, or fallback path was added.

No unresolved correctness or responsibility-boundary finding remains in Phase 0 scope.

Verification

The completed tree passed with /private/tmp/nocter-v019-phase0 as the external Cargo target:

cargo test --locked --manifest-path development/compiler/Cargo.toml --workspace --quiet
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

Native acceptance covers more than one directory-record batch, dot filtering, regular files, directories, symbolic links, absent and non-directory paths, explicit close, repeated automatic drop cleanup, malformed records, invalid UTF-8 names, and terminal failure. Editor acceptance covers imported completion and navigation plus source-backed hover in both the public contract and its implementation source.