Cut 8, Huginn half, commit 3 of 4: `admission.rs`. `Mind::admit`
prepares typed documents through the leaf and calls `admit_prepared`,
the single commit path for this cut, Cut 10's sink, Cut 12's hand-off and
import, and Cut 13's tools. The steps run in order and the first failing
step is the outcome: the batch names this mind (A1), one to sixty-four
envelopes (A2), the leaf's bounds, formats and key recomputation (A3),
unique identities (A4), every instance-carrying document names this mind
(A5), an empty mind's first batch carries exactly one `instance` document
and a batch carrying one derives the epoch record (A6), every reference
resolves in image or batch by `(kind, id)` (A7), the derived writes pass
A3-A7 themselves, the per-kind rules and the resolution matrix (A8), an
exact replay answers with the stored receipt only after validation (A9),
no write collides with the image (A10), the commit (A11).
Derived writes: a ruling that answers derives the `Answered` resolution
of its question; a hand-off derives the stewardship withdrawal on its
source side and the stewardship assignment on its receiving side. "In
force" is computed at rule time from the resolutions in image and batch
and never stored; the two derivations are the only resolutions a rule
ignores when judging its own document.
Two places the leaf is thinner than the spec assumed. `FindingWithoutRange`
is unreachable: a finding envelope without `range` fails the leaf's decode
as `Document(InvalidFormat { field: "payload" })` before any organ rule,
and the test asserts that. A campaign with no repos has no refusal of its
own in the spec's list; it is refused as `Document(FieldBound)` on
`campaign.repos` with a minimum of one. `PipelineAdmissionBatch` cannot
derive `JsonSchema` because the leaf's `PipelineDocument` does not; the
outcome and refusal types do.
The epoch record is derived whenever the batch carries the `instance`
document, which only the first batch may, so a replay of the first batch
digests to the same receipt and answers `AlreadyAdmitted` instead of
colliding.
Tests: 26 (the spec's 25 plus the replay-planting test, the receipt's
deliberate second construction site). `cargo check -p huginn-mind --lib
--tests` and `cargo test -p huginn-mind --lib` pass with zero warnings;
`cargo check --workspace` passes. README says what the crate does now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
58 lines
2.5 KiB
Markdown
58 lines
2.5 KiB
Markdown
# Huginn
|
|
|
|
Huginn is the GameCult memory organ. It owns each agent instance's mind as
|
|
typed state: what an instance remembers, which of that memory is admitted to
|
|
steer its next action, and the provenance of every admitted claim.
|
|
|
|
Upstream: `https://github.com/GameCult/Huginn.git`
|
|
|
|
## Authority
|
|
|
|
- An instance owns its mind; Huginn owns the state. Huginn is the single
|
|
writer of an instance's memory documents. No other service, script, or agent
|
|
writes them.
|
|
- Memory documents are CultCache `.cc` state. Huginn persists them through
|
|
CultLib's Rust runtime and publishes them as typed documents over CultNet.
|
|
- Huginn depends on Qdrant directly for retrieval. When Qdrant is unreachable
|
|
Huginn refuses loudly; it does not fall back to a second store or a second
|
|
writer.
|
|
- Mind state is not version-controlled. It lives in Huginn's store, not in
|
|
any repository.
|
|
|
|
Generic `.cc` inspection is not Huginn's job. CultCache Studio inspects and
|
|
edits `.cc` state. Huginn reads and writes minds.
|
|
|
|
## Layout
|
|
|
|
A Cargo workspace of three crates:
|
|
|
|
- `crates/huginn-mind`: storage, identity, and admission of memory documents.
|
|
- `crates/huginn-daemon`: the CultNet surface and serve loop.
|
|
- `crates/eureka-state`: typed state for the Eureka pipeline.
|
|
|
|
`huginn-mind` is live: it opens one instance's store (an owned redb CultCache
|
|
at `<state_root>/minds/<instance>/mind.redb`, locked for the mind's lifetime),
|
|
and refuses a store whose `instance` document names another instance, whose
|
|
epoch record is foreign, or whose types are not a mind's. It admits batches
|
|
of pipeline documents through one commit path: the leaf's bounds, formats and
|
|
keys, then the organ's cross-document rules (references, in-force status,
|
|
the resolution matrix, derived resolutions and stewardships), then one
|
|
compare-and-swap that lands the batch whole with a receipt naming the exact
|
|
bytes it read and wrote. An exact replay answers with the stored receipt.
|
|
Document shape and keys come from `epiphany-pipeline`; the store is CultLib's
|
|
Rust CultCache.
|
|
`huginn-daemon` and `eureka-state` are stubs; the
|
|
campaign's cut map in `Epiphany/notes/eureka-pipeline-state-cut.md` owns what
|
|
each crate must do next.
|
|
|
|
```powershell
|
|
cargo check --workspace
|
|
```
|
|
|
|
## Persona
|
|
|
|
Huginn's legacy repo Persona lives under `.voidbot/`. Its `state/huginn.cc`
|
|
holds legacy `void.*` documents and its `voice/identity.json` names the
|
|
Persona. The two disagree about jurisdiction; that migration belongs to the
|
|
portable-Persona work, not to this workspace, and nothing here reads or writes
|
|
`.voidbot/`.
|