dw-kit 1.4.0 → 1.6.0-rc.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.
- package/.claude/agents/executor.md +80 -80
- package/.claude/hooks/pre-commit-gate.sh +59 -0
- package/.claude/hooks/stop-check.sh +111 -31
- package/.claude/rules/commit-standards.md +48 -37
- package/.claude/rules/dw.md +47 -11
- package/.claude/skills/dw-commit/SKILL.md +7 -4
- package/.claude/skills/dw-decision/SKILL.md +5 -4
- package/.claude/skills/dw-execute/SKILL.md +18 -5
- package/.claude/skills/dw-handoff/SKILL.md +8 -3
- package/.claude/skills/dw-plan/SKILL.md +15 -2
- package/.claude/skills/dw-research/SKILL.md +7 -5
- package/.claude/skills/dw-retroactive/SKILL.md +75 -63
- package/.claude/skills/dw-task-init/SKILL.md +40 -35
- package/.dw/adapters/generic/AGENT.md +171 -169
- package/.dw/core/WORKFLOW.md +450 -450
- package/.dw/core/schemas/agent-claim.schema.json +127 -0
- package/.dw/core/schemas/agent-report.schema.json +72 -0
- package/.dw/core/schemas/task-frontmatter.schema.json +78 -0
- package/.dw/core/templates/v3/task.md +188 -0
- package/CLAUDE.md +2 -2
- package/MIGRATION-v1.5.md +330 -0
- package/README.md +17 -0
- package/package.json +3 -2
- package/src/cli.mjs +161 -0
- package/src/commands/agent-claim.mjs +235 -0
- package/src/commands/agent-inspect.mjs +123 -0
- package/src/commands/doctor.mjs +64 -0
- package/src/commands/lint-task.mjs +112 -0
- package/src/commands/task-migrate.mjs +366 -0
- package/src/commands/task-new.mjs +90 -0
- package/src/commands/task-render.mjs +235 -0
- package/src/commands/task-rotate.mjs +168 -0
- package/src/commands/task-show.mjs +137 -0
- package/src/commands/task-view.mjs +386 -0
- package/src/commands/task-watch.mjs +223 -0
- package/src/lib/active-index.mjs +19 -1
- package/src/lib/agent-claim.mjs +173 -0
- package/src/lib/agent-conflict.mjs +137 -0
- package/src/lib/agent-events.mjs +43 -0
- package/src/lib/agent-report.mjs +96 -0
- package/src/lib/frontmatter.mjs +72 -0
- package/src/lib/lint-rules.mjs +149 -0
- package/src/lib/timeline-parser.mjs +80 -0
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: executor
|
|
3
|
-
description: "Agent thực hiện implementation theo plan đã approve. Có thể chạy trong isolated worktree. Tuân thủ TDD, commit sau mỗi subtask."
|
|
4
|
-
tools:
|
|
5
|
-
- Read
|
|
6
|
-
- Write
|
|
7
|
-
- Edit
|
|
8
|
-
- Bash
|
|
9
|
-
- Grep
|
|
10
|
-
- Glob
|
|
11
|
-
- Agent
|
|
12
|
-
disallowedTools:
|
|
13
|
-
- NotebookEdit
|
|
14
|
-
model: inherit
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
# Executor Agent
|
|
18
|
-
|
|
19
|
-
Bạn là Senior Developer thực hiện implementation. Nhiệm vụ: execute plan đã được approve, tuân thủ TDD, commit sau mỗi subtask.
|
|
20
|
-
|
|
21
|
-
## Nguyên Tắc
|
|
22
|
-
|
|
23
|
-
1. **Đọc plan trước mỗi subtask** — không làm từ memory
|
|
24
|
-
2. **Chỉ làm đúng scope** — không "while I'm here" fixes
|
|
25
|
-
3. **TDD**: Test trước → implement → refactor → commit
|
|
26
|
-
4. **Gặp ambiguity** → DỪNG và hỏi human, không tự suy diễn
|
|
27
|
-
5. **Scope thay đổi** → cập nhật plan, hỏi human trước khi tiếp tục
|
|
28
|
-
6. **Mỗi subtask done** → update progress file + commit
|
|
29
|
-
|
|
30
|
-
## TDD Workflow (mỗi subtask)
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
1. Đọc acceptance criteria của subtask
|
|
34
|
-
2. Viết test mô tả expected behavior → RED (failing)
|
|
35
|
-
3. Implement tối thiểu để test pass → GREEN
|
|
36
|
-
4. Refactor nếu cần (không thay đổi tests) → REFACTOR
|
|
37
|
-
5. Verify: không còn debug code
|
|
38
|
-
6. Update progress file: subtask status → Done
|
|
39
|
-
7. Commit: git commit -m "type(scope): description"
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Khi Gặp Blocker
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
1. Ghi blocker vào progress file với mô tả đầy đủ
|
|
46
|
-
2. Xác định: có thể self-resolve không?
|
|
47
|
-
- Có: document approach, proceed
|
|
48
|
-
- Không: DỪNG, escalate rõ ràng
|
|
49
|
-
3. KHÔNG silent-skip subtask
|
|
50
|
-
4. KHÔNG self-approve scope changes
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Worktree Mode (nếu được chỉ định)
|
|
54
|
-
|
|
55
|
-
Khi task có risk cao (large refactor, breaking changes):
|
|
56
|
-
- Xác nhận với human: "Task này có risk cao. Nên chạy trong isolated worktree. Confirm?"
|
|
57
|
-
- Sau khi confirm: sử dụng isolation: "worktree" khi spawn sub-agents
|
|
58
|
-
- Changes trong worktree không ảnh hưởng main branch cho đến khi human approve merge
|
|
59
|
-
|
|
60
|
-
## Pre-Commit Checklist (mỗi subtask)
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
[ ] Logic đúng? Tests pass?
|
|
64
|
-
[ ] Không còn console.log/debugger/var_dump
|
|
65
|
-
[ ] Không có hardcoded credentials/tokens
|
|
66
|
-
[ ] Commit message theo format: type(scope): description ≤72 chars
|
|
67
|
-
[ ] Progress file updated
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
## Commit Format
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
<type>(<scope>): <
|
|
74
|
-
|
|
75
|
-
[
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
1
|
+
---
|
|
2
|
+
name: executor
|
|
3
|
+
description: "Agent thực hiện implementation theo plan đã approve. Có thể chạy trong isolated worktree. Tuân thủ TDD, commit sau mỗi subtask."
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Edit
|
|
8
|
+
- Bash
|
|
9
|
+
- Grep
|
|
10
|
+
- Glob
|
|
11
|
+
- Agent
|
|
12
|
+
disallowedTools:
|
|
13
|
+
- NotebookEdit
|
|
14
|
+
model: inherit
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Executor Agent
|
|
18
|
+
|
|
19
|
+
Bạn là Senior Developer thực hiện implementation. Nhiệm vụ: execute plan đã được approve, tuân thủ TDD, commit sau mỗi subtask.
|
|
20
|
+
|
|
21
|
+
## Nguyên Tắc
|
|
22
|
+
|
|
23
|
+
1. **Đọc plan trước mỗi subtask** — không làm từ memory
|
|
24
|
+
2. **Chỉ làm đúng scope** — không "while I'm here" fixes
|
|
25
|
+
3. **TDD**: Test trước → implement → refactor → commit
|
|
26
|
+
4. **Gặp ambiguity** → DỪNG và hỏi human, không tự suy diễn
|
|
27
|
+
5. **Scope thay đổi** → cập nhật plan, hỏi human trước khi tiếp tục
|
|
28
|
+
6. **Mỗi subtask done** → update progress file + commit
|
|
29
|
+
|
|
30
|
+
## TDD Workflow (mỗi subtask)
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
1. Đọc acceptance criteria của subtask
|
|
34
|
+
2. Viết test mô tả expected behavior → RED (failing)
|
|
35
|
+
3. Implement tối thiểu để test pass → GREEN
|
|
36
|
+
4. Refactor nếu cần (không thay đổi tests) → REFACTOR
|
|
37
|
+
5. Verify: không còn debug code
|
|
38
|
+
6. Update progress file: subtask status → Done
|
|
39
|
+
7. Commit: git commit -m "type(scope): description"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Khi Gặp Blocker
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
1. Ghi blocker vào progress file với mô tả đầy đủ
|
|
46
|
+
2. Xác định: có thể self-resolve không?
|
|
47
|
+
- Có: document approach, proceed
|
|
48
|
+
- Không: DỪNG, escalate rõ ràng
|
|
49
|
+
3. KHÔNG silent-skip subtask
|
|
50
|
+
4. KHÔNG self-approve scope changes
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Worktree Mode (nếu được chỉ định)
|
|
54
|
+
|
|
55
|
+
Khi task có risk cao (large refactor, breaking changes):
|
|
56
|
+
- Xác nhận với human: "Task này có risk cao. Nên chạy trong isolated worktree. Confirm?"
|
|
57
|
+
- Sau khi confirm: sử dụng isolation: "worktree" khi spawn sub-agents
|
|
58
|
+
- Changes trong worktree không ảnh hưởng main branch cho đến khi human approve merge
|
|
59
|
+
|
|
60
|
+
## Pre-Commit Checklist (mỗi subtask)
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
[ ] Logic đúng? Tests pass?
|
|
64
|
+
[ ] Không còn console.log/debugger/var_dump
|
|
65
|
+
[ ] Không có hardcoded credentials/tokens
|
|
66
|
+
[ ] Commit message theo format: type(scope): description ≤72 chars
|
|
67
|
+
[ ] Progress file updated
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Commit Format
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
<type>(<scope>): <imperative English ≤72 chars>
|
|
74
|
+
|
|
75
|
+
[Optional body — explain WHY, not WHAT, wrap at 72]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `perf`
|
|
79
|
+
|
|
80
|
+
English imperative mood. **Do not append `Co-Authored-By: Claude` or any AI signature.** Full rules: `.claude/rules/commit-standards.md`.
|
|
@@ -67,6 +67,65 @@ if [ -n "$STAGED_FILES" ]; then
|
|
|
67
67
|
fi
|
|
68
68
|
fi
|
|
69
69
|
|
|
70
|
+
# v1.5 (ADR-0008): v3 task.md SVG regen on staged commit
|
|
71
|
+
# Diff-aware — only render tasks whose task.md changed.
|
|
72
|
+
# Fail-graceful: sub-package absent → Mermaid fallback (in-md, no SVG needed).
|
|
73
|
+
# Auto-stage SVG if user opts-in to commit (gitignored by default per .gitignore).
|
|
74
|
+
DW_BIN="$CLAUDE_PROJECT_DIR/bin/dw.mjs"
|
|
75
|
+
if [ -f "$DW_BIN" ] && command -v node >/dev/null 2>&1 && [ -n "$STAGED_FILES" ]; then
|
|
76
|
+
TIMELINE_TASKS=$(echo "$STAGED_FILES" | grep -E '^\.dw/tasks/[^/]+/task\.md$' | sed -E 's|^\.dw/tasks/([^/]+)/task\.md$|\1|' | sort -u)
|
|
77
|
+
if [ -n "$TIMELINE_TASKS" ]; then
|
|
78
|
+
echo "📐 dw-kit: regenerating timeline.svg for staged task.md" >&2
|
|
79
|
+
while IFS= read -r task; do
|
|
80
|
+
[ -z "$task" ] && continue
|
|
81
|
+
node "$DW_BIN" task render "$task" >/dev/null 2>&1 || true
|
|
82
|
+
# Auto-stage SVG if not gitignored (opt-in projects)
|
|
83
|
+
SVG_FILE="$CLAUDE_PROJECT_DIR/.dw/tasks/$task/timeline.svg"
|
|
84
|
+
if [ -f "$SVG_FILE" ]; then
|
|
85
|
+
if ! git -C "$CLAUDE_PROJECT_DIR" check-ignore -q "$SVG_FILE" 2>/dev/null; then
|
|
86
|
+
git -C "$CLAUDE_PROJECT_DIR" add "$SVG_FILE" 2>/dev/null || true
|
|
87
|
+
echo " ✓ staged $task/timeline.svg" >&2
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
done <<EOF
|
|
91
|
+
$TIMELINE_TASKS
|
|
92
|
+
EOF
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# v1.6 (ADR-0009 R2-2): Agent OS post-hoc check.
|
|
97
|
+
# When ≥1 active claim exists, verify staged files fall within an active claim's write_scope.
|
|
98
|
+
# Cooperative protocol — warn only (cannot prevent non-compliant agents).
|
|
99
|
+
if [ -f "$DW_BIN" ] && command -v node >/dev/null 2>&1 && [ -n "$STAGED_FILES" ]; then
|
|
100
|
+
CLAIMS_DIR="$CLAUDE_PROJECT_DIR/.dw/cache/agents/claims"
|
|
101
|
+
if [ -d "$CLAIMS_DIR" ] && ls "$CLAIMS_DIR"/*.json >/dev/null 2>&1; then
|
|
102
|
+
OUT_OF_SCOPE=$(STAGED="$STAGED_FILES" node -e "
|
|
103
|
+
const fs = require('fs');
|
|
104
|
+
const path = require('path');
|
|
105
|
+
(async () => {
|
|
106
|
+
const { listClaims } = await import('$CLAUDE_PROJECT_DIR/src/lib/agent-claim.mjs');
|
|
107
|
+
const { pathMatchesScope } = await import('$CLAUDE_PROJECT_DIR/src/lib/agent-conflict.mjs');
|
|
108
|
+
const claims = listClaims(process.env.CLAUDE_PROJECT_DIR || '$CLAUDE_PROJECT_DIR').filter(c => c._live_status === 'created' || c._live_status === 'active');
|
|
109
|
+
if (claims.length === 0) return;
|
|
110
|
+
const allScopes = claims.flatMap(c => c.write_scope);
|
|
111
|
+
const staged = (process.env.STAGED || '').split(/\r?\n/).filter(Boolean);
|
|
112
|
+
const outside = staged.filter(f => !pathMatchesScope(f, allScopes));
|
|
113
|
+
if (outside.length > 0) {
|
|
114
|
+
console.log('Files NOT in any active claim write_scope:');
|
|
115
|
+
for (const f of outside.slice(0, 10)) console.log(' ' + f);
|
|
116
|
+
if (outside.length > 10) console.log(' ... +' + (outside.length - 10) + ' more');
|
|
117
|
+
}
|
|
118
|
+
})().catch(e => { /* fail-graceful */ });
|
|
119
|
+
" 2>/dev/null || true)
|
|
120
|
+
if [ -n "$OUT_OF_SCOPE" ]; then
|
|
121
|
+
echo "⚠️ Agent OS (ADR-0009 R2-2): post-hoc claim check" >&2
|
|
122
|
+
echo "$OUT_OF_SCOPE" >&2
|
|
123
|
+
echo " Run \`dw agent claims\` to inspect; cooperative trust — proceed with care." >&2
|
|
124
|
+
ISSUES=$((ISSUES + 1))
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
fi
|
|
128
|
+
|
|
70
129
|
# Check: sensitive patterns?
|
|
71
130
|
SENSITIVE=$(git diff --cached 2>/dev/null | grep "^+" | grep -iE '(password|secret|api_key|private_key)[[:space:]]*=[[:space:]]*.{8,}' | grep -v "^+++" | head -3)
|
|
72
131
|
if [ -n "$SENSITIVE" ]; then
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Stop hook: warn on uncommitted changes + auto-
|
|
3
|
-
# v1.4: auto-handoff (ST-2.5) — append session summary
|
|
2
|
+
# Stop hook: warn on uncommitted changes + auto-handoff + auto-rotate v3 task.md
|
|
3
|
+
# v1.4: auto-handoff (ST-2.5) — append session summary when uncommitted
|
|
4
|
+
# v1.5 (ADR-0008): v3 task.md support + auto-rotate Section 4 > 400 lines via `dw task rotate`
|
|
4
5
|
# Output via stderr for user visibility. Always exit 0 (non-blocking).
|
|
5
6
|
|
|
6
7
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
@@ -22,60 +23,139 @@ else
|
|
|
22
23
|
WARNINGS+=("Uncommitted changes:"$'\n'"$CHANGED")
|
|
23
24
|
fi
|
|
24
25
|
|
|
25
|
-
# --- Check in-progress tasks (
|
|
26
|
+
# --- Check in-progress tasks (v1 / v2 / v3 formats) ---
|
|
26
27
|
TASKS_DIR="$PROJECT_DIR/.dw/tasks"
|
|
27
28
|
ACTIVE_TASK=""
|
|
29
|
+
ACTIVE_TASK_FORMAT=""
|
|
30
|
+
ACTIVE_TASK_FILE=""
|
|
28
31
|
|
|
29
32
|
if [ -d "$TASKS_DIR" ]; then
|
|
33
|
+
# v3 format (preferred): task.md with frontmatter status In Progress
|
|
34
|
+
while IFS= read -r timeline_file; do
|
|
35
|
+
if grep -qE "^status:[[:space:]]*(In Progress|Blocked)" "$timeline_file" 2>/dev/null; then
|
|
36
|
+
task_name=$(basename "$(dirname "$timeline_file")")
|
|
37
|
+
WARNINGS+=("Task active (v3): $task_name")
|
|
38
|
+
if [ -z "$ACTIVE_TASK" ]; then
|
|
39
|
+
ACTIVE_TASK="$task_name"
|
|
40
|
+
ACTIVE_TASK_FORMAT="v3"
|
|
41
|
+
ACTIVE_TASK_FILE="$timeline_file"
|
|
42
|
+
fi
|
|
43
|
+
fi
|
|
44
|
+
done < <(find "$TASKS_DIR" -maxdepth 3 -name "task.md" -not -path "*/archive/*" 2>/dev/null)
|
|
45
|
+
|
|
30
46
|
# v1 format: {task}-progress.md with "Trạng thái: In Progress"
|
|
31
47
|
while IFS= read -r progress_file; do
|
|
32
48
|
if grep -q "Trạng thái: In Progress" "$progress_file" 2>/dev/null; then
|
|
33
49
|
task_name=$(basename "$(dirname "$progress_file")")
|
|
34
50
|
WARNINGS+=("Task in-progress (v1): $task_name")
|
|
35
|
-
[ -z "$ACTIVE_TASK" ]
|
|
51
|
+
if [ -z "$ACTIVE_TASK" ]; then
|
|
52
|
+
ACTIVE_TASK="$task_name"
|
|
53
|
+
ACTIVE_TASK_FORMAT="v1"
|
|
54
|
+
ACTIVE_TASK_FILE="$progress_file"
|
|
55
|
+
fi
|
|
36
56
|
fi
|
|
37
57
|
done < <(find "$TASKS_DIR" -maxdepth 3 -name "*-progress.md" -not -path "*/archive/*" 2>/dev/null)
|
|
38
58
|
|
|
39
59
|
# v2 format: tracking.md with frontmatter status In Progress
|
|
40
60
|
while IFS= read -r tracking_file; do
|
|
61
|
+
# Skip if same folder already has task.md (v3 takes precedence)
|
|
62
|
+
folder_dir=$(dirname "$tracking_file")
|
|
63
|
+
[ -f "$folder_dir/task.md" ] && continue
|
|
41
64
|
if grep -qE "^status:.*(In Progress|Code Complete)" "$tracking_file" 2>/dev/null; then
|
|
42
|
-
task_name=$(basename "$
|
|
65
|
+
task_name=$(basename "$folder_dir")
|
|
43
66
|
WARNINGS+=("Task active (v2): $task_name")
|
|
44
|
-
[ -z "$ACTIVE_TASK" ]
|
|
67
|
+
if [ -z "$ACTIVE_TASK" ]; then
|
|
68
|
+
ACTIVE_TASK="$task_name"
|
|
69
|
+
ACTIVE_TASK_FORMAT="v2"
|
|
70
|
+
ACTIVE_TASK_FILE="$tracking_file"
|
|
71
|
+
fi
|
|
45
72
|
fi
|
|
46
73
|
done < <(find "$TASKS_DIR" -maxdepth 3 -name "tracking.md" -not -path "*/archive/*" 2>/dev/null)
|
|
47
74
|
fi
|
|
48
75
|
|
|
49
|
-
# ---
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
76
|
+
# --- v3 auto-rotate (Section 4 > 400 lines → timeline-history.md) ---
|
|
77
|
+
# Fire-and-forget; uses local dw CLI if available.
|
|
78
|
+
if [ "$ACTIVE_TASK_FORMAT" = "v3" ] && [ -n "$ACTIVE_TASK" ]; then
|
|
79
|
+
DW_BIN="$PROJECT_DIR/bin/dw.mjs"
|
|
80
|
+
if [ -f "$DW_BIN" ] && command -v node >/dev/null 2>&1; then
|
|
81
|
+
ROTATE_OUTPUT=$(node "$DW_BIN" task rotate "$ACTIVE_TASK" --quiet 2>&1 || true)
|
|
82
|
+
if [ -n "$ROTATE_OUTPUT" ] && echo "$ROTATE_OUTPUT" | grep -q "rotated"; then
|
|
83
|
+
WARNINGS+=("Auto-rotated Section 4 → timeline-history.md ($ACTIVE_TASK)")
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# --- Auto-handoff: append snippet to active task's tracking/timeline file if uncommitted ---
|
|
89
|
+
if [ "$HAS_UNCOMMITTED" = "1" ] && [ -n "$ACTIVE_TASK_FILE" ]; then
|
|
90
|
+
TS=$(date -u +"%Y-%m-%d %H:%M UTC")
|
|
91
|
+
MARKER="<!-- dw-auto-handoff -->"
|
|
55
92
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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")
|
|
93
|
+
# Only append if no handoff snippet added in last 10 minutes (idempotency via marker + timestamp grep)
|
|
94
|
+
if ! grep -q "$MARKER.*$TS" "$ACTIVE_TASK_FILE" 2>/dev/null; then
|
|
95
|
+
if [ "$ACTIVE_TASK_FORMAT" = "v3" ]; then
|
|
96
|
+
READ_FIRST="Re-read this task.md (Section 1 + 3 + 5) first."
|
|
97
|
+
else
|
|
98
|
+
READ_FIRST="Re-read spec.md + this tracking.md first."
|
|
75
99
|
fi
|
|
100
|
+
|
|
101
|
+
HANDOFF_SNIPPET=$({
|
|
102
|
+
echo ""
|
|
103
|
+
echo "$MARKER"
|
|
104
|
+
echo "### Auto-handoff — $TS"
|
|
105
|
+
echo ""
|
|
106
|
+
echo "Session ended with uncommitted changes."
|
|
107
|
+
echo ""
|
|
108
|
+
echo "**Files changed:**"
|
|
109
|
+
echo '```'
|
|
110
|
+
git -C "$PROJECT_DIR" diff --stat --cached 2>/dev/null
|
|
111
|
+
git -C "$PROJECT_DIR" diff --stat 2>/dev/null
|
|
112
|
+
echo '```'
|
|
113
|
+
echo ""
|
|
114
|
+
echo "Next session: commit or continue work. $READ_FIRST"
|
|
115
|
+
echo ""
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
if [ "$ACTIVE_TASK_FORMAT" = "v3" ]; then
|
|
119
|
+
# v3: insert before Section 5 closing (## 6. Annexes) so handoffs stay in Handoff section
|
|
120
|
+
# Use node for cross-platform reliable section insertion
|
|
121
|
+
if command -v node >/dev/null 2>&1; then
|
|
122
|
+
TMPF=$(mktemp)
|
|
123
|
+
printf '%s' "$HANDOFF_SNIPPET" > "$TMPF"
|
|
124
|
+
node -e "
|
|
125
|
+
const fs = require('fs');
|
|
126
|
+
const file = '$ACTIVE_TASK_FILE';
|
|
127
|
+
const snippet = fs.readFileSync('$TMPF', 'utf8');
|
|
128
|
+
const body = fs.readFileSync(file, 'utf8');
|
|
129
|
+
// Insert right before '## 6. Annexes' (or EOF if not found)
|
|
130
|
+
const sec6 = body.indexOf('## 6. Annexes');
|
|
131
|
+
if (sec6 >= 0) {
|
|
132
|
+
fs.writeFileSync(file, body.slice(0, sec6) + snippet + '\\n' + body.slice(sec6));
|
|
133
|
+
} else {
|
|
134
|
+
// No Section 6 yet — append (rare; only freshly-scaffolded tasks)
|
|
135
|
+
fs.appendFileSync(file, snippet);
|
|
136
|
+
}
|
|
137
|
+
" 2>/dev/null
|
|
138
|
+
rm -f "$TMPF"
|
|
139
|
+
else
|
|
140
|
+
# Fallback: append to EOF (degraded for v3 but still functional)
|
|
141
|
+
printf '%s' "$HANDOFF_SNIPPET" >> "$ACTIVE_TASK_FILE" 2>/dev/null
|
|
142
|
+
fi
|
|
143
|
+
else
|
|
144
|
+
# v1/v2: append to EOF (legacy behavior, unchanged)
|
|
145
|
+
printf '%s' "$HANDOFF_SNIPPET" >> "$ACTIVE_TASK_FILE" 2>/dev/null
|
|
146
|
+
fi
|
|
147
|
+
WARNINGS+=("Auto-handoff appended to: $ACTIVE_TASK_FILE")
|
|
76
148
|
fi
|
|
77
149
|
fi
|
|
78
150
|
|
|
151
|
+
# --- Nudge dw task show (first-of-session, v3 only) ---
|
|
152
|
+
NUDGE_FILE="$PROJECT_DIR/.dw/cache/.show-nudge-$(date -u +%Y-%m-%d)"
|
|
153
|
+
if [ "$ACTIVE_TASK_FORMAT" = "v3" ] && [ -n "$ACTIVE_TASK" ] && [ ! -f "$NUDGE_FILE" ]; then
|
|
154
|
+
mkdir -p "$PROJECT_DIR/.dw/cache" 2>/dev/null
|
|
155
|
+
touch "$NUDGE_FILE" 2>/dev/null
|
|
156
|
+
WARNINGS+=("Tip: \`dw task show $ACTIVE_TASK\` (terminal) · \`dw task view $ACTIVE_TASK\` (HTML in browser) · \`dw task lint\` (drift check)")
|
|
157
|
+
fi
|
|
158
|
+
|
|
79
159
|
# --- Print warnings ---
|
|
80
160
|
if [ ${#WARNINGS[@]} -gt 0 ]; then
|
|
81
161
|
printf -- "--- dw stop-check ---\n" >&2
|
|
@@ -1,37 +1,48 @@
|
|
|
1
|
-
# Commit Standards
|
|
2
|
-
|
|
3
|
-
## Format
|
|
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
|
-
|
|
37
|
-
|
|
1
|
+
# Commit Standards
|
|
2
|
+
|
|
3
|
+
## Format
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
<type>(<scope>): <imperative English subject ≤72 chars>
|
|
7
|
+
|
|
8
|
+
[Optional body — explain WHY, wrap at 72 chars]
|
|
9
|
+
|
|
10
|
+
[Optional footer — BREAKING CHANGE: ..., Refs: #123]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**English only.** Use imperative mood: `add user auth`, `fix login redirect`, `update API client` — never `added`, `fixes`, or past tense.
|
|
14
|
+
|
|
15
|
+
**Do not append `Co-Authored-By: Claude` or any AI signature.** Commits are authored by the human who reviewed and shipped them.
|
|
16
|
+
|
|
17
|
+
## Types
|
|
18
|
+
|
|
19
|
+
| Type | When to use |
|
|
20
|
+
|------|-------------|
|
|
21
|
+
| `feat` | New feature |
|
|
22
|
+
| `fix` | Bug fix |
|
|
23
|
+
| `refactor` | Restructure without behavior change |
|
|
24
|
+
| `test` | Add or update tests |
|
|
25
|
+
| `docs` | Documentation, comments |
|
|
26
|
+
| `chore` | Build, config, dependencies |
|
|
27
|
+
| `style` | Format, whitespace (no logic change) |
|
|
28
|
+
| `perf` | Performance improvement |
|
|
29
|
+
|
|
30
|
+
## Rules
|
|
31
|
+
|
|
32
|
+
- One commit = one subtask or one complete logical unit
|
|
33
|
+
- Subject ≤72 chars; body wrapped at 72
|
|
34
|
+
- Imperative present tense (`add`, `fix`, `update` — not `added`, `fixed`, `updates`)
|
|
35
|
+
- Never commit secrets (`.env`, credentials, tokens)
|
|
36
|
+
- Never commit leftover `console.log`, `debugger`, etc.
|
|
37
|
+
|
|
38
|
+
## Branch Naming
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
<type>/<task-name>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Examples: `feat/user-auth`, `fix/login-redirect`, `refactor/api-structure`
|
|
45
|
+
|
|
46
|
+
## Localization Override
|
|
47
|
+
|
|
48
|
+
This convention defaults to English to match the global open-source norm. A team that ships only in another language MAY override this rule in their own project by editing this file — but the toolkit itself ships English-default templates.
|
package/.claude/rules/dw.md
CHANGED
|
@@ -18,7 +18,7 @@ Prompt contains `--no-dw` → ignore all dw instructions for that request, work
|
|
|
18
18
|
| **Guards** | Block unsafe actions | privacy-block, pre-commit-gate | Non-negotiable safety |
|
|
19
19
|
| **Surfaces** | Make state visible | ACTIVE.md, project-map, modules | Shared team context |
|
|
20
20
|
| **Records** | Capture decisions | ADRs in `.dw/decisions/` | Organizational memory |
|
|
21
|
-
| **Bridges** | Connect across sessions | auto-handoff,
|
|
21
|
+
| **Bridges** | Connect across sessions | auto-handoff, task.md, auto-rotate | Continuity over time |
|
|
22
22
|
| **Tunes** | Behavioral knobs | roles, depth, presets | Team/solo customization |
|
|
23
23
|
|
|
24
24
|
---
|
|
@@ -30,8 +30,8 @@ Assess per task — file count, API changes, git blame:
|
|
|
30
30
|
| Scope | Depth | Approach |
|
|
31
31
|
|-------|-------|----------|
|
|
32
32
|
| ≤2 files, hotfix | quick | Understand → Execute → Close |
|
|
33
|
-
| 3–5 files, new module | standard |
|
|
34
|
-
| 6+ files, API/DB/security | thorough | Full
|
|
33
|
+
| 3–5 files, new module | standard | task.md (Sections 1-5) |
|
|
34
|
+
| 6+ files, API/DB/security | thorough | Full task.md + Section 6 Annexes + optional Section 7 Debate |
|
|
35
35
|
|
|
36
36
|
Default when unsure: `standard`.
|
|
37
37
|
|
|
@@ -40,22 +40,56 @@ Default when unsure: `standard`.
|
|
|
40
40
|
## Session Start
|
|
41
41
|
|
|
42
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`
|
|
43
|
+
2. Resume any task with status `In Progress` from its `task.md` (v3) / `tracking.md` (v2)
|
|
44
44
|
3. Check `.dw/decisions/` for recent ADRs if task touches architecture
|
|
45
|
+
4. Optional quick scan: `dw task show <name>` for ANSI snapshot
|
|
45
46
|
|
|
46
47
|
---
|
|
47
48
|
|
|
48
|
-
## Task Docs (
|
|
49
|
+
## Task Docs (v3 default — 1 file, per ADR-0008)
|
|
49
50
|
|
|
50
51
|
```
|
|
51
52
|
.dw/tasks/{task-name}/
|
|
52
|
-
├──
|
|
53
|
-
|
|
53
|
+
├── task.md # canonical SoT: Snapshot + Intent + Tracker + Changelog + Handoff
|
|
54
|
+
├── timeline.svg # auto-rendered sidecar (v1.6+ via dw-kit-render)
|
|
55
|
+
└── (free-form appendages):
|
|
56
|
+
├── baseline.md # benchmark snapshots
|
|
57
|
+
├── experiment-{id}.md # spike notes
|
|
58
|
+
├── debate-r{N}.md # extended adversarial logs
|
|
59
|
+
└── timeline-history.md # auto-rotated changelog overflow
|
|
54
60
|
```
|
|
55
61
|
|
|
56
|
-
|
|
62
|
+
**Section structure** (status lives ONLY in Section 3 — drift prevention):
|
|
63
|
+
1. Snapshot · 2. Intent & Scope · 3. Subtask Tracker · 4. Timeline/Changelog · 5. Handoff & Friction · 6. Annexes · 7. Debate Log (optional thorough)
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
**Lint default strict** — drift markers (✅🟡 status) in Section 2 → error. Configure via `task.lint: warn | off` in `dw.config.yml`.
|
|
66
|
+
|
|
67
|
+
**CLI:** `dw task new <name>` (scaffold) · `dw task show [name]` (ANSI snapshot) · `dw task lint [name]` (drift + schema check) · `dw task migrate <name>` (v2→v3) · `dw task rotate [name]` (auto Section-4 overflow).
|
|
68
|
+
|
|
69
|
+
**Backward compat:**
|
|
70
|
+
- v2 (`spec.md` + `tracking.md`) read-only — migrate via `dw task migrate <name>`.
|
|
71
|
+
- v1 (3-file `context + plan + progress`) read-only legacy.
|
|
72
|
+
|
|
73
|
+
Templates: `.dw/core/templates/v3/task.md`. Schema: `.dw/core/schemas/task-frontmatter.schema.json` (ajv-validated).
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Agent OS (v1.6+, ADR-0009)
|
|
78
|
+
|
|
79
|
+
Multi-agent orchestration protocol. Multiple AI agents (Claude Code / Codex / Gemini / human) work from same `task.md` without conflict.
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
dw agent claim <task> --subtasks ST-1 --write "src/foo.js" --vendor claude --lease 1h
|
|
83
|
+
dw agent claims # list active
|
|
84
|
+
dw agent conflicts # detect overlaps (exit 1 if dirty)
|
|
85
|
+
dw agent release <claim-id> # clean exit
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Cooperative-only:** protocol catches violations post-hoc via `dw agent conflicts` + `pre-commit-gate`. Not an enforcement system.
|
|
89
|
+
|
|
90
|
+
**Storage:** `.dw/cache/agents/claims/{id}.json` (gitignored ephemeral); `.dw/tasks/{task}/reports/{agent}-{ts}.md` + `events.jsonl` (committed audit).
|
|
91
|
+
|
|
92
|
+
**Workflow:** orchestrator role splits work → agents claim → write → release → reports merged into `task.md` Section 3/4 → orchestrator stops before push/release for human approval.
|
|
59
93
|
|
|
60
94
|
---
|
|
61
95
|
|
|
@@ -82,11 +116,13 @@ See `.dw/core/skills-index.md` for complete list with descriptions.
|
|
|
82
116
|
## Commit Format
|
|
83
117
|
|
|
84
118
|
```
|
|
85
|
-
<type>(<scope>): <
|
|
119
|
+
<type>(<scope>): <imperative English subject ≤72 chars>
|
|
86
120
|
```
|
|
87
121
|
|
|
88
122
|
Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `perf`
|
|
89
123
|
|
|
124
|
+
English imperative mood (`add`, `fix`, `update` — not past tense or other languages). **Do not append `Co-Authored-By: Claude` or any AI signature.** Full rules: `.claude/rules/commit-standards.md`.
|
|
125
|
+
|
|
90
126
|
---
|
|
91
127
|
|
|
92
128
|
## Hooks
|
|
@@ -95,7 +131,7 @@ Types: `feat` `fix` `refactor` `test` `docs` `chore` `style` `perf`
|
|
|
95
131
|
|------|---------|
|
|
96
132
|
| `privacy-block` | Guard — block .env/credentials/keys |
|
|
97
133
|
| `pre-commit-gate` | Guard — quality check + sensitive scan |
|
|
98
|
-
| `stop-check` | Bridge — auto-handoff to tracking.md + uncommitted warning |
|
|
134
|
+
| `stop-check` | Bridge — auto-handoff to task.md (v3) / tracking.md (v2) + auto-rotate Section 4 + uncommitted warning |
|
|
99
135
|
| `telemetry-log` | Meta — local event log for v1.4 cut decisions |
|
|
100
136
|
|
|
101
137
|
Legacy (deprecated, removal in v2.0 based on telemetry): scout-block, post-write, progress-ping, session-init, safety-guard.
|
|
@@ -48,17 +48,20 @@ Nếu không có changes → thông báo "Không có gì để commit."
|
|
|
48
48
|
|
|
49
49
|
### 5. Tạo commit message
|
|
50
50
|
|
|
51
|
-
Nếu có `$ARGUMENTS` → dùng làm
|
|
51
|
+
Nếu có `$ARGUMENTS` → dùng làm subject (rewrite sang English imperative nếu input không phải English):
|
|
52
52
|
```
|
|
53
|
-
<auto-detect-type>(<auto-detect-scope>):
|
|
53
|
+
<auto-detect-type>(<auto-detect-scope>): <imperative English ≤72 chars>
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
[Optional body — explain WHY in English, wrap at 72]
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
+
**KHÔNG append `Co-Authored-By: Claude` hoặc bất kỳ AI signature nào.**
|
|
59
|
+
Convention chi tiết: `.claude/rules/commit-standards.md`.
|
|
60
|
+
|
|
58
61
|
Nếu KHÔNG có `$ARGUMENTS` → phân tích diff và tạo message tự động:
|
|
59
62
|
- Detect type từ loại thay đổi (feat/fix/refactor/test/docs/chore)
|
|
60
63
|
- Detect scope từ files/directories changed
|
|
61
|
-
-
|
|
64
|
+
- Subject: imperative English, ≤72 chars (`add X`, `fix Y`, `update Z` — không past tense)
|
|
62
65
|
|
|
63
66
|
### 6. Thực hiện commit
|
|
64
67
|
```bash
|
|
@@ -78,7 +78,7 @@ Nếu yes → write file + print:
|
|
|
78
78
|
✓ ADR-{NNNN} created
|
|
79
79
|
Status: Proposed
|
|
80
80
|
Next: Review → change status to Accepted when approved
|
|
81
|
-
Related task: update tracking.md với reference
|
|
81
|
+
Related task: update task.md (v3) / tracking.md (v2) với reference
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
## Quality Bar
|
|
@@ -110,7 +110,8 @@ Trong các case này, đẩy lại user với câu hỏi clarify.
|
|
|
110
110
|
|
|
111
111
|
## Super-power: Link related task
|
|
112
112
|
|
|
113
|
-
Sau khi save ADR, nếu đang trong task folder
|
|
113
|
+
Sau khi save ADR, nếu đang trong task folder, check task file theo thứ tự ưu tiên:
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
- **v3** (default): `.dw/tasks/*/task.md` — append Section 4 Changelog entry: `Referenced: ADR-{NNNN}`; update frontmatter `related_adr: ADR-{NNNN}` nếu chưa có.
|
|
116
|
+
- **v2**: `.dw/tasks/*/tracking.md` — append Changelog entry; update spec.md frontmatter `related_adr`.
|
|
117
|
+
- **v1** (legacy): `.dw/tasks/*/*-progress.md` — append changelog
|