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

The terminal's run screen says a word to a running crew run with `s`, as the run page's steer box and MCP `steer` do #7309

Merged opened this

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

Merged

The terminal can now steer a running crew run. A one-line composer sends the text through `steerRepoRun`, and the outcome shows as a toast in MCP's words: "Sent. The agent hears it at its next step." or "Commented. No session was listening; …".

shipped production is serving it deploy 0583edb

opened this

The terminal can now steer a running crew run. A one-line composer sends the text through steerRepoRun, and the outcome shows as a toast in MCP's words: "Sent. The agent hears it at its next step." or "Commented. No session was listening; …".

Keys. The issue asked for s, but on the runs list (src/tui/screens/runs.ts) s already cycles the state filter, and test/tui-runs-state.test.ts checks that. Letting s steer only when a running agent row is selected would also trap someone on the Running filter. So steering is S there. On the issue screen's crew card and the pull's Crew tab, s is free and steers.

Where it lives.

  • maySteer and steerPrompt in src/tui/screens/runlist.ts, used by all three screens. Steering is offered only on an agent run that is running, to a person (never an agent session) who can write the repository. Empty text keeps the composer open with "Say something first.".
  • The two outcome sentences are STEER_SAYS in src/actions/runs.ts. MCP steer now reads them from there instead of writing them inline; its doc and schema are unchanged.
  • src/crew/runner.ts registers a listening session through a new exported listenForSteer, which the runner itself now calls. Behaviour is the same, and a test can listen to a run the way a session does.

Tests. The new test/tui-steer.test.ts covers: S on the runs list reaches a listening session; with no session listening the text becomes a comment on the issue; empty text is refused in place; a finished run has no steer key; the crew card steers with s; and an agent with write access is not offered it. With the agent check removed, the last test fails. bun x tsc --noEmit is clean. 329 tests across 34 files pass with 1 skipped, including test/mcp-size.test.ts, the run-cancel and runs-state tests, and the issue, pull, runner and steer suites. scripts/fast.ts named 1130 files, so I chose these by hand.

I left a queued run without steering: the issue asks only for running runs, and the run page still covers the others.

To try it: start a crew run, open the repository's runs list in the terminal, select the running agent row, press S, type a sentence and press enter.

🤖 Generated with Claude Code

Closes #7288

commented

The terminal can now steer a running crew run. A one-line composer sends the text through steerRepoRun, and the outcome shows as a toast in MCP's words: "Sent. The agent hears it at its next step." or "Commented. No session was listening; …".

Keys. The issue asked for s, but on the runs list (src/tui/screens/runs.ts) s already cycles the state filter, and test/tui-runs-state.test.ts checks that. Letting s steer only when a running agent row is selected would also trap someone on the Running filter. So steering is S there. On the issue screen's crew card and the pull's Crew tab, s is free and steers.

Where it lives.

  • maySteer and steerPrompt in src/tui/screens/runlist.ts, used by all three screens. Steering is offered only on an agent run that is running, to a person (never an agent session) who can write the repository. Empty text keeps the composer open with "Say something first.".
  • The two outcome sentences are STEER_SAYS in src/actions/runs.ts. MCP steer now reads them from there instead of writing them inline; its doc and schema are unchanged.
  • src/crew/runner.ts registers a listening session through a new exported listenForSteer, which the runner itself now calls. Behaviour is the same, and a test can listen to a run the way a session does.

Tests. The new test/tui-steer.test.ts covers: S on the runs list reaches a listening session; with no session listening the text becomes a comment on the issue; empty text is refused in place; a finished run has no steer key; the crew card steers with s; and an agent with write access is not offered it. With the agent check removed, the last test fails. bun x tsc --noEmit is clean. 329 tests across 34 files pass with 1 skipped, including test/mcp-size.test.ts, the run-cancel and runs-state tests, and the issue, pull, runner and steer suites. scripts/fast.ts named 1130 files, so I chose these by hand.

I left a queued run without steering: the issue asks only for running runs, and the run page still covers the others.

To try it: start a crew run, open the repository's runs list in the terminal, select the running agent row, press S, type a sentence and press enter.

🤖 Generated with Claude Code

Changes requested — before the latest push

The change is sound. Steering goes through steerRepoRun, so the terminal is gated like the run page and MCP: only a person who can write, never an agent, and the verified check happens in the action. A word that is sent lands in the run log through steerRun, the same path the page uses. A comment goes through addComment. S on the runs list is the right choice and the pull explains it. I found no security problems: no new input crosses a boundary unchecked, and the output is a toast in fixed words.

Two items on the review list are missing. Fix both in this round:

  1. Do this first: the pull's Crew tab s has no test. src/tui/screens/pull.ts adds a key and its binding, but test/tui-steer.test.ts only covers runsScreen and issueScreen. If the tab === 2 branch were deleted, every test would still pass. Add one test in the style of the issue-card test: open pullScreen on a pull with a running agent run on it, switch to the Crew tab, check that s steer shows, then press s, type, press enter, and assert the word reached listenForSteer and the toast says Sent.
  1. Nothing tells a person the terminal can steer. The README and the docs are untouched. Add one line where the terminal's run doors are described, for example next to the MCP steer row in docs/MCP.md or in the README: S on the runs list, s on an issue's crew card and on a pull's Crew tab, for a writer who is a person, on a running agent run only.

I could not test it in the preview myself: it answers / with 200, but my sandbox has no SSH, so I could not reach the terminal there.

commented

The terminal can now steer a running crew run. S on the runs list, s on an issue's crew card and s on a pull's Crew tab each open a prompt. The word goes through steerRepoRun, the same path as the run page's steer box and MCP steer. It is offered only on a running agent run, to someone who can write here and is a person, not an agent. If no agent session is listening, the word is posted as a comment on the issue or pull instead.

This round adds the two things the review asked for:

  • Crew tab test. test/tui-steer.test.ts has a new test, "the pull's Crew tab steers with s". It opens pullScreen on a real pull with a running agent run, switches to the Crew tab and checks that s steer shows. Then it presses s, types, presses enter, and checks that the word reached listenForSteer and the toast says Sent.. I turned off the s branch in src/tui/screens/pull.ts and the test failed, then put the branch back. All 7 tests in the file pass and tsc --noEmit is clean.
  • Docs. The steer row in docs/MCP.md now says the terminal does the same with these three keys, and who gets them.

I chose S rather than s on the runs list, which the first round's description explains.

To try it: SSH into the forge with a running agent run on a repository you can write to. Open its runs list and press S, or open the pull, press tab to reach Crew and press s. Type a word and press enter.

🤖 Generated with Claude Code

commented

The terminal can now steer a running crew run, as the run page's steer box and MCP steer can. S on the runs list, s on an issue's Crew card and s on a pull's Crew tab open a prompt. The word goes through steerRepoRun, so the rules are the same as on the page. Steering is offered only on a running agent run, to someone who can write here and is a person, never an agent. Empty text is refused in place. The toast says whether the agent heard the word or, with no session listening, it was posted as a comment on the issue or pull. The runs list uses S, not s; the first round's description says why.

Changes from review:

  • Crew tab test: test/tui-steer.test.ts now covers steering from a pull's Crew tab. With that key's handler in src/tui/screens/pull.ts turned off, the test fails.
  • Docs: the terminal's steering is described in docs/design/sections/6g-terminal-apps-runs-crew.md, next to the entry for a run row.
  • Failed check: the reviewer suggested putting the docs line in the steer row of docs/MCP.md. That table is generated by scripts/mcp-tools.ts, and the hand edit failed the freshness test in test/mcp-tools.test.ts. The row is back to its generated text, and the docs line lives in the design section instead.

test/tui-steer.test.ts and test/mcp-tools*.test.ts pass (166 tests), and bun x tsc --noEmit was clean on the previous commit (this last one changed only docs).

To try it: SSH into the forge with a running agent run on a repository you can write to. Press S on its runs list, or open the pull, press tab until the Crew tab is showing and press s. Type a word and press enter.

🤖 Generated with Claude Code

Approved — before the latest push

Both asks from the last round are done.

  1. Pull Crew tab test: met. test/tui-steer.test.ts now has "the pull's Crew tab steers with s". It opens pullScreen on a real pull with a claimed agent run, tabs to Crew, checks that s steer shows, sends a word, and checks that listenForSteer heard it and the toast says Sent. The builder reports the test fails with the tab === 2 branch turned off, which matches what the test asserts.
  2. Docs: met. docs/design/sections/6g-terminal-apps-runs-crew.md now has a Steer line that names the three keys and says who gets them: a writer who is a person, on a running agent run only. Restoring the generated docs/MCP.md row was right, since that table is checked for freshness.

The lines that changed since my last review are only the new test and the docs line. They raise no security issue. The preview answers / with 200. I could not drive the terminal there because my sandbox has no SSH.

Non-blocking: the pull test waits up to 20 s for the Crew tab to appear. If it ever runs slowly, a smaller ceiling or a seeded state that skips the wait would keep it inside a per-test time budget (#1242).

commented

In the terminal, s now sends a word to a running crew run from three places: the runs list (S), an issue's crew card, and a pull's Crew tab. It does the same as the steer box on the run page and the MCP steer tool. Only a person who can write to the repository gets the key, and only on an agent run that is still running. A finished run, or an agent session that may write, is not offered it.

This round makes one change, from review: the pull's Crew tab test in test/tui-steer.test.ts now gives up after 3 s instead of 20 s while it waits for the tab to show. A hang now fails fast and stays inside the per-test budget (#1242). 3 s is the limit test/tui-teams.test.ts already uses. The test passes in about 1.5 s on its own, and all 7 tests in the file pass.

Earlier commits on this pull:

  • 6e7f3cc7 adds the keys.
  • 7da7d067 adds the pull Crew tab test.
  • 03cec815 adds the Steer line to docs/design/sections/6g-terminal-apps-runs-crew.md and leaves docs/MCP.md as generated, since that table is checked for freshness.

To try it, connect with the command in FORGE_APP_SSH, open a repository's runs while an agent run is running, press S, type a word, and press enter. The toast says Sent. and the run hears the word.

🤖 Generated with Claude Code

commented

In the terminal, a person who can write to the repository can now send a word to a running crew run, the same way the run page's steer box and MCP steer do. The key is S on the runs list (where s already cycles the state filter), and s on an issue's crew card and on a pull's Crew tab. It only appears on an agent run that is running, and an agent's own session is never offered it. The send goes through steerRepoRun, and the toast uses the same words MCP answers with.

What moved where:

  • maySteer and steerPrompt live in src/tui/screens/runlist.ts, and the runs, issue and pull screens all call them.
  • docs/design/sections/6g-terminal-apps-runs-crew.md has a Steer line naming the three keys and who gets them.

Since the last round:

  • Merge with main. The pull did not merge because main added the run log screen and runwords.ts (#7306) and the runs screen's a requeue (#7307) in the same files. Both sides are kept:

- pull.ts imports runTone from runwords.ts. - runlist.ts keeps main's log screen beside maySteer and steerPrompt. - The runs screen offers both S and a, in its key list, its key handling and its header comment.

  • Test timeout. From review, the pull Crew tab test in test/tui-steer.test.ts now waits at most 3 s for the tab instead of 20 s, the same limit test/tui-teams.test.ts uses. On its own that test takes about 1.5 s.

After the merge, tsc is clean, the design lint passes, and the steer, runs, cancel, requeue, run log and pull hold test files pass (40 tests).

To try it: connect with the command in FORGE_APP_SSH, open a repository's runs while an agent run is running, press S, type a word and press enter. The toast says Sent.

🤖 Generated with Claude Code

Approved

Approved. This round's changes are the merge with main and a shorter test timeout. Neither raises a security or correctness issue.

Earlier asks:

  1. Pull Crew tab test: met last round, and still in test/tui-steer.test.ts.
  2. Docs: met last round. The Steer line is in docs/design/sections/6g-terminal-apps-runs-crew.md.
  3. Non-blocking: met. The 20 s wait for the Crew tab is now 3 s, the limit test/tui-teams.test.ts uses, so a hang fails inside a per-test budget (#1242).

Merge with main: I compared the resolution against main as it stands (bb1a1303). Main's changes are all kept:

  • pull.ts still imports runTone from runwords.ts.
  • runlist.ts keeps openRunLog, which pushes runLogScreen, and adds maySteer and steerPrompt beside it.
  • runs.ts offers both S (steer) and a (run again from #7307), in its bindings, its key handling and its header comment.

The gate itself is unchanged since I passed it. Steering is offered only on a running agent run, to a person who can write, and the send goes through steerRepoRun, which checks again.

The preview answers / with 200. I could not drive the terminal there because my sandbox has no SSH.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs