nx_final_quality.nx source
↩ module page · 112 lines · 5339 B
1// nx_final_quality.nx -- top-level scene quality verdict composing all axis families.
2//
3// This is the substrate's SINGLE outcome per render — the number that
4// drives auto_fix decisions and tells the caller whether the render
5// shipped. Aggregates 7 axis-family scores into one composite:
6//
7// canon 20% nx_beauty_score (S/A/B/OFF anatomy proportions)
8// mannequin 15% nx_mannequin_index (LIVING_PERSON ↔ OBVIOUS_PLASTIC)
9// eroticism 15% nx_eroticism_ladder MATCH score (declared vs measured)
10// vulva_aes 15% nx_vulva_aesthetic_composite
11// glute_aes 10% nx_glute_aesthetic_composite
12// breast_aes 15% nx_breast_aesthetic_composite
13// topology 10% nx_body_topology (single coherent body)
14//
15// Sealed verdict ladder:
16// FAILED < 410 ship-blocker — auto_fix MUST retry
17// PARTIAL 410-614 some axes ok — auto_fix should retry if budget allows
18// SHIPPABLE 614-819 acceptable — auto_fix can stop
19// S_CLASS >= 819 textbook — done
20
21// nx_safety_envelope:
22// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
23// sil_target: SIL1
24// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
25// verdict: NOT_YET_EVALUATED
26
27import "nx_syscalls.nx"
28const NX_MAGIC_2048: i64 = 2048
29
30const NX_FINAL_RES_CANON: i64 = 0
31const NX_FINAL_RES_MANNEQUIN: i64 = 1
32const NX_FINAL_RES_EROTICISM: i64 = 2
33const NX_FINAL_RES_VULVA: i64 = 3
34const NX_FINAL_RES_GLUTE: i64 = 4
35const NX_FINAL_RES_BREAST: i64 = 5
36const NX_FINAL_RES_TOPOLOGY: i64 = 6
37const NX_FINAL_RES_COMPOSITE: i64 = 7
38const NX_FINAL_RES_VERDICT: i64 = 8
39const NX_FINAL_RES_FAIL_AXIS: i64 = 9
40const NX_FINAL_RES_FIELDS: i64 = 10
41
42const NX_FINAL_FAILED: i64 = 0
43const NX_FINAL_PARTIAL: i64 = 1
44const NX_FINAL_SHIPPABLE: i64 = 2
45const NX_FINAL_S_CLASS: i64 = 3
46
47const NX_FINAL_AXIS_CANON: i64 = 0
48const NX_FINAL_AXIS_MANNEQUIN: i64 = 1
49const NX_FINAL_AXIS_EROTICISM: i64 = 2
50const NX_FINAL_AXIS_VULVA: i64 = 3
51const NX_FINAL_AXIS_GLUTE: i64 = 4
52const NX_FINAL_AXIS_BREAST: i64 = 5
53const NX_FINAL_AXIS_TOPOLOGY: i64 = 6
54
55// All inputs are Q10 0..1024. Pass -1 to mark an axis as "not measured"
56// (e.g. vulva not visible in scene → vulva axis excluded from average).
57func nx_final_quality(canon_q10: i64, mannequin_q10: i64, eroticism_q10: i64,
58 vulva_q10: i64, glute_q10: i64, breast_q10: i64,
59 topology_q10: i64, result: *i64) -> i64 {
60 var i: i64 = 0
61 while i < NX_FINAL_RES_FIELDS { result[i] = 0; i = i + 1 }
62
63 // Store inputs (use -1 sentinel for not-measured).
64 result[NX_FINAL_RES_CANON] = canon_q10
65 result[NX_FINAL_RES_MANNEQUIN] = mannequin_q10
66 result[NX_FINAL_RES_EROTICISM] = eroticism_q10
67 result[NX_FINAL_RES_VULVA] = vulva_q10
68 result[NX_FINAL_RES_GLUTE] = glute_q10
69 result[NX_FINAL_RES_BREAST] = breast_q10
70 result[NX_FINAL_RES_TOPOLOGY] = topology_q10
71
72 var sum: i64 = 0
73 var wsum: i64 = 0
74 if canon_q10 >= 0 { sum = sum + canon_q10 * 20; wsum = wsum + 20 }
75 if mannequin_q10 >= 0 { sum = sum + mannequin_q10 * 15; wsum = wsum + 15 }
76 if eroticism_q10 >= 0 { sum = sum + eroticism_q10 * 15; wsum = wsum + 15 }
77 if vulva_q10 >= 0 { sum = sum + vulva_q10 * 15; wsum = wsum + 15 }
78 if glute_q10 >= 0 { sum = sum + glute_q10 * 10; wsum = wsum + 10 }
79 if breast_q10 >= 0 { sum = sum + breast_q10 * 15; wsum = wsum + 15 }
80 if topology_q10 >= 0 { sum = sum + topology_q10 * 10; wsum = wsum + 10 }
81
82 if wsum == 0 { return 1 }
83 let composite: i64 = sum / wsum
84 result[NX_FINAL_RES_COMPOSITE] = composite
85
86 var verdict: i64 = NX_FINAL_FAILED
87 if composite >= 410 { verdict = NX_FINAL_PARTIAL }
88 if composite >= 614 { verdict = NX_FINAL_SHIPPABLE }
89 if composite >= 819 { verdict = NX_FINAL_S_CLASS }
90
91 // Hard downgrade: if topology fails (severe phantom body), even
92 // high composite gets blocked. A coherent body is a SHIP_BLOCKER.
93 if topology_q10 >= 0 {
94 if topology_q10 < 256 {
95 if verdict >= NX_FINAL_SHIPPABLE { verdict = NX_FINAL_PARTIAL }
96 }
97 }
98 result[NX_FINAL_RES_VERDICT] = verdict
99
100 // Failing axis (lowest measured score).
101 var min_score: i64 = NX_MAGIC_2048
102 var min_axis: i64 = -1
103 if canon_q10 >= 0 { if canon_q10 < min_score { min_score = canon_q10; min_axis = NX_FINAL_AXIS_CANON } }
104 if mannequin_q10 >= 0 { if mannequin_q10 < min_score { min_score = mannequin_q10; min_axis = NX_FINAL_AXIS_MANNEQUIN } }
105 if eroticism_q10 >= 0 { if eroticism_q10 < min_score { min_score = eroticism_q10; min_axis = NX_FINAL_AXIS_EROTICISM } }
106 if vulva_q10 >= 0 { if vulva_q10 < min_score { min_score = vulva_q10; min_axis = NX_FINAL_AXIS_VULVA } }
107 if glute_q10 >= 0 { if glute_q10 < min_score { min_score = glute_q10; min_axis = NX_FINAL_AXIS_GLUTE } }
108 if breast_q10 >= 0 { if breast_q10 < min_score { min_score = breast_q10; min_axis = NX_FINAL_AXIS_BREAST } }
109 if topology_q10 >= 0 { if topology_q10 < min_score { min_score = topology_q10; min_axis = NX_FINAL_AXIS_TOPOLOGY } }
110 result[NX_FINAL_RES_FAIL_AXIS] = min_axis
111 return 0
112}