dw-kit 1.2.0 → 1.2.1

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.
@@ -1,74 +1,85 @@
1
- #!/usr/bin/env bash
2
- # .claude/hooks/session-init.sh — dw-kit v1.2
3
- # Inject active task context vào đầu session, giải quyết "session amnesia".
4
- # Chỉ chạy một lần mỗi session (track bằng session_id).
5
- #
6
- # UserPromptSubmit hook
7
- # Stdout output → được inject vào context của user prompt
8
- # exit 0 = allow
9
-
10
- INPUT=$(cat)
11
-
12
- SESSION_ID=$(echo "$INPUT" | node -e "
13
- let d='';
14
- process.stdin.on('data',c=>d+=c).on('end',()=>{
15
- try{ process.stdout.write(JSON.parse(d).session_id||''); }catch(e){}
16
- });
17
- " 2>/dev/null || true)
18
-
19
- [ -z "$SESSION_ID" ] && exit 0
20
-
21
- # ── Track session: chỉ chạy một lần mỗi session ───────────────────────────────
22
- SESSION_MARKER="/tmp/dw-session-${SESSION_ID}"
23
- if [ -f "$SESSION_MARKER" ]; then
24
- exit 0
25
- fi
26
- touch "$SESSION_MARKER" 2>/dev/null || true
27
-
28
- # ── Scan .dw/tasks/ tìm tasks In Progress ─────────────────────────────────────
29
- PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
30
- TASKS_DIR="$PROJECT_DIR/.dw/tasks"
31
-
32
- [ ! -d "$TASKS_DIR" ] && exit 0
33
-
34
- ACTIVE_TASKS=()
35
- ACTIVE_SUMMARIES=()
36
-
37
- while IFS= read -r progress_file; do
38
- if grep -q "Trạng thái: In Progress" "$progress_file" 2>/dev/null; then
39
- task_name=$(basename "$(dirname "$progress_file")")
40
-
41
- # Extract current subtask (dòng "In Progress" trong table)
42
- current_st=$(grep -m1 "In Progress" "$progress_file" 2>/dev/null \
43
- | grep -oP '\| ST-\d+ \| [^|]+' | sed 's/|//g' | xargs 2>/dev/null || echo "")
44
-
45
- # Extract last handoff note nếu có
46
- last_handoff=$(awk '/## Handoff Notes/{found=1} found{print}' "$progress_file" 2>/dev/null \
47
- | grep -m1 "Bước tiếp theo:" | sed 's/.*Bước tiếp theo://' | xargs 2>/dev/null || echo "")
48
-
49
- ACTIVE_TASKS+=("$task_name")
50
- summary="$task_name"
51
- [ -n "$current_st" ] && summary="$summary — $current_st"
52
- [ -n "$last_handoff" ] && summary="$summary | Next: $last_handoff"
53
- ACTIVE_SUMMARIES+=("$summary")
54
- fi
55
- done < <(find "$TASKS_DIR" -name "*-progress.md" 2>/dev/null)
56
-
57
- [ ${#ACTIVE_TASKS[@]} -eq 0 ] && exit 0
58
-
59
- # ── Output context vào stdout (injected vào conversation) ─────────────────────
60
- echo ""
61
- echo "---"
62
- echo "[dw-kit session-init] Task đang in-progress:"
63
- for summary in "${ACTIVE_SUMMARIES[@]}"; do
64
- echo "$summary"
65
- done
66
- if [ ${#ACTIVE_TASKS[@]} -eq 1 ]; then
67
- echo "Context: .dw/tasks/${ACTIVE_TASKS[0]}/"
68
- else
69
- echo "Nhiều tasks đang active — hỏi user task nào cần tiếp tục."
70
- fi
71
- echo "---"
72
- echo ""
73
-
74
- exit 0
1
+ #!/usr/bin/env bash
2
+ # .claude/hooks/session-init.sh — dw-kit v1.2
3
+ # Inject active task context vào đầu session, giải quyết "session amnesia".
4
+ # Chỉ chạy một lần mỗi session (track bằng session_id).
5
+ #
6
+ # UserPromptSubmit hook
7
+ # Stdout output → được inject vào context của user prompt
8
+ # exit 0 = allow
9
+
10
+ INPUT=$(cat)
11
+
12
+ SESSION_ID=$(echo "$INPUT" | node -e "
13
+ let d='';
14
+ process.stdin.on('data',c=>d+=c).on('end',()=>{
15
+ try{ process.stdout.write(JSON.parse(d).session_id||''); }catch(e){}
16
+ });
17
+ " 2>/dev/null || true)
18
+
19
+ # Tier 2: pure-bash grep fallback works without node (e.g. node absent or CRLF-corrupt shebang)
20
+ if [ -z "$SESSION_ID" ]; then
21
+ SESSION_ID=$(echo "$INPUT" | grep -o '"session_id":"[^"]*"' | cut -d'"' -f4 2>/dev/null || true)
22
+ fi
23
+
24
+ # Tier 3: project-scoped + hour-scoped stable ID
25
+ # cksum is POSIX — available on Linux, macOS, and Git Bash on Windows.
26
+ # Ensures marker is always created so re-injection is suppressed even when tiers 1+2 fail.
27
+ if [ -z "$SESSION_ID" ]; then
28
+ _dir_hash=$(pwd | cksum | cut -d' ' -f1)
29
+ SESSION_ID="fallback-${_dir_hash}-$(date +%Y%m%d-%H)"
30
+ fi
31
+
32
+ # ── Track session: chỉ chạy một lần mỗi session ───────────────────────────────
33
+ SESSION_MARKER="/tmp/dw-session-${SESSION_ID}"
34
+ if [ -f "$SESSION_MARKER" ]; then
35
+ exit 0
36
+ fi
37
+ touch "$SESSION_MARKER" 2>/dev/null || true
38
+
39
+ # ── Scan .dw/tasks/ tìm tasks In Progress ─────────────────────────────────────
40
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
41
+ TASKS_DIR="$PROJECT_DIR/.dw/tasks"
42
+
43
+ [ ! -d "$TASKS_DIR" ] && exit 0
44
+
45
+ ACTIVE_TASKS=()
46
+ ACTIVE_SUMMARIES=()
47
+
48
+ while IFS= read -r progress_file; do
49
+ if grep -q "Trạng thái: In Progress" "$progress_file" 2>/dev/null; then
50
+ task_name=$(basename "$(dirname "$progress_file")")
51
+
52
+ # Extract current subtask (dòng "In Progress" trong table)
53
+ current_st=$(grep -m1 "In Progress" "$progress_file" 2>/dev/null \
54
+ | grep -oP '\| ST-\d+ \| [^|]+' | sed 's/|//g' | xargs 2>/dev/null || echo "")
55
+
56
+ # Extract last handoff note nếu có
57
+ last_handoff=$(awk '/## Handoff Notes/{found=1} found{print}' "$progress_file" 2>/dev/null \
58
+ | grep -m1 "Bước tiếp theo:" | sed 's/.*Bước tiếp theo://' | xargs 2>/dev/null || echo "")
59
+
60
+ ACTIVE_TASKS+=("$task_name")
61
+ summary="$task_name"
62
+ [ -n "$current_st" ] && summary="$summary — $current_st"
63
+ [ -n "$last_handoff" ] && summary="$summary | Next: $last_handoff"
64
+ ACTIVE_SUMMARIES+=("$summary")
65
+ fi
66
+ done < <(find "$TASKS_DIR" -name "*-progress.md" 2>/dev/null)
67
+
68
+ [ ${#ACTIVE_TASKS[@]} -eq 0 ] && exit 0
69
+
70
+ # ── Output context vào stdout (injected vào conversation) ─────────────────────
71
+ echo ""
72
+ echo "---"
73
+ echo "[dw-kit session-init] Task đang in-progress:"
74
+ for summary in "${ACTIVE_SUMMARIES[@]}"; do
75
+ echo " • $summary"
76
+ done
77
+ if [ ${#ACTIVE_TASKS[@]} -eq 1 ]; then
78
+ echo "Context: .dw/tasks/${ACTIVE_TASKS[0]}/"
79
+ else
80
+ echo "Nhiều tasks đang active — hỏi user task nào cần tiếp tục."
81
+ fi
82
+ echo "---"
83
+ echo ""
84
+
85
+ exit 0
@@ -1,37 +1,37 @@
1
- # Code Style & Conventions
2
-
3
- ## Nguyên tắc chung
4
- - Đặt tên biến/hàm rõ ràng, tự giải thích (self-documenting)
5
- - Ưu tiên đơn giản, dễ đọc hơn clever code
6
- - Mỗi function làm MỘT việc
7
- - Comments giải thích WHY, không phải WHAT
8
- - Xử lý errors ở đầu function (guard clauses / early return)
9
-
10
- ## Naming Conventions
11
- - Variables/Functions: camelCase
12
- - Classes/Components: PascalCase
13
- - Constants: UPPER_SNAKE_CASE
14
- - Files: kebab-case hoặc theo convention của framework
15
- - Directories: kebab-case
16
-
17
- ## File Organization
18
- - 1 component/class per file (trừ khi strongly related)
19
- - Group imports: external → internal → relative
20
- - Export ở cuối file hoặc inline (nhất quán trong project)
21
-
22
- ## Error Handling
23
- - KHÔNG swallow errors (catch rỗng)
24
- - Log đủ context để debug (error message, input data, stack)
25
- - Dùng custom error types cho domain errors
26
- - Validate input ở boundary (API, form, external data)
27
-
28
- ## Testing
29
- - Test file cùng tên với source: `foo.ts` → `foo.test.ts` hoặc `foo.spec.ts`
30
- - Mỗi test case kiểm tra MỘT behavior
31
- - Test name mô tả expected behavior: "should return error when input is empty"
32
- - Arrange → Act → Assert pattern
33
- - KHÔNG mock internal implementation details
34
-
35
- ## NOTE
36
- Đây là quy tắc mặc định. Team tùy chỉnh theo stack cụ thể của dự án.
37
- Thêm framework-specific rules vào file này hoặc tạo file riêng trong `.claude/rules/`.
1
+ # Code Style & Conventions
2
+
3
+ ## Nguyên tắc chung
4
+ - Đặt tên biến/hàm rõ ràng, tự giải thích (self-documenting)
5
+ - Ưu tiên đơn giản, dễ đọc hơn clever code
6
+ - Mỗi function làm MỘT việc
7
+ - Comments giải thích WHY, không phải WHAT
8
+ - Xử lý errors ở đầu function (guard clauses / early return)
9
+
10
+ ## Naming Conventions
11
+ - Variables/Functions: camelCase
12
+ - Classes/Components: PascalCase
13
+ - Constants: UPPER_SNAKE_CASE
14
+ - Files: kebab-case hoặc theo convention của framework
15
+ - Directories: kebab-case
16
+
17
+ ## File Organization
18
+ - 1 component/class per file (trừ khi strongly related)
19
+ - Group imports: external → internal → relative
20
+ - Export ở cuối file hoặc inline (nhất quán trong project)
21
+
22
+ ## Error Handling
23
+ - KHÔNG swallow errors (catch rỗng)
24
+ - Log đủ context để debug (error message, input data, stack)
25
+ - Dùng custom error types cho domain errors
26
+ - Validate input ở boundary (API, form, external data)
27
+
28
+ ## Testing
29
+ - Test file cùng tên với source: `foo.ts` → `foo.test.ts` hoặc `foo.spec.ts`
30
+ - Mỗi test case kiểm tra MỘT behavior
31
+ - Test name mô tả expected behavior: "should return error when input is empty"
32
+ - Arrange → Act → Assert pattern
33
+ - KHÔNG mock internal implementation details
34
+
35
+ ## NOTE
36
+ Đây là quy tắc mặc định. Team tùy chỉnh theo stack cụ thể của dự án.
37
+ Thêm framework-specific rules vào file này hoặc tạo file riêng trong `.claude/rules/`.
@@ -1,37 +1,37 @@
1
- # Commit Standards
2
-
3
- ## Format
4
- ```
5
- <type>(<scope>): <mô tả tiếng Việt hoặc tiếng Anh>
6
-
7
- [Body - chi tiết thay đổi, lý do]
8
- [Blank line]
9
- [Footer - breaking changes, references]
10
-
11
- Co-Authored-By: Claude <noreply@anthropic.com>
12
- ```
13
-
14
- ## Types
15
- | Type | Khi nào dùng |
16
- |------|-------------|
17
- | `feat` | Tính năng mới |
18
- | `fix` | Sửa lỗi |
19
- | `refactor` | Tái cấu trúc, không thay đổi behavior |
20
- | `test` | Thêm/sửa tests |
21
- | `docs` | Tài liệu, comments |
22
- | `chore` | Build, config, dependencies |
23
- | `style` | Format, whitespace (không thay đổi logic) |
24
- | `perf` | Cải thiện performance |
25
-
26
- ## Quy tắc
27
- - Mỗi commit = 1 subtask hoặc 1 đơn vị logic hoàn chỉnh
28
- - Mô tả ngắn <= 72 ký tự
29
- - Dùng thì hiện tại: "thêm", "sửa", "cập nhật" (không phải "đã thêm")
30
- - KHÔNG commit files chứa secrets (.env, credentials, tokens)
31
- - KHÔNG commit console.log/debugger còn sót
32
-
33
- ## Branch Naming
34
- ```
35
- <type>/<task-name>
36
- ```
37
- Ví dụ: `feat/user-auth`, `fix/login-redirect`, `refactor/api-structure`
1
+ # Commit Standards
2
+
3
+ ## Format
4
+ ```
5
+ <type>(<scope>): <mô tả tiếng Việt hoặc tiếng Anh>
6
+
7
+ [Body - chi tiết thay đổi, lý do]
8
+ [Blank line]
9
+ [Footer - breaking changes, references]
10
+
11
+ Co-Authored-By: Claude <noreply@anthropic.com>
12
+ ```
13
+
14
+ ## Types
15
+ | Type | Khi nào dùng |
16
+ |------|-------------|
17
+ | `feat` | Tính năng mới |
18
+ | `fix` | Sửa lỗi |
19
+ | `refactor` | Tái cấu trúc, không thay đổi behavior |
20
+ | `test` | Thêm/sửa tests |
21
+ | `docs` | Tài liệu, comments |
22
+ | `chore` | Build, config, dependencies |
23
+ | `style` | Format, whitespace (không thay đổi logic) |
24
+ | `perf` | Cải thiện performance |
25
+
26
+ ## Quy tắc
27
+ - Mỗi commit = 1 subtask hoặc 1 đơn vị logic hoàn chỉnh
28
+ - Mô tả ngắn <= 72 ký tự
29
+ - Dùng thì hiện tại: "thêm", "sửa", "cập nhật" (không phải "đã thêm")
30
+ - KHÔNG commit files chứa secrets (.env, credentials, tokens)
31
+ - KHÔNG commit console.log/debugger còn sót
32
+
33
+ ## Branch Naming
34
+ ```
35
+ <type>/<task-name>
36
+ ```
37
+ Ví dụ: `feat/user-auth`, `fix/login-redirect`, `refactor/api-structure`
@@ -1,99 +1,101 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Read(*)",
5
- "Grep(*)",
6
- "Glob(*)",
7
- "Bash(git log *)",
8
- "Bash(git diff *)",
9
- "Bash(git show *)",
10
- "Bash(git status)",
11
- "Bash(git blame *)",
12
- "Bash(git stash list)",
13
- "Bash(ls *)",
14
- "Bash(wc *)"
15
- ]
16
- },
17
- "mcpServers": {},
18
- "hooks": {
19
- "UserPromptSubmit": [
20
- {
21
- "hooks": [
22
- {
23
- "type": "command",
24
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-init.sh\""
25
- }
26
- ]
27
- }
28
- ],
29
- "PreToolUse": [
30
- {
31
- "matcher": "Read|Glob",
32
- "hooks": [
33
- {
34
- "type": "command",
35
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/scout-block.sh\""
36
- }
37
- ]
38
- },
39
- {
40
- "matcher": "Read",
41
- "hooks": [
42
- {
43
- "type": "command",
44
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/privacy-block.sh\""
45
- }
46
- ]
47
- },
48
- {
49
- "matcher": "Bash",
50
- "hooks": [
51
- {
52
- "type": "command",
53
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit-gate.sh\""
54
- }
55
- ]
56
- },
57
- {
58
- "matcher": "Bash",
59
- "hooks": [
60
- {
61
- "type": "command",
62
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/safety-guard.sh\""
63
- }
64
- ]
65
- }
66
- ],
67
- "PostToolUse": [
68
- {
69
- "matcher": "Write|Edit",
70
- "hooks": [
71
- {
72
- "type": "command",
73
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/post-write.sh\""
74
- }
75
- ]
76
- }
77
- ],
78
- "Stop": [
79
- {
80
- "hooks": [
81
- {
82
- "type": "command",
83
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop-check.sh\""
84
- }
85
- ]
86
- }
87
- ],
88
- "Notification": [
89
- {
90
- "hooks": [
91
- {
92
- "type": "command",
93
- "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/progress-ping.sh\""
94
- }
95
- ]
96
- }
97
- ]
98
- }
99
- }
1
+ {
2
+ "includeCoAuthoredBy": false,
3
+ "permissions": {
4
+ "allow": [
5
+ "Read(*)",
6
+ "Grep(*)",
7
+ "Glob(*)",
8
+ "Bash(git log *)",
9
+ "Bash(git diff *)",
10
+ "Bash(git show *)",
11
+ "Bash(git status)",
12
+ "Bash(git blame *)",
13
+ "Bash(git stash list)",
14
+ "Bash(ls *)",
15
+ "Bash(wc *)",
16
+ "Bash(node src/smoke-test.mjs)"
17
+ ]
18
+ },
19
+ "hooks": {
20
+ "UserPromptSubmit": [
21
+ {
22
+ "hooks": [
23
+ {
24
+ "type": "command",
25
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/session-init.sh\""
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "PreToolUse": [
31
+ {
32
+ "matcher": "Read|Glob",
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/scout-block.sh\""
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ "matcher": "Read",
42
+ "hooks": [
43
+ {
44
+ "type": "command",
45
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/privacy-block.sh\""
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "matcher": "Bash",
51
+ "hooks": [
52
+ {
53
+ "type": "command",
54
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/pre-commit-gate.sh\""
55
+ }
56
+ ]
57
+ },
58
+ {
59
+ "matcher": "Bash",
60
+ "hooks": [
61
+ {
62
+ "type": "command",
63
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/safety-guard.sh\""
64
+ }
65
+ ]
66
+ }
67
+ ],
68
+ "PostToolUse": [
69
+ {
70
+ "matcher": "Write|Edit",
71
+ "hooks": [
72
+ {
73
+ "type": "command",
74
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/post-write.sh\""
75
+ }
76
+ ]
77
+ }
78
+ ],
79
+ "Stop": [
80
+ {
81
+ "hooks": [
82
+ {
83
+ "type": "command",
84
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/stop-check.sh\""
85
+ }
86
+ ]
87
+ }
88
+ ],
89
+ "Notification": [
90
+ {
91
+ "hooks": [
92
+ {
93
+ "type": "command",
94
+ "command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/progress-ping.sh\""
95
+ }
96
+ ]
97
+ }
98
+ ]
99
+ },
100
+ "mcpServers": {}
101
+ }