claude-mycelium 2.0.0 → 2.1.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 (189) hide show
  1. package/.agent-meta/_inhibitors.ndjson +1287 -0
  2. package/.agent-meta/_quarantine.json +45 -0
  3. package/.agent-meta/config.json +9 -0
  4. package/.claude/memory.db +0 -0
  5. package/.claude/settings.local.json +4 -1
  6. package/README.md +81 -235
  7. package/SECURITY.md +145 -0
  8. package/dist/agent/worker.d.ts +8 -0
  9. package/dist/agent/worker.d.ts.map +1 -0
  10. package/dist/agent/worker.js +97 -0
  11. package/dist/agent/worker.js.map +1 -0
  12. package/dist/bin.d.ts +7 -0
  13. package/dist/bin.d.ts.map +1 -0
  14. package/dist/bin.js +11 -0
  15. package/dist/bin.js.map +1 -0
  16. package/dist/cli/cost.d.ts +10 -0
  17. package/dist/cli/cost.d.ts.map +1 -0
  18. package/dist/cli/cost.js +163 -0
  19. package/dist/cli/cost.js.map +1 -0
  20. package/dist/cli/gc.d.ts +10 -0
  21. package/dist/cli/gc.d.ts.map +1 -0
  22. package/dist/cli/gc.js +108 -0
  23. package/dist/cli/gc.js.map +1 -0
  24. package/dist/cli/gradients.d.ts +10 -0
  25. package/dist/cli/gradients.d.ts.map +1 -0
  26. package/dist/cli/gradients.js +69 -0
  27. package/dist/cli/gradients.js.map +1 -0
  28. package/dist/cli/index.d.ts +17 -0
  29. package/dist/cli/index.d.ts.map +1 -0
  30. package/dist/cli/index.js +72 -0
  31. package/dist/cli/index.js.map +1 -0
  32. package/dist/cli/init.d.ts +11 -0
  33. package/dist/cli/init.d.ts.map +1 -0
  34. package/dist/cli/init.js +97 -0
  35. package/dist/cli/init.js.map +1 -0
  36. package/dist/cli/status.d.ts +10 -0
  37. package/dist/cli/status.d.ts.map +1 -0
  38. package/dist/cli/status.js +191 -0
  39. package/dist/cli/status.js.map +1 -0
  40. package/dist/coordination/file-locks.d.ts +42 -0
  41. package/dist/coordination/file-locks.d.ts.map +1 -0
  42. package/dist/coordination/file-locks.js +269 -0
  43. package/dist/coordination/file-locks.js.map +1 -0
  44. package/dist/coordination/index.d.ts +4 -0
  45. package/dist/coordination/index.d.ts.map +1 -1
  46. package/dist/coordination/index.js +4 -0
  47. package/dist/coordination/index.js.map +1 -1
  48. package/dist/coordination/inhibitors.d.ts +84 -0
  49. package/dist/coordination/inhibitors.d.ts.map +1 -0
  50. package/dist/coordination/inhibitors.js +290 -0
  51. package/dist/coordination/inhibitors.js.map +1 -0
  52. package/dist/coordination/process-manager.d.ts +73 -0
  53. package/dist/coordination/process-manager.d.ts.map +1 -0
  54. package/dist/coordination/process-manager.js +144 -0
  55. package/dist/coordination/process-manager.js.map +1 -0
  56. package/dist/core/agent-executor.d.ts.map +1 -1
  57. package/dist/core/agent-executor.js +28 -10
  58. package/dist/core/agent-executor.js.map +1 -1
  59. package/dist/core/change-applier.d.ts +29 -5
  60. package/dist/core/change-applier.d.ts.map +1 -1
  61. package/dist/core/change-applier.js +254 -24
  62. package/dist/core/change-applier.js.map +1 -1
  63. package/dist/core/signals/churn.d.ts.map +1 -1
  64. package/dist/core/signals/churn.js +6 -4
  65. package/dist/core/signals/churn.js.map +1 -1
  66. package/dist/core/signals/debt.d.ts.map +1 -1
  67. package/dist/core/signals/debt.js +4 -3
  68. package/dist/core/signals/debt.js.map +1 -1
  69. package/dist/cost/cost-tracker.d.ts.map +1 -1
  70. package/dist/cost/cost-tracker.js +2 -0
  71. package/dist/cost/cost-tracker.js.map +1 -1
  72. package/dist/gc/index.d.ts +17 -0
  73. package/dist/gc/index.d.ts.map +1 -0
  74. package/dist/gc/index.js +17 -0
  75. package/dist/gc/index.js.map +1 -0
  76. package/dist/gc/runner.d.ts +39 -0
  77. package/dist/gc/runner.d.ts.map +1 -0
  78. package/dist/gc/runner.js +277 -0
  79. package/dist/gc/runner.js.map +1 -0
  80. package/dist/gc/trace-compactor.d.ts +31 -0
  81. package/dist/gc/trace-compactor.d.ts.map +1 -0
  82. package/dist/gc/trace-compactor.js +162 -0
  83. package/dist/gc/trace-compactor.js.map +1 -0
  84. package/dist/index.d.ts +5 -1
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +6 -1
  87. package/dist/index.js.map +1 -1
  88. package/dist/prompts/index.d.ts +2 -1
  89. package/dist/prompts/index.d.ts.map +1 -1
  90. package/dist/prompts/index.js.map +1 -1
  91. package/dist/quarantine/explorer.d.ts +65 -0
  92. package/dist/quarantine/explorer.d.ts.map +1 -0
  93. package/dist/quarantine/explorer.js +175 -0
  94. package/dist/quarantine/explorer.js.map +1 -0
  95. package/dist/quarantine/index.d.ts +7 -0
  96. package/dist/quarantine/index.d.ts.map +1 -0
  97. package/dist/quarantine/index.js +7 -0
  98. package/dist/quarantine/index.js.map +1 -0
  99. package/dist/quarantine/manager.d.ts +75 -0
  100. package/dist/quarantine/manager.d.ts.map +1 -0
  101. package/dist/quarantine/manager.js +275 -0
  102. package/dist/quarantine/manager.js.map +1 -0
  103. package/dist/task/acceptance.d.ts +29 -0
  104. package/dist/task/acceptance.d.ts.map +1 -0
  105. package/dist/task/acceptance.js +228 -0
  106. package/dist/task/acceptance.js.map +1 -0
  107. package/dist/task/executor.d.ts +30 -0
  108. package/dist/task/executor.d.ts.map +1 -0
  109. package/dist/task/executor.js +429 -0
  110. package/dist/task/executor.js.map +1 -0
  111. package/dist/task/index.d.ts +12 -0
  112. package/dist/task/index.d.ts.map +1 -0
  113. package/dist/task/index.js +12 -0
  114. package/dist/task/index.js.map +1 -0
  115. package/dist/task/planner.d.ts +21 -0
  116. package/dist/task/planner.d.ts.map +1 -0
  117. package/dist/task/planner.js +253 -0
  118. package/dist/task/planner.js.map +1 -0
  119. package/dist/task/storage.d.ts +46 -0
  120. package/dist/task/storage.d.ts.map +1 -0
  121. package/dist/task/storage.js +266 -0
  122. package/dist/task/storage.js.map +1 -0
  123. package/dist/trace/trace-event.d.ts +2 -18
  124. package/dist/trace/trace-event.d.ts.map +1 -1
  125. package/dist/trace/trace-event.js +6 -6
  126. package/dist/trace/trace-event.js.map +1 -1
  127. package/dist/utils/file-utils.d.ts.map +1 -1
  128. package/dist/utils/file-utils.js +54 -15
  129. package/dist/utils/file-utils.js.map +1 -1
  130. package/docs/PHASE5_IMPLEMENTATION.md +237 -0
  131. package/docs/PHASES-3-7-COMPLETE.md +177 -0
  132. package/docs/PHASE_4_COMPLETE.md +135 -0
  133. package/docs/PHASE_7_DELIVERABLES.md +295 -0
  134. package/docs/PHASE_7_IMPLEMENTATION.md +306 -0
  135. package/docs/PHASE_7_SUMMARY.txt +195 -0
  136. package/docs/RELEASE-NOTES-v2.1.md +213 -0
  137. package/docs/ROADMAP.md +64 -57
  138. package/docs/SECURITY-AUDIT.md +387 -0
  139. package/docs/SNAPSHOT.md +59 -32
  140. package/docs/implementation/phase3-summary.md +220 -0
  141. package/package.json +19 -11
  142. package/src/agent/worker.ts +111 -0
  143. package/src/bin.ts +13 -0
  144. package/src/cli/cost.ts +210 -0
  145. package/src/cli/gc.ts +138 -0
  146. package/src/cli/gradients.ts +95 -0
  147. package/src/cli/index.ts +79 -0
  148. package/src/cli/init.ts +139 -0
  149. package/src/cli/status.ts +218 -0
  150. package/src/coordination/file-locks.ts +300 -0
  151. package/src/coordination/index.ts +4 -0
  152. package/src/coordination/inhibitors.ts +345 -0
  153. package/src/coordination/process-manager.ts +199 -0
  154. package/src/core/agent-executor.ts +20 -4
  155. package/src/core/signals/churn.ts +8 -5
  156. package/src/core/signals/debt.ts +4 -3
  157. package/src/cost/cost-tracker.ts +2 -0
  158. package/src/gc/index.ts +17 -0
  159. package/src/gc/runner.ts +314 -0
  160. package/src/gc/trace-compactor.ts +187 -0
  161. package/src/index.ts +7 -1
  162. package/src/prompts/index.ts +2 -1
  163. package/src/quarantine/explorer.ts +234 -0
  164. package/src/quarantine/index.ts +7 -0
  165. package/src/quarantine/manager.ts +336 -0
  166. package/src/task/acceptance.ts +267 -0
  167. package/src/task/executor.ts +538 -0
  168. package/src/task/index.ts +38 -0
  169. package/src/task/planner.ts +294 -0
  170. package/src/task/storage.ts +332 -0
  171. package/src/trace/trace-event.ts +7 -26
  172. package/src/utils/file-utils.ts +61 -15
  173. package/tests/cli/gc.test.ts +206 -0
  174. package/tests/cli/init.test.ts +181 -0
  175. package/tests/cli/status.test.ts +282 -0
  176. package/tests/coordination/file-locks.test.ts +196 -0
  177. package/tests/coordination/inhibitors.test.ts +459 -0
  178. package/tests/coordination/integration.test.ts +195 -0
  179. package/tests/coordination/process-manager.test.ts +165 -0
  180. package/tests/gc/trace-compactor.test.ts +245 -0
  181. package/tests/integration/phase-7.test.ts +145 -0
  182. package/tests/quarantine/explorer.test.ts +381 -0
  183. package/tests/quarantine/manager.test.ts +399 -0
  184. package/tests/security/command-injection.test.ts +88 -0
  185. package/tests/security/path-traversal.test.ts +103 -0
  186. package/tests/task/acceptance.test.ts +411 -0
  187. package/tests/task/executor.test.ts +421 -0
  188. package/tests/task/planner.test.ts +359 -0
  189. package/tsconfig.json +2 -2
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Init CLI Command
3
+ *
4
+ * Initialize .agent-meta/ directory structure
5
+ * Create default configuration files
6
+ * Per Phase 7 specification §15
7
+ */
8
+ import { Command } from 'commander';
9
+ declare const command: Command;
10
+ export default command;
11
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,QAAA,MAAM,OAAO,SAYT,CAAC;AAgHL,eAAe,OAAO,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Init CLI Command
3
+ *
4
+ * Initialize .agent-meta/ directory structure
5
+ * Create default configuration files
6
+ * Per Phase 7 specification §15
7
+ */
8
+ import { Command } from 'commander';
9
+ import chalk from 'chalk';
10
+ import * as fs from 'fs/promises';
11
+ import * as path from 'path';
12
+ import { fileExists } from '../utils/file-utils.js';
13
+ const command = new Command()
14
+ .name('init')
15
+ .description('Initialize .agent-meta/ in current directory')
16
+ .option('--force', 'Reinitialize even if exists')
17
+ .action(async (options) => {
18
+ try {
19
+ await initCommand(options.force);
20
+ }
21
+ catch (error) {
22
+ const message = error instanceof Error ? error.message : 'Unknown error';
23
+ console.error(chalk.red(`Error: ${message}`));
24
+ process.exit(1);
25
+ }
26
+ });
27
+ /**
28
+ * Initialize .agent-meta/ directory and configuration
29
+ */
30
+ async function initCommand(force = false) {
31
+ const metaDir = '.agent-meta';
32
+ // Check if already initialized
33
+ if (fileExists(metaDir) && !force) {
34
+ console.log(chalk.yellow('Already initialized. Use --force to reinitialize.'));
35
+ return;
36
+ }
37
+ // Create directory structure
38
+ await fs.mkdir(metaDir, { recursive: true });
39
+ await fs.mkdir(path.join(metaDir, 'traces'), { recursive: true });
40
+ await fs.mkdir(path.join(metaDir, 'tasks'), { recursive: true });
41
+ await fs.mkdir(path.join(metaDir, 'locks'), { recursive: true });
42
+ // Create initial config file
43
+ await fs.writeFile(path.join(metaDir, 'config.json'), JSON.stringify({
44
+ version: '2.0.0',
45
+ created_at: new Date().toISOString(),
46
+ error_provider: 'file',
47
+ error_file: '.agent-meta/_errors.json',
48
+ ci_command: 'npm test && npm run lint',
49
+ spawn_count: 0,
50
+ last_gc_at_spawn: 0,
51
+ }, null, 2) + '\n');
52
+ // Create quarantine file
53
+ await fs.writeFile(path.join(metaDir, '_quarantine.json'), JSON.stringify({
54
+ updated_at: new Date().toISOString(),
55
+ entries: [],
56
+ }, null, 2) + '\n');
57
+ // Create inhibitors file
58
+ await fs.writeFile(path.join(metaDir, '_inhibitors.ndjson'), '');
59
+ // Create errors file
60
+ await fs.writeFile(path.join(metaDir, '_errors.json'), JSON.stringify({
61
+ updated_at: new Date().toISOString(),
62
+ errors: [],
63
+ }, null, 2) + '\n');
64
+ // Create GC log file
65
+ await fs.writeFile(path.join(metaDir, '_gc.log'), '');
66
+ // Add to .gitignore if needed
67
+ const gitignorePath = '.gitignore';
68
+ const lockPattern = '.agent-meta/locks/';
69
+ try {
70
+ const gitignore = await fs.readFile(gitignorePath, 'utf-8');
71
+ if (!gitignore.includes(lockPattern)) {
72
+ await fs.appendFile(gitignorePath, `\n# Claude Mycelium locks (ephemeral)\n${lockPattern}\n`);
73
+ }
74
+ }
75
+ catch {
76
+ // No .gitignore, create one
77
+ await fs.writeFile(gitignorePath, `# Claude Mycelium locks (ephemeral)\n${lockPattern}\n`);
78
+ }
79
+ // Success message
80
+ console.log('');
81
+ console.log(chalk.green('✓ Initialized .agent-meta/'));
82
+ console.log(chalk.dim(' - Created directory structure (traces, tasks, locks)'));
83
+ console.log(chalk.dim(' - Created config.json'));
84
+ console.log(chalk.dim(' - Created _quarantine.json'));
85
+ console.log(chalk.dim(' - Created _inhibitors.ndjson'));
86
+ console.log(chalk.dim(' - Created _errors.json'));
87
+ console.log(chalk.dim(' - Created _gc.log'));
88
+ console.log(chalk.dim(' - Updated .gitignore'));
89
+ console.log('');
90
+ console.log(chalk.bold('Next steps:'));
91
+ console.log(' 1. Set ANTHROPIC_API_KEY environment variable');
92
+ console.log(' 2. Run: npx claude-mycelium gradients ./src');
93
+ console.log(' 3. Check system status: npx claude-mycelium status');
94
+ console.log('');
95
+ }
96
+ export default command;
97
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Status CLI Command
3
+ *
4
+ * Display system overview
5
+ * Show agent count, recent activity
6
+ */
7
+ import { Command } from 'commander';
8
+ declare const command: Command;
9
+ export default command;
10
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,QAAA,MAAM,OAAO,SA8DT,CAAC;AA4IL,eAAe,OAAO,CAAC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Status CLI Command
3
+ *
4
+ * Display system overview
5
+ * Show agent count, recent activity
6
+ */
7
+ import { Command } from 'commander';
8
+ import chalk from 'chalk';
9
+ import * as fs from 'fs/promises';
10
+ import * as path from 'path';
11
+ import { fileExists } from '../utils/file-utils.js';
12
+ import { loadConfig } from '../utils/config.js';
13
+ const command = new Command()
14
+ .name('status')
15
+ .description('Show system status and recent activity')
16
+ .option('--json', 'Output as JSON')
17
+ .action(async (options) => {
18
+ try {
19
+ const status = await getSystemStatus();
20
+ if (options.json) {
21
+ console.log(JSON.stringify(status, null, 2));
22
+ return;
23
+ }
24
+ // Colorized output
25
+ console.log('');
26
+ console.log(chalk.bold('Claude Mycelium Status'));
27
+ console.log(chalk.dim('─'.repeat(60)));
28
+ console.log(chalk.bold('Configuration:'));
29
+ console.log(` Config version: ${status.config.version}`);
30
+ console.log(` Created: ${new Date(status.config.created_at).toLocaleDateString()}`);
31
+ console.log(` Error provider: ${status.config.error_provider}`);
32
+ console.log(chalk.bold('Statistics:'));
33
+ console.log(` Total spawns: ${status.spawn_count}`);
34
+ console.log(` Last GC at spawn: ${status.last_gc_at_spawn}`);
35
+ console.log(` Spawns since GC: ${status.spawn_count - status.last_gc_at_spawn}`);
36
+ console.log(chalk.bold('Storage:'));
37
+ console.log(` Trace events: ${status.trace_event_count}`);
38
+ console.log(` Quarantined files: ${status.quarantine_count}`);
39
+ console.log(` Inhibitors: ${status.inhibitor_count}`);
40
+ console.log(` Errors logged: ${status.error_count}`);
41
+ if (status.recent_activity.length > 0) {
42
+ console.log(chalk.bold('Recent Activity (last 5):'));
43
+ for (const activity of status.recent_activity.slice(0, 5)) {
44
+ const timeAgo = getTimeAgo(new Date(activity.timestamp));
45
+ const modeColor = getModeColor(activity.mode);
46
+ console.log(` ${chalk[modeColor](activity.mode.padEnd(18))} ${activity.file.substring(0, 35).padEnd(35)} ${timeAgo.padStart(10)}`);
47
+ }
48
+ }
49
+ console.log(chalk.dim('─'.repeat(60)));
50
+ console.log('');
51
+ }
52
+ catch (error) {
53
+ const message = error instanceof Error ? error.message : 'Unknown error';
54
+ console.error(chalk.red(`Error: ${message}`));
55
+ process.exit(1);
56
+ }
57
+ });
58
+ /**
59
+ * Get system status
60
+ */
61
+ async function getSystemStatus() {
62
+ const config = loadConfig();
63
+ let traceEventCount = 0;
64
+ let quarantineCount = 0;
65
+ let inhibitorCount = 0;
66
+ let errorCount = 0;
67
+ const recentActivity = [];
68
+ // Count trace events
69
+ const tracesDir = '.agent-meta/traces';
70
+ if (fileExists(tracesDir)) {
71
+ try {
72
+ const entries = await fs.readdir(tracesDir);
73
+ const traceFiles = entries.filter(f => f.endsWith('.ndjson'));
74
+ for (const file of traceFiles) {
75
+ const filePath = path.join(tracesDir, file);
76
+ try {
77
+ const content = await fs.readFile(filePath, 'utf-8');
78
+ const lines = content.split('\n').filter(Boolean);
79
+ traceEventCount += lines.length;
80
+ // Collect recent activity
81
+ for (const line of lines) {
82
+ try {
83
+ const event = JSON.parse(line);
84
+ recentActivity.push({
85
+ timestamp: event.timestamp,
86
+ mode: event.mode,
87
+ file: event.file_path,
88
+ });
89
+ }
90
+ catch {
91
+ // Skip malformed lines
92
+ }
93
+ }
94
+ }
95
+ catch {
96
+ // File read error
97
+ }
98
+ }
99
+ }
100
+ catch {
101
+ // Directory read error
102
+ }
103
+ }
104
+ // Count quarantine entries
105
+ const quarantinePath = '.agent-meta/_quarantine.json';
106
+ if (fileExists(quarantinePath)) {
107
+ try {
108
+ const content = await fs.readFile(quarantinePath, 'utf-8');
109
+ const quarantine = JSON.parse(content);
110
+ quarantineCount = (quarantine.entries || []).length;
111
+ }
112
+ catch {
113
+ // File read error
114
+ }
115
+ }
116
+ // Count inhibitors
117
+ const inhibitorsPath = '.agent-meta/_inhibitors.ndjson';
118
+ if (fileExists(inhibitorsPath)) {
119
+ try {
120
+ const content = await fs.readFile(inhibitorsPath, 'utf-8');
121
+ const lines = content.split('\n').filter(Boolean);
122
+ inhibitorCount = lines.length;
123
+ }
124
+ catch {
125
+ // File read error
126
+ }
127
+ }
128
+ // Count errors
129
+ const errorsPath = '.agent-meta/_errors.json';
130
+ if (fileExists(errorsPath)) {
131
+ try {
132
+ const content = await fs.readFile(errorsPath, 'utf-8');
133
+ const errors = JSON.parse(content);
134
+ errorCount = (errors.errors || []).length;
135
+ }
136
+ catch {
137
+ // File read error
138
+ }
139
+ }
140
+ // Sort recent activity by timestamp descending
141
+ recentActivity.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
142
+ return {
143
+ config,
144
+ spawn_count: config.spawn_count,
145
+ last_gc_at_spawn: config.last_gc_at_spawn,
146
+ trace_event_count: traceEventCount,
147
+ quarantine_count: quarantineCount,
148
+ inhibitor_count: inhibitorCount,
149
+ error_count: errorCount,
150
+ recent_activity: recentActivity.slice(0, 10),
151
+ };
152
+ }
153
+ /**
154
+ * Get human-readable time ago
155
+ */
156
+ function getTimeAgo(date) {
157
+ const now = new Date();
158
+ const diff = now.getTime() - date.getTime();
159
+ const seconds = Math.floor(diff / 1000);
160
+ const minutes = Math.floor(seconds / 60);
161
+ const hours = Math.floor(minutes / 60);
162
+ const days = Math.floor(hours / 24);
163
+ if (days > 0)
164
+ return `${days}d ago`;
165
+ if (hours > 0)
166
+ return `${hours}h ago`;
167
+ if (minutes > 0)
168
+ return `${minutes}m ago`;
169
+ return `${seconds}s ago`;
170
+ }
171
+ /**
172
+ * Get color for mode
173
+ */
174
+ function getModeColor(mode) {
175
+ switch (mode) {
176
+ case 'error_reducer':
177
+ return 'red';
178
+ case 'complexity_reducer':
179
+ return 'yellow';
180
+ case 'debt_payer':
181
+ return 'magenta';
182
+ case 'stabilizer':
183
+ return 'green';
184
+ case 'explorer':
185
+ return 'cyan';
186
+ default:
187
+ return 'blue';
188
+ }
189
+ }
190
+ export default command;
191
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/cli/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * File-based locking for multi-agent coordination
3
+ * Uses atomic O_CREAT|O_EXCL flags via fs.open() for race-free lock acquisition
4
+ *
5
+ * Reference: ADR-004, second-spec §4.1
6
+ */
7
+ import type { LockFile, Mode } from '../types/index.js';
8
+ /**
9
+ * Acquire an exclusive lock on a file
10
+ * Uses atomic O_CREAT|O_EXCL to prevent races
11
+ *
12
+ * @param filePath - File to lock (relative path)
13
+ * @param agentId - Agent requesting the lock
14
+ * @param mode - Mode of operation
15
+ * @param taskId - Optional task ID
16
+ * @returns true if lock acquired, false if already locked
17
+ */
18
+ export declare function acquireLock(filePath: string, agentId: string, mode: Mode, taskId?: string): Promise<boolean>;
19
+ /**
20
+ * Release a lock
21
+ *
22
+ * @param filePath - File to unlock
23
+ * @returns true if lock released, false if not locked by this process
24
+ */
25
+ export declare function releaseLock(filePath: string): Promise<boolean>;
26
+ /**
27
+ * Check if a file is locked
28
+ *
29
+ * @param filePath - File to check
30
+ * @returns LockFile if locked and valid, null otherwise
31
+ */
32
+ export declare function checkLock(filePath: string): Promise<LockFile | null>;
33
+ /**
34
+ * List all active locks
35
+ */
36
+ export declare function listLocks(): Promise<LockFile[]>;
37
+ /**
38
+ * Clean up expired and dead process locks
39
+ * Returns the number of locks cleaned up
40
+ */
41
+ export declare function cleanupStaleLocks(): Promise<number>;
42
+ //# sourceMappingURL=file-locks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-locks.d.ts","sourceRoot":"","sources":["../../src/coordination/file-locks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAKxD;;;;;;;;;GASG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,IAAI,EACV,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAsClB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAsBpE;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAwB1E;AAkGD;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CA+BrD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAgCzD"}
@@ -0,0 +1,269 @@
1
+ /**
2
+ * File-based locking for multi-agent coordination
3
+ * Uses atomic O_CREAT|O_EXCL flags via fs.open() for race-free lock acquisition
4
+ *
5
+ * Reference: ADR-004, second-spec §4.1
6
+ */
7
+ import * as fs from 'fs/promises';
8
+ import * as path from 'path';
9
+ const LOCK_DIR = '.agent-meta/locks';
10
+ const DEFAULT_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
11
+ /**
12
+ * Acquire an exclusive lock on a file
13
+ * Uses atomic O_CREAT|O_EXCL to prevent races
14
+ *
15
+ * @param filePath - File to lock (relative path)
16
+ * @param agentId - Agent requesting the lock
17
+ * @param mode - Mode of operation
18
+ * @param taskId - Optional task ID
19
+ * @returns true if lock acquired, false if already locked
20
+ */
21
+ export async function acquireLock(filePath, agentId, mode, taskId) {
22
+ await ensureLockDir();
23
+ const lockPath = getLockPath(filePath);
24
+ const now = new Date();
25
+ const expiresAt = new Date(now.getTime() + DEFAULT_TIMEOUT_MS);
26
+ const lockData = {
27
+ agent_id: agentId,
28
+ file: filePath,
29
+ mode,
30
+ acquired_at: now.toISOString(),
31
+ expires_at: expiresAt.toISOString(),
32
+ pid: process.pid,
33
+ task_id: taskId,
34
+ };
35
+ try {
36
+ // Check for expired lock first and attempt takeover
37
+ const takenOver = await tryTakeoverExpiredLock(lockPath, lockData);
38
+ if (takenOver) {
39
+ return true;
40
+ }
41
+ // Atomic creation: wx = O_CREAT|O_EXCL
42
+ // Will fail if file already exists
43
+ const fd = await fs.open(lockPath, 'wx');
44
+ await fd.writeFile(JSON.stringify(lockData, null, 2));
45
+ await fd.close();
46
+ return true;
47
+ }
48
+ catch (error) {
49
+ if (error.code === 'EEXIST') {
50
+ // Lock already exists, check if we can take it over
51
+ return false;
52
+ }
53
+ throw error;
54
+ }
55
+ }
56
+ /**
57
+ * Release a lock
58
+ *
59
+ * @param filePath - File to unlock
60
+ * @returns true if lock released, false if not locked by this process
61
+ */
62
+ export async function releaseLock(filePath) {
63
+ const lockPath = getLockPath(filePath);
64
+ try {
65
+ // Verify we own the lock before releasing
66
+ const content = await fs.readFile(lockPath, 'utf-8');
67
+ const lock = JSON.parse(content);
68
+ if (lock.pid !== process.pid) {
69
+ // Not our lock
70
+ return false;
71
+ }
72
+ await fs.unlink(lockPath);
73
+ return true;
74
+ }
75
+ catch (error) {
76
+ if (error.code === 'ENOENT') {
77
+ // Lock doesn't exist
78
+ return false;
79
+ }
80
+ throw error;
81
+ }
82
+ }
83
+ /**
84
+ * Check if a file is locked
85
+ *
86
+ * @param filePath - File to check
87
+ * @returns LockFile if locked and valid, null otherwise
88
+ */
89
+ export async function checkLock(filePath) {
90
+ const lockPath = getLockPath(filePath);
91
+ try {
92
+ const content = await fs.readFile(lockPath, 'utf-8');
93
+ const lock = JSON.parse(content);
94
+ // Check if lock is expired
95
+ if (isExpired(lock)) {
96
+ return null;
97
+ }
98
+ // Check if process is alive
99
+ if (!isProcessAlive(lock.pid)) {
100
+ return null;
101
+ }
102
+ return lock;
103
+ }
104
+ catch (error) {
105
+ if (error.code === 'ENOENT') {
106
+ return null;
107
+ }
108
+ throw error;
109
+ }
110
+ }
111
+ /**
112
+ * Try to take over an expired or dead process lock
113
+ *
114
+ * @param lockPath - Path to lock file
115
+ * @param newLock - New lock data
116
+ * @returns true if takeover successful
117
+ */
118
+ async function tryTakeoverExpiredLock(lockPath, newLock) {
119
+ try {
120
+ const content = await fs.readFile(lockPath, 'utf-8');
121
+ const oldLock = JSON.parse(content);
122
+ // Check if lock is expired
123
+ if (isExpired(oldLock)) {
124
+ await fs.unlink(lockPath);
125
+ const fd = await fs.open(lockPath, 'wx');
126
+ await fd.writeFile(JSON.stringify(newLock, null, 2));
127
+ await fd.close();
128
+ return true;
129
+ }
130
+ // Check if process is dead
131
+ if (!isProcessAlive(oldLock.pid)) {
132
+ await fs.unlink(lockPath);
133
+ const fd = await fs.open(lockPath, 'wx');
134
+ await fd.writeFile(JSON.stringify(newLock, null, 2));
135
+ await fd.close();
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+ catch (error) {
141
+ if (error.code === 'ENOENT') {
142
+ // Lock doesn't exist, normal acquisition can proceed
143
+ return false;
144
+ }
145
+ throw error;
146
+ }
147
+ }
148
+ /**
149
+ * Check if a lock has expired (5-minute timeout)
150
+ */
151
+ function isExpired(lock) {
152
+ const expiresAt = new Date(lock.expires_at);
153
+ return Date.now() > expiresAt.getTime();
154
+ }
155
+ /**
156
+ * Check if a process is alive
157
+ * Uses process.kill(pid, 0) which doesn't actually kill but checks existence
158
+ */
159
+ function isProcessAlive(pid) {
160
+ try {
161
+ // Signal 0 checks if process exists without killing it
162
+ process.kill(pid, 0);
163
+ return true;
164
+ }
165
+ catch (error) {
166
+ if (error.code === 'ESRCH') {
167
+ // Process not found
168
+ return false;
169
+ }
170
+ if (error.code === 'EPERM') {
171
+ // Process exists but we don't have permission to signal it
172
+ // This means it's alive
173
+ return true;
174
+ }
175
+ throw error;
176
+ }
177
+ }
178
+ /**
179
+ * Get the lock file path for a given file
180
+ */
181
+ function getLockPath(filePath) {
182
+ // Sanitize file path to create a unique lock filename
183
+ const sanitized = filePath.replace(/[^a-zA-Z0-9]/g, '_');
184
+ return path.join(LOCK_DIR, `${sanitized}.lock`);
185
+ }
186
+ /**
187
+ * Ensure lock directory exists
188
+ */
189
+ async function ensureLockDir() {
190
+ try {
191
+ await fs.mkdir(LOCK_DIR, { recursive: true });
192
+ }
193
+ catch (error) {
194
+ if (error.code !== 'EEXIST') {
195
+ throw error;
196
+ }
197
+ }
198
+ }
199
+ /**
200
+ * List all active locks
201
+ */
202
+ export async function listLocks() {
203
+ try {
204
+ await ensureLockDir();
205
+ const files = await fs.readdir(LOCK_DIR);
206
+ const locks = [];
207
+ for (const file of files) {
208
+ if (!file.endsWith('.lock'))
209
+ continue;
210
+ try {
211
+ const lockPath = path.join(LOCK_DIR, file);
212
+ const content = await fs.readFile(lockPath, 'utf-8');
213
+ const lock = JSON.parse(content);
214
+ // Only include valid locks
215
+ if (!isExpired(lock) && isProcessAlive(lock.pid)) {
216
+ locks.push(lock);
217
+ }
218
+ }
219
+ catch {
220
+ // Skip invalid lock files
221
+ continue;
222
+ }
223
+ }
224
+ return locks;
225
+ }
226
+ catch (error) {
227
+ if (error.code === 'ENOENT') {
228
+ return [];
229
+ }
230
+ throw error;
231
+ }
232
+ }
233
+ /**
234
+ * Clean up expired and dead process locks
235
+ * Returns the number of locks cleaned up
236
+ */
237
+ export async function cleanupStaleLocks() {
238
+ try {
239
+ await ensureLockDir();
240
+ const files = await fs.readdir(LOCK_DIR);
241
+ let cleaned = 0;
242
+ for (const file of files) {
243
+ if (!file.endsWith('.lock'))
244
+ continue;
245
+ try {
246
+ const lockPath = path.join(LOCK_DIR, file);
247
+ const content = await fs.readFile(lockPath, 'utf-8');
248
+ const lock = JSON.parse(content);
249
+ // Remove if expired or process is dead
250
+ if (isExpired(lock) || !isProcessAlive(lock.pid)) {
251
+ await fs.unlink(lockPath);
252
+ cleaned++;
253
+ }
254
+ }
255
+ catch {
256
+ // Skip files we can't process
257
+ continue;
258
+ }
259
+ }
260
+ return cleaned;
261
+ }
262
+ catch (error) {
263
+ if (error.code === 'ENOENT') {
264
+ return 0;
265
+ }
266
+ throw error;
267
+ }
268
+ }
269
+ //# sourceMappingURL=file-locks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-locks.js","sourceRoot":"","sources":["../../src/coordination/file-locks.ts"],"names":[],"mappings":"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"}