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

A fork's page says in one line how it follows its upstream and an admin switches it in one tap #10765

Merged opened this

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

Merged

A fork's page now says in one line how it follows its upstream, and an admin switches the mode with one button after a confirm. I ran the gate, `tsc`, design-lint and the seven affected test files, including `test/mcp-size.test.ts`. They passed, 60 tests, 0 failures. I did not run the full suite.

shipped production is serving it deploy 114667f

opened this

A fork's page now says in one line how it follows its upstream, and an admin switches the mode with one button after a confirm. I ran the gate, tsc, design-lint and the seven affected test files, including test/mcp-size.test.ts. They passed, 60 tests, 0 failures. I did not run the full suite.

What changed

  • The line: the Following card on a fork's repository page shows Follows <upstream> automatically or Proposes updates from <upstream>, with the reason beside it. Anyone who can see the card sees the line. followModeWords and followSwitchPreview in src/actions/follow_words.ts hold the wording.
  • The switch: for an admin who can write, one button (“Follow automatically” or “Only propose updates”) replaces the old radio form. It goes to /-/confirm, which previews what changes and, for automatic, says a conflict still goes to the crew. Confirming POSTs to the new route /:owner/:name/following/mode/:mode. That POST goes through readForm, so it has the same-origin check, and setFollowMode still receipts it as a forge.follow_mode event.
  • MCP: the existing follow_mode tool already switched the mode, so I added no action to repo and no tool. It now answers in the same words as the page (followModeSaid). The tool list is unchanged, so test/mcp-size.test.ts passes without touching the ceilings.
  • Conflicts: automatic mode still runs the existing takeUpdates path, and when both sides changed the same files the fork is told it diverged so the crew converges it. I did not touch that path.
  • Tests: test/fork-tree-web.test.ts covers both modes on the page, the confirm preview, the cross-origin POST (403), a non-admin POST (303, nothing saved) and the audit event. A reader sees the line but no switch. test/spawn-chain-mode.test.ts checks the MCP words.

Things to know

  • Reserved query key: ?mode= is reserved by the server (the old studio/dev redirect strips it), so the mode travels in the path rather than the query.
  • Replaced test: I replaced the old radio-form assertions in test/fork-tree-web.test.ts, because that UI no longer exists on the fork page. The forge's own chain page keeps its radio form.
  • Not changed: the TUI toasts still say “Now following in X mode.” I left them alone.
  • Empty commit: the pre-push hook wanted a “Try:” commit, so the branch ends with an empty one.

To try it: open a fork you administer, read the line, and press the button. Confirm, and the line flips.

🤖 Generated with Claude Code

Closes #10748

commented

A fork's page now says in one line how it follows its upstream, and an admin switches the mode with one button after a confirm. I ran the gate, tsc, design-lint and the seven affected test files, including test/mcp-size.test.ts. They passed, 60 tests, 0 failures. I did not run the full suite.

What changed

  • The line: the Following card on a fork's repository page shows Follows <upstream> automatically or Proposes updates from <upstream>, with the reason beside it. Anyone who can see the card sees the line. followModeWords and followSwitchPreview in src/actions/follow_words.ts hold the wording.
  • The switch: for an admin who can write, one button (“Follow automatically” or “Only propose updates”) replaces the old radio form. It goes to /-/confirm, which previews what changes and, for automatic, says a conflict still goes to the crew. Confirming POSTs to the new route /:owner/:name/following/mode/:mode. That POST goes through readForm, so it has the same-origin check, and setFollowMode still receipts it as a forge.follow_mode event.
  • MCP: the existing follow_mode tool already switched the mode, so I added no action to repo and no tool. It now answers in the same words as the page (followModeSaid). The tool list is unchanged, so test/mcp-size.test.ts passes without touching the ceilings.
  • Conflicts: automatic mode still runs the existing takeUpdates path, and when both sides changed the same files the fork is told it diverged so the crew converges it. I did not touch that path.
  • Tests: test/fork-tree-web.test.ts covers both modes on the page, the confirm preview, the cross-origin POST (403), a non-admin POST (303, nothing saved) and the audit event. A reader sees the line but no switch. test/spawn-chain-mode.test.ts checks the MCP words.

Things to know

  • Reserved query key: ?mode= is reserved by the server (the old studio/dev redirect strips it), so the mode travels in the path rather than the query.
  • Replaced test: I replaced the old radio-form assertions in test/fork-tree-web.test.ts, because that UI no longer exists on the fork page. The forge's own chain page keeps its radio form.
  • Not changed: the TUI toasts still say “Now following in X mode.” I left them alone.
  • Empty commit: the pre-push hook wanted a “Try:” commit, so the branch ends with an empty one.

To try it: open a fork you administer, read the line, and press the button. Confirm, and the line flips.

🤖 Generated with Claude Code

Changes requested — before the latest push

The page line, confirm preview, same-origin POST and audit receipt are sound, and the MCP reuse of follow_mode is the right call. Three things block it. Fix the first one first.

  1. Both doors: the terminal still says 'Now following in X mode.' (src/tui/screens/forks.ts, setFollowMode toasts). It must say the same words (use followModeSaid) and show the line (followModeWords) on the fork's screen. Mason left this untouched, and the checklist requires both doors to speak alike.
  2. No docs/features how-to. Add the mode switch to docs/features/fork-tree.md or a new docs/features/follow-mode.md. It should cover the line, the confirm, the MCP follow_mode tool and the TUI key. README stays untouched.
  3. Tests are too weak. The audit assertion is length > 0, which any earlier event satisfies. Assert the count went up by one, with this repo and actor. The MCP test checks only 'automatically', so add the tell-me wording ('Proposes updates from') and assert a non-admin MCP call is refused. Also test the confirm preview for tell-me, and the page for a repo with no parent name.

Smaller: see the inline comments on dead code and on the line stating the reason twice.

commented

All three blockers and the inline comments are addressed and pushed. tsc, the gate and the design lint are clean. The six test files I ran pass, along with test/tui-following.test.ts; I did not run the full suite.

What changed

  • Both doors.

- A fork's terminal screen now shows the mode line ("Proposes updates from ann/yard" or "Follows ann/yard automatically") instead of "tells you" / "takes updates". - Pressing m toasts followModeSaid(...), the same sentence the web page and MCP use. - The forge-chain terminal screen (src/tui/screens/chain.ts) also dropped "Now following in X mode" for followModeSaid. - I updated the existing tests that asserted the old wording: test/spawn-chain-doors.test.ts and test/fork-follow-mode.test.ts.

  • Docs. New docs/features/follow-mode.md covers the line, the confirm, the MCP follow_mode tool and the m key. README is untouched.
  • Tests.

- The audit is asserted as exactly one more event, with this repo, this actor and the mode. - The MCP test now covers the "Proposes updates from" wording, a non-admin call being refused, and the switch back. - New web test: the tell-me confirm preview, the "its parent" preview for a non-writer, a root repository with no line, and followModeSaid(undefined, …) with no parent name.

  • Cleanups.

- In src/web/pages/search.ts the unreachable "Pick a mode" branch is gone; the route pattern already limits the mode, so it is cast to FollowMode. - The Following card says the mode once, as the line. The reason sentence stays in followModeSaid for MCP and the terminal toast, and in the confirm preview. - FollowMode from spawn/chain.ts is the only definition of the mode type in follow_words.ts.

Not done: the confirm preview for a non-writer still says "its parent". You called that fine, so I only added the test.

Try it: open a fork's page as its admin and tap "Follow automatically". Or open the fork's screen over SSH and press m.

🤖 Generated with Claude Code

commented

I couldn't reproduce either failure here. I merged the latest main into the branch and pushed it, so I can't say what caused them.

On the old head, both tests (docs/MCP.md holds the tool table… and the page offers the three windows…) passed when run alone and in a repeat loop. bun scripts/mcp-table.ts made no change to docs/MCP.md, so the tool table was already in sync. I believe the check ran against a different main than my branch was based on, and the merge fixes that. I haven't confirmed it.

After the merge, bun x tsc --noEmit is clean and test/mcp-table.test.ts and test/traffic-history.test.ts pass. I didn't run scripts/gate.ts or any other test files.

If the check fails again on the same two tests, send me the log lines that name what differed, since I have nothing else to go on.

The pull itself is unchanged: a fork's page says in one line how it follows its upstream, with a confirmed one-tap switch. The terminal and MCP follow_mode use the same words.

🤖 Generated with Claude Code

Approved

Earlier asks are met: the terminal shows the same line and toasts the shared sentence, docs/features/follow-mode.md exists with README untouched, the audit is asserted exactly, and the MCP refusal and switch-back are tested. The switch is a link to the confirm page and then a POST that goes through readForm, so it has the same-origin check. It works with JavaScript off and uses the existing btn component. I could not diff against my last head because the clone lacks that commit, so I judged the change as listed. Non-blocking: the chain.ts terminal toast passes undefined, so it says "its parent" instead of the upstream name. Non-blocking: the old POST /following/mode route is kept alongside the new one.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs