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

Vote from the API, MCP and the terminal, through the one action #45

open not picked up yet opened this
opened this

A vote from a script, from an agent and from a keyboard, each calling the same vote from #5 and deciding nothing of its own. The page, the terminal and MCP are one implementation; this is the half that is not the page.

What done looks like

  • [ ] POST /api/proposals/:id/vote takes {optionId} validated at the boundary — a number, not a numeric string coerced; #41 is the precedent — and answers through answer, so the named failures keep their statuses: 401 anon, 403 off the roster, 404 no such proposal, 422 an option that is not on it.
  • [ ] The response carries the tally and, when that vote decided it, the decision, so a script needs no second request to learn what happened.
  • [ ] MCP tool vote in src/mcp.ts, its schema naming proposalId and optionId, with one sentence saying that votes are public, that changing a vote while the proposal is open replaces it, and that a decision is final. Its result is the shape the API returns.
  • [ ] MCP's get_proposal carries the tally and each option's id, so an agent can vote without scraping a page.
  • [ ] v in src/tty.ts picks an option by its number in the listing, prints the tally's reason back, and says plainly when the account at the keyboard is not on the roster. The terminal's help line lists it.
  • [ ] A vote from any door reaches an open page live — the action already emits the event, so this is a test that it crosses processes, not new code.
  • [ ] Tests in src/server.test.ts: the API's four refusals and its happy path; optionId as "3" refused rather than coerced; a cross-origin POST refused; the MCP tool voting and returning the tally; the terminal's v with a number out of range saying so without throwing.
  • [ ] README.md shows voting by curl and over MCP in the shape its other examples use. bun test is green.

Files I expect to change: src/routes.ts, src/mcp.ts, src/tty.ts, src/server.test.ts, README.md.

Risks: three doors are three chances to put a rule in the wrong place — none of them may check the roster, the state or the option itself; each parses its input, calls vote, and prints what comes back. The terminal is a second process on the same file: it must not hold a write transaction open while waiting for a keystroke.

Fit: Ledger — one action, four doors, the same answer at every one. A person assigns; I do not.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs