Summary
When graphify update discovers a community that has no saved label, it names that community after a file — README.md, vite.config.ts, SKILL.md — and writes the name into .graphify_labels.json.
That is reasonable as a fallback. The problem is where it lands: .graphify_labels.json is the file users are told to commit, because it is the curated semantic layer that makes label reuse work. So a deterministic placeholder ends up inside the artifact whose value is that it was not machine-generated, and nothing in the output says so.
Reproduction
- Clone a repository whose
graphify-out/ contains only the semantic layer (.graphify_labels.json, .graphify_labels.json.sig, .graphify_root) — no graph.json.
- Run
graphify update .
git diff graphify-out/.graphify_labels.json
What we measured
Two repositories, graphify 0.9.8, no GEMINI_API_KEY / GOOGLE_API_KEY set. Comparing the committed labels file against the one written by the rebuild:
|
|
| Committed community labels |
715 |
| Surviving the rebuild verbatim |
715 (100 %) |
| Existing labels changed |
0 |
| Communities appended by the rebuild |
36 |
| Appended names that are filenames |
36 of 36 |
Examples of the appended names: README.md, vite.config.ts, playwright.config.ts, rotation-runbook.test.ts, and SKILL.md appearing twice as the name of two different communities.
The reuse mechanism itself is excellent and worth saying plainly: 715 of 715 curated names were re-attached correctly by membership fingerprint, with zero LLM calls. Nothing was lost or overwritten. This is a hygiene issue, not a data-loss issue.
Why it matters
We recently moved our repositories to a model where the mechanical graph (graph.json, manifest.json, GRAPH_REPORT.md, intermediates) is gitignored and rebuilt locally, while only the semantic layer stays in git. That model depends entirely on the label-reuse behaviour above, and it works.
But it also makes from-empty rebuilds routine rather than rare: every fresh clone, every CI job that needs a graph, and every new worktree now starts from an empty graphify-out/. Each one appends its own placeholders to a tracked file. In a single working session we saw the drift appear three times, twice staged by tooling (git add -A) rather than by a person — caught only because we happened to be looking for it.
Suggested fix, in preference order
- Keep unlabelled communities out of the tracked file. Write newly discovered, unlabelled communities to a separate side file until a labelling pass names them, and merge them into
.graphify_labels.json only when they have real names.
- Or make it opt-out, e.g.
graphify update --no-placeholder-labels, so a caller that treats the labels file as reviewed content can decline the fallback.
- Or, at minimum, disclose it. Print how many communities were named by fallback and where, so a person staging the diff knows what they are committing. This would match what
fix(wiki): disclose truncated cross-community relationships already does elsewhere in the project — do not degrade silently, say so.
Happy to send a patch if one of these directions is welcome — flagging first rather than arriving with an unsolicited PR.
Environment
graphify 0.9.8 (PyPI graphifyy)
- Windows 11 and Ubuntu 24.04 (GitHub Actions runner), same behaviour on both
- ~9 400 nodes / 751 communities and ~42 700 nodes / 2 428 communities in the two repositories measured
Summary
When
graphify updatediscovers a community that has no saved label, it names that community after a file —README.md,vite.config.ts,SKILL.md— and writes the name into.graphify_labels.json.That is reasonable as a fallback. The problem is where it lands:
.graphify_labels.jsonis the file users are told to commit, because it is the curated semantic layer that makes label reuse work. So a deterministic placeholder ends up inside the artifact whose value is that it was not machine-generated, and nothing in the output says so.Reproduction
graphify-out/contains only the semantic layer (.graphify_labels.json,.graphify_labels.json.sig,.graphify_root) — nograph.json.graphify update .git diff graphify-out/.graphify_labels.jsonWhat we measured
Two repositories,
graphify 0.9.8, noGEMINI_API_KEY/GOOGLE_API_KEYset. Comparing the committed labels file against the one written by the rebuild:Examples of the appended names:
README.md,vite.config.ts,playwright.config.ts,rotation-runbook.test.ts, andSKILL.mdappearing twice as the name of two different communities.The reuse mechanism itself is excellent and worth saying plainly: 715 of 715 curated names were re-attached correctly by membership fingerprint, with zero LLM calls. Nothing was lost or overwritten. This is a hygiene issue, not a data-loss issue.
Why it matters
We recently moved our repositories to a model where the mechanical graph (
graph.json,manifest.json,GRAPH_REPORT.md, intermediates) is gitignored and rebuilt locally, while only the semantic layer stays in git. That model depends entirely on the label-reuse behaviour above, and it works.But it also makes from-empty rebuilds routine rather than rare: every fresh clone, every CI job that needs a graph, and every new worktree now starts from an empty
graphify-out/. Each one appends its own placeholders to a tracked file. In a single working session we saw the drift appear three times, twice staged by tooling (git add -A) rather than by a person — caught only because we happened to be looking for it.Suggested fix, in preference order
.graphify_labels.jsononly when they have real names.graphify update --no-placeholder-labels, so a caller that treats the labels file as reviewed content can decline the fallback.fix(wiki): disclose truncated cross-community relationshipsalready does elsewhere in the project — do not degrade silently, say so.Happy to send a patch if one of these directions is welcome — flagging first rather than arriving with an unsolicited PR.
Environment
graphify 0.9.8(PyPIgraphifyy)