# Contributing to dsh-hindsight-daemon Thanks for taking the time to help. This plugin sits on a seam between three moving parts — DSH's Cordis tree, the Hindsight Python daemon, and an embedded PostgreSQL — so a small change can look harmless and still leave orphan processes behind. ## Before opening a change Read [`docs/architecture.md`](docs/architecture.md) first. It explains why the plugin does some things that look redundant (three exit channels, two ways to stop the daemon, `pg_ctl` instead of `daemon stop`). Most "simplifications" there have already been tried and reverted; the doc says why. A few hard constraints: - **Zero runtime dependencies.** Config reading/writing, the settings page, and the HTTP routes are all hand-rolled on purpose. Public npm versions of the DSH packages do not match the versions bundled inside DSH, and binding to them makes the plugin break on every DSH upgrade. - **Cleanup must stay synchronous.** Signal handlers cannot await. Anything the exit path needs must work with sync calls (`spawnSync`, `readFileSync`) inside a 5 second grace window. - **Never let the plugin stop DSH from starting.** Initialisation errors are caught and degrade to "no settings page, lifecycle still works"; a missing `webServer` is polled, not required. ## Development workflow No `npm install` is needed — there is nothing to install. ```bash npm test # node --test, 40 assertions, ~1s npm run check # node --check on every entry point ``` Run a single file: ```bash node --test tests/units.test.mjs node --test tests/packaging.test.mjs ``` Optional lint and pack checks: ```bash npm run pack:dry # verify the files whitelist ``` To exercise the plugin inside a live DSH instance, mount it from a profile's `cordis.patch.yml` (see the README's "Manual" install) and set `DSH_HINDSIGHT_DEBUG=1` so the exit path writes `~/.dsh/hindsight-daemon/debug.log`. ## Test conventions - Tests are `node:test` files under `tests/`, named `*.test.mjs`. - **Every test must sandbox `HOME`, `USERPROFILE` *and* `DSH_HOME`** into a fresh `mkdtemp` before importing plugin modules. Miss `DSH_HOME` and the test will read the developer's real config, launch a real daemon and then kill it (this exact bug cost a test file 46 seconds and one maintainer's running daemon). - Import order matters: set the environment variables, *then* `await import(...)`. - Tests must pass on both Windows and Linux; branch on `IS_WINDOWS` rather than assuming a path separator or an executable suffix. - `tests/packaging.test.mjs` guards the boring-but-fatal invariants (files whitelist, bundle patch ids, PowerShell BOM, README links). If you add a doc file, link it from the README — the test will fail otherwise. ## Compatibility - Node.js ≥ 22, DSH Desktop 2.0.x, Windows 10/11 or Linux x86_64. - The settings page is a hand-written browser bundle loaded by DSH's `__ModuleLoader__`; it must not `import` anything except `react` / `react/jsx-runtime`. - Behaviour that differs per platform belongs in `lib/core/platform.js`, not scattered through call sites. ## Pull requests - One topic per PR. Structural refactors and behaviour changes are easier to review apart. - Include the reason, not just the diff — especially for anything touching the exit path, where the observable symptom (an orphan `pythonw` process) shows up minutes later. - Add or update a test for behaviour changes. If something genuinely cannot be tested without a live daemon, say so in the PR description. - Windows and Linux both need to work. Say which one you actually ran.