@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
package/lib/worktree.cjs
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// s17 (core 0.7.2): worktree của một bước điều phối, có dấu dieu-phoi.
|
|
3
|
+
// - `wt add` tạo `<cha của repo>/<tên repo>-wt-<task_id>` trên nhánh dp/<task_id> và ghi dấu
|
|
4
|
+
// `<git-dir của worktree>/dieu-phoi.json` {task_id, root, created_ts, branch}. Dấu nằm trong git-dir nên không làm
|
|
5
|
+
// worktree dirty.
|
|
6
|
+
// - verdict --task accept (người dùng) và discard chỉ gỡ worktree CÓ DẤU của đúng task: sạch thì
|
|
7
|
+
// `git worktree remove` (không --force), nhánh giữ nguyên; còn thay đổi chưa commit thì giữ và báo.
|
|
8
|
+
// Worktree không dấu không bị đụng.
|
|
9
|
+
// - `wt clean` (dry-run mặc định) liệt kê worktree có dấu mà task đã nghiệm thu / bị loại, hoặc thư mục đã mất.
|
|
10
|
+
// Sự kiện `worktree` (chỉ ở máy, không đồng bộ sink) ghi repo chính để verdict/discard tìm đúng repo.
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const cp = require('child_process');
|
|
14
|
+
const core = require('../hook.cjs');
|
|
15
|
+
const agg = require('./aggregate.cjs');
|
|
16
|
+
const { ctxOf, repoOf } = require('./args.cjs');
|
|
17
|
+
|
|
18
|
+
const MARK = 'dieu-phoi.json';
|
|
19
|
+
const BRANCH_PREFIX = 'dp/';
|
|
20
|
+
|
|
21
|
+
function git(cwd, args) {
|
|
22
|
+
const r = cp.spawnSync('git', args, { cwd, encoding: 'utf8', windowsHide: true, timeout: 60000 });
|
|
23
|
+
const err = r.stderr || (r.error ? r.error.message : '') || '';
|
|
24
|
+
return { ok: r.status === 0, out: (r.stdout || '').trim(), err: err.trim() };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function requireTaskId(id) {
|
|
28
|
+
if (!core.isValidTaskId(id)) throw new Error(core.taskIdError(id));
|
|
29
|
+
return id;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Checkout chính của repo (thư mục có .git) từ một đường dẫn bất kỳ trong repo hoặc worktree của nó. */
|
|
33
|
+
function mainCheckoutOf(dir) {
|
|
34
|
+
const r = git(dir, ['rev-parse', '--path-format=absolute', '--git-common-dir']);
|
|
35
|
+
if (!r.ok) throw new Error(`không phải repo git: ${dir}${r.err ? ` (${r.err})` : ''}`);
|
|
36
|
+
if (path.basename(r.out) !== '.git') throw new Error(`repo không có thư mục .git (${r.out}); wt chỉ làm việc với checkout thường`);
|
|
37
|
+
return { main: path.dirname(r.out), common: r.out };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Worktree có dấu của repo (đọc <common>/worktrees/<name>/dieu-phoi.json). Không ném. */
|
|
41
|
+
function markedWorktrees(common) {
|
|
42
|
+
const dir = path.join(common, 'worktrees');
|
|
43
|
+
let names = [];
|
|
44
|
+
try { names = fs.readdirSync(dir); } catch (_) { return []; }
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const name of names) {
|
|
47
|
+
const admin = path.join(dir, name);
|
|
48
|
+
const mark = core.readJsonFile(path.join(admin, MARK), null);
|
|
49
|
+
if (!mark || typeof mark.task_id !== 'string') continue;
|
|
50
|
+
let wtPath = null;
|
|
51
|
+
try { wtPath = path.dirname(fs.readFileSync(path.join(admin, 'gitdir'), 'utf8').trim()); } catch (_) { /* no gitdir: stale admin */ }
|
|
52
|
+
out.push({
|
|
53
|
+
admin, name, task_id: mark.task_id, root: mark.root || null, branch: mark.branch || null,
|
|
54
|
+
created_ts: mark.created_ts || null, path: wtPath, exists: !!wtPath && fs.existsSync(wtPath),
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** true = còn thay đổi (kể cả file chưa theo dõi), false = sạch, null = không đọc được. */
|
|
61
|
+
function dirtyOf(wtPath) {
|
|
62
|
+
const r = git(wtPath, ['status', '--porcelain']);
|
|
63
|
+
if (!r.ok) return null;
|
|
64
|
+
return r.out.length > 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Gỡ một worktree có dấu đang còn thư mục. Không --force: còn thay đổi thì giữ. */
|
|
68
|
+
function removeMarked(w, mainDir) {
|
|
69
|
+
const dirty = dirtyOf(w.path);
|
|
70
|
+
if (dirty !== false) return { removed: false, msg: `giữ ${w.path}: ${dirty ? 'còn thay đổi chưa commit' : 'không đọc được trạng thái git'}` };
|
|
71
|
+
const r = git(mainDir, ['worktree', 'remove', w.path]);
|
|
72
|
+
if (!r.ok) return { removed: false, msg: `giữ ${w.path}: git worktree remove lỗi (${r.err || 'không rõ'})` };
|
|
73
|
+
return { removed: true, msg: `đã gỡ worktree ${w.path} (nhánh ${w.branch || '?'} giữ nguyên)` };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function recordWt(ctx, taskId, fields) {
|
|
77
|
+
try {
|
|
78
|
+
core.appendEvent(ctx, Object.assign({
|
|
79
|
+
schema: core.SCHEMA, kind: 'worktree', ts: core.nowIso(), agent_id: `wt:${taskId}`, task_id: taskId,
|
|
80
|
+
}, fields, core.commonFields(ctx)));
|
|
81
|
+
} catch (_) { /* best effort: the worktree itself is the truth */ }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Các repo chính mà task đã có worktree (sự kiện `worktree` action=add), kèm repo người dùng chỉ định nếu có. */
|
|
85
|
+
function reposOfTask(events, taskId, repoDir) {
|
|
86
|
+
const set = new Set();
|
|
87
|
+
for (const e of events) {
|
|
88
|
+
if (e && e.kind === 'worktree' && e.task_id === taskId && e.action === 'add' && typeof e.repo === 'string') set.add(e.repo);
|
|
89
|
+
}
|
|
90
|
+
if (typeof repoDir === 'string' && repoDir) set.add(repoDir);
|
|
91
|
+
return Array.from(set);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* verdict --task accept (người dùng) / discard: gỡ worktree có dấu của đúng task. Trả các dòng báo, không ném.
|
|
96
|
+
* repoDir: --repo của lệnh (nếu có) — ngoài repo đã ghi trong sự kiện worktree.
|
|
97
|
+
*/
|
|
98
|
+
function cleanupTask(ctx, events, taskId, repoDir) {
|
|
99
|
+
const lines = [];
|
|
100
|
+
for (const repo of reposOfTask(events, taskId, repoDir)) {
|
|
101
|
+
let info;
|
|
102
|
+
try { info = mainCheckoutOf(repo); } catch (e) { lines.push(`wt: bỏ qua ${repo} (${e.message})`); continue; }
|
|
103
|
+
const mine = markedWorktrees(info.common).filter((w) => w.task_id === taskId);
|
|
104
|
+
for (const w of mine) {
|
|
105
|
+
if (!w.exists) { lines.push(`wt: ${w.path || w.name} đã mất thư mục — dọn bằng dieu-phoi wt clean --yes`); continue; }
|
|
106
|
+
const r = removeMarked(w, info.main);
|
|
107
|
+
if (r.removed) recordWt(ctx, taskId, { action: 'remove', path: w.path, repo: info.main, reason: 'verdict' });
|
|
108
|
+
lines.push(`wt: ${r.msg}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return lines;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function wtAdd(opts) {
|
|
115
|
+
if (typeof opts.task !== 'string') throw new Error('Cú pháp: dieu-phoi wt add --task <task_id> [--repo r] [--path dir] [--branch b]');
|
|
116
|
+
const taskId = requireTaskId(opts.task);
|
|
117
|
+
const ctx = ctxOf(opts);
|
|
118
|
+
const { main, common } = mainCheckoutOf(repoOf(opts));
|
|
119
|
+
const dup = markedWorktrees(common).filter((w) => w.task_id === taskId && w.exists);
|
|
120
|
+
if (dup.length) throw new Error(`task ${taskId} đã có worktree có dấu: ${dup.map((w) => w.path).join(', ')}`);
|
|
121
|
+
const wtPath = typeof opts.path === 'string' && opts.path
|
|
122
|
+
? path.resolve(opts.path)
|
|
123
|
+
: path.join(path.dirname(main), `${path.basename(main)}-wt-${taskId}`);
|
|
124
|
+
if (fs.existsSync(wtPath)) throw new Error(`wt add: ${wtPath} đã tồn tại`);
|
|
125
|
+
const branch = typeof opts.branch === 'string' && opts.branch ? opts.branch : `${BRANCH_PREFIX}${taskId}`;
|
|
126
|
+
const r = git(main, ['worktree', 'add', '-b', branch, wtPath]);
|
|
127
|
+
if (!r.ok) throw new Error(`git worktree add lỗi: ${r.err || 'không rõ'}`);
|
|
128
|
+
const adminDir = git(wtPath, ['rev-parse', '--path-format=absolute', '--git-dir']).out;
|
|
129
|
+
if (!adminDir) throw new Error(`worktree ${wtPath} tạo xong nhưng không đọc được git-dir để ghi dấu`);
|
|
130
|
+
const mark = { task_id: taskId, root: main, created_ts: core.nowIso(), branch };
|
|
131
|
+
fs.writeFileSync(path.join(adminDir, MARK), `${JSON.stringify(mark, null, 2)}\n`);
|
|
132
|
+
recordWt(ctx, taskId, { action: 'add', path: wtPath, repo: main, branch });
|
|
133
|
+
const msg = `Đã tạo worktree ${wtPath} trên nhánh ${branch} (dấu dieu-phoi: task ${taskId}). Brief dùng dòng "worktree: ${wtPath}".`;
|
|
134
|
+
return { code: 0, out: opts.json ? JSON.stringify({ task_id: taskId, path: wtPath, branch }) : msg };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function wtClean(opts) {
|
|
138
|
+
const ctx = ctxOf(opts);
|
|
139
|
+
const { main, common } = mainCheckoutOf(repoOf(opts));
|
|
140
|
+
const events = core.readEvents(ctx);
|
|
141
|
+
const accepted = new Set(events.filter((e) => e && e.kind === 'verdict' && agg.normalizeVerdict(e).by === 'user' && e.outcome === 'accept')
|
|
142
|
+
.map((e) => e.task_id));
|
|
143
|
+
const gone = agg.discardedTaskIds(events);
|
|
144
|
+
const rows = [];
|
|
145
|
+
for (const w of markedWorktrees(common)) {
|
|
146
|
+
let why = null;
|
|
147
|
+
if (!w.exists) why = 'thư mục đã mất';
|
|
148
|
+
else if (accepted.has(w.task_id)) why = 'đã nghiệm thu';
|
|
149
|
+
else if (gone.has(w.task_id)) why = 'đã loại (discard)';
|
|
150
|
+
if (why) rows.push(Object.assign({}, w, { why }));
|
|
151
|
+
}
|
|
152
|
+
if (!rows.length) return { code: 0, out: 'wt clean: không có worktree có dấu nào cần dọn.' };
|
|
153
|
+
const apply = opts.yes === true;
|
|
154
|
+
const lines = [];
|
|
155
|
+
for (const w of rows) {
|
|
156
|
+
const label = `task=${w.task_id} nhánh=${w.branch || '?'} (${w.why})`;
|
|
157
|
+
if (!w.exists) {
|
|
158
|
+
// Thư mục đã mất: chỉ bỏ thư mục đăng ký của chính worktree có dấu này (git-dir), không đụng thư mục khác.
|
|
159
|
+
if (apply && path.dirname(w.admin) === path.join(common, 'worktrees')) {
|
|
160
|
+
fs.rmSync(w.admin, { recursive: true, force: true, maxRetries: 3 });
|
|
161
|
+
recordWt(ctx, w.task_id, { action: 'remove', path: w.path, repo: main, reason: 'missing' });
|
|
162
|
+
lines.push(`đã bỏ đăng ký ${w.path || w.name}: ${label}`);
|
|
163
|
+
} else lines.push(`sẽ bỏ đăng ký ${w.path || w.name}: ${label}`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
const dirty = dirtyOf(w.path);
|
|
167
|
+
if (dirty !== false) { lines.push(`giữ ${w.path}: ${dirty ? 'còn thay đổi chưa commit' : 'không đọc được trạng thái git'} — ${label}`); continue; }
|
|
168
|
+
if (!apply) { lines.push(`sẽ gỡ ${w.path}: ${label}`); continue; }
|
|
169
|
+
const r = removeMarked(w, main);
|
|
170
|
+
if (r.removed) recordWt(ctx, w.task_id, { action: 'remove', path: w.path, repo: main, reason: w.why });
|
|
171
|
+
lines.push(`${r.msg}: ${label}`);
|
|
172
|
+
}
|
|
173
|
+
const tail = apply ? '' : '\nDry-run: chưa xoá gì. Chạy lại với --yes để thực hiện.';
|
|
174
|
+
return { code: 0, out: `wt clean (${apply ? 'đã thực hiện' : 'dry-run'}):\n${lines.join('\n')}${tail}` };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** `dieu-phoi wt add|clean` (core 0.7.2 s17). */
|
|
178
|
+
function cmdWt(opts) {
|
|
179
|
+
const sub = opts._[0];
|
|
180
|
+
if (sub === 'add') return wtAdd(opts);
|
|
181
|
+
if (sub === 'clean') return wtClean(opts);
|
|
182
|
+
throw new Error('Cú pháp: dieu-phoi wt add --task <task_id> [--repo r] [--path dir] [--branch b]\n'
|
|
183
|
+
+ ' dieu-phoi wt clean [--repo r] [--yes]');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports = { cmdWt, cleanupTask, mainCheckoutOf, markedWorktrees, MARK };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kienntpixon/dieu-phoi",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Hook + CLI ghi log subagent của Claude Code và chọn model/effort theo chi phí + thời gian tới lúc nghiệm thu.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "kiennt <kiennt@pixon.games>",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"bin/",
|
|
23
23
|
"agents/",
|
|
24
24
|
"lib/",
|
|
25
|
+
"profile/",
|
|
25
26
|
"hook.cjs",
|
|
26
27
|
"pricing.json",
|
|
27
28
|
"README.md",
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
"node": ">=18"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
36
|
+
"prepack": "node scripts/pack-profile.cjs",
|
|
35
37
|
"test": "node --test"
|
|
36
38
|
},
|
|
37
39
|
"keywords": [
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Bài học điều phối — phòng ai-lab
|
|
2
|
+
|
|
3
|
+
Một dòng mỗi bài học, ghi sau mỗi lần fail hoặc người dùng phải sửa lại. Brief cho lần sau chèn các dòng khớp `task_type` / tag. Retro gộp dòng trùng và xoá dòng lỗi thời.
|
|
4
|
+
|
|
5
|
+
Định dạng:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
- [YYYY-MM-DD] <task_type> | <model>/<effort> | <tag tự do, vd. repo/miền> — <điều đã sai> → <cách tránh trong brief/kiểm tra>
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Ví dụ: `- [2026-10-09] feature-impl | sonnet/high | isle — quên chạy migration → thêm "chạy migration + test trên DB test" vào tiêu chí nghiệm thu`
|
|
12
|
+
|
|
13
|
+
Không ghi nội dung prompt, dữ liệu khách hàng, secrets, đường dẫn tuyệt đối.
|
|
14
|
+
|
|
15
|
+
Bài học viết cho **điều phối viên** đặt `[orch]` ở chỗ `<task_type>` (vd. `- [2026-10-12] [orch] | * | verdict — …`): điều phối viên không đọc file này, CLI (≥ 0.4.0) hiện 5 dòng `[orch]` cuối trong khối khởi động / `dieu-phoi start`. Các dòng khác do agent tự lọc theo `task_type`.
|
|
16
|
+
|
|
17
|
+
Nhiều máy: file trong skill đã publish là bản đã duyệt (một nguồn duy nhất, sửa ở repo nguồn). Dòng ghi `>>` trên một máy chỉ ở máy đó; khi cài hoặc cập nhật skill, `profile/.lessons.published.md` giữ nguyên bản đã publish mà máy đang dùng, để `tools/lessons_sync.cjs` (`harvest`) biết dòng nào là của riêng máy (so sánh văn bản đã chuẩn hoá) và đẩy vào `lessons-inbox/<máy>.md` trong repo nguồn (ngoài `skill/`, không lên Hub). Retro gộp inbox vào file này; dòng đã gộp tự biến khỏi tập dòng riêng của máy.
|
|
18
|
+
|
|
19
|
+
## Câu hỏi cổng 1
|
|
20
|
+
|
|
21
|
+
Câu hỏi bắt buộc hỏi ở cổng 1 cho từng loại task (retro thêm khi tỉ lệ steer cao). Định dạng: `- <task_type>: <câu hỏi>`
|
|
22
|
+
|
|
23
|
+
- *: (chỉ khi kế hoạch có ≥ 4 bước s≤6) Chọn mode? fast (bước s≤6 không verifier riêng, test chọn lọc, một verifier gộp chạy cả suite trước khi trình, tự nghiệm thu rồi bạn duyệt cuối) | normal (mặc định) | strict (luôn cả suite + kiểm ngẫu nhiên 1/3). Kế hoạch nhỏ hơn: dùng normal, không hỏi (retro 11-05: 46/46 lần chọn normal, fast 0 lần qua 2 retro). Sàn an toàn giữ ở mọi mode; đổi được giữa chừng.
|
|
24
|
+
- extract: Cần đúng những trường nào, đầu ra định dạng gì (bảng/JSON/cột Sheet), và khi các nguồn lệch nhau thì nguồn nào là chuẩn? (retro 11-05: steer_rate 0,3, n10)
|
|
25
|
+
|
|
26
|
+
## Bài học
|
|
27
|
+
|
|
28
|
+
- [2026-10-12] plan-design,search | * | steps.json — 23 agent dùng task_type tự đặt (bug-fix, config, shell, docs, design, plan, deploy, research, art-fix) nên mất prior, rơi về opus/medium → chỉ dùng 12 loại cố định + art-gen; bug-fix→debug, config/shell/deploy→mechanical-edit, docs→content-write, design/plan→plan-design, research→research-synth, art-fix→art-gen
|
|
29
|
+
- [2026-10-12] feature-impl,content-write,debug,art-gen | * | quota — dừng vì hết usage limit bị ghi thành timeout (5/18 lượt không pass) → báo "STATUS: partial — quota-pause", không bao giờ báo timeout
|
|
30
|
+
- [2026-10-11] [orch] | * | state/log — lấy tier --approved từ `dieu-phoi state` (lần duyệt mới nhất), xem lại sau mỗi lần duyệt lại, không theo trí nhớ; yêu cầu nhầm thì `dieu-phoi discard --task <id>`, không sửa tay events.jsonl
|
|
31
|
+
- [2026-10-12] [orch] | * | verdict — 4 verdict ghi "điều phối viên chạy lại test" → verdict chỉ dựa trên file dp-out verify của verifier; còn nghi thì giao verifier mới, không tự chạy
|
|
32
|
+
- [2026-10-12] [orch] | * | cổng 3 — chỉ 16% task có verdict người dùng nên retro học trên verdict agent → ở cổng 3 hỏi nghiệm thu từng bước; bước chưa đạt reject theo task, phần còn lại `verdict --root <root> accept`
|
|
33
|
+
- [2026-10-16] * | * | report — Claude Code chặn cứng Write trong subagent khi tên file khớp `/^(REPORT|SUMMARY|FINDINGS|ANALYSIS).*.md$/i` ("Subagents should return findings as text"; không cấu hình được, chạy trước permissions) → mọi file kết quả của exec/verify/scout đặt tên `dp-out-<task>-<role>-try<n>.md` (handoff-*.md không bị chặn); ghi hỏng thì Bash heredoc, vẫn hỏng thì trả inline (hook tự lưu `.inline.md`); áp dụng cả file sản phẩm trong repo (REPORT.md bị chặn 2026-10-17) → đặt tên khác, vd. RESULTS.md / docs/<topic>.md
|
|
34
|
+
- [2026-10-13] feature-impl | * | web/brand — QA headless bỏ sót lỗi cache cũ → trước khi deploy yêu cầu cache-busting `?v=` cho css/js và layout vẫn đúng khi không có CSS/JS (inline SVG)
|
|
35
|
+
- [2026-10-11] art-gen | * | qis — agent in hub key từ qis-information.md ra output công cụ → brief ghi rõ: đọc file trong script, không cat/grep/in nội dung
|
|
36
|
+
- [2026-10-11] feature-impl,test-write | * | lanes — DoD của bước lane phải chạy mọi smoke mode chạm màn hình bước đổi; smoke mode mới chờ theo điều kiện, không đếm tap cố định (PB)
|
|
37
|
+
- [2026-10-13] art-gen,feature-impl | * | brand/logo — logo nhiều lớp: mọi xử lý tương phản (viền/glow) áp dụng giống nhau cho mọi lớp của logo, không chỉ một lớp
|
|
38
|
+
- [2026-10-13] feature-impl,debug,test-write | * | unity-lanes — nhiều editor Unity cùng máy dẫm nhau (khớp process lỏng, đóng nhầm editor, play không focus đứng hình, C: đầy) → brief bước Unity đọc <skill>/profile/unity-lanes.md mục 4-11
|
|
39
|
+
- [2026-10-13] plan-design | * | unity-lanes — kế hoạch Unity dài chạy tuần tự → planner đọc unity-lanes.md mục 1-3, ghi unity_lane/unity_lane_2 + bước integrator
|
|
40
|
+
- [2026-10-13] plan-design,feature-impl | * | unity-lanes — nhiều máy cùng repo game → planner gán thêm `machine` cho bước Unity; claim bước bằng commit+push, push thường (không force); đọc unity-lanes.md mục "Nhiều máy"
|
|
41
|
+
- [2026-10-13] [orch] | * | unity-lanes — bước Unity song song/nhiều máy → planner gán unity_lane (+machine), mỗi lane một agent, sau mỗi bước lane có bước integrator trên trunk; editor/khoá/claim: <skill>/profile/unity-lanes.md
|
|
42
|
+
- [2026-10-13] feature-impl,debug,test-write | * | stuck — git/Unity "treo" thường là hộp thoại modal ẩn (UnityYAMLMerge, Safe Mode) → soi cây process con + tên cửa sổ; git qua lanes.py có timeout; chỉ kill PID mình; unity-lanes.md mục 14
|
|
43
|
+
- [2026-10-13] test-write,feature-impl | * | device-qa — QA MuMu chơi save thật của người dùng, adb hay chết → sao lưu save app trước, khôi phục sau; adb offline: kill-server, MuMuManager restart, đọc lại cổng
|
|
44
|
+
- [2026-10-13] [orch] | integrate | trunk — phiên khác commit/push trunk trong lúc integrator đang test → mọi commit/push trên trunk phải tôn trọng MERGE_LOCK; lượt tap đầu của smoke chờ theo điều kiện ≤ 30 s khi nhiều editor cùng chạy
|
|
45
|
+
- [2026-10-13] [orch] | * | stuck — agent im > min(15 phút, ½ budget_s) hoặc lặp một trạng thái → SendMessage hỏi đang chờ gì; 10 phút không tiến → steer theo unity-lanes.md mục 14; không ngồi chờ, "Waiting." lặp thì không trả lời
|
|
46
|
+
- [2026-10-16] [orch] | feature-impl | brief — brief trỏ 4+ báo cáo/hợp đồng làm exec chạm ngưỡng handoff (200k) trước khi viết code → chỉ trỏ bước + báo cáo đầu vào trực tiếp; agent tiếp nối chỉ đọc handoff
|
|
47
|
+
- [2026-10-18] feature-impl | * | demo-match — game làm sát demo: test xanh không chứng minh khớp hình ảnh → exec đo tỉ lệ (px/ô, nhân vật, khung UI) từ ảnh demo tham chiếu, dựng sprite theo demo; verifier so ảnh chụp cạnh demo
|
|
48
|
+
- [2026-10-18] feature-impl | * | process — `taskkill /F /IM node.exe` giết tiến trình node của agent song song/người dùng → chỉ dừng PID mình khởi chạy
|
|
49
|
+
- [2026-10-18] feature-impl | * | web-audio — Chromium desktop xanh không đủ cho game web có âm thanh → nghiệm thu gồm Safari iOS/Chrome Android thật hoặc WebKit e2e (unlock/resume AudioContext, định dạng)
|
|
50
|
+
- [2026-10-18] [orch] | * | ports — exec song song trên cùng repo chạy e2e/preview tranh cổng 4173 và dist → brief ghi cổng riêng (--port) hoặc gộp e2e vào 1 verifier sau khi các bước song song xong
|
|
51
|
+
- [2026-10-18] feature-impl | sonnet/high | handoff — era 200k: 3/9 chuỗi handoff sonnet không đạt (0/12 opus) → bước feature-impl lớn (dự đoán > 200k) giao opus/medium, hoặc tách bước ngay ở kế hoạch; không leo tier giữa chuỗi
|
|
52
|
+
- [2026-10-22] [orch] | feature-impl | handoff — 10-22: 15/63 task handoff ≥ 2 lần (median $16 so với $2,3), cq7yn1ws 10 handoff $70 rồi fail; 10-26: phiên 36cee993 vẫn 25/66 task ≥ 2 handoff, 11 task tới handoff thứ 3 (phiên khác 2/87) → sau handoff thứ 2 của một task: dừng tiếp nối, giao planner chia phần còn lại thành bước mới (task_id mới); nhận handoff còn > 1 hạng mục thì giao thành các bước riêng; ở cổng 1, bước feature-impl đụng > 1 màn hình/module lớn thì tách sẵn
|
|
53
|
+
- [2026-10-18] [orch] | * | handoff — 2 chuỗi đóng ở `partial — handoff` không có agent tiếp nối mà vẫn pass → STATUS handoff luôn phải có agent tiếp nối hoặc verifier kiểm phần còn lại trước verdict
|
|
54
|
+
- [2026-10-18] review,verify | haiku/* | dp-out — 10/24 file .inline.md ở era B là của verifier → brief verify: Write dp-out trước khi trả VERDICT
|
|
55
|
+
- [2026-10-18] feature-impl,content-write | * | edit — s32b xoá nhầm 41 dòng design.md bằng script regex/sed → sửa docs/markdown bằng Edit với chuỗi khớp duy nhất, không dùng script thay khối; backup file trước khi sửa hàng loạt
|
|
56
|
+
- [2026-10-18] [orch] | * | verify — giao verifier sớm thì nó đọc dp-out rỗng và trả fail giả → chỉ giao verifier SAU khi nhận task-notification completed của chính exec đó
|
|
57
|
+
- [2026-10-22] [orch] | * | tag — 76 dp-exec ($407) mất task_id vì `[dp:<id>|…]`; 10-26 còn 10 nhãn lạ; 11-05 hook đã tự đổi 15 bí danh, còn 10 bad-type (test-run, test-verify, device-qa, git-ops, release-build, read-scan, untagged), và sau compact từng viết root=/step= → tag luôn đủ `[dp:<task_type>|s<n>|<urgency>|try<n>|task=<id>|role=…]`, task_type lấy đúng chuỗi `choose --json` trả về; quét/đọc → search, architecture → plan-design, shell/git-ops/release-build → mechanical-edit, test-run/device-qa → test-write
|
|
58
|
+
- [2026-10-22] [orch] | * | agent — 9 agent general-purpose chạy tới 311–367k (không có watchdog handoff) → mọi việc điều phối dùng dp-scout/dp-exec/dp-verify; general-purpose chỉ khi `doctor` báo chưa cài
|
|
59
|
+
- [2026-10-26] [orch] | * | session — 10-26: phiên 36cee993 (168 lượt, 946k, 20 nén, 73% chi phí); 11-05: phiên d8fe5944 vẫn chạy 10-25..11-04, 286 lượt, ngữ cảnh 956k, 27 nén, chi phí điều phối $673 (66% chi phí điều phối của kỳ), 0 verdict người dùng, 31 task ≥ 2 handoff, 273 lượt exec không chạy `choose` → khi `choose`/`ctx` báo `new_session` (ngữ cảnh > 400k hoặc ≥ 5 nén): ghi trạng thái (plan.md + backlog), trình cổng 3 các bước đã xong, mở phiên mới; không giao bước mới trong phiên cũ
|
|
60
|
+
- [2026-10-26] [orch] | * | knowledge — kho chỉ gộp delta khi người dùng `accept`; 11-05: 73 delta đọng > 24h, đa số thuộc task chỉ có verdict agent, nhưng 16 task ĐÃ accept vẫn chưa gộp (7 task không có trong plan file nên accept không tìm thấy run dir; 3 xung đột build-test) → ở cổng 3 dùng `verdict --root <root> accept` và ĐỌC dòng "knowledge (tự gộp khi accept)": không có dòng đó mà run có delta của task → `knowledge merge --run <root> --task <id> --dry-run` rồi chạy thật; bước thêm ngoài kế hoạch cũng phải vào plan file; header `repo:` là đường dẫn tuyệt đối
|
|
61
|
+
- [2026-10-26] [orch] | * | input-recall — sau khi nén ngữ cảnh, điều phối viên báo "nội dung X còn chờ người khác" dù người dùng đã giao đủ nguồn trong run dir → trước khi báo việc gì "chờ người dùng/bên ngoài": grep plan.md + mở thư mục nguồn đã giao; việc đã giao mà chưa xếp lane ghi backlog "chưa làm", không ghi "chờ"
|
|
62
|
+
- [2026-10-26] [orch] | * | e2e-base — exec s7 chạy e2e mcp/install/integrity quên đặt BASE nên gọi prod skillhub.pixon.cc (chỉ đọc, token sai) → brief chạy e2e luôn ghi rõ BASE=localhost và bắt agent kiểm biến trước khi chạy
|
|
63
|
+
- [2026-10-26] [orch] | feature-impl,debug,test-write | unity-lanes — agent nào cũng tự mở/đóng Unity, worktree mới mỗi bước → trần 3 editor/máy, 3 slot worktree cố định (Library ấm), editor mở sẵn + cầu nối job queue (`unity_slot.py`); brief bước Unity ghi slot + "không tự chạy Unity.exe"; xoá worktree hết dùng sau khi kiểm sạch; đọc unity-lanes.md mục 2.1
|
|
64
|
+
- [2026-10-27] [orch] | debug,test-write,feature-impl | slow-fix-escalate — bug khó tái hiện (flaky E2E/race) ở sonnet/medium→sonnet/high: 2 lượt ~45 phút đổi test qua lại không ra gốc, người dùng phải tự nâng lên opus/medium thì 1 lượt ~16 phút chốt nguyên nhân bằng log timestamp và sửa ở code app → khi bước debug/flaky không hội tụ sau 1 lượt (tỉ lệ xanh không tăng, chưa có nguyên nhân gốc) hoặc vượt ~2× est_time, đề xuất leo thẳng opus/medium thay vì bậc kế tiếp cùng họ model; retro nên đưa ngưỡng thời gian vào luật leo thang
|
|
65
|
+
- [2026-11-05] [orch] | * | python-stdin — máy Windows này: `python3 -`/heredoc/pipe vào python qua shim pyenv-win mất stdin → REPL lặp vô hạn (log 63 GB đầy C:); agent đã vi phạm 2 lần dù có luật → brief ghi nguyên văn: "chỉ chạy Python bằng `python file.py` (ghi script ra file), không bao giờ qua stdin"; giới hạn output lệnh nền
|
|
66
|
+
- [orch] Parallel dp-exec in one worktree: an agent staging a shared file swept another's WIP and left HEAD uncompilable; give each parallel agent its own worktree, or require py_compile at HEAD + clean git status before reporting.
|
|
67
|
+
- [2026-11-02] [orch] | feature-impl | ctx-ceiling — prototype game Three.js+WS ở sonnet/medium: 3 bước liên tiếp handoff ở ~210k token (server+client+smoke trong 1 bước) → chia bước theo lớp: (1) shared+server+test, (2) client+smoke+push; dặn commit phần xanh trước handoff
|
|
68
|
+
- [2026-11-03] [orch] | feature-impl | netcode-smooth — prototype multiplayer qua verifier (smoke/test xanh) nhưng người dùng thấy di chuyển giật + camera không ra TPS hành động: tiêu chí máy không bắt cảm giác chơi → brief game client phải ghi rõ nội suy/snapshot buffer + client prediction và tham chiếu camera của game TPS cụ thể; verifier chụp/quay vài khung để đánh giá
|
|
69
|
+
- [2026-11-03] [orch] | art-gen,feature-impl | asset-tier — người dùng chỉ định: việc model nhân vật (mọi dự án; sonnet/medium ra bản diorama "cute" chưa đủ) và MỌI việc dựng asset của Anti Sleep City (nhân vật, NPC, monster, cosmetic, props, VFX, UI art) giao opus/medium bằng `--override`; brief trỏ asset guideline (docs/asset-guideline + PAS) khi đã có
|
|
70
|
+
- [2026-11-03] [orch] | deploy,smoke | prod-cleanup — smoke trên prod: script dọn dẹp revoke cả token thật (pixi) của người dùng → brief smoke prod phải buộc chỉ thu hồi/xoá đúng id token/user do chính lượt đó tạo (ghi id lúc tạo), cấm revoke theo tên/pattern/toàn bộ.
|
|
71
|
+
|
|
72
|
+
- [2026-11-03] review,feature-impl | * | docker-cleanup — verifier kill "tiến trình nghe cổng pg/redis của mình" (2kaq9gvq M1) nhưng đó là backend Docker Desktop, mọi container trên máy dừng → dọn bằng `docker compose -p <project> down -v`, chỉ kill PID node/vite do chính mình spawn (ghi PID lúc spawn); KHÔNG kill theo cổng, KHÔNG kill com.docker.*/wsl*/vmmem
|
|
73
|
+
- [orch] home-school: không cho agent `docker exec`/psql/pg_isready vào DB prod (Postgres PID 1 không init → tiến trình mồ côi exit 2 gây crash recovery); hạn chế chạy song song test/DB container khi ổ D HDD nghẽn (docker vhdx trên D:).
|
|
74
|
+
- [orch] feature-impl port lớn (Rust parity): agent opus/medium hay chạm 200k ngữ cảnh trước khi commit — brief phải ép 'build+commit từng phần ngay', đọc file lớn theo đoạn, và tách bước >8 người-ngày thành bước con trước khi giao
|
|
75
|
+
- [2026-11-04] [orch] | debug,security | argv-secret — brief điều tra tiến trình có secret trong argv phải cấm ps -ef/ps aux/cat /proc/*/cmdline (chỉ grep -c), agent haiku đã in argv làm lộ token GitLab trong phiên
|
|
76
|
+
- [2026-11-04] [orch] | debug,security | secret-file-read — brief sửa webapp/deploy phải cấm sed/cat/grep không -c lên /etc/comfy-studio/* và mọi file secret (chỉ stat/ls/grep -c), agent sonnet đã in admin-initial-password ra tool output
|
|
77
|
+
- [orch] Agent kiểm prod viết lệnh git grep sai (pattern/ref đảo) nên kết luận ngược; brief kiểm code phải ghi sẵn lệnh git grep đúng cú pháp hoặc yêu cầu trích dòng code làm bằng chứng.
|
|
78
|
+
- [2026-11-05] [orch] | * | orphan — 143/2.423 agent (5,9%) kết thúc không có dòng STATUS (đã chết giữa chừng), 117 không được giao lại, 42 không có verdict nào; giao lại sau p50 31 phút, p75 71, tối đa 12 giờ; sau nén ngữ cảnh tỉ lệ này cao gấp 3 lần (10% so với 3%); từng báo s16 "đang chạy" nhiều giờ khi không còn agent → sau mỗi restart/compact/handoff/stop: lấy danh sách agent đang chạy (TaskStop lỗi liệt kê) đối chiếu với các bước báo "đang chạy"; bước không có agent hoặc dp-out chỉ có `.inline.md` dở dang/không STATUS → giao lại ngay (try+1), không chờ thông báo sẽ không tới
|
|
79
|
+
- [orch] Trước khi giao một bước, xem tên/đặc tả trong steps có phải deploy không. Nếu đúng: choose --publish y, hỏi người dùng go-ahead rồi trích nguyên văn vào brief, kẻo exec dừng blocked (bwkuqdna s8, 05/11).
|
|
80
|
+
- [orch] Trước khi giao bước, kiểm depends_on của nó đã merge vào nhánh tích hợp chưa (g4 giao trước khi g1 merge → blocked).
|
|
81
|
+
- [2026-11-05] [orch] | * | verify-task-id — 41/756 lượt verify (5,4%) mang task_id không có exec nào (19 không có cả trong plan), 24 verdict agent rơi vào id sai nên bước thật thiếu verdict → thẻ verify chép đúng `task=<id>` từ lượt exec của bước đó (không tự đặt id mới); verifier gộp dùng thẻ `|batch`
|
|
82
|
+
- [2026-11-05] [orch] | * | choose — 425/1.540 lượt exec (28%) giao không chạy `choose` (273 trong phiên d8fe5944: debug chạy opus 61 lượt, $p50 5,5 so với sonnet/medium 1,1) và 138 lượt khác tier của `choose` không ghi override → mỗi lượt exec chạy `choose --json`; giao tier khác thì `--override` để retro học
|
|
83
|
+
- [2026-11-05] plan-design | * | tier-table — kế hoạch xếp opus/medium cho mechanical-edit ≥ 35 lần (n105, $p50 1,50 trong khi haiku/medium $0,03 accept 0,91, sonnet/medium $0,58 accept 0,91) và haiku/low 13 lần (accept 0,73, n15) → cột tier lấy từ `dieu-phoi choose --json` cho từng bước; opus cho mechanical-edit/debug phải ghi lý do một dòng; không xếp haiku/low
|