Skip to content

Releases: henit-chobisa/deck

v0.1.0 — the walk

v0.1.0 — the walk Pre-release
Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 18 Sep 10:21

Ninety commits since v0.0.9. deck talks now.

The walk

deck walk replaces deck live. The agent narrates a group out loud and the
code lights up underneath what it is saying — the light moves with the voice,
sentence by sentence, taken from the sound's own clock rather than a guess at
how long a word takes. Click any sentence and the code goes to what it names.

Speech for the groups ahead is rendered while you read the one you are on, so
changing group no longer stops to think. A passage is one sound, not a clip per
point, which is what used to make the voice stall at every full stop.

Voice needs a Google API key, set once in deck setup. Without one, walk is
not offered and everything else works as before.

Panes

Prose calls a pane by its name — the protocol pane — instead of by where it
happens to be sitting, so the sentence still reads when the layout changes.

Panes fold down to a spine, with the file's name turned on its side, and unfold
when something points at them. The agent can fold one pane or a whole group.
bring borrows a file that is not in the group and gives it back afterwards. A
proposed change arrives as a diff rather than a description of one. Long lines
scroll sideways.

Comments

A remark is deferred by default: it goes into the review and wakes nobody, so
the agent does not start work off half a thought. Queue hands it over at the
next gap; interrupt takes the floor. The rail reads as a thread now, and says
where a deferred remark was left.

Setup

deck setup lists every Chirp 3 HD voice Google offers and plays one before you
pick it, rather than after.

Fixed

  • Clicking a face in the rail published it immediately, although pressing the
    same face deferred it — so a reaction reached the agent the reader thought
    they were keeping until submit.
  • A lapsed hold waited for a show request before releasing.
  • Folding a resized pane left a gap, and juddered on the way in and out.
  • q did nothing while the composer was open, and comments were read aloud
    outside a walk.
  • The Windows build failed under -D warnings on a unix-only permission call.

Upgrading

brew upgrade deck

Do not run deck setup before upgrading — it writes the binary's older embedded
skill back over the newer file.

v0.0.9 — lights off

v0.0.9 — lights off Pre-release
Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 15 Sep 00:33

Lights off, proposed changes, and the first bug somebody else reported.

Zen: z

A shade over every display with the deck left on top of it, blurred and dimmed,
so the only lit thing on screen is the thing you are reading. Press it again, or
click the dark, to bring the lights up. It goes by itself when the deck does, and
when the deck stops being the active window.

# ~/.deck/config.toml
[zen]
dim = 0.72   # how far the rest of the screen goes down
blur = true  # and whether it is blurred as well as darkened

Most of the work was in making it read as an overlay rather than a very large
window. window_background in WindowOptions never reaches the platform, so the
blur has to be set inside the window builder. macOS draws every window with
rounded corners and a hairline edge and a titleless window is a titled one
underneath, so the sheet is drawn sixty pixels past every edge — the corners are
still round, they are round off the side of the screen. And AppKit will not put a
window over the menu bar however it is asked, so the bar is hidden outright,
before the shade opens rather than after.

On a Mac with a notch the top thirty-two points stay black. AppKit keeps windows
below the safe area and the only thing that lifts it is an Info.plist key,
which a binary installed by Homebrew has no plist to put it in.

--after: propose a change, do not describe one

A ref could always carry a replacement — PROTOCOL.md has documented after
since v1 and the renderer has drawn it the whole time. Nothing could write one.

deck group <path> \
  --ref "src/batch.ts:140-148 decremented *twice* when the write fails" \
  --after "    } catch (err) {
      logger.error(err);
      continue;
    }"

The range is drawn as going and the replacement spliced in under it, so the pane
reads as a diff. It attaches to the --ref in front of it. The file on disk is
never touched, which makes this the right shape for a plan: the code that
exists plus what you would do to it, reviewed before the edit rather than after.

Fixed

  • The narration was clipped with no way to reach the rest (#1, thanks
    @Saurabhkmr98). A say is as long as the agent needed it, the band is as tall
    as you have left it, and when they disagreed the prose stopped mid-sentence.
    It scrolls now; the title stays put; a new group opens at the top of its own
    prose.
  • Double-clicking the titlebar zooms the window, like every other window on
    the machine. Deck's titlebar is a real one made invisible, so the double-click
    had been landing on the band and doing nothing.

Refused rather than documented against

deck group now turns down two shapes that make a deck worse than prose. Both
were already rules in the skill, and both got written anyway.

  • A code block typed into the narration. The band renders inline marks only,
    so a fence came out as a wrapped paragraph with the backticks still in it. Code
    that exists belongs in a --ref; code that does not exist yet belongs in
    --after.
  • One file split across two panes a few lines apart. The second pane opens
    below the first and repeats most of it — two panes spent saying one thing, in
    the grid that exists to put two different things side by side.

v0.0.8 — the skill knows when to reach for itself

Choose a tag to compare

@henit-chobisa henit-chobisa released this 10 Sep 11:45

The skill knows when to reach for itself.

Everything here is the agent-facing skill, which is compiled into the binary —
so a new machine gets it from deck setup rather than from a file somebody has
to copy.

A trigger you can count

The skill's description now carries the rule that decides, rather than burying
it in the body where it is read after a model has already chosen prose:

If the answer you are about to write would name TWO OR MORE file:line
locations, it is a deck and you build one instead of writing the answer.

Arithmetic rather than judgement, because judgement loses to momentum at exactly
the moment it is needed — right after an investigation, when writing up what you
found feels like the job you were asked to do.

Do not ask permission

"Would you like me to put this in a deck?" is the failure this tool exists to
prevent. The reader asked a question about code; building the deck is
answering it.

A deck costs one keypress to ignore — a bar appears at the bottom of the screen
and they open it when they choose — so there is no cost to weigh and nothing to
ask about.

Twenty-one named situations

"About to explain code" is a category an agent does not notice being in. It
notices being in a PR review, or having just found a root cause. Each is named,
with the shape that suits it — including the ones that do not look like
explaining at all:

  • A stack trace is already a list of file:line locations, so the count has
    fired before a word is written. Do not paste it back to somebody who has it.
  • A failing test is the clearest three-ref group there is: the assertion, the
    code under test, and the change that broke it.
  • "Why did you do it that way?" — the constraint, the alternative, and the
    line that rules it out. If nothing rules it out, you have just learned you were
    wrong, and that is worth more than the defence.
  • "It does not actually do that." Correcting a belief is the hardest thing to
    do in prose. Point at the absence: the branch never taken, the handler nobody
    registers.
  • They asked the same thing twice. The prose failed. Do not explain it again
    more slowly.

And a PR is one deck per concern, never one per PR — a branch that touches a
schema, a connection and the UI is three decks walked in order.

Also

Five exclusions, including a new one: when they ask for prose outright — just
tell me
— give them prose. Answering the way somebody asked is not a failure to
reach for the tool.

v0.0.7 — diagrams you can walk

Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 10 Sep 10:50

Diagrams got most of the work.

Flows: a path through the picture

A diagram of any size answers several questions at once, and a reader looking
for one of them has to find it with a finger. A flow is the agent saying which
part it means — a name, and the nodes it touches in order.

"flows": [
  { "name": "the happy path",  "color": "#3fb950", "steps": ["run", "post", "q", "worker"] },
  { "name": "where it stalls", "color": "#d29922",
    "steps": ["run", "post", "q", { "node": "queued", "color": "#f85149" }] }
]

Several to a picture, and that is the point of them: the happy path and the one
that stalls over the same seven boxes is a better answer than two diagrams,
because what is being compared is what they share. A button per flow sits over
the drawing, wearing the colour its path is lit in.

Playing one sends a current along it rather than stepping frames. The front
moves continuously and every frame is drawn from where it has got to, so a box
lights through rather than lighting up. Speed is three tabs — slow, normal,
fast — at the bottom right.

A flow changes what stands out rather than recolouring: nodes on the path keep
their own skin and everything else recedes toward the page, so a diamond is
still visibly a decision while a flow plays.

Zoom, and drag in any direction

Hold or ctrl and use the wheel, or pinch on a trackpad. The layout is not
redone — a diagram's shape is its meaning, and a zoom that reflowed it would be
a different picture at every size — so every measurement is multiplied on the
way to the screen, text included. A percentage appears once you have changed it
and puts it back.

Dragging previously went through the scroll container, which re-clamps its own
offset every frame: a picture that fitted its pane could not be moved and one
that did not could only be pulled two of the four ways. It carries the drawing
itself now.

A decision with room for its question

A diamond's widest point is a single line through the middle and everything
above and below is corner, so a question of more than three words either spilled
or wrapped absurdly — and a question is the whole content of a decision node. A
hexagon says the same thing, points to the left and right where the two answers
leave, but its middle is a flat band the full height of the box.

Comment on the sentence you meant

Commenting on the narration quoted the first line of the group's say whatever
the reader had in mind. Drag across the words now and the comment carries
exactly what was covered; a click with no movement takes the whole sentence.

Fixed

  • Deck aborted the instant a deck was sealed — an animation list that got
    shorter between frames, indexed past its end.
  • Deck aborted when a deck with a diagram was opened — a pane reading the
    window that was drawing it, which is a second borrow, inside a mouse handler
    that cannot unwind.
  • The last node of every flow never lit: the front ran one step short of the
    box the whole path was walked to reach.
  • Drawings sat hard against the left of their panes instead of centred.
  • The play and stop glyphs are different widths, so pressing one resized the
    pill under the pointer that had just pressed it.

v0.0.6 — the crash on seal

Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 10 Sep 08:48

Two bugs. The first one killed the window.

Deck crashed the moment a deck was finished

The mark on the bar is a sequence of animations — two of them while the agent is
writing, one when it has finished. The library keeps the index of the running
animation in element state and indexes the list with it on the next frame, so a
list that got shorter between frames was an index past the end.

It got shorter at exactly one moment: when writing turns off, which is when the
agent seals the deck. So deck aborted the instant a deck was completed —
panic_bounds_check inside AnimationElement::request_layout.

It only started happening in v0.0.3, where the bar goes up before the writing
starts. Before that the bar appeared after everything was written, with the flag
already false, and the list never changed length.

The list is a fixed two entries now, and only the second one differs.

An agent can no longer open a deck

--now skipped the bar and put the deck straight on screen. It existed for an
agent that had been asked to show somebody something immediately. An agent used
it to open a deck on top of one the reader already had open.

The skill said not to do this. The agent did it anyway — which answers whether
the rule belonged in the skill. A rule that can be ignored is not a fix, so the
flag is gone. There is no longer any way for whoever writes a deck to decide
when it is read. The bar appears; the reader opens it, or does not.

Alongside it, a claim: two deck open calls on the same deck used to give two
windows. The second now finds the first written down under ~/.deck/showing and
leaves. Nothing hands a claim back — a claim is released by its process ceasing
to exist, which is the only event worth relying on, and a claim that outlived a
crash would make that deck unopenable forever.

v0.0.5 — the skill learns to teach

Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 10 Sep 08:27

The skill learns to teach. All of this release is the skill — no behaviour
changed in the binary.

A range is the smallest whole thing

Ranges were stopping in the middle of the function they pointed at. The reader
gets an opening brace and no closing one, and spends their first seconds working
out what they are looking at instead of reading it. Tight ranges on its own
pushed straight into that.

Now: the smallest range that is still a complete thing — a whole function, a
whole block, a whole match arm, signature through closing brace, because a body
without its signature is a body without its name. If a function is ninety lines
and eight matter, point at the eight and say which function they are in. Never
split the difference by stopping halfway.

A deck does not open itself

Sealing was being treated as a cue to put a window in front of somebody. It is
not. The bar is the whole invitation, and when to read is the reader's to
choose — which is almost never the moment the agent happens to finish.

deck open runs once, second, right after deck new, and not again.
--now is gated on the reader having said in words to show them something now:
finishing a deck is not such a moment, and neither is being pleased with it.

Three rules about explaining

The file said a great deal about what to show and almost nothing about how to
explain it.

  • Predict before you reveal. In a teaching deck, point at the code and ask
    what they think happens, then answer it a group later. Somebody handed the
    conclusion learns less than somebody who guessed and found out they were
    right. And a check before writing: does the story make them reason, or only
    receive?
  • Explain in terms of what is already on their screen. The comparison that
    lands comes from their own codebase — the sibling that does it correctly, the
    thing they built last month that works the same way. A generic metaphor makes
    them translate; a reference to the queue they already know makes them
    recognise.
  • Tell it like a story at a whiteboard, not like a changelog. Group by
    group, each carrying the last one forward.

Windows

Unchanged: builds and installs through cargo install --git, needs the MSVC
Build Tools for the linker, and has still never been run there.

v0.0.4 — deck open returns

Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 09 Sep 16:53

deck open returns.

The bug

deck open is the window — it ran the event loop in the process that was
typed, for as long as the bar or the deck was on screen. The skill said it
returned immediately. It never did.

That was survivable while open came last, after every group was written. In
v0.0.3 the order changed so the bar goes up before the research, and that made
it fatal: the agent ran deck open in the foreground, hung until its timeout,
and never wrote a single group. A bar appeared over an empty deck and stayed
that way.

It went unnoticed because every time it was run by hand it was run as
nohup deck open … & — never the way an agent runs it.

The fix

The process that was typed now starts another to hold the window and returns:
twenty milliseconds instead of never. A new session rather than just a new
process, because a shell reaps its whole process group when a command finishes
and a window in that group goes with it.

If the handover cannot be made it holds the window itself. Blocking is a worse
command than one that returns, but it is a working one, and a deck nobody can
open is not.

deck open --wait still blocks. Blocking is what it is for.

The skill marks deck open as a background command regardless — backgrounding
something that returns at once costs nothing, and there are installs older than
this release.

Windows

Unchanged: builds and installs through cargo install --git, needs the MSVC
Build Tools for the linker, and has still never been run there.

v0.0.3 — the bar arrives when the work starts

Choose a tag to compare

@henit-chobisa henit-chobisa released this 09 Sep 16:27

The bar arrives when the work starts, not when it finishes.

deck felt slow, and this is why

An agent would read code in silence for two minutes, write four groups, and
then put a finished deck on screen. From the other side of that, nothing
happens for two minutes and then a window appears. A tool that makes people
wait is a tool they stop reaching for.

deck open now works on a deck with nothing in it, so the bar can go up the
moment the agent starts. Open holds back until there is a group to read and
then comes up to colour over half a second — the button waking rather than
a window arriving. Waiting is drawn by draining the colour out of it rather
than by hiding it: a control that appears when something lands is a bar that
changes shape while you are looking at it.

The skill now teaches the order, which is the actual product:

  1. deck new — the title comes from the question, so this runs before any reading
  2. deck open — straight away, with nothing in the deck
  3. now read the code
  4. deck group, one at a time, as each becomes ready
  5. deck seal, then deck wait in the background

A picture and its code belong in the same group

--diagram was described as drawing a picture instead of refs, and no example
anywhere showed a group holding both. So a question about a flow came back as
six code refs and no picture at all. One group takes both, and for anything
shaped like a flow that is the normal thing to do.

Four paths stopped looking for a Mac

  • the window's shape read HOME, which Windows does not set
  • VS Code settings were looked for under Library/Application Support, never %APPDATA%
  • the themes an editor ships with sat behind one /Applications/… string
  • nvim asked correctly and was handed %APPDATA%, where nvim uses %LOCALAPPDATA%

And the mono font list had six faces, none of which ships with Windows or Linux.

Windows

Builds and installs through cargo install --git, and needs the MSVC Build
Tools for the linker. Still never run there.
cargo run -p deck-theme --example paths prints what deck resolved, which is
the useful thing to send back if it misbehaves.

v0.0.2 — the skill learns to draw

Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 09 Sep 16:00

The skill learns to draw, and learns to wait.

Both of these were found by using deck rather than by reading it — a real
deck went wrong in two ways in one afternoon.

A flow question is a diagram

Asked how a click reaches a controller, deck came back with six code refs and
no picture. The reason was structural: --diagram appeared exactly once in the
skill, in a list of flags, and pointed at PROTOCOL.md for its shape — a
document whose second paragraph says "Agents do not read this." The format
was documented in the one place its only audience had been told not to look.

The skill now has a When the answer is a picture section: the trigger stated
plainly, and the whole format inline — roles, weights, lanes, clusters, edge
lines, and a worked example. A test parses that example out of the skill as a
real Diagram, so an example that would not draw cannot ship.

Do not open a deck you are still working out

A deck was opened after group one while the agent went back to reading code to
work out group two, and the reader spent minutes watching the pulsing dot.
Streaming was meant to overlap their reading with the writing, not with the
thinking. The rule that was missing:

If you open a file to work out what group three says after the deck is already
on screen, you opened too early.

Also

  • deck --version now reports the version the release was cut from.

Windows

Unchanged. It builds and installs through cargo install --git, and four paths
still look for a Mac — HOME where Windows sets USERPROFILE, VS Code settings
under Library/Application Support, three /Applications/*.app bundle paths,
and dot_config() handing nvim %APPDATA% when nvim lives in %LOCALAPPDATA%.
Deck has still never been run on Windows.

v0.0.1

v0.0.1 Pre-release
Pre-release

Choose a tag to compare

@henit-chobisa henit-chobisa released this 09 Sep 15:33

The first one that leaves this machine.

What works

  • The window: panes, diagrams, comments, the review that comes back at once.
  • deck new / group / seal / open / wait — the whole agent loop.
  • Themes borrowed from Neovim, VS Code, Cursor, Windsurf and Zed.
  • deck setup — colours, and a skill installed into your agents.

What is rough

  • Only run on macOS so far. It builds for Linux and Windows and nothing there has been tried.
  • No signed binaries yet, so every install builds from source.
  • pages, three of the mock's keys, and writing an after ref are unbuilt.

Install

brew install henit-chobisa/deck/deck                                  # macOS, Linux
cargo install --git https://github.com/henit-chobisa/deck deck-app    # anywhere