@torus-engineering/tas-kit 1.5.1 → 1.7.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 (113) hide show
  1. package/.claude/agents/README.md +83 -0
  2. package/.claude/agents/architect.md +53 -0
  3. package/.claude/agents/aws-reviewer.md +71 -0
  4. package/.claude/agents/build-resolver.md +59 -0
  5. package/.claude/agents/code-architect.md +62 -0
  6. package/.claude/agents/code-explorer.md +63 -0
  7. package/.claude/agents/code-simplifier.md +53 -0
  8. package/.claude/agents/comment-analyzer.md +59 -0
  9. package/.claude/agents/conversation-analyzer.md +57 -0
  10. package/.claude/agents/csharp-reviewer.md +62 -0
  11. package/.claude/agents/database-reviewer.md +73 -0
  12. package/.claude/agents/doc-updater.md +66 -0
  13. package/.claude/agents/docs-lookup.md +55 -0
  14. package/.claude/agents/e2e-runner.md +61 -0
  15. package/.claude/agents/harness-optimizer.md +62 -0
  16. package/.claude/agents/loop-operator.md +56 -0
  17. package/.claude/agents/performance-optimizer.md +78 -0
  18. package/.claude/agents/planner.md +82 -0
  19. package/.claude/agents/pr-test-analyzer.md +68 -0
  20. package/.claude/agents/python-reviewer.md +67 -0
  21. package/.claude/agents/pytorch-build-resolver.md +76 -0
  22. package/.claude/agents/refactor-cleaner.md +70 -0
  23. package/.claude/agents/security-reviewer.md +79 -0
  24. package/.claude/agents/seo-specialist.md +75 -0
  25. package/.claude/agents/silent-failure-hunter.md +69 -0
  26. package/.claude/agents/tdd-guide.md +84 -0
  27. package/.claude/agents/type-design-analyzer.md +75 -0
  28. package/.claude/agents/typescript-reviewer.md +65 -0
  29. package/.claude/commands/ado-create.md +2 -1
  30. package/.claude/commands/ado-delete.md +3 -2
  31. package/.claude/commands/ado-get.md +2 -1
  32. package/.claude/commands/ado-status.md +2 -1
  33. package/.claude/commands/ado-update.md +2 -1
  34. package/.claude/commands/tas-adr.md +13 -12
  35. package/.claude/commands/tas-bug.md +97 -50
  36. package/.claude/commands/tas-design.md +3 -1
  37. package/.claude/commands/tas-dev.md +115 -0
  38. package/.claude/commands/tas-epic.md +4 -2
  39. package/.claude/commands/tas-feature.md +5 -3
  40. package/.claude/commands/tas-fix.md +47 -0
  41. package/.claude/commands/tas-plan.md +184 -0
  42. package/.claude/commands/tas-prd.md +3 -1
  43. package/.claude/commands/tas-review.md +104 -0
  44. package/.claude/commands/tas-sad.md +3 -1
  45. package/.claude/commands/tas-security.md +80 -0
  46. package/.claude/commands/tas-spec.md +50 -0
  47. package/.claude/commands/tas-story.md +77 -40
  48. package/.claude/commands/tas-verify.md +8 -0
  49. package/.claude/hooks/code-quality.js +127 -0
  50. package/.claude/hooks/session-end.js +116 -0
  51. package/.claude/rules/.gitkeep +0 -0
  52. package/.claude/rules/common/agents.md +65 -0
  53. package/.claude/rules/common/code-review.md +124 -0
  54. package/.claude/rules/common/coding-style.md +90 -0
  55. package/.claude/rules/common/development-workflow.md +44 -0
  56. package/.claude/rules/common/git-workflow.md +24 -0
  57. package/.claude/rules/common/hooks.md +30 -0
  58. package/.claude/rules/common/patterns.md +31 -0
  59. package/.claude/rules/common/performance.md +55 -0
  60. package/.claude/rules/common/post-review-agent.md +39 -0
  61. package/.claude/rules/common/project-status.md +80 -0
  62. package/.claude/rules/common/security.md +29 -0
  63. package/.claude/rules/common/stack-detection.md +29 -0
  64. package/.claude/rules/common/testing.md +57 -0
  65. package/.claude/rules/csharp/coding-style.md +72 -0
  66. package/.claude/rules/csharp/hooks.md +25 -0
  67. package/.claude/rules/csharp/patterns.md +50 -0
  68. package/.claude/rules/csharp/security.md +58 -0
  69. package/.claude/rules/csharp/testing.md +46 -0
  70. package/.claude/rules/python/coding-style.md +42 -0
  71. package/.claude/rules/python/hooks.md +19 -0
  72. package/.claude/rules/python/patterns.md +39 -0
  73. package/.claude/rules/python/security.md +30 -0
  74. package/.claude/rules/python/testing.md +38 -0
  75. package/.claude/rules/typescript/coding-style.md +199 -0
  76. package/.claude/rules/typescript/hooks.md +22 -0
  77. package/.claude/rules/typescript/patterns.md +52 -0
  78. package/.claude/rules/typescript/security.md +28 -0
  79. package/.claude/rules/typescript/testing.md +18 -0
  80. package/.claude/rules/web/coding-style.md +96 -0
  81. package/.claude/rules/web/design-quality.md +63 -0
  82. package/.claude/rules/web/hooks.md +120 -0
  83. package/.claude/rules/web/patterns.md +79 -0
  84. package/.claude/rules/web/performance.md +64 -0
  85. package/.claude/rules/web/security.md +57 -0
  86. package/.claude/rules/web/testing.md +55 -0
  87. package/.claude/settings.json +37 -0
  88. package/.claude/settings.local.json +38 -0
  89. package/.claude/skills/ado-integration/SKILL.md +44 -1
  90. package/.claude/skills/agent-harness-construction/SKILL.md +77 -0
  91. package/.claude/skills/agent-introspection-debugging/SKILL.md +157 -0
  92. package/.claude/skills/ai-regression-testing/SKILL.md +364 -0
  93. package/.claude/skills/api-design/SKILL.md +528 -0
  94. package/.claude/skills/architecture-decision-records/SKILL.md +184 -0
  95. package/.claude/skills/backend-patterns/SKILL.md +602 -0
  96. package/.claude/skills/benchmark/SKILL.md +98 -0
  97. package/.claude/skills/browser-qa/SKILL.md +92 -0
  98. package/.claude/skills/canary-watch/SKILL.md +104 -0
  99. package/.claude/skills/tas-conventions/SKILL.md +51 -3
  100. package/.claude/skills/tas-implementation-complete/SKILL.md +97 -0
  101. package/.claude/skills/tas-tdd/SKILL.md +72 -16
  102. package/.tas/README.md +29 -24
  103. package/.tas/tas-example.yaml +2 -1
  104. package/.tas/templates/SAD.md +221 -11
  105. package/.tas/templates/Story.md +18 -18
  106. package/CLAUDE-Example.md +1 -1
  107. package/README.md +20 -5
  108. package/bin/cli.js +13 -6
  109. package/lib/install.js +68 -6
  110. package/package.json +2 -2
  111. package/.claude/commands/tas-dev-story.md +0 -61
  112. package/.claude/commands/tas-review-code.md +0 -42
  113. package/.claude/commands/tas-security-check.md +0 -30
@@ -0,0 +1,104 @@
1
+ # /tas-review $ARGUMENTS
2
+
3
+ Review code thay đổi gần nhất hoặc một file/PR cụ thể.
4
+ Bao gồm hygiene scan, test run, và parallel multi-agent review.
5
+
6
+ ## Stack Detection
7
+ Đọc `.claude/rules/common/stack-detection.md`.
8
+
9
+ ## Hành động
10
+
11
+ ### Bước 1 — Xác định scope review
12
+ `$ARGUMENTS` có thể là: file path, Story ID, hoặc để trống (review git diff).
13
+ - Nếu trống: lấy `git diff HEAD` (staged + unstaged) hoặc last commit
14
+ - Nếu Story ID: tìm file Story tương ứng để lấy danh sách files đã thay đổi
15
+ - Nếu file path: review trực tiếp file đó
16
+
17
+ ### Bước 2 — Pre-checks (PHẢI pass mới tiếp tục)
18
+
19
+ **Hygiene scan** — scan nhanh các files trong scope:
20
+ - Debug code còn sót: `console.log`, `print(`, `Debug.WriteLine`, `debugger`
21
+ - Secrets hardcoded: password/key/token/secret gán bằng string literal
22
+ - Commented-out code block lớn (>5 dòng) không có comment lý do
23
+
24
+ → Nếu có blocker: liệt kê ngay, yêu cầu fix trước khi tiếp tục.
25
+
26
+ **Run tests** — detect từ project structure:
27
+ - `package.json` → `npm test`
28
+ - `*.csproj` / `*.sln` → `dotnet test`
29
+ - `pytest.ini` / `pyproject.toml` → `python -m pytest`
30
+
31
+ → Nếu fail: dừng, list lỗi, KHÔNG tiếp tục review.
32
+ → Nếu không detect được: ghi chú "No test runner detected" và tiếp tục.
33
+
34
+ ### Bước 3 — Parallel Multi-Agent Review
35
+
36
+ Launch các agents ĐỒNG THỜI (không chờ nhau):
37
+
38
+ **Agent 1 — `code-reviewer`** (luôn chạy):
39
+ > Review [scope]. Đọc `.tas/checklists/code-review.md` và `.claude/rules/common/code-review.md`.
40
+ > Tập trung: naming, architecture alignment, error handling, DRY, function size, nesting depth.
41
+ > Format: findings nhóm theo Critical / High / Medium / Low, mỗi finding có file:line và fix cụ thể.
42
+
43
+ **Agent 2 — `security-reviewer`** (luôn chạy):
44
+ > Security audit [scope]. Đọc `.claude/rules/common/security.md`.
45
+ > Tập trung: OWASP Top 10, injection, hardcoded secrets, auth/authz, data exposure.
46
+ > Format: findings nhóm theo Critical / High / Medium / Low, mỗi finding có file:line và remediation.
47
+
48
+ **Agent 3 — Language reviewer** (dựa theo `lang_agent` từ stack detection):
49
+ > Language-specific review [scope].
50
+ > Đọc `.claude/rules/[stack]/coding-style.md` và `.claude/rules/[stack]/patterns.md`.
51
+ > Tập trung: async/await patterns, null handling, type safety, anti-patterns đặc thù của stack.
52
+ > Format: findings theo Critical / High / Medium / Low với file:line.
53
+
54
+ **Agent 4 — `aws-reviewer`** (chỉ khi `infra_agent = aws-reviewer`):
55
+ > AWS infrastructure review [scope].
56
+ > Tập trung: IAM policies, secrets trong env/config, S3 permissions, Lambda security.
57
+ > Format: findings theo Critical / High / Medium / Low.
58
+
59
+ Chờ TẤT CẢ agents hoàn thành, sau đó tổng hợp.
60
+
61
+ ### Bước 4 — Tổng hợp kết quả
62
+
63
+ Gộp findings từ tất cả agents, deduplicate (cùng file:line từ nhiều agent → gộp lại), sort theo severity:
64
+
65
+ ```
66
+ ## Review Summary
67
+
68
+ ### Critical (phải fix trước khi merge)
69
+ - [file:line] Issue — Fix: ...
70
+
71
+ ### High (nên fix trước khi merge)
72
+ - [file:line] Issue — Fix: ...
73
+
74
+ ### Medium (cân nhắc fix)
75
+ - [file:line] Issue — Fix: ...
76
+
77
+ ### Low / Info (optional)
78
+ - [file:line] Issue — Fix: ...
79
+ ```
80
+
81
+ ## Sau khi review
82
+
83
+ **Nếu có Critical/High:**
84
+ → Liệt kê rõ, yêu cầu human fix. KHÔNG tiếp tục flow.
85
+
86
+ **Nếu chỉ có Medium/Low:**
87
+ → List gợi ý, hỏi human có muốn fix không, sau đó tiếp tục.
88
+
89
+ **Khi human xác nhận đã fix:**
90
+ 1. Tick `- [x] Code review passed` trong section `## Definition of Done` của Story
91
+ 2. Hỏi: "Bạn đã tự test lại ở local chưa? Nếu OK, có muốn chuyển ticket sang Deploy Test không?"
92
+ 3. Nếu Yes:
93
+ a. Cập nhật `Status:` trong Story → `Deploy Test`
94
+ b. Thêm dòng Changelog trong Story: ngày, "Code review passed, moved to Deploy Test"
95
+ c. Cập nhật `Status:` trong Feature cha → `In Progress`, update bảng Stories
96
+ d. Thêm Changelog trong Feature
97
+ e. Cập nhật `project-status.yaml`
98
+ f. Gợi ý: chạy `/ado-update story <ado-id> --status "Deploy Test"` nếu dùng ADO
99
+
100
+ ## Nguyên tắc
101
+ - Review khách quan — chỉ ra file:line cụ thể và lý do
102
+ - Đề xuất fix cụ thể, không chỉ nói "code xấu"
103
+ - Check xem code có vi phạm ADR nào không (đọc từ Technical Notes trong Story)
104
+ - KHÔNG tự động chuyển status mà không có xác nhận của human
@@ -1,4 +1,4 @@
1
- # /tas-sad $ARGUMENTS
1
+ # /tas-sad $ARGUMENTS
2
2
 
3
3
  Vai trò: SE - Software Engineer
4
4
  Tạo hoặc cập nhật Solution Architecture Document.
@@ -15,6 +15,7 @@ Tạo hoặc cập nhật Solution Architecture Document.
15
15
  ### Chế độ CREATE (file chưa tồn tại):
16
16
  5. Cần context từ .tas/templates/SAD.md
17
17
  6. Tạo file docs/sad.md theo template SAD của Torus
18
+ 7. Cập nhật `project-status.yaml` theo `.claude/rules/common/project-status.md` — thêm `artifacts.sad`.
18
19
 
19
20
  ### Chế độ UPDATE (file đã tồn tại):
20
21
  5. Cần context từ docs/sad.md hiện tại
@@ -22,6 +23,7 @@ Tạo hoặc cập nhật Solution Architecture Document.
22
23
  7. Cập nhật file, giữ nguyên các section không thay đổi
23
24
  8. Thêm dòng vào section Changelog cuối file
24
25
  9. Nếu thay đổi là quyết định kiến trúc quan trọng, gợi ý user chạy /tas-adr
26
+ 10. Cập nhật `project-status.yaml` theo `.claude/rules/common/project-status.md` — cập nhật `artifacts.sad`.
25
27
 
26
28
  ## Quy tắc Mermaid
27
29
  - Các sơ đồ C4 PHẢI dùng Mermaid flow diagram
@@ -0,0 +1,80 @@
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à: file path, directory, hoặc để trống (scan toàn bộ codebase).
12
+ Đọc `.tas/checklists/security.md` để lấy checklist.
13
+
14
+ ### Bước 2 — Parallel Security Scan
15
+
16
+ Launch các agents ĐỒNG THỜI dựa theo stack:
17
+
18
+ **Agent 1 — `security-reviewer`** (luôn chạy):
19
+ > Security audit [scope].
20
+ > Đọc `.claude/rules/common/security.md`.
21
+ > Kiểm tra OWASP Top 10: injection, broken auth, XSS, IDOR, security misconfiguration,
22
+ > sensitive data exposure, insecure deserialization, vulnerable components, logging/monitoring.
23
+ > Kiểm tra thêm: hardcoded secrets, CORS config, anti-forgery tokens, rate limiting.
24
+ > Format: findings theo Critical / High / Medium / Low với file:line và remediation cụ thể.
25
+ > Mỗi finding có: status = Open.
26
+
27
+ **Agent 2 — `database-reviewer`** (chỉ khi `db_agent = database-reviewer`):
28
+ > Database security review [scope].
29
+ > Tập trung: parameterized queries vs string concatenation, ORM raw query usage,
30
+ > sensitive data stored in plaintext, missing field-level encryption, excessive permissions.
31
+ > Format: findings theo Critical / High / Medium / Low với file:line và remediation.
32
+
33
+ **Agent 3 — `aws-reviewer`** (chỉ khi `infra_agent = aws-reviewer`):
34
+ > AWS infrastructure security review [scope].
35
+ > Tập trung: IAM overpermission, S3 public access, secrets trong env/config/code,
36
+ > Lambda environment variables, API Gateway auth, VPC security groups.
37
+ > Format: findings theo Critical / High / Medium / Low với file:line và remediation.
38
+
39
+ Chờ TẤT CẢ agents hoàn thành.
40
+
41
+ ### Bước 3 — Tổng hợp và lưu báo cáo
42
+
43
+ Gộp findings từ tất cả agents, deduplicate (cùng file:line → gộp), sort theo severity.
44
+
45
+ Kiểm tra `docs/security-report.md`:
46
+ - **Chưa có**: tạo mới theo template `.tas/templates/Security-Report.md`
47
+ - **Đã có**: append report mới, cập nhật status findings cũ nếu đã được fix
48
+
49
+ Nội dung report bao gồm:
50
+ - Scan date, scope, stack
51
+ - Findings theo Critical / High / Medium / Low
52
+ - Mỗi finding: file:line, mô tả, remediation, status (Open / Fixed / Accepted Risk)
53
+ - Summary: tổng số findings mỗi severity, số đã fix vs còn open
54
+
55
+ ### Bước 4 — Cập nhật project-status.yaml
56
+
57
+ ```yaml
58
+ artifacts:
59
+ security_report:
60
+ file: docs/security-report.md
61
+ status: [Critical findings present | Clean]
62
+ last_updated: [ngày hôm nay]
63
+ ```
64
+
65
+ ### Bước 5 — Hành động tiếp theo
66
+
67
+ Nếu có **Critical findings**:
68
+ → Liệt kê rõ, yêu cầu fix ngay trước khi deploy bất kỳ môi trường nào.
69
+
70
+ Nếu có **High findings**:
71
+ → Liệt kê, khuyến nghị fix trước khi merge vào main.
72
+
73
+ Nếu chỉ có **Medium/Low**:
74
+ → Tóm tắt, gợi ý fix theo thứ tự ưu tiên.
75
+
76
+ ## Nguyên tắc
77
+ - Phân loại: Critical / High / Medium / Low
78
+ - Mỗi finding phải có recommended fix cụ thể
79
+ - Finding có status: Open | In Progress | Fixed | Accepted Risk
80
+ - KHÔNG hardcode fix — đề xuất remediation pattern, không viết code thay thế
@@ -0,0 +1,50 @@
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,50 +1,87 @@
1
- # /tas-story $ARGUMENTS
1
+ # /tas-story $ARGUMENTS
2
2
 
3
3
  Vai trò: PE - Product Engineer
4
4
  Tạo mới hoặc cập nhật User Story document.
5
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
+
6
18
  ## Prerequisite
7
19
  - Ít nhất một Feature phải tồn tại
8
20
 
9
21
  ## Hành động
10
- 1. Cần context từ root/tas.yaml
11
- 2. Cần context từ .tas/templates/Story.md
12
- 3. Xác định chế độ dựa vào $ARGUMENTS:
13
-
14
- ### Chế độ CREATE ($ARGUMENTS là mô tả Story mới, hoặc không có $ARGUMENTS):
15
- 4. Đọc project.code từ root/tas.yaml (ví dụ: "MP"). Liệt kê Features hiện có (quét docs/epics/{code}-Epic-*/{code}-Feature-*/), hỏi user Story thuộc Feature nào
16
- 5. **Đọc đầy đủ context để trích xuất thông tin vào Story:**
17
- - Đọc Feature đã chọn
18
- - Đọc PRD (nếu có)
19
- - Đọc SAD (nếu có)
20
- - Đọc ADRs liên quan (nếu có)
21
- 6. Quét thư mục Feature đã chọn để xác định số thứ tự Story
22
- 7. Tạo file docs/epics/{code}-Epic-{NNN}-{slug}/{code}-Feature-{NNN}-{slug}/{code}-Story-{NNN}-{slug}.md
23
- 8. **Story phải NHÚNG TẤT CẢ thông tin cần thiết** để SE khi coding chỉ cần đọc file Story này, KHÔNG cần đọc lại file nào khác:
24
- - User story format: "As a [role], I want [goal], so that [benefit]"
25
- - Acceptance criteria (Given/When/Then format)
26
- - Technical notes: files cần thay đổi, patterns áp dụng, constraints từ SAD/ADR
27
- - Context từ PRD (chỉ thêm section nếu có business requirements đặc biệt)
28
- - Context từ SAD/ADR (chỉ thêm section nếu có architecture decisions, patterns cần tuân thủ)
29
- - Prerequisites từ Feature (chỉ thêm section nếu có dependency)
30
- - Unit Test Cases
31
- - Definition of Done checklist
32
- 9. **Test Case Prompting**: Sau khi PE điền acceptance criteria, TỰ ĐỘNG hỏi thêm:
33
- - "Ngoài happy path, có edge case nào cần test không?" (ví dụ: input rỗng, giá trị biên, concurrent access)
34
- - "Có negative case nào cần cover?" (ví dụ: unauthorized, invalid data, timeout)
35
- - "Có dependency nào cần mock khi test?" (ví dụ: external API, database state)
36
- Ghi tất cả vào section Unit Test Cases trong Story.
37
-
38
- ### Chế độ UPDATE ($ARGUMENTS Story ID, dụ: "Story-005"):
39
- 4. Tìm file Story trong cây docs/epics/ (dùng glob)
40
- 5. Cần context từ file Story hiện tại
41
- 6. Hỏi user cần thay đổi gì (cập nhật AC, đổi status, thêm test cases...)
42
- 7. Cập nhật file, thêm changelog
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 `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`.
43
83
 
44
84
  ## Nguyên tắc
45
- - Story phải nhỏ đủ để hoàn thành trong 1-3 ngày
46
- - PHẢI acceptance criteria dạng Given/When/Then
47
- - **Single Source of Truth:** Story file phải chứa TẤT CẢ thông tin cần thiết từ PRD, SAD, ADR, Feature. SE khi coding chỉ cần đọc file Story-*.md, KHÔNG cần đọc lại file nào khác để tiết kiệm token.
48
- - Chỉ nhúng thông tin liên quan, không dư thừa - linh hoạt theo từng Story
49
- - Unit Test Cases PHẢI cover: happy path, edge cases, negative cases
50
- - Story status: New -> Committed -> In Progress -> Deploy Test -> Verify Test -> Deploy Stag -> Verify Stag -> Deploy Prod | Verify Prod -> Done
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
@@ -14,6 +14,14 @@ Verify Feature trên môi trường Staging (Phase 2).
14
14
  4. Cần context từ file Feature hiện tại (đặc biệt section Integration Test Cases và E2E Test Cases)
15
15
 
16
16
  ### Workflow verify:
17
+ 4.5. **Launch `e2e-runner`** (nếu Feature có 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
+
17
25
  5. Hiển thị checklist từ 2 section test trong Feature:
18
26
  a. **Integration Test Cases**: Liệt kê từng test case, hỏi PE kết quả (Pass/Fail)
19
27
  b. **E2E / Acceptance Test Cases**: Liệt kê từng test case, hỏi PE kết quả (Pass/Fail)
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * PostToolUse Hook: Auto format/lint source files after Write/Edit/MultiEdit
4
+ *
5
+ * Detects file extension and runs the appropriate formatter using project-local tools:
6
+ * .ts/.tsx/.js/.jsx → prettier (via npx/yarn)
7
+ * .py → ruff format (preferred) or black
8
+ * .cs → dotnet format --include <file>
9
+ *
10
+ * Uses project-local binaries only — never installs packages globally.
11
+ * Silently skips if the tool is not installed in the project.
12
+ *
13
+ * Hook input (stdin): JSON with tool_input.file_path
14
+ */
15
+
16
+ 'use strict';
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const { execSync } = require('child_process');
21
+
22
+ // --- Read hook input ---
23
+ let input;
24
+ try {
25
+ const raw = fs.readFileSync('/dev/stdin', 'utf8');
26
+ input = JSON.parse(raw);
27
+ } catch {
28
+ process.exit(0);
29
+ }
30
+
31
+ const filePath = (input.tool_input || {}).file_path || '';
32
+ if (!filePath) process.exit(0);
33
+
34
+ const ext = path.extname(filePath).toLowerCase();
35
+ const fileName = path.basename(filePath);
36
+
37
+ // Skip non-source files (markdown, yaml, json config, etc.)
38
+ const SOURCE_EXTS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.cs']);
39
+ if (!SOURCE_EXTS.has(ext)) process.exit(0);
40
+
41
+ // --- Helper: run command, return true on success ---
42
+ function run(cmd, cwd) {
43
+ try {
44
+ execSync(cmd, { cwd, stdio: 'pipe' });
45
+ return true;
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ // --- Helper: find repo root (where package.json / pyproject.toml / *.sln lives) ---
52
+ function findRoot(startDir, markers) {
53
+ let dir = path.resolve(startDir);
54
+ for (let i = 0; i < 10; i++) {
55
+ if (markers.some(m => fs.existsSync(path.join(dir, m)))) return dir;
56
+ const parent = path.dirname(dir);
57
+ if (parent === dir) break;
58
+ dir = parent;
59
+ }
60
+ return null;
61
+ }
62
+
63
+ // ─── TypeScript / JavaScript ─────────────────────────────────────────────────
64
+ if (['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext)) {
65
+ const root = findRoot(path.dirname(filePath), ['package.json']);
66
+ if (!root) process.exit(0);
67
+
68
+ const pkg = path.join(root, 'package.json');
69
+ let hasScript = false;
70
+ try {
71
+ const pkgJson = JSON.parse(fs.readFileSync(pkg, 'utf8'));
72
+ hasScript = !!(pkgJson.scripts && pkgJson.scripts.format);
73
+ } catch { /* ignore */ }
74
+
75
+ // Prefer project format script → npx prettier → yarn prettier
76
+ const formatted =
77
+ (hasScript && run(`npm run format -- --write "${filePath}"`, root)) ||
78
+ run(`npx --no-install prettier --write "${filePath}"`, root) ||
79
+ run(`yarn prettier --write "${filePath}"`, root);
80
+
81
+ if (formatted) {
82
+ console.log(`[Format] ${fileName}`);
83
+ }
84
+ }
85
+
86
+ // ─── Python ──────────────────────────────────────────────────────────────────
87
+ else if (ext === '.py') {
88
+ const root = findRoot(path.dirname(filePath), ['pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt']);
89
+ const cwd = root || path.dirname(filePath);
90
+
91
+ const formatted =
92
+ run(`ruff format "${filePath}"`, cwd) ||
93
+ run(`python -m ruff format "${filePath}"`, cwd) ||
94
+ run(`black "${filePath}"`, cwd) ||
95
+ run(`python -m black "${filePath}"`, cwd);
96
+
97
+ if (formatted) {
98
+ console.log(`[Format] ${fileName}`);
99
+ }
100
+ }
101
+
102
+ // ─── C# ──────────────────────────────────────────────────────────────────────
103
+ else if (ext === '.cs') {
104
+ // Find nearest .csproj
105
+ function findCsproj(startDir) {
106
+ let dir = path.resolve(startDir);
107
+ for (let i = 0; i < 8; i++) {
108
+ const files = fs.readdirSync(dir).filter(f => f.endsWith('.csproj'));
109
+ if (files.length > 0) return { cwd: dir, proj: path.join(dir, files[0]) };
110
+ const parent = path.dirname(dir);
111
+ if (parent === dir) break;
112
+ dir = parent;
113
+ }
114
+ return null;
115
+ }
116
+
117
+ const result = findCsproj(path.dirname(filePath));
118
+ if (!result) process.exit(0);
119
+
120
+ const formatted = run(
121
+ `dotnet format "${result.proj}" --include "${filePath}" --no-restore`,
122
+ result.cwd
123
+ );
124
+ if (formatted) {
125
+ console.log(`[Format] ${fileName}`);
126
+ }
127
+ }
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Stop Hook: End-of-session verification
4
+ *
5
+ * Runs when Claude Code session ends. Performs:
6
+ * 1. Auto-detects test runner and runs the test suite
7
+ * 2. Checks if project-status.yaml was updated today
8
+ * 3. Prints a summary of pass/fail checks
9
+ *
10
+ * Designed to be non-blocking — all failures are reported as warnings,
11
+ * not hard errors, so the session can still end cleanly.
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const { execSync } = require('child_process');
19
+
20
+ const checks = [];
21
+
22
+ // --- Helper: run command, return { ok, output } ---
23
+ function run(cmd, cwd) {
24
+ try {
25
+ const output = execSync(cmd, { cwd, stdio: 'pipe', timeout: 60_000 }).toString();
26
+ return { ok: true, output };
27
+ } catch (err) {
28
+ return { ok: false, output: (err.stderr || err.stdout || err.message || '').toString() };
29
+ }
30
+ }
31
+
32
+ // --- Find repo root (cwd of the session) ---
33
+ const cwd = process.cwd();
34
+
35
+ // ─── 1. Run test suite ────────────────────────────────────────────────────────
36
+ let testRan = false;
37
+
38
+ // Node.js / npm
39
+ if (fs.existsSync(path.join(cwd, 'package.json'))) {
40
+ let hasTestScript = false;
41
+ try {
42
+ const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
43
+ hasTestScript = !!(pkg.scripts && pkg.scripts.test &&
44
+ pkg.scripts.test !== 'echo "Error: no test specified" && exit 1');
45
+ } catch { /* ignore */ }
46
+
47
+ if (hasTestScript) {
48
+ const result = run('npm test -- --passWithNoTests 2>&1', cwd);
49
+ checks.push(result.ok
50
+ ? '✓ Tests passed (npm test)'
51
+ : '✗ Tests FAILED (npm test) — fix before committing'
52
+ );
53
+ testRan = true;
54
+ }
55
+ }
56
+
57
+ // .NET
58
+ if (!testRan) {
59
+ const csprojFiles = (() => {
60
+ try {
61
+ return fs.readdirSync(cwd).filter(f => f.endsWith('.csproj') || f.endsWith('.sln'));
62
+ } catch { return []; }
63
+ })();
64
+
65
+ if (csprojFiles.length > 0) {
66
+ const result = run('dotnet test --no-build --logger "console;verbosity=minimal" 2>&1', cwd);
67
+ checks.push(result.ok
68
+ ? '✓ Tests passed (dotnet test)'
69
+ : '✗ Tests FAILED (dotnet test) — fix before committing'
70
+ );
71
+ testRan = true;
72
+ }
73
+ }
74
+
75
+ // Python (pytest)
76
+ if (!testRan) {
77
+ const hasPytest =
78
+ fs.existsSync(path.join(cwd, 'pytest.ini')) ||
79
+ fs.existsSync(path.join(cwd, 'pyproject.toml')) ||
80
+ fs.existsSync(path.join(cwd, 'setup.cfg'));
81
+
82
+ if (hasPytest) {
83
+ const result = run('python -m pytest -q --tb=no 2>&1', cwd);
84
+ checks.push(result.ok
85
+ ? '✓ Tests passed (pytest)'
86
+ : '✗ Tests FAILED (pytest) — fix before committing'
87
+ );
88
+ testRan = true;
89
+ }
90
+ }
91
+
92
+ // ─── 2. Check project-status.yaml updated today ──────────────────────────────
93
+ const statusFile = path.join(cwd, 'project-status.yaml');
94
+ if (fs.existsSync(statusFile)) {
95
+ const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
96
+ try {
97
+ const content = fs.readFileSync(statusFile, 'utf8');
98
+ if (content.includes(today)) {
99
+ checks.push('✓ project-status.yaml updated today');
100
+ } else {
101
+ checks.push('⚠ project-status.yaml not updated today — run /tas-status to sync');
102
+ }
103
+ } catch {
104
+ checks.push('⚠ Could not read project-status.yaml');
105
+ }
106
+ }
107
+
108
+ // ─── 3. Remind about story status ────────────────────────────────────────────
109
+ checks.push('→ Next: /tas-review-code before moving story to Deploy Test');
110
+
111
+ // ─── Output ──────────────────────────────────────────────────────────────────
112
+ if (checks.length > 0) {
113
+ console.log('\n[TAS] Session end checks:');
114
+ checks.forEach(c => console.log(' ' + c));
115
+ console.log('');
116
+ }
File without changes