nx_makeup_style.nx source
↩ module page · 153 lines · 6389 B
1// nx_makeup_style.nx -- typed makeup classification + scene-appropriateness check.
2//
3// For DM-level autonomous generation the substrate has to KNOW what
4// makeup is appropriate for the scene context. Gym scenes don't get
5// smokey eye; bedroom intimate doesn't get harsh contour; date-night
6// dinner wants subtle glam. The substrate stores typed MakeupKind +
7// per-LocationKind acceptable bands + scoring against declared intent.
8//
9// 6 sealed makeup kinds (intensity ladder):
10// NO_MAKEUP bare skin
11// NATURAL mascara + balm + light blush
12// SOFT_GLAM subtle eye + lip + cheek
13// GLAM full eye + lip + contour
14// SMOKEY_BOLD dramatic eye + bold lip
15// STAGE_AVANT editorial extreme (red carpet / runway)
16//
17// Per-scene appropriateness bitmask: which makeup kinds work for
18// which LocationKind from nx_outfit_location_coherence.
19
20// nx_safety_envelope:
21// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
22// sil_target: SIL1
23// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
24// verdict: NOT_YET_EVALUATED
25
26import "nx_syscalls.nx"
27const NX_MAGIC_1024: i64 = 1024
28
29const NX_MAKEUP_NO_MAKEUP: i64 = 0
30const NX_MAKEUP_NATURAL: i64 = 1
31const NX_MAKEUP_SOFT_GLAM: i64 = 2
32const NX_MAKEUP_GLAM: i64 = 3
33const NX_MAKEUP_SMOKEY_BOLD: i64 = 4
34const NX_MAKEUP_STAGE_AVANT: i64 = 5
35
36// LocationKind ids (mirror nx_outfit_location_coherence Python enum).
37const NX_LOC_UNKNOWN: i64 = 0
38const NX_LOC_GYM: i64 = 1
39const NX_LOC_BEDROOM: i64 = 2
40const NX_LOC_KITCHEN: i64 = 3
41const NX_LOC_BATHROOM: i64 = 4
42const NX_LOC_OUTDOOR: i64 = 5
43const NX_LOC_OFFICE: i64 = 6
44const NX_LOC_RESTAURANT: i64 = 7
45const NX_LOC_STUDIO: i64 = 8
46const NX_LOC_BEACH: i64 = 9
47const NX_LOC_POOL: i64 = 10
48
49const NX_MAKEUP_RES_DECLARED: i64 = 0
50const NX_MAKEUP_RES_MEASURED: i64 = 1
51const NX_MAKEUP_RES_APPROP_Q10: i64 = 2
52const NX_MAKEUP_RES_MATCH_Q10: i64 = 3
53const NX_MAKEUP_RES_VERDICT: i64 = 4
54const NX_MAKEUP_RES_FIELDS: i64 = 5
55
56const NX_MAKEUP_V_INAPPROPRIATE: i64 = 0 // makeup wrong for scene
57const NX_MAKEUP_V_MISMATCHED: i64 = 1 // makeup ≠ declared
58const NX_MAKEUP_V_ACCEPTABLE: i64 = 2
59const NX_MAKEUP_V_APPROPRIATE: i64 = 3 // exact match for scene + declared
60
61// Scene-appropriate makeup score (Q10) per (location, makeup_kind).
62// 1024 = perfect fit; 0 = wrong; intermediate = passable.
63func nx_makeup_scene_score(location: i64, makeup_kind: i64) -> i64 {
64 if location == NX_LOC_GYM {
65 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return NX_MAGIC_1024 }
66 if makeup_kind == NX_MAKEUP_NATURAL { return 819 }
67 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return 256 }
68 return 0
69 }
70 if location == NX_LOC_BEDROOM {
71 if makeup_kind == NX_MAKEUP_NATURAL { return NX_MAGIC_1024 }
72 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return 870 }
73 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return 768 }
74 if makeup_kind == NX_MAKEUP_GLAM { return 410 } // smudged-after looks
75 if makeup_kind == NX_MAKEUP_SMOKEY_BOLD { return 200 }
76 return 100
77 }
78 if location == NX_LOC_RESTAURANT {
79 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return NX_MAGIC_1024 }
80 if makeup_kind == NX_MAKEUP_GLAM { return 870 }
81 if makeup_kind == NX_MAKEUP_SMOKEY_BOLD { return 614 }
82 if makeup_kind == NX_MAKEUP_NATURAL { return 614 }
83 return 256
84 }
85 if location == NX_LOC_OFFICE {
86 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return NX_MAGIC_1024 }
87 if makeup_kind == NX_MAKEUP_NATURAL { return 870 }
88 if makeup_kind == NX_MAKEUP_GLAM { return 410 }
89 return 102
90 }
91 if location == NX_LOC_STUDIO {
92 // Fashion / photography studio — anything goes
93 if makeup_kind == NX_MAKEUP_GLAM { return NX_MAGIC_1024 }
94 if makeup_kind == NX_MAKEUP_STAGE_AVANT { return NX_MAGIC_1024 }
95 if makeup_kind == NX_MAKEUP_SMOKEY_BOLD { return 870 }
96 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return 768 }
97 return 410
98 }
99 if location == NX_LOC_BEACH {
100 if makeup_kind == NX_MAKEUP_NATURAL { return NX_MAGIC_1024 }
101 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return 870 }
102 return 256
103 }
104 if location == NX_LOC_POOL {
105 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return NX_MAGIC_1024 }
106 if makeup_kind == NX_MAKEUP_NATURAL { return 768 }
107 return 200
108 }
109 if location == NX_LOC_OUTDOOR {
110 if makeup_kind == NX_MAKEUP_NATURAL { return NX_MAGIC_1024 }
111 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return 768 }
112 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return 717 }
113 return 410
114 }
115 if location == NX_LOC_KITCHEN {
116 if makeup_kind == NX_MAKEUP_NATURAL { return NX_MAGIC_1024 }
117 if makeup_kind == NX_MAKEUP_SOFT_GLAM { return 717 }
118 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return 870 }
119 return 410
120 }
121 if location == NX_LOC_BATHROOM {
122 if makeup_kind == NX_MAKEUP_NO_MAKEUP { return NX_MAGIC_1024 }
123 if makeup_kind == NX_MAKEUP_NATURAL { return 870 }
124 return 410
125 }
126 return 614
127}
128
129// Score makeup: declared vs measured + scene appropriateness.
130func nx_makeup_style_score(declared_kind: i64, measured_kind: i64,
131 location: i64, result: *i64) -> i64 {
132 var i: i64 = 0
133 while i < NX_MAKEUP_RES_FIELDS { result[i] = 0; i = i + 1 }
134
135 result[NX_MAKEUP_RES_DECLARED] = declared_kind
136 result[NX_MAKEUP_RES_MEASURED] = measured_kind
137
138 let approp: i64 = nx_makeup_scene_score(location, measured_kind)
139 result[NX_MAKEUP_RES_APPROP_Q10] = approp
140
141 var diff: i64 = declared_kind - measured_kind
142 if diff < 0 { diff = -diff }
143 var match_score: i64 = NX_MAGIC_1024 - diff * 205 // each rank away costs ~20%
144 if match_score < 0 { match_score = 0 }
145 result[NX_MAKEUP_RES_MATCH_Q10] = match_score
146
147 var verdict: i64 = NX_MAKEUP_V_INAPPROPRIATE
148 if approp >= 410 { verdict = NX_MAKEUP_V_MISMATCHED }
149 if approp >= 614 { verdict = NX_MAKEUP_V_ACCEPTABLE }
150 if approp >= 819 { if match_score >= 614 { verdict = NX_MAKEUP_V_APPROPRIATE } }
151 result[NX_MAKEUP_RES_VERDICT] = verdict
152 return 0
153}