Skip to content

manifest.json rewrites per-file "seen" timestamps on every run, so graphify-out/ is never clean and the pre-push hook never converges #2838

Description

@zero1srl

Version: graphifyy 0.9.46 · Windows 11 · Python 3.12 (uv tool install)

Summary

On unchanged code, graph.json is byte-identical across runs and graphify correctly reports No code-graph topology changes detected; outputs left untouched. But manifest.json is rewritten anyway, and the only thing that differs is the per-file seen timestamp.

Because the git hooks commit graphify-out/ wholesale, graphify-out/ is never clean, and every git push leaves one trailing graph commit behind — permanently.

Reproduction

On a clean working tree, with no source change between runs:

graphify update . && sha256sum graphify-out/graph.json
graphify update . && sha256sum graphify-out/graph.json
graphify update . && sha256sum graphify-out/graph.json

graph.json is identical all three times (same sha256), and runs 2 and 3 print No code-graph topology changes detected; outputs left untouched.

Now diff two consecutive graph commits made by the hooks:

graphify-out/manifest.json | 772 ++++++++++++++++--------------
1 file changed, 386 insertions(+), 386 deletions(-)

graph.json, GRAPH_REPORT.md and .graphify_labels.json do not appear in the diff. Every changed line is a seen field — verified, zero changed lines are anything else:

"app/admin-ui/src/App.tsx": {
  "mtime": 1785366505.196617,
- "seen": 1787000934.3112164,
+ "seen": 1787001063.5783465,
  "ast_hash": "f8f7775881b973daf0c485283570a6c1",
  "semantic_hash": "f8f7775881b973daf0c485283570a6c1"
}

386 entries, one line changed each.

Impact

The pre-push hook sees graphify-out/ as dirty, commits, and reports:

[graphify] Il grafo cambia a ogni run: committato, push lasciato passare.
           Da guardare: 'graphify update .' non converge su questo repo.

Two problems with that:

  1. It never converges. Observed three pushes in a row: the hook commits, the push transfers up to the pre-hook HEAD, and the newly created commit stays local. Re-running git push just produces another one. The repo sits permanently one graph commit ahead of origin.
  2. The message points at the wrong thing. It says the graph changes, which sends you looking for nondeterminism in extraction or clustering. The graph is fine — it's cache bookkeeping. I spent a while bisecting node/edge sets and reading _rewire_unique_stub_nodes and cluster() before diffing the manifest.

Suggested fix

Any of these would do:

  • Don't rewrite seen when no other field in the entry changed — or skip writing manifest.json entirely on the outputs left untouched path.
  • Or exclude manifest.json from the hook's change detection, since it's cache bookkeeping rather than graph content.
  • Or drop !graphify-out/manifest.json from the .gitignore template that graphify install writes, so it isn't versioned in the first place.

Workaround

Untracking it fixes it immediately, and the hook converges on the first try:

git rm --cached graphify-out/manifest.json
# remove the "!graphify-out/manifest.json" allowlist line from .gitignore

Verified on two repos: after this, git push completes with zero trailing commits and a clean working tree.

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