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>
74 lines
4.8 KiB
Markdown
74 lines
4.8 KiB
Markdown
---
|
|
name: buglog
|
|
description: Log a new bug, change a bug's status (fixed / partial / cannot-reproduce / ...), record a recurrence, or list open bugs. Bugs are Markdown records in .wolf/bugs/<id>.md checked against a record standard. Use whenever you log or fix a bug, or are asked for the open-bug list.
|
|
argument-hint: new | status <id> <status> | note <id> | recur <id> | list [--open] | show <id> | check
|
|
triggers:
|
|
- /buglog
|
|
- log a bug
|
|
- open bug list
|
|
- mark bug fixed
|
|
---
|
|
|
|
# Buglog Skill
|
|
|
|
Each bug is one Markdown file, `.wolf/bugs/<id>.md`: short machine fields in
|
|
front matter, `# <id>: <summary>`, then the sections of the record standard.
|
|
**Read `bug-record.md` (next to this file) before writing a record**: it says
|
|
what every section must contain (e.g. Environment needs the OS, the libc the
|
|
failing binary loads, toolchain, build profile, commit and deployment).
|
|
|
|
- `.wolf/buglog.json` is an **index generated** from the records (for
|
|
OpenWolf's hooks, `openwolf bug search` and `jq`). Never edit it; every
|
|
`buglog.py` write regenerates it, and `python3 scripts/buglog.py index` does
|
|
it after a hand edit of a record.
|
|
- `.wolf/buglog-archive.json` holds the retired OpenWolf hook auto-detections
|
|
(710 entries, template messages like "Missing guard clause"). They are
|
|
not bug reports; leave them there.
|
|
- Records migrated from the old JSON log carry `legacy: true` and
|
|
`_Not recorded (migrated from buglog.json)._` where the old log had no such
|
|
field. They are exempt from the reporting sections, but changing one to
|
|
`fixed`/`partial` still needs the fix-time sections.
|
|
|
|
Status values and when to use each: `.claude/rules/buglog-status.md`.
|
|
|
|
## Before fixing a bug
|
|
|
|
Search for prior art first (project rule): `openwolf bug search "<error text>"`,
|
|
or `python3 scripts/buglog.py list --grep '<regex>'`.
|
|
|
|
## Commands
|
|
|
|
| Task | Command |
|
|
|------|---------|
|
|
| Log a new bug | `python3 scripts/buglog.py new --summary "<symptom in component, ≤100 chars>" --component <c> --severity <s> [--binary <failing binary>] [--files a,b] [--tags x,y] [--related bug-N]` → prints the file path. Environment is filled in from this machine (pass `--binary` so libc and build profile come from that binary). Then edit the file: replace every `TODO` in Description, Environment (`Deployment`) and Reproduction, and run `check <id>`. |
|
|
| Environment block only | `python3 scripts/buglog.py env [<binary>]` |
|
|
| Check records | `python3 scripts/buglog.py check <id> …` / `check --all` |
|
|
| Mark fixed | Fill in Root cause, Fix and Verification (`- Test:` RED before/GREEN after, `- Suites:`, `- Live:`), then `python3 scripts/buglog.py status <id> fixed --commit <sha> [--commit <sha2>]`. Refused, and nothing written, until the record meets the standard; each `--commit` must be a real commit. |
|
|
| Mark partly fixed | `python3 scripts/buglog.py status <id> partial --note "<what remains>"` (Root cause + Fix required) |
|
|
| Couldn't reproduce | `python3 scripts/buglog.py status <id> cannot-reproduce --repro "0/40 runs, 2026-09-24" --note "<what was tried>"` |
|
|
| Real failure, cause unknown | `python3 scripts/buglog.py status <id> investigating --note "<next step>"` |
|
|
| Not a bug / accepted | `python3 scripts/buglog.py status <id> wontfix --note "<why / who decided>"` |
|
|
| Duplicate | `python3 scripts/buglog.py status <id> duplicate --duplicate-of <other-id> --note "<same defect as ...>"` |
|
|
| Add findings | `python3 scripts/buglog.py note <id> "<text>" [--section "Root cause"]` (appends `UPDATE (date): …`; default section Description) |
|
|
| Seen again | `python3 scripts/buglog.py recur <id> [--note "<where>"]` (bumps occurrences/last_seen; reopens a `fixed`/`wontfix`/`cannot-reproduce` bug) |
|
|
| Open-bug list | `python3 scripts/buglog.py list --open` (add `--tag scheduler`, `--grep`, `--since YYYY-MM-DD`) |
|
|
| One record | `python3 scripts/buglog.py show <id>` |
|
|
| Front-matter field | `python3 scripts/buglog.py set <id> key=<json> ...` |
|
|
|
|
Components: controller, scheduler, worker, lib, harness, apiserver, xcecli,
|
|
xceadmin, autoscaler, build, config, tooling. Severities: data-loss, crash,
|
|
hang, wrong-result, leak, security, noise.
|
|
|
|
## Rules
|
|
|
|
- **Ids**: let `new` pick the id (one past the highest in records + archive).
|
|
- **Editing sections**: edit the Markdown file directly (Edit tool), keeping
|
|
the `## <Section>` headings; then `check <id>` and `index`. Status changes
|
|
go through `status`, never a hand edit of `status:`.
|
|
- **Enforcement**: the pre-commit hook (`scripts/git-hooks/pre-commit`; install
|
|
once per clone with `ln -sf ../../scripts/git-hooks/pre-commit
|
|
.git/hooks/pre-commit`) runs `check --staged`: it refuses staged records
|
|
that miss the standard, a legacy record hand-changed to fixed/partial without
|
|
the fix-time sections, and a stale `buglog.json`.
|
|
- **Gitea**: `/gitea-sync` mirrors status, and refreshes an issue's title and
|
|
body whenever the record's text changes; fix commits are linked.
|