# /fix-bug — Workflow Fix Bug đầy đủ

## Gate
{{include:steps/gate.md}}

*Lưu ý: Với lệnh này, target ở Bước 1 là một ticket ID (vd `PROJ-123`), một **bug đã file `{BUG-ID}`** (một `{paths.bug_reports_dir}/{BUG-ID}.md` từ `/report-bug` — vd một QC product-gap), hoặc một mô tả bug từ `$ARGUMENTS`. Nếu cho `{BUG-ID}`, phân giải & đọc report đó để lấy spec context; ngược lại tiếp tục sang context loading.*

## Context
{{include:steps/context-loader.md}}

---

## Phase 1 — Gather Info
Nếu cho `{BUG-ID}`: đọc `{paths.bug_reports_dir}/{BUG-ID}.md` để lấy spec context, AC bị vi phạm, expected-vs-actual, và layer gợi ý — dùng làm chi tiết bug (không cần hỏi lại).
Nếu ticket: fetch chi tiết (hoặc nhờ user dán).
Nếu không có ticket / BUG-ID — CHECKPOINT:
1. Bug xảy ra ở đâu? (module, endpoint, flow)
2. Các bước tái hiện?
3. Expected vs Actual?
4. Error log / stack trace?

## Phase 2 — Root Cause Analysis

Dùng `active_module` từ context để chọn bảng liên quan.

### Nếu `platform_type = backend`

#### java-spring / golang / dotnet / php-laravel

| Bug Type | Vị trí thường gặp | Cách kiểm tra |
|----------|----------------|--------------|
| Wrong response data | Mapping layer | Kiểm tra field mapping, DTO conversion |
| 400 Bad Request | Input validation | Kiểm tra DTO constraint / validator |
| 401 Unauthorized | Auth filter | Kiểm tra token config, thứ tự filter |
| 403 Forbidden | Auth config | Kiểm tra rule role-based access |
| 404 Not Found | Repository query | Kiểm tra find method, kiểu ID |
| N+1 Query | Data access | Kiểm tra thiếu JOIN FETCH / eager load |
| Null Pointer | Optional chưa xử lý | Kiểm tra Optional.orElseThrow, null guard |
| Transaction rollback | Thiếu @Transactional | Kiểm tra transaction scope, propagation |
| Stale cache | Thiếu eviction | Kiểm tra trigger cache invalidation |
| Type mismatch | Filter / specification | Kiểm tra kiểu field trong predicate |

#### context-engineering (AI/LLM pipelines)

| Bug Type | Vị trí thường gặp | Cách kiểm tra |
|----------|----------------|--------------|
| Wrong pipeline output | Prompt template | Kiểm tra nội dung prompt; verify biến được substitute đúng |
| Missing context in output | Context assembly | Verify mọi context block bắt buộc có mặt và không rỗng |
| Schema validation failure | Output parser | So raw LLM output vs schema kỳ vọng; thêm output instruction chặt hơn |
| Flaky / non-deterministic results | LLM temperature | Kiểm tra temperature; dùng fixed seed/mock trong test |
| API rate limit errors | LLM client | Implement backoff; kiểm tra quota trên dashboard provider |
| Token limit exceeded | Prompt assembly | Giảm kích thước context; thêm chiến lược chunking |

### Nếu `platform_type = web-frontend`

| Bug Type | Vị trí thường gặp | Cách kiểm tra |
|----------|----------------|--------------|
| Wrong data displayed | State / store | Kiểm tra logic update state, selector |
| UI not re-rendering | Thiếu reactive dep | Kiểm tra deps array, state immutability |
| API data not loading | HTTP client / hook | Kiểm tra network tab, error handler |
| 401 on API call | Auth token | Kiểm tra token refresh, header injection |
| Form not submitting | Validation / handler | Kiểm tra form state, field bắt buộc, error |
| Route not found | Router config | Kiểm tra route definition, lazy import |
| Build / type error | TypeScript types | So type definition vs shape API thực tế |

### Nếu `platform_type = mobile`

| Bug Type | Vị trí thường gặp | Cách kiểm tra |
|----------|----------------|--------------|
| Screen shows stale data | State / BLoC / ViewModel | Kiểm tra event dispatch, state emit đúng |
| Crash on navigation | Thiếu route param | Kiểm tra param truyền, null safety |
| API call not firing | Repository / service layer | Thêm log trong repo method, kiểm tra network |
| UI not reflecting state | Widget không observe stream | Kiểm tra setup `BlocBuilder` / `StateObserver` |
| Crash on app resume | Lifecycle handler | Kiểm tra logic `onResume` / `viewDidAppear` |
| Auth token expired | Token refresh logic | Kiểm tra refresh flow, token storage |
| Permission denied | OS permission | Kiểm tra code request runtime permission |

CHECKPOINT — Root Cause Report:
```
Bug: {description} | Module: {name}
Root cause: {analysis}
Affected files: {list}
Proposed fix: {what to change}
Regression risk: Low / Medium / High
Proceed? (Y/N)
```

## Phase 3 — Fix

*Umbrella mode: code lỗi sống trong **service submodule** phân giải ở context-loader Bước 1.6 — tạo branch và chạy mọi bước git/build từ **trong** `{service_root}`. Single-service: bỏ `cd`.*

```bash
cd {service_root}                              # umbrella: the service submodule; single-service: omit
git checkout -b fix/{TICKET_ID}-{description}
```
Áp dụng fix. Thêm trace annotation nếu file có `@trace.implements`:
```
@trace.fixes={TICKET_ID}
@trace.root_cause={brief description}
```

## Phase 4 — Regression Test
```
// @trace.verifies={UC-ID}
// @trace.regression={TICKET_ID}
Test: "Regression {TICKET_ID}: {bug description}"
```
Chạy test. Nếu fail → debug và fix (tối đa 3 vòng).

## Phase 5 — Build & Commit (push 2 tầng ở umbrella mode)
```bash
{conventions.build_command}   # tối đa 3 retry — chạy trong {service_root} ở umbrella mode
# Tầng 1 — push fix branch trong service submodule (nơi code sống):
git add {files}
git commit -m "fix({TICKET_ID}): {description}"
git push -u origin fix/{TICKET_ID}-{slug}      # rồi mở PR vào branch được track của service
```
> **Umbrella mode — Tầng 2 (bump umbrella pointer):** umbrella ghi một *commit* của service
> submodule, không phải branch. Sau khi PR fix-branch **merge** vào branch được track của service, bump
> pointer để đồng đội pull umbrella không gặp "commit not found":
> ```bash
> cd -                                          # back to umbrella root
> git add {service_root} && git commit -m "chore: bump {service_root} pointer (fix {TICKET_ID})"
> git push
> ```
> Single-service mode: không có umbrella pointer — Tầng 1 là toàn bộ push. Quy tắc đầy đủ: Sync & Update §4.4 (commit 2 tầng).

## Phase 5.5 — Đóng bug report (nếu fix một `{BUG-ID}` đã file)

*Bỏ qua nếu target là ticket/mô tả thường (không có file `{BUG-ID}`).*

Sau khi fix được commit, cập nhật `{paths.bug_reports_dir}/{BUG-ID}.md`:
- Set `State` → `🟡 Fixed` và thêm một **Resolution** ngắn (root cause + link commit/PR).
- Nó **chưa** `Closed` — QC sở hữu verification: khi `/qc-run-test` chạy lại và `qc_status`
  của SC liên kết flip thành `pass`, nó thành `🟢 Closed` (và `qc_owner`/`qc_blocked_by` clear).
- Commit report đã cập nhật vào spec repo (cùng push 2 tầng như `/report-bug`) để view
  "waiting-on" của PO/PM phản ánh nó trên `/sync`.

Đây là lần ghi duy nhất `/fix-bug` làm tới khu feedback — nó vẫn chỉ fix **code**,
không bao giờ sửa PRD/BDD (thay đổi spec là việc PO/Dev theo BUG_FLOW Case 2–4).

## Phase 6 — Đề xuất ghi Lesson (tuỳ chọn)

Nếu root cause là một **lỗi AI gây ra khi sinh và có thể lặp lại**
(vd nó sinh code skip layer, thiếu null guard, dùng sai pattern —
KHÔNG phải nguyên nhân bên ngoài như outage third-party hay input data sai), hỏi:

```
Root cause này trông như một lỗi AI lặp lại.
Ghi nó thành project lesson để không bị sinh lại? (Y/N)
```

Nếu `Y` → chạy quy trình capture bên dưới với `source=/fix-bug {TICKET_ID}`, một
`category` phù hợp (thường `code-gen`), và `scope` = domain hoặc file glob bị ảnh hưởng.

{{include:steps/capture-lesson.md}}

## Output

{{include:steps/report-footer.md}}

```
/fix-bug Hoàn tất — {TICKET_ID}
Root Cause: {analysis}
Changes: {list}
✅ Regression test added | ✅ Build: SUCCESS
{🐞 BUG-{id} → State: Fixed (pushed) — Closed sau khi /qc-run-test re-verify pass | nếu fix một bug đã file}
{📝 Lesson L-NNN recorded (nếu đã capture)}
Branch: fix/{TICKET_ID}-{slug}
Next: Tạo PR và link tới ticket. {QC: chạy lại /qc-run-test {UC-ID} để verify + đóng bug | nếu áp dụng}
```
