# Changelog

All notable changes to `dev-cockpit` are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] — 2026-05-10

First pre-1.0 release. The public surface (`Profile` interface with `boot` lifecycle hook, `buildCli`, the four core commands `dev / doctor / init-config / mount`, the `cockpit.yaml` schema with `version: 1`) is stable enough for first consumers to depend on. Expect minor churn until the post-1.0 roadmap items land.

### Added

- **Interactive `init-config` wizard** (`-i` / `--interactive`). Seven-step onboarding with project sniffing — auto-detects compose files + services, `package.json` scripts as watcher candidates, npm/yarn/pnpm workspaces as repo entries, and surfaces sensible defaults so most prompts just need an enter. Closes by offering to run `doctor` immediately.
- **`profile.boot` lifecycle hook**. Profiles return `{cockpitHandlers, subscribeFsEvents, cleanup}` from a single async function called after config load + workspace resolution and before the cockpit renders. Replaces the older "profile registers its own dev command" override pattern.
- **`profile.reposProvider(ctx)` receives the wizard context** so profiles can drive the Repos pane from their validated `profile.<appName>` namespace.
- **`killAllSpawned()` global subprocess registry** — every `spawnStream` auto-registers + auto-deregisters; `killAllSpawned()` SIGTERMs stragglers, awaits reap, falls back to SIGKILL after 1.5s. Eliminates the "second Ctrl-C needed to quit" class of bugs.
- **Periodic poll for `docker`-trigger health checks** (default 5s, configurable via `SchedulerDeps.dockerPollIntervalMs`, set 0 to disable). `docker compose down` mid-session now flips `container-running` / `port-open` checks red within the poll interval.
- **Synthetic test fixtures** under `tests/fixtures/`: `plain-node` (no docker block; tsc watcher; http-ok + file-exists checks) and `dockerized` (alpine heartbeat + redis; container-running + port-open checks). Smoke tests via `ink-testing-library`.
- **Generic CLI commands** — `dev / doctor / init-config / mount` — with `buildCli({ profile? })` factory. Profile-first registration: `setupCli(program)` runs before core, claimed names skip their core counterpart (one mechanism, no array mutation).
- **Health framework** with five built-in check types (`container-running`, `port-open`, `http-ok`, `file-exists`, `exec-zero`), `useHealth` hook orchestrating the scheduler + transition diffing + remediation dispatch, per-item `notify` overrides.
- **Watcher subsystem** (chokidar lazy-spawn, reactive lint, transition-only build notifications).
- **Docker subsystem** (log tailer with live-check, highlight engine, stack-trace extractor, restart helper).
- **Cockpit shell** — four-pane TUI (Repos / Output / Health / Help), tab nav, modals (filter / search), live-markdown Help loader.
- **Core modules** — config loader (zod + `version: 1` schema), state paths (`xdg_state_home/<appName>/<hash>/`), pino logger, execa subprocess wrapper, OS notifier (detached `osascript` / `notify-send` so the helper doesn't keep the parent loop alive).

### Changed

- **OS notifier no longer uses `node-notifier`.** Direct `child_process.spawn` with `detached: true` + `stdio: 'ignore'` + `unref()` so notification helpers run independently of the cockpit's lifetime.
- **`DockerLogTailer.stop()` and `WatcherManager.stop()` await child SIGTERM reap** before resolving (previously sent the signal and returned immediately, leaving handles in the event loop).
- **Bin shim filters Node 22's `ExperimentalWarning: Importing JSON modules`** (cli-boxes uses `with {type: 'json'}`). Filtered at the bin level via dynamic-import-after-emitWarning-hook.

### Fixed

- Per-phase exit cleanup so the shell prompt returns immediately on `q` — no more "second Ctrl-C needed to quit".

## [0.0.0] — early lifts

Initial scaffold + the phase 2-6 lifts of the cockpit shell + watcher / docker / health subsystems into a generic, domain-neutral library. Captured here for completeness; commit history in git is the authoritative record.
