safeword 0.2.4 → 0.2.6

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.
Files changed (235) hide show
  1. package/dist/check-3NGQ4NR5.js +129 -0
  2. package/dist/check-3NGQ4NR5.js.map +1 -0
  3. package/dist/chunk-2XWIUEQK.js +190 -0
  4. package/dist/chunk-2XWIUEQK.js.map +1 -0
  5. package/dist/chunk-GZRQL3SX.js +146 -0
  6. package/dist/chunk-GZRQL3SX.js.map +1 -0
  7. package/dist/chunk-ORQHKDT2.js +10 -0
  8. package/dist/chunk-ORQHKDT2.js.map +1 -0
  9. package/dist/chunk-W66Z3C5H.js +21 -0
  10. package/dist/chunk-W66Z3C5H.js.map +1 -0
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cli.js +34 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/diff-Y6QTAW4O.js +166 -0
  15. package/dist/diff-Y6QTAW4O.js.map +1 -0
  16. package/dist/index.d.ts +11 -0
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/reset-3ACTIYYE.js +143 -0
  20. package/dist/reset-3ACTIYYE.js.map +1 -0
  21. package/dist/setup-AIL5RL45.js +276 -0
  22. package/dist/setup-AIL5RL45.js.map +1 -0
  23. package/dist/upgrade-6AR3DHUV.js +134 -0
  24. package/dist/upgrade-6AR3DHUV.js.map +1 -0
  25. package/package.json +44 -19
  26. package/{.safeword → templates}/hooks/agents-md-check.sh +0 -0
  27. package/{.safeword → templates}/hooks/post-tool.sh +0 -0
  28. package/{.safeword → templates}/hooks/pre-commit.sh +0 -0
  29. package/.claude/commands/arch-review.md +0 -32
  30. package/.claude/commands/lint.md +0 -6
  31. package/.claude/commands/quality-review.md +0 -13
  32. package/.claude/commands/setup-linting.md +0 -6
  33. package/.claude/hooks/auto-lint.sh +0 -6
  34. package/.claude/hooks/auto-quality-review.sh +0 -170
  35. package/.claude/hooks/check-linting-sync.sh +0 -17
  36. package/.claude/hooks/inject-timestamp.sh +0 -6
  37. package/.claude/hooks/question-protocol.sh +0 -12
  38. package/.claude/hooks/run-linters.sh +0 -8
  39. package/.claude/hooks/run-quality-review.sh +0 -76
  40. package/.claude/hooks/version-check.sh +0 -10
  41. package/.claude/mcp/README.md +0 -96
  42. package/.claude/mcp/arcade.sample.json +0 -9
  43. package/.claude/mcp/context7.sample.json +0 -7
  44. package/.claude/mcp/playwright.sample.json +0 -7
  45. package/.claude/settings.json +0 -62
  46. package/.claude/skills/quality-reviewer/SKILL.md +0 -190
  47. package/.claude/skills/safeword-quality-reviewer/SKILL.md +0 -13
  48. package/.env.arcade.example +0 -4
  49. package/.env.example +0 -11
  50. package/.gitmodules +0 -4
  51. package/.safeword/SAFEWORD.md +0 -33
  52. package/.safeword/eslint/eslint-base.mjs +0 -101
  53. package/.safeword/guides/architecture-guide.md +0 -404
  54. package/.safeword/guides/code-philosophy.md +0 -174
  55. package/.safeword/guides/context-files-guide.md +0 -405
  56. package/.safeword/guides/data-architecture-guide.md +0 -183
  57. package/.safeword/guides/design-doc-guide.md +0 -165
  58. package/.safeword/guides/learning-extraction.md +0 -515
  59. package/.safeword/guides/llm-instruction-design.md +0 -239
  60. package/.safeword/guides/llm-prompting.md +0 -95
  61. package/.safeword/guides/tdd-best-practices.md +0 -570
  62. package/.safeword/guides/test-definitions-guide.md +0 -243
  63. package/.safeword/guides/testing-methodology.md +0 -573
  64. package/.safeword/guides/user-story-guide.md +0 -237
  65. package/.safeword/guides/zombie-process-cleanup.md +0 -214
  66. package/.safeword/planning/002-user-story-quality-evaluation.md +0 -1840
  67. package/.safeword/planning/003-langsmith-eval-setup-prompt.md +0 -363
  68. package/.safeword/planning/004-llm-eval-test-cases.md +0 -3226
  69. package/.safeword/planning/005-architecture-enforcement-system.md +0 -169
  70. package/.safeword/planning/006-reactive-fix-prevention-research.md +0 -135
  71. package/.safeword/planning/011-cli-ux-vision.md +0 -330
  72. package/.safeword/planning/012-project-structure-cleanup.md +0 -154
  73. package/.safeword/planning/README.md +0 -39
  74. package/.safeword/planning/automation-plan-v2.md +0 -1225
  75. package/.safeword/planning/automation-plan-v3.md +0 -1291
  76. package/.safeword/planning/automation-plan.md +0 -3058
  77. package/.safeword/planning/design/005-cli-implementation.md +0 -343
  78. package/.safeword/planning/design/013-cli-self-contained-templates.md +0 -596
  79. package/.safeword/planning/design/013a-eslint-plugin-suite.md +0 -256
  80. package/.safeword/planning/design/013b-implementation-snippets.md +0 -385
  81. package/.safeword/planning/design/013c-config-isolation-strategy.md +0 -242
  82. package/.safeword/planning/design/code-philosophy-improvements.md +0 -60
  83. package/.safeword/planning/mcp-analysis.md +0 -545
  84. package/.safeword/planning/phase2-subagents-vs-skills-analysis.md +0 -451
  85. package/.safeword/planning/settings-improvements.md +0 -970
  86. package/.safeword/planning/test-definitions/005-cli-implementation.md +0 -1301
  87. package/.safeword/planning/test-definitions/cli-self-contained-templates.md +0 -205
  88. package/.safeword/planning/user-stories/001-guides-review-user-stories.md +0 -1381
  89. package/.safeword/planning/user-stories/003-reactive-fix-prevention.md +0 -132
  90. package/.safeword/planning/user-stories/004-technical-constraints.md +0 -86
  91. package/.safeword/planning/user-stories/005-cli-implementation.md +0 -311
  92. package/.safeword/planning/user-stories/cli-self-contained-templates.md +0 -172
  93. package/.safeword/planning/versioned-distribution.md +0 -740
  94. package/.safeword/prompts/arch-review.md +0 -43
  95. package/.safeword/prompts/quality-review.md +0 -11
  96. package/.safeword/scripts/arch-review.sh +0 -235
  97. package/.safeword/scripts/check-linting-sync.sh +0 -58
  98. package/.safeword/scripts/setup-linting.sh +0 -559
  99. package/.safeword/templates/architecture-template.md +0 -136
  100. package/.safeword/templates/ci/architecture-check.yml +0 -79
  101. package/.safeword/templates/design-doc-template.md +0 -127
  102. package/.safeword/templates/test-definitions-feature.md +0 -100
  103. package/.safeword/templates/ticket-template.md +0 -74
  104. package/.safeword/templates/user-stories-template.md +0 -82
  105. package/.safeword/tickets/001-guides-review-user-stories.md +0 -83
  106. package/.safeword/tickets/002-architecture-enforcement.md +0 -211
  107. package/.safeword/tickets/003-reactive-fix-prevention.md +0 -57
  108. package/.safeword/tickets/004-technical-constraints-in-user-stories.md +0 -39
  109. package/.safeword/tickets/005-cli-implementation.md +0 -248
  110. package/.safeword/tickets/006-flesh-out-skills.md +0 -43
  111. package/.safeword/tickets/007-flesh-out-questioning.md +0 -44
  112. package/.safeword/tickets/008-upgrade-questioning.md +0 -58
  113. package/.safeword/tickets/009-naming-conventions.md +0 -41
  114. package/.safeword/tickets/010-safeword-md-cleanup.md +0 -34
  115. package/.safeword/tickets/011-cursor-setup.md +0 -86
  116. package/.safeword/tickets/README.md +0 -73
  117. package/.safeword/version +0 -1
  118. package/AGENTS.md +0 -59
  119. package/CLAUDE.md +0 -12
  120. package/README.md +0 -347
  121. package/docs/001-cli-implementation-plan.md +0 -856
  122. package/docs/elite-dx-implementation-plan.md +0 -1034
  123. package/framework/README.md +0 -131
  124. package/framework/mcp/README.md +0 -96
  125. package/framework/mcp/arcade.sample.json +0 -8
  126. package/framework/mcp/context7.sample.json +0 -6
  127. package/framework/mcp/playwright.sample.json +0 -6
  128. package/framework/scripts/arch-review.sh +0 -235
  129. package/framework/scripts/check-linting-sync.sh +0 -58
  130. package/framework/scripts/load-env.sh +0 -49
  131. package/framework/scripts/setup-claude.sh +0 -223
  132. package/framework/scripts/setup-linting.sh +0 -559
  133. package/framework/scripts/setup-quality.sh +0 -477
  134. package/framework/scripts/setup-safeword.sh +0 -550
  135. package/framework/templates/ci/architecture-check.yml +0 -78
  136. package/learnings/ai-sdk-v5-breaking-changes.md +0 -178
  137. package/learnings/e2e-test-zombie-processes.md +0 -231
  138. package/learnings/milkdown-crepe-editor-property.md +0 -96
  139. package/learnings/prosemirror-fragment-traversal.md +0 -119
  140. package/packages/cli/AGENTS.md +0 -1
  141. package/packages/cli/ARCHITECTURE.md +0 -279
  142. package/packages/cli/package.json +0 -51
  143. package/packages/cli/src/cli.ts +0 -63
  144. package/packages/cli/src/commands/check.ts +0 -166
  145. package/packages/cli/src/commands/diff.ts +0 -209
  146. package/packages/cli/src/commands/reset.ts +0 -190
  147. package/packages/cli/src/commands/setup.ts +0 -325
  148. package/packages/cli/src/commands/upgrade.ts +0 -163
  149. package/packages/cli/src/index.ts +0 -3
  150. package/packages/cli/src/templates/config.ts +0 -58
  151. package/packages/cli/src/templates/content.ts +0 -18
  152. package/packages/cli/src/templates/index.ts +0 -12
  153. package/packages/cli/src/utils/agents-md.ts +0 -66
  154. package/packages/cli/src/utils/fs.ts +0 -179
  155. package/packages/cli/src/utils/git.ts +0 -124
  156. package/packages/cli/src/utils/hooks.ts +0 -29
  157. package/packages/cli/src/utils/output.ts +0 -60
  158. package/packages/cli/src/utils/project-detector.test.ts +0 -185
  159. package/packages/cli/src/utils/project-detector.ts +0 -44
  160. package/packages/cli/src/utils/version.ts +0 -28
  161. package/packages/cli/src/version.ts +0 -6
  162. package/packages/cli/templates/SAFEWORD.md +0 -776
  163. package/packages/cli/templates/doc-templates/architecture-template.md +0 -136
  164. package/packages/cli/templates/doc-templates/design-doc-template.md +0 -134
  165. package/packages/cli/templates/doc-templates/test-definitions-feature.md +0 -131
  166. package/packages/cli/templates/doc-templates/ticket-template.md +0 -82
  167. package/packages/cli/templates/doc-templates/user-stories-template.md +0 -92
  168. package/packages/cli/templates/guides/architecture-guide.md +0 -423
  169. package/packages/cli/templates/guides/code-philosophy.md +0 -195
  170. package/packages/cli/templates/guides/context-files-guide.md +0 -457
  171. package/packages/cli/templates/guides/data-architecture-guide.md +0 -200
  172. package/packages/cli/templates/guides/design-doc-guide.md +0 -171
  173. package/packages/cli/templates/guides/learning-extraction.md +0 -552
  174. package/packages/cli/templates/guides/llm-instruction-design.md +0 -248
  175. package/packages/cli/templates/guides/llm-prompting.md +0 -102
  176. package/packages/cli/templates/guides/tdd-best-practices.md +0 -615
  177. package/packages/cli/templates/guides/test-definitions-guide.md +0 -334
  178. package/packages/cli/templates/guides/testing-methodology.md +0 -618
  179. package/packages/cli/templates/guides/user-story-guide.md +0 -256
  180. package/packages/cli/templates/guides/zombie-process-cleanup.md +0 -219
  181. package/packages/cli/templates/hooks/agents-md-check.sh +0 -27
  182. package/packages/cli/templates/hooks/post-tool.sh +0 -4
  183. package/packages/cli/templates/hooks/pre-commit.sh +0 -10
  184. package/packages/cli/templates/prompts/arch-review.md +0 -43
  185. package/packages/cli/templates/prompts/quality-review.md +0 -10
  186. package/packages/cli/templates/skills/safeword-quality-reviewer/SKILL.md +0 -207
  187. package/packages/cli/tests/commands/check.test.ts +0 -129
  188. package/packages/cli/tests/commands/cli.test.ts +0 -89
  189. package/packages/cli/tests/commands/diff.test.ts +0 -115
  190. package/packages/cli/tests/commands/reset.test.ts +0 -310
  191. package/packages/cli/tests/commands/self-healing.test.ts +0 -170
  192. package/packages/cli/tests/commands/setup-blocking.test.ts +0 -71
  193. package/packages/cli/tests/commands/setup-core.test.ts +0 -135
  194. package/packages/cli/tests/commands/setup-git.test.ts +0 -139
  195. package/packages/cli/tests/commands/setup-hooks.test.ts +0 -334
  196. package/packages/cli/tests/commands/setup-linting.test.ts +0 -189
  197. package/packages/cli/tests/commands/setup-noninteractive.test.ts +0 -80
  198. package/packages/cli/tests/commands/setup-templates.test.ts +0 -181
  199. package/packages/cli/tests/commands/upgrade.test.ts +0 -215
  200. package/packages/cli/tests/helpers.ts +0 -243
  201. package/packages/cli/tests/npm-package.test.ts +0 -83
  202. package/packages/cli/tests/technical-constraints.test.ts +0 -96
  203. package/packages/cli/tsconfig.json +0 -25
  204. package/packages/cli/tsup.config.ts +0 -11
  205. package/packages/cli/vitest.config.ts +0 -23
  206. package/promptfoo.yaml +0 -3270
  207. /package/{framework → templates}/SAFEWORD.md +0 -0
  208. /package/{packages/cli/templates → templates}/commands/arch-review.md +0 -0
  209. /package/{packages/cli/templates → templates}/commands/lint.md +0 -0
  210. /package/{packages/cli/templates → templates}/commands/quality-review.md +0 -0
  211. /package/{framework/templates → templates/doc-templates}/architecture-template.md +0 -0
  212. /package/{framework/templates → templates/doc-templates}/design-doc-template.md +0 -0
  213. /package/{framework/templates → templates/doc-templates}/test-definitions-feature.md +0 -0
  214. /package/{framework/templates → templates/doc-templates}/ticket-template.md +0 -0
  215. /package/{framework/templates → templates/doc-templates}/user-stories-template.md +0 -0
  216. /package/{framework → templates}/guides/architecture-guide.md +0 -0
  217. /package/{framework → templates}/guides/code-philosophy.md +0 -0
  218. /package/{framework → templates}/guides/context-files-guide.md +0 -0
  219. /package/{framework → templates}/guides/data-architecture-guide.md +0 -0
  220. /package/{framework → templates}/guides/design-doc-guide.md +0 -0
  221. /package/{framework → templates}/guides/learning-extraction.md +0 -0
  222. /package/{framework → templates}/guides/llm-instruction-design.md +0 -0
  223. /package/{framework → templates}/guides/llm-prompting.md +0 -0
  224. /package/{framework → templates}/guides/tdd-best-practices.md +0 -0
  225. /package/{framework → templates}/guides/test-definitions-guide.md +0 -0
  226. /package/{framework → templates}/guides/testing-methodology.md +0 -0
  227. /package/{framework → templates}/guides/user-story-guide.md +0 -0
  228. /package/{framework → templates}/guides/zombie-process-cleanup.md +0 -0
  229. /package/{packages/cli/templates → templates}/hooks/inject-timestamp.sh +0 -0
  230. /package/{packages/cli/templates → templates}/lib/common.sh +0 -0
  231. /package/{packages/cli/templates → templates}/lib/jq-fallback.sh +0 -0
  232. /package/{packages/cli/templates → templates}/markdownlint.jsonc +0 -0
  233. /package/{framework → templates}/prompts/arch-review.md +0 -0
  234. /package/{framework → templates}/prompts/quality-review.md +0 -0
  235. /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,11 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/cli.ts', 'src/index.ts'],
5
- format: ['esm'],
6
- dts: true,
7
- sourcemap: true,
8
- clean: true,
9
- target: 'node18',
10
- shims: false,
11
- });
@@ -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
- });