vgxness 1.0.5 → 1.1.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.
- package/README.md +121 -13
- package/dist/cli/bun-bin.js +40 -0
- package/dist/cli/commands/setup-dispatcher.js +14 -6
- package/dist/cli/dispatcher.js +9 -1
- package/dist/cli/sdd-renderer.js +8 -4
- package/dist/code/runtime/project-detection.js +13 -3
- package/dist/code/tools/read-only-executor.js +7 -3
- package/dist/mcp/doctor.js +10 -4
- package/dist/memory/sqlite/database.js +128 -39
- package/dist/verification/verification-plan-service.js +2 -2
- package/docs/cli.md +132 -26
- package/docs/funcionamiento-del-sistema.md +4 -6
- package/package.json +19 -11
package/README.md
CHANGED
|
@@ -10,9 +10,114 @@ OpenCode is the primary supported provider. Other providers remain preview/manua
|
|
|
10
10
|
|
|
11
11
|
## Requirements
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- A platform supported by `
|
|
13
|
+
- Bun >= 1.3.14 for the installed `vgxness`/`vgx` CLI/MCP runtime and repository verification
|
|
14
|
+
- Node.js >= 22 for repository development, build, test, and helper-script tooling
|
|
15
|
+
- A platform supported by Bun SQLite (`bun:sqlite`) for runtime storage
|
|
16
|
+
|
|
17
|
+
Bun is the canonical installed runtime and verification tool. Node remains development/build/test tooling for TypeScript, `node:test`, and selected helper scripts; package consumer metadata (`bin` and `files`) remains part of the npm install contract.
|
|
18
|
+
|
|
19
|
+
### Bun-first staged toolchain
|
|
20
|
+
|
|
21
|
+
Use Bun for development verification and CI parity:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun install --frozen-lockfile
|
|
25
|
+
bun run check:bun-lock
|
|
26
|
+
bun run verify:typecheck
|
|
27
|
+
bun run verify:test
|
|
28
|
+
bun run verify:bun-sqlite
|
|
29
|
+
bun run verify:package
|
|
30
|
+
bun run package:bun:evidence -- --require-pass
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun run verify
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Package evidence is Bun-only after the npm publication bridge retirement:
|
|
38
|
+
|
|
39
|
+
| Area | Current owner | Why |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| Typecheck, tests, Bun SQLite probe, package evidence | Bun | This is the canonical CI verification path. |
|
|
42
|
+
| Package artifact and isolated install smoke | `bun run package:bun:evidence -- --require-pass` | It creates/inspects the artifact, validates package contents, installs in an isolated Bun environment, checks both CLI bins, and records Bun runtime identity. |
|
|
43
|
+
| Installed CLI runtime | Bun >=1.3.14 | Published `vgxness`/`vgx` execute `dist/cli/bun-bin.js`, which records optional runtime evidence and then imports the CLI. |
|
|
44
|
+
| Lockfile review | `bun.lock` | The npm bridge lockfile has been retired; do not treat that as dropping npm consumer installability. |
|
|
45
|
+
|
|
46
|
+
Do not remove npm package metadata, `bin`, or `files` as part of bridge cleanup; those remain the package consumer contract. The product runtime engine is `engines.bun`, not `engines.node`.
|
|
47
|
+
|
|
48
|
+
When `package.json` dependency specifiers change, refresh and review `bun.lock` intentionally. To check manifest/lock drift without mutating `node_modules`, run:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bun run check:bun-lock
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The manual compatibility probe remains useful when diagnosing Bun/package-manager behavior:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm run probe:bun
|
|
58
|
+
npm run probe:bun -- --yes # mutates dependencies only after explicit consent
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Runtime SQLite readiness is proven only with `bun:sqlite`. `bun run verify:bun-sqlite` copies the source migrations into a temporary directory, applies them against a temporary database, checks foreign keys, busy timeout, FTS/search, transaction rollback, integrity, and cleanup. Node.js remains development/build/test tooling, but real local SQLite storage is supported through the Bun runtime path.
|
|
62
|
+
|
|
63
|
+
#### Bun package evidence
|
|
64
|
+
|
|
65
|
+
To collect diagnostic package artifact and isolated install-smoke evidence without publishing, run:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
bun run package:bun:evidence
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Diagnostic mode may emit `status: incompatible` and still exit `0` so maintainers can inspect JSON. For release-readiness, require a passing result explicitly:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
bun run package:bun:evidence -- --require-pass
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The probe is the authoritative release evidence path for package contents. It does not invoke registry publication commands, writes optional JSON only where requested, records `publicationAttempted: false`, and reports `releaseReadiness` diagnostics when evaluating the gate.
|
|
78
|
+
|
|
79
|
+
It protects:
|
|
80
|
+
|
|
81
|
+
- package metadata, `files`, `bin`, license, Bun engine, README/LICENSE, docs, migrations, and shipped seed assets;
|
|
82
|
+
- absence of workspace-only content such as `src/`, `test/`, `.opencode/`, `openspec/`, source maps, SQLite/database files, and OS junk;
|
|
83
|
+
- both installed commands: `vgxness --help` and `vgx --help`.
|
|
84
|
+
|
|
85
|
+
Release-candidate checklist, still non-publishing:
|
|
86
|
+
|
|
87
|
+
1. `bun install --frozen-lockfile` completes on a clean checkout.
|
|
88
|
+
2. `bun run check:bun-lock` passes.
|
|
89
|
+
3. `bun run verify:typecheck`, `bun run verify:test`, and `bun run verify:bun-sqlite` pass.
|
|
90
|
+
4. `bun run package:bun:evidence -- --require-pass` passes on supported CI OSes.
|
|
91
|
+
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
|
+
6. Version, release notes, proprietary license boundary, and rollback criteria are reviewed.
|
|
93
|
+
7. Publishing remains a separate explicit human-approved process.
|
|
94
|
+
|
|
95
|
+
This checklist does **not** run `npm publish`, `bun publish`, registry dry-runs that contact a registry, registry token use, provenance upload, release creation, or dist-tag mutation.
|
|
96
|
+
|
|
97
|
+
#### Temporary rollback if Bun package evidence misses a release regression
|
|
98
|
+
|
|
99
|
+
Rollback is release-impacting and temporary. Use it only when Bun package evidence misses a package regression, downstream install verification fails in a way Bun did not catch, or a release candidate needs short-lived npm bridge validation while the Bun evidence gap is investigated.
|
|
100
|
+
|
|
101
|
+
Restore these bridge elements from the previous known-good main commit:
|
|
102
|
+
|
|
103
|
+
- `package-lock.json`
|
|
104
|
+
- package scripts: `prepack`, `package:release-check`, `package:dry-run`, and `package:smoke:install`
|
|
105
|
+
- deleted helper scripts: `scripts/validate-package-release.mjs` and `scripts/smoke-tarball-install.mjs`
|
|
106
|
+
- npm validation wiring and tests that enforced the bridge
|
|
107
|
+
- the `.github/workflows/node22.yml` `npm-publication-bridge` job and its artifact/install-smoke steps
|
|
108
|
+
|
|
109
|
+
Do not publish during rollback verification unless a separate explicit approval covers publication. Follow up with an investigation or SDD change before retiring the bridge again.
|
|
110
|
+
|
|
111
|
+
### Legacy Bun probe commands
|
|
112
|
+
|
|
113
|
+
These commands are retained for compatibility investigation, not as a replacement for `bun run verify`:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm run check:bun:typecheck
|
|
117
|
+
bun run typecheck
|
|
118
|
+
bun run build
|
|
119
|
+
bun run package:bun:evidence
|
|
120
|
+
```
|
|
16
121
|
|
|
17
122
|
## Install globally
|
|
18
123
|
|
|
@@ -101,25 +206,28 @@ Rollback validates the backup, creates a pre-rollback backup of the current targ
|
|
|
101
206
|
|
|
102
207
|
Common issues:
|
|
103
208
|
|
|
104
|
-
-
|
|
105
|
-
-
|
|
209
|
+
- Bun < 1.3.14: upgrade Bun and reinstall.
|
|
210
|
+
- Node < 22 while developing from source: upgrade Node for repository tooling.
|
|
211
|
+
- Bun SQLite failure: include the Bun version, OS/CPU, whether migrations applied, and the failing `verify:bun-sqlite` output.
|
|
106
212
|
- JSONC or malformed OpenCode config: convert to valid JSON or resolve manually; VGXNESS refuses unsafe rewrites.
|
|
107
213
|
- Existing `mcp.vgxness`: inspect the existing entry before rerunning setup; VGXNESS refuses overwrite by default.
|
|
108
214
|
|
|
109
215
|
## Release verification matrix
|
|
110
216
|
|
|
111
|
-
CI
|
|
217
|
+
CI verifies Bun on macOS, Linux, and Windows:
|
|
112
218
|
|
|
113
219
|
```bash
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
220
|
+
bun install --frozen-lockfile
|
|
221
|
+
bun run check:bun-lock
|
|
222
|
+
bun run verify:typecheck
|
|
223
|
+
bun run verify:test
|
|
224
|
+
bun run verify:bun-sqlite
|
|
225
|
+
bun run package:bun:evidence -- --require-pass
|
|
120
226
|
```
|
|
121
227
|
|
|
122
|
-
|
|
228
|
+
Run `bun run check:bun-lock` when dependency specifiers or `bun.lock` changed. It is read-only and helps review lock drift without installing dependencies.
|
|
229
|
+
|
|
230
|
+
Do not publish from CI. Publication or registry dry-run checks require separate explicit approval outside this verification path.
|
|
123
231
|
|
|
124
232
|
## Uninstall
|
|
125
233
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { writeFileSync } from 'node:fs';
|
|
3
|
+
import { basename } from 'node:path';
|
|
4
|
+
writeRuntimeEvidence();
|
|
5
|
+
await import('./index.js');
|
|
6
|
+
function writeRuntimeEvidence() {
|
|
7
|
+
const evidencePath = process.env.VGXNESS_RUNTIME_EVIDENCE_FILE;
|
|
8
|
+
if (evidencePath === undefined || evidencePath.length === 0)
|
|
9
|
+
return;
|
|
10
|
+
const bunVersion = globalThis.Bun?.version;
|
|
11
|
+
const argv0 = process.argv[0] ?? null;
|
|
12
|
+
const entrypoint = process.argv[1] ?? null;
|
|
13
|
+
const binName = entrypoint === null ? null : basename(entrypoint).replace(/\.cmd$/i, '');
|
|
14
|
+
const command = process.argv.slice(2);
|
|
15
|
+
const evidence = {
|
|
16
|
+
runtime: 'bun',
|
|
17
|
+
bunVersion: typeof bunVersion === 'string' && bunVersion.length > 0 ? bunVersion : null,
|
|
18
|
+
execPath: process.execPath,
|
|
19
|
+
argv0,
|
|
20
|
+
entrypoint,
|
|
21
|
+
binName,
|
|
22
|
+
argv: process.argv,
|
|
23
|
+
platform: {
|
|
24
|
+
os: process.platform,
|
|
25
|
+
arch: process.arch,
|
|
26
|
+
},
|
|
27
|
+
commandContext: {
|
|
28
|
+
command,
|
|
29
|
+
commandName: command[0] ?? null,
|
|
30
|
+
isHelp: command.includes('--help') || command.includes('-h'),
|
|
31
|
+
cwd: process.cwd(),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
try {
|
|
35
|
+
writeFileSync(evidencePath, `${JSON.stringify(evidence, null, 2)}\n`, 'utf8');
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Runtime evidence is diagnostic only; do not block the CLI if the path is invalid.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -318,16 +318,24 @@ export function promptLineExport(environment, prompt) {
|
|
|
318
318
|
export function renderSetupPlanForHumansExport(plan) {
|
|
319
319
|
return renderSetupPlanForHumans(plan);
|
|
320
320
|
}
|
|
321
|
-
export
|
|
321
|
+
export function resolveInitDispatchMode(parsed, environment) {
|
|
322
322
|
if (parsed.flags.plan === true || parsed.flags.json === true)
|
|
323
|
-
return
|
|
323
|
+
return 'setup-plan';
|
|
324
324
|
if (parsed.flags.yes === true)
|
|
325
|
-
return
|
|
326
|
-
|
|
327
|
-
|
|
325
|
+
return 'setup-apply';
|
|
326
|
+
return environment.stdin?.isTTY === true && environment.stdout?.isTTY === true ? 'setup-tui' : 'setup-plan';
|
|
327
|
+
}
|
|
328
|
+
export async function runInitCommand(parsed, environment) {
|
|
329
|
+
return runInitCommandWithSetupTui(parsed, environment, runSetupTuiCommand);
|
|
330
|
+
}
|
|
331
|
+
export async function runInitCommandWithSetupTui(parsed, environment, setupTui) {
|
|
332
|
+
const mode = resolveInitDispatchMode(parsed, environment);
|
|
333
|
+
if (mode === 'setup-plan')
|
|
328
334
|
return runSetupPlanCommand(parsed, environment);
|
|
335
|
+
if (mode === 'setup-apply')
|
|
336
|
+
return runSetupApplyCommand({ ...parsed, flags: { ...parsed.flags, yes: true } }, environment);
|
|
329
337
|
const project = optionalStringFlag(parsed.flags, 'project');
|
|
330
|
-
return
|
|
338
|
+
return setupTui(environment, project === undefined ? undefined : { project });
|
|
331
339
|
}
|
|
332
340
|
export async function runSetupTuiCommand(environment, input) {
|
|
333
341
|
if (!canRunInteractiveTui(environment.stdin, environment.stdout))
|
package/dist/cli/dispatcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Thin CLI router -- all command handlers live in src/cli/commands/*.ts
|
|
2
2
|
import { isWorkflowId } from '../workflows/schema.js';
|
|
3
|
-
import { databasePathFor, parseArgs } from './cli-flags.js';
|
|
3
|
+
import { databasePathFor, parseArgs, requiredFlag } from './cli-flags.js';
|
|
4
4
|
import { okText, usageFailure, visibleHelpText } from './cli-help.js';
|
|
5
5
|
import { openCliDatabase, resultFailure } from './cli-helpers.js';
|
|
6
6
|
import { runAgentCommand, runApprovalsCommand, runCodeCliCommand, runDashboardCommand, runDashboardInteractiveCommand, runDefaultInteractiveEntrypoint, runDoctorAliasCommand, runInitCommand, runMcpDoctorCommand, runMcpInstallCommand, runMcpSetupCommand, runMemoryCommand, runMemoryImportCommand, runOpenCodeCommand, runOrchestratorCommand, runPermissionsCommand, runRunsCommand, runSddCommand, runSetupApplyCommand, runSetupLifecycleCommand, runSetupPlanCommand, runSetupRollbackCommand, runSkillCommand, runSubagentCommand, runVerificationPlanCommand, runVerificationReportCommand, runWorkflowExecuteCommand, runWorkflowPreviewCommand, runWorkflowRunCommand, } from './commands/index.js';
|
|
@@ -25,6 +25,14 @@ export function dispatchCli(argv, environment) {
|
|
|
25
25
|
return runVerificationPlanCommand(command, parsed);
|
|
26
26
|
if (isWorkflowId(area) && command === 'preview')
|
|
27
27
|
return runWorkflowPreviewCommand(area, parsed);
|
|
28
|
+
if (area === 'orchestrator' && command === 'preview') {
|
|
29
|
+
const project = requiredFlag(parsed.flags, 'project');
|
|
30
|
+
if (!project.ok)
|
|
31
|
+
return resultFailure(project);
|
|
32
|
+
const intent = requiredFlag(parsed.flags, 'intent');
|
|
33
|
+
if (!intent.ok)
|
|
34
|
+
return resultFailure(intent);
|
|
35
|
+
}
|
|
28
36
|
if (area === 'memory' && command === 'import')
|
|
29
37
|
return runMemoryImportCommand(parsed, environment);
|
|
30
38
|
const selectedDatabasePath = databasePathFor(parsed.flags, environment);
|
package/dist/cli/sdd-renderer.js
CHANGED
|
@@ -2,15 +2,19 @@ import { normalizeSddArtifact, sddPhases } from '../sdd/schema.js';
|
|
|
2
2
|
export function renderSddStatus(input) {
|
|
3
3
|
const missing = input.status.phases.filter((phase) => !phase.present).map((phase) => phase.topicKey);
|
|
4
4
|
const blockers = input.status.phases.filter((phase) => phase.present && phase.accepted !== true);
|
|
5
|
+
const complete = input.status.phases.length > 0 && input.status.phases.every((phase) => phase.present && phase.accepted === true);
|
|
6
|
+
const statusLabel = complete ? 'complete' : input.status.nextReadyPhase === undefined ? 'blocked' : 'ready';
|
|
5
7
|
const directPhaseCommand = input.status.nextReadyPhase === undefined ? undefined : `vgx code sdd ${input.status.change} ${input.status.nextReadyPhase} --save-artifact`;
|
|
6
|
-
const recommendedAction =
|
|
7
|
-
? '
|
|
8
|
-
:
|
|
8
|
+
const recommendedAction = complete
|
|
9
|
+
? 'No next SDD phase remains for this change.'
|
|
10
|
+
: input.status.nextReadyPhase === undefined
|
|
11
|
+
? 'Review blockers or accept present draft artifacts before continuing.'
|
|
12
|
+
: `Run or draft the ${input.status.nextReadyPhase} phase with ${directPhaseCommand}.`;
|
|
9
13
|
const lines = [
|
|
10
14
|
'SDD Status',
|
|
11
15
|
`Project: ${input.project}`,
|
|
12
16
|
`Change: ${input.status.change}`,
|
|
13
|
-
`Status: ${
|
|
17
|
+
`Status: ${statusLabel}`,
|
|
14
18
|
`Next ready phase: ${input.status.nextReadyPhase ?? 'none'}`,
|
|
15
19
|
'',
|
|
16
20
|
'Phases:',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, join, relative, resolve } from 'node:path';
|
|
2
|
+
import { dirname, join, relative, resolve, sep } from 'node:path';
|
|
3
3
|
const ignoredDirectories = new Set(['.git', 'node_modules', 'dist', 'build', '.next', 'coverage']);
|
|
4
4
|
export function detectProject(workspaceRoot, fileLimit = 250) {
|
|
5
5
|
const root = resolve(workspaceRoot);
|
|
@@ -28,7 +28,14 @@ function findRepositoryRoot(start) {
|
|
|
28
28
|
function listFiles(root, limit) {
|
|
29
29
|
const files = [];
|
|
30
30
|
const visit = (directory) => {
|
|
31
|
-
|
|
31
|
+
let entries;
|
|
32
|
+
try {
|
|
33
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
32
39
|
if (files.length >= limit)
|
|
33
40
|
return;
|
|
34
41
|
if (entry.isDirectory() && ignoredDirectories.has(entry.name))
|
|
@@ -37,7 +44,7 @@ function listFiles(root, limit) {
|
|
|
37
44
|
if (entry.isDirectory())
|
|
38
45
|
visit(full);
|
|
39
46
|
else
|
|
40
|
-
files.push(relative(root, full));
|
|
47
|
+
files.push(toPortablePath(relative(root, full)));
|
|
41
48
|
}
|
|
42
49
|
};
|
|
43
50
|
visit(root);
|
|
@@ -46,6 +53,9 @@ function listFiles(root, limit) {
|
|
|
46
53
|
function isConfigFile(file) {
|
|
47
54
|
return /(^|\/)(package\.json|tsconfig[^/]*\.json|vite\.config\.|eslint\.config\.|\.eslintrc|vitest\.config\.|jest\.config\.|playwright\.config\.|pyproject\.toml|Cargo\.toml|go\.mod|pom\.xml|build\.gradle|settings\.gradle|pubspec\.yaml|Package\.swift)$/.test(file);
|
|
48
55
|
}
|
|
56
|
+
function toPortablePath(path) {
|
|
57
|
+
return sep === '/' ? path : path.split(sep).join('/');
|
|
58
|
+
}
|
|
49
59
|
function stackHints(root, files) {
|
|
50
60
|
const hints = new Set();
|
|
51
61
|
if (files.includes('package.json'))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
-
import { basename, join, relative, resolve } from 'node:path';
|
|
3
|
+
import { basename, join, relative, resolve, sep } from 'node:path';
|
|
4
4
|
import { normalizeToolError, normalizeToolSuccess } from './tool-result-normalizer.js';
|
|
5
5
|
export class ReadOnlyToolExecutor {
|
|
6
6
|
registry;
|
|
@@ -75,7 +75,8 @@ export class ReadOnlyToolExecutor {
|
|
|
75
75
|
}
|
|
76
76
|
function safePath(root, path) {
|
|
77
77
|
const resolved = resolve(root, path);
|
|
78
|
-
|
|
78
|
+
const fromRoot = relative(root, resolved);
|
|
79
|
+
if (fromRoot.startsWith('..') || fromRoot === '..' || resolve(fromRoot) === fromRoot)
|
|
79
80
|
throw new Error('Path escapes workspace root');
|
|
80
81
|
return resolved;
|
|
81
82
|
}
|
|
@@ -89,7 +90,7 @@ function listFiles(root, limit) {
|
|
|
89
90
|
if (entry.isDirectory())
|
|
90
91
|
visit(full);
|
|
91
92
|
else
|
|
92
|
-
files.push(relative(root, full));
|
|
93
|
+
files.push(toPortablePath(relative(root, full)));
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
visit(root);
|
|
@@ -124,6 +125,9 @@ function inspectProject(root) {
|
|
|
124
125
|
configFiles: listFiles(root, 200).filter((file) => /(^|\/)(package|tsconfig|vite|eslint|vitest|jest|playwright)/.test(file)),
|
|
125
126
|
};
|
|
126
127
|
}
|
|
128
|
+
function toPortablePath(path) {
|
|
129
|
+
return sep === '/' ? path : path.split(sep).join('/');
|
|
130
|
+
}
|
|
127
131
|
function git(root, args) {
|
|
128
132
|
return execFileSync('git', args, {
|
|
129
133
|
cwd: root,
|
package/dist/mcp/doctor.js
CHANGED
|
@@ -66,7 +66,7 @@ async function runRealMcpSmoke(options) {
|
|
|
66
66
|
const client = new Client({ name: 'vgxness-doctor', version: '0.1.0' }, { capabilities: {} });
|
|
67
67
|
const invocation = resolveDoctorCliInvocation(options.databasePath);
|
|
68
68
|
const transport = new StdioClientTransport({
|
|
69
|
-
command:
|
|
69
|
+
command: invocation.command,
|
|
70
70
|
args: invocation.args,
|
|
71
71
|
cwd: options.cwd,
|
|
72
72
|
stderr: 'pipe',
|
|
@@ -173,11 +173,17 @@ function parseMcpToolResult(result) {
|
|
|
173
173
|
return { ok: false, error: { code: 'validation_failed', message: 'MCP response did not contain text JSON' } };
|
|
174
174
|
return JSON.parse(text);
|
|
175
175
|
}
|
|
176
|
-
export function resolveDoctorCliInvocation(databasePath, moduleUrl = import.meta.url) {
|
|
176
|
+
export function resolveDoctorCliInvocation(databasePath, moduleUrl = import.meta.url, options = {}) {
|
|
177
|
+
const runtime = options.runtime ?? currentRuntime();
|
|
177
178
|
const builtCliPath = fileURLToPath(new URL('../cli/index.js', moduleUrl));
|
|
178
179
|
if (existsSync(builtCliPath))
|
|
179
|
-
return { args: [builtCliPath, 'mcp', 'start', '--db', databasePath] };
|
|
180
|
-
|
|
180
|
+
return { command: process.execPath, args: [builtCliPath, 'mcp', 'start', '--db', databasePath] };
|
|
181
|
+
if (runtime === 'bun')
|
|
182
|
+
return { command: process.execPath, args: [cliSourcePath(moduleUrl), 'mcp', 'start', '--db', databasePath] };
|
|
183
|
+
return { command: process.execPath, args: ['--import', import.meta.resolve('tsx'), cliSourcePath(moduleUrl), 'mcp', 'start', '--db', databasePath] };
|
|
184
|
+
}
|
|
185
|
+
function currentRuntime() {
|
|
186
|
+
return typeof globalThis.Bun === 'undefined' ? 'node' : 'bun';
|
|
181
187
|
}
|
|
182
188
|
function cliSourcePath(moduleUrl) {
|
|
183
189
|
return fileURLToPath(new URL('../cli/index.ts', moduleUrl));
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { dirname, join } from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import Database from 'better-sqlite3';
|
|
5
5
|
const migrationsDirectory = join(dirname(fileURLToPath(import.meta.url)), 'migrations');
|
|
6
6
|
export const sqliteBusyTimeoutMs = 5000;
|
|
7
|
-
const
|
|
8
|
-
const nativeBindingFailurePatterns = [
|
|
9
|
-
/better_sqlite3\.node/i,
|
|
10
|
-
/better-sqlite3/i,
|
|
11
|
-
/NODE_MODULE_VERSION/i,
|
|
12
|
-
/ERR_DLOPEN_FAILED/i,
|
|
13
|
-
/Could not locate the bindings file/i,
|
|
14
|
-
/compiled against a different Node\.js version/i,
|
|
15
|
-
];
|
|
7
|
+
const bunRequiredGuidance = 'Real local SQLite storage requires Bun. Use the installed Bun-backed vgxness/vgx runtime, or run Bun storage verification with bun run verify:bun-sqlite.';
|
|
16
8
|
export class MemoryDatabase {
|
|
17
9
|
connection;
|
|
18
10
|
constructor(connection) {
|
|
@@ -20,7 +12,7 @@ export class MemoryDatabase {
|
|
|
20
12
|
}
|
|
21
13
|
static open(options) {
|
|
22
14
|
try {
|
|
23
|
-
const connection =
|
|
15
|
+
const connection = openSqliteConnection(options);
|
|
24
16
|
connection.pragma('foreign_keys = ON');
|
|
25
17
|
connection.pragma(`busy_timeout = ${sqliteBusyTimeoutMs}`);
|
|
26
18
|
const memoryDatabase = new MemoryDatabase(connection);
|
|
@@ -100,13 +92,133 @@ export function openMemoryDatabase(options) {
|
|
|
100
92
|
}
|
|
101
93
|
export function buildMemoryStoreUnavailableMessage(path, cause) {
|
|
102
94
|
const message = `Unable to open local memory store at ${path}`;
|
|
103
|
-
if (!
|
|
95
|
+
if (!isUnsupportedSqliteRuntimeError(cause))
|
|
104
96
|
return message;
|
|
105
|
-
return `${message}. ${
|
|
97
|
+
return `${message}. ${bunRequiredGuidance}`;
|
|
106
98
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
function openSqliteConnection(options) {
|
|
100
|
+
return resolveSqliteDriver()(options);
|
|
101
|
+
}
|
|
102
|
+
function resolveSqliteDriver() {
|
|
103
|
+
if (isBunRuntime())
|
|
104
|
+
return resolveBunSqliteDriver();
|
|
105
|
+
throw createUnsupportedSqliteRuntimeError();
|
|
106
|
+
}
|
|
107
|
+
function isBunRuntime() {
|
|
108
|
+
return typeof globalThis.Bun !== 'undefined';
|
|
109
|
+
}
|
|
110
|
+
function resolveBunSqliteDriver() {
|
|
111
|
+
const require = createRequire(import.meta.url);
|
|
112
|
+
const module = require('bun:sqlite');
|
|
113
|
+
const BunDatabase = module.Database;
|
|
114
|
+
if (typeof BunDatabase !== 'function')
|
|
115
|
+
throw new Error('bun:sqlite Database constructor is unavailable');
|
|
116
|
+
return (options) => createBunSqliteConnection(new BunDatabase(options.path, { readonly: options.readonly ?? false, strict: true }));
|
|
117
|
+
}
|
|
118
|
+
function createUnsupportedSqliteRuntimeError() {
|
|
119
|
+
const error = new Error(bunRequiredGuidance);
|
|
120
|
+
error.name = 'UnsupportedSqliteRuntimeError';
|
|
121
|
+
return error;
|
|
122
|
+
}
|
|
123
|
+
function isUnsupportedSqliteRuntimeError(cause) {
|
|
124
|
+
return cause instanceof Error && cause.name === 'UnsupportedSqliteRuntimeError';
|
|
125
|
+
}
|
|
126
|
+
function createBunSqliteConnection(database) {
|
|
127
|
+
const record = database;
|
|
128
|
+
return {
|
|
129
|
+
prepare(sql) {
|
|
130
|
+
const prepare = record.prepare;
|
|
131
|
+
if (typeof prepare !== 'function')
|
|
132
|
+
throw new Error('bun:sqlite prepare() is unavailable');
|
|
133
|
+
return createBunSqliteStatement(prepare.call(database, sql));
|
|
134
|
+
},
|
|
135
|
+
exec(sql) {
|
|
136
|
+
const exec = record.exec;
|
|
137
|
+
if (typeof exec === 'function')
|
|
138
|
+
return exec.call(database, sql);
|
|
139
|
+
const run = record.run;
|
|
140
|
+
if (typeof run === 'function')
|
|
141
|
+
return run.call(database, sql);
|
|
142
|
+
throw new Error('bun:sqlite exec() is unavailable');
|
|
143
|
+
},
|
|
144
|
+
pragma(statement) {
|
|
145
|
+
return runBunPragma(database, statement);
|
|
146
|
+
},
|
|
147
|
+
transaction(operation) {
|
|
148
|
+
const transaction = record.transaction;
|
|
149
|
+
if (typeof transaction !== 'function')
|
|
150
|
+
throw new Error('bun:sqlite transaction() is unavailable');
|
|
151
|
+
const run = transaction.call(database, operation);
|
|
152
|
+
if (typeof run !== 'function')
|
|
153
|
+
throw new Error('bun:sqlite transaction() did not return a callable transaction');
|
|
154
|
+
const transactionRunner = run;
|
|
155
|
+
if (typeof transactionRunner.immediate !== 'function') {
|
|
156
|
+
throw new Error('bun:sqlite transaction().immediate() is unavailable');
|
|
157
|
+
}
|
|
158
|
+
return transactionRunner;
|
|
159
|
+
},
|
|
160
|
+
close() {
|
|
161
|
+
const close = record.close;
|
|
162
|
+
if (typeof close !== 'function')
|
|
163
|
+
return;
|
|
164
|
+
close.call(database, false);
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
function createBunSqliteStatement(statement) {
|
|
169
|
+
const record = statement;
|
|
170
|
+
return {
|
|
171
|
+
get(...params) {
|
|
172
|
+
const get = record.get;
|
|
173
|
+
if (typeof get !== 'function')
|
|
174
|
+
throw new Error('bun:sqlite statement.get() is unavailable');
|
|
175
|
+
const row = get.call(statement, ...params);
|
|
176
|
+
return row === null ? undefined : row;
|
|
177
|
+
},
|
|
178
|
+
all(...params) {
|
|
179
|
+
const all = record.all;
|
|
180
|
+
if (typeof all !== 'function')
|
|
181
|
+
throw new Error('bun:sqlite statement.all() is unavailable');
|
|
182
|
+
return all.call(statement, ...params);
|
|
183
|
+
},
|
|
184
|
+
run(...params) {
|
|
185
|
+
const run = record.run;
|
|
186
|
+
if (typeof run !== 'function')
|
|
187
|
+
throw new Error('bun:sqlite statement.run() is unavailable');
|
|
188
|
+
return run.call(statement, ...params);
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function runBunPragma(database, statement) {
|
|
193
|
+
const normalizedStatement = statement.trim();
|
|
194
|
+
if (isPragmaSetter(normalizedStatement)) {
|
|
195
|
+
const exec = database.exec;
|
|
196
|
+
if (typeof exec !== 'function')
|
|
197
|
+
throw new Error('bun:sqlite exec() is unavailable for PRAGMA setter');
|
|
198
|
+
return exec.call(database, `PRAGMA ${normalizedStatement}`);
|
|
199
|
+
}
|
|
200
|
+
const prepare = database.prepare;
|
|
201
|
+
if (typeof prepare !== 'function')
|
|
202
|
+
throw new Error('bun:sqlite prepare() is unavailable for PRAGMA reader');
|
|
203
|
+
const rows = prepare.call(database, `PRAGMA ${normalizedStatement}`).all();
|
|
204
|
+
if (/^busy_timeout\b/i.test(normalizedStatement))
|
|
205
|
+
return normalizeBusyTimeoutRows(rows);
|
|
206
|
+
return rows;
|
|
207
|
+
}
|
|
208
|
+
function isPragmaSetter(statement) {
|
|
209
|
+
return /=/.test(statement);
|
|
210
|
+
}
|
|
211
|
+
function normalizeBusyTimeoutRows(rows) {
|
|
212
|
+
return rows.map((row) => {
|
|
213
|
+
if (row === null || typeof row !== 'object')
|
|
214
|
+
return row;
|
|
215
|
+
const record = row;
|
|
216
|
+
if (typeof record.timeout === 'number')
|
|
217
|
+
return row;
|
|
218
|
+
if (typeof record.busy_timeout === 'number')
|
|
219
|
+
return { timeout: record.busy_timeout };
|
|
220
|
+
return row;
|
|
221
|
+
});
|
|
110
222
|
}
|
|
111
223
|
function migrationFailure(message, cause) {
|
|
112
224
|
const error = { code: 'migration_failed', message };
|
|
@@ -114,26 +226,3 @@ function migrationFailure(message, cause) {
|
|
|
114
226
|
error.cause = cause;
|
|
115
227
|
return { ok: false, error };
|
|
116
228
|
}
|
|
117
|
-
function collectDiagnosticValues(value, seen = new Set()) {
|
|
118
|
-
if (value === undefined || value === null)
|
|
119
|
-
return [];
|
|
120
|
-
if (typeof value === 'string')
|
|
121
|
-
return [value];
|
|
122
|
-
if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint' || typeof value === 'symbol')
|
|
123
|
-
return [String(value)];
|
|
124
|
-
if (typeof value !== 'object')
|
|
125
|
-
return [];
|
|
126
|
-
if (seen.has(value))
|
|
127
|
-
return [];
|
|
128
|
-
seen.add(value);
|
|
129
|
-
const diagnosticValues = [];
|
|
130
|
-
const record = value;
|
|
131
|
-
for (const key of ['code', 'message', 'stack', 'name']) {
|
|
132
|
-
const property = record[key];
|
|
133
|
-
if (property !== undefined)
|
|
134
|
-
diagnosticValues.push(...collectDiagnosticValues(property, seen));
|
|
135
|
-
}
|
|
136
|
-
if (record.cause !== undefined)
|
|
137
|
-
diagnosticValues.push(...collectDiagnosticValues(record.cause, seen));
|
|
138
|
-
return diagnosticValues;
|
|
139
|
-
}
|
|
@@ -40,8 +40,8 @@ const templates = {
|
|
|
40
40
|
manualChecks: [manualCheck('review-provider-config-writes', 'Review provider config write gating', 'Confirm provider config writes still require explicit consent and backup/rollback where applicable.')],
|
|
41
41
|
},
|
|
42
42
|
'package-release': {
|
|
43
|
-
rationale: ['Package release changes need packaging checks, but package scripts are not allowlisted in the workflow executor.', '
|
|
44
|
-
recommendations: [nodeVersionRecommendation(), typecheckRecommendation(), manualRecommendation('manual-
|
|
43
|
+
rationale: ['Package release changes need packaging checks, but package scripts are not allowlisted in the workflow executor.', 'Bun package evidence is the authoritative artifact and isolated install-smoke path; recommendations stay copy-only except for harmless allowlisted environment/type checks.'],
|
|
44
|
+
recommendations: [nodeVersionRecommendation(), typecheckRecommendation(), manualRecommendation('manual-bun-package-evidence', 'Run authoritative Bun package evidence manually', 'Bun package evidence validates package metadata, artifact contents, isolated install smoke, and no-publication safety as copy-only guidance.', 'bun run package:bun:evidence')],
|
|
45
45
|
manualChecks: [manualCheck('review-package-files', 'Review package contents', 'Confirm package whitelist changes are intentional and runtime files are included.')],
|
|
46
46
|
},
|
|
47
47
|
'workflow-runs': {
|
package/docs/cli.md
CHANGED
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
# Use the local CLI
|
|
2
2
|
|
|
3
|
-
Run `vgxness` commands from the repo with `
|
|
3
|
+
Run `vgxness` commands from the repo with `bun run cli -- ...`. The CLI is intentionally thin: it parses flags, opens the local SQLite store, and calls the existing domain services for memory, agents, runs, and permissions. `npm run cli -- ...` remains available for Node development tooling compatibility when dependencies are already installed, but installed `vgxness`/`vgx` bins require Bun.
|
|
4
4
|
|
|
5
5
|
## Local tarball install and dogfood
|
|
6
6
|
|
|
7
|
-
Use
|
|
7
|
+
Use the Bun package evidence workflow to dogfood the installable package without publishing. It builds package artifacts, validates package contents, installs into an isolated Bun environment, and checks both CLI bins.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
bun run package:bun:evidence
|
|
11
|
+
```
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
VGXNESS_SMOKE_WORKDIR=$(mktemp -d)
|
|
15
|
-
VGXNESS_SMOKE_DB="$VGXNESS_SMOKE_WORKDIR/smoke.sqlite"
|
|
13
|
+
That command is diagnostic. For release-readiness, require a passing result explicitly:
|
|
16
14
|
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
```bash
|
|
16
|
+
bun run package:bun:evidence -- --require-pass
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
The evidence includes these smoke checks from the isolated install location:
|
|
22
20
|
|
|
23
21
|
```bash
|
|
24
|
-
cd "$VGXNESS_SMOKE_WORKDIR"
|
|
25
22
|
vgxness --help
|
|
26
23
|
vgx --help
|
|
27
|
-
vgx setup plan
|
|
28
|
-
vgx setup status --db "$VGXNESS_SMOKE_DB"
|
|
29
|
-
vgxness dashboard status --project vgxness --db "$VGXNESS_SMOKE_DB"
|
|
30
|
-
vgxness mcp install opencode --plan --db "$VGXNESS_SMOKE_DB"
|
|
31
24
|
```
|
|
32
25
|
|
|
33
|
-
`vgx setup plan` and `vgx setup status` are human-readable and read-only by default; pass `--json` when you need parseable automation output. The MCP plan is read-only.
|
|
26
|
+
`vgx setup plan` and `vgx 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.
|
|
34
27
|
|
|
35
28
|
Only apply the OpenCode user/global config after reviewing the plan (use `--scope project` only when you intentionally want project config):
|
|
36
29
|
|
|
@@ -38,15 +31,7 @@ Only apply the OpenCode user/global config after reviewing the plan (use `--scop
|
|
|
38
31
|
vgxness mcp install opencode --yes --db "$VGXNESS_SMOKE_DB"
|
|
39
32
|
```
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
rm -rf "$VGXNESS_SMOKE_PREFIX"
|
|
45
|
-
rm -rf "$VGXNESS_SMOKE_WORKDIR"
|
|
46
|
-
rm -f "./$VGXNESS_TARBALL"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
For the automated version of this workflow, run `npm run package:smoke:install`.
|
|
34
|
+
For deeper manual troubleshooting, create temporary directories outside the checkout and do not treat npm tarball/install smoke commands as current release evidence.
|
|
50
35
|
|
|
51
36
|
## Stable npm/global setup
|
|
52
37
|
|
|
@@ -54,7 +39,9 @@ The npm package name is `vgxness`, the stable release path uses the default/late
|
|
|
54
39
|
|
|
55
40
|
Release defaults used by the guided setup are:
|
|
56
41
|
|
|
57
|
-
-
|
|
42
|
+
- Bun `>=1.3.14` as the installed CLI/MCP runtime and repository verification path.
|
|
43
|
+
- Node.js `>=22` for repository development/build/test tooling only.
|
|
44
|
+
- Bun package evidence as the release artifact and isolated install-smoke path.
|
|
58
45
|
- Provider: OpenCode.
|
|
59
46
|
- Database: global user data location by default.
|
|
60
47
|
- OpenCode scope: user/global config by default (`$HOME/.config/opencode/opencode.json`).
|
|
@@ -79,6 +66,125 @@ vgx setup rollback --backup <path>
|
|
|
79
66
|
|
|
80
67
|
`vgx 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. `vgx doctor`, `vgx sdd status`, `vgx sdd next`, `vgx sdd get-artifact`, and `vgx sdd list-artifacts` are also human-readable by default; use `--json` for scripts.
|
|
81
68
|
|
|
69
|
+
## Bun-first repository verification
|
|
70
|
+
|
|
71
|
+
VGXNESS uses Bun as the canonical installed runtime and verification path for repository development and CI. Node.js `>=22` remains development/build/test tooling for TypeScript, `node:test`, and helper scripts. npm package consumer metadata remains supported, but the product runtime engine is `engines.bun`.
|
|
72
|
+
|
|
73
|
+
Happy path for local verification:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bun install --frozen-lockfile
|
|
77
|
+
bun run check:bun-lock
|
|
78
|
+
bun run verify:typecheck
|
|
79
|
+
bun run verify:test
|
|
80
|
+
bun run verify:test:bun-storage
|
|
81
|
+
bun run verify:bun-sqlite
|
|
82
|
+
bun run verify:package
|
|
83
|
+
bun run package:bun:evidence -- --require-pass
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`bun run verify:bun-sqlite` is the SQLite runtime release gate. It uses `bun:sqlite` against a temporary database, copies/applies the source migrations, and checks foreign keys, busy timeout, FTS/search, transaction rollback, integrity, and cleanup. `bun run verify:test:bun-storage` covers storage-backed tests under Bun. Node.js remains development/build/test tooling, but real local SQLite storage is supported through the Bun runtime path.
|
|
87
|
+
|
|
88
|
+
Keep lockfile changes intentional: when `package.json` dependency specifiers change, refresh and review the root `bun.lock` diff. The read-only drift check does not run `bun install` and does not mutate `node_modules`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
bun run check:bun-lock
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Bun package evidence
|
|
95
|
+
|
|
96
|
+
The authoritative package evidence path is:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bun run package:bun:evidence
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This default mode is diagnostic: it may emit `status: incompatible` and exit `0` so maintainers can collect and review JSON evidence. The release-readiness gate is:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun run package:bun:evidence -- --require-pass
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
It validates package metadata, artifact contents, forbidden workspace-only files, isolated Bun global install behavior, both `vgxness --help` and `vgx --help`, Bun runtime identity evidence for the installed wrapper, retired bridge invariants, no `package-lock.json`, and `publicationAttempted: false`. It must not invoke registry publication commands.
|
|
109
|
+
|
|
110
|
+
Release-candidate checklist, without publishing:
|
|
111
|
+
|
|
112
|
+
1. `bun install --frozen-lockfile` completes on a clean checkout.
|
|
113
|
+
2. `bun run check:bun-lock` passes.
|
|
114
|
+
3. `bun run verify:typecheck`, `bun run verify:test`, and `bun run verify:bun-sqlite` pass.
|
|
115
|
+
4. `bun run package:bun:evidence -- --require-pass` passes on supported CI OSes.
|
|
116
|
+
5. Uploaded JSON shows `status: pass`, artifact/install smoke pass, no retired scripts, no `package-lock.json`, `publicationAttempted: false`, and `releaseReadiness.status: pass`.
|
|
117
|
+
6. Version, release notes, proprietary license boundary, and rollback criteria are reviewed.
|
|
118
|
+
7. Publishing remains a separate explicit human-approved process.
|
|
119
|
+
|
|
120
|
+
This path does **not** run `npm publish`, `bun publish`, registry dry-runs that contact a registry, registry token use, provenance upload, release creation, or dist-tag mutation.
|
|
121
|
+
|
|
122
|
+
### Temporary npm bridge rollback
|
|
123
|
+
|
|
124
|
+
The npm publication bridge is retired as a current release path. Restore it only temporarily if Bun package evidence misses a release regression, downstream install verification fails in a way Bun did not catch, or a release candidate needs short-lived npm bridge validation while a Bun evidence gap is investigated.
|
|
125
|
+
|
|
126
|
+
Restore these elements from the previous known-good main commit:
|
|
127
|
+
|
|
128
|
+
- `package-lock.json`
|
|
129
|
+
- package scripts: `prepack`, `package:release-check`, `package:dry-run`, and `package:smoke:install`
|
|
130
|
+
- deleted helper scripts: `scripts/validate-package-release.mjs` and `scripts/smoke-tarball-install.mjs`
|
|
131
|
+
- npm validation wiring and tests that enforced the bridge
|
|
132
|
+
- the `.github/workflows/node22.yml` `npm-publication-bridge` job and its artifact/install-smoke steps
|
|
133
|
+
|
|
134
|
+
Rollback is release-impacting and temporary. Do not publish during rollback verification unless a separate explicit approval covers publication. Open a follow-up investigation or SDD change before retiring the bridge again.
|
|
135
|
+
|
|
136
|
+
### Bun package evidence probe details
|
|
137
|
+
|
|
138
|
+
Run the evidence probe:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
bun run package:bun:evidence
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
By default, the probe exits `0` for `pass` or `incompatible` results and exits `1` only for probe malfunction or safety violations. JSON evidence is written to stdout and optionally to a path via `--json-out <path>`. With `--require-pass`, JSON is still emitted/written first, but the process exits non-zero unless `releaseReadiness.status` is `pass`.
|
|
145
|
+
|
|
146
|
+
A `pass` status means Bun produced and inspected package artifact evidence on this OS. An `incompatible` status means Bun is available but lacks a required packaging/install capability; treat it as a release blocker until resolved or explicitly accepted.
|
|
147
|
+
|
|
148
|
+
The probe never invokes `npm publish`, `bun publish`, or any registry publication command. It records retired bridge status as a release-readiness invariant.
|
|
149
|
+
|
|
150
|
+
### Compatibility probe
|
|
151
|
+
|
|
152
|
+
The Bun runtime compatibility probe is bounded extra evidence for the built CLI entrypoint and MCP stdio server under Bun. It does not replace installed-bin package evidence and does not use the installed bin shebang. Build first; the probe intentionally requires `dist/cli/index.js` and does not auto-build or fall back to `src/`, `tsx`, or `npm run cli`:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
bun run build
|
|
156
|
+
bun run probe:bun-runtime
|
|
157
|
+
bun run probe:bun-runtime -- --require-pass
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The probe runs `bun dist/cli/index.js --help`, then starts `bun dist/cli/index.js mcp start --db <tmp>/memory.sqlite` with isolated temporary state. It lists MCP tools, requires `verification_plan`, calls it with `{ changeType: 'mcp' }`, and emits JSON evidence to stdout or `--json-out <path>`. Default diagnostic mode reports missing Bun as `status: incompatible` and exits `0`; `--require-pass` exits non-zero unless the full CLI + MCP smoke passes.
|
|
161
|
+
|
|
162
|
+
For a strict alias, use:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
bun run verify:bun-runtime
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
This alias is intentionally not part of the aggregate `verify` script.
|
|
169
|
+
|
|
170
|
+
Use the older probe only when diagnosing package-manager behavior. Review the plan before allowing mutation:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm run probe:bun
|
|
174
|
+
npm run probe:bun -- --yes
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Additional compatibility-only checks:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
npm run check:bun:typecheck
|
|
181
|
+
bun run typecheck
|
|
182
|
+
bun run build
|
|
183
|
+
bun run package:bun:evidence
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
When reporting a Bun failure, include the Bun version, OS/CPU, Node version, whether `bun install --frozen-lockfile` completed, which `bun run verify:*` command failed, and whether the error points to `bun:sqlite`, migration application, package evidence, or another install step.
|
|
187
|
+
|
|
82
188
|
## Quick path
|
|
83
189
|
|
|
84
190
|
```bash
|
|
@@ -43,13 +43,12 @@ Esa capa no reemplaza a OpenCode, Claude Code o futuros adapters. Los coordina.
|
|
|
43
43
|
|
|
44
44
|
## Como esta construido
|
|
45
45
|
|
|
46
|
-
El proyecto esta escrito en TypeScript
|
|
46
|
+
El proyecto esta escrito en TypeScript. Node.js 22 o superior sigue siendo tooling de desarrollo/build/tests; la persistencia local real en SQLite corre por el runtime Bun soportado.
|
|
47
47
|
|
|
48
48
|
Dependencias principales:
|
|
49
49
|
|
|
50
50
|
| Dependencia | Uso |
|
|
51
51
|
|---|---|
|
|
52
|
-
| `better-sqlite3` | Persistencia local en SQLite. |
|
|
53
52
|
| `@modelcontextprotocol/sdk` | Servidor MCP por stdio. |
|
|
54
53
|
| `zod` | Validacion de schemas de entrada. |
|
|
55
54
|
| `tsx` | Ejecucion TypeScript en desarrollo. |
|
|
@@ -63,8 +62,7 @@ Scripts principales:
|
|
|
63
62
|
| `npm run build` | Compila TypeScript y copia migraciones. |
|
|
64
63
|
| `npm run test` | Ejecuta tests con el runner nativo de Node. |
|
|
65
64
|
| `npm run typecheck` | Valida tipos sin emitir archivos. |
|
|
66
|
-
| `
|
|
67
|
-
| `npm run package:smoke:install` | Prueba instalacion local del tarball. |
|
|
65
|
+
| `bun run package:bun:evidence` | Valida el paquete con Bun: artefacto, contenido, instalacion aislada y ambos bins. |
|
|
68
66
|
|
|
69
67
|
## Vista de alto nivel
|
|
70
68
|
|
|
@@ -136,9 +134,9 @@ Archivo clave:
|
|
|
136
134
|
src/memory/sqlite/database.ts
|
|
137
135
|
```
|
|
138
136
|
|
|
139
|
-
Al abrir la base, el sistema:
|
|
137
|
+
Al abrir la base con el runtime Bun, el sistema:
|
|
140
138
|
|
|
141
|
-
1. Crea una conexion
|
|
139
|
+
1. Crea una conexion SQLite usando `bun:sqlite`.
|
|
142
140
|
2. Activa `foreign_keys`.
|
|
143
141
|
3. Configura `busy_timeout`.
|
|
144
142
|
4. Aplica migraciones SQL si la base no esta en modo readonly.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vgxness",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
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": {
|
|
@@ -22,16 +22,26 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"cli": "tsx src/cli/index.ts",
|
|
24
24
|
"build": "tsc -p tsconfig.build.json && node scripts/copy-migrations.mjs",
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
25
|
+
"verify": "bun run verify:typecheck && bun run verify:test && bun run verify:test:bun-storage && bun run verify:bun-sqlite && bun run verify:package",
|
|
26
|
+
"verify:typecheck": "tsc --noEmit",
|
|
27
|
+
"verify:test": "node scripts/run-node-tests.mjs",
|
|
28
|
+
"verify:test:bun-storage": "node scripts/run-bun-storage-tests.mjs",
|
|
29
|
+
"verify:package": "bun run package:bun:evidence",
|
|
30
|
+
"verify:bun-sqlite": "bun scripts/probe-bun-sqlite.mjs",
|
|
31
|
+
"ci:bun": "bun run check:bun-lock && bun run verify",
|
|
32
|
+
"check:bun-lock": "node scripts/check-bun-lock.mjs",
|
|
33
|
+
"check:vgxcode:bun-lock": "node scripts/check-bun-lock.mjs --package-json packages/vgxcode/package.json --bun-lock packages/vgxcode/bun.lock",
|
|
34
|
+
"check:bun:typecheck": "node scripts/run-bun-typecheck.mjs",
|
|
35
|
+
"probe:bun": "node scripts/probe-bun-compat.mjs",
|
|
36
|
+
"probe:bun-runtime": "node scripts/probe-bun-runtime-cli-mcp.mjs",
|
|
37
|
+
"verify:bun-runtime": "node scripts/probe-bun-runtime-cli-mcp.mjs --require-pass",
|
|
38
|
+
"package:bun:evidence": "node scripts/probe-bun-package-evidence.mjs",
|
|
39
|
+
"test": "node scripts/run-node-tests.mjs",
|
|
30
40
|
"typecheck": "tsc --noEmit"
|
|
31
41
|
},
|
|
32
42
|
"bin": {
|
|
33
|
-
"vgxness": "dist/cli/
|
|
34
|
-
"vgx": "dist/cli/
|
|
43
|
+
"vgxness": "dist/cli/bun-bin.js",
|
|
44
|
+
"vgx": "dist/cli/bun-bin.js"
|
|
35
45
|
},
|
|
36
46
|
"files": [
|
|
37
47
|
"dist",
|
|
@@ -43,19 +53,17 @@
|
|
|
43
53
|
],
|
|
44
54
|
"dependencies": {
|
|
45
55
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
|
-
"better-sqlite3": "^12.10.0",
|
|
47
56
|
"ink": "^7.0.3",
|
|
48
57
|
"react": "^19.2.6",
|
|
49
58
|
"zod": "^4.4.3"
|
|
50
59
|
},
|
|
51
60
|
"devDependencies": {
|
|
52
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
53
61
|
"@types/node": "^22.15.18",
|
|
54
62
|
"@types/react": "^19.2.15",
|
|
55
63
|
"tsx": "^4.19.4",
|
|
56
64
|
"typescript": "^5.8.3"
|
|
57
65
|
},
|
|
58
66
|
"engines": {
|
|
59
|
-
"
|
|
67
|
+
"bun": ">=1.3.14"
|
|
60
68
|
}
|
|
61
69
|
}
|