A live window stays undiscoverable after another window prunes its stale registry entry
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 56/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- node.js, typescript, vscode
调研方向
Start with src/utils/workspaceRegistry.ts, especially list() and heartbeat(), then read the registration flow in src/extension.ts and the existing registry tests. Reproduce the missing-entry case with the linked harness, then check that a live owner's workspace stays discoverable after pruning and subsequent heartbeats. The issue allows several fix strategies, so confirm the chosen behavior with maintainers before treating the regression as done.
由索引模型根据 Issue 内容生成。
描述
Summary
If one DebugMCP window misses registry heartbeats long enough for another window
to prune its entry, later heartbeats from the still-live owner do not restore
that entry. Other windows can no longer discover the owner's workspace until it
explicitly registers again.
This report isolates the registry recovery path. The reproduction simulates an
expired timestamp in its own fixture data; it does not suspend a real VS Code
extension host or reproduce an operating-system sleep/resume sequence.
Environment
- Microsoft/DebugMCP source commit:
d0b4a334a6a3d8d600c5aa75ec60d9de272af3c4. - Verified baseline: Windows x64, Node.js
v24.22.1, package version 2.4.4. - The actual compiled
WorkspaceRegistryimplementation, loaded from a separate
checkout. Each run reports its commit, Node version, source state and
source/compiled-module hashes. - Two isolated Node fixture processes with real, distinct process IDs and an
exclusive temporary registry. No installed editor registry is accessed.
Reproduction steps
-
Prepare a separate checkout of Microsoft/DebugMCP at the pinned revision:
git clone https://github.com/microsoft/DebugMCP.git cd DebugMCP git checkout d0b4a334a6a3d8d600c5aa75ec60d9de272af3c4 npm ci --ignore-scripts npm run compile -
Clone this reproduction repository's
mainbranch in a separate directory
and run the harness. Replace<absolute-path-to-DebugMCP>with the absolute
path of the Microsoft/DebugMCP checkout prepared in step 1:git clone --branch main https://github.com/hahnfk/debugmcp-repro.git cd debugmcp-repro node scripts/review/registry-heartbeat-recovery.cjs --debugmcp-root "<absolute-path-to-DebugMCP>"Reproduction files on
main: -
The harness creates its own temporary directory and starts fixture processes
A and B. Each constructs a realWorkspaceRegistrywith its own process ID,
registers a synthetic workspace, and remains available over IPC. The harness
confirms that B can list both registrations and find both workspace paths. -
It changes only
updatedAtin A's own fixture registration file to
Date.now() - 61000. All other registration fields are preserved. This is a
simulation of elapsed heartbeat time; the system clock and upstream methods
are unchanged, and the test does not wait 61 seconds. -
B calls the public
list()method. On the reviewed commit this removes A's
stale entry even though A remains alive. The harness confirms A's identity
through its existing IPC channel and performs the read-only OS liveness check
process.kill(pid, 0)before and after this operation. -
A calls its real public
heartbeat()three times. After every completed
call, B useslist()andfindByPath(A)to check discoverability. Both fixture
processes must remain alive and responsive throughout. -
Finally, A calls the public
register()explicitly. B can then find A again,
demonstrating a recovery workaround using the same live owner and registry.
The test also checks normal registration/path lookup, timestamp advancement and
file persistence during a fresh heartbeat, and explicit unregistration removing
only A while preserving B. The fresh-heartbeat control sets only its fixture
timestamp one second into the past, within the normal entry lifetime, to avoid a
clock-tick timing dependency. It does not call heartbeat() after explicit
unregistration or prescribe a reactivation policy for that case.
Expected result
An owner that remains active and resumes heartbeats should remain discoverable
or recover its registry advertisement. After each heartbeat in this scenario,
B should be able to list A and find A's workspace while retaining its own entry.
The default regression command should exit with code 0 when that healthy
contract holds and all four controls and cleanup checks pass. It also accepts a
future implementation that keeps a live owner's entry instead of pruning it;
the test does not require a particular fix strategy.
Actual result
On the reviewed commit:
| Phase | Observed result |
|---|---|
| Initial registrations | A and B are present; both workspace paths resolve correctly |
| B lists after A's timestamp was aged | A's file is removed; only B remains |
| A completes heartbeat 1 | A's file is still absent; B cannot find A |
| A completes heartbeat 2 | A's file is still absent; B cannot find A |
| A completes heartbeat 3 | A's file is still absent; B cannot find A |
| A explicitly registers again | A becomes discoverable again; B remains present |
IPC identity checks and OS liveness checks confirm that both original fixture
processes remain alive during pruning and all three heartbeats. All four
controls pass. The default regression command therefore exits with code 1.
The recorded evidence contains
both central runs, all heartbeat outcomes, the controls, liveness checks,
cleanup results and source/compiled-module hashes.
To require the exact current failure signature, all controls and successful
cleanup, use:
node scripts/review/registry-heartbeat-recovery.cjs --debugmcp-root "<absolute-path-to-DebugMCP>" --expect-current-bug
That diagnostic mode exits with code 0 only when B actually prunes the live A
registration and all three completed A heartbeats leave it absent while B stays
discoverable. An IPC timeout, crashed fixture, filesystem failure or unrelated
exception does not count as reproducing the bug.
Cause and impact
list()
prunes another process's entry when its timestamp is older than 60 seconds,
even if its process is alive. The owner's subsequent
heartbeat()
first reads its existing file. Once that file is missing, ENOENT is ignored
and no replacement registration is written.
In the extension,
registerSelf() is called on activation and workspace-folder changes,
whereas the periodic timer calls only heartbeat(). A peer-pruned window can
therefore stay undiscoverable until one of those explicit registration paths is
triggered. Existing cached routing targets may still work; this report concerns
registry discoverability and new path-based target resolution.
A recovery approach could retain the active registration inputs for recreation
or explicitly re-register active windows periodically. Avoiding removal of a
live owner's entry is another possible approach. The reproduction checks the
observable discoverability contract rather than choosing one implementation.
Scope and test seams
The harness does not replace or monkeypatch registry methods or private fields.
It uses the real filesystem and actual child-process liveness checks. The only
direct registration-file edit is the controlled updatedAt fixture-data change.
The common loader suppresses logging; an error-counting logger sink also prevents
an unrelated internally logged heartbeat error from counting as the bug signature.
No real editor, debugger or MCP server is started. Each fixture owns an idle loopback listener solely to reserve an
OS-assigned port for its registration metadata; it is not a VS Code
ControlServer.
The scenario has a twelve-second deadline followed by bounded worker cleanup.
Cleanup uses only the harness's exact child-process handles, IPC disconnect and
the fixture's own exit path. Recursive removal verifies that the resolved target
is the harness's own prefixed directory immediately under the OS temporary
directory. Process IDs, ports, synthetic tokens and paths are locally generated
observations, not reproduction constants; tokens are not printed.
The evidence establishes the recovery failure after controlled timestamp aging.
It does not establish how often a real host pauses long enough to trigger
pruning, or claim a live reproduction of suspend/resume behavior.
Related reports and changes
- PR #104 introduced multi-window
registration and heartbeat-based pruning. - PR #154 hardened registry
storage, ownership checks and atomic writes. It preserves the missing-file
heartbeat behavior described here. - Issue #165 concerns per-workspace
ports and multi-window reliability; it does not identify this recovery trigger.
Investigation tooling
This investigation and its reproduction work were carried out with assistance
from OpenAI Codex.
- Codex desktop app version:
26.1021.31345(build21828). - Version verified on
2026-10-25, when this tooling disclosure was added.
The automated reproduction runs directly as an isolated Node.js harness against
the DebugMCP implementation. Codex assisted the investigation, harness authoring
and report preparation.
- 主要语言
- TypeScript
- 星标
- 580
- 派生
- 63
- 平均合并
- 1 天 17 小时
- 30 天内合并 PR
- 11
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
microsoft/DebugMCP 的其他 Issue
-
难度 5/5 一周以上 新手友好度 35/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 45/100
维护者通常 1 天内回复
-
难度 4/5 3-5 天 新手友好度 48/100
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 58/100
维护者通常 1 天内回复
-
难度 3/5 1-2 天 新手友好度 66/100
维护者通常 1 天内回复
查看 microsoft/DebugMCP 的全部 Issue
相似的 Issue
-
[Text] Add Reading Time & Word Count Estimator for Reflection Notes in src/lib/text/reading-time.ts未关闭area:core beginner-friendly community contributions-welcome difficulty:easy enhancement good first issue
难度 2/5 1-3 小时 新手友好度 88/100
维护者通常 1 天内回复
-
[fullsend] E2E: scorecard — filecheck GitLab entity metrics unavailable due to initialDelay timing未关闭e2e-failure ready-to-code
难度 2/5 1-3 小时 新手友好度 75/100
redhat-developer/rhdh-plugin-export-overlays#4698 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 88/100
devswha/herdr-web-ui#2884 ·
-
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
b:minor bug
难度 2/5 1-3 小时 新手友好度 78/100
software-mansion/argent#1771 ·
维护者通常 1 天内回复