Skip to content

Incremental --no-cluster extraction overwrites the full graph with the changed-file subset #2169

Description

@kitsupanic

Summary

After a successful full graphify extract, editing one code file and rerunning graphify extract . --code-only --no-cluster overwrites graphify-out/graph.json with only the changed file’s incremental extraction.

Unchanged nodes and edges disappear, and retained edges can point to absent endpoint nodes. --force restores the full graph.

This reproduces on upstream v8 (2fa6cd3) and PR #2134 commit 36ecb25. The PR author independently confirmed the same behavior on an unrelated 789-file TypeScript/Next.js corpus: #2134 (comment)

Environment

  • graphifyy 0.9.25
  • macOS
  • TypeScript / TSX
  • code-only extraction
  • reproduced with and without multigraph; the minimal case below uses the default simple/raw --no-cluster path

Minimal reproduction

.
├── app/add/scan.tsx
└── src/components/ScanScreen.tsx
// app/add/scan.tsx
import { ScanScreen } from '../../src/components/ScanScreen';

export default ScanScreen;
// src/components/ScanScreen.tsx
export function ScanScreen() {
  return null;
}
graphify extract . --code-only --no-cluster
# 3 nodes, 4 edges:
# imports_from, imports, contains, re_exports

printf '\n// harmless edit\n' >> app/add/scan.tsx

graphify extract . --code-only --no-cluster
# incremental scan: 1 changed, 1 unchanged
# 1 node, 3 edges

graphify extract . --code-only --no-cluster --force
# restored: 3 nodes, 4 edges

Observed result

After the incremental run:

  • only app_add_scan remains;
  • the unchanged ScanScreen.tsx file/function nodes are gone;
  • its contains edge is gone;
  • the three retained import/re-export edges target absent, absolute-path-shaped IDs.

Representative missing targets:

private_tmp_..._src_components_scanscreen_tsx
private_tmp_..._src_components_scanscreen_scanscreen

The output is therefore both incomplete and structurally invalid.

Larger-corpus confirmation

On an Expo/React Native TypeScript corpus:

  • clustered simple: 1,143 → 1,140 edges after editing app/add/scan.tsx;
  • clustered edit of another TSX file: 1,143 → 1,134 edges;
  • --no-cluster --multigraph: 556 nodes / 1,143 edges → 1 node / 0 edges;
  • --force restores the baseline.

The PR author reproduced the same pattern on a 789-file TypeScript/Next.js corpus:

  • simple: 13,001 → 12,995 edges;
  • --no-cluster: 4,586 nodes / 15,340 edges → 9 nodes / 22 edges;
  • multigraph: 13,240 → 13,234 edges;
  • --force restores all baselines.

Expected behavior

Incremental extraction should merge or replace the changed file’s freshly extracted content in the existing graph while preserving unchanged nodes and edges.

For --no-cluster, it must not serialize the changed subset over the full graph.json.

Changed-file endpoint IDs should also be normalized against the extraction root so newly extracted import edges resolve to the unchanged target nodes.

Likely area

The --no-cluster path appears to write the current incremental merged payload directly. The carry-forward path currently appears limited to format conversion, while ordinary incremental changed-file runs do not carry the existing graph before replacement/deduplication.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions