vgxness 1.2.1 → 1.3.1

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 (85) hide show
  1. package/README.md +20 -19
  2. package/dist/cli/cli-help.js +4 -7
  3. package/dist/cli/commands/index.js +1 -1
  4. package/dist/cli/commands/interactive-entrypoint-dispatcher.js +150 -0
  5. package/dist/cli/commands/setup-dispatcher.js +11 -8
  6. package/dist/cli/dispatcher.js +1 -8
  7. package/dist/cli/doctor-renderer.js +1 -1
  8. package/dist/cli/index.js +0 -0
  9. package/dist/cli/sdd-renderer.js +7 -7
  10. package/dist/cli/setup-status-renderer.js +1 -0
  11. package/dist/cli/tui/main-menu/index.js +0 -1
  12. package/dist/cli/tui/main-menu/main-menu-controller.js +0 -2
  13. package/dist/cli/tui/main-menu/main-menu-read-model.js +10 -8
  14. package/dist/cli/tui/main-menu/main-menu-render-shape.js +19 -2
  15. package/dist/cli/tui/main-menu/main-menu-state.js +1 -1
  16. package/dist/cli/tui/opentui/code/index.js +210 -0
  17. package/dist/cli/tui/opentui/code/screen.js +107 -0
  18. package/dist/cli/tui/opentui/code/smoke.js +32 -0
  19. package/dist/cli/tui/opentui/main-menu/index.js +3 -0
  20. package/dist/cli/tui/opentui/main-menu/renderer.js +68 -0
  21. package/dist/cli/tui/opentui/main-menu/screen.js +68 -0
  22. package/dist/cli/tui/opentui/main-menu/smoke.js +17 -0
  23. package/dist/cli/tui/opentui/main-menu/view.js +8 -0
  24. package/dist/cli/tui/opentui/setup/index.js +3 -0
  25. package/dist/cli/tui/opentui/setup/renderer.js +87 -0
  26. package/dist/cli/tui/opentui/setup/screen.js +170 -0
  27. package/dist/cli/tui/opentui/setup/smoke.js +42 -0
  28. package/dist/cli/tui/opentui/setup/view.js +12 -0
  29. package/dist/cli/tui/setup/setup-tui-input.js +43 -0
  30. package/dist/cli/tui/setup/setup-tui-read-model.js +4 -4
  31. package/dist/cli/tui/setup/setup-tui-render-shape.js +9 -10
  32. package/dist/cli/tui/setup/setup-tui-state.js +1 -1
  33. package/dist/cli/tui/setup/setup-tui-view-helpers.js +46 -0
  34. package/dist/cli/tui/visual/index.js +0 -2
  35. package/dist/code/runtime/sdd-context.js +2 -2
  36. package/dist/code/tui/approval-actions.js +33 -0
  37. package/dist/code/tui/prompt-mode.js +11 -0
  38. package/dist/code/tui/runtime-events.js +320 -0
  39. package/dist/mcp/validation.js +6 -2
  40. package/dist/orchestrator/natural-language-planner.js +1 -1
  41. package/dist/sdd/sdd-workflow-service.js +1 -25
  42. package/dist/setup/backup-rollback-service.js +2 -2
  43. package/dist/setup/providers/antigravity-setup-adapter.js +1 -1
  44. package/dist/setup/providers/claude-setup-adapter.js +2 -2
  45. package/dist/setup/providers/custom-setup-adapter.js +1 -1
  46. package/dist/setup/providers/opencode-setup-adapter.js +3 -3
  47. package/dist/setup/setup-lifecycle-service.js +6 -6
  48. package/dist/setup/setup-plan.js +3 -3
  49. package/dist/verification/verification-plan-service.js +1 -1
  50. package/docs/architecture.md +43 -42
  51. package/docs/cli.md +141 -133
  52. package/docs/funcionamiento-del-sistema.md +22 -23
  53. package/docs/harness-gap-analysis.md +15 -1
  54. package/docs/prd.md +14 -14
  55. package/docs/vgxcode.md +87 -0
  56. package/docs/vgxness-code.md +6 -4
  57. package/package.json +5 -6
  58. package/dist/cli/commands/dashboard-dispatcher.js +0 -560
  59. package/dist/cli/dashboard-operational-read-models.js +0 -428
  60. package/dist/cli/dashboard-renderer.js +0 -158
  61. package/dist/cli/dashboard-screen-renderers.js +0 -256
  62. package/dist/cli/dashboard-tui-read-model.js +0 -73
  63. package/dist/cli/dashboard-tui-state.js +0 -314
  64. package/dist/cli/guided-main-menu.js +0 -470
  65. package/dist/cli/interactive-dashboard.js +0 -34
  66. package/dist/cli/setup-wizard-read-model.js +0 -72
  67. package/dist/cli/setup-wizard-renderer.js +0 -155
  68. package/dist/cli/setup-wizard-state.js +0 -82
  69. package/dist/cli/tui/dashboard/dashboard-adapter.js +0 -4
  70. package/dist/cli/tui/main-menu/main-menu-app.js +0 -28
  71. package/dist/cli/tui/render-ink-app.js +0 -10
  72. package/dist/cli/tui/setup/screens/applying-screen.js +0 -6
  73. package/dist/cli/tui/setup/screens/cancellation-screen.js +0 -6
  74. package/dist/cli/tui/setup/screens/error-recovery-screen.js +0 -6
  75. package/dist/cli/tui/setup/screens/final-confirmation-screen.js +0 -6
  76. package/dist/cli/tui/setup/screens/opencode-details-screen.js +0 -10
  77. package/dist/cli/tui/setup/screens/plan-review-screen.js +0 -6
  78. package/dist/cli/tui/setup/screens/project-database-screen.js +0 -6
  79. package/dist/cli/tui/setup/screens/provider-screen.js +0 -7
  80. package/dist/cli/tui/setup/screens/result-screen.js +0 -16
  81. package/dist/cli/tui/setup/screens/screen-components.js +0 -103
  82. package/dist/cli/tui/setup/screens/welcome-screen.js +0 -6
  83. package/dist/cli/tui/setup/setup-tui-app.js +0 -113
  84. package/dist/cli/tui/visual/choice-list.js +0 -10
  85. package/dist/cli/tui/visual/layout.js +0 -10
package/README.md CHANGED
@@ -6,7 +6,7 @@ VGXNESS is an installable CLI and MCP control plane for guided AI-agent workflow
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. The dashboard is read-only/copy-only; provider config writes require explicit CLI confirmation.
9
+ OpenCode is the primary supported provider. Other providers remain preview/manual only. Provider config writes require explicit CLI confirmation.
10
10
 
11
11
  ## Requirements
12
12
 
@@ -123,8 +123,8 @@ bun run package:bun:evidence
123
123
 
124
124
  ```bash
125
125
  npm install -g vgxness
126
- vgx --help
127
126
  vgxness --help
127
+ vgx --help # compatibility alias
128
128
  ```
129
129
 
130
130
  ## First setup with OpenCode
@@ -132,16 +132,16 @@ vgxness --help
132
132
  Run the guided setup wizard in a TTY:
133
133
 
134
134
  ```bash
135
- vgx init
135
+ vgxness init
136
136
  ```
137
137
 
138
- In non-TTY shells, `vgx init` prints the same read-only setup plan instead of prompting. For a copyable happy path after installing the package globally:
138
+ In non-TTY shells, `vgxness init` prints the same read-only setup plan instead of prompting. For a copyable happy path after installing the package globally:
139
139
 
140
140
  ```bash
141
- vgx setup plan
142
- vgx setup apply --yes
143
- vgx doctor
144
- vgx sdd next --project <project> --change <change>
141
+ vgxness setup plan
142
+ vgxness setup apply --yes
143
+ vgxness doctor
144
+ vgxness sdd next --project <project> --change <change>
145
145
  ```
146
146
 
147
147
  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,28 +153,29 @@ vgxness mcp start
153
153
  Apply only after reviewing the plan:
154
154
 
155
155
  ```bash
156
- vgx setup apply --yes
156
+ vgxness setup apply --yes
157
157
  ```
158
158
 
159
- `vgx setup plan` and `vgx setup status` are human-readable and read-only by default. `vgx doctor`, `vgx sdd status`, `vgx sdd next`, and `vgx sdd accept-artifact` are also human-readable by default. Pass `--json` when you need parseable automation output. `vgx setup apply --yes` is the explicit provider-config write path.
159
+ `vgxness setup plan` and `vgxness setup status` are human-readable and read-only by default. `vgxness doctor`, `vgxness sdd status`, `vgxness sdd next`, and `vgxness sdd accept-artifact` are also human-readable by default. Pass `--json` when you need parseable automation output. `vgxness setup apply --yes` is the explicit provider-config write path.
160
160
 
161
161
  ## Safety model
162
162
 
163
163
  - Preview, status, and plan commands are read-only.
164
164
  - Provider config writes require explicit `--yes` confirmation.
165
- - The dashboard is read-only/copy-only; run copied commands outside the TUI when you choose to act.
165
+ - Setup/status TUI surfaces are preview-oriented; run copied commands explicitly when you choose to act.
166
166
  - SDD artifacts are SQLite-backed through VGXNESS services. Do not create or write `openspec/`.
167
- - `vgx sdd accept-artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
167
+ - `vgxness sdd accept-artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
168
168
  - OpenCode is the primary supported provider; other providers are preview/manual extension points.
169
169
 
170
- ## Dashboard entrypoint
170
+ ## Main menu entrypoint
171
171
 
172
- Run `vgx` or `vgxness` with no arguments in an interactive terminal to open the operational dashboard. `vgx dashboard interactive` opens the same read-only/copy-only surface. In non-TTY shells, no-args prints static safe guidance and exits 0 without reading dashboard status or inferring project state.
172
+ Run `vgxness` with no arguments in an interactive terminal to open the OpenTUI main menu. `vgx` remains a compatibility alias. In non-TTY shells, no-args prints static safe setup guidance and exits 0 without inferring project state.
173
173
 
174
- For scripts, use the read-only status renderer with an explicit project:
174
+ For scripts, use explicit read-only commands with an explicit project:
175
175
 
176
176
  ```bash
177
- vgx dashboard status --project <name>
177
+ vgxness setup status --project <name>
178
+ vgxness sdd status --project <name> --change <change>
178
179
  ```
179
180
 
180
181
  For project-local or custom databases, use `--db project-local` or `--db custom --db-path <path>` with setup commands. Existing low-level commands remain available:
@@ -187,7 +188,7 @@ vgxness mcp install opencode --yes
187
188
  ## Verify
188
189
 
189
190
  ```bash
190
- vgx doctor
191
+ vgxness doctor
191
192
  vgxness mcp doctor opencode
192
193
  vgxness setup status
193
194
  ```
@@ -199,10 +200,10 @@ Restart OpenCode after applying config and verify that the `vgxness` MCP server
199
200
  OpenCode applies create a backup before merging existing config. Restore one with:
200
201
 
201
202
  ```bash
202
- vgx setup rollback --backup <path>
203
+ vgxness setup rollback --backup <path>
203
204
  ```
204
205
 
205
- Rollback validates the backup, creates a pre-rollback backup of the current target when present, restores the selected backup byte-for-byte, and keeps the original backup if anything fails. Rerun `vgx doctor` after rollback.
206
+ Rollback validates the backup, creates a pre-rollback backup of the current target when present, restores the selected backup byte-for-byte, and keeps the original backup if anything fails. Rerun `vgxness doctor` after rollback.
206
207
 
207
208
  Common issues:
208
209
 
@@ -91,14 +91,11 @@ Areas:
91
91
  subagents list --parent-agent-id <id>
92
92
  subagents get --id <id> | --project <name> --name <name> [--scope project|personal]
93
93
 
94
- dashboard status --project <name> [--change <id>] [--run-id <id>] [--limit <n>]
95
- dashboard interactive [--project <name>] [--change <id>] [--limit <n>]
96
- No args in an interactive TTY opens the same operational dashboard as dashboard interactive.
97
- No args without a TTY prints static safe guidance and exits 0 without reading dashboard status or opening project state.
98
- Dashboard menu: Installation, Status, Agents, Skills, Memory, SDD, Runs, Approvals, Permissions, Settings. Menu: ↑/↓ or j/k, Enter, 1-9/0. Section: b/Esc/Backspace back, r, ?, q.
99
- Dashboardinteractive may launch without --project; Installation remains available and project-scoped checks are deferred while project screens render project-required recovery states.
94
+ No args in an interactive TTY opens the OpenTUI main menu.
95
+ No args without a TTY prints static safe setup guidance and exits 0 without opening project state.
96
+ Setup TUI may launch without --project; Installation remains available and project-scoped checks are deferred while project screens render project-required recovery states.
100
97
  Provider setup support: OpenCode supported primary; Claude preview-only; Antigravity placeholder; Custom/future extension point.
101
- Dashboard status is scriptable/read-only and requires --project. Provider config writes/install/apply are external-only, require explicit confirmation outside the dashboard, and are not run by dashboard flows.
98
+ Provider config writes/install/apply are external-only and require explicit confirmation.
102
99
 
103
100
  sdd status --project <name> --change <id> [--json]
104
101
  sdd next --project <name> --change <id> [--json]
@@ -1,5 +1,5 @@
1
1
  export { runAgentCommand, runSkillCommand, runSubagentCommand } from './agent-skill-dispatcher.js';
2
- export { runCodeCliCommand, runDashboardCommand, runDashboardInteractiveCommand, runDefaultInteractiveEntrypoint } from './dashboard-dispatcher.js';
2
+ export { runCodeCliCommand, runDefaultInteractiveEntrypoint } from './interactive-entrypoint-dispatcher.js';
3
3
  export { runDoctorAliasCommand, runMcpDoctorCommand, runMcpDoctorOpenCodeCommand, runMcpInstallCommand, runMcpSetupCommand } from './mcp-dispatcher.js';
4
4
  export { runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runSddCommand } from './memory-sdd-dispatcher.js';
5
5
  export { runApprovalsCommand, runPermissionsCommand, runRunsCommand } from './run-permission-dispatcher.js';
@@ -0,0 +1,150 @@
1
+ import { runCodeCommand } from '../../code/cli/code-command.js';
2
+ import { InMemoryRunGateway } from '../../code/runtime/gateways.js';
3
+ import { MemoryServiceCodeGateway } from '../../code/runtime/memory-service-gateway.js';
4
+ import { RunsCodeRunGateway } from '../../code/runtime/runs-code-run-gateway.js';
5
+ import { SddWorkflowGateway } from '../../code/runtime/sdd-workflow-gateway.js';
6
+ import { MemoryService } from '../../memory/memory-service.js';
7
+ import { RunService } from '../../runs/run-service.js';
8
+ import { SddWorkflowService } from '../../sdd/sdd-workflow-service.js';
9
+ import { codeApprovalPolicyFlag, codeMemoryPolicyFlag, codeTranscriptModeFlag, codeVerificationModeFlag, databasePathFor, optionalNumberFlag, optionalStringFlag, } from '../cli-flags.js';
10
+ import { okText, usageFailure, validationFailure } from '../cli-help.js';
11
+ import { openCliDatabase, resultFailure } from '../cli-helpers.js';
12
+ import { canRunInteractiveTui } from '../tui/terminal-capabilities.js';
13
+ import { runSetupTuiCommand } from './setup-dispatcher.js';
14
+ function defaultNoTtyGuidance() {
15
+ return ([
16
+ 'VGXNESS main menu requires a TTY; no provider config was written.',
17
+ 'Next: rerun `vgxness` in an interactive terminal, run `vgxness init --plan`, or run `vgxness setup plan` for read-only installation guidance.',
18
+ ].join('\n') + '\n');
19
+ }
20
+ function guidanceForMainMenuResult(result) {
21
+ if (result.type === 'show-doctor-guidance')
22
+ return ['Doctor / recovery guidance:', '- Read-only status: `vgxness setup status`', '- Provider doctor: `vgxness mcp doctor opencode`', '- No provider config was written.'].join('\n') + '\n';
23
+ if (result.type === 'show-sdd-guidance')
24
+ return ['SDD / workflow guidance:', '- Use VGXNESS MCP tools from OpenCode for normal SDD progression.', '- Manual status: `vgxness sdd status --project <name> --change <change>`', '- No provider config was written.'].join('\n') + '\n';
25
+ if (result.type === 'show-advanced-cli')
26
+ return ['Advanced CLI guidance:', '- Installation preview: `vgxness init --plan` or `vgxness setup plan`', '- Setup status: `vgxness setup status --project <name>`', '- SDD status: `vgxness sdd status --project <name> --change <change>`', '- No provider config was written.'].join('\n') + '\n';
27
+ if (result.type === 'exit')
28
+ return 'Exited main menu; no provider config was written.\n';
29
+ return undefined;
30
+ }
31
+ async function renderDefaultMainMenu(environment, onResult) {
32
+ const { renderOpenTuiMainMenu } = await import('../tui/opentui/main-menu/renderer.js');
33
+ await renderOpenTuiMainMenu({
34
+ stdin: environment.stdin,
35
+ stdout: environment.stdout,
36
+ onResult,
37
+ });
38
+ }
39
+ export async function runDefaultInteractiveEntrypointWithMainMenu(environment, input = {}) {
40
+ if (!canRunInteractiveTui(environment.stdin, environment.stdout))
41
+ return okText(defaultNoTtyGuidance());
42
+ let selected;
43
+ await (input.renderMainMenu ?? ((onResult) => renderDefaultMainMenu(environment, onResult)))((result) => {
44
+ selected = result;
45
+ });
46
+ const result = selected ?? { type: 'exit' };
47
+ if (result.type === 'open-setup')
48
+ return (input.setupTui ?? runSetupTuiCommand)(environment);
49
+ return okText(guidanceForMainMenuResult(result) ?? 'No provider config was written.\n');
50
+ }
51
+ function codeApprovalChannelFlag(flags) {
52
+ const value = optionalStringFlag(flags, 'approval-channel');
53
+ if (value === undefined)
54
+ return { ok: true, value: undefined };
55
+ return value === 'stdio' ? { ok: true, value } : validationFailure('--approval-channel must be stdio');
56
+ }
57
+ export async function runDefaultInteractiveEntrypoint(environment) {
58
+ return runDefaultInteractiveEntrypointWithMainMenu(environment);
59
+ }
60
+ export async function runCodeCliCommand(parsed, environment) {
61
+ const [, command] = parsed.positionals;
62
+ if (command !== 'inspect' && command !== 'plan' && command !== 'craft' && command !== 'craft-preview' && command !== 'sdd')
63
+ return usageFailure(`Unknown code command: ${command ?? ''}`.trim());
64
+ const eventsJsonl = parsed.flags['events-jsonl'] === true;
65
+ const approvalChannel = codeApprovalChannelFlag(parsed.flags);
66
+ if (!approvalChannel.ok)
67
+ return resultFailure(approvalChannel);
68
+ if (approvalChannel.value === 'stdio' && (command !== 'craft' || !eventsJsonl))
69
+ return usageFailure('--approval-channel stdio is supported only for code craft --events-jsonl');
70
+ if (eventsJsonl && command !== 'inspect' && command !== 'plan' && command !== 'craft-preview' && approvalChannel.value !== 'stdio')
71
+ return usageFailure('code craft --events-jsonl requires --approval-channel stdio; JSONL without approvals is currently supported only for read-only inspect, plan, and craft-preview');
72
+ const maxSourceBytes = optionalNumberFlag(parsed.flags, 'max-source-bytes');
73
+ if (!maxSourceBytes.ok)
74
+ return resultFailure(maxSourceBytes);
75
+ const output = parsed.flags.json === true || optionalStringFlag(parsed.flags, 'output') === 'json' ? 'json' : 'human';
76
+ const approvalPolicy = codeApprovalPolicyFlag(parsed.flags);
77
+ if (!approvalPolicy.ok)
78
+ return resultFailure(approvalPolicy);
79
+ const verificationMode = codeVerificationModeFlag(parsed.flags);
80
+ if (!verificationMode.ok)
81
+ return resultFailure(verificationMode);
82
+ const transcriptMode = codeTranscriptModeFlag(parsed.flags);
83
+ if (!transcriptMode.ok)
84
+ return resultFailure(transcriptMode);
85
+ const memoryPolicy = codeMemoryPolicyFlag(parsed.flags);
86
+ if (!memoryPolicy.ok)
87
+ return resultFailure(memoryPolicy);
88
+ const provider = optionalStringFlag(parsed.flags, 'provider');
89
+ const model = optionalStringFlag(parsed.flags, 'model');
90
+ if (eventsJsonl) {
91
+ if (approvalChannel.value === 'stdio' && (environment.stdin === undefined || environment.stdout === undefined))
92
+ return resultFailure(validationFailure('--approval-channel stdio requires CLI stdin and stdout streams'));
93
+ return await runCodeCommand({
94
+ command,
95
+ args: parsed.positionals.slice(2),
96
+ cwd: environment.cwd,
97
+ output,
98
+ runGateway: new InMemoryRunGateway(),
99
+ project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
100
+ ...(provider === undefined ? {} : { provider }),
101
+ ...(model === undefined ? {} : { model }),
102
+ stream: parsed.flags.stream === true,
103
+ env: environment.env,
104
+ eventsJsonl,
105
+ memoryPolicy: 'off',
106
+ ...(approvalChannel.value === undefined ? {} : { approvalChannel: approvalChannel.value }),
107
+ ...(approvalChannel.value === 'stdio' ? { approvalDecisionInput: environment.stdin, eventOutput: environment.stdout } : {}),
108
+ ...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
109
+ ...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
110
+ ...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
111
+ ...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
112
+ });
113
+ }
114
+ const selectedDatabasePath = databasePathFor(parsed.flags, environment);
115
+ if (!selectedDatabasePath.ok)
116
+ return resultFailure(selectedDatabasePath);
117
+ const opened = openCliDatabase(selectedDatabasePath.value);
118
+ if (!opened.ok)
119
+ return resultFailure(opened);
120
+ try {
121
+ const runs = new RunService(opened.value);
122
+ const memory = new MemoryService(opened.value);
123
+ return await runCodeCommand({
124
+ command,
125
+ args: parsed.positionals.slice(2),
126
+ cwd: environment.cwd,
127
+ output,
128
+ runGateway: new RunsCodeRunGateway(runs),
129
+ sddGateway: new SddWorkflowGateway(new SddWorkflowService(memory)),
130
+ memoryGateway: new MemoryServiceCodeGateway(memory),
131
+ project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
132
+ ...(provider === undefined ? {} : { provider }),
133
+ ...(model === undefined ? {} : { model }),
134
+ stream: parsed.flags.stream === true,
135
+ env: environment.env,
136
+ eventsJsonl,
137
+ persistArtifact: parsed.flags['save-artifact'] === true || parsed.flags.persist === true,
138
+ ...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
139
+ ...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
140
+ ...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
141
+ ...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
142
+ ...(memoryPolicy.value === undefined ? {} : { memoryPolicy: memoryPolicy.value }),
143
+ });
144
+ }
145
+ finally {
146
+ opened.value.close();
147
+ }
148
+ }
149
+ // Re-export helpers
150
+ export { defaultNoTtyGuidance, };
@@ -1,5 +1,4 @@
1
1
  import { resolve } from 'node:path';
2
- import React from 'react';
3
2
  import { AgentRegistryService } from '../../agents/agent-registry-service.js';
4
3
  import { resolveAgentProfileModel } from '../../agents/profile-model-routing.js';
5
4
  import { installOpenCodeMcpClient } from '../../mcp/client-install-opencode.js';
@@ -14,8 +13,6 @@ import { okText, usageFailure, validationFailure } from '../cli-help.js';
14
13
  import { jsonResult, openCliDatabase, resultFailure } from '../cli-helpers.js';
15
14
  import { renderSetupPlan } from '../setup-plan-renderer.js';
16
15
  import { renderSetupStatus } from '../setup-status-renderer.js';
17
- import { renderInkApp } from '../tui/render-ink-app.js';
18
- import { SetupTuiApp } from '../tui/setup/setup-tui-app.js';
19
16
  import { createDefaultSetupTuiServices } from '../tui/setup/setup-tui-services.js';
20
17
  import { canRunInteractiveTui } from '../tui/terminal-capabilities.js';
21
18
  function renderSetupRollbackApply(result, parsed) {
@@ -28,7 +25,7 @@ function renderSetupRollbackApply(result, parsed) {
28
25
  `Target: ${result.value.targetPath}`,
29
26
  `Restored from: ${result.value.backupPath}`,
30
27
  ...(result.value.preRollbackBackupPath === undefined ? [] : [`Pre-rollback backup: ${result.value.preRollbackBackupPath}`]),
31
- 'Next: vgx doctor; restart OpenCode and verify the vgxness MCP server is visible.',
28
+ 'Next: vgxness doctor; restart OpenCode and verify the vgxness MCP server is visible.',
32
29
  ];
33
30
  return okText(`${lines.join('\n')}\n`);
34
31
  }
@@ -92,7 +89,7 @@ export function runSetupRollbackCommand(parsed, environment) {
92
89
  `Backup: ${result.value.backupPath}`,
93
90
  ...result.value.blockers.map((blocker) => `Blocker: ${blocker}`),
94
91
  ...result.value.warnings.map((warning) => `Warning: ${warning}`),
95
- ...(result.value.restorable ? [`Apply with: vgx setup rollback --backup ${result.value.backupPath} --yes`] : []),
92
+ ...(result.value.restorable ? [`Apply with: vgxness setup rollback --backup ${result.value.backupPath} --yes`] : []),
96
93
  ];
97
94
  return okText(`${lines.join('\n')}\n`);
98
95
  }
@@ -156,7 +153,7 @@ export async function applySetupPlanInput(input, environment) {
156
153
  status: 'installed',
157
154
  plan: plan.value,
158
155
  opencode: result,
159
- nextCommands: ['vgx doctor', 'Restart OpenCode and verify the vgxness MCP server is visible.'],
156
+ nextCommands: ['vgxness doctor', 'Restart OpenCode and verify the vgxness MCP server is visible.'],
160
157
  },
161
158
  }
162
159
  : validationFailure(`${result.reason}: ${result.message}`);
@@ -339,7 +336,7 @@ export async function runInitCommandWithSetupTui(parsed, environment, setupTui)
339
336
  }
340
337
  export async function runSetupTuiCommand(environment, input) {
341
338
  if (!canRunInteractiveTui(environment.stdin, environment.stdout))
342
- return okText('Setup TUI requires an interactive TTY; no provider config was written. Run `vgx init --plan` or `vgx setup plan` for read-only output.\n');
339
+ return okText('Setup TUI requires an interactive TTY; no provider config was written. Run `vgxness init --plan` or `vgxness setup plan` for read-only output.\n');
343
340
  const selectedDatabasePath = databasePathSelectionFor({}, environment);
344
341
  if (!selectedDatabasePath.ok)
345
342
  return resultFailure(selectedDatabasePath);
@@ -361,7 +358,13 @@ export async function runSetupTuiCommand(environment, input) {
361
358
  },
362
359
  };
363
360
  try {
364
- await renderInkApp(React.createElement(SetupTuiApp, { services: createDefaultSetupTuiServices({ lifecycle, cwd: environment.cwd, env: environment.env }), runtime }), { stdin: environment.stdin, stdout: environment.stdout });
361
+ const { renderOpenTuiSetup } = await import('../tui/opentui/setup/index.js');
362
+ await renderOpenTuiSetup({
363
+ services: createDefaultSetupTuiServices({ lifecycle, cwd: environment.cwd, env: environment.env }),
364
+ runtime,
365
+ stdin: environment.stdin,
366
+ stdout: environment.stdout,
367
+ });
365
368
  return { exitCode: 0, stdout: '', stderr: '' };
366
369
  }
367
370
  finally {
@@ -4,7 +4,7 @@ import { isWorkflowId } from '../workflows/schema.js';
4
4
  import { databasePathFor, parseArgs, requiredFlag } from './cli-flags.js';
5
5
  import { okText, usageFailure, visibleHelpText } from './cli-help.js';
6
6
  import { openCliDatabase, resultFailure } from './cli-helpers.js';
7
- import { runAgentCommand, runApprovalsCommand, runCodeCliCommand, runDashboardCommand, runDashboardInteractiveCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
7
+ import { runAgentCommand, runApprovalsCommand, runCodeCliCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
8
8
  const _promptBuffers = new WeakMap();
9
9
  const require = createRequire(import.meta.url);
10
10
  const packageJson = require('../../package.json');
@@ -75,8 +75,6 @@ export function dispatchCli(argv, environment) {
75
75
  return runOrchestratorCommand(command, parsed, opened.value);
76
76
  if (area === 'opencode')
77
77
  return runOpenCodeCommand(command, parsed, opened.value, environment);
78
- if (area === 'dashboard')
79
- return runDashboardCommand(command, parsed, opened.value, environment, databasePath);
80
78
  return usageFailure(`Unknown command area: ${area}`);
81
79
  }
82
80
  finally {
@@ -91,8 +89,6 @@ export async function dispatchCliAsync(argv, environment) {
91
89
  const [area, command] = parsed.positionals;
92
90
  if (argv.length === 0)
93
91
  return runDefaultInteractiveEntrypoint(environment);
94
- if (area === 'dashboard' && command === 'interactive')
95
- return runDashboardInteractiveCommand(parsed, environment);
96
92
  if (area === 'mcp') {
97
93
  if (!command)
98
94
  return usageFailure('Missing command for mcp');
@@ -222,9 +218,6 @@ function validateCommand(area, command) {
222
218
  if (area === 'verification') {
223
219
  return command === 'plan' || command === 'report' ? { ok: true } : { ok: false, message: `Unknown verification command: ${command}` };
224
220
  }
225
- if (area === 'dashboard') {
226
- return command === 'status' ? { ok: true } : { ok: false, message: `Unknown dashboard command: ${command}` };
227
- }
228
221
  if (area === 'code') {
229
222
  return command === 'inspect' || command === 'plan' || command === 'craft' || command === 'sdd'
230
223
  ? { ok: true }
@@ -7,7 +7,7 @@ export function renderDoctorReport(input) {
7
7
  const failedCheckRemediation = input.report.checks.find((check) => check.status === 'fail' && check.remediation !== undefined)?.remediation;
8
8
  const next = input.report.ready
9
9
  ? 'VGXNESS doctor checks are ready; continue with your SDD workflow.'
10
- : (failedCheckRemediation ?? 'Resolve failed or skipped checks, then rerun `vgx doctor --json` or `vgx doctor`.');
10
+ : (failedCheckRemediation ?? 'Resolve failed or skipped checks, then rerun `vgxness doctor --json` or `vgxness doctor`.');
11
11
  const lines = [
12
12
  'VGXNESS Doctor',
13
13
  `Project: ${input.project}`,
package/dist/cli/index.js CHANGED
File without changes
@@ -4,7 +4,7 @@ export function renderSddStatus(input) {
4
4
  const blockers = input.status.phases.filter((phase) => phase.present && phase.accepted !== true);
5
5
  const complete = input.status.phases.length > 0 && input.status.phases.every((phase) => phase.present && phase.accepted === true);
6
6
  const statusLabel = complete ? 'complete' : input.status.nextReadyPhase === undefined ? 'blocked' : 'ready';
7
- const directPhaseCommand = input.status.nextReadyPhase === undefined ? undefined : `vgx code sdd ${input.status.change} ${input.status.nextReadyPhase} --save-artifact`;
7
+ const directPhaseCommand = input.status.nextReadyPhase === undefined ? undefined : `vgxness code sdd ${input.status.change} ${input.status.nextReadyPhase} --save-artifact`;
8
8
  const recommendedAction = complete
9
9
  ? 'No next SDD phase remains for this change.'
10
10
  : input.status.nextReadyPhase === undefined
@@ -27,8 +27,8 @@ export function renderSddStatus(input) {
27
27
  ...(missing.length === 0 ? ['- none'] : missing.map((topicKey) => `- ${topicKey}`)),
28
28
  '',
29
29
  `Recommended action: ${recommendedAction}`,
30
- `Command: ${directPhaseCommand ?? `vgx sdd next --project ${input.project} --change ${input.status.change}`}`,
31
- `JSON: vgx sdd status --project ${input.project} --change ${input.status.change} --json`,
30
+ `Command: ${directPhaseCommand ?? `vgxness sdd next --project ${input.project} --change ${input.status.change}`}`,
31
+ `JSON: vgxness sdd status --project ${input.project} --change ${input.status.change} --json`,
32
32
  ];
33
33
  return `${lines.join('\n')}\n`;
34
34
  }
@@ -36,8 +36,8 @@ export function renderSddNext(input) {
36
36
  const blockers = input.decision.blockedPrerequisites ?? [];
37
37
  const phase = input.decision.nextPhase ?? 'none';
38
38
  const commandGuidance = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined
39
- ? `vgx code sdd ${input.decision.change} ${input.decision.nextPhase} --save-artifact`
40
- : `vgx sdd status --project ${input.project} --change ${input.decision.change}`;
39
+ ? `vgxness code sdd ${input.decision.change} ${input.decision.nextPhase} --save-artifact`
40
+ : `vgxness sdd status --project ${input.project} --change ${input.decision.change}`;
41
41
  const lines = [
42
42
  'SDD Next',
43
43
  `Project: ${input.project}`,
@@ -54,7 +54,7 @@ export function renderSddNext(input) {
54
54
  '',
55
55
  `Recommended action: ${input.decision.recommendedAction}`,
56
56
  `Command: ${commandGuidance}`,
57
- `JSON: vgx sdd next --project ${input.project} --change ${input.decision.change} --json`,
57
+ `JSON: vgxness sdd next --project ${input.project} --change ${input.decision.change} --json`,
58
58
  ];
59
59
  return `${lines.join('\n')}\n`;
60
60
  }
@@ -89,7 +89,7 @@ export function renderSddArtifactAccepted(input) {
89
89
  `- Accepted by: ${input.acceptedBy.displayName} (${input.acceptedBy.id})`,
90
90
  `- Accepted at: ${input.acceptedAt}`,
91
91
  ...(input.note === undefined ? [] : [`- Note: ${input.note}`]),
92
- `JSON: vgx sdd accept-artifact --project ${input.project} --change ${input.change} --phase ${input.phase} --actor ${input.acceptedBy.id} --json`,
92
+ `JSON: vgxness sdd accept-artifact --project ${input.project} --change ${input.change} --phase ${input.phase} --actor ${input.acceptedBy.id} --json`,
93
93
  ];
94
94
  return `${lines.join('\n')}\n`;
95
95
  }
@@ -29,6 +29,7 @@ function renderProviderPreview(provider) {
29
29
  ...(preview.backupRequired === undefined ? [] : [` Backup required: ${String(preview.backupRequired)}`]),
30
30
  ...(preview.confirmationRequired === undefined ? [] : [` Confirmation required: ${String(preview.confirmationRequired)}`]),
31
31
  ...(preview.risks.length === 0 ? [] : [` Risks: ${preview.risks.join(' ')}`]),
32
+ ...(preview.warnings.length === 0 ? [] : [` Warnings: ${preview.warnings.join(' ')}`]),
32
33
  ];
33
34
  }
34
35
  function renderDefaults(status) {
@@ -1,5 +1,4 @@
1
1
  export * from './main-menu-actions.js';
2
- export * from './main-menu-app.js';
3
2
  export * from './main-menu-controller.js';
4
3
  export * from './main-menu-read-model.js';
5
4
  export * from './main-menu-render-shape.js';
@@ -1,8 +1,6 @@
1
1
  export function resultForMainMenuOption(optionId) {
2
2
  if (optionId === 'setup')
3
3
  return { type: 'open-setup' };
4
- if (optionId === 'dashboard')
5
- return { type: 'open-dashboard' };
6
4
  if (optionId === 'doctor')
7
5
  return { type: 'show-doctor-guidance' };
8
6
  if (optionId === 'sdd')
@@ -1,5 +1,12 @@
1
- import { formatTuiFooter, tuiBadges } from '../visual/index.js';
1
+ import { tuiBadges } from '../visual/badges.js';
2
+ import { formatTuiFooter } from '../visual/footer.js';
2
3
  import { mainMenuOptionIds } from './main-menu-state.js';
4
+ const statusSnapshotLines = [
5
+ 'Primary provider: OpenCode.',
6
+ 'Manual checks: vgxness setup status; vgxness mcp doctor opencode.',
7
+ 'SDD cue: vgxness sdd next --project <project> --change <change>.',
8
+ 'No checks run here; copy and run commands explicitly when needed.',
9
+ ];
3
10
  const optionCopy = {
4
11
  setup: {
5
12
  label: 'Installation',
@@ -12,13 +19,6 @@ const optionCopy = {
12
19
  'Provider writes require final confirmation; OpenCode is the only automatic provider with explicit consent.',
13
20
  ],
14
21
  },
15
- dashboard: {
16
- label: 'Dashboard',
17
- description: 'Inspect project health, runs, approvals, SDD, agents, and skills.',
18
- badges: [tuiBadges.readOnly],
19
- detailTitle: 'Interactive dashboard',
20
- detailLines: ['Opens the existing read-only dashboard.', 'Dashboard navigation does not apply provider config or write OpenCode setup.'],
21
- },
22
22
  doctor: {
23
23
  label: 'Doctor / recovery',
24
24
  description: 'See health-check and recovery commands.',
@@ -63,8 +63,10 @@ export function buildMainMenuViewModel(state) {
63
63
  contextLines: ['Choose where to go next. Installation is first; the menu itself is read-only and does not write provider config.'],
64
64
  options,
65
65
  detail: { title: focused.detailTitle, lines: focused.detailLines, badges: focused.badges },
66
+ statusSnapshot: { title: 'Status snapshot', lines: statusSnapshotLines, badges: [tuiBadges.readOnly, tuiBadges.noProviderWrites] },
66
67
  safetyLines: [
67
68
  'Previews are read-only.',
69
+ 'Status snapshot is static guidance; no SQLite, doctor/status checks, provider calls, or provider config writes run from the main menu.',
68
70
  'Installation/provider writes require final confirmation.',
69
71
  'OpenCode is the only automatic provider path and still requires explicit consent.',
70
72
  ],
@@ -1,4 +1,4 @@
1
- import { choiceLine } from '../visual/index.js';
1
+ import { formatBadges, tuiBadges } from '../visual/badges.js';
2
2
  import { buildMainMenuViewModel } from './main-menu-read-model.js';
3
3
  export function renderMainMenuShape(input) {
4
4
  const state = input.width === undefined ? input.state : { ...input.state, viewport: { ...input.state.viewport, width: input.width } };
@@ -11,6 +11,8 @@ export function renderMainMenuShape(input) {
11
11
  ...vm.options.map(choiceLine),
12
12
  `Detail: ${vm.detail.title}${vm.detail.badges.length === 0 ? '' : ` ${vm.detail.badges.join(' ')}`}`,
13
13
  ...vm.detail.lines,
14
+ `${vm.statusSnapshot.title}${vm.statusSnapshot.badges.length === 0 ? '' : ` ${vm.statusSnapshot.badges.join(' ')}`}`,
15
+ ...vm.statusSnapshot.lines,
14
16
  'Safety',
15
17
  ...vm.safetyLines,
16
18
  ...vm.helpLines.map((line) => `Help: ${line}`),
@@ -21,9 +23,24 @@ export function renderMainMenuShape(input) {
21
23
  function clampLine(line, width) {
22
24
  if (line.length <= width)
23
25
  return line;
24
- const protectedPhrases = ['final confirmation', 'read-only', 'Requires confirmation', 'explicit consent', 'No provider writes', 'quit without writes'];
26
+ const protectedPhrases = [
27
+ 'final confirmation',
28
+ 'read-only',
29
+ 'Requires confirmation',
30
+ 'explicit consent',
31
+ 'No provider writes',
32
+ 'quit without writes',
33
+ 'vgxness setup status',
34
+ 'vgxness mcp doctor opencode',
35
+ 'no SQLite',
36
+ 'provider config writes',
37
+ ];
25
38
  const phrase = protectedPhrases.find((candidate) => line.includes(candidate));
26
39
  if (phrase !== undefined)
27
40
  return `${line.slice(0, Math.max(0, width - phrase.length - 5)).trim()} ... ${phrase}`.trim();
28
41
  return `${line.slice(0, Math.max(0, width - 1)).trim()}…`;
29
42
  }
43
+ function choiceLine(choice) {
44
+ const badges = formatBadges([...(choice.focused === true ? [tuiBadges.focused] : []), ...choice.badges]);
45
+ return `${choice.focused === true ? '›' : ' '} ${choice.label}${badges.length === 0 ? '' : ` ${badges}`} — ${choice.description}`;
46
+ }
@@ -1,5 +1,5 @@
1
1
  import { createTuiViewport } from '../visual/viewport.js';
2
- export const mainMenuOptionIds = ['setup', 'dashboard', 'doctor', 'sdd', 'advanced-cli', 'exit'];
2
+ export const mainMenuOptionIds = ['setup', 'doctor', 'sdd', 'advanced-cli', 'exit'];
3
3
  export function createMainMenuState(input = {}) {
4
4
  return {
5
5
  focusedOptionId: input.focusedOptionId ?? 'setup',