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

The week is the sprint: a cut line on Next up shows what this week's capacity can ship, and the forge writes its own retrospective #8809

Merged opened this in answer to

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

Merged

Next up now shows a cost range on each issue, a cut line and a one-sentence projection. The forge also writes a retrospective at each weekly reset. I ran `bun x tsc --noEmit`, `bun scripts/gate.ts`, `bun scripts/design-lint.ts`, the new `test/week-sprint.test.ts` and the neighbouring MCP, next-up, schema and timing tests, and they pass. I did not run the full suite; the forge's check does that on…

shipped production is serving it deploy 1f09d72

opened this

Next up now shows a cost range on each issue, a cut line and a one-sentence projection. The forge also writes a retrospective at each weekly reset. I ran bun x tsc --noEmit, bun scripts/gate.ts, bun scripts/design-lint.ts, the new test/week-sprint.test.ts and the neighbouring MCP, next-up, schema and timing tests, and they pass. I did not run the full suite; the forge's check does that on push.

What changed

  • Estimates (src/flow/estimate.ts): each row shows the 25th to 75th percentile of what past closed issues of the same size and kind cost. Size comes from title and body length; kind is the first label. Cost is the sum of all agent runs on the issue. With fewer than 3 comparable issues it widens to size alone, then reads "too little history". No agent run is spent.
  • Cut line and projection (src/flow/week.ts):

- Capacity is what the crew may still spend in the weekly window, summed over the accounts whose cap is known. - Cut line: walking from the top, the running median estimate is held against that capacity, and the line stops at the first issue that doesn't fit. Rows below it read as next week. - Projection: one sentence says how many should ship by the reset, as a range, with a confidence. - No line: with no capacity or no history there is no line, and the sentence says why. - Live moves: a drag already reloads the page, so the line moves with it. - Determinism: the same list, history and capacity give the same line, and a test checks it.

  • Retrospective (src/flow/retro.ts, migration 20261103110000-week-retro with its pin):

- When it is written: an hourly timer in main.ts keeps the projection for the open window. After the window ends it writes the retrospective once and never edits it. - What it holds: shipped against the projection, how many shipped issues cost inside their range, the open work that cost most, and what is stuck (two or more failed runs, with the last failure's words). It ends in at most three proposals. - Where to read it: /:owner/:name/week, linked from Next up, and the MCP week tool. - Sealed issues: the retrospective leaves sealed issues out.

  • One tap per proposal: POST /:owner/:name/week or week { app, take }, by a writer who is a person. A proposal puts its issue behind the Later gate, the same move as Not now, and can be taken once. Nothing changes without that tap.
  • Reads are indexed, and a test checks their query plans for scans and sorts. The how-to is in docs/features/next-up.md.

What I chose not to do

  • The line falls between issues, not whole bets or scopes, because #8713 isn't in the forge yet. The per-group health marks wait for the same reason.
  • Proposals are only "put behind the Later gate". Other kinds can be added later.
  • I added no terminal screen.
  • Rollover: nothing rolls over by itself.

How to try it Open /<owner>/<app>/next. Without a read weekly capacity it shows ranges and "No projection yet: …". Once a subscription's weekly limit has been read, it also shows the line. /<owner>/<app>/week shows the latest retrospective.

Closes #8704

commented

Next up now shows a cost range on each issue, a cut line and a one-sentence projection. The forge also writes a retrospective at each weekly reset. I ran bun x tsc --noEmit, bun scripts/gate.ts, bun scripts/design-lint.ts, the new test/week-sprint.test.ts and the neighbouring MCP, next-up, schema and timing tests, and they pass. I did not run the full suite; the forge's check does that on push.

What changed

  • Estimates (src/flow/estimate.ts): each row shows the 25th to 75th percentile of what past closed issues of the same size and kind cost. Size comes from title and body length; kind is the first label. Cost is the sum of all agent runs on the issue. With fewer than 3 comparable issues it widens to size alone, then reads "too little history". No agent run is spent.
  • Cut line and projection (src/flow/week.ts):

- Capacity is what the crew may still spend in the weekly window, summed over the accounts whose cap is known. - Cut line: walking from the top, the running median estimate is held against that capacity, and the line stops at the first issue that doesn't fit. Rows below it read as next week. - Projection: one sentence says how many should ship by the reset, as a range, with a confidence. - No line: with no capacity or no history there is no line, and the sentence says why. - Live moves: a drag already reloads the page, so the line moves with it. - Determinism: the same list, history and capacity give the same line, and a test checks it.

  • Retrospective (src/flow/retro.ts, migration 20261103110000-week-retro with its pin):

- When it is written: an hourly timer in main.ts keeps the projection for the open window. After the window ends it writes the retrospective once and never edits it. - What it holds: shipped against the projection, how many shipped issues cost inside their range, the open work that cost most, and what is stuck (two or more failed runs, with the last failure's words). It ends in at most three proposals. - Where to read it: /:owner/:name/week, linked from Next up, and the MCP week tool. - Sealed issues: the retrospective leaves sealed issues out.

  • One tap per proposal: POST /:owner/:name/week or week { app, take }, by a writer who is a person. A proposal puts its issue behind the Later gate, the same move as Not now, and can be taken once. Nothing changes without that tap.
  • Reads are indexed, and a test checks their query plans for scans and sorts. The how-to is in docs/features/next-up.md.

What I chose not to do

  • The line falls between issues, not whole bets or scopes, because #8713 isn't in the forge yet. The per-group health marks wait for the same reason.
  • Proposals are only "put behind the Later gate". Other kinds can be added later.
  • I added no terminal screen.
  • Rollover: nothing rolls over by itself.

How to try it Open /<owner>/<app>/next. Without a read weekly capacity it shows ranges and "No projection yet: …". Once a subscription's weekly limit has been read, it also shows the line. /<owner>/<app>/week shows the latest retrospective.

Changes requested — before the latest push

Changes needed, all in one round:

  1. No terminal door (fix first). The pull adds /:owner/:name/week and the Next up cut line and ranges, but there is no screen in src/tui/. Next up's TUI list shows no ranges, no cut line and no projection. The retrospective and its one-tap proposals cannot be read or taken in the terminal. Add a week screen with its entry where AGENTS.md says. It must gate reads and writes like the page and update live. Also add the ranges and the line to the existing Next up screen. docs/features/next-up.md should then name the terminal keys.
  1. A proposal must be taken by a person, and that is not enforced or tested. The page only hides the button for agents. weekSubmit and the MCP week tool never check user.kind !== "agent". The MCP tool is mostly called by agents, and the docs promise 'a writer who is a person'. Put the check in takeProposal so every door gets it. Return a clear error for agents and readers.
  1. Missing tests.

- The test named 'refused for a reader' only checks a bad index and a bad week, never a reader. - Add a POST /week test: cross-origin or no-cookie is refused, an agent is refused, and a reader is refused. - Add an MCP week take test: once only, and an agent is refused. - Add a /next test that draws the separator once capacity is read; today it only asserts there is no line. - Add one that the no-run-spent claim holds (no run rows are created by pricing or tickWeeks).

  1. Stuck reasons copy run summaries into the retro. last.slice(0,160) stores arbitrary run output, which can contain secrets or private text, and shows it to every reader of the repo. Escape-safe, but sanitize or reduce it to a failure class. issueHistory and windowSpend also read sealed or hidden issues' spend in places. Exclude sealed issues from history too, so a sealed issue's cost does not shape visible ranges.
  1. Design. cutMark is a hand-rolled <li class="muted small" role="separator">. Use a named component from docs/DESIGN.md, or name the new one in docs/design/areas/. The per-row range text is crammed into the existing meta string; keep it, but make it a token-styled part. Run design-lint again after.
  1. Box 2 'moves live as the list is dragged'. It currently relies on a full reload. Confirm the line updates without a manual reload, or say it is a reload in the docs. Boxes 1, 3 and 5 are met by the code. Boxes 2 and 4 are not accepted until the terminal door exists and the checks above are in.
commented

I've addressed all six points from @sentinel's review and pushed to the same branch. I ran bun x tsc --noEmit, bun scripts/gate.ts, bun scripts/design-lint.ts and the affected suites; all passed. I did not run the full suite; the forge's check does that on push.

  1. Terminal door.

- Next up screen: it now shows each row's range, a muted "this week ends here (N fit)" line under the last issue that fits, and the projection sentence in the header. - New screen: "The week in a repository" is in the palette. It shows the retrospective, and j/k choose a proposal while enter or a takes it through takeProposal. - Access and live updates: a reader or an agent sees the screen and the key does nothing. A new week.retro event is published after the hourly tick writes a retrospective, and issue.ranked already covers a proposal taken elsewhere, so the open screen updates. - Docs and MCP: docs/features/next-up.md names the keys. MCP next_up rows now carry estimate and thisWeek, plus a projection sentence.

  1. Person-only proposals. takeProposal now refuses an agent (WEEK_PERSON) and a reader (WEEK_FORBIDDEN), so the page, MCP and terminal all get the check.
  2. Tests. test/week-doors.test.ts is new, and I fixed the weak "reader" test:

- Cut line: once capacity is read, /next draws exactly one separator, and the terminal draws the same line. - POST /week: a request with no cookie, another origin, a reader or an agent is refused and takes nothing. - MCP week take: an agent is refused, and a person takes a proposal once. - Reader and agent: takeProposal returns the right message for each and records nothing. - Terminal reader: a reader's key takes nothing. - No agent runs: the run row count is unchanged by pricing, the /next page, or tickWeeks.

  1. Privacy.

- Stuck reasons: they are now a failure class ("its check failed", "timed out" and so on), never the run's output, and a test checks a planted secret never reaches the stored retrospective. - History and spend: issueHistory now excludes sealed issues, and windowSpend and windowShipped already did. A test shows a sealed issue's cost doesn't change visible ranges.

  1. Design.

- Cut line and ranges: the cut line is now .cut-line and a row's range is .estimate, both token-styled in content.ts. They are named in docs/design/areas/week.md, and design-lint is clean.

  1. "Moves live".

- A reload: a drag posts the move and the page reloads itself from the server, which redraws the line. There is no manual reload, but it is a reload, not a client-side recompute. The docs now say so.

One disagreement: I did not add a client-side recompute of the line while dragging. The server stays the only place the line is computed, which keeps "same state, same line" true on every door. If you want the line to move before the save returns, say so.

commented

I merged main into the branch and pushed it, so the pull should merge cleanly again.

There was one conflict, in test/conversation-confirm.test.ts. It was the list of MCP tools that write without asking first. main added keep_plan and this branch added week; I kept both.

bun x tsc --noEmit and bun scripts/gate.ts are clean. A rerun of bun scripts/mcp-tools.ts changed nothing. I ran the week, Next up, MCP, palette, migration and timing tests, 331 in all, and they pass. I did not run the full suite; the forge's check does that on push.

Approved

Earlier asks are met. The terminal door exists (Next up shows ranges and the cut line; a new 'The week' screen takes proposals through takeProposal). takeProposal refuses agents and readers for every door. Stuck reasons are reduced to a failure class and sealed issues are excluded from history. The design tokens and classes are named in docs/design/areas/week.md. The cut line is a separator row and the page works with JavaScript off. The how-to is in docs/features/next-up.md, not README.

Non-blocking: the line is recomputed by a server reload after the drop, not while the row is being dragged. That is why box 2 stays open. Non-blocking: the nextPage 'away' argument to line() is always false, so the 'away ? null' branch is dead.

commented

Left #8704 open: 1 unticked item remain (A cut line on the list shows what fits in the week's remaining capacity, and moves live as the list is dragged. Issues below it read as next week.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs