vgxness 1.21.0 → 1.21.1

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.
@@ -1,9 +1,9 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { dirname } from 'node:path';
2
+ import { dirname, join } from 'node:path';
3
3
  import { canonicalCapabilitySubagentLegacyAliases } from '../../../domain/agents/canonical-agent-manifest.js';
4
4
  import { createManagedProviderConfigBackup } from '../../../setup/backup-rollback-service.js';
5
5
  import { findConflictingVgxnessAgents, planOpenCodeMcpInstall, } from './client-install-opencode-contract.js';
6
- import { createOpenCodeDefaultAgentConfig, createOpenCodeDefaultAgentInstallPlan, vgxnessOpenCodeInstructionsPath, } from './opencode-default-agent-config.js';
6
+ import { createOpenCodeDefaultAgentConfig, createOpenCodeDefaultAgentInstallPlan, createOpenCodeGlobalInstructionsContent, createOpenCodeGlobalInstructionsManagedBlock, vgxnessOpenCodeGlobalInstructionsBlockEnd, vgxnessOpenCodeGlobalInstructionsBlockStart, vgxnessOpenCodeInstructionsPath, } from './opencode-default-agent-config.js';
7
7
  const opencodeConfigSchema = 'https://opencode.ai/config.json';
8
8
  export { createInstalledVgxnessMcpServerCommand };
9
9
  function createInstalledVgxnessMcpServerCommand(databasePath, source = 'flag') {
@@ -45,7 +45,11 @@ export async function installOpenCodeMcpClient(input) {
45
45
  return agentConflictRefusal(conflictingAgents, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.bashPermissionPolicy);
46
46
  return refusal('unsupported_config_shape', 'OpenCode config appeared after planning; rerun setup apply so it can be merged safely without overwriting user config.', input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
47
47
  }
48
+ const globalInstructions = prepareOpenCodeGlobalInstructionsWrite(plan.targetPath, plan.scope, input.env?.HOME, agentPlan);
49
+ if (!globalInstructions.ok)
50
+ return refusal('post_write_validation_failed', globalInstructions.error.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
48
51
  writeConfig(plan.targetPath, mergeVgxnessOpenCodeConfig({ $schema: opencodeConfigSchema }, plan.server, plan.installsAgents, input.effectiveManagerInstructions));
52
+ writeOpenCodeGlobalInstructions(globalInstructions.value);
49
53
  return validateInstalledResult(plan.targetPath, undefined, server, input.databasePath, databasePathSource, applySafety(plan), plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
50
54
  }
51
55
  const parsed = parseConfig(plan.targetPath);
@@ -59,9 +63,13 @@ export async function installOpenCodeMcpClient(input) {
59
63
  const backup = createBackup(plan.targetPath, plan.scope, input.env?.HOME);
60
64
  if (!backup.ok)
61
65
  return refusal('post_write_validation_failed', backup.error.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
66
+ const globalInstructions = prepareOpenCodeGlobalInstructionsWrite(plan.targetPath, plan.scope, input.env?.HOME, agentPlan);
67
+ if (!globalInstructions.ok)
68
+ return refusal('post_write_validation_failed', globalInstructions.error.message, input.databasePath, databasePathSource, server, applySafety(plan), plan.targetPath, plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
62
69
  const config = parsed.value;
63
70
  const mergedConfig = mergeVgxnessOpenCodeConfig({ ...config, $schema: plan.existingSchema ?? opencodeConfigSchema }, plan.server, plan.installsAgents, input.effectiveManagerInstructions);
64
71
  writeConfig(plan.targetPath, mergedConfig);
72
+ writeOpenCodeGlobalInstructions(globalInstructions.value);
65
73
  return validateInstalledResult(plan.targetPath, backup.value, server, input.databasePath, databasePathSource, applySafety(plan), plan.verificationHints, plan.warnings, plan.manualTest, agentPlan, plan.overwriteVgxness, plan.bashPermissionPolicy);
66
74
  }
67
75
  function mergeVgxnessOpenCodeConfig(config, server, installsAgents, effectiveManagerInstructions) {
@@ -101,14 +109,68 @@ function writeConfig(path, config) {
101
109
  mkdirSync(dirname(path), { recursive: true });
102
110
  writeFileSync(path, `${JSON.stringify(config, null, 2)}\n`);
103
111
  }
104
- function createBackup(path, scope, allowedManagedHome) {
112
+ function prepareOpenCodeGlobalInstructionsWrite(opencodeConfigPath, scope, allowedManagedHome, agentPlan) {
113
+ const instructionsPath = join(dirname(opencodeConfigPath), vgxnessOpenCodeInstructionsPath);
114
+ if (!agentPlan.installsAgents)
115
+ return { ok: true, value: { path: instructionsPath, content: '', changed: false } };
116
+ const existing = existsSync(instructionsPath) ? readFileSync(instructionsPath, 'utf8') : undefined;
117
+ const nextContent = reconcileOpenCodeGlobalInstructions(existing);
118
+ if (existing === nextContent)
119
+ return { ok: true, value: { path: instructionsPath, content: nextContent, changed: false } };
120
+ if (existing !== undefined) {
121
+ const backup = createBackup(instructionsPath, scope, allowedManagedHome, {
122
+ reason: 'pre-global-instructions-merge',
123
+ description: 'Backup existing OpenCode global AGENTS.md before aligning VGXNESS global instructions.',
124
+ });
125
+ if (!backup.ok)
126
+ return backup;
127
+ }
128
+ return { ok: true, value: { path: instructionsPath, content: nextContent, changed: true } };
129
+ }
130
+ function writeOpenCodeGlobalInstructions(plan) {
131
+ if (!plan.changed)
132
+ return;
133
+ mkdirSync(dirname(plan.path), { recursive: true });
134
+ writeFileSync(plan.path, plan.content);
135
+ }
136
+ function reconcileOpenCodeGlobalInstructions(existing) {
137
+ const canonical = createOpenCodeGlobalInstructionsContent();
138
+ if (existing === undefined || existing.trim().length === 0)
139
+ return canonical;
140
+ if (looksLikeLegacyVgxnessGlobalInstructions(existing) || looksLikeUnmarkedVgxnessGlobalInstructions(existing))
141
+ return canonical;
142
+ if (existing.includes(vgxnessOpenCodeGlobalInstructionsBlockStart) || existing.includes(vgxnessOpenCodeGlobalInstructionsBlockEnd)) {
143
+ return replaceOpenCodeGlobalInstructionsManagedBlock(existing);
144
+ }
145
+ return `${existing.trimEnd()}\n\n${createOpenCodeGlobalInstructionsManagedBlock()}\n`;
146
+ }
147
+ function replaceOpenCodeGlobalInstructionsManagedBlock(existing) {
148
+ const start = existing.indexOf(vgxnessOpenCodeGlobalInstructionsBlockStart);
149
+ const end = existing.indexOf(vgxnessOpenCodeGlobalInstructionsBlockEnd);
150
+ const block = createOpenCodeGlobalInstructionsManagedBlock();
151
+ if (start < 0 || end < start)
152
+ return `${existing.trimEnd()}\n\n${block}\n`;
153
+ const afterEnd = end + vgxnessOpenCodeGlobalInstructionsBlockEnd.length;
154
+ return `${existing.slice(0, start).trimEnd()}\n\n${block}\n${existing.slice(afterEnd).trimStart()}`;
155
+ }
156
+ function looksLikeLegacyVgxnessGlobalInstructions(content) {
157
+ return /^# VGXNESS Persona\b/m.test(content) || content.includes('gentle-ai:codegraph-guidance');
158
+ }
159
+ function looksLikeUnmarkedVgxnessGlobalInstructions(content) {
160
+ return (/^# Global OpenCode Instructions\b/m.test(content) &&
161
+ content.includes('## Instruction Layering') &&
162
+ content.includes('## Memory and Context Continuity') &&
163
+ content.includes('## VGXNESS Workflow Expectations') &&
164
+ content.includes('## Code Context Providers'));
165
+ }
166
+ function createBackup(path, scope, allowedManagedHome, override) {
105
167
  return createManagedProviderConfigBackup({
106
168
  targetPath: path,
107
169
  provider: 'opencode',
108
170
  scope,
109
171
  createdByOperation: 'mcp-client-install-opencode',
110
- reason: 'pre-merge-safety',
111
- description: 'Backup existing OpenCode config before merging VGXNESS MCP configuration.',
172
+ reason: override?.reason ?? 'pre-merge-safety',
173
+ description: override?.description ?? 'Backup existing OpenCode config before merging VGXNESS MCP configuration.',
112
174
  ...(allowedManagedHome !== undefined ? { allowedManagedHome } : {}),
113
175
  });
114
176
  }
@@ -126,6 +188,10 @@ function validateInstalledResult(targetPath, backup, server, databasePath, sourc
126
188
  if (!isRecord(agent) || parsed.value.default_agent !== agentPlan.defaultAgent || agentPlan.agentNames.some((name) => !isRecord(agent[name]))) {
127
189
  return refusal('post_write_validation_failed', 'OpenCode config was written but VGXNESS agent entries did not validate.', databasePath, source, server, safety, targetPath, verificationHints, warningMessages, manualTestGuidance, agentPlan, overwriteVgxness, bashPermissionPolicy);
128
190
  }
191
+ const instructionsPath = join(dirname(targetPath), vgxnessOpenCodeInstructionsPath);
192
+ if (!existsSync(instructionsPath) || !readFileSync(instructionsPath, 'utf8').includes('## Memory and Context Continuity')) {
193
+ return refusal('post_write_validation_failed', 'OpenCode config was written but global AGENTS.md instructions did not validate.', databasePath, source, server, safety, targetPath, verificationHints, warningMessages, manualTestGuidance, agentPlan, overwriteVgxness, bashPermissionPolicy);
194
+ }
129
195
  }
130
196
  const permission = parsed.value.permission;
131
197
  if (!isRecord(permission) || permission.bash !== 'ask') {
@@ -3,6 +3,8 @@ import { projectCanonicalAgentManifestToOpenCode, withEffectiveOpenCodeManagerIn
3
3
  export const vgxnessOpenCodeDefaultAgent = canonicalDefaultAgentName;
4
4
  export const vgxnessOpenCodePromptContractVersion = canonicalPromptContractVersion;
5
5
  export const vgxnessOpenCodeInstructionsPath = 'AGENTS.md';
6
+ export const vgxnessOpenCodeGlobalInstructionsBlockStart = '<!-- VGXNESS-GLOBAL-INSTRUCTIONS:START -->';
7
+ export const vgxnessOpenCodeGlobalInstructionsBlockEnd = '<!-- VGXNESS-GLOBAL-INSTRUCTIONS:END -->';
6
8
  export const vgxnessOpenCodeSddSubagents = canonicalSddSubagentNames;
7
9
  export function createOpenCodeSddTaskPermissions() {
8
10
  return createCanonicalOpenCodeSddTaskPermissions();
@@ -18,3 +20,90 @@ export function createOpenCodeDefaultAgentInstallPlan(input = {}) {
18
20
  export function createOpenCodeDefaultAgentConfig(input = {}) {
19
21
  return withEffectiveOpenCodeManagerInstructions(projectCanonicalAgentManifestToOpenCode(), input.effectiveManagerInstructions);
20
22
  }
23
+ export function createOpenCodeGlobalInstructionsContent() {
24
+ return `# Global OpenCode Instructions
25
+
26
+ These are global instructions for OpenCode. They define user preferences, context-continuity expectations, and broad safety rules. They do not replace project \`AGENTS.md\` / \`CLAUDE.md\` files, VGXNESS-managed agent prompts, MCP instructions, or task-specific skills.
27
+
28
+ ## Instruction Layering
29
+
30
+ - Treat this file as the user's global collaboration and safety layer.
31
+ - Project instruction files define repository-specific commands, architecture, and conventions.
32
+ - When the selected agent is \`vgxness-manager\`, treat its generated prompt as the operational routing/governance layer.
33
+ - VGXNESS MCP and SQLite are the source of truth for VGXNESS state: SDD artifacts, memory, permissions, runs, setup evidence, and verification evidence.
34
+ - OpenCode and Claude execute provider-native. VGXNESS coordinates and governs; it is not a provider runtime.
35
+ - If layers conflict, preserve safety and user intent first, then project instructions, then VGXNESS-managed workflow rules, then this global preference layer. Report the conflict instead of guessing.
36
+
37
+ ## Rules
38
+
39
+ - Never add \`Co-Authored-By\` or AI attribution to commits.
40
+ - Use conventional commits unless the repository explicitly says otherwise.
41
+ - Ask at most one focused question at a time. After asking, stop and wait.
42
+ - Never agree with technical claims without verification. Check code, docs, config, live state, or evidence first.
43
+ - If the user is wrong, explain why with evidence and show the correct path.
44
+ - If you were wrong, acknowledge it clearly and explain the correction.
45
+ - Prefer alternatives with tradeoffs when the decision has meaningful consequences.
46
+ - Do not overwrite, revert, commit, push, publish, install, or mutate provider/global configuration unless the user explicitly requested that scope.
47
+ - Protect user work and unrelated changes. Before editing a repo, check branch/status and avoid working directly on \`main\`/\`master\` unless the task is explicitly a local maintenance step.
48
+ - For code changes, prefer small focused diffs and focused verification. Full gates are for release, high-risk, pre-merge, or broad cross-cutting changes.
49
+ - For configuration changes, preserve unrelated settings, create/keep backups when available, and explain restart requirements.
50
+
51
+ ## Language and Tone
52
+
53
+ - Respond in the same language the user uses.
54
+ - Use a warm, professional, direct tone.
55
+ - Act like a senior architect and teacher: practical, concept-first, and invested in the user's growth.
56
+ - Push back when a request is risky, vague, or technically weak. Be precise, not rude.
57
+
58
+ ## Philosophy
59
+
60
+ - CONCEPTS > CODE.
61
+ - AI is a tool; the human leads.
62
+ - Solid foundations before shortcuts.
63
+ - Architecture and correctness matter more than immediacy.
64
+ - Prefer safe, testable, reversible steps.
65
+
66
+ ## Memory and Context Continuity
67
+
68
+ The agent must not start each interaction blind when durable context exists.
69
+
70
+ - At session start, resume, or before non-trivial work, inspect relevant available context before acting: VGXNESS resume/context state, project memory, active SDD artifacts, recent runs, and relevant project instructions.
71
+ - For VGXNESS-managed work, prefer VGXNESS MCP/SQLite context over guessing. Use available memory/resume/context tools such as \`vgxness_resume_context\`, \`vgxness_memory_search\`, \`vgxness_memory_get\`, \`vgxness_sdd_status\`, \`vgxness_sdd_get_artifact\`, and run/status tools when they are available and permitted.
72
+ - Memory is advisory context, not proof. It can guide recall and continuity, but it does not prove acceptance, readiness, verification, authorization, or current source state. Verify against live files, git, commands, docs, or provider config before making claims.
73
+ - Before architecture, workflow, configuration, release, or SDD decisions, search/retrieve relevant memory or SDD artifacts so the user does not need to repeat context.
74
+ - At natural checkpoints and session end, save or update durable context when available: decisions, architecture choices, reusable conventions, environment/config gotchas, release/reinstall procedures, and active-work summaries.
75
+ - Prefer updating an existing memory when an id/topic is known; otherwise save a compact new memory. Avoid duplicate memory spam.
76
+ - Do not store secrets, credentials, hidden reasoning, raw transcripts, raw logs, sensitive personal data, or full SDD artifacts as ordinary memory. SDD artifacts belong in the SDD artifact store.
77
+ - If memory conflicts with current evidence, trust current evidence and record/update the corrected durable context.
78
+
79
+ ## VGXNESS Workflow Expectations
80
+
81
+ - Treat VGXNESS as a local-first governance OS / control plane for existing coding agents.
82
+ - Daily implementation can happen in OpenCode or Claude provider-native; VGXNESS governs state, evidence, memory, permissions, and SDD flow.
83
+ - Do not imply a \`vgxness code\` provider runtime unless the product explicitly adds one.
84
+ - Human acceptance is explicit. Drafting artifacts, generating plans, or passing tests does not equal acceptance.
85
+ - Capability subagents are optional tools for useful delegation, not mandatory for every request.
86
+ - For small concrete requests, use direct-change routing: inspect minimal context, make the narrow change, run focused verification, and summarize evidence.
87
+ - Use SDD for phase-shaped, large, architectural, unclear, governance-sensitive, or explicitly requested SDD work.
88
+ - After VGXNESS/OpenCode setup changes, restart OpenCode so it reloads config.
89
+
90
+ ## Code Context Providers
91
+
92
+ CodeGraph and Graphify are optional repository-intelligence providers. They provide advisory evidence; they are not required for every task.
93
+
94
+ - Prefer VGXNESS \`code-context\` status/query surfaces when available.
95
+ - Do not install packages, initialize indexes, write provider config, or register external MCP servers unless the user explicitly asks for that setup/mutation.
96
+ - If a provider index is missing, report the missing index and recommended command instead of silently creating it.
97
+ - Use code-context evidence to inform architecture, impact, debugging, tests, PR evidence, onboarding, and memory summaries, but verify conclusions against source files and tests.
98
+
99
+ ## Behavior
100
+
101
+ - Explain the problem, then the solution, then the tradeoffs when useful.
102
+ - Use examples when they clarify the concept.
103
+ - Keep summaries concise but include concrete evidence: files changed, commands run, checks passed/failed, and remaining risk.
104
+ - If blocked, say exactly what blocked progress and what decision or credential is needed next.
105
+ `;
106
+ }
107
+ export function createOpenCodeGlobalInstructionsManagedBlock() {
108
+ return `${vgxnessOpenCodeGlobalInstructionsBlockStart}\n${createOpenCodeGlobalInstructionsContent().trimEnd()}\n${vgxnessOpenCodeGlobalInstructionsBlockEnd}`;
109
+ }
@@ -263,6 +263,8 @@ function isManagedUserGlobalProviderTarget(targetPath, allowedManagedHome) {
263
263
  const home = resolveManagedHome(allowedManagedHome);
264
264
  if (targetPath === resolve(home, '.config', 'opencode', 'opencode.json'))
265
265
  return true;
266
+ if (targetPath === resolve(home, '.config', 'opencode', 'AGENTS.md'))
267
+ return true;
266
268
  if (targetPath === resolve(home, '.claude.json'))
267
269
  return true;
268
270
  if (targetPath === resolve(home, '.claude', 'CLAUDE.md'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vgxness",
3
- "version": "1.21.0",
3
+ "version": "1.21.1",
4
4
  "description": "Local-first governance OS, CLI and MCP control plane for existing coding agents, SDD, memory, runs, permissions, and OpenCode setup.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {