Skip to content

Commit 1778127

Browse files
committed
migration: 17 integer-brain kernels from idaptik logic-directory sweep (cluster C13)
Exhaustive sweep of the eight brain-dense logic directories (devices, player, combat, enemies, companions, multiplayer, src/shared, utils — 159 .res files). Extracted 17 new Int(...)->Int brains; classified the remainder as host-side senses, FFI binding shims, float/string-input cores, or already-migrated. New brains (all G1 compile, G2 parity all-pass vs independent JS oracle, G4 assail clean): PlayerSprite, CombatResolve, ThreatClass, GameI18nCore, AlertPalette, PeerPort, AccessClamp, Coprocessor, Coprocessor_IO, Kernel_Crypto, Kernel_Quantum, ResourceAccounting, UmsLevelLoader, MoletaireCoprocessors, MoletaireHunger, LobbyManager, MultiplayerClient. ~8,450 parity cases total. Several are residual sub-brains earlier clusters scoped out as "routing" (ThreatClass from DualAlertBridge; the Coprocessor/Kernel/Resource set from the shared coprocessor layer). Each new brain's exported signature matches an existing *Coprocessor.res host bridge. Full per-file disposition (159 files: 17 new / 43 already / 99 no-brain) recorded in EVIDENCE-C13-logic-sweep.adoc. Brain count 62 -> 79. https://claude.ai/code/session_01WoKhFQePiRsAj7aqnxbG8s
1 parent 9ca22a8 commit 1778127

35 files changed

Lines changed: 3076 additions & 0 deletions
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: AGPL-3.0-or-later
2+
// SPDX-FileCopyrightText: 2025-2026 hyperpolymath
3+
//
4+
// AccessClamp -- the accessibility-preference range-clamp co-processor, the
5+
// pure-integer core extracted from src/app/utils/AccessibilitySettings.res
6+
// `setFontScale` and `setGameSpeed` (the font-scale clamp is the same bound the
7+
// FontScaleCoprocessor.res bridge documents as `clampScale`, 0.75..2.0). Per the
8+
// DESIGN-VISION ("AffineScript is the brain, JS/Pixi the senses; only primitives
9+
// cross the wasm boundary") the JS host keeps the cached refs, the localStorage
10+
// persistence and the live PixiJS multiply (px * scale); AffineScript owns only
11+
// the integer range-clamp arithmetic.
12+
//
13+
// The ReScript clamps a Float preference with `Math.max(lo, Math.min(hi, v))`.
14+
// Float cannot cross the scalar-i32 boundary, so the preference crosses in
15+
// MILLI-UNITS: the JS caller passes round(scale * 1000) and reads back an integer
16+
// milli-value it divides by 1000. The bounds become integer milli-bounds and the
17+
// clamp is exact (the ReScript bounds 0.75 / 2.0 / 0.25 / 1.0 are all multiples of
18+
// 0.001, so the milli-domain loses nothing).
19+
//
20+
//## Font-scale bound (setFontScale: Math.max(0.75, Math.min(2.0, scale)))
21+
// milli range [750 .. 2000] (0.75x .. 2.0x text size)
22+
//## Game-speed bound (setGameSpeed: Math.max(0.25, Math.min(1.0, speed)))
23+
// milli range [250 .. 1000] (0.25x very-slow .. 1.0x normal)
24+
//
25+
// This is a genuine CLAMP (saturating to the nearest in-band bound), not a
26+
// sentinel: an out-of-range preference is pinned to the lo or hi bound exactly as
27+
// the ReScript Math.max/Math.min does, never to a sentinel. The clamp is total
28+
// and idempotent over the integer milli-domain.
29+
30+
// The font-scale lower / upper milli-bounds (0.75 / 2.0 * 1000).
31+
pub fn font_scale_min_milli() -> Int { 750 }
32+
pub fn font_scale_max_milli() -> Int { 2000 }
33+
34+
// The game-speed lower / upper milli-bounds (0.25 / 1.0 * 1000).
35+
pub fn game_speed_min_milli() -> Int { 250 }
36+
pub fn game_speed_max_milli() -> Int { 1000 }
37+
38+
// A generic saturating clamp of v into [lo, hi]. Mirrors Math.max(lo,
39+
// Math.min(hi, v)): clamp UP to lo first conceptually, but the ReScript applies
40+
// min(hi, v) then max(lo, ...) -- when lo <= hi the two orders agree, and the
41+
// preference bounds always satisfy lo <= hi, so the single form below is exact.
42+
fn clamp_range(v: Int, lo: Int, hi: Int) -> Int {
43+
if v < lo { lo } else { if v > hi { hi } else { v } }
44+
}
45+
46+
// Clamp a font-scale milli-value into [750, 2000] (AccessibilitySettings
47+
// setFontScale's range bound; the FontScaleCoprocessor `clampScale`).
48+
pub fn clamp_font_scale_milli(scale_milli: Int) -> Int {
49+
clamp_range(scale_milli, 750, 2000)
50+
}
51+
52+
// Clamp a game-speed milli-value into [250, 1000] (AccessibilitySettings
53+
// setGameSpeed's range bound).
54+
pub fn clamp_game_speed_milli(speed_milli: Int) -> Int {
55+
clamp_range(speed_milli, 250, 1000)
56+
}
57+
58+
// Whether a font-scale milli-value is already in-band (no clamp would change it).
59+
// 1 = in [750,2000], 0 = would be saturated. Lets the host skip a redundant
60+
// write when the preference is already valid.
61+
pub fn font_scale_in_band(scale_milli: Int) -> Int {
62+
if scale_milli < 750 { 0 } else { if scale_milli > 2000 { 0 } else { 1 } }
63+
}
64+
65+
// Whether a game-speed milli-value is already in-band (no clamp would change it).
66+
pub fn game_speed_in_band(speed_milli: Int) -> Int {
67+
if speed_milli < 250 { 0 } else { if speed_milli > 1000 { 0 } else { 1 } }
68+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// hypatia: allow cicd_rules/javascript_detected -- Deno trial component for nextgen-evangelist; production target is Rust/AffineScript (see proposals/nextgen-evangelist/README.adoc)
3+
//
4+
// affine-parity config for AccessClamp.affine (idaptik accessibility-preference
5+
// range clamps in milli-units; scalar i32 ABI). The oracle re-derives the
6+
// Math.max(lo, Math.min(hi, v)) clamps from AccessibilitySettings.res
7+
// INDEPENDENTLY in plain JS (milli-scaled bounds), so a codegen regression
8+
// surfaces as a differential mismatch.
9+
10+
// Independent re-derivation of the ReScript Math.max(lo, Math.min(hi, v)).
11+
const clampRange = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
12+
const FS_LO = 750, FS_HI = 2000, GS_LO = 250, GS_HI = 1000;
13+
14+
export default {
15+
affine: "AccessClamp.affine",
16+
cases: [
17+
{ name: "font_scale_min_milli()", export: "font_scale_min_milli", args: [], oracle: () => 750 },
18+
{ name: "font_scale_max_milli()", export: "font_scale_max_milli", args: [], oracle: () => 2000 },
19+
{ name: "game_speed_min_milli()", export: "game_speed_min_milli", args: [], oracle: () => 250 },
20+
{ name: "game_speed_max_milli()", export: "game_speed_max_milli", args: [], oracle: () => 1000 },
21+
{
22+
// Sweep across and well past both bounds, stepping by 1 over the full
23+
// [0..2500] milli-range would be 2501 cases; a coarser representative sweep
24+
// over the boundary neighbourhoods plus interior is sufficient and fast.
25+
name: "clamp_font_scale_milli over boundary + interior",
26+
export: "clamp_font_scale_milli",
27+
args: [{ values: [0, 500, 749, 750, 751, 1000, 1375, 1999, 2000, 2001, 2500, -100] }],
28+
oracle: (v) => clampRange(v, FS_LO, FS_HI),
29+
},
30+
{
31+
name: "clamp_game_speed_milli over boundary + interior",
32+
export: "clamp_game_speed_milli",
33+
args: [{ values: [0, 100, 249, 250, 251, 500, 750, 999, 1000, 1001, 1500, -50] }],
34+
oracle: (v) => clampRange(v, GS_LO, GS_HI),
35+
},
36+
{
37+
name: "font_scale_in_band over boundary neighbourhood",
38+
export: "font_scale_in_band",
39+
args: [{ values: [749, 750, 751, 1999, 2000, 2001, 0, 2500] }],
40+
oracle: (v) => (v >= FS_LO && v <= FS_HI ? 1 : 0),
41+
},
42+
{
43+
name: "game_speed_in_band over boundary neighbourhood",
44+
export: "game_speed_in_band",
45+
args: [{ values: [249, 250, 251, 999, 1000, 1001, 0, 1500] }],
46+
oracle: (v) => (v >= GS_LO && v <= GS_HI ? 1 : 0),
47+
},
48+
],
49+
};
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// SPDX-License-Identifier: AGPL-3.0-or-later
2+
// SPDX-FileCopyrightText: 2025-2026 hyperpolymath
3+
//
4+
// AlertPalette -- the accessibility alert-colour lookup co-processor, the
5+
// pure-integer core extracted from src/app/utils/ColorPalette.res `alertColor`.
6+
// The existing ColorPalette co-processor (colorpalette.wasm, bound by
7+
// ColorPaletteCoprocessor.res) deliberately captured only the RGB-channel and
8+
// WCAG luminance/contrast KERNELS and left the accessibility palette LOOKUP
9+
// TABLES on the ReScript side (FeaturePacks documents this: "the live HUD
10+
// call-sites alertColor/deviceColor are accessibility palette lookup tables with
11+
// no corresponding kernel"). This brain captures exactly that residual: the
12+
// alert-level colour table, which is wholly pure-integer (enum bands in, a 24-bit
13+
// RGB integer out) with no host delegation -- unlike deviceColor/securityColor
14+
// whose Normal arm delegates to DeviceTypes host getters.
15+
//
16+
// Per the DESIGN-VISION the JS host keeps the AccessibilitySettings refs (the
17+
// high-contrast flag and colour-blind mode); AffineScript owns only the integer
18+
// table: given the high-contrast flag, the colour-blind mode and the alert level
19+
// it returns the packed colour.
20+
//
21+
//## Alert level encoding (levelInt, the header contract for the JS host)
22+
// 0 = Clear 1 = Noticed 2 = Caution 3 = Alert 4 = Danger
23+
// The ReScript switch has explicit arms for 0..4 and a `_` catch-all that takes
24+
// the Danger-row's "max" colour; we reproduce that fold (level >= 4 OR level < 0
25+
// uses the catch-all row), so the table is total over all Int and matches the
26+
// ReScript exactly.
27+
//
28+
//## Colour-blind mode encoding (mode, mirrors AccessibilitySettings.colorBlindMode)
29+
// 0 = Normal 3 = Tritanopia
30+
// 1 = Protanopia 4 = Achromatopsia
31+
// 2 = Deuteranopia
32+
// Protanopia and Deuteranopia share one table (the ReScript `Protanopia |
33+
// Deuteranopia =>` combined arm). An out-of-band mode folds onto Normal (0),
34+
// matching AccessibilitySettings.colorBlindModeFromString's `_ => Normal`.
35+
//
36+
// high_contrast is a host boolean crossed as 0 (off) or 1 (on); any non-zero is
37+
// treated as on. When on, the mode is ignored (the ReScript tests high contrast
38+
// first), so the high-contrast table is returned regardless of mode.
39+
//
40+
// All outputs are 24-bit RGB integers (0..0xFFFFFF = 16777215), well inside i32;
41+
// no value collides with another row at the same level, and -1 is never emitted,
42+
// so this is a pure total lookup (assail stays clean: no sentinel collapse).
43+
44+
// Fold an arbitrary colour-blind mode index onto the valid 0..4 band; unknown ->
45+
// Normal (0). Mirrors colorBlindModeFromString's `_ => Normal`.
46+
pub fn clamp_mode(mode: Int) -> Int {
47+
if mode < 0 { 0 } else { if mode > 4 { 0 } else { mode } }
48+
}
49+
50+
// The catch-all alert row index used for level < 0 or level > 4: the ReScript
51+
// `_` arm coincides with the Danger row visually but uses a DISTINCT "max"
52+
// colour, so it is modelled as its own row index 5.
53+
fn alert_row(level: Int) -> Int {
54+
if level < 0 { 5 } else { if level > 4 { 5 } else { level } }
55+
}
56+
57+
//## High-contrast alert table (isHighContrastEnabled() == true)
58+
// row 0 0x00ff00 1 0xffff00 2 0xffaa00 3 0xff4400 4 0xff0000 _ 0xff0000
59+
fn high_contrast_colour(level: Int) -> Int {
60+
let r = alert_row(level);
61+
if r == 0 { 65280 } else {
62+
if r == 1 { 16776960 } else {
63+
if r == 2 { 16755200 } else {
64+
if r == 3 { 16729088 } else {
65+
16711680 } } } }
66+
}
67+
68+
//## Normal-mode alert table
69+
// 0 0x00ff00 1 0x88ff00 2 0xffff00 3 0xff8800 4 0xff4400 _ 0xff0000
70+
fn normal_colour(level: Int) -> Int {
71+
let r = alert_row(level);
72+
if r == 0 { 65280 } else {
73+
if r == 1 { 8978176 } else {
74+
if r == 2 { 16776960 } else {
75+
if r == 3 { 16746496 } else {
76+
if r == 4 { 16729088 } else {
77+
16711680 } } } } }
78+
}
79+
80+
//## Protanopia/Deuteranopia alert table (shared arm)
81+
// 0 0x0088ff 1 0x44aaff 2 0xffdd44 3 0xffaa00 4 0xff8800 _ 0xff6600
82+
fn protan_deuter_colour(level: Int) -> Int {
83+
let r = alert_row(level);
84+
if r == 0 { 35071 } else {
85+
if r == 1 { 4500223 } else {
86+
if r == 2 { 16768324 } else {
87+
if r == 3 { 16755200 } else {
88+
if r == 4 { 16746496 } else {
89+
16737792 } } } } }
90+
}
91+
92+
//## Tritanopia alert table
93+
// 0 0x00ee88 1 0x66dd66 2 0xdddd00 3 0xee6688 4 0xdd2266 _ 0xcc0044
94+
fn tritan_colour(level: Int) -> Int {
95+
let r = alert_row(level);
96+
if r == 0 { 61064 } else {
97+
if r == 1 { 6741350 } else {
98+
if r == 2 { 14540032 } else {
99+
if r == 3 { 15623816 } else {
100+
if r == 4 { 14492262 } else {
101+
13369412 } } } } }
102+
}
103+
104+
//## Achromatopsia alert table (brightness-only)
105+
// 0 0xffffff 1 0xcccccc 2 0x999999 3 0x777777 4 0x444444 _ 0x222222
106+
fn achroma_colour(level: Int) -> Int {
107+
let r = alert_row(level);
108+
if r == 0 { 16777215 } else {
109+
if r == 1 { 13421772 } else {
110+
if r == 2 { 10066329 } else {
111+
if r == 3 { 7829367 } else {
112+
if r == 4 { 4473924 } else {
113+
2236962 } } } } }
114+
}
115+
116+
// The packed RGB alert colour for a high-contrast flag, a colour-blind mode and
117+
// an alert level. High contrast wins first (mode ignored); otherwise the mode
118+
// selects the table. This is the full ColorPalette.res `alertColor` decision.
119+
pub fn alert_colour(high_contrast: Int, mode: Int, level: Int) -> Int {
120+
if high_contrast != 0 { high_contrast_colour(level) } else {
121+
let m = clamp_mode(mode);
122+
if m == 0 { normal_colour(level) } else {
123+
if m == 1 { protan_deuter_colour(level) } else {
124+
if m == 2 { protan_deuter_colour(level) } else {
125+
if m == 3 { tritan_colour(level) } else {
126+
achroma_colour(level) } } } }
127+
}
128+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// hypatia: allow cicd_rules/javascript_detected -- Deno trial component for nextgen-evangelist; production target is Rust/AffineScript (see proposals/nextgen-evangelist/README.adoc)
3+
//
4+
// affine-parity config for AlertPalette.affine (idaptik accessibility alert
5+
// colour lookup; scalar i32 ABI). The oracle re-derives the alertColor decision
6+
// tables from ColorPalette.res INDEPENDENTLY in plain JS (hex literals, mirroring
7+
// the ReScript source rather than the .affine's decimal encoding), so a codegen
8+
// regression or a transcription error in the .affine surfaces as a differential
9+
// mismatch.
10+
11+
// The catch-all row for level < 0 or > 4 (the ReScript `_` arm), modelled as row 5.
12+
const row = (lvl) => (lvl < 0 || lvl > 4 ? 5 : lvl);
13+
14+
const HC = [0x00ff00, 0xffff00, 0xffaa00, 0xff4400, 0xff0000, 0xff0000];
15+
const NORMAL = [0x00ff00, 0x88ff00, 0xffff00, 0xff8800, 0xff4400, 0xff0000];
16+
const PROTDEUT = [0x0088ff, 0x44aaff, 0xffdd44, 0xffaa00, 0xff8800, 0xff6600];
17+
const TRITAN = [0x00ee88, 0x66dd66, 0xdddd00, 0xee6688, 0xdd2266, 0xcc0044];
18+
const ACHROMA = [0xffffff, 0xcccccc, 0x999999, 0x777777, 0x444444, 0x222222];
19+
20+
const clampMode = (m) => (m < 0 || m > 4 ? 0 : m);
21+
22+
const alertColour = (hc, mode, level) => {
23+
const r = row(level);
24+
if (hc !== 0) return HC[r];
25+
const m = clampMode(mode);
26+
if (m === 0) return NORMAL[r];
27+
if (m === 1 || m === 2) return PROTDEUT[r];
28+
if (m === 3) return TRITAN[r];
29+
return ACHROMA[r];
30+
};
31+
32+
export default {
33+
affine: "AlertPalette.affine",
34+
cases: [
35+
{
36+
name: "clamp_mode over [-3..8]",
37+
export: "clamp_mode",
38+
args: [[-3, 8]],
39+
oracle: (m) => clampMode(m),
40+
},
41+
{
42+
// Full cartesian over the high-contrast path: hc=1, every mode, every level
43+
// (incl. out-of-band level to exercise the `_` row).
44+
name: "alert_colour high-contrast path (hc=1) over modes x levels",
45+
export: "alert_colour",
46+
args: [{ values: [1, 2, 7] }, [0, 4], [-2, 6]],
47+
oracle: (hc, mode, level) => alertColour(hc, mode, level),
48+
},
49+
{
50+
// Full cartesian over the normal-path: hc=0, every mode 0..4 (+ out-of-band),
51+
// every level -2..6.
52+
name: "alert_colour mode-selected path (hc=0) over modes x levels",
53+
export: "alert_colour",
54+
args: [0, [-1, 6], [-2, 6]],
55+
oracle: (hc, mode, level) => alertColour(hc, mode, level),
56+
},
57+
],
58+
};

0 commit comments

Comments
 (0)