vgxness 1.20.8 → 1.20.9
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/application/code-context/code-context-service.js +226 -0
- package/dist/application/code-context/providers/status-probes.js +34 -0
- package/dist/domain/agents/canonical-agent-manifest.js +5 -3
- package/dist/domain/code-context/schema.js +20 -0
- package/dist/interfaces/cli/cli-help.js +1 -1
- package/dist/interfaces/cli/commands/code-context-dispatcher.js +67 -0
- package/dist/interfaces/cli/commands/index.js +1 -0
- package/dist/interfaces/cli/dispatcher.js +6 -1
- package/dist/interfaces/mcp/contracts/code-context.js +1 -0
- package/dist/interfaces/mcp/control-plane/handlers/code-context.js +7 -0
- package/dist/interfaces/mcp/control-plane.js +5 -0
- package/dist/interfaces/mcp/schema.js +4 -1
- package/dist/interfaces/mcp/schemas/inputs/code-context.js +10 -0
- package/dist/interfaces/mcp/schemas/inputs/index.js +1 -0
- package/dist/interfaces/mcp/validation/code-context.js +22 -0
- package/dist/interfaces/mcp/validation.js +3 -0
- package/dist/verification/verification-plan-service.js +14 -0
- package/dist/verification/verification-plan.js +1 -0
- package/docs/cli.md +13 -0
- package/docs/mcp.md +10 -2
- package/package.json +1 -1
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { realpathSync, statSync } from 'node:fs';
|
|
3
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
4
|
+
import { codeContextProviderCommandSafety, codeContextSafety, } from '../../domain/code-context/schema.js';
|
|
5
|
+
import { codeContextProviderDefinitions, providerIndexStatus, providerReportPath } from './providers/status-probes.js';
|
|
6
|
+
const defaultTimeoutMs = 1_000;
|
|
7
|
+
const defaultMaxBytes = 4_096;
|
|
8
|
+
const maxTimeoutMs = 60_000;
|
|
9
|
+
const maxMaxBytes = 1_048_576;
|
|
10
|
+
export class CodeContextService {
|
|
11
|
+
commandRunner;
|
|
12
|
+
commandEnv;
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.commandRunner = options.commandRunner ?? runBoundedCommand;
|
|
15
|
+
this.commandEnv = options.commandEnv;
|
|
16
|
+
}
|
|
17
|
+
getStatus(input) {
|
|
18
|
+
const workspace = normalizeWorkspaceRoot(input.workspaceRoot);
|
|
19
|
+
if (!workspace.ok)
|
|
20
|
+
return workspace;
|
|
21
|
+
const workspaceRoot = workspace.value;
|
|
22
|
+
const timeoutMs = boundedTimeoutMs(input.timeoutMs);
|
|
23
|
+
const maxBytes = boundedMaxBytes(input.maxBytes);
|
|
24
|
+
const providerEntries = codeContextProviderDefinitions.map((provider) => {
|
|
25
|
+
const commandResult = this.commandRunner(this.withCommandEnv({ command: provider.command, args: provider.versionArgs, cwd: workspaceRoot, timeoutMs, maxBytes }));
|
|
26
|
+
const available = commandResult.ok && commandResult.exitCode === 0;
|
|
27
|
+
const index = providerIndexStatus(workspaceRoot, provider.indexRelativePath);
|
|
28
|
+
const diagnostics = available ? ['Provider command was found through a bounded read-only version probe.'] : ['Provider command is unavailable or version probe failed.'];
|
|
29
|
+
if (commandResult.truncated === true)
|
|
30
|
+
diagnostics.push('Provider version probe output was truncated at the bounded output cap.');
|
|
31
|
+
if (index.present)
|
|
32
|
+
diagnostics.push('Local graph index was detected by filesystem inspection only.');
|
|
33
|
+
const reportPath = providerReportPath(workspaceRoot, provider.reportRelativePath);
|
|
34
|
+
const status = {
|
|
35
|
+
provider: provider.id,
|
|
36
|
+
available,
|
|
37
|
+
...(available ? { version: firstLine(commandResult.stdout) } : {}),
|
|
38
|
+
index,
|
|
39
|
+
setupGuidance: [...provider.setupGuidance],
|
|
40
|
+
diagnostics,
|
|
41
|
+
};
|
|
42
|
+
if (reportPath !== undefined)
|
|
43
|
+
status.reportPath = reportPath;
|
|
44
|
+
return [provider.id, status];
|
|
45
|
+
});
|
|
46
|
+
const providers = Object.fromEntries(providerEntries);
|
|
47
|
+
const availableCount = Object.values(providers).filter((provider) => provider.available).length;
|
|
48
|
+
const overallStatus = availableCount === 0 ? 'unavailable' : availableCount === providerEntries.length ? 'available' : 'partial';
|
|
49
|
+
return {
|
|
50
|
+
ok: true,
|
|
51
|
+
value: {
|
|
52
|
+
kind: 'code-context-status',
|
|
53
|
+
version: 1,
|
|
54
|
+
workspaceRoot,
|
|
55
|
+
overallStatus,
|
|
56
|
+
providers,
|
|
57
|
+
safety: { ...codeContextSafety },
|
|
58
|
+
summary: `[read-only] Code-context providers: ${overallStatus}. No tools were installed, no indexes were initialized, and no provider config was written.`,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
query(input) {
|
|
63
|
+
const workspace = normalizeWorkspaceRoot(input.workspaceRoot);
|
|
64
|
+
if (!workspace.ok)
|
|
65
|
+
return workspace;
|
|
66
|
+
const workspaceRoot = workspace.value;
|
|
67
|
+
if (input.question.trim().length === 0)
|
|
68
|
+
return { ok: false, error: { code: 'invalid-question', message: 'question must not be empty.' } };
|
|
69
|
+
const mode = input.mode ?? 'overview';
|
|
70
|
+
const provider = selectProvider(input.provider ?? 'auto', mode);
|
|
71
|
+
const maxBytes = boundedMaxBytes(input.maxBytes);
|
|
72
|
+
const timeoutMs = boundedTimeoutMs(input.timeoutMs);
|
|
73
|
+
const status = this.getStatus({ workspaceRoot, timeoutMs, maxBytes });
|
|
74
|
+
if (!status.ok)
|
|
75
|
+
return status;
|
|
76
|
+
const providerStatus = status.value.providers[provider];
|
|
77
|
+
const command = commandFor(provider);
|
|
78
|
+
const args = queryArgs(provider, mode, input.question);
|
|
79
|
+
if (!providerStatus.available) {
|
|
80
|
+
return {
|
|
81
|
+
ok: true,
|
|
82
|
+
value: {
|
|
83
|
+
kind: 'code-context-query',
|
|
84
|
+
version: 1,
|
|
85
|
+
workspaceRoot,
|
|
86
|
+
provider,
|
|
87
|
+
mode,
|
|
88
|
+
question: input.question,
|
|
89
|
+
status: 'provider-unavailable',
|
|
90
|
+
summary: `[read-only] ${providerLabel(provider)} is unavailable. No install, init, hook, provider config, or index write was attempted.`,
|
|
91
|
+
command: { command, args },
|
|
92
|
+
setupGuidance: [...providerStatus.setupGuidance],
|
|
93
|
+
diagnostics: [...providerStatus.diagnostics],
|
|
94
|
+
safety: { ...codeContextSafety },
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
const commandResult = this.commandRunner(this.withCommandEnv({ command, args, cwd: workspaceRoot, timeoutMs, maxBytes }));
|
|
99
|
+
const ok = commandResult.ok && commandResult.exitCode === 0;
|
|
100
|
+
const output = firstNonEmpty(commandResult.stdout, commandResult.stderr);
|
|
101
|
+
const diagnostics = ok ? ['Provider query completed through a bounded command.'] : ['Provider query failed through a bounded command.'];
|
|
102
|
+
diagnostics.push(`Command bounds applied: timeoutMs=${timeoutMs}, maxBytes=${maxBytes}.`);
|
|
103
|
+
if (commandResult.truncated === true)
|
|
104
|
+
diagnostics.push('Provider output was truncated at the bounded output cap.');
|
|
105
|
+
return {
|
|
106
|
+
ok: true,
|
|
107
|
+
value: {
|
|
108
|
+
kind: 'code-context-query',
|
|
109
|
+
version: 1,
|
|
110
|
+
workspaceRoot,
|
|
111
|
+
provider,
|
|
112
|
+
mode,
|
|
113
|
+
question: input.question,
|
|
114
|
+
status: ok ? 'answered' : 'error',
|
|
115
|
+
summary: output || `${providerLabel(provider)} returned no output for the requested query.`,
|
|
116
|
+
command: { command, args },
|
|
117
|
+
setupGuidance: [...providerStatus.setupGuidance],
|
|
118
|
+
diagnostics,
|
|
119
|
+
safety: { ...codeContextProviderCommandSafety },
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
getSetupPlan(input) {
|
|
124
|
+
const workspace = normalizeWorkspaceRoot(input.workspaceRoot);
|
|
125
|
+
if (!workspace.ok)
|
|
126
|
+
return workspace;
|
|
127
|
+
const workspaceRoot = workspace.value;
|
|
128
|
+
return {
|
|
129
|
+
ok: true,
|
|
130
|
+
value: {
|
|
131
|
+
kind: 'code-context-setup-plan',
|
|
132
|
+
version: 1,
|
|
133
|
+
workspaceRoot,
|
|
134
|
+
recommendedCommands: [
|
|
135
|
+
'codegraph init # optional: create/update CodeGraph index outside VGXNESS',
|
|
136
|
+
'graphify --path . --output graphify-out # optional: create/update Graphify graph outside VGXNESS',
|
|
137
|
+
],
|
|
138
|
+
safety: { ...codeContextSafety },
|
|
139
|
+
summary: '[read-only] Advisory plan only. VGXNESS does not install packages, initialize indexes, register external MCP servers, or write provider config.',
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
withCommandEnv(request) {
|
|
144
|
+
return this.commandEnv === undefined ? request : { ...request, env: this.commandEnv };
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function selectProvider(selection, mode) {
|
|
148
|
+
if (selection !== 'auto')
|
|
149
|
+
return selection;
|
|
150
|
+
return mode === 'architecture' || mode === 'overview' || mode === 'pr-impact' ? 'graphify' : 'codegraph';
|
|
151
|
+
}
|
|
152
|
+
function commandFor(provider) {
|
|
153
|
+
return provider === 'codegraph' ? 'codegraph' : 'graphify';
|
|
154
|
+
}
|
|
155
|
+
function providerLabel(provider) {
|
|
156
|
+
return provider === 'codegraph' ? 'CodeGraph' : 'Graphify';
|
|
157
|
+
}
|
|
158
|
+
function queryArgs(provider, mode, question) {
|
|
159
|
+
return provider === 'codegraph' ? [mode, question] : ['query', '--mode', mode, question];
|
|
160
|
+
}
|
|
161
|
+
function firstNonEmpty(...values) {
|
|
162
|
+
return values.find((value) => value.trim().length > 0)?.trim() ?? '';
|
|
163
|
+
}
|
|
164
|
+
function normalizeWorkspaceRoot(value) {
|
|
165
|
+
if (value.trim().length === 0)
|
|
166
|
+
return { ok: false, error: { code: 'invalid-workspace-root', message: 'workspaceRoot must not be empty.' } };
|
|
167
|
+
const resolved = isAbsolute(value) ? value : resolve(value);
|
|
168
|
+
try {
|
|
169
|
+
const canonical = realpathSync(resolved);
|
|
170
|
+
if (!statSync(canonical).isDirectory()) {
|
|
171
|
+
return { ok: false, error: { code: 'invalid-workspace-root', message: 'workspaceRoot must resolve to an existing directory.' } };
|
|
172
|
+
}
|
|
173
|
+
return { ok: true, value: canonical };
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return { ok: false, error: { code: 'invalid-workspace-root', message: 'workspaceRoot must resolve to an existing directory.' } };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function firstLine(value) {
|
|
180
|
+
return value.split(/\r?\n/).find((line) => line.trim().length > 0)?.trim() ?? '';
|
|
181
|
+
}
|
|
182
|
+
function runBoundedCommand(request) {
|
|
183
|
+
const options = {
|
|
184
|
+
cwd: request.cwd,
|
|
185
|
+
shell: false,
|
|
186
|
+
encoding: 'utf8',
|
|
187
|
+
timeout: request.timeoutMs,
|
|
188
|
+
maxBuffer: request.maxBytes,
|
|
189
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
190
|
+
...(request.env === undefined ? {} : { env: request.env }),
|
|
191
|
+
};
|
|
192
|
+
const executed = spawnSync(request.command, request.args, options);
|
|
193
|
+
const stdout = limitText(executed.stdout ?? '', request.maxBytes);
|
|
194
|
+
const stderr = limitText(executed.stderr ?? '', request.maxBytes);
|
|
195
|
+
const truncated = wasTruncated(executed.stdout ?? '', request.maxBytes) || wasTruncated(executed.stderr ?? '', request.maxBytes) || errorCode(executed.error) === 'ENOBUFS';
|
|
196
|
+
if (executed.error !== undefined) {
|
|
197
|
+
const errorText = [stderr, executed.error.message].filter((value) => value.trim().length > 0).join('\n');
|
|
198
|
+
return { ok: false, stdout, stderr: errorText, exitCode: executed.status, ...(truncated ? { truncated: true } : {}) };
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
ok: executed.status === 0,
|
|
202
|
+
stdout,
|
|
203
|
+
stderr,
|
|
204
|
+
exitCode: executed.status,
|
|
205
|
+
...(truncated ? { truncated: true } : {}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function limitText(value, maxBytes) {
|
|
209
|
+
const buffer = Buffer.from(value, 'utf8');
|
|
210
|
+
if (buffer.byteLength <= maxBytes)
|
|
211
|
+
return value;
|
|
212
|
+
return buffer.subarray(0, maxBytes).toString('utf8');
|
|
213
|
+
}
|
|
214
|
+
function wasTruncated(value, maxBytes) {
|
|
215
|
+
return Buffer.from(value, 'utf8').byteLength > maxBytes;
|
|
216
|
+
}
|
|
217
|
+
function errorCode(error) {
|
|
218
|
+
const code = error?.code;
|
|
219
|
+
return typeof code === 'string' ? code : undefined;
|
|
220
|
+
}
|
|
221
|
+
function boundedTimeoutMs(value) {
|
|
222
|
+
return Math.min(value ?? defaultTimeoutMs, maxTimeoutMs);
|
|
223
|
+
}
|
|
224
|
+
function boundedMaxBytes(value) {
|
|
225
|
+
return Math.min(value ?? defaultMaxBytes, maxMaxBytes);
|
|
226
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const codegraphProviderDefinition = {
|
|
4
|
+
id: 'codegraph',
|
|
5
|
+
command: 'codegraph',
|
|
6
|
+
versionArgs: ['--version'],
|
|
7
|
+
indexRelativePath: join('.codegraph', 'codegraph.db'),
|
|
8
|
+
setupGuidance: [
|
|
9
|
+
'Install CodeGraph explicitly if desired: npm install -g @colbymchenry/codegraph',
|
|
10
|
+
'Initialize only after approval: codegraph init',
|
|
11
|
+
],
|
|
12
|
+
};
|
|
13
|
+
export const graphifyProviderDefinition = {
|
|
14
|
+
id: 'graphify',
|
|
15
|
+
command: 'graphify',
|
|
16
|
+
versionArgs: ['--version'],
|
|
17
|
+
indexRelativePath: join('graphify-out', 'graph.json'),
|
|
18
|
+
reportRelativePath: join('graphify-out', 'GRAPH_REPORT.md'),
|
|
19
|
+
setupGuidance: [
|
|
20
|
+
'Install Graphify explicitly if desired: pipx install graphifyy',
|
|
21
|
+
'Generate graph output only after approval: graphify <workspace>',
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export const codeContextProviderDefinitions = [codegraphProviderDefinition, graphifyProviderDefinition];
|
|
25
|
+
export function providerIndexStatus(workspaceRoot, relativePath) {
|
|
26
|
+
const path = join(workspaceRoot, relativePath);
|
|
27
|
+
return { present: existsSync(path), path, freshness: 'unknown' };
|
|
28
|
+
}
|
|
29
|
+
export function providerReportPath(workspaceRoot, relativePath) {
|
|
30
|
+
if (relativePath === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
const path = join(workspaceRoot, relativePath);
|
|
33
|
+
return existsSync(path) ? path : undefined;
|
|
34
|
+
}
|
|
@@ -2,7 +2,7 @@ import { canonicalBehaviorContractVersion } from '../../behavior/behavior-contra
|
|
|
2
2
|
export const canonicalDefaultAgentName = 'vgxness-manager';
|
|
3
3
|
export const canonicalOpenCodeDefaultModel = 'openai/gpt-5.5';
|
|
4
4
|
export const canonicalOpenCodeManagerReasoningEffort = 'high';
|
|
5
|
-
export const canonicalPromptContractVersion =
|
|
5
|
+
export const canonicalPromptContractVersion = 24;
|
|
6
6
|
export const canonicalSddSubagentNames = [
|
|
7
7
|
'vgxness-sdd-explore',
|
|
8
8
|
'vgxness-sdd-propose',
|
|
@@ -170,6 +170,7 @@ export function createCanonicalOpenCodeSddMcpToolPermissions() {
|
|
|
170
170
|
vgxness_run_resume_gate: 'allow',
|
|
171
171
|
vgxness_provider_status: 'allow',
|
|
172
172
|
vgxness_provider_doctor: 'allow',
|
|
173
|
+
vgxness_code_context_status: 'allow',
|
|
173
174
|
vgxness_governance_report: 'allow',
|
|
174
175
|
};
|
|
175
176
|
}
|
|
@@ -214,7 +215,7 @@ SDD happens in OpenCode conversation + VGXNESS MCP/subagents. No terminal SDD ph
|
|
|
214
215
|
## MCP playbook
|
|
215
216
|
- Start/resume/recover: call \`vgxness_resume_context\` first for generic resume/continue; pass \`explicitChange\` only for an exact user change. Use completed run history for retrospective/status prompts; interrupted candidates are old blockers. \`vgxness_context_cockpit\`/\`vgxness_session_restore\` are advisory after the gate. Do not infer a change from \`context_cockpit.memoryPreviews\`. Close with \`vgxness_session_close\` when session id exists.
|
|
216
217
|
- Bounded resume/start hard stop: for generic "continue"/"sigamos"/"continuemos"/"resume development" without an explicit change, call \`vgxness_resume_context\` before any SDD continuation/status. \`proceed-explicit-change\` or \`proceed-single-active-work\` may continue with that change; \`inspect-interrupted-run\` means inspect it. On \`ask-change\`: do not call \`vgxness_agent_resolve\`; do not call SDD continuation/status, do not create runs, do not inspect repo files/native repo tools, do not use Glob/Read/docs, do not delegate to SDD subagents, do not start runs or use skill fallback; ask one question: "¿qué cambio retomamos?".
|
|
217
|
-
- Project preparation:
|
|
218
|
+
- Project preparation: to start a new project/product/app or idea, clarify goals, users, scope, constraints, stack, repo/location, integrations, data, security, deliverables, milestones, success criteria and propose PRD/requirements/design/tasks/roadmap. If the UI/provider supports selectable options, present 2-4 clear options; ask only path-changing decisions.
|
|
218
219
|
- Proposal clarity: if product/business clarity is missing, run a proposal question round.
|
|
219
220
|
- SDD artifacts: guide with \`vgxness_sdd_next\`/\`vgxness_sdd_cockpit\`; bodies use memory-style API \`vgxness_memory_get\`/\`vgxness_memory_save\`/\`vgxness_memory_update\` + \`kind: "sdd-artifact"\`. Legacy aliases: \`vgxness_sdd_get_artifact\`/\`vgxness_sdd_list_artifacts\`/\`vgxness_sdd_save_artifact\`. Summarize proposal draft then ask accept+continue. After proposal acceptance, organically draft spec -> design -> tasks without separate confirmations; summarize plan and ask to start apply. Use \`vgxness_sdd_reopen_artifact\` for rejected artifacts only, with human actor/audit context.
|
|
220
221
|
- delegated phase subagent outputs: inspect delegated result-envelope completeness before SDD artifact persistence or phase advancement (status, executive_summary, artifacts_examined, skill_resolution, risks, next_recommended); this is prompt guidance only, not runtime parsing/rejection.
|
|
@@ -225,7 +226,7 @@ SDD happens in OpenCode conversation + VGXNESS MCP/subagents. No terminal SDD ph
|
|
|
225
226
|
- Active-work memory uses existing memory APIs only: \`active-work/{change}/summary\` (+others). No secrets or hidden reasoning. Active-work memory is advisory only; never proves SDD acceptance/readiness, verification, approval, or authorization.
|
|
226
227
|
- Agents/skills: Use \`vgxness_skill_payload\` first for contextual skill guidance; preview/context-only, no provider execution or config writes. Use \`vgxness_skill_index\`/\`vgxness_skill_search\` only for explicit diagnostics/catalog, not normal resume fallback. Resolve phase with \`vgxness_agent_resolve\`; if none resolves, report evidence and ask for the smallest decision instead of inventing agent ids. \`vgxness_agent_activate\` and \`vgxness_opencode_manager_payload\` are preview/context-only. \`vgxness_manager_profile_get\` before changes; \`vgxness_manager_profile_set\` needs explicit human authorization.
|
|
227
228
|
- Runs/recovery: \`vgxness_run_start\`/\`vgxness_run_list\`/\`vgxness_run_get\`; checkpoint with \`vgxness_run_checkpoint\`, preflight with \`vgxness_run_preflight\` (include \`explicitRequest\` only for exact human-requested one-off actions), close with \`vgxness_run_finalize\`. Unknown runId: \`vgxness_run_resume_candidates\`. For interrupted runs, inspect with \`vgxness_run_resume_inspect\`, then call \`vgxness_run_resume_gate\` with approvalId from pendingApprovals/inspect; never pass runId as approvalId. Follow safe \`recommendedActions[]\`. Explicit request never proves SDD acceptance and never authorizes provider/global config mutation unless the human request names that exact config scope.
|
|
228
|
-
- Provider diagnostics: \`vgxness_provider_status\`/\`vgxness_provider_doctor\` read-only; report evidence limits; use status for configured/phase/next and doctor for OpenCode MCP/manager health.
|
|
229
|
+
- Provider diagnostics: \`vgxness_provider_status\`/\`vgxness_provider_doctor\` read-only; report evidence limits; use status for configured/phase/next and doctor for OpenCode MCP/manager health. Code context: \`vgxness_code_context_status\` only. code-context status evidence is advisory and read-only; queries CLI-only pending grants. Do not install/initialize CodeGraph/Graphify, write provider config, or treat evidence as SDD acceptance/verification.
|
|
229
230
|
|
|
230
231
|
## Minimum flows
|
|
231
232
|
- Organic SDD: propose -> save draft -> ask accept+continue. Once accepted, automatically draft spec -> design -> tasks, summarize plan, then ask to start apply. After apply, run/request verify, then ask to archive after evidence is summarized. Drafts stay unaccepted until human acceptance; never silently accept.
|
|
@@ -260,6 +261,7 @@ const registryManagerInstructionsV11 = [
|
|
|
260
261
|
'Prefer payloadMode=compact for manager-facing status/context reads, SDD artifact reads/lists, and activation handoffs so the primary context stays clean; request payloadMode=verbose only when full artifact contents, provider payloads, or skill context are actually needed, preferably inside delegated phase subagents. Git/PR hygiene: never implement on main; sync main and create a topic branch/worktree before edits; preserve unrelated work; use conventional commits; link approved issues when repo policy requires them; include verification evidence. Estimate changed lines before PR: <=400 focused changed lines can be one PR; >400 lines or multiple review units should become stacked/chained PRs, or ask the user to choose a single PR with size exception vs stacked plan.',
|
|
261
262
|
'MCP sdd_continue must not execute providers, create runs, mutate artifacts, write provider config/openspec, bypass human acceptance, or treat draft-run as apply-progress.',
|
|
262
263
|
'CLI is an escape hatch for bootstrap, doctor, rollback, recovery, MCP unavailable/setup missing, or explicit user request; do not tell users to run terminal SDD phase commands for normal daily flow. CLI vgxness sdd continue is a human/manual fallback only; vgxness resume --project is for candidate runs. The removed experimental vgxness code runtime is not an SDD fallback.',
|
|
264
|
+
'Code context: use vgxness_code_context_status before relying on repository-intelligence providers. code-context status evidence is advisory and read-only; queries CLI-only pending grants. Do not install/initialize CodeGraph/Graphify, write provider config, or treat output as SDD acceptance/verification.',
|
|
263
265
|
'OpenCode native/provider tools are governance-v1 audit-only/non-hard-blocking; report warnings, never say they are hard-blocked by config.',
|
|
264
266
|
].join(' ');
|
|
265
267
|
const subagentData = {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const codeContextProviderIds = ['codegraph', 'graphify'];
|
|
2
|
+
export const codeContextProviderSelections = ['auto', 'codegraph', 'graphify'];
|
|
3
|
+
export const codeContextModes = ['overview', 'architecture', 'debug', 'impact', 'affected-tests', 'verify', 'pr-impact'];
|
|
4
|
+
export const codeContextSafety = {
|
|
5
|
+
readOnly: true,
|
|
6
|
+
writesFiles: false,
|
|
7
|
+
writesProviderConfig: false,
|
|
8
|
+
installsPackages: false,
|
|
9
|
+
initializesIndexes: false,
|
|
10
|
+
registersExternalMcp: false,
|
|
11
|
+
runsHooks: false,
|
|
12
|
+
executesProviderCommands: false,
|
|
13
|
+
externalProviderSideEffects: 'not-invoked',
|
|
14
|
+
};
|
|
15
|
+
export const codeContextProviderCommandSafety = {
|
|
16
|
+
...codeContextSafety,
|
|
17
|
+
readOnly: false,
|
|
18
|
+
executesProviderCommands: true,
|
|
19
|
+
externalProviderSideEffects: 'unknown',
|
|
20
|
+
};
|
|
@@ -17,7 +17,7 @@ Areas:
|
|
|
17
17
|
setup rollback --backup <path> [--preview|--yes] [--json]
|
|
18
18
|
setup status [--project <name>] [--scope project|personal] [--db <path>] [--json]
|
|
19
19
|
doctor [--db <path>] [--project <name>] [--change <id>] [--timeout-ms <ms>] [--json]
|
|
20
|
-
verification plan --type docs-only|test-only|cli|mcp|sdd-storage|provider-setup|package-release|workflow-runs [--json]
|
|
20
|
+
verification plan --type docs-only|test-only|cli|mcp|sdd-storage|provider-setup|package-release|workflow-runs|code-context [--json]
|
|
21
21
|
verification report save --project <name> --change <id> --file <report.json> [--db <path>] [--json]
|
|
22
22
|
verification report get --project <name> --change <id> [--db <path>] [--json]
|
|
23
23
|
Status answers "where am I?" with the human front-door cockpit.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { CodeContextService } from '../../../application/code-context/code-context-service.js';
|
|
3
|
+
import { codeContextModes, codeContextProviderSelections, codeContextSafety } from '../../../domain/code-context/schema.js';
|
|
4
|
+
import { optionalNumberFlag, optionalStringFlag, requiredFlag } from '../cli-flags.js';
|
|
5
|
+
import { okText, usageFailure } from '../cli-help.js';
|
|
6
|
+
export function runCodeContextCommand(command, parsed, environment) {
|
|
7
|
+
const workspaceRoot = resolveWorkspaceRoot(optionalStringFlag(parsed.flags, 'workspace'), environment.cwd);
|
|
8
|
+
const service = new CodeContextService({ commandEnv: environment.env });
|
|
9
|
+
const timeout = optionalNumberFlag(parsed.flags, 'timeout-ms');
|
|
10
|
+
if (!timeout.ok)
|
|
11
|
+
return usageFailure(timeout.error.message);
|
|
12
|
+
const maxBytes = optionalNumberFlag(parsed.flags, 'max-bytes');
|
|
13
|
+
if (!maxBytes.ok)
|
|
14
|
+
return usageFailure(maxBytes.error.message);
|
|
15
|
+
const common = { workspaceRoot, ...(timeout.value !== undefined ? { timeoutMs: timeout.value } : {}), ...(maxBytes.value !== undefined ? { maxBytes: maxBytes.value } : {}) };
|
|
16
|
+
if (command === 'status') {
|
|
17
|
+
const result = service.getStatus(common);
|
|
18
|
+
if (!result.ok)
|
|
19
|
+
return usageFailure(result.error.message);
|
|
20
|
+
return parsed.flags.json === true ? json(result.value) : okText(`${result.value.summary}\n`);
|
|
21
|
+
}
|
|
22
|
+
if (command === 'query') {
|
|
23
|
+
const question = requiredFlag(parsed.flags, 'question');
|
|
24
|
+
if (!question.ok)
|
|
25
|
+
return usageFailure(question.error.message);
|
|
26
|
+
const provider = optionalStringFlag(parsed.flags, 'provider');
|
|
27
|
+
if (provider !== undefined && !codeContextProviderSelections.includes(provider))
|
|
28
|
+
return usageFailure('--provider must be auto, codegraph, or graphify');
|
|
29
|
+
const mode = optionalStringFlag(parsed.flags, 'mode');
|
|
30
|
+
if (mode !== undefined && !codeContextModes.includes(mode))
|
|
31
|
+
return usageFailure(`--mode must be ${codeContextModes.join(', ')}`);
|
|
32
|
+
const result = service.query({
|
|
33
|
+
...common,
|
|
34
|
+
question: question.value,
|
|
35
|
+
...(provider !== undefined ? { provider: provider } : {}),
|
|
36
|
+
...(mode !== undefined ? { mode: mode } : {}),
|
|
37
|
+
});
|
|
38
|
+
if (!result.ok)
|
|
39
|
+
return usageFailure(result.error.message);
|
|
40
|
+
return parsed.flags.json === true ? json(result.value) : okText(`${result.value.summary}\n`);
|
|
41
|
+
}
|
|
42
|
+
if (command === 'setup') {
|
|
43
|
+
if (parsed.positionals[2] !== 'plan' || parsed.positionals.length !== 3)
|
|
44
|
+
return usageFailure('code-context setup requires the plan subcommand');
|
|
45
|
+
const result = service.getSetupPlan(common);
|
|
46
|
+
if (!result.ok)
|
|
47
|
+
return usageFailure(result.error.message);
|
|
48
|
+
return parsed.flags.json === true ? json(result.value) : okText(`${result.value.summary}\n${result.value.recommendedCommands.join('\n')}\n`);
|
|
49
|
+
}
|
|
50
|
+
const body = {
|
|
51
|
+
kind: 'code-context-setup-plan',
|
|
52
|
+
version: 1,
|
|
53
|
+
workspaceRoot,
|
|
54
|
+
recommendedCommands: ['codegraph init # optional: run manually outside VGXNESS', 'graphify --path . --output graphify-out # optional: run manually outside VGXNESS'],
|
|
55
|
+
safety: { ...codeContextSafety },
|
|
56
|
+
summary: '[read-only] Advisory plan only. VGXNESS does not install packages, initialize indexes, register external MCP servers, or write provider config.',
|
|
57
|
+
};
|
|
58
|
+
return parsed.flags.json === true ? json(body) : okText(`${body.summary}\n${body.recommendedCommands.join('\n')}\n`);
|
|
59
|
+
}
|
|
60
|
+
function resolveWorkspaceRoot(value, cwd) {
|
|
61
|
+
if (value === undefined)
|
|
62
|
+
return cwd;
|
|
63
|
+
return value.startsWith('/') ? value : resolve(cwd, value);
|
|
64
|
+
}
|
|
65
|
+
function json(value) {
|
|
66
|
+
return okText(`${JSON.stringify(value, null, 2)}\n`);
|
|
67
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { runCodeContextCommand } from './code-context-dispatcher.js';
|
|
1
2
|
export { runAgentCommand, runSkillCommand, runSubagentCommand } from './agent-skill-dispatcher.js';
|
|
2
3
|
export { runDefaultInteractiveEntrypoint } from './interactive-entrypoint-dispatcher.js';
|
|
3
4
|
export { runDoctorAliasCommand, runMcpDoctorCommand, runMcpDoctorOpenCodeCommand, runMcpInstallCommand, runMcpSetupCommand } from './mcp-dispatcher.js';
|
|
@@ -5,7 +5,7 @@ import { runBootAgentSeedUpgrade } from '../../agents/boot-upgrade.js';
|
|
|
5
5
|
import { databasePathFor, parseArgs, requiredFlag } from './cli-flags.js';
|
|
6
6
|
import { okText, usageFailure, visibleHelpText } from './cli-help.js';
|
|
7
7
|
import { openCliDatabase, resultFailure } from './cli-helpers.js';
|
|
8
|
-
import { runAgentCommand, runApprovalsCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runHomeTuiCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runProductNextCommand, runProductResumeCommand, runProductStatusCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupReinstallApplyCommand, runSetupRollbackCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
|
|
8
|
+
import { runAgentCommand, runApprovalsCommand, runCodeContextCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runHomeTuiCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runProductNextCommand, runProductResumeCommand, runProductStatusCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupReinstallApplyCommand, runSetupRollbackCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
|
|
9
9
|
import { canRunInteractiveTui } from './tui/terminal-capabilities.js';
|
|
10
10
|
const _promptBuffers = new WeakMap();
|
|
11
11
|
const require = createRequire(import.meta.url);
|
|
@@ -35,6 +35,8 @@ export function dispatchCli(argv, environment) {
|
|
|
35
35
|
return usageFailure(commandValidation.message);
|
|
36
36
|
if (area === 'setup')
|
|
37
37
|
return runSetupLifecycleCommand(parsed, environment);
|
|
38
|
+
if (area === 'code-context')
|
|
39
|
+
return runCodeContextCommand(command, parsed, environment);
|
|
38
40
|
if (area === 'verification' && command === 'plan')
|
|
39
41
|
return runVerificationPlanCommand(command, parsed);
|
|
40
42
|
if (isWorkflowId(area) && command === 'preview')
|
|
@@ -235,6 +237,9 @@ function validateCommand(area, command) {
|
|
|
235
237
|
if (area === 'opencode') {
|
|
236
238
|
return command === 'preview' ? { ok: true } : { ok: false, message: `Unknown opencode command: ${command}` };
|
|
237
239
|
}
|
|
240
|
+
if (area === 'code-context') {
|
|
241
|
+
return command === 'status' || command === 'query' || command === 'setup' ? { ok: true } : { ok: false, message: `Unknown code-context command: ${command}` };
|
|
242
|
+
}
|
|
238
243
|
if (area === 'setup') {
|
|
239
244
|
return command === 'status' || command === 'plan' || command === 'apply' || command === 'reinstall' || command === 'backup' || command === 'rollback'
|
|
240
245
|
? { ok: true }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { errorEnvelope, successEnvelope } from '../../schema.js';
|
|
2
|
+
export function codeContextStatusEnvelope(input, services) {
|
|
3
|
+
if (services.codeContext === undefined)
|
|
4
|
+
return errorEnvelope('validation_failed', 'Code-context service is not available', 'vgxness_code_context_status');
|
|
5
|
+
const result = services.codeContext.getStatus(input);
|
|
6
|
+
return result.ok ? successEnvelope('vgxness_code_context_status', result.value) : errorEnvelope('validation_failed', result.error.message, 'vgxness_code_context_status');
|
|
7
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OpenCodeHandoffPreviewService } from '../../adapters/opencode/install/opencode-handoff-preview.js';
|
|
2
2
|
import { AgentActivationService } from '../../agents/agent-activation-service.js';
|
|
3
|
+
import { CodeContextService } from '../../application/code-context/code-context-service.js';
|
|
3
4
|
import { AgentRegistryService } from '../../agents/agent-registry-service.js';
|
|
4
5
|
import { ManagerProfileOverlayService } from '../../agents/manager-profile-overlay-service.js';
|
|
5
6
|
import { ManagerProfileOverlayRepository } from '../../agents/repositories/manager-profile-overlays.js';
|
|
@@ -18,6 +19,7 @@ import { SkillRegistryService } from '../../skills/skill-registry-service.js';
|
|
|
18
19
|
import { SkillStatusService } from '../../skills/skill-status-service.js';
|
|
19
20
|
import { VerificationPlanService } from '../../verification/index.js';
|
|
20
21
|
import { agentActivateEnvelope, agentResolveEnvelope, managerProfileGetEnvelope, managerProfileSetEnvelope, opencodeHandoffPreviewEnvelope, opencodeManagerPayloadEnvelope, } from './control-plane/handlers/agents.js';
|
|
22
|
+
import { codeContextStatusEnvelope } from './control-plane/handlers/code-context.js';
|
|
21
23
|
import { contextCockpitEnvelope, resumeContextEnvelope } from './control-plane/handlers/context.js';
|
|
22
24
|
import { memoryGetEnvelope, memorySaveEnvelope, memorySearchEnvelope, memoryUpdateEnvelope } from './control-plane/handlers/memory.js';
|
|
23
25
|
import { providerChangePlanEnvelope, providerDoctorEnvelope, providerStatusEnvelope } from './control-plane/handlers/providers.js';
|
|
@@ -75,6 +77,8 @@ export function callVgxTool(call, services) {
|
|
|
75
77
|
return sessionRestoreEnvelope(validated.input, services);
|
|
76
78
|
case 'vgxness_context_cockpit':
|
|
77
79
|
return contextCockpitEnvelope(validated.input, services);
|
|
80
|
+
case 'vgxness_code_context_status':
|
|
81
|
+
return codeContextStatusEnvelope(validated.input, services);
|
|
78
82
|
case 'vgxness_resume_context':
|
|
79
83
|
return resumeContextEnvelope(validated.input, services);
|
|
80
84
|
case 'vgxness_agent_resolve':
|
|
@@ -218,6 +222,7 @@ function createServices(database) {
|
|
|
218
222
|
opencodeHandoffPreview: new OpenCodeHandoffPreviewService({ managerPayload: opencodeManagerPayload, sdd, providerStatus }),
|
|
219
223
|
activation: new AgentActivationService({ agents, managerProfiles, runs, opencodeManagerPayload }),
|
|
220
224
|
runs,
|
|
225
|
+
codeContext: new CodeContextService(),
|
|
221
226
|
providerStatus,
|
|
222
227
|
providerDoctor,
|
|
223
228
|
providerChangePlan: new ProviderChangePlanService({ providerStatus, providerDoctor }),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { AGENTS_MCP_TOOL_INPUT_SCHEMAS, CONTEXT_MCP_TOOL_INPUT_SCHEMAS, GOVERNANCE_MCP_TOOL_INPUT_SCHEMAS, MEMORY_MCP_TOOL_INPUT_SCHEMAS, PROVIDERS_MCP_TOOL_INPUT_SCHEMAS, RUNS_MCP_TOOL_INPUT_SCHEMAS, SDD_MCP_TOOL_INPUT_SCHEMAS, SESSIONS_MCP_TOOL_INPUT_SCHEMAS, SKILLS_MCP_TOOL_INPUT_SCHEMAS, VERIFICATION_MCP_TOOL_INPUT_SCHEMAS, } from './schemas/inputs/index.js';
|
|
2
|
+
import { AGENTS_MCP_TOOL_INPUT_SCHEMAS, CONTEXT_MCP_TOOL_INPUT_SCHEMAS, CODE_CONTEXT_MCP_TOOL_INPUT_SCHEMAS, GOVERNANCE_MCP_TOOL_INPUT_SCHEMAS, MEMORY_MCP_TOOL_INPUT_SCHEMAS, PROVIDERS_MCP_TOOL_INPUT_SCHEMAS, RUNS_MCP_TOOL_INPUT_SCHEMAS, SDD_MCP_TOOL_INPUT_SCHEMAS, SESSIONS_MCP_TOOL_INPUT_SCHEMAS, SKILLS_MCP_TOOL_INPUT_SCHEMAS, VERIFICATION_MCP_TOOL_INPUT_SCHEMAS, } from './schemas/inputs/index.js';
|
|
3
3
|
import { buildProviderMcpToolOutputSchemas, buildSddMcpToolOutputSchemas } from './schemas/outputs/index.js';
|
|
4
4
|
export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
|
|
5
5
|
'vgxness_sdd_status',
|
|
@@ -23,6 +23,7 @@ export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
|
|
|
23
23
|
'vgxness_session_close',
|
|
24
24
|
'vgxness_session_restore',
|
|
25
25
|
'vgxness_context_cockpit',
|
|
26
|
+
'vgxness_code_context_status',
|
|
26
27
|
'vgxness_resume_context',
|
|
27
28
|
'vgxness_agent_resolve',
|
|
28
29
|
'vgxness_agent_activate',
|
|
@@ -86,6 +87,7 @@ export const EXPOSED_VGX_MCP_TOOL_NAMES = [
|
|
|
86
87
|
'session_close',
|
|
87
88
|
'session_restore',
|
|
88
89
|
'context_cockpit',
|
|
90
|
+
'code_context_status',
|
|
89
91
|
'resume_context',
|
|
90
92
|
'agent_resolve',
|
|
91
93
|
'agent_activate',
|
|
@@ -147,6 +149,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
147
149
|
...MEMORY_MCP_TOOL_INPUT_SCHEMAS,
|
|
148
150
|
...SESSIONS_MCP_TOOL_INPUT_SCHEMAS,
|
|
149
151
|
...CONTEXT_MCP_TOOL_INPUT_SCHEMAS,
|
|
152
|
+
...CODE_CONTEXT_MCP_TOOL_INPUT_SCHEMAS,
|
|
150
153
|
...AGENTS_MCP_TOOL_INPUT_SCHEMAS,
|
|
151
154
|
...SKILLS_MCP_TOOL_INPUT_SCHEMAS,
|
|
152
155
|
...RUNS_MCP_TOOL_INPUT_SCHEMAS,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const CODE_CONTEXT_MCP_TOOL_INPUT_SCHEMAS = {
|
|
3
|
+
vgxness_code_context_status: z
|
|
4
|
+
.object({
|
|
5
|
+
workspaceRoot: z.string().min(1),
|
|
6
|
+
timeoutMs: z.number().int().positive().optional(),
|
|
7
|
+
maxBytes: z.number().int().positive().optional(),
|
|
8
|
+
})
|
|
9
|
+
.passthrough(),
|
|
10
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { AGENTS_MCP_TOOL_INPUT_SCHEMAS } from './agents.js';
|
|
2
2
|
export { CONTEXT_MCP_TOOL_INPUT_SCHEMAS } from './context.js';
|
|
3
|
+
export { CODE_CONTEXT_MCP_TOOL_INPUT_SCHEMAS } from './code-context.js';
|
|
3
4
|
export { GOVERNANCE_MCP_TOOL_INPUT_SCHEMAS } from './governance.js';
|
|
4
5
|
export { MEMORY_MCP_TOOL_INPUT_SCHEMAS } from './memory.js';
|
|
5
6
|
export { PROVIDERS_MCP_TOOL_INPUT_SCHEMAS } from './providers.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { inputRecord, readNonEmptyString, validationFailure } from './common.js';
|
|
2
|
+
export function validateCodeContextStatusInput(input, tool) {
|
|
3
|
+
const record = inputRecord(input, tool, ['workspaceRoot', 'timeoutMs', 'maxBytes']);
|
|
4
|
+
if (!record.ok)
|
|
5
|
+
return record;
|
|
6
|
+
const workspaceRoot = readNonEmptyString(record.value, 'workspaceRoot', tool);
|
|
7
|
+
if (!workspaceRoot.ok)
|
|
8
|
+
return workspaceRoot;
|
|
9
|
+
const result = { workspaceRoot: workspaceRoot.value };
|
|
10
|
+
const numeric = copyOptionalPositiveIntegers(result, record.value, tool, ['timeoutMs', 'maxBytes']);
|
|
11
|
+
return numeric.ok ? { ok: true, value: result } : numeric;
|
|
12
|
+
}
|
|
13
|
+
function copyOptionalPositiveIntegers(target, record, tool, fields) {
|
|
14
|
+
for (const field of fields) {
|
|
15
|
+
if (record[field] === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
if (typeof record[field] !== 'number' || !Number.isSafeInteger(record[field]) || record[field] <= 0)
|
|
18
|
+
return validationFailure(`${field} must be a positive safe integer`, tool);
|
|
19
|
+
target[field] = record[field];
|
|
20
|
+
}
|
|
21
|
+
return { ok: true, value: undefined };
|
|
22
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isVgxMcpToolName } from './schema.js';
|
|
2
2
|
import { validateAgentActivateInput, validateAgentResolveInput, validateManagerProfileGetInput, validateManagerProfileSetInput, validateOpenCodeHandoffPreviewInput, validateOpenCodeManagerPayloadInput, } from './validation/agents.js';
|
|
3
|
+
import { validateCodeContextStatusInput } from './validation/code-context.js';
|
|
3
4
|
import { asRecord, readString, toValidationResultFailure, validationFailure, validationSuccess } from './validation/common.js';
|
|
4
5
|
import { validateGovernanceReportInput } from './validation/governance.js';
|
|
5
6
|
import { validateMemoryGetInput, validateMemorySaveInput, validateMemorySearchInput, validateMemoryUpdateInput } from './validation/memory.js';
|
|
@@ -62,6 +63,8 @@ export function validateVgxMcpToolCall(call) {
|
|
|
62
63
|
return validationSuccess(tool.value, validateSessionRestoreInput(input, tool.value));
|
|
63
64
|
case 'vgxness_context_cockpit':
|
|
64
65
|
return validationSuccess(tool.value, validateContextCockpitInput(input, tool.value));
|
|
66
|
+
case 'vgxness_code_context_status':
|
|
67
|
+
return validationSuccess(tool.value, validateCodeContextStatusInput(input, tool.value));
|
|
65
68
|
case 'vgxness_resume_context':
|
|
66
69
|
return validationSuccess(tool.value, validateResumeContextInput(input, tool.value));
|
|
67
70
|
case 'vgxness_agent_resolve':
|
|
@@ -49,6 +49,20 @@ const templates = {
|
|
|
49
49
|
recommendations: [nodeVersionRecommendation(), typecheckRecommendation(), manualRecommendation('manual-workflow-tests', 'Run workflow/run tests manually', 'Copy focused node --import tsx --test commands for touched workflow or run test files.')],
|
|
50
50
|
manualChecks: [manualCheck('review-allowlist-boundary', 'Review command allowlist boundary', 'Confirm no arbitrary shell, argv, or package-script execution contract was added.')],
|
|
51
51
|
},
|
|
52
|
+
'code-context': {
|
|
53
|
+
rationale: [
|
|
54
|
+
'Code-context changes span CLI, MCP, provider selection, and bounded repository-intelligence probes.',
|
|
55
|
+
'CodeGraph and Graphify evidence must remain read-only advisory context; verification must not install packages, initialize indexes, or write provider config.',
|
|
56
|
+
],
|
|
57
|
+
recommendations: [
|
|
58
|
+
typecheckRecommendation(),
|
|
59
|
+
manualRecommendation('manual-code-context-tests', 'Run focused code-context tests manually', 'Copy focused node --import tsx --test commands for code-context service, MCP, CLI, docs, and prompt tests after selecting touched files.'),
|
|
60
|
+
],
|
|
61
|
+
manualChecks: [
|
|
62
|
+
manualCheck('review-code-context-read-only-boundary', 'Review code-context read-only boundary', 'Confirm CodeGraph and Graphify paths only report status/query evidence and do not install packages, initialize indexes, write provider config, or infer SDD acceptance.'),
|
|
63
|
+
manualCheck('review-code-context-provider-selection', 'Review provider selection guidance', 'Confirm source/call-path/blast-radius modes prefer CodeGraph and architecture/docs/corpus modes prefer Graphify while unsupported/missing providers degrade gracefully.'),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
52
66
|
};
|
|
53
67
|
export class VerificationPlanService {
|
|
54
68
|
getPlan(changeType) {
|
package/docs/cli.md
CHANGED
|
@@ -262,6 +262,19 @@ Provider support for setup is:
|
|
|
262
262
|
|
|
263
263
|
Setup CLI surfaces do **not** silently write OpenCode or other provider config, do **not** call provider executables, and do **not** approve/reject preflights. They print diagnostics, recovery hints, and manual fallback commands; daily SDD work should continue in OpenCode.
|
|
264
264
|
|
|
265
|
+
|
|
266
|
+
## Code context CLI
|
|
267
|
+
|
|
268
|
+
Use `code-context status` and `code-context query` when you need optional repository-intelligence evidence from CodeGraph or Graphify without making those tools part of setup.
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
bun run cli:bun -- code-context status --workspace . --json
|
|
272
|
+
bun run cli:bun -- code-context query --workspace . --mode impact --question "What calls this service?" --json
|
|
273
|
+
bun run cli:bun -- code-context setup plan --workspace .
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
`code-context setup plan` is guidance only. The code-context CLI never installs packages, does not initialize indexes, does not write provider config, does not register external MCP servers, and does not infer SDD acceptance. `code-context query` is an explicit CLI command that runs the selected provider binary under bounded timeout/output caps; provider side effects are treated as unknown and the query tool is not exposed over MCP. CodeGraph is preferred for impact/debug/affected-tests modes; Graphify is preferred for architecture/overview/PR-impact modes. Missing providers degrade to diagnostics instead of auto-installing anything.
|
|
277
|
+
|
|
265
278
|
## Natural-language orchestrator preview
|
|
266
279
|
|
|
267
280
|
Use `orchestrator preview` when you want `vgxness` to classify a request before deciding whether to answer directly, plan manually, diagnose, or enter SDD:
|
package/docs/mcp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP tools
|
|
2
2
|
|
|
3
|
-
VGXNESS exposes
|
|
3
|
+
VGXNESS exposes 43 typed MCP tools over stdio through `vgxness mcp start`. The canonical list is the `SUPPORTED_VGX_MCP_TOOL_NAMES` array in `src/mcp/schema.ts` — treat that as the source of truth. The list below mirrors it; if a tool appears here that is not in the array, or vice versa, the array wins.
|
|
4
4
|
|
|
5
5
|
Tools are exposed under the `vgxness_*` prefix. Some MCP hosts strip the prefix and accept the short form (`sdd_status`, `memory_save`, etc.). The schema accepts both.
|
|
6
6
|
|
|
@@ -107,11 +107,19 @@ Run `status` accepts the full 8-state vocabulary: `created`, `planned`, `running
|
|
|
107
107
|
| `vgxness_provider_doctor` | Run provider health checks with structured JSON output. | same as `status` | |
|
|
108
108
|
| `vgxness_provider_change_plan` | Compose a read-only provider config change plan. | `ProviderChangePlanInput` shape (`provider`: `opencode`/`claude`/`antigravity`/`custom`; `changeType`: `opencode-mcp-install`/`setup`/`install`/`config-preparation`; `workspaceRoot`; `payloadMode`) | Does not write provider config. See [Providers](./providers.md). |
|
|
109
109
|
|
|
110
|
+
## Code context (1)
|
|
111
|
+
|
|
112
|
+
| Tool | Purpose | Required inputs | Notes |
|
|
113
|
+
|---|---|---|---|
|
|
114
|
+
| `vgxness_code_context_status` | Report optional CodeGraph and Graphify provider availability/index state. | `workspaceRoot`; optional `timeoutMs`, `maxBytes` | Read-only status only; does not install packages, initialize indexes, write provider config, run provider query commands, or infer SDD acceptance. |
|
|
115
|
+
|
|
116
|
+
Code-context output is advisory evidence only. It can guide SDD, debugging, planning, verification, PR evidence, onboarding, and memory summaries, but it does not prove implementation correctness, artifact acceptance, or verification completion. The MCP surface exposes status only and does not install packages, initialize indexes, write provider config, run provider query commands, mutate files, or register external MCP servers. Provider-backed code-context queries intentionally stay CLI-only for now because they execute external provider binaries on the host; exposing them through MCP requires a future task-scoped grant/sandbox boundary.
|
|
117
|
+
|
|
110
118
|
## Verification (1)
|
|
111
119
|
|
|
112
120
|
| Tool | Purpose | Required inputs |
|
|
113
121
|
|---|---|---|
|
|
114
|
-
| `vgxness_verification_plan` | Recommend a verification plan for a change type. | `changeType` (`docs-only`/`test-only`/`cli`/`mcp`/`sdd-storage`/`provider-setup`/`package-release`/`workflow-runs`) |
|
|
122
|
+
| `vgxness_verification_plan` | Recommend a verification plan for a change type. | `changeType` (`docs-only`/`test-only`/`cli`/`mcp`/`sdd-storage`/`provider-setup`/`package-release`/`workflow-runs`/`code-context`) |
|
|
115
123
|
|
|
116
124
|
## Usage patterns
|
|
117
125
|
|