961 lines
91 KiB
Markdown
961 lines
91 KiB
Markdown
# eureka-body: map (Imagination, 2026-10-08)
|
|
|
|
Status: map, Imagination (`imagination-eureka-body`), session `self-2026-10-08`.
|
|
Campaign `eureka-body` in Eureka's mind (instance `eureka`). Target in force
|
|
`eureka-body:target:r1`, whose doc is Huginn `docs/eureka-self-cut.md` at
|
|
`570f369` (map r4 of 2026-10-01). This page keeps body facts, the model page
|
|
(step 0b) and rationale. Questions, cut specs, follow-ups and rulings are typed
|
|
documents in the mind; read them by id. Self commits this page where the
|
|
target doc lives (Huginn `docs/`), probably as `docs/eureka-body-map.md`.
|
|
|
|
Revised 2026-10-09 (Modeling, session `self-2026-10-09-morning`) after
|
|
`leaf-into-huginn` (Huginn `afc35f9`) and the Epiphany body teardown
|
|
(gamecult-ops `9c12adb`; leftovers in follow-up
|
|
`eureka-body:follow_up:epiphany-body-leftovers`). Pinned heads and facts F1-F14 are
|
|
as read on 2026-10-08 and keep their tense; each carries a note where a cut has since
|
|
changed it. F15-F17 are new.
|
|
|
|
Revised again on 2026-10-09 by Imagination (`imagination-brake-stop`, session
|
|
`self-2026-10-09-eureka`) at Huginn `df7507b`, after leaf-into-huginn, mind-authority,
|
|
mind-control-store and run-kind had merged. New facts are F18-F20, which name the
|
|
owner of the brake stop. The Brake, Units and run rows changed, and a rationale
|
|
section was added.
|
|
|
|
Revised again on 2026-10-09 by Imagination (`imagination-launch-r3`, session
|
|
`self-2026-10-09-eureka`) at the mind-launch head `8dee875`, after Soul's verdict
|
|
`eureka-body:verdict:cut-mind-launch.s1` falsified that cut with nine findings. New fact
|
|
F21. The run, Repetition breaker, Brake and Units rows changed, and the rationale gained
|
|
"Who decides one live run, and who ends a dead one" and "What the breaker counts".
|
|
Specs: `cut-run-live-admission.r1`, `cut-mind-launch.r3`, `cut-mind-wake.r3`,
|
|
`cut-brake-stop.r2`.
|
|
|
|
Revised again on 2026-10-10 by Imagination (`imagination-mind-units`, session
|
|
`self-2026-10-10-eureka`) at Huginn `0c6f6cb` and gamecult-ops `6b4a874`, for cut
|
|
`mind-units-install`. New fact F22. New section "The mind units: identity, lifecycle and
|
|
authority", written before the cut was mapped. Specs: `cut-mind-unit-gate.r1` (Huginn) and
|
|
`cut-mind-units-install.r1` (gamecult-ops). Questions: `mind-unit-names` and
|
|
`mind-unit-start-grant`.
|
|
|
|
Revised again on 2026-10-22 by Imagination (`imagination-self-run`, session
|
|
`self-2026-10-22-eureka-c2a`) at Huginn `70d0cef`, for cut `mind-self-run`. New facts F23-F25
|
|
(Claude Code session ids, resume and stream usage, probed on Starfire; the live-request half was
|
|
blocked by an expired CLI credential). The stale "Undone" list is replaced by "Cut sequence",
|
|
and "How a Self run is carried" is new. Specs: `cut-mind-self-run.r1`,
|
|
`cut-mind-body-riders.r1`. Questions: `first-self-run-starter`, `self-run-permissions`. Probe
|
|
outputs: `F:\Projects\eureka-handoff-aux-2026-10-22\imag-self-run\`.
|
|
|
|
Revised again on 2026-10-28 by Imagination (`imagination-kit-lift`, session
|
|
`self-2026-10-28-eureka`) at CodexConnector `fd7cec4`, Ghostlight `c43eb54` and ModelConnector
|
|
`1cf879f`, for cut `connector-kit-lift`. New facts F26-F29, new rationale "Where the kit lift's
|
|
cut line falls", path B refreshed. Spec: `cut-connector-kit-lift.r1`. Questions:
|
|
`connector-kit-relicense` (blocks the spec), `codex-connector-fate`. The baseline probe log was
|
|
a session scratchpad file and is not kept; its counts are in F26.
|
|
|
|
Revised again on 2026-10-28 by Imagination (`imagination-contract-v3`, session
|
|
`self-2026-10-28-eureka`) at ModelConnector `ec0519d` and CultLib `a4eae90`, for cut
|
|
`connector-contract-v3`. New facts F30-F31 (probes on Yggdrasil), new rationale "Where the
|
|
contract v3 cut line falls", B3 split into B3a-B3c. Spec: `cut-connector-contract-v3.r2`.
|
|
Questions: `connector-v3-wire`, `connector-v2-coexistence` (both raised in r1, which r2
|
|
superseded only to split two context windows; they block r2). Follow-up:
|
|
`cultnet-binary-operation-payload`. Research: Huginn `725f5a5`
|
|
`docs/research/connector-contract-v3-prior-art.md`.
|
|
|
|
Revised again on 2026-10-28 by Imagination (`imagination-reasoning-item`, session
|
|
`self-2026-10-28-eureka`) at ModelConnector `bf958fc` (B3a landed), for cut
|
|
`connector-reasoning-item`. New fact F32 (probe on Yggdrasil), the B3b bullet of "Where the
|
|
contract v3 cut line falls" made exact, path B line 3b given its spec. Spec:
|
|
`cut-connector-reasoning-item.r1`. No question: the ruling and research section 5 settle every
|
|
choice the cut makes. Research reused unchanged.
|
|
|
|
Revised again on 2026-10-28 by Imagination (`imagination-connector-spend`, session
|
|
`self-2026-10-28-eureka`) at ModelConnector `1d51e71` (B3b landed), for cut `connector-spend`.
|
|
New fact F33 (probes on Yggdrasil), the B3c bullet of "Where the contract v3 cut line falls"
|
|
made exact, path B line 3c given its spec and B4's riders carried. Spec:
|
|
`cut-connector-spend.r1`. Question: `connector-spend-ceiling` (blocks the spec). Follow-up:
|
|
`connector-spend-readout`. Research reused unchanged (`725f5a5` section 2 is the ceiling
|
|
question's evidence).
|
|
|
|
Revised again on 2026-10-28 by Imagination (`imagination-claude-connector`, session
|
|
`self-2026-10-28-eureka`) at ModelConnector `e0c0832` (B3c landed), for map line B4. New fact F34
|
|
(probes on Yggdrasil), rationale "Where the Claude connector cut line falls", path B line 4 split
|
|
into B4a-c. Spec: `cut-claude-backend.r1` (B4a). Question: `claude-connector-credential` (blocks
|
|
the spec). Follow-up: `claude-byte-bound-live-check`. Research: Huginn `f237623`
|
|
`docs/research/claude-connector-prior-art.md`.
|
|
|
|
Revised again on 2026-10-29 by Modeling (`modeling-claude-code-backend`, session
|
|
`self-2026-10-29-eureka`) at ModelConnector `200933f`, after B4a landed as `claude-code-backend`
|
|
(spec `cut-claude-code-backend.r1`; cut report `h2`, Soul verdict `s2`). Ruling
|
|
`claude-connector-via-claude-code` answered question `claude-connector-credential` and withdrew
|
|
spec `cut-claude-backend.r1`. New fact F35. The B4 rationale and path B line 4 are rewritten
|
|
(B4a landed, B4d added, the Console-key backend deferred), the spend-ledger row of the model
|
|
page changed and a Claude connector backend row was added. F34's repo-state sentence keeps its
|
|
tense.
|
|
|
|
## Pinned heads (fetched 2026-10-08 ~12:10 UTC)
|
|
|
|
| Repo | Ref | Commit | Note |
|
|
| --- | --- | --- | --- |
|
|
| Huginn | `origin/main` = local `main`, `F:\Projects\Huginn`, clean | `6b496eb` | last commit 2026-10-02; deployed daemon is `107552d` (docs-only diff to main) |
|
|
| Epiphany | `origin/main` | `ef956865` | was Huginn's leaf pin (no pin since `afc35f9`); local checkout is on `codex/eureka-pipeline-state` `4006b14b`. GitHub `isArchived: false` |
|
|
| CodexConnector | `origin/main` | `3ddc12e` | local checkout is on `codex/ghostlight-release-binding` `6519289`; Ghostlight pins `68fe94b` |
|
|
| gamecult-ops | `origin/main` | `7e23387` | clean |
|
|
| Bifrost | `origin/main` | `160fac2` | clean |
|
|
| Eureka (forge) | `main` | `0bb414d` | scratch clone, removed after |
|
|
| Idunn | `origin/main` | `6667f0f` | read only; not a campaign repo |
|
|
|
|
## Body facts
|
|
|
|
Each line: what was run, where, result.
|
|
|
|
- **F1 Huginn never left Epiphany (at 6b496eb; cut at `afc35f9`, no build edge remains).** `grep epiphany crates/*/Cargo.toml` (Huginn 6b496eb):
|
|
`crates/huginn-mind/Cargo.toml:22` pins `epiphany-pipeline` by git at Epiphany
|
|
`ef956865`. `Cargo.lock:376-378` carries the git source. The map-r4 cut
|
|
`leaf-into-huginn` was never specified; no `cut_spec` for it exists in any
|
|
campaign (query of cut_spec headers under `eureka-substrate` and `eureka-body`).
|
|
- **F2 Leaf users in Huginn.** `pub use epiphany_pipeline;` at
|
|
`crates/huginn-mind/src/lib.rs:62`; direct `use epiphany_pipeline` in huginn-mind
|
|
`admission.rs:33` (26 mentions), `docs.rs:9`, `fixtures.rs:7`, `index.rs:10,157`,
|
|
`mind.rs:16` (9), `query.rs:28,624`, `receipt.rs:19,50-52,314`, `refusal.rs:6`,
|
|
`rows.rs:15`, `wire.rs:9`; through the re-export
|
|
`huginn_mind::epiphany_pipeline::` in eureka-state `src/lib.rs:29`, `src/main.rs:25`,
|
|
`tests/client.rs:17`, `tests/common/mod.rs:16`, `tests/mcp.rs:14,539`; huginn-daemon
|
|
`src/daemon.rs:7,220,688,718,747`, `src/index/mod.rs:102`, `src/semantic_tests.rs:13`,
|
|
`src/serve.rs:71,551`. Prose: `README.md:64`, `AGENTS.md:18`.
|
|
- **F3 The leaf at the pin (now Huginn `crates/eureka-pipeline`, `afc35f9`).** Epiphany `ef956865`: `epiphany-pipeline/Cargo.toml`
|
|
(lib `epiphany_pipeline`, deps anyhow, chrono, cultcache-rs at CultLib `8fc74c7`
|
|
= Huginn's own CultLib pin, rmp-serde, schemars, serde; dev serde_json),
|
|
`epiphany-pipeline/src/lib.rs` (schema-publication test reads
|
|
`CARGO_MANIFEST_DIR/../schemas/cultnet` at lib.rs:2725). `schemas/cultnet/` holds
|
|
13 `epiphany.pipeline.*.v2` schemas, `epiphany.work_organ_state.v0`,
|
|
`gamecult.persona_state.v0`, `index.json`, README; `schemas/README.md`.
|
|
- **F4 Mind deployment.** `ssh yggdrasil`: `huginn.service` active, ExecStart
|
|
`/opt/gamecult/huginn/current/huginn-daemon --state-root /var/lib/gamecult/huginn
|
|
--instance eureka --bind 10.77.0.1:17872 ...`; `current ->
|
|
releases/107552dc...` (Huginn merge of huginn-admission-rules; on 2026-10-08 main added docs only, and since then main has moved code: see F17).
|
|
UFW admits 17872/udp on wg-gamecult from 10.77.0.2 only (runbook
|
|
`huginn-yggdrasil.md:38,124`). The daemon has no peer authentication
|
|
(`serve.rs`: one session per peer, `max_peers = 256`); any reachable peer admits
|
|
as any faculty.
|
|
- **F5 Epiphany residue on Yggdrasil (12:13 UTC, before the teardown; what the teardown left is follow-up `eureka-body:follow_up:epiphany-body-leftovers`).** Units `epiphany.service`,
|
|
`epiphany-swarm.service`, `epiphany-heartbeat.service` inactive/dead;
|
|
`epiphany-model-connector.service` loaded, disabled. Users `epiphany` (988; groups
|
|
epiphany-state, bifrost-feedback-readers) and `epiphany-model` (984; group
|
|
gamecult-model); no process runs as either. Roots and sizes: `/srv/epiphany` 6.8G,
|
|
`/srv/epiphany-model-connector` 16G, `/var/lib/gamecult/epiphany` 1.9G (body.cc,
|
|
heartbeat.cc, codex-home, artifacts, capstones), `/var/lib/gamecult/epiphany-model-connector`
|
|
28K, `/etc/gamecult/epiphany` (bifrost-persona-feedback-anchor.msgpack, credentials/,
|
|
idunn-provider-projection-anchor.cc, mcp.toml), `/etc/gamecult/epiphany-model-connector`
|
|
(connection.key). Manifests `/srv/odin/deploy-manifests/epiphany`, `epiphany-capstone-17`,
|
|
`epiphany.capstone-17.yggdrasil.yaml`, `epiphany-ox17`, `epiphany.ox17.yggdrasil.yaml`,
|
|
`epiphany-swarm.service`, `epiphany.yggdrasil.Dockerfile`.
|
|
`/etc/gamecult/idunn/daemon-health-trust.cc` contains the string `epiphany`.
|
|
About 24.7 GB in all.
|
|
- **F6 What the live crossing still names.** `/etc/systemd/system/bifrost-persona-mouth.service`
|
|
carries flags `--epiphany-persona-mouth-trust-anchor`, `--epiphany-persona-permit-rudp`,
|
|
`--epiphany-persona-permit-trust-anchor`, `--epiphany-runtime-id epiphany-starfire`.
|
|
gamecult-ops `runbooks/bifrost-persona-feedback-yggdrasil.md:17` names
|
|
`/etc/gamecult/epiphany/bifrost-persona-feedback-anchor.msgpack`, `:45` the installed
|
|
`/usr/local/sbin/bifrost-authorize-epiphany-release` (sealed historical name), `:67`
|
|
the feedback target `--persona-id epiphany --repo GameCult/Epiphany --runtime-id
|
|
epiphany-yggdrasil`. These belong to the mouth rebinding, not to the teardown.
|
|
- **F7 Nothing Epiphany runs on Starfire.** `Get-Process`, `Get-ScheduledTask`,
|
|
`Get-Service` filtered on epiphany|eureka|persona|bifrost: empty. The permit
|
|
issuer the crossing expects on Starfire is not running, so the mouth cannot
|
|
obtain a permit today.
|
|
- **F8 Idunn still lists Epiphany.** Idunn `deploy/legacy/README.md:51-52` lists
|
|
targets `epiphany`, `epiphany-capstone-17`; `deploy/legacy/idunn-yggdrasil:126-135`
|
|
dispatch, `:312,:321` restart/deploy cases; `deploy/legacy/idunn-yggdrasil.sudoers:10-11,19`.
|
|
The precedent for retirement is the same file's "Retired targets"
|
|
(bifrost-persona-feedback, 2026-09-30). Idunn is not one of `eureka-body`'s repos.
|
|
- **F9 Codex is dead in practice.** Idunn `docs/migration.md:49-55`: "The operator is
|
|
not returning to Codex"; the deployed daemon failed with `401 token_expired`. On
|
|
Yggdrasil `codex-connector.service` is disabled, inactive since 2026-09-05 21:54 UTC,
|
|
and nothing listens on 4103. Ghostlight's codex-connector library dependency is pinned
|
|
at `68fe94b`, so a kit lift does not move Ghostlight.
|
|
- **F10 CodexConnector at origin/main 3ddc12e** (2026-09-13): `src/lib.rs` 1,958,
|
|
`daemon.rs` 1,180, `provider_backend.rs` 1,463, `idunn_health.rs` 1,396, `main.rs` 188,
|
|
`deployment/idunn/recipe.toml`. Contract types: `CodexProviderRequest` lib.rs:76-94,
|
|
`CodexInputItem` :212-229 (UserText, AssistantText, ToolCall, ToolResult; no
|
|
reasoning item), `CodexTransportInvocation` :238-245 (no `max_cost_usd`),
|
|
`CodexTransportOutcome::Completed` :449-462 (tokens, no cost), `CodexRefusal`
|
|
:464-474 (no `Budget`). Schema ids `gamecult.codex.*.v2` lib.rs:51-55.
|
|
- **F11 gamecult-ops Epiphany tooling, before the teardown** (`git ls-files | grep -i epiphany`, 7e23387):
|
|
`compose/epiphany.capstone-17.yggdrasil.yaml` 38, `compose/epiphany.yggdrasil.Dockerfile` 55,
|
|
`runbooks/epiphany-yggdrasil-deploy.md` 196, `runbooks/epiphany-starfire-bifrost-crossing.md` 101
|
|
(live crossing binding, kept), scripts `bootstrap-epiphany-yggdrasil.sh` 134,
|
|
`check-epiphany-yggdrasil.sh` 136, `construct-epiphany-image-yggdrasil.sh` 91,
|
|
`deploy-epiphany-yggdrasil.sh` 499, `deploy-epiphany-capstone-17-transaction-yggdrasil.sh` 5,
|
|
`deploy-epiphany-capstone-17-yggdrasil.sh` 79, `epiphany-capstone-17-connector-bridge-yggdrasil.sh` 50,
|
|
`provision-epiphany-provider-health-yggdrasil.sh` 116, `seal-epiphany-capstone-failure.sh` 67,
|
|
`test-deploy-epiphany-yggdrasil-order.sh` 144, `test-epiphany-container-promotion.sh` 47,
|
|
`systemd/epiphany.service` 31, `systemd/epiphany-swarm.service` 34; kept for the mouth
|
|
cut: `allow-starfire-epiphany-persona-permit.ps1`, `bifrost-authorize-epiphany-release.sh`,
|
|
`configure-voidbot-epiphany-feedback-target-yggdrasil.sh`. Inventory prose:
|
|
`inventory.md:581-588` (Starfire as Epiphany body), `:726-730` (archived Verse residue),
|
|
`:773-785` (intended Epiphany deployment body). `docs/repo-census-2026-09/` is history.
|
|
- **F12 Eureka repo (forge main 0bb414d)** carries the charters and doctrine (PR #3
|
|
landed). Epiphany citations remain: `README.md:63,86-87,95`, `SKILL.md:3,8-9,146`,
|
|
every charter's line 14 ("Self-improvement law (Epiphany `epiphany_doctrine.md`)"),
|
|
`agents/hands.md:28`, `agents/soul.md:48`, `agents/life.md:24`, `doctrine/persona.md:3,13`,
|
|
`doctrine/CLAUDE.md:31,229,233`, `doctrine/colossus.md:47,51` (lore, kept).
|
|
- **F13 eureka-substrate specs written against Epiphany.** `cut-mind-authority.r1` and
|
|
`cut-run-kind.r1` have repo `GameCult/Epiphany`, base `ef956865`;
|
|
`cut-huginn-persona-state.r2` base `bf73c42`; `cut-doctrine-persona-in-huginn.r2`
|
|
gamecult-ops base `2aeb7364`. None has a report. Since `leaf-into-huginn` they point at
|
|
a repo nothing builds from; `mind-authority` and `run-kind` have r2 specs against Huginn
|
|
(see Undone).
|
|
- **F14 Discord developer policy** on training with message content: the policy page
|
|
(support-dev.discord.com article 8563934450327) answered 403 to a fetch on 2026-10-08.
|
|
Self's recollection, unverified: the policy forbids using message content obtained
|
|
through the API to train AI models without express permission. An Eyes pass must
|
|
verify before question `persona-trace-retention` is ruled.
|
|
- **F15 Selection order is admission ordinal.** CultLib `packages/cultnet-rs/src/selection.rs:1998-2005`
|
|
(`order_rows`: ordinal, then schema id, then record key; reversed when descending). So
|
|
"newest" is `descending: true, limit: 1`, and a run label needs no order of its own.
|
|
- **F16 Huginn's leaf holds `leaf-key-bound`.** `crates/eureka-pipeline/src/lib.rs`
|
|
at `afc35f9`: `SUBJECT_LOCAL_MAX` (:898), `RESOLUTION_LOCAL_MAX` derived from it (:912),
|
|
`Sha::names_same_commit` (:272). The literal `64` at :915 (the root bound in the
|
|
fits-`Short` assert) is follow-up `eureka-substrate:follow_up:leaf-bound-hygiene`.
|
|
`leaf-key-bound` landed at Epiphany `ef956865` and came in with the leaf.
|
|
- **F17 The live Huginn release is still `107552dc`.** Read-only `ssh yggdrasil readlink
|
|
/opt/gamecult/huginn/current` on 2026-10-09: `releases/107552dc4b27b8856b043616ae74c2ebe7908b66`.
|
|
Main (`afc35f9`) is ahead of it by the leaf move and the relicense; no deploy has happened since.
|
|
- **F18 At Huginn `df7507b` nothing stops a unit of hers.** Read from `git show df7507b:`
|
|
on 2026-10-09 (Imagination `imagination-brake-stop`). `crates/mind-body` holds
|
|
`control.rs`, `cli.rs`, `main.rs` and `lib.rs`. `cli::run` (cli.rs:40-61) dispatches `show`,
|
|
`brake hold`, `brake release` and `dial set`. `brake hold` is `ControlWriter::open(&path)?.set_brake(false, ..)`
|
|
(cli.rs:53) and does nothing else. `git grep systemctl` over `crates/mind-body` finds nothing.
|
|
The binary sets umask 077 and calls `cli::run` with the root `CONTROL_ROOT` (main.rs:21-37).
|
|
The window probe runs the real binary with `brake release` and `brake hold` 100 times
|
|
(tests/control.rs:573-581), so a hold that ran `systemctl` would run it in the verify container.
|
|
No `launch.rs` exists yet: the Launcher is cut mind-launch. RunTurn and RunOperator carry
|
|
`NAMES` (crates/eureka-pipeline/src/lib.rs:507-508).
|
|
- **F19 Yggdrasil has no unit, user or control store of hers.** Read-only `ssh yggdrasil`
|
|
as `gamecultadmin` on 2026-10-09:
|
|
- `systemctl list-units --all 'mind-*'` and `list-unit-files 'mind-*'` both list nothing.
|
|
- `ls /etc/gamecult/minds` gives "No such file or directory". `command -v mind-control`
|
|
finds nothing. `id mind-eureka` gives "no such user".
|
|
- The host runs systemd 257 (257.13-1~deb13u1). `systemctl --help` lists
|
|
`stop UNIT...` and "--no-block Do not wait until operation finished", so a stop
|
|
waits by default.
|
|
- `systemctl stop --no-ask-password 'zz-probe-none@eureka:*.service'` as non-root returned 0:
|
|
a glob that matches no loaded unit is a no-op. `systemctl is-active 'huginn*.service'`
|
|
matched by glob (`active`).
|
|
- Operators act through `sudo`: the gamecult-ops runbook `huginn-yggdrasil.md:86` uses
|
|
`sudo systemctl stop huginn`, and `/etc/sudoers.d/` holds `90-gamecultadmin`.
|
|
- **F20 The ruling decides when the stop happens.** Ruling `eureka-body:ruling:self-run-actuator` says:
|
|
"Holding the brake stops running units (systemctl stop; SIGTERM exits 143 with the turn
|
|
unfinished, section 1.4)". It cites the OpenClaw inbox incident: a stop sent as a message
|
|
was not acted on in time, and the process was killed at the host (prior-art file
|
|
lines 323-325, secondary). Cut mind-wake r2 has the waker return `Held` before any query,
|
|
admission or unit call, and lists "the waker ... ending a live run" among its forbidden writers.
|
|
- **F21 What the mind can attribute a document to, at the mind-launch head `8dee875`.** Read
|
|
from a throwaway worktree on 2026-10-09 (Imagination `imagination-launch-r3`).
|
|
- A receipt's provenance is `{ faculty, agent, session, tool }`, all declared by the writer.
|
|
No selection alias reads `session`, so attributing by session means scanning headers.
|
|
`open_and_launch` admits a run with session equal to its run label
|
|
(`crates/mind-body/src/launch.rs:205`). Nothing makes a Self run's later admissions carry
|
|
that label: the Self organ is not built.
|
|
- Citations are typed content. A `cites` selection with no role over every schema is
|
|
supported and tested (`crates/huginn-mind/src/query.rs:1499`). A run's header facts carry
|
|
`turn`, `operated_by` and `claims` (query.rs:139).
|
|
- The breaker at 8dee875 scans every header in the mind, newest first, back to the oldest
|
|
counted run (`crates/mind-body/src/queue.rs:210`). Its cost grows with the whole mind.
|
|
- `Mind::admit` takes `&mut self` (`crates/huginn-mind/src/admission.rs:81`), so
|
|
admissions are serialized. The run rule is `run_claims_rule` (admission.rs:537-547). It is
|
|
applied when a run opens (admission.rs:526-529) and when a withdrawal reinstates a closed
|
|
run (admission.rs:685-694). It checks claims only.
|
|
- `MindRefusal` is huginn-mind's (`crates/huginn-mind/src/refusal.rs`), published in
|
|
`schemas/cultnet/huginn.mind_response.v1.schema.json` and pinned by
|
|
`published_wire_schemas_match_derivation` (wire.rs:276). The leaf's `PipelineRefusal` has
|
|
five variants (`crates/eureka-pipeline/src/lib.rs:59-65`) and is not where admission's rules
|
|
refuse.
|
|
- `Effective::Released { cadence, run_cap_usd }` is a public struct variant
|
|
(`crates/mind-body/src/control.rs:117-120`), so any caller can build one without reading the
|
|
store. `ControlState::effective` is called only by `read_effective` (control.rs:192-197).
|
|
- huginn-mind's `fixtures::run` builds an in-force SelfRun with `operated_by: Mind`
|
|
(fixtures.rs:331-342). The claim tests open several of them at once
|
|
(admission.rs:1987-2015).
|
|
- `Slug::validate_slug` and `Label::validate_label` are public
|
|
(crates/eureka-pipeline/src/lib.rs:287, 386). `RunTurn` and `RunOperator` spell their
|
|
variants through `Debug`, which is also their `NAMES` (lib.rs:436-452).
|
|
- **F22 What the mind units would land on, 2026-10-10.** Read-only `ssh yggdrasil` as
|
|
`gamecultadmin` and an Eyes pass over Idunn `6667f0f` (Imagination `imagination-mind-units`).
|
|
- Still no unit, user or store of hers: `systemctl list-unit-files 'mind-*'` lists 0;
|
|
`getent passwd` has no `mind-*` user; `/etc/gamecult/minds` is absent; no `mind-control`
|
|
on PATH. `/opt/gamecult/huginn/current` is `releases/107552dc...` and holds only
|
|
`huginn-daemon` (0755 root). The Release step builds only `-p huginn-daemon`
|
|
(gamecult-ops `runbooks/huginn-yggdrasil.md:57`).
|
|
- systemd 257 (257.13-1~deb13u1): `ExecCondition=` (since 243) exists. Per
|
|
systemd.service(5), an ExecCondition exit of 1-254 skips the unit (inactive, not failed)
|
|
and 255 or a signal fails it; the `+` prefix runs that command with full privileges.
|
|
- **polkit is not installed:** `polkitd` "Installed: (none)", candidate 126-2;
|
|
`/etc/polkit-1/rules.d` absent (`/usr/share/polkit-1/actions` exists, from systemd).
|
|
Without polkitd, systemd refuses an unprivileged caller's `StartUnit`, so no user of hers
|
|
can start a unit today. `/etc/sudoers.d` holds only `90-gamecultadmin` and README.
|
|
- systemd cannot derive a per-instance user from a `<instance>:<label>` instance: no
|
|
specifier splits `%i`, and dash-truncated drop-ins truncate the unit prefix (the part
|
|
before `@`) and re-attach the whole instance (systemd v257 `src/shared/dropin.c`,
|
|
`unit_file_find_dirs`: `unit_name_to_prefix`, `strrchr(prefix, '-')`,
|
|
`unit_name_build_from_type(prefix, instance, ...)`). So `User=mind-%i` works only when
|
|
the instance is the mind's slug alone.
|
|
- `SystemdLauncher::alive` counts `active`, `activating` and `reloading` as alive
|
|
(mind-launch head `origin/eureka-body/mind-launch`, launch.rs:96-99), and starts with
|
|
`systemctl start --no-block`, calling `systemctl` directly (no sudo).
|
|
- Idunn has no target, binding or reference for huginn, mind-control or `mind-*`
|
|
(`/etc/gamecult/idunn/bindings/` holds ghostlight, heimdall, odin, raven-muninn and two
|
|
streampixels). Idunn supervises only workloads it admitted and launched itself as
|
|
transient `systemd-run` units (`Type=exec`, `Restart=no`, `DynamicUser=yes`; Idunn
|
|
`src/drivers.rs:3628-3650`); its continuity loop restarts an admitted workload that is not
|
|
running, up to 6 times an hour, unless its lifecycle brake is engaged
|
|
(`src/control_plane.rs` ~5880-6190, 7932-7956). It has no one-shot, timer or template
|
|
workload (`docs/watchdog-reporting-map.md` row C9) and installs no unit file, polkit rule,
|
|
sudoers file or system user (`src/drivers.rs:3620-3720`). A unit Idunn did not launch is
|
|
never observed or restarted by it.
|
|
- **F23 Claude Code session ids and resume, probed 2026-10-22 on Starfire.** Claude Code
|
|
2.1.268 (Windows), `claude -p --output-format stream-json --verbose`, run with the desktop
|
|
host's `CLAUDE*`/`ANTHROPIC*` variables removed (Imagination `imagination-self-run`).
|
|
Every call ended `terminal_reason: api_error`, "OAuth session expired and could not be
|
|
refreshed": the CLI credential on Starfire is expired, so nothing below involved a model
|
|
request, and every claim about cache reads on resume is still unprobed (see F25).
|
|
- `--session-id <uuid>` is honoured: the `system/init` event, every event after it and the
|
|
transcript file carry exactly that id. The transcript is
|
|
`<config dir>/projects/<cwd with separators as '-'>/<id>.jsonl`, written even when the
|
|
request fails.
|
|
- `--session-id` of an id that already has a transcript is refused before any event:
|
|
"Error: Session ID ... is already in use.", exit 1. So a fresh run's id must be new.
|
|
- `--resume <id>` keeps the id: init and result carry the same id, and the resumed turns are
|
|
appended to the original transcript file, from another working directory as well (the
|
|
file found was under the first cwd's project dir; the appended lines record the new cwd).
|
|
`--resume <id> --fork-session` starts a new random id. `--resume <unknown id>` fails before
|
|
the stream with "No conversation found with session ID: ...", exit 1, one line on stdout.
|
|
- `--resume` together with `--session-id` is refused: "--session-id can only be used with
|
|
--continue or --resume if --fork-session is also specified." So a chain is: the first run
|
|
`--session-id <v5 of its own run key>`, every continuation `--resume <that id>`.
|
|
- Help text: `--input-format stream-json` (realtime streaming input, print only),
|
|
`--replay-user-messages`, `--max-budget-usd`, `--max-turns`, `--permission-prompts
|
|
host|none` ("none: anything that would prompt is denied automatically"),
|
|
`--no-session-persistence`, `--system-prompt-snapshot on` (default: the system prompt is
|
|
recorded on the first request and resent verbatim on every later request and resume).
|
|
- **F24 What one request's usage looks like.** Read from a real Claude Code 2.1.268
|
|
transcript on Starfire (`~/.claude/projects/F--Projects-CultLib/<session>.jsonl`, 736 lines,
|
|
64 assistant messages) and from the probe's stream (F23), which carries the same `assistant`
|
|
records.
|
|
- One API request is one `message.id`. A response with several content blocks is written as
|
|
several `assistant` records with the same `message.id` and an identical `usage` (45 of 64
|
|
messages had 2 or more records; e.g. `thinking` then `tool_use`, both
|
|
`input 2 / cache_read 45175 / cache_write 39033 / output 73`). Summing records double
|
|
counts; a reader keys on `message.id`.
|
|
- `usage` fields: `input_tokens`, `cache_read_input_tokens`, `cache_creation_input_tokens`,
|
|
`cache_creation.ephemeral_5m_input_tokens`, `cache_creation.ephemeral_1h_input_tokens`,
|
|
`output_tokens`, `iterations`, `service_tier`. The request's prefix is
|
|
`input + cache_read + cache_creation`; in that session it grew 84,210 to 287,837 over 64
|
|
requests.
|
|
- A record from a subagent carries `parent_tool_use_id` (set); the main thread's is null.
|
|
The `result` event carries `usage` (session totals), `modelUsage`, `total_cost_usd`,
|
|
`terminal_reason`, `num_turns`, `subagent_stats` and `queued_turn_count`.
|
|
- **F25 What the stream-json input channel accepts, read from the binary.** Strings in
|
|
Claude Code 2.1.268's `bin/claude.exe` (npm `@anthropic-ai/claude-code`): 64 occurrences of
|
|
`"control_request"`; a handler `if(d.request.subtype==="interrupt")` that aborts the running
|
|
turn and snapshots the command queue; an option `cancel_queued` on interrupt; the result
|
|
schema's `queued_turn_count`. So, by source read only: user messages written while a turn
|
|
runs go to a command queue, and a control request `interrupt` ends the running turn.
|
|
Unprobed: whether a queued user message is delivered mid-turn or after the turn's `result`,
|
|
and whether closing stdin lets queued messages finish. The actuator spec is written so its
|
|
correctness holds under either delivery, and its operator verification probes both on
|
|
Yggdrasil with her token.
|
|
|
|
- **F26 CodexConnector at origin/main `fd7cec4` builds and tests green** (2026-10-28, Yggdrasil,
|
|
ygg-verify rust image, `cargo build --features daemon --all-targets`, `cargo test --features
|
|
daemon`, `cargo test`): 46 lib + 1 bin tests with `daemon`, 11 lib tests without. `fd7cec4` is
|
|
F10's `3ddc12e` plus a README merge; F10's line numbers still hold. Files: `src/lib.rs` 1,958,
|
|
`daemon.rs` 1,180, `provider_backend.rs` 1,463, `idunn_health.rs` 1,396, `main.rs` 188, no
|
|
`vendor/`. CultLib pinned at `e171eca` (2026-09-04); 248 CultLib commits touch
|
|
`packages/cultcache-rs` or `packages/cultnet-rs` since, and the store API the connector uses
|
|
(`OwnedRedbMessagePackBackingStore`, `SingleFileMessagePackBackingStore`, `register_entry_type`,
|
|
`pull_all_backing_stores`, `get_all_with_keys`) still exists at CultLib `a4eae90`.
|
|
- **F27 What is provider-neutral and what is Codex** (source read, `fd7cec4`). Neutral: the contract
|
|
types and validation (`lib.rs:51-485`, `622-631`, `1351-1415`), the AES-256-GCM envelope and
|
|
four-byte big-endian framing (`633-710`, `824-952`), the one-request client (`711-833`), caller
|
|
admission and the CultCache replay service (`954-1313`), and the accept loop
|
|
(`daemon.rs:344-380`, `565-740`). The daemon calls its backend at exactly two points,
|
|
`readiness()` and `execute(&invocation) -> CodexTransportResult` (`daemon.rs:592-653`), so one
|
|
trait is the whole seam. Codex: `provider_backend.rs` (the pinned `codex app-server` child,
|
|
`auth.json`, Responses SSE parsing), the Responses lowering `canonical_responses_body`
|
|
(`lib.rs:487-620`), `CodexDaemonConfig` (`daemon.rs:47-171`, CultCache type
|
|
`gamecult.codex.connector_config.v1`, with `codex_executable` and `codex_home`), the managed
|
|
paths (`daemon.rs:453-536`), and the Idunn recipe (npm `@openai/codex` input). `idunn_health.rs`
|
|
is Idunn runtime presence with Codex-named constants (target `codex-connector`, capability
|
|
`gamecult.codex.subscription-inference`, env `CODEX_CONNECTOR_CULTNET_RUDP`). The request
|
|
itself carries OpenAI Responses fields (`reasoning_summary`, `service_tier`,
|
|
`previous_response_id`, `output_format_name`, `prompt_cache_key`).
|
|
- **F28 The wire is serde MessagePack, not CultNet** (source read). The envelope, invocation and
|
|
result are `rmp_serde` encodings of serde structs (`lib.rs:476-710`, client `748` and `765`,
|
|
daemon `637` and `652`); schema ids are strings compared by hand, not a CultNet schema.
|
|
CultCache holds only the replay record and the daemon config; CultNet is used only for Idunn
|
|
runtime presence and route observation. JSON: `parameters_json`, `output_schema_json` and tool
|
|
`arguments` are JSON strings checked by `require_json_object`; they are provider-facing (JSON
|
|
Schema and the provider's own tool-call arguments), a xenos boundary. Every other JSON use is
|
|
inside `provider_backend.rs` (HTTP body, SSE, app-server JSON-RPC, `auth.json`), also xenos.
|
|
- **F29 Consumers and license** (git grep at each origin/main). Ghostlight `c43eb54` pins
|
|
`codex-connector` at `68fe94b` as a library (`Cargo.toml:18`, no `daemon` feature) and imports
|
|
the contract and client in `crates/ghostlight/src/controllers.rs:34-37` and seven other files;
|
|
Epiphany's pins are archive (target invariant `nothing-runs-from-epiphany`). gamecult-ops
|
|
`idunn/yggdrasil/bindings/codex-connector.toml.in` names origin GitHub CodexConnector; Idunn
|
|
`docs/migration.md:49-55` says retire codex-connector, and `:163` calls its recipe stale.
|
|
CodexConnector's project code is PolyForm Noncommercial 1.0.0 (`LICENSE` section 3), all 33
|
|
commits by Meta Vens; ModelConnector is AGPL-3.0-only at `1cf879f` (LICENSE and a 26-line
|
|
planned README).
|
|
|
|
- **F30 The v2 wire decoded, and what a v3 change costs it** (2026-10-28, Yggdrasil, ygg-verify
|
|
rust image, scratch clone of ModelConnector `ec0519d` plus a probe-only commit; research
|
|
`725f5a5` section 4, probes P2-P5). Baseline 77 tests green with and without `daemon`. The real
|
|
v2 frame `envelope_invocation.mp` is 735 bytes for 429 bytes of ciphertext (ratio 1.713; a
|
|
positional six-array, `0x96`) and decrypts to Ghostlight-shaped content. Ciphertext as
|
|
MessagePack `bin` makes it 526 (1.226); at 1 MiB all-high, v2 2,097,251 vs bin 1,048,675. The
|
|
v2 type reads bin and named encodings unchanged. Positional encoding fails on any added field
|
|
("array had incorrect length"); named encoding drops an unknown field silently; a v2
|
|
`InputItem` refuses an unknown variant; a v3 envelope id is refused by v2 before decryption,
|
|
so a v2 daemon drops a v3 caller's connection and never answers.
|
|
- **F31 CultNet can carry the kit as an operation service** (same job, cultnet-rs at CultLib
|
|
`a4eae90`; source reads in research section 4). The sealed envelope as the
|
|
`messagepack-base64` payload of `cultnet.operation_request.v0` round-trips through
|
|
`encode_cultnet_message_to_vec`/`decode_cultnet_message_from_slice`: 1.354x at 64 KiB, 1.335x
|
|
at 1 MiB, 1.334x at 8 MiB (deterministic), 6.5 ms encode and 1.0 ms decode at 1 MiB, release.
|
|
CultNet's `TcpFramed` frame is the kit's 4-byte big-endian frame; operation payloads may only
|
|
be `messagepack-base64` (`contracts.rs:780`); CultNet security holds one key per server where
|
|
the kit binds one per caller with ids in the AAD. Huginn's `huginn.mind` is already this
|
|
shape (`huginn-mind/src/envelope.rs`).
|
|
- **F32 The reasoning variants cost the v3 wire nothing it has pinned** (2026-10-28, Yggdrasil
|
|
ygg-verify rust image, scratch commit `af9fb74` on ModelConnector `bf958fc`, never pushed).
|
|
`InputItem::ReasoningState { provider, model, state }` and
|
|
`TransportEventPayload::ReasoningState { state }`, `state` under `serde_bytes` with the
|
|
envelope's `binary_schema`: all 83 unit tests and both `wire_golden_v3` tests pass with every
|
|
committed golden byte-identical; only `published_schemas` fails (the new variant, expected).
|
|
The item encodes as a one-key map whose `state` is MessagePack `bin` (`c4 03 ff 80 01` for three
|
|
bytes); a 1 MiB state encodes in 1,048,623 bytes (47 bytes of overhead); the schema shows
|
|
`state` as `format: binary`. So the receipt field `foreign_reasoning_dropped` and the new event
|
|
in the transported golden are the only wire changes B3b makes to existing fixtures. Source
|
|
reads at `bf958fc`: `ProviderBackend::execute` receives the caller's whole
|
|
`TransportInvocation` (`serve.rs:29`, via `ExecutionClaim::invocation`, `service.rs:115-119`),
|
|
and every backend writes its own `receipt.provider` (`fixtures.rs:63-83`, test backends
|
|
`serve.rs:945-962`, `service.rs:1074-1091`): today nothing stops a backend from seeing foreign
|
|
state or mis-tagging its own.
|
|
- **F33 The kit holds no spend today, and its store fails closed but locks out readers**
|
|
(2026-10-28, Yggdrasil ygg-verify rust image, scratch commit `79e14b8` on ModelConnector
|
|
`1d51e71`, never pushed; source reads at `1d51e71`). Baseline: 94 lib tests with `daemon`, 37
|
|
without, plus 4 `published_schemas`, 4 `reasoning_state` and 3 `wire_golden_v3`, all green.
|
|
P1: a `CacheBackingStore` whose `push` fails makes `CultCache::put` return the error and leaves
|
|
nothing in memory (`get` is `None`), so a reservation written with `put` before execution is
|
|
either durable or refused. `begin` already returns `ServiceError::ReplayStore` before
|
|
`live.insert` and before the backend runs (`service.rs:367-369`), so the replay store is a
|
|
fail-closed ledger by construction. P2: a second `OwnedRedbMessagePackBackingStore::new` on a
|
|
held path fails "already has an active owner", in the same process and from a child process,
|
|
so no root stop hook can read the connector's store while the connector runs. Source reads:
|
|
`CallerConfig` and `CallerAdmission` carry no spend field (`serve.rs:105-114`,
|
|
`service.rs:19-28`); `Usage` is tokens only and the receipt has no cost (`contract.rs:193-204`,
|
|
`465-479`); `TransportOutcome::Failed` carries no usage (`524-527`); replay records are never
|
|
deleted or pruned (no `delete` on the store in `service.rs`); `TransportService::open` takes a
|
|
path, so a test cannot inject a failing store (`service.rs:181-182`).
|
|
- **F34 The kit's in-flight boundary misses Claude's turn rule; caller JSON must not pass through
|
|
`json!`** (2026-10-28, Yggdrasil ygg-verify rust image, scratch commits `eb021f0`, `0c9a39d` on
|
|
ModelConnector `e0c0832`, never pushed). P1: a kit lib test admitting `[UserText,
|
|
ReasoningState(other-provider), ToolCall, ToolResult, UserText]` printed `executed, dropped=1`,
|
|
so foreign state in a tool exchange the model has not yet answered is dropped, where Anthropic
|
|
counts a tool loop as one assistant turn (research `f237623` section 4). P2: a `RawValue`
|
|
`{"b":1,"a":2}` serialized through `json!` came out `{"a":2,"b":1}`; through a typed
|
|
`#[derive(Serialize)]` field it came out verbatim. P3: `ureq 3.5.0` (rustls, no default features)
|
|
with `serde_json` `raw_value` builds in the workspace on rust 1.95. Baseline: 138 kit lib tests
|
|
with `daemon`, green. Source reads at `e0c0832`: `ProviderBackend::execute` returns a
|
|
`TransportResult` synchronously on the serve loop's per-connection thread (`serve.rs:25-38`,
|
|
`240-262`); the backend's only result door is `ProviderCall::transported` (`service.rs:380`);
|
|
`wire_encode` is `pub(crate)` (`contract.rs:586`), so a connector crate encodes its own state
|
|
with `rmp_serde` directly; there is no connector binary, config document or Idunn presence in the
|
|
repo (`crates/` holds only `model-connector`); CodexConnector's `idunn_health.rs` is 1,396 lines
|
|
and its recipe binds a CultCache config document, a replay slot and a credential state slot
|
|
(`deployment/idunn/recipe.toml`).
|
|
- **F35 B4a at ModelConnector `200933f` (landed; read from cut report `h2`, verdict `s2` and the
|
|
crate, 2026-10-29).** `crates/claude-connector` is a library (`backend.rs`, `config.rs`,
|
|
`handle.rs`, `launch.rs`, `process.rs`, `stream.rs`; deps `model-connector` with `daemon`,
|
|
`serde_json`, `rmp-serde`, `sha2`, `zeroize`, `libc` on unix; no HTTP client). There is still no
|
|
binary, config document or Idunn presence. `model-connector` and `schemas/` are byte-identical
|
|
to `e0c0832`. Gate: 198 tests green; `cargo mutants --in-diff` 155 mutants, 121 caught, 0 missed,
|
|
2 timeouts (`process.rs` `StdChild::kill`). Live (claude 2.1.312, Starfire, haiku-5-5, four
|
|
calls): print mode emits `result.model_usage_since_last_result`, the turn's own usage; the
|
|
cumulative `modelUsage` of a resumed fork also counts the earlier turns, so it is never read;
|
|
`--system-prompt-file` replaces the system prompt as `--system-prompt` does. Argv sets
|
|
`--tools ""`, `--strict-mcp-config`, `--setting-sources ""`, `--permission-prompts none`, and
|
|
`--resume <id> --fork-session` on every resume. The child env is cleared to `PATH`, `HOME`,
|
|
`CLAUDE_CONFIG_DIR`, `CLAUDE_CODE_MAX_OUTPUT_TOKENS` and the one const
|
|
`CLAUDE_CODE_OAUTH_TOKEN`. Not exercised live: `CLAUDE_CODE_MAX_OUTPUT_TOKENS`. Open scars from
|
|
Soul `s2`: `stderr-join-reachable` (the stderr-tail join is reachable but undefended in the
|
|
repo), `prompt-file-exclusive-undefended` (the exclusive create on a predictable temp name),
|
|
and `door-refusal-boundary` (code bills zero only for a 401 or 403 with explicitly empty usage;
|
|
ruling `claude-code-plan-quota-fuse-2`, admitted after `s2`, says 401, 403 and 429, so a 429 with
|
|
`{}` still bills the reservation until follow-up `claude-backend-hardening` lands). Follow-ups
|
|
`handle-unauthenticated`, `pin-checked-only-at-ready`.
|
|
|
|
## The model page (step 0b)
|
|
|
|
One row per persistent kind this body introduces or changes. Rows for the thirteen
|
|
pipeline kinds are in Huginn `docs/eureka-substrate-map.md`.
|
|
|
|
| Kind | Identity (what names it) | Lifecycle (what happens over time) | Authority (who decides) |
|
|
| --- | --- | --- | --- |
|
|
| Pipeline wire ids | `epiphany.pipeline.<kind>.v2`, epoch `epiphany.pipeline.epoch.v2`, defined by the leaf, the Huginn crate `crates/eureka-pipeline` (lib `eureka_pipeline`), ids unchanged. | Renamed once to `eureka.pipeline.<kind>.v3` by one `mind.redb` migration, at the next breaking leaf change or before the first hosted mind (ruling `wire-names-rename-before-hosting`). Adding the `run` kind or the `Mind` authority variant is additive (old stored documents decode; no migration), so it does not trigger the rename; a field added with the leaf's `= absent` marker is additive too (leaf-read-anchors r2: old bytes decode, empty fields encode byte-identically, `golden/envelopes.txt` gains lines and loses none); a field added any other way would. | Huginn owns the leaf. The migration is a live-mind upgrade, which is the operator's (`mind-rules-which-forks`). |
|
|
| Leaf crate and schema catalogue | Huginn `crates/eureka-pipeline`, `schemas/cultnet/` (13 pipeline schemas, `gamecult.persona_state.v0`, index, README). `epiphany.work_organ_state.v0` dies: no reader outside Epiphany (grep, F1/F3). | Landed at Huginn `afc35f9` (leaf-into-huginn). Wire pinned by `crates/eureka-pipeline/golden/envelopes.txt` and huginn-mind's opt-in `query::tests::stored_documents_read_back`. Huginn is AGPL-3.0-only (ruling `eureka-body:ruling:leaf-relicensed-agpl`). | Huginn. Forbidden: any Cargo source resolving into GameCult/Epiphany (`nothing-runs-from-epiphany`). |
|
|
| `run` | `<instance>:run:<label>` (cut-run-kind r2). Label `mind-<YYYYMMDD>T<HHMMSS><mmm>Z` from mind-launch's `run_label`; two launches in one millisecond produce the same key with different content, which admission answers `Conflict`, so the name stays injective. Order is admission ordinal (F15), not label. | The heartbeat opens a PersonaTurn run with no claims each time it launches a Persona turn (a `mind-persona` start that finds no such run opens none and runs nothing) (ruling `eureka-substrate:ruling:every-wake-a-run`); the Persona tool opens SelfRun runs with claims; both go through `open_and_launch`, and the unit starts only after the run commits (the run is the grant). The Self in a unit admits under its label and ends it `Recorded { reason }`. A run whose unit is not alive past a 120 s start grace is closed `Recorded { reason: "unit not active" }` by the next `open_and_launch` of the same turn, before it checks anything else. It is Recorded, not Withdrawn, so a unit that keeps dying counts as an empty ended run and trips the breaker. Only a unit whose start failed in the launch itself is Withdrawn. Idle time comes from the newest PersonaTurn run's `admitted_at` (any status), not `started_on` (a date cannot carry seconds); there is no cadence, the heartbeat's initiative timeline decides when a Persona wakes. | Opening: `open_and_launch`, called by the heartbeat for PersonaTurn and by the Persona tool for SelfRun, each with a `Grant` that only `read_effective` constructs. One live run of hers per turn and instance: huginn-mind admission refuses a second in-force run with `operated_by: Mind` of the same turn and instance as `AlreadyLive { run }` (ruling `one-live-self-run`, option `one-live-per-turn`; cut run-live-admission). `open_and_launch` answers `Busy` from that refusal, or earlier, when the holder it has just read is alive. Operator runs never count. `operated_by` is declared by the writer (follow-up `eureka-substrate:follow_up:operator-authority-needs-operator-credential`). Ending: the Self that worked it; a dead one is closed by the next launch of its turn (cut mind-launch r3). No sweep exists elsewhere. Forbidden: Hands, Soul, Imagination, Life. |
|
|
| Repetition breaker | No state of its own (rulings `self-waker`, `merge-gate-own-soul`). Trip condition derived from one selection: the documents citing the item, in any role. Counted runs are the item's ended SelfRun runs of hers (`operated_by: Mind`, not withdrawn) admitted after the newest question `raised_in` the item. Trip when the last 3 counted runs are empty, or 10 of the last 50. A run is empty when no citing document other than a run has an ordinal in its window (its admission up to the next run's, or now). Documents that cite something else never count, wherever they were admitted (F21). | Evaluated in `open_and_launch` when a Self run claims the item, not by the heartbeat. When tripped, it admits one `question` labelled `breaker-<run label>` under the item's campaign, `raised_in` the item, and launches nothing. The run label is the label the refused launch would have used, so every trip has its own key. The existing blocked-spec recipe then removes the item from the queue. Answered by a ruling or withdrawn: either reopens the item, and that question is the boundary, so a reopened item starts a fresh count. | `open_and_launch` admits the question; any Self may answer it (substrate-internal, `mind-rules-which-forks`). |
|
|
| Brake | One document per instance in a root-owned CultCache store `/etc/gamecult/minds/<instance>/control.cc`, type `eureka.control.brake.v1 { released: bool, set_at, set_by }`. | Replaced whole by the operator's CLI; never appended. Absent or undecodable reads as held. `mind-control brake hold` writes it held and then, in the same command, stops her running units: `systemctl stop` (blocking) over `mind-self@<i>:*` and `mind-persona@<i>:*`, through `SystemdLauncher::stop_all` (cut brake-stop; ruling `self-run-actuator`; F18-F20). | Operator only (ruling `brake-dial-root-store-now`); her units read it, and the file is not writable by any user she runs as. The hold is the one stopper of her units. `read_effective` is the one reader. Its `Released` answer carries a `Grant` (cadence and run cap, private fields, not `Clone`), which `open_and_launch` takes by value, so no run opens without a released reading (cut mind-launch r3). |
|
|
| Swarm dial (supersedes the per-instance burn-rate dial) | `CONTROL_ROOT/swarm.cc` only; the per-instance `control.cc` holds the brake and nothing else. `eureka.control.burn_rate.v1`, `Grant.cadence` and `base_cooldown_s` are deleted (cut mind-heartbeat). | Operator CLI `mind-control swarm ...`. | Ceilings: heat 2, base rate 100 USD/h, base run 50 USD, k 16. |
|
|
| Connector request and transcript items | Request: `(caller_runtime_id, request_id)`, the replay key the daemon already keeps (`replay.cc`). Items: UserText, AssistantText, ToolCall, ToolResult, plus `ReasoningState { provider, model, opaque }` (ruling `connector-opaque-state-item`). Contract ids become provider-neutral `gamecult.model.*.v3` (follow-up `connector-contract-untyped`); the connector serves Ghostlight too, so not `eureka.*`. | Invocation expires at `expires_at_unix_ms`; replay record per key; restart-era `Indeterminate`. The caller stores the transcript and replays it verbatim; foreign-tagged reasoning state inside an in-flight tool exchange is refused typed; completed-turn foreign state is settled per provider in the connector cut (follow-up `connector-reasoning-state-cheap-providers`). | The connector produces, reads or refuses reasoning bytes; callers never branch on provider. |
|
|
| Connector spend ledger | The reservation lives in the replay record itself (cut connector-spend, F33): integer micro-USD, windowed per caller (ruling `connector-spend-caller-window-ceiling`). | Reserve before the provider runs, settle to actual; refusals `CostBound` (the invocation's own `max_cost_micro_usd`) and `SpendCeiling` (the caller's window); a ledger that cannot be written refuses the request. | The kit's `ProviderCall::charge` is the one billing owner; a backend reports usage or `None` (bills the reservation). The root caller config sets the ceiling. |
|
|
| Claude connector backend (B4a, landed `200933f`) | `ClaudeCodeBackend` in `crates/claude-connector`, provider tag `claude-code`: one `claude -p` child per call in its own process group, tool-less, system prompt in a private temp file; reasoning state is a named-MessagePack `ClaudeCodeHandle { session_id, instance, prefix_sha256 }`; usage is `model_usage_since_last_result` summed over models, in list-price units from B4b's price table (ruling `claude-code-plan-quota-fuse-2`). | A handle resumes (always `--fork-session`) only when it decodes, names this instance, its session file exists and its digest matches the request's instructions, model and earlier items; anything else re-seeds from the caller's transcript (ruling `claude-code-handle-reseeds`). The CLI's session store under `config_dir` is a cache; the caller's transcript is the truth. A refusal at the door with explicitly empty usage bills zero; unknown usage, a crash or a deadline bills the reservation. | The backend owns the argv, env, process and stream mapping. It never reads `total_cost_usd`, never forwards `ANTHROPIC_API_KEY`, never retries, never spawns twice per execute. Forbidden: `--bare`, `--fallback-model`, `--mcp-config` and `--dangerously-skip-permissions` (B4d changes the MCP line, by spec). Her organs hold none of it: the subscription token lives in the connector's own environment. |
|
|
| Persona turn traces | **Empty: question `persona-trace-retention`.** Candidate: per turn, the request digest, the transcript items and the typed output, keyed by the turn's run. | Empty: how long they are kept, whether Discord-sourced content may enter a training export (F14). | Empty: who may export them. |
|
|
| Persona state | `gamecult.persona_state.v0`, one per mind, `personaId` = instance (cut-huginn-persona-state r2, eureka-substrate). | Replaced whole under CAS with a receipt; she may rewrite any field (`identity-write-all-visible`). | The Persona organ is the only writer. |
|
|
| Identity diffs | The pair of receipts of two consecutive Persona puts whose identity fields (publicName, publicDescription, presentation, values) differ. Derived, not stored. | Composed by the Persona organ at put time and sent as one delivery request through the crossing; a failed post is retried by Bifrost's delivery journal, not by her. | Persona organ composes; Bifrost posts under the permit. No rate limit. |
|
|
| Discord body surfaces | Outbound: crossing ids `epiphany.persona_discord_delivery_request.v0` and `..._permit.v0`, agent `epiphany.Persona`, runtime `epiphany-starfire` (F6), renamed to `eureka.*` and `eureka-yggdrasil` in the mouth rebinding (`mouth-crossing-on-yggdrasil`). Inbound: Bifrost persona-feedback deliveries for target `epiphany` (F6). Persona-session tools reach both (`body-includes-discord`). | Request, permit, post, receipt (Bifrost journal). Inbound deliveries: **unprobed** who records that a delivery was answered; `run-is-the-grant` forbids her organ from holding that fact. Blocks the Persona cuts only, not the cuts admitted today. | Bifrost owns posting and delivery records; her permit issuer grants while the brake is released. |
|
|
| Units and instance templates | `mind-heartbeat.service` (one, not per instance), `mind-self@<instance>:<label>.service`, `mind-persona@<instance>:<label>.service` (one-shot per Persona turn; `RuntimeMaxSec` set at install bounds a hung unit), `mind-permit@<instance>`; users `mind-<instance>` (organs) and `mind-<instance>-self` (Self runs); state `/var/lib/gamecult/minds/<instance>/`; control `/etc/gamecult/minds/<instance>/`. Instance `eureka`. | Hand-installed by gamecult-ops now; Idunn targets declared before the first hosted member, which deletes the hand install (`mind-units-templated-interim`). | gamecult-ops installs; Idunn later. Starting: `open_and_launch` through `SystemdLauncher::start`, as her users, who are granted start only. The instance in a unit name is always the mind's (`MindPort::instance`), passed to every `Launcher` call; `SystemdLauncher` holds none. The instance and label are validated by the leaf's grammar before any `systemctl` argv is built. Stopping: only the operator's `brake hold`, as root (cut brake-stop). The unit-level brake gate and the start-only grant are follow-up `mind-units-brake-gate`. None of this exists on Yggdrasil yet (F19, F22). Each piece's identity, lifecycle and authority: the section "The mind units" below (cut mind-units-install; unit names pending question `mind-unit-names`). |
|
|
| Self-run credential | None in her unit. The connector holds the one subscription token; a Self run borrows it as a lease over a unix socket (`CLAUDE_LEASE_SOCKET`), and the token reaches `claude` only as a descriptor it reads once (`CLAUDE_CODE_OAUTH_TOKEN_FILE_DESCRIPTOR`). The child's environment is cleared and rebuilt from an allow-list (`PATH`, `LANG`, `LC_*`, `TERM`, and its own `HOME` and `CLAUDE_CONFIG_DIR`), so no credential variable in the unit can outrank the lease. | Rotated by the operator at the connector, never in her unit: no `EnvironmentFile` carries a token for `mind-self@` (rulings `self-runs-through-connector`, `self-run-credential-lease`; `self-run-token-reach` is superseded). | The connector's: one lease per unit invocation, bound to the peer; the unit holds no credential variable. Her `claude` runs her tools, so anything in the unit's environment is readable from `/proc/<claude>/environ` by her Bash (ruling `claude-code-runs-her-tools-2`). |
|
|
| Wake frame | Fixed prompt frame (provenance, jurisdiction, brake obedience) in `/etc/gamecult/minds/<instance>/wake-frame.md`, root-owned. Composed by the Persona organ from host config; the waker passes the unit only the instance and the run label. | Changed only by an install. | Host config (ruling `self-waker` rider 2); never a file her runs merge into. |
|
|
| Epiphany residue | F5, F8, F11, as they stood before the teardown. | Teardown landed (gamecult-ops `9c12adb`); what it did not name is follow-up `eureka-body:follow_up:epiphany-body-leftovers`; the repo is archived last. | gamecult-ops for host and repo tooling; Idunn for its legacy target list (follow-up). |
|
|
|
|
## The mind units: identity, lifecycle and authority
|
|
|
|
Written 2026-10-10 before cut `mind-units-install` was mapped (operator direction: settle
|
|
ownership first). `<i>` is the mind's slug (`eureka` now). Unit names follow the
|
|
recommended option of question `mind-unit-names` (`instance-only`): the instance is the slug
|
|
alone, one unit per instance and turn, because admission already allows only one live run of
|
|
hers per turn (`one-live-self-run`) and only then can `User=` name a per-instance user (F22).
|
|
"Root" means the operator through `sudo`, or an agent under her deploy instruction.
|
|
|
|
| Thing | Identity | Lifecycle | Who may start, stop, enable or change it |
|
|
| --- | --- | --- | --- |
|
|
| Heartbeat unit | One `mind-heartbeat.service` (not per instance; `mind-wake@` timers and units are retired). Needs `HEARTBEAT_PERSONAS` (each entry ends with that Persona's own Huginn `rudp://<ip>:<port>`: each Mind is its own daemon, ruling `swarm-one-connector-many-callers-mind-per-daemon`), `MIND_PERSONA_OPERATOR`, `BIFROST_CHAT_ENDPOINT` and `_KEY_FILE`, `MIND_CONNECTOR_ENDPOINT`, `_KEY_FILE`, `HEARTBEAT_CLASSIFIER_MODEL`, `STATE_DIRECTORY`. | Idunn-managed, sole writer of `heartbeat.cc`. | Install, replace, restart. |
|
|
| Persona template | `/etc/systemd/system/mind-persona@.service`. Instance unit `mind-persona@<i>.service`, `User=mind-%i`, `Type=exec`, no `[Install]`, so it cannot be enabled. | Inactive until started for one Persona turn. Ends by its own exit, at `RuntimeMaxSec=30min`, or by the brake hold's stop (`TimeoutStopSec=30s`, then SIGKILL to the whole cgroup). `Restart=no`, and nothing else restarts it. Every start first runs the gate (below); while the brake is not Released the unit is skipped and ends inactive. `ExecStart` names the Persona organ's binary in the Huginn release; that cut ships the binary and owns the argv. Until then a released start fails at exec (203/EXEC), and the closing launch counts it as a dead run. | Start: `mind-<i>` only, through `open_and_launch` (the waker), by polkit's verb `start` on this one unit name. Stop, kill, restart: root only, which in practice means `mind-control brake hold` (cut brake-stop). Change: root via the script. Enable: nobody. |
|
|
| Self template | `/etc/systemd/system/mind-self@.service`. Instance unit `mind-self@<i>.service`, `User=mind-%i-self`, `Type=exec`, no `[Install]`. | As the Persona unit, with `RuntimeMaxSec=4h`. `ExecStart` names the Self-run actuator's binary in the Huginn release; that cut adds the state directory, `RuntimeDirectory=` (each child's fresh configuration), `MIND_SELF_RUN_CAP_S` equal to `RuntimeMaxSec` in seconds, `CLAUDE_LEASE_SOCKET` and the argv. It adds no token and no `EnvironmentFile` with a credential. | Start: `mind-<i>` only (the Persona's start-Self-run tool through `open_and_launch`), by polkit, verb `start`. Stop, kill, restart: root only. Change: root via the script. Enable: nobody. |
|
|
| Organ user | `mind-<i>`: system user and group, shell `/usr/sbin/nologin`, home `/nonexistent`. | Created by the install script if absent and never modified by it after that. Deleted by root at the mind's retirement. Runs the waker and Persona units. | Root creates and deletes it. It may start `mind-persona@<i>` and `mind-self@<i>`, and nothing else. It cannot write the control store (root 0644, dir 0755) or stop a unit. It can signal its own processes with `kill(2)`, as any Unix user can. That only ends spend, and the ended run is closed Recorded by the next launch, so it adds no second stopper of her units. |
|
|
| Self user | `mind-<i>-self`: system user and group, nologin, home `/nonexistent`. The install script refuses an instance slug ending in `-self`, so this name never collides with another mind's organ user. | As the organ user. | Root creates and deletes it. It starts no unit. Polkit refuses it every verb, and the rule refuses any subject whose name ends in `-self`. |
|
|
| `mind-control` | `/opt/gamecult/huginn/releases/<sha>/mind-control`, root:root 0700, reached by the `current` symlink; `/usr/local/sbin/mind-control` links to `/opt/gamecult/huginn/current/mind-control`. | Built and installed with each Huginn release by the Release step of `runbooks/huginn-yggdrasil.md`. Replaced when `current` flips. The previous release is kept until the new one verifies. | Install, replace: root via the Release step. Run: root only (mode 0700), which covers the operator's verbs and the gate, which systemd runs as root through the `+` prefix. No user of hers can execute it. |
|
|
| `mind-heartbeat` | `/opt/gamecult/huginn/releases/<sha>/mind-heartbeat`, root:root 0755. | Owner of initiative: reads the swarm envelope, the mind (busy, idle, run ends), the mouth (typed sender, `m.mentions`, room) and the connector (classifier urgency, spend); writes `heartbeat.cc` (Initiative per instance, poll traces) and launches Persona turns through `open_and_launch`. The operator tagging or naming a Persona fills its initiative once per message; a member never does. | `mind-heartbeat timeline` prints the latest poll. |
|
|
| The gate | `ExecCondition=+/opt/gamecult/huginn/current/mind-control --instance %i check` in both spending templates. The verb is cut mind-unit-gate. | Runs at every start of a Persona or Self unit. It exits 0 only when `read_effective` is `Released`; held, absent, undecodable or out of bounds exit 2 (systemd skips on 1-254). It holds no state and writes nothing. | Owner: `read_effective`, the one derivation. Change: a Huginn release (the verb) or the script (the line). It closes the window in which a launch that read Released before a hold starts its unit after the hold's stop (follow-up `mind-units-brake-gate`). |
|
|
| Polkit rule | `/etc/polkit-1/rules.d/60-mind-units.rules`, root 0644, source `polkit/60-mind-units.rules` in gamecult-ops. Needs package `polkitd` (absent today, F22; question `mind-unit-start-grant`). | Installed and replaced by the script. Instance-generic: one file serves every mind. | Root changes it. It grants exactly one thing: action `org.freedesktop.systemd1.manage-units`, verb `start`, unit `mind-persona@<i>.service` or `mind-self@<i>.service`, to subject `mind-<i>`. Every other request falls through to systemd's default, `auth_admin`, which an unattended caller cannot satisfy. |
|
|
| Control store | `/etc/gamecult/minds/<i>/control.cc`, root:root 0644 in a 0755 dir (cut mind-control-store). | The install script writes `brake hold` once, if no store exists, so a fresh install reads `held` with a name and time rather than `absent`. Afterwards only the operator's verbs change it. | Operator only (`brake-dial-root-store-now`). |
|
|
| A unit on a brake hold | The instance unit above. | `brake hold` writes the brake held, then stops both units of the instance and waits; the unit ends inactive, its run stays in force. A start after the hold is skipped by the gate and ends inactive (dead), not failed. The next `open_and_launch` of that turn after a release closes the run Recorded "unit not active" (mind-launch r3 step 0). Nothing restarts a stopped unit: `Restart=no`, the waker does not launch without a Grant, and Idunn does not know the unit. | Stopper: the hold only. Restarter: none. |
|
|
| Idunn's view | No binding, no target. | Idunn observes and restarts only workloads it launched itself, and every Idunn workload is a resident service that continuity restarts. It has no one-shot, timer or template kind (F22). So today it never touches these units. The deletion line of the hand install (ruling `mind-units-templated-interim`: Idunn targets before the first hosted member) needs an Idunn job workload that is never continuity-restarted. That is follow-up `idunn-job-workload`. | Idunn: none until that follow-up lands. Its owner then may install and change the templates and users, and must never start or restart a spending unit. |
|
|
|
|
## Rationale
|
|
|
|
### Why the order is leaf, teardown, control, wake
|
|
|
|
The four specs admitted today depend on nothing the operator has to rule except the
|
|
wake target. `leaf-into-huginn` removed the only build edge into Epiphany and is the
|
|
base every Huginn-side body cut needs (the `run` kind re-pointed, Persona state, the
|
|
v3 rename); it landed at `afc35f9`. The teardown removed the 24.7 GB (F5) and the tooling that would otherwise be
|
|
re-read by every later pass; it landed at gamecult-ops `9c12adb`. The control store comes before the waker because the
|
|
waker's first rule is "read the brake before any consequence". The waker raises
|
|
`wake-target`, because the operator's 2026-10-03 ruling (`body-includes-discord`, "the
|
|
Persona session, which is also what drives the Self") and the Defaulted `self-waker`
|
|
("starts at most one Self run") read differently.
|
|
|
|
### One crate for her organs
|
|
|
|
Her organs live in Huginn's workspace (`organ-homes-huginn`). They share the control
|
|
reader, the client and the instance templating, and they deploy together. So they are
|
|
one crate, `mind-body`, with one binary per earned process (`mind-control` for the
|
|
root CLI, `mind-wake`; the Persona organ and permit issuer later), not a crate per
|
|
organ. The crate name is instance-generic because the units are templates.
|
|
|
|
### Who stops her units when the brake is held
|
|
|
|
Ruling `self-run-actuator` says holding the brake stops her running units. Three cuts each
|
|
held part of that and none held all of it (finding
|
|
`cut-mind-control-store.s1.brake-hold-stops-no-units`). The control-store CLI writes the brake.
|
|
mind-launch owns the unit actuator, which had start and alive. mind-wake reads the brake. The
|
|
stop now has one owner: the operator's `mind-control brake hold`. It writes the brake held
|
|
and then, in the same command, runs `SystemdLauncher::stop_all`, a blocking `systemctl stop`
|
|
over the instance's `mind-self@` and `mind-persona@` units (cut brake-stop).
|
|
|
|
- **Synchronous, not on the waker's next tick.** The ruling's own precedent is a stop that
|
|
had to happen at the host. A stop sent as a message was not acted on in time (F20). The
|
|
waker's next tick comes one timer interval later, and mind-wake r2 already keeps the waker
|
|
away from units while the brake is held. Prior art agrees. `systemctl stop` waits for its job
|
|
unless `--no-block` (F19). `kubectl drain` cordons the node and then evicts its pods.
|
|
`supervisorctl stop` waits through `stopwaitsecs` and then kills. In each, the operator's
|
|
command does the stop; no reconciler's next pass does.
|
|
- **Write first, then stop, and stop even if the write failed.** This is cordon before drain.
|
|
A unit that starts after the write must already see the brake held. Stopping is always the
|
|
safe direction, so a failed write does not skip it.
|
|
- **Privilege.** The hold runs as root because the store is root-owned, and root needs no polkit
|
|
rule to stop a system unit. Her users get start only (follow-up `mind-units-brake-gate`), so no
|
|
organ of hers can stop or restart around the operator.
|
|
- **Stop is not on the Launcher port.** `stop_all` is a method on `SystemdLauncher` itself, called
|
|
only from `main.rs`. Code that holds a `Launcher`, such as `open_and_launch` or the waker,
|
|
cannot reach it. The stop patterns come from the same templates as start, so the units
|
|
stopped are exactly the ones started.
|
|
- **Not a mind client.** A Self run killed by a hold cannot record its own end. Its run stays in
|
|
force until the next launch of its turn after release closes it as `Recorded` "unit not
|
|
active" (mind-launch r3). The operator's CLI never talks to the mind.
|
|
- **One race the CLI cannot close.** A launch can read `Released` (its `Grant`), then the hold
|
|
writes and stops, then the launch starts its unit. The unit's own `ExecCondition=` on the brake closes that, so
|
|
the gate belongs with the units install (follow-up `mind-units-brake-gate`), not in a second
|
|
stopper.
|
|
- **Idunn.** Her Self and Persona units are one-shot jobs. Idunn's continuity restarts installed
|
|
daemons, so stopping one of these jobs is not a continuity decision. When Idunn targets
|
|
replace the hand install, Idunn must not restart a unit the hold stopped.
|
|
|
|
### Who decides one live run, and who ends a dead one
|
|
|
|
Soul's verdict `cut-mind-launch.s1` found the one-live rule decided in two places, neither
|
|
of them sound. `open_and_launch` read for a live run and then admitted later, so two
|
|
interleaved launches both passed. The MCP admit door checked nothing, so a second live run
|
|
committed directly. Mind-launch r2 had accepted the race, on the grounds that only a Persona
|
|
turn starts Self runs. Neither the waker nor the Persona tool exists, so nothing enforced that.
|
|
|
|
- **Admission owns the rule.** Batches are serialized (`&mut self`, F21), and admission already
|
|
owns the neighbouring exclusivity, `AlreadyClaimed`. The rule is "at most one in-force run
|
|
with `operated_by: Mind` per instance and turn". That is the ruled option's own text: "one
|
|
run cap in flight per turn kind", with Persona turns one at a time in every option. So the
|
|
waker's own PersonaTurn Busy check goes too. The refusal is a new `MindRefusal` variant,
|
|
`AlreadyLive { run }`. `PipelineRefusal` is the leaf's document-shape vocabulary and stays at
|
|
five variants (F21).
|
|
- **The primitive owns liveness.** Admission cannot see units. A run whose unit died, never
|
|
started, or lost its admit answer would otherwise hold the turn's slot forever. Before it
|
|
checks anything else, `open_and_launch` reads the turn's live holders of hers. It closes each
|
|
one whose unit is not alive and whose admission is older than the 120 s start grace, and
|
|
answers `Busy` for any that remain. That early `Busy` only refuses, so it cannot make a
|
|
second live run; admission stays the authority for races and for direct admits. The waker's
|
|
sweep in mind-wake r2 was a second owner of the same judgement, and r3 deletes it.
|
|
- **Recorded, not Withdrawn.** The breaker treats a withdrawn run as one that never ran. A Self
|
|
unit that crashes every time would then never trip, and would loop at the dial's cadence.
|
|
Closing a dead run as `Recorded` makes a crash an empty ended run, so three in a row raise a
|
|
question. Prior art does the same: a Kubernetes Job counts a failed pod against
|
|
`backoffLimit`, and systemd's `StartLimitBurst` counts failed starts. A start that fails
|
|
inside the launch, before any unit ran, is still Withdrawn.
|
|
- **Lease prior art, and why there is no lease.** A Kubernetes Lease or an etcd lease makes
|
|
liveness a renewal the holder must keep sending. Here the host's unit table already is that
|
|
signal (`systemctl is-active`), so a renewal would be a second owner of the fact
|
|
(`run-is-the-grant`). The cost is that a dead run is only noticed when the slot is next
|
|
wanted. That is also the only moment its being in force matters, apart from the queue's
|
|
claimed-by view. That view is wrong for at most one launch attempt, because the next Self
|
|
launch closes the dead holder first.
|
|
- **Writer-declared `operated_by`.** A writer that declares `Operator` escapes the rule. This is
|
|
the gap already owned by follow-up `operator-authority-needs-operator-credential`, which must
|
|
land before autonomous Self runs. No second guard is added here.
|
|
|
|
### What the breaker counts
|
|
|
|
The ruling's rider says a run is empty when it "admitted nothing but their own run". The
|
|
built breaker counted every document admitted anywhere in the mind during a run's window.
|
|
Under `every-wake-a-run` a PersonaTurn run always lands in that window, so the breaker could
|
|
never trip (finding `breaker-counts-every-document`). Two attributions are available (F21):
|
|
|
|
- **By receipt session.** It is declared by the writer. Nothing makes a Self run's subagents use
|
|
the run label yet. No alias reads it, so the whole-mind scan stays.
|
|
- **By citation of the item (chosen).** Citations are typed content, and one role-less `cites`
|
|
selection on the item returns the runs that claim it, the questions raised in it, and every
|
|
report, resolution, follow-up or deferral that names it. That replaces the whole-mind scan
|
|
with a bounded one. A productive run on a cut spec admits a report, a question, a superseding
|
|
revision or a follow-up. Each of those cites the item, and most also take the item out of the
|
|
queue. Work a Self run does that names another item is not progress on this one.
|
|
- **The reset is a question, not a ruling.** A ruling that answers the breaker question cites the
|
|
question, not the item. Counting only runs admitted after the newest question raised in the
|
|
item makes the trip itself the boundary. A reopened item then starts a fresh count, and the
|
|
10-of-50 rule cannot trip again after one more run. Every trip gets its own key,
|
|
`breaker-<run label>`, so a second trip raises a second question.
|
|
- **Counted runs are hers.** Only `operated_by: Mind` runs count, because the breaker guards her
|
|
loop (`merge-gate-own-soul`), not the operator's sessions.
|
|
|
|
### Why the kit keeps its Codex backend
|
|
|
|
Idunn's migration doc says Codex is dead (F9). The kit is lifted out of CodexConnector,
|
|
and the Codex backend's existing tests are the only proof that the lift is behaviour
|
|
neutral. Keeping the backend compiling costs nothing; deploying it is not proposed.
|
|
Superseded 2026-10-28 by "Where the kit lift's cut line falls" below: a wire parity test
|
|
against the v2 library proves neutrality without porting the backend.
|
|
|
|
### Where the kit lift's cut line falls (cut `connector-kit-lift`)
|
|
|
|
The lift moves only what F27 calls provider-neutral, behind one `ProviderBackend` trait, and
|
|
proves itself by a parity test against the v2 library at `fd7cec4` rather than by porting the
|
|
Codex backend. Three reasons. The Codex daemon has no consumer (F29, ruling
|
|
`no-return-to-openai-supplier`), so porting it buys nothing the parity test does not prove more
|
|
directly. Leaving it out makes the cut independent of question `codex-connector-fate`. And it keeps
|
|
B2 a pure move (verbatim code, `Codex` stripped from Rust names, wire bytes unchanged), so Soul can
|
|
falsify the move alone, and B3 owns every contract change: ids, the reasoning item, spend, and the
|
|
Responses-shaped request fields (F27). This supersedes "Why the kit keeps its Codex backend" above,
|
|
whose premise (the backend's tests are the only proof of neutrality) the parity test removes.
|
|
Idunn presence (`idunn_health.rs`) is not lifted with it: it is deployment, and is checked
|
|
against Idunn's current presence contract when a connector binary is first deployed (B4).
|
|
|
|
### Where the contract v3 cut line falls (cut `connector-contract-v3`)
|
|
|
|
B3 as one cut (wire, request shape, reasoning item, spend) reads the whole kit and rewrites most
|
|
of it, past half of a Hands pass. It splits along owners, each falsifiable alone, all landing
|
|
before B4 so no consumer ever sees an intermediate v3:
|
|
|
|
- B3a `connector-contract-v3` (spec r2): the wire and the documents. One codec owner (named
|
|
MessagePack, unknown fields refused), one carriage owner (a CultNet operation, if
|
|
`connector-v3-wire` goes as recommended), typed outcomes and refusals, the request made
|
|
provider-neutral, v2 deleted, schemas published from the types. It folds in
|
|
`v3-ciphertext-as-bytes` and the parts of `kit-contract-test-debt` in code it rewrites, and
|
|
takes the CultLib bump from B4 because cultnet-rs must be at the rev cultcache-rs is.
|
|
- B3b `connector-reasoning-item`, settled here so its spec is quick (research section 5): one
|
|
`ReasoningState {provider, model, state: bytes}` per provider block, in transcript order, as
|
|
both an `InputItem` and an event, the bytes the connector's encoding of the whole block; a kit
|
|
function that turns a result's events into transcript items, so no caller branches on provider;
|
|
`ProviderBackend` declares its provider tag; the service refuses foreign state after the last
|
|
user text (`ForeignReasoningState`) and drops it elsewhere before the backend sees it, counting
|
|
the drop on the receipt. A backend receives a call that cannot show it a foreign item.
|
|
Placed by spec `cut-connector-reasoning-item.r1` (F32): the event carries the bytes alone and
|
|
the kit stamps provider and model from the receipt when it builds transcript items, and the
|
|
receipt's provider and drop count are derived by the service (`ProviderCall::transported`,
|
|
gated in `complete`), so a backend can neither see foreign state nor mis-tag its own. Only a
|
|
`Completed` result yields transcript items: a partial thinking block is never replayed.
|
|
- B3c `connector-spend`: price table in the connector's config, `max_cost` on the invocation,
|
|
a worst-case reservation (input estimate plus `max_output_tokens` times the output price) held
|
|
in the replay store and settled to actual, cost on the outcome, a `Budget` refusal, fail
|
|
closed when the ledger cannot be written (ruling `connector-owner`; LiteLLM and OpenRouter
|
|
both reserve this way). Its map raises how the connector's per-caller ceiling relates to her
|
|
run's `budget_usd` (invariant `run-is-the-grant`, ruling `turn-cost-measured`) and whether
|
|
amounts are integer micro-dollars or the mind's canonical decimal string.
|
|
Placed by spec `cut-connector-spend.r1` (F33):
|
|
- The ledger is the connector's replay store, not her mind and not mind-body's control store.
|
|
The rulings settle it: `brake-dial-root-store-now` keeps the spend ledger with the wallet,
|
|
outside what she merges; its question names "the connector's max_cost_usd and ledger
|
|
(another user)" as an enforcement point outside her writable environment; `turn-cost-measured`
|
|
names the connector ledger as the Persona turn's cost source; `connector-owner` makes it
|
|
durable and fail-closed. `run-is-the-grant` binds her organs, and the connector is the
|
|
wallet's, not hers. The reservation lives in the replay record itself, so reserving and
|
|
claiming the request are one `put` (P1): there is no second record to drift.
|
|
- Amounts are integer micro-USD (`u64`), prices micro-USD per million tokens, cost rounded up
|
|
once per request. Not a fork: exact arithmetic needs integers or a decimal, cultcache-rs has
|
|
no decimal (follow-up `cultcache-rs-decimal-and-nofollow`), and a canonical decimal budget of
|
|
at most six places converts exactly at the Persona organ (B5).
|
|
- The input bound is the named-MessagePack length of the provider request plus a per-model
|
|
overhead from the price table: a byte-level BPE token is at least one byte, so text cannot
|
|
exceed it (unprobed against a real tokenizer; B4's rider). It is priced at the dearest input
|
|
rate the request's cache retention allows.
|
|
- Two refusals, not one `Budget`: `CostBound` (the worst case exceeds the invocation's own
|
|
`max_cost_micro_usd`, decided by the invocation alone, before the replay lookup) and
|
|
`SpendCeiling` (the caller's window cannot hold the reservation, after the replay lookup, so
|
|
a recorded answer is always replayed). OpenRouter tells its limit sources apart the same way.
|
|
- What bounds the caller's total is question `connector-spend-ceiling`: `max_cost` is written by
|
|
her own Persona organ, which she may rewrite (`she-owns-her-body`), so it is not a wallet
|
|
control on its own.
|
|
|
|
### Where the Claude connector cut line falls (map line B4)
|
|
|
|
B4 as one cut (backend, binary, config document, credential delivery, Idunn presence, spend
|
|
readout, retention, clock recovery) is three owners and well past one Hands pass: the presence port
|
|
alone is 1,396 lines in CodexConnector (F34). Ruling `claude-connector-via-claude-code`
|
|
(2026-10-29, operator) answered the credential question: the first Claude backend drives the
|
|
`claude` binary on the operator's subscription, not the Messages API with a Console key. It
|
|
splits so each part is falsifiable alone:
|
|
|
|
- B4a `claude-code-backend` (landed, ModelConnector `200933f`, spec `cut-claude-code-backend.r1`,
|
|
F35): `ClaudeCodeBackend` as a library crate, tool-less turns, session-handle reasoning state
|
|
(ruling `claude-code-handle-reseeds`), usage from `model_usage_since_last_result` (ruling
|
|
`claude-code-plan-quota-fuse-2`). The kit is unchanged, so the in-flight boundary (follow-up
|
|
`claude-tool-exchange-boundary`) was not moved here; it belongs to B4d.
|
|
- B4b `claude-connector-binary` (next): the `claude-connector` binary, its config document
|
|
(CultCache, root-owned: listen address, `ServeLimits`, callers, the `ClaudeCodeConfig` fields,
|
|
the price table with one `ModelPrice` per allowed model in list-price units and
|
|
`overhead_tokens` for the harness preamble), credential delivery
|
|
(`CLAUDE_CODE_OAUTH_TOKEN` from a root-0600 EnvironmentFile to the connector's own unit user,
|
|
readable by no unit of hers), the pinned `claude` binary digest, and deployment. Its map raises
|
|
whether Idunn deploys it now (presence rebuilt from `idunn_health.rs` against Idunn's current
|
|
contract) or it is hand-installed beside her units until `idunn-job-workload`
|
|
(`mind-units-templated-interim` is the precedent). It carries follow-ups
|
|
`spend-window-clock-recovery` and `claude-byte-bound-live-check`; the first live tool-less turn
|
|
is its operator check, and confirms `CLAUDE_CODE_MAX_OUTPUT_TOKENS` under the pinned binary.
|
|
- B4c `connector-spend-readout`: the spend read operation beside `invoke` and replay-store
|
|
retention (follow-ups `connector-spend-readout-2`, `replay-store-retention`). Kit code, needed by
|
|
the turn-cost charge (A8, B5), not by the first live turn.
|
|
- B4d `claude-tool-exchange`: ruling `claude-code-runs-her-tools` (operator, 2026-10-29) lets the
|
|
claude process run her tool loop over MCP, so one kit call becomes a whole agent loop, and
|
|
`self-run-actuator-2` restates the actuator ruling to match (the connector may host her Persona
|
|
turn's tool loop on this backend). The cut owes: the kit reserves for the whole call, not one
|
|
turn; the process carries `--max-turns` and a budget cap; her tools never inherit the
|
|
connector's environment, where the subscription token lives, so they run as MCP servers in her
|
|
own unit that claude reaches, or under a scrubbed environment (`token-out-of-her-reach` holds);
|
|
`--mcp-config` and `--tools` leave B4a's forbidden list for exactly that surface; the kit's
|
|
in-flight boundary and `partition_reasoning` change (F34 P1). It waits on B4b.
|
|
- Later, off the path: a Console-key Messages API backend (follow-up `claude-api-backend`, owner
|
|
Self when quota contention is observed), from the withdrawn spec `cut-claude-backend.r1`, whose
|
|
probes (F34) and anchors are its raw material. Its provider tag differs from `claude-code`, so
|
|
the kit treats each backend's reasoning state as foreign to the other.
|
|
|
|
B4a touched none of the code `kit-contract-test-debt` names, so that follow-up stays open for the
|
|
next cut in `contract.rs`, `client.rs` or `envelope.rs`.
|
|
|
|
### How a Self run is carried (cut `mind-self-run`)
|
|
|
|
The run document is the grant (`open_and_launch`); the unit takes only `--instance`
|
|
(`mind-units-install` r2). So the actuator learns which run it carries from the mind: the one
|
|
in-force `operated_by Mind` Self run of its instance, which admission keeps unique
|
|
(`run-live-admission`). No run, no `claude`: a unit started by hand carries nothing.
|
|
|
|
- Owner: `mind_body::self_run::carry`, inside `mind-self@<i>`, decides the argv, the session
|
|
id, when to ask for the flush and when to interrupt.
|
|
- Inputs: its run (budget, claims, id) from the mind; the child's stdout stream; the clock.
|
|
- Outputs: one `claude` child; the start message; at most one flush message; stdin closed at
|
|
the first `result`; at most one interrupt; an outcome line and an exit status.
|
|
- Derived: the request's prefix (F24, keyed on `message.id`, main thread only); the session id
|
|
(UUIDv5 of the run id, so the measure cut can find the transcript and resume it).
|
|
- Not its decision: continuation (fresh only until `self-run-measure`), the brake (the unit's
|
|
gate), the stop (the hold), the budget (the run's `budget_usd`, from the dial at launch),
|
|
the environment, token and permissions (the unit and managed settings, gamecult-ops).
|
|
- Robust to F25's open point: the flush is written only before the first `result`, stdin closes
|
|
at that `result`, and if the child has not exited `FLUSH_GRACE` after the flush, or the
|
|
prefix passes `CEILING_TOKENS + FLUSH_ALLOWANCE_TOKENS`, it is interrupted once. A queued
|
|
message that is never delivered costs the flush, never the stop.
|
|
|
|
### Swarm by 2026-10-30 (Imagination `imagination-swarm-tonight`, 2026-10-29)
|
|
|
|
Ruling `self-runs-through-connector` (operator) makes this the top priority: Eureka hears and
|
|
speaks in Matrix, takes turns through the Claude connector on one token, starts her own Self runs
|
|
and reads the communal burn into #burn, under the operator's brake and dial. Units are
|
|
hand-managed on Yggdrasil tonight (follow-up `swarm-units-under-idunn`).
|
|
|
|
Flow: a message in #swarm, #burn or #operator reaches the Bifrost mouth (`persona-mouth`, the only
|
|
holder of @eureka's Matrix token, ruling `persona-matrix-account-interim`), which queues a typed
|
|
delivery and rings `mind-persona@eureka`; the waker rings it on cadence too
|
|
(`persona-turn-drains-deliveries`). The unit's gate reads brake and dial; `mind-persona` builds a
|
|
turn (persona state, deliveries, her runs, the connector's spend and plan-quota readout), calls the
|
|
connector tool-less with a JSON Schema, and decodes one typed `PersonaReply`
|
|
(`persona-reply-typed-by-schema`): say items go back to the mouth, a `start_self_run` admits a brief
|
|
follow-up and calls `open_and_launch` (`self-run-brief-claimed-follow-up`). `mind-self@eureka`
|
|
leases the token from the connector on a pipe fd over a peer-uid unix socket and runs claude in her
|
|
own user and workspace (`self-run-credential-lease`); the connector reserves and settles in its
|
|
ledger. The brake hold stops both units; the mouth refuses sends while held.
|
|
|
|
Authority: connector = token, admission, ledger, plan-quota observation; mind-control = brake and
|
|
dial; Bifrost = Matrix credential, ear, mouth; mind-persona = the turn and the decision to start a
|
|
Self run; mind-self-run = the Self run's process (argv, flush, interrupt). Demoted: A5's token
|
|
EnvironmentFile (never lands), A6 `mind-launch-self` (not built; the Persona opens runs, ruling
|
|
`first-self-run-starter`), the Discord posting actuator (deleted in `persona-mouth`).
|
|
|
|
Cuts (specs `cut_spec:cut-<label>.r1`), all dispatchable now in parallel:
|
|
`claude-turn-schema-quota` and `claude-self-run-lease` (ModelConnector; merge in that order),
|
|
`mind-persona` and `mind-self-via-lease` (Huginn), `persona-mouth` (Bifrost),
|
|
`swarm-connector-yggdrasil` and `swarm-units-yggdrasil` (gamecult-ops). Then bring-up (Self and
|
|
operator): token minted, releases built, scripts run as root, smoke turn, dial set, brake released,
|
|
`mind-wake@eureka.timer` enabled. Open: questions `eureka-forge-write-tonight`,
|
|
`who-directs-self-runs`. Not on tonight's path: B4d tools in Persona turns, the appservice
|
|
(follow-up `matrix-appservice-persona-identity`), the swarm scheduler (C3), more instances (C2).
|
|
|
|
### Cut sequence (refreshed 2026-10-22, Imagination `imagination-self-run`)
|
|
|
|
Landed on Huginn main `70d0cef`: leaf-into-huginn, mind-control-store, run-live-admission,
|
|
mind-launch, brake-stop, mind-unit-gate, mind-wake, huginn-persona-state (`766cba4`). In flight:
|
|
`mind-units-install` r2 (gamecult-ops, Hands now). One line per remaining cut: title (repo),
|
|
then what it waits on. Ids without a prefix are `eureka-body:`.
|
|
|
|
**A. To "Eureka runs a Self run on Yggdrasil"** (critical path: A2, then A5 with the
|
|
operator's token, then A6 and the bring-up; A3, A4 and A1 run beside it):
|
|
|
|
1. `mind-units-install` r2 (gamecult-ops): in flight; its host half waits on a Huginn release
|
|
that holds mind-wake (main `70d0cef` does).
|
|
2. `mind-self-run` (Huginn): spec `cut_spec:cut-mind-self-run.r1`. Waits on nothing.
|
|
3. `mind-body-riders` (Huginn): spec `cut_spec:cut-mind-body-riders.r1`, runs beside A2.
|
|
Waits on nothing.
|
|
4. `skill-mind-self` (Eureka repo): the Self brief her run is told to use: rehydrate from the
|
|
mind, work the run's claims, flush (admit what the mind lacks, close her own run), end.
|
|
Waits on nothing but A2's message contract (the two prompt constants in
|
|
`cut-mind-self-run.r1`).
|
|
5. `self-run-environment` (gamecult-ops): the `mind-self@` lines A2 leaves to ops (`StateDirectory`, `WorkingDirectory`, `RuntimeDirectory`,
|
|
`MIND_SELF_RUN_CAP_S` (= `RuntimeMaxSec`), optional `MIND_SELF_CONFIG_SEED`, `CLAUDE_LEASE_SOCKET`, `HUGINN_ENDPOINT`), Claude Code and the `huginn` CLI on Yggdrasil (follow-up
|
|
`eureka-substrate:follow_up:huginn-cli-on-yggdrasil`), the skill installed from A4, git and
|
|
forge reach for her work, the root-owned managed settings. Waits on A1, A2, question
|
|
`question:self-run-permissions`, and the connector's `--lease-max-ms` at least the cap plus
|
|
slack (rulings `self-runs-through-connector`, `self-run-credential-lease`: no token in her unit).
|
|
6. `mind-launch-self` (Huginn): the one binary that opens a Self run through
|
|
`open_and_launch`; the Persona's start-Self tool later, the operator's bring-up now.
|
|
Waits on question `question:first-self-run-starter`.
|
|
7. Bring-up (Self and operator, not a cut): Huginn release with A2 and A6, the Release step
|
|
building them, install, brake release, dial set, one Self run started by A6.
|
|
8. `self-run-measure` (Huginn, plus one gamecult-ops line): `runs.cc` and
|
|
`eureka.body.run_measure.v1`, the root `ExecStopPost` verb that reads the transcript (F24),
|
|
`$SERVICE_RESULT` and whether her run is closed, then the resume decision and the rental
|
|
rule in the actuator. Waits on A2 (ruling `run-measure-in-body-store`). Not on the path to
|
|
the first run: A2 runs every run fresh, which the ruling allows (a cold cache is fresh).
|
|
|
|
**B. To "Eureka speaks a Persona turn"** (critical path: B2, B3a-c, B4, B5, B6; refreshed
|
|
2026-10-28, Imagination `imagination-kit-lift`):
|
|
|
|
1. Done 2026-10-28: `target:r2` carries the eight-repo set with GameCult/Idunn and
|
|
GameCult/ModelConnector (follow-up `body-campaign-repos` Fixed by Huginn `f8eaf50`); the kit
|
|
repo is GameCult/ModelConnector on the forge (`connector-kit-repo-modelconnector`).
|
|
2. Landed 2026-10-28: `connector-kit-lift` (ModelConnector main `ec0519d`, spec
|
|
`cut_spec:cut-connector-kit-lift.r1`, relicensed by ruling `connector-kit-relicense-agpl`).
|
|
- Beside it, off the critical path: `codex-connector-park` (CodexConnector, gamecult-ops;
|
|
ruling `codex-connector-park`).
|
|
3. `connector-contract-v3` (ModelConnector), split three ways (rationale "Where the contract v3
|
|
cut line falls"):
|
|
- a. `connector-contract-v3`: spec `cut_spec:cut-connector-contract-v3.r2`. Waits on B2
|
|
(landed, `ec0519d`) and questions `question:connector-v3-wire` and
|
|
`question:connector-v2-coexistence`.
|
|
- b. `connector-reasoning-item` (ModelConnector): spec
|
|
`cut_spec:cut-connector-reasoning-item.r1` at `bf958fc`; B3a has landed, so it is ready to
|
|
dispatch. Follow-up `connector-reasoning-state-cheap-providers` is answered by research
|
|
`725f5a5` section 1d and needs no kit rule (every provider's state stays opaque bytes).
|
|
- c. `connector-spend` (ModelConnector): spec `cut_spec:cut-connector-spend.r1` at `1d51e71`.
|
|
B3b has landed; it waits on question `question:connector-spend-ceiling`.
|
|
4. `claude-connector` (ModelConnector; rulings `persona-first-connector-claude`,
|
|
`claude-connector-via-claude-code`), split four ways (rationale "Where the Claude connector cut
|
|
line falls"):
|
|
- a. `claude-code-backend`: landed 2026-10-29 as ModelConnector `200933f` (spec
|
|
`cut_spec:cut-claude-code-backend.r1`, report `h2`, verdict `s2`). The withdrawn
|
|
`cut-claude-backend.r1` (Console-key Messages lowering) is raw material for the later
|
|
`claude-api-backend`.
|
|
- b. `claude-connector-binary` (next; ModelConnector, gamecult-ops or Idunn): the binary, its
|
|
CultCache config document and price table, credential delivery, deployment and Idunn
|
|
presence on Yggdrasil, follow-ups `spend-window-clock-recovery` and
|
|
`claude-byte-bound-live-check`; its map raises Idunn-now versus hand-install.
|
|
- c. `connector-spend-readout` (ModelConnector): follow-ups `connector-spend-readout-2`,
|
|
`replay-store-retention`. Kit code, ready now that B4a has landed; due before the turn-cost
|
|
charge (A8, B5).
|
|
- d. `claude-tool-exchange` (ModelConnector, with her tool MCP servers): claude runs her tools
|
|
over MCP (ruling `claude-code-runs-her-tools`); her tools never inherit the connector's
|
|
token. Waits on B4b.
|
|
- Later: `claude-api-backend` (follow-up), a Console-key API backend.
|
|
5. `mind-persona` (Huginn): the Persona organ, one connector request per turn (a whole tool loop once B4d lands)
|
|
(`persona-turn-connector`), Persona state through Huginn (landed), the start-Self tool (A6),
|
|
traces with provenance from day one (`collect-with-provenance-gate-at-training`). Waits on
|
|
B4 and on where traces live (question `persona-trace-retention` was withdrawn to be re-asked
|
|
with the trace store; re-ask it when B5 is mapped).
|
|
6. `persona-mouth` (Bifrost or gamecult-ops): Matrix (ruling `persona-mouth-matrix`; Discord
|
|
stays out, `gamecult-chat:ruling:discord-taints-training`). Waits on B5 and on the Matrix
|
|
deployment (`chat-platform`, `chat-stand-up-now`; follow-up
|
|
`identity-minting-moves-to-bifrost` precedes the chat rollout).
|
|
|
|
**C. Beside both paths:**
|
|
|
|
1. `fork-desk-web` (Huginn, or a repo Self names): a web UI over Huginn (ruling
|
|
`fork-desk-web-ui-on-huginn`). Waits on an identity-lifecycle-authority pass over the
|
|
Eyes facts at Huginn `70d0cef` (`docs/research/`, fork desk prior art) and on Self naming
|
|
its home.
|
|
2. `first-autonomous-minds` (Huginn, gamecult-ops): one instance per shortlist mind
|
|
(`first-autonomous-minds-shortlist`). Waits on A7, A8, follow-up `weksa-mind` (multi-instance
|
|
and eureka-substrate Cut 12 leasing) and the swarm scheduler (C3).
|
|
3. `swarm-ctb-scheduler` (Huginn): rulings `mind-scheduling-ctb`, `swarm-dial-one-budget`,
|
|
`swarm-scheduler-one-shot`, `turn-cost-measured`. Waits on A8 (its cost source).
|
|
4. `idunn-job-workload` (Idunn): the deletion line of the hand install. Idunn joined the
|
|
campaign in `target:r2`; due before the first hosted member (`mind-units-templated-interim`).
|
|
5. `wire-names-rename` (Huginn, Eureka): before the first hosted mind
|
|
(`wire-names-rename-before-hosting`). Waits on nothing; schedule before C2.
|
|
6. `doctrine-repoint` (Eureka, F12), then `epiphany-archive` (last).
|
|
|
|
## Admitted this pass (receipts in the mind)
|
|
|
|
Specs, in dependency order: `eureka-body:cut_spec:cut-leaf-into-huginn.r1`,
|
|
`cut-epiphany-body-teardown.r1` (independent), `cut-mind-control-store.r1`,
|
|
`cut-mind-wake.r1` (superseded by r2 on 2026-10-09).
|
|
Questions: `eureka-body:question:wake-target`, `self-run-token-reach`,
|
|
`persona-trace-retention`. Follow-ups: `eureka-body:follow_up:substrate-specs-repoint`,
|
|
`body-campaign-repos`. H9 sources exist at Epiphany ef956865: notes/huginn-organ-cut.md,
|
|
eureka-body-plane-cut.md, eureka-pipeline-state-cut.md, eureka-pipeline-state-target.md,
|
|
eureka-query-prior-art.md, eureka-read-side-cut.md, postmortem-eureka-schema-phase.md.
|
|
Huginn carries an AGPL-3.0 LICENSE and the workspace license is AGPL-3.0-only
|
|
(rulings `license-split`, `eureka-body:ruling:leaf-relicensed-agpl`).
|