dw-kit 1.0.0 → 1.0.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,243 +0,0 @@
1
- #!/bin/bash
2
- # scripts/migrate-v03-to-v1.sh
3
- # ⚠ DEPRECATED: Prefer `dw migrate` from npm CLI.
4
- # Migrate project từ dw-kit v0.3 sang v1
5
- # Usage: bash scripts/migrate-v03-to-v1.sh [--dry-run]
6
-
7
- set -euo pipefail
8
-
9
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11
-
12
- DRY_RUN=false
13
- [ "${1:-}" = "--dry-run" ] && DRY_RUN=true
14
-
15
- log() { echo " $*"; }
16
- info() { echo ""; echo "▶ $*"; }
17
- warn() { echo " ⚠ $*"; }
18
- ok() { echo " ✓ $*"; }
19
- dry() { [ "$DRY_RUN" = true ] && echo " [dry] $*" || true; }
20
- do_action() {
21
- if [ "$DRY_RUN" = true ]; then echo " [dry] $*"; else eval "$*"; fi
22
- }
23
-
24
- OLD_CONFIG="$PROJECT_ROOT/.dw/config/dw.config.yml"
25
- NEW_CONFIG_DIR="$PROJECT_ROOT/config"
26
- NEW_CONFIG="$NEW_CONFIG_DIR/dw.config.yml"
27
-
28
- echo ""
29
- echo "══════════════════════════════════════════"
30
- echo " dw-kit v0.3 → v1 Migration"
31
- [ "$DRY_RUN" = true ] && echo " Mode: DRY RUN"
32
- echo "══════════════════════════════════════════"
33
-
34
- # ── Step 1: Validate v0.3 present ────────────────────────────────────────────
35
- info "Step 1: Validate source config"
36
-
37
- if [ ! -f "$OLD_CONFIG" ]; then
38
- echo " No config/dw.config.yml found. Already on v1 or fresh install."
39
- exit 0
40
- fi
41
-
42
- if [ -L "$OLD_CONFIG" ]; then
43
- warn "config/dw.config.yml is already a symlink → migration may have already run."
44
- read -r -p " Continue anyway? [y/N] " confirm
45
- [[ "$confirm" =~ ^[Yy]$ ]] || exit 0
46
- fi
47
-
48
- ok "Found config/dw.config.yml"
49
-
50
- # ── Step 2: Detect customized skills ─────────────────────────────────────────
51
- info "Step 2: Detect customized skills"
52
-
53
- OVERRIDES_DIR="$PROJECT_ROOT/.dw/adapters/claude-cli/overrides/skills"
54
- SKILLS_DIR="$PROJECT_ROOT/.claude/skills"
55
- customized_count=0
56
-
57
- # Heuristic: compare với toolkit's own copy nếu có, hoặc check git
58
- if command -v git &>/dev/null && git -C "$PROJECT_ROOT" rev-parse --git-dir &>/dev/null; then
59
- for skill_dir in "$SKILLS_DIR"/*/; do
60
- [ -d "$skill_dir" ] || continue
61
- skill_name=$(basename "$skill_dir")
62
- skill_file="$skill_dir/SKILL.md"
63
- [ -f "$skill_file" ] || continue
64
-
65
- # Check if file was modified from its committed version
66
- if ! git -C "$PROJECT_ROOT" diff --quiet HEAD -- ".claude/skills/$skill_name/SKILL.md" 2>/dev/null; then
67
- warn "Skill '$skill_name' has uncommitted changes → preserving to overrides/"
68
- do_action "mkdir -p '$OVERRIDES_DIR/$skill_name'"
69
- do_action "cp '$skill_file' '$OVERRIDES_DIR/$skill_name/SKILL.md'"
70
- customized_count=$((customized_count + 1))
71
- fi
72
- done
73
- else
74
- warn "Not a git repo or git not available. Cannot auto-detect customizations."
75
- warn "Manually copy customized skills to adapters/claude-cli/overrides/skills/ before upgrading."
76
- fi
77
-
78
- if [ $customized_count -gt 0 ]; then
79
- ok "$customized_count customized skill(s) preserved to overrides/"
80
- else
81
- ok "No customized skills detected"
82
- fi
83
-
84
- # ── Step 3: Migrate config ────────────────────────────────────────────────────
85
- info "Step 3: Migrate config (config/dw.config.yml → config/dw.config.yml)"
86
-
87
- if [ -f "$NEW_CONFIG" ]; then
88
- warn "config/dw.config.yml already exists. Skipping config migration."
89
- warn "Review manually: $NEW_CONFIG"
90
- else
91
- if ! command -v python3 &>/dev/null; then
92
- warn "python3 not found. Manual config migration needed."
93
- warn "Map: level: 1 → default_depth: quick"
94
- warn " level: 2 → default_depth: standard"
95
- warn " level: 3 → default_depth: thorough"
96
- else
97
- if [ "$DRY_RUN" = false ]; then
98
- mkdir -p "$NEW_CONFIG_DIR"
99
- python3 - "$OLD_CONFIG" "$NEW_CONFIG" <<'PYEOF'
100
- import sys, re
101
-
102
- old_path = sys.argv[1]
103
- new_path = sys.argv[2]
104
-
105
- with open(old_path) as f:
106
- old_content = f.read()
107
-
108
- # Extract values from old config
109
- def get_val(key, content, default=""):
110
- m = re.search(rf'^\s*{re.escape(key)}:\s*([^\n#]+)', content, re.MULTILINE)
111
- if m:
112
- return m.group(1).strip().strip('"').strip("'")
113
- return default
114
-
115
- project_name = get_val("name", old_content, "my-project")
116
- project_lang = get_val("language", old_content, "vi")
117
- level_str = get_val("level", old_content, "2")
118
-
119
- depth_map = {"1": "quick", "2": "standard", "3": "thorough"}
120
- depth = depth_map.get(level_str, "standard")
121
-
122
- # Extract roles
123
- roles_match = re.findall(r'^\s+-\s+(dev|techlead|ba|qc|pm)\b', old_content, re.MULTILINE)
124
- roles = roles_match if roles_match else ["dev"]
125
-
126
- # Extract quality commands
127
- test_cmd = get_val("test_command", old_content, "")
128
- lint_cmd = get_val("lint_command", old_content, "")
129
-
130
- # Extract paths
131
- tasks_path = get_val("tasks", old_content, ".dw/tasks")
132
- docs_path = get_val("docs", old_content, ".dw/docs")
133
-
134
- # Build new config
135
- roles_yaml = "\n".join(f" - {r}" for r in roles)
136
-
137
- new_config = f"""# dw-kit Configuration
138
- # Generated by migrate-v03-to-v1.sh
139
- # Review and adjust as needed.
140
-
141
- project:
142
- name: "{project_name}"
143
- language: "{project_lang}"
144
-
145
- workflow:
146
- default_depth: "{depth}" # quick | standard | thorough
147
- # AI assesses per-task and may recommend different depth
148
-
149
- team:
150
- roles:
151
- {roles_yaml}
152
-
153
- quality:
154
- test_command: "{test_cmd}" # empty = skip
155
- lint_command: "{lint_cmd}" # empty = skip
156
- block_on_fail: false
157
-
158
- tracking:
159
- estimation: false
160
- log_work: false
161
- estimation_unit: "hours"
162
-
163
- paths:
164
- tasks: "{tasks_path}"
165
- docs: "{docs_path}"
166
-
167
- # Claude-specific capabilities (Layer 2)
168
- claude:
169
- models:
170
- plan: "" # empty = inherit from Claude Code settings
171
- execute: ""
172
- review: ""
173
- structured_output: true
174
- worktree_execution: false
175
- mcp: []
176
-
177
- # Toolkit version tracking (do not edit manually)
178
- _toolkit:
179
- core_version: "1.0"
180
- platform_version: "1.0"
181
- capability_version: "1.0"
182
- migrated_from: "v0.3"
183
- last_upgrade: "{__import__('datetime').date.today().isoformat()}"
184
- """
185
-
186
- with open(new_path, 'w') as f:
187
- f.write(new_config)
188
- PYEOF
189
- ok "config/dw.config.yml created (migrated from level: $level_str → depth: $(grep default_depth "$NEW_CONFIG" | head -1))"
190
- else
191
- dry "Would create config/dw.config.yml from config/dw.config.yml"
192
- fi
193
- fi
194
- fi
195
-
196
- # ── Step 4: Create backward-compat symlink ────────────────────────────────────
197
- info "Step 4: Create backward-compat symlink"
198
-
199
- if [ -f "$NEW_CONFIG" ] && [ ! -L "$OLD_CONFIG" ]; then
200
- if [ "$DRY_RUN" = false ]; then
201
- # Backup original
202
- cp "$OLD_CONFIG" "${OLD_CONFIG}.bak"
203
- ok "Backed up original to config/dw.config.yml.bak"
204
- # Create symlink
205
- rm "$OLD_CONFIG"
206
- ln -s ".dw/.dw/config/dw.config.yml" "$OLD_CONFIG"
207
- ok "Created symlink: config/dw.config.yml → config/dw.config.yml"
208
- else
209
- dry "Would create symlink: config/dw.config.yml → config/dw.config.yml"
210
- fi
211
- fi
212
-
213
- # ── Step 5: Check CI/CD references ───────────────────────────────────────────
214
- info "Step 5: Check CI/CD references"
215
-
216
- found_refs=false
217
- for ci_file in ".github/workflows/"*.yml ".gitlab-ci.yml" "Makefile" ".circleci/config.yml" "package.json"; do
218
- full_path="$PROJECT_ROOT/$ci_file"
219
- if [ -f "$full_path" ]; then
220
- if grep -qE "dv-workflow\.config\.yml|dv-workflow-kit" "$full_path" 2>/dev/null; then
221
- warn "Found reference in: $ci_file — update to config/dw.config.yml"
222
- found_refs=true
223
- fi
224
- fi
225
- done
226
- [ "$found_refs" = false ] && ok "No CI/CD references found"
227
-
228
- # ── Summary ───────────────────────────────────────────────────────────────────
229
- echo ""
230
- echo "══════════════════════════════════════════"
231
- if [ "$DRY_RUN" = true ]; then
232
- echo " DRY RUN complete. Review above, then run without --dry-run."
233
- else
234
- echo " Migration complete!"
235
- echo ""
236
- echo " Next steps:"
237
- echo " 1. Review config/dw.config.yml — adjust team.roles, quality commands"
238
- echo " 2. Run: bash setup.sh to regenerate .claude/ from new config"
239
- echo " 3. Check adapters/claude-cli/overrides/ for preserved customizations"
240
- [ "$found_refs" = true ] && echo " 4. ⚠ Update CI/CD files (see warnings above)"
241
- fi
242
- echo "══════════════════════════════════════════"
243
- echo ""
@@ -1,246 +0,0 @@
1
- #!/bin/bash
2
- # scripts/upgrade.sh
3
- # ⚠ DEPRECATED: Prefer `dw upgrade` from npm CLI.
4
- # Upgrade dw-kit: update generated/ files, preserve overrides/ và extensions/
5
- # Usage: bash scripts/upgrade.sh [--dry-run] [--layer core|platform|all]
6
-
7
- set -euo pipefail
8
-
9
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
- PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11
-
12
- # ── Options ──────────────────────────────────────────────────────────────────
13
- DRY_RUN=false
14
- LAYER="all"
15
-
16
- for arg in "$@"; do
17
- case "$arg" in
18
- --dry-run) DRY_RUN=true ;;
19
- --layer) shift; LAYER="${1:-all}" ;;
20
- --layer=*) LAYER="${arg#*=}" ;;
21
- esac
22
- done
23
-
24
- # ── Helpers ───────────────────────────────────────────────────────────────────
25
- log() { echo " $*"; }
26
- info() { echo ""; echo "▶ $*"; }
27
- warn() { echo " ⚠ $*"; }
28
- ok() { echo " ✓ $*"; }
29
- dry() { echo " [dry-run] $*"; }
30
-
31
- do_copy() {
32
- local src="$1" dst="$2"
33
- if [ "$DRY_RUN" = true ]; then
34
- dry "cp $src → $dst"
35
- else
36
- mkdir -p "$(dirname "$dst")"
37
- cp "$src" "$dst"
38
- fi
39
- }
40
-
41
- do_mkdir() {
42
- if [ "$DRY_RUN" = true ]; then
43
- dry "mkdir -p $1"
44
- else
45
- mkdir -p "$1"
46
- fi
47
- }
48
-
49
- # ── Read current versions ─────────────────────────────────────────────────────
50
- CONFIG_FILE="$PROJECT_ROOT/.dw/config/dw.config.yml"
51
- CURRENT_CORE="unknown"
52
- CURRENT_PLATFORM="unknown"
53
-
54
- if [ -f "$CONFIG_FILE" ]; then
55
- CURRENT_CORE=$(grep -m1 "core_version:" "$CONFIG_FILE" 2>/dev/null \
56
- | sed 's/.*:[[:space:]]*//' | tr -d '"' | tr -d "'" | tr -d '[:space:]' || echo "unknown")
57
- CURRENT_PLATFORM=$(grep -m1 "platform_version:" "$CONFIG_FILE" 2>/dev/null \
58
- | sed 's/.*:[[:space:]]*//' | tr -d '"' | tr -d "'" | tr -d '[:space:]' || echo "unknown")
59
- fi
60
-
61
- TOOLKIT_CORE=$(grep -m1 "core-version:" "$PROJECT_ROOT/core/WORKFLOW.md" 2>/dev/null \
62
- | sed 's/.*core-version:[[:space:]]*//' | tr -d ' -->' | head -1 || echo "1.0")
63
-
64
- echo ""
65
- echo "══════════════════════════════════════════"
66
- echo " dw-kit Upgrade"
67
- echo " Current: core=$CURRENT_CORE platform=$CURRENT_PLATFORM"
68
- echo " Toolkit: core=$TOOLKIT_CORE"
69
- if [ "$DRY_RUN" = true ]; then
70
- echo " Mode: DRY RUN (no changes)"
71
- fi
72
- echo "══════════════════════════════════════════"
73
-
74
- # ── Phase 1: Update generated/ ───────────────────────────────────────────────
75
- info "Phase 1: Update generated files"
76
-
77
- GENERATED="$PROJECT_ROOT/.dw/adapters/claude-cli/generated"
78
- CLAUDE_DIR="$PROJECT_ROOT/.claude"
79
-
80
- if [ "$LAYER" = "all" ] || [ "$LAYER" = "platform" ]; then
81
- # Copy generated skills → .claude/skills (skip if override exists)
82
- if [ -d "$GENERATED/skills" ]; then
83
- for skill_dir in "$GENERATED/skills"/*/; do
84
- skill_name=$(basename "$skill_dir")
85
- override="$PROJECT_ROOT/.dw/adapters/claude-cli/overrides/skills/$skill_name"
86
-
87
- if [ -d "$override" ]; then
88
- warn "Skill '$skill_name': override exists → keeping override"
89
- # Copy override instead of generated
90
- for f in "$override"/*; do
91
- [ -f "$f" ] && do_copy "$f" "$CLAUDE_DIR/skills/$skill_name/$(basename "$f")"
92
- done
93
- else
94
- for f in "$skill_dir"*; do
95
- [ -f "$f" ] && do_copy "$f" "$CLAUDE_DIR/skills/$skill_name/$(basename "$f")"
96
- done
97
- ok "Skill '$skill_name': updated"
98
- fi
99
- done
100
- fi
101
-
102
- # Copy generated agents → .claude/agents (skip if override exists)
103
- if [ -d "$GENERATED/agents" ]; then
104
- for agent_file in "$GENERATED/agents"/*.md; do
105
- [ -f "$agent_file" ] || continue
106
- agent_name=$(basename "$agent_file")
107
- override="$PROJECT_ROOT/.dw/adapters/claude-cli/overrides/agents/$agent_name"
108
-
109
- if [ -f "$override" ]; then
110
- warn "Agent '$agent_name': override exists → keeping override"
111
- do_copy "$override" "$CLAUDE_DIR/agents/$agent_name"
112
- else
113
- do_copy "$agent_file" "$CLAUDE_DIR/agents/$agent_name"
114
- ok "Agent '$agent_name': updated"
115
- fi
116
- done
117
- fi
118
- fi
119
-
120
- # ── Phase 2: Copy extensions/ ────────────────────────────────────────────────
121
- info "Phase 2: Copy extensions (team-specific skills)"
122
-
123
- EXTENSIONS="$PROJECT_ROOT/.dw/adapters/claude-cli/extensions"
124
- if [ -d "$EXTENSIONS" ]; then
125
- ext_count=0
126
- for ext_dir in "$EXTENSIONS"/*/; do
127
- [ -d "$ext_dir" ] || continue
128
- ext_name=$(basename "$ext_dir")
129
- [ "$ext_name" = ".gitkeep" ] && continue
130
-
131
- do_mkdir "$CLAUDE_DIR/skills/$ext_name"
132
- for f in "$ext_dir"*; do
133
- [ -f "$f" ] && do_copy "$f" "$CLAUDE_DIR/skills/$ext_name/$(basename "$f")"
134
- done
135
- ok "Extension '$ext_name': installed"
136
- ext_count=$((ext_count + 1))
137
- done
138
- [ $ext_count -eq 0 ] && log "No extensions found"
139
- fi
140
-
141
- # ── Phase 3: Merge settings.json ─────────────────────────────────────────────
142
- info "Phase 3: Merge settings.json"
143
-
144
- SETTINGS_TEMPLATE="$GENERATED/settings.json"
145
- SETTINGS_TARGET="$CLAUDE_DIR/settings.json"
146
-
147
- if [ -f "$SETTINGS_TEMPLATE" ] && [ -f "$SETTINGS_TARGET" ]; then
148
- if command -v python3 &>/dev/null; then
149
- if [ "$DRY_RUN" = true ]; then
150
- dry "Merge settings.json (python3)"
151
- else
152
- python3 - "$SETTINGS_TEMPLATE" "$SETTINGS_TARGET" <<'PYEOF'
153
- import json, sys
154
-
155
- template_path = sys.argv[1]
156
- target_path = sys.argv[2]
157
-
158
- with open(template_path) as f:
159
- template = json.load(f)
160
- with open(target_path) as f:
161
- target = json.load(f)
162
-
163
- def deep_merge(base, override):
164
- """Override values from base with override, but preserve keys not in template."""
165
- result = dict(base)
166
- for k, v in override.items():
167
- if k in result and isinstance(result[k], dict) and isinstance(v, dict):
168
- result[k] = deep_merge(result[k], v)
169
- else:
170
- result[k] = v
171
- return result
172
-
173
- merged = deep_merge(template, target)
174
-
175
- with open(target_path, 'w') as f:
176
- json.dump(merged, f, indent=2, ensure_ascii=False)
177
- f.write('\n')
178
- PYEOF
179
- ok "settings.json: merged"
180
- fi
181
- else
182
- warn "python3 not found — skipping settings.json merge. Manual merge may be needed."
183
- fi
184
- elif [ -f "$SETTINGS_TEMPLATE" ] && [ ! -f "$SETTINGS_TARGET" ]; then
185
- do_copy "$SETTINGS_TEMPLATE" "$SETTINGS_TARGET"
186
- ok "settings.json: created from template"
187
- fi
188
-
189
- # ── Phase 4: Update version in config ────────────────────────────────────────
190
- info "Phase 4: Update version tracking"
191
-
192
- if [ "$DRY_RUN" = false ] && [ -f "$CONFIG_FILE" ]; then
193
- TODAY=$(date +%Y-%m-%d)
194
- if command -v python3 &>/dev/null; then
195
- python3 - "$CONFIG_FILE" "$TOOLKIT_CORE" "$TODAY" <<'PYEOF'
196
- import sys, re
197
-
198
- config_path = sys.argv[1]
199
- new_core = sys.argv[2]
200
- today = sys.argv[3]
201
-
202
- with open(config_path) as f:
203
- content = f.read()
204
-
205
- content = re.sub(r'(core_version:\s*)["\']?[\d.]+["\']?', f'\\g<1>"{new_core}"', content)
206
- content = re.sub(r'(last_upgrade:\s*)["\']?[\d-]+["\']?', f'\\g<1>"{today}"', content)
207
-
208
- with open(config_path, 'w') as f:
209
- f.write(content)
210
- PYEOF
211
- ok "Config version updated: core=$TOOLKIT_CORE, last_upgrade=$TODAY"
212
- fi
213
- fi
214
-
215
- # ── Phase 5: Check for CI/CD references needing manual update ────────────────
216
- info "Phase 5: Check backward compatibility"
217
-
218
- OLD_CONFIG="$PROJECT_ROOT/.dw/config/dw.config.yml"
219
- if [ -f "$OLD_CONFIG" ]; then
220
- if [ -L "$OLD_CONFIG" ]; then
221
- ok "config/dw.config.yml: symlink intact (backward compat)"
222
- else
223
- warn "config/dw.config.yml exists as real file. Run scripts/migrate-v03-to-v1.sh first."
224
- fi
225
- fi
226
-
227
- # Check for CI references
228
- for ci_file in ".github/workflows/"*.yml ".gitlab-ci.yml" "Makefile" ".circleci/config.yml"; do
229
- full_path="$PROJECT_ROOT/$ci_file"
230
- if [ -f "$full_path" ] && grep -q ".dw/.dw/config/dw.config.yml" "$full_path" 2>/dev/null; then
231
- warn "CI file '$ci_file' references config/dw.config.yml — update manually"
232
- fi
233
- done
234
-
235
- # ── Summary ───────────────────────────────────────────────────────────────────
236
- echo ""
237
- echo "══════════════════════════════════════════"
238
- if [ "$DRY_RUN" = true ]; then
239
- echo " DRY RUN complete. No changes made."
240
- echo " Run without --dry-run to apply."
241
- else
242
- echo " Upgrade complete!"
243
- echo " Core version: $TOOLKIT_CORE"
244
- fi
245
- echo "══════════════════════════════════════════"
246
- echo ""