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,441 +0,0 @@
1
- /**
2
- * Configuration Manager
3
- *
4
- * Advanced configuration management with:
5
- * - Automatic backup before changes
6
- * - Environment variable expansion
7
- * - Rollback capability
8
- * - Change history tracking
9
- *
10
- * @module lib/config-manager
11
- */
12
-
13
- const fs = require('fs');
14
- const path = require('path');
15
- const crypto = require('crypto');
16
- const { ConfigValidator } = require('./config-validator');
17
- const { ConfigError } = require('./errors');
18
-
19
- /**
20
- * Configuration Manager class
21
- */
22
- class ConfigManager {
23
- /**
24
- * @param {Object} options - Manager options
25
- * @param {string} options.configDir - Configuration directory
26
- * @param {string} options.configFile - Configuration file path
27
- * @param {string} options.backupDir - Backup directory
28
- * @param {number} options.maxBackups - Maximum number of backups to keep
29
- * @param {boolean} options.strict - Strict validation mode
30
- */
31
- constructor(options = {}) {
32
- this.configDir = options.configDir || path.join(process.env.HOME, '.claude');
33
- this.configFile = options.configFile || path.join(this.configDir, 'config.json');
34
- this.backupDir = options.backupDir || path.join(this.configDir, 'backups');
35
- this.maxBackups = options.maxBackups || 10;
36
-
37
- this.validator = new ConfigValidator({
38
- strict: options.strict !== false
39
- });
40
-
41
- this._ensureDirectories();
42
- }
43
-
44
- /**
45
- * Load configuration with validation
46
- * @param {Object} options - Load options
47
- * @returns {Object} Configuration object
48
- */
49
- load(options = {}) {
50
- const {
51
- useDefaults = true,
52
- expandEnv = true,
53
- strict = null
54
- } = options;
55
-
56
- if (!fs.existsSync(this.configFile)) {
57
- if (useDefaults) {
58
- return this._getDefaults();
59
- }
60
- throw new ConfigError('Configuration file not found', [], [
61
- `Create file at: ${this.configFile}`,
62
- 'Or run: smc init'
63
- ]);
64
- }
65
-
66
- const content = fs.readFileSync(this.configFile, 'utf-8');
67
- let config;
68
-
69
- try {
70
- config = JSON.parse(content);
71
- } catch (e) {
72
- const validation = this.validator.validateFile(this.configFile);
73
- throw new ConfigError(
74
- 'Invalid JSON in configuration file',
75
- validation.errors,
76
- validation.fixes
77
- );
78
- }
79
-
80
- // Expand environment variables
81
- if (expandEnv) {
82
- config = this._expandEnvVars(config);
83
- }
84
-
85
- // Validate against schema
86
- const effectiveStrict = strict !== null ? strict : this.validator.strict;
87
- if (effectiveStrict) {
88
- const validation = this.validator.validate(config);
89
- if (!validation.valid) {
90
- throw new ConfigError(
91
- 'Configuration validation failed',
92
- validation.errors,
93
- validation.fixes
94
- );
95
- }
96
- }
97
-
98
- return config;
99
- }
100
-
101
- /**
102
- * Save configuration with backup
103
- * @param {Object} config - Configuration to save
104
- * @param {Object} options - Save options
105
- * @returns {Object} Save result
106
- */
107
- save(config, options = {}) {
108
- const { backup = true, validate = true } = options;
109
-
110
- // Validate before saving
111
- if (validate) {
112
- const validation = this.validator.validate(config);
113
- if (!validation.valid) {
114
- throw new ConfigError(
115
- 'Cannot save invalid configuration',
116
- validation.errors,
117
- validation.fixes
118
- );
119
- }
120
- }
121
-
122
- // Create backup
123
- let backupPath = null;
124
- if (backup && fs.existsSync(this.configFile)) {
125
- backupPath = this._createBackup();
126
- }
127
-
128
- // Write new config
129
- const content = JSON.stringify(config, null, 2);
130
- fs.writeFileSync(this.configFile, content, 'utf-8');
131
-
132
- // Record change
133
- this._recordChange('save', {
134
- hash: this._hash(content),
135
- backup: backupPath
136
- });
137
-
138
- return { success: true, backup: backupPath };
139
- }
140
-
141
- /**
142
- * Rollback to previous configuration
143
- * @param {string|null} version - Backup version (null for latest)
144
- * @returns {Object} Rollback result
145
- */
146
- rollback(version = null) {
147
- const backups = this.listBackups();
148
-
149
- if (backups.length === 0) {
150
- throw new ConfigError('No backups available', [], [
151
- 'Backups are created when you save config changes',
152
- 'Enable backup option when saving'
153
- ]);
154
- }
155
-
156
- const targetBackup = version
157
- ? backups.find(b => b.version === version)
158
- : backups[0];
159
-
160
- if (!targetBackup) {
161
- throw new ConfigError(`Backup version ${version} not found`, [], [
162
- 'Available versions: ' + backups.map(b => b.version).join(', ')
163
- ]);
164
- }
165
-
166
- const backupPath = path.join(this.backupDir, targetBackup.file);
167
- const content = fs.readFileSync(backupPath, 'utf-8');
168
-
169
- // Create backup of current before rollback
170
- if (fs.existsSync(this.configFile)) {
171
- this._createBackup('pre-rollback');
172
- }
173
-
174
- fs.writeFileSync(this.configFile, content, 'utf-8');
175
-
176
- return {
177
- success: true,
178
- restoredFrom: targetBackup.version,
179
- timestamp: targetBackup.timestamp
180
- };
181
- }
182
-
183
- /**
184
- * List available backups
185
- * @returns {Array} List of backup info objects
186
- */
187
- listBackups() {
188
- if (!fs.existsSync(this.backupDir)) {
189
- return [];
190
- }
191
-
192
- const files = fs.readdirSync(this.backupDir)
193
- .filter(f => f.startsWith('config-') && f.endsWith('.json'))
194
- .map(f => {
195
- const stat = fs.statSync(path.join(this.backupDir, f));
196
- return {
197
- file: f,
198
- version: f.replace('config-', '').replace('.json', ''),
199
- timestamp: stat.mtime,
200
- size: stat.size
201
- };
202
- })
203
- .sort((a, b) => b.timestamp - a.timestamp)
204
- .slice(0, this.maxBackups);
205
-
206
- return files;
207
- }
208
-
209
- /**
210
- * Get configuration diff
211
- * @param {string|Object} left - Left config (file path or object)
212
- * @param {string|Object} right - Right config (file path or object, null for current)
213
- * @returns {Array} Array of change objects
214
- */
215
- diff(left, right = null) {
216
- const leftConfig = typeof left === 'string'
217
- ? JSON.parse(fs.readFileSync(left, 'utf-8'))
218
- : left;
219
-
220
- const rightConfig = right
221
- ? (typeof right === 'string'
222
- ? JSON.parse(fs.readFileSync(right, 'utf-8'))
223
- : right)
224
- : this.load({ validate: false });
225
-
226
- return this._computeDiff(leftConfig, rightConfig);
227
- }
228
-
229
- /**
230
- * Create backup of current config
231
- * @param {string} suffix - Optional suffix for backup name
232
- * @returns {string} Backup file path
233
- */
234
- _createBackup(suffix = null) {
235
- const timestamp = new Date().toISOString()
236
- .replace(/[:.]/g, '-')
237
- .replace('T', '_')
238
- .split('.')[0];
239
-
240
- const version = `${timestamp}${suffix ? '-' + suffix : ''}`;
241
- const filename = `config-${version}.json`;
242
- const backupPath = path.join(this.backupDir, filename);
243
-
244
- fs.copyFileSync(this.configFile, backupPath);
245
-
246
- // Clean old backups
247
- this._cleanOldBackups();
248
-
249
- return backupPath;
250
- }
251
-
252
- /**
253
- * Remove old backups beyond maxBackups limit
254
- */
255
- _cleanOldBackups() {
256
- const backups = this.listBackups();
257
- if (backups.length <= this.maxBackups) return;
258
-
259
- const toRemove = backups.slice(this.maxBackups);
260
- for (const backup of toRemove) {
261
- fs.unlinkSync(path.join(this.backupDir, backup.file));
262
- }
263
- }
264
-
265
- /**
266
- * Expand environment variables in config values
267
- * Supports ${VAR} and ${VAR:default} syntax
268
- * @param {*} value - Value to expand
269
- * @returns {*} Expanded value
270
- */
271
- _expandEnvVars(value) {
272
- if (typeof value === 'string') {
273
- return value.replace(/\$\{([^:}]+)(?::([^}]*))?\}/g, (_, name, defaultValue) => {
274
- return process.env[name] !== undefined
275
- ? process.env[name]
276
- : (defaultValue !== undefined ? defaultValue : '');
277
- });
278
- }
279
-
280
- if (Array.isArray(value)) {
281
- return value.map(item => this._expandEnvVars(item));
282
- }
283
-
284
- if (value && typeof value === 'object') {
285
- const result = {};
286
- for (const [key, val] of Object.entries(value)) {
287
- result[key] = this._expandEnvVars(val);
288
- }
289
- return result;
290
- }
291
-
292
- return value;
293
- }
294
-
295
- /**
296
- * Ensure necessary directories exist
297
- */
298
- _ensureDirectories() {
299
- [this.configDir, this.backupDir].forEach(dir => {
300
- if (!fs.existsSync(dir)) {
301
- fs.mkdirSync(dir, { recursive: true });
302
- }
303
- });
304
- }
305
-
306
- /**
307
- * Get default configuration
308
- * @returns {Object} Default config
309
- */
310
- _getDefaults() {
311
- const defaultsPath = path.join(__dirname, '../config/defaults.json');
312
- if (fs.existsSync(defaultsPath)) {
313
- return JSON.parse(fs.readFileSync(defaultsPath, 'utf-8'));
314
- }
315
- return {
316
- version: '1.0.7',
317
- model: 'claude-opus-4.5',
318
- agents: {
319
- conductor: { role: 'Task coordination and decomposition' },
320
- architect: { role: 'Architecture design and decisions' },
321
- builder: { role: 'Code implementation and testing' },
322
- reviewer: { role: 'Code review and quality check' },
323
- librarian: { role: 'Documentation and knowledge' }
324
- },
325
- skills: ['anthropics/skills', 'numman-ali/n-skills'],
326
- hooks: { preTask: [], postTask: [] },
327
- thinkingLens: {
328
- enabled: true,
329
- autoSync: true,
330
- syncInterval: 20
331
- }
332
- };
333
- }
334
-
335
- /**
336
- * Compute SHA256 hash of content
337
- * @param {string} content - Content to hash
338
- * @returns {string} Hex hash
339
- */
340
- _hash(content) {
341
- return crypto.createHash('sha256').update(content).digest('hex');
342
- }
343
-
344
- /**
345
- * Record configuration change
346
- * @param {string} action - Action type
347
- * @param {Object} details - Change details
348
- */
349
- _recordChange(action, details = {}) {
350
- const historyPath = path.join(this.configDir, 'config-history.jsonl');
351
- const entry = {
352
- timestamp: new Date().toISOString(),
353
- action,
354
- ...details
355
- };
356
-
357
- const line = JSON.stringify(entry) + '\n';
358
- fs.appendFileSync(historyPath, line, 'utf-8');
359
-
360
- // Keep only last 100 entries
361
- try {
362
- const history = fs.readFileSync(historyPath, 'utf-8').trim().split('\n');
363
- if (history.length > 100) {
364
- const recent = history.slice(-100);
365
- fs.writeFileSync(historyPath, recent.join('\n') + '\n', 'utf-8');
366
- }
367
- } catch {
368
- // First write, ignore
369
- }
370
- }
371
-
372
- /**
373
- * Get configuration history
374
- * @param {number} limit - Maximum entries to return
375
- * @returns {Array} History entries
376
- */
377
- getHistory(limit = 20) {
378
- const historyPath = path.join(this.configDir, 'config-history.jsonl');
379
- if (!fs.existsSync(historyPath)) {
380
- return [];
381
- }
382
-
383
- const content = fs.readFileSync(historyPath, 'utf-8');
384
- const lines = content.trim().split('\n');
385
- const entries = lines
386
- .slice(-limit)
387
- .map(line => {
388
- try {
389
- return JSON.parse(line);
390
- } catch {
391
- return null;
392
- }
393
- })
394
- .filter(Boolean);
395
-
396
- return entries.reverse();
397
- }
398
-
399
- /**
400
- * Compute diff between two configs
401
- * @param {Object} left - Left config
402
- * @param {Object} right - Right config
403
- * @returns {Array} Array of changes
404
- */
405
- _computeDiff(left, right) {
406
- const changes = [];
407
-
408
- const compare = (l, r, path = '') => {
409
- const allKeys = new Set([
410
- ...(l ? Object.keys(l) : []),
411
- ...(r ? Object.keys(r) : [])
412
- ]);
413
-
414
- for (const key of allKeys) {
415
- const keyPath = path ? `${path}.${key}` : key;
416
- const lv = l?.[key];
417
- const rv = r?.[key];
418
-
419
- if (JSON.stringify(lv) !== JSON.stringify(rv)) {
420
- if (typeof lv === 'object' && typeof rv === 'object' &&
421
- lv !== null && rv !== null && !Array.isArray(lv) && !Array.isArray(rv)) {
422
- compare(lv, rv, keyPath);
423
- } else {
424
- changes.push({
425
- path: keyPath,
426
- from: lv,
427
- to: rv,
428
- type: lv === undefined ? 'added' :
429
- rv === undefined ? 'removed' : 'changed'
430
- });
431
- }
432
- }
433
- }
434
- };
435
-
436
- compare(left, right);
437
- return changes;
438
- }
439
- }
440
-
441
- module.exports = { ConfigManager };