dw-kit 1.1.0 → 1.2.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.
- package/.claude/hooks/post-write.sh +9 -11
- package/.claude/hooks/privacy-block.sh +94 -0
- package/.claude/hooks/scout-block.sh +82 -0
- package/.claude/hooks/session-init.sh +74 -0
- package/.claude/hooks/stop-check.sh +36 -0
- package/.claude/rules/code-style.md +37 -37
- package/.claude/rules/commit-standards.md +37 -37
- package/.claude/rules/dw-core.md +100 -0
- package/.claude/rules/dw-skills.md +53 -0
- package/.claude/settings.json +30 -2
- package/.claude/skills/dw-kit-report/SKILL.md +152 -0
- package/.claude/skills/dw-research/SKILL.md +17 -1
- package/.claude/templates/agent-report.md +35 -0
- package/.dw/core/AGENTS.md +53 -0
- package/CLAUDE.md +27 -99
- package/README.md +119 -119
- package/package.json +31 -4
- package/src/cli.mjs +92 -92
- package/src/commands/init.mjs +17 -17
- package/src/lib/config.mjs +31 -2
- package/scripts/e2e-local-check.sh +0 -75
- package/src/__fixtures__/claude-cli-bug-snippet.js +0 -15
- package/src/smoke-test.mjs +0 -351
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dw-kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "AI development workflow toolkit — structured, quality-assured, team-ready. From requirements to dashboard.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,15 +8,42 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin/",
|
|
11
|
-
"src/",
|
|
11
|
+
"src/cli.mjs",
|
|
12
|
+
"src/commands/",
|
|
13
|
+
"src/lib/",
|
|
12
14
|
".dw/core/",
|
|
13
15
|
".dw/config/",
|
|
14
16
|
".dw/adapters/",
|
|
15
|
-
"scripts/",
|
|
16
17
|
".claude/agents/",
|
|
17
18
|
".claude/hooks/",
|
|
18
19
|
".claude/rules/",
|
|
19
|
-
".claude/skills/",
|
|
20
|
+
".claude/skills/dw-arch-review/",
|
|
21
|
+
".claude/skills/dw-archive/",
|
|
22
|
+
".claude/skills/dw-commit/",
|
|
23
|
+
".claude/skills/dw-config-init/",
|
|
24
|
+
".claude/skills/dw-config-validate/",
|
|
25
|
+
".claude/skills/dw-dashboard/",
|
|
26
|
+
".claude/skills/dw-debug/",
|
|
27
|
+
".claude/skills/dw-docs-update/",
|
|
28
|
+
".claude/skills/dw-estimate/",
|
|
29
|
+
".claude/skills/dw-execute/",
|
|
30
|
+
".claude/skills/dw-flow/",
|
|
31
|
+
".claude/skills/dw-handoff/",
|
|
32
|
+
".claude/skills/dw-kit-report/",
|
|
33
|
+
".claude/skills/dw-log-work/",
|
|
34
|
+
".claude/skills/dw-onboard/",
|
|
35
|
+
".claude/skills/dw-plan/",
|
|
36
|
+
".claude/skills/dw-prompt/",
|
|
37
|
+
".claude/skills/dw-requirements/",
|
|
38
|
+
".claude/skills/dw-research/",
|
|
39
|
+
".claude/skills/dw-retroactive/",
|
|
40
|
+
".claude/skills/dw-review/",
|
|
41
|
+
".claude/skills/dw-rollback/",
|
|
42
|
+
".claude/skills/dw-sprint-review/",
|
|
43
|
+
".claude/skills/dw-task-init/",
|
|
44
|
+
".claude/skills/dw-test-plan/",
|
|
45
|
+
".claude/skills/dw-thinking/",
|
|
46
|
+
".claude/skills/dw-upgrade/",
|
|
20
47
|
".claude/templates/",
|
|
21
48
|
".claude/settings.json",
|
|
22
49
|
"CLAUDE.md"
|
package/src/cli.mjs
CHANGED
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { createRequire } from 'node:module';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { dirname, join } from 'node:path';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { getUpdateNotice, scheduleUpdateCheck } from './lib/update-checker.mjs';
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = dirname(__filename);
|
|
10
|
-
const require = createRequire(import.meta.url);
|
|
11
|
-
const pkg = require(join(__dirname, '..', 'package.json'));
|
|
12
|
-
|
|
13
|
-
export function run(argv) {
|
|
14
|
-
// Show cached update notice (non-blocking), then schedule fresh check in background
|
|
15
|
-
const latestVersion = getUpdateNotice(pkg.version);
|
|
16
|
-
scheduleUpdateCheck(pkg.version);
|
|
17
|
-
|
|
18
|
-
const program = new Command();
|
|
19
|
-
|
|
20
|
-
program
|
|
21
|
-
.name('dw')
|
|
22
|
-
.description('dw-kit — AI development workflow toolkit')
|
|
23
|
-
.version(pkg.version, '-v, --version');
|
|
24
|
-
|
|
25
|
-
program
|
|
26
|
-
.command('init')
|
|
27
|
-
.description('Setup dw-kit in current project (interactive wizard)')
|
|
28
|
-
.option('-p, --preset <name>', 'Use preset: solo-quick | small-team | enterprise')
|
|
29
|
-
.option('-a, --adapter <platform>', 'Target platform: claude-cli | cursor | generic', 'claude-cli')
|
|
30
|
-
.option('-s, --silent', 'Non-interactive mode (reads DW_NAME, DW_DEPTH, DW_ROLES, DW_LANG env vars)')
|
|
31
|
-
.action(async (opts) => {
|
|
32
|
-
const { initCommand } = await import('./commands/init.mjs');
|
|
33
|
-
await initCommand(opts);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
program
|
|
37
|
-
.command('upgrade')
|
|
38
|
-
.description('Update dw-kit files in current project')
|
|
39
|
-
.option('-n, --dry-run', 'Preview changes without applying')
|
|
40
|
-
.option('-c, --check', 'Only check if update is available')
|
|
41
|
-
.option('-l, --layer <name>', 'Update specific layer: core | platform | capability | all', 'all')
|
|
42
|
-
.action(async (opts) => {
|
|
43
|
-
const { upgradeCommand } = await import('./commands/upgrade.mjs');
|
|
44
|
-
await upgradeCommand(opts);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
program
|
|
48
|
-
.command('validate')
|
|
49
|
-
.description('Validate .dw/config/dw.config.yml against schema')
|
|
50
|
-
.option('-f, --file <path>', 'Config file path', '.dw/config/dw.config.yml')
|
|
51
|
-
.action(async (opts) => {
|
|
52
|
-
const { validateCommand } = await import('./commands/validate.mjs');
|
|
53
|
-
await validateCommand(opts);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
program
|
|
57
|
-
.command('doctor')
|
|
58
|
-
.description('Check dw-kit installation health')
|
|
59
|
-
.action(async () => {
|
|
60
|
-
const { doctorCommand } = await import('./commands/doctor.mjs');
|
|
61
|
-
await doctorCommand();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
program
|
|
65
|
-
.command('prompt')
|
|
66
|
-
.description('Build a well-structured task prompt with autocomplete + guided wizard')
|
|
67
|
-
.option('-t, --text <text>', 'Non-interactive: provide description directly')
|
|
68
|
-
.action(async (opts) => {
|
|
69
|
-
const { promptCommand } = await import('./commands/prompt.mjs');
|
|
70
|
-
await promptCommand(opts);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
program
|
|
74
|
-
.command('claude-vn-fix')
|
|
75
|
-
.description('Patch Claude CLI to fix Vietnamese IME (local, with backup/restore)')
|
|
76
|
-
.option('--path <file>', 'Path to @anthropic-ai/claude-code/cli.js (optional; auto-detect if omitted)')
|
|
77
|
-
.option('--restore', 'Restore from latest backup')
|
|
78
|
-
.option('--dry-run', 'Show what would change without writing')
|
|
79
|
-
.action(async (opts) => {
|
|
80
|
-
const { claudeVnFixCommand } = await import('./commands/claude-vn-fix.mjs');
|
|
81
|
-
await claudeVnFixCommand(opts);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
program.parse(argv);
|
|
85
|
-
|
|
86
|
-
if (latestVersion) {
|
|
87
|
-
console.log();
|
|
88
|
-
console.log(chalk.yellow(` ↑ Update available`) + ` v${pkg.version} → ` + chalk.green.bold(`v${latestVersion}`));
|
|
89
|
-
console.log(` Run ` + chalk.cyan(`npm install -g dw-kit`) + ` to update`);
|
|
90
|
-
console.log();
|
|
91
|
-
}
|
|
92
|
-
}
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { getUpdateNotice, scheduleUpdateCheck } from './lib/update-checker.mjs';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
const pkg = require(join(__dirname, '..', 'package.json'));
|
|
12
|
+
|
|
13
|
+
export function run(argv) {
|
|
14
|
+
// Show cached update notice (non-blocking), then schedule fresh check in background
|
|
15
|
+
const latestVersion = getUpdateNotice(pkg.version);
|
|
16
|
+
scheduleUpdateCheck(pkg.version);
|
|
17
|
+
|
|
18
|
+
const program = new Command();
|
|
19
|
+
|
|
20
|
+
program
|
|
21
|
+
.name('dw')
|
|
22
|
+
.description('dw-kit — AI development workflow toolkit')
|
|
23
|
+
.version(pkg.version, '-v, --version');
|
|
24
|
+
|
|
25
|
+
program
|
|
26
|
+
.command('init')
|
|
27
|
+
.description('Setup dw-kit in current project (interactive wizard)')
|
|
28
|
+
.option('-p, --preset <name>', 'Use preset: solo-quick | small-team | enterprise')
|
|
29
|
+
.option('-a, --adapter <platform>', 'Target platform: claude-cli | cursor | generic', 'claude-cli')
|
|
30
|
+
.option('-s, --silent', 'Non-interactive mode (reads DW_NAME, DW_DEPTH, DW_ROLES, DW_LANG env vars)')
|
|
31
|
+
.action(async (opts) => {
|
|
32
|
+
const { initCommand } = await import('./commands/init.mjs');
|
|
33
|
+
await initCommand(opts);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
program
|
|
37
|
+
.command('upgrade')
|
|
38
|
+
.description('Update dw-kit files in current project')
|
|
39
|
+
.option('-n, --dry-run', 'Preview changes without applying')
|
|
40
|
+
.option('-c, --check', 'Only check if update is available')
|
|
41
|
+
.option('-l, --layer <name>', 'Update specific layer: core | platform | capability | all', 'all')
|
|
42
|
+
.action(async (opts) => {
|
|
43
|
+
const { upgradeCommand } = await import('./commands/upgrade.mjs');
|
|
44
|
+
await upgradeCommand(opts);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
program
|
|
48
|
+
.command('validate')
|
|
49
|
+
.description('Validate .dw/config/dw.config.yml against schema')
|
|
50
|
+
.option('-f, --file <path>', 'Config file path', '.dw/config/dw.config.yml')
|
|
51
|
+
.action(async (opts) => {
|
|
52
|
+
const { validateCommand } = await import('./commands/validate.mjs');
|
|
53
|
+
await validateCommand(opts);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
program
|
|
57
|
+
.command('doctor')
|
|
58
|
+
.description('Check dw-kit installation health')
|
|
59
|
+
.action(async () => {
|
|
60
|
+
const { doctorCommand } = await import('./commands/doctor.mjs');
|
|
61
|
+
await doctorCommand();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
program
|
|
65
|
+
.command('prompt')
|
|
66
|
+
.description('Build a well-structured task prompt with autocomplete + guided wizard')
|
|
67
|
+
.option('-t, --text <text>', 'Non-interactive: provide description directly')
|
|
68
|
+
.action(async (opts) => {
|
|
69
|
+
const { promptCommand } = await import('./commands/prompt.mjs');
|
|
70
|
+
await promptCommand(opts);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
program
|
|
74
|
+
.command('claude-vn-fix')
|
|
75
|
+
.description('Patch Claude CLI to fix Vietnamese IME (local, with backup/restore)')
|
|
76
|
+
.option('--path <file>', 'Path to @anthropic-ai/claude-code/cli.js (optional; auto-detect if omitted)')
|
|
77
|
+
.option('--restore', 'Restore from latest backup')
|
|
78
|
+
.option('--dry-run', 'Show what would change without writing')
|
|
79
|
+
.action(async (opts) => {
|
|
80
|
+
const { claudeVnFixCommand } = await import('./commands/claude-vn-fix.mjs');
|
|
81
|
+
await claudeVnFixCommand(opts);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
program.parse(argv);
|
|
85
|
+
|
|
86
|
+
if (latestVersion) {
|
|
87
|
+
console.log();
|
|
88
|
+
console.log(chalk.yellow(` ↑ Update available`) + ` v${pkg.version} → ` + chalk.green.bold(`v${latestVersion}`));
|
|
89
|
+
console.log(` Run ` + chalk.cyan(`npm install -g dw-kit`) + ` to update`);
|
|
90
|
+
console.log();
|
|
91
|
+
}
|
|
92
|
+
}
|
package/src/commands/init.mjs
CHANGED
|
@@ -135,7 +135,7 @@ async function setupProject(projectDir, { projectName, depth, roles, language, a
|
|
|
135
135
|
|
|
136
136
|
if (adapter === 'claude-cli') {
|
|
137
137
|
copyClaudeFiles(projectDir);
|
|
138
|
-
|
|
138
|
+
createMinimalCLAUDEmd(projectDir, projectName);
|
|
139
139
|
} else if (adapter === 'cursor') {
|
|
140
140
|
copyCursorFiles(projectDir);
|
|
141
141
|
copyGenericAdapter(projectDir);
|
|
@@ -191,34 +191,34 @@ function copyClaudeFiles(projectDir) {
|
|
|
191
191
|
if (skipCount > 0) log(` ${skipCount} existing files preserved`);
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
function
|
|
195
|
-
const src = join(TOOLKIT_ROOT, 'CLAUDE.md');
|
|
194
|
+
function createMinimalCLAUDEmd(projectDir, projectName) {
|
|
196
195
|
const dst = join(projectDir, 'CLAUDE.md');
|
|
197
196
|
|
|
198
197
|
if (existsSync(dst)) {
|
|
199
|
-
|
|
198
|
+
// User already has their own CLAUDE.md — leave it completely alone
|
|
200
199
|
return;
|
|
201
200
|
}
|
|
202
201
|
|
|
203
|
-
|
|
202
|
+
const content = `# ${projectName}
|
|
203
|
+
|
|
204
|
+
> Add your project description here.
|
|
204
205
|
|
|
205
|
-
const techStackSection = `
|
|
206
206
|
---
|
|
207
207
|
|
|
208
208
|
## Tech Stack
|
|
209
209
|
|
|
210
210
|
<!-- Update with your project's actual stack -->
|
|
211
|
-
- Framework:
|
|
212
|
-
- Database:
|
|
213
|
-
- Testing:
|
|
211
|
+
- Framework:
|
|
212
|
+
- Database:
|
|
213
|
+
- Testing:
|
|
214
214
|
|
|
215
215
|
## Project-Specific Rules
|
|
216
216
|
|
|
217
|
-
<!-- Add project-specific rules -->
|
|
218
|
-
-
|
|
217
|
+
<!-- Add project-specific rules here -->
|
|
218
|
+
<!-- dw workflow rules are auto-loaded from .claude/rules/ -->
|
|
219
219
|
`;
|
|
220
|
-
|
|
221
|
-
ok('CLAUDE.md (
|
|
220
|
+
writeFileSync(dst, content, 'utf-8');
|
|
221
|
+
ok('CLAUDE.md (minimal project template — dw rules are in .claude/rules/)');
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
function copyCursorFiles(projectDir) {
|
|
@@ -276,7 +276,7 @@ function createRuntimeDirs(projectDir) {
|
|
|
276
276
|
|
|
277
277
|
function updateGitignore(projectDir) {
|
|
278
278
|
const gitignorePath = join(projectDir, '.gitignore');
|
|
279
|
-
const entriesToAdd = ['CLAUDE.local.md', '.claude/settings.local.json'];
|
|
279
|
+
const entriesToAdd = ['CLAUDE.local.md', '.claude/settings.local.json', '.dw/config/dw.config.local.yml'];
|
|
280
280
|
|
|
281
281
|
if (existsSync(gitignorePath)) {
|
|
282
282
|
const content = readFileSync(gitignorePath, 'utf-8');
|
|
@@ -304,8 +304,8 @@ function printSummary({ projectName, depth, roles, language, adapter }) {
|
|
|
304
304
|
console.log(` Files created:`);
|
|
305
305
|
console.log(` .dw/ — core/, config/, adapters/, tasks, docs`);
|
|
306
306
|
if (adapter === 'claude-cli') {
|
|
307
|
-
console.log(` .claude/ — skills, agents, hooks, rules
|
|
308
|
-
console.log(` CLAUDE.md`);
|
|
307
|
+
console.log(` .claude/ — skills, agents, hooks, rules/`);
|
|
308
|
+
console.log(` CLAUDE.md — minimal project template (dw rules in .claude/rules/)`);
|
|
309
309
|
} else if (adapter === 'cursor') {
|
|
310
310
|
console.log(` .cursor/rules/ — workflow rules for Cursor`);
|
|
311
311
|
console.log(` AGENT.md — methodology reference`);
|
|
@@ -317,7 +317,7 @@ function printSummary({ projectName, depth, roles, language, adapter }) {
|
|
|
317
317
|
console.log(` Next steps:`);
|
|
318
318
|
console.log(` Run: claude (to open Claude Code in this directory in terminal)`);
|
|
319
319
|
console.log(` Run: /dw-flow [task-name]`);
|
|
320
|
-
console.log(` Suggested: Update Tech Stack in CLAUDE.md
|
|
320
|
+
console.log(` Suggested: Update Tech Stack + rules in CLAUDE.md`);
|
|
321
321
|
} else if (adapter === 'cursor') {
|
|
322
322
|
console.log(` Next steps:`);
|
|
323
323
|
console.log(` 1. Open Cursor in this directory`);
|
package/src/lib/config.mjs
CHANGED
|
@@ -7,6 +7,35 @@ export function loadConfig(configPath) {
|
|
|
7
7
|
return yaml.load(content);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Load config với local override (v1.2+).
|
|
12
|
+
* dw.config.yml — shared, committed
|
|
13
|
+
* dw.config.local.yml — machine-specific, gitignored
|
|
14
|
+
* Local values win over base values (shallow merge per top-level key).
|
|
15
|
+
*/
|
|
16
|
+
export function loadConfigWithLocal(configDir) {
|
|
17
|
+
const basePath = `${configDir}/dw.config.yml`;
|
|
18
|
+
const localPath = `${configDir}/dw.config.local.yml`;
|
|
19
|
+
|
|
20
|
+
const base = loadConfig(basePath);
|
|
21
|
+
if (!base) return null;
|
|
22
|
+
|
|
23
|
+
if (!existsSync(localPath)) return base;
|
|
24
|
+
|
|
25
|
+
const local = loadConfig(localPath);
|
|
26
|
+
if (!local) return base;
|
|
27
|
+
|
|
28
|
+
const merged = { ...base };
|
|
29
|
+
for (const key of Object.keys(local)) {
|
|
30
|
+
if (typeof local[key] === 'object' && !Array.isArray(local[key]) && local[key] !== null) {
|
|
31
|
+
merged[key] = { ...(merged[key] || {}), ...local[key] };
|
|
32
|
+
} else {
|
|
33
|
+
merged[key] = local[key];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return merged;
|
|
37
|
+
}
|
|
38
|
+
|
|
10
39
|
export function writeConfig(configPath, data) {
|
|
11
40
|
const content = yaml.dump(data, {
|
|
12
41
|
indent: 2,
|
|
@@ -57,9 +86,9 @@ export function buildConfig({ projectName, language, depth, roles }) {
|
|
|
57
86
|
mcp: [],
|
|
58
87
|
},
|
|
59
88
|
_toolkit: {
|
|
60
|
-
core_version: '1.
|
|
89
|
+
core_version: '1.2',
|
|
61
90
|
platform_version: '1.0',
|
|
62
|
-
capability_version: '1.
|
|
91
|
+
capability_version: '1.2',
|
|
63
92
|
installed: today,
|
|
64
93
|
last_upgrade: today,
|
|
65
94
|
},
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# scripts/e2e-local-check.sh
|
|
3
|
-
# End-to-end local publish check (pack -> install -> run CLI)
|
|
4
|
-
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
-
cd "$ROOT_DIR"
|
|
9
|
-
|
|
10
|
-
log() { echo " $*"; }
|
|
11
|
-
info() { echo ""; echo "▶ $*"; }
|
|
12
|
-
ok() { echo " ✓ $*"; }
|
|
13
|
-
warn() { echo " ⚠ $*"; }
|
|
14
|
-
|
|
15
|
-
cleanup() {
|
|
16
|
-
if [ -n "${TMP_DIR:-}" ] && [ -d "${TMP_DIR:-}" ]; then
|
|
17
|
-
rm -rf "$TMP_DIR"
|
|
18
|
-
fi
|
|
19
|
-
if [ -n "${PACK_FILE:-}" ] && [ -f "${PACK_FILE:-}" ]; then
|
|
20
|
-
rm -f "$PACK_FILE"
|
|
21
|
-
fi
|
|
22
|
-
}
|
|
23
|
-
trap cleanup EXIT
|
|
24
|
-
|
|
25
|
-
info "Step 1: Run smoke tests"
|
|
26
|
-
npm test
|
|
27
|
-
ok "Smoke tests passed"
|
|
28
|
-
|
|
29
|
-
info "Step 2: Build npm package tarball"
|
|
30
|
-
PACK_OUTPUT="$(npm pack)"
|
|
31
|
-
PACK_FILE="$(echo "$PACK_OUTPUT" | tail -n 1 | tr -d '\r')"
|
|
32
|
-
if [ ! -f "$PACK_FILE" ]; then
|
|
33
|
-
echo " ✗ Failed to produce package tarball"
|
|
34
|
-
exit 1
|
|
35
|
-
fi
|
|
36
|
-
ok "Tarball: $PACK_FILE"
|
|
37
|
-
|
|
38
|
-
info "Step 3: Create isolated test project"
|
|
39
|
-
TMP_DIR="$(mktemp -d 2>/dev/null || true)"
|
|
40
|
-
if [ -z "${TMP_DIR}" ]; then
|
|
41
|
-
TMP_DIR=".tmp-e2e-local-check"
|
|
42
|
-
rm -rf "$TMP_DIR"
|
|
43
|
-
mkdir -p "$TMP_DIR"
|
|
44
|
-
fi
|
|
45
|
-
TEST_DIR="$TMP_DIR/e2e-project"
|
|
46
|
-
mkdir -p "$TEST_DIR"
|
|
47
|
-
cd "$TEST_DIR"
|
|
48
|
-
npm init -y >/dev/null 2>&1
|
|
49
|
-
git init >/dev/null 2>&1 || true
|
|
50
|
-
ok "Created isolated project at $TEST_DIR"
|
|
51
|
-
|
|
52
|
-
info "Step 4: Install from local tarball"
|
|
53
|
-
npm install "$ROOT_DIR/$PACK_FILE" >/dev/null
|
|
54
|
-
ok "Installed package from tarball"
|
|
55
|
-
|
|
56
|
-
info "Step 5: Run CLI checks in isolated project"
|
|
57
|
-
VERSION_OUT="$(npx dw --version | tr -d '\r')"
|
|
58
|
-
log "dw --version: $VERSION_OUT"
|
|
59
|
-
npx dw init --preset small-team
|
|
60
|
-
npx dw validate
|
|
61
|
-
npx dw doctor
|
|
62
|
-
npx dw upgrade --check
|
|
63
|
-
|
|
64
|
-
info "Step 6: Verify task-depth override guidance artifacts"
|
|
65
|
-
grep -q "Task-Level Depth Override" ".dw/core/WORKFLOW.md"
|
|
66
|
-
grep -q "Depth Source: default (from config) | override (task-specific)" ".dw/core/templates/vi/task-context.md"
|
|
67
|
-
ok "Depth override guidance exists in generated artifacts"
|
|
68
|
-
|
|
69
|
-
ok "CLI flow passed in isolated project"
|
|
70
|
-
|
|
71
|
-
echo ""
|
|
72
|
-
echo "══════════════════════════════════════════"
|
|
73
|
-
echo " E2E local check passed"
|
|
74
|
-
echo "══════════════════════════════════════════"
|
|
75
|
-
echo ""
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// Minimal fixture that contains the known Vietnamese IME bug pattern.
|
|
2
|
-
// This is NOT the real Claude CLI; only used for testing the patcher logic.
|
|
3
|
-
//
|
|
4
|
-
// IMPORTANT: The comment below must contain both '@anthropic-ai' and 'claude-code'
|
|
5
|
-
// to pass the bundle signature guard in patchCliJs(). Do not remove it.
|
|
6
|
-
// @anthropic-ai/claude-code bundle stub
|
|
7
|
-
|
|
8
|
-
function demo(INPUT) {
|
|
9
|
-
if(INPUT.includes("\x7f")){
|
|
10
|
-
let COUNT=(INPUT.match(/\x7f/g)||[]).length,STATE=CURSTATE;
|
|
11
|
-
UPDATETEXT(STATE.text);UPDATEOFFSET(STATE.offset)
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|