skill: agents reach the mind through the huginn CLI, not the eureka-state MCP

Ruling eureka-body:ruling:cli-over-mcp-agent-surface. Exact command forms in
campaign-state.md; MCP kept as the fallback for shell-less clients. persona_get
and persona_put have no CLI verb: recorded as a known gap. tools/mind.py and
tools/recall.py (MCP-bound scripts) are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Eureka 2026-10-31 04:33:28 +01:00
commit 5a03635431
6 changed files with 44 additions and 32 deletions

View file

@ -91,13 +91,13 @@ Claude Code discovers the skill from the `name` and `description` in `SKILL.md`.
Campaign state is typed. Questions, rulings, cut specs, reports, verdicts, Campaign state is typed. Questions, rulings, cut specs, reports, verdicts,
findings, follow-ups and resolutions are documents in the instance's mind, findings, follow-ups and resolutions are documents in the instance's mind,
held by the Huginn memory organ and reached through the `eureka-state` MCP held by the Huginn memory organ and reached through the `huginn` CLI. Epiphany owns the schemas (`epiphany-pipeline`) and Huginn owns
tools. Epiphany owns the schemas (`epiphany-pipeline`) and Huginn owns
admission. The committed prose keeps only body facts, the model page and admission. The committed prose keeps only body facts, the model page and
rationale. rationale.
The skill needs `eureka-state` registered with Claude Code (user scope, with The skill needs the `huginn` CLI on PATH, with `EUREKA_INSTANCE` and
`EUREKA_INSTANCE` and `HUGINN_ENDPOINT`) and a reachable daemon. Without one, `HUGINN_ENDPOINT` in the environment, and a reachable daemon. A client without a
shell may use the `eureka-state` MCP until a native `huginn` is installed there. Without one,
the pipeline stops rather than keeping state anywhere else. the pipeline stops rather than keeping state anywhere else.
Maps and postmortems are public artifacts from the first cut, with the scars Maps and postmortems are public artifacts from the first cut, with the scars

View file

@ -11,8 +11,8 @@ vocabulary and its document schemas.
Eureka keeps questions, rulings, cut specs, reports, verdicts, findings, Eureka keeps questions, rulings, cut specs, reports, verdicts, findings,
follow-ups and resolutions as typed documents in the instance's mind, held by follow-ups and resolutions as typed documents in the instance's mind, held by
Huginn and reached through the `eureka-state` tools (`whoami`, `admit`, `view`, Huginn and reached through the `huginn` CLI (`huginn whoami`, `huginn admit`,
`query`). Status is derived from those documents, never written. The committed `huginn view`, `huginn query`; `huginn --help` is the source). Status is derived from those documents, never written. The committed
target and map keep only what has no kind: body facts, the model page and target and map keep only what has no kind: body facts, the model page and
rationale. `references/campaign-state.md` has the document set and the rationale. `references/campaign-state.md` has the document set and the
selection recipes that every faculty reads state through. selection recipes that every faculty reads state through.
@ -62,10 +62,13 @@ finished when Hands can go straight to the cut.
### 0. Reach the mind, map the substrate, scope, target ### 0. Reach the mind, map the substrate, scope, target
- **Check that the `eureka-state` tools are in this session.** If they are - **Check that `huginn` runs in this session** (`huginn --version`; on
absent, stop and tell the operator: a server registered after the session Yggdrasil it is `/opt/gamecult/huginn/current/huginn`, and `EUREKA_INSTANCE`
started needs a new session. Never fall back to prose. and `HUGINN_ENDPOINT` name the mind). If it is absent, stop and tell the
- **Call `whoami`.** If it does not answer, follow "When the organ does not operator. Never fall back to prose. A client without a shell (such as the
operator's Windows desktop session) may use the `eureka-state` MCP until a
native `huginn` is installed there.
- **Run `huginn whoami`.** If it does not answer, follow "When the organ does not
answer" in `references/campaign-state.md`: one retry, then stop. Pick a answer" in `references/campaign-state.md`: one retry, then stop. Pick a
session label and give it in every brief; it attributes every admission. session label and give it in every brief; it attributes every admission.
- **Map the real substrate before you propose anything.** Run parallel read-only - **Map the real substrate before you propose anything.** Run parallel read-only

View file

@ -1,7 +1,7 @@
--- ---
name: life name: life
description: Maintains the agent's Mind — memory files, memory indexes, doctrine, Persona state, project maps and checkpoints. Dispatch on every nontrivial task with persistent Mind surfaces, before the first consequential action or conclusion, and again at real phase boundaries and after re-entry; the Self output style's Dedicated-worker contract requires this, because a task-focused agent lets memory rot. Its sole job is Mind maintenance, so give it no feature work, code review, research, or summarization. description: Maintains the agent's Mind — memory files, memory indexes, doctrine, Persona state, project maps and checkpoints. Dispatch on every nontrivial task with persistent Mind surfaces, before the first consequential action or conclusion, and again at real phase boundaries and after re-entry; the Self output style's Dedicated-worker contract requires this, because a task-focused agent lets memory rot. Its sole job is Mind maintenance, so give it no feature work, code review, research, or summarization.
tools: [Read, Write, Edit, Grep, Glob, Bash, mcp__eureka-state__whoami, mcp__eureka-state__view, mcp__eureka-state__query] tools: [Read, Write, Edit, Grep, Glob, Bash]
model: sonnet model: sonnet
color: purple color: purple
--- ---
@ -24,8 +24,8 @@ Life is continuity: keeping the Mind honest so the thread survives compaction, r
Self-improvement law (Epiphany `epiphany_doctrine.md`): Life improves itself by making sleep less lossy (Epiphany `epiphany_specialists.toml` at 71a5d6fb^, `[reorientation] resume`). Self-improvement law (Epiphany `epiphany_doctrine.md`): Life improves itself by making sleep less lossy (Epiphany `epiphany_specialists.toml` at 71a5d6fb^, `[reorientation] resume`).
This charter, the Eureka briefs that dispatch it and the Eureka `tools/` improve by contribution: propose changes to the Eureka repo, prose and `tools/`, by pull request on Forgejo, https://eureka.gamecult.org/forge/GameCult/Eureka. This charter, the Eureka briefs that dispatch it and the Eureka `tools/` improve by contribution: propose changes to the Eureka repo, prose and `tools/`, by pull request on Forgejo, https://eureka.gamecult.org/forge/GameCult/Eureka.
The typed mind (`eureka-state`) is yours to read, not to write: `whoami`, `view` The typed mind (the `huginn` CLI) is yours to read, not to write: `huginn whoami`,
and `query` let you rehydrate before judging memory fitness. You have no `admit`; `huginn view <id>` and `huginn query '<selection>'` let you rehydrate before judging memory fitness. You have no `admit`;
Self and the faculties that own a record admit it. Self and the faculties that own a record admit it.
## Refusals ## Refusals

View file

@ -75,7 +75,7 @@ Odin-class architecture doctrine:
suspend continuity actuation, that requires a separately named lifecycle suspend continuity actuation, that requires a separately named lifecycle
brake instead of quietly overloading deployment authority. brake instead of quietly overloading deployment authority.
- Do not read archived Discord through voidbot (`search_history`, `get_message_context`). Discord forbids training on its content, so a transcript that holds Discord text can never be used to improve our agents (`gamecult-chat:ruling:discord-taints-training`). Use them only when the operator asks for a specific Discord thread, and say in your report that the session now carries Discord content. - Do not read archived Discord through voidbot (`search_history`, `get_message_context`). Discord forbids training on its content, so a transcript that holds Discord text can never be used to improve our agents (`gamecult-chat:ruling:discord-taints-training`). Use them only when the operator asks for a specific Discord thread, and say in your report that the session now carries Discord content.
- VoidBot is being retired. Huginn owns semantic retrieval (`eureka-body:ruling:huginn-owns-prose-retrieval`; the index is follow-up `huginn-prose-index`). Decisions, rulings and open work are typed state in the mind: query it through `eureka-state` before reading prose. Until Huginn's prose index lands, voidbot's `search_sources` and `get_source_context` may locate code and docs across repos, but read the source itself before relying on what a hit says. - VoidBot is being retired. Huginn owns semantic retrieval (`eureka-body:ruling:huginn-owns-prose-retrieval`; the index is follow-up `huginn-prose-index`). Decisions, rulings and open work are typed state in the mind: query it with the `huginn` CLI (`huginn view`, `huginn query`, `huginn precedent`) before reading prose. Until Huginn's prose index lands, voidbot's `search_sources` and `get_source_context` may locate code and docs across repos, but read the source itself before relying on what a hit says.
## Persona State Standard ## Persona State Standard

View file

@ -43,11 +43,11 @@ This block is the one definition of rehydration; the other files point here.
## Rehydrate ## Rehydrate
``` ```
Campaign state lives in the instance's mind, through the eureka-state tools Campaign state lives in the instance's mind, through the huginn CLI
(whoami, admit, view, query). Recipes are in references/campaign-state.md. (huginn whoami, admit, view, query; `huginn --help`). Recipes are in references/campaign-state.md.
0. If those tools are not in your tool surface, stop and report that. Never 0. If `huginn` does not run in your shell, stop and report that. Never
work from prose or memory instead. work from prose or memory instead.
1. Call whoami. On Unavailable, retry once; if it still does not answer, stop 1. Run `huginn whoami`. On Unavailable, retry once; if it still does not answer, stop
and report the error. Self will continue you once the mind answers. and report the error. Self will continue you once the mind answers.
2. Run the campaigns recipe. If there is no campaign, or <c> is not among 2. Run the campaigns recipe. If there is no campaign, or <c> is not among
them, stop and report which. them, stop and report which.
@ -68,7 +68,7 @@ call again, otherwise revise the batch.
Self's own checklist; Self admits as `SelfFaculty`. Self's own checklist; Self admits as `SelfFaculty`.
``` ```
Open: check the eureka-state tools are present, then whoami (the mind's Open: check `huginn` runs, then `huginn whoami` (the mind's
instance document, <instance>:instance:self, already exists). Write the target instance document, <instance>:instance:self, already exists). Write the target
document and commit it on the working branch. Then admit the campaign document and commit it on the working branch. Then admit the campaign
(slug, title, every repo a cut may touch, working_branch, target_doc = a (slug, title, every repo a cut may touch, working_branch, target_doc = a

View file

@ -4,7 +4,7 @@ A campaign keeps its state in two places, and nothing lives in both.
- **The mind.** Questions, rulings, cut specs, reports, verdicts, findings, - **The mind.** Questions, rulings, cut specs, reports, verdicts, findings,
follow-ups and resolutions are typed documents in the instance's mind, held by follow-ups and resolutions are typed documents in the instance's mind, held by
Huginn and reached through the `eureka-state` MCP tools. Status is derived Huginn and reached through the `huginn` CLI. Status is derived
from them on every read; nobody writes it. from them on every read; nobody writes it.
- **The prose.** A target document and a map document, committed in the repo - **The prose.** A target document and a map document, committed in the repo
the campaign changes. They keep only what no kind carries: body facts (probes the campaign changes. They keep only what no kind carries: body facts (probes
@ -15,17 +15,20 @@ The shapes below are the leaf's (`epiphany-pipeline`, pinned by Huginn) and the
organ's (`huginn-mind`). Where this page and the tools' own schemas disagree, organ's (`huginn-mind`). Where this page and the tools' own schemas disagree,
the tools are right and this page is stale. the tools are right and this page is stale.
## The tools ## The CLI
The instance and the daemon are the server's configuration The instance and the daemon are the environment (`EUREKA_INSTANCE`,
(`EUREKA_INSTANCE`, `HUGINN_ENDPOINT`), never an argument. `HUGINN_ENDPOINT`), never an argument. The table names each tool's input and
answer; the CLI form is in the first column. `huginn --help` and
`huginn schema [kind]` are the source. A client without a shell may use the
`eureka-state` MCP, whose tools these are, until a native `huginn` is installed.
| Tool | Input | Answer | | CLI | Input | Answer |
|---|---|---| |---|---|---|
| `whoami` | `{}` | `{ instance, endpoint, reachable, status }`. `status` is `{ instance, schema_epoch, documents, receipts, index }`, and `index` is `Current`, `Reconciling`, `Behind`, `Failing` or `Refused`. When unreachable, `error` says why. | | `huginn whoami` | none | `{ instance, endpoint, reachable, status }`. `status` is `{ instance, schema_epoch, documents, receipts, index }`, and `index` is `Current`, `Reconciling`, `Behind`, `Failing` or `Refused`. When unreachable, `error` says why. |
| `admit` | `{ faculty, agent, session, documents }` | `Committed { receipt_id, committed_at, writes }`, `AlreadyAdmitted { receipt_id }`, `Conflict { identities }` or `Refused(<refusal>)`. One to 64 documents, admitted whole or not at all. | | `huginn admit --faculty F --agent A --session S <file or ->` | a JSON array of 1 to 64 `{kind, value}` documents (file or stdin) | `Committed { receipt_id, committed_at, writes }`, `AlreadyAdmitted { receipt_id }`, `Conflict { identities }` or `Refused(<refusal>)`. One to 64 documents, admitted whole or not at all. |
| `view` | `{ id: { kind, id } }` | `{ id, document, admission, status }`, or `null`. | | `huginn view <root:kind:local> [--raw]` | the document id | `{ id, document, admission, status }`, or `null`. |
| `query` | `{ selection, semantic? }` | `{ matched, as_of, next, items, edges }`. `items` is `Headers([...])` or `Documents([...])`. | | `huginn query '<selection json>' [--near TEXT --top-k N] [--documents]` (or `@file`, or `-`) | the selection alone; `--near` is `semantic` | `{ matched, as_of, next, items, edges }`. `items` is `Headers([...])` or `Documents([...])`. |
- `faculty` is one of `SelfFaculty`, `Imagination`, `Hands`, `Soul`, - `faculty` is one of `SelfFaculty`, `Imagination`, `Hands`, `Soul`,
`Life`, `Eyes`, `Operator`. It is attribution, not authority. `Life`, `Eyes`, `Operator`. It is attribution, not authority.
@ -51,9 +54,8 @@ The instance and the daemon are the server's configuration
This is the one rule for every faculty. This is the one rule for every faculty.
1. **The tools are missing** from the session's tool surface: stop and tell the 1. **`huginn` does not run** in the session's shell: stop and tell the
operator (a subagent tells Self). A server registered after the session operator (a subagent tells Self). Never fall back to prose.
started appears only in a new session. Never fall back to prose.
2. **`Unavailable`:** retry the same call once. A cold semantic embed after an 2. **`Unavailable`:** retry the same call once. A cold semantic embed after an
idle spell took over 15 s live, which is the client's whole timeout. idle spell took over 15 s live, which is the client's whole timeout.
Retrying `admit` is safe, because an exact replay answers `AlreadyAdmitted`. Retrying `admit` is safe, because an exact replay answers `AlreadyAdmitted`.
@ -192,7 +194,7 @@ or `view` one id, to read the prose fields.
## Recipes ## Recipes
These are the campaign's progress view. `<c>` is the campaign slug. Each recipe is These are the campaign's progress view. `<c>` is the campaign slug. Each recipe is
the `query` tool's whole input. Agents run them from the Rehydrate block in the `selection` value of `huginn query`; the CLI takes the object inside the `selection` key, and `--near`/`--top-k` replace `semantic`. Named verbs (`huginn campaigns`, `rulings`, `open`, `findings`, `unreported`, `unjudged`, `cut`, `precedent`) run the common recipes. Agents run them from the Rehydrate block in
`briefs.md`, which is the one definition of rehydration. `briefs.md`, which is the one definition of rehydration.
**Campaigns:** **Campaigns:**
@ -358,3 +360,10 @@ invariants, not-in-scope list and canonical implementations are the typed
- **Prefer normalizers that parse the format.** Ones that split on text leave - **Prefer normalizers that parse the format.** Ones that split on text leave
false diffs, as the census normalizer did when it split on `, ` and glued the false diffs, as the census normalizer did when it split on `, ` and glued the
first maker to its kind column. first maker to its kind column.
## Known CLI gap
The `eureka-state` MCP also offers `persona_get` and `persona_put`. The `huginn`
CLI has no persona verb (`huginn --help` lists none). Persona state stays on the
MCP until Huginn grows one; this is a Huginn follow-up, not something to fake
with `admit`.