Agent Sandbox Registry

agent-sandbox

Adversarial review: area commands

无中文版

parity/review/commands.md

Adversarial review: area commands

Scope: cli/src/framework/**, cli/src/cli/{main,output,formatters,region,repl,scaffold,_rich*,_orjson}.ts, cli/src/bin/abx.ts, cli/src/cli/commands/{config_cmd,sandbox,sandbox_files,sandbox_process,sandbox_system}.ts against Python agent_sandbox/cli/**. Reviewer: independent (did not write the port). cli/src/** was not edited.

Placeholders: $ORACLE_VENV = virtualenv with the original Python abx (real Click 8.5, Rich, httpx), $ORIG_REPO = original checkout. All harness runs used an isolated HOME, ABX_NO_KEYCHAIN=1, no real credentials and a private stub HTTP server per run.

Deliverables

Kind Path
Vitest, ADV-commands-01..15 (no oracle needed; expected values come from the oracle and are hard-coded) cli/tests/test_cli/adv_commands.test.ts (ADV-01..15 plus ADV-16..18 added with the fixes)
Option/argument/command metadata dump of both trees (Python side / Node side, compared with inspect.cleandoc on help) cli/parity/diff/adv_commands_meta_dump.{py,mjs} (the .mjs needs node --import tsx)
Shared runner (private stub, pty, signals, shell, tree snapshots) cli/parity/diff/adv_commands_lib.mjs
Auto-generated option-parsing fuzz from oracle metadata (2385 cases) cli/parity/diff/adv_commands_fuzz.mjs
Timeouts / huge ints (75) cli/parity/diff/adv_commands_misc.mjs
Every runnable command x output mode x fault (1517) cli/parity/diff/adv_commands_matrix.mjs
[shortcuts] shapes and unknown-command hints (994) cli/parity/diff/adv_commands_shortcuts.mjs
Closed/full/broken stdio, pipes, signals, locale, REPL over pipes (237) cli/parity/diff/adv_commands_proc.mjs
REPL under a pty, Rich/Click TTY env matrix (375+) cli/parity/diff/adv_commands_pty.mjs
upload/download transfers with a binary-safe stub (89) cli/parity/diff/adv_commands_xfer.mjs
create/kill/list flag semantics (232) cli/parity/diff/adv_commands_create.mjs
Rich replacement through real commands, hostile cell data, widths 1..300 (456) cli/parity/diff/adv_commands_rich.mjs

Run: ORACLE_VENV=... node parity/diff/adv_commands_<x>.mjs (prints DIFF ...; prints SKIP and exits 0 without the oracle). Env knob: ADV_DROP_HTTP_INFO=1 hides the INFO: HTTP Request: lines (see C-05) so other diffs are visible. Tests: npx vitest run tests/test_cli/adv_commands.test.ts (moved from tests/adversarial/commands/commands.test.ts; about 40 s; ADV-12/13 need python3, ADV-07/10 need /dev/full).

Counts

Test map: ADV-01 = C-10a, 02 = C-10b, 03 = C-10c, 04 = C-10d, 05 = C-04, 06 = C-05, 07 = C-03, 08 = C-06, 09 = C-07, 10 = C-08, 11 = C-09, 12 = C-01, 13 = C-02, 14 = C-10b (signal), 15 = C-10c (request timeout).

Fix status

All BUG / GAP-UNJUSTIFIED findings were addressed in cli/src; the ADV-commands-NN tests moved to tests/test_cli/adv_commands.test.ts (18 tests, all active, no test.skip; it.skipIf only when python3 or /dev/full is missing on the machine).

Id Kind Fix status Where / how
C-01 BUG HIGH FIXED (ADV-12, ADV-16) src/cli/repl.ts: stdin is read once into a module-level buffer; each prompt gets a readline Interface fed only up to the first Enter / Ctrl+J / Ctrl+C / Ctrl+D (GNU readline consumes one byte at a time), the remainder stays queued for the next input(). Raw mode is on only while a prompt is active. EOF / Ctrl+C / Ctrl+D semantics unchanged.
C-02 BUG MEDIUM-LOW FIXED (ADV-13) same redesign (no raw-mode toggling with unread bytes dropped); 5000 char line + following line work.
C-03 BUG MEDIUM FIXED (ADV-07) src/framework/io.ts: non-TTY stdout/stderr are written with fs.writeSync (EAGAIN retried), failures (ENOSPC, EIO, ...) are sticky and thrown as the Node error so handle_errors prints OS error: [Errno 28] ...; stream 'error' events are recorded, never unhandled. finalizeStreams (src/bin/abx_main.ts) reproduces Python's final failing flush: Exception ignored in: <_io.TextIOWrapper name='<stdout>' ...> and exit status 120 (the oracle exits 120, not 1; the old test expectation was wrong). EPIPE stays silent.
C-04 GAP-UNJUSTIFIED FIXED (ADV-05) src/transport/_httpx.ts: httpx logger INFO HTTP Request: METHOD URL "HTTP/x CODE Reason" for every response incl. redirect hops.
C-05 BUG LOW FIXED (ADV-06) _parsePairs (sandbox.ts) and the pydantic dict validator/dump (src/models/_pydantic.ts) define __proto__ as an own property.
C-06 BUG LOW FIXED (ADV-08) src/bin/abx.ts is now a shim that drops Node's NO_COLOR/FORCE_COLOR warning (emitted while linking node:http) and then imports abx_main.ts.
C-07 BUG LOW FIXED (ADV-09) URL_ keeps scheme-less URLs (127.0.0.1:9, not a url, /x, //h/x) so the request fails with httpx's UnsupportedProtocol text; unparsable URLs that do have a scheme still raise InvalidURL.
C-08 BUG LOW FIXED (ADV-10) download in sandbox.ts and Files.download in src/api/files.ts: open errors keep the filename, write errors do not.
C-09 BUG LOW FIXED (ADV-11) _httpx.ts: truncated body -> (received N bytes, expected M) for Content-Length, (incomplete chunked read) for chunked; a real RST is a ReadError.
C-10a..d BUG FIXED during review (ADV-01..04, 14, 15) ADV-04 additionally needed t.connect <= 0 to expire before anything is sent (it raced with an instant localhost connect and sent Start). An already-expired timeout (httpx.Timeout(<= 0)) stays ConnectTimeout and the CLI reports [E3001] Request timed out (exit 5), matching the oracle (AT-12). A ConnectTimeout under a positive timeout is still ConnectionError_ ([E5001], KI-003).
C-11 BUG LOW FIXED (ADV-17, ADV-18) repl.ts: TERM=dumb keeps full editing (Node's dumb handler is removed), kill ring + Ctrl+Y, whitespace-delimited Ctrl+W (kills do not merge, verified against the oracle), Alt+D / Alt+Backspace, bell on Ctrl+D at end of a non-empty line. Tab / Ctrl+L redraw bytes remain ACCEPTED-OK (escape-sequence encodings).
C-12 BUG LOW FIXED subsumed by C-01 (type-ahead is consumed prompt by prompt). The redraw bytes (ESC[1G ESC[0J) readline emits around the prompt stay ACCEPTED-OK.
C-13 GAP-UNJUSTIFIED DOCUMENTED, not changed lone surrogates cannot come from a real terminal or argv (both are bytes); Node cannot hold them in process.argv at all. Only reachable programmatically.
C-14 ACCEPTED-OK unchanged info . URL normalisation.

Findings

Severity is the user impact on a real run. "expected" is always the Python oracle.

C-01 REPL drops type-ahead / pasted lines and then hangs (BUG, HIGH) - open, ADV-commands-12

C-02 REPL stops reacting after a very long line (BUG, MEDIUM-LOW) - open, ADV-commands-13

C-03 failed stdout/stderr write crashes with an unhandled stream error (BUG, MEDIUM) - open, ADV-commands-07

C-04 --log-level info|debug and --verbose omit httpx's INFO: HTTP Request: line (GAP-UNJUSTIFIED, LOW-MEDIUM) - open, ADV-commands-05

C-05 create --env __proto__=X / --metadata __proto__=X silently drop the key (BUG, LOW) - open, ADV-commands-06

C-06 FORCE_COLOR together with NO_COLOR leaks a Node warning (BUG, LOW) - open, ADV-commands-08

C-07 scheme-less E2B_API_URL message differs (BUG, LOW) - open, ADV-commands-09

C-08 download write error carries a filename (BUG, LOW) - open, ADV-commands-10

C-09 truncated Content-Length body message (BUG, LOW) - open, ADV-commands-11

C-10 Integer / timeout parsing: FIXED while reviewing

Minor, not covered by a test

Held up (no diff found)

ACCEPTED-OK (Python-specific or Node-inherent)