magi-code 0.96.5

Repository-aware CLI coding agent for terminal work
Documentation
# Local-agent backend handoff

Contract: [Local-agent stdio protocol](local-agent-protocol.md). Backend work does not depend on a frontend release. Ma-gi's independent decoder, application-state and native-control evidence is linked under [Integrated acceptance](#integrated-acceptance).

Historical validation records for the pinned revisions below. Current repository retains no process-test suite or trace recapture runner. These observations do not verify later backend revisions.

## Tested backend

Synthetic process fixtures tested commit `490c366c35011ea5aa583eb8406a69ec7f869753`, package `0.96.0`, on macOS. Protocol name `magi-code.local-agent`, protocol version `1`; trace wrapper `fixture_version=1` is a separate format. Package version alone does not prove capability support. Require all nine advertised operations before enabling chat.

Build in a disposable checkout of that commit:

```sh
git checkout 490c366c35011ea5aa583eb8406a69ec7f869753
cargo build --locked --bin magi-code
```

Use an explicit absolute executable path to that build. Start one owned subprocess with argv `serve --stdio`, stdin/stdout pipes and a separately drained stderr pipe. Set cwd to an existing `~/.ma-gi/agent`; do not pass cwd as a CLI argument. Resolve `MC_HOME` normally (default `~/.magi-code`), independently of cwd. Do not run the child through a TTY or redirect protocol stdout to a file.

Configure credentials/models through existing Mission Control `/login`, `/model` and `/settings` before starting the child. Provider environment variables must reach the child. Do not copy credential files, mutate global settings automatically or fall back to another provider after readiness failure. Initialization checks local readiness, not remote availability. See [provider authentication](provider-authentication.md).

Approved enabled MCP definitions can spawn processes or perform HTTP/OAuth refresh during initialization. Global approval of the canonical definition source remains mandatory; a project cannot approve itself. Per-command `approval.answer` is separate. Backend tools are not an OS sandbox. Existing CLI retention defaults to 30 days; `sessions.retention_days=0` disables automatic cleanup. The stdio endpoint adds no retention sweep.

## Synthetic traces

Captured from passing actual-child workflows using temporary cwd/home, local HTTP/MCP fixtures and synthetic conversations. Identifiers and context digests are illustrative, not reusable session IDs. Each JSON document contains metadata plus ordered `{ "direction":"client"|"backend", "frame":object }` entries. Serialize only `frame` plus LF when testing a wire decoder; do not send the wrapper. Recorded ordering is one valid execution, not a promise of identical delta boundaries or activity timing.

Repository artifacts under `docs/features/local-agent-traces/`:

| Trace | Observed outcome |
| --- | --- |
| [tool-turn.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/tool-turn.json) | Handshake, lazy session, persisted input, Code Mode write, text continuation, history, independent prompt, shutdown; exactly one controlled write |
| [resume-history.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/resume-history.json) | New child opens the same durable session, pages history, shuts down without executing another turn |
| [approval-allow.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/approval-allow.json) | Status remains responsive; stale/duplicate replies rejected; one allowed command effect; completed/durable |
| [approval-deny.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/approval-deny.json) | Denied command has no effect; failed/durable, partial assistant text preserved |
| [mcp-turn.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/mcp-turn.json) | Approved MCP call executes once; text continues; completed/durable; raw MCP result omitted from history |
| [cancelled-turn.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/cancelled-turn.json) | Stop acknowledgement precedes cancelled/durable terminal; partial reply survives |
| [degraded-turn.json](https://github.com/magimetal/magi-code/blob/main/docs/features/local-agent-traces/degraded-turn.json) | Required input persisted; later append fails; displayed reply reconciles; completed/degraded with null revision |

Fixtures contain protocol data, not live credentials or private reasoning. Recapture requires independent client validation using isolated cwd/home and synthetic inputs. Review captures before publication; production approval expiry remains 60 seconds.

## Client obligations

- Preflight `initialize` with required capabilities. Enforce protocol/version, UTF-8, frame/depth/content bounds and response/event identity before changing UI state; stdout contains only protocol frames.
- Keep draft/UI state locally. Save session ID for relaunch only after `input.persisted`. Admission is not persistence. Rejected preflight or failed required append must not appear as an acknowledged user submission.
- Replace deltas with complete `message.reconcile` parts. Tool-separated assistant segments remain distinct. `last_part=true` completes a message replacement, not execution. Do not append cumulative snapshots or treat a missing chunk as complete.
- Run/session/approval IDs are scoped to one child. Only explicit Allow can approve; Deny, Stop, EOF, disconnect and expiry cannot authorize execution. Denial/expiry end this protected turn as failed; cancellation ends it as cancelled. Neither implies rollback of prior effects.
- Wait for `run.finished` before another prompt/history request. Use its revision, not the input-ack revision. Completed/degraded is not durable; null revision requires explicit reopen. Resume restores history, not unfinished execution.
- Never retry an uncertain accepted prompt automatically. Child death or a lost terminal may leave durable input and completed tool effects. If an output deadline cuts a frame mid-write, discard its unterminated tail and keep outcome uncertain until explicit history inspection.
- On app quit, Stop/close input, continue draining output and stderr, wait under a bounded deadline, then terminate/reap a stuck child. Backend output drain and cleanup have separate 2-second bounds. MCP leases/resources may remain held until cleanup finishes. Agent lifetime equals application lifetime; no daemon, reconnect, heartbeat, sleep/reboot or crash-continuation guarantee.

## Verification evidence and limits

At the tested revision: full native suite passed (4,288 tests, 37 ignored), including 21 stdio process workflows, 9 CLI smoke tests and one public-contract integration test. Formatting, locked check, strict all-target/all-feature Clippy and diff checks passed. Full suite includes existing TUI regressions; it does not prove physical terminal compatibility or native GPUI behavior.

Process coverage includes malformed/oversized input, readiness/auth failure, cross-process writer conflicts, required/later append failures, EOF during provider/MCP tool/approval waits, broken output, stalled reader with Stop, shutdown during stalled provider work, ordered terminal delivery and explicit partial replay without automatic retry. MCP fixture logs count one `tools/call` across reopen and verify child cleanup. Approval tests use a pinned synthetic local judgment cache and a dead loopback HTTPS proxy; they exercise real protection/approval callbacks without contacting TypeSafe. Cache drift fails the workflow rather than opening a live service.

Seven captures were checked for metadata, frame size, monotonic sequence, matching request IDs, admission/persisted-input/event ordering, one terminal per run, no events after terminal and sensitive/raw-reasoning exclusion. Authoritative message/history reconciliation is asserted by their source workflows. Pressure/disconnect tests accept that terminal delivery may be impossible; replay still preserves one user input and partial assistant content.

Only production change is a cancellation check after Bash approval returns. Runtime APIs remain private; no new public Rust exports. Local `cargo semver-checks` is unavailable. GitHub checks for prerequisite PR #844 never started due to account billing/spending limits; no Linux, Windows or automated public-API-check success is claimed here. Unix pipe support is implemented for macOS/Linux; Windows serving explicitly remains unsupported. Additional platform/CI checks require separate execution.

At the backend handoff revision, Ma-gi native checks and independent decoder/state validation remained frontend work. No live provider checks or user-state access were performed for that handoff. Subsequent integrated evidence follows.

## Integrated acceptance

Backend tracker [#819](https://github.com/magimetal/magi-code/issues/819) retains its original four acceptance criteria. Delivery and evidence:

| Original criterion | Evidence |
| --- | --- |
| Child prerequisites, source evidence and native GitHub dependency edges agree | Backend children #820, #821, #822, #823 and #824 are closed, with native blocked-by edges forming that sequence. Frontend [#1](https://github.com/magimetal/ma-gi/issues/1) and children #2, #3 and #4 are closed. Frontend #2 depends on backend #820/#821/#822; #3 on frontend #2/backend #823; #4 on frontend #3/backend #824. All referenced prerequisites are closed. |
| Non-TTY open/create, send, streamed text, tool continuation, approval, cancel and restart/resume use the normal runner | Backend process captures above and independent frontend decoding cover the conversation flow. Actual frozen-child MCP continuation, pointer Allow/Deny/Stop and exact durable reopen are recorded separately from synthetic protocol/native UI observations. No frontend provider fallback. |
| Errors, partial durability, disconnect and lock conflicts remain explicit, without duplicate submission or tool execution | Independent worker observations cover admission/ack uncertainty, buffered-output drain, required nullable fields, persistence faults and explicit recovery. Actual-child observations cover busy-session rejection and effect-free reopen. Duplicate persisted identity is rejected before transcript mutation; uncertain drafts remain available without automatic resend. |
| Final backend/client smoke evidence records revisions and separate synthetic/native/live limitations | The immutable frontend [verification record](https://github.com/magimetal/ma-gi/blob/b9a7fcf00b7467ca68f958a04a1604c29590acfc/docs/verification.md) separates published captures, controlled processes, frozen-child workflows, native observations and human visual confirmation. |

Frozen backend: source `dd9e31890f70a00926b6ed90178614666e37ab15`, package `0.96.1`, executable SHA-256 `60cb267f5c7611f9cef6274f21e850152c2633d9bc04854e2468ddb1d88f80e5`. Earlier actual-child observations lacked per-launch hashes; they must not be assigned this revision. Published captures retain their original `490c366c35011ea5aa583eb8406a69ec7f869753` provenance.

Merged frontend evidence: `b9a7fcf00b7467ca68f958a04a1604c29590acfc` (PR #14). Production last changed in PR #12 (`94161c4`); final staged frontend `80a430b` used the same executable UUID `C0363200-FAEB-3699-A34B-8E8FD6F8527F`. Recorded native coverage includes pointer/drag/wheel, Unicode clipboard/selection, VoiceOver transcript/composer/error/approval actions, Japanese/Pinyin/Korean input at three sizes, and owned-child cleanup. User watched six Japanese/Pinyin candidate/main scenes and confirmed readability/placement without clipping, obstruction or hidden controls. This is human display evidence, not screenshot proof or an acceptance deferral.

The frontend record reports formatting, strict locked Clippy, locked desktop build and source review; no tests written or run during frontend verification. This reconciliation does not rerun those native workflows. No live provider/TypeSafe requests, other-platform certification, packaging or always-on guarantee. Child lifetime remains application lifetime.

Retained limits and incidents: inconsistent `AXFocused` despite successful observed workflows; earlier premature closure/approval attribution corrected; historical edits/reverts and failed capture/focus/restoration attempts preserved. Earlier unrelated-window/shell restoration and byte-for-byte cache/learning restoration remain unverified. Input/VoiceOver effective baselines were restored; disabled recording rows may leave running Ghostty access until user restart. Milestone acceptance does not certify restoration of historical external effects.