vgxness 1.9.8 → 1.10.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.
Files changed (35) hide show
  1. package/README.md +5 -4
  2. package/dist/cli/cli-flags.js +15 -2
  3. package/dist/cli/cli-help.js +13 -13
  4. package/dist/cli/commands/mcp-dispatcher.js +8 -4
  5. package/dist/cli/commands/setup-dispatcher.js +2 -2
  6. package/dist/cli/tui/setup/setup-tui-read-model.js +17 -17
  7. package/dist/cli/tui/setup/setup-tui-state.js +1 -3
  8. package/dist/mcp/claude-code-config.js +2 -0
  9. package/dist/mcp/claude-code-scope.js +1 -0
  10. package/dist/mcp/claude-code-user-config.js +2 -0
  11. package/dist/mcp/client-install-claude-code-contract.js +15 -72
  12. package/dist/mcp/client-install-claude-code.js +4 -6
  13. package/dist/mcp/client-install-opencode-contract.js +5 -79
  14. package/dist/mcp/opencode-visibility.js +4 -3
  15. package/dist/mcp/provider-change-plan.js +10 -7
  16. package/dist/mcp/provider-doctor.js +31 -14
  17. package/dist/mcp/provider-health-types.js +19 -0
  18. package/dist/mcp/provider-status.js +19 -10
  19. package/dist/mcp/schema.js +5 -4
  20. package/dist/mcp/validation.js +11 -1
  21. package/dist/setup/backup-rollback-service.js +33 -2
  22. package/dist/setup/providers/claude-setup-adapter.js +13 -15
  23. package/dist/setup/providers/opencode-setup-adapter.js +12 -12
  24. package/dist/setup/setup-defaults.js +1 -0
  25. package/dist/setup/setup-plan.js +6 -6
  26. package/docs/architecture.md +3 -3
  27. package/docs/cli.md +29 -33
  28. package/docs/glossary.md +2 -2
  29. package/docs/mcp.md +1 -1
  30. package/docs/prd.md +3 -3
  31. package/docs/providers.md +14 -15
  32. package/docs/roadmap.md +1 -1
  33. package/docs/safety.md +1 -1
  34. package/docs/storage.md +1 -1
  35. package/package.json +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@ VGXNESS is an installable CLI, MCP control plane, and native code runtime for gu
6
6
 
7
7
  This package is proprietary software. The npm package ships inspectable JavaScript (`dist/`) so Node can run it, but it is **not open-source licensed** and may not be redistributed unless you have written permission. See [LICENSE](./LICENSE).
8
8
 
9
- OpenCode is the primary supported provider. Other providers remain preview/manual only. Provider config writes require explicit CLI confirmation.
9
+ OpenCode is the primary supported provider. Claude setup support is secondary. VGX-managed OpenCode and Claude provider configuration is user-global only; provider config writes require explicit CLI confirmation.
10
10
 
11
11
  VGXNESS v1.9.1 has a canonical project health audit with validated evidence: 38 MCP tools, 106 test files, and the official Bun validation path passing, including package evidence with `releaseReadiness: pass`. Current unreleased builds expose 41 MCP tools after adding read-only SDD/run recovery parity. See [Project health audit v1.9.1](./docs/project-health-audit-v1.9.1.md) for the versioned matrix and safety taxonomy.
12
12
 
@@ -150,7 +150,7 @@ vgxness sdd continue --project <project> --change <change>
150
150
  vgxness code sdd <change> <phase> --project <project> --save-artifact
151
151
  ```
152
152
 
153
- Stable defaults are: package `vgxness`, provider `opencode`, global user data DB, user/global OpenCode scope (`$HOME/.config/opencode/opencode.json`), and `mcp-plus-agents` mode. Use `--scope project` only when you intentionally want `<workspace>/.opencode/opencode.json`. The generated MCP command for the global DB default is:
153
+ Stable defaults are: package `vgxness`, provider `opencode`, global user data DB, user-global OpenCode config (`$HOME/.config/opencode/opencode.json`), and `mcp-plus-agents` mode. VGX-managed OpenCode and Claude provider configuration is user-global only; runtime VGXNESS state remains project-aware through `--project`, `--change`, workspace, and database context. Existing project-local provider files such as `.opencode/`, `opencode.json`, `.mcp.json`, `.claude/`, and `CLAUDE.md` remain untouched by VGXNESS setup. They may still affect OpenCode or Claude behavior externally, but VGXNESS treats them as external/manual diagnostics and will not repair, write, back up, or delete them. The generated MCP command for the global DB default is:
154
154
 
155
155
  ```bash
156
156
  vgxness mcp start
@@ -182,7 +182,8 @@ Edits, shell, network, git mutations, SDD persistence, and memory saves route th
182
182
  ## Safety model
183
183
 
184
184
  - Preview, status, and plan commands do not write provider config; local VGXNESS store initialization may occur where the command needs SQLite-backed state.
185
- - Provider config writes require explicit `--yes` confirmation.
185
+ - VGX-managed OpenCode and Claude provider config writes are user-global only and require explicit `--yes` confirmation.
186
+ - Runtime VGXNESS state remains project-aware; project-local provider files are read-only external/manual diagnostics and may still affect provider behavior outside VGXNESS.
186
187
  - Setup/status TUI surfaces are read-only setup, diagnostics, recovery, and fallback surfaces; daily SDD progression stays in OpenCode with VGXNESS MCP.
187
188
  - SDD artifacts are SQLite-backed through VGXNESS services. Do not create or write `openspec/`.
188
189
  - `vgxness sdd accept-artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
@@ -260,7 +261,7 @@ Do not publish from CI. Publication or registry dry-run checks require separate
260
261
  npm uninstall -g vgxness
261
262
  ```
262
263
 
263
- Remove any OpenCode config entries and local/global VGXNESS data manually if you no longer need them.
264
+ Remove any user-global OpenCode/Claude config entries and local/global VGXNESS data manually if you no longer need them. Project-local provider files are external/manual and are not created, repaired, or deleted by VGXNESS setup.
264
265
 
265
266
  ## More docs
266
267
 
@@ -112,9 +112,22 @@ function optionalScopeFlag(flags, name) {
112
112
  return { ok: true, value: undefined };
113
113
  return value === 'project' || value === 'personal' ? { ok: true, value } : validationFailure(`--${name} must be project or personal`);
114
114
  }
115
+ const providerUserGlobalOnlyMigrationMessage = 'VGX-managed provider configuration is user-global only for OpenCode and Claude. Project/local provider files are treated as external/manual diagnostics and will not be written by VGXNESS. Re-run without the project/local install scope.';
115
116
  function opencodeInstallScopeFlag(flags, name) {
116
117
  const value = optionalStringFlag(flags, name) ?? vgxnessSetupDefaults.defaultOpenCodeScope;
117
- return value === 'project' || value === 'user' ? { ok: true, value } : validationFailure(`--${name} must be project or user`);
118
+ if (value === 'user' || value === 'global' || value === 'personal')
119
+ return { ok: true, value: 'user' };
120
+ if (value === 'project' || value === 'local')
121
+ return validationFailure(providerUserGlobalOnlyMigrationMessage);
122
+ return validationFailure(`--${name} must be user, global, or personal`);
123
+ }
124
+ function opencodeDiagnosticScopeFlag(flags, name) {
125
+ const value = optionalStringFlag(flags, name) ?? vgxnessSetupDefaults.defaultOpenCodeScope;
126
+ if (value === 'user' || value === 'global' || value === 'personal')
127
+ return { ok: true, value: 'user' };
128
+ if (value === 'project')
129
+ return { ok: true, value };
130
+ return validationFailure(`--${name} must be user, global, personal, or project`);
118
131
  }
119
132
  function optionalModeFlag(flags, name) {
120
133
  const value = optionalStringFlag(flags, name);
@@ -325,4 +338,4 @@ function setupInstallModeFlag(flags) {
325
338
  return { ok: true, value: 'mcp-only' };
326
339
  return { ok: true, value: vgxnessSetupDefaults.defaultInstallMode };
327
340
  }
328
- export { acceptedAtFlag, codeApprovalPolicyFlag, codeMemoryPolicyFlag, codeTranscriptModeFlag, codeVerificationModeFlag, csvFlag, databasePathFor, databasePathSelectionFor, finalRunStatusFlag, instructionKindFlag, isRunStatus, isSkillEvaluationResultStatus, isSkillTargetType, jsonFlag, opencodeInstallScopeFlag, optionalJsonFlag, optionalModeFlag, optionalNumberFlag, optionalRunStatusFlag, optionalScopeFlag, optionalSkillEvaluationResultStatusFlag, optionalSkillImprovementProposalStatusFlag, optionalSkillResolutionUsageFlag, optionalSkillTargetTypeFlag, optionalSkillVersionStatusFlag, optionalStringFlag, optionalTrimmedFlag, parseArgs, permissionCategoryFlag, requiredFlag, requiredTrimmedFlag, retryPolicyFlag, runOutcomeFlag, scopeFlag, setupDatabaseFlags, setupInstallModeFlag, setupProviderFlag, skillEvaluationResultStatusFlag, skillSourceFromFlags, skillSourceKindFlag, skillTargetTypeFlag, skillUsageOutcomeFlag, };
341
+ export { acceptedAtFlag, codeApprovalPolicyFlag, codeMemoryPolicyFlag, codeTranscriptModeFlag, codeVerificationModeFlag, csvFlag, databasePathFor, databasePathSelectionFor, finalRunStatusFlag, instructionKindFlag, isRunStatus, isSkillEvaluationResultStatus, isSkillTargetType, jsonFlag, providerUserGlobalOnlyMigrationMessage, opencodeDiagnosticScopeFlag, opencodeInstallScopeFlag, optionalJsonFlag, optionalModeFlag, optionalNumberFlag, optionalRunStatusFlag, optionalScopeFlag, optionalSkillEvaluationResultStatusFlag, optionalSkillImprovementProposalStatusFlag, optionalSkillResolutionUsageFlag, optionalSkillTargetTypeFlag, optionalSkillVersionStatusFlag, optionalStringFlag, optionalTrimmedFlag, parseArgs, permissionCategoryFlag, requiredFlag, requiredTrimmedFlag, retryPolicyFlag, runOutcomeFlag, scopeFlag, setupDatabaseFlags, setupInstallModeFlag, setupProviderFlag, skillEvaluationResultStatusFlag, skillSourceFromFlags, skillSourceKindFlag, skillTargetTypeFlag, skillUsageOutcomeFlag, };
@@ -9,9 +9,9 @@ Areas:
9
9
  status [--project <name>] [--change <id>] [--db <path>] [--json]
10
10
  next [--project <name>] [--change <id>] [--db <path>] [--json]
11
11
  resume [--project <name>] [--run-id <id>] [--db <path>] [--json]
12
- init [--project <name>] [--provider opencode|claude|none] [--scope user|project] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents] [--json]
13
- setup plan [--project <name>] [--provider opencode|claude|none] [--scope user|project] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents] [--json]
14
- setup apply --yes [--project <name>] [--provider opencode|claude|none] [--scope user|project] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents]
12
+ init [--project <name>] [--provider opencode|claude|none] [--scope user|global|personal] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents] [--json]
13
+ setup plan [--project <name>] [--provider opencode|claude|none] [--scope user|global|personal] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents] [--json]
14
+ setup apply --yes [--project <name>] [--provider opencode|claude|none] [--scope user|global|personal] [--db global|project-local|custom|<path>] [--db-path <path>] [--mode mcp-only|mcp-plus-agents]
15
15
  setup backup list --provider opencode [--scope project|user|global] [--target <path>] [--json]
16
16
  setup rollback --backup <path> [--preview|--yes] [--json]
17
17
  setup status [--project <name>] [--scope project|personal] [--db <path>] [--json]
@@ -23,7 +23,7 @@ Areas:
23
23
  Next answers "what should I do now?" with a shorter next-action view.
24
24
  Resume answers "how do I continue interrupted work?" with run inspection guidance.
25
25
  Without --change or --run-id they stay orientation-only and do not open local memory; with --change or --run-id they read SQLite read-only. Pass --json for automation.
26
- Setup plan/init default to human-readable read-only output; pass --json for automation. Setup apply writes OpenCode config only with --yes and uses the global user DB plus mcp-plus-agents by default.
26
+ Setup plan/init default to human-readable read-only output; pass --json for automation. VGX-managed provider configuration is user-global only for OpenCode and Claude; setup apply writes provider config only with --yes and uses the global user DB plus mcp-plus-agents by default.
27
27
  Setup status defaults to human-readable read-only output; pass --json for automation. It never writes provider config or executes providers.
28
28
  Doctor defaults to human-readable output; pass --json for automation.
29
29
  Verification plans are read-only recommendations only; they never execute commands, write provider config, persist results, mutate SDD artifacts, or infer acceptance.
@@ -64,19 +64,19 @@ Areas:
64
64
  Approval commands resolve explicit run/preflight approval records; they do not change agent seed permissions or globally allow shell/provider access.
65
65
 
66
66
  mcp setup --preview --provider opencode|claude [--db <path>]
67
- mcp install opencode --plan [--scope user|project] [--db <path>] [--mcp-only|--no-agents] [--overwrite-vgxness|--reinstall]
68
- mcp install opencode --yes [--scope user|project] [--db <path>] [--mcp-only|--no-agents] [--overwrite-vgxness|--reinstall]
69
- mcp install claude --plan [--scope local|project|user] [--db <path>] [--overwrite-vgxness|--reinstall]
70
- mcp install claude --yes --run-id <id> [--scope local|project|user] [--db <path>] [--phase <phase>] [--agent-id <id>] [--overwrite-vgxness|--reinstall]
67
+ mcp install opencode --plan [--scope user|global|personal] [--db <path>] [--mcp-only|--no-agents] [--overwrite-vgxness|--reinstall]
68
+ mcp install opencode --yes [--scope user|global|personal] [--db <path>] [--mcp-only|--no-agents] [--overwrite-vgxness|--reinstall]
69
+ mcp install claude --plan [--scope user|global|personal] [--db <path>] [--overwrite-vgxness|--reinstall]
70
+ mcp install claude --yes --run-id <id> [--scope user|global|personal] [--db <path>] [--phase <phase>] [--agent-id <id>] [--overwrite-vgxness|--reinstall]
71
71
  mcp doctor opencode [--scope user|project] [--project-root <path>]
72
72
  mcp doctor [--db <path>] [--project <name>] [--change <id>] [--timeout-ms <ms>]
73
73
  MCP setup preview is read-only; it does not install or write .opencode/, .claude/, or provider config.
74
74
  Without --db, MCP install and setup commands use the vgxness global default database; pass --db .vgx/memory.sqlite for project-local compatibility.
75
- OpenCode install defaults to user/global scope and installs mcp.vgxness plus top-level permission.bash=ask, vgxness-manager with bash=allow, and hidden vgxness-sdd-* agents with explicit permissions; use --mcp-only for legacy MCP-only config.
75
+ OpenCode install defaults to user-global scope and installs mcp.vgxness plus top-level permission.bash=ask, vgxness-manager with bash=allow, and hidden vgxness-sdd-* agents with explicit permissions; use --mcp-only for legacy MCP-only config.
76
76
  Use --overwrite-vgxness (alias --reinstall) to reinstall only VGXNESS-managed OpenCode entries while preserving unrelated config; --yes is still required to write.
77
- It writes only after --yes. The default target is $HOME/.config/opencode/opencode.json; use --scope project to target .opencode/opencode.json explicitly.
78
- Project OpenCode config can override user config. Plans are read-only; applies refuse unsafe existing config and create backups before merge.
79
- Claude support is first-class for guarded MCP setup. Claude scopes are local|project|user; compatibility aliases personal/global map to user with warnings. Plans show Claude CLI argv, project .mcp.json compatibility, user ~/.claude.json MCP merge, agents, and guarded CLAUDE.md managed memory separately. Project scope confirmed applies write .mcp.json, .claude/agents/*.md, and the project-root CLAUDE.md managed block as needed. User/global confirmed applies narrowly merge only mcpServers.vgxness in ~/.claude.json, write ~/.claude/agents/*.md, and manage only the VGXNESS block in ~/.claude/CLAUDE.md. Confirmed Claude writes/CLI execution require VGXNESS run preflight metadata (--run-id, with optional --phase/--agent-id). Status/doctor/change-plan are read-only and do not execute Claude Code.
77
+ It writes only after --yes. VGX-managed provider configuration is user-global only for OpenCode and Claude; the OpenCode target is $HOME/.config/opencode/opencode.json.
78
+ Project/local provider files are external/manual diagnostics and will not be written by VGXNESS. Plans are read-only; applies refuse unsafe existing user-global config and create backups before merge.
79
+ Claude support is first-class for guarded MCP setup. Claude user/global/personal scopes all target user-global managed config. Confirmed Claude writes narrowly merge mcpServers.vgxness in ~/.claude.json, write ~/.claude/agents/*.md, and manage only the VGXNESS block in ~/.claude/CLAUDE.md. Confirmed Claude writes/CLI execution require VGXNESS run preflight metadata (--run-id, with optional --phase/--agent-id). Status/doctor/change-plan are read-only and do not execute Claude Code.
80
80
 
81
81
  skills register --project <name> --name <name> --description <text>
82
82
  skills list [--project <name>] [--scope project|personal]
@@ -105,7 +105,7 @@ Areas:
105
105
  No args in an interactive TTY opens the OpenTUI main menu.
106
106
  No args without a TTY prints static safe setup guidance and exits 0 without opening project state.
107
107
  Setup TUI may launch without --project; Installation remains available and project-scoped checks are deferred while project screens render project-required recovery states.
108
- Provider setup support: OpenCode first-class supported default guided install; Claude first-class supported guarded install for CLI MCP registration, project compatibility, and project/user agent planning; Antigravity placeholder; Custom/future extension point.
108
+ Provider setup support: OpenCode first-class supported default guided install; Claude first-class supported guarded user-global install; project/local provider files are diagnostics only; Antigravity placeholder; Custom/future extension point.
109
109
  Provider config writes/install/apply are external-only and require explicit confirmation.
110
110
 
111
111
  sdd status --project <name> --change <id> [--json]
@@ -9,7 +9,7 @@ import { resolveClaudeCodeScope } from '../../mcp/claude-code-scope.js';
9
9
  import { computeEffectiveManagerInstructions } from '../../agents/manager-profile-overlay-service.js';
10
10
  import { RunService } from '../../runs/run-service.js';
11
11
  import { isTerminalRunStatus } from '../../runs/schema.js';
12
- import { databasePathFor, databasePathSelectionFor, opencodeInstallScopeFlag, optionalNumberFlag, optionalStringFlag } from '../cli-flags.js';
12
+ import { databasePathFor, databasePathSelectionFor, opencodeDiagnosticScopeFlag, opencodeInstallScopeFlag, optionalNumberFlag, optionalStringFlag, providerUserGlobalOnlyMigrationMessage, } from '../cli-flags.js';
13
13
  import { usageFailure, validationFailure } from '../cli-help.js';
14
14
  import { jsonResult, openCliDatabase, resultFailure } from '../cli-helpers.js';
15
15
  import { renderDoctorReport } from '../doctor-renderer.js';
@@ -129,8 +129,12 @@ export function runMcpInstallCommand(parsed, environment) {
129
129
  }
130
130
  function claudeInstallScopeFlag(flags) {
131
131
  const value = optionalStringFlag(flags, 'scope');
132
- const resolved = resolveClaudeCodeScope(value);
133
- return resolved.ok ? { ok: true, value: resolved.value.canonical } : validationFailure(resolved.error.message);
132
+ const resolved = resolveClaudeCodeScope(value, 'user');
133
+ if (!resolved.ok)
134
+ return validationFailure(resolved.error.message);
135
+ if (resolved.value.canonical === 'project' || resolved.value.canonical === 'local')
136
+ return validationFailure(providerUserGlobalOnlyMigrationMessage);
137
+ return { ok: true, value: resolved.value.canonical };
134
138
  }
135
139
  function createClaudeCodeInstallPreflight(parsed, database, environment) {
136
140
  return (request) => {
@@ -211,7 +215,7 @@ export function runMcpDoctorCommand(parsed, environment, output = 'json') {
211
215
  })();
212
216
  }
213
217
  export function runMcpDoctorOpenCodeCommand(parsed, environment) {
214
- const scope = opencodeInstallScopeFlag(parsed.flags, 'scope');
218
+ const scope = opencodeDiagnosticScopeFlag(parsed.flags, 'scope');
215
219
  if (!scope.ok)
216
220
  return resultFailure(scope);
217
221
  const projectRoot = optionalStringFlag(parsed.flags, 'project-root');
@@ -9,7 +9,7 @@ import { applyRollbackConfigBackup, listProviderConfigBackups, previewRollbackCo
9
9
  import { vgxnessSetupDefaults } from '../../setup/setup-defaults.js';
10
10
  import { SetupLifecycleService } from '../../setup/setup-lifecycle-service.js';
11
11
  import { createSetupPlan } from '../../setup/setup-plan.js';
12
- import { databasePathFor, databasePathSelectionFor, opencodeInstallScopeFlag, optionalStringFlag, scopeFlag, setupDatabaseFlags, setupInstallModeFlag, setupProviderFlag, } from '../cli-flags.js';
12
+ import { databasePathFor, databasePathSelectionFor, opencodeInstallScopeFlag, optionalStringFlag, providerUserGlobalOnlyMigrationMessage, scopeFlag, setupDatabaseFlags, setupInstallModeFlag, setupProviderFlag, } from '../cli-flags.js';
13
13
  import { okText, usageFailure, validationFailure } from '../cli-help.js';
14
14
  import { jsonResult, openCliDatabase, resultFailure } from '../cli-helpers.js';
15
15
  import { renderSetupPlan } from '../setup-plan-renderer.js';
@@ -141,7 +141,7 @@ export async function applySetupPlanInput(input, environment) {
141
141
  ok: true,
142
142
  value: {
143
143
  status: 'manual-required',
144
- message: 'Claude setup apply is intentionally non-mutating here; use vgxness mcp install claude --scope project --yes --run-id <id> for guarded Claude writes.',
144
+ message: `Claude setup apply is intentionally non-mutating here; use vgxness mcp install claude --yes --run-id <id> for guarded user-global Claude writes. ${providerUserGlobalOnlyMigrationMessage}`,
145
145
  plan: plan.value,
146
146
  },
147
147
  };
@@ -35,20 +35,20 @@ export function setupTuiViewModelFromPlan(plan, status, state) {
35
35
  databaseLabel: plan === undefined ? 'pending' : plan.db.mode,
36
36
  databasePathLabel: compactPath(databasePath, 72),
37
37
  databaseSourceLabel: String(databaseSource),
38
- scopeLabel: isOpenCode ? (opencode?.scope ?? selections?.scope ?? 'user') : isClaude ? 'Project-local Claude config only; OpenCode controls disabled' : 'Manual / none (OpenCode controls disabled)',
38
+ scopeLabel: isOpenCode ? 'user-global provider config' : isClaude ? 'User-global Claude config only; project-local files are diagnostics' : 'Manual / none (OpenCode controls disabled)',
39
39
  installModeLabel: isOpenCode
40
40
  ? opencode?.installsAgents === false
41
41
  ? 'mcp-only'
42
42
  : (selections?.installMode ?? 'mcp-plus-agents')
43
43
  : isClaude
44
- ? 'Claude guarded apply outside guided OpenCode install'
44
+ ? 'Claude guarded user-global apply outside guided OpenCode install'
45
45
  : 'Manual / none (no OpenCode install)',
46
- targetPathLabel: isOpenCode && opencode?.targetPath !== undefined ? compactPath(opencode.targetPath, 72) : isClaude ? 'Claude targets: .mcp.json and .claude/agents/*.md via guarded apply' : 'No provider config target; manual/no-provider-write mode',
47
- opencodeActionLabel: isOpenCode ? opencodeActionLabel(opencode?.action) : isClaude ? 'No guided setup write; use guarded Claude install with run preflight.' : 'No automatic provider write; use manual setup guidance.',
46
+ targetPathLabel: isOpenCode && opencode?.targetPath !== undefined ? compactPath(opencode.targetPath, 72) : isClaude ? 'Claude targets: user-global ~/.claude.json, ~/.claude/agents/*.md, ~/.claude/CLAUDE.md via guarded apply' : 'No provider config target; manual/no-provider-write mode',
47
+ opencodeActionLabel: isOpenCode ? opencodeActionLabel(opencode?.action) : isClaude ? 'No guided setup write; use guarded user-global Claude install with run preflight.' : 'No automatic provider write; use manual setup guidance.',
48
48
  memoryPathExplanation: memoryExplanation,
49
49
  providerInstallabilityLabel: isOpenCode
50
- ? 'OpenCode is the default guided install provider. Claude is first-class supported via guarded mcp install claude --scope project --yes --run-id <id>.'
51
- : 'Manual / none is read-only guidance. Claude remains supported through explicit guarded apply outside this guided OpenCode flow.',
50
+ ? 'OpenCode is the default guided install provider. VGXNESS will manage user-global provider configuration. Claude is first-class supported via guarded mcp install claude --yes --run-id <id>. Project-local provider files are external/manual diagnostics and will not be modified.'
51
+ : 'Manual / none is read-only guidance. Claude remains supported through explicit guarded user-global apply outside this guided OpenCode flow.',
52
52
  agentReadinessLabel: agentReadiness.label,
53
53
  agentReadinessDetail: agentReadiness.detail,
54
54
  plannedActions: plan?.actions.map((action) => ({
@@ -63,8 +63,8 @@ export function setupTuiViewModelFromPlan(plan, status, state) {
63
63
  nextCommands: plan?.nextCommands ?? ['vgxness setup plan'],
64
64
  canAutoApply: plan?.provider === 'opencode' && plan.status === 'ready' && state?.selections.provider !== 'none' && plan.opencode !== undefined,
65
65
  safetyWarning: isOpenCode && (selections?.overwriteVgxness === true || opencode?.overwriteVgxness === true)
66
- ? 'Final confirmation is required. Reinstall is enabled: VGXNESS OpenCode entries will be overwritten after a managed backup when the target exists; unrelated config is preserved.'
67
- : 'Final confirmation is required before any provider config write. OpenCode config may be modified and backed up.',
66
+ ? 'Final confirmation is required. Reinstall is enabled: user-global VGXNESS OpenCode entries will be overwritten after a managed backup when the target exists; unrelated config is preserved. Project-local provider files are external/manual diagnostics and will not be modified.'
67
+ : 'Final confirmation is required before any provider config write. VGXNESS will manage user-global provider configuration. Project-local provider files are external/manual diagnostics and will not be modified.',
68
68
  frameLabel: 'VGXNESS Setup Assistant workspace',
69
69
  progressLabel: progressLabel(state?.screen),
70
70
  previewLabel,
@@ -78,14 +78,13 @@ export function setupTuiViewModelFromPlan(plan, status, state) {
78
78
  choice('database:custom', 'Custom database path', 'Deferred/read-only in the TUI unless already supplied by flags or environment.', selections?.databaseMode === 'custom' || (selections === undefined && plan?.db.mode === 'custom'), state?.focusedChoiceId, [badgeLabels.deferred, badgeLabels.readOnly]),
79
79
  ],
80
80
  providerChoices: [
81
- choice('provider:opencode', 'OpenCode', 'Default guided install provider; writes still require final confirmation.', (selections?.provider ?? plan?.provider ?? 'opencode') === 'opencode', state?.focusedChoiceId, [badgeLabels.recommended]),
82
- choice('provider:claude-supported', 'Claude (first-class supported)', 'Claude CLI MCP registration and project compatibility apply only via guarded mcp install claude --scope project --yes --run-id <id>; explicit install path.', (selections?.provider ?? plan?.provider) === 'claude', state?.focusedChoiceId, ['[supported]', badgeLabels.readOnly]),
81
+ choice('provider:opencode', 'OpenCode', 'Default guided install provider. VGXNESS will manage user-global provider configuration.', (selections?.provider ?? plan?.provider ?? 'opencode') === 'opencode', state?.focusedChoiceId, [badgeLabels.recommended]),
82
+ choice('provider:claude-supported', 'Claude (first-class supported)', 'Claude user-global CLI MCP registration and config apply only via guarded mcp install claude --yes --run-id <id>; project-local files are diagnostics only.', (selections?.provider ?? plan?.provider) === 'claude', state?.focusedChoiceId, ['[supported]', badgeLabels.readOnly]),
83
83
  choice('provider:none', 'Manual / none', 'No automatic provider config write; follow manual setup guidance.', (selections?.provider ?? plan?.provider) === 'none', state?.focusedChoiceId, [badgeLabels.manual, badgeLabels.readOnly]),
84
84
  ],
85
85
  scopeChoices: isOpenCode
86
86
  ? [
87
- choice('scope:user', 'User/global scope', 'Preview the default user-level OpenCode config target; still requires final confirmation.', (selections?.scope ?? opencode?.scope ?? 'user') === 'user', state?.focusedChoiceId, [badgeLabels.recommended, badgeLabels.writeAfterConfirm]),
88
- choice('scope:project', 'Project scope', 'Opt in to writing project OpenCode config only after final confirmation.', (selections?.scope ?? opencode?.scope) === 'project', state?.focusedChoiceId, [badgeLabels.writeAfterConfirm]),
87
+ choice('scope:user', 'User-global provider config', 'VGXNESS will manage user-global provider configuration. Project-local provider files are external/manual diagnostics and will not be modified.', true, state?.focusedChoiceId, [badgeLabels.recommended, badgeLabels.writeAfterConfirm]),
89
88
  ]
90
89
  : [],
91
90
  installModeChoices: isOpenCode
@@ -96,7 +95,7 @@ export function setupTuiViewModelFromPlan(plan, status, state) {
96
95
  : [],
97
96
  overwriteChoices: isOpenCode
98
97
  ? [
99
- choice('overwrite:vgxness', 'Reinstall VGXNESS entries', 'Default off. When enabled, final confirmation overwrites existing VGXNESS OpenCode entries and preserves unrelated OpenCode config.', selections?.overwriteVgxness ?? opencode?.overwriteVgxness ?? false, state?.focusedChoiceId, [badgeLabels.warning, badgeLabels.writeAfterConfirm]),
98
+ choice('overwrite:vgxness', 'Reinstall VGXNESS entries', 'Default off. When enabled, final confirmation overwrites existing user-global VGXNESS OpenCode entries and preserves unrelated OpenCode config.', selections?.overwriteVgxness ?? opencode?.overwriteVgxness ?? false, state?.focusedChoiceId, [badgeLabels.warning, badgeLabels.writeAfterConfirm]),
100
99
  ]
101
100
  : [],
102
101
  };
@@ -109,10 +108,10 @@ function previewDetailLines(input) {
109
108
  `Provider: ${input.provider === 'opencode' ? 'OpenCode [recommended default]' : input.provider === 'claude' ? 'Claude [first-class supported] [guarded explicit apply]' : 'Manual / none [manual] [read-only]'}`,
110
109
  `Memory path: ${plan?.db.mode ?? 'pending'} at ${compactPath(input.databasePath, 72)} (source: ${String(input.databaseSource)})`,
111
110
  `Memory guidance: ${memoryPathExplanation(plan, input.databasePath, input.databaseSource)}`,
112
- `Scope: ${input.isOpenCode ? (opencode?.scope ?? 'user') : 'disabled for manual/none provider'}`,
111
+ `Scope: ${input.isOpenCode ? 'user-global provider config' : 'disabled for manual/none provider'}`,
113
112
  `Install mode: ${input.isOpenCode ? (opencode?.installsAgents === false ? 'mcp-only' : 'mcp-plus-agents') : 'disabled for manual/none provider'}`,
114
113
  `Reinstall VGXNESS entries: ${input.isOpenCode ? String(opencode?.overwriteVgxness ?? false) : 'disabled for manual/none provider'}`,
115
- `Provider installability: ${input.isOpenCode ? 'OpenCode installable after final confirmation; Claude first-class support requires guarded mcp install claude --scope project --yes --run-id <id>.' : 'No guided provider install from this selection; Claude uses guarded explicit apply.'}`,
114
+ `Provider installability: ${input.isOpenCode ? 'OpenCode installable after final confirmation. VGXNESS will manage user-global provider configuration. Claude first-class support requires guarded mcp install claude --yes --run-id <id>. Project-local provider files are external/manual diagnostics and will not be modified.' : 'No guided provider install from this selection; Claude uses guarded explicit user-global apply.'}`,
116
115
  `Agent readiness: ${agentReadinessFromPlan(plan)}`,
117
116
  `Target config: ${input.isOpenCode && opencode?.targetPath !== undefined ? compactPath(opencode.targetPath, 72) : 'none; no provider config will be written'}`,
118
117
  `Safety: ${input.isOpenCode ? '[will write after confirm] only on final confirmation' : '[read-only] manual/no-provider-write mode'}`,
@@ -132,7 +131,8 @@ function helpLines(screen) {
132
131
  'Next/back: Tab continues; Shift+Tab goes back. Enter continues on review and confirms only on final confirmation.',
133
132
  'Cancel/close: q or Esc cancels setup; when help is open, ?/h toggles it closed.',
134
133
  reviewLine,
135
- 'Provider support: OpenCode is the default guided install provider; Claude is first-class supported for guarded explicit apply via mcp install claude --scope project --yes --run-id <id>; Manual / none writes no provider config.',
134
+ 'Provider support: OpenCode is the default guided install provider; Claude is first-class supported for guarded explicit user-global apply via mcp install claude --yes --run-id <id>; Manual / none writes no provider config.',
135
+ 'Provider config: VGXNESS will manage user-global provider configuration. Project-local provider files are external/manual diagnostics and will not be modified.',
136
136
  'Agent readiness: the preview checks vgxness-manager/SDD readiness guidance; preview screens never seed agents.',
137
137
  'No-write guarantee: no provider config is written before explicit final confirmation.',
138
138
  ];
@@ -177,7 +177,7 @@ function progressLabel(screen) {
177
177
  if (screen === 'provider')
178
178
  return 'Step 3/6 Provider: choose OpenCode or manual/none';
179
179
  if (screen === 'opencode-details')
180
- return 'Step 4/6 OpenCode: scope and install mode';
180
+ return 'Step 4/6 OpenCode: user-global target and install mode';
181
181
  if (screen === 'plan-review')
182
182
  return 'Step 5/6 Review: read-only plan review';
183
183
  if (screen === 'final-confirmation')
@@ -4,7 +4,7 @@ const screenChoiceIds = {
4
4
  welcome: [],
5
5
  'project-database': ['database:global', 'database:project-local', 'database:custom'],
6
6
  provider: ['provider:opencode', 'provider:none'],
7
- 'opencode-details': ['scope:project', 'scope:user', 'install:mcp-plus-agents', 'install:mcp-only', 'overwrite:vgxness'],
7
+ 'opencode-details': ['scope:user', 'install:mcp-plus-agents', 'install:mcp-only', 'overwrite:vgxness'],
8
8
  'plan-review': [],
9
9
  'final-confirmation': [],
10
10
  applying: [],
@@ -126,8 +126,6 @@ function selectFocusedChoice(state) {
126
126
  return reduceSetupTuiState(state, { type: 'select-provider', provider: 'opencode' });
127
127
  case 'provider:none':
128
128
  return reduceSetupTuiState(state, { type: 'select-provider', provider: 'none' });
129
- case 'scope:project':
130
- return reduceSetupTuiState(state, { type: 'select-scope', scope: 'project' });
131
129
  case 'scope:user':
132
130
  return reduceSetupTuiState(state, { type: 'select-scope', scope: 'user' });
133
131
  case 'install:mcp-plus-agents':
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join, relative, resolve } from 'node:path';
3
+ import { providerConfigPathDiagnostics } from './provider-health-types.js';
3
4
  export function resolveClaudeCodeMcpJsonPath(workspaceRoot) {
4
5
  const target = resolve(workspaceRoot, '.mcp.json');
5
6
  assertInsideWorkspace(workspaceRoot, target);
@@ -55,6 +56,7 @@ export function claudeMcpConfigPathStatus(state) {
55
56
  parsed: state.parsed,
56
57
  status: state.status === 'configured' ? 'pass' : state.status === 'invalid' || state.status === 'conflicting' ? 'fail' : 'not-configured',
57
58
  detail: state.message,
59
+ diagnostics: providerConfigPathDiagnostics('external-project', state.exists),
58
60
  };
59
61
  }
60
62
  export function claudeMcpEntryStatus(state) {
@@ -16,3 +16,4 @@ export function resolveClaudeCodeScope(input, fallback = 'project') {
16
16
  export function isClaudeCodeUserScope(scope) {
17
17
  return scope === 'user';
18
18
  }
19
+ export const CLAUDE_CODE_USER_GLOBAL_ONLY_MESSAGE = 'VGX-managed Claude provider configuration is user-global only. Project/local Claude files are treated as external/manual diagnostics and will not be written by VGXNESS. Re-run without the project/local install scope.';
@@ -1,5 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
+ import { providerConfigPathDiagnostics } from './provider-health-types.js';
3
4
  import { isManagedClaudeCodeMcpServer } from './claude-code-config.js';
4
5
  import { safeHomeDirectory } from './claude-code-agent-config.js';
5
6
  export function resolveClaudeCodeUserMcpJsonPath(env = process.env) {
@@ -39,6 +40,7 @@ export function claudeUserMcpConfigPathStatus(state) {
39
40
  parsed: state.parsed,
40
41
  status: state.status === 'configured' ? 'pass' : state.status === 'invalid' || state.status === 'conflicting' ? 'fail' : 'not-configured',
41
42
  detail: state.message,
43
+ diagnostics: providerConfigPathDiagnostics('managed-user-global', state.exists),
42
44
  };
43
45
  }
44
46
  export function claudeUserMcpEntryStatus(state) {
@@ -1,68 +1,23 @@
1
1
  import { withEffectiveManagerInstructions } from '../agents/canonical-agent-projection.js';
2
2
  import { expectedClaudeCodeAgentFiles, inspectClaudeCodeAgents, renderClaudeCodeAgentMarkdown } from './claude-code-agent-config.js';
3
3
  import { buildClaudeCodeMcpAddCommand } from './claude-code-cli.js';
4
- import { createClaudeCodeMcpDoctorCommand, createClaudeCodeMcpServerConfig, inspectClaudeCodeMcpConfig, resolveClaudeCodeMcpJsonPath } from './claude-code-config.js';
5
- import { inspectClaudeProjectMemory } from './claude-code-project-memory.js';
6
- import { resolveClaudeCodeScope } from './claude-code-scope.js';
4
+ import { createClaudeCodeMcpDoctorCommand, createClaudeCodeMcpServerConfig } from './claude-code-config.js';
5
+ import { CLAUDE_CODE_USER_GLOBAL_ONLY_MESSAGE, resolveClaudeCodeScope } from './claude-code-scope.js';
7
6
  import { inspectClaudeCodeUserMcpConfig, resolveClaudeCodeUserMcpJsonPath } from './claude-code-user-config.js';
8
7
  import { inspectClaudeUserMemory } from './claude-code-user-memory.js';
9
8
  export function planClaudeCodeMcpInstall(input) {
10
9
  const source = input.databasePathSource ?? 'flag';
11
10
  const server = createClaudeCodeMcpServerConfig(input.databasePath, source);
12
11
  const overwriteVgxness = input.overwriteVgxness === true;
13
- const resolvedScope = resolveClaudeCodeScope(input.scope);
12
+ const resolvedScope = resolveClaudeCodeScope(input.scope, 'user');
14
13
  if (!resolvedScope.ok)
15
14
  return refused(input, server, 'unsupported_scope', resolvedScope.error.message, [], [], overwriteVgxness);
15
+ if (resolvedScope.value.canonical !== 'user')
16
+ return refused(input, server, 'unsupported_scope', CLAUDE_CODE_USER_GLOBAL_ONLY_MESSAGE, [], [], overwriteVgxness);
16
17
  const cliCommand = buildClaudeCodeMcpAddCommand({ scope: resolvedScope.value.canonical });
17
18
  if (!cliCommand.ok)
18
19
  return refused(input, server, 'unsupported_scope', cliCommand.error.message, [], [], overwriteVgxness);
19
- if (resolvedScope.value.canonical !== 'project') {
20
- if (resolvedScope.value.canonical === 'local') {
21
- const targets = [{ kind: 'cli-mcp-registration', scope: resolvedScope.value.canonical, command: cliCommand.value, action: 'register' }];
22
- return { ...base(input, server, targets, [], false, overwriteVgxness, resolvedScope.value.canonical, cliCommand.value, resolvedScope.value.warnings), status: 'would_install' };
23
- }
24
- return planUserInstall(input, server, overwriteVgxness, cliCommand.value, resolvedScope.value.warnings);
25
- }
26
- let mcpPath;
27
- try {
28
- mcpPath = resolveClaudeCodeMcpJsonPath(input.cwd);
29
- }
30
- catch (cause) {
31
- return refused(input, server, 'outside_workspace', cause instanceof Error ? cause.message : String(cause), [], [], overwriteVgxness);
32
- }
33
- const mcpState = inspectClaudeCodeMcpConfig(input.cwd);
34
- const targets = [];
35
- targets.push({ kind: 'cli-mcp-registration', scope: resolvedScope.value.canonical, command: cliCommand.value, action: 'register' });
36
- const preservedTopLevelKeys = mcpState.parsed ? Object.keys(mcpState.config) : [];
37
- if (mcpState.status === 'missing')
38
- targets.push({ kind: 'mcp-json', path: mcpPath, action: 'create' });
39
- else if (mcpState.status === 'stale')
40
- targets.push({ kind: 'mcp-json', path: mcpPath, action: 'merge' });
41
- else if (mcpState.status === 'configured')
42
- targets.push({ kind: 'mcp-json', path: mcpPath, action: 'update-vgxness' });
43
- else
44
- targets.push({ kind: 'mcp-json', path: mcpPath, action: 'blocked', reason: mcpState.message });
45
- const agentInspection = inspectClaudeCodeAgents(input.cwd);
46
- for (const agent of agentInspection.agents) {
47
- if (agent.status === 'missing')
48
- targets.push({ kind: 'agent-file', path: agent.path, agentName: agent.agentName, scope: 'project', external: false, action: 'create' });
49
- else if (agent.status === 'managed')
50
- targets.push({ kind: 'agent-file', path: agent.path, agentName: agent.agentName, scope: 'project', external: false, action: 'update-vgxness' });
51
- else
52
- targets.push({ kind: 'agent-file', path: agent.path, agentName: agent.agentName, scope: 'project', external: false, action: 'blocked', reason: agent.detail });
53
- }
54
- const projectMemory = inspectClaudeProjectMemory(input.cwd);
55
- targets.push({ kind: 'project-memory', path: projectMemory.path, action: projectMemory.action, status: projectMemory.status, backupRequired: projectMemory.backupRequired, ...(projectMemory.status === 'blocked' ? { reason: projectMemory.message } : {}) });
56
- const blocked = targets.find((target) => target.action === 'blocked');
57
- if (blocked !== undefined) {
58
- const reason = blocked.kind === 'mcp-json' ? mcpRefusalReason(mcpState.status) : blocked.kind === 'project-memory' ? projectMemoryRefusalReason(projectMemory) : 'existing_vgxness_agent';
59
- return refused(input, server, reason, blocked.reason ?? 'Claude Code install plan is blocked by an existing conflicting target.', targets, preservedTopLevelKeys, overwriteVgxness);
60
- }
61
- const backupRequired = targets.some((target) => (target.kind === 'mcp-json' && target.action !== 'create') || (target.kind === 'agent-file' && target.action === 'update-vgxness') || (target.kind === 'project-memory' && target.backupRequired));
62
- return {
63
- ...base(input, server, targets, preservedTopLevelKeys, backupRequired, overwriteVgxness, resolvedScope.value.canonical, cliCommand.value, resolvedScope.value.warnings),
64
- status: 'would_install',
65
- };
20
+ return planUserInstall(input, server, overwriteVgxness, cliCommand.value, resolvedScope.value.warnings);
66
21
  }
67
22
  export function expectedClaudeCodeRenderedAgents(workspaceRoot, options) {
68
23
  const files = expectedClaudeCodeAgentFiles(workspaceRoot);
@@ -116,21 +71,21 @@ function planUserInstall(input, server, overwriteVgxness, cliCommand, scopeWarni
116
71
  return { ...base(input, server, targets, preservedTopLevelKeys, backupRequired, overwriteVgxness, 'user', cliCommand, scopeWarnings), status: 'would_install' };
117
72
  }
118
73
  function refused(input, server, reason, message, targets, preservedTopLevelKeys, overwriteVgxness) {
119
- const resolved = resolveClaudeCodeScope(input.scope);
120
- const canonical = resolved.ok ? resolved.value.canonical : 'project';
121
- const cli = buildClaudeCodeMcpAddCommand({ scope: canonical });
122
- return { ...base(input, server, targets, preservedTopLevelKeys, false, overwriteVgxness, canonical, cli.ok ? cli.value : undefined, resolved.ok ? resolved.value.warnings : []), status: 'refused', reason, message };
74
+ const resolved = resolveClaudeCodeScope(input.scope, 'user');
75
+ const canonical = resolved.ok ? resolved.value.canonical : 'user';
76
+ const cli = canonical === 'user' ? buildClaudeCodeMcpAddCommand({ scope: canonical }) : undefined;
77
+ return { ...base(input, server, targets, preservedTopLevelKeys, false, overwriteVgxness, canonical, cli?.ok ? cli.value : undefined, resolved.ok ? resolved.value.warnings : []), status: 'refused', reason, message };
123
78
  }
124
79
  function base(input, server, targets, preservedTopLevelKeys, backupRequired, overwriteVgxness, canonicalClaudeScope, cliCommand, scopeWarnings) {
125
80
  const source = input.databasePathSource ?? 'flag';
126
- const targetPath = canonicalClaudeScope === 'project' ? resolveClaudeCodeMcpJsonPath(input.cwd) : canonicalClaudeScope === 'user' ? resolveClaudeCodeUserMcpJsonPath(input.env) : `claude-cli:${canonicalClaudeScope}:vgxness`;
81
+ const targetPath = resolveClaudeCodeUserMcpJsonPath(input.env);
127
82
  return {
128
83
  version: 1,
129
84
  kind: 'mcp-client-install-claude-code',
130
85
  installable: true,
131
86
  mutating: false,
132
87
  provider: 'claude',
133
- scope: input.scope ?? 'project',
88
+ scope: input.scope ?? 'user',
134
89
  targetPath,
135
90
  targets,
136
91
  backupRequired,
@@ -138,12 +93,12 @@ function base(input, server, targets, preservedTopLevelKeys, backupRequired, ove
138
93
  warnings: [
139
94
  ...scopeWarnings,
140
95
  'Claude Code MCP registration is modeled as structured config/argv, never shell strings.',
141
- 'Project compatibility may write .mcp.json, .claude/agents/*.md, and a guarded project-root CLAUDE.md managed block after explicit confirmation/preflight.',
96
+ 'VGX-managed Claude provider configuration is user-global only; project/local Claude files are treated as external/manual diagnostics and are not written by VGXNESS.',
142
97
  'Claude user/global support narrowly merges only mcpServers.vgxness in ~/.claude.json and writes VGXNESS-owned ~/.claude/agents/*.md plus a managed block in ~/.claude/CLAUDE.md after confirmation/preflight; unknown config keys and non-managed memory content are preserved.',
143
98
  ],
144
99
  verificationHints: [
145
- { kind: 'restart-client', message: 'Restart or reload Claude Code after confirmed project config installation.' },
146
- { kind: 'manual-check', message: 'Open the project in Claude Code and verify the vgxness MCP server and project agents are visible.' },
100
+ { kind: 'restart-client', message: 'Restart or reload Claude Code after confirmed user-global config installation.' },
101
+ { kind: 'manual-check', message: 'Open Claude Code and verify the vgxness MCP server and user agents are visible.' },
147
102
  { kind: 'command', message: 'Run the MCP doctor command after installation.', command: createClaudeCodeMcpDoctorCommand(input.databasePath, source) },
148
103
  ],
149
104
  server,
@@ -154,13 +109,6 @@ function base(input, server, targets, preservedTopLevelKeys, backupRequired, ove
154
109
  overwriteVgxness,
155
110
  };
156
111
  }
157
- function mcpRefusalReason(status) {
158
- if (status === 'invalid')
159
- return 'malformed_json';
160
- if (status === 'conflicting')
161
- return 'existing_vgxness_mcp';
162
- return 'invalid_mcp_shape';
163
- }
164
112
  function userMcpRefusalReason(status) {
165
113
  if (status === 'invalid')
166
114
  return 'malformed_json';
@@ -168,11 +116,6 @@ function userMcpRefusalReason(status) {
168
116
  return 'existing_vgxness_mcp';
169
117
  return 'invalid_mcp_shape';
170
118
  }
171
- function projectMemoryRefusalReason(state) {
172
- if (state.status === 'blocked' && state.reason === 'conflicting_ownership')
173
- return 'conflicting_claude_project_memory';
174
- return 'malformed_claude_project_memory';
175
- }
176
119
  function userMemoryRefusalReason(state) {
177
120
  if (state.status === 'blocked' && state.reason === 'conflicting_ownership')
178
121
  return 'conflicting_claude_project_memory';
@@ -15,17 +15,15 @@ export async function installClaudeCodeMcpClient(input) {
15
15
  if (plan.status === 'refused')
16
16
  return refusal(plan.reason, plan.message, plan, server, [], []);
17
17
  if (!input.confirmed)
18
- return refusal('confirmation_required', '`mcp install claude` requires explicit --yes before any project config write.', plan, server, [], []);
18
+ return refusal('confirmation_required', '`mcp install claude` requires explicit --yes before any user-global provider config write.', plan, server, [], []);
19
19
  if (input.preflight === undefined) {
20
- return refusal('preflight_failed', 'Claude Code provider config writes require VGXNESS preflight before any project config write.', plan, server, [], []);
20
+ return refusal('preflight_failed', 'Claude Code provider config writes require VGXNESS preflight before any user-global provider config write.', plan, server, [], []);
21
21
  }
22
- const preflightPaths = unique(plan.targets.flatMap((target) => (isMutatingTarget(target) ? [target.path] : [])));
23
- if (plan.canonicalClaudeScope !== 'project')
24
- preflightPaths.unshift(plan.targetPath);
22
+ const preflightPaths = unique([plan.targetPath, ...plan.targets.flatMap((target) => (isMutatingTarget(target) ? [target.path] : []))]);
25
23
  for (const targetPath of preflightPaths) {
26
24
  const preflight = await input.preflight({
27
25
  category: 'provider-tool',
28
- operation: plan.canonicalClaudeScope === 'user' ? 'write claude user provider config' : 'write claude project provider config',
26
+ operation: 'write claude user-global provider config',
29
27
  targetPath,
30
28
  workspaceRoot: input.cwd,
31
29
  providerToolName: 'claude-code',