fix(cli): avoid stale git branch watcher setup#5271
Conversation
|
|
||
| const gitLogsHeadPath = path.join(cwd, '.git', 'logs', 'HEAD'); | ||
| let watcher: fs.FSWatcher | undefined; | ||
| let disposed = false; |
There was a problem hiding this comment.
[Suggestion] The flag is named disposed, but every other hook in this directory that uses the same async-cancellation pattern names it cancelled:
useWorktreeSession.ts:58—let cancelled = false;useDiffData.ts:49—let cancelled = false;useAtCompletion.ts:160—let cancelled = false;useTurnDiffs.ts:69—let cancelled = false;
Renaming to cancelled would keep the convention consistent across the hooks directory.
| let disposed = false; | |
| let cancelled = false; |
— qwen3.7-max via Qwen Code /review
| const CWD = '/test/project'; | ||
| const GIT_LOGS_HEAD_PATH = `${CWD}/.git/logs/HEAD`; | ||
|
|
||
| async function flushAsyncEffects() { |
There was a problem hiding this comment.
[Suggestion] This helper hardcodes exactly two await Promise.resolve() ticks after vi.runAllTimers(), which works today but is brittle — if setupWatcher ever gains an additional await, the flush becomes silently insufficient. Other test files in this directory (e.g. useToolScheduler.test.ts, ideCommand.test.ts) use await vi.runAllTimersAsync() instead, which natively drains the full microtask + timer queue:
// Before
async function flushAsyncEffects() {
vi.runAllTimers();
await Promise.resolve();
await Promise.resolve();
}
// After — replace all flushAsyncEffects() calls with:
await vi.runAllTimersAsync();— qwen3.7-max via Qwen Code /review
ac01b71 to
6bde99c
Compare
✅ Local runtime verification — fix confirmedI verified this PR locally with real test runs under The bug
The fix adds a How I verifiedAll runs are the real 1) The new test is a genuine regression test (base ✗ / PR ✓) Running the PR's test file against each source:
PR shipped state (PR source + PR test): 8/8 tests pass. 2) Real-filesystem demonstration (not mocked) I rendered the real hook with a real
This shows the real-world consequence: on base, a live OS watcher survives unmount and keeps spawning 3) PR's stated checks (on the PR state) — Notes for the maintainer (non-blocking)
Recommendation: minimal, correct, well-covered. 👍 to merge. Verified by running the real 中文版(点击展开)✅ 本地真实运行验证 —— 修复已确认我在本地用 Bug 是什么
修复方案:在 cleanup 中置一个 验证方法所有运行都是在 1) 新测试是真正的回归测试(base 失败 / PR 通过) 用 PR 的测试文件分别跑两个源码版本:
PR 完整状态(PR 源码 + PR 测试):8/8 测试通过。 2) 真实文件系统演示(非 mock) 我用真实 hook + 真实
这展示了真实世界的后果:在 base 上,一个活的 OS watcher 在 unmount 后仍然存活并持续触发 3) PR 声明的检查(在 PR 状态下) —— 给维护者的提示(不阻塞)
建议: 改动最小、正确、覆盖充分。👍 可以合并。 通过在 |
|
@qwen-code /triage |
|
Nice cleanup, and the test additions here (un-skipping the two watcher tests + the new unmount-race test) are genuinely useful. The production change has been overtaken by
Could you rebase onto 中文说明清理得不错,这里的测试新增(解封两个 watcher 测试 + 新的卸载竞态测试)确实有价值。不过生产代码那部分已经被
能否 rebase 到 |
|
@copilot resolve the merge conflicts in this pull request |
|
@copilot resolve the merge conflicts in this pull request |
1 similar comment
|
@copilot resolve the merge conflicts in this pull request |
# Conflicts: # packages/cli/src/ui/hooks/useGitBranchName.ts
|
Resolved the merge conflict by merging A note on how it resolved: 中文说明通过把 关于解决方式的说明: |
|
@qwen-code /triage |
|
Thanks for the PR, @tt-a1i! Template: The PR body doesn't follow the PR template — it's missing "What this PR does", "Why it's needed", "Reviewer Test Plan", "Risk & Scope", "Linked Issues", and the 中文说明 section. However, a collaborator has already reviewed and resolved merge conflicts on this PR, so I'm treating this as non-blocking. For future PRs, please follow the template — it helps reviewers move faster. Direction: This addresses a real bug — an async race in Approach: The scope is tight — one test file, focused changes. The Moving on to code review. 🔍 中文说明感谢贡献, @tt-a1i! 模板: PR 正文未遵循 PR 模板 —— 缺少 "What this PR does"、"Why it's needed"、"Reviewer Test Plan"、"Risk & Scope"、"Linked Issues" 和中文说明部分。不过协作者已经审查并解决了合并冲突,因此视为非阻塞项。后续 PR 请遵循模板,有助于加快审查速度。 方向: 修复了一个真实 bug —— 方案: 范围紧凑 —— 只改一个测试文件,变更聚焦。 进入代码审查 🔍 — Qwen Code · qwen3.7-max |
Code ReviewIndependent proposal: For a race condition where Comparison with the diff: The PR matches this proposal almost exactly. The No critical issues found. The code follows project conventions and the test patterns are sound. TestingBefore (main — 7 tests, 2 skipped)After (this PR — 8 tests, 0 skipped)Regression verification (removed
|
|
Stepping back: this is a clean, minimal test-only PR that does exactly what it says. The production fix (the My independent proposal for these tests matched what the PR delivers: deterministic async flushing instead of flaky The regression verification is the clincher: stripping the The only note is the PR template non-compliance, which I've flagged as non-blocking for future PRs. Approving. ✅ 中文说明退后一步看:这是一个干净、最小化的纯测试 PR,完全兑现了它的承诺。生产代码修复( 我对这些测试的独立方案与 PR 交付的内容一致:用确定性异步刷新替代不稳定的 回归验证是关键:移除 唯一的备注是 PR 模板不合规,已作为非阻塞项标注,供后续 PR 参考。 批准 ✅ — Qwen Code · qwen3.7-max |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
Summary
fs.watchafter unmountValidation
npx vitest run src/ui/hooks/useGitBranchName.test.tsnpx prettier --check packages/cli/src/ui/hooks/useGitBranchName.ts packages/cli/src/ui/hooks/useGitBranchName.test.tsnpx eslint packages/cli/src/ui/hooks/useGitBranchName.ts packages/cli/src/ui/hooks/useGitBranchName.test.tsnpm run build --workspace=packages/corenpm run build --workspace=packages/acp-bridgenpm run generatenpm run typecheck --workspace=packages/cligit diff --checkAI Assistance Disclosure
I used Codex to review the changes, sanity-check the implementation against existing patterns, and help spot potential edge cases.