Skip to content

manifest.json uses absolute paths as keys — --update always triggers full rebuild on CI or different clone path #1964

Description

@varuna-zededa

Summary

manifest.json and cache/stat-index.json store absolute file paths as keys. This means --update (incremental re-extraction) always falls back to a full rebuild when the repo is cloned to a different path — including CI environments (GitHub Actions, etc.).

Reproduction

from graphify.detect import detect_incremental
from pathlib import Path

# After a full build at /original/path, copy the repo to /new/path
# then run detect_incremental from /new/path:
result = detect_incremental(Path('.'))
print(result['new_total'])   # reports ALL files as new
print(len(result['deleted_files']))  # reports ALL original files as deleted

Confirmed by copying a 193-file corpus repo from /Users/.../device-managing-portal to /private/tmp/dmp-test:

  • 193 files "deleted" (old absolute paths gone from manifest)
  • 618 files "new" (new absolute paths not in manifest)
  • Result: full re-extraction triggered instead of incremental

Root cause

manifest.json keys are absolute paths:

{
  "/Users/Varuna_1/git/device-managing-portal/backend/apps/__init__.py": {
    "mtime": 1783744253.177,
    "ast_hash": "d41d8cd98f00b204e9800998ecf8427e",
    "semantic_hash": "d41d8cd98f00b204e9800998ecf8427e"
  }
}

cache/stat-index.json has the same structure — absolute path as key, content hash as value — but the hash is never used as a fallback lookup when the path key doesn't match.

Impact

  • CI/CD broken: GitHub Actions checks out repos at /home/runner/work/<repo>/ — never matching a developer's local path. Every CI run does a full rebuild.
  • Multi-machine teams broken: developer A builds the graph, commits graphify-out/, developer B clones and runs --update — full rebuild every time.
  • graph.json itself is fine: all source_file values are already relative paths. Only the incremental bookkeeping files are affected.

Expected behavior

detect_incremental() should match files by relative path from the repo root (or by content hash as a fallback), not by absolute path. This would make graphify-out/manifest.json portable across machines and clone paths.

Suggested fix

Option A — store relative paths as manifest keys:

# Instead of: str(abs_path)  →  "/Users/.../repo/backend/foo.py"
# Use:         str(abs_path.relative_to(scan_root))  →  "backend/foo.py"

Option B — hash-first lookup: when an absolute path key misses, fall back to matching by ast_hash/semantic_hash on the file content. This is more robust (survives renames too) but requires an inverted index.

Option A is simpler and fixes the CI use case completely.

Environment

  • graphifyy version: pip show graphifyy → installed 2026-07-17
  • Python 3.12
  • macOS 25.5.0

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