vgxness 1.9.1 → 1.9.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.
@@ -62,7 +62,7 @@ export async function installClaudeCodeMcpClient(input) {
62
62
  if (!mcpWrite.ok)
63
63
  return refusal('post_write_validation_failed', mcpWrite.error.message, plan, server, writtenPaths, backups);
64
64
  writtenPaths.push(mcpWrite.value);
65
- for (const agent of expectedClaudeCodeRenderedAgents(input.cwd)) {
65
+ for (const agent of expectedClaudeCodeRenderedAgents(input.cwd, { effectiveManagerInstructions: input.effectiveManagerInstructions })) {
66
66
  const target = plan.targets.find((item) => item.kind === 'agent-file' && item.path === agent.path);
67
67
  if (target?.action !== 'create' && target?.action !== 'update-vgxness')
68
68
  continue;
@@ -140,7 +140,7 @@ async function applyUserInstall(input, plan, server, writtenPaths, backups) {
140
140
  if (!mcpWrite.ok)
141
141
  return refusal('post_write_validation_failed', mcpWrite.error.message, plan, server, writtenPaths, backups);
142
142
  writtenPaths.push(mcpWrite.value);
143
- for (const agent of expectedClaudeCodeRenderedUserAgents(input.cwd, input.env)) {
143
+ for (const agent of expectedClaudeCodeRenderedUserAgents(input.cwd, input.env, { effectiveManagerInstructions: input.effectiveManagerInstructions })) {
144
144
  const target = plan.targets.find((item) => item.kind === 'agent-file' && item.path === agent.path);
145
145
  if (target?.action !== 'create' && target?.action !== 'update-vgxness')
146
146
  continue;
@@ -32,7 +32,9 @@ export function callVgxTool(call, services) {
32
32
  case 'vgxness_sdd_save_artifact':
33
33
  return auditedEnvelope(validated.tool, services.sdd.saveArtifact(validated.input), services, sddSaveAuditPayload(validated.input));
34
34
  case 'vgxness_sdd_accept_artifact':
35
- return auditedEnvelope(validated.tool, services.sdd.acceptArtifact(toAcceptArtifactServiceInput(validated.input)), services, sddAcceptanceAuditPayload(validated.input));
35
+ return auditedEnvelope(validated.tool, services.sdd.acceptArtifact(validated.input), services, sddAcceptanceAuditPayload(validated.input));
36
+ case 'vgxness_sdd_reopen_artifact':
37
+ return auditedEnvelope(validated.tool, services.sdd.reopenArtifact(validated.input), services, sddReopenAuditPayload(validated.input));
36
38
  case 'vgxness_sdd_get_artifact':
37
39
  return toEnvelope(validated.tool, services.sdd.getArtifact(validated.input));
38
40
  case 'vgxness_sdd_list_artifacts':
@@ -117,10 +119,6 @@ export function callVgxTool(call, services) {
117
119
  }
118
120
  return errorEnvelope('validation_failed', 'Tool dispatch is not implemented');
119
121
  }
120
- function toAcceptArtifactServiceInput(input) {
121
- const note = input.note ?? input.notes ?? input.rationale;
122
- return note === undefined ? input : { ...input, note };
123
- }
124
122
  function auditedEnvelope(tool, result, services, audit) {
125
123
  if (result.ok && audit.runId !== undefined) {
126
124
  services.runs.appendEvent({
@@ -171,6 +169,24 @@ function sddAcceptanceAuditPayload(input) {
171
169
  }),
172
170
  };
173
171
  }
172
+ function sddReopenAuditPayload(input) {
173
+ return {
174
+ runId: input.runId,
175
+ title: 'Audit: sdd-artifact-reopened',
176
+ relatedType: 'sdd-artifact',
177
+ relatedId: `${input.change}:${input.phase}`,
178
+ payload: (value) => ({
179
+ eventType: 'sdd-artifact-reopened',
180
+ project: input.project,
181
+ change: input.change,
182
+ phase: input.phase,
183
+ topicKey: value.topicKey,
184
+ artifactId: value.id,
185
+ reopenedBy: { type: 'human', id: input.reopenedBy.id },
186
+ ...(input.agentId === undefined ? {} : { agentId: input.agentId }),
187
+ }),
188
+ };
189
+ }
174
190
  function sddSaveAuditPayload(input) {
175
191
  return {
176
192
  runId: input.runId,
@@ -237,6 +253,7 @@ export function createVgxMcpControlPlane(options = {}) {
237
253
  let closed = false;
238
254
  return {
239
255
  callVgxTool: (tool, input) => callVgxTool({ tool, input }, services),
256
+ database,
240
257
  close: () => {
241
258
  if (closed)
242
259
  return;
@@ -221,16 +221,12 @@ function claudeProjectMemoryPathStatus(state) {
221
221
  function compactPaths(paths, mode) {
222
222
  if (mode === 'verbose')
223
223
  return paths;
224
- return paths.map((path) => path.status === 'pass'
225
- ? { ...path, detail: `${path.label}: pass` }
226
- : path.status === 'not-configured'
227
- ? { ...path, detail: `${path.label}: not configured` }
228
- : path);
224
+ return paths.map((path) => ({ label: path.label, path: path.path, status: path.status }));
229
225
  }
230
226
  function compactMcpEntry(entry, mode) {
231
- if (mode === 'verbose' || entry.status !== 'pass')
227
+ if (mode === 'verbose')
232
228
  return entry;
233
- return { ...entry, detail: 'MCP server entry found.' };
229
+ return { configured: entry.configured, status: entry.status, serverName: entry.serverName };
234
230
  }
235
231
  function compactSdd(sdd, mode) {
236
232
  if (mode === 'verbose')
@@ -9,6 +9,7 @@ export const SUPPORTED_VGX_MCP_TOOL_NAMES = [
9
9
  'vgxness_sdd_get_readiness',
10
10
  'vgxness_sdd_save_artifact',
11
11
  'vgxness_sdd_accept_artifact',
12
+ 'vgxness_sdd_reopen_artifact',
12
13
  'vgxness_sdd_get_artifact',
13
14
  'vgxness_sdd_list_artifacts',
14
15
  'vgxness_sdd_next',
@@ -49,6 +50,7 @@ export const EXPOSED_VGX_MCP_TOOL_NAMES = [
49
50
  'sdd_get_readiness',
50
51
  'sdd_save_artifact',
51
52
  'sdd_accept_artifact',
53
+ 'sdd_reopen_artifact',
52
54
  'sdd_get_artifact',
53
55
  'sdd_list_artifacts',
54
56
  'sdd_next',
@@ -148,8 +150,22 @@ export const VGX_MCP_TOOL_INPUT_SCHEMAS = {
148
150
  }),
149
151
  acceptedAt: z.string().min(1).optional(),
150
152
  note: z.string().min(1).optional(),
151
- notes: z.string().min(1).optional(),
152
- rationale: z.string().min(1).optional(),
153
+ runId: z.string().min(1).optional(),
154
+ agentId: z.string().min(1).optional(),
155
+ })
156
+ .passthrough(),
157
+ vgxness_sdd_reopen_artifact: z
158
+ .object({
159
+ project: z.string().min(1),
160
+ change: z.string().min(1),
161
+ phase: z.enum(sddPhases),
162
+ reopenedBy: z.object({
163
+ type: z.literal('human'),
164
+ id: z.string().min(1),
165
+ displayName: z.string().min(1).optional(),
166
+ }),
167
+ reopenedAt: z.string().min(1).optional(),
168
+ note: z.string().min(1).optional(),
153
169
  runId: z.string().min(1).optional(),
154
170
  agentId: z.string().min(1).optional(),
155
171
  })
@@ -1,9 +1,11 @@
1
1
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { runBootAgentSeedUpgrade } from '../agents/boot-upgrade.js';
3
4
  import { createVgxMcpControlPlane } from './control-plane.js';
4
5
  import { EXPOSED_VGX_MCP_TOOL_NAMES, toInternalVgxMcpToolName, VGX_MCP_TOOL_INPUT_SCHEMAS, } from './schema.js';
5
6
  export async function startVgxMcpStdioServer(options = {}) {
6
7
  const controlPlane = createVgxMcpControlPlane(options.databasePath === undefined ? {} : { databasePath: options.databasePath });
8
+ runBootAgentSeedUpgrade(controlPlane.database);
7
9
  const mcpServer = new McpServer({ name: 'vgxness', version: '0.1.0' });
8
10
  const transport = new StdioServerTransport();
9
11
  let closed = false;
@@ -42,6 +42,8 @@ export function validateVgxMcpToolCall(call) {
42
42
  return validationSuccess(tool.value, validateSddSaveArtifactInput(input, tool.value));
43
43
  case 'vgxness_sdd_accept_artifact':
44
44
  return validationSuccess(tool.value, validateSddAcceptArtifactInput(input, tool.value));
45
+ case 'vgxness_sdd_reopen_artifact':
46
+ return validationSuccess(tool.value, validateSddReopenArtifactInput(input, tool.value));
45
47
  case 'vgxness_sdd_get_artifact':
46
48
  return validationSuccess(tool.value, validateSddGetArtifactInput(input, tool.value));
47
49
  case 'vgxness_sdd_list_artifacts':
@@ -312,7 +314,7 @@ function validateSddSaveArtifactInput(input, tool) {
312
314
  return { ok: true, value: { ...base.value, phase: phase.value, content: content.value } };
313
315
  }
314
316
  function validateSddAcceptArtifactInput(input, tool) {
315
- const record = inputRecord(input, tool, ['project', 'change', 'phase', 'acceptedBy', 'acceptedAt', 'note', 'notes', 'rationale', 'runId', 'agentId']);
317
+ const record = inputRecord(input, tool, ['project', 'change', 'phase', 'acceptedBy', 'acceptedAt', 'note', 'runId', 'agentId']);
316
318
  if (!record.ok)
317
319
  return record;
318
320
  const base = readProjectAndChange(record.value, tool);
@@ -340,7 +342,41 @@ function validateSddAcceptArtifactInput(input, tool) {
340
342
  if (displayName.value !== undefined)
341
343
  acceptedBy.displayName = displayName.value;
342
344
  const result = { ...base.value, phase: phase.value, acceptedBy };
343
- const copied = copyOptionalLimitedStrings(result, record.value, tool, ['acceptedAt', 'note', 'notes', 'rationale', 'runId', 'agentId'], undefined);
345
+ const copied = copyOptionalLimitedStrings(result, record.value, tool, ['acceptedAt', 'note', 'runId', 'agentId'], undefined);
346
+ if (!copied.ok)
347
+ return copied;
348
+ return { ok: true, value: result };
349
+ }
350
+ function validateSddReopenArtifactInput(input, tool) {
351
+ const record = inputRecord(input, tool, ['project', 'change', 'phase', 'reopenedBy', 'reopenedAt', 'note', 'runId', 'agentId']);
352
+ if (!record.ok)
353
+ return record;
354
+ const base = readProjectAndChange(record.value, tool);
355
+ if (!base.ok)
356
+ return base;
357
+ const phase = readPhase(record.value, tool);
358
+ if (!phase.ok)
359
+ return phase;
360
+ const reopenedByRecord = asRecord(record.value.reopenedBy, tool, 'reopenedBy is required');
361
+ if (!reopenedByRecord.ok)
362
+ return reopenedByRecord;
363
+ const reopenedByExtra = Object.keys(reopenedByRecord.value).find((key) => !['type', 'id', 'displayName'].includes(key));
364
+ if (reopenedByExtra !== undefined)
365
+ return validationFailure(`Unexpected field: reopenedBy.${reopenedByExtra}`, tool);
366
+ const type = readRequiredOneOf(reopenedByRecord.value, 'type', ['human'], tool);
367
+ if (!type.ok)
368
+ return type;
369
+ const id = readNonEmptyString(reopenedByRecord.value, 'id', tool);
370
+ if (!id.ok)
371
+ return id;
372
+ const displayName = readOptionalNonEmptyString(reopenedByRecord.value, 'displayName', tool);
373
+ if (!displayName.ok)
374
+ return displayName;
375
+ const reopenedBy = { type: type.value, id: id.value };
376
+ if (displayName.value !== undefined)
377
+ reopenedBy.displayName = displayName.value;
378
+ const result = { ...base.value, phase: phase.value, reopenedBy };
379
+ const copied = copyOptionalLimitedStrings(result, record.value, tool, ['reopenedAt', 'note', 'runId', 'agentId'], undefined);
344
380
  if (!copied.ok)
345
381
  return copied;
346
382
  return { ok: true, value: result };
@@ -0,0 +1,15 @@
1
+ CREATE TABLE agent_seed_history (
2
+ id TEXT PRIMARY KEY,
3
+ applied_at TEXT NOT NULL,
4
+ from_version INTEGER,
5
+ to_version INTEGER NOT NULL,
6
+ agent_name TEXT NOT NULL,
7
+ project TEXT NOT NULL,
8
+ scope TEXT NOT NULL,
9
+ outcome TEXT NOT NULL,
10
+ reason TEXT,
11
+ source TEXT NOT NULL
12
+ );
13
+
14
+ CREATE INDEX idx_agent_seed_history_applied_at ON agent_seed_history(applied_at);
15
+ CREATE INDEX idx_agent_seed_history_project_scope_name ON agent_seed_history(project, scope, agent_name);
@@ -1 +1,5 @@
1
+ export const TERMINAL_RUN_STATUSES = ['completed', 'failed', 'blocked', 'cancelled'];
2
+ export function isTerminalRunStatus(status) {
3
+ return TERMINAL_RUN_STATUSES.includes(status);
4
+ }
1
5
  export const runSnapshotPackageKind = 'vgxness.run-snapshot-package';
@@ -30,10 +30,22 @@ export const SddArtifactAcceptanceRecordSchema = z
30
30
  note: z.string().optional(),
31
31
  })
32
32
  .strict();
33
+ export const SddArtifactReopenRecordSchema = z
34
+ .object({
35
+ actor: z.object({
36
+ type: z.literal('human'),
37
+ id: z.string().min(1),
38
+ displayName: z.string().min(1).optional(),
39
+ }),
40
+ reopenedAt: z.string().min(1),
41
+ note: z.string().optional(),
42
+ })
43
+ .strict();
33
44
  export const SddArtifactMetadataSchema = z
34
45
  .object({
35
46
  status: SddArtifactStatusSchema,
36
47
  acceptance: SddArtifactAcceptanceRecordSchema.optional(),
48
+ reopen: SddArtifactReopenRecordSchema.optional(),
37
49
  supersededByTopicKey: z.string().min(1).optional(),
38
50
  updatedAt: z.string().min(1).optional(),
39
51
  })
@@ -175,7 +175,7 @@ export class SddWorkflowService {
175
175
  if (status === 'accepted')
176
176
  return validationFailure('Cannot overwrite an accepted SDD artifact; supersede it under a new topic key.');
177
177
  if (status === 'rejected')
178
- return validationFailure('Rejected SDD artifact must be re-opened with an explicit decision before saving.');
178
+ return validationFailure('Rejected SDD artifact must be re-opened via SddWorkflowService.reopenArtifact before saving.');
179
179
  if (status === 'superseded')
180
180
  return validationFailure('Cannot overwrite a superseded SDD artifact.');
181
181
  }
@@ -198,7 +198,7 @@ export class SddWorkflowService {
198
198
  const existingEnvelope = normalizeSddArtifact(existing.value);
199
199
  const existingStatus = existingEnvelope.metadata.status;
200
200
  if (existingStatus === 'rejected')
201
- return validationFailure('Rejected SDD artifact must be re-opened with an explicit decision before accepting.');
201
+ return validationFailure('Rejected SDD artifact must be re-opened via SddWorkflowService.reopenArtifact before accepting.');
202
202
  if (existingStatus === 'superseded')
203
203
  return validationFailure('Cannot accept a superseded SDD artifact; create a new artifact under a different topic key instead.');
204
204
  const acceptance = {
@@ -223,6 +223,47 @@ export class SddWorkflowService {
223
223
  },
224
224
  }, this.context);
225
225
  }
226
+ reopenArtifact(input) {
227
+ const validated = this.validatePhaseInput(input);
228
+ if (!validated.ok)
229
+ return validated;
230
+ if (input.reopenedBy === undefined)
231
+ return validationFailure('SDD artifact reopen requires an explicit human actor');
232
+ if (input.reopenedBy.type !== 'human')
233
+ return validationFailure('SDD artifact reopen must be performed by a human actor');
234
+ if (input.reopenedBy.id === undefined || input.reopenedBy.id.trim().length === 0)
235
+ return validationFailure('SDD artifact reopen human actor id must not be empty');
236
+ const topicKey = sddTopicKey(validated.value.change, validated.value.phase);
237
+ const existing = this.memory.getArtifact(validated.value.project, topicKey, this.context);
238
+ if (!existing.ok)
239
+ return existing;
240
+ const existingEnvelope = normalizeSddArtifact(existing.value);
241
+ const existingStatus = existingEnvelope.metadata.status;
242
+ if (existingStatus !== 'rejected')
243
+ return validationFailure(`SDD artifact reopen is only valid for rejected artifacts (current status: ${existingStatus}).`);
244
+ const reopenedAt = input.reopenedAt ?? new Date().toISOString();
245
+ const reopenRecord = {
246
+ actor: {
247
+ type: 'human',
248
+ id: input.reopenedBy.id,
249
+ ...(input.reopenedBy.displayName === undefined ? {} : { displayName: input.reopenedBy.displayName }),
250
+ },
251
+ reopenedAt,
252
+ ...(input.note === undefined ? {} : { note: input.note }),
253
+ };
254
+ return this.memory.saveArtifact({
255
+ project: existing.value.project,
256
+ topicKey: existing.value.topicKey,
257
+ phase: existing.value.phase,
258
+ content: existing.value.content,
259
+ metadata: {
260
+ ...existingEnvelope.metadata,
261
+ status: 'draft',
262
+ reopen: reopenRecord,
263
+ updatedAt: reopenedAt,
264
+ },
265
+ }, this.context);
266
+ }
226
267
  getArtifact(input) {
227
268
  const validated = this.validatePhaseInput(input);
228
269
  if (!validated.ok)
@@ -91,6 +91,14 @@ Gentle-AI/`gentle-pi` are strong references for the configurator and agent-behav
91
91
  | `Adapter` | Translator between the neutral `vgxness` model and a provider-specific config/runtime. |
92
92
  | `PermissionPolicy` | Rules defining what an agent may do, what requires approval, and what must be denied. |
93
93
 
94
+ ### Agent registry self-healing
95
+
96
+ The canonical agent manifest in `src/agents/canonical-agent-manifest.ts` is the source of truth for built-in agents (1 manager + 10 SDD subagents). At every CLI/MCP boot, `src/agents/boot-upgrade.ts` reconciles the live `agents` table with that manifest via `src/agents/agent-seed-upgrade-service.ts`: missing rows are created, drifted rows (changed `vgxnessPromptContractVersion`, instructions, adapters, or description) are overwritten, and matches are recorded as noop. Each non-noop outcome is appended to the `agent_seed_history` table for audit. Operators can opt out with `VGXNESS_SKIP_AGENT_SEED_AUTO_UPGRADE=1`. This eliminates the long-standing drift between the canonical prompt contract and stored agent rows after a version bump.
97
+
98
+ ### Manager overlay parity across providers
99
+
100
+ A user-saved `manager_profile_overlay` flows to both providers symmetrically. OpenCode consults the overlay inside `OpenCodeManagerPayloadService.applyManagerOverlayWhenAvailable` (`src/providers/opencode/manager-payload.ts:152-156`), which calls `ManagerProfileOverlayService.resolveEffectiveManager` before producing the OpenCode manager payload. Claude Code was previously canonical-only; the fix routes the overlay through `withEffectiveManagerInstructions` (`src/agents/canonical-agent-projection.ts`) into the render path (`expectedClaudeCodeRenderedAgents` / `expectedClaudeCodeRenderedUserAgents`), with the caller (`mcp install claude` in `src/cli/commands/mcp-dispatcher.ts`) computing the effective instructions via `computeEffectiveManagerInstructions(database)` and passing them into `installClaudeCodeMcpClient`. As a result, `vgxness mcp install claude` writes the user's customized instructions into `.claude/agents/vgxness-manager.md` instead of silently falling back to canonical.
101
+
94
102
  ## Storage model
95
103
 
96
104
  `vgxness` should keep local storage split by scope.
package/docs/cli.md CHANGED
@@ -24,7 +24,7 @@ vgx --help
24
24
  vgxness mcp start --db <temp-memory.sqlite> # then call verification_plan with { changeType: 'mcp' }
25
25
  ```
26
26
 
27
- `vgxness setup plan` and `vgxness setup status` are human-readable and read-only by default; pass `--json` when you need parseable automation output. The MCP plan is read-only. Installed-package setup plans should use `vgxness mcp start` and must not mention `npm run cli`, `tsx`, or repository-relative source paths.
27
+ `vgxness setup plan` and `vgxness setup status` are human-readable and do not write provider config by default; local VGXNESS store initialization may occur when the selected SQLite store is needed. Pass `--json` when you need parseable automation output. The MCP plan does not write provider config. Installed-package setup plans should use `vgxness mcp start` and must not mention `npm run cli`, `tsx`, or repository-relative source paths.
28
28
 
29
29
  Only apply the OpenCode user/global config after reviewing the plan (use `--scope project` only when you intentionally want project config):
30
30
 
@@ -63,7 +63,7 @@ vgxness sdd next --project <project> --change <change>
63
63
  vgxness setup rollback --backup <path>
64
64
  ```
65
65
 
66
- `setup plan`, `setup status`, and non-TTY `init` planning are read-only and do not write provider config. They are human-readable by default; pass `--json` when you need parseable automation output. With the default global database, the OpenCode MCP command is `vgxness mcp start`; for custom/project-local DBs it includes `--db <path>`. The default OpenCode target is `$HOME/.config/opencode/opencode.json`; pass `--scope project` to opt into `<workspace>/.opencode/opencode.json`. `setup apply --yes` is the explicit OpenCode provider-config write path. `setup rollback --backup <path>` validates a VGXNESS/OpenCode backup such as `opencode.json.backup-<timestamp>`, creates a pre-rollback backup of the current target when present, restores the selected backup byte-for-byte, and recommends `vgxness doctor`.
66
+ `setup plan`, `setup status`, and non-TTY `init` planning do not write provider config. Local VGXNESS store initialization may occur when the selected SQLite store is needed. They are human-readable by default; pass `--json` when you need parseable automation output. With the default global database, the OpenCode MCP command is `vgxness mcp start`; for custom/project-local DBs it includes `--db <path>`. The default OpenCode target is `$HOME/.config/opencode/opencode.json`; pass `--scope project` to opt into `<workspace>/.opencode/opencode.json`. `setup apply --yes` is the explicit OpenCode provider-config write path. `setup rollback --backup <path>` validates a VGXNESS/OpenCode backup such as `opencode.json.backup-<timestamp>`, creates a pre-rollback backup of the current target when present, restores the selected backup byte-for-byte, and recommends `vgxness doctor`.
67
67
 
68
68
  `vgxness init` prompts in English when stdin/stdout are TTYs: project name, DB location, provider, OpenCode scope, install mode, then shows the plan and asks `Apply this setup? Type "yes" to continue:`. Any answer other than `yes` exits successfully without writes. In CI/non-TTY without `--yes`, `init` returns the read-only plan and never waits for input. `vgxness doctor`, `vgxness sdd status`, `vgxness sdd next`, `vgxness sdd get-artifact`, and `vgxness sdd list-artifacts` are also human-readable by default; use `--json` for scripts.
69
69
 
@@ -112,7 +112,7 @@ Release-candidate checklist, without publishing:
112
112
 
113
113
  1. `bun install --frozen-lockfile` completes on a clean checkout.
114
114
  2. `bun run check:bun-lock` passes.
115
- 3. `bun run verify:typecheck`, `bun run verify:test`, and `bun run verify:bun-sqlite` pass.
115
+ 3. `bun run verify:typecheck`, `bun run verify:test`, `bun run verify:test:bun-storage`, and `bun run verify:bun-sqlite` pass.
116
116
  4. `bun run package:bun:evidence -- --require-pass` passes on supported CI OSes.
117
117
  5. Uploaded JSON shows `status: pass`, artifact/install smoke pass, no retired scripts, no `package-lock.json`, `publicationAttempted: false`, and `releaseReadiness.status: pass`.
118
118
  6. Version, release notes, proprietary license boundary, and rollback criteria are reviewed.
@@ -312,7 +312,7 @@ bun run cli:bun -- <workflow> run --project <name> --intent <text> [--phase <nam
312
312
  bun run cli:bun -- <workflow> execute --run-id <id> --confirm [--override-escalation] [--workspace <path>] [--db <path>] [--executor safe-non-dispatching|provider|command]
313
313
  ```
314
314
 
315
- `preview` is read-only: it returns the workflow registry plus optional planner output, does not open or write the database, does not create runs, does not call providers, does not edit files, and does not write provider config. Use it to choose between `quickfix`, `debug`, `sdd`, or another workflow before recording state.
315
+ `preview` is read-only: it returns the workflow registry plus optional planner output, does not open or write the database, does not create runs, does not call providers, does not edit files, and does not write provider config. Use it to choose between `quickfix`, `debug`, `sdd`, or another workflow before recording state. Other status/plan surfaces may open or initialize the selected VGXNESS SQLite store; that local store state is separate from provider config.
316
316
 
317
317
  `run` records the selected workflow intent and a `workflow-run-planned` checkpoint in the local SQLite store. It selects or validates an agent, stores the run id, and reports any planner recommendation such as SDD escalation. It does not dispatch providers, edit files, write provider config, create subagents, or mutate SDD artifacts.
318
318
 
@@ -437,7 +437,7 @@ A rejected approval is recorded in the run audit trail and prevents the matching
437
437
 
438
438
  ## MCP setup preview and doctor
439
439
 
440
- Use this flow to manually verify MCP readiness after implementation. Setup preview is read-only: it does **not** install anything, create `.opencode/` or `.claude/`, or write provider/user/global config.
440
+ Use this flow to manually verify MCP readiness after implementation. Setup preview does **not** install anything, create `.opencode/` or `.claude/`, or write provider/user/global config. Local VGXNESS store initialization may occur when a command needs the selected SQLite store.
441
441
 
442
442
  ```bash
443
443
  bun run cli:bun -- mcp setup --preview --provider opencode --db <path>
@@ -69,7 +69,7 @@ The configurator/setup plane (rendering/installing provider config) is separate
69
69
 
70
70
  These rules are non-negotiable. The harness is loaded with capability; do not remove these guards.
71
71
 
72
- - Read-only/preview commands must stay non-mutating. Setup plans, MCP setup previews, OpenCode previews, workflow previews, and status views must not write provider config or call providers.
72
+ - Read-only/preview commands must not mutate provider config or external tool state. Setup plans, MCP setup previews, OpenCode previews, workflow previews, and status views must not write provider config or call providers. Local VGXNESS store initialization may occur when a command needs the selected SQLite store.
73
73
  - Provider config writes require explicit consent (`--yes` or equivalent confirmed flow) plus backup/rollback behavior.
74
74
  - Do not create or write `openspec/`. SDD artifacts are stored through the local SQLite artifact service under canonical topic keys `sdd/{change}/{phase}`.
75
75
  - Human acceptance is distinct from artifact presence. Do not infer acceptance from generated content or saved drafts. The runtime rejects `acceptedBy.type !== 'human'`.
package/docs/glossary.md CHANGED
@@ -64,7 +64,7 @@ A permission resolution: `allow`, `ask`, or `deny`. For SDD-phase gating the mat
64
64
 
65
65
  ## Dry-run
66
66
 
67
- A read-only preview. Setup plans, MCP setup previews, OpenCode previews, workflow previews, and status views are dry-runs by contract they must not write provider config or call providers.
67
+ A read-only preview. Setup plans, MCP setup previews, OpenCode previews, workflow previews, and status views are dry-runs by contract for provider config and external tools: they must not write provider config or call providers. Local VGXNESS store initialization may occur when a command needs the selected SQLite store.
68
68
 
69
69
  ## Eval target
70
70
 
package/docs/mcp.md CHANGED
@@ -20,7 +20,7 @@ All tools:
20
20
  | `vgxness_sdd_ready` | Check whether a specific phase is ready. | `project`, `change`, `phase`; optional `runId`, `agentId` | Returns structured `SddReadiness` with `blockedPrerequisites`. |
21
21
  | `vgxness_sdd_get_readiness` | Same as `ready` with explicit output shape. | same as `ready` | |
22
22
  | `vgxness_sdd_save_artifact` | Persist phase content under canonical topic key `sdd/{change}/{phase}`. | `project`, `change`, `phase`, `content` | Saving does not imply acceptance. |
23
- | `vgxness_sdd_accept_artifact` | Record explicit human acceptance for a phase. | `project`, `change`, `phase`, `acceptedBy` (`{type:"human", id, displayName?}`); optional `acceptedAt`, `note`, `notes`, `rationale`, `runId`, `agentId` | `acceptedBy.type` must be `"human"`. Runtime rejects agent or anonymous acceptance. |
23
+ | `vgxness_sdd_accept_artifact` | Record explicit human acceptance for a phase. | `project`, `change`, `phase`, `acceptedBy` (`{type:"human", id, displayName?}`); optional `acceptedAt`, `note`, `runId`, `agentId` | `acceptedBy.type` must be `"human"`. Runtime rejects agent or anonymous acceptance. Only `note` is accepted; `notes` and `rationale` are rejected as unexpected fields. |
24
24
  | `vgxness_sdd_get_artifact` | Read one full artifact. | `project`, `change`, `phase`; optional `payloadMode` (`compact`/`verbose`) | |
25
25
  | `vgxness_sdd_list_artifacts` | List all artifacts for a change in canonical phase order. | `project`, `change`; optional `payloadMode` | |
26
26
  | `vgxness_sdd_cockpit` | Aggregate per-phase status, blockers, and recommended next action. | `project`, `change` | Returns `SddCockpit` with `aggregateBlockers` of kinds `missing-topic-key`, `unaccepted-phase`, `legacy-artifact`, `readiness`. |
@@ -117,7 +117,7 @@ Recording a phase with explicit human acceptance:
117
117
  ```text
118
118
  vgxness_sdd_save_artifact { project, change, phase: "proposal", content: "..." }
119
119
  # human opens the harness and runs:
120
- vgxness_sdd_accept_artifact { project, change, phase: "proposal", acceptedBy: { type: "human", id: "uziel" }, rationale: "Reviewed proposal." }
120
+ vgxness_sdd_accept_artifact { project, change, phase: "proposal", acceptedBy: { type: "human", id: "uziel" }, note: "Reviewed proposal." }
121
121
  ```
122
122
 
123
123
  Running a planned operation:
@@ -0,0 +1,126 @@
1
+ # Auditoría de salud del proyecto VGXNESS v1.9.1
2
+
3
+ ## Resumen v1.9.1
4
+
5
+ VGXNESS v1.9.1 fue validado exitosamente como CLI/MCP control plane local-first, con runtime instalado basado en Bun, almacenamiento SQLite local y gobernanza SDD con aceptación humana explícita. Esta auditoría es la fuente canónica para la evidencia v1.9.1; si los conteos o comandos cambian, actualiza este documento en vez de duplicar la matriz en otros docs.
6
+
7
+ ## Evidencia oficial validada
8
+
9
+ - VGXNESS v1.9.1 validado exitosamente.
10
+ - MCP expone 38 tools tipadas.
11
+ - Inventario de tests: 106 test files.
12
+ - Validación oficial aprobada:
13
+ - `bun run verify:typecheck`
14
+ - `bun run verify:test` con 437 pass, 0 fail
15
+ - `bun run verify:test:bun-storage`
16
+ - `bun run verify:bun-sqlite`
17
+ - `bun run package:bun:evidence` con `releaseReadiness: pass`
18
+
19
+ ## Matriz de validación
20
+
21
+ | Superficie | Evidencia v1.9.1 | Taxonomía | Resultado esperado |
22
+ |---|---|---|---|
23
+ | Typecheck | `bun run verify:typecheck` | `test-run` | TypeScript estricto compila sin errores. |
24
+ | Node tests | `bun run verify:test` | `test-run` | Suite Node pasa; evidencia validada: 437 pass, 0 fail. |
25
+ | Bun storage tests | `bun run verify:test:bun-storage` | `test-run/local-store` | Tests storage-backed pasan vía runner oficial bajo Bun. |
26
+ | Bun SQLite probe | `bun run verify:bun-sqlite` | `test-run/local-store` | `bun:sqlite` aplica migraciones en DB temporal y valida integridad. |
27
+ | Package evidence | `bun run package:bun:evidence` | `package evidence` | Evidencia de paquete sin publicar; `releaseReadiness: pass`. |
28
+ | MCP schema/tools | `docs/mcp.md` + `SUPPORTED_VGX_MCP_TOOL_NAMES` | `governance/read model` | 38 tools documentadas; schema y tabla deben mantenerse sincronizados. |
29
+ | Test inventory | Inventario v1.9.1 | `test-run` | 106 test files como evidencia versionada. |
30
+ | Setup/provider status | `setup plan/status`, provider status/doctor/change-plan | `read-only/no provider writes` | No escriben provider config; pueden leer o inicializar el store local de VGXNESS si hace falta. |
31
+ | Provider previews | MCP setup preview, OpenCode preview, agent render | `read-only/provider-preview` | Preview sin ejecutar proveedores ni escribir `.opencode/`, `.claude/` o config global. |
32
+ | SDD workflow | `sdd status/ready/get/list/next/save/accept` | `governance/read model` | Artefactos en SQLite bajo `sdd/{change}/{phase}`; aceptación humana explícita. |
33
+ | Runs/preflight | `run_start`, `run_preflight`, resume inspect/gate | `guarded apply` | Operaciones riesgosas pasan por preflight/approval antes de ejecución. |
34
+ | Memory/session local state | Memory, sessions, cockpit | `local-store possible` | Estado durable vive en SQLite local; no implica provider config writes. |
35
+ | Workflow executor | Workflow preview/run/execute + allowlist | `requires explicit consent` | Preview no muta; ejecución requiere confirmación y comandos allowlisted. |
36
+ | Package runtime Bun | Bins `vgxness`/`vgx` y MCP instalado | `package evidence` | Runtime instalado usa wrapper Bun y evidencia de paquete sin publicación. |
37
+
38
+ ## Taxonomía de seguridad
39
+
40
+ - `docs-only`: documentación sin cambios de runtime.
41
+ - `test-run`: verificación local o CI que puede consumir CPU/IO pero no cambia el contrato de producto.
42
+ - `test-run/local-store`: tests/probes que crean o usan storage local temporal.
43
+ - `package evidence`: inspección de artefacto/install smoke sin publicar.
44
+ - `read-only/no provider writes`: no escribe configuración de proveedor, aunque puede abrir o preparar estado local de VGXNESS.
45
+ - `read-only/provider-preview`: produce planes o previews sin instalar hooks, ejecutar proveedores ni escribir provider config.
46
+ - `local-store possible`: puede leer/escribir SQLite local de VGXNESS por diseño del comando.
47
+ - `governance/read model`: estado SDD/runs/memory consultable, con aceptación humana separada de la presencia del artefacto.
48
+ - `guarded apply`: operación mutante detrás de preflight, approval y auditoría.
49
+ - `requires explicit consent`: requiere `--yes`, confirmación equivalente o aprobación humana registrada.
50
+ - `future/not implemented`: documentado como trabajo futuro, no como alcance actual.
51
+
52
+ ## Read-only, provider config y local store
53
+
54
+ En esta auditoría, “read-only” debe leerse con precisión operacional: una superficie puede ser read-only respecto de proveedor y workspace, pero aun así abrir, leer o preparar el store local de VGXNESS. La regla canónica es:
55
+
56
+ > No provider config writes; local VGXNESS store initialization may occur.
57
+
58
+ Esto distingue tres planos:
59
+
60
+ 1. **Provider config**: `.opencode/`, `opencode.json`, `.claude/`, `.mcp.json`, `CLAUDE.md` y archivos equivalentes. Escribirlos requiere consentimiento explícito y backup/rollback cuando aplique.
61
+ 2. **Local VGXNESS store**: SQLite local para memoria, sesiones, runs, SDD artifacts, agentes, skills y perfiles. Algunos comandos pueden abrir o inicializar este store.
62
+ 3. **Workspace/source**: archivos del repo y artefactos de código. Este cambio es docs-only y no cambia runtime, permisos, approvals, provider setup ni packaging.
63
+
64
+ ## Comandos oficiales de validación
65
+
66
+ Validación oficial completa para v1.9.1:
67
+
68
+ ```bash
69
+ bun run verify:typecheck
70
+ bun run verify:test
71
+ bun run verify:test:bun-storage
72
+ bun run verify:bun-sqlite
73
+ bun run package:bun:evidence
74
+ ```
75
+
76
+ Para release-readiness, el package evidence debe requerir pase explícito:
77
+
78
+ ```bash
79
+ bun run package:bun:evidence -- --require-pass
80
+ ```
81
+
82
+ ## Notas sobre tests storage-backed
83
+
84
+ Los tests storage-backed no deben documentarse como invocaciones genéricas directas de `node --test`. Usa los runners oficiales porque preparan el runtime correcto, paths temporales y expectativas de Bun/SQLite:
85
+
86
+ - `bun run verify:test:bun-storage` para tests storage-backed bajo Bun.
87
+ - `bun run verify:bun-sqlite` para el probe SQLite real con `bun:sqlite`.
88
+
89
+ Node.js sigue siendo tooling de desarrollo/build/test para TypeScript, `node:test` y scripts auxiliares, pero el storage runtime soportado es Bun.
90
+
91
+ ## Riesgos y mitigaciones
92
+
93
+ | Riesgo | Mitigación |
94
+ |---|---|
95
+ | Duplicar la matriz en README u otros docs y crear drift. | Mantener este archivo como fuente canónica; README solo resume y enlaza. |
96
+ | Prometer “no mutation” absoluta donde puede inicializarse SQLite local. | Usar wording preciso: no provider config writes; local VGXNESS store initialization may occur. |
97
+ | Confundir package evidence con publicación. | Package evidence no publica; publishing requiere proceso humano explícito separado. |
98
+ | Tratar aceptación SDD como presencia de artifact. | Mantener aceptación humana explícita como requisito independiente. |
99
+ | Ejecutar storage tests con runner incorrecto. | Documentar runners oficiales Bun para storage-backed tests. |
100
+ | Expandir esta auditoría hacia refactors P1/P2. | Mantener P1/P2 bajo future work solamente. |
101
+
102
+ ## Fuera de alcance
103
+
104
+ - Cambios de runtime, approvals, preflight, permisos, SDD acceptance o provider setup.
105
+ - Cambios de package metadata, scripts, packaging o publicación.
106
+ - Escritura de provider config o creación de `.opencode/`, `.claude/` u `openspec/`.
107
+ - Refactors de MCP control-plane, SDD workflow, runs, storage o CLI.
108
+ - Nuevos comandos de health audit o nuevos MCP tools.
109
+
110
+ ## Future work P1/P2
111
+
112
+ Estos puntos son notas futuras (`future/not implemented`), no alcance de v1.9.1:
113
+
114
+ - Modularizar MCP control-plane.
115
+ - Separar SDD projections/read models.
116
+ - Unificar lenguaje de guarded apply/Claude.
117
+ - Crear un comando/reporte integrado de health audit.
118
+
119
+ ## Cómo actualizar esta auditoría
120
+
121
+ 1. Revalidar los comandos oficiales y registrar conteos nuevos solo si fueron medidos.
122
+ 2. Si cambia el número de MCP tools, actualizar `SUPPORTED_VGX_MCP_TOOL_NAMES` y `docs/mcp.md` en el mismo cambio.
123
+ 3. Si cambia el inventario de tests, actualizar esta evidencia versionada y evitar duplicar conteos en README.
124
+ 4. Si cambia la semántica de setup/provider preview/status, revisar wording de provider config vs local store.
125
+ 5. Si cambian runners o package evidence, actualizar `README.md`, `docs/cli.md` y `docs/contributing.md` según corresponda.
126
+ 6. No marcar esta auditoría ni artefactos SDD como aceptados salvo aceptación humana explícita.
package/docs/providers.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  VGXNESS is provider-agnostic at the core: the registry stores provider-neutral definitions and adapters translate them into provider-specific config and runtime behavior. This document covers the two adapter layers: the **control-plane adapter** (OpenCode primary plus supported secondary Claude Code support) and the **code-runtime provider adapter** (OpenAI-compatible + fake).
4
4
 
5
- ## Status (v1.6.0)
5
+ ## Status (v1.9.1)
6
6
 
7
7
  | Provider | Control plane | Code runtime | Notes |
8
8
  |---|---|---|---|
@@ -44,7 +44,7 @@ vgxness agents render --provider json --project vgxness --name apply-agent
44
44
 
45
45
  ### Claude Code support
46
46
 
47
- Claude Code is supported as a secondary, non-default control-plane target. Read-only status, doctor, setup plan, and change-plan surfaces can inspect or preview Claude targets without Claude Code installed and without writing files.
47
+ Claude Code is supported as a secondary, non-default control-plane target. Status, doctor, setup plan, and change-plan surfaces can inspect or preview Claude targets without Claude Code installed and without writing provider config. Local VGXNESS store initialization may occur when the selected SQLite store is needed.
48
48
 
49
49
  Claude scopes are canonicalized to `local`, `project`, and `user`; VGXNESS compatibility aliases `personal` and legacy `global` map to Claude `user` with warnings. MCP registration is represented as structured config/argv, for example `claude mcp add --scope user vgxness -- vgxness mcp start`; no shell strings are generated. For user/global apply, VGXNESS narrowly merges only `mcpServers.vgxness` in `~/.claude.json`, preserves unknown keys, backs up existing files, and does not manage auth/session data. Status/doctor/change-plan are read-only and do not execute Claude Code.
50
50
 
@@ -128,13 +128,13 @@ Deterministic, offline. Used by `test/code/` and `bun run smoke:opentui-code` to
128
128
 
129
129
  Provider install and doctor flows live in `src/mcp/client-install-opencode.ts` and `src/mcp/provider-doctor.ts` and are exposed through the MCP server and the CLI:
130
130
 
131
- - `vgxness mcp install opencode --plan` — read-only plan; never writes config.
131
+ - `vgxness mcp install opencode --plan` — plan that never writes provider config; local VGXNESS store initialization may occur when the selected SQLite store is needed.
132
132
  - `vgxness mcp install opencode --yes` — explicit write path; creates a backup first.
133
133
  - `vgxness mcp doctor opencode` — JSON report of provider health.
134
134
  - `vgxness provider status` / `vgxness provider doctor` (planned CLI) — same shape through the operator surface.
135
135
  - `vgxness setup rollback --backup <path>` — restores a previous OpenCode config byte-for-byte after validation.
136
136
 
137
- Writes happen only through `apply` with explicit consent. Plans, status, doctor, change-plan, and previews are read-only by contract.
137
+ Provider config writes happen only through `apply` with explicit consent. Plans, status, doctor, change-plan, and previews do not write provider config; local VGXNESS store initialization may occur when the selected SQLite store is needed.
138
138
 
139
139
  ## Safety boundary
140
140
 
package/docs/safety.md CHANGED
@@ -132,7 +132,7 @@ Retry policy evaluation is separate from execution. `vgxness_run_resume_gate` ev
132
132
 
133
133
  ## Safety boundaries (enforced everywhere)
134
134
 
135
- - Read-only/preview commands must stay non-mutating: setup plans, MCP setup previews, OpenCode previews, workflow previews, status views, and the natural-language orchestrator preview never write provider config, call providers, or install global memory.
135
+ - Read-only/preview commands must not mutate provider config or external tool state: setup plans, MCP setup previews, OpenCode previews, workflow previews, status views, and the natural-language orchestrator preview never write provider config, call providers, or install global memory. Local VGXNESS store initialization may occur when a command needs the selected SQLite store.
136
136
  - Provider config writes (`opencode.json`, `.opencode/`, `.claude/`, `CLAUDE.md`) require explicit consent (`--yes` or an equivalent confirmed flow) plus backup/rollback behavior.
137
137
  - The control plane and the code runtime do not create or write `openspec/`. SDD artifacts are stored through the local SQLite artifact service under canonical topic keys.
138
138
  - Human acceptance is distinct from artifact presence: `vgxness_sdd_accept_artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vgxness",
3
- "version": "1.9.1",
3
+ "version": "1.9.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": {