Summary
CHANGELOG.md's [Unreleased] section documents 7 of the ~40 commits merged since v0.24.2. A whole new CLI subcommand (mcp-debugger doctor), a Docker-only debugging fix, two behavior changes, a new opt-out env var, and the supply-chain attestation work are all merged and shipping but undocumented. The section also has a malformed heading structure.
This should be reconciled as part of v0.25.0 release prep — the release notes are generated from this section, so whatever is missing here is missing from the release.
1. Malformed section structure
[Unreleased] currently reads:
## [Unreleased]
### Changed
### Fixed <- first block
### Added
### Fixed <- second block, duplicate category
Two ### Fixed blocks around one ### Added. Keep a Changelog expects at most one block per category per release, and the split means a reader (or any tooling that parses by heading) sees only whichever half it reaches first. The two blocks should be merged, and the conventional order is Added → Changed → Fixed.
2. Merged but undocumented
Verified by diffing git log v0.24.2..HEAD against the [Unreleased] body. Grouped by how user-visible they are.
New user-facing surface — highest priority
| Change |
Commits |
mcp-debugger doctor CLI subcommand — doctor [languages...] --json --timeout <ms>, per-language toolchain/backend verdicts, host-platform checks (Yama ptrace_scope, container workspace mount), exit code gated on requested languages, schemaVersion: 1 JSON. Plus the new IAdapterFactory.describeToolchain() extension point and typed IAdapterRegistry surface |
7cca1d72, 17d9ef79, 9699ee20, 40bf1927, 66885f1f (#423, #435) |
New docs/diagnostics.md — first complete environment-variable reference; corrects setup-guide's table (was missing RUBY_PATH/RDBG_PATH/CODELLDB_PATH and wrongly listed DLV_PATH, which the Go adapter never honored) |
17d9ef79 (#423 part 2) |
Docker Rust type summaries — image vendors lib/rustlib/etc and sets CODELLDB_RUST_SYSROOT; &str/String/Vec previously rendered as raw LLDB internals in the container. Also: user-supplied _adapterSettings now passes through instead of being dropped, and a new annotateOutputEvent policy hook attributes CodeLLDB's "Failed to initialize language support" line |
0f7b4798 (#441) |
Behavior changes callers can observe
| Change |
Commits |
DAP_TRACE is now opt-in — per-session dap-trace-<id>.ndjson was previously always-on, synchronous and uncapped; now off by default, DAP_TRACE=1 enables, DAP_TRACE_FILE=<path> overrides, capped at 50 MB. The per-session proxy-<id>.log also stopped being hardcoded to debug and now honors --log-level/DEBUG_MCP_LOG_LEVEL |
a5fb26f0 (#410) |
list_threads no longer retargets the stopped thread — ProxyManager adopts threads[0] as currentThreadId only when no thread is anchored, so list_threads and internal polls can't redirect a subsequent stackTrace/scopes/evaluate. Also tool:response logging now mirrors the payload's real success instead of hardcoding true |
2014358c (#396, #397, #407) |
tools/list no longer imports all 9 adapters — availability is now a metadata-only on-disk probe. Worth documenting the trade-off: a present-but-broken package now reports installed: true and only errors at first load (doctor is what surfaces it) |
375ec584 (#409) |
New MCP_SKIP_ORPHAN_REAPERS=1 opt-out for PID-namespaced containers; reapers now share one process scan, run only for stdio/sse/http commands (so --version no longer pays), and the janitor sweeps stale session run dirs older than 7 days |
91893879 (#411) |
Release / supply chain — release-prep relevant
| Change |
Commits |
Docker image is now attested (gh attestation verify oci://index.docker.io/debugmcp/mcp-debugger:<tag> --repo debugmcp/mcp-debugger) and the PyPI launcher migrates to trusted publishing with PEP 740 attestations. Note the ordering constraint: the PyPI trusted publisher must exist before the tag |
0e73344d (#422) |
Reproducible builds — fetchedAt/downloadedAt timestamps dropped from shipped vendor outputs, so two clean builds produce byte-identical vendor trees and tarballs |
b421391f (#421) |
Infrastructure and hardening
| Change |
Commits |
Weekly canary workflow installing published npm/Docker artifacts and running a real debug cycle (scripts/canary-smoke.mjs); doubles as the release gate in docs/release-checklist.md |
94ea158b (#425) |
Weekly kind smoke job exercising both documented Kubernetes attach patterns against published artifacts (scripts/k8s-smoke.mjs) |
94c45fe7 (#451) |
js-debug vsDebugServer orphans reaped — argv tagged with --mcp-owner-pid/--mcp-session-id, third janitor matcher, win32 tree-kill of the worker while alive |
6e319571 (#431) |
Debugging skill + in-band instructions/debugging-workflow prompt point at the Kubernetes recipe and mention pathMappings |
0d9400c2 (#452) |
ROADMAP.md published (path to 1.0) |
ce2832a1 (#426) |
Proxy/DAP hardening: bounded DapFrameDecoder frames with linear accumulation (#413), bounded remaining worker collections (#414), HTTP per-session loggers detached from the shared file transport on stop() (#412), dangling-rejection elimination (#420) |
0b8e2a94, f037e994, 0ef2b9a5, af080fb9 |
| Lazy-import SSE/HTTP transport stacks in CLI actions (startup perf) |
74b329b7 (#408) |
scripts/mem-bench.mjs + advisory weekly memory-footprint workflow |
9ba7c9d8 (#406) |
Judgement call on the last group — the hardening and perf items may be fine to fold into one summary line rather than enumerate. The first three groups should be written out.
3. Root cause
docs/release-checklist.md verifies that the changelog has a dated entry and that [Unreleased] is empty at the top (lines 9–10), but nothing checks that [Unreleased] actually covers what merged. So entries are only ever added when the authoring PR remembers, and the ones that forgot are invisible until release time.
Suggested addition to the pre-release section of the checklist:
- [ ] `[Unreleased]` reconciled against `git log <last-tag>..HEAD` — every user-facing
change has an entry, and each category appears at most once
Proposed fix
- Merge the two
### Fixed blocks and order the section Added → Changed → Fixed.
- Backfill the entries above, writing out at least the "new user-facing surface" and "behavior changes" groups.
- Add the reconciliation step to
docs/release-checklist.md.
Found while auditing local test-harness coverage against the changelog ahead of v0.25.0.
Summary
CHANGELOG.md's[Unreleased]section documents 7 of the ~40 commits merged sincev0.24.2. A whole new CLI subcommand (mcp-debugger doctor), a Docker-only debugging fix, two behavior changes, a new opt-out env var, and the supply-chain attestation work are all merged and shipping but undocumented. The section also has a malformed heading structure.This should be reconciled as part of v0.25.0 release prep — the release notes are generated from this section, so whatever is missing here is missing from the release.
1. Malformed section structure
[Unreleased]currently reads:Two
### Fixedblocks around one### Added. Keep a Changelog expects at most one block per category per release, and the split means a reader (or any tooling that parses by heading) sees only whichever half it reaches first. The two blocks should be merged, and the conventional order is Added → Changed → Fixed.2. Merged but undocumented
Verified by diffing
git log v0.24.2..HEADagainst the[Unreleased]body. Grouped by how user-visible they are.New user-facing surface — highest priority
mcp-debugger doctorCLI subcommand —doctor [languages...] --json --timeout <ms>, per-language toolchain/backend verdicts, host-platform checks (Yamaptrace_scope, container workspace mount), exit code gated on requested languages,schemaVersion: 1JSON. Plus the newIAdapterFactory.describeToolchain()extension point and typedIAdapterRegistrysurface7cca1d72,17d9ef79,9699ee20,40bf1927,66885f1f(#423, #435)docs/diagnostics.md— first complete environment-variable reference; correctssetup-guide's table (was missingRUBY_PATH/RDBG_PATH/CODELLDB_PATHand wrongly listedDLV_PATH, which the Go adapter never honored)17d9ef79(#423 part 2)lib/rustlib/etcand setsCODELLDB_RUST_SYSROOT;&str/String/Vecpreviously rendered as raw LLDB internals in the container. Also: user-supplied_adapterSettingsnow passes through instead of being dropped, and a newannotateOutputEventpolicy hook attributes CodeLLDB's "Failed to initialize language support" line0f7b4798(#441)Behavior changes callers can observe
DAP_TRACEis now opt-in — per-sessiondap-trace-<id>.ndjsonwas previously always-on, synchronous and uncapped; now off by default,DAP_TRACE=1enables,DAP_TRACE_FILE=<path>overrides, capped at 50 MB. The per-sessionproxy-<id>.logalso stopped being hardcoded todebugand now honors--log-level/DEBUG_MCP_LOG_LEVELa5fb26f0(#410)list_threadsno longer retargets the stopped thread —ProxyManageradoptsthreads[0]ascurrentThreadIdonly when no thread is anchored, solist_threadsand internal polls can't redirect a subsequentstackTrace/scopes/evaluate. Alsotool:responselogging now mirrors the payload's realsuccessinstead of hardcodingtrue2014358c(#396, #397, #407)tools/listno longer imports all 9 adapters — availability is now a metadata-only on-disk probe. Worth documenting the trade-off: a present-but-broken package now reportsinstalled: trueand only errors at first load (doctoris what surfaces it)375ec584(#409)MCP_SKIP_ORPHAN_REAPERS=1opt-out for PID-namespaced containers; reapers now share one process scan, run only forstdio/sse/httpcommands (so--versionno longer pays), and the janitor sweeps stale session run dirs older than 7 days91893879(#411)Release / supply chain — release-prep relevant
gh attestation verify oci://index.docker.io/debugmcp/mcp-debugger:<tag> --repo debugmcp/mcp-debugger) and the PyPI launcher migrates to trusted publishing with PEP 740 attestations. Note the ordering constraint: the PyPI trusted publisher must exist before the tag0e73344d(#422)fetchedAt/downloadedAttimestamps dropped from shipped vendor outputs, so two clean builds produce byte-identical vendor trees and tarballsb421391f(#421)Infrastructure and hardening
scripts/canary-smoke.mjs); doubles as the release gate indocs/release-checklist.md94ea158b(#425)scripts/k8s-smoke.mjs)94c45fe7(#451)vsDebugServerorphans reaped — argv tagged with--mcp-owner-pid/--mcp-session-id, third janitor matcher, win32 tree-kill of the worker while alive6e319571(#431)instructions/debugging-workflowprompt point at the Kubernetes recipe and mentionpathMappings0d9400c2(#452)ROADMAP.mdpublished (path to 1.0)ce2832a1(#426)DapFrameDecoderframes with linear accumulation (#413), bounded remaining worker collections (#414), HTTP per-session loggers detached from the shared file transport onstop()(#412), dangling-rejection elimination (#420)0b8e2a94,f037e994,0ef2b9a5,af080fb974b329b7(#408)scripts/mem-bench.mjs+ advisory weekly memory-footprint workflow9ba7c9d8(#406)Judgement call on the last group — the hardening and perf items may be fine to fold into one summary line rather than enumerate. The first three groups should be written out.
3. Root cause
docs/release-checklist.mdverifies that the changelog has a dated entry and that[Unreleased]is empty at the top (lines 9–10), but nothing checks that[Unreleased]actually covers what merged. So entries are only ever added when the authoring PR remembers, and the ones that forgot are invisible until release time.Suggested addition to the pre-release section of the checklist:
Proposed fix
### Fixedblocks and order the section Added → Changed → Fixed.docs/release-checklist.md.Found while auditing local test-harness coverage against the changelog ahead of v0.25.0.