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 CHANGED
@@ -10,9 +10,114 @@ OpenCode is the primary supported provider. Other providers remain preview/manua
10
10
 
11
11
  ## Requirements
12
12
 
13
- - Node.js >= 22
14
- - npm
15
- - A platform supported by `better-sqlite3` for your Node/runtime combination
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
- - Node < 22: upgrade Node and reinstall.
105
- - Native SQLite install failure: verify your platform has compatible `better-sqlite3` binaries/build tools.
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 and manual release checks target Node 22 on macOS, Linux, and Windows:
217
+ CI verifies Bun on macOS, Linux, and Windows:
112
218
 
113
219
  ```bash
114
- npm ci
115
- npm run typecheck
116
- npm test
117
- npm run package:release-check
118
- npm run package:dry-run
119
- npm run package:smoke:install
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
- Do not publish from CI. Use `npm publish --dry-run --tag latest` as the final manual gate for the stable path before any explicit publish decision.
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 async function runInitCommand(parsed, environment) {
321
+ export function resolveInitDispatchMode(parsed, environment) {
322
322
  if (parsed.flags.plan === true || parsed.flags.json === true)
323
- return runSetupPlanCommand(parsed, environment);
323
+ return 'setup-plan';
324
324
  if (parsed.flags.yes === true)
325
- return runSetupApplyCommand({ ...parsed, flags: { ...parsed.flags, yes: true } }, environment);
326
- const terminal = environment.stdin?.isTTY === true && environment.stdout?.isTTY === true;
327
- if (!terminal)
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 runSetupTuiCommand(environment, project === undefined ? undefined : { project });
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))
@@ -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);
@@ -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 = input.status.nextReadyPhase === undefined
7
- ? 'Review blockers or accept present draft artifacts before continuing.'
8
- : `Run or draft the ${input.status.nextReadyPhase} phase with ${directPhaseCommand}.`;
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: ${input.status.nextReadyPhase === undefined ? 'blocked' : 'ready'}`,
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
- for (const entry of readdirSync(directory, { withFileTypes: true })) {
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
- if (resolved !== root && !resolved.startsWith(`${root}/`))
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,
@@ -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: process.execPath,
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
- return { args: ['--import', import.meta.resolve('tsx'), cliSourcePath(moduleUrl), 'mcp', 'start', '--db', databasePath] };
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 nativeBindingDiagnosticGuidance = 'Detected a likely better-sqlite3 native binding problem. Ensure npm install scripts are enabled, then rebuild or reinstall dependencies for the active Node.js version (for example: npm rebuild better-sqlite3 --ignore-scripts=false).';
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 = new Database(options.path, { readonly: options.readonly ?? false });
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 (!isLikelyBetterSqlite3NativeBindingFailure(cause))
95
+ if (!isUnsupportedSqliteRuntimeError(cause))
104
96
  return message;
105
- return `${message}. ${nativeBindingDiagnosticGuidance}`;
97
+ return `${message}. ${bunRequiredGuidance}`;
106
98
  }
107
- export function isLikelyBetterSqlite3NativeBindingFailure(cause) {
108
- const values = collectDiagnosticValues(cause);
109
- return values.some((value) => nativeBindingFailurePatterns.some((pattern) => pattern.test(value)));
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.', 'Recommendations are deliberately copy-only except for harmless allowlisted environment/type checks.'],
44
- recommendations: [nodeVersionRecommendation(), typecheckRecommendation(), manualRecommendation('manual-release-check', 'Run release package validation manually', 'Package script npm run package:release-check is copy-only in this slice.', 'npm run package:release-check'), manualRecommendation('manual-package-dry-run', 'Run package dry-run manually', 'Package script npm run package:dry-run is copy-only in this slice.', 'npm run package:dry-run'), manualRecommendation('manual-smoke-install', 'Run package smoke install manually', 'Package script npm run package:smoke:install is copy-only in this slice.', 'npm run package:smoke:install')],
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 `npm 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.
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 this workflow to dogfood the installable package without publishing to npm. It builds the package, installs the tarball into an isolated temporary prefix, and uses an explicit temporary database so your default global memory store is untouched.
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
- npm run build
11
- VGXNESS_TARBALL=$(npm pack --json | node -e 'const fs = require("node:fs"); const [pkg] = JSON.parse(fs.readFileSync(0, "utf8")); process.stdout.write(pkg.filename);')
10
+ bun run package:bun:evidence
11
+ ```
12
12
 
13
- VGXNESS_SMOKE_PREFIX=$(mktemp -d)
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
- npm install --prefix "$VGXNESS_SMOKE_PREFIX" --global --no-audit --no-fund "./$VGXNESS_TARBALL"
18
- export PATH="$VGXNESS_SMOKE_PREFIX/bin:$PATH"
15
+ ```bash
16
+ bun run package:bun:evidence -- --require-pass
19
17
  ```
20
18
 
21
- Run the smoke checks from the temporary workdir:
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. With the explicit smoke DB above, it should show an installed server command that starts with `vgxness mcp start --db "$VGXNESS_SMOKE_DB"` and must not mention `npm run cli`, `tsx`, or repository-relative source paths. If `--db` is omitted, the installed command should be `vgxness mcp start` and use the global default at runtime.
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
- Rollback cleanup:
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
- - Node.js `>=22`.
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 y corre sobre Node.js 22 o superior.
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
- | `npm run package:dry-run` | Simula el empaquetado npm. |
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 con `better-sqlite3`.
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.0.5",
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
- "prepack": "npm run build",
26
- "package:dry-run": "npm pack --dry-run --json",
27
- "package:release-check": "node scripts/validate-package-release.mjs",
28
- "package:smoke:install": "node scripts/smoke-tarball-install.mjs",
29
- "test": "node --import tsx --test \"test/**/*.test.ts\"",
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/index.js",
34
- "vgx": "dist/cli/index.js"
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
- "node": ">=22"
67
+ "bun": ">=1.3.14"
60
68
  }
61
69
  }