diff --git a/.kiro/specs/raft-sim-conformance/design.md b/.kiro/specs/raft-sim-conformance/design.md index ce31de25..d2ab97e9 100644 --- a/.kiro/specs/raft-sim-conformance/design.md +++ b/.kiro/specs/raft-sim-conformance/design.md @@ -452,8 +452,14 @@ quiet on success unless `RAFT_SIM_VERBOSE` (R5.4). ### Deliberately-broken-build fault switch (test-only) -Compile-time macros gate **harness-side adapter** corruptions that emulate the bug-851 -defects without touching `raft.c`: +A **runtime** fault-injection flag (`cluster.fault_inject`, set via +`raft_sim_set_fault_inject`) gates **harness-side adapter** corruptions that emulate the +bug-851 defects without touching `raft.c`. The flag is compiled only under `XCE_TESTING` +(never in the shipped build) and defaults to OFF (never enabled in the default CI run), so +it satisfies R7.3 by the same substance a compile-time macro would — but, unlike a +`#ifdef`, a runtime flag can be toggled within a SINGLE binary, which R7.4 requires (the +negative test must assert the broken-config FAILURE and the correct-config PASS in one +test). The `RAFT_SIM_BREAK_*` names are the flag's bit values: - `RAFT_SIM_BREAK_TERM_STAMP` — `on_persist_entry` writes `term = 0` instead of the supplied term (emulates G1: entry term always 0), so `on_get_entry_term` can no longer @@ -461,10 +467,14 @@ defects without touching `raft.c`: - `RAFT_SIM_BREAK_TRUNCATE` — `on_truncate_from` is a no-op (emulates G3: the divergent suffix is never deleted). -Under either macro the targeted scenarios (Figure-8, stale-rejoin, divergent-suffix) must -trip Log Matching / Leader Completeness / State Machine Safety; with the macros off, the -same run is clean. This keeps the negative test entirely inside the harness build -configuration (R7.3) — the shipped protocol and the default CI run are unaffected. +With a fault bit set the run must trip Log Matching / Leader Completeness / State Machine +Safety; with the flag off (the default), the same run is clean. This keeps the negative +test entirely inside the harness build configuration (R7.3) — the shipped protocol and the +default CI run are unaffected. (Implementation note: `RAFT_SIM_BREAK_TERM_STAMP` is the +flag used by the task-7.2 negative test because the library collapses conflict-truncate +and the immediately-following append into one AppendEntries handler invocation, so a no-op +truncate alone is overwritten by the re-persist and does not diverge through normal +replication — the term-stamp corruption reliably trips Log Matching instead.) > **Why adapter-side and not a `raft.c` edit:** the harness owns only `raft_sim.c`/tests. > Emulating G1 by having the *adapter* drop the term reproduces the exact observable