gstack now asks a Capy Captain in plain words

2 days ago

This pull request makes gstack Capy aware. When it runs under a Capy Captain, every decision now reaches the person in plain words. Plan approvals arrive as a five part brief with a one word reply. Each branch keeps a record of who approved what. And the ship step puts before and after pictures of the change at the top of the pull request.

Ask about this presentation

Chapters

  1. 0:00gstack asks a Capy Captain in plain words
  2. 0:21Why: the relay lost the plain words
  3. 0:42The plan gate, before and after
  4. 1:06The Captain brief
  5. 1:31Who gets asked
  6. 1:56Standing approvals and fresh asks
  7. 2:23The approval record
  8. 2:50What keeps the record honest
  9. 3:17Before and after images on the merge ask
  10. 3:43Evidence
  11. 4:05What to know before you rely on it
Show transcript
  1. This pull request makes gstack Capy aware. When it runs under a Capy Captain, every decision now reaches the person in plain words. Plan approvals arrive as a five part brief with a one word reply. Each branch keeps a record of who approved what. And the ship step puts before and after pictures of the change at the top of the pull request.

    Slide text

    gstack now asks a Capy Captain in plain words

    briefplan approvals as a five-part brief, reply rec
    recordwho approved what, kept per branch
    imagesbefore/after pictures on merge asks
    v1.91.172.0 · feat(capy)
  2. On October 17th, Garry had to write this. He runs gstack through one Captain, GStack Minder, and about 30 crew threads, so every plan gate and every merge ask reaches him through a relay. Each thread and the Captain translated gate output by hand, so the shape depended on who wrote it. Three days later he asked for the fix.

    Slide text
    “Eli5 these recommendations and please note in the future you need to explain.”
    Garry · 2026-10-17
    1 CaptainGStack Minder relays every ask
    ~30 crew threads29 thread reports as of 2026-10-20
  3. This is the plan gate a thread used to relay. A gate line with a run id, then numbered items with option letters, and a reply grammar built from those letters. The Captain rewrote it into plain language by hand, and the codes leaked through anyway. Here is the same gate now. It opens with the decision in one sentence, says reply rec to take every recommendation, and then explains the plan.

    Slide text
    brief asks record images

    Gate codes became a brief that says “reply rec”

    Before: the autoplan gate as relayed, with gate ids, option letters and reply tokens before
    After: the Captain brief, opening with Decision needed and Reply rec after
  4. The brief comes from gstack owner brief render, with the captain flag. The first four sections are read straight from the reviewed plan, through a new fence aware heading parser. The last one is built from the gate itself. It lists every choice rec would take, in words. Gate ids and the rec hash move to one trailing line for the relaying agent. And a plan missing a section prints not ready for approval, and exits with code 1.

    Slide text
    brief asks record images

    Five sections, in a fixed order

    $ gstack-owner-brief render --captain --out <run>
    1. Before → after
    2. Why it matters
    3. What caused this work
    4. Big decisions
    5. What we need from you
    Reply: rec
    trailing agent linegate ids, gate_rev and rec_hash, for the relaying agent only
    CAPTAIN_BRIEF_INCOMPLETEa plan missing a section prints “Not ready for approval” and exits 1
  5. How does a workflow know it is under Capy? The Capy launch line sets a flag, and skill start prints Capy on, plus one block of instructions. A crew thread sends a needs you report to its Captain. A thread with no Captain asks the person with a Capy question. The agent picks the route, since Capy keeps crew membership to itself. The block is printed at runtime, so the generated skill files stay the same size.

    Slide text
    brief asks record images

    Under Capy, every ask goes through a Captain or the person

    CAPY: on
    gstack-skill-start, when the launch line sets GSTACK_CAPY=1, plus one capy-asks block
    crew thread →
    Its Captain
    a needs-you report
    no Captain →
    The person
    a Capy question
    Printed at runtime: 0 bytes added to generated SKILL.md files. Other hosts print CAPY: off.
  6. Some decisions are already settled. A standing approval, like merge when green through a merge train, lives in the Captain's rules, and the thread cites it instead of asking again. A fixed list always needs the person's own words. That covers a product or behaviour decision, spend over a stated cap, anything published outside the repository, a change to a threshold, a budget or a trial count, closing someone's contribution without landing it, and anything destructive.

    Slide text
    brief asks record images

    Standing approvals get cited, and a fixed list always gets asked

    standing approval
    “yes merge when green”
    Listed in the Captain’s rules. The thread cites the rule instead of asking again.
    always a fresh ask
    • a product or behaviour decision
    • spend over a stated cap
    • publishing outside the repository
    • a threshold, budget or trial-count change
    • closing someone’s contribution without landing it
    • anything destructive
  7. Every answer gets written down. gstack approvals add stores one row per answer, with the person's exact words, who said them, what the answer covers, and what is still pending. After an autoplan gate is answered, import pulls the reply the gate already stored, and a second run adds zero rows. Render prints this table, which comes from this pull request's own body: the plan approval, a standing approval for paid evals, and merge when green.

    Slide text
    brief asks record images

    Each branch keeps who approved what, in their exact words

    DateAskedExact wordsOutcome
    2026-10-20Approve the plan “Make gstack Capy-aware …” (5 decisions)“rec”approved
    2026-10-15Run the focused paid eval cases for the changed skills“it's fine run as many $93 paid gates as you want who cares”standing approval
    2026-10-16Merge this PR“yes merge when green”standing approval
    $ gstack-approvals add | import --autoplan <run> | render | list | sync | path
  8. The record is one file per repository and branch, under the state root. A Capy machine's state root gets thrown away, so under Capy every write is mirrored to the private Drive folder. Every field goes through the secret scanner first, and a hit refuses the whole row. Cells are escaped, so the table can never be read as an approval citation. And a fresh machine with no record and no mirror says the record is unavailable, rather than showing an empty table.

    Slide text
    brief asks record images

    The record refuses secrets and never poses as a citation

    One JSONL file per branch
    <state root>/projects/<slug>/approvals/
    mirrored to the private Drive folder under Capy
    Secrets refuse the write
    APPROVAL_RECORD_SECRET
    names the field and rule, never the text
    Display only, never a citation
    cell() escapes @ [ ] ! ` | and “approved by”
    checked against parseCitations in the tests
    “Record unavailable”
    APPROVAL_RECORD_UNAVAILABLE
    a fresh machine with no mirror says so, instead of “No approvals recorded”
  9. Merge asks get pictures. Before, the ship step's pull request body opened with a summary and test coverage, so a merge decision meant reading the diff. Under Capy it now opens with what changed, why, and approvals. These two images come from the new PR shots command. It reads text only and runs nothing, then stacks before over after at GitHub's 880 pixel column, showing only the changed hunks.

    Slide text
    brief asks record images

    Under Capy, the /ship PR body opens with what changed, why, and approvals

    Before: the /ship PR body template opened with Summary and Test Coveragebefore
    After: the PR body opens with What changed, captioned before/after images, then Whyafter
  10. Four new test files cover the record, the brief, the images, and the whole Captain flow, from the gate, to the relay line, to the brief, to a relayed answer landing in the record and its mirror. Before merge, the remote free tier ran about 21 thousand tests with zero failures. Three focused paid ship cases passed, and typecheck came back clean.

    Slide text

    Tested end to end, from the gate to the mirrored record

    4 new test files
    including the whole Captain flow: gate, RELAY line, brief, relayed answer, record and mirror
    0 failed
    of 21,395 tests on the remote free tier at 3a7867f
    3 paid cases
    ship-local-workflow, ship-base-branch and ship-section-loading PASS; typecheck clean
    approval-record.test.ts captain-brief.test.ts pr-shots.test.ts capy-captain-flow.test.ts + Capy cases in gstack-skill-start.test.ts
  11. Three things to know before you rely on it. Two gate ceilings moved: the Capy skill's context budget went from about 2,900 to 3,500 tokens, and ship's parity cap rose slightly for the new section. Eval thresholds stayed where they were. Owners copy the skill folder over their Drive copy by hand to pick up the new guidance. And outside Capy, the only change is one status line. That is gstack, asking a Capy Captain in plain words.

    Slide text

    Three things to know before you rely on it

    Two gate ceilings moved
    capy/skill/gstack context budget 2,923 → 3,498 tokens
    ship parity cap maxSizeRatio 1.6488 → 1.6690
    Owners refresh their Drive copy by hand
    cp -R ~/.local/share/gstack/capy/skill/gstack/. <drive>/skills/gstack/
    Outside Capy, one new line
    every host prints CAPY: off; nothing else changes
    gstack asks a Capy Captain in plain words

What happened in AI today, in your inbox

One short email each evening. Read it and you’re caught up.

Built in New York with ❤️