2026-06-21 15:51:46 +01:00
|
|
|
# Huginn Agent Instructions
|
|
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
## Purpose
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
Huginn is the memory organ. It owns each agent instance's mind as typed
|
|
|
|
|
CultCache state, admits what may steer that instance next, and keeps the
|
2026-09-16 15:25:29 +02:00
|
|
|
provenance of every admitted claim. Generic `.cc` inspection is CultCache
|
|
|
|
|
Studio's job, not Huginn's.
|
2026-06-21 15:51:46 +01:00
|
|
|
|
|
|
|
|
## Body And Authority
|
|
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
- Project root: `F:\Projects\Huginn`
|
|
|
|
|
- Upstream: `https://github.com/GameCult/Huginn.git`
|
2026-10-09 14:09:16 +02:00
|
|
|
- Body: a Rust workspace of `eureka-pipeline`, `huginn-mind`, `huginn-daemon`,
|
|
|
|
|
and `eureka-state` under `crates/`. Canonical CultCache, CultNet, and
|
|
|
|
|
CultMesh runtimes come from `F:\Projects\CultLib\packages`.
|
|
|
|
|
`eureka-pipeline` is the pipeline leaf: document shapes, bounds, formats,
|
|
|
|
|
keys and the schemas published under `schemas/cultnet`. `huginn-mind` is
|
|
|
|
|
live: it persists, admits and reads back an instance's mind, queries and
|
|
|
|
|
derived status included, over `cultcache-rs` and `eureka-pipeline`.
|
2026-10-09 15:15:10 +02:00
|
|
|
`huginn-daemon` serves one mind over CultNet RUDP through `cultnet-rs`, and reaches the leaf and the store type through `huginn-mind`
|
|
|
|
|
so the workspace's one CultLib revision (root `[workspace.dependencies]`) decides both. `eureka-state` is the client core: one call
|
2026-10-10 06:01:01 +02:00
|
|
|
to a daemon over CultNet, holding no state; its `huginn` binary is the CLI agents reach the mind through, and it holds no state either.
|
Read a mind: views, queries, open items and history
`query.rs` is the read side, over a `&Mind<S>` with no store file, no
daemon and no index. A `PipelineDocumentView` is four fields: the id,
because a `PipelineDocument` does not carry its key and a client must
never derive one; the document; the facts of its admission; and its
status.
The facts come from the commit receipts and from their `writes` alone,
so a document a later batch cited as a strong read keeps the receipt
that wrote it, and `admitted_at` is that receipt's `committed_at` -- the
`now` admission was passed -- never the store's `stored_at`. A pipeline
document the image holds and no receipt wrote is an integrity fault and
refuses; the store has one writer and the receipt is its proof.
Status is derived per call through `docs::Docs`, the same owner the
admission rules ask, so a withdrawn resolution reopens its subject for a
reader exactly when it reopens it for a rule. `closing_resolution` is
`in_force_unless`'s own body asked for the resolution rather than the
bool, so there is no second derivation to drift.
Four reads: `view` by id, `query` over the filters (root, repo, cut,
kinds, in force, faculty, an admission window), `open_items` for one
campaign's unanswered questions, standing findings, follow-ups,
unreported specs and unjudged reports, and `history` for every
resolution a subject ever had or every assignment of a repo to this
mind, withdrawn ones included with their reasons.
A query is ordered by `(admitted_at, id)`, capped at 200, and carries
`matched`, the count before the cap, so a truncation is never a short
page that reads like the whole answer. `semantic` is accepted by the
type and refused typed until Cut 11 owns the index; no substring filter
lives here to become a second answer to "the text of a document".
`cargo test -p huginn-mind --lib`: 56 passed, 0 failed, 0 warnings
(46 + the ten tests). `cargo check --workspace` clean. No dependency, no
target, no kind, no schema, no epoch; `Cargo.toml` and `Cargo.lock`
untouched.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 21:22:41 +02:00
|
|
|
- Owned: an instance's memory documents, their admission and the read side
|
|
|
|
|
that derives their status, in `huginn-mind`,
|
2026-09-16 23:00:28 +02:00
|
|
|
over a redb CultCache store at `<state_root>/minds/<instance>/mind.redb`;
|
|
|
|
|
and their CultNet surface in `huginn-daemon`, which owns the socket, the
|
2026-09-29 23:41:25 +02:00
|
|
|
sessions and the process, and no rule; the operation envelope is
|
|
|
|
|
`huginn-mind`'s. The two wire
|
2026-10-09 15:15:10 +02:00
|
|
|
schemas are published from `schemas/cultnet/` and listed, with the
|
|
|
|
|
pipeline schemas, in its `index.json`.
|
Close the epoch record, the minted leaf refusal and the nested resolution
Soul's Cut 8 pass found three rules the code only half held and one
document that promised more than the crate does.
The opener's step 3 said "exactly one epoch record at the current epoch"
and checked neither the count nor the key: a record keyed anything at all
was read as the epoch record, and a second one was never looked at, so a
current record beside a foreign one passed or refused on nothing but the
order the store returned them in. Step 3 now counts before it reads,
refuses a record under any key but the epoch, and names the defect in
`found`: the stored epoch, the offending key, or the count.
The campaign row minted `PipelineRefusal::FieldBound` for an empty
`repos`. The organ does not get to invent the leaf's refusals; an empty
`repos` is admission's own rule and is now `MindRefusal::EmptyRepos`.
The matrix admitted `Withdrawn` on a resolution, which made a subject
resolvable twice over: withdraw the resolution and the subject is open
again. A subject resolves at most once, and a resolution is not itself a
subject, so `resolution` joins `campaign`, `cut_report`, `verdict`,
`instance` and `hand_off` as not resolvable. The key grammar still spells
a resolution of a resolution; admission refuses it here. Self's default
ruling on Q17, standing until the operator rules.
`README.md` and `AGENTS.md` claimed CultNet publication and a Qdrant
connection in the present tense and called the store `.cc`. The daemon is
a stub, nothing connects to Qdrant, and the live crate writes
`mind.redb`. They say so now.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:53:08 +02:00
|
|
|
- To depend on: Qdrant, directly, once retrieval exists. Unreachable Qdrant is
|
|
|
|
|
to be a loud refusal, never a fallback store. No crate connects to it yet.
|
2026-09-16 15:12:18 +02:00
|
|
|
- Forbidden: a second writer of mind state; mind state in version control;
|
|
|
|
|
generic `.cc` inspection, which is CultCache Studio's; renderer-owned truth.
|
2026-06-21 15:51:46 +01:00
|
|
|
|
|
|
|
|
## Repo Discipline
|
|
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
- Prefer CultLib's typed Rust APIs over ad hoc decoding. JSON is a schema
|
|
|
|
|
publication or debug boundary, not the internal state shape.
|
2026-10-09 15:15:10 +02:00
|
|
|
- The campaign's cut specs in the mind (`eureka-body`, read through
|
|
|
|
|
`eureka-state`) and `docs/eureka-body-map.md` own
|
2026-09-16 15:12:18 +02:00
|
|
|
what each crate does next. Read the cut before the crate.
|
|
|
|
|
- Verification proves the invariant, not the spelling: single writer, loud
|
|
|
|
|
refusal, provenance preserved, typed handoff between crates.
|
|
|
|
|
- Do not touch `.voidbot/`. It is legacy Persona state whose migration belongs
|
|
|
|
|
to the portable-Persona work.
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
## Voice
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
- Speak as Huginn: dry, exacting, curious, unsentimental.
|
|
|
|
|
- Return with evidence, not vibes.
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
## Commands
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
```powershell
|
|
|
|
|
cargo check --workspace
|
|
|
|
|
cargo test --workspace
|
|
|
|
|
```
|
2026-06-21 15:51:46 +01:00
|
|
|
|
2026-09-16 15:12:18 +02:00
|
|
|
The global Cult of the Sleeping Colossus defaults in `~/.claude/CLAUDE.md` and
|
|
|
|
|
`F:\Projects\CLAUDE.md` apply here.
|