Skip to content

v0.17.0 — the queue you can address, and the caller you can name

Choose a tag to compare

@jack-work jack-work released this 31 Jul 16:30
· 1413 commits to main since this release

Three feature lines land: a queue with identity and a hangup surface, a
prompt that mints the aria it needs, and a figaro that knows who is
talking to it.

Messages accepted while an aria is busy now have an identity — (epoch,
id) — and a surface. figaro queue lists them; rm and edit mutate
them; every refusal is a first-class result rather than an error.

The EPOCH is what makes an id safe to mutate against. Ids restart
whenever an agent is rebuilt, so a mutation presents the generation it
read and a stale one is refused rather than resolved against whatever
holds that number now. Without it, queue rm 3 after a daemon restart
deletes a different message.

Two hangup verbs, named rather than negated: hup stops the turn and
keeps the queue, cut stops it and hands the queue back so it can be
persisted rather than lost. H hangs up from the pager and stays
listening.

COALESCING IS A PROPERTY OF DRAINING. Every drain site folds the
contiguous run of queued prompts into one message — the idle drain that
opens a turn, the two mid-turn drains that steer one, and the interrupt.
Four chained sends are one reply and then ONE combined question. A
queued set or fork is a BARRIER: folding a prompt in front of a set
would answer it against a chalkboard it was never written against.

AN INTERRUPTED TURN TAKES NOTHING WITH IT. A dying turn can no longer
lift the queue on its way out.

figaro send creates an aria when this shell has none, with --loadout
to say which. A QUEUE VERB NEVER DOES: reading or editing what has not
been answered is meaningless against an aria that did not exist a moment
ago, so those verbs refuse instead of conjuring one.

Arias could not tell who was messaging them, and the reason was
structural: consecutive prompts fold into ONE message and the fold
flattened them, so a human, a parent aria and a sibling three worktrees
away all arrived as one anonymous blob.

  • The CALLING aria now rides the wire (x-internal-figaro-id) on both
    hops, CLI→angelus and angelus→agent.
  • Content.Sender and Turn.InquirySegments mean a message says who
    sent each of its parts. Blocks fold by sender RUN, so one sender is one
    block and a message with no senders encodes byte-identically to before.
    On screen: one > input header, each part labelled beneath it.
  • THE DUKE is the end user, named by the TARGET aria's duke-title
    chalkboard key (default "user") rather than by shell config. An
    interactive CLI sends a typed placeholder the agent resolves. Set
    duke-title = "yourname" in a loadout.

New in internal/authz: an authentication provider CONFIG CAN DISABLE
(a credential nobody can doubt is not authenticating anything) and ONE
authorization policy seam. [authz] in config.toml selects both, and
both default OFF — an absent section behaves exactly as before.

Its first rule refuses a self-fork issued from inside a running turn,
with an error that teaches the detached workaround. That is a GUARDRAIL,
NOT A CURE: the defect is that fork coordination rides the agent's
single-threaded event loop at all, and the real fix — trunk state in its
own reducible xwal channel — is recorded at the site and deferred.

  • A failed chalkboard append no longer advances the in-memory board. It
    was a hallucinated write, not a lost one: the patch reaches the model
    as a system-reminder it would lose on restart.
  • clip and hardWrap count CELLS, not runes, so wide glyphs no longer
    overflow a row.
  • Opening a turn no longer depends on which branch built a message's
    content.

Attribution is trust-on-assertion. A figaro that allocates itself a
terminal can present as the duke, and anything able to set FIGARO_ARIA
can claim that id. Accepted until real authentication — and exactly why
no asserted value reaches an authorization decision: Identity.Label is
a separate field from FigaroID so that rule is enforced by the type
rather than by memory.