Serves eureka-body:ruling:fork-desk-web-ui-on-huginn (session sp-reentry-2026-10-20). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
50 KiB
Eureka fork desk: a web UI on Huginn where the operator answers forks
Eyes pass, 2026-10-20, session sp-reentry-2026-10-20. Facts and evidence pointers only; no conclusion, no recommendation.
Serves eureka-body:ruling:fork-desk-web-ui-on-huginn and eureka-body:ruling:first-autonomous-minds, which the coordinator reports is superseded by eureka-body:ruling:first-autonomous-minds-shortlist (admitted 2026-10-20T13:31:00Z, ordinal 3110, viewed 2026-10-20; the supersession Resolution document itself was not viewed). Rulings viewed at ordinals 3109 and 3110, authority Operator. Revision note: corrected the same day to cover all eight shortlisted Personas, not three.
Repo state read: Huginn 0b3cac3 (2026-10-10, working tree on disk), CultLib e9c563eb, Heimdall 5952cce, gamecult-ops 5c7dfc8, gamecult-site 9bd39bb (brand doc and quartz config), Eureka skill 979b190. Web pages: "accessed 2026-10-20". Mind facts cite eureka-state view or query on instance eureka, as_of 3109.
Not established, listed once here: (a) the content of the live questions/answers collections of the two artifacts (the data model below is read from the page code, not from stored rows); (b) whether the deployed Huginn daemon matches the on-disk Huginn 0b3cac3 (the on-disk schema index lists epiphany.pipeline.*.v2; whoami reports schema_epoch epiphany.pipeline.epoch.v2); (c) any design for an operator credential beyond the follow-up text; (d) any route from a browser to Huginn; (e) desk-ready pose sets for the six Personas other than Libby and Nibu (none in either desk artifact; branch cells exist for most, status unknown); (f) a campaign-to-Persona mapping, and a Huginn instance for any shortlisted Persona other than eureka; (g) operator verdicts on rounds 2-4 of the Flux busts (blank in the README).
1. What exists today
1.1 The two artifact desks
Both read with the Artifact tool read action, 2026-10-20.
- Nibu's desk: https://claude.ai/artifact/HccfYaXb84FMEPAWRyf8aY, artifact id
868b3ac5-762d-47f6-b1ae-c4ab1100d3c5, version1792103971-6b36, title "Nibu's Fork Desk", 10 files (index.html20340 bytes,poses/nibu/{concerned,determined,happy,idle,neutral,note,surprised,thinking,triumph}.webp), capabilities{"db":{}}, contract 0.2.81. - CultLib desk: https://claude.ai/artifact/LBZMjcWDLjQtwkqJTLzfR4, artifact id
9b570364-a424-474f-853b-5243f8378363, version1792103848-7827, title "Fork Desk", 19 files (index.html20333 bytes,poses/libby/*andposes/nibu/*, the same nine moods each), capabilities{"db":{}}. - The two
index.htmlpages are the same program (a 7-byte size difference); the persona is chosen at runtime by thedesk/configdocument, with a hard-coded defaultlibby(script:let persona = "libby",PERSONAS = {libby, nibu}).
Data model, from the page script (both artifacts; page-owned db capability via window.claude.use("db")):
| Collection / doc | Fields read or written | Writer |
|---|---|---|
desk/config (single doc) |
persona (key into PERSONAS), kicker, title |
Self |
questions/<docId> |
qid (display id), title, body (pre-line text), depends, flag (provisional note), rec (recommended option key), lean (Self leans; shown only when different from rec), options[] of {key, label, text} (needs >= 2 or the doc is hidden), status (open default, closed), ruling (id shown in the "recorded" list), order (number sort key) |
Self |
answers/<docId> |
choice (option key or null), note (free text), question (the qid), updatedAt (ISO string) |
the page, as the viewer |
Page behaviour (same script): radio choice plus an optional free-text note per question; the answer saves on pick and 900 ms after typing stops; a viewer who gets invalid_argument or permission_denied on save sees the desk go read-only; a single persona portrait sticks in a side booth (fixed bottom corner under 760 px) and changes among nine moods on events (pick equals rec shows happy, off-script pick shows surprised, all answered shows triumph, note focus shows note, save failure shows concerned); closed questions fold into a "recorded as rulings" list of qid -> ruling; the page states that changing an answer is fine "until it's admitted as a ruling", after which it becomes a new ruling in the session. Source: the index.html of each artifact, read 2026-10-20.
How answers flow back (what Self does by hand), from memory note C:\Users\Meta\.claude\projects\F--Projects-CultLib\memory\forks-go-on-the-desk.md (modified 2026-10-17T16:25:53Z):
- Self writes each open question to a desk once it is admitted and has had its prior-art pass. Doc id is the question label on Nibu's desk and the full question id on the CultLib desk; fields
rec,status: open, plusleanandflagon the CultLib desk. - Self reads the operator's answers from the
answerscollection (the note says "read both desks'answers" when she says she answered). - Self admits each answer as a ruling in the mind (admission derives the
Answeredresolution of the question). - Self closes the desk doc with
status: closedand the ruling id. - Before posting, Self searches the mind's rulings for the topic (semantic
query), because a question was posted that a ruling had already retired (2026-10-17,minor-power-geonames). The artifact store is therefore a second, page-local copy of each question and answer; the mind holds the typedquestionandrulingdocuments. Nothing in the artifact links back to the mind except theqidstring and therulingid Self writes by hand.
Related in-house notes:
forks-for-understanding.md(modified 2026-10-03, same directory): one fork at a time with context line, options, recommendation and what depends; never an "accept all" bundle; catch-up briefings read options from thequestiondocument, never from a handoff one-liner. Operator quote, 2026-09-29: "Even if I end up agreeing, I still have to understand the decisions being made. My decisions are the only reason anything gets done."option-text-is-not-her-words.md(2026-10-17): a pick endorses the core choice; a side clause in option text we wrote ("no galaxy presence") was built into a flag across three spec revisions and was not hers. Operator, 2026-10-17: "This is not the same as banning factions from appearing."observation-is-not-a-ruling.md(2026-10-14): a remark is not a ruling;relay-operator-words-verbatim.md: a ruling'srulingtext says only what she said.- The Eureka skill at
C:\Users\Meta\.claude\skills\eureka(979b190) contains no match for "fork desk" (grep, 2026-10-20).
1.2 The three rulings (full text, viewed 2026-10-20)
eureka-substrate:ruling:fork-desk-reusable (admitted 2026-10-15T22:14:02Z, ordinal 2415, ruled_on 2026-10-16, authority Operator, session self-2026-10-15-eureka).
- operator_quote: "It would be a good idea to turn this into a reusable flow so we don't have to reinvent the wheel every time. As a Eureka feature it fits into the UX nicely, it's much more friendly than answering a list of forks in prose"
- ruling: After Self put five forks to her as a claude.ai artifact (cards with options, Libby's poses, answers saved to the page's store), the operator directed that this become a reusable Eureka flow. Her words decide that it is built and that it is a Eureka feature; the shape (one persistent desk Self feeds, persona poses, answers read back into rulings) is Self's design.
eureka-substrate:ruling:fork-desk-nibu-format (admitted 2026-10-15T22:32:54Z, ordinal 2421, ruled_on 2026-10-16).
- operator_quote: "Nibu's fork desk actually turned out a bit more stylish than Libby's (build by the other Self), I'd prefer this format for the standardized version we're shipping, with a single character that follows the viewport and changes expressions on interaction"
- ruling: The operator chose the Aetheria Self's Nibu fork desk (artifact
HccfYaXb84FMEPAWRyf8aYv2) over Self's Libby desk as the format: a single character that follows the viewport (sticky booth on desktop, fixed corner on phones) and changes expression on interaction, rather than one persona image per card. Relayed verbatim by the Aetheria/Ghostlight Self (sessionself-2026-10-15-ag3) on 2026-10-16; Self did not hear it directly. Refinesfork-desk-reusable, which stays in force.
eureka-substrate:ruling:fork-desk-presenter-follows-work (admitted 2026-10-15T22:38:24Z, ordinal 2422, ruled_on 2026-10-16).
- operator_quote: "That's not to say that the questions should be coming from Nibu. She was the one presenting because the work was Aetheria-related, and here the work was CultLib-related"
- ruling: Clarifying
fork-desk-nibu-format: the standard takes Nibu's desk format, not Nibu as the presenter everywhere. Nibu presented because that work was Aetheria-related; CultLib work is presented by Libby. The presenter is chosen by the work's domain; the two names are her examples, not a closed mapping.
The two rulings this pass serves:
eureka-body:ruling:fork-desk-web-ui-on-huginn (admitted 2026-10-20T13:27:11Z, ordinal 3109, session sp-reentry-2026-10-20).
- operator_quote: "the fork desk thing is cool but we can do better than the artifact we have if this is gonna be a Eureka feature which I think it should be ... Thing 2.0 is still under construction, so I think a web UI that talks to Huginn is an acceptable compromise"
- ruling: Operator forks are answered through one Eureka fork desk, a web UI that reads and writes the mind through Huginn, rather than per-area artifacts. A web UI is accepted as a compromise because Thing 2.0, the intended interface substrate, is still under construction. Each fork is presented by the Persona whose domain it belongs to (
fork-desk-presenter-follows-work).
eureka-body:ruling:first-autonomous-minds (same admission).
- operator_quote: "Kiko is the StreamPixels persona, one of the few that made the short list to be in the first batch of autonomous Eureka minds. Libby and Nibu made the list, too, and the two fork desks are an improvised representation of the stewardship they're planned to have."
- ruling: Kiko is the StreamPixels Persona. Kiko, Libby and Nibu made the short list for the first batch of autonomous Eureka minds, each with its own Huginn instance under persona-per-mind. The two existing desks are an improvised representation of the stewardship those minds are planned to hold.
eureka-body:ruling:first-autonomous-minds-shortlist (admitted 2026-10-20T13:31:00Z, ordinal 3110, session sp-reentry-2026-10-20; supersedes first-autonomous-minds per the coordinator's message).
- operator_quote: "Kiko is the StreamPixels persona, one of the few that made the short list to be in the first batch of autonomous Eureka minds. Libby and Nibu made the list, too, and the two fork desks are an improvised representation of the stewardship they're planned to have. ... Find the rest of the short list, we generated avatars for them, this is not a new thing"
- ruling: The first batch is the swarm shortlist that already has Flux avatars (
site-masthead:follow_up:cast-art-flux-portraits; gamecult-site branchself/cast-portraits): Libby, Heimdall, Kiko, Aqua, Weksa, Nibu, Eureka and Void, each its own Huginn instance under persona-per-mind. Kiko is the StreamPixels Persona. The two existing desks are an improvised representation of the stewardship those minds are planned to hold. - The superseded ruling's three-name list (Kiko, Libby, Nibu) is a subset of the eight.
site-masthead:ruling:cast-expression-library (admitted 2026-10-13T23:47:52Z, ordinal 2104, ruled_on 2026-10-13). operator_quote: "the stickers I mentioned for the artifact are the avatars we generated with flux, I'd like to have a library of expressions for each short listed swarm character so they can use them in communications". Ruling: the stickers for the decision-page artifact are the Flux avatars of the swarm shortlist, not gamecult-site sprites; each shortlisted character gets a library of expressions for use in communications; generation path per ~/.claude/doctrine/images.md.
Adjacent rulings (viewed 2026-10-20):
eureka-body:ruling:persona-per-mind(ruled 2026-10-09): a Persona that pushes its own domain gets its own Huginn instance, with its own dial share and waker turns; minds cooperate byForeignRefandHandOff. Operator quote: "Second mind makes sense, it's the shape we were planning for already." First case named: Weksa (follow-upeureka-body:follow_up:weksa-mind). Kiko, Libby and Nibu instances: no instance or follow-up for them was found in the queries run (semantic query "persona-per-mind each Persona own Huginn instance stewardship autonomous", top 10 returned only the Weksa follow-up and Persona-state cuts).eureka-substrate:ruling:mind-rules-which-forks(ruled 2026-10-01, quote "On the others I take your recommendations."): the Mind's Self rules only forks whose consequences stay inside Huginn, the leaf, Eureka and its runbooks; consent, doctrine, spending, publishing, operator projects and live-mind upgrades stay the operator's, raised as questions.persona-poses:ruling:reports-and-artifacts-consume(2026-10-14): generated reports and operator-interaction artifacts consume the pose library as well as chat.persona-poses:ruling:pose-home-ruled(2026-10-14, choiceasset-catalogue): each Persona's poses live in a typed asset catalogue that Persona state references by id.persona-poses:target:r2invariants: canon-is-source, one-vocabulary, no-edit-chains, provenance-beside-image, one-cutout-pipeline, persona-plus-label, one-catalogue, stable-hosting, report-and-chat-sizes.
2. Huginn's surface for a web UI
2.1 How a client reaches the mind
- Transport: CultNet RUDP over UDP only.
crates/huginn-daemon/src/serve.rs:190-197binds oneUdpSocketand aCultNetRudpServerHub; no HTTP listener, no WebSocket, no TLS in the daemon (serve.rs:120: "this build carries no TLS", about the Qdrant/Ollama URLs). Grep ofserve.rs,daemon.rs,main.rsfor http/tcp finds only the outbound Qdrant/Ollama URLs. - Live deployment:
docs/eureka-body-map.md:76-81(F4):huginn.serviceon Yggdrasil,--instance eureka --bind 10.77.0.1:17872; UFW admits 17872/udp onwg-gamecultfrom 10.77.0.2 only (runbookhuginn-yggdrasil.md:38,124).mcp__eureka-state__whoamion 2026-10-20: endpointrudp://10.77.0.1:17872,reachable: true, 8951 documents, 3109 receipts, indexCurrent, epochepiphany.pipeline.epoch.v2. - Client:
crates/eureka-state/src/lib.rs:1-22:HuginnClient::callsends oneHuginnMindRequestin the CultNet operation envelope over RUDP, one session per call, fetches aDeferredbody on the same session; holds no state. MCP config:C:\Users\Meta\.claude.json:1427setsHUGINN_ENDPOINT=rudp://10.77.0.1:17872. CLI:huginnbinary (crates/eureka-state/src/main.rs): whoami, view, query (raw and named recipes), admit from a file with read-back, schema. - Operations (
crates/huginn-mind/src/wire.rs:63-100):Whoami,Admit(PipelineAdmissionBatch),View{instance,id},Query{instance,selection,semantic}, plus Persona get/put (HuginnMindResponse::Persona, wire.rs:129). - Limits that shape a client (
serve.rs:30-53): a session idle 30 s is removed server-side; one send carries at most 1,228,800 encoded bytes, larger answers up toMAX_DEFERRED_BODY_BYTESgo as aDeferredmanifest fetched throughcultmesh.content_chunk_request.v1; two large reads pipelined on one session are not both answered; client request limitMAX_REQUEST_BYTES = 65,507 - 36 - 6(eureka-state/src/lib.rs:36). - No peer authentication:
docs/eureka-body-map.md:81: "The daemon has no peer authentication (serve.rs: one session per peer,max_peers = 256); any reachable peer admits as any faculty." Admission provenance (agent, faculty, session, tool) is declared by the writer (theprovenanceobject on everyviewresult above is client-supplied;huginn-mind/src/admission.rs:227shows one provenance authority check on persona state only). - Browser-side CultLib pieces that exist:
F:\Projects\CultLib\packages\cultmesh-browser(README: one WebSocket session to a Verse/authority runtime resolved through configured Odin WebSocket endpoints; leases provider-owned documents; "does not expose direct document writes"; invokes provider-owned operations) andpackages\cultnet-ts(README line 8: not an HTTP wrapper; RUDP socket transport for non-browser runtimes). Whether Odin or any other component bridges a browser WebSocket to the Huginn RUDP port: not found in the files read. Huginn publishes no Eve/Thing surface and no CultMesh provider document that was found (README and AGENTS.md describe only the RUDP operation envelope and the schema catalog). - The TS CultMesh content plane (HTTPS provider and verifying reader) is released per the StreamPixels memory index (
cultnet-ts-v0.3.0,cultmesh-ts-v0.2.0,cultmesh-browser-v0.4.0, CultLib mainb9497d35); not read in this pass beyond the memory index line.
2.2 The question and ruling schemas and admission rules
Leaf definitions, F:\Projects\Huginn\crates\eureka-pipeline\src\lib.rs, Huginn 0b3cac3:
PipelineQuestion(lib.rs:634-636):campaign: Slug,label: Label([A-Za-z0-9_-]{1,64}),title: Title,question: Para(<= 4000 bytes),options: Vec<QuestionOption>(max 8),recommended: Label,depends: Vec<Line>(max 8, Line <= 1000 bytes),raised_in: Option<PipelineRef>,asked_on: Date.QuestionOption { label: Label, text: Line }(lib.rs:585). There is no field for a presenter, Persona,lean,flagor display order; the campaign slug is the only domain key on the document.eureka-statequery headers returnoptionsas labels only;viewreturns the full document.PipelineRuling(lib.rs:637-639):campaign,label,title,answers: Option<Short>(question id),choice: Option<Label>,ruling: Para(<= 4000 bytes),operator_quote: Option<Para>,ruled_on: Date,precedents: Vec<ForeignRef>(max 8),authority: RulingAuthority { Operator, Standing, Defaulted, Mind }(lib.rs:567).- Admission rules,
crates/huginn-mind/src/admission.rs:- Question: needs >= 2 options and
recommendedequal to one option label, elseInvalidOptions(admission.rs:462-465); option labels unique. - Ruling:
operator_quotepresent with an authority other thanOperatoris refusedQuoteWithoutOperator(admission.rs:468-470). Ifanswersis present, the question must exist (MissingReference), be in force or resolved only by this ruling (AlreadyResolved), andchoicemust equal one option label, elseInvalidChoice(admission.rs:471-485; the missing-choice case compares""to the labels, sochoice: Nonewithanswersset is refused too). Test pins at admission.rs:1899-1905 (choice "C" refused, "A" admitted). - A ruling with
answers: Noneis admitted with no check of the above and derives no resolution, so it does not close any question (derive, admission.rs:385-405: onlyRulingwithanswersderives aResolution::Answered; the resolution copies the ruling text as rationale and itsruled_on). - Where an answer falls outside the options: the leaf has no free-form choice path. A free-text answer can ride in
rulingtext andoperator_quoteof a ruling, either withanswers(thenchoicemust still be an option label) or withoutanswers(then nothing resolves the question; a withdrawal or supersession resolution is separate). The artifact desks carry free text in thenotefield ofanswers/<docId>, which Self copies into the ruling by hand. - Resolutions of a ruling are by withdrawal only (admission.rs:682-684); memory note
observation-is-not-a-ruling.mdrecords "rulings cannot be withdrawn" and are superseded by a new Operator ruling quoting her correction. - Replay: an exact replay answers
AlreadyAdmittedwith the first receipt (admission.rs header comment A9).
- Question: needs >= 2 options and
- Query facts for an "open questions" read: the selection supports
schemas,fieldspredicates,in_forcealias (query.rs:520-523 "in_forceis the caller's to ask for and the mind's to derive"),cites/cited, cursor paging (limit clamped 1..200), and an optionalsemanticrank (not cursor-paged; refusedUnavailablewhen the index is failing). AQuestionheader carriesstatusInForceorResolved{outcome, resolution}; observed outcomes:Answered{by},Withdrawn{reason},Superseded{by},Recorded{reason},Deferred{to},Fixed{by,commit}. - Persona state:
huginn-mind/src/persona.rsstores onegamecult.persona_state.v0per mind, schema-validated, replaced whole under CAS with a receipt (cuteureka-substrate:cut_spec:cut-huginn-persona-state.r3, InForce 2026-10-09).HuginnClienthas persona methods per the cut title.
2.3 Substrate gap: eureka-substrate:follow_up:operator-authority-needs-operator-credential
Viewed 2026-10-20 (admitted 2026-10-01T19:17:49Z, ordinal 126, session self-2026-10-01b, status InForce, repo GameCult/Huginn, owner "huginn-mind admission, with cut-mind-authority", source ruling eureka-substrate:ruling:operator-mind-mission).
- item: "With the Mind interpreting its own mission, the record must tell its rulings from the operator's. Today any agent can admit authority: Operator with an operator_quote (see gap-faculty-attribution). Admission must accept authority: Operator only under a credential the operator holds and the Mind's Self does not. Should block the wake cut."
- why_it_can_wait: "No autonomous Self runs yet; must land before cut-mind-self-wake."
- Design for the credential: none found. The follow-up text names no mechanism;
docs/eureka-body-map.md:404-406says the gap "must land before autonomous Self runs" and that "No second guard is added here"; body-map row forrun(line 270) saysoperated_by"is declared by the writer (follow-up ...)". Grep of Huginndocs/*.mdandREADME.mdfor "credential" finds only the Self-run OAuth token row (eureka-body-map.md:281,CLAUDE_CODE_OAUTH_TOKEN, open questionself-run-token-reach) andeureka-self-cut.md:130-146(headlessclaude setup-token; root-onlycredentials/). No admission code path checks a credential: the only authority tests inadmission.rsareQuoteWithoutOperator(quote needs authority Operator) and persona provenance at :227. - Existing operator-held controls elsewhere in the body (not credentials for admission): the brake and burn-rate dial are a root-owned store with
brake holdas root (crates/mind-body/src/lib.rs:1-8, rulingeureka-body:ruling:brake-dial-root-store-now); unit start grant by polkit tomind-<instance>users only (eureka-body-map.md:304).
2.4 Heimdall and Bifrost (authentication of the operator today)
- Rulings:
eureka-body:ruling:bifrost-provides-identity(ruled 2026-10-11, admitted 2026-10-10T22:16:45Z), quote: "keep the ruling, check Heimdall OIDC. Heimdall is our auth guy, but he doesn't issue the identity himself. Bifrost is the one with identities to provide". Ruling text: Bifrost is the identity provider; Heimdall is the authentication organ and does not issue identities. - Follow-ups (viewed 2026-10-20):
eureka-body:follow_up:identity-minting-moves-to-bifrost("Heimdall mints the account id today"; chat not deployed, "nothing live depends on the move until the Matrix rollout");eureka-body:follow_up:bifrost-heimdall-callback-unsigned(Bifrost accepted unsigned callback JSON); cuteureka-body:cut_spec:cut-heimdall-callback-signed.r2InForce 2026-10-11 (completion-code redeem by the browser that started and authenticated). Whether r2 landed: not checked in this pass. - Heimdall,
F:\Projects\Heimdall(5952cce): TypeScript/Fastify; Ed25519 JWTs plus/.well-known/jwks.json(README:22); provider logins Discord, Patreon, Twitch, YouTube/Google, Spotify (pergamecult-ops/docs/research/matrix-oidc-surface.md, section 1, 2026-10-11); app profiles keyed by app slug insrc/app-profiles.ts(built-ins at :58-156:repixelizer,streampixels,bifrost,ghostlight, plus profilesdocs/app-profiles/{bifrost,ghostlight,repixelizer,spotiverse,streampixels}.md); no profile for Huginn, Eureka or a fork desk (grep for "huginn|eureka" insrc,docs,README.mdfinds onlydocs/architecture.mdand vendored CultLib text). Capability rule example with an operator grant:admin_access = grant.operator || grant.admin_access(docs/architecture.md:484). Host-app flow: backend handoff or one-time completion code redeemed atPOST /v1/apps/:appSlug/auth-completions/redeem(architecture.md:515-560; routes in the Matrix OIDC note). Access JWT claims:iss, aud=app slug, sub=accountId, sid, jti, iat, nbf, exp, typ, account_id, access_revision, app, facts, capabilities, identities, display_name(src/claims.ts:95-145per the Matrix OIDC note). The only service verified to check these tokens at 2026-10-11: Ghostlight (ghostlight-dungeon/src/heimdall.rs:507-538). - Heimdall does not serve OIDC provider endpoints (no
/authorize,/token,/userinfo,openid-configuration; Matrix OIDC note section 1 and 5). Bifrost holds no signing key and no provider surface (same note, section 2). Heimdall's own deployment: "never an Idunn-admitted generation ... live is a hand-copied release under hand-written heimdall.service" (follow-upjoystick:follow_up:heimdall-idunn-onboarding, 2026-10-19). - An existing browser-session path today: Bifrost cookie sessions (GitHub OAuth
/auth/sign-in, Heimdall sign-in/auth/heimdall/{provider},ActiveMembercookie policy; Matrix OIDC note section 2) and Heimdall access/refresh JWTs per app. How either would identify "the operator" to a Huginn-facing service: no mapping found; Heimdall has anoperatorgrant concept (architecture.md:235sourceenum includesoperator; :484) in the app-profile rule language. - Network posture: Huginn's port is reachable only over
wg-gamecultfrom 10.77.0.2 (body map F4); no public HTTPS route to Huginn was found.
2.5 Persona State Standard and the three character sheets
F:\Projects\gamecult-ops\docs\persona-state-standard.md(last commit757ba9c; 64 lines): schemagamecult.persona_state.v0(published in Huginnschemas/cultnet/); Persona state is "the Mind they keep"; Huginn holds canonical Persona state per instance with a mind (cuteureka-substrate:cut_spec:cut-doctrine-persona-in-huginn.r3), while the file text (not updated for r3) still says Huginn has no reader and VoidBot remains the operational owner of the portable read/projection/migration path. Neither Huginn nor VoidBot owns presentation: "Eve, overlays, native clients, browsers, and future rooms lower emitted DSL inside their own runtime."- Pose library: campaign
persona-poses:campaign:self(repos gamecult-site, gamecult-ops, Huginn, Bifrost); poses in a typed asset catalogue referenced by id from Persona state (persona-poses:ruling:pose-home-ruled). Existing artifact pose sets: Libby and Nibu, nine moods each (idle, neutral, thinking, happy, surprised, note, determined, triumph, concerned) as.webp; no Kiko set in either artifact. - Canon pixel sheets in
F:\Projects\gamecult-site\GameCult\static\interactive\cotsc-praxis\character-sheets\(3x2 sheets of six poses on a dark ground):aqua-sheet.png,heimdall-sheet.png,kiko-sheet.png,libby-sheet.png,nibu-sheet.png,void-sheet.png,weksa-sheet.pngexist;eureka-sheet.pngdoes not (Eureka's canon source is the Eureka skill'sdocs/assets/eureka-mascot-clean.png; Aqua's alsoAquaSynth/icon.png; percast-portraits/README.md, Canon section). The folder also holdsdruzkai,epiphany,huginnsheets.cotsc-praxis.visual-manifest.jsonmapsavatarandcharacter_sheetper name (entries seen by text match: Void, Aqua, Nibu, Weksa, Epiphany, Kiko, Heimdall, Libby, Druzkai, Huginn; no Eureka entry seen). Only the Kiko, Libby and Nibu sheets were viewed in this pass; the other descriptions below are the portrait branch README's reading of the sheets. - Flux bust source: gamecult-site branch
self/cast-portraits(HEADa2a769a, 2026-10-10, same asorigin/self/cast-portraits), worktreeF:\Projects\gamecult-site-wt-portraits;cast-portraits/README.mdcovers rounds 1-4. Originals (2k, outside git) inF:\Projects\cast-art-originals\(r1,r2,r3,r4,contacts,poses-r1,vector). Final set per README Round 4 andcontacts\contact-final.png(viewed 2026-10-20): libby-r2a, heimdall-r2a, kiko-r2a, aqua-r4a, weksa-r2a, nibu-r3a, eureka-r2a, void-r3a. Per render in the branch:.webp(lossless, 1024 px),-cutout.png(transparent, keyed from a flat green ground bymatte_r2.py/matte_r4.py),.txt(hypothesis, record, exact prompt). Style: FLUX 3 Image, 4:5, chibi bust, three-quarter turn right; from round 2 a shared "two heads tall" style block, one line weight, flat cel shading, no background. Operator verdict on round 1 (rulingsite-masthead:ruling:cast-portrait-canon-r1, not viewed, quoted in the README): "Hood up, blue-grey eyes, push Libby further from Nibu, Weksa is a girl (if tomboyish, she's kind of an indiana jones type after all). No backgrounds. See if you can get a consistent batch now." The Operator verdict cells for rounds 2-4 are blank in the README tables. Expression cells:cast-art-originals\poses-r1\<name>\<name>-r1a-cells\holds 12 cells (01-neutral,02-happy,03-amused,04-thinking,05-concerned,06-annoyed,07-surprised,08-determined, then four character-specific cells, e.g. Libby09-stamp 10-research 11-shush 12-schema, Kiko09-tinker 10-confetti 11-sprint 12-debug) for aqua, eureka, heimdall, kiko, libby, nibu (r1a and r1b);weksahas onlyweksa-r1a.pngandvoidonlyvoid-r1b.pnglisted at folder level. Whether those cells are final, catalogued or published: not established (cast-expression-libraryis a direction; the catalogue is campaignpersona-poses,pose-home-ruled). - The eight Personas (pixel sheet = canon; Flux bust = final-set render in
contact-final.png):
| Persona | Pixel sheet (canon) | Flux bust (final set) | Domain facts found |
|---|---|---|---|
| Libby | lavender wavy hair, bone clip, diamond bow, round glasses, black scholar robe with violet trim; poses (viewed): reading a glowing book, stamping a document, wand at a node diagram, wand with runic debris, large keyhole book, bookshelf with document panels | libby-r2a: deep violet-lavender hair in one fat wavy braid over the shoulder, bone clip, diamond bow, round glasses, gold earrings, black-and-gold robe, book hugged to chest, open happy smile; deliberately set apart from Nibu | CultLib (default persona of the CultLib desk; ruling fork-desk-presenter-follows-work) |
| Heimdall | dark brown skin, messy dark curly hair with gold highlights, glowing gold eyes, stern frown, black coat with royal-blue lapels and cape, gold filigree, large gold key; gates, blue circuitry, red denial cards | heimdall-r2a: chibi, curly hair with gold highlights, black-and-blue coat, gold filigree, large gold key | Heimdall is the authentication organ (bifrost-provides-identity; repo F:\Projects\Heimdall) |
| Kiko | white fox girl: kitsune mask on head, bells, tassels, cyan eyes, fang grin, pink-tipped tails, neon magenta and cyan stream UI; poses (viewed): leaning out of a monitor waving, sprinting with a pixel trail, kneeling at neon panels with a pink cat, arms open between a cat avatar and a person avatar inside a hex shield, confetti, at a laptop with linked tiles | kiko-r2a: mask, bells, tassels, fang grin, wave, magenta-and-teal kimono, pink-tipped tail | StreamPixels (shortlist ruling) |
| Aqua | round scaled goldfish, golden-yellow face, orange body, crest fin, big blue eyes, black over-ear headphones with cyan rings; bubbles, music notes, synth, blue holographic panel | aqua-r4a: whole round goldfish, scales, wide open smile with pink tongue, forked tail, cyan-ringed headphones; shown whole, not cut at mid-chest like the busts | name matches repo GameCult/AquaSynth (in campaign thing-providers); no file read assigns a domain to Aqua's mind |
| Weksa | warm brown skin, half-up topknot with turquoise and amber beads and feathers, large round gold glasses, cream robe with teal trim, brown vest, bead necklaces, leather backpack with scrolls and a carved idol; glyph cards, magnifier, maps, field notebook | weksa-r2a: young woman (operator: "Weksa is a girl", tomboyish, "indiana jones type"), topknot, gold glasses, teal trim, scroll backpack, chest strap, glyph card | language work "that never wins prioritisation" (persona-per-mind ruling text; follow-up eureka-body:follow_up:weksa-mind, the first named second instance) |
| Nibu | very long pale lavender hair, pink connector-shaped clip, pink bow, half-lidded violet eyes, folded arms, lilac blouse, circuit-embroidered sleeves, cyan shoulder ring, long dark purple coat; glitch dissolve, blue worldbuilding panels; poses (viewed): idle, arms crossed, console, glitch, holo map, cyan ring | nibu-r3a (re-render under batch A's block; the connector clip appeared in r2b) | Aetheria and Ghostlight (Nibu's desk; fork-desk-presenter-follows-work) |
| Eureka | young woman in a neon-noir dark trenchcoat piped in glowing orange, tactical straps, fingerless gloves, orange probe and lantern; mascot docs/assets/eureka-mascot-clean.png; no pixel sheet |
eureka-r2a: hood up (round-1 verdict), orange-piped hood, black hair with one orange streak, blue-grey eyes, chest rig, probe | the Eureka mind itself (instance eureka) |
| Void | small figure in a pointed indigo-violet hood, pure-black face with two tall white oval eyes, thick frayed orange scarf, dark gloves; spiral portal door, glowing violet document | void-r3a: pointed hood, black face, white oval eyes, frayed orange scarf, gloves | gamecult-site/docs/gamecult_void_dossier.md:1-8: a dossier "Voice: Void, speaking from inside the work" about GameCult, Eve, Bifrost; no other domain for Void found |
- Domain routing facts: the
questiondocument carriescampaignand no presenter field (section 2.2); no campaign-to-Persona mapping document was found in the mind. Campaign groups seen: StreamPixels (web-customize,rps,motion-pipeline,joystickshared with Heimdall); Aetheria and Ghostlight (aetheria-release,aetheria-ew,aetheria-fauna,aetheria-gravity,asura,brush-tree,ghostlight-verse); CultLib (cultlib-gaps,variants,cultmath-tapes,cultmesh-ts-content,brokkr-msgpack); Idunn/Bifrost/Heimdall-owned (idunn-watchdog,idunn-reincarnation,idunn-deploy-provenance,concept-mill-votes); Eureka's own (eureka-substrate,eureka-body,persona-poses,site-masthead); Thing (thing,thing2,thing-family,thing-providers,thing-verse). Only instanceeurekaexists (whoami);weksa-mindis an open follow-up; no instance or follow-up for the other six was found. - Pose facts: both desk artifacts ship nine moods for Libby and Nibu only (idle, neutral, thinking, happy, surprised, note, determined, triumph, concerned) as
.webp; no desk pose set exists for Heimdall, Kiko, Aqua, Weksa, Eureka or Void.
2.6 Thing 2.0 status
- Campaigns:
thing2:campaign:self("Thing 2.0: more Things, fewer things", repos Eve and gamecult-ops, admitted 2026-10-10T17:39:50Z); targetthing2:target:r1invariants: one-solver, closed-commands, compose-not-kind, core-owns-text, rasterizer-backend-private, live-state-core, geometry-parity, narrow-consumer-contract, born-thing-ids, consumer-port-carries-rename. Family campaignsthing-family(renderers: ThingUnity, ThingFlutter, ThingElectron, ThingTui, ThingPlugins, ThingConformance, CultLib, Ymir),thing-providers,thing-verse(Odin, Ghostlight, Heimdall, Muninn, Mimir, Gjallar, Hermodr, Bifrost);thing:campaign:self(rename of Eve). - Rulings (all Operator, 2026-10-10):
thing:ruling:thing2-one-solver-taffy(direction: closed primitive set, one Taffy layout solver, one closed render-command list, thin backends, live typed CultMesh state binding in core; evidence fileF:/Projects/thing2-foundation-prior-art.md);thing:ruling:thing2-thing-owns-text(core owns text shaping, editing/IME, focus, accessibility tree);thing2:ruling:code-home(Thing 2.0 lives in the Eve repo renamed Thing);thing2:ruling:port-cutover(consumers cut over one at a time);thing:ruling:wire-rename-freeze-fold(wire rename frozen, folded into Thing 2.0). - Cut specs: the rename cuts (
kernel-schemas-contracts,kernel-lowering-scripts,voidbot-wire,thingtui-wire,thingelectron-wire,thingflutter-wire,thingplugins-wire,thingconformance-wire,cultlib-wire,aquasynth-wire,repixelizer-wire,kernel-prose) are ResolvedWithdrawn("Wire rename frozen and folded into Thing 2.0");thing:cut_spec:cut-site-prose.r2InForce ("Thing 2.0 described as in construction");thing:cut_spec:cut-deck-site-page.r1InForce. Follow-upsthing2:follow_up:tour-evecanvas-card,thing2:follow_up:site-thing1-surface. - No Thing 2.0 implementation cut spec, cut report or released backend was found in the query results (semantic query on the Thing 2.0 terms, top 20 across cut_spec/target/follow_up). Operator, 2026-10-20: "Thing 2.0 is still under construction" (
fork-desk-web-ui-on-huginn). - Doctrine in
F:\Projects\CLAUDE.md(GameCult defaults): operator interfaces are Eve/CultUI composition graphs published through CultMesh and lowered by browser/native/TUI renderers; "Do not invent parallel HTTP/status-card summaries unless they are explicitly marked as temporary probes feeding a proper CultMesh surface." The Thing 2.0 surfaces a desk would overlap: composition graph publication, live typed state binding, command-result validation (target invariantslive-state-core,compose-not-kind), and the browser lowering (Thing 1 web lowering existed in the Eve repo per the withdrawnkernel-lowering-scriptsspec;thing:cut_spec:cut-deck-site-page.r1puts a Thing deck on gamecult.org).
3. Prior art: a human rules on decisions an agent raised
All web pages accessed 2026-10-20.
3.1 Decision records
- adr-tools (https://github.com/npryce/adr-tools): numbered Markdown ADRs in
doc/adrby default;adr new -s 9 <title>creates an ADR that supersedes ADR 9 and updates ADR 9's status; statuses and template fields are not listed on that page. - Log4brains (https://github.com/thomvaill/log4brains): ADRs as Markdown in the git repo, published as a static site (
log4brains build, locallog4brains previewwith hot reload); statuses given as proposed, accepted, deprecated, superseded; an ADR is otherwise immutable, only its status changes; metadata guessed from raw text and git logs (CI needs full history); default template MADR; planned features include a decision backlog and ADR editing from the UI. - MADR (https://adr.github.io/madr/): sections Context and Problem Statement, Decision Drivers, Considered Options, Decision Outcome (chosen option and justification), Consequences, Confirmation (how compliance is verified), Pros and Cons of the Options, More Information; optional front matter
status,date,decision-makers,consulted,informed; statuses proposed, rejected, accepted, deprecated, "superseded by" another ADR. - In-house equivalent: mind
question(context, options, recommended, depends, raised_in) ->ruling(authority, quote, precedents) -> derivedResolution(Answered,Superseded,Withdrawn); records are typed documents with receipts, not files (HuginnREADME.mdAuthority section).
3.2 Review and approval queues
- GitHub pull request reviews (https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews): three review states (Comment, Approve, Request changes); administrators can require approvals before merge via protected branches; CODEOWNERS auto-requests review from owners of changed code. The fetched page does not cover stale-review dismissal or the review-to-commit tie.
- Gerrit (https://gerrit-review.googlesource.com/Documentation/config-labels.html): label votes (Code-Review -2..+2, Verified -1..+1); -2 blocks submit, +2 enables it; submit requirements define submittability; votes are tied to a patch set, and on a new patch set a vote is copied forward only if it matches the label's
copyCondition(for examplechangekind:NO_CODE_CHANGE,changekind:TRIVIAL_REBASE); non-copied votes become "outdated", the uploader is notified and the voter is added to the attention set. - Linear Triage (https://linear.app/docs/triage): an inbox for issues from integrations or outside the team; actions Accept (to default status, optional comment), Decline (Canceled, optional explanation), Mark as duplicate (merge into an existing issue), Snooze (hidden until a chosen time or new activity); triage responsibility can rotate by on-call schedule (Business and Enterprise plans); the page does not describe automatic decline or snooze.
3.3 Agent harnesses with a human approval step
- LangGraph
interrupt()(https://docs.langchain.com/oss/python/langgraph/interrupts): saves graph state through a checkpointer, returns a JSON-serializable payload to the caller (__interrupt__orstream.interrupts); resume withCommand(resume=...)on the samethread_id; the node restarts from its beginning on resume, so code beforeinterrupt()must be idempotent; interrupts must be called in the same order each time; patterns: approve or reject, review and edit, tool interrupts (approve, edit arguments, cancel), input validation by re-entering the node, parallel interrupts keyed by interrupt id; optional response schema validates resume values (langgraph>=1.2.12). (An older URL, langchain-ai.github.io/langgraph/concepts/human_in_the_loop/, returned only a redirect.) - OpenHands confirmation mode (https://docs.openhands.dev/sdk/guides/security): policies
AlwaysConfirm,NeverConfirm,ConfirmRisky(threshold); pending actions put the conversation inWAITING_FOR_CONFIRMATION; approve byconversation.run(), reject byconversation.reject_pending_actions("reason")with the reason returned to the agent; an LLM security analyzer rates actions LOW/MEDIUM/HIGH/UNKNOWN;conversation.execute_tool()bypasses both analyzer and policy. - OpenAI Agents SDK human-in-the-loop (https://openai.github.io/openai-agents-python/human_in_the_loop/):
needs_approval(bool or async callable per call); a paused run exposesresult.interruptions(ToolApprovalItem: agent, tool, arguments);result.to_state()serializes (to_json/to_string);state.approve(interruption)orstate.reject(interruption, rejection_message=...)per call, sticky withalways_approve/always_reject; resume withRunner.run(agent, state); docs state serialized state is not authenticated, so reviewer identity and authorization must be verified before resuming. - Claude Agent SDK (https://code.claude.com/docs/en/agent-sdk/user-input):
canUseToolfires for tool approval and forAskUserQuestion; callback may stay pending indefinitely, or aPreToolUsehookdeferdecision lets the process exit and resume from the persisted session; responses: allow (optionallyupdatedInput), allow withupdatedPermissions(approve and remember), deny with a message the agent sees;AskUserQuestioninput is 1-4 questions with 2-4 options each (question,header<= 12 chars,options[{label, description, preview?}],multiSelect), the answer is a map from question text to chosen label (arrays or comma-joined for multi-select), free text goes in the answer value, optionalresponsefor a general reply; options may carry an HTML preview (previewFormat: "html"); not available in subagents;PermissionRequesthook can notify Slack, email or push. - Claude Code permission modes (https://code.claude.com/docs/en/permission-modes):
default(prompts for edits, shell, network),acceptEdits,plan(edits blocked until a plan is approved),auto(classifier reviews actions, ask rules still prompt),dontAsk(would-prompt calls are denied),bypassPermissions. - HumanLayer (https://github.com/humanlayer/humanlayer): the repo page states "the code here is pretty much all deprecated" and points to a rebuild at humanlayer.com; topics human-in-the-loop, claude-code; 11.7k stars. The approval API (
require_approval,human_as_tool) was not shown on the fetched page; not established here. - Other Claude-side precedent in this environment: Claude Code
AskUserQuestion(as used by Self in this session family, memoryforks-for-understanding.md: "one AskUserQuestion per fork") is the question channel the desks replaced for open forks.
3.4 Known failure modes (sourced)
- Approval fatigue and rubber-stamping: Anthropic engineering post (https://www.anthropic.com/engineering/claude-code-auto-mode): "approval fatigue, where people stop paying close attention to what they're approving"; users approve 93% of permission prompts.
- Automation bias and explanation limits: Green, "The Flaws of Policies Requiring Human Oversight of Government Algorithms" (Computer Law & Security Review 2022; https://arxiv.org/abs/2109.05067): surveys 41 policies; reports that most research finds people cannot reliably oversee algorithms, that people defer to automated tools and increase attention to the factors an algorithm emphasizes, and that explanations and transparency do not reliably improve oversight. EU AI Act Article 14(4)(b) (https://artificialintelligenceact.eu/article/14/): overseers must remain aware of the possible tendency to over-rely on system output (automation bias), notably where the system provides recommendations.
- Questions without context: Claude Code and SDK question forms bound questions to 1-4 per call and 2-4 options with a short label (
header<= 12 chars); in-house record: the operator asked to understand each decision ("My decisions are the only reason anything gets done", 2026-09-29,forks-for-understanding.md), and a handoff one-liner lost "options and decision context" (operator, 2026-10-03, same note: "I want options and decision context to survive next time."). - Answers losing provenance: the OpenAI SDK documents that serialized approval state is unauthenticated and caller must verify reviewer identity; Huginn's own record has the same shape (no peer authentication, writer-declared provenance,
operator-authority-needs-operator-credential); the artifact desks writeanswerswith no identity beyond the artifact viewer andupdatedAt, and Self re-types them into a ruling; two in-house wording losses: option text clauses read as rulings (option-text-is-not-her-words.md, 2026-10-17), a paraphrase replacing her words (relay-operator-words-verbatim.md, 2026-09-30 and 2026-10-07); a remark admitted as a ruling (observation-is-not-a-ruling.md, 2026-10-13); a verbatim relay that Self did not hear directly (fork-desk-nibu-formatruling text). - Stale questions: Gerrit marks votes outdated when a new patch set is not copy-eligible and adds the voter to the attention set; Linear Triage offers Snooze until time or new activity and Decline with a comment; LangGraph/OpenAI/Claude SDK pause states persist until resumed (the Claude SDK callback "can stay pending indefinitely"). In-house: a question already retired by a ruling was posted to the desk (2026-10-17,
minor-power-geonames, memoryforks-go-on-the-desk.md); an answer on one desk was missed because only the other was read (2026-10-17, same note); "So much work gets left hanging and never comes up until I bring it up" (operator, 2026-10-10,work-left-hanging.md). Huginn has no question expiry or review date;eureka-substrate:follow_up:mind-standing-decay(admitted 2026-10-01) records that Mind rulings never age and names review dates as future work. - Cross-desk fragmentation: two desks with separate stores and separate
answerscollections is the state the rulingfork-desk-web-ui-on-huginnnames ("rather than per-area artifacts").
4. GameCult brand constraints a desk would need
Sources: F:\Projects\gamecult-site\docs\brand-design-language.md (last commit 9bd39bb, 2026-10-02; the note says the code wins over it) and F:\Projects\gamecult-site\site\quartz.config.ts lines 22-62 (configuration.theme, same commit).
- Typefaces (quartz.config.ts:25-39): header and title Montserrat (header weights 100 200 300 400 600; title weights 100 200 300, "thin only", no bold title), body Ubuntu (300 400 500 700 plus italic; running text at 300, emphasis step 500), code IBM Plex Mono. IBM Plex Mono is also a display face: uppercase, letter-spaced 0.06em-0.18em for eyebrows, labels, table headers, metadata (brand note "Typography").
- Palette (quartz.config.ts:41-62; note "Palette"; Quartz
lightis the background anddarkis the text): ground#07111a; panels and borders#16212c; muted#63758a; body#b7c7d9; headings#eef5ff; accent#ff8a2a; links and info#59b7ff; highlightrgba(89,183,255,.14); text highlight#ff8a2a55. - Ground wash:
#07111ais the midpoint; the body layers three radials (orange at 78% 14%, violet#6d60ffat 18% 10%, blue at 52% 0%) overlinear-gradient(180deg, #03070d 0%, #07111a 44%, #09141f 100%)with intensity--gamecult-wash(1 on/, 0.5 elsewhere); a flat#07111a"loses the thing that makes it recognisable". - Single dark theme by decision:
lightModeanddarkModeidentical;color-scheme: darkforced; no light mode; paint every colour explicitly, skipprefers-color-scheme, and set an explicit background. - Surfaces: no cards; grouping by whitespace, type hierarchy and one hairline
--gamecult-ruleasborder-top: 1px solid, named by a mono uppercase tracked label (.gamecult-kicker); an aside is a left rule with no fill; list rows separate by the same top rule; hover turns a title--secondary. - Layout: one centred column,
--gamecult-column72rem, applied once as.pagemax-width; nothing placed beside it on site pages. - Rules for use outside the site (note "Applying this outside the site"): Montserrat 100-200 titles carried large, Ubuntu 300 prose, IBM Plex Mono uppercase tracked for small structural labels, ground
#07111aplus the radial wash on large surfaces, rulesrgba(148,163,184,.22), body#b7c7d9, headings#eef5ff, one accent#ff8a2a,#59b7fffor links and informational state. - No semantic colour set: no defined success, warning or error colour; anything needing status colour is inventing it, and should stay distinct from
#ff8a2a. The existing desk artifact adds--ok: #6fd3a0(index.html of both artifacts,:root),--tintper persona (#c3a4ffLibby,#b79cffNibu) and panels#111c27, none of which are brand config tokens. - Ritual Paper (Georgia serif, cobalt and amber) is a scoped variant for three essays; the note says not to use it for ordinary pages, dashboards or documents.
- The desk artifacts' own header comment says "Single dark GameCult look by brand decision"; their mood-pose images are
.webpassets hosted inside the artifact (stable-hostingis a persona-poses target invariant for the library, so the artifact-hosted copies are not its catalogue).