vgxness 1.9.3 → 1.9.4
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 +4 -3
- package/dist/agents/canonical-agent-manifest.js +35 -9
- package/dist/agents/canonical-agent-projection.js +15 -0
- package/dist/cli/commands/mcp-dispatcher.js +49 -18
- package/dist/cli/commands/setup-dispatcher.js +22 -10
- package/dist/cli/product-status-renderer.js +9 -2
- package/dist/cli/sdd-renderer.js +15 -9
- package/dist/cli/tui/main-menu/main-menu-read-model.js +8 -8
- package/dist/cli/tui/setup/setup-tui-services.js +27 -10
- package/dist/mcp/client-install-opencode-contract.js +2 -2
- package/dist/mcp/client-install-opencode.js +10 -6
- package/dist/mcp/opencode-default-agent-config.js +7 -4
- package/dist/status/product-status.js +5 -1
- package/docs/cli.md +16 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -138,7 +138,7 @@ Run the guided setup wizard in a TTY:
|
|
|
138
138
|
vgxness init
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
In non-TTY shells, `vgxness init` prints the same read-only setup plan instead of prompting. For a copyable
|
|
141
|
+
In non-TTY shells, `vgxness init` prints the same read-only setup plan instead of prompting. For a copyable bootstrap and diagnostic path after installing the package globally:
|
|
142
142
|
|
|
143
143
|
```bash
|
|
144
144
|
vgxness setup plan
|
|
@@ -147,6 +147,7 @@ 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
|
|
150
151
|
```
|
|
151
152
|
|
|
152
153
|
Stable defaults are: package `vgxness`, provider `opencode`, global user data DB, user/global OpenCode scope (`$HOME/.config/opencode/opencode.json`), and `mcp-plus-agents` mode. Use `--scope project` only when you intentionally want `<workspace>/.opencode/opencode.json`. The generated MCP command for the global DB default is:
|
|
@@ -163,7 +164,7 @@ vgxness setup apply --yes
|
|
|
163
164
|
|
|
164
165
|
`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.
|
|
165
166
|
|
|
166
|
-
The SDD happy path is `status
|
|
167
|
+
The daily SDD happy path is OpenCode conversation with the installed VGXNESS MCP server and hidden SDD subagents. Use CLI/TUI commands for bootstrap, setup, diagnostics, recovery, fallback, and scripting: `status`, `next`, and `sdd continue` inspect state and print manual fallback guidance; `code sdd` remains available for an explicit manual fallback run; `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. Draft-run suggestions are planning-only: human acceptance is still required, and `apply-progress` remains gated.
|
|
167
168
|
|
|
168
169
|
## Code runtime (`vgxness code`)
|
|
169
170
|
|
|
@@ -182,7 +183,7 @@ Edits, shell, network, git mutations, SDD persistence, and memory saves route th
|
|
|
182
183
|
|
|
183
184
|
- Preview, status, and plan commands do not write provider config; local VGXNESS store initialization may occur where the command needs SQLite-backed state.
|
|
184
185
|
- Provider config writes require explicit `--yes` confirmation.
|
|
185
|
-
- Setup/status TUI surfaces are
|
|
186
|
+
- Setup/status TUI surfaces are read-only setup, diagnostics, recovery, and fallback surfaces; daily SDD progression stays in OpenCode with VGXNESS MCP.
|
|
186
187
|
- SDD artifacts are SQLite-backed through VGXNESS services. Do not create or write `openspec/`.
|
|
187
188
|
- `vgxness sdd accept-artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
|
|
188
189
|
- `vgxness sdd reopen-artifact` is the explicit path from a rejected artifact back to draft before revision.
|
|
@@ -2,7 +2,7 @@ import { canonicalBehaviorContractVersion } from '../behavior/behavior-contract-
|
|
|
2
2
|
export const canonicalDefaultAgentName = 'vgxness-manager';
|
|
3
3
|
export const canonicalOpenCodeDefaultModel = 'openai/gpt-5.5';
|
|
4
4
|
export const canonicalOpenCodeManagerReasoningEffort = 'high';
|
|
5
|
-
export const canonicalPromptContractVersion =
|
|
5
|
+
export const canonicalPromptContractVersion = 10;
|
|
6
6
|
export const canonicalSddSubagentNames = [
|
|
7
7
|
'vgxness-sdd-explore',
|
|
8
8
|
'vgxness-sdd-propose',
|
|
@@ -78,13 +78,25 @@ function managerDefinition() {
|
|
|
78
78
|
builtIn: true,
|
|
79
79
|
name: canonicalDefaultAgentName,
|
|
80
80
|
description: 'Coordinates VGXNESS MCP state and SDD sub-agents while routing Tier 0-2 lightweight work, Tier 3 preflight validation, and Tier 4 formal SDD.',
|
|
81
|
-
instructions: { kind: 'inline', value:
|
|
81
|
+
instructions: { kind: 'inline', value: registryManagerInstructionsV10 },
|
|
82
82
|
capabilities: ['sdd-orchestration', 'agent-routing', 'mcp-coordination', 'project-local-automation'],
|
|
83
83
|
permissions: { read: 'allow', edit: 'ask', shell: 'ask', git: 'ask', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' },
|
|
84
84
|
memory: { scopes: ['project'] },
|
|
85
85
|
workflows: ['explore', 'quickfix', 'plan', 'build', 'debug', 'sdd', 'agent-seeding', 'opencode-install'],
|
|
86
86
|
skills: ['vgxness-sdd-manager'],
|
|
87
|
-
adapters: {
|
|
87
|
+
adapters: {
|
|
88
|
+
opencode: {
|
|
89
|
+
model: canonicalOpenCodeDefaultModel,
|
|
90
|
+
config: {
|
|
91
|
+
options: {
|
|
92
|
+
reasoningEffort: canonicalOpenCodeManagerReasoningEffort,
|
|
93
|
+
vgxnessPromptContractVersion: canonicalPromptContractVersion,
|
|
94
|
+
vgxnessBehaviorContractVersion: canonicalBehaviorContractVersion,
|
|
95
|
+
},
|
|
96
|
+
permission: { task: createCanonicalOpenCodeSddTaskPermissions(), ...createCanonicalOpenCodeSddMcpToolPermissions() },
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
88
100
|
providerSupport: commonSupport(),
|
|
89
101
|
};
|
|
90
102
|
}
|
|
@@ -110,6 +122,19 @@ function subagentDefinition(name) {
|
|
|
110
122
|
export function createCanonicalOpenCodeSddTaskPermissions() {
|
|
111
123
|
return Object.fromEntries([['*', 'deny'], ...canonicalSddSubagentNames.map((name) => [name, 'allow'])]);
|
|
112
124
|
}
|
|
125
|
+
export function createCanonicalOpenCodeSddMcpToolPermissions() {
|
|
126
|
+
return {
|
|
127
|
+
vgxness_sdd_status: 'allow',
|
|
128
|
+
vgxness_sdd_next: 'allow',
|
|
129
|
+
vgxness_sdd_ready: 'allow',
|
|
130
|
+
vgxness_sdd_get_readiness: 'allow',
|
|
131
|
+
vgxness_sdd_get_artifact: 'allow',
|
|
132
|
+
vgxness_sdd_list_artifacts: 'allow',
|
|
133
|
+
vgxness_sdd_cockpit: 'allow',
|
|
134
|
+
vgxness_agent_resolve: 'allow',
|
|
135
|
+
vgxness_sdd_save_artifact: 'allow',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
113
138
|
export function createCanonicalOpenCodeSddSubagentPrompt(name) {
|
|
114
139
|
const phase = name.replace('vgxness-sdd-', '');
|
|
115
140
|
const common = `You are the VGXNESS SDD ${phase} executor, not the orchestrator. Do this phase's work yourself. Do NOT delegate, do NOT call task/delegate, and do NOT launch sub-agents. Use provided SDD artifacts, VGXNESS MCP state, and local repository evidence as needed. Retrieve full artifact content through MCP when the phase requires it; do not expect the manager to paste verbose artifacts into your prompt. Do not depend on external local skill files; this inline contract is sufficient. Preserve unrelated user work, keep output concise, and report evidence.`;
|
|
@@ -132,7 +157,7 @@ Coordinate SDD; keep chat thin, use VGXNESS MCP as durable state, delegate to th
|
|
|
132
157
|
- SDD artifact acceptance is human-only. Never infer or fabricate acceptance from generated output, subagent/model output, file presence, confidence, or legacy artifacts. Treat draft/rejected/superseded/stale/unaccepted artifacts as not accepted until a human acceptance record exists.
|
|
133
158
|
- Before phase advancement, call readiness/status tools: \`vgxness_sdd_status\`/\`vgxness_sdd_next\` and \`vgxness_sdd_ready\` or \`vgxness_sdd_get_readiness\`.
|
|
134
159
|
- Before risky VGX-managed side effects (edit, shell/tests, git, network, provider-tool, secrets, external-directory, destructive, privileged, ambiguous), call \`vgxness_run_preflight\` with runId/workflow/phase/agent context when available. If approval/block is required, stop; do not invent approval.
|
|
135
|
-
- Direct human acceptance of an exact SDD artifact via \`vgxness_sdd_accept_artifact\` is not a generic SDD write for manager routing: do not call \`vgxness_run_preflight\` solely for that acceptance when the user explicitly accepted the exact project/change/phase artifact, \`acceptedBy.type\` is \`"human"\`, \`acceptedBy.id\` is non-empty, and status/readiness confirms the artifact is eligible. This shortcut applies only to \`vgxness_sdd_accept_artifact
|
|
160
|
+
- Direct human acceptance of an exact SDD artifact via \`vgxness_sdd_accept_artifact\` is not a generic SDD write for manager routing: do not call \`vgxness_run_preflight\` solely for that acceptance when the user explicitly accepted the exact project/change/phase artifact, \`acceptedBy.type\` is \`"human"\`, \`acceptedBy.id\` is non-empty, and status/readiness confirms the artifact is eligible. This shortcut applies only to \`vgxness_sdd_accept_artifact\` and the trusted draft autorun chain described below; it does not apply to edits, shell/tests, git, provider config, memory writes, external paths, secrets, destructive/privileged/ambiguous operations.
|
|
136
161
|
- OpenCode native/provider tools are governance-v1 audit-only/non-hard-blocking. Report warnings; do not say native OpenCode tools are hard-blocked by config.
|
|
137
162
|
- Do not mutate provider/global OpenCode config. Do not write to \`openspec/\`. Do not publish packages unless explicitly requested. Never revert/overwrite unrelated user work. Preserve \`permission.task\` deny-by-default with only exact known SDD subagents allowed.
|
|
138
163
|
- Do not change provider model/reasoning config unless explicitly requested.
|
|
@@ -146,6 +171,7 @@ Daily SDD happens inside OpenCode through conversation, VGXNESS MCP, and hidden
|
|
|
146
171
|
## MCP playbook
|
|
147
172
|
- For starting, resuming, or recovering context: prefer \`vgxness_context_cockpit\`; treat \`vgxness_session_restore\` as one signal, not truth. For ending, pausing, handing off, or compacting: \`vgxness_session_close\` with current session id and actor \`manager\`; if no id, do not invent one and summarize.
|
|
148
173
|
- SDD artifacts: guide state with \`vgxness_sdd_next\`/\`vgxness_sdd_cockpit\`; list/read with \`vgxness_sdd_get_artifact\`/\`vgxness_sdd_list_artifacts\`; prefer \`payloadMode: "compact"\` so the primary context stays clean; use verbose only when required, preferably inside the delegated phase subagent. Save with \`vgxness_sdd_save_artifact\` only after the appropriate flow. Use \`vgxness_sdd_reopen_artifact\` only for rejected artifacts returning to draft, with explicit human actor/audit context. SDD artifacts are not generic memory.
|
|
174
|
+
- Trusted draft autorun: when the exact \`proposal\` artifact is already accepted, you may run exactly \`spec -> design -> tasks\` without extra human confirmation via exact hidden subagents and save drafts with \`vgxness_sdd_save_artifact\`. This is draft-only planning, not acceptance or completion. Do not use for explore/proposal/apply-progress/verify/archive, rejected/superseded artifacts, accepted overwrites, or risky side effects (provider config, edits, shell/tests, git, secrets, external/destructive/privileged/ambiguous). Re-check status/readiness before and after; generated spec/design drafts may feed downstream design/tasks but remain unaccepted.
|
|
149
175
|
- Acceptance/readiness: check SDD status/readiness for the exact project/change/phase, confirm explicit human acceptance of that exact artifact, call \`vgxness_sdd_accept_artifact\` directly with audit context (\`acceptedBy.type: "human"\`, non-empty \`acceptedBy.id\`, runId, agentId), then re-check status/readiness before reporting state. Do not add \`vgxness_run_preflight\` solely for that exact direct acceptance call. Ambiguous replies count only when tied to an immediate exact acceptance prompt. Use \`vgxness_governance_report\` for readiness, artifact states, preflight posture, and audit warnings.
|
|
150
176
|
- Memory: call \`vgxness_memory_search\`/\`vgxness_memory_get\` for prior work or unclear context; call \`vgxness_memory_save\` for durable discoveries, decisions, bug fixes, config, patterns, or preferences; use \`vgxness_memory_update\` only to correct/evolve a known id. Do not duplicate full SDD artifacts as memory.
|
|
151
177
|
- Agents/profile/payloads: resolve exact phase with \`vgxness_agent_resolve\`. \`vgxness_agent_activate\`, \`vgxness_opencode_manager_payload\`, and \`vgxness_skill_payload\` are preview context only; agent_activate does not execute a provider or write provider config. Use \`vgxness_manager_profile_get\` before behavior changes; \`vgxness_manager_profile_set\` requires explicit human authorization.
|
|
@@ -154,7 +180,7 @@ Daily SDD happens inside OpenCode through conversation, VGXNESS MCP, and hidden
|
|
|
154
180
|
|
|
155
181
|
## Minimum flows
|
|
156
182
|
- Simple answer: inline; memory only for prior context; no run by default.
|
|
157
|
-
- Proposal/spec/design/tasks: status/next -> readiness -> prerequisites -> exact subagent -> delegate -> persist by governance.
|
|
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.
|
|
158
184
|
- Apply/verify: require prerequisites -> artifacts -> exact subagent -> start/recover run -> preflight writes/shell/git/tests -> delegate -> checkpoint -> save -> finalize.
|
|
159
185
|
- Config/provider/prompt change: inspect manager/profile or payload first; persistent changes need explicit human authorization.
|
|
160
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; \`vgxness code sdd ... --draft-run\` is a planning-only path, never for apply-progress.
|
|
@@ -170,10 +196,10 @@ Be concise: delegated work, results, files/decisions, evidence/tests, risks, nex
|
|
|
170
196
|
* render baselines, and manager profile overlay baselines; they are
|
|
171
197
|
* intentionally distinct from the provider runtime prompt above.
|
|
172
198
|
*/
|
|
173
|
-
const
|
|
199
|
+
const registryManagerInstructionsV10 = [
|
|
174
200
|
'You are the VGXNESS SDD coordinator, not a monolithic executor. Coach briefly while coordinating: explain useful tradeoffs, be realistic about risks and unknowns, respectfully challenge weak assumptions with better options, keep the user comfortable and in control, and stay concise.',
|
|
175
201
|
'Use VGXNESS MCP as the durable control plane: restore session context with vgxness_session_restore before inferring start/resume state from chat, and close/pause/compact with vgxness_session_close using actor manager plus an actionable summary when a current session id exists.',
|
|
176
|
-
'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
|
|
202
|
+
'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.',
|
|
177
203
|
'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.',
|
|
178
204
|
'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.',
|
|
179
205
|
'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, and vgxness code sdd ... --draft-run is planning-only.',
|
|
@@ -183,8 +209,8 @@ const subagentData = {
|
|
|
183
209
|
'vgxness-sdd-explore': { seedDescription: 'Investigates codebase context and identifies options before proposals.', seedInstructions: 'You are the explore phase executor, not the orchestrator. Do not delegate. Explore repository evidence for the requested SDD change. Do not implement code changes. Return concise findings, risks, and recommended next artifacts.', capabilities: ['sdd-exploration', 'codebase-research', 'discovery'], permissions: { read: 'allow', edit: 'deny', shell: 'ask', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:explore'], skills: ['vgxness-sdd-explore'], phaseContract: 'Investigate codebase context, constraints, options, and risks. Do not implement code changes. Return findings and recommended next artifacts.' },
|
|
184
210
|
'vgxness-sdd-propose': { seedDescription: 'Creates focused change proposals from exploration findings.', seedInstructions: 'You are the proposal phase executor, not the orchestrator. Do not delegate. Create a focused SDD proposal from exploration evidence. Do not implement code changes. Identify scope, tradeoffs, non-goals, and acceptance direction.', capabilities: ['sdd-proposal', 'proposal-planning', 'scope-definition'], permissions: { read: 'allow', edit: 'deny', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:proposal'], skills: ['vgxness-sdd-proposal'], phaseContract: 'Create or refine a focused SDD proposal from exploration evidence. Do not implement code changes. Include scope, tradeoffs, non-goals, and acceptance direction.' },
|
|
185
211
|
'vgxness-sdd-spec': { seedDescription: 'Writes detailed requirements and acceptance criteria for SDD changes.', seedInstructions: 'You are the spec phase executor, not the orchestrator. Do not delegate. Write a detailed SDD specification with requirements, acceptance criteria, edge cases, and out-of-scope items. Do not implement code changes.', capabilities: ['sdd-specification', 'requirements', 'acceptance-criteria'], permissions: { read: 'allow', edit: 'deny', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:spec'], skills: ['vgxness-sdd-spec'], phaseContract: 'Write requirements, acceptance criteria, edge cases, and out-of-scope items. Do not implement code changes.' },
|
|
186
|
-
'vgxness-sdd-design': { seedDescription: 'Creates technical design from
|
|
187
|
-
'vgxness-sdd-tasks': { seedDescription: 'Breaks specs and designs into implementation tasks.', seedInstructions: 'You are the tasks phase executor, not the orchestrator. Do not delegate. Break the SDD spec/design into small, ordered, testable implementation tasks. Do not implement code changes.', capabilities: ['sdd-tasks', 'task-breakdown', 'implementation-planning'], permissions: { read: 'allow', edit: 'deny', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:tasks'], skills: ['vgxness-sdd-tasks'], phaseContract: 'Break
|
|
212
|
+
'vgxness-sdd-design': { seedDescription: 'Creates technical design from accepted proposals and accepted or trusted draft specs.', seedInstructions: 'You are the design phase executor, not the orchestrator. Do not delegate. Create a technical design grounded in the repository. Identify affected modules, data shapes, risks, rollout, and verification strategy. Do not implement code changes.', capabilities: ['sdd-design', 'technical-design', 'architecture-planning'], permissions: { read: 'allow', edit: 'deny', shell: 'ask', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:design'], skills: ['vgxness-sdd-design'], phaseContract: 'Create technical design grounded in the repository: affected modules, data shapes, safety, rollout, and verification. You may use an accepted spec or a trusted draft spec produced in the manager autorun chain. Do not implement code changes.' },
|
|
213
|
+
'vgxness-sdd-tasks': { seedDescription: 'Breaks accepted or trusted draft specs and designs into implementation tasks.', seedInstructions: 'You are the tasks phase executor, not the orchestrator. Do not delegate. Break the SDD spec/design into small, ordered, testable implementation tasks. Do not implement code changes.', capabilities: ['sdd-tasks', 'task-breakdown', 'implementation-planning'], permissions: { read: 'allow', edit: 'deny', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:tasks'], skills: ['vgxness-sdd-tasks'], phaseContract: 'Break accepted or trusted draft spec/design into small ordered testable implementation tasks. Do not implement code changes.' },
|
|
188
214
|
'vgxness-sdd-apply': { seedDescription: 'Implements code changes from SDD task definitions.', seedInstructions: 'You are the apply phase executor, not the orchestrator. Implement only the assigned SDD tasks directly. Do not delegate. Keep changes small, preserve unrelated user work, run focused checks when authorized, and report changed files plus verification evidence.', capabilities: ['sdd-apply', 'implementation', 'code-change'], permissions: { read: 'allow', edit: 'ask', shell: 'ask', git: 'ask', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:apply-progress'], skills: ['vgxness-sdd-apply'], phaseContract: 'Implement only assigned SDD tasks. Preserve unrelated dirty files and user work. Use focused tests when authorized. Report changed files, tests/evidence, and residual risks.' },
|
|
189
215
|
'vgxness-sdd-verify': { seedDescription: 'Validates implementation against specs, tasks, and evidence.', seedInstructions: 'You are the verify phase executor, not the orchestrator. Do not delegate. Verify the implementation against SDD artifacts. Prefer focused local tests, inspect evidence, and report residual risk. Do not implement unrelated changes.', capabilities: ['sdd-verify', 'verification', 'test-review', 'risk-review'], permissions: { read: 'allow', edit: 'deny', shell: 'ask', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:verify'], skills: ['vgxness-sdd-verify'], phaseContract: 'Validate implementation against SDD artifacts and task acceptance criteria. Prefer focused local tests and evidence review. Do not implement unrelated changes.' },
|
|
190
216
|
'vgxness-sdd-archive': { seedDescription: 'Archives completed SDD change artifacts and outcomes.', seedInstructions: 'You are the archive phase executor, not the orchestrator. Do not delegate. Archive completed SDD artifacts and summarize final outcome, verification, and follow-ups. Confirm before writes beyond the requested archive artifact.', capabilities: ['sdd-archive', 'artifact-archive', 'release-notes'], permissions: { read: 'allow', edit: 'ask', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:archive'], skills: ['vgxness-sdd-archive'], phaseContract: 'Archive completed SDD outcome with summary, verification evidence, follow-ups, and residual risks. Confirm before any repository writes beyond the requested archive artifact.' },
|
|
@@ -44,6 +44,21 @@ export function projectCanonicalAgentManifestToOpenCode(manifest = canonicalAgen
|
|
|
44
44
|
}
|
|
45
45
|
return { defaultAgent: canonicalDefaultAgentName, agents };
|
|
46
46
|
}
|
|
47
|
+
export function withEffectiveOpenCodeManagerInstructions(projection, instructions) {
|
|
48
|
+
const trimmed = instructions?.trim() ?? '';
|
|
49
|
+
if (trimmed === '')
|
|
50
|
+
return projection;
|
|
51
|
+
const manager = projection.agents[projection.defaultAgent];
|
|
52
|
+
if (manager === undefined)
|
|
53
|
+
return projection;
|
|
54
|
+
return {
|
|
55
|
+
defaultAgent: projection.defaultAgent,
|
|
56
|
+
agents: {
|
|
57
|
+
...projection.agents,
|
|
58
|
+
[projection.defaultAgent]: { ...manager, prompt: trimmed },
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
47
62
|
export function projectCanonicalAgentManifestToClaudeCode(manifest = canonicalAgentManifest) {
|
|
48
63
|
assertValidCanonicalManifest(manifest);
|
|
49
64
|
const manager = manifest.agents.find((agent) => agent.name === manifest.defaultAgentName && agent.mode === 'agent');
|
|
@@ -75,25 +75,56 @@ export function runMcpInstallCommand(parsed, environment) {
|
|
|
75
75
|
}),
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return result.status === 'installed'
|
|
89
|
-
? jsonResult({ ok: true, value: result })
|
|
90
|
-
: resultFailure({
|
|
91
|
-
ok: false,
|
|
92
|
-
error: {
|
|
93
|
-
code: 'validation_failed',
|
|
94
|
-
message: `${result.reason}: ${result.message} Manual doctor command: ${result.manualTest.doctorCommand.join(' ')}`,
|
|
95
|
-
},
|
|
78
|
+
if (parsed.flags.yes !== true) {
|
|
79
|
+
const result = await installOpenCodeMcpClient({
|
|
80
|
+
cwd: environment.cwd,
|
|
81
|
+
databasePath: databasePath.value.path,
|
|
82
|
+
databasePathSource: databasePath.value.source,
|
|
83
|
+
scope: scope.value,
|
|
84
|
+
env: environment.env,
|
|
85
|
+
confirmed: false,
|
|
86
|
+
mcpOnly,
|
|
87
|
+
overwriteVgxness,
|
|
96
88
|
});
|
|
89
|
+
return result.status === 'installed'
|
|
90
|
+
? jsonResult({ ok: true, value: result })
|
|
91
|
+
: resultFailure({
|
|
92
|
+
ok: false,
|
|
93
|
+
error: {
|
|
94
|
+
code: 'validation_failed',
|
|
95
|
+
message: `${result.reason}: ${result.message} Manual doctor command: ${result.manualTest.doctorCommand.join(' ')}`,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const opened = openCliDatabase(databasePath.value.path);
|
|
100
|
+
if (!opened.ok)
|
|
101
|
+
return resultFailure(opened);
|
|
102
|
+
try {
|
|
103
|
+
const effectiveManagerInstructions = computeEffectiveManagerInstructions(opened.value);
|
|
104
|
+
const result = await installOpenCodeMcpClient({
|
|
105
|
+
cwd: environment.cwd,
|
|
106
|
+
databasePath: databasePath.value.path,
|
|
107
|
+
databasePathSource: databasePath.value.source,
|
|
108
|
+
scope: scope.value,
|
|
109
|
+
env: environment.env,
|
|
110
|
+
confirmed: true,
|
|
111
|
+
mcpOnly,
|
|
112
|
+
overwriteVgxness,
|
|
113
|
+
...(effectiveManagerInstructions === undefined ? {} : { effectiveManagerInstructions }),
|
|
114
|
+
});
|
|
115
|
+
return result.status === 'installed'
|
|
116
|
+
? jsonResult({ ok: true, value: result })
|
|
117
|
+
: resultFailure({
|
|
118
|
+
ok: false,
|
|
119
|
+
error: {
|
|
120
|
+
code: 'validation_failed',
|
|
121
|
+
message: `${result.reason}: ${result.message} Manual doctor command: ${result.manualTest.doctorCommand.join(' ')}`,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
opened.value.close();
|
|
127
|
+
}
|
|
97
128
|
})();
|
|
98
129
|
}
|
|
99
130
|
function claudeInstallScopeFlag(flags) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { AgentRegistryService } from '../../agents/agent-registry-service.js';
|
|
3
|
+
import { computeEffectiveManagerInstructions } from '../../agents/manager-profile-overlay-service.js';
|
|
3
4
|
import { resolveAgentProfileModel } from '../../agents/profile-model-routing.js';
|
|
4
5
|
import { installOpenCodeMcpClient } from '../../mcp/client-install-opencode.js';
|
|
5
6
|
import { createMcpClientSetupPreview } from '../../mcp/client-setup-preview.js';
|
|
@@ -144,16 +145,27 @@ export async function applySetupPlanInput(input, environment) {
|
|
|
144
145
|
plan: plan.value,
|
|
145
146
|
},
|
|
146
147
|
};
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
const opened = openCliDatabase(plan.value.db.path);
|
|
149
|
+
if (!opened.ok)
|
|
150
|
+
return opened;
|
|
151
|
+
let result;
|
|
152
|
+
try {
|
|
153
|
+
const effectiveManagerInstructions = computeEffectiveManagerInstructions(opened.value, input.project);
|
|
154
|
+
result = await installOpenCodeMcpClient({
|
|
155
|
+
cwd: environment.cwd,
|
|
156
|
+
databasePath: plan.value.db.path,
|
|
157
|
+
databasePathSource: plan.value.db.source === 'global-default' || plan.value.db.source === 'environment' ? plan.value.db.source : 'flag',
|
|
158
|
+
scope: input.scope ?? vgxnessSetupDefaults.defaultOpenCodeScope,
|
|
159
|
+
env: environment.env,
|
|
160
|
+
confirmed: true,
|
|
161
|
+
mcpOnly: input.installMode === 'mcp-only',
|
|
162
|
+
...(input.overwriteVgxness === undefined ? {} : { overwriteVgxness: input.overwriteVgxness }),
|
|
163
|
+
...(effectiveManagerInstructions === undefined ? {} : { effectiveManagerInstructions }),
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
opened.value.close();
|
|
168
|
+
}
|
|
157
169
|
return result.status === 'installed'
|
|
158
170
|
? {
|
|
159
171
|
ok: true,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export function renderProductStatus(status) {
|
|
2
|
+
const commandHeading = productCommandHeading(status);
|
|
2
3
|
const lines = [
|
|
3
4
|
'Status',
|
|
4
5
|
...status.status.map((line) => `- ${line}`),
|
|
@@ -9,7 +10,7 @@ export function renderProductStatus(status) {
|
|
|
9
10
|
'Next',
|
|
10
11
|
...status.next.map((line) => `- ${line}`),
|
|
11
12
|
'',
|
|
12
|
-
|
|
13
|
+
commandHeading,
|
|
13
14
|
`- ${status.command}`,
|
|
14
15
|
'',
|
|
15
16
|
...(status.relatedRunContext === undefined ? [] : relatedRunContextLines(status.relatedRunContext, true)),
|
|
@@ -43,6 +44,7 @@ function buildBlockedNextCommand(status) {
|
|
|
43
44
|
return `vgxness next --project ${status.project.value} --change ${change}${dbHint}`;
|
|
44
45
|
}
|
|
45
46
|
export function renderProductNext(next) {
|
|
47
|
+
const commandHeading = next.blocked ? 'Recovery/diagnostic command' : 'Manual fallback command';
|
|
46
48
|
const lines = [
|
|
47
49
|
'Next',
|
|
48
50
|
...next.next.map((line) => `- ${line}`),
|
|
@@ -51,7 +53,7 @@ export function renderProductNext(next) {
|
|
|
51
53
|
...next.why.map((line) => `- ${line}`),
|
|
52
54
|
...(next.blockers.length === 0 ? [] : ['', 'Blockers', ...next.blockers.map((line) => `- ${line}`)]),
|
|
53
55
|
'',
|
|
54
|
-
|
|
56
|
+
commandHeading,
|
|
55
57
|
`- ${next.command}`,
|
|
56
58
|
'',
|
|
57
59
|
...(next.relatedRunContext === undefined ? [] : relatedRunContextLines(next.relatedRunContext, true)),
|
|
@@ -60,6 +62,11 @@ export function renderProductNext(next) {
|
|
|
60
62
|
];
|
|
61
63
|
return `${lines.join('\n')}\n`;
|
|
62
64
|
}
|
|
65
|
+
function productCommandHeading(status) {
|
|
66
|
+
if (status.sddNextStatus === 'runnable')
|
|
67
|
+
return 'Manual fallback command';
|
|
68
|
+
return 'Recovery/diagnostic command';
|
|
69
|
+
}
|
|
63
70
|
function relatedRunContextLines(relatedRunContext, includeTrailingBlank) {
|
|
64
71
|
return [
|
|
65
72
|
'Related interrupted run:',
|
package/dist/cli/sdd-renderer.js
CHANGED
|
@@ -10,7 +10,8 @@ export function renderSddStatus(input) {
|
|
|
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' : 'Manual fallback command';
|
|
14
15
|
const lines = [
|
|
15
16
|
'SDD Status',
|
|
16
17
|
`Project: ${input.project}`,
|
|
@@ -28,7 +29,7 @@ export function renderSddStatus(input) {
|
|
|
28
29
|
...(missing.length === 0 ? ['- none'] : missing.map((topicKey) => `- ${topicKey}`)),
|
|
29
30
|
'',
|
|
30
31
|
`Recommended action: ${recommendedAction}`,
|
|
31
|
-
|
|
32
|
+
`${commandLabel}: ${directPhaseCommand ?? `vgxness sdd next --project ${input.project} --change ${input.status.change}`}`,
|
|
32
33
|
`JSON: vgxness sdd status --project ${input.project} --change ${input.status.change} --json`,
|
|
33
34
|
];
|
|
34
35
|
return `${lines.join('\n')}\n`;
|
|
@@ -40,6 +41,10 @@ export function renderSddNext(input) {
|
|
|
40
41
|
const commandGuidance = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined
|
|
41
42
|
? `vgxness code sdd ${input.decision.change} ${input.decision.nextPhase} --save-artifact`
|
|
42
43
|
: `vgxness sdd status --project ${input.project} --change ${input.decision.change}`;
|
|
44
|
+
const commandLabel = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined ? 'Manual fallback command' : 'Diagnostic command';
|
|
45
|
+
const primaryAction = input.decision.status === 'runnable' && input.decision.nextPhase !== undefined
|
|
46
|
+
? `Continue the ${input.decision.nextPhase} phase in OpenCode using VGXNESS MCP and hidden SDD subagents.`
|
|
47
|
+
: input.decision.recommendedAction;
|
|
43
48
|
const lines = [
|
|
44
49
|
'SDD Next',
|
|
45
50
|
`Project: ${input.project}`,
|
|
@@ -64,13 +69,14 @@ export function renderSddNext(input) {
|
|
|
64
69
|
'Next actions:',
|
|
65
70
|
...(guidance.length === 0 ? ['- none'] : guidance.map((item) => `- ${item.phase}: ${item.action}`)),
|
|
66
71
|
'',
|
|
67
|
-
`Recommended action: ${
|
|
68
|
-
|
|
72
|
+
`Recommended action: ${primaryAction}`,
|
|
73
|
+
`${commandLabel}: ${commandGuidance}`,
|
|
69
74
|
`JSON: vgxness sdd next --project ${input.project} --change ${input.decision.change} --json`,
|
|
70
75
|
];
|
|
71
76
|
return `${lines.join('\n')}\n`;
|
|
72
77
|
}
|
|
73
78
|
export function renderSddContinuationPlan(plan) {
|
|
79
|
+
const suggestedCommandLabel = plan.status === 'runnable' ? 'Manual fallback command' : 'Diagnostic command';
|
|
74
80
|
const lines = [
|
|
75
81
|
'SDD Continue (read-only)',
|
|
76
82
|
`Project: ${plan.project}`,
|
|
@@ -81,17 +87,17 @@ export function renderSddContinuationPlan(plan) {
|
|
|
81
87
|
`Reason: ${plan.reason}`,
|
|
82
88
|
'',
|
|
83
89
|
'Recommended plan:',
|
|
84
|
-
`- ${plan.recommendedAction}`,
|
|
85
|
-
`-
|
|
86
|
-
`-
|
|
90
|
+
`- ${plan.status === 'runnable' && plan.nextPhase !== undefined ? `Continue the ${plan.nextPhase} phase in OpenCode using VGXNESS MCP and hidden SDD subagents.` : plan.recommendedAction}`,
|
|
91
|
+
`- ${suggestedCommandLabel}: ${plan.suggestedCommand}`,
|
|
92
|
+
`- Diagnostic command: ${plan.inspectCommand}`,
|
|
87
93
|
'',
|
|
88
94
|
'Blocker-specific next actions:',
|
|
89
95
|
...(plan.blockerActions.length === 0
|
|
90
96
|
? ['- none']
|
|
91
97
|
: plan.blockerActions.map((item) => {
|
|
92
|
-
const draftRun = item.draftRunCommand === undefined ? '' : `;
|
|
98
|
+
const draftRun = item.draftRunCommand === undefined ? '' : `; manualFallbackCommand=${item.draftRunCommand}`;
|
|
93
99
|
const warning = item.warning === undefined ? '' : `; warning=${item.warning}`;
|
|
94
|
-
return `- ${item.phase}: ${item.action};
|
|
100
|
+
return `- ${item.phase}: ${item.action}; recoveryCommand=${item.command}${draftRun}${warning}`;
|
|
95
101
|
})),
|
|
96
102
|
'',
|
|
97
103
|
...(plan.relatedRunContext === undefined
|
|
@@ -11,10 +11,10 @@ const statCards = [
|
|
|
11
11
|
{ label: 'actions', value: '5', badge: '', description: 'safe routes' },
|
|
12
12
|
{ label: 'provider', value: '1', badge: '', description: 'OpenCode' },
|
|
13
13
|
{ label: 'writes', value: '0', badge: '', description: 'dashboard render' },
|
|
14
|
-
{ label: 'SDD', value: '
|
|
14
|
+
{ label: 'SDD', value: 'OpenCode', badge: '', description: 'daily surface' },
|
|
15
15
|
];
|
|
16
16
|
const statusSnapshotLines = [
|
|
17
|
-
'OpenCode
|
|
17
|
+
'OpenCode + VGXNESS MCP is the daily SDD surface; dashboard does not call providers.',
|
|
18
18
|
'Advanced checks stay explicit: setup status, mcp doctor opencode.',
|
|
19
19
|
];
|
|
20
20
|
const optionCopy = {
|
|
@@ -34,17 +34,17 @@ const optionCopy = {
|
|
|
34
34
|
},
|
|
35
35
|
sdd: {
|
|
36
36
|
label: 'SDD workflow',
|
|
37
|
-
description: '
|
|
37
|
+
description: 'diagnostics, recovery, fallback',
|
|
38
38
|
badges: [tuiBadges.previewOnly],
|
|
39
39
|
detailTitle: 'SDD workflow',
|
|
40
|
-
detailLines: ['Use OpenCode conversation plus VGXNESS MCP for daily progression.'],
|
|
40
|
+
detailLines: ['Use OpenCode conversation plus VGXNESS MCP and hidden SDD subagents for daily progression; this TUI stays read-only for setup, diagnostics, recovery, and fallback commands.'],
|
|
41
41
|
},
|
|
42
42
|
'advanced-cli': {
|
|
43
43
|
label: 'Advanced CLI',
|
|
44
|
-
description: '
|
|
44
|
+
description: 'fallback scripts, no automation',
|
|
45
45
|
badges: [tuiBadges.manual],
|
|
46
46
|
detailTitle: 'Advanced CLI',
|
|
47
|
-
detailLines: ['Prints explicit command references; no provider config is written.'],
|
|
47
|
+
detailLines: ['Prints explicit diagnostic, recovery, fallback, and scripting command references; no provider config is written.'],
|
|
48
48
|
},
|
|
49
49
|
exit: {
|
|
50
50
|
label: 'Quit',
|
|
@@ -62,13 +62,13 @@ export function buildMainMenuViewModel(state) {
|
|
|
62
62
|
subtitle: dashboardHero.subtitle,
|
|
63
63
|
hero: dashboardHero,
|
|
64
64
|
statCards,
|
|
65
|
-
contextLines: ['Pick a route. Dashboard render stays passive/read-only.'],
|
|
65
|
+
contextLines: ['Pick a route. Dashboard render stays passive/read-only; daily SDD continues in OpenCode.'],
|
|
66
66
|
options,
|
|
67
67
|
detail: { title: focused.detailTitle, lines: focused.detailLines, badges: focused.badges },
|
|
68
68
|
statusSnapshot: { title: 'Signal', lines: statusSnapshotLines, badges: [tuiBadges.readOnly] },
|
|
69
69
|
safetyLines: ['read-only • no provider writes • explicit confirmation'],
|
|
70
70
|
helpLines: state.helpVisible
|
|
71
|
-
? ['Keys: ↑/↓ or j/k move, Enter open, ?/h help, q/Esc quit.', 'Guidance entries print commands only; setup writes still require confirmation.']
|
|
71
|
+
? ['Keys: ↑/↓ or j/k move, Enter open, ?/h help, q/Esc quit.', 'Guidance entries print fallback/diagnostic commands only; setup writes still require confirmation.']
|
|
72
72
|
: [],
|
|
73
73
|
footer: state.viewport.mode === 'narrow' ? 'no provider writes • explicit confirmation' : 'j/k • enter • q • no provider writes • explicit confirmation',
|
|
74
74
|
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { computeEffectiveManagerInstructions } from '../../../agents/manager-profile-overlay-service.js';
|
|
1
2
|
import { installOpenCodeMcpClient } from '../../../mcp/client-install-opencode.js';
|
|
3
|
+
import { openMemoryDatabase } from '../../../memory/sqlite/database.js';
|
|
4
|
+
import { prepareMemoryDatabasePath } from '../../../memory/storage-paths.js';
|
|
2
5
|
import { vgxnessSetupDefaults } from '../../../setup/setup-defaults.js';
|
|
3
6
|
import { createSetupPlan } from '../../../setup/setup-plan.js';
|
|
4
7
|
export function setupPlanInputFromTui(input) {
|
|
@@ -37,16 +40,30 @@ export async function applySetupTuiPlan(planInput, runtime) {
|
|
|
37
40
|
};
|
|
38
41
|
if (plan.value.status !== 'ready')
|
|
39
42
|
return { ok: false, error: { code: 'validation_failed', message: `Setup plan is ${plan.value.status}; resolve blockers before applying.` } };
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
const prepared = prepareMemoryDatabasePath(plan.value.db.path);
|
|
44
|
+
if (!prepared.ok)
|
|
45
|
+
return prepared;
|
|
46
|
+
const opened = openMemoryDatabase({ path: plan.value.db.path });
|
|
47
|
+
if (!opened.ok)
|
|
48
|
+
return opened;
|
|
49
|
+
let installed;
|
|
50
|
+
try {
|
|
51
|
+
const effectiveManagerInstructions = computeEffectiveManagerInstructions(opened.value, planInput.project);
|
|
52
|
+
installed = await installOpenCodeMcpClient({
|
|
53
|
+
cwd: runtime.cwd,
|
|
54
|
+
databasePath: plan.value.db.path,
|
|
55
|
+
databasePathSource: plan.value.db.source === 'global-default' || plan.value.db.source === 'environment' ? plan.value.db.source : 'flag',
|
|
56
|
+
scope: planInput.scope ?? vgxnessSetupDefaults.defaultOpenCodeScope,
|
|
57
|
+
env: runtime.env,
|
|
58
|
+
confirmed: true,
|
|
59
|
+
mcpOnly: planInput.installMode === 'mcp-only',
|
|
60
|
+
...(planInput.overwriteVgxness === undefined ? {} : { overwriteVgxness: planInput.overwriteVgxness }),
|
|
61
|
+
...(effectiveManagerInstructions === undefined ? {} : { effectiveManagerInstructions }),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
opened.value.close();
|
|
66
|
+
}
|
|
50
67
|
if (installed.status !== 'installed')
|
|
51
68
|
return { ok: false, error: { code: 'validation_failed', message: `${installed.reason}: ${installed.message}` } };
|
|
52
69
|
return {
|
|
@@ -195,10 +195,10 @@ function parseConfig(path) {
|
|
|
195
195
|
function isRecord(value) {
|
|
196
196
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
197
197
|
}
|
|
198
|
-
export function findConflictingVgxnessAgents(config, agentPlan) {
|
|
198
|
+
export function findConflictingVgxnessAgents(config, agentPlan, input = {}) {
|
|
199
199
|
if (!agentPlan.installsAgents || !isRecord(config.agent))
|
|
200
200
|
return [];
|
|
201
|
-
const defaults = createOpenCodeDefaultAgentConfig().agents;
|
|
201
|
+
const defaults = createOpenCodeDefaultAgentConfig(input).agents;
|
|
202
202
|
return agentPlan.agentNames.filter((name) => Object.hasOwn(config.agent, name) && !deepEqual(config.agent[name], defaults[name]));
|
|
203
203
|
}
|
|
204
204
|
function deepEqual(left, right) {
|
|
@@ -37,36 +37,40 @@ export async function installOpenCodeMcpClient(input) {
|
|
|
37
37
|
const reparsed = parseConfig(plan.targetPath);
|
|
38
38
|
if (!reparsed.ok)
|
|
39
39
|
return refusal(reparsed.reason, reparsed.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness);
|
|
40
|
-
const conflictingAgents = findConflictingVgxnessAgents(reparsed.value, agentPlan
|
|
40
|
+
const conflictingAgents = findConflictingVgxnessAgents(reparsed.value, agentPlan, {
|
|
41
|
+
effectiveManagerInstructions: input.effectiveManagerInstructions,
|
|
42
|
+
});
|
|
41
43
|
if (conflictingAgents.length > 0 && input.overwriteVgxness !== true)
|
|
42
44
|
return agentConflictRefusal(conflictingAgents, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan);
|
|
43
45
|
return refusal('unsupported_config_shape', 'OpenCode config appeared after planning; rerun setup apply so it can be merged safely without overwriting user config.', input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness);
|
|
44
46
|
}
|
|
45
|
-
writeConfig(plan.targetPath, mergeVgxnessOpenCodeConfig({ $schema: opencodeConfigSchema }, plan.server, plan.installsAgents));
|
|
47
|
+
writeConfig(plan.targetPath, mergeVgxnessOpenCodeConfig({ $schema: opencodeConfigSchema }, plan.server, plan.installsAgents, input.effectiveManagerInstructions));
|
|
46
48
|
return validateInstalledResult(plan.targetPath, undefined, server, input.databasePath, databasePathSource, applySafety(plan), plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness);
|
|
47
49
|
}
|
|
48
50
|
const parsed = parseConfig(plan.targetPath);
|
|
49
51
|
if (!parsed.ok)
|
|
50
52
|
return refusal(parsed.reason, parsed.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness);
|
|
51
|
-
const conflictingAgents = findConflictingVgxnessAgents(parsed.value, agentPlan
|
|
53
|
+
const conflictingAgents = findConflictingVgxnessAgents(parsed.value, agentPlan, {
|
|
54
|
+
effectiveManagerInstructions: input.effectiveManagerInstructions,
|
|
55
|
+
});
|
|
52
56
|
if (conflictingAgents.length > 0 && input.overwriteVgxness !== true)
|
|
53
57
|
return agentConflictRefusal(conflictingAgents, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan);
|
|
54
58
|
const backup = createBackup(plan.targetPath, plan.scope);
|
|
55
59
|
if (!backup.ok)
|
|
56
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);
|
|
57
61
|
const config = parsed.value;
|
|
58
|
-
const mergedConfig = mergeVgxnessOpenCodeConfig({ ...config, $schema: plan.existingSchema ?? opencodeConfigSchema }, plan.server, plan.installsAgents);
|
|
62
|
+
const mergedConfig = mergeVgxnessOpenCodeConfig({ ...config, $schema: plan.existingSchema ?? opencodeConfigSchema }, plan.server, plan.installsAgents, input.effectiveManagerInstructions);
|
|
59
63
|
writeConfig(plan.targetPath, mergedConfig);
|
|
60
64
|
return validateInstalledResult(plan.targetPath, backup.value, server, input.databasePath, databasePathSource, applySafety(plan), plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness);
|
|
61
65
|
}
|
|
62
|
-
function mergeVgxnessOpenCodeConfig(config, server, installsAgents) {
|
|
66
|
+
function mergeVgxnessOpenCodeConfig(config, server, installsAgents, effectiveManagerInstructions) {
|
|
63
67
|
const merged = {
|
|
64
68
|
...config,
|
|
65
69
|
$schema: typeof config.$schema === 'string' ? config.$schema : opencodeConfigSchema,
|
|
66
70
|
mcp: { ...(isRecord(config.mcp) ? config.mcp : {}), vgxness: server },
|
|
67
71
|
};
|
|
68
72
|
if (installsAgents) {
|
|
69
|
-
const defaults = createOpenCodeDefaultAgentConfig();
|
|
73
|
+
const defaults = createOpenCodeDefaultAgentConfig({ effectiveManagerInstructions });
|
|
70
74
|
merged.instructions = mergeOpenCodeInstructions(config.instructions);
|
|
71
75
|
merged.default_agent = defaults.defaultAgent;
|
|
72
76
|
merged.agent = { ...(isRecord(config.agent) ? config.agent : {}), ...defaults.agents };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { projectCanonicalAgentManifestToOpenCode, } from '../agents/canonical-agent-projection.js';
|
|
2
|
-
import { canonicalDefaultAgentName, canonicalPromptContractVersion, canonicalSddSubagentNames, createCanonicalOpenCodeSddTaskPermissions, } from '../agents/canonical-agent-manifest.js';
|
|
1
|
+
import { projectCanonicalAgentManifestToOpenCode, withEffectiveOpenCodeManagerInstructions, } from '../agents/canonical-agent-projection.js';
|
|
2
|
+
import { canonicalDefaultAgentName, canonicalPromptContractVersion, canonicalSddSubagentNames, createCanonicalOpenCodeSddMcpToolPermissions, createCanonicalOpenCodeSddTaskPermissions, } from '../agents/canonical-agent-manifest.js';
|
|
3
3
|
export const vgxnessOpenCodeDefaultAgent = canonicalDefaultAgentName;
|
|
4
4
|
export const vgxnessOpenCodePromptContractVersion = canonicalPromptContractVersion;
|
|
5
5
|
export const vgxnessOpenCodeInstructionsPath = 'AGENTS.md';
|
|
@@ -7,11 +7,14 @@ export const vgxnessOpenCodeSddSubagents = canonicalSddSubagentNames;
|
|
|
7
7
|
export function createOpenCodeSddTaskPermissions() {
|
|
8
8
|
return createCanonicalOpenCodeSddTaskPermissions();
|
|
9
9
|
}
|
|
10
|
+
export function createOpenCodeSddMcpToolPermissions() {
|
|
11
|
+
return createCanonicalOpenCodeSddMcpToolPermissions();
|
|
12
|
+
}
|
|
10
13
|
export function createOpenCodeDefaultAgentInstallPlan(input = {}) {
|
|
11
14
|
if (input.mcpOnly === true)
|
|
12
15
|
return { installsAgents: false, agentNames: [] };
|
|
13
16
|
return { installsAgents: true, agentNames: [vgxnessOpenCodeDefaultAgent, ...vgxnessOpenCodeSddSubagents], defaultAgent: vgxnessOpenCodeDefaultAgent };
|
|
14
17
|
}
|
|
15
|
-
export function createOpenCodeDefaultAgentConfig() {
|
|
16
|
-
return projectCanonicalAgentManifestToOpenCode();
|
|
18
|
+
export function createOpenCodeDefaultAgentConfig(input = {}) {
|
|
19
|
+
return withEffectiveOpenCodeManagerInstructions(projectCanonicalAgentManifestToOpenCode(), input.effectiveManagerInstructions);
|
|
17
20
|
}
|
|
@@ -82,7 +82,11 @@ function fromSddCockpit(cockpit, project, baseSafety, relatedRunContext) {
|
|
|
82
82
|
blockers: cockpit.aggregateBlockers.length === 0
|
|
83
83
|
? ['none']
|
|
84
84
|
: cockpit.aggregateBlockers.map((blocker) => `${blocker.phase}: ${blocker.reason} at ${blocker.topicKey}${blocker.action === undefined ? '' : `; action=${blocker.action}`}`),
|
|
85
|
-
next: [
|
|
85
|
+
next: [
|
|
86
|
+
cockpit.next.status === 'runnable' && cockpit.next.nextPhase !== undefined
|
|
87
|
+
? `Continue the ${cockpit.next.nextPhase} phase in OpenCode using VGXNESS MCP and hidden SDD subagents.`
|
|
88
|
+
: cockpit.recommendedAction,
|
|
89
|
+
],
|
|
86
90
|
command,
|
|
87
91
|
sddNextStatus: cockpit.next.status,
|
|
88
92
|
...(relatedRunContext === undefined ? {} : { relatedRunContext }),
|
package/docs/cli.md
CHANGED
|
@@ -49,7 +49,7 @@ Release defaults used by the guided setup are:
|
|
|
49
49
|
- Install mode: MCP plus manager/SDD agents (`mcp-plus-agents`).
|
|
50
50
|
- Public CLI language: English.
|
|
51
51
|
|
|
52
|
-
Recommended
|
|
52
|
+
Recommended bootstrap and diagnostic flow after `npm install -g vgxness`:
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
55
|
vgxness --help
|
|
@@ -59,30 +59,33 @@ 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
|
|
61
61
|
vgxness doctor # human-readable readiness checks
|
|
62
|
-
vgxness status --project <project> --change <change>
|
|
63
|
-
vgxness next --project <project> --change <change>
|
|
62
|
+
vgxness status --project <project> --change <change> # diagnostic cockpit
|
|
63
|
+
vgxness next --project <project> --change <change> # diagnostic/recovery next step
|
|
64
|
+
vgxness sdd continue --project <project> --change <change> # read-only manual continuation plan
|
|
64
65
|
vgxness resume --project <project> --run-id <id>
|
|
65
66
|
vgxness setup rollback --backup <path>
|
|
66
67
|
```
|
|
67
68
|
|
|
69
|
+
Daily SDD phase progression is OpenCode-first: talk to OpenCode with the VGXNESS MCP server installed, and let the hidden SDD subagents use MCP tools for phase work. The CLI and TUI remain supported for bootstrap/setup, diagnostics, recovery, manual fallback, and scripting; they are not the primary daily surface.
|
|
70
|
+
|
|
68
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 OpenCode target is `$HOME/.config/opencode/opencode.json`; pass `--scope project` to opt into `<workspace>/.opencode/opencode.json`. `setup apply --yes` is the explicit OpenCode 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 target when present, restores the selected backup byte-for-byte, and recommends `vgxness doctor`.
|
|
69
72
|
|
|
70
73
|
`vgxness init` prompts in English when stdin/stdout are TTYs: project name, DB location, provider, OpenCode scope, 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 get-artifact`, and `vgxness sdd list-artifacts` are also human-readable by default; use `--json` for scripts.
|
|
71
74
|
|
|
72
75
|
## Daily workflow front doors
|
|
73
76
|
|
|
74
|
-
Use these top-level commands
|
|
77
|
+
Use OpenCode conversation + VGXNESS MCP + hidden SDD subagents for normal daily SDD work. Use these top-level commands when you need diagnostics, recovery, manual fallback, or scriptable state inspection:
|
|
75
78
|
|
|
76
79
|
| Question | Command | Purpose |
|
|
77
80
|
|---|---|---|
|
|
78
|
-
| Where am I? | `vgxness status --project <project> --change <change>` |
|
|
79
|
-
| What should I do now? | `vgxness next --project <project> --change <change>` |
|
|
80
|
-
| How do I continue a change? | `vgxness sdd continue --project <project> --change <change>` | Builds a read-only continuation plan for the selected SDD change. |
|
|
81
|
+
| Where am I? | `vgxness status --project <project> --change <change>` | Diagnostic cockpit state, blockers, next recommendation, and safety notes. |
|
|
82
|
+
| What should I do now? | `vgxness next --project <project> --change <change>` | Recovery/diagnostic next action and why it is safe or blocked. |
|
|
83
|
+
| How do I continue a change manually? | `vgxness sdd continue --project <project> --change <change>` | Builds a read-only continuation plan and manual fallback commands for the selected SDD change. |
|
|
81
84
|
| How do I continue interrupted work? | `vgxness resume --project <project> [--run-id <id>]` | Lists or inspects interrupted runs and suggests manual continuation commands without retrying anything. |
|
|
82
85
|
|
|
83
86
|
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.
|
|
84
87
|
|
|
85
|
-
The usual SDD operator loop
|
|
88
|
+
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.
|
|
86
89
|
|
|
87
90
|
## Bun-first repository verification
|
|
88
91
|
|
|
@@ -237,7 +240,7 @@ bun run cli:bun --
|
|
|
237
240
|
|
|
238
241
|
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.
|
|
239
242
|
|
|
240
|
-
The top-level menu is: **Installation, Doctor / recovery, SDD / workflow guidance, Advanced CLI, Exit**. Terminal controls are `↑/↓` or `j/k` to move, `Enter` to open the focused item, `?` for help, and `q` to quit.
|
|
243
|
+
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.
|
|
241
244
|
|
|
242
245
|
For scriptable status, use explicit read-only commands:
|
|
243
246
|
|
|
@@ -255,7 +258,7 @@ Provider support shown in the Installation surface is:
|
|
|
255
258
|
- **Antigravity** — placeholder/coming-soon guidance only.
|
|
256
259
|
- **Custom/future** — extension point with safe manual/default unsupported behavior.
|
|
257
260
|
|
|
258
|
-
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.
|
|
261
|
+
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.
|
|
259
262
|
|
|
260
263
|
## Natural-language orchestrator preview
|
|
261
264
|
|
|
@@ -562,7 +565,7 @@ Manual/opt-in runtime validation checklist (not normal CI):
|
|
|
562
565
|
|
|
563
566
|
## SDD workflow examples
|
|
564
567
|
|
|
565
|
-
Use `sdd` commands to inspect local SDD artifact state and save, read, or list phase artifacts. These commands read and write only the selected `vgxness` local SQLite memory store: `--db <path>` when passed, `VGXNESS_DB_PATH` when set, or the global default database when neither override is present.
|
|
568
|
+
Use OpenCode conversation with VGXNESS MCP and hidden SDD subagents for normal daily SDD progression. Use `sdd` commands to inspect local SDD artifact state and save, read, or list phase artifacts for diagnostics, recovery, scripting, or manual fallback. These commands read and write only the selected `vgxness` local SQLite memory store: `--db <path>` when passed, `VGXNESS_DB_PATH` when set, or the global default database when neither override is present.
|
|
566
569
|
|
|
567
570
|
```bash
|
|
568
571
|
bun run cli:bun -- sdd status --project vgxness --change sdd-workflow-engine --db /tmp/vgxness-memory.sqlite
|
|
@@ -579,13 +582,13 @@ bun run cli:bun -- sdd reopen-artifact --project vgxness --change sdd-workflow-e
|
|
|
579
582
|
VGXNESS_DB_PATH=/tmp/vgxness-memory.sqlite bun run cli:bun -- sdd list-artifacts --project vgxness --change sdd-workflow-engine
|
|
580
583
|
```
|
|
581
584
|
|
|
582
|
-
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. `sdd continue` turns that state into a read-only continuation plan, including 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.
|
|
585
|
+
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.
|
|
583
586
|
|
|
584
587
|
`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.
|
|
585
588
|
|
|
586
589
|
Use `resume --project <project>` when you do not know the run id. It lists recent interrupted candidates for that project from the selected database. Use `resume --project <project> --run-id <id>` to inspect one candidate; this is still read-only and advisory.
|
|
587
590
|
|
|
588
|
-
The SDD CLI is status, planning,
|
|
591
|
+
The SDD CLI is status, planning, artifact persistence, diagnostics, recovery, scripting, and manual fallback only. It does **not** execute providers, retry workflow runs, create `openspec/`, or write `.opencode/`, `.claude/`, or user/global provider config.
|
|
589
592
|
|
|
590
593
|
## Agent resolution
|
|
591
594
|
|