You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Added
The TUI dashboard now shows the cost-proportional weighted token total, with the raw total in a new
column. The tokens column and the run-header summary discount cache-read tokens by the run's cache_read_weight — the same weighting the per-story budget enforces — so the headline number
tracks spend rather than context re-reads; the previous unweighted total moves to a new raw column.
Fixed
The dashboard no longer crashes when a background poll lands as the screen is torn down or
switched away. A poll worker delivers its refresh on the UI thread; if that arrived just as the
app quit or another screen opened, the query for the run table raised NoMatches. The apply now
drops stale refreshes for a screen that is no longer running (while still updating one merely
backgrounded under a modal).
A failed attempt's work is preserved before an auto-rollback hard reset instead of being silently
discarded. With scm.rollback_on_failure on (or on a resolved re-drive), a deferred or stopped
attempt's commits above baseline are now parked under an attempt-preserve/<run_id>-<head8> branch,
and its uncommitted working-tree diff — tracked edits and run-created untracked files alike — under refs/attempt-preserve-dirty/; both are recoverable by name and survive gc. A plain rollback that
cannot create the ref refuses to reset and pauses for manual recovery rather than destroying work.
The uncommitted snapshot is scoped to this run's own changes (never a pre-existing untracked file),
commits under a synthetic identity so it works with no git user configured, and is keyed per retry
so repeated rollbacks against the same baseline no longer overwrite each other's recovery ref.
Process liveness is now identity-aware, so a reused PID no longer reads as a live run. A recycled
pid (common on Windows) used to register as a false "alive" — blocking resume of a dead run,
stranding worktree reclaim, leaking sessions, and showing dead runs as RUNNING. The pid file now
carries a process-identity token that resume, stop, and the TUI verify against; on win32 the engine
also ignores console SIGINT/SIGBREAK during a run so a ConPTY Ctrl+C broadcast can't kill it.
A story from a resolved escalation that still can't finish now re-escalates instead of being
silently deferred. When a human-resolved CRITICAL blocked escalation was re-driven and the
re-drive couldn't reach status: done (e.g. the environment was still broken), the story used to
exhaust its dev/review budget and plateau-defer — filing an unresolved blocker as deferred work and
rolling back the implemented code. While resolved_redrive is latched, budget exhaustion now
re-escalates (pauses for the human) instead of deferring, and the attempt's tree is preserved.
A resumed --epic N run stays scoped to its epic and no longer declares the epic "done" while
stories remain.resume rebuilt the engine without the run's --epic/--story/--max-stories,
so a scoped run silently widened to every epic; with strict file-order story selection, deferring or
finishing a story in an epic placed out of numeric order in the sprint board (e.g. one appended last)
bounced selection to an earlier-in-file epic and fired a spurious "epic N complete" boundary,
stranding the epic's remaining stories. The selector and cap are now persisted and restored on
resume, and story selection exhausts the current epic before advancing — so an epic boundary fires
only when that epic has no actionable stories left. Document-order epic execution is unchanged.