Skip to content

Review fresh controller state before restarting at a chosen Python function - #63

Draft
Jepson2k wants to merge 28 commits into
feat/run-debug-recordsfrom
feat/supervised-restart
Draft

Jepson2k wants to merge 28 commits into
feat/run-debug-recordsfrom
feat/supervised-restart

Conversation

@Jepson2k

@Jepson2k Jepson2k commented Sep 8, 2026 •

Copy link
Copy Markdown
Owner

After interruption, the editor shows prior run context and lets the builder pick any top-level function of the program that can be called without arguments, the way an industrial controller lets the operator move the program pointer to a routine. Private names, generators, skills and decorated functions are not offered, and nothing in the program runs to build the list. A top-level before_restart() is the program's restart hook, the counterpart of a controller's restart event routine: it runs in the fresh process before the chosen function on every supervised restart, never on ordinary Start, and is never offered as a place to start. Before launch it requires fresh, advancing controller state, an empty stationary queue, valid referencing, and confirmation of the physical setup. A final check detects source, session, world, tool, TCP, or pose changes since that review.

The selected function runs in a fresh Python process, which re-checks that it is still a plain function callable without arguments. Discovery does not import or execute the program; entry execution accepts only the documented restricted module initialization. Ordinary programs still start from the beginning. Stopping during launch preflight cancels launch and stops the backend. PAR6's normal idle gravity-compensation/freedrive flag does not itself prohibit restart.

Validation: managed stop/restart/pause/run-record workflows, a populated browser selection/confirmation workflow, and native PAR6 execution with six consecutive restarts passed. Lint and type checks passed. Stacked on run records. The PAR6 dependency still has the three native settling/clearance failures documented in PAR6 #78.

Companion PRs: PAROL6, PAR6. The waldoctl marker PR (#36) was closed without merging; no waldoctl change is needed.

Supervised restart uses a compact dialog with optional details and is accessible through Program → More.

Screenshots — revised interface, PAROL6 and PAR6

Captured in Chromium on September 10 from the combined feature stack; shared panels may include later PRs. PAROL6 uses fake serial; PAR6 uses par6d --sim.

PAROL6 — stopped run, selected restart entry, and current controller readiness.

PAROL6 — stopped run, selected restart entry, and current controller readiness.

PAR6 — controller state refreshed after Stop, with a restart entry selected and ready to launch.

PAR6 — controller state refreshed after Stop, with a restart entry selected and ready to launch.

PAR6 — initial guard after Stop, before refreshing controller state.

PAR6 — initial guard after Stop, before refreshing controller state.

Jepson2k and others added 24 commits September 8, 2026 03:47
# Conflicts:
#	waldo_commander/components/script_execution.py
# Conflicts:
#	waldo_commander/components/editor.py
start() cleared the tab log and log panel and overwrote last_outcome,
last_run_source_digest and the run record before the restart preflight
could refuse, so one refusal (a nudged arm, a changed TCP) replaced the
"prior run context" the review dialog exists to show. fresh_state also
treated a lost queue readback as a non-empty queue and a lost error
readback as no fault; the queue must be read, and a controller whose
action state is ERROR is a fault whether or not the ERROR query answered.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… files

The program side (StepIO) connects to a listener the GUI opens per session
(multiprocessing.connection: a named pipe on Windows, an owner-only Unix
socket file elsewhere). Control states — paused, granted steps, the pause
clock — travel down and wake a waiting program at once; command and skill
events and the program's waiting state travel up and are queued as they
arrive. Nothing is polled from disk: the three JSON files, the 256-event
window, events_lost, the per-event rewrite and the Windows file-lock path
are gone, and every program client (sync and async) shares the link.

Tests drive the real link: a 2 000-event burst arrives complete and in
order, a paused program blocks until a grant and is released by play, a
pause behind a grant survives, cleanup frees a program to run unmanaged,
recorded values only cross the owner's link, and the page-reload case
keeps the link open. The stop/blend and pause-budget cases run against
the fake-serial controller as before.

ty skipped: pre-existing DryRunRobotClient.skill_capabilities diagnostic.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A taught setup is programs/setups/<name>.py holding one SetupSnapshot
literal, and a library world is programs/worlds/<name>.py holding one
ShapeWorld literal, written the way the recorder writes programs so they
are copied, diffed and versioned with the programs that use them and can
be imported directly. Both stores compile the module from source rather
than through the import system, whose bytecode cache is keyed on mtime and
size and read back stale values on a same-second re-teach. JSON files
from earlier releases, including the old ~/.waldo-commander/setups store,
are converted on first use and removed. Live programs get their own
directory on sys.path so `from setups.bench import setup` works.

SKIP=ty: pre-existing DryRunRobotClient.skill_capabilities diagnostic.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rt shows

A function decorated as both a skill and a restart entry binds the module
name to a Skill, which is not a function and so is not a restart entry: the
dialog offered an entry that failed at launch (or a program that failed at
import, with the decorators the other way round). It is refused at discovery,
naming the conflict.

The restart event recorded its entry under a key the export does not carry, so
a shared export of a restart had no entry name in it, and none of the launch
state's fields were labelled -- the booleans exported as field_7 and field_13
with no way to tell the fault flag from the empty queue.

The dialog's failure label read `error or type(error).__name__`, and an
exception is always truthy, so the likeliest failure here -- an argless
TimeoutError from the state read -- printed nothing after the colon.

SKIP=ty: pre-existing DryRunRobotClient.skill_capabilities diagnostic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The event link is a pipe now, so the conflicts resolve toward it: the
queue-based poll_events keeps its no-loss contract and the run-record
assertions that described the old 256-event file window stay deleted,
along with the hand-kept STEPPABLE_METHODS list the command table
replaced.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
# Conflicts:
#	waldo_commander/components/script_execution.py
#	waldo_commander/services/stepping_client.py
Industrial controllers let the operator move the program pointer to
any routine and declare only the pre-start hooks, so the marker is
gone: discovery lists each top-level function callable without
arguments, skipping private names, generators, skills and decorated
functions, and the launch re-checks the signature in the fresh
process.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8zt66KjkzgZLtQuSfJd9r
@Jepson2k Jepson2k changed the title Review fresh controller state before restarting at explicit Python entries Review fresh controller state before restarting at a chosen Python function Sep 18, 2026
A top-level before_restart() is the program's restart event routine:
it runs in the fresh process before whichever function the operator
picked, never on an ordinary start, and is never offered as a place
to start from. A hook that cannot run without arguments is refused at
discovery.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N8zt66KjkzgZLtQuSfJd9r

This branch has not been deployed

No deployments
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.

2 participants