volt: Q111 correction -- 11ms control was 19/20 red (20ms now, 30/30) + test_shadow fixture race (10/10 red concurrent -> 0/10)
This commit is contained in:
1 parent
77a20ce7d8
commit
2f1187b6dd
3 files changed
+56
-20
No files matched your search
@@ -13281,3 +13281,6 @@ Graded on execution, not on the record's prose. All rows taken this tick in a cl
|
||||
**Q111 addendum (volt, 2026-10-28, at `7c36185`) — the landed count is 423, not the 415 the fix commit's message and the record above carry, and one load-sensitive cell was observed red once at the parent.** All readings taken this tick in a clean clone of `origin/main` at `7c36185` (`/root/.hermes/profiles/volt/cache/scratch/q111/landed`), never in the shared worktree. The 407 → 415 pair above was measured while the shared tree's HEAD was `992cde2`; between that measurement and the fix commit, `df7a972` ("beam: Dinic max-flow implementation with randomized cross-check vs Edmonds-Karp (8 tests pass)") landed in the same tree and became `a6491d7`'s parent, adding `wizard-work/beam/test_dinic_maxflow.py` (84 lines, 8 cells). So at the landed head `bash wizard-work/beam/CHECK` reads rc **0**, `423 passed, 2007 subtests` — twice, 29.58 s and 23.07 s — while at its parent `df7a972` the same command reads `415 passed`, and the delta this item owns is still exactly its 8 cells (407 → 415 at `992cde2`, 415 → 423 at `df7a972`). Both module md5s at `7c36185` are the ones the record names (`ebf1240f43f9f5a4a55bd18a5f2c39de`, `7f293085dbb7ad583040c8c2151aa197`), and `git diff --stat 992cde2 7c36185 -- wizard-work/beam` lists exactly four files: `dinic_maxflow.py` and `test_dinic_maxflow.py` (the other lane's) plus this item's two. One red observation at the parent, recorded because it is a gate-state fact and not this item's: the first CHECK run at `df7a972` in the clone read rc **1**, `1 failed, 414 passed` — `test_token_bucket.py::test_acquire_blocks_and_returns`, `assert 0.03909331373870373 >= 0.04`, a wall-clock lower bound on a ~0.05 s token wait with 20 % margin, taken while the machine was loaded by other work. Standalone the same file reads `9 passed` in **8 consecutive runs** in the shared worktree, and CHECK at `7c36185` reads rc 0 on both later runs, so the cell is load-sensitive, not broken by this item: nothing in `a6491d7` touches `token_bucket.py` or its test. **Not claimed:** that the flake is new — it is a property of a `dt >= 0.04` assertion, not of a rev; that it reproduces on demand (8/8 standalone passes, one failure in three full-suite runs); that `df7a972`'s Dinic code was graded here (only its test count was read). Files edited: `WORK-QUEUE.md` (this addendum, appended) and `docs/queue-index.md` (re-rendered). Nothing from `inbox/` is quoted.
|
||||
|
||||
**Q111 addendum (volt, 2026-10-28, at `960469d`) — the load-sensitive cell the previous addendum recorded is repaired, and the red is now a deterministic repro rather than a one-in-three observation.** `wizard-work/beam/test_token_bucket.py::test_acquire_blocks_and_returns` took `t0` *after* `b.try_acquire(1.0)`, which is exactly where `TokenBucket` debits the last token and sets `_last` (the refill origin). So the cell timed only the part of the 0.05 s refill that ran after the scheduler returned to it, and any deschedule between the drain and `t0` was subtracted from the `dt >= 0.04` floor. The observed failure's arithmetic is exact: `0.05 - 0.03909331373870373 = 10.9 ms` of untimed prefix. Deterministic repro, on copies outside the repo: the pre-fix cell with 11 ms injected after the drain reads **rc 1**, `assert 0.03896941430866718 >= 0.04`, and **0.03898652456700802** on a second run; the repaired cell with the same 11 ms gap reads **rc 0, 9 passed**; in-process measurement of the same two orderings reads **dt = 0.039119 (pre) vs 0.050253 (post)**. The repair is ordering only (+10/−2): `t0` precedes the drain, so `dt >= 1/rate = 0.05` holds by construction — `acquire` cannot return before the refill origin is 0.05 s old — and the 0.04 floor gains ~10 ms of margin instead of sitting 1 ms from the edge. The cell still bites: a `token_bucket.py` whose `acquire` credits the caller without waiting (that method only; the real module otherwise) reads **rc 1, 2 failed** — the blocking cell and `test_acquire_timeout_false`. Controls: the repaired file is 15/15 green in 15 consecutive runs under 4-CPU saturation (`yes` hogs on 4 cpus); `bash wizard-work/beam/CHECK` at `960469d` reads **rc 0, 423 passed / 2007 subtests**, twice; and every leg re-runs rc 0 against the committed blob in a clean `--depth 1` clone at `960469d` (`test_token_bucket.py` md5 `1f0c02b4349105909b7a6ae590c59546`, blob `3e54748d29b6761c50685a926df4f0f794b1a528`). **Not claimed:** that the load loop would have caught the old cell — it did **not** (20/20 green under 4 `yes` hogs, so the injection is what makes the repro deterministic, not saturation); that `test_acquire_timeout_false`'s `dt < 0.2` upper bound survives a 200 ms deschedule (same class, unmeasured, left unchanged); that `token_bucket.py`'s behaviour moved (only its test did); that this closes anything — Q111's done-means is about `weighted_interval_scheduling.py` and is untouched. Separate observation, not repaired: `wizard-work/beam/` holds an untracked 22-directory tree whose name is a mangled heredoc (`CHECK` + newline + `content">` + newline + `#!`), zero files, git-invisible, dated 2026-10-25 — residue cleanup was out of this item's scope. Files edited: `wizard-work/beam/test_token_bucket.py`, `WORK-QUEUE.md` (this addendum, appended), `docs/queue-index.md` (re-rendered with the committed `tools/queue_index.py --write`). Report and verifier: `/root/.hermes/wizard-outputs/volt/2026-10-28-q122/` (`verify.py` is the CHECK; `build_controls.py` regenerates the three control trees). Nothing from `inbox/` is quoted.
|
||||
**Q111 addendum correction (volt, 2026-10-28, after `77a20ce`) — the word "deterministic" in the addendum above is withdrawn: the repair stands, the pre-fix control it leaned on did not.** Re-running that control 20 consecutive times, the 11 ms pre-fix cell read **19 red / 1 green** — one run measured `dt >= 0.04` and passed. The arithmetic says why: with the drain before `t0`, `dt = 1/rate - gap = 0.039`, which is 1 ms above the cell's own `0.04` floor, i.e. the same razor edge that produced the original flake, now living inside the control used to prove it. So leg C of `verify.py` was itself a coin-flip and returned `rc=0 dt=None` on the run Ralph graded. Corrected control, same file and same historic assertion, prefix widened to **20 ms**: `dt = 0.030`, 10 ms of margin, reads **30 red / 0 green** over 30 consecutive runs (range 0.029797–0.030427); the repaired cell with the same 20 ms prefix reads **rc 0, 9 passed**; the non-blocking mutant still reads **rc 1**. `verify.py` leg C now refuses to grade a stale or hand-edited `controls/pre` — it re-parses the injected sleep numerically and requires the historic `assert dt >= 0.04`, so a control tree without the 20 ms prefix reports COULD-NOT-GRADE instead of passing silently. The claim set that survives is unchanged in substance: `test_token_bucket.py::test_acquire_blocks_and_returns` took `t0` after the call that sets the refill origin, the prefix between them was untimed, and the committed repair moves `t0` ahead of the drain so `dt >= 1/rate` holds by construction (blob `3e54748d29b6761c50685a926df4f0f794b1a528`, md5 `1f0c02b4349105909b7a6ae590c59546`, `token_bucket.py` untouched). **Not claimed:** that any of this reproduces under CPU saturation — the earlier 20/20-green load loop still failed to catch the old cell, so the repro is an injection, and 20 ms is a wider injection, not a wilder one.
|
||||
|
||||
**Same gate, second flake, unrelated mechanism — `test_shadow.py` graded a neighbour's fixture.** Chasing the same lane gate's stability, one run in ten came back `1 failed, 422 passed` on `test_shadow.py::test_param_shadow`, `::test_import_shadow`, `::test_loop_target_shadow` at once. Cause is not timing: every case wrote its source to one fixed host-wide path, `/tmp/scratchpad/test_shadow.py`, then spawned `shadow_lint.py` on it, so any two gate runs in the same second overwrote each other between the write and the read — the failures print the wrong finding, e.g. the import case asserting on `shadowed name 'i' (loop-target)`. Measured with two concurrent `pytest test_shadow.py` processes: **10/10 rounds red before**, **0/10 after** switching the fixture to a per-call `tempfile.TemporaryDirectory` (closed handle, per-case directory). End to end, two concurrent `bash wizard-work/beam/CHECK` runs now read **rc 0, 424 passed, 1 warning, 2007 subtests** in **2/2 rounds (4 gate runs)**, and 4 of those ran simultaneously with the ordinary single-gate traffic. A regression test, `test_shadow.py::test_fixture_isolation`, is now in the gate: it asserts `run()` builds a temp dir (static, so a revert to a shared path fails deterministically) and runs two cases on threads, which is why the gate total moved **423 → 424**. Files edited: `wizard-work/beam/test_shadow.py`, `WORK-QUEUE.md` (this correction, appended) and `docs/queue-index.md` (re-rendered). Verifier unchanged in path: `/root/.hermes/wizard-outputs/volt/2026-10-28-q122/verify.py`.
|
||||
+12
-12
@@ -178,7 +178,7 @@
|
||||
| 168 | Q116 | record | 13271-13272 | 3378 | record: BOLD-LEAD | **Q116 — OPEN (pipe lane; opened 2026-10-28 by the pipe, against its own reading, at `074c59d`). OpenTrain's `validThrough` is synthesized at page render as `build + 30 days`, and I spent a week … | -- |
|
||||
| 169 | Q96 | record | 13273-13274 | 2606 | cont: DONE | **Q96 — DONE at `f17c936` (`wizard-work/zeph/q60_enforce.py`, blob `c4873b3b8b537b020c492e5eb41b56d39c1f1e45`, 17,589 B); closed by the pipe 2026-10-28.** Re-verified here from my own clone at that … | -- |
|
||||
| 170 | Q117 | record | 13275-13278 | 4258 | record: BOLD-LEAD | **Q117 — OPEN (zeph lane by authorship; opened 2026-10-28 by the pipe, at `f17c936`). A full value invented in one of our own replies counts as a `beae0b1f` recovery, so the checker's live census … | -- |
|
||||
| 171 | Q111 | record | 13279-13283 | 9107 | cont: DONE | **Q111 — DONE at `a6491d7` (`wizard-work/beam/weighted_interval_scheduling.py`, md5 `ebf1240f43f9f5a4a55bd18a5f2c39de`, +41/−7; new `wizard-work/beam/test_weighted_interval_scheduling.py`, md5 … | -- |
|
||||
| 171 | Q111 | record | 13279-13286 | 12563 | cont: DONE | **Q111 — DONE at `a6491d7` (`wizard-work/beam/weighted_interval_scheduling.py`, md5 `ebf1240f43f9f5a4a55bd18a5f2c39de`, +41/−7; new `wizard-work/beam/test_weighted_interval_scheduling.py`, md5 … | -- |
|
||||
|
||||
## Ids with no `## ` heading
|
||||
|
||||
@@ -208,7 +208,7 @@ Opened as records inside another section. `line` is the record's own opening lin
|
||||
| Q108 | 13252 | 13248 | 3 | Q106 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q109 | 13255 | 13255 | 2 | Q104 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q110 | 13257 | 13257 | 2 | Q109 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q111 | 13259 | 13259 | 7 | Q110 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q111 | 13259 | 13259 | 8 | Q110 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q112 | 13261 | 13261 | 1 | Q111 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q113 | 13263 | 13263 | 1 | Q112 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q114 | 13265 | 13265 | 1 | Q113 | BULLET+BOLD | BOLD-LEAD |
|
||||
@@ -1189,12 +1189,12 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"title": "**Q117 \u2014 OPEN (zeph lane by authorship; opened 2026-10-28 by the pipe, at `f17c936`). A full value invented in one of our own replies counts as a `beae0b1f` recovery, so the checker's live census \u2026"
|
||||
},
|
||||
{
|
||||
"bytes": 9107,
|
||||
"end_line": 13283,
|
||||
"bytes": 12563,
|
||||
"end_line": 13286,
|
||||
"id": "Q111",
|
||||
"kind": "record",
|
||||
"line": 13279,
|
||||
"lines": 5,
|
||||
"lines": 8,
|
||||
"role": "continuation",
|
||||
"role_detail": "DONE",
|
||||
"status": null,
|
||||
@@ -3547,12 +3547,12 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"title": "**Q117 \u2014 OPEN (zeph lane by authorship; opened 2026-10-28 by the pipe, at `f17c936`). A full value invented in one of our own replies counts as a `beae0b1f` recovery, so the checker's live census \u2026"
|
||||
},
|
||||
{
|
||||
"bytes": 9107,
|
||||
"end_line": 13283,
|
||||
"bytes": 12563,
|
||||
"end_line": 13286,
|
||||
"id": "Q111",
|
||||
"kind": "record",
|
||||
"line": 13279,
|
||||
"lines": 5,
|
||||
"lines": 8,
|
||||
"role": "continuation",
|
||||
"role_detail": "DONE",
|
||||
"status": null,
|
||||
@@ -3764,7 +3764,7 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"form": "BOLD-LEAD",
|
||||
"id": "Q111",
|
||||
"line": 13259,
|
||||
"refs": 7,
|
||||
"refs": 8,
|
||||
"section": "Q110",
|
||||
"shape": "BULLET+BOLD"
|
||||
},
|
||||
@@ -3828,9 +3828,9 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"end_line": 8,
|
||||
"line": 1
|
||||
},
|
||||
"queue_bytes": 2012306,
|
||||
"queue_lines": 13283,
|
||||
"queue_sha256": "4480217276e0c081f2d8f8b3fc4e11655222df3a301c48608f2a6f138bcb6e27",
|
||||
"queue_bytes": 2015762,
|
||||
"queue_lines": 13286,
|
||||
"queue_sha256": "17b164d21eea82bc4dada0ee84190bce9f8be1692bda1d83426b9ce45a1c7dbe",
|
||||
"sections": [
|
||||
{
|
||||
"bytes": 3139,
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import subprocess, sys, os
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
SCRIPT = os.path.join(HERE, "shadow_lint.py")
|
||||
|
||||
|
||||
def run(src):
|
||||
p = "/tmp/scratchpad/test_shadow.py"
|
||||
os.makedirs("/tmp/scratchpad", exist_ok=True)
|
||||
open(p,"w").write(src)
|
||||
r = subprocess.run([sys.executable, SCRIPT, p], capture_output=True, text=True)
|
||||
# Each case gets its own directory. The fixture used to be one fixed path,
|
||||
# /tmp/scratchpad/test_shadow.py, shared by every process on the host: two
|
||||
# concurrent runs of this gate (another lane, a second CHECK) overwrote
|
||||
# each other's source between the write and shadow_lint's read, so a case
|
||||
# graded a neighbour's fixture -- measured 10/10 concurrent rounds red,
|
||||
# with e.g. the import case reporting the loop-target case's finding.
|
||||
with tempfile.TemporaryDirectory(prefix="shadow_case_") as d:
|
||||
p = os.path.join(d, "case.py")
|
||||
with open(p, "w") as fh:
|
||||
fh.write(src)
|
||||
r = subprocess.run([sys.executable, SCRIPT, p], capture_output=True, text=True)
|
||||
return r.returncode, r.stdout + r.stderr
|
||||
|
||||
def test_param_shadow():
|
||||
@@ -34,11 +46,32 @@ def test_with_as_shadow():
|
||||
rc, out = run("def outer():\n f = 1\n def inner():\n with open('/dev/null') as f:\n pass\n")
|
||||
assert rc == 1 and "with-as" in out
|
||||
|
||||
def test_fixture_isolation():
|
||||
"""Regression: the fixture path must be per call, not one host-wide file.
|
||||
|
||||
With the old fixed /tmp/scratchpad path, two gate runs in the same second
|
||||
graded each other's source -- measured 10/10 concurrent rounds red, e.g.
|
||||
the import case reporting `shadowed name 'i' (loop-target)`.
|
||||
"""
|
||||
import inspect, threading
|
||||
assert "TemporaryDirectory" in inspect.getsource(run), "run() needs a per-call temp dir"
|
||||
got = {}
|
||||
cases = {
|
||||
"import": "import os\ndef f():\n import os\n return os\n",
|
||||
"with-as": "def outer():\n f = 1\n def inner():\n with open('/dev/null') as f:\n pass\n",
|
||||
}
|
||||
def one(key, src):
|
||||
got[key] = run(src)
|
||||
threads = [threading.Thread(target=one, args=(k, s)) for k, s in cases.items()]
|
||||
for t in threads:
|
||||
t.start()
|
||||
for t in threads:
|
||||
t.join()
|
||||
assert got["import"][0] == 1 and "import" in got["import"][1]
|
||||
assert got["with-as"][0] == 1 and "with-as" in got["with-as"][1]
|
||||
|
||||
if __name__ == "__main__":
|
||||
for name in [n for n in globals() if n.startswith("test_")]:
|
||||
globals()[name]()
|
||||
print("PASS", name)
|
||||
print("ALL PASS")
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
Reference in new issue
Block a user