원클릭으로
bugfix
End-to-end bug fix workflow — report, analyze, fix, verify, ship (PR + merge + deploy + knowledge capture)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
End-to-end bug fix workflow — report, analyze, fix, verify, ship (PR + merge + deploy + knowledge capture)
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
| name | bugfix |
| description | End-to-end bug fix workflow — report, analyze, fix, verify, ship (PR + merge + deploy + knowledge capture) |
| argument-hint | Bug description or BUG-xxx ID |
You are fixing a bug using a streamlined workflow that skips the full spec ceremony but follows the same deployment strategy as a feature: changes land via PR, ride the project's CI/CD pipeline (staging-first if the project has one), and aren't marked resolved until every declared deploy target is confirmed.
!sh .adlc/partials/ethos-include.sh 2>/dev/null || sh ~/.claude/skills/partials/ethos-include.sh
cat .adlc/config.yml 2>/dev/null || echo "No config — single-repo legacy mode"cat .adlc/templates/bug-template.md 2>/dev/null || cat ~/.claude/skills/templates/bug-template.md 2>/dev/null || echo "No bug template found"cat .adlc/context/conventions.md 2>/dev/null || echo "No conventions found"ls .adlc/bugs/ 2>/dev/null || echo "No bugs directory found"Bug report: $ARGUMENTS
Before proceeding, verify that .adlc/bugs/ exists. If it doesn't, stop and tell the user: "The .adlc/ structure hasn't been initialized. Run /init first."
~/.claude/.global-next-bug (shared across all repos for unique IDs, mirroring the REQ counter — see LESSON-004). The counter is now a cache, not the authority — the remote is the source of truth (REQ-518): allocation derives the remote high-water, takes max(remote, local) + 1, and fast-forwards the local counter, all inside the existing mkdir lock. Allocate via the shared partials/id-alloc.sh helper (BR-5 — the lock block + its REQ-416/LESSON-014 rationale live in the partial). Source it and call adlc_alloc_id in the same fenced block (the cross-fence-fn rule — see conventions.md "Bash in skills"):
. .adlc/partials/id-alloc.sh 2>/dev/null || . ~/.claude/skills/partials/id-alloc.sh
BUG_NUM=$(adlc_alloc_id bug)
# `exit 1` inside adlc_alloc_id's subshell terminates only the subshell — BUG_NUM
# would be silently empty. Guard the parent context (REQ-416 verify D-pass).
[ -n "$BUG_NUM" ] || { echo "ERROR: failed to allocate BUG number — aborting before writing malformed bug report" >&2; exit 1; }
# If ADLC_ALLOC_DEGRADED=1 (remote unreachable), the helper warned on stderr — note
# "id allocated without remote verification — verify before PR" (BR-3). Never block.
adlc_alloc_id bug handles the absent-counter bootstrap scan internally (highest BUG-xxx under $ADLC_REPOS_ROOT; bug reports are .md files so the scan uses -type f), the mkdir lock that serializes concurrent sessions, and the remote high-water max. Single-machine behavior is unchanged when the remote has no higher allocation (BR-7).
Note: the legacy per-repo .adlc/.next-bug counter is deprecated and no longer consulted — existing files can be left in place but should not be read or written.BUG-<id> against the remote — a colleague on another machine may have pushed the same id since allocation. Source partials/id-recheck.sh and call adlc_recheck_id in the same fenced block; a collision halts with the renumber instruction rather than pushing a duplicate:
. .adlc/partials/id-recheck.sh 2>/dev/null || . ~/.claude/skills/partials/id-recheck.sh
BUG_ID=$(printf 'BUG-%03d' "$BUG_NUM")
if ! adlc_recheck_id bug "$BUG_ID"; then
echo "Halting: $BUG_ID collides on the remote — renumber before pushing (see message above)." >&2
exit 1
fi
.adlc/bugs/BUG-xxx-slug.md (always in the current repo — this becomes the "primary" for the bug) using the template from .adlc/templates/bug-template.mdopen, severity based on impact.adlc/config.yml declares siblings AND the bug's fix likely lives in a sibling (e.g., a frontend symptom whose root cause is in a backend repo), add a repo: <sibling-id> field to the bug frontmatter. If the fix spans multiple repos, add a touched_repos: [<id>, <id>] field. The repo: field determines where Phase 3's commit and Phase 4's PR land.repo: or touched_repos: field for routing.repo: and it names a sibling (not this repo), cd into that sibling's path from .adlc/config.yml and do all fix work there. For touched_repos: [...], cd into each in turn — one commit per repo, on a shared branch name. Otherwise fix in the current repo.npm test (or appropriate test command)resolved yet — that happens in Phase 6 after the fix is merged and deployed):
open (or set to in-review if your project uses that value)updated dateFor each touched repo (just the current repo in single-repo mode; each entry in touched_repos: in cross-repo mode):
git -C <worktree> push -u origin fix/bug-xxx-slugadlc_forge_pr_create (source partials/forge.sh in the same fence; run from inside the worktree, or pass -R <owner/repo>). All PR ops route through the forge adapter, never direct gh (REQ-520 BR-1). In cross-repo mode, create the primary repo's PR last so its body can link every sibling.
fix(BUG-xxx): short description — when cross-repo, scope to the repo (e.g., fix(api): null deref in user serializer [BUG-042]).## Summary
[1-2 lines describing what broke and what was fixed in THIS repo]
## Bug
BUG-xxx: [bug title]
Severity: [critical | high | medium | low]
Primary repo: <primary-repo-id>
## Root Cause
[Pulled from the bug report's Root Cause section]
## Files Changed (this repo)
- `path/to/file.ts` — what changed and why
## Related PRs (cross-repo)
[Omit in single-repo mode. Otherwise list each sibling PR URL — back-fill
sibling bodies via `adlc_forge_pr_edit` once every URL is known.]
## Test Plan
- [ ] Unit/integration tests pass locally
- [ ] CI green on this PR
- [ ] Staging deploy succeeded (verified in Phase 6)
- [ ] Production deploy succeeded (verified in Phase 6)
adlc_forge_pr_edit <prUrl> --body ...) to fill in the Related PRs section.gh pr checks <prUrl>. If CI fails, diagnose and re-push — never bypass with --no-verify or admin-merge.This is the equivalent of /proceed's Phase 8 / /wrapup steps, condensed for bugs.
Step 1 — Merge each PR.
adlc_forge_pr_view <prUrl> --json mergeable,mergeStateStatus should report MERGEABLE (on GitHub; ADO normalizes via pr_view). If main has advanced, rebase the fix branch onto origin/main, force-push with lease, and wait for CI to re-pass.adlc_forge_pr_merge <prUrl> --squash --delete-branch. In cross-repo mode, walk touched_repos: order (or merge_order: from .adlc/config.yml if not specified on the bug).Step 2 — Confirm deploys (this is the staging-first gate when the project has one — same model as features).
Skip this step entirely if the project doesn't deploy via Cloud Run (i.e., stack.backends in .adlc/config.yml doesn't include cloud-run and there's no gcp: block).
Otherwise, for each touched service that has a services: entry in .adlc/config.yml, look up gcp.staging_project and gcp.production_project from the config and confirm both:
# Staging
gcloud run services describe <service> \
--project=<gcp.staging_project from config> \
--region=<services[<id>].region or gcp.default_region> \
--format="value(status.latestReadyRevisionName,status.traffic[0].revisionName)"
# Production
gcloud run services describe <service> \
--project=<gcp.production_project from config> \
--region=<services[<id>].region or gcp.default_region> \
--format="value(status.latestReadyRevisionName,status.traffic[0].revisionName)"
Confirm the merge SHA's revision is serving 100% traffic in each. If gcp.production_project is omitted (no separate prod project), only confirm staging.
If staging deployed but production has NOT yet been promoted, wait — the pipeline runs them sequentially. If either fails, surface to the user with the failed deploy log link before claiming the bug resolved.
iOS deploy (only when stack.frontends in .adlc/config.yml includes ios AND the fix touched the iOS repo):
ios.deploy_targets, ios.derived_data_clean, and ios.deploy_command from .adlc/config.yml.ios.derived_data_clean is true: rm -rf ~/Library/Developer/Xcode/DerivedData/*<ios.deploy_command> and deploy to every device in ios.deploy_targets — never skip one. Don't leave this as a follow-up for the user.If stack.frontends doesn't include ios, skip this section entirely.
Step 3 — Update the bug report.
resolvedupdated dateStep 4 — Capture knowledge (NEVER skip — per memory feedback_wrapup_knowledge_capture.md).
Evaluate honestly: did this bug reveal something a future implementer should know?
If yes, write a lesson to .adlc/knowledge/lessons/LESSON-xxx-slug.md using the global atomic counter ~/.claude/.global-next-lesson (shared across all repos for unique IDs, mirroring the REQ/BUG counters — see LESSON-004). The counter is now a cache, not the authority — the remote is the source of truth (REQ-518): allocation derives the remote high-water, takes max(remote, local) + 1, and fast-forwards the local counter, all inside the shared mkdir-lock (~/.claude/.global-next-lesson.lock.d, shared with /wrapup so concurrent /bugfix and /wrapup runs mutually exclude). Allocate via the shared partials/id-alloc.sh helper (BR-5 — the lock block + its LESSON-014 symlink pre-check live in the partial). Source it and call adlc_alloc_id in the same fenced block (the cross-fence-fn rule — see conventions.md "Bash in skills"):
. .adlc/partials/id-alloc.sh 2>/dev/null || . ~/.claude/skills/partials/id-alloc.sh
LESSON_NUM=$(adlc_alloc_id lesson)
# `exit 1` inside adlc_alloc_id's subshell terminates only the subshell — LESSON_NUM
# would be silently empty. Guard the parent context (REQ-416 verify D-pass).
[ -n "$LESSON_NUM" ] || { echo "ERROR: failed to allocate LESSON number — aborting before writing malformed lesson" >&2; exit 1; }
adlc_alloc_id lesson handles the absent-counter bootstrap scan internally (highest LESSON-xxx under $ADLC_REPOS_ROOT; lessons are .md files so the scan uses -type f), the shared mkdir lock, and the remote high-water max. Single-machine behavior is unchanged when the remote has no higher allocation (BR-7). Note: the legacy per-repo .adlc/.next-lesson counter is deprecated and no longer consulted — existing files can be left in place but should not be read or written.
Pre-push recheck (BR-4, BR-8). Before the lesson file is committed on a branch for push, re-verify LESSON-<id> against the remote — a colleague on another machine may have pushed the same id since allocation. Source partials/id-recheck.sh and call adlc_recheck_id in the same fenced block; a collision halts with the renumber instruction rather than pushing a duplicate:
. .adlc/partials/id-recheck.sh 2>/dev/null || . ~/.claude/skills/partials/id-recheck.sh
LESSON_ID=$(printf 'LESSON-%03d' "$LESSON_NUM")
if ! adlc_recheck_id lesson "$LESSON_ID"; then
echo "Halting: $LESSON_ID collides on the remote — renumber before pushing (see message above)." >&2
exit 1
fi
Use the lesson template (.adlc/templates/lesson-template.md, fall back to ~/.claude/skills/templates/lesson-template.md). Filename format is LESSON-xxx-slug.md only — no date prefixes, no bare-numeric prefixes. Include domain, component, and tags so future runs of /spec, /architect, /reflect, and /review can filter by relevance.
If the bug genuinely produced no useful lesson (one-line typo, etc.), say so explicitly in the final summary — don't silently skip.
Step 5 — Clean up.
git -C <main-worktree> checkout main && git -C <main-worktree> pullgit -C <main-worktree> worktree remove <fix-worktree-path>git branch -D fix/bug-xxx-sluggit fetch --pruneStep 6 — Final ship summary.
## BUG-xxx: Bug Title — Resolved
**Severity**: <severity>
**PR(s)**: #nn (and siblings if cross-repo)
**Merged**: YYYY-MM-DD
### Root cause
- 1-2 lines
### Fix
- 1-2 lines
### Deployment
- Staging: <service> revision <hash> @ 100% traffic
- Production: <service> revision <hash> @ 100% traffic
- iOS: deployed to <list of ios.deploy_targets from config> (or "n/a — backend-only fix")
### Lessons captured
- `.adlc/knowledge/lessons/LESSON-xxx-slug.md` — one-line hook
(or "None — fix was straightforward and revealed no new pattern")
Use fix/bug-xxx-slug for the branch name. In cross-repo bugs, use the same branch name in every touched repo so PRs can be linked visually.
fix(BUG-xxx): short description of the fix
When a bug's fix spans repos (via touched_repos: in the bug frontmatter):
/bugfix was invoked from (the "primary" for this bug).fix/bug-xxx-slug).touched_repos:. If the bug report doesn't specify an order, use the merge_order from .adlc/config.yml./proceed instead.Parallel pipeline orchestrator — launch multiple /proceed sessions concurrently across REQs, monitor progress, and report status. Use when the user says "sprint", "run these REQs in parallel", "proceed with all approved REQs", "launch a sprint", or wants to advance multiple requirements simultaneously.
Codebase health audit — identify technical debt, quality issues, and improvement opportunities
End-to-end ADLC pipeline that takes a requirement from spec through to deployed. Takes a REQ number as argument and runs validate → fix → architect → fix → implement → verify (reflect + review) → create PR → wrapup (merge, deploy, knowledge capture). Use when the user says "proceed", "proceed with REQ-xxx", "run the pipeline", "take REQ-xxx to completion", "implement REQ-xxx end to end", or wants to advance a drafted requirement all the way through to deployment in one shot.
Write requirement specs from feature requests
Close out a completed feature — update ADLC artifacts, log knowledge, and summarize
Bootstrap .adlc/ structure in a new repo or subdirectory