gitnexus 1.6.8-rc.10 → 1.6.8-rc.11

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.
@@ -459,7 +459,14 @@ export declare const assertSafeStoragePath: (entry: RegistryEntry) => void;
459
459
  export declare const resolveRegistryEntry: (entries: RegistryEntry[], target: string) => RegistryEntry;
460
460
  /**
461
461
  * List all registered repos from the global registry.
462
- * Optionally validates that each entry's .gitnexus/ still exists.
462
+ *
463
+ * With `validate: true`, prunes only entries whose index is *provably* gone
464
+ * (fs.access on .gitnexus/meta.json fails with ENOENT or ENOTDIR) and persists
465
+ * the result. Entries that are merely "not provably absent" — any other
466
+ * fs.access failure (EIO/EAGAIN/EBUSY/EACCES, etc.) — are KEPT, so a transient
467
+ * I/O storm cannot wipe the registry. A kept entry is therefore "not confirmed
468
+ * present," not "confirmed present"; downstream DB opens are independently and
469
+ * lazily guarded.
463
470
  */
464
471
  export declare const listRegisteredRepos: (opts?: {
465
472
  validate?: boolean;
@@ -862,7 +862,14 @@ export const resolveRegistryEntry = (entries, target) => {
862
862
  };
863
863
  /**
864
864
  * List all registered repos from the global registry.
865
- * Optionally validates that each entry's .gitnexus/ still exists.
865
+ *
866
+ * With `validate: true`, prunes only entries whose index is *provably* gone
867
+ * (fs.access on .gitnexus/meta.json fails with ENOENT or ENOTDIR) and persists
868
+ * the result. Entries that are merely "not provably absent" — any other
869
+ * fs.access failure (EIO/EAGAIN/EBUSY/EACCES, etc.) — are KEPT, so a transient
870
+ * I/O storm cannot wipe the registry. A kept entry is therefore "not confirmed
871
+ * present," not "confirmed present"; downstream DB opens are independently and
872
+ * lazily guarded.
866
873
  */
867
874
  export const listRegisteredRepos = async (opts) => {
868
875
  const entries = await readRegistry();
@@ -875,8 +882,28 @@ export const listRegisteredRepos = async (opts) => {
875
882
  await fs.access(path.join(entry.storagePath, 'meta.json'));
876
883
  valid.push(entry);
877
884
  }
878
- catch {
879
- // Index no longer exists skip
885
+ catch (err) {
886
+ // Prune ONLY when the index is provably gone: ENOENT (file absent) or
887
+ // ENOTDIR (a path component is no longer a directory). Every other
888
+ // fs.access failure keeps the entry, because the file may well still
889
+ // exist and we must not wipe the registry on a transient I/O storm
890
+ // (EIO/EAGAIN/EBUSY under swap pressure, NFS hiccups, etc.).
891
+ //
892
+ // Note: some kept codes are NOT necessarily transient — EACCES, for
893
+ // example, can be permanent (a chmod'd directory). Keeping is still the
894
+ // correct conservative choice: a stale-but-kept entry is harmless (DB
895
+ // opens are lazily guarded) and removable via `gitnexus remove`, whereas
896
+ // an over-eager prune destroys data. When in doubt, keep.
897
+ if (err?.code === 'ENOENT' || err?.code === 'ENOTDIR') {
898
+ // Index genuinely removed — safe to prune
899
+ }
900
+ else {
901
+ // Not provably absent — keep entry to prevent mass registry wipe.
902
+ // Warn so an I/O storm becomes observable instead of silently
903
+ // keeping (or, pre-fix, silently wiping) entries.
904
+ logger.warn({ name: entry.name, storagePath: entry.storagePath, code: err?.code }, 'Keeping registry entry despite fs.access failure (not provably absent); not pruning to avoid mass registry wipe.');
905
+ valid.push(entry);
906
+ }
880
907
  }
881
908
  }
882
909
  // If we pruned any entries, save the cleaned registry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.8-rc.10",
3
+ "version": "1.6.8-rc.11",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",