diff --git a/README.md b/README.md
index c888662..d12a674 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,16 @@
-# DroidSock
+# @cldmv/droidsock
-A complete, from-scratch implementation of the Android Debug Bridge (ADB) protocol in Node.js. This library provides full ADB functionality including device connection, RSA authentication, shell command execution, and file transfers - eliminating clicking sounds on Android TV devices!
+**DroidSock** is a complete, from-scratch implementation of the Android Debug Bridge (ADB) protocol in Node.js. This library provides full ADB functionality including device connection, RSA authentication, shell command execution, and file transfers - eliminating clicking sounds on Android TV devices!
-[![npm version]][npm_version_url] [![npm downloads]][npm_downloads_url] [![GitHub downloads]][github_downloads_url] [![Last commit]][last_commit_url] [![npm last update]][npm_last_update_url] [![coverage]][coverage_url]
+It talks to devices directly over TCP, with no `adb` binary or ADB server in between, and composes its protocol layers into a single API tree with [`@cldmv/slothlet`](https://github.com/CLDMV/slothlet), so every connected device becomes its own persistent API leaf.
-[![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
+> _ADB over the wire, in pure Node.js - no adb binary required._
+
+[![npm version]][npm_version_url] [![npm downloads]][npm_downloads_url] [![GitHub downloads]][github_downloads_url] [![Last commit]][last_commit_url] [![npm last update]][npm_last_update_url] [![coverage]][coverage_url]
> [!NOTE]
> **Current status:**
@@ -17,30 +19,26 @@ A complete, from-scratch implementation of the Android Debug Bridge (ADB) protoc
> - **File transfer**: `mkdir` / `remove` / `move` / `copy` / `chmod` / `diskUsage` / `find` / `stat` work today via shell commands. `list` prefers a binary-safe SYNC-based implementation with automatic shell fallback.
> - **Experimental**: `push` / `pull` / `pushV2` / `pullV2` / `listSync` / `listV2` / `statV2` (real ADB SYNC sub-protocol usage, both the legacy 32-bit and newer 64-bit variants), `device.reboot()`, `device.forward()` / `device.reverse()`, `device.install()` (both the classic push-then-install and modern streaming install paths), and `pairing.pair()` (Wi-Fi pairing) are all implemented - built from the ADB protocol spec and covered by unit tests (several exercised against real loopback TCP/TLS servers, not purely mocks) - but **none of them have been run against a real device yet**. See [#1](https://github.com/CLDMV/droidsock/issues/1).
+[![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
+
---
## โจ What's New
-### Latest: v2.0.0 (September 2026)
+### Latest: v2.0.3 (October 2026)
-- **๐จ Breaking**: the `device` module is now split into `device` (single-target `connect(host, port)` / `disconnect(host, port)` / `remove(host, port)`) and `devices` (collection-wide `list()` / `disconnect()` (all) / `remove()` (all) / `get(idOrLeaf)`) - connected devices are still mounted as composed API leaves at `api.devices.`. A device leaf now persists across a disconnect - `disconnect()` only tears down the socket (and stays synchronous), `connect()` on the same host:port later reconnects that same leaf without re-supplying options, and `remove()` is the new, separate "forget this device" operation (the one that's actually `async`).
-- **IPv6 support** - `device.connect()`, `discover.subnet()`, and `discover.mdns()` all accept IPv6 addresses/CIDRs now, not just IPv4.
-- **`devices.get(idOrLeaf)`** (new) - looks up a connected device leaf by `"host:port"` string or by the leaf object itself; the safe way to re-resolve a leaf reference instead of holding onto a stale one.
-- **`device.reverse()`** (experimental) - completes port forwarding with the device โ host direction.
-- **`pairing.pair()`** (experimental) - Wi-Fi pairing (SPAKE2-over-Ed25519 + TLS 1.3) for Android 11+ wireless debugging.
-- **Streaming APK install** (experimental) - `device.install()` now tries `exec:cmd`-based streaming install first, falling back to the classic push-then-install flow.
-- **SYNC V2 (64-bit)** - `pushV2` / `pullV2` / `statV2` / `listV2` lift the legacy 32-bit size ceiling, with optional brotli compression.
-- **Hardening** - closed a shell-injection gap in `devices.mjs`'s and `shell.mjs`'s convenience shortcuts, capped several unbounded device-controlled memory allocations in the SYNC V2 paths, and fixed a handful of mid-transfer disconnect/failure edge cases.
-- [View full v2.0.0 Changelog](./docs/changelog/v2/v2.0.0.md)
+- **Bundler-friendly CommonJS entry** - `index.cjs` now loads the ESM entry with a plain `require()` instead of `createRequire`, so esbuild and webpack can follow it, and on a Node.js version without `require(esm)` it fails with a clear message pointing to `import()`. The ESM entry and the API are unchanged ([#58](https://github.com/CLDMV/droidsock/pull/58)).
+- **`devcheck` no longer published** - the source-checkout-only `devcheck.mjs` and its `./devcheck` subpath export are gone from the package. It never did anything in an installed copy, but importing `@cldmv/droidsock/devcheck` now throws `ERR_PACKAGE_PATH_NOT_EXPORTED`, so remove any such import ([#58](https://github.com/CLDMV/droidsock/pull/58)).
+- [View full v2.0.3 Changelog](https://github.com/CLDMV/droidsock/blob/master/docs/changelog/v2/v2.0.3.md)
### Recent Releases
-- **v1.2.0** (September 2026) - Device discovery (`discover.subnet()` CIDR sweep, `discover.mdns()` for wireless-debugging-advertised devices, both experimental) and a shell-injection fix across every `files.*` shell-based method ([Changelog](./docs/changelog/v1/v1.2.0.md))
-- **v1.1.1** (September 2026) - Documentation formatting fix (padded slashes between adjacent code spans) - no code changes ([PR #16](https://github.com/CLDMV/droidsock/pull/16))
-- **v1.1.0** (September 2026) - Fixed the `list()`/`stat()` regression from v1.0.0, and added a binary-safe SYNC-based `list()` with shell fallback, real ADB `reboot:` support, TCP port forwarding, and local APK install ([Changelog](./docs/changelog/v1/v1.1.0.md))
-- **v1.0.0** (September 2026) - First tagged release - a callable quick-path default export (dropping `connect()`/`listDevices()`), a real test suite with measured coverage, and a full CI/release pipeline ([Changelog](./docs/changelog/v1/v1.0.0.md))
+- **v2.0.2** (October 2026) - Dev tooling only: shared CLDMV fix-headers config and a required PR check that never reports as skipped, no runtime change ([Changelog](https://github.com/CLDMV/droidsock/blob/master/docs/changelog/v2/v2.0.2.md))
+- **v2.0.1** (October 2026) - No runtime change, but `engines.node` rose to `>=22.12.0` (from `>=20.19.0`) to match the vitest 5 toolchain; also syncs the v4 workflows with the v4.29.2 templates ([Changelog](https://github.com/CLDMV/droidsock/blob/master/docs/changelog/v2/v2.0.1.md))
+- **v2.0.0** (September 2026) - Breaking: the `device` module splits into `device` and `devices`, device leaves persist across a disconnect, plus IPv6, `devices.get()`, and experimental `device.reverse()`, Wi-Fi pairing, streaming install and SYNC V2 ([Changelog](https://github.com/CLDMV/droidsock/blob/master/docs/changelog/v2/v2.0.0.md))
+- **v1.2.0** (September 2026) - Device discovery (`discover.subnet()` CIDR sweep, `discover.mdns()` for wireless-debugging-advertised devices, both experimental) and a shell-injection fix across every `files.*` shell-based method ([Changelog](https://github.com/CLDMV/droidsock/blob/master/docs/changelog/v1/v1.2.0.md))
-๐ **For complete version history and detailed release notes, see [docs/changelog/](./docs/changelog/) folder.**
+๐ **For complete version history and detailed release notes, see the [docs/changelog/](https://github.com/CLDMV/droidsock/tree/master/docs/changelog/) folder.**
---
@@ -55,16 +53,27 @@ A complete, from-scratch implementation of the Android Debug Bridge (ADB) protoc
- โ
**Port Forwarding** (experimental): `adb forward`/`adb reverse`-equivalent TCP tunneling, both directions
- โ
**APK Install** (experimental): `adb install`-equivalent local APK installation - classic push-then-install and modern streaming (`exec:cmd package install`) paths
- โ
**Wi-Fi Pairing** (experimental): `adb pair`-equivalent PIN-based pairing (SPAKE2-over-Ed25519 + TLS 1.3) for Android 11+ wireless debugging
-- โ
**Device Discovery**: Support for multiple devices via configuration
+- โ
**Device Discovery** (experimental): `discover.subnet()` CIDR sweep and `discover.mdns()` for devices advertising wireless debugging, plus support for multiple devices via configuration
- โ
**Error Handling**: Robust error handling and connection recovery
-## Installation
+---
+
+## ๐ฆ Installation
+
+### Requirements
+
+- **Node.js v22.12.0 or higher** (the package's `engines.node` floor)
+- Both `import` and `require()` are supported. `require()` loads the ESM entry through Node's synchronous `require(esm)`, which needs Node.js ^20.19.0 or >=22.12.0; on older versions, load the package with `import()` instead.
+
+### Install
```bash
npm install @cldmv/droidsock
```
-## Quick Start
+---
+
+## ๐ Quick Start
```javascript
import droidsock from "@cldmv/droidsock";
@@ -92,9 +101,13 @@ const logcat = device.logcat({
await device.disconnect();
```
-## Device Configuration
+CommonJS works the same way: `const droidsock = require("@cldmv/droidsock")` (also available as `createDroidSock`).
-Use the `references/devices.json` file to configure your devices:
+---
+
+## โ๏ธ Device Configuration
+
+The example scripts read device addresses from `references/devices.json`. The folder is git-ignored, so create the file yourself:
```json
{
@@ -114,13 +127,17 @@ Use the `references/devices.json` file to configure your devices:
}
```
-## API Reference
+---
+
+## ๐ API Reference
`droidsock(options)` (also `createDroidSock`) creates the API instance; `api.device.connect(host, port, options)` connects to a device (IPv4 or IPv6) and returns its live leaf - also reachable afterward at `api.devices["_"]` (a `.` becomes `_`, a `:` becomes `__`) - exposing connection state, shell execution/streaming, file operations (`push` / `pull` / `list` / `stat`), reboot, port forwarding, and APK install. `api.device.disconnect(host, port)` tears down one device's connection without forgetting it - reconnect later with `connect()` on the same host:port, no need to re-supply options; `api.device.remove(host, port)` forgets it entirely. `api.devices.list()` / `disconnect()` (all) / `remove()` (all) / `get(idOrLeaf)` manage the set of known devices as a whole.
-๐ **See [docs/API.md](./docs/API.md) for the full method reference**, including every option and the experimental/scope caveats on `push` / `pull` / `list` / `forward` / `reverse` / `install`.
+๐ **See [docs/API.md](https://github.com/CLDMV/droidsock/blob/master/docs/API.md) for the full method reference**, including every option and the experimental/scope caveats on `push` / `pull` / `list` / `forward` / `reverse` / `install`.
+
+---
-## Examples
+## ๐ก Examples
### Basic Usage
@@ -145,7 +162,9 @@ node examples/streaming-example.mjs top
node examples/streaming-example.mjs files
```
-## Architecture
+---
+
+## ๐๏ธ Architecture
`src/droidsock.mjs` composes the layers below into a single api tree via [`@cldmv/slothlet`](https://github.com/CLDMV/slothlet):
@@ -162,9 +181,11 @@ node examples/streaming-example.mjs files
11. **Device / Devices Layers** (`src/api/device.mjs`, `src/api/devices.mjs`): High-level per-device API composing the layers above, split by single-target (`device.connect`/`disconnect`/`remove`) vs. collection-wide (`devices.list`/`disconnect`/`remove`/`get`) operations. Each device is a real, persistent slothlet leaf at `api.devices.`, assigned there by `connect()` rather than held in a private module variable, so its methods keep working `self`/context access exactly like any other leaf - the leaf outlives any one connection, and only `remove()` unmounts it
12. **Config / Log Layers** (`src/api/config.mjs`, `src/api/log.mjs`): Shared configuration and logging
-๐ **See [docs/PROTOCOL.md](./docs/PROTOCOL.md) for wire-level protocol details** (packet structure, auth flow, SYNC sub-protocol framing, reboot/forward service usage).
+๐ **See [docs/PROTOCOL.md](https://github.com/CLDMV/droidsock/blob/master/docs/PROTOCOL.md) for wire-level protocol details** (packet structure, auth flow, SYNC sub-protocol framing, reboot/forward service usage).
-## Troubleshooting
+---
+
+## ๐ Troubleshooting
### Connection Issues
@@ -185,28 +206,71 @@ node examples/streaming-example.mjs files
- "Stream not open": Ensure connection is established
- "File not found": Check paths and permissions
-## Development
+---
+
+## ๐งช Development
The implementation is built directly from the public ADB protocol documentation (AOSP `SYNC.TXT` and the wire-protocol references), cross-checked against Google's own reference client (`google/python-adb`) where the public docs are ambiguous, and covered by a mocked Vitest suite. The core connection/shell/stream-multiplexing path has real device usage behind it; the newer SYNC-protocol and service additions (`push` / `pull` / `listSync` / `reboot` / `forward` / `install`) have not yet been run against a real device - see the status note at the top of this README and [#1](https://github.com/CLDMV/droidsock/issues/1).
-## License
+---
+
+## ๐ Documentation
-Apache-2.0 - see [LICENSE](LICENSE) for details.
+- **[API Reference](https://github.com/CLDMV/droidsock/blob/master/docs/API.md)** - every method and option, with the experimental and scope caveats
+- **[Protocol Details](https://github.com/CLDMV/droidsock/blob/master/docs/PROTOCOL.md)** - packet structure, auth flow, SYNC sub-protocol framing, reboot / forward service usage
+- **[Changelog](https://github.com/CLDMV/droidsock/tree/master/docs/changelog/)** - per-version release notes
-## Contributing
+[![CodeFactor]][codefactor_url] [![OpenSSF Scorecard]][ossf_scorecard_url] [![npms.io score]][npms_url] [![npm unpacked size]][npm_size_url] [![Repo size]][repo_size_url]
+
+---
+
+## ๐ค Contributing
This is a complete implementation of the ADB protocol. For improvements or bug fixes, please submit issues or pull requests.
+[![Contributors]][contributors_url] [![Sponsor shinrai]][sponsor_url]
+
+---
+
+## ๐ Links
+
+- **npm**: [@cldmv/droidsock](https://www.npmjs.com/package/@cldmv/droidsock)
+- **GitHub**: [CLDMV/droidsock](https://github.com/CLDMV/droidsock)
+- **Issues**: [GitHub Issues](https://github.com/CLDMV/droidsock/issues)
+- **Changelog**: [docs/changelog/](https://github.com/CLDMV/droidsock/tree/master/docs/changelog/)
+
+---
+
+## ๐ License
+
+[![GitHub license]][github_license_url] [![npm license]][npm_license_url]
+
+Apache-2.0 - see [LICENSE](https://github.com/CLDMV/droidsock/blob/HEAD/LICENSE) for details.
+
[npm version]: https://img.shields.io/npm/v/%40cldmv%2Fdroidsock.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
[npm_version_url]: https://www.npmjs.com/package/@cldmv/droidsock
-[npm downloads]: https://img.shields.io/npm/dm/%40cldmv%2Fdroidsock.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
-[npm_downloads_url]: https://www.npmjs.com/package/@cldmv/droidsock
-[github downloads]: https://img.shields.io/github/downloads/CLDMV/droidsock/total?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
-[github_downloads_url]: https://github.com/CLDMV/droidsock/releases
[last commit]: https://img.shields.io/github/last-commit/CLDMV/droidsock?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
[last_commit_url]: https://github.com/CLDMV/droidsock/commits
[npm last update]: https://img.shields.io/npm/last-update/%40cldmv%2Fdroidsock?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
[npm_last_update_url]: https://www.npmjs.com/package/@cldmv/droidsock
+[codefactor]: https://img.shields.io/codefactor/grade/github/CLDMV/droidsock?style=for-the-badge&logo=codefactor&logoColor=white&labelColor=F44A6A
+[codefactor_url]: https://www.codefactor.io/repository/github/cldmv/droidsock
+[openssf scorecard]: https://img.shields.io/ossf-scorecard/github.com/CLDMV/droidsock?style=for-the-badge&label=OpenSSF%20Scorecard
+[ossf_scorecard_url]: https://scorecard.dev/viewer/?uri=github.com/CLDMV/droidsock
+[npms.io score]: https://img.shields.io/npms-io/final-score/%40cldmv%2Fdroidsock?style=for-the-badge&logo=npms&logoColor=white&labelColor=0B5D57
+[npms_url]: https://npms.io/search?q=%40cldmv%2Fdroidsock
+[npm downloads]: https://img.shields.io/npm/dm/%40cldmv%2Fdroidsock.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
+[npm_downloads_url]: https://www.npmjs.com/package/@cldmv/droidsock
+[github downloads]: https://img.shields.io/github/downloads/CLDMV/droidsock/total?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
+[github_downloads_url]: https://github.com/CLDMV/droidsock/releases
+[npm unpacked size]: https://img.shields.io/npm/unpacked-size/%40cldmv%2Fdroidsock.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
+[npm_size_url]: https://www.npmjs.com/package/@cldmv/droidsock
+[repo size]: https://img.shields.io/github/repo-size/CLDMV/droidsock?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
+[repo_size_url]: https://github.com/CLDMV/droidsock
+[github license]: https://img.shields.io/github/license/CLDMV/droidsock.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
+[github_license_url]: https://github.com/CLDMV/droidsock/blob/HEAD/LICENSE
+[npm license]: https://img.shields.io/npm/l/%40cldmv%2Fdroidsock.svg?style=for-the-badge&logo=npm&logoColor=white&labelColor=CB3837
+[npm_license_url]: https://www.npmjs.com/package/@cldmv/droidsock
[coverage]: https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2FCLDMV%2Fdroidsock%2Fbadges%2Fcoverage.json&style=for-the-badge&logo=vitest&logoColor=white
[coverage_url]: https://github.com/CLDMV/droidsock/blob/badges/coverage.json
[contributors]: https://img.shields.io/github/contributors/CLDMV/droidsock.svg?style=for-the-badge&logo=github&logoColor=white&labelColor=181717
diff --git a/docs/changelog/v1/v1.1.1.md b/docs/changelog/v1/v1.1.1.md
new file mode 100644
index 0000000..26d3a13
--- /dev/null
+++ b/docs/changelog/v1/v1.1.1.md
@@ -0,0 +1,24 @@
+# DroidSock v1.1.1 Changelog
+
+**Release Date**: September 2026
+**Release Type**: Patch
+
+---
+
+## Overview
+
+v1.1.1 is a documentation-only release. **No runtime code changed**: the shipped `index.mjs`, `index.cjs` and `dist/` files are the same as in v1.1.0.
+
+---
+
+## ๐ Documentation
+
+### Pad slashes between adjacent code spans ([#15](https://github.com/CLDMV/droidsock/pull/15), release [#16](https://github.com/CLDMV/droidsock/pull/16))
+
+Runs of adjacent inline code spans separated by bare slashes (for example `` `mkdir`/`remove`/`move` ``) now have a space on each side of the slash (`` `mkdir` / `remove` / `move` ``) throughout `README.md`, `docs/API.md` and `docs/PROTOCOL.md`. Some Markdown renderers merge unpadded spans into one, which made the method lists hard to read. The wording and the documented API are unchanged.
+
+---
+
+## Upgrade notes
+
+- No breaking changes. This is a drop-in replacement for v1.1.0, and no runtime code changed.
diff --git a/docs/changelog/v2/v2.0.1.md b/docs/changelog/v2/v2.0.1.md
new file mode 100644
index 0000000..6b148ad
--- /dev/null
+++ b/docs/changelog/v2/v2.0.1.md
@@ -0,0 +1,76 @@
+# DroidSock v2.0.1 Changelog
+
+**Release Date**: October 2026
+**Release Type**: Patch
+
+---
+
+## Overview
+
+v2.0.1 is a maintenance release. **No runtime code changed**: `src/`, `index.mjs` and `index.cjs` are the same as in v2.0.0, so the API behaves exactly as before.
+
+The one change a consumer can see is the declared Node.js floor: `engines.node` rose from `>=20.19.0` to `>=22.12.0`, despite this being a patch release. It was raised to match the test toolchain (vitest 5), not because the library's own code needs a newer Node.js. See Breaking Changes below for who it affects.
+
+The rest of the release moves the test toolchain to vitest 5, syncs the CI and release workflows with the `CLDMV/.github` v4.29.2 templates, restores the verbatim Apache-2.0 license text, and makes the test suite more reliable under load.
+
+---
+
+## ๐ฅ Breaking Changes
+
+### `engines.node` raised to `>=22.12.0` ([#38](https://github.com/CLDMV/droidsock/pull/38))
+
+The package's declared Node.js floor moved from `>=20.19.0` to `>=22.12.0` in a patch release. The library code did not change, so it still runs on Node.js 20.19 and later, but the declaration now excludes Node.js 20.19 to 22.11:
+
+- With npm's default settings, installing on those versions prints an `EBADENGINE` warning and continues.
+- With `engine-strict=true` (or a package manager configured to enforce `engines`), installing on those versions fails.
+
+**Upgrade step:** run on Node.js 22.12.0 or later. Projects that must stay on Node.js 20.19 to 22.11 can pin `@cldmv/droidsock@2.0.0`, which has the same runtime code.
+
+## ๐ง CI & tooling
+
+### Test toolchain moved to vitest 5 ([#36](https://github.com/CLDMV/droidsock/pull/36), [#38](https://github.com/CLDMV/droidsock/pull/38))
+
+`vitest` and `@vitest/coverage-v8` moved to 5.x together. vitest 5 needs Node.js `^22.12.0 || ^24.0.0 || >=26.0.0`, so the CI test matrix now runs from Node.js 22.12.0 up to 26.
+
+### Sync the v4 workflows with the CLDMV/.github v4.29.2 templates ([#46](https://github.com/CLDMV/droidsock/pull/46))
+
+Every workflow caller under `.github/workflows/` now matches the v4.29.2 templates. New callers are `release-merge.yml` (squash-merges the approved `next โ master` release PR with its curated body as the commit message), `member-auto-merge.yml`, `dependabot-recreate.yml`, `provenance.yml` (SLSA build provenance for published releases), `pr-notify.yml` and `bundle-size.yml`, which reports how the published files change in size on each PR. The existing callers and `.github/dependabot.yml` were refreshed to the same template version. The same PR stops the bundle-size check from counting files twice.
+
+### Required PR Check no longer satisfied by a skipped run ([#50](https://github.com/CLDMV/droidsock/pull/50))
+
+On a PR from a branch in this repository, the `pull_request` run's copy of the `โ
Required PR Check` mirror job was skipped, because the push run reports the check for the same commit. GitHub counts a skipped job as passing for a required check, so a PR could look mergeable while its tests were still running. The skipped job now shows under a different name, so only the push run's result satisfies the ruleset.
+
+### Grouped Dependabot bumps ([#39](https://github.com/CLDMV/droidsock/pull/39))
+
+`vitest` + `@vitest/*`, the eslint family and the prettier family each bump in one grouped PR. These packages peer each other with major-locked ranges, so separate PRs broke `npm ci` with `ERESOLVE` whenever one moved without the others.
+
+### More reliable tests under load ([#48](https://github.com/CLDMV/droidsock/pull/48))
+
+A new Vitest setup file (`tests/setup/warm-droidsock.mjs`) composes and shuts down one droidsock instance before each test file is collected. The first instance in a file pays a one-time cold cost that was measured at 7 to 11 seconds on a busy machine, which raced the 10-second hook timeout and failed whichever test happened to run first. The device and connection tests also now assert against the real session instead of slothlet's mirror views.
+
+## ๐ License
+
+- `LICENSE` once again carries the verbatim Apache-2.0 text ([#45](https://github.com/CLDMV/droidsock/pull/45)). The license itself did not change.
+
+## ๐ง Dependencies
+
+Runtime:
+
+- `@cldmv/slothlet`: the lockfile moves from 3.15.0 to 3.20.0 (patch group bumps, including [#40](https://github.com/CLDMV/droidsock/pull/40)). The declared range stays `^3.15.0`, so consumers resolve whatever 3.x their own install picks.
+
+Dev-only:
+
+- `vitest` 4.1.11 โ 5.0.2 and `@vitest/coverage-v8` 4.1.11 โ 5.0.2 ([#36](https://github.com/CLDMV/droidsock/pull/36))
+- `@eslint/css` 1.4.0 โ 2.0.0 ([#42](https://github.com/CLDMV/droidsock/pull/42))
+- `@types/node` 26.4.0 โ 26.6.3, `eslint` 10.9.1 โ 10.11.0, `@eslint/json` 2.0.1 โ 2.1.0, `globals` 17.11.0 โ 17.12.0, `prettier` 3.9.6 โ 3.9.9, `@cldmv/fix-headers` 1.3.10 โ 1.3.12, `@cldmv/jsonv` 1.0.2 โ 1.0.9, `@cldmv/eslint-plugin-jsonv` 1.0.3 โ 1.0.10 and `@cldmv/prettier-plugin-jsonv` 1.0.1 โ 1.0.6 (grouped bumps [#32](https://github.com/CLDMV/droidsock/pull/32), [#33](https://github.com/CLDMV/droidsock/pull/33), [#41](https://github.com/CLDMV/droidsock/pull/41), [#43](https://github.com/CLDMV/droidsock/pull/43), [#44](https://github.com/CLDMV/droidsock/pull/44))
+
+## ๐ Documentation
+
+- **NEW:** [docs/changelog/v2/v2.0.1.md](./v2.0.1.md): this changelog, added after the release.
+
+---
+
+## Upgrade notes
+
+- The runtime code is identical to [v2.0.0](./v2.0.0.md).
+- Run on Node.js 22.12.0 or later to match the new `engines.node` declaration, or pin v2.0.0 if you need Node.js 20.19 to 22.11 with strict engine checks.
diff --git a/docs/changelog/v2/v2.0.2.md b/docs/changelog/v2/v2.0.2.md
new file mode 100644
index 0000000..0c5331c
--- /dev/null
+++ b/docs/changelog/v2/v2.0.2.md
@@ -0,0 +1,45 @@
+# DroidSock v2.0.2 Changelog
+
+**Release Date**: October 2026
+**Release Type**: Patch
+
+---
+
+## Overview
+
+v2.0.2 changes only development tooling and CI. **No runtime code changed**: the shipped `index.mjs`, `index.cjs` and `dist/` files differ from v2.0.1 only in their file-header comments, so the API behaves exactly as before.
+
+The release moves header maintenance onto the shared CLDMV `@cldmv/fix-headers` configuration, makes the required PR check report a real result on in-repo PRs, and brings in a set of dependency bumps.
+
+---
+
+## ๐ง CI & tooling
+
+### Shared fix-headers configuration ([#54](https://github.com/CLDMV/droidsock/pull/54))
+
+`npm run fix:headers` now runs the `fix-headers` CLI directly against a checked-in `.configs/fix-headers.json`, which extends `@cldmv/configs/fix-headers.json`. The local `tools/fix-headers.mjs` wrapper is gone. Running the shared config once rewrote the file headers across the repository into the uniform CLDMV format, which is why almost every file shows a header-only change in this release.
+
+### Run the in-repo PR mirror job instead of skipping it ([#55](https://github.com/CLDMV/droidsock/pull/55))
+
+v2.0.1 renamed the skipped copy of the `โ
Required PR Check` mirror job so it couldn't satisfy the ruleset. The job now always runs instead, and exits early with a note when the push run owns the status for that commit, so it never reports as skipped at all.
+
+## ๐ง Dependencies
+
+Runtime:
+
+- `@cldmv/slothlet`: the lockfile moves from 3.20.0 to 3.21.0 ([#57](https://github.com/CLDMV/droidsock/pull/57) / [#51](https://github.com/CLDMV/droidsock/pull/51)). The declared range stays `^3.15.0`.
+
+Dev-only:
+
+- `@cldmv/fix-headers` 1.3.12 โ 2.1.2, plus `@cldmv/configs` 1.2.1 added for the shared config ([#54](https://github.com/CLDMV/droidsock/pull/54))
+- `@cldmv/vitest-runner` 1.2.0 โ 1.5.1, `@cldmv/jsonv` 1.0.9 โ 1.1.1, `@cldmv/prettier-plugin-jsonv` 1.0.6 โ 1.1.0 and `@cldmv/eslint-plugin-jsonv` 1.0.10 โ 1.0.13 (grouped bumps [#51](https://github.com/CLDMV/droidsock/pull/51), [#57](https://github.com/CLDMV/droidsock/pull/57))
+
+## ๐ Documentation
+
+- **NEW:** [docs/changelog/v2/v2.0.2.md](./v2.0.2.md): this changelog, added after the release.
+
+---
+
+## Upgrade notes
+
+- No breaking changes. This is a drop-in replacement for v2.0.1, and no runtime code changed.
diff --git a/docs/changelog/v2/v2.0.3.md b/docs/changelog/v2/v2.0.3.md
new file mode 100644
index 0000000..66513c2
--- /dev/null
+++ b/docs/changelog/v2/v2.0.3.md
@@ -0,0 +1,53 @@
+# DroidSock v2.0.3 Changelog
+
+**Release Date**: October 2026
+**Release Type**: Patch
+**Branch**: `release/2.0.3`
+
+---
+
+## Overview
+
+v2.0.3 cleans up the CommonJS entry and the published file list. `index.cjs` now loads the ESM entry with a plain `require()`, which bundlers can follow, and fails with a clear message on Node.js versions that can't `require()` ES modules. The ESM entry and the API itself are unchanged.
+
+The release also stops publishing `devcheck.mjs`, a source-checkout-only development check, and removes its `./devcheck` subpath export. Removing an export is technically a breaking change despite this being a patch release, so it's listed under Breaking Changes below. In practice the module did nothing in an installed copy of the package.
+
+---
+
+## ๐ฅ Breaking Changes
+
+### `@cldmv/droidsock/devcheck` is no longer exported or published ([#58](https://github.com/CLDMV/droidsock/pull/58))
+
+`package.json` no longer lists a `./devcheck` export, and `devcheck.mjs` and `types/devcheck.d.mts` are no longer in the published files. Importing `@cldmv/droidsock/devcheck` now fails with `ERR_PACKAGE_PATH_NOT_EXPORTED`.
+
+The module was never part of the documented API. It has no exports; its only job is to warn a developer working in a source checkout who forgot to set `NODE_OPTIONS=--conditions=droidsock-dev`. It only acts when a `src/` folder sits next to it, and the published package has no `src/`, so importing it from an installed copy did nothing. `index.mjs` still loads it fire-and-forget and already tolerates it being missing, so the main entry is unaffected.
+
+**Upgrade step:** if anything imports `@cldmv/droidsock/devcheck`, delete that import. Nothing replaces it, because it never did anything outside this repository.
+
+## ๐ Bug Fixes
+
+### Require the ESM entry directly, and fail clearly without `require(esm)` ([#58](https://github.com/CLDMV/droidsock/pull/58))
+
+`index.cjs` used `createRequire(__filename)` to load `index.mjs`. That idiom predates Node's native `require(esm)`, and bundlers such as esbuild and webpack don't follow a `createRequire`-constructed `require` the way they follow a literal `require()` call, so a CommonJS build that bundled droidsock could miss the ESM entry.
+
+- `index.cjs` now calls `require("./index.mjs")` directly and exports the same functions as before (`module.exports` is the `droidsock` quick path, with `createDroidSock`, `DroidSock`, `ADB` and `AndroidDebugBridge` as properties).
+- On a Node.js version without `require(esm)` (before 20.19.0, or 22.0.0 to 22.11.x), `index.cjs` throws an `ERR_REQUIRE_ESM` error whose message names the supported versions and points to `import()`, instead of a bare loader error. The package's `engines.node` is already `>=22.12.0`, so this only matters for installs that ignore `engines`.
+- `index.mjs` already avoided top-level `await`, so it needed no change.
+- New `tests/cjs/entry.test.cjs` checks run under Node's own test runner after Vitest, from both `npm test` and `npm run coverage` (through the new `test:cjs` script). They check that `require()` returns the same functions as `import`, and that the version check fires when `require(esm)` is turned off. They don't call `droidsock()`, since that opens a real ADB connection.
+
+## ๐ง CI & tooling
+
+- `bundle-size.yml` no longer lists the `devcheck` files in `dist_paths`, matching the new published file list ([#58](https://github.com/CLDMV/droidsock/pull/58)).
+
+## ๐ Documentation
+
+- **NEW:** [docs/changelog/v2/v2.0.3.md](./v2.0.3.md): this changelog.
+- **NEW:** backfilled [v1.1.1](../v1/v1.1.1.md), [v2.0.1](./v2.0.1.md) and [v2.0.2](./v2.0.2.md).
+- README restructured to the standard CLDMV layout, with a new Requirements section that states the Node.js floor for `import` and `require()`.
+
+---
+
+## Upgrade notes
+
+- If anything imports `@cldmv/droidsock/devcheck`, remove that import. Nothing else needs to change.
+- `import droidsock from "@cldmv/droidsock"` and `require("@cldmv/droidsock")` both work as before on Node.js 22.12.0 or later.