# Filesystem capability and scan contract [`PRODUCT.md`](PRODUCT.md) incorporates this document as normative version 1 behavior. ## Traversal attempt model A directory entry belongs to a scan generation when its raw name is returned by a successful bounded directory enumeration before that directory reaches its end marker. For every returned name, the scanner records exactly one terminal attempt outcome: - retained or aggregated successfully; - excluded by a configured component-boundary rule; - deduplicated by trusted identity; - disappeared before metadata inspection; - permission or metadata failure; - crossed into a discovered mount; - capacity or depth failure; - cancelled before inspection. An attempt means the scanner issued the required descriptor-relative no-follow metadata operation or recorded why admission prevented it. Entries created after the end marker are outside that generation's attempted set. A removed or renamed entry produces a concurrent-change warning and incomplete affected totals. Repeated enumeration of the same raw name in one directory is a duplicate-name failure, not a second finding. The ledger is a bounded aggregate of outcome counts per root and failure class, not a retained record for every encountered object. Counter saturation reports `at least N`. The run log retains bounded examples for failures. ## Root initialization Configuration paths are lexically normalized to absolute raw paths without following symlinks. Path text is never identity. The only resolution exception is a configured Termux shared-storage entry point. Default shared-storage entries are existing members of this fixed set: - `$HOME/storage/shared` - `$HOME/storage/downloads` - `$HOME/storage/dcim` - `$HOME/storage/pictures` - `$HOME/storage/music` - `$HOME/storage/movies` - `$HOME/storage/external-1` Root initialization follows at most 40 symlinks for these entries, rejects loops, and opens the resolved directory with no-follow semantics. Unresolved, excessive, non-directory, or changed roots remain visible with a warning and are not scanned through that alias. A resolved alias deduplicates only when physical-root, mount, device, and inode identity agree. ## Mount behavior Traversal crosses mount boundaries. When an entry's mount ID differs from its parent, the scanner registers a filesystem identity domain before descending and shows the boundary in progress and details. Failure to obtain a trusted mount ID keeps the subtree reportable but makes deduplicated totals and direct mutation unavailable. A mount identity change during scanning marks both affected domains incomplete. ## Capability states Each capability has state `unknown`, `supported`, `unsupported`, or `contradicted` and confidence `none`, `observed`, or `evidenced`. - `unknown`: no complete probe has run or a transient failure prevented a conclusion; - `supported`: the current generation's operation probe succeeded; - `unsupported`: the kernel or filesystem returned a documented permanent unsupported result; - `contradicted`: observations disagree or a previously successful property fails. `observed` confidence applies only to the current open filesystem identity and generation. `evidenced` additionally requires a checked-in capable-platform result for the same operation, filesystem implementation, kernel interface, and relevant mount configuration. Safety-critical mutation requires `supported` state and `evidenced` confidence. Contradiction fails closed and emits a warning. No capability confidence survives refresh, remount, filesystem-daemon restart, or changed mount ID. ## Capability probes Identity requires stable filesystem, mount, device, inode, and type results from the opened root and one independently reopened descriptor. Allocated-block accounting requires identity plus checked `statx` or `stat` block observations and checked-in evidence for the same backing implementation; filesystem type alone is insufficient. Descriptor-relative access requires successful root-relative opens of `.` and a synthetic initialization fixture with beneath and no-symlink constraints. No-follow behavior requires a synthetic symlink fixture proving metadata and open operations inspect the entry rather than its target. Mutation capability requires isolated synthetic fixtures proving the exact regular-file, symlink, and directory operation sequence, revalidation fields, and mount behavior. A probe never mutates operator data. If no isolated fixture is available on the filesystem, mutation confidence cannot become evidenced. Transient `EINTR`, permission, capacity, disconnect, or concurrent-change failures leave the capability unknown for that generation rather than unsupported. ## Accounting details Allocated size is `st_blocks * 512` after checked conversion and includes whatever metadata or rounding the filesystem reports in `st_blocks`. The tool does not invent separate credit for metadata blocks, compressed extents, inline data, sparse holes, or allocation-unit rounding. Those properties are represented only through reliable reported blocks and capability evidence. Allocated-block accounting is reliable only when its capability state is `supported` with `evidenced` confidence on the current open filesystem identity and generation; otherwise the allocated metric is unknown for that root. “Reliable allocated size” elsewhere in the specification means exactly this enumerated state. Apparent bytes remain separate. Version 1 never emits a cross-filesystem additive reclaim estimate. It shows separate per-filesystem totals because no portable runtime probe establishes shared backing, snapshot, or extent relationships strongly enough to prevent double counting. A future cross-filesystem total requires a new specification and capable-platform evidence. ## Display truncation Display text is sanitized and shortened independently from authority bytes. When a path does not fit, retain the longest component-aligned prefix and suffix that fit with the marker `…#NNNNNNNN` between them; ASCII uses `...#NNNNNNNN`. `NNNNNNNN` is the first eight lowercase hexadecimal digits of BLAKE3 over the full raw path plus its stable finding identity. If two visible labels still collide, extend both digest fragments in two-digit steps up to 64 digits. If they still collide or the label cannot fit, show the stable finding index as `item #N`. Details always provide a lossless byte-escaped representation when the authority bytes fit. Truncated display text never authorizes mutation. ## Capacity failures Every exhausted capacity increments the affected omission counter, marks the root or result incomplete, contributes a visible warning, and records a bounded run-log example. A finding remains reviewable only when its retained identity and display record fit. It is confirmable only when every authority, manifest, effect, revalidation, and audit field fits. No capacity failure triggers allocation or silently drops a required warning.