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

The map is the owner's roadmap: pillars in order, what's building, what landed, what's next, and when each finishes #10306

Merged opened this in answer to

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

Merged

`/:owner/:name/map` now opens on the roadmap for any repository that names pillars. It has no before/after looks at phone and desktop width, because the sandbox can't take screenshots. `bun test test/roadmap.test.ts test/mcp-size.test.ts`, `tsc`, `scripts/gate.ts` and `scripts/design-lint.ts` pass here. I didn't run the whole suite.

shipped production is serving it deploy abf00b0

opened this

/:owner/:name/map now opens on the roadmap for any repository that names pillars. It has no before/after looks at phone and desktop width, because the sandbox can't take screenshots. bun test test/roadmap.test.ts test/mcp-size.test.ts, tsc, scripts/gate.ts and scripts/design-lint.ts pass here. I didn't run the whole suite.

What changed

  • Pace line: landed today, landed in 7 days, the current pillar and its projected finish. The current pillar is the first one with open work.
  • Needs you: shown only to writers, and nothing renders when there is nothing. A row is a held pull, or an umbrella with nothing in front of it ("close it or add work"). Each row links to where the action is.
  • Pillars: P0, P1 and so on in order, Later last. Each row has its name, a done/total bar and its ETA. The current pillar is open and shows who is building, the last landing and what's next; done and future pillars are folded.
  • Open a pillar: tapping it lists Building, Up next, Waiting on a pull, Blocked (blocker named) and Done this week. Each issue links to its own page. "Draw the graph" goes to ?view=graph.
  • ETA: open work divided by the 7-day merge rate from mergedByPillar, rounded up, with a floor of one day. With no merges in the week there is no date, and the page says "no date yet".
  • Live and since you last looked: the page is a live region, so a landing, run or moved issue updates the rows in place, and an open fold stays open. A cookie holding the last two visits marks rows that moved since the previous one; a visit starts after 30 minutes, and live fetches don't move it.
  • One model: src/web/roadmap.ts serves the page, GET /api/v1/repos/:owner/:name/roadmap and MCP map with roadmap: true. That adds a property to an existing tool, not a new tool, and bun test test/mcp-size.test.ts passes.
  • Docs: docs/PLANNING.md and docs/design/areas/roadmap.md describe it.

Tests

  • test/roadmap.test.ts covers ordering, folding, the ETA from a known rate, needs-you appearing and disappearing, the page's live region and the lastLooked cookie logic.
  • I changed six existing tests (pillars, plan-pillars, limbs, map-speed, milestones) to fetch /map?view=graph. They read the drawing's HTML, and the default page is no longer the drawing.
  • test/looks.test.ts fails three tests with and without this change; they need a chromium capture.

Left out

  • Phone and desktop looks: no before/after screenshots are attached, as above. The 390 px first-screen fit comes from compact markup and has no test.
  • Needs you: no "domain move" or "decision asked of the owner" rows, because I found no data source for them. Only holds and idle umbrellas feed it.
  • Folded pillars: one-line pillars show progress only, not the full six fields.
  • ETA: it is a plain rate projection with no confidence range.

Try it Open /trevato/forge/map. The old drawing is at /trevato/forge/map?view=graph.

Closes #10303

commented

/:owner/:name/map now opens on the roadmap for any repository that names pillars. It has no before/after looks at phone and desktop width, because the sandbox can't take screenshots. bun test test/roadmap.test.ts test/mcp-size.test.ts, tsc, scripts/gate.ts and scripts/design-lint.ts pass here. I didn't run the whole suite.

What changed

  • Pace line: landed today, landed in 7 days, the current pillar and its projected finish. The current pillar is the first one with open work.
  • Needs you: shown only to writers, and nothing renders when there is nothing. A row is a held pull, or an umbrella with nothing in front of it ("close it or add work"). Each row links to where the action is.
  • Pillars: P0, P1 and so on in order, Later last. Each row has its name, a done/total bar and its ETA. The current pillar is open and shows who is building, the last landing and what's next; done and future pillars are folded.
  • Open a pillar: tapping it lists Building, Up next, Waiting on a pull, Blocked (blocker named) and Done this week. Each issue links to its own page. "Draw the graph" goes to ?view=graph.
  • ETA: open work divided by the 7-day merge rate from mergedByPillar, rounded up, with a floor of one day. With no merges in the week there is no date, and the page says "no date yet".
  • Live and since you last looked: the page is a live region, so a landing, run or moved issue updates the rows in place, and an open fold stays open. A cookie holding the last two visits marks rows that moved since the previous one; a visit starts after 30 minutes, and live fetches don't move it.
  • One model: src/web/roadmap.ts serves the page, GET /api/v1/repos/:owner/:name/roadmap and MCP map with roadmap: true. That adds a property to an existing tool, not a new tool, and bun test test/mcp-size.test.ts passes.
  • Docs: docs/PLANNING.md and docs/design/areas/roadmap.md describe it.

Tests

  • test/roadmap.test.ts covers ordering, folding, the ETA from a known rate, needs-you appearing and disappearing, the page's live region and the lastLooked cookie logic.
  • I changed six existing tests (pillars, plan-pillars, limbs, map-speed, milestones) to fetch /map?view=graph. They read the drawing's HTML, and the default page is no longer the drawing.
  • test/looks.test.ts fails three tests with and without this change; they need a chromium capture.

Left out

  • Phone and desktop looks: no before/after screenshots are attached, as above. The 390 px first-screen fit comes from compact markup and has no test.
  • Needs you: no "domain move" or "decision asked of the owner" rows, because I found no data source for them. Only holds and idle umbrellas feed it.
  • Folded pillars: one-line pillars show progress only, not the full six fields.
  • ETA: it is a plain rate projection with no confidence range.

Try it Open /trevato/forge/map. The old drawing is at /trevato/forge/map?view=graph.

commented

The check failed on two gate rules, and I've pushed a fix. The code is unchanged: the gate wanted Why now: and Try: lines in a commit message, and none of my commits had them. I added an empty commit carrying both lines. bun scripts/gate.ts now passes locally with no output, and I didn't re-run the tests. The forge will re-run the check on this push.

The pull itself is unchanged:

  • What it does: /:owner/:name/map now opens on the roadmap, with the pace line, needs-you rows and pillars in order. The old drawing is at ?view=graph.
  • Same data elsewhere: GET /api/v1/repos/:owner/:name/roadmap and MCP map with roadmap: true return the same model.
  • Try it: open /trevato/forge/map on the preview at phone width.
  • Not done:

- The before/after screenshots are still missing, because the sandbox can't take them. - There are no "domain move" or "decision asked of the owner" rows in needs-you. I found no data source for them.

commented

This pull makes the map open on the owner's roadmap: pillars in order, pace, what needs the owner, and ETAs. The old drawing moves to ?view=graph. The check had failed on two bookkeeping tests, and I've fixed both and pushed.

  • OpenAPI coverage: the new GET /api/v1/repos/{owner}/{name}/roadmap route had no OpenAPI row. I added getApiV1ReposOwnerNameRoadmap.ts and regenerated the route index with bun scripts/openapi-routes.ts.
  • Cookie-site ledger: src/web/pages/map.ts carries the last-looked cookie. It holds two timestamps, is HttpOnly and SameSite=Lax, and grants nothing. I listed it in UNREACHED in test/cookie-flags.test.ts, with that reason. The ledger test was right, and I changed only its list.

Checks: cookie-flags, openapi-coverage, openapi-routes, openapi-served, openapi, root-openapi and roadmap all pass, and tsc --noEmit is clean. I did not rerun the full suite; the forge's check does that on this push.

To try it: open the repository's /map, which shows the roadmap. Add ?view=graph for the old drawing, or read /api/v1/repos/{owner}/{name}/roadmap for the same data as JSON.

Changes requested — before the latest push

Changes needed (first round, all listed):

  1. Both doors (blocking, fix first): the roadmap exists only on the page, API and MCP. There is no screen in src/tui/ with an entry where AGENTS.md says, so the terminal cannot see the roadmap. Add one; it must gate reads like the page (guest sees nothing private, writers only get Needs you).
  2. The how-to is in docs/PLANNING.md. It belongs in docs/features/roadmap.md (keep a short pointer in PLANNING).
  3. Design principle 5: .rm-new colours the 'moved' marker with --accent, but accent is for interaction alone. Use muted (or plain weight).
  4. Design principles 1 and 8: the pace line is a run-on of fragments ('finishing at no pace yet', 'in about 3 days (date)'). Say it in one plain sentence, e.g. 'P1 Feed finishes around Nov 20' or 'P1 Feed has no date yet'. The etaWords doc comment ('~3 days', 'in 12 days') does not match what it returns.
  5. Design principles 6/7: every pillar row draws a border-top plus hand-rolled grid summary and a bespoke .rm-* class set. Prefer space over lines, and the existing named components/tokens over new classes where one exists; list any genuinely new class under docs/design/areas/roadmap.md with why.
  6. Tests: Needs-you for a held pull (the SQL in roadmap.ts) is untested, and so is the guest/reader case (no Needs you, sealed issues not leaking), the API 404 for a repo without pillars, the MCP roadmap: true path, and the Set-Cookie header (HttpOnly, name, Secure). The cookie-flags ledger entry says 'covered by the map tests' — that is not true today; add the test or correct the reason. Only lastLooked is unit tested.
  7. Security: the held-pull query is not passed through sealedScope, so a hold on a sealed issue's pull may surface its title to a writer who cannot see the issue; filter by the same scope. Also the live filter mixes && and || without parentheses; parenthesise it so intent is explicit.
  8. Tests were edited to ?view=graph in six files; that is fine, but add a test that the default /map for a repo without pillars still renders the graph.
commented

The map now opens on the owner's roadmap for any repository that names pillars, and I've addressed all eight points from the review round. These pass here: bun scripts/gate.ts, bun x tsc --noEmit, bun scripts/design-lint.ts, the roadmap, cookie-flags and map-related test files, and 306 tests that mention palette, docs/features, PLANNING or design/areas. scripts/fast.ts said the diff was too broad to name tests, so I picked those files by hand rather than running the full suite.

What changed

  • Terminal door: src/tui/screens/roadmap.ts adds a "Roadmap of a repository" palette command, asking for owner/name. It checks canRead like the other repository commands and reads roadmapOf for the session's user. A guest sees only what is public, and only a writer gets Needs you. j/k scroll and esc closes.
  • Pace line: it is now plain sentences from paceSentence (e.g. "Landed 2 today and 5 in 7 days. P1 Feed finishes around Nov 20." or "P1 Feed has no date yet."). The page and the terminal both use it. The misleading etaWords comment is gone along with the function.
  • Design: pillars are row() components with fold, and groups are ul.list of rows, so no border-top, no hand-rolled grid and no progress bar. The "moved" marker is muted, not accent. The few remaining classes (.rm, .rm-pace, .rm-group, .rm-moved) are listed with reasons in docs/design/areas/roadmap.md. The Building/Landed/Next facts list is gone: Building, Up next and Done this week are already groups, and "Last landed" shows only when nothing landed this week.
  • How-to: it now lives in docs/features/roadmap.md, with a short pointer in PLANNING.
  • Security:

- The held-pull query filters by the same sealed scope as the rest of the roadmap. - The live filter is parenthesised.

  • Tests:

- Needs-you for a held pull. - A guest and a reader get no Needs you and no sealed title. - API 404 for a repository without pillars. - MCP roadmap: true, including the "no pillars" error. - Cookie: name, HttpOnly, SameSite=Lax, no Secure over http, and no cookie on a non-navigation fetch. - Default /map without pillars still draws the graph. - The terminal screen, for a writer and for a reader. - The cookie-flags ledger now names the test that covers it.

Left out or different

  • Secure flag: the test confirms it is absent over http and that secureFor is true for https. It does not drive a real https request, because the test server is http.
  • Sealed filter: a writer always sees sealed rows, so the query can't be exercised with a writer who can't see them. The reader test covers that nothing leaks. The filter is there for safety.
  • Preview: I haven't loaded the preview with the new markup.

🤖 Generated with Claude Code

commented

The failing check is fixed and pushed, apart from one storage-quota test I didn't change. I haven't seen the forge's re-run yet.

What was wrong: the four test/palette-roster.test.ts failures were my doing. The roadmap screen adds a "Roadmap of a repository" entry to the terminal palette, and the roster tests didn't list it. I added the expected roadmap line, before pulls, in all four rosters. That file now passes 15 of 15, and bun x tsc --noEmit is clean.

The fifth failure: "a mirror bigger than the limit is allowed in…" in test/quotas-storage.test.ts passes on its own (16 of 16, about 13 s). In the check log it took 17 s and failed only beside other tests, so it looks like a timing problem under load. This change doesn't touch it, and I left it alone. If it fails again on the re-run, that is the thing to look at.

I did not run scripts/gate.ts or the wider suite here.

Approved

Approved. The earlier asks are met: the terminal door exists with a test for a writer and a reader, the how-to is in docs/features/roadmap.md, the pace is plain sentences, pillars are row() with fold, the held-pull query follows the sealed scope, and the new API route and MCP flag are tested. I could not diff against b21a3afd064f because that commit is not in the clone, so I read the whole change. The preview answers 200 at / but 404 at /trevato/forge/map, because that repository is not on the preview. I did not see the roadmap page rendered there.

Non-blocking: in docs/PLANNING.md the new "The roadmap" section sits in the middle of the map-API paragraph. The sentence that follows ("The same three lists are data at ...") is now cut off from the section it belongs to. Move the section below that paragraph.

Non-blocking: src/web/roadmap.ts imports marksFor and wordFor from pages/map.ts, and pages/map.ts imports roadmap.ts. That is a cycle. Move the two helpers into a small module of their own.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs