vt-d-bug-report¶
Report a bug — creates a BugChen intake file (BUG-NNN.md) in intake/pending/bugs/
Plugin: vt-product-dev
Category: Other
Command: /vt-d-bug-report
/vt-d-bug-report — Bug Intake Skill¶
Create a structured bug report in the intake pipeline. Asks clarifying questions and writes a BUG-NNN.md file to intake/pending/bugs/ for later triage.
Invocation¶
/vt-d-bug-report # Start with no context
/vt-d-bug-report "login fails on Safari" # Start with initial description
Execution¶
Step 1: Parse Argument¶
If an argument was provided, use it as the initial bug description. If no argument, set initial description to empty string.
Step 2: Detect Branch Context¶
Run: git branch --show-current
Extract related spec or bug:
- If branch matches feature/spec-NNN-*: related_spec = SPEC-NNN
- If branch matches fix/bug-NNN-*: related_bug = BUG-NNN
- Otherwise: no related context
Step 3: Ask Structured Questions¶
Use AskUserQuestion to collect:
-
Bug description (if not provided as argument): "What is the bug? Describe what happens."
-
Severity: "What is the severity?" Options: critical (system down / data loss), high (major feature broken), medium (feature partially broken), low (minor issue / cosmetic)
-
Domain: "Which domain does this bug belong to?"
Compose the option list from three sources. Each value has exactly one home, so nothing is duplicated and the list cannot drift out of step with itself:
- Component domains — the canonical vocabulary, read from
intake/bug-domains.yaml(adomains:map of id → gloss). Offer the gloss next to each id; the gloss is what stops a near-duplicate pair liketests/testinggrowing back. cross-cutting— fixed. For a toolkit-wide bug belonging to no single component.- Product domains — unique
domain:values underprojects:inintake/projects.yaml. Offer these only when the bug is in a PRODUCT rather than in the toolkit itself.
Nearly every bug filed here is a toolkit bug, so a component domain is usually the answer. Measured 2026-09-18 (BUG-239): of 99 tracked bugs, exactly one carried a product domain.
Do not hand-type a domain that is not on the composed list. Add it to
intake/bug-domains.yaml with a gloss in the same commit as the bug that needed it, then
use it — that file is the single source, and a free-typed value is how the vocabulary
fragmented in the first place.
If intake/bug-domains.yaml is missing or yields zero domains, fall back to
[cross-cutting] as the only option rather than blocking the filing.
Persist the chosen value to the BUG-NNN.md frontmatter as domain: (see Step 5).
Constraint: cross-cutting is valid for bugs ONLY — never for specs
(per SPEC-122 Decision 1). The bug-report skill is the only intake path
where this value may be assigned without further review.
⚠ domain: is not inert metadata. /vt-p-domain-dashboard renders a bug on a product
dashboard when domain equals that product, and fans cross-cutting bugs out to every
dashboard (SPEC-122 T5). A component domain therefore matches no product dashboard — which
is correct for a toolkit bug, and is why the product options stayed on the list for the rare
bug that is not one.
-
Steps to reproduce: "What are the steps to reproduce? (e.g. 1. Go to login page, 2. Enter email, 3. Click submit)"
-
Expected behavior: "What should happen?"
-
Actual behavior: "What actually happens?"
-
Screenshots or logs (optional): "Any screenshot paths or log snippets? (press Enter to skip)"
Step 4: Allocate the BUG Number¶
Allocate the ID — never compute it. BUG-047 replaced the max + 1 scan this step used to
document, because two sessions scanning the same main compute the same answer:
- 2026-08-10 — six distinct defects filed under BUG-041/042/043
- 2026-08-19 — BUG-085/086 claimed twice for unrelated bugs, hours apart
Scanning harder cannot fix that. The allocator reserves the ID with an O_EXCL claim marker
in the shared git dir, and it reads every local and remote ref, so an ID held only on an unmerged
branch is already taken — which a glob of the checked-out tree cannot see. Measured 2026-09-18
(BUG-238): the scan deleted here returned BUG-234, which already existed as
intake/pending/bugs/BUG-234.md on an unmerged branch; the allocator returned BUG-236 for the
same filing, correctly skipping 234 and 235.
id="$(python3 ~/.claude/skills/vt-d-spec-from-requirements/scripts/allocate_spec_id.py \
--cwd "$(git rev-parse --show-toplevel)" --kind bug 2>/dev/null)"
case "$id" in
BUG-[0-9][0-9][0-9]) ;; # good
*) echo "allocator returned '$id', not a BUG id — its checkout predates BUG-047; \
update it before filing" >&2; exit 1 ;;
esac
Use $id verbatim for the filename and the id: frontmatter. It prints one ID on stdout and
always exits 0 — a numbering problem must never block filing a bug.
⚠ Check the prefix, as above. Deployed skills are symlinks into a checkout, so on a machine
whose checkout predates BUG-047 this script does not understand --kind. The never-block contract
forbids it failing loudly, so an older build answers the argparse error with a SPEC-NNN on
stdout and exit 0. Measured: --kind bug printed SPEC-184. Using that verbatim files a bug under
a spec number and burns a spec ID.
⚠ Never pass --no-lock or VT_SPEC_NO_MARKER=1. Both are test-only controls that disable the
reservation this step depends on — with the marker suppressed, 12 concurrent calls returned
1 distinct ID.
⚠ --show is not a preview. It allocates like any other call and prints labelled diagnostics
instead of the bare ID. Measured 2026-09-18 in a throwaway repo: plain, --show, plain, --show,
plain returned 008, 009, 010, 011, 012 — every --show consumed a number. Never reach for it to
"check what the next ID would be".
Do not go back to a max + 1 scan, and do not "simplify" this to a shell one-liner. The
previous one-liner was correct as far as it went and still collided twice. This is the same script
and the same rule the triage-bugs skill uses for renumbering — one implementation, so the next
lesson lands in one place.
Step 5: Write BugChen File¶
Write to intake/pending/bugs/BUG-NNN.md:
---
id: BUG-NNN
title: [first 60 chars of description]
severity: [critical|high|medium|low]
domain: [component id from intake/bug-domains.yaml, 'cross-cutting', or a product domain from intake/projects.yaml]
status: reported
reporter: user
reported_at: [ISO-8601 date]
branch: [current branch name]
related_spec: [SPEC-NNN or null]
related_bug: [BUG-NNN or null]
screenshots: [list of paths, or []]
---
# BUG-NNN: [description]
## Severity
[severity]
## Steps to Reproduce
[steps]
## Expected Behavior
[expected]
## Actual Behavior
[actual]
## Screenshots / Logs
[screenshots or "None provided"]
Step 6: Confirm¶
Display: