Skip to content

graph: a code-only, pruned build; communities named by their hub; routing asks with identifiers - #85

Merged
brunogbv merged 2 commits into
mainfrom
fix/graph-code-only-pruned
Oct 10, 2026
Merged

brunogbv merged 2 commits into
mainfrom
fix/graph-code-only-pruned

Conversation

@brunogbv

Copy link
Copy Markdown
Collaborator

Summary — The umbrella's graph answered 1 of 8 symbol questions right first, with 53% of returned nodes noise: update . added 3,381 Markdown headings, and 839 library/package nodes with no source file (marola, kyo, String) were the biggest hubs, bridging repos through 1,874 references edges.

Closes #82

MIP none — not MIP-scoped
Tested ⬜ gates · ⬜ e2e · ⬜ live · ⬜ ci-only — graph --self-test red first (10 failures: one cluster-only no labels extract/update passed through) green after new cases refuses_update_and_extract and communities_named_by_hub (incl. a rebuild drops the last labels) build argv and call counts adjusted. shellcheck docs_lint tests/self-tests.sh claude plugin validate pass. Real graphify 0.9.66 build on the umbrella under strace: 0 non-AF_UNIX connects token footer 0/0 0 "Community N" placeholders no dated backup left git status --porcelain --ignored empty devkit build likewise clean. — (+1 earlier notes in the commits)
Cost $5.87 · diff-size estimate (cost-split --estimate-commit) (36f5bf4)
$6.15 · diff-size estimate (cost-split --estimate-commit) (e223b25)

What changed

  • fix(graph): build a code-only graph, pruned of library nodes (36f5bf4)
  • fix(graph): build is the only writer; communities named by their hub (e223b25)

Real builds (graphify 0.9.66, unshare -rn): devkit 701→659 nodes; umbrella 3,056→2,218 nodes, 0 without a source file, 0 self-loops, 0 Markdown nodes; report token footer 0/0; strace shows no network connect() (only local Unix sockets from Python multiprocessing); git status --porcelain --ignored empty. With marola-dev/marola#768's ignores the umbrella graph is ~1,600 nodes. 8 symbol questions on the umbrella: 2/8 right first, 23% noise without #768's ignores (1/8, 53% before this change; ~3/8, 0% with both). The remaining misses are concept questions; the routing skill now sends those to git grep and asks the graph with identifiers.

Communities are named by their hub symbol (.graphify_labels.json, no model): the 10 largest are self_test, renderCard, RunHandle, rewrite, WaterSample, GroundTruth, bash, HourlyConditions, run, OpenMeteoForecasts. graph update/extract now refuse (they would overwrite the pruned graph). Takes effect in consumers with the next release (v0.8.3).

brunogbv and others added 2 commits October 10, 2026 04:46
The umbrella's graph answered 1 of 8 symbol questions right first, with
53% of returned nodes noise: `update .` added 3,381 Markdown headings, and
839 library/package nodes with no source file (`marola`, `kyo`, `String`)
were the biggest hubs, bridging repos through 1,874 `references` edges.

`graph build` now runs `extract . --code-only --no-label`, drops every
node without a `source_file`, the edges touching one and self-loops (jq),
then `cluster-only . --no-label --graph <graph.json>`, which rewrites
graph.json, GRAPH_REPORT.md and graph.html from the pruned graph. It never
runs `update`. In 0.9.66, cluster-only calls a labelling model only when
neither `--no-label` nor a saved labels file is present; under strace it
made no connect() at all.

Before/after (graphify 0.9.66): devkit 701 -> 659 nodes, 1,508 -> 1,360
edges; umbrella 3,056 -> 2,218 nodes, 6,331 -> 3,923 edges (6,441 nodes
before this change, with `update`). The 8 questions: 2/8 right first, 23%
noise; the noise left is tests, JSON and .claude, marola-dev/marola#767.

The routing skill now says to query with identifiers and to `git grep` a
concept or behaviour word first: graphify matches symbol names, not
meanings. CHANGELOG is untouched: release.py writes the entry from commit
subjects.

Closes #82

Tested: graph --self-test red first (6 failures: build ran update, no prune, no report/HTML), green after; new cases build_is_code_only and build_prunes_library_nodes_and_self_loops, build argv expectation adjusted. shellcheck, docs_lint, tests/self-tests.sh, claude plugin validate all pass. Real graphify 0.9.66 build: devkit 659 nodes/1,360 edges, umbrella 2,218/3,923, 0 nodes without a source file, 0 self-loops, 0 Markdown nodes, "Token cost: 0 input · 0 output", git status --porcelain --ignored empty in both; umbrella 8-question eval 2/8 right first, 23% noise (was 1/8, 53%).
Cost: ~$5.87 · diff-size estimate (cost-split --estimate-commit)
Co-Authored-By: Claude <noreply@anthropic.com>
`graph extract` and `graph update` passed straight to graphify, and either
would overwrite the pruned graph with an unpruned one. Both now exit
non-zero pointing at `graph build`; the verbs are build, query, path and
explain.

With `cluster-only --no-label` every community was "Community N", which
left graph.html and GRAPH_REPORT.md unreadable. build now runs cluster-only
twice. The first assigns communities. jq then names each one after its
highest-degree member (a file node only when nothing else is there; ties
to the shortest label, then the first alphabetically) into
.graphify_labels.json, with no .sig beside it. In 0.9.66 the second pass
keeps a saved label when the community count matches, since clustering is
seeded and cids are remapped to the previous run. Otherwise it names the
community after graphify's own hub. No model is called in either branch.
`export html --labels` would have named the HTML only, not the report. A
saved named label makes cluster-only copy the graph to a dated backup dir,
so build removes that.

Umbrella, under strace -f -e trace=connect: 16 connect() calls, all
AF_UNIX (multiprocessing), none AF_INET/AF_INET6; token footer 0/0; all
172 community names in graph.json are ours. The largest: self_test,
renderCard, RunHandle, rewrite, WaterSample, GroundTruth, bash,
HourlyConditions, run, OpenMeteoForecasts.

Part of #82

Tested: graph --self-test red first (10 failures: one cluster-only, no labels, extract/update passed through), green after; new cases refuses_update_and_extract and communities_named_by_hub (incl. a rebuild drops the last labels), build argv and call counts adjusted. shellcheck, docs_lint, tests/self-tests.sh, claude plugin validate pass. Real graphify 0.9.66 build on the umbrella under strace: 0 non-AF_UNIX connects, token footer 0/0, 0 "Community N" placeholders, no dated backup left, git status --porcelain --ignored empty; devkit build likewise clean.
Cost: ~$6.15 · diff-size estimate (cost-split --estimate-commit)
Co-Authored-By: Claude <noreply@anthropic.com>
@brunogbv
brunogbv merged commit d016e91 into main Oct 10, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

graph: a code-only, pruned build, and routing that asks with identifiers

1 participant