@mod-computer/cli 0.2.3 → 0.2.5
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/dist/cli.bundle.js +216 -36371
- package/package.json +3 -3
- package/dist/app.js +0 -227
- package/dist/cli.bundle.js.map +0 -7
- package/dist/cli.js +0 -132
- package/dist/commands/add.js +0 -245
- package/dist/commands/agents-run.js +0 -71
- package/dist/commands/auth.js +0 -259
- package/dist/commands/branch.js +0 -1411
- package/dist/commands/claude-sync.js +0 -772
- package/dist/commands/comment.js +0 -568
- package/dist/commands/diff.js +0 -182
- package/dist/commands/index.js +0 -73
- package/dist/commands/init.js +0 -597
- package/dist/commands/ls.js +0 -135
- package/dist/commands/members.js +0 -687
- package/dist/commands/mv.js +0 -282
- package/dist/commands/recover.js +0 -207
- package/dist/commands/rm.js +0 -257
- package/dist/commands/spec.js +0 -386
- package/dist/commands/status.js +0 -296
- package/dist/commands/sync.js +0 -119
- package/dist/commands/trace.js +0 -1752
- package/dist/commands/workspace.js +0 -447
- package/dist/components/conflict-resolution-ui.js +0 -120
- package/dist/components/messages.js +0 -5
- package/dist/components/thread.js +0 -8
- package/dist/config/features.js +0 -83
- package/dist/containers/branches-container.js +0 -140
- package/dist/containers/directory-container.js +0 -92
- package/dist/containers/thread-container.js +0 -214
- package/dist/containers/threads-container.js +0 -27
- package/dist/containers/workspaces-container.js +0 -27
- package/dist/daemon/conflict-resolution.js +0 -172
- package/dist/daemon/content-hash.js +0 -31
- package/dist/daemon/file-sync.js +0 -985
- package/dist/daemon/index.js +0 -203
- package/dist/daemon/mime-types.js +0 -166
- package/dist/daemon/offline-queue.js +0 -211
- package/dist/daemon/path-utils.js +0 -64
- package/dist/daemon/share-policy.js +0 -83
- package/dist/daemon/wasm-errors.js +0 -189
- package/dist/daemon/worker.js +0 -557
- package/dist/daemon-worker.js +0 -258
- package/dist/errors/workspace-errors.js +0 -48
- package/dist/lib/auth-server.js +0 -216
- package/dist/lib/browser.js +0 -35
- package/dist/lib/diff.js +0 -284
- package/dist/lib/formatters.js +0 -204
- package/dist/lib/git.js +0 -137
- package/dist/lib/local-fs.js +0 -201
- package/dist/lib/prompts.js +0 -56
- package/dist/lib/storage.js +0 -213
- package/dist/lib/trace-formatters.js +0 -314
- package/dist/services/add-service.js +0 -554
- package/dist/services/add-validation.js +0 -124
- package/dist/services/automatic-file-tracker.js +0 -303
- package/dist/services/cli-orchestrator.js +0 -227
- package/dist/services/feature-flags.js +0 -187
- package/dist/services/file-import-service.js +0 -283
- package/dist/services/file-transformation-service.js +0 -218
- package/dist/services/logger.js +0 -44
- package/dist/services/mod-config.js +0 -67
- package/dist/services/modignore-service.js +0 -328
- package/dist/services/sync-daemon.js +0 -244
- package/dist/services/thread-notification-service.js +0 -50
- package/dist/services/thread-service.js +0 -147
- package/dist/stores/use-directory-store.js +0 -96
- package/dist/stores/use-threads-store.js +0 -46
- package/dist/stores/use-workspaces-store.js +0 -54
- package/dist/types/add-types.js +0 -99
- package/dist/types/config.js +0 -16
- package/dist/types/index.js +0 -2
- package/dist/types/workspace-connection.js +0 -53
- package/dist/types.js +0 -1
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Trace Formatters
|
|
3
|
-
* Formatting utilities for trace CLI output
|
|
4
|
-
*
|
|
5
|
-
* spec: packages/mod-cli/specs/traces-cli.md
|
|
6
|
-
*/
|
|
7
|
-
// =============================================================================
|
|
8
|
-
// List Formatters
|
|
9
|
-
// =============================================================================
|
|
10
|
-
// glassware[type="implementation", id="impl-trace-list-table--58311354", specifications="specification-spec-traces-cli-list-output--46cf3c8e"]
|
|
11
|
-
/**
|
|
12
|
-
* Format traces as a table
|
|
13
|
-
*/
|
|
14
|
-
export function formatTracesTable(traces) {
|
|
15
|
-
if (traces.length === 0) {
|
|
16
|
-
return 'No traces found.';
|
|
17
|
-
}
|
|
18
|
-
const lines = [];
|
|
19
|
-
lines.push('Traces');
|
|
20
|
-
lines.push('═'.repeat(70));
|
|
21
|
-
lines.push('');
|
|
22
|
-
// Group by node type
|
|
23
|
-
const byType = new Map();
|
|
24
|
-
for (const trace of traces) {
|
|
25
|
-
const list = byType.get(trace.nodeType) || [];
|
|
26
|
-
list.push(trace);
|
|
27
|
-
byType.set(trace.nodeType, list);
|
|
28
|
-
}
|
|
29
|
-
for (const [nodeType, typeTraces] of byType) {
|
|
30
|
-
lines.push(`${nodeType} (${typeTraces.length})`);
|
|
31
|
-
lines.push('─'.repeat(40));
|
|
32
|
-
for (const trace of typeTraces) {
|
|
33
|
-
const location = trace.location.type === 'inline'
|
|
34
|
-
? `${trace.location.file}:${trace.location.line}`
|
|
35
|
-
: `mod:${trace.location.docId}`;
|
|
36
|
-
const status = trace.status === 'orphaned' ? ' [orphaned]' : '';
|
|
37
|
-
const linkCount = trace.links.length > 0 ? ` (${trace.links.length} links)` : '';
|
|
38
|
-
lines.push(` ${trace.id}${status}${linkCount}`);
|
|
39
|
-
lines.push(` └─ ${location}`);
|
|
40
|
-
if (trace.text && trace.text !== trace.id) {
|
|
41
|
-
const truncatedText = trace.text.length > 50
|
|
42
|
-
? trace.text.slice(0, 47) + '...'
|
|
43
|
-
: trace.text;
|
|
44
|
-
lines.push(` "${truncatedText}"`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
lines.push('');
|
|
48
|
-
}
|
|
49
|
-
lines.push(`Total: ${traces.length} traces`);
|
|
50
|
-
return lines.join('\n');
|
|
51
|
-
}
|
|
52
|
-
// glassware[type="implementation", id="impl-trace-list-json--fc16c20a", specifications="specification-spec-traces-cli-json--abf2b82f"]
|
|
53
|
-
/**
|
|
54
|
-
* Format traces as JSON
|
|
55
|
-
*/
|
|
56
|
-
export function formatTracesJson(traces) {
|
|
57
|
-
return JSON.stringify({
|
|
58
|
-
traces: traces.map(t => ({
|
|
59
|
-
id: t.id,
|
|
60
|
-
nodeType: t.nodeType,
|
|
61
|
-
storage: t.storage,
|
|
62
|
-
location: t.location,
|
|
63
|
-
text: t.text,
|
|
64
|
-
status: t.status,
|
|
65
|
-
links: t.links,
|
|
66
|
-
})),
|
|
67
|
-
total: traces.length,
|
|
68
|
-
}, null, 2);
|
|
69
|
-
}
|
|
70
|
-
// =============================================================================
|
|
71
|
-
// Report Formatters
|
|
72
|
-
// =============================================================================
|
|
73
|
-
// glassware[type="implementation", id="impl-trace-report-text--5ba186be", specifications="specification-spec-traces-cli-report--2af325ed,specification-spec-traces-cli-report-content--8971542e"]
|
|
74
|
-
/**
|
|
75
|
-
* Format trace report as text
|
|
76
|
-
* @param allTests - Optional array of all tests in workspace for test coverage checking
|
|
77
|
-
*/
|
|
78
|
-
export function formatTraceReport(report, allTests = []) {
|
|
79
|
-
const lines = [];
|
|
80
|
-
const fileName = report.file.split('/').pop() || report.file;
|
|
81
|
-
lines.push(`${fileName} - Trace Report`);
|
|
82
|
-
lines.push('═'.repeat(55));
|
|
83
|
-
lines.push('');
|
|
84
|
-
if (report.traces.length === 0) {
|
|
85
|
-
lines.push('No traces found in this file.');
|
|
86
|
-
return lines.join('\n');
|
|
87
|
-
}
|
|
88
|
-
for (const item of report.traces) {
|
|
89
|
-
const trace = item.trace;
|
|
90
|
-
const statusIcon = getStatusIcon(item.status);
|
|
91
|
-
const implStatus = getImplStatus(item);
|
|
92
|
-
const testStatus = getTestStatus(item, allTests);
|
|
93
|
-
// Main trace line
|
|
94
|
-
const shortId = trace.id.split('--')[0];
|
|
95
|
-
const title = trace.text && trace.text !== trace.id
|
|
96
|
-
? trace.text.slice(0, 40)
|
|
97
|
-
: shortId;
|
|
98
|
-
lines.push(`${statusIcon} ${shortId}: ${title}`);
|
|
99
|
-
lines.push(` ${implStatus} ${testStatus}`);
|
|
100
|
-
// Show implementations (implementations point TO specs, so check incoming)
|
|
101
|
-
const implementations = item.incoming['implements'] || [];
|
|
102
|
-
for (const impl of implementations) {
|
|
103
|
-
const implLoc = impl.location.type === 'inline'
|
|
104
|
-
? `${impl.location.file}:${impl.location.line}`
|
|
105
|
-
: `mod:${impl.location.docId}`;
|
|
106
|
-
lines.push(` └─ impl: ${implLoc}`);
|
|
107
|
-
// Show tests for this implementation
|
|
108
|
-
const tests = getTestsForImpl(impl, allTests);
|
|
109
|
-
for (const test of tests) {
|
|
110
|
-
const testLoc = test.location.type === 'inline'
|
|
111
|
-
? `${test.location.file}:${test.location.line}`
|
|
112
|
-
: `mod:${test.location.docId}`;
|
|
113
|
-
lines.push(` └─ test: ${testLoc}`);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
lines.push('');
|
|
117
|
-
}
|
|
118
|
-
// Recalculate summary based on incoming edges (since implementations point TO specs)
|
|
119
|
-
let fullyLinked = 0;
|
|
120
|
-
let partiallyLinked = 0;
|
|
121
|
-
let unlinked = 0;
|
|
122
|
-
for (const item of report.traces) {
|
|
123
|
-
const impls = item.incoming['implements'] || [];
|
|
124
|
-
const hasImpl = impls.length > 0;
|
|
125
|
-
const hasTests = impls.some(impl => allTests.some(test => test.links.some(l => stripTypePrefix(l.targetId) === impl.id)));
|
|
126
|
-
if (hasImpl && hasTests) {
|
|
127
|
-
fullyLinked++;
|
|
128
|
-
}
|
|
129
|
-
else if (hasImpl) {
|
|
130
|
-
partiallyLinked++;
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
unlinked++;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
lines.push('─'.repeat(55));
|
|
137
|
-
lines.push(`Summary: ${fullyLinked}/${report.traces.length} fully linked, ` +
|
|
138
|
-
`${partiallyLinked} partial, ${unlinked} unlinked`);
|
|
139
|
-
return lines.join('\n');
|
|
140
|
-
}
|
|
141
|
-
function getStatusIcon(status) {
|
|
142
|
-
switch (status) {
|
|
143
|
-
case 'fully-linked': return '✓';
|
|
144
|
-
case 'partially-linked': return '⚠';
|
|
145
|
-
case 'unlinked': return '✗';
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function getImplStatus(item) {
|
|
149
|
-
// Implementations point TO specs, so check incoming edges
|
|
150
|
-
const hasImpl = (item.incoming['implements'] || []).length > 0;
|
|
151
|
-
return hasImpl ? '✓ Implemented' : '✗ Not implemented';
|
|
152
|
-
}
|
|
153
|
-
// Strip type prefix from link target IDs (e.g., "implementation-impl-foo--abc" -> "impl-foo--abc")
|
|
154
|
-
function stripTypePrefix(targetId) {
|
|
155
|
-
const prefixes = ['implementation-', 'specification-', 'requirement-', 'test-'];
|
|
156
|
-
for (const prefix of prefixes) {
|
|
157
|
-
if (targetId.startsWith(prefix)) {
|
|
158
|
-
return targetId.slice(prefix.length);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return targetId;
|
|
162
|
-
}
|
|
163
|
-
function getTestStatus(item, allTests) {
|
|
164
|
-
// Check if any incoming implementations have tests pointing TO them
|
|
165
|
-
const impls = item.incoming['implements'] || [];
|
|
166
|
-
for (const impl of impls) {
|
|
167
|
-
// Find tests that link to this implementation (strip type prefix from targetId)
|
|
168
|
-
const hasTest = allTests.some(test => test.links.some(l => stripTypePrefix(l.targetId) === impl.id));
|
|
169
|
-
if (hasTest) {
|
|
170
|
-
return '✓ Tested';
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return impls.length > 0 ? '✗ No tests' : '';
|
|
174
|
-
}
|
|
175
|
-
function getTestsForImpl(impl, allTests) {
|
|
176
|
-
// Find tests that link to this implementation (strip type prefix from targetId)
|
|
177
|
-
return allTests.filter(test => test.links.some(l => stripTypePrefix(l.targetId) === impl.id));
|
|
178
|
-
}
|
|
179
|
-
// glassware[type="implementation", id="impl-trace-report-json--10381dca", specifications="specification-spec-traces-cli-report-json--0a0ddd0d"]
|
|
180
|
-
/**
|
|
181
|
-
* Format trace report as JSON
|
|
182
|
-
* @param allTests - Optional array of all tests in workspace for test coverage checking
|
|
183
|
-
*/
|
|
184
|
-
export function formatTraceReportJson(report, allTests = []) {
|
|
185
|
-
// TODO: Could enhance JSON output with test coverage info from allTests
|
|
186
|
-
return JSON.stringify(report, null, 2);
|
|
187
|
-
}
|
|
188
|
-
// =============================================================================
|
|
189
|
-
// Coverage Formatters
|
|
190
|
-
// =============================================================================
|
|
191
|
-
// glassware[type="implementation", id="impl-trace-coverage-text--45e4276a", specifications="specification-spec-traces-cli-coverage--571a6cbb,specification-spec-traces-cli-coverage-visual--d06a6e97"]
|
|
192
|
-
/**
|
|
193
|
-
* Format coverage report as text with progress bars
|
|
194
|
-
*/
|
|
195
|
-
export function formatCoverageReport(coverage) {
|
|
196
|
-
const lines = [];
|
|
197
|
-
lines.push('Trace Coverage');
|
|
198
|
-
lines.push('═'.repeat(55));
|
|
199
|
-
lines.push('');
|
|
200
|
-
// Per node type stats
|
|
201
|
-
for (const [nodeType, stats] of Object.entries(coverage.byNodeType)) {
|
|
202
|
-
if (stats.total === 0)
|
|
203
|
-
continue;
|
|
204
|
-
const linkedCount = stats.fullyLinked + stats.partiallyLinked;
|
|
205
|
-
const percentage = Math.round((linkedCount / stats.total) * 100);
|
|
206
|
-
const bar = createProgressBar(percentage);
|
|
207
|
-
lines.push(`${nodeType}:`);
|
|
208
|
-
lines.push(` ${bar} ${percentage}% (${linkedCount}/${stats.total} linked)`);
|
|
209
|
-
}
|
|
210
|
-
lines.push('');
|
|
211
|
-
lines.push('─'.repeat(55));
|
|
212
|
-
// Summary
|
|
213
|
-
const { summary } = coverage;
|
|
214
|
-
lines.push(`Total traces: ${summary.totalTraces}`);
|
|
215
|
-
lines.push(`Fully linked: ${summary.fullyLinked}`);
|
|
216
|
-
lines.push(`Coverage: ${summary.coveragePercentage.toFixed(1)}%`);
|
|
217
|
-
// Gaps
|
|
218
|
-
if (coverage.orphaned.length > 0) {
|
|
219
|
-
lines.push('');
|
|
220
|
-
lines.push(`⚠ Orphaned traces: ${coverage.orphaned.length}`);
|
|
221
|
-
}
|
|
222
|
-
const missingCount = Object.values(coverage.missingEdges).reduce((sum, arr) => sum + arr.length, 0);
|
|
223
|
-
if (missingCount > 0) {
|
|
224
|
-
lines.push(`⚠ Missing edges: ${missingCount}`);
|
|
225
|
-
}
|
|
226
|
-
return lines.join('\n');
|
|
227
|
-
}
|
|
228
|
-
function createProgressBar(percentage, width = 16) {
|
|
229
|
-
const filled = Math.round((percentage / 100) * width);
|
|
230
|
-
const empty = width - filled;
|
|
231
|
-
return '█'.repeat(filled) + '░'.repeat(empty);
|
|
232
|
-
}
|
|
233
|
-
// glassware[type="implementation", id="impl-trace-coverage-json--f30dd68a", specifications="specification-spec-traces-cli-coverage-json--f23ec095"]
|
|
234
|
-
/**
|
|
235
|
-
* Format coverage report as JSON
|
|
236
|
-
*/
|
|
237
|
-
export function formatCoverageJson(coverage) {
|
|
238
|
-
// Transform to agent-friendly format
|
|
239
|
-
const requirements = coverage.byNodeType['requirement'] || { total: 0, fullyLinked: 0, partiallyLinked: 0, unlinked: 0 };
|
|
240
|
-
const implementations = coverage.byNodeType['implementation'] || { total: 0, fullyLinked: 0, partiallyLinked: 0, unlinked: 0 };
|
|
241
|
-
return JSON.stringify({
|
|
242
|
-
coverage: {
|
|
243
|
-
requirements: {
|
|
244
|
-
total: requirements.total,
|
|
245
|
-
implemented: requirements.fullyLinked + requirements.partiallyLinked,
|
|
246
|
-
},
|
|
247
|
-
implementations: {
|
|
248
|
-
total: implementations.total,
|
|
249
|
-
tested: implementations.fullyLinked,
|
|
250
|
-
},
|
|
251
|
-
},
|
|
252
|
-
byNodeType: coverage.byNodeType,
|
|
253
|
-
summary: coverage.summary,
|
|
254
|
-
orphaned: coverage.orphaned.map(t => ({
|
|
255
|
-
id: t.id,
|
|
256
|
-
nodeType: t.nodeType,
|
|
257
|
-
file: t.location.type === 'inline' ? t.location.file : undefined,
|
|
258
|
-
line: t.location.type === 'inline' ? t.location.line : undefined,
|
|
259
|
-
})),
|
|
260
|
-
missingEdges: Object.fromEntries(Object.entries(coverage.missingEdges).map(([edge, traces]) => [
|
|
261
|
-
edge,
|
|
262
|
-
traces.map(t => ({
|
|
263
|
-
id: t.id,
|
|
264
|
-
nodeType: t.nodeType,
|
|
265
|
-
file: t.location.type === 'inline' ? t.location.file : undefined,
|
|
266
|
-
})),
|
|
267
|
-
])),
|
|
268
|
-
}, null, 2);
|
|
269
|
-
}
|
|
270
|
-
// =============================================================================
|
|
271
|
-
// Unmet Requirements Formatter
|
|
272
|
-
// =============================================================================
|
|
273
|
-
// glassware[type="implementation", id="impl-trace-unmet-text--fc495826", specifications="specification-spec-traces-cli-unmet--1c11203e,specification-spec-traces-cli-unmet-output--623dd824"]
|
|
274
|
-
/**
|
|
275
|
-
* Format unmet requirements list
|
|
276
|
-
*/
|
|
277
|
-
export function formatUnmetRequirements(traces) {
|
|
278
|
-
if (traces.length === 0) {
|
|
279
|
-
return 'All requirements have implementations! 🎉';
|
|
280
|
-
}
|
|
281
|
-
const lines = [];
|
|
282
|
-
lines.push('Unmet Requirements');
|
|
283
|
-
lines.push('═'.repeat(55));
|
|
284
|
-
lines.push('');
|
|
285
|
-
for (const trace of traces) {
|
|
286
|
-
const location = trace.location.type === 'inline'
|
|
287
|
-
? `${trace.location.file}:${trace.location.line}`
|
|
288
|
-
: `mod:${trace.location.docId}`;
|
|
289
|
-
const title = trace.text && trace.text !== trace.id
|
|
290
|
-
? trace.text.slice(0, 50)
|
|
291
|
-
: trace.id.split('--')[0];
|
|
292
|
-
lines.push(`✗ ${trace.id}`);
|
|
293
|
-
lines.push(` "${title}"`);
|
|
294
|
-
lines.push(` └─ ${location}`);
|
|
295
|
-
lines.push('');
|
|
296
|
-
}
|
|
297
|
-
lines.push(`Total: ${traces.length} unmet requirements`);
|
|
298
|
-
return lines.join('\n');
|
|
299
|
-
}
|
|
300
|
-
// glassware[type="implementation", id="impl-trace-unmet-json--aa05049d", specifications="specification-spec-traces-cli-json--abf2b82f"]
|
|
301
|
-
/**
|
|
302
|
-
* Format unmet requirements as JSON
|
|
303
|
-
*/
|
|
304
|
-
export function formatUnmetJson(traces) {
|
|
305
|
-
return JSON.stringify({
|
|
306
|
-
unmet: traces.map(t => ({
|
|
307
|
-
id: t.id,
|
|
308
|
-
title: t.text || t.id.split('--')[0],
|
|
309
|
-
file: t.location.type === 'inline' ? t.location.file : undefined,
|
|
310
|
-
line: t.location.type === 'inline' ? t.location.line : undefined,
|
|
311
|
-
})),
|
|
312
|
-
total: traces.length,
|
|
313
|
-
}, null, 2);
|
|
314
|
-
}
|