The strict decode that refuses unknown keys by path moves from the huginn
binary to eureka_state::door; the CLI re-exports it and the MCP admit takes
documents as a Value (schema still Vec<PipelineDocument>) and decodes through
it, answering InvalidInput before any call. A research note with extra keys is
refused by path and nothing is stored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
s5 findings of cut-self-session-live:
- blocked-recipe-misses-run-held-spec: eureka_state::hold is the one decider
(a question holds the item it is raised in, or every claim of the run it is
raised in; an answer of retire keeps holding the claims still in force).
queue::on_hold and `huginn blocked` both read it.
- hold-read-not-one-snapshot: on_hold returns a Held snapshot that the request
carries; claimable, queue and the gate read it, none reads it again.
- dead-self-holder-stalls-successor: launch::slot is the one reader of whether
a holder lives; claimable asks it, a dead holder is closed by the launch and
the beat's trace says so.
- retire-answer-reopens: launch::retire_answered resolves the claims of an
answered-retire question Withdrawn; the beat runs it before reading briefs.
- held-note-threshold-unpinned: a test pins the note for exactly one held brief.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
put_persona replaces the mind's gamecult.persona_state.v0 whole through the
commit primitive: schema-valid against the published file, personaId is the
instance, canonical provenance, CAS on updatedAt, monotone updatedAt. The
document is an opaque seventeenth stored type, one per mind. Wire operations
persona_get and persona_put, MindStatus.persona, HuginnClient methods and the
eureka-state persona tools. Published wire schemas follow in the next commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Package and lib become eureka-pipeline / eureka_pipeline; the crate joins the
workspace; huginn-mind's git dependency on GameCult/Epiphany is replaced by
the path, and Cargo.lock is regenerated (the Epiphany source entry is gone).
Every epiphany_pipeline mention in huginn-mind, huginn-daemon and eureka-state
is renamed. The schema-publication test reads ../../schemas/cultnet. The
leaf's license-file key (../LICENSE, which Huginn has no file for) is dropped.
Type ids, the epoch and every schema_id string are untouched. Schemas README
and the pipeline section of schemas/cultnet/README.md are rewritten for the
new home; README and AGENTS no longer say the leaf is pinned by git. New test:
the catalogue lists exactly the schema files beside it.
Not yet built or tested; verification follows on Yggdrasil.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A request that fails to encode is a defect in this client, not a transport
failure, so it is ClientError::Unencodable, typed Unencodable at the tool,
instead of the retryable Unavailable. A test reports a non-UTF-8
HUGINN_ENDPOINT as such.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- The client refuses a request whose encoded size exceeds what one RUDP send
carries (65,507 less the 36-byte header and the 6-byte channel id), before
connecting, as ClientError::TooLarge { bytes, limit }. It was reported as
a retryable Unavailable ("Message too long"). The MCP tools surface it as
isError with {"error":"TooLarge","bytes","limit"}.
- Arguments that fail to deserialize are still a tool error, now with the
same typed body as every other one: {"error":"InvalidInput","detail"}.
- A non-UTF-8 EUREKA_INSTANCE or HUGINN_ENDPOINT is reported as not valid
UTF-8 and not as unset.
- Tests: the schema walk asserts no $id or $schema below any tool's root; the
15 s timeout is measured against a silent daemon; the semantic part of a
query is observed on the wire; Internal's and TooLarge's bodies and the
InvalidInput rewrite are pinned; attribution is refused through the MCP
admit; oversize is TooLarge at and one past the limit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The timeout now bounds the whole call: one deadline at call start, every wait
gets what remains, so a chunk-by-chunk deferred body cannot outlive it. The
response's message id and operation are checked against the request. An
envelope-level OperationFailure is ClientError::Rejected, distinct from the
transport's Unavailable, so a retry on Unavailable cannot loop on a permanent
protocol mismatch. Every call disconnects its session, success or failure.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
One call carries one HuginnMindRequest to a daemon over CultNet RUDP on the
operation connection and returns the mind's own HuginnMindResponse. Each call
is its own session and nothing survives it. A Deferred answer is fetched on
that session through cultnet-rs's fetch_content, capped at huginn-mind's
MAX_DEFERRED_BODY_BYTES, and decoded, so a caller never sees the deferral.
Refusals are answers. ClientError::Unavailable is the only error and names the
endpoint. The client opens no store and admits nothing.
Tests run a real daemon in-process on a loopback port over a temporary mind,
plus scripted servers for the failures a daemon cannot be made to produce.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three stub crates following Odin's layout: huginn-mind and eureka-state as
libraries, huginn-daemon as the binary. Edition, license and publish are
workspace-owned. .gitignore gains target/ and drops the four entries that
named build outputs no longer produced here.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>