fix: persist the autopilot milestone map so a paused run survives a reload (#4140) - #4246
Merged
Conversation
…eload (#4140) The Autonomous-mode card drew its map from two halves that lived only on the in-memory run record — the projected plan on the retained `start` frame and the progress snapshot folded onto it. Both are served only while the run is alive, so a run that paused overnight came back as a resume banner with no map beside it. persistMarker now stamps both onto the persisted marker (on every write that has a plan, not only the terminals — a hard restart never reaches a terminal write, and the boot recovery demotes its `running` marker by spreading it), sanitizeAutopilot bounds them so the shape survives a peer round-trip, and the panel falls back to the marker when no run is active. No schema-version bump: the marker keeps its existing transient posture, so a behind peer that drops the map just shows the pre-#4140 bare banner until the next run re-stamps it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Autonomous-mode card's milestone map was drawn from two halves that lived only on the in-memory run record — the projected plan on the run's retained
startframe, and the progress snapshot folded onto the record bynoteProgress. Both are served only while the run is alive (activeRunStart/activeRunProgressreturn null once the run finishes, and the panel's mount effect bails on!active), so the map answered "where is it now" perfectly while the panel stayed open and answered nothing the morning after: a run that paused overnight came back as a resume banner with no map beside it.persistMarker(server/services/pipeline/seriesAutopilot/session.js) now stamps{ plan, progress }onto the marker alongsidestatus/currentStep/resumeOptions. Stamped on every marker write that has a projected plan, not only the pause/complete/error terminals: the marker is wholesale-replaced per write, so a terminals-only stamp would leave the map missing for the one interruption that skips a terminal write entirely — a hard restart, whoserunningmarker the boot recovery demotes topausedby spreading whatever it already held.sanitizeAutopilot(server/services/pipeline/series.js) bounds both halves so the shape survives a peer round-trip: plan rows are capped and each drops to{kind, count, note, estActions}; the progress snapshot keepscurrentStep/currentStepCompleteand boundedcompleted/skipped/verifiedmaps. A zero tally and a verification blob carrying none of the numbers the map reads are dropped rather than persisted.AutopilotPanelfalls back toseries.autopilot.plan/.progressonly when no run is active and there is no live plan — a run in flight and a dry-run preview both keep the fresher in-memory copy. The newautopilotMarkerTerminal(status)inclient/src/lib/autopilotMilestones.jstranslates a persisted status into the terminal frame type the fold reads, so the step a paused run stopped on redraws as blocked instead of still running.SCHEMA_VERSIONSbump. The map keeps the existing autopilot-marker posture documented insanitizeAutopilot— transient, regenerated-every-run status, not durable creative content — so a behind peer that drops it just shows the pre-Persist autopilot milestone map so a paused run survives reload #4140 bare banner until the next run re-stamps it. The added payload is a couple of KB on a series record that is already tens.Also rolled in: the three keyed autopilot marker maps (per-dimension discarded findings, per-step progress counts, per-gate verifications) now share one
sanitizeAutopilotKeyedMapbounder instead of each re-rolling the cap/trim/drop-empty loop.Test plan
cd server && NODE_ENV=test npx vitest run services/pipeline lib/schemaVersions— 2093 passed / 13 skipped, including:sanitizeAutopilot milestone map (#4140)cases: plan rows kept, kind-less rows dropped, absurd counts defaulted, peer-written plan capped, progress snapshot kept with the stopped-on step, both gate verification shapes, empty/malformed inputs.seriesAutopilotintegration cases: a paused run's marker carries the plan and the progress (withcurrentStep: 'editorialReview'), and a restart-interrupted run keeps both acrossrecoverStuckAutopilots().cd client && npx vitest run src/lib/autopilotMilestones.test.js src/components/pipeline/AutopilotPanel.test.jsx src/lib/index.test.js— 84 passed, including new cases forautopilotMarkerTerminal, the panel redrawing the map from the marker with no active run, and a live run winning over a stale marker.cd client && npm run lint— clean.Closes #4140