vgxness 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/canonical-agent-manifest.js +8 -7
- package/dist/cli/cli-flags.js +3 -3
- package/dist/cli/cli-help.js +4 -4
- package/dist/cli/commands/agent-skill-dispatcher.js +10 -1
- package/dist/mcp/control-plane.js +5 -0
- package/dist/mcp/provider-doctor.js +10 -6
- package/dist/mcp/provider-health-types.js +20 -0
- package/dist/mcp/provider-status.js +18 -6
- package/dist/mcp/schema.js +177 -0
- package/dist/mcp/stdio-server.js +20 -5
- package/dist/mcp/validation.js +6 -0
- package/dist/memory/sqlite/migrations/017_intent_signal_skill_targets.sql +42 -0
- package/dist/orchestrator/natural-language-planner.js +53 -8
- package/dist/sdd/cockpit-read-model.js +2 -0
- package/dist/sdd/sdd-continuation-plan.js +149 -0
- package/dist/sdd/sdd-workflow-service.js +127 -4
- package/dist/skills/boot-seed.js +42 -0
- package/dist/skills/skill-resolver.js +6 -0
- package/dist/skills/skill-seed-service.js +39 -16
- package/docs/sdd-flow.es.md +403 -0
- package/docs/sdd-flow.md +403 -0
- package/package.json +1 -1
- package/seeds/skills/skill-seed-v1.json +73 -1
|
@@ -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 = 11;
|
|
6
6
|
export const canonicalSddSubagentNames = [
|
|
7
7
|
'vgxness-sdd-explore',
|
|
8
8
|
'vgxness-sdd-propose',
|
|
@@ -78,7 +78,7 @@ 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: registryManagerInstructionsV11 },
|
|
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'] },
|
|
@@ -166,7 +166,7 @@ Coordinate SDD; keep chat thin, use VGXNESS MCP as durable state, delegate to sm
|
|
|
166
166
|
Use the lightest safe path: Tier 0-2 direct; Tier 3 preflight; Tier 4 formal SDD for governance, permissions, acceptance, architecture/security, or cross-surface behavior. Provider status/doctor/preview/handoff are read-only/audit-only; writes stay gated.
|
|
167
167
|
|
|
168
168
|
## Provider-native daily flow
|
|
169
|
-
|
|
169
|
+
SDD happens in OpenCode via conversation, VGXNESS MCP, and SDD subagents. No terminal SDD phase commands for normal flow. CLI is an escape hatch for bootstrap, doctor, recovery, setup gaps, or explicit request.
|
|
170
170
|
|
|
171
171
|
## MCP playbook
|
|
172
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.
|
|
@@ -174,9 +174,9 @@ Daily SDD happens inside OpenCode through conversation, VGXNESS MCP, and hidden
|
|
|
174
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.
|
|
175
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.
|
|
176
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.
|
|
177
|
-
- Agents/profile/payloads: resolve
|
|
178
|
-
- Runs/recovery: use \`vgxness_run_start\`/\`vgxness_run_list\`/\`vgxness_run_get\` for run work; checkpoint with \`vgxness_run_checkpoint\`, preflight with \`vgxness_run_preflight\`, and close with \`vgxness_run_finalize\`. Unknown runId: \`vgxness_run_resume_candidates\`. For interrupted runs, inspect with \`vgxness_run_resume_inspect\`, then call \`vgxness_run_resume_gate\` with approvalId from pendingApprovals/inspect before advice; never pass runId as approvalId
|
|
179
|
-
- Provider diagnostics: \`vgxness_provider_status\`/\`vgxness_provider_doctor\`
|
|
177
|
+
- Agents/profile/payloads: resolve phase with \`vgxness_agent_resolve\`. Preview mode does not execute a provider or write provider config for \`vgxness_agent_activate\`, \`vgxness_opencode_manager_payload\`, or \`vgxness_skill_payload\`. Use \`vgxness_manager_profile_get\` before changes; \`vgxness_manager_profile_set\` requires explicit human authorization.
|
|
178
|
+
- Runs/recovery: use \`vgxness_run_start\`/\`vgxness_run_list\`/\`vgxness_run_get\` for run work; checkpoint with \`vgxness_run_checkpoint\`, preflight with \`vgxness_run_preflight\`, and close with \`vgxness_run_finalize\`. Unknown runId: \`vgxness_run_resume_candidates\`. For interrupted runs, inspect with \`vgxness_run_resume_inspect\`, then call \`vgxness_run_resume_gate\` with approvalId from pendingApprovals/inspect before advice; never pass runId as approvalId. Follow safe \`recommendedActions[]\`.
|
|
179
|
+
- Provider diagnostics: \`vgxness_provider_status\`/\`vgxness_provider_doctor\` read-only; report \`providerEvidence.evidenceLevel\`/\`hostToolPresenceVerified\` limits.
|
|
180
180
|
|
|
181
181
|
## Minimum flows
|
|
182
182
|
- Simple answer: inline; memory only for prior context; no run by default.
|
|
@@ -196,11 +196,12 @@ Be concise: delegated work, results, files/decisions, evidence/tests, risks, nex
|
|
|
196
196
|
* render baselines, and manager profile overlay baselines; they are
|
|
197
197
|
* intentionally distinct from the provider runtime prompt above.
|
|
198
198
|
*/
|
|
199
|
-
const
|
|
199
|
+
const registryManagerInstructionsV11 = [
|
|
200
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.',
|
|
201
201
|
'Default to delegation for SDD phase-shaped work, repository exploration beyond one narrow lookup, implementation, verification, incident recovery, or multi-step analysis. Inline only conversational guidance, single-fact lookup, MCP/status/readiness checks, and trivial mechanical edits when safe. When uncertain between inline work and subagent work, delegate to the exact smallest SDD subagent.',
|
|
202
202
|
'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.',
|
|
203
203
|
'Check SDD status/next/ready/cockpit, read prerequisites with sdd_get_artifact or sdd_list_artifacts, use public sdd_continue/internal vgxness_sdd_continue first for advisory read-only continuation plans, use sdd_reopen_artifact only for rejected artifacts returning to draft with explicit human actor/audit context, save phase output with sdd_save_artifact only by governance; when proposal is accepted, spec/design/tasks may run sequentially as draft-only autorun without extra confirmation, while acceptance remains human-only. Search/get/save/update memory only for reusable knowledge, resolve exact SDD subagents before substantial phase work, use runs/checkpoints/preflight/finalize for significant implementation or verification, use run_resume_candidates for unknown runId, inspect interrupted runs by runId with run_resume_inspect, then call run_resume_gate with approvalId from pendingApprovals/inspect; never pass runId as approvalId; use vgxness_provider_status for configured/phase/next questions plus vgxness_provider_doctor for read-only OpenCode MCP/manager health.',
|
|
204
|
+
'When sdd_continue/vgxness_sdd_continue returns recommendedActions, prefer the first safe action with agentCallable true and humanOnly false; use targetTool plus suggestedArgs as the starting point, and stop for requiresHumanConfirmation, requiresProviderWriteConsent, requiresPreflight, ambiguous, destructive, privileged, external, or outside-approval actions. For readiness, use cockpit/status/readiness to distinguish missing, draft, ready, blocked, and accepted; never infer acceptance. For provider evidence, report providerEvidence.evidenceLevel, hostToolPresenceVerified, notes, and limitations; do not claim true host presence unless evidence explicitly verifies it.',
|
|
204
205
|
'Prefer payloadMode=compact for manager-facing status/context reads, SDD artifact reads/lists, and activation handoffs so the primary context stays clean; request payloadMode=verbose only when full artifact contents, provider payloads, or skill context are actually needed, preferably inside delegated phase subagents.',
|
|
205
206
|
'MCP sdd_continue must not execute providers, create runs, mutate artifacts, write provider config/openspec, bypass human acceptance, or treat draft-run as apply-progress.',
|
|
206
207
|
'CLI is an escape hatch for bootstrap, doctor, rollback, recovery, MCP unavailable/setup missing, or explicit user request; do not tell users to run terminal SDD phase commands for normal daily flow. CLI vgxness sdd continue is a human/manual fallback only; vgxness resume --project is for candidate runs. The removed experimental vgxness code runtime is not an SDD fallback.',
|
package/dist/cli/cli-flags.js
CHANGED
|
@@ -180,13 +180,13 @@ function skillTargetTypeFlag(flags, name) {
|
|
|
180
180
|
return value;
|
|
181
181
|
return isSkillTargetType(value.value)
|
|
182
182
|
? { ok: true, value: value.value }
|
|
183
|
-
: validationFailure(`--${name} must be agent, subagent, workflow-phase, or
|
|
183
|
+
: validationFailure(`--${name} must be agent, subagent, workflow-phase, provider-adapter, or intent-signal`);
|
|
184
184
|
}
|
|
185
185
|
function optionalSkillTargetTypeFlag(flags, name) {
|
|
186
186
|
const value = optionalStringFlag(flags, name);
|
|
187
187
|
if (value === undefined)
|
|
188
188
|
return { ok: true, value: undefined };
|
|
189
|
-
return isSkillTargetType(value) ? { ok: true, value } : validationFailure(`--${name} must be agent, subagent, workflow-phase, or
|
|
189
|
+
return isSkillTargetType(value) ? { ok: true, value } : validationFailure(`--${name} must be agent, subagent, workflow-phase, provider-adapter, or intent-signal`);
|
|
190
190
|
}
|
|
191
191
|
function skillUsageOutcomeFlag(flags, name) {
|
|
192
192
|
const value = requiredFlag(flags, name);
|
|
@@ -228,7 +228,7 @@ function isSkillEvaluationResultStatus(value) {
|
|
|
228
228
|
return value === 'passed' || value === 'failed' || value === 'needs-review' || value === 'not-applicable';
|
|
229
229
|
}
|
|
230
230
|
function isSkillTargetType(value) {
|
|
231
|
-
return value === 'agent' || value === 'subagent' || value === 'workflow-phase' || value === 'provider-adapter';
|
|
231
|
+
return value === 'agent' || value === 'subagent' || value === 'workflow-phase' || value === 'provider-adapter' || value === 'intent-signal';
|
|
232
232
|
}
|
|
233
233
|
function instructionKindFlag(flags) {
|
|
234
234
|
const value = optionalStringFlag(flags, 'instructions-kind') ?? 'inline';
|
package/dist/cli/cli-help.js
CHANGED
|
@@ -77,12 +77,12 @@ Areas:
|
|
|
77
77
|
skills list [--project <name>] [--scope project|personal]
|
|
78
78
|
skills get --id <id> | --project <name> --name <name> [--scope project|personal]
|
|
79
79
|
skills add-version (--id <id> | --project <name> --name <name>) --version <version> --source-kind path|url|inline [--source-path <path>] [--source-url <url>] [--inline-metadata <json>] [--activate]
|
|
80
|
-
skills attach (--id <id> | --project <name> --name <name>) --target-type agent|subagent|workflow-phase|provider-adapter --target-key <key>
|
|
81
|
-
skills detach (--id <id> | --project <name> --name <name>) --target-type agent|subagent|workflow-phase|provider-adapter --target-key <key>
|
|
80
|
+
skills attach (--id <id> | --project <name> --name <name>) --target-type agent|subagent|workflow-phase|provider-adapter|intent-signal --target-key <key>
|
|
81
|
+
skills detach (--id <id> | --project <name> --name <name>) --target-type agent|subagent|workflow-phase|provider-adapter|intent-signal --target-key <key>
|
|
82
82
|
skills record-usage (--id <id> | --project <name> --name <name>) --outcome selected|injected|helped|failed|neutral [--run-id <id>]
|
|
83
|
-
skills resolve [--agent <name> | --agent-id <id>] [--project <name>] [--workflow <name>] [--phase <name>] [--provider <name>] [--run <id>] [--record-usage selected|injected]
|
|
83
|
+
skills resolve [--agent <name> | --agent-id <id>] [--project <name>] [--workflow <name>] [--phase <name>] [--intent-signals a,b] [--provider <name>] [--run <id>] [--record-usage selected|injected]
|
|
84
84
|
skills status --project <name> [--scope project|personal] [--provider opencode] [--mode agent|subagent] [--agent <name-or-id>]
|
|
85
|
-
skills payload [--agent <name> | --agent-id <id>] [--project <name>] [--workflow <name>] [--phase <name>] [--provider <name>]
|
|
85
|
+
skills payload [--agent <name> | --agent-id <id>] [--project <name>] [--workflow <name>] [--phase <name>] [--intent-signals a,b] [--provider <name>]
|
|
86
86
|
skills propose (--id <id> | --project <name> --name <name>) --proposed-version <version> --source-kind path|url|inline --rationale <text>
|
|
87
87
|
skills proposals [--skill-id <id>] [--status draft|pending-approval|approved|rejected|cancelled|applied]
|
|
88
88
|
skills create-scenario (--id <id> --name <scenario> | --project <name> --name <skill> --scenario-name <scenario>) --criteria <json> --created-by <actor> [--proposal <id>] [--version-id <id>]
|
|
@@ -4,6 +4,7 @@ import { ManagerProfileOverlayService } from '../../agents/manager-profile-overl
|
|
|
4
4
|
import { getProviderRenderer } from '../../agents/renderers/index.js';
|
|
5
5
|
import { ManagerProfileOverlayRepository } from '../../agents/repositories/manager-profile-overlays.js';
|
|
6
6
|
import { createAgentRegistryToolHandlers } from '../../harness/tools/agents.js';
|
|
7
|
+
import { runBootSkillSeed } from '../../skills/boot-seed.js';
|
|
7
8
|
import { SkillRegistryService } from '../../skills/skill-registry-service.js';
|
|
8
9
|
import { SkillStatusService } from '../../skills/skill-status-service.js';
|
|
9
10
|
import { csvFlag, instructionKindFlag, jsonFlag, optionalJsonFlag, optionalModeFlag, optionalScopeFlag, optionalSkillEvaluationResultStatusFlag, optionalSkillImprovementProposalStatusFlag, optionalSkillResolutionUsageFlag, optionalSkillTargetTypeFlag, optionalSkillVersionStatusFlag, optionalStringFlag, requiredFlag, scopeFlag, skillEvaluationResultStatusFlag, skillSourceFromFlags, skillTargetTypeFlag, skillUsageOutcomeFlag, } from '../cli-flags.js';
|
|
@@ -37,6 +38,7 @@ function resolveSkillsInput(flags) {
|
|
|
37
38
|
const agentName = optionalStringFlag(flags, 'agent');
|
|
38
39
|
const workflow = optionalStringFlag(flags, 'workflow');
|
|
39
40
|
const phase = optionalStringFlag(flags, 'phase');
|
|
41
|
+
const intentSignals = csvFlag(flags, 'intent-signals');
|
|
40
42
|
const providerAdapter = optionalStringFlag(flags, 'provider');
|
|
41
43
|
const runId = optionalStringFlag(flags, 'run');
|
|
42
44
|
if (project !== undefined)
|
|
@@ -51,6 +53,8 @@ function resolveSkillsInput(flags) {
|
|
|
51
53
|
input.workflow = workflow;
|
|
52
54
|
if (phase !== undefined)
|
|
53
55
|
input.phase = phase;
|
|
56
|
+
if (intentSignals.length > 0)
|
|
57
|
+
input.intentSignals = intentSignals;
|
|
54
58
|
if (providerAdapter !== undefined)
|
|
55
59
|
input.providerAdapter = providerAdapter;
|
|
56
60
|
if (runId !== undefined)
|
|
@@ -658,7 +662,12 @@ export function runSkillCommand(command, parsed, database, environment) {
|
|
|
658
662
|
}
|
|
659
663
|
if (command === 'payload') {
|
|
660
664
|
const input = skillPayloadInput(parsed.flags);
|
|
661
|
-
|
|
665
|
+
if (!input.ok)
|
|
666
|
+
return resultFailure(input);
|
|
667
|
+
const seeded = runBootSkillSeed(database, environment.env);
|
|
668
|
+
if (!seeded.ok)
|
|
669
|
+
return resultFailure(seeded);
|
|
670
|
+
return jsonResult(registry.buildSkillPayload(input.value, { workspaceRoot: environment.cwd }));
|
|
662
671
|
}
|
|
663
672
|
return usageFailure(`Unknown skills command: ${command}`);
|
|
664
673
|
}
|
|
@@ -11,6 +11,7 @@ import { RunService } from '../runs/run-service.js';
|
|
|
11
11
|
import { sddContinuationPlanFrom } from '../sdd/sdd-continuation-plan.js';
|
|
12
12
|
import { buildSddCockpitSurfaceResponse } from '../sdd/cockpit-read-model.js';
|
|
13
13
|
import { SddWorkflowService } from '../sdd/sdd-workflow-service.js';
|
|
14
|
+
import { runBootSkillSeed } from '../skills/boot-seed.js';
|
|
14
15
|
import { SkillRegistryService } from '../skills/skill-registry-service.js';
|
|
15
16
|
import { VerificationPlanService } from '../verification/index.js';
|
|
16
17
|
import { ProviderChangePlanService } from './provider-change-plan.js';
|
|
@@ -312,6 +313,7 @@ function createServices(database) {
|
|
|
312
313
|
agents,
|
|
313
314
|
managerProfiles,
|
|
314
315
|
skills,
|
|
316
|
+
seedBuiltInSkills: () => runBootSkillSeed(database),
|
|
315
317
|
opencodeManagerPayload,
|
|
316
318
|
opencodeHandoffPreview: new OpenCodeHandoffPreviewService({ managerPayload: opencodeManagerPayload, sdd, providerStatus }),
|
|
317
319
|
activation: new AgentActivationService({ agents, managerProfiles, runs, opencodeManagerPayload }),
|
|
@@ -358,6 +360,9 @@ function memoryContext(sessionId) {
|
|
|
358
360
|
return context;
|
|
359
361
|
}
|
|
360
362
|
function buildSkillPayloadEnvelope(input, services) {
|
|
363
|
+
const seeded = services.seedBuiltInSkills?.();
|
|
364
|
+
if (seeded !== undefined && !seeded.ok)
|
|
365
|
+
return errorEnvelope(seeded.error.code, seeded.error.message, 'vgxness_skill_payload');
|
|
361
366
|
const { workspaceRoot, maxSourceBytes, mode, ...resolverInput } = input;
|
|
362
367
|
const options = { workspaceRoot, ...(maxSourceBytes === undefined ? {} : { maxSourceBytes }), ...(mode === undefined ? {} : { mode }) };
|
|
363
368
|
return toEnvelope('vgxness_skill_payload', services.skills.buildSkillPayload(resolverInput, options));
|
|
@@ -7,7 +7,7 @@ import { inspectClaudeCodeUserMcpConfig } from './claude-code-user-config.js';
|
|
|
7
7
|
import { inspectClaudeUserMemory } from './claude-code-user-memory.js';
|
|
8
8
|
import { vgxnessOpenCodeDefaultAgent, vgxnessOpenCodeSddSubagents } from './opencode-default-agent-config.js';
|
|
9
9
|
import { buildCanonicalAgentManifestDiagnostic } from './provider-canonical-agent-manifest.js';
|
|
10
|
-
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, classifyProviderConfigPaths, providerHealthFailure, providerRuntimeContext, isUserGlobalScope, REQUIRED_PROVIDER_NATIVE_MCP_TOOLS, rollupProviderDoctor, } from './provider-health-types.js';
|
|
10
|
+
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, classifyProviderConfigPaths, providerEvidence, providerHealthFailure, providerRuntimeContext, isUserGlobalScope, REQUIRED_PROVIDER_NATIVE_MCP_TOOLS, rollupProviderDoctor, } from './provider-health-types.js';
|
|
11
11
|
import { inspectOpenCodeConfigPaths } from './provider-status.js';
|
|
12
12
|
export class ProviderDoctorService {
|
|
13
13
|
deps;
|
|
@@ -28,6 +28,7 @@ export class ProviderDoctorService {
|
|
|
28
28
|
const before = snapshotPaths(paths.map((path) => path.path), normalized.workspaceRoot);
|
|
29
29
|
const readableJson = paths.filter((path) => path.parsed);
|
|
30
30
|
const config = readFirstConfig(readableJson[0]?.path);
|
|
31
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: paths.length > 0 });
|
|
31
32
|
const checks = [
|
|
32
33
|
{
|
|
33
34
|
id: 'workspace-root',
|
|
@@ -42,7 +43,7 @@ export class ProviderDoctorService {
|
|
|
42
43
|
subagentsCheck(config),
|
|
43
44
|
delegationCheck(config),
|
|
44
45
|
{ id: 'mcp-current-call', status: 'pass', detail: 'Current MCP call reached the VGXNESS control-plane.' },
|
|
45
|
-
{ id: 'mcp-required-tools', status: 'pass', detail: `
|
|
46
|
+
{ id: 'mcp-required-tools', status: 'pass', detail: `Static VGXNESS manifest expects provider-native tools: ${REQUIRED_PROVIDER_NATIVE_MCP_TOOLS.join(', ')}. MCP host tool presence was not verified.` },
|
|
46
47
|
promptContractCheck(config, normalized.expectedPromptContractVersion),
|
|
47
48
|
readonlySafetyCheck(before, snapshotPaths(paths.map((path) => path.path), normalized.workspaceRoot)),
|
|
48
49
|
];
|
|
@@ -54,8 +55,8 @@ export class ProviderDoctorService {
|
|
|
54
55
|
: paths.filter((path) => path.exists || path.status !== 'not-configured').map((path) => path.path);
|
|
55
56
|
const failedChecks = checks.filter((check) => check.status === 'fail').map((check) => check.id);
|
|
56
57
|
const recommendations = checks.flatMap((check) => (check.remediation === undefined ? [] : [check.remediation]));
|
|
57
|
-
const originalBytes = Buffer.byteLength(JSON.stringify({ checks, checkedPaths: paths.map((path) => path.path) }), 'utf8');
|
|
58
|
-
const compactBytes = Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths }), 'utf8');
|
|
58
|
+
const originalBytes = Buffer.byteLength(JSON.stringify({ checks, checkedPaths: paths.map((path) => path.path), providerEvidence: evidence }), 'utf8');
|
|
59
|
+
const compactBytes = Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths, providerEvidence: evidence }), 'utf8');
|
|
59
60
|
return {
|
|
60
61
|
ok: true,
|
|
61
62
|
value: {
|
|
@@ -80,6 +81,7 @@ export class ProviderDoctorService {
|
|
|
80
81
|
recommendations,
|
|
81
82
|
checks: compactChecksValue,
|
|
82
83
|
checkedPaths,
|
|
84
|
+
providerEvidence: evidence,
|
|
83
85
|
bytes: { originalBytes, compactBytes },
|
|
84
86
|
verboseAvailable: normalized.payloadMode === 'compact',
|
|
85
87
|
fullContentRef: `provider-doctor:${normalized.providerAdapter}:${normalized.workspaceRoot}`,
|
|
@@ -99,6 +101,7 @@ export class ProviderDoctorService {
|
|
|
99
101
|
const projectMemory = inspectClaudeProjectMemory(normalized.workspaceRoot);
|
|
100
102
|
const advisoryPaths = claudeAdvisoryPaths(normalized.workspaceRoot);
|
|
101
103
|
const checkedPathList = [mcp.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), projectMemory.path, ...advisoryPaths];
|
|
104
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: checkedPathList.length > 0 });
|
|
102
105
|
const before = snapshotPaths(checkedPathList, normalized.workspaceRoot);
|
|
103
106
|
const missingAgents = agents.agents.filter((agent) => agent.status === 'missing');
|
|
104
107
|
const blockingAgents = agents.agents.filter((agent) => agent.status === 'conflicting' || agent.status === 'invalid');
|
|
@@ -133,13 +136,14 @@ export class ProviderDoctorService {
|
|
|
133
136
|
const checkedPaths = normalized.payloadMode === 'verbose' ? checkedPathList : checkedPathList.filter((path) => existsSync(path) || path === mcp.path);
|
|
134
137
|
const failedChecks = checks.filter((check) => check.status === 'fail').map((check) => check.id);
|
|
135
138
|
const recommendations = checks.flatMap((check) => (check.remediation === undefined ? [] : [check.remediation]));
|
|
136
|
-
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, runtimeContext: providerRuntimeContext(normalized), configClassification: externalProjectClassification(checkedPathList), status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: summarizeDoctor(status, failedChecks.length, recommendations.length), recommendations, checks: compactChecksValue, checkedPaths, bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: checkedPathList }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: PROVIDER_HEALTH_SAFETY } };
|
|
139
|
+
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, runtimeContext: providerRuntimeContext(normalized), configClassification: externalProjectClassification(checkedPathList), status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: summarizeDoctor(status, failedChecks.length, recommendations.length), recommendations, checks: compactChecksValue, checkedPaths, providerEvidence: evidence, bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: checkedPathList, providerEvidence: evidence }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths, providerEvidence: evidence }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: PROVIDER_HEALTH_SAFETY } };
|
|
137
140
|
}
|
|
138
141
|
getClaudeUserGlobalDoctor(normalized, canonicalScope = 'user', scopeWarnings = []) {
|
|
139
142
|
const mcp = inspectClaudeCodeUserMcpConfig(normalized.env);
|
|
140
143
|
const agents = inspectClaudeCodeAgents({ workspaceRoot: normalized.workspaceRoot, scope: 'user', env: normalized.env });
|
|
141
144
|
const userMemory = inspectClaudeUserMemory(normalized.env);
|
|
142
145
|
const checkedPathList = [mcp.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), userMemory.path];
|
|
146
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: checkedPathList.length > 0 });
|
|
143
147
|
const before = snapshotPaths(checkedPathList, normalized.workspaceRoot);
|
|
144
148
|
const missingAgents = agents.agents.filter((agent) => agent.status === 'missing');
|
|
145
149
|
const blockingAgents = agents.agents.filter((agent) => agent.status === 'conflicting' || agent.status === 'invalid');
|
|
@@ -164,7 +168,7 @@ export class ProviderDoctorService {
|
|
|
164
168
|
const failedChecks = checks.filter((check) => check.status === 'fail').map((check) => check.id);
|
|
165
169
|
const recommendations = checks.flatMap((check) => (check.remediation === undefined ? [] : [check.remediation]));
|
|
166
170
|
const checkedPaths = normalized.payloadMode === 'verbose' ? checkedPathList : checkedPathList.filter((path) => existsSync(path) || path === mcp.path || path === userMemory.path);
|
|
167
|
-
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, runtimeContext: providerRuntimeContext(normalized), configClassification: managedUserGlobalClassification(checkedPathList), status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: summarizeDoctor(status, failedChecks.length, recommendations.length), recommendations, checks: compactChecksValue, checkedPaths, bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: checkedPathList }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${canonicalScope}:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES } } };
|
|
171
|
+
return { ok: true, value: { version: 1, kind: 'provider-doctor', project: normalized.project, providerAdapter: 'claude', scope: normalized.scope, workspaceRoot: normalized.workspaceRoot, runtimeContext: providerRuntimeContext(normalized), configClassification: managedUserGlobalClassification(checkedPathList), status, payloadMode: normalized.payloadMode, overallStatus: status, checkCount: checks.length, passedCount: checks.filter((check) => check.status === 'pass').length, warningCount: checks.filter((check) => check.status === 'warn' || check.status === 'not-configured').length, errorCount: failedChecks.length, skippedCount: checks.filter((check) => check.status === 'skip').length, failedChecks, summary: summarizeDoctor(status, failedChecks.length, recommendations.length), recommendations, checks: compactChecksValue, checkedPaths, providerEvidence: evidence, bytes: { originalBytes: Buffer.byteLength(JSON.stringify({ checks, checkedPaths: checkedPathList, providerEvidence: evidence }), 'utf8'), compactBytes: Buffer.byteLength(JSON.stringify({ checks: compactChecksValue, checkedPaths, providerEvidence: evidence }), 'utf8') }, verboseAvailable: normalized.payloadMode === 'compact', fullContentRef: `provider-doctor:claude:${canonicalScope}:${normalized.workspaceRoot}`, generatedAt: 'read-only-snapshot', safety: { ...PROVIDER_HEALTH_SAFETY, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES } } };
|
|
168
172
|
}
|
|
169
173
|
}
|
|
170
174
|
function externalProjectClassification(paths) {
|
|
@@ -34,6 +34,26 @@ export function classifyProviderConfigPaths(paths) {
|
|
|
34
34
|
detectedExternalUserConfig: paths.filter((path) => path.diagnostics.ownership === 'external-user' && path.exists).map((path) => path.path),
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
export function providerEvidence(input) {
|
|
38
|
+
const hostIntrospectionAvailable = input.hostIntrospectionAvailable ?? false;
|
|
39
|
+
const hostToolPresenceVerified = input.hostToolPresenceVerified ?? false;
|
|
40
|
+
return {
|
|
41
|
+
staticManifestKnown: input.staticManifestKnown,
|
|
42
|
+
renderedConfigExpected: input.renderedConfigExpected,
|
|
43
|
+
configPathInspected: input.configPathInspected,
|
|
44
|
+
hostIntrospectionAvailable,
|
|
45
|
+
hostToolPresenceVerified,
|
|
46
|
+
evidenceLevel: hostIntrospectionAvailable ? 'host-introspection' : input.configPathInspected ? 'config-inspection' : 'static-manifest',
|
|
47
|
+
notes: [
|
|
48
|
+
'VGXNESS inspected static provider manifests and expected provider configuration metadata only.',
|
|
49
|
+
input.configPathInspected
|
|
50
|
+
? 'VGXNESS inspected provider config paths as read-only diagnostics.'
|
|
51
|
+
: 'VGXNESS did not inspect provider config paths; evidence is limited to static manifests.',
|
|
52
|
+
'No provider host process was launched during this diagnostic.',
|
|
53
|
+
'MCP host tool presence is not verified by provider status/doctor.',
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
37
57
|
export const REQUIRED_PROVIDER_MCP_TOOLS = ['vgxness_provider_status', 'vgxness_provider_doctor', 'vgxness_provider_change_plan'];
|
|
38
58
|
export const REQUIRED_PROVIDER_NATIVE_MCP_TOOLS = [
|
|
39
59
|
'vgxness_provider_status',
|
|
@@ -9,7 +9,7 @@ import { inspectClaudeUserMemory } from './claude-code-user-memory.js';
|
|
|
9
9
|
import { resolveOpenCodeMcpInstallTarget } from './client-install-opencode-contract.js';
|
|
10
10
|
import { vgxnessOpenCodeDefaultAgent, vgxnessOpenCodePromptContractVersion, vgxnessOpenCodeSddSubagents } from './opencode-default-agent-config.js';
|
|
11
11
|
import { buildCanonicalAgentManifestDiagnostic } from './provider-canonical-agent-manifest.js';
|
|
12
|
-
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, classifyProviderConfigPaths, providerConfigPathDiagnostics, providerRuntimeContext, providerHealthFailure, isUserGlobalScope, REQUIRED_PROVIDER_MCP_TOOLS, rollupProviderHealth, } from './provider-health-types.js';
|
|
12
|
+
import { normalizeProviderHealthInput, PROVIDER_HEALTH_SAFETY, CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, classifyProviderConfigPaths, providerConfigPathDiagnostics, providerRuntimeContext, providerEvidence, providerHealthFailure, isUserGlobalScope, REQUIRED_PROVIDER_MCP_TOOLS, rollupProviderHealth, } from './provider-health-types.js';
|
|
13
13
|
const projectConfigTargets = ['.opencode/opencode.json', 'opencode.json', '.opencode/opencode.jsonc', 'opencode.jsonc'];
|
|
14
14
|
export class ProviderStatusService {
|
|
15
15
|
deps;
|
|
@@ -29,6 +29,7 @@ export class ProviderStatusService {
|
|
|
29
29
|
const managerConfigured = hasConfiguredManager(providerConfig);
|
|
30
30
|
const subagentsConfigured = hasConfiguredSubagents(providerConfig);
|
|
31
31
|
const tools = requiredToolPresence();
|
|
32
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: paths.length > 0 });
|
|
32
33
|
const configStatus = resolveConfigStatus(paths, mcpEntry, managerConfigured, subagentsConfigured);
|
|
33
34
|
const status = rollupProviderHealth([canonicalAgentManifest.status, configStatus, ...tools.map((tool) => (tool.present ? 'pass' : 'fail'))]);
|
|
34
35
|
const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
|
|
@@ -39,12 +40,14 @@ export class ProviderStatusService {
|
|
|
39
40
|
const verboseShape = {
|
|
40
41
|
config: { status: configStatus, paths, mcpEntry },
|
|
41
42
|
canonicalAgentManifest,
|
|
43
|
+
providerEvidence: evidence,
|
|
42
44
|
sdd,
|
|
43
45
|
mcpRequiredTools: tools,
|
|
44
46
|
};
|
|
45
47
|
const compactShape = {
|
|
46
48
|
config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') },
|
|
47
49
|
canonicalAgentManifest,
|
|
50
|
+
providerEvidence: evidence,
|
|
48
51
|
sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'),
|
|
49
52
|
mcpRequiredTools: tools,
|
|
50
53
|
};
|
|
@@ -70,6 +73,7 @@ export class ProviderStatusService {
|
|
|
70
73
|
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
71
74
|
checkedPaths,
|
|
72
75
|
canonicalAgentManifest,
|
|
76
|
+
providerEvidence: evidence,
|
|
73
77
|
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
74
78
|
mcpRequiredTools: tools,
|
|
75
79
|
originalBytes,
|
|
@@ -112,8 +116,9 @@ export class ProviderStatusService {
|
|
|
112
116
|
const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
|
|
113
117
|
const checkedPaths = normalized.payloadMode === 'verbose' ? [mcpState.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), projectMemory.path, ...claudeAdvisoryPaths(normalized.workspaceRoot)] : [mcpState.path, projectMemory.path, ...agents.agents.filter((agent) => agent.exists || agent.status !== 'missing').map((agent) => agent.path), ...advisory];
|
|
114
118
|
const tools = [...requiredToolPresence(), { tool: 'claude-cli', present: false, diagnostic: 'Read-only status does not execute `claude --version`; CLI presence is checked during explicit apply/preflight only.' }];
|
|
115
|
-
const
|
|
116
|
-
const
|
|
119
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: paths.length > 0 });
|
|
120
|
+
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, providerEvidence: evidence, agents, projectMemory, advisory, sdd, mcpRequiredTools: tools };
|
|
121
|
+
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, providerEvidence: evidence, agentSummary: summarizeClaudeAgents(agents), projectMemory: { status: projectMemory.status, action: projectMemory.action }, advisory, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
117
122
|
const originalBytes = Buffer.byteLength(JSON.stringify(verboseShape), 'utf8');
|
|
118
123
|
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
119
124
|
const issueCount = [canonicalAgentManifest.status, configStatus, ...agentStatuses].filter((item) => item === 'fail' || item === 'not-configured').length;
|
|
@@ -136,6 +141,7 @@ export class ProviderStatusService {
|
|
|
136
141
|
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
137
142
|
checkedPaths,
|
|
138
143
|
canonicalAgentManifest,
|
|
144
|
+
providerEvidence: evidence,
|
|
139
145
|
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
140
146
|
mcpRequiredTools: tools,
|
|
141
147
|
originalBytes,
|
|
@@ -163,11 +169,12 @@ export class ProviderStatusService {
|
|
|
163
169
|
const agentStatuses = agents.agents.map((agent) => (agent.status === 'managed' ? 'pass' : agent.status === 'missing' ? 'not-configured' : 'fail'));
|
|
164
170
|
const configStatus = claudeConfigHealthStatus([...paths.map((path) => path.status), ...agentStatuses]);
|
|
165
171
|
const tools = [...requiredToolPresence(), { tool: 'claude-cli', present: false, diagnostic: 'Read-only status does not execute `claude --version`; no Claude Code process was launched.' }];
|
|
172
|
+
const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: paths.length > 0 });
|
|
166
173
|
const status = rollupProviderHealth([canonicalAgentManifest.status, configStatus]);
|
|
167
174
|
const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
|
|
168
175
|
const checkedPaths = normalized.payloadMode === 'verbose' ? [mcpState.path, agents.directoryPath, ...agents.agents.map((agent) => agent.path), userMemory.path] : [mcpState.path, userMemory.path, ...agents.agents.filter((agent) => agent.exists || agent.status !== 'missing').map((agent) => agent.path)];
|
|
169
|
-
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, agents, userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, scopeWarnings, sdd, mcpRequiredTools: tools };
|
|
170
|
-
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, agentSummary: summarizeClaudeAgents(agents), userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
176
|
+
const verboseShape = { config: { status: configStatus, paths, mcpEntry }, canonicalAgentManifest, providerEvidence: evidence, agents, userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, scopeWarnings, sdd, mcpRequiredTools: tools };
|
|
177
|
+
const compactShape = { config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') }, canonicalAgentManifest, providerEvidence: evidence, agentSummary: summarizeClaudeAgents(agents), userMemory: { status: userMemory.status, action: userMemory.action }, scopeCapabilities: CLAUDE_USER_GLOBAL_SCOPE_CAPABILITIES, sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'), mcpRequiredTools: tools };
|
|
171
178
|
const originalBytes = Buffer.byteLength(JSON.stringify(verboseShape), 'utf8');
|
|
172
179
|
const compactBytes = Buffer.byteLength(JSON.stringify(compactShape), 'utf8');
|
|
173
180
|
const reportBase = {
|
|
@@ -188,6 +195,7 @@ export class ProviderStatusService {
|
|
|
188
195
|
nextAction: nextActionFor(status, mcpEntry, sdd?.next),
|
|
189
196
|
checkedPaths,
|
|
190
197
|
canonicalAgentManifest,
|
|
198
|
+
providerEvidence: evidence,
|
|
191
199
|
...(sdd === undefined ? {} : { sdd: compactSdd(sdd, normalized.payloadMode) }),
|
|
192
200
|
mcpRequiredTools: tools,
|
|
193
201
|
originalBytes,
|
|
@@ -335,7 +343,11 @@ function inspectOpenCodeMcpEntry(paths) {
|
|
|
335
343
|
}
|
|
336
344
|
}
|
|
337
345
|
function requiredToolPresence() {
|
|
338
|
-
return REQUIRED_PROVIDER_MCP_TOOLS.map((tool) => ({
|
|
346
|
+
return REQUIRED_PROVIDER_MCP_TOOLS.map((tool) => ({
|
|
347
|
+
tool,
|
|
348
|
+
present: true,
|
|
349
|
+
diagnostic: 'Static VGXNESS manifest expects this MCP tool; provider host tool presence was not verified.',
|
|
350
|
+
}));
|
|
339
351
|
}
|
|
340
352
|
function resolveConfigStatus(paths, mcpEntry, managerConfigured, subagentsConfigured) {
|
|
341
353
|
if (paths.some((path) => path.status === 'fail') || mcpEntry.status === 'fail')
|
package/dist/mcp/schema.js
CHANGED
|
@@ -109,7 +109,125 @@ const contextCockpitLevels = ['compact', 'expanded', 'verbose'];
|
|
|
109
109
|
const providerChangePlanProviders = ['opencode', 'claude', 'antigravity', 'custom'];
|
|
110
110
|
const providerChangePlanTypes = ['opencode-mcp-install', 'claude-mcp-install', 'setup', 'install', 'config-preparation'];
|
|
111
111
|
const sddPhaseInputSchema = z.union([z.enum(sddPhases), z.literal('apply')]);
|
|
112
|
+
const sddPhaseSchema = z.enum(sddPhases);
|
|
112
113
|
const jsonValueSchema = z.lazy(() => z.union([z.string(), z.number().finite(), z.boolean(), z.null(), z.array(jsonValueSchema), z.record(z.string(), jsonValueSchema)]));
|
|
114
|
+
const providerEvidenceOutputSchema = z
|
|
115
|
+
.object({
|
|
116
|
+
staticManifestKnown: z.boolean(),
|
|
117
|
+
renderedConfigExpected: z.boolean(),
|
|
118
|
+
configPathInspected: z.boolean(),
|
|
119
|
+
hostIntrospectionAvailable: z.boolean(),
|
|
120
|
+
hostToolPresenceVerified: z.boolean(),
|
|
121
|
+
evidenceLevel: z.enum(['static-manifest', 'config-inspection', 'host-introspection']),
|
|
122
|
+
notes: z.array(z.string()),
|
|
123
|
+
})
|
|
124
|
+
.passthrough();
|
|
125
|
+
const sddPhaseGateOutputSchema = z
|
|
126
|
+
.object({
|
|
127
|
+
phase: sddPhaseSchema,
|
|
128
|
+
topicKey: z.string(),
|
|
129
|
+
artifactPresent: z.boolean(),
|
|
130
|
+
artifactStatus: z.enum(['missing', 'draft', 'accepted', 'rejected', 'superseded']),
|
|
131
|
+
artifactState: z.enum(['missing', 'draft', 'accepted', 'rejected', 'superseded', 'legacy']),
|
|
132
|
+
accepted: z.boolean(),
|
|
133
|
+
acceptedByHuman: z.boolean(),
|
|
134
|
+
agentCallable: z.boolean(),
|
|
135
|
+
requiresHumanAcceptance: z.boolean(),
|
|
136
|
+
draftPresent: z.boolean(),
|
|
137
|
+
contentFrozen: z.boolean(),
|
|
138
|
+
runnable: z.boolean(),
|
|
139
|
+
blocked: z.boolean(),
|
|
140
|
+
blockedReasons: z.array(z.string()),
|
|
141
|
+
humanOnly: z.boolean(),
|
|
142
|
+
preflightRequired: z.boolean(),
|
|
143
|
+
requiresPreflight: z.boolean(),
|
|
144
|
+
requiresProviderWriteConsent: z.boolean(),
|
|
145
|
+
canDraft: z.boolean(),
|
|
146
|
+
canMarkReady: z.boolean(),
|
|
147
|
+
canAccept: z.boolean(),
|
|
148
|
+
canReopen: z.boolean(),
|
|
149
|
+
nextAllowedActions: z.array(z.string()),
|
|
150
|
+
requiredPriorPhase: sddPhaseSchema.optional(),
|
|
151
|
+
blockerReason: z.enum(['missing', 'draft', 'accepted', 'legacy', 'rejected', 'superseded']).optional(),
|
|
152
|
+
})
|
|
153
|
+
.passthrough();
|
|
154
|
+
const sddReadinessGatesOutputSchema = z
|
|
155
|
+
.object({
|
|
156
|
+
phase: sddPhaseGateOutputSchema,
|
|
157
|
+
prerequisites: z.array(sddPhaseGateOutputSchema),
|
|
158
|
+
runnable: z.boolean(),
|
|
159
|
+
blocked: z.boolean(),
|
|
160
|
+
blockedReasons: z.array(z.string()),
|
|
161
|
+
humanOnly: z.boolean(),
|
|
162
|
+
preflightRequired: z.boolean(),
|
|
163
|
+
agentCallable: z.boolean(),
|
|
164
|
+
canDraft: z.boolean(),
|
|
165
|
+
canMarkReady: z.boolean(),
|
|
166
|
+
canAccept: z.boolean(),
|
|
167
|
+
canReopen: z.boolean(),
|
|
168
|
+
nextAllowedActions: z.array(z.string()),
|
|
169
|
+
requiresProviderWriteConsent: z.boolean(),
|
|
170
|
+
})
|
|
171
|
+
.passthrough();
|
|
172
|
+
const sddCockpitGatesOutputSchema = z
|
|
173
|
+
.object({
|
|
174
|
+
phases: z.array(sddPhaseGateOutputSchema),
|
|
175
|
+
changeComplete: z.boolean(),
|
|
176
|
+
nextPhase: sddPhaseSchema.optional(),
|
|
177
|
+
nextPhaseRunnable: z.boolean(),
|
|
178
|
+
runnableNextPhases: z.array(sddPhaseSchema),
|
|
179
|
+
blockedTransitions: z.array(sddPhaseGateOutputSchema),
|
|
180
|
+
blockedReasons: z.array(z.string()),
|
|
181
|
+
requiresHumanAcceptance: z.boolean(),
|
|
182
|
+
humanOnly: z.boolean(),
|
|
183
|
+
preflightRequired: z.boolean(),
|
|
184
|
+
agentCallable: z.boolean(),
|
|
185
|
+
canDraft: z.boolean(),
|
|
186
|
+
canMarkReady: z.boolean(),
|
|
187
|
+
canAccept: z.boolean(),
|
|
188
|
+
canReopen: z.boolean(),
|
|
189
|
+
nextAllowedActions: z.array(z.string()),
|
|
190
|
+
requiresProviderWriteConsent: z.boolean(),
|
|
191
|
+
})
|
|
192
|
+
.passthrough();
|
|
193
|
+
const sddRecommendedActionOutputSchema = z
|
|
194
|
+
.object({
|
|
195
|
+
id: z.string(),
|
|
196
|
+
label: z.string(),
|
|
197
|
+
title: z.string(),
|
|
198
|
+
description: z.string(),
|
|
199
|
+
kind: z.enum(['inspect', 'draft-phase', 'mark-ready', 'accept-human', 'reopen-human']),
|
|
200
|
+
category: z.enum(['inspection', 'sdd-phase', 'human-governance']),
|
|
201
|
+
phase: sddPhaseSchema.optional(),
|
|
202
|
+
targetTool: z.string(),
|
|
203
|
+
suggestedArgs: z.record(z.string(), jsonValueSchema),
|
|
204
|
+
readOnly: z.boolean(),
|
|
205
|
+
mutating: z.boolean(),
|
|
206
|
+
agentCallable: z.boolean(),
|
|
207
|
+
humanOnly: z.boolean(),
|
|
208
|
+
requiresHumanApproval: z.boolean(),
|
|
209
|
+
requiresHumanConfirmation: z.boolean(),
|
|
210
|
+
requiresPreflight: z.boolean(),
|
|
211
|
+
requiresProviderWriteConsent: z.boolean(),
|
|
212
|
+
reason: z.string(),
|
|
213
|
+
rationale: z.string(),
|
|
214
|
+
blockingPrerequisites: z.array(z
|
|
215
|
+
.object({
|
|
216
|
+
phase: sddPhaseSchema,
|
|
217
|
+
topicKey: z.string(),
|
|
218
|
+
reason: z.string(),
|
|
219
|
+
artifactId: z.string().optional(),
|
|
220
|
+
})
|
|
221
|
+
.passthrough()),
|
|
222
|
+
})
|
|
223
|
+
.passthrough();
|
|
224
|
+
const mcpSuccessOutputSchema = (value) => z
|
|
225
|
+
.object({
|
|
226
|
+
ok: z.literal(true),
|
|
227
|
+
tool: z.enum(SUPPORTED_VGX_MCP_TOOL_NAMES),
|
|
228
|
+
value,
|
|
229
|
+
})
|
|
230
|
+
.passthrough();
|
|
113
231
|
export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
114
232
|
vgxness_sdd_status: z
|
|
115
233
|
.object({
|
|
@@ -351,6 +469,7 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
351
469
|
agentName: z.string().min(1).optional(),
|
|
352
470
|
workflow: z.string().min(1).optional(),
|
|
353
471
|
phase: z.string().min(1).optional(),
|
|
472
|
+
intentSignals: z.array(z.string().min(1)).optional(),
|
|
354
473
|
providerAdapter: z.string().min(1).optional(),
|
|
355
474
|
runId: z.string().min(1).optional(),
|
|
356
475
|
mode: z.enum(payloadModes).optional(),
|
|
@@ -503,6 +622,64 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
|
|
|
503
622
|
})
|
|
504
623
|
.passthrough(),
|
|
505
624
|
};
|
|
625
|
+
export const VGX_MCP_TOOL_OUTPUT_SCHEMAS = {
|
|
626
|
+
vgxness_sdd_ready: mcpSuccessOutputSchema(z
|
|
627
|
+
.object({
|
|
628
|
+
change: z.string(),
|
|
629
|
+
phase: sddPhaseSchema,
|
|
630
|
+
ready: z.boolean(),
|
|
631
|
+
gates: sddReadinessGatesOutputSchema.optional(),
|
|
632
|
+
})
|
|
633
|
+
.passthrough()),
|
|
634
|
+
vgxness_sdd_get_readiness: mcpSuccessOutputSchema(z
|
|
635
|
+
.object({
|
|
636
|
+
change: z.string(),
|
|
637
|
+
phase: sddPhaseSchema,
|
|
638
|
+
ready: z.boolean(),
|
|
639
|
+
gates: sddReadinessGatesOutputSchema.optional(),
|
|
640
|
+
})
|
|
641
|
+
.passthrough()),
|
|
642
|
+
vgxness_sdd_cockpit: mcpSuccessOutputSchema(z
|
|
643
|
+
.object({
|
|
644
|
+
project: z.string(),
|
|
645
|
+
change: z.string(),
|
|
646
|
+
gates: sddCockpitGatesOutputSchema.optional(),
|
|
647
|
+
readModel: z
|
|
648
|
+
.object({
|
|
649
|
+
project: z.string(),
|
|
650
|
+
change: z.string(),
|
|
651
|
+
gates: sddCockpitGatesOutputSchema.optional(),
|
|
652
|
+
phases: z.array(z
|
|
653
|
+
.object({
|
|
654
|
+
phase: sddPhaseSchema,
|
|
655
|
+
gates: sddPhaseGateOutputSchema.optional(),
|
|
656
|
+
})
|
|
657
|
+
.passthrough()),
|
|
658
|
+
})
|
|
659
|
+
.passthrough(),
|
|
660
|
+
})
|
|
661
|
+
.passthrough()),
|
|
662
|
+
vgxness_sdd_continue: mcpSuccessOutputSchema(z
|
|
663
|
+
.object({
|
|
664
|
+
kind: z.literal('sdd-continuation-plan'),
|
|
665
|
+
project: z.string(),
|
|
666
|
+
change: z.string(),
|
|
667
|
+
recommendedActions: z.array(sddRecommendedActionOutputSchema),
|
|
668
|
+
})
|
|
669
|
+
.passthrough()),
|
|
670
|
+
vgxness_provider_status: mcpSuccessOutputSchema(z
|
|
671
|
+
.object({
|
|
672
|
+
kind: z.literal('provider-status'),
|
|
673
|
+
providerEvidence: providerEvidenceOutputSchema,
|
|
674
|
+
})
|
|
675
|
+
.passthrough()),
|
|
676
|
+
vgxness_provider_doctor: mcpSuccessOutputSchema(z
|
|
677
|
+
.object({
|
|
678
|
+
kind: z.literal('provider-doctor'),
|
|
679
|
+
providerEvidence: providerEvidenceOutputSchema,
|
|
680
|
+
})
|
|
681
|
+
.passthrough()),
|
|
682
|
+
};
|
|
506
683
|
export function successEnvelope(tool, value) {
|
|
507
684
|
return { ok: true, tool, value };
|
|
508
685
|
}
|