src/skills/x-refine-bug/SKILL.md
Refine a bug report and set Refinement Verdict approved/rejected
npx skillsauth add edercnj/claude-environment x-refine-bugInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Refines a bug report by validating completeness of all 9 RA9 sections, enforcing
acceptance criteria quality (Gherkin format), verifying reproduction recipe, assigning
severity and scope classifications, and setting the Refinement Verdict to approved or
rejected with structured blocker feedback.
/x-refine-bug bug-000001 — refine bug by ID/x-refine-bug .aikittools/bugs/bug-000001/bug.md — refine bug by file path| Parameter | Required | Description |
|-----------|----------|-------------|
| bug-id or path | Yes | Bug ID (bug-NNNNNN) or path to bug.md |
| --non-interactive | No | Skip interactive gate; emit JSON result only |
Phase 0 VALIDATE -> Parse and validate bug-id format
Phase 1 LOAD -> Read bug.md; verify 9 RA9 sections present
Phase 2 ASSESS -> Check each section for completeness
Phase 3 GATE -> Compute verdict (approved / rejected)
Phase 4 WRITE -> Update Refinement Verdict block in bug.md
Phase 4.5 STORIES -> If bug approved: validate and stamp each story file
Phase 5 EMIT -> Output JSON result (including storyVerdicts[])
Validate bug-id format:
if [[ ! "$BUG_ID" =~ ^bug-[0-9]{6}$ ]]; then
echo "ABORT [ARGS_INVALID]: Bug ID must match bug-NNNNNN"
exit 2
fi
Locate bug file at .aikittools/bugs/${BUG_ID}/bug.md. If absent, exit 3 (BUG_NOT_FOUND).
Read bug.md. Verify all 9 mandatory sections are present:
## 1. Visão (Vision)## 2. Persona & Cenário de Uso## 3. Entrega de Valor## 4. Critérios de Aceite## 5. Reproduction Recipe## 6. Root-Cause Hypothesis## 7. Regression Test Slot## 8. Dependências## 9. Histórico de DecisãoMissing sections are collected as blockers.
For each section, validate content quality:
Section 1 — Visão: Must have ≥ 1 non-empty line after header.
Section 4 — Critérios de Aceite: Must contain at least one Dado/Given + Quando/When
Então/Then (Gherkin triplet). Missing triplet → blocker AC_MISSING_GHERKIN.Section 5 — Reproduction Recipe: Must contain:
### 5.1 Environment (or 5.1) — environment spec### 5.2 Steps to Reproduce — numbered steps (at least 2)### 5.3 Observed vs Expected — both Observed: and Expected: fields### 5.4 Artifacts — log/screenshot referenceMissing sub-sections → blockers RECIPE_MISSING_ENV, RECIPE_MISSING_STEPS,
RECIPE_MISSING_OBSERVED_EXPECTED, RECIPE_MISSING_ARTIFACTS.
Section 6 — Root-Cause Hypothesis: Must contain hypothesis text (≥ 10 chars).
Section 7 — Regression Test Slot: Must reference a test file path or TBD.
Severity + Scope: The **Status:** Pendente line must exist. Severity and scope are
read from frontmatter (severity, scope fields) or body. If missing, warn but do not
block (they may be set during investigation).
If blockers is empty → verdict = approved.
If any blockers exist → verdict = rejected.
Compute verdictHash:
VERDICT_HASH=$(echo "${BUG_ID}:${verdict}:$(date -u +%Y-%m-%dT%H:%M:%SZ)" | sha256sum | cut -c1-64)
Update the ## Refinement Verdict block in bug.md. The block format:
## Refinement Verdict
```yaml
status: approved
verdictHash: "abc123..."
refinedAt: "2026-05-07T14:00:00Z"
blockers: []
```
When rejected:
## Refinement Verdict
```yaml
status: rejected
verdictHash: "abc123..."
refinedAt: "2026-05-07T14:00:00Z"
blockers:
- AC_MISSING_GHERKIN
- RECIPE_MISSING_STEPS
```
Write atomically via temp file + rename (POSIX rename is atomic on same filesystem):
TMP=$(mktemp "${bug_file}.XXXXXX")
# ... build content ...
mv "$TMP" "$bug_file"
If status transitions to approved, also update **Status:** Pendente →
**Status:** Refinada in the body.
Executes only when bug.md verdict = approved. Skipped when bug verdict = rejected.
Glob all story files in the bug directory:
mapfile -t STORY_FILES < <(find ".aikittools/bugs/${BUG_ID}" -name "story-[0-9][0-9]-*.md" | sort)
For each story file, validate:
Section 1 — Visão: Must have ≥ 1 non-empty line after the ## 1. Visão header (prefix match: ^## 1\. Visão — accepts both ## 1. Visão and ## 1. Visão (Vision) as used in the canonical bug-story template).
Section 4 — Critérios de Aceite: Must contain at least one Given/Dado + When/Quando + Then/Então triplet (Gherkin). Missing → blocker STORY_AC_MISSING_GHERKIN.
Section 5 — Reproduction Recipe: Sub-sections 5.1, 5.3 must be present (story-level recipe inherits from parent bug). Missing → blocker STORY_RECIPE_INCOMPLETE.
Section 7 — Dependências: **Blocked By:** field must be filled (value or —). Missing → blocker STORY_DEPS_MISSING.
Compute per-story hash and write verdict:
for STORY_FILE in "${STORY_FILES[@]}"; do
STORY_NAME=$(basename "$STORY_FILE" .md)
# ... validate sections, collect story_blockers ...
if [[ ${#story_blockers[@]} -eq 0 ]]; then
STORY_VERDICT="approved"
else
STORY_VERDICT="rejected"
fi
STORY_HASH=$(echo "${BUG_ID}:${STORY_NAME}:${STORY_VERDICT}:$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
| sha256sum | cut -c1-64)
# Write verdict block atomically (same pattern as Phase 4)
TMP=$(mktemp "${STORY_FILE}.XXXXXX")
# ... build story content with updated Refinement Verdict block ...
mv "$TMP" "$STORY_FILE"
# Collect result for Phase 5 envelope
STORY_VERDICTS+=("{\"story\":\"${STORY_NAME}\",\"verdict\":\"${STORY_VERDICT}\",\"blockers\":[${story_blockers_json}]}")
done
Story verdict block written in each story file:
## Refinement Verdict
```yaml
status: approved
verdictHash: "def456..."
refinedAt: "2026-05-07T14:00:00Z"
blockers: []
```
Story status transitions:
approved → update **Status:** Pendente → **Status:** Refinada in the story body.rejected → status unchanged; story must be fixed and bug re-refined.Emit JSON to stdout:
{
"bugId": "bug-000001",
"verdict": "approved",
"verdictHash": "abc123...",
"refinedAt": "2026-05-07T14:00:00Z",
"blockers": [],
"statusTransition": "Pendente→Refinada",
"storyVerdicts": [
{ "story": "story-01-regression-test", "verdict": "approved", "blockers": [] },
{ "story": "story-02-fix", "verdict": "approved", "blockers": [] }
]
}
When rejected, statusTransition is null (status unchanged) and storyVerdicts is [] (stories are not validated when bug itself is rejected).
| Code | Name | Condition |
|------|------|-----------|
| 0 | SUCCESS | Verdict written (approved or rejected); stories stamped if bug approved |
| 2 | ARGS_INVALID | Bug ID does not match ^bug-[0-9]{6}$ |
| 3 | BUG_NOT_FOUND | .aikittools/bugs/${BUG_ID}/bug.md not found |
| 4 | BUG_FILE_NOT_FOUND | Bug file path argument does not exist |
| 5 | WRITE_FAILED | Could not write verdict to bug.md or story file |
A bug whose Refinement Verdict is rejected or pending MUST NOT:
x-create-bug Step 8 não deve rodar sem verdict approved)Em Investigação statusA bug story whose Refinement Verdict is rejected or pending MUST NOT:
x-implement-story exits with BUG_NOT_REFINED or STORY_NOT_REFINED)x-create-bug sets initial Refinement Verdict to status: pending on both the bug and its stories. The gate is:
pending → rejected|approved (via x-refine-bug)
rejected → approved (re-run x-refine-bug after fixing blockers)
approved → (locked — no further status changes to verdict)
Once approved, the verdict hash is immutable. Re-running x-refine-bug on an
already-approved bug exits 0 with {"verdict":"approved","idempotent":true,"storyVerdicts":[]}.
| Scenario | Action |
|----------|--------|
| Bug ID invalid format | ABORT exit 2: "Bug ID must match bug-NNNNNN" |
| Bug directory absent | ABORT exit 3: "Bug not found: .aikittools/bugs/<id>" |
| Bug file path not found | ABORT exit 4: "Bug file not found: <path>" |
| Atomic write fails (bug.md) | ABORT exit 5: "Write failed: <reason>" |
| Atomic write fails (story file) | ABORT exit 5: "Write failed: <reason>" |
| Already approved | Exit 0: {"verdict":"approved","idempotent":true,"storyVerdicts":[]} |
| No story files found | Phase 4.5 skipped silently; storyVerdicts: [] in envelope |
| Skill | Relationship | Context |
|-------|-------------|---------|
| x-create-bug | predecessor | Sets initial status: pending verdict on bug and stories |
| x-create-bug (decomposição inline, Step 8) | blocked by gate | Decomposição em stories não deve rodar se bug verdict ≠ approved |
| x-create-bug (mapa inline, Step 9) | blocked by gate | Geração do IMPLEMENTATION-MAP.md só após decomposição (após aprovação) |
| x-implement-story | blocked by gate | BUG_GATE checks bug + story verdicts before proceeding |
development
Documentation freshness gate: validates 6 dimensions (readme, api, adr, etc.) per PR.
testing
Conditional dep-policy gate: CVEs, licenses, versions, freshness; SARIF + report.
documentation
Incrementally updates the service or system architecture document; never regenerative.
development
Scans code and git history for leaked credentials, API keys, and tokens; SARIF output.