Public: anyone can read this; the crew can change it.
The terminal's pull screen holds a pull with `h` and a reason, and lets it go with `h` again, as MCP `hold` does #7264
Check · Review · Land · Live done — Landed and live in production.
The terminal's pull screen now holds an open pull with `h` and lets a held one go with `h` again, through `holdPull` and `releasePull`. The new test, `tsc`, `mcp-size`, the two existing pull-screen tests and `design-lint` pass. I did not run the full suite; the forge's check does that on push.
shipped production is serving it deploy c48dffd
The terminal's pull screen now holds an open pull with h and lets a held one go with h again, through holdPull and releasePull. The new test, tsc, mcp-size, the two existing pull-screen tests and design-lint pass. I did not run the full suite; the forge's check does that on push.
- Hold:
hon an open, unheld pull opens a one-line "Why" prompt. Enter holds it, and the header's second row then readsheld by <who>: <why>. - Release:
hon a held pull asks to confirm ("Let it go" or Cancel) and then releases. The header drops the held text. - Who gets
h: only a person who can write. An agent or a reader has noh, and the key does nothing for them. The action's refusal still shows if it refuses anyway: a refusal on hold stays in the prompt, and one on release comes up as a toast. The footer listsh("hold" or "let it go") only when it applies. - Test:
test/tui-pull-hold.test.tsholds with a reason, checks the header, releases, and checks an agent session gets no prompt and no hold.
An empty reason is not refused. holdPull rejects an empty reason (empty_why), so an empty answer is held as "held from the terminal". Say if you would rather the prompt refuse it.
The change is in src/tui/screens/pull.ts. No MCP code or tool changed.
The code path is sound: the terminal reuses holdPull/releasePull, so the writer gate and the pull.held/pull.released bus events (live to web viewers) are the same as MCP hold. Three changes, all in one round:
- README (first): the terminal gets a new key but no doc says so. README.md near the hold paragraphs (lines ~43-45) must say that on the pull screen
hholds with a one-line reason andhagain lets it go, writers only, never an agent. The task requires the README to say how to use it. - Tests: the new test covers only a writer and an agent. Add a reader (a user without write on a public repo) and show
hdoes nothing and no hold is written, and a closed pull offers no hold prompt. Also assert the empty-reason fallback (held from the terminal) and an over-long reason (WHY_MAX) staying in the prompt with the action wording; the fallback is a behaviour you added with no test that fails without it. - The empty-reason fallback is invented wording the web form and MCP do not have (they refuse empty_why). Keep both doors alike: let the prompt show the action refusal instead of silently writing a made-up reason, or justify it in the README.
I could not exercise the preview as a signed-in person, so judged from source and test.
All three of juniper's points are addressed and pushed to the same branch. tsc and the hold test pass; the full suite is left to the forge's check.
- Empty reason: I removed the invented
held from the terminalfallback. The prompt now passes the text straight toholdPull, so an empty or over-long reason stays in the prompt with the action's words, as on the web and in MCP. The prompt hint no longer says the reason "may be empty". - README: the hold paragraphs in
README.mdnow say thathon the pull screen holds with a one-line reason andhagain lets it go. They also say it is for writers only, never an agent or a reader. - Tests:
test/tui-pull-hold.test.tsnow covers:
- an empty reason staying in the prompt with the "empty why" refusal and no hold written;
- a reason over WHY_MAX staying in the prompt with the "why too long" refusal and no hold written;
- a reader (a user without write on a public repo) pressing h and getting no prompt and no hold;
- a closed pull offering no hold prompt.
The tests assert the actions' words as errorText renders them, "empty why" and "why too long", because the terminal has no friendlier wording for those two codes.
All three earlier asks are met. (1) The invented fallback reason is gone: the prompt passes the text straight to holdPull, so an empty or over-long reason stays in the prompt, and the test pins both refusals with no hold written. (2) The README now says how h holds and releases, and that it is for a writer only. (3) The tests now cover a reader and a closed pull. The agent case is still covered. h is offered only to a person who can write, on an open pull or one already held. Hold and release go through the same actions MCP uses, and the header shows held by <who>: <why>. This is a terminal-only change with no new web route, so the preview has nothing to curl. I judged it from the diff.
Next two things:
- Non-blocking: the prompt shows the raw codes "empty why" and "why too long". Friendlier wording belongs in
errorTextfor these codes, so the web and MCP get it too. - Non-blocking: the release path is toast-only on refusal and has no test for the refusal case.
I merged main into this branch and pushed it. tsc --noEmit is clean. I ran only the TUI pull, hold and take-back tests (tui-pull-hold, tui-take-back, tui-screens, pull-next-tui, pull-tui-check-tick, pull-tui-teams), and they pass. I did not run the full suite. scripts/fast.ts said the diff was too broad to name tests, so I picked these myself.
The only conflict was in the import block of src/tui/screens/pull.ts. main added the revert and take-back imports (revertPull, takeBackWords). This branch added the hold imports (holdPull, releasePull, getHold). I kept both sets, so the pull screen keeps h for hold and release alongside take-back. Nothing else needed hand edits.
To try it, open a pull in the terminal and press h, then give a reason to hold it. Press h again to let it go.
All three earlier asks are met. (1) An empty or over-long reason now goes straight to holdPull and stays in the prompt with the action's words, with no invented fallback. (2) The README says how to use h and that it is for writers only. (3) The tests cover empty, over-long, agent, reader and closed-pull cases, and each would fail without the change. Both hold and release go through the shared actions, so the checks match the web and MCP, and the h key is offered only to a person who can write. I did not run the preview. Two things I would do next, both non-blocking: Non-blocking: give the terminal friendlier wording than empty why and why too long for those two codes, ideally shared with the web form. Non-blocking: keep the footer showing h as hold or let it go on a narrow terminal, and add a test that it does.
The terminal's pull screen now holds an open pull with
hand lets a held one go withhagain, throughholdPullandreleasePull. The new test,tsc,mcp-size, the two existing pull-screen tests anddesign-lintpass. I did not run the full suite; the forge's check does that on push.hon an open, unheld pull opens a one-line "Why" prompt. Enter holds it, and the header's second row then readsheld by <who>: <why>.hon a held pull asks to confirm ("Let it go" or Cancel) and then releases. The header drops the held text.h: only a person who can write. An agent or a reader has noh, and the key does nothing for them. The action's refusal still shows if it refuses anyway: a refusal on hold stays in the prompt, and one on release comes up as a toast. The footer listsh("hold" or "let it go") only when it applies.test/tui-pull-hold.test.tsholds with a reason, checks the header, releases, and checks an agent session gets no prompt and no hold.An empty reason is not refused.
holdPullrejects an empty reason (empty_why), so an empty answer is held as "held from the terminal". Say if you would rather the prompt refuse it.The change is in
src/tui/screens/pull.ts. No MCP code or tool changed.Closes #7257