spidersan 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +91 -0
- package/LICENSE +21 -0
- package/LICENSE.md +85 -0
- package/README.md +217 -0
- package/dist/bin/spidersan.d.ts +9 -0
- package/dist/bin/spidersan.d.ts.map +1 -0
- package/dist/bin/spidersan.js +152 -0
- package/dist/bin/spidersan.js.map +1 -0
- package/dist/commands/abandon.d.ts +8 -0
- package/dist/commands/abandon.d.ts.map +1 -0
- package/dist/commands/abandon.js +49 -0
- package/dist/commands/abandon.js.map +1 -0
- package/dist/commands/activate.d.ts +9 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +45 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/active-windows.d.ts +16 -0
- package/dist/commands/active-windows.d.ts.map +1 -0
- package/dist/commands/active-windows.js +373 -0
- package/dist/commands/active-windows.js.map +1 -0
- package/dist/commands/audit-mark.d.ts +12 -0
- package/dist/commands/audit-mark.d.ts.map +1 -0
- package/dist/commands/audit-mark.js +204 -0
- package/dist/commands/audit-mark.js.map +1 -0
- package/dist/commands/cleanup.d.ts +8 -0
- package/dist/commands/cleanup.d.ts.map +1 -0
- package/dist/commands/cleanup.js +41 -0
- package/dist/commands/cleanup.js.map +1 -0
- package/dist/commands/close.d.ts +9 -0
- package/dist/commands/close.d.ts.map +1 -0
- package/dist/commands/close.js +129 -0
- package/dist/commands/close.js.map +1 -0
- package/dist/commands/collab-sync.d.ts +14 -0
- package/dist/commands/collab-sync.d.ts.map +1 -0
- package/dist/commands/collab-sync.js +240 -0
- package/dist/commands/collab-sync.js.map +1 -0
- package/dist/commands/collab.d.ts +6 -0
- package/dist/commands/collab.d.ts.map +1 -0
- package/dist/commands/collab.js +103 -0
- package/dist/commands/collab.js.map +1 -0
- package/dist/commands/completions.d.ts +8 -0
- package/dist/commands/completions.d.ts.map +1 -0
- package/dist/commands/completions.js +83 -0
- package/dist/commands/completions.js.map +1 -0
- package/dist/commands/conflicts.d.ts +12 -0
- package/dist/commands/conflicts.d.ts.map +1 -0
- package/dist/commands/conflicts.js +426 -0
- package/dist/commands/conflicts.js.map +1 -0
- package/dist/commands/demo.d.ts +3 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +113 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/depends.d.ts +8 -0
- package/dist/commands/depends.d.ts.map +1 -0
- package/dist/commands/depends.js +44 -0
- package/dist/commands/depends.js.map +1 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +249 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/inbox.d.ts +3 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +66 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/index.d.ts +43 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +61 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +23 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/intent-scan.d.ts +17 -0
- package/dist/commands/intent-scan.d.ts.map +1 -0
- package/dist/commands/intent-scan.js +336 -0
- package/dist/commands/intent-scan.js.map +1 -0
- package/dist/commands/key-import.d.ts +3 -0
- package/dist/commands/key-import.d.ts.map +1 -0
- package/dist/commands/key-import.js +54 -0
- package/dist/commands/key-import.js.map +1 -0
- package/dist/commands/keygen.d.ts +3 -0
- package/dist/commands/keygen.d.ts.map +1 -0
- package/dist/commands/keygen.js +53 -0
- package/dist/commands/keygen.js.map +1 -0
- package/dist/commands/keys.d.ts +3 -0
- package/dist/commands/keys.d.ts.map +1 -0
- package/dist/commands/keys.js +56 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +45 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/lock.d.ts +11 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +220 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/log.d.ts +8 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +95 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/mcp-health.d.ts +3 -0
- package/dist/commands/mcp-health.d.ts.map +1 -0
- package/dist/commands/mcp-health.js +305 -0
- package/dist/commands/mcp-health.js.map +1 -0
- package/dist/commands/mcp-restart.d.ts +3 -0
- package/dist/commands/mcp-restart.d.ts.map +1 -0
- package/dist/commands/mcp-restart.js +176 -0
- package/dist/commands/mcp-restart.js.map +1 -0
- package/dist/commands/merge-order.d.ts +9 -0
- package/dist/commands/merge-order.d.ts.map +1 -0
- package/dist/commands/merge-order.js +138 -0
- package/dist/commands/merge-order.js.map +1 -0
- package/dist/commands/merged.d.ts +8 -0
- package/dist/commands/merged.d.ts.map +1 -0
- package/dist/commands/merged.js +39 -0
- package/dist/commands/merged.js.map +1 -0
- package/dist/commands/msg-read.d.ts +3 -0
- package/dist/commands/msg-read.d.ts.map +1 -0
- package/dist/commands/msg-read.js +70 -0
- package/dist/commands/msg-read.js.map +1 -0
- package/dist/commands/pulse.d.ts +9 -0
- package/dist/commands/pulse.d.ts.map +1 -0
- package/dist/commands/pulse.js +232 -0
- package/dist/commands/pulse.js.map +1 -0
- package/dist/commands/radar.d.ts +3 -0
- package/dist/commands/radar.d.ts.map +1 -0
- package/dist/commands/radar.js +147 -0
- package/dist/commands/radar.js.map +1 -0
- package/dist/commands/ready-check.d.ts +9 -0
- package/dist/commands/ready-check.d.ts.map +1 -0
- package/dist/commands/ready-check.js +156 -0
- package/dist/commands/ready-check.js.map +1 -0
- package/dist/commands/register.d.ts +3 -0
- package/dist/commands/register.d.ts.map +1 -0
- package/dist/commands/register.js +124 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/send.d.ts +3 -0
- package/dist/commands/send.d.ts.map +1 -0
- package/dist/commands/send.js +134 -0
- package/dist/commands/send.js.map +1 -0
- package/dist/commands/stale.d.ts +8 -0
- package/dist/commands/stale.d.ts.map +1 -0
- package/dist/commands/stale.js +38 -0
- package/dist/commands/stale.js.map +1 -0
- package/dist/commands/status.d.ts +9 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +41 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync-all.d.ts +9 -0
- package/dist/commands/sync-all.d.ts.map +1 -0
- package/dist/commands/sync-all.js +180 -0
- package/dist/commands/sync-all.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +49 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/tension.d.ts +12 -0
- package/dist/commands/tension.d.ts.map +1 -0
- package/dist/commands/tension.js +242 -0
- package/dist/commands/tension.js.map +1 -0
- package/dist/commands/torrent.d.ts +9 -0
- package/dist/commands/torrent.d.ts.map +1 -0
- package/dist/commands/torrent.js +431 -0
- package/dist/commands/torrent.js.map +1 -0
- package/dist/commands/tui.d.ts +8 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +15 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/commands/wake.d.ts +9 -0
- package/dist/commands/wake.d.ts.map +1 -0
- package/dist/commands/wake.js +188 -0
- package/dist/commands/wake.js.map +1 -0
- package/dist/commands/watch.d.ts +3 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +245 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/who-touched.d.ts +9 -0
- package/dist/commands/who-touched.d.ts.map +1 -0
- package/dist/commands/who-touched.js +186 -0
- package/dist/commands/who-touched.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent-errors.d.ts +41 -0
- package/dist/lib/agent-errors.d.ts.map +1 -0
- package/dist/lib/agent-errors.js +143 -0
- package/dist/lib/agent-errors.js.map +1 -0
- package/dist/lib/ast.d.ts +56 -0
- package/dist/lib/ast.d.ts.map +1 -0
- package/dist/lib/ast.js +134 -0
- package/dist/lib/ast.js.map +1 -0
- package/dist/lib/config.d.ts +33 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +127 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/crdt.d.ts +83 -0
- package/dist/lib/crdt.d.ts.map +1 -0
- package/dist/lib/crdt.js +160 -0
- package/dist/lib/crdt.js.map +1 -0
- package/dist/lib/crypto.d.ts +71 -0
- package/dist/lib/crypto.d.ts.map +1 -0
- package/dist/lib/crypto.js +172 -0
- package/dist/lib/crypto.js.map +1 -0
- package/dist/lib/errors.d.ts +35 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +71 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/license.d.ts +61 -0
- package/dist/lib/license.d.ts.map +1 -0
- package/dist/lib/license.js +171 -0
- package/dist/lib/license.js.map +1 -0
- package/dist/lib/security.d.ts +53 -0
- package/dist/lib/security.d.ts.map +1 -0
- package/dist/lib/security.js +122 -0
- package/dist/lib/security.js.map +1 -0
- package/dist/lib/update-check.d.ts +11 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +113 -0
- package/dist/lib/update-check.js.map +1 -0
- package/dist/storage/adapter.d.ts +58 -0
- package/dist/storage/adapter.d.ts.map +1 -0
- package/dist/storage/adapter.js +8 -0
- package/dist/storage/adapter.js.map +1 -0
- package/dist/storage/factory.d.ts +6 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/factory.js +22 -0
- package/dist/storage/factory.js.map +1 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +24 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +101 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/supabase.d.ts +52 -0
- package/dist/storage/supabase.d.ts.map +1 -0
- package/dist/storage/supabase.js +221 -0
- package/dist/storage/supabase.js.map +1 -0
- package/dist/tui/screen.d.ts +14 -0
- package/dist/tui/screen.d.ts.map +1 -0
- package/dist/tui/screen.js +136 -0
- package/dist/tui/screen.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spidersan intent-scan
|
|
3
|
+
*
|
|
4
|
+
* Layer 3: Intent Conflict Detection
|
|
5
|
+
*
|
|
6
|
+
* Parses collab entries to detect overlapping work intentions
|
|
7
|
+
* BEFORE agents start coding. Prevents duplicate work like
|
|
8
|
+
* the formation incident.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* spidersan intent-scan # Scan today's collab
|
|
12
|
+
* spidersan intent-scan --days 3 # Scan last 3 days
|
|
13
|
+
* spidersan intent-scan --watch # Watch for new intents
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import { readFileSync, readdirSync, existsSync } from 'fs';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
import chalk from 'chalk';
|
|
19
|
+
// Keywords that indicate work intent
|
|
20
|
+
const INTENT_VERBS = [
|
|
21
|
+
'building', 'implementing', 'creating', 'adding', 'developing',
|
|
22
|
+
'starting', 'working on', 'claiming', 'taking', 'picking up',
|
|
23
|
+
'coding', 'writing', 'designing', 'planning', 'shipping'
|
|
24
|
+
];
|
|
25
|
+
// Keywords that indicate completion
|
|
26
|
+
const COMPLETION_VERBS = [
|
|
27
|
+
'shipped', 'completed', 'finished', 'done', 'merged', 'pushed'
|
|
28
|
+
];
|
|
29
|
+
// High-value keywords to track
|
|
30
|
+
const PROJECT_KEYWORDS = [
|
|
31
|
+
'formation', 'invoak', 'swarmsan', 'treesan', 'spidersan',
|
|
32
|
+
'flockview', 'treesync', 'mycmail', 'myceliumail', 'watsan',
|
|
33
|
+
'sancho', 'birdsan', 'sherlocksan', 'envoak', 'mappersan',
|
|
34
|
+
'mvp', 'cli', 'mcp', 'worker', 'pool', 'task', 'sync',
|
|
35
|
+
'hybrid', 'search', 'rag', 'kg', 'digest', 'status'
|
|
36
|
+
];
|
|
37
|
+
// Agent emoji patterns
|
|
38
|
+
const AGENT_PATTERNS = {
|
|
39
|
+
'🐦': 'Birdsan',
|
|
40
|
+
'🕷️': 'Spidersan',
|
|
41
|
+
'🔍': 'Sherlocksan',
|
|
42
|
+
'🌵': 'Sancho',
|
|
43
|
+
'📣': 'Marksan',
|
|
44
|
+
'🗺️': 'Mappersan',
|
|
45
|
+
'🍄': 'Myceliumail',
|
|
46
|
+
'📚': 'Watsan',
|
|
47
|
+
'🧪': 'Yosef',
|
|
48
|
+
'🎨': 'Artisan',
|
|
49
|
+
'🌑': 'Sasusan',
|
|
50
|
+
'🌲': 'Treesan'
|
|
51
|
+
};
|
|
52
|
+
function parseAgentEntry(line) {
|
|
53
|
+
// Pattern: ## 🐦 Birdsan — 21:10 (optional context)
|
|
54
|
+
const match = line.match(/^##\s+([\p{Emoji}]+)\s+(\w+)\s*[—-]\s*(\d{1,2}:\d{2})/u);
|
|
55
|
+
if (match) {
|
|
56
|
+
return { agent: match[2], time: match[3] };
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function extractStatus(text) {
|
|
61
|
+
const lower = text.toLowerCase();
|
|
62
|
+
if (COMPLETION_VERBS.some(v => lower.includes(v)))
|
|
63
|
+
return 'complete';
|
|
64
|
+
if (lower.includes('starting') || lower.includes('claiming'))
|
|
65
|
+
return 'starting';
|
|
66
|
+
if (lower.includes('implementing') || lower.includes('building'))
|
|
67
|
+
return 'implementing';
|
|
68
|
+
if (lower.includes('planning') || lower.includes('proposing'))
|
|
69
|
+
return 'planning';
|
|
70
|
+
return 'unknown';
|
|
71
|
+
}
|
|
72
|
+
function extractKeywords(text) {
|
|
73
|
+
const lower = text.toLowerCase();
|
|
74
|
+
return PROJECT_KEYWORDS.filter(kw => lower.includes(kw));
|
|
75
|
+
}
|
|
76
|
+
function extractIntent(text) {
|
|
77
|
+
const lower = text.toLowerCase();
|
|
78
|
+
// Look for intent patterns
|
|
79
|
+
for (const verb of INTENT_VERBS) {
|
|
80
|
+
const idx = lower.indexOf(verb);
|
|
81
|
+
if (idx !== -1) {
|
|
82
|
+
// Extract up to 50 chars after verb
|
|
83
|
+
const start = idx;
|
|
84
|
+
const end = Math.min(idx + 60, text.length);
|
|
85
|
+
const snippet = text.substring(start, end).split('\n')[0];
|
|
86
|
+
return snippet.trim();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Fallback: first line with keywords
|
|
90
|
+
const lines = text.split('\n');
|
|
91
|
+
for (const line of lines) {
|
|
92
|
+
if (extractKeywords(line).length > 0) {
|
|
93
|
+
return line.trim().substring(0, 80);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
function parseCollabFile(filePath) {
|
|
99
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
100
|
+
const lines = content.split('\n');
|
|
101
|
+
const intents = [];
|
|
102
|
+
let currentAgent = null;
|
|
103
|
+
let currentTime = null;
|
|
104
|
+
let entryStart = 0;
|
|
105
|
+
let entryLines = [];
|
|
106
|
+
for (let i = 0; i < lines.length; i++) {
|
|
107
|
+
const line = lines[i];
|
|
108
|
+
const agentMatch = parseAgentEntry(line);
|
|
109
|
+
if (agentMatch) {
|
|
110
|
+
// Save previous entry if exists
|
|
111
|
+
if (currentAgent && entryLines.length > 0) {
|
|
112
|
+
const entryText = entryLines.join('\n');
|
|
113
|
+
const intent = extractIntent(entryText);
|
|
114
|
+
const keywords = extractKeywords(entryText);
|
|
115
|
+
const status = extractStatus(entryText);
|
|
116
|
+
// Only record if intent detected
|
|
117
|
+
if (intent || keywords.length > 0) {
|
|
118
|
+
intents.push({
|
|
119
|
+
agent: currentAgent,
|
|
120
|
+
timestamp: currentTime,
|
|
121
|
+
rawEntry: entryText.substring(0, 500),
|
|
122
|
+
intent,
|
|
123
|
+
keywords,
|
|
124
|
+
status,
|
|
125
|
+
file: filePath,
|
|
126
|
+
lineNumber: entryStart
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Start new entry
|
|
131
|
+
currentAgent = agentMatch.agent;
|
|
132
|
+
currentTime = agentMatch.time;
|
|
133
|
+
entryStart = i + 1;
|
|
134
|
+
entryLines = [];
|
|
135
|
+
}
|
|
136
|
+
else if (currentAgent) {
|
|
137
|
+
entryLines.push(line);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Don't forget last entry
|
|
141
|
+
if (currentAgent && entryLines.length > 0) {
|
|
142
|
+
const entryText = entryLines.join('\n');
|
|
143
|
+
const intent = extractIntent(entryText);
|
|
144
|
+
const keywords = extractKeywords(entryText);
|
|
145
|
+
const status = extractStatus(entryText);
|
|
146
|
+
if (intent || keywords.length > 0) {
|
|
147
|
+
intents.push({
|
|
148
|
+
agent: currentAgent,
|
|
149
|
+
timestamp: currentTime,
|
|
150
|
+
rawEntry: entryText.substring(0, 500),
|
|
151
|
+
intent,
|
|
152
|
+
keywords,
|
|
153
|
+
status,
|
|
154
|
+
file: filePath,
|
|
155
|
+
lineNumber: entryStart
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return intents;
|
|
160
|
+
}
|
|
161
|
+
function calculateOverlap(a, b) {
|
|
162
|
+
// Same agent can't conflict with themselves
|
|
163
|
+
if (a.agent === b.agent)
|
|
164
|
+
return null;
|
|
165
|
+
// Completed work doesn't conflict
|
|
166
|
+
if (a.status === 'complete' || b.status === 'complete')
|
|
167
|
+
return null;
|
|
168
|
+
// Find shared keywords
|
|
169
|
+
const sharedKeywords = a.keywords.filter(k => b.keywords.includes(k));
|
|
170
|
+
if (sharedKeywords.length === 0)
|
|
171
|
+
return null;
|
|
172
|
+
// Calculate overlap score
|
|
173
|
+
const totalKeywords = new Set([...a.keywords, ...b.keywords]).size;
|
|
174
|
+
const overlapScore = Math.round((sharedKeywords.length / totalKeywords) * 100);
|
|
175
|
+
// Determine severity
|
|
176
|
+
let severity = 'info';
|
|
177
|
+
if (overlapScore >= 70)
|
|
178
|
+
severity = 'conflict';
|
|
179
|
+
else if (overlapScore >= 40)
|
|
180
|
+
severity = 'warn';
|
|
181
|
+
return {
|
|
182
|
+
intent1: a,
|
|
183
|
+
intent2: b,
|
|
184
|
+
overlapScore,
|
|
185
|
+
sharedKeywords,
|
|
186
|
+
severity
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function findOverlaps(intents) {
|
|
190
|
+
const overlaps = [];
|
|
191
|
+
// Only look at recent intents (last 24 hours worth)
|
|
192
|
+
const recentIntents = intents.filter(i => i.status !== 'complete' &&
|
|
193
|
+
(i.status === 'starting' || i.status === 'implementing' || i.status === 'planning'));
|
|
194
|
+
// Compare all pairs
|
|
195
|
+
for (let i = 0; i < recentIntents.length; i++) {
|
|
196
|
+
for (let j = i + 1; j < recentIntents.length; j++) {
|
|
197
|
+
const overlap = calculateOverlap(recentIntents[i], recentIntents[j]);
|
|
198
|
+
if (overlap) {
|
|
199
|
+
overlaps.push(overlap);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Sort by severity and score
|
|
204
|
+
return overlaps.sort((a, b) => {
|
|
205
|
+
if (a.severity === 'conflict' && b.severity !== 'conflict')
|
|
206
|
+
return -1;
|
|
207
|
+
if (b.severity === 'conflict' && a.severity !== 'conflict')
|
|
208
|
+
return 1;
|
|
209
|
+
return b.overlapScore - a.overlapScore;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
function formatOverlap(overlap) {
|
|
213
|
+
const icon = overlap.severity === 'conflict' ? '🔴' :
|
|
214
|
+
overlap.severity === 'warn' ? '🟠' : '🟡';
|
|
215
|
+
const label = overlap.severity === 'conflict' ? 'CONFLICT' :
|
|
216
|
+
overlap.severity === 'warn' ? 'WARNING' : 'INFO';
|
|
217
|
+
return `
|
|
218
|
+
${icon} ${chalk.bold(label)}: Overlapping intent detected (${overlap.overlapScore}% match)
|
|
219
|
+
|
|
220
|
+
${chalk.cyan(overlap.intent1.agent)} (${overlap.intent1.timestamp}):
|
|
221
|
+
"${overlap.intent1.intent || overlap.intent1.keywords.join(', ')}"
|
|
222
|
+
Status: ${overlap.intent1.status}
|
|
223
|
+
|
|
224
|
+
${chalk.cyan(overlap.intent2.agent)} (${overlap.intent2.timestamp}):
|
|
225
|
+
"${overlap.intent2.intent || overlap.intent2.keywords.join(', ')}"
|
|
226
|
+
Status: ${overlap.intent2.status}
|
|
227
|
+
|
|
228
|
+
Shared keywords: ${chalk.yellow(overlap.sharedKeywords.join(', '))}
|
|
229
|
+
|
|
230
|
+
${chalk.gray('Recommendation: Coordinate before continuing')}
|
|
231
|
+
`;
|
|
232
|
+
}
|
|
233
|
+
export const intentScanCommand = new Command('intent-scan')
|
|
234
|
+
.description('Detect overlapping work intentions in collab entries (Layer 3)')
|
|
235
|
+
.option('--days <n>', 'Number of days to scan', '1')
|
|
236
|
+
.option('--json', 'Output as JSON')
|
|
237
|
+
.option('--verbose', 'Show all detected intents')
|
|
238
|
+
.option('--collab-dir <path>', 'Path to collab directory', process.env.TREEBIRD_INTERNAL
|
|
239
|
+
? join(process.env.TREEBIRD_INTERNAL, 'collab')
|
|
240
|
+
: join(process.env.HOME || '', 'Dev', 'treebird-internal', 'collab'))
|
|
241
|
+
.addHelpText('after', `
|
|
242
|
+
Examples:
|
|
243
|
+
spidersan intent-scan # Scan today's collab for overlaps
|
|
244
|
+
spidersan intent-scan --days 3 # Scan last 3 days
|
|
245
|
+
spidersan intent-scan --verbose # Show all detected intents
|
|
246
|
+
spidersan intent-scan --json # Output as JSON for tooling
|
|
247
|
+
|
|
248
|
+
Layer 3 of Spidersan's 7-layer conflict detection:
|
|
249
|
+
L1: File-level (git conflicts)
|
|
250
|
+
L2: Semantic (code dependencies)
|
|
251
|
+
L3: Intent (collab entries) ← THIS
|
|
252
|
+
L4: Temporal (active windows)
|
|
253
|
+
L5: Cross-repo (breaking changes)
|
|
254
|
+
L6: Predictive (pattern analysis)
|
|
255
|
+
L7: Resolution (auto-merge)
|
|
256
|
+
`)
|
|
257
|
+
.action((options) => {
|
|
258
|
+
const days = parseInt(options.days) || 1;
|
|
259
|
+
const collabDir = options.collabDir;
|
|
260
|
+
const isJson = options.json;
|
|
261
|
+
if (!existsSync(collabDir)) {
|
|
262
|
+
console.error(chalk.red(`Collab directory not found: ${collabDir}`));
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
// Find collab files for the date range
|
|
266
|
+
const files = readdirSync(collabDir)
|
|
267
|
+
.filter(f => f.match(/^\d{4}-\d{2}-\d{2}-daily\.md$/))
|
|
268
|
+
.sort()
|
|
269
|
+
.slice(-days);
|
|
270
|
+
if (files.length === 0) {
|
|
271
|
+
console.log(chalk.yellow('No collab files found'));
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
if (!isJson) {
|
|
275
|
+
console.log(chalk.bold('\n🕷️ INTENT SCAN — Layer 3 Conflict Detection\n'));
|
|
276
|
+
console.log(chalk.gray(`Scanning ${files.length} collab file(s)...\n`));
|
|
277
|
+
}
|
|
278
|
+
// Parse all files
|
|
279
|
+
const allIntents = [];
|
|
280
|
+
for (const file of files) {
|
|
281
|
+
const filePath = join(collabDir, file);
|
|
282
|
+
const intents = parseCollabFile(filePath);
|
|
283
|
+
allIntents.push(...intents);
|
|
284
|
+
}
|
|
285
|
+
// Find overlaps
|
|
286
|
+
const overlaps = findOverlaps(allIntents);
|
|
287
|
+
if (isJson) {
|
|
288
|
+
console.log(JSON.stringify({
|
|
289
|
+
scanned: files,
|
|
290
|
+
intentsFound: allIntents.length,
|
|
291
|
+
overlaps: overlaps,
|
|
292
|
+
summary: {
|
|
293
|
+
conflicts: overlaps.filter(o => o.severity === 'conflict').length,
|
|
294
|
+
warnings: overlaps.filter(o => o.severity === 'warn').length,
|
|
295
|
+
info: overlaps.filter(o => o.severity === 'info').length
|
|
296
|
+
}
|
|
297
|
+
}, null, 2));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
// Verbose: show all intents
|
|
301
|
+
if (options.verbose) {
|
|
302
|
+
console.log(chalk.bold('📋 Detected Intents:\n'));
|
|
303
|
+
for (const intent of allIntents) {
|
|
304
|
+
const statusIcon = intent.status === 'complete' ? '✅' :
|
|
305
|
+
intent.status === 'implementing' ? '🔨' :
|
|
306
|
+
intent.status === 'starting' ? '🚀' :
|
|
307
|
+
intent.status === 'planning' ? '📝' : '❓';
|
|
308
|
+
console.log(` ${statusIcon} ${chalk.cyan(intent.agent)} (${intent.timestamp})`);
|
|
309
|
+
console.log(` ${intent.intent || intent.keywords.join(', ')}`);
|
|
310
|
+
console.log(` Keywords: ${chalk.gray(intent.keywords.join(', '))}\n`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// Show overlaps
|
|
314
|
+
if (overlaps.length === 0) {
|
|
315
|
+
console.log(chalk.green('✅ No overlapping intents detected\n'));
|
|
316
|
+
console.log(chalk.gray(`Scanned ${allIntents.length} intents from ${files.length} file(s)`));
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
const conflicts = overlaps.filter(o => o.severity === 'conflict');
|
|
320
|
+
const warnings = overlaps.filter(o => o.severity === 'warn');
|
|
321
|
+
console.log(chalk.bold(`Found ${overlaps.length} overlap(s):\n`));
|
|
322
|
+
for (const overlap of overlaps) {
|
|
323
|
+
console.log(formatOverlap(overlap));
|
|
324
|
+
}
|
|
325
|
+
// Summary
|
|
326
|
+
console.log(chalk.bold('Summary:'));
|
|
327
|
+
if (conflicts.length > 0) {
|
|
328
|
+
console.log(chalk.red(` 🔴 ${conflicts.length} conflict(s) — coordinate immediately`));
|
|
329
|
+
}
|
|
330
|
+
if (warnings.length > 0) {
|
|
331
|
+
console.log(chalk.yellow(` 🟠 ${warnings.length} warning(s) — check with agents`));
|
|
332
|
+
}
|
|
333
|
+
console.log(chalk.gray(` 📊 ${allIntents.length} intents scanned from ${files.length} file(s)\n`));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
//# sourceMappingURL=intent-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intent-scan.js","sourceRoot":"","sources":["../../src/commands/intent-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-import.d.ts","sourceRoot":"","sources":["../../src/commands/key-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,eAAO,MAAM,gBAAgB,SAmCvB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { execSync, spawnSync } from 'child_process';
|
|
3
|
+
// Security: Input validation
|
|
4
|
+
const VALID_AGENT_ID = /^[a-z0-9][a-z0-9_-]{0,30}$/i;
|
|
5
|
+
const VALID_BASE64_KEY = /^[A-Za-z0-9+/=]{20,500}$/;
|
|
6
|
+
function validateAgentId(agentId) {
|
|
7
|
+
if (!VALID_AGENT_ID.test(agentId)) {
|
|
8
|
+
throw new Error(`Invalid agent ID: "${agentId.slice(0, 20)}..."`);
|
|
9
|
+
}
|
|
10
|
+
return agentId;
|
|
11
|
+
}
|
|
12
|
+
function validatePublicKey(key) {
|
|
13
|
+
if (!VALID_BASE64_KEY.test(key)) {
|
|
14
|
+
throw new Error(`Invalid public key format (expected base64)`);
|
|
15
|
+
}
|
|
16
|
+
return key;
|
|
17
|
+
}
|
|
18
|
+
export const keyImportCommand = new Command('key-import')
|
|
19
|
+
.description('Import another agent\'s public key (via Myceliumail)')
|
|
20
|
+
.argument('<agentId>', 'Agent ID to associate with the key')
|
|
21
|
+
.argument('<publicKey>', 'Base64-encoded public key')
|
|
22
|
+
.action(async (agentId, publicKey) => {
|
|
23
|
+
// Security: Validate inputs
|
|
24
|
+
let safeAgentId;
|
|
25
|
+
let safeKey;
|
|
26
|
+
let myAgent;
|
|
27
|
+
try {
|
|
28
|
+
safeAgentId = validateAgentId(agentId);
|
|
29
|
+
safeKey = validatePublicKey(publicKey);
|
|
30
|
+
myAgent = validateAgentId(process.env.SPIDERSAN_AGENT || 'cli-agent');
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error(`❌ ${error.message}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
execSync('which mycmail', { stdio: 'ignore' });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
console.error('❌ Myceliumail not found');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
// Security: Use spawnSync with argument array
|
|
44
|
+
try {
|
|
45
|
+
spawnSync('mycmail', ['key-import', safeAgentId, safeKey], {
|
|
46
|
+
stdio: 'inherit',
|
|
47
|
+
env: { ...process.env, MYCELIUMAIL_AGENT_ID: myAgent }
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
//# sourceMappingURL=key-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-import.js","sourceRoot":"","sources":["../../src/commands/key-import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEpD,6BAA6B;AAC7B,MAAM,cAAc,GAAG,6BAA6B,CAAC;AACrD,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAEpD,SAAS,eAAe,CAAC,OAAe;IACpC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IAClC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;KACpD,WAAW,CAAC,sDAAsD,CAAC;KACnE,QAAQ,CAAC,WAAW,EAAE,oCAAoC,CAAC;KAC3D,QAAQ,CAAC,aAAa,EAAE,2BAA2B,CAAC;KACpD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,SAAiB,EAAE,EAAE;IACjD,4BAA4B;IAC5B,IAAI,WAAmB,CAAC;IACxB,IAAI,OAAe,CAAC;IACpB,IAAI,OAAe,CAAC;IAEpB,IAAI,CAAC;QACD,WAAW,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACvC,OAAO,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC,CAAC;IAC1E,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,CAAC;QACD,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,8CAA8C;IAC9C,IAAI,CAAC;QACD,SAAS,CAAC,SAAS,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE;YACvD,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,OAAO,EAAE;SACzD,CAAC,CAAC;IACP,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keygen.d.ts","sourceRoot":"","sources":["../../src/commands/keygen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,aAAa,SA4CpB,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { execSync, spawnSync } from 'child_process';
|
|
3
|
+
// Security: Input validation
|
|
4
|
+
const VALID_AGENT_ID = /^[a-z0-9][a-z0-9_-]{0,30}$/i;
|
|
5
|
+
function validateAgentId(agentId) {
|
|
6
|
+
if (!VALID_AGENT_ID.test(agentId)) {
|
|
7
|
+
throw new Error(`Invalid agent ID: "${agentId.slice(0, 20)}..."`);
|
|
8
|
+
}
|
|
9
|
+
return agentId;
|
|
10
|
+
}
|
|
11
|
+
export const keygenCommand = new Command('keygen')
|
|
12
|
+
.description('Generate a new keypair for encrypted messaging (via Myceliumail)')
|
|
13
|
+
.option('--agent <id>', 'Agent ID (default: from SPIDERSAN_AGENT env)')
|
|
14
|
+
.option('--force', 'Overwrite existing keypair (if supported by mycmail)')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const rawAgentId = options.agent || process.env.SPIDERSAN_AGENT;
|
|
17
|
+
if (!rawAgentId) {
|
|
18
|
+
console.error('❌ Agent ID required. Set SPIDERSAN_AGENT env or use --agent');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
// Security: Validate agent ID
|
|
22
|
+
let agentId;
|
|
23
|
+
try {
|
|
24
|
+
agentId = validateAgentId(rawAgentId);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error(`❌ ${error.message}`);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
execSync('which mycmail', { stdio: 'ignore' });
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
console.error('❌ Myceliumail (mycmail) not found.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
console.log(`🔑 Delegating to Myceliumail for agent: ${agentId}`);
|
|
38
|
+
// Security: Use spawnSync with argument array
|
|
39
|
+
const args = ['keygen'];
|
|
40
|
+
if (options.force) {
|
|
41
|
+
args.push('--force');
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
spawnSync('mycmail', args, {
|
|
45
|
+
stdio: 'inherit',
|
|
46
|
+
env: { ...process.env, MYCELIUMAIL_AGENT_ID: agentId }
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=keygen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keygen.js","sourceRoot":"","sources":["../../src/commands/keygen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEpD,6BAA6B;AAC7B,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAErD,SAAS,eAAe,CAAC,OAAe;IACpC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC7C,WAAW,CAAC,kEAAkE,CAAC;KAC/E,MAAM,CAAC,cAAc,EAAE,8CAA8C,CAAC;KACtE,MAAM,CAAC,SAAS,EAAE,sDAAsD,CAAC;KACzE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACtB,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAEhE,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,8BAA8B;IAC9B,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACD,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,CAAC;QACD,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2CAA2C,OAAO,EAAE,CAAC,CAAC;IAElE,8CAA8C;IAC9C,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,CAAC;QACD,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE;YACvB,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,OAAO,EAAE;SACzD,CAAC,CAAC;IACP,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,WAAW,SA6ClB,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { execSync, spawnSync } from 'child_process';
|
|
3
|
+
// Security: Input validation
|
|
4
|
+
const VALID_AGENT_ID = /^[a-z0-9][a-z0-9_-]{0,30}$/i;
|
|
5
|
+
function validateAgentId(agentId) {
|
|
6
|
+
if (!VALID_AGENT_ID.test(agentId)) {
|
|
7
|
+
throw new Error(`Invalid agent ID: "${agentId.slice(0, 20)}..."`);
|
|
8
|
+
}
|
|
9
|
+
return agentId;
|
|
10
|
+
}
|
|
11
|
+
export const keysCommand = new Command('keys')
|
|
12
|
+
.description('List known public keys (via Myceliumail)')
|
|
13
|
+
.option('--json', 'Output as JSON')
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const rawAgentId = process.env.SPIDERSAN_AGENT || 'cli-agent';
|
|
16
|
+
// Security: Validate agent ID
|
|
17
|
+
let agentId;
|
|
18
|
+
try {
|
|
19
|
+
agentId = validateAgentId(rawAgentId);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
console.error(`❌ ${error.message}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
execSync('which mycmail', { stdio: 'ignore' });
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
console.error('❌ Myceliumail not found');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
// Security: Use spawnSync with argument array
|
|
33
|
+
try {
|
|
34
|
+
const result = spawnSync('mycmail', ['keys'], {
|
|
35
|
+
encoding: 'utf-8',
|
|
36
|
+
env: { ...process.env, MYCELIUMAIL_AGENT_ID: agentId }
|
|
37
|
+
});
|
|
38
|
+
if (result.error) {
|
|
39
|
+
throw result.error;
|
|
40
|
+
}
|
|
41
|
+
const output = result.stdout || '';
|
|
42
|
+
if (options.json) {
|
|
43
|
+
console.log(JSON.stringify({
|
|
44
|
+
command: 'keys',
|
|
45
|
+
output: output.trim()
|
|
46
|
+
}, null, 2));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log(output);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/commands/keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEpD,6BAA6B;AAC7B,MAAM,cAAc,GAAG,6BAA6B,CAAC;AAErD,SAAS,eAAe,CAAC,OAAe;IACpC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KACzC,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACtB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;IAE9D,8BAA8B;IAC9B,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACD,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,CAAC;QACD,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,8CAA8C;IAC9C,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE;YAC1C,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,oBAAoB,EAAE,OAAO,EAAE;SACzD,CAAC,CAAC;QAEH,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,CAAC,KAAK,CAAC;QACvB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACvB,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;aACxB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACL,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QAClB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,eAAO,MAAM,WAAW,SAuClB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { getStorage } from '../storage/index.js';
|
|
3
|
+
export const listCommand = new Command('list')
|
|
4
|
+
.description('List all registered branches')
|
|
5
|
+
.option('--json', 'Output as JSON')
|
|
6
|
+
.action(async (options) => {
|
|
7
|
+
const storage = await getStorage();
|
|
8
|
+
if (!await storage.isInitialized()) {
|
|
9
|
+
console.error('❌ Spidersan not initialized. Run: spidersan init');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const branches = await storage.list();
|
|
13
|
+
if (branches.length === 0) {
|
|
14
|
+
console.log('🕷️ No branches registered yet.');
|
|
15
|
+
console.log(' Run: spidersan register --files "src/foo.ts"');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (options.json) {
|
|
19
|
+
console.log(JSON.stringify(branches, null, 2));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
console.log('🕷️ Registered Branches:\n');
|
|
23
|
+
for (const branch of branches) {
|
|
24
|
+
const status = branch.status === 'active' ? '🔄' :
|
|
25
|
+
branch.status === 'completed' ? '✅' : '❌';
|
|
26
|
+
const ago = getTimeAgo(new Date(branch.registeredAt));
|
|
27
|
+
console.log(` ${status} ${branch.name}`);
|
|
28
|
+
console.log(` └─ ${ago}${branch.agent ? ` | ${branch.agent}` : ''}`);
|
|
29
|
+
if (branch.files.length > 0) {
|
|
30
|
+
console.log(` └─ Files: ${branch.files.slice(0, 3).join(', ')}${branch.files.length > 3 ? ` (+${branch.files.length - 3} more)` : ''}`);
|
|
31
|
+
}
|
|
32
|
+
console.log('');
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
function getTimeAgo(date) {
|
|
36
|
+
const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000);
|
|
37
|
+
if (seconds < 60)
|
|
38
|
+
return 'Just now';
|
|
39
|
+
if (seconds < 3600)
|
|
40
|
+
return `${Math.floor(seconds / 60)} min ago`;
|
|
41
|
+
if (seconds < 86400)
|
|
42
|
+
return `${Math.floor(seconds / 3600)} hours ago`;
|
|
43
|
+
return `${Math.floor(seconds / 86400)} days ago`;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spidersan lock
|
|
3
|
+
*
|
|
4
|
+
* Claim or release locks on symbols (functions, classes, etc.)
|
|
5
|
+
* Uses CRDT for decentralized coordination, syncs via Hub.
|
|
6
|
+
*
|
|
7
|
+
* Part of Codex 5.2 implementation.
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
export declare const lockCommand: Command;
|
|
11
|
+
//# sourceMappingURL=lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+EpC,eAAO,MAAM,WAAW,SA4JlB,CAAC"}
|