Skip to content

fix(pi): seal the wakeup slot only against a run in flight - #237

Merged
michael-denyer merged 1 commit into
mainfrom
loop-seal-during-compaction
Oct 8, 2026
Merged

michael-denyer merged 1 commit into
mainfrom
loop-seal-during-compaction

Conversation

@michael-denyer

Copy link
Copy Markdown
Owner

Why

A /loop command typed while Pi compacts the session left the scheduler refusing wakeups for a run the command never interrupted. A self-paced loop started during /compact ran one iteration and stopped, and /loop stop during /compact made the next run unable to schedule a wakeup. The command read "not idle" as "a run is in flight", but Pi is also not idle during a compaction, and it emits agent_settled only when a run ends.

What changed

  • The scheduler tracks a run from agent_start to agent_settled and seals the wakeup slot only while one is in flight. A /loop during a compaction still waits for idle before its first prompt.
  • The notice for a deferred start now reads "The loop starts once the session is idle."
  • tla/ holds a TLA+ model of the scheduler with its TLC matrix and mutations file.

Scope

This PR fixes the compaction case. The model records two narrower findings that it leaves open, and its matrix exits 1 because of them: a /loop stop that lands between a prompt being sent and its run starting, and a new run that replaces a queued loop start within a second of the previous run ending. It bumps no version, so the fix reaches installs with the next release. No CI job runs the model yet.

Blast Radius

Only the Pi extension changes. If Pi ever skipped agent_start, a /loop during that run would not seal, and the stopped loop could return for one iteration. Pi emits agent_settled from a finally block, so the flag cannot stay set after a run.

Verification

  • Two new cases in tests/pi/interaction.test.mjs failed on the old code with "Not scheduled" where "Wakeup scheduled" is required, and pass on the new code.
  • bun test tests/ reports 1180 pass, 36 skip, 0 fail. bun tools/typecheck-pi.mjs exits 0.
  • TLC passes 13 of 15 runs over 1267325 states, with the two open findings as the failures. The mutation run detects 19 of 19 planted bugs, three of them the old sealing rule.

/loop treated any non-idle session as a run in flight. Pi is also not idle during a manual compaction, and it emits agent_settled only when a run ends, so a /loop typed during a compaction left the slot sealed and the next run was refused every wakeup. The scheduler now tracks a run from agent_start to agent_settled and seals only then. The TLA+ model of the scheduler comes with the change; two of its runs still fail by design and record narrower findings this does not fix.
@michael-denyer
michael-denyer merged commit f807105 into main Oct 8, 2026
14 checks passed
@michael-denyer
michael-denyer deleted the loop-seal-during-compaction branch October 8, 2026 21:05
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