vibe-splain 3.4.2 → 4.0.0

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.
Files changed (87) hide show
  1. package/README.md +110 -158
  2. package/dist/commands/install.d.ts +0 -5
  3. package/dist/commands/install.js +5 -55
  4. package/dist/commands/serve.js +1 -1
  5. package/dist/export/ArtifactBundleWriter.js +3 -3
  6. package/dist/export/ExportOrchestrator.d.ts +2 -20
  7. package/dist/export/ExportOrchestrator.js +5 -116
  8. package/dist/export/Watcher.js +5 -5
  9. package/dist/export/renderers/AgentMarkdownRenderer.d.ts +1 -1
  10. package/dist/export/renderers/GraphRenderer.d.ts +2 -2
  11. package/dist/export/renderers/HtmlRenderer.d.ts +1 -1
  12. package/dist/export/renderers/HtmlRenderer.js +1 -1
  13. package/dist/export/renderers/JsonRenderer.d.ts +1 -1
  14. package/dist/export/renderers/RawAnalysisRenderer.d.ts +1 -1
  15. package/dist/export/renderers/Renderer.d.ts +1 -1
  16. package/dist/export/renderers/ValidationRenderer.d.ts +1 -1
  17. package/dist/index.js +1425 -6511
  18. package/dist/mcp/server.js +6 -46
  19. package/dist/mcp/tools/get_file_context.js +1 -1
  20. package/dist/mcp/tools/get_project_map.js +1 -1
  21. package/dist/mcp/tools/get_strategic_overview.js +1 -1
  22. package/dist/mcp/tools/get_wild_discoveries.js +1 -1
  23. package/dist/mcp/tools/inspect_pillar.js +1 -1
  24. package/dist/mcp/tools/mark_stale.js +1 -1
  25. package/dist/mcp/tools/scan_project.d.ts +2 -3
  26. package/dist/mcp/tools/scan_project.js +12 -13
  27. package/dist/mcp/tools/set_project_brief.js +1 -1
  28. package/dist/mcp/tools/write_decision_card.d.ts +1 -1
  29. package/dist/mcp/tools/write_decision_card.js +2 -2
  30. package/dist/ui/index.html +1 -1
  31. package/package.json +9 -14
  32. package/dist/commands/bundle.d.ts +0 -4
  33. package/dist/commands/bundle.js +0 -68
  34. package/dist/commands/export.d.ts +0 -1
  35. package/dist/commands/export.js +0 -19
  36. package/dist/commands/gc.d.ts +0 -3
  37. package/dist/commands/gc.js +0 -59
  38. package/dist/commands/hook.d.ts +0 -9
  39. package/dist/commands/hook.js +0 -84
  40. package/dist/commands/importBundle.d.ts +0 -4
  41. package/dist/commands/importBundle.js +0 -80
  42. package/dist/commands/network.d.ts +0 -1
  43. package/dist/commands/network.js +0 -91
  44. package/dist/commands/scan.d.ts +0 -13
  45. package/dist/commands/scan.js +0 -97
  46. package/dist/export/renderers/DeltaRenderer.d.ts +0 -6
  47. package/dist/export/renderers/DeltaRenderer.js +0 -22
  48. package/dist/hook/preToolUse.d.ts +0 -30
  49. package/dist/hook/preToolUse.js +0 -81
  50. package/dist/hook-entry.d.ts +0 -2
  51. package/dist/hook-entry.js +0 -8
  52. package/dist/hook.d.ts +0 -1
  53. package/dist/hook.js +0 -337
  54. package/dist/mcp/BudgetGuard.d.ts +0 -13
  55. package/dist/mcp/BudgetGuard.js +0 -55
  56. package/dist/mcp/SessionScope.d.ts +0 -26
  57. package/dist/mcp/SessionScope.js +0 -56
  58. package/dist/mcp/tools/apply_patch.d.ts +0 -37
  59. package/dist/mcp/tools/apply_patch.js +0 -103
  60. package/dist/mcp/tools/explainSpecialistScope.d.ts +0 -15
  61. package/dist/mcp/tools/explainSpecialistScope.js +0 -30
  62. package/dist/mcp/tools/get_call_chain.d.ts +0 -42
  63. package/dist/mcp/tools/get_call_chain.js +0 -50
  64. package/dist/mcp/tools/get_file_skeleton.d.ts +0 -23
  65. package/dist/mcp/tools/get_file_skeleton.js +0 -124
  66. package/dist/mcp/tools/hydration/get_evidence_slice.d.ts +0 -31
  67. package/dist/mcp/tools/hydration/get_evidence_slice.js +0 -57
  68. package/dist/mcp/tools/hydration/get_project_summary.d.ts +0 -23
  69. package/dist/mcp/tools/hydration/get_project_summary.js +0 -58
  70. package/dist/mcp/tools/hydration/get_start_here.d.ts +0 -23
  71. package/dist/mcp/tools/hydration/get_start_here.js +0 -52
  72. package/dist/mcp/tools/prepareTaskContext.d.ts +0 -38
  73. package/dist/mcp/tools/prepareTaskContext.js +0 -93
  74. package/dist/mcp/tools/read_file.d.ts +0 -31
  75. package/dist/mcp/tools/read_file.js +0 -90
  76. package/dist/mcp/tools/set_session_scope.d.ts +0 -19
  77. package/dist/mcp/tools/set_session_scope.js +0 -40
  78. package/dist/mcp/tools/submit_receipt.d.ts +0 -68
  79. package/dist/mcp/tools/submit_receipt.js +0 -94
  80. package/dist/mcp/tools/work_orders.d.ts +0 -79
  81. package/dist/mcp/tools/work_orders.js +0 -126
  82. package/dist/mcp/tools/yield_for_scope_expansion.d.ts +0 -29
  83. package/dist/mcp/tools/yield_for_scope_expansion.js +0 -59
  84. package/dist/store/BlobStore.d.ts +0 -22
  85. package/dist/store/BlobStore.js +0 -96
  86. package/dist/store/PointerStore.d.ts +0 -52
  87. package/dist/store/PointerStore.js +0 -154
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "vibe-splain",
3
- "version": "3.4.2",
4
- "description": "Architectural mapping and behavioral call-chain engine. Built on a language-agnostic foundation with specialized optimization for TypeScript/JavaScript projects.",
3
+ "version": "4.0.0",
4
+ "description": "Static-analysis dossier engine for codebases: Tree-Sitter powered architectural analysis and interactive UI. Language-agnostic core, optimized for TypeScript/JavaScript.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "abp2204",
8
- "homepage": "https://github.com/abp2204/vibe-splain#readme",
8
+ "homepage": "https://github.com/abp2204/vibesplain#readme",
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/abp2204/vibe-splain.git",
11
+ "url": "git+https://github.com/abp2204/vibesplain.git",
12
12
  "directory": "packages/cli"
13
13
  },
14
14
  "bugs": {
15
- "url": "https://github.com/abp2204/vibe-splain/issues"
15
+ "url": "https://github.com/abp2204/vibesplain/issues"
16
16
  },
17
17
  "keywords": [
18
18
  "mcp",
@@ -30,33 +30,28 @@
30
30
  "node": ">=18"
31
31
  },
32
32
  "bin": {
33
- "vibe-splain": "dist/index.js"
33
+ "vibesplain": "dist/index.js"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsc && node build.mjs"
37
37
  },
38
38
  "dependencies": {
39
39
  "@modelcontextprotocol/sdk": "^1.0.0",
40
- "better-sqlite3": "^12.10.0",
41
40
  "chokidar": "^3.6.0",
42
41
  "commander": "^12.0.0",
43
42
  "fs-extra": "^11.0.0",
44
43
  "tar": "^7.5.16",
45
44
  "tree-sitter-wasms": "^0.1.11",
46
- "web-tree-sitter": "^0.22.0"
45
+ "web-tree-sitter": "^0.22.0",
46
+ "uuid": "^9.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@types/better-sqlite3": "^7.6.13",
50
49
  "@types/fs-extra": "^11.0.0",
51
- "@types/minimatch": "^5.1.2",
52
50
  "@types/tar": "^6.1.13",
53
51
  "@types/uuid": "^9.0.0",
54
- "async-mutex": "^0.5.0",
55
52
  "esbuild": "^0.28.0",
56
- "minimatch": "^10.2.5",
57
53
  "tsx": "^4.22.4",
58
- "typescript": "^5.4.0",
59
- "uuid": "^9.0.0"
54
+ "typescript": "^5.4.0"
60
55
  },
61
56
  "files": [
62
57
  "dist/",
@@ -1,4 +0,0 @@
1
- export declare function bundleCommand(scanId: string, opts?: {
2
- output?: string;
3
- projectRoot?: string;
4
- }): Promise<void>;
@@ -1,68 +0,0 @@
1
- import { join } from 'path';
2
- import { writeFile, mkdir, copyFile, rm } from 'fs/promises';
3
- import { existsSync } from 'fs';
4
- import * as tar from 'tar';
5
- import { PointerStore } from '../store/PointerStore.js';
6
- import { BlobStore } from '../store/BlobStore.js';
7
- export async function bundleCommand(scanId, opts = {}) {
8
- const root = opts.projectRoot ?? process.cwd();
9
- const outputPath = opts.output ?? join(root, `vibe-bundle-${scanId}.tar.gz`);
10
- console.error(`[vibe-splain bundle] Bundling scan ${scanId} from ${root}`);
11
- const pointerStore = PointerStore.open(root);
12
- const blobStore = new BlobStore(root);
13
- const pointers = pointerStore.listPointersByScan(scanId);
14
- if (pointers.length === 0) {
15
- throw new Error(`No pointers found for scanId "${scanId}"`);
16
- }
17
- // Stage bundle into a temp directory with predictable layout
18
- const stagingDir = join(root, '.vibe-splainer', 'tmp', `bundle-stage-${scanId}`);
19
- const blobsStageDir = join(stagingDir, 'blobs');
20
- await mkdir(blobsStageDir, { recursive: true });
21
- try {
22
- // Build manifest for the bundle
23
- const bundleManifest = {
24
- schemaVersion: '1.0.0',
25
- scanId,
26
- exportedAt: new Date().toISOString(),
27
- projectRoot: root,
28
- pointers: pointers.map(p => ({
29
- pointerId: p.pointerId,
30
- scanId: p.scanId,
31
- artifactName: p.artifactName,
32
- contentHash: p.contentHash,
33
- blobFile: `blobs/${p.contentHash.replace('sha256:', 'sha256_')}`,
34
- schemaVersion: p.schemaVersion,
35
- createdAt: p.createdAt,
36
- expiresAt: p.expiresAt,
37
- })),
38
- };
39
- await writeFile(join(stagingDir, 'bundle-manifest.json'), JSON.stringify(bundleManifest, null, 2), 'utf8');
40
- // Copy blobs (deduplicated by contentHash)
41
- const seen = new Set();
42
- for (const p of pointers) {
43
- const hex = p.contentHash.replace('sha256:', '');
44
- if (seen.has(hex))
45
- continue;
46
- seen.add(hex);
47
- const srcPath = p.blobPath;
48
- if (!existsSync(srcPath)) {
49
- console.error(`[vibe-splain bundle] Warning: blob missing for ${p.pointerId}: ${srcPath}`);
50
- continue;
51
- }
52
- await copyFile(srcPath, join(blobsStageDir, `sha256_${hex}`));
53
- }
54
- // Create tarball from staging directory
55
- await tar.create({
56
- gzip: true,
57
- file: outputPath,
58
- cwd: stagingDir,
59
- portable: true,
60
- }, ['.']);
61
- console.error(`[vibe-splain bundle] Bundle written: ${outputPath}`);
62
- console.error(`[vibe-splain bundle] ${pointers.length} pointers, ${seen.size} blobs`);
63
- }
64
- finally {
65
- await rm(stagingDir, { recursive: true, force: true });
66
- }
67
- }
68
- //# sourceMappingURL=bundle.js.map
@@ -1 +0,0 @@
1
- export declare function exportCommand(projectRoot: string, options: any): Promise<void>;
@@ -1,19 +0,0 @@
1
- import { readDossier } from '@vibe-splain/brain';
2
- import { ExportOrchestrator } from '../export/ExportOrchestrator.js';
3
- export async function exportCommand(projectRoot, options) {
4
- const root = projectRoot || process.cwd();
5
- console.error(`[vibe-splain] Exporting dossier for ${root}`);
6
- const dossier = await readDossier(root);
7
- if (!dossier) {
8
- console.error('[vibe-splain] Dossier not found. Run scan first.');
9
- process.exit(1);
10
- }
11
- const orchestrator = new ExportOrchestrator(root);
12
- await orchestrator.writeBundle(dossier, {
13
- format: options.format,
14
- budget: options.budget ? parseInt(options.budget, 10) : undefined,
15
- scope: options.scope,
16
- });
17
- console.error('[vibe-splain] Export complete.');
18
- }
19
- //# sourceMappingURL=export.js.map
@@ -1,3 +0,0 @@
1
- export declare function gcCommand(projectRoot?: string, opts?: {
2
- keepScans?: number;
3
- }): Promise<void>;
@@ -1,59 +0,0 @@
1
- import { join } from 'path';
2
- import { rm, readdir } from 'fs/promises';
3
- import { PointerStore } from '../store/PointerStore.js';
4
- import { BlobStore } from '../store/BlobStore.js';
5
- const DEFAULT_KEEP_SCANS = 3;
6
- export async function gcCommand(projectRoot, opts = {}) {
7
- const root = projectRoot ?? process.cwd();
8
- const keepScans = opts.keepScans ?? DEFAULT_KEEP_SCANS;
9
- console.error(`[vibe-splain gc] Running GC on ${root} (keeping last ${keepScans} scans)`);
10
- const pointerStore = PointerStore.open(root);
11
- const blobStore = new BlobStore(root);
12
- // 1. Get all scan IDs ordered by createdAt desc
13
- const allScanIds = pointerStore.listAllScanIds();
14
- console.error(`[vibe-splain gc] Found ${allScanIds.length} scans`);
15
- // Keep the N most recent by taking last N from sorted list
16
- // Scan IDs contain timestamps, sort lexicographically descending
17
- const sorted = [...allScanIds].sort().reverse();
18
- const keepIds = sorted.slice(0, keepScans);
19
- const deleteIds = sorted.slice(keepScans);
20
- if (deleteIds.length === 0) {
21
- console.error('[vibe-splain gc] Nothing to collect');
22
- return;
23
- }
24
- // 2. Collect all blob paths still referenced by kept pointers before deletion
25
- const keptPointers = keepIds.flatMap(id => pointerStore.listPointersByScan(id));
26
- const referencedBlobs = new Set(keptPointers.map(p => p.blobPath));
27
- // 3. Delete old scan pointers
28
- const deleted = await pointerStore.gcScanPointers(keepIds);
29
- console.error(`[vibe-splain gc] Deleted ${deleted} pointer rows`);
30
- // 4. Delete unreferenced blobs (reference count = 0)
31
- const allBlobs = await blobStore.listBlobPaths();
32
- let blobsDeleted = 0;
33
- for (const blobPath of allBlobs) {
34
- if (!referencedBlobs.has(blobPath)) {
35
- try {
36
- await rm(blobPath);
37
- blobsDeleted++;
38
- }
39
- catch {
40
- // ignore — may have already been deleted
41
- }
42
- }
43
- }
44
- console.error(`[vibe-splain gc] Deleted ${blobsDeleted} unreferenced blobs`);
45
- // 5. Clean up tmp dir
46
- const tmpDir = join(root, '.vibe-splainer', 'tmp');
47
- try {
48
- const tmpFiles = await readdir(tmpDir);
49
- for (const f of tmpFiles) {
50
- await rm(join(tmpDir, f), { force: true });
51
- }
52
- console.error(`[vibe-splain gc] Cleaned ${tmpFiles.length} tmp files`);
53
- }
54
- catch {
55
- // tmp dir may not exist
56
- }
57
- console.error('[vibe-splain gc] Done');
58
- }
59
- //# sourceMappingURL=gc.js.map
@@ -1,9 +0,0 @@
1
- export interface HookCommandResult {
2
- /** JSON to print to stdout, or null to print nothing (defer / exit 0). */
3
- stdout: string | null;
4
- }
5
- export declare function findProjectRoot(start: string | undefined): string | null;
6
- /** Pure-ish core: raw stdin string in, hook decision (as a string or null) out. */
7
- export declare function runHookCommand(rawStdin: string): Promise<HookCommandResult>;
8
- /** CLI entrypoint: read all of stdin, run the gate, emit the result. */
9
- export declare function hookPreToolUseCommand(): Promise<void>;
@@ -1,84 +0,0 @@
1
- // `vibe-splain hook pretooluse` — the deterministic PreToolUse gate, wired to stdio.
2
- //
3
- // Claude Code pipes a JSON describing the tool call about to run onto stdin; we
4
- // decide whether to escalate and, if so, write hook JSON to stdout. On a safe
5
- // edit (or any non-edit tool, unscanned repo, etc.) we print nothing and exit 0,
6
- // deferring to normal permission flow.
7
- //
8
- // NOTE on the console.log ban: that rule protects the MCP *server's* stdout.
9
- // This is a separate, short-lived process whose stdout IS the hook protocol —
10
- // writing JSON here is correct. Diagnostics still go to stderr.
11
- import { existsSync, writeFileSync, readFileSync } from 'fs';
12
- import { dirname, join } from 'path';
13
- import { tmpdir } from 'os';
14
- import { decidePreToolUse } from '../hook/preToolUse.js';
15
- // Walk up from `start` looking for the directory that holds a `.vibe-splainer` scan.
16
- // Returns null if none is found — an unscanned repo means the gate is inert.
17
- export function findProjectRoot(start) {
18
- let dir = start || process.cwd();
19
- // Bound the walk so a stray cwd can't traverse the whole filesystem.
20
- for (let i = 0; i < 64; i++) {
21
- if (existsSync(join(dir, '.vibe-splainer', 'analysis.json')))
22
- return dir;
23
- const parent = dirname(dir);
24
- if (parent === dir)
25
- break;
26
- dir = parent;
27
- }
28
- return null;
29
- }
30
- /** Pure-ish core: raw stdin string in, hook decision (as a string or null) out. */
31
- export async function runHookCommand(rawStdin) {
32
- let input;
33
- try {
34
- input = JSON.parse(rawStdin);
35
- }
36
- catch {
37
- return { stdout: null }; // malformed input → never block the agent
38
- }
39
- const root = findProjectRoot(input.cwd);
40
- const gatePath = root ? join(root, '.vibe-splainer', 'gate.json') : null;
41
- const gateExists = gatePath ? existsSync(gatePath) : false;
42
- let gateIndex = null;
43
- if (gateExists) {
44
- try {
45
- gateIndex = JSON.parse(readFileSync(gatePath, 'utf8'));
46
- }
47
- catch { }
48
- }
49
- const sessionId = input.session_id || 'default';
50
- const warnFile = join(tmpdir(), `vibe-splain-warn-${sessionId}`);
51
- const warningShown = existsSync(warnFile);
52
- const result = decidePreToolUse(input, gateIndex, { warningShown });
53
- if (result.action === 'defer')
54
- return { stdout: null };
55
- if (!gateIndex && result.action === 'emit') {
56
- try {
57
- writeFileSync(warnFile, '1');
58
- }
59
- catch { }
60
- }
61
- return { stdout: JSON.stringify(result.output) };
62
- }
63
- /** CLI entrypoint: read all of stdin, run the gate, emit the result. */
64
- export async function hookPreToolUseCommand() {
65
- const raw = await readStdin();
66
- const { stdout } = await runHookCommand(raw);
67
- if (stdout)
68
- process.stdout.write(stdout);
69
- // No stdout on defer; exit code stays 0.
70
- }
71
- function readStdin() {
72
- return new Promise((resolve) => {
73
- let data = '';
74
- if (process.stdin.isTTY) {
75
- resolve('');
76
- return;
77
- }
78
- process.stdin.setEncoding('utf8');
79
- process.stdin.on('data', (chunk) => { data += chunk; });
80
- process.stdin.on('end', () => resolve(data));
81
- process.stdin.on('error', () => resolve(data));
82
- });
83
- }
84
- //# sourceMappingURL=hook.js.map
@@ -1,4 +0,0 @@
1
- export declare function importBundleCommand(tarballPath: string, opts?: {
2
- projectRoot?: string;
3
- namespace?: string;
4
- }): Promise<void>;
@@ -1,80 +0,0 @@
1
- import { join } from 'path';
2
- import { readFile, mkdir, rm } from 'fs/promises';
3
- import { existsSync } from 'fs';
4
- import * as tar from 'tar';
5
- import { createHash } from 'crypto';
6
- import { BlobStore } from '../store/BlobStore.js';
7
- import { PointerStore } from '../store/PointerStore.js';
8
- export async function importBundleCommand(tarballPath, opts = {}) {
9
- const root = opts.projectRoot ?? process.cwd();
10
- const namespace = opts.namespace ?? `imported_${Date.now()}`;
11
- console.error(`[vibe-splain import] Importing ${tarballPath} into ${root} (namespace: ${namespace})`);
12
- if (!existsSync(tarballPath)) {
13
- throw new Error(`Tarball not found: ${tarballPath}`);
14
- }
15
- // Extract to a temp directory
16
- const extractDir = join(root, '.vibe-splainer', 'tmp', `import-${namespace}`);
17
- await mkdir(extractDir, { recursive: true });
18
- try {
19
- await tar.extract({
20
- file: tarballPath,
21
- cwd: extractDir,
22
- });
23
- // Read bundle manifest
24
- const manifestPath = join(extractDir, 'bundle-manifest.json');
25
- if (!existsSync(manifestPath)) {
26
- throw new Error('Invalid bundle: missing bundle-manifest.json');
27
- }
28
- const manifestRaw = await readFile(manifestPath, 'utf8');
29
- const manifest = JSON.parse(manifestRaw);
30
- if (manifest.schemaVersion !== '1.0.0') {
31
- throw new Error(`Unsupported bundle schema version: ${manifest.schemaVersion}`);
32
- }
33
- const blobStore = new BlobStore(root);
34
- const pointerStore = PointerStore.open(root);
35
- await blobStore.ensureDirs();
36
- let imported = 0;
37
- let hashErrors = 0;
38
- for (const entry of manifest.pointers) {
39
- const blobSrcPath = join(extractDir, entry.blobFile);
40
- if (!existsSync(blobSrcPath)) {
41
- console.error(`[vibe-splain import] Missing blob for pointer ${entry.pointerId}: ${entry.blobFile}`);
42
- hashErrors++;
43
- continue;
44
- }
45
- // Verify hash before importing
46
- const content = await readFile(blobSrcPath);
47
- const actualHash = `sha256:${createHash('sha256').update(content).digest('hex')}`;
48
- if (actualHash !== entry.contentHash) {
49
- console.error(`[vibe-splain import] Hash mismatch for ${entry.pointerId}: expected ${entry.contentHash}, got ${actualHash}`);
50
- hashErrors++;
51
- continue;
52
- }
53
- // Write blob to local store (atomic)
54
- const { blobPath } = await blobStore.writeAtomic(content);
55
- // Insert pointer under bundle namespace alias
56
- const namespacedPointerId = `${namespace}::${entry.pointerId}`;
57
- const namespacedScanId = `${namespace}::${entry.scanId}`;
58
- await pointerStore.insertPointer({
59
- pointerId: namespacedPointerId,
60
- scanId: namespacedScanId,
61
- artifactName: entry.artifactName,
62
- contentHash: entry.contentHash,
63
- blobPath,
64
- schemaVersion: entry.schemaVersion,
65
- createdAt: entry.createdAt,
66
- expiresAt: entry.expiresAt,
67
- });
68
- imported++;
69
- }
70
- if (hashErrors > 0) {
71
- console.error(`[vibe-splain import] Warning: ${hashErrors} blobs failed hash verification and were skipped`);
72
- }
73
- console.error(`[vibe-splain import] Imported ${imported}/${manifest.pointers.length} pointers under namespace "${namespace}"`);
74
- console.error(`[vibe-splain import] Original scanId: ${manifest.scanId} → namespaced as: ${namespace}::${manifest.scanId}`);
75
- }
76
- finally {
77
- await rm(extractDir, { recursive: true, force: true });
78
- }
79
- }
80
- //# sourceMappingURL=importBundle.js.map
@@ -1 +0,0 @@
1
- export declare function networkPlanCommand(task: string, options: any): Promise<void>;
@@ -1,91 +0,0 @@
1
- import { join, resolve } from 'path';
2
- import { readFile, writeFile, mkdir } from 'fs/promises';
3
- import { buildExpertNetworkPacket } from '@vibe-splain/brain';
4
- export async function networkPlanCommand(task, options) {
5
- const projectRoot = options.root ? resolve(options.root) : process.cwd();
6
- const maxFiles = options.maxFiles ? parseInt(options.maxFiles, 10) : 8;
7
- // Try to load scan artifact
8
- let scanArtifact = null;
9
- const artifactPath = options.scanArtifact
10
- ? resolve(options.scanArtifact)
11
- : join(projectRoot, '.vibe-splainer', 'analysis.json');
12
- try {
13
- const raw = await readFile(artifactPath, 'utf8');
14
- scanArtifact = JSON.parse(raw);
15
- }
16
- catch (err) {
17
- if (options.scanArtifact) {
18
- console.error(`[vibe-splain] Error reading scan artifact at ${artifactPath}:`, err.message);
19
- }
20
- }
21
- // Build the packet
22
- const packet = buildExpertNetworkPacket({
23
- task,
24
- projectRoot,
25
- scanArtifact,
26
- errorTrace: options.errorTrace,
27
- intendedBehavior: options.intendedBehavior,
28
- maxFiles
29
- });
30
- // Save artifacts
31
- const networkDir = join(projectRoot, '.vibe-splainer', 'network');
32
- const packetsDir = join(networkDir, 'packets');
33
- try {
34
- await mkdir(packetsDir, { recursive: true });
35
- // Save latest
36
- const latestPath = join(networkDir, 'latest_packet.json');
37
- await writeFile(latestPath, JSON.stringify(packet, null, 2), 'utf8');
38
- // Save timestamped
39
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
40
- const timestampedPath = join(packetsDir, `${timestamp}.json`);
41
- await writeFile(timestampedPath, JSON.stringify(packet, null, 2), 'utf8');
42
- if (options.json) {
43
- process.stdout.write(JSON.stringify(packet, null, 2) + '\n');
44
- }
45
- else {
46
- process.stdout.write('────────────────────────────────────────────────────────\n');
47
- process.stdout.write(' Vibe-Splain Specialist Network — Task Plan\n');
48
- process.stdout.write('────────────────────────────────────────────────────────\n');
49
- process.stdout.write(`Task: "${packet.task}"\n`);
50
- process.stdout.write(`Project Root: ${packet.projectRoot}\n`);
51
- process.stdout.write(`Primary Specialist: ${packet.route.primarySpecialist}\n`);
52
- process.stdout.write(`Panel: ${packet.route.panel.join(', ')}\n`);
53
- process.stdout.write(`Confidence: ${packet.route.confidence}\n`);
54
- process.stdout.write(`Reason: ${packet.route.reason}\n`);
55
- process.stdout.write('\nSelected Files:\n');
56
- if (packet.selectedFiles.length > 0) {
57
- packet.selectedFiles.forEach(f => {
58
- process.stdout.write(` • ${f.path} [blastRadius: ${f.blastRadius}]\n`);
59
- process.stdout.write(` Reason: ${f.reason}\n`);
60
- });
61
- }
62
- else {
63
- process.stdout.write(' (No files selected)\n');
64
- }
65
- process.stdout.write('\nRisk Warnings:\n');
66
- if (packet.riskWarnings.length > 0) {
67
- packet.riskWarnings.forEach(w => {
68
- const levelLabel = w.level === 'critical' ? '🔴 CRITICAL' : (w.level === 'warning' ? '🟡 WARNING' : 'ℹ️ INFO');
69
- process.stdout.write(` • [${levelLabel}] ${w.message}\n`);
70
- process.stdout.write(` Reason: ${w.reason}\n`);
71
- });
72
- }
73
- else {
74
- process.stdout.write(' (No risks identified)\n');
75
- }
76
- process.stdout.write('\nSmallest Safe Change Policy:\n');
77
- process.stdout.write(` ${packet.smallestSafeChangePolicy.summary}\n`);
78
- process.stdout.write('\nSaved Artifacts:\n');
79
- process.stdout.write(` • Latest: ${latestPath}\n`);
80
- process.stdout.write(` • Packet: ${timestampedPath}\n`);
81
- process.stdout.write('────────────────────────────────────────────────────────\n');
82
- }
83
- }
84
- catch (err) {
85
- console.error('[vibe-splain] Error saving network artifacts:', err.message);
86
- if (options.json) {
87
- process.stdout.write(JSON.stringify(packet, null, 2) + '\n');
88
- }
89
- }
90
- }
91
- //# sourceMappingURL=network.js.map
@@ -1,13 +0,0 @@
1
- interface ScanOptions {
2
- root?: string;
3
- out?: string;
4
- json?: boolean;
5
- }
6
- /**
7
- * Headless one-shot scan. Reuses the exact MCP scan pipeline (performScan),
8
- * relocates the artifact bundle to --out, and prints a summary. The gravity
9
- * formula is selected by the ROZE_GRAVITY_V2 env var, never a CLI flag — v2 is
10
- * still an experimental candidate (see CONTEXT.md / Phase 0).
11
- */
12
- export declare function scanCommand(options?: ScanOptions): Promise<void>;
13
- export {};
@@ -1,97 +0,0 @@
1
- import { resolve, join, dirname } from 'path';
2
- import { rm, rename, mkdir, writeFile } from 'fs/promises';
3
- import { performScan } from '../mcp/tools/scan_project.js';
4
- /**
5
- * Headless one-shot scan. Reuses the exact MCP scan pipeline (performScan),
6
- * relocates the artifact bundle to --out, and prints a summary. The gravity
7
- * formula is selected by the ROZE_GRAVITY_V2 env var, never a CLI flag — v2 is
8
- * still an experimental candidate (see CONTEXT.md / Phase 0).
9
- */
10
- export async function scanCommand(options = {}) {
11
- const root = resolve(options.root || '.');
12
- const gravityMode = process.env.ROZE_GRAVITY_V2 === '1' ? 'v2_candidate' : 'v1_default';
13
- console.error(`[roze] Scanning ${root} (gravity mode: ${gravityMode})...`);
14
- const { result, scanId } = await performScan(root);
15
- // The pipeline always writes to <root>/.roze. Relocate to --out if different
16
- // so v1 and v2 runs can coexist for comparison.
17
- const defaultDir = join(root, '.roze');
18
- const outDir = resolve(options.out || defaultDir);
19
- if (outDir !== defaultDir) {
20
- await rm(outDir, { recursive: true, force: true });
21
- await mkdir(dirname(outDir), { recursive: true });
22
- await rename(defaultDir, outDir);
23
- }
24
- // Persist the gravity mode so v1/v2 scans are self-identifying.
25
- const meta = {
26
- gravityMode,
27
- scannedAt: new Date().toISOString(),
28
- root,
29
- scanId,
30
- totalFilesScanned: result.totalFilesScanned,
31
- realSourceCount: result.realSourceCount,
32
- wildCandidateCount: result.wildCandidates.length,
33
- };
34
- await writeFile(join(outDir, 'scan_meta.json'), JSON.stringify(meta, null, 2));
35
- // Build gravity/heat lookups from the scored files for display.
36
- const gravityByPath = new Map(result.files.map(f => [f.relativePath, f.gravity]));
37
- const heatByPath = new Map(result.files.map(f => [f.relativePath, f.heat]));
38
- const topGravity = result.map.topGravity.slice(0, 12).map(p => ({
39
- path: p,
40
- gravity: Math.round(gravityByPath.get(p) ?? 0),
41
- }));
42
- const topHeat = result.map.topHeat.slice(0, 12).map(p => ({
43
- path: p,
44
- heat: Math.round(heatByPath.get(p) ?? 0),
45
- }));
46
- const wildDiscovery = result.wildCandidates.slice(0, 12).map(f => ({
47
- path: f.relativePath,
48
- heat: Math.round(f.heat),
49
- gravity: Math.round(f.gravity),
50
- topSmells: f.smells.filter(s => s.severity >= 3).slice(0, 3).map(s => s.note),
51
- }));
52
- const specialistMap = result.map.pillars.map(p => ({
53
- name: p.name,
54
- fileCount: p.memberFiles.length,
55
- }));
56
- const summary = {
57
- gravityMode,
58
- root,
59
- outDir,
60
- dossier: join(outDir, 'dossier.json'),
61
- analysis: join(outDir, 'analysis.json'),
62
- stack: result.map.stack,
63
- totalFilesScanned: result.totalFilesScanned,
64
- realSourceCount: result.realSourceCount,
65
- topGravity,
66
- topHeat,
67
- wildDiscovery,
68
- specialistMap,
69
- };
70
- if (options.json) {
71
- process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
72
- return;
73
- }
74
- const lines = [];
75
- lines.push('');
76
- lines.push(`roze scan — gravity mode: ${gravityMode}`);
77
- lines.push(` root: ${root}`);
78
- lines.push(` stack: ${result.map.stack.join(', ') || '(none detected)'}`);
79
- lines.push(` files: ${result.totalFilesScanned} scanned, ${result.realSourceCount} real-source`);
80
- lines.push('');
81
- lines.push('Top Gravity (Start Here):');
82
- topGravity.forEach((f, i) => lines.push(` ${String(i + 1).padStart(2)}. [${String(f.gravity).padStart(3)}] ${f.path}`));
83
- lines.push('');
84
- lines.push('Top Heat (Wild Discovery):');
85
- topHeat.forEach((f, i) => lines.push(` ${String(i + 1).padStart(2)}. [${String(f.heat).padStart(3)}] ${f.path}`));
86
- lines.push('');
87
- lines.push('Specialist Map (pillars):');
88
- specialistMap.forEach(p => lines.push(` - ${p.name} (${p.fileCount} files)`));
89
- lines.push('');
90
- lines.push(`Artifacts written to: ${outDir}`);
91
- lines.push(` dossier: ${join(outDir, 'dossier.json')}`);
92
- lines.push(` analysis: ${join(outDir, 'analysis.json')}`);
93
- lines.push(` meta: ${join(outDir, 'scan_meta.json')} (gravityMode: ${gravityMode})`);
94
- lines.push('');
95
- process.stdout.write(lines.join('\n'));
96
- }
97
- //# sourceMappingURL=scan.js.map
@@ -1,6 +0,0 @@
1
- import type { DossierViewModel, AnalysisStore } from '@vibe-splain/brain';
2
- import type { Renderer } from './Renderer.js';
3
- import type { Artifact } from '../ArtifactBundleWriter.js';
4
- export declare class DeltaRenderer implements Renderer {
5
- render(_viewModel: DossierViewModel, store: AnalysisStore): Artifact[];
6
- }
@@ -1,22 +0,0 @@
1
- export class DeltaRenderer {
2
- render(_viewModel, store) {
3
- const deltaTargets = Object.values(store.files)
4
- .filter(pf => pf.isRealSource)
5
- .sort((a, b) => b.gravity - a.gravity)
6
- .map(pf => ({
7
- path: pf.relativePath,
8
- gravity: Math.round(pf.gravity),
9
- isLoadBearing: pf.canonicalLoadBearing,
10
- blastRadius: pf.importedBy,
11
- pillarHint: pf.pillarHint,
12
- }));
13
- return [
14
- {
15
- type: 'delta',
16
- path: 'delta_targets.json',
17
- content: JSON.stringify(deltaTargets, null, 2),
18
- }
19
- ];
20
- }
21
- }
22
- //# sourceMappingURL=DeltaRenderer.js.map