Fail on empty scenario directories, and scenarios that are directories
An empty `scenarioDir` suite now fails, and scenarios can be directories.
### Fail on an empty scenario directory
An empty scenario directory defined no tests at all, so a suite whose scenario files went missing, left out of `extra-source-files` or behind a mistyped path, reported success. `scenarioDir` and `scenarioDirRecur` now define a single failing test when they find no files. An absent directory takes the same path, because `forgivingAbsence` already turns absence into an empty list.
This is the reasoning that already makes an empty test suite fail, applied one level down.
### `scenarioDirOfDirs`
A scenario often consists of more than one file: an input and the output it must produce, a config and a golden rendering of it. The two existing definers can only hand a single file to the test definition, so such a suite had to reconstruct the grouping by hand.
```haskell
scenarioDirOfDirs "test_resources/same" $ \fp ->
it "contains two files with the same contents" $ do
a <- readFile (fp </> "a")
b <- readFile (fp </> "b")
a `shouldBe` b
```
Each subdirectory is one scenario, whatever it contains. Files in the given directory itself are ignored, and so is any nesting below the subdirectories. There is no recursive variant, because a scenario directory has no obvious depth at which to stop.
The three definers now share a helper parameterised over how it lists scenarios, so the empty case behaves identically for all of them.
### A separable third commit
`Test.Syd.TimingSpec.long diff timing is bounded` failed in two of three `nix flake check` runs here, unrelated to the above; the first failure predates the `scenarioDirOfDirs` work. The test bounds its inner run at 120s, deliberately generously, so that it fails only if the 2s diff timeout stopped working. The default test timeout is 60s, so on a machine slow enough for that bound to matter the suite killed the test first: `Timeout!` after ~65s in the nix sandbox, while printing the two 100k-element lists. The last commit raises the timeout for that one test above the bound it asserts. Drop that commit if you would rather handle it separately.
### Testing
`test_resources/same/{numbers,words}/{a,b}` exercises the real path. Beyond that, `ScenarioSpec` builds specs with `execTestDefM`, runs them, and asserts over `computeTestSuiteStats`: the empty and absent directories produce exactly one failure and no successes, and a directory holding one subdirectory, a nested subdirectory inside it, and a loose file produces exactly one scenario. The empty-directory tests fail against the unmodified library, and the nesting test fails if the lister is swapped for `listDirRecurRel`.
`stack test sydtest-test --pedantic` passes, and `nix flake check` passes on a run that rebuilt most of the tree in parallel, which is the load that previously exposed the timing flake.
### Breaking
`scenarioDir` and `scenarioDirRecur` now fail where they previously defined nothing, so sydtest is bumped to 0.28.0.0.