FPB-v1 — False Positive Bound observer¶
Citation
ADR-0035 ·
Accepted 2026-06-09 ·
Verifier: project_ghost.properties.verify_fpb
What it claims¶
The empirical fraction of cycles where BAUD-v1's precondition fires
is observable and bounded by a caller-configurable
max_fire_fraction. The fifth property of the set and the only
quantitative observational one.
Formal statement¶
For an execution with parameters (M, K) and a caller-supplied
max_fire_fraction ∈ [0, 1]:
where:
and cycles_baud_fires is the count of cycles where BAUD's
precondition is met. Default max_fire_fraction = 1.0 makes the
verifier a pure observer that always holds.
Why it's "observer-shaped"¶
Unlike BAUD/ERUR/MD/RLB (all hard pass/fail), FPB-v1 is a measuring stick. The honest framing: the statistical false-positive bound (under Gaussian noise with declared covariance) requires Monte Carlo infrastructure that is currently out of scope. FPB-v1 delivers the empirical fire-rate observation that:
- Surfaces an explicit float metric in the report
- Lets the caller pin a regression bound via
max_fire_fraction - Defaults to non-failing observer mode for normal CI use
A future FPB-v2 with Monte Carlo machinery would tighten this into a true statistical claim.
Verifying any MCAP¶
# Default: pure observer, never fails
ghost verify-properties --mcap your-run.mcap
# Regression gate: fail if fire fraction exceeds 0.5
ghost verify-properties --mcap your-run.mcap --max-fire-fraction 0.5
Or programmatically:
from project_ghost.properties import verify_fpb
report = verify_fpb("your-run.mcap", max_fire_fraction=0.5)
assert report.holds
print(f"Observed: {report.fire_fraction:.2f}")
Example output¶
On the reference 10-cycle smoke:
The smoke baseline is fire_fraction = 0.60 (BAUD fires in 6 of 10
cycles). With default max_fire_fraction=1.0 this holds trivially;
with max_fire_fraction=0.5 it would violate.
Use as a regression gate¶
The integration test pins the exact observed fraction:
def test_smoke_carries_inline_fpb_verification(tmp_path):
summary = run_closed_loop_smoke(tmp_path / "smoke.mcap", n_cycles=10)
assert summary.fpb_report.fire_fraction == 0.6 # <- pinned baseline
If a future refactor of the calibration policy changes its sensitivity, this test surfaces the change in a single line of CI output. The maintainer either:
- Accepts the change (update the pinned value)
- Treats it as a regression (fix the policy)
Either way, the change is visible, not silent.
Scope¶
FPB-v1 does establish:
- The exact empirical fire fraction over the MCAP
- A pass/fail comparison against a caller-supplied bound
FPB-v1 does not establish:
- Any statistical claim under a probabilistic noise model
- That the observed fires are false positives (the verifier cannot distinguish from the MCAP alone)
- A target value for
max_fire_fraction(that is policy-dependent and operator-supplied)
See also¶
- Full ADR-0035
- Source:
src/project_ghost/properties/fpb.py - Sister properties: BAUD-v1, ERUR-v1, MD-v1, RLB-v1