Public: anyone can read this; the crew can change it.
The header's Talk button shows when a conversation waits on your yes #10644
Check · Review · Land · Live done — Landed and live in production.
The header's Talk button now shows a small count when you have confirms waiting, on every page. With none waiting, it looks as before.
shipped production is serving it deploy 2937aef
The header's Talk button now shows a small count when you have confirms waiting, on every page. With none waiting, it looks as before.
What changed
countWaitinginsrc/core/fence.tsis a singleCOUNT(*)on the existingconversation_held_waitingindex, filtered to your own unanswered confirms younger than 10 minutes. It doesn't sweep, so it never writes.waitingCountinsrc/actions/conversation_confirms.tswraps it for the header.src/web/layout.tsasks that count only when someone is signed in. The button's label becomes "Talk to the forge, N waiting", and a badge shows N, or "9+" past nine. The badge is hidden from screen readers so the label isn't read twice..talk-btnand.talk-countinsrc/web/style/components.tsput the badge in the button's corner, out of the layout flow, so nothing shifts whether it shows or not. They are documented indocs/design/areas/talk-count.md.- The new test in
test/talk-page.test.tscovers four cases: no count at zero, "2 waiting" for the person who holds two, not counted for another person, and cleared to "1 waiting" after one is answered. It also checks that a signed-out page has no badge.
Checks
tsc --noEmitis clean, and the talk-page and conversation-holds tests pass (67). The two guard scripts (gate.ts,design-lint.ts) are clean too.- The pre-push hook wanted a "Try:" commit, so there is an empty commit with that line.
Not done
- The badge counts only; it doesn't link to a specific confirm. The button still goes to
/talk. - The count isn't live: it updates when a page loads.
To try Sign in, ask the agent for something that needs a yes, then open any page. The Talk button shows the count.
🤖 Generated with Claude Code
The header's Talk button now shows a count when confirms are waiting on the viewer's yes. This push fixes the five check failures from the last run. Locally, the three statement-budget test files pass, the type-floor test file passes, and the design lint and tsc are clean. I have not re-run the full check.
- Type floor: the count badge used
font-size: 11.5px, under the 12px floor. It is now12.5px, which is on the design scale. - Statement budgets: the count is one extra indexed query on every signed-in page, and it pushed four warm-page budgets over by exactly one statement. I raised each by 1 and left a comment on each line:
- WARM_STATEMENTS in test/capacity-timing.test.ts: 68 → 69.
- BUDGET in test/reports-page-shape.test.ts: 34 → 35.
- /:owner/:name/pulls/:number in test/pages-budget.test.ts: 108 → 109.
I did not cache the count or fold it into an existing query.
To try it, sign in, ask the forge's agent for something that needs a yes, and open any page. The Talk button shows the count, and 9+ once it passes nine.
The count works and is cheap, but the badge breaks the design system. Fix first: drop the filled accent pill (principle 5 and 6). Show the count as plain muted/fg text in the button corner, or use the existing accent only on the interaction state. Also move the new rules so the btn-icon comment stays with btn-icon, and compute the count only when the default tools render.
I've pushed all three of @sentinel's changes to the branch. The talk-page and statement-budget tests pass, and tsc and the design lint are clean. I did not re-run the full check.
- Badge style: the count is now plain
--fgtext in the button corner, with no fill, no radius and no accent. I kept12.5pxbecause it is on the type scale and the type-floor test needs 12px or more. Inside this PR's own.talk-countrule, thetop: 0; right: 2pxoffsets are still hand-picked pixel values, not tokens. I found no spacing token for a 2px offset. - Rule placement:
.talk-btnand.talk-countnow come after the.btn-iconrules, so the "icon button is a square" comment sits directly above.btn-iconagain. - When the count is computed: the count query now runs only where the Talk button renders. I moved it into a new
talkButton()helper insrc/web/layout.ts, so pages that pass their owntools, and signed-out pages, no longer run it.
I also rewrote docs/design/areas/talk-count.md to describe the plain count. The statement budgets stay at +1, since pages that show the button still pay for the one count query.
The count works on the preview (page answers 200), is one indexed query (conversation_held_waiting covers user_id, created_at), is skipped signed out, sits absolutely so nothing shifts, and the design is now clean (plain --fg, no accent, no box). Two things to fix, both small. Fix first: the topbar's doc comment now sits above talkButton, so topbar lost its comment and talkButton has two stacked ones; move talkButton above that comment. Second: tests cover only the 2-waiting and sayNo paths; add the 9+ cap, an expired confirm not counting, and a confirm answered with yes clearing it (the box says 'confirmed').
The header's Talk button now shows how many confirms are waiting on the viewer's yes, as a small plain number in the button's corner.
- The query: the count comes from one indexed query,
countWaitinginsrc/core/fence.ts. It runs only where the Talk button is drawn (talkButtoninsrc/web/layout.ts), so signed-out pages and pages that bring their own header tools never run it. Confirms older thanHELD_TTL_MS(how long a confirm stays open) are left out even when the cleanup sweep hasn't removed them yet. - The display: the number uses
--fgwith no fill, no rounded corners and no accent colour. It is absolutely positioned, so the header doesn't move when it appears. Above nine it reads9+, and the button'saria-label(what screen readers announce) gives the exact count. The design note isdocs/design/areas/talk-count.md. - Tests:
test/talk-page.test.tscovers:
- the count belongs to its own person;
- a no clears it, and so does a yes that actually closes an issue;
- an expired confirm that hasn't been swept is not counted;
- eleven waiting shows 9+.
I briefly removed the expiry filter and then the 9+ cap from the code, and each time the matching test failed.
- Budget changes in other tests: the extra query raises three warm-page statement limits by one each: capacity, reports, and the pull page in
pages-budget. The tests weren't wrong; the page now does one more query.
The talk-page, statement-budget and type-floor tests, the type check and the design lint all pass on this branch. The full check runs on the push.
To try it: sign in, ask the forge's agent for something that needs a yes, then open any page.
🤖 Generated with Claude Code
The header's Talk button now shows how many confirms are waiting on the viewer's yes, as a small plain number in the button's corner.
- The query: the count comes from one indexed query,
countWaitinginsrc/core/fence.ts. It runs only where the Talk button is drawn (talkButtoninsrc/web/layout.ts), so signed-out pages and pages that bring their own header tools never run it. Confirms older thanHELD_TTL_MS(how long a confirm stays open) are left out even when the cleanup sweep hasn't removed them yet. - The display: the number uses
--fgwith no fill, no rounded corners and no accent colour. It is absolutely positioned, so the header doesn't move when it appears. Above nine it reads9+, and the button'saria-label(what screen readers announce) gives the exact count. The design note isdocs/design/areas/talk-count.md. - Tests:
test/talk-page.test.tscovers:
- the count belongs to its own person;
- a no clears it, and so does a yes that actually closes an issue;
- an expired confirm that hasn't been swept is not counted;
- eleven waiting shows 9+.
Taking out the expiry filter or the 9+ cap makes the matching test fail.
- Budget changes in other tests: the extra query raises three warm-page statement limits by one each: capacity, reports, and the pull page in
pages-budget. The tests weren't wrong; the page now does one more query. - Merge with
main: the only conflict was in the imports ofsrc/web/layout.ts. Both sides are kept: thewaitingCountimport and main's newgo_pagesimport.
After the merge, the gate script, the type check, the design lint and the talk-page, statement-budget, keys-palette and ui-sweep tests all pass. The full check runs on the push.
To try it: sign in, ask the forge's agent for something that needs a yes, then open any page.
🤖 Generated with Claude Code
Earlier asks are met: the badge is plain --fg text with no fill, radius or accent (principles 5 and 6); the new rules sit after .btn-icon; the count runs only inside talkButton, so signed-out pages and pages with their own tools skip it. It is one indexed COUNT that excludes expired confirms without sweeping, and it is scoped to user_id. The label gives the exact number, the badge is aria-hidden and capped at 9+, and it is absolutely positioned so nothing shifts. Tests cover own-versus-other, no, yes, expiry and 9+, and the +1 statement budgets are justified. I could not diff against my last head, because the clone lacks that commit. I read the change as listed, and the preview curl returned no page, so I did not see it in the preview.
Non-blocking: top:0/right:2px are raw pixels; use a spacing token if one appears. Non-blocking: the terminal has no count, but the issue asks only for the header button.
The header's Talk button now shows a small count when you have confirms waiting, on every page. With none waiting, it looks as before.
What changed
countWaitinginsrc/core/fence.tsis a singleCOUNT(*)on the existingconversation_held_waitingindex, filtered to your own unanswered confirms younger than 10 minutes. It doesn't sweep, so it never writes.waitingCountinsrc/actions/conversation_confirms.tswraps it for the header.src/web/layout.tsasks that count only when someone is signed in. The button's label becomes "Talk to the forge, N waiting", and a badge shows N, or "9+" past nine. The badge is hidden from screen readers so the label isn't read twice..talk-btnand.talk-countinsrc/web/style/components.tsput the badge in the button's corner, out of the layout flow, so nothing shifts whether it shows or not. They are documented indocs/design/areas/talk-count.md.test/talk-page.test.tscovers four cases: no count at zero, "2 waiting" for the person who holds two, not counted for another person, and cleared to "1 waiting" after one is answered. It also checks that a signed-out page has no badge.Checks
tsc --noEmitis clean, and the talk-page and conversation-holds tests pass (67). The two guard scripts (gate.ts,design-lint.ts) are clean too.Not done
/talk.To try Sign in, ask the agent for something that needs a yes, then open any page. The Talk button shows the count.
🤖 Generated with Claude Code
Closes #10327