diff --git a/docs/eureka-body-map.md b/docs/eureka-body-map.md index d353bc6..7451bf3 100644 --- a/docs/eureka-body-map.md +++ b/docs/eureka-body-map.md @@ -91,6 +91,14 @@ spec `cut-claude-backend.r1`. New fact F35. The B4 rationale and path B line 4 a page changed and a Claude connector backend row was added. F34's repo-state sentence keeps its tense. +Revised 2026-11-02 by Modeling (session `self-2026-11-02-eureka`) at Huginn `ffd4136` and +gamecult-ops `477d0d2`, with a read-only look at Yggdrasil the same day. Ruling +`persona-session-landed` replaced the one-shot Persona turn: the units rows, the Idunn sentence and +the "Swarm by 2026-10-30" flow are rewritten or marked historical, the section "The Persona session" +and the governance list are added, model-page rows for the session, sandbox, fence and doctrine +set are added, and facts F36-F40 are new. Claims the source note marks as inference or +unconfirmed keep that marking here. + ## Pinned heads (fetched 2026-10-08 ~12:10 UTC) | Repo | Ref | Commit | Note | @@ -494,6 +502,12 @@ Each line: what was run, where, result. 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`. +- **F36-F40 (Modeling, 2026-11-02, Yggdrasil read-only).** + F36 `ssh yggdrasil` 2026-11-02: units active: `mind-fence`, `mind-heartbeat`, `mind-persona@{eureka,kiko,nibu,void,weksa}`, `mind-self@{eureka,heimdall,kiko,void}`, `huginn.service` (eureka) and `huginn@{aqua,heimdall,kiko,libby,nibu,void,weksa}`. Deploy `/opt/gamecult/huginn/current` -> `releases/ffd4136a35355587a1a6d04c3cc42d8fabc31e86` = Huginn main head. + F37 `systemctl cat mind-persona@.service`: `Requires/After=mind-fence.service`, `User=mind-%i`, `RuntimeMaxSec=4h`, `Restart=no`, `KillMode=control-group`, `ProtectSystem=strict`, seed `persona-seed`. + F38 `nft list table inet mind_fence`: 8 persona uids, 8 uid.port huginn pairs (17872-17879), chain `persona` with reject rules. + F39 `/opt/commons` modes as in the Persona session section; `id mind-eureka` shows no `mind-commons`; `systemctl cat mind-self@.service` shows `SupplementaryGroups=claude-lease mind-commons`, `ReadWritePaths=/opt/commons`. + F40 `grep pombabranca /etc/nginx/sites-enabled/*`: no match; `/site` and `/site/` locations present in `yggdrasil.gamecult.org.conf` (lines 50, 54). Retired `/pombabranca` (7586a3f). A pre-ghostlight backup `sites-available/yggdrasil.gamecult.org.conf.before-ghostlight-*` still names `/pombabranca` but is not enabled. ## The model page (step 0b) @@ -510,13 +524,18 @@ pipeline kinds are in Huginn `docs/eureka-substrate-map.md`. | 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. | +| Claude connector backend (B4a, landed `200933f`; the Persona does not use this backend, it borrows a lease like the Self) | `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. Unconfirmed 2026-11-02: `FileTrace`/`TurnTrace` exist in `persona.rs`; whether they are the retention answer is not checked against the question's state. | | 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. | +| Persona session | Process `claude` under bwrap in `mind-persona@`; id uuid5(run, `p`); one conversation per process | Ends at cache TTL, near the 4 h cap minus `ROTATE_MARGIN_S`, at the context ceiling's flush, or when another conversation's delivery is the oldest unanswered; next process rehydrates from the mind | The Persona organ (lifetime, input, acks); the mind is truth; heartbeat only starts units | +| Persona sandbox | `/var/lib/mind-/sandbox` | Kept between processes; the only place her tools write (besides the fresh config dir) | Her; nobody else reads it. Not a source of truth for anything. | +| Mind fence | nft table `inet mind_fence` | Reloaded at every Persona start; absent after any nft flush until then | gamecult-ops | +| Persona doctrine set | `MIND_PERSONA_DOCTRINE` | Changed only by an installer run at a new skill pin | gamecult-ops installer + Eureka skill repo | +| Web publish surface | **Not built.** Ruling `every-mind-publishes-web-builds`; spec `hands/eureka-body-minds-web` waits on a domain. Prior-art note: gamecult-ops `docs/research/2026-11-02-artifact-host-safety.md`. | n/a | Void's Self unit may write `/srv/site` (e827f70); `/site/` on `yggdrasil.gamecult.org` is the interim beta and is `mind-void-self`-owned (live `drwxrwsr-x mind-void-self`) | | 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@: