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.4 KiB
| id | status | status_updated | status_note | component | severity | timestamp | last_seen | occurrences | files | tags | related | legacy | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| bug-1437 | open | 2026-09-24 | LSan leaks in test_jobj_hardening (makeInstance 240B + 7B strdup), no fix/suppression | lib | crash | 2026-07-13T00:55:00Z | 2026-09-19T09:00:00Z | 2 |
|
|
true |
bug-1437: Verification run of lib build + xcelib_test --run test_jobj_hardening…
Description
Verification run of lib build + xcelib_test --run test_jobj_hardening (ASAN_OPTIONS=detect_leaks=1) after user changed 4x .datakiller=destroy -> .datakiller=dereference in src/lib/testsuite/test_jobj_hardening.c (to fix a leak in the kvmgr-of-job_t test fixture, since job_t.destroy is NULL in RTTI typeinfo and teardown only runs via job_dereference): Unity reports 5/5 PASS, 0 Failures, 0 Ignored, but LeakSanitizer STILL reports two leaks totaling 247 bytes and the process exits 1 (no halt_on_error/abort_on_error set, so no SIGABRT with plain detect_leaks=1 -- differs from the meson full-suite run which sets abort_on_error=1 and gets killed by signal 6).
Environment
Not recorded (migrated from buglog.json).
Reproduction
Not recorded (migrated from buglog.json).
Root cause
TWO leaks detected, only one already known. (1) Direct leak of 240 bytes via calloc -> makeInstance -> makeJob_ (../lib/jobj.c:768) -> makeJob (../lib/jobj.c:789) -> test_job_init_propagates_makeJobsub_failure (test_jobj_hardening.c:133) -- this IS the already-diagnosed, out-of-repo makeInstance-does-not-free-on-negative-init-rc characteristic (vendored rtti library), unrelated to the datakiller fix. (2) Direct leak of 7 bytes via strdup -> hard_build_accounts (test_jobj_hardening.c:269) -> test_job_destroy_does_not_leak_accounts (test_jobj_hardening.c:328) -- this is a SEPARATE, NEW leak signature not previously logged, and it is attributed to the exact test (test_job_destroy_does_not_leak_accounts) that the datakiller=dereference fix was meant to make leak-free. NOT YET DIAGNOSED WHY: could be an unrelated small leak in the hard_build_accounts helper itself (e.g. a strdup()d account string never freed regardless of datakiller correctness), or could indicate the datakiller fix is incomplete. Not investigated further per explicit user instruction to build/run/report only, no fixing.
Fix
NOT FIXED IN THIS SESSION -- user explicitly instructed build+run+report only, no code changes. Logging the raw finding so the next session does not have to rediscover it: the accounts-leak test still leaks (7 bytes, strdup, hard_build_accounts) even after the .datakiller=dereference change, though it is a much smaller leak than the pre-existing 240-byte makeInstance one and does not cause any Unity test FAILURE (LSAN leak detection is a separate pass/fail axis from Unity PASS/FAIL in this harness). RECURRENCE 2026-07-16 (2nd occurrence, mechanical-validation pass for job-array-single-wal-record spec, dimension A/full-suite reconfirmation): full lib test binary run (ASan) again reports 638 PASS / 0 FAIL at the Unity level, but LeakSanitizer aborts the process at exit with the same 240-byte makeInstance->makeJob_ (jobj.c:768) leak signature, triggered via test_job_init_propagates_makeJobsub_failure (test_jobj_hardening.c:133). Confirmed this is the SAME pre-existing vendored-rtti-library characteristic already diagnosed in this entry's root_cause (1), not a new leak and not introduced by this feature's production code -- the feature's own new test is simply the first test in the suite to deliberately drive job_init() to fail after makeInstance() has already allocated, so it is the first to trip the latent characteristic. Still NOT FIXED (out of scope for a validation-only pass); flagging that under meson's full-suite invocation (abort_on_error=1) this leak turns into a SIGABRT / non-zero exit code for the lib test binary, so a naive exit-code-only CI gate would read this as a lib-suite failure even though zero Unity assertions fail and zero new markers/regressions exist in feature code.
Verification
Not recorded (migrated from buglog.json).
References
Not recorded (migrated from buglog.json).