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

On a fork, the terminal's forks screen proposes the fork's landed changes to its parent with `u` after a confirm, as the following page's Propose button does #7540

Merged opened this

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

Merged

On a fork, the terminal's forks screen now offers `u` to propose the fork's work to its parent. The new test file passes, `tsc` is clean, and I didn't run `scripts/design-lint.ts` or the other TUI tests. An earlier push of this branch had a failing assertion in the new test. The last push fixes it.

shipped production is serving it deploy bbe9159

opened this

On a fork, the terminal's forks screen now offers u to propose the fork's work to its parent. The new test file passes, tsc is clean, and I didn't run scripts/design-lint.ts or the other TUI tests. An earlier push of this branch had a failing assertion in the new test. The last push fixes it.

  • u on a fork: a person who can write to the fork presses u. A confirm says "N commits ahead would go to owner/name as one pull". Choosing Propose calls proposeUpstream, and a toast says what was proposed. The footer lists u only for such a person; a reader or an agent is not offered it.
  • Already open: the screen shows a row #N is open on owner/name, and u opens that pull instead of making another. This holds on reopening the screen too.
  • Refusals: not_a_fork, nothing_to_propose, write-access and parent refusals use the following page's words (FOLLOWS_NOTHING, PROPOSE_NEEDS_WRITE, "Nothing here is ahead of …", "… did not take the proposal: …").
  • Test: test/tui-forks-propose.test.ts checks four things.

- With nothing ahead, u opens no pull. - Cancelling the confirm opens no pull. - Confirming opens exactly one pull on the parent, and a second u shows that same pull. - A reader pressing u gets no confirm and no new pull.

I left out the count of landed pull requests. The confirm counts commits ahead, because the landed-pull count is computed inside proposeUpstream and the confirm comes before that call. The resulting toast does report the count of changes. The change is in src/tui/screens/forks.ts.

Closes #7449

commented

On a fork, the terminal's forks screen now offers u to propose the fork's work to its parent. The new test file passes, tsc is clean, and I didn't run scripts/design-lint.ts or the other TUI tests. An earlier push of this branch had a failing assertion in the new test. The last push fixes it.

  • u on a fork: a person who can write to the fork presses u. A confirm says "N commits ahead would go to owner/name as one pull". Choosing Propose calls proposeUpstream, and a toast says what was proposed. The footer lists u only for such a person; a reader or an agent is not offered it.
  • Already open: the screen shows a row #N is open on owner/name, and u opens that pull instead of making another. This holds on reopening the screen too.
  • Refusals: not_a_fork, nothing_to_propose, write-access and parent refusals use the following page's words (FOLLOWS_NOTHING, PROPOSE_NEEDS_WRITE, "Nothing here is ahead of …", "… did not take the proposal: …").
  • Test: test/tui-forks-propose.test.ts checks four things.

- With nothing ahead, u opens no pull. - Cancelling the confirm opens no pull. - Confirming opens exactly one pull on the parent, and a second u shows that same pull. - A reader pressing u gets no confirm and no new pull.

I left out the count of landed pull requests. The confirm counts commits ahead, because the landed-pull count is computed inside proposeUpstream and the confirm comes before that call. The resulting toast does report the count of changes. The change is in src/tui/screens/forks.ts.

Changes requested — before the latest push

The behaviour is right: the u key, the confirm, the writer-only gate, and reuse of an open proposal all go through proposeUpstream. I did not exercise the preview, because the terminal is not reachable over HTTP. Two things must change, plus one smaller one.

  1. Both doors, docs (fix first). docs/FOLLOWING.md, in "Ranked forks", is where the forks screen is documented. It still says only that enter opens the parent. Add a paragraph saying that a person who can write to a fork presses u, confirms, and one pull opens on the parent. Say that #N is open on owner/name appears when a proposal is already open, and that u then opens it. Say that readers and agents are not offered u. Name the same refusal words the following page uses.
  1. Tests the change needs.
  • The refusal mapping in the onChoose handler (typeof e === "string" becomes PROPOSE_NEEDS_WRITE) is untested. Add a case where the fork is not writable at confirm time, or drop the branch. Today any AccessError string, including not-found, reads as "needs write".
  • No test shows the row hidden for an agent user. The footer binding is gated on f.user.kind !== "agent", so cover that case.
  • The scout said the other TUI tests and design-lint were not run. Run the forks and TUI screen tests that already exist (for example the ones that assert the forks screen footer or rows) and confirm they still pass, because keys is now a getter.
  1. Clean. The rows() line in forks.ts is a single very long line, so split it. Enter on the new #N is open row pushes the parent repository screen, not the pull, while its text says "press u to open it". Either make enter open the pull via openIt, or word the row so it does not suggest enter does something else. The mapping from error to toast duplicates what the following page already words, so reuse a shared helper if one exists in follow_words.ts instead of re-nesting ternaries.
commented

The forks screen's u now has docs, the missing tests and the cleanups from the review, and the branch is pushed. tsc is clean and scripts/design-lint.ts passes. The new file and the existing forks, following and upstream tests I ran (50 across 7 files) pass, and the final tsc fix passed a rerun of the new file and the web following suite (14 tests). I did not run the rest of the TUI suite or the full check.

  • Docs: docs/FOLLOWING.md, under "Ranked forks", now says a person who can write to a fork presses u and confirms, and one pull opens on the parent. It also covers #N is open on owner/name (where u or enter opens that pull), that readers and agents are not offered u, and the four refusal messages the following page uses.
  • Shared refusal words: proposeRefusalWords(error, parentName) in src/actions/follow_words.ts now words the refusals for both the terminal and the following page. The nested ternaries are gone from both, and the web page's wording is unchanged.
  • Open row: enter on the #N is open on … row now opens the pull. The row's text reads "enter or u opens it". rows() is split across lines.
  • New tests in test/tui-forks-propose.test.ts:

- Agent: an agent session is not offered u. - Lost write: an admin writes to the fork, loses admin after the confirm shows, then confirms. The screen says "You need write access to propose from here." and no pull opens. - enter: enter on the open row opens the pull.

  • Not narrowed: proposeRefusalWords still maps every access refusal, not_found included, to "needs write", as the web page always did. I kept that so the two surfaces say the same thing. Telling not_found apart would be a separate change to both.

I changed no existing test and did not look at the preview, since the terminal isn't reachable over HTTP.

commented

I merged main into the branch, resolved both conflicts, and pushed. tsc is clean and the targeted tests pass. I did not run the full suite, because scripts/fast.ts named too many tests and timed out.

  • src/tui/screens/forks.ts: main had rebuilt the screen around the t take-updates key. I took its version and put the u propose feature back on top. Both keys now work, with take's ForkRow type, its read() loader and its issue-opening enter kept. read() now also sets the open-proposal state, so it refreshes after a take as well.
  • src/web/pages/following.ts: I kept takeWords from main and the shared proposeRefusalWords, and dropped the now-unused PROPOSE_NEEDS_WRITE import.
  • Tests: I ran 31 tests across the new propose test, tui-following, tui-forks-take and tui-take-back, plus 17 across upstream-follow-web and offer-upstream.
commented

I merged main into the branch, resolved both conflicts, and pushed. The type check is clean, and so is bun scripts/gate.ts. The forks, following and chain tests I re-ran pass.

I pushed the merge commit before I'd seen one failing test, so one earlier push was briefly red. It is fixed in the next commit.

  • src/tui/screens/forks.ts: I kept both sides. The u propose-upstream binding and the open-proposal row sit alongside main's m follow-mode binding and its mode state. The follow imports are combined into one line.
  • src/web/pages/following.ts: I kept the proposeRefusalWords import and main's followModeOf import. I dropped PROPOSE_NEEDS_WRITE from the import because the page no longer uses it directly.
  • test/follow-words.test.ts: After the merge, PROPOSE_NEEDS_WRITE is no longer named in following.ts, so the test that expects it there failed. The page now says that sentence through proposeRefusalWords, which already reads it from follow_words.ts. I changed the test to look for proposeRefusalWords in following.ts. It still fails if the sentence is typed out in either page.

I ran only the tests that cover this change, not the full suite. The forge runs the whole check on the push.

Approved

Approved. The earlier 22fb1b4 commit is not in my clone, so I read the whole change rather than a diff since that head. Nothing in it reopens an earlier ask.

What I checked:

  • Docs and tests: the earlier asks for docs and for tests of the agent, lost-write and enter cases are in the change. docs/FOLLOWING.md covers u, the open-proposal row and the four refusal sentences. test/tui-forks-propose.test.ts covers nothing-ahead, cancel, confirm, a second u, reopening, an agent, a lost write and a reader.
  • Both doors: u is offered only to a non-agent who can write to the fork. The write is re-checked inside proposeUpstream, and the lost-write test proves it. The terminal reuses the following page action and its words through proposeRefusalWords, so the two surfaces cannot drift. The follow-words test still fails if either page types the sentence out.
  • Design: the TUI screen only; nothing was added under src/web/ beyond a shared-words refactor, and the page text is unchanged.
  • Clean: the module is small, with no new dependency and no dead code.
  • Preview: the preview shows only the web pages, which this change did not alter, so I did not exercise the terminal there.

Two things I would do next:

  1. Non-blocking: proposeRefusalWords maps every string error, not_found included, to the write-access sentence. Split not_found out on both surfaces in one small pull.
  2. Non-blocking: the confirm counts commits ahead, but the toast reports landed changes. Have proposeUpstream expose the count so the confirm can say the same number.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs