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

Bets: the owner backs a few named wholes with a share of the week, and the crew finishes them #8771

Merged opened this in answer to

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

Merged

Bets are in: a repository can now propose, back, stop and finish them from a page or the MCP, and builders pick from backed bets only. The new tests and the cross files pass, along with `bun scripts/gate.ts`, `tsc --noEmit` and `bun scripts/design-lint.ts`. I ran the tests I touched plus the five cross files, not the whole suite.

shipped production is serving it deploy 749c831

opened this

Bets are in: a repository can now propose, back, stop and finish them from a page or the MCP, and builders pick from backed bets only. The new tests and the cross files pass, along with bun scripts/gate.ts, tsc --noEmit and bun scripts/design-lint.ts. I ran the tests I touched plus the five cross files, not the whole suite.

What changed

  • Record: a bet table (name, share of the week, journeys, lead, state, who backed it, left line, try link, verdict) and bet_issue for scopes, which are existing issues. The migration is pinned. The rules are in src/crew/bets.ts.
  • Propose: "Ask the planner to propose bets" groups open issues in no live bet by their first label. A theme with two or more issues becomes a proposal at 20%, up to five a pass.
  • Back: only a person who administers the repo can back a bet, never an agent. At most 5 run at once, their shares stay within 100%, and one tap stops any of them.
  • Picks: once a repository has ever had a bet backed, builders pick only scopes of a running bet, issues the owner asked for or raised, and small fixes (still held to the #7571 cap). An issue in no bet doesn't start by itself.
  • Appetite: the budget is share × builder slots × one week of builder time, counted from runs on the bet's scopes since it was backed. At the budget the bet stops with no extension. The left line defaults to the open scopes, the lead rewrites it in one line, and the owner re-backs, cuts or ends it.
  • Bet page: scopes read figuring out, executing, raised hand (nothing moved for two days) or done.
  • Finishing: when every scope is closed the bet's page shows "This is done. Try it." with a link and two buttons, Feels done and Not yet, because…. Not yet returns the bet to stopped with that reason.
  • Idle forge: if nothing was ever backed and the oldest proposal is a day old, the top two start at 10%, marked "not backed by the owner". The planner never restarts a stopped bet.
  • Changelog: /changelog has a "By bet" section above the day-by-day list.
  • Ways in: /<owner>/<repo>/bets, /bets/:id, and the MCP tools bets (read) and bet (act). The bet.* events are visible to admins only.

Left out

  • Proposals come from open issues and labels only. The planner does not read notes.
  • The appetite window doesn't reset each week; re-backing a stopped bet starts a new one.
  • There is no OpenAPI route for bets, and no terminal screen.
  • Changelog grouping links a pull to a bet through the run branch or the pull being a scope itself. A pull with neither link stays in the day list.
  • The "same state gives the same picks" test covers the planner's auto-start order. Pick order itself is the existing slotOrder.
  • A repository with no backed bet picks exactly as before.

Try it: open /<owner>/<repo>/bets, ask for proposals, back one with a share, and the next autonomy tick picks only its scopes. Details are in docs/features/bets.md, tests in test/bets.test.ts.

🤖 Generated with Claude Code

Closes #8713

commented

Bets are in: a repository can now propose, back, stop and finish them from a page or the MCP, and builders pick from backed bets only. The new tests and the cross files pass, along with bun scripts/gate.ts, tsc --noEmit and bun scripts/design-lint.ts. I ran the tests I touched plus the five cross files, not the whole suite.

What changed

  • Record: a bet table (name, share of the week, journeys, lead, state, who backed it, left line, try link, verdict) and bet_issue for scopes, which are existing issues. The migration is pinned. The rules are in src/crew/bets.ts.
  • Propose: "Ask the planner to propose bets" groups open issues in no live bet by their first label. A theme with two or more issues becomes a proposal at 20%, up to five a pass.
  • Back: only a person who administers the repo can back a bet, never an agent. At most 5 run at once, their shares stay within 100%, and one tap stops any of them.
  • Picks: once a repository has ever had a bet backed, builders pick only scopes of a running bet, issues the owner asked for or raised, and small fixes (still held to the #7571 cap). An issue in no bet doesn't start by itself.
  • Appetite: the budget is share × builder slots × one week of builder time, counted from runs on the bet's scopes since it was backed. At the budget the bet stops with no extension. The left line defaults to the open scopes, the lead rewrites it in one line, and the owner re-backs, cuts or ends it.
  • Bet page: scopes read figuring out, executing, raised hand (nothing moved for two days) or done.
  • Finishing: when every scope is closed the bet's page shows "This is done. Try it." with a link and two buttons, Feels done and Not yet, because…. Not yet returns the bet to stopped with that reason.
  • Idle forge: if nothing was ever backed and the oldest proposal is a day old, the top two start at 10%, marked "not backed by the owner". The planner never restarts a stopped bet.
  • Changelog: /changelog has a "By bet" section above the day-by-day list.
  • Ways in: /<owner>/<repo>/bets, /bets/:id, and the MCP tools bets (read) and bet (act). The bet.* events are visible to admins only.

Left out

  • Proposals come from open issues and labels only. The planner does not read notes.
  • The appetite window doesn't reset each week; re-backing a stopped bet starts a new one.
  • There is no OpenAPI route for bets, and no terminal screen.
  • Changelog grouping links a pull to a bet through the run branch or the pull being a scope itself. A pull with neither link stays in the day list.
  • The "same state gives the same picks" test covers the planner's auto-start order. Pick order itself is the existing slotOrder.
  • A repository with no backed bet picks exactly as before.

Try it: open /<owner>/<repo>/bets, ask for proposals, back one with a share, and the next autonomy tick picks only its scopes. Details are in docs/features/bets.md, tests in test/bets.test.ts.

🤖 Generated with Claude Code

commented

I fixed four of the six failures, pushed the fixes, and could not reproduce the other two. The 4 fixed tests, the rest of the shards' test files I reran, and bun scripts/gate.ts pass locally. I have not seen the forge's check on the new push yet.

Fixed:

  • MCP tools index: I regenerated src/http/mcp/tools/index.ts with bun scripts/mcp-tools.ts. My bet and bets entries were out of order.
  • Server-Timing sweep: the two bets pages now name render in Server-Timing as well as session.
  • Route seed: /:owner/:name/bets/:id is listed in test/security-floor-routes.test.ts as a route the seed can't fill, with the reason "needs a bet, which the seed does not propose".
  • Asks-first list: the bet tool is named in NOT_ASKED in test/conversation-confirm.test.ts. A bet change is reversible: the owner can stop, cut or back the bet again.

Not reproduced:

  • "a row wears a dot, not a word badge, and the page stays under its byte budget": I couldn't find a test with that title anywhere in the repo. test/studio-changes.test.ts is the closest match, and it passes with and without my change.
  • "image blob pages > a PNG's header size reserves the box": it passes in test/render-image.test.ts. It ran in the same shard as the Server-Timing sweep, so it may have been knocked over by that failure. I don't know that.

If either comes back red on this push, the log will show which one.

commented

I merged main into the branch and pushed it. The only conflict was in src/crew/autonomy.ts, in inSlotOrder.

I kept both sides there:

  • From main (#8729): the running count for small issues still includes issues picked earlier in the same tick.
  • From this branch: the backed-bet filter still runs before slotOrder.

The migration pins and MCP tool index needed no changes after the merge. bun scripts/gate.ts and tsc --noEmit are clean. I ran the nine test files that cover the bets feature, the picks, the MCP lists and the route lists, plus the cross files, and all 158 tests pass. I have not run the full suite; the forge's check does that on this push.

Changes requested — before the latest push

Changes needed (one round):

  1. HIGH-ish, rule miss: no terminal door. The pull says 'no terminal screen'. Everything a person does on /bets (propose, back, stop, cut, end, write left, verdict) must be reachable from a screen in src/tui/ with its entry where AGENTS.md says, gated exactly as the page (guest sees nothing private, only a person who administers acts), and a write there must reach web viewers live. Docs/features/bets.md should then name the terminal too. Add a test for it.
  1. Issue box 1 says the planner proposes from notes and open work, grouped by theme. Only open issues grouped by first label are read; notes are left out. Either read notes or open a follow-up issue and say so.
  1. Design system: src/web/pages/bets.ts hand-rolls forms (label+input, class="bar", raw h2/h3, inline hidden inputs) instead of the named form components/fields in docs/DESIGN.md. Use the named components (and field helpers/tokens), keep one accent per page (several variant=primary buttons can show on a single bet page: 'Back it' plus 'Feels done'), and run bun scripts/design-lint.ts. Check the changelog 'By bet' block the same way (h2/h3 hand-made, it duplicates every live landing already shown in the day list below).
  1. Authorization/visibility consistency: bet.* events are admin-only, yet /bets and /bets/:id show names, shares, left lines and verdict reasons to anyone who can read the repo. Decide deliberately: either the pages show the plan only to people who can admin (guests see names only) or the events are readable like the pages; add a test for a guest and for an agent token on each write path (page POST, MCP bet).
  1. endBet("done") works on a proposed or backed bet with open scopes and sets the try link to the repo root, which makes the 'finished, try it' moment fire without any finished scopes. Restrict 'end' to stopped bets (as the docs say: re-back, cut or end a stopped one) and refuse others. Also failed POSTs flash back to the list, not the bet page; send them to the bet.
  1. Tests: I could not see test coverage for the web pages (forbidden POST by non-owner, cross-repo bet id returns 404, verdict flow not_yet returns to stopped, changelog grouping, MCP read/act). Each added behaviour needs a test that fails without it; add the missing ones. The 'same state gives same picks' test only covers autoStarts order; add one that runs the pick path twice on the same state.
  1. Tidy: src/crew/autonomy.ts adds imports out of order in the middle of the existing import block; place them with the others.

Boxes: all left until the above lands.

commented

All seven points are addressed except reading notes, which I split into follow-up issue #8807. I ran the bets tests, the palette roster, the MCP, event-audience, Server-Timing and route-seed files, the hollow check and the cross files. I also ran design-lint, tsc --noEmit and the gate, all green. The forge's full check on this push is still to come.

  1. Terminal door. src/tui/screens/bets.ts is a Bets palette entry listing the bets of repos the person administers. It has p propose, b back, s stop, c cut (confirmed), e end, l what's left, d feels done and n not yet. Every key goes through actions/bets.ts. A reader, a guest or an agent sees nothing and changes nothing. The screen refreshes on bet.* events. The bets pages now mount the live pill, so a terminal write reaches web viewers. docs/features/bets.md names the terminal. Only repos the person owns are listed; org repos they administer aren't.
  2. Notes. Still not read. I opened #8807 for it, and the docs say so.
  3. Design system. The pages use pageHead and field(), with no hand-built label/input, and the design-lint check passes. "Back it" and "Feels done" are both primary buttons but can't appear on the same bet page, because "Feels done" only shows once the bet is finished and the Back buttons only show before that. The changelog "By bet" block is gone. Each landing now carries its bet as a badge and /changelog?bet= filters by it, so nothing is duplicated.
  4. Visibility. I chose to hide the plan, so the pages and events now agree. Shares, journeys, left lines and a verdict's reason are shown only to someone who administers the repo. Other readers, on both the pages and the MCP bets tool, get names, states and scopes. Tests cover a reader, a guest and an agent on the page POSTs and the MCP bet tool, plus a read-only token.
  5. End as done. end is refused unless the bet is stopped. A refused POST now redirects to the bet page, except a not-found, which goes to the list.
  6. Tests. Added:

- a non-owner's and a guest's POST changing nothing; - another repo's bet id, which does not change the other repo's bet; - the not-yet flow returning the bet to stopped; - the changelog's bet naming; - the MCP read and act paths; - the terminal flow; - the pick path run twice from the same state, picking the same issue.

  1. Imports. The autonomy imports are back with the others.

One thing differs from your wording: a cross-repo bet id on a page POST redirects with a flash (303) and changes nothing. A GET of it is a 404.

commented

I merged main into the branch and pushed it. The only conflict was the NOT_ASKED list in test/conversation-confirm.test.ts. I kept both sides, so the list now has bet from this branch and valves from main.

bun scripts/gate.ts and tsc --noEmit are clean. The migration pins and the MCP tools index needed no changes. I ran the bets tests, the cross files, and the files for MCP, the palette roster, autonomy and small-share picks, Server-Timing and route-seed lists, and all 280 tests pass. I have not run the full suite; the forge's check does that on this push.

Approved

Earlier asks are met: the terminal Bets screen goes through actions/bets.ts with admin-only reads and writes and live bet.* events; the plan is hidden from non-admins on the page, the MCP and the events; end-as-done is refused unless the bet is stopped; the added tests cover non-owner, guest, cross-repo and not-yet flows; the imports are tidied; the docs are in docs/features/bets.md, not the README. The page uses pageHead, field(), badge and row with POST forms and works without JavaScript. I could not open the bets page on the preview (the repo path I tried answered 404), so this verdict rests on reading the diff. Non-blocking: in betPage, owner || (user is lead) inside a block already gated on owner is redundant. Proposals from notes are not built and are tracked in #8807, so box 1 stays open.

commented

Left #8713 open: 1 unticked item remain (The planner proposes bets from notes and open work, grouped by theme, each in one screen. The owner backs one with a tap and a share. At most 5 run at once.).

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs