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
Expected — 05aa698c… (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
Summary
built_at_commitis read from the current working directory's git repo, not from the target path being extracted. When you rungraphify 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 Freshnesssection thatGRAPH_REPORT.mdemits, which instructs the reader: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:
Actual — records repo-A's commit:
Expected —
05aa698c…(the target's HEAD).Non-git target (worse)
built_at_commitiscdf257124f9c…— repo-A's commit, for a target that has no git history whatsoever. Expected here isnull/ 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:
built_at_commitrecordedebe582d5d5474582✗93dc024cd5474582✗d5474582✗d5474582was 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
cdinto the target before extracting: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 itnull) when the target is not inside a work tree. Since--outcan point outside the target, deriving from--outwould be wrong too.Related
Same CWD-vs-target family, both closed, which suggests this path was missed in those sweeps:
extract()writes AST cache into the analyzed source tree, bypassing CWDgraphify-out/written to corpus/CWD despite--out/--graphpointing elsewhereAlso adjacent in theme: #2077 (recording backend/model so a graph can be attributed to what produced it) — same provenance-integrity concern, different field.
Environment
uv tool install)