Public: anyone can read this; the crew can change it.

The header's Talk button shows when a conversation waits on your yes #10644

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

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

opened this

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

  • countWaiting in src/core/fence.ts is a single COUNT(*) on the existing conversation_held_waiting index, filtered to your own unanswered confirms younger than 10 minutes. It doesn't sweep, so it never writes. waitingCount in src/actions/conversation_confirms.ts wraps it for the header.
  • src/web/layout.ts asks 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-btn and .talk-count in src/web/style/components.ts put the badge in the button's corner, out of the layout flow, so nothing shifts whether it shows or not. They are documented in docs/design/areas/talk-count.md.
  • The new test in test/talk-page.test.ts covers 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 --noEmit is 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

Closes #10327

commented

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

  • countWaiting in src/core/fence.ts is a single COUNT(*) on the existing conversation_held_waiting index, filtered to your own unanswered confirms younger than 10 minutes. It doesn't sweep, so it never writes. waitingCount in src/actions/conversation_confirms.ts wraps it for the header.
  • src/web/layout.ts asks 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-btn and .talk-count in src/web/style/components.ts put the badge in the button's corner, out of the layout flow, so nothing shifts whether it shows or not. They are documented in docs/design/areas/talk-count.md.
  • The new test in test/talk-page.test.ts covers 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 --noEmit is 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

commented

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 now 12.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.

Changes requested — before the latest push

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.

commented

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 --fg text in the button corner, with no fill, no radius and no accent. I kept 12.5px because it is on the type scale and the type-floor test needs 12px or more. Inside this PR's own .talk-count rule, the top: 0; right: 2px offsets are still hand-picked pixel values, not tokens. I found no spacing token for a 2px offset.
  • Rule placement: .talk-btn and .talk-count now come after the .btn-icon rules, so the "icon button is a square" comment sits directly above .btn-icon again.
  • When the count is computed: the count query now runs only where the Talk button renders. I moved it into a new talkButton() helper in src/web/layout.ts, so pages that pass their own tools, 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.

Changes requested — before the latest push

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').

commented

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, countWaiting in src/core/fence.ts. It runs only where the Talk button is drawn (talkButton in src/web/layout.ts), so signed-out pages and pages that bring their own header tools never run it. Confirms older than HELD_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 --fg with 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 reads 9+, and the button's aria-label (what screen readers announce) gives the exact count. The design note is docs/design/areas/talk-count.md.
  • Tests: test/talk-page.test.ts covers:

- 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

commented

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, countWaiting in src/core/fence.ts. It runs only where the Talk button is drawn (talkButton in src/web/layout.ts), so signed-out pages and pages that bring their own header tools never run it. Confirms older than HELD_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 --fg with 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 reads 9+, and the button's aria-label (what screen readers announce) gives the exact count. The design note is docs/design/areas/talk-count.md.
  • Tests: test/talk-page.test.ts covers:

- 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 of src/web/layout.ts. Both sides are kept: the waitingCount import and main's new go_pages import.

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

Approved

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.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs