ce53fa71

Fix watch crash on attachment in a nonexistent directory

## Summary of the bug

When an attachment's path points into a directory that does not exist (for example because of a typo, like `attach typo-dir/receipt.pdf` where `typo-dir/` doesn't exist), the `watch` feature crashes.

## The test that reproduces the bug

Added scenario `centjes-gen/test_resources/check/CE_MISSING_ATTACHMENT_NONEXISTENT_DIR.cent`:

```
2023-12-05
  + attach nonexistent-directory/example.pdf
```

This is picked up by the existing golden test in `centjes-gen/test/Centjes/Report/CheckSpec.hs`, which runs `doCompleteCheck` over every `.cent` scenario and asserts a graceful, golden-comparable error.

Before the fix, the test does not just fail — it throws:

```
.../nonexistent-directory: getDirectoryContents:openDirStream: does not exist (No such file or directory)
```

which is exactly the uncaught IO exception that crashes the watch loop.

## Root cause

In `centjes/src/Centjes/Report/Check.hs`, `checkAttachment` checks whether the attachment file exists with `doesFileExist`. When it does not exist, it tries to be helpful by listing the *parent directory* with `listDirRel (parent af)` to suggest similarly-named files. If the parent directory itself does not exist, `listDirRel` throws an `openDirStream: does not exist` IO exception.

The watch loop in `centjes/src/Centjes/Load.hs` (`loadWatchedModules`) only catches `ExitCode`, so this IO exception propagates and crashes the whole watch process.

## The fix

Wrap the directory listing in `forgivingAbsence` (from `Path.IO`, already used elsewhere in the codebase) so that a nonexistent parent directory simply yields no suggestions. The normal `CE_MISSING_ATTACHMENT` error is then reported as expected, and `watch` no longer crashes.

## Things to manually check

- Run `centjes watch` on a ledger with an attachment pointing into a nonexistent directory and confirm it now reports the missing-attachment error instead of crashing, and recovers once the typo is fixed.
- Confirm the missing-attachment error message still reads well when there are no similar-file hints (no parent directory to scan).

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 1m13s 4s 4s 1m17s 1m13s
Eval 1m18s 1m48s 1m48s 3m06s 0s
Build 2m48s 26s 19s 3m07s 0s
Suite 1m13s 2m19s 1m54s 3m07s 1m13s

Timeline

0s1m20s1m30s1m40s1m50s2m2m10s2m20s2m30s2m40s2m50s3m