nx_handcheck.nx
buildroot/runtime/nx_handcheck.nx
about
nx_handcheck.nx -- THE HAND STRUCTURE JUDGE over an NXA SKEL (operator 2026-09-01: "the hands are
bad"). It is the SIBLING OF nx_footcheck and deliberately mirrors its contract -- check / selftest,
one measured report, one predicate made of things a hand IS rather than a blended score -- because
two judges for two ends of the same limb must not have two different shapes.
WHY IT EXISTS: the hands were the ONE named character defect in this estate with NO instrument at
all. nx_clipcheck measures limb-vs-torso and limb-vs-floor; nx_footcheck measures the distal foot;
nothing measured a hand. Grading therefore depended entirely on the operator's eye.
THE STRUCTURAL PROBLEM, AND WHY THIS IS NOT NAME MATCHING: NXA's SKEL carries NO JOINT NAMES, by
design (nx_nxa_joints.nx states it and quotes nx_nxa_rig_emit: "SKEL carries no names by design").
So a hand cannot be looked up -- it must be DERIVED FROM TOPOLOGY. A hand is the only place on a
humanoid where three or more TERMINAL SIMPLE CHAINS hang off one attachment. That is what this
organ finds. Nothing here knows a joint index, so the judge keeps working when joints are added or
reordered ahead of it -- the same structural stance nx_footcheck takes with its rotation.
THE ANATOMICAL CANON IS CITED, NOT DIALLED. Buryanov and Kotiuk, "Proportions of Hand Segments",
Int. J. Morphol. 28(3):755-758, 2010 (open access; mirror
knowledge/fetched/cmp_handcheck_buryanov2010.pdf, sha256 ec2a49be..., 66 adult hands by X-ray with
a radiopaque ruler and no scaling error). Their Table I lengths in mm, reconstructed and then
INDEPENDENTLY CONFIRMED by their own Table II ratio row for every one of the five rays -- two
instruments inside one document agreeing:
ray distal medial proximal metacarpal Tab.II ratio (pd:pm:pp:m)
I 21.67 -- 31.57 46.22 1 : -- : 1.5 : 2.1
II 15.82 22.38 39.78 68.12 1 : 1.4 : 2.5 : 4.3
III 17.40 26.33 44.63 64.60 1 : 1.5 : 2.6 : 3.7
IV 17.30 25.65 41.37 58.00 1 : 1.5 : 2.4 : 3.4
V 15.96 18.11 32.74 53.69 1 : 1.1 : 2.1 : 3.4
TWO LAWS FALL OUT OF THAT TABLE AND BOTH ARE ENFORCED HERE:
(1) MONOTONIC DISTAL SHORTENING -- proximal > medial > distal holds in ALL FIVE rays without
exception. It is dimensionless, so it survives any stylisation of hand size. It is the STRICT
clause here and it needs no tolerance at all.
(2) PHALANX COUNT -- four fingers carry THREE phalanges and the thumb carries TWO (the paper's
medial column is empty for ray I, and its text names "even different phalanges numbers").
In a rig a chain of L joints spans L-1 bones, so a finger is a 4-joint chain and a thumb a
3-joint chain.
DECLARED IMPRECISION -- name it or the next reader trusts it as exact:
- v1 measures the BIND SKELETON. It does NOT read SKIN weights, so it cannot yet say whether the
hand is a distinct skinned region or fused to the forearm; and it does NOT read POSE or ANIM, so
dependencies 3 imports · 1 importers
imports: nx_syscalls.nxnx_nxa.nxnx_gate_verdict.nx
imported by: nx_handcheck_gate.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 62 | const HC_WPJ: i64 = 8 // SKEL record: [parent][x][y][z][qx][qy][qz][qw] |
| 63 | const HC_MAXJ: i64 = 4096 |
| 64 | const HC_MAXD: i64 = 24 // digit chains tracked per hub |
| 65 | const HC_MAXH: i64 = 8 // hubs tracked |
| 66 | const HC_MAXCH: i64 = 24 // joints tracked per digit chain |
| 67 | const HC_Q: i64 = 1000 |
| 68 | const HC_BIG: i64 = 1000000000 |
| 70 | const HC_MIN_CHAIN: i64 = 2 |
| 72 | const HC_MIN_HUB_DIGITS: i64 = 3 |
| 74 | const HC_DIGITS_CANON: i64 = 5 |
| 75 | const HC_FINGER_BONES: i64 = 3 |
| 76 | const HC_THUMB_BONES: i64 = 2 |
| 77 | const HC_MIN_3BONE: i64 = 4 |
| 82 | const HC_R_PPPM_MAX: i64 = 2600 |
| 83 | const HC_R_PMPD_MAX: i64 = 2600 |
| 86 | const HC_THUMB_OPP_MIN: i64 = 150 |
| 89 | const HC_FUSE_PERMIL: i64 = 100 |
| 92 | const HC_HAND_MIN_H01: i64 = 150 |
| 93 | const HC_OUT: i64 = 32 |
| 94 | const HC_NEWTON: i64 = 64 |
| 95 | const HC_SQRTCAP: i64 = 65536 |
functions
| 97 | func hc_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } called by 1: hc_puts |
| 98 | func hc_puts(s: *u8) -> i64 { sys_write(1, s, hc_slen(s)); return 0 } |
| 99 | func hc_pn(v: i64) -> i64 |
| 112 | func hc_streq(a: *u8, b: *u8) -> i64 called by 1: main |
| 120 | func hc_isqrt(v: i64) -> i64 |
| 134 | func hc_dist(W: *i64, sw: i64, a: i64, b: i64) -> i64 |
| 145 | func hc_children(W: *i64, sw: i64, nj: i64, NC: *i64) -> i64 |
| 157 | func hc_only_child(W: *i64, sw: i64, nj: i64, j: i64) -> i64 called by 1: hc_chain |
| 169 | func hc_chain(W: *i64, sw: i64, nj: i64, NC: *i64, d: i64, CH: *i64) -> i64 |
| 186 | func hc_hub_digits(W: *i64, sw: i64, nj: i64, NC: *i64, j: i64, CH: *i64) -> i64 |
| 206 | func hc_measure(W: *i64, sw: i64, nj: i64, out: *i64) -> i64 |
| 432 | func hc_ok(out: *i64) -> i64 |
| 441 | func hc_report(out: *i64) -> i64 |
| 470 | func hc_setj(W: *i64, sw: i64, j: i64, p: i64, x: i64, y: i64, z: i64) -> i64 |
| 485 | func hc_fx_good(nout: *i64) -> *i64 |
| 511 | func hc_fx_bad(nout: *i64) -> *i64 |
| 531 | func hc_fx_leg(nout: *i64) -> *i64 |
| 543 | func hc_fx_foot(nout: *i64) -> *i64 |
| 563 | func hc_dump(W: *i64, sw: i64, nj: i64) -> i64 |
| 588 | func hc_teeth(ctr: *i64) -> i64 |
| 677 | func hc_gate() -> i64 |
| 685 | func hc_load(path: *u8, lp: *i64, swp: *i64, njp: *i64) -> *u8 |
| 696 | func main(argc: i64, argv: *i64) -> i64 |