vgxness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/LICENSE +9 -0
  2. package/README.md +110 -0
  3. package/dist/agents/agent-activation-service.js +144 -0
  4. package/dist/agents/agent-registry-service.js +46 -0
  5. package/dist/agents/agent-resolver.js +249 -0
  6. package/dist/agents/agent-seed-service.js +146 -0
  7. package/dist/agents/manager-profile-overlay-service.js +34 -0
  8. package/dist/agents/profile-model-routing.js +26 -0
  9. package/dist/agents/renderers/claude-renderer.js +98 -0
  10. package/dist/agents/renderers/index.js +16 -0
  11. package/dist/agents/renderers/json-renderer.js +87 -0
  12. package/dist/agents/renderers/opencode-renderer.js +100 -0
  13. package/dist/agents/renderers/provider-adapter.js +6 -0
  14. package/dist/agents/repositories/agents.js +185 -0
  15. package/dist/agents/repositories/manager-profile-overlays.js +81 -0
  16. package/dist/agents/schema.js +1 -0
  17. package/dist/cli/dashboard-operational-read-models.js +153 -0
  18. package/dist/cli/dashboard-renderer.js +109 -0
  19. package/dist/cli/dashboard-screen-renderers.js +332 -0
  20. package/dist/cli/dashboard-tui-read-model.js +71 -0
  21. package/dist/cli/dashboard-tui-state.js +218 -0
  22. package/dist/cli/dispatcher.js +2880 -0
  23. package/dist/cli/index.js +27 -0
  24. package/dist/cli/interactive-dashboard.js +29 -0
  25. package/dist/cli/mcp-start-path.js +21 -0
  26. package/dist/cli/setup-status-renderer.js +29 -0
  27. package/dist/cli/setup-wizard-read-model.js +56 -0
  28. package/dist/cli/setup-wizard-renderer.js +148 -0
  29. package/dist/cli/setup-wizard-state.js +82 -0
  30. package/dist/cli/tui-render-helpers.js +192 -0
  31. package/dist/export/redaction.js +71 -0
  32. package/dist/harness/tools/agents.js +245 -0
  33. package/dist/harness/tools/memory.js +29 -0
  34. package/dist/mcp/client-install-opencode-contract.js +227 -0
  35. package/dist/mcp/client-install-opencode.js +194 -0
  36. package/dist/mcp/client-setup-preview.js +38 -0
  37. package/dist/mcp/control-plane.js +175 -0
  38. package/dist/mcp/doctor.js +193 -0
  39. package/dist/mcp/index.js +10 -0
  40. package/dist/mcp/opencode-default-agent-config.js +156 -0
  41. package/dist/mcp/opencode-visibility.js +102 -0
  42. package/dist/mcp/schema.js +234 -0
  43. package/dist/mcp/stdio-server.js +56 -0
  44. package/dist/mcp/validation.js +761 -0
  45. package/dist/memory/import/dry-run-planner.js +58 -0
  46. package/dist/memory/import/index.js +3 -0
  47. package/dist/memory/import/observation-writer.js +220 -0
  48. package/dist/memory/import/package.js +178 -0
  49. package/dist/memory/memory-service.js +126 -0
  50. package/dist/memory/repositories/artifacts.js +41 -0
  51. package/dist/memory/repositories/observations.js +133 -0
  52. package/dist/memory/repositories/sessions.js +105 -0
  53. package/dist/memory/repositories/traces.js +58 -0
  54. package/dist/memory/schema.js +1 -0
  55. package/dist/memory/search.js +11 -0
  56. package/dist/memory/sqlite/database.js +97 -0
  57. package/dist/memory/sqlite/migrations/001_initial.sql +128 -0
  58. package/dist/memory/sqlite/migrations/002_observation_revisions.sql +14 -0
  59. package/dist/memory/sqlite/migrations/003_agent_registry.sql +26 -0
  60. package/dist/memory/sqlite/migrations/004_run_runtime.sql +62 -0
  61. package/dist/memory/sqlite/migrations/005_run_approvals.sql +20 -0
  62. package/dist/memory/sqlite/migrations/006_run_operation_attempts.sql +32 -0
  63. package/dist/memory/sqlite/migrations/007_abandoned_operation_attempts.sql +46 -0
  64. package/dist/memory/sqlite/migrations/008_run_execution_plan_events.sql +105 -0
  65. package/dist/memory/sqlite/migrations/009_multiple_operation_attempts.sql +73 -0
  66. package/dist/memory/sqlite/migrations/010_skill_registry.sql +66 -0
  67. package/dist/memory/sqlite/migrations/011_skill_usage_resolution_outcomes.sql +21 -0
  68. package/dist/memory/sqlite/migrations/012_skill_improvement_proposals.sql +37 -0
  69. package/dist/memory/sqlite/migrations/013_skill_evaluation_scenarios.sql +43 -0
  70. package/dist/memory/sqlite/migrations/014_manager_profile_overlays.sql +14 -0
  71. package/dist/memory/storage-paths.js +72 -0
  72. package/dist/orchestrator/natural-language-planner.js +191 -0
  73. package/dist/orchestrator/schema.js +1 -0
  74. package/dist/permissions/index.js +2 -0
  75. package/dist/permissions/policy-evaluator.js +109 -0
  76. package/dist/permissions/schema.js +1 -0
  77. package/dist/providers/opencode/injection-preview.js +134 -0
  78. package/dist/providers/opencode/manager-payload.js +129 -0
  79. package/dist/runs/execution-planning.js +117 -0
  80. package/dist/runs/operation-execution.js +1 -0
  81. package/dist/runs/operation-retry.js +124 -0
  82. package/dist/runs/repositories/runs.js +611 -0
  83. package/dist/runs/run-insights.js +145 -0
  84. package/dist/runs/run-service.js +713 -0
  85. package/dist/runs/run-snapshot-export-service.js +31 -0
  86. package/dist/runs/sandbox-process-execution.js +218 -0
  87. package/dist/runs/sandbox-worktree-planning.js +59 -0
  88. package/dist/runs/schema.js +1 -0
  89. package/dist/sdd/artifact-portability-service.js +118 -0
  90. package/dist/sdd/schema.js +17 -0
  91. package/dist/sdd/sdd-workflow-service.js +217 -0
  92. package/dist/setup/backup-rollback-service.js +76 -0
  93. package/dist/setup/index.js +3 -0
  94. package/dist/setup/providers/antigravity-setup-adapter.js +18 -0
  95. package/dist/setup/providers/claude-setup-adapter.js +30 -0
  96. package/dist/setup/providers/custom-setup-adapter.js +18 -0
  97. package/dist/setup/providers/index.js +6 -0
  98. package/dist/setup/providers/opencode-setup-adapter.js +104 -0
  99. package/dist/setup/providers/provider-setup-adapter.js +15 -0
  100. package/dist/setup/providers/provider-setup-registry.js +11 -0
  101. package/dist/setup/schema.js +1 -0
  102. package/dist/setup/setup-defaults.js +11 -0
  103. package/dist/setup/setup-lifecycle-service.js +175 -0
  104. package/dist/setup/setup-plan.js +105 -0
  105. package/dist/skills/repositories/skill-evaluation-scenarios.js +289 -0
  106. package/dist/skills/repositories/skill-improvement-proposals.js +288 -0
  107. package/dist/skills/repositories/skills.js +430 -0
  108. package/dist/skills/schema.js +1 -0
  109. package/dist/skills/skill-payload.js +94 -0
  110. package/dist/skills/skill-registry-service.js +92 -0
  111. package/dist/skills/skill-resolver.js +191 -0
  112. package/dist/workflows/command-allowlist-adapter.js +70 -0
  113. package/dist/workflows/schema.js +4 -0
  114. package/dist/workflows/workflow-executor.js +345 -0
  115. package/dist/workflows/workflow-registry.js +66 -0
  116. package/docs/architecture.md +698 -0
  117. package/docs/cli.md +741 -0
  118. package/docs/funcionamiento-del-sistema.md +868 -0
  119. package/docs/harness-gap-analysis.md +229 -0
  120. package/docs/prd.md +372 -0
  121. package/package.json +57 -0
@@ -0,0 +1,156 @@
1
+ export const vgxnessOpenCodeDefaultAgent = 'vgxness-manager';
2
+ export const vgxnessOpenCodeSddSubagents = [
3
+ 'vgxness-sdd-explore',
4
+ 'vgxness-sdd-propose',
5
+ 'vgxness-sdd-spec',
6
+ 'vgxness-sdd-design',
7
+ 'vgxness-sdd-tasks',
8
+ 'vgxness-sdd-apply',
9
+ 'vgxness-sdd-verify',
10
+ 'vgxness-sdd-archive',
11
+ 'vgxness-sdd-init',
12
+ 'vgxness-sdd-onboard',
13
+ ];
14
+ export function createOpenCodeSddTaskPermissions() {
15
+ const taskPermissions = { '*': 'deny' };
16
+ for (const subagent of vgxnessOpenCodeSddSubagents)
17
+ taskPermissions[subagent] = 'allow';
18
+ return taskPermissions;
19
+ }
20
+ export function createOpenCodeDefaultAgentInstallPlan(input = {}) {
21
+ if (input.mcpOnly === true)
22
+ return { installsAgents: false, agentNames: [] };
23
+ return { installsAgents: true, agentNames: [vgxnessOpenCodeDefaultAgent, ...vgxnessOpenCodeSddSubagents], defaultAgent: vgxnessOpenCodeDefaultAgent };
24
+ }
25
+ export function createOpenCodeDefaultAgentConfig() {
26
+ const agents = {
27
+ [vgxnessOpenCodeDefaultAgent]: {
28
+ description: 'VGXNESS SDD Manager - coordinates MCP state and SDD sub-agents, avoids inline execution when delegation is safer',
29
+ mode: 'primary',
30
+ model: 'openai/gpt-5.5',
31
+ options: { reasoningEffort: 'high' },
32
+ permission: { task: createOpenCodeSddTaskPermissions() },
33
+ prompt: vgxnessManagerPrompt,
34
+ reasoningEffort: 'high',
35
+ tools: { bash: true, delegate: true, delegation_list: true, delegation_read: true, edit: true, read: true, write: true },
36
+ variant: '',
37
+ },
38
+ };
39
+ const descriptions = {
40
+ 'vgxness-sdd-explore': 'Investigate codebase and think through ideas',
41
+ 'vgxness-sdd-propose': 'Create change proposals from explorations',
42
+ 'vgxness-sdd-spec': 'Write detailed specifications from proposals',
43
+ 'vgxness-sdd-design': 'Create technical design from proposals',
44
+ 'vgxness-sdd-tasks': 'Break down specs and designs into implementation tasks',
45
+ 'vgxness-sdd-apply': 'Implement code changes from task definitions',
46
+ 'vgxness-sdd-verify': 'Validate implementation against specs',
47
+ 'vgxness-sdd-archive': 'Archive completed change artifacts',
48
+ 'vgxness-sdd-init': 'Bootstrap SDD context and project configuration',
49
+ 'vgxness-sdd-onboard': 'Guide user through a complete SDD cycle using their real codebase',
50
+ };
51
+ for (const name of vgxnessOpenCodeSddSubagents) {
52
+ agents[name] = {
53
+ description: descriptions[name],
54
+ hidden: true,
55
+ mode: 'subagent',
56
+ model: 'openai/gpt-5.5',
57
+ prompt: createSddSubagentPrompt(name),
58
+ tools: { bash: true, edit: true, read: true, write: true },
59
+ };
60
+ }
61
+ return { defaultAgent: vgxnessOpenCodeDefaultAgent, agents };
62
+ }
63
+ function createSddSubagentPrompt(name) {
64
+ const phase = name.replace('vgxness-sdd-', '');
65
+ 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. Do not depend on external local skill files; this inline contract is sufficient. Preserve unrelated user work, keep output concise, and report evidence.`;
66
+ const contracts = {
67
+ 'vgxness-sdd-explore': 'Investigate codebase context, constraints, options, and risks. Do not implement code changes. Return findings and recommended next artifacts.',
68
+ 'vgxness-sdd-propose': 'Create or refine a focused SDD proposal from exploration evidence. Do not implement code changes. Include scope, tradeoffs, non-goals, and acceptance direction.',
69
+ 'vgxness-sdd-spec': 'Write requirements, acceptance criteria, edge cases, and out-of-scope items. Do not implement code changes.',
70
+ 'vgxness-sdd-design': 'Create technical design grounded in the repository: affected modules, data shapes, safety, rollout, and verification. Do not implement code changes.',
71
+ 'vgxness-sdd-tasks': 'Break approved spec/design into small ordered testable implementation tasks. Do not implement code changes.',
72
+ 'vgxness-sdd-apply': '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.',
73
+ 'vgxness-sdd-verify': 'Validate implementation against SDD artifacts and task acceptance criteria. Prefer focused local tests and evidence review. Do not implement unrelated changes.',
74
+ 'vgxness-sdd-archive': 'Archive completed SDD outcome with summary, verification evidence, follow-ups, and residual risks. Confirm before any repository writes beyond the requested archive artifact.',
75
+ 'vgxness-sdd-init': 'Bootstrap SDD context and project setup safely. Prefer diagnostics/read-only inspection and require explicit confirmation before writes or provider/global config changes.',
76
+ 'vgxness-sdd-onboard': 'Guide the user through the SDD cycle with the smallest missing decision at each step. Keep assumptions explicit and confirm before writes or provider/global config changes.',
77
+ };
78
+ return `${common}\n\nPhase contract: ${contracts[name]}`;
79
+ }
80
+ const vgxnessManagerPrompt = `# VGXNESS Manager - SDD Orchestrator Instructions
81
+
82
+ Bind this to the dedicated \`vgxness-manager\` primary agent only. Do NOT apply it to executor phase agents such as \`vgxness-sdd-apply\` or \`vgxness-sdd-verify\`.
83
+
84
+ ## Role
85
+
86
+ You are the VGXNESS SDD coordinator, not a monolithic executor. Keep one thin conversation thread, use VGXNESS MCP for durable state, delegate real phase work to the smallest appropriate SDD sub-agent, then synthesize results for the user.
87
+
88
+ Act with the personality configured for VGXNESS: direct, practical, grounded in the repository, and willing to challenge weak assumptions. Preserve user control. Prefer small, safe, testable changes. Keep VGXNESS terminology and behavior clean; do not import concepts from unrelated orchestrator experiments.
89
+
90
+ ## MCP-First Operating Model
91
+
92
+ Use the \`vgxness\` MCP server as the source of durable workflow state. MCP tools coordinate and persist. OpenCode sub-agent delegation performs phase work. Do not rely on external \`sdd-*\` skill files; default manager and subagent contracts are inline.
93
+
94
+ ## MCP Tool Playbook
95
+
96
+ - SDD state and artifacts: use \`vgxness_sdd_status\`, \`vgxness_sdd_next\`, and \`vgxness_sdd_ready\` before advancing phases; read prerequisites with \`vgxness_sdd_get_artifact\` or \`vgxness_sdd_list_artifacts\`; persist accepted phase output with \`vgxness_sdd_save_artifact\`. SDD artifacts are not generic memory.
97
+ - Session lifecycle: when starting, resuming, or recovering context, call \`vgxness_session_restore\` with the project and workspace directory before inferring state from chat. Before ending, pausing, handing off, or compacting, call \`vgxness_session_close\` with the current session id, actor \`manager\`, and a concise actionable summary. If no current session id is available, do not invent one; state that clearly and preserve the actionable summary in the final response.
98
+ - Memory: use \`vgxness_memory_search\` at the start when the user references previous work, remembered decisions, prior solutions, or unclear project context; use \`vgxness_memory_get\` for full relevant results; use \`vgxness_memory_save\` immediately after durable discoveries, decisions, bug fixes, configuration changes, patterns, or preferences; use \`vgxness_memory_update\` when correcting/evolving a known observation id. Do not duplicate full SDD artifacts as memory.
99
+ - Agents: use \`vgxness_agent_resolve\` with project/scope/workflow/phase/provider/mode before substantial SDD phase execution. \`vgxness_agent_activate\` prepares provider-ready context/run payloads only; it does not execute a provider or write provider config.
100
+ - Manager/profile and payloads: use \`vgxness_manager_profile_get\` before changing manager behavior. \`vgxness_manager_profile_set\` is a persistent behavior change and requires explicit human confirmation. \`vgxness_skill_payload\` builds context only and does not install skill files. \`vgxness_opencode_manager_payload\` is a read-only preview; it does not install, execute, load seeds, or write provider config.
101
+ - Runs: simple questions do not require runs by default. For significant implementation, verification, risky, or multi-step delegated work, create or recover state with \`vgxness_run_start\`, \`vgxness_run_list\`, and \`vgxness_run_get\`; record progress with \`vgxness_run_checkpoint\`; call \`vgxness_run_preflight\` before edit, shell, git, network, external-directory, provider-tool, secrets, privileged, destructive, or ambiguous operations; close clear outcomes with \`vgxness_run_finalize\`.
102
+ - Safety: do not call MCP with unsupported execution/config fields such as \`executeProvider\` or \`writesProviderConfig\`. Do not mutate provider/global OpenCode config unless the user explicitly asks for install/apply/configuration changes.
103
+
104
+ ## Request Type -> Minimum MCP Sequence
105
+
106
+ | Request type | Minimum sequence |
107
+ |---|---|
108
+ | Start/resume/recover conversation | \`vgxness_session_restore\` with project + workspace directory -> use returned session summary/activity before asking for missing context or inferring from chat. |
109
+ | Simple question or small explanation | Answer inline; search/get memory only if prior context is referenced; no run by default. |
110
+ | SDD proposal/spec/design/tasks | \`vgxness_sdd_status\` or \`vgxness_sdd_next\` -> \`vgxness_sdd_ready\` -> \`vgxness_sdd_get_artifact\`/\`vgxness_sdd_list_artifacts\` -> \`vgxness_agent_resolve\` -> delegate exact phase subagent -> \`vgxness_sdd_save_artifact\` after accepted output. |
111
+ | Apply/verify | Require/recover \`tasks\` for apply and \`apply-progress\` for verify; get relevant artifacts -> resolve exact subagent -> \`vgxness_run_start\` or recover run -> \`vgxness_run_preflight\` for writes/shell/git/tests -> delegate -> checkpoint -> save \`apply-progress\`/\`verify\` artifact -> finalize when outcome is clear. |
112
+ | Config/provider/prompt changes | \`vgxness_manager_profile_get\` and/or \`vgxness_opencode_manager_payload\` first; use \`vgxness_manager_profile_set\` or OpenCode install only with explicit human authorization. |
113
+ | Resume/diagnostics | Use \`vgxness_run_list\`, \`vgxness_run_get\`, \`vgxness_sdd_status\`, and artifact reads before inferring state from chat. |
114
+ | Close/pause/handoff/compact conversation | \`vgxness_session_close\` with current session id, actor \`manager\`, and concise actionable summary -> final user response; if the id is unavailable, say so and include the summary in the final response. |
115
+
116
+ ## Delegation Rules
117
+
118
+ Core principle: does this inflate the manager context without need? If yes, delegate. If no, keep it inline.
119
+
120
+ Do not perform substantial multi-file implementation inline. Resolve/delegate phase work to exact allowed SDD subagents, synthesize results, and persist artifacts/checkpoints through MCP.
121
+
122
+ | Action | Inline | Delegate |
123
+ |--------|--------|----------|
124
+ | Read to decide/verify 1-3 files | Yes | No |
125
+ | Read to explore/understand 4+ files | No | Yes |
126
+ | Read as preparation for writing | No | Yes, together with the write |
127
+ | Write atomic one-file mechanical change | Yes | No |
128
+ | Write with analysis, multiple files, or new logic | No | Yes |
129
+ | Bash for state such as git, gh, status | Yes | No |
130
+ | Bash for execution such as tests, installs, external tooling | No | Yes |
131
+
132
+ ## SDD Phase Mapping
133
+
134
+ - Explore or investigate: \`vgxness-sdd-explore\`
135
+ - Proposal: \`vgxness-sdd-propose\`
136
+ - Spec: \`vgxness-sdd-spec\`
137
+ - Design: \`vgxness-sdd-design\`
138
+ - Tasks: \`vgxness-sdd-tasks\`
139
+ - Apply implementation: \`vgxness-sdd-apply\`
140
+ - Verify implementation: \`vgxness-sdd-verify\`
141
+ - Archive completed work: \`vgxness-sdd-archive\`
142
+ - Onboard/init: \`vgxness-sdd-onboard\` or \`vgxness-sdd-init\`
143
+
144
+ ## Safety Boundaries
145
+
146
+ - Do not mutate provider config unless the user explicitly asks for provider configuration changes.
147
+ - Do not mutate global OpenCode config or provider config unless the user explicitly asks for install/apply/configuration changes.
148
+ - Do not write to \`openspec/\`.
149
+ - Do not publish packages unless explicitly requested.
150
+ - Never revert or overwrite user changes unless explicitly requested.
151
+ - Keep unrelated dirty files out of commits.
152
+ - Preserve \`permission.task\` as deny-by-default: only exact known SDD subagents are allowed; wildcard delegation remains denied.
153
+
154
+ ## Output Discipline
155
+
156
+ Keep the manager response concise. Say what was delegated, what came back, what changed, and what remains.`;
@@ -0,0 +1,102 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join, relative, resolve } from 'node:path';
3
+ import { resolveOpenCodeMcpInstallTarget } from './client-install-opencode-contract.js';
4
+ import { SUPPORTED_VGX_MCP_TOOL_NAMES } from './schema.js';
5
+ const serverName = 'vgxness';
6
+ const expectedToolCount = SUPPORTED_VGX_MCP_TOOL_NAMES.length;
7
+ export function createOpenCodeMcpVisibilityReport(options) {
8
+ const cwd = resolve(options.cwd);
9
+ const projectRoot = resolve(options.projectRoot ?? findNearestOpenCodeProjectRoot(cwd));
10
+ const targetScope = options.scope ?? 'project';
11
+ const projectTargetPath = join(projectRoot, '.opencode', 'opencode.json');
12
+ const cwdInsideProject = isPathInsideOrEqual(cwd, projectRoot);
13
+ const projectConfigExists = existsSync(projectTargetPath);
14
+ const projectHasVgxnessServer = projectConfigExists && readHasVgxnessServer(projectTargetPath);
15
+ const projectVisibleFromCurrentCwd = cwdInsideProject && projectConfigExists && projectHasVgxnessServer;
16
+ const userTarget = resolveOpenCodeMcpInstallTarget({ cwd: projectRoot, scope: 'user', env: options.env });
17
+ const userReport = userTarget.ok ? userVisibilityReport(userTarget.path, projectVisibleFromCurrentCwd) : undefined;
18
+ const selectedTargetPath = targetScope === 'user' && userTarget.ok ? userTarget.path : projectTargetPath;
19
+ const selectedReady = targetScope === 'user'
20
+ ? userReport?.configExists === true && userReport.hasVgxnessServer
21
+ : projectVisibleFromCurrentCwd;
22
+ return {
23
+ version: 1,
24
+ kind: 'mcp-doctor-opencode-visibility',
25
+ ready: selectedReady,
26
+ cwd,
27
+ projectRoot,
28
+ targetScope,
29
+ targetPath: selectedTargetPath,
30
+ targets: {
31
+ project: { path: projectTargetPath, configExists: projectConfigExists, hasVgxnessServer: projectHasVgxnessServer, visibleFromCurrentCwd: projectVisibleFromCurrentCwd },
32
+ ...(userReport !== undefined ? { user: userReport } : {}),
33
+ },
34
+ visibility: { cwdInsideProject, configExists: projectConfigExists, hasVgxnessServer: projectHasVgxnessServer },
35
+ expected: { serverName, toolCount: expectedToolCount, visibleFromCurrentCwd: selectedReady },
36
+ guidance: buildGuidance({
37
+ cwdInsideProject,
38
+ configExists: projectConfigExists,
39
+ hasVgxnessServer: projectHasVgxnessServer,
40
+ targetScope,
41
+ ...(userTarget.ok ? {} : { userTargetMessage: userTarget.message }),
42
+ userOverridden: userReport?.overriddenByProjectConfig === true,
43
+ }),
44
+ safety: { readOnly: true, writesProviderConfig: false, globalInstallDeferred: true },
45
+ };
46
+ }
47
+ function buildGuidance(state) {
48
+ const guidance = [
49
+ 'Run `opencode mcp list` from inside the vgxness worktree to verify project-local MCP visibility.',
50
+ 'After OpenCode starts inside vgxness, the expected connected-tools result is `vgxness` with the registered VGXNESS MCP tools from the current build.',
51
+ 'Restart OpenCode if the project-local server is not listed after config changes.',
52
+ ];
53
+ if (state.targetScope === 'user') {
54
+ guidance.push('User scope targets `$HOME/.config/opencode/opencode.json` and this diagnostic reads it without writing provider config.');
55
+ guidance.push('Project OpenCode config can override user config for a workspace; inspect project config first when both define `mcp.vgxness`.');
56
+ }
57
+ if (state.userTargetMessage !== undefined)
58
+ guidance.push(state.userTargetMessage);
59
+ if (state.userOverridden)
60
+ guidance.push('Project OpenCode config can override user config for this workspace because both project and user targets define `mcp.vgxness`.');
61
+ if (!state.cwdInsideProject) {
62
+ guidance.push('The project-local `vgxness` server is not expected to appear from outside the worktree.');
63
+ guidance.push('Use `mcp install opencode --scope user --plan` to inspect the user config target without writing it.');
64
+ }
65
+ if (!state.configExists)
66
+ guidance.push('Expected project-local config `.opencode/opencode.json` was not found.');
67
+ if (state.configExists && !state.hasVgxnessServer)
68
+ guidance.push('Project-local config exists, but it does not define `mcp.vgxness`.');
69
+ return guidance;
70
+ }
71
+ function userVisibilityReport(targetPath, projectVisibleFromCurrentCwd) {
72
+ const configExists = existsSync(targetPath);
73
+ const hasVgxnessServer = configExists && readHasVgxnessServer(targetPath);
74
+ return { path: targetPath, configExists, hasVgxnessServer, overriddenByProjectConfig: projectVisibleFromCurrentCwd && hasVgxnessServer };
75
+ }
76
+ function readHasVgxnessServer(targetPath) {
77
+ try {
78
+ const parsed = JSON.parse(readFileSync(targetPath, 'utf8'));
79
+ return isRecord(parsed) && isRecord(parsed.mcp) && isRecord(parsed.mcp[serverName]);
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ }
85
+ function isPathInsideOrEqual(candidate, parent) {
86
+ const relativePath = relative(parent, candidate);
87
+ return relativePath === '' || (!relativePath.startsWith('..') && !relativePath.startsWith('/') && !relativePath.startsWith('\\'));
88
+ }
89
+ function findNearestOpenCodeProjectRoot(start) {
90
+ let current = resolve(start);
91
+ while (true) {
92
+ if (existsSync(join(current, '.opencode', 'opencode.json')))
93
+ return current;
94
+ const parent = dirname(current);
95
+ if (parent === current)
96
+ return start;
97
+ current = parent;
98
+ }
99
+ }
100
+ function isRecord(value) {
101
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
102
+ }
@@ -0,0 +1,234 @@
1
+ import { z } from 'zod';
2
+ import { sddPhases } from '../sdd/schema.js';
3
+ export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
4
+ 'vgxness_sdd_status',
5
+ 'vgxness_sdd_ready',
6
+ 'vgxness_sdd_save_artifact',
7
+ 'vgxness_sdd_get_artifact',
8
+ 'vgxness_sdd_list_artifacts',
9
+ 'vgxness_sdd_next',
10
+ 'vgxness_memory_save',
11
+ 'vgxness_memory_search',
12
+ 'vgxness_memory_get',
13
+ 'vgxness_memory_update',
14
+ 'vgxness_session_start',
15
+ 'vgxness_session_append_activity',
16
+ 'vgxness_session_close',
17
+ 'vgxness_session_restore',
18
+ 'vgxness_agent_resolve',
19
+ 'vgxness_agent_activate',
20
+ 'vgxness_manager_profile_get',
21
+ 'vgxness_manager_profile_set',
22
+ 'vgxness_skill_payload',
23
+ 'vgxness_opencode_manager_payload',
24
+ 'vgxness_run_list',
25
+ 'vgxness_run_get',
26
+ 'vgxness_run_preflight',
27
+ 'vgxness_run_start',
28
+ 'vgxness_run_checkpoint',
29
+ 'vgxness_run_finalize',
30
+ ];
31
+ const scopes = ['project', 'personal'];
32
+ const agentModes = ['agent', 'subagent'];
33
+ const memoryTypes = ['architecture', 'decision', 'bugfix', 'pattern', 'config', 'discovery', 'learning', 'preference', 'manual'];
34
+ const activityKinds = ['prompt', 'tool_call', 'artifact', 'summary', 'error'];
35
+ const runStatuses = ['created', 'planned', 'running', 'needs-human', 'completed', 'failed', 'blocked', 'cancelled'];
36
+ const finalRunStatuses = ['completed', 'failed', 'blocked', 'cancelled'];
37
+ const runOutcomes = ['success', 'partial', 'failure', 'blocked', 'cancelled'];
38
+ const permissionCategories = ['read', 'edit', 'shell', 'network', 'git', 'memory', 'external-directory', 'provider-tool', 'secrets'];
39
+ const jsonValueSchema = z.lazy(() => z.union([
40
+ z.string(),
41
+ z.number().finite(),
42
+ z.boolean(),
43
+ z.null(),
44
+ z.array(jsonValueSchema),
45
+ z.record(z.string(), jsonValueSchema),
46
+ ]));
47
+ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
48
+ vgxness_sdd_status: z.object({
49
+ project: z.string().min(1),
50
+ change: z.string().min(1),
51
+ }).passthrough(),
52
+ vgxness_sdd_ready: z.object({
53
+ project: z.string().min(1),
54
+ change: z.string().min(1),
55
+ phase: z.enum(sddPhases),
56
+ }).passthrough(),
57
+ vgxness_sdd_save_artifact: z.object({
58
+ project: z.string().min(1),
59
+ change: z.string().min(1),
60
+ phase: z.enum(sddPhases),
61
+ content: z.string().min(1),
62
+ }).passthrough(),
63
+ vgxness_sdd_get_artifact: z.object({
64
+ project: z.string().min(1),
65
+ change: z.string().min(1),
66
+ phase: z.enum(sddPhases),
67
+ }).passthrough(),
68
+ vgxness_sdd_list_artifacts: z.object({
69
+ project: z.string().min(1),
70
+ change: z.string().min(1),
71
+ }).passthrough(),
72
+ vgxness_sdd_next: z.object({
73
+ project: z.string().min(1),
74
+ change: z.string().min(1),
75
+ }).passthrough(),
76
+ vgxness_memory_save: z.object({
77
+ project: z.string().min(1),
78
+ scope: z.enum(scopes).optional(),
79
+ type: z.enum(memoryTypes),
80
+ title: z.string().min(1),
81
+ content: z.string().min(1),
82
+ topicKey: z.string().min(1).optional(),
83
+ }).passthrough(),
84
+ vgxness_memory_search: z.object({
85
+ project: z.string().min(1).optional(),
86
+ scope: z.enum(scopes).optional(),
87
+ type: z.enum(memoryTypes).optional(),
88
+ topicKey: z.string().min(1).optional(),
89
+ query: z.string().min(1).optional(),
90
+ limit: z.number().int().min(1).max(100),
91
+ }).passthrough(),
92
+ vgxness_memory_get: z.object({
93
+ id: z.string().min(1),
94
+ }).passthrough(),
95
+ vgxness_memory_update: z.object({
96
+ id: z.string().min(1),
97
+ type: z.enum(memoryTypes).optional(),
98
+ title: z.string().min(1).optional(),
99
+ content: z.string().min(1).optional(),
100
+ topicKey: z.string().min(1).optional(),
101
+ }).passthrough(),
102
+ vgxness_session_start: z.object({
103
+ id: z.string().min(1).optional(),
104
+ project: z.string().min(1),
105
+ directory: z.string().min(1).optional(),
106
+ }).passthrough(),
107
+ vgxness_session_append_activity: z.object({
108
+ sessionId: z.string().min(1),
109
+ actor: z.string().min(1),
110
+ kind: z.enum(activityKinds),
111
+ payloadJson: z.string().min(1),
112
+ }).passthrough(),
113
+ vgxness_session_close: z.object({
114
+ sessionId: z.string().min(1),
115
+ actor: z.string().min(1),
116
+ summary: z.string().trim().min(1),
117
+ }).passthrough(),
118
+ vgxness_session_restore: z.object({
119
+ project: z.string().min(1),
120
+ directory: z.string().min(1).optional(),
121
+ }).passthrough(),
122
+ vgxness_agent_resolve: z.object({
123
+ project: z.string().min(1).optional(),
124
+ scope: z.enum(scopes).optional(),
125
+ taskDescription: z.string().min(1).optional(),
126
+ intent: z.string().min(1).optional(),
127
+ desiredCapabilities: z.array(z.string().min(1)).optional(),
128
+ workflow: z.string().min(1).optional(),
129
+ phase: z.string().min(1).optional(),
130
+ providerAdapter: z.string().min(1).optional(),
131
+ mode: z.enum(agentModes).optional(),
132
+ }).passthrough(),
133
+ vgxness_agent_activate: z.object({
134
+ project: z.string().min(1),
135
+ scope: z.enum(scopes).optional(),
136
+ agentId: z.string().min(1).optional(),
137
+ userIntent: z.string().min(1),
138
+ workflow: z.string().min(1).optional(),
139
+ phase: z.string().min(1).optional(),
140
+ workspaceRoot: z.string().min(1).optional(),
141
+ maxSourceBytes: z.number().int().positive().optional(),
142
+ providerAdapter: z.string().min(1).optional(),
143
+ }).passthrough(),
144
+ vgxness_manager_profile_get: z.object({
145
+ project: z.string().min(1),
146
+ scope: z.enum(scopes).optional(),
147
+ managerName: z.string().min(1).optional(),
148
+ }).passthrough(),
149
+ vgxness_manager_profile_set: z.object({
150
+ project: z.string().min(1),
151
+ scope: z.enum(scopes),
152
+ managerName: z.string().min(1),
153
+ instructions: z.string().min(1),
154
+ }).passthrough(),
155
+ vgxness_skill_payload: z.object({
156
+ workspaceRoot: z.string().min(1),
157
+ maxSourceBytes: z.number().int().positive().optional(),
158
+ project: z.string().min(1).optional(),
159
+ scope: z.enum(scopes).optional(),
160
+ agentId: z.string().min(1).optional(),
161
+ agentName: z.string().min(1).optional(),
162
+ workflow: z.string().min(1).optional(),
163
+ phase: z.string().min(1).optional(),
164
+ providerAdapter: z.string().min(1).optional(),
165
+ runId: z.string().min(1).optional(),
166
+ }).passthrough(),
167
+ vgxness_opencode_manager_payload: z.object({
168
+ project: z.string().min(1),
169
+ scope: z.enum(scopes).optional(),
170
+ agentId: z.string().min(1).optional(),
171
+ agentName: z.string().min(1).optional(),
172
+ workspaceRoot: z.string().min(1).optional(),
173
+ maxSourceBytes: z.number().int().positive().optional(),
174
+ }).passthrough(),
175
+ vgxness_run_list: z.object({
176
+ project: z.string().min(1).optional(),
177
+ status: z.enum(runStatuses).optional(),
178
+ limit: z.number().int().min(1).max(100),
179
+ }).passthrough(),
180
+ vgxness_run_get: z.object({
181
+ id: z.string().min(1),
182
+ }).passthrough(),
183
+ vgxness_run_preflight: z.object({
184
+ runId: z.string().min(1),
185
+ category: z.enum(permissionCategories),
186
+ operation: z.string().min(1),
187
+ workspaceRoot: z.string().min(1).optional(),
188
+ targetPath: z.string().min(1).optional(),
189
+ providerToolName: z.string().min(1).optional(),
190
+ agent: z.object({
191
+ id: z.string().min(1),
192
+ name: z.string().min(1).optional(),
193
+ mode: z.enum(agentModes),
194
+ permissions: z.record(z.enum(permissionCategories), z.enum(['allow', 'ask', 'deny'])).optional(),
195
+ }).optional(),
196
+ sandboxStrategy: z.enum(['worktree']).optional(),
197
+ destructive: z.boolean().optional(),
198
+ external: z.boolean().optional(),
199
+ privileged: z.boolean().optional(),
200
+ ambiguous: z.boolean().optional(),
201
+ }).passthrough(),
202
+ vgxness_run_start: z.object({
203
+ project: z.string().min(1),
204
+ userIntent: z.string().min(1),
205
+ workflow: z.string().min(1),
206
+ phase: z.string().min(1),
207
+ selectedAgentId: z.string().min(1),
208
+ providerAdapter: z.string().min(1),
209
+ model: z.string().min(1),
210
+ }).passthrough(),
211
+ vgxness_run_checkpoint: z.object({
212
+ runId: z.string().min(1),
213
+ label: z.string().min(1),
214
+ state: jsonValueSchema,
215
+ }).passthrough(),
216
+ vgxness_run_finalize: z.object({
217
+ runId: z.string().min(1),
218
+ status: z.enum(finalRunStatuses),
219
+ outcome: z.enum(runOutcomes),
220
+ outcomeReason: z.string().min(1).optional(),
221
+ }).passthrough(),
222
+ };
223
+ export function successEnvelope(tool, value) {
224
+ return { ok: true, tool, value };
225
+ }
226
+ export function errorEnvelope(code, message, tool) {
227
+ const result = { ok: false, error: { code, message } };
228
+ if (tool !== undefined)
229
+ result.tool = tool;
230
+ return result;
231
+ }
232
+ export function isVgxMcpToolName(value) {
233
+ return typeof value === 'string' && SUPPORTED_VGX_MCP_TOOL_NAMES.includes(value);
234
+ }
@@ -0,0 +1,56 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createVgxMcpControlPlane } from './control-plane.js';
4
+ import { SUPPORTED_VGX_MCP_TOOL_NAMES, VGX_MCP_TOOL_INPUT_SCHEMAS } from './schema.js';
5
+ export async function startVgxMcpStdioServer(options = {}) {
6
+ const controlPlane = createVgxMcpControlPlane(options.databasePath === undefined ? {} : { databasePath: options.databasePath });
7
+ const mcpServer = new McpServer({ name: 'vgxness', version: '0.1.0' });
8
+ const transport = new StdioServerTransport();
9
+ let closed = false;
10
+ const close = async () => {
11
+ if (closed)
12
+ return;
13
+ closed = true;
14
+ process.off('SIGINT', closeOnSignal);
15
+ process.off('SIGTERM', closeOnSignal);
16
+ try {
17
+ await mcpServer.close();
18
+ }
19
+ finally {
20
+ controlPlane.close();
21
+ }
22
+ };
23
+ const closeOnSignal = () => {
24
+ void close().finally(() => {
25
+ process.exitCode = 0;
26
+ });
27
+ };
28
+ mcpServer.server.onclose = () => {
29
+ controlPlane.close();
30
+ };
31
+ registerVgxTools(mcpServer, controlPlane);
32
+ process.once('SIGINT', closeOnSignal);
33
+ process.once('SIGTERM', closeOnSignal);
34
+ await mcpServer.connect(transport);
35
+ return { close };
36
+ }
37
+ function registerVgxTools(server, controlPlane) {
38
+ for (const toolName of SUPPORTED_VGX_MCP_TOOL_NAMES) {
39
+ server.registerTool(toolName, {
40
+ title: toolName,
41
+ description: `VGX control-plane tool ${toolName}`,
42
+ inputSchema: VGX_MCP_TOOL_INPUT_SCHEMAS[toolName],
43
+ }, async (args) => toMcpTextResult(controlPlane.callVgxTool(toolName, argsForTool(args))));
44
+ }
45
+ }
46
+ function argsForTool(args) {
47
+ return args;
48
+ }
49
+ function toMcpTextResult(envelope) {
50
+ const result = {
51
+ content: [{ type: 'text', text: JSON.stringify(envelope, null, 2) }],
52
+ };
53
+ if (!envelope.ok)
54
+ result.isError = true;
55
+ return result;
56
+ }