The buglog was one 27K-line JSON file whose fields covered only symptom,
root cause and fix, as free text: 2% of entries named the code version a
bug was found on, 12% the build profile, 36% a way to reproduce, and 58% of
the file was OpenWolf hook auto-detections ("Missing guard clause",
"Function not marked async" on .md files).
- .claude/skills/buglog/bug-record.md: the record standard. Eight
sections (Summary as the title, Description, Environment, Reproduction;
Root cause, Fix, Verification, References once fixed), each with the
content it must contain -- e.g. Environment needs the OS, the libc the
failing binary loads (from its ELF interpreter: glibc 2.42 in the nix
shell vs 2.40 on the host), toolchain, build profile and commit.
- .wolf/bugs/<id>.md: 500 records migrated from buglog.json; every field
verified to round-trip. They carry legacy: true and an explicit "not
recorded" where the old log had no such field; component derived from
file paths, severity from keywords (else unknown), fix_commits from
hashes in status_note/fix that git resolves (91 of 463 fixed).
- .wolf/buglog-archive.json: the 710 hook auto-detections, verbatim.
- .wolf/buglog.json is now an index generated from the records, keeping
the fields OpenWolf's hooks and `openwolf bug search` read.
- scripts/buglog.py rewritten: new (template + Environment collected from
the machine and --binary), check, status (refuses a status the record
doesn't support; fixed needs Root cause, Fix, Verification and
--commit hashes git resolves), note, recur, set, show, list, triage,
env, index. 29 unittest cases in scripts/tests/test_buglog.py.
- scripts/git-hooks/pre-commit runs `check --staged`: incomplete staged
records, a legacy record hand-changed to fixed without the fix-time
sections, a new record claiming legacy: true, or a stale index refuse
the commit.
- scripts/gitea-sync.py reads the records: issue body = the record's
sections plus linked fix commits (origin remote, GITEA_COMMIT_REPO to
override), and a body hash so an issue's text is refreshed when the
record changes.
- bug-1866 rewritten to the full standard as the worked example.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4.1 KiB
| id | status | status_updated | status_note | component | severity | timestamp | last_seen | occurrences | files | tags | related | legacy | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bug-1582 | fixed | 2026-09-24 | unknown | unknown | 2026-08-18T13:00:00Z | 2026-09-19T09:00:00Z | 1 |
|
|
|
true |
bug-1582: run-resource-verify.sh task 7.1 round-1 review REJECTED: independent reviewer killed the live…
Description
run-resource-verify.sh task 7.1 round-1 review REJECTED: independent reviewer killed the live scheduler process mid-run (after deployment confirmed up, before its trace-log poll completed) and got VERDICT line unreachable=0 mismatches=1 plus FAILURE line status=MISMATCH ... observed= -- should have been unreachable=1 mismatches=0 and status=UNREACHABLE ... observed=<none>.
Environment
Not recorded (migrated from buglog.json).
Reproduction
Not recorded (migrated from buglog.json).
Root cause
main()'s record-building loop derived sched_ok/api_ok (feeding aggregate_verdict()) by testing whether the SCHEDULER_OBSERVED[$vname]/APISERVER_OBSERVED[$vname] associative-array KEY EXISTED ([ -n "${arr[k]+x}" ]). But query_scheduler_resvals()/query_apiserver_resvals() (tasks 6.3/6.4, already-approved) unconditionally SET these array entries for every accepted+checked resource -- including on a genuine UNREACHABLE/timeout, where the value is just set to the empty string "". Since the key always existed, sched_ok/api_ok were always 1 regardless of reachability, so aggregate_verdict() never saw the real UNREACHABLE status -- it fell through to comparing the injected value against an empty string, which reads as MISMATCH instead of UNREACHABLE. Contradicted Requirement 6.3, design.md's Error Handling ("Layer unreachable ... labeled UNREACHABLE distinctly from MISMATCH ... not a silent skip"), and this task's own SKILL.md documentation of the same behavior. Note: the analogous ctrl_ok derivation (from CONTROLLER_OBSERVED array-key existence) is NOT affected -- query_controller_resvals()/internal_controller_check() has no separate UNREACHABLE concept at all (a query failure there aborts the whole run via fail()), so array-key existence is an accurate proxy for that layer specifically.
Fix
Round-2 remediation: derive sched_ok/api_ok from SCHEDULER_CHECK_RESULTS[$vname]/APISERVER_CHECK_RESULTS[$vname] instead (already correctly populated by tasks 6.3/6.4 with exactly "MATCH", "MISMATCH: injected=... observed=...", or "UNREACHABLE: ...") -- a leading "UNREACHABLE:" means ok=0, anything else (including a defensive UNCHECKED fallback for a missing key, which should never happen given both query_*_resvals() functions iterate the same accepted-name list this loop reads) means ok=1 with the real observed value. Also extracted main()'s inline record-building loop into a standalone build_verdict_records_from_tsv() function (populates global VERDICT_RECORDS) so a synthetic test can exercise main()'s ACTUAL data-marshaling code (not just aggregate_verdict() called directly with hand-built records, which is what round-1's task 8.2-style synthetic tests did and which structurally could never have caught this bug). Live-reproduced the reviewer's exact scenario (kill scheduler right after deployment confirms up, before inject_resources()/query_scheduler_resvals() ever runs) and confirmed the VERDICT line now correctly shows unreachable=9 mismatches=0 (all 9 default-set resources) with status=UNREACHABLE ... observed=<none> FAILURE lines, apiserver/controller layers unaffected (still MATCH). New synthetic regression test (scenario E, using build_verdict_records_from_tsv() directly) added and confirmed to fail against a reverted copy of the old buggy logic (unreachable=0 mismatches=2) and pass against the fix (unreachable=1 mismatches=1 across a mixed good/schedbad/apibad/rejected batch) -- proving the test is meaningful, not tautological.
Verification
Not recorded (migrated from buglog.json).
References
- Related: bug-1581