dw-kit 1.2.1 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/post-write.sh +64 -58
- package/.claude/hooks/pre-commit-gate.sh +96 -90
- package/.claude/hooks/privacy-block.sh +99 -94
- package/.claude/hooks/progress-ping.sh +53 -47
- package/.claude/hooks/safety-guard.sh +60 -54
- package/.claude/hooks/scout-block.sh +88 -82
- package/.claude/hooks/session-init.sh +6 -0
- package/.claude/hooks/stop-check.sh +88 -36
- package/.claude/hooks/telemetry-log.sh +34 -0
- package/.claude/rules/dw.md +138 -0
- package/.claude/settings.json +28 -1
- package/.claude/skills/dw-arch-review/SKILL.md +119 -119
- package/.claude/skills/dw-archive/SKILL.md +81 -81
- package/.claude/skills/dw-commit/SKILL.md +81 -81
- package/.claude/skills/dw-config-init/SKILL.md +91 -91
- package/.claude/skills/dw-config-validate/SKILL.md +75 -75
- package/.claude/skills/dw-dashboard/SKILL.md +209 -209
- package/.claude/skills/dw-debug/SKILL.md +97 -97
- package/.claude/skills/dw-decision/SKILL.md +116 -0
- package/.claude/skills/dw-docs-update/SKILL.md +125 -125
- package/.claude/skills/dw-estimate/SKILL.md +90 -90
- package/.claude/skills/dw-execute/SKILL.md +121 -98
- package/.claude/skills/dw-flow/SKILL.md +274 -274
- package/.claude/skills/dw-handoff/SKILL.md +92 -81
- package/.claude/skills/dw-kit-report/SKILL.md +152 -152
- package/.claude/skills/dw-log-work/SKILL.md +69 -69
- package/.claude/skills/dw-onboard/SKILL.md +201 -201
- package/.claude/skills/dw-plan/SKILL.md +222 -125
- package/.claude/skills/dw-prompt/SKILL.md +62 -62
- package/.claude/skills/dw-requirements/SKILL.md +98 -98
- package/.claude/skills/dw-research/SKILL.md +128 -114
- package/.claude/skills/dw-retroactive/SKILL.md +195 -311
- package/.claude/skills/dw-review/SKILL.md +66 -66
- package/.claude/skills/dw-rollback/SKILL.md +90 -90
- package/.claude/skills/dw-sprint-review/SKILL.md +99 -99
- package/.claude/skills/dw-task-init/SKILL.md +71 -59
- package/.claude/skills/dw-test-plan/SKILL.md +113 -113
- package/.claude/skills/dw-thinking/SKILL.md +70 -70
- package/.claude/skills/dw-upgrade/SKILL.md +72 -72
- package/.dw/core/PILLARS.md +122 -0
- package/.dw/core/ROLES.md +257 -257
- package/.dw/core/templates/v2/spec.md +68 -0
- package/.dw/core/templates/v2/tracking.md +62 -0
- package/.dw/core/v14-evaluation-protocol.md +118 -0
- package/CLAUDE.md +42 -39
- package/MIGRATION-v1.3.md +202 -0
- package/README.md +35 -6
- package/package.json +4 -2
- package/src/cli.mjs +29 -1
- package/src/commands/dashboard.mjs +116 -0
- package/src/commands/doctor.mjs +165 -149
- package/src/commands/init.mjs +339 -332
- package/src/commands/metrics.mjs +185 -0
- package/src/lib/active-index.mjs +87 -0
- package/src/lib/cut-analysis.mjs +240 -0
- package/src/lib/telemetry.mjs +80 -0
- package/.claude/rules/dw-core.md +0 -100
- package/.claude/rules/dw-skills.md +0 -53
- 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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
echo "
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"/
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"/
|
|
57
|
-
"/
|
|
58
|
-
"
|
|
59
|
-
"/
|
|
60
|
-
"/.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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,138 @@
|
|
|
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
|
+
`/dw:plan` includes **Quick Debate** (red/blue self-critique): default ON for `thorough`, auto-trigger on high-stakes signals for `standard`, off for `quick`. Override via `--debate` / `--no-debate` / `--debate-deep`.
|
|
69
|
+
|
|
70
|
+
Decisions: `/dw:decision [title]` — create ADR
|
|
71
|
+
|
|
72
|
+
Dev: `/dw:debug` · `/dw:review` · `/dw:thinking` · `/dw:prompt` · `/dw:docs-update`
|
|
73
|
+
|
|
74
|
+
Role-specific: `/dw:requirements` · `/dw:test-plan` · `/dw:arch-review` · `/dw:dashboard` · `/dw:sprint-review`
|
|
75
|
+
|
|
76
|
+
Setup: `/dw:onboard` · `/dw:retroactive` · `/dw:config-init` · `/dw:upgrade` · `/dw:rollback` · `/dw:archive`
|
|
77
|
+
|
|
78
|
+
See `.dw/core/skills-index.md` for complete list with descriptions.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Commit Format
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
<type>(<scope>): <description ≤72 chars>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `perf`
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Hooks
|
|
93
|
+
|
|
94
|
+
| Hook | Purpose |
|
|
95
|
+
|------|---------|
|
|
96
|
+
| `privacy-block` | Guard — block .env/credentials/keys |
|
|
97
|
+
| `pre-commit-gate` | Guard — quality check + sensitive scan |
|
|
98
|
+
| `stop-check` | Bridge — auto-handoff to tracking.md + uncommitted warning |
|
|
99
|
+
| `telemetry-log` | Meta — local event log for v1.4 cut decisions |
|
|
100
|
+
|
|
101
|
+
Legacy (deprecated, removal in v2.0 based on telemetry): scout-block, post-write, progress-ping, session-init, safety-guard.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Decisions Layer
|
|
106
|
+
|
|
107
|
+
ADRs at `.dw/decisions/{NNNN}-{title}.md`. Create with `/dw:decision`.
|
|
108
|
+
|
|
109
|
+
Status values: `Proposed | Accepted | Deprecated | Superseded by ADR-{NNNN}`
|
|
110
|
+
|
|
111
|
+
When to write: architectural choice · cross-cutting concern · breaking change · trade-off with long-term impact.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Telemetry (Local-Only)
|
|
116
|
+
|
|
117
|
+
- Storage: `.dw/metrics/events.jsonl`
|
|
118
|
+
- Inspect: `dw metrics show`
|
|
119
|
+
- Privacy: zero network; `DW_NO_TELEMETRY=1` to disable
|
|
120
|
+
- Used for: v1.4 data-driven cut decisions (internal teams only)
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Config Local Override
|
|
125
|
+
|
|
126
|
+
`.dw/config/dw.config.local.yml` (gitignored) for machine-specific overrides.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Presets
|
|
131
|
+
|
|
132
|
+
| Preset | Audience | Config |
|
|
133
|
+
|--------|----------|--------|
|
|
134
|
+
| `solo` | Vibe coders, solo dev | Guards only, zero task docs |
|
|
135
|
+
| `team` | 5-15 dev teams | Full hooks, tracking encouraged |
|
|
136
|
+
| `enterprise` | Regulated / large teams | Full + roles + audit |
|
|
137
|
+
|
|
138
|
+
Install: `dw init --preset {name}` or `dw init --solo`.
|
package/.claude/settings.json
CHANGED
|
@@ -13,7 +13,34 @@
|
|
|
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
|
+
"Edit(/.claude/skills/dw-task-init/**)",
|
|
34
|
+
"Edit(/.claude/skills/dw-retroactive/**)",
|
|
35
|
+
"Edit(/.claude/skills/dw-research/**)",
|
|
36
|
+
"Edit(/.claude/skills/dw-plan/**)",
|
|
37
|
+
"Edit(/.claude/skills/dw-execute/**)",
|
|
38
|
+
"Edit(/.claude/skills/dw-handoff/**)",
|
|
39
|
+
"Bash(git commit -m 'fix\\(v1.3.3\\): writer skills v1/v2 compat + cleanup legacy slash-command refs *)",
|
|
40
|
+
"Bash(git commit -m 'feat\\(v1.3.4\\): /dw:plan integrated Quick Debate \\(red/blue team\\) - depth-driven *)"
|
|
41
|
+
],
|
|
42
|
+
"additionalDirectories": [
|
|
43
|
+
"D:\\huygdv_projects\\dw-kit\\.claude\\rules"
|
|
17
44
|
]
|
|
18
45
|
},
|
|
19
46
|
"hooks": {
|