vgxness 1.5.0 → 1.5.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/README.md +23 -2
- package/dist/agents/agent-seed-service.js +10 -0
- package/dist/agents/canonical-agent-manifest.js +177 -0
- package/dist/agents/canonical-agent-projection.js +146 -0
- package/dist/agents/renderers/claude-renderer.js +30 -52
- package/dist/cli/bun-bin.js +6 -0
- package/dist/cli/cli-help.js +3 -0
- package/dist/cli/commands/agent-skill-dispatcher.js +6 -5
- package/dist/cli/commands/mcp-dispatcher.js +65 -3
- package/dist/cli/index.js +1 -1
- package/dist/governance/governance-report-builder.js +45 -26
- package/dist/mcp/claude-code-agent-config.js +79 -0
- package/dist/mcp/claude-code-config.js +84 -0
- package/dist/mcp/client-install-claude-code-contract.js +86 -0
- package/dist/mcp/client-install-claude-code.js +85 -0
- package/dist/mcp/control-plane.js +2 -0
- package/dist/mcp/index.js +5 -0
- package/dist/mcp/opencode-default-agent-config.js +7 -113
- package/dist/mcp/provider-canonical-agent-manifest.js +39 -0
- package/dist/mcp/provider-change-plan.js +57 -1
- package/dist/mcp/provider-doctor.js +54 -0
- package/dist/mcp/provider-health-types.js +3 -1
- package/dist/mcp/provider-status.js +82 -2
- package/dist/mcp/schema.js +11 -2
- package/dist/mcp/stdio-server.js +2 -0
- package/dist/mcp/validation.js +23 -1
- package/dist/memory/memory-service.js +59 -0
- package/dist/memory/repositories/sessions.js +1 -1
- package/dist/sdd/sdd-workflow-service.js +129 -59
- package/dist/setup/providers/claude-setup-adapter.js +7 -4
- package/docs/architecture.md +54 -112
- package/docs/cli.md +53 -0
- package/docs/code-runtime.md +218 -0
- package/docs/contributing.md +120 -0
- package/docs/glossary.md +211 -0
- package/docs/mcp.md +144 -0
- package/docs/prd.md +23 -26
- package/docs/providers.md +123 -0
- package/docs/roadmap.md +88 -0
- package/docs/safety.md +147 -0
- package/docs/storage.md +93 -0
- package/package.json +1 -1
- package/docs/funcionamiento-del-sistema.md +0 -865
- package/docs/harness-gap-analysis.md +0 -243
- package/docs/vgxcode.md +0 -87
- package/docs/vgxness-code.md +0 -48
package/dist/mcp/validation.js
CHANGED
|
@@ -66,6 +66,8 @@ export function validateVgxMcpToolCall(call) {
|
|
|
66
66
|
return validationSuccess(tool.value, validateSessionCloseInput(input, tool.value));
|
|
67
67
|
case 'vgxness_session_restore':
|
|
68
68
|
return validationSuccess(tool.value, validateSessionRestoreInput(input, tool.value));
|
|
69
|
+
case 'vgxness_context_cockpit':
|
|
70
|
+
return validationSuccess(tool.value, validateContextCockpitInput(input, tool.value));
|
|
69
71
|
case 'vgxness_agent_resolve':
|
|
70
72
|
return validationSuccess(tool.value, validateAgentResolveInput(input, tool.value));
|
|
71
73
|
case 'vgxness_agent_activate':
|
|
@@ -185,7 +187,7 @@ function validateProviderHealthInput(input, tool) {
|
|
|
185
187
|
return scope;
|
|
186
188
|
if (scope.value !== undefined)
|
|
187
189
|
result.scope = scope.value;
|
|
188
|
-
const providerAdapter = readOptionalOneOf(record.value, 'providerAdapter', ['opencode'], tool);
|
|
190
|
+
const providerAdapter = readOptionalOneOf(record.value, 'providerAdapter', ['opencode', 'claude'], tool);
|
|
189
191
|
if (!providerAdapter.ok)
|
|
190
192
|
return providerAdapter;
|
|
191
193
|
if (providerAdapter.value !== undefined)
|
|
@@ -234,6 +236,26 @@ function validateSddCockpitInput(input, tool) {
|
|
|
234
236
|
return record;
|
|
235
237
|
return readProjectAndChange(record.value, tool);
|
|
236
238
|
}
|
|
239
|
+
function validateContextCockpitInput(input, tool) {
|
|
240
|
+
const record = inputRecord(input, tool, ['project', 'directory', 'limit']);
|
|
241
|
+
if (!record.ok)
|
|
242
|
+
return record;
|
|
243
|
+
const project = readNonEmptyString(record.value, 'project', tool);
|
|
244
|
+
if (!project.ok)
|
|
245
|
+
return project;
|
|
246
|
+
const result = { project: project.value };
|
|
247
|
+
const directory = readOptionalNonEmptyString(record.value, 'directory', tool);
|
|
248
|
+
if (!directory.ok)
|
|
249
|
+
return directory;
|
|
250
|
+
if (directory.value !== undefined)
|
|
251
|
+
result.directory = directory.value;
|
|
252
|
+
if (record.value.limit !== undefined) {
|
|
253
|
+
if (typeof record.value.limit !== 'number' || !Number.isSafeInteger(record.value.limit) || record.value.limit < 1 || record.value.limit > 100)
|
|
254
|
+
return validationFailure('limit must be an integer between 1 and 100', tool);
|
|
255
|
+
result.limit = record.value.limit;
|
|
256
|
+
}
|
|
257
|
+
return { ok: true, value: result };
|
|
258
|
+
}
|
|
237
259
|
function readProjectAndChange(record, tool) {
|
|
238
260
|
const project = readNonEmptyString(record, 'project', tool);
|
|
239
261
|
if (!project.ok)
|
|
@@ -50,6 +50,54 @@ export class MemoryService {
|
|
|
50
50
|
const result = this.observations.searchPreviews(filters);
|
|
51
51
|
return this.record(result, context, { operation: 'observation.search', targetType: 'observation', topicKey: filters.topicKey });
|
|
52
52
|
}
|
|
53
|
+
/** Read memory previews without writing provenance traces. */
|
|
54
|
+
searchObservationPreviewsNoTrace(filters) {
|
|
55
|
+
return this.observations.searchPreviews(filters);
|
|
56
|
+
}
|
|
57
|
+
/** Read compact current context without writing traces or mutating durable state. */
|
|
58
|
+
getContextCockpit(input) {
|
|
59
|
+
const limit = normalizeContextLimit(input.limit);
|
|
60
|
+
const memories = this.searchObservationPreviewsNoTrace({ project: input.project, limit });
|
|
61
|
+
if (!memories.ok)
|
|
62
|
+
return { ok: false, error: memories.error };
|
|
63
|
+
const session = this.restoreSession(input.directory === undefined ? { project: input.project } : { project: input.project, directory: input.directory });
|
|
64
|
+
if (!session.ok && session.error.code !== 'not_found')
|
|
65
|
+
return { ok: false, error: session.error };
|
|
66
|
+
const latestRestorableSession = session.ok ? session.value : undefined;
|
|
67
|
+
const newestMemoryUpdatedAt = memories.value[0]?.updatedAt;
|
|
68
|
+
const latestSessionEndedAt = latestRestorableSession?.endedAt;
|
|
69
|
+
const stale = latestRestorableSession === undefined || (newestMemoryUpdatedAt !== undefined && latestSessionEndedAt !== undefined && newestMemoryUpdatedAt > latestSessionEndedAt);
|
|
70
|
+
const staleness = {
|
|
71
|
+
stale,
|
|
72
|
+
reason: latestRestorableSession === undefined ? 'no-restorable-session' : stale ? 'memory-newer-than-session' : 'current',
|
|
73
|
+
...(newestMemoryUpdatedAt === undefined ? {} : { newestMemoryUpdatedAt }),
|
|
74
|
+
...(latestSessionEndedAt === undefined ? {} : { latestSessionEndedAt }),
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
value: {
|
|
79
|
+
version: 1,
|
|
80
|
+
kind: 'context-cockpit',
|
|
81
|
+
project: input.project,
|
|
82
|
+
...(input.directory === undefined ? {} : { directory: input.directory }),
|
|
83
|
+
...(latestRestorableSession === undefined ? {} : { latestRestorableSession }),
|
|
84
|
+
memoryPreviews: memories.value,
|
|
85
|
+
staleness,
|
|
86
|
+
optionalSectionsOmitted: ['sdd', 'runs'],
|
|
87
|
+
notes: ['SDD and run summaries are omitted because safe no-trace metadata-only aggregation is not part of this cockpit path yet.'],
|
|
88
|
+
safety: {
|
|
89
|
+
readOnly: true,
|
|
90
|
+
recordsTraces: false,
|
|
91
|
+
mutatesSessions: false,
|
|
92
|
+
mutatesMemories: false,
|
|
93
|
+
mutatesArtifacts: false,
|
|
94
|
+
mutatesRuns: false,
|
|
95
|
+
writesProviderConfig: false,
|
|
96
|
+
mutatesRepository: false,
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
53
101
|
listObservationRevisions(id, context) {
|
|
54
102
|
const result = this.observations.listRevisions(id);
|
|
55
103
|
return this.record(result, context, { operation: 'observation.revisions.list', targetType: 'observation', targetId: id });
|
|
@@ -113,6 +161,10 @@ export class MemoryService {
|
|
|
113
161
|
const result = this.artifacts.listByTopicPrefix(project, topicPrefix);
|
|
114
162
|
return this.record(result, context, { operation: 'artifact.list', targetType: 'artifact', topicKey: topicPrefix });
|
|
115
163
|
}
|
|
164
|
+
/** Read artifacts for read-only/status projections without writing provenance traces. */
|
|
165
|
+
listArtifactsByTopicPrefixNoTrace(project, topicPrefix) {
|
|
166
|
+
return this.artifacts.listByTopicPrefix(project, topicPrefix);
|
|
167
|
+
}
|
|
116
168
|
close() {
|
|
117
169
|
this.database.close();
|
|
118
170
|
}
|
|
@@ -140,3 +192,10 @@ class MemoryServiceTransactionRollback extends Error {
|
|
|
140
192
|
super('Memory service transaction rolled back');
|
|
141
193
|
}
|
|
142
194
|
}
|
|
195
|
+
function normalizeContextLimit(limit) {
|
|
196
|
+
if (limit === undefined)
|
|
197
|
+
return 5;
|
|
198
|
+
if (!Number.isFinite(limit))
|
|
199
|
+
return 5;
|
|
200
|
+
return Math.max(1, Math.min(100, Math.trunc(limit)));
|
|
201
|
+
}
|
|
@@ -39,7 +39,7 @@ export class SessionRepository {
|
|
|
39
39
|
AND summary IS NOT NULL
|
|
40
40
|
AND TRIM(summary) <> ''
|
|
41
41
|
AND (@directory IS NULL OR directory = @directory)
|
|
42
|
-
ORDER BY ended_at DESC
|
|
42
|
+
ORDER BY ended_at DESC, started_at DESC, id DESC
|
|
43
43
|
LIMIT 1
|
|
44
44
|
`)
|
|
45
45
|
.get({ project: input.project, directory: input.directory ?? null });
|
|
@@ -21,7 +21,9 @@ export class SddWorkflowService {
|
|
|
21
21
|
if (!validated.ok)
|
|
22
22
|
return validated;
|
|
23
23
|
const phases = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
24
|
-
|
|
24
|
+
if (!phases.ok)
|
|
25
|
+
return phases;
|
|
26
|
+
const readiness = getReadinessFromStatuses(validated.value.change, validated.value.phase, phases.value);
|
|
25
27
|
return {
|
|
26
28
|
ok: true,
|
|
27
29
|
value: {
|
|
@@ -36,20 +38,27 @@ export class SddWorkflowService {
|
|
|
36
38
|
if (!validated.ok)
|
|
37
39
|
return validated;
|
|
38
40
|
const phases = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
39
|
-
|
|
41
|
+
if (!phases.ok)
|
|
42
|
+
return phases;
|
|
43
|
+
return statusFromPhases(validated.value.change, phases.value);
|
|
40
44
|
}
|
|
41
45
|
getNext(input) {
|
|
42
46
|
const validated = validateProjectAndChange(input.project, input.change);
|
|
43
47
|
if (!validated.ok)
|
|
44
48
|
return validated;
|
|
45
49
|
const phases = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
46
|
-
|
|
50
|
+
if (!phases.ok)
|
|
51
|
+
return phases;
|
|
52
|
+
return ok(nextDecisionFromStatuses(validated.value.change, phases.value));
|
|
47
53
|
}
|
|
48
54
|
getCockpit(input) {
|
|
49
55
|
const validated = validateProjectAndChange(input.project, input.change);
|
|
50
56
|
if (!validated.ok)
|
|
51
57
|
return validated;
|
|
52
|
-
const
|
|
58
|
+
const snapshot = this.loadPhaseSnapshot(validated.value.project, validated.value.change);
|
|
59
|
+
if (!snapshot.ok)
|
|
60
|
+
return snapshot;
|
|
61
|
+
const phases = snapshot.value.phases;
|
|
53
62
|
const next = nextDecisionFromStatuses(validated.value.change, phases);
|
|
54
63
|
const cockpitPhases = phases.map((phaseStatus) => {
|
|
55
64
|
const readiness = {
|
|
@@ -57,9 +66,7 @@ export class SddWorkflowService {
|
|
|
57
66
|
phase: phaseStatus.phase,
|
|
58
67
|
...getReadinessFromStatuses(validated.value.change, phaseStatus.phase, phases),
|
|
59
68
|
};
|
|
60
|
-
const artifact = phaseStatus.present
|
|
61
|
-
? this.artifactSummaryForPhase(validated.value.project, validated.value.change, phaseStatus.phase, phaseStatus.topicKey)
|
|
62
|
-
: undefined;
|
|
69
|
+
const artifact = phaseStatus.present ? cockpitArtifactSummaryFromSnapshotItem(phaseStatus) : undefined;
|
|
63
70
|
const blockers = cockpitBlockersForPhase(phaseStatus, readiness);
|
|
64
71
|
return {
|
|
65
72
|
phase: phaseStatus.phase,
|
|
@@ -100,6 +107,39 @@ export class SddWorkflowService {
|
|
|
100
107
|
};
|
|
101
108
|
return ok(cockpit);
|
|
102
109
|
}
|
|
110
|
+
getGovernanceSnapshot(input) {
|
|
111
|
+
const validated = validateProjectAndChange(input.project, input.change);
|
|
112
|
+
if (!validated.ok)
|
|
113
|
+
return validated;
|
|
114
|
+
const snapshot = this.loadPhaseSnapshot(validated.value.project, validated.value.change);
|
|
115
|
+
if (!snapshot.ok)
|
|
116
|
+
return snapshot;
|
|
117
|
+
const phases = snapshot.value.phases;
|
|
118
|
+
const status = statusFromPhases(validated.value.change, phases);
|
|
119
|
+
if (!status.ok)
|
|
120
|
+
return status;
|
|
121
|
+
const warnings = [];
|
|
122
|
+
const artifacts = phases.flatMap((phase) => {
|
|
123
|
+
if (phase.artifact === undefined)
|
|
124
|
+
return [];
|
|
125
|
+
const envelope = normalizeSddArtifact(phase.artifact);
|
|
126
|
+
warnings.push(...envelope.warnings);
|
|
127
|
+
if ((input.payloadMode ?? 'compact') === 'compact') {
|
|
128
|
+
const compactArtifact = compactGovernanceArtifact(envelope.artifact);
|
|
129
|
+
return [
|
|
130
|
+
{
|
|
131
|
+
phase: phase.phase,
|
|
132
|
+
topicKey: phase.topicKey,
|
|
133
|
+
artifact: compactArtifact,
|
|
134
|
+
envelope: { ...envelope, artifact: compactArtifact },
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
}
|
|
138
|
+
return [{ phase: phase.phase, topicKey: phase.topicKey, artifact: phase.artifact, envelope }];
|
|
139
|
+
});
|
|
140
|
+
const readiness = input.phase === undefined ? undefined : { change: validated.value.change, phase: input.phase, ...getReadinessFromStatuses(validated.value.change, input.phase, phases) };
|
|
141
|
+
return ok({ status: status.value, artifacts, ...(readiness === undefined ? {} : { readiness }), warnings });
|
|
142
|
+
}
|
|
103
143
|
saveArtifact(input) {
|
|
104
144
|
const validated = this.validatePhaseInput(input);
|
|
105
145
|
if (!validated.ok)
|
|
@@ -161,12 +201,33 @@ export class SddWorkflowService {
|
|
|
161
201
|
if (input.payloadMode !== 'compact')
|
|
162
202
|
return artifact;
|
|
163
203
|
const statuses = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
164
|
-
|
|
204
|
+
if (!statuses.ok)
|
|
205
|
+
return statuses;
|
|
206
|
+
return ok(compactArtifactProjection(artifact.value, validated.value.change, validated.value.phase, getReadinessFromStatuses(validated.value.change, validated.value.phase, statuses.value)));
|
|
165
207
|
}
|
|
166
208
|
listArtifacts(input) {
|
|
167
209
|
const validated = validateProjectAndChange(input.project, input.change);
|
|
168
210
|
if (!validated.ok)
|
|
169
211
|
return validated;
|
|
212
|
+
if (input.payloadMode === 'compact') {
|
|
213
|
+
const snapshot = this.loadPhaseSnapshot(validated.value.project, validated.value.change);
|
|
214
|
+
if (!snapshot.ok)
|
|
215
|
+
return snapshot;
|
|
216
|
+
return ok({
|
|
217
|
+
project: validated.value.project,
|
|
218
|
+
change: validated.value.change,
|
|
219
|
+
artifacts: snapshot.value.phases.flatMap((phase) => {
|
|
220
|
+
if (phase.artifact === undefined)
|
|
221
|
+
return [];
|
|
222
|
+
return [compactArtifactProjection(phase.artifact, validated.value.change, phase.phase, getReadinessFromStatuses(validated.value.change, phase.phase, snapshot.value.phases))];
|
|
223
|
+
}),
|
|
224
|
+
fullRetrieval: {
|
|
225
|
+
tool: 'vgxness_sdd_list_artifacts',
|
|
226
|
+
payloadMode: 'verbose',
|
|
227
|
+
input: { project: validated.value.project, change: validated.value.change },
|
|
228
|
+
},
|
|
229
|
+
});
|
|
230
|
+
}
|
|
170
231
|
const listed = this.memory.listArtifactsByTopicPrefix(validated.value.project, `sdd/${validated.value.change}/`, this.context);
|
|
171
232
|
if (!listed.ok)
|
|
172
233
|
return listed;
|
|
@@ -174,22 +235,7 @@ export class SddWorkflowService {
|
|
|
174
235
|
const artifacts = sddPhases
|
|
175
236
|
.map((phase) => artifactsByTopicKey.get(sddTopicKey(validated.value.change, phase)))
|
|
176
237
|
.filter((artifact) => artifact !== undefined);
|
|
177
|
-
|
|
178
|
-
return ok({ project: validated.value.project, change: validated.value.change, artifacts });
|
|
179
|
-
const statuses = this.getPhaseStatuses(validated.value.project, validated.value.change);
|
|
180
|
-
return ok({
|
|
181
|
-
project: validated.value.project,
|
|
182
|
-
change: validated.value.change,
|
|
183
|
-
artifacts: artifacts.map((artifact) => {
|
|
184
|
-
const phase = isSddPhase(artifact.phase) ? artifact.phase : phaseFromTopicKey(validated.value.change, artifact.topicKey);
|
|
185
|
-
return compactArtifactProjection(artifact, validated.value.change, phase, getReadinessFromStatuses(validated.value.change, phase, statuses));
|
|
186
|
-
}),
|
|
187
|
-
fullRetrieval: {
|
|
188
|
-
tool: 'vgxness_sdd_list_artifacts',
|
|
189
|
-
payloadMode: 'verbose',
|
|
190
|
-
input: { project: validated.value.project, change: validated.value.change },
|
|
191
|
-
},
|
|
192
|
-
});
|
|
238
|
+
return ok({ project: validated.value.project, change: validated.value.change, artifacts });
|
|
193
239
|
}
|
|
194
240
|
validatePhaseInput(input) {
|
|
195
241
|
const validated = validateProjectAndChange(input.project, input.change);
|
|
@@ -200,31 +246,38 @@ export class SddWorkflowService {
|
|
|
200
246
|
return { ok: true, value: { ...validated.value, phase: input.phase } };
|
|
201
247
|
}
|
|
202
248
|
getPhaseStatuses(project, change) {
|
|
203
|
-
|
|
249
|
+
const snapshot = this.loadPhaseSnapshot(project, change);
|
|
250
|
+
if (!snapshot.ok)
|
|
251
|
+
return snapshot;
|
|
252
|
+
return ok(snapshot.value.phases.map(({ artifact, acceptance, createdAt, updatedAt, warnings, ...status }) => status));
|
|
253
|
+
}
|
|
254
|
+
loadPhaseSnapshot(project, change) {
|
|
255
|
+
const listed = this.memory.listArtifactsByTopicPrefixNoTrace(project, `sdd/${change}/`);
|
|
256
|
+
if (!listed.ok)
|
|
257
|
+
return listed;
|
|
258
|
+
const artifactsByTopicKey = new Map(listed.value.map((artifact) => [artifact.topicKey, artifact]));
|
|
259
|
+
const phases = sddPhases.map((phase) => {
|
|
204
260
|
const topicKey = sddTopicKey(change, phase);
|
|
205
|
-
const artifact =
|
|
206
|
-
if (
|
|
207
|
-
return { phase, topicKey, present: false, state: 'missing', accepted: false, legacy: false };
|
|
208
|
-
|
|
261
|
+
const artifact = artifactsByTopicKey.get(topicKey);
|
|
262
|
+
if (artifact === undefined)
|
|
263
|
+
return { phase, topicKey, present: false, state: 'missing', accepted: false, legacy: false, warnings: [] };
|
|
264
|
+
const envelope = normalizeSddArtifact(artifact);
|
|
265
|
+
return {
|
|
266
|
+
phase,
|
|
267
|
+
topicKey,
|
|
268
|
+
present: true,
|
|
269
|
+
state: envelope.metadata.status,
|
|
270
|
+
accepted: envelope.metadata.status === 'accepted',
|
|
271
|
+
legacy: envelope.warnings.includes('legacy-artifact-defaulted-to-draft'),
|
|
272
|
+
artifactId: artifact.id,
|
|
273
|
+
artifact,
|
|
274
|
+
...(envelope.metadata.acceptance === undefined ? {} : { acceptance: envelope.metadata.acceptance }),
|
|
275
|
+
createdAt: artifact.createdAt,
|
|
276
|
+
updatedAt: artifact.updatedAt,
|
|
277
|
+
warnings: envelope.warnings,
|
|
278
|
+
};
|
|
209
279
|
});
|
|
210
|
-
|
|
211
|
-
artifactSummaryForPhase(project, change, phase, topicKey) {
|
|
212
|
-
const artifact = this.memory.getArtifact(project, topicKey, this.context);
|
|
213
|
-
if (!artifact.ok)
|
|
214
|
-
return undefined;
|
|
215
|
-
const envelope = normalizeSddArtifact(artifact.value);
|
|
216
|
-
return {
|
|
217
|
-
phase,
|
|
218
|
-
topicKey,
|
|
219
|
-
present: true,
|
|
220
|
-
accepted: envelope.metadata.status === 'accepted',
|
|
221
|
-
legacy: envelope.warnings.includes('legacy-artifact-defaulted-to-draft'),
|
|
222
|
-
state: envelope.metadata.status,
|
|
223
|
-
artifactId: artifact.value.id,
|
|
224
|
-
...(envelope.metadata.acceptance === undefined ? {} : { acceptance: envelope.metadata.acceptance }),
|
|
225
|
-
createdAt: artifact.value.createdAt,
|
|
226
|
-
updatedAt: artifact.value.updatedAt,
|
|
227
|
-
};
|
|
280
|
+
return ok({ project, change, phases });
|
|
228
281
|
}
|
|
229
282
|
}
|
|
230
283
|
export function nextDecisionFromStatuses(change, phases) {
|
|
@@ -336,18 +389,6 @@ function getReadinessFromStatuses(change, phase, phases) {
|
|
|
336
389
|
blockedPrerequisites,
|
|
337
390
|
};
|
|
338
391
|
}
|
|
339
|
-
function phaseStatusFromArtifact(phase, topicKey, artifact) {
|
|
340
|
-
const envelope = normalizeSddArtifact(artifact);
|
|
341
|
-
return {
|
|
342
|
-
phase,
|
|
343
|
-
topicKey,
|
|
344
|
-
present: true,
|
|
345
|
-
state: envelope.metadata.status,
|
|
346
|
-
accepted: envelope.metadata.status === 'accepted',
|
|
347
|
-
legacy: envelope.warnings.includes('legacy-artifact-defaulted-to-draft'),
|
|
348
|
-
artifactId: artifact.id,
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
392
|
function compactArtifactProjection(artifact, change, phase, readiness) {
|
|
352
393
|
const envelope = normalizeSddArtifact(artifact);
|
|
353
394
|
const summary = summarizePayloadContent(artifact.content);
|
|
@@ -370,6 +411,35 @@ function compactArtifactProjection(artifact, change, phase, readiness) {
|
|
|
370
411
|
updatedAt: artifact.updatedAt,
|
|
371
412
|
};
|
|
372
413
|
}
|
|
414
|
+
function cockpitArtifactSummaryFromSnapshotItem(item) {
|
|
415
|
+
if (item.artifact === undefined || item.artifactId === undefined || item.createdAt === undefined || item.updatedAt === undefined)
|
|
416
|
+
return undefined;
|
|
417
|
+
return {
|
|
418
|
+
phase: item.phase,
|
|
419
|
+
topicKey: item.topicKey,
|
|
420
|
+
present: true,
|
|
421
|
+
accepted: item.accepted === true,
|
|
422
|
+
legacy: item.legacy === true,
|
|
423
|
+
state: item.state ?? 'draft',
|
|
424
|
+
artifactId: item.artifactId,
|
|
425
|
+
...(item.acceptance === undefined ? {} : { acceptance: item.acceptance }),
|
|
426
|
+
createdAt: item.createdAt,
|
|
427
|
+
updatedAt: item.updatedAt,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function compactGovernanceArtifact(artifact) {
|
|
431
|
+
return {
|
|
432
|
+
id: artifact.id,
|
|
433
|
+
project: artifact.project,
|
|
434
|
+
topicKey: artifact.topicKey,
|
|
435
|
+
phase: artifact.phase,
|
|
436
|
+
observationId: artifact.observationId,
|
|
437
|
+
createdAt: artifact.createdAt,
|
|
438
|
+
updatedAt: artifact.updatedAt,
|
|
439
|
+
contentLength: artifact.content.length,
|
|
440
|
+
contentOmitted: true,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
373
443
|
function cockpitBlockersForPhase(status, readiness) {
|
|
374
444
|
const blockers = [];
|
|
375
445
|
if (!status.present)
|
|
@@ -4,17 +4,20 @@ export const claudeSetupAdapter = {
|
|
|
4
4
|
id: 'claude',
|
|
5
5
|
displayName: 'Claude',
|
|
6
6
|
supportLevel: 'preview-only',
|
|
7
|
-
capabilities: ['mcp-preview', 'manual-guidance'],
|
|
8
|
-
targets: [
|
|
7
|
+
capabilities: ['mcp-preview', 'mcp-install-plan', 'agent-preview', 'doctor', 'manual-guidance'],
|
|
8
|
+
targets: [
|
|
9
|
+
{ kind: 'project-config', label: 'Project .mcp.json', path: '.mcp.json', writableBySetup: false },
|
|
10
|
+
{ kind: 'project-config', label: 'Project Claude agents', path: '.claude/agents/*.md', writableBySetup: false },
|
|
11
|
+
],
|
|
9
12
|
getStatus(context) {
|
|
10
13
|
return {
|
|
11
14
|
providerId: 'claude',
|
|
12
15
|
status: 'preview-only',
|
|
13
|
-
summary: 'Claude setup
|
|
16
|
+
summary: 'Claude setup supports project-local read-only planning for .mcp.json and .claude/agents/*.md; confirmed writes are handled by guarded install flows.',
|
|
14
17
|
evidence: context.databasePath !== undefined
|
|
15
18
|
? ['Claude MCP preview can be generated from the selected database path.']
|
|
16
19
|
: ['Claude MCP preview uses a placeholder until a database path is selected.'],
|
|
17
|
-
guidance: ['
|
|
20
|
+
guidance: ['Review the Claude plan before any write. VGXNESS never writes ~/.claude.json, CLAUDE.md, or .claude/CLAUDE.md and does not execute/install Claude Code.'],
|
|
18
21
|
actions: [
|
|
19
22
|
{
|
|
20
23
|
id: 'claude-manual-guidance',
|