@swarmvaultai/cli 0.1.29 → 0.1.31

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 (3) hide show
  1. package/README.md +31 -3
  2. package/dist/index.js +51 -6
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -41,6 +41,7 @@ swarmvault hook install
41
41
  swarmvault graph serve
42
42
  swarmvault graph export --html ./exports/graph.html
43
43
  swarmvault graph export --cypher ./exports/graph.cypher
44
+ swarmvault graph push neo4j --dry-run
44
45
  ```
45
46
 
46
47
  ## Commands
@@ -134,7 +135,8 @@ Measure graph-guided context reduction against a naive full-corpus read.
134
135
  Inspect and resolve staged approval bundles created by `swarmvault compile --approve`.
135
136
 
136
137
  - `review list` shows pending, accepted, and rejected entry counts per bundle
137
- - `review show <approvalId>` shows each staged entry plus its current and staged content
138
+ - `review show <approvalId>` shows each staged entry plus its current and staged content, including a section-level change summary when available
139
+ - `review show <approvalId> --diff` adds a unified diff between current and staged content
138
140
  - `review accept <approvalId> [targets...]` applies pending entries to the live wiki
139
141
  - `review reject <approvalId> [targets...]` marks pending entries as rejected without mutating active wiki paths
140
142
 
@@ -178,13 +180,14 @@ Each step:
178
180
 
179
181
  The command also writes a hub page linking the root question, saved step pages, and generated follow-up questions.
180
182
 
181
- ### `swarmvault lint [--deep] [--web]`
183
+ ### `swarmvault lint [--deep] [--web] [--conflicts]`
182
184
 
183
- Run anti-drift and vault health checks such as stale pages, missing graph artifacts, and other structural issues.
185
+ Run anti-drift and vault health checks such as stale pages, missing graph artifacts, contradiction findings, and other structural issues.
184
186
 
185
187
  `--deep` adds an LLM-powered advisory pass that can report:
186
188
 
187
189
  - `coverage_gap`
190
+ - `contradiction`
188
191
  - `contradiction_candidate`
189
192
  - `missing_citation`
190
193
  - `candidate_page`
@@ -192,6 +195,8 @@ Run anti-drift and vault health checks such as stale pages, missing graph artifa
192
195
 
193
196
  `--web` can only be used with `--deep`. It enriches deep-lint findings with external evidence snippets and URLs from a configured web-search provider.
194
197
 
198
+ `--conflicts` filters the results down to contradiction-focused findings so you can audit conflicting claims without the rest of the lint output.
199
+
195
200
  ### `swarmvault watch [--lint] [--repo] [--once] [--debounce <ms>]`
196
201
 
197
202
  Watch the inbox directory and trigger import and compile cycles when files change. With `--repo`, each cycle also refreshes tracked repo roots that were previously ingested through directory ingest. With `--once`, SwarmVault runs one refresh cycle immediately instead of starting a long-running watcher. With `--lint`, each cycle also runs linting. Each cycle writes a canonical session artifact to `state/sessions/`, and compatibility run metadata is still appended to `state/jobs.ndjson`.
@@ -256,6 +261,29 @@ Export the current graph as one of four formats:
256
261
  - `--graphml` for graph-tool interoperability
257
262
  - `--cypher` for Neo4j-style import scripts
258
263
 
264
+ ### `swarmvault graph push neo4j`
265
+
266
+ Push the compiled graph directly into Neo4j over Bolt/Aura instead of writing an intermediate file.
267
+
268
+ Useful flags:
269
+
270
+ - `--uri <bolt-uri>`
271
+ - `--username <user>`
272
+ - `--password-env <env-var>`
273
+ - `--database <name>`
274
+ - `--vault-id <id>`
275
+ - `--include-third-party`
276
+ - `--include-resources`
277
+ - `--include-generated`
278
+ - `--dry-run`
279
+
280
+ Defaults:
281
+
282
+ - reads `graphSinks.neo4j` from `swarmvault.config.json` when present
283
+ - includes only `first_party` graph material unless you opt into more source classes
284
+ - namespaces every remote record by `vaultId` so multiple vaults can safely share one Neo4j database
285
+ - upserts current graph records and does not prune stale remote data yet
286
+
259
287
  ### `swarmvault install --agent <codex|claude|cursor|goose|pi|gemini|opencode|aider|copilot>`
260
288
 
261
289
  Install agent-specific rules into the current project so an agent understands the SwarmVault workspace contract and workflow.
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ import {
29
29
  loadVaultConfig,
30
30
  pathGraphVault,
31
31
  promoteCandidate,
32
+ pushGraphNeo4j,
32
33
  queryGraphVault,
33
34
  queryVault,
34
35
  readApproval,
@@ -216,9 +217,9 @@ program.name("swarmvault").description("SwarmVault is a local-first LLM wiki com
216
217
  function readCliVersion() {
217
218
  try {
218
219
  const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
219
- return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.1.29";
220
+ return typeof packageJson.version === "string" && packageJson.version.trim() ? packageJson.version : "0.1.31";
220
221
  } catch {
221
- return "0.1.29";
222
+ return "0.1.31";
222
223
  }
223
224
  }
224
225
  function parsePositiveInt(value, fallback) {
@@ -396,10 +397,11 @@ program.command("benchmark").description("Measure graph-guided context reduction
396
397
  log(`Reduction ratio: ${(result.reductionRatio * 100).toFixed(1)}%`);
397
398
  }
398
399
  });
399
- program.command("lint").description("Run anti-drift and wiki-health checks.").option("--deep", "Run LLM-powered advisory lint", false).option("--web", "Augment deep lint with configured web search", false).action(async (options) => {
400
+ program.command("lint").description("Run anti-drift and wiki-health checks.").option("--deep", "Run LLM-powered advisory lint", false).option("--web", "Augment deep lint with configured web search", false).option("--conflicts", "Filter to contradiction findings only", false).action(async (options) => {
400
401
  const findings = await lintVault(process2.cwd(), {
401
402
  deep: options.deep ?? false,
402
- web: options.web ?? false
403
+ web: options.web ?? false,
404
+ conflicts: options.conflicts ?? false
403
405
  });
404
406
  if (isJson()) {
405
407
  emitJson(findings);
@@ -414,6 +416,43 @@ program.command("lint").description("Run anti-drift and wiki-health checks.").op
414
416
  }
415
417
  });
416
418
  var graph = program.command("graph").description("Graph-related commands.");
419
+ var graphPush = graph.command("push").description("Push the compiled graph into external sinks.");
420
+ graphPush.command("neo4j").description("Push the compiled graph directly into Neo4j over Bolt/Aura.").option("--uri <bolt-uri>", "Neo4j Bolt or Aura URI").option("--username <user>", "Neo4j username").option("--password-env <env-var>", "Environment variable containing the Neo4j password").option("--database <name>", "Neo4j database name").option("--vault-id <id>", "Stable vault identifier used for shared-database namespacing").option("--batch-size <n>", "Maximum rows to write per Neo4j transaction batch").option("--include-third-party", "Also push third-party repo material", false).option("--include-resources", "Also push resource-like content", false).option("--include-generated", "Also push generated output", false).option("--dry-run", "Show what would be pushed without writing to Neo4j", false).action(
421
+ async (options) => {
422
+ const batchSize = typeof options.batchSize === "string" && options.batchSize.trim() ? parsePositiveInt(options.batchSize, 0) || void 0 : void 0;
423
+ const includeClasses = [
424
+ "first_party",
425
+ ...options.includeThirdParty ? ["third_party"] : [],
426
+ ...options.includeResources ? ["resource"] : [],
427
+ ...options.includeGenerated ? ["generated"] : []
428
+ ];
429
+ const result = await pushGraphNeo4j(process2.cwd(), {
430
+ uri: options.uri,
431
+ username: options.username,
432
+ passwordEnv: options.passwordEnv,
433
+ database: options.database,
434
+ vaultId: options.vaultId,
435
+ batchSize,
436
+ includeClasses,
437
+ dryRun: options.dryRun ?? false
438
+ });
439
+ if (isJson()) {
440
+ emitJson(result);
441
+ } else {
442
+ log(
443
+ `${result.dryRun ? "Planned" : "Pushed"} ${result.counts.nodes} nodes, ${result.counts.relationships} relationships, ${result.counts.hyperedges} hyperedges, and ${result.counts.groupMembers} group-member links to ${result.uri}/${result.database} as ${result.vaultId}.`
444
+ );
445
+ if (result.skipped.nodes || result.skipped.relationships || result.skipped.hyperedges) {
446
+ log(
447
+ `Skipped ${result.skipped.nodes} node(s), ${result.skipped.relationships} relationship(s), and ${result.skipped.hyperedges} hyperedge(s) outside the selected source classes.`
448
+ );
449
+ }
450
+ for (const warning of result.warnings) {
451
+ log(`Warning: ${warning}`);
452
+ }
453
+ }
454
+ }
455
+ );
417
456
  graph.command("serve").description("Serve the local graph viewer.").option("--port <port>", "Port override").action(async (options) => {
418
457
  const port = options.port ? parsePositiveInt(options.port, 0) || void 0 : void 0;
419
458
  const server = await startGraphServer(process2.cwd(), port);
@@ -504,8 +543,8 @@ review.command("list").description("List staged approval bundles and their resol
504
543
  );
505
544
  }
506
545
  });
507
- review.command("show").description("Show the entries inside a staged approval bundle.").argument("<approvalId>", "Approval bundle identifier").action(async (approvalId) => {
508
- const approval = await readApproval(process2.cwd(), approvalId);
546
+ review.command("show").description("Show the entries inside a staged approval bundle.").argument("<approvalId>", "Approval bundle identifier").option("--diff", "Show unified diff for each entry", false).action(async (approvalId, options) => {
547
+ const approval = await readApproval(process2.cwd(), approvalId, { diff: options.diff });
509
548
  if (isJson()) {
510
549
  emitJson(approval);
511
550
  return;
@@ -513,6 +552,12 @@ review.command("show").description("Show the entries inside a staged approval bu
513
552
  log(`${approval.approvalId} pending=${approval.pendingCount} accepted=${approval.acceptedCount} rejected=${approval.rejectedCount}`);
514
553
  for (const entry of approval.entries) {
515
554
  log(`- ${entry.status} ${entry.changeType} ${entry.pageId} ${entry.nextPath ?? entry.previousPath ?? ""}`.trim());
555
+ if (entry.changeSummary) log(` Summary: ${entry.changeSummary}`);
556
+ if (entry.diff) {
557
+ log("");
558
+ log(entry.diff);
559
+ log("");
560
+ }
516
561
  }
517
562
  });
518
563
  review.command("accept").description("Accept all pending entries, or selected entries, from a staged approval bundle.").argument("<approvalId>", "Approval bundle identifier").argument("[targets...]", "Optional page ids or paths to accept").action(async (approvalId, targets) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swarmvaultai/cli",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "Global CLI for SwarmVault.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -43,7 +43,7 @@
43
43
  "typecheck": "tsc --noEmit"
44
44
  },
45
45
  "dependencies": {
46
- "@swarmvaultai/engine": "0.1.29",
46
+ "@swarmvaultai/engine": "0.1.31",
47
47
  "commander": "^14.0.1"
48
48
  },
49
49
  "devDependencies": {