dw-kit 1.2.1 → 1.3.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 (58) hide show
  1. package/.claude/hooks/post-write.sh +64 -58
  2. package/.claude/hooks/pre-commit-gate.sh +96 -90
  3. package/.claude/hooks/privacy-block.sh +99 -94
  4. package/.claude/hooks/progress-ping.sh +53 -47
  5. package/.claude/hooks/safety-guard.sh +60 -54
  6. package/.claude/hooks/scout-block.sh +88 -82
  7. package/.claude/hooks/session-init.sh +6 -0
  8. package/.claude/hooks/stop-check.sh +88 -36
  9. package/.claude/hooks/telemetry-log.sh +34 -0
  10. package/.claude/rules/dw.md +136 -0
  11. package/.claude/settings.json +20 -1
  12. package/.claude/skills/dw-arch-review/SKILL.md +119 -119
  13. package/.claude/skills/dw-archive/SKILL.md +81 -81
  14. package/.claude/skills/dw-commit/SKILL.md +81 -81
  15. package/.claude/skills/dw-config-init/SKILL.md +91 -91
  16. package/.claude/skills/dw-config-validate/SKILL.md +75 -75
  17. package/.claude/skills/dw-dashboard/SKILL.md +209 -209
  18. package/.claude/skills/dw-debug/SKILL.md +97 -97
  19. package/.claude/skills/dw-decision/SKILL.md +116 -0
  20. package/.claude/skills/dw-docs-update/SKILL.md +125 -125
  21. package/.claude/skills/dw-estimate/SKILL.md +90 -90
  22. package/.claude/skills/dw-execute/SKILL.md +98 -98
  23. package/.claude/skills/dw-flow/SKILL.md +274 -274
  24. package/.claude/skills/dw-handoff/SKILL.md +81 -81
  25. package/.claude/skills/dw-kit-report/SKILL.md +152 -152
  26. package/.claude/skills/dw-log-work/SKILL.md +69 -69
  27. package/.claude/skills/dw-onboard/SKILL.md +201 -201
  28. package/.claude/skills/dw-plan/SKILL.md +125 -125
  29. package/.claude/skills/dw-prompt/SKILL.md +62 -62
  30. package/.claude/skills/dw-requirements/SKILL.md +98 -98
  31. package/.claude/skills/dw-research/SKILL.md +114 -114
  32. package/.claude/skills/dw-retroactive/SKILL.md +311 -311
  33. package/.claude/skills/dw-review/SKILL.md +66 -66
  34. package/.claude/skills/dw-rollback/SKILL.md +90 -90
  35. package/.claude/skills/dw-sprint-review/SKILL.md +99 -99
  36. package/.claude/skills/dw-task-init/SKILL.md +59 -59
  37. package/.claude/skills/dw-test-plan/SKILL.md +113 -113
  38. package/.claude/skills/dw-thinking/SKILL.md +70 -70
  39. package/.claude/skills/dw-upgrade/SKILL.md +72 -72
  40. package/.dw/core/PILLARS.md +122 -0
  41. package/.dw/core/templates/v2/spec.md +68 -0
  42. package/.dw/core/templates/v2/tracking.md +62 -0
  43. package/.dw/core/v14-evaluation-protocol.md +118 -0
  44. package/CLAUDE.md +42 -39
  45. package/MIGRATION-v1.3.md +201 -0
  46. package/README.md +35 -6
  47. package/package.json +4 -2
  48. package/src/cli.mjs +29 -1
  49. package/src/commands/dashboard.mjs +116 -0
  50. package/src/commands/doctor.mjs +165 -149
  51. package/src/commands/init.mjs +339 -332
  52. package/src/commands/metrics.mjs +165 -0
  53. package/src/lib/active-index.mjs +87 -0
  54. package/src/lib/cut-analysis.mjs +161 -0
  55. package/src/lib/telemetry.mjs +80 -0
  56. package/.claude/rules/dw-core.md +0 -100
  57. package/.claude/rules/dw-skills.md +0 -53
  58. package/.claude/rules/workflow-rules.md +0 -77
@@ -1,54 +1,60 @@
1
- #!/bin/bash
2
- # .claude/hooks/safety-guard.sh
3
- # Intercept destructive Bash commands trước khi execute.
4
- # exit 0 = allow, exit 2 = block
5
- #
6
- # Được gọi bởi PreToolUse hook cho tất cả Bash commands.
7
-
8
- INPUT=$(cat)
9
-
10
- COMMAND=$(echo "$INPUT" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' \
11
- | sed 's/"command"[[:space:]]*:[[:space:]]*"//;s/"$//' | head -1)
12
-
13
- [ -z "$COMMAND" ] && exit 0
14
-
15
- # ── Pattern 1: rm -rf với path quá rộng ──────────────────────────────────────
16
- # Block: rm -rf / | rm -rf * | rm -rf . (nguy hiểm)
17
- # Allow: rm -rf ./specific/path | rm -rf /tmp/specific-file
18
- if echo "$COMMAND" | grep -qE 'rm\s+-rf?\s+(\/\s*$|\*|\.(\s|$))'; then
19
- echo "🚨 BLOCKED: rm -rf với path nguy hiểm ($COMMAND)" >&2
20
- echo " Chỉ định path cụ thể hơn để proceed." >&2
21
- exit 2
22
- fi
23
-
24
- # ── Pattern 2: git push --force lên main/master ───────────────────────────────
25
- if echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force'; then
26
- BRANCH=$(echo "$COMMAND" | grep -oE '(main|master|develop|dev)' | head -1)
27
- if [ -n "$BRANCH" ]; then
28
- echo "🚨 BLOCKED: git push --force lên $BRANCH" >&2
29
- echo " Force push lên protected branch không được phép." >&2
30
- exit 2
31
- fi
32
- # Force push lên non-protected branch: warn nhưng allow
33
- echo "⚠ Warning: git push --force (non-protected branch)" >&2
34
- echo " Proceed nếu intentional." >&2
35
- exit 0
36
- fi
37
-
38
- # ── Pattern 3: Destructive SQL không WHERE ─────────────────────────────────
39
- if echo "$COMMAND" | grep -qiE '(DELETE\s+FROM|UPDATE\s+\w+\s+SET)' \
40
- && ! echo "$COMMAND" | grep -qi 'WHERE'; then
41
- echo "🚨 BLOCKED: Destructive SQL không có WHERE clause" >&2
42
- echo " Thêm WHERE clause hoặc confirm intentional." >&2
43
- exit 2
44
- fi
45
-
46
- # ── Pattern 4: DROP TABLE / DROP DATABASE ────────────────────────────────────
47
- if echo "$COMMAND" | grep -qiE 'DROP\s+(TABLE|DATABASE|SCHEMA)'; then
48
- echo "⚠ Warning: DROP statement detected ($COMMAND)" >&2
49
- echo " Đây có phải migration script đã được review không?" >&2
50
- # Warn but allow — user có thể đang chạy migration
51
- exit 0
52
- fi
53
-
54
- exit 0
1
+ #!/bin/bash
2
+ # .claude/hooks/safety-guard.sh
3
+ # Intercept destructive Bash commands trước khi execute.
4
+ # exit 0 = allow, exit 2 = block
5
+ #
6
+ # Được gọi bởi PreToolUse hook cho tất cả Bash commands.
7
+
8
+ # Telemetry (local, fire-and-forget)
9
+ TELEMETRY_SCRIPT="${CLAUDE_PROJECT_DIR:-$(pwd)}/.claude/hooks/telemetry-log.sh"
10
+ if [ -x "$TELEMETRY_SCRIPT" ] && [ "${DW_NO_TELEMETRY:-}" != "1" ]; then
11
+ "$TELEMETRY_SCRIPT" hook safety-guard >/dev/null 2>&1 || true
12
+ fi
13
+
14
+ INPUT=$(cat)
15
+
16
+ COMMAND=$(echo "$INPUT" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' \
17
+ | sed 's/"command"[[:space:]]*:[[:space:]]*"//;s/"$//' | head -1)
18
+
19
+ [ -z "$COMMAND" ] && exit 0
20
+
21
+ # ── Pattern 1: rm -rf với path quá rộng ──────────────────────────────────────
22
+ # Block: rm -rf / | rm -rf * | rm -rf . (nguy hiểm)
23
+ # Allow: rm -rf ./specific/path | rm -rf /tmp/specific-file
24
+ if echo "$COMMAND" | grep -qE 'rm\s+-rf?\s+(\/\s*$|\*|\.(\s|$))'; then
25
+ echo "🚨 BLOCKED: rm -rf với path nguy hiểm ($COMMAND)" >&2
26
+ echo " Chỉ định path cụ thể hơn để proceed." >&2
27
+ exit 2
28
+ fi
29
+
30
+ # ── Pattern 2: git push --force lên main/master ───────────────────────────────
31
+ if echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force'; then
32
+ BRANCH=$(echo "$COMMAND" | grep -oE '(main|master|develop|dev)' | head -1)
33
+ if [ -n "$BRANCH" ]; then
34
+ echo "🚨 BLOCKED: git push --force lên $BRANCH" >&2
35
+ echo " Force push lên protected branch không được phép." >&2
36
+ exit 2
37
+ fi
38
+ # Force push lên non-protected branch: warn nhưng allow
39
+ echo "⚠ Warning: git push --force (non-protected branch)" >&2
40
+ echo " Proceed nếu intentional." >&2
41
+ exit 0
42
+ fi
43
+
44
+ # ── Pattern 3: Destructive SQL không có WHERE ─────────────────────────────────
45
+ if echo "$COMMAND" | grep -qiE '(DELETE\s+FROM|UPDATE\s+\w+\s+SET)' \
46
+ && ! echo "$COMMAND" | grep -qi 'WHERE'; then
47
+ echo "🚨 BLOCKED: Destructive SQL không có WHERE clause" >&2
48
+ echo " Thêm WHERE clause hoặc confirm intentional." >&2
49
+ exit 2
50
+ fi
51
+
52
+ # ── Pattern 4: DROP TABLE / DROP DATABASE ────────────────────────────────────
53
+ if echo "$COMMAND" | grep -qiE 'DROP\s+(TABLE|DATABASE|SCHEMA)'; then
54
+ echo "⚠ Warning: DROP statement detected ($COMMAND)" >&2
55
+ echo " Đây có phải migration script đã được review không?" >&2
56
+ # Warn but allow — user có thể đang chạy migration
57
+ exit 0
58
+ fi
59
+
60
+ exit 0
@@ -1,82 +1,88 @@
1
- #!/usr/bin/env bash
2
- # .claude/hooks/scout-block.sh — dw-kit v1.2
3
- # Block agent reads vào heavy/irrelevant directories để tăng performance.
4
- # Học từ claudekit scout-block pattern.
5
- #
6
- # PreToolUse hook cho: Read, Glob
7
- # exit 0 = allow, exit 2 = block
8
-
9
- INPUT=$(cat)
10
-
11
- # Extract tool name file path từ JSON input
12
- TOOL_NAME=$(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).tool_name||''); }catch(e){}
16
- });
17
- " 2>/dev/null || true)
18
-
19
- # Extract path tùy theo tool
20
- if [ "$TOOL_NAME" = "Read" ]; then
21
- TARGET=$(echo "$INPUT" | node -e "
22
- let d='';
23
- process.stdin.on('data',c=>d+=c).on('end',()=>{
24
- try{ const p=JSON.parse(d); process.stdout.write((p.tool_input&&p.tool_input.file_path)||''); }catch(e){}
25
- });
26
- " 2>/dev/null || true)
27
- elif [ "$TOOL_NAME" = "Glob" ]; then
28
- TARGET=$(echo "$INPUT" | node -e "
29
- let d='';
30
- process.stdin.on('data',c=>d+=c).on('end',()=>{
31
- try{ const p=JSON.parse(d); const ti=p.tool_input||{}; process.stdout.write(ti.path||ti.pattern||''); }catch(e){}
32
- });
33
- " 2>/dev/null || true)
34
- else
35
- exit 0
36
- fi
37
-
38
- [ -z "$TARGET" ] && exit 0
39
-
40
- # Normalize: lowercase, forward slashes
41
- NORM=$(echo "$TARGET" | tr '\\' '/')
42
-
43
- # ── Danh sách heavy/irrelevant directories ─────────────────────────────────────
44
- BLOCKED_PATTERNS=(
45
- "node_modules/"
46
- "/node_modules"
47
- "dist/"
48
- "/dist/"
49
- "build/"
50
- "/build/"
51
- ".git/"
52
- "/__pycache__/"
53
- "/.pytest_cache/"
54
- "/.next/"
55
- "/.nuxt/"
56
- "/vendor/"
57
- "/coverage/"
58
- "/.tmp/"
59
- "/tmp/"
60
- "/.cache/"
61
- )
62
-
63
- for pattern in "${BLOCKED_PATTERNS[@]}"; do
64
- if echo "$NORM" | grep -q "$pattern"; then
65
- echo "⚡ scout-block: Skipped heavy directory [${TOOL_NAME}] $(basename "$TARGET")/" >&2
66
- echo " Path: $TARGET" >&2
67
- echo " Dùng path cụ thể hơn nếu thực sự cần đọc file này." >&2
68
- exit 2
69
- fi
70
- done
71
-
72
- # Block pattern: kết thúc bằng thư mục blocked (không có trailing slash)
73
- BLOCKED_EXACT=("node_modules" ".git" "dist" "build" "__pycache__" ".next" ".nuxt" "vendor" "coverage")
74
- BASENAME=$(basename "$NORM")
75
- for exact in "${BLOCKED_EXACT[@]}"; do
76
- if [ "$BASENAME" = "$exact" ]; then
77
- echo "⚡ scout-block: Skipped heavy directory [${TOOL_NAME}] $BASENAME/" >&2
78
- exit 2
79
- fi
80
- done
81
-
82
- exit 0
1
+ #!/usr/bin/env bash
2
+ # .claude/hooks/scout-block.sh — dw-kit v1.2
3
+ # Block agent reads vào heavy/irrelevant directories để tăng performance.
4
+ # Học từ claudekit scout-block pattern.
5
+ #
6
+ # PreToolUse hook cho: Read, Glob
7
+ # exit 0 = allow, exit 2 = block
8
+
9
+ # Telemetry (local, fire-and-forget)
10
+ TELEMETRY_SCRIPT="${CLAUDE_PROJECT_DIR:-$(pwd)}/.claude/hooks/telemetry-log.sh"
11
+ if [ -x "$TELEMETRY_SCRIPT" ] && [ "${DW_NO_TELEMETRY:-}" != "1" ]; then
12
+ "$TELEMETRY_SCRIPT" hook scout-block >/dev/null 2>&1 || true
13
+ fi
14
+
15
+ INPUT=$(cat)
16
+
17
+ # Extract tool name và file path từ JSON input
18
+ TOOL_NAME=$(echo "$INPUT" | node -e "
19
+ let d='';
20
+ process.stdin.on('data',c=>d+=c).on('end',()=>{
21
+ try{ process.stdout.write(JSON.parse(d).tool_name||''); }catch(e){}
22
+ });
23
+ " 2>/dev/null || true)
24
+
25
+ # Extract path tùy theo tool
26
+ if [ "$TOOL_NAME" = "Read" ]; then
27
+ TARGET=$(echo "$INPUT" | node -e "
28
+ let d='';
29
+ process.stdin.on('data',c=>d+=c).on('end',()=>{
30
+ try{ const p=JSON.parse(d); process.stdout.write((p.tool_input&&p.tool_input.file_path)||''); }catch(e){}
31
+ });
32
+ " 2>/dev/null || true)
33
+ elif [ "$TOOL_NAME" = "Glob" ]; then
34
+ TARGET=$(echo "$INPUT" | node -e "
35
+ let d='';
36
+ process.stdin.on('data',c=>d+=c).on('end',()=>{
37
+ try{ const p=JSON.parse(d); const ti=p.tool_input||{}; process.stdout.write(ti.path||ti.pattern||''); }catch(e){}
38
+ });
39
+ " 2>/dev/null || true)
40
+ else
41
+ exit 0
42
+ fi
43
+
44
+ [ -z "$TARGET" ] && exit 0
45
+
46
+ # Normalize: lowercase, forward slashes
47
+ NORM=$(echo "$TARGET" | tr '\\' '/')
48
+
49
+ # ── Danh sách heavy/irrelevant directories ─────────────────────────────────────
50
+ BLOCKED_PATTERNS=(
51
+ "node_modules/"
52
+ "/node_modules"
53
+ "dist/"
54
+ "/dist/"
55
+ "build/"
56
+ "/build/"
57
+ ".git/"
58
+ "/__pycache__/"
59
+ "/.pytest_cache/"
60
+ "/.next/"
61
+ "/.nuxt/"
62
+ "/vendor/"
63
+ "/coverage/"
64
+ "/.tmp/"
65
+ "/tmp/"
66
+ "/.cache/"
67
+ )
68
+
69
+ for pattern in "${BLOCKED_PATTERNS[@]}"; do
70
+ if echo "$NORM" | grep -q "$pattern"; then
71
+ echo "⚡ scout-block: Skipped heavy directory [${TOOL_NAME}] $(basename "$TARGET")/" >&2
72
+ echo " Path: $TARGET" >&2
73
+ echo " Dùng path cụ thể hơn nếu thực sự cần đọc file này." >&2
74
+ exit 2
75
+ fi
76
+ done
77
+
78
+ # Block pattern: kết thúc bằng thư mục blocked (không có trailing slash)
79
+ BLOCKED_EXACT=("node_modules" ".git" "dist" "build" "__pycache__" ".next" ".nuxt" "vendor" "coverage")
80
+ BASENAME=$(basename "$NORM")
81
+ for exact in "${BLOCKED_EXACT[@]}"; do
82
+ if [ "$BASENAME" = "$exact" ]; then
83
+ echo "⚡ scout-block: Skipped heavy directory [${TOOL_NAME}] $BASENAME/" >&2
84
+ exit 2
85
+ fi
86
+ done
87
+
88
+ exit 0
@@ -36,6 +36,12 @@ if [ -f "$SESSION_MARKER" ]; then
36
36
  fi
37
37
  touch "$SESSION_MARKER" 2>/dev/null || true
38
38
 
39
+ # Telemetry (once per session, fire-and-forget)
40
+ TELEMETRY_SCRIPT="${CLAUDE_PROJECT_DIR:-$(pwd)}/.claude/hooks/telemetry-log.sh"
41
+ if [ -x "$TELEMETRY_SCRIPT" ] && [ "${DW_NO_TELEMETRY:-}" != "1" ]; then
42
+ "$TELEMETRY_SCRIPT" hook session-init >/dev/null 2>&1 || true
43
+ fi
44
+
39
45
  # ── Scan .dw/tasks/ tìm tasks In Progress ─────────────────────────────────────
40
46
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
41
47
  TASKS_DIR="$PROJECT_DIR/.dw/tasks"
@@ -1,36 +1,88 @@
1
- #!/usr/bin/env bash
2
- # Stop hook: warn nếu uncommitted changes hoặc task in-progress chưa update
3
- # Output ra stderr để hiện thị cho user, exit 0 để không block
4
-
5
- PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
6
- WARNINGS=()
7
-
8
- # Check uncommitted changes
9
- if git -C "$PROJECT_DIR" diff --quiet && git -C "$PROJECT_DIR" diff --cached --quiet; then
10
- : # clean
11
- else
12
- CHANGED=$(git -C "$PROJECT_DIR" diff --stat --cached && git -C "$PROJECT_DIR" diff --stat)
13
- WARNINGS+=("Uncommitted changes:"$'\n'"$CHANGED")
14
- fi
15
-
16
- # Check in-progress tasks
17
- TASKS_DIR="$PROJECT_DIR/.dw/tasks"
18
- if [ -d "$TASKS_DIR" ]; then
19
- while IFS= read -r progress_file; do
20
- if grep -q "Trạng thái: In Progress" "$progress_file" 2>/dev/null; then
21
- task_name=$(basename "$(dirname "$progress_file")")
22
- WARNINGS+=("Task in-progress chưa được update: $task_name")
23
- fi
24
- done < <(find "$TASKS_DIR" -name "*-progress.md" 2>/dev/null)
25
- fi
26
-
27
- # Print warnings
28
- if [ ${#WARNINGS[@]} -gt 0 ]; then
29
- echo "--- dw stop-check ---" >&2
30
- for w in "${WARNINGS[@]}"; do
31
- printf "⚠ %b\n" "$w" >&2
32
- done
33
- echo "---------------------" >&2
34
- fi
35
-
36
- exit 0
1
+ #!/usr/bin/env bash
2
+ # Stop hook: warn on uncommitted changes + auto-append handoff to active task tracking.md
3
+ # v1.4: auto-handoff (ST-2.5) append session summary to tracking.md when uncommitted
4
+ # Output via stderr for user visibility. Always exit 0 (non-blocking).
5
+
6
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
7
+ WARNINGS=()
8
+
9
+ # --- Telemetry (local, fire-and-forget) ---
10
+ TELEMETRY_SCRIPT="$PROJECT_DIR/.claude/hooks/telemetry-log.sh"
11
+ if [ -x "$TELEMETRY_SCRIPT" ] && [ "${DW_NO_TELEMETRY:-}" != "1" ]; then
12
+ "$TELEMETRY_SCRIPT" hook stop-check >/dev/null 2>&1 || true
13
+ fi
14
+
15
+ # --- Check uncommitted changes ---
16
+ HAS_UNCOMMITTED=0
17
+ if git -C "$PROJECT_DIR" diff --quiet && git -C "$PROJECT_DIR" diff --cached --quiet; then
18
+ : # clean
19
+ else
20
+ HAS_UNCOMMITTED=1
21
+ CHANGED=$(git -C "$PROJECT_DIR" diff --stat --cached && git -C "$PROJECT_DIR" diff --stat)
22
+ WARNINGS+=("Uncommitted changes:"$'\n'"$CHANGED")
23
+ fi
24
+
25
+ # --- Check in-progress tasks (both v1 3-file and v2 2-file formats) ---
26
+ TASKS_DIR="$PROJECT_DIR/.dw/tasks"
27
+ ACTIVE_TASK=""
28
+
29
+ if [ -d "$TASKS_DIR" ]; then
30
+ # v1 format: {task}-progress.md with "Trạng thái: In Progress"
31
+ while IFS= read -r progress_file; do
32
+ if grep -q "Trạng thái: In Progress" "$progress_file" 2>/dev/null; then
33
+ task_name=$(basename "$(dirname "$progress_file")")
34
+ WARNINGS+=("Task in-progress (v1): $task_name")
35
+ [ -z "$ACTIVE_TASK" ] && ACTIVE_TASK="$task_name"
36
+ fi
37
+ done < <(find "$TASKS_DIR" -maxdepth 3 -name "*-progress.md" -not -path "*/archive/*" 2>/dev/null)
38
+
39
+ # v2 format: tracking.md with frontmatter status In Progress
40
+ while IFS= read -r tracking_file; do
41
+ if grep -qE "^status:.*(In Progress|Code Complete)" "$tracking_file" 2>/dev/null; then
42
+ task_name=$(basename "$(dirname "$tracking_file")")
43
+ WARNINGS+=("Task active (v2): $task_name")
44
+ [ -z "$ACTIVE_TASK" ] && ACTIVE_TASK="$task_name"
45
+ fi
46
+ done < <(find "$TASKS_DIR" -maxdepth 3 -name "tracking.md" -not -path "*/archive/*" 2>/dev/null)
47
+ fi
48
+
49
+ # --- Auto-handoff: append snippet to active task's tracking.md if uncommitted + active task ---
50
+ if [ "$HAS_UNCOMMITTED" = "1" ] && [ -n "$ACTIVE_TASK" ]; then
51
+ TRACKING_FILE="$TASKS_DIR/$ACTIVE_TASK/tracking.md"
52
+ if [ -f "$TRACKING_FILE" ]; then
53
+ TS=$(date -u +"%Y-%m-%d %H:%M UTC")
54
+ MARKER="<!-- dw-auto-handoff -->"
55
+
56
+ # Only append if no handoff snippet added in last 10 minutes (idempotency via marker + timestamp grep)
57
+ if ! grep -q "$MARKER.*$TS" "$TRACKING_FILE" 2>/dev/null; then
58
+ {
59
+ echo ""
60
+ echo "$MARKER"
61
+ echo "### Auto-handoff — $TS"
62
+ echo ""
63
+ echo "Session ended with uncommitted changes."
64
+ echo ""
65
+ echo "**Files changed:**"
66
+ echo '```'
67
+ git -C "$PROJECT_DIR" diff --stat --cached 2>/dev/null
68
+ git -C "$PROJECT_DIR" diff --stat 2>/dev/null
69
+ echo '```'
70
+ echo ""
71
+ echo "Next session: commit or continue work. Re-read spec.md + this tracking.md first."
72
+ echo ""
73
+ } >> "$TRACKING_FILE" 2>/dev/null
74
+ WARNINGS+=("Auto-handoff appended to: $TRACKING_FILE")
75
+ fi
76
+ fi
77
+ fi
78
+
79
+ # --- Print warnings ---
80
+ if [ ${#WARNINGS[@]} -gt 0 ]; then
81
+ printf -- "--- dw stop-check ---\n" >&2
82
+ for w in "${WARNINGS[@]}"; do
83
+ printf "⚠ %b\n" "$w" >&2
84
+ done
85
+ printf -- "---------------------\n" >&2
86
+ fi
87
+
88
+ exit 0
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ # Lightweight telemetry logger — invoked by other hooks to record events.
3
+ # Usage: telemetry-log.sh <event-type> <name> [result] [latency_ms]
4
+ # Silently no-ops if DW_NO_TELEMETRY=1 or .dw/metrics unavailable.
5
+
6
+ set -e
7
+
8
+ if [ "${DW_NO_TELEMETRY:-}" = "1" ] || [ "${DW_NO_TELEMETRY:-}" = "true" ]; then
9
+ exit 0
10
+ fi
11
+
12
+ EVENT_TYPE="${1:-unknown}"
13
+ NAME="${2:-unknown}"
14
+ RESULT="${3:-}"
15
+ LATENCY="${4:-}"
16
+
17
+ METRICS_DIR=".dw/metrics"
18
+ EVENTS_FILE="$METRICS_DIR/events.jsonl"
19
+
20
+ if [ ! -d "$METRICS_DIR" ]; then
21
+ mkdir -p "$METRICS_DIR" 2>/dev/null || exit 0
22
+ fi
23
+
24
+ TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
25
+ SESSION_HASH=$(echo "$$:${CLAUDE_SESSION_ID:-default}" | sha256sum 2>/dev/null | cut -c1-8 || echo "unknown")
26
+
27
+ JSON="{\"ts\":\"$TS\",\"session\":\"$SESSION_HASH\",\"event\":\"$EVENT_TYPE\",\"name\":\"$NAME\""
28
+ [ -n "$RESULT" ] && JSON="$JSON,\"result\":\"$RESULT\""
29
+ [ -n "$LATENCY" ] && JSON="$JSON,\"latency_ms\":$LATENCY"
30
+ JSON="$JSON}"
31
+
32
+ echo "$JSON" >> "$EVENTS_FILE" 2>/dev/null || true
33
+
34
+ exit 0
@@ -0,0 +1,136 @@
1
+ # dw Workflow (consolidated)
2
+
3
+ Config: `.dw/config/dw.config.yml`
4
+ Full methodology: `.dw/core/` (WORKFLOW · THINKING · QUALITY · ROLES · PILLARS)
5
+
6
+ ---
7
+
8
+ ## Override
9
+
10
+ Prompt contains `--no-dw` → ignore all dw instructions for that request, work as plain Claude Code.
11
+
12
+ ---
13
+
14
+ ## 5-Pillar Architecture (v2.0)
15
+
16
+ | Pillar | Role | Owners | Examples |
17
+ |--------|------|--------|----------|
18
+ | **Guards** | Block unsafe actions | privacy-block, pre-commit-gate | Non-negotiable safety |
19
+ | **Surfaces** | Make state visible | ACTIVE.md, project-map, modules | Shared team context |
20
+ | **Records** | Capture decisions | ADRs in `.dw/decisions/` | Organizational memory |
21
+ | **Bridges** | Connect across sessions | auto-handoff, tracking.md | Continuity over time |
22
+ | **Tunes** | Behavioral knobs | roles, depth, presets | Team/solo customization |
23
+
24
+ ---
25
+
26
+ ## Depth Routing
27
+
28
+ Assess per task — file count, API changes, git blame:
29
+
30
+ | Scope | Depth | Approach |
31
+ |-------|-------|----------|
32
+ | ≤2 files, hotfix | quick | Understand → Execute → Close |
33
+ | 3–5 files, new module | standard | spec.md + tracking.md |
34
+ | 6+ files, API/DB/security | thorough | Full 2-file + optional reports/ |
35
+
36
+ Default when unsure: `standard`.
37
+
38
+ ---
39
+
40
+ ## Session Start
41
+
42
+ 1. Read `.dw/tasks/ACTIVE.md` — single source of truth for team state
43
+ 2. Resume any task with status `In Progress` from its `tracking.md`
44
+ 3. Check `.dw/decisions/` for recent ADRs if task touches architecture
45
+
46
+ ---
47
+
48
+ ## Task Docs (v2 default — 2 files)
49
+
50
+ ```
51
+ .dw/tasks/{task-name}/
52
+ ├── spec.md # Intent + plan (stable after approve)
53
+ └── tracking.md # Progress + handoff (mutable)
54
+ ```
55
+
56
+ Legacy 3-file (`context + plan + progress`) still supported for older tasks.
57
+
58
+ Templates at `.dw/core/templates/v2/`.
59
+
60
+ ---
61
+
62
+ ## Skills — Namespace `/dw:*`
63
+
64
+ All dw skills invoke via `/dw:{name}` (colon namespace separator).
65
+
66
+ Core workflow: `/dw:flow` · `/dw:task-init` · `/dw:research` · `/dw:plan` · `/dw:execute` · `/dw:commit` · `/dw:handoff`
67
+
68
+ Decisions: `/dw:decision [title]` — create ADR
69
+
70
+ Dev: `/dw:debug` · `/dw:review` · `/dw:thinking` · `/dw:prompt` · `/dw:docs-update`
71
+
72
+ Role-specific: `/dw:requirements` · `/dw:test-plan` · `/dw:arch-review` · `/dw:dashboard` · `/dw:sprint-review`
73
+
74
+ Setup: `/dw:onboard` · `/dw:retroactive` · `/dw:config-init` · `/dw:upgrade` · `/dw:rollback` · `/dw:archive`
75
+
76
+ See `.dw/core/skills-index.md` for complete list with descriptions.
77
+
78
+ ---
79
+
80
+ ## Commit Format
81
+
82
+ ```
83
+ <type>(<scope>): <description ≤72 chars>
84
+ ```
85
+
86
+ Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `perf`
87
+
88
+ ---
89
+
90
+ ## Hooks
91
+
92
+ | Hook | Purpose |
93
+ |------|---------|
94
+ | `privacy-block` | Guard — block .env/credentials/keys |
95
+ | `pre-commit-gate` | Guard — quality check + sensitive scan |
96
+ | `stop-check` | Bridge — auto-handoff to tracking.md + uncommitted warning |
97
+ | `telemetry-log` | Meta — local event log for v1.4 cut decisions |
98
+
99
+ Legacy (deprecated, removal in v2.0 based on telemetry): scout-block, post-write, progress-ping, session-init, safety-guard.
100
+
101
+ ---
102
+
103
+ ## Decisions Layer
104
+
105
+ ADRs at `.dw/decisions/{NNNN}-{title}.md`. Create with `/dw:decision`.
106
+
107
+ Status values: `Proposed | Accepted | Deprecated | Superseded by ADR-{NNNN}`
108
+
109
+ When to write: architectural choice · cross-cutting concern · breaking change · trade-off with long-term impact.
110
+
111
+ ---
112
+
113
+ ## Telemetry (Local-Only)
114
+
115
+ - Storage: `.dw/metrics/events.jsonl`
116
+ - Inspect: `dw metrics show`
117
+ - Privacy: zero network; `DW_NO_TELEMETRY=1` to disable
118
+ - Used for: v1.4 data-driven cut decisions (internal teams only)
119
+
120
+ ---
121
+
122
+ ## Config Local Override
123
+
124
+ `.dw/config/dw.config.local.yml` (gitignored) for machine-specific overrides.
125
+
126
+ ---
127
+
128
+ ## Presets
129
+
130
+ | Preset | Audience | Config |
131
+ |--------|----------|--------|
132
+ | `solo` | Vibe coders, solo dev | Guards only, zero task docs |
133
+ | `team` | 5-15 dev teams | Full hooks, tracking encouraged |
134
+ | `enterprise` | Regulated / large teams | Full + roles + audit |
135
+
136
+ Install: `dw init --preset {name}` or `dw init --solo`.
@@ -13,7 +13,26 @@
13
13
  "Bash(git stash list)",
14
14
  "Bash(ls *)",
15
15
  "Bash(wc *)",
16
- "Bash(node src/smoke-test.mjs)"
16
+ "Bash(node src/smoke-test.mjs)",
17
+ "Bash(xargs echo *)",
18
+ "Edit(/.claude/skills/dw-decision/**)",
19
+ "Bash(node bin/dw.mjs active)",
20
+ "Bash(node bin/dw.mjs metrics show)",
21
+ "Bash(node bin/dw.mjs dashboard)",
22
+ "Bash(node bin/dw.mjs init --help)",
23
+ "Bash(mkdir -p /tmp/test-solo)",
24
+ "Read(//tmp/**)",
25
+ "Bash(DW_NAME=test node /d/huygdv_projects/dw-kit/bin/dw.mjs init --solo)",
26
+ "Bash(npm test *)",
27
+ "Bash(node bin/dw.mjs metrics cut-analysis)",
28
+ "Bash(bash -n .claude/hooks/pre-commit-gate.sh)",
29
+ "Bash(bash -n /dev/stdin)",
30
+ "Bash(dos2unix .claude/hooks/pre-commit-gate.sh)",
31
+ "Bash(sed -i 's/\\\\r$//' .claude/hooks/pre-commit-gate.sh)",
32
+ "Bash(git add *)"
33
+ ],
34
+ "additionalDirectories": [
35
+ "D:\\huygdv_projects\\dw-kit\\.claude\\rules"
17
36
  ]
18
37
  },
19
38
  "hooks": {