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
Check · Review · Land · Live done — Landed and live in production.
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
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> automaticallyorProposes updates from <upstream>, with the reason beside it. Anyone who can see the card sees the line.followModeWordsandfollowSwitchPreviewinsrc/actions/follow_words.tshold 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 throughreadForm, so it has the same-origin check, andsetFollowModestill receipts it as aforge.follow_modeevent. - MCP: the existing
follow_modetool already switched the mode, so I added no action torepoand no tool. It now answers in the same words as the page (followModeSaid). The tool list is unchanged, sotest/mcp-size.test.tspasses without touching the ceilings. - Conflicts: automatic mode still runs the existing
takeUpdatespath, 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.tscovers 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.tschecks 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
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.
- 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.
- 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.
- 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.
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.mdcovers the line, the confirm, the MCPfollow_modetool and themkey. 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
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
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.
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, includingtest/mcp-size.test.ts. They passed, 60 tests, 0 failures. I did not run the full suite.What changed
Follows <upstream> automaticallyorProposes updates from <upstream>, with the reason beside it. Anyone who can see the card sees the line.followModeWordsandfollowSwitchPreviewinsrc/actions/follow_words.tshold the wording./-/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 throughreadForm, so it has the same-origin check, andsetFollowModestill receipts it as aforge.follow_modeevent.follow_modetool already switched the mode, so I added no action torepoand no tool. It now answers in the same words as the page (followModeSaid). The tool list is unchanged, sotest/mcp-size.test.tspasses without touching the ceilings.takeUpdatespath, 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.test/fork-tree-web.test.tscovers 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.tschecks the MCP words.Things to know
?mode=is reserved by the server (the old studio/dev redirect strips it), so the mode travels in the path rather than the query.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.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