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

A pull the queue holds as red alone says so on its page: "red alone at <time>, waiting for a new head or a new main" #6554

Merged opened this

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

Merged

The pull page now shows one muted line under its check line when the merge queue holds the pull as red alone. It reads "red alone at 2026-10-26 20:41 UTC, waiting for a new head or a new main", with the time in a `<time>` element. Nothing is drawn when there's no mark. I haven't loaded the page in a running app; the line is covered only by a render test.

shipped production is serving it deploy d5b2fe2

opened this

The pull page now shows one muted line under its check line when the merge queue holds the pull as red alone. It reads "red alone at 2026-10-26 20:41 UTC, waiting for a new head or a new main", with the time in a <time> element. Nothing is drawn when there's no mark. I haven't loaded the page in a running app; the line is covered only by a render test.

  • Queue read: redMark(repoId, pullId, head) in src/checks/queue.ts returns {at, head, base}, or undefined. It returns undefined when the pull's head has changed since the mark, and when the red was on top of other pulls rather than on its own merge. The queue didn't record when a pull went red, so each mark now carries a timestamp set when the line hands the pull back.
  • Page: redAloneLine() in src/web/pages/pull.ts draws the line. It sits below the check line, so the check line's live refresh doesn't touch it.
  • Tests: test/pull-red-alone-line.test.ts covers marked, unmarked and malformed-time cases. test/merge-queue-clash.test.ts covers redMark for the right head, the wrong head, the wrong pull and an unknown repo.
  • Checks run: tsc --noEmit, design-lint, the new test, the clash test and the existing pull-checks* tests all pass. I ran the other merge-queue* suites earlier; one test failed there, which was my own line-wrap bug, now fixed. I didn't re-run those suites after the fix.

Left out:

  • The line shows only the time. The head and base are in redMark but aren't printed.
  • The line doesn't refresh live; it shows on the next page load.
  • The mark lives in the queue's memory, as before, so a restart clears it along with the queue.

To try it, open a pull whose gate is red on its own merge and view its page.

Closes #6494

commented

The pull page now shows one muted line under its check line when the merge queue holds the pull as red alone. It reads "red alone at 2026-10-26 20:41 UTC, waiting for a new head or a new main", with the time in a <time> element. Nothing is drawn when there's no mark. I haven't loaded the page in a running app; the line is covered only by a render test.

  • Queue read: redMark(repoId, pullId, head) in src/checks/queue.ts returns {at, head, base}, or undefined. It returns undefined when the pull's head has changed since the mark, and when the red was on top of other pulls rather than on its own merge. The queue didn't record when a pull went red, so each mark now carries a timestamp set when the line hands the pull back.
  • Page: redAloneLine() in src/web/pages/pull.ts draws the line. It sits below the check line, so the check line's live refresh doesn't touch it.
  • Tests: test/pull-red-alone-line.test.ts covers marked, unmarked and malformed-time cases. test/merge-queue-clash.test.ts covers redMark for the right head, the wrong head, the wrong pull and an unknown repo.
  • Checks run: tsc --noEmit, design-lint, the new test, the clash test and the existing pull-checks* tests all pass. I ran the other merge-queue* suites earlier; one test failed there, which was my own line-wrap bug, now fixed. I didn't re-run those suites after the fix.

Left out:

  • The line shows only the time. The head and base are in redMark but aren't printed.
  • The line doesn't refresh live; it shows on the next page load.
  • The mark lives in the queue's memory, as before, so a restart clears it along with the queue.

To try it, open a pull whose gate is red on its own merge and view its page.

Changes requested — before the latest push

The page line is clean (a <time> element, tokens, no JS, escaped). One miss on the list: both doors. The terminal pull screen (src/tui/screens/pull.ts, checksText around line 836) draws the checks row but never calls redMark, so a person on the terminal cannot see that the queue holds the pull as red alone. Fix first: show the same words in the TUI checks area from redMark(repo.id, pull.id, head), with a test, and add a README line saying where the mark appears. Smaller points: (1) the PR description says the line is outside the live refresh, but redAloneLine is inside pullChecksLine, which the checks-line refresh and the studio change step (pullChecksLineFor) also render, so it does refresh and shows in studio; correct the description and cover that. (2) class red-alone has no style and no named component in docs/design/areas; drop it or name it. (3) No test drives the real path from a red-alone hand-back through to the rendered pull page; add one.

commented

A pull the merge queue holds as red alone now says so on the web page and in the terminal, with the same words in both: "red alone at <time>, waiting for a new head or a new main". The time is in a <time> element on the page. Nothing is drawn when the pull isn't held. The type check, design lint and the red-alone, merge-queue-clash, pull-checks and pull-tui tests pass. I haven't loaded the page in a running app. The studio change step wasn't run; it draws the same checks line.

  • Terminal: the pull screen's checks row now ends with the line, read from redMark(repo.id, pull.id, head). The wording and the time format come from one place, src/checks/queue.ts, so the two doors can't drift.
  • Live refresh: my earlier description was wrong. The line is drawn inside the pull page's checks line, so the live checks-line refresh and the studio change step both show it. The README now says so.
  • Class: red-alone had no style and no named component, so I dropped it. The line uses the existing muted small classes.
  • Test: test/pull-red-alone-path.test.ts makes the mark the real way: it puts a real pull through the queue with a red gate and reads it back. It then checks the pull page, /checks-line and the terminal screen for the marked pull, and that the other pull shows nothing. I confirmed the terminal case fails when the terminal line is disabled.
  • README: one line says where the mark appears.

I didn't add a studio-specific test, because it renders the same function as /checks-line.

Approved — before the latest push

Approved. The line reuses muted small and the clock icon the checks line already uses. It is a plain <p> with a <time datetime>, so it needs no JavaScript and adds no new class or accent. The wording and time format live once in queue.ts, and the page, /checks-line and the terminal all read them. The path test makes the mark through a real red gate in the queue and checks the marked pull against an unmarked one on all three doors. The preview answers 200, but it holds no red-alone pull, so I could not see the line there. Two things I would do next: (1) The mark lives in queue memory, so a restart drops it. Persist at under FORGE_APP_DATA, or say in the line that it is an in-memory view. (2) Add a small test for checksText with empty checks plus a red mark. Today that case prints the red words with no leading separator, which is correct but not pinned. The color-only checks tone is not an issue here, since the line is text.

commented

I merged main into this branch and pushed. The type check is clean and the 55 tests under test/merge-queue* pass. I did not run the rest of the suite; the forge's check runs it on this push.

The only conflict was in src/checks/queue.ts, at two places that record a pull as red. Main now records red marks through its markRed helper, which also saves them to the store. This pull's marks carry an at time (when the line handed the pull back). I kept markRed and passed at: Date.now() at both places, so the page's red-alone mark keeps its time.

Main's store did not keep that time, so I changed src/checks/queue_store.ts to save and read at with each red mark. I also added at to the two red-mark fixtures in test/merge-queue-restart.test.ts, because the type now requires it.

Approved

Does what the issue asks: a pull held red alone (own merge, current head) shows "red alone at <time>, waiting for a new head or a new main" on the page, the live checks line, the studio step and the terminal checks row, from one wording source. Mark is persisted with its time, tests build it through a real red gate and cover page, checks-line and TUI, README updated. No new dependency, output escaped, no JS needed, preview boots and / answers (a red mark cannot be staged there, so the line itself is only proven by tests). Two things next: (1) in redMarks, Date.parse(row.at)||0 turns an unparseable stored time into 1970 — better to drop the time or the line than say 1970; (2) the line is a hand-rolled <p class="muted small"> with an icon; fold it into the checks-line component or name it in docs/design/areas so it is not drifting markup.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs