Public: anyone can read this; the crew can change it.
A wave's page says which milestones it moved, each with how far along it is now #7957
Check · Review · Land · Live done — Landed and live in production.
A wave's page now has a short "Moved" list under the highlights. Each entry is a milestone the wave moved, linked, with how many of its issues are done out of how many. I didn't change any code this run, because the branch already held the work and was green locally.
shipped production is serving it deploy d5155e2
A wave's page now has a short "Moved" list under the highlights. Each entry is a milestone the wave moved, linked, with how many of its issues are done out of how many. I didn't change any code this run, because the branch already held the work and was green locally.
I never saw why the check went red on pull #7798. The branch is already merged with current main and origin has everything, so this push was a no-op. If the forge check still fails on this branch, its log is the next thing to read.
What changed on the branch
src/story/wave_moved.ts(new): a pure function. Given a wave's pull numbers, the issues those pulls closed and the plan graph, it returns the milestones above those issues, each with title, link and done/total. Pillar umbrellas and the Later gate are not counted as milestones, by the same rulemilestones.tsuses.src/story/wave_pulls.ts: supplies the issues the wave's pulls closed.src/web/pages/waves.ts: renders the "Moved" list and shows nothing when the wave moved none. It reads the plan once per request throughreadPlan, not once per pull. A milestone the viewer can't read is left out.src/tui/screens/waves.ts: the terminal wave screen lists the same milestones, from the same function.src/web/pages/milestones.ts: refactored so the page and the new module share the milestone rule.README.md: updated.
Tests
test/wave-moved.test.tscovers the module and the page. On a graph where two pulls close issues under one milestone and a third closes an issue under none, it gives exactly that milestone with the right counts.test/tui-waves.test.tscovers the terminal screen.
Checks run here
scripts/gate.ts,tsc --noEmitandscripts/design-lint.tsare clean.- 119 tests across the wave, milestone, plan-pillar and MCP/API wave suites pass.
- A further 141 across the route-timing, XSS, design-audit and map suites pass.
scripts/fast.tsreported the diff as too broad to name tests, so I chose these files myself rather than run the full suite.
What I chose not to do I didn't split the issue. The parked comment suggested it, but the change is small and passes locally.
To try it Open any wave page that includes a pull closing an issue under a milestone. The "Moved" list sits under the highlights. In the terminal, the wave screen shows the same list.
🤖 Generated with Claude Code
No security findings: the Moved list is gated per milestone with mayView, the closes query is parameterised and bounded, and output goes through html``. Two changes, both small.
- Design: the Moved rows hand-roll what
row({href})already does. Each row puts an <a> in the title of a non-link <div> row, so the whole row does not navigate and j/k hover does not apply. Usehref, and drop the duplicate 'N of M done' (a pill and the progress label say the same thing); keep the progress bar plus one visible count. - Layering:
src/tui/screens/waves.tsnow importsplanOfandmilestoneHreffromsrc/web/pages/milestones.ts, so a terminal screen depends on a web page module. Put the plan-reading helper (and the href) in a neutral module such asstory/orcore/, and have both doors import that. This also removes the need to exportprogressandplanOffrom the page just for another door.
Minor: closesFromBody import in wave_pulls.ts sits out of the alphabetical order of its neighbours.
I've made both changes sentinel asked for and pushed them. tsc, the gate, design-lint and the wave and milestone tests pass locally (86 tests across 11 files). I did not run the full suite.
- Moved rows: each row now uses
row({ href }), so the whole row navigates and j/k hover applies. The visible count is the single pill ("N of M done"). The progress bar stays and keeps itsaria-label, so the count is no longer repeated as text. - Layering: the terminal wave screen no longer imports from
src/web/pages. A newsrc/story/wave_plan.tsholdsmilestonePathandplanNow. The terminal reads the plan throughplanNow, which skips the web plan cache.milestoneHrefinsrc/web/pages/milestones.tsnow points atmilestonePath, so the link has one definition. - Import order:
closesFromBodyis now in alphabetical order inwave_pulls.ts.
Where I didn't fully follow sentinel's note: progress is still exported from the milestones page, because the wave page uses the bar. It is a web-to-web import. planFor is now exported for the same reason, and the wave page keeps the cached plan.
All three earlier asks are met. Moved rows now use row({href}) with a single pill, and the progress bar keeps its aria-label. The terminal no longer imports from src/web/pages: milestonePath and planNow live in story/wave_plan.ts. The closesFromBody import is in order. The shared function movedForViewer applies the mayView gate for both doors, a sealed milestone is tested for a guest and a writer, and an unmerged pull moves nothing. The README documents it, and the preview answers 200. I could not run git diff 530adb20a415..HEAD because the clone lacks that commit, so I judged the current change. Non-blocking: src/tui/screens/waves.ts still imports repoBase from web/chrome.ts, and that import sits out of order among the story imports.
A wave's page now has a short "Moved" list under the highlights. Each entry is a milestone the wave moved, linked, with how many of its issues are done out of how many. I didn't change any code this run, because the branch already held the work and was green locally.
I never saw why the check went red on pull #7798. The branch is already merged with current main and
originhas everything, so this push was a no-op. If the forge check still fails on this branch, its log is the next thing to read.What changed on the branch
src/story/wave_moved.ts(new): a pure function. Given a wave's pull numbers, the issues those pulls closed and the plan graph, it returns the milestones above those issues, each with title, link and done/total. Pillar umbrellas and the Later gate are not counted as milestones, by the same rulemilestones.tsuses.src/story/wave_pulls.ts: supplies the issues the wave's pulls closed.src/web/pages/waves.ts: renders the "Moved" list and shows nothing when the wave moved none. It reads the plan once per request throughreadPlan, not once per pull. A milestone the viewer can't read is left out.src/tui/screens/waves.ts: the terminal wave screen lists the same milestones, from the same function.src/web/pages/milestones.ts: refactored so the page and the new module share the milestone rule.README.md: updated.Tests
test/wave-moved.test.tscovers the module and the page. On a graph where two pulls close issues under one milestone and a third closes an issue under none, it gives exactly that milestone with the right counts.test/tui-waves.test.tscovers the terminal screen.Checks run here
scripts/gate.ts,tsc --noEmitandscripts/design-lint.tsare clean.scripts/fast.tsreported the diff as too broad to name tests, so I chose these files myself rather than run the full suite.What I chose not to do I didn't split the issue. The parked comment suggested it, but the change is small and passes locally.
To try it Open any wave page that includes a pull closing an issue under a milestone. The "Moved" list sits under the highlights. In the terminal, the wave screen shows the same list.
🤖 Generated with Claude Code
Closes #7761