Kabuto

Kabuto.png

兜

The Helmet.

Beneath the helmet
the head that planned every plate
armor remembers. 兜

Yoroi laced the plates.

Ō-Yoroi closed the gaps.

But the armor was never the thing it existed to protect.

Behind the steel is the judgment that placed it there. The memory of the last blow. The attention that notices when a cord has loosened, when a message has not arrived, when a familiar voice has fallen silent.

LunarWing v2.1.4.0, Kabuto, is out.

This release turns toward the mind behind the armor: recovering interrupted missions, protecting the records they leave behind, keeping voice inference from crowding itself into silence, and making the system more exact about what it knows.

Kabuto protects the head.

The head houses the mind.

The mind is the most important part of a warrior.

A reply cut short is not a successful conclusion. A message accepted into a queue has not necessarily reached its recipient. A corrupted page should not keep returning to the agent as memory. And a security check that could not run has not passed.

Kabuto works at those distinctions.

Not a taller crest.

A clearer view beneath it.

Fire bent the steel,
thread drew the plates tight together,
now the helm takes form. 兜

The mind behind the armor

Highlights

  • The mission finds its way back. Mission turns interrupted after partial provider output now attempt bounded recovery for qualifying transient or unavailable providers. Failed partial responses stay out of history and tool execution. Global listings also keep missions visible when their project metadata is missing or unreadable, restoring their path through daily rollover and dispatch. The new mission_history tool provides newest-first runs with ownership checks and multilingual-safe summaries.

  • An ending keeps its real name. Blocking responses and the deployed OpenAI-compatible streaming path preserve actual provider finish metadata. Missing or unfamiliar reasons become Unknown rather than an invented successful stop, and the deployed proxy no longer fills absent reasons with stop. Lightweight routines distinguish a length-truncated response from an empty one.

  • Memory receives another layer of protection. Curated-memory appends scan both the new entry and the combined document before committing. Full replacements of prompt-visible files attempt a rolling shadow backup of the previous content, readable by exact path but excluded from search. These are best-effort, single-slot backups, not an archive; a failed backup is logged rather than blocking the replacement.

  • The record can describe a threat without becoming it. Daily logs allow narrowly scoped, short, single-line quotations of High-severity injection-shaped text as descriptive context, while tokenizer-level patterns and unsafe spans still reject. When a clean append discovers an already poisoned daily log, the old content is quarantined outside search and automatic prompt inclusion. The discovering append is rejected with a retry hint: the clean entry is not silently written on its behalf.

  • A messenger carries a record of the journey. XMPP persists outbound messages before acknowledging their queue acceptance, then replays pending records after reconnect or restart. The message tool now says queued, not delivered. Recovery is at-least-once, so a crash between sending and removing a spool record can produce a duplicate. Exhausted retries leave a failed record for operator inspection instead of an invisible disappearance.

  • The voice keeps room to breathe. Separate admission limits for speech recognition, synthesis, and voice detection prevent repeated TTS retries from piling up behind the model mutex and consuming the other components’ capacity. Blocking work holds its permits until it settles. Readiness and metrics expose activity, abandonment, and permanent failure rather than treating every stalled call as the same condition.

  • The operator can shape the instructions. Settings → System Prompt adds tenant-scoped source editing, missing-file creation, and a saved workspace preview. Failed saves preserve unsaved edits. Engine V2 still takes an initialization snapshot, so applying a changed prompt requires a whole-tenant restart and a new conversation; existing threads keep their System message.

  • The watch gains better instruments. Optional tool-runtime hints learn from successful completions after a five-sample warmup, without counting approval waits, failures, or cancellations as completed runtime. mt-admin gains psql and daemon-pid diagnostics, while worker-image status distinguishes present, missing, and unselected lanes. The diagnostic commands are intended for read-only use, but that remains operator discipline, not an enforced restriction.

  • A new invitation does not erase the old ones. Pairing approvals now read and rewrite the allowlist through the same locked file handle. Existing grants survive new and concurrent approvals, and shorter replacements cannot leave stale bytes behind. The secrets-store redesign remains a design update; current pairing storage does not migrate.

  • The forge is inspected as carefully as the helm. Wasmtime/WASI advances to 36.0.17, alongside 121 semver-compatible external crate updates and a re-audit of all 27 tracked lockfile roots. The eight existing advisory exceptions were re-verified and remain unchanged. Registry-index failures now fail dependency checks instead of silently skipping the yanked-crate scan. Release validation includes remote CI, the published worker-image scan, and OpenCode 2’s candidate-versus-clean rebuild digest check.

Upgrading

Back up the database, tenant environments, /etc/lunarwing/ports.json, workspace and channel state, rendered units, worker data, and voice models before upgrading.

There are no new SQL or port-registry migrations. V27__memory_index_outbox.sql remains current, and the port registry stays at v17. Pairing storage and the seven bundled product skills require no migration.

Deploy the rebuilt components together. Rebuild the daemon, XMPP bridge, and installed WASM extensions, deploy the updated voice sidecar, and update lunarwing-proxy.py alongside the daemon. All four channel registry packages and nine tool registry packages have updates. Channel versions are darkirc 0.1.10, multica 0.1.13, weechat 0.2.11, and xmpp 0.1.16; the channel version bumps themselves do not change protocols.

Refresh the worker images. OpenCode 2 advances to v2.0.20. Rebuild Pebble with its updated dependency-lock override even though its source pin is unchanged. Kimi Code remains at 2.1.1, OpenCode v1 at v1.18.25, and Pebble at 2d0f3786…. Use the image digests recorded in worker-image-evidence.json.

Keep the vendor patch intact. Use ic/scripts/refresh-vendor.sh for dependency refreshes. Commit rig-core patch edits and regenerated checksums first. Same-version refreshes preserve the patch; a rig-core version change requires porting it, not replacing the patched tree with pristine registry sources.

Choose the tenant behavior explicitly. LUNARWING_TOOL_ESTIMATES=1 records and displays runtime hints after warmup; unset or observe records only, and 0 disables recording and new hints. Estimates are advisory, held in memory, and reset on restart. New tenants render ORCHESTRATOR_SELF_MODIFY=true; upgrading does not change existing tenants’ settings, and explicit values survive re-renders. After editing a system prompt, run restart-tenant and start a new conversation.

Use the updated tool contracts. Inside Engine V2 threads, use mission_history rather than routine_history. Record outbound messages as queued, not delivered. Every memory_write payload must fit within 256 KiB. When a daily-log append reports successful quarantine, retry the clean entry: the rejected append was not saved. Shadow backups and quarantined logs remain recoverable by exact path.

The release identifier is 2.1.4.0. All eleven LunarWing-owned release packages use 2.1.4. Rust 2024 and MSRV 1.96.1 remain unchanged.

What the helmet does not promise

The durable spool is XMPP-local. Other channels still use memory-only queues, and this release does not add end-to-end delivery receipts. XMPP also refuses proactive enqueue when no session is bound; persistence protects accepted messages, not every attempted send.

Voice admission is bounded, but a native inference call that never returns still holds a permit. Permanent component failures leave readiness degraded. The supported recovery is restart-tenant, which restarts the whole tenant.

Provider metadata is more faithful on the updated paths, but the outbound web OpenAI-compatible surface still maps Unknown to stop. The release adds no finish-reason-driven Engine V2 recovery policy. Research-child terminal triggers also remain a separate, unresolved mission behavior.

The helmet narrows the exposure.

It does not replace the watch.


Yoroi built the armor.

Ō-Yoroi fitted its joints.

Kabuto guards the mind that must keep using it.

The point was never to make the steel forget the blow.

It was to leave someone beneath it able to remember.

What the helmet guards
was never the metal’s strength:
the one who keeps watch.

兜

For full release notes, check the repository as always.