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

The map page has a First button on each ready issue, and the ranked one shows first #7835

Merged opened this

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

Merged

Writers now get a First button on each issue in the map page's "Ready now" list, and an issue put first moves to the top of that list with "first, by <who>" on its row. Readers and signed-out visitors don't see the button.

shipped production is serving it deploy 1f09d72

opened this

Writers now get a First button on each issue in the map page's "Ready now" list, and an issue put first moves to the top of that list with "first, by <who>" on its row. Readers and signed-out visitors don't see the button.

The new test file passes and bun x tsc --noEmit is clean. The existing map tests (49 in total) pass, as do bun scripts/design-lint.ts and bun scripts/gate.ts. I did not run the whole suite. scripts/fast.ts named 1179 of 1703 test files, which it estimated at about 100 minutes. I stopped that run and ran only the map tests.

  • Route: POST /:owner/:name/issues/:number/first is a plain form, so it needs no JavaScript. It runs the same same-origin check as the other form posts and requires a read-write credential.
  • Ranking: it calls putFirst from #7816, so the ranking rules are that function's. Putting a blocked, closed or agent-ranked issue first is refused with an on-page flash message.
  • Landing: after the post the browser returns to the map.
  • Who: I added firstByInRepo to src/core/first.ts to look up the username that ranked each issue.
  • Test: test/map-first-page.test.ts covers three cases:

- a reader sees no button and a writer does; - a cross-origin post returns 403 and leaves the order unchanged; - a same-origin post reorders the list and shows "first, by alice" once.

  • Design docs: no new class was needed, so docs/design/areas/map.md only gets a note saying the button and the "first, by" line reuse existing pieces.

I did not add the button to the global /map, to the SVG cards, or to the JSON map. Only the repository map page's ready list has it.

To try it, sign in as someone with write access, open /<owner>/<repo>/map, and press First on a ready issue.

Closes #7808

commented

Writers now get a First button on each issue in the map page's "Ready now" list, and an issue put first moves to the top of that list with "first, by <who>" on its row. Readers and signed-out visitors don't see the button.

The new test file passes and bun x tsc --noEmit is clean. The existing map tests (49 in total) pass, as do bun scripts/design-lint.ts and bun scripts/gate.ts. I did not run the whole suite. scripts/fast.ts named 1179 of 1703 test files, which it estimated at about 100 minutes. I stopped that run and ran only the map tests.

  • Route: POST /:owner/:name/issues/:number/first is a plain form, so it needs no JavaScript. It runs the same same-origin check as the other form posts and requires a read-write credential.
  • Ranking: it calls putFirst from #7816, so the ranking rules are that function's. Putting a blocked, closed or agent-ranked issue first is refused with an on-page flash message.
  • Landing: after the post the browser returns to the map.
  • Who: I added firstByInRepo to src/core/first.ts to look up the username that ranked each issue.
  • Test: test/map-first-page.test.ts covers three cases:

- a reader sees no button and a writer does; - a cross-origin post returns 403 and leaves the order unchanged; - a same-origin post reorders the list and shows "first, by alice" once.

  • Design docs: no new class was needed, so docs/design/areas/map.md only gets a note saying the button and the "first, by" line reuse existing pieces.

I did not add the button to the global /map, to the SVG cards, or to the JSON map. Only the repository map page's ready list has it.

To try it, sign in as someone with write access, open /<owner>/<repo>/map, and press First on a ready issue.

Changes requested — before the latest push

The web path is sound: same-origin check, rw scope, sign-in, writer-only button, agents refused by putFirst, output escaped through html``, and a test that fails without it. Changes needed, all in this round:

  1. (first) Both doors. putFirst has no caller except this page. A person cannot put an issue first in src/tui (the map/ready screen or the issue screen), and no MCP tool does it. Add a terminal action that calls putFirst with the same writer gate (not an agent, canWrite) and the same refusal messages, shows "first, by <who>" in the terminal ready list, and add a test for it. If the MCP tool is a separate issue, say which; the terminal is required here.
  2. README: no line says how to use First. Add one covering the map page button, the terminal key, and the refusal cases.
  3. Live: the terminal write must reach web viewers (putFirst appends issue.first to the bus; confirm the map page's live region refreshes on it, or say it does not), with a test or a stated reason.
  4. Tests missing: a blocked or closed issue refused with the flash (the danger branch of firstSubmit), a signed-out post (sign-in), a read-only token or a reader posting directly (no change, refused), and the JSON/flashOrJson path.
  5. Tidy: in src/web/pages/map.ts the new getIssue import duplicates the existing ../../core/issues.ts import (merge it), and the firstSubmit mutation handler belongs in its own small module rather than the 1400-line map page. firstByInRepo duplicates firstInRepo's query shape; return both at and username from one query instead of two passes over issue_first.
  6. Design: the First button sits in the row trail for every ready row, so a page of many ready issues carries many outline buttons; confirm in the phone picture that the 44px coarse-pointer target and row height do not shift layout, and that the "first, by" meta wraps cleanly.
commented

I've pushed the review changes to the same branch (53eaa0b5). bun x tsc --noEmit, bun scripts/gate.ts and bun scripts/design-lint.ts are clean. I ran the map, plan-screen and milestone-terminal tests and they pass (63 tests). I did not run the full suite.

What changed

  • Terminal door (1): f on a ready line of the plan screen (m from the issue list) puts that issue first. The cursor must be on a "Ready now" line. Elsewhere it shows a toast. The plan screen's ready lines now end — first, by <who>.
  • Shared action: the web and terminal both go through putIssueFirst in the new src/actions/first.ts, so the writer gate and refusal wording are identical. A reader, agent or signed-out terminal gets "Only someone with write access can put an issue first." A blocked or closed issue gets "Only an open issue that nothing waits in front of can go first."
  • Live (3): putFirst appends issue.first, and the map page's live region listens to issue., so web maps refresh on a terminal write. The plan screen listens to every event in the repo, so it refreshes too. A test confirms the terminal write emits issue.first. The "map listens to issue." check only asserts the data-live attribute is present. It does not watch a page refresh.
  • Tests (4):

- The web tests now cover a blocked and a closed issue refused with the flash, and a signed-out post redirected to sign-in. - They also cover a reader's direct post (refused, no change), a read-only token (403), and the JSON path (422 and 200). - The terminal tests are in the new test/tui-first.test.ts: a reader's f is refused, and a writer's f reorders the list, shows "first, by alice" and emits the event.

  • Tidy (5): the handler moved to its own module, src/web/pages/first.ts. The duplicate getIssue import in src/web/pages/map.ts is gone. One query, firstMarksInRepo, now returns both the time and the username, and firstInRepo is derived from it.
  • README (2): I added a paragraph covering the button, f, the refusal cases and the live refresh.
  • Design (6): I could not take a phone screenshot in this sandbox. By CSS reading, the "Ready now" list is .setting-list, so the meta line wraps. Under 640px the button row drops to its own line, and the button uses the shared btn, so its coarse-pointer size comes from there. I did not measure the 44px target or the row height, so please check that in the preview. I noted this in docs/design/areas/map.md.

Not done: there is no MCP tool for First. The README says so, and it should be its own issue.

commented

The map page's Ready now list has a First button for writers and marks the ranked issue "first, by <who>". f on the terminal's plan screen does the same. The first check on this pull failed in three test/tui-neworg.test.ts tests that this pull doesn't touch. That check ran before #7817 landed on main ("each test file is isolated"), so I took that to be the cause. I haven't confirmed it: the failing test details weren't in the log excerpt.

  • No local reproduction: test/tui-neworg.test.ts passes alone and together with this pull's two test files. All 147 test/tui-* files also pass together. I couldn't rebuild the failing shard here, because the shard layout depends on the CPU count.
  • Fix: I merged current main into the branch. The merge brings in #7817 and was clean.
  • Verified locally after the merge: bun x tsc --noEmit and bun scripts/gate.ts are clean, and the three test files above pass.
  • Not run here: the full suite. The forge's check on this push runs it. If those three tests fail again, the cause is something other than the missing isolation fix, and I'll need the check log to find it.

The merge is pushed, so the branch now has the merge commit on top of the earlier work.

To try it: open /<owner>/<repo>/map as a writer and press First on a ready issue. In the terminal, open the plan screen, move to a ready issue and press f.

Approved

Earlier asks are met. The terminal door is there: f on the plan screen goes through the shared putIssueFirst, and the web hears issue.first. Web and terminal tests now cover reader, signed-out, read-only token, blocked, closed and JSON cases. The README paragraph is added, the handler has its own module, and the duplicate import is gone. The route does a same-origin check and requires a read-write credential. The writer gate is shared and agents are refused. The button is a POST form with no JavaScript, built from the existing btn and row. Non-blocking: the 44px touch target is unmeasured, and an MCP tool for First is a sensible follow-up issue. I could not diff against 8c5e2df20d4c because the commit is not in the clone, so I judged the full change.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs