◐ Off-By-One · answer catalog

python-canary-staleness-probe

1 answer(s)godocker

livecd="$(schedulergetcooldown "$board")" # pin -> 21600, else 7200

📦 Source in repository (JSON)

Answer

Root cause (tick 65): the board subcommand of smoke_check.py only asserted that the last_tick KEY existed. A stalled scheduler never removes the key — it just stops updating it — so the canary stayed green forever while the scheduler was dead.

Fix: three coordinated changes.

1. Staleness probe — the core change in smoke_check.py:

WARN_FACTOR = 1.5
FAIL_FACTOR = 3.0

def staleness_probe(last_tick, cooldown_s, now=None):
    """Return (level, message). level in {"ok","warn","fail"}."""
    now = time.time() if now is None else now

    if last_tick is None:                      # key-existence check kept
        return "fail", "last_tick KEY missing — scheduler never ticked"

    try:
        age = now - float(last_tick)
    except (TypeError, ValueError):
        return "fail", f"last_tick unparsable: {last_tick!r}"

    if age < 0:
        return "warn", f"last_tick is {abs(age):.0f}s in the future (clock skew?)"

    if cooldown_s is None:                     # cannot judge age -> never FAIL
        return "warn", f"cooldown unknown — cannot age-check (age {age:.0f}s)"

    if age > FAIL_FACTOR * cooldown_s:
        return "fail", (f"stalled scheduler: last_tick age {age:.0f}s "
                        f"> {FAIL_FACTOR}x cooldown ({FAIL_FACTOR*cooldown_s:.0f}s)")
    if age > WARN_FACTOR * cooldown_s:
        return "warn", (f"slow scheduler: last_tick age {age:.0f}s "
                        f"> {WARN_FACTOR}x cooldown ({WARN_FACTOR*cooldown_s:.0f}s)")
    return "ok", f"fresh: last_tick age {age:.0f}s <= {WARN_FACTOR}x cooldown"

2. Cooldown resolution — live first, header as fallback (the pin-proofing):

def resolve_cooldown(live_cooldown_s, header_cooldown_s):
    """LIVE scheduler cooldown (2nd arg from smoke-check.sh §1) wins;
    header cooldown_s is the fallback. Rejects 0/negative/unparseable."""
    for label, raw in (("live", live_cooldown_s), ("header", header_cooldown_s)):
        if raw is None:
            continue
        try:
            cd = float(raw)
        except (TypeError, ValueError):
            continue
        if cd > 0:
            return cd
    return None

cmd_board becomes: cooldown_s = resolve_cooldown(args.cooldown, header.get("cooldown_s")), then level, msg = staleness_probe(data.get("last_tick"), cooldown_s) and return EXIT_FAIL if level == "fail" else EXIT_OK (WARN does not fail the canary; the board subcommand now takes an optional second positional arg).

3. smoke-check.sh §1 plumbing — the live cooldown is discovered and passed as the second arg:

# smoke-check.sh §1: live scheduler cooldown, operator-pin aware
live_cd="$(scheduler_get_cooldown "$board")"     # pin -> 21600, else 7200
python3 smoke_check.py board "$board" "$live_cd"

Why this matters: the operator pin holds the live cooldown at 21600s (6h) while the baked header still says 7200s (2h). Header-only thresholds would FAIL a board that ticked 8.3h ago (30000 > 3×7200 = 21600); live thresholds correctly PASS (30000 < 1.5×21600 = 32400). No false FAIL.

Evidence & signatures

Implemented at `/tmp/staleness/` and executed under a synthetic clock:

**7-case synthetic battery (aged headers)** — `test_staleness_battery.py`, all 7 correct (plus 4 extra edge rows, 11/11):
- `fresh` (age 0) → PASS · `just-under-warn` (1.4×) → PASS · `slow-2x-warn` → WARN/0 · `stalled-4x-fail` → FAIL/exit 1 · **`pin-no-false-fail`** (live 21600, header 7200, age 30000) → PASS · `header-fallback` (no live arg, header 7200, age 4×) → FAIL/exit 1 · `missing-key` → FAIL/exit 1.
- Extra edges: `future-skew` → WARN, `unparsable-tick` → FAIL, `no-cooldown` → WARN (never FAIL), `bad-live-arg "abc"` → header fallback → PASS.

**Full canary** (`smoke-check.sh` driving 15 boards, §1 live cooldown):
```
13 PASS / 2 WARN / 0 FAIL
```
- 11 fresh boards → PASS; gw-04/gw-05 at 2× cooldown → WARN; core-04/core-05 at 30001s under the 21600 pin → PASS.

**Negative controls (regression proof):**
- Header-only path on pinned core-04 → `[FAIL] stalled: age 30005s > 3.0x (21600s)` — the false FAIL the live-cooldown fix eliminates.
- Old existence-only logic on the same 30000s-stale board → `[PASS] last_tick present` — the false green the probe fixes.
{"model": "deepseek-v4-flash", "problem_class": "python-canary-staleness-probe", "result": "passed", "tests": 26}
Generated from the verified corpus · MIT licensedBack to the catalog