# Libtrading canonical public Session qualification — 2026-10-19

Both HP and SCAN pass a new four-flow functional fixture through the pinned
SDK's public `fix_session_send` and `fix_session_recv` APIs. Each flow uses
separate client/server TCP processes, actual Logon/Logout frames and twelve
canonical cycles. Independent cold replay checks both original peer captures,
full bodies and every owner sink. This is functional evidence only: no
latency, offered-rate, Stage 5 or matched comparison is admitted. Zero cells
are exported. The full plan remains incomplete.

## Exact source and configuration

The existing provenance identifies upstream libtrading commit
`9cf4dfa58fd7201935f7bf7e9046d78653e041d3`. Its independently fetched archive
has 149 regular files, 796,370 bytes and SHA-256
`f8081622ddf0dace75a3b95fb9b8e1b12e377a6a833dc6bb8940c5bb0f1a4588`.
The sorted original content inventory is
`30661ae985c174427e0d270196286d07ea1b1772717db0dfa4965dac66b89a4d`.
The original archive contains the BSD licence. The old shared cache differs
at the capacity header and its dialect generator; it is read-only throughout
this work and supplies no compiled product to this qualification.

Fresh SDK copies receive only the existing tracked
`libtrading-stage5-field-capacity.patch`, SHA-256
`e9c950f0e037f07ce655c43f64916b1d8a0aa5073f3958fcf0615d0b20017434`.
It raises the receive allocation from 48 to 128, needed for the 63-field
application book plus session headers. All other 148 original files remain
byte-identical. SDK sources become read-only before compilation, and all 149
bytes/modes remain unchanged through the complete run.

The explicit configuration is `canonical_text_numbers_v1`:

- The public `fix_dialect::tag_type` extension retains numeric application
  fields as SDK strings. Extraction obtains bounded values through
  `fix_get_string`, checks their spelling and bounds, and uses the original
  `fix_atoi64` for integer components. Five-place price conversion and the
  complete book/acknowledgement checks are application extraction work.
- The public `FIX_PARSE_FLAG_NO_TYPE` accepts `V`, missing from this SDK's
  built-in type catalogue. It preserves the SDK's framing and checksum
  parser; the application verifies original MsgType and incoming sequence.
- Each Session owns its `fix_session_cfg` until after `fix_session_free`.
  The SDK retains pointers to those strings; a temporary configuration must
  not escape. The new fixture does not borrow the legacy adapter's Session
  construction or extraction implementation.

This is a declared configuration distinct from the SDK's default floating
numeric dialect and the legacy benchmark. It is not a changed SDK parser or
a custom FIX encoder/decoder. Fresh SDK fields, messages and public Session
calls produce and consume every actual frame. The independent cold reader
parses captures separately and never substitutes re-encoded frames.

## Build and execution

Both jobs run as UID/GID 1000 under the host CPU helper. HP uses high-priority
`isol`, CPUs 8–17; SCAN uses normal-priority `shared`, CPUs 0–9. These are
functional runs with no timing grade. They use the same GCC toolset 15.2.1.

The worker compiles six unchanged original FIX component sources:
`lib/itoa.c`, `lib/buffer.c`, `lib/read-write.c`,
`lib/proto/fix_message.c`, `lib/proto/fix_session.c` and
`lib/stringencoders/modp_numtoa.c`. Their flags are GNU C99, `-D_GNU_SOURCE`,
`-O3`, `-g0`, `-fPIC`. The separate fixture is C++17, `-O2`, `-DNDEBUG`, linked
against that fresh static library and zlib/libm. Objects, the deterministic
archive, generated empty little-endian config header and executable all live
outside the SDK/repository. The original optional protocol generators and
unrelated SDK programs are not built: this is FIX-component qualification,
not a whole-SDK build claim.

| Product / receipt | HP | SCAN |
|---|---|---|
| FIX component library | `cfc66b7888fc4c51b2adb49c055cf18c8d74bfe10135dad651f321fc5a15cc18` | same |
| Fixture executable | `2a0da5affa57ea852e8c90dca23e11178926cfcb762f6fba282292e0b9e411b2` | same |
| Native receipt | `4a662a9df57fc2572f0be23ebc8804b01fe2e3b20bc325fd63ddc482e57dcc8d` | `60c110849f821bf66628c2a4f9ed125e84ad7be02f446f8a00e619bf8de3b576` |
| Cold review | `2563cb29edb16be154de1b661b7a4a511f84905c663cd39307a0593a62dfc279` | `2ce71af1cf4279b35436f6f73554fc49b1f22ef35a3ba9366b25c5637089e581` |

Worker SHA-256:
`eb7afcfc38fbe4e97b490de57a1023d538037ef5ba5b9c34cd3e430792ddea22`.
Public canonical helper:
`92c1b28e14cea984747db0a69570983d389ac0f9e71af4027b0d6e23f24c2994`.
Public actual-TCP fixture:
`d44e3f8beb404b91689f74b7a5af6f809d880da541c2a401c8ad953f517f2e86`.

## Independent actual evidence

Per host, the four flows have 48 cycles, 120 application frames and 16
administrative frames **per peer**. All counterpart frames match byte for
byte with opposite directions. The cold reader checks checksum, BodyLength,
both comp IDs, contiguous per-sender sequences, full canonical values/order,
all twenty standard-book entries and the mixed flow's snapshot-derived order
and acknowledgement. Distinct child PIDs and their parent relationships
prove separate client/server processes. Each server is waited for.

| Flow | Clock-owner role for a future benchmark | Actual sink at 12 cycles | Folds |
|---|---|---:|---:|
| `nos_er` | client | 11083906249535899689 | 144 |
| `md` | client | 8452780597659586061 | 756 |
| `md_nos_er` | client | 2230293092686911834 | 900 |
| `tick_to_trade` | server | 17327418772661543379 | 60 |

Non-owner sinks remain zero. The tick consumer derives its order from the
parsed two-entry book; its server owner folds the returned order. The mixed
owner folds the complete book and its correlated acknowledgement.

All 39 actual SDK Session field-reader controls refuse missing/duplicate
required order fields, invalid quantity/price spellings and bounds, changed
order identity and changed first/last book entries. These controls deliberately
use one sending Session, including malformed `W` inputs; their role is not a
normal flow or timing proof. Each sent control matches its receiving capture.

The new source checker and existing independent reference suites pass **52
tests**, with no skips. Controls with matching bilateral captures and correct
checksums still reject wrong sequence, order or book values. Public source/doc
scrubbing checks three files with zero findings. Each host's **33 bounded
payloads** is independently collected and hash checked under
`~/build/codex-fullbench/libhft/libtrading-canonical-review-20261019-v2/<host>`.
Original native products and logs remain on their respective hosts.

## Retained failed attempts and next gate

Both initial v1 runs built the original FIX components and fixture but stopped
at Logon, before application cycles: the fixture incorrectly expected tags
98/108 to be SDK integer fields. This pinned SDK exposes both as strings.
The corrected v2 fixture reads those original SDK strings and validates them
through checked integer extraction. The initial immutable inputs, failed
status and handshake captures/logs remain retained separately. The SDK is not
changed to accommodate that fixture mistake.

The cold reader also initially applied normal server-origin `W` direction to
the deliberate single-sender negative controls. Its corrected scope keeps
strict normal-flow directions, checks control sender/sequences separately,
and replays the same unchanged actual native evidence. No native or physical
rerun was needed for that reader correction.

Both corrected qualifications are complete. A timed producer must still
qualify pre-warmup capture closure, warmup resets, original primary/delay clock
series, measured admin observations and prepared-wire tick boundaries before
a fresh physical DAC controller can promote results. Existing diagnostics,
the original 10,000/s rate policy and all failed historical gates stay intact.
