Order of work for the jobs flow redesign (#170-#183) #184

Closed
opened 2026-08-23 19:46:30 +00:00 by nalum · 1 comment
Owner

The jobs surface is being rebuilt from a design handoff
(design_handoff_jobs_flow, held outside the repo). This issue holds the order
of work; each step is its own issue.

What changes

Viewing and editing become states of one screen. The Edit button and the single
Save go away, on both surfaces — web/src/pages/Jobs.tsx (2,534 lines) and
android/.../ItemSheets.kt (1,434 lines) both carry the old model today. Five
rules govern the result:

  1. A record has one surface.
  2. A field is edited where it is shown. A chevron means a picker opens; no
    chevron means it edits in place.
  3. Changes commit on blur and undo once. Only two acts confirm first: deleting
    anything, and ticking a repeating job.
  4. Creating is the only explicit Save.
  5. Fewer permissions means fewer rows, never disabled ones.

Order

Steps 0 and 1 are prerequisites; nothing above them can start first.

Step Issue Why here
0 #170 token roles The row grammar has no fill, no border and no error colour without them
1 #171 the row component Everything else composes from it
2 #172 the detail sheet The first screen that uses the row
3 #173 the three pickers Who and Worth share one; When is its own
4 #174 the board card Reuses the sheet's progress block
5 #175 options and repeats The largest piece, and the only real date maths
6 #176 delete and chain ends
7 #177 create
8 #178 the restricted sheets The full sheet with rows removed, so it goes last

Running alongside, and none of them optional:

  • #179 — retire the "step" noun, settle Anyone / Up for grabs / Take this job
  • #180 — conformance fixtures and the 196 screenshot goldens
  • #182 — the offline queue cannot group writes, which #175 needs
  • #181 — Update writes a sub-job deadline that SetDeadline refuses
  • #183 — one product question left: reward value editing on the jobs surface

Already settled

The design was checked against the server, and five of its assumptions were
wrong. The corrections are folded into the issues above:

  • Update is partial-safe, so per-field commits need no read-modify-write.
  • SetParent refuses a job carrying a repeat rule, a deadline or children — it
    does not strip them. The affordance pre-clears, and is absent when it cannot.
  • CompleteItem requires the owner, so a non-owner cannot tick. The footer has
    four states, and the read-only sheet promises nothing.
  • Reward eligibility depends on the job's owner, so the Worth picker re-filters
    when Who changes.
  • Deleting a job left its unclaimed reward pointing at a dead row, which every
    eligibility filter then hid — the reward was not returned to the pool, it was
    lost. Fixed: the delete transaction now unlinks unclaimed rewards for the
    job and each cascaded sub-job, while claimed ones keep their link as settled
    history. Commit is local, not yet pushed.

Sub-jobs also turned out to be able to hold a points reward — the server already
mirrors one onto each repeat clone — so the Worth row inside a sub-job stays.


Update — the late-state pass

The handoff added a late state after this plan was written, and the calendar
surfaces moved out to their own handover. Three changes here:

  • #186 is new — lateness derived on the device: a date-only deadline is late
    only after the end of that day (reversing a pinned fixture, and closing a
    client/server disagreement), plus the shared minute ticker that makes a card
    flip at 09:45 without a refresh. It sits with step 1, and #174 and #179 both
    depend on it.
  • #170 grows a decision — late is amber, and the palette has no amber but
    celebrate. A tenth role, or a written decision to share it.
  • #174 and #179 carry the state and its wording — the late modifier and the
    merged due/points line on the card, Overdue retired as copy everywhere
    except the stored enum value.

Step 0's server change is done and in review: PR #185. #176 depends on it.

Nothing else in the order changes.


Update — the calendar bundle is now tracked separately

The calendar surfaces have their own handover and their own plan: #199
(#187-#198). The two bundles share the token roles (#170), the row component
(#171) and the minute ticker (#186) — the calendar's rows are that component
with a different payload, so those three are prerequisites for both.

The only contract between the plans: a job opened from a calendar surface is
this bundle's job card, unmodified, and ticking it there is a full
completion site — the mark stamps, linked points auto-claim, celebration
follows. Anything calendar-only on a job card is a bug in one of the two
documents.

One open question crosses over: whether an unowned ("up for grabs") job appears
in calendar views at all depends on #183's answer about where the pool lives.


Update — goldens ride with the PR that breaks them

Re-recording 196 golden images in one late PR would mean one author re-recording
work they did not do, and reviewing a diff nobody can read. The repo rule already
says a visible change re-records its goldens; this plan applies it per PR.

Every UI PR in this plan re-records the goldens it invalidates, in its own
commit inside that PR
(make web-screens-update, make android-screens-update,
and make web-pages-update where a whole-page shot moves). Both surfaces move
together or the other one's suite fails.

Update — decisions settled, and the model per issue

#183 is closed: creating a points reward inside the job stays. #173 keeps
Make a new one in the Worth picker, and the shipped changeRewardValue
convenience stays on the job sheet rather than moving to the rewards surface.

#170 is decided: add a tenth role, a warning with a matching icon. Note the
⚠ glyph is already in the bundled Eagrai Symbols subset, so the icon needs no
font work.

Order and the model each ticket runs on:

Wave Issues Model
0 — server, parallel #198 haiku
#181 sonnet
#188 opus
#182 opus
1 — foundations, sequential #170, #186, #171 opus
2 — jobs #172 fable — the longest-horizon rewrite in the set
#175 opus
#173, #174, #176, #177, #178, #179, #180 sonnet

Stack base: PR #185 (reward unlink) then PR #200 (these handover docs). Every
branch below stacks on the previous one; merge bottom-first.


Standing requirements for every remaining UI ticket

Added after #213 needed three deploys to come right. Both are now written into
each open ticket:

  1. Screenshot goldens are a deliverable, not a follow-up. New cases ride in
    the same commit as the code; re-recorded existing ones go in their own.
  2. A form-styling sweep before hand-off — raw inputs outside the row and
    picker components, number spinners, links where rows belong, (optional)
    labels, any Save button on a commit-on-blur surface, disabled-and-grey
    controls, and a record's title used as a field label.

The second one exists because all seven of #213's defects had the same cause:
the shipped app's form fragments reused inside the new grammar. Suites stay
green through every one of them, because they assert the pieces exist rather
than that the screen reads right.

The jobs surface is being rebuilt from a design handoff (`design_handoff_jobs_flow`, held outside the repo). This issue holds the order of work; each step is its own issue. ## What changes Viewing and editing become states of one screen. The Edit button and the single Save go away, on both surfaces — `web/src/pages/Jobs.tsx` (2,534 lines) and `android/.../ItemSheets.kt` (1,434 lines) both carry the old model today. Five rules govern the result: 1. A record has one surface. 2. A field is edited where it is shown. A chevron means a picker opens; no chevron means it edits in place. 3. Changes commit on blur and undo once. Only two acts confirm first: deleting anything, and ticking a repeating job. 4. Creating is the only explicit Save. 5. Fewer permissions means fewer rows, never disabled ones. ## Order Steps 0 and 1 are prerequisites; nothing above them can start first. | Step | Issue | Why here | |---|---|---| | 0 | #170 token roles | The row grammar has no fill, no border and no error colour without them | | 1 | #171 the row component | Everything else composes from it | | 2 | #172 the detail sheet | The first screen that uses the row | | 3 | #173 the three pickers | Who and Worth share one; When is its own | | 4 | #174 the board card | Reuses the sheet's progress block | | 5 | #175 options and repeats | The largest piece, and the only real date maths | | 6 | #176 delete and chain ends | | | 7 | #177 create | | | 8 | #178 the restricted sheets | The full sheet with rows removed, so it goes last | Running alongside, and none of them optional: - #179 — retire the "step" noun, settle `Anyone` / `Up for grabs` / `Take this job` - #180 — conformance fixtures and the 196 screenshot goldens - #182 — the offline queue cannot group writes, which #175 needs - #181 — `Update` writes a sub-job deadline that `SetDeadline` refuses - #183 — one product question left: reward value editing on the jobs surface ## Already settled The design was checked against the server, and five of its assumptions were wrong. The corrections are folded into the issues above: - `Update` is partial-safe, so per-field commits need no read-modify-write. - `SetParent` refuses a job carrying a repeat rule, a deadline or children — it does not strip them. The affordance pre-clears, and is absent when it cannot. - `CompleteItem` requires the owner, so a non-owner cannot tick. The footer has four states, and the read-only sheet promises nothing. - Reward eligibility depends on the job's owner, so the Worth picker re-filters when Who changes. - Deleting a job left its unclaimed reward pointing at a dead row, which every eligibility filter then hid — the reward was not returned to the pool, it was lost. **Fixed**: the delete transaction now unlinks unclaimed rewards for the job and each cascaded sub-job, while claimed ones keep their link as settled history. Commit is local, not yet pushed. Sub-jobs also turned out to be able to hold a points reward — the server already mirrors one onto each repeat clone — so the Worth row inside a sub-job stays. --- ## Update — the late-state pass The handoff added a late state after this plan was written, and the calendar surfaces moved out to their own handover. Three changes here: - **#186 is new** — lateness derived on the device: a date-only deadline is late only after the end of that day (reversing a pinned fixture, and closing a client/server disagreement), plus the shared minute ticker that makes a card flip at 09:45 without a refresh. It sits with step 1, and #174 and #179 both depend on it. - **#170 grows a decision** — late is amber, and the palette has no amber but `celebrate`. A tenth role, or a written decision to share it. - **#174 and #179 carry the state and its wording** — the late modifier and the merged due/points line on the card, `Overdue` retired as copy everywhere except the stored enum value. **Step 0's server change is done and in review: PR #185.** #176 depends on it. Nothing else in the order changes. --- ## Update — the calendar bundle is now tracked separately The calendar surfaces have their own handover and their own plan: **#199** (#187-#198). The two bundles share the token roles (#170), the row component (#171) and the minute ticker (#186) — the calendar's rows are that component with a different payload, so those three are prerequisites for both. The only contract between the plans: a job opened from a calendar surface is **this bundle's job card, unmodified**, and ticking it there is a full completion site — the mark stamps, linked points auto-claim, celebration follows. Anything calendar-only on a job card is a bug in one of the two documents. One open question crosses over: whether an unowned ("up for grabs") job appears in calendar views at all depends on #183's answer about where the pool lives. --- ## Update — goldens ride with the PR that breaks them Re-recording 196 golden images in one late PR would mean one author re-recording work they did not do, and reviewing a diff nobody can read. The repo rule already says a visible change re-records its goldens; this plan applies it per PR. **Every UI PR in this plan re-records the goldens it invalidates, in its own commit inside that PR** (`make web-screens-update`, `make android-screens-update`, and `make web-pages-update` where a whole-page shot moves). Both surfaces move together or the other one's suite fails. ## Update — decisions settled, and the model per issue **#183 is closed: creating a points reward inside the job stays.** #173 keeps `Make a new one` in the Worth picker, and the shipped `changeRewardValue` convenience stays on the job sheet rather than moving to the rewards surface. **#170 is decided: add a tenth role, a `warning` with a matching icon.** Note the ⚠ glyph is already in the bundled Eagrai Symbols subset, so the icon needs no font work. Order and the model each ticket runs on: | Wave | Issues | Model | |---|---|---| | 0 — server, parallel | #198 | haiku | | | #181 | sonnet | | | #188 | opus | | | #182 | opus | | 1 — foundations, sequential | #170, #186, #171 | opus | | 2 — jobs | #172 | **fable** — the longest-horizon rewrite in the set | | | #175 | opus | | | #173, #174, #176, #177, #178, #179, #180 | sonnet | Stack base: PR #185 (reward unlink) then PR #200 (these handover docs). Every branch below stacks on the previous one; merge bottom-first. --- ## Standing requirements for every remaining UI ticket Added after #213 needed three deploys to come right. Both are now written into each open ticket: 1. **Screenshot goldens are a deliverable**, not a follow-up. New cases ride in the same commit as the code; re-recorded existing ones go in their own. 2. **A form-styling sweep before hand-off** — raw inputs outside the row and picker components, number spinners, links where rows belong, `(optional)` labels, any Save button on a commit-on-blur surface, disabled-and-grey controls, and a record's title used as a field label. The second one exists because all seven of #213's defects had the same cause: the shipped app's form fragments reused inside the new grammar. Suites stay green through every one of them, because they assert the pieces exist rather than that the screen reads right.
Author
Owner

Every step (#170–#183) is built, audited and merged — the whole chain #185–#254 landed on main 2026-08-26. Remaining follow-ups have their own issues (#217, #234, #235, #236).

Every step (#170–#183) is built, audited and merged — the whole chain #185–#254 landed on main 2026-08-26. Remaining follow-ups have their own issues (#217, #234, #235, #236).
nalum closed this issue 2026-08-26 18:47:56 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
eagraiclainne/app#184
No description provided.