vgxness 1.10.0 → 1.11.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 (97) hide show
  1. package/README.md +10 -20
  2. package/dist/agents/canonical-agent-manifest.js +2 -2
  3. package/dist/behavior/behavior-contract-manifest.js +1 -3
  4. package/dist/behavior/behavior-contract-validation.js +0 -4
  5. package/dist/cli/cli-help.js +3 -9
  6. package/dist/cli/commands/index.js +2 -2
  7. package/dist/cli/commands/interactive-entrypoint-dispatcher.js +9 -153
  8. package/dist/cli/commands/setup-dispatcher.js +7 -51
  9. package/dist/cli/dispatcher.js +1 -8
  10. package/dist/cli/doctor-renderer.js +1 -1
  11. package/dist/cli/product-status-renderer.js +2 -2
  12. package/dist/cli/sdd-renderer.js +5 -5
  13. package/dist/cli/setup-plan-renderer.js +2 -2
  14. package/dist/cli/setup-status-renderer.js +2 -2
  15. package/dist/mcp/client-install-claude-code.js +3 -2
  16. package/dist/mcp/client-install-opencode.js +3 -2
  17. package/dist/mcp/provider-change-plan.js +8 -8
  18. package/dist/mcp/provider-doctor.js +7 -6
  19. package/dist/mcp/provider-status.js +10 -8
  20. package/dist/runs/execution-planning.js +3 -3
  21. package/dist/sdd/sdd-continuation-plan.js +5 -16
  22. package/dist/sdd/sdd-workflow-service.js +1 -1
  23. package/dist/setup/backup-rollback-service.js +10 -4
  24. package/dist/status/product-status.js +1 -1
  25. package/docs/architecture.md +13 -14
  26. package/docs/cli.md +12 -49
  27. package/docs/contributing.md +18 -3
  28. package/docs/glossary.md +5 -5
  29. package/docs/mcp.md +1 -1
  30. package/docs/prd.md +7 -7
  31. package/docs/project-health-audit-v1.10.x.md +115 -0
  32. package/docs/project-health-audit-v1.9.1.md +2 -0
  33. package/docs/providers.md +9 -37
  34. package/docs/roadmap.md +4 -10
  35. package/docs/safety.md +5 -21
  36. package/docs/storage.md +6 -5
  37. package/package.json +1 -3
  38. package/dist/cli/tui/main-menu/index.js +0 -6
  39. package/dist/cli/tui/main-menu/main-menu-actions.js +0 -34
  40. package/dist/cli/tui/main-menu/main-menu-controller.js +0 -11
  41. package/dist/cli/tui/main-menu/main-menu-read-model.js +0 -75
  42. package/dist/cli/tui/main-menu/main-menu-render-shape.js +0 -46
  43. package/dist/cli/tui/main-menu/main-menu-result.js +0 -1
  44. package/dist/cli/tui/main-menu/main-menu-state.js +0 -21
  45. package/dist/cli/tui/opentui/code/index.js +0 -210
  46. package/dist/cli/tui/opentui/code/screen.js +0 -107
  47. package/dist/cli/tui/opentui/code/smoke.js +0 -32
  48. package/dist/cli/tui/opentui/main-menu/index.js +0 -3
  49. package/dist/cli/tui/opentui/main-menu/renderer.js +0 -68
  50. package/dist/cli/tui/opentui/main-menu/screen.js +0 -66
  51. package/dist/cli/tui/opentui/main-menu/smoke.js +0 -17
  52. package/dist/cli/tui/opentui/main-menu/view.js +0 -8
  53. package/dist/cli/tui/opentui/setup/index.js +0 -3
  54. package/dist/cli/tui/opentui/setup/renderer.js +0 -87
  55. package/dist/cli/tui/opentui/setup/screen.js +0 -170
  56. package/dist/cli/tui/opentui/setup/smoke.js +0 -42
  57. package/dist/cli/tui/opentui/setup/view.js +0 -12
  58. package/dist/cli/tui/setup/setup-tui-actions.js +0 -1
  59. package/dist/cli/tui/setup/setup-tui-controller.js +0 -86
  60. package/dist/cli/tui/setup/setup-tui-input.js +0 -43
  61. package/dist/cli/tui/setup/setup-tui-read-model.js +0 -215
  62. package/dist/cli/tui/setup/setup-tui-render-shape.js +0 -168
  63. package/dist/cli/tui/setup/setup-tui-result.js +0 -1
  64. package/dist/cli/tui/setup/setup-tui-services.js +0 -79
  65. package/dist/cli/tui/setup/setup-tui-state.js +0 -193
  66. package/dist/cli/tui/setup/setup-tui-view-helpers.js +0 -46
  67. package/dist/code/cli/code-command.js +0 -104
  68. package/dist/code/config/defaults.js +0 -108
  69. package/dist/code/prompts/prompt-builder.js +0 -127
  70. package/dist/code/providers/credentials.js +0 -13
  71. package/dist/code/providers/fake-provider-adapter.js +0 -98
  72. package/dist/code/providers/message-mapper.js +0 -73
  73. package/dist/code/providers/openai-compatible-provider-adapter.js +0 -68
  74. package/dist/code/providers/provider-adapter.js +0 -10
  75. package/dist/code/providers/provider-registry.js +0 -38
  76. package/dist/code/providers/stream-normalizer.js +0 -34
  77. package/dist/code/reporting/redaction.js +0 -39
  78. package/dist/code/reporting/summary.js +0 -32
  79. package/dist/code/runtime/approval-coordinator.js +0 -468
  80. package/dist/code/runtime/code-runtime.js +0 -1031
  81. package/dist/code/runtime/gateways.js +0 -143
  82. package/dist/code/runtime/memory-service-gateway.js +0 -20
  83. package/dist/code/runtime/project-detection.js +0 -102
  84. package/dist/code/runtime/runs-code-run-gateway.js +0 -29
  85. package/dist/code/runtime/sdd-context.js +0 -164
  86. package/dist/code/runtime/sdd-workflow-gateway.js +0 -63
  87. package/dist/code/runtime/types.js +0 -1
  88. package/dist/code/runtime/verification-coordinator.js +0 -30
  89. package/dist/code/tools/read-only-executor.js +0 -145
  90. package/dist/code/tools/tool-definitions.js +0 -58
  91. package/dist/code/tools/tool-registry.js +0 -13
  92. package/dist/code/tools/tool-result-normalizer.js +0 -119
  93. package/dist/code/tools/workspace-executor.js +0 -278
  94. package/dist/code/tui/approval-actions.js +0 -33
  95. package/dist/code/tui/prompt-mode.js +0 -11
  96. package/dist/code/tui/runtime-events.js +0 -320
  97. package/docs/code-runtime.md +0 -221
@@ -55,7 +55,7 @@ export async function installOpenCodeMcpClient(input) {
55
55
  });
56
56
  if (conflictingAgents.length > 0 && input.overwriteVgxness !== true)
57
57
  return agentConflictRefusal(conflictingAgents, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.bashPermissionPolicy);
58
- const backup = createBackup(plan.targetPath, plan.scope);
58
+ const backup = createBackup(plan.targetPath, plan.scope, input.env?.HOME);
59
59
  if (!backup.ok)
60
60
  return refusal('post_write_validation_failed', backup.error.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
61
61
  const config = parsed.value;
@@ -97,7 +97,7 @@ function writeConfig(path, config) {
97
97
  mkdirSync(dirname(path), { recursive: true });
98
98
  writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`);
99
99
  }
100
- function createBackup(path, scope) {
100
+ function createBackup(path, scope, allowedManagedHome) {
101
101
  return createManagedProviderConfigBackup({
102
102
  targetPath: path,
103
103
  provider: 'opencode',
@@ -105,6 +105,7 @@ function createBackup(path, scope) {
105
105
  createdByOperation: 'mcp-client-install-opencode',
106
106
  reason: 'pre-merge-safety',
107
107
  description: 'Backup existing OpenCode config before merging VGXNESS MCP configuration.',
108
+ ...(allowedManagedHome !== undefined ? { allowedManagedHome } : {}),
108
109
  });
109
110
  }
110
111
  function validateInstalledResult(targetPath, backup, server, databasePath, source, safety, verificationHints, warningMessages, manualTestGuidance, agentPlan, overwriteVgxness = false, bashPermissionPolicy = bashPermissionPolicyFor(agentPlan)) {
@@ -100,7 +100,7 @@ function unsupportedProviderEnvelope(input) {
100
100
  supported: false,
101
101
  status: 'unsupported',
102
102
  code: 'UNSUPPORTED_PROVIDER',
103
- summary: `${input.provider} is a recognized provider value, but read-only provider change planning currently supports OpenCode and Claude.`,
103
+ summary: `[read-only] ${input.provider} is a recognized provider value, but provider change planning currently supports OpenCode and Claude. No provider config was written. This diagnostic does not install or repair provider config.`,
104
104
  providerIdentity: {
105
105
  provider: input.provider,
106
106
  adapter: input.provider,
@@ -114,7 +114,7 @@ function unsupportedProviderEnvelope(input) {
114
114
  backupRollback: descriptiveBackupPolicy(false),
115
115
  confirmations: confirmationPolicy(),
116
116
  risks: ['No provider-specific change preview is available for this provider yet.'],
117
- warnings: ['Known provider enum value is unsupported by this read-only planner.'],
117
+ warnings: ['Known provider enum value is unsupported by this read-only planner. No files were written.'],
118
118
  };
119
119
  }
120
120
  function blockedPlanEnvelope(input, status, doctor, message) {
@@ -124,7 +124,7 @@ function blockedPlanEnvelope(input, status, doctor, message) {
124
124
  supported: true,
125
125
  status: 'blocked',
126
126
  code: 'PLAN_UNAVAILABLE',
127
- summary: `${providerName} change planning could not resolve the future MCP server command: ${message}`,
127
+ summary: `[read-only] ${providerName} change planning could not resolve the future MCP server command: ${message}. No provider config was written. This diagnostic does not install or repair provider config.`,
128
128
  providerIdentity: {
129
129
  provider: input.provider,
130
130
  adapter: input.provider,
@@ -143,7 +143,7 @@ function blockedPlanEnvelope(input, status, doctor, message) {
143
143
  backupRollback: descriptiveBackupPolicy(false),
144
144
  confirmations: confirmationPolicy(),
145
145
  risks: ['Future write planning requires a resolvable VGXNESS database path.'],
146
- warnings: [message],
146
+ warnings: [message, 'No files were written.'],
147
147
  };
148
148
  }
149
149
  function opencodeEnvelope(input, status, doctor, installPlan, source) {
@@ -185,7 +185,7 @@ function claudeEnvelope(input, status, doctor, installPlan, source) {
185
185
  supported: true,
186
186
  status: installPlan.status === 'refused' ? 'blocked' : 'planned',
187
187
  ...(installPlan.status === 'refused' ? { code: 'PLAN_UNAVAILABLE' } : {}),
188
- summary: installPlan.status === 'refused' ? `Read-only Claude ${input.changeType} planning completed; future install is currently refused: ${installPlan.message}` : 'Read-only Claude planning completed; future confirmed write would update ~/.claude.json, user agents, and ~/.claude/CLAUDE.md as needed. Project/local Claude files are diagnostics only.',
188
+ summary: installPlan.status === 'refused' ? `[read-only] Claude ${input.changeType} planning completed; future install is currently refused: ${installPlan.message}. No provider config was written. This diagnostic does not install or repair provider config.` : '[read-only] Claude planning completed. No provider config was written. This diagnostic does not install or repair provider config. A future confirmed write would update ~/.claude.json, user agents, and ~/.claude/CLAUDE.md as needed. Project/local Claude files are diagnostics only.',
189
189
  providerIdentity: { provider: 'claude', adapter: 'claude', support: 'supported' },
190
190
  statusSummary: statusSummary(status),
191
191
  statusFindings: status.config,
@@ -307,7 +307,7 @@ function confirmationPolicy() {
307
307
  requiredNow: false,
308
308
  requiredBeforeFutureWrite: true,
309
309
  acceptedMutationInputs: false,
310
- message: 'This response is read-only; any future provider config write must be requested and confirmed separately.',
310
+ message: '[read-only] No provider config was written. Any future provider config write must be requested and confirmed separately.',
311
311
  };
312
312
  }
313
313
  function statusWarnings(status) {
@@ -339,6 +339,6 @@ function risksForClaude(status, doctor, plan, source) {
339
339
  }
340
340
  function summaryForOpenCode(input, plan) {
341
341
  if (plan.status === 'refused')
342
- return `Read-only OpenCode ${input.changeType} planning completed; future install is currently refused: ${plan.message}`;
343
- return `Read-only OpenCode ${input.changeType} planning completed; future confirmed write would ${plan.action} ${plan.targetPath}.`;
342
+ return `[read-only] OpenCode ${input.changeType} planning completed; future install is currently refused: ${plan.message}. No provider config was written. This diagnostic does not install or repair provider config.`;
343
+ return `[read-only] OpenCode ${input.changeType} planning completed. No provider config was written. This diagnostic does not install or repair provider config. A future confirmed write would ${plan.action} ${plan.targetPath}.`;
344
344
  }
@@ -174,15 +174,16 @@ function managedUserGlobalClassification(paths) {
174
174
  return { managedUserGlobalConfig: [...paths], detectedExternalProjectConfig: [], detectedExternalUserConfig: [] };
175
175
  }
176
176
  function summarizeDoctor(status, failedCount, recommendationCount) {
177
+ const suffix = '[read-only] No provider config was written. This diagnostic does not install or repair provider config.';
177
178
  if (status === 'healthy')
178
- return 'Provider doctor checks passed; no configuration was changed.';
179
+ return `Provider doctor checks passed. ${suffix}`;
179
180
  if (status === 'degraded')
180
- return `Provider doctor found warnings and ${recommendationCount} recommendation(s); no configuration was changed.`;
181
+ return `Provider doctor found warnings and ${recommendationCount} recommendation(s). ${suffix}`;
181
182
  if (status === 'failed')
182
- return `Provider doctor found ${failedCount} failed check(s); no configuration was changed.`;
183
+ return `Provider doctor found ${failedCount} failed check(s). ${suffix}`;
183
184
  if (status === 'skipped')
184
- return 'Provider doctor checks were skipped.';
185
- return 'Provider doctor status is unknown; review checks before continuing.';
185
+ return `Provider doctor checks were skipped. ${suffix}`;
186
+ return `Provider doctor status is unknown; review checks before continuing. ${suffix}`;
186
187
  }
187
188
  function compactChecks(checks, mode) {
188
189
  if (mode === 'verbose')
@@ -280,7 +281,7 @@ function readonlySafetyCheck(before, after) {
280
281
  ? {
281
282
  id: 'provider-config-readonly-safety',
282
283
  status: 'pass',
283
- detail: 'Provider config path existence and mtimes were unchanged; no repair/install/write occurred.',
284
+ detail: '[read-only] Provider config path existence and mtimes were unchanged. No files were written. This diagnostic does not install or repair provider config.',
284
285
  }
285
286
  : { id: 'provider-config-readonly-safety', status: 'fail', detail: 'Provider config path existence or mtimes changed during read-only doctor.' };
286
287
  }
@@ -354,22 +354,24 @@ function hasProjectConfigAlongsideUser(paths) {
354
354
  return paths.some((path) => path.label.startsWith('user ') && path.exists) && paths.some((path) => !path.label.startsWith('user ') && path.exists);
355
355
  }
356
356
  function summarizeStatus(status, mcpEntry) {
357
+ const suffix = '[read-only] No provider config was written. This diagnostic does not install or repair provider config.';
357
358
  if (status === 'ready')
358
- return 'OpenCode provider config is readable and the vgxness MCP entry is present.';
359
+ return `OpenCode provider config is readable and the vgxness MCP entry is present. ${suffix}`;
359
360
  if (status === 'not-configured')
360
- return mcpEntry.detail;
361
+ return `${mcpEntry.detail} ${suffix}`;
361
362
  if (status === 'warning')
362
- return 'OpenCode provider config has warnings; no changes were made.';
363
- return 'OpenCode provider status check found a blocking issue; no changes were made.';
363
+ return `OpenCode provider config has warnings. ${suffix}`;
364
+ return `OpenCode provider status check found a blocking issue. ${suffix}`;
364
365
  }
365
366
  function summarizeClaudeStatus(status, mcpEntry) {
367
+ const suffix = '[read-only] No provider config was written. This diagnostic does not install or repair provider config.';
366
368
  if (status === 'ready')
367
- return 'Claude project .mcp.json and VGXNESS agent files are readable and configured.';
369
+ return `Claude provider files were inspected and VGXNESS entries are readable. ${suffix}`;
368
370
  if (status === 'not-configured')
369
- return mcpEntry.detail;
371
+ return `${mcpEntry.detail} ${suffix}`;
370
372
  if (status === 'warning')
371
- return 'Claude provider project config has warnings; no changes were made.';
372
- return 'Claude provider status check found a blocking issue; no changes were made.';
373
+ return `Claude provider project config has warnings. ${suffix}`;
374
+ return `Claude provider status check found a blocking issue. ${suffix}`;
373
375
  }
374
376
  function nextActionFor(status, mcpEntry, sddNext) {
375
377
  if (sddNext !== undefined)
@@ -79,11 +79,11 @@ function conditionRequirements(operation, decision, realpathHardeningRequired, s
79
79
  return conditions;
80
80
  }
81
81
  function planLimitations(operation, decision, strategy, sandbox) {
82
- const limitations = ['planning-only: no command, provider tool, worktree, sandbox, directory, or filesystem mutation is performed'];
82
+ const limitations = ['planning-only: this preflight records an execution plan only; no command, provider tool, worktree, sandbox, directory, or filesystem mutation was performed'];
83
83
  if (strategy === 'worktree')
84
- limitations.push('worktree is a planned isolation target only; creation is future executor work');
84
+ limitations.push('worktree is only the planned isolation target; no worktree was created and mutations still require a separate executor or manual worktree');
85
85
  if (strategy === 'process-sandbox')
86
- limitations.push('process-sandbox is a planned isolation target only; launch/enforcement is future executor work');
86
+ limitations.push('process-sandbox is only the planned isolation target; no sandbox was launched and execution still requires a separate executor');
87
87
  if (decision.decision === 'deny')
88
88
  limitations.push(`permission policy denies execution: ${decision.reason}`);
89
89
  if (sandbox?.decision === 'rejected')
@@ -4,8 +4,7 @@ export function sddContinuationPlanFrom(input) {
4
4
  const inspectCommand = `vgxness sdd cockpit --project ${input.project} --change ${input.next.change} --json${dbFlag}`;
5
5
  const suggestedCommand = suggestedContinuationCommand(input.project, input.next, inspectCommand, dbFlag);
6
6
  const blockerGuidance = input.next.blockerGuidance ?? [];
7
- const blockerActions = blockerGuidance.map((blocker) => continuationBlockerAction(input.project, input.next.change, input.next.nextPhase, blocker, dbFlag));
8
- const hasDraftRunAction = blockerActions.some((action) => action.draftRunCommand !== undefined);
7
+ const blockerActions = blockerGuidance.map((blocker) => continuationBlockerAction(input.project, input.next.change, blocker, dbFlag));
9
8
  const relatedRunContext = relatedRunContextView(input.project, input.relatedRunContext, dbFlag);
10
9
  return {
11
10
  kind: 'sdd-continuation-plan',
@@ -24,7 +23,7 @@ export function sddContinuationPlanFrom(input) {
24
23
  safety: [
25
24
  'Read-only planner: this command does not execute providers or mutate SDD artifacts, runs, provider config, or openspec/ files.',
26
25
  'Human acceptance remains explicit; artifact presence is not treated as acceptance.',
27
- ...(hasDraftRunAction ? [draftRunWarning()] : []),
26
+ 'Continue SDD phases in OpenCode conversation through VGXNESS MCP and hidden SDD subagents; the removed code runtime is not a CLI fallback.',
28
27
  'No openspec/ files are created or written.',
29
28
  ],
30
29
  };
@@ -43,15 +42,13 @@ function suggestedContinuationCommand(project, next, fallbackInspectCommand, dbF
43
42
  return runPhaseCommand(project, next.change, next.nextPhase, dbFlag);
44
43
  return fallbackInspectCommand;
45
44
  }
46
- function continuationBlockerAction(project, change, blockedPhase, blocker, dbFlag) {
47
- const draftRunCommand = blocker.reason === 'draft' && isDraftRunPlanningPhase(blockedPhase) ? draftRunPhaseCommand(project, change, blockedPhase, dbFlag) : undefined;
45
+ function continuationBlockerAction(project, change, blocker, dbFlag) {
48
46
  return {
49
47
  phase: blocker.phase,
50
48
  topicKey: blocker.topicKey,
51
49
  reason: blocker.reason,
52
50
  action: blocker.action,
53
51
  command: blockerCommand(project, change, blocker, dbFlag),
54
- ...(draftRunCommand === undefined ? {} : { draftRunCommand, warning: draftRunWarning() }),
55
52
  ...(blocker.artifactId === undefined ? {} : { artifactId: blocker.artifactId }),
56
53
  };
57
54
  }
@@ -65,16 +62,8 @@ function blockerCommand(project, change, blocker, dbFlag) {
65
62
  return `vgxness sdd get-artifact --project ${project} --change ${change} --phase ${blocker.phase} --json${dbFlag}`;
66
63
  }
67
64
  function runPhaseCommand(project, change, phase, dbFlag) {
68
- return `vgxness code sdd ${change} ${phase} --project ${project} --save-artifact${dbFlag}`;
69
- }
70
- function draftRunPhaseCommand(project, change, phase, dbFlag) {
71
- return `vgxness code sdd ${change} ${phase} --project ${project} --draft-run --save-artifact${dbFlag}`;
72
- }
73
- function isDraftRunPlanningPhase(phase) {
74
- return phase === 'explore' || phase === 'proposal' || phase === 'spec' || phase === 'design' || phase === 'tasks';
75
- }
76
- function draftRunWarning() {
77
- return 'Draft-run is planning-only; human acceptance is still required; apply-progress remains gated.';
65
+ void phase;
66
+ return `vgxness sdd continue --project ${project} --change ${change}${dbFlag}`;
78
67
  }
79
68
  function continuationDbFlag(explicitDatabasePath) {
80
69
  return explicitDatabasePath === undefined ? '' : ` --db ${explicitDatabasePath}`;
@@ -644,7 +644,7 @@ function blockerActionForBlocker(blocker, blockedPhase) {
644
644
  return `Run or create the ${blocker.phase} SDD phase artifact at ${blocker.topicKey}`;
645
645
  case 'draft':
646
646
  if (blockedPhase !== undefined && isDraftRunPlanningPhase(blockedPhase))
647
- return `Accept ${blocker.topicKey} if it is ready, or intentionally continue planning ${blockedPhase} with --draft-run; draft-run is planning-only, human acceptance is still required, and apply-progress remains gated`;
647
+ return `Accept ${blocker.topicKey} if it is ready, or continue planning ${blockedPhase} in OpenCode with VGXNESS MCP after explicitly acknowledging that human acceptance is still required and apply-progress remains gated`;
648
648
  return `Accept ${blocker.topicKey}, or continue and re-run the ${blocker.phase} phase if the draft is incomplete`;
649
649
  case 'accepted':
650
650
  return `Inspect ${blocker.topicKey}; it is marked accepted but still appears in blocker data`;
@@ -10,6 +10,9 @@ export function createManagedProviderConfigBackup(input) {
10
10
  const readable = validateReadableFile(targetPath, 'target');
11
11
  if (!readable.ok)
12
12
  return readable;
13
+ const rollbackTargetBlocker = validateProviderRollbackTarget(targetPath, input.allowedManagedHome);
14
+ if (rollbackTargetBlocker !== undefined)
15
+ return { ok: false, error: { code: 'validation_failed', message: rollbackTargetBlocker } };
13
16
  const provider = input.provider ?? 'opencode';
14
17
  const createdAt = (input.now ?? new Date()).toISOString();
15
18
  const timestamp = createdAt.replaceAll(/[-:.]/g, '');
@@ -250,14 +253,14 @@ function validateMetadataBinding(backupPath, metadata) {
250
253
  blockers.push(rollbackTargetBlocker);
251
254
  return { blockers, warnings };
252
255
  }
253
- function validateProviderRollbackTarget(targetPath) {
256
+ function validateProviderRollbackTarget(targetPath, allowedManagedHome) {
254
257
  const normalizedTarget = resolve(targetPath);
255
- if (isManagedUserGlobalProviderTarget(normalizedTarget))
258
+ if (isManagedUserGlobalProviderTarget(normalizedTarget, allowedManagedHome))
256
259
  return undefined;
257
260
  return `Refusing to restore provider config backup to ${normalizedTarget}. VGX-managed provider rollback writes user-global OpenCode/Claude targets only; project-local provider files are external/manual diagnostics and will not be restored.`;
258
261
  }
259
- function isManagedUserGlobalProviderTarget(targetPath) {
260
- const home = resolve(homedir());
262
+ function isManagedUserGlobalProviderTarget(targetPath, allowedManagedHome) {
263
+ const home = resolveManagedHome(allowedManagedHome);
261
264
  if (targetPath === resolve(home, '.config', 'opencode', 'opencode.json'))
262
265
  return true;
263
266
  if (targetPath === resolve(home, '.claude.json'))
@@ -267,6 +270,9 @@ function isManagedUserGlobalProviderTarget(targetPath) {
267
270
  const claudeAgentsRoot = resolve(home, '.claude', 'agents');
268
271
  return isPathInside(claudeAgentsRoot, targetPath) && dirname(targetPath) === claudeAgentsRoot && basename(targetPath).endsWith('.md');
269
272
  }
273
+ function resolveManagedHome(allowedManagedHome) {
274
+ return resolve(typeof allowedManagedHome === 'string' && allowedManagedHome.trim().length > 0 ? allowedManagedHome : homedir());
275
+ }
270
276
  function isPathInside(parentPath, candidatePath) {
271
277
  const relation = relative(parentPath, candidatePath);
272
278
  return relation === '' || (relation !== '' && !relation.startsWith('..') && !isAbsolute(relation));
@@ -65,7 +65,7 @@ function resolveProject(input) {
65
65
  function fromSddCockpit(cockpit, project, baseSafety, relatedRunContext) {
66
66
  const nextLabel = cockpit.next.nextPhase === undefined ? cockpit.next.status : `${cockpit.next.status} / ${cockpit.next.nextPhase}`;
67
67
  const command = cockpit.next.status === 'runnable' && cockpit.next.nextPhase !== undefined
68
- ? `vgxness code sdd ${cockpit.change} ${cockpit.next.nextPhase} --project ${cockpit.project} --save-artifact`
68
+ ? `vgxness sdd continue --project ${cockpit.project} --change ${cockpit.change}`
69
69
  : `vgxness sdd cockpit --project ${cockpit.project} --change ${cockpit.change} --json`;
70
70
  return {
71
71
  version: 1,
@@ -1,12 +1,12 @@
1
1
  # vgxness Architecture
2
2
 
3
- > **Scope:** this document describes the v1.5.1 architecture as it is actually built. It is the source of truth for how the product works today. Planned work that is not yet shipped lives in [Roadmap](./roadmap.md); historical planning context that no longer reflects reality has been retired. Where this doc disagrees with code, code wins — file a doc-sync task against the relevant module.
3
+ > **Scope:** this document describes the current v1.10.x architecture as it is actually built. It is the source of truth for how the product works today, with the latest health snapshot captured in [Project health audit v1.10.x](./project-health-audit-v1.10.x.md). Planned work that is not yet shipped lives in [Roadmap](./roadmap.md); historical planning context that no longer reflects reality has been retired. Where this doc disagrees with code, code wins — file a doc-sync task against the relevant module.
4
4
 
5
5
  `vgxness` is a local-first, provider-agnostic, Gentle-AI-like harness for agentic development. Its core architecture separates the product domain from provider-specific tooling so agents, skills, memory, SDD workflows, runs, and traces can work across OpenCode, Claude Code, and future adapters such as Pi.
6
6
 
7
- The architectural goal is not only to install better prompts or agent configs. `vgxness` combines an ecosystem configurator with a runtime control plane and a native code runtime: configured agents may execute the work, the control plane keeps explicit state for phase readiness, artifacts, runs, approvals, checkpoints, and audit evidence, and the code runtime performs bounded agentic work in the local workspace with explicit permission decisions.
7
+ The architectural goal is not only to install better prompts or agent configs. `vgxness` combines an ecosystem configurator with a runtime control plane: configured agents may execute the work, and the control plane keeps explicit state for phase readiness, artifacts, runs, approvals, checkpoints, and audit evidence.
8
8
 
9
- The user-facing shape is deliberately four-surface: **MCP for agents**, **CLI for scriptable operator control**, **TUI for guided setup and visual local operations**, and **code runtime (`vgxness code`)** for bounded agentic work in the workspace. All four call the same core services instead of reimplementing workflow rules.
9
+ The user-facing shape is deliberately provider-native: **MCP for agents** and **CLI for scriptable operator control**, with TUI/setup work deferred. The experimental `vgxness code` runtime and principal OpenTUI code surface were removed temporarily.
10
10
 
11
11
  ## Architecture decision summary
12
12
 
@@ -16,9 +16,9 @@ The user-facing shape is deliberately four-surface: **MCP for agents**, **CLI fo
16
16
  | Reference model | Similar product surface to Gentle-AI/`gentle-pi`: agent setup, SDD orchestration, memory wiring, skills, profiles, permissions, verification. |
17
17
  | Differentiator | Verifiable runtime state engine: SDD phases, artifacts, runs, approvals, checkpoints, and audit trails are queryable product state, not prompt-only convention. |
18
18
  | Core workflow | SDD-first canonical state: explore → proposal → spec → design → tasks → apply-progress → verify → archive. |
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. |
19
+ | Interfaces | MCP server for AI tools and CLI for automation/power users. The experimental `vgxness code` runtime and principal OpenTUI code surface are temporarily unavailable. |
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/default supported provider; Claude Code is supported secondary for user-global CLI MCP registration, direct user `~/.claude.json` MCP merge, and VGXNESS-owned user agent/memory files. VGX-managed OpenCode and Claude provider configuration is user-global only. Project-local provider files are external/manual diagnostics that may still affect providers externally, but VGXNESS does not repair, write, back up, or delete them. Read-only status/doctor/change-plan never execute providers. 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`. |
21
+ | Provider strategy | Provider-agnostic domain model with OpenCode as the primary/default supported provider; Claude Code is supported secondary for user-global CLI MCP registration, direct user `~/.claude.json` MCP merge, and VGXNESS-owned user agent/memory files. VGX-managed OpenCode and Claude provider configuration is user-global only. Project-local provider files are external/manual diagnostics that may still affect providers externally, but VGXNESS does not repair, write, back up, or delete them. Read-only status/doctor/change-plan never execute providers. Pi/`gentle-pi` compatibility is a future adapter/reference target. |
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. |
@@ -474,7 +474,7 @@ The checked-in OpenCode default config and `seeds/agents/agent-seed-v1.json` def
474
474
 
475
475
  ## Run lifecycle
476
476
 
477
- A run is the core unit of execution. Run records are stored locally in SQLite and stay provider-neutral. The lifecycle is complete in v1.5.1:
477
+ A run is the core unit of execution. Run records are stored locally in SQLite and stay provider-neutral. The lifecycle is complete in the current architecture:
478
478
 
479
479
  ```text
480
480
  created → planned → running → needs-human
@@ -501,16 +501,16 @@ Timeline events store audit entries such as tool calls, permission decisions, ap
501
501
 
502
502
  Current operation enforcement is safe-by-default and executor-injected: `RunService.executeOperation(...)` evaluates permission, records the `permission-decision`, then either blocks or calls the supplied `RunOperationExecutor`.
503
503
 
504
- Execution isolation is currently **planning-only**. `planExecutionIsolation(...)` and `RunService.planOperationExecution(...)` produce an auditable plan before any real executor exists; they do not create worktrees, launch sandboxes, run shell commands, call providers, or mutate files.
504
+ Execution isolation is currently **planning-only**. `planExecutionIsolation(...)` and `RunService.planOperationExecution(...)` produce an auditable plan before any real executor exists; they do not create worktrees, launch sandboxes, run shell commands, call providers, or mutate files. Treat `strategy: "worktree"` as a recommended future/manual isolation boundary, not proof that isolation has already happened.
505
505
 
506
506
  | Operation shape | Current planned strategy | Current behavior |
507
507
  |---|---|---|
508
508
  | In-workspace read | `workspace` | Allowed when permission policy allows it; filesystem plans require realpath/symlink hardening before any future execution. |
509
- | Edit, git, destructive mutation | `git-worktree` | Planned as isolated mutation work, but still asks/blocks according to permission policy. No worktree is created yet. |
510
- | Shell, network, provider tool, privileged operation | `process-sandbox` | Planned as sandboxed process/provider work, but approval is still required by default. No sandbox is launched yet. |
509
+ | Edit, git, destructive mutation | `git-worktree` | Planned as isolated mutation work, but still asks/blocks according to permission policy. No worktree is created yet; mutation still happens in the current checkout unless a human or future executor creates a separate worktree first. |
510
+ | Shell, network, provider tool, privileged operation | `process-sandbox` | Planned as sandboxed process/provider work, but approval is still required by default. No sandbox is launched yet; execution requires a separate executor with enforceable sandbox evidence. |
511
511
  | External directory or out-of-workspace path | `process-sandbox` or blocked workspace plan | Denied by default or requires explicit stronger future approval conditions; external paths are not allowed by current plans. |
512
512
 
513
- Every plan includes path constraints, required approvals/conditions, whether realpath hardening must happen before execution, and limitations that state the future boundary. Real sandbox/worktree executors are follow-up work after this planner is connected to a safe execution backend.
513
+ Every plan includes path constraints, required approvals/conditions, whether realpath hardening must happen before execution, and limitations that state the future boundary. Real sandbox/worktree executors are follow-up work after this planner is connected to a safe execution backend. Until then, large or risky edits should use a human-created branch/worktree and PR flow.
514
514
 
515
515
  | Decision | Current behavior |
516
516
  |---|---|
@@ -619,17 +619,17 @@ Current foundation API: `evaluatePermission(request)` in `src/permissions/policy
619
619
  - destructive, external, privileged, or ambiguous requests require ask even when an agent override would otherwise allow the category
620
620
  - workspace boundary denials cannot be relaxed by agent/subagent overrides
621
621
 
622
- The code runtime layers a second, finer-grained decision on top of the policy evaluator: per-tool definitions declare whether a tool is `read`, `confirm`, or `restricted`; `PolicyApprovalBroker`, `StdioApprovalBroker`, and `ConservativePermissionGateway` (in `src/code/runtime/approval-coordinator.ts`) wire approval prompts to the runtime event stream. See [Code runtime](./code-runtime.md) for the workspace-side contract.
622
+ The experimental code runtime layer was removed. Current risky side effects are governed through the policy evaluator, run preflight, SDD phase permissions, and explicit setup confirmation.
623
623
 
624
624
  ## Interface surface (current)
625
625
 
626
626
  CLI surface groups are documented in [CLI reference](./cli.md). The plural form is canonical — singular shortcuts are not added.
627
627
 
628
- MCP tools mirror the same core services for agent use. The full, current list of 41 tools is in [MCP tools](./mcp.md) and `SUPPORTED_VGX_MCP_TOOL_NAMES` (`src/mcp/schema.ts`); treat that array as the source of truth. The CLI and TUI are human/operator control surfaces. MCP is the agent-facing control surface. Provider integrations and the code runtime sit on the execution plane.
628
+ MCP tools mirror the same core services for agent use. The full, current list of 41 tools is in [MCP tools](./mcp.md) and `SUPPORTED_VGX_MCP_TOOL_NAMES` (`src/mcp/schema.ts`); treat that array as the source of truth. The CLI is the human/operator control surface. MCP is the agent-facing control surface.
629
629
 
630
630
  ## Evaluation strategy
631
631
 
632
- Minimum eval/test targets (asserted through `node:test` files under `test/`, totaling 95 files as of v1.5.1):
632
+ Minimum eval/test targets, asserted through `node:test` files under `test/`:
633
633
 
634
634
  - Agent resolution selects the expected agent (`test/agents/agent-resolver.test.ts`).
635
635
  - Skill resolution injects the expected skill (`test/skills/`).
@@ -640,7 +640,6 @@ Minimum eval/test targets (asserted through `node:test` files under `test/`, tot
640
640
  - Run resume restores expected run state and respects retry policies (`test/runs/`).
641
641
  - Skill improvement proposals are versioned and require approval (`test/skills/`).
642
642
  - MCP tools call the same core services as CLI/TUI and return actionable blocked states (`test/mcp/`).
643
- - Code runtime behavior across inspect, plan, craft-preview, and craft modes (`test/code/`).
644
643
  - OpenCode config rendering and drift detection (`test/mcp/opencode-agent-config-drift.test.ts`).
645
644
  - Installation dry-run reports the exact provider config changes before mutation.
646
645
 
package/docs/cli.md CHANGED
@@ -53,8 +53,8 @@ Recommended bootstrap and diagnostic flow after `npm install -g vgxness`:
53
53
 
54
54
  ```bash
55
55
  vgxness --help
56
- vgxness # OpenTUI main menu in a TTY; static safe setup guidance in CI/non-TTY
57
- vgxness init # setup wizard in a TTY; read-only plan in CI/non-TTY
56
+ vgxness # static safe guidance; no DB open, provider write, or OpenTUI import
57
+ vgxness init # read-only setup plan unless --yes is provided
58
58
  vgxness setup plan # human-readable, read-only plan
59
59
  vgxness setup status # human-readable, read-only setup status
60
60
  vgxness setup apply --yes # writes OpenCode config only after explicit consent
@@ -70,7 +70,7 @@ Daily SDD phase progression is OpenCode-first: talk to OpenCode with the VGXNESS
70
70
 
71
71
  `setup plan`, `setup status`, and non-TTY `init` planning do not write provider config. Local VGXNESS store initialization may occur when the selected SQLite store is needed. They are human-readable by default; pass `--json` when you need parseable automation output. With the default global database, the OpenCode MCP command is `vgxness mcp start`; for custom/project-local DBs it includes `--db <path>`. The default and only VGX-managed OpenCode target is `$HOME/.config/opencode/opencode.json`; Claude managed targets are user-global (`~/.claude.json`, `~/.claude/agents/*.md`, and `~/.claude/CLAUDE.md`). `setup apply --yes` is the explicit provider-config write path. `setup rollback --backup <path>` validates a VGXNESS/OpenCode backup such as `opencode.json.backup-<timestamp>`, creates a pre-rollback backup of the current user-global target when present, restores the selected backup byte-for-byte, and recommends `vgxness doctor`.
72
72
 
73
- `vgxness init` prompts in English when stdin/stdout are TTYs: project name, DB location, provider, user-global provider target, install mode, then shows the plan and asks `Apply this setup? Type "yes" to continue:`. Any answer other than `yes` exits successfully without writes. In CI/non-TTY without `--yes`, `init` returns the read-only plan and never waits for input. `vgxness doctor`, `vgxness sdd status`, `vgxness sdd next`, `vgxness sdd cockpit`, `vgxness sdd get-artifact`, and `vgxness sdd list-artifacts` are also human-readable by default; use `--json` for scripts.
73
+ `vgxness init` returns the read-only setup plan by default, including in interactive terminals. It applies only when `--yes` is provided, preserving the same explicit confirmation path as `vgxness setup apply --yes`. `vgxness doctor`, `vgxness sdd status`, `vgxness sdd next`, `vgxness sdd cockpit`, `vgxness sdd get-artifact`, and `vgxness sdd list-artifacts` are also human-readable by default; use `--json` for scripts.
74
74
 
75
75
  `vgxness sdd cockpit --json` returns the same additive compatibility shape as the MCP cockpit: all existing raw `SddCockpit` top-level fields remain present, with an additional top-level `readModel`. The cockpit is read-only and metadata-only: it does not include artifact bodies, infer acceptance from artifact presence, advance phases, execute acceptance, call providers, or write provider config. Text output renders from read-model concepts such as next action, phase metadata, blockers, guidance, and `Content included: no`.
76
76
 
@@ -87,7 +87,7 @@ Use OpenCode conversation + VGXNESS MCP + hidden SDD subagents for normal daily
87
87
 
88
88
  Without `--change`, `--project`, or `--run-id`, these commands stay orientation-only and do not open the local memory store. With a selected change, project, or run, top-level `status`, `next`, and `resume` inspect SQLite read-only; formal `sdd` commands are non-provider, non-run-executing planning/artifact commands that may use the normal local store path. Pass `--json` for automation.
89
89
 
90
- The usual SDD operator loop happens inside OpenCode: continue the phase in conversation while VGXNESS MCP and hidden SDD subagents inspect readiness, persist artifacts, and report evidence. CLI commands remain fallback/recovery tools: inspect `status`, ask `next`, run `sdd continue` for a copyable manual continuation plan, then either run `vgxness code sdd ...` as an explicit fallback or `vgxness resume ...` for interrupted work. After a draft is ready, use `sdd accept-artifact` for explicit human acceptance; if an artifact was rejected, use `sdd reopen-artifact` before revising it. Related interrupted run hints in `status`, `next`, and `sdd continue` are advisory only; they help avoid duplicate work but do not retry or execute runs.
90
+ The usual SDD operator loop happens inside OpenCode: continue the phase in conversation while VGXNESS MCP and hidden SDD subagents inspect readiness, persist artifacts, and report evidence. CLI commands remain fallback/recovery tools: inspect `status`, ask `next`, run `sdd continue` for a read-only continuation plan, or run `vgxness resume ...` for interrupted work. After a draft is ready, use `sdd accept-artifact` for explicit human acceptance; if an artifact was rejected, use `sdd reopen-artifact` before revising it. Related interrupted run hints in `status`, `next`, and `sdd continue` are advisory only; they help avoid duplicate work but do not retry or execute runs.
91
91
 
92
92
  ## Bun-first repository verification
93
93
 
@@ -232,17 +232,17 @@ The checked-in agent seed is currently a repository development asset. It is not
232
232
 
233
233
  `opencode preview` returns a combined, preview-only injection envelope for future OpenCode/MCP/hook callers. It does **not** execute OpenCode, install hooks or MCP servers, create runs, record skill usage, or write provider config.
234
234
 
235
- ## OpenTUI main menu
235
+ ## Principal entrypoint
236
236
 
237
- Use no arguments in a TTY to open the main menu from a checkout:
237
+ Use no arguments from a checkout to print static safe guidance:
238
238
 
239
239
  ```bash
240
240
  bun run cli:bun --
241
241
  ```
242
242
 
243
- The installed `vgxness`/`vgx` binary opens the OpenTUI main menu when run with no arguments in a TTY. With no TTY, no-args prints deterministic safe setup guidance, exits 0, and does not infer a project, open project state, toggle raw mode, or write provider/config artifacts. Use `vgxness --help` or `vgxness -h` to print command help without starting the main menu; explicit subcommands keep their normal behavior.
243
+ The installed `vgxness`/`vgx` binary prints deterministic safe setup guidance with no arguments, exits 0, and does not infer a project, open project state, import OpenTUI, toggle raw mode, or write provider/config artifacts. The experimental principal code/OpenTUI surface was removed and is temporarily unavailable. Use `vgxness --help` or `vgxness -h` to print command help; explicit subcommands keep their normal behavior.
244
244
 
245
- The top-level menu is: **Installation, Doctor / recovery, SDD / workflow guidance, Advanced CLI, Exit**. It is a read-only setup, diagnostics, recovery, and fallback surface; daily SDD progression stays in OpenCode with VGXNESS MCP. Terminal controls are `↑/↓` or `j/k` to move, `Enter` to open the focused item, `?` for help, and `q` to quit.
245
+ Setup is CLI-only: use `setup plan` and `setup status` for read-only guidance, and `setup apply --yes` only after review. Daily SDD progression stays in OpenCode with VGXNESS MCP.
246
246
 
247
247
  For scriptable status, use explicit read-only commands:
248
248
 
@@ -253,14 +253,14 @@ bun run cli:bun -- next --project vgxness --change my-change
253
253
  bun run cli:bun -- resume --project vgxness --run-id <id>
254
254
  ```
255
255
 
256
- Provider support shown in the Installation surface is:
256
+ Provider support for setup is:
257
257
 
258
258
  - **OpenCode** — supported primary provider with preview/status/doctor and read-only install planning.
259
259
  - **Claude** — supported secondary provider for user-global Claude CLI MCP registration, user `~/.claude.json` MCP merge, and VGXNESS-owned user agents/memory. Project-local Claude files are external/manual diagnostics only. Explicit guarded apply is outside the guided OpenCode flow and requires `mcp install claude --scope user --yes --run-id <id>`. Read-only status/doctor/change-plan do not execute Claude Code.
260
260
  - **Antigravity** — placeholder/coming-soon guidance only.
261
261
  - **Custom/future** — extension point with safe manual/default unsupported behavior.
262
262
 
263
- Setup and main-menu TUI surfaces do **not** silently write OpenCode or other provider config, do **not** call provider executables, and do **not** approve/reject preflights. They print diagnostics, recovery hints, and manual fallback commands; daily SDD work should continue in OpenCode.
263
+ Setup CLI surfaces do **not** silently write OpenCode or other provider config, do **not** call provider executables, and do **not** approve/reject preflights. They print diagnostics, recovery hints, and manual fallback commands; daily SDD work should continue in OpenCode.
264
264
 
265
265
  ## Natural-language orchestrator preview
266
266
 
@@ -280,42 +280,7 @@ Safety boundary: this is a preview only. It does **not** call providers, edit fi
280
280
 
281
281
  ## Code runtime CLI (`vgxness code`)
282
282
 
283
- `vgxness code` is the native workspace runtime for bounded agentic work. It is not a wrapper around OpenCode or any provider; provider adapters translate VGXNESS-native requests only. See [Code runtime](./code-runtime.md) for the full contract; this section lists the CLI surface.
284
-
285
- Modes (read-only by default unless `--approval-channel` and `--approval-policy` are passed):
286
-
287
- | Mode | Purpose | Mutations |
288
- |---|---|---|
289
- | `inspect` | Read-only investigation of the workspace. | None. |
290
- | `plan` | Read-only implementation planning. | None. |
291
- | `craft-preview` | Show the diff that would be applied. | None. |
292
- | `craft` | Approval-gated, bounded edit-capable work. | Edits, shell, network, git, SDD persistence all routed through explicit policy decisions. |
293
-
294
- Common flags across modes:
295
-
296
- ```bash
297
- vgxness code inspect "<question>" \
298
- --provider openai-compatible \ # or "fake" for offline testing
299
- --model <model-id> \
300
- --stream \ # emit JSONL runtime events as they happen
301
- --json \ # final response as JSON
302
- --max-source-bytes <bytes> \ # bound on sources loaded into prompt
303
- --approval-policy ask|allow|deny \
304
- --approval-channel stdio|auto \
305
- --verification none|suggest|run|repair \
306
- --transcript off|summary|full \
307
- --memory off|ask|auto
308
- ```
309
-
310
- SDD-aware mode is exposed through `vgxness code sdd <change> <phase>`; pass `--save-artifact` only when persistence is intended, and pass `--change-id`/`--phase` to scope work. Read-only phases stay artifact-oriented; `apply-progress` may expose edit and shell tools; `verify` may expose verification shell tools. `--draft-run` lets planning phases use draft prerequisites for planning only; human acceptance is still required, and `apply-progress` remains gated. `apply` is accepted as a user-facing alias for `apply-progress`.
311
-
312
- Useful events-only output for piping into the OpenTUI shell or your own tooling:
313
-
314
- ```bash
315
- vgxness code inspect "Summarize the current architecture" --events-jsonl
316
- ```
317
-
318
- Safety boundary: `inspect`, `plan`, and `craft-preview` never mutate. `craft` may only mutate through the permission-aware executors and the explicit approval channel; it never writes outside the workspace, never pushes to remote, and never edits `openspec/`. Secret-like values are redacted from prompts, transcripts, checkpoints, and memory saves. See [Safety model](./safety.md).
283
+ The experimental `vgxness code` runtime and principal OpenTUI code surface were removed and are temporarily unavailable. Do not use `vgxness code` as an SDD fallback. Continue SDD phases in OpenCode conversation with VGXNESS MCP and hidden SDD subagents, and use `vgxness status`, `vgxness next`, `vgxness sdd continue`, or `vgxness resume` for safe CLI diagnostics and recovery.
319
284
 
320
285
  ## Workflow CLI
321
286
 
@@ -570,7 +535,6 @@ bun run cli:bun -- sdd status --project vgxness --change sdd-workflow-engine --d
570
535
  bun run cli:bun -- sdd ready --project vgxness --change sdd-workflow-engine --phase spec --db /tmp/vgxness-memory.sqlite
571
536
  bun run cli:bun -- sdd save-artifact --project vgxness --change sdd-workflow-engine --phase proposal --content "# Proposal" --db /tmp/vgxness-memory.sqlite
572
537
  bun run cli:bun -- sdd continue --project vgxness --change sdd-workflow-engine --db /tmp/vgxness-memory.sqlite
573
- bun run cli:bun -- code sdd sdd-workflow-engine spec --project vgxness --draft-run --save-artifact --db /tmp/vgxness-memory.sqlite
574
538
  bun run cli:bun -- sdd accept-artifact --project vgxness --change sdd-workflow-engine --phase proposal --actor user --note "Approved for spec" --db /tmp/vgxness-memory.sqlite
575
539
  bun run cli:bun -- resume --project vgxness --db /tmp/vgxness-memory.sqlite
576
540
  bun run cli:bun -- sdd get-artifact --project vgxness --change sdd-workflow-engine --phase proposal --db /tmp/vgxness-memory.sqlite
@@ -580,7 +544,7 @@ bun run cli:bun -- sdd reopen-artifact --project vgxness --change sdd-workflow-e
580
544
  VGXNESS_DB_PATH=/tmp/vgxness-memory.sqlite bun run cli:bun -- sdd list-artifacts --project vgxness --change sdd-workflow-engine
581
545
  ```
582
546
 
583
- Current canonical phases are `explore`, `proposal`, `spec`, `design`, `tasks`, `apply-progress`, `verify`, and `archive`. `apply` is accepted as a user-facing input alias, but artifacts, topic keys, readiness/status/cockpit JSON, and internal metadata continue to use canonical `apply-progress`. Each artifact is stored under `sdd/{change}/{phase}` in the local SQLite memory store. `sdd status` reports which phase artifacts are present, blocker-specific next actions, and related interrupted run hints when available. `sdd next` reports the next SDD action for a project/change and frames runnable phase work as OpenCode-first while preserving fallback command fields. `sdd continue` turns that state into a read-only continuation plan, including manual fallback commands, draft-run suggestions for planning phases, and related interrupted run context when a matching stopped run exists. `sdd status`, `sdd next`, `sdd continue`, `sdd get-artifact`, and `sdd list-artifacts` are human-readable by default; pass `--json` for automation/stable structured output. `sdd ready` reports satisfied prerequisites and missing artifact topic keys for one phase. `sdd get-artifact` shows artifact metadata and then full content after `--- Content ---`; `sdd list-artifacts` shows one compact row for every canonical SDD phase in phase order and does not print full artifact content.
547
+ Current canonical phases are `explore`, `proposal`, `spec`, `design`, `tasks`, `apply-progress`, `verify`, and `archive`. `apply` is accepted as a user-facing input alias, but artifacts, topic keys, readiness/status/cockpit JSON, and internal metadata continue to use canonical `apply-progress`. Each artifact is stored under `sdd/{change}/{phase}` in the local SQLite memory store. `sdd status` reports which phase artifacts are present, blocker-specific next actions, and related interrupted run hints when available. `sdd next` reports the next SDD action for a project/change and frames runnable phase work as OpenCode-first while preserving safe continuation command fields. `sdd continue` turns that state into a read-only continuation plan and related interrupted run context when a matching stopped run exists. `sdd status`, `sdd next`, `sdd continue`, `sdd get-artifact`, and `sdd list-artifacts` are human-readable by default; pass `--json` for automation/stable structured output. `sdd ready` reports satisfied prerequisites and missing artifact topic keys for one phase. `sdd get-artifact` shows artifact metadata and then full content after `--- Content ---`; `sdd list-artifacts` shows one compact row for every canonical SDD phase in phase order and does not print full artifact content.
584
548
 
585
549
  `sdd accept-artifact` records explicit human-only acceptance of an existing artifact through the same SDD workflow service used by MCP. It requires `--project`, `--change`, `--phase`, and `--actor`; `--display-name` defaults to the actor id. `--accepted-at` is optional, but when supplied it must be an ISO date-time with an explicit timezone (`Z` or offset) and is normalized to UTC `toISOString()` output. The default output is a human-readable confirmation with a JSON hint; `--json` returns a content-free success object with project/change/phase/topic key/artifact id/status/acceptedBy/acceptedAt and optional note. `save-artifact` creates or updates draft content only and does not imply acceptance. `sdd reopen-artifact` moves a rejected artifact back to draft after an explicit human decision, so the artifact can be revised and accepted again.
586
550
 
@@ -978,7 +942,6 @@ For more on schema, scopes, and lifecycle, see [Storage](./storage.md).
978
942
  ## See also
979
943
 
980
944
  - [Architecture](./architecture.md) — current-state architecture and core domain model.
981
- - [Code runtime](./code-runtime.md) — `vgxness code` modes, tools, providers, and approval flow.
982
945
  - [MCP tools](./mcp.md) — full reference for the 41 MCP tools exposed to agents.
983
946
  - [Safety model](./safety.md) — permission categories, approval flow, redactors, and runtime gates.
984
947
  - [Storage](./storage.md) — SQLite schema, scopes, and lifecycle.
@@ -8,7 +8,6 @@ VGXNESS is an alpha local-first control plane. The repository follows a few rule
8
8
  src/
9
9
  agents/ # agent + subagent registry, resolver, canonical manifest
10
10
  cli/ # CLI dispatch, command modules, TUI, OpenTUI
11
- code/ # native code runtime (vgxness code)
12
11
  export/ # redaction and export helpers
13
12
  governance/ # governance report builder, overlay fingerprint
14
13
  harness/ # harness-side tool handlers
@@ -74,7 +73,7 @@ These rules are non-negotiable. The harness is loaded with capability; do not re
74
73
  - Do not create or write `openspec/`. SDD artifacts are stored through the local SQLite artifact service under canonical topic keys `sdd/{change}/{phase}`.
75
74
  - Human acceptance is distinct from artifact presence. Do not infer acceptance from generated content or saved drafts. The runtime rejects `acceptedBy.type !== 'human'`.
76
75
  - Workspace boundary denials cannot be relaxed by agent or subagent overrides. The policy evaluator uses `realpathSync` to defeat symlink escapes.
77
- - Secrets and external directory access deny by default. Redaction helpers in `src/code/reporting/redaction.ts` and `src/export/redaction.ts` are the only place secret-shaped values should be stripped.
76
+ - Secrets and external directory access deny by default. Redaction helpers in `src/export/redaction.ts` strip secret-shaped values for export surfaces.
78
77
 
79
78
  ## Style
80
79
 
@@ -92,7 +91,7 @@ The docs are the user-facing contract. When the code drifts, the docs must catch
92
91
  - When you add a new CLI command, document it in [CLI reference](./cli.md).
93
92
  - When you change a permission category, default, or phase mode, update [Safety model](./safety.md).
94
93
  - When you add a migration, append it to the table in [Storage](./storage.md).
95
- - When you add or change a provider, update [Providers](./providers.md) and the [Code runtime](./code-runtime.md) tool list.
94
+ - When you add or change a provider, update [Providers](./providers.md) and setup/status documentation.
96
95
 
97
96
  ## Pull request process
98
97
 
@@ -106,6 +105,22 @@ VGXNESS is shipped as a proprietary package. The npm publication step is a separ
106
105
 
107
106
  PRs that touch safety gates, permission categories, default policies, the run lifecycle, or the SDD acceptance gate are reviewed by a maintainer who can answer "does this still match the safety model?" without consulting the diff. If you are unsure, open the PR as a draft and ask.
108
107
 
108
+ Do not push directly to `main` for normal development. Use a branch, open a PR, and let CI/check requirements enforce the review boundary. Direct pushes are reserved for exceptional maintainer recovery and must be followed by an explicit note that branch protection was bypassed.
109
+
110
+ ### Stacked PRs
111
+
112
+ Use stacked PRs when a change naturally splits into reviewable layers, for example docs groundwork → safety-policy hardening → CLI/MCP behavior. A stacked PR keeps each review small while preserving dependency order.
113
+
114
+ Recommended pattern:
115
+
116
+ 1. Start from `main` for the first branch: `feature/base-slice`.
117
+ 2. Open PR 1 into `main`.
118
+ 3. Branch PR 2 from PR 1: `feature/follow-up-slice`, and open PR 2 with PR 1 as its base.
119
+ 4. Keep each PR focused on one logical change and explain its base PR in the description.
120
+ 5. Rebase or retarget follow-up PRs after their base merges; do not squash unrelated stacked slices into one large review.
121
+
122
+ Avoid stacked PRs for emergency CI repairs: use one small hotfix PR against `main` unless the repair truly depends on another unmerged branch.
123
+
109
124
  ## Commit conventions
110
125
 
111
126
  - Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, `build:`, `ci:`).