vgxness 1.9.1 → 1.9.3
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 +15 -5
- package/dist/agents/agent-activation-service.js +13 -4
- package/dist/agents/agent-registry-service.js +8 -2
- package/dist/agents/agent-resolver.js +33 -3
- package/dist/agents/agent-seed-upgrade-service.js +231 -0
- package/dist/agents/boot-upgrade.js +59 -0
- package/dist/agents/canonical-agent-manifest.js +39 -18
- package/dist/agents/canonical-agent-projection.js +38 -4
- package/dist/agents/manager-profile-overlay-service.js +14 -0
- package/dist/agents/repositories/agent-seed-history.js +128 -0
- package/dist/cli/cli-help.js +14 -3
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +8 -0
- package/dist/cli/commands/mcp-dispatcher.js +7 -0
- package/dist/cli/commands/memory-sdd-dispatcher.js +71 -5
- package/dist/cli/commands/status-dispatcher.js +130 -0
- package/dist/cli/commands/workflow-dispatcher.js +11 -5
- package/dist/cli/dispatcher.js +11 -1
- package/dist/cli/product-resume-renderer.js +32 -0
- package/dist/cli/product-status-renderer.js +74 -0
- package/dist/cli/sdd-renderer.js +80 -3
- package/dist/code/cli/code-command.js +7 -4
- package/dist/code/reporting/summary.js +4 -1
- package/dist/code/runtime/code-runtime.js +27 -4
- package/dist/code/runtime/sdd-context.js +18 -2
- package/dist/governance/governance-report-builder.js +18 -7
- package/dist/mcp/claude-code-agent-config.js +10 -4
- package/dist/mcp/client-install-claude-code-contract.js +19 -4
- package/dist/mcp/client-install-claude-code.js +2 -2
- package/dist/mcp/control-plane.js +78 -5
- package/dist/mcp/provider-status.js +89 -88
- package/dist/mcp/schema.js +42 -8
- package/dist/mcp/stdio-server.js +6 -0
- package/dist/mcp/validation.js +77 -5
- package/dist/memory/sqlite/migrations/016_agent_seed_history.sql +15 -0
- package/dist/resume/product-resume.js +166 -0
- package/dist/runs/repositories/runs.js +12 -1
- package/dist/runs/run-service.js +62 -5
- package/dist/runs/schema.js +4 -0
- package/dist/sdd/schema.js +20 -0
- package/dist/sdd/sdd-continuation-plan.js +81 -0
- package/dist/sdd/sdd-workflow-service.js +146 -18
- package/dist/skills/skill-resolver.js +21 -4
- package/dist/status/product-status.js +117 -0
- package/docs/architecture.md +9 -1
- package/docs/cli.md +38 -13
- package/docs/code-runtime.md +3 -0
- package/docs/contributing.md +1 -1
- package/docs/glossary.md +2 -2
- package/docs/mcp.md +20 -6
- package/docs/project-health-audit-v1.9.1.md +126 -0
- package/docs/providers.md +4 -4
- package/docs/safety.md +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ import { openMemoryDatabase } from '../memory/sqlite/database.js';
|
|
|
8
8
|
import { prepareMemoryDatabasePath, resolveMemoryDatabasePath } from '../memory/storage-paths.js';
|
|
9
9
|
import { OpenCodeManagerPayloadService } from '../providers/opencode/manager-payload.js';
|
|
10
10
|
import { RunService } from '../runs/run-service.js';
|
|
11
|
+
import { sddContinuationPlanFrom } from '../sdd/sdd-continuation-plan.js';
|
|
11
12
|
import { SddWorkflowService } from '../sdd/sdd-workflow-service.js';
|
|
12
13
|
import { SkillRegistryService } from '../skills/skill-registry-service.js';
|
|
13
14
|
import { VerificationPlanService } from '../verification/index.js';
|
|
@@ -32,7 +33,9 @@ export function callVgxTool(call, services) {
|
|
|
32
33
|
case 'vgxness_sdd_save_artifact':
|
|
33
34
|
return auditedEnvelope(validated.tool, services.sdd.saveArtifact(validated.input), services, sddSaveAuditPayload(validated.input));
|
|
34
35
|
case 'vgxness_sdd_accept_artifact':
|
|
35
|
-
return auditedEnvelope(validated.tool, services.sdd.acceptArtifact(
|
|
36
|
+
return auditedEnvelope(validated.tool, services.sdd.acceptArtifact(validated.input), services, sddAcceptanceAuditPayload(validated.input));
|
|
37
|
+
case 'vgxness_sdd_reopen_artifact':
|
|
38
|
+
return auditedEnvelope(validated.tool, services.sdd.reopenArtifact(validated.input), services, sddReopenAuditPayload(validated.input));
|
|
36
39
|
case 'vgxness_sdd_get_artifact':
|
|
37
40
|
return toEnvelope(validated.tool, services.sdd.getArtifact(validated.input));
|
|
38
41
|
case 'vgxness_sdd_list_artifacts':
|
|
@@ -41,6 +44,8 @@ export function callVgxTool(call, services) {
|
|
|
41
44
|
return toEnvelope(validated.tool, services.sdd.getNext(validated.input));
|
|
42
45
|
case 'vgxness_sdd_cockpit':
|
|
43
46
|
return toEnvelope(validated.tool, services.sdd.getCockpit(validated.input));
|
|
47
|
+
case 'vgxness_sdd_continue':
|
|
48
|
+
return sddContinueEnvelope(validated.input, services);
|
|
44
49
|
case 'vgxness_governance_report':
|
|
45
50
|
return auditedEnvelope(validated.tool, new GovernanceReportBuilder({
|
|
46
51
|
sdd: governanceSddServices(services.sdd),
|
|
@@ -94,6 +99,8 @@ export function callVgxTool(call, services) {
|
|
|
94
99
|
return toEnvelope(validated.tool, services.runs.appendCheckpoint(validated.input));
|
|
95
100
|
case 'vgxness_run_finalize':
|
|
96
101
|
return toEnvelope(validated.tool, services.runs.updateFinalStatus(validated.input));
|
|
102
|
+
case 'vgxness_run_resume_candidates':
|
|
103
|
+
return runResumeCandidatesEnvelope(validated.input, services);
|
|
97
104
|
case 'vgxness_run_resume_inspect':
|
|
98
105
|
return toEnvelope(validated.tool, services.runs.getRunOperatorResumePlan(validated.input.runId));
|
|
99
106
|
case 'vgxness_run_resume_gate':
|
|
@@ -117,10 +124,6 @@ export function callVgxTool(call, services) {
|
|
|
117
124
|
}
|
|
118
125
|
return errorEnvelope('validation_failed', 'Tool dispatch is not implemented');
|
|
119
126
|
}
|
|
120
|
-
function toAcceptArtifactServiceInput(input) {
|
|
121
|
-
const note = input.note ?? input.notes ?? input.rationale;
|
|
122
|
-
return note === undefined ? input : { ...input, note };
|
|
123
|
-
}
|
|
124
127
|
function auditedEnvelope(tool, result, services, audit) {
|
|
125
128
|
if (result.ok && audit.runId !== undefined) {
|
|
126
129
|
services.runs.appendEvent({
|
|
@@ -171,6 +174,24 @@ function sddAcceptanceAuditPayload(input) {
|
|
|
171
174
|
}),
|
|
172
175
|
};
|
|
173
176
|
}
|
|
177
|
+
function sddReopenAuditPayload(input) {
|
|
178
|
+
return {
|
|
179
|
+
runId: input.runId,
|
|
180
|
+
title: 'Audit: sdd-artifact-reopened',
|
|
181
|
+
relatedType: 'sdd-artifact',
|
|
182
|
+
relatedId: `${input.change}:${input.phase}`,
|
|
183
|
+
payload: (value) => ({
|
|
184
|
+
eventType: 'sdd-artifact-reopened',
|
|
185
|
+
project: input.project,
|
|
186
|
+
change: input.change,
|
|
187
|
+
phase: input.phase,
|
|
188
|
+
topicKey: value.topicKey,
|
|
189
|
+
artifactId: value.id,
|
|
190
|
+
reopenedBy: { type: 'human', id: input.reopenedBy.id },
|
|
191
|
+
...(input.agentId === undefined ? {} : { agentId: input.agentId }),
|
|
192
|
+
}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
174
195
|
function sddSaveAuditPayload(input) {
|
|
175
196
|
return {
|
|
176
197
|
runId: input.runId,
|
|
@@ -222,6 +243,23 @@ function governanceSddServices(services) {
|
|
|
222
243
|
},
|
|
223
244
|
};
|
|
224
245
|
}
|
|
246
|
+
function sddContinueEnvelope(input, services) {
|
|
247
|
+
const next = services.sdd.getNext({ project: input.project, change: input.change });
|
|
248
|
+
if (!next.ok)
|
|
249
|
+
return errorEnvelope(next.error.code, next.error.message, 'vgxness_sdd_continue');
|
|
250
|
+
const cockpit = services.sdd.getCockpit({ project: input.project, change: input.change });
|
|
251
|
+
if (!cockpit.ok)
|
|
252
|
+
return errorEnvelope(cockpit.error.code, cockpit.error.message, 'vgxness_sdd_continue');
|
|
253
|
+
const relatedRun = services.runs.findRelatedInterruptedSddRun({ project: input.project, change: input.change });
|
|
254
|
+
if (!relatedRun.ok)
|
|
255
|
+
return errorEnvelope(relatedRun.error.code, relatedRun.error.message, 'vgxness_sdd_continue');
|
|
256
|
+
return successEnvelope('vgxness_sdd_continue', sddContinuationPlanFrom({
|
|
257
|
+
project: input.project,
|
|
258
|
+
next: next.value,
|
|
259
|
+
cockpit: cockpit.value,
|
|
260
|
+
...(relatedRun.value === undefined ? {} : { relatedRunContext: relatedRun.value }),
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
225
263
|
export function createVgxMcpControlPlane(options = {}) {
|
|
226
264
|
const databasePath = resolveControlPlaneDatabasePath(options);
|
|
227
265
|
if (!databasePath.ok)
|
|
@@ -237,6 +275,7 @@ export function createVgxMcpControlPlane(options = {}) {
|
|
|
237
275
|
let closed = false;
|
|
238
276
|
return {
|
|
239
277
|
callVgxTool: (tool, input) => callVgxTool({ tool, input }, services),
|
|
278
|
+
database,
|
|
240
279
|
close: () => {
|
|
241
280
|
if (closed)
|
|
242
281
|
return;
|
|
@@ -329,6 +368,40 @@ function listRunsEnvelope(input, services) {
|
|
|
329
368
|
? successEnvelope('vgxness_run_list', result.value.slice(0, limit))
|
|
330
369
|
: errorEnvelope(result.error.code, result.error.message, 'vgxness_run_list');
|
|
331
370
|
}
|
|
371
|
+
function runResumeCandidatesEnvelope(input, services) {
|
|
372
|
+
const limit = input.limit ?? 5;
|
|
373
|
+
const result = services.runs.listRecentInterruptedRuns({ project: input.project, limit });
|
|
374
|
+
if (!result.ok)
|
|
375
|
+
return errorEnvelope(result.error.code, result.error.message, 'vgxness_run_resume_candidates');
|
|
376
|
+
return successEnvelope('vgxness_run_resume_candidates', {
|
|
377
|
+
kind: 'run-resume-candidates',
|
|
378
|
+
version: 1,
|
|
379
|
+
project: input.project,
|
|
380
|
+
statuses: ['failed', 'blocked', 'needs-human'],
|
|
381
|
+
limit,
|
|
382
|
+
candidates: result.value.map((candidate) => ({
|
|
383
|
+
...candidate,
|
|
384
|
+
recommendation: 'Inspect this interrupted run before deciding whether to continue manually.',
|
|
385
|
+
inspectTool: 'run_resume_inspect',
|
|
386
|
+
inspectInput: { runId: candidate.runId },
|
|
387
|
+
resumeCommand: `vgxness resume --project ${input.project} --run-id ${candidate.runId}`,
|
|
388
|
+
})),
|
|
389
|
+
nextStep: result.value.length === 0
|
|
390
|
+
? 'No interrupted run candidates were found for this project. Start from the current project status or a known runId.'
|
|
391
|
+
: 'Call run_resume_inspect with a candidate runId, then use run_resume_gate only when inspect returns a relevant approvalId.',
|
|
392
|
+
safety: {
|
|
393
|
+
readOnly: true,
|
|
394
|
+
runMutation: false,
|
|
395
|
+
retryAdmitted: false,
|
|
396
|
+
providerInvoked: false,
|
|
397
|
+
writesProviderConfig: false,
|
|
398
|
+
writesArtifacts: false,
|
|
399
|
+
writesOpenSpec: false,
|
|
400
|
+
createsSandbox: false,
|
|
401
|
+
createsWorktree: false,
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
}
|
|
332
405
|
function toEnvelope(tool, result) {
|
|
333
406
|
return result.ok ? successEnvelope(tool, result.value) : errorEnvelope(result.error.code, result.error.message, tool);
|
|
334
407
|
}
|
|
@@ -52,35 +52,36 @@ export class ProviderStatusService {
|
|
|
52
52
|
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
53
53
|
const issueCount = [canonicalAgentManifest.status, configStatus, ...tools.map((tool) => (tool.present ? 'pass' : 'fail'))].filter((item) => item === 'fail' || item === 'not-configured').length;
|
|
54
54
|
const warningCount = [configStatus, mcpEntry.status, ...paths.map((path) => path.status)].filter((item) => item === 'warn').length;
|
|
55
|
+
const reportBase = {
|
|
56
|
+
version: 1,
|
|
57
|
+
kind: 'provider-status',
|
|
58
|
+
project: normalized.project,
|
|
59
|
+
providerAdapter: normalized.providerAdapter,
|
|
60
|
+
scope: normalized.scope,
|
|
61
|
+
workspaceRoot: normalized.workspaceRoot,
|
|
62
|
+
status,
|
|
63
|
+
overallStatus: status,
|
|
64
|
+
inspectedPaths: checkedPaths,
|
|
65
|
+
issueCount,
|
|
66
|
+
warningCount,
|
|
67
|
+
summary: summarizeStatus(status, mcpEntry),
|
|
68
|
+
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
69
|
+
checkedPaths,
|
|
70
|
+
canonicalAgentManifest,
|
|
71
|
+
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
72
|
+
mcpRequiredTools: tools,
|
|
73
|
+
originalBytes,
|
|
74
|
+
compactBytes,
|
|
75
|
+
verboseAvailable: normalized.payloadMode === 'compact',
|
|
76
|
+
fullContentRef: `provider-status:${normalized.providerAdapter}:${normalized.workspaceRoot}`,
|
|
77
|
+
generatedAt,
|
|
78
|
+
safety: PROVIDER_HEALTH_SAFETY,
|
|
79
|
+
};
|
|
55
80
|
return {
|
|
56
81
|
ok: true,
|
|
57
|
-
value:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
project: normalized.project,
|
|
61
|
-
providerAdapter: normalized.providerAdapter,
|
|
62
|
-
scope: normalized.scope,
|
|
63
|
-
workspaceRoot: normalized.workspaceRoot,
|
|
64
|
-
status,
|
|
65
|
-
payloadMode: normalized.payloadMode,
|
|
66
|
-
overallStatus: status,
|
|
67
|
-
inspectedPaths: checkedPaths,
|
|
68
|
-
issueCount,
|
|
69
|
-
warningCount,
|
|
70
|
-
summary: summarizeStatus(status, mcpEntry),
|
|
71
|
-
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
72
|
-
checkedPaths,
|
|
73
|
-
canonicalAgentManifest,
|
|
74
|
-
config: { status: configStatus, paths: compactPaths(paths, normalized.payloadMode), mcpEntry: compactMcpEntry(mcpEntry, normalized.payloadMode) },
|
|
75
|
-
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
76
|
-
mcpRequiredTools: tools,
|
|
77
|
-
originalBytes,
|
|
78
|
-
compactBytes,
|
|
79
|
-
verboseAvailable: normalized.payloadMode === 'compact',
|
|
80
|
-
fullContentRef: `provider-status:${normalized.providerAdapter}:${normalized.workspaceRoot}`,
|
|
81
|
-
generatedAt,
|
|
82
|
-
safety: PROVIDER_HEALTH_SAFETY,
|
|
83
|
-
},
|
|
82
|
+
value: normalized.payloadMode === 'verbose'
|
|
83
|
+
? { ...reportBase, payloadMode: 'verbose', config: { status: configStatus, paths: compactPaths(paths, 'verbose'), mcpEntry: compactMcpEntry(mcpEntry, 'verbose') } }
|
|
84
|
+
: { ...reportBase, payloadMode: 'compact', config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') } },
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
readSdd(project, change) {
|
|
@@ -115,35 +116,36 @@ export class ProviderStatusService {
|
|
|
115
116
|
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
116
117
|
const issueCount = [canonicalAgentManifest.status, configStatus, ...agentStatuses].filter((item) => item === 'fail' || item === 'not-configured').length;
|
|
117
118
|
const warningCount = advisory.length + resolvedScope.value.warnings.length + paths.filter((path) => path.status === 'warn').length;
|
|
119
|
+
const reportBase = {
|
|
120
|
+
version: 1,
|
|
121
|
+
kind: 'provider-status',
|
|
122
|
+
project: normalized.project,
|
|
123
|
+
providerAdapter: 'claude',
|
|
124
|
+
scope: normalized.scope,
|
|
125
|
+
workspaceRoot: normalized.workspaceRoot,
|
|
126
|
+
status,
|
|
127
|
+
overallStatus: status,
|
|
128
|
+
inspectedPaths: checkedPaths,
|
|
129
|
+
issueCount,
|
|
130
|
+
warningCount,
|
|
131
|
+
summary: summarizeClaudeStatus(status, mcpEntry),
|
|
132
|
+
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
133
|
+
checkedPaths,
|
|
134
|
+
canonicalAgentManifest,
|
|
135
|
+
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
136
|
+
mcpRequiredTools: tools,
|
|
137
|
+
originalBytes,
|
|
138
|
+
compactBytes,
|
|
139
|
+
verboseAvailable: normalized.payloadMode === 'compact',
|
|
140
|
+
fullContentRef: `provider-status:claude:${normalized.workspaceRoot}`,
|
|
141
|
+
generatedAt: 'read-only-snapshot',
|
|
142
|
+
safety: PROVIDER_HEALTH_SAFETY,
|
|
143
|
+
};
|
|
118
144
|
return {
|
|
119
145
|
ok: true,
|
|
120
|
-
value:
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
project: normalized.project,
|
|
124
|
-
providerAdapter: 'claude',
|
|
125
|
-
scope: normalized.scope,
|
|
126
|
-
workspaceRoot: normalized.workspaceRoot,
|
|
127
|
-
status,
|
|
128
|
-
payloadMode: normalized.payloadMode,
|
|
129
|
-
overallStatus: status,
|
|
130
|
-
inspectedPaths: checkedPaths,
|
|
131
|
-
issueCount,
|
|
132
|
-
warningCount,
|
|
133
|
-
summary: summarizeClaudeStatus(status, mcpEntry),
|
|
134
|
-
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
135
|
-
checkedPaths,
|
|
136
|
-
canonicalAgentManifest,
|
|
137
|
-
config: { status: configStatus, paths: compactPaths(paths, normalized.payloadMode), mcpEntry: compactMcpEntry(mcpEntry, normalized.payloadMode) },
|
|
138
|
-
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
139
|
-
mcpRequiredTools: tools,
|
|
140
|
-
originalBytes,
|
|
141
|
-
compactBytes,
|
|
142
|
-
verboseAvailable: normalized.payloadMode === 'compact',
|
|
143
|
-
fullContentRef: `provider-status:claude:${normalized.workspaceRoot}`,
|
|
144
|
-
generatedAt: 'read-only-snapshot',
|
|
145
|
-
safety: PROVIDER_HEALTH_SAFETY,
|
|
146
|
-
},
|
|
146
|
+
value: normalized.payloadMode === 'verbose'
|
|
147
|
+
? { ...reportBase, payloadMode: 'verbose', config: { status: configStatus, paths: compactPaths(paths, 'verbose'), mcpEntry: compactMcpEntry(mcpEntry, 'verbose') } }
|
|
148
|
+
: { ...reportBase, payloadMode: 'compact', config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') } },
|
|
147
149
|
};
|
|
148
150
|
}
|
|
149
151
|
getClaudeUserGlobalStatus(normalized, canonicalScope = 'user', scopeWarnings = []) {
|
|
@@ -162,35 +164,38 @@ export class ProviderStatusService {
|
|
|
162
164
|
const checkedPaths = normalized.payloadMode === 'verbose' ? [mcpState.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), userMemory.path] : [mcpState.path, userMemory.path, ...agents.agents.filter((agent) => agent.exists || agent.status !== 'missing').map((agent) => agent.path)];
|
|
163
165
|
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, agents, userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, scopeWarnings, sdd, mcpRequiredTools: tools };
|
|
164
166
|
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, agentSummary: summarizeClaudeAgents(agents), userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
167
|
+
const originalBytes = Buffer.byteLength(JSON.stringify(verboseShape), 'utf8');
|
|
168
|
+
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
169
|
+
const reportBase = {
|
|
170
|
+
version: 1,
|
|
171
|
+
kind: 'provider-status',
|
|
172
|
+
project: normalized.project,
|
|
173
|
+
providerAdapter: 'claude',
|
|
174
|
+
scope: normalized.scope,
|
|
175
|
+
workspaceRoot: normalized.workspaceRoot,
|
|
176
|
+
status,
|
|
177
|
+
overallStatus: status,
|
|
178
|
+
inspectedPaths: checkedPaths,
|
|
179
|
+
issueCount: [canonicalAgentManifest.status, configStatus, ...agentStatuses].filter((item) => item === 'fail' || item === 'not-configured').length,
|
|
180
|
+
warningCount: scopeWarnings.length + paths.filter((path) => path.status === 'warn').length + 1,
|
|
181
|
+
summary: summarizeClaudeStatus(status, mcpEntry),
|
|
182
|
+
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
183
|
+
checkedPaths,
|
|
184
|
+
canonicalAgentManifest,
|
|
185
|
+
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
186
|
+
mcpRequiredTools: tools,
|
|
187
|
+
originalBytes,
|
|
188
|
+
compactBytes,
|
|
189
|
+
verboseAvailable: normalized.payloadMode === 'compact',
|
|
190
|
+
fullContentRef: `provider-status:claude:user-global:${normalized.workspaceRoot}`,
|
|
191
|
+
generatedAt: 'read-only-snapshot',
|
|
192
|
+
safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES },
|
|
193
|
+
};
|
|
165
194
|
return {
|
|
166
195
|
ok: true,
|
|
167
|
-
value:
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
project: normalized.project,
|
|
171
|
-
providerAdapter: 'claude',
|
|
172
|
-
scope: normalized.scope,
|
|
173
|
-
workspaceRoot: normalized.workspaceRoot,
|
|
174
|
-
status,
|
|
175
|
-
payloadMode: normalized.payloadMode,
|
|
176
|
-
overallStatus: status,
|
|
177
|
-
inspectedPaths: checkedPaths,
|
|
178
|
-
issueCount: [canonicalAgentManifest.status, configStatus, ...agentStatuses].filter((item) => item === 'fail' || item === 'not-configured').length,
|
|
179
|
-
warningCount: scopeWarnings.length + paths.filter((path) => path.status === 'warn').length + 1,
|
|
180
|
-
summary: summarizeClaudeStatus(status, mcpEntry),
|
|
181
|
-
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
182
|
-
checkedPaths,
|
|
183
|
-
canonicalAgentManifest,
|
|
184
|
-
config: { status: configStatus, paths: compactPaths(paths, normalized.payloadMode), mcpEntry: compactMcpEntry(mcpEntry, normalized.payloadMode) },
|
|
185
|
-
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
186
|
-
mcpRequiredTools: tools,
|
|
187
|
-
originalBytes: Buffer.byteLength(JSON.stringify(verboseShape), 'utf8'),
|
|
188
|
-
compactBytes: Buffer.byteLength(JSON.stringify(compactShape), 'utf8'),
|
|
189
|
-
verboseAvailable: normalized.payloadMode === 'compact',
|
|
190
|
-
fullContentRef: `provider-status:claude:user-global:${normalized.workspaceRoot}`,
|
|
191
|
-
generatedAt: 'read-only-snapshot',
|
|
192
|
-
safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES },
|
|
193
|
-
},
|
|
196
|
+
value: normalized.payloadMode === 'verbose'
|
|
197
|
+
? { ...reportBase, payloadMode: 'verbose', config: { status: configStatus, paths: compactPaths(paths, 'verbose'), mcpEntry: compactMcpEntry(mcpEntry, 'verbose') } }
|
|
198
|
+
: { ...reportBase, payloadMode: 'compact', config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') } },
|
|
194
199
|
};
|
|
195
200
|
}
|
|
196
201
|
}
|
|
@@ -221,16 +226,12 @@ function claudeProjectMemoryPathStatus(state) {
|
|
|
221
226
|
function compactPaths(paths, mode) {
|
|
222
227
|
if (mode === 'verbose')
|
|
223
228
|
return paths;
|
|
224
|
-
return paths.map((path) => path.status
|
|
225
|
-
? { ...path, detail: `${path.label}: pass` }
|
|
226
|
-
: path.status === 'not-configured'
|
|
227
|
-
? { ...path, detail: `${path.label}: not configured` }
|
|
228
|
-
: path);
|
|
229
|
+
return paths.map((path) => ({ label: path.label, path: path.path, status: path.status }));
|
|
229
230
|
}
|
|
230
231
|
function compactMcpEntry(entry, mode) {
|
|
231
|
-
if (mode === 'verbose'
|
|
232
|
+
if (mode === 'verbose')
|
|
232
233
|
return entry;
|
|
233
|
-
return {
|
|
234
|
+
return { configured: entry.configured, status: entry.status, serverName: entry.serverName };
|
|
234
235
|
}
|
|
235
236
|
function compactSdd(sdd, mode) {
|
|
236
237
|
if (mode === 'verbose')
|
package/dist/mcp/schema.js
CHANGED
|
@@ -9,10 +9,12 @@ export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
|
|
|
9
9
|
'vgxness_sdd_get_readiness',
|
|
10
10
|
'vgxness_sdd_save_artifact',
|
|
11
11
|
'vgxness_sdd_accept_artifact',
|
|
12
|
+
'vgxness_sdd_reopen_artifact',
|
|
12
13
|
'vgxness_sdd_get_artifact',
|
|
13
14
|
'vgxness_sdd_list_artifacts',
|
|
14
15
|
'vgxness_sdd_next',
|
|
15
16
|
'vgxness_sdd_cockpit',
|
|
17
|
+
'vgxness_sdd_continue',
|
|
16
18
|
'vgxness_governance_report',
|
|
17
19
|
'vgxness_memory_save',
|
|
18
20
|
'vgxness_memory_search',
|
|
@@ -36,6 +38,7 @@ export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
|
|
|
36
38
|
'vgxness_run_start',
|
|
37
39
|
'vgxness_run_checkpoint',
|
|
38
40
|
'vgxness_run_finalize',
|
|
41
|
+
'vgxness_run_resume_candidates',
|
|
39
42
|
'vgxness_run_resume_inspect',
|
|
40
43
|
'vgxness_run_resume_gate',
|
|
41
44
|
'vgxness_provider_status',
|
|
@@ -49,10 +52,12 @@ export const EXPOSED_VGX_MCP_TOOL_NAMES = [
|
|
|
49
52
|
'sdd_get_readiness',
|
|
50
53
|
'sdd_save_artifact',
|
|
51
54
|
'sdd_accept_artifact',
|
|
55
|
+
'sdd_reopen_artifact',
|
|
52
56
|
'sdd_get_artifact',
|
|
53
57
|
'sdd_list_artifacts',
|
|
54
58
|
'sdd_next',
|
|
55
59
|
'sdd_cockpit',
|
|
60
|
+
'sdd_continue',
|
|
56
61
|
'governance_report',
|
|
57
62
|
'memory_save',
|
|
58
63
|
'memory_search',
|
|
@@ -76,6 +81,7 @@ export const EXPOSED_VGX_MCP_TOOL_NAMES = [
|
|
|
76
81
|
'run_start',
|
|
77
82
|
'run_checkpoint',
|
|
78
83
|
'run_finalize',
|
|
84
|
+
'run_resume_candidates',
|
|
79
85
|
'run_resume_inspect',
|
|
80
86
|
'run_resume_gate',
|
|
81
87
|
'provider_status',
|
|
@@ -102,6 +108,7 @@ const payloadModes = ['compact', 'verbose'];
|
|
|
102
108
|
const contextCockpitLevels = ['compact', 'expanded', 'verbose'];
|
|
103
109
|
const providerChangePlanProviders = ['opencode', 'claude', 'antigravity', 'custom'];
|
|
104
110
|
const providerChangePlanTypes = ['opencode-mcp-install', 'claude-mcp-install', 'setup', 'install', 'config-preparation'];
|
|
111
|
+
const sddPhaseInputSchema = z.union([z.enum(sddPhases), z.literal('apply')]);
|
|
105
112
|
const jsonValueSchema = z.lazy(() => z.union([z.string(), z.number().finite(), z.boolean(), z.null(), z.array(jsonValueSchema), z.record(z.string(), jsonValueSchema)]));
|
|
106
113
|
export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
107
114
|
vgxness_sdd_status: z
|
|
@@ -114,7 +121,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
114
121
|
.object({
|
|
115
122
|
project: z.string().min(1),
|
|
116
123
|
change: z.string().min(1),
|
|
117
|
-
phase:
|
|
124
|
+
phase: sddPhaseInputSchema,
|
|
118
125
|
runId: z.string().min(1).optional(),
|
|
119
126
|
agentId: z.string().min(1).optional(),
|
|
120
127
|
})
|
|
@@ -123,7 +130,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
123
130
|
.object({
|
|
124
131
|
project: z.string().min(1),
|
|
125
132
|
change: z.string().min(1),
|
|
126
|
-
phase:
|
|
133
|
+
phase: sddPhaseInputSchema,
|
|
127
134
|
runId: z.string().min(1).optional(),
|
|
128
135
|
agentId: z.string().min(1).optional(),
|
|
129
136
|
})
|
|
@@ -132,7 +139,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
132
139
|
.object({
|
|
133
140
|
project: z.string().min(1),
|
|
134
141
|
change: z.string().min(1),
|
|
135
|
-
phase:
|
|
142
|
+
phase: sddPhaseInputSchema,
|
|
136
143
|
content: z.string().min(1),
|
|
137
144
|
})
|
|
138
145
|
.passthrough(),
|
|
@@ -140,7 +147,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
140
147
|
.object({
|
|
141
148
|
project: z.string().min(1),
|
|
142
149
|
change: z.string().min(1),
|
|
143
|
-
phase:
|
|
150
|
+
phase: sddPhaseInputSchema,
|
|
144
151
|
acceptedBy: z.object({
|
|
145
152
|
type: z.literal('human'),
|
|
146
153
|
id: z.string().min(1),
|
|
@@ -148,8 +155,22 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
148
155
|
}),
|
|
149
156
|
acceptedAt: z.string().min(1).optional(),
|
|
150
157
|
note: z.string().min(1).optional(),
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
runId: z.string().min(1).optional(),
|
|
159
|
+
agentId: z.string().min(1).optional(),
|
|
160
|
+
})
|
|
161
|
+
.passthrough(),
|
|
162
|
+
vgxness_sdd_reopen_artifact: z
|
|
163
|
+
.object({
|
|
164
|
+
project: z.string().min(1),
|
|
165
|
+
change: z.string().min(1),
|
|
166
|
+
phase: sddPhaseInputSchema,
|
|
167
|
+
reopenedBy: z.object({
|
|
168
|
+
type: z.literal('human'),
|
|
169
|
+
id: z.string().min(1),
|
|
170
|
+
displayName: z.string().min(1).optional(),
|
|
171
|
+
}),
|
|
172
|
+
reopenedAt: z.string().min(1).optional(),
|
|
173
|
+
note: z.string().min(1).optional(),
|
|
153
174
|
runId: z.string().min(1).optional(),
|
|
154
175
|
agentId: z.string().min(1).optional(),
|
|
155
176
|
})
|
|
@@ -158,7 +179,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
158
179
|
.object({
|
|
159
180
|
project: z.string().min(1),
|
|
160
181
|
change: z.string().min(1),
|
|
161
|
-
phase:
|
|
182
|
+
phase: sddPhaseInputSchema,
|
|
162
183
|
payloadMode: z.enum(payloadModes).optional(),
|
|
163
184
|
})
|
|
164
185
|
.passthrough(),
|
|
@@ -181,6 +202,13 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
181
202
|
change: z.string().min(1),
|
|
182
203
|
})
|
|
183
204
|
.passthrough(),
|
|
205
|
+
vgxness_sdd_continue: z
|
|
206
|
+
.object({
|
|
207
|
+
project: z.string().min(1),
|
|
208
|
+
change: z.string().min(1),
|
|
209
|
+
payloadMode: z.enum(payloadModes).optional(),
|
|
210
|
+
})
|
|
211
|
+
.passthrough(),
|
|
184
212
|
vgxness_governance_report: z
|
|
185
213
|
.object({
|
|
186
214
|
project: z.string().min(1),
|
|
@@ -348,7 +376,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
348
376
|
workspaceRoot: z.string().min(1).optional(),
|
|
349
377
|
maxSourceBytes: z.number().int().positive().optional(),
|
|
350
378
|
change: z.string().min(1).optional(),
|
|
351
|
-
phase:
|
|
379
|
+
phase: sddPhaseInputSchema.optional(),
|
|
352
380
|
})
|
|
353
381
|
.passthrough(),
|
|
354
382
|
vgxness_run_list: z
|
|
@@ -415,6 +443,12 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
415
443
|
outcomeReason: z.string().min(1).optional(),
|
|
416
444
|
})
|
|
417
445
|
.passthrough(),
|
|
446
|
+
vgxness_run_resume_candidates: z
|
|
447
|
+
.object({
|
|
448
|
+
project: z.string().min(1),
|
|
449
|
+
limit: z.number().int().min(1).max(100).optional(),
|
|
450
|
+
})
|
|
451
|
+
.passthrough(),
|
|
418
452
|
vgxness_run_resume_inspect: z
|
|
419
453
|
.object({
|
|
420
454
|
runId: z.string().min(1),
|
package/dist/mcp/stdio-server.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { runBootAgentSeedUpgrade } from '../agents/boot-upgrade.js';
|
|
3
4
|
import { createVgxMcpControlPlane } from './control-plane.js';
|
|
4
5
|
import { EXPOSED_VGX_MCP_TOOL_NAMES, toInternalVgxMcpToolName, VGX_MCP_TOOL_INPUT_SCHEMAS, } from './schema.js';
|
|
5
6
|
export async function startVgxMcpStdioServer(options = {}) {
|
|
6
7
|
const controlPlane = createVgxMcpControlPlane(options.databasePath === undefined ? {} : { databasePath: options.databasePath });
|
|
8
|
+
runBootAgentSeedUpgrade(controlPlane.database);
|
|
7
9
|
const mcpServer = new McpServer({ name: 'vgxness', version: '0.1.0' });
|
|
8
10
|
const transport = new StdioServerTransport();
|
|
9
11
|
let closed = false;
|
|
@@ -55,6 +57,8 @@ function descriptionForTool(publicToolName) {
|
|
|
55
57
|
return 'Read-only OpenCode handoff preview; returns context for manual continuation only, does not execute/control OpenCode, write .opencode/provider config, or create runs, checkpoints, events, sessions, or skill-usage records.';
|
|
56
58
|
if (publicToolName === 'verification_plan')
|
|
57
59
|
return 'Read-only verification plan recommendations only; does not execute commands, write provider config, persist results, create checkpoints, or infer SDD acceptance.';
|
|
60
|
+
if (publicToolName === 'run_resume_candidates')
|
|
61
|
+
return 'Read-only interrupted run resume candidate discovery by project; lists bounded failed, blocked, and needs-human runs without mutation, retry admission, provider execution, artifact/config/openspec writes, sandboxes, worktrees, or sessions.';
|
|
58
62
|
if (publicToolName === 'run_resume_inspect')
|
|
59
63
|
return 'Read-only run resume advisory inspect; plan-only and does not execute resume logic, invoke providers, write provider config, mutate retry/abandon/attempt state, or reconstruct sandboxes, worktrees, sessions, or transcripts.';
|
|
60
64
|
if (publicToolName === 'run_resume_gate')
|
|
@@ -63,6 +67,8 @@ function descriptionForTool(publicToolName) {
|
|
|
63
67
|
return 'Read-only context cockpit for start/resume/recovery; returns latest restorable session plus bounded memory previews without traces, provider config writes, repository writes, runs, artifacts, or session mutations.';
|
|
64
68
|
if (publicToolName === 'sdd_cockpit')
|
|
65
69
|
return 'Read-only SDD cockpit summary with next decision, explicit acceptance state, metadata-only artifact summaries, and aggregate blockers.';
|
|
70
|
+
if (publicToolName === 'sdd_continue')
|
|
71
|
+
return 'Read-only SDD continuation planner; returns blocker actions, safe suggested commands, related interrupted run context, and safety notes without provider execution, run creation, artifact mutation, provider config writes, or openspec writes.';
|
|
66
72
|
const toolName = toInternalVgxMcpToolName(publicToolName);
|
|
67
73
|
return `VGX control-plane tool ${toolName}`;
|
|
68
74
|
}
|