|
| 1 | +# Recorder Exit Code Policy – Implementation Plan |
| 2 | + |
| 3 | +Plan owners: codetracer Python recorder maintainers |
| 4 | +Related ADR: 0017 – Recorder Exit Code Policy |
| 5 | +Target release: codetracer-python-recorder 0.x (next minor) |
| 6 | + |
| 7 | +## Goals |
| 8 | +- Default the recorder CLI to exit with status `0` when tracing succeeds, even if the target script exits non-zero. |
| 9 | +- Preserve the script exit status in trace metadata and surface it through logs so users stay informed. |
| 10 | +- Provide consistent configuration knobs (CLI flag, environment variable, policy API) to re-enable exit-code passthrough when desired. |
| 11 | +- Ensure recorder failures (`start`, `flush`, `stop`, `require_trace`) still emit non-zero exit codes. |
| 12 | + |
| 13 | +## Non-Goals |
| 14 | +- Changing how `ct record` parses or surfaces recorder output beyond the new default. |
| 15 | +- Altering metadata schemas storing script exit information. |
| 16 | +- Introducing scripting hooks for arbitrary exit-code transforms outside passthrough vs. success modes. |
| 17 | + |
| 18 | +## Current Gaps |
| 19 | +- `codetracer_python_recorder.cli.main` (`codetracer_python_recorder/cli.py:165`) always returns the traced script's exit code; there is no concept of recorder success vs. script result. |
| 20 | +- `RecorderPolicy` (`src/policy/model.rs`) and associated FFI lack an exit-code behaviour flag, so env policy and embedding APIs cannot control the outcome. |
| 21 | +- No CLI argument or environment variable communicates the user's preference, and the help text/docs imply passthrough semantics. |
| 22 | +- There are no regression tests asserting CLI exit behaviour; `ct record` integration relies on current passthrough behaviour implicitly. |
| 23 | + |
| 24 | +## Workstreams |
| 25 | + |
| 26 | +### WS1 – Policy & Configuration Plumbing |
| 27 | +**Scope:** Extend recorder policy models and configuration surfaces with an exit-code behaviour flag. |
| 28 | +- Add `propagate_script_exit_code: bool` to `RecorderPolicy` (default `false`) plus matching field in `PolicyUpdate`; update `apply_update`/`Default` implementations. |
| 29 | +- Extend PyO3 bindings `configure_policy_py`/`policy_snapshot` to accept and expose `propagate_script_exit_code`. |
| 30 | +- Add environment variable `CODETRACER_PROPAGATE_SCRIPT_EXIT` in `policy/env.rs`, parsing booleans via existing helpers. |
| 31 | +- Update Python session helpers (`session.py`) to pass through a `propagate_script_exit` policy key, including `_coerce_policy_kwargs`. |
| 32 | +- Unit tests: |
| 33 | + - Rust: policy default and update round-trips (`policy::model` & `policy::ffi` tests). |
| 34 | + - Rust: env configuration toggles new flag and rejects invalid values. |
| 35 | + - Python: `configure_policy` keyword argument path accepts the new key. |
| 36 | + |
| 37 | +### WS2 – CLI Behaviour & Warning Surface |
| 38 | +**Scope:** Teach the CLI to honour the new policy and compute the final exit status. |
| 39 | +- Introduce `--propagate-script-exit` boolean flag (default `False`) wired into CLI help; set `policy["propagate_script_exit"] = True` when provided. |
| 40 | +- After `start(...)`, cache the effective propagation flag by inspecting CLI config and, when unspecified, consulting `policy_snapshot()` to honour env defaults. |
| 41 | +- Rework `main`'s shutdown path: |
| 42 | + - Track recorder success across `start`, script execution, `flush`, and `stop`. |
| 43 | + - Decide final process exit: return `script_exit` if propagation enabled, otherwise `0` when recorder succeeded; use a distinct error code (existing) when recorder fails. |
| 44 | + - On non-zero script exit with propagation disabled, emit a concise stderr warning mentioning the exit status and `--propagate-script-exit`. |
| 45 | +- Ensure the script exit status continues to flow into `stop(exit_code=...)` and metadata serialisation unchanged. |
| 46 | +- Add CLI unit/integration tests (pytest) covering combinations: default non-propagating success/failure, `--propagate-script-exit`, and recorder failure paths (e.g., missing script). |
| 47 | + |
| 48 | +### WS3 – Documentation, Tooling, and Release Notes |
| 49 | +**Scope:** Update user-facing materials and automation checks. |
| 50 | +- Refresh CLI `--help`, README, and docs (`docs/book/src/...` if applicable) to describe default exit behaviour and configuration options. |
| 51 | +- Document `CODETRACER_PROPAGATE_SCRIPT_EXIT` and Python policy key in API guides. |
| 52 | +- Add CHANGELOG entry summarising behaviour change and migration guidance for users relying on passthrough. |
| 53 | +- Extend CI/test harness: |
| 54 | + - Add regression test via `just test` hitting CLI exit codes (likely in Python test suite under `tests/`). |
| 55 | + - Update any existing `ct record` integration smoke tests to pin the expected default (0) where relevant. |
| 56 | +- Coordinate with desktop CLI maintainers to flip their expectations once the recorder release lands. |
| 57 | + |
| 58 | +## Timeline & Dependencies |
| 59 | +- WS1 should land first to provide configuration plumbing for CLI work. |
| 60 | +- WS2 depends on WS1's policy flag; both should merge within the same feature branch to avoid transient inconsistent behaviour. |
| 61 | +- WS3 can progress in parallel once WS2 stabilises, but final doc updates should wait for CLI flag names to settle. |
0 commit comments