chore(integration): sync main into daemon_mode_b_main (2026-05-25)#4500
Conversation
Pulls 5 main commits since #4469 (2026-05-24): - #4464 fix(weixin): send decryptable image payloads - #4465 fix(weixin): allow Windows image paths inside workspace - #4470 fix(cli): resolve stale closure race in text buffer submit handler - #4468 feat(skills): add memory-leak-debug skill for heap snapshot diagnosis - #4288 feat(cli): do not append trailing space for directory completions (#4092) 11 manual conflicts resolved + 2 add/add conflicts taken from main wholesale: Manual UU (12, all daemon-side preferred except text-buffer.ts): - packages/acp-bridge/package.json — kept HEAD's fuller description (F1 lift expanded the package surface; main has stale pre-F1 wording). - packages/cli/src/acp-integration/acpAgent.ts — kept HEAD's WorkspaceMcpBudget import (F2 needs it). - packages/cli/src/acp-integration/acpAgent.worktree.test.ts (AA): kept HEAD's superset of mocks (MCP_BUDGET_WARN_FRACTION, getMCPDiscoveryState, MCPServerStatus, McpTransportPool, WorkspaceMcpBudget, workspace/debug/mcp config mocks). HEAD already includes main-side SessionStartSource + SessionEndReason mocks. - packages/cli/src/ui/commands/directoryCommand.tsx — pure formatting (HEAD wrapped vs main inline). Kept HEAD. - packages/cli/src/ui/commands/directoryCommand.test.tsx — pure formatting. Kept HEAD. - packages/cli/src/ui/commands/skillsCommand.ts — pure formatting. Kept HEAD. - packages/cli/src/ui/hooks/useCommandCompletion.tsx — pure formatting. Kept HEAD. - packages/cli/src/ui/hooks/useCommandCompletion.test.ts — pure formatting. Kept HEAD. - packages/cli/src/ui/hooks/useSlashCompletion.test.ts — pure formatting. Kept HEAD. - packages/core/src/config/config.test.ts — kept HEAD's TrustGateError import (daemon-added). text-buffer.ts (4 zones — took MAIN wholesale for #4470's stale-closure fix): - Import: useRef instead of useReducer (daemon side had useReducer as a dead import — file uses dispatch via useCallback, not useReducer; verified via grep). useRef is needed for stateRef + #4470's currentText capture. - writeFileSync zone: use stateRef.current.lines.join('\n') instead of stale closure-captured `text`. Fixes #4470's bug. - text comparison: `newText !== currentText` not `newText !== text`. - dep array: `[dispatch, ...]` not `[text, ...]` (callback reads from ref now, doesn't need to re-bind on text change). AA (2, main wholesale via git checkout --theirs): - packages/core/src/permissions/dangerousRules.ts + .test.ts Original #4151 Auto-mode added these on main, came into daemon via #4469 squash. Main then landed #4371 ("strip additional dangerous interpreter rules") as a follow-up that daemon side never saw. Take main's evolved version wholesale. Verification: - packages/core tsc: 50 errors PRE-merge, 50 errors POST-merge (pre-existing baseline — none introduced by this sync). - packages/acp-bridge tsc: clean. - 5 spot-test runs on conflict-resolved files: 132 + 17 + 24 + 30 + 1 = 204 tests pass (text-buffer / directoryCommand / useCommandCompletion / useSlashCompletion / skillsCommand). Mirrors #4469's pattern (squash merge daemon_mode_b_main-side). Unblocks #4490 daemon_mode_b_main → main reverse integration merge (currently CONFLICTING precisely because of these 5 main commits).
📋 Review SummaryThis PR syncs 🔍 General Feedback
🎯 Specific Feedback🟢 Medium
🔵 Low
✅ Highlights
|
|
@wenshao 这个 sync PR + #4490 是一个 chain,按 #4175 branching strategy 推进 v0.16-alpha 切版: Action chain:
这个 PR 安全性: 11 个 UU 手工解 + 2 个 AA 走 验证: core tsc 50 errors pre = 50 errors post(零新增 baseline);acp-bridge tsc clean;5 个 spot test 共 204/204 通过。 Cron |
There was a problem hiding this comment.
Pull request overview
This PR syncs in changes from main into the integration branch, bringing in new core utilities and a debugging skill intended to improve reliability (project root detection), security (URL credential redaction), and operational diagnostics (heap snapshot workflow).
Changes:
- Added a
findProjectRoot()utility with Vitest coverage, intended to correctly detect git worktree/submodule roots where.gitis a file. - Added
redactUrlCredentials()+ tests to prevent credential leakage when rendering credentialed URLs. - Added a
memory-leak-debugskill with scripts and a worked example for heap snapshot-based leak diagnosis.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core/src/utils/projectRoot.ts | New shared helper to locate the nearest git repo root by detecting .git as dir or file. |
| packages/core/src/utils/projectRoot.test.ts | Unit tests for findProjectRoot() covering directory, file, and symlink behavior. |
| packages/core/src/extension/redaction.ts | New redaction helper to strip userinfo credentials from URL-like strings. |
| packages/core/src/extension/redaction.test.ts | Unit tests for URL credential redaction across multiple edge cases. |
| .qwen/skills/memory-leak-debug/SKILL.md | New skill documenting a heap snapshot workflow using chrome-devtools CLI. |
| .qwen/skills/memory-leak-debug/scripts/find-leaf-node.sh | Helper script to find the leaf node PID in a tmux session process tree. |
| .qwen/skills/memory-leak-debug/examples/react-reconciler-performance-measure-leak.md | Worked example documenting diagnosis + remediation of a past leak. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export async function findProjectRoot( | ||
| startDir: string, | ||
| ): Promise<string | null> { | ||
| let currentDir = path.resolve(startDir); | ||
| while (true) { |
| it('treats a .git symlink to a directory as a project root', async () => { | ||
| // Edge: some setups symlink .git. lstat would NOT follow the link, | ||
| // so this pins the behavior we get with the directory-or-file shape: | ||
| // a symlink to a directory should still be recognized via the file | ||
| // branch (lstat reports it as a symlink, which is neither — so this | ||
| // documents the current behavior, not a guarantee). | ||
| const target = path.join(testRootDir, 'real-git'); | ||
| await fsPromises.mkdir(target); | ||
| await fsPromises.symlink(target, path.join(projectRoot, '.git')); | ||
|
|
||
| // Symlinks aren't directories or regular files under lstat. Document | ||
| // that we do NOT chase them — caller would see null and fall back. | ||
| // If this assertion ever needs to flip, do it deliberately. |
| export const REDACTED_URL_CREDENTIAL = '***REDACTED***'; | ||
|
|
||
| const URL_CREDENTIALS_PATTERN = /\b([a-z][a-z0-9+.-]*:\/\/)(?:[^/\s]+@)+/gi; | ||
|
|
||
| /** | ||
| * Redacts userinfo credentials from URL-like extension sources for logs, | ||
| * telemetry, and display. This also handles diagnostic messages that contain | ||
| * credentialed URLs. The original source should still be preserved for | ||
| * installation and update operations. | ||
| */ | ||
| export function redactUrlCredentials(source: string): string { | ||
| return source.replace( | ||
| URL_CREDENTIALS_PATTERN, | ||
| `$1${REDACTED_URL_CREDENTIAL}@`, | ||
| ); |
Qwen Code Review (DEEP)CI-safe profile adapted from bundled Correctness / Security
No correctness or security issues found at P0/P1. Needs Verification
Test Coverage
No other concrete test coverage gaps found. The Needs VerificationNo coverage concerns requiring code outside the supplied context. Validation EvidenceMISSING - The PR provides typecheck results (
Maintainability / PerformanceNo maintainability or performance issues found. Notes on reviewed code:
Needs VerificationNo concerns requiring additional code context. Validation EvidencePRESENT — The author provides comprehensive validation evidence:
Undirected Audit
Needs Verification
Validation EvidencePRESENT - The PR provides tsc verification (50 errors pre-merge = 50 errors post-merge, zero introduced), 204 passing tests on conflict-resolved files, and detailed conflict resolution rationale. However, explicit test runs for the newly synced files (
Qwen Code |
Summary
Periodic main → integration sync, mirroring #4469's pattern (2026-05-24). Pulls 5 main commits that landed since #4469:
94da486e1fix(weixin): send decryptable image payloads8ef73599dfix(weixin): allow Windows image paths inside workspaceab26a5ab7fix(cli): resolve stale closure race in text buffer submit handler84f408017feat(skills): add memory-leak-debug skill for heap snapshot diagnosis4dc98484ffeat(cli): do not append trailing space for directory completions (#4092)Why now
Unblocks #4490 (the reverse
daemon_mode_b_main → mainintegration merge for v0.16-alpha), which is currentlyCONFLICTINGprecisely because of these 5 commits. After this PR merges, #4490 will auto-recompute mergeable status and the maintainer can flip it from DRAFT to ready-for-review.Conflicts resolved (13 total)
11 manual
UU(daemon-side preferred except text-buffer.ts)packages/acp-bridge/package.jsondescription(F1 lift expanded the package surface; main has stale pre-F1 wording).packages/cli/src/acp-integration/acpAgent.tsWorkspaceMcpBudgetimport (F2 needs it).packages/cli/src/acp-integration/acpAgent.worktree.test.ts(AA)SessionStartSource+SessionEndReasonalready present in HEAD's version.packages/cli/src/ui/commands/directoryCommand.{tsx,test.tsx}packages/cli/src/ui/commands/skillsCommand.tspackages/cli/src/ui/hooks/useCommandCompletion.{tsx,test.ts}packages/cli/src/ui/hooks/useSlashCompletion.test.tspackages/core/src/config/config.test.tsTrustGateErrorimport (daemon-added).packages/cli/src/ui/components/shared/text-buffer.ts(4 zones)stateRef.current.lines.join('\n')capture for the writeFileSync + text-comparison + dep array. Daemon side haduseReduceras a dead import (verified via grep — file usesdispatchfrom auseCallback, notuseReducer); main'suseRefimport is the live one needed forstateRef.2
AA(main wholesale viagit checkout --theirs)packages/core/src/permissions/dangerousRules.ts+.test.ts— Original #4151 Auto-mode added these on main; they came into daemon via the chore(integration): sync main into daemon_mode_b_main (2026-05-24) #4469 squash. Main then landed #4371 ("strip additional dangerous interpreter rules") as a follow-up that daemon side never saw. Take main's evolved version wholesale.Verification
packages/coretsc: 50 errors PRE-merge, 50 errors POST-merge — none introduced by this sync (pre-existing baseline; out of scope for an integration PR).packages/acp-bridgetsc: clean.text-buffer.test.ts: 132/132 ✅directoryCommand.test.tsx: 17/17 ✅useCommandCompletion.test.ts: 24/24 ✅useSlashCompletion.test.ts: 30/30 ✅skillsCommand.test.ts: 1/1 ✅Recommended merge strategy
Squash (mirroring #4469's pattern). The 5 main PRs already each have their own commit + PR # link on main; daemon_mode_b_main only needs a single squash commit summarizing "pulled X commits".
🤖 Generated with Qwen Code