From 40fe7f26e34a6591ac2890a9450adb62058b18e9 Mon Sep 17 00:00:00 2001 From: Trinity Bee Date: Mon, 5 Oct 2026 09:29:09 +0000 Subject: [PATCH 01/17] Port hermes-provider-map.ts to .t27 (isHermesSupportedProviderType, getHermesProviderMapping) Re-authors trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.ts (gHashTag/BrowserOS at 879799a8bfb2, 86 lines) as a .t27 spec, so the table and its two lookups are generated instead of hand-written. The file is pure decision - one fixed table, two lookups - so every function carries a real body; no undefined; plumbing exists or is needed. Port decisions, documented in the spec header: - isHermesSupportedProviderType: the shared supported-type set from @browseros/shared/constants/hermes (exactly the four keys of the original's HERMES_PROVIDER_MAP) inlined as case-sensitive literal comparisons, mirroring the original's .includes() membership test. - getHermesProviderMapping: the four-entry table as per-key helpers plus a lookup with a verdict struct (ok + mapping), because the original's `HermesProviderMapping | undefined` return cannot compile in .t27 today (no optional unwrap). ok == false carries the original's `undefined`. - The original's optional `defaultBaseUrl?` becomes hasDefaultBaseUrl plus defaultBaseUrl ("" when absent). Six test blocks assert the original's behavior: all four supported types, case/whitespace-sensitive rejection, every table entry field by field, the zero mapping, and the public lookup for supported and unsupported types. t27c parse: OK. t27c typecheck: Typecheck OK (0 errors, 0 warnings). t27c gen: generates (147 lines, 0 "not yet implemented" markers). t27c test-report: 6/6 tests pass, no FAIL, grep -c BLOCKED = 0. Coverage: 7/7 functions tested (100%). Closes #6381 --- .../lib/agents/hermes/hermes-provider-map.t27 | 205 ++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 diff --git a/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 b/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 new file mode 100644 index 0000000000..3f8238cafc --- /dev/null +++ b/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 @@ -0,0 +1,205 @@ +// Port of trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.ts +// (gHashTag/BrowserOS at 879799a8bfb2, 86 lines of hand-written TypeScript). +// +// The original is the decision table from BrowserOS LLM provider types (the +// values that live in LlmProviderConfig.type on the extension side) to Hermes +// runtime configuration: which provider key to write into `model.provider` in +// config.yaml, which env var carries the API key, and whether an explicit +// baseUrl is required. The whole file is a decision - one fixed table, two +// lookups - so both exported functions are ported with real bodies; there is +// no plumbing and no function body is left undefined. +// +// Three shape changes the language forces, documented rather than faked: +// - The original imports HERMES_SUPPORTED_BROWSEROS_PROVIDER_TYPES from +// @browseros/shared/constants/hermes. That set is exactly the keys of the +// original's HERMES_PROVIDER_MAP (the original type-checks that every +// supported type has a mapping), so the four values are inlined here as +// the decision they carry. +// - The original's optional `defaultBaseUrl?` field becomes hasDefaultBaseUrl +// plus defaultBaseUrl ("" when absent). In the original the field is only +// read when hermesProvider is "custom" and the caller passed no baseUrl. +// - The original's `HermesProviderMapping | undefined` return becomes a +// verdict struct: ok == false is the original's `undefined`, i.e. agent +// creation rejects the type and no mapping exists for it. + +pub struct HermesProviderMapping { + // Hermes' own provider key, written into `model.provider` in config.yaml. + hermesProvider: []const u8, + // Env var Hermes reads the API key from. + envVarName: []const u8, + // True when the harness must require an explicit baseUrl from input. + requiresBaseUrl: bool, + // True when the original mapping carries a defaultBaseUrl. + hasDefaultBaseUrl: bool, + defaultBaseUrl: []const u8, +} + +pub struct HermesMappingResult { + // False is the original's `undefined`: unsupported provider type. + ok: bool, + mapping: HermesProviderMapping, +} + +// The original's HERMES_SUPPORTED_BROWSEROS_PROVIDER_TYPES.includes(providerType): +// a case-sensitive membership test over the shared constant, whose values are +// exactly the keys of the original's HERMES_PROVIDER_MAP. Inlined here as +// literal comparisons. +pub fn isHermesSupportedProviderType(providerType: []const u8) -> bool { + if (providerType == "anthropic") { + return true; + } + if (providerType == "openai") { + return true; + } + if (providerType == "openrouter") { + return true; + } + if (providerType == "openai-compatible") { + return true; + } + return false; +} + +// The zero mapping, standing in for an absent table entry. +fn hermes_mapping_empty() -> HermesProviderMapping { + return HermesProviderMapping { hermesProvider: "", envVarName: "", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +} + +// HERMES_PROVIDER_MAP.anthropic: pass-through, no base URL involved. +fn hermes_mapping_anthropic() -> HermesProviderMapping { + return HermesProviderMapping { hermesProvider: "anthropic", envVarName: "ANTHROPIC_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +} + +// HERMES_PROVIDER_MAP.openai: the original rewrites this to Hermes' custom +// provider shape and carries the OpenAI base URL as the default. +fn hermes_mapping_openai() -> HermesProviderMapping { + return HermesProviderMapping { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: true, defaultBaseUrl: "https://api.openai.com/v1" }; +} + +// HERMES_PROVIDER_MAP.openrouter: pass-through, no base URL involved. +fn hermes_mapping_openrouter() -> HermesProviderMapping { + return HermesProviderMapping { hermesProvider: "openrouter", envVarName: "OPENROUTER_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +} + +// HERMES_PROVIDER_MAP["openai-compatible"]: custom provider shape, and the +// caller must supply the base URL explicitly. +fn hermes_mapping_openai_compatible() -> HermesProviderMapping { + return HermesProviderMapping { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: true, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +} + +// The original's getHermesProviderMapping: the table entry for a supported +// provider type, `undefined` when it is not supported. ok == false carries +// the `undefined`; the zero mapping it arrives with must not be read as a +// real entry. +pub fn getHermesProviderMapping(providerType: []const u8) -> HermesMappingResult { + if (!isHermesSupportedProviderType(providerType)) { + return HermesMappingResult { ok: false, mapping: hermes_mapping_empty() }; + } + if (providerType == "anthropic") { + return HermesMappingResult { ok: true, mapping: hermes_mapping_anthropic() }; + } + if (providerType == "openai") { + return HermesMappingResult { ok: true, mapping: hermes_mapping_openai() }; + } + if (providerType == "openrouter") { + return HermesMappingResult { ok: true, mapping: hermes_mapping_openrouter() }; + } + // Only "openai-compatible" is left: the guard above rejects everything + // else, so this fall-through mirrors the original's table index. + return HermesMappingResult { ok: true, mapping: hermes_mapping_openai_compatible() }; +} + +// The four supported BrowserOS provider types: exactly the shared constant +// the original imports, i.e. the keys of the original's table. +test is_supported_provider_types { + assert(isHermesSupportedProviderType("anthropic")); + assert(isHermesSupportedProviderType("openai")); + assert(isHermesSupportedProviderType("openrouter")); + assert(isHermesSupportedProviderType("openai-compatible")); +} + +// The original's check is case-sensitive (a plain string includes over the +// constant) and whitespace-significant; anything else yields no mapping. +test rejects_unsupported_provider_types { + assert(!isHermesSupportedProviderType("gemini")); + assert(!isHermesSupportedProviderType("Anthropic")); + assert(!isHermesSupportedProviderType("openai_compatible")); + assert(!isHermesSupportedProviderType(" openai")); + assert(!isHermesSupportedProviderType("")); +} + +// Each entry of the original's HERMES_PROVIDER_MAP, field by field. +test mapping_entries { + const anthropic = hermes_mapping_anthropic(); + assert(anthropic.hermesProvider == "anthropic"); + assert(anthropic.envVarName == "ANTHROPIC_API_KEY"); + assert(!anthropic.requiresBaseUrl); + assert(!anthropic.hasDefaultBaseUrl); + + const openai = hermes_mapping_openai(); + assert(openai.hermesProvider == "custom"); + assert(openai.envVarName == "OPENAI_API_KEY"); + assert(!openai.requiresBaseUrl); + assert(openai.hasDefaultBaseUrl); + assert(openai.defaultBaseUrl == "https://api.openai.com/v1"); + + const openrouter = hermes_mapping_openrouter(); + assert(openrouter.hermesProvider == "openrouter"); + assert(openrouter.envVarName == "OPENROUTER_API_KEY"); + assert(!openrouter.requiresBaseUrl); + assert(!openrouter.hasDefaultBaseUrl); + + const compatible = hermes_mapping_openai_compatible(); + assert(compatible.hermesProvider == "custom"); + assert(compatible.envVarName == "OPENAI_API_KEY"); + assert(compatible.requiresBaseUrl); + assert(!compatible.hasDefaultBaseUrl); +} + +// The zero mapping that stands in for an absent entry: empty strings, no +// default base URL. +test mapping_empty { + const m = hermes_mapping_empty(); + assert(m.hermesProvider == ""); + assert(m.envVarName == ""); + assert(!m.requiresBaseUrl); + assert(!m.hasDefaultBaseUrl); + assert(m.defaultBaseUrl == ""); +} + +// The public lookup for supported types: ok with the table's entry. +test get_mapping_supported { + const a = getHermesProviderMapping("anthropic"); + assert(a.ok); + assert(a.mapping.hermesProvider == "anthropic"); + assert(a.mapping.envVarName == "ANTHROPIC_API_KEY"); + assert(!a.mapping.requiresBaseUrl); + + const o = getHermesProviderMapping("openai"); + assert(o.ok); + assert(o.mapping.hermesProvider == "custom"); + assert(o.mapping.envVarName == "OPENAI_API_KEY"); + assert(o.mapping.hasDefaultBaseUrl); + assert(o.mapping.defaultBaseUrl == "https://api.openai.com/v1"); + + const r = getHermesProviderMapping("openrouter"); + assert(r.ok); + assert(r.mapping.hermesProvider == "openrouter"); + assert(r.mapping.envVarName == "OPENROUTER_API_KEY"); + + const c = getHermesProviderMapping("openai-compatible"); + assert(c.ok); + assert(c.mapping.hermesProvider == "custom"); + assert(c.mapping.requiresBaseUrl); + assert(!c.mapping.hasDefaultBaseUrl); +} + +// Unsupported types get the original's `undefined`: ok == false. +test get_mapping_unsupported { + const g = getHermesProviderMapping("gemini"); + assert(!g.ok); + const blank = getHermesProviderMapping(""); + assert(!blank.ok); + const cased = getHermesProviderMapping("Anthropic"); + assert(!cased.ok); +} From 29bdc214ad208d772475b69c5c87423fc68397a9 Mon Sep 17 00:00:00 2001 From: "queen-publisher[bot]" Date: Mon, 5 Oct 2026 09:51:48 +0000 Subject: [PATCH 02/17] docs: the coordination entry this branch needs to land A pull request must add exactly one docs/now entry and a bee has no way to know that: its brief names a boundary file and acceptance criteria, and docs/now/ is neither. The publisher adds it rather than failing the gate. Closes #6381 Co-Authored-By: Claude Opus 5 --- ...-browseros-trios-agent-server-apps-server-src-l.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/now/2026-10-05-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md diff --git a/docs/now/2026-10-05-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md b/docs/now/2026-10-05-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md new file mode 100644 index 0000000000..f334325de3 --- /dev/null +++ b/docs/now/2026-10-05-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md @@ -0,0 +1,11 @@ +# NOW -- Port gHashTag/BrowserOS:trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.ts (TypeScript, 2 functions) to specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 (published 2026-10-05) + +## A bee's work on #6381, published from `queen-6381` (Closes #6381) + +- The branch changes 1 file(s): `specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27`. +- `git diff --stat origin/master...queen-6381` reads: 1 file changed, 205 insertions(+) +- This entry is written by the publisher, not by the bee. A pull request must + add exactly one `docs/now/` entry and a bee has no way to know that: its brief + names a boundary file and acceptance criteria, and `docs/now/` is neither. +- What this entry does NOT establish: that the work is correct. The gates on the + pull request judge that, and they are the same gates every other change meets. From d82e22af45e57a2e111353a03077a7bf7500221b Mon Sep 17 00:00:00 2001 From: Trinity Bee Date: Mon, 5 Oct 2026 17:19:15 +0000 Subject: [PATCH 03/17] Port gHashTag/trinity:src/brain/fusiform_gyrus.zig to specs/port/trinity/src/brain/fusiform_gyrus.t27 Closes #6383 --- .../port/trinity/src/brain/fusiform_gyrus.t27 | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 specs/port/trinity/src/brain/fusiform_gyrus.t27 diff --git a/specs/port/trinity/src/brain/fusiform_gyrus.t27 b/specs/port/trinity/src/brain/fusiform_gyrus.t27 new file mode 100644 index 0000000000..1b6d29d8b4 --- /dev/null +++ b/specs/port/trinity/src/brain/fusiform_gyrus.t27 @@ -0,0 +1,115 @@ +module port::trinity::src::brain::fusiform_gyrus; + +pub fn encodeF32ToGF16(v: f32) -> u16 { + if (v == 0.0) { + return 0; + } + + // Check for infinity + if (v > 1.0e38) { + return if (v < 0) 0xFFFF else 0x7FFF; + } + if (v < -1.0e38) { + return 0xFFFF; + } + + const sign: u16 = if (v < 0) 1 << 15 else 0; + const abs_v = if (v < 0) -v else v; + + var exp: i16 = 0; + var mant_f: f64 = abs_v; + while (mant_f >= 1.0 and exp < 31) : (exp += 1) { + mant_f /= 2.0; + } + while (mant_f < 0.5 and exp > -32) : (exp -= 1) { + mant_f *= 2.0; + } + + const temp_exp: i32 = exp + 31; + const clamped_temp: i32 = if (temp_exp > 63) 63 else if (temp_exp < 0) 0 else temp_exp; + const exp_u6: u16 = clamped_temp as u16; + const clamped_exp: u16 = if (exp_u6 > 63) 63 else exp_u6; + const mant_u9: u16 = @intFromFloat((mant_f - 0.5) * 512.0); + const clamped_mant: u16 = if (mant_u9 > 511) 511 else mant_u9; + + return sign | (clamped_exp << 9) | (clamped_mant & 0x1FF); +} + +pub fn decodeGF16ToF32(raw: u16) -> f32 { + if (raw == 0) { + return 0.0; + } + if (raw == 0x8000) { + return -0.0; + } + + const sign: f32 = if ((raw >> 15) & 1 == 1) -1.0 else 1.0; + const exp: u16 = (raw >> 9) & 0x3F; + const mant: u16 = raw & 0x1FF; + + if (exp == 0x3F) { + return if (sign < 0) -999999.0 else 999999.0; + } + + const exp_f: f32 = @as(f32, exp) - 31.0; + const mant_f: f32 = 0.5 + @as(f32, mant) * 0.001953125; + + // Simplified power calculation for 2^exp_f + var power: f32 = 1.0; + var abs_exp: usize = if (exp_f > 10.0) 10 else if (exp_f > 5.0) 5 else if (exp_f > 0.0) 2 else if (exp_f > -5.0) 5 else 8; + for (0..abs_exp) |_| { + if (exp_f > 0.0) { + power *= 2.0; + } else { + power *= 0.5; + } + } + + return sign * mant_f * power; +} + +pub fn encodeBF16(v: f32) -> u16 { + const bits: u32 = @bitCast(v); + return @intCast(bits >> 16); +} + +pub fn decodeBF16(raw: u16) -> f32 { + const bits: u32 = @as(u32, raw) << 16; + return @bitCast(bits); +} + +test encodeF32ToGF16_zero { + assert(encodeF32ToGF16(0.0) == 0); +} + +test encodeF32ToGF16_positive { + assert(encodeF32ToGF16(1.0) == 0x4000); +} + +test encodeF32ToGF16_negative { + assert(encodeF32ToGF16(-1.0) == 0xC000); +} + +test decodeGF16ToF32_zero { + assert(decodeGF16ToF32(0) == 0.0); +} + +test decodeGF16ToF32_negative_zero { + assert(decodeGF16ToF32(0x8000) == -0.0); +} + +test encodeBF16_simple { + assert(encodeBF16(1.0) == 0x3F80); +} + +test decodeBF16_simple { + assert(decodeBF16(0x3F80) == 1.0); +} + +test encode_decode_GF16_roundtrip { + const original: f32 = 3.14; + const encoded = encodeF32ToGF16(original); + const decoded = decodeGF16ToF32(encoded); + const err = @abs(original - decoded) / original; + assert(err < 0.01); +} \ No newline at end of file From d5bdc33a41357faee099596616b7a9ce24c4820b Mon Sep 17 00:00:00 2001 From: "queen-publisher[bot]" Date: Tue, 6 Oct 2026 14:23:05 +0000 Subject: [PATCH 04/17] docs: the coordination entry this branch needs to land A pull request must add exactly one docs/now entry and a bee has no way to know that: its brief names a boundary file and acceptance criteria, and docs/now/ is neither. The publisher adds it rather than failing the gate. Closes #6383 Co-Authored-By: Claude Opus 5 --- ...-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/now/2026-10-06-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md diff --git a/docs/now/2026-10-06-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md b/docs/now/2026-10-06-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md new file mode 100644 index 0000000000..870230831c --- /dev/null +++ b/docs/now/2026-10-06-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md @@ -0,0 +1,11 @@ +# NOW -- Port gHashTag/trinity:src/brain/fusiform_gyrus.zig (Zig, 4 functions) to specs/port/trinity/src/brain/fusiform_gyrus.t27 (published 2026-10-06) + +## A bee's work on #6383, published from `queen-6383` (Closes #6383) + +- The branch changes 1 file(s): `specs/port/trinity/src/brain/fusiform_gyrus.t27`. +- `git diff --stat origin/master...queen-6383` reads: 1 file changed, 115 insertions(+) +- This entry is written by the publisher, not by the bee. A pull request must + add exactly one `docs/now/` entry and a bee has no way to know that: its brief + names a boundary file and acceptance criteria, and `docs/now/` is neither. +- What this entry does NOT establish: that the work is correct. The gates on the + pull request judge that, and they are the same gates every other change meets. From 86eb3ac7fed845d04d3a53ceebb39c1fc78669e0 Mon Sep 17 00:00:00 2001 From: "queen-publisher[bot]" Date: Mon, 12 Oct 2026 13:13:15 +0000 Subject: [PATCH 05/17] docs: the coordination entry this branch needs to land A pull request must add exactly one docs/now entry and a bee has no way to know that: its brief names a boundary file and acceptance criteria, and docs/now/ is neither. The publisher adds it rather than failing the gate. Closes #6381 Co-Authored-By: Claude Opus 5 --- ...-browseros-trios-agent-server-apps-server-src-l.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/now/2026-10-12-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md diff --git a/docs/now/2026-10-12-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md b/docs/now/2026-10-12-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md new file mode 100644 index 0000000000..9296ad7bff --- /dev/null +++ b/docs/now/2026-10-12-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md @@ -0,0 +1,11 @@ +# NOW -- Port gHashTag/BrowserOS:trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.ts (TypeScript, 2 functions) to specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 (published 2026-10-12) + +## A bee's work on #6381, published from `queen-6381` (Closes #6381) + +- The branch changes 2 file(s): `docs/now/2026-10-05-published-port-ghashtag-browseros-trios-agent-server-apps-server-src-l.md`, `specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27`. +- `git diff --stat origin/master...queen-6381` reads: 2 files changed, 216 insertions(+) +- This entry is written by the publisher, not by the bee. A pull request must + add exactly one `docs/now/` entry and a bee has no way to know that: its brief + names a boundary file and acceptance criteria, and `docs/now/` is neither. +- What this entry does NOT establish: that the work is correct. The gates on the + pull request judge that, and they are the same gates every other change meets. From 1cd82ef2d4302a4b73d849226572b07d19ad1e95 Mon Sep 17 00:00:00 2001 From: "queen-publisher[bot]" Date: Mon, 12 Oct 2026 20:26:00 +0000 Subject: [PATCH 06/17] docs: the coordination entry this branch needs to land A pull request must add exactly one docs/now entry and a bee has no way to know that: its brief names a boundary file and acceptance criteria, and docs/now/ is neither. The publisher adds it rather than failing the gate. Closes #6383 Co-Authored-By: Claude Opus 5 --- ...-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 docs/now/2026-10-12-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md diff --git a/docs/now/2026-10-12-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md b/docs/now/2026-10-12-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md new file mode 100644 index 0000000000..a669ef0d55 --- /dev/null +++ b/docs/now/2026-10-12-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md @@ -0,0 +1,11 @@ +# NOW -- Port gHashTag/trinity:src/brain/fusiform_gyrus.zig (Zig, 4 functions) to specs/port/trinity/src/brain/fusiform_gyrus.t27 (published 2026-10-12) + +## A bee's work on #6383, published from `queen-6383` (Closes #6383) + +- The branch changes 2 file(s): `docs/now/2026-10-06-published-port-ghashtag-trinity-src-brain-fusiform-gyrus-zig-zig-4-fun.md`, `specs/port/trinity/src/brain/fusiform_gyrus.t27`. +- `git diff --stat origin/master...queen-6383` reads: 2 files changed, 126 insertions(+) +- This entry is written by the publisher, not by the bee. A pull request must + add exactly one `docs/now/` entry and a bee has no way to know that: its brief + names a boundary file and acceptance criteria, and `docs/now/` is neither. +- What this entry does NOT establish: that the work is correct. The gates on the + pull request judge that, and they are the same gates every other change meets. From 367ddeb4ee5a75abeef2cb6989aa4cfabbb7fedd Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 17:02:48 -0300 Subject: [PATCH 07/17] spec(port): port specs/port/trinity/src/bsd/verify_lmfdb.t27 (Closes #9611) Port gHashTag/trinity:src/bsd/verify_lmfdb.zig (at ee512359254b, 84 lines) as specs/port/trinity/src/bsd/verify_lmfdb.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The BSD verification command's decisions are ported as pure functions and tested (7 tests, 7 pass, 0 vacuous, 35 runtime asserts, 100% function coverage): the usage gate (no argument prints usage and returns before any load), the --test default (bsd_test_curves.json; any other argument is the JSON path as-is), the rank-0 filter (only rank 0 curves are verified; everything else is skipped without failing), the BSD formula Sha = L(E,1) * torsion^2 / (Omega * c_p) carried as special_value * torsion^2 / c_p with the orders widened to f64 before the square so no integer multiply can overflow, the 0.5 match window (strict: a difference of exactly 0.5 fails, on either side), and the summary verdict (ALL PASSED exactly when nothing failed - a run with no eligible curves reaches it too). The JSON load, the table prints and the colour codes are the callers' plumbing. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 7/7, test-report 7/7 pass, 0 BLOCKED, gen 110 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 7 function names unique, bare body scan adds no group of mine. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- specs/port/trinity/src/bsd/verify_lmfdb.t27 | 136 ++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 specs/port/trinity/src/bsd/verify_lmfdb.t27 diff --git a/specs/port/trinity/src/bsd/verify_lmfdb.t27 b/specs/port/trinity/src/bsd/verify_lmfdb.t27 new file mode 100644 index 0000000000..60cff1a385 --- /dev/null +++ b/specs/port/trinity/src/bsd/verify_lmfdb.t27 @@ -0,0 +1,136 @@ +module port::trinity::verify_lmfdb; + +// Port of gHashTag/trinity:src/bsd/verify_lmfdb.zig (at ee512359254b, +// 84 lines) - t27 issue #9611, Roadmap Stage 5 (goal #4547), target t27c +// gen-rust. The BSD verification command's decisions as pure functions: +// the usage gate, the --test default path, the rank-0 filter, the BSD +// formula Sha = L(E,1) * torsion^2 / (Omega * c_p) carried as +// special_value * torsion^2 / c_p, the 0.5 match window, and the summary +// verdict. The JSON load, the table prints and the colour codes are the +// caller's plumbing. + +// The command's terminal states, as exit markers. +pub const VERIFY_LMFDB_USAGE: i32 = 0; +pub const VERIFY_LMFDB_ALL_PASSED: i32 = 1; +pub const VERIFY_LMFDB_SOME_FAILED: i32 = 2; + +// Lines 18-23: with no argument the command prints the usage block and +// returns - no curve is loaded, no verification runs. +pub fn verify_lmfdb_needs_usage(arg_count: usize) -> bool { + return arg_count < 1; +} + +// Lines 26-29: --test selects the built-in curve file; anything else is +// taken as the JSON path as-is. +pub fn verify_lmfdb_json_path(arg: []const u8) -> []const u8 { + if (arg == "--test") { + return "bsd_test_curves.json"; + } + return arg; +} + +// Line 50: only rank 0 curves are verified - everything else is skipped. +pub fn verify_lmfdb_rank_eligible(rank: i32) -> bool { + return rank == 0; +} + +// Lines 52-58: the BSD formula. special_value = L(E,1)/Omega, so +// Sha = special_value * torsion^2 / c_p. The orders are widened to f64 +// BEFORE the square, so no integer multiply can overflow. +pub fn verify_lmfdb_sha_from_formula(special_value: f64, torsion_order: i64, tamagawa_product: i64) -> f64 { + const torsion: f64 = torsion_order as f64; + const tamagawa: f64 = tamagawa_product as f64; + return special_value * (torsion * torsion) / tamagawa; +} + +// Lines 61-64: the computed Sha matches the known order when the two sit +// within 0.5 of each other - strictly: a difference of exactly 0.5 fails. +pub fn verify_lmfdb_sha_matches(sha_from_formula: f64, sha_order: i64) -> bool { + const known: f64 = sha_order as f64; + const diff = sha_from_formula - known; + if (diff < 0.0) { + return -diff < 0.5; + } + return diff < 0.5; +} + +// Lines 76-80: the summary says ALL PASSED exactly when nothing failed - +// a run with no eligible curves also reaches it (0/0 verified). +pub fn verify_lmfdb_all_passed(failed: usize) -> bool { + return failed == 0; +} + +// Line 7: the command itself. No argument: usage, nothing verified. With +// a path: each rank-0 curve is checked by the BSD formula and the 0.5 +// window; rank!=0 curves are skipped without failing anything. The +// summary is ALL PASSED when the failure count is zero, else SOME +// FAILED. +pub fn runVerifyLMFDBCommand(arg_count: usize, curve_rank: i32, special_value: f64, torsion_order: i64, tamagawa_product: i64, sha_order: i64) -> i32 { + if (verify_lmfdb_needs_usage(arg_count)) { + return VERIFY_LMFDB_USAGE; + } + if (!verify_lmfdb_rank_eligible(curve_rank)) { + return VERIFY_LMFDB_ALL_PASSED; + } + const sha = verify_lmfdb_sha_from_formula(special_value, torsion_order, tamagawa_product); + if (verify_lmfdb_sha_matches(sha, sha_order)) { + return VERIFY_LMFDB_ALL_PASSED; + } + return VERIFY_LMFDB_SOME_FAILED; +} + +test usage_gate_without_arguments { + assert(verify_lmfdb_needs_usage(0) == true); + assert(verify_lmfdb_needs_usage(1) == false); + assert(verify_lmfdb_needs_usage(3) == false); + assert(runVerifyLMFDBCommand(0, 0, 1.0, 1, 1, 1) == VERIFY_LMFDB_USAGE); +} + +test test_flag_selects_builtin_file { + assert(verify_lmfdb_json_path("--test") == "bsd_test_curves.json"); + assert(verify_lmfdb_json_path("my_curves.json") == "my_curves.json"); + assert(verify_lmfdb_json_path("--testx") == "--testx"); + assert(verify_lmfdb_json_path("") == ""); +} + +test only_rank_zero_verified { + assert(verify_lmfdb_rank_eligible(0) == true); + assert(verify_lmfdb_rank_eligible(1) == false); + assert(verify_lmfdb_rank_eligible(2) == false); + assert(verify_lmfdb_rank_eligible(-1) == false); + assert(runVerifyLMFDBCommand(1, 1, 99.0, 5, 5, 1) == VERIFY_LMFDB_ALL_PASSED); + assert(runVerifyLMFDBCommand(2, 3, 99.0, 5, 5, 1) == VERIFY_LMFDB_ALL_PASSED); +} + +test bsd_formula_values { + assert(verify_lmfdb_sha_from_formula(2.0, 2, 2) == 4.0); + assert(verify_lmfdb_sha_from_formula(0.5, 2, 4) == 0.5); + assert(verify_lmfdb_sha_from_formula(1.5, 3, 2) == 6.75); + assert(verify_lmfdb_sha_from_formula(1.0, 1, 1) == 1.0); + assert(verify_lmfdb_sha_from_formula(3.0, 2, 4) == 3.0); +} + +test match_window_is_half_open { + assert(verify_lmfdb_sha_matches(6.0, 6) == true); + assert(verify_lmfdb_sha_matches(6.4, 6) == true); + assert(verify_lmfdb_sha_matches(5.6, 6) == true); + assert(verify_lmfdb_sha_matches(6.5, 6) == false); + assert(verify_lmfdb_sha_matches(5.5, 6) == false); + assert(verify_lmfdb_sha_matches(6.6, 6) == false); + assert(verify_lmfdb_sha_matches(5.4, 6) == false); + assert(verify_lmfdb_sha_matches(0.25, 0) == true); +} + +test summary_verdict { + assert(verify_lmfdb_all_passed(0) == true); + assert(verify_lmfdb_all_passed(1) == false); + assert(verify_lmfdb_all_passed(7) == false); +} + +test command_verifies_one_curve { + assert(runVerifyLMFDBCommand(1, 0, 2.0, 2, 2, 4) == VERIFY_LMFDB_ALL_PASSED); + assert(runVerifyLMFDBCommand(1, 0, 2.0, 2, 2, 6) == VERIFY_LMFDB_SOME_FAILED); + assert(runVerifyLMFDBCommand(1, 0, 1.5, 3, 2, 7) == VERIFY_LMFDB_ALL_PASSED); + assert(runVerifyLMFDBCommand(2, 0, 1.5, 3, 2, 6) == VERIFY_LMFDB_SOME_FAILED); + assert(runVerifyLMFDBCommand(1, 0, 1.5, 3, 2, 3) == VERIFY_LMFDB_SOME_FAILED); +} From e632042ad1721c8e4f91e705a65496c517e016bd Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 17:26:07 -0300 Subject: [PATCH 08/17] spec(port): port specs/port/trinity/src/cli/tri_record.t27 (Closes #9620) Port gHashTag/trinity:src/cli/tri_record.zig (at ee512359254b, 157 lines) as specs/port/trinity/src/cli/tri_record.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The terminal-recording wrapper's decisions are ported as pure functions and tested (7 tests, 7 pass, 0 vacuous, 33 runtime asserts, 100% function coverage): the usage gate (only the program name prints usage and exits 1), the environment overrides with their fallback (a present-but-invalid value keeps the default, exactly like the original's catch; an absent variable too), the TRI_REC_OVERWRITE flag (presence alone turns it on), the basename cut (the GIF is named after the command's first word - the length up to the first space, or the whole command when it has none), the existing-GIF block (without overwrite an existing GIF stops the run), the exit-code cascade (usage, the GIF block, an asciinema failure and an agg failure each exit 1; only a finished recording exits 0), and the KB size display (bytes / 1024, truncated). The argv and environment reads, the directory creation, the file checks, the subprocess runs and the prints are the callers' plumbing; the Config record's five defaults are carried as consts plus the override rule. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 7/7, test-report 7/7 pass, 0 BLOCKED, gen 124 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 7 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- specs/port/trinity/src/cli/tri_record.t27 | 158 ++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 specs/port/trinity/src/cli/tri_record.t27 diff --git a/specs/port/trinity/src/cli/tri_record.t27 b/specs/port/trinity/src/cli/tri_record.t27 new file mode 100644 index 0000000000..3ad62a0a28 --- /dev/null +++ b/specs/port/trinity/src/cli/tri_record.t27 @@ -0,0 +1,158 @@ +module port::trinity::tri_record; + +// Port of gHashTag/trinity:src/cli/tri_record.zig (at ee512359254b, 157 +// lines) - t27 issue #9620, Roadmap Stage 5 (goal #4547), target t27c +// gen-rust. The terminal-recording wrapper's decisions as pure +// functions: the usage gate, the environment overrides with their +// keep-the-default fallback, the overwrite flag, the basename cut at the +// first space, the existing-GIF block, the exit-code cascade of the +// asciinema/agg stages, and the KB size display. The argv read, the +// environment reads, the directory creation, the file checks, the +// subprocess runs and the prints are the caller's plumbing. The +// original's Config record lives here as its five carried defaults +// (cols 120, rows 40, idle_max 3, overwrite false, output_dir +// "recordings") plus the override rule as a function. + +// Exit codes of the command (main returns u8: 1 on every failure, 0 on +// a finished recording). +pub const TRI_REC_EXIT_OK: i32 = 0; +pub const TRI_REC_EXIT_FAIL: i32 = 1; + +// The Config defaults (original lines 17-23). +pub const TRI_REC_DEFAULT_COLS: u16 = 120; +pub const TRI_REC_DEFAULT_ROWS: u16 = 40; +pub const TRI_REC_DEFAULT_IDLE_MAX: u16 = 3; +pub const TRI_REC_DEFAULT_OUTPUT_DIR = "recordings"; + +// The GIF conversion speed of the agg stage (line 131). +pub const TRI_REC_AGG_FPS: u32 = 30; + +// Lines 29-46: the command needs a tri-command argument - with only the +// program name the usage block prints and the run exits 1. +pub fn tri_record_needs_usage(arg_count: usize) -> bool { + return arg_count < 2; +} + +// Lines 52-59: an environment override takes effect only when it parses; +// a present-but-invalid value keeps the default (the catch in the +// original). An absent variable also keeps the default. +pub fn tri_record_config_or_default(env_present: bool, parsed_ok: bool, parsed_value: u16, default_value: u16) -> u16 { + if (!env_present) { + return default_value; + } + if (!parsed_ok) { + return default_value; + } + return parsed_value; +} + +// Lines 61-63: TRI_REC_OVERWRITE turns the overwrite on whenever the +// variable is present - any value, no parsing. +pub fn tri_record_overwrite_flag(env_present: bool) -> bool { + if (env_present) { + return true; + } + return false; +} + +// Lines 72-75: the GIF is named after the command's first word - the +// basename is the command up to its first space, or the whole command +// when it has none. The length of that basename is the portable fact. +pub fn tri_record_basename_len(command: []const u8) -> usize { + var n: usize = 0; + for c in command { + if (c == ' ') { + return n; + } + n += 1; + } + return command.len; +} + +// Lines 89-95: without overwrite an already-existing GIF stops the run +// before any recording starts; with overwrite the run proceeds. +pub fn tri_record_existing_file_blocks(overwrite: bool, gif_exists: bool) -> bool { + if (overwrite) { + return false; + } + return gif_exists; +} + +// Lines 149-152: the final report shows the file size in KB - the byte +// count divided by 1024, truncated. +pub fn tri_record_kb(size_bytes: u64) -> u64 { + return size_bytes / 1024; +} + +// Line 25: the command's exit cascade. Usage exits 1; an existing GIF +// without overwrite exits 1; an asciinema failure exits 1; an agg +// failure exits 1; only a recording that ran and converted exits 0. +pub fn main(arg_count: usize, overwrite: bool, gif_exists: bool, asciinema_ok: bool, agg_ok: bool) -> i32 { + if (tri_record_needs_usage(arg_count)) { + return TRI_REC_EXIT_FAIL; + } + if (tri_record_existing_file_blocks(overwrite, gif_exists)) { + return TRI_REC_EXIT_FAIL; + } + if (!asciinema_ok) { + return TRI_REC_EXIT_FAIL; + } + if (!agg_ok) { + return TRI_REC_EXIT_FAIL; + } + return TRI_REC_EXIT_OK; +} + +test usage_gate_needs_a_command { + assert(tri_record_needs_usage(0) == true); + assert(tri_record_needs_usage(1) == true); + assert(tri_record_needs_usage(2) == false); + assert(tri_record_needs_usage(3) == false); + assert(main(1, false, false, true, true) == TRI_REC_EXIT_FAIL); +} + +test env_override_keeps_default_when_absent_or_invalid { + assert(tri_record_config_or_default(false, true, 200, 120) == 120); + assert(tri_record_config_or_default(true, true, 200, 120) == 200); + assert(tri_record_config_or_default(true, false, 999, 120) == 120); + assert(tri_record_config_or_default(true, true, 80, 120) == 80); + assert(tri_record_config_or_default(false, false, 999, 40) == 40); + assert(tri_record_config_or_default(true, true, 5, 3) == 5); +} + +test overwrite_flag_is_presence_only { + assert(tri_record_overwrite_flag(true) == true); + assert(tri_record_overwrite_flag(false) == false); +} + +test basename_cuts_at_first_space { + assert(tri_record_basename_len("benchmark") == 9); + assert(tri_record_basename_len("math demo") == 4); + assert(tri_record_basename_len("test --fast extra") == 4); + assert(tri_record_basename_len("") == 0); + assert(tri_record_basename_len(" x") == 0); + assert(tri_record_basename_len("a b c") == 1); +} + +test existing_gif_blocks_without_overwrite { + assert(tri_record_existing_file_blocks(false, true) == true); + assert(tri_record_existing_file_blocks(true, true) == false); + assert(tri_record_existing_file_blocks(false, false) == false); + assert(tri_record_existing_file_blocks(true, false) == false); +} + +test kb_size_truncates { + assert(tri_record_kb(0) == 0); + assert(tri_record_kb(1023) == 0); + assert(tri_record_kb(1024) == 1); + assert(tri_record_kb(2048) == 2); + assert(tri_record_kb(1048576) == 1024); +} + +test exit_cascade_of_the_stages { + assert(main(2, false, false, true, true) == TRI_REC_EXIT_OK); + assert(main(2, false, true, true, true) == TRI_REC_EXIT_FAIL); + assert(main(2, true, true, true, true) == TRI_REC_EXIT_OK); + assert(main(2, false, false, false, true) == TRI_REC_EXIT_FAIL); + assert(main(2, false, false, true, false) == TRI_REC_EXIT_FAIL); +} From 3e1d26af7fec9506adebb0d1416fee4158cde2d6 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 17:43:58 -0300 Subject: [PATCH 09/17] spec(port): port specs/port/trinity/src/vibeec/create_test_mistral.t27 (Closes #9644) Port gHashTag/trinity:src/vibeec/create_test_mistral.zig (at ee512359254b, 129 lines) as specs/port/trinity/src/vibeec/ create_test_mistral.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The safetensors builder's decisions are ported as pure functions and tested (9 tests, 9 pass, 0 vacuous, 42 runtime asserts, 100% function coverage): the mini Mistral config (vocab 256, hidden 64, intermediate 128, 2 layers, 4 heads, 2 kv heads - head_dim = hidden/heads), the f32 tensor byte rule (4 bytes per element times the 2-D shape product), the per-layer shape table (q/o [hidden, hidden], k/v [kv_dim, hidden], gate/up [intermediate, hidden], down [hidden, intermediate] - slot codes 0..6), the tensor count (the embedding plus seven per layer plus the lm head = 2 + 7*layers), the whole payload's byte count (the embedding and lm head share the [vocab, hidden] shape), the parameter count (bytes / 4), the file size (8-byte prefix + header + payload), the JSON header's comma rule (every entry except the first), and the seeded data range (random float in [0,1) scaled to [-1, 1)). The header string building, the file write and the PRNG itself are the callers' plumbing. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 11/11, test-report 9/9 pass, 0 BLOCKED, gen 137 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 11 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../src/vibeec/create_test_mistral.t27 | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 specs/port/trinity/src/vibeec/create_test_mistral.t27 diff --git a/specs/port/trinity/src/vibeec/create_test_mistral.t27 b/specs/port/trinity/src/vibeec/create_test_mistral.t27 new file mode 100644 index 0000000000..57d6de6d33 --- /dev/null +++ b/specs/port/trinity/src/vibeec/create_test_mistral.t27 @@ -0,0 +1,179 @@ +module port::trinity::create_test_mistral; + +// Port of gHashTag/trinity:src/vibeec/create_test_mistral.zig (at +// ee512359254b, 129 lines) - t27 issue #9644, Roadmap Stage 5 (goal +// #4547), target t27c gen-rust. The safetensors builder's decisions as +// pure functions: the mini Mistral config, the per-layer tensor shape +// table, the f32 tensor byte rule, the comma rule of the JSON header, +// the payload totals and the sample range of the random data. The +// header string building, the file write and the PRNG itself are the +// caller's plumbing. + +// The mini Mistral config (original lines 12-21). +pub const MISTRAL_TEST_VOCAB: usize = 256; +pub const MISTRAL_TEST_HIDDEN: usize = 64; +pub const MISTRAL_TEST_INTERMEDIATE: usize = 128; +pub const MISTRAL_TEST_LAYERS: usize = 2; +pub const MISTRAL_TEST_HEADS: usize = 4; +pub const MISTRAL_TEST_KV_HEADS: usize = 2; + +// Line 46: every tensor is f32 - 4 bytes per element. +pub const MISTRAL_TEST_F32_BYTES: usize = 4; + +// Line 110: the test data is seeded, not random-random. +pub const MISTRAL_TEST_PRNG_SEED: u32 = 42; + +// Line 21: head_dim = hidden_size / num_heads. +pub fn mistral_test_head_dim(hidden_size: usize, num_heads: usize) -> usize { + return hidden_size / num_heads; +} + +// Lines 46-49: a 2-D tensor's byte size - 4 bytes per element times the +// product of its two dimensions. +pub fn mistral_test_tensor_bytes_2(dim0: usize, dim1: usize) -> usize { + return MISTRAL_TEST_F32_BYTES * dim0 * dim1; +} + +// Lines 62-89: the shape table. Per layer the tensors are +// q [hidden, hidden], k [kv_heads*head_dim, hidden], +// v [kv_heads*head_dim, hidden], o [hidden, hidden], +// gate [intermediate, hidden], up [intermediate, hidden], +// down [hidden, intermediate] - slot codes 0 to 6 in that order. +pub fn mistral_test_layer_rows(slot: u8, hidden: usize, intermediate: usize, kv_dim: usize) -> usize { + if (slot == 1 or slot == 2) { + return kv_dim; + } + if (slot == 4 or slot == 5) { + return intermediate; + } + return hidden; +} + +pub fn mistral_test_layer_cols(slot: u8, hidden: usize, intermediate: usize) -> usize { + if (slot == 6) { + return intermediate; + } + return hidden; +} + +// Lines 61-93: the file holds the embedding, seven tensors per layer, +// and the lm head - 2 + 7*num_layers tensors in total. +pub fn mistral_test_tensors_total(num_layers: usize) -> usize { + return 2 + num_layers * 7; +} + +// The whole payload's byte count: the embedding and the lm head share +// the [vocab, hidden] shape; every layer contributes q, k, v, o, gate, +// up and down. +pub fn mistral_test_param_bytes(vocab: usize, hidden: usize, intermediate: usize, num_layers: usize, kv_dim: usize) -> usize { + const embed_side: usize = MISTRAL_TEST_F32_BYTES * vocab * hidden; + const square_attn: usize = MISTRAL_TEST_F32_BYTES * hidden * hidden; + const kv_attn: usize = MISTRAL_TEST_F32_BYTES * kv_dim * hidden; + const mlp_wide: usize = MISTRAL_TEST_F32_BYTES * intermediate * hidden; + const mlp_down: usize = MISTRAL_TEST_F32_BYTES * hidden * intermediate; + const per_layer: usize = square_attn + kv_attn + kv_attn + square_attn + mlp_wide + mlp_wide + mlp_down; + return embed_side * 2 + per_layer * num_layers; +} + +// Line 125: the parameter count the builder reports - one f32 per +// 4 bytes of payload. +pub fn mistral_test_total_params(offset_bytes: usize) -> usize { + return offset_bytes / MISTRAL_TEST_F32_BYTES; +} + +// Line 128: the file size - the 8-byte header-size prefix, the JSON +// header, and the tensor payload. +pub fn mistral_test_file_size(header_len: usize, offset_bytes: usize) -> usize { + return 8 + header_len + offset_bytes; +} + +// Lines 41-44: the JSON header separates entries with a comma - every +// entry except the first one. +pub fn mistral_test_entry_needs_comma(is_first: bool) -> bool { + if (is_first) { + return false; + } + return true; +} + +// Line 118: the data is filled with samples scaled from the PRNG's +// [0,1) float into [-1, 1). +pub fn mistral_test_scale_sample(u: f32) -> f32 { + return u * 2.0 - 1.0; +} + +// Line 7: main builds the mini model and reports its parameter count - +// the payload the writer emits, halved twice into f32 elements. +pub fn main(vocab: usize, hidden: usize, intermediate: usize, num_layers: usize, kv_dim: usize) -> usize { + const offset = mistral_test_param_bytes(vocab, hidden, intermediate, num_layers, kv_dim); + return mistral_test_total_params(offset); +} + +test head_dim_is_hidden_over_heads { + assert(mistral_test_head_dim(64, 4) == 16); + assert(mistral_test_head_dim(64, 8) == 8); + assert(mistral_test_head_dim(48, 4) == 12); + assert(mistral_test_head_dim(40, 5) == 8); +} + +test tensor_bytes_rule { + assert(mistral_test_tensor_bytes_2(256, 64) == 65536); + assert(mistral_test_tensor_bytes_2(64, 64) == 16384); + assert(mistral_test_tensor_bytes_2(32, 64) == 8192); + assert(mistral_test_tensor_bytes_2(128, 64) == 32768); + assert(mistral_test_tensor_bytes_2(64, 128) == 32768); + assert(mistral_test_tensor_bytes_2(1, 1) == 4); + assert(mistral_test_tensor_bytes_2(0, 5) == 0); +} + +test layer_shape_table { + assert(mistral_test_layer_rows(0, 64, 128, 32) == 64); + assert(mistral_test_layer_rows(1, 64, 128, 32) == 32); + assert(mistral_test_layer_rows(2, 64, 128, 32) == 32); + assert(mistral_test_layer_rows(3, 64, 128, 32) == 64); + assert(mistral_test_layer_rows(4, 64, 128, 32) == 128); + assert(mistral_test_layer_rows(5, 64, 128, 32) == 128); + assert(mistral_test_layer_rows(6, 64, 128, 32) == 64); + assert(mistral_test_layer_cols(0, 64, 128) == 64); + assert(mistral_test_layer_cols(4, 64, 128) == 64); + assert(mistral_test_layer_cols(6, 64, 128) == 128); +} + +test tensor_count { + assert(mistral_test_tensors_total(2) == 16); + assert(mistral_test_tensors_total(0) == 2); + assert(mistral_test_tensors_total(3) == 23); +} + +test payload_bytes { + assert(mistral_test_param_bytes(256, 64, 128, 2, 32) == 425984); + assert(mistral_test_param_bytes(10, 4, 8, 1, 2) == 896); + assert(mistral_test_param_bytes(256, 64, 128, 0, 32) == 131072); +} + +test param_and_file_totals { + assert(mistral_test_total_params(425984) == 106496); + assert(mistral_test_total_params(896) == 224); + assert(mistral_test_total_params(0) == 0); + assert(mistral_test_total_params(4) == 1); + assert(mistral_test_file_size(100, 425984) == 426092); + assert(mistral_test_file_size(0, 0) == 8); + assert(mistral_test_file_size(1, 0) == 9); +} + +test header_comma_rule { + assert(mistral_test_entry_needs_comma(true) == false); + assert(mistral_test_entry_needs_comma(false) == true); +} + +test sample_range_is_minus_one_to_one { + assert(mistral_test_scale_sample(0.0) == -1.0); + assert(mistral_test_scale_sample(0.5) == 0.0); + assert(mistral_test_scale_sample(0.75) == 0.5); + assert(mistral_test_scale_sample(0.25) == -0.5); +} + +test main_reports_param_count { + assert(main(256, 64, 128, 2, 32) == 106496); + assert(main(10, 4, 8, 1, 2) == 224); +} From 285b6bd894530e049b33c5f2f4f829e83c1676b9 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 18:06:14 -0300 Subject: [PATCH 10/17] spec(port): port specs/port/trinity/src/vibeec/soul_collector.t27 (Closes #9719) Port gHashTag/trinity:src/vibeec/soul_collector.zig (at ee512359254b, 69 lines) as specs/port/trinity/src/vibeec/soul_collector.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The corpus builder's decisions are ported as pure functions and tested (5 tests, 5 pass, 0 vacuous, 33 runtime asserts, 100% function coverage): the suffix scan (endsWith, byte-indexed), the marker scan (contains, sliding window), the sacred filter (a file enters the corpus exactly when it ends with .tri or .zig and mentions none of .git, zig-cache, temp_generated anywhere in its path - including the original's quirk that .gitignore.zig is profane too, since indexOf '.git' matches it), and the 10 MB read cap (a file at most the cap in size is absorbed; a larger one fails the capped read and the walk continues without it - the original's catch-continue). The directory walk, the reads and the corpus writes are the caller's plumbing. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 5/5, test-report 5/5 pass, 0 BLOCKED, gen 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 5 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../trinity/src/vibeec/soul_collector.t27 | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 specs/port/trinity/src/vibeec/soul_collector.t27 diff --git a/specs/port/trinity/src/vibeec/soul_collector.t27 b/specs/port/trinity/src/vibeec/soul_collector.t27 new file mode 100644 index 0000000000..82b79697d7 --- /dev/null +++ b/specs/port/trinity/src/vibeec/soul_collector.t27 @@ -0,0 +1,153 @@ +module port::trinity::soul_collector; + +// Port of gHashTag/trinity:src/vibeec/soul_collector.zig (at ee512359254b, +// 69 lines) - t27 issue #9719, Roadmap Stage 5 (goal #4547), target t27c +// gen-rust. The corpus builder's decisions as pure functions: the sacred +// filter (a file enters the corpus exactly when it ends with .tri or .zig +// and mentions none of the profane markers), and the 10 MB read cap that +// silently skips a file it cannot read. The directory walk, the reads and +// the corpus writes are the caller's plumbing. + +// The sacred extensions (original lines 31-32). +pub const SOUL_COLLECTOR_VIBEE_EXT = ".tri"; +pub const SOUL_COLLECTOR_ZIG_EXT = ".zig"; + +// The profane markers (original lines 35-37). +pub const SOUL_COLLECTOR_GIT_DIR = ".git"; +pub const SOUL_COLLECTOR_ZIG_CACHE = "zig-cache"; +pub const SOUL_COLLECTOR_TEMP_DIR = "temp_generated"; + +// Line 47: a file larger than 10 MB fails the capped read and the walk +// continues without it. +pub const SOUL_COLLECTOR_READ_CAP: usize = 10 * 1024 * 1024; + +// The per-file outcomes of the walk. +pub const SOUL_COLLECTOR_SKIPPED: i32 = 0; +pub const SOUL_COLLECTOR_ABSORBED: i32 = 1; + +// Lines 31-32 and 35-37 rest on ends-with and contains scans; the suffix +// check compares the path's last suffix.len bytes, and the containment +// check slides a window across the path. +pub fn soul_collector_ends_with(path: []const u8, suffix: []const u8) -> bool { + if (path.len < suffix.len) { + return false; + } + var i: usize = 0; + while (i < suffix.len) { + if (path[path.len - suffix.len + i] != suffix[i]) { + return false; + } + i += 1; + } + return true; +} + +pub fn soul_collector_contains(path: []const u8, marker: []const u8) -> bool { + if (marker.len == 0) { + return true; + } + if (path.len < marker.len) { + return false; + } + var start: usize = 0; + while (start + marker.len <= path.len) { + var k: usize = 0; + var all_match = true; + while (k < marker.len) { + if (path[start + k] != marker[k]) { + all_match = false; + } + k += 1; + } + if (all_match) { + return true; + } + start += 1; + } + return false; +} + +// Lines 39: the sacred filter - .tri or .zig, and none of .git, +// zig-cache, temp_generated anywhere in the path. +pub fn soul_collector_file_is_sacred(path: []const u8) -> bool { + const is_vibee = soul_collector_ends_with(path, SOUL_COLLECTOR_VIBEE_EXT); + const is_zig = soul_collector_ends_with(path, SOUL_COLLECTOR_ZIG_EXT); + if (!(is_vibee or is_zig)) { + return false; + } + if (soul_collector_contains(path, SOUL_COLLECTOR_GIT_DIR)) { + return false; + } + if (soul_collector_contains(path, SOUL_COLLECTOR_ZIG_CACHE)) { + return false; + } + if (soul_collector_contains(path, SOUL_COLLECTOR_TEMP_DIR)) { + return false; + } + return true; +} + +// Line 47: only a file at most the cap in size can be absorbed. +pub fn soul_collector_file_absorbable(size_bytes: usize) -> bool { + return size_bytes <= SOUL_COLLECTOR_READ_CAP; +} + +// Line 3: the walk's decision per file - a path passes the sacred filter +// and fits the cap exactly when it lands in the corpus. +pub fn main(path: []const u8, size_bytes: usize) -> i32 { + if (!soul_collector_file_is_sacred(path)) { + return SOUL_COLLECTOR_SKIPPED; + } + if (!soul_collector_file_absorbable(size_bytes)) { + return SOUL_COLLECTOR_SKIPPED; + } + return SOUL_COLLECTOR_ABSORBED; +} + +test ends_with_suffix_scan { + assert(soul_collector_ends_with("src/main.zig", ".zig") == true); + assert(soul_collector_ends_with("ritual.tri", ".tri") == true); + assert(soul_collector_ends_with("a.zig.txt", ".zig") == false); + assert(soul_collector_ends_with("zig", ".zig") == false); + assert(soul_collector_ends_with("", ".zig") == false); + assert(soul_collector_ends_with(".zig", ".zig") == true); + assert(soul_collector_ends_with("any", "") == true); +} + +test contains_marker_scan { + assert(soul_collector_contains("src/.git/config", ".git") == true); + assert(soul_collector_contains(".gitignore", ".git") == true); + assert(soul_collector_contains("src/main.zig", ".git") == false); + assert(soul_collector_contains("build/zig-cache/a.zig", "zig-cache") == true); + assert(soul_collector_contains("gen/temp_generated/b.tri", "temp_generated") == true); + assert(soul_collector_contains("abc", "abcd") == false); + assert(soul_collector_contains("hello", "ll") == true); + assert(soul_collector_contains("", "") == true); +} + +test sacred_filter { + assert(soul_collector_file_is_sacred("src/main.zig") == true); + assert(soul_collector_file_is_sacred("ritual.tri") == true); + assert(soul_collector_file_is_sacred("notes.txt") == false); + assert(soul_collector_file_is_sacred("src/.git/x.zig") == false); + assert(soul_collector_file_is_sacred("build/zig-cache/a.zig") == false); + assert(soul_collector_file_is_sacred("gen/temp_generated/b.tri") == false); + assert(soul_collector_file_is_sacred(".gitignore.zig") == false); + assert(soul_collector_file_is_sacred("") == false); +} + +test read_cap_boundary { + assert(soul_collector_file_absorbable(0) == true); + assert(soul_collector_file_absorbable(10485760) == true); + assert(soul_collector_file_absorbable(10485761) == false); + assert(soul_collector_file_absorbable(999999999) == false); +} + +test walk_decision_per_file { + assert(main("src/main.zig", 100) == SOUL_COLLECTOR_ABSORBED); + assert(main("ritual.tri", 10485760) == SOUL_COLLECTOR_ABSORBED); + assert(main("notes.txt", 100) == SOUL_COLLECTOR_SKIPPED); + assert(main("src/main.zig", 10485761) == SOUL_COLLECTOR_SKIPPED); + assert(main("a/.git/x.tri", 10) == SOUL_COLLECTOR_SKIPPED); + assert(main("b/zig-cache/y.zig", 10) == SOUL_COLLECTOR_SKIPPED); +} From e35a82c349c748a8ce68bdcc6b147870c880fff3 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 18:27:28 -0300 Subject: [PATCH 11/17] spec(port): port specs/port/trinity/src/registry/export_cli.t27 (Closes #9725) Port gHashTag/trinity:src/registry/export_cli.zig (at ee512359254b, 77 lines) as specs/port/trinity/src/registry/export_cli.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The registry export CLI's decisions are ported as pure functions and tested (4 tests, 4 pass, 0 vacuous, 15 runtime asserts, 100% function coverage): the registry destination (the first user argument overrides the default .trinity/registry.json - the bar is args.len > 1), the MCP schemas destination (the SECOND user argument overrides the default .trinity/mcp_schemas.json - one argument is not enough, the bar is args.len > 2), and the stats block the run ends with (the two top counts plus one line per mode, per stability and per namespace - 14 lines for the registry's 3 modes, 3 stabilities and 6 namespaces). The registry export, the schema export and the stats gathering live in mcp_gen and are the caller's plumbing. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 4/4, test-report 4/4 pass, 0 BLOCKED, gen 60 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 4 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../port/trinity/src/registry/export_cli.t27 | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 specs/port/trinity/src/registry/export_cli.t27 diff --git a/specs/port/trinity/src/registry/export_cli.t27 b/specs/port/trinity/src/registry/export_cli.t27 new file mode 100644 index 0000000000..c6c435e1c2 --- /dev/null +++ b/specs/port/trinity/src/registry/export_cli.t27 @@ -0,0 +1,74 @@ +module port::trinity::export_cli; + +// Port of gHashTag/trinity:src/registry/export_cli.zig (at ee512359254b, +// 77 lines) - t27 issue #9725, Roadmap Stage 5 (goal #4547), target t27c +// gen-rust. The registry export CLI's decisions as pure functions: the two +// positional output paths with their defaults, and the shape of the stats +// report the run ends with. The registry export, the MCP schema export and +// the stats gathering itself live in mcp_gen and are the caller's plumbing. + +// Line 20: the default registry destination. +pub const EXPORT_CLI_DEFAULT_REGISTRY_PATH = ".trinity/registry.json"; + +// Line 29: the default MCP schemas destination. +pub const EXPORT_CLI_DEFAULT_SCHEMAS_PATH = ".trinity/mcp_schemas.json"; + +// Lines 17-20: the first user argument (argv beyond the program name) +// overrides the registry destination; without it the default stands. +pub fn export_cli_registry_path(arg_count: usize, arg: []const u8) -> []const u8 { + if (arg_count > 1) { + return arg; + } + return EXPORT_CLI_DEFAULT_REGISTRY_PATH; +} + +// Lines 26-29: the SECOND user argument overrides the schemas destination - +// one argument is not enough, the bar is args.len > 2. +pub fn export_cli_schemas_path(arg_count: usize, arg: []const u8) -> []const u8 { + if (arg_count > 2) { + return arg; + } + return EXPORT_CLI_DEFAULT_SCHEMAS_PATH; +} + +// Lines 36-76: the stats block the run ends with - the two top counts +// (total commands, MCP-enabled) plus one line per mode, per stability and +// per namespace. +pub fn export_cli_report_line_count(mode_count: usize, stability_count: usize, namespace_count: usize) -> usize { + return 2 + mode_count + stability_count + namespace_count; +} + +// Line 8: the run - both exports happen, then the stats print. The number +// the printed block carries is its line count for the registry's shape: +// 3 modes (sync, job, stream), 3 stabilities (stable, experimental, +// dangerous), 6 namespaces (core, dev, forge, agent, mcp, system). +pub fn main(mode_count: usize, stability_count: usize, namespace_count: usize) -> usize { + return export_cli_report_line_count(mode_count, stability_count, namespace_count); +} + +test registry_path_default_and_override { + assert(export_cli_registry_path(0, "custom.json") == ".trinity/registry.json"); + assert(export_cli_registry_path(1, "custom.json") == ".trinity/registry.json"); + assert(export_cli_registry_path(2, "custom.json") == "custom.json"); + assert(export_cli_registry_path(3, "deep/custom.json") == "deep/custom.json"); +} + +test schemas_path_needs_the_second_argument { + assert(export_cli_schemas_path(1, "s.json") == ".trinity/mcp_schemas.json"); + assert(export_cli_schemas_path(2, "s.json") == ".trinity/mcp_schemas.json"); + assert(export_cli_schemas_path(3, "s.json") == "s.json"); + assert(export_cli_schemas_path(4, "x/s.json") == "x/s.json"); +} + +test stats_block_shape { + assert(export_cli_report_line_count(3, 3, 6) == 14); + assert(export_cli_report_line_count(0, 0, 0) == 2); + assert(export_cli_report_line_count(1, 1, 1) == 5); + assert(export_cli_report_line_count(3, 2, 6) == 13); +} + +test main_prints_the_registry_shape { + assert(main(3, 3, 6) == 14); + assert(main(0, 0, 0) == 2); + assert(main(1, 0, 0) == 3); +} From 882e5f8994de7929dd04a9604a063d37b1792f0d Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 18:51:40 -0300 Subject: [PATCH 12/17] spec(port): port specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 (Closes #9781) Port gHashTag/trinity:src/phi-engine/quantum/qutritizer.zig (at ee512359254b) as specs/port/trinity/src/phi-engine/quantum/ qutritizer.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The trit-to-qutrit converter's decisions are ported as pure functions and tested (9 tests, 9 pass, 0 vacuous, 49 runtime asserts, 100% function coverage): the uniform 1/sqrt(3) superposition the state starts from (Newton's method replaces the math library sqrt, 40 rounds), the sign-bucket threshold (strictly positive is plus, strictly negative is minus, zero is zero), the strict-majority bias (only a trit class strictly more frequent than BOTH others takes the 0.1 boost - a tie boosts nothing), and the norm that brings the three amplitudes back to unit length; an empty input returns the raw uniform superposition. The QutritState record is carried as a struct with the three amplitudes. The amplitude windows in the tests were measured on the generated code (boosted 0.638479, unboosted 0.544217 for the uniform 0.5773503 + 0.1 bias shape). All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 5/5, test-report 9/9 pass, 0 BLOCKED, gen 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 5 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../src/phi-engine/quantum/qutritizer.t27 | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 diff --git a/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 b/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 new file mode 100644 index 0000000000..3613db4a77 --- /dev/null +++ b/specs/port/trinity/src/phi-engine/quantum/qutritizer.t27 @@ -0,0 +1,208 @@ +module port::trinity::qutritizer; + +// Port of gHashTag/trinity:src/phi-engine/quantum/qutritizer.zig (at +// ee512359254b, ~110 lines) - t27 issue #9781, Roadmap Stage 5 (goal +// #4547), target t27c gen-rust. The trit-to-qutrit converter's decisions +// as pure functions: the uniform 1/sqrt(3) superposition the state starts +// from, the sign-bucket threshold, the strict-majority bias (only a trit +// class strictly more frequent than BOTH others gets the 0.1 boost - a tie +// boosts nothing), and the norm that brings the amplitudes back to unit +// length. Newton's method replaces the math library sqrt, as in the +// earlier sqrt ports of this series. + +// The boost targets of the frequency argmax; NONE covers every tie. +pub const QUTRITIZER_BOOST_MINUS: i32 = 0; +pub const QUTRITIZER_BOOST_ZERO: i32 = 1; +pub const QUTRITIZER_BOOST_PLUS: i32 = 2; +pub const QUTRITIZER_BOOST_NONE: i32 = 3; + +// The MVP bias of the original (line 62). +pub const QUTRITIZER_BIAS: f64 = 0.1; + +// QutritState (original lines 20-27): the three amplitudes of +// psi = alpha|-1> + beta|0> + gamma|+1>. +pub struct QutritState { + alpha: f64, + beta: f64, + gamma: f64, +} + +// Newton's method for sqrt, 40 rounds - the series' portable square root. +pub fn qutritizer_sqrt(x: f64) -> f64 { + if (x <= 0.0) { + return 0.0; + } + var g: f64 = x; + var i: usize = 0; + while (i < 40) { + g = (g + x / g) / 2.0; + i += 1; + } + return g; +} + +// Line 36: the uniform superposition amplitude 1/sqrt(3). +pub fn qutritizer_uniform_amplitude() -> f64 { + const s = qutritizer_sqrt(3.0); + return 1.0 / s; +} + +// Lines 46-54: the MVP threshold - strictly positive trits are plus, +// strictly negative are minus, zero is zero. +pub fn qutritizer_trit_bucket(t: i8) -> i32 { + if (t > 0) { + return 1; + } + if (t < 0) { + return -1; + } + return 0; +} + +// Lines 66-72: only the strictly most frequent class is boosted - ties +// and second places boost nothing. +pub fn qutritizer_strict_argmax(count_minus: i64, count_zero: i64, count_plus: i64) -> i32 { + if (count_minus > count_zero and count_minus > count_plus) { + return QUTRITIZER_BOOST_MINUS; + } + if (count_zero > count_minus and count_zero > count_plus) { + return QUTRITIZER_BOOST_ZERO; + } + if (count_plus > count_minus and count_plus > count_zero) { + return QUTRITIZER_BOOST_PLUS; + } + return QUTRITIZER_BOOST_NONE; +} + +// Line 33: the conversion. The state starts uniform; with at least one +// trit the strictly most frequent class takes the 0.1 bias and the three +// amplitudes are renormalized to unit length; an empty input returns the +// raw uniform superposition. +pub fn tritsToQutrit(trits: []const i8) -> QutritState { + var count_minus: i64 = 0; + var count_zero: i64 = 0; + var count_plus: i64 = 0; + for t in trits { + const bucket = qutritizer_trit_bucket(t); + if (bucket == 1) { + count_plus += 1; + } + if (bucket == -1) { + count_minus += 1; + } + if (bucket == 0) { + count_zero += 1; + } + } + const total: i64 = count_minus + count_zero + count_plus; + const uniform = qutritizer_uniform_amplitude(); + var alpha: f64 = uniform; + var beta: f64 = uniform; + var gamma: f64 = uniform; + if (total > 0) { + const target = qutritizer_strict_argmax(count_minus, count_zero, count_plus); + if (target == QUTRITIZER_BOOST_MINUS) { + alpha = alpha + QUTRITIZER_BIAS; + } + if (target == QUTRITIZER_BOOST_ZERO) { + beta = beta + QUTRITIZER_BIAS; + } + if (target == QUTRITIZER_BOOST_PLUS) { + gamma = gamma + QUTRITIZER_BIAS; + } + const norm = qutritizer_sqrt(alpha * alpha + beta * beta + gamma * gamma); + if (norm > 0.0) { + alpha = alpha / norm; + beta = beta / norm; + gamma = gamma / norm; + } + } + return QutritState { alpha: alpha, beta: beta, gamma: gamma }; +} + +test sqrt_newton_converges { + assert(qutritizer_sqrt(0.0) == 0.0); + assert(qutritizer_sqrt(4.0) > 1.9999); + assert(qutritizer_sqrt(4.0) < 2.0001); + assert(qutritizer_sqrt(9.0) > 2.9998); + assert(qutritizer_sqrt(9.0) < 3.0002); + assert(qutritizer_sqrt(3.0) > 1.7320); + assert(qutritizer_sqrt(3.0) < 1.7321); +} + +test uniform_amplitude_is_inverse_sqrt3 { + const u = qutritizer_uniform_amplitude(); + assert(u > 0.5772); + assert(u < 0.5775); +} + +test bucket_threshold { + assert(qutritizer_trit_bucket(1) == 1); + assert(qutritizer_trit_bucket(13) == 1); + assert(qutritizer_trit_bucket(0) == 0); + assert(qutritizer_trit_bucket(-1) == -1); + assert(qutritizer_trit_bucket(-13) == -1); +} + +test strict_majority_only { + assert(qutritizer_strict_argmax(4, 2, 1) == QUTRITIZER_BOOST_MINUS); + assert(qutritizer_strict_argmax(0, 3, 1) == QUTRITIZER_BOOST_ZERO); + assert(qutritizer_strict_argmax(1, 2, 4) == QUTRITIZER_BOOST_PLUS); + assert(qutritizer_strict_argmax(0, 0, 5) == QUTRITIZER_BOOST_PLUS); + assert(qutritizer_strict_argmax(2, 2, 1) == QUTRITIZER_BOOST_NONE); + assert(qutritizer_strict_argmax(3, 1, 3) == QUTRITIZER_BOOST_NONE); + assert(qutritizer_strict_argmax(1, 1, 1) == QUTRITIZER_BOOST_NONE); +} + +test empty_input_is_raw_uniform { + var none: [0]i8 = []; + const q = tritsToQutrit(&none); + assert(q.alpha > 0.5772); + assert(q.alpha < 0.5775); + assert(q.beta > 0.5772); + assert(q.gamma > 0.5772); +} + +test balanced_input_stays_uniform { + var mixed: [3]i8 = [-1, 0, 1]; + const q = tritsToQutrit(&mixed); + assert(q.alpha > 0.5772); + assert(q.alpha < 0.5775); + assert(q.beta > 0.5772); + assert(q.beta < 0.5775); + assert(q.gamma > 0.5772); + assert(q.gamma < 0.5775); +} + +test zero_majority_boosts_beta { + var zeros: [3]i8 = [0, 0, 0]; + const q = tritsToQutrit(&zeros); + assert(q.beta > 0.637); + assert(q.beta < 0.639); + assert(q.alpha > 0.5441); + assert(q.alpha < 0.5443); + assert(q.gamma > 0.5441); + assert(q.gamma < 0.5443); +} + +test plus_majority_boosts_gamma { + var plus: [3]i8 = [1, 1, 0]; + const q = tritsToQutrit(&plus); + assert(q.gamma > 0.637); + assert(q.gamma < 0.639); + assert(q.beta > 0.5441); + assert(q.beta < 0.5443); + assert(q.alpha > 0.5441); + assert(q.alpha < 0.5443); +} + +test minus_majority_boosts_alpha { + var minus: [3]i8 = [-5, -6, 7]; + const q = tritsToQutrit(&minus); + assert(q.alpha > 0.637); + assert(q.alpha < 0.639); + assert(q.beta > 0.5441); + assert(q.beta < 0.5443); + assert(q.gamma > 0.5441); + assert(q.gamma < 0.5443); +} From ca0d71272424262cda696d42d911177a9be6dd79 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 19:15:28 -0300 Subject: [PATCH 13/17] spec(port): port specs/port/trios-railway/bin/seed-agent/src/main.t27 (Closes #9800) Port gHashTag/trios-railway:bin/seed-agent/src/main.rs (at 5cc46e798dda, main from line 89) as specs/port/trios-railway/bin/seed-agent/src/ main.t27 - Roadmap Stage 6, goal #4548, target t27c gen-rust. The ADR-0081 pull-based trainer worker's boot decisions are ported as pure functions and tested (6 tests, 6 pass, 0 vacuous, 25 runtime asserts, 100% function coverage): the L-NEON-RENAME URL chain (a present, non-empty --neon-url flag bound to RAILWAY_POSTGRES_URL wins; an absent or empty one falls back to the legacy NEON_DATABASE_URL; neither is the boot error), the connect-retry patience (up to 30 attempts, 2s apart - the attempt that reaches the cap is the bail), the pull loop's wait shape (a trained or pruned experiment pulls the next at once, an idle queue waits the 30s poll interval, an iteration error backs off 30s), the shutdown release (the signal ends the loop cleanly), and the early-stop rule the CLI carries (at step 1000 a BPB strictly exceeding the 2.60 ceiling prunes - the ceiling itself does not prune). The CLI defaults (acc1, local-perplexity, seed-agent-auto, poll 30s, step 1000, ceiling 2.60, trainer external) are carried as consts. The TLS setup, the Postgres connection, the UUID, the worker registration and the iteration runs are the caller's plumbing. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 6/6, test-report 6/6 pass, 0 BLOCKED, gen 110 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 6 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../trios-railway/bin/seed-agent/src/main.t27 | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 specs/port/trios-railway/bin/seed-agent/src/main.t27 diff --git a/specs/port/trios-railway/bin/seed-agent/src/main.t27 b/specs/port/trios-railway/bin/seed-agent/src/main.t27 new file mode 100644 index 0000000000..bb8c5b545d --- /dev/null +++ b/specs/port/trios-railway/bin/seed-agent/src/main.t27 @@ -0,0 +1,146 @@ +module port::trios_railway::seed_agent_main; + +// Port of gHashTag/trios-railway:bin/seed-agent/src/main.rs (at +// 5cc46e798dda, main from line 89) - t27 issue #9800, Roadmap Stage 6 +// (goal #4548), target t27c gen-rust. The ADR-0081 pull-based trainer +// worker's boot decisions as pure functions: the L-NEON-RENAME URL +// chain, the connect-retry patience (30 attempts, 2s apart), the pull +// loop's wait shape (trained and pruned pull next at once, idle waits +// the poll interval, an error backs off), the shutdown release, and the +// early-stop rule the CLI carries. The TLS setup, the Postgres +// connection, the UUID, the worker registration and the iteration runs +// are the caller's plumbing. + +// CLI defaults (original lines 43-84). +pub const SEED_AGENT_DEFAULT_ACC = "acc1"; +pub const SEED_AGENT_DEFAULT_SVC_ID = "local-perplexity"; +pub const SEED_AGENT_DEFAULT_SVC_NAME = "seed-agent-auto"; +pub const SEED_AGENT_POLL_IDLE_SECS: u64 = 30; +pub const SEED_AGENT_EARLY_STOP_STEP: i32 = 1000; +pub const SEED_AGENT_EARLY_STOP_BPB_CEILING: f64 = 2.60; +pub const SEED_AGENT_TRAINER_KIND = "external"; + +// Lines 152-166: the connect retry - up to 30 attempts, 2s apart; +// attempt 30 is the bail. +pub const SEED_AGENT_MAX_CONNECT_ATTEMPTS: u32 = 30; +pub const SEED_AGENT_CONNECT_RETRY_SLEEP_SECS: u64 = 2; + +// Line 206: an iteration error backs off before the next pull. +pub const SEED_AGENT_ERROR_BACKOFF_SECS: u64 = 30; + +// Exit codes (R5 - honest exits: the missing URL is the one boot +// failure that surfaces). +pub const SEED_AGENT_EXIT_OK: i32 = 0; +pub const SEED_AGENT_EXIT_FAIL: i32 = 1; + +// The iteration outcomes of the pull loop (lines 193-207). +pub const SEED_AGENT_OUTCOME_TRAINED: i32 = 0; +pub const SEED_AGENT_OUTCOME_PRUNED: i32 = 1; +pub const SEED_AGENT_OUTCOME_IDLE: i32 = 2; +pub const SEED_AGENT_OUTCOME_ERROR: i32 = 3; + +// Lines 110-115, the L-NEON-RENAME chain: a present, non-empty --neon-url +// flag (clap-bound to RAILWAY_POSTGRES_URL) wins; an absent or empty one +// falls back to the legacy NEON_DATABASE_URL; neither is the boot error. +pub fn seed_agent_url_source(neon_flag_present: bool, neon_flag: []const u8, legacy_env_present: bool) -> i32 { + if (neon_flag_present and neon_flag.len > 0) { + return 1; + } + if (legacy_env_present) { + return 2; + } + return 0; +} + +// Lines 151-169: the connect loop stays patient while attempts remain - +// the attempt that reaches the cap is the bail. +pub fn seed_agent_retry_still_patient(attempt: u32) -> bool { + return attempt < SEED_AGENT_MAX_CONNECT_ATTEMPTS; +} + +// Lines 193-207: the loop's wait - a finished experiment (trained or +// pruned) pulls the next at once, an idle queue waits the poll interval, +// an iteration error backs off. +pub fn seed_agent_iteration_wait_secs(outcome: i32) -> u64 { + if (outcome == SEED_AGENT_OUTCOME_IDLE) { + return SEED_AGENT_POLL_IDLE_SECS; + } + if (outcome == SEED_AGENT_OUTCOME_ERROR) { + return SEED_AGENT_ERROR_BACKOFF_SECS; + } + return 0; +} + +// Lines 188-192: the shutdown signal ends the loop - the claimed row is +// released and the worker stops; anything else keeps pulling. +pub fn seed_agent_loop_continues(shutdown_seen: bool) -> bool { + if (shutdown_seen) { + return false; + } + return true; +} + +// Lines 66-68, the early-stop rule the CLI carries: at the early-stop +// step, a BPB exceeding the ceiling prunes the experiment - strictly +// exceeding; the ceiling itself does not prune. +pub fn seed_agent_early_stop_prunes(bpb: f64, ceiling: f64) -> bool { + if (bpb > ceiling) { + return true; + } + return false; +} + +// Line 89: the boot gate - the worker resolves its Postgres URL first; +// with none from any source the boot fails before the retry loop or the +// pull loop can start. With a URL the worker registers and pulls until +// the shutdown signal, exiting cleanly. +pub fn main(neon_flag_present: bool, neon_flag: []const u8, legacy_env_present: bool) -> i32 { + const source = seed_agent_url_source(neon_flag_present, neon_flag, legacy_env_present); + if (source == 0) { + return SEED_AGENT_EXIT_FAIL; + } + return SEED_AGENT_EXIT_OK; +} + +test url_chain_l_neon_rename { + assert(seed_agent_url_source(true, "postgres://railway/db", false) == 1); + assert(seed_agent_url_source(true, "postgres://railway/db", true) == 1); + assert(seed_agent_url_source(true, "", true) == 2); + assert(seed_agent_url_source(false, "", true) == 2); + assert(seed_agent_url_source(false, "", false) == 0); + assert(seed_agent_url_source(true, "", false) == 0); +} + +test boot_gate_exits_on_missing_url { + assert(main(true, "postgres://railway/db", false) == SEED_AGENT_EXIT_OK); + assert(main(false, "", true) == SEED_AGENT_EXIT_OK); + assert(main(false, "", false) == SEED_AGENT_EXIT_FAIL); + assert(main(true, "", false) == SEED_AGENT_EXIT_FAIL); +} + +test connect_retry_patience { + assert(seed_agent_retry_still_patient(0) == true); + assert(seed_agent_retry_still_patient(1) == true); + assert(seed_agent_retry_still_patient(29) == true); + assert(seed_agent_retry_still_patient(30) == false); + assert(seed_agent_retry_still_patient(31) == false); +} + +test loop_wait_shape { + assert(seed_agent_iteration_wait_secs(SEED_AGENT_OUTCOME_TRAINED) == 0); + assert(seed_agent_iteration_wait_secs(SEED_AGENT_OUTCOME_PRUNED) == 0); + assert(seed_agent_iteration_wait_secs(SEED_AGENT_OUTCOME_IDLE) == 30); + assert(seed_agent_iteration_wait_secs(SEED_AGENT_OUTCOME_ERROR) == 30); +} + +test shutdown_ends_the_loop { + assert(seed_agent_loop_continues(false) == true); + assert(seed_agent_loop_continues(true) == false); +} + +test early_stop_ceiling_is_strict { + assert(seed_agent_early_stop_prunes(2.61, 2.60) == true); + assert(seed_agent_early_stop_prunes(2.60, 2.60) == false); + assert(seed_agent_early_stop_prunes(2.59, 2.60) == false); + assert(seed_agent_early_stop_prunes(3.0, 2.60) == true); +} From ce83b820cedca374f2cdc90f9a60ed70baab717c Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 19:39:59 -0300 Subject: [PATCH 14/17] spec(port): port specs/port/trinity/src/tri/compat/managed_list.t27 (Closes #9860) Port gHashTag/trinity:src/tri/compat/managed_list.zig (at ee512359254b, ~129 lines) as specs/port/trinity/src/tri/compat/managed_list.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The original is a generic wrapper, ManagedList(comptime T: type), restoring the Zig 0.14 allocator-with-list API over Zig 0.15's pass-the-allocator API. Generics cannot be expressed in this language, so the port instantiates the wrapper's decisions for the concrete element type u32 at a fixed capacity of 16 - the generic itself (original line 17) is the named missing piece, everything it wraps carries: the empty init, append within capacity, len, isEmpty, get, set, clearRetainingCapacity (the count drops, the storage stays), the pop pair (an empty list pops nothing, a non-empty one shrinks by one) and the iterator (has-next at the index, next returning the item and the advanced index). One generator quirk is worked around in place and commented: a copy-then-indexed-write-then-return emits the wrong return variable, and a trailing alias keeps the picker on the mutated copy. The allocator that travels with the list is the caller's plumbing here. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 11/11, test-report 7/7 pass, 0 BLOCKED, gen 158 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: all 11 function names unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- .../trinity/src/tri/compat/managed_list.t27 | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 specs/port/trinity/src/tri/compat/managed_list.t27 diff --git a/specs/port/trinity/src/tri/compat/managed_list.t27 b/specs/port/trinity/src/tri/compat/managed_list.t27 new file mode 100644 index 0000000000..d5ce9298a4 --- /dev/null +++ b/specs/port/trinity/src/tri/compat/managed_list.t27 @@ -0,0 +1,181 @@ +module port::trinity::managed_list; + +// Port of gHashTag/trinity:src/tri/compat/managed_list.zig (at ee512359254b, +// ~129 lines) - t27 issue #9860, Roadmap Stage 5 (goal #4547), target t27c +// gen-rust. The original is a GENERIC wrapper, ManagedList(comptime T: type), +// restoring the Zig 0.14 allocator-with-list API over Zig 0.15's +// pass-the-allocator-everywhere API. Generics cannot be expressed in this +// language, so the port instantiates the wrapper's decisions for the concrete +// element type u32 with a fixed capacity of 16; the generic itself (original +// line 17) is the named missing piece - everything it wraps carries. The +// allocator that travels with the list is the caller's plumbing here. + +// The fixed capacity of the port's instantiation. +pub const MANAGED_LIST_CAPACITY: usize = 16; + +// The wrapper's state: the items and the count. +pub struct TrinityManagedList { + items: [16]u32, + len: usize, +} + +// Lines 25-30: init - an empty list. +pub fn ManagedList() -> TrinityManagedList { + const empty = TrinityManagedList { items: [_]u32{0} ** 16, len: 0 }; + return empty; +} + +// Lines 40-43: append - the allocator is provided automatically (the +// wrapper's whole point); the list grows within its capacity. +pub fn managed_list_append(l: TrinityManagedList, item: u32) -> TrinityManagedList { + var next = l; + if (next.len < MANAGED_LIST_CAPACITY) { + next.items[next.len] = item; + next.len = next.len + 1; + } + return next; +} + +// Lines 50-53: len. +pub fn managed_list_len(l: TrinityManagedList) -> usize { + return l.len; +} + +// Lines 56-58: isEmpty. +pub fn managed_list_is_empty(l: TrinityManagedList) -> bool { + return l.len == 0; +} + +// Lines 85-88: get. +pub fn managed_list_get(l: TrinityManagedList, index: usize) -> u32 { + return l.items[index]; +} + +// Lines 90-93: set. +pub fn managed_list_set(l: TrinityManagedList, index: usize, item: u32) -> TrinityManagedList { + var next = l; + if (index < MANAGED_LIST_CAPACITY) { + next.items[index] = item; + } + // The trailing alias keeps the generator's return-variable picker on + // the mutated copy; without it the emitted code returns the input. + const out = next; + return out; +} + +// Lines 71-73: clearRetainingCapacity - the count drops to zero, the +// storage stays. +pub fn managed_list_clear(l: TrinityManagedList) -> TrinityManagedList { + var next = l; + next.len = 0; + return next; +} + +// Lines 96-103: pop / popOrNull return ?T - an empty list pops nothing. +pub fn managed_list_pop_present(l: TrinityManagedList) -> bool { + return l.len > 0; +} + +pub fn managed_list_pop(l: TrinityManagedList) -> TrinityManagedList { + var next = l; + if (next.len > 0) { + next.len = next.len - 1; + } + return next; +} + +// Lines 113-123: the iterator - next returns null at the end of the list, +// otherwise the item at the index and the index advanced by one. +pub fn managed_list_iter_has_next(l: TrinityManagedList, index: usize) -> bool { + return index < l.len; +} + +pub fn managed_list_iter_next(l: TrinityManagedList, index: usize) -> (u32, usize) { + const item = l.items[index]; + return (item, index + 1); +} + +test init_is_empty { + const l = ManagedList(); + assert(managed_list_len(l) == 0); + assert(managed_list_is_empty(l) == true); + assert(managed_list_pop_present(l) == false); +} + +test append_grows_in_order { + const base = ManagedList(); + const one = managed_list_append(base, 7); + const two = managed_list_append(one, 9); + assert(managed_list_len(two) == 2); + assert(managed_list_get(two, 0) == 7); + assert(managed_list_get(two, 1) == 9); + assert(managed_list_len(one) == 1); + assert(managed_list_len(base) == 0); + assert(managed_list_is_empty(two) == false); +} + +test append_stops_at_capacity { + var l = ManagedList(); + var i: usize = 0; + while (i < 20) { + l = managed_list_append(l, 100); + i += 1; + } + assert(managed_list_len(l) == 16); + assert(managed_list_get(l, 15) == 100); +} + +test set_replaces_in_place { + const base = ManagedList(); + const one = managed_list_append(base, 1); + const two = managed_list_append(one, 2); + const changed = managed_list_set(two, 0, 42); + assert(managed_list_len(changed) == 2); + assert(managed_list_get(changed, 0) == 42); + assert(managed_list_get(changed, 1) == 2); + assert(managed_list_get(two, 0) == 1); +} + +test clear_keeps_the_list_usable { + const base = ManagedList(); + const one = managed_list_append(base, 5); + const two = managed_list_append(one, 6); + const cleared = managed_list_clear(two); + assert(managed_list_len(cleared) == 0); + assert(managed_list_is_empty(cleared) == true); + const again = managed_list_append(cleared, 8); + assert(managed_list_len(again) == 1); + assert(managed_list_get(again, 0) == 8); +} + +test pop_shrinks_one_at_a_time { + const empty = ManagedList(); + const none = managed_list_pop(empty); + assert(managed_list_len(none) == 0); + const base = ManagedList(); + const one = managed_list_append(base, 3); + const two = managed_list_append(one, 4); + assert(managed_list_pop_present(two) == true); + const popped = managed_list_pop(two); + assert(managed_list_len(popped) == 1); + assert(managed_list_pop_present(popped) == true); + const gone = managed_list_pop(popped); + assert(managed_list_len(gone) == 0); + assert(managed_list_pop_present(gone) == false); +} + +test iterator_walks_to_the_end { + const base = ManagedList(); + const one = managed_list_append(base, 10); + const two = managed_list_append(one, 20); + assert(managed_list_iter_has_next(two, 0) == true); + const (first, idx1) = managed_list_iter_next(two, 0); + assert(first == 10); + assert(idx1 == 1); + assert(managed_list_iter_has_next(two, idx1) == true); + const (second, idx2) = managed_list_iter_next(two, idx1); + assert(second == 20); + assert(idx2 == 2); + assert(managed_list_iter_has_next(two, idx2) == false); + assert(managed_list_iter_has_next(ManagedList(), 0) == false); +} From 7b388bb8ce0a0c06cc7e1d411dd6949b897d2914 Mon Sep 17 00:00:00 2001 From: dmitrii-f-t27 Date: Sat, 17 Oct 2026 20:00:57 -0300 Subject: [PATCH 15/17] spec(port): port specs/port/trinity/src/tri/faculty_types.t27 (Closes #10005) Port gHashTag/trinity:src/tri/faculty_types.zig (at ee512359254b, ~170 lines) as specs/port/trinity/src/tri/faculty_types.t27 - Roadmap Stage 5, goal #4547, target t27c gen-rust. The one listed function is ported under the name the issue asks for, FacultySnapshot_activeFaculty (original line 123, activeFaculty method), and tested (3 tests, 3 pass, 0 vacuous, 6 runtime asserts, 100% function coverage): the active faculty is the count of the six seats whose status is up. Two honest notes: the original's FacultySnapshot carries agents: [6]AgentState - an array of structs this language's Verilog lowering does not implement (W469) - so the port's TrinityFacultySnapshot carries the six statuses as a scalar array of status codes (the up/down/stub/tbd enum as codes, the labels and colors are the caller's presentation); and the name FacultySnapshot is already defined by specs/tri/agent/faculty_board.t27, so the port's type is renamed TrinityFacultySnapshot - the function keeps the required name. All four generators (gen, gen-rust, gen-c, gen-verilog) emit this spec before the push. Verified: parse OK, spec-status IMPLEMENTED, typecheck 0 errors, coverage 1/1, test-report 3/3 pass, 0 BLOCKED, gen 56 lines with 0 'not yet implemented', boundary exactly this one file, dupe_scan: the function name is unique, bare scan reports zero error lines. Dmitrii Fedorov ([@dmitrii-f-t27](https://github.com/dmitrii-f-t27)) --- specs/port/trinity/src/tri/faculty_types.t27 | 64 ++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 specs/port/trinity/src/tri/faculty_types.t27 diff --git a/specs/port/trinity/src/tri/faculty_types.t27 b/specs/port/trinity/src/tri/faculty_types.t27 new file mode 100644 index 0000000000..87c06702bf --- /dev/null +++ b/specs/port/trinity/src/tri/faculty_types.t27 @@ -0,0 +1,64 @@ +module port::trinity::faculty_types; + +// Port of gHashTag/trinity:src/tri/faculty_types.zig (at ee512359254b, +// ~170 lines) - t27 issue #10005, Roadmap Stage 5 (goal #4547), target +// t27c gen-rust. The faculty board's shared types file the A2A dashboard +// reads; the one listed function is the snapshot's active-faculty count. +// The original's FacultySnapshot carries agents: [6]AgentState - an array +// of structs this language's Verilog lowering does not implement (W469), +// and the name FacultySnapshot is already defined by +// specs/tri/agent/faculty_board.t27, so the port's snapshot is named +// TrinityFacultySnapshot and carries the six agents' statuses as a +// scalar array of status codes. The enum status set (up, down, stub, +// tbd) arrives as those codes; the labels, colors and emoji of the +// original's enums are the caller's presentation. + +// The status codes of the original's AgentStatus enum. +pub const FACULTY_STATUS_UP: u8 = 0; +pub const FACULTY_STATUS_DOWN: u8 = 1; +pub const FACULTY_STATUS_STUB: u8 = 2; +pub const FACULTY_STATUS_TBD: u8 = 3; + +// The faculty is fixed at six agents (ralph, scholar, mu, oracle, swarm, +// linter - original lines 10-16). +pub const FACULTY_AGENT_COUNT: usize = 6; + +// The snapshot the dashboard reads: one status code per faculty seat. +pub struct TrinityFacultySnapshot { + statuses: [6]u8, +} + +// Line 123, written per the issue as FacultySnapshot_activeFaculty: the +// active faculty is the count of seats whose status is up. +pub fn FacultySnapshot_activeFaculty(s: TrinityFacultySnapshot) -> u8 { + var count: u8 = 0; + var i: usize = 0; + while (i < s.statuses.len) { + if (s.statuses[i] == FACULTY_STATUS_UP) { + count += 1; + } + i += 1; + } + return count; +} + +test all_six_up_counts_six { + const all = TrinityFacultySnapshot { statuses: [0, 0, 0, 0, 0, 0] }; + assert(FacultySnapshot_activeFaculty(all) == 6); +} + +test none_up_counts_zero { + const none = TrinityFacultySnapshot { statuses: [1, 2, 3, 1, 2, 3] }; + assert(FacultySnapshot_activeFaculty(none) == 0); + const down = TrinityFacultySnapshot { statuses: [1, 1, 1, 1, 1, 1] }; + assert(FacultySnapshot_activeFaculty(down) == 0); +} + +test mixed_statuses_count_exactly { + const three = TrinityFacultySnapshot { statuses: [0, 1, 0, 2, 0, 3] }; + assert(FacultySnapshot_activeFaculty(three) == 3); + const one = TrinityFacultySnapshot { statuses: [1, 2, 3, 3, 2, 0] }; + assert(FacultySnapshot_activeFaculty(one) == 1); + const five = TrinityFacultySnapshot { statuses: [0, 0, 3, 0, 0, 0] }; + assert(FacultySnapshot_activeFaculty(five) == 5); +} From e11faf51d0f61c29bdac5ef2df77a52765a8de7c Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Sun, 18 Oct 2026 09:27:26 +0700 Subject: [PATCH 16/17] fix(ci): master green -- rust_convert CSE hoist, mesh crypto mismatch, stale OptimizerStepResult row (Closes #10158) Master 18c98cc77 was red on t27b-native-ratchet (rust_convert: ledger pass, now blocked by FnDecl(reference CSE hoist)) and on Corpus ratchet (tri types classified: STALE OptimizerStepResult after #10088). Every open PR inherited both reds. - rust_convert.t27 / crypto.t27: the .t27 repairs from draft #9637, without its workflow and Python; gen-rust regenerated, both sealed with zig 0.16. - type_conflicts_classified.json + TYPE_CONFLICTS.md: drop the stale row, DRIFT 62 -> 61. Co-Authored-By: Claude Opus 5.5 --- .../src_port::trios_mesh_node_crypto.json | 28 +++++++++++++++++++ .trinity/seals/t27o_T27oRust.json | 14 +++++----- docs/TYPE_CONFLICTS.md | 3 +- docs/reports/type_conflicts_classified.json | 14 +--------- gen/rust/tools/t27o/rust_convert.rs | 7 +++-- .../crates/trios-mesh-node/src/crypto.t27 | 19 +++++++++---- specs/tools/t27o/rust_convert.t27 | 7 +++-- 7 files changed, 60 insertions(+), 32 deletions(-) create mode 100644 .trinity/seals/src_port::trios_mesh_node_crypto.json diff --git a/.trinity/seals/src_port::trios_mesh_node_crypto.json b/.trinity/seals/src_port::trios_mesh_node_crypto.json new file mode 100644 index 0000000000..ea52e0dcd9 --- /dev/null +++ b/.trinity/seals/src_port::trios_mesh_node_crypto.json @@ -0,0 +1,28 @@ +{ + "built_by": "t27c-bootstrap@0.5.2+0d4fe82f2", + "closure": [], + "config": "gen=c,rust,verilog,zig;tests=zig", + "gen_hash_c": "sha256:1e74b996ade22e83796910c9b4e244b1cc04f6253a35505054198be62254e853", + "gen_hash_rust": "sha256:ea7c338992c88064b5375c0b5462bb4868f244384f01a344780f025452123335", + "gen_hash_verilog": "sha256:fc2816200338199bc3a3553bfd5fa97ddc9ec7e707af61b23ec096758d38e309", + "gen_hash_zig": "sha256:11c4e273387ec011bd4e7c6a27d1a0217fc821c5c58f1abb7e225a95d9eee469", + "module": "port::trios_mesh_node_crypto", + "ring": 12, + "seal_schema": 2, + "sealed_at": "2026-10-18T02:25:06Z", + "sealed_by": "t27c-bootstrap@0.5.2", + "spec_hash": "sha256:d1d3ed152196c59afbafb1b1c08af5ef6e270fd7e354dc4f101e5bc9dcf212d7", + "spec_path": "specs/port/trios/crates/trios-mesh-node/src/crypto.t27", + "tests": { + "failed": 0, + "failing": [], + "forced": false, + "passed": 23, + "total": 23, + "vacuous": 0 + }, + "toolchain": { + "test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d", + "zig": "0.16.0" + } +} \ No newline at end of file diff --git a/.trinity/seals/t27o_T27oRust.json b/.trinity/seals/t27o_T27oRust.json index 4b9ba5d329..84074f8dd5 100644 --- a/.trinity/seals/t27o_T27oRust.json +++ b/.trinity/seals/t27o_T27oRust.json @@ -1,17 +1,17 @@ { - "built_by": "t27c-bootstrap@0.5.2+e7fbc2639", + "built_by": "t27c-bootstrap@0.5.2+0d4fe82f2", "closure": [], "config": "gen=c,rust,verilog,zig;tests=zig", - "gen_hash_c": "sha256:5ced192099954e788bc953c0973428c9f278751b7610f050e07758a9a6611a14", - "gen_hash_rust": "sha256:ae84f2ed194de288b42f9dfeb10b6a965c65f99ca992ef82aaf971082aaca512", - "gen_hash_verilog": "sha256:130434cc65aee3c2c38a14354c010aedbfd11c6e2e565a2da72448ca8a471d17", - "gen_hash_zig": "sha256:a3aee0b8ec566bb21157cb64c6330e87ffcb44ce765a2bf150beb95dd0c9b2ab", + "gen_hash_c": "sha256:93076da93a404ea49f455526fa1d25dfc8b6040dda6f2972dcb747074eb755a3", + "gen_hash_rust": "sha256:d912c313830e2ec4ba390adcf66baabba71cecd6f720246e1a619a95b0964334", + "gen_hash_verilog": "sha256:2b7550a7c7d5e0f989df3e4a00597c788e5abc0671043978bef8bd4cfd40aa9c", + "gen_hash_zig": "sha256:a47e14e956324ccd1ff1d9f521f2761b659ee6e61623c53365af62043c731264", "module": "T27oRust", "ring": 12, "seal_schema": 2, - "sealed_at": "2026-10-12T10:09:28Z", + "sealed_at": "2026-10-18T02:25:04Z", "sealed_by": "t27c-bootstrap@0.5.2", - "spec_hash": "sha256:f4ee9bcc7818621bf5d591d8d74f6cb41ef6fcac3e558e550af6dc45d549aec5", + "spec_hash": "sha256:690282a6a0c834606de0def8b4b05499c1a0e415bc270ffac2d908bc3ca5abbf", "spec_path": "specs/tools/t27o/rust_convert.t27", "tests": { "failed": 0, diff --git a/docs/TYPE_CONFLICTS.md b/docs/TYPE_CONFLICTS.md index 3193df6ccb..49e05ef71e 100644 --- a/docs/TYPE_CONFLICTS.md +++ b/docs/TYPE_CONFLICTS.md @@ -61,7 +61,7 @@ definition moves. `tri types classified` cross-checks the file against a live Non-empty drift in either direction exits non-zero. A classification nobody re-reads becomes a claim about a tree that no longer exists. -## DRIFT -- 62 names +## DRIFT -- 61 names One concept, two definitions. These are the ones with a repair. @@ -90,7 +90,6 @@ One concept, two definitions. These are the ones with a repair. | `Match` | 2 | 2 files | Collapse Match/MatchResult/RegexMatch onto regex_advanced.t27's RegexMatch (it is already the... | | `MemPort` | 2 | 2 files | Make fpga/hir.t27 import Memory's MemPort rather than restate it; reconcile MAX_MEM_PORTS (4 ... | | `Message` | 3 | 3 files | Pick one Message and one MessageRole (with fixed discriminants) in provider/schema.t27; have ... | -| `OptimizerStepResult` | 3 | 2 files | Two fixes: (1) delete the second body of adamw.t27 (lines ~460-end duplicate lines ~14-459) o... | | `PinAssignment` | 3 | 3 files | Hoist one PinAssignment (the 9-field version) into a shared boards module and have all three ... | | `PinMapping` | 2 | 2 files | Either give each board its own name (ArtyA7PinMapping / QMTechA100TPinMapping) or use the spe... | | `PolicyOutput` | 2 | 2 files | Rename to PPOPolicyOutput / SACPolicyOutput, matching the SACActorConfig convention already i... | diff --git a/docs/reports/type_conflicts_classified.json b/docs/reports/type_conflicts_classified.json index b8adcf8b58..0dec0b6f75 100644 --- a/docs/reports/type_conflicts_classified.json +++ b/docs/reports/type_conflicts_classified.json @@ -1,7 +1,7 @@ { "note": "Classification of every conflicted type name reported by `tri types dup`. DRIFT = one concept that grew two definitions; DISTINCT = two concepts that collided on a name. Evidence is the reading that decided it. Regenerate the observation with `tri types dup`; cross-check this file against it with `tri types classified`.", "verdicts": { - "DRIFT": 62, + "DRIFT": 61, "DISTINCT": 47 }, "names": [ @@ -581,18 +581,6 @@ "confidence": "certain \u2014 a self-hosting parser's AST and a collections-library list cell are unrelated by construction; the only overlap is the English word \"node\"", "suggested_action": "Leave both; if the type namespace is ever flattened, rename the cache one to LruEntry." }, - { - "name": "OptimizerStepResult", - "sites": [ - "specs/ml/optimizer/adamw.t27:46", - "specs/ml/optimizer/adamw.t27:501", - "specs/ml/optimizer/sgd_momentum.t27:40" - ], - "verdict": "DRIFT", - "evidence": "`updated_params: []gf16::GF16, m: []gf16::GF16, v: []gf16::GF16, step_norm: gf16::GF16` (adamw) vs `updated_params: []gf16::GF16, velocities: []gf16::GF16, step_norm: gf16::GF16` (sgd_momentum). The trailing comments are byte-identical across the two files \u2014 `// New parameter values` on updated_params and `// L2 norm of the parameter update` on step_norm \u2014 so the lineage is copy-paste; only the optimizer's own state field was swapped (Adam's first/second moments m,v for SGD's velocities). Both files namespace their siblings and leave this one bare: AdamWConfig/AdamWState next to a plain OptimizerStepResult, SgdMomentumConfig/SgdMomentumState next to a plain OptimizerStepResult. Separately, sites 1 and 2 are the SAME FILE and byte-identical: specs/ml/optimizer/adamw.t27 (1019 lines) holds two complete copies of its body \u2014 `// 2. Types` at lines 25 and 470, `// 3. Core Functions` at 54 and 509, `pub const AdamWConfig` at 28 and 483, `pub const OptimizerStepResult` at 46 and 501 \u2014 an ASCII/PhiVariant rewrite pasted in without deleting the original, so `init` and `step` are each declared twice in one module and AdamWConfig's last field is `use_phi_betas: bool` in the first copy and `phi_variant: PhiVariant` in the second.", - "confidence": "certain \u2014 identical comment text on the shared fields proves common origin, and both live in specs/ml/optimizer/", - "suggested_action": "Two fixes: (1) delete the second body of adamw.t27 (lines ~460-end duplicate lines ~14-459) or finish the intended replacement; (2) rename to AdamWStepResult / SgdStepResult, or factor a common `{ updated_params, step_norm }` and let each optimizer return its own state alongside." - }, { "name": "OscillatorState", "sites": [ diff --git a/gen/rust/tools/t27o/rust_convert.rs b/gen/rust/tools/t27o/rust_convert.rs index 199a90f884..99102edd9f 100644 --- a/gen/rust/tools/t27o/rust_convert.rs +++ b/gen/rust/tools/t27o/rust_convert.rs @@ -7262,7 +7262,7 @@ pub fn out_format(src: &[u8], st: &mut [usize], out: &mut [u8], a: usize, ret: b } let fq: usize = quoted_end(src, f); let mut p: usize = (f + 1); - let mut piece: usize = (f + 1); + let mut piece: usize = p; let mut arg: usize = skip_ws(src, fq); if tok_is(src, arg, b",") { arg = skip_ws(src, tok_end(src, arg)); @@ -7310,8 +7310,9 @@ pub fn out_format(src: &[u8], st: &mut [usize], out: &mut [u8], a: usize, ret: b refuse(st, R_STRUSE, a, a, fe); return (); } - if ((fq - 1) > piece) { - put_out_piece(src, st, out, piece, (fq - 1)); + let tail_end: usize = (fq - 1); + if (tail_end > piece) { + put_out_piece(src, st, out, piece, tail_end); newline(st, out); } st[(P) as usize] = skip_ws(src, rp); diff --git a/specs/port/trios/crates/trios-mesh-node/src/crypto.t27 b/specs/port/trios/crates/trios-mesh-node/src/crypto.t27 index d088806ae5..3730bca1c2 100644 --- a/specs/port/trios/crates/trios-mesh-node/src/crypto.t27 +++ b/specs/port/trios/crates/trios-mesh-node/src/crypto.t27 @@ -398,10 +398,12 @@ module port::trios_mesh_node_crypto { // crypto.rs lines 41-50: rand fills 32 bytes and they become the secret // directly -- no stretching, unlike from_seed. The OS randomness is the // parameter here; everything after it is the derivation from_seed tails - // with. - pub fn MeshKeypair_random(entropy: [32]u8) -> MeshKeypair { - const public: [32]u8 = pubkey_from_secret(entropy); - const digest: [32]u8 = sha256_32(public); + // with. The X25519 public key of the entropy and the SHA-256 of that public key + // are the host's results (the header: primitives are declared, never called by a + // test), so they arrive as parameters like the entropy; a body that called the + // undefined primitives read bytes nothing wrote, which t27b's interpreter refuses + // and Zig only hides by filling them. + pub fn MeshKeypair_random(entropy: [32]u8, public: [32]u8, digest: [32]u8) -> MeshKeypair { return keypair_from_public(entropy, public, digest); } @@ -600,8 +602,15 @@ module port::trios_mesh_node_crypto { // lines 43-45: the raw 32 random bytes ARE the secret -- no 0xA3 // layout, no stretching; only from_seed does that. const e: [32]u8 = stretch_seed(6); - const kp: MeshKeypair = MeshKeypair_random(e); + const p: [32]u8 = stretch_seed(7); + const d: [32]u8 = stretch_seed(8); + const kp: MeshKeypair = MeshKeypair_random(e, p, d); assert(arr32_eq(kp.secret, e)); + assert(arr32_eq(kp.public, p)); + assert(kp.secret[0] == 6); + assert(kp.public[0] == 7); + assert(kp.dest_hash[0] == 8); + assert(kp.dest_hash[1] == 0xA3); } test b64_alphabet_table { diff --git a/specs/tools/t27o/rust_convert.t27 b/specs/tools/t27o/rust_convert.t27 index 170da2ed90..46e6de8a35 100644 --- a/specs/tools/t27o/rust_convert.t27 +++ b/specs/tools/t27o/rust_convert.t27 @@ -6206,8 +6206,10 @@ pub fn out_format(src: []const u8, st: []usize, out: []u8, a: usize, ret: bool) const f : usize = skip_ws(src, lp + 1); if (!str_tok(src, f)) { refuse(st, R_STRUSE, a, a, fe); return; } const fq : usize = quoted_end(src, f); + // `f + 1` is spelled once: repeated, it became a `_cse` temporary that t27c writes above `const f` + // (t27b: FnDecl(reference CSE hoist), #9632). var p : usize = f + 1; - var piece : usize = f + 1; + var piece : usize = p; // the arguments start after the format string's comma: format!(FMT, a0, a1, ..) var arg : usize = skip_ws(src, fq); if (tok_is(src, arg, ",")) { arg = skip_ws(src, tok_end(src, arg)); } @@ -6240,7 +6242,8 @@ pub fn out_format(src: []const u8, st: []usize, out: []u8, a: usize, ret: bool) refuse(st, R_STRUSE, a, a, fe); return; } - if (fq - 1 > piece) { put_out_piece(src, st, out, piece, fq - 1); newline(st, out); } + const tail_end : usize = fq - 1; + if (tail_end > piece) { put_out_piece(src, st, out, piece, tail_end); newline(st, out); } st[P] = skip_ws(src, rp); if (ret) { puts(st, out, "return t27o_w;"); } } From 1de17df83a66d82dfbb4229eab88a1966c9eb1ee Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Sun, 18 Oct 2026 09:34:13 +0700 Subject: [PATCH 17/17] spec(port): name the hermes provider-map struct apart from OC-01's HermesProviderMapping (Refs #2774) The batch's #6399 defined a second HermesProviderMapping, which made tri types classified report an UNJUDGED conflict. Renamed in the newer spec; the TS original's name stays in the prose. Co-Authored-By: Claude Opus 5.5 --- .../lib/agents/hermes/hermes-provider-map.t27 | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 b/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 index 3f8238cafc..f7c477f79b 100644 --- a/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 +++ b/specs/port/browseros/trios/agent-server/apps/server/src/lib/agents/hermes/hermes-provider-map.t27 @@ -22,7 +22,9 @@ // verdict struct: ok == false is the original's `undefined`, i.e. agent // creation rejects the type and no mapping exists for it. -pub struct HermesProviderMapping { +// Named apart from trios-openclaw OC-01 HermesProviderMapping: the same table ported from +// another tree with a different field set; one definition per type name (#2774). +pub struct HermesProviderMapEntry { // Hermes' own provider key, written into `model.provider` in config.yaml. hermesProvider: []const u8, // Env var Hermes reads the API key from. @@ -37,7 +39,7 @@ pub struct HermesProviderMapping { pub struct HermesMappingResult { // False is the original's `undefined`: unsupported provider type. ok: bool, - mapping: HermesProviderMapping, + mapping: HermesProviderMapEntry, } // The original's HERMES_SUPPORTED_BROWSEROS_PROVIDER_TYPES.includes(providerType): @@ -61,30 +63,30 @@ pub fn isHermesSupportedProviderType(providerType: []const u8) -> bool { } // The zero mapping, standing in for an absent table entry. -fn hermes_mapping_empty() -> HermesProviderMapping { - return HermesProviderMapping { hermesProvider: "", envVarName: "", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +fn hermes_mapping_empty() -> HermesProviderMapEntry { + return HermesProviderMapEntry { hermesProvider: "", envVarName: "", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; } // HERMES_PROVIDER_MAP.anthropic: pass-through, no base URL involved. -fn hermes_mapping_anthropic() -> HermesProviderMapping { - return HermesProviderMapping { hermesProvider: "anthropic", envVarName: "ANTHROPIC_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +fn hermes_mapping_anthropic() -> HermesProviderMapEntry { + return HermesProviderMapEntry { hermesProvider: "anthropic", envVarName: "ANTHROPIC_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; } // HERMES_PROVIDER_MAP.openai: the original rewrites this to Hermes' custom // provider shape and carries the OpenAI base URL as the default. -fn hermes_mapping_openai() -> HermesProviderMapping { - return HermesProviderMapping { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: true, defaultBaseUrl: "https://api.openai.com/v1" }; +fn hermes_mapping_openai() -> HermesProviderMapEntry { + return HermesProviderMapEntry { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: true, defaultBaseUrl: "https://api.openai.com/v1" }; } // HERMES_PROVIDER_MAP.openrouter: pass-through, no base URL involved. -fn hermes_mapping_openrouter() -> HermesProviderMapping { - return HermesProviderMapping { hermesProvider: "openrouter", envVarName: "OPENROUTER_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +fn hermes_mapping_openrouter() -> HermesProviderMapEntry { + return HermesProviderMapEntry { hermesProvider: "openrouter", envVarName: "OPENROUTER_API_KEY", requiresBaseUrl: false, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; } // HERMES_PROVIDER_MAP["openai-compatible"]: custom provider shape, and the // caller must supply the base URL explicitly. -fn hermes_mapping_openai_compatible() -> HermesProviderMapping { - return HermesProviderMapping { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: true, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; +fn hermes_mapping_openai_compatible() -> HermesProviderMapEntry { + return HermesProviderMapEntry { hermesProvider: "custom", envVarName: "OPENAI_API_KEY", requiresBaseUrl: true, hasDefaultBaseUrl: false, defaultBaseUrl: "" }; } // The original's getHermesProviderMapping: the table entry for a supported