Files
KarandeepSWranch 6417d118f1 fix(sbox): silent failures caught by audit follow-up
Parallel-agent audit pass over the prior fix turned up two real silent
failures and a couple of missing test coverages. All in-scope of the
PR #251 review feedback (failures must be visible to scripts/agents).

Code fixes:

* core/codegen.py: generate_class split method body on the literal
  two-character string `\n` instead of an actual newline (line 589).
  Multi-line method bodies collapsed into a single line of malformed
  C# without raising, so `cli-anything-sbox codegen class --methods
  '[{"name":"X","body":"a;\nb;"}]'` produced broken output and
  exited 0. Compare with _format_method on line 412 for the correct
  pattern. One-character fix; no other call sites use the bad pattern.
* core/session.py: corrupt-file backup now uses a timestamp suffix
  (`session.json.corrupt.<unix-ts>`) instead of a fixed `.corrupt`
  name. A second corruption no longer silently overwrites the first
  preserved copy. Also broadened the stderr-write guard to catch
  ValueError (closed-stderr scenarios in pytest fd-capture mode) so
  the warning never silently disappears.

Test additions (+6, total 244, was 238):

* test_core.py::TestCodegenClass::test_generate_class_method_with_multiline_body
  - regression test for the codegen \n bug. Asserts each body line
    appears on its own indented line in the output.
* test_core.py::TestSession::test_session_load_corrupt_file_warns_and_preserves_backup
  - gates the new session.py behavior: malformed file is preserved
    with a timestamp suffix and a warning is written to stderr.
* test_exit_codes.py::TestOneShotFailureExitsNonZero::test_scene_list_missing_file_exits_one
  - true gate of the bare `except Exception -> _output_error` path
    (scene_list has no ClickException re-raise short-circuit, so the
    test would have observed exit 0 without the _output_error fix).
* test_exit_codes.py::TestOneShotFailureExitsNonZero::test_asset_info_corrupt_json_exits_one
  - covers the asset_info json_info.error surface path added in the
    prior commit.
* test_exit_codes.py::TestAuditedFailurePaths (new class, 2 tests)
  - test_asset_compile_returns_success_false_exits_one: monkeypatches
    sbox_backend.run_resource_compiler to return success=False and
    asserts CliRunner exit_code == 1 with stderr in the message.
  - test_server_info_version_error_exits_one: monkeypatches
    get_sbox_version to return an error dict and asserts exit_code 1.
    These are the only way to test these paths without an installed
    s&box (and resourcecompiler).

Doc updates:

* TEST.md: test_core 155 -> 157, test_exit_codes 16 -> 20 (with new
  TestAuditedFailurePaths class breakdown), total 238 -> 244. Also
  fixes the prior commit's stale "3 classes" count for test_exit_codes
  (it had 4 then; now 5 with TestAuditedFailurePaths).
* README.md: per-tool table 238 -> 244; file tree breakdown updated.
* README_CN.md: per-tool table 238 -> 244; total 1,757 -> 1,763 in 4
  places (marketing copy, table TOTAL, test-results TOTAL, footer).
  The breakdown line previously stale at 1,741 is now corrected to
  1,763 (1,258 unit + 486 e2e + 19 Node.js).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 00:59:42 -07:00
..