dd5e2ffa

Ask what a directory is, not what it is called

Independent of the rule stack. #13, #11 and #12 do not need it.

The discovery walk skipped any directory whose name started with `result`, meaning to skip a nix build output:

```haskell
|| "result" `isPrefixOf` name
```

It also skipped one called `results`, and every package under it went missing from discovery **with nothing reported**. That is the part that makes it worth a PR rather than a line: a walk that finds no cabal file and a walk that refused to look return the same answer to a caller, so the packages simply were not there.

The regression test fails on master with `Right []` where it wants `Right [PackageName "thing"]`. I checked that before keeping the fix.

## What it asks instead

A nix build output is a symlink into the store, so that is the question now. It covers `result`, `result-1`, `result-doc` and anything else linked in from elsewhere, and it is the better question anyway: what is on the far side of a symlink is not this repository's, and following one is how a walk here reports another repository's packages as this one's. The neighbouring comment already worried about exactly that hazard for nested packages.

The two build directories are still skipped by name, because they are real directories rather than links, and so is anything hidden. Those compare whole names.

## Testable

Both predicates are top-level and exported, where the walk had one in a `where` clause with no signature and no test:

- `skippedByName :: Path Rel Dir -> Bool` is pure, so the prefix case is a unit test rather than a walk over a fixture.
- `descendInto :: Path Abs Dir -> IO Bool` needs the one IO question.

185 tests, 7 new: the named and hidden cases, the four prefix lookalikes, two symlink cases over a temp directory, and the fixture with a package two levels under `results`.

## One thing worth knowing

The fixture needed a line in `.gitignore`. Your global ignore file has `result*`, which hides a directory called `results` exactly the way this walk did — this repository's own `.gitignore` gets it right with `result` and `result-*`. Same bug, one level up; you may want to fix it there too, since it silently untracks anything named that way in every repository.

## Review loop

```
nix flake check
nix develop --command cabal test hopinion-test --test-options="--ai-executor"
```

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 27s 1s 1s 28s 27s
Eval 39s 9s 9s 48s 10s
Build 48s 0s 0s 48s 0s
Suite 27s 10s 21s 48s 37s

Timeline

0s40s