nx_facet_classify.nx source
↩ module page · 205 lines · 10093 B
1// nx_facet_classify.nx -- SREACH R2: the bits-up FACET CLASSIFIER.
2//
3// module: nishi-core.search.bench.facet_classify
4// depends: nx_str.nx, nx_source_tier.nx (verified host tables + ci_contains),
5// nx_bench_intent.nx (the 7-facet model constants)
6// capability: CORE_COMPUTE
7//
8// WHY: until this rung, Nishi's re-rank was handed the GOLD facet labels
9// (oracle-from-gold) -- an honest, named leak in the leaderboard. This module
10// derives the facet from URL/HOST/TITLE signals alone, so the reach gate runs
11// end-to-end with NO gold leakage into ranking. The signal classes are GENERIC
12// (path shapes, host classes from the research-verified tier tables, title
13// keywords), not per-document rules -- the gate (nx_facet_gate) measures
14// honest agreement vs gold at a permil bar instead of asserting it.
15//
16// Signal order IS the policy (first match wins; one table per facet, Rule #11):
17// SELF_SOCIAL own-platform profile hosts (instagram/x/threads/onlyfans/...)
18// OFFICIAL_MEDIA first-hand photo/still archives (getty/wikimedia-commons/ap)
19// INTERVIEWS direct-statement signals in title/path (interview/chats/podcast)
20// WORKS the work's own record page (/title/ catalog paths)
21// IDENTITY canonical bio records (wikipedia /wiki/, wikidata, imdb /name/,
22// /person/ catalog paths, kid-encyclopedia)
23// PRESS professional NEWS-press hosts (the tier table's editorial
24// outlets minus aggregator CATALOGS -- TMDB/RottenTomatoes/
25// Fandango are catalogs, not press; lad-mag galleries are
26// derivative media, not reporting)
27// LONGTAIL everything else (net-worth/measurement SEO, fan cuts,
28// wallpapers, community wikis) -- the honest default.
29
30import "fx.nx"
31import "nx_str.nx"
32import "nx_source_tier.nx"
33import "nx_bench_intent.nx"
34
35// host-BOUNDED domain match: dom counts only when the byte before it is '.'
36// or '/' (start of a host label), so "people.com" never matches inside
37// "thefamouspeople.com" (real false-positive caught by the gate 2026-06-10).
38// Case-insensitive; dom must be lowercase.
39func nx_facet_host_has(url: *u8, dom: *u8) -> i64 {
40 let un: i64 = nx_str_len(url)
41 let dn: i64 = nx_str_len(dom)
42 if dn == 0 { return 0 }
43 var i: i64 = 1
44 while i + dn <= un {
45 var j: i64 = 0
46 var ok: i64 = 1
47 while j < dn {
48 if nx_tier_lc(url[i + j] as i64) != (dom[j] as i64) {
49 ok = 0
50 j = dn
51 } else {
52 j = j + 1
53 }
54 }
55 if ok == 1 {
56 let pre: i64 = url[i - 1] as i64
57 if pre == 0x2E { return 1 }
58 if pre == 0x2F { return 1 }
59 }
60 i = i + 1
61 }
62 return 0
63}
64
65// own-platform social profile host?
66func nx_facet_is_social_host(url: *u8) -> i64 {
67 if nx_facet_host_has(url, "instagram.com") == 1 { return 1 }
68 if nx_tier_host_has(url, "://x.com/") == 1 { return 1 }
69 if nx_facet_host_has(url, "twitter.com") == 1 { return 1 }
70 if nx_facet_host_has(url, "threads.com") == 1 { return 1 }
71 if nx_facet_host_has(url, "threads.net") == 1 { return 1 }
72 if nx_facet_host_has(url, "onlyfans.com") == 1 { return 1 }
73 if nx_facet_host_has(url, "tiktok.com") == 1 { return 1 }
74 if nx_facet_host_has(url, "facebook.com") == 1 { return 1 }
75 return 0
76}
77
78// first-hand photo / still archive host?
79func nx_facet_is_media_host(url: *u8) -> i64 {
80 if nx_facet_host_has(url, "gettyimages.com") == 1 { return 1 }
81 if nx_facet_host_has(url, "commons.wikimedia.org") == 1 { return 1 }
82 if nx_facet_host_has(url, "apimages.com") == 1 { return 1 }
83 if nx_facet_host_has(url, "shutterstock.com") == 1 { return 1 }
84 return 0
85}
86
87// direct first-hand-statement signal in title or url path?
88func nx_facet_is_interview(url: *u8, title: *u8) -> i64 {
89 if nx_tier_ci_contains(title, "interview") == 1 { return 1 }
90 if nx_tier_ci_contains(title, "chats") == 1 { return 1 }
91 if nx_tier_ci_contains(title, "podcast") == 1 { return 1 }
92 if nx_tier_ci_contains(url, "/interview") == 1 { return 1 }
93 return 0
94}
95
96// canonical bio-record page?
97func nx_facet_is_identity(url: *u8) -> i64 {
98 if nx_facet_host_has(url, "wikipedia.org") == 1 {
99 if nx_tier_ci_contains(url, "/wiki/") == 1 { return 1 }
100 }
101 if nx_facet_host_has(url, "wikidata.org") == 1 { return 1 }
102 if nx_facet_host_has(url, "imdb.com") == 1 {
103 if nx_tier_ci_contains(url, "/name/") == 1 { return 1 }
104 }
105 if nx_tier_ci_contains(url, "/person/") == 1 { return 1 }
106 if nx_facet_host_has(url, "kiddle.co") == 1 { return 1 }
107 return 0
108}
109
110// professional NEWS-press host (editorial reporting, NOT aggregator catalogs).
111// Subset of the research-verified editorial table in nx_source_tier.nx
112// (2026-05-29): outlets that REPORT -- catalogs (TMDB/RT/BoxOfficeMojo/
113// Fandango/TVGuide) and lad-mag gallery sites (Maxim) classify elsewhere.
114func nx_facet_is_press_host(url: *u8) -> i64 {
115 if nx_facet_host_has(url, "variety.com") == 1 { return 1 }
116 if nx_facet_host_has(url, "hollywoodreporter.com") == 1 { return 1 }
117 if nx_facet_host_has(url, "deadline.com") == 1 { return 1 }
118 if nx_facet_host_has(url, "ew.com") == 1 { return 1 }
119 if nx_facet_host_has(url, "people.com") == 1 { return 1 }
120 if nx_facet_host_has(url, "nytimes.com") == 1 { return 1 }
121 if nx_facet_host_has(url, "vanityfair.com") == 1 { return 1 }
122 if nx_facet_host_has(url, "screenrant.com") == 1 { return 1 }
123 if nx_facet_host_has(url, "collider.com") == 1 { return 1 }
124 if nx_facet_host_has(url, "cbr.com") == 1 { return 1 }
125 if nx_facet_host_has(url, "advocate.com") == 1 { return 1 }
126 if nx_facet_host_has(url, "losangelesblade.com") == 1 { return 1 }
127 if nx_facet_host_has(url, "sbs.com.au") == 1 { return 1 }
128 if nx_facet_host_has(url, "bloody-disgusting.com") == 1 { return 1 }
129 return 0
130}
131
132// (url, title) -> facet id 0..6. First matching signal class wins; the order
133// is the comment block at the top of this file.
134func nx_facet_classify(url: *u8, title: *u8) -> i64 {
135 if nx_facet_is_social_host(url) == 1 { return NX_FACET_SELF_SOCIAL }
136 if nx_facet_is_media_host(url) == 1 { return NX_FACET_OFFICIAL_MEDIA }
137 if nx_facet_is_interview(url, title) == 1 { return NX_FACET_INTERVIEWS }
138 if nx_tier_ci_contains(url, "/title/") == 1 { return NX_FACET_WORKS }
139 if nx_facet_is_identity(url) == 1 { return NX_FACET_IDENTITY }
140 if nx_facet_is_press_host(url) == 1 { return NX_FACET_PRESS }
141 return NX_FACET_LONGTAIL
142}
143
144// facet id -> display name (shared by the gate + leaderboard transparency rows)
145func nx_facet_name(f: i64) -> *u8 {
146 if f == NX_FACET_IDENTITY { return "IDENTITY" }
147 if f == NX_FACET_WORKS { return "WORKS" }
148 if f == NX_FACET_OFFICIAL_MEDIA { return "OFFICIAL_MEDIA" }
149 if f == NX_FACET_INTERVIEWS { return "INTERVIEWS" }
150 if f == NX_FACET_PRESS { return "PRESS" }
151 if f == NX_FACET_SELF_SOCIAL { return "SELF_SOCIAL" }
152 if f == NX_FACET_LONGTAIL { return "LONGTAIL" }
153 return "?"
154}
155
156// ---------------------------------------------------------------------------
157// CONTENT ACCESSIBILITY (operator directive 2026-06-10: "not just first hand --
158// content accessibility, like how Yandex prioritizes media sites or heavy
159// information sites like interviews ... things that help drive engagement").
160//
161// A per-document ENGAGEMENT/INFORMATION-DENSITY value in Q16.16 [0,1]: how
162// much consumable content a click delivers. Facet base table (Rule #11 -- the
163// table IS the policy, one rationale per row) + a media-richness boost from
164// generic title signals. This is a RANKING AXIS fused alongside (never
165// replacing) source tier + facet diversity -- Rule #25: add the axis, don't
166// strip the first-hand feature.
167const NX_CONTENT_MEDIA_BOOST_NUM: i64 = 1 // +1/5 for photo/video-rich titles
168const NX_CONTENT_MEDIA_BOOST_DEN: i64 = 5
169
170func nx_facet_content_base(facet: i64) -> i64 {
171 // interviews: long-form direct statements = the densest engagement payload
172 if facet == NX_FACET_INTERVIEWS { return FX_ONE }
173 // official media: galleries/stills = the Yandex media-site prioritization
174 if facet == NX_FACET_OFFICIAL_MEDIA { return FX_ONE }
175 // identity: canonical records are information-heavy (infobox/structured)
176 if facet == NX_FACET_IDENTITY { return fx_from_frac(9, 10) }
177 // self-social: continuously fresh first-party media feeds
178 if facet == NX_FACET_SELF_SOCIAL { return fx_from_frac(8, 10) }
179 // works: the record of one work -- informative but narrow
180 if facet == NX_FACET_WORKS { return fx_from_frac(7, 10) }
181 // press: one story per page
182 if facet == NX_FACET_PRESS { return fx_from_frac(6, 10) }
183 // longtail/default: thin SEO pages until proven otherwise
184 return fx_from_frac(3, 10)
185}
186
187// (url, title, facet) -> engagement value Q16.16 in [0, 1].
188// Media-richness title signals add a capped boost -- but NEVER for LONGTAIL:
189// "wallpaper"/"photos" on a thin SEO host is bait, not content.
190func nx_facet_content_value(url: *u8, title: *u8, facet: i64) -> i64 {
191 if facet < 0 { return nx_facet_content_base(NX_FACET_LONGTAIL) } // unjudged = thin until proven
192 var v: i64 = nx_facet_content_base(facet)
193 if facet != NX_FACET_LONGTAIL {
194 var media: i64 = 0
195 if nx_tier_ci_contains(title, "photos") == 1 { media = 1 }
196 if nx_tier_ci_contains(title, "pictures") == 1 { media = 1 }
197 if nx_tier_ci_contains(title, "video") == 1 { media = 1 }
198 if nx_tier_ci_contains(title, "gallery") == 1 { media = 1 }
199 if media == 1 {
200 v = v + fx_from_frac(NX_CONTENT_MEDIA_BOOST_NUM, NX_CONTENT_MEDIA_BOOST_DEN)
201 if v > FX_ONE { v = FX_ONE }
202 }
203 }
204 return v
205}