Skip to content

firstmate 0.4.0: action buttons and an Answer box on held cards - #96

Merged
gpambrozio merged 2 commits into
mainfrom
fm/paseo-card-actions
Oct 9, 2026
Merged

gpambrozio merged 2 commits into
mainfrom
fm/paseo-card-actions

Conversation

@gpambrozio

@gpambrozio gpambrozio commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Closes #94

What

A card waiting on the captain ((hold: …)) can now be answered from the board:

  • Action buttons. The first mate writes the captain's likely answers on the backlog line as
    (actions: Label => prompt | Label => prompt). The card draws each as a button under "Captain's call"
    (on any card that has them, held or not, open or folded). A press sends the prompt through the board's
    existing sender, the one suggestions use, so the behaviour is the same: one message at a time, buttons
    disabled while one is out, a failure toast, and the chat coming into view (the First mate tab on a phone).
  • Answer box. Every held card has a text box and Send at its foot, which sends
    <task id> — <task title>: <typed text>. A half-typed answer survives the card changing column and the
    screen unmounting. In the workspace/agent panels, where no chat is in view, a toast says it went.
  • Charter. §2 now says every (hold: …) carries (actions: …): prompts that stand alone (full URLs,
    project names), most likely first, about four at most, rewritten when the next steps change and dropped
    when the hold comes off. Nothing else in the charter changed. Untouched homes pick it up on their own;
    edited ones get the usual Compare notice.

Syntax, as implemented

Ported from bb's FirstMate (gpambrozio/bb-plugins#35, fm/board-card-actions). takeActions and its test
cases are the same, and the charter paragraph is byte-identical to bb's:

  • (actions: (any case) up to its balanced closing ), anywhere on the line outside every other
    parenthesis
    . An (actions: inside (hold: …) or a note is that group's text, and a stray ) outside any
    group is ignored. It's taken out of the line
    before anything else is read, so a URL or (project: …) inside a prompt never reaches the title or fields.
  • Every unescaped | separates buttons, with or without spaces around it.
  • A button splits at its first =>, both sides trimmed. No arrow, an empty label or an empty prompt
    means that button is skipped.
  • \|, \(, \) and \\ are literal. A backslash before any other character is kept (C:\Users).
  • An unclosed field runs to the end of the line, is removed from the line and gives no buttons. The rest of
    the line still parses. Only the first field gives buttons; later ones are removed too.

Where this differs from the first mate's original spec (the bb branch wins): the spec had | with spaces as
the separator; bb (and so this PR) treats any unescaped | as one. The spec didn't say what happens to a
backslash before other characters, to later fields, or to an unclosed field's text; those follow bb as listed
above.

Not included (possible follow-ups)

The issue also suggests a "Why is stuck?" button and a column-level "Walk me through these"
button. They aren't part of the chosen design and are left out.

Found while testing, already there before this PR and not fixed here: on a compact web layout, clicking
into a card's Steer or Relaunch box folds the card and hides the box, because react-native-web fires a
Pressable's onPress from the DOM click. The new Answer box sits outside the card's Pressable for that
reason (recorded in firstmate/AGENTS.md).

Checks

  • npm run typecheck and npm test in firstmate/ (274 tests). New tests: the parser (bb's cases plus
    unspaced pipes), card actions and answer text, kept answer drafts, and the charter rule, with its examples
    parsed back through the parser. The pinned charter fingerprint was moved on purpose.
  • check-plugin-consistency.mjs firstmate passes. npm pack --dry-run includes client/card-answer.ts.
  • I rendered the card through react-native-web in headless Chromium at 240px and 420px. Long action labels
    wrap inside the card. Clicking into the Answer box doesn't toggle the card, action buttons don't either, and
    sends are refused while one is in flight.
  • After bb's review (fixes ported at bb 68ac588): the Answer box keeps its text with the input disabled while
    the send is out, and clears once it lands. A test covers a send that switches to the chat and back: the box
    is open and empty, and only one message was sent. Not checked: iOS/Android, a second theme, or a live daemon
    reload (the installed plugin points at another clone). These need a human look before merging, because
    merging is the release.

🤖 Generated with Claude Code

gpambrozio and others added 2 commits October 8, 2026 16:16
The first mate writes the captain's likely answers on a held backlog line as
`(actions: Label => prompt | …)`; the card draws each as a button under
"Captain's call" that sends its prompt the way a suggestion does, and every
held card gets an Answer box that sends `<id> — <title>: <text>`. The parser
(`takeActions`), its tests and the charter paragraph match bb's FirstMate
(gpambrozio/bb-plugins#35) so both boards read the same lines.

Closes #94

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- takeActions reads only an `(actions:` outside every other parenthesis, so
  one quoted inside a hold or a note is that group's text; a stray `)` outside
  any group is ignored. Same function and regression tests as bb's
  fm/board-card-actions at 68ac588.
- The Answer box keeps its words, with the input itself disabled, while the
  send is on its way, and clears once it lands, even after the board swapped
  for the chat; a failure leaves them to send again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gpambrozio
gpambrozio merged commit 5989657 into main Oct 9, 2026
9 checks passed
@gpambrozio
gpambrozio deleted the fm/paseo-card-actions branch October 9, 2026 16:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

firstmate: a Blocked card has no action, so held work is only reachable through the 8 suggestion buttons

1 participant