@zabaca/lattice 1.0.19 → 1.0.21

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 +5 -25
  2. package/dist/main.js +25 -62
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -173,15 +173,6 @@ Show relationships for a node.
173
173
  lattice rels "TypeScript" # Show all relationships for an entity
174
174
  ```
175
175
 
176
- ### `lattice validate`
177
-
178
- Validate entity references and relationships.
179
-
180
- ```bash
181
- lattice validate # Check for broken references
182
- lattice validate --fix # Attempt to fix validation issues
183
- ```
184
-
185
176
  ### `lattice ontology`
186
177
 
187
178
  Display the derived ontology from your documents.
@@ -218,23 +209,12 @@ You can back up, copy, or version control this file like any other.
218
209
 
219
210
  ### Entity Extraction
220
211
 
221
- When you run `/graph-sync`, Claude Code extracts entities from your documents and writes them to YAML frontmatter. The Lattice CLI then syncs this to DuckDB.
222
-
223
- ```yaml
224
- ---
225
- entities:
226
- - name: React
227
- type: technology
228
- description: JavaScript library for building user interfaces
229
-
230
- relationships:
231
- - source: React
232
- target: Component Architecture
233
- relation: REFERENCES
234
- ---
235
- ```
212
+ When you run `/graph-sync`, Claude Code extracts entities from your documents and writes them directly to the DuckDB database. No frontmatter required your markdown files stay clean.
236
213
 
237
- You don't need to write this manually — Claude Code handles it automatically.
214
+ The extraction identifies:
215
+ - **Entities**: People, technologies, concepts, tools, etc.
216
+ - **Relationships**: How entities connect to each other
217
+ - **Document metadata**: Title, summary, topic classification
238
218
 
239
219
  ### Database Schema
240
220
 
package/dist/main.js CHANGED
@@ -2036,6 +2036,11 @@ class DatabaseChangeDetectorService {
2036
2036
  this.hashCache.clear();
2037
2037
  this.loaded = false;
2038
2038
  }
2039
+ clearEntries(paths) {
2040
+ for (const path2 of paths) {
2041
+ this.hashCache.delete(path2);
2042
+ }
2043
+ }
2039
2044
  getContentHash(content) {
2040
2045
  return createHash3("sha256").update(content).digest("hex");
2041
2046
  }
@@ -2213,30 +2218,30 @@ class SyncService {
2213
2218
  embeddingsGenerated: 0,
2214
2219
  entityEmbeddingsGenerated: 0
2215
2220
  };
2216
- const useDbDetection = options.legacy ? false : options.useDbChangeDetection ?? true;
2217
- const useAiExtraction = options.legacy ? false : options.aiExtraction ?? true;
2221
+ const useAiExtraction = options.aiExtraction ?? true;
2218
2222
  try {
2219
2223
  await this.manifest.load();
2220
- if (useDbDetection) {
2221
- await this.dbChangeDetector.loadHashes();
2222
- if (options.verbose) {
2223
- this.logger.log(`v2 mode: Loaded ${this.dbChangeDetector.getCacheSize()} document hashes from database`);
2224
- }
2224
+ await this.dbChangeDetector.loadHashes();
2225
+ if (options.verbose) {
2226
+ this.logger.log(`Loaded ${this.dbChangeDetector.getCacheSize()} document hashes from database`);
2225
2227
  }
2226
2228
  if (options.force) {
2227
2229
  if (options.paths && options.paths.length > 0) {
2230
+ const normalizedPaths = this.pathResolver.resolveDocPaths(options.paths, { requireExists: true, requireInDocs: true });
2228
2231
  if (options.verbose) {
2229
- this.logger.log(`Force mode: marking ${options.paths.length} document(s) for re-sync`);
2232
+ this.logger.log(`Force mode: marking ${normalizedPaths.length} document(s) for re-sync`);
2230
2233
  }
2231
2234
  await this.clearManifestEntries(options.paths);
2235
+ this.dbChangeDetector.clearEntries(normalizedPaths);
2232
2236
  } else {
2233
2237
  if (options.verbose) {
2234
- this.logger.log("Force mode: clearing manifest to force full re-sync");
2238
+ this.logger.log("Force mode: clearing tracking data to force full re-sync");
2235
2239
  }
2236
2240
  await this.clearManifest();
2241
+ this.dbChangeDetector.reset();
2237
2242
  }
2238
2243
  }
2239
- const changes = await this.detectChanges(options.paths, useDbDetection);
2244
+ const changes = await this.detectChanges(options.paths);
2240
2245
  result.changes = changes;
2241
2246
  const docsToSync = [];
2242
2247
  const docsByPath = new Map;
@@ -2352,7 +2357,7 @@ class SyncService {
2352
2357
  result.duration = Date.now() - startTime;
2353
2358
  return result;
2354
2359
  }
2355
- async detectChanges(paths, useDbDetection = false) {
2360
+ async detectChanges(paths) {
2356
2361
  const changes = [];
2357
2362
  let allDocPaths = await this.parser.discoverDocuments();
2358
2363
  if (paths && paths.length > 0) {
@@ -2363,11 +2368,11 @@ class SyncService {
2363
2368
  const pathSet = new Set(normalizedPaths);
2364
2369
  allDocPaths = allDocPaths.filter((p) => pathSet.has(p));
2365
2370
  }
2366
- const trackedPaths = new Set(useDbDetection ? this.dbChangeDetector.getTrackedPaths() : this.manifest.getTrackedPaths());
2371
+ const trackedPaths = new Set(this.dbChangeDetector.getTrackedPaths());
2367
2372
  for (const docPath of allDocPaths) {
2368
2373
  try {
2369
2374
  const doc = await this.parser.parseDocument(docPath);
2370
- const changeType = useDbDetection ? this.dbChangeDetector.detectChange(docPath, doc.contentHash) : this.manifest.detectChange(docPath, doc.contentHash, doc.frontmatterHash);
2375
+ const changeType = this.dbChangeDetector.detectChange(docPath, doc.contentHash);
2371
2376
  changes.push({
2372
2377
  path: docPath,
2373
2378
  changeType,
@@ -2524,11 +2529,8 @@ class SyncService {
2524
2529
  change.embeddingGenerated = embeddingGenerated;
2525
2530
  const currentDoc = await this.parser.parseDocument(change.path);
2526
2531
  this.manifest.updateEntry(currentDoc.path, currentDoc.contentHash, currentDoc.frontmatterHash, currentDoc.entities.length, currentDoc.relationships.length);
2527
- const shouldUpdateDbHashes = options.legacy ? false : options.useDbChangeDetection ?? true;
2528
- if (shouldUpdateDbHashes) {
2529
- const embeddingSourceHash = embeddingGenerated ? currentDoc.contentHash : undefined;
2530
- await this.graph.updateDocumentHashes(currentDoc.path, currentDoc.contentHash, embeddingSourceHash);
2531
- }
2532
+ const embeddingSourceHash = embeddingGenerated ? currentDoc.contentHash : undefined;
2533
+ await this.graph.updateDocumentHashes(currentDoc.path, currentDoc.contentHash, embeddingSourceHash);
2532
2534
  break;
2533
2535
  }
2534
2536
  case "deleted": {
@@ -2679,7 +2681,6 @@ class MigrateCommand extends CommandRunner3 {
2679
2681
  if (!options.dryRun) {
2680
2682
  const result = await this.syncService.sync({
2681
2683
  force: false,
2682
- useDbChangeDetection: true,
2683
2684
  aiExtraction: true,
2684
2685
  verbose: options.verbose,
2685
2686
  embeddings: true
@@ -3118,23 +3119,16 @@ import { Injectable as Injectable16 } from "@nestjs/common";
3118
3119
  import { Command as Command6, CommandRunner as CommandRunner6, Option as Option4 } from "nest-commander";
3119
3120
  class StatusCommand extends CommandRunner6 {
3120
3121
  syncService;
3121
- manifestService;
3122
3122
  dbChangeDetector;
3123
- constructor(syncService, manifestService, dbChangeDetector) {
3123
+ constructor(syncService, dbChangeDetector) {
3124
3124
  super();
3125
3125
  this.syncService = syncService;
3126
- this.manifestService = manifestService;
3127
3126
  this.dbChangeDetector = dbChangeDetector;
3128
3127
  }
3129
3128
  async run(_inputs, options) {
3130
3129
  try {
3131
- const useDbDetection = !options.legacy;
3132
- if (useDbDetection) {
3133
- await this.dbChangeDetector.loadHashes();
3134
- } else {
3135
- await this.manifestService.load();
3136
- }
3137
- const changes = await this.syncService.detectChanges(undefined, useDbDetection);
3130
+ await this.dbChangeDetector.loadHashes();
3131
+ const changes = await this.syncService.detectChanges();
3138
3132
  const newDocs = changes.filter((c) => c.changeType === "new");
3139
3133
  const updatedDocs = changes.filter((c) => c.changeType === "updated");
3140
3134
  const deletedDocs = changes.filter((c) => c.changeType === "deleted");
@@ -3187,9 +3181,6 @@ class StatusCommand extends CommandRunner6 {
3187
3181
  parseVerbose() {
3188
3182
  return true;
3189
3183
  }
3190
- parseLegacy() {
3191
- return true;
3192
- }
3193
3184
  }
3194
3185
  __legacyDecorateClassTS([
3195
3186
  Option4({
@@ -3200,15 +3191,6 @@ __legacyDecorateClassTS([
3200
3191
  __legacyMetadataTS("design:paramtypes", []),
3201
3192
  __legacyMetadataTS("design:returntype", Boolean)
3202
3193
  ], StatusCommand.prototype, "parseVerbose", null);
3203
- __legacyDecorateClassTS([
3204
- Option4({
3205
- flags: "--legacy",
3206
- description: "Use legacy v1 mode: manifest-based change detection"
3207
- }),
3208
- __legacyMetadataTS("design:type", Function),
3209
- __legacyMetadataTS("design:paramtypes", []),
3210
- __legacyMetadataTS("design:returntype", Boolean)
3211
- ], StatusCommand.prototype, "parseLegacy", null);
3212
3194
  StatusCommand = __legacyDecorateClassTS([
3213
3195
  Injectable16(),
3214
3196
  Command6({
@@ -3217,7 +3199,6 @@ StatusCommand = __legacyDecorateClassTS([
3217
3199
  }),
3218
3200
  __legacyMetadataTS("design:paramtypes", [
3219
3201
  typeof SyncService === "undefined" ? Object : SyncService,
3220
- typeof ManifestService === "undefined" ? Object : ManifestService,
3221
3202
  typeof DatabaseChangeDetectorService === "undefined" ? Object : DatabaseChangeDetectorService
3222
3203
  ])
3223
3204
  ], StatusCommand);
@@ -3422,7 +3403,6 @@ class SyncCommand extends CommandRunner7 {
3422
3403
  paths: paths.length > 0 ? paths : undefined,
3423
3404
  skipCascade: options.skipCascade,
3424
3405
  embeddings: options.embeddings !== false,
3425
- legacy: options.legacy,
3426
3406
  aiExtraction: !options.skipExtraction
3427
3407
  };
3428
3408
  console.log(`
@@ -3444,14 +3424,9 @@ class SyncCommand extends CommandRunner7 {
3444
3424
  console.log(`\uD83D\uDEAB Embedding generation disabled
3445
3425
  `);
3446
3426
  }
3447
- if (syncOptions.legacy) {
3448
- console.log(`\uD83D\uDCDC Legacy mode: Using manifest-based change detection
3427
+ if (!syncOptions.aiExtraction) {
3428
+ console.log(`\u23ED\uFE0F AI entity extraction skipped (--skip-extraction)
3449
3429
  `);
3450
- } else {
3451
- if (!syncOptions.aiExtraction) {
3452
- console.log(`\u23ED\uFE0F AI entity extraction skipped (--skip-extraction)
3453
- `);
3454
- }
3455
3430
  }
3456
3431
  if (syncOptions.paths) {
3457
3432
  console.log(`\uD83D\uDCC1 Syncing specific paths: ${syncOptions.paths.join(", ")}
@@ -3649,9 +3624,6 @@ class SyncCommand extends CommandRunner7 {
3649
3624
  parseSkipExtraction() {
3650
3625
  return true;
3651
3626
  }
3652
- parseLegacy() {
3653
- return true;
3654
- }
3655
3627
  }
3656
3628
  __legacyDecorateClassTS([
3657
3629
  Option5({
@@ -3725,15 +3697,6 @@ __legacyDecorateClassTS([
3725
3697
  __legacyMetadataTS("design:paramtypes", []),
3726
3698
  __legacyMetadataTS("design:returntype", Boolean)
3727
3699
  ], SyncCommand.prototype, "parseSkipExtraction", null);
3728
- __legacyDecorateClassTS([
3729
- Option5({
3730
- flags: "--legacy",
3731
- description: "Use legacy v1 mode: manifest-based change detection, no AI extraction"
3732
- }),
3733
- __legacyMetadataTS("design:type", Function),
3734
- __legacyMetadataTS("design:paramtypes", []),
3735
- __legacyMetadataTS("design:returntype", Boolean)
3736
- ], SyncCommand.prototype, "parseLegacy", null);
3737
3700
  SyncCommand = __legacyDecorateClassTS([
3738
3701
  Injectable18(),
3739
3702
  Command7({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zabaca/lattice",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "Human-initiated, AI-powered knowledge graph for markdown documentation",
5
5
  "type": "module",
6
6
  "bin": {