# C++ copied finalization journals reject allocation failures

Copying a healthy C++ `FinalizedSessionJournal` could make `Record` report success
for an ID absent from its durable metadata. The fix rejects a failed ID set before
checking membership. Healthy copies and assignments remain supported. Application
send and replay paths, file formats and writer fences are unchanged; no lock is added.

## Reproduced failure

At `eff840275`, a deterministic allocator fault fails the deep copy of a journal
holding one recorded ID. The implicit journal copy constructor and assignment
operator retain `m_open=true` and `m_failed=false`, while `FinalizedIds` sets its
own failure flag. Its `Contains` then returns true for every ID, deliberately
refusing to forget retired sessions. `Record` incorrectly treats that fail-closed
answer as proof that a record is already durable.

The baseline has **17 passing cases, three failed cases and zero skips**. The
three failures cover construction, assignment to an empty destination and
assignment replacing an already bound journal. Each also copies and assigns the
failed result again before its first `Record`, then checks retries, metadata size,
the independent healthy source and successful reopen. The metadata stays at one
28-byte record despite the false acknowledgements. Healthy copies, healthy
replacement, empty copies, self-assignment and the existing ownership and directory
sync cases all pass on the baseline.

This is a direct public C++ journal-helper defect. It is not a claim that the
noncopyable file replay store can be copied. Java and .NET's journal classes expose
no equivalent deep-copy API, and the Rust journal has no `Clone` implementation.

## Correction

`Record` now checks `m_ids.Failed()` alongside its journal failure and open-state
guards. A failed copy rejects both new and known-ID records and remains failed
until a successful `Open` reloads the file. Queries continue to treat every ID
as retired. Copying a failed result cannot turn it healthy, and an independent
source completing a record does not heal it. Valid deep copies and no-allocation
self-assignment preserve their existing behavior.

## Qualification

hp ran functional checks under normal-priority isolated-core leases, overlapping
the shared-core conformance sweep. These are correctness checks, not latency
measurements. All outputs are below this session's out-of-tree build root.

| Selection | Result |
| --- | --- |
| Ownership, recovery and copy regression fixture | 20 of 20 cases, zero skips |
| Compiler repetitions | GCC 11.5.0, 14.2.1, 15.2.1 and Clang 21.1.8 all pass |
| Address and undefined-behavior sanitizers | 20 of 20 cases, leak checking enabled |
| Normal Makefile target | 20 of 20 cases with production optimization and LTO flags |
| Development and open finalized-path fixtures | 14 cases and 269 checks each |
| Development and open finalized-ID fixtures | 20 cases and 6,686 checks each |
| Development and open file replay and classic file stores | All selected fixtures pass |
| Additional private mmap companions | 16 path cases and 352 checks; nine finalized-ID cases and 697 checks |
| Publication source scan | Three files, zero findings |

The fixed qualification starts at the same source pin as the baseline, with its
exact uncommitted implementation and fixture patch retained in the logs. Source
and driver hashes are checked at completion. Counts are per execution and are
not summed as unique tests. Managed and Rust sources are unchanged in this batch.

Rebasing onto `6622c6ef1` changes none of the qualified C++ inputs. The integrated
pin `673e802c4` passes all 20 focused cases and the publication scan; its source
pin, input hashes and logs are retained in `integrated-logs.tar.gz`.

## Reproduction and retained evidence

The driver is
[run-qualification.sh](evidence/finalized-copy-failure-20261014/run-qualification.sh).
Pass a session worktree, an absolute output root and `fixed`; wrap the outer
command in `host-cpu-slot` using an available functional-test pool. The `baseline`
mode expects the three red cases; reproduce it at the baseline source pin with
the baseline log archive's `source.patch` applied. `integrated` runs the focused
regression and publication scan after a rebase.

`baseline-logs.tar.gz` and `fixed-logs.tar.gz` are tracked beside the driver.
Their SHA-256 hashes are respectively
`401a43bfccc4bd9f47ea53a98481a3fedfbc4a3cc00f9c4a523951e8deea404e` and
`2cea494a12df2e34d7363fe65a67c460278080b446ed885ae5cd02a8fd008084`.
Copies are retained under
`/home/yann/archive/libhft/finalized-copy-failure-20261014/`; the build products
are under `/home/yann/build/codex-libhft-hp/libhft/finalized-copy-failure-20261014/`.
