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.
- 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-AIL5RL45.js +276 -0
- package/dist/setup-AIL5RL45.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,310 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 11: Reset
|
|
3
|
-
*
|
|
4
|
-
* Tests for `safeword reset` command.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
createTempDir,
|
|
10
|
-
removeTempDir,
|
|
11
|
-
createTypeScriptPackageJson,
|
|
12
|
-
createConfiguredProject,
|
|
13
|
-
runCli,
|
|
14
|
-
readTestFile,
|
|
15
|
-
writeTestFile,
|
|
16
|
-
fileExists,
|
|
17
|
-
initGitRepo,
|
|
18
|
-
} from '../helpers';
|
|
19
|
-
|
|
20
|
-
describe('Test Suite 11: Reset', () => {
|
|
21
|
-
let tempDir: string;
|
|
22
|
-
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
tempDir = createTempDir();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
removeTempDir(tempDir);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('Test 11.1: Prompts for confirmation', () => {
|
|
32
|
-
// In TTY mode, should prompt. We test the prompt message content.
|
|
33
|
-
it('should mention removing safeword', async () => {
|
|
34
|
-
await createConfiguredProject(tempDir);
|
|
35
|
-
|
|
36
|
-
// With --yes, it shouldn't prompt but we can check the output
|
|
37
|
-
const result = await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
38
|
-
|
|
39
|
-
// Should mention what it's removing
|
|
40
|
-
const output = result.stdout + result.stderr;
|
|
41
|
-
expect(output.toLowerCase()).toMatch(/remov|reset|safeword/i);
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('Test 11.2: --yes auto-confirms', () => {
|
|
46
|
-
it('should skip confirmation and remove .safeword', async () => {
|
|
47
|
-
await createConfiguredProject(tempDir);
|
|
48
|
-
|
|
49
|
-
expect(fileExists(tempDir, '.safeword')).toBe(true);
|
|
50
|
-
|
|
51
|
-
const result = await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
52
|
-
|
|
53
|
-
expect(result.exitCode).toBe(0);
|
|
54
|
-
expect(fileExists(tempDir, '.safeword')).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe('Test 11.3: No TTY auto-confirms', () => {
|
|
59
|
-
it('should auto-confirm in non-TTY mode', async () => {
|
|
60
|
-
await createConfiguredProject(tempDir);
|
|
61
|
-
|
|
62
|
-
const result = await runCli(['reset'], {
|
|
63
|
-
cwd: tempDir,
|
|
64
|
-
env: { CI: 'true' },
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
// Should complete without hanging
|
|
68
|
-
expect(result.exitCode).toBeDefined();
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('Test 11.4: Removes .safeword directory', () => {
|
|
73
|
-
it('should remove .safeword/ completely', async () => {
|
|
74
|
-
await createConfiguredProject(tempDir);
|
|
75
|
-
|
|
76
|
-
expect(fileExists(tempDir, '.safeword')).toBe(true);
|
|
77
|
-
expect(fileExists(tempDir, '.safeword/SAFEWORD.md')).toBe(true);
|
|
78
|
-
|
|
79
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
80
|
-
|
|
81
|
-
expect(fileExists(tempDir, '.safeword')).toBe(false);
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
describe('Test 11.5: Removes hooks from settings.json', () => {
|
|
86
|
-
it('should remove safeword hooks but preserve custom hooks', async () => {
|
|
87
|
-
await createConfiguredProject(tempDir);
|
|
88
|
-
|
|
89
|
-
// Add a custom hook
|
|
90
|
-
const settings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
91
|
-
settings.hooks.SessionStart = settings.hooks.SessionStart || [];
|
|
92
|
-
settings.hooks.SessionStart.push({
|
|
93
|
-
command: 'echo "Custom preserved hook"',
|
|
94
|
-
description: 'Custom',
|
|
95
|
-
});
|
|
96
|
-
writeTestFile(tempDir, '.claude/settings.json', JSON.stringify(settings, null, 2));
|
|
97
|
-
|
|
98
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
99
|
-
|
|
100
|
-
expect(fileExists(tempDir, '.claude/settings.json')).toBe(true);
|
|
101
|
-
|
|
102
|
-
const updatedSettings = JSON.parse(readTestFile(tempDir, '.claude/settings.json'));
|
|
103
|
-
|
|
104
|
-
// Custom hook preserved
|
|
105
|
-
const hasCustom = updatedSettings.hooks?.SessionStart?.some(
|
|
106
|
-
(h: { command?: string }) => h.command === 'echo "Custom preserved hook"',
|
|
107
|
-
);
|
|
108
|
-
expect(hasCustom).toBe(true);
|
|
109
|
-
|
|
110
|
-
// Safeword hooks removed (no references to .safeword)
|
|
111
|
-
const settingsStr = JSON.stringify(updatedSettings);
|
|
112
|
-
expect(settingsStr).not.toContain('.safeword/hooks');
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('Test 11.6: Removes safeword skills', () => {
|
|
117
|
-
it('should remove safeword-* skill directories', async () => {
|
|
118
|
-
await createConfiguredProject(tempDir);
|
|
119
|
-
|
|
120
|
-
// Verify skills exist after setup
|
|
121
|
-
const skillsExist = fileExists(tempDir, '.claude/skills');
|
|
122
|
-
|
|
123
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
124
|
-
|
|
125
|
-
// After reset, safeword skills should be gone
|
|
126
|
-
// but .claude/skills directory may remain if empty or have other skills
|
|
127
|
-
if (skillsExist) {
|
|
128
|
-
// Check no safeword-* directories remain
|
|
129
|
-
// This would require listing directory contents
|
|
130
|
-
// For now, verify the command completed
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('Test 11.7: Removes git hook markers', () => {
|
|
136
|
-
it('should remove safeword markers from pre-commit', async () => {
|
|
137
|
-
createTypeScriptPackageJson(tempDir);
|
|
138
|
-
initGitRepo(tempDir);
|
|
139
|
-
|
|
140
|
-
// Create custom pre-commit content
|
|
141
|
-
writeTestFile(
|
|
142
|
-
tempDir,
|
|
143
|
-
'.git/hooks/pre-commit',
|
|
144
|
-
`#!/bin/bash
|
|
145
|
-
# Custom content before
|
|
146
|
-
echo "Before safeword"
|
|
147
|
-
|
|
148
|
-
# SAFEWORD_ARCH_CHECK_START
|
|
149
|
-
echo "Safeword check"
|
|
150
|
-
# SAFEWORD_ARCH_CHECK_END
|
|
151
|
-
|
|
152
|
-
# Custom content after
|
|
153
|
-
echo "After safeword"
|
|
154
|
-
`,
|
|
155
|
-
);
|
|
156
|
-
|
|
157
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
158
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
159
|
-
|
|
160
|
-
const content = readTestFile(tempDir, '.git/hooks/pre-commit');
|
|
161
|
-
|
|
162
|
-
// Markers and content between them removed
|
|
163
|
-
expect(content).not.toContain('SAFEWORD_ARCH_CHECK_START');
|
|
164
|
-
expect(content).not.toContain('SAFEWORD_ARCH_CHECK_END');
|
|
165
|
-
expect(content).not.toContain('Safeword check');
|
|
166
|
-
|
|
167
|
-
// Custom content preserved
|
|
168
|
-
expect(content).toContain('Before safeword');
|
|
169
|
-
expect(content).toContain('After safeword');
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
describe('Test 11.8: Removes link from AGENTS.md', () => {
|
|
174
|
-
it('should remove safeword link but preserve other content', async () => {
|
|
175
|
-
await createConfiguredProject(tempDir);
|
|
176
|
-
|
|
177
|
-
// Add custom content to AGENTS.md
|
|
178
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
179
|
-
writeTestFile(tempDir, 'AGENTS.md', content + '\n## My Custom Section\n\nCustom content.\n');
|
|
180
|
-
|
|
181
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
182
|
-
|
|
183
|
-
expect(fileExists(tempDir, 'AGENTS.md')).toBe(true);
|
|
184
|
-
|
|
185
|
-
const updatedContent = readTestFile(tempDir, 'AGENTS.md');
|
|
186
|
-
|
|
187
|
-
// Link removed
|
|
188
|
-
expect(updatedContent).not.toContain('@./.safeword/SAFEWORD.md');
|
|
189
|
-
|
|
190
|
-
// Custom content preserved
|
|
191
|
-
expect(updatedContent).toContain('My Custom Section');
|
|
192
|
-
expect(updatedContent).toContain('Custom content');
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe('Test 11.9: Preserves linting config', () => {
|
|
197
|
-
it('should keep eslint and prettier config', async () => {
|
|
198
|
-
await createConfiguredProject(tempDir);
|
|
199
|
-
|
|
200
|
-
expect(fileExists(tempDir, 'eslint.config.mjs')).toBe(true);
|
|
201
|
-
expect(fileExists(tempDir, '.prettierrc')).toBe(true);
|
|
202
|
-
|
|
203
|
-
const pkgBefore = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
204
|
-
|
|
205
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
206
|
-
|
|
207
|
-
// Linting files preserved
|
|
208
|
-
expect(fileExists(tempDir, 'eslint.config.mjs')).toBe(true);
|
|
209
|
-
expect(fileExists(tempDir, '.prettierrc')).toBe(true);
|
|
210
|
-
|
|
211
|
-
// Scripts preserved
|
|
212
|
-
const pkgAfter = JSON.parse(readTestFile(tempDir, 'package.json'));
|
|
213
|
-
expect(pkgAfter.scripts?.lint).toBe(pkgBefore.scripts?.lint);
|
|
214
|
-
expect(pkgAfter.scripts?.format).toBe(pkgBefore.scripts?.format);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
describe('Test 11.10: Unconfigured project message', () => {
|
|
219
|
-
it('should show nothing to remove message', async () => {
|
|
220
|
-
createTypeScriptPackageJson(tempDir);
|
|
221
|
-
// No setup
|
|
222
|
-
|
|
223
|
-
const result = await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
224
|
-
|
|
225
|
-
expect(result.exitCode).toBe(0);
|
|
226
|
-
expect(result.stdout.toLowerCase()).toMatch(/nothing|already|not configured/i);
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
describe('Test 11.11: Removes safeword slash commands', () => {
|
|
231
|
-
it('should remove safeword commands but preserve custom ones', async () => {
|
|
232
|
-
await createConfiguredProject(tempDir);
|
|
233
|
-
|
|
234
|
-
// Verify commands directory exists after setup
|
|
235
|
-
expect(fileExists(tempDir, '.claude/commands')).toBe(true);
|
|
236
|
-
|
|
237
|
-
// Add a custom command that should be preserved
|
|
238
|
-
writeTestFile(
|
|
239
|
-
tempDir,
|
|
240
|
-
'.claude/commands/my-custom-command.md',
|
|
241
|
-
'# My Custom Command\n\nDo something custom.',
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
245
|
-
|
|
246
|
-
// Custom command should be preserved
|
|
247
|
-
expect(fileExists(tempDir, '.claude/commands/my-custom-command.md')).toBe(true);
|
|
248
|
-
const customContent = readTestFile(tempDir, '.claude/commands/my-custom-command.md');
|
|
249
|
-
expect(customContent).toContain('My Custom Command');
|
|
250
|
-
|
|
251
|
-
// Safeword commands should be removed (quality-review, arch-review, lint)
|
|
252
|
-
expect(fileExists(tempDir, '.claude/commands/quality-review.md')).toBe(false);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
describe('Test 11.12: Removes MCP servers from .mcp.json', () => {
|
|
257
|
-
it('should remove context7 and playwright servers', async () => {
|
|
258
|
-
await createConfiguredProject(tempDir);
|
|
259
|
-
|
|
260
|
-
// Verify MCP config exists
|
|
261
|
-
expect(fileExists(tempDir, '.mcp.json')).toBe(true);
|
|
262
|
-
|
|
263
|
-
// Add a custom MCP server
|
|
264
|
-
const mcpConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
265
|
-
mcpConfig.mcpServers['my-custom-server'] = {
|
|
266
|
-
command: 'my-server',
|
|
267
|
-
args: ['--port', '3000'],
|
|
268
|
-
};
|
|
269
|
-
writeTestFile(tempDir, '.mcp.json', JSON.stringify(mcpConfig, null, 2));
|
|
270
|
-
|
|
271
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
272
|
-
|
|
273
|
-
// .mcp.json should still exist with custom server
|
|
274
|
-
expect(fileExists(tempDir, '.mcp.json')).toBe(true);
|
|
275
|
-
|
|
276
|
-
const updatedConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
277
|
-
|
|
278
|
-
// Custom server preserved
|
|
279
|
-
expect(updatedConfig.mcpServers['my-custom-server']).toBeDefined();
|
|
280
|
-
expect(updatedConfig.mcpServers['my-custom-server'].command).toBe('my-server');
|
|
281
|
-
|
|
282
|
-
// Safeword servers removed
|
|
283
|
-
expect(updatedConfig.mcpServers.context7).toBeUndefined();
|
|
284
|
-
expect(updatedConfig.mcpServers.playwright).toBeUndefined();
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should delete or empty .mcp.json if only safeword servers remain', async () => {
|
|
288
|
-
await createConfiguredProject(tempDir);
|
|
289
|
-
|
|
290
|
-
// Overwrite with only safeword servers
|
|
291
|
-
const mcpConfig = {
|
|
292
|
-
mcpServers: {
|
|
293
|
-
context7: { command: 'npx', args: ['@context7/mcp'] },
|
|
294
|
-
playwright: { command: 'npx', args: ['@playwright/mcp'] },
|
|
295
|
-
},
|
|
296
|
-
};
|
|
297
|
-
writeTestFile(tempDir, '.mcp.json', JSON.stringify(mcpConfig, null, 2));
|
|
298
|
-
|
|
299
|
-
await runCli(['reset', '--yes'], { cwd: tempDir });
|
|
300
|
-
|
|
301
|
-
// Either .mcp.json is deleted OR mcpServers is empty
|
|
302
|
-
if (fileExists(tempDir, '.mcp.json')) {
|
|
303
|
-
const updatedConfig = JSON.parse(readTestFile(tempDir, '.mcp.json'));
|
|
304
|
-
const serverCount = Object.keys(updatedConfig.mcpServers || {}).length;
|
|
305
|
-
expect(serverCount).toBe(0);
|
|
306
|
-
}
|
|
307
|
-
// If file doesn't exist, test passes implicitly
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
});
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 12: AGENTS.md Self-Healing
|
|
3
|
-
*
|
|
4
|
-
* Tests for SessionStart hook that maintains AGENTS.md link.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import { execSync } from 'node:child_process';
|
|
9
|
-
import { join } from 'node:path';
|
|
10
|
-
import {
|
|
11
|
-
createTempDir,
|
|
12
|
-
removeTempDir,
|
|
13
|
-
createConfiguredProject,
|
|
14
|
-
runCli,
|
|
15
|
-
readTestFile,
|
|
16
|
-
writeTestFile,
|
|
17
|
-
fileExists,
|
|
18
|
-
measureTimeSync,
|
|
19
|
-
} from '../helpers';
|
|
20
|
-
import { unlinkSync } from 'node:fs';
|
|
21
|
-
|
|
22
|
-
describe('Test Suite 12: AGENTS.md Self-Healing', () => {
|
|
23
|
-
let tempDir: string;
|
|
24
|
-
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
tempDir = createTempDir();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
removeTempDir(tempDir);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Helper to run the self-healing hook script
|
|
35
|
-
*/
|
|
36
|
-
function runSelfHealingHook(dir: string): { stdout: string; exitCode: number } {
|
|
37
|
-
// The hook script location depends on implementation
|
|
38
|
-
// Typically: .safeword/hooks/agents-md-check.sh
|
|
39
|
-
const hookPath = join(dir, '.safeword/hooks/agents-md-check.sh');
|
|
40
|
-
|
|
41
|
-
if (!fileExists(dir, '.safeword/hooks/agents-md-check.sh')) {
|
|
42
|
-
// Hook may have different name - check for any agents-related hook
|
|
43
|
-
// For now, return a placeholder
|
|
44
|
-
return { stdout: '', exitCode: 0 };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const stdout = execSync(`bash "${hookPath}"`, {
|
|
49
|
-
cwd: dir,
|
|
50
|
-
encoding: 'utf-8',
|
|
51
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
52
|
-
});
|
|
53
|
-
return { stdout, exitCode: 0 };
|
|
54
|
-
} catch (error: unknown) {
|
|
55
|
-
const execError = error as { stdout?: string; status?: number };
|
|
56
|
-
return {
|
|
57
|
-
stdout: execError.stdout ?? '',
|
|
58
|
-
exitCode: execError.status ?? 1,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
describe('Test 12.1: Hook detects missing link', () => {
|
|
64
|
-
it('should detect when safeword link is missing', async () => {
|
|
65
|
-
await createConfiguredProject(tempDir);
|
|
66
|
-
|
|
67
|
-
// Remove the safeword link from AGENTS.md
|
|
68
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
69
|
-
const withoutLink = content
|
|
70
|
-
.split('\n')
|
|
71
|
-
.filter(line => !line.includes('@./.safeword/SAFEWORD.md'))
|
|
72
|
-
.join('\n');
|
|
73
|
-
writeTestFile(tempDir, 'AGENTS.md', withoutLink);
|
|
74
|
-
|
|
75
|
-
const result = runSelfHealingHook(tempDir);
|
|
76
|
-
|
|
77
|
-
// Hook should indicate repair is needed or perform repair
|
|
78
|
-
// The exact output depends on implementation
|
|
79
|
-
expect(result.exitCode).toBeDefined();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
describe('Test 12.2: Hook re-adds missing link', () => {
|
|
84
|
-
it('should restore removed link', async () => {
|
|
85
|
-
await createConfiguredProject(tempDir);
|
|
86
|
-
|
|
87
|
-
// Remove the safeword link
|
|
88
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
89
|
-
const withoutLink = '# My Project\n\nSome content without the link.\n';
|
|
90
|
-
writeTestFile(tempDir, 'AGENTS.md', withoutLink);
|
|
91
|
-
|
|
92
|
-
// Run hook
|
|
93
|
-
runSelfHealingHook(tempDir);
|
|
94
|
-
|
|
95
|
-
// Link should be restored
|
|
96
|
-
const updatedContent = readTestFile(tempDir, 'AGENTS.md');
|
|
97
|
-
expect(updatedContent).toContain('@./.safeword/SAFEWORD.md');
|
|
98
|
-
|
|
99
|
-
// Original content preserved
|
|
100
|
-
expect(updatedContent).toContain('My Project');
|
|
101
|
-
expect(updatedContent).toContain('Some content');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Test 12.3: Hook shows warning on restoration', () => {
|
|
106
|
-
it('should output message when restoring', async () => {
|
|
107
|
-
await createConfiguredProject(tempDir);
|
|
108
|
-
|
|
109
|
-
// Remove link
|
|
110
|
-
writeTestFile(tempDir, 'AGENTS.md', '# No link\n');
|
|
111
|
-
|
|
112
|
-
const result = runSelfHealingHook(tempDir);
|
|
113
|
-
|
|
114
|
-
// Should mention restoration
|
|
115
|
-
const output = result.stdout.toLowerCase();
|
|
116
|
-
expect(output).toMatch(/restor|repair|add|fix|agents/i);
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
describe('Test 12.4: Hook recreates deleted AGENTS.md', () => {
|
|
121
|
-
it('should recreate AGENTS.md if deleted', async () => {
|
|
122
|
-
await createConfiguredProject(tempDir);
|
|
123
|
-
|
|
124
|
-
// Delete AGENTS.md entirely
|
|
125
|
-
unlinkSync(join(tempDir, 'AGENTS.md'));
|
|
126
|
-
expect(fileExists(tempDir, 'AGENTS.md')).toBe(false);
|
|
127
|
-
|
|
128
|
-
// Run hook
|
|
129
|
-
runSelfHealingHook(tempDir);
|
|
130
|
-
|
|
131
|
-
// AGENTS.md should be recreated
|
|
132
|
-
expect(fileExists(tempDir, 'AGENTS.md')).toBe(true);
|
|
133
|
-
|
|
134
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
135
|
-
expect(content).toContain('@./.safeword/SAFEWORD.md');
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('Test 12.5: Hook prevents duplicates', () => {
|
|
140
|
-
it('should not add duplicate links', async () => {
|
|
141
|
-
await createConfiguredProject(tempDir);
|
|
142
|
-
|
|
143
|
-
// Verify link exists
|
|
144
|
-
const contentBefore = readTestFile(tempDir, 'AGENTS.md');
|
|
145
|
-
expect(contentBefore).toContain('@./.safeword/SAFEWORD.md');
|
|
146
|
-
|
|
147
|
-
// Run hook multiple times
|
|
148
|
-
runSelfHealingHook(tempDir);
|
|
149
|
-
runSelfHealingHook(tempDir);
|
|
150
|
-
runSelfHealingHook(tempDir);
|
|
151
|
-
|
|
152
|
-
// Count links
|
|
153
|
-
const contentAfter = readTestFile(tempDir, 'AGENTS.md');
|
|
154
|
-
const linkCount = (contentAfter.match(/@\.\/\.safeword\/SAFEWORD\.md/g) || []).length;
|
|
155
|
-
|
|
156
|
-
expect(linkCount).toBe(1);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('Test 12.6: Hook exits cleanly', () => {
|
|
161
|
-
it('should exit with code 0 and complete quickly', async () => {
|
|
162
|
-
await createConfiguredProject(tempDir);
|
|
163
|
-
|
|
164
|
-
const { result, timeMs } = measureTimeSync(() => runSelfHealingHook(tempDir));
|
|
165
|
-
|
|
166
|
-
expect(result.exitCode).toBe(0);
|
|
167
|
-
expect(timeMs).toBeLessThan(1000); // Should complete in under 1 second
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
});
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 5: Setup Blocks on Existing
|
|
3
|
-
*
|
|
4
|
-
* Tests for setup error when already configured.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import { mkdirSync } from 'node:fs';
|
|
9
|
-
import { join } from 'node:path';
|
|
10
|
-
import {
|
|
11
|
-
createTempDir,
|
|
12
|
-
removeTempDir,
|
|
13
|
-
createTypeScriptPackageJson,
|
|
14
|
-
runCli,
|
|
15
|
-
readTestFile,
|
|
16
|
-
writeTestFile,
|
|
17
|
-
fileExists,
|
|
18
|
-
} from '../helpers';
|
|
19
|
-
|
|
20
|
-
describe('Test Suite 5: Setup Blocks on Existing', () => {
|
|
21
|
-
let tempDir: string;
|
|
22
|
-
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
tempDir = createTempDir();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
removeTempDir(tempDir);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('Test 5.1: Error when .safeword exists', () => {
|
|
32
|
-
it('should error with exit 1 when .safeword/ already exists', async () => {
|
|
33
|
-
createTypeScriptPackageJson(tempDir);
|
|
34
|
-
|
|
35
|
-
// Create existing .safeword directory
|
|
36
|
-
mkdirSync(join(tempDir, '.safeword'));
|
|
37
|
-
|
|
38
|
-
const result = await runCli(['setup'], { cwd: tempDir });
|
|
39
|
-
|
|
40
|
-
expect(result.exitCode).toBe(1);
|
|
41
|
-
expect(result.stderr.toLowerCase()).toContain('already configured');
|
|
42
|
-
expect(result.stderr.toLowerCase()).toContain('upgrade');
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('Test 5.2: No files modified on error', () => {
|
|
47
|
-
it('should not modify files when erroring', async () => {
|
|
48
|
-
createTypeScriptPackageJson(tempDir);
|
|
49
|
-
|
|
50
|
-
// Create existing .safeword directory
|
|
51
|
-
mkdirSync(join(tempDir, '.safeword'));
|
|
52
|
-
|
|
53
|
-
// Create AGENTS.md with known content
|
|
54
|
-
const originalContent = '# Original AGENTS.md\n\nThis should not change.\n';
|
|
55
|
-
writeTestFile(tempDir, 'AGENTS.md', originalContent);
|
|
56
|
-
|
|
57
|
-
const result = await runCli(['setup'], { cwd: tempDir });
|
|
58
|
-
|
|
59
|
-
expect(result.exitCode).toBe(1);
|
|
60
|
-
|
|
61
|
-
// AGENTS.md should be unchanged
|
|
62
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
63
|
-
expect(content).toBe(originalContent);
|
|
64
|
-
|
|
65
|
-
// No new files should be created
|
|
66
|
-
expect(fileExists(tempDir, '.claude')).toBe(false);
|
|
67
|
-
expect(fileExists(tempDir, 'eslint.config.mjs')).toBe(false);
|
|
68
|
-
expect(fileExists(tempDir, '.prettierrc')).toBe(false);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Suite 2: Setup - Core Files
|
|
3
|
-
*
|
|
4
|
-
* Tests for .safeword/ directory creation and AGENTS.md handling.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
createTempDir,
|
|
10
|
-
removeTempDir,
|
|
11
|
-
createTypeScriptPackageJson,
|
|
12
|
-
runCli,
|
|
13
|
-
readTestFile,
|
|
14
|
-
writeTestFile,
|
|
15
|
-
fileExists,
|
|
16
|
-
initGitRepo,
|
|
17
|
-
createConfiguredProject,
|
|
18
|
-
} from '../helpers';
|
|
19
|
-
|
|
20
|
-
describe('Test Suite 2: Setup - Core Files', () => {
|
|
21
|
-
let tempDir: string;
|
|
22
|
-
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
tempDir = createTempDir();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterEach(() => {
|
|
28
|
-
removeTempDir(tempDir);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('Test 2.1: Creates .safeword directory structure', () => {
|
|
32
|
-
it('should create complete .safeword/ directory', async () => {
|
|
33
|
-
createTypeScriptPackageJson(tempDir);
|
|
34
|
-
initGitRepo(tempDir);
|
|
35
|
-
|
|
36
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
37
|
-
|
|
38
|
-
expect(result.exitCode).toBe(0);
|
|
39
|
-
|
|
40
|
-
// Core structure
|
|
41
|
-
expect(fileExists(tempDir, '.safeword')).toBe(true);
|
|
42
|
-
expect(fileExists(tempDir, '.safeword/SAFEWORD.md')).toBe(true);
|
|
43
|
-
expect(fileExists(tempDir, '.safeword/version')).toBe(true);
|
|
44
|
-
|
|
45
|
-
// Subdirectories
|
|
46
|
-
expect(fileExists(tempDir, '.safeword/guides')).toBe(true);
|
|
47
|
-
expect(fileExists(tempDir, '.safeword/templates')).toBe(true);
|
|
48
|
-
expect(fileExists(tempDir, '.safeword/hooks')).toBe(true);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should write CLI version to .safeword/version', async () => {
|
|
52
|
-
createTypeScriptPackageJson(tempDir);
|
|
53
|
-
initGitRepo(tempDir);
|
|
54
|
-
|
|
55
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
56
|
-
|
|
57
|
-
const version = readTestFile(tempDir, '.safeword/version').trim();
|
|
58
|
-
// Should be semver format
|
|
59
|
-
expect(version).toMatch(/^\d+\.\d+\.\d+(-[\w.]+)?$/);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('Test 2.2: Creates AGENTS.md if missing', () => {
|
|
64
|
-
it('should create AGENTS.md with safeword link', async () => {
|
|
65
|
-
createTypeScriptPackageJson(tempDir);
|
|
66
|
-
initGitRepo(tempDir);
|
|
67
|
-
|
|
68
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
69
|
-
|
|
70
|
-
expect(fileExists(tempDir, 'AGENTS.md')).toBe(true);
|
|
71
|
-
|
|
72
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
73
|
-
expect(content).toContain('**⚠️ ALWAYS READ FIRST: @./.safeword/SAFEWORD.md**');
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
describe('Test 2.3: Prepends link to existing AGENTS.md', () => {
|
|
78
|
-
it('should prepend link without losing content', async () => {
|
|
79
|
-
createTypeScriptPackageJson(tempDir);
|
|
80
|
-
initGitRepo(tempDir);
|
|
81
|
-
|
|
82
|
-
// Create existing AGENTS.md
|
|
83
|
-
const existingContent = '# My Project\n\nExisting content here.\n';
|
|
84
|
-
writeTestFile(tempDir, 'AGENTS.md', existingContent);
|
|
85
|
-
|
|
86
|
-
await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
87
|
-
|
|
88
|
-
const content = readTestFile(tempDir, 'AGENTS.md');
|
|
89
|
-
|
|
90
|
-
// Link should be first
|
|
91
|
-
const lines = content.split('\n');
|
|
92
|
-
expect(lines[0]).toContain('**⚠️ ALWAYS READ FIRST: @./.safeword/SAFEWORD.md**');
|
|
93
|
-
|
|
94
|
-
// Original content preserved
|
|
95
|
-
expect(content).toContain('# My Project');
|
|
96
|
-
expect(content).toContain('Existing content here.');
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe('Test 2.4: No duplicate links in AGENTS.md on upgrade', () => {
|
|
101
|
-
it('should not add duplicate link on upgrade', async () => {
|
|
102
|
-
// First setup
|
|
103
|
-
await createConfiguredProject(tempDir);
|
|
104
|
-
|
|
105
|
-
// Verify link exists
|
|
106
|
-
const contentBefore = readTestFile(tempDir, 'AGENTS.md');
|
|
107
|
-
const linkCount = (contentBefore.match(/@\.\/\.safeword\/SAFEWORD\.md/g) || []).length;
|
|
108
|
-
expect(linkCount).toBe(1);
|
|
109
|
-
|
|
110
|
-
// Run upgrade
|
|
111
|
-
await runCli(['upgrade'], { cwd: tempDir });
|
|
112
|
-
|
|
113
|
-
// Count links after
|
|
114
|
-
const contentAfter = readTestFile(tempDir, 'AGENTS.md');
|
|
115
|
-
const linkCountAfter = (contentAfter.match(/@\.\/\.safeword\/SAFEWORD\.md/g) || []).length;
|
|
116
|
-
|
|
117
|
-
expect(linkCountAfter).toBe(1);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('Test 2.5: Prints summary of created files', () => {
|
|
122
|
-
it('should output summary of created files', async () => {
|
|
123
|
-
createTypeScriptPackageJson(tempDir);
|
|
124
|
-
initGitRepo(tempDir);
|
|
125
|
-
|
|
126
|
-
const result = await runCli(['setup', '--yes'], { cwd: tempDir });
|
|
127
|
-
|
|
128
|
-
expect(result.exitCode).toBe(0);
|
|
129
|
-
|
|
130
|
-
// Should mention what was created
|
|
131
|
-
expect(result.stdout).toMatch(/created|Created/i);
|
|
132
|
-
expect(result.stdout).toMatch(/\.safeword|safeword/i);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
});
|