Skip to content

built_at_commit is read from CWD, not the extraction target — stamps graphs with an unrelated repo's commit (and fabricates one for non-git targets) #2081

Description

@Kyo14363

Summary

built_at_commit is read from the current working directory's git repo, not from the target path being extracted. When you run graphify extract <target> from anywhere other than inside <target>, the graph is stamped with an unrelated commit.

The worst variant: if the target is not a git repository at all, the graph still gets stamped with the CWD repo's commit — fabricated provenance rather than an absent field.

This directly undermines the ## Graph Freshness section that GRAPH_REPORT.md emits, which instructs the reader:

  • Built from commit: <hash>
  • Run git rev-parse HEAD and compare to check if the graph is stale.

Following that instruction compares the target repo's HEAD against a foreign repo's commit. The comparison silently always mismatches (or, worse, coincidentally matches), so staleness detection cannot be trusted.

Reproduction

Minimal, two throwaway repos:

mkdir -p /tmp/repro/repo-A /tmp/repro/repo-B

cd /tmp/repro/repo-A
git init -q -b main && echo "print('A')" > a.py
git add -A && git commit -qm "repo A commit"

cd /tmp/repro/repo-B
git init -q -b main && echo "def f(): pass" > b.py
git add -A && git commit -qm "repo B commit"

git -C /tmp/repro/repo-A rev-parse HEAD   # cwd repo
git -C /tmp/repro/repo-B rev-parse HEAD   # target repo

# run from repo-A, targeting repo-B
cd /tmp/repro/repo-A
graphify extract /tmp/repro/repo-B --code-only --out /tmp/repro/out

python -c "import json;print(json.load(open('/tmp/repro/out/graphify-out/graph.json'))['built_at_commit'])"

Actual — records repo-A's commit:

repo-A HEAD (cwd)        : cdf257124f9cb3f28bdf5d98a1d2f189760551ba
repo-B HEAD (target)     : 05aa698cc0c5306c1e27a720b5f7be2effaa08d3
built_at_commit recorded : cdf257124f9cb3f28bdf5d98a1d2f189760551ba   ← repo-A

Expected05aa698c… (the target's HEAD).

Non-git target (worse)

mkdir -p /tmp/repro/repo-C-nogit
echo "def g(): pass" > /tmp/repro/repo-C-nogit/c.py

cd /tmp/repro/repo-A
graphify extract /tmp/repro/repo-C-nogit --code-only --out /tmp/repro/out-c

built_at_commit is cdf257124f9c… — repo-A's commit, for a target that has no git history whatsoever. Expected here is null / field omitted.

Real-world impact

Hit while evaluating graphify across three unrelated local projects in one session. All three graphs were stamped with the same commit — the commit of the shell's CWD — while the actual targets were at different HEADs and one wasn't a git repo:

target target HEAD built_at_commit recorded
project 1 ebe582d5 d5474582
project 2 93dc024c d5474582
project 3 (not a git repo) d5474582

d5474582 was the CWD repo, which was never an extraction target.

This matters for any batch/CI usage where one driver directory extracts several repos, and for the check-update / staleness workflow generally.

Workaround

cd into the target before extracting:

cd /tmp/repro/repo-B && graphify extract . --code-only --out /tmp/repro/out
# → built_at_commit == 05aa698c… (correct)

Confirmed working — so the resolution appears to be purely CWD-based rather than derived from the target argument.

Suggested fix

Resolve the commit from the target path — e.g. git -C <resolved_target> rev-parse HEAD — and omit the field (or set it null) when the target is not inside a work tree. Since --out can point outside the target, deriving from --out would be wrong too.

Related

Same CWD-vs-target family, both closed, which suggests this path was missed in those sweeps:

Also adjacent in theme: #2077 (recording backend/model so a graph can be attributed to what produced it) — same provenance-integrity concern, different field.

Environment

  • graphifyy 0.9.22 (installed via uv tool install)
  • Python 3.13.7
  • Windows 11 Pro 26100, Git Bash

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions