Skip to content

graph: a small repository opens as clean as a large one, and no label covers another - #1337

Merged
swapnilpaliwal-sd merged 1 commit into
devfrom
fix/graph-small-repo-labels
Sep 25, 2026
Merged

swapnilpaliwal-sd merged 1 commit into
devfrom
fix/graph-small-repo-labels

Conversation

@swapnilpaliwal-sd

@swapnilpaliwal-sd swapnilpaliwal-sd commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1336

What changed

All in plugins/axiomcode/skills/axiomcode/scripts/viewer.html:

  • Chip thresholds count from the fitted view. fitAll records the zoom it chose (K0). The directory, file, type, method and library thresholds now compare k / K0 instead of k. So every repository opens the same way, with only the four busiest libraries labelled, and more labels appear as the user zooms in. Before, a small disc was fitted at a zoom that already passed every threshold.
  • No chip covers another. chip() takes the list of boxes already drawn and skips a chip that would overlap one. The hover and the selection always draw. The ambient chips (the busiest libraries, and what the zoom reveals) also give way to the rim package labels; the chips of a selection, a search or an impact do not, so a selected method's callers and callees stay labelled.
  • The "label every node when fewer than 500 are shown" pass is gone. The thresholds and the overlap check decide on their own.

Also in README.md: an image of the graph under "Why AxiomCode Graph?", docs/images/graph-selected-method.png, showing one method selected with its resolved calls drawn across an open-source Spring application.

Why the goldens moved, or why they did not

No golden moved. This change is confined to the viewer page, which no suite reads.

Evidence

Checked in a browser with the reproduction in the issue (fifteen fixtures from graph/test/java/cases/, about 260 nodes). With 0.1.0 it opens under a wall of overlapping chips; with this change it opens with four library chips, the package names on the rim and the call paths visible. A repository of a few hundred directories opens as before, except that one library chip no longer draws over the package label next to it.

The version stays at 0.1.1, which dev already carries and which is not tagged yet, so this ships in it.

Checklist

  • The three suites pass locally against the parser commit in .github/parser-ref (not applicable: no rule, parser or engine file changed)
  • Any golden that moved is explained above
  • A fix validated on more than one shape, so this is not overfitting to one case
  • Labels set, including the front end (not applicable: viewer only, no front end changed)

@swapnilpaliwal-sd swapnilpaliwal-sd added bug Something isn't working plugin the axiomcode plugin: skill + MCP layer labels Sep 25, 2026
@swapnilpaliwal-sd swapnilpaliwal-sd added bug Something isn't working plugin the axiomcode plugin: skill + MCP layer labels Sep 25, 2026
@swapnilpaliwal-sd
swapnilpaliwal-sd force-pushed the fix/graph-small-repo-labels branch from 76cf0e2 to 4456691 Compare September 25, 2026 19:31
… covers another (#1336)

The chip thresholds compared the absolute zoom, and a small disc is fitted
at a zoom that already passed all of them, so every node was labelled on
open. They now count from the zoom fitAll chose. chip() skips a box that
overlaps one already drawn; the hover and the selection always draw. Only
the ambient chips give way to the rim package labels, so a selection's
callers and callees stay labelled. The pass that labelled every node when
fewer than 500 were shown is removed.

readme: an image of the graph under "Why AxiomCode Graph?", one method
selected with its resolved calls drawn across the codebase.
@swapnilpaliwal-sd
swapnilpaliwal-sd merged commit 3f8d673 into dev Sep 25, 2026
9 checks passed
@swapnilpaliwal-sd
swapnilpaliwal-sd deleted the fix/graph-small-repo-labels branch September 25, 2026 19:36
swapnilpaliwal-sd added a commit that referenced this pull request Sep 25, 2026
* parser/readme: C# and TypeScript are documented, and usage, output and tests match the code (#1321)

* parser/readme: C# and TypeScript are documented, and usage, output and tests match the code
* parser/readme: nested type names and the spellings a query still meets
* parser: a description that does not list languages, so it cannot go stale

* index: use python3's sqlite3 module, not the sqlite3 CLI (#1329) (#1333)

* index: use python3's sqlite3 module, not the sqlite3 CLI (#1329)

axiomcode-build shelled out to the sqlite3 command-line program in four
places. Stock Ubuntu and Git for Windows do not ship it, so index exited
127 after building the graph and, under set -e, skipped the fact export
and rule warm-up, which then crashed context on a missing edge.facts.
python3 is already a stated requirement and carries sqlite3 itself.

* release: 0.1.1 (#1329); the vendored parser keeps 0.1.0

* windows: find Python as the MCP launcher does, and give bash a python3 that runs it (#1331) (#1334)

* windows: find Python the way the MCP launcher does, and give bash a python3 that runs it (#1331)

A python.org install on Windows has python.exe and py.exe and no python3, and on a
desktop Windows python3 is the Store placeholder. Every CLI verb and every hook
called python3, so all of them failed although Python was installed.

- mcp/find-python.js: AXIOMCODE_PYTHON, python3, python, py -3; the first that runs,
  by its sys.executable. launch.js now takes its list from here.
- bin/axiomcode.js and launch.js put scripts/pyshim/python3 first on bash's PATH,
  pointing at that interpreter (always on Windows, and elsewhere when python3 is not
  the one chosen).
- hooks: every command is node hooks/run.js <hook>.py, which passes stdin, stdout,
  stderr and the exit status through unchanged, and exits 0 when there is no Python
  so a hook never blocks a tool.
- scripts/axiomcode makes the same choice when run straight from a shell, as the
  skill says to without MCP tools.
- Python-started builds use AXIOMCODE_BASH when set, as server.py already does.
- tests/python_names.py: 7 checks, all red on dev; manifests.py requires the runner.
- version 0.1.1.

* ax_fresh: Git Bash's fd 9 is not a descriptor in native python.exe, so the build lock looped forever (#1331)

tests/README.md is left as it was.

* windows: run Python in UTF-8 mode, so a piped answer with → does not raise UnicodeEncodeError (#1331)

* graph: run axiomcode-build through bash; Windows cannot exec a script (#1331)

* parser stays at 0.1.0

* version.mjs: the vendored parser keeps its own version

* graph: a small repository opens as clean as a large one, and no label covers another (#1336) (#1337)

The chip thresholds compared the absolute zoom, and a small disc is fitted
at a zoom that already passed all of them, so every node was labelled on
open. They now count from the zoom fitAll chose. chip() skips a box that
overlaps one already drawn; the hover and the selection always draw. Only
the ambient chips give way to the rim package labels, so a selection's
callers and callees stay labelled. The pass that labelled every node when
fewer than 500 were shown is removed.

readme: an image of the graph under "Why AxiomCode Graph?", one method
selected with its resolved calls drawn across the codebase.

* README: replace the graph screenshot with the test-impact graph (#1338)

* README: replace the Spring graph screenshot with the test-impact graph

* README: transparent corners on the impact graph image

* path --every: bound the route enumeration by work, not only by routes found (#1341) (#1342)

Through a cycle the partial routes multiply with every hop, and when fewer than
max_paths short routes exist the heap grew until the machine ran out of memory.
The search now stops after AXIOMCODE_EVERY_BUDGET partial routes (200,000) and
says so, with how to narrow an endpoint.

* windows: the index stores '/' paths on every platform, so context and --in find their scopes (#1340) (#1343)

rel() built the index's paths with os.path.relpath, which uses the platform
separator, while every reader of the index splits on '/'. On Windows context
found no scope and exited 2. The indexer, the hooks and the verbs now build
'/'-separated keys, and --in accepts a path written with backslashes.

* engines: ship the query programs compiled, so impact and path need no Soufflé (#1330) (#1335)

build-engines compiles impact.dl, path.dl, path-opt.dl and path-every.dl on all five
platforms next to the language engines, keyed by dl_program.py's own rules id, and checks
each platform's binaries against the interpreter on a small fixture. The engine package
ships them under queries/, dl_program.py uses the one built from these rules before it
tries a local compile, and publish refuses a platform that lacks them. The nightly e2e now
indexes, runs impact and path from the installed tarballs with no souffle on PATH.

A local dl/.cache no longer reaches the npm package.

* path --every: list routes with Yen's k-shortest paths, count them up to 1000 (#1341) (#1344)

#1342 stopped the enumeration after a fixed amount of work, which kept memory
bounded but cut the route list short: on a cyclic subgraph it printed one route
where far more exist. Yen's algorithm finds each next-shortest simple route with
a bounded number of breadth-first searches, so the work grows with the routes
asked for and the ones printed are exactly the shortest. --every counts routes
up to 1000, prints the shortest --paths N (20), and past 1000 says so and asks
for a narrower endpoint.

* ci: the way into main installs the packages on all five platforms and checks every verb's answer (#1347)

* ci: the way into main installs the packages on all five platforms and runs every verb

A pull request into main now packs @axiomcode/code-graph once, and on linux-x64,
linux-arm64, win32-x64, darwin-arm64 and darwin-x64 installs it with that
platform's engine package, with no Soufflé, and for every language indexes a
case and runs impact, test-impact, path (SQL and Datalog), path --every (both)
and context. The required CI check fails unless every platform passes, so a
release is never cut from a main that has not done this.

* e2e: every query verb must return the answer a tiny project makes true, in all five languages

.github/e2e/<language> is entry() -> helper() -> leaf() and one test calling
entry(). e2e-queries.sh indexes it and requires: impact leaf lists helper as a
resolved caller; path entry leaf reaches it through helper, from SQL and from
the shipped Datalog programs; --every lists a route through helper; context
names leaf; and after a real edit to leaf, changed names it and test-impact
selects the test through the graph, not by its name. A non-zero exit or a
traceback fails. Removing the call, or the test's call, turns it red.

* context: a tree with every file at its root is scoped to the root, not refused (#1345) (#1346)

The scope menu is built from the directories above the indexed files, so a
repository whose files sit at its root had nothing to offer, and context refused
with an empty list of suggestions. The root is the one scope such a tree has:
context now uses it and says so, the way a single-package tree is handled.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working plugin the axiomcode plugin: skill + MCP layer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

graph: on a small repository the labels cover the view

1 participant