Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .trinity/seals/lab_LabJobKind.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"built_by": "t27c-bootstrap@0.5.2+c948f4df7",
"built_by": "t27c-bootstrap@0.5.2+0fba674ef",
"closure": [
{
"spec": "specs/hosting/credit.t27",
Expand Down Expand Up @@ -47,7 +47,7 @@
},
{
"spec": "specs/t27f/petal_menu.t27",
"spec_hash": "sha256:e1ced494087ebcbe9e5fe07803f187f1bafef21d7f22086297e7ace675407760"
"spec_hash": "sha256:9e90e3afe418dc36e5087b01566e97115d6e809e1e42bbec686e572ec19554b1"
},
{
"spec": "specs/trinet/node-work-credit.t27",
Expand All @@ -67,16 +67,16 @@
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:444db4020d3fc934a71d3ca266416323bb69e148c72832fd25f145eaeaac092b",
"gen_hash_c": "sha256:c7e6bdbb24d42e7fb1f6effee13e471f73c2d120d3378d629cf85ecc8edbcdd3",
"gen_hash_rust": "sha256:2b570638d4d94dfd551e8bff976e58d48b2a4de2a9cbadd87ac8646bf5ee3b5b",
"gen_hash_verilog": "sha256:364431e262b73b0f826730718deda22b885ec04015fa3a2e252e71c04e3a0d23",
"gen_hash_zig": "sha256:2ca1666f3c8fe9ec60dfd2edffb44b98521c44dd7ce6555908f92a97b9f88520",
"gen_hash_zig": "sha256:45ee6959f3a7b45542f8c30180224caa1ff0fafab76e4d8bf07ae3074177fd72",
"module": "LabJobKind",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-19T13:59:45Z",
"sealed_at": "2026-10-20T07:25:30Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:ddcb04fd605b9b47e33fc6357167ef8035a6006d9031ad2c398d8c8230107118",
"spec_hash": "sha256:ae6064a2e267dcc06583f8a47efd71bb42e6951262f0aa84e5762f6eb9eab590",
"spec_path": "specs/lab/job_kind.t27",
"tests": {
"failed": 0,
Expand Down
37 changes: 37 additions & 0 deletions .trinity/seals/t27os_T27osHomes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"built_by": "t27c-bootstrap@0.5.2+0fba674ef",
"closure": [
{
"spec": "specs/t27f/petal_menu.t27",
"spec_hash": "sha256:9e90e3afe418dc36e5087b01566e97115d6e809e1e42bbec686e572ec19554b1"
},
{
"spec": "specs/t27os/session_store.t27",
"spec_hash": "sha256:7d05d7dda14587458a77291c3d587e3f08516d8e678f0a4bd06dcaab7f6d1f2f"
}
],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:2d1003dad6a3db9287e48777b36dcfec0eccf4afbcbe7adf290bdc8194a0a11a",
"gen_hash_rust": "sha256:141ff74b276be22f1d8475755c4f39f646a806ab93663f27dc2002701cd004aa",
"gen_hash_verilog": "sha256:07ad7d52d1b53258d6552a7b7089b55f53430f34f593b9e98008f6a7ea81f3ff",
"gen_hash_zig": "sha256:e4ca80e7ba45434ec2575086c4a0d88fc41fae619c6b601f8e263415ba456ce6",
"module": "T27osHomes",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-20T07:25:36Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:b6e84467e629c9b21de72f520f18b48136447f3616d498604b4a0eca60ce74b0",
"spec_path": "specs/t27os/homes.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 26,
"total": 26,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:8512b80da533b79289110fca4a65f3336abd7a059ca4b72ea595d5e33ff8ad10",
"zig": "0.16.0"
}
}
3 changes: 2 additions & 1 deletion specs/lab/job_kind.t27
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,8 @@ test the_reward_card_belongs_to_the_depin_node_petal_of_the_home {
assert PETAL_COUNT == 27;
assert petal_ok(LJK_HOME_PETAL);
assert ljk_world_is(WORLD_NAMES, LJK_HOME_PETAL, "DePIN NODE");
assert ljk_world_is(WORLD_NAMES, 0, "CHAT");
assert ljk_world_is(WORLD_NAMES, 2, "CHAT");
assert ljk_world_is(WORLD_NAMES, 0, "LOGS");
assert ljk_world_is(WORLD_NAMES, 26, "ABOUT");
assert ljk_world_is(WORLD_NAMES, LJK_HOME_PETAL, "DePIN") == false;
assert ljk_world_is(WORLD_NAMES, 27, "ABOUT") == false;
Expand Down
8 changes: 6 additions & 2 deletions specs/t27f/petal_menu.t27
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,12 @@ pub const QY : [108]i64 = [
272637, 248279, 287010, 349402,
];

/// L2. The 27 worlds, in petal order (TriangleLogo.worlds, from sacred_worlds.zig:99-141).
pub const WORLD_NAMES : str = "CHAT,CODE,LOGS,DEBUG,REVIEW,TRANSLATE,VIBEE,VOICE,COMPOSE,FILES,EDITOR,BUILD,TEST,TERMINAL,GIT,DEPLOY,DePIN NODE,SETTINGS,DOCS,REELS,FEED,ROADMAP,BENCHMARKS,RESEARCH,FORMULAS,COMMUNITY,ABOUT";
/// L2. The 27 worlds, in petal order. Owner, 2026-10-20: CHAT is the THIRD petal (index 2, Cmd+3; the pair
/// chat + commander lives there) and LOGS takes index 0; petals 19..25 are the seven homes t27a, t27b, t27c,
/// t27f, t27o, t27t, t27u (specs/t27os/homes.t27 maps a home to its petal and reads its names from here, so
/// this string is the ONE definition). Before: TriangleLogo.worlds, from sacred_worlds.zig:99-141, with CHAT
/// first and REELS .. COMMUNITY at 19..25.
pub const WORLD_NAMES : str = "LOGS,CODE,CHAT,DEBUG,REVIEW,TRANSLATE,VIBEE,VOICE,COMPOSE,FILES,EDITOR,BUILD,TEST,TERMINAL,GIT,DEPLOY,DePIN NODE,SETTINGS,DOCS,T27A,T27B,T27C,T27F,T27O,T27T,T27U,ABOUT";
pub const REALM_NAMES : str = "RAZUM,MATERIYA,DUKH";

/// L3. Colours as 0xAARRGGBB. Realm colours from sacred_worlds.zig: gold, cyan, purple.
Expand Down
187 changes: 182 additions & 5 deletions specs/t27os/glass_window.t27
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ use t27f::petal_menu::on_back;
use t27f::petal_menu::menu_open;
use t27f::petal_menu::card_x;
use t27f::petal_menu::card_y;
use t27os::homes::PETAL_CHAT;
use t27os::homes::HOME_COUNT;
use t27os::homes::HOME_NAMES;
use t27os::homes::HOME_ROLES;
use t27os::homes::home_of_petal;
use t27os::homes::home_cards;
use t27os::homes::card_title;
use t27os::homes::card_line;
use t27os::homes::card_note;
use t27os::doctor::ROOT_HOME;
use t27os::doctor::ROOT_TMP;
use t27os::doctor::ROOT_TMP_PATH;
Expand Down Expand Up @@ -1981,6 +1990,95 @@ fn draw_cards(c: u64, kit: [48]u64, task: u32, a: f64, collapsed: bool, mx: f64,
}
}

/// H. The body of a home tab is the chat's card column with no sidebar: the same slots, the same honeycomb.
pub fn home_card_at(x: f64, y: f64, sw: f64, sh: f64, p: u32) -> u32 {
const k : u32 = card_at(x, y, sw, sh, WS_EXPANDED, true);
if (k < home_cards(home_of_petal(p))) { return k; }
return CARD_SLOTS;
}

/// H. Text from a table constant, as bytes.
fn draw_str(c: u64, kit: [48]u64, s: []const u8, x: f64, base: f64, size: f64, weight: f64) -> f64 {
return draw_bytes(c, kit, s, s.len, x, base, size, weight, false);
}

/// H. One line of a card, centred on kx and cut with an ellipsis where it would pass the cell's width.
fn draw_mid(c: u64, kit: [48]u64, s: []const u8, n: usize, kx: f64, base: f64, size: f64, weight: f64, room: f64) -> void {
if (n == 0) { return; }
const ns : u64 = cf_bytes(0, s, n, UTF8, false);
if (ns == 0) { return; }
const w : f64 = text_w(kit, ns, size, weight, false);
if (w <= room) {
draw_text(c, kit, ns, kx - 0.5 * w, base, size, weight, false);
} else {
draw_text_fit(c, kit, ns, kx - 0.5 * room, base, size, weight, false, kx + 0.5 * room);
}
cf_release(ns);
}

/// H. The screen of a petal that is not the CHAT petal (t27 OS: black and white, shape and text only). The
/// title bar below is the chat's; the header names the petal and, for a home, the home and its role; the body
/// is the 3 x 3 honeycomb with the cards homes.t27 lists for that home (agents, widget counts, courses). A petal
/// that is no home shows the nine empty cells (petal_menu: every menu empty).
fn draw_home(c: u64, kit: [48]u64, p: u32, a: f64, mx: f64, my: f64, sw: f64, sh: f64) -> void {
const h : u32 = home_of_petal(p);
cg_fill_rgba(c, 0.0, 0.0, 0.0, STRICT_CONTENT * a);
cg_fill_rect(c, 0.0, WS_TOP, sw, sh - WS_TOP);
const base : f64 = WS_TOP + 0.5 * HEADER_H + 4.2;
cg_fill_rgba(c, 1.0, 1.0, 1.0, TEXT_WHITE * a);
const tw : f64 = draw_text(c, kit, world(kit, p), 14.0, base, 12.0, WEIGHT_SEMIBOLD, false);
if (h < HOME_COUNT) {
cg_fill_rgba(c, 1.0, 1.0, 1.0, MUTED_WHITE * a);
const nw : f64 = draw_str(c, kit, HOME_NAMES[h], 14.0 + tw + 12.0, base, 11.0, WEIGHT_MEDIUM);
cg_fill_rgba(c, 1.0, 1.0, 1.0, LABEL_WHITE * a);
const rx : f64 = 14.0 + tw + 12.0 + nw + 12.0;
const rn : usize = HOME_ROLES[h].len;
const rs : u64 = cf_bytes(0, HOME_ROLES[h], rn, UTF8, false);
if (rs != 0) {
draw_text_fit(c, kit, rs, rx, base, 10.0, 0.0, false, sw - 14.0);
cf_release(rs);
}
}
cg_fill_rgba(c, 1.0, 1.0, 1.0, LINE_WHITE * a);
cg_fill_rect(c, 0.0, WS_TOP + HEADER_H, sw, HAIR);
const l : f64 = body_left(sw, WS_EXPANDED, true);
const t : f64 = body_top(WS_EXPANDED);
const w : f64 = body_w(sw, WS_EXPANDED, true);
const bh : f64 = body_h(sw, sh, WS_EXPANDED, true);
const r : f64 = hex_r(w, bh);
const room : f64 = SQRT3 * r - 16.0;
var hk : u32 = CARD_SLOTS;
if (a >= 1.0) { hk = home_card_at(mx, my, sw, sh, p); }
var tb : [64]u8 = undefined;
var k : u32 = 0;
while (k < CARD_SLOTS) {
const ka : f64 = card_alpha(a, k);
var kf : f64 = STRICT_CARD_FILL;
if (k == hk) { kf = STRICT_HOVER_FILL; }
const kx : f64 = hex_c(k, 0, l, t, w, bh);
const ky : f64 = hex_c(k, 1, l, t, w, bh) + (1.0 - ka) * 6.0;
hex_path(c, kx, ky, r - 0.25);
cg_fill_rgba(c, 1.0, 1.0, 1.0, kf * ka);
cg_fill_path(c);
cg_line_width(c, cell_line(k));
hex_path(c, kx, ky, r - 0.25);
cg_stroke_rgba(c, 1.0, 1.0, 1.0, cell_edge(k, hk, CARD_SLOTS) * ka);
cg_stroke_path(c);
if (h < HOME_COUNT and k < home_cards(h)) {
cg_fill_rgba(c, 1.0, 1.0, 1.0, TEXT_WHITE * ka);
const n1 : usize = card_title(h, k, tb[0..64]);
draw_mid(c, kit, tb[0..64], n1, kx, ky - 3.0, 11.0, WEIGHT_SEMIBOLD, room);
cg_fill_rgba(c, 1.0, 1.0, 1.0, MUTED_WHITE * ka);
const n2 : usize = card_line(h, k, tb[0..64]);
draw_mid(c, kit, tb[0..64], n2, kx, ky + 12.0, 9.5, 0.0, room);
cg_fill_rgba(c, 1.0, 1.0, 1.0, LABEL_WHITE * ka);
const n3 : usize = card_note(h, k, tb[0..64]);
draw_mid(c, kit, tb[0..64], n3, kx, ky + 25.0, 8.5, 0.0, room);
}
k = k + 1;
}
}

/// F. The frame's fill alpha: clear in a window (matte black glass, the blur and the layer tint show
/// through), opaque black #000000 in full screen (no transparency there).
pub fn backdrop_alpha(full: bool) -> f64 {
Expand Down Expand Up @@ -2534,13 +2632,19 @@ fn draw(c: u64, kit: [48]u64, frame: u32, state: u32, hov: u32, ma: f64, shown:
if (hov != PETAL_NONE) { draw_tooltip(c, kit, hov, ha, z, sw, sh); }
}
if (ma > 0.0) {
draw_chat(c, kit, shown, task, space, sp, ss, cur, ma, collapsed, mx, my, sw, sh, ws, dlabel, dp);
if (topen != PANE_NONE) { draw_term(c, kit, tst, tcells, tcur, ma, collapsed, sw, sh, ws); }
// the screen of petal `shown`: the chat workspace for the CHAT petal (index 2), a home tab for t27a ..
// t27u, an empty frame with the petal's name for every other petal
if (shown == PETAL_CHAT) {
draw_chat(c, kit, shown, task, space, sp, ss, cur, ma, collapsed, mx, my, sw, sh, ws, dlabel, dp);
if (topen != PANE_NONE) { draw_term(c, kit, tst, tcells, tcur, ma, collapsed, sw, sh, ws); }
} else {
draw_home(c, kit, shown, ma, mx, my, sw, sh);
}
}
if (qp) { draw_queen_panel(c, kit, sw, sh, mx, my, view_of(menu_open(state), shown), space, ss, cur, ring, n, now, sug, god); }
if (dp and qp == false) { draw_doctor_panel(c, kit, dk, sw, sh, mx, my, darmed, doff, dgo, dlive); }
if (kyp and qp == false and dp == false) { draw_keys_panel(c, kit, sw, sh, mx, my, kstored, kmask, kmlen, kst, kfail, kopen, now, kedit, kbuf, klen, karm, kbusy, kemask, kewhy, ktpick); }
if (ma > 0.0 and ws == WS_EXPANDED and collapsed == false) {
if (ma > 0.0 and shown == PETAL_CHAT and ws == WS_EXPANDED and collapsed == false) {
// K. KEYS in the foot, left of DOCTOR
var ka : f64 = LABEL_WHITE;
if (kyp or on_keys_foot(mx, my, sh, ws, collapsed)) { ka = TEXT_WHITE; }
Expand Down Expand Up @@ -3738,7 +3842,10 @@ pub fn main() -> void {
var vy : i64 = @as(i64, @intFromFloat(virt(my, 1, z, sw, sh)));
// H. the logo answers the mouse only at home, once the screen has gone.
const home_live : bool = menu_open(state) == false and ma == 0.0 and my > AREA_TOP;
const screen : bool = menu_open(state) and ma >= 0.5;
// the CHAT petal's screen carries every chat control; a home tab (any other petal) carries only the
// title bar's back chevron and its cards
const screen : bool = menu_open(state) and ma >= 0.5 and shown == PETAL_CHAT;
const hscreen : bool = menu_open(state) and ma >= 0.5 and shown != PETAL_CHAT;
now = unix_time(0);
var sug : u32 = shown_suggestion(suggest_for(sessions_in(ss, space), cur != SESSION_NONE, screen and ktpick != TERM_NONE, edone, space), dismissed);
var ev : u64 = msg_event(app, s_next, 0xffffffffffffffff, msg_f(date_cls, s_wait, fwait), mode, true);
Expand Down Expand Up @@ -3875,7 +3982,7 @@ pub fn main() -> void {
msg_set_frame(win, s_set_frame, vf[0] + vf[2] - PANEL_W, vf[1], PANEL_W, vf[3], true, true);
}
docked = docked == false;
} else if (screen and on_nav_back(mx, my, full)) {
} else if ((screen or hscreen) and on_nav_back(mx, my, full)) {
state = on_back(state);
ctl = C_HOME;
} else if (screen and on_open_dash(mx, my, sw, ws)) {
Expand Down Expand Up @@ -4413,6 +4520,7 @@ pub fn main() -> void {
var hov : u32 = PETAL_NONE;
if (home_live) { hov = hit_px(vx, vy, 960, 540); }
var on_control : bool = on_home_button(mx, my, sw) or on_full_button(mx, my, sw) or on_dock_button(mx, my, sw);
if (hscreen and on_nav_back(mx, my, full)) { on_control = true; }
if (screen and (on_nav_back(mx, my, full) or on_side_toggle(mx, my, ws, collapsed))) { on_control = true; }
if (screen and (on_open_dash(mx, my, sw, ws) or on_close_dash(mx, my, ws, collapsed))) { on_control = true; }
if (screen and ma >= 1.0 and card_at(mx, my, sw, sh, ws, collapsed) != CARD_SLOTS) { on_control = true; }
Expand Down Expand Up @@ -4934,3 +5042,72 @@ test the_editor_view_shares_the_terminal_areas_key_space_with_the_chat_panes {
assert view_key(true, true, 2) == VIEW_EDITOR;
assert view_key(true, false, SESSION_NONE) == VIEW_EDITOR;
}

test chat_is_the_third_petal_and_cmd_3_opens_it {
assert PETAL_CHAT == 2;
assert petal_for_key(3, MOD_COMMAND) == PETAL_CHAT;
assert petal_for_key(1, MOD_COMMAND) == 0;
assert petal_for_key(4, MOD_COMMAND) == 3;
assert PETAL_CHAT != 0;
}

test each_home_petal_draws_its_own_home_and_the_rest_draw_the_empty_frame {
var p : u32 = 19;
while (p <= 25) {
assert home_of_petal(p) == p - 19;
assert home_cards(home_of_petal(p)) >= 2;
p = p + 1;
}
assert home_of_petal(PETAL_CHAT) == 7;
assert home_of_petal(0) == HOME_COUNT;
assert home_of_petal(1) == HOME_COUNT;
assert home_of_petal(26) == HOME_COUNT;
assert home_of_petal(18) == HOME_COUNT;
assert home_cards(home_of_petal(26)) == 0;
}

test a_card_in_a_home_tab_is_hit_where_it_is_drawn_and_only_for_cards_that_exist {
const l : f64 = body_left(W_PT, WS_EXPANDED, true);
const t : f64 = body_top(WS_EXPANDED);
const w : f64 = body_w(W_PT, WS_EXPANDED, true);
const bh : f64 = body_h(W_PT, H_PT, WS_EXPANDED, true);
var p : u32 = 19;
while (p <= 25) {
const n : u32 = home_cards(home_of_petal(p));
var hits : u32 = 0;
var k : u32 = 0;
while (k < CARD_SLOTS) {
const got : u32 = home_card_at(hex_c(k, 0, l, t, w, bh), hex_c(k, 1, l, t, w, bh), W_PT, H_PT, p);
if (k < n) { assert got == k; hits = hits + 1; }
if (k >= n) { assert got == CARD_SLOTS; }
k = k + 1;
}
assert hits == n;
p = p + 1;
}
// a petal that is no home has no card to hit, and neither has the empty corner of the body
assert home_card_at(hex_c(0, 0, l, t, w, bh), hex_c(0, 1, l, t, w, bh), W_PT, H_PT, 26) == CARD_SLOTS;
assert home_card_at(1.0, 1.0, W_PT, H_PT, 21) == CARD_SLOTS;
}

test the_home_tab_cards_do_not_overlap_and_hold_nine_slots {
const l : f64 = body_left(W_PT, WS_EXPANDED, true);
const t : f64 = body_top(WS_EXPANDED);
const w : f64 = body_w(W_PT, WS_EXPANDED, true);
const bh : f64 = body_h(W_PT, H_PT, WS_EXPANDED, true);
const r : f64 = hex_r(w, bh);
var a : u32 = 0;
while (a < CARD_SLOTS) {
var b : u32 = a + 1;
while (b < CARD_SLOTS) {
const dx : f64 = hex_c(a, 0, l, t, w, bh) - hex_c(b, 0, l, t, w, bh);
const dy : f64 = hex_c(a, 1, l, t, w, bh) - hex_c(b, 1, l, t, w, bh);
assert dx * dx + dy * dy > 4.0 * 0.75 * r * r;
b = b + 1;
}
a = a + 1;
}
assert CARD_SLOTS == 9;
// the title bar's back chevron answers on a home tab exactly as on the chat
assert on_nav_back(home_x(false) + 2.0, 0.5 * TITLE_H, false);
}
Loading
Loading