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,179 +0,0 @@
1
- /**
2
- * File system utilities for CLI operations
3
- */
4
-
5
- import {
6
- existsSync,
7
- mkdirSync,
8
- readFileSync,
9
- writeFileSync,
10
- rmSync,
11
- readdirSync,
12
- statSync,
13
- chmodSync,
14
- copyFileSync,
15
- } from 'node:fs';
16
- import { join, dirname } from 'node:path';
17
- import { fileURLToPath } from 'node:url';
18
-
19
- // Get the directory of this module (for locating templates)
20
- const __dirname = dirname(fileURLToPath(import.meta.url));
21
-
22
- /**
23
- * Get path to bundled templates directory.
24
- * Works in both development (src/) and production (dist/) contexts.
25
- */
26
- export function getTemplatesDir(): string {
27
- // When running from dist/, __dirname is packages/cli/dist/
28
- // Templates are at packages/cli/templates/ (one level up)
29
- const fromDist = join(__dirname, '..', 'templates');
30
-
31
- // Fallback path for edge cases
32
- const fallback = join(__dirname, '..', '..', 'templates');
33
-
34
- if (existsSync(fromDist)) return fromDist;
35
- if (existsSync(fallback)) return fallback;
36
-
37
- throw new Error('Templates directory not found');
38
- }
39
-
40
- /**
41
- * Check if a path exists
42
- */
43
- export function exists(path: string): boolean {
44
- return existsSync(path);
45
- }
46
-
47
- /**
48
- * Check if path is a directory
49
- */
50
- export function isDirectory(path: string): boolean {
51
- return existsSync(path) && statSync(path).isDirectory();
52
- }
53
-
54
- /**
55
- * Create directory recursively
56
- */
57
- export function ensureDir(path: string): void {
58
- if (!existsSync(path)) {
59
- mkdirSync(path, { recursive: true });
60
- }
61
- }
62
-
63
- /**
64
- * Read file as string
65
- */
66
- export function readFile(path: string): string {
67
- return readFileSync(path, 'utf-8');
68
- }
69
-
70
- /**
71
- * Read file as string, return null if not exists
72
- */
73
- export function readFileSafe(path: string): string | null {
74
- if (!existsSync(path)) return null;
75
- return readFileSync(path, 'utf-8');
76
- }
77
-
78
- /**
79
- * Write file, creating parent directories if needed
80
- */
81
- export function writeFile(path: string, content: string): void {
82
- ensureDir(dirname(path));
83
- writeFileSync(path, content);
84
- }
85
-
86
- /**
87
- * Remove file or directory recursively
88
- */
89
- export function remove(path: string): void {
90
- if (existsSync(path)) {
91
- rmSync(path, { recursive: true, force: true });
92
- }
93
- }
94
-
95
- /**
96
- * List files in directory
97
- */
98
- export function listDir(path: string): string[] {
99
- if (!existsSync(path)) return [];
100
- return readdirSync(path);
101
- }
102
-
103
- /**
104
- * Copy a single file
105
- */
106
- export function copyFile(src: string, dest: string): void {
107
- ensureDir(dirname(dest));
108
- copyFileSync(src, dest);
109
- }
110
-
111
- /**
112
- * Copy directory recursively
113
- */
114
- export function copyDir(src: string, dest: string): void {
115
- ensureDir(dest);
116
- const entries = readdirSync(src, { withFileTypes: true });
117
-
118
- for (const entry of entries) {
119
- const srcPath = join(src, entry.name);
120
- const destPath = join(dest, entry.name);
121
-
122
- if (entry.isDirectory()) {
123
- copyDir(srcPath, destPath);
124
- } else {
125
- copyFileSync(srcPath, destPath);
126
- }
127
- }
128
- }
129
-
130
- /**
131
- * Make file executable
132
- */
133
- export function makeExecutable(path: string): void {
134
- chmodSync(path, 0o755);
135
- }
136
-
137
- /**
138
- * Make all shell scripts in a directory executable
139
- */
140
- export function makeScriptsExecutable(dirPath: string): void {
141
- if (!existsSync(dirPath)) return;
142
- for (const file of readdirSync(dirPath)) {
143
- if (file.endsWith('.sh')) {
144
- chmodSync(join(dirPath, file), 0o755);
145
- }
146
- }
147
- }
148
-
149
- /**
150
- * Read JSON file
151
- */
152
- export function readJson<T = unknown>(path: string): T | null {
153
- const content = readFileSafe(path);
154
- if (!content) return null;
155
- try {
156
- return JSON.parse(content) as T;
157
- } catch {
158
- return null;
159
- }
160
- }
161
-
162
- /**
163
- * Write JSON file with formatting
164
- */
165
- export function writeJson(path: string, data: unknown): void {
166
- writeFile(path, JSON.stringify(data, null, 2) + '\n');
167
- }
168
-
169
- /**
170
- * Update JSON file, merging with existing content
171
- */
172
- export function updateJson<T extends Record<string, unknown>>(
173
- path: string,
174
- updater: (existing: T | null) => T,
175
- ): void {
176
- const existing = readJson<T>(path);
177
- const updated = updater(existing);
178
- writeJson(path, updated);
179
- }
@@ -1,124 +0,0 @@
1
- /**
2
- * Git utilities for CLI operations
3
- */
4
-
5
- import { execSync } from 'node:child_process';
6
- import { join } from 'node:path';
7
- import { exists, readFile, writeFile, ensureDir, makeExecutable } from './fs.js';
8
-
9
- const MARKER_START = '# SAFEWORD_ARCH_CHECK_START';
10
- const MARKER_END = '# SAFEWORD_ARCH_CHECK_END';
11
-
12
- /**
13
- * Check if directory is a git repository
14
- */
15
- export function isGitRepo(cwd: string): boolean {
16
- return exists(join(cwd, '.git'));
17
- }
18
-
19
- /**
20
- * Initialize a git repository
21
- */
22
- export function initGitRepo(cwd: string): void {
23
- execSync('git init', { cwd, stdio: 'pipe' });
24
- }
25
-
26
- /**
27
- * Get the pre-commit hook content to add
28
- */
29
- function getHookContent(): string {
30
- return `
31
- ${MARKER_START}
32
- # Safeword architecture check
33
- # This section is managed by safeword - do not edit manually
34
- if [ -f ".safeword/hooks/pre-commit.sh" ]; then
35
- bash .safeword/hooks/pre-commit.sh
36
- fi
37
- ${MARKER_END}
38
- `;
39
- }
40
-
41
- /**
42
- * Install safeword markers into pre-commit hook
43
- */
44
- export function installGitHook(cwd: string): void {
45
- const hooksDir = join(cwd, '.git', 'hooks');
46
- const hookPath = join(hooksDir, 'pre-commit');
47
-
48
- ensureDir(hooksDir);
49
-
50
- let content = '';
51
-
52
- if (exists(hookPath)) {
53
- content = readFile(hookPath);
54
-
55
- // Check if already has safeword markers
56
- if (content.includes(MARKER_START)) {
57
- // Remove existing safeword section and re-add (update)
58
- content = removeMarkerSection(content);
59
- }
60
- } else {
61
- // Create new hook file with shebang
62
- content = '#!/bin/bash\n';
63
- }
64
-
65
- // Add safeword section
66
- content = content.trimEnd() + '\n' + getHookContent();
67
-
68
- writeFile(hookPath, content);
69
- makeExecutable(hookPath);
70
- }
71
-
72
- /**
73
- * Remove safeword markers from pre-commit hook
74
- */
75
- export function removeGitHook(cwd: string): void {
76
- const hookPath = join(cwd, '.git', 'hooks', 'pre-commit');
77
-
78
- if (!exists(hookPath)) return;
79
-
80
- let content = readFile(hookPath);
81
-
82
- if (!content.includes(MARKER_START)) return;
83
-
84
- content = removeMarkerSection(content);
85
-
86
- // If only shebang remains, we could delete the file
87
- // but safer to leave it
88
- writeFile(hookPath, content);
89
- }
90
-
91
- /**
92
- * Remove the section between markers (inclusive)
93
- */
94
- function removeMarkerSection(content: string): string {
95
- const lines = content.split('\n');
96
- const result: string[] = [];
97
- let inMarkerSection = false;
98
-
99
- for (const line of lines) {
100
- if (line.includes(MARKER_START)) {
101
- inMarkerSection = true;
102
- continue;
103
- }
104
- if (line.includes(MARKER_END)) {
105
- inMarkerSection = false;
106
- continue;
107
- }
108
- if (!inMarkerSection) {
109
- result.push(line);
110
- }
111
- }
112
-
113
- return result.join('\n').trim() + '\n';
114
- }
115
-
116
- /**
117
- * Check if git hooks have safeword markers
118
- */
119
- export function hasGitHook(cwd: string): boolean {
120
- const hookPath = join(cwd, '.git', 'hooks', 'pre-commit');
121
- if (!exists(hookPath)) return false;
122
- const content = readFile(hookPath);
123
- return content.includes(MARKER_START);
124
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * Hook utilities for Claude Code settings
3
- */
4
-
5
- /**
6
- * Type guard to check if a value is a hook object with a command property
7
- */
8
- export function isHookObject(h: unknown): h is { command: string } {
9
- return (
10
- typeof h === 'object' &&
11
- h !== null &&
12
- 'command' in h &&
13
- typeof (h as { command: string }).command === 'string'
14
- );
15
- }
16
-
17
- /**
18
- * Check if a hook is a safeword hook (command contains '.safeword')
19
- */
20
- export function isSafewordHook(h: unknown): boolean {
21
- return isHookObject(h) && h.command.includes('.safeword');
22
- }
23
-
24
- /**
25
- * Filter out safeword hooks from an array of hooks
26
- */
27
- export function filterOutSafewordHooks(hooks: unknown[]): unknown[] {
28
- return hooks.filter((h) => !isSafewordHook(h));
29
- }
@@ -1,60 +0,0 @@
1
- /**
2
- * Console output utilities for consistent CLI messaging
3
- */
4
-
5
- /**
6
- * Print info message
7
- */
8
- export function info(message: string): void {
9
- console.log(message);
10
- }
11
-
12
- /**
13
- * Print success message
14
- */
15
- export function success(message: string): void {
16
- console.log(`✓ ${message}`);
17
- }
18
-
19
- /**
20
- * Print warning message
21
- */
22
- export function warn(message: string): void {
23
- console.warn(`⚠ ${message}`);
24
- }
25
-
26
- /**
27
- * Print error message to stderr
28
- */
29
- export function error(message: string): void {
30
- console.error(`✗ ${message}`);
31
- }
32
-
33
- /**
34
- * Print a blank line
35
- */
36
- export function blank(): void {
37
- console.log('');
38
- }
39
-
40
- /**
41
- * Print a section header
42
- */
43
- export function header(title: string): void {
44
- console.log(`\n${title}`);
45
- console.log('─'.repeat(title.length));
46
- }
47
-
48
- /**
49
- * Print a list item
50
- */
51
- export function listItem(item: string, indent = 2): void {
52
- console.log(`${' '.repeat(indent)}• ${item}`);
53
- }
54
-
55
- /**
56
- * Print key-value pair
57
- */
58
- export function keyValue(key: string, value: string): void {
59
- console.log(` ${key}: ${value}`);
60
- }
@@ -1,185 +0,0 @@
1
- /**
2
- * Unit tests for project type detection (Tests 4.1-4.3)
3
- *
4
- * These are pure unit tests for the detectProjectType function.
5
- */
6
-
7
- import { describe, it, expect } from 'vitest';
8
- import { detectProjectType, PackageJson } from './project-detector';
9
-
10
- describe('detectProjectType', () => {
11
- describe('Test 4.1: Detects TypeScript project', () => {
12
- it('should detect typescript from devDependencies', () => {
13
- const packageJson: PackageJson = {
14
- name: 'test',
15
- version: '1.0.0',
16
- devDependencies: {
17
- typescript: '^5.0.0',
18
- },
19
- };
20
-
21
- const result = detectProjectType(packageJson);
22
- expect(result.typescript).toBe(true);
23
- });
24
-
25
- it('should detect typescript from dependencies', () => {
26
- const packageJson: PackageJson = {
27
- name: 'test',
28
- version: '1.0.0',
29
- dependencies: {
30
- typescript: '^5.0.0',
31
- },
32
- };
33
-
34
- const result = detectProjectType(packageJson);
35
- expect(result.typescript).toBe(true);
36
- });
37
-
38
- it('should return false when typescript is not present', () => {
39
- const packageJson: PackageJson = {
40
- name: 'test',
41
- version: '1.0.0',
42
- dependencies: {},
43
- };
44
-
45
- const result = detectProjectType(packageJson);
46
- expect(result.typescript).toBe(false);
47
- });
48
- });
49
-
50
- describe('Test 4.2: Detects React project', () => {
51
- it('should detect react from dependencies', () => {
52
- const packageJson: PackageJson = {
53
- name: 'test',
54
- version: '1.0.0',
55
- dependencies: {
56
- react: '^18.0.0',
57
- },
58
- };
59
-
60
- const result = detectProjectType(packageJson);
61
- expect(result.react).toBe(true);
62
- });
63
-
64
- it('should detect react from devDependencies', () => {
65
- const packageJson: PackageJson = {
66
- name: 'test',
67
- version: '1.0.0',
68
- devDependencies: {
69
- react: '^18.0.0',
70
- },
71
- };
72
-
73
- const result = detectProjectType(packageJson);
74
- expect(result.react).toBe(true);
75
- });
76
-
77
- it('should return false when react is not present', () => {
78
- const packageJson: PackageJson = {
79
- name: 'test',
80
- version: '1.0.0',
81
- dependencies: {},
82
- };
83
-
84
- const result = detectProjectType(packageJson);
85
- expect(result.react).toBe(false);
86
- });
87
- });
88
-
89
- describe('Test 4.3: Detects Next.js project', () => {
90
- it('should detect next.js from dependencies', () => {
91
- const packageJson: PackageJson = {
92
- name: 'test',
93
- version: '1.0.0',
94
- dependencies: {
95
- next: '^14.0.0',
96
- react: '^18.0.0',
97
- },
98
- };
99
-
100
- const result = detectProjectType(packageJson);
101
- expect(result.nextjs).toBe(true);
102
- });
103
-
104
- it('should imply react when next.js is present', () => {
105
- const packageJson: PackageJson = {
106
- name: 'test',
107
- version: '1.0.0',
108
- dependencies: {
109
- next: '^14.0.0',
110
- // Note: react not explicitly listed
111
- },
112
- };
113
-
114
- const result = detectProjectType(packageJson);
115
- expect(result.nextjs).toBe(true);
116
- expect(result.react).toBe(true); // Next.js implies React
117
- });
118
- });
119
-
120
- describe('Detects other frameworks', () => {
121
- it('should detect Astro project', () => {
122
- const packageJson: PackageJson = {
123
- name: 'test',
124
- version: '1.0.0',
125
- dependencies: {
126
- astro: '^4.0.0',
127
- },
128
- };
129
-
130
- const result = detectProjectType(packageJson);
131
- expect(result.astro).toBe(true);
132
- });
133
-
134
- it('should detect Electron project', () => {
135
- const packageJson: PackageJson = {
136
- name: 'test',
137
- version: '1.0.0',
138
- devDependencies: {
139
- electron: '^28.0.0',
140
- },
141
- };
142
-
143
- const result = detectProjectType(packageJson);
144
- expect(result.electron).toBe(true);
145
- });
146
- });
147
-
148
- describe('Handles edge cases', () => {
149
- it('should handle empty package.json', () => {
150
- const packageJson: PackageJson = {};
151
-
152
- const result = detectProjectType(packageJson);
153
-
154
- expect(result.typescript).toBe(false);
155
- expect(result.react).toBe(false);
156
- expect(result.nextjs).toBe(false);
157
- expect(result.astro).toBe(false);
158
- expect(result.electron).toBe(false);
159
- });
160
-
161
- it('should handle complex project with multiple frameworks', () => {
162
- const packageJson: PackageJson = {
163
- name: 'complex-project',
164
- version: '1.0.0',
165
- dependencies: {
166
- next: '^14.0.0',
167
- react: '^18.0.0',
168
- 'react-dom': '^18.0.0',
169
- },
170
- devDependencies: {
171
- typescript: '^5.3.0',
172
- electron: '^28.0.0',
173
- },
174
- };
175
-
176
- const result = detectProjectType(packageJson);
177
-
178
- expect(result.typescript).toBe(true);
179
- expect(result.react).toBe(true);
180
- expect(result.nextjs).toBe(true);
181
- expect(result.electron).toBe(true);
182
- expect(result.astro).toBe(false);
183
- });
184
- });
185
- });
@@ -1,44 +0,0 @@
1
- /**
2
- * Project type detection from package.json
3
- *
4
- * Detects frameworks and tools used in the project to configure
5
- * appropriate linting rules.
6
- */
7
-
8
- export interface PackageJson {
9
- name?: string;
10
- version?: string;
11
- dependencies?: Record<string, string>;
12
- devDependencies?: Record<string, string>;
13
- }
14
-
15
- export interface ProjectType {
16
- typescript: boolean;
17
- react: boolean;
18
- nextjs: boolean;
19
- astro: boolean;
20
- electron: boolean;
21
- }
22
-
23
- /**
24
- * Detects project type from package.json contents
25
- */
26
- export function detectProjectType(packageJson: PackageJson): ProjectType {
27
- const deps = packageJson.dependencies || {};
28
- const devDeps = packageJson.devDependencies || {};
29
- const allDeps = { ...deps, ...devDeps };
30
-
31
- const hasTypescript = 'typescript' in allDeps;
32
- const hasReact = 'react' in deps || 'react' in devDeps;
33
- const hasNextJs = 'next' in deps;
34
- const hasAstro = 'astro' in deps || 'astro' in devDeps;
35
- const hasElectron = 'electron' in deps || 'electron' in devDeps;
36
-
37
- return {
38
- typescript: hasTypescript,
39
- react: hasReact || hasNextJs, // Next.js implies React
40
- nextjs: hasNextJs,
41
- astro: hasAstro,
42
- electron: hasElectron,
43
- };
44
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Version comparison utilities
3
- */
4
-
5
- /**
6
- * Compare two semver versions
7
- * @returns -1 if a < b, 0 if a == b, 1 if a > b
8
- */
9
- export function compareVersions(a: string, b: string): -1 | 0 | 1 {
10
- const aParts = a.split('.').map(Number);
11
- const bParts = b.split('.').map(Number);
12
-
13
- for (let i = 0; i < 3; i++) {
14
- const aVal = aParts[i] ?? 0;
15
- const bVal = bParts[i] ?? 0;
16
- if (aVal < bVal) return -1;
17
- if (aVal > bVal) return 1;
18
- }
19
-
20
- return 0;
21
- }
22
-
23
- /**
24
- * Check if latest version is newer than current
25
- */
26
- export function isNewerVersion(current: string, latest: string): boolean {
27
- return compareVersions(current, latest) === -1;
28
- }
@@ -1,6 +0,0 @@
1
- import { createRequire } from 'node:module';
2
-
3
- const require = createRequire(import.meta.url);
4
- const pkg = require('../package.json') as { version: string };
5
-
6
- export const VERSION = pkg.version;