docs/verification/abort-controller-refactor/README.md
Scenarios used to validate the change manually before opening the PR. Each
scenario captures its tmux pane via tmux pipe-pane -o 'cat >> <log>'.
# Point WT at your local checkout of the branch under review.
WT=/path/to/qwen-code/worktree
LOGDIR=$WT/docs/verification/abort-controller-refactor/logs
mkdir -p "$LOGDIR"
# Build the CLI once (skip sandbox image, skip vscode).
( cd "$WT" && npm run build:packages )
For each scenario:
tmux new-session -d -s qwen-verify-XX
tmux pipe-pane -t qwen-verify-XX -o "cat >> $LOGDIR/XX-name.log"
tmux send-keys -t qwen-verify-XX "cd /path/to/your/test/workspace && exec node $WT/packages/cli/dist/index.js" C-m
tmux attach -t qwen-verify-XX
Then drive the session manually per the matrix below. Hit C-b d to detach
when done; tmux kill-session -t qwen-verify-XX to stop the pane.
main, build, run with NODE_OPTIONS=--trace-warnings.MaxListenersExceededWarning: ... 1500+ abort listeners added to [AbortSignal] printed to stderr.00-baseline-reproduction.log.NODE_OPTIONS=--trace-warnings DEBUG=1 qwen.MaxListenersExceededWarning printed; any other warnings still print.01-long-session-debug.log.qwen (no debug env).console.error probe inside the handler (added then removed) confirms the filter fires.02-long-session-prod.log.process._getActiveHandles() count returns to baseline (use :debug handles).03-ctrlc-streaming.log.sleep 60 via the shell tool; cancel mid-execution.pgrep -f sleep returning empty), tool result shows cancellation, agent accepts next prompt.04-shell-cancel.log.05-subagent-cancel.log.qwen --prompt "do a long task"; send SIGINT from outside via kill -INT <pid>.06-headless-abort.log.run_in_background: true); let it complete; spawn a second one; cancel the second mid-flight.07-background-agent.log.qwen --inspect, attach Chrome devtools.AbortSignal instance count and per-signal listener count stable (no monotonic growth).08-memory-snapshots/.09-http-hook-shim.log.The automated checks below were run during development and recorded in
automated-results.md:
abortController.test.ts, 26 tests; 1 GC test skipped under non---expose-gc).warningHandler.test.ts, 13 tests including a spawned-child stderr integration test).combineAbortSignals consumer tests pass (httpHookRunner.test.ts); the deprecated createCombinedAbortSignal shim plus its own test file were removed once the lone caller migrated.agent-interactive.ts, agent-core.ts, agent-headless.ts) plus promptHookRunner.ts (real cleanup leak) was switched to the helper. Independent short-lived controllers (per-shell-command, per-fetch, per-recall, etc.) stay on raw new AbortController() — they're GC'd quickly and don't accumulate listeners on a long-lived parent. See migration-completeness.txt for the captured grep + rationale.packages/core and packages/cli.See automated-results.md for the actual command output.
After running each scenario, attach the transcript file (or relevant excerpt) to the PR. For #08 (memory), export the heap snapshots and include the listener-count delta between snapshots.