claude-mycelium 2.0.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 (207) hide show
  1. package/.claude/settings.local.json +14 -0
  2. package/README.md +304 -0
  3. package/dist/coordination/gradient-cache.d.ts +48 -0
  4. package/dist/coordination/gradient-cache.d.ts.map +1 -0
  5. package/dist/coordination/gradient-cache.js +145 -0
  6. package/dist/coordination/gradient-cache.js.map +1 -0
  7. package/dist/coordination/index.d.ts +10 -0
  8. package/dist/coordination/index.d.ts.map +1 -0
  9. package/dist/coordination/index.js +10 -0
  10. package/dist/coordination/index.js.map +1 -0
  11. package/dist/core/agent-executor.d.ts +31 -0
  12. package/dist/core/agent-executor.d.ts.map +1 -0
  13. package/dist/core/agent-executor.js +257 -0
  14. package/dist/core/agent-executor.js.map +1 -0
  15. package/dist/core/change-applier.d.ts +10 -0
  16. package/dist/core/change-applier.d.ts.map +1 -0
  17. package/dist/core/change-applier.js +32 -0
  18. package/dist/core/change-applier.js.map +1 -0
  19. package/dist/core/gradient.d.ts +60 -0
  20. package/dist/core/gradient.d.ts.map +1 -0
  21. package/dist/core/gradient.js +191 -0
  22. package/dist/core/gradient.js.map +1 -0
  23. package/dist/core/index.d.ts +24 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +24 -0
  26. package/dist/core/index.js.map +1 -0
  27. package/dist/core/mode-selector.d.ts +44 -0
  28. package/dist/core/mode-selector.d.ts.map +1 -0
  29. package/dist/core/mode-selector.js +208 -0
  30. package/dist/core/mode-selector.js.map +1 -0
  31. package/dist/core/signals/centrality.d.ts +44 -0
  32. package/dist/core/signals/centrality.d.ts.map +1 -0
  33. package/dist/core/signals/centrality.js +264 -0
  34. package/dist/core/signals/centrality.js.map +1 -0
  35. package/dist/core/signals/churn.d.ts +41 -0
  36. package/dist/core/signals/churn.d.ts.map +1 -0
  37. package/dist/core/signals/churn.js +188 -0
  38. package/dist/core/signals/churn.js.map +1 -0
  39. package/dist/core/signals/complexity.d.ts +29 -0
  40. package/dist/core/signals/complexity.d.ts.map +1 -0
  41. package/dist/core/signals/complexity.js +169 -0
  42. package/dist/core/signals/complexity.js.map +1 -0
  43. package/dist/core/signals/debt.d.ts +27 -0
  44. package/dist/core/signals/debt.d.ts.map +1 -0
  45. package/dist/core/signals/debt.js +80 -0
  46. package/dist/core/signals/debt.js.map +1 -0
  47. package/dist/core/signals/errors.d.ts +32 -0
  48. package/dist/core/signals/errors.d.ts.map +1 -0
  49. package/dist/core/signals/errors.js +73 -0
  50. package/dist/core/signals/errors.js.map +1 -0
  51. package/dist/core/signals/index.d.ts +19 -0
  52. package/dist/core/signals/index.d.ts.map +1 -0
  53. package/dist/core/signals/index.js +19 -0
  54. package/dist/core/signals/index.js.map +1 -0
  55. package/dist/cost/cost-tracker.d.ts +90 -0
  56. package/dist/cost/cost-tracker.d.ts.map +1 -0
  57. package/dist/cost/cost-tracker.js +305 -0
  58. package/dist/cost/cost-tracker.js.map +1 -0
  59. package/dist/cost/index.d.ts +56 -0
  60. package/dist/cost/index.d.ts.map +1 -0
  61. package/dist/cost/index.js +111 -0
  62. package/dist/cost/index.js.map +1 -0
  63. package/dist/index.d.ts +35 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +40 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/llm/anthropic-client.d.ts +52 -0
  68. package/dist/llm/anthropic-client.d.ts.map +1 -0
  69. package/dist/llm/anthropic-client.js +310 -0
  70. package/dist/llm/anthropic-client.js.map +1 -0
  71. package/dist/llm/index.d.ts +27 -0
  72. package/dist/llm/index.d.ts.map +1 -0
  73. package/dist/llm/index.js +34 -0
  74. package/dist/llm/index.js.map +1 -0
  75. package/dist/prompts/complexity-reducer.d.ts +7 -0
  76. package/dist/prompts/complexity-reducer.d.ts.map +1 -0
  77. package/dist/prompts/complexity-reducer.js +55 -0
  78. package/dist/prompts/complexity-reducer.js.map +1 -0
  79. package/dist/prompts/debt-payer.d.ts +7 -0
  80. package/dist/prompts/debt-payer.d.ts.map +1 -0
  81. package/dist/prompts/debt-payer.js +55 -0
  82. package/dist/prompts/debt-payer.js.map +1 -0
  83. package/dist/prompts/error-reducer.d.ts +7 -0
  84. package/dist/prompts/error-reducer.d.ts.map +1 -0
  85. package/dist/prompts/error-reducer.js +54 -0
  86. package/dist/prompts/error-reducer.js.map +1 -0
  87. package/dist/prompts/index.d.ts +22 -0
  88. package/dist/prompts/index.d.ts.map +1 -0
  89. package/dist/prompts/index.js +112 -0
  90. package/dist/prompts/index.js.map +1 -0
  91. package/dist/prompts/stabilizer.d.ts +7 -0
  92. package/dist/prompts/stabilizer.d.ts.map +1 -0
  93. package/dist/prompts/stabilizer.js +55 -0
  94. package/dist/prompts/stabilizer.js.map +1 -0
  95. package/dist/prompts/types.d.ts +14 -0
  96. package/dist/prompts/types.d.ts.map +1 -0
  97. package/dist/prompts/types.js +5 -0
  98. package/dist/prompts/types.js.map +1 -0
  99. package/dist/trace/index.d.ts +51 -0
  100. package/dist/trace/index.d.ts.map +1 -0
  101. package/dist/trace/index.js +60 -0
  102. package/dist/trace/index.js.map +1 -0
  103. package/dist/trace/trace-event.d.ts +72 -0
  104. package/dist/trace/trace-event.d.ts.map +1 -0
  105. package/dist/trace/trace-event.js +244 -0
  106. package/dist/trace/trace-event.js.map +1 -0
  107. package/dist/types/index.d.ts +206 -0
  108. package/dist/types/index.d.ts.map +1 -0
  109. package/dist/types/index.js +6 -0
  110. package/dist/types/index.js.map +1 -0
  111. package/dist/utils/ci-provider.d.ts +43 -0
  112. package/dist/utils/ci-provider.d.ts.map +1 -0
  113. package/dist/utils/ci-provider.js +130 -0
  114. package/dist/utils/ci-provider.js.map +1 -0
  115. package/dist/utils/config.d.ts +31 -0
  116. package/dist/utils/config.d.ts.map +1 -0
  117. package/dist/utils/config.js +85 -0
  118. package/dist/utils/config.js.map +1 -0
  119. package/dist/utils/error-provider.d.ts +51 -0
  120. package/dist/utils/error-provider.d.ts.map +1 -0
  121. package/dist/utils/error-provider.js +123 -0
  122. package/dist/utils/error-provider.js.map +1 -0
  123. package/dist/utils/file-utils.d.ts +18 -0
  124. package/dist/utils/file-utils.d.ts.map +1 -0
  125. package/dist/utils/file-utils.js +95 -0
  126. package/dist/utils/file-utils.js.map +1 -0
  127. package/dist/utils/index.d.ts +10 -0
  128. package/dist/utils/index.d.ts.map +1 -0
  129. package/dist/utils/index.js +10 -0
  130. package/dist/utils/index.js.map +1 -0
  131. package/dist/utils/logger.d.ts +36 -0
  132. package/dist/utils/logger.d.ts.map +1 -0
  133. package/dist/utils/logger.js +74 -0
  134. package/dist/utils/logger.js.map +1 -0
  135. package/docs/IMPLEMENTATION-STATUS.md +199 -0
  136. package/docs/PHASE-0-COMPLETE.md +252 -0
  137. package/docs/PHASE-1-COMPLETE.md +204 -0
  138. package/docs/PHASE-2-COMPLETE.md +233 -0
  139. package/docs/PHASE2_COMPLETION_CHECKLIST.md +290 -0
  140. package/docs/PHASE2_INTEGRATION_SUMMARY.md +255 -0
  141. package/docs/PHASE2_QUICK_REFERENCE.md +365 -0
  142. package/docs/PHASE2_TEST_RESULTS.md +282 -0
  143. package/docs/ROADMAP.md +746 -0
  144. package/docs/SNAPSHOT.md +376 -0
  145. package/docs/adrs/ADR-001-signal-computation.md +76 -0
  146. package/docs/adrs/ADR-002-inhibitor-signals.md +108 -0
  147. package/docs/adrs/ADR-003-llm-integration.md +156 -0
  148. package/docs/adrs/ADR-004-process-architecture.md +175 -0
  149. package/docs/adrs/ADR-005-testing-strategy.md +243 -0
  150. package/docs/pitch.md +94 -0
  151. package/docs/specs/fourth-spec.md +1973 -0
  152. package/docs/specs/initial-spec.md +2096 -0
  153. package/docs/specs/second-spec.md +2690 -0
  154. package/package.json +50 -0
  155. package/src/coordination/gradient-cache.ts +185 -0
  156. package/src/coordination/index.ts +10 -0
  157. package/src/core/agent-executor.ts +327 -0
  158. package/src/core/change-applier.ts +338 -0
  159. package/src/core/gradient.ts +258 -0
  160. package/src/core/index.ts +24 -0
  161. package/src/core/mode-selector.ts +243 -0
  162. package/src/core/signals/centrality.ts +328 -0
  163. package/src/core/signals/churn.ts +239 -0
  164. package/src/core/signals/complexity.ts +206 -0
  165. package/src/core/signals/debt.ts +111 -0
  166. package/src/core/signals/errors.ts +93 -0
  167. package/src/core/signals/index.ts +19 -0
  168. package/src/cost/cost-tracker.ts +410 -0
  169. package/src/cost/index.ts +143 -0
  170. package/src/index.ts +43 -0
  171. package/src/llm/anthropic-client.ts +415 -0
  172. package/src/llm/index.ts +43 -0
  173. package/src/prompts/complexity-reducer.ts +59 -0
  174. package/src/prompts/debt-payer.ts +59 -0
  175. package/src/prompts/error-reducer.ts +58 -0
  176. package/src/prompts/index.ts +128 -0
  177. package/src/prompts/stabilizer.ts +59 -0
  178. package/src/prompts/types.ts +15 -0
  179. package/src/trace/README.md +178 -0
  180. package/src/trace/index.ts +88 -0
  181. package/src/trace/trace-event.ts +324 -0
  182. package/src/types/index.ts +271 -0
  183. package/src/utils/ci-provider.ts +145 -0
  184. package/src/utils/config.ts +95 -0
  185. package/src/utils/error-provider.ts +138 -0
  186. package/src/utils/file-utils.ts +111 -0
  187. package/src/utils/index.ts +10 -0
  188. package/src/utils/logger.ts +94 -0
  189. package/test-8d713cc8-f4b7-403d-8153-57573172b94c.ts +3 -0
  190. package/tests/coordination/gradient-cache.test.ts +270 -0
  191. package/tests/core/agent-executor.test.ts +217 -0
  192. package/tests/core/change-applier.test.ts +336 -0
  193. package/tests/core/gradient.test.ts +263 -0
  194. package/tests/core/mode-selector.test.ts +239 -0
  195. package/tests/core/signals/centrality.test.ts +512 -0
  196. package/tests/core/signals/churn.test.ts +355 -0
  197. package/tests/core/signals/complexity.test.ts +284 -0
  198. package/tests/core/signals/debt.test.ts +437 -0
  199. package/tests/core/signals/errors.test.ts +350 -0
  200. package/tests/cost/cost-tracker.test.ts +475 -0
  201. package/tests/integration/phase2.test.ts +405 -0
  202. package/tests/llm/anthropic-client.test.ts +437 -0
  203. package/tests/prompts/prompts.test.ts +266 -0
  204. package/tests/trace/trace-event.test.ts +666 -0
  205. package/tests/utils/file-utils.test.ts +148 -0
  206. package/tsconfig.json +24 -0
  207. package/vitest.config.ts +28 -0
@@ -0,0 +1,145 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import type { CIProvider, ChangeSet } from '../types/index.js';
4
+ import { loadConfig } from './config.js';
5
+ import { logInfo, logError } from './logger.js';
6
+
7
+ const execAsync = promisify(exec);
8
+
9
+ /**
10
+ * CI provider that runs tests and linters
11
+ * Per spec §16 (second-spec.md)
12
+ *
13
+ * Default command: "npm test && npm run lint"
14
+ * Configurable via .agent-meta/config.json
15
+ */
16
+ export class NpmCIProvider implements CIProvider {
17
+ private ciCommand: string;
18
+
19
+ constructor(ciCommand?: string) {
20
+ if (ciCommand) {
21
+ this.ciCommand = ciCommand;
22
+ } else {
23
+ // Load from config
24
+ const config = loadConfig();
25
+ this.ciCommand = config.ci_command;
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Run CI checks (tests + lint)
31
+ * Returns whether all checks passed and output
32
+ */
33
+ async run(changes: ChangeSet): Promise<{ passed: boolean; output: string }> {
34
+ logInfo('Running CI checks', {
35
+ command: this.ciCommand,
36
+ files: changes.files_touched.length,
37
+ });
38
+
39
+ try {
40
+ const { stdout, stderr } = await execAsync(this.ciCommand, {
41
+ maxBuffer: 1024 * 1024 * 10, // 10MB buffer for large test output
42
+ timeout: 300000, // 5 minute timeout
43
+ });
44
+
45
+ const output = [stdout, stderr].filter(Boolean).join('\n');
46
+
47
+ logInfo('CI checks passed', {
48
+ additions: changes.additions,
49
+ deletions: changes.deletions,
50
+ });
51
+
52
+ return {
53
+ passed: true,
54
+ output,
55
+ };
56
+ } catch (error: any) {
57
+ // exec throws error when command exits with non-zero code
58
+ const output = [error.stdout || '', error.stderr || '']
59
+ .filter(Boolean)
60
+ .join('\n');
61
+
62
+ logError('CI checks failed', error, {
63
+ exitCode: error.code,
64
+ signal: error.signal,
65
+ });
66
+
67
+ return {
68
+ passed: false,
69
+ output: output || error.message,
70
+ };
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Run only tests (skip lint)
76
+ */
77
+ async runTests(): Promise<{ passed: boolean; output: string }> {
78
+ const testCommand = 'npm test';
79
+
80
+ try {
81
+ const { stdout, stderr } = await execAsync(testCommand, {
82
+ maxBuffer: 1024 * 1024 * 10,
83
+ timeout: 300000,
84
+ });
85
+
86
+ return {
87
+ passed: true,
88
+ output: [stdout, stderr].filter(Boolean).join('\n'),
89
+ };
90
+ } catch (error: any) {
91
+ return {
92
+ passed: false,
93
+ output:
94
+ [error.stdout, error.stderr].filter(Boolean).join('\n') ||
95
+ error.message,
96
+ };
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Run only lint (skip tests)
102
+ */
103
+ async runLint(): Promise<{ passed: boolean; output: string }> {
104
+ const lintCommand = 'npm run lint';
105
+
106
+ try {
107
+ const { stdout, stderr } = await execAsync(lintCommand, {
108
+ maxBuffer: 1024 * 1024 * 10,
109
+ timeout: 60000, // 1 minute for lint
110
+ });
111
+
112
+ return {
113
+ passed: true,
114
+ output: [stdout, stderr].filter(Boolean).join('\n'),
115
+ };
116
+ } catch (error: any) {
117
+ return {
118
+ passed: false,
119
+ output:
120
+ [error.stdout, error.stderr].filter(Boolean).join('\n') ||
121
+ error.message,
122
+ };
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Check if CI is configured (npm scripts exist)
128
+ */
129
+ async isConfigured(): Promise<boolean> {
130
+ try {
131
+ // Check if npm test is defined
132
+ await execAsync('npm run test --help', {
133
+ timeout: 5000,
134
+ });
135
+ return true;
136
+ } catch {
137
+ return false;
138
+ }
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Default CI provider instance
144
+ */
145
+ export const ciProvider = new NpmCIProvider();
@@ -0,0 +1,95 @@
1
+ import { fileExists, readJsonFile, writeJsonFile } from './file-utils.js';
2
+ import type { SystemConfig } from '../types/index.js';
3
+
4
+ const CONFIG_PATH = '.agent-meta/config.json';
5
+
6
+ /**
7
+ * Default configuration per spec §13
8
+ */
9
+ export const DEFAULT_CONFIG: SystemConfig = {
10
+ version: '2.0.0',
11
+ created_at: new Date().toISOString(),
12
+ error_provider: 'file',
13
+ error_file: '.agent-meta/_errors.json',
14
+ ci_command: 'npm test && npm run lint',
15
+ spawn_count: 0,
16
+ last_gc_at_spawn: 0,
17
+ };
18
+
19
+ /**
20
+ * Load configuration from .agent-meta/config.json
21
+ * Creates default config if file doesn't exist
22
+ */
23
+ export function loadConfig(): SystemConfig {
24
+ if (!fileExists(CONFIG_PATH)) {
25
+ // Initialize with defaults
26
+ writeJsonFile(CONFIG_PATH, DEFAULT_CONFIG);
27
+ return DEFAULT_CONFIG;
28
+ }
29
+
30
+ try {
31
+ const config = readJsonFile<SystemConfig>(CONFIG_PATH);
32
+
33
+ // Merge with defaults to handle missing fields
34
+ return {
35
+ ...DEFAULT_CONFIG,
36
+ ...config,
37
+ };
38
+ } catch (error) {
39
+ console.error(`Failed to load config from ${CONFIG_PATH}:`, error);
40
+ console.error('Using default configuration');
41
+ return DEFAULT_CONFIG;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Save configuration to .agent-meta/config.json
47
+ */
48
+ export function saveConfig(config: SystemConfig): void {
49
+ try {
50
+ writeJsonFile(CONFIG_PATH, config);
51
+ } catch (error) {
52
+ console.error(`Failed to save config to ${CONFIG_PATH}:`, error);
53
+ throw error;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Update specific config fields
59
+ */
60
+ export function updateConfig(updates: Partial<SystemConfig>): SystemConfig {
61
+ const config = loadConfig();
62
+ const updated = {
63
+ ...config,
64
+ ...updates,
65
+ };
66
+ saveConfig(updated);
67
+ return updated;
68
+ }
69
+
70
+ /**
71
+ * Increment spawn counter and check if GC should run
72
+ * GC runs every 100 spawns (per spec §8)
73
+ */
74
+ export function incrementSpawnCount(): { count: number; shouldRunGC: boolean } {
75
+ const config = loadConfig();
76
+ config.spawn_count += 1;
77
+
78
+ const shouldRunGC = config.spawn_count - config.last_gc_at_spawn >= 100;
79
+
80
+ saveConfig(config);
81
+
82
+ return {
83
+ count: config.spawn_count,
84
+ shouldRunGC,
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Mark that GC has been run
90
+ */
91
+ export function markGCRun(): void {
92
+ const config = loadConfig();
93
+ config.last_gc_at_spawn = config.spawn_count;
94
+ saveConfig(config);
95
+ }
@@ -0,0 +1,138 @@
1
+ import { fileExists, readJsonFile, writeJsonFile } from './file-utils.js';
2
+ import type { ErrorProvider, ErrorProviderData } from '../types/index.js';
3
+ import { logWarn } from './logger.js';
4
+
5
+ const ERROR_FILE_PATH = '.agent-meta/_errors.json';
6
+
7
+ /**
8
+ * File-based error provider implementation
9
+ * Per spec §2.5 (second-spec.md lines 665-705)
10
+ *
11
+ * Users populate .agent-meta/_errors.json manually or via external tools
12
+ * Format:
13
+ * {
14
+ * "updated_at": "2026-01-30T17:00:00Z",
15
+ * "errors": [
16
+ * {
17
+ * "file": "src/auth.ts",
18
+ * "count": 6,
19
+ * "types": ["TypeError", "ReferenceError"]
20
+ * }
21
+ * ]
22
+ * }
23
+ */
24
+ export class FileErrorProvider implements ErrorProvider {
25
+ private errorFilePath: string;
26
+
27
+ constructor(errorFilePath: string = ERROR_FILE_PATH) {
28
+ this.errorFilePath = errorFilePath;
29
+ }
30
+
31
+ /**
32
+ * Get error count and types for a specific file
33
+ */
34
+ async getErrors(file: string): Promise<{ count: number; types: string[] }> {
35
+ if (!fileExists(this.errorFilePath)) {
36
+ // No error file exists - return zero errors
37
+ return { count: 0, types: [] };
38
+ }
39
+
40
+ try {
41
+ const data = readJsonFile<ErrorProviderData>(this.errorFilePath);
42
+
43
+ const entry = data.errors.find((e) => e.file === file);
44
+
45
+ if (!entry) {
46
+ return { count: 0, types: [] };
47
+ }
48
+
49
+ return {
50
+ count: entry.count,
51
+ types: entry.types,
52
+ };
53
+ } catch (error) {
54
+ logWarn(`Failed to read error file: ${this.errorFilePath}`, {
55
+ error: error instanceof Error ? error.message : String(error),
56
+ });
57
+ return { count: 0, types: [] };
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Initialize error file with empty data
63
+ */
64
+ initializeErrorFile(): void {
65
+ if (!fileExists(this.errorFilePath)) {
66
+ const initialData: ErrorProviderData = {
67
+ updated_at: new Date().toISOString(),
68
+ errors: [],
69
+ };
70
+ writeJsonFile(this.errorFilePath, initialData);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Update errors for a specific file
76
+ * Helper for manual error tracking
77
+ */
78
+ updateErrors(file: string, count: number, types: string[]): void {
79
+ let data: ErrorProviderData;
80
+
81
+ if (fileExists(this.errorFilePath)) {
82
+ data = readJsonFile<ErrorProviderData>(this.errorFilePath);
83
+ } else {
84
+ data = {
85
+ updated_at: new Date().toISOString(),
86
+ errors: [],
87
+ };
88
+ }
89
+
90
+ // Update or add entry
91
+ const existingIndex = data.errors.findIndex((e) => e.file === file);
92
+
93
+ if (existingIndex >= 0) {
94
+ data.errors[existingIndex] = { file, count, types };
95
+ } else {
96
+ data.errors.push({ file, count, types });
97
+ }
98
+
99
+ data.updated_at = new Date().toISOString();
100
+
101
+ writeJsonFile(this.errorFilePath, data);
102
+ }
103
+
104
+ /**
105
+ * Clear all error data
106
+ */
107
+ clearErrors(): void {
108
+ const data: ErrorProviderData = {
109
+ updated_at: new Date().toISOString(),
110
+ errors: [],
111
+ };
112
+ writeJsonFile(this.errorFilePath, data);
113
+ }
114
+
115
+ /**
116
+ * Get all errors (for reporting)
117
+ */
118
+ getAllErrors(): ErrorProviderData['errors'] {
119
+ if (!fileExists(this.errorFilePath)) {
120
+ return [];
121
+ }
122
+
123
+ try {
124
+ const data = readJsonFile<ErrorProviderData>(this.errorFilePath);
125
+ return data.errors;
126
+ } catch (error) {
127
+ logWarn(`Failed to read error file: ${this.errorFilePath}`, {
128
+ error: error instanceof Error ? error.message : String(error),
129
+ });
130
+ return [];
131
+ }
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Default error provider instance
137
+ */
138
+ export const errorProvider = new FileErrorProvider();
@@ -0,0 +1,111 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ export function pathToSafeFilename(filePath: string): string {
5
+ return filePath.replace(/[/\\]+/g, '__');
6
+ }
7
+
8
+ export function safeFilenameToPath(safeFilename: string): string {
9
+ return safeFilename.replace(/__/g, '/');
10
+ }
11
+
12
+ export function fileExists(filePath: string): boolean {
13
+ try {
14
+ fs.accessSync(filePath, fs.constants.F_OK);
15
+ return true;
16
+ } catch {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ export function readFile(filePath: string): string {
22
+ return fs.readFileSync(filePath, 'utf-8');
23
+ }
24
+
25
+ export function writeFile(filePath: string, content: string): void {
26
+ const dir = path.dirname(filePath);
27
+ if (!fs.existsSync(dir)) {
28
+ fs.mkdirSync(dir, { recursive: true });
29
+ }
30
+ fs.writeFileSync(filePath, content, 'utf-8');
31
+ }
32
+
33
+ export function appendFile(filePath: string, content: string): void {
34
+ const dir = path.dirname(filePath);
35
+ if (!fs.existsSync(dir)) {
36
+ fs.mkdirSync(dir, { recursive: true });
37
+ }
38
+ fs.appendFileSync(filePath, content, 'utf-8');
39
+ }
40
+
41
+ export function readJsonFile<T>(filePath: string): T {
42
+ const content = readFile(filePath);
43
+ return JSON.parse(content);
44
+ }
45
+
46
+ export function writeJsonFile<T>(filePath: string, data: T, indent: number = 2): void {
47
+ const content = JSON.stringify(data, null, indent);
48
+ writeFile(filePath, content);
49
+ }
50
+
51
+ export function listFilesRecursive(dirPath: string): string[] {
52
+ const files: string[] = [];
53
+
54
+ function traverse(currentPath: string): void {
55
+ const entries = fs.readdirSync(currentPath, { withFileTypes: true });
56
+ for (const entry of entries) {
57
+ const fullPath = path.join(currentPath, entry.name);
58
+ if (entry.isDirectory()) {
59
+ traverse(fullPath);
60
+ } else {
61
+ files.push(fullPath);
62
+ }
63
+ }
64
+ }
65
+
66
+ traverse(dirPath);
67
+ return files;
68
+ }
69
+
70
+ export function getLineCount(filePath: string): number {
71
+ const content = readFile(filePath);
72
+ return content.split('\n').length;
73
+ }
74
+
75
+ export function isTypeScriptFile(filePath: string): boolean {
76
+ return /\.ts$/.test(filePath) && !/\.d\.ts$/.test(filePath);
77
+ }
78
+
79
+ export function isTestFile(filePath: string): boolean {
80
+ return /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filePath);
81
+ }
82
+
83
+ export function ensureDir(dirPath: string): void {
84
+ if (!fs.existsSync(dirPath)) {
85
+ fs.mkdirSync(dirPath, { recursive: true });
86
+ }
87
+ }
88
+
89
+ export function deleteFile(filePath: string): void {
90
+ if (fileExists(filePath)) {
91
+ fs.unlinkSync(filePath);
92
+ }
93
+ }
94
+
95
+ export function copyFile(sourcePath: string, destPath: string): void {
96
+ const dir = path.dirname(destPath);
97
+ if (!fs.existsSync(dir)) {
98
+ fs.mkdirSync(dir, { recursive: true });
99
+ }
100
+ fs.copyFileSync(sourcePath, destPath);
101
+ }
102
+
103
+ export function getFileModTime(filePath: string): number {
104
+ const stats = fs.statSync(filePath);
105
+ return stats.mtimeMs;
106
+ }
107
+
108
+ export function getFileSize(filePath: string): number {
109
+ const stats = fs.statSync(filePath);
110
+ return stats.size;
111
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Utility functions for Claude-Mycelium
3
+ * Centralized exports for cleaner imports
4
+ */
5
+
6
+ export * from './file-utils.js';
7
+ export * from './config.js';
8
+ export * from './logger.js';
9
+ export * from './error-provider.js';
10
+ export * from './ci-provider.js';
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Structured logging utility for Claude-Mycelium
3
+ * Simple console-based logging with timestamp and context
4
+ */
5
+
6
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
7
+
8
+ interface LogContext {
9
+ [key: string]: unknown;
10
+ }
11
+
12
+ const LOG_LEVEL: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'info';
13
+
14
+ const LEVEL_PRIORITY: Record<LogLevel, number> = {
15
+ debug: 0,
16
+ info: 1,
17
+ warn: 2,
18
+ error: 3,
19
+ };
20
+
21
+ function shouldLog(level: LogLevel): boolean {
22
+ return LEVEL_PRIORITY[level] >= LEVEL_PRIORITY[LOG_LEVEL];
23
+ }
24
+
25
+ function formatTimestamp(): string {
26
+ return new Date().toISOString();
27
+ }
28
+
29
+ function formatMessage(level: LogLevel, message: string, context?: LogContext): string {
30
+ const timestamp = formatTimestamp();
31
+ const contextStr = context ? ` ${JSON.stringify(context)}` : '';
32
+ return `[${timestamp}] [${level.toUpperCase()}] ${message}${contextStr}`;
33
+ }
34
+
35
+ /**
36
+ * Log debug message (lowest priority)
37
+ */
38
+ export function logDebug(message: string, context?: LogContext): void {
39
+ if (shouldLog('debug')) {
40
+ console.debug(formatMessage('debug', message, context));
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Log info message (normal priority)
46
+ */
47
+ export function logInfo(message: string, context?: LogContext): void {
48
+ if (shouldLog('info')) {
49
+ console.info(formatMessage('info', message, context));
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Log warning message (high priority)
55
+ */
56
+ export function logWarn(message: string, context?: LogContext): void {
57
+ if (shouldLog('warn')) {
58
+ console.warn(formatMessage('warn', message, context));
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Log error message (highest priority)
64
+ */
65
+ export function logError(message: string, error?: Error, context?: LogContext): void {
66
+ if (shouldLog('error')) {
67
+ const errorContext = error
68
+ ? {
69
+ ...context,
70
+ error: error.message,
71
+ stack: error.stack,
72
+ }
73
+ : context;
74
+
75
+ console.error(formatMessage('error', message, errorContext));
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Create a child logger with fixed context
81
+ * Useful for agent-specific or file-specific logging
82
+ */
83
+ export function createLogger(baseContext: LogContext) {
84
+ return {
85
+ debug: (message: string, context?: LogContext) =>
86
+ logDebug(message, { ...baseContext, ...context }),
87
+ info: (message: string, context?: LogContext) =>
88
+ logInfo(message, { ...baseContext, ...context }),
89
+ warn: (message: string, context?: LogContext) =>
90
+ logWarn(message, { ...baseContext, ...context }),
91
+ error: (message: string, error?: Error, context?: LogContext) =>
92
+ logError(message, error, { ...baseContext, ...context }),
93
+ };
94
+ }
@@ -0,0 +1,3 @@
1
+ function add(a: number, b: number): number {
2
+ return a + b;
3
+ }