vgxness 1.10.1 → 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.
- package/README.md +10 -20
- package/dist/agents/canonical-agent-manifest.js +2 -2
- package/dist/behavior/behavior-contract-manifest.js +1 -3
- package/dist/behavior/behavior-contract-validation.js +0 -4
- package/dist/cli/cli-help.js +3 -9
- package/dist/cli/commands/index.js +2 -2
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +9 -153
- package/dist/cli/commands/setup-dispatcher.js +6 -50
- package/dist/cli/dispatcher.js +1 -8
- package/dist/cli/product-status-renderer.js +2 -2
- package/dist/cli/sdd-renderer.js +5 -5
- package/dist/mcp/client-install-claude-code.js +3 -2
- package/dist/mcp/client-install-opencode.js +3 -2
- package/dist/runs/execution-planning.js +3 -3
- package/dist/sdd/sdd-continuation-plan.js +5 -16
- package/dist/sdd/sdd-workflow-service.js +1 -1
- package/dist/setup/backup-rollback-service.js +10 -4
- package/dist/status/product-status.js +1 -1
- package/docs/architecture.md +13 -14
- package/docs/cli.md +12 -49
- package/docs/contributing.md +18 -3
- package/docs/glossary.md +5 -5
- package/docs/mcp.md +1 -1
- package/docs/prd.md +7 -7
- package/docs/project-health-audit-v1.10.x.md +115 -0
- package/docs/project-health-audit-v1.9.1.md +2 -0
- package/docs/providers.md +9 -37
- package/docs/roadmap.md +4 -10
- package/docs/safety.md +5 -21
- package/docs/storage.md +6 -5
- package/package.json +1 -3
- package/dist/cli/tui/main-menu/index.js +0 -6
- package/dist/cli/tui/main-menu/main-menu-actions.js +0 -34
- package/dist/cli/tui/main-menu/main-menu-controller.js +0 -11
- package/dist/cli/tui/main-menu/main-menu-read-model.js +0 -75
- package/dist/cli/tui/main-menu/main-menu-render-shape.js +0 -50
- package/dist/cli/tui/main-menu/main-menu-result.js +0 -1
- package/dist/cli/tui/main-menu/main-menu-state.js +0 -21
- package/dist/cli/tui/opentui/code/index.js +0 -210
- package/dist/cli/tui/opentui/code/screen.js +0 -107
- package/dist/cli/tui/opentui/code/smoke.js +0 -32
- package/dist/cli/tui/opentui/main-menu/index.js +0 -3
- package/dist/cli/tui/opentui/main-menu/renderer.js +0 -68
- package/dist/cli/tui/opentui/main-menu/screen.js +0 -66
- package/dist/cli/tui/opentui/main-menu/smoke.js +0 -17
- package/dist/cli/tui/opentui/main-menu/view.js +0 -8
- package/dist/cli/tui/opentui/setup/index.js +0 -3
- package/dist/cli/tui/opentui/setup/renderer.js +0 -87
- package/dist/cli/tui/opentui/setup/screen.js +0 -170
- package/dist/cli/tui/opentui/setup/smoke.js +0 -42
- package/dist/cli/tui/opentui/setup/view.js +0 -12
- package/dist/cli/tui/setup/setup-tui-actions.js +0 -1
- package/dist/cli/tui/setup/setup-tui-controller.js +0 -86
- package/dist/cli/tui/setup/setup-tui-input.js +0 -43
- package/dist/cli/tui/setup/setup-tui-read-model.js +0 -215
- package/dist/cli/tui/setup/setup-tui-render-shape.js +0 -171
- package/dist/cli/tui/setup/setup-tui-result.js +0 -1
- package/dist/cli/tui/setup/setup-tui-services.js +0 -79
- package/dist/cli/tui/setup/setup-tui-state.js +0 -193
- package/dist/cli/tui/setup/setup-tui-view-helpers.js +0 -62
- package/dist/code/cli/code-command.js +0 -104
- package/dist/code/config/defaults.js +0 -108
- package/dist/code/prompts/prompt-builder.js +0 -127
- package/dist/code/providers/credentials.js +0 -13
- package/dist/code/providers/fake-provider-adapter.js +0 -98
- package/dist/code/providers/message-mapper.js +0 -73
- package/dist/code/providers/openai-compatible-provider-adapter.js +0 -68
- package/dist/code/providers/provider-adapter.js +0 -10
- package/dist/code/providers/provider-registry.js +0 -38
- package/dist/code/providers/stream-normalizer.js +0 -34
- package/dist/code/reporting/redaction.js +0 -39
- package/dist/code/reporting/summary.js +0 -32
- package/dist/code/runtime/approval-coordinator.js +0 -468
- package/dist/code/runtime/code-runtime.js +0 -1031
- package/dist/code/runtime/gateways.js +0 -143
- package/dist/code/runtime/memory-service-gateway.js +0 -20
- package/dist/code/runtime/project-detection.js +0 -102
- package/dist/code/runtime/runs-code-run-gateway.js +0 -29
- package/dist/code/runtime/sdd-context.js +0 -164
- package/dist/code/runtime/sdd-workflow-gateway.js +0 -63
- package/dist/code/runtime/types.js +0 -1
- package/dist/code/runtime/verification-coordinator.js +0 -30
- package/dist/code/tools/read-only-executor.js +0 -145
- package/dist/code/tools/tool-definitions.js +0 -58
- package/dist/code/tools/tool-registry.js +0 -13
- package/dist/code/tools/tool-result-normalizer.js +0 -119
- package/dist/code/tools/workspace-executor.js +0 -278
- package/dist/code/tui/approval-actions.js +0 -33
- package/dist/code/tui/prompt-mode.js +0 -11
- package/dist/code/tui/runtime-events.js +0 -320
- package/docs/code-runtime.md +0 -221
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VGXNESS
|
|
2
2
|
|
|
3
|
-
VGXNESS is an installable CLI
|
|
3
|
+
VGXNESS is an installable CLI and MCP control plane for guided AI-agent workflows, SDD artifacts, local memory, and OpenCode integration.
|
|
4
4
|
|
|
5
5
|
## Release status and license
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ This package is proprietary software. The npm package ships inspectable JavaScri
|
|
|
8
8
|
|
|
9
9
|
OpenCode is the primary supported provider. Claude setup support is secondary. VGX-managed OpenCode and Claude provider configuration is user-global only; provider config writes require explicit CLI confirmation.
|
|
10
10
|
|
|
11
|
-
VGXNESS v1.
|
|
11
|
+
VGXNESS v1.10.x has a current project health audit describing the implemented CLI/MCP/SDD control plane, OpenCode health, known docs drift, interrupted runs, and the remaining execution/recovery gaps. See [Project health audit v1.10.x](./docs/project-health-audit-v1.10.x.md) for the current system snapshot; [v1.9.1](./docs/project-health-audit-v1.9.1.md) remains historical validation evidence for that release.
|
|
12
12
|
|
|
13
13
|
## Requirements
|
|
14
14
|
|
|
@@ -132,13 +132,13 @@ vgx --help # compatibility alias
|
|
|
132
132
|
|
|
133
133
|
## First setup with OpenCode
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
Preview the setup plan:
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
138
|
vgxness init
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
`vgxness init` is read-only by default, including in TTYs; apply still requires explicit `--yes`. For a copyable bootstrap and diagnostic path after installing the package globally:
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
144
|
vgxness setup plan
|
|
@@ -147,7 +147,6 @@ vgxness doctor
|
|
|
147
147
|
vgxness status --project <project> --change <change>
|
|
148
148
|
vgxness next --project <project> --change <change>
|
|
149
149
|
vgxness sdd continue --project <project> --change <change>
|
|
150
|
-
vgxness code sdd <change> <phase> --project <project> --save-artifact
|
|
151
150
|
```
|
|
152
151
|
|
|
153
152
|
Stable defaults are: package `vgxness`, provider `opencode`, global user data DB, user-global OpenCode config (`$HOME/.config/opencode/opencode.json`), and `mcp-plus-agents` mode. VGX-managed OpenCode and Claude provider configuration is user-global only; runtime VGXNESS state remains project-aware through `--project`, `--change`, workspace, and database context. Existing project-local provider files such as `.opencode/`, `opencode.json`, `.mcp.json`, `.claude/`, and `CLAUDE.md` remain untouched by VGXNESS setup. They may still affect OpenCode or Claude behavior externally, but VGXNESS treats them as external/manual diagnostics and will not repair, write, back up, or delete them. The generated MCP command for the global DB default is:
|
|
@@ -164,20 +163,11 @@ vgxness setup apply --yes
|
|
|
164
163
|
|
|
165
164
|
`vgxness setup plan` and `vgxness setup status` are human-readable and do not write provider config by default; local VGXNESS store initialization may occur when a command needs the selected SQLite store. `vgxness doctor`, `vgxness status`, `vgxness next`, `vgxness sdd status`, `vgxness sdd next`, `vgxness sdd continue`, 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.
|
|
166
165
|
|
|
167
|
-
The daily SDD happy path is OpenCode conversation with the installed VGXNESS MCP server and hidden SDD subagents. Use CLI
|
|
166
|
+
The daily SDD happy path is OpenCode conversation with the installed VGXNESS MCP server and hidden SDD subagents. Use CLI commands for bootstrap, setup, diagnostics, recovery, fallback, and scripting: `status`, `next`, and `sdd continue` inspect state and print read-only continuation guidance; `resume` helps inspect interrupted work. After a draft is ready, `sdd accept-artifact` records explicit human acceptance, and `sdd reopen-artifact` returns rejected artifacts to draft.
|
|
168
167
|
|
|
169
|
-
## Code runtime
|
|
168
|
+
## Code runtime status
|
|
170
169
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
vgxness code inspect "<question>" # read-only investigation
|
|
175
|
-
vgxness code plan "<task>" # read-only implementation plan
|
|
176
|
-
vgxness code craft-preview "<task>" # show the diff you would make
|
|
177
|
-
vgxness code craft "<task>" # approval-gated, bounded edit-capable work
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
Edits, shell, network, git mutations, SDD persistence, and memory saves route through explicit permission decisions. External workspace edits are denied, destructive commands require approval, and secret-like values are redacted from prompts, transcripts, and reports. See [Code runtime](./docs/code-runtime.md) and [Safety model](./docs/safety.md) for the full contract.
|
|
170
|
+
The experimental `vgxness code` runtime and principal OpenTUI code surface have been removed temporarily because they were copied OpenCode-like runtime work. Continue SDD work in OpenCode through VGXNESS MCP, and use the safe CLI commands above for diagnostics and recovery.
|
|
181
171
|
|
|
182
172
|
## Safety model
|
|
183
173
|
|
|
@@ -191,9 +181,9 @@ Edits, shell, network, git mutations, SDD persistence, and memory saves route th
|
|
|
191
181
|
- OpenCode is the primary supported provider; other providers are preview/manual extension points.
|
|
192
182
|
- VGXNESS exposes 41 typed MCP tools across SDD, memory, sessions, agents, skills, runs, providers, and verification. See [MCP tools](./docs/mcp.md).
|
|
193
183
|
|
|
194
|
-
##
|
|
184
|
+
## Principal entrypoint
|
|
195
185
|
|
|
196
|
-
Run `vgxness` with no arguments
|
|
186
|
+
Run `vgxness` with no arguments to print static safe guidance and exit 0 without opening local memory, importing OpenTUI, or writing provider config. `vgx` remains a compatibility alias.
|
|
197
187
|
|
|
198
188
|
For scripts, use explicit read-only commands with an explicit project:
|
|
199
189
|
|
|
@@ -266,9 +256,9 @@ Remove any user-global OpenCode/Claude config entries and local/global VGXNESS d
|
|
|
266
256
|
## More docs
|
|
267
257
|
|
|
268
258
|
- [CLI reference](./docs/cli.md)
|
|
259
|
+
- [Project health audit v1.10.x](./docs/project-health-audit-v1.10.x.md)
|
|
269
260
|
- [Project health audit v1.9.1](./docs/project-health-audit-v1.9.1.md)
|
|
270
261
|
- [Architecture](./docs/architecture.md)
|
|
271
|
-
- [Code runtime](./docs/code-runtime.md)
|
|
272
262
|
- [MCP tools](./docs/mcp.md)
|
|
273
263
|
- [Safety model](./docs/safety.md)
|
|
274
264
|
- [Storage](./docs/storage.md)
|
|
@@ -183,7 +183,7 @@ Daily SDD happens inside OpenCode through conversation, VGXNESS MCP, and hidden
|
|
|
183
183
|
- Proposal/spec/design/tasks: status/next -> readiness -> prerequisites -> exact subagent -> delegate -> persist by governance; if proposal is accepted, spec/design/tasks may run as the trusted draft autorun chain without extra confirmation, but drafts remain unaccepted.
|
|
184
184
|
- Apply/verify: require prerequisites -> artifacts -> exact subagent -> start/recover run -> preflight writes/shell/git/tests -> delegate -> checkpoint -> save -> finalize.
|
|
185
185
|
- Config/provider/prompt change: inspect manager/profile or payload first; persistent changes need explicit human authorization.
|
|
186
|
-
- Recovery: MCP first. Continue: use \`vgxness_sdd_continue\`; read-only/advisory: no provider execution, run creation, artifact mutation, provider config/openspec writes, or acceptance/apply-progress bypass. CLI \`vgxness sdd continue\` is human fallback only. \`vgxness resume --project\` is for candidate runs
|
|
186
|
+
- Recovery: MCP first. Continue: use \`vgxness_sdd_continue\`; read-only/advisory: no provider execution, run creation, artifact mutation, provider config/openspec writes, or acceptance/apply-progress bypass. CLI \`vgxness sdd continue\` is human fallback only. \`vgxness resume --project\` is for candidate runs. The removed experimental \`vgxness code\` runtime is not an SDD fallback.
|
|
187
187
|
|
|
188
188
|
## Delegation thresholds
|
|
189
189
|
Default to delegation for SDD phase-shaped work, repository exploration beyond one narrow lookup, implementation, verification, incident recovery, or multi-step analysis. Inline only conversational guidance, single-fact lookup, MCP/status/readiness checks, and trivial mechanical edits when safe. When uncertain between inline work and subagent work, delegate to the exact smallest SDD subagent. Never delegate to unknown agents; use exact SDD phase mapping.
|
|
@@ -203,7 +203,7 @@ const registryManagerInstructionsV10 = [
|
|
|
203
203
|
'Check SDD status/next/ready/cockpit, read prerequisites with sdd_get_artifact or sdd_list_artifacts, use public sdd_continue/internal vgxness_sdd_continue first for advisory read-only continuation plans, use sdd_reopen_artifact only for rejected artifacts returning to draft with explicit human actor/audit context, save phase output with sdd_save_artifact only by governance; when proposal is accepted, spec/design/tasks may run sequentially as draft-only autorun without extra confirmation, while acceptance remains human-only. Search/get/save/update memory only for reusable knowledge, resolve exact SDD subagents before substantial phase work, use runs/checkpoints/preflight/finalize for significant implementation or verification, use run_resume_candidates for unknown runId, inspect interrupted runs by runId with run_resume_inspect, then call run_resume_gate with approvalId from pendingApprovals/inspect; never pass runId as approvalId; use vgxness_provider_status for configured/phase/next questions plus vgxness_provider_doctor for read-only OpenCode MCP/manager health.',
|
|
204
204
|
'Prefer payloadMode=compact for manager-facing status/context reads, SDD artifact reads/lists, and activation handoffs so the primary context stays clean; request payloadMode=verbose only when full artifact contents, provider payloads, or skill context are actually needed, preferably inside delegated phase subagents.',
|
|
205
205
|
'MCP sdd_continue must not execute providers, create runs, mutate artifacts, write provider config/openspec, bypass human acceptance, or treat draft-run as apply-progress.',
|
|
206
|
-
'CLI is an escape hatch for bootstrap, doctor, rollback, recovery, MCP unavailable/setup missing, or explicit user request; do not tell users to run terminal SDD phase commands for normal daily flow. CLI vgxness sdd continue is a human/manual fallback only; vgxness resume --project is for candidate runs
|
|
206
|
+
'CLI is an escape hatch for bootstrap, doctor, rollback, recovery, MCP unavailable/setup missing, or explicit user request; do not tell users to run terminal SDD phase commands for normal daily flow. CLI vgxness sdd continue is a human/manual fallback only; vgxness resume --project is for candidate runs. The removed experimental vgxness code runtime is not an SDD fallback.',
|
|
207
207
|
'OpenCode native/provider tools are governance-v1 audit-only/non-hard-blocking; report warnings, never say they are hard-blocked by config.',
|
|
208
208
|
].join(' ');
|
|
209
209
|
const subagentData = {
|
|
@@ -12,13 +12,12 @@ export const criticalBehaviorContractInvariantIds = [
|
|
|
12
12
|
'context.manager-compact-default',
|
|
13
13
|
'context.progressive-disclosure',
|
|
14
14
|
'flow.provider-native-no-terminal-sdd-daily',
|
|
15
|
-
'scope.exclude-vgxcode-runtime',
|
|
16
15
|
'worktree.preserve-unrelated-user-work',
|
|
17
16
|
];
|
|
18
17
|
export const behaviorContractManifest = {
|
|
19
18
|
name: canonicalBehaviorContractName,
|
|
20
19
|
contractVersion: canonicalBehaviorContractVersion,
|
|
21
|
-
excludedTargets: [
|
|
20
|
+
excludedTargets: [],
|
|
22
21
|
invariants: [
|
|
23
22
|
{ id: 'sdd.acceptance.human-only', category: 'sdd', severity: 'critical', summary: 'SDD acceptance is recorded only from explicit human acceptance.' },
|
|
24
23
|
{ id: 'sdd.draft-is-not-accepted', category: 'sdd', severity: 'critical', summary: 'Draft, rejected, superseded, legacy, or unaccepted artifacts are not accepted prerequisites.' },
|
|
@@ -31,7 +30,6 @@ export const behaviorContractManifest = {
|
|
|
31
30
|
{ id: 'context.manager-compact-default', category: 'context', severity: 'critical', summary: 'Manager-facing context defaults to compact payloads.' },
|
|
32
31
|
{ id: 'context.progressive-disclosure', category: 'context', severity: 'critical', summary: 'Expanded and verbose context are requested only when needed.' },
|
|
33
32
|
{ id: 'flow.provider-native-no-terminal-sdd-daily', category: 'flow', severity: 'critical', summary: 'Daily SDD progression happens provider-natively through conversation and MCP, not mandatory terminal phase commands.' },
|
|
34
|
-
{ id: 'scope.exclude-vgxcode-runtime', category: 'scope', severity: 'critical', summary: 'This behavior contract excludes vgxcode and src/code runtime/prompt implementation targets.' },
|
|
35
33
|
{ id: 'worktree.preserve-unrelated-user-work', category: 'worktree', severity: 'critical', summary: 'Unrelated user work and dirty files are preserved.' },
|
|
36
34
|
],
|
|
37
35
|
};
|
|
@@ -22,10 +22,6 @@ export function validateBehaviorContractManifest(manifest = behaviorContractMani
|
|
|
22
22
|
else if (invariant.severity !== 'critical')
|
|
23
23
|
errors.push(`critical invariant ${id} must have severity critical`);
|
|
24
24
|
}
|
|
25
|
-
for (const target of ['vgxcode', 'src/code/runtime/*', 'src/code/prompts/*']) {
|
|
26
|
-
if (!manifest.excludedTargets.includes(target))
|
|
27
|
-
errors.push(`missing excluded target: ${target}`);
|
|
28
|
-
}
|
|
29
25
|
return { ok: errors.length === 0, errors };
|
|
30
26
|
}
|
|
31
27
|
export function validateBehaviorContractProjection(metadata, manifest = behaviorContractManifest) {
|
package/dist/cli/cli-help.js
CHANGED
|
@@ -41,12 +41,7 @@ Areas:
|
|
|
41
41
|
|
|
42
42
|
opencode preview --provider opencode (--agent <name> | --agent-id <id>) --project <name> --change <id> --phase <phase> [--scope project|personal]
|
|
43
43
|
|
|
44
|
-
code
|
|
45
|
-
code plan "<task>" [--json|--events-jsonl] [--max-source-bytes <n>] [--provider fake|openai-compatible] [--model <id>] [--stream] [--transcript off|summary|full] [--memory off|ask|auto]
|
|
46
|
-
code craft-preview "<task>" [--events-jsonl] [--provider fake|openai-compatible] [--model <id>] [--stream]
|
|
47
|
-
code craft "<task>" [--json|--events-jsonl --approval-channel stdio] [--max-source-bytes <n>] [--provider fake|openai-compatible] [--model <id>] [--stream] [--approval-policy ask|allow|deny] [--verification none|suggest|run|repair] [--transcript off|summary|full] [--memory off|ask|auto]
|
|
48
|
-
code sdd <change> <phase> [--json] [--save-artifact] [--draft-run] [--provider fake|openai-compatible] [--model <id>] [--stream] [--verification none|suggest|run|repair] [--transcript off|summary|full] [--memory off|ask|auto]
|
|
49
|
-
VGXNESS Code inspect and plan are native read-only repository flows. Craft is bounded edit-capable work with approval-gated edits and shell verification; craft JSONL approvals require explicit --approval-channel stdio. SDD mode follows phase-specific artifact boundaries and saves only with --save-artifact. --draft-run lets planning phases use draft prerequisites only; human acceptance is still required and apply-progress remains gated.
|
|
44
|
+
The experimental vgxness code runtime and principal OpenTUI code surface were removed and are temporarily unavailable. Daily SDD progression should happen inside OpenCode through conversation, VGXNESS MCP, and hidden SDD subagents; use status/next/sdd continue for read-only CLI guidance.
|
|
50
45
|
|
|
51
46
|
orchestrator preview --project <name> --intent <text> [--change <id>] [--db <path>]
|
|
52
47
|
Orchestrator preview classifies natural-language requests only; it never executes providers, edits files, records runs, or writes provider config.
|
|
@@ -102,9 +97,8 @@ Areas:
|
|
|
102
97
|
subagents list --parent-agent-id <id>
|
|
103
98
|
subagents get --id <id> | --project <name> --name <name> [--scope project|personal]
|
|
104
99
|
|
|
105
|
-
No args
|
|
106
|
-
|
|
107
|
-
Setup TUI may launch without --project; Installation remains available and project-scoped checks are deferred while project screens render project-required recovery states.
|
|
100
|
+
No args prints static safe guidance and exits 0 without opening project state, importing OpenTUI, or writing provider config.
|
|
101
|
+
Setup is CLI-only: use setup plan/status for read-only guidance and setup apply --yes only after review.
|
|
108
102
|
Provider setup support: OpenCode first-class supported default guided install; Claude first-class supported guarded user-global install; project/local provider files are diagnostics only; Antigravity placeholder; Custom/future extension point.
|
|
109
103
|
Provider config writes/install/apply are external-only and require explicit confirmation.
|
|
110
104
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { runAgentCommand, runSkillCommand, runSubagentCommand } from './agent-skill-dispatcher.js';
|
|
2
|
-
export {
|
|
2
|
+
export { 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';
|
|
6
6
|
export { runProductNextCommand, runProductResumeCommand, runProductStatusCommand } from './status-dispatcher.js';
|
|
7
|
-
export { applySetupPlanInput, collectRunDetails, collectRunInsights, createSetupLifecycleService, promptSetupWizard, readSetupStatus, runInitCommand, runSetupApplyCommand, runSetupBackupCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand,
|
|
7
|
+
export { applySetupPlanInput, collectRunDetails, collectRunInsights, createSetupLifecycleService, promptSetupWizard, readSetupStatus, runInitCommand, runSetupApplyCommand, runSetupBackupCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand, setupMcpEvidence, setupPlanInputFromFlags, } from './setup-dispatcher.js';
|
|
8
8
|
export { runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand } from './workflow-dispatcher.js';
|
|
9
9
|
export { runVerificationPlanCommand, runVerificationReportCommand } from './verification-dispatcher.js';
|
|
@@ -1,158 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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() {
|
|
1
|
+
import { okText } from '../cli-help.js';
|
|
2
|
+
function defaultNoArgsGuidance() {
|
|
15
3
|
return ([
|
|
16
|
-
'VGXNESS
|
|
17
|
-
'
|
|
4
|
+
'VGXNESS no-args entrypoint is safe and deterministic; no local DB was opened and no provider config was written.',
|
|
5
|
+
'The experimental principal code/OpenTUI surface was removed and is temporarily unavailable.',
|
|
6
|
+
'Next: use `vgxness status`, `vgxness next`, `vgxness init --plan`, `vgxness setup plan`, or `vgxness --help`.',
|
|
18
7
|
].join('\n') + '\n');
|
|
19
8
|
}
|
|
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 dashboard; 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
9
|
export async function runDefaultInteractiveEntrypoint(environment) {
|
|
58
|
-
|
|
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 draftRunFlag = parsed.flags['draft-run'];
|
|
73
|
-
if (draftRunFlag !== undefined && command !== 'sdd')
|
|
74
|
-
return usageFailure('--draft-run is supported only for code sdd');
|
|
75
|
-
if (draftRunFlag !== undefined && draftRunFlag !== true)
|
|
76
|
-
return usageFailure('--draft-run does not accept a value; use --draft-run for code sdd draft mode');
|
|
77
|
-
const sddRuntimeMode = draftRunFlag === true ? 'draft-run' : undefined;
|
|
78
|
-
const maxSourceBytes = optionalNumberFlag(parsed.flags, 'max-source-bytes');
|
|
79
|
-
if (!maxSourceBytes.ok)
|
|
80
|
-
return resultFailure(maxSourceBytes);
|
|
81
|
-
const output = parsed.flags.json === true || optionalStringFlag(parsed.flags, 'output') === 'json' ? 'json' : 'human';
|
|
82
|
-
const approvalPolicy = codeApprovalPolicyFlag(parsed.flags);
|
|
83
|
-
if (!approvalPolicy.ok)
|
|
84
|
-
return resultFailure(approvalPolicy);
|
|
85
|
-
const verificationMode = codeVerificationModeFlag(parsed.flags);
|
|
86
|
-
if (!verificationMode.ok)
|
|
87
|
-
return resultFailure(verificationMode);
|
|
88
|
-
const transcriptMode = codeTranscriptModeFlag(parsed.flags);
|
|
89
|
-
if (!transcriptMode.ok)
|
|
90
|
-
return resultFailure(transcriptMode);
|
|
91
|
-
const memoryPolicy = codeMemoryPolicyFlag(parsed.flags);
|
|
92
|
-
if (!memoryPolicy.ok)
|
|
93
|
-
return resultFailure(memoryPolicy);
|
|
94
|
-
const provider = optionalStringFlag(parsed.flags, 'provider');
|
|
95
|
-
const model = optionalStringFlag(parsed.flags, 'model');
|
|
96
|
-
if (eventsJsonl) {
|
|
97
|
-
if (approvalChannel.value === 'stdio' && (environment.stdin === undefined || environment.stdout === undefined))
|
|
98
|
-
return resultFailure(validationFailure('--approval-channel stdio requires CLI stdin and stdout streams'));
|
|
99
|
-
return await runCodeCommand({
|
|
100
|
-
command,
|
|
101
|
-
args: parsed.positionals.slice(2),
|
|
102
|
-
cwd: environment.cwd,
|
|
103
|
-
output,
|
|
104
|
-
runGateway: new InMemoryRunGateway(),
|
|
105
|
-
project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
|
|
106
|
-
...(provider === undefined ? {} : { provider }),
|
|
107
|
-
...(model === undefined ? {} : { model }),
|
|
108
|
-
stream: parsed.flags.stream === true,
|
|
109
|
-
env: environment.env,
|
|
110
|
-
eventsJsonl,
|
|
111
|
-
memoryPolicy: 'off',
|
|
112
|
-
...(approvalChannel.value === undefined ? {} : { approvalChannel: approvalChannel.value }),
|
|
113
|
-
...(approvalChannel.value === 'stdio' ? { approvalDecisionInput: environment.stdin, eventOutput: environment.stdout } : {}),
|
|
114
|
-
...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
|
|
115
|
-
...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
|
|
116
|
-
...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
|
|
117
|
-
...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
|
|
118
|
-
...(sddRuntimeMode === undefined ? {} : { sddRuntimeMode }),
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
const selectedDatabasePath = databasePathFor(parsed.flags, environment);
|
|
122
|
-
if (!selectedDatabasePath.ok)
|
|
123
|
-
return resultFailure(selectedDatabasePath);
|
|
124
|
-
const opened = openCliDatabase(selectedDatabasePath.value);
|
|
125
|
-
if (!opened.ok)
|
|
126
|
-
return resultFailure(opened);
|
|
127
|
-
try {
|
|
128
|
-
const runs = new RunService(opened.value);
|
|
129
|
-
const memory = new MemoryService(opened.value);
|
|
130
|
-
return await runCodeCommand({
|
|
131
|
-
command,
|
|
132
|
-
args: parsed.positionals.slice(2),
|
|
133
|
-
cwd: environment.cwd,
|
|
134
|
-
output,
|
|
135
|
-
runGateway: new RunsCodeRunGateway(runs),
|
|
136
|
-
sddGateway: new SddWorkflowGateway(new SddWorkflowService(memory)),
|
|
137
|
-
memoryGateway: new MemoryServiceCodeGateway(memory),
|
|
138
|
-
project: optionalStringFlag(parsed.flags, 'project') ?? 'vgxness',
|
|
139
|
-
...(provider === undefined ? {} : { provider }),
|
|
140
|
-
...(model === undefined ? {} : { model }),
|
|
141
|
-
stream: parsed.flags.stream === true,
|
|
142
|
-
env: environment.env,
|
|
143
|
-
eventsJsonl,
|
|
144
|
-
persistArtifact: parsed.flags['save-artifact'] === true || parsed.flags.persist === true,
|
|
145
|
-
...(sddRuntimeMode === undefined ? {} : { sddRuntimeMode }),
|
|
146
|
-
...(maxSourceBytes.value !== undefined ? { maxSourceBytes: maxSourceBytes.value } : {}),
|
|
147
|
-
...(approvalPolicy.value === undefined ? {} : { approvalPolicy: approvalPolicy.value }),
|
|
148
|
-
...(verificationMode.value === undefined ? {} : { verificationMode: verificationMode.value }),
|
|
149
|
-
...(transcriptMode.value === undefined ? {} : { transcriptMode: transcriptMode.value }),
|
|
150
|
-
...(memoryPolicy.value === undefined ? {} : { memoryPolicy: memoryPolicy.value }),
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
finally {
|
|
154
|
-
opened.value.close();
|
|
155
|
-
}
|
|
10
|
+
void environment;
|
|
11
|
+
return okText(defaultNoArgsGuidance());
|
|
156
12
|
}
|
|
157
|
-
// Re-export
|
|
158
|
-
export {
|
|
13
|
+
// Re-export helper for focused CLI tests.
|
|
14
|
+
export { defaultNoArgsGuidance };
|
|
@@ -9,13 +9,11 @@ import { applyRollbackConfigBackup, listProviderConfigBackups, previewRollbackCo
|
|
|
9
9
|
import { vgxnessSetupDefaults } from '../../setup/setup-defaults.js';
|
|
10
10
|
import { SetupLifecycleService } from '../../setup/setup-lifecycle-service.js';
|
|
11
11
|
import { createSetupPlan } from '../../setup/setup-plan.js';
|
|
12
|
-
import { databasePathFor,
|
|
12
|
+
import { databasePathFor, opencodeInstallScopeFlag, optionalStringFlag, providerUserGlobalOnlyMigrationMessage, scopeFlag, setupDatabaseFlags, setupInstallModeFlag, setupProviderFlag, } from '../cli-flags.js';
|
|
13
13
|
import { okText, usageFailure, validationFailure } from '../cli-help.js';
|
|
14
14
|
import { jsonResult, openCliDatabase, resultFailure } from '../cli-helpers.js';
|
|
15
15
|
import { renderSetupPlan } from '../setup-plan-renderer.js';
|
|
16
16
|
import { renderSetupStatus } from '../setup-status-renderer.js';
|
|
17
|
-
import { createDefaultSetupTuiServices } from '../tui/setup/setup-tui-services.js';
|
|
18
|
-
import { canRunInteractiveTui } from '../tui/terminal-capabilities.js';
|
|
19
17
|
function renderSetupRollbackApply(result, parsed) {
|
|
20
18
|
if (parsed.flags.json === true)
|
|
21
19
|
return jsonResult(result);
|
|
@@ -344,63 +342,21 @@ export function promptLineExport(environment, prompt) {
|
|
|
344
342
|
export function renderSetupPlanForHumansExport(plan) {
|
|
345
343
|
return renderSetupPlanForHumans(plan);
|
|
346
344
|
}
|
|
347
|
-
export function resolveInitDispatchMode(parsed,
|
|
345
|
+
export function resolveInitDispatchMode(parsed, _environment) {
|
|
348
346
|
if (parsed.flags.plan === true || parsed.flags.json === true)
|
|
349
347
|
return 'setup-plan';
|
|
350
348
|
if (parsed.flags.yes === true)
|
|
351
349
|
return 'setup-apply';
|
|
352
|
-
return
|
|
350
|
+
return 'setup-plan';
|
|
353
351
|
}
|
|
354
352
|
export async function runInitCommand(parsed, environment) {
|
|
355
|
-
return
|
|
353
|
+
return runInitCommandWithoutSetupTui(parsed, environment);
|
|
356
354
|
}
|
|
357
|
-
export async function
|
|
355
|
+
export async function runInitCommandWithoutSetupTui(parsed, environment) {
|
|
358
356
|
const mode = resolveInitDispatchMode(parsed, environment);
|
|
359
357
|
if (mode === 'setup-plan')
|
|
360
358
|
return runSetupPlanCommand(parsed, environment);
|
|
361
|
-
|
|
362
|
-
return runSetupApplyCommand({ ...parsed, flags: { ...parsed.flags, yes: true } }, environment);
|
|
363
|
-
const project = optionalStringFlag(parsed.flags, 'project');
|
|
364
|
-
return setupTui(environment, project === undefined ? undefined : { project });
|
|
365
|
-
}
|
|
366
|
-
export async function runSetupTuiCommand(environment, input) {
|
|
367
|
-
if (!canRunInteractiveTui(environment.stdin, environment.stdout))
|
|
368
|
-
return okText('Setup TUI requires an interactive TTY. [read-only] No provider config was written. Run `vgxness init --plan` or `vgxness setup plan` for read-only preview output; apply later with `vgxness setup apply --yes` only after review.\n');
|
|
369
|
-
const selectedDatabasePath = databasePathSelectionFor({}, environment);
|
|
370
|
-
if (!selectedDatabasePath.ok)
|
|
371
|
-
return resultFailure(selectedDatabasePath);
|
|
372
|
-
const opened = input?.lifecycle === undefined ? openCliDatabase(selectedDatabasePath.value.path) : undefined;
|
|
373
|
-
if (opened !== undefined && !opened.ok)
|
|
374
|
-
return resultFailure(opened);
|
|
375
|
-
const lifecycle = input?.lifecycle ??
|
|
376
|
-
createSetupLifecycleService({ opened: opened ?? validationFailure('Store is unavailable.'), databasePath: selectedDatabasePath.value.path, environment });
|
|
377
|
-
const project = input?.project ?? environment.cwd.replace(/[/]+$/, '').split(/[/]/).pop() ?? 'vgxness';
|
|
378
|
-
const runtime = {
|
|
379
|
-
project,
|
|
380
|
-
workspaceRoot: environment.cwd,
|
|
381
|
-
env: environment.env,
|
|
382
|
-
selections: {
|
|
383
|
-
databaseMode: vgxnessSetupDefaults.defaultDatabaseMode,
|
|
384
|
-
provider: vgxnessSetupDefaults.defaultProvider,
|
|
385
|
-
scope: vgxnessSetupDefaults.defaultOpenCodeScope,
|
|
386
|
-
installMode: vgxnessSetupDefaults.defaultInstallMode,
|
|
387
|
-
overwriteVgxness: false,
|
|
388
|
-
},
|
|
389
|
-
};
|
|
390
|
-
try {
|
|
391
|
-
const { renderOpenTuiSetup } = await import('../tui/opentui/setup/index.js');
|
|
392
|
-
await renderOpenTuiSetup({
|
|
393
|
-
services: createDefaultSetupTuiServices({ lifecycle, cwd: environment.cwd, env: environment.env }),
|
|
394
|
-
runtime,
|
|
395
|
-
stdin: environment.stdin,
|
|
396
|
-
stdout: environment.stdout,
|
|
397
|
-
});
|
|
398
|
-
return { exitCode: 0, stdout: '', stderr: '' };
|
|
399
|
-
}
|
|
400
|
-
finally {
|
|
401
|
-
if (opened?.ok)
|
|
402
|
-
opened.value.close();
|
|
403
|
-
}
|
|
359
|
+
return runSetupApplyCommand({ ...parsed, flags: { ...parsed.flags, yes: true } }, environment);
|
|
404
360
|
}
|
|
405
361
|
export function createSetupLifecycleService(input) {
|
|
406
362
|
return new SetupLifecycleService({
|
package/dist/cli/dispatcher.js
CHANGED
|
@@ -5,7 +5,7 @@ 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
7
|
import { runBootAgentSeedUpgrade } from '../agents/boot-upgrade.js';
|
|
8
|
-
import { runAgentCommand, runApprovalsCommand,
|
|
8
|
+
import { runAgentCommand, runApprovalsCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runProductNextCommand, runProductResumeCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand, runProductStatusCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
|
|
9
9
|
const _promptBuffers = new WeakMap();
|
|
10
10
|
const require = createRequire(import.meta.url);
|
|
11
11
|
const packageJson = require('../../package.json');
|
|
@@ -110,8 +110,6 @@ export async function dispatchCliAsync(argv, environment) {
|
|
|
110
110
|
}
|
|
111
111
|
if (area === 'doctor')
|
|
112
112
|
return runDoctorAliasCommand(parsed, environment);
|
|
113
|
-
if (area === 'code')
|
|
114
|
-
return runCodeCliCommand(parsed, environment);
|
|
115
113
|
if (area === 'init')
|
|
116
114
|
return runInitCommand(parsed, environment);
|
|
117
115
|
if (area === 'setup' && command === 'apply')
|
|
@@ -228,10 +226,5 @@ function validateCommand(area, command) {
|
|
|
228
226
|
if (area === 'verification') {
|
|
229
227
|
return command === 'plan' || command === 'report' ? { ok: true } : { ok: false, message: `Unknown verification command: ${command}` };
|
|
230
228
|
}
|
|
231
|
-
if (area === 'code') {
|
|
232
|
-
return command === 'inspect' || command === 'plan' || command === 'craft' || command === 'sdd'
|
|
233
|
-
? { ok: true }
|
|
234
|
-
: { ok: false, message: `Unknown code command: ${command}` };
|
|
235
|
-
}
|
|
236
229
|
return { ok: false, message: `Unknown command area: ${area}` };
|
|
237
230
|
}
|
|
@@ -44,7 +44,7 @@ function buildBlockedNextCommand(status) {
|
|
|
44
44
|
return `vgxness next --project ${status.project.value} --change ${change}${dbHint}`;
|
|
45
45
|
}
|
|
46
46
|
export function renderProductNext(next) {
|
|
47
|
-
const commandHeading = next.blocked ? 'Recovery/diagnostic command' : '
|
|
47
|
+
const commandHeading = next.blocked ? 'Recovery/diagnostic command' : 'Continuation guidance command';
|
|
48
48
|
const lines = [
|
|
49
49
|
'Next',
|
|
50
50
|
...next.next.map((line) => `- ${line}`),
|
|
@@ -64,7 +64,7 @@ export function renderProductNext(next) {
|
|
|
64
64
|
}
|
|
65
65
|
function productCommandHeading(status) {
|
|
66
66
|
if (status.sddNextStatus === 'runnable')
|
|
67
|
-
return '
|
|
67
|
+
return 'Continuation guidance command';
|
|
68
68
|
return 'Recovery/diagnostic command';
|
|
69
69
|
}
|
|
70
70
|
function relatedRunContextLines(relatedRunContext, includeTrailingBlank) {
|
package/dist/cli/sdd-renderer.js
CHANGED
|
@@ -5,13 +5,13 @@ export function renderSddStatus(input) {
|
|
|
5
5
|
const blockers = input.status.phases.filter((phase) => phase.present && phase.accepted !== true);
|
|
6
6
|
const complete = input.status.phases.length > 0 && input.status.phases.every((phase) => phase.present && phase.accepted === true);
|
|
7
7
|
const statusLabel = complete ? 'complete' : input.status.nextReadyPhase === undefined ? 'blocked' : 'ready';
|
|
8
|
-
const directPhaseCommand = input.status.nextReadyPhase === undefined ? undefined : `vgxness
|
|
8
|
+
const directPhaseCommand = input.status.nextReadyPhase === undefined ? undefined : `vgxness sdd continue --project ${input.project} --change ${input.status.change}`;
|
|
9
9
|
const recommendedAction = complete
|
|
10
10
|
? 'No next SDD phase remains for this change.'
|
|
11
11
|
: input.status.nextReadyPhase === undefined
|
|
12
12
|
? 'Review blockers or accept present draft artifacts before continuing.'
|
|
13
13
|
: `Continue the ${input.status.nextReadyPhase} phase in OpenCode using VGXNESS MCP and hidden SDD subagents.`;
|
|
14
|
-
const commandLabel = directPhaseCommand === undefined ? 'Diagnostic command' : '
|
|
14
|
+
const commandLabel = directPhaseCommand === undefined ? 'Diagnostic command' : 'Continuation guidance command';
|
|
15
15
|
const lines = [
|
|
16
16
|
'SDD Status',
|
|
17
17
|
`Project: ${input.project}`,
|
|
@@ -39,9 +39,9 @@ export function renderSddNext(input) {
|
|
|
39
39
|
const guidance = input.decision.blockerGuidance ?? [];
|
|
40
40
|
const phase = input.decision.nextPhase ?? 'none';
|
|
41
41
|
const commandGuidance = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined
|
|
42
|
-
? `vgxness
|
|
42
|
+
? `vgxness sdd continue --project ${input.project} --change ${input.decision.change}`
|
|
43
43
|
: `vgxness sdd status --project ${input.project} --change ${input.decision.change}`;
|
|
44
|
-
const commandLabel = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined ? '
|
|
44
|
+
const commandLabel = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined ? 'Continuation guidance command' : 'Diagnostic command';
|
|
45
45
|
const primaryAction = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined
|
|
46
46
|
? `Continue the ${input.decision.nextPhase} phase in OpenCode using VGXNESS MCP and hidden SDD subagents.`
|
|
47
47
|
: input.decision.recommendedAction;
|
|
@@ -76,7 +76,7 @@ export function renderSddNext(input) {
|
|
|
76
76
|
return `${lines.join('\n')}\n`;
|
|
77
77
|
}
|
|
78
78
|
export function renderSddContinuationPlan(plan) {
|
|
79
|
-
const suggestedCommandLabel = plan.status === 'runnable' ? '
|
|
79
|
+
const suggestedCommandLabel = plan.status === 'runnable' ? 'Continuation guidance command' : 'Diagnostic command';
|
|
80
80
|
const lines = [
|
|
81
81
|
'SDD Continue (read-only)',
|
|
82
82
|
`Project: ${plan.project}`,
|
|
@@ -129,7 +129,7 @@ function writeProjectMemory(plan) {
|
|
|
129
129
|
async function applyUserInstall(input, plan, server, writtenPaths, backups) {
|
|
130
130
|
const existingTargets = plan.targets.filter((target) => target.kind !== 'cli-mcp-registration' && (target.action === 'merge' || target.action === 'update-vgxness' || target.action === 'append-managed-block' || target.action === 'update-managed-block'));
|
|
131
131
|
for (const target of existingTargets) {
|
|
132
|
-
const backup = createBackup(target.path, target.kind === 'user-memory' ? 'user-memory' : 'config', 'user');
|
|
132
|
+
const backup = createBackup(target.path, target.kind === 'user-memory' ? 'user-memory' : 'config', 'user', input.env?.HOME);
|
|
133
133
|
if (!backup.ok)
|
|
134
134
|
return refusal('backup_failed', backup.error.message, plan, server, writtenPaths, backups);
|
|
135
135
|
backups.push(toBackupSummary(backup.value));
|
|
@@ -173,7 +173,7 @@ function writeUserMemory(env, plan) {
|
|
|
173
173
|
const after = inspectClaudeUserMemory(env);
|
|
174
174
|
return after.status === 'managed-current' ? { ok: true, value: target.path } : { ok: false, error: { code: 'validation_failed', message: 'Claude user memory did not validate as managed-current after write.' } };
|
|
175
175
|
}
|
|
176
|
-
function createBackup(path, kind, scope = 'project') {
|
|
176
|
+
function createBackup(path, kind, scope = 'project', allowedManagedHome) {
|
|
177
177
|
return createManagedProviderConfigBackup({
|
|
178
178
|
targetPath: path,
|
|
179
179
|
provider: 'claude',
|
|
@@ -181,6 +181,7 @@ function createBackup(path, kind, scope = 'project') {
|
|
|
181
181
|
createdByOperation: 'mcp-client-install-claude-code',
|
|
182
182
|
reason: kind === 'project-memory' ? 'pre-project-memory-update-safety' : kind === 'user-memory' ? 'pre-user-memory-update-safety' : 'pre-merge-safety',
|
|
183
183
|
description: kind === 'project-memory' ? 'Backup existing Claude Code project memory before appending or updating the VGXNESS managed block.' : kind === 'user-memory' ? 'Backup existing Claude Code user memory before appending or updating the VGXNESS managed block.' : 'Backup existing Claude Code config before merging VGXNESS MCP or agent configuration.',
|
|
184
|
+
...(allowedManagedHome !== undefined ? { allowedManagedHome } : {}),
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
187
|
function refusal(reason, message, plan, server, writtenPaths, backups, cliResult) {
|
|
@@ -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)) {
|
|
@@ -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
|
|
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
|
|
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
|
|
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')
|