vgxness 1.5.2 → 1.6.0
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/agents/canonical-agent-projection.js +18 -0
- package/dist/agents/renderers/claude-renderer.js +3 -3
- package/dist/cli/cli-flags.js +1 -1
- package/dist/cli/cli-help.js +7 -7
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +2 -2
- package/dist/cli/commands/mcp-dispatcher.js +11 -1
- package/dist/cli/commands/setup-dispatcher.js +9 -0
- package/dist/cli/tui/main-menu/main-menu-read-model.js +41 -44
- package/dist/cli/tui/main-menu/main-menu-render-shape.js +15 -15
- package/dist/cli/tui/opentui/main-menu/screen.js +39 -41
- package/dist/cli/tui/opentui/main-menu/smoke.js +1 -1
- package/dist/cli/tui/opentui/main-menu/view.js +1 -1
- package/dist/cli/tui/setup/setup-tui-read-model.js +15 -12
- package/dist/mcp/claude-code-agent-config.js +23 -7
- package/dist/mcp/claude-code-cli.js +71 -0
- package/dist/mcp/claude-code-config.js +1 -1
- package/dist/mcp/claude-code-project-memory.js +127 -0
- package/dist/mcp/claude-code-scope.js +18 -0
- package/dist/mcp/client-install-claude-code-contract.js +40 -12
- package/dist/mcp/client-install-claude-code.js +61 -10
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/provider-change-plan.js +56 -4
- package/dist/mcp/provider-doctor.js +55 -5
- package/dist/mcp/provider-health-types.js +4 -0
- package/dist/mcp/provider-status.js +84 -8
- package/dist/mcp/schema.js +4 -3
- package/dist/setup/providers/claude-setup-adapter.js +9 -7
- package/dist/setup/setup-plan.js +60 -1
- package/docs/architecture.md +2 -2
- package/docs/cli.md +37 -2
- package/docs/glossary.md +2 -2
- package/docs/prd.md +2 -2
- package/docs/providers.md +33 -6
- package/docs/roadmap.md +1 -1
- package/package.json +1 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
2
|
import { inspectClaudeCodeAgents } from './claude-code-agent-config.js';
|
|
3
3
|
import { claudeAdvisoryPaths, inspectClaudeCodeMcpConfig } from './claude-code-config.js';
|
|
4
|
+
import { inspectClaudeProjectMemory } from './claude-code-project-memory.js';
|
|
5
|
+
import { resolveClaudeCodeScope } from './claude-code-scope.js';
|
|
4
6
|
import { vgxnessOpenCodeDefaultAgent, vgxnessOpenCodeSddSubagents } from './opencode-default-agent-config.js';
|
|
5
7
|
import { buildCanonicalAgentManifestDiagnostic } from './provider-canonical-agent-manifest.js';
|
|
6
|
-
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, providerHealthFailure, REQUIRED_PROVIDER_NATIVE_MCP_TOOLS, rollupProviderDoctor, } from './provider-health-types.js';
|
|
8
|
+
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, providerHealthFailure, isUserGlobalScope, REQUIRED_PROVIDER_NATIVE_MCP_TOOLS, rollupProviderDoctor, } from './provider-health-types.js';
|
|
7
9
|
import { inspectOpenCodeConfigPaths } from './provider-status.js';
|
|
8
10
|
export class ProviderDoctorService {
|
|
9
11
|
deps;
|
|
@@ -83,24 +85,42 @@ export class ProviderDoctorService {
|
|
|
83
85
|
};
|
|
84
86
|
}
|
|
85
87
|
getClaudeDoctor(normalized) {
|
|
88
|
+
const resolvedScope = resolveClaudeCodeScope(normalized.scope);
|
|
89
|
+
if (!resolvedScope.ok)
|
|
90
|
+
return resolvedScope;
|
|
91
|
+
if (isUserGlobalScope(normalized.scope) || resolvedScope.value.canonical === 'local')
|
|
92
|
+
return this.getClaudeUserGlobalDoctor(normalized, resolvedScope.value.canonical, resolvedScope.value.warnings);
|
|
86
93
|
const mcp = inspectClaudeCodeMcpConfig(normalized.workspaceRoot);
|
|
87
94
|
const agents = inspectClaudeCodeAgents(normalized.workspaceRoot);
|
|
95
|
+
const projectMemory = inspectClaudeProjectMemory(normalized.workspaceRoot);
|
|
88
96
|
const advisoryPaths = claudeAdvisoryPaths(normalized.workspaceRoot);
|
|
89
|
-
const checkedPathList = [mcp.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), ...advisoryPaths];
|
|
97
|
+
const checkedPathList = [mcp.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), projectMemory.path, ...advisoryPaths];
|
|
90
98
|
const before = snapshotPaths(checkedPathList, normalized.workspaceRoot);
|
|
91
99
|
const missingAgents = agents.agents.filter((agent) => agent.status === 'missing');
|
|
92
|
-
const
|
|
100
|
+
const blockingAgents = agents.agents.filter((agent) => agent.status === 'conflicting' || agent.status === 'invalid');
|
|
101
|
+
const badFrontmatter = agents.agents.filter((agent) => agent.exists && agent.frontmatter === 'invalid');
|
|
93
102
|
const badMarkers = agents.agents.filter((agent) => agent.exists && !agent.generatedMarker);
|
|
94
103
|
const memoryFiles = advisoryPaths.filter((path) => existsSync(path));
|
|
95
104
|
const checks = [
|
|
96
105
|
{ id: 'workspace-root', status: existsSync(normalized.workspaceRoot) ? 'pass' : 'fail', detail: `Workspace root ${existsSync(normalized.workspaceRoot) ? 'exists' : 'does not exist'}: ${normalized.workspaceRoot}` },
|
|
97
|
-
{ id: 'provider-supported', status: 'pass', detail: 'Claude provider adapter selected for project
|
|
106
|
+
{ id: 'provider-supported', status: 'pass', detail: 'Claude provider adapter selected for CLI MCP registration diagnostics, project .mcp.json compatibility, and Claude agents support.' },
|
|
107
|
+
{ id: 'claude-scope', status: 'pass', detail: 'Claude scope project resolved to canonical project.' },
|
|
108
|
+
{ id: 'claude-cli-presence', status: 'warn', detail: 'Read-only doctor does not execute `claude --version`; CLI availability is diagnosed during explicit apply/preflight only.' },
|
|
98
109
|
{ id: 'claude-project-mcp-readable', status: mcp.status === 'invalid' ? 'fail' : mcp.status === 'missing' ? 'not-configured' : 'pass', detail: mcp.message, ...(mcp.status === 'invalid' ? { remediation: 'Fix malformed .mcp.json before installing VGXNESS Claude support.' } : {}) },
|
|
99
110
|
{ id: 'claude-vgxness-mcp-entry', status: mcp.status === 'configured' ? 'pass' : mcp.status === 'conflicting' ? 'fail' : 'not-configured', detail: mcp.message, ...(mcp.status === 'conflicting' ? { remediation: 'Manually reconcile mcpServers.vgxness before applying VGXNESS Claude support.' } : {}) },
|
|
100
111
|
{ id: 'claude-agents-directory', status: agents.directoryExists ? 'pass' : 'not-configured', detail: agents.directoryExists ? 'Claude project agents directory exists.' : 'Claude project agents directory is missing; confirmed apply may create it.' },
|
|
101
|
-
{
|
|
112
|
+
{
|
|
113
|
+
id: 'claude-vgxness-agents',
|
|
114
|
+
status: blockingAgents.length > 0 ? 'fail' : missingAgents.length > 0 ? 'not-configured' : 'pass',
|
|
115
|
+
detail: blockingAgents.length > 0
|
|
116
|
+
? `Conflicting or invalid VGXNESS Claude agents: ${blockingAgents.map((agent) => agent.agentName).join(', ')}.`
|
|
117
|
+
: missingAgents.length > 0
|
|
118
|
+
? `Missing VGXNESS Claude agents: ${missingAgents.map((agent) => agent.agentName).join(', ')}.`
|
|
119
|
+
: 'Expected VGXNESS Claude agent targets were inspected.',
|
|
120
|
+
},
|
|
102
121
|
{ id: 'claude-agent-frontmatter', status: badFrontmatter.length === 0 ? 'pass' : 'fail', detail: badFrontmatter.length === 0 ? 'Expected Claude agent frontmatter is valid.' : `Invalid or missing frontmatter for: ${badFrontmatter.map((agent) => agent.agentName).join(', ')}.` },
|
|
103
122
|
{ id: 'claude-agent-generated-metadata', status: badMarkers.length === 0 ? 'pass' : 'fail', detail: badMarkers.length === 0 ? 'Existing VGXNESS Claude agent files include generated metadata markers.' : `Missing VGXNESS generated marker for: ${badMarkers.map((agent) => agent.agentName).join(', ')}.` },
|
|
123
|
+
claudeProjectMemoryCheck(projectMemory),
|
|
104
124
|
{ id: 'claude-project-memory-advisory', status: memoryFiles.length === 0 ? 'pass' : 'warn', detail: memoryFiles.length === 0 ? 'No Claude project memory/settings advisory files were found.' : `Advisory only; VGXNESS will not modify: ${memoryFiles.join(', ')}.` },
|
|
105
125
|
readonlySafetyCheck(before, snapshotPaths(checkedPathList, normalized.workspaceRoot)),
|
|
106
126
|
];
|
|
@@ -111,6 +131,23 @@ export class ProviderDoctorService {
|
|
|
111
131
|
const recommendations = checks.flatMap((check) => (check.remediation === undefined ? [] : [check.remediation]));
|
|
112
132
|
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: summarizeDoctor(status, failedChecks.length, recommendations.length), recommendations, checks: compactChecksValue, checkedPaths, bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: checkedPathList }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: PROVIDER_HEALTH_SAFETY } };
|
|
113
133
|
}
|
|
134
|
+
getClaudeUserGlobalDoctor(normalized, canonicalScope = 'user', scopeWarnings = []) {
|
|
135
|
+
const checks = [
|
|
136
|
+
{ id: 'workspace-root', status: existsSync(normalized.workspaceRoot) ? 'pass' : 'fail', detail: `Workspace root ${existsSync(normalized.workspaceRoot) ? 'exists' : 'does not exist'}: ${normalized.workspaceRoot}` },
|
|
137
|
+
{ id: 'provider-supported', status: 'warn', detail: `Claude ${canonicalScope} scope is supported as read-only advisory status/doctor/change-plan. Future install requires explicit confirmation/preflight and Claude CLI; private config mutation is unsupported.` },
|
|
138
|
+
{ id: 'claude-scope', status: scopeWarnings.length === 0 ? 'pass' : 'warn', detail: scopeWarnings.join(' ') || `Claude scope resolved to canonical ${canonicalScope}.` },
|
|
139
|
+
{ id: 'claude-cli-presence', status: 'warn', detail: 'Read-only doctor does not execute `claude --version`; no provider process was launched.' },
|
|
140
|
+
{ id: 'provider-config-readonly-safety', status: 'pass', detail: `No Claude ${canonicalScope} paths were inspected or mutated; no repair/install/write occurred.` },
|
|
141
|
+
];
|
|
142
|
+
const status = rollupProviderDoctor(checks.map((check) => check.status));
|
|
143
|
+
const compactChecksValue = compactChecks(checks, normalized.payloadMode);
|
|
144
|
+
const failedChecks = checks.filter((check) => check.status === 'fail').map((check) => check.id);
|
|
145
|
+
const recommendations = [
|
|
146
|
+
`If you choose to configure Claude ${canonicalScope} scope manually, run Claude Code yourself and use a command like: claude mcp add --scope ${canonicalScope} vgxness -- vgxness mcp start.`,
|
|
147
|
+
'VGXNESS will not read or write private Claude config files during status/doctor/change-plan, repair config, or execute Claude Code from read-only surfaces.',
|
|
148
|
+
];
|
|
149
|
+
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: `Claude ${canonicalScope} doctor is advisory and read-only; no private Claude files were inspected, no config was changed, and Claude Code was not executed.`, recommendations, checks: compactChecksValue, checkedPaths: [], bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: [] }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths: [] }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${canonicalScope}:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES } } };
|
|
150
|
+
}
|
|
114
151
|
}
|
|
115
152
|
function summarizeDoctor(status, failedCount, recommendationCount) {
|
|
116
153
|
if (status === 'healthy')
|
|
@@ -223,6 +260,19 @@ function readonlySafetyCheck(before, after) {
|
|
|
223
260
|
}
|
|
224
261
|
: { id: 'provider-config-readonly-safety', status: 'fail', detail: 'Provider config path existence or mtimes changed during read-only doctor.' };
|
|
225
262
|
}
|
|
263
|
+
function claudeProjectMemoryCheck(state) {
|
|
264
|
+
const status = state.status === 'managed-current' ? 'pass' : state.status === 'managed-stale' ? 'warn' : state.status === 'blocked' ? 'fail' : 'not-configured';
|
|
265
|
+
return {
|
|
266
|
+
id: 'claude-project-memory-managed-block',
|
|
267
|
+
status,
|
|
268
|
+
detail: state.message,
|
|
269
|
+
...(state.status === 'blocked'
|
|
270
|
+
? { remediation: 'Manually reconcile VGXNESS Claude project-memory markers before installing.' }
|
|
271
|
+
: state.status === 'managed-current'
|
|
272
|
+
? {}
|
|
273
|
+
: { remediation: 'Run confirmed Claude project install when ready.' }),
|
|
274
|
+
};
|
|
275
|
+
}
|
|
226
276
|
function snapshotPaths(paths, workspaceRoot) {
|
|
227
277
|
const unique = [...paths, `${workspaceRoot}/.vgx`];
|
|
228
278
|
return Object.fromEntries(unique.map((path) => [path, existsSync(path) ? statSync(path).mtimeMs : false]));
|
|
@@ -11,6 +11,10 @@ export const PROVIDER_HEALTH_SAFETY = {
|
|
|
11
11
|
runsRepair: false,
|
|
12
12
|
executesProvider: false,
|
|
13
13
|
};
|
|
14
|
+
export const CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES = ['status', 'doctor', 'change-plan'];
|
|
15
|
+
export function isUserGlobalScope(scope) {
|
|
16
|
+
return scope === 'personal' || scope === 'user';
|
|
17
|
+
}
|
|
14
18
|
export const REQUIRED_PROVIDER_MCP_TOOLS = ['vgxness_provider_status', 'vgxness_provider_doctor', 'vgxness_provider_change_plan'];
|
|
15
19
|
export const REQUIRED_PROVIDER_NATIVE_MCP_TOOLS = [
|
|
16
20
|
'vgxness_provider_status',
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { inspectClaudeCodeAgents } from './claude-code-agent-config.js';
|
|
4
|
+
import { createClaudeCodeCliRegistrationPreview } from './claude-code-cli.js';
|
|
4
5
|
import { claudeAdvisoryPaths, claudeMcpConfigPathStatus, claudeMcpEntryStatus, inspectClaudeCodeMcpConfig } from './claude-code-config.js';
|
|
6
|
+
import { inspectClaudeProjectMemory } from './claude-code-project-memory.js';
|
|
7
|
+
import { resolveClaudeCodeScope } from './claude-code-scope.js';
|
|
5
8
|
import { resolveOpenCodeMcpInstallTarget } from './client-install-opencode-contract.js';
|
|
6
9
|
import { vgxnessOpenCodeDefaultAgent, vgxnessOpenCodePromptContractVersion, vgxnessOpenCodeSddSubagents } from './opencode-default-agent-config.js';
|
|
7
10
|
import { buildCanonicalAgentManifestDiagnostic } from './provider-canonical-agent-manifest.js';
|
|
8
|
-
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, providerHealthFailure, REQUIRED_PROVIDER_MCP_TOOLS, rollupProviderHealth, } from './provider-health-types.js';
|
|
11
|
+
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, providerHealthFailure, isUserGlobalScope, REQUIRED_PROVIDER_MCP_TOOLS, rollupProviderHealth, } from './provider-health-types.js';
|
|
9
12
|
const projectConfigTargets = ['.opencode/opencode.json', 'opencode.json', '.opencode/opencode.jsonc', 'opencode.jsonc'];
|
|
10
13
|
export class ProviderStatusService {
|
|
11
14
|
deps;
|
|
@@ -87,24 +90,30 @@ export class ProviderStatusService {
|
|
|
87
90
|
return { change, ...(status.ok ? { status: status.value } : {}), ...(next.ok ? { next: next.value } : {}) };
|
|
88
91
|
}
|
|
89
92
|
getClaudeStatus(normalized) {
|
|
93
|
+
const resolvedScope = resolveClaudeCodeScope(normalized.scope);
|
|
94
|
+
if (!resolvedScope.ok)
|
|
95
|
+
return resolvedScope;
|
|
96
|
+
if (isUserGlobalScope(normalized.scope) || resolvedScope.value.canonical === 'local')
|
|
97
|
+
return this.getClaudeUserGlobalStatus(normalized, resolvedScope.value.canonical, resolvedScope.value.warnings);
|
|
90
98
|
const canonicalAgentManifest = (this.deps.canonicalAgentManifestDiagnostic ?? buildCanonicalAgentManifestDiagnostic)();
|
|
91
99
|
const mcpState = inspectClaudeCodeMcpConfig(normalized.workspaceRoot);
|
|
92
100
|
const agents = inspectClaudeCodeAgents(normalized.workspaceRoot);
|
|
93
|
-
const
|
|
101
|
+
const projectMemory = inspectClaudeProjectMemory(normalized.workspaceRoot);
|
|
102
|
+
const paths = [claudeMcpConfigPathStatus(mcpState), claudeProjectMemoryPathStatus(projectMemory)];
|
|
94
103
|
const mcpEntry = claudeMcpEntryStatus(mcpState);
|
|
95
104
|
const agentStatuses = agents.agents.map((agent) => (agent.status === 'managed' ? 'pass' : agent.status === 'missing' ? 'not-configured' : 'fail'));
|
|
96
105
|
const advisory = claudeAdvisoryPaths(normalized.workspaceRoot).filter((path) => existsSync(path));
|
|
97
|
-
const configStatus = claudeConfigHealthStatus([paths
|
|
106
|
+
const configStatus = claudeConfigHealthStatus([...paths.map((path) => path.status), ...agentStatuses]);
|
|
98
107
|
const status = rollupProviderHealth([canonicalAgentManifest.status, configStatus]);
|
|
99
108
|
const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
|
|
100
|
-
const checkedPaths = normalized.payloadMode === 'verbose' ? [mcpState.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), ...claudeAdvisoryPaths(normalized.workspaceRoot)] : [mcpState.path, ...agents.agents.filter((agent) => agent.exists || agent.status !== 'missing').map((agent) => agent.path), ...advisory];
|
|
101
|
-
const tools = requiredToolPresence();
|
|
102
|
-
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, agents, advisory, sdd, mcpRequiredTools: tools };
|
|
103
|
-
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, agentSummary: summarizeClaudeAgents(agents), advisory, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
109
|
+
const checkedPaths = normalized.payloadMode === 'verbose' ? [mcpState.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), projectMemory.path, ...claudeAdvisoryPaths(normalized.workspaceRoot)] : [mcpState.path, projectMemory.path, ...agents.agents.filter((agent) => agent.exists || agent.status !== 'missing').map((agent) => agent.path), ...advisory];
|
|
110
|
+
const tools = [...requiredToolPresence(), { tool: 'claude-cli', present: false, diagnostic: 'Read-only status does not execute `claude --version`; CLI presence is checked during explicit apply/preflight only.' }];
|
|
111
|
+
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, agents, projectMemory, advisory, sdd, mcpRequiredTools: tools };
|
|
112
|
+
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, agentSummary: summarizeClaudeAgents(agents), projectMemory: { status: projectMemory.status, action: projectMemory.action }, advisory, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
104
113
|
const originalBytes = Buffer.byteLength(JSON.stringify(verboseShape), 'utf8');
|
|
105
114
|
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
106
115
|
const issueCount = [canonicalAgentManifest.status, configStatus, ...agentStatuses].filter((item) => item === 'fail' || item === 'not-configured').length;
|
|
107
|
-
const warningCount = advisory.length;
|
|
116
|
+
const warningCount = advisory.length + resolvedScope.value.warnings.length + paths.filter((path) => path.status === 'warn').length;
|
|
108
117
|
return {
|
|
109
118
|
ok: true,
|
|
110
119
|
value: {
|
|
@@ -136,6 +145,61 @@ export class ProviderStatusService {
|
|
|
136
145
|
},
|
|
137
146
|
};
|
|
138
147
|
}
|
|
148
|
+
getClaudeUserGlobalStatus(normalized, canonicalScope = 'user', scopeWarnings = []) {
|
|
149
|
+
const canonicalAgentManifest = (this.deps.canonicalAgentManifestDiagnostic ?? buildCanonicalAgentManifestDiagnostic)();
|
|
150
|
+
const paths = [
|
|
151
|
+
{
|
|
152
|
+
label: `Claude ${canonicalScope} scope`,
|
|
153
|
+
path: `${canonicalScope} Claude configuration (not inspected)`,
|
|
154
|
+
exists: false,
|
|
155
|
+
readable: false,
|
|
156
|
+
parsed: false,
|
|
157
|
+
status: 'warn',
|
|
158
|
+
detail: `Claude ${canonicalScope} scope is advisory only in read-only status: VGXNESS does not read private Claude files, write config, execute Claude Code, or install provider config.`,
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
const mcpEntry = {
|
|
162
|
+
configured: false,
|
|
163
|
+
status: 'warn',
|
|
164
|
+
serverName: 'vgxness',
|
|
165
|
+
detail: `${canonicalScope} Claude MCP status is not inspected by VGXNESS; use this as planning guidance only. Future apply uses Claude CLI argv only: ${createClaudeCodeCliRegistrationPreview(canonicalScope).join(' ')}`,
|
|
166
|
+
};
|
|
167
|
+
const tools = requiredToolPresence();
|
|
168
|
+
const status = rollupProviderHealth([canonicalAgentManifest.status, 'warn']);
|
|
169
|
+
const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
|
|
170
|
+
const verboseShape = { config: { status: 'warn', paths, mcpEntry }, canonicalAgentManifest, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, scopeWarnings, sdd, mcpRequiredTools: tools };
|
|
171
|
+
const compactShape = { config: { status: 'warn', paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
172
|
+
return {
|
|
173
|
+
ok: true,
|
|
174
|
+
value: {
|
|
175
|
+
version: 1,
|
|
176
|
+
kind: 'provider-status',
|
|
177
|
+
project: normalized.project,
|
|
178
|
+
providerAdapter: 'claude',
|
|
179
|
+
scope: normalized.scope,
|
|
180
|
+
workspaceRoot: normalized.workspaceRoot,
|
|
181
|
+
status,
|
|
182
|
+
payloadMode: normalized.payloadMode,
|
|
183
|
+
overallStatus: status,
|
|
184
|
+
inspectedPaths: [],
|
|
185
|
+
issueCount: canonicalAgentManifest.status === 'fail' ? 1 : 0,
|
|
186
|
+
warningCount: 1 + scopeWarnings.length,
|
|
187
|
+
summary: `Claude ${canonicalScope} scope status is read-only/advisory; no private Claude files are inspected or written, and Claude Code is not executed.`,
|
|
188
|
+
nextAction: { kind: 'review', message: 'Review the planning-only guidance; future apply requires explicit confirmation/preflight and uses Claude CLI argv, not private config mutation.' },
|
|
189
|
+
checkedPaths: [],
|
|
190
|
+
canonicalAgentManifest,
|
|
191
|
+
config: { status: 'warn', paths: compactPaths(paths, normalized.payloadMode), mcpEntry: compactMcpEntry(mcpEntry, normalized.payloadMode) },
|
|
192
|
+
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
193
|
+
mcpRequiredTools: tools,
|
|
194
|
+
originalBytes: Buffer.byteLength(JSON.stringify(verboseShape), 'utf8'),
|
|
195
|
+
compactBytes: Buffer.byteLength(JSON.stringify(compactShape), 'utf8'),
|
|
196
|
+
verboseAvailable: normalized.payloadMode === 'compact',
|
|
197
|
+
fullContentRef: `provider-status:claude:user-global:${normalized.workspaceRoot}`,
|
|
198
|
+
generatedAt: 'read-only-snapshot',
|
|
199
|
+
safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES },
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
}
|
|
139
203
|
}
|
|
140
204
|
function summarizeClaudeAgents(agents) {
|
|
141
205
|
return { expected: agents.agents.length, managed: agents.agents.filter((agent) => agent.status === 'managed').length, missing: agents.agents.filter((agent) => agent.status === 'missing').length, conflicting: agents.agents.filter((agent) => agent.status === 'conflicting' || agent.status === 'invalid').length };
|
|
@@ -149,6 +213,18 @@ function claudeConfigHealthStatus(statuses) {
|
|
|
149
213
|
return 'warn';
|
|
150
214
|
return 'pass';
|
|
151
215
|
}
|
|
216
|
+
function claudeProjectMemoryPathStatus(state) {
|
|
217
|
+
const status = state.status === 'managed-current' ? 'pass' : state.status === 'managed-stale' ? 'warn' : state.status === 'blocked' ? 'fail' : 'not-configured';
|
|
218
|
+
return {
|
|
219
|
+
label: 'project CLAUDE.md managed block',
|
|
220
|
+
path: state.path,
|
|
221
|
+
exists: state.exists,
|
|
222
|
+
readable: state.status !== 'blocked' || state.reason !== 'unreadable',
|
|
223
|
+
parsed: state.status === 'managed-current' || state.status === 'managed-stale',
|
|
224
|
+
status,
|
|
225
|
+
detail: state.message,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
152
228
|
function compactPaths(paths, mode) {
|
|
153
229
|
if (mode === 'verbose')
|
|
154
230
|
return paths;
|
package/dist/mcp/schema.js
CHANGED
|
@@ -90,6 +90,7 @@ export function toInternalVgxMcpToolName(toolName) {
|
|
|
90
90
|
return EXPOSED_TO_INTERNAL_TOOL_NAMES[toolName];
|
|
91
91
|
}
|
|
92
92
|
const scopes = ['project', 'personal'];
|
|
93
|
+
const providerScopes = ['project', 'personal', 'local', 'user'];
|
|
93
94
|
const agentModes = ['agent', 'subagent'];
|
|
94
95
|
const memoryTypes = ['architecture', 'decision', 'bugfix', 'pattern', 'config', 'discovery', 'learning', 'preference', 'manual'];
|
|
95
96
|
const activityKinds = ['prompt', 'tool_call', 'artifact', 'summary', 'error'];
|
|
@@ -429,7 +430,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
429
430
|
vgxness_provider_status: z
|
|
430
431
|
.object({
|
|
431
432
|
project: z.string().min(1).optional(),
|
|
432
|
-
scope: z.enum(
|
|
433
|
+
scope: z.enum(providerScopes).optional(),
|
|
433
434
|
providerAdapter: z.enum(['opencode', 'claude']).optional(),
|
|
434
435
|
workspaceRoot: z.string().min(1).optional(),
|
|
435
436
|
change: z.string().min(1).optional(),
|
|
@@ -439,7 +440,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
439
440
|
vgxness_provider_doctor: z
|
|
440
441
|
.object({
|
|
441
442
|
project: z.string().min(1).optional(),
|
|
442
|
-
scope: z.enum(
|
|
443
|
+
scope: z.enum(providerScopes).optional(),
|
|
443
444
|
providerAdapter: z.enum(['opencode', 'claude']).optional(),
|
|
444
445
|
workspaceRoot: z.string().min(1).optional(),
|
|
445
446
|
expectedPromptContractVersion: z.number().int().positive().optional(),
|
|
@@ -449,7 +450,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
449
450
|
vgxness_provider_change_plan: z
|
|
450
451
|
.object({
|
|
451
452
|
project: z.string().min(1).optional(),
|
|
452
|
-
scope: z.enum(
|
|
453
|
+
scope: z.enum(providerScopes).optional(),
|
|
453
454
|
provider: z.enum(providerChangePlanProviders),
|
|
454
455
|
changeType: z.enum(providerChangePlanTypes),
|
|
455
456
|
workspaceRoot: z.string().min(1),
|
|
@@ -3,27 +3,29 @@ import { noWriteActionSafety } from './provider-setup-adapter.js';
|
|
|
3
3
|
export const claudeSetupAdapter = {
|
|
4
4
|
id: 'claude',
|
|
5
5
|
displayName: 'Claude',
|
|
6
|
-
supportLevel: '
|
|
7
|
-
capabilities: ['mcp-preview', 'mcp-install-plan', 'agent-preview', 'doctor', 'manual-guidance'],
|
|
6
|
+
supportLevel: 'supported-secondary',
|
|
7
|
+
capabilities: ['mcp-preview', 'mcp-install-plan', 'cli-mcp-plan', 'agent-preview', 'doctor', 'manual-guidance'],
|
|
8
8
|
targets: [
|
|
9
9
|
{ kind: 'project-config', label: 'Project .mcp.json', path: '.mcp.json', writableBySetup: false },
|
|
10
10
|
{ kind: 'project-config', label: 'Project Claude agents', path: '.claude/agents/*.md', writableBySetup: false },
|
|
11
|
+
{ kind: 'project-config', label: 'Project Claude memory', path: 'CLAUDE.md', writableBySetup: false },
|
|
12
|
+
{ kind: 'user-config', label: 'User Claude agents', path: '~/.claude/agents/*.md', writableBySetup: false },
|
|
11
13
|
],
|
|
12
14
|
getStatus(context) {
|
|
13
15
|
return {
|
|
14
16
|
providerId: 'claude',
|
|
15
|
-
status: '
|
|
16
|
-
summary: 'Claude
|
|
17
|
+
status: 'supported-secondary',
|
|
18
|
+
summary: 'Claude is supported as a secondary, non-default provider for CLI MCP registration planning/apply, project .mcp.json compatibility, and project/user agent planning; explicit guarded apply is required for writes or CLI execution.',
|
|
17
19
|
evidence: context.databasePath !== undefined
|
|
18
20
|
? ['Claude MCP preview can be generated from the selected database path.']
|
|
19
21
|
: ['Claude MCP preview uses a placeholder until a database path is selected.'],
|
|
20
|
-
guidance: ['
|
|
22
|
+
guidance: ['Use `vgxness mcp install claude --scope local|project|user --yes --run-id <id>` for explicit guarded apply. VGXNESS may write project-root CLAUDE.md only through confirmed, preflighted Claude project install; it never manually writes ~/.claude.json or .claude/CLAUDE.md. Read-only setup/status surfaces do not execute Claude Code.'],
|
|
21
23
|
actions: [
|
|
22
24
|
{
|
|
23
25
|
id: 'claude-manual-guidance',
|
|
24
|
-
label: 'Review Claude
|
|
26
|
+
label: 'Review guarded Claude install guidance',
|
|
25
27
|
kind: 'manual-guidance',
|
|
26
|
-
description: '
|
|
28
|
+
description: 'Supported secondary guidance only in setup status; writes are available only through the guarded mcp install claude flow with run preflight metadata.',
|
|
27
29
|
safety: noWriteActionSafety,
|
|
28
30
|
},
|
|
29
31
|
],
|
package/dist/setup/setup-plan.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { join, resolve } from 'node:path';
|
|
2
|
+
import { planClaudeCodeMcpInstall } from '../mcp/client-install-claude-code-contract.js';
|
|
2
3
|
import { planOpenCodeMcpInstall } from '../mcp/client-install-opencode-contract.js';
|
|
3
4
|
import { resolveMemoryDatabasePath } from '../memory/storage-paths.js';
|
|
4
5
|
import { vgxnessSetupDefaults } from './setup-defaults.js';
|
|
@@ -45,8 +46,66 @@ export function createSetupPlan(input) {
|
|
|
45
46
|
},
|
|
46
47
|
};
|
|
47
48
|
}
|
|
49
|
+
if (provider === 'claude') {
|
|
50
|
+
const claude = planClaudeCodeMcpInstall({
|
|
51
|
+
cwd: input.workspaceRoot,
|
|
52
|
+
databasePath: database.value.path,
|
|
53
|
+
databasePathSource: database.value.planSource,
|
|
54
|
+
...(input.overwriteVgxness === undefined ? {} : { overwriteVgxness: input.overwriteVgxness }),
|
|
55
|
+
});
|
|
56
|
+
const targetPath = claude.targetPath;
|
|
57
|
+
if (claude.status === 'refused') {
|
|
58
|
+
return {
|
|
59
|
+
ok: true,
|
|
60
|
+
value: {
|
|
61
|
+
...common,
|
|
62
|
+
provider: 'claude',
|
|
63
|
+
db: { mode: database.value.mode, path: database.value.path, source: database.value.source },
|
|
64
|
+
status: 'conflict',
|
|
65
|
+
actions: [],
|
|
66
|
+
conflicts: [
|
|
67
|
+
{
|
|
68
|
+
id: claude.reason,
|
|
69
|
+
severity: 'blocking',
|
|
70
|
+
message: claude.message,
|
|
71
|
+
targetPath,
|
|
72
|
+
recovery: claude.reason === 'malformed_claude_project_memory' || claude.reason === 'conflicting_claude_project_memory' ? 'Manually reconcile the VGXNESS markers in project-root CLAUDE.md, then rerun `vgxness setup plan --provider claude`.' : 'Inspect the Claude project config, resolve the conflict, then rerun `vgxness setup plan --provider claude`.',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
backupsPlanned: [],
|
|
76
|
+
nextCommands: ['vgxness mcp install claude --plan --scope project', 'Resolve the reported Claude project conflict before guarded apply.'],
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
ok: true,
|
|
82
|
+
value: {
|
|
83
|
+
...common,
|
|
84
|
+
provider: 'claude',
|
|
85
|
+
db: { mode: database.value.mode, path: database.value.path, source: database.value.source },
|
|
86
|
+
status: 'ready',
|
|
87
|
+
actions: [
|
|
88
|
+
{
|
|
89
|
+
id: 'claude-guarded-install',
|
|
90
|
+
description: `Review supported secondary Claude plan for CLI MCP registration, .mcp.json compatibility, ${claude.agentNames.length} .claude/agents/*.md file(s), and guarded project-root CLAUDE.md managed block; apply only with vgxness mcp install claude --scope project --yes --run-id <id>.`,
|
|
91
|
+
mutating: false,
|
|
92
|
+
targetPath,
|
|
93
|
+
backupRequired: claude.backupRequired,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
conflicts: [],
|
|
97
|
+
backupsPlanned: claude.targets
|
|
98
|
+
.filter((target) => target.kind !== 'cli-mcp-registration' && ((target.kind === 'project-memory' && target.backupRequired) || target.action === 'merge' || target.action === 'update-vgxness'))
|
|
99
|
+
.map((target) => ({
|
|
100
|
+
targetPath: target.path,
|
|
101
|
+
reason: target.kind === 'project-memory' ? 'A future guarded Claude apply would create a managed VGXNESS backup before appending or updating the project-root CLAUDE.md managed block.' : 'A future guarded Claude apply would create a managed VGXNESS backup before merging or updating Claude project configuration.',
|
|
102
|
+
})),
|
|
103
|
+
nextCommands: ['vgxness mcp install claude --plan --scope project', 'vgxness mcp install claude --scope project --yes --run-id <id>', 'OpenCode remains the default/primary provider.'],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
48
107
|
if (provider !== 'opencode')
|
|
49
|
-
return { ok: false, error: { code: 'validation_failed', message: 'Provider must be opencode or none for the setup plan.' } };
|
|
108
|
+
return { ok: false, error: { code: 'validation_failed', message: 'Provider must be opencode, claude, or none for the setup plan.' } };
|
|
50
109
|
const opencode = planOpenCodeMcpInstall({
|
|
51
110
|
cwd: input.workspaceRoot,
|
|
52
111
|
databasePath: database.value.path,
|
package/docs/architecture.md
CHANGED
|
@@ -18,7 +18,7 @@ The user-facing shape is deliberately four-surface: **MCP for agents**, **CLI fo
|
|
|
18
18
|
| Core workflow | SDD-first canonical state: explore → proposal → spec → design → tasks → apply-progress → verify → archive. |
|
|
19
19
|
| Interfaces | MCP server for AI tools, CLI for automation/power users, TUI for guided install/status/profile/SDD workflows, and `vgxness code` runtime for bounded workspace work. |
|
|
20
20
|
| Installation UX | Step-based guided setup with doctor checks, dry-run support, and no manual provider JSON editing on the happy path. |
|
|
21
|
-
| Provider strategy | Provider-agnostic domain model with OpenCode as the primary supported provider; Claude Code is
|
|
21
|
+
| Provider strategy | Provider-agnostic domain model with OpenCode as the primary/default supported provider; Claude Code is supported secondary for CLI MCP registration, project `.mcp.json` compatibility, guarded project-root `CLAUDE.md` managed memory, and project/user agent planning. Claude scopes are `local`, `project`, and `user` (`personal`/`global` map to `user`). Read-only status/doctor/change-plan never execute Claude Code or inspect private Claude config, and VGXNESS never manually mutates `~/.claude.json` or `.claude/CLAUDE.md`. Pi/`gentle-pi` compatibility is a future adapter/reference target. The code runtime speaks to any OpenAI-compatible endpoint through `src/code/providers/openai-compatible-provider-adapter.ts`. |
|
|
22
22
|
| Memory | Project memory plus personal/global memory, backed locally. |
|
|
23
23
|
| Agents | Agents/subagents are registered in a neutral schema, then rendered into provider-specific config. |
|
|
24
24
|
| Skills | Skills are first-class, versioned, attachable to agents/workflows/adapters, and improved through reviewable proposals. |
|
|
@@ -439,7 +439,7 @@ vgxness agents render --provider opencode --project vgxness --name apply-agent
|
|
|
439
439
|
Rendering is intentionally read-only: it returns generated content in the CLI response. It does **not** write `.opencode/`, `.claude/`, or any user/global provider config.
|
|
440
440
|
OpenCode agent keys are sanitized deterministically from registry names, and rendering rejects key collisions instead of overwriting generated config.
|
|
441
441
|
|
|
442
|
-
Claude Code
|
|
442
|
+
Claude Code install planning/apply is supported through the guarded MCP install path. Rendering remains read-only; confirmed project compatibility writes are limited to `.mcp.json`, `.claude/agents/*.md`, and the project-root `CLAUDE.md` managed block with run preflight metadata. Local/user MCP registration is represented through Claude CLI argv after confirmation/preflight, not private config mutation.
|
|
443
443
|
|
|
444
444
|
### OpenCode injection preview
|
|
445
445
|
|
package/docs/cli.md
CHANGED
|
@@ -232,7 +232,7 @@ bun run cli:bun -- sdd status --project vgxness --change my-change
|
|
|
232
232
|
Provider support shown in the Installation surface is:
|
|
233
233
|
|
|
234
234
|
- **OpenCode** — supported primary provider with preview/status/doctor and read-only install planning.
|
|
235
|
-
- **Claude** —
|
|
235
|
+
- **Claude** — supported secondary provider for Claude CLI MCP registration, project `.mcp.json` compatibility, project-root `CLAUDE.md` managed memory, and project/user agent planning. Scopes are `local|project|user`; `personal`/`global` map to `user`. Explicit guarded apply is outside the guided OpenCode flow and requires `mcp install claude --scope <scope> --yes --run-id <id>`. Read-only status/doctor/change-plan do not read private Claude config or execute Claude Code.
|
|
236
236
|
- **Antigravity** — placeholder/coming-soon guidance only.
|
|
237
237
|
- **Custom/future** — extension point with safe manual/default unsupported behavior.
|
|
238
238
|
|
|
@@ -445,7 +445,7 @@ bun run cli:bun -- mcp setup --preview --provider claude --db <path>
|
|
|
445
445
|
bun run cli:bun -- mcp doctor --db <path> --project vgxness --change manual-smoke
|
|
446
446
|
```
|
|
447
447
|
|
|
448
|
-
The setup preview JSON includes `installable:false`, `readOnly:true`, `writesProviderConfig:false`, plus a copyable MCP server command. Without `--db`, preview snippets omit `--db` and rely on the global default database; with `--db <path>` or `VGXNESS_DB_PATH`, snippets keep the explicit database argument. If needed, copy the `server.command` and `server.args` from the preview into your client manually; the preview itself never writes that config. For OpenCode config automation, inspect `mcp install opencode --plan` before applying with `--yes`; the default target is `$HOME/.config/opencode/opencode.json`.
|
|
448
|
+
The setup preview JSON includes `installable:false`, `readOnly:true`, `writesProviderConfig:false`, plus a copyable MCP server command. Without `--db`, preview snippets omit `--db` and rely on the global default database; with `--db <path>` or `VGXNESS_DB_PATH`, snippets keep the explicit database argument. If needed, copy the `server.command` and `server.args` from the preview into your client manually; the preview itself never writes that config. For OpenCode config automation, inspect `mcp install opencode --plan` before applying with `--yes`; the default target is `$HOME/.config/opencode/opencode.json`. For Claude config, inspect `mcp install claude --plan --scope local|project|user`; confirmed writes or CLI execution require `mcp install claude --scope <scope> --yes --run-id <id>` so VGXNESS run preflight can authorize each target.
|
|
449
449
|
|
|
450
450
|
The top-level `vgxness doctor` command prints human-readable readiness checks by default and accepts `--json` for scriptable output. Lower-level `mcp doctor` remains useful for MCP-specific checks and manual diagnostics; use `--json` where parseable output is needed. `ready:true` means required checks passed. `ready:false` means at least one required check failed; read the failed check `id`, `detail`, and optional `remediation` to fix the local setup, then run doctor again.
|
|
451
451
|
|
|
@@ -506,6 +506,41 @@ Manual OpenCode verification checklist:
|
|
|
506
506
|
5. In OpenCode, confirm the `vgxness` MCP tools are available.
|
|
507
507
|
6. Call `vgxness_sdd_status` against a known project/change, then run doctor again if anything fails.
|
|
508
508
|
|
|
509
|
+
## Claude Code MCP install
|
|
510
|
+
|
|
511
|
+
Claude Code is supported as a secondary, non-default provider for VGXNESS MCP/subagent configuration. Planning/status/doctor/change-plan are read-only and do not require Claude Code, network, or credentials. Scopes are `local`, `project`, and `user`; compatibility aliases `personal` and legacy `global` map to Claude `user` with warnings. MCP registration is represented as Claude CLI argv (`claude mcp add --scope <scope> vgxness -- vgxness mcp start`), never shell strings or manual `~/.claude.json` mutation.
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
bun run cli:bun -- mcp install claude --plan --scope project --db <path>
|
|
515
|
+
bun run cli:bun -- mcp install claude --plan --scope user --db <path>
|
|
516
|
+
bun run cli:bun -- mcp install claude --yes --scope project --run-id <id> --db <path>
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Allowed project-scope writes after explicit confirmation and run preflight:
|
|
520
|
+
|
|
521
|
+
- `.mcp.json`
|
|
522
|
+
- `.claude/agents/*.md`
|
|
523
|
+
- project-root `CLAUDE.md`, only the VGXNESS managed block; user-authored content outside the block is preserved and existing files are backed up before append/update
|
|
524
|
+
|
|
525
|
+
User agent files target `~/.claude/agents/*.md` only when a future apply path explicitly preflights that external directory. Read-only plans/status/doctor/change-plan never write it.
|
|
526
|
+
|
|
527
|
+
Forbidden writes:
|
|
528
|
+
|
|
529
|
+
- `~/.claude.json`
|
|
530
|
+
- `.claude/CLAUDE.md`
|
|
531
|
+
|
|
532
|
+
Malformed or conflicting VGXNESS markers in project-root `CLAUDE.md` refuse the full Claude project install before any Claude target is mutated.
|
|
533
|
+
|
|
534
|
+
Manual/opt-in runtime validation checklist (not normal CI):
|
|
535
|
+
|
|
536
|
+
1. Apply Claude project-local config through the guarded VGXNESS flow.
|
|
537
|
+
2. Open Claude Code in the project manually.
|
|
538
|
+
3. Approve the project MCP server if prompted.
|
|
539
|
+
4. Run `/mcp` and verify `vgxness` is connected.
|
|
540
|
+
5. Run `/agents` and verify expected project subagents are visible.
|
|
541
|
+
6. Ask Claude to call a safe read-only VGXNESS MCP tool.
|
|
542
|
+
7. Confirm forbidden files were not written by VGXNESS.
|
|
543
|
+
|
|
509
544
|
## SDD workflow examples
|
|
510
545
|
|
|
511
546
|
Use `sdd` commands to inspect local SDD artifact state and save, read, or list phase artifacts. These commands read and write only the selected `vgxness` local SQLite memory store: `--db <path>` when passed, `VGXNESS_DB_PATH` when set, or the global default database when neither override is present.
|
package/docs/glossary.md
CHANGED
|
@@ -8,7 +8,7 @@ A human-only action that records explicit approval of a SDD phase artifact. `vgx
|
|
|
8
8
|
|
|
9
9
|
## Adapter
|
|
10
10
|
|
|
11
|
-
A translator between VGXNESS's provider-neutral domain and a specific provider. The control plane uses renderers (OpenCode, JSON, Claude
|
|
11
|
+
A translator between VGXNESS's provider-neutral domain and a specific provider. The control plane uses renderers/install planners (OpenCode, JSON, Claude project-local support). The code runtime uses `CodeProviderAdapter` implementations (`openai-compatible`, `fake`).
|
|
12
12
|
|
|
13
13
|
## Agent
|
|
14
14
|
|
|
@@ -92,7 +92,7 @@ The provider-agnostic front-door classifier for operator text. Maps an intent to
|
|
|
92
92
|
|
|
93
93
|
## OpenCode
|
|
94
94
|
|
|
95
|
-
The primary supported provider for the control plane. The configurator renders OpenCode MCP config and manager/SDD agent definitions. Claude Code is
|
|
95
|
+
The primary/default supported provider for the control plane. The configurator renders OpenCode MCP config and manager/SDD agent definitions. Claude Code is supported secondary for project-local VGXNESS MCP/subagent configuration through explicit guarded apply.
|
|
96
96
|
|
|
97
97
|
## Operation attempt
|
|
98
98
|
|
package/docs/prd.md
CHANGED
|
@@ -203,7 +203,7 @@ The same flow must be available through CLI flags for automation and CI-friendly
|
|
|
203
203
|
Initial integration targets:
|
|
204
204
|
|
|
205
205
|
- OpenCode — primary supported provider. The configurator plane renders OpenCode MCP config and manager/SDD agent definitions; the code runtime speaks to any OpenAI-compatible endpoint, including OpenCode's local bridge.
|
|
206
|
-
- Claude Code —
|
|
206
|
+
- Claude Code — supported secondary for project-local VGXNESS MCP/subagent configuration and guarded project-root `CLAUDE.md` managed memory. Confirmed writes are explicit and guarded (`.mcp.json`, `.claude/agents/*.md`, and the `CLAUDE.md` managed block only); VGXNESS does not install/execute Claude Code and never manually writes `~/.claude.json` or `.claude/CLAUDE.md`.
|
|
207
207
|
|
|
208
208
|
Pi/`gentle-pi` is a design reference and future adapter target, not part of the first integration target list unless the MVP scope is explicitly expanded.
|
|
209
209
|
|
|
@@ -351,7 +351,7 @@ Many of the early PRD questions are resolved in v1.5.1. Tracking them here keeps
|
|
|
351
351
|
|
|
352
352
|
| Question | Resolved as of v1.5.1 |
|
|
353
353
|
|---|---|
|
|
354
|
-
| First integration adapter | OpenCode primary; Claude is
|
|
354
|
+
| First integration adapter | OpenCode primary/default; Claude is supported secondary for project-local explicit apply. |
|
|
355
355
|
| Memory storage scopes | Project memory and personal/global memory live in separate SQLite stores; `--db` flag and `VGXNESS_DB_PATH` env var override. |
|
|
356
356
|
| Agent config format | Provider-neutral schema in `src/agents/schema.ts`; canonical manifest with validation in `src/agents/canonical-agent-manifest.ts`. |
|
|
357
357
|
| Skill config format | Versioned skills with source metadata (`path`/`url`/`inline`); active version gating in `src/skills/skill-registry-service.ts`. |
|
package/docs/providers.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Providers
|
|
2
2
|
|
|
3
|
-
VGXNESS is provider-agnostic at the core: the registry stores provider-neutral definitions and adapters translate them into provider-specific config and runtime behavior. This document covers the two adapter layers: the **control-plane adapter** (OpenCode
|
|
3
|
+
VGXNESS is provider-agnostic at the core: the registry stores provider-neutral definitions and adapters translate them into provider-specific config and runtime behavior. This document covers the two adapter layers: the **control-plane adapter** (OpenCode primary plus supported secondary Claude Code support) and the **code-runtime provider adapter** (OpenAI-compatible + fake).
|
|
4
4
|
|
|
5
|
-
## Status (v1.
|
|
5
|
+
## Status (v1.6.0)
|
|
6
6
|
|
|
7
7
|
| Provider | Control plane | Code runtime | Notes |
|
|
8
8
|
|---|---|---|---|
|
|
9
9
|
| OpenCode | `managed` | n/a (target) | Primary supported provider. The configurator renders OpenCode MCP config and manager/SDD agent definitions into the chosen scope. |
|
|
10
|
-
| Claude Code | `
|
|
10
|
+
| Claude Code | `supported-secondary` | n/a | Supported for Claude CLI MCP registration planning/apply, project `.mcp.json` compatibility, project-root `CLAUDE.md` managed memory, and project/user agent planning. Scopes are `local`, `project`, and `user`; `personal`/`global` map to `user` for compatibility. Confirmed applies are explicit and guarded; read-only surfaces do not execute Claude Code and VGXNESS never manually mutates `~/.claude.json`. |
|
|
11
11
|
| Antigravity | `placeholder` | n/a | Listed in the TUI Installation surface as coming-soon. |
|
|
12
12
|
| Custom / future | `extension` | extension point | Per the [Architecture](./architecture.md) decision, anything not OpenCode or Claude is a custom extension. |
|
|
13
13
|
| OpenAI-compatible | n/a | `openai-compatible-provider-adapter.ts` | Real adapter used by `vgxness code`. Speaks to any OpenAI-compatible endpoint. |
|
|
@@ -42,9 +42,36 @@ The output is previewable JSON; the renderer does not write to `.opencode/`, `.c
|
|
|
42
42
|
vgxness agents render --provider json --project vgxness --name apply-agent
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
### Claude
|
|
45
|
+
### Claude Code support
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Claude Code is supported as a secondary, non-default control-plane target. Read-only status, doctor, setup plan, and change-plan surfaces can inspect or preview Claude targets without Claude Code installed and without writing files.
|
|
48
|
+
|
|
49
|
+
Claude scopes are canonicalized to `local`, `project`, and `user`; VGXNESS compatibility aliases `personal` and legacy `global` map to Claude `user` with warnings. MCP registration is represented as argv only, for example `claude mcp add --scope user vgxness -- vgxness mcp start`; no shell strings or manual `~/.claude.json` edits are generated. Status/doctor/change-plan avoid private Claude config reads and do not execute Claude Code.
|
|
50
|
+
|
|
51
|
+
Allowed project-scope writes, only after explicit guarded apply with run preflight metadata (`vgxness mcp install claude --scope project --yes --run-id <id>`):
|
|
52
|
+
|
|
53
|
+
- `.mcp.json`
|
|
54
|
+
- `.claude/agents/*.md`
|
|
55
|
+
- project-root `CLAUDE.md`, only the VGXNESS managed block; user content outside the block is preserved exactly and existing files are backed up before append/update
|
|
56
|
+
|
|
57
|
+
User-scoped agent files target `~/.claude/agents/*.md` only as an explicit external-directory/preflighted operation. They are never written by read-only planning/status/doctor/change-plan.
|
|
58
|
+
|
|
59
|
+
Forbidden writes:
|
|
60
|
+
|
|
61
|
+
- `~/.claude.json`
|
|
62
|
+
- `.claude/CLAUDE.md`
|
|
63
|
+
|
|
64
|
+
Malformed, duplicate, partial, or conflicting VGXNESS markers in `CLAUDE.md` cause the full Claude project install to be refused before `.mcp.json`, `.claude/agents/*.md`, or `CLAUDE.md` are mutated.
|
|
65
|
+
|
|
66
|
+
Manual/opt-in runtime validation checklist (not normal CI):
|
|
67
|
+
|
|
68
|
+
1. Apply Claude project-local config through the guarded VGXNESS flow.
|
|
69
|
+
2. Open Claude Code in the project manually.
|
|
70
|
+
3. Approve the project MCP server if prompted.
|
|
71
|
+
4. Run `/mcp` and verify `vgxness` is connected.
|
|
72
|
+
5. Run `/agents` and verify expected project subagents are visible.
|
|
73
|
+
6. Ask Claude to call a safe read-only VGXNESS MCP tool.
|
|
74
|
+
7. Confirm forbidden files were not written by VGXNESS.
|
|
48
75
|
|
|
49
76
|
### OpenCode injection preview
|
|
50
77
|
|
|
@@ -113,7 +140,7 @@ Writes happen only through `apply` with explicit consent. Plans, status, doctor,
|
|
|
113
140
|
|
|
114
141
|
Adapters and renderers must not:
|
|
115
142
|
|
|
116
|
-
- Write provider config
|
|
143
|
+
- Write provider config outside explicit guarded apply. OpenCode install writes only its selected target; Claude project compatibility apply writes only `.mcp.json`, `.claude/agents/*.md`, and the guarded project-root `CLAUDE.md` managed block; Claude local/user MCP registration uses Claude CLI argv after confirmation/preflight and never manual private-config mutation.
|
|
117
144
|
- Call providers (`opencode`, `claude`, etc.) during preview or status.
|
|
118
145
|
- Install global memory.
|
|
119
146
|
- Create `openspec/`.
|
package/docs/roadmap.md
CHANGED
|
@@ -63,7 +63,7 @@ The main menu and setup screens are in via OpenTUI. The dashboard directory is e
|
|
|
63
63
|
|
|
64
64
|
## Provider coverage
|
|
65
65
|
|
|
66
|
-
- **Claude Code
|
|
66
|
+
- **Claude Code runtime validation.** Project-local install planning/apply is supported behind explicit run preflight. Remaining work is optional manual runtime smoke guidance or future live smoke tooling; it must stay out of normal CI.
|
|
67
67
|
- **Antigravity and other custom adapters.** Listed as placeholders; a real adapter would unblock those workflows.
|
|
68
68
|
- **Provider doctor upgrades.** Doctor checks could surface real config drift, not just existence of expected files.
|
|
69
69
|
|