vgxness 1.20.1 → 1.20.2

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.
@@ -168,7 +168,7 @@ Coordinate SDD; keep chat thin, use VGXNESS MCP state, delegate to exact SDD sub
168
168
  - Before phase advancement, call \`vgxness_sdd_status\`/\`vgxness_sdd_next\` plus \`vgxness_sdd_ready\` or \`vgxness_sdd_get_readiness\`.
169
169
  - 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 when available. Stop on approval/block; never invent approval.
170
170
  - Direct human acceptance via \`vgxness_sdd_accept_artifact\` is not a generic SDD write: do not preflight solely for it; require exact project/change/phase, \`acceptedBy.type\` \`"human"\`, non-empty \`acceptedBy.id\`, and eligible status/readiness. Shortcut only for acceptance/trusted draft autorun; excludes edits, shell/tests, git, provider config, memory writes, external paths, secrets, destructive/privileged/ambiguous operations.
171
- - manager native repo tools are disabled in config (read/glob/edit/write/bash); report config-level enforcement, not proof of host runtime behavior. Subagents keep phase tools.
171
+ - bounded read/search repo tools may be enabled for inspection; bash, edit, and write remain denied. Diagnostics are config-level evidence, not host runtime proof.
172
172
  - Do not mutate provider/global OpenCode config. 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.
173
173
  - Do not change provider model/reasoning config unless explicitly requested.
174
174
 
@@ -137,7 +137,7 @@ function openCodeManagerPermissionsFor(agent) {
137
137
  ...openCodePermissionsFor(agent, { task: createCanonicalOpenCodeSddTaskPermissions() }),
138
138
  bash: 'deny',
139
139
  edit: 'deny',
140
- read: 'deny',
140
+ read: 'allow',
141
141
  write: 'deny',
142
142
  };
143
143
  }
@@ -148,9 +148,9 @@ function openCodeManagerTools() {
148
148
  delegation_list: true,
149
149
  delegation_read: true,
150
150
  edit: false,
151
- glob: false,
152
- grep: false,
153
- read: false,
151
+ glob: true,
152
+ grep: true,
153
+ read: true,
154
154
  write: false,
155
155
  };
156
156
  }
@@ -15,7 +15,7 @@ const openCodeCapabilities = {
15
15
  'instructions',
16
16
  'mode',
17
17
  'adapter model',
18
- 'adapter config keys: variant, temperature, top_p, hidden, options, color, steps, permission',
18
+ 'adapter config keys: variant, temperature, top_p, hidden, options, color, steps, permission, tools',
19
19
  ],
20
20
  skillInjectionModes: ['external preview services may inject skill payloads before rendering; renderer does not resolve skills'],
21
21
  permissionCategories: ['registry permission metadata mapped from adapter permission config'],
@@ -78,6 +78,7 @@ function openCodeAgentConfig(agent) {
78
78
  copyString(config, rendered, 'color');
79
79
  copyNumber(config, rendered, 'steps');
80
80
  copyJson(config, rendered, 'permission');
81
+ copyJson(config, rendered, 'tools');
81
82
  return rendered;
82
83
  }
83
84
  function copyString(source, target, key) {
@@ -197,7 +197,11 @@ function warningsForScope(scope, overwriteVgxness, agentPlan, bashPermissionPoli
197
197
  `Reinstall/overwrite is enabled: existing VGXNESS-managed OpenCode entries will be replaced (${agentPlan.installsAgents ? 'mcp.vgxness, default_agent, instructions AGENTS.md, and known VGXNESS agents' : 'mcp.vgxness only'}); unrelated OpenCode config is preserved.`,
198
198
  ]
199
199
  : [];
200
- const bashWarnings = bashPermissionPolicy.manager === 'deny' ? ['OpenCode top-level permission.bash is set to ask; the VGXNESS manager agent denies bash while SDD subagents keep explicit phase permissions.'] : ['OpenCode top-level permission.bash is set to ask.'];
200
+ const bashWarnings = bashPermissionPolicy.manager === 'deny'
201
+ ? [
202
+ 'OpenCode config sets top-level permission.bash = ask; manager read/search discovery tools (read/glob/grep) are allowed while manager bash/edit/write are denied; SDD subagents keep explicit phase permissions. This is config-level evidence only and does not verify provider runtime enforcement.',
203
+ ]
204
+ : ['OpenCode top-level permission.bash is set to ask.'];
201
205
  return [
202
206
  'Restart OpenCode after installation so it reloads the user MCP config.',
203
207
  'OpenCode project config may override user config for a workspace; check project-level config if vgxness is not visible.',
@@ -214,7 +214,10 @@ function confirmationRequiredMessage(scope) {
214
214
  return `\`mcp install opencode\` requires explicit --yes before any ${scope} config write.`;
215
215
  }
216
216
  function warnings() {
217
- return ['Restart OpenCode after installation so it reloads the project MCP config.', 'OpenCode top-level permission.bash is set to ask; the VGXNESS manager agent denies bash while SDD subagents keep explicit phase permissions.'];
217
+ return [
218
+ 'Restart OpenCode after installation so it reloads the project MCP config.',
219
+ 'OpenCode config sets top-level permission.bash = ask; manager read/search discovery tools (read/glob/grep) are allowed while manager bash/edit/write are denied; SDD subagents keep explicit phase permissions. This is config-level evidence only and does not verify provider runtime enforcement.',
220
+ ];
218
221
  }
219
222
  function manualTest(databasePath, source) {
220
223
  return {
@@ -40,6 +40,7 @@ export class ProviderDoctorService {
40
40
  configReadableCheck(readableJson.length, paths.filter((path) => path.exists).length),
41
41
  mcpEntryCheck(config),
42
42
  defaultAgentCheck(config),
43
+ managerNativeCapabilityCheck(config),
43
44
  subagentsCheck(config),
44
45
  delegationCheck(config),
45
46
  { id: 'mcp-current-call', status: 'pass', detail: 'Current MCP call reached the VGXNESS control-plane.' },
@@ -255,6 +256,35 @@ function defaultAgentCheck(config) {
255
256
  return { id: 'opencode-default-agent', status: 'fail', detail: 'OpenCode default_agent is not vgxness-manager or the manager config is missing.' };
256
257
  return { id: 'opencode-default-agent', status: 'pass', detail: 'OpenCode default agent points to vgxness-manager.' };
257
258
  }
259
+ function managerNativeCapabilityCheck(config) {
260
+ const manager = isRecord(config?.agent) && isRecord(config.agent[vgxnessOpenCodeDefaultAgent]) ? config.agent[vgxnessOpenCodeDefaultAgent] : undefined;
261
+ const permission = isRecord(manager?.permission) ? manager.permission : undefined;
262
+ const tools = isRecord(manager?.tools) ? manager.tools : undefined;
263
+ const problems = [];
264
+ if (permission?.read !== 'allow')
265
+ problems.push('permission.read is not allow');
266
+ for (const tool of ['read', 'glob', 'grep']) {
267
+ if (tools?.[tool] !== true)
268
+ problems.push(`tools.${tool} is not enabled`);
269
+ }
270
+ for (const tool of ['bash', 'edit', 'write']) {
271
+ if (tools?.[tool] !== false)
272
+ problems.push(`tools.${tool} is not disabled`);
273
+ }
274
+ const evidenceSuffix = 'This is config-level evidence only; host runtime/tool presence is not verified.';
275
+ if (problems.length > 0)
276
+ return {
277
+ id: 'opencode-manager-native-capability',
278
+ status: 'fail',
279
+ detail: `Manager native capability drift detected: ${problems.join('; ')}. ${evidenceSuffix}`,
280
+ remediation: 'Re-run explicit OpenCode setup/install only after reviewing provider config drift; doctor does not auto-repair or write config.',
281
+ };
282
+ return {
283
+ id: 'opencode-manager-native-capability',
284
+ status: 'pass',
285
+ detail: `Manager config allows read/glob/grep inspection and denies bash/edit/write native tools. ${evidenceSuffix}`,
286
+ };
287
+ }
258
288
  function subagentsCheck(config) {
259
289
  const agents = isRecord(config?.agent) ? config.agent : undefined;
260
290
  const missing = vgxnessOpenCodeSddSubagents.filter((name) => !isRecord(agents?.[name]) || agents[name]?.hidden !== true);
@@ -27,10 +27,11 @@ export class ProviderStatusService {
27
27
  const mcpEntry = inspectOpenCodeMcpEntry(paths);
28
28
  const providerConfig = readFirstParsedConfig(paths);
29
29
  const managerConfigured = hasConfiguredManager(providerConfig);
30
+ const managerNativeCapabilityStatus = inspectManagerNativeCapability(providerConfig);
30
31
  const subagentsConfigured = hasConfiguredSubagents(providerConfig);
31
32
  const tools = requiredToolPresence();
32
33
  const evidence = providerEvidence({ staticManifestKnown: true, renderedConfigExpected: true, configPathInspected: paths.length > 0 });
33
- const configStatus = resolveConfigStatus(paths, mcpEntry, managerConfigured, subagentsConfigured);
34
+ const configStatus = resolveConfigStatus(paths, mcpEntry, managerConfigured, managerNativeCapabilityStatus, subagentsConfigured);
34
35
  const status = rollupProviderHealth([canonicalAgentManifest.status, configStatus, ...tools.map((tool) => (tool.present ? 'pass' : 'fail'))]);
35
36
  const sdd = normalized.change.length > 0 ? this.readSdd(normalized.project, normalized.change) : undefined;
36
37
  const generatedAt = 'read-only-snapshot';
@@ -38,14 +39,14 @@ export class ProviderStatusService {
38
39
  ? paths.map((path) => path.path)
39
40
  : paths.filter((path) => path.exists || path.status !== 'not-configured').map((path) => path.path);
40
41
  const verboseShape = {
41
- config: { status: configStatus, paths, mcpEntry },
42
+ config: { status: configStatus, paths, mcpEntry, managerNativeCapability: managerNativeCapabilityStatus },
42
43
  canonicalAgentManifest,
43
44
  providerEvidence: evidence,
44
45
  sdd,
45
46
  mcpRequiredTools: tools,
46
47
  };
47
48
  const compactShape = {
48
- config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') },
49
+ config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact'), managerNativeCapability: managerNativeCapabilityStatus },
49
50
  canonicalAgentManifest,
50
51
  providerEvidence: evidence,
51
52
  sdd: sdd === undefined ? undefined : compactSdd(sdd, 'compact'),
@@ -86,8 +87,8 @@ export class ProviderStatusService {
86
87
  return {
87
88
  ok: true,
88
89
  value: normalized.payloadMode === 'verbose'
89
- ? { ...reportBase, payloadMode: 'verbose', config: { status: configStatus, paths: compactPaths(paths, 'verbose'), mcpEntry: compactMcpEntry(mcpEntry, 'verbose') } }
90
- : { ...reportBase, payloadMode: 'compact', config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact') } },
90
+ ? { ...reportBase, payloadMode: 'verbose', config: { status: configStatus, paths: compactPaths(paths, 'verbose'), mcpEntry: compactMcpEntry(mcpEntry, 'verbose'), managerNativeCapability: managerNativeCapabilityStatus } }
91
+ : { ...reportBase, payloadMode: 'compact', config: { status: configStatus, paths: compactPaths(paths, 'compact'), mcpEntry: compactMcpEntry(mcpEntry, 'compact'), managerNativeCapability: managerNativeCapabilityStatus } },
91
92
  };
92
93
  }
93
94
  readSdd(project, change) {
@@ -393,12 +394,12 @@ function requiredToolPresence() {
393
394
  diagnostic: 'Static VGXNESS manifest expects this MCP tool; provider host tool presence was not verified.',
394
395
  }));
395
396
  }
396
- function resolveConfigStatus(paths, mcpEntry, managerConfigured, subagentsConfigured) {
397
+ function resolveConfigStatus(paths, mcpEntry, managerConfigured, managerNativeCapabilityStatus, subagentsConfigured) {
397
398
  if (paths.some((path) => path.status === 'fail') || mcpEntry.status === 'fail')
398
399
  return 'fail';
399
400
  if (mcpEntry.status === 'not-configured')
400
401
  return 'not-configured';
401
- if (!managerConfigured || !subagentsConfigured)
402
+ if (!managerConfigured || managerNativeCapabilityStatus === 'warn' || !subagentsConfigured)
402
403
  return 'warn';
403
404
  if (hasProjectConfigAlongsideUser(paths))
404
405
  return 'warn';
@@ -449,6 +450,17 @@ function hasConfiguredManager(config) {
449
450
  isRecord(agent?.[vgxnessOpenCodeDefaultAgent]) &&
450
451
  promptContractVersion(agent[vgxnessOpenCodeDefaultAgent]) === vgxnessOpenCodePromptContractVersion);
451
452
  }
453
+ function inspectManagerNativeCapability(config) {
454
+ if (config === undefined)
455
+ return 'not-configured';
456
+ const agent = isRecord(config.agent) ? config.agent : undefined;
457
+ const manager = isRecord(agent?.[vgxnessOpenCodeDefaultAgent]) ? agent[vgxnessOpenCodeDefaultAgent] : undefined;
458
+ const permission = isRecord(manager?.permission) ? manager.permission : undefined;
459
+ const tools = isRecord(manager?.tools) ? manager.tools : undefined;
460
+ const readSearchEnabled = permission?.read === 'allow' && tools?.read === true && tools.glob === true && tools.grep === true;
461
+ const writeShellDenied = tools?.bash === false && tools.edit === false && tools.write === false;
462
+ return readSearchEnabled && writeShellDenied ? 'pass' : 'warn';
463
+ }
452
464
  function hasConfiguredSubagents(config) {
453
465
  if (config === undefined)
454
466
  return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vgxness",
3
- "version": "1.20.1",
3
+ "version": "1.20.2",
4
4
  "description": "CLI and MCP control plane for guided AI-agent workflows, SDD, memory, and OpenCode setup.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {