Skip to content

Allow refine from ready, returning through triage - #119

Merged
MJohnson459 merged 1 commit into
mainfrom
refine-from-ready
Aug 5, 2026
Merged

Allow refine from ready, returning through triage#119
MJohnson459 merged 1 commit into
mainfrom
refine-from-ready

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

Refine now fires from ready as well as proposed, so a task triaged before refine existed can have its body agent-rewritten instead of hand-edited through voro set --body-file.

What changed

  • voro-core/src/transition.rs: the transition arm widens to (Proposed | Ready, Action::Refine(_)) => Refining, for both intensities (the note-driven and interactive flavours are one action carrying different notes). legal_actions still withholds refine — it collects verdicts, and refine is not one — so only the apply match and the test matrix moved.
  • The conclude transition is untouched: refining → proposed, always. A round keeps no memory of its origin, so a task refined out of ready deliberately returns through triage — the ready verdict was passed on a body that no longer exists, so the rewrite earns a fresh verdict. No refining → ready arm, no origin state.
  • parked stays excluded.
  • voro/src/dispatch.rs: guard_refinable — the early refusal both flavours share — accepts Ready; the message becomes "only a proposed or ready task can be refined".
  • voro/src/app.rs: is_proposed becomes is_refinable (proposed or ready), and refine_selected's shared guard follows, refusing with "task is {state} — refine works on a proposal or a ready task".
  • voro/src/ui.rs: the r/R refine key-line slot is advertised on a selected ready row on both the cockpit and the task browser; the ? key map's uppercase gloss rewords to "refine a brief". The cockpit line stays within its ten slots on a ready row (⏎, d/D, r/R, s, !, n/N, e, ?, tab, q).
  • voro/src/cli.rs: voro triage <id> refine is unchanged apart from the widened guard — no new verb — and the --help transitions entry and the handler doc say so.
  • docs/DESIGN.md: §6's state table (ready gains the refine transition; the refining row's "entered from" and "leaves by" prose), a new paragraph of rationale after the refine-is-a-state argument, and the §6 sentences that said refine is refused on anything but a proposal.

Nothing else needed code changes, which was verified rather than assumed: the ↻ refined / ⚠ refine failed markers, the session row, reconcile of dead refine rounds, and scoring all hang off the refining state and the proposed landing, not the origin.

Tests

voro-core gains a transition::tests::refine module: a ready task refines in either flavour and opens its session row in the same write; every round concludes to proposed whatever it started from, across all three RefineOutcomes; refine is refused from every other state including parked, running, review, needs-input, waiting, stalled and the closed pair; and a refining task drops out of candidates()/focus(), which is the dispatch race closed by construction. Two existing "refused from the wrong state" tests move their fixture from ready to parked, and voro's dispatch tests gain a ready-task refine round-trip. app.rs gains a positive r-on-a-ready-row test beside the reworked refusal test.

Verified

cargo test --workspace (619 tests) and cargo clippy --workspace --all-targets -- -D warnings pass; cargo fmt --all --check clean.

Driven end-to-end in the TUI against a scratch database with a stub agent: on a selected ready row the key line advertises r/R refine; r opens the "Refine note — what needs fixing" prompt; submitting it moves the task off the queue onto the running strip as ⟳ refining (header refining 1 ready 1); when the stub's voro set --body lands, the task returns as a proposal marked ↻ refined↻ 1 refined on the folded digest, ↻ refined on the row — with the rewritten body and a refined event carrying the note. voro triage 2 refine --note "…" accepts a ready id from the CLI. While a round is in flight voro next reports "no ready tasks" and voro dispatch refuses with "only ready or stalled tasks can be dispatched; task 3 is refining"; on a parked task refine refuses with "only a proposed or ready task can be refined".

Branch refine-from-ready, one commit, not pushed.

Refine was refused on anything but a `proposed` task, so tasks triaged
before refine landed were stuck: the only way to have an agent rewrite
their body was a manual `voro set --body-file`.

`ready → refining` is now a legal transition for both intensities. The
conclude transition is untouched — a round lands on `proposed` however
it began and keeps no memory of its origin, so a task refined out of
`ready` comes back through triage: its verdict was issued against a body
that no longer exists. `parked` stays excluded.

Everything hanging off the `refining` state needed no change, which was
the point of making it a state: the markers, the session row, reconcile
of dead rounds, and scoring all read the state rather than the origin.
The dispatch race is closed the same way triage's was — the scheduler's
candidate query does not list `refining`, so a refining task drops out of
`voro next` and out of every window's ready rows at once.
@MJohnson459
MJohnson459 merged commit da88e98 into main Aug 5, 2026
6 checks passed
@MJohnson459
MJohnson459 deleted the refine-from-ready branch August 5, 2026 11:35
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