Repository navigation
v0.17.0 — the queue you can address, and the caller you can name
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.SenderandTurn.InquirySegmentsmean 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> inputheader, 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. clipandhardWrapcount 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.