Skip to content

feat(lsp): run a drawn behavior and report it in render IDs - #294

Merged
HuiJun merged 51 commits into
developfrom
feature/live-diagram-execution
Sep 16, 2026
Merged

HuiJun merged 51 commits into
developfrom
feature/live-diagram-execution

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

What and why

The VS Code diagram panel and the CLI draw state machines and action flows as static pictures, while the REPL can step the same behaviors textually; nothing joins the two. This PR adds the server half of live execution on a diagram: an LSP-hosted debug service that runs the behavior a view draws and reports where the run stands in that rendering's node and edge IDs, so a client can overlay it on the drawing it already has. The panel's toolbar and animation come in a follow-up that consumes this protocol.

New requests, advertised as the experimental capability openSysmlDebug:

opensysml/debug/start        { textDocument, view, target, object? }   -> snapshot
opensysml/debug/step         { session }                               -> snapshot
opensysml/debug/continue     { session }                               -> snapshot
opensysml/debug/send         { session, signal, args? }                -> snapshot
opensysml/debug/advance      { session, time }                         -> snapshot
opensysml/debug/breakpoints  { session, nodeIds }                      -> snapshot
opensysml/debug/stop         { session }                               -> snapshot
opensysml/debugChanged       (server -> client) snapshot of a session an edit moved or ended

A snapshot carries state (ready | running | waiting | suspended | completed | failed | ended), the virtual time, and everything in render IDs: activeStates (each active leaf with the composite states and regions enclosing it, outermost first), tokens ({id, node, awaiting[]}), taken edges since the previous request, queue, breakpoints, pausedAt, notes, results, root/version of the rendering it is keyed against, and a per-session revision — a debugChanged notification is captured under the session's lock but sent outside it, so it can reach the client after the answer to a later request; the client keeps the highest revision it has seen. object names a performer — a part, item or occurrence definition or usage; anything else is refused with InvalidParams — so a machine or action runs with that instance's attributes: when the instantiated object already exhibits or performs the target, the session attaches to that running behavior (ExhibitedStatesOf/PerformedActionsOf, as %state does) rather than starting a second executor beside it, and an object running it under several usages is refused as ambiguous; otherwise a fresh executor is made via CreateStateExecutorFor/CreateActionExecutorFor.

Semantics follow the REPL: step is one dispatch (change events, then the next queued event, then a do-activity round) for a machine and one Step() for an action; continue runs until the run waits, completes, fails or hits a breakpoint, holding the clock (a machine whose only pending event is due later is waiting until advance); advance moves the runtime clock through Context.AdvanceUntil, stopping at the instant a breakpoint is reached; send parses the arguments as expressions and refuses a signal no active state accepts. Breakpoints are set by render ID and mapped to graph nodes by identity, so unnamed or duplicate-named action nodes work too; state breakpoints live in the runtime (StateExecutor.SetBreakpointAt), pausing as the dispatch entering the state completes so a state left again at the same instant is paused on too.

Sessions run over a model.Workspace.NewRuntime() — a runtime on its own index over the documents as they stood, so the workspace's later reindexing does not move under a live executor. Closing a document ends the sessions started on it outright, whether or not the workspace keeps the file's text from disk. After each document open/change, watched-file or workspace-folder event, sessions are reconciled against every declaration the run reads. model.Runtime.Dependencies walks the references reachable from the target, the performer and anything a send later named (resolve.RunReferences, which also counts a bare accept Halt as a read of the signal) and records each declaration by (Doc, FQN) with its source text, trailing trivia trimmed; the closure covers the definitions typing or specializing a machine or its states, the actions an action invokes or specializes, accepted signals and their schemas, feature types, and whatever a guard, effect or argument names. Reconciliation recomputes the closure from the current workspace (Reading.Dependencies) and compares (dependencyChange): a session whose declarations are all unchanged is re-rendered and remapped to the fresh IDs, a pause at a breakpoint included (announced by debugChanged); one where a read declaration was edited or is no longer declared, no longer read, or where the run would now read a declaration it did not (a nearer definition now shadows the specialized one, so the name resolves elsewhere), or whose declared view was rewritten even while still drawing the target, is ended and released. Library declarations are not watched, since workspace edits cannot reach them. A pseudo-view has no declaration to compare, so a session on one ends only for the other reasons. A machine's queue lists every message pending on the bus, accepted by an active state or not.

A session's rendering and runtime come from one reading of the workspace: Workspace.Read runs a callback under a single read lock over a model.Reading (RenderView, NewRuntime, Declared, DeclaredView, DeclarationText), and reconciliation compares and re-renders within one reading too. The workspace keeps a generation bumped on every invalidation and the runtime records the one it was built at; every workspace mutation the server makes (didOpen, didChange, didClose, watched files, workspace folders, the initial folder walk) is applied and the sessions rebound under the session-store lock debug requests hold (debugEdit), with diagnostics and the debugChanged notifications following the unlock, so a request in flight completes at the documents it began with and the next finds the session already moved; registration of a new session happens under that lock too and reconciles the session first when the generation moved since its reading — so an edit that lands while a start is in flight either answers the start under the fresh IDs or refuses it when it rewrote the behavior, and never leaves a session mapped to stale IDs unannounced.

To make the runtime→render join possible:

  • runtime: StateExecutor.FiredTransitions()/FiredCount() log every transition taken (compound segments, fork/join branches, entry transitions — an entry transition carries the Owner body it is written in, so one into a nested state is drawn from the start marker of that body, not of the state's parent); ActionExecutor.Traversals()/TraversalCount() log every succession, with all token movement funnelled through move; Token.Within() names the nested flows a token runs in; ActionExecutor.ReplaceBreakpointsAt([]NodeBreakpoint{Within, Node}) sets breakpoints by identity on one occurrence of a node in a nested flow, keeping the stop already made at a breakpoint kept so a resumed run passes it; ActionExecutor.Resume returns a run a breakpoint suspended to running, for advance; EventQueue.Events() lists pending events in dispatch order. Both logs are captured/restored with runtime snapshots so a rolled-back speculative step leaves no trace.
  • view: LocateStates/LocateActions map lowered vertices and edges onto a rendering by declaration-relative position: kind + the declaring document + span offset within the innermost enclosing anchor of that document (the drawn declaration or one it inherits from, Node.Inherited) + ordinal among same-span siblings. A graph lowered from earlier text thus still locates after unrelated declarations moved every absolute offset, in the target's document or in the document of a general it inherits states, regions, transitions, nodes or successions from. Origin.Doc of inherited content is the document it is written in, which the lowered graphs now supply (StateGraph.DocOf/ActionGraph.DocOf, from the scope of the general's body); LocateActions takes the lowered graph.
  • model: Workspace.Read/Reading, Workspace.NewRuntime, Runtime.Declared/Named/Lookup/FQN/Dependencies/DeclarationOf/GenerationNamed resolves target and object in the view's document first, then in the one other workspace document declaring the qualified name (a view usually exposes a behavior another file declares), refusing a name two documents declare; the session records the declaring documents and rebinds through them, ending when any is closed, Reading.Dependencies, Workspace.Declared/DeclarationText/TextAt/DeclaredView/Generation.
  • lower: StateGraph.EntryOwner names the body keying a state's entry transitions.
  • resolve: RunReferences/ExpressionReferences collect the references a run resolves, bare signal triggers included.
  • runtime: a failed fork or compound route leaves none of its uncompleted segments in the fired log (unfireOnError); breakpoints may be set on pseudostates (SetBreakpointAt, PausedAt), pausing as the route passes through them.
  • model: a runtime built over a caller-supplied index keeps that index's documents the workspace does not manage.
  • runtime: ActionExecutor.StepToBreakpoint is Step honoring breakpoints the way RunToCompletion does — a token stepping onto a breakpoint node suspends the run there, one already on it pauses without moving, the next step resumes past it; opensysml/debug/step and the REPL's %step use it.

How it was verified

  • internal/lsp/debug_test.go (new): JSON round-trip of every request/snapshot shape; typed InvalidParams refusals (undrawn behavior, wrong-kind target, a performer that is no object, unknown session/node/signal, negative duration); a state-machine session over a fixture with orthogonal regions, a composite state, a timed transition, a guarded signal transition and a final state — initial configuration, step, send with expression args, advance, continue to completion, breakpoint pause and resume, taken per request; an action session over a fork/join with a nested own-flow, timed and signal waits, a decision and a final — every token and its awaited edges, traversal ordering, breakpoint by render ID on an unnamed node, failure and budget exhaustion; sessions surviving an unrelated edit (remapped IDs, debugChanged, a pause moved to the fresh ID, consecutive revisions across answers and notifications), ending on an edit to the target/performer/view, and being released on stop and shutdown; static opensysml/render unaffected.
  • internal/core/view/locate_test.go (new): vertex/transition and node/edge mapping, entry transitions, nested flows, undrawn-node fallback, stale-symbol rejection, and shifted-offset resilience for both locators. locate_inherited_test.go (new): a state machine specializing one in another document and an action specializing one declared earlier in the same document both keep locating inherited and own nodes, transitions and successions after an unrelated declaration is inserted ahead of the general.
  • internal/core/runtime/debug_api_test.go, internal/lsp/debug_test.go, internal/repl/runtime_commands_test.go: a stepped action pauses on a breakpoint node before executing it and resumes on the next step, through the executor, opensysml/debug/step and %step.
  • internal/lsp/debug_test.go also covers continue holding the clock on a machine with an event due later (state waiting, clock unchanged, advance then firing it), an advance pausing on a breakpoint state left again at the same instant with the clock held there, a session on an object exhibiting the target attaching to its machine (its timed effect happens once; an object exhibiting it twice is refused), didClose ending a session when the document's text remains on disk, a session ending when a specialized or typing definition is edited, removed or shadowed (state and action, including a definition typing a nested state) while unrelated edits still relocate, a rewritten view that still draws the target ending the session while a pseudo-view session outlives edits beside its target, and a machine's queue reporting a pending message no active state accepts; an edit landing between a session's preparation and its registration (relocated to the new IDs, or refused when it rewrote the machine by a same-length edit); a machine-level entry transition into a nested state reported from the machine's start marker.
  • internal/lsp/debug_test.go further covers the dependency lifecycle: a session ends when a performer supertype's default, an invoked action's body, a signal's schema or a feature's type is edited, when a read declaration is removed or a nearer one shadows it, and when a send names a signal the run had not read whose declaration then changes, while an edit beside those declarations only relocates; a pseudostate breakpoint pauses and clears on resume.
  • internal/lsp/debug_test.go, internal/core/runtime/debug_api_test.go: setting the same breakpoints again while paused keeps the pause and the next step resumes past it, removing and re-setting one stops the held token again, advance from a pause resumes the action and reaches the due work, and a breakpoint on one drawing of a declaration that two nested flows run stops only the token in that flow.
  • internal/core/model/render_test.go: a transition inherited from a definition in another document is labelled with its trigger and guard as written there (the workspace renderer reads every workspace document, not the viewed one alone).
  • internal/core/runtime/debug_api_test.go: a compound transition through a choice logs the segments into the choice as well as the branch taken, and a firing that fails past the choice logs none of them.
  • internal/core/resolve/references_test.go: References leaves a bare accept Halt to the event resolver while RunReferences reports it.
  • internal/core/runtime/debug_api_test.go: a failed fork and a failed route leave the fired log as it was; a pseudostate breakpoint pauses after the route through it. internal/core/model/runtime_test.go (new): a runtime keeps a definition that exists only in the caller's index; Named prefers the document's own declaration, finds a unique one in another workspace document, ignores a library's, and refuses an ambiguous name naming both documents. internal/lsp/debug_test.go: a session on a view, machine and performer split across three documents survives an unrelated edit to the machine's document, ends when the machine is rewritten or its document closed, and a duplicate declaration is refused with InvalidParams.
  • internal/core/model/reading_test.go (new): a reading's rendering, runtime, dependencies and view agree, with no trailing trivia in dependency text; an equal-length edit moves the generation while an earlier runtime keeps its own.
  • internal/core/runtime/debug_api_test.go: fired-transition and traversal ordering, fork/join segments, rollback leaving no trace, identity breakpoints, Token.Within, a state breakpoint pausing on a transient state under Advance, ClearBreakpoints.
  • Full gate locally with develop merged in and the corpus gates required: gofmt -l . clean, go build ./..., go vet ./..., go test ./..., make lint (staticcheck + gosec), scripts/changelog.py check, scripts/check-doc-ids.py.

Not in this PR: any VS Code / webview change. The panel still renders statically; the follow-up wires Step/Continue/Send/Advance/Stop, token animation and click-to-set breakpoints onto these requests.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (docs/reference/lsp.md)
  • Changelog entry added as changes/unreleased/lsp-debug-sessions.added.md
  • baselines regenerated and make docs-counts run if a gate count moved — the generated test-suite figures are regenerated
  • No internal work-item labels in the body, docs, or changelog

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/e0936f79d51248529de87f141b7807e3
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/e0936f79d51248529de87f141b7807e3?variant=devin
Requested by: @HuiJun

Add the opensysml/debug/* requests (start, step, continue, send, advance, breakpoints, stop) and the opensysml/debugChanged notification. A session runs the state machine or action a state or action view draws, with the REPL's executors, in a runtime built over the workspace, and answers every request with a snapshot keyed by the rendering's node and edge IDs: active states with the composite states and regions enclosing them, tokens with the node they sit at and the edges they took or await, queued events, notes, results and the run's status. Breakpoints are set by render ID.

Sessions survive edits that leave the target's declaration as it was, moving to the fresh IDs, and end when the target, performer or view is rewritten or removed.

To place a run on a rendering, the runtime records the transitions a state machine fires and the successions each token travels, and Token.Within names the nested flows a token runs in; view.LocateStates/LocateActions map lowered vertices and edges to render IDs by declaration-relative position; model.Workspace.NewRuntime builds a runtime over a workspace.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 14, 2026 23:19
devin-ai-integration[bot]

This comment was marked as resolved.

…tates, attach to the performer's behavior

A debug continue on a state machine runs it to quiescence at the current
instant, so an event due later leaves it waiting for an advance rather than
moving the clock to it; the snapshot reports the wait as waiting.

Breakpoints on states live in the runtime: StateExecutor.SetBreakpointAt
pauses the machine as the dispatch entering the state completes, a state
left again at the same instant included, and Context.AdvanceUntil stops an
advance at that instant so the breakpoint is reported, not run past.

A session started on an object that already exhibits or performs the target
attaches to that running behavior instead of creating a second executor
beside it, so timed effects happen once; an object running it under several
usages is refused as ambiguous, as the REPL refuses it.

Closing a document ends the sessions started on it directly, whether or not
the workspace keeps the file's text from disk.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

A session compared only the target's and performer's declarations with what
the runtime lowered, so an edit to a definition the target specializes or is
typed by left a frozen run reported under a fresh rendering, and a rewritten
view that still drew the target relocated the session the documentation said
ends. Lowered graphs now list the declarations they took content from
(StateGraph.Inherited, ActionGraph.Inherited), the root of a state or action
rendering carries where they were written (view.Node.Inherited), and
reconciliation ends the session when any of them is edited or removed, when
the fresh drawing takes content from a declaration the runtime did not, or
when the declared view's text changes; a pseudo-view has no declaration to
compare. A machine's queue now lists every message pending on the bus rather
than only those a state accepts now.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 15, 2026 01:14
…nested entry transitions where written

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…tests

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 02:13
A session recorded the target, its performer and the definitions the target
took content from, so an edit of an invoked action, an accepted signal, a
feature's type or a value a guard named left a stale runtime under fresh IDs.
The runtime now lists every declaration a run reads by following references
from the roots through the workspace's documents (model.Runtime.Dependencies,
Reading.Dependencies), a bare `accept Halt` included (resolve.RunReferences),
and a session ends when one is edited, removed, resolved elsewhere, or newly
read. A send whose signal or arguments name a declaration the run had not read
checks it the same way before posting.

Failed fork and route firings no longer leave the transitions never completed in
the fired log; pseudostate breakpoints pause where they are set; and a
standalone runtime index keeps the caller-supplied indexed documents.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 03:10
…ted content by its own document

`opensysml/debug/step` and the REPL's `%step` step an action through
`ActionExecutor.StepToBreakpoint`, which suspends the run on a node a token has
just reached, or already sits on, when a breakpoint is set there, as
`RunToCompletion` does; the next step resumes past it.

A lowered `StateGraph`/`ActionGraph` now answers `DocOf(decl)`, the document an
inherited vertex, node, region, transition or succession was written in, from
the scope of the general's body it came from. Renderings draw inherited content
with that document as its origin, and the locators measure every span against
the innermost enclosing declaration of its own document — the behavior drawn or
one it inherits — so an unrelated edit in the document of a general no longer
leaves inherited nodes and edges of a running session without a fresh render ID.
`LocateActions` takes the lowered graph it places.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

…me it on advance

Setting a debug session's breakpoints replaces the executor's identity
breakpoints without forgetting the stop already made at one kept, so a
run resumed afterwards passes the node it paused at rather than pausing
there again; a breakpoint removed and set again stops the run once more.
An advance resumes an action paused at a breakpoint before moving the
clock, as it does a machine, so the run reaches what is due by then.

An identity breakpoint now names the occurrence of a node in one nested
flow (NodeBreakpoint), so a breakpoint on one drawing of a declaration
that several nested flows run stops only the token in that flow.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 03:53
…itten in

A workspace renderer read notation from the viewed document alone, so a
trigger or guard a machine inherits from a definition in another document
lost its text and drew as a placeholder. The renderer now reads any of the
workspace's documents and the library behind them, as the REPL's does.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

A compound transition through a choice logged only the branch out of it,
since resolving the choice starts a fresh route; the segments into it are
now logged once their effects have run, under the same rollback a failed
firing already has.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

A breakpoint state's hit is staged as the state is entered, before its entry
behavior runs; a dispatch failing after that returned without consuming it, so
the next dispatch to succeed paused there, even once the breakpoint was cleared.
Each dispatch now begins with no staged hit, alongside the fired-log mark.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 15, 2026 21:38
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

Entering the state that completes the machine completed it inside the dispatch, before the dispatch checked its breakpoints, so a breakpoint on `done` never suspended anything. A dispatch that staged a breakpoint now holds the completion (`completionDue`): the machine suspends standing on the completion vertex, and the next run, step or ProcessNextEvent after a resume finishes it — exit behaviors, StateCompleted and the end of its performance happen once, then. Snapshots and held images carry the held completion; the LSP step finishes it.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 15, 2026 23:45
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
#	internal/core/runtime/state_change_trigger.go
#	internal/core/runtime/state_executor.go
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 16, 2026 01:39
The advance request's time was a plain float64, so a request that omitted it
or sent null decoded as 0 and was accepted as a zero-duration advance. The
field is now a pointer: omitted and null are refused with InvalidParams while
an explicit 0 remains a valid advance that leaves the clock where it stands.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits September 16, 2026 03:53
A debug request could run between a document update and the rebinding of
the sessions that follow it, driving the old runtime and answering render
IDs of the version the edit replaced. Every workspace mutation the server
makes (open, change, close, watched files, folders, the initial walk) now
lands under the lock debug requests hold, and the sessions are rebound
before it is released; notifications still follow the unlock.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 4 commits September 16, 2026 04:43
A machine or action kept every transition fired and succession taken for
its lifetime. Now a dispatch keeps only its own firings and a run keeps no
successions unless a debugger asks (KeepFired, KeepTraversals); FiredSince
and TraversalsSince release the records before the mark they read from,
while FiredCount and TraversalCount go on counting the released ones so
marks stay valid. Snapshots and held images carry the kept records with
their released count.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
#	internal/core/runtime/classifier_behavior.go
…am-execution

Co-Authored-By: jason.han <hanhuijun@gmail.com>

# Conflicts:
#	README.md
#	docs/project/spec-compliance.md
#	internal/core/runtime/state_executor.go
#	internal/core/runtime/state_route.go
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 16, 2026 14:32
A view usually exposes a behavior another document declares, so
debug/start looks the target and the object up in the view's document
first and then among the other documents the runtime holds, refusing a
qualified name two of them declare. A session remembers the declaring
documents and rebinds through them, ending when any is closed.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

…is closed

A close keeps a document whose file is on disk, so rebinding still found the target's and the object's documents and a cross-document session went on after either was closed. The close now ends every session standing on the closed document: the view's, the target's and the object's.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit 3969e9e into develop Sep 16, 2026
12 checks passed
@HuiJun
HuiJun deleted the feature/live-diagram-execution branch September 16, 2026 16:22
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.

1 participant