readJSON's fallback was whole-file-only: it returned the fallback
object only when the file read/parse threw. If .wolf/config.json
exists and parses but is missing a nested section (e.g. an older
config written before dashboard/daemon/cron were added), every
accessor like `config.openwolf.dashboard.port` throws
`TypeError: Cannot read properties of undefined`.
Make readJSON deep-merge the parsed value over the fallback:
loaded values always win, but missing nested keys fall through to
the caller-supplied defaults. Arrays and scalars are replaced
wholesale — only plain objects are merged. File read/parse
failures still return the fallback as-is (unchanged behavior).
Net effect: every existing readJSON call site becomes tolerant of
older/partial configs without any call-site changes. Fixes
`openwolf dashboard` and `openwolf daemon *` crashes when a user's
.wolf/config.json predates a section the current release reads.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ported from upstream cytostack/openwolf. Needs review before merge.