@kienntpixon/dieu-phoi 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +3 -0
- package/agents/dp-exec.md +2 -0
- package/agents/dp-helper.md +2 -0
- package/agents/dp-scout.md +2 -0
- package/agents/dp-verify.md +2 -0
- package/bin/dieu-phoi.cjs +14 -2
- package/hook.cjs +788 -34
- package/lib/aggregate.cjs +49 -6
- package/lib/args.cjs +1 -1
- package/lib/choose.cjs +41 -25
- package/lib/commands.cjs +212 -42
- package/lib/knowledge.cjs +77 -22
- package/lib/procs.cjs +223 -0
- package/lib/profile-scan.cjs +85 -0
- package/lib/profile-seed.cjs +147 -0
- package/lib/profile.cjs +141 -1
- package/lib/prune.cjs +56 -8
- package/lib/setup.cjs +47 -15
- package/lib/worktree.cjs +186 -0
- package/package.json +3 -1
- package/profile/lessons.md +83 -0
- package/profile/unity-lanes.md +316 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Unity lanes: nhiều editor Unity song song (phòng ai-lab)
|
|
2
|
+
|
|
3
|
+
Tài liệu miền của profile ai-lab, cho kế hoạch Fast Forward / rebuild game Unity. Agent tìm tới file này qua dòng `unity-lanes`
|
|
4
|
+
trong `profile/lessons.md`; điều phối viên qua dòng `[orch]`. Ký hiệu: `<project>` = checkout chính của game, `<wt_root>` =
|
|
5
|
+
gốc worktree (mặc định `<project>-wt`, cạnh project), `<wt>` = `<wt_root>/<lane>`, `<main>` = nhánh chính của game (vd.
|
|
6
|
+
`mobile-portrait`), `<skill>` = thư mục skill dieu-phoi. Phần toolchain: `docs/machine-setup.md` trong repo ai-lab/pixon-fast-forward.
|
|
7
|
+
|
|
8
|
+
## 1. Khi nào dùng lanes
|
|
9
|
+
- Backlog Unity dài và đồ thị phụ thuộc thật cho phép >= 2 nhánh chạy cùng lúc. Một bước lẻ hoặc chuỗi tuần tự: không dùng.
|
|
10
|
+
- Số đo pilot 2026-10-11: cặp 2 lane 1.59x trước tích hợp, 1.16x khi tính cả bước tích hợp; mô phỏng phần còn lại 3 lane 2.0-2.3x,
|
|
11
|
+
2 lane 1.4-1.7x. Chi phí chính là **test sau merge** (~0.85 h editor trunk mỗi bước lane), không phải merge (1 phút, 0 xung đột).
|
|
12
|
+
|
|
13
|
+
## 2. Mô hình
|
|
14
|
+
- **trunk** = checkout chính trên `<main>`, là đường găng: tích hợp, cổng thiết bị, build Android.
|
|
15
|
+
- **Lane vệ tinh** = git worktree `<wt>` trên nhánh `lane/<lane>`, một editor mỗi lane, nhận trọn một miền tự chứa (vd. repair,
|
|
16
|
+
monetization). Một miền không bao giờ ở hai lane cùng lúc.
|
|
17
|
+
- Planner ghi `unity_lane` (trunk / b / c) cho mỗi bước Unity, và `unity_lane_2` (phương án 2 lane) để lùi về khi thiếu máy.
|
|
18
|
+
- Tạo/mở/liệt kê/xoá lane bằng `lanes.py` (toolset hoặc bản trong game: `create [--sparse] [--keep-art ...]`, `launch`, `list`,
|
|
19
|
+
`env`, `remove`, `device-lock`, `--selftest`). `--sparse` bỏ thư mục art thô (~1-2 GB thay vì ~8 GB checkout).
|
|
20
|
+
|
|
21
|
+
### 2.1 Slot cố định + editor mở sẵn + hàng đợi việc (mặc định từ 2026-10-26)
|
|
22
|
+
- **Tối đa 3 editor Unity mỗi máy** (người dùng đo; con số theo máy ghi trong `~/.pff/machine.env` nếu khác). Đây là trần cứng,
|
|
23
|
+
không phải mục tiêu.
|
|
24
|
+
- **Slot = worktree cố định có Library ấm**, đặt tên và giữ suốt dự án (vd. `<wt_root>/cut|tai|b8`). Không tạo worktree mới cho mỗi
|
|
25
|
+
bước; bước sau `git checkout -B lane/<việc> origin/<main>` trong slot rảnh. Worktree hết dùng thì xoá (`git worktree remove`) sau khi
|
|
26
|
+
kiểm sạch + không còn commit chưa lên `<main>` — Library mỗi cái ~5-10 GB (sự cố 2026-10-26: 19 worktree bỏ quên chiếm ~95 GB).
|
|
27
|
+
- **Agent không tự chạy Unity.exe / `-executeMethod`.** Mỗi slot có một editor có cửa sổ mở sẵn chạy cầu nối (Editor script
|
|
28
|
+
[InitializeOnLoad] đọc hàng đợi job file-based, sống qua domain reload, timeout + watchdog mỗi job); agent gửi job qua CLI
|
|
29
|
+
(`unity_slot.py start|submit --wait|status|stop <slot>`): `refresh_compile`, `editmode`, `playmode`, `smoke <mode> [res]`,
|
|
30
|
+
`screenshot`. Khoá slot để mỗi lúc một agent. Xong việc để editor mở cho lượt sau.
|
|
31
|
+
- **Editor slot chạy ẩn cửa sổ** (từ 2026-10-28, PO không muốn thấy): `start <slot>` ẩn cửa sổ mặc định (`--show` để hiện),
|
|
32
|
+
`hide|show <slot>` chỉ tác động PID editor của slot, `status` in `window hidden|visible`. Cửa sổ ẩn (SW_HIDE) vẫn render Game view
|
|
33
|
+
kèm UI, play mode chạy frame, job cầu nối / unity CLI / `capture` y như cũ. Chỉ `show` khi có người yêu cầu xem, xong `hide` lại.
|
|
34
|
+
- Lý do (đo DTU 2026-10-26): mỗi lần agent tự mở/đóng editor tốn 2-5 phút khởi động, hay để lại editor treo khoá dự án; qua cầu nối
|
|
35
|
+
smoke nhanh hơn ~28-55 s/job, kết quả trùng cách cũ. Agent tiếp nối (handoff) dùng lại đúng slot + nhánh, không mở slot mới.
|
|
36
|
+
- Điều phối viên giữ bảng slot -> lane đang chạy; việc Unity mới xếp hàng theo slot rảnh, không vượt trần. Game chưa có cầu nối: bước
|
|
37
|
+
đầu tiên là dựng nó (bản tham chiếu: pff-tailor `Assets/Tailor/Editor/AgentBridge/` + `tools/unity_slot.py` + `Docs/qa/agent_bridge.md`).
|
|
38
|
+
|
|
39
|
+
### 2.2 Unity CLI trên editor của slot (mặc định từ 2026-10-28, task rs5wj1g4)
|
|
40
|
+
- **Mọi việc editor trực tiếp** (eval C#, sửa scene/asset, play mode, chụp ảnh, đọc console, test nhanh) dùng skill `unity:unity-cli`
|
|
41
|
+
nhắm vào editor ĐANG CHẠY của slot, luôn kèm `--project-path <worktree slot>` (3 editor cùng chạy; thiếu cờ thì CLI theo cwd và có
|
|
42
|
+
thể điều khiển nhầm worktree khác). `python tools/unity_slot.py cli <slot>` in đường dẫn + công thức. Job cầu nối vẫn dùng cho cổng
|
|
43
|
+
compile, chạy test đầy đủ, smoke/VisRun.
|
|
44
|
+
- Giữ kỷ luật khoá slot (`lock`/`unlock --owner <task>`) và trần 3 editor. **Không bao giờ chạy Unity.exe trực tiếp** (kể cả
|
|
45
|
+
`unity open`, `-batchmode`); editor sập thì báo điều phối. Editor mở ngoài `unity_slot.py start` còn mất env lane (sandbox save/prefs).
|
|
46
|
+
- Cần `com.unity.pipeline` 0.9.1-exp.1 (đã lên main pff-tailor e5bb7ca4; worktree cũ còn 0.8.0 dùng tên phẳng `eval`, `editor_play`).
|
|
47
|
+
- Công thức chụp: `editor set_auto_tick -- --enable true` (một lần, nếu không eval timeout 5000 ms) → mở scene đã lưu →
|
|
48
|
+
`editor.playmode start` → `unity status --until-ready` → `job wait -- --condition '{"member":"UnityEngine.Time.frameCount","op":"changed"}' --timeout 10`
|
|
49
|
+
phải `met: true` → `python tools/unity_slot.py capture <slot> --out Logs/cli-render/x.png [--source camera]` (base64 → file, có kiểm
|
|
50
|
+
frame) → `editor.playmode stop`.
|
|
51
|
+
- Bẫy: `capture game_view --save_path` luôn ghi vào `Assets/` (+ .meta) → không dùng, decode base64 ra file, KHÔNG in base64 vào ngữ
|
|
52
|
+
cảnh, chỉ xem bản thu nhỏ. `source=screen` (Game view + UI overlay) cần editor có cửa sổ (minimize hoặc ẩn vẫn được); batchmode chỉ có
|
|
53
|
+
`source=camera` (mất UI overlay). Editor đứng hình vẫn trả ảnh trông hợp lý → luôn kiểm frameCount trước.
|
|
54
|
+
|
|
55
|
+
## 3. Lập lịch (điều phối viên + planner)
|
|
56
|
+
- Một agent Unity mỗi lane tại một thời điểm. Bắt đầu 2 lane (trunk + b), lên 3 khi RAM/đĩa (mục 7) đạt.
|
|
57
|
+
- Bước lane xong -> **bước integrator** trên trunk (sonnet/high; opus/medium nếu xung đột chạm code). Lane chờ integrator > 1 h hai
|
|
58
|
+
lần -> gộp mỗi 2 bước, hoặc lùi về 2 lane (`unity_lane_2`).
|
|
59
|
+
- Chỉ trên trunk: cổng thiết bị, build Android, đổi schema save, sửa package dùng chung (puzzlecore/casualcore).
|
|
60
|
+
- Integrator đường tắt: trunk HEAD == base merge-forward của lane (lane đã test đúng cây đó) -> compile + EditMode + smoke chính +
|
|
61
|
+
mode của lane (~10-15 phút). Khác -> EditMode + smoke en/vi + các mode ở mục 11 (~25 phút); vòng đầy đủ thứ hai chỉ sau khi sửa.
|
|
62
|
+
|
|
63
|
+
## 4. Một editor mỗi đường dẫn dự án
|
|
64
|
+
- Mọi Bash call của lane: `set -a; . <wt>/.lane.env; set +a` (đặt `UPROJ`, `UNITY_PROJECT_PATH`, `PFF_LANE`, `PFF_SAVE_SANDBOX`,
|
|
65
|
+
`ADB_SERIAL`, `UNITY_LOG`, `TMP`/`TEMP`). Trunk cũng export `UNITY_PROJECT_PATH` (có 2 editor thì tự dò bị mơ hồ).
|
|
66
|
+
- Dự án không có editor mở -> "No Pipeline instance found", không fallback sang editor khác: đúng hành vi, không lách.
|
|
67
|
+
- Trước khi mở editor: kiểm `Temp/UnityLockfile` và process có `-projectPath <đúng đường dẫn>` theo sau là dấu cách (khớp chính xác).
|
|
68
|
+
|
|
69
|
+
## 5. Đóng editor
|
|
70
|
+
- Chỉ đóng PID mình mở, bằng `EditorApplication.Exit(0)`. Cấm `CloseMainWindow()` lên mọi Unity.
|
|
71
|
+
- Script đếm/chờ process phải khớp `-projectPath` chính xác (sự cố 2026-10-11: khớp lỏng `pff-dressmaker` dính cả
|
|
72
|
+
`pff-dressmaker-wt`, script khác đứng chờ và suýt đóng nhầm editor lane).
|
|
73
|
+
- TaskStop không giết vòng bash nền: `ps` + `kill` PID còn sót trước khi chạy lại.
|
|
74
|
+
|
|
75
|
+
## 6. Mở lần đầu
|
|
76
|
+
- Import/compile batchmode trước: `Unity -batchmode -quit -projectPath <wt> -buildTarget <t> -logFile <log>`, rồi mới mở GUI
|
|
77
|
+
(import nguội lane sparse ~5.5 phút; mở lại GUI ~20 s).
|
|
78
|
+
- Seed `Library` bằng robocopy từ trunk chỉ khi editor trunk đóng; đang mở thì import nguội.
|
|
79
|
+
|
|
80
|
+
## 7. Ngưỡng đĩa / RAM
|
|
81
|
+
- Ổ hệ thống (C:) >= 10 GB trước khi mở editor hoặc build; < 8 GB -> đóng lane cuối (c). Lane gần như không tốn C: (đo -0.04 GB)
|
|
82
|
+
khi TMP/TEMP, `-logFile`, Library, worktree nằm trên ổ dữ liệu.
|
|
83
|
+
- **TMP/TEMP của agent và editor phải trỏ sang ổ dữ liệu** (`PFF_TMP`, mục "Nhiều máy"); shell mặc định vẫn dùng Temp trên C:.
|
|
84
|
+
- Ổ dữ liệu còn >= 20 GB sau khi tạo lane (~5 GB/lane sparse: checkout ~1 + art giữ lại ~2 + Library ~2).
|
|
85
|
+
- RAM: đỉnh x1.5 < RAM trống (đo: 2 editor GUI 6 GB WS / 8.4 GB private; 3 editor ~9-10 GB WS; một MuMu +4-6 GB).
|
|
86
|
+
- Agent **không tự dọn C:**; báo người dùng kèm danh sách thủ phạm thường gặp: Docker WSL vhdx (lớn nhất, ~77 GB lúc đo),
|
|
87
|
+
`~/.gradle`, `%TEMP%`, `~/.cache`, npm-cache, cache trình duyệt. Sự cố 2026-10-13: C: 12 -> 3.4 GB không do lane.
|
|
88
|
+
|
|
89
|
+
## 8. Cô lập trong một máy
|
|
90
|
+
- Save: lane editor mặc định dùng sandbox `agent_sandbox/lane_<lane>` (env `PFF_SAVE_SANDBOX`), bỏ qua nút "REAL save" trong
|
|
91
|
+
EditorPrefs; chỉ `PFF_REAL_SAVE=1` trong env của chính lane đó mới trỏ vào save thật.
|
|
92
|
+
- PlayerPrefs: facade `Prefs` thêm tiền tố `lane_<lane>.` khi có `PFF_LANE`; trunk giữ key gốc.
|
|
93
|
+
- EditorPrefs là chung cả máy: đặt Interaction Mode = No Throttling một lần.
|
|
94
|
+
- Play không focus bị đứng hình: hook `AgentPlayMode` bật `Application.runInBackground = true` cho phiên play của agent. Phiên RDP
|
|
95
|
+
ngắt: dùng `EditorApplication.Step` (`ustep`).
|
|
96
|
+
- Kiểm hash save thật trước/sau mỗi chiến dịch test (phải không đổi).
|
|
97
|
+
|
|
98
|
+
## 9. Khoá (trong một máy)
|
|
99
|
+
- `DEVICE_LOCK`: MuMu + build Android, một cái một lúc (`lanes.py device-lock <lane>`, exit 3 = bận, thử lại sau).
|
|
100
|
+
- `MERGE_LOCK`: không commit trunk khi đang merge.
|
|
101
|
+
- `LFS_HOLD`: kiểm trước MỌI commit ở mọi lane (các worktree dùng chung một kho `.git/lfs`).
|
|
102
|
+
- Vị trí: `PFF_LOCK_DIR` (mặc định `<wt_root>/locks`), **không đặt trong run dir** (run dir là nháp của một phiên, một máy).
|
|
103
|
+
|
|
104
|
+
## 10. Commit / merge / push
|
|
105
|
+
- Commit đúng đường dẫn của mình: `git commit -- <paths>`. Lane không commit lên `<main>`, không bao giờ push `lane/*`.
|
|
106
|
+
- Merge-forward `<main>` vào lane ở đầu và cuối mỗi bước.
|
|
107
|
+
- Integrator: trên nhánh cục bộ `integration/<id>`, `git merge --no-ff lane/<x>` (giữ MERGE_LOCK + LFS_HOLD chỉ quanh merge),
|
|
108
|
+
tái sinh asset sinh (LocTable, GameConfig, ...), compile, test. Đỏ -> bỏ nhánh, sửa ở lane bằng editor lane. Xanh -> MERGE_LOCK,
|
|
109
|
+
`git merge --ff-only` vào `<main>`, push thường (theo push policy của game). Kẹt / khoá / LFS: mục 14.
|
|
110
|
+
- File nóng: smoke mode mới = file partial mới; dòng CSV thêm ở cuối; asset sinh không merge tay, luôn tái sinh.
|
|
111
|
+
|
|
112
|
+
## 11. DoD bước lane
|
|
113
|
+
- EditMode tất cả (số test >= trước) + smoke chính (en + vi) + mode của bước + **mọi smoke mode lái màn hình mà bước đổi** (brief
|
|
114
|
+
liệt kê). Chạy trong lane sau merge-forward `<main>` mới nhất.
|
|
115
|
+
- Smoke chờ theo điều kiện (`Until(cond, max)`, ngân sách thời gian thực), không đếm tap/frame cố định (gây 3 lần flake ở pilot).
|
|
116
|
+
|
|
117
|
+
## 12. Rollback
|
|
118
|
+
- Merge phải sửa code ở cả hai miền hai lần -> gộp cặp đó vào một lane.
|
|
119
|
+
- Editor lane crash / lỗi license -> đóng lane, giữ nhánh, cherry-pick sang trunk.
|
|
120
|
+
|
|
121
|
+
## 13. Máy mới (phần dieu-phoi)
|
|
122
|
+
1. `npm i -g @kienntpixon/dieu-phoi`.
|
|
123
|
+
2. Cài `ai-lab/dieu-phoi` từ Skill Hub vào `~/.claude/skills/dieu-phoi` (skill `skill-hub`: install / tải zip).
|
|
124
|
+
3. `dieu-phoi setup --dept ai-lab --sink-url <url> --sink-token <...>`: URL + sink token lấy từ trưởng phòng (password manager /
|
|
125
|
+
nhắn trực tiếp), không ghi vào file nào trong repo hay tài liệu. Khởi động lại Claude Code; `dieu-phoi doctor --net`.
|
|
126
|
+
4. Tạo `~/.pff/machine.env` (mục "Nhiều máy") từ mẫu `tools/templates/machine.env.example` của toolset.
|
|
127
|
+
5. Auto-memory của Claude không theo máy: điều cần biết đã nằm trong file này + `docs/machine-setup.md` của toolset.
|
|
128
|
+
6. Toolchain Fast Forward (Unity, MuMu, git-lfs, Python, gws...): `docs/machine-setup.md` trong repo ai-lab/pixon-fast-forward.
|
|
129
|
+
|
|
130
|
+
## 14. Xử lý kẹt (stuck)
|
|
131
|
+
|
|
132
|
+
Rút từ sự cố thật 2026-10-11..13 (3-4 lane + integrator trên một máy). "Treo" hiếm khi do mạng hay LFS: thường là một hộp thoại
|
|
133
|
+
modal không ai thấy, một khoá bị giữ quá lâu, hoặc một agent chờ thứ không tồn tại. Điều phối viên không tự soi bằng shell (luật
|
|
134
|
+
không tự làm): nhắn agent đang kẹt bằng `SendMessage`, hoặc giao một agent `debug` chạy lệnh soi ở 14.3.
|
|
135
|
+
|
|
136
|
+
### 14.1 Watchdog của điều phối viên (không bao giờ ngồi chờ)
|
|
137
|
+
- Mỗi agent Unity/git đang chạy: hẹn giờ kiểm (Monitor / ScheduleWakeup) mỗi `min(15 phút, ½ budget_s)`. Tín hiệu kẹt: không có
|
|
138
|
+
thông báo tiến độ mới > 15 phút; cùng một trạng thái lặp >= 2 lần ("Waiting.", "merging...", "waiting for MERGE_LOCK"); agent nói
|
|
139
|
+
đang chờ khoá / Unity / thiết bị / push.
|
|
140
|
+
- Bước 1, hỏi trạng thái (`SendMessage`, một câu): "Trả lời <= 3 dòng: đang chờ gì, từ lúc nào, PID / khoá / lệnh nào đang chặn."
|
|
141
|
+
- Bước 2: 10 phút sau vẫn không tiến, hoặc câu trả lời khớp một triệu chứng ở 14.2 -> gửi đúng các dòng brief của triệu chứng đó.
|
|
142
|
+
Cần soi máy (process, khoá, C:) mà agent kẹt không tự làm được -> giao agent `debug` (sonnet/medium, <= 15 phút) chạy 14.3, chỉ
|
|
143
|
+
báo cáo, không kill thứ không phải của mình.
|
|
144
|
+
- Bước 3: vẫn kẹt hoặc quá `budget_s` -> `TaskStop` + `verdict <id> timeout --reason looping|over-budget` (watchdog trong
|
|
145
|
+
`references/verify.md`). Khoá / PID của agent đã dừng: giao agent mới gỡ, kèm danh sách PID / khoá cụ thể.
|
|
146
|
+
- Trong lúc một lane chờ: giao bước không phụ thuộc (không Unity, QIS, docs) hoặc báo người dùng một dòng đang chờ gì, tới khi nào.
|
|
147
|
+
Thông báo "Waiting." lặp của agent nền: không trả lời từng cái, chỉ theo đồng hồ ở trên.
|
|
148
|
+
- Verifier / agent chờ Unity mà dự án không có editor nào chạy (sự cố: ~80 phút im) = kẹt. Brief verifier: "5 phút không thấy editor
|
|
149
|
+
của dự án -> tự mở theo mục 6 (batchmode trước), hoặc báo `BLOCKED` ngay; không chờ."
|
|
150
|
+
|
|
151
|
+
### 14.2 Theo triệu chứng: phát hiện -> dòng brief -> gỡ an toàn
|
|
152
|
+
1. **`git merge` / `git merge-tree` treo 25-40 phút, trông như LFS.** Nguyên nhân thật: merge driver UnityYAMLMerge chạy
|
|
153
|
+
`merge -p` không có `--force` nên không nhận file tạm `.merge_file_*` của git, đi tìm tool GUI dự phòng và mở MessageBox
|
|
154
|
+
"UnityYAMLMerge Error" mà không ai thấy. Không có process git-lfs nào; LFS và credential vẫn khoẻ. `merge-tree` (preview) cũng chạy driver.
|
|
155
|
+
- Phát hiện: process `git` có cây con `sh -> UnityYAMLMerge.exe merge ...`, có cửa sổ tiêu đề "UnityYAMLMerge Error", CPU ~0.
|
|
156
|
+
- Brief: "git chỉ qua `lanes.py git --timeout <s> -- ...`, `lanes.py merge-forward`, `lanes.py push` (bản lanes.py có các lệnh
|
|
157
|
+
này; chưa có thì merge-forward `<main>` trước). git treo -> in cây process con + tiêu đề cửa sổ, không đoán từ dòng log cuối."
|
|
158
|
+
- Gỡ: kill đúng PID git của mình kèm cây con (`taskkill /T /F /PID <pid>`), `git merge --abort`; xoá `.git/index.lock` (hoặc
|
|
159
|
+
lock của worktree) chỉ khi không còn git nào chạy trên worktree đó. Chạy `lanes.py merge-driver` (ghi vào `.git/config` chung,
|
|
160
|
+
phủ mọi worktree: `timeout -k 5 120 UnityYAMLMerge merge -h -p --force`, lỗi thì khôi phục bản ours rồi `git merge-file` ghi
|
|
161
|
+
marker) rồi `lanes.py merge-forward`. Khẩn cấp khi chưa có driver mới: `git -c merge.unityyamlmerge.driver=false merge ...` -> mọi
|
|
162
|
+
file dùng driver thành conflict giữ bản ours, không marker; asset sinh thì tái sinh, còn lại chọn bản rồi `git add`. Không dùng
|
|
163
|
+
`--fallback none` (ghi theirs vào %A, rc 2).
|
|
164
|
+
2. **git-lfs smudge / fetch / push chậm, hoặc push báo "unable to migrate objects to permanent storage".** Nguyên nhân: `git lfs
|
|
165
|
+
checkout` cả cây (~10 phút mỗi lane), `git lfs fetch <ref>` không `--include` (kéo cả ref ~9 GB vào kho trống), nhiều lane tải
|
|
166
|
+
cùng lúc. Lỗi "migrate objects" là lỗi tạm phía GitLab; commit thường đã lên.
|
|
167
|
+
- Brief: "merge với `GIT_LFS_SKIP_SMUDGE=1` (`lanes.py merge-forward` làm sẵn, timeout cứng 900 s), sau đó chỉ kéo file đổi:
|
|
168
|
+
`lanes.py lfs-pull --changed-since <rev>` hoặc `--include <path>`. Cấm `git lfs checkout` / `git lfs fetch` cả cây. Push bằng
|
|
169
|
+
`lanes.py push` (tự thử lại lỗi migrate / 5xx / timeout, coi là xong nếu origin đã có HEAD)."
|
|
170
|
+
- Gỡ: trước khi push lại, `git fetch` rồi `git branch -r --contains HEAD`: đã có thì thôi. Thao tác mạng chạy tuần tự qua
|
|
171
|
+
`GIT_NET_LOCK` trong `PFF_LOCK_DIR` (giữ trong một thao tác; PID chết hoặc > 45 phút = cũ, được lấy lại).
|
|
172
|
+
3. **MERGE_LOCK / LFS_HOLD bị giữ hàng giờ, nhiều agent xếp hàng** (sự cố: integrator giữ ~1.5 h trong lúc test, 4 agent chờ, một
|
|
173
|
+
agent chờ ~95 phút).
|
|
174
|
+
- Phát hiện: `lanes.py locks` (holder + tuổi khoá). Khoá > 30 phút là bất thường.
|
|
175
|
+
- Brief integrator: "MERGE_LOCK / LFS_HOLD chỉ giữ quanh merge, commit, fast-forward, push (tính bằng phút). Test chạy trên
|
|
176
|
+
`integration/<id>` không giữ khoá."
|
|
177
|
+
- Brief người chờ: "khoá bận -> làm phần không commit trước, kiểm lại mỗi 5 phút, quá 30 phút báo
|
|
178
|
+
`STATUS: partial — waiting-lock <holder>`. Không xoá khoá của người khác."
|
|
179
|
+
- Gỡ: holder còn sống -> nhắn holder nhả khoá giữa các lượt test. Holder đã chết (agent đã dừng, PID không còn) -> giao agent
|
|
180
|
+
`lanes.py unlock` kèm tên holder (hỏi người dùng nếu holder là phiên khác).
|
|
181
|
+
4. **Merge cục bộ của integrator bị push lên origin theo push của agent khác; agent commit nhầm lên nhánh integration.**
|
|
182
|
+
- Integrator merge trên nhánh cục bộ `integration/<id>`; xanh mới lấy MERGE_LOCK, `git merge --ff-only` vào `<main>`, push. Đỏ ->
|
|
183
|
+
bỏ nhánh (`<main>` chưa bao giờ chứa merge chưa test).
|
|
184
|
+
- Trunk đang checkout `integration/<id>` -> agent khác không commit trong checkout trunk (commit rơi vào nhánh integration): commit
|
|
185
|
+
ArtIncoming / docs từ worktree tạm (`git worktree add <wt_root>/tmp/<task_id> <main>`), hoặc chờ trunk về `<main>`.
|
|
186
|
+
- Mọi commit / push trên trunk tôn trọng MERGE_LOCK. Trước commit: `git branch --show-current` phải đúng nhánh brief ghi.
|
|
187
|
+
- Gỡ: commit lỡ trên nhánh sai -> cherry-pick sang đúng nhánh; đã push thì sửa bằng commit mới (revert), không force.
|
|
188
|
+
5. **Script nháp đè nhau, đóng editor của lane khác.** Các agent song song dùng chung scratchpad của phiên; runner cùng tên
|
|
189
|
+
(`smokes.sh`) ghi đè nhau và đóng editor lane khác.
|
|
190
|
+
- Brief: "script / file tạm / log của bạn chỉ nằm trong `<wt_root>/tmp/<lane>/<task_id>/`; không đặt runner trong scratchpad của
|
|
191
|
+
phiên; script chỉ đụng editor có `-projectPath` đúng của bạn (mục 4-5)."
|
|
192
|
+
6. **C: tụt dưới ngưỡng giữa chừng** (12 -> 3.4 GB không do lane; một integrator tự xoá npx cache, log Claude, temp của VS: vi phạm).
|
|
193
|
+
- Phát hiện: `lanes.py paths` (C: free) hoặc `Get-PSDrive C`.
|
|
194
|
+
- Brief: "Không bao giờ xoá gì ngoài repo / worktree / tmp lane của bạn. C: < 10 GB -> dừng ở điểm an toàn, báo
|
|
195
|
+
`STATUS: partial — disk-low <GB>`; không tự dọn."
|
|
196
|
+
- Gỡ: điều phối viên báo người dùng kèm danh sách thủ phạm ở mục 7; < 8 GB đóng lane cuối.
|
|
197
|
+
7. **Unity Safe Mode / hộp thoại modal chặn editor hoặc batchmode** ("Enter Safe Mode?" khi mở dự án đang lỗi compile; hộp thoại
|
|
198
|
+
import / nâng cấp / khoá dự án).
|
|
199
|
+
- Phát hiện: process Unity đúng `-projectPath`, log đứng, có cửa sổ tiêu đề hộp thoại (14.3).
|
|
200
|
+
- Brief: "compile batchmode (`-batchmode -quit -logFile <log>`, có timeout cứng) trước khi mở GUI; có `error CS` thì sửa trước;
|
|
201
|
+
gặp hộp thoại Safe Mode: không vào Safe Mode, đóng editor của bạn và sửa lỗi compile."
|
|
202
|
+
- Gỡ: editor của mình kẹt hộp thoại, không nhận `EditorApplication.Exit(0)` -> `Stop-Process -Id <PID mình mở>` (chỉ PID đó;
|
|
203
|
+
mục 5 vẫn cấm `CloseMainWindow()` lên mọi Unity), xoá `Temp/UnityLockfile` của đúng dự án đó, compile batchmode lại.
|
|
204
|
+
8. **adb / MuMu chết, touch kẹt** (adb server :5037 chết liên tục, adb.exe của Unity SDK crash 0xc0000409, thiết bị offline).
|
|
205
|
+
- Brief: "một adb duy nhất (`ADB_SERIAL`, luôn cùng một adb.exe), giữ DEVICE_LOCK. adb offline -> `adb kill-server`, rồi
|
|
206
|
+
`MuMuManager control -v <index> restart` (giữ dữ liệu), đọc lại cổng bằng `MuMuManager info -i <index>` (cổng có thể đổi).
|
|
207
|
+
Touch kẹt -> gửi lại sự kiện nhả / back, không được thì khởi động lại app. Trước QA thiết bị: sao lưu save của app
|
|
208
|
+
(`adb shell run-as <pkg>` / backup), khôi phục sau (MuMu đang chơi save thật của người dùng)."
|
|
209
|
+
9. **Smoke flake ở tap đầu khi nhiều editor chạy.** Brief: "trước tap đầu chờ theo điều kiện <= 30 s (`Until`), không đếm frame;
|
|
210
|
+
flake 1 lần -> chạy lại đúng một lần, lặp lại -> báo, không vòng thử."
|
|
211
|
+
10. **GitLab bảo trì (không push được).** Phát hiện: push 5xx / 503 / trang maintenance. Brief: "commit cục bộ, ghi
|
|
212
|
+
`PUSH PENDING (GitLab maintenance)` trong báo cáo; tối đa 3 lần với back-off, không thử dồn dập." Điều phối viên đánh dấu bước
|
|
213
|
+
"chờ push", không chặn bước khác; GitLab về thì giao agent `lanes.py push`.
|
|
214
|
+
|
|
215
|
+
### 14.3 Lệnh soi (agent `debug` chạy, điều phối viên không chạy)
|
|
216
|
+
```powershell
|
|
217
|
+
# Unity của đúng một dự án (khớp -projectPath chính xác, mục 4)
|
|
218
|
+
Get-CimInstance Win32_Process -Filter "Name='Unity.exe'" | ? { $_.CommandLine -like '*-projectPath <path> *' -or $_.CommandLine -like '*-projectPath "<path>"*' } | select ProcessId,CreationDate
|
|
219
|
+
# cây con của một git treo (lặp với từng PID con) + cửa sổ có tiêu đề
|
|
220
|
+
Get-CimInstance Win32_Process -Filter "ParentProcessId=<pid>" | select ProcessId,Name,CommandLine
|
|
221
|
+
Get-Process | ? MainWindowTitle | select Id,ProcessName,MainWindowTitle
|
|
222
|
+
```
|
|
223
|
+
Kèm `lanes.py locks` (holder, tuổi khoá) và `lanes.py paths` (C: free). `lanes.py git --timeout` tự in cây process và tiêu đề cửa
|
|
224
|
+
sổ khi hết giờ, rồi kill cây đó và xoá index.lock nó để lại.
|
|
225
|
+
|
|
226
|
+
### 14.4 Phòng ngừa: dòng bắt buộc trong mọi brief bước Unity / git
|
|
227
|
+
- `set -a; . <wt>/.lane.env; set +a`; `lanes.py env` đã xuất `GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never GIT_MERGE_AUTOEDIT=no
|
|
228
|
+
GIT_EDITOR=true`. Không có `.lane.env` thì tự export 4 biến đó.
|
|
229
|
+
- Không lệnh git / lfs / Unity / adb nào chạy không có trần thời gian (`lanes.py git --timeout`, `timeout`, `-batchmode -quit`).
|
|
230
|
+
- Script và file tạm trong `<wt_root>/tmp/<lane>/<task_id>/`. Không xoá gì ngoài repo / worktree / tmp của mình; C: < 10 GB -> dừng, báo.
|
|
231
|
+
- Integrator merge trên `integration/<id>`, ff `<main>` sau khi xanh; khoá chỉ quanh merge / commit / push.
|
|
232
|
+
- Trước commit: `git branch --show-current` đúng nhánh; `git commit -- <paths>`.
|
|
233
|
+
- Chỉ kill PID mình mở và git con của mình.
|
|
234
|
+
- QA thiết bị: sao lưu save app trước, khôi phục sau.
|
|
235
|
+
- Chờ bất cứ thứ gì (khoá, Unity, thiết bị, push): tối đa 30 phút rồi báo `STATUS: partial — waiting-<thứ>`, không chờ im.
|
|
236
|
+
|
|
237
|
+
## Nhiều máy
|
|
238
|
+
|
|
239
|
+
Fast Forward + dieu-phoi (cùng profile ai-lab) chạy trên nhiều máy cùng lúc. Nguyên tắc: thứ máy khác phải thấy đi qua **git
|
|
240
|
+
(GitLab)** hoặc **Skill Hub**, không bao giờ qua thư mục cục bộ (run dir, memory, `~/.claude`). File chung: hoặc mỗi file một người
|
|
241
|
+
ghi (file theo máy), hoặc merge bằng `git merge` thường. Không force push, không rebase commit đã push.
|
|
242
|
+
|
|
243
|
+
### Cấu hình theo máy: `~/.pff/machine.env`
|
|
244
|
+
Ngoài mọi repo; lanes.py, wrapper `tools/bin` và brief agent đều source file này. Mẫu chỉ có placeholder.
|
|
245
|
+
|
|
246
|
+
| biến | mặc định khi trống | dùng cho |
|
|
247
|
+
|---|---|---|
|
|
248
|
+
| `PFF_MACHINE` | hostname (chữ thường) | inbox bài học, tên nhánh, tag job, tên APK |
|
|
249
|
+
| `PFF_DATA_ROOT` | ổ dữ liệu nếu có (vd. `D:/`), không thì `~` | gốc của các biến dưới |
|
|
250
|
+
| `PFF_WT_ROOT` | `<project>-wt` cạnh project | worktree lane |
|
|
251
|
+
| `PFF_LOCK_DIR` | `<PFF_WT_ROOT>/locks` | DEVICE_LOCK, MERGE_LOCK, LFS_HOLD |
|
|
252
|
+
| `PFF_TMP` | `<PFF_DATA_ROOT>/pff-tmp` | TMP/TEMP của agent và editor, file kết quả `ujob` |
|
|
253
|
+
| `PFF_UNITY_HUB_EDITORS` | thư mục Editor của Unity Hub | Unity theo `ProjectSettings/ProjectVersion.txt` |
|
|
254
|
+
| `UNITY_CLI` | `unity.exe` của Unity CLI trong LocalAppData | `tools/bin` |
|
|
255
|
+
| `ADB_SERIAL`, `PFF_MUMU_INDEX` | từ `MuMuManager info -i <index>` | device QA, adbshot, lanes |
|
|
256
|
+
| `DIEU_PHOI_RUNS_DIR` | `~/.dieu-phoi/runs` | dieu-phoi CLI |
|
|
257
|
+
| `QIS_MAX_INFLIGHT`, `ATLAS_MAX_INFLIGHT` | 2 | job đồng thời của máy này |
|
|
258
|
+
|
|
259
|
+
Run dir là nháp của một máy: contract/báo cáo mà máy khác cần phải chép vào repo game (`Docs/` hoặc `Reports/`) trước khi bước kết thúc.
|
|
260
|
+
|
|
261
|
+
### Máy maintainer
|
|
262
|
+
- **Một** máy publish lên Skill Hub. Mặc định: máy chính của người dùng (ví dụ, máy này lúc viết: `desktop-l730gt6`); đổi máy thì
|
|
263
|
+
sửa dòng này và báo cả phòng.
|
|
264
|
+
- Publish chỉ từ HEAD của `main` trên GitLab, luôn tăng version; Hub từ chối version trùng, nên hai máy publish chồng nhau sẽ lộ ra.
|
|
265
|
+
- Máy khác không publish: chỉ push file inbox bài học.
|
|
266
|
+
|
|
267
|
+
### Bài học trên nhiều máy
|
|
268
|
+
- `profile/lessons.md` publish = danh sách đã tuyển (nguồn duy nhất, trong repo nguồn ai-lab/dieu-phoi).
|
|
269
|
+
- Dòng ghi `>>` trên một máy chỉ ở máy đó. `tools/lessons_sync.cjs harvest` chép dòng chỉ-có-ở-máy vào `lessons-inbox/<PFF_MACHINE>.md`
|
|
270
|
+
(gốc repo, ngoài `skill/`), commit + `git pull --no-rebase` + push thường. Mỗi máy một file inbox -> không xung đột.
|
|
271
|
+
- Máy vừa cài từ Hub chưa có `profile/.lessons.published.md`: lần chạy đầu của `lessons_sync` (`status` / `harvest` / `update`) tự
|
|
272
|
+
tạo nó từ `lessons.md` đã cài (mọi dòng coi là đã publish). Chạy `lessons_sync status` ngay sau khi cài, trước khi `>>` bài học mới.
|
|
273
|
+
- `lessons_sync update`: harvest -> tải bản Hub mới -> thay skill -> nối lại cuối file các dòng cục bộ chưa vào bản tuyển ->
|
|
274
|
+
`dieu-phoi setup` -> `dieu-phoi doctor`. Không cài đè skill bằng tay (mất dòng cục bộ).
|
|
275
|
+
- Retro trên máy maintainer: đọc `lessons-inbox/*.md`, gộp vào `skill/profile/lessons.md`, chuyển dòng đã gộp sang
|
|
276
|
+
`lessons-inbox/merged/<date>.md`, commit, publish version mới.
|
|
277
|
+
|
|
278
|
+
### Sink chung
|
|
279
|
+
Mọi máy dùng cùng sink của phòng (setup ở mục 13). Sink chỉ nhận event (metrics + nhãn), không nhận bài học hay profile.
|
|
280
|
+
`choose` / `stats` đọc event cục bộ, nên máy mới bắt đầu từ prior cho tới khi có dữ liệu riêng: chấp nhận.
|
|
281
|
+
|
|
282
|
+
### Chia việc giữa các máy
|
|
283
|
+
- Như lanes, một tầng trên: kế hoạch đã duyệt gán cho mỗi bước Unity một `machine` (và `unity_lane` trong máy đó). Một miền không ở
|
|
284
|
+
hai máy cùng lúc. Kế hoạch nằm trong repo game (`Docs/plan/assignments.json`), không trong run dir.
|
|
285
|
+
- Khoá (mục 9) chỉ có hiệu lực trong một máy (mỗi máy có clone, kho `.git/lfs`, emulator riêng). Phối hợp giữa máy = git.
|
|
286
|
+
|
|
287
|
+
### Claim trước khi làm
|
|
288
|
+
- `Docs/plan/claims.md` trong repo game, mỗi bước một dòng: `<step> <machine> <utc> <branch>`.
|
|
289
|
+
- Commit claim rồi push. Push bị từ chối non-fast-forward = máy khác push trước -> fetch + merge + kiểm lại claim; **claim push trước
|
|
290
|
+
thắng**. git push là khoá nguyên tử, không cần server thêm.
|
|
291
|
+
- `.gitattributes` của repo game có `Docs/plan/claims.md merge=union`: hai máy claim bước khác nhau thì merge giữ cả hai dòng,
|
|
292
|
+
không xung đột. Trùng **cùng một bước**: dòng đã có trong origin (push sớm nhất) thắng; máy thua xoá dòng của mình, push, rồi
|
|
293
|
+
lập lại kế hoạch sang bước khác. Không xoá dòng của máy khác.
|
|
294
|
+
|
|
295
|
+
### Nhánh và push
|
|
296
|
+
- `<main>` = việc đã tích hợp. Mỗi máy tích hợp trên trunk của mình và tự push `<main>` sau khi xanh (không có máy integrator duy nhất).
|
|
297
|
+
- `lane/*` chỉ ở máy, không bao giờ push. Được push `m/<machine>/<topic>` để sao lưu/bàn giao; xoá sau khi merge.
|
|
298
|
+
- Giao thức push (mọi máy): `git fetch` -> `git merge --no-ff origin/<main>` vào trunk (mặc định `git pull --no-rebase`; chỉ rebase
|
|
299
|
+
commit cục bộ chưa push) -> tái sinh asset sinh -> kiểm ngắn (compile + EditMode + smoke chính + mode bước chạm) -> `git push`
|
|
300
|
+
thường. Non-fast-forward -> lặp lại, tối đa 3 lần rồi hỏi người dùng. Cấm `--force` / `--force-with-lease` trên nhánh chung.
|
|
301
|
+
Chỉ push việc đã kiểm (push policy của game).
|
|
302
|
+
- Binary/YAML không merge được (`*.png`, `*.psd`, `*.unity`, `*.prefab` ở thư mục chung): ưu tiên chia miền; chỉ khi hai máy buộc
|
|
303
|
+
phải sửa cùng file mới `git lfs lock <path>` và nhả trong cùng bước. **Không** đặt thuộc tính `lockable` (làm mọi file LFS chỉ-đọc,
|
|
304
|
+
hỏng tool của agent).
|
|
305
|
+
|
|
306
|
+
### QIS / Atlas dùng chung
|
|
307
|
+
- Danh sách job + trạng thái nằm trong repo game (mỗi job một dòng, `status` = todo / claimed:<machine> / done); claim như trên.
|
|
308
|
+
- Mặc định **2 job đồng thời mỗi máy** (`QIS_MAX_INFLIGHT`, `ATLAS_MAX_INFLIGHT`) cho tới khi chủ hub cho số thật.
|
|
309
|
+
- Tag job / tên file ra có tiền tố `<machine>`. Gặp 429 / hết quota: back-off luỹ thừa (30 s -> 10 phút), rồi
|
|
310
|
+
`STATUS: partial — quota-pause`; không vòng thử lại dồn dập.
|
|
311
|
+
- Credential mỗi máy trong `<toolset>/.env` (gitignore), nhận ngoài luồng; script đọc trong process, không bao giờ in ra.
|
|
312
|
+
|
|
313
|
+
### Emulator / thiết bị
|
|
314
|
+
- **Mỗi máy một emulator** (MuMu riêng: `PFF_MUMU_INDEX` + `ADB_SERIAL` trong `machine.env`), DEVICE_LOCK cục bộ.
|
|
315
|
+
- Cổng thiết bị của milestone chạy trên máy đã tích hợp build milestone đó. Tên APK `<game>-<commit>-<machine>.apk` (upload Drive
|
|
316
|
+
theo policy của game). Điện thoại thật dùng chung cần người cầm: không tự động.
|