Repository navigation
Move a part only after its handoff is in the fresh Session - #743
Conversation
moveOn flipped the Bot's Session pointer and saved before it wrote the handoff package. A save failure then left the state on a fresh part with no package, and a later failure (capabilities, resolving the fresh Session, the package flush) left it there empty while the finalizer, seeing job.moved, dropped the carried input. Send the package first, then flip and save (restoring the old state if the save fails), and mark the move done only after the input is forwarded. A switch that never starts now lets the step continue instead of rejecting its messages. Fixes ThinkFlowLab#740
|
Verdict: PASS at fd02696 The reorder is right and the test pins it: the handoff package is written to the fresh Session before anything points at it, the pointer/segment save comes after with the previous state restored on failure, and Ran:
Not blocking, worth a follow-up issue rather than another tip:
Neither changes my verdict: the reproduced defect is fixed, and the failure it was about is now pinned. |
ThinkFlowLab#743 wrote the handoff package before the state flip so a failed handoff would keep the old part current. The fresh part's handoff followup starts a turn, and its events can arrive before the new segment is saved; a second switch then reads partsOf without the previous segment and loses its note (the full core suite showed it deterministically under load). Save the new segment first, then write the package; a failed package rolls the pointer back (best effort saved) and archives the fresh Session, so the finalizer still hands the input on in the old part. Fixes ThinkFlowLab#751
Move a part only after its handoff is in the fresh Session
Fixes #740
parts.jsmoveOnflipped the Bot's pointer (sessionId/room.sessions, the new segment, the question card) and saved before it wrote the handoff package to the fresh Session, then setjob.moved = truebefore sending it. Two failure windows lost work:rt.save()left the in-memory state on the fresh Session, and the finalizer (seeingjob.moved === false) forwarded the carried input tocurrentOf— now the fresh part — with no package, no transcript and no in-place checkpoint;job.moved = true(ensureCapabilities, resolving the fresh Session, the package flush) made the finalizer return: the fresh part stayed current and empty and the stopped turn's input plus the old inbox messages were dropped.Also
switchBeforeStepreturned{ kind: 'reject' }even whenstartSwitchreturned early (no place, another switch, read-only), though DSH had already taken the step's messages out of the inbox.Now the handoff package is written to the fresh Session first; only then are the pointer/segment saved, with the previous state restored (and the fresh Session archived) if the save fails. The move is marked done only after the carried input and the old inbox messages were forwarded, so a failure lets the existing finalizer hand them on to the part that is current.
startSwitchreports whether it started, andswitchBeforeSteplets the step continue when it did not.core/test/work-dir.test.jsfails the fresh Session's handoff flush, runs an idle folder move, and asserts the old part stays current with no segment recorded — it fails without the change (the Bot points at the empty fresh part). The existing switch/folder tests are unchanged.docs/subsystems/core-host.mdrecords the order.Ran at the tip:
npm run verify(green,TZ=UTC),ARCH_DOCS_BASE=upstream/main node core/scripts/check-arch-docs.mjs,ds-bot-patches generate+check. Not run: smoke (this macOS box has nosetsid, sodev/bench.shcannot startdsh web), Desktop, real-model steward.