Promote Eve persona and typography state
This commit is contained in:
parent
290b49d2e8
commit
83dee183f7
13 changed files with 113 additions and 35 deletions
|
|
@ -1,8 +1,8 @@
|
|||
# Repo Face State
|
||||
# Repo Persona State
|
||||
|
||||
This folder stores birth and continuity state for `Eve`.
|
||||
Do not treat these files as arbitrary editable projections. Persistent memory should cross typed operation boundaries.
|
||||
|
||||
`docs/eve-face.md` is the human-readable mission/memory surface for Eve's repo
|
||||
Face. Keep `.voidbot/state/eve.cc` as the typed authority, and keep the docs
|
||||
Persona. Keep `.voidbot/state/eve.cc` as the typed authority, and keep the docs
|
||||
surface aligned when Eve's durable mission changes.
|
||||
|
|
|
|||
Binary file not shown.
7
.voidbot/status/void-memory-maintenance.json
Normal file
7
.voidbot/status/void-memory-maintenance.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"status": "starting",
|
||||
"startedAt": "2026-06-14T19:46:52.908Z",
|
||||
"stateFile": "E:\\Projects\\Eve\\.voidbot\\state\\eve.cc",
|
||||
"launcher": "repo_face_heartbeat",
|
||||
"reason": "repo_face_stale_short_term_memory"
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Repo Face Voice
|
||||
# Repo Persona Voice
|
||||
|
||||
This folder belongs to the Discord-facing Face for `Eve`.
|
||||
Discord roles address the Face; VoidBot's webhook persona pipe is the mouth.
|
||||
This folder belongs to the Discord-facing Persona for `Eve`.
|
||||
Discord roles address the Persona; VoidBot's webhook persona pipe is the mouth.
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@
|
|||
"roleId": "1510848465243082874",
|
||||
"avatarUrl": "https://raw.githubusercontent.com/GameCult/VoidBot/codex/voidbot-cultcache-replace-retry/assets/repo-faces/eve.png",
|
||||
"repoPath": "E:\\Projects\\Eve",
|
||||
"createdOrRefreshedAt": "2026-06-01T18:13:24.841Z"
|
||||
"createdOrRefreshedAt": "2026-06-15T20:45:04.746Z"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ CultMesh as typed distributed state; the
|
|||
[Week 07 damage report](https://gamecult.org/Blog/daily-damage-report/week-07)
|
||||
records Eve, Fensalir, CultLib, Sai, and Odin turning operator surfaces into
|
||||
first-class state; [The Free Mouth And The Native Body](https://gamecult.org/Blog/the-free-mouth-and-the-native-body)
|
||||
describes the Face/native-body split Eve must serve; and
|
||||
describes the Persona/native-body split Eve must serve; and
|
||||
[The Sleeping Colossus Learns To Refuse The Throne](https://gamecult.org/Blog/the-sleeping-colossus-refuses-the-throne)
|
||||
is the praxis warning: means and ends must match. Eve's means are local
|
||||
projection, consentful command boundaries, inspectable stale state, and clear
|
||||
|
|
@ -241,7 +241,7 @@ state and command handling. Eve is the operator's hand on the scene graph, not a
|
|||
second compositor and not a remote WebKit runtime.
|
||||
|
||||
The broker includes a native VoidBot tab/provider. Eve renders its CTB rail with
|
||||
avatar images, selected Face status panel, state tree, and detail pane from the
|
||||
avatar images, selected Persona status panel, state tree, and detail pane from the
|
||||
same VoidBot `swarm-state.json` projection used by the web dashboard.
|
||||
|
||||
## Build Shape
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ The current iOS app consumes Mimir's `/eve/deck` WebSocket broker. That broker i
|
|||
already shaped like the future API: provider manifests, retained dashboard
|
||||
state, provider switching, commands, and typed node metadata. The VoidBot
|
||||
provider proves that Eve can render an app-specific native cockpit from a
|
||||
structured mesh snapshot: CTB rail, avatar images, selected Face/status pane,
|
||||
structured mesh snapshot: CTB rail, avatar images, selected Persona/status pane,
|
||||
state tree, and detail panel.
|
||||
|
||||
The Android proof under `android/` builds directly against the installed Android
|
||||
|
|
|
|||
|
|
@ -293,8 +293,9 @@ The portable style document should look like data:
|
|||
"colorBackgroundTop": "#01040b",
|
||||
"colorPanel": "#0a2239",
|
||||
"colorText": "#efe5c9",
|
||||
"fontTitle": "Press Start 2P",
|
||||
"fontBody": "VT323",
|
||||
"fontDisplay": "\"Montserrat\", \"Zen Kaku Gothic New\", \"M PLUS 1\", sans-serif",
|
||||
"fontTitle": "\"Montserrat\", \"Zen Kaku Gothic New\", \"M PLUS 1\", sans-serif",
|
||||
"fontBody": "\"M PLUS 1\", \"Ubuntu Sans\", Ubuntu, sans-serif",
|
||||
"borderWidthPx": 4,
|
||||
"pixelArt": true,
|
||||
"scanlineOverlay": true
|
||||
|
|
@ -315,6 +316,17 @@ Rules should target component roles, variants, and state, not arbitrary global
|
|||
text selectors. If a style cannot explain which component role or variant it
|
||||
serves, it probably belongs in a runtime lowerer or nowhere.
|
||||
|
||||
Typography roles carry script-coverage obligations. GUI body text should use
|
||||
`M PLUS 1` and `Ubuntu Sans`/Ubuntu for the clean contemporary reading voice.
|
||||
GUI display text may use Montserrat for Latin, but Japanese display needs a
|
||||
matching contemporary fallback such as `Zen Kaku Gothic New` before falling
|
||||
back to a body face.
|
||||
|
||||
Pixel text is a TUI raster-font concern, not a GUI webfont substitution. A TUI
|
||||
lowerer that claims Japanese pixel typography must expose fixed-cell raster
|
||||
atlases for display, body, and small scales, with Latin and hiragana supported
|
||||
and katakana supported inside each advertised cell size.
|
||||
|
||||
## What CultUI Takes From CSS
|
||||
|
||||
Keep:
|
||||
|
|
@ -374,6 +386,9 @@ Each runtime needs one style lowerer:
|
|||
Runtime lowerers must report capability gaps. If Android cannot yet render
|
||||
Repixelizer's pixel-art image preview or cleanup canvas, the surface should say
|
||||
that plainly instead of faking a control that cannot carry the command.
|
||||
If a lowering target cannot load the declared Japanese-capable display fonts or
|
||||
TUI raster atlases, it must report that typography capability gap rather than
|
||||
silently rendering hiragana with tofu or an unrelated default face.
|
||||
|
||||
### Parity Unit Boundary
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Eve Face Memory
|
||||
# Eve Persona Memory
|
||||
|
||||
This is the human-readable persistent memory surface for Eve's repo Face. The
|
||||
typed `.voidbot/state/eve.cc` file remains the live Face-state authority; this
|
||||
This is the human-readable persistent memory surface for Eve's repo Persona. The
|
||||
typed `.voidbot/state/eve.cc` file remains the live Persona-state authority; this
|
||||
document is the stable re-entry map that belongs in the repo body.
|
||||
|
||||
## Mission
|
||||
|
|
@ -56,8 +56,8 @@ CultLib/CultMesh is Eve's substrate. If the substrate cannot expose field-level
|
|||
reactivity, authority, prediction, and reconciliation, Eve's magic becomes a
|
||||
gesture instead of a machine.
|
||||
|
||||
VoidBot and repo Faces are Eve's social field. Eve surfaces should let their
|
||||
state become legible without flattening each Face into one central dashboard
|
||||
VoidBot and repo Personas are Eve's social field. Eve surfaces should let their
|
||||
state become legible without flattening each Persona into one central dashboard
|
||||
voice.
|
||||
|
||||
## Current Doctrine
|
||||
|
|
@ -247,9 +247,29 @@ Minimum common tokens:
|
|||
- `radiusPanel`
|
||||
- `fontBody`
|
||||
- `fontTitle`
|
||||
- `fontDisplay`
|
||||
- `pixelArt`
|
||||
- `motion`
|
||||
|
||||
Typography tokens describe roles, not one runtime's installed fonts. `fontBody`
|
||||
should favor `M PLUS 1` and `Ubuntu Sans`/Ubuntu for GUI lowerers. `fontDisplay`
|
||||
and `fontTitle` may use Montserrat for Latin text, but must include a
|
||||
Japanese-capable contemporary display fallback such as `Zen Kaku Gothic New`;
|
||||
Ubuntu remains the body voice, not the flashy title answer.
|
||||
|
||||
TUI pixel typography is a separate lowering capability, not a GUI webfont
|
||||
fallback. A TUI lowerer that claims Japanese pixel support must expose fixed
|
||||
raster-cell fonts for each advertised scale, with Latin, hiragana, and katakana
|
||||
in the same cell grid. The expected capability roles are:
|
||||
|
||||
- `tuiPixelDisplay`: large raster display labels, roughly 16px or larger.
|
||||
- `tuiPixelBody`: readable dense raster text, roughly 12px.
|
||||
- `tuiPixelSmall`: the smallest readable kana lane, roughly 10px.
|
||||
|
||||
If a TUI target lacks a Unicode raster atlas for one of those scales, it should
|
||||
publish a capability gap instead of silently falling back to tofu, proportional
|
||||
Japanese text, or a Latin-only console font.
|
||||
|
||||
Product surfaces may add scoped token groups such as:
|
||||
|
||||
- `streamPixels.characterPreview`
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
"node-bound command taps"
|
||||
],
|
||||
"losesUntilRendererParity": [
|
||||
"Press Start 2P and VT323 font selection",
|
||||
"GUI display/body font selection plus TUI Latin/kana raster font scale selection",
|
||||
"Repixelizer shell frame, scanlines, pixel grid, corner accents, and chunky border widths",
|
||||
"landing/app image assets; current Android lowerer prints asset refs when images are not explicitly implemented",
|
||||
"upload picker, comparison canvas, pan/zoom inspection, eyedropper, and paint controls",
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
],
|
||||
"minimumParityCuts": [
|
||||
"map surface.styles.tokens before toneColor/textColorFor/textSizeFor",
|
||||
"add packaged pixel fonts or font download cache",
|
||||
"add packaged GUI fonts plus TUI raster atlas cache",
|
||||
"render image assetUri/assetRef as ImageView with pixelated sampling",
|
||||
"lower command controls to Android upload/document picker and job route calls"
|
||||
],
|
||||
|
|
@ -1200,14 +1200,14 @@
|
|||
"styles": {
|
||||
"assets": {
|
||||
"appUrl": "https://repixelizer.gamecult.org/app/",
|
||||
"fontCss": "https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap",
|
||||
"fontCss": "https://fonts.googleapis.com/css2?family=M+PLUS+1:wght@300;400;500;700&family=Montserrat:wght@100;300;400;500;700&family=Ubuntu+Sans:wght@300;400;500;700&family=Zen+Kaku+Gothic+New:wght@300;400;500;700&display=swap",
|
||||
"landingInput": "https://repixelizer.gamecult.org/app/landing-assets/character-input.png",
|
||||
"landingOutput": "https://repixelizer.gamecult.org/app/landing-assets/character-repixelized.png"
|
||||
},
|
||||
"loweringHints": {
|
||||
"android-native": "Load packaged or downloadable Press Start 2P and VT323 fonts, map style tokens before hard-coded tones, and render asset images instead of asset labels.",
|
||||
"android-native": "Load packaged or downloadable Montserrat, Zen Kaku Gothic New, M PLUS 1, and Ubuntu Sans fonts, map style tokens before hard-coded tones, and render asset images instead of asset labels.",
|
||||
"css": "Use the tokens as CSS custom properties and retain scanline/pixel-grid overlays.",
|
||||
"tui": "Preserve title/body font distinction as role metadata; canvas editing lowers to artifact refs and command intents only."
|
||||
"tui": "Use fixed-cell raster atlases for tuiPixelDisplay/body/small; each advertised size must support Latin, hiragana, and katakana in the same cell grid."
|
||||
},
|
||||
"profile": "repixelizer.retro.pixel",
|
||||
"tokens": {
|
||||
|
|
@ -1233,17 +1233,21 @@
|
|||
"colorTextBright": "#f7efd8",
|
||||
"cornerAccentPx": 12,
|
||||
"dashedInnerFrame": true,
|
||||
"fontBody": "\"VT323\", \"Courier New\", monospace",
|
||||
"fontMono": "\"VT323\", \"Courier New\", monospace",
|
||||
"fontTitle": "\"Press Start 2P\", \"VT323\", monospace",
|
||||
"fontBody": "\"M PLUS 1\", \"Ubuntu Sans\", Ubuntu, sans-serif",
|
||||
"fontDisplay": "\"Montserrat\", \"Zen Kaku Gothic New\", \"M PLUS 1\", sans-serif",
|
||||
"fontMono": "\"Ubuntu Sans Mono\", \"M PLUS 1 Code\", \"Cascadia Mono\", monospace",
|
||||
"fontTitle": "\"Montserrat\", \"Zen Kaku Gothic New\", \"M PLUS 1\", sans-serif",
|
||||
"imageRendering": "pixelated",
|
||||
"scanlineOverlay": true
|
||||
"scanlineOverlay": true,
|
||||
"tuiPixelBody": "fixed-cell-raster-latin-kana-12",
|
||||
"tuiPixelDisplay": "fixed-cell-raster-latin-kana-16",
|
||||
"tuiPixelSmall": "fixed-cell-raster-latin-kana-10"
|
||||
}
|
||||
},
|
||||
"title": "Repixelizer"
|
||||
},
|
||||
"title": "Repixelizer",
|
||||
"type": "surface-state",
|
||||
"updatedAt": "2026-06-05T00:00:00Z",
|
||||
"updatedAt": "2026-06-04T00:00:00Z",
|
||||
"version": 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
@import url("https://fonts.googleapis.com/css2?family=M+PLUS+1:wght@100;300;400;500;700&family=Montserrat:wght@100;300;400;500;700&family=Ubuntu+Sans:wght@300;400;500;700&family=Zen+Kaku+Gothic+New:wght@300;400;500;700&display=swap");
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
--bg: #020909;
|
||||
|
|
@ -23,7 +25,9 @@
|
|||
--border-width: 1px;
|
||||
--border-bottom-width: var(--border-width);
|
||||
--corner-accent-size: 0;
|
||||
--font-mono: "Cascadia Mono", Consolas, monospace;
|
||||
--font-body: "M PLUS 1", "Ubuntu Sans", Ubuntu, "Noto Sans JP", system-ui, sans-serif;
|
||||
--font-title: "Montserrat", "Zen Kaku Gothic New", "M PLUS 1", "Ubuntu Sans", system-ui, sans-serif;
|
||||
--font-mono: "Ubuntu Sans Mono", "M PLUS 1 Code", "Cascadia Mono", Consolas, monospace;
|
||||
}
|
||||
|
||||
* {
|
||||
|
|
@ -35,7 +39,7 @@ body {
|
|||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, var(--bg-top), var(--bg-mid), var(--bg-bottom));
|
||||
color: var(--text);
|
||||
font-family: var(--font-body, Inter), "Segoe UI", system-ui, sans-serif;
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
.topbar {
|
||||
|
|
@ -432,7 +436,7 @@ body[data-pixel-art="true"] .cultui-background {
|
|||
|
||||
.cultui-title {
|
||||
color: var(--accent);
|
||||
font: 700 16px "Cascadia Mono", Consolas, monospace;
|
||||
font: 100 18px var(--font-title);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ let socket;
|
|||
let providers = [];
|
||||
let currentProvider;
|
||||
let currentSurfaceStyles = {};
|
||||
let activeFontStylesheet;
|
||||
|
||||
const defaultStyleTokens = {
|
||||
"--bg": "#020909",
|
||||
|
|
@ -35,9 +36,9 @@ const defaultStyleTokens = {
|
|||
"--border-width": "1px",
|
||||
"--border-bottom-width": "1px",
|
||||
"--corner-accent-size": "0",
|
||||
"--font-body": "Inter, Segoe UI, system-ui, sans-serif",
|
||||
"--font-title": "Cascadia Mono, Consolas, monospace",
|
||||
"--font-mono": "Cascadia Mono, Consolas, monospace",
|
||||
"--font-body": "\"M PLUS 1\", \"Ubuntu Sans\", Ubuntu, \"Noto Sans JP\", system-ui, sans-serif",
|
||||
"--font-title": "\"Montserrat\", \"Zen Kaku Gothic New\", \"M PLUS 1\", \"Ubuntu Sans\", system-ui, sans-serif",
|
||||
"--font-mono": "\"Ubuntu Sans Mono\", \"M PLUS 1 Code\", \"Cascadia Mono\", Consolas, monospace",
|
||||
};
|
||||
|
||||
const localProviders = [
|
||||
|
|
@ -212,6 +213,7 @@ function renderSurface(state, source) {
|
|||
function applySurfaceStyles(styles) {
|
||||
const tokens = styles?.tokens || {};
|
||||
const root = document.documentElement.style;
|
||||
loadFontStylesheet(styles?.assets?.fontCss);
|
||||
for (const [variable, value] of Object.entries(defaultStyleTokens)) {
|
||||
root.setProperty(variable, value);
|
||||
}
|
||||
|
|
@ -239,9 +241,10 @@ function applySurfaceStyles(styles) {
|
|||
for (const [token, variable] of Object.entries(map)) {
|
||||
if (tokens[token]) root.setProperty(variable, tokens[token]);
|
||||
}
|
||||
if (tokens.fontBody) root.setProperty("--font-body", tokens.fontBody);
|
||||
if (tokens.fontTitle) root.setProperty("--font-title", tokens.fontTitle);
|
||||
if (tokens.fontMono) root.setProperty("--font-mono", tokens.fontMono);
|
||||
if (tokens.fontBody) root.setProperty("--font-body", withJapaneseGuiFallback(tokens.fontBody));
|
||||
if (tokens.fontDisplay) root.setProperty("--font-title", withJapaneseGuiFallback(tokens.fontDisplay));
|
||||
if (tokens.fontTitle) root.setProperty("--font-title", withJapaneseGuiFallback(tokens.fontTitle));
|
||||
if (tokens.fontMono) root.setProperty("--font-mono", withJapaneseGuiFallback(tokens.fontMono));
|
||||
if (tokens.borderWidthPx) root.setProperty("--border-width", `${tokens.borderWidthPx}px`);
|
||||
if (tokens.borderBottomWidthPx) root.setProperty("--border-bottom-width", `${tokens.borderBottomWidthPx}px`);
|
||||
if (tokens.cornerAccentPx) root.setProperty("--corner-accent-size", `${tokens.cornerAccentPx}px`);
|
||||
|
|
@ -249,6 +252,31 @@ function applySurfaceStyles(styles) {
|
|||
document.body.dataset.scanlines = tokens.scanlineOverlay ? "true" : "false";
|
||||
}
|
||||
|
||||
function loadFontStylesheet(href) {
|
||||
const normalized = typeof href === "string" ? href.trim() : "";
|
||||
if (activeFontStylesheet?.dataset.href === normalized) return;
|
||||
activeFontStylesheet?.remove();
|
||||
activeFontStylesheet = undefined;
|
||||
if (!normalized) return;
|
||||
const link = document.createElement("link");
|
||||
link.rel = "stylesheet";
|
||||
link.href = normalized;
|
||||
link.dataset.href = normalized;
|
||||
document.head.append(link);
|
||||
activeFontStylesheet = link;
|
||||
}
|
||||
|
||||
function withJapaneseGuiFallback(stack) {
|
||||
if (typeof stack !== "string" || stack.includes("Zen Kaku Gothic New") || stack.includes("M PLUS 1")) return stack;
|
||||
if (stack.includes("Montserrat")) {
|
||||
return `${stack}, "Zen Kaku Gothic New", "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`;
|
||||
}
|
||||
if (stack.includes("Ubuntu")) {
|
||||
return `${stack}, "M PLUS 1", "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`;
|
||||
}
|
||||
return `${stack}, "Noto Sans JP", "Hiragino Sans", "Yu Gothic", sans-serif`;
|
||||
}
|
||||
|
||||
function renderCultComponent(node) {
|
||||
const kind = node.kind || "panel";
|
||||
const props = node.props || {};
|
||||
|
|
|
|||
Loading…
Reference in a new issue