vgxness 1.2.1 → 1.3.1
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/README.md +20 -19
- package/dist/cli/cli-help.js +4 -7
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +150 -0
- package/dist/cli/commands/setup-dispatcher.js +11 -8
- package/dist/cli/dispatcher.js +1 -8
- package/dist/cli/doctor-renderer.js +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/cli/sdd-renderer.js +7 -7
- package/dist/cli/setup-status-renderer.js +1 -0
- package/dist/cli/tui/main-menu/index.js +0 -1
- package/dist/cli/tui/main-menu/main-menu-controller.js +0 -2
- package/dist/cli/tui/main-menu/main-menu-read-model.js +10 -8
- package/dist/cli/tui/main-menu/main-menu-render-shape.js +19 -2
- package/dist/cli/tui/main-menu/main-menu-state.js +1 -1
- package/dist/cli/tui/opentui/code/index.js +210 -0
- package/dist/cli/tui/opentui/code/screen.js +107 -0
- package/dist/cli/tui/opentui/code/smoke.js +32 -0
- package/dist/cli/tui/opentui/main-menu/index.js +3 -0
- package/dist/cli/tui/opentui/main-menu/renderer.js +68 -0
- package/dist/cli/tui/opentui/main-menu/screen.js +68 -0
- package/dist/cli/tui/opentui/main-menu/smoke.js +17 -0
- package/dist/cli/tui/opentui/main-menu/view.js +8 -0
- package/dist/cli/tui/opentui/setup/index.js +3 -0
- package/dist/cli/tui/opentui/setup/renderer.js +87 -0
- package/dist/cli/tui/opentui/setup/screen.js +170 -0
- package/dist/cli/tui/opentui/setup/smoke.js +42 -0
- package/dist/cli/tui/opentui/setup/view.js +12 -0
- package/dist/cli/tui/setup/setup-tui-input.js +43 -0
- package/dist/cli/tui/setup/setup-tui-read-model.js +4 -4
- package/dist/cli/tui/setup/setup-tui-render-shape.js +9 -10
- package/dist/cli/tui/setup/setup-tui-state.js +1 -1
- package/dist/cli/tui/setup/setup-tui-view-helpers.js +46 -0
- package/dist/cli/tui/visual/index.js +0 -2
- package/dist/code/runtime/sdd-context.js +2 -2
- package/dist/code/tui/approval-actions.js +33 -0
- package/dist/code/tui/prompt-mode.js +11 -0
- package/dist/code/tui/runtime-events.js +320 -0
- package/dist/mcp/validation.js +6 -2
- package/dist/orchestrator/natural-language-planner.js +1 -1
- package/dist/sdd/sdd-workflow-service.js +1 -25
- package/dist/setup/backup-rollback-service.js +2 -2
- package/dist/setup/providers/antigravity-setup-adapter.js +1 -1
- package/dist/setup/providers/claude-setup-adapter.js +2 -2
- package/dist/setup/providers/custom-setup-adapter.js +1 -1
- package/dist/setup/providers/opencode-setup-adapter.js +3 -3
- package/dist/setup/setup-lifecycle-service.js +6 -6
- package/dist/setup/setup-plan.js +3 -3
- package/dist/verification/verification-plan-service.js +1 -1
- package/docs/architecture.md +43 -42
- package/docs/cli.md +141 -133
- package/docs/funcionamiento-del-sistema.md +22 -23
- package/docs/harness-gap-analysis.md +15 -1
- package/docs/prd.md +14 -14
- package/docs/vgxcode.md +87 -0
- package/docs/vgxness-code.md +6 -4
- package/package.json +5 -6
- package/dist/cli/commands/dashboard-dispatcher.js +0 -560
- package/dist/cli/dashboard-operational-read-models.js +0 -428
- package/dist/cli/dashboard-renderer.js +0 -158
- package/dist/cli/dashboard-screen-renderers.js +0 -256
- package/dist/cli/dashboard-tui-read-model.js +0 -73
- package/dist/cli/dashboard-tui-state.js +0 -314
- package/dist/cli/guided-main-menu.js +0 -470
- package/dist/cli/interactive-dashboard.js +0 -34
- package/dist/cli/setup-wizard-read-model.js +0 -72
- package/dist/cli/setup-wizard-renderer.js +0 -155
- package/dist/cli/setup-wizard-state.js +0 -82
- package/dist/cli/tui/dashboard/dashboard-adapter.js +0 -4
- package/dist/cli/tui/main-menu/main-menu-app.js +0 -28
- package/dist/cli/tui/render-ink-app.js +0 -10
- package/dist/cli/tui/setup/screens/applying-screen.js +0 -6
- package/dist/cli/tui/setup/screens/cancellation-screen.js +0 -6
- package/dist/cli/tui/setup/screens/error-recovery-screen.js +0 -6
- package/dist/cli/tui/setup/screens/final-confirmation-screen.js +0 -6
- package/dist/cli/tui/setup/screens/opencode-details-screen.js +0 -10
- package/dist/cli/tui/setup/screens/plan-review-screen.js +0 -6
- package/dist/cli/tui/setup/screens/project-database-screen.js +0 -6
- package/dist/cli/tui/setup/screens/provider-screen.js +0 -7
- package/dist/cli/tui/setup/screens/result-screen.js +0 -16
- package/dist/cli/tui/setup/screens/screen-components.js +0 -103
- package/dist/cli/tui/setup/screens/welcome-screen.js +0 -6
- package/dist/cli/tui/setup/setup-tui-app.js +0 -113
- package/dist/cli/tui/visual/choice-list.js +0 -10
- package/dist/cli/tui/visual/layout.js +0 -10
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
export function sampleEvents(now = new Date('2026-05-26T23:30:00.000Z')) {
|
|
2
|
+
const createdAt = now.toISOString();
|
|
3
|
+
return [
|
|
4
|
+
{
|
|
5
|
+
type: 'session.started',
|
|
6
|
+
projectRoot: 'vgxness',
|
|
7
|
+
userIntent: 'Build the vgxcode OpenTUI shell',
|
|
8
|
+
createdAt,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
type: 'provider.message',
|
|
12
|
+
content: 'I will inspect the runtime event stream and prepare a safe UI shell.',
|
|
13
|
+
toolCallCount: 1,
|
|
14
|
+
createdAt,
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: 'tool.requested',
|
|
18
|
+
toolName: 'read_file',
|
|
19
|
+
createdAt,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'tool.completed',
|
|
23
|
+
toolName: 'read_file',
|
|
24
|
+
ok: true,
|
|
25
|
+
changedFiles: [],
|
|
26
|
+
createdAt,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: 'verification.completed',
|
|
30
|
+
status: 'not-run',
|
|
31
|
+
reason: 'Static shell preview; no runtime commands executed.',
|
|
32
|
+
createdAt,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'session.completed',
|
|
36
|
+
status: 'completed',
|
|
37
|
+
outcome: 'success',
|
|
38
|
+
createdAt,
|
|
39
|
+
},
|
|
40
|
+
];
|
|
41
|
+
}
|
|
42
|
+
export function parseVgxcodeJsonl(input) {
|
|
43
|
+
const events = [];
|
|
44
|
+
const errors = [];
|
|
45
|
+
const lines = input.split(/\r?\n/);
|
|
46
|
+
for (const [index, line] of lines.entries()) {
|
|
47
|
+
const trimmed = line.trim();
|
|
48
|
+
if (!trimmed)
|
|
49
|
+
continue;
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(trimmed);
|
|
52
|
+
if (isVgxcodeEvent(parsed))
|
|
53
|
+
events.push(parsed);
|
|
54
|
+
else
|
|
55
|
+
errors.push(formatUnsupportedRuntimeEvent(parsed, index + 1));
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
errors.push(`Line ${index + 1}: ${formatJsonlParseError(trimmed, error)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return { events, errors };
|
|
62
|
+
}
|
|
63
|
+
export function parseVgxcodeJsonlLine(line, lineNumber) {
|
|
64
|
+
const trimmed = line.trim();
|
|
65
|
+
if (!trimmed)
|
|
66
|
+
return {};
|
|
67
|
+
try {
|
|
68
|
+
const parsed = JSON.parse(trimmed);
|
|
69
|
+
if (isVgxcodeEvent(parsed))
|
|
70
|
+
return { event: parsed };
|
|
71
|
+
return { error: formatUnsupportedRuntimeEvent(parsed, lineNumber) };
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return { error: `Line ${lineNumber}: ${formatJsonlParseError(trimmed, error)}` };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function formatJsonlParseError(line, error) {
|
|
78
|
+
const reason = error instanceof Error ? error.message : 'invalid JSON';
|
|
79
|
+
const looksLikeNpmBanner = line.startsWith('>') || line.includes('npm') || line.includes('run-script');
|
|
80
|
+
const snippet = line.length > 80 ? `${line.slice(0, 77)}...` : line;
|
|
81
|
+
return looksLikeNpmBanner
|
|
82
|
+
? `${reason} (non-JSON output; use npm --silent for the bridge; got: ${snippet})`
|
|
83
|
+
: `${reason} (invalid JSONL; got: ${snippet})`;
|
|
84
|
+
}
|
|
85
|
+
function formatUnsupportedRuntimeEvent(value, lineNumber) {
|
|
86
|
+
const type = isRecord(value) && typeof value.type === 'string' ? value.type : 'missing type';
|
|
87
|
+
return `Line ${lineNumber}: unsupported runtime event (${type}); expected vgxcode read-only JSONL event`;
|
|
88
|
+
}
|
|
89
|
+
export function summarizeEvent(event) {
|
|
90
|
+
switch (event.type) {
|
|
91
|
+
case 'session.started':
|
|
92
|
+
return `◇ Session started — ${event.userIntent}`;
|
|
93
|
+
case 'prompt.accepted':
|
|
94
|
+
return `◇ Prompt accepted — ${event.messageCount} messages, ${event.toolCount} tools`;
|
|
95
|
+
case 'provider.message':
|
|
96
|
+
return `● Assistant — ${event.content}`;
|
|
97
|
+
case 'tool.requested':
|
|
98
|
+
return `▸ Tool requested — ${event.toolName}`;
|
|
99
|
+
case 'approval.pending':
|
|
100
|
+
return `! Approval pending — ${event.toolName}`;
|
|
101
|
+
case 'approval.decided':
|
|
102
|
+
return `! Approval ${event.final} — ${event.toolName}: ${event.reason}`;
|
|
103
|
+
case 'approval.decision_rejected':
|
|
104
|
+
return `! Approval decision rejected — ${event.bindingResult}: ${event.reason}`;
|
|
105
|
+
case 'approval.preview':
|
|
106
|
+
return `! Approval preview — ${event.toolName}: No mutation executed`;
|
|
107
|
+
case 'tool.completed':
|
|
108
|
+
return `${event.ok ? '✓' : '✕'} Tool completed — ${event.toolName}`;
|
|
109
|
+
case 'diff.preview':
|
|
110
|
+
return `◇ Diff preview — ${event.files.length} files, ${event.bodyBytes}/${event.originalBytes} bytes${event.truncated ? ' (truncated)' : ''}`;
|
|
111
|
+
case 'verification.completed':
|
|
112
|
+
return `${event.status === 'passed' ? '✓' : event.status === 'failed' ? '✕' : '·'} Verification — ${event.reason}`;
|
|
113
|
+
case 'session.completed':
|
|
114
|
+
return `◆ Session ${event.status} — ${event.outcome}`;
|
|
115
|
+
case 'session.failed':
|
|
116
|
+
return `✕ Session ${event.status} — ${event.message}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function buildSafetyReadModel(events) {
|
|
120
|
+
const pendingApprovals = new Map();
|
|
121
|
+
let latestApprovalDecision;
|
|
122
|
+
let latestApprovalPreview;
|
|
123
|
+
const changedFiles = [];
|
|
124
|
+
const seenChangedFiles = new Set();
|
|
125
|
+
let latestDiffPreview;
|
|
126
|
+
for (const event of events) {
|
|
127
|
+
switch (event.type) {
|
|
128
|
+
case 'approval.pending':
|
|
129
|
+
if (event.approvalId === undefined || event.toolCallId === undefined)
|
|
130
|
+
break;
|
|
131
|
+
pendingApprovals.set(approvalKey(event.approvalId, event.toolCallId), {
|
|
132
|
+
...(event.approvalId === undefined ? {} : { approvalId: event.approvalId }),
|
|
133
|
+
...(event.toolCallId === undefined ? {} : { toolCallId: event.toolCallId }),
|
|
134
|
+
toolName: event.toolName,
|
|
135
|
+
...(event.operationSummary === undefined ? {} : { operationSummary: event.operationSummary }),
|
|
136
|
+
...(event.targetPath === undefined ? {} : { targetPath: event.targetPath }),
|
|
137
|
+
...(event.risk === undefined ? {} : { risk: event.risk }),
|
|
138
|
+
createdAt: event.createdAt,
|
|
139
|
+
});
|
|
140
|
+
break;
|
|
141
|
+
case 'approval.decided':
|
|
142
|
+
if (event.approvalId !== undefined && event.toolCallId !== undefined)
|
|
143
|
+
pendingApprovals.delete(approvalKey(event.approvalId, event.toolCallId));
|
|
144
|
+
latestApprovalDecision = {
|
|
145
|
+
...(event.approvalId === undefined ? {} : { approvalId: event.approvalId }),
|
|
146
|
+
...(event.toolCallId === undefined ? {} : { toolCallId: event.toolCallId }),
|
|
147
|
+
toolName: event.toolName,
|
|
148
|
+
...(event.status === undefined ? {} : { status: event.status }),
|
|
149
|
+
final: event.final,
|
|
150
|
+
reason: event.reason,
|
|
151
|
+
createdAt: event.createdAt,
|
|
152
|
+
};
|
|
153
|
+
break;
|
|
154
|
+
case 'approval.decision_rejected':
|
|
155
|
+
if (event.approvalId !== undefined && event.toolCallId !== undefined && isResolvingDecisionRejection(event.bindingResult)) {
|
|
156
|
+
pendingApprovals.delete(approvalKey(event.approvalId, event.toolCallId));
|
|
157
|
+
}
|
|
158
|
+
break;
|
|
159
|
+
case 'approval.preview':
|
|
160
|
+
latestApprovalPreview = {
|
|
161
|
+
toolName: event.toolName,
|
|
162
|
+
capability: event.capability,
|
|
163
|
+
...(event.targetPath === undefined ? {} : { targetPath: event.targetPath }),
|
|
164
|
+
reason: event.reason,
|
|
165
|
+
risk: event.risk,
|
|
166
|
+
createdAt: event.createdAt,
|
|
167
|
+
};
|
|
168
|
+
break;
|
|
169
|
+
case 'tool.completed':
|
|
170
|
+
for (const changedFile of event.changedFiles) {
|
|
171
|
+
if (seenChangedFiles.has(changedFile))
|
|
172
|
+
continue;
|
|
173
|
+
seenChangedFiles.add(changedFile);
|
|
174
|
+
changedFiles.push(changedFile);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
case 'diff.preview':
|
|
178
|
+
latestDiffPreview = {
|
|
179
|
+
files: event.files,
|
|
180
|
+
body: event.body,
|
|
181
|
+
bodyBytes: event.bodyBytes,
|
|
182
|
+
originalBytes: event.originalBytes,
|
|
183
|
+
truncated: event.truncated,
|
|
184
|
+
redacted: event.redacted,
|
|
185
|
+
hash: event.hash,
|
|
186
|
+
createdAt: event.createdAt,
|
|
187
|
+
};
|
|
188
|
+
for (const file of event.files) {
|
|
189
|
+
if (seenChangedFiles.has(file))
|
|
190
|
+
continue;
|
|
191
|
+
seenChangedFiles.add(file);
|
|
192
|
+
changedFiles.push(file);
|
|
193
|
+
}
|
|
194
|
+
break;
|
|
195
|
+
default:
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const pendingApprovalValues = [...pendingApprovals.values()];
|
|
200
|
+
const latestPendingApproval = pendingApprovalValues.at(-1);
|
|
201
|
+
return {
|
|
202
|
+
pendingApprovals: pendingApprovalValues,
|
|
203
|
+
pendingApprovalCount: pendingApprovalValues.length,
|
|
204
|
+
...(latestPendingApproval ? { latestPendingApproval } : {}),
|
|
205
|
+
...(latestApprovalDecision ? { latestApprovalDecision } : {}),
|
|
206
|
+
...(latestApprovalPreview ? { latestApprovalPreview } : {}),
|
|
207
|
+
changedFiles,
|
|
208
|
+
diffAvailability: latestDiffPreview !== undefined ? 'preview' : changedFiles.length > 0 ? 'filenames-only' : 'none',
|
|
209
|
+
...(latestDiffPreview ? { latestDiffPreview } : {}),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function isVgxcodeEvent(value) {
|
|
213
|
+
if (!isRecord(value) || typeof value.type !== 'string' || typeof value.createdAt !== 'string')
|
|
214
|
+
return false;
|
|
215
|
+
switch (value.type) {
|
|
216
|
+
case 'session.started':
|
|
217
|
+
return typeof value.projectRoot === 'string' && typeof value.userIntent === 'string';
|
|
218
|
+
case 'prompt.accepted':
|
|
219
|
+
return typeof value.messageCount === 'number' && typeof value.toolCount === 'number';
|
|
220
|
+
case 'provider.message':
|
|
221
|
+
return typeof value.content === 'string' && typeof value.toolCallCount === 'number';
|
|
222
|
+
case 'tool.requested':
|
|
223
|
+
return typeof value.toolName === 'string';
|
|
224
|
+
case 'approval.pending':
|
|
225
|
+
return typeof value.toolName === 'string' && isOptionalApprovalContext(value);
|
|
226
|
+
case 'approval.decided':
|
|
227
|
+
return (typeof value.toolName === 'string' &&
|
|
228
|
+
typeof value.reason === 'string' &&
|
|
229
|
+
isApprovalFinal(value.final) &&
|
|
230
|
+
(value.approvalId === undefined || typeof value.approvalId === 'string') &&
|
|
231
|
+
(value.toolCallId === undefined || typeof value.toolCallId === 'string') &&
|
|
232
|
+
(value.status === undefined || isApprovalStatus(value.status)));
|
|
233
|
+
case 'approval.decision_rejected':
|
|
234
|
+
return (typeof value.reason === 'string' &&
|
|
235
|
+
isApprovalDecisionBindingResult(value.bindingResult) &&
|
|
236
|
+
(value.approvalId === undefined || typeof value.approvalId === 'string') &&
|
|
237
|
+
(value.toolCallId === undefined || typeof value.toolCallId === 'string') &&
|
|
238
|
+
(value.status === undefined || value.status === 'approved' || value.status === 'denied'));
|
|
239
|
+
case 'approval.preview':
|
|
240
|
+
return (typeof value.toolCallId === 'string' &&
|
|
241
|
+
typeof value.toolName === 'string' &&
|
|
242
|
+
isCapability(value.capability) &&
|
|
243
|
+
isRecord(value.risk) &&
|
|
244
|
+
typeof value.risk.mutatesWorkspace === 'boolean' &&
|
|
245
|
+
typeof value.risk.requiresApproval === 'boolean' &&
|
|
246
|
+
value.reason === 'preview_only' &&
|
|
247
|
+
(value.targetPath === undefined || typeof value.targetPath === 'string'));
|
|
248
|
+
case 'tool.completed':
|
|
249
|
+
return typeof value.toolName === 'string' && typeof value.ok === 'boolean' && Array.isArray(value.changedFiles) && value.changedFiles.every((changedFile) => typeof changedFile === 'string');
|
|
250
|
+
case 'diff.preview':
|
|
251
|
+
return (typeof value.sourceToolCallId === 'string' &&
|
|
252
|
+
value.sourceToolName === 'git_diff' &&
|
|
253
|
+
value.format === 'unified' &&
|
|
254
|
+
Array.isArray(value.files) &&
|
|
255
|
+
value.files.every((file) => typeof file === 'string') &&
|
|
256
|
+
typeof value.body === 'string' &&
|
|
257
|
+
typeof value.bodyBytes === 'number' &&
|
|
258
|
+
typeof value.originalBytes === 'number' &&
|
|
259
|
+
typeof value.truncated === 'boolean' &&
|
|
260
|
+
typeof value.redacted === 'boolean' &&
|
|
261
|
+
typeof value.hash === 'string');
|
|
262
|
+
case 'verification.completed':
|
|
263
|
+
return isVerificationStatus(value.status) && typeof value.reason === 'string';
|
|
264
|
+
case 'session.completed':
|
|
265
|
+
return isSessionStatus(value.status) && isOutcome(value.outcome);
|
|
266
|
+
case 'session.failed':
|
|
267
|
+
return isFailedSessionStatus(value.status) && typeof value.message === 'string';
|
|
268
|
+
default:
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function isRecord(value) {
|
|
273
|
+
return typeof value === 'object' && value !== null;
|
|
274
|
+
}
|
|
275
|
+
function isApprovalFinal(value) {
|
|
276
|
+
return value === 'allow' || value === 'deny' || value === 'blocked';
|
|
277
|
+
}
|
|
278
|
+
function isApprovalStatus(value) {
|
|
279
|
+
return value === 'approved' || value === 'denied' || value === 'blocked' || value === 'cancelled' || value === 'timed_out';
|
|
280
|
+
}
|
|
281
|
+
function isApprovalDecisionBindingResult(value) {
|
|
282
|
+
return value === 'malformed' || value === 'unknown' || value === 'binding_mismatch' || value === 'duplicate' || value === 'stale' || value === 'invalid_status' || value === 'cancelled';
|
|
283
|
+
}
|
|
284
|
+
function isResolvingDecisionRejection(bindingResult) {
|
|
285
|
+
return bindingResult === 'duplicate' || bindingResult === 'stale' || bindingResult === 'cancelled';
|
|
286
|
+
}
|
|
287
|
+
function approvalKey(approvalId, toolCallId) {
|
|
288
|
+
return `${approvalId}:${toolCallId}`;
|
|
289
|
+
}
|
|
290
|
+
function isOptionalApprovalContext(value) {
|
|
291
|
+
return ((value.approvalId === undefined || typeof value.approvalId === 'string') &&
|
|
292
|
+
(value.toolCallId === undefined || typeof value.toolCallId === 'string') &&
|
|
293
|
+
(value.operationSummary === undefined || typeof value.operationSummary === 'string') &&
|
|
294
|
+
(value.targetPath === undefined || typeof value.targetPath === 'string') &&
|
|
295
|
+
(value.risk === undefined || isApprovalRisk(value.risk)));
|
|
296
|
+
}
|
|
297
|
+
function isApprovalRisk(value) {
|
|
298
|
+
return (isRecord(value) &&
|
|
299
|
+
typeof value.mutatesWorkspace === 'boolean' &&
|
|
300
|
+
typeof value.requiresApproval === 'boolean' &&
|
|
301
|
+
(value.destructive === undefined || typeof value.destructive === 'boolean') &&
|
|
302
|
+
(value.external === undefined || typeof value.external === 'boolean') &&
|
|
303
|
+
(value.privileged === undefined || typeof value.privileged === 'boolean') &&
|
|
304
|
+
(value.ambiguous === undefined || typeof value.ambiguous === 'boolean'));
|
|
305
|
+
}
|
|
306
|
+
function isCapability(value) {
|
|
307
|
+
return value === 'read' || value === 'edit' || value === 'shell' || value === 'git' || value === 'network' || value === 'memory' || value === 'sdd' || value === 'run' || value === 'mcp';
|
|
308
|
+
}
|
|
309
|
+
function isVerificationStatus(value) {
|
|
310
|
+
return value === 'not-run' || value === 'passed' || value === 'failed';
|
|
311
|
+
}
|
|
312
|
+
function isSessionStatus(value) {
|
|
313
|
+
return value === 'completed' || value === 'partial' || value === 'blocked' || value === 'failed' || value === 'cancelled';
|
|
314
|
+
}
|
|
315
|
+
function isFailedSessionStatus(value) {
|
|
316
|
+
return value === 'blocked' || value === 'failed' || value === 'cancelled';
|
|
317
|
+
}
|
|
318
|
+
function isOutcome(value) {
|
|
319
|
+
return value === 'success' || value === 'partial' || value === 'failure' || value === 'blocked' || value === 'cancelled';
|
|
320
|
+
}
|
package/dist/mcp/validation.js
CHANGED
|
@@ -244,7 +244,7 @@ function readProjectAndChange(record, tool) {
|
|
|
244
244
|
return { ok: true, value: { project: project.value, change: change.value } };
|
|
245
245
|
}
|
|
246
246
|
function validateSddReadyInput(input, tool) {
|
|
247
|
-
const record = inputRecord(input, tool, ['project', 'change', 'phase']);
|
|
247
|
+
const record = inputRecord(input, tool, ['project', 'change', 'phase', 'runId', 'agentId']);
|
|
248
248
|
if (!record.ok)
|
|
249
249
|
return record;
|
|
250
250
|
const base = readProjectAndChange(record.value, tool);
|
|
@@ -253,7 +253,11 @@ function validateSddReadyInput(input, tool) {
|
|
|
253
253
|
const phase = readPhase(record.value, tool);
|
|
254
254
|
if (!phase.ok)
|
|
255
255
|
return phase;
|
|
256
|
-
|
|
256
|
+
const result = { ...base.value, phase: phase.value };
|
|
257
|
+
const copied = copyOptionalStrings(result, record.value, tool, ['runId', 'agentId']);
|
|
258
|
+
if (!copied.ok)
|
|
259
|
+
return copied;
|
|
260
|
+
return { ok: true, value: result };
|
|
257
261
|
}
|
|
258
262
|
function validateSddGetReadinessInput(input, tool) {
|
|
259
263
|
return validateSddReadyInput(input, tool);
|
|
@@ -226,7 +226,7 @@ function buildPreviewActions(input, flow, needsClarification) {
|
|
|
226
226
|
if (flow === 'build')
|
|
227
227
|
return [{ kind: 'workflow-preview', description: 'Preview a scoped build workflow; no execution occurs in this planner response.' }];
|
|
228
228
|
const change = input.change;
|
|
229
|
-
const command = change === undefined ? undefined : `
|
|
229
|
+
const command = change === undefined ? undefined : `vgxness sdd next --project ${input.project} --change ${change}`;
|
|
230
230
|
return [
|
|
231
231
|
{
|
|
232
232
|
kind: 'sdd-preview',
|
|
@@ -38,30 +38,6 @@ export class SddWorkflowService {
|
|
|
38
38
|
const phases = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
39
39
|
return statusFromPhases(validated.value.change, phases);
|
|
40
40
|
}
|
|
41
|
-
getDashboardStatus(input) {
|
|
42
|
-
const validated = validateProjectAndChange(input.project, input.change);
|
|
43
|
-
if (!validated.ok)
|
|
44
|
-
return validated;
|
|
45
|
-
const phases = this.getPhaseStatusesNoTrace(validated.value.project, validated.value.change);
|
|
46
|
-
if (!phases.ok)
|
|
47
|
-
return phases;
|
|
48
|
-
return statusFromPhases(validated.value.change, phases.value);
|
|
49
|
-
}
|
|
50
|
-
getPhaseStatusesNoTrace(project, change) {
|
|
51
|
-
const statuses = [];
|
|
52
|
-
for (const phase of sddPhases) {
|
|
53
|
-
const topicKey = sddTopicKey(change, phase);
|
|
54
|
-
const artifact = this.memory.getArtifactNoTrace(project, topicKey);
|
|
55
|
-
if (!artifact.ok) {
|
|
56
|
-
if (artifact.error.code !== 'not_found')
|
|
57
|
-
return artifact;
|
|
58
|
-
statuses.push({ phase, topicKey, present: false, state: 'missing', accepted: false, legacy: false });
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
statuses.push(phaseStatusFromArtifact(phase, topicKey, artifact.value));
|
|
62
|
-
}
|
|
63
|
-
return { ok: true, value: statuses };
|
|
64
|
-
}
|
|
65
41
|
getNext(input) {
|
|
66
42
|
const validated = validateProjectAndChange(input.project, input.change);
|
|
67
43
|
if (!validated.ok)
|
|
@@ -120,7 +96,7 @@ export class SddWorkflowService {
|
|
|
120
96
|
acceptedCount: cockpitPhases.filter((phase) => phase.accepted).length,
|
|
121
97
|
legacyCount: cockpitPhases.filter((phase) => phase.legacy).length,
|
|
122
98
|
aggregateBlockers,
|
|
123
|
-
inspectCommand: `
|
|
99
|
+
inspectCommand: `vgxness sdd cockpit --project ${validated.value.project} --change ${validated.value.change} --json`,
|
|
124
100
|
};
|
|
125
101
|
return ok(cockpit);
|
|
126
102
|
}
|
|
@@ -81,7 +81,7 @@ export function previewRollbackConfigBackup(input) {
|
|
|
81
81
|
restorable: blockers.length === 0 && targetPath !== undefined,
|
|
82
82
|
blockers,
|
|
83
83
|
warnings,
|
|
84
|
-
nextCommands: blockers.length === 0 ? [`
|
|
84
|
+
nextCommands: blockers.length === 0 ? [`vgxness setup rollback --backup ${backupPath} --yes`] : ['Resolve blockers, then rerun rollback preview.'],
|
|
85
85
|
},
|
|
86
86
|
};
|
|
87
87
|
}
|
|
@@ -133,7 +133,7 @@ export function applyRollbackConfigBackup(input) {
|
|
|
133
133
|
targetPath,
|
|
134
134
|
...(preRollbackBackup === undefined ? {} : { preRollbackBackupPath: preRollbackBackup.backupPath, preRollbackBackup }),
|
|
135
135
|
backup: preview.value.backup,
|
|
136
|
-
nextCommands: ['
|
|
136
|
+
nextCommands: ['vgxness doctor', 'Restart OpenCode and verify the vgxness MCP server is visible.'],
|
|
137
137
|
},
|
|
138
138
|
};
|
|
139
139
|
}
|
|
@@ -4,7 +4,7 @@ export const antigravitySetupAdapter = {
|
|
|
4
4
|
displayName: 'Antigravity',
|
|
5
5
|
supportLevel: 'placeholder',
|
|
6
6
|
capabilities: ['manual-guidance'],
|
|
7
|
-
targets: [{ kind: 'manual', label: 'Coming soon manual guidance',
|
|
7
|
+
targets: [{ kind: 'manual', label: 'Coming soon manual guidance', writableBySetup: false }],
|
|
8
8
|
getStatus() {
|
|
9
9
|
return {
|
|
10
10
|
providerId: 'antigravity',
|
|
@@ -5,7 +5,7 @@ export const claudeSetupAdapter = {
|
|
|
5
5
|
displayName: 'Claude',
|
|
6
6
|
supportLevel: 'preview-only',
|
|
7
7
|
capabilities: ['mcp-preview', 'manual-guidance'],
|
|
8
|
-
targets: [{ kind: 'manual', label: 'Claude MCP config snippet',
|
|
8
|
+
targets: [{ kind: 'manual', label: 'Claude MCP config snippet', writableBySetup: false }],
|
|
9
9
|
getStatus(context) {
|
|
10
10
|
return {
|
|
11
11
|
providerId: 'claude',
|
|
@@ -14,7 +14,7 @@ export const claudeSetupAdapter = {
|
|
|
14
14
|
evidence: context.databasePath !== undefined
|
|
15
15
|
? ['Claude MCP preview can be generated from the selected database path.']
|
|
16
16
|
: ['Claude MCP preview uses a placeholder until a database path is selected.'],
|
|
17
|
-
guidance: ['Copy snippets manually after reviewing them. The
|
|
17
|
+
guidance: ['Copy snippets manually after reviewing them. The TUI does not install or apply Claude config.'],
|
|
18
18
|
actions: [
|
|
19
19
|
{
|
|
20
20
|
id: 'claude-manual-guidance',
|
|
@@ -4,7 +4,7 @@ export const customSetupAdapter = {
|
|
|
4
4
|
displayName: 'Custom',
|
|
5
5
|
supportLevel: 'extension-point',
|
|
6
6
|
capabilities: ['manual-guidance'],
|
|
7
|
-
targets: [{ kind: 'extension', label: 'Custom provider extension point',
|
|
7
|
+
targets: [{ kind: 'extension', label: 'Custom provider extension point', writableBySetup: false }],
|
|
8
8
|
getStatus() {
|
|
9
9
|
return {
|
|
10
10
|
providerId: 'custom',
|
|
@@ -8,8 +8,8 @@ export const openCodeSetupAdapter = {
|
|
|
8
8
|
supportLevel: 'supported-primary',
|
|
9
9
|
capabilities: ['mcp-preview', 'mcp-install-plan', 'mcp-install-apply-external', 'agent-preview', 'doctor', 'visibility-check'],
|
|
10
10
|
targets: [
|
|
11
|
-
{ kind: 'user-config', label: 'User/global OpenCode config (default)', path: '$HOME/.config/opencode/opencode.json',
|
|
12
|
-
{ kind: 'project-config', label: 'Project OpenCode config (explicit opt-in)', path: '.opencode/opencode.json',
|
|
11
|
+
{ kind: 'user-config', label: 'User/global OpenCode config (default)', path: '$HOME/.config/opencode/opencode.json', writableBySetup: false },
|
|
12
|
+
{ kind: 'project-config', label: 'Project OpenCode config (explicit opt-in)', path: '.opencode/opencode.json', writableBySetup: false },
|
|
13
13
|
],
|
|
14
14
|
getStatus(context) {
|
|
15
15
|
const visibility = this.getVisibility?.(context);
|
|
@@ -161,7 +161,7 @@ function externalInstallAction(scope, targetPath) {
|
|
|
161
161
|
label: `Copy external OpenCode ${scope === 'user' ? 'user/global' : 'project'} install command`,
|
|
162
162
|
kind: 'copy-command',
|
|
163
163
|
command: ['vgxness', 'mcp', 'install', 'opencode', '--scope', scope, '--yes'],
|
|
164
|
-
description: 'Copy and run this outside the
|
|
164
|
+
description: 'Copy and run this outside the TUI only after reviewing the read-only plan.',
|
|
165
165
|
safety: externalProviderWriteSafety(targetPath),
|
|
166
166
|
};
|
|
167
167
|
}
|
|
@@ -74,7 +74,7 @@ function storeStatus(result) {
|
|
|
74
74
|
status: 'blocked',
|
|
75
75
|
path: '',
|
|
76
76
|
blocker: result.error.message,
|
|
77
|
-
recovery: 'Run `
|
|
77
|
+
recovery: 'Run `vgxness doctor` and verify the configured local memory path is writable.',
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
function mcpStatus(result, storeReadiness) {
|
|
@@ -178,17 +178,17 @@ function verificationSummary(environment, project, providers, agents, mcp) {
|
|
|
178
178
|
}
|
|
179
179
|
function nextAction(store, mcp, defaults, providers, project) {
|
|
180
180
|
if (store.status !== 'ready') {
|
|
181
|
-
return { command: '
|
|
181
|
+
return { command: 'vgxness doctor', reason: `Local store is blocked: ${store.blocker ?? 'local store is unavailable'}` };
|
|
182
182
|
}
|
|
183
183
|
if (defaults.status !== 'ready') {
|
|
184
184
|
if (defaults.blocker?.startsWith('No project selected') === true) {
|
|
185
185
|
return {
|
|
186
|
-
command: '
|
|
186
|
+
command: 'vgxness setup status --project <project>',
|
|
187
187
|
reason: defaults.nextAction ?? 'Select a project to verify project-scoped setup checks.',
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
190
|
return {
|
|
191
|
-
command: '
|
|
191
|
+
command: 'vgxness agents seed --scope project',
|
|
192
192
|
reason: `Default context is blocked: ${defaults.blocker ?? 'default context is unavailable'}`,
|
|
193
193
|
};
|
|
194
194
|
}
|
|
@@ -201,8 +201,8 @@ function nextAction(store, mcp, defaults, providers, project) {
|
|
|
201
201
|
reason: `Provider MCP status is not ready; review the Providers section for provider-specific preview/install guidance (${providerSummary}).`,
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
|
-
return { command: '
|
|
204
|
+
return { command: 'vgxness runs list', reason: 'Project setup is ready; continue with normal vgxness usage.' };
|
|
205
205
|
}
|
|
206
206
|
function setupStatusCommand(project) {
|
|
207
|
-
return project === undefined ? '
|
|
207
|
+
return project === undefined ? 'vgxness setup status' : `vgxness setup status --project ${project}`;
|
|
208
208
|
}
|
package/dist/setup/setup-plan.js
CHANGED
|
@@ -78,11 +78,11 @@ function setupPlanFromOpenCode(input) {
|
|
|
78
78
|
severity: 'blocking',
|
|
79
79
|
message: input.opencode.message,
|
|
80
80
|
...(input.opencode.targetPath === undefined ? {} : { targetPath: input.opencode.targetPath }),
|
|
81
|
-
recovery: 'Inspect the OpenCode config, resolve the conflict, then rerun `
|
|
81
|
+
recovery: 'Inspect the OpenCode config, resolve the conflict, then rerun `vgxness setup plan`.',
|
|
82
82
|
},
|
|
83
83
|
],
|
|
84
84
|
backupsPlanned: [],
|
|
85
|
-
nextCommands: ['
|
|
85
|
+
nextCommands: ['vgxness setup plan', 'vgxness mcp doctor opencode'],
|
|
86
86
|
};
|
|
87
87
|
}
|
|
88
88
|
return {
|
|
@@ -115,7 +115,7 @@ function setupPlanFromOpenCode(input) {
|
|
|
115
115
|
},
|
|
116
116
|
]
|
|
117
117
|
: [],
|
|
118
|
-
nextCommands: ['
|
|
118
|
+
nextCommands: ['vgxness setup apply --yes', 'vgxness doctor', 'Restart OpenCode and verify the vgxness MCP server is visible.'],
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
function resolveSetupDatabase(input) {
|
|
@@ -21,7 +21,7 @@ const templates = {
|
|
|
21
21
|
},
|
|
22
22
|
cli: {
|
|
23
23
|
rationale: ['CLI changes affect TypeScript dispatch/rendering paths and user-visible behavior.', 'Only typecheck is currently allowlisted; CLI execution remains manual/copy-only.'],
|
|
24
|
-
recommendations: [typecheckRecommendation(), manualRecommendation('manual-cli-smoke', 'Smoke-test CLI command manually', 'Use
|
|
24
|
+
recommendations: [typecheckRecommendation(), manualRecommendation('manual-cli-smoke', 'Smoke-test CLI command manually', 'Use bun run cli:bun -- <command> as copy-only text for an operator-selected CLI scenario.', 'bun run cli:bun -- <command>')],
|
|
25
25
|
manualChecks: [manualCheck('review-cli-output', 'Review CLI output shape', 'Confirm human output is concise and JSON output remains structured where applicable.')],
|
|
26
26
|
},
|
|
27
27
|
mcp: {
|