Fixes#77656.
Summary:
- Carry chat turn-source metadata through approved async host=node replays.
- Bind trusted backend replay to node, command, session, agent, and chat target metadata instead of transient WebSocket connection ids.
- Cover Telegram and WeCom-style reconnect replay plus denial cases with gateway, websocket, and agent tests.
- Carry the current-main CLI help assertion fix needed to clear exact-head CI after the rebase.
Verification:
- pnpm test src/gateway/node-invoke-system-run-approval.test.ts src/gateway/server.node-invoke-approval-bypass.test.ts src/agents/bash-tools.exec-host-node.test.ts -- --reporter=verbose
- pnpm test src/cli/channel-auth.test.ts src/cli/plugins-cli.policy.test.ts src/cli/command-registration-policy.test.ts -- --reporter=verbose
- pnpm check:changed
- GitHub CI passed on d1392a873c
- ClawSweeper re-review completed on the approval replay head
When exec runs with host=node and no explicit cwd is provided, the
gateway was injecting its own process.cwd() as the default working
directory. In cross-platform setups (e.g. Linux gateway + Windows node),
this gateway-local path does not exist on the node, causing
"SYSTEM_RUN_DENIED: approval requires an existing canonical cwd".
This change detects when no explicit workdir was provided (neither via
the tool call params.workdir nor via agent defaults.cwd) and passes
undefined instead of the gateway cwd. This lets the remote node use its
own default working directory.
Changes:
- bash-tools.exec.ts: Track whether workdir was explicitly provided;
when host=node and no explicit workdir, pass undefined instead of
gateway process.cwd()
- bash-tools.exec-host-node.ts: Accept workdir as string | undefined;
only send cwd to system.run.prepare when defined
- bash-tools.exec-approval-request.ts: Accept workdir as
string | undefined in HostExecApprovalParams
Fixes#58934
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>