fix: a zoom level that cannot render says so, instead of looking stuck - #139
Merged
Conversation
#131) Four of the six levels can legitimately render empty, or identically to the level below, and none of them said which. Someone stepping through the picker saw the same picture repeatedly and reported the control as broken. That is the defect: the views were right, the silence was not. None of these become errors. `logical` on a k8s estate is correctly empty (#74 -- the projection's headline kinds are literal AWS::*), and `composites` with no component ownership is correctly the resource graph. They are captioned, not fixed, because there is nothing wrong with them to fix. src/zoom-notes.ts is pure and reads the FINISHED IR, so a note describes what was actually rendered rather than what the request asked for. Composites needs one extra input -- how many component edges attached -- because that is not recoverable from the IR afterwards: an estate can have zero edges either way (fountain-ops#84). addCompositeDepsCounted reports it; the silent catch that swallowed a missing component DAG now records the zero instead of shrugging. The second note is orthogonal to the zoom. A graph with nodes and no edges lays out as one flat row, which reads as a broken renderer rather than as an accurate picture of a project that declares no references. `components` and `logical` are exempt -- both lay themselves out, so edge count is not a judgement of either. Deliberately not a RouteError: those replace the canvas with a card and are for a view that could not be produced. These were produced and are honest. Verified against a live pure-k8s estate (fountain-ops on k3d): logical 0n 0e logical is an AWS projection -- no AWS resources in this estate components 5n 4e (no note) composites 11n 0e no component ownership to join -- showing the resource graph unchanged | no edges -- nothing references anything else resources 11n 0e no edges -- nothing in this estate references anything else runtime 15n 0e no edges -- nothing in this estate references anything else Closes #131 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012n8PKN49z8c6jZVA9QYwvk
This was referenced Aug 5, 2026
lex00
added a commit
that referenced
this pull request
Aug 5, 2026
…t it is empty (#140) Ported from #133, which had this and #139 -- the version I merged -- did not. Recording that plainly: #133 was open first and I implemented #131 without checking, so the better reading of this one case shipped second. #139 noted logical only when it projected zero nodes. The quiet failure is the partial one: a lens that keeps 1 of 11 renders a plausible-looking diagram of almost nothing, which reads as "this is your estate" rather than "no data". Empty at least reads as absence. `logicalKept` is #133's function under a different name, threshold and message intact. Its reasoning is kept verbatim because it is the right reasoning: a note on every logical view would be noise, and noise is how a real signal stops being read. The `* 3` cut-off is a judgement call and is better argued with than inherited. Both call sites now count before projecting, so the note can say what was dropped. Callers that cannot count keep the empty-only check -- notesFor takes the input count as optional and prefers it when present. Verified against a live pure-k8s estate: logical projected nothing from 11 resources -- it is a cloud-topology lens, and this estate declares none of the kinds it nests (behold#74) against #139's flatter "logical is an AWS projection -- no AWS resources in this estate". The count is the part that tells you it looked at something. 462 tests (7 new), tsc and build clean. Claude-Session: https://claude.ai/code/session_012n8PKN49z8c6jZVA9QYwvk Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #131.
Four of the six zoom levels can legitimately render empty, or identically to the level below, and none of them said which. Someone stepping through the picker saw the same picture repeatedly and reported the control as stuck. The views were right; the silence was not.
Nothing here becomes an error
logicalon a k8s estate is correctly empty (#74 — the projection's headline kinds are literalAWS::*).compositeswith no component ownership is correctly the resource graph (#138). These are captioned, not fixed, because there is nothing wrong with them to fix.Deliberately not a
RouteError: those replace the canvas with a card and exist for a view that could not be produced at all. These were produced and are honest — they need a caption, not an error screen.How it works
src/zoom-notes.tsis pure and reads the finished IR, so a note describes what was actually rendered rather than what the request asked for. The SPA never infers a note; it only displaysmeta.note.Composites needs one extra input — how many component edges attached — because that is not recoverable from the IR afterwards: an estate can have zero edges either way (fountain-ops#84).
addCompositeDepsCountedreports it, and the silentcatchthat swallowed a missing component DAG now records the zero instead of shrugging:} catch { - /* component DAG unavailable — leave composites as-is */ + /* component DAG unavailable — leave composites as-is, and say so */ + compositeEdgesAttached = 0; }The second note
Orthogonal to the zoom: a graph with nodes and no edges lays out as a single flat row, which reads as a broken renderer rather than as an accurate picture of a project that declares no references.
componentsandlogicalare exempt — both lay themselves out (waves, nested boxes), so edge count is not a meaningful judgement of either.Verified against a live estate
fountain-opson k3d, pure k8s,serve --env local:componentsstays silent because it renders what it promises — which is the control case that proves the notes are conditional rather than decorative.just check: tsc clean, 455 tests pass (15 new), build clean.Scope
This resolves the reported symptom without waiting on any of the projections it describes — #138, #74, chant#1489 and chant#1493 all remain open and all now announce themselves in the UI instead of looking like a dead control.
🤖 Generated with Claude Code
https://claude.ai/code/session_012n8PKN49z8c6jZVA9QYwvk