sumulige-claude 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/.claude/hooks/hook-registry.json +0 -15
  2. package/.claude/rules/coding-style.md +18 -7
  3. package/.claude/rules/hooks.md +15 -4
  4. package/.claude/rules/performance.md +15 -5
  5. package/.claude/rules/security.md +140 -4
  6. package/.claude/rules/testing.md +138 -9
  7. package/.claude/rules/web-design-standard.md +16 -5
  8. package/.claude/skills/algorithmic-art/metadata.yaml +28 -0
  9. package/.claude/skills/api-tester/SKILL.md +61 -0
  10. package/.claude/skills/api-tester/examples/basic.md +3 -0
  11. package/.claude/skills/api-tester/metadata.yaml +30 -0
  12. package/.claude/skills/api-tester/templates/default.md +3 -0
  13. package/.claude/skills/brand-guidelines/metadata.yaml +26 -0
  14. package/.claude/skills/canvas-design/metadata.yaml +27 -0
  15. package/.claude/skills/code-reviewer-123/SKILL.md +61 -0
  16. package/.claude/skills/code-reviewer-123/examples/basic.md +3 -0
  17. package/.claude/skills/code-reviewer-123/metadata.yaml +30 -0
  18. package/.claude/skills/code-reviewer-123/templates/default.md +3 -0
  19. package/.claude/skills/doc-coauthoring/metadata.yaml +27 -0
  20. package/.claude/skills/docx/metadata.yaml +30 -0
  21. package/.claude/skills/frontend-design/metadata.yaml +28 -0
  22. package/.claude/skills/internal-comms/metadata.yaml +28 -0
  23. package/.claude/skills/mcp-builder/metadata.yaml +26 -0
  24. package/.claude/skills/my-skill/SKILL.md +61 -0
  25. package/.claude/skills/my-skill/examples/basic.md +3 -0
  26. package/.claude/skills/my-skill/metadata.yaml +30 -0
  27. package/.claude/skills/my-skill/templates/default.md +3 -0
  28. package/.claude/skills/pdf/metadata.yaml +29 -0
  29. package/.claude/skills/pptx/metadata.yaml +29 -0
  30. package/.claude/skills/react-best-practices/metadata.yaml +26 -0
  31. package/.claude/skills/react-node-practices/SKILL.md +409 -0
  32. package/.claude/skills/react-node-practices/metadata.yaml +56 -0
  33. package/.claude/skills/skill-creator/metadata.yaml +25 -0
  34. package/.claude/skills/slack-gif-creator/metadata.yaml +28 -0
  35. package/.claude/skills/test-skill-name/SKILL.md +61 -0
  36. package/.claude/skills/test-skill-name/examples/basic.md +3 -0
  37. package/.claude/skills/test-skill-name/metadata.yaml +30 -0
  38. package/.claude/skills/test-skill-name/templates/default.md +3 -0
  39. package/.claude/skills/test-workflow/metadata.yaml +32 -0
  40. package/.claude/skills/theme-factory/metadata.yaml +26 -0
  41. package/.claude/skills/threejs-fundamentals/metadata.yaml +27 -0
  42. package/.claude/skills/web-artifacts-builder/metadata.yaml +30 -0
  43. package/.claude/skills/web-design-guidelines/metadata.yaml +26 -0
  44. package/.claude/skills/webapp-testing/metadata.yaml +26 -0
  45. package/.claude/skills/xlsx/metadata.yaml +29 -0
  46. package/LICENSE +21 -0
  47. package/README.md +280 -529
  48. package/cli.js +19 -3
  49. package/package.json +29 -3
  50. package/template/.codex/README.md +69 -0
  51. package/template/.codex/config.toml +56 -0
  52. package/template/AGENTS.md +94 -0
  53. package/.claude/.kickoff-hint.txt +0 -52
  54. package/.claude/.sumulige-claude-version +0 -1
  55. package/.claude/.version +0 -1
  56. package/.claude/AGENTS.md +0 -42
  57. package/.claude/ANCHORS.md +0 -40
  58. package/.claude/CLAUDE.md +0 -138
  59. package/.claude/MEMORY.md +0 -69
  60. package/.claude/PROJECT_LOG.md +0 -101
  61. package/.claude/THINKING_CHAIN_GUIDE.md +0 -287
  62. package/.claude/USAGE.md +0 -175
  63. package/.claude/boris-optimizations.md +0 -167
  64. package/.claude/handoffs/INDEX.md +0 -21
  65. package/.claude/handoffs/LATEST.md +0 -76
  66. package/.claude/handoffs/handoff_2026-01-22T13-07-04-757Z.md +0 -76
  67. package/.claude/quality-gate.json +0 -82
  68. package/.claude/rag/skill-index.json +0 -135
  69. package/.claude/settings.json +0 -99
  70. package/.claude/settings.local.json +0 -175
  71. package/.claude/templates/PROJECT_KICKOFF.md +0 -89
  72. package/.claude/templates/PROJECT_PROPOSAL.md +0 -227
  73. package/.claude/templates/TASK_PLAN.md +0 -121
  74. package/.claude/templates/hooks/README.md +0 -302
  75. package/.claude/templates/hooks/hook.sh.template +0 -94
  76. package/.claude/templates/hooks/user-prompt-submit.cjs.template +0 -116
  77. package/.claude/templates/hooks/user-response-submit.cjs.template +0 -94
  78. package/.claude/templates/hooks/validate.js +0 -173
  79. package/.claude/templates/tasks/develop.md +0 -69
  80. package/.claude/templates/tasks/research.md +0 -64
  81. package/.claude/templates/tasks/test.md +0 -96
  82. package/.claude/thinking-routes/.last-sync +0 -1
  83. package/.claude/thinking-routes/QUICKREF.md +0 -98
  84. package/.claude/workflow/document-scanner.js +0 -426
  85. package/.claude/workflow/knowledge-engine.js +0 -941
  86. package/.claude/workflow/notebooklm/browser.js +0 -1028
  87. package/.claude/workflow/phases/phase1-research.js +0 -578
  88. package/.claude/workflow/phases/phase1-research.ts +0 -465
  89. package/.claude/workflow/phases/phase2-approve.js +0 -722
  90. package/.claude/workflow/phases/phase3-plan.js +0 -1200
  91. package/.claude/workflow/phases/phase4-develop.js +0 -894
  92. package/.claude/workflow/search-cache.js +0 -230
  93. package/.claude/workflow/templates/approval.md +0 -315
  94. package/.claude/workflow/templates/development.md +0 -377
  95. package/.claude/workflow/templates/planning.md +0 -328
  96. package/.claude/workflow/templates/research.md +0 -250
  97. package/.claude/workflow/types.js +0 -37
  98. package/.claude/workflow/web-search.js +0 -278
  99. package/.claude-plugin/marketplace.json +0 -71
  100. package/.github/workflows/sync-skills.yml +0 -74
  101. package/.versionrc +0 -25
  102. package/AGENTS.md +0 -580
  103. package/CHANGELOG.md +0 -481
  104. package/CLAUDE-template.md +0 -114
  105. package/DEV_TOOLS_GUIDE.md +0 -190
  106. package/PROJECT_STRUCTURE.md +0 -266
  107. package/Q&A.md +0 -325
  108. package/config/defaults.json +0 -34
  109. package/config/official-skills.json +0 -183
  110. package/config/quality-gate.json +0 -67
  111. package/config/skill-categories.json +0 -40
  112. package/config/version-manifest.json +0 -85
  113. package/demos/power-3d-scatter.html +0 -683
  114. package/development/cache/web-search/search_1193d605f8eb364651fc2f2041b58a31.json +0 -36
  115. package/development/cache/web-search/search_3798bf06960edc125f744a1abb5b72c5.json +0 -36
  116. package/development/cache/web-search/search_37c7d4843a53f0d83f1122a6f908a2a3.json +0 -36
  117. package/development/cache/web-search/search_44166fa0153709ee168485a22aa0ab40.json +0 -36
  118. package/development/cache/web-search/search_4deaebb1f77e86a8ca066dc5a49c59fd.json +0 -36
  119. package/development/cache/web-search/search_94da91789466070a7f545612e73c7372.json +0 -36
  120. package/development/cache/web-search/search_dd5de8491b8b803a3cb01339cd210fb0.json +0 -36
  121. package/development/knowledge-base/.index.clean.json +0 -1
  122. package/development/knowledge-base/.index.json +0 -486
  123. package/development/knowledge-base/test-best-practices.md +0 -29
  124. package/development/projects/proj_mkh1pazz_ixmt1/phase1/feasibility-report.md +0 -160
  125. package/development/projects/proj_mkh4jvnb_z7rwf/phase1/feasibility-report.md +0 -160
  126. package/development/projects/proj_mkh4jxkd_ewz5a/phase1/feasibility-report.md +0 -160
  127. package/development/projects/proj_mkh4k84n_ni73k/phase1/feasibility-report.md +0 -160
  128. package/development/projects/proj_mkh4wfyd_u9w88/phase1/feasibility-report.md +0 -160
  129. package/development/projects/proj_mkh4wsbo_iahvf/development/projects/proj_mkh4xbpg_4na5w/phase1/feasibility-report.md +0 -160
  130. package/development/projects/proj_mkh4wsbo_iahvf/phase1/feasibility-report.md +0 -160
  131. package/development/projects/proj_mkh4xulg_1ka8x/phase1/feasibility-report.md +0 -160
  132. package/development/projects/proj_mkh4xwhj_gch8j/phase1/feasibility-report.md +0 -160
  133. package/development/projects/proj_mkh4y2qk_9lm8z/phase1/feasibility-report.md +0 -160
  134. package/development/projects/proj_mkh4y2qk_9lm8z/phase2/requirements.md +0 -226
  135. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/PRD.md +0 -345
  136. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/TASK_PLAN.md +0 -284
  137. package/development/projects/proj_mkh4y2qk_9lm8z/phase3/prototype/README.md +0 -14
  138. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/DEVELOPMENT_LOG.md +0 -35
  139. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/TASKS.md +0 -34
  140. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/.env.example +0 -5
  141. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/README.md +0 -60
  142. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/package.json +0 -25
  143. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/index.js +0 -70
  144. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/src/routes/index.js +0 -48
  145. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/health.test.js +0 -20
  146. package/development/projects/proj_mkh4y2qk_9lm8z/phase4/source/tests/jest.config.js +0 -21
  147. package/development/projects/proj_mkh7veqg_3lypc/phase1/feasibility-report.md +0 -160
  148. package/development/projects/proj_mkh7veqg_3lypc/phase2/requirements.md +0 -226
  149. package/development/projects/proj_mkh7veqg_3lypc/phase3/PRD.md +0 -345
  150. package/development/projects/proj_mkh7veqg_3lypc/phase3/TASK_PLAN.md +0 -284
  151. package/development/projects/proj_mkh7veqg_3lypc/phase3/prototype/README.md +0 -14
  152. package/development/projects/proj_mkh8k8fo_rmqn5/phase1/feasibility-report.md +0 -160
  153. package/development/projects/proj_mkh8xyhy_1vshq/phase1/feasibility-report.md +0 -178
  154. package/development/projects/proj_mkh8zddd_dhamf/phase1/feasibility-report.md +0 -377
  155. package/development/projects/proj_mkh8zddd_dhamf/phase2/requirements.md +0 -442
  156. package/development/projects/proj_mkh8zddd_dhamf/phase3/api-design.md +0 -800
  157. package/development/projects/proj_mkh8zddd_dhamf/phase3/architecture.md +0 -625
  158. package/development/projects/proj_mkh8zddd_dhamf/phase3/data-model.md +0 -830
  159. package/development/projects/proj_mkh8zddd_dhamf/phase3/risks.md +0 -957
  160. package/development/projects/proj_mkh8zddd_dhamf/phase3/wbs.md +0 -381
  161. package/development/todos/.state.json +0 -19
  162. package/development/todos/INDEX.md +0 -63
  163. package/development/todos/active/_README.md +0 -49
  164. package/development/todos/archived/_README.md +0 -11
  165. package/development/todos/backlog/_README.md +0 -11
  166. package/development/todos/backlog/mcp-integration.md +0 -35
  167. package/development/todos/completed/_README.md +0 -11
  168. package/development/todos/completed/boris-optimizations.md +0 -39
  169. package/development/todos/completed/develop/local-knowledge-index.md +0 -85
  170. package/development/todos/completed/develop/todo-system.md +0 -47
  171. package/development/todos/completed/develop/web-search-integration.md +0 -83
  172. package/development/todos/completed/test/phase1-e2e-test.md +0 -103
  173. package/docs/DEVELOPMENT.md +0 -461
  174. package/docs/MARKETPLACE.md +0 -352
  175. package/docs/RELEASE.md +0 -93
  176. package/jest.config.js +0 -63
  177. package/lib/commands.js +0 -3588
  178. package/lib/config-manager.js +0 -441
  179. package/lib/config-schema.js +0 -408
  180. package/lib/config-validator.js +0 -330
  181. package/lib/config.js +0 -122
  182. package/lib/errors.js +0 -305
  183. package/lib/incremental-sync.js +0 -274
  184. package/lib/marketplace.js +0 -487
  185. package/lib/migrations.js +0 -154
  186. package/lib/permission-audit.js +0 -255
  187. package/lib/quality-gate.js +0 -431
  188. package/lib/quality-rules.js +0 -373
  189. package/lib/utils.js +0 -150
  190. package/lib/version-check.js +0 -169
  191. package/lib/version-manifest.js +0 -171
  192. package/project-paradigm.md +0 -313
  193. package/prompts/how-to-find.md +0 -163
  194. package/prompts/linus-architect.md +0 -71
  195. package/prompts/software-architect.md +0 -173
  196. package/prompts/web-designer.md +0 -249
  197. package/scripts/fix-hooks.mjs +0 -97
  198. package/scripts/sync-external.mjs +0 -298
  199. package/scripts/sync-to-home.sh +0 -108
  200. package/scripts/update-registry.mjs +0 -325
  201. package/sources.yaml +0 -83
  202. package/tests/README.md +0 -263
  203. package/tests/commands.test.js +0 -1086
  204. package/tests/config-manager.test.js +0 -677
  205. package/tests/config-schema.test.js +0 -425
  206. package/tests/config-validator.test.js +0 -436
  207. package/tests/config.test.js +0 -100
  208. package/tests/errors.test.js +0 -477
  209. package/tests/manual/phase1-e2e.sh +0 -389
  210. package/tests/manual/phase2-test-cases.md +0 -311
  211. package/tests/manual/phase3-test-cases.md +0 -309
  212. package/tests/manual/phase4-test-cases.md +0 -414
  213. package/tests/manual/test-cases.md +0 -417
  214. package/tests/marketplace.test.js +0 -420
  215. package/tests/migrations.test.js +0 -187
  216. package/tests/quality-gate.test.js +0 -679
  217. package/tests/quality-rules.test.js +0 -619
  218. package/tests/sync-external.test.js +0 -214
  219. package/tests/update-registry.test.js +0 -251
  220. package/tests/utils.test.js +0 -171
  221. package/tests/version-check.test.js +0 -75
  222. package/tests/web-search.test.js +0 -392
  223. package/thinkinglens-silent.md +0 -138
@@ -1,436 +0,0 @@
1
- /**
2
- * Config Validator 模块单元测试
3
- */
4
-
5
- const fs = require('fs');
6
- const path = require('path');
7
- const os = require('os');
8
-
9
- describe('Config Validator Module', () => {
10
- const {
11
- ConfigValidator,
12
- defaultValidator,
13
- validate,
14
- validateFile,
15
- validateOrThrow,
16
- isAJVAvailable
17
- } = require('../lib/config-validator');
18
-
19
- const { ConfigError } = require('../lib/errors');
20
-
21
- // Temporary directory for test files
22
- const tempDir = path.join(os.tmpdir(), 'smc-validator-test-' + Date.now());
23
- const validConfigFile = path.join(tempDir, 'valid-config.json');
24
- const invalidConfigFile = path.join(tempDir, 'invalid-config.json');
25
- const malformedJsonFile = path.join(tempDir, 'malformed.json');
26
- const settingsFile = path.join(tempDir, 'settings.json');
27
- const qualityGateFile = path.join(tempDir, 'quality-gate.json');
28
-
29
- beforeAll(() => {
30
- fs.mkdirSync(tempDir, { recursive: true });
31
-
32
- // Create valid config file
33
- fs.writeFileSync(validConfigFile, JSON.stringify({
34
- version: '1.0.7',
35
- model: 'claude-opus-4.5',
36
- agents: {
37
- conductor: { role: 'coordination' }
38
- },
39
- skills: []
40
- }));
41
-
42
- // Create invalid config file
43
- fs.writeFileSync(invalidConfigFile, JSON.stringify({
44
- model: 'test'
45
- // Missing required 'version' field
46
- }));
47
-
48
- // Create malformed JSON file
49
- fs.writeFileSync(malformedJsonFile, '{ "version": "1.0.0", }');
50
-
51
- // Create settings file
52
- fs.writeFileSync(settingsFile, JSON.stringify({
53
- updateCheck: true,
54
- syncInterval: 24
55
- }));
56
-
57
- // Create quality-gate file
58
- fs.writeFileSync(qualityGateFile, JSON.stringify({
59
- enabled: true,
60
- severity: 'warn',
61
- rules: []
62
- }));
63
- });
64
-
65
- afterAll(() => {
66
- if (fs.existsSync(tempDir)) {
67
- fs.rmSync(tempDir, { recursive: true, force: true });
68
- }
69
- });
70
-
71
- describe('isAJVAvailable', () => {
72
- it('should return boolean indicating AJV availability', () => {
73
- expect(typeof isAJVAvailable()).toBe('boolean');
74
- });
75
- });
76
-
77
- describe('ConfigValidator', () => {
78
- let validator;
79
-
80
- beforeEach(() => {
81
- validator = new ConfigValidator();
82
- });
83
-
84
- describe('constructor', () => {
85
- it('should create validator with default options', () => {
86
- expect(validator.strict).toBe(true);
87
- expect(validator.allErrors).toBe(true);
88
- expect(validator.coerceTypes).toBe(true);
89
- expect(validator.useDefaults).toBe(false);
90
- });
91
-
92
- it('should accept custom options', () => {
93
- const customValidator = new ConfigValidator({
94
- strict: false,
95
- allErrors: false,
96
- coerceTypes: false,
97
- useDefaults: true
98
- });
99
-
100
- expect(customValidator.strict).toBe(false);
101
- expect(customValidator.allErrors).toBe(false);
102
- expect(customValidator.coerceTypes).toBe(false);
103
- expect(customValidator.useDefaults).toBe(true);
104
- });
105
-
106
- it('should initialize AJV if available', () => {
107
- if (isAJVAvailable()) {
108
- expect(validator.ajv).toBeDefined();
109
- expect(typeof validator.configValidate).toBe('function');
110
- expect(typeof validator.settingsValidate).toBe('function');
111
- expect(typeof validator.qualityGateValidate).toBe('function');
112
- } else {
113
- expect(validator.ajv).toBeNull();
114
- }
115
- });
116
- });
117
-
118
- describe('validate', () => {
119
- describe('with valid config', () => {
120
- it('should validate valid config object', () => {
121
- const validConfig = {
122
- version: '1.0.7',
123
- model: 'claude-opus-4.5',
124
- agents: {},
125
- skills: []
126
- };
127
-
128
- const result = validator.validate(validConfig, 'config');
129
-
130
- expect(result.valid).toBe(true);
131
- expect(result.errors).toEqual([]);
132
- expect(result.warnings).toEqual([]);
133
- expect(result.fixes).toEqual([]);
134
- });
135
-
136
- it('should validate settings object', () => {
137
- const settings = {
138
- updateCheck: true,
139
- syncInterval: 24
140
- };
141
-
142
- const result = validator.validate(settings, 'settings');
143
-
144
- expect(result.valid).toBe(true);
145
- });
146
-
147
- it('should validate quality-gate object', () => {
148
- const qualityGate = {
149
- enabled: true,
150
- severity: 'warn',
151
- rules: []
152
- };
153
-
154
- const result = validator.validate(qualityGate, 'quality-gate');
155
-
156
- expect(result.valid).toBe(true);
157
- });
158
- });
159
-
160
- describe('with invalid config', () => {
161
- it('should return errors for invalid config', () => {
162
- const invalidConfig = {
163
- model: 'test'
164
- // Missing version
165
- };
166
-
167
- const result = validator.validate(invalidConfig, 'config');
168
-
169
- expect(result.valid).toBe(false);
170
- expect(result.errors.length).toBeGreaterThan(0);
171
- });
172
-
173
- it('should handle unknown schema name', () => {
174
- const result = validator.validate({ test: 'value' }, 'unknown-schema');
175
-
176
- expect(result.valid).toBe(false);
177
- expect(result.errors[0].path).toBe('schema');
178
- });
179
-
180
- it('should separate errors from warnings', () => {
181
- // This test depends on AJV's error categorization
182
- const result = validator.validate({}, 'config');
183
-
184
- if (!isAJVAvailable()) {
185
- // Basic validation
186
- expect(result.valid).toBe(false);
187
- expect(result.errors.length).toBeGreaterThan(0);
188
- }
189
- });
190
-
191
- it('should include fix suggestions', () => {
192
- const result = validator.validate({}, 'config');
193
-
194
- if (result.errors.length > 0) {
195
- expect(result.fixes.length).toBeGreaterThan(0);
196
- }
197
- });
198
- });
199
-
200
- describe('without AJV (fallback)', () => {
201
- it('should do basic validation when AJV not available', () => {
202
- // This is tested implicitly when AJV is not installed
203
- const result = validator.validate({ version: '1.0.0' }, 'config');
204
-
205
- expect(result).toBeDefined();
206
- expect(typeof result.valid).toBe('boolean');
207
- });
208
-
209
- it('should require config to be object', () => {
210
- const result = validator.validate(null, 'config');
211
-
212
- expect(result.valid).toBe(false);
213
- expect(result.errors[0].message).toContain('object');
214
- });
215
-
216
- it('should validate version format', () => {
217
- const result = validator.validate({ version: 'invalid' }, 'config');
218
-
219
- expect(result.valid).toBe(false);
220
- if (result.errors.length > 0) {
221
- expect(result.errors.some(e => e.path === 'version')).toBe(true);
222
- }
223
- });
224
- });
225
- });
226
-
227
- describe('validateFile', () => {
228
- it('should validate valid config file', () => {
229
- const result = validator.validateFile(validConfigFile);
230
-
231
- expect(result.valid).toBe(true);
232
- });
233
-
234
- it('should handle non-existent file', () => {
235
- const result = validator.validateFile('/does/not/exist.json');
236
-
237
- expect(result.valid).toBe(false);
238
- expect(result.errors[0].message).toContain('not found');
239
- });
240
-
241
- it('should handle malformed JSON', () => {
242
- const result = validator.validateFile(malformedJsonFile);
243
-
244
- expect(result.valid).toBe(false);
245
- expect(result.errors[0].message).toContain('JSON');
246
- });
247
-
248
- it('should provide fix suggestion for JSON errors', () => {
249
- const result = validator.validateFile(malformedJsonFile);
250
-
251
- // Should have errors for malformed JSON
252
- expect(result.valid).toBe(false);
253
- expect(result.errors.length).toBeGreaterThan(0);
254
- // Fix suggestions may or may not be present depending on error type
255
- expect(result.errors[0].message).toContain('JSON');
256
- });
257
-
258
- it('should auto-detect schema from filename', () => {
259
- // For config.json
260
- const configResult = validator.validateFile(validConfigFile);
261
- expect(configResult).toBeDefined();
262
-
263
- // For settings.json
264
- const settingsResult = validator.validateFile(settingsFile);
265
- expect(settingsResult).toBeDefined();
266
-
267
- // For quality-gate.json
268
- const gateResult = validator.validateFile(qualityGateFile);
269
- expect(gateResult).toBeDefined();
270
- });
271
-
272
- it('should accept explicit schema name', () => {
273
- const result = validator.validateFile(validConfigFile, 'config');
274
-
275
- expect(result).toBeDefined();
276
- expect(typeof result.valid).toBe('boolean');
277
- });
278
- });
279
-
280
- describe('validateOrThrow', () => {
281
- it('should return config when valid', () => {
282
- const validConfig = {
283
- version: '1.0.7',
284
- model: 'claude-opus-4.5',
285
- agents: {},
286
- skills: []
287
- };
288
-
289
- const result = validator.validateOrThrow(validConfig, 'config');
290
-
291
- expect(result).toEqual(validConfig);
292
- });
293
-
294
- it('should throw ConfigError when invalid', () => {
295
- const invalidConfig = { model: 'test' };
296
-
297
- expect(() => {
298
- validator.validateOrThrow(invalidConfig, 'config');
299
- }).toThrow(ConfigError);
300
- });
301
-
302
- it('should include error details in thrown error', () => {
303
- const invalidConfig = {};
304
-
305
- try {
306
- validator.validateOrThrow(invalidConfig, 'config');
307
- fail('Should have thrown');
308
- } catch (e) {
309
- expect(e instanceof ConfigError).toBe(true);
310
- expect(e.errors).toBeDefined();
311
- expect(e.fixes).toBeDefined();
312
- }
313
- });
314
- });
315
- });
316
-
317
- describe('defaultValidator', () => {
318
- it('should export a default validator instance', () => {
319
- expect(defaultValidator).toBeDefined();
320
- expect(defaultValidator instanceof ConfigValidator).toBe(true);
321
- });
322
-
323
- it('should have default options', () => {
324
- expect(defaultValidator.strict).toBe(true);
325
- });
326
- });
327
-
328
- describe('Convenience Functions', () => {
329
- describe('validate', () => {
330
- it('should use default validator', () => {
331
- const result = validate({
332
- version: '1.0.7',
333
- model: 'claude-opus-4.5',
334
- agents: {},
335
- skills: []
336
- });
337
-
338
- expect(result).toBeDefined();
339
- });
340
- });
341
-
342
- describe('validateFile', () => {
343
- it('should use default validator', () => {
344
- const result = validateFile(validConfigFile);
345
-
346
- expect(result).toBeDefined();
347
- });
348
- });
349
-
350
- describe('validateOrThrow', () => {
351
- it('should use default validator', () => {
352
- const result = validateOrThrow({
353
- version: '1.0.7',
354
- model: 'claude-opus-4.5',
355
- agents: {},
356
- skills: []
357
- });
358
-
359
- expect(result).toBeDefined();
360
- });
361
- });
362
- });
363
-
364
- describe('Edge Cases', () => {
365
- it('should handle empty config', () => {
366
- const validator = new ConfigValidator();
367
- const result = validator.validate({}, 'config');
368
-
369
- expect(result).toBeDefined();
370
- });
371
-
372
- it('should handle null config', () => {
373
- const validator = new ConfigValidator();
374
- const result = validator.validate(null, 'config');
375
-
376
- expect(result.valid).toBe(false);
377
- });
378
-
379
- it('should handle array config', () => {
380
- const validator = new ConfigValidator();
381
- const result = validator.validate([], 'config');
382
-
383
- expect(result.valid).toBe(false);
384
- });
385
-
386
- it('should handle config with extra properties', () => {
387
- const validator = new ConfigValidator();
388
- const result = validator.validate({
389
- version: '1.0.7',
390
- extraProperty: 'should not error'
391
- }, 'config');
392
-
393
- // Extra properties should not cause validation failure (removeAdditional: false)
394
- expect(result.valid).toBeDefined();
395
- });
396
- });
397
-
398
- describe('Schema Auto-detection', () => {
399
- it('should detect config schema from config.json', () => {
400
- const result = validateFile(validConfigFile);
401
-
402
- // Should not throw and should return a result
403
- expect(result).toBeDefined();
404
- });
405
-
406
- it('should detect settings schema from settings.json', () => {
407
- const result = validateFile(settingsFile);
408
-
409
- expect(result).toBeDefined();
410
- });
411
-
412
- it('should detect settings schema from settings.local.json', () => {
413
- const localSettingsFile = path.join(tempDir, 'settings.local.json');
414
- fs.writeFileSync(localSettingsFile, JSON.stringify({ updateCheck: false }));
415
-
416
- const result = validateFile(localSettingsFile);
417
-
418
- expect(result).toBeDefined();
419
- });
420
-
421
- it('should detect quality-gate schema from quality-gate.json', () => {
422
- const result = validateFile(qualityGateFile);
423
-
424
- expect(result).toBeDefined();
425
- });
426
-
427
- it('should default to config schema for unknown filenames', () => {
428
- const unknownFile = path.join(tempDir, 'unknown.json');
429
- fs.writeFileSync(unknownFile, JSON.stringify({ version: '1.0.0' }));
430
-
431
- const result = validateFile(unknownFile);
432
-
433
- expect(result).toBeDefined();
434
- });
435
- });
436
- });
@@ -1,100 +0,0 @@
1
- /**
2
- * Config 模块单元测试
3
- */
4
-
5
- const fs = require('fs');
6
- const path = require('path');
7
- const os = require('os');
8
-
9
- describe('Config Module', () => {
10
- const config = require('../lib/config');
11
-
12
- describe('loadConfig', () => {
13
- it('should return default config when no user config exists', () => {
14
- // 使用真实的 CONFIG_DIR 但临时移除 config.json
15
- const realConfigFile = config.CONFIG_FILE;
16
- const tempBackup = realConfigFile + '.backup-test';
17
-
18
- // 备份现有配置(如果存在)
19
- if (fs.existsSync(realConfigFile)) {
20
- fs.renameSync(realConfigFile, tempBackup);
21
- }
22
-
23
- try {
24
- const result = config.loadConfig();
25
-
26
- expect(result).toBeDefined();
27
- expect(result).toHaveProperty('version');
28
- expect(result).toHaveProperty('agents');
29
- expect(result).toHaveProperty('skills');
30
- } finally {
31
- // 恢复原配置
32
- if (fs.existsSync(tempBackup)) {
33
- fs.renameSync(tempBackup, realConfigFile);
34
- }
35
- }
36
- });
37
-
38
- it('should return DEFAULTS constant', () => {
39
- expect(config.DEFAULTS).toBeDefined();
40
- expect(typeof config.DEFAULTS).toBe('object');
41
- });
42
- });
43
-
44
- describe('saveConfig & ensureDir', () => {
45
- const tempDir = path.join(os.tmpdir(), 'smc-test-' + Date.now());
46
- const tempFile = path.join(tempDir, 'test-config.json');
47
-
48
- afterAll(() => {
49
- // 清理
50
- if (fs.existsSync(tempDir)) {
51
- fs.rmSync(tempDir, { recursive: true, force: true });
52
- }
53
- });
54
-
55
- it('should create directory and save config', () => {
56
- const testConfig = {
57
- version: '1.0.0',
58
- test: 'value'
59
- };
60
-
61
- // 直接调用 ensureDir
62
- config.ensureDir(tempDir);
63
- expect(fs.existsSync(tempDir)).toBe(true);
64
-
65
- // 手动保存文件
66
- fs.writeFileSync(tempFile, JSON.stringify(testConfig, null, 2));
67
- expect(fs.existsSync(tempFile)).toBe(true);
68
-
69
- const saved = JSON.parse(fs.readFileSync(tempFile, 'utf-8'));
70
- expect(saved).toEqual(testConfig);
71
- });
72
-
73
- it('should not error when directory exists', () => {
74
- expect(() => config.ensureDir(tempDir)).not.toThrow();
75
- });
76
- });
77
-
78
- describe('deepMerge (internal behavior)', () => {
79
- it('should have loadConfig and saveConfig functions', () => {
80
- expect(typeof config.loadConfig).toBe('function');
81
- expect(typeof config.saveConfig).toBe('function');
82
- expect(typeof config.ensureDir).toBe('function');
83
- });
84
- });
85
-
86
- describe('exports', () => {
87
- it('should export required constants', () => {
88
- expect(config.CONFIG_DIR).toBeDefined();
89
- expect(config.CONFIG_FILE).toBeDefined();
90
- expect(config.DEFAULTS).toBeDefined();
91
- expect(config.SKILLS_DIR).toBeDefined();
92
- });
93
-
94
- it('should have correct paths', () => {
95
- expect(config.CONFIG_DIR).toContain('.claude');
96
- expect(config.CONFIG_FILE).toContain('config.json');
97
- expect(config.SKILLS_DIR).toContain('skills');
98
- });
99
- });
100
- });