Repository navigation
feat(studio): lead the plan card with its scope choices and keep the approved plan under its answer - #74
Merged
Conversation
…proved plan under its answer The plan card shows the plan's title, a one-line summary, each scope choice with Change, the step that gives the answer and a View full plan button. A failed switch keeps the card and states its reason under the choice it concerns. A changed value carries a Changed tag. plan.approved attaches an approved-plan pill to the answer, stored with the message and opened read-only. A harness that sends none of the new fields still gets a card.
…oice rows accessible A switch stream that closes, errors or is stopped without a plan returns the card to idle with its notice and leaves the paused reply untouched. Every refusal shows the harness's detail; 401 and 429 offer no retry. Options are buttons with aria-pressed in a group, focus returns to the switched row, and the notice sits in a live region mounted empty. An older harness's card leads with the question.
A switch re-pins a part, so a choice's id carries a new spec id; rows are matched by their axis. A row is Changed when its option differs from the turn's first plan, so two switches mark both rows and a switch back marks none.
…hoices on their stable ids Stop on a switch sends cancel and keeps reading: a re-offered plan makes the card live again, and a stream that ends without one leaves it read-only with its Activity entry closed. Try again follows switch_failed.retryable or the refusal's retry mode. Choices are keyed on choice_id, with the axis only for an id missing from the earlier plan, and a stale refusal keeps the turn's first plan as the baseline. Map.groupBy is replaced for older Safari. Conversation search matches message text only. The approved plan shows its caveats.
… and quiet a stopped switch A refusal for a pause that no longer exists ends the card read-only. A choice falls back to its axis only when its id was replaced. 401 and 429 never offer an immediate Try again, and a busy refusal offers it after its retry delay. Moved choices with no row, each choice's reason and the plan's caveats show on the card, and a stopped switch is a quiet note. Switch settling moves out of stream() into an onEnd callback, notices share one builder, and the card and full plan share one approve bar. Conversation search also matches a user message's card title, with a database test.
…le and match choices by id only A switch whose request got no response keeps the card live with Try again; only a server-confirmed end makes it read-only. Every failed switch clears the steps-updated mark. Choices match on choice_id alone. The fallback answer step is the last answering step in plan order, the headline takes the harness's title when it has one, caveats key by index, and the three switch notices share one builder.
…ries from the notice A switch's stop grace (15 s) outlasts the harness's 10 s re-offer, and repeated Stop clicks send one cancel. A 429 with a retry delay offers Try again after it, timed from when the notice arrived. The switch-ended path reuses endTurn, stream() handles a caller-owned end in one place, and the live card and approved view share the answer-step rule and the caveats list.
… alone Only a busy, option-unavailable or rate-limited refusal keeps the card live; every other refusal ends it read-only with a reader sentence, and a proxy's raw text goes to the console. Try again appears only when the harness asks for a retry after a delay. done and error frames end the turn when they arrive, a stopped switch keeps its Stopping line, a Stop after a fresh plan sends no cancel, and a switch stream's Activity entry closes by how the harness ended it.
A switch the proxy refused before the harness answered (its 502 with no upstream status, or its 429) left a live pause behind a read-only card or a row without Try again. The proxy's 502 now names the upstream status when the harness had answered, the card stays live otherwise, and a proxy 429 offers Try again after Retry-After. A live row shows detail only from a harness ToolError, and a stopped switch's notice is quiet.
A switch picked while the paused stream was still open waited with no halt, so Stop did nothing. The halt is published when the stream is queued, and a Stop before the request starts skips it and keeps the card live with a quiet note. A Stop followed by a refusal ends as stopped, and the approved view guards stored steps and choices.
A refusal after Stop ends the switch with the quiet stopped note, a Stop on an unsent switch clears its halt so a later switch can be stopped, and only a switch publishes its halt while queued. A proxy 429 offers Try again only with a positive Retry-After and reads "Studio is busy."
A switch the user stopped whose fetch then rejected came back as a live card reading "Studio could not be reached." It now ends as stopped, as a refused one does.
…hen they did The card keeps one polite live region that states what a switch changed, as the moved-choices note did, and "Steps updated to match." shows only when the step labels differ from the previous plan's.
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.
Deploy this before DevelopmentFinanceObservatory/ai#90, the harness change that sends the new plan fields. The card works against the current harness, which sends none of them, and leads with the question in that case.
The plan card listed every step as a timeline, so a five-step plan filled the chat panel and the scope choices that decide the answer sat below the steps.
PlanCard.tsxandPlanLedger.tsxshow the plan's title, a one-sentence summary, each scope choice with a Change button, the plan's caveats under "Keep in mind", and the step that gives the answer. "View full plan (N steps)" opensPlanModal.tsx, which also shows each choice's reason. The card and the full plan sharePlanApproveBar.tsx. A switched row carries a Changed tag against the turn's first plan, keyed onchoice_id, which DevelopmentFinanceObservatory/ai#90 keeps stable across switches. Against the current harness, which re-keys a choice when a switch re-pins its part, a switched row shows no Changed tag until that change deploys.The card is live only while the server's pause is. A failed switch keeps the card and puts "Could not switch to X." with the harness's reason under its row, with Try again only when
switch_failed.retryableor the refusal's retry mode allows it. A refusal that leaves the pause alone (409 busy, 422 option unavailable, 429) keeps the card live, and any other ends it read-only with "Ask again to change the plan." A switch the site proxy refused before the harness answered also keeps the card live. The proxy's 429 offers Try again after its Retry-After, and its 502 does unless it namesupstream_status, a new problem member thatsrc/lib/proxy/forward.tssets on every route when the upstream had answered. Stop during a switch sends cancel and keeps reading, and the harness re-offers the unchanged plan with a quiet note.plan.approvedattaches an approved-plan pill to the answer it produced (ApprovedPlanPill.tsx), stored with the message and opened read-only with its caveats. Conversation search (src/lib/chat/conversationSearch.ts) matches message text and a user message's card title, which keeps stored plans out of the matches. Follow-up and chip labels are not searched.Guest conversations are never saved, so the pill does not survive a reload in guest mode.
Testing: tsc, eslint, stylelint and prettier are clean, the
src/lib/studio,src/lib/chatandsrc/lib/proxytests pass (768), anddb/test/conversation-search.test.tsruns the search query against Postgres. This branch ran locally against the ai#90 branch and dev Search. The US health share proposed its card and answered 14.2%, a provider switch marked its row and moved the answer to 14.8%, a Stop during a switch and one 50 ms after picking left the plan approvable, and the approved pill opened the read-only plan with its caveat.Screenshots
Before is dev and after is this branch, both from live runs against dev Search of "What share of US aid went to health in 2023?" and, for the providers caveat, the same question using the DAC1 total as the denominator.