Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,19 @@ Fedora Asahi, and `v0.2.0` was released (PR #127 ded6e80; resume-anchor sync PR
`v0.2.1` then shipped two reprioritized backlog items plus a consistency sweep: a Codex
resume-anchor/PMU sweep (PR #129), a perf call-graph flamegraph + `make flamegraph` (PR #134,
superseding the auto-closed #130, closing #32), and the FIX-like text protocol adapter (PR #131,
closing #29), with the version bump on the release PR. There is no active milestone; the
closing #29), with the version bump on the release PR.

Since `v0.2.1`, a post-v0.2.1 hardening + perf wave (PRs #135–#146) is merged to `main` and
unreleased, being cut as **`v0.2.2`**. It came out of a 4-round adversarial bug hunt (converged
5→2→1→0 confirmed) plus flamegraph-guided optimization. Security/robustness: out-of-domain enum
rejection in the replay/protocol decoders (#136); network hardening — EINTR retry, accept fairness,
connection cap, UDP send-error tracking, transient-accept survival, and threaded/epoll fd-exhaustion
handling (#137, #140, #143); CLI arg validation (#141); a **real UBSan abort gate** — the `asan`
preset now sets `-fno-sanitize-recover=undefined`, since UBSan previously ran in recover mode and
exited 0, so pure-UBSan defects passed CI green (#142); OCaml `diff_report` per-fixture robustness
(#144). Perf (measured back-to-back A/B): `try_emplace` for baseline price levels (~+5%, #138) and
an order-index hash `max_load_factor` cap at 0.25 (~+18.6%, #145), flamegraph regenerated
(#135/#139/#146). Determinism preserved (byte-identical fixtures; OCaml differential pass).
`make check`/`make asan` 270/270 (the latter now a real UBSan gate). After `v0.2.2`, the
highest-value remaining work is non-code and gated on #94 (external review) and #90 (full cache-PMU
evidence on a PMU-capable microarchitecture).
49 changes: 49 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,55 @@ All notable changes to this project. The format is loosely based on

_Nothing yet._

## [0.2.2] - 2026-06-24

A security/robustness **hardening** wave plus two measured order-book **performance** wins, driven by
a multi-round adversarial bug hunt (converged 5→2→1→0 confirmed bugs) and flamegraph-guided
optimization. Same honesty bar: a deterministic C++20 exchange simulator and cross-language
differential-testing harness — **not** a production exchange, no real-market connectivity, no latency
or profitability claims, not formal verification. Determinism preserved throughout (fixtures
byte-identical across g++/clang++ and vs the committed copies; the OCaml differential passes).
`make check`/`make asan` 270/270.

### Fixed

- **Reject out-of-domain enum bytes in the decoders (#136).** `replay::decode_command` (NewLimit /
NewMarket) and `protocol::decode_reject` cast raw bytes to `Side` / `TimeInForce` / `RejectReason`
without validating the domain. Since the replay path applies decoded commands straight to the
engine with no gateway risk check, a corrupt log record could silently diverge replayed state.
Both now validate via `core::is_valid` (added `is_valid(RejectReason)`) and refuse out-of-domain
bytes like a malformed frame.
- **Network-path hardening (#137, #140, #143).** The TCP gateway now retries `EINTR` in its
read/write paths and survives transient `accept()` errors (`EINTR`/`ECONNABORTED`) instead of
tearing the listener down; both the threaded acceptor (back-off retry) and the epoll loop (listener
disarm/re-arm) survive fd exhaustion (`EMFILE`/`ENFILE`); a `TcpServerOptions::max_active_connections`
cap sheds load; the epoll loop bounds accepts per tick for fairness; and `UdpPublisher` counts
`send_failures` rather than silently dropping datagrams.
- **CLI argument validation (#141).** `qsl-client`, `qsl-mdfeed`, and `qsl-export-fixture` parse
numeric arguments with `std::from_chars` and reject malformed / out-of-range input with a usage
message and non-zero exit, instead of `std::terminate` (from an uncaught `std::sto*` exception) or
silently truncating an out-of-range port.
- **UBSan gate now actually fails (#142).** The `asan` preset adds `-fno-sanitize-recover=undefined`
so UBSan **aborts** on the first violation. It previously ran in recover mode (print a diagnostic,
exit 0), so a pure-UBSan defect passed `make asan` / CI green. The tree is UBSan-clean under the
strict gate.
- **OCaml `diff_report` robustness (#144).** The differential-bundle bin guards each fixture
(catching `Stream_parser.Parse_error` / `Sys_error`) so one malformed or unreadable fixture cannot
abort the whole batch and silently lose the divergence bundles for the rest.

### Performance

- **`try_emplace` for baseline price levels (#138).** `OrderBook::level_for` used
`std::map::emplace`, which allocates and frees a node even when the price level already exists.
`try_emplace` avoids that on the steady-state common path. Measured back-to-back A/B on the
`qsl-bench profile` workload: **~+5%**.
- **Order-index hash load-factor cap (#145).** The `OrderId → Locator` index is the busiest structure
on the engine hot path (1–4 point lookups per op). Capping its `max_load_factor` at 0.25 shortens
probe chains. Measured A/B: **~+18.6%**. Determinism is unaffected — the index is never iterated
for output.
- **Flamegraph regenerated (#135, #139, #146)** against the new code, now a dense (~20k-sample),
fully-symbolized frame-pointer profile with zero `[unknown]` frames.

## [0.2.1] - 2026-06-21

Two backlog items — reprioritized by the maintainer and delivered — plus a resume-anchor and
Expand Down
15 changes: 14 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,19 @@ Fedora Asahi, and `v0.2.0` was released (PR #127 ded6e80; resume-anchor sync PR
`v0.2.1` then shipped two reprioritized backlog items plus a consistency sweep: a Codex
resume-anchor/PMU sweep (PR #129), a perf call-graph flamegraph + `make flamegraph` (PR #134,
superseding the auto-closed #130, closing #32), and the FIX-like text protocol adapter (PR #131,
closing #29), with the version bump on the release PR. There is no active milestone; the
closing #29), with the version bump on the release PR.

Since `v0.2.1`, a post-v0.2.1 hardening + perf wave (PRs #135–#146) is merged to `main` and
unreleased, being cut as **`v0.2.2`**. It came out of a 4-round adversarial bug hunt (converged
5→2→1→0 confirmed) plus flamegraph-guided optimization. Security/robustness: out-of-domain enum
rejection in the replay/protocol decoders (#136); network hardening — EINTR retry, accept fairness,
connection cap, UDP send-error tracking, transient-accept survival, and threaded/epoll fd-exhaustion
handling (#137, #140, #143); CLI arg validation (#141); a **real UBSan abort gate** — the `asan`
preset now sets `-fno-sanitize-recover=undefined`, since UBSan previously ran in recover mode and
exited 0, so pure-UBSan defects passed CI green (#142); OCaml `diff_report` per-fixture robustness
(#144). Perf (measured back-to-back A/B): `try_emplace` for baseline price levels (~+5%, #138) and
an order-index hash `max_load_factor` cap at 0.25 (~+18.6%, #145), flamegraph regenerated
(#135/#139/#146). Determinism preserved (byte-identical fixtures; OCaml differential pass).
`make check`/`make asan` 270/270 (the latter now a real UBSan gate). After `v0.2.2`, the
highest-value remaining work is non-code and gated on #94 (external review) and #90 (full cache-PMU
evidence on a PMU-capable microarchitecture).
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(quant-systems-lab VERSION 0.2.1 LANGUAGES CXX)
project(quant-systems-lab VERSION 0.2.2 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ reviewable.

```bash
make check # clang-format check + build + tests
make asan # AddressSanitizer + UBSan build and tests
make asan # AddressSanitizer + UBSan build and tests (UBSan aborts on first violation)
dune runtest --root ocaml # OCaml log verifier + independent replay + differential + mutation tests
```

Expand Down
44 changes: 29 additions & 15 deletions HANDOFF.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,19 @@ partial-PMU reframe, and a full documentation staleness sweep — landed as PR #
**v0.2.1 release** then adds two reprioritized backlog items and a consistency sweep: a Codex
resume-anchor/PMU sweep (PR #129), a perf call-graph flamegraph + `make flamegraph` (PR #130,
issue #32), the FIX-like text protocol adapter (PR #131, issue #29), and the version-bump release
PR — merged in that order, with `v0.2.1` tagged on the release merge commit. There is no active
milestone; the project is between releases.
PR — merged in that order, with `v0.2.1` tagged on the release merge commit.

Since `v0.2.1`, a **post-v0.2.1 hardening + perf wave (#135–#146) is merged to `main` and
unreleased**, being cut as **`v0.2.2`**. It came out of a 4-round adversarial bug hunt (converged
5→2→1→0 confirmed bugs) plus flamegraph-guided optimization. Security/robustness: out-of-domain enum
rejection in the replay/protocol decoders (#136); network hardening — EINTR retry, accept fairness,
connection cap, UDP send-error tracking, transient-accept survival, and threaded/epoll fd-exhaustion
handling (#137, #140, #143); CLI arg validation (#141); a **real UBSan abort gate** —
`-fno-sanitize-recover=undefined`, since UBSan previously ran in recover mode and exited 0 (#142);
OCaml `diff_report` robustness (#144). Perf (measured A/B): `try_emplace` for baseline price levels
(~+5%, #138) and an order-index hash load-factor cap (~+18.6%, #145), with the flamegraph regenerated
(#135/#139/#146). `make check`/`make asan` 270/270 (the latter now under the real UBSan gate). The
next action is to finish this `v0.2.2` doc/artifact overhaul and cut the tag.

Background — Linux perf evidence (merged, now bare-metal partial PMU):

Expand Down Expand Up @@ -77,13 +88,15 @@ Current state:

- latest synced main baseline: `ded6e80` (PR #127, v0.2.0); the `v0.2.1` baseline is the release-PR
merge commit, after PRs #129/#130/#131
- current active branch, if active: none (work lands via scoped PRs from `main`)
- current active status: `v0.2.1` is the current release on top of `v0.2.0`. It adds the FIX-like
text protocol adapter (#29), `make flamegraph` + a bare-metal flamegraph artifact (#32), and a
Codex resume-anchor/PMU consistency sweep. `make check` 263/263 and `make asan` 263/263 on the
bare-metal Apple M2 Fedora Asahi host; both new code files pass the CI CodeScene Code Health gate.
No active milestone
- release tag: `v0.2.1` (Latest, tagged on the release-PR merge commit), after `v0.2.0` and `v0.1.0`
- current active branch, if active: `docs/post-v0.2.1-overhaul` (v0.2.2 prep + doc/artifact sweep)
- current active status: `v0.2.1` is the latest tag; a post-v0.2.1 hardening + perf wave (#135–#146)
is merged to `main` and unreleased, being cut as `v0.2.2` (decoder enum rejection, network/CLI
hardening, a real UBSan abort gate, OCaml diff_report robustness, and two measured order-book perf
wins — `try_emplace` ~+5% and an index load-factor cap ~+18.6%). `make check` 270/270 and
`make asan` 270/270 (the latter now under the real UBSan gate) on the bare-metal Apple M2 Fedora
Asahi host; every touched file passes the CI CodeScene Code Health gate
- release tag: `v0.2.1` (Latest, tagged on the release-PR merge commit), after `v0.2.0` and `v0.1.0`;
`v0.2.2` prepared on this branch, not yet tagged
- open follow-up issue: #90 — narrowed to the full cache-counter PMU set; the bare-metal Apple host
provides real cycles/instructions/branches/branch-misses but no cache-reference/cache-miss support
- issues #95, #28, and #26 were closed by PR #112; issues #32 and #29 were closed by PR #134 and
Expand All @@ -94,12 +107,13 @@ Current state:

### Next milestone

There is no active milestone. M0–M49, the Linux artifact refresh (PR #125), the v0.2.0 release
(PR #127), and the v0.2.1 content (PRs #129/#134/#131 + release PR) are merged. The highest-value
remaining work is non-code and externally gated: issue #94 (independent external review — needs a
human reviewer) and issue #90 (full cache-counter PMU evidence — needs a PMU microarchitecture that
exposes cache events). The #32 (flamegraph) and #29 (FIX adapter) backlog items are now done. Do not
invent a new milestone without an explicit human request.
There is no active milestone. M0–M49 are merged, as are the v0.2.0/v0.2.1 releases and the
post-v0.2.1 hardening + perf wave (#135–#146, being released as `v0.2.2`). The immediate next action
is to finish the `v0.2.2` doc/artifact overhaul (this branch) and cut the tag. After that the
highest-value remaining work is non-code and externally gated: issue #94 (independent external
review — needs a human reviewer) and issue #90 (full cache-counter PMU evidence — needs a PMU
microarchitecture that exposes cache events). Do not invent a new milestone without an explicit
human request.

### Phase III / IV purpose

Expand Down
Loading
Loading