vgxness 1.9.1 → 1.9.3
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/README.md +15 -5
- package/dist/agents/agent-activation-service.js +13 -4
- package/dist/agents/agent-registry-service.js +8 -2
- package/dist/agents/agent-resolver.js +33 -3
- package/dist/agents/agent-seed-upgrade-service.js +231 -0
- package/dist/agents/boot-upgrade.js +59 -0
- package/dist/agents/canonical-agent-manifest.js +39 -18
- package/dist/agents/canonical-agent-projection.js +38 -4
- package/dist/agents/manager-profile-overlay-service.js +14 -0
- package/dist/agents/repositories/agent-seed-history.js +128 -0
- package/dist/cli/cli-help.js +14 -3
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/interactive-entrypoint-dispatcher.js +8 -0
- package/dist/cli/commands/mcp-dispatcher.js +7 -0
- package/dist/cli/commands/memory-sdd-dispatcher.js +71 -5
- package/dist/cli/commands/status-dispatcher.js +130 -0
- package/dist/cli/commands/workflow-dispatcher.js +11 -5
- package/dist/cli/dispatcher.js +11 -1
- package/dist/cli/product-resume-renderer.js +32 -0
- package/dist/cli/product-status-renderer.js +74 -0
- package/dist/cli/sdd-renderer.js +80 -3
- package/dist/code/cli/code-command.js +7 -4
- package/dist/code/reporting/summary.js +4 -1
- package/dist/code/runtime/code-runtime.js +27 -4
- package/dist/code/runtime/sdd-context.js +18 -2
- package/dist/governance/governance-report-builder.js +18 -7
- package/dist/mcp/claude-code-agent-config.js +10 -4
- package/dist/mcp/client-install-claude-code-contract.js +19 -4
- package/dist/mcp/client-install-claude-code.js +2 -2
- package/dist/mcp/control-plane.js +78 -5
- package/dist/mcp/provider-status.js +89 -88
- package/dist/mcp/schema.js +42 -8
- package/dist/mcp/stdio-server.js +6 -0
- package/dist/mcp/validation.js +77 -5
- package/dist/memory/sqlite/migrations/016_agent_seed_history.sql +15 -0
- package/dist/resume/product-resume.js +166 -0
- package/dist/runs/repositories/runs.js +12 -1
- package/dist/runs/run-service.js +62 -5
- package/dist/runs/schema.js +4 -0
- package/dist/sdd/schema.js +20 -0
- package/dist/sdd/sdd-continuation-plan.js +81 -0
- package/dist/sdd/sdd-workflow-service.js +146 -18
- package/dist/skills/skill-resolver.js +21 -4
- package/dist/status/product-status.js +117 -0
- package/docs/architecture.md +9 -1
- package/docs/cli.md +38 -13
- package/docs/code-runtime.md +3 -0
- package/docs/contributing.md +1 -1
- package/docs/glossary.md +2 -2
- package/docs/mcp.md +20 -6
- package/docs/project-health-audit-v1.9.1.md +126 -0
- package/docs/providers.md +4 -4
- package/docs/safety.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ This package is proprietary software. The npm package ships inspectable JavaScri
|
|
|
8
8
|
|
|
9
9
|
OpenCode is the primary supported provider. Other providers remain preview/manual only. Provider config writes require explicit CLI confirmation.
|
|
10
10
|
|
|
11
|
+
VGXNESS v1.9.1 has a canonical project health audit with validated evidence: 38 MCP tools, 106 test files, and the official Bun validation path passing, including package evidence with `releaseReadiness: pass`. Current unreleased builds expose 41 MCP tools after adding read-only SDD/run recovery parity. See [Project health audit v1.9.1](./docs/project-health-audit-v1.9.1.md) for the versioned matrix and safety taxonomy.
|
|
12
|
+
|
|
11
13
|
## Requirements
|
|
12
14
|
|
|
13
15
|
- Bun >= 1.3.14 for the installed `vgxness`/`vgx` CLI/MCP runtime and repository verification
|
|
@@ -25,6 +27,7 @@ bun install --frozen-lockfile
|
|
|
25
27
|
bun run check:bun-lock
|
|
26
28
|
bun run verify:typecheck
|
|
27
29
|
bun run verify:test
|
|
30
|
+
bun run verify:test:bun-storage
|
|
28
31
|
bun run verify:bun-sqlite
|
|
29
32
|
bun run verify:package
|
|
30
33
|
bun run package:bun:evidence -- --require-pass
|
|
@@ -86,7 +89,7 @@ Release-candidate checklist, still non-publishing:
|
|
|
86
89
|
|
|
87
90
|
1. `bun install --frozen-lockfile` completes on a clean checkout.
|
|
88
91
|
2. `bun run check:bun-lock` passes.
|
|
89
|
-
3. `bun run verify:typecheck`, `bun run verify:test`, and `bun run verify:bun-sqlite` pass.
|
|
92
|
+
3. `bun run verify:typecheck`, `bun run verify:test`, `bun run verify:test:bun-storage`, and `bun run verify:bun-sqlite` pass.
|
|
90
93
|
4. `bun run package:bun:evidence -- --require-pass` passes on supported CI OSes.
|
|
91
94
|
5. JSON evidence shows `status: pass`, artifact/install smoke pass, no retired bridge scripts, no `package-lock.json`, `publicationAttempted: false`, and `releaseReadiness.status: pass`.
|
|
92
95
|
6. Version, release notes, proprietary license boundary, and rollback criteria are reviewed.
|
|
@@ -141,7 +144,9 @@ In non-TTY shells, `vgxness init` prints the same read-only setup plan instead o
|
|
|
141
144
|
vgxness setup plan
|
|
142
145
|
vgxness setup apply --yes
|
|
143
146
|
vgxness doctor
|
|
144
|
-
vgxness
|
|
147
|
+
vgxness status --project <project> --change <change>
|
|
148
|
+
vgxness next --project <project> --change <change>
|
|
149
|
+
vgxness sdd continue --project <project> --change <change>
|
|
145
150
|
```
|
|
146
151
|
|
|
147
152
|
Stable defaults are: package `vgxness`, provider `opencode`, global user data DB, user/global OpenCode scope (`$HOME/.config/opencode/opencode.json`), and `mcp-plus-agents` mode. Use `--scope project` only when you intentionally want `<workspace>/.opencode/opencode.json`. The generated MCP command for the global DB default is:
|
|
@@ -156,7 +161,9 @@ Apply only after reviewing the plan:
|
|
|
156
161
|
vgxness setup apply --yes
|
|
157
162
|
```
|
|
158
163
|
|
|
159
|
-
`vgxness setup plan` and `vgxness setup status` are human-readable and
|
|
164
|
+
`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 a command needs the selected SQLite store. `vgxness doctor`, `vgxness status`, `vgxness next`, `vgxness sdd status`, `vgxness sdd next`, `vgxness sdd continue`, and `vgxness sdd accept-artifact` are also human-readable by default. Pass `--json` when you need parseable automation output. `vgxness setup apply --yes` is the explicit provider-config write path.
|
|
165
|
+
|
|
166
|
+
The SDD happy path is `status` -> `next` -> `sdd continue` -> `code sdd` or `resume` -> `accept-artifact` or `reopen-artifact`. `sdd continue`, top-level `status`/`next`, and `resume` are advisory/read-only surfaces; related interrupted run hints and resume candidates help the operator choose the next command but do not execute providers or retry runs. Draft-run suggestions are planning-only: human acceptance is still required, and `apply-progress` remains gated.
|
|
160
167
|
|
|
161
168
|
## Code runtime (`vgxness code`)
|
|
162
169
|
|
|
@@ -173,13 +180,14 @@ Edits, shell, network, git mutations, SDD persistence, and memory saves route th
|
|
|
173
180
|
|
|
174
181
|
## Safety model
|
|
175
182
|
|
|
176
|
-
- Preview, status, and plan commands
|
|
183
|
+
- Preview, status, and plan commands do not write provider config; local VGXNESS store initialization may occur where the command needs SQLite-backed state.
|
|
177
184
|
- Provider config writes require explicit `--yes` confirmation.
|
|
178
185
|
- Setup/status TUI surfaces are preview-oriented; run copied commands explicitly when you choose to act.
|
|
179
186
|
- SDD artifacts are SQLite-backed through VGXNESS services. Do not create or write `openspec/`.
|
|
180
187
|
- `vgxness sdd accept-artifact` records explicit human-only acceptance; saving a draft never implies acceptance.
|
|
188
|
+
- `vgxness sdd reopen-artifact` is the explicit path from a rejected artifact back to draft before revision.
|
|
181
189
|
- OpenCode is the primary supported provider; other providers are preview/manual extension points.
|
|
182
|
-
- VGXNESS exposes
|
|
190
|
+
- VGXNESS exposes 41 typed MCP tools across SDD, memory, sessions, agents, skills, runs, providers, and verification. See [MCP tools](./docs/mcp.md).
|
|
183
191
|
|
|
184
192
|
## Main menu entrypoint
|
|
185
193
|
|
|
@@ -236,6 +244,7 @@ bun install --frozen-lockfile
|
|
|
236
244
|
bun run check:bun-lock
|
|
237
245
|
bun run verify:typecheck
|
|
238
246
|
bun run verify:test
|
|
247
|
+
bun run verify:test:bun-storage
|
|
239
248
|
bun run verify:bun-sqlite
|
|
240
249
|
bun run package:bun:evidence -- --require-pass
|
|
241
250
|
```
|
|
@@ -255,6 +264,7 @@ Remove any OpenCode config entries and local/global VGXNESS data manually if you
|
|
|
255
264
|
## More docs
|
|
256
265
|
|
|
257
266
|
- [CLI reference](./docs/cli.md)
|
|
267
|
+
- [Project health audit v1.9.1](./docs/project-health-audit-v1.9.1.md)
|
|
258
268
|
- [Architecture](./docs/architecture.md)
|
|
259
269
|
- [Code runtime](./docs/code-runtime.md)
|
|
260
270
|
- [MCP tools](./docs/mcp.md)
|
|
@@ -98,14 +98,23 @@ export class AgentActivationService {
|
|
|
98
98
|
return this.dependencies.agents.getAgentByName(input.project, input.scope, defaultAgentName);
|
|
99
99
|
}
|
|
100
100
|
failAfterRun(runId, code, message) {
|
|
101
|
-
|
|
101
|
+
const nestedFailures = [];
|
|
102
|
+
const eventResult = this.dependencies.runs.appendEvent({
|
|
102
103
|
runId,
|
|
103
104
|
kind: 'timeline',
|
|
104
105
|
title: 'Agent activation failed',
|
|
105
|
-
payload: { error: { code: String(code), message }, nextSafeActionReturned: false },
|
|
106
|
+
payload: toJson({ error: { code: String(code), message }, nextSafeActionReturned: false }),
|
|
106
107
|
});
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
if (!eventResult.ok) {
|
|
109
|
+
nestedFailures.push({ step: 'append-event', code: String(eventResult.error.code), message: eventResult.error.message });
|
|
110
|
+
}
|
|
111
|
+
const finalStatusResult = this.dependencies.runs.updateFinalStatus({ runId, status: 'failed', outcome: 'failure', outcomeReason: message });
|
|
112
|
+
if (!finalStatusResult.ok) {
|
|
113
|
+
nestedFailures.push({ step: 'update-final-status', code: String(finalStatusResult.error.code), message: finalStatusResult.error.message });
|
|
114
|
+
}
|
|
115
|
+
return nestedFailures.length === 0
|
|
116
|
+
? { ok: false, error: { code, message } }
|
|
117
|
+
: { ok: false, error: { code, message, cause: { nestedFailures } } };
|
|
109
118
|
}
|
|
110
119
|
}
|
|
111
120
|
function validateActivationInput(input) {
|
|
@@ -32,8 +32,14 @@ export class AgentRegistryService {
|
|
|
32
32
|
this.database.close();
|
|
33
33
|
}
|
|
34
34
|
listAgentDefinitions(input) {
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const filters = {};
|
|
36
|
+
if (input.project !== undefined)
|
|
37
|
+
filters.project = input.project;
|
|
38
|
+
if (input.scope !== undefined)
|
|
39
|
+
filters.scope = input.scope;
|
|
40
|
+
if (input.mode !== undefined)
|
|
41
|
+
filters.mode = input.mode;
|
|
42
|
+
const summaries = this.agents.list(filters);
|
|
37
43
|
if (!summaries.ok)
|
|
38
44
|
return summaries;
|
|
39
45
|
const definitions = [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeSddPhaseInput } from '../sdd/schema.js';
|
|
1
2
|
export class AgentResolver {
|
|
2
3
|
loadAgents;
|
|
3
4
|
constructor(loadAgents) {
|
|
@@ -58,8 +59,10 @@ function normalizeInput(input) {
|
|
|
58
59
|
const desiredCapabilities = normalizeList(input.desiredCapabilities ?? []);
|
|
59
60
|
const taskDescription = normalizeText(input.taskDescription);
|
|
60
61
|
const intent = normalizeText(input.intent);
|
|
62
|
+
const phase = input.phase === undefined ? undefined : (isSddWorkflow(input.workflow) ? (normalizeSddPhaseInput(input.phase) ?? input.phase) : input.phase);
|
|
61
63
|
return {
|
|
62
64
|
...input,
|
|
65
|
+
...(phase !== undefined ? { phase } : {}),
|
|
63
66
|
...(taskDescription !== undefined ? { taskDescription } : {}),
|
|
64
67
|
...(intent !== undefined ? { intent } : {}),
|
|
65
68
|
desiredCapabilities,
|
|
@@ -143,7 +146,7 @@ function workflowMatches(agent, input) {
|
|
|
143
146
|
return [...matches.broad, ...matches.phaseOnly, ...matches.exactPhase];
|
|
144
147
|
}
|
|
145
148
|
function workflowSignalMatches(agent, input) {
|
|
146
|
-
const requested =
|
|
149
|
+
const requested = workflowRequestedSignals(input)
|
|
147
150
|
.filter((value) => value !== undefined)
|
|
148
151
|
.map(normalizeKey);
|
|
149
152
|
if (requested.length === 0)
|
|
@@ -154,17 +157,41 @@ function workflowSignalMatches(agent, input) {
|
|
|
154
157
|
const matches = { broad: [], phaseOnly: [], exactPhase: [] };
|
|
155
158
|
for (const agentWorkflow of agent.workflows) {
|
|
156
159
|
const normalizedWorkflow = normalizeKey(agentWorkflow);
|
|
157
|
-
|
|
160
|
+
const comparableWorkflow = canonicalSddWorkflowTargetKey(agentWorkflow);
|
|
161
|
+
if (!requested.includes(normalizedWorkflow) && !requested.includes(comparableWorkflow) && !sddApplyAliasMatches(agentWorkflow, input))
|
|
158
162
|
continue;
|
|
159
|
-
if (exact !== undefined && normalizedWorkflow === exact)
|
|
163
|
+
if (exact !== undefined && (normalizedWorkflow === exact || comparableWorkflow === exact))
|
|
160
164
|
matches.exactPhase.push(agentWorkflow);
|
|
161
165
|
else if (phase !== undefined && normalizedWorkflow === phase)
|
|
162
166
|
matches.phaseOnly.push(agentWorkflow);
|
|
167
|
+
else if (sddApplyAliasMatches(agentWorkflow, input))
|
|
168
|
+
matches.exactPhase.push(agentWorkflow);
|
|
163
169
|
else
|
|
164
170
|
matches.broad.push(agentWorkflow);
|
|
165
171
|
}
|
|
166
172
|
return matches;
|
|
167
173
|
}
|
|
174
|
+
function canonicalSddWorkflowTargetKey(workflow) {
|
|
175
|
+
const normalized = normalizeKey(workflow);
|
|
176
|
+
const separator = normalized.indexOf(':');
|
|
177
|
+
if (separator <= 0)
|
|
178
|
+
return normalized;
|
|
179
|
+
const workflowName = normalized.slice(0, separator);
|
|
180
|
+
const phase = normalized.slice(separator + 1);
|
|
181
|
+
if (workflowName !== 'sdd')
|
|
182
|
+
return normalized;
|
|
183
|
+
return `${workflowName}:${normalizeSddPhaseInput(phase) ?? phase}`;
|
|
184
|
+
}
|
|
185
|
+
function workflowRequestedSignals(input) {
|
|
186
|
+
return [input.workflow, input.phase, input.workflow !== undefined && input.phase !== undefined ? `${input.workflow}:${input.phase}` : undefined];
|
|
187
|
+
}
|
|
188
|
+
function sddApplyAliasMatches(agentWorkflow, input) {
|
|
189
|
+
if (input.phase === undefined || normalizeKey(input.phase) !== 'apply')
|
|
190
|
+
return false;
|
|
191
|
+
if (input.workflow !== undefined && !isSddWorkflow(input.workflow))
|
|
192
|
+
return false;
|
|
193
|
+
return normalizeKey(agentWorkflow) === 'sdd:apply-progress';
|
|
194
|
+
}
|
|
168
195
|
function phaseSemanticMatchesFor(agent, input) {
|
|
169
196
|
const workflow = input.workflow !== undefined ? normalizeKey(input.workflow) : undefined;
|
|
170
197
|
if (workflow !== undefined && workflow !== 'sdd')
|
|
@@ -220,6 +247,9 @@ function normalizeText(value) {
|
|
|
220
247
|
function normalizeKey(value) {
|
|
221
248
|
return value.trim().toLowerCase();
|
|
222
249
|
}
|
|
250
|
+
function isSddWorkflow(workflow) {
|
|
251
|
+
return workflow?.trim().toLowerCase() === 'sdd';
|
|
252
|
+
}
|
|
223
253
|
function tokenize(value) {
|
|
224
254
|
const seen = new Set();
|
|
225
255
|
return value
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { canonicalAgentManifest, canonicalPromptContractVersion, canonicalSddSubagentNames } from './canonical-agent-manifest.js';
|
|
2
|
+
import { projectCanonicalAgentManifestToSeed } from './canonical-agent-projection.js';
|
|
3
|
+
export class AgentSeedUpgradeService {
|
|
4
|
+
agents;
|
|
5
|
+
history;
|
|
6
|
+
database;
|
|
7
|
+
constructor(dependencies) {
|
|
8
|
+
this.agents = dependencies.agents;
|
|
9
|
+
this.history = dependencies.history;
|
|
10
|
+
this.database = dependencies.database;
|
|
11
|
+
}
|
|
12
|
+
upgrade(input) {
|
|
13
|
+
if (!input.project.trim())
|
|
14
|
+
return validationFailure('Agent seed upgrade project is required');
|
|
15
|
+
if (input.scope !== 'project' && input.scope !== 'personal')
|
|
16
|
+
return validationFailure('Agent seed upgrade scope is invalid');
|
|
17
|
+
const seed = projectCanonicalAgentManifestToSeed();
|
|
18
|
+
const canonicalByName = new Map();
|
|
19
|
+
for (const agent of seed.agents)
|
|
20
|
+
canonicalByName.set(agent.name, agent);
|
|
21
|
+
for (const subagent of seed.subagents)
|
|
22
|
+
canonicalByName.set(subagent.name, subagent);
|
|
23
|
+
const source = input.source ?? 'boot-upgrade';
|
|
24
|
+
const summary = {
|
|
25
|
+
created: [],
|
|
26
|
+
upgraded: [],
|
|
27
|
+
noop: [],
|
|
28
|
+
overwritten: [],
|
|
29
|
+
errors: [],
|
|
30
|
+
skipped: false,
|
|
31
|
+
};
|
|
32
|
+
const expected = canonicalPromptContractVersion;
|
|
33
|
+
const transaction = this.database.transaction(() => {
|
|
34
|
+
for (const [name, definition] of canonicalByName) {
|
|
35
|
+
const outcome = this.upgradeOne(input.project, input.scope, name, definition, source, expected);
|
|
36
|
+
if (outcome.ok) {
|
|
37
|
+
switch (outcome.value.outcome) {
|
|
38
|
+
case 'created':
|
|
39
|
+
summary.created.push(name);
|
|
40
|
+
break;
|
|
41
|
+
case 'upgraded':
|
|
42
|
+
summary.upgraded.push(name);
|
|
43
|
+
break;
|
|
44
|
+
case 'overwrote-custom-instructions':
|
|
45
|
+
summary.overwritten.push(name);
|
|
46
|
+
break;
|
|
47
|
+
case 'noop':
|
|
48
|
+
summary.noop.push(name);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const failureOutcome = outcome.error.code === 'validation_failed' ? 'validation_failed' : 'db_error';
|
|
54
|
+
summary.errors.push({ agentName: name, outcome: failureOutcome, reason: outcome.error.message });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return summary;
|
|
58
|
+
});
|
|
59
|
+
if (!transaction.ok) {
|
|
60
|
+
return { ok: false, error: transaction.error };
|
|
61
|
+
}
|
|
62
|
+
return transaction;
|
|
63
|
+
}
|
|
64
|
+
hasDrift(input) {
|
|
65
|
+
const expected = input.expectedVersion ?? canonicalPromptContractVersion;
|
|
66
|
+
try {
|
|
67
|
+
const canonicalNames = [canonicalAgentManifest.defaultAgentName, ...canonicalSddSubagentNames];
|
|
68
|
+
const placeholders = canonicalNames.map(() => '?').join(', ');
|
|
69
|
+
const row = this.database.connection
|
|
70
|
+
.prepare(`
|
|
71
|
+
SELECT COUNT(*) AS stale_count
|
|
72
|
+
FROM agents
|
|
73
|
+
WHERE project = ? AND scope = ? AND name IN (${placeholders})
|
|
74
|
+
AND json_extract(adapters_json, '$.opencode.config.options.vgxnessPromptContractVersion') <> ?
|
|
75
|
+
`)
|
|
76
|
+
.get(input.project, input.scope, ...canonicalNames, expected);
|
|
77
|
+
return ok((row?.stale_count ?? 0) > 0);
|
|
78
|
+
}
|
|
79
|
+
catch (cause) {
|
|
80
|
+
return fail('Failed to detect agent seed drift', cause);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
upgradeOne(project, scope, name, definition, source, expected) {
|
|
84
|
+
const existing = this.agents.getByName(project, scope, name);
|
|
85
|
+
const fromVersion = existing.ok ? readPromptContractVersion(existing.value) : null;
|
|
86
|
+
if (existing.ok && fromVersion === expected && isByteEqualToCanonical(existing.value, definition)) {
|
|
87
|
+
return ok({ outcome: 'noop', fromVersion: expected });
|
|
88
|
+
}
|
|
89
|
+
const parentAgentId = 'parentAgentName' in definition ? this.resolveParentId(project, scope, definition.parentAgentName) : undefined;
|
|
90
|
+
if ('parentAgentName' in definition && parentAgentId === undefined) {
|
|
91
|
+
return validationFailure(`Unresolved parentAgentName: ${definition.parentAgentName}`);
|
|
92
|
+
}
|
|
93
|
+
const registerInput = toRegisterInput(project, scope, definition, parentAgentId);
|
|
94
|
+
const registered = this.agents.register(registerInput);
|
|
95
|
+
if (!registered.ok) {
|
|
96
|
+
this.appendHistory({
|
|
97
|
+
project,
|
|
98
|
+
scope,
|
|
99
|
+
agentName: name,
|
|
100
|
+
fromVersion,
|
|
101
|
+
toVersion: expected,
|
|
102
|
+
outcome: registered.error.code === 'validation_failed' ? 'validation_failed' : 'db_error',
|
|
103
|
+
reason: registered.error.message,
|
|
104
|
+
source,
|
|
105
|
+
});
|
|
106
|
+
return registered;
|
|
107
|
+
}
|
|
108
|
+
let outcome;
|
|
109
|
+
if (!existing.ok) {
|
|
110
|
+
outcome = 'created';
|
|
111
|
+
}
|
|
112
|
+
else if (fromVersion !== null && fromVersion !== expected) {
|
|
113
|
+
outcome = 'upgraded';
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
outcome = 'overwrote-custom-instructions';
|
|
117
|
+
}
|
|
118
|
+
this.appendHistory({
|
|
119
|
+
project,
|
|
120
|
+
scope,
|
|
121
|
+
agentName: name,
|
|
122
|
+
fromVersion,
|
|
123
|
+
toVersion: expected,
|
|
124
|
+
outcome,
|
|
125
|
+
reason: outcomeReason(outcome, fromVersion, expected, existing.ok),
|
|
126
|
+
source,
|
|
127
|
+
});
|
|
128
|
+
return ok({ outcome, fromVersion });
|
|
129
|
+
}
|
|
130
|
+
resolveParentId(project, scope, parentAgentName) {
|
|
131
|
+
const parent = this.agents.getByName(project, scope, parentAgentName);
|
|
132
|
+
if (!parent.ok || parent.value.mode !== 'agent')
|
|
133
|
+
return undefined;
|
|
134
|
+
return parent.value.id;
|
|
135
|
+
}
|
|
136
|
+
appendHistory(input) {
|
|
137
|
+
this.history.append({
|
|
138
|
+
project: input.project,
|
|
139
|
+
scope: input.scope,
|
|
140
|
+
agentName: input.agentName,
|
|
141
|
+
fromVersion: input.fromVersion,
|
|
142
|
+
toVersion: input.toVersion,
|
|
143
|
+
outcome: input.outcome,
|
|
144
|
+
reason: input.reason,
|
|
145
|
+
source: input.source,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function toRegisterInput(project, scope, definition, parentAgentId) {
|
|
150
|
+
const input = {
|
|
151
|
+
project,
|
|
152
|
+
scope,
|
|
153
|
+
mode: 'parentAgentName' in definition ? 'subagent' : 'agent',
|
|
154
|
+
name: definition.name,
|
|
155
|
+
description: definition.description,
|
|
156
|
+
instructions: definition.instructions,
|
|
157
|
+
};
|
|
158
|
+
if (definition.capabilities !== undefined)
|
|
159
|
+
input.capabilities = definition.capabilities;
|
|
160
|
+
if (definition.permissions !== undefined)
|
|
161
|
+
input.permissions = definition.permissions;
|
|
162
|
+
if (definition.memory !== undefined)
|
|
163
|
+
input.memory = definition.memory;
|
|
164
|
+
if (definition.workflows !== undefined)
|
|
165
|
+
input.workflows = definition.workflows;
|
|
166
|
+
if (definition.skills !== undefined)
|
|
167
|
+
input.skills = definition.skills;
|
|
168
|
+
if (definition.adapters !== undefined)
|
|
169
|
+
input.adapters = definition.adapters;
|
|
170
|
+
if (parentAgentId !== undefined)
|
|
171
|
+
input.parentAgentId = parentAgentId;
|
|
172
|
+
return input;
|
|
173
|
+
}
|
|
174
|
+
function isByteEqualToCanonical(existing, definition) {
|
|
175
|
+
if (existing.description !== definition.description)
|
|
176
|
+
return false;
|
|
177
|
+
if (existing.instructions.value !== definition.instructions.value)
|
|
178
|
+
return false;
|
|
179
|
+
if (!adaptersEqual(existing.adapters, definition.adapters ?? {}))
|
|
180
|
+
return false;
|
|
181
|
+
if (!arraysEqual(existing.capabilities, definition.capabilities ?? []))
|
|
182
|
+
return false;
|
|
183
|
+
if (!arraysEqual(existing.workflows, definition.workflows ?? []))
|
|
184
|
+
return false;
|
|
185
|
+
if (!arraysEqual(existing.skills, definition.skills ?? []))
|
|
186
|
+
return false;
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
function adaptersEqual(a, b) {
|
|
190
|
+
return JSON.stringify(a ?? {}) === JSON.stringify(b ?? {});
|
|
191
|
+
}
|
|
192
|
+
function arraysEqual(a, b) {
|
|
193
|
+
if (a.length !== b.length)
|
|
194
|
+
return false;
|
|
195
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
196
|
+
if (a[i] !== b[i])
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
function readPromptContractVersion(agent) {
|
|
202
|
+
const opencode = agent.adapters?.opencode;
|
|
203
|
+
if (opencode === undefined)
|
|
204
|
+
return null;
|
|
205
|
+
const options = opencode.config?.options;
|
|
206
|
+
const value = options?.vgxnessPromptContractVersion;
|
|
207
|
+
if (typeof value !== 'number' || !Number.isInteger(value))
|
|
208
|
+
return null;
|
|
209
|
+
return value;
|
|
210
|
+
}
|
|
211
|
+
function outcomeReason(outcome, fromVersion, toVersion, existed) {
|
|
212
|
+
if (outcome === 'created')
|
|
213
|
+
return `created canonical row at v${toVersion}`;
|
|
214
|
+
if (outcome === 'upgraded')
|
|
215
|
+
return `upgraded v${fromVersion ?? 'unknown'} -> v${toVersion}`;
|
|
216
|
+
if (outcome === 'overwrote-custom-instructions')
|
|
217
|
+
return `overwrote customized row (was v${fromVersion ?? 'unknown'}) with v${toVersion} canonical`;
|
|
218
|
+
return existed ? `noop at v${toVersion}` : `noop at v${toVersion}`;
|
|
219
|
+
}
|
|
220
|
+
function ok(value) {
|
|
221
|
+
return { ok: true, value };
|
|
222
|
+
}
|
|
223
|
+
function validationFailure(message) {
|
|
224
|
+
return { ok: false, error: { code: 'validation_failed', message } };
|
|
225
|
+
}
|
|
226
|
+
function fail(message, cause) {
|
|
227
|
+
const error = { code: 'validation_failed', message };
|
|
228
|
+
if (cause !== undefined)
|
|
229
|
+
error.cause = cause;
|
|
230
|
+
return { ok: false, error };
|
|
231
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { AgentSeedUpgradeService } from './agent-seed-upgrade-service.js';
|
|
2
|
+
import { AgentRepository } from './repositories/agents.js';
|
|
3
|
+
import { AgentSeedHistoryRepository } from './repositories/agent-seed-history.js';
|
|
4
|
+
import { canonicalAgentManifest } from './canonical-agent-manifest.js';
|
|
5
|
+
const skipEnvVar = 'VGXNESS_SKIP_AGENT_SEED_AUTO_UPGRADE';
|
|
6
|
+
export function runBootAgentSeedUpgrade(database, env = process.env, project = canonicalAgentManifest.project, scope = canonicalAgentManifest.scope) {
|
|
7
|
+
if (isOptOut(env)) {
|
|
8
|
+
return { ok: true, skipped: true, created: 0, upgraded: 0, overwritten: 0, noop: 0, errors: 0 };
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const service = new AgentSeedUpgradeService({
|
|
12
|
+
agents: new AgentRepository(database),
|
|
13
|
+
history: new AgentSeedHistoryRepository(database),
|
|
14
|
+
database,
|
|
15
|
+
});
|
|
16
|
+
const result = service.upgrade({ project, scope, source: 'boot-upgrade' });
|
|
17
|
+
if (!result.ok) {
|
|
18
|
+
const message = `boot-upgrade failed: ${result.error.message} (code=${result.error.code})`;
|
|
19
|
+
process.stderr.write(`[vgxness] ${message}\n`);
|
|
20
|
+
return { ok: false, skipped: false, created: 0, upgraded: 0, overwritten: 0, noop: 0, errors: 1, message };
|
|
21
|
+
}
|
|
22
|
+
const value = result.value;
|
|
23
|
+
const touched = value.created.length + value.upgraded.length + value.overwritten.length + value.errors.length;
|
|
24
|
+
if (touched > 0) {
|
|
25
|
+
const parts = [];
|
|
26
|
+
if (value.created.length > 0)
|
|
27
|
+
parts.push(`created ${value.created.length}`);
|
|
28
|
+
if (value.upgraded.length > 0)
|
|
29
|
+
parts.push(`upgraded ${value.upgraded.length}`);
|
|
30
|
+
if (value.overwritten.length > 0)
|
|
31
|
+
parts.push(`overwrote ${value.overwritten.length}`);
|
|
32
|
+
if (value.errors.length > 0)
|
|
33
|
+
parts.push(`errors ${value.errors.length}`);
|
|
34
|
+
process.stderr.write(`[vgxness] boot-upgrade: ${parts.join(', ')}\n`);
|
|
35
|
+
for (const error of value.errors) {
|
|
36
|
+
process.stderr.write(`[vgxness] boot-upgrade: ${error.agentName} ${error.outcome}: ${error.reason}\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
ok: true,
|
|
41
|
+
skipped: false,
|
|
42
|
+
created: value.created.length,
|
|
43
|
+
upgraded: value.upgraded.length,
|
|
44
|
+
overwritten: value.overwritten.length,
|
|
45
|
+
noop: value.noop.length,
|
|
46
|
+
errors: value.errors.length,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (cause) {
|
|
50
|
+
const detail = cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause);
|
|
51
|
+
const message = `boot-upgrade threw: ${detail}`;
|
|
52
|
+
process.stderr.write(`[vgxness] ${message}\n`);
|
|
53
|
+
return { ok: false, skipped: false, created: 0, upgraded: 0, overwritten: 0, noop: 0, errors: 1, message };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function isOptOut(env) {
|
|
57
|
+
const value = env[skipEnvVar];
|
|
58
|
+
return value === '1' || value === 'true';
|
|
59
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { canonicalBehaviorContractVersion } from '../behavior/behavior-contract-manifest.js';
|
|
2
2
|
export const canonicalDefaultAgentName = 'vgxness-manager';
|
|
3
|
-
export const
|
|
3
|
+
export const canonicalOpenCodeDefaultModel = 'openai/gpt-5.5';
|
|
4
|
+
export const canonicalOpenCodeManagerReasoningEffort = 'high';
|
|
5
|
+
export const canonicalPromptContractVersion = 9;
|
|
4
6
|
export const canonicalSddSubagentNames = [
|
|
5
7
|
'vgxness-sdd-explore',
|
|
6
8
|
'vgxness-sdd-propose',
|
|
@@ -76,13 +78,13 @@ function managerDefinition() {
|
|
|
76
78
|
builtIn: true,
|
|
77
79
|
name: canonicalDefaultAgentName,
|
|
78
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.',
|
|
79
|
-
instructions: { kind: 'inline', value:
|
|
81
|
+
instructions: { kind: 'inline', value: registryManagerInstructionsV9 },
|
|
80
82
|
capabilities: ['sdd-orchestration', 'agent-routing', 'mcp-coordination', 'project-local-automation'],
|
|
81
83
|
permissions: { read: 'allow', edit: 'ask', shell: 'ask', git: 'ask', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' },
|
|
82
84
|
memory: { scopes: ['project'] },
|
|
83
85
|
workflows: ['explore', 'quickfix', 'plan', 'build', 'debug', 'sdd', 'agent-seeding', 'opencode-install'],
|
|
84
86
|
skills: ['vgxness-sdd-manager'],
|
|
85
|
-
adapters: { opencode: { model:
|
|
87
|
+
adapters: { opencode: { model: canonicalOpenCodeDefaultModel, config: { options: { reasoningEffort: canonicalOpenCodeManagerReasoningEffort, vgxnessPromptContractVersion: canonicalPromptContractVersion, vgxnessBehaviorContractVersion: canonicalBehaviorContractVersion }, permission: { task: createCanonicalOpenCodeSddTaskPermissions() } } } },
|
|
86
88
|
providerSupport: commonSupport(),
|
|
87
89
|
};
|
|
88
90
|
}
|
|
@@ -101,7 +103,7 @@ function subagentDefinition(name) {
|
|
|
101
103
|
memory: { scopes: ['project'] },
|
|
102
104
|
workflows: data.workflows,
|
|
103
105
|
skills: data.skills,
|
|
104
|
-
adapters: { opencode: { model:
|
|
106
|
+
adapters: { opencode: { model: canonicalOpenCodeDefaultModel, config: { hidden: true, options: { vgxnessPromptContractVersion: canonicalPromptContractVersion, vgxnessBehaviorContractVersion: canonicalBehaviorContractVersion } } } },
|
|
105
107
|
providerSupport: commonSupport(),
|
|
106
108
|
};
|
|
107
109
|
}
|
|
@@ -114,12 +116,17 @@ export function createCanonicalOpenCodeSddSubagentPrompt(name) {
|
|
|
114
116
|
const contract = subagentData[name].phaseContract;
|
|
115
117
|
return `${common}\n\nPhase contract: ${contract}\n\nSDD governance v1: SDD artifact acceptance is human-only. Do not mark, describe, or persist generated phase output as accepted unless the user explicitly accepts it or an MCP acceptance record shows a human actor. Before advancing phases, use VGXNESS MCP readiness/status tools so draft, rejected, superseded, or legacy artifacts are not treated as accepted prerequisites. For risky VGX-managed side effects, use VGXNESS run preflight/reporting and include runId, phase, and agent context when available. OpenCode native/provider tools are audit-only and non-hard-blocking in governance v1; do not claim they are hard-blocked by OpenCode config.\n\nProvider-native daily progression: daily SDD progression happens inside OpenCode through conversation, VGXNESS MCP, and hidden SDD subagents. Do not instruct the user to run terminal SDD phase commands for normal daily flow. Return phase output, decisions, changed files, and evidence so the manager can persist artifacts and advance through MCP. Preserve confirmation/preflight requirements for apply, verify, init, archive, edits, shell, git, provider-tool, secrets, destructive, privileged, or ambiguous operations.`;
|
|
116
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Provider runtime prompt for generated provider managers.
|
|
121
|
+
* This feeds the OpenCode default config and Claude generated agent files; it is
|
|
122
|
+
* intentionally separate from registry/seed instructions below.
|
|
123
|
+
*/
|
|
117
124
|
export const canonicalOpenCodeManagerPrompt = `# VGXNESS Manager - compact SDD orchestrator
|
|
118
125
|
|
|
119
|
-
Bind only to the primary \`vgxness-manager\` agent. Executor agents
|
|
126
|
+
Bind only to the primary \`vgxness-manager\` agent. Executor agents use their own prompts.
|
|
120
127
|
|
|
121
128
|
## Role
|
|
122
|
-
Coordinate SDD; keep chat thin, use VGXNESS MCP as durable state, delegate to the smallest exact hidden SDD subagent,
|
|
129
|
+
Coordinate SDD; keep chat thin, use VGXNESS MCP as durable state, delegate to the smallest exact hidden SDD subagent, synthesize evidence. Coach while coordinating: teach briefly, explain practical tradeoffs, stay realistic about risk/effort/unknowns, respectfully challenge weak assumptions, keep the user comfortable and in control, avoid lectures or unnecessary verbosity.
|
|
123
130
|
|
|
124
131
|
## Non-negotiable governance
|
|
125
132
|
- SDD artifact acceptance is human-only. Never infer or fabricate acceptance from generated output, subagent/model output, file presence, confidence, or legacy artifacts. Treat draft/rejected/superseded/stale/unaccepted artifacts as not accepted until a human acceptance record exists.
|
|
@@ -127,9 +134,8 @@ Coordinate SDD; keep chat thin, use VGXNESS MCP as durable state, delegate to th
|
|
|
127
134
|
- 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 context when available. If approval/block is required, stop; do not invent approval.
|
|
128
135
|
- Direct human acceptance of an exact SDD artifact via \`vgxness_sdd_accept_artifact\` is not a generic SDD write for manager routing: do not call \`vgxness_run_preflight\` solely for that acceptance when the user explicitly accepted the exact project/change/phase artifact, \`acceptedBy.type\` is \`"human"\`, \`acceptedBy.id\` is non-empty, and status/readiness confirms the artifact is eligible. This shortcut applies only to \`vgxness_sdd_accept_artifact\`, not \`vgxness_sdd_save_artifact\`, edits, shell/tests, git, provider config, memory writes, external paths, secrets, destructive/privileged/ambiguous operations.
|
|
129
136
|
- OpenCode native/provider tools are governance-v1 audit-only/non-hard-blocking. Report warnings; do not say native OpenCode tools are hard-blocked by config.
|
|
130
|
-
- Do not mutate provider/global OpenCode config
|
|
131
|
-
- Do not
|
|
132
|
-
- Do not change model or reasoning effort.
|
|
137
|
+
- Do not mutate provider/global OpenCode config. Do not write to \`openspec/\`. 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 allowed.
|
|
138
|
+
- Do not change provider model/reasoning config unless explicitly requested.
|
|
133
139
|
|
|
134
140
|
## Flexible governance routing
|
|
135
141
|
Use the lightest safe path: Tier 0-2 direct; Tier 3 preflight/explicit validation; Tier 4 formal SDD for governance, permission model, SDD acceptance, architecture/security, or cross-surface behavior. Provider status/doctor/preview/handoff are read-only audit-only; provider config writes stay gated.
|
|
@@ -138,26 +144,41 @@ Use the lightest safe path: Tier 0-2 direct; Tier 3 preflight/explicit validatio
|
|
|
138
144
|
Daily SDD happens inside OpenCode through conversation, VGXNESS MCP, and hidden SDD subagents. Do not tell users to run terminal SDD phase commands for normal flow. CLI is an escape hatch for bootstrap, doctor, recovery, setup gaps, or explicit request.
|
|
139
145
|
|
|
140
146
|
## MCP playbook
|
|
141
|
-
- For starting, resuming, or recovering context: prefer \`vgxness_context_cockpit
|
|
142
|
-
- SDD artifacts: list/read with \`vgxness_sdd_get_artifact\`/\`vgxness_sdd_list_artifacts\`;
|
|
143
|
-
- 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
|
|
147
|
+
- 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.
|
|
148
|
+
- SDD artifacts: guide state with \`vgxness_sdd_next\`/\`vgxness_sdd_cockpit\`; list/read with \`vgxness_sdd_get_artifact\`/\`vgxness_sdd_list_artifacts\`; prefer \`payloadMode: "compact"\` so the primary context stays clean; use verbose only when required, preferably inside the delegated phase subagent. Save with \`vgxness_sdd_save_artifact\` only after the appropriate flow. Use \`vgxness_sdd_reopen_artifact\` only for rejected artifacts returning to draft, with explicit human actor/audit context. SDD artifacts are not generic memory.
|
|
149
|
+
- 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.
|
|
144
150
|
- 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.
|
|
145
151
|
- Agents/profile/payloads: resolve exact phase with \`vgxness_agent_resolve\`. \`vgxness_agent_activate\`, \`vgxness_opencode_manager_payload\`, and \`vgxness_skill_payload\` are preview context only; agent_activate does not execute a provider or write provider config. Use \`vgxness_manager_profile_get\` before behavior changes; \`vgxness_manager_profile_set\` requires explicit human authorization.
|
|
146
|
-
- Runs: use \`vgxness_run_start\`/\`vgxness_run_list\`/\`vgxness_run_get\` for
|
|
147
|
-
- Provider diagnostics: \`vgxness_provider_status
|
|
152
|
+
- 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
|
|
153
|
+
- Provider diagnostics: \`vgxness_provider_status\`/\`vgxness_provider_doctor\` are read-only reports.
|
|
148
154
|
|
|
149
155
|
## Minimum flows
|
|
150
156
|
- Simple answer: inline; memory only for prior context; no run by default.
|
|
151
|
-
- Proposal/spec/design/tasks: status/next -> readiness ->
|
|
152
|
-
- Apply/verify: require prerequisites ->
|
|
153
|
-
- Config/provider/prompt change: inspect manager/profile or payload first; persistent changes
|
|
157
|
+
- Proposal/spec/design/tasks: status/next -> readiness -> prerequisites -> exact subagent -> delegate -> persist by governance.
|
|
158
|
+
- Apply/verify: require prerequisites -> artifacts -> exact subagent -> start/recover run -> preflight writes/shell/git/tests -> delegate -> checkpoint -> save -> finalize.
|
|
159
|
+
- Config/provider/prompt change: inspect manager/profile or payload first; persistent changes need explicit human authorization.
|
|
160
|
+
- Recovery: MCP first. Continue: use \`vgxness_sdd_continue\`; read-only/advisory: no provider execution, run creation, artifact mutation, provider config/openspec writes, or acceptance/apply-progress bypass. CLI \`vgxness sdd continue\` is human fallback only. \`vgxness resume --project\` is for candidate runs; \`vgxness code sdd ... --draft-run\` is a planning-only path, never for apply-progress.
|
|
154
161
|
|
|
155
162
|
## Delegation thresholds
|
|
156
163
|
Inline only small decisions, 1-3 file reads, status commands, and atomic one-file mechanical edits. Delegate broad exploration, substantial implementation, writes with analysis/new logic, and execution-heavy verification. Never delegate to unknown agents; use exact SDD phase mapping.
|
|
157
164
|
|
|
158
165
|
## Output
|
|
159
166
|
Be concise: delegated work, results, files/decisions, evidence/tests, risks, next step.`;
|
|
160
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Registry/seed instructions for the manager agent definition.
|
|
169
|
+
* These feed the canonical manifest, checked-in seed, boot upgrade, registry
|
|
170
|
+
* render baselines, and manager profile overlay baselines; they are
|
|
171
|
+
* intentionally distinct from the provider runtime prompt above.
|
|
172
|
+
*/
|
|
173
|
+
const registryManagerInstructionsV9 = [
|
|
174
|
+
'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.',
|
|
175
|
+
'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.',
|
|
176
|
+
'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 accepted phase output with sdd_save_artifact, 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.',
|
|
177
|
+
'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.',
|
|
178
|
+
'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.',
|
|
179
|
+
'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, and vgxness code sdd ... --draft-run is planning-only.',
|
|
180
|
+
'OpenCode native/provider tools are governance-v1 audit-only/non-hard-blocking; report warnings, never say they are hard-blocked by config.',
|
|
181
|
+
].join(' ');
|
|
161
182
|
const subagentData = {
|
|
162
183
|
'vgxness-sdd-explore': { seedDescription: 'Investigates codebase context and identifies options before proposals.', seedInstructions: 'You are the explore phase executor, not the orchestrator. Do not delegate. Explore repository evidence for the requested SDD change. Do not implement code changes. Return concise findings, risks, and recommended next artifacts.', capabilities: ['sdd-exploration', 'codebase-research', 'discovery'], permissions: { read: 'allow', edit: 'deny', shell: 'ask', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:explore'], skills: ['vgxness-sdd-explore'], phaseContract: 'Investigate codebase context, constraints, options, and risks. Do not implement code changes. Return findings and recommended next artifacts.' },
|
|
163
184
|
'vgxness-sdd-propose': { seedDescription: 'Creates focused change proposals from exploration findings.', seedInstructions: 'You are the proposal phase executor, not the orchestrator. Do not delegate. Create a focused SDD proposal from exploration evidence. Do not implement code changes. Identify scope, tradeoffs, non-goals, and acceptance direction.', capabilities: ['sdd-proposal', 'proposal-planning', 'scope-definition'], permissions: { read: 'allow', edit: 'deny', shell: 'deny', git: 'deny', memory: 'allow', 'provider-tool': 'deny', secrets: 'deny' }, workflows: ['sdd:proposal'], skills: ['vgxness-sdd-proposal'], phaseContract: 'Create or refine a focused SDD proposal from exploration evidence. Do not implement code changes. Include scope, tradeoffs, non-goals, and acceptance direction.' },
|