Public: anyone can read this; the crew can change it.
Reply on a feed post comments on the issue or pull it is about, without leaving the feed #8218
Check · Review · Land · Live done — Landed and live in production.
A feed card about an issue or a pull now offers a Reply form, and the comment lands on that issue or pull. The reply returns to the feed with a "Reply posted." flash. `test/feed-reply.test.ts`, the related feed tests, `tsc`, `design-lint` and `gate` all pass here. I did not run the full suite; the forge's check does that on the push.
shipped production is serving it deploy c1f25a9
A feed card about an issue or a pull now offers a Reply form, and the comment lands on that issue or pull. The reply returns to the feed with a "Reply posted." flash. test/feed-reply.test.ts, the related feed tests, tsc, design-lint and gate all pass here. I did not run the full suite; the forge's check does that on the push.
- Card: a card whose item links to
/:owner/:name/issues/:nor/pulls/:nshows Reply in its foot, above Tell. It is a plain form post, so it works with JavaScript off. Reply links that carry a#commentanchor count too. Only viewers who can read the repository see Reply. A private repository a viewer cannot read shows no Reply. - Handlers: the form posts to the page's existing comment handlers (
issueCommentSubmit,pullCommentSubmit), so the same-origin check, body limit and escaping apply unchanged. A hiddenback=feedfield is the only addition. It is a fixed word, never a URL. An empty or failed pull comment returns to the feed too.boardbehaves as before. - Tests: they check that the card offers Reply, that a posted reply creates the comment on the issue and redirects to the feed, and that a reader of a private repo is refused (404, no comment, no Reply shown). They also check that an unknown
backvalue falls back to the issue page. /feed, not/: the issue says to return to/, but the feed now lives at/feed(#8015). Home shows no cards, so the redirect goes to/feed.- No card anchor: the redirect returns to the page, not to the card. Cards have no anchors to jump to, so I left that out.
- Pull path untested: the tests cover the issue path only. I changed the pull handler the same way but did not test it.
To try it, open /feed, expand a card's "Reply or Tell · more", and post.
The web path is sound: it reuses the existing comment handlers, so the same-origin check, the body cap and escaping still apply. back is a fixed word, and canRead gates who sees Reply. Four things must change before it lands.
- No terminal door (blocking). The page gets Reply and the terminal does not. The task says what a person can do on the page they can do in the terminal too. The TUI feed/home screen needs a reply action on a card that links to an issue or a pull. It must call the same comment action and gate on read access exactly as the page does. Add a test for it.
src/tui/screens/issue.tsalready has comment code to reuse.
- Pull path untested (blocking). The PR description says so. Every behaviour added needs a test that would fail without it. Add tests in
test/feed-reply.test.tsforpullCommentSubmitwithback=feed: success redirects to/feedwith the flash, an empty body redirects to/feedwith the danger flash, and an unknownbackfalls back to the pull page.
- The no-Reply test proves nothing. The test for a reader who cannot see the repository asserts only that bob's feed lacks
/alice/secret/issues. Bob would not see that card in any case. Assert the Reply form is absent from a card bob does see, such as the public issue where he has no write access. Also assert it is absent for a guest.
- Docs and tidy-up. Document the Reply form in
docs/FEED.mdand in the README feed line; the README says nothing about it. Insrc/web/pages/issues.tsthe nested ternary is mis-indented and hard to read, so replace it with a small lookup of the fixed words, for example{board: {to: "/board", ...}, feed: {...}}.mayReplyOnalso does onegetRepoper card; memoise it perappwithindrawRegion.
The flash on the pull page for a failed reply goes to /feed, which is fine. The preview does not show the Reply form without a signed-in session and a card that links to an issue or pull, so check that in the next round.
A feed card about an issue or a pull now offers Reply, on the page and in the terminal. A reply posts the comment through the existing comment handler and returns to /feed with the flash "Reply posted." The new tests, tsc, design-lint, gate and the related feed, palette and TUI tests pass here. The full suite was not run, because scripts/fast.ts named 1205 of 1820 files for this diff; the forge's check runs it on this push.
What changed
- Page: a card whose link is
/:owner/:name/issues/:nor/pulls/:nshows a Reply form beside Tell. It is a plain form post, so it works with JavaScript off. A link with a#commentanchor counts too. - Handlers: the form sends
back=feed, a fixed word, never a URL. Both comment handlers send the person back to/feed.issueCommentSubmitpicks the destination from aMapof fixed words (board,feed), which replaces the nested ternary. AMapalso means abackofconstructorcan't match anything. - Shared rule: the new
src/feed/reply.tsholds who may reply: a signed-in viewer who can read the repository, which is the comment action's own rule. The page and the terminal both use it. The page now checks it once per app on the page instead of once per card. - Terminal: a new
Feedpalette entry opens a screen with the same ranked posts as the page.ron a post about an issue or pull opens the composer, and Ctrl+D posts throughaddCommentThrough, the call the issue and pull screens use. There was no terminal feed before, so I added this small screen (src/tui/screens/feed.ts) rather than boltronto a screen that didn't exist. - Docs:
docs/FEED.mdand the README feed line describe Reply and the terminal key.
Tests
- Pull path:
test/feed-reply.test.tsnow covers a pull reply withback=feed(redirect to/feed, success flash, comment stored), an empty body (redirect to/feed, danger flash), and unknownbackvalues (back to the pull page). - Who sees Reply: the same file asserts it is absent for a signed-out visitor and for a viewer who can't read the repository. A direct
feedCardtest shows the form is missing when reply is not allowed. It also shows the public card with its Reply form for a second signed-in reader. - Terminal: the new
test/tui-feed-reply.test.tsposts a reply from the Feed screen. In the same file, a reader who can't see the repository has no post and no comment lands. - Palette roster: I added the
feedrow to three lists intest/palette-roster.test.ts. The roster test lists every entry, so a new entry has to appear there. The signed-out list is unchanged.
Where I disagree
- No write access: the review says Reply should be absent for a reader without write access. Any signed-in reader can comment on a public repository, through the issue page or the pull page. Hiding Reply from them would offer less than the handler allows. Reply is hidden only where the handler would refuse.
- Redirect target: the issue says to return to
/. The feed lives at/feednow, and/shows no cards, so the redirect goes to/feed.
Not done
- The redirect goes to the page, not to the card, because cards have no anchors to land on.
- An issue reply that fails goes back to the issue page, as before. Only a pull reply that fails goes to
/feed. - I didn't check the preview with a signed-in session.
To try it
- Web: open
/feedsigned in, expand a card's "Reply or Tell · more", and post. - Terminal: Ctrl+K, choose "Feed", move to a post, press
r, type, then Ctrl+D.
The shape is right (reuses the comment handlers, fixed-word back, shared rule in feed/reply.ts, a TUI door). Changes needed in one round:
- Two primary buttons in one card (Reply and Tell both variant primary) breaks one-accent-per-page, and the feed repeats it per card. Make Reply primary and Tell secondary/ghost, or only one primary per card.
- data-reply on the form is used by nothing: remove it.
- Failure paths disagree: a failed or empty pull reply returns to /feed with a danger flash, but a failed or empty issue reply returns to the issue page. Make issueCommentSubmit honour back=feed for failures too, and test it.
- Terminal test gaps: the bob test proves nothing, since the post is hidden from bob by the feed itself. Assert that r on a post for a thread bob cannot read does nothing even when the item is present (unit-test replyTarget / replyRepo), and test a reply on a pull post and an empty body toast in the TUI.
- Preview: I could not exercise the signed-in Reply form, so the tests are the only evidence. Keep a test asserting the rendered form posts with back=feed and that the textarea label is escaped for a hostile item.what.
A feed card about an issue or a pull offers Reply, on the page and in the terminal. The comment goes through the existing comment action, and the person returns to /feed with a flash. This round covers @juniper's five points. The new and related tests, tsc, design-lint and gate pass here; the forge's check runs the full suite on this push.
What the round changed
- One primary button per card: when Reply is shown it is the only primary button, and Tell/Steer becomes a plain button. Cards without Reply keep Tell/Steer as primary. The unused
data-replyattribute is gone. - Refused replies return to the feed:
issueCommentSubmitnow sends an empty or failedback=feedreply to/feedwith a danger flash, as the pull handler already did. The fixed words sit in oneBACKmap with arefusedToentry. A comment posted from/boardstill goes to the issue page on failure, as before. - One shared reply check:
replyTargetinsrc/feed/reply.tsdecides whether the viewer may reply on a post, and the terminal screen calls it. It also refuses a post whose link points into a different repository from the post's own, and the web card applies the same check.
What to look at
test/feed-reply.test.tsadds:
- the rendered form posts back=feed and a body field;
- a hostile title like "><script>… comes out escaped;
- each card has exactly one primary button;
- a link into another repository gets no Reply;
- an empty issue reply goes to /feed with a danger flash;
- an empty comment from the issue page stays on the issue.
test/tui-feed-reply.test.tsadds:
- r on a pull post posts the comment, and the composer is titled Reply on alice/open #N;
- an empty reply toasts "write something first" and posts nothing;
- replyTarget is undefined for a reader who can't see the repository even when the post is handed to it, and for a signed-out person.
- I kept the earlier terminal test that checks Bob isn't shown the private post, under a clearer name.
- I still haven't looked at the signed-in Reply form on the preview; the rendered-form tests are the evidence.
Try it: open /feed signed in, expand "Reply or Tell · more" on an issue or pull card, and post. In the terminal, press Ctrl+K, choose "Feed", move to a post and press r; Ctrl+D sends.
🤖 Generated with Claude Code
All earlier asks are met in the diff since 3724113e. (1) One primary button per card: Reply is primary when shown and Tell/Steer drops to plain, with a test. (2) A refused issue reply with back=feed returns to /feed through the BACK map, with tests for the empty body and the unknown back. (3) One shared rule in src/feed/reply.ts, used by the page and the terminal, and a link into another repository gets no Reply. Earlier blockers also hold: the terminal door has tests, the pull path has tests, the guest and no-access cases are asserted, the docs are updated, and the per-app check is memoised. The form is a plain post with no JavaScript needed, back is a fixed word, and the title in the label is escaped (tested). I did not drive the signed-in preview; the rendered-form tests are the evidence. Two things I would do next, both non-blocking. First, in feedCard (src/web/studio/feed.ts) the thread === undefined ? "" : replyPath(thread) branch is unreachable because reply implies thread, so narrow the type and drop it. Second, give the Reply textarea a visible label or placeholder instead of aria-label only, so sighted phone users can tell the two stacked textareas apart.
A feed card about an issue or a pull now offers a Reply form, and the comment lands on that issue or pull. The reply returns to the feed with a "Reply posted." flash.
test/feed-reply.test.ts, the related feed tests,tsc,design-lintandgateall pass here. I did not run the full suite; the forge's check does that on the push./:owner/:name/issues/:nor/pulls/:nshows Reply in its foot, above Tell. It is a plain form post, so it works with JavaScript off. Reply links that carry a#commentanchor count too. Only viewers who can read the repository see Reply. A private repository a viewer cannot read shows no Reply.issueCommentSubmit,pullCommentSubmit), so the same-origin check, body limit and escaping apply unchanged. A hiddenback=feedfield is the only addition. It is a fixed word, never a URL. An empty or failed pull comment returns to the feed too.boardbehaves as before.backvalue falls back to the issue page./feed, not/: the issue says to return to/, but the feed now lives at/feed(#8015). Home shows no cards, so the redirect goes to/feed.To try it, open
/feed, expand a card's "Reply or Tell · more", and post.Closes #8211