@torus-engineering/tas-kit 1.10.0 → 1.12.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/.tas/README.md +70 -70
- package/{.claude → .tas/_platform/claude-code}/settings.json +0 -12
- package/{.claude → .tas/_platform}/hooks/code-quality.js +1 -1
- package/{.claude → .tas/_platform}/hooks/session-end.js +20 -25
- package/.tas/commands/ado-create.md +28 -0
- package/.tas/commands/ado-delete.md +22 -0
- package/.tas/commands/ado-get.md +20 -0
- package/.tas/commands/ado-status.md +18 -0
- package/.tas/commands/ado-update.md +27 -0
- package/.tas/commands/tas-adr.md +33 -0
- package/.tas/commands/tas-apitest-plan.md +173 -0
- package/.tas/commands/tas-apitest.md +143 -0
- package/.tas/commands/tas-brainstorm.md +19 -0
- package/.tas/commands/tas-bug.md +113 -0
- package/.tas/commands/tas-design.md +37 -0
- package/.tas/commands/tas-dev.md +125 -0
- package/{.claude → .tas}/commands/tas-e2e-mobile.md +155 -155
- package/{.claude → .tas}/commands/tas-e2e-web.md +163 -163
- package/.tas/commands/tas-e2e.md +102 -0
- package/.tas/commands/tas-epic.md +35 -0
- package/.tas/commands/tas-feature.md +47 -0
- package/.tas/commands/tas-fix.md +51 -0
- package/.tas/commands/tas-functest-mobile.md +144 -0
- package/{.claude → .tas}/commands/tas-functest-web.md +192 -192
- package/.tas/commands/tas-functest.md +76 -0
- package/.tas/commands/tas-init.md +17 -0
- package/.tas/commands/tas-plan.md +198 -0
- package/.tas/commands/tas-prd.md +37 -0
- package/.tas/commands/tas-review.md +113 -0
- package/.tas/commands/tas-sad.md +43 -0
- package/.tas/commands/tas-security.md +87 -0
- package/.tas/commands/tas-spec.md +50 -0
- package/.tas/commands/tas-status.md +16 -0
- package/.tas/commands/tas-story.md +91 -0
- package/.tas/platforms.json +5 -0
- package/.tas/project-status-example.yaml +17 -17
- package/.tas/rules/ado-integration.md +65 -0
- package/{.claude/skills/api-design/SKILL.md → .tas/rules/common/api-design.md} +517 -530
- package/{.claude → .tas}/rules/common/code-review.md +30 -6
- package/.tas/rules/common/post-implementation-review.md +51 -0
- package/{.claude → .tas}/rules/common/project-status.md +80 -80
- package/.tas/rules/common/stack-detection.md +29 -0
- package/.tas/rules/common/story-done.md +30 -0
- package/.tas/rules/common/tdd.md +89 -0
- package/{.claude → .tas}/rules/common/testing.md +3 -8
- package/.tas/rules/common/token-logging.md +36 -0
- package/{.claude → .tas}/rules/csharp/api-testing.md +20 -20
- package/{.claude → .tas}/rules/csharp/coding-style.md +0 -2
- package/{.claude → .tas}/rules/csharp/security.md +10 -0
- package/{.claude → .tas}/rules/python/coding-style.md +0 -2
- package/{.claude → .tas}/rules/typescript/coding-style.md +0 -2
- package/.tas/rules/typescript/patterns.md +142 -0
- package/.tas/rules/typescript/security.md +88 -0
- package/{.claude → .tas}/rules/typescript/testing.md +0 -4
- package/{.claude → .tas}/rules/web/coding-style.md +0 -2
- package/.tas/tas-example.yaml +10 -11
- package/.tas/templates/ADR.md +47 -47
- package/.tas/templates/AGENTS.md +37 -0
- package/.tas/templates/API-Test-Spec.md +3 -3
- package/.tas/templates/Bug.md +67 -67
- package/.tas/templates/Design-Spec.md +36 -36
- package/.tas/templates/E2E-Execution-Report.md +1 -1
- package/.tas/templates/Epic.md +46 -46
- package/.tas/templates/Feature.md +10 -10
- package/.tas/templates/Func-Test-Spec.md +3 -3
- package/.tas/templates/SAD.md +106 -106
- package/.tas/templates/Security-Report.md +27 -27
- package/.tas/templates/Story.md +9 -9
- package/.tas/tools/tas-ado-readme.md +68 -68
- package/.tas/tools/tas-ado.py +621 -621
- package/README.md +78 -78
- package/bin/cli.js +91 -73
- package/lib/adapters/antigravity.js +137 -0
- package/lib/adapters/claude-code.js +35 -0
- package/lib/adapters/codex.js +163 -0
- package/lib/adapters/cursor.js +80 -0
- package/lib/adapters/index.js +20 -0
- package/lib/adapters/utils.js +81 -0
- package/lib/deleted-files.json +99 -0
- package/lib/install.js +403 -327
- package/package.json +4 -3
- package/.claude/agents/code-reviewer.md +0 -41
- package/.claude/agents/e2e-runner.md +0 -61
- package/.claude/agents/planner.md +0 -82
- package/.claude/agents/tdd-guide.md +0 -84
- package/.claude/commands/ado-create.md +0 -27
- package/.claude/commands/ado-delete.md +0 -21
- package/.claude/commands/ado-get.md +0 -20
- package/.claude/commands/ado-status.md +0 -18
- package/.claude/commands/ado-update.md +0 -26
- package/.claude/commands/tas-adr.md +0 -33
- package/.claude/commands/tas-apitest-plan.md +0 -173
- package/.claude/commands/tas-apitest.md +0 -143
- package/.claude/commands/tas-brainstorm.md +0 -19
- package/.claude/commands/tas-bug.md +0 -113
- package/.claude/commands/tas-design.md +0 -37
- package/.claude/commands/tas-dev.md +0 -128
- package/.claude/commands/tas-e2e.md +0 -102
- package/.claude/commands/tas-epic.md +0 -35
- package/.claude/commands/tas-feature.md +0 -47
- package/.claude/commands/tas-fix.md +0 -51
- package/.claude/commands/tas-functest-mobile.md +0 -144
- package/.claude/commands/tas-functest.md +0 -76
- package/.claude/commands/tas-init.md +0 -17
- package/.claude/commands/tas-plan.md +0 -200
- package/.claude/commands/tas-prd.md +0 -37
- package/.claude/commands/tas-review.md +0 -111
- package/.claude/commands/tas-sad.md +0 -43
- package/.claude/commands/tas-security.md +0 -87
- package/.claude/commands/tas-spec.md +0 -50
- package/.claude/commands/tas-status.md +0 -16
- package/.claude/commands/tas-story.md +0 -91
- package/.claude/commands/tas-verify.md +0 -51
- package/.claude/rules/common/post-review-agent.md +0 -49
- package/.claude/rules/common/stack-detection.md +0 -29
- package/.claude/rules/common/token-logging.md +0 -27
- package/.claude/rules/typescript/patterns.md +0 -62
- package/.claude/rules/typescript/security.md +0 -28
- package/.claude/settings.local.json +0 -38
- package/.claude/skills/ado-integration/SKILL.md +0 -75
- package/.claude/skills/ai-regression-testing/SKILL.md +0 -364
- package/.claude/skills/architecture-decision-records/SKILL.md +0 -184
- package/.claude/skills/benchmark/SKILL.md +0 -98
- package/.claude/skills/browser-qa/SKILL.md +0 -92
- package/.claude/skills/canary-watch/SKILL.md +0 -104
- package/.claude/skills/js-backend-patterns/SKILL.md +0 -603
- package/.claude/skills/tas-conventions/SKILL.md +0 -65
- package/.claude/skills/tas-implementation-complete/SKILL.md +0 -99
- package/.claude/skills/tas-tdd/SKILL.md +0 -123
- package/.claude/skills/token-logger/SKILL.md +0 -19
- package/.tas/checklists/code-review.md +0 -29
- package/.tas/checklists/security.md +0 -21
- package/.tas/checklists/story-done.md +0 -23
- package/CLAUDE-Example.md +0 -61
- /package/{.claude → .tas}/agents/architect.md +0 -0
- /package/{.claude → .tas}/agents/aws-reviewer.md +0 -0
- /package/{.claude → .tas}/agents/build-resolver.md +0 -0
- /package/{.claude → .tas}/agents/code-explorer.md +0 -0
- /package/{.claude → .tas}/agents/csharp-reviewer.md +0 -0
- /package/{.claude → .tas}/agents/database-reviewer.md +0 -0
- /package/{.claude → .tas}/agents/doc-updater.md +0 -0
- /package/{.claude → .tas}/agents/python-reviewer.md +0 -0
- /package/{.claude → .tas}/agents/security-reviewer.md +0 -0
- /package/{.claude → .tas}/agents/typescript-reviewer.md +0 -0
- /package/{.claude → .tas}/rules/.gitkeep +0 -0
- /package/{.claude → .tas}/rules/common/hooks.md +0 -0
- /package/{.claude → .tas}/rules/common/patterns.md +0 -0
- /package/{.claude → .tas}/rules/common/security.md +0 -0
- /package/{.claude → .tas}/rules/csharp/hooks.md +0 -0
- /package/{.claude → .tas}/rules/csharp/patterns.md +0 -0
- /package/{.claude → .tas}/rules/csharp/testing.md +0 -0
- /package/{.claude → .tas}/rules/python/hooks.md +0 -0
- /package/{.claude → .tas}/rules/python/patterns.md +0 -0
- /package/{.claude → .tas}/rules/python/security.md +0 -0
- /package/{.claude → .tas}/rules/python/testing.md +0 -0
- /package/{.claude → .tas}/rules/typescript/hooks.md +0 -0
- /package/{.claude → .tas}/rules/web/design-quality.md +0 -0
- /package/{.claude → .tas}/rules/web/hooks.md +0 -0
- /package/{.claude → .tas}/rules/web/patterns.md +0 -0
- /package/{.claude → .tas}/rules/web/performance.md +0 -0
- /package/{.claude → .tas}/rules/web/security.md +0 -0
- /package/{.claude → .tas}/rules/web/testing.md +0 -0
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
# /tas-security $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Kiểm tra bảo mật codebase, lưu báo cáo vào docs/security-report.md.
|
|
4
|
-
|
|
5
|
-
## Stack Detection
|
|
6
|
-
Đọc `.claude/rules/common/stack-detection.md`.
|
|
7
|
-
|
|
8
|
-
## Hành động
|
|
9
|
-
|
|
10
|
-
### Bước 1 — Xác định scope
|
|
11
|
-
`$ARGUMENTS` có thể là:
|
|
12
|
-
- File path hoặc directory → scan scope chỉ định
|
|
13
|
-
- Để trống → scan toàn bộ codebase
|
|
14
|
-
- `--staged` → chỉ scan các file đang staged (giống pre-commit hook), nhanh + dùng để self-test trước khi commit
|
|
15
|
-
|
|
16
|
-
Với `--staged`: lấy danh sách từ `git diff --cached --name-only --diff-filter=ACM` và chỉ review các file đó. Dùng chung regex patterns với `.tas/hooks/security-scan.js` rồi bổ sung deep review bằng agents bên dưới.
|
|
17
|
-
|
|
18
|
-
Đọc `.tas/checklists/security.md` để lấy checklist.
|
|
19
|
-
|
|
20
|
-
### Bước 2 — Parallel Security Scan
|
|
21
|
-
|
|
22
|
-
Launch các agents ĐỒNG THỜI dựa theo stack:
|
|
23
|
-
|
|
24
|
-
**Agent 1 — `security-reviewer`** (luôn chạy):
|
|
25
|
-
> Security audit [scope].
|
|
26
|
-
> Đọc `.claude/rules/common/security.md`.
|
|
27
|
-
> Nếu stack đã xác định, đọc thêm `.claude/rules/[stack]/security.md`.
|
|
28
|
-
> Kiểm tra OWASP Top 10: injection, broken auth, XSS, IDOR, security misconfiguration,
|
|
29
|
-
> sensitive data exposure, insecure deserialization, vulnerable components, logging/monitoring.
|
|
30
|
-
> Kiểm tra thêm: hardcoded secrets, CORS config, anti-forgery tokens, rate limiting.
|
|
31
|
-
> Format: findings theo Critical / High / Medium / Low với file:line và remediation cụ thể.
|
|
32
|
-
> Mỗi finding có: status = Open.
|
|
33
|
-
|
|
34
|
-
**Agent 2 — `database-reviewer`** (chỉ khi `db_agent = database-reviewer`):
|
|
35
|
-
> Database security review [scope].
|
|
36
|
-
> Tập trung: parameterized queries vs string concatenation, ORM raw query usage,
|
|
37
|
-
> sensitive data stored in plaintext, missing field-level encryption, excessive permissions.
|
|
38
|
-
> Format: findings theo Critical / High / Medium / Low với file:line và remediation.
|
|
39
|
-
|
|
40
|
-
**Agent 3 — `aws-reviewer`** (chỉ khi `infra_agent = aws-reviewer`):
|
|
41
|
-
> AWS infrastructure security review [scope].
|
|
42
|
-
> Tập trung: IAM overpermission, S3 public access, secrets trong env/config/code,
|
|
43
|
-
> Lambda environment variables, API Gateway auth, VPC security groups.
|
|
44
|
-
> Format: findings theo Critical / High / Medium / Low với file:line và remediation.
|
|
45
|
-
|
|
46
|
-
Chờ TẤT CẢ agents hoàn thành.
|
|
47
|
-
|
|
48
|
-
### Bước 3 — Tổng hợp và lưu báo cáo
|
|
49
|
-
|
|
50
|
-
Gộp findings từ tất cả agents, deduplicate (cùng file:line → gộp), sort theo severity.
|
|
51
|
-
|
|
52
|
-
Kiểm tra `docs/security-report.md`:
|
|
53
|
-
- **Chưa có**: tạo mới theo template `.tas/templates/Security-Report.md`
|
|
54
|
-
- **Đã có**: append report mới, cập nhật status findings cũ nếu đã được fix
|
|
55
|
-
|
|
56
|
-
Nội dung report bao gồm:
|
|
57
|
-
- Scan date, scope, stack
|
|
58
|
-
- Findings theo Critical / High / Medium / Low
|
|
59
|
-
- Mỗi finding: file:line, mô tả, remediation, status (Open / Fixed / Accepted Risk)
|
|
60
|
-
- Summary: tổng số findings mỗi severity, số đã fix vs còn open
|
|
61
|
-
|
|
62
|
-
### Bước 4 — Cập nhật project-status.yaml
|
|
63
|
-
|
|
64
|
-
```yaml
|
|
65
|
-
artifacts:
|
|
66
|
-
security_report:
|
|
67
|
-
file: docs/security-report.md
|
|
68
|
-
status: [Critical findings present | Clean]
|
|
69
|
-
last_updated: [ngày hôm nay]
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Bước 5 — Hành động tiếp theo
|
|
73
|
-
|
|
74
|
-
Nếu có **Critical findings**:
|
|
75
|
-
→ Liệt kê rõ, yêu cầu fix ngay trước khi deploy bất kỳ môi trường nào.
|
|
76
|
-
|
|
77
|
-
Nếu có **High findings**:
|
|
78
|
-
→ Liệt kê, khuyến nghị fix trước khi merge vào main.
|
|
79
|
-
|
|
80
|
-
Nếu chỉ có **Medium/Low**:
|
|
81
|
-
→ Tóm tắt, gợi ý fix theo thứ tự ưu tiên.
|
|
82
|
-
|
|
83
|
-
## Nguyên tắc
|
|
84
|
-
- Phân loại: Critical / High / Medium / Low
|
|
85
|
-
- Mỗi finding phải có recommended fix cụ thể
|
|
86
|
-
- Finding có status: Open | In Progress | Fixed | Accepted Risk
|
|
87
|
-
- KHÔNG hardcode fix — đề xuất remediation pattern, không viết code thay thế
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# /tas-spec $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Tạo lightweight spec trước khi code — cho solo dev, prototype, spike, internal tool.
|
|
4
|
-
Khác với `/tas-fix`: có spec document, phù hợp task > 2 giờ hoặc cần track AC.
|
|
5
|
-
|
|
6
|
-
## Steps
|
|
7
|
-
|
|
8
|
-
### 1 — Thu thập thông tin
|
|
9
|
-
`$ARGUMENTS` là mô tả task. Nếu chưa đủ rõ, hỏi tối đa 3 câu:
|
|
10
|
-
- **Goal**: Build cái gì? Giải quyết vấn đề gì?
|
|
11
|
-
- **AC**: Done trông như thế nào? (2-5 criteria cụ thể, testable)
|
|
12
|
-
- **Constraints**: Tech constraints, out of scope?
|
|
13
|
-
|
|
14
|
-
Không hỏi nếu $ARGUMENTS đã đủ rõ.
|
|
15
|
-
|
|
16
|
-
### 2 — Tạo SPEC.md
|
|
17
|
-
Tạo file `SPEC.md` ở project root:
|
|
18
|
-
|
|
19
|
-
```markdown
|
|
20
|
-
# {Title}
|
|
21
|
-
> {one-line summary}
|
|
22
|
-
|
|
23
|
-
**Status:** Draft | **Date:** {today}
|
|
24
|
-
|
|
25
|
-
## Goal
|
|
26
|
-
{Vấn đề cần giải quyết — không phải solution}
|
|
27
|
-
|
|
28
|
-
## Acceptance Criteria
|
|
29
|
-
- [ ] {Given/When/Then hoặc testable statement}
|
|
30
|
-
- [ ] ...
|
|
31
|
-
|
|
32
|
-
## Out of Scope
|
|
33
|
-
- {Gì sẽ không làm}
|
|
34
|
-
|
|
35
|
-
## Constraints
|
|
36
|
-
{Tech constraints, patterns phải follow — bỏ qua nếu không có}
|
|
37
|
-
|
|
38
|
-
## Open Questions
|
|
39
|
-
{Câu hỏi chưa có câu trả lời — bỏ qua nếu không có}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 3 — Next step
|
|
43
|
-
> "SPEC.md đã tạo.
|
|
44
|
-
> - Plan kỹ hơn: `/tas-plan SPEC.md`
|
|
45
|
-
> - Code ngay: `/tas-dev` (cần `require_plan: false` trong tas.yaml)"
|
|
46
|
-
|
|
47
|
-
## Principles
|
|
48
|
-
- SPEC.md là single source of truth — không tạo thêm file khác
|
|
49
|
-
- Giữ ngắn: mục tiêu < 1 trang
|
|
50
|
-
- AC > 8 items hoặc task > 1 ngày → gợi ý dùng `/tas-story` thay thế
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# /tas-status
|
|
2
|
-
|
|
3
|
-
Kiểm tra trạng thái hiện tại của dự án TAS.
|
|
4
|
-
|
|
5
|
-
## Hành động
|
|
6
|
-
1. Cần context từ root/project-status.yaml (CHỈ đọc file này, KHÔNG quét thư mục docs/)
|
|
7
|
-
2. Cần context từ root/tas.yaml để biết workflow config
|
|
8
|
-
3. Dựa vào project-status.yaml, tổng hợp:
|
|
9
|
-
- Số lượng artifacts đã tạo và status
|
|
10
|
-
- Số lượng epics/features/stories theo từng status
|
|
11
|
-
- Phase hiện tại dựa trên trạng thái tổng hợp
|
|
12
|
-
4. Hiển thị bảng trạng thái phases và chi tiết stories theo status.
|
|
13
|
-
|
|
14
|
-
## Lưu ý
|
|
15
|
-
- Đây là command chỉ đọc, không thay đổi gì
|
|
16
|
-
- Nếu nghi ngờ project-status.yaml lệch thực tế, user có thể chạy /tas-init để quét lại và đồng bộ
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
# /tas-story $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Vai trò: PE - Product Engineer
|
|
4
|
-
Tạo mới hoặc cập nhật User Story document.
|
|
5
|
-
|
|
6
|
-
**Phạm vi:** Nghiệp vụ, trải nghiệm người dùng, acceptance criteria, test cases.
|
|
7
|
-
**Không thuộc phạm vi:** Kỹ thuật implement, files cần sửa, database schema — đó là việc của `/tas-plan`.
|
|
8
|
-
|
|
9
|
-
## Always / Ask / Never
|
|
10
|
-
|
|
11
|
-
| | Hành động |
|
|
12
|
-
|---|---|
|
|
13
|
-
| **Always** | Viết AC dạng Given/When/Then |
|
|
14
|
-
| **Always** | Set `plan_status: pending` cho Story mới |
|
|
15
|
-
| **Ask** | Khi Story > 8h — gợi ý tách nhỏ |
|
|
16
|
-
| **Never** | Đọc SAD, ADR — kỹ thuật là việc của `/tas-plan` |
|
|
17
|
-
|
|
18
|
-
## Prerequisite
|
|
19
|
-
- Ít nhất một Feature phải tồn tại
|
|
20
|
-
|
|
21
|
-
## Hành động
|
|
22
|
-
|
|
23
|
-
### Chế độ CREATE ($ARGUMENTS là mô tả Story mới, hoặc không có $ARGUMENTS)
|
|
24
|
-
|
|
25
|
-
**Bước 1 — Xác định Feature**
|
|
26
|
-
- Đọc `project.code` từ root/`tas.yaml`
|
|
27
|
-
- Ưu tiên theo thứ tự:
|
|
28
|
-
1. Nếu `$ARGUMENTS` chứa Feature ID → dùng luôn
|
|
29
|
-
2. Nếu context có `parent_id` → dùng luôn
|
|
30
|
-
3. Hỏi user: "Story này thuộc Feature nào?" — không quét thư mục
|
|
31
|
-
|
|
32
|
-
**Bước 2 — Thu thập context nghiệp vụ**
|
|
33
|
-
- Đọc file Feature đã xác định (lấy business context, scope, danh sách Stories hiện có)
|
|
34
|
-
- Đọc PRD (nếu có) — chỉ lấy business requirements, user goals
|
|
35
|
-
|
|
36
|
-
**Bước 3 — Xác định Story ID**
|
|
37
|
-
- Đọc section Stories trong Feature file → xác định index tiếp theo từ danh sách đó
|
|
38
|
-
- KHÔNG quét thư mục
|
|
39
|
-
|
|
40
|
-
**Bước 4 — Soạn Story với user**
|
|
41
|
-
|
|
42
|
-
Thảo luận để điền đầy đủ:
|
|
43
|
-
|
|
44
|
-
a) **User Story**: "As a [role], I want [goal], so that [benefit]"
|
|
45
|
-
|
|
46
|
-
b) **Business Requirements** (nếu có): business rules đặc thù, constraints từ stakeholders
|
|
47
|
-
|
|
48
|
-
c) **Design Notes** (nếu có): UI/UX specs, mockup links, flow diagrams
|
|
49
|
-
|
|
50
|
-
d) **Prerequisites** (nếu có): Stories khác phải done trước
|
|
51
|
-
|
|
52
|
-
e) **Acceptance Criteria**: mỗi AC một kịch bản Given/When/Then rõ ràng
|
|
53
|
-
|
|
54
|
-
**Bước 5 — Test Case Prompting**
|
|
55
|
-
|
|
56
|
-
Sau khi AC được xác nhận, hỏi thêm:
|
|
57
|
-
- "Ngoài happy path, có edge case nào cần test không?" (input rỗng, giá trị biên, concurrent)
|
|
58
|
-
- "Có negative case nào cần cover?" (unauthorized, invalid data, timeout, not found)
|
|
59
|
-
- "Có external dependency nào cần mock khi test?" (API bên ngoài, database state)
|
|
60
|
-
|
|
61
|
-
Ghi tất cả vào section `## Unit Test Cases`.
|
|
62
|
-
|
|
63
|
-
**Bước 6 — Tạo file**
|
|
64
|
-
- Đọc `.tas/templates/Story.md` để lấy format
|
|
65
|
-
- Tạo `docs/epics/{code}-Epic-{NNN}-{slug}/{code}-Feature-{NNN}-{slug}/{code}-Story-{NNN}-{slug}.md`
|
|
66
|
-
- Frontmatter: `plan_status: pending`, `plan_date:` để trống
|
|
67
|
-
|
|
68
|
-
**Bước 7 — Cập nhật project-status.yaml**
|
|
69
|
-
Theo `.claude/rules/common/project-status.md` — thêm entry vào `epics.{EPIC_ID}.features.{FEATURE_ID}.stories`.
|
|
70
|
-
|
|
71
|
-
**Bước 8 — Thông báo next step**
|
|
72
|
-
> "Story đã tạo. Trước khi SE bắt đầu code, cần chạy `/tas-plan {Story-ID}` để lập kế hoạch kỹ thuật."
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
### Chế độ UPDATE ($ARGUMENTS là Story ID, ví dụ: "Story-005")
|
|
77
|
-
|
|
78
|
-
1. Tìm file qua glob `docs/epics/**/{code}-Story-{ID}-*.md`
|
|
79
|
-
2. Đọc file Story hiện tại
|
|
80
|
-
3. Hỏi user cần thay đổi gì (cập nhật AC, đổi status, thêm test cases, sửa business rule...)
|
|
81
|
-
4. Cập nhật file, thêm entry vào Changelog
|
|
82
|
-
5. Cập nhật `project-status.yaml` theo `.claude/rules/common/project-status.md`.
|
|
83
|
-
|
|
84
|
-
## Nguyên tắc
|
|
85
|
-
- Story phải đủ nhỏ để hoàn thành trong **4-8 giờ**; nếu lớn hơn → tách thành nhiều Stories
|
|
86
|
-
- Story file = **product artifact**: mô tả *what* và *why*, không phải *how*
|
|
87
|
-
- Story status: New → Committed → In Progress → Deploy Test → Verify Test → Deploy Stag → Verify Stag → Deploy Prod → Verify Prod → Done
|
|
88
|
-
|
|
89
|
-
## Bước cuối — Token Log
|
|
90
|
-
|
|
91
|
-
Invoke skill `token-logger`: ghi AI Usage Log vào file Story đang làm việc.
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# /tas-verify $ARGUMENTS
|
|
2
|
-
|
|
3
|
-
Vai trò: PE - Product Engineer
|
|
4
|
-
Verify Feature trên môi trường Staging (Phase 2).
|
|
5
|
-
|
|
6
|
-
## Prerequisite
|
|
7
|
-
- Feature phải có status "Ready To Verify"
|
|
8
|
-
- Môi trường Staging phải sẵn sàng
|
|
9
|
-
|
|
10
|
-
## Hành động
|
|
11
|
-
1. Cần context từ root/tas.yaml
|
|
12
|
-
2. $ARGUMENTS là Feature ID. Nếu không có, liệt kê features có status "Ready To Verify".
|
|
13
|
-
3. Tìm file Feature trong cây docs/epics/ (dùng glob)
|
|
14
|
-
4. Cần context từ file Feature hiện tại (đặc biệt section Integration Test Cases và E2E Test Cases)
|
|
15
|
-
|
|
16
|
-
### Workflow verify:
|
|
17
|
-
4.5. **Chạy Automated Tests** (nếu có):
|
|
18
|
-
|
|
19
|
-
**Functional Tests** (Layer 2):
|
|
20
|
-
- Kiểm tra `docs/epics/{epic-dir}/{feature-dir}/Func-Test-*.md` đã có chưa
|
|
21
|
-
- Nếu có, hỏi PE: "Chạy functional test suite? Command: `yarn functest:mobile:{feature-slug}` (hoặc `yarn functest:web:{feature-slug}`)"
|
|
22
|
-
- Ghi nhận pass/fail của func suite
|
|
23
|
-
|
|
24
|
-
**E2E Tests** (Layer 3 - nếu Feature có E2E / Acceptance Test Cases):
|
|
25
|
-
> Launch `e2e-runner`: E2E verification cho Feature {ID}.
|
|
26
|
-
> Đọc section `## E2E / Acceptance Test Cases` từ Feature file — list từng test case.
|
|
27
|
-
> Chạy các test cases đó, báo cáo kết quả: Pass/Fail per test case với lý do nếu Fail.
|
|
28
|
-
> Không tự động fix lỗi — chỉ báo cáo kết quả để PE xác nhận.
|
|
29
|
-
|
|
30
|
-
5. **Tổng hợp kết quả và xác nhận với PE**:
|
|
31
|
-
- Hiển thị summary automated test results (Functional + E2E)
|
|
32
|
-
- Hỏi PE: "Automated tests đã pass. Trên Staging thực có vấn đề nào mà automated tests không catch được không? (UX, business logic, edge case thực tế...)"
|
|
33
|
-
|
|
34
|
-
6. Với mỗi issue PE báo cáo hoặc test case FAIL:
|
|
35
|
-
- Hỏi PE mô tả lỗi
|
|
36
|
-
- Tự động tạo Bug trong thư mục Feature đó (dùng logic /tas-bug)
|
|
37
|
-
- Bug có reference đến test case gốc (FT ID hoặc E2E ID), hoặc ghi rõ "phát hiện qua manual verify Staging"
|
|
38
|
-
7. Cập nhật file Feature:
|
|
39
|
-
- Ghi kết quả test (Pass/Fail + ngày) vào từng test case
|
|
40
|
-
- Nếu tất cả Pass: cập nhật Feature status thành "Verified"
|
|
41
|
-
- Nếu có Fail: giữ Feature status "Ready To Verify", liệt kê bugs
|
|
42
|
-
8. Cập nhật root/project-status.yaml
|
|
43
|
-
|
|
44
|
-
## Nguyên tắc
|
|
45
|
-
- KHÔNG skip test case nào, phải verify hết
|
|
46
|
-
- Bug phát hiện ở Phase 2 PHẢI được ghi thành Bug để track
|
|
47
|
-
- Feature chỉ được chuyển sang Phase 3 (Deploy) khi status = "Verified"
|
|
48
|
-
|
|
49
|
-
## Bước cuối — Token Log
|
|
50
|
-
|
|
51
|
-
Invoke skill `token-logger`: ghi AI Usage Log vào file Feature đang verify.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Post-Implementation Review (Isolated Agent)
|
|
2
|
-
|
|
3
|
-
Sau khi implement hoặc fix xong, chạy review qua **Agent độc lập** — không dùng session hiện tại để tránh reviewer bias từ quá trình implement.
|
|
4
|
-
|
|
5
|
-
## Cách dùng
|
|
6
|
-
|
|
7
|
-
Gọi `Agent` tool với prompt sau (thay thế các placeholder `{}`):
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
Bạn là code reviewer. Không có context từ session trước — hãy review hoàn toàn khách quan.
|
|
11
|
-
|
|
12
|
-
Artifact: {path-to-artifact-file}
|
|
13
|
-
Changed files: {danh sách files vừa thay đổi}
|
|
14
|
-
Stack: {stack từ CLAUDE.md}
|
|
15
|
-
|
|
16
|
-
Thực hiện:
|
|
17
|
-
1. Hygiene scan: debug code còn sót (console.log, debugger, print), secrets hardcoded,
|
|
18
|
-
commented-out blocks lớn (>5 dòng).
|
|
19
|
-
1b. Silent failure scan — tìm các pattern sau:
|
|
20
|
-
- Swallowed exceptions: empty catch {}, catch chỉ log nhưng tiếp tục chạy như không có lỗi
|
|
21
|
-
- Silent async failures: fire-and-forget (unawaited task/Promise), async void (.NET),
|
|
22
|
-
.catch(() => {}) không xử lý gì
|
|
23
|
-
- Null blindspots: .FirstOrDefault() dùng trực tiếp không null-check (.NET),
|
|
24
|
-
optional chaining thiếu trên deeply nested object access (TS/JS),
|
|
25
|
-
dict.get() result dùng như non-None (Python)
|
|
26
|
-
- Error propagation sai: HTTP calls không check status trước khi parse,
|
|
27
|
-
hàm return bool/null khi lỗi thay vì throw (caller bỏ qua kết quả)
|
|
28
|
-
- Config reads không check existence
|
|
29
|
-
2. Chạy tests: detect test runner (package.json → npm test / *.csproj → dotnet test /
|
|
30
|
-
pytest.ini → python -m pytest), report kết quả.
|
|
31
|
-
3. Parallel review — launch đồng thời:
|
|
32
|
-
- code-reviewer: đọc .tas/checklists/code-review.md + .claude/rules/common/code-review.md.
|
|
33
|
-
Tập trung: naming, architecture, error handling, DRY, function size, nesting depth.
|
|
34
|
-
- security-reviewer: đọc .claude/rules/common/security.md.
|
|
35
|
-
Tập trung: OWASP Top 10, injection, hardcoded secrets, auth/authz.
|
|
36
|
-
- {lang_agent}: đọc .claude/rules/[stack]/coding-style.md + .claude/rules/[stack]/patterns.md.
|
|
37
|
-
Tập trung: async/await, null handling, type safety, anti-patterns của stack.
|
|
38
|
-
4. Tổng hợp findings: Critical / High / Medium / Low với file:line và fix cụ thể.
|
|
39
|
-
|
|
40
|
-
Trả về Review Summary đầy đủ.
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Gate Rule
|
|
44
|
-
|
|
45
|
-
| Kết quả | Hành động |
|
|
46
|
-
|---|---|
|
|
47
|
-
| Có **Critical** hoặc **High** | List findings, **DỪNG**, yêu cầu fix trước khi tiếp tục |
|
|
48
|
-
| Chỉ có **Medium** / **Low** | List gợi ý, hỏi user có muốn fix không, sau đó tiếp tục |
|
|
49
|
-
| Không có findings | Tiếp tục bình thường |
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Stack Detection
|
|
2
|
-
|
|
3
|
-
Đọc `CLAUDE.md` tại root, tìm section `## Tech Stack`, xác định các biến sau để dùng trong agent prompts và rule file lookups.
|
|
4
|
-
|
|
5
|
-
## lang_agent — Backend
|
|
6
|
-
|
|
7
|
-
| Tech Stack chứa | lang_agent |
|
|
8
|
-
|---|---|
|
|
9
|
-
| `.NET` / `C#` | `csharp-reviewer` |
|
|
10
|
-
| `Node.js` / `TypeScript` / `NestJS` / `Express` | `typescript-reviewer` |
|
|
11
|
-
| `Python` / `FastAPI` / `Django` / `Flask` | `python-reviewer` |
|
|
12
|
-
|
|
13
|
-
**Frontend bổ sung:** nếu Tech Stack chứa `React` → thêm `typescript-reviewer` vào lang_agent (nếu chưa có).
|
|
14
|
-
|
|
15
|
-
## infra_agent và db_agent — Tùy chọn
|
|
16
|
-
|
|
17
|
-
| Tech Stack chứa | Biến | Value |
|
|
18
|
-
|---|---|---|
|
|
19
|
-
| `AWS` (Infrastructure) | `infra_agent` | `aws-reviewer` |
|
|
20
|
-
| `MySQL` / `PostgreSQL` / `MSSQL` / `SQL Server` / `SQLite` | `db_agent` | `database-reviewer` |
|
|
21
|
-
|
|
22
|
-
## Rules directory theo stack
|
|
23
|
-
|
|
24
|
-
| lang_agent | Rules directory |
|
|
25
|
-
|---|---|
|
|
26
|
-
| `csharp-reviewer` | `.claude/rules/csharp/` |
|
|
27
|
-
| `typescript-reviewer` | `.claude/rules/typescript/` |
|
|
28
|
-
| `python-reviewer` | `.claude/rules/python/` |
|
|
29
|
-
| Frontend / React | `.claude/rules/web/` |
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# Token Usage Logging
|
|
2
|
-
|
|
3
|
-
Ghi `## AI Usage Log` vào cuối artifact file khi TAS command hoàn thành.
|
|
4
|
-
|
|
5
|
-
## Token Estimation
|
|
6
|
-
|
|
7
|
-
Ước tính từ session awareness: số ký tự mỗi file đã `Read` ÷ 4 ≈ tokens (English/code), ÷ 2 (Vietnamese).
|
|
8
|
-
Số ký tự output artifact ÷ 4. Luôn append `(est.)`. User verify bằng `/cost` (CLI) hoặc `/context` (Desktop app).
|
|
9
|
-
|
|
10
|
-
## Format
|
|
11
|
-
|
|
12
|
-
```markdown
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## AI Usage Log
|
|
16
|
-
|
|
17
|
-
| # | Date | Command | Input (est.) | Output (est.) |
|
|
18
|
-
|---|------|---------|-------------|---------------|
|
|
19
|
-
| 1 | YYYY-MM-DD | /tas-{name} | ~{N}k | ~{N}k |
|
|
20
|
-
| 2 | YYYY-MM-DD | /tas-{name} (revision) | ~{N}k | ~{N}k |
|
|
21
|
-
| **Total** | | | **~{N}k** | **~{N}k** |
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Update Rules
|
|
25
|
-
|
|
26
|
-
- **Lần đầu**: section chưa tồn tại → append toàn bộ section với row đầu tiên và row Total
|
|
27
|
-
- **Lần sau**: append row mới trước row Total, cập nhật Total (cộng dồn)
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
paths:
|
|
3
|
-
- "**/*.ts"
|
|
4
|
-
- "**/*.tsx"
|
|
5
|
-
- "**/*.js"
|
|
6
|
-
- "**/*.jsx"
|
|
7
|
-
---
|
|
8
|
-
# TypeScript/JavaScript Patterns
|
|
9
|
-
|
|
10
|
-
> This file extends [common/patterns.md](../common/patterns.md) with TypeScript/JavaScript specific content.
|
|
11
|
-
|
|
12
|
-
## API Response Format
|
|
13
|
-
|
|
14
|
-
```typescript
|
|
15
|
-
interface ApiResponse<T> {
|
|
16
|
-
success: boolean
|
|
17
|
-
data?: T
|
|
18
|
-
error?: string
|
|
19
|
-
meta?: {
|
|
20
|
-
total: number
|
|
21
|
-
page: number
|
|
22
|
-
limit: number
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Custom Hooks Pattern
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
export function useDebounce<T>(value: T, delay: number): T {
|
|
31
|
-
const [debouncedValue, setDebouncedValue] = useState<T>(value)
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
const handler = setTimeout(() => setDebouncedValue(value), delay)
|
|
35
|
-
return () => clearTimeout(handler)
|
|
36
|
-
}, [value, delay])
|
|
37
|
-
|
|
38
|
-
return debouncedValue
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Repository Pattern
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
interface Repository<T> {
|
|
46
|
-
findAll(filters?: Filters): Promise<T[]>
|
|
47
|
-
findById(id: string): Promise<T | null>
|
|
48
|
-
create(data: CreateDto): Promise<T>
|
|
49
|
-
update(id: string, data: UpdateDto): Promise<T>
|
|
50
|
-
delete(id: string): Promise<void>
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Performance Anti-Patterns
|
|
55
|
-
|
|
56
|
-
Avoid these in Node.js backends:
|
|
57
|
-
|
|
58
|
-
- **Sequential awaits that could be parallel**: use `Promise.all()` when calls are independent
|
|
59
|
-
- **CPU-blocking on event loop**: offload heavy computation to worker threads
|
|
60
|
-
- **Missing connection pooling**: never create a new DB connection per request — use pooled clients
|
|
61
|
-
- **ORM N+1**: missing `include`/`select` in Prisma/Sequelize — use eager loading or DataLoader for GraphQL
|
|
62
|
-
- **Large file reads without streaming**: avoid `fs.readFile` on large files — use streams instead
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
paths:
|
|
3
|
-
- "**/*.ts"
|
|
4
|
-
- "**/*.tsx"
|
|
5
|
-
- "**/*.js"
|
|
6
|
-
- "**/*.jsx"
|
|
7
|
-
---
|
|
8
|
-
# TypeScript/JavaScript Security
|
|
9
|
-
|
|
10
|
-
> This file extends [common/security.md](../common/security.md) with TypeScript/JavaScript specific content.
|
|
11
|
-
|
|
12
|
-
## Secret Management
|
|
13
|
-
|
|
14
|
-
```typescript
|
|
15
|
-
// NEVER: Hardcoded secrets
|
|
16
|
-
const apiKey = "sk-proj-xxxxx"
|
|
17
|
-
|
|
18
|
-
// ALWAYS: Environment variables
|
|
19
|
-
const apiKey = process.env.OPENAI_API_KEY
|
|
20
|
-
|
|
21
|
-
if (!apiKey) {
|
|
22
|
-
throw new Error('OPENAI_API_KEY not configured')
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Agent Support
|
|
27
|
-
|
|
28
|
-
- Use **security-reviewer** skill for comprehensive security audits
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Skill(*)",
|
|
5
|
-
"Bash(*)",
|
|
6
|
-
"Edit(*)",
|
|
7
|
-
"Write(*)",
|
|
8
|
-
"Read(*)",
|
|
9
|
-
"Glob(*)",
|
|
10
|
-
"Grep(*)",
|
|
11
|
-
"Agent(*)",
|
|
12
|
-
"ExitPlanMode",
|
|
13
|
-
"EnterWorktree",
|
|
14
|
-
"ExitWorktree",
|
|
15
|
-
"TodoWrite",
|
|
16
|
-
"NotebookEdit",
|
|
17
|
-
"CronCreate",
|
|
18
|
-
"CronDelete",
|
|
19
|
-
"CronList",
|
|
20
|
-
"RemoteTrigger(*)",
|
|
21
|
-
"TaskOutput",
|
|
22
|
-
"TaskStop",
|
|
23
|
-
"AskUserQuestion"
|
|
24
|
-
],
|
|
25
|
-
"deny": [
|
|
26
|
-
"Read:env:*",
|
|
27
|
-
"Bash:sudo:*",
|
|
28
|
-
"WebSearch",
|
|
29
|
-
"WebFetch",
|
|
30
|
-
"Skill(mcp__web_reader__webReader)",
|
|
31
|
-
"Skill(mcp__4_5v_mcp__analyze_image)"
|
|
32
|
-
]
|
|
33
|
-
},
|
|
34
|
-
"enabledMcpjsonServers": [
|
|
35
|
-
"figma"
|
|
36
|
-
],
|
|
37
|
-
"enableAllProjectMcpServers": true
|
|
38
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: ado-integration
|
|
3
|
-
description: |
|
|
4
|
-
Azure DevOps integration. Auto-invoke khi user nhắc đến:
|
|
5
|
-
sync ADO, push to board, pull work item, update status on ADO,
|
|
6
|
-
create work item on ADO, hoặc bất kỳ thao tác liên quan Azure DevOps.
|
|
7
|
-
allowed-tools: Read, Write, Edit, Bash, Grep
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
# ADO Integration Skill
|
|
11
|
-
|
|
12
|
-
Cho phép đồng bộ hai chiều giữa file .md trong repo và work items trên Azure DevOps.
|
|
13
|
-
ADO sync là **thao tác có chủ đích** — không tự động sau mỗi lần edit file.
|
|
14
|
-
|
|
15
|
-
## When to Use
|
|
16
|
-
|
|
17
|
-
- User yêu cầu sync, push, pull work item lên/từ ADO
|
|
18
|
-
- User chạy `/ado-create`, `/ado-update`, `/ado-status`, `/ado-get`, `/ado-delete`
|
|
19
|
-
- KHÔNG invoke khi: user chỉ edit file .md thông thường mà không nhắc đến ADO
|
|
20
|
-
|
|
21
|
-
## Always / Ask / Never
|
|
22
|
-
|
|
23
|
-
| | Hành động |
|
|
24
|
-
|---|---|
|
|
25
|
-
| **Always** | Đọc `tas.yaml` và kiểm tra `ado.enabled` trước bất kỳ thao tác nào |
|
|
26
|
-
| **Always** | Hiển thị ADO ID và URL sau mỗi create/update thành công |
|
|
27
|
-
| **Always** | Cập nhật frontmatter `ado_id`, `ado_state`, `last_ado_sync` trong file .md sau sync |
|
|
28
|
-
| **Ask** | Khi sync bulk nhiều items cùng lúc — confirm list trước khi chạy |
|
|
29
|
-
| **Ask** | Khi phát hiện conflict giữa file .md và ADO item (ai là source of truth?) |
|
|
30
|
-
| **Ask** | Khi delete work item — đây là thao tác không thể undo |
|
|
31
|
-
| **Never** | Auto-sync mỗi khi file .md được edit (quá aggressive, dễ gây noise) |
|
|
32
|
-
| **Never** | Xóa ADO item mà không có xác nhận rõ ràng từ user |
|
|
33
|
-
| **Never** | Tạo duplicate work item nếu đã có `ado_id` trong frontmatter |
|
|
34
|
-
|
|
35
|
-
## Bước đầu tiên — Kiểm tra ADO enabled
|
|
36
|
-
|
|
37
|
-
Trước khi thực hiện bất kỳ thao tác nào, đọc `tas.yaml` tại root và kiểm tra `ado.enabled`:
|
|
38
|
-
- Nếu `ado.enabled: false` hoặc field không tồn tại: thông báo "ADO integration bị tắt trong tas.yaml (`ado.enabled: false`). Bật lên nếu project dùng ADO." rồi dừng lại.
|
|
39
|
-
- Nếu `ado.enabled: true`: tiếp tục bình thường.
|
|
40
|
-
|
|
41
|
-
## Prerequisites
|
|
42
|
-
|
|
43
|
-
- Azure CLI + extension azure-devops: `az extension add --name azure-devops --upgrade`
|
|
44
|
-
- Python 3.8+ với pyyaml: `pip install pyyaml`
|
|
45
|
-
- PAT trong file .env: `AzureDevops_Personal_AccessToken=your-pat-here`
|
|
46
|
-
|
|
47
|
-
## Commands
|
|
48
|
-
|
|
49
|
-
Tất cả ADO commands chạy qua: `python .tas/tools/tas-ado.py <command> [args]`
|
|
50
|
-
|
|
51
|
-
Hoặc dùng slash commands:
|
|
52
|
-
- `/ado-create <type> <temp-id> [--parent-id <id>]`
|
|
53
|
-
- `/ado-get <ado-id>`
|
|
54
|
-
- `/ado-update <type> <ado-id> [--assign <name>] [--status <state>]`
|
|
55
|
-
- `/ado-status <ado-id> --status <state>`
|
|
56
|
-
- `/ado-delete <type> <ado-id>`
|
|
57
|
-
|
|
58
|
-
## File Convention
|
|
59
|
-
|
|
60
|
-
- Tên file: `{type}-{ado_id}-{slug-title}.md`
|
|
61
|
-
- Mỗi file có frontmatter YAML: `ado_id`, `ado_type`, `ado_state`, `last_ado_sync`
|
|
62
|
-
- File .md là single source of truth, sync lên ADO khi cần
|
|
63
|
-
|
|
64
|
-
## Red Flags
|
|
65
|
-
|
|
66
|
-
- File có `ado_id` nhưng state trong file khác ADO → confirm với user trước khi ghi đè
|
|
67
|
-
- PAT hết hạn → hướng dẫn rotate, không log token ra stdout
|
|
68
|
-
- `ado.enabled: true` nhưng project chưa setup Azure CLI → check prerequisites trước
|
|
69
|
-
|
|
70
|
-
## Anti-Rationalization
|
|
71
|
-
|
|
72
|
-
| Rationalization | Counter |
|
|
73
|
-
|---|---|
|
|
74
|
-
| "Auto-sync tiện hơn, không cần nhớ" | Hook auto-sync gây unintended pushes khi edit draft — sync phải có chủ đích |
|
|
75
|
-
| "Delete chắc OK, mình biết mình đang làm gì" | ADO delete không có undo — luôn confirm, dù user trông có vẻ chắc chắn |
|