@remnic/coding-graph 9.6.24 → 9.6.26

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
@@ -4,8 +4,7 @@
4
4
  engine: web-tree-sitter grammars, per-language symbol extractors, and the
5
5
  neutral `FileIR` intermediate representation that the graph store consumes.
6
6
 
7
- > Part of #1548 (Track B, Phase 1). Package and core wiring for PR1 (#1551
8
- > step 1 + step 2). The real backend lands in PR2 (#1551 step 3+).
7
+ > Part of Remnic's coding-knowledge layer (issue #1548).
9
8
 
10
9
  ## Install
11
10
 
@@ -15,23 +14,21 @@ npm install @remnic/coding-graph
15
14
  pnpm add @remnic/coding-graph
16
15
  ```
17
16
 
18
- ## Status (PR1)
19
-
20
- This package's public surface is **scaffolded only**:
21
-
22
- - `ENGINE_VERSION = "0.1.0-pr1"` constant
23
- - `TIER_1_LANGUAGES` (15 languages)
24
- - `CodingGraphError` tagged error class (`code: "not_implemented" | "module_load_failed"`)
25
- - `CodingGraphEngine` interface the full PR2 contract, no implementation
26
- - `createCodingGraphEngine()` throws `CodingGraphError("not_implemented", …)`
27
-
28
- Calling `createCodingGraphEngine()` *always* throws a tagged error. There
29
- is no silent stub and there is no half-working fallback. The runtime
30
- contract is observable today; PR2 fills the implementation.
31
-
32
- `web-tree-sitter` is declared as the parser engine; grammar `.wasm` assets
33
- will ship in PR2 via the `grammars/` directory listed in the package's
34
- `files` manifest.
17
+ ## What it provides
18
+
19
+ - `createCodingGraphEngine()` returns a working engine backed by a
20
+ WASM tree-sitter parser. It parses source files into the neutral `FileIR`
21
+ (symbols plus import edges) for the 15 tier-1 languages.
22
+ - `TIER_1_LANGUAGES` the supported tier-1 language list.
23
+ - `ENGINE_VERSION` / `CODING_GRAPH_ENGINE_VERSION` the engine version
24
+ string. The single source of truth lives in `@remnic/core`; this package
25
+ re-exports it so every consumer stays in lockstep.
26
+ - `CodingGraphEngine` interface and the `CodingGraphError` tagged error class.
27
+
28
+ A per-file parse failure surfaces as a tagged `{ ok: false, code: "parse_failed" }`
29
+ result rather than a thrown exception, so one unparseable file never bricks a
30
+ whole index run. Grammar `.wasm` assets ship in the `grammars/` directory listed
31
+ in the package's `files` manifest.
35
32
 
36
33
  ## How `@remnic/core` loads this
37
34
 
@@ -207,6 +207,80 @@ var GraphStore = class _GraphStore {
207
207
  }
208
208
  return this.queue.schedule(() => this.runUpsertEdges(edges));
209
209
  }
210
+ /**
211
+ * Retire stale LSP-provenance edges for a file (issue #1895).
212
+ *
213
+ * The LSP resolution pass re-derives edges from the CURRENT source on each
214
+ * run. After writing the new `lsp` edges for a file, this method deletes
215
+ * prior `lsp`-provenance edges owned by that file's nodes whose
216
+ * `(src, dst, type)` key is NOT in the asserted set. This is the LSP
217
+ * layer's side of the provenance-lifecycle contract: each layer owns its
218
+ * own stale-edge retirement (#1894 established that reindex's heuristic
219
+ * scope never touches `lsp` rows).
220
+ *
221
+ * Heuristic, trace, and semantic edges are never touched.
222
+ *
223
+ * @returns the number of retired edges.
224
+ */
225
+ reconcileLspEdges(filePath, assertedEdges) {
226
+ if (this.closed) return 0;
227
+ try {
228
+ const fileRow = expectRow(
229
+ this.db.prepare("SELECT id FROM files WHERE path = ?").get(filePath),
230
+ ["id"]
231
+ );
232
+ if (!fileRow) return 0;
233
+ const nodes = expectRows(
234
+ this.db.prepare("SELECT id, qualified_name FROM nodes WHERE file_id = ?").all(fileRow.id),
235
+ ["id", "qualified_name"]
236
+ );
237
+ if (nodes.length === 0) return 0;
238
+ const nameCount = /* @__PURE__ */ new Map();
239
+ for (const n of nodes) nameCount.set(n.qualified_name, (nameCount.get(n.qualified_name) ?? 0) + 1);
240
+ const srcMap = /* @__PURE__ */ new Map();
241
+ for (const n of nodes) {
242
+ if (nameCount.get(n.qualified_name) === 1) srcMap.set(n.qualified_name, n.id);
243
+ }
244
+ const nodeIds = nodes.map((n) => n.id);
245
+ const assertedKeys = /* @__PURE__ */ new Set();
246
+ for (const e of assertedEdges) {
247
+ const srcId = srcMap.get(e.srcQualifiedName);
248
+ if (!srcId) continue;
249
+ const dstId = resolveNodeId(e.dstQualifiedName, /* @__PURE__ */ new Map(), this.db);
250
+ if (!dstId) continue;
251
+ assertedKeys.add(`${srcId}\0${dstId}\0${e.type}`);
252
+ }
253
+ const placeholders = nodeIds.map(() => "?").join(", ");
254
+ const priorEdges = expectRows(
255
+ this.db.prepare(
256
+ `SELECT src, dst, type FROM edges
257
+ WHERE src IN (${placeholders}) AND provenance = 'lsp'`
258
+ ).all(...nodeIds),
259
+ ["src", "dst", "type"]
260
+ );
261
+ let deleted = 0;
262
+ const toDelete = [];
263
+ for (const e of priorEdges) {
264
+ const key = `${e.src}\0${e.dst}\0${e.type}`;
265
+ if (!assertedKeys.has(key)) toDelete.push([e.src, e.dst, e.type]);
266
+ }
267
+ if (toDelete.length > 0) {
268
+ const SQLITE_VARIABLE_LIMIT2 = 32766;
269
+ const PARAMS_PER_TUPLE = 3;
270
+ const MAX_TUPLES = Math.floor(SQLITE_VARIABLE_LIMIT2 / PARAMS_PER_TUPLE);
271
+ for (let i = 0; i < toDelete.length; i += MAX_TUPLES) {
272
+ const chunk = toDelete.slice(i, i + MAX_TUPLES);
273
+ const ph = chunk.map(() => "(?, ?, ?)").join(", ");
274
+ const r = this.db.prepare(`DELETE FROM edges WHERE (src, dst, type) IN (${ph})`).run(...chunk.flat());
275
+ deleted += r.changes;
276
+ }
277
+ }
278
+ return deleted;
279
+ } catch (error) {
280
+ logWriteFailure(error);
281
+ return 0;
282
+ }
283
+ }
210
284
  /** Wait for pending writes to drain — test seam. */
211
285
  async drain() {
212
286
  await this.queue.drain();
@@ -1899,4 +1973,4 @@ export {
1899
1973
  GraphStore,
1900
1974
  nodeIdFor
1901
1975
  };
1902
- //# sourceMappingURL=chunk-ZLCF3XQK.js.map
1976
+ //# sourceMappingURL=chunk-ABDBWCXU.js.map