# /sync — Sync & Refresh Umbrella Project

Một lệnh cho cả **setup lần đầu** lẫn **cập nhật hằng ngày** một umbrella repo có git submodule.
An toàn chạy lặp lại — tự phát hiện cần làm gì.

**Argument tuỳ chọn:** `/sync [spec-branch]` — branch của spec submodule để pull (vd `/sync develop`). Nếu bỏ, branch được phân giải tự động (xem Step 0-D).

---

## Step 0 — Pre-flight Checks

**A. Git repo check**

Xác minh thư mục hiện tại nằm trong git repo. Nếu không → dừng:
```
❌ Not a git repository. Open Claude Code from umbrella root and retry.
```

**B. Đọc project config sớm**

Đọc `.agent/project-context.yaml` trước khi chạy lệnh git nào. Trích:
- `setup.spec_source` → path của spec submodule (vd `"my-project-specs"`)
- `services` → map domain → `{path, module, ...}` cho mỗi service submodule

Cần cái này để phân biệt spec vs service submodule ở Step 1.

Nếu `.agent/project-context.yaml` không tồn tại → cảnh báo và set `spec_source = null`, `services = {}`.

**C. Submodule status scan**

Chạy `git submodule status --recursive` và phân loại mỗi entry theo ký tự đầu:

| Char | Ý nghĩa | Hành động |
|------|---------|--------|
| `-` | Chưa init | → **Setup mode** |
| ` ` | Khớp pointer đã ghi | → OK |
| `+` | Ahead của pointer đã ghi (local advance chưa commit) | → cảnh báo từng submodule |
| `U` | Merge conflict | → **STOP** |

Nếu **bất kỳ** entry nào có `U`:
```
❌ Merge conflict in submodule: {path}
   Resolve manually before running /sync:
     cd {path} && git status
```

Nếu **bất kỳ** entry nào có `+` (commit đang checkout khác pointer đã ghi):
```
ℹ️ {path} is ahead of the umbrella's recorded pointer.
   /sync classifies it in Step 1b — if you're on a branch there, it stays untouched.
```
Đừng xử lý `+` ở đây — Step 1b quyết định cách xử lý đúng cho từng submodule.

In mode phát hiện: `Mode: Setup (first-time init)` hoặc `Mode: Update (sync latest)`.

---

## Step 1 — Umbrella Pull

Ghi branch umbrella hiện tại trước (đây là cái `git pull` cập nhật):
`git rev-parse --abbrev-ref HEAD` → lưu thành `umbrella_branch` và hiển thị.

```bash
# 1. Pull latest umbrella (includes updated submodule pointer records)
git pull

# 2. Sync .gitmodules config into local git config
#    (needed when new submodules were added since last clone)
git submodule sync --recursive

# 3. Initialize any NOT-yet-cloned submodules ONLY (the '-' entries from Step 0-C).
#    Do NOT run a blanket `git submodule update --recursive` — that would detach
#    a submodule you are actively working in. Per-submodule handling is Step 1b.
git submodule update --init {paths that were '-' in Step 0-C}
```

Nếu `git pull` exit khác 0 → in lỗi và dừng với `❌`.

---

## Step 1b — Phân loại & Sync từng Submodule

**Ý tưởng cốt lõi:** `/sync` không bao giờ áp một branch lên submodule. Nó **kiểm tra checkout hiện tại của từng submodule** và tôn trọng nó. Đây là cách nó biết submodule nào bạn đang làm vs cái nào là dependency thụ động.

Với mỗi submodule (dùng `git submodule foreach` hoặc lặp các path), đọc state:

```bash
# Inside each submodule:
git symbolic-ref --short -q HEAD   # → branch name, or empty/non-zero if DETACHED
git status --porcelain             # → non-empty means uncommitted local changes
```

Phân loại vào một trong bốn case và xử lý tương ứng:

| Case | State phát hiện | Hành động |
|------|----------------|--------|
| **Spec submodule** | `path == spec_source` | Advance tới `spec_branch` (Step 1c bên dưới) |
| **Active (on a branch)** | HEAD là một branch, không detached | **KHÔNG checkout.** Đây là nơi bạn (hoặc đồng đội) đang code. Chỉ `git -C {path} fetch` và report branch + ahead/behind. Để working tree y nguyên. |
| **Passive (detached, clean)** | Detached HEAD, không có thay đổi local | An toàn align về pointer đã ghi của umbrella: `git submodule update {path}` |
| **Dirty (uncommitted changes)** | `git status --porcelain` non-empty | **Đừng đụng.** Cảnh báo: `⚠️ {path} has uncommitted changes — skipped. Commit or stash before syncing this submodule.` |

> **Vì sao quan trọng:** Một `git submodule update` toàn bộ checkout mọi submodule về **detached HEAD** ở pointer đã ghi. Nếu bạn đang checkout `feature/FEAT-01` trong `user-service/` và đang làm dở, cái đó sẽ âm thầm chuyển bạn khỏi branch. Phân loại trước bảo vệ công việc đang làm của bạn.

---

## Step 1c — Advance Spec Submodule *(chỉ khi `spec_source` được cấu hình)*

Spec submodule là submodule duy nhất ta cố ý advance tới một branch HEAD (PO push spec liên tục).

**Phân giải spec branch** (giờ submodule đã init), theo thứ tự ưu tiên:

1. **Command argument** — nếu `$ARGUMENTS` chứa tên branch → dùng nó (override một lần)
2. **`.gitmodules` config** — `git config -f .gitmodules --get submodule.{spec_source}.branch`. Nếu set → dùng nó (default committed của team)
3. **Remote default** — else branch default của spec repo: `git -C {spec_source} rev-parse --abbrev-ref origin/HEAD` (bỏ prefix `origin/`)

Lưu thành `spec_branch` + `spec_branch_source` (argument | .gitmodules | remote-default). Nếu nó rơi xuống remote-default mà không có gì pin, thêm hint này vào output:
```
ℹ️ Spec submodule branch not pinned in .gitmodules — using remote default '{spec_branch}'.
   To pin it for the whole team:
     git config -f .gitmodules submodule.{spec_source}.branch {spec_branch}
     git add .gitmodules && git commit -m "chore: pin spec submodule branch"
```

Rồi kiểm tra an toàn: nếu spec submodule có thay đổi chưa commit → cảnh báo và skip (dev nên coi spec là read-only). Ngược lại dùng **explicit checkout** (không phải `--remote` trần) để branch rõ ràng:

```bash
cd {spec_source}
git fetch origin
git checkout {spec_branch}        # branch resolved in Step 0-D
git pull origin {spec_branch}
cd -                              # back to umbrella root
```

In: `Spec submodule {spec_source}: pulled branch '{spec_branch}' (source: {spec_branch_source})`

> **Vì sao không `--remote` cho service submodule?** Service submodule bị version-lock bởi pointer đã ghi của umbrella — cố ý để mọi dev làm từ cùng commit. `--remote` sẽ bỏ qua lock này và tạo pointer drift chưa commit. Spec submodule là ngoại lệ: PO push liên tục, nên ta advance nó tới branch HEAD — nhưng làm bằng explicit `checkout {spec_branch}` thay vì `--remote` để nó không bao giờ âm thầm theo sai branch.

Nếu `git pull` hoặc `git submodule update` exit khác 0 → in lỗi và dừng với `❌`.

Thu từ output:
- Submodule nào đổi SHA
- Cái nào đã up to date
- `{old_sha}..{new_sha}` của spec submodule (cần cho Step 1d)

---

## Step 1d — Surface Feedback của Tester/QC *(bug report / scenario proposal / PRD change request)*

`/report-bug`, `/propose-scenario` của tester & QC (gồm cả PRD change request Case B) commit feedback vào spec repo. Step này cho PO/Dev biết cái gì tới trong **lần** pull này, để họ được thông báo qua routine bình thường. Nó phủ cả hai đối tượng:

- **Dev/tester trong umbrella** → feedback tới qua spec submodule advance (Step 1c)
- **PO làm trực tiếp trong spec repo** → feedback tới qua `git pull` của umbrella/current-repo (Step 1)

Chọn repo + range đã pull feedback:
- Umbrella có `spec_source` → `REPO={spec_source}`, range = spec submodule `{old_sha}..{new_sha}`
- Ngược lại (chạy trong chính spec repo) → `REPO=.`, range = `{old_sha}..{new_sha}` của `git pull` từ Step 1

Nếu `feedback/` không tồn tại trong REPO → skip âm thầm.

```bash
git -C {REPO} diff --name-status {old_sha}..{new_sha} -- feedback/bug-reports/ feedback/bdd-proposals/ feedback/prd-change-requests/
```

Với mỗi entry, đọc title/summary + `State` và report. **Bug report: chỉ surface `State: Open`** là cần chú ý; liệt kê `Fixed`/`Closed` riêng (hoặc bỏ) để PO/PM thấy cái gì còn pending:
```
📥 New feedback (pulled this sync):
   Bug reports (open):
     BUG-20260608-01  FT-001 — account locks after 6 fails (spec says 5)   [layer: Code · waiting: dev]
   Bug reports (fixed, awaiting QC re-verify): BUG-20260605-02
   Scenario proposals:
     FT-001-trailing-spaces.md  → maps to AC2  (pending review)
   PRD change requests:
     FT-001-bulk-export.md  → new requirement, needs an AC  (waiting: PO)
```

Nếu không có gì đổi → in `📥 Feedback: none new this sync`.

Nếu người đọc là PO/Dev, thêm một dòng nudge:
`→ Review feedback/ then act: /fix-bug {BUG-ID} · promote proposal via /generate-bdd · or add an AC to the PRD.`

---

## Step 2 — Post-sync State Check

Chạy `git status --short` và kiểm tra entry submodule bị modified (dòng bắt đầu bằng ` M` mà path khớp một submodule).

Nếu pointer submodule nào đổi (thường là spec submodule sau `--remote`):
```
⚠️ Submodule pointer(s) updated — commit to lock new version into umbrella:
   git add {spec_source} && git commit -m "chore: sync {spec_source} to latest"
```

Nếu không có thay đổi → `✅ Umbrella state clean — no commit needed`.

---

## Step 3 — Bootstrap Service Configs

*Skip nếu `services` rỗng.*

Với mỗi entry trong `services[]`:

**A. Nếu `{service.path}/.agent/project-context.yaml` đã tồn tại:**
- Đọc `conventions.test_command` và `conventions.build_command`
- Report: `✅ {service.path} — test: {test_command} | build: {build_command}`

**B. Nếu thiếu — tự tạo:**

1. Xác định `module` từ umbrella `services[].module` (authoritative). Nếu không set, auto-detect từ file trong `{service.path}/`:

   | File có mặt | Module phát hiện | test_command | build_command |
   |---|---|---|---|
   | `pom.xml` | `java-spring` | `mvn test` | `mvn compile` |
   | `build.gradle` or `build.gradle.kts` | `java-spring` | `./gradlew test` | `./gradlew build` |
   | `go.mod` | `golang` | `go test ./...` | `go build ./...` |
   | `*.csproj` or `*.sln` | `dotnet` | `dotnet test` | `dotnet build` |
   | `composer.json` | `php-laravel` | `php artisan test` | `composer install` |
   | `pubspec.yaml` | `flutter` | `flutter test` | `flutter build apk` |
   | `angular.json` | `angular` | `npx ng test --watch=false` | `npm run build` |
   | `next.config.*` | `nextjs` | `npx vitest run` | `npm run build` |
   | `package.json` + `nest-cli.json` | `nestjs` | `npm test` | `npm run build` |
   | `package.json` (fallback) | `react` | `npx vitest run` | `npm run build` |
   | `requirements.txt` or `pyproject.toml` | `context-engineering` | `pytest tests/ -v` | `pip install -r requirements.txt` |
   | *(none matched)* | `unknown` | `{{TEST_COMMAND}}` | `{{BUILD_COMMAND}}` |

2. Tạo thư mục `{service.path}/.agent/` nếu chưa có.

3. Ghi `{service.path}/.agent/project-context.yaml`:

   ```yaml
   # Auto-generated by /sync — review and update as needed
   tech_stack:
     language: "{detected or from module}"
     framework: "{detected or from module}"
     module: "{module}"

   conventions:
     test_command: "{test_command}"
     build_command: "{build_command}"

   paths:
     trace_dir: ".trace"
     lessons_file: ".agent/project-lessons.md"   # per-service guardrails (see /learn)
   ```

4. Report:
   - Nếu auto-detect: `✅ Created {service.path}/.agent/project-context.yaml (module: {module}, test: {test_command})`
   - Nếu unknown/placeholder: `⚠️ Created {service.path}/.agent/project-context.yaml — fill in {{TEST_COMMAND}} and {{BUILD_COMMAND}}`

---

## Step 4 — Check `.gitignore`

Kiểm tra các Living Docs mirror được sinh ra có gitignore không:
- `.trace/` trong `.gitignore` của repo hiện tại (hoặc `.git/info/exclude`)
- `.living-docs/` trong `.gitignore` của **specs module** (khi `setup.spec_source` được set)

Nếu thiếu cái nào:
```
⚠️ Living Docs mirrors not gitignored — they are generated, never commit them:
   echo ".trace/" >> .gitignore
   echo ".living-docs/" >> {spec_source}/.gitignore   # specs module (if spec_source set)
```

---

## Step 5 — Refresh Living Docs *(chỉ umbrella mode)*

*Skip nếu `services` rỗng.*

**Phân giải Living Docs home (cùng quy tắc như `/validate-traces`):**
- `living_docs_dir` = `{spec_source}/.living-docs` nếu `setup.spec_source` được set, else `.living-docs` ở umbrella root. *(Specs module được mount trong mọi service workspace, nên panel phân giải nó kể cả khi dev mở một service submodule đơn.)*
- `panel_mirror` = `./.trace` ở gốc workspace hiện tại.

1. Với mỗi service trong `services[]`: nếu `{service.path}/.trace/` có file `.tsv` → copy chúng vào `{living_docs_dir}/{service-name}/` (tạo dir nếu cần).
2. Ghi merged `{living_docs_dir}/trace-report.json`:
   - Tổng hợp TSV `.trace/` của mỗi service, thêm field `"service"` **và `"platform"`** (suy từ tên file `{UC-ID}-{platform}.tsv`) cho mỗi row, tính lại summary totals. **Không dedupe theo `sc_id` giữa các platform** — `web·SC1` và `system·SC1` là 2 row khác nhau; nhờ field `platform` dashboard hiển thị tách bạch coverage từng platform.
3. **Mirror tới panel location:** copy `{living_docs_dir}/trace-report.json` (+ TSV namespaced) → `{panel_mirror}/` để panel trong repo đang mở không rỗng. Skip nếu `panel_mirror` đã bằng `living_docs_dir`.

In kết quả sync:
```
Living Docs → {living_docs_dir}/ synced  (canonical, specs module)
  {service-name}: {N} TSVs
  trace-report.json: {total} scenarios across {S} services
Panel mirror → {panel_mirror}/  (current workspace)
```

Nếu không tìm thấy dir `.trace/` → `Living Docs: no trace data yet — run /generate-bdd then /generate-code first.`

---

## Step 6 — Refresh Spec Manifest *(nếu có spec_source)*

*Skip nếu `setup.spec_source` vắng.*

Nếu `spec-manifest.yaml` tồn tại HOẶC `setup.spec_source` được cấu hình:
- Re-scan các file PRD `{spec_source}/specs/*/*/*.md` (file `.md` ở gốc mỗi feature folder = PRD; tech-docs/design-spec `.md` nằm sâu hơn nên không bị quét nhầm)
- Rebuild `spec-manifest.yaml` map TICKET-ID → path PRD/BDD/tech-doc
- In: `spec-manifest.yaml refreshed — {N} features indexed`

---

## Output

# Report Footer — Định dạng output chuẩn cho mọi lệnh

Mọi report của lệnh phải kết thúc bằng section footer chuẩn này.

## Status Badge

Chọn một theo kết quả:
- `✅ Complete` — mọi bước thành công, không có vấn đề
- `❌ Failed` — lệnh không hoàn thành được do lỗi chặn
- `⚠️ Warnings` — hoàn thành nhưng có vấn đề không chặn, nên review lại

## Output Artifacts

Liệt kê mọi file được tạo hoặc sửa bởi lệnh này:
```
Output Artifacts:
  {created|updated} {file-path} ({mô tả ngắn})
  {created|updated} {file-path} ({mô tả ngắn})
```

Nếu không ghi file nào (vd: lệnh review hoặc phân tích) → ghi `Output Artifacts: none (read-only)`.

## Pipeline Position

In một sơ đồ pipeline một dòng, đánh dấu phase của lệnh HIỆN TẠI bằng `◀ bạn ở đây`,
để người dùng luôn thấy lệnh này nằm ở đâu trong luồng end-to-end:

```
Discovery → PRD → [Design Spec] → BDD → Tech Design → Code → Dev Self-Check → QC → Trace Audit
```

Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **phase của nó** trong sơ đồ trên:

| Phase | Commands |
|-------|----------|
| Discovery | `/define-product` |
| PRD | `/generate-prd` · `/refine-prd` · `/review-context` (PRD) |
| Design Spec | `/generate-design-spec` |
| BDD | `/generate-bdd` · `/review-context` (BDD) |
| Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
| Code | `/generate-code` · `/review-code` |
| Dev Self-Check | `/dev-gen-test` · `/dev-run-test` · `/dev-smoke-test` |
| QC | `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review` · `/qc-run-test` · `/qc-report` |
| Trace Audit | `/validate-traces` |

Với **lệnh review**, thêm vòng review 3 bước và đánh dấu bước hiện tại, vd:
`Vòng review: [① phân tích ◀] → ② Review Board → ③ --resume`.

**Lệnh xuyên suốt** (`/sync`, `/update-framework`, `/fix-bug`, `/debug`, `/learn`,
`/report-bug`, `/propose-scenario`, `/generate-spec-manifest`) nằm ngoài pipeline tuyến tính —
**bỏ hẳn dòng Pipeline** cho các lệnh này (đừng cố nhét chúng vào sơ đồ).

## Gợi ý lệnh tiếp theo

Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:

| Lệnh hiện tại           | Gợi ý lệnh tiếp theo                          |
|-------------------------|-----------------------------------------------|
| /setup-ai-first         | `/define-product` để bắt đầu feature đầu tiên |
| /define-product         | `/generate-prd {product-definition-file}`     |
| /generate-prd           | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
| /refine-prd             | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
| /review-context (PRD)   | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` (→ design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX → sửa PRD (giữ draft) |
| /generate-design-spec   | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
| /generate-bdd           | `/review-context {feature-file}` để kiểm tra độ phủ |
| /review-context (BDD)   | `/generate-tech-docs {UC-ID}` nếu APPROVED; sinh lại nếu NEEDS_FIX |
| /qc-analyze             | `/qc-plan {UC-ID}` (xử lý các gap blocker 🔴 trước) |
| /qc-plan                | `/qc-design-test {UC-ID}`                     |
| /qc-design-test         | `/qc-review {UC-ID}` (review test-case)       |
| /qc-review (test-case)  | `/qc-run-test {UC-ID}` nếu APPROVED; sửa TC nếu NEEDS_FIX |
| /qc-run-test            | `/qc-report {UC-ID}` rồi `/qc-review {UC-ID}` (review script) |
| /qc-review (script)     | `/qc-report {UC-ID}` rồi tạo PR nếu APPROVED |
| /qc-report              | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
| /generate-tech-docs     | `/review-tech-docs {tech-design-file}`        |
| /review-tech-docs       | `/generate-code {feature-file}` nếu APPROVED; sửa doc nếu NEEDS_FIX |
| /generate-code          | Lần gen đầu → `/review-code {UC-ID}`; gen lại → `/dev-gen-test {UC-ID}` |
| /dev-gen-test         | `/dev-run-test {UC-ID}`                          |
| /dev-run-test (passing)    | `/review-code {UC-ID}`                        |
| /dev-run-test (failing)    | `/fix-bug {ticket-id}` hoặc `/debug {error}`    |
| /review-code            | `/dev-smoke-test {UC-ID}` hoặc tạo PR            |
| /dev-smoke-test             | Tạo PR và link tới ticket                  |
| /validate-traces        | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/dev-gen-test {UC-ID}`; tất cả OK → tạo PR |
| /fix-bug                | Tạo PR và link tới ticket                  |
| /debug                  | `/fix-bug {ticket-id}` nếu cần sửa          |
| /report-bug             | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
| /propose-scenario       | Báo PO/Dev review proposal trong `feedback/bdd-proposals/` |
| /learn                  | Tiếp tục làm việc — lesson áp dụng ở lệnh kế tiếp |
| /sync                   | `/validate-traces` để xem độ phủ đầy đủ; xử lý mọi `📥 tester feedback` được nêu |
| /update-framework       | Review `git diff .agent/`, commit; `/sync` để đồng bộ nội dung dự án |

Định dạng footer như sau:
```
---
Status   : {badge}
{khối Output Artifacts}
Pipeline : Discovery → PRD → [BDD ◀ bạn ở đây] → Tech Design → Code → Dev Self-Check → QC → Trace Audit
           (lệnh review) Vòng review: [① phân tích ◀] → ② Review Board → ③ --resume
Next     : {lệnh gợi ý kèm ví dụ tham số}
```
*(Bỏ dòng `Pipeline` cho các lệnh xuyên suốt liệt kê ở trên.)*


```
/sync — {Setup | Update}

Git
  ✅ git pull             — umbrella on branch '{umbrella_branch}'
  ✅ submodule sync       — .gitmodules config refreshed

Submodules (each handled by its current state)
  ✅ {spec_source}    [spec]            — pulled branch '{spec_branch}' ({spec_branch_source}) → {new-sha}
  ✋ user-service     [active]          — on 'feature/FEAT-01' — left untouched, fetched (↓2 behind origin)
  ✅ order-service    [passive]         — aligned to umbrella pointer {sha}
  ⚠️ payment-service  [dirty]           — uncommitted changes, skipped (commit/stash first)

Umbrella state
  ⚠️ Pointer changed: git add {spec_source} && git commit -m "chore: sync specs"
  (or: ✅ Clean — no commit needed)

Tester feedback (pulled this sync)
  📥 1 bug report:  BUG-20260608-01 FT-001 [Code]
     1 proposal:    FT-001-trailing-spaces → AC2 (pending review)
  (or: 📥 none new this sync)
  → /fix-bug {BUG-ID} · promote proposal into BDD · or update PRD

Service Configs
  ✅ user-service    — test: mvn test  | build: mvn compile
  ✅ order-service   — test: mvn test  | build: mvn compile
  ⚠️ payment-service — .agent/project-context.yaml missing
                       → create it so /dev-run-test works correctly

.gitignore
  ✅ .trace/ is gitignored
  (or: ⚠️ Add .trace/ to .gitignore)

Living Docs
  ✅ .trace/ synced — {N} TSVs across {S} services
     (run /validate-traces for full coverage report)

Spec Manifest
  ✅ spec-manifest.yaml — {N} features indexed

---
Status : ✅ Complete | ⚠️ Warnings
Output Artifacts: updated .trace/ (umbrella mirror), spec-manifest.yaml
Next   : /validate-traces (full coverage check) | /generate-code {UC-ID} (start coding)
```
