openmoneta-dev-kit 2.1.0 → 2.2.0
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/VERSION +1 -1
- package/hooks/inject-process-context.sh +1 -1
- package/hooks/verify-completion.sh +25 -2
- package/opencode/AGENTS.md.tpl +4 -4
- package/opencode/plugins/openmoneta-guard.ts +45 -12
- package/package.json +1 -1
- package/skills/decision-recorder/SKILL.md +5 -1
- package/skills/module-architect/SKILL.md +18 -3
- package/skills/requirement-analysis/SKILL.md +1 -0
- package/templates/docs-INDEX.md.tpl +3 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.2.0
|
|
@@ -59,7 +59,7 @@ SUMMARY='# OpenMoneta Dev Kit v1.7.0 — Quy trình 6 bước (Adaptive Planning
|
|
|
59
59
|
- **B2 Thiết kế** (skill `module-architect`): SRP 1 module 1 trách nhiệm. Feature mới có concept riêng → module mới (KHÔNG nhét utils/common/shared). Existing project: backfill `docs/modules/<slug>/README.md` 3 sections nếu thiếu. Module mới → thêm keyword vào Token Routing.
|
|
60
60
|
- **B3 Adaptive Plan** (skill `plan-writer`): task nhỏ/rõ → không cần plan. Task lớn/rủi ro/mơ hồ → tạo repo plan `Status: Draft`, trình user review, chỉ code sau khi user approve và đổi `Status: In Progress`.
|
|
61
61
|
- **B4 Triển khai**: nếu có plan active → chỉ edit file trong scope plan. Không plan → chỉ sửa đúng yêu cầu; nếu vượt ngưỡng/rủi ro → dừng tạo plan Draft.
|
|
62
|
-
- **B5 Update doc + close** (hook `verify-completion` Check 6 enforce):
|
|
62
|
+
- **B5 Update doc + close** (hook `verify-completion` Check 6 enforce): chạm module nào → sync README module đó NGAY trong session (Trách nhiệm/Public API/Dependencies + ràng buộc; Check 6 nudge nếu README không đổi). Thay đổi chạm kiến trúc mà KHÔNG có plan → vẫn phải tạo ADR (`decision-recorder`); Check 12 nudge khi đổi đáng kể mà thiếu ADR. Plan → `Status: Done` + auto-archive `git mv plans/<f>.md plans/archive/`.
|
|
63
63
|
- **B6 Pre-push Sync + Safe Push** (skill `safe-push`, CONDITIONAL): chỉ khi user yêu cầu push/commit+push. `git fetch` + rebase trước push, conflict code logic → hỏi user, verify lại, `git push` thường, retry ≤3, KHÔNG `--force` shared branch.
|
|
64
64
|
|
|
65
65
|
## Sub-agents (delegate khi cần)
|
|
@@ -113,12 +113,17 @@ if [[ -x "$LIST_MODULES_SCRIPT" || -f "$LIST_MODULES_SCRIPT" ]]; then
|
|
|
113
113
|
AFFECTED=$(bash "$LIST_MODULES_SCRIPT" "$CHANGES_FILE" 2>/dev/null || true)
|
|
114
114
|
|
|
115
115
|
if [[ -n "$AFFECTED" ]]; then
|
|
116
|
+
# Danh sách path đã đổi trong session (để check README freshness — Tuyến 1).
|
|
117
|
+
CHANGED_PATHS=$(jq -r '.changes[] | .path' "$CHANGES_FILE" 2>/dev/null || true)
|
|
116
118
|
while IFS=$'\t' read -r slug docs_path source_path; do
|
|
117
119
|
[[ -z "$slug" ]] && continue
|
|
118
120
|
MODULE_README="$WORKSPACE/$docs_path/README.md"
|
|
119
121
|
|
|
120
122
|
if [[ ! -f "$MODULE_README" ]]; then
|
|
121
123
|
ISSUES+=("❌ Module '$slug' (source: $source_path) bị sửa nhưng chưa có '$docs_path/README.md'. Tạo README 3 sections (Trách nhiệm + Public API + Dependencies) theo skill module-architect Bước 2.2 + cập nhật bảng 'Modules hiện có' và 'Token Routing' trong docs/INDEX.md.")
|
|
124
|
+
elif [[ "$LOOP_COUNT" -eq 0 ]] && ! printf '%s\n' "$CHANGED_PATHS" | grep -qFx "$docs_path/README.md"; then
|
|
125
|
+
# README freshness (nudge mềm 1 lần): module source đổi nhưng README chưa sync trong session.
|
|
126
|
+
ISSUES+=("⚠️→ Module '$slug' bị sửa source nhưng '$docs_path/README.md' KHÔNG được cập nhật trong session. Nếu có đổi Public API / Trách nhiệm / Dependencies / ràng buộc → sync README NGAY (skill module-architect Bước 5). Nếu chỉ fix nội bộ không đổi hợp đồng → bỏ qua, kết thúc lại lần nữa (nhắc 1 lần).")
|
|
122
127
|
fi
|
|
123
128
|
done <<< "$AFFECTED"
|
|
124
129
|
|
|
@@ -159,16 +164,34 @@ if [[ -n "$CHANGED_DECISIONS" ]]; then
|
|
|
159
164
|
fi
|
|
160
165
|
|
|
161
166
|
# Check 11: plan trong session khai báo đổi/đảo kiến trúc nhưng KHÔNG sinh/sửa ADR
|
|
167
|
+
ARCH_DECLARED=0
|
|
162
168
|
for plan in $ALL_RECENT_PLANS; do
|
|
163
169
|
[[ -z "$plan" || ! -f "$plan" ]] && continue
|
|
164
170
|
if grep -qE "^##[[:space:]]+Quyết định kiến trúc" "$plan" 2>/dev/null; then
|
|
165
171
|
DECL=$(awk '/^##[[:space:]]+Quyết định kiến trúc/{flag=1; next} flag && /^##[[:space:]]/{exit} flag {print}' "$plan" | grep -iE 'supersede|đổi kiến trúc|revert|đảo ngược' || true)
|
|
166
|
-
if [[ -n "$DECL"
|
|
167
|
-
|
|
172
|
+
if [[ -n "$DECL" ]]; then
|
|
173
|
+
ARCH_DECLARED=1
|
|
174
|
+
if [[ -z "$CHANGED_DECISIONS" ]]; then
|
|
175
|
+
ISSUES+=("❌ Plan '$(basename "$plan")' có '## Quyết định kiến trúc' khai báo đổi/đảo kiến trúc nhưng KHÔNG có docs/decisions/*.md được tạo/cập nhật. Tạo/supersede ADR (skill decision-recorder) trước khi đóng session.")
|
|
176
|
+
fi
|
|
168
177
|
fi
|
|
169
178
|
fi
|
|
170
179
|
done
|
|
171
180
|
|
|
181
|
+
# Check 12: thay đổi "đáng kể" KHÔNG qua plan kiến trúc + KHÔNG có ADR → nudge mềm 1 lần.
|
|
182
|
+
# Backstop cho ca sửa code chạm kiến trúc nhưng không tạo plan (Check 11 không bắt được).
|
|
183
|
+
# Ngưỡng CHẶT (≥4 module HOẶC ≥12 file code) để hiếm khi kêu, tránh false-positive.
|
|
184
|
+
if [[ "$LOOP_COUNT" -eq 0 && -f "$WORKSPACE/docs/decisions/INDEX.md" && -z "$CHANGED_DECISIONS" && "$ARCH_DECLARED" -eq 0 ]]; then
|
|
185
|
+
NUM_CODE_FILES=$(jq -r '.changes[] | .path' "$CHANGES_FILE" 2>/dev/null \
|
|
186
|
+
| grep -vE '^(docs/|plans/|README|\.gitignore|\.env\.example|AGENTS\.md|\.cursor/|CHANGELOG|VERSION$|package(-lock)?\.json|pnpm-lock|yarn\.lock)' \
|
|
187
|
+
| grep -cvE '^$' || true)
|
|
188
|
+
NUM_CODE_FILES=${NUM_CODE_FILES:-0}
|
|
189
|
+
NUM_MODULES=${NUM_MODULES:-0}
|
|
190
|
+
if [[ "$NUM_MODULES" -ge 4 || "$NUM_CODE_FILES" -ge 12 ]]; then
|
|
191
|
+
ISSUES+=("⚠️→ Session đụng $NUM_MODULES module / $NUM_CODE_FILES file code nhưng KHÔNG tạo/sửa ADR nào và KHÔNG có plan khai báo kiến trúc. NẾU đây là quyết định kiến trúc (đổi data flow, đổi cách module giao tiếp, thay/đảo 1 cơ chế, fix bug bằng cách đổi thiết kế) → tạo ADR (skill decision-recorder) hoặc nâng lên plan TRƯỚC khi đóng. Nếu chỉ là thay đổi thường (refactor nội bộ, đổi text, thêm field) → bỏ qua, kết thúc lại lần nữa (nhắc 1 lần).")
|
|
192
|
+
fi
|
|
193
|
+
fi
|
|
194
|
+
|
|
172
195
|
# === Output ===
|
|
173
196
|
WARN_STR=""
|
|
174
197
|
if [[ ${#WARNINGS[@]} -gt 0 ]]; then
|
package/opencode/AGENTS.md.tpl
CHANGED
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
- **B1 Phân tích** (skill `requirement-analysis`): Read `docs/INDEX.md` → match Token Routing → đọc README module liên quan → đọc source → hỏi clarify nếu yêu cầu chưa rõ (ghi vào `## Hiểu yêu cầu` của plan). **Nếu có `docs/decisions/INDEX.md`: PHẢI đọc nó + ADR liên quan trước khi đổi kiến trúc** (plugin guard chặn read source nếu chưa đọc `docs/decisions/`). Muốn đảo kiến trúc đã chốt → supersede tường minh (skill `decision-recorder`), chống flip-flop A1→B1→A1.
|
|
17
17
|
- **B2 Thiết kế** (skill `module-architect`): SRP 1 module 1 trách nhiệm. Feature có concept riêng → module mới (KHÔNG nhét utils/common/shared). **Module có source nhưng chưa có doc → BẮT BUỘC backfill `docs/modules/<slug>/README.md` 3 sections (Trách nhiệm + Public API + Dependencies)** trước khi sang B4. Module mới → thêm keyword vào Token Routing của `docs/INDEX.md`.
|
|
18
18
|
- **B3 Adaptive Plan** (skill `plan-writer`): task nhỏ/rõ → không cần plan. Task lớn/rủi ro/mơ hồ → tạo repo plan `Status: Draft`, trình user review, chỉ code sau khi user approve và đổi `Status: In Progress`. Plan đổi/đảo kiến trúc → thêm section `## Quyết định kiến trúc` (`Supersede ADR-NNNN` + lý do root cause cũ hết đúng).
|
|
19
|
-
- **B4 Triển khai**: có plan active → chỉ edit file trong scope plan; không plan → chỉ sửa đúng yêu cầu. Mỗi sub-task xong → tick `- [x]`.
|
|
19
|
+
- **B4 Triển khai**: có plan active → chỉ edit file trong scope plan; không plan → chỉ sửa đúng yêu cầu. Mỗi sub-task xong → tick `- [x]`. **Bug-fix hoá ra chạm kiến trúc** (đổi data flow / cách module giao tiếp / thay-đảo cơ chế) → nâng lên B3 hoặc tạo ADR, KHÔNG âm thầm sửa.
|
|
20
20
|
- **B5 Update doc + close plan** — **mandatory closing checklist** (plugin guard `event:session.idle` sẽ re-prompt nếu thiếu):
|
|
21
|
-
- [ ] Sync `docs/modules/<slug>/README.md` cho
|
|
21
|
+
- [ ] Sync `docs/modules/<slug>/README.md` cho MỌI module bị sửa NGAY trong session: **Trách nhiệm + Public API + Dependencies** (+ **Lưu ý/Ràng buộc** nếu có invariant mới). Guard Check 6 nudge nếu module source đổi mà README không đổi.
|
|
22
22
|
- [ ] Module mới đã có trong bảng "Modules hiện có" + "Token Routing" của `docs/INDEX.md`.
|
|
23
|
-
- [ ] Nếu session đổi kiến trúc → tạo/supersede ADR trong `docs/decisions/` + link vào README module + cập nhật `docs/decisions/INDEX.md` (skill `decision-recorder`).
|
|
23
|
+
- [ ] Nếu session đổi kiến trúc (kể cả KHÔNG có plan) → tạo/supersede ADR trong `docs/decisions/` + link vào README module + cập nhật `docs/decisions/INDEX.md` (skill `decision-recorder`). Guard Check 12 nudge khi đổi đáng kể (≥4 module / ≥12 file) mà thiếu ADR.
|
|
24
24
|
- [ ] Plan → `Status: Done` + tick mọi checkbox.
|
|
25
25
|
- [ ] **AUTO-ARCHIVE**: `git mv plans/<file>.md plans/archive/<file>.md` + update `plans/INDEX.md` (Active → Archived).
|
|
26
26
|
- **B6 Pre-push Sync + Safe Push** (skill `safe-push`, CONDITIONAL): chỉ khi user yêu cầu push. `git fetch` + rebase trước push, conflict logic → hỏi user, `git push` thường, KHÔNG `--force` shared branch.
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
- OpenMoneta skills được cài vào `~/.config/opencode/skills/*/SKILL.md` và agent nên load bằng skill tool khi cần.
|
|
33
33
|
- **Bảo trì doc dự án cũ** (ON-DEMAND): khi user yêu cầu tạo/refresh docs còn thiếu hoặc lỗi thời, chạy `bash ~/.config/opencode/scripts/docs-audit.sh` để soi rồi load skill `docs-maintenance` (backfill MISSING + refresh STALE + sync `docs/INDEX.md`).
|
|
34
34
|
- OpenMoneta subagents được cài vào `~/.config/opencode/agents/`.
|
|
35
|
-
- OpenCode plugin guard trong `~/.config/opencode/plugins/openmoneta-guard.ts` enforce workflow tương đương Cursor hooks: `tool.execute.before` (docs-first + decisions-read gate + plan gate), `tool.execute.after` (track changes), và `event:session.idle` (verify B2/B5 + ADR integrity: module README, close plan, supersede ADR, re-prompt nhắc hoàn tất với loop guard ≤4 lần).
|
|
35
|
+
- OpenCode plugin guard trong `~/.config/opencode/plugins/openmoneta-guard.ts` enforce workflow tương đương Cursor hooks: `tool.execute.before` (docs-first + decisions-read gate + plan gate), `tool.execute.after` (track changes), và `event:session.idle` (verify B2/B5 + ADR integrity: module README tồn tại + freshness nudge (Check 6), close plan, supersede ADR (Check 10/11), ADR backstop khi đổi đáng kể không plan (Check 12), re-prompt nhắc hoàn tất với loop guard ≤4 lần).
|
|
36
36
|
|
|
37
37
|
## Khi Bắt Đầu Task
|
|
38
38
|
|
|
@@ -320,8 +320,10 @@ function planHasUnderstanding(planPath: string): boolean {
|
|
|
320
320
|
return foundHeading && hasContent
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
// Build danh sách issue tương đương verify-completion Check 5/6/9.
|
|
324
|
-
|
|
323
|
+
// Build danh sách issue tương đương verify-completion Check 5/6/9/10/11/12.
|
|
324
|
+
// firstNudge = true khi đây là lần re-prompt đầu (verify-loop count === 0) — dùng cho
|
|
325
|
+
// các nudge mềm "1 lần" (README freshness + Check 12 ADR backstop), parity với LOOP_COUNT == 0.
|
|
326
|
+
function buildVerifyIssues(root: string, firstNudge = true): string[] {
|
|
325
327
|
const paths = readSessionChanges(root)
|
|
326
328
|
if (paths.length === 0) return []
|
|
327
329
|
if (!paths.some((p) => !NON_CODE_CHANGE.test(p))) return []
|
|
@@ -366,11 +368,17 @@ function buildVerifyIssues(root: string): string[] {
|
|
|
366
368
|
}
|
|
367
369
|
}
|
|
368
370
|
|
|
369
|
-
// Check 6: module bị sửa phải có docs/modules/<slug>/README.md
|
|
371
|
+
// Check 6: module bị sửa phải có docs/modules/<slug>/README.md (+ README freshness — Tuyến 1)
|
|
370
372
|
for (const { slug, docsPath } of inferModules(paths)) {
|
|
371
|
-
|
|
373
|
+
const readmeRel = `${docsPath}/README.md`
|
|
374
|
+
if (!fs.existsSync(path.join(root, readmeRel))) {
|
|
372
375
|
issues.push(
|
|
373
|
-
`❌ Module '${slug}' bị sửa nhưng thiếu '${
|
|
376
|
+
`❌ Module '${slug}' bị sửa nhưng thiếu '${readmeRel}'. Tạo README 3 sections (Trách nhiệm + Public API + Dependencies) + cập nhật docs/INDEX.md (Bước 2/5).`,
|
|
377
|
+
)
|
|
378
|
+
} else if (firstNudge && !paths.includes(readmeRel)) {
|
|
379
|
+
// README freshness (nudge mềm 1 lần): module source đổi nhưng README chưa sync.
|
|
380
|
+
issues.push(
|
|
381
|
+
`⚠️→ Module '${slug}' bị sửa source nhưng '${readmeRel}' KHÔNG được cập nhật trong session. Nếu có đổi Public API / Trách nhiệm / Dependencies / ràng buộc → sync README NGAY (Bước 5). Nếu chỉ fix nội bộ không đổi hợp đồng → bỏ qua, kết thúc lại lần nữa (nhắc 1 lần).`,
|
|
374
382
|
)
|
|
375
383
|
}
|
|
376
384
|
}
|
|
@@ -403,6 +411,7 @@ function buildVerifyIssues(root: string): string[] {
|
|
|
403
411
|
}
|
|
404
412
|
|
|
405
413
|
// Check 11: plan khai báo "## Quyết định kiến trúc" (đổi/đảo) nhưng không sinh/sửa ADR
|
|
414
|
+
let archDeclared = false
|
|
406
415
|
for (const plan of planSet) {
|
|
407
416
|
if (!fs.existsSync(plan)) continue
|
|
408
417
|
const lines = fs.readFileSync(plan, "utf8").split(/\r?\n/)
|
|
@@ -416,9 +425,32 @@ function buildVerifyIssues(root: string): string[] {
|
|
|
416
425
|
if (inSection && /^##\s+/.test(line)) break
|
|
417
426
|
if (inSection && /supersede|đổi kiến trúc|revert|đảo ngược/i.test(line)) declared = true
|
|
418
427
|
}
|
|
419
|
-
if (declared
|
|
428
|
+
if (declared) {
|
|
429
|
+
archDeclared = true
|
|
430
|
+
if (changedDecisions.length === 0) {
|
|
431
|
+
issues.push(
|
|
432
|
+
`❌ Plan '${path.basename(plan)}' có '## Quyết định kiến trúc' khai báo đổi/đảo kiến trúc nhưng KHÔNG có docs/decisions/*.md được tạo/cập nhật. Tạo/supersede ADR (skill decision-recorder) trước khi kết thúc.`,
|
|
433
|
+
)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Check 12: thay đổi "đáng kể" KHÔNG qua plan kiến trúc + KHÔNG có ADR → nudge mềm 1 lần.
|
|
439
|
+
// Backstop cho ca sửa code chạm kiến trúc nhưng không tạo plan. Ngưỡng CHẶT (≥4 module HOẶC
|
|
440
|
+
// ≥12 file code) để hiếm khi kêu, tránh false-positive.
|
|
441
|
+
if (
|
|
442
|
+
firstNudge &&
|
|
443
|
+
fs.existsSync(path.join(root, "docs", "decisions", "INDEX.md")) &&
|
|
444
|
+
changedDecisions.length === 0 &&
|
|
445
|
+
!archDeclared
|
|
446
|
+
) {
|
|
447
|
+
const numModules = inferModules(paths).length
|
|
448
|
+
const numCodeFiles = paths.filter(
|
|
449
|
+
(p) => !/^(docs\/|plans\/|README|\.gitignore|\.env\.example|AGENTS\.md|\.cursor\/|CHANGELOG|VERSION$|package(-lock)?\.json|pnpm-lock|yarn\.lock)/.test(p),
|
|
450
|
+
).length
|
|
451
|
+
if (numModules >= 4 || numCodeFiles >= 12) {
|
|
420
452
|
issues.push(
|
|
421
|
-
|
|
453
|
+
`⚠️→ Session đụng ${numModules} module / ${numCodeFiles} file code nhưng KHÔNG tạo/sửa ADR nào và KHÔNG có plan khai báo kiến trúc. NẾU đây là quyết định kiến trúc (đổi data flow, đổi cách module giao tiếp, thay/đảo 1 cơ chế, fix bug bằng cách đổi thiết kế) → tạo ADR (skill decision-recorder) hoặc nâng lên plan TRƯỚC khi đóng. Nếu chỉ là thay đổi thường → bỏ qua, kết thúc lại lần nữa (nhắc 1 lần).`,
|
|
422
454
|
)
|
|
423
455
|
}
|
|
424
456
|
}
|
|
@@ -518,7 +550,7 @@ export const OpenMonetaGuard = async (ctx: GuardContext) => {
|
|
|
518
550
|
{
|
|
519
551
|
loaded_at: new Date().toISOString(),
|
|
520
552
|
root,
|
|
521
|
-
version: "2.0
|
|
553
|
+
version: "2.2.0",
|
|
522
554
|
load_count: globalState[globalKey],
|
|
523
555
|
},
|
|
524
556
|
null,
|
|
@@ -686,8 +718,12 @@ export const OpenMonetaGuard = async (ctx: GuardContext) => {
|
|
|
686
718
|
}) => {
|
|
687
719
|
if (event.type !== "session.idle") return
|
|
688
720
|
try {
|
|
689
|
-
const issues = buildVerifyIssues(root)
|
|
690
721
|
const sessionID = asString(event.properties?.sessionID)
|
|
722
|
+
const loop = readVerifyLoop(root)
|
|
723
|
+
const count = loop.sessionID === sessionID ? loop.count : 0
|
|
724
|
+
|
|
725
|
+
// count === 0 ⇒ lần nhắc đầu ⇒ bật các nudge mềm "1 lần" (parity LOOP_COUNT == 0).
|
|
726
|
+
const issues = buildVerifyIssues(root, count === 0)
|
|
691
727
|
|
|
692
728
|
if (issues.length === 0) {
|
|
693
729
|
clearSessionChanges(root)
|
|
@@ -695,9 +731,6 @@ export const OpenMonetaGuard = async (ctx: GuardContext) => {
|
|
|
695
731
|
return
|
|
696
732
|
}
|
|
697
733
|
|
|
698
|
-
const loop = readVerifyLoop(root)
|
|
699
|
-
const count = loop.sessionID === sessionID ? loop.count : 0
|
|
700
|
-
|
|
701
734
|
if (count >= VERIFY_LOOP_LIMIT) {
|
|
702
735
|
console.warn(
|
|
703
736
|
`[OpenMoneta Dev Kit] verify-completion: đã nhắc ${count} lần, graceful exit. ` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openmoneta-dev-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "OpenMoneta Dev Kit — Biến Cursor IDE / OpenCode thành team developer hoàn chỉnh với quy trình 6 bước, adaptive planning, hooks enforcement, và token-aware doc routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cursor",
|
|
@@ -19,8 +19,12 @@ KHÔNG ĐẢO NGƯỢC một kiến trúc đã Accepted (LOCKED) khi CHƯA:
|
|
|
19
19
|
|
|
20
20
|
## Khi nào TẠO ADR
|
|
21
21
|
|
|
22
|
+
> **Trigger này áp dụng kể cả KHÔNG có plan.** Nếu đang fix bug / sửa code mà chạm 1 trong các dấu hiệu dưới → DỪNG, tạo ADR NGAY (hoặc nâng lên plan), KHÔNG âm thầm sửa rồi đóng session. Hook Check 12 sẽ nudge nếu thay đổi đáng kể mà thiếu ADR.
|
|
23
|
+
|
|
22
24
|
- Chọn giữa ≥2 phương án kiến trúc có trade-off thật (state management, data flow, sync vs async, pattern...).
|
|
23
|
-
- Đổi cách triển khai một tính năng đang chạy (vd: polling → websocket).
|
|
25
|
+
- Đổi cách triển khai một tính năng đang chạy (vd: polling → websocket; DB heartbeat → in-memory).
|
|
26
|
+
- **Đổi data flow / đổi cách các module giao tiếp với nhau** (đổi contract giữa module, đổi nguồn sự thật).
|
|
27
|
+
- **Thay/đảo một cơ chế cốt lõi** dù khởi đầu chỉ là "fix bug" — fix bug bằng cách ĐỔI THIẾT KẾ = quyết định kiến trúc.
|
|
24
28
|
- `systematic-debugging` xác nhận một approach hỏng do bản chất kiến trúc (không phải bug vặt).
|
|
25
29
|
- Đảo ngược / thay thế một quyết định cũ.
|
|
26
30
|
|
|
@@ -70,7 +70,7 @@ Khi nào IGNORE rule (không tách dù dài):
|
|
|
70
70
|
- Config files (webpack, playwright, biome, ...).
|
|
71
71
|
- File có cohesion cực cao (vd 1 state machine 500 dòng cho 1 workflow rõ ràng).
|
|
72
72
|
|
|
73
|
-
#### 3. Mỗi module có `README.md` riêng (3
|
|
73
|
+
#### 3. Mỗi module có `README.md` riêng (3 section bắt buộc + 2 tùy, lean)
|
|
74
74
|
|
|
75
75
|
```markdown
|
|
76
76
|
# <Tên module>
|
|
@@ -82,13 +82,27 @@ Khi nào IGNORE rule (không tách dù dài):
|
|
|
82
82
|
- `funcA(arg1: X, arg2: Y): Z` — mô tả 1 dòng
|
|
83
83
|
- `class Foo` — mô tả 1 dòng
|
|
84
84
|
|
|
85
|
+
## Lưu ý / Ràng buộc (invariants) <!-- TÙY: chỉ khi có ràng buộc không hiển nhiên -->
|
|
86
|
+
|
|
87
|
+
- <quy tắc phải giữ / cạm bẫy, vd: "phải init DB trước khi gọi", "chạy cả Cursor + OpenCode nên giữ path trừu tượng">
|
|
88
|
+
|
|
89
|
+
## Quyết định kiến trúc (ADR) <!-- TÙY: chỉ khi module có ADR -->
|
|
90
|
+
|
|
91
|
+
- [ADR-0003](../../decisions/0003-...md) — <1 dòng> (Accepted)
|
|
92
|
+
|
|
85
93
|
## Dependencies
|
|
86
94
|
|
|
87
95
|
- Internal: `modules/auth`, `modules/db`
|
|
88
96
|
- External: `axios`, `zod`
|
|
89
97
|
```
|
|
90
98
|
|
|
91
|
-
|
|
99
|
+
**3 section BẮT BUỘC**: Trách nhiệm + Public API + Dependencies.
|
|
100
|
+
|
|
101
|
+
**2 section TÙY** (thêm khi có, vì là trí nhớ chống regression — đừng bỏ nếu thật sự có):
|
|
102
|
+
- **`## Lưu ý / Ràng buộc (invariants)`** (≤5 bullet): ràng buộc/cạm bẫy ngầm mà session sau dễ phá nếu không biết (thứ tự init, side-effect, môi trường chạy, giả định dữ liệu). Đây là tri thức ngầm hay mất giữa các session → gây regression; ghi ngắn gọn ngay khi phát hiện.
|
|
103
|
+
- **`## Quyết định kiến trúc (ADR)`**: list ADR-NNNN chi phối module (link). Tạo qua skill `decision-recorder`.
|
|
104
|
+
|
|
105
|
+
> KHÔNG thêm Owner/Stability/Cách dùng/tutorial — dễ stale, AI hiếm dùng. Giữ README lean: chỉ ghi cái session sau THỰC SỰ cần để không hiểu lệch / không phá đồ.
|
|
92
106
|
|
|
93
107
|
### Cấu trúc folder mẫu
|
|
94
108
|
|
|
@@ -204,7 +218,7 @@ Quy tắc maintenance:
|
|
|
204
218
|
|
|
205
219
|
### Bước 5 workflow — Sync module README (BẮT BUỘC)
|
|
206
220
|
|
|
207
|
-
> Hook `verify-completion` Check 6
|
|
221
|
+
> Hook `verify-completion` Check 6: **CHẶN** nếu module bị sửa nhưng thiếu `docs/modules/<slug>/README.md`; và **nudge mềm 1 lần** (README freshness) nếu module source đổi nhưng README KHÔNG được cập nhật trong session. Chạm module nào → sync README module đó NGAY trong session, KHÔNG để "sửa sau".
|
|
208
222
|
|
|
209
223
|
**Cách xác định module từ file path** (cho file đã sửa trong session):
|
|
210
224
|
|
|
@@ -227,6 +241,7 @@ Quy tắc maintenance:
|
|
|
227
241
|
4. Check section **Dependencies**:
|
|
228
242
|
- Có `import` mới từ module khác? → thêm.
|
|
229
243
|
- Có `import` bị xóa? → xóa.
|
|
244
|
+
4b. Check section **Lưu ý / Ràng buộc**: thay đổi có tạo ra ràng buộc/cạm bẫy ngầm mới (thứ tự init, side-effect, giả định dữ liệu)? → thêm bullet ngắn. Đây là thứ chống regression cho session sau.
|
|
230
245
|
5. Nếu module **mới được backfill** ở Bước 2.2 → đảm bảo `docs/INDEX.md` đã có trong bảng "Modules hiện có" + Token Routing.
|
|
231
246
|
6. **Nếu session ra/đổi quyết định kiến trúc cho module này** → tạo/cập nhật ADR (skill `decision-recorder`) trong `docs/decisions/` + thêm/sync section "## Quyết định kiến trúc (ADR)" trong README module (list các ADR-NNNN liên quan) + cập nhật `docs/decisions/INDEX.md`. KHÔNG bắt buộc cho task không đổi kiến trúc.
|
|
232
247
|
|
|
@@ -47,6 +47,7 @@ description: "Dùng khi bắt đầu phân tích một yêu cầu trước khi t
|
|
|
47
47
|
- Kiểm tra phần **Rejected alternatives** + **Failed approaches log**: phương án bạn định chuyển sang có phải cái đã từng bị loại/hỏng không? Nếu CÓ và root cause còn đúng → KHÔNG lặp lại (đây chính là cái bẫy `A1 → B1 → A1`).
|
|
48
48
|
- Khi ADR tóm tắt chưa đủ ngữ cảnh → theo link **`Plan nguồn`** xuống `plans/archive/<file>.md` (tầng chi tiết, chỉ nạp khi cần).
|
|
49
49
|
- Muốn đổi kiến trúc đã khóa → áp dụng skill `decision-recorder` (quy trình supersede tường minh).
|
|
50
|
+
- **Bug-fix hoá ra chạm kiến trúc**: nếu trong lúc làm 1 task tưởng nhỏ (fix bug) mà phát hiện phải đổi data flow / đổi cách module giao tiếp / thay-đảo cơ chế cốt lõi → KHÔNG âm thầm sửa rồi đóng. Nâng lên B3 (tạo plan) HOẶC tạo ADR ngay (skill `decision-recorder`), kể cả khi task khởi đầu không có plan.
|
|
50
51
|
|
|
51
52
|
#### Anti-pattern token waste
|
|
52
53
|
|
|
@@ -41,10 +41,12 @@
|
|
|
41
41
|
|
|
42
42
|
## Cách thêm module mới
|
|
43
43
|
|
|
44
|
-
1. Tạo `docs/modules/<module-name>/README.md` với 3
|
|
44
|
+
1. Tạo `docs/modules/<module-name>/README.md` với 3 section BẮT BUỘC + 2 section TÙY:
|
|
45
45
|
- **Trách nhiệm**: 1 câu không có "và".
|
|
46
46
|
- **Public API**: function/class export.
|
|
47
47
|
- **Dependencies**: internal + external.
|
|
48
|
+
- *(tùy)* **Lưu ý / Ràng buộc (invariants)**: ≤5 bullet ràng buộc/cạm bẫy ngầm (thứ tự init, side-effect, giả định dữ liệu) — thêm khi có, để session sau không phá đồ.
|
|
49
|
+
- *(tùy)* **Quyết định kiến trúc (ADR)**: link ADR-NNNN chi phối module (xem `docs/decisions/` + skill `decision-recorder`).
|
|
48
50
|
2. Update bảng "Modules hiện có" ở trên.
|
|
49
51
|
3. **BẮT BUỘC**: thêm 3-5 keyword vào bảng "Token Routing" (cho cả VN + EN).
|
|
50
52
|
4. Tạo source folder tương ứng (`src/modules/<name>/` hoặc `apps/<name>/` hoặc `packages/<name>/`).
|