# Rust application Logout qualification — 2026-10-12

## Historical draft, superseded on 2026-10-13

The observations below describe the October 12 draft and its retained review
packet. They do not describe the current runtime. Upstream corrected the recovery
test expectations in `cea09afe7`; the owners agreed in `43bcaf37e` to keep the
retained-frame ordering. The archived proposed recovery patch is retired and
unapplied. The later ruling requires idle Logout requests to be forgotten and
active transport waits to stop promptly. The current implementation and complete
qualification are recorded in
[the October 13 lifecycle record](RECORD_2026-10-13_rust-logout-lifecycle.md).

## Contract and scope

The shared application Logout ruling is recorded in `docs/WIP_AGENT_CLAIMS.md`.
The caller-driven Rust operation is now `Session::logout() -> bool`, with
`logout_text(Option<&[u8]>) -> bool` for Text(58). It writes or queues one Logout
only while logged on and returns true for that accepted send. A repeated request
returns false without another frame, sequence consumption, callback or a change
to the original confirmation deadline. Before startup and after the exchange
ends it returns false without sending. An unanswered initiator Logon is closed
immediately without sending Logout.

A caller continues to drive the manual session to flush queued output and await
the reply or timeout. For managed runs, the existing `LogoutHandle::logout()`
queues an owner request and returns unit, as C++'s void request does. The owner
ends its run without reconnecting. Idle requests retain the existing Rust
behavior: they are remembered for one subsequent run. The five initiator handle
states are regression controls; their production behavior was already correct.

Internal protocol refusals and replies retain their own send path independently
of the application operation. The refusal control now drives a real inbound
Logon through an application hook that rejects admission; it does not depend on
an unrestricted public sender. The other Rust owner retains the claimed public
`send_logout`/`send_logout_text` restriction and private `emit_logout` change on
`s/claude-rust-settings`; its pending box is preserved. This wrapper calls that
public sender only from LOGGED_ON, compatible with its proposed restriction. The implementation is in a private `logout`
module with public inherent Session methods; the concurrently claimed inbound
Logon walk in `session.rs` is untouched. This is a lifecycle qualification, not
venue certification or a change to the static 82/82 capability score.

## Source pins and differential check

- Baseline: `3b7d5c049` (the claim commit on `59f1cba87`; unchanged Rust engine).
- First complete qualification: focused `0ce2c1d56`, integrated
  `97535b24e44b00fc8e7efbb80af80d7e13795e41` on `b991b0d50`.
- Integrated candidate: `670250ea9cd17b0a850a8c83c718902c40d951ee` on
  `84d6c4b40a6641924d96bd1aa3c0ec9a4c508674`. It preserves the other owner's
  claim and tests the real inbound refusal hook. All 17 focused cases pass both
  editions; the identical baseline test body again passes 9 / fails 8.
- **The integrated complete gate fails**, so the application operation is a draft
  on `s/codex-libhft`, not published to main. The existing library test
  `admission_checkpoint_refusal_stops_deferred_reply_and_new_recovery` fails after
  the upstream retained-Reject recovery changes (`e61d6eda7`, `f16f9606e`).
- The final test body is identical in the baseline and focused candidate. The
  baseline alone appends a compatibility trait delegating `logout` to the former
  public `send_logout` and `logout_text` to `send_logout_text`, with success code
  zero mapped to true. It changes no engine source and measures that former
  sender's behavior; it does not claim that the new inherent API existed before.
- Both baseline editions: **9 controls pass, 8 behavior checks fail**, no ignored
  cases. Both corrected candidate editions: **17 pass**, no failures or ignores.
- Integrated inputs: **372 Rust** and **632 shared** path/hash pairs, including
  the new upstream provider parity test. The first complete green qualification
  (371 Rust inputs) is retained separately under `original-gates`.

The fixture covers the five ruled states, initiator and acceptor manual sessions
in fast/safe/test modes, Text preservation, strict original deadline and disabled
timeout, a real raw TCP unanswered Logon, store/overflow refusal, a still-attached
ended connection, a full Unix socket with queued output, and application hooks.
Raw managed peers independently build FIX frames, check BodyLength/CheckSum,
observe EOF and count connections with reconnect enabled. They never use another
Session to answer Logout automatically. A bounded watchdog is joined after each
run. Fixture sockets have owning Io handles or standard-library owners; no
filesystem runtime fixtures remain.

## Complete gates and resources

At the first integrated source `97535b24e`: complete default/open stages pass
**2,152 / 1,960**, each with one existing ignored builders doctest; strict
all-target Clippy passes both. Those results do not qualify the later recovery
changes or the revised refusal control.

At `670250ea9`: final baseline/focus comparisons pass as above. The default full
stage fails: **1,473 library tests pass, 1 fails**; later integration/doc targets
are not reached. The selected-stage result is 0 ran, 1 failed, 0 skipped. Final
open full and Clippy gates are not run after that failure. Scoped rustfmt, public
export scan, inventory/matrix checks and all **13** current inventory tests pass.

Source review identifies the ordering issue: `try_resolve_pending` splices a
retained boundary and sends a later watermark request before `advance` checkpoints
the retained receipt. That send may flush a queued batch before checkpoint refusal.
A proposed patch defers that watermark request until the existing checkpoint
succeeds and clears its flag on fault/clear/reconnect. It is **not applied or
runtime verified**: `session.rs` remains claimed by `claude-rust-settings`, and
permission for this narrow recovery fix is pending. The Logon work is outside the
proposal. Publication and final qualification remain pending.

The full stages run through `tools/run-conformance`, retaining command, stdout,
stderr and JSON. Selected-stage summaries must be 1 ran, 0 failed, 0 skipped;
PARTIAL names the unselected monorepo stages, not skipped Rust tests. Cargo and
Rust are 1.92.0; strict Clippy uses the retained 1.93.1 toolchain.

HP holds one exclusive `isol-no-shared` CPU lease for the serial full/Clippy gates:
`-j2`, CPUs 0–1, one test thread, dev/test debug info disabled. Its 21 GiB RAM
requires at least 8 GiB available before starting. The guard stops only its own
child group if available RAM drops below 5 GiB or foreign heavy work appears.
All build output is under `~/build/codex-rust-ibv/libhft`. No heavy job starts on
BEELINK2; the other sessions' busy leases are respected.

## Corrections and retained packet

Two draft fixture mistakes are retained rather than called valid negative
evidence: the first compile accessed private sequence fields (corrected to the
public getters); the next draft forgot `LibhftTransport=transcript`, which
correctly refused a transcript under a TCP label. The final baseline/candidate
comparison repeats after both corrections and after replacing the direct raw
sender control with the inbound refusal hook. A coordination-only rebase conflict
keeps all upstream claims and their pending status rather than replacing them. A unit-return signature check uses a
typed function pointer. The first draft candidate histories are preserved in the
source bundle. The squashed session branch is refreshed with a lease against its
own prior tip; no main history is rewritten.

The final evidence destination is `~/archive/libhft/rust-application-logout-20261012`
on BEELINK2, HP and Scan. While approval/publication are pending, the retained
review packet is `~/archive/libhft/rust-application-logout-review-20261012`
on BEELINK2, HP and Scan: pinned fixture variants, initial failures, final baseline
and focus outputs, full-stage commands/output/JSON, Clippy logs, input hashes,
candidate source bundles and helper scripts. Topic scratch is removed only after
review archive checksum and source-bundle verification; final qualification is
a separate follow-up after permission and the recovery fix. The ongoing
parity worktrees and their ordinary Cargo outputs are retained.
