Skip to content

feat(runtime): draw a due do step against the dispatch under check, replay and explore - #438

Open
devin-ai-integration[bot] wants to merge 13 commits into
developfrom
feature/region-do-step-order
Open

devin-ai-integration[bot] wants to merge 13 commits into
developfrom
feature/region-do-step-order

Conversation

@devin-ai-integration

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

Copy link
Copy Markdown
Contributor

What and why

Implements the do-step site of docs/internals/design/region-order-scheduling.md: under check, replay and explore the state executor no longer runs a whole do round before it dispatches. At each unit it offers one step of each due do action and the dispatch the machine would make now together, drawn under the new ChoiceStepOrder and recorded as

choice at t=0.0: next do top, dispatch accept Stop (unordered; took dispatch accept Stop first)

with do <state> per due state (round order) followed by dispatch <event> / dispatch change <transition>, or a bare dispatch where tied events leave the event to their own draw. Once every due do action has stepped, the dispatch owed is made before another round opens. declared, reverse and seed:<n> keep running the whole round (runSteprunDoRound) and dispatch after it, so no default, declared or seed trace golden moves; runUnit routes only one-move scheduling (scheduler.oneMove()) through oneUnit.

enabledMoves mirrors oneUnit (closed round → its dispatch alone; a due round with an acting dispatch → the do steps picked by place, the dispatch moves prefixed with the pick len(due); either alone → picked only where a draw is made), so check and explore agree. risenChange records the transitions in observation order so the change-trigger alternative is named deterministically.

A dispatch is drawn only where it acts. dueDispatch previews the dispatch (eventActs, under the same probe Decide uses, rolled back): a dispatch that would fire a transition or let a do behavior parked at an accept go on competes with the due do step; one that would defer or drop the occurrence does not, since the due step may be the accept that takes it, so the occurrence waits for the round to close as under the fixed policies. Without that rule the draw spent an occurrence a do behavior was one action from accepting — a run no policy of the runtime makes and none the library orders. The two join fixtures (state_join_completion_segment_waits_for_do_behavior, state_join_completion_is_not_a_timers_expiry) therefore keep their four outcomes; behavior-semantic-oracle.md states the rule and the new fixtures' sets. Events tied at the head are judged one by one: dueDispatch previews each, the acting ones alone are the step order's dispatch alternatives (one by name, several as the bare dispatch whose dispatch order is then drawn among them alone), and nextEvent draws among that same set when the dispatch alternative is taken, so the checker's picks, replay and the runtime name one event. A tied trigger the dispatch would drop therefore hides no tied trigger it would fire (state_do_step_or_tied_dispatch: a guarded and an unguarded timer tied at the instant the do step is due, outcomes did one , did two , two ). A signal in flight is read the same way: dueDispatch takes the head, or the tied events, of the queue as deliverPendingSignal leaves it (EventQueue.With, a copy with the signal pushed under the ID and instant enqueueSignal gives it), so the signal is drawn as the queue would dispatch it — hidden by a queued event nothing accepts until the round closes, behind a queued event that acts drawn by that event's name, and named dispatch accept <signal> only once nothing is ahead of it; the descriptor never offers a dispatch the queue would not make.

Design delta. The record specified the draw at token-move granularity: a due do behavior's flow stepped one token move at a time with the machine free to dispatch after each, so a dispatch may cut a sweep anywhere. That depends on the resumable inline do body pausing per token (executeBehavior/doRun), owned elsewhere. This PR draws at do-action-step granularity: one move is one stepDoAction — one statement of an inline do body, one action of a do behavior given as actions, the unit runDoRound already steps — against the head-of-pool dispatch. That is the granularity reachable today and the one Behavior 003 A needs. Kept until the token refinement, and stated as a known limitation in spec-compliance.md and the record: check still names do round before dispatch as not enumerated where a step left a token standing before a dispatch (state_do_action_loop_timed_exit keeps its fixed-policy expected.json; the record's "exact outcomes set" for it is the token-granularity follow-up). The record's do-step section is rewritten to describe what is implemented, the acting-dispatch rule, and what the token grain changes (stepRound alone).

Finding 11 (a completion pending inside the entry front) is not in this PR: it is independent of the do-step site and stays on its own branch; the rows attributed to it in pssm-referee.md are unchanged.

PSSM referee (go run -C tools ./cmd/pssm-referee, -check, -filter "Behavior 003")

Before: 51 pass / 13 fail / 38 not-expressible / 1 differs-by-design. After: 51 / 13 / 38 / 1, with these rows moved and adjudicated per row in pssm-referee.md (baseline re-recorded with -update):

  • Behavior 003 A failpass: both admitted orders reached (S1(entry)::S1(doActivityPartI) and S1(entry) alone, the dispatch first).
  • Exiting 002 passfail: now also reaches S1(exit) — the tester's Continue dispatched before the do activity's first segment, which the exit aborts. The suite registers exactly this order for the same race one test earlier (Behavior 003 A) and not here; recorded as the suite's defect in omg-issues.md (new section and table row), no differs-by-design row added.
  • Terminate 002 failfail, reason changed: the two admitted traces with the terminating completion before the do activity's first segment are reached; the one trace left, S1(entry)::S1.1(entry)::S1.1(doActivityPartI)::S2.1(entry), is finding 11's.
  • Transition 017 failfail, reason changed: every admitted place of deep(doActivity) among the completion effects is reached; the two remaining traces are the suite defect already recorded, no new row.
  • Deferred 006 C explores more runs and reaches the same admitted traces; unchanged bucket.

Specification basis

StatePerformances.kerml StatePerformance (succession do.startShot then nonDoMiddle.startShot; middle then exit), TransitionPerformances.kerml StateTransitionPerformance (accept then transitionLinkSource.exit), PSSM 1.0 §8.5.5 do-activity concurrency, as derived in docs/internals/design/region-order-scheduling.md. Adds a row to spec-compliance.md (⚠️ Approximate: do-action-step grain, not token-move) and a Runtime known limitation; moves the design record's do-step row from designed to implemented.

How it was verified

  • go build ./..., go vet ./..., gofmt -l . (empty), go test ./... (full, -count=1), make lint — green at this head (merged with origin/develop after its layering refactor; the new tests and fixtures live under internal/exec/runtime/).
  • OPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 go test -count=1 ./tests/corpus -run 'TestTrainingExamples|TestPilotCorpora' — pass (both gates ran, corpora present).
  • make docs-check (0 broken links), python3 scripts/changelog.py check, mkdocs build --strict — green.
  • PSSM referee: bucket counts as above; -check passes against the re-recorded baseline; -filter "Behavior 003" 2 pass / 0 fail.
  • Pilot differential: go run -C tools ./cmd/pilot-diff -check reproduces every count (378 files, 347 fully agreeing; 38 agreed / 38 only ours / 1185 only the pilot's); only the examples digest moved, because the self-model's choiceKindCount is now 10, so pilot-differential-baseline.json is re-recorded with -update (digest and date only).
  • New fixtures: state_do_step_or_dispatch (outcomes did stop , stop ), state_do_step_among_completions (did m r , m did r , m r did ) and state_do_step_or_tied_dispatch (did one , did two , two ) with .expected.json, .check.expected.json and default/declared/seed-1 trace goldens; TestExecutionConformance, TestExecutionTrace, TestCheckConformanceOracles cover them.
  • robustness_region_do_step_test.go (TestRuntimeRobustnessRegionDoStep): a witness naming a state with no due do step, a dispatch not at the head, a draw at a unit offering none — each refused with ErrReplayRefused and the run restored; an endless do body under explore ends in ErrDoStepLimitExceeded.
  • step_order_tied_test.go (TestStepOrderDrawsTheActingTiedEventAlone): the check over the tied fixture is complete with the three outcomes, every witness's one step order is do top, dispatch time top 2->idle, the dispatch order is drawn exactly when the step goes first, and each witness replays to its own trace.
  • step_order_pending_signal_test.go (TestStepOrderDrawsThePendingSignalAsQueued): with Stop in flight while a do step is due, a queued Noise nothing accepts yields the one outcome did stop and no step order, a queued Go yields did go /go with the step order among do top, dispatch accept Go, and the signal alone yields did stop /stop among do top, dispatch accept Stop; every witness replays to its own trace.
  • Replay: TestReplayRefusedJoinDrawChangesNothing (the witness loses the step-order line the acting rule no longer draws; refusal at move 4, state restored), round trips of every ChoiceStepOrder spelling.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

…eplay and explore

Under one-move scheduling the state executor offers one step of each due do
action and the dispatch the machine would make now together, recorded as a
ChoiceStepOrder (`at t=<instant>: next do <state>, dispatch <event>`); once
every due do action has stepped the dispatch owed is made before another round
opens. The fixed policies keep running the whole do round before dispatching,
so no default trace moves. The checker's enabledMoves mirrors that unit, and a
change condition's transition is now named deterministically.

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

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration Bot and others added 7 commits September 19, 2026 02:51
…s suite

state_do_step_or_dispatch and state_do_step_among_completions record the draw
between a due do step and the dispatch under default, declared, seed:1 and
check; the robustness suite refuses step-order lines naming a move the unit
does not offer and bounds an endless do behavior under explore.

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

A dispatch that would defer or drop the occurrence at the head of the pool is
not drawn against a due do step: the due step may be the accept that takes it,
so the occurrence waits for the round to close, as under the fixed policies.
The join fixtures lose the incomplete-join outcome the draw reached through a
completion or timer that could not act, and the semantic oracle states the rule.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ce map and PSSM baseline

Behavior 003 A moves to pass; Exiting 002 moves to fail on the order the suite
registers for the same race in Behavior 003 A and not for this test, recorded
as the suite's defect; Terminate 002 and Transition 017 reach the do step's
admitted places and stay on their remaining reasons. The design record states
the implemented grain, one step of a do action, and the token-move grain that
follows the resumable inline do body.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ne after the self-model's choice kind count moved

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review September 19, 2026 06:38
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits September 19, 2026 06:59
…ng the dispatch against a due do step

A dispatch tied between an event that would fire and one that would be dropped
was judged as a whole and not drawn, so check and explore missed the schedules
where the firing event dispatches before the do step. dueDispatch now previews
the tied events one by one; the acting ones alone are the step order's dispatch
alternatives, and nextEvent draws among the same set when that alternative is
taken, so replay and the checker's picks name the event the runtime dispatches.

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 3 commits September 19, 2026 07:18
…eue would dispatch it

A message in flight is queued behind the events already there before the
next event is taken, so the dispatch offered against a due do step is the
head of the queue with the signal counted in, not the signal itself: a
queued event nothing accepts hides it until the round closes, a queued
event that acts is drawn by its own name, and the signal is named
(dispatch accept <signal>) only once nothing is ahead of it. The checker's
moves, replay and the run draw among that same set.

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

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

# Conflicts:
#	docs/project/pilot-differential-baseline.json
…step-order

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

# Conflicts:
#	docs/project/pilot-differential-baseline.json
#	examples/self-model/execution.sysml
#	internal/exec/runtime/robustness_region_do_step_test.go
#	internal/exec/runtime/step_order_pending_signal_test.go
#	internal/exec/runtime/step_order_tied_test.go
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.check.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.declared.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.seed-1.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.sysml
#	internal/exec/runtime/testdata/conformance/state_do_step_among_completions.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.check.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.declared.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.seed-1.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.sysml
#	internal/exec/runtime/testdata/conformance/state_do_step_or_dispatch.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.check.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.declared.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.expected.json
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.seed-1.trace.golden
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.sysml
#	internal/exec/runtime/testdata/conformance/state_do_step_or_tied_dispatch.trace.golden
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