safeword 0.2.4 → 0.2.5
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/dist/check-3NGQ4NR5.js +129 -0
- package/dist/check-3NGQ4NR5.js.map +1 -0
- package/dist/chunk-2XWIUEQK.js +190 -0
- package/dist/chunk-2XWIUEQK.js.map +1 -0
- package/dist/chunk-GZRQL3SX.js +146 -0
- package/dist/chunk-GZRQL3SX.js.map +1 -0
- package/dist/chunk-ORQHKDT2.js +10 -0
- package/dist/chunk-ORQHKDT2.js.map +1 -0
- package/dist/chunk-W66Z3C5H.js +21 -0
- package/dist/chunk-W66Z3C5H.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +34 -0
- package/dist/cli.js.map +1 -0
- package/dist/diff-Y6QTAW4O.js +166 -0
- package/dist/diff-Y6QTAW4O.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/reset-3ACTIYYE.js +143 -0
- package/dist/reset-3ACTIYYE.js.map +1 -0
- package/dist/setup-RR4M334C.js +266 -0
- package/dist/setup-RR4M334C.js.map +1 -0
- package/dist/upgrade-6AR3DHUV.js +134 -0
- package/dist/upgrade-6AR3DHUV.js.map +1 -0
- package/package.json +44 -19
- package/{.safeword → templates}/hooks/agents-md-check.sh +0 -0
- package/{.safeword → templates}/hooks/post-tool.sh +0 -0
- package/{.safeword → templates}/hooks/pre-commit.sh +0 -0
- package/.claude/commands/arch-review.md +0 -32
- package/.claude/commands/lint.md +0 -6
- package/.claude/commands/quality-review.md +0 -13
- package/.claude/commands/setup-linting.md +0 -6
- package/.claude/hooks/auto-lint.sh +0 -6
- package/.claude/hooks/auto-quality-review.sh +0 -170
- package/.claude/hooks/check-linting-sync.sh +0 -17
- package/.claude/hooks/inject-timestamp.sh +0 -6
- package/.claude/hooks/question-protocol.sh +0 -12
- package/.claude/hooks/run-linters.sh +0 -8
- package/.claude/hooks/run-quality-review.sh +0 -76
- package/.claude/hooks/version-check.sh +0 -10
- package/.claude/mcp/README.md +0 -96
- package/.claude/mcp/arcade.sample.json +0 -9
- package/.claude/mcp/context7.sample.json +0 -7
- package/.claude/mcp/playwright.sample.json +0 -7
- package/.claude/settings.json +0 -62
- package/.claude/skills/quality-reviewer/SKILL.md +0 -190
- package/.claude/skills/safeword-quality-reviewer/SKILL.md +0 -13
- package/.env.arcade.example +0 -4
- package/.env.example +0 -11
- package/.gitmodules +0 -4
- package/.safeword/SAFEWORD.md +0 -33
- package/.safeword/eslint/eslint-base.mjs +0 -101
- package/.safeword/guides/architecture-guide.md +0 -404
- package/.safeword/guides/code-philosophy.md +0 -174
- package/.safeword/guides/context-files-guide.md +0 -405
- package/.safeword/guides/data-architecture-guide.md +0 -183
- package/.safeword/guides/design-doc-guide.md +0 -165
- package/.safeword/guides/learning-extraction.md +0 -515
- package/.safeword/guides/llm-instruction-design.md +0 -239
- package/.safeword/guides/llm-prompting.md +0 -95
- package/.safeword/guides/tdd-best-practices.md +0 -570
- package/.safeword/guides/test-definitions-guide.md +0 -243
- package/.safeword/guides/testing-methodology.md +0 -573
- package/.safeword/guides/user-story-guide.md +0 -237
- package/.safeword/guides/zombie-process-cleanup.md +0 -214
- package/.safeword/planning/002-user-story-quality-evaluation.md +0 -1840
- package/.safeword/planning/003-langsmith-eval-setup-prompt.md +0 -363
- package/.safeword/planning/004-llm-eval-test-cases.md +0 -3226
- package/.safeword/planning/005-architecture-enforcement-system.md +0 -169
- package/.safeword/planning/006-reactive-fix-prevention-research.md +0 -135
- package/.safeword/planning/011-cli-ux-vision.md +0 -330
- package/.safeword/planning/012-project-structure-cleanup.md +0 -154
- package/.safeword/planning/README.md +0 -39
- package/.safeword/planning/automation-plan-v2.md +0 -1225
- package/.safeword/planning/automation-plan-v3.md +0 -1291
- package/.safeword/planning/automation-plan.md +0 -3058
- package/.safeword/planning/design/005-cli-implementation.md +0 -343
- package/.safeword/planning/design/013-cli-self-contained-templates.md +0 -596
- package/.safeword/planning/design/013a-eslint-plugin-suite.md +0 -256
- package/.safeword/planning/design/013b-implementation-snippets.md +0 -385
- package/.safeword/planning/design/013c-config-isolation-strategy.md +0 -242
- package/.safeword/planning/design/code-philosophy-improvements.md +0 -60
- package/.safeword/planning/mcp-analysis.md +0 -545
- package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +0 -451
- package/.safeword/planning/settings-improvements.md +0 -970
- package/.safeword/planning/test-definitions/005-cli-implementation.md +0 -1301
- package/.safeword/planning/test-definitions/cli-self-contained-templates.md +0 -205
- package/.safeword/planning/user-stories/001-guides-review-user-stories.md +0 -1381
- package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +0 -132
- package/.safeword/planning/user-stories/004-technical-constraints.md +0 -86
- package/.safeword/planning/user-stories/005-cli-implementation.md +0 -311
- package/.safeword/planning/user-stories/cli-self-contained-templates.md +0 -172
- package/.safeword/planning/versioned-distribution.md +0 -740
- package/.safeword/prompts/arch-review.md +0 -43
- package/.safeword/prompts/quality-review.md +0 -11
- package/.safeword/scripts/arch-review.sh +0 -235
- package/.safeword/scripts/check-linting-sync.sh +0 -58
- package/.safeword/scripts/setup-linting.sh +0 -559
- package/.safeword/templates/architecture-template.md +0 -136
- package/.safeword/templates/ci/architecture-check.yml +0 -79
- package/.safeword/templates/design-doc-template.md +0 -127
- package/.safeword/templates/test-definitions-feature.md +0 -100
- package/.safeword/templates/ticket-template.md +0 -74
- package/.safeword/templates/user-stories-template.md +0 -82
- package/.safeword/tickets/001-guides-review-user-stories.md +0 -83
- package/.safeword/tickets/002-architecture-enforcement.md +0 -211
- package/.safeword/tickets/003-reactive-fix-prevention.md +0 -57
- package/.safeword/tickets/004-technical-constraints-in-user-stories.md +0 -39
- package/.safeword/tickets/005-cli-implementation.md +0 -248
- package/.safeword/tickets/006-flesh-out-skills.md +0 -43
- package/.safeword/tickets/007-flesh-out-questioning.md +0 -44
- package/.safeword/tickets/008-upgrade-questioning.md +0 -58
- package/.safeword/tickets/009-naming-conventions.md +0 -41
- package/.safeword/tickets/010-safeword-md-cleanup.md +0 -34
- package/.safeword/tickets/011-cursor-setup.md +0 -86
- package/.safeword/tickets/README.md +0 -73
- package/.safeword/version +0 -1
- package/AGENTS.md +0 -59
- package/CLAUDE.md +0 -12
- package/README.md +0 -347
- package/docs/001-cli-implementation-plan.md +0 -856
- package/docs/elite-dx-implementation-plan.md +0 -1034
- package/framework/README.md +0 -131
- package/framework/mcp/README.md +0 -96
- package/framework/mcp/arcade.sample.json +0 -8
- package/framework/mcp/context7.sample.json +0 -6
- package/framework/mcp/playwright.sample.json +0 -6
- package/framework/scripts/arch-review.sh +0 -235
- package/framework/scripts/check-linting-sync.sh +0 -58
- package/framework/scripts/load-env.sh +0 -49
- package/framework/scripts/setup-claude.sh +0 -223
- package/framework/scripts/setup-linting.sh +0 -559
- package/framework/scripts/setup-quality.sh +0 -477
- package/framework/scripts/setup-safeword.sh +0 -550
- package/framework/templates/ci/architecture-check.yml +0 -78
- package/learnings/ai-sdk-v5-breaking-changes.md +0 -178
- package/learnings/e2e-test-zombie-processes.md +0 -231
- package/learnings/milkdown-crepe-editor-property.md +0 -96
- package/learnings/prosemirror-fragment-traversal.md +0 -119
- package/packages/cli/AGENTS.md +0 -1
- package/packages/cli/ARCHITECTURE.md +0 -279
- package/packages/cli/package.json +0 -51
- package/packages/cli/src/cli.ts +0 -63
- package/packages/cli/src/commands/check.ts +0 -166
- package/packages/cli/src/commands/diff.ts +0 -209
- package/packages/cli/src/commands/reset.ts +0 -190
- package/packages/cli/src/commands/setup.ts +0 -325
- package/packages/cli/src/commands/upgrade.ts +0 -163
- package/packages/cli/src/index.ts +0 -3
- package/packages/cli/src/templates/config.ts +0 -58
- package/packages/cli/src/templates/content.ts +0 -18
- package/packages/cli/src/templates/index.ts +0 -12
- package/packages/cli/src/utils/agents-md.ts +0 -66
- package/packages/cli/src/utils/fs.ts +0 -179
- package/packages/cli/src/utils/git.ts +0 -124
- package/packages/cli/src/utils/hooks.ts +0 -29
- package/packages/cli/src/utils/output.ts +0 -60
- package/packages/cli/src/utils/project-detector.test.ts +0 -185
- package/packages/cli/src/utils/project-detector.ts +0 -44
- package/packages/cli/src/utils/version.ts +0 -28
- package/packages/cli/src/version.ts +0 -6
- package/packages/cli/templates/SAFEWORD.md +0 -776
- package/packages/cli/templates/doc-templates/architecture-template.md +0 -136
- package/packages/cli/templates/doc-templates/design-doc-template.md +0 -134
- package/packages/cli/templates/doc-templates/test-definitions-feature.md +0 -131
- package/packages/cli/templates/doc-templates/ticket-template.md +0 -82
- package/packages/cli/templates/doc-templates/user-stories-template.md +0 -92
- package/packages/cli/templates/guides/architecture-guide.md +0 -423
- package/packages/cli/templates/guides/code-philosophy.md +0 -195
- package/packages/cli/templates/guides/context-files-guide.md +0 -457
- package/packages/cli/templates/guides/data-architecture-guide.md +0 -200
- package/packages/cli/templates/guides/design-doc-guide.md +0 -171
- package/packages/cli/templates/guides/learning-extraction.md +0 -552
- package/packages/cli/templates/guides/llm-instruction-design.md +0 -248
- package/packages/cli/templates/guides/llm-prompting.md +0 -102
- package/packages/cli/templates/guides/tdd-best-practices.md +0 -615
- package/packages/cli/templates/guides/test-definitions-guide.md +0 -334
- package/packages/cli/templates/guides/testing-methodology.md +0 -618
- package/packages/cli/templates/guides/user-story-guide.md +0 -256
- package/packages/cli/templates/guides/zombie-process-cleanup.md +0 -219
- package/packages/cli/templates/hooks/agents-md-check.sh +0 -27
- package/packages/cli/templates/hooks/post-tool.sh +0 -4
- package/packages/cli/templates/hooks/pre-commit.sh +0 -10
- package/packages/cli/templates/prompts/arch-review.md +0 -43
- package/packages/cli/templates/prompts/quality-review.md +0 -10
- package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +0 -207
- package/packages/cli/tests/commands/check.test.ts +0 -129
- package/packages/cli/tests/commands/cli.test.ts +0 -89
- package/packages/cli/tests/commands/diff.test.ts +0 -115
- package/packages/cli/tests/commands/reset.test.ts +0 -310
- package/packages/cli/tests/commands/self-healing.test.ts +0 -170
- package/packages/cli/tests/commands/setup-blocking.test.ts +0 -71
- package/packages/cli/tests/commands/setup-core.test.ts +0 -135
- package/packages/cli/tests/commands/setup-git.test.ts +0 -139
- package/packages/cli/tests/commands/setup-hooks.test.ts +0 -334
- package/packages/cli/tests/commands/setup-linting.test.ts +0 -189
- package/packages/cli/tests/commands/setup-noninteractive.test.ts +0 -80
- package/packages/cli/tests/commands/setup-templates.test.ts +0 -181
- package/packages/cli/tests/commands/upgrade.test.ts +0 -215
- package/packages/cli/tests/helpers.ts +0 -243
- package/packages/cli/tests/npm-package.test.ts +0 -83
- package/packages/cli/tests/technical-constraints.test.ts +0 -96
- package/packages/cli/tsconfig.json +0 -25
- package/packages/cli/tsup.config.ts +0 -11
- package/packages/cli/vitest.config.ts +0 -23
- package/promptfoo.yaml +0 -3270
- /package/{framework → templates}/SAFEWORD.md +0 -0
- /package/{packages/cli/templates → templates}/commands/arch-review.md +0 -0
- /package/{packages/cli/templates → templates}/commands/lint.md +0 -0
- /package/{packages/cli/templates → templates}/commands/quality-review.md +0 -0
- /package/{framework/templates → templates/doc-templates}/architecture-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/design-doc-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/test-definitions-feature.md +0 -0
- /package/{framework/templates → templates/doc-templates}/ticket-template.md +0 -0
- /package/{framework/templates → templates/doc-templates}/user-stories-template.md +0 -0
- /package/{framework → templates}/guides/architecture-guide.md +0 -0
- /package/{framework → templates}/guides/code-philosophy.md +0 -0
- /package/{framework → templates}/guides/context-files-guide.md +0 -0
- /package/{framework → templates}/guides/data-architecture-guide.md +0 -0
- /package/{framework → templates}/guides/design-doc-guide.md +0 -0
- /package/{framework → templates}/guides/learning-extraction.md +0 -0
- /package/{framework → templates}/guides/llm-instruction-design.md +0 -0
- /package/{framework → templates}/guides/llm-prompting.md +0 -0
- /package/{framework → templates}/guides/tdd-best-practices.md +0 -0
- /package/{framework → templates}/guides/test-definitions-guide.md +0 -0
- /package/{framework → templates}/guides/testing-methodology.md +0 -0
- /package/{framework → templates}/guides/user-story-guide.md +0 -0
- /package/{framework → templates}/guides/zombie-process-cleanup.md +0 -0
- /package/{packages/cli/templates → templates}/hooks/inject-timestamp.sh +0 -0
- /package/{packages/cli/templates → templates}/lib/common.sh +0 -0
- /package/{packages/cli/templates → templates}/lib/jq-fallback.sh +0 -0
- /package/{packages/cli/templates → templates}/markdownlint.jsonc +0 -0
- /package/{framework → templates}/prompts/arch-review.md +0 -0
- /package/{framework → templates}/prompts/quality-review.md +0 -0
- /package/{framework/skills/quality-reviewer → templates/skills/safeword-quality-reviewer}/SKILL.md +0 -0
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
import { execSync, exec } from 'node:child_process';
|
|
2
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join, dirname } from 'node:path';
|
|
5
|
-
import { promisify } from 'node:util';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
|
|
8
|
-
const execAsync = promisify(exec);
|
|
9
|
-
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = dirname(__filename);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Path to the CLI entry point (built)
|
|
15
|
-
*/
|
|
16
|
-
export const CLI_PATH = join(__dirname, '../dist/cli.js');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Path to the CLI source (for ts-node execution during development)
|
|
20
|
-
*/
|
|
21
|
-
export const CLI_SRC_PATH = join(__dirname, '../src/cli.ts');
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Creates a temporary directory for test isolation
|
|
25
|
-
*/
|
|
26
|
-
export function createTempDir(): string {
|
|
27
|
-
return mkdtempSync(join(tmpdir(), 'safeword-test-'));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Removes a temporary directory and all contents
|
|
32
|
-
*/
|
|
33
|
-
export function removeTempDir(dir: string): void {
|
|
34
|
-
rmSync(dir, { recursive: true, force: true });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Creates a minimal package.json in the given directory
|
|
39
|
-
*/
|
|
40
|
-
export function createPackageJson(dir: string, overrides: Record<string, unknown> = {}): void {
|
|
41
|
-
const pkg = {
|
|
42
|
-
name: 'test-project',
|
|
43
|
-
version: '1.0.0',
|
|
44
|
-
...overrides,
|
|
45
|
-
};
|
|
46
|
-
writeFileSync(join(dir, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Creates a TypeScript package.json (with typescript in devDependencies)
|
|
51
|
-
*/
|
|
52
|
-
export function createTypeScriptPackageJson(
|
|
53
|
-
dir: string,
|
|
54
|
-
overrides: Record<string, unknown> = {},
|
|
55
|
-
): void {
|
|
56
|
-
createPackageJson(dir, {
|
|
57
|
-
devDependencies: {
|
|
58
|
-
typescript: '^5.0.0',
|
|
59
|
-
},
|
|
60
|
-
...overrides,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Creates a React package.json
|
|
66
|
-
*/
|
|
67
|
-
export function createReactPackageJson(dir: string, overrides: Record<string, unknown> = {}): void {
|
|
68
|
-
createPackageJson(dir, {
|
|
69
|
-
dependencies: {
|
|
70
|
-
react: '^18.0.0',
|
|
71
|
-
'react-dom': '^18.0.0',
|
|
72
|
-
},
|
|
73
|
-
...overrides,
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Creates a Next.js package.json
|
|
79
|
-
*/
|
|
80
|
-
export function createNextJsPackageJson(
|
|
81
|
-
dir: string,
|
|
82
|
-
overrides: Record<string, unknown> = {},
|
|
83
|
-
): void {
|
|
84
|
-
createPackageJson(dir, {
|
|
85
|
-
dependencies: {
|
|
86
|
-
next: '^14.0.0',
|
|
87
|
-
react: '^18.0.0',
|
|
88
|
-
'react-dom': '^18.0.0',
|
|
89
|
-
},
|
|
90
|
-
...overrides,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Result from running the CLI
|
|
96
|
-
*/
|
|
97
|
-
export interface CliResult {
|
|
98
|
-
stdout: string;
|
|
99
|
-
stderr: string;
|
|
100
|
-
exitCode: number;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Runs the CLI with the given arguments in the specified directory
|
|
105
|
-
* Uses built CLI (dist/cli.js)
|
|
106
|
-
*/
|
|
107
|
-
export async function runCli(
|
|
108
|
-
args: string[],
|
|
109
|
-
options: {
|
|
110
|
-
cwd?: string;
|
|
111
|
-
input?: string;
|
|
112
|
-
env?: Record<string, string>;
|
|
113
|
-
timeout?: number;
|
|
114
|
-
} = {},
|
|
115
|
-
): Promise<CliResult> {
|
|
116
|
-
const { cwd = process.cwd(), input, env = {}, timeout = 30000 } = options;
|
|
117
|
-
|
|
118
|
-
const command = `node ${CLI_PATH} ${args.join(' ')}`;
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
const { stdout, stderr } = await execAsync(command, {
|
|
122
|
-
cwd,
|
|
123
|
-
env: { ...process.env, ...env },
|
|
124
|
-
timeout,
|
|
125
|
-
...(input ? { input } : {}),
|
|
126
|
-
});
|
|
127
|
-
return { stdout, stderr, exitCode: 0 };
|
|
128
|
-
} catch (error: unknown) {
|
|
129
|
-
const execError = error as {
|
|
130
|
-
stdout?: string;
|
|
131
|
-
stderr?: string;
|
|
132
|
-
code?: number;
|
|
133
|
-
status?: number;
|
|
134
|
-
};
|
|
135
|
-
return {
|
|
136
|
-
stdout: execError.stdout ?? '',
|
|
137
|
-
stderr: execError.stderr ?? '',
|
|
138
|
-
exitCode: execError.code ?? execError.status ?? 1,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Runs the CLI synchronously (for simple tests)
|
|
145
|
-
*/
|
|
146
|
-
export function runCliSync(
|
|
147
|
-
args: string[],
|
|
148
|
-
options: {
|
|
149
|
-
cwd?: string;
|
|
150
|
-
env?: Record<string, string>;
|
|
151
|
-
timeout?: number;
|
|
152
|
-
} = {},
|
|
153
|
-
): CliResult {
|
|
154
|
-
const { cwd = process.cwd(), env = {}, timeout = 30000 } = options;
|
|
155
|
-
|
|
156
|
-
const command = `node ${CLI_PATH} ${args.join(' ')}`;
|
|
157
|
-
|
|
158
|
-
try {
|
|
159
|
-
const stdout = execSync(command, {
|
|
160
|
-
cwd,
|
|
161
|
-
env: { ...process.env, ...env },
|
|
162
|
-
timeout,
|
|
163
|
-
encoding: 'utf-8',
|
|
164
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
165
|
-
});
|
|
166
|
-
return { stdout, stderr: '', exitCode: 0 };
|
|
167
|
-
} catch (error: unknown) {
|
|
168
|
-
const execError = error as {
|
|
169
|
-
stdout?: string | Buffer;
|
|
170
|
-
stderr?: string | Buffer;
|
|
171
|
-
status?: number;
|
|
172
|
-
};
|
|
173
|
-
return {
|
|
174
|
-
stdout: execError.stdout?.toString() ?? '',
|
|
175
|
-
stderr: execError.stderr?.toString() ?? '',
|
|
176
|
-
exitCode: execError.status ?? 1,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Reads a file from the test directory
|
|
183
|
-
*/
|
|
184
|
-
export function readTestFile(dir: string, relativePath: string): string {
|
|
185
|
-
return readFileSync(join(dir, relativePath), 'utf-8');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Writes a file to the test directory
|
|
190
|
-
*/
|
|
191
|
-
export function writeTestFile(dir: string, relativePath: string, content: string): void {
|
|
192
|
-
const fullPath = join(dir, relativePath);
|
|
193
|
-
const parentDir = join(fullPath, '..');
|
|
194
|
-
if (!existsSync(parentDir)) {
|
|
195
|
-
mkdirSync(parentDir, { recursive: true });
|
|
196
|
-
}
|
|
197
|
-
writeFileSync(fullPath, content);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Checks if a file exists in the test directory
|
|
202
|
-
*/
|
|
203
|
-
export function fileExists(dir: string, relativePath: string): boolean {
|
|
204
|
-
return existsSync(join(dir, relativePath));
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Initializes a git repository in the given directory
|
|
209
|
-
*/
|
|
210
|
-
export function initGitRepo(dir: string): void {
|
|
211
|
-
execSync('git init', { cwd: dir, stdio: 'pipe' });
|
|
212
|
-
execSync('git config user.email "test@test.com"', { cwd: dir, stdio: 'pipe' });
|
|
213
|
-
execSync('git config user.name "Test User"', { cwd: dir, stdio: 'pipe' });
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Creates a configured project (runs setup) for tests that need pre-configured state
|
|
218
|
-
*/
|
|
219
|
-
export async function createConfiguredProject(dir: string): Promise<void> {
|
|
220
|
-
createTypeScriptPackageJson(dir);
|
|
221
|
-
initGitRepo(dir);
|
|
222
|
-
await runCli(['setup', '--yes'], { cwd: dir });
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Measures execution time of a function in milliseconds
|
|
227
|
-
*/
|
|
228
|
-
export async function measureTime<T>(fn: () => Promise<T>): Promise<{ result: T; timeMs: number }> {
|
|
229
|
-
const start = performance.now();
|
|
230
|
-
const result = await fn();
|
|
231
|
-
const timeMs = performance.now() - start;
|
|
232
|
-
return { result, timeMs };
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Measures execution time of a sync function in milliseconds
|
|
237
|
-
*/
|
|
238
|
-
export function measureTimeSync<T>(fn: () => T): { result: T; timeMs: number } {
|
|
239
|
-
const start = performance.now();
|
|
240
|
-
const result = fn();
|
|
241
|
-
const timeMs = performance.now() - start;
|
|
242
|
-
return { result, timeMs };
|
|
243
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite: NPM Package Distribution
|
|
3
|
-
*
|
|
4
|
-
* Tests that the npm package is correctly structured and would work
|
|
5
|
-
* when installed via `npm install` or `npx`.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect } from 'vitest';
|
|
9
|
-
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
10
|
-
import { join, dirname } from 'node:path';
|
|
11
|
-
import { fileURLToPath } from 'node:url';
|
|
12
|
-
|
|
13
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
-
const cliRoot = join(__dirname, '..');
|
|
15
|
-
|
|
16
|
-
describe('NPM Package Structure', () => {
|
|
17
|
-
it('should have package.json with correct files array', () => {
|
|
18
|
-
const packageJson = JSON.parse(readFileSync(join(cliRoot, 'package.json'), 'utf-8'));
|
|
19
|
-
|
|
20
|
-
expect(packageJson.files).toBeDefined();
|
|
21
|
-
expect(packageJson.files).toContain('dist');
|
|
22
|
-
expect(packageJson.files).toContain('templates');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should have dist directory with CLI entry point', () => {
|
|
26
|
-
const distPath = join(cliRoot, 'dist');
|
|
27
|
-
expect(existsSync(distPath)).toBe(true);
|
|
28
|
-
expect(existsSync(join(distPath, 'cli.js'))).toBe(true);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('should have templates directory with all required subdirectories', () => {
|
|
32
|
-
const templatesPath = join(cliRoot, 'templates');
|
|
33
|
-
expect(existsSync(templatesPath)).toBe(true);
|
|
34
|
-
|
|
35
|
-
const required = ['SAFEWORD.md', 'guides', 'doc-templates', 'hooks', 'prompts', 'skills', 'commands', 'lib'];
|
|
36
|
-
for (const item of required) {
|
|
37
|
-
expect(existsSync(join(templatesPath, item))).toBe(true);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should have templates/hooks with all hook scripts', () => {
|
|
42
|
-
const hooksPath = join(cliRoot, 'templates', 'hooks');
|
|
43
|
-
const files = readdirSync(hooksPath);
|
|
44
|
-
|
|
45
|
-
expect(files).toContain('agents-md-check.sh');
|
|
46
|
-
expect(files).toContain('pre-commit.sh');
|
|
47
|
-
expect(files).toContain('post-tool.sh');
|
|
48
|
-
expect(files).toContain('inject-timestamp.sh');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should have templates/guides with methodology files', () => {
|
|
52
|
-
const guidesPath = join(cliRoot, 'templates', 'guides');
|
|
53
|
-
const files = readdirSync(guidesPath);
|
|
54
|
-
|
|
55
|
-
// Should have multiple guide files
|
|
56
|
-
const mdFiles = files.filter((f) => f.endsWith('.md'));
|
|
57
|
-
expect(mdFiles.length).toBeGreaterThan(5);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should have templates/skills with quality reviewer', () => {
|
|
61
|
-
const skillPath = join(cliRoot, 'templates', 'skills', 'safeword-quality-reviewer');
|
|
62
|
-
expect(existsSync(skillPath)).toBe(true);
|
|
63
|
-
expect(existsSync(join(skillPath, 'SKILL.md'))).toBe(true);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it('should have templates/commands with slash commands', () => {
|
|
67
|
-
const commandsPath = join(cliRoot, 'templates', 'commands');
|
|
68
|
-
const files = readdirSync(commandsPath);
|
|
69
|
-
|
|
70
|
-
expect(files).toContain('quality-review.md');
|
|
71
|
-
expect(files).toContain('arch-review.md');
|
|
72
|
-
expect(files).toContain('lint.md');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should resolve templates from dist context', () => {
|
|
76
|
-
// Simulate the path resolution that getTemplatesDir() does
|
|
77
|
-
const distDir = join(cliRoot, 'dist');
|
|
78
|
-
const templatesFromDist = join(distDir, '..', 'templates');
|
|
79
|
-
|
|
80
|
-
expect(existsSync(templatesFromDist)).toBe(true);
|
|
81
|
-
expect(existsSync(join(templatesFromDist, 'SAFEWORD.md'))).toBe(true);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 0: Technical Constraints
|
|
3
|
-
*
|
|
4
|
-
* Tests for non-functional requirements that apply across all commands.
|
|
5
|
-
* These tests verify performance, compatibility, and quality requirements.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
9
|
-
import {
|
|
10
|
-
createTempDir,
|
|
11
|
-
removeTempDir,
|
|
12
|
-
createTypeScriptPackageJson,
|
|
13
|
-
runCli,
|
|
14
|
-
runCliSync,
|
|
15
|
-
measureTime,
|
|
16
|
-
initGitRepo,
|
|
17
|
-
} from './helpers';
|
|
18
|
-
|
|
19
|
-
describe('Test Suite 0: Technical Constraints', () => {
|
|
20
|
-
let tempDir: string;
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
tempDir = createTempDir();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
afterEach(() => {
|
|
27
|
-
removeTempDir(tempDir);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe('Test 0.1: CLI startup time under 500ms', () => {
|
|
31
|
-
it('should start quickly with average under 500ms', async () => {
|
|
32
|
-
const runs = 10;
|
|
33
|
-
const times: number[] = [];
|
|
34
|
-
|
|
35
|
-
for (let i = 0; i < runs; i++) {
|
|
36
|
-
const { timeMs } = await measureTime(async () => {
|
|
37
|
-
return runCliSync(['--version']);
|
|
38
|
-
});
|
|
39
|
-
times.push(timeMs);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const averageTime = times.reduce((a, b) => a + b, 0) / times.length;
|
|
43
|
-
const maxTime = Math.max(...times);
|
|
44
|
-
|
|
45
|
-
expect(averageTime).toBeLessThan(500);
|
|
46
|
-
expect(maxTime).toBeLessThan(750);
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
describe('Test 0.2: Setup completes under 30s', () => {
|
|
51
|
-
it('should complete setup in under 30 seconds', async () => {
|
|
52
|
-
createTypeScriptPackageJson(tempDir);
|
|
53
|
-
initGitRepo(tempDir);
|
|
54
|
-
|
|
55
|
-
const { result, timeMs } = await measureTime(async () => {
|
|
56
|
-
return runCli(['setup', '--yes'], { cwd: tempDir, timeout: 60000 });
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(result.exitCode).toBe(0);
|
|
60
|
-
expect(timeMs).toBeLessThan(30000);
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe('Test 0.3: Node.js version check', () => {
|
|
65
|
-
it.skip('should exit with error on Node.js < 18 (requires CI container)', async () => {
|
|
66
|
-
// This test requires running with Node.js < 18, which needs:
|
|
67
|
-
// - A Docker container with older Node, OR
|
|
68
|
-
// - nvm switching in CI
|
|
69
|
-
//
|
|
70
|
-
// The implementation should check process.version at startup
|
|
71
|
-
// and exit with code 1 if version < 18.
|
|
72
|
-
//
|
|
73
|
-
// Expected behavior:
|
|
74
|
-
// - Exit code 1
|
|
75
|
-
// - stderr contains "Node.js version" and "18"
|
|
76
|
-
expect(true).toBe(true); // Placeholder
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('Test 0.4: Works with different package managers', () => {
|
|
81
|
-
it('should work with npm', async () => {
|
|
82
|
-
createTypeScriptPackageJson(tempDir);
|
|
83
|
-
initGitRepo(tempDir);
|
|
84
|
-
|
|
85
|
-
const result = await runCli(['setup', '--yes'], {
|
|
86
|
-
cwd: tempDir,
|
|
87
|
-
timeout: 60000,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
expect(result.exitCode).toBe(0);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Note: pnpm and yarn tests should be in separate CI jobs
|
|
94
|
-
// to ensure proper package manager isolation
|
|
95
|
-
});
|
|
96
|
-
});
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"outDir": "./dist",
|
|
8
|
-
"rootDir": "./src",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"declaration": true,
|
|
14
|
-
"declarationMap": true,
|
|
15
|
-
"sourceMap": true,
|
|
16
|
-
"resolveJsonModule": true,
|
|
17
|
-
"isolatedModules": true,
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"noImplicitReturns": true,
|
|
21
|
-
"noFallthroughCasesInSwitch": true
|
|
22
|
-
},
|
|
23
|
-
"include": ["src/**/*"],
|
|
24
|
-
"exclude": ["node_modules", "dist", "tests"]
|
|
25
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vitest/config';
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: true,
|
|
6
|
-
environment: 'node',
|
|
7
|
-
include: ['tests/**/*.test.ts', 'src/**/*.test.ts'],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: 'v8',
|
|
10
|
-
include: ['src/**/*.ts'],
|
|
11
|
-
exclude: ['src/**/*.test.ts', 'src/index.ts'],
|
|
12
|
-
},
|
|
13
|
-
// Increase timeout for integration tests that spawn processes
|
|
14
|
-
testTimeout: 30000,
|
|
15
|
-
// Run tests sequentially to avoid temp directory conflicts
|
|
16
|
-
pool: 'forks',
|
|
17
|
-
poolOptions: {
|
|
18
|
-
forks: {
|
|
19
|
-
singleFork: true,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
});
|