dw-kit 1.0.0 → 1.0.2
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 +1 -3
- package/.claude/rules/code-style.md +37 -37
- package/.claude/rules/commit-standards.md +37 -37
- package/.claude/settings.json +1 -1
- package/.claude/settings.local.json +2 -1
- package/.claude/skills/dw-prompt/SKILL.md +62 -0
- package/.claude/skills/dw-upgrade/SKILL.md +20 -30
- package/.dw/adapters/claude-cli/extensions/README.md +2 -2
- package/.dw/adapters/claude-cli/generated/README.md +3 -3
- package/.dw/adapters/claude-cli/overrides/README.md +4 -2
- package/CLAUDE.md +1 -0
- package/README.md +78 -122
- package/package.json +5 -5
- package/scripts/e2e-local-check.sh +1 -2
- package/src/__fixtures__/claude-cli-bug-snippet.js +15 -0
- package/src/cli.mjs +29 -5
- package/src/commands/claude-vn-fix.mjs +267 -0
- package/src/commands/prompt.mjs +125 -0
- package/src/lib/clipboard.mjs +24 -0
- package/src/lib/prompt-suggest.mjs +84 -0
- package/src/lib/update-checker.mjs +73 -0
- package/src/smoke-test.mjs +47 -11
- package/scripts/migrate-v03-to-v1.sh +0 -243
- package/scripts/upgrade.sh +0 -246
- package/setup.sh +0 -382
- package/src/commands/migrate.mjs +0 -215
package/src/commands/migrate.mjs
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync, readdirSync, mkdirSync, copyFileSync } from 'node:fs';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
3
|
-
import { execSync } from 'node:child_process';
|
|
4
|
-
import { header, ok, warn, err, info, log, dry, ask } from '../lib/ui.mjs';
|
|
5
|
-
import { loadConfig, buildConfig, writeConfig } from '../lib/config.mjs';
|
|
6
|
-
|
|
7
|
-
const DEPTH_MAP = { '1': 'quick', '2': 'standard', '3': 'thorough' };
|
|
8
|
-
const VALID_ROLES = ['dev', 'techlead', 'ba', 'qc', 'pm'];
|
|
9
|
-
|
|
10
|
-
export async function migrateCommand(opts) {
|
|
11
|
-
const projectDir = process.cwd();
|
|
12
|
-
const dryRun = opts.dryRun || false;
|
|
13
|
-
|
|
14
|
-
header('dw-kit v0.3 → v1 Migration');
|
|
15
|
-
if (dryRun) log('Mode: DRY RUN');
|
|
16
|
-
|
|
17
|
-
const oldConfigPath = findOldConfig(projectDir);
|
|
18
|
-
if (!oldConfigPath) {
|
|
19
|
-
ok('No v0.3 config found (dv-workflow.config.yml). Already on v1 or fresh install.');
|
|
20
|
-
log('If migrating manually, run `dw init` instead.');
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
info(`Step 1: Parse old config (${oldConfigPath})`);
|
|
25
|
-
const oldConfig = loadConfig(oldConfigPath);
|
|
26
|
-
if (!oldConfig) {
|
|
27
|
-
err('Failed to parse old config. Manual migration needed.');
|
|
28
|
-
process.exit(1);
|
|
29
|
-
}
|
|
30
|
-
ok('Old config parsed');
|
|
31
|
-
|
|
32
|
-
const extracted = extractOldValues(oldConfig);
|
|
33
|
-
log(` Project: ${extracted.name}`);
|
|
34
|
-
log(` Level: ${extracted.level} → depth: ${extracted.depth}`);
|
|
35
|
-
log(` Roles: ${extracted.roles.join(', ')}`);
|
|
36
|
-
log(` Language: ${extracted.language}`);
|
|
37
|
-
|
|
38
|
-
info('Step 2: Detect customized skills');
|
|
39
|
-
const customized = detectCustomizedSkills(projectDir);
|
|
40
|
-
if (customized.length > 0) {
|
|
41
|
-
for (const skill of customized) {
|
|
42
|
-
if (dryRun) {
|
|
43
|
-
dry(`preserve ${skill} → .dw/adapters/claude-cli/overrides/skills/${skill}/`);
|
|
44
|
-
} else {
|
|
45
|
-
preserveSkillOverride(projectDir, skill);
|
|
46
|
-
ok(`Preserved: ${skill} → overrides/`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
} else {
|
|
50
|
-
ok('No customized skills detected');
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
info('Step 3: Create v1 config');
|
|
54
|
-
const newConfigDir = join(projectDir, '.dw', 'config');
|
|
55
|
-
const newConfigPath = join(newConfigDir, 'dw.config.yml');
|
|
56
|
-
|
|
57
|
-
if (existsSync(newConfigPath)) {
|
|
58
|
-
warn('.dw/config/dw.config.yml already exists — skipping config generation');
|
|
59
|
-
warn('Review and update manually if needed.');
|
|
60
|
-
} else {
|
|
61
|
-
const newConfig = buildConfig({
|
|
62
|
-
projectName: extracted.name,
|
|
63
|
-
language: extracted.language,
|
|
64
|
-
depth: extracted.depth,
|
|
65
|
-
roles: extracted.roles,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
if (extracted.testCommand) newConfig.quality.test_command = extracted.testCommand;
|
|
69
|
-
if (extracted.lintCommand) newConfig.quality.lint_command = extracted.lintCommand;
|
|
70
|
-
newConfig._toolkit.migrated_from = 'v0.3';
|
|
71
|
-
|
|
72
|
-
if (dryRun) {
|
|
73
|
-
dry('Would create .dw/config/dw.config.yml');
|
|
74
|
-
} else {
|
|
75
|
-
mkdirSync(newConfigDir, { recursive: true });
|
|
76
|
-
writeConfig(newConfigPath, newConfig);
|
|
77
|
-
ok(`.dw/config/dw.config.yml created (depth: ${extracted.depth})`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
info('Step 4: Backup old config');
|
|
82
|
-
if (dryRun) {
|
|
83
|
-
dry(`Would backup ${oldConfigPath} → ${oldConfigPath}.bak`);
|
|
84
|
-
} else {
|
|
85
|
-
const bakPath = `${oldConfigPath}.bak`;
|
|
86
|
-
if (!existsSync(bakPath)) {
|
|
87
|
-
copyFileSync(oldConfigPath, bakPath);
|
|
88
|
-
ok(`Backed up: ${oldConfigPath} → ${bakPath}`);
|
|
89
|
-
} else {
|
|
90
|
-
warn('Backup already exists — skipping');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
info('Step 5: Check CI/CD references');
|
|
95
|
-
const ciFiles = checkCIReferences(projectDir);
|
|
96
|
-
if (ciFiles.length > 0) {
|
|
97
|
-
for (const file of ciFiles) {
|
|
98
|
-
warn(`Found reference in: ${file} — update to .dw/config/dw.config.yml`);
|
|
99
|
-
}
|
|
100
|
-
} else {
|
|
101
|
-
ok('No CI/CD references found');
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
console.log();
|
|
105
|
-
header(dryRun ? 'DRY RUN complete — no changes made' : 'Migration complete!');
|
|
106
|
-
|
|
107
|
-
if (!dryRun) {
|
|
108
|
-
console.log();
|
|
109
|
-
log('Next steps:');
|
|
110
|
-
log(' 1. Review .dw/config/dw.config.yml');
|
|
111
|
-
log(' 2. Run: dw init --adapter claude-cli (to regenerate .claude/)');
|
|
112
|
-
log(' 3. Check .dw/adapters/claude-cli/overrides/ for preserved customizations');
|
|
113
|
-
if (ciFiles.length > 0) {
|
|
114
|
-
log(' 4. Update CI/CD files (see warnings above)');
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
log('Run without --dry-run to apply migration.');
|
|
118
|
-
}
|
|
119
|
-
console.log();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function findOldConfig(projectDir) {
|
|
123
|
-
const candidates = [
|
|
124
|
-
join(projectDir, 'dv-workflow.config.yml'),
|
|
125
|
-
join(projectDir, 'dw.config.yml'),
|
|
126
|
-
];
|
|
127
|
-
return candidates.find(p => existsSync(p)) || null;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function extractOldValues(config) {
|
|
131
|
-
const name = config.project?.name || config.name || 'my-project';
|
|
132
|
-
const language = config.project?.language || config.language || 'vi';
|
|
133
|
-
const level = String(config.level || config.workflow?.level || '2');
|
|
134
|
-
const depth = DEPTH_MAP[level] || 'standard';
|
|
135
|
-
|
|
136
|
-
let roles = config.team?.roles || [];
|
|
137
|
-
if (!Array.isArray(roles)) roles = ['dev'];
|
|
138
|
-
roles = roles.filter(r => VALID_ROLES.includes(r));
|
|
139
|
-
if (!roles.includes('dev')) roles.unshift('dev');
|
|
140
|
-
|
|
141
|
-
const testCommand = config.quality?.test_command || config.test_command || '';
|
|
142
|
-
const lintCommand = config.quality?.lint_command || config.lint_command || '';
|
|
143
|
-
|
|
144
|
-
return { name, language, level, depth, roles, testCommand, lintCommand };
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function detectCustomizedSkills(projectDir) {
|
|
148
|
-
const skillsDir = join(projectDir, '.claude', 'skills');
|
|
149
|
-
if (!existsSync(skillsDir)) return [];
|
|
150
|
-
|
|
151
|
-
const customized = [];
|
|
152
|
-
try {
|
|
153
|
-
const isGitRepo = existsSync(join(projectDir, '.git'));
|
|
154
|
-
if (!isGitRepo) return [];
|
|
155
|
-
|
|
156
|
-
const skills = readdirSync(skillsDir, { withFileTypes: true })
|
|
157
|
-
.filter(d => d.isDirectory())
|
|
158
|
-
.map(d => d.name);
|
|
159
|
-
|
|
160
|
-
for (const skill of skills) {
|
|
161
|
-
const skillFile = join('.claude', 'skills', skill, 'SKILL.md');
|
|
162
|
-
try {
|
|
163
|
-
execSync(`git diff --quiet HEAD -- "${skillFile}"`, {
|
|
164
|
-
cwd: projectDir,
|
|
165
|
-
stdio: 'pipe',
|
|
166
|
-
});
|
|
167
|
-
} catch {
|
|
168
|
-
customized.push(skill);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
} catch { /* not a git repo or other issue */ }
|
|
172
|
-
|
|
173
|
-
return customized;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function preserveSkillOverride(projectDir, skillName) {
|
|
177
|
-
const srcFile = join(projectDir, '.claude', 'skills', skillName, 'SKILL.md');
|
|
178
|
-
const dstDir = join(projectDir, '.dw', 'adapters', 'claude-cli', 'overrides', 'skills', skillName);
|
|
179
|
-
const dstFile = join(dstDir, 'SKILL.md');
|
|
180
|
-
|
|
181
|
-
if (!existsSync(srcFile)) return;
|
|
182
|
-
mkdirSync(dstDir, { recursive: true });
|
|
183
|
-
copyFileSync(srcFile, dstFile);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function checkCIReferences(projectDir) {
|
|
187
|
-
const found = [];
|
|
188
|
-
|
|
189
|
-
const directChecks = ['.gitlab-ci.yml', 'Makefile', '.circleci/config.yml'];
|
|
190
|
-
for (const file of directChecks) {
|
|
191
|
-
const fullPath = join(projectDir, file);
|
|
192
|
-
if (existsSync(fullPath)) {
|
|
193
|
-
const content = readFileSync(fullPath, 'utf-8');
|
|
194
|
-
if (/dv-workflow\.config\.yml|dv-workflow-kit/.test(content)) {
|
|
195
|
-
found.push(file);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const workflowsDir = join(projectDir, '.github', 'workflows');
|
|
201
|
-
if (existsSync(workflowsDir)) {
|
|
202
|
-
try {
|
|
203
|
-
const files = readdirSync(workflowsDir).filter(f => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
204
|
-
for (const file of files) {
|
|
205
|
-
const fullPath = join(workflowsDir, file);
|
|
206
|
-
const content = readFileSync(fullPath, 'utf-8');
|
|
207
|
-
if (/dv-workflow\.config\.yml|dv-workflow-kit/.test(content)) {
|
|
208
|
-
found.push(join('.github', 'workflows', file));
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
} catch { /* dir read failed */ }
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return found;
|
|
215
|
-
}
|