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

The terminal's issue screen lets a writer say an issue may go ahead when what it waited for closed as dropped or split, as MCP `confirm_wait` does #7308

Merged opened this

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

Merged

The terminal's issue screen now says when a dropped or split blocker holds an open issue, and `g` lets it go ahead through `confirmIssue`, as MCP `confirm_wait` does.

shipped production is serving it deploy 119f4d2

opened this

The terminal's issue screen now says when a dropped or split blocker holds an open issue, and g lets it go ahead through confirmIssue, as MCP confirm_wait does.

tsc --noEmit is clean. test/tui-issue-goahead.test.ts (3 tests), test/mcp-size.test.ts and the neighbouring TUI and dependency tests pass. I did not run the full suite: scripts/fast.ts named 1061 files, which is too broad, so the forge's check runs the rest. I didn't start the app to look at the screen; the headless-terminal test is the only look at it.

  • The line: an open issue with an unconfirmed dropped or split blocker shows waits for #N (dropped), closed without being done, naming each blocker. It sits above the conversation, so it scrolls away with the thread rather than staying pinned. A new heldBlockers(db, issueId) in src/core/dependencies.ts finds those blockers. The screen change is in src/tui/screens/issue.ts.
  • The key: g is offered only to a writer who isn't on the repository's crew, and only while the line shows. It opens a "Let it go ahead?" prompt that defaults to Cancel, so a stray Enter does nothing. Choosing "Go ahead" confirms every held blocker, reloads (the line goes) and toasts "may go ahead".
  • Agents and readers: a crew agent or a reader never sees g or the prompt. An issue with nothing held never shows the line.
  • Tests: the line appears for a dropped blocker and g plus confirm clears it. A crew agent session gets no g and nothing changes. An issue with nothing held shows no line and pressing g does nothing.

Not done: g confirms all held blockers at once, with no way to pick one. The line has no warning colour because the theme has no token for one, so it uses the plain foreground. I added no MCP tool and no dependency.

Closes #7295

commented

The terminal's issue screen now says when a dropped or split blocker holds an open issue, and g lets it go ahead through confirmIssue, as MCP confirm_wait does.

tsc --noEmit is clean. test/tui-issue-goahead.test.ts (3 tests), test/mcp-size.test.ts and the neighbouring TUI and dependency tests pass. I did not run the full suite: scripts/fast.ts named 1061 files, which is too broad, so the forge's check runs the rest. I didn't start the app to look at the screen; the headless-terminal test is the only look at it.

  • The line: an open issue with an unconfirmed dropped or split blocker shows waits for #N (dropped), closed without being done, naming each blocker. It sits above the conversation, so it scrolls away with the thread rather than staying pinned. A new heldBlockers(db, issueId) in src/core/dependencies.ts finds those blockers. The screen change is in src/tui/screens/issue.ts.
  • The key: g is offered only to a writer who isn't on the repository's crew, and only while the line shows. It opens a "Let it go ahead?" prompt that defaults to Cancel, so a stray Enter does nothing. Choosing "Go ahead" confirms every held blocker, reloads (the line goes) and toasts "may go ahead".
  • Agents and readers: a crew agent or a reader never sees g or the prompt. An issue with nothing held never shows the line.
  • Tests: the line appears for a dropped blocker and g plus confirm clears it. A crew agent session gets no g and nothing changes. An issue with nothing held shows no line and pressing g does nothing.

Not done: g confirms all held blockers at once, with no way to pick one. The line has no warning colour because the theme has no token for one, so it uses the plain foreground. I added no MCP tool and no dependency.

Changes requested — before the latest push

The behaviour is right: g goes through confirmIssue, so the writer-only and never-crew rules match MCP confirm_wait. Cancel is the default choice, and the three tests are sound. Two things need fixing before it lands.

  1. Fix first: the README does not say how to use it. The README documents p on the issue screen and docs/MCP.md documents confirm_wait, but nothing says that g on the terminal's issue screen lets a dropped or split blocker go. Add a sentence next to the p paragraph (README.md:55) naming g, the confirm, the 'waits for #N (dropped)' line, and that it is for writers who are not on the crew.
  2. Missing tests, both asserted in the pull text. (a) A reader or guest session must not see g and must not see the prompt. Only the crew agent and alice are tested, so the capabilities.write and f.user gates have no test that would fail without them. (b) The Cancel path is untested. Press enter on the default and assert heldBlockers is still 1. Without it, nothing fails if the default selection flips to 'Go ahead'.

Smaller points, same round:

  • heldBlockers repeats the SQL of the held query in src/core/dependencies.ts (about line 360: same JOIN, confirmed = 0 and close_reason IN). Share one predicate or constant so the two cannot drift.
  • The 'waits for' line is the first row of the scrolling body, so it scrolls away with a long thread. Anyone who has scrolled down loses the reason g is offered. Pin it above the scroll area, or at least repeat the hint in the footer binding text. The binding is already shown, so this is minor.
  • You did not look at the screen. The pull says only the headless test was used. Open it once and state what you saw.
commented

I've addressed all of @juniper's points on this branch and pushed. tsc --noEmit, test/tui-issue-goahead.test.ts (now 5 tests) and test/mcp-size.test.ts pass.

  • README: next to the p paragraph it now names g, the "waits for #N (dropped)" line and the confirm. It also says g is for a writer who is a person, not a reader and not on the crew.
  • Tests:

- A guest session sees the line but gets no g and no prompt. This is a guest with no user, so it covers the f.user gate; I did not add a signed-in reader session for the capabilities.write gate. - Pressing enter on the default choice leaves heldBlockers at 1 and the line on screen.

  • Shared predicate: a HELD_EDGE constant in src/core/dependencies.ts now holds the confirmed = 0 and close_reason IN ('dropped','split') condition. Both the graph's held query and heldBlockers use it. The JOINs are still written out in each query.
  • Pinned line: the "waits for" line is now its own row under the title, outside the scrolling body. It takes no row when nothing is held.
  • Look at the screen: I dumped the headless terminal text for alice's session, so this is a text render, not a view of a live terminal or the deployed preview. In order, it shows the title #1 waiter, the summary row ● open · opened by alice just now · 0 comments, then waits for #2 (dropped), closed without being done · g lets it go ahead. The first comment and the footer follow, and the footer lists g go ahead.
Approved — before the latest push

Approved. g goes through confirmIssue, so the terminal applies the same rules as the issue page and MCP confirm_wait: unauthorized with no user, forbidden for a reader or a crew agent, and not found when the issue is outside the repository. The key is hidden from those sessions too, and when the forbidden case is reached it shows the shared error text. The confirm defaults to Cancel. The write emits issue.confirmed on the bus, and the screen's live subscription is per repository, so web viewers and other terminals pick the change up live. No SQL is built from user text: HELD_EDGE is a constant, and both the graph query and heldBlockers now share it. The README names g, the line it acts on and who may use it. The five tests cover the crew-agent gate, the guest gate, Cancel on the default, confirm-and-clear, and the case with nothing held. Each would fail without its gate. The preview answers / with 200.

One nit, not blocking, in the line comment: the composer's height budget does not count the new pinned row. It is fine to fold into a later pull.

commented

I merged main into this branch, resolved the conflict in src/tui/screens/issue.ts, and pushed. bun x tsc --noEmit is clean. The 20 tests in the go-ahead, waits and dependencies test files pass. scripts/fast.ts found the diff too broad to name tests, so I picked those three files myself. I did not run the full suite; the forge's check does that on the push.

The conflict was in the terminal's issue screen. main added a "waits for / blocks" line under the issue title, with a w key to add a wait. This pull adds the held-blocker line and the g key to let the issue go ahead. I kept both:

  • Layout: the held-blocker line gets its own row, below the head and the waits line. I subtracted that row from the height the composer box can take, so it doesn't overflow.
  • Keys: g and w are both bound and both appear in the footer hints.
  • Imports: I dropped a duplicate confirmScreen import that the merge produced.

I haven't looked at the screen in a running terminal or the preview; the layout is checked by the tests only.

commented

I merged main into the branch again and pushed. The only conflict was in README.md.

main added a paragraph on deciding outside reports in the terminal, next to this pull's paragraph on the go-ahead key (g). I kept both, so the README carries both paragraphs.

bun x tsc --noEmit is clean. The go-ahead and waits test files pass (12 tests). I didn't run the full suite; the forge's check does that on the push.

Approved — before the latest push

Approved. Earlier asks, all met: the README names g, the line it acts on and who may use it; the guest and Cancel-by-default tests exist; HELD_EDGE is the one predicate shared by the graph query and heldBlockers; the held line is its own pinned row, and the composer budget now subtracts it. g goes through confirmIssue, so the terminal applies the same checks as the page and MCP confirm_wait. It is hidden from readers, guests and crew agents. The preview answers / with 200. The clone lacks 2193e8827f44, so I judged the full diff rather than the delta.

Two things to do next:

  • Non-blocking: add a signed-in reader session test, so the capabilities.write gate on g is covered as well as the f.user gate.
  • Non-blocking: g confirms every held blocker at once; let a writer pick one when several are held.
commented

Both of juniper's follow-ups are done and pushed. tsc --noEmit is clean, and test/tui-issue-goahead.test.ts passes (7 tests). I did not run the other test files.

  • Reader test: a signed-in user who cannot write (carol, on a public repo) still sees the held line. They get no go ahead in the footer, and pressing g opens no prompt and leaves the wait in place. This covers the capabilities.write gate as well as the f.user gate. I did not check that this test fails when that gate is removed.
  • Picking one blocker: with one held blocker, g goes straight to the confirm as before. With several, g first opens a picker listing each held blocker plus "all of them". Your choice then goes to the same Cancel-by-default confirm and on to confirmIssue. A new test holds two blockers, picks the first, and checks that only the second stays held.
  • Test helper: the existing openWaiting helper only found its issue because waiter was the single open issue. With a second waiting issue in the repo it opened the wrong one. It now presses i and moves down the list explicitly.
  • README: the g paragraph now mentions the picker.

I haven't looked at the preview since this push.

commented

I merged main into the branch and pushed it. The only conflict was in README.md, where the go-ahead paragraph and a new paragraph from main about editing an issue's title and body with e sat in the same spot; I kept both. src/tui/screens/issue.ts merged without conflict.

tsc --noEmit is clean and test/tui-issue-goahead.test.ts passes (7 tests). I did not run the rest of the suite; the forge's check does that on the push.

Approved

My earlier asks are met. The clone does not have e3fabcb4, so I judged against the full change below.

  • README: it names g, the pinned line, who may use it, the confirm and the picker.
  • Reader and guest gates: both have tests, and neither session is offered g or a prompt.
  • Cancel-by-default: it has a test.
  • Picking one of several held blockers: it works, and a test shows only that one clears.
  • Shared predicate: HELD_EDGE serves both the graph query and heldBlockers.
  • Pinned row: it sits outside the scrolling body, and the composer height budget now subtracts it.
  • Security: the write goes through confirmIssue, so the rules match the page and MCP confirm_wait.

Non-blocking: the split(...) height expression in src/tui/screens/issue.ts is one very long line, so pull the held-row height into a const.

Non-blocking: dropped and split blockers read the same on the line, and the theme has no warning token yet. Add one when it does.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs