Skip to content

Focus the state machine on the rejected call - #158

Merged
CatarinaGamboa merged 11 commits into
mainfrom
feat/117-focus-state-error
Oct 24, 2026
Merged

CatarinaGamboa merged 11 commits into
mainfrom
feat/117-focus-state-error

Conversation

@CatarinaGamboa

@CatarinaGamboa CatarinaGamboa commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Closes #117.

When the State Machine view is opened from a state refinement error, it marks the rejected call on the full diagram. There are two sets of states:

  • P, the states the receiver can be in, from Found;
  • A, the states the call accepts, from Expected.

The view marks:

  • Invalid, P \ A: red outline and ✕. The call fails from here.
  • Valid, P ∩ A: green outline and ✓. The call is fine from here.
  • Accepted but not possible here, A \ P: a thin dashed yellow outline and no text. It hints at where the object could be brought.
  • The failed method: every arrow labelled with it gets a red label, including inside merged labels. The rejected call is never drawn as a new transition.

Red and green have a faint fill and yellow is outline only, so a large machine stays calm.

The full diagram is always shown. Focus mode dims what does not help with the error:

  • states outside P ∪ A;
  • constructors;
  • every method name that is neither the failed method nor a transition that moves the receiver out of a state in P to a different state. This applies to each name inside merged labels: in getOption / receive / send / … only receive stays bright.

An arrow's path is dimmed only when all of its names are. "Show all" and "Focus on error" switch the dimming off and on and keep pan and zoom. The label text is identical in both modes, so the layout does not move.

A one-line legend shows only the marks that are present: "✕ Call rejected", "✓ Call allowed" and "Allowed, but not reachable here". In light themes the dashed outline uses a darker warning colour.

One summary line sits above the diagram, e.g. "socket.receive() is rejected when socket is in state closed · allowed in state bound".

Edge cases

  • When the receiver's state is unknown (every state is possible), only A is marked, and the summary says the state is unknown.
  • With no known receiver or accepted states, or with an older server, the view behaves as on main.

Data

  • P is possibleStates (Add the receiver's possible states to the error context liquidjava-fsm#11). With an older server, it falls back to definiteFoundState and then actualStates.
  • A is expectedStates.
  • Dependency: bumps liquidjava-fsm to 0.1.5.
  • The call is matched by its exact method name from the error context, not by label text.
  • "Copy Mermaid Source" copies the plain diagram.

Screenshots

These are real verifier output in headless VS Code.

UDP chat client. The study example E_OSS_A1_22_UdpChatClient: receive after an if that may close the socket. In focus mode the following stay bright:

  • receive;
  • close and connect out of bound;
  • the accessors out of closed.

The accessors stay bright because the DatagramSocket spec writes from = "closed(this) && connected(old(this))", which is drawn as an arrow from closed to connected. That old(...) in a from is a spec error, not an extension issue.

DatagramSocket focus: only receive, close and connect stay bright

Whole UDP machine: focus in dark and light, and Show all

UDP focus, dark UDP focus, light

UDP Show all

DefaultMutableTreeNode (the issue's example). getFirstChild() after removeAllChildren():

  • childrenAllowed is invalid;
  • maybeHasChildren is accepted;
  • add, the way there, stays bright;
  • removeAllChildren is dimmed.

Tree focus, dark Tree focus, light

Dimmed unrelated state (simplified demo machine, not a real class) Dimmed unrelated state

Tests

Run against liquidjava-fsm 0.1.5 and verifier 0.0.35 from Maven Central:

  • npm run lint and npm run test:typecheck: clean.
  • npm run test:unit: 75 passed in 7 files.
  • npm test (VS Code): 8 + 1 passing.
  • Server mvn test: 24 passing.
  • Local smoke test: passed.

The new tests cover:

  • the split into Valid, Invalid and accepted states;
  • the fallbacks and the unknown-state case;
  • empty or unknown states;
  • exact method matching (receive does not match receiveAll);
  • red labels inside merged labels;
  • dimming of rendered paths and labels, per-name dimming inside merged labels, and the rule for which methods count as useful;
  • the legend;
  • dimmed constructors;
  • diagram clipping below the summary when panned;
  • the toggle keeping zoom;
  • plain Mermaid copy;
  • the computed outline styles.

Independently reviewed twice; all findings were fixed.

Known limits

🤖 Generated with Claude Code

CatarinaGamboa and others added 4 commits October 20, 2026 23:49
When the State Machine view is opened from a state refinement error, start
with a reduced diagram of the found state, the required states, and the
states on a shortest path between them. The rejected call is a note on the
found state instead of a highlighted transition, so it never reads as a
successful transition, and it is shown even when the method is absent from
the general diagram or merged into another label. A summary lists the
rejected call, Found, and Required with icons and text, and a button toggles
between the focused and the full diagram.

The view uses the receiver, expected states, conditions, and definite found
state from the liquidjava-fsm error context. When Found is not one definite
state, the found condition is shown without marking a single state. Error
contexts without these fields keep the previous highlighting by label.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mermaid draws a state with a description as an outer rect and a divider
line rather than a .label-container, so the found, required, and possible
state styles only reached the divider. Target the outer rect as well and
cover both node shapes with style tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Give a state that may be found and is also required one combined label
  and style instead of duplicate descriptions.
- Keep self loops of the called method on required states in the focused
  view, since they show where the call is allowed.
- Keep the called method highlight in the full diagram; the focused view
  shows the allowed edge without it.
- Let the pan handler ignore the error summary so its text stays selectable.
- Enable condition expansion only for the transitions actually displayed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa and others added 2 commits October 24, 2026 02:28
Rework the state error view into a minimal overlay on the full diagram.
Given the receiver's possible states and the states the call accepts,
possible states that accept the call get a green outline and a check
mark, possible states that reject it a red outline and a cross, and the
other accepted states a thin dashed warning outline. Every transition of
the called method keeps its red label. Focusing on the error dims the
states and transitions unrelated to those states, and a single button
toggles the dimming. A one line summary says where the call is rejected
and where it is allowed.

This removes the reduced diagram, the rejected call note, the found
condition node, and the state descriptions. The possible states come from
the new possibleStates field, falling back to the definite found state or
the found states; error contexts without the accepted states keep the
previous highlighting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Do not focus when the call accepts no state of the machine, fall back
  on empty possible states, and never dim when nothing is related.
- When every state is possible, only hint at the accepted states and say
  that the state of the receiver is unknown.
- Dim transitions after rendering from a Mermaid comment instead of
  wrapping their labels, so unlabeled initial transitions are dimmed
  without changing the layout between modes.
- Keep the zoom and pan when toggling the dimming.
- Copy the Mermaid source without the error overlay.
- Phrase the summary when every possible state accepts the call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa added a commit that referenced this pull request Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa and others added 2 commits October 24, 2026 02:53
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Explain the state marks in a one line legend with the same outlines,
  fills, and icons as the diagram, shown only for the marks present.
- In focus mode, dim each method name that neither is the failed method
  nor leaves a possible state for another state, including names inside
  merged labels, and dim a transition when all its methods are dimmed.
  Only styling hooks are added, so the layout matches the plain view.
- Darken the dashed outline of the other accepted states in light themes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa added a commit that referenced this pull request Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa and others added 2 commits October 24, 2026 12:40
- In focus mode, dim the initial transitions too, since the receiver
  already exists at the failing call.
- Clip the diagram to its own viewport so that panning it upwards no
  longer draws it over the error summary and legend.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The opaque background of a fully dimmed label stood out from its dimmed
transition, so make it transparent. Labels with a bright method keep it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa added a commit that referenced this pull request Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CatarinaGamboa added a commit that referenced this pull request Oct 24, 2026
@CatarinaGamboa
CatarinaGamboa merged commit 34d7611 into main Oct 24, 2026
3 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.

Focus the state machine on the rejected call and relevant states

1 participant