@longph2102/v-flow 1.5.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/AGENTS.md +265 -0
- package/CHANGELOG.md +318 -0
- package/LICENSE +21 -0
- package/README.md +326 -0
- package/agents/ba-agent.md +437 -0
- package/agents/ba-critic-agent.md +156 -0
- package/agents/ba-to-ptyc-agent.md +112 -0
- package/agents/bugfix-analyst-agent.md +221 -0
- package/agents/constitute-agent.md +155 -0
- package/agents/help-agent.md +168 -0
- package/agents/implement-agent.md +220 -0
- package/agents/import-ba-docs-agent.md +164 -0
- package/agents/master-check-agent.md +228 -0
- package/agents/metrics-agent.md +180 -0
- package/agents/operations-agent.md +123 -0
- package/agents/plan-agent.md +218 -0
- package/agents/prototype-agent.md +191 -0
- package/agents/retrospective-agent.md +196 -0
- package/agents/review-agent.md +210 -0
- package/agents/sprint-agent.md +191 -0
- package/agents/status-agent.md +186 -0
- package/agents/sync-agent.md +201 -0
- package/agents/test-agent.md +166 -0
- package/agents/understand-agent.md +339 -0
- package/cli/commands/check.js +96 -0
- package/cli/commands/dev-quiz.js +107 -0
- package/cli/commands/doctor.js +348 -0
- package/cli/commands/feature.js +259 -0
- package/cli/commands/hooks.js +163 -0
- package/cli/commands/init.js +189 -0
- package/cli/commands/log.js +199 -0
- package/cli/commands/plugin.js +230 -0
- package/cli/commands/score-card.js +203 -0
- package/cli/commands/status.js +269 -0
- package/cli/commands/sync.js +59 -0
- package/cli/commands/upgrade.js +150 -0
- package/cli/commands/validate.js +1259 -0
- package/cli/commands/watch.js +151 -0
- package/cli/index.js +46 -0
- package/cli/lib/ac-test-gate.js +89 -0
- package/cli/lib/activity-log.js +209 -0
- package/cli/lib/cli-error.js +183 -0
- package/cli/lib/constitution-lint.js +561 -0
- package/cli/lib/dev-quiz-grade.js +127 -0
- package/cli/lib/governance.js +78 -0
- package/cli/lib/hook-targets.js +167 -0
- package/cli/lib/i18n.js +375 -0
- package/cli/lib/knowledge-oracle.js +379 -0
- package/cli/lib/logger.js +203 -0
- package/cli/lib/module-card-lint.js +304 -0
- package/cli/lib/module-card-score.js +223 -0
- package/cli/lib/plugins.js +481 -0
- package/cli/lib/scanner.js +692 -0
- package/cli/lib/sync-core.js +232 -0
- package/cli/lib/sync-targets.js +84 -0
- package/cli/lib/templates.js +268 -0
- package/cli/lib/yaml-parser.js +203 -0
- package/commands/v.ba-critic.md +101 -0
- package/commands/v.ba-to-ptyc.md +71 -0
- package/commands/v.bugfix.md +86 -0
- package/commands/v.check.md +131 -0
- package/commands/v.constitute.md +87 -0
- package/commands/v.constitution.md +84 -0
- package/commands/v.fork.md +127 -0
- package/commands/v.help.md +73 -0
- package/commands/v.hotfix.md +200 -0
- package/commands/v.implement.md +92 -0
- package/commands/v.import-ba-docs.md +222 -0
- package/commands/v.metrics.md +74 -0
- package/commands/v.operations.md +70 -0
- package/commands/v.plan.md +78 -0
- package/commands/v.prototype.md +121 -0
- package/commands/v.quickfix.md +169 -0
- package/commands/v.retrospective.md +80 -0
- package/commands/v.review.md +78 -0
- package/commands/v.rewind.md +127 -0
- package/commands/v.specify.md +118 -0
- package/commands/v.sprint.md +75 -0
- package/commands/v.status.md +62 -0
- package/commands/v.sync.md +81 -0
- package/commands/v.test.md +67 -0
- package/commands/v.understand.md +112 -0
- package/package.json +65 -0
- package/skills/_shared/constitution-reader/SKILL.md +109 -0
- package/skills/_shared/constitution-reader/config.json +52 -0
- package/skills/_shared/constitution-reader/examples/good/b1-phase-output.md +48 -0
- package/skills/_shared/constitution-reader/gotchas.md +46 -0
- package/skills/_shared/context-reader/SKILL.md +111 -0
- package/skills/_shared/context-reader/config.json +54 -0
- package/skills/_shared/context-reader/examples/good/legacy-nodejs-output.md +35 -0
- package/skills/_shared/context-reader/gotchas.md +49 -0
- package/skills/_shared/ears-notation/SKILL.md +63 -0
- package/skills/_shared/ears-notation/config.json +55 -0
- package/skills/_shared/ears-notation/examples/good/plan-test-interpretation.md +29 -0
- package/skills/_shared/ears-notation/gotchas.md +43 -0
- package/skills/check/cross-validator/SKILL.md +206 -0
- package/skills/check/cross-validator/config.json +33 -0
- package/skills/check/cross-validator/examples/good/validation-report-pass-with-concerns.md +105 -0
- package/skills/check/cross-validator/gotchas.md +43 -0
- package/skills/implement/constitution-enforcer/SKILL.md +134 -0
- package/skills/implement/constitution-enforcer/config.json +16 -0
- package/skills/implement/constitution-enforcer/examples/bad/vague-report.md +42 -0
- package/skills/implement/constitution-enforcer/examples/good/compliance-report.md +57 -0
- package/skills/implement/constitution-enforcer/gotchas.md +26 -0
- package/skills/implement/constitution-enforcer/scripts/check-constitution.sh +88 -0
- package/skills/implement/no-go-zone-guard/SKILL.md +173 -0
- package/skills/implement/no-go-zone-guard/config.json +28 -0
- package/skills/implement/no-go-zone-guard/examples/good/adapter-workaround.md +46 -0
- package/skills/implement/no-go-zone-guard/gotchas.md +27 -0
- package/skills/implement/no-go-zone-guard/scripts/check-nogo-zones.sh +148 -0
- package/skills/implement/no-go-zone-guard/scripts/nogo-precommit.sh +96 -0
- package/skills/implement/tdd-driver/SKILL.md +159 -0
- package/skills/implement/tdd-driver/config.json +33 -0
- package/skills/implement/tdd-driver/examples/good/tdd-cycle-product-repo.md +81 -0
- package/skills/implement/tdd-driver/gotchas.md +34 -0
- package/skills/metrics/metrics-collector/SKILL.md +133 -0
- package/skills/metrics/metrics-collector/config.json +16 -0
- package/skills/metrics/metrics-collector/examples/bad/incomplete-report.md +48 -0
- package/skills/metrics/metrics-collector/examples/good/full-metrics-report.md +101 -0
- package/skills/metrics/metrics-collector/gotchas.md +26 -0
- package/skills/operations/incident-runbook/SKILL.md +167 -0
- package/skills/operations/incident-runbook/config.json +21 -0
- package/skills/operations/incident-runbook/examples/bad/vague-incident-report.md +48 -0
- package/skills/operations/incident-runbook/examples/good/p1-hotfix-response.md +119 -0
- package/skills/operations/incident-runbook/gotchas.md +26 -0
- package/skills/plan/architecture-designer/SKILL.md +228 -0
- package/skills/plan/architecture-designer/config.json +32 -0
- package/skills/plan/architecture-designer/examples/bad/vague-plan.md +62 -0
- package/skills/plan/architecture-designer/examples/good/expand-contract-migration.md +56 -0
- package/skills/plan/architecture-designer/examples/good/plan-structure.md +58 -0
- package/skills/plan/architecture-designer/gotchas.md +45 -0
- package/skills/plan/task-breakdown/SKILL.md +208 -0
- package/skills/plan/task-breakdown/config.json +26 -0
- package/skills/plan/task-breakdown/examples/bad/vague-tasks.md +77 -0
- package/skills/plan/task-breakdown/examples/good/spike-clarify-tasks.md +66 -0
- package/skills/plan/task-breakdown/examples/good/tasks-login-feature.md +111 -0
- package/skills/plan/task-breakdown/gotchas.md +39 -0
- package/skills/prototype/LOGIC.md +240 -0
- package/skills/prototype/SKILL.md +185 -0
- package/skills/prototype/UI.md +407 -0
- package/skills/prototype/config.json +104 -0
- package/skills/prototype/examples/bad/prototype-notes.md +68 -0
- package/skills/prototype/examples/good/prototype-notes-ui.md +109 -0
- package/skills/prototype/examples/good/prototype-notes.md +67 -0
- package/skills/prototype/gotchas.md +128 -0
- package/skills/prototype/scripts/check-flow-state.ps1 +112 -0
- package/skills/prototype/scripts/check-flow-state.sh +104 -0
- package/skills/prototype/scripts/check-prototype-cleanup.ps1 +124 -0
- package/skills/prototype/scripts/check-prototype-cleanup.sh +109 -0
- package/skills/prototype/scripts/check-prototype-notes.ps1 +107 -0
- package/skills/prototype/scripts/check-prototype-notes.sh +102 -0
- package/skills/review/adversarial-reviewer/SKILL.md +137 -0
- package/skills/review/adversarial-reviewer/config.json +32 -0
- package/skills/review/adversarial-reviewer/examples/good/review-report-template.md +56 -0
- package/skills/review/adversarial-reviewer/gotchas.md +46 -0
- package/skills/review/adversarial-reviewer/scripts/quick-security-scan.sh +52 -0
- package/skills/specify/ba-bpmn-doc-gen/SKILL.md +108 -0
- package/skills/specify/ba-bpmn-doc-gen/reference/reference-bpmn-generation.md +528 -0
- package/skills/specify/ba-bpmn-doc-gen/reference/reference-drawio-flowchart.md +466 -0
- package/skills/specify/ba-critic/SKILL.md +172 -0
- package/skills/specify/ba-critic/config.json +32 -0
- package/skills/specify/ba-critic/examples/good/critic-report-round1.md +51 -0
- package/skills/specify/ba-critic/gotchas.md +40 -0
- package/skills/specify/ba-critic/scripts/check-spec-quality.sh +72 -0
- package/skills/specify/ba-doc-generator/SKILL.md +102 -0
- package/skills/specify/ba-doc-generator/references/template-clevel.md +84 -0
- package/skills/specify/ba-doc-generator/references/template-compliance.md +83 -0
- package/skills/specify/ba-doc-generator/references/template-dev.md +138 -0
- package/skills/specify/ba-doc-generator/references/template-partner.md +167 -0
- package/skills/specify/ba-doc-generator/references/template-pm.md +92 -0
- package/skills/specify/ba-doc-generator/references/template-review.md +114 -0
- package/skills/specify/ba-doc-generator/references/template-tester.md +108 -0
- package/skills/specify/ba-doc-generator/references/template-user.md +98 -0
- package/skills/specify/bugfix-analyst/SKILL.md +296 -0
- package/skills/specify/bugfix-analyst/config.json +41 -0
- package/skills/specify/bugfix-analyst/examples/bad/common-mistakes.md +71 -0
- package/skills/specify/bugfix-analyst/examples/good/email-validation-bugfix.md +53 -0
- package/skills/specify/bugfix-analyst/gotchas.md +51 -0
- package/skills/specify/ears-writer/SKILL.md +129 -0
- package/skills/specify/ears-writer/config.json +20 -0
- package/skills/specify/ears-writer/examples/bad/common-mistakes.md +17 -0
- package/skills/specify/ears-writer/examples/good/login-requirements.md +41 -0
- package/skills/specify/ears-writer/gotchas.md +43 -0
- package/skills/specify/ears-writer/scripts/check-ears-compliance.sh +51 -0
- package/skills/test/test-case-generator/SKILL.md +161 -0
- package/skills/test/test-case-generator/config.json +33 -0
- package/skills/test/test-case-generator/examples/good/test-cases-login.md +104 -0
- package/skills/test/test-case-generator/gotchas.md +43 -0
- package/skills/understand/ba-docs-scanner/SKILL.md +239 -0
- package/skills/understand/ba-docs-scanner/config.json +47 -0
- package/skills/understand/ba-docs-scanner/examples/good/work-order-br-extract.md +28 -0
- package/skills/understand/ba-docs-scanner/gotchas.md +44 -0
- package/skills/understand/ba-docs-scanner/merge-rules.md +47 -0
- package/skills/understand/codebase-scanner/SKILL.md +260 -0
- package/skills/understand/codebase-scanner/config.json +56 -0
- package/skills/understand/codebase-scanner/examples/good/menu-module-output.md +44 -0
- package/skills/understand/codebase-scanner/gotchas.md +42 -0
- package/skills/understand/codebase-scanner/scripts/scan-project-structure.sh +64 -0
- package/templates/DESIGN.md +456 -0
- package/templates/agent-command-template.yaml +240 -0
- package/templates/agent-config-template.md +170 -0
- package/templates/agent-definition-template.md +145 -0
- package/templates/agent-metrics-template.md +150 -0
- package/templates/api-contract-template.md +72 -0
- package/templates/bugfix-report-template.md +195 -0
- package/templates/bugfix-spec-template.md +134 -0
- package/templates/code-review-report-template.md +119 -0
- package/templates/constitution-template.md +234 -0
- package/templates/context-template.md +94 -0
- package/templates/data-model-template.md +95 -0
- package/templates/decision-log-template.md +92 -0
- package/templates/flow-state-template.yaml +208 -0
- package/templates/github/workflows/v-flow-validate.yml +30 -0
- package/templates/knowledge/adr-template.md +70 -0
- package/templates/knowledge/api-contract-template.md +140 -0
- package/templates/knowledge/domain-glossary.md +29 -0
- package/templates/knowledge/golden-tests-readme.md +115 -0
- package/templates/knowledge/lessons-learned.md +41 -0
- package/templates/knowledge/patterns.md +103 -0
- package/templates/module-card/SKILL.md +85 -0
- package/templates/module-card/api-specs.md +96 -0
- package/templates/module-card/business-quiz.md +119 -0
- package/templates/module-card/cross-service.md +125 -0
- package/templates/module-card/db.md +85 -0
- package/templates/module-card/dev-quiz.md +62 -0
- package/templates/module-card/permissions.md +83 -0
- package/templates/module-card/state-diagram.md +64 -0
- package/templates/module-card/tech-context.md +90 -0
- package/templates/module-card/ui-flows.md +91 -0
- package/templates/module-card/use-cases.md +142 -0
- package/templates/module-template.yaml +161 -0
- package/templates/operations-report-template.md +108 -0
- package/templates/plan-template.md +308 -0
- package/templates/prototype-notes-template.md +116 -0
- package/templates/ptyc/PTYC.template.docx +0 -0
- package/templates/ptyc/ptyc.meta.example.yaml +44 -0
- package/templates/retrospective-report-template.md +136 -0
- package/templates/security-review-template.md +84 -0
- package/templates/session-template.md +167 -0
- package/templates/spec-review-log-template.md +75 -0
- package/templates/spec-template.md +229 -0
- package/templates/sprint-status-template.md +101 -0
- package/templates/tasks-template.md +275 -0
- package/templates/test-cases-template.md +124 -0
- package/templates/ux-checklist-template.md +79 -0
- package/templates/validation-report-template.md +125 -0
- package/templates/vflow-config-template.yaml +22 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: no-go-zone-guard
|
|
3
|
+
description: "Ngăn Implement Agent đụng vào No-Go Zones trong context.md. Skill này LUÔN ACTIVE trong Phase B.1 — kiểm tra TRƯỚC MỖI file edit."
|
|
4
|
+
trigger: "LUÔN ACTIVE trong B.1 — trước mỗi file edit"
|
|
5
|
+
phase: "B.1"
|
|
6
|
+
used_by:
|
|
7
|
+
- /v.implement
|
|
8
|
+
- /v.review
|
|
9
|
+
hooks:
|
|
10
|
+
pre_file_edit: "Kiểm tra file path against No-Go Zones"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# No-Go Zone Guard — Bảo Vệ Vùng Code Cấm
|
|
14
|
+
|
|
15
|
+
> ⚠️ Skill này **bắt buộc** trong B.1 — nhưng harness KHÔNG tự fire.
|
|
16
|
+
> Implement Agent PHẢI **tự chạy** `.v-flow/skills/implement/no-go-zone-guard/scripts/check-nogo-zones.sh <file>` TRƯỚC mỗi file edit (đã ghi trong `implement-agent.md` Bước 2). Muốn enforce cứng → wire vào git pre-commit / CI (xem `constitution-enforcer/SKILL.md → Wiring enforcement thật`).
|
|
17
|
+
>
|
|
18
|
+
> → Xem `gotchas.md` cho lỗi phổ biến khi xử lý No-Go.
|
|
19
|
+
> → Xem `examples/good/` cho workaround patterns.
|
|
20
|
+
> → Xem `config.json` để customize enforcement level.
|
|
21
|
+
> → `.v-flow/skills/implement/no-go-zone-guard/scripts/check-nogo-zones.sh <file>`: tự động phủ **Check 1/2** (path/dir), **Check 3** (import — advisory), **Check 5** (test→source). **Check 4** (config side-effect) vẫn cần agent rà thủ công.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Khi nào KHÔNG áp dụng
|
|
26
|
+
|
|
27
|
+
- Greenfield project (không có context.md → không có No-Go Zones)
|
|
28
|
+
- File mới hoàn toàn (không nằm trong No-Go directory)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Nguồn No-Go Zones
|
|
33
|
+
|
|
34
|
+
Đọc từ các nguồn theo thứ tự ưu tiên:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
1. .v-flow/context.md → §4 🚫 No-Go Zones ← PRIMARY
|
|
38
|
+
2. constitution.md → §7 No-Go Zones ← SECONDARY
|
|
39
|
+
3. tasks.md → "No-Go Check" per-task ← TASK-LEVEL
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3 Levels
|
|
45
|
+
|
|
46
|
+
| Level | Marker | Nghĩa | Action |
|
|
47
|
+
|-------|:------:|-------|--------|
|
|
48
|
+
| 🔴 **Strict** | `🔴 Cao` | Tuyệt đối cấm — production, audited, PCI | **BLOCK** — không ngoại lệ |
|
|
49
|
+
| 🟡 **Warning** | `🟡 Trung bình` | Nên tránh — nhiều service phụ thuộc | **WARN** — cần Tech Lead approval |
|
|
50
|
+
| 🟢 **Caution** | `🟢 Thấp` | Cẩn thận — legacy code, side effects unknown | **LOG** — ghi lý do vào _session.md |
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Kiểm Tra — Cái Gì Cần Check
|
|
55
|
+
|
|
56
|
+
> 💡 Đây là phần quan trọng nhất — **KHÔNG CHỈ KIỂM TRA FILE PATH**.
|
|
57
|
+
|
|
58
|
+
### Check 1: Direct File Match
|
|
59
|
+
```
|
|
60
|
+
File đang edit nằm trong No-Go Zone?
|
|
61
|
+
VD: routes/payment.js là No-Go → BLOCK
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Check 2: Parent Directory Match
|
|
65
|
+
```
|
|
66
|
+
File nằm trong directory là No-Go?
|
|
67
|
+
VD: No-Go = "routes/payment/" → routes/payment/webhook.js cũng BLOCK
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Check 3: New Import From No-Go
|
|
71
|
+
```
|
|
72
|
+
File mới import/require từ No-Go module?
|
|
73
|
+
VD: const auth = require('../middleware/auth') // auth.js là No-Go
|
|
74
|
+
→ Import READ-ONLY ok, nhưng MODIFY behavior → cần xem xét
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Check 4: Config Side-Effects
|
|
78
|
+
```
|
|
79
|
+
Sửa shared config (env, DB config) có ảnh hưởng No-Go modules?
|
|
80
|
+
VD: Thay đổi DB pool config → ảnh hưởng payment module
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Check 5: Test Files Tương Ứng
|
|
84
|
+
```
|
|
85
|
+
test/payment.test.js thuộc No-Go nếu routes/payment.js là No-Go?
|
|
86
|
+
→ CÓ. Test file của No-Go module = No-Go.
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Workaround Patterns
|
|
92
|
+
|
|
93
|
+
> 💡 Khi cần interact với No-Go module mà KHÔNG sửa nó.
|
|
94
|
+
|
|
95
|
+
### Pattern 1: Wrapper / Adapter
|
|
96
|
+
Tạo file mới wrap interface No-Go module:
|
|
97
|
+
```
|
|
98
|
+
// adapters/payment-adapter.js (NEW file — OK)
|
|
99
|
+
const payment = require('../no-go/payment'); // import OK
|
|
100
|
+
module.exports = {
|
|
101
|
+
getStatus: (id) => payment.checkStatus(id), // wrap, không modify
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
**Rule**: Adapter KHÔNG modify behavior — chỉ wrap hoặc extend.
|
|
105
|
+
|
|
106
|
+
### Pattern 2: Event Bus
|
|
107
|
+
Emit event thay vì gọi trực tiếp:
|
|
108
|
+
```
|
|
109
|
+
// Không gọi payment.process() trực tiếp
|
|
110
|
+
eventBus.emit('payment:requested', data);
|
|
111
|
+
// payment module listen event này (nếu nó đã support)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Pattern 3: Interface Segregation
|
|
115
|
+
Tạo interface, No-Go module implement nó. New code depend on interface, không direct dependency.
|
|
116
|
+
|
|
117
|
+
### Pattern 4: API Gateway
|
|
118
|
+
Gọi No-Go service qua HTTP API thay vì import trực tiếp (microservices pattern).
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Khi Phải Đụng No-Go Zone (Bất khả kháng)
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
1. DỪNG NGAY — không tự ý sửa
|
|
126
|
+
2. Ghi vào _session.md:
|
|
127
|
+
"⚠️ TASK-{N} requires editing No-Go Zone: {file}. Reason: {why}"
|
|
128
|
+
3. Set .flow-state.yaml: blocked = true, blocked_reason = "No-Go Zone conflict"
|
|
129
|
+
4. Chờ Tech Lead quyết định:
|
|
130
|
+
- Option A: Approve exception (ghi approval vào _session.md)
|
|
131
|
+
- Option B: Redesign approach (update plan.md)
|
|
132
|
+
- Option C: Scope out (update spec.md)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## No-Go Zone Types — Reference
|
|
138
|
+
|
|
139
|
+
| Loại | Ví dụ | Rủi ro | Workaround |
|
|
140
|
+
|------|-------|--------|-----------|
|
|
141
|
+
| Payment/Billing | `routes/payment.js`, `services/stripe.js` | PCI compliance | Adapter pattern |
|
|
142
|
+
| Auth/Identity | `middleware/auth.js`, `services/sso.js` | Cascading breakage | Interface segregation |
|
|
143
|
+
| Core Infrastructure | `db/pool.js`, `config/env.js` | System-wide impact | Environment variables |
|
|
144
|
+
| 3rd Party SDK | `lib/vendor-sdk.js` | Vendor-controlled | Wrapper pattern |
|
|
145
|
+
| Legacy Critical | `legacy/core-engine.js` | Unknown side effects | Event bus |
|
|
146
|
+
| Audited Code | `security/encryption.js` | Audit invalidation | Extend, don't modify |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Wiring — Cưỡng chế cứng qua git (batch gate)
|
|
151
|
+
|
|
152
|
+
`check-nogo-zones.sh` kiểm **một** file (agent gọi trước mỗi edit). `nogo-precommit.sh` chạy nó trên **toàn bộ git diff** → biến No-Go thành rào chắn thật, **không phụ thuộc agent nhớ**.
|
|
153
|
+
|
|
154
|
+
**Pre-commit hook** (`.git/hooks/pre-commit`, `chmod +x`):
|
|
155
|
+
```bash
|
|
156
|
+
#!/bin/bash
|
|
157
|
+
exec .v-flow/skills/implement/no-go-zone-guard/scripts/nogo-precommit.sh
|
|
158
|
+
```
|
|
159
|
+
→ chặn commit nếu chạm 🔴 Strict zone. Thêm `--strict-warn` để chặn cả 🟡.
|
|
160
|
+
|
|
161
|
+
**CI (GitHub Actions)** — chặn PR:
|
|
162
|
+
```yaml
|
|
163
|
+
- name: No-Go Zone gate
|
|
164
|
+
run: bash .v-flow/skills/implement/no-go-zone-guard/scripts/nogo-precommit.sh --base origin/${{ github.base_ref }} --strict-warn
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Exit: `0` sạch (hoặc chỉ 🟢 Low) · `1` chạm 🔴 (hoặc 🟡 khi `--strict-warn`). Mặc định: staged files. `--base <ref>`: so với base ref (CI/PR).
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Gotchas
|
|
172
|
+
|
|
173
|
+
→ Xem `gotchas.md` cho lỗi phổ biến — cập nhật liên tục.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_note": "setup_questions là PROMPT. Đáp án resolve persist vào .v-flow/config.yaml (nogo_strict_mode, nogo_source). Thiếu → dùng default dưới đây.",
|
|
3
|
+
"answers_persisted_to": ".v-flow/config.yaml",
|
|
4
|
+
"setup_questions": [
|
|
5
|
+
{
|
|
6
|
+
"id": "strict_mode",
|
|
7
|
+
"question": "No-Go Zone enforcement level?",
|
|
8
|
+
"options": ["strict", "warning", "log"],
|
|
9
|
+
"default": "strict",
|
|
10
|
+
"description": "strict = BLOCK mọi vi phạm. warning = WARN nhưng cho phép nếu có approval. log = chỉ ghi log."
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "nogo_source",
|
|
14
|
+
"question": "No-Go Zones đọc từ đâu?",
|
|
15
|
+
"options": ["context.md", "constitution.md", "both"],
|
|
16
|
+
"default": "both"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"hooks": {
|
|
20
|
+
"pre_file_edit": "Kiểm tra file path against No-Go Zones list trước mỗi edit",
|
|
21
|
+
"pre_command": "Validate scope — command không ảnh hưởng No-Go Zone files"
|
|
22
|
+
},
|
|
23
|
+
"memory": {
|
|
24
|
+
"file": "nogo-violations.log",
|
|
25
|
+
"format": "[date] | [feature] | [task] | [file_attempted] | [nogo_zone] | [action_taken]",
|
|
26
|
+
"purpose": "Track violations — giúp identify patterns lặp lại"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Good Example — Adapter Pattern cho No-Go Zone
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
- No-Go Zone: `routes/payment.js` (PCI compliance — 🔴 Strict)
|
|
5
|
+
- Task: T-006 cần lấy payment status để hiển thị trên product page
|
|
6
|
+
- Problem: Cần gọi payment nhưng KHÔNG ĐƯỢC sửa payment module
|
|
7
|
+
|
|
8
|
+
## Workaround: Adapter Pattern
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
// ✅ MỚI: adapters/payment-adapter.js (file mới — OK)
|
|
12
|
+
const paymentService = require('../routes/payment'); // import OK, không sửa
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Adapter cho payment module (No-Go Zone)
|
|
16
|
+
* KHÔNG modify behavior — chỉ wrap interface cần thiết
|
|
17
|
+
* Ref: T-006, No-Go: routes/payment.js
|
|
18
|
+
*/
|
|
19
|
+
module.exports = {
|
|
20
|
+
// Wrap method hiện có — pass through, không modify
|
|
21
|
+
getStatus: async (orderId) => {
|
|
22
|
+
return paymentService.checkPaymentStatus(orderId);
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
// Format output cho product page — logic MỚI ở adapter, KHÔNG ở payment
|
|
26
|
+
getStatusForDisplay: async (orderId) => {
|
|
27
|
+
const status = await paymentService.checkPaymentStatus(orderId);
|
|
28
|
+
return {
|
|
29
|
+
isPaid: status.code === 'COMPLETED',
|
|
30
|
+
label: STATUS_LABELS[status.code] || 'Unknown',
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const STATUS_LABELS = {
|
|
36
|
+
COMPLETED: 'Đã thanh toán',
|
|
37
|
+
PENDING: 'Đang xử lý',
|
|
38
|
+
FAILED: 'Thất bại',
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Rules Applied
|
|
43
|
+
- ✅ `routes/payment.js` KHÔNG bị sửa
|
|
44
|
+
- ✅ Adapter chỉ WRAP — không modify return value của original
|
|
45
|
+
- ✅ Logic mới (getStatusForDisplay) nằm ở adapter, không ở payment
|
|
46
|
+
- ✅ Comment ghi rõ: No-Go reference + Task ID
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Gotchas — No-Go Zone Guard
|
|
2
|
+
|
|
3
|
+
> Cập nhật liên tục khi Agent gặp edge case mới.
|
|
4
|
+
> Mỗi lỗi lặp lại 2 lần → BẮT BUỘC thêm vào đây.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Anti-Patterns
|
|
9
|
+
|
|
10
|
+
1. ❌ **"Chỉ refactor nhỏ thôi"** — Không có refactor nhỏ trong No-Go Zone.
|
|
11
|
+
- **Thực tế**: Rename variable trong payment.js → 3 services import nó break.
|
|
12
|
+
|
|
13
|
+
2. ❌ **Quên test files** — `test/payment.test.js` cũng thuộc No-Go.
|
|
14
|
+
- **Lý do**: Sửa test → false confidence → miss regression.
|
|
15
|
+
|
|
16
|
+
3. ❌ **Import chain** — File A import File B (No-Go) → sửa export interface B → A break.
|
|
17
|
+
- **Check**: `grep -r "require.*payment\|import.*payment" src/`
|
|
18
|
+
|
|
19
|
+
4. ❌ **Config changes** — Sửa `.env` hoặc `config.js` có thể ảnh hưởng No-Go modules.
|
|
20
|
+
- **VD**: `DB_POOL_SIZE=5→10` → payment module connection behavior thay đổi.
|
|
21
|
+
|
|
22
|
+
5. ❌ **Wrapper modify behavior** — Adapter pattern nhưng thay đổi return value.
|
|
23
|
+
- **Rule**: Adapter chỉ WRAP — pass through data unchanged.
|
|
24
|
+
|
|
25
|
+
6. ✅ **Hỏi trước khi sửa** — Khi BẮT BUỘC đụng No-Go → DỪNG, ghi _session.md, chờ Tech Lead.
|
|
26
|
+
|
|
27
|
+
7. ✅ **Document workaround** — Khi dùng adapter → ghi rõ TẠI SAO trong code comment.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# check-nogo-zones.sh — Kiểm tra file có nằm trong No-Go Zone
|
|
3
|
+
# Usage: ./check-nogo-zones.sh <file_path> [context.md_path]
|
|
4
|
+
#
|
|
5
|
+
# Exit codes:
|
|
6
|
+
# 0 = File OK (không trong No-Go Zone; hoặc chỉ khớp mức 🟢 Thấp → LOG, được phép)
|
|
7
|
+
# 1 = File BLOCKED (🔴 Strict — HOẶC zone không đánh mức → mặc định Strict, fail-safe)
|
|
8
|
+
# 2 = File WARNING (🟡 cần Tech Lead approval)
|
|
9
|
+
|
|
10
|
+
FILE="$1"
|
|
11
|
+
CONTEXT="${2:-.v-flow/context.md}"
|
|
12
|
+
|
|
13
|
+
if [ -z "$FILE" ]; then
|
|
14
|
+
echo "Usage: $0 <file_path> [context.md_path]"
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
if [ ! -f "$CONTEXT" ]; then
|
|
19
|
+
echo "✅ No context.md found — greenfield project, no No-Go Zones"
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
# Extract No-Go Zones section from context.md
|
|
24
|
+
# Dùng `sed '$d'` (POSIX) thay cho `head -n -1` (GNU-only) — trên macOS/BSD `head -n -1`
|
|
25
|
+
# lỗi → section rỗng → guard FAIL OPEN (báo PASS cho file cấm). Đây là bug an toàn.
|
|
26
|
+
NOGO_SECTION=$(sed -n '/No-Go Zones/,/^##[^#]/p' "$CONTEXT" | sed '$d')
|
|
27
|
+
|
|
28
|
+
if [ -z "$NOGO_SECTION" ]; then
|
|
29
|
+
echo "✅ No No-Go Zones defined in context.md"
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# path_matches FILE ZONE → 0 nếu FILE LÀ zone, NẰM TRONG zone (dir), hoặc zone là 1
|
|
34
|
+
# path-segment trọn vẹn của FILE. Dùng so khớp theo ranh giới path — KHÔNG substring
|
|
35
|
+
# (tránh false positive: zone `auth.js` KHÔNG còn chặn nhầm `oauth.js`).
|
|
36
|
+
path_matches() {
|
|
37
|
+
local file="$1" zone="$2"
|
|
38
|
+
zone="${zone#./}"; zone="${zone%/}"
|
|
39
|
+
case "$file" in
|
|
40
|
+
"$zone") return 0 ;; # khớp path tuyệt đối
|
|
41
|
+
"$zone"/*) return 0 ;; # file nằm trong thư mục zone
|
|
42
|
+
*/"$zone") return 0 ;; # zone là segment cuối (file/dir)
|
|
43
|
+
*/"$zone"/*) return 0 ;; # zone là segment giữa đường dẫn
|
|
44
|
+
esac
|
|
45
|
+
return 1
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Check 5: test file của 1 module No-Go cũng là No-Go.
|
|
49
|
+
# Map ngược test file → source: test/payment.test.js → payment.js ; foo.spec.ts → foo.ts
|
|
50
|
+
src_of_test() {
|
|
51
|
+
echo "$1" | sed -E 's#(^|/)(__tests__|__test__|tests?|spec)/##; s#\.(test|spec)\.([A-Za-z]+)$#.\2#'
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# is_test_of FILE ZONE → 0 nếu FILE là test file có basename source == basename zone.
|
|
55
|
+
# Heuristic theo basename (test path không mang thư mục source) — over-block an toàn cho zone.
|
|
56
|
+
is_test_of() {
|
|
57
|
+
local file="$1" zone="$2" src
|
|
58
|
+
case "$zone" in */) return 1 ;; esac # zone là thư mục, không phải file → bỏ
|
|
59
|
+
src=$(src_of_test "$file")
|
|
60
|
+
[ "$src" = "$file" ] && return 1 # không phải test file
|
|
61
|
+
[ "$(basename "$src")" = "$(basename "$zone")" ] && return 0
|
|
62
|
+
return 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Phân loại từng zone theo marker mức độ TRÊN DÒNG chứa nó. FAIL-SAFE: một path trong
|
|
66
|
+
# backtick KHÔNG có marker (hoặc đánh 🔴/Cao/strict/critical) → STRICT (block). CHỈ hạ cấp
|
|
67
|
+
# khi có marker rõ ràng: 🟡/Trung bình/warning → WARN; 🟢/Thấp → LOG. Tránh để vùng cấm
|
|
68
|
+
# lọt qua chỉ vì tác giả quên đánh dấu mức độ (trước đây không marker = exit 0 im lặng).
|
|
69
|
+
STRICT_ZONES=""; WARN_ZONES=""; LOG_ZONES=""
|
|
70
|
+
while IFS= read -r line; do
|
|
71
|
+
zones=$(printf '%s\n' "$line" | grep -oE '`[^`]+`' | tr -d '`')
|
|
72
|
+
[ -z "$zones" ] && continue
|
|
73
|
+
if printf '%s' "$line" | grep -qi "🟢\|Thấp"; then
|
|
74
|
+
LOG_ZONES="$LOG_ZONES
|
|
75
|
+
$zones"
|
|
76
|
+
elif printf '%s' "$line" | grep -qi "🟡\|Trung bình\|warning"; then
|
|
77
|
+
WARN_ZONES="$WARN_ZONES
|
|
78
|
+
$zones"
|
|
79
|
+
else
|
|
80
|
+
STRICT_ZONES="$STRICT_ZONES
|
|
81
|
+
$zones"
|
|
82
|
+
fi
|
|
83
|
+
done <<EOF
|
|
84
|
+
$NOGO_SECTION
|
|
85
|
+
EOF
|
|
86
|
+
|
|
87
|
+
# Check 1/2/5 — Strict (🔴) → BLOCK
|
|
88
|
+
while IFS= read -r zone; do
|
|
89
|
+
[ -z "$zone" ] && continue
|
|
90
|
+
if path_matches "$FILE" "$zone"; then
|
|
91
|
+
echo "🚫 BLOCKED: '$FILE' matches Strict No-Go Zone: '$zone'"
|
|
92
|
+
echo " Action: STOP — cannot edit this file"
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
if is_test_of "$FILE" "$zone"; then
|
|
96
|
+
echo "🚫 BLOCKED: '$FILE' là test của module No-Go '$zone' (Check 5)"
|
|
97
|
+
echo " Action: STOP — test file của module No-Go cũng là No-Go"
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
done <<EOF
|
|
101
|
+
$STRICT_ZONES
|
|
102
|
+
EOF
|
|
103
|
+
|
|
104
|
+
# Check 1/2/5 — Warning (🟡) → cần Tech Lead approval
|
|
105
|
+
while IFS= read -r zone; do
|
|
106
|
+
[ -z "$zone" ] && continue
|
|
107
|
+
if path_matches "$FILE" "$zone" || is_test_of "$FILE" "$zone"; then
|
|
108
|
+
echo "⚠️ WARNING: '$FILE' matches Warning No-Go Zone: '$zone'"
|
|
109
|
+
echo " Action: Needs Tech Lead approval before editing"
|
|
110
|
+
exit 2
|
|
111
|
+
fi
|
|
112
|
+
done <<EOF
|
|
113
|
+
$WARN_ZONES
|
|
114
|
+
EOF
|
|
115
|
+
|
|
116
|
+
# 🟢 Thấp → LOG (được phép, chỉ ghi nhận — KHÔNG block, KHÔNG cần duyệt)
|
|
117
|
+
while IFS= read -r zone; do
|
|
118
|
+
[ -z "$zone" ] && continue
|
|
119
|
+
if path_matches "$FILE" "$zone" || is_test_of "$FILE" "$zone"; then
|
|
120
|
+
echo "📝 LOG: '$FILE' thuộc No-Go Zone mức Thấp (🟢): '$zone' — được phép sửa, đã ghi nhận."
|
|
121
|
+
exit 0
|
|
122
|
+
fi
|
|
123
|
+
done <<EOF
|
|
124
|
+
$LOG_ZONES
|
|
125
|
+
EOF
|
|
126
|
+
|
|
127
|
+
# Check 3 (advisory) — file có import/require module No-Go không?
|
|
128
|
+
if [ -f "$FILE" ] && [ -n "$STRICT_ZONES" ]; then
|
|
129
|
+
IMPORTED=""
|
|
130
|
+
while IFS= read -r zone; do
|
|
131
|
+
[ -z "$zone" ] && continue
|
|
132
|
+
base=$(basename "$zone"); base="${base%.*}"
|
|
133
|
+
[ -z "$base" ] && continue
|
|
134
|
+
if grep -Eq "(require|import|from)[^A-Za-z0-9_]+['\"][^'\"]*${base}" "$FILE" 2>/dev/null; then
|
|
135
|
+
IMPORTED="$IMPORTED $zone"
|
|
136
|
+
fi
|
|
137
|
+
done <<EOF
|
|
138
|
+
$STRICT_ZONES
|
|
139
|
+
EOF
|
|
140
|
+
if [ -n "$IMPORTED" ]; then
|
|
141
|
+
echo "ℹ️ NOTE: '$FILE' import module No-Go:$IMPORTED"
|
|
142
|
+
echo " Import READ-ONLY OK — KHÔNG sửa behavior module No-Go, chỉ wrap/adapter."
|
|
143
|
+
echo " (Check 4 — config side-effect — cần agent tự rà thủ công.)"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
echo "✅ '$FILE' is NOT in any No-Go Zone"
|
|
148
|
+
exit 0
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# nogo-precommit.sh — Batch No-Go gate over the git diff (pre-commit / CI).
|
|
3
|
+
#
|
|
4
|
+
# Wraps check-nogo-zones.sh across every changed file so a commit/PR that
|
|
5
|
+
# touches a 🔴 Strict No-Go Zone is BLOCKED mechanically — not left to the
|
|
6
|
+
# agent reading context.md and "remembering". This is the file-path enforcement
|
|
7
|
+
# leg that turns No-Go from documentation into a guard rail.
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# nogo-precommit.sh # staged files (default — pre-commit)
|
|
11
|
+
# nogo-precommit.sh --base origin/main # files changed vs a base ref (CI/PR)
|
|
12
|
+
# nogo-precommit.sh --strict-warn # treat 🟡 Warning zones as blocking too
|
|
13
|
+
# nogo-precommit.sh --context path/to/context.md
|
|
14
|
+
#
|
|
15
|
+
# Exit 0 = clean (or only 🟢 Low / advisory).
|
|
16
|
+
# Exit 1 = a 🔴 Strict zone was touched (or 🟡 Warning under --strict-warn),
|
|
17
|
+
# or the guard is misconfigured (fail-safe: block rather than allow).
|
|
18
|
+
|
|
19
|
+
set -u
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
CHECK="$SCRIPT_DIR/check-nogo-zones.sh"
|
|
23
|
+
|
|
24
|
+
BASE=""
|
|
25
|
+
STRICT_WARN=0
|
|
26
|
+
CONTEXT=".v-flow/context.md"
|
|
27
|
+
|
|
28
|
+
while [ $# -gt 0 ]; do
|
|
29
|
+
case "$1" in
|
|
30
|
+
--base) BASE="$2"; shift 2 ;;
|
|
31
|
+
--strict-warn) STRICT_WARN=1; shift ;;
|
|
32
|
+
--context) CONTEXT="$2"; shift 2 ;;
|
|
33
|
+
-h|--help) sed -n '2,20p' "$0"; exit 0 ;;
|
|
34
|
+
*) echo "Unknown arg: $1"; exit 1 ;;
|
|
35
|
+
esac
|
|
36
|
+
done
|
|
37
|
+
|
|
38
|
+
if [ ! -f "$CHECK" ]; then
|
|
39
|
+
echo "🚫 No-Go guard misconfigured: not found: $CHECK"
|
|
40
|
+
exit 1 # fail-safe — block rather than silently allow
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
44
|
+
echo "✅ Not a git repo — No-Go batch gate skipped"
|
|
45
|
+
exit 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Determine the changed-file list.
|
|
49
|
+
if [ -n "$BASE" ]; then
|
|
50
|
+
FILES=$(git diff --name-only "$BASE"...HEAD 2>/dev/null || git diff --name-only "$BASE" HEAD)
|
|
51
|
+
else
|
|
52
|
+
FILES=$(git diff --cached --name-only)
|
|
53
|
+
[ -z "$FILES" ] && FILES=$(git diff --name-only HEAD) # manual run convenience
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ -z "$FILES" ]; then
|
|
57
|
+
echo "✅ No changed files — No-Go gate clean"
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
BLOCKED=""
|
|
62
|
+
WARNED=""
|
|
63
|
+
|
|
64
|
+
while IFS= read -r file; do
|
|
65
|
+
[ -z "$file" ] && continue
|
|
66
|
+
out=$(bash "$CHECK" "$file" "$CONTEXT")
|
|
67
|
+
code=$?
|
|
68
|
+
case "$code" in
|
|
69
|
+
1) BLOCKED="$BLOCKED\n $file" ; echo "$out" ;;
|
|
70
|
+
2) WARNED="$WARNED\n $file" ; echo "$out" ;;
|
|
71
|
+
esac
|
|
72
|
+
done <<EOF
|
|
73
|
+
$FILES
|
|
74
|
+
EOF
|
|
75
|
+
|
|
76
|
+
echo ""
|
|
77
|
+
echo "── No-Go Batch Gate ──"
|
|
78
|
+
|
|
79
|
+
if [ -n "$BLOCKED" ]; then
|
|
80
|
+
echo -e "🚫 BLOCKED — changed files in 🔴 Strict No-Go Zone:$BLOCKED"
|
|
81
|
+
echo " Commit/PR rejected. Move the change out of the zone, or get Tech Lead sign-off + update context.md."
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
if [ -n "$WARNED" ]; then
|
|
86
|
+
echo -e "⚠️ WARNING — changed files in 🟡 No-Go Zone (cần Tech Lead duyệt):$WARNED"
|
|
87
|
+
if [ "$STRICT_WARN" -eq 1 ]; then
|
|
88
|
+
echo " --strict-warn: treated as blocking."
|
|
89
|
+
exit 1
|
|
90
|
+
fi
|
|
91
|
+
echo " Advisory (không chặn). Dùng --strict-warn để chặn ở CI."
|
|
92
|
+
exit 0
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
echo "✅ No changed file touches a Strict/Warning No-Go Zone"
|
|
96
|
+
exit 0
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tdd-driver
|
|
3
|
+
description: "Hướng dẫn Implement Agent tuân thủ TDD (Red-Green-Refactor) khi implement tasks. Agent PHẢI đọc skill này trước khi bắt đầu bất kỳ TASK nào."
|
|
4
|
+
trigger: "Khi bắt đầu implement task từ tasks.md"
|
|
5
|
+
phase: "B.1"
|
|
6
|
+
used_by:
|
|
7
|
+
- /v.implement
|
|
8
|
+
hooks:
|
|
9
|
+
pre_implement: "Map TC-xxx từ test-cases.md cho TASK hiện tại"
|
|
10
|
+
post_implement: "Chạy full test suite, verify không regression"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# TDD Driver — Implement Đúng Quy Trình
|
|
14
|
+
|
|
15
|
+
> ⚠️ Đây là **Skill bắt buộc** cho Implement Agent.
|
|
16
|
+
> Đọc trước khi implement. TDD không phải suggestion — đây là RULE.
|
|
17
|
+
>
|
|
18
|
+
> → Xem `gotchas.md` cho lỗi phổ biến khi làm TDD.
|
|
19
|
+
> → Xem `examples/good/` cho mẫu TDD cycle đúng chuẩn.
|
|
20
|
+
> → Xem `config.json` để customize test framework, coverage target.
|
|
21
|
+
> → Xem `scripts/` cho automation (nếu có).
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Iron Law — Không code production khi chưa có test FAIL trước
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
KHÔNG VIẾT CODE PRODUCTION KHI CHƯA CÓ MỘT TEST ĐANG FAIL.
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Lỡ viết code TRƯỚC test → **xóa code đó, làm lại từ test**. Không giữ "để tham khảo", không "chỉnh lại trong lúc viết test" (đó vẫn là test-after). Lý do cốt lõi: **nếu không tận mắt thấy test FAIL, bạn không biết nó có thực sự kiểm đúng thứ cần kiểm** — test viết sau code thường pass ngay và chứng minh số 0.
|
|
32
|
+
|
|
33
|
+
> ⚠️ Đây là chỗ agent hay **tự ngụy biện để bỏ qua**. Gặp ý nghĩ "thôi lần này bỏ TDD" = tín hiệu DỪNG, quay lại viết test trước. Bảng dưới đập lại từng cái:
|
|
34
|
+
|
|
35
|
+
| Ngụy biện | Sự thật |
|
|
36
|
+
|-----------|---------|
|
|
37
|
+
| "Đơn giản quá, khỏi test" | Code đơn giản vẫn hỏng. Test mất 30 giây. |
|
|
38
|
+
| "Test sau cũng vậy thôi" | Test-after = "code này làm gì?"; test-first = "code này NÊN làm gì?". Test-after thiên lệch theo cái đã viết. |
|
|
39
|
+
| "Tôi test tay rồi" | Tay = ad-hoc, không tái chạy được, không có dấu vết. |
|
|
40
|
+
| "Xóa mấy giờ code phí lắm" | Sunk cost. Giữ code chưa được test = nợ kỹ thuật. |
|
|
41
|
+
| "Giữ lại tham khảo, viết test trước" | Bạn sẽ "phỏng theo" nó → vẫn là test-after. Xóa là xóa. |
|
|
42
|
+
| "Test khó viết quá" | Khó test = thiết kế đang coupling/khó dùng. Nghe theo test → tách interface/DI. |
|
|
43
|
+
| "TDD cứng nhắc, tôi đang thực dụng" | TDD MỚI là thực dụng: bắt bug trước commit, chặn regression, refactor tự do. |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Khi nào KHÔNG áp dụng strict TDD
|
|
48
|
+
|
|
49
|
+
- Tạo file config/constant (không có logic → không cần test trước)
|
|
50
|
+
- Chạy migration/DDL (test ở integration level, không unit)
|
|
51
|
+
- Viết documentation, comments
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Đặc Thù Và Quy Ước
|
|
56
|
+
|
|
57
|
+
> 💡 Phần này chứa thông tin Agent thường bỏ sót hoặc làm sai.
|
|
58
|
+
|
|
59
|
+
### 1. Nguồn test cases — quan hệ TC-xxx ↔ TDD block
|
|
60
|
+
|
|
61
|
+
> 🔑 Hai tầng **bổ sung nhau**, KHÔNG mâu thuẫn. Đừng đọc "không tự nghĩ test" thành "không được gõ test".
|
|
62
|
+
|
|
63
|
+
| Tầng | Ở đâu | Ai tạo | Vai trò |
|
|
64
|
+
|------|-------|--------|---------|
|
|
65
|
+
| `TC-xxx` | `test-cases.md` (B.0b) | Test Agent | Catalog **ý đồ test chính thức** (scenario), trace tới AC/REQ |
|
|
66
|
+
| TDD block | trong task ở `tasks.md` | Plan Agent (provisional) | Checklist Red→Green để Implement Agent **viết code test** hiện thực TC |
|
|
67
|
+
|
|
68
|
+
**Quy tắc:**
|
|
69
|
+
- "**KHÔNG tự nghĩ test mới**" = KHÔNG bịa scenario/ý đồ nằm ngoài spec/AC. **CÓ viết code test** — đó chính là việc của TDD.
|
|
70
|
+
- Task **có `TC-xxx`** → hiện thực đúng các TC đó (theo TDD block).
|
|
71
|
+
- Task **chưa có `TC-xxx` nhưng có TDD block** (provisional — Test Agent chạy song song B.0b) → **VẪN implement**: viết test theo TDD block (bám `Done khi`/AC), và ghi `_session.md`: `T-{N}: cần TC backfill ở R.0` để Test Agent đối soát sau. **KHÔNG hard-stop.**
|
|
72
|
+
- Chỉ **DỪNG (blocked)** khi task **không có CẢ `TC-xxx` LẪN TDD block VÀ không có AC** để bám → ghi `_session.md`: `T-{N} blocked — không có test spec lẫn AC`.
|
|
73
|
+
|
|
74
|
+
### 2. Concern resolution trong TDD cycle
|
|
75
|
+
- Đọc `_session.md` → tìm W-xxx concerns assigned cho task hiện tại
|
|
76
|
+
- Viết test cho concern scenario TRƯỚC khi implement fix
|
|
77
|
+
- Ghi kết quả: `W-xxx: Resolved — [mô tả fix]` vào `_session.md`
|
|
78
|
+
|
|
79
|
+
### 3. Test naming convention
|
|
80
|
+
- **Pattern**: `should_<expected_behavior>_when_<condition>`
|
|
81
|
+
- VD: `should_return_404_when_product_not_found`
|
|
82
|
+
- KHÔNG: `test1`, `testLogin`, `it_works`
|
|
83
|
+
|
|
84
|
+
### 4. Mocking strategy
|
|
85
|
+
- Mock **external dependencies** (DB, API, file system) trong unit tests
|
|
86
|
+
- KHÔNG mock module đang test (test real behavior)
|
|
87
|
+
- Document mock behavior trong test file header comment
|
|
88
|
+
- Đọc `config.json → test_framework` để biết mock library phù hợp
|
|
89
|
+
- **Test anti-patterns — TRÁNH** (test phải kiểm hành vi THẬT, không kiểm hành vi của mock):
|
|
90
|
+
- ❌ **Assert lên mock** (vd `getByTestId('sidebar-mock')`) → chỉ chứng minh mock tồn tại. Sửa: test component thật / assert lên `role`/hành vi thật.
|
|
91
|
+
- ❌ **Method test-only trong class production** (vd `destroy()` chỉ test gọi) → đẩy sang `test-utils/`, đừng làm bẩn production (YAGNI).
|
|
92
|
+
- ❌ **Mock khi chưa hiểu dependency** → mock nuốt mất side-effect mà test phụ thuộc. Chạy test với impl thật TRƯỚC, hiểu nó cần gì, rồi mock ở **tầng thấp nhất** (cái chậm/external), không mock hàm cấp cao test đang dựa vào.
|
|
93
|
+
- ❌ **Mock thiếu field** → mirror ĐẦY ĐỦ cấu trúc API thật, không chỉ field test này dùng (downstream đọc field thiếu → fail âm thầm).
|
|
94
|
+
|
|
95
|
+
### 5. V-Flow Integration Points
|
|
96
|
+
- **test-cases.md** (B.0b) → nguồn TC. KHÔNG tự nghĩ TC mới
|
|
97
|
+
- **plan.md** (B.0a) → architecture cần follow khi implement
|
|
98
|
+
- **constitution.md** → naming convention, patterns
|
|
99
|
+
- **_session.md** → ghi trace mỗi TDD cycle completion
|
|
100
|
+
- **No-Go Zone Guard** → cross-check TRƯỚC khi tạo file mới
|
|
101
|
+
|
|
102
|
+
### 6. Coverage Tracking
|
|
103
|
+
- Đọc target từ `.v-flow/config.yaml → coverage_target` (đáp án setup đã resolve); thiếu file → fallback default `config.json` = 80%
|
|
104
|
+
- Sau mỗi task: verify coverage ≥ target (gate này nằm ở `implement-agent.md` Bước 4)
|
|
105
|
+
- Nếu dưới target → viết thêm tests cho untested branches
|
|
106
|
+
- Ghi vào `tdd-history.log`: task, tests written, coverage delta
|
|
107
|
+
|
|
108
|
+
> ⚠️ `hooks: pre_implement/post_implement` ở frontmatter chỉ là **ý định** — harness KHÔNG tự fire. Implement Agent tự thực hiện trong quy trình B.1.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Red-Green-Refactor — Signals Nhận Biết
|
|
113
|
+
|
|
114
|
+
| Phase | Signal đúng | Signal sai |
|
|
115
|
+
|-------|------------|-----------|
|
|
116
|
+
| 🔴 **RED** | Test FAIL với expected reason | Test FAIL vì syntax error |
|
|
117
|
+
| 🔴 **RED** | Test FAIL vì function chưa tồn tại | Test PASS ngay → test sai |
|
|
118
|
+
| 🟢 **GREEN** | Test PASS sau khi viết code tối thiểu | Test PASS nhưng code quá complex |
|
|
119
|
+
| 🟢 **GREEN** | ALL tests pass (cũ + mới) | Chỉ test mới pass, test cũ break |
|
|
120
|
+
| 🔵 **REFACTOR** | Code cleaner, tests vẫn pass | Tests break → undo refactor |
|
|
121
|
+
| 🔵 **REFACTOR** | Naming/structure theo constitution | Thêm feature mới (không phải refactor) |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Per-Task Verification Signals
|
|
126
|
+
|
|
127
|
+
Agent tự verify trước khi chuyển task. Nếu BẤT KỲ signal nào ❌ → không chuyển task:
|
|
128
|
+
|
|
129
|
+
| Signal | Verify bằng cách | Nếu fail |
|
|
130
|
+
|--------|------------------|----------|
|
|
131
|
+
| Spec-fit (đúng & đủ) | Diff task khớp ĐÚNG `AC-NN`/`TC-xx` của task — **không thiếu** (đủ AC) **và không thừa** (không thêm field/flag/endpoint/abstraction không ai yêu cầu) | Thiếu → bổ sung; Thừa → gỡ bỏ (over-build vi phạm YAGNI) |
|
|
132
|
+
| TC mapped | Grep TC-xxx trong test-cases.md cho TASK hiện tại | Có TDD block/AC → vẫn code, log "TC backfill R.0". Không có gì để bám → DỪNG, báo Test Agent |
|
|
133
|
+
| Test wrote first | Git diff: test file created TRƯỚC impl file | Nếu ngược → commit history sai |
|
|
134
|
+
| Red confirmed | Test output showed FAIL trước khi viết impl | Nếu pass ngay → test sai, fix test |
|
|
135
|
+
| Green confirmed | ALL tests pass (cũ + mới) | Nếu test cũ break → regression |
|
|
136
|
+
| Refactored | Code follows constitution naming/patterns | Nếu skip → tech debt |
|
|
137
|
+
| No-Go safe | File list không overlap No-Go Zones | Nếu overlap → BLOCK |
|
|
138
|
+
| Concerns | W-xxx resolved nếu có | Nếu skip → R.1 sẽ reject |
|
|
139
|
+
| Trace logged | _session.md có entry cho task | Nếu thiếu → audit trail mất |
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Edge Cases
|
|
144
|
+
|
|
145
|
+
### Test quá khó viết
|
|
146
|
+
→ **Signal**: Design problem. Tightly coupled code = hard to test.
|
|
147
|
+
→ **Action**: Ghi vào `_session.md`, suggest refactor approach. Viết simplest possible test.
|
|
148
|
+
|
|
149
|
+
### External dependency không mock được
|
|
150
|
+
→ **Action**: Tạo interface/adapter, mock interface. Test real implementation ở integration level.
|
|
151
|
+
|
|
152
|
+
### Task quá lớn cho 1 TDD cycle
|
|
153
|
+
→ **Action**: Split sub-tasks. Mỗi sub-task = 1 TDD cycle. Update `tasks.md`.
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Gotchas
|
|
158
|
+
|
|
159
|
+
→ Xem `gotchas.md` để tránh lỗi phổ biến — cập nhật liên tục.
|