# Persistent backend release evidence
Scope: [#505](https://github.com/magimetal/magi-code/issues/505), under
[parent #500](https://github.com/magimetal/magi-code/issues/500).
**Release readiness is not established.** The coordinator, Unix adapter and
writer exclusion exist; adding CI is not a macOS/Linux pass or frontend completion.
This supplements, not replaces, the [normal release procedure](../release.md).
## Evidence matrix
The [CI lifecycle-evidence job](../../.github/workflows/ci.yml) runs the same
partitions on `ubuntu-latest` and `macos-latest`, using Rust 1.88.0, isolated test
stores and synthetic workers. No live provider credentials are required.
Local macOS verification passed `cargo test --quiet`, `cargo check --quiet`,
`cargo fmt --check`, and `cargo clippy --all-targets --all-features -- -D warnings`.
[CI run 34008178878](https://github.com/magimetal/magi-code/actions/runs/34008178878)
did not start its jobs because of the billing/spending limit: **no CI pass or OS
artifacts**. Linux execution is excluded from this acceptance scope by the user;
local results do not establish Linux or packaged-launch support.
| Contract / race | Exact suite and evidence boundary |
| --- | --- |
| Frontend death after acceptance; busy stop; reconnect completion | `cargo test --locked --quiet --lib service::` includes [`accepted_synthetic_turn_survives_frontend_process_death_and_rejects_busy_stop`](../../src/service/unix/survival_tests.rs). Real processes, synthetic work; not cgroup teardown evidence. |
| Singleton launch, aliases/root isolation, unsafe/stale endpoints, version refusal, controller disconnect, descriptor exhaustion | `cargo test --locked --quiet --test unix_daemon_process`; [process suite](../../tests/unix_daemon_process.rs), including `aliases_long_paths_roots_and_concurrent_launchers`, `idle_socket_controller_holds_lease_until_disconnect`, and `descriptor_exhaustion_preserves_existing_client_and_recovers_accepts`. |
| Crash recovery, busy reuse, stalled handshakes | The process suite covers completed session creation, unknown old operations, busy reuse and handshake expiry. `service::` adds [`daemon_crash_does_not_replay_an_accepted_active_turn_after_restart`](../../src/service/unix/survival_tests.rs): kill during blocked synthetic provider work, release the writer lease, restart with unknown outcome and unchanged durable history, without replay. No execution continuation after crash is claimed. |
| Staged activation and uninitialized connections | The process suite adds `staged_executable_activates_only_after_explicit_idle_stop` and `uninitialized_socket_blocks_idle_stop_only_until_admission_expires`. Test binaries and local sockets, not signed-package upgrade or GUI-launch evidence. |
| Standalone writer handoff and CLI regressions | `cargo test --locked --quiet --lib sessions::` and `cargo test --locked --quiet --test cli_smoke`, plus [`standalone_writer_waits_for_daemon_cleanup_and_control_release`](../../src/service/persistent/handoff_tests.rs) under `service::`: writer admission waits through cleanup/control ownership while another session remains independent. Not physical-terminal evidence. |
| Zero-client execution, cleanup-held lease, late claim, stale Stop, independent sessions, persistence failure, lost acceptance/outcome retention | `service::` includes [persistent tests](../../src/service/persistent/tests.rs): `zero_clients_execute_tools_once_and_hold_lease_through_cleanup_and_late_claim`, `stale_grants_do_not_start_or_cancel_after_disconnect_and_sessions_are_independent`, `bounded_outcomes_expire_without_reexecution_or_secret_retention`, and `persistence_failure_and_cleanup_panic_release_only_after_worker_exit`. Synthetic coordinator schedules do not prove every process race. |
| Disconnect while settings/auth locks are held; preparation fencing; cancellation cleanup | `service::` includes [admission tests](../../src/service/persistent/admission_tests.rs) and [auth tests](../../src/service/persistent/auth_tests.rs). Idle-stop/admission ordering is covered by `queued_stop_rejects_later_admissions` in [entrypoint tests](../../src/service/persistent/entrypoint.rs). |
| Claim sequence and committed login handoff | `service::` includes [`handoff_tests`](../../src/service/persistent/handoff_tests.rs): `claim_snapshot_and_terminal_delivery_cover_both_sequence_boundaries` and `committed_login_survives_initiating_disconnect_and_lookup_reports_cleanup`. Login uses the production exchange/commit/completion helper with a fake exchange, pauses after durable commit, and verifies credentials survive disconnect. No live OAuth request is made. |
| Production persistence-failure projection | `service::` includes [`persistence_failure_projects_failed_terminal_with_authoritative_assistant_text`](../../src/service/turns.rs): force a real terminal append failure and check failed status, persistence error, accepted text and sequence through the production terminal helper. Not a live provider turn. |
| Automatic idle expiry | `service::` includes [`entrypoint` tests](../../src/service/persistent/entrypoint.rs): `automatic_idle_expiry_prioritizes_queued_admission`, `automatic_idle_expiry_rejects_admission_after_exit`, and `automatic_idle_expiry_waits_for_disconnected_accepted_settings_write`. Controlled idle clock and blocked local settings write, not OS suspend/logout evidence. |
| Stdio v1 regression and consumer decoding | `service::` plus `cargo test --locked --quiet --test service_conformance`; [v1 fixture contract](../../tests/fixtures/application_service/README.md). The consumer suite is not a v2 adapter test. |
| V2 claim-before/after-terminal, uncertain outcomes, duplicate intent, stale grants, auth/settings expectations | `python3 tests/fixtures/application_service/persistent_v2/check_vectors.py`; [schema-2 vectors](../../tests/fixtures/application_service/persistent_v2/README.md). Structure and narrow consumer projection only; no server execution or Swift compatibility claim. |
### Acceptance checklist
- [x] Local process/coordinator acceptance tests above pass on macOS.
- [x] Full suite, build, formatting and Clippy pass for the combined changes.
- [ ] Successful CI artifacts for the exact candidate; linked run never started.
- [ ] Privileged distinct-user security setup and supported-launch/resource evidence below.
- [ ] Linux OS evidence before claiming Linux readiness; excluded from this local acceptance scope.
### Fixture revision and artifacts
Baseline fixture revisions (wire, fixture schema and package versions are distinct):
- V1/schema 1: commit `066483319b762e166a8e4defced56650e9186ef3`.
- V2/schema 2: commit `62577fdacc91b6d52be4ef447ed8ef0ef16d67ea`.
Each platform uploads `lifecycle-evidence-<runner>-<commit>-<attempt>` for 30 days:
`identity.txt` records the tested commit, runner/kernel, Rust/Cargo versions and
fixture Git blob IDs; `test-health.tsv` records partition outcomes and run identity;
partition logs retain failures and test counts. Upload runs even after failure.
A missing partition, skipped test, timeout, cancelled run or missing artifact is
**unavailable evidence**, never a pass. Review logs, not only the job badge.
Before release, retain both artifacts beyond CI expiry and link their run URLs,
exact commit, fixture IDs and results in the release review. Re-run after changes;
results from another revision are not evidence for the release candidate.
## Launch, upgrade and rollback
Use the [Unix launch contract](unix-daemon.md#commands-and-identity), including
[trusted installation and idle-only activation](unix-daemon.md#trusted-installation-and-activation)
and [environment/lifetime restrictions](unix-daemon.md#process-lifetime-and-environment).
Stage a verified immutable versioned executable; do not overwrite the running
helper or launch through PATH/a mutable symlink. Canonical workspace plus state
root identifies one daemon. Pause client admissions, stop using the old binary,
and confirm idle exit before selecting the new binary. Busy/incompatible means
refuse, not kill or start a parallel version. Rollback uses the same procedure.
Disconnect is not Stop; uncertain acceptance requires lookup/reconciliation,
never automatic prompt replay.
## Unavailable release gates
| Gate | Evidence still required |
| --- | --- |
| OS lifecycle artifacts | Successful artifacts for the exact release candidate remain missing. Focused local macOS passes are not CI artifacts; Linux execution is user-excluded here and remains required before claiming Linux readiness. |
| Cross-UID rejection | Controlled distinct-user test requires privileged setup on each claimed platform; same-user socket tests are insufficient. Not established by this local run. |
| Resource/lifetime deployment checks | Memory/thread/descriptor bounds under sustained reconnect and slow-client load, plus the intended supported launcher policy. Existing queue and descriptor tests are narrower. Forced session/cgroup teardown, logout and reboot are unsupported contexts, not promised survival gates; `setsid()` cannot escape cgroup teardown. |
| Trusted distribution and activation (separate packaging gate) | Actual signed/notarized macOS helper and Linux release digest/installation checks, Finder/GUI environment/auth behavior, and packaged upgrade/rollback. Local staged-executable tests are not packaging evidence; these signed/live frontend checks do not block backend API publication. |
| Companion v2 integration | [Companion #12](https://github.com/magimetal/magi-companion/issues/12) and [#13](https://github.com/magimetal/magi-companion/issues/13): production decoding, complete-event/bound preflight, reconnect/Stop/uncertainty UX, and helper integration evidence. Rust vectors do not complete these follow-ups. |
| Physical Mission Control / frontend behavior | Actual terminal and GUI handoff validation; synthetic backend tests cannot establish frontend completion. |
Backend readiness requires the backend lifecycle, security and supported-launch
evidence above. Companion integration and signed/live frontend gates are separate:
they do not block backend API publication or a tested backend-ready milestone.
Parent #500 remains open until both backend and Companion gates are complete.
Logout, reboot, execution continuation after crash or forced session/cgroup kill,
and live writer takeover remain outside the supported contract.