Skip to content

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:

  1. Bug description (if not provided as argument): "What is the bug? Describe what happens."

  2. Severity: "What is the severity?" Options: critical (system down / data loss), high (major feature broken), medium (feature partially broken), low (minor issue / cosmetic)

  3. 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:

  1. Component domains — the canonical vocabulary, read from intake/bug-domains.yaml (a domains: map of id → gloss). Offer the gloss next to each id; the gloss is what stops a near-duplicate pair like tests/testing growing back.
  2. cross-cutting — fixed. For a toolkit-wide bug belonging to no single component.
  3. Product domains — unique domain: values under projects: in intake/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.

  1. Steps to reproduce: "What are the steps to reproduce? (e.g. 1. Go to login page, 2. Enter email, 3. Click submit)"

  2. Expected behavior: "What should happen?"

  3. Actual behavior: "What actually happens?"

  4. 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:

✓ Bug report created: intake/pending/bugs/BUG-NNN.md
  Title: [title]
  Severity: [severity]

Next: /vt-d-triage-bugs  to promote to the bugs/ backlog