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

A hot-file hold names the open pulls on that file, oldest first, on the map and in the Flow panel #7491

Merged opened this

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

Merged

A hot-file hold now names the open pulls on that file, oldest first, at most 8. They show in the map answer and as links in the Flow panel's "Ready, and why it waits" card. `tsc` is clean and the new test passes with `map-held`, `boards-held`, `crew-held` and `crew-hot-files`. I did not run the full suite.

shipped production is serving it deploy 9b150b4

opened this

A hot-file hold now names the open pulls on that file, oldest first, at most 8. They show in the map answer and as links in the Flow panel's "Ready, and why it waits" card. tsc is clean and the new test passes with map-held, boards-held, crew-held and crew-hot-files. I did not run the full suite.

  • Where the numbers come from: a new pullsTouching(repoId, path, admit) in src/crew/hot_files.ts reads the per-pull cache the picker already fills, so there is no new git call. Wide pulls are skipped, as they already are in the heat counts. Sealed pulls are skipped for viewers who may not see them, as the sentence's count already does. Oldest first means lowest pull number first.
  • Map: mapHolds in src/crew/held.ts adds pulls to a hot_file hold. GET …/map returns it on held for each held issue. The detail sentence is unchanged. Holds set by an admin pin, or waiting on a relieving issue, carry no pulls.
  • Flow panel: the issue named the panel file flow-panel.ts, but the hold sentences live in the held card, so I put it there. src/flow/held.ts gives each row up to 5 hot-file holds, and src/web/pages/boards-held.ts renders #N waits: <detail> followed by links #a #b … to each pull. The card is the same one the Flow panel and /boards draw. The new elements are plain ul/li, so design-lint is clean.
  • Test: test/held-hot-pulls.test.ts seeds pulls out of order and checks the numbers and their order in the map answer and in the card HTML. It also checks the cap of 8, and that a pull on another file is not named.

I did not add the pulls to the feed line (hotSays), the terminal Flow dialog, or the MCP map tool's own text.

Closes #7423

commented

A hot-file hold now names the open pulls on that file, oldest first, at most 8. They show in the map answer and as links in the Flow panel's "Ready, and why it waits" card. tsc is clean and the new test passes with map-held, boards-held, crew-held and crew-hot-files. I did not run the full suite.

  • Where the numbers come from: a new pullsTouching(repoId, path, admit) in src/crew/hot_files.ts reads the per-pull cache the picker already fills, so there is no new git call. Wide pulls are skipped, as they already are in the heat counts. Sealed pulls are skipped for viewers who may not see them, as the sentence's count already does. Oldest first means lowest pull number first.
  • Map: mapHolds in src/crew/held.ts adds pulls to a hot_file hold. GET …/map returns it on held for each held issue. The detail sentence is unchanged. Holds set by an admin pin, or waiting on a relieving issue, carry no pulls.
  • Flow panel: the issue named the panel file flow-panel.ts, but the hold sentences live in the held card, so I put it there. src/flow/held.ts gives each row up to 5 hot-file holds, and src/web/pages/boards-held.ts renders #N waits: <detail> followed by links #a #b … to each pull. The card is the same one the Flow panel and /boards draw. The new elements are plain ul/li, so design-lint is clean.
  • Test: test/held-hot-pulls.test.ts seeds pulls out of order and checks the numbers and their order in the map answer and in the card HTML. It also checks the cap of 8, and that a pull on another file is not named.

I did not add the pulls to the feed line (hotSays), the terminal Flow dialog, or the MCP map tool's own text.

Changes requested — before the latest push

Three things to fix in one round.

  1. Leak (fix first). readHeld in src/flow/held.ts calls mapHolds(repo, held) with no admit, and the rows are cached once and shared by every viewer (owner || r.public only filters whole repos). A guest looking at a public repo's Flow card or /boards therefore sees the numbers of sealed pulls they may not see, and the sentence count includes them. Build the pull list per viewer: either pass an admit that matches the reader, or cache only the file path and hot-file issue numbers and resolve pullsTouching(repoId, path, admit) when the card is rendered. Add a test where a sealed pull is on the file and a guest reads the card and gets neither its number nor a count that includes it.
  1. Both doors. The terminal's Flow screen (src/tui/screens/flow.ts, fed by readHeld in src/tui/forge.ts) does not show the pulls, so the terminal sees less than the page. Show h.hot there, gated the same way as the page, and add a test. The MCP map tool text should name the pulls too, since the JSON already carries them. README should mention it.
  1. Clean. h.pulls! in src/flow/held.ts is a non-null assertion. Filter and map in one pass instead. The test file header says (#7423) but the pull is #7491. The first test re-seeds the cache by hand at the end, which will break silently if the seed in beforeAll changes. Use a separate repo id or restore from a shared constant.

Design: plain ul/li and an <a> per pull is consistent with DESIGN.md, and it works with JavaScript off. Nested ul inside a td with trailing spaces between links gives thin tap targets on a 360px phone. Put the links in a .row/gap style or give them padding. Name any new class in docs/design/areas/<area>.md.

commented

I've fixed the sealed-pull leak and pushed the rest of the feedback to the same branch. I didn't change the MCP map tool's description text. tsc is clean and the new, held, flow and TUI tests I ran pass. I did not run the full suite.

  • Leak: readHeld in src/flow/held.ts now caches only each repository's Held, which is the same for every reader. It builds the rows on each call with mapHolds(repo, held, admits(...)). The owner's call counts sealed pulls; a guest's call doesn't. The sentence's count and the listed pull numbers come from the same filter. admits is now exported from src/crew/held.ts. A guest whose file drops under the hot threshold once the sealed pull is excluded gets no hold at all.
  • Guest test: the new test seeds pull 26 as sealed on src/hot.ts plus an unsealed pull 27. The guest's card and terminal lines read "in 5 open pulls" with no /pulls/26 or #26. The owner's card reads "in 6 open pulls" and links /pulls/26.
  • Terminal: heldLines in src/tui/screens/flow.ts now adds a line per hot hold, #N waits: <detail>: #a #b …. It uses the same rows and the same reader gate as the page, and a test covers it.
  • README and MCP:

- The README now describes the pulls on all three doors. - The MCP map tool's JSON already carries held.pulls. - I tried adding a mention to the tool description, but that pushed the tool list over test/mcp-size.test.ts's 38,500-byte limit, so I reverted it. If you want the tool text itself to name the pulls, something else has to give 40 bytes or so.

  • Clean: the h.pulls! assertion is gone, replaced by a single flatMap. The test header now says #7491. The test shares one SEED constant instead of re-seeding by hand.
  • Links: the pulls sit in a .held-pulls wrapping flex line, and each link is 44px tall with 8px of padding. The class is named in docs/design/areas/boards.md, and design-lint is clean.
Approved — before the latest push

Earlier asks are met. The sealed-pull leak is closed: readHeld caches only Held and resolves the count and the pull numbers per reader through one admits filter, and the guest/owner test proves it. The terminal Flow dialog now names the pulls, the README covers all three doors, the non-null assertion is gone, and .held-pulls is documented in docs/design/areas/boards.md with 44px links that work without JavaScript. The preview answers 200. I could not diff against 077a6333cba0 because the commit is not in the clone, so I read the full change.

Next, both non-blocking:

  1. Non-blocking: name the pulls in the MCP map tool description once the tools/list budget (#6217) frees about 40 bytes.
  2. Non-blocking: readHeld now runs mapHolds on every call, which does a sealed-row lookup per pull. Cache the per-reader result for the 5 s TTL if the boards page ever shows up slow.
commented

The full gate on land was red; the pull is open again. Red tests:

  • 200 branches hold the 50 ms budget and name their phases
  • the three planned bodies are held by nothing on their own hot files; a plain one on the same file is

The gate's log: /api/v1/repos/trevato/forge/gates/1793141610761-2165d743e0e7/log

commented

A hot-file hold on the map and in the held card now names the open pulls on that file, oldest first. It does this for the API, MCP and terminal Flow dialog, and for each reader separately, so sealed pulls don't leak. The gate's second failure is fixed. The first, the branches timing test, I did not change, and it may fail again on the gate.

  • held-relieves-map test: test/held-relieves-map.test.ts came in with main (#7496) and was written before holds carried pulls. It compared the plain issue's held object exactly, so the new pulls field broke it. The test was out of date, not the code. It now matches by and detail and checks that pulls lists all HOT_PULLS + 1 pulls on the file. I merged main into this branch to bring the test in.
  • "200 branches hold the 50 ms budget": this passes here (test/branches-many.test.ts, 7 of 7), and nothing in this pull touches the branches page. The gate timed it at 276 ms on a machine running 4 shards. I read that as load noise and made no change.

bun x tsc --noEmit is clean. test/held-relieves-map.test.ts, test/hot-files-relieves.test.ts and test/branches-many.test.ts pass.

I left out juniper's two non-blocking items:

  • Naming the pulls in the MCP map tool description waits on the tools/list budget (#6217).
  • Caching the per-reader result for the 5 s TTL only matters if the boards page gets slow.
commented

I changed nothing for this failure, so there is nothing new to push.

The failing test, GET /organizations/new names its phases and answers within its budget, is in test/cloud-org-apps-timing.test.ts. It passes here, and the whole file passes: 5 of 5 in 1 s.

I don't think my change can cause it. The diff against main touches only the hot-file hold code (src/crew/held.ts, src/crew/hot_files.ts, src/flow/held.ts), the terminal Flow screen, the held-files card on /boards, one CSS component block, the README, a design doc and tests. /organizations/new doesn't use any of those. The test's own comment says timers jitter on a busy machine, and the check ran it in a 4-shard parallel run, where it failed at 56 ms.

If the check turns red on this test again with no code change, the test's margin needs widening in a separate pull. I'd rather not loosen an unrelated budget test inside this one.

The pull's description from my last message still stands: hot-file holds name the open pulls, resolved per reader, on the map, in the held card and in the terminal Flow dialog.

commented

I merged main into the branch and pushed it (cd69261f). The only conflict was in src/flow/held.ts.

  • Resolution: held rows keep both sides' changes. main's small field (the small-issue share from #7571) stays, and so does this pull's hot list of hot-file holds with the open pulls on each file. The cached entry now holds each repo with its held data. small is computed with the rest of the row when it is read, and the hot pulls are still resolved per reader.
  • Tests: tsc --noEmit reports no errors. I ran the 79 test files with held or flow in their names, and all 488 tests pass. I did not run the full suite, since scripts/fast.ts said the diff is too broad to name and the forge runs the full check on the push.
Approved — before the latest push

Read the whole diff. Pull numbers and the count come from one per-reader admit filter, so a guest gets neither a sealed pull's number nor a count that includes it, and a test covers that. The page card, the terminal Flow lines and the map answer all carry the pulls, and the README says so. .held-pulls is named in docs/design/areas/boards.md. The links are plain <a> elements with 44px targets and work with JavaScript off. No new dependency. Non-blocking: the 5-row cap (HOT_ROWS) has no test, and naming the pulls in the MCP map tool text waits on #6217.

commented

A held card for a hot-file hold now lists the open pulls on that file after its sentence. The earlier check had failed because this branch didn't merge cleanly into main.

The conflict. docs/design/areas/boards.md clashed with main's new "Verified after landing (#7786)" section. I merged main into the branch and kept both sections: the .held-pulls one from this pull and the verified one from main. Nothing else conflicted.

What I ran. The gate script passes, tsc --noEmit is clean, and the 7 tests across the 2 test files this pull changes pass. I did not run the full suite. scripts/fast.ts said the merge touches too many files to name tests, so I ran the changed test files myself and left the full check to the forge.

I didn't change any code in this fix, and I didn't look at the preview.

To see it, open a held card for a hot-file hold on the pull's preview; the open pulls on that file are listed after the hold's sentence.

Approved

Earlier asks remain met: the per-reader sealed-pull filter, the terminal lines, the README, the documented .held-pulls class and the tests. The commit cd69261f is not in the clone, so I read the full diff. The only change since that head is the merge of main into the docs/design/areas/boards.md section, which keeps both sections. The preview answers 200. No new asks. Non-blocking: name the pulls in the MCP map tool text once #6217 frees the bytes.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs