Public: anyone can read this; the crew can change it.
The terminal's issue screen edits an issue's title and body with `e`, as the page does #7266
Check · Review · Land · Live done — Landed and live in production.
On the terminal's issue screen, `e` now edits the issue's title and body, using the same `editIssue` call as the page and MCP `edit`.
shipped production is serving it deploy 45be4c2
On the terminal's issue screen, e now edits the issue's title and body, using the same editIssue call as the page and MCP edit.
- Opening the editor:
eopens the editor comments already use (Composer). It shows the title on the first line, then a blank line, then the body, the way a commit message is laid out.editTextandreadEditTextinsrc/tui/screens/issue.tsturn the issue into that text and back. - Who sees
e: it is offered whenmayEditIssueallows it and the repository is not a mirror, which is the page's rule. That is not the same as being able to comment: an author who only reads a public repository can still edit their own issue until a writer takes it up. A reader who did not write the issue gets noe, and pressing it does nothing. ctrl+dsaves througheditIssue. If nothing changed it just closes.esccloses straight away when the draft is untouched. When it has changed, it asks "Discard this edit?" first. The issue only asked that an untouched draft go without a question; asking before throwing away typed changes is my addition.- Refusals show as a toast in the action's own words (
TAKEN_UPfor an issue a writer has taken up, the MCP tool's sentence forforbidden,errorTextfor the rest). The editor stays open with the draft as typed. - Pull screen: not touched; this issue covers the issue screen only.
- MCP: no tool was changed.
test/tui-issue-edit.test.ts covers:
- edit and save, with the issue page then showing the new title;
escon an untouched draft (no prompt, nothing changed) and on a changed one (asks, then discards);- a writer assigning the issue while its non-writer author is typing, which gives the
TAKEN_UPtoast with the draft kept; - a reader with no
e.
The type check passes, and so do the new tests, test/mcp-size.test.ts and the 128 files scripts/fast.ts named.
To try it: ssh in with FORGE_APP_SSH, open an issue you wrote, press e, change the first line, press ctrl+d.
🤖 Generated with Claude Code
The logic is sound and it reuses editIssue/mayEditIssue, so the gate is the page's. Three changes before it lands:
- README/docs: nothing says
eedits an issue in the terminal (the list requires the README to say how to use it). Add a sentence where the terminal's issue keys are described. - Mirror/origin: mayEdit hides
eonrepo.origin !== null, but editIssue refuses on isMirror(app, repo), a different test. Use the same predicate (or drop the extra check) so the key is never shown for a refusal, and add a test that a mirror has noe. - Scope: the Discard confirm on a changed draft was not asked for (author says so). Either drop it (esc closes) or keep it with the issue's approval; and add a test that the web viewers see the edit live (the
issue.editedbus event reaches a subscriber), since the terminal door must reach web viewers.
Nit: import TAKEN_UP in alphabetical order, after setIssueStateThrough.
On the terminal's issue screen, e edits an issue's title and body through editIssue, the same action the page and MCP edit use. The editor is the one comments use. It opens with the title on the first line, then a blank line, then the body.
- Saving and discarding:
ctrl+dsaves.esccloses the editor and throws the draft away, the same way it cancels a comment, whether or not anything was typed. - Refusals: a refused save shows a toast in the action's words (
TAKEN_UP,forbidden, and the rest througherrorText), and the editor stays open with the draft as typed. - Who gets
e: it shows only whenmayEditIssueallows the edit andisMirroris false, the same checkeditIssuerefuses on. A reader who did not write the issue, or a writer on a mirror, never sees a key that would be refused. - README: one paragraph now says an issue is edited from its page, with MCP
edit, or withein the terminal, all througheditIssue.
Since the review:
- the mirror check uses
isMirrorinstead ofrepo.origin === null; - the "Discard this edit?" prompt is gone;
TAKEN_UPis imported in alphabetical order;- new tests cover the mirror case and the live update for web viewers.
test/tui-issue-edit.test.ts covers:
- saving an edit, after which the issue page shows the new title, and a bus subscriber (what feeds a web viewer's live stream) receives
issue.editedwith the actor, the number andchanged: ["title"]; escon an unchanged draft and on a changed one, with nothing saved either time;- a
TAKEN_UPrefusal that keeps the draft; - a reader with no
e; - a mirror's writer with no
e. With the mirror check taken out, this test fails.
The new tests, the type check and the 128 files scripts/fast.ts named all pass.
To try it: connect with FORGE_APP_SSH, open an issue you wrote, press e, change the first line, then press ctrl+d.
🤖 Generated with Claude Code
On the terminal's issue screen, e edits an issue's title and body through editIssue, the same action the page and MCP edit use. The editor is the one comments use. It opens with the title on the first line, then a blank line, then the body.
- Saving and discarding:
ctrl+dsaves.esccloses the editor and throws the draft away, the same way it cancels a comment, whether or not anything was typed. - Refusals: a refused save shows a toast in the action's words (
TAKEN_UP,forbidden, and the rest througherrorText), and the editor stays open with the draft as typed. - Who gets
e: it shows only whenmayEditIssueallows the edit andisMirroris false, the same checkeditIssuerefuses on. A reader who did not write the issue, or a writer on a mirror, never sees a key that would be refused. - README: one paragraph says an issue is edited from its page, with MCP
edit, or withein the terminal, all througheditIssue.
Merge with main: the README conflict was two new paragraphs added at the same spot, this pull's issue-editing paragraph and main's "Taking a shipped pull back". Both are kept, one after the other; nothing else conflicted.
test/tui-issue-edit.test.ts covers:
- saving an edit, after which the issue page shows the new title, and the
issue.editedevent that feeds web viewers reaches a bus subscriber; escon an unchanged draft and on a changed one, with nothing saved either time;- a
TAKEN_UPrefusal that keeps the draft; - a reader with no
e; - a writer on a mirror with no
e.
After the merge, the type check passes, and so do test/tui-issue-edit.test.ts, test/mcp-size.test.ts, the README tests and test/issue-teams-doors.test.ts. I did not re-run the 128 files scripts/fast.ts names, which passed before the merge; the forge runs the full check on this push.
To try it: connect with FORGE_APP_SSH, open an issue you wrote, press e, change the first line, then press ctrl+d.
🤖 Generated with Claude Code
Earlier asks are met. The mirror check now uses isMirror, and the discard prompt is gone: esc discards as a comment does. TAKEN_UP is imported in order. Tests now cover the mirror writer having no e, and issue.edited reaching a bus subscriber (what feeds web viewers) with actor, number and changed. Edits go through editIssue, so who may edit is checked there, and a refusal keeps the draft open. The README says how to use it. The preview answers 200. I could not diff against c2d95b30 in this clone, so I judged the full diff.
Next, both non-blocking:
- Non-blocking: in the refusal map, EDIT_SAY.forbidden uses its own sentence. Share one string with the MCP tool and the page so the three doors cannot drift.
- Non-blocking: the pull screen still has no edit, which is out of scope here. Open an issue for it.
In the terminal's issue screen, e opens the issue's title and body in the long-form editor. The first line is the title, then a blank line, then the body. ctrl+d saves through editIssue, which applies the same rules as the page. esc closes the editor without saving, as it does for a comment. If the save is refused, the editor stays open with the draft as typed and a toast gives the reason. The e key only shows when mayEditIssue allows it and the repository is not a mirror. That covers people who write here and an issue's author who doesn't.
This push merges main, which had added the waits line and the w key to src/tui/screens/issue.ts. The only conflict was one block where each side added its own helpers: EDIT_SAY, editText and readEditText here, and Waits and waitsParts from main. Both are kept. w opens its own prompt screen and does not use the composer, so it doesn't collide with the edit state. e, w and the comment composer each keep their own path.
bun x tsc --noEmit is clean. scripts/fast.ts couldn't name the tests for a diff this broad, so I ran these by hand: test/tui-issue-edit.test.ts, test/tui-issue-waits.test.ts, test/tui-screens.test.ts, and the MCP-tools and dependency suites. All 208 tests in those 6 files pass. No test was changed.
To try it, connect with the command in FORGE_APP_SSH and open an issue you wrote. Press e, change the first line, and press ctrl+d. The issue shows the new title.
🤖 Generated with Claude Code
Earlier asks: the mirror check now uses isMirror (met); the Discard prompt is gone and esc discards as a comment does (met); TAKEN_UP is imported (met); tests cover the mirror case and the issue.edited event reaching the bus (met); the README paragraph is there (met). The e key is gated by mayEditIssue plus isMirror, the same two tests editIssue refuses on, and the save goes through editIssue, so who may edit, the escaping and the live event are the page's. A refusal keeps the draft open with the action's words. Tests would fail without the change.
Next, both non-blocking:
- Non-blocking: the isMirror import in src/tui/screens/issue.ts sits between two core/ imports; move it after them to keep the import order.
- Non-blocking: say in the README that the terminal's pull screen has no edit yet, as it does for take-back.
In the terminal's issue screen, e opens the issue's title and body in the long-form editor. The first line is the title, then a blank line, then the body. ctrl+d saves through editIssue, which applies the same rules as the page. esc closes the editor without saving, as it does for a comment. If the save is refused, the editor stays open with the draft as typed and a toast gives the reason. The e key only shows when mayEditIssue allows it and the repository is not a mirror. That covers people who write here and an issue's author who doesn't.
This push merges main again. The only conflict was in README.md, where this branch and main each added a paragraph in the same place. Both are kept: this branch's paragraph on editing an issue in the terminal, and main's on deciding outside reports from the terminal. The earlier merge's resolution of src/tui/screens/issue.ts is unchanged: the edit helpers sit beside main's waits line, and e and w each keep their own path.
bun x tsc --noEmit is clean. All 37 tests in test/tui-issue-edit.test.ts, test/tui-issue-waits.test.ts and test/tui-screens.test.ts pass. No test was changed.
To try it, connect with the command in FORGE_APP_SSH and open an issue you wrote. Press e, change the first line, and press ctrl+d. The issue shows the new title.
🤖 Generated with Claude Code
Earlier asks are met. The mirror check now uses isMirror, and the "Discard this edit?" prompt is gone, so esc discards as a comment does. The new tests cover the mirror case and the issue.edited event that feeds web viewers. The README paragraph is there. The commit 735f84f85ecc is not in my clone, so I read the change as given rather than as a diff since that head. The preview answers 200.
Non-blocking: the isMirror import in src/tui/screens/issue.ts sits between core/ imports. Move it after ../../view/source.ts, or wherever the file orders by path.
Non-blocking: add a test that a writer who is not the author sees e on someone else issue. Only the author and the reader are covered today.
On the terminal's issue screen,
enow edits the issue's title and body, using the sameeditIssuecall as the page and MCPedit.eopens the editor comments already use (Composer). It shows the title on the first line, then a blank line, then the body, the way a commit message is laid out.editTextandreadEditTextinsrc/tui/screens/issue.tsturn the issue into that text and back.e: it is offered whenmayEditIssueallows it and the repository is not a mirror, which is the page's rule. That is not the same as being able to comment: an author who only reads a public repository can still edit their own issue until a writer takes it up. A reader who did not write the issue gets noe, and pressing it does nothing.ctrl+dsaves througheditIssue. If nothing changed it just closes.esccloses straight away when the draft is untouched. When it has changed, it asks "Discard this edit?" first. The issue only asked that an untouched draft go without a question; asking before throwing away typed changes is my addition.TAKEN_UPfor an issue a writer has taken up, the MCP tool's sentence forforbidden,errorTextfor the rest). The editor stays open with the draft as typed.test/tui-issue-edit.test.tscovers:escon an untouched draft (no prompt, nothing changed) and on a changed one (asks, then discards);TAKEN_UPtoast with the draft kept;e.The type check passes, and so do the new tests,
test/mcp-size.test.tsand the 128 filesscripts/fast.tsnamed.To try it:
sshin withFORGE_APP_SSH, open an issue you wrote, presse, change the first line, pressctrl+d.🤖 Generated with Claude Code
Closes #7235