@torus-engineering/tas-kit 1.7.0 → 1.9.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.
Files changed (73) hide show
  1. package/.claude/commands/tas-adr.md +33 -29
  2. package/.claude/commands/tas-apitest-plan.md +173 -0
  3. package/.claude/commands/tas-apitest.md +143 -0
  4. package/.claude/commands/tas-bug.md +113 -109
  5. package/.claude/commands/tas-design.md +37 -33
  6. package/.claude/commands/tas-dev.md +128 -115
  7. package/.claude/commands/tas-e2e-mobile.md +155 -0
  8. package/.claude/commands/tas-e2e-web.md +163 -0
  9. package/.claude/commands/tas-e2e.md +102 -0
  10. package/.claude/commands/tas-epic.md +35 -31
  11. package/.claude/commands/tas-feature.md +47 -43
  12. package/.claude/commands/tas-fix.md +51 -47
  13. package/.claude/commands/tas-functest-mobile.md +144 -0
  14. package/.claude/commands/tas-functest-web.md +192 -0
  15. package/.claude/commands/tas-functest.md +76 -0
  16. package/.claude/commands/tas-plan.md +200 -184
  17. package/.claude/commands/tas-prd.md +37 -33
  18. package/.claude/commands/tas-review.md +111 -104
  19. package/.claude/commands/tas-sad.md +43 -39
  20. package/.claude/commands/tas-security.md +81 -80
  21. package/.claude/commands/tas-story.md +91 -87
  22. package/.claude/commands/tas-verify.md +51 -41
  23. package/.claude/rules/common/post-review-agent.md +49 -39
  24. package/.claude/rules/common/testing.md +24 -0
  25. package/.claude/rules/common/token-logging.md +27 -0
  26. package/.claude/rules/csharp/api-testing.md +171 -0
  27. package/.claude/rules/csharp/patterns.md +10 -0
  28. package/.claude/rules/python/patterns.md +10 -0
  29. package/.claude/rules/typescript/patterns.md +10 -0
  30. package/.claude/rules/web/performance.md +9 -0
  31. package/.claude/skills/api-design/SKILL.md +3 -1
  32. package/.claude/skills/{backend-patterns → js-backend-patterns}/SKILL.md +2 -1
  33. package/.claude/skills/tas-implementation-complete/SKILL.md +99 -97
  34. package/.claude/skills/tas-tdd/SKILL.md +123 -82
  35. package/.claude/skills/token-logger/SKILL.md +19 -0
  36. package/.tas/templates/API-Test-Spec.md +400 -0
  37. package/.tas/templates/E2E-Execution-Report.md +198 -0
  38. package/.tas/templates/E2E-Mobile-Spec.md +130 -0
  39. package/.tas/templates/E2E-Report.md +174 -0
  40. package/.tas/templates/E2E-Scenario.md +180 -0
  41. package/.tas/templates/E2E-Web-Spec.md +164 -0
  42. package/.tas/templates/Feature.md +55 -55
  43. package/.tas/templates/Func-Test-Script.md +254 -0
  44. package/.tas/templates/Func-Test-Spec.md +187 -0
  45. package/.tas/templates/SAD.md +274 -274
  46. package/.tas/templates/Story.md +90 -88
  47. package/bin/cli.js +56 -56
  48. package/lib/deleted-files.json +36 -0
  49. package/lib/install.js +213 -176
  50. package/package.json +34 -34
  51. package/.claude/agents/README.md +0 -83
  52. package/.claude/agents/ado-agent.md +0 -39
  53. package/.claude/agents/code-architect.md +0 -62
  54. package/.claude/agents/code-simplifier.md +0 -53
  55. package/.claude/agents/comment-analyzer.md +0 -59
  56. package/.claude/agents/conversation-analyzer.md +0 -57
  57. package/.claude/agents/docs-lookup.md +0 -55
  58. package/.claude/agents/harness-optimizer.md +0 -62
  59. package/.claude/agents/loop-operator.md +0 -56
  60. package/.claude/agents/performance-optimizer.md +0 -78
  61. package/.claude/agents/pr-test-analyzer.md +0 -68
  62. package/.claude/agents/pytorch-build-resolver.md +0 -76
  63. package/.claude/agents/refactor-cleaner.md +0 -70
  64. package/.claude/agents/seo-specialist.md +0 -75
  65. package/.claude/agents/silent-failure-hunter.md +0 -69
  66. package/.claude/agents/type-design-analyzer.md +0 -75
  67. package/.claude/rules/common/agents.md +0 -65
  68. package/.claude/rules/common/coding-style.md +0 -90
  69. package/.claude/rules/common/development-workflow.md +0 -44
  70. package/.claude/rules/common/git-workflow.md +0 -24
  71. package/.claude/rules/common/performance.md +0 -55
  72. package/.claude/skills/agent-harness-construction/SKILL.md +0 -77
  73. package/.claude/skills/agent-introspection-debugging/SKILL.md +0 -157
@@ -1,87 +1,91 @@
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
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,41 +1,51 @@
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. **Launch `e2e-runner`** (nếu Feature E2E / Acceptance Test Cases):
18
- > E2E verification cho Feature {ID}.
19
- > Đọc section `## E2E / Acceptance Test Cases` từ Feature file — list từng test case.
20
- > 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.
21
- > Không tự động fix lỗi chỉ báo cáo kết quả để PE xác nhận.
22
-
23
- Dùng kết quả từ `e2e-runner` làm input cho bước 5.
24
-
25
- 5. Hiển thị checklist từ 2 section test trong Feature:
26
- a. **Integration Test Cases**: Liệt từng test case, hỏi PE kết quả (Pass/Fail)
27
- b. **E2E / Acceptance Test Cases**: Liệt từng test case, hỏi PE kết quả (Pass/Fail)
28
- 6. Với mỗi test case FAIL:
29
- - Hỏi PE mô tả lỗi
30
- - Tự động tạo Bug trong thư mục Feature đó (dùng logic /tas-bug)
31
- - Bug reference đến test case gốc
32
- 7. Cập nhật file Feature:
33
- - Ghi kết quả test (Pass/Fail + ngày) vào từng test case
34
- - Nếu tất cả Pass: cập nhật Feature status thành "Verified"
35
- - Nếu Fail: giữ Feature status "Ready To Verify", liệt kê bugs
36
- 8. Cập nhật root/project-status.yaml
37
-
38
- ## Nguyên tắc
39
- - KHÔNG skip test case nào, phải verify hết
40
- - Bug phát hiện Phase 2 PHẢI được ghi thành Bug để track
41
- - Feature chỉ được chuyển sang Phase 3 (Deploy) khi status = "Verified"
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` đã 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 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ả 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 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 Fail: giữ Feature status "Ready To Verify", liệt 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,39 +1,49 @@
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
- 2. Chạy tests: detect test runner (package.json npm test / *.csproj → dotnet test /
20
- pytest.ini python -m pytest), report kết quả.
21
- 3. Parallel review launch đồng thời:
22
- - code-reviewer: đọc .tas/checklists/code-review.md + .claude/rules/common/code-review.md.
23
- Tập trung: naming, architecture, error handling, DRY, function size, nesting depth.
24
- - security-reviewer: đọc .claude/rules/common/security.md.
25
- Tập trung: OWASP Top 10, injection, hardcoded secrets, auth/authz.
26
- - {lang_agent}: đọc .claude/rules/[stack]/coding-style.md + .claude/rules/[stack]/patterns.md.
27
- Tập trung: async/await, null handling, type safety, anti-patterns của stack.
28
- 4. Tổng hợp findings: Critical / High / Medium / Low với file:line và fix cụ thể.
29
-
30
- Trả về Review Summary đầy đủ.
31
- ```
32
-
33
- ## Gate Rule
34
-
35
- | Kết quả | Hành động |
36
- |---|---|
37
- | **Critical** hoặc **High** | List findings, **DỪNG**, yêu cầu fix trước khi tiếp tục |
38
- | Chỉ **Medium** / **Low** | List gợi ý, hỏi user muốn fix không, sau đó tiếp tục |
39
- | Không có findings | Tiếp tục bình thường |
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 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 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 |
@@ -28,6 +28,30 @@ MANDATORY workflow:
28
28
 
29
29
  - **tdd-guide** - Use PROACTIVELY for new features, enforces write-tests-first
30
30
 
31
+ ## PR Test Gap Analysis
32
+
33
+ Before merging, identify missing tests by categorizing each changed file:
34
+
35
+ | Change type | Tests required |
36
+ |-------------|---------------|
37
+ | New logic added | New unit tests |
38
+ | Logic modified | Updated/new unit tests + regression check |
39
+ | New API endpoint | Integration test (happy path + validation + error) |
40
+ | Bug fix | Regression test that reproduces the bug |
41
+ | Refactor only | Verify existing tests still pass — no new tests needed |
42
+ | Config/infra change | Manual verification step — document it |
43
+
44
+ ### How to find gaps
45
+
46
+ 1. Run `git diff main...HEAD --name-only` to get changed files
47
+ 2. For each changed source file, find its test file (grep for class/function name in test dirs)
48
+ 3. Check: happy path covered? edge cases (null, empty, boundary)? failure/error path?
49
+ 4. List specific missing test cases with method name and scenario
50
+
51
+ ### Regression test rule
52
+
53
+ Every bug fix must include a test that **fails before the fix and passes after**. No exceptions.
54
+
31
55
  ## Test Structure (AAA Pattern)
32
56
 
33
57
  Prefer Arrange-Act-Assert structure for tests:
@@ -0,0 +1,27 @@
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)
@@ -0,0 +1,171 @@
1
+ ---
2
+ paths:
3
+ - "**/*.cs"
4
+ - "**/ApiTests/**"
5
+ - "**/Api.Tests/**"
6
+ ---
7
+
8
+ # C# API Automation Testing
9
+
10
+ > Dùng bởi `/tas-api-test`. Extends [csharp/testing.md](./testing.md).
11
+
12
+ ## Tech Stack
13
+
14
+ | Thành phần | Lựa chọn |
15
+ |---|---|
16
+ | Framework | xUnit (default) — match project nếu đã dùng MSTest/NUnit |
17
+ | Assertions | FluentAssertions |
18
+ | HTTP | System.Net.Http.HttpClient |
19
+ | Config | Microsoft.Extensions.Configuration + JSON/EnvVars |
20
+
21
+ ```xml
22
+ <!-- ApiTests.csproj packages -->
23
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
24
+ <PackageReference Include="xunit" Version="2.*" />
25
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.*" />
26
+ <PackageReference Include="FluentAssertions" Version="6.*" />
27
+ <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.*" />
28
+ <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.*" />
29
+ <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.*" />
30
+ ```
31
+
32
+ ## Project Structure
33
+
34
+ ```
35
+ tests/ApiTests/
36
+ appsettings.json # base (không có secrets thật)
37
+ appsettings.Test.json # Test env override
38
+ appsettings.Staging.json # Staging env override
39
+ .gitignore # appsettings.*.local.json
40
+ Shared/
41
+ ApiTestSettings.cs
42
+ TestBase.cs
43
+ v1/
44
+ UsersApiTests.cs
45
+ v2/ # APPEND-ONLY: không sửa v1
46
+ UsersApiTests.cs
47
+ ```
48
+
49
+ ## Config
50
+
51
+ ```json
52
+ // appsettings.json
53
+ {
54
+ "ApiTest": {
55
+ "BaseUrl": "https://localhost:5001",
56
+ "TimeoutSeconds": 30,
57
+ "Auth": { "Type": "Bearer", "TokenEndpoint": "/api/auth/token", "Username": "", "Password": "" }
58
+ }
59
+ }
60
+ ```
61
+
62
+ ```csharp
63
+ // ApiTestSettings.cs
64
+ public sealed class ApiTestSettings
65
+ {
66
+ public required string BaseUrl { get; init; }
67
+ public int TimeoutSeconds { get; init; } = 30;
68
+ public required AuthSettings Auth { get; init; }
69
+ }
70
+ public sealed class AuthSettings
71
+ {
72
+ public string Type { get; init; } = "Bearer";
73
+ public string TokenEndpoint { get; init; } = "/api/auth/token";
74
+ public string Username { get; init; } = "";
75
+ public string Password { get; init; } = "";
76
+ }
77
+ ```
78
+
79
+ ```csharp
80
+ // TestBase.cs
81
+ public abstract class TestBase : IAsyncLifetime
82
+ {
83
+ protected HttpClient Client { get; private set; } = null!;
84
+ protected ApiTestSettings Settings { get; private set; } = null!;
85
+
86
+ public async Task InitializeAsync()
87
+ {
88
+ var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Test";
89
+ Settings = new ConfigurationBuilder()
90
+ .AddJsonFile("appsettings.json")
91
+ .AddJsonFile($"appsettings.{env}.json", optional: true)
92
+ .AddEnvironmentVariables("APITEST_")
93
+ .Build()
94
+ .GetRequiredSection("ApiTest").Get<ApiTestSettings>()!;
95
+
96
+ Client = new HttpClient { BaseAddress = new Uri(Settings.BaseUrl),
97
+ Timeout = TimeSpan.FromSeconds(Settings.TimeoutSeconds) };
98
+
99
+ if (!string.IsNullOrEmpty(Settings.Auth.Username))
100
+ await AuthenticateAsync();
101
+ }
102
+
103
+ public Task DisposeAsync() { Client.Dispose(); return Task.CompletedTask; }
104
+
105
+ protected async Task AuthenticateAsync(string? username = null, string? password = null)
106
+ {
107
+ var res = await Client.PostAsJsonAsync(Settings.Auth.TokenEndpoint,
108
+ new { username = username ?? Settings.Auth.Username, password = password ?? Settings.Auth.Password });
109
+ res.EnsureSuccessStatusCode();
110
+ var token = (await res.Content.ReadFromJsonAsync<TokenResponse>())!.AccessToken;
111
+ Client.DefaultRequestHeaders.Authorization =
112
+ new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
113
+ }
114
+
115
+ private sealed record TokenResponse(string AccessToken);
116
+ }
117
+ ```
118
+
119
+ ## Test Class Header (bắt buộc)
120
+
121
+ ```csharp
122
+ // ============================================================
123
+ // {Resource} API Tests — v{N}
124
+ // Spec: {spec-file} | Generated: {YYYY-MM-DD} | Story: {ID}
125
+ // APPEND-ONLY: không sửa methods đã tồn tại.
126
+ // ============================================================
127
+ namespace ApiTests.V{N};
128
+ public sealed class {Resource}ApiTests : TestBase
129
+ {
130
+ // Inline DTOs — không import từ production code
131
+ private sealed record {Resource}Dto(Guid Id, string Name);
132
+ private sealed record ListResponse<T>(IReadOnlyList<T> Data, int Total);
133
+ }
134
+ ```
135
+
136
+ ## Test Naming
137
+
138
+ ```
139
+ {HttpMethod}_{Resource}_Returns{Status}_When{Condition}
140
+ ```
141
+
142
+ Ví dụ: `GetById_User_Returns200_WhenExists`, `Create_Order_Returns422_WhenEmailInvalid`
143
+
144
+ AC test: comment `// AC: {text}` ngay dưới XML doc.
145
+
146
+ ## XML Doc (bắt buộc trên mỗi test)
147
+
148
+ ```csharp
149
+ /// <summary>Verify {METHOD} {path} → {status} khi {condition}. Spec: {ref}</summary>
150
+ [Fact]
151
+ public async Task ...
152
+ ```
153
+
154
+ ## Coverage Matrix
155
+
156
+ | Điều kiện | Status | Khi nào |
157
+ |---|---|---|
158
+ | Valid, authenticated | 2xx | Luôn |
159
+ | Không có token | 401 | Endpoint yêu cầu auth |
160
+ | Không đủ quyền | 403 | RBAC / ownership |
161
+ | `{id}` không tồn tại | 404 | Có path param |
162
+ | Required field thiếu/sai | 400/422 | Có request body |
163
+ | Business rule (từ AC) | 4xx | Story có AC tương ứng |
164
+
165
+ ## CI/CD Env Vars
166
+
167
+ ```
168
+ ASPNETCORE_ENVIRONMENT=Test
169
+ APITEST__AUTH__USERNAME=... # double __ cho nested key
170
+ APITEST__AUTH__PASSWORD=...
171
+ ```
@@ -48,3 +48,13 @@ public sealed class PaymentsOptions
48
48
  - Depend on interfaces at service boundaries
49
49
  - Keep constructors focused; if a service needs too many dependencies, split responsibilities
50
50
  - Register lifetimes intentionally: singleton for stateless/shared services, scoped for request data, transient for lightweight pure workers
51
+
52
+ ## Performance Anti-Patterns
53
+
54
+ Avoid these in hot paths and async contexts:
55
+
56
+ - **Blocking async**: `.Result` or `.Wait()` in async methods — use `await` instead
57
+ - **EF Core N+1**: loading related entities in a loop — use `.Include()` or explicit batch queries
58
+ - **Missing `AsNoTracking()`**: use on read-only queries to reduce EF overhead
59
+ - **Missing `CancellationToken`**: propagate through all public async APIs to enable early exit
60
+ - **Large allocations in hot paths**: prefer `ArrayPool<T>` or `Span<T>` over `new T[]` in frequently called code
@@ -34,6 +34,16 @@ class CreateUserRequest:
34
34
  - Use context managers (`with` statement) for resource management
35
35
  - Use generators for lazy evaluation and memory-efficient iteration
36
36
 
37
+ ## Performance Anti-Patterns
38
+
39
+ Avoid these in Python services:
40
+
41
+ - **Sync I/O in async handlers**: blocking DB/HTTP calls inside `async def` FastAPI/Django routes — use `await` with async drivers
42
+ - **Missing connection pooling**: configure `pool_size` and `max_overflow` in SQLAlchemy; never create a new engine per request
43
+ - **Heavy computation in request handlers**: offload to Celery background tasks or `asyncio.run_in_executor`
44
+ - **Missing cache on expensive queries**: wrap slow aggregations with Redis (e.g., `aiocache` or `fastapi-cache`)
45
+ - **Loading full querysets when only counts or IDs needed**: use `.values_list()` / `.scalar()` instead of full ORM objects
46
+
37
47
  ## Reference
38
48
 
39
49
  See skill: `python-patterns` for comprehensive patterns including decorators, concurrency, and package organization.
@@ -50,3 +50,13 @@ interface Repository<T> {
50
50
  delete(id: string): Promise<void>
51
51
  }
52
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