flag-truth mark cost -- box 206, registry.arbi.work/arbi-serve:test-4a2f15c
==========================================================================

WHAT IS BEING MEASURED
----------------------
The per-mark cost of arbi_serve.flag_truth, which every perf-relevant path
bumps to prove it executed. Python 3.12.3 in the test image, timeit, the
statement unrolled 200x per loop iteration so the loop's own cost (~0.03 ns
residual) cannot mask it; min of 15 repeats.

    shape                                              ns/mark   vs fire()
    ------------------------------------------------  --------  ---------
    counter.fire()                     -- main today    34.57      1.00x
    counter.fired = 1                  -- bit door       6.00      5.76x
    counter.fired += 1                 -- counted door  16.30      2.12x
    counter.fired = 1, counting ARMED  -- diagnostic    137.61      0.25x

Both shipped doors are cheaper than the method call. Half of what fire()
cost was the CALL, not the arithmetic: an inline `fired += 1` measures
~14 ns against ~34 for the same increment behind a method.

WHY THE BIT IS A STORE AND NOT AN INCREMENT
-------------------------------------------
An increment is a read-modify-write of a Python int (~16 ns); a store is a
pointer write of a cached small int (~6 ns). A MustFire contract only ever
asks "did this path execute", which a store answers, and a store is also
idempotent and lock-free under the GIL where the increment is neither.

WHY THE STORE IS ON THE COUNTER AND NOT INTO A SIDE LIST
--------------------------------------------------------
#2308 proposed `_FT[IDX] = 1` into a preallocated list, on the measurement
that a list store beats a bytearray store. It does -- but a slot store on
the counter object measures the SAME, and needs no list, no index constant
per counter, and no second module global to keep in sync with the counter
it indexes:

    FT[IDX] = 1        (list, int-literal index global)     4.76 ns
    _C.fired = 1       (slotted attribute on the counter)   4.73 ns
    FT[_C.slot] = 1    (list, index read off the counter)   6.13 ns
    D[_C] = 1          (dict keyed by the counter)          9.41 ns
    BA[IDX] = 1        (bytearray)                         11.39 ns

(measured in the same image on an otherwise idle box; the absolute numbers
drift a few percent between runs, the ordering does not.)

So the list buys nothing over the attribute and costs an index global per
counter -- a second binding that can silently name a DIFFERENT counter from
the `refuse()` two lines below it. The attribute is one binding.

WHY COUNTING IS NOT A MASTER SWITCH ON THE HOT PATH
---------------------------------------------------
A guard that skips the mark measures ~2.1 ns against the ~4.8 ns mark it
would skip. Guarding would therefore save ~2.7 ns per mark, and would cost
the property the machinery exists for: MustFire contracts evaluable on an
ordinary production boot. Marks stay always-on. The guarded thing is
COUNTING -- the diagnostic that turns bits into totals -- and it is flipped
by swapping the counter's class, so it costs the hot path nothing at all
rather than 2.1 ns.

    if _EN: _C.fire()      guard, plain module global, OFF   2.13 ns
    if _mod.EN: ...        guard, module attribute, OFF      4.98 ns
    if FT[0]: ...          guard, shared list slot, OFF      6.66 ns

PER REQUEST
-----------
8.03 marks per output token on a live 27B boot, so ~0.23 us/token saved
against a 21.7 ms TPOT -- 0.0011%, three orders of magnitude under what an
end-to-end A/B can resolve. See flag-truth-live-ab-2026-09-08.txt for that
census, the A/B that confirms no regression, and why the 0.0011% is not the
number that decided this.
