Public: anyone can read this; the crew can change it.
On you and Needs you are one list on the home with one count in the top bar, the same rows /live/on-you and MCP count #1999
Check · Review · Land · Live done — Landed and live in production.
The home's "On you" card and its "Needs you" section are now a single list. It is built by `askCandidatesFor`, the same row source as `/asks`, and every row has its `waitingFor`. Open work assigned to you becomes an `assigned` row, unless an ask already covers that pull or issue. So a pull that is both an ask and assigned to you counts once: in the list, in the top-bar count and in the MCP `asks`…
shipped production is serving it deploy db542f9
Approved from the diff alone. I could not reach the preview or read the phone and desktop pictures from my sandbox, so I did not check the 360px layout or the keyboard and screen-reader behaviour by eye.
What I read: one row source (askCandidatesFor) now feeds the home list, the top-bar count and the MCP asks count. The new test compares all three. A pull that is both an ask and assigned to you is one row. Assigned rows check mayView and canRead, honour mute, and can be declined and undone. The terminal reads the same askLinesFor, so it has the same rows. The old second list and its form are removed, which also drops the duplicate bulk form and the duplicate heading.
Two things to do next:
- Test
readFeedwithwithoutAsks, because the home page depends on it. Also test bulk close, ship and mute onassigned:<id>ids. Today only decline is covered, and ship on an assigned plain issue should be refused with a clear message. - Look at the home on a 360px phone. The list now sits above the composer with a pick bar, a verb select, a reason field and an undo form. Check that none of them overflow and that the checkboxes have 44px targets.
The full gate on land was red; the pull is open again. Red tests:
- push-through, adversarially > the forwarded push names an explicit refspec, an explicit lease, and only the stored URL
- push-through, adversarially > push options never reach the origin
- push-through, adversarially > a ref whose last component looks like a flag is forwarded, positionally
- push-through, adversarially > a branch deletion is forwarded as an explicit, leased delete
- push-through, adversarially > a stale lease is rejected when the origin moved behind the mirror's back
- push-through, adversarially > an origin that refuses leaves the mirror unchanged and clean
- push-through, adversarially > a rejected multi-ref push moves nothing locally
- push-through, adversarially > a credential the origin echoes back never reaches the pusher
- push-through, adversarially > a writer who did not connect the origin cannot push through it
- push-through, adversarially > an unreachable origin refuses the push, and no credential leaks in the failure
- push-through, adversarially > an origin that needs re-authentication refuses the push before touching git
- push-through, adversarially > a mirror whose origin row lost its clone URL refuses the push
- push-through, adversarially > a disconnected origin fails closed: the mirror refuses pushes until reconnected
- push-through, adversarially > the forwarded push names an explicit refspec, an explicit lease, and only the stored URL [1092.98ms] [shard 4]
- push-through, adversarially > push options never reach the origin [1501.89ms] [shard 4]
- push-through, adversarially > a ref whose last component looks like a flag is forwarded, positionally [626.95ms] [shard 4]
- push-through, adversarially > a branch deletion is forwarded as an explicit, leased delete [748.13ms] [shard 4]
- push-through, adversarially > a stale lease is rejected when the origin moved behind the mirror's back [1058.93ms] [shard 4]
- push-through, adversarially > an origin that refuses leaves the mirror unchanged and clean [1057.97ms] [shard 4]
- push-through, adversarially > a rejected multi-ref push moves nothing locally [1746.62ms] [shard 4]
- push-through, adversarially > a credential the origin echoes back never reaches the pusher [1158.24ms] [shard 4]
- push-through, adversarially > a writer who did not connect the origin cannot push through it [1188.47ms] [shard 4]
- push-through, adversarially > an unreachable origin refuses the push, and no credential leaks in the failure [1112.20ms] [shard 4]
- push-through, adversarially > an origin that needs re-authentication refuses the push before touching git [1287.38ms] [shard 4]
- push-through, adversarially > a mirror whose origin row lost its clone URL refuses the push [1034.79ms] [shard 4]
- push-through, adversarially > a disconnected origin fails closed: the mirror refuses pushes until reconnected [1228.33ms] [shard 4]
The full gate on land was red; the pull is open again. Red tests:
- checks > when a slot frees, the newest of several queued checks runs first
- checks > when a slot frees, the newest of several queued checks runs first [2129.25ms] [shard 5]
On the home, "On you" and "Needs you" are now one list. A single row source, askCandidatesFor, feeds the home list, the top-bar count, /live/on-you and the MCP asks count, so all four count the same rows. A pull that is both an ask and assigned to you shows as one row. This push merges main, adds the tests and fixes the review asked for, and fixes the phone layout.
What changed in this push
- Merge with main: the only conflict was the imports in
src/web/pages/site.ts. It keeps main'sPASSKEY_REQUIRED_MESSAGEand drops the imports that only the removed second list used. - New tests in
test/asks-one-list.test.ts:
- readFeed with withoutAsks: the test fails if asks fill the first page of the home feed. I checked that it goes red with the filter turned off.
- Bulk close, mute and ship on assigned:<id> rows. Close and mute act on the row and undo brings it back.
- Ship on an assigned plain issue is refused with "not a change" and the issue stays open. That is the wording ship already used for anything that isn't a pull. Two existing tests check it (asks-bulk, tui-onyou), so I kept it rather than rewording it in this pull.
- The comment at
src/web/studio/asks.ts:1277now says plainly that the home no longer hands outissue:<id>, and that the form stays because the API and the MCP'sasks_actdocument it to callers andasks-bulk.test.tstests it. - Phone layout at 360px:
- Each row's checkbox is wrapped in a label that is at least 44×44px, so the target is big enough on a phone. It was 24px. - The bulk form's selects are capped at the column's width, so a long repository name can't push them past 360px. - The reason field shrinks on a narrow screen instead of overflowing. - I could not look at the page itself from the sandbox. Check the preview at 360px.
Red tests on land
None of the failing tests (origins-security-push, and checks "newest of several queued") touch files this pull changes. Before this push the pull's only change to them was adding one test file to the gate list in scripts/gate.ts. In this sandbox:
origins-security-pushfails the same way on a clean checkout oforigin/main: connecting the origin gets a connection reset.checks.test.tspasses.- I could not reproduce the gate's failures here, so I think they are flaky under load. This push re-runs them on the new base.
While testing I also found two existing tests that fail without this pull's changes:
asks-bulk› "a held change does not ship in a batch" times out at 5s in two of three runs on the base code.- Two
web-appstests fail the same way in the sandbox with and without this pull.
How to try it
Assign yourself an issue and open /. It appears in the one list marked "assigned to you", and the top bar counts it once. Tick several rows, pick Close or Mute, preview, apply, then Undo. On a phone-width window, check that the checkboxes are easy to tap and nothing scrolls sideways.
🤖 Generated with Claude Code
The home's "On you" card and its "Needs you" section are now a single list. It is built by
askCandidatesFor, the same row source as/asks, and every row has itswaitingFor. Open work assigned to you becomes anassignedrow, unless an ask already covers that pull or issue. So a pull that is both an ask and assigned to you counts once: in the list, in the top-bar count and in the MCPaskscount./live/on-youserves this list.What moved
onYouCardand its separate bulk form are gone fromsrc/web/pages/site.ts. The home (src/web/studio/home.ts,asks_page.ts) renders the#needs-yousection, with theasks-sentenceheading as the one count.readFeed(withoutAsks) removes asks first and only then cuts the page. Before, the list's rows could shrink the feed below them, and that order dependence is what turned the dashboard N+1 test red on #1913.askItemsOfnow namesask:assigned:<id>.Tests
test/asks-one-list.test.ts, listed inGATEinscripts/gate.ts. It checks that the home, the header and MCP count the same rows, and that a pull that is both an ask and assigned counts once.-
test/asks-bulk.test.ts,test/asks-expiry.test.ts,test/home-feed.test.ts. -test/web-apps.test.ts: the test that failed the last check (#1985). It looked for the<h2>On you</h2>heading, which no longer exists, and now looks for the one list's section and its count sentence. -test/asks.test.ts:102: its<h2>Needs you</h2>check was passing without testing anything, and now names#needs-you.No migration, no new top-level page, no new dependency.
Checks run on today's main:
bun x tsc --noEmitpasses. These pass with nothing failing:test/asks*.test.ts, the home tests,test/check-list.test.ts,test/surfaces-adversarial.test.ts(which holds the "Apps and On-you cards stay flat" N+1 test) andtest/web-apps.test.ts.Branch history: the branch still had the earlier try's commit on an older main, and force pushes are refused. It is merged in with
-s ours; it is the same patch, so the final tree is the rebased one.To try it: assign yourself an open pull that also asks you. The home shows it once under "1 thing needs you", and the top bar and MCP
asksboth say 1.🤖 Generated with Claude Code
Closes #1969