Completeness review: CLI port (Python abx -> cli/src)
Method: mechanical inventories, not sampling. Everything below is regenerated by
ORIG_REPO=<original python repo> ORACLE_VENV=<oracle venv> bash cli/parity/review/inventory/run_all.sh
(offline, skips cleanly when the oracle is absent). Raw outputs are in cli/parity/review/inventory/out/.
- Python side:
py_inventory.py(stdlibast) over the originalsrc/-> 104 modules, 1579 symbols, ~7000 string literals (each tagged message / path / env / endpoint / identifier), 72 env reads, exit sites. - Node side:
ts_inventory.mjs(TypeScript compiler API) overcli/src-> 112 files, 20107 literals, 66 env reads. - Click surface:
click_tree.py(live introspection of the oracle) vsclick_tree.mjs(live introspection ofdist/framework), compared field by field byclick_tree_diff.py. - Comparison:
cli_compare.py(camelCase mapping, relocation check, literal matching modulo placeholders/formatting).
1. Modules (104 Python modules)
| Status | Count | Notes |
|---|---|---|
present (x.py -> x.ts, same path) |
72 | includes cli/*, agent/*, api/*, models/*, protocol/*, session/*, transport/*, utils/* |
re-export only (__init__.py) |
3 | agent/__init__, cli/__init__, cli/commands/__init__ (barrel files; Node has index.ts) |
| intentionally dropped, SDK/server-owned | 26 | compat.*, declarative.*, extensions.*, server.*, agent.builtin, agent.infer, api.deploy - not reachable from any abx command (PORTING.md "Module mirroring"; KNOWN-GAPS: api/deploy not ported) |
| MISSING | 3 | agent_sandbox/__init__ (package facade + __getattr__), _version (replaced by package.json version), utils/async_bridge (KNOWN-GAPS "no *_sync/async_bridge") - all justified |
Full table: inventory/out/modules.tsv.
2. Symbols (classes, functions, methods, constants, class attributes): 1579
| Status | Count |
|---|---|
| present with the same name | 933 |
renamed (snake_case -> camelCase, mapping by cli_compare.py) |
585 |
| MISSING | 61 |
All 61 MISSING symbols are accounted for (inventory/out/symbols-missing.tsv, rows with status MISSING):
| Group | Count | Justification |
|---|---|---|
*_sync wrappers (Sandbox.create_sync, FilesModule.read_sync, CommandsModule.run_sync, CodeContextModule.*_sync...) |
45 | KNOWN-GAPS: no sync variants in Node |
utils/async_bridge: run_sync, make_sync, _has_running_loop, _executor, T |
5 | KNOWN-GAPS async_bridge |
TypeVar constants F, T (cli/main, transport/streaming, utils/retry) |
3 | typing artefacts |
agent_sandbox.__getattr__ (lazy attribute loader) |
1 | Python import mechanism |
agent/mcp.py: _install_stop_signals, _line_exceeds_limit, _discard_overlong_line |
3 | re-implemented inside McpServer.run / StdioFramer (src/agent/mcp.ts:330-380, 640-700); behaviour covered by ledger tests |
agent/mcp_http.py: _LazyApp, _STARLETTE_IMPORT_ERROR |
2 | Starlette/uvicorn replaced by node:http (KNOWN-GAPS) |
config_cmd._tty_char_reader |
1 | masked-input reader implemented natively (src/cli/commands/config_cmd.ts, ledger test_config_masked_input) |
pydantic validators CustomCommandArg._validate_type, SandboxTemplate._validate_capabilities |
2 | validation inlined in src/models/template.ts (same Unknown capability ...; allowed: [...] message) |
session.local._get_lock |
1 | mkdir-lock (KNOWN-GAPS) |
EnvelopeStreamParser.__slots__ |
1 | Python-only |
No symbol is missing without an explanation. No BUG.
3. Click tree: commands, groups, options, arguments
click_tree_diff.py: 66 commands, 315 parameters, 0 differences (type, name, help, short_help, epilog, hidden,
deprecated, subcommand set and order, context_settings, and for every parameter: opts, secondary opts, type repr,
default, required, nargs, multiple, is_flag, envvar, help, hidden, choices, metavar, callback presence). The checker was
validated with a mutated JSON (it flags a 1-char change), so "0" is not vacuous.
4. Environment variables read
cli_compare env check: 97 env-name sites in Python CLI-reachable modules, 97 present in cli/src, 0 missing.
(76 further sites live in dropped server/SDK modules.) Env vars used only by the Node port (test harness) are not
user-facing.
5. User-facing message literals
Python literals classified message in CLI-reachable modules: 2587 found verbatim, 92 not found verbatim, plus 386
that live in dropped modules (server, compat, declarative, extensions, deploy). After matching each literal against the
TS source (exact -> stripped -> joined -> per-line -> segments split on {}/%s placeholders), the
128 rows of inventory/out/literals-missing.tsv (92 messages, 35 identifiers, 1 path) are the complete residue.
Every row is classified:
| Class | Count | Why not found / verdict |
|---|---|---|
regex patterns (re.compile, re.sub, re.search) |
32 | ported as JS RegExp literals; textual form differs ((?im) -> flags). Behaviour covered by ledger tests (adopt, repl, qwen_code, dockerfile_sources, config_cmd) |
strftime / URL-encoding constants (%Y%m%d-%H%M%S, %Y-%m-%dT%H:%M:%SZ, %7E, %20) |
7 | native helpers (src/agent/_pycompat.ts:319 ...) |
cli/main.py lazy-import table (agent_sandbox.cli.commands.sandbox:create ...) |
21 | Python import paths, meaningless in Node |
pydantic Field(description=...) strings (models.sandbox, models.session, transport.config) |
13 | Node models carry no pydantic descriptions; never printed by the CLI |
identifier-only keys (on_activity, modelProviders, structured_result, retry_after, creationflags, __main__, abx-activity-tick...) |
35 | camelCase / property names in TS (onActivity...), Python-only threading / subprocess kwargs |
Python-only install hints (pip install 'agent-sandbox[mcp]', [alicloud], websockets package is required, Starlette is required..., HTTP mode needs uvicorn) |
5 | optional Python extras do not exist in Node |
SDK deploy logs and 10m default (Deploy completed..., Deploy failed, killing sandbox, Failed to kill sandbox after deploy error, max_wall_time="10m") |
4 | api/deploy / Sandbox.deploy not ported (KNOWN-GAPS) |
utils.async_bridge log line |
1 | module dropped (KNOWN-GAPS) |
template_guide prompt block (Chinese "Dockerfile rules" with pip install agent-sandbox) |
1 | documented change: SDK install hint -> agent-sandbox-server (KNOWN-GAPS, 3 lines) |
tar open modes (r:*, r:gz) |
2 | src/agent/_archive.ts, src/utils/_tar.ts auto-detect |
concatenated literals (". Use --force to overwrite." x4 after an f-string; "Build, push, and create template in one step." docstring present in click help) |
5 | verified present as ... + "Use --force to overwrite." in src/cli/commands/{sandbox.ts:743,793,template.ts:2226,2271}; help string covered by the click-tree diff (0 differences) |
\u9fff range test (any("\u4e00" <= ch <= "\u9fff")) |
1 | present as regex /[\u4e00-\u9fff]/u (src/cli/commands/template.ts:2008) |
fc_template "Official Alibaba Cloud FCSandbox SDK is not installed" (+ pip install hint) |
2 | Python SDK dependency; Node uses the bundled @alicloud/fcsandbox20260509 client |
glob("*.json") path |
1 | .endsWith(".json") at src/session/local.ts:128 |
Result: 0 user-facing message literals missing (no BUG).
6. Exit codes
Exit sites (sys.exit, raise SystemExit, ctx.exit, EXIT_* constants): Python 63, Node 62 per module
(inventory/out/exit-sites.txt). The single delta is cli/commands/mcp: Node has one extra sysExit(3)
(src/cli/commands/mcp.ts:939, uvicorn start-up failure). In Python that exit comes from inside uvicorn.run itself
(uvicorn exits with status 3 when it cannot start), so the observable exit code is identical; it is the documented
"uvicorn replaced by node:http" gap. x if result.success else 1 is equivalent to result.success ? 0 : 1.
All of exit codes 0-6 and the EXIT_* mapping in cli/main (17 sites) match one to one. No exit code is lost.
7. File paths, config keys, TOML/YAML keys
Literals of kind path: 112 present, 1 "missing" (*.json glob in session/local.py: present as .endsWith(".json") at
src/session/local.ts:128). Config keys (api_key, api_url, domain, region, acr_*, llm_*, http_*, shortcuts.*...)
are all present as literals (they are part of config_cmd ledger tests). ~/.abx/{config.toml,.env,sessions/},
./.env, template.yaml/sandbox.yaml, .dockerignore, Dockerfile, commands.py all present.
8. HTTP routes / endpoints called
endpoint literals: 76 present, 61 only in dropped modules (server routes server.routes*, api.deploy).
Every control-plane / data-plane URL fragment used by the CLI-reachable api/transport modules is present.
9. CLI-exposed log messages
logger.* literal checks are part of the message check above; the only misses are the deploy logs (not ported) and
utils.async_bridge logs.
10. Tests
All 2980 original test ids are accounted for: 0 unaccounted (see completeness-sdk-split.md section 3). Every ledger
entry (999 base ids / 1333 raw parametrised ids) has >= as many Node test instances as Python parameters, no skips
(inventory/out/ledger-params.txt, npm run parity:coverage -> 999 passed, 0 missing, 18 moved).
Verdict (CLI port)
Nothing omitted at the module, symbol, click-surface, env-var, message, exit-code, path and endpoint level.
Every absence is traceable to KNOWN-GAPS.md / PORTING.md. Stale cross-references in the maintainer docs are
tracked in completeness.md (F-02..F-05).