🤖 feat(goals-tab): consolidate Cost/Budget/Remaining + always show Turn cap#3314
Conversation
…rn cap
Active-goal stat tiles previously fragmented one concept across multiple
tiles. The user had to mentally re-assemble "I've spent $1.25 of $5.00,
so $3.75 is left" from three separate corners of the panel; the turn
cap was only surfaced inside the edit dialog, so "3" looked the same
whether the cap was 4, 1000, or unset.
Replace the 5-tile grid with three semantically-grouped tiles:
• Budget (full-width): cost / cap, remaining, and a thin progress
bar in one card. Bar collapses + tile becomes a Cost-only card
when budgetCents is null. Bar turns danger-soft once the goal is
budget_limited or cost meets the cap.
• Turns (half-width): turns / cap with "X left" secondary line.
When turnCap is null we surface "no cap" so the user can tell
"no limit set" from "limit way higher than current usage".
• Elapsed (half-width): unchanged.
Edit affordances stay on each tile with the existing aria-labels so
the inline editor path is untouched.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f73d56ab40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…d $0.00 (Codex P2) Codex caught two parallel defects in the new BudgetTile / TurnsTile over-cap branches: each computed a single `remaining = max(0, cap - used)` delta and rendered it with the `over` suffix, so a 25¢ overspend (`costCents: 525`, `budgetCents: 500`) and any over-cap turn count were both reported as "$0.00 over" / "0 over". The clamped magnitude hid how far past the limit the goal actually was. Compute two non-negative deltas per tile and pick the one that matches the active branch: - under-limit branch shows `cap - used` with "left" suffix - over-limit branch shows `used - cap` with "over" suffix Added two behavioral tests (over-budget BudgetLimited goal + over-cap Turns goal) to lock the corrected magnitude.
|
@codex review Addressed both P2 findings: the over-budget and over-cap branches now Added two behavioral tests covering both branches. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 097482c344
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…lutter continuation card (Codex P2) Two related cleanups in the same diff: 1. Codex P2: the new BudgetTile keyed its over/under-budget rendering off `status === "budget_limited"`. The backend (`hasReachedAnyLimit()` in workspaceGoalService.ts) sets that status when EITHER limit is reached, so a goal at `cost $1.25 of $5.00, turns 10/10` was labeled "$0.00 over" — a lie about the money. The fix is to base over/under-budget strictly on the budget numbers themselves (`costCents >= budgetCents`) and let TurnsTile worry about turn overages independently. `status` is no longer a BudgetTile input. 2. The goal-continuation / budget-limit transcript card had double chrome (its own border + tinted background sitting inside the user-message bubble's border + tinted surface), a `min-w-[18rem]` that blew out the bubble for short objectives, and a chunky icon badge (`bg-muted/20 p-1.5` around a 16px icon) that didn't scale with the 14px title text. Result: an awkwardly oversized inline card mid-transcript. Strip the inner card chrome — the parent bubble is the visual container — replace the badge with a small inline icon (`size-4` + `mt-0.5` to vertically center with the first line of text), and let the bubble hug its content. The "goal continuation" pill in the meta row still labels the synthetic nature of the message. Added behavioral test locking the budget-tile fix (Codex case: budget_limited with turn cap reached but cost below budget renders under-budget, not over).
|
@codex review Round 2 fixes:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 215fe8b9aa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…'over' (Codex P2 round 3) At `turnsUsed === turnCap` (the normal cap-reached path used by `hasReachedTurnLimit()`), the previous render sent the tile down the "over" branch with `turnsOverBy === 0`, producing "0 over" — a misleading label since the goal is AT the cap, not past it. Same applies to budget at `costCents === budgetCents`. Reserve the "over" copy for STRICT inequality: - `costCents > budgetCents` / `turnsUsed > turnCap` → "X over" - exact equality → "0 left" The bar fill and danger color still trip at `>=` so reaching the cap exactly is visually signaled — only the textual suffix changed. Added a behavioral test covering exact-equality saturation on both tiles.
|
@codex review Round 3 fix: Added a behavioral test covering both tiles at exact saturation. |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Cleans up the active-goal stat surface in the right-sidebar Goal tab so
the user can read "spent of cap, X left" without bouncing between
tiles, and so the turn cap is always visible alongside the turns used
— not just after clicking Edit.
Background
Prior layout placed Cost, Budget, and Remaining as three sibling tiles
in a 2-column grid. The Turns tile rendered just
turnsUsedwhen nocap was configured, so "3" was indistinguishable from "no cap set yet"
vs "limit set higher than current usage". Both behaviors made the user
do mental arithmetic and click Edit to inspect state, which the slot
was supposed to surface in the first place.
Implementation
Two small components extracted from
GoalTab.tsx:BudgetTile— consolidates Cost / Budget / Remaining into a singlefull-width card. Renders
$1.25 of $5.00prominently with$3.75 leftmuted, plus a thin progress bar exposed viarole="progressbar"aria-valuetext. Bar turns danger-soft when the goal is inbudget_limitedstatus or cost meets the cap. When no budget isconfigured (
budgetCents == null) the bar collapses and the cardbecomes a Cost-only view with a
no budgetlabel.TurnsTile— rendersturns / capplus a secondaryX leftline.When
turnCap == nullwe surface ano caplabel instead ofhiding the cap entirely.
Edit affordances and aria-labels are unchanged so the inline budget
and turn-cap editors continue to work and existing tests targeting
Edit goal budget/Edit goal turn capstill match.Validation
GoalTab.test.tsxpass (16 existing + 3 new behavioral testscovering: turn cap visible when null; budget tile composite render;
bar omitted when no budget).
make static-checkgreen locally.Chromatic will diff the redesigned
Active,ActiveWithAccounting,Paused, andBudgetLimitedstories — the new layout is intentionalso those snapshots will need approval.
Risks
Low. The change is contained to the active-goal stat tile rendering
in
GoalTab.tsx. Goal record types, lifecycle math, and backendmutations are untouched. The new components are pure-render with no
new effects, no IPC calls, and no localStorage interaction.
Generated with
mux• Model:anthropic:claude-opus-4-7• Thinking:xhigh• Cost:$203.76