nx_gatherer.nx source
↩ module page · 296 lines · 10215 B
1// nx_gatherer.nx -- inward-axis compounding primitive.
2//
3// Per [[feedback-hunter-gatherer-meta-primitives-outward-inward-axes]]
4// CARDINAL: "nx_gatherer (inward — iteratively compound substrate ROI
5// like farmer compounds land/crops/animals/machinery)."
6//
7// THE FARMER PRIMITIVE per user 2026-05-17: "gathering as the
8// iterative process that the farmer does of improving their land
9// and crops and animals and machinery to get a higher and higher
10// roi." Gatherer is the INWARD arm: every session adds yield to
11// substrate fields (new primitive shipped, smoke coverage axis +1,
12// ms saved on a hot path, false-positive eliminated). Yields
13// accumulate across sessions like compound interest on land.
14//
15// Composes:
16// nx_hunter -- outward-axis dual; gatherer+hunter together
17// form the session-audit gate
18// nx_gather_journal -- append-only event log of yields
19// nx_metabolism -- ms-saved yields measured against per-site
20// cycle counts
21// nx_palette -- bytes-shaved yields measured against pre/post
22// packing densities
23// nx_pamp / nx_pamp_meta -- false-positive-eliminated yields
24// measured against pre/post detection rates
25//
26// V1 ships:
27// - sealed enum NxGatherFieldKind (5 from cardinal:
28// PRIMITIVE / ISA / SMOKE / METRIC / COMPOST)
29// - sealed enum NxGatherYieldKind (4 from cardinal:
30// MS_SAVED / BYTES_SHAVED / FALSE_POSITIVE_ELIMINATED / COVERAGE_AXIS_PLUS_ONE)
31// - struct NxGatherField + NxGatherer container
32// - sow_field/harvest_yield verbs
33// - cumulative-yield queries (sum across the fields tilled)
34//
35// Gap list (V1 honest perf verdict):
36// - per-season rotation (weekly/monthly/quarterly fallow review)
37// queued -- V1 is one continuous season
38// - compost recycling (prior-arc knowledge informing current)
39// is a tag/kind in V1; deeper compose with archived hunts
40// is V2 (nx_gather_compost specialized primitive)
41// - no per-field decay model (sown fields don't auto-archive)
42//
43// genealogy_id: cardinal_2026-05-17_hunter_gatherer_meta_primitives +
44// regenerative_agriculture_compound_interest
45// lineage_id: substrate_gatherer_v1
46//
47// nx_safety_envelope:
48// intended_use: "Inward-axis compounding of substrate yield;
49// farmer-discipline ROI accumulation across
50// sessions"
51// sil_target: SIL1
52// evidence: [append_only_field_log,
53// cumulative_yield_observable]
54// verdict: NOT_YET_EVALUATED
55
56import "nx_syscalls.nx"
57import "nx_tier.nx"
58
59// ===== Sealed enum: NxGatherFieldKind =============================
60
61const NX_GFK_PRIMITIVE: nx_int = 0 // new substrate primitive shipped
62const NX_GFK_ISA: nx_int = 1 // new ISA backend / codegen target
63const NX_GFK_SMOKE: nx_int = 2 // new smoke test added
64const NX_GFK_METRIC: nx_int = 3 // new measurable metric exposed
65const NX_GFK_COMPOST: nx_int = 4 // prior-arc knowledge applied here
66const NX_GFK_N_KINDS: nx_int = 5
67
68// ===== Sealed enum: NxGatherYieldKind =============================
69
70const NX_GYK_MS_SAVED: nx_int = 0
71const NX_GYK_BYTES_SHAVED: nx_int = 1
72const NX_GYK_FALSE_POSITIVE_ELIMINATED: nx_int = 2
73const NX_GYK_COVERAGE_AXIS_PLUS_ONE: nx_int = 3
74const NX_GYK_N_KINDS: nx_int = 4
75
76// ===== Sealed enum: NxGathererVerdict =============================
77
78const NX_GATHERER_OK: nx_int = 0
79const NX_GATHERER_ERR_FULL: nx_int = 1
80const NX_GATHERER_ERR_BAD_KIND: nx_int = 2
81const NX_GATHERER_ERR_NOT_FOUND: nx_int = 3
82
83// ===== Struct: NxGatherField ======================================
84
85struct NxGatherField {
86 field_id: nx_int,
87 kind: nx_int,
88 content_hash: nx_size,
89 yield_ms_saved: nx_size,
90 yield_bytes_shaved: nx_size,
91 yield_fp_eliminated: nx_int,
92 yield_coverage_delta: nx_int,
93 sown_us: nx_size,
94 last_harvest_us: nx_size,
95}
96
97// ===== Struct: NxGatherer =========================================
98
99struct NxGatherer {
100 fields: *NxGatherField,
101 capacity: nx_size,
102 head: nx_size,
103 count: nx_size,
104}
105
106const NX_GATHER_FIELD_BYTES: nx_size = 72
107
108// ===== Validators ================================================
109
110func nx_gfk_is_valid(k: nx_int) -> nx_int {
111 if k < 0 { return 0 }
112 if k >= NX_GFK_N_KINDS { return 0 }
113 return 1
114}
115
116func nx_gyk_is_valid(k: nx_int) -> nx_int {
117 if k < 0 { return 0 }
118 if k >= NX_GYK_N_KINDS { return 0 }
119 return 1
120}
121
122// ===== nx_gatherer_new ============================================
123
124func nx_gatherer_new(capacity: nx_size) -> *NxGatherer {
125 let g: *NxGatherer = (sys_mmap(32)) as *NxGatherer
126 let bytes: nx_size = capacity * NX_GATHER_FIELD_BYTES
127 g.fields = (sys_mmap(bytes)) as *NxGatherField
128 g.capacity = capacity
129 g.head = 0
130 g.count = 0
131 return g
132}
133
134// ===== _gatherer_at ===============================================
135
136func _gatherer_at(g: *NxGatherer, idx: nx_size) -> *NxGatherField {
137 return (g.fields as i64 + (idx as i64) * NX_GATHER_FIELD_BYTES) as *NxGatherField
138}
139
140// ===== _gatherer_find =============================================
141
142func _gatherer_find(g: *NxGatherer, field_id: nx_int) -> nx_int {
143 var i: nx_size = 0
144 while i < g.count {
145 let f: *NxGatherField = _gatherer_at(g, i)
146 if f.field_id == field_id { return i as i64 }
147 i = i + 1
148 }
149 return -1
150}
151
152// ===== nx_gatherer_sow ============================================
153//
154// Begin tracking a new field. Returns the index, or -1 if full /
155// bad kind / duplicate. Yields start at zero and accumulate via
156// nx_gatherer_harvest.
157
158func nx_gatherer_sow(g: *NxGatherer,
159 field_id: nx_int,
160 kind: nx_int,
161 content_hash: nx_size,
162 now_us: nx_size) -> nx_int {
163 if nx_gfk_is_valid(kind) == 0 { return -1 }
164 if _gatherer_find(g, field_id) >= 0 { return -1 }
165 if g.count >= g.capacity { return -1 }
166 let f: *NxGatherField = _gatherer_at(g, g.head)
167 f.field_id = field_id
168 f.kind = kind
169 f.content_hash = content_hash
170 f.yield_ms_saved = 0
171 f.yield_bytes_shaved = 0
172 f.yield_fp_eliminated = 0
173 f.yield_coverage_delta = 0
174 f.sown_us = now_us
175 f.last_harvest_us = now_us
176 g.head = g.head + 1
177 if g.head >= g.capacity { g.head = 0 }
178 g.count = g.count + 1
179 return (g.count - 1) as i64
180}
181
182// ===== nx_gatherer_harvest ========================================
183//
184// Add a yield to an existing field. yield_kind selects which yield
185// counter to bump; value is added (not assigned) so harvests
186// compound across sessions on the same field.
187
188func nx_gatherer_harvest(g: *NxGatherer,
189 field_id: nx_int,
190 yield_kind: nx_int,
191 value: nx_size,
192 now_us: nx_size) -> nx_int {
193 if nx_gyk_is_valid(yield_kind) == 0 { return NX_GATHERER_ERR_BAD_KIND }
194 let idx: nx_int = _gatherer_find(g, field_id)
195 if idx < 0 { return NX_GATHERER_ERR_NOT_FOUND }
196 let f: *NxGatherField = _gatherer_at(g, idx as nx_size)
197 if yield_kind == NX_GYK_MS_SAVED {
198 f.yield_ms_saved = f.yield_ms_saved + value
199 }
200 if yield_kind == NX_GYK_BYTES_SHAVED {
201 f.yield_bytes_shaved = f.yield_bytes_shaved + value
202 }
203 if yield_kind == NX_GYK_FALSE_POSITIVE_ELIMINATED {
204 f.yield_fp_eliminated = f.yield_fp_eliminated + (value as i64)
205 }
206 if yield_kind == NX_GYK_COVERAGE_AXIS_PLUS_ONE {
207 f.yield_coverage_delta = f.yield_coverage_delta + (value as i64)
208 }
209 f.last_harvest_us = now_us
210 return NX_GATHERER_OK
211}
212
213// ===== nx_gatherer_total_ms_saved =================================
214//
215// Sum yield_ms_saved across all fields. The farmer compound result:
216// total ms saved across the substrate's lifetime.
217
218func nx_gatherer_total_ms_saved(g: *NxGatherer) -> nx_size {
219 var total: nx_size = 0
220 var i: nx_size = 0
221 while i < g.count {
222 let f: *NxGatherField = _gatherer_at(g, i)
223 total = total + f.yield_ms_saved
224 i = i + 1
225 }
226 return total
227}
228
229// ===== nx_gatherer_total_bytes_shaved =============================
230
231func nx_gatherer_total_bytes_shaved(g: *NxGatherer) -> nx_size {
232 var total: nx_size = 0
233 var i: nx_size = 0
234 while i < g.count {
235 let f: *NxGatherField = _gatherer_at(g, i)
236 total = total + f.yield_bytes_shaved
237 i = i + 1
238 }
239 return total
240}
241
242// ===== nx_gatherer_total_fp_eliminated ============================
243
244func nx_gatherer_total_fp_eliminated(g: *NxGatherer) -> nx_int {
245 var total: nx_int = 0
246 var i: nx_size = 0
247 while i < g.count {
248 let f: *NxGatherField = _gatherer_at(g, i)
249 total = total + f.yield_fp_eliminated
250 i = i + 1
251 }
252 return total
253}
254
255// ===== nx_gatherer_total_coverage_delta ===========================
256
257func nx_gatherer_total_coverage_delta(g: *NxGatherer) -> nx_int {
258 var total: nx_int = 0
259 var i: nx_size = 0
260 while i < g.count {
261 let f: *NxGatherField = _gatherer_at(g, i)
262 total = total + f.yield_coverage_delta
263 i = i + 1
264 }
265 return total
266}
267
268// ===== nx_gatherer_count_by_kind ==================================
269
270func nx_gatherer_count_by_kind(g: *NxGatherer, kind: nx_int) -> nx_int {
271 var hits: nx_int = 0
272 var i: nx_size = 0
273 while i < g.count {
274 let f: *NxGatherField = _gatherer_at(g, i)
275 if f.kind == kind { hits = hits + 1 }
276 i = i + 1
277 }
278 return hits
279}
280
281// ===== nx_gatherer_count ==========================================
282
283func nx_gatherer_count(g: *NxGatherer) -> nx_size {
284 return g.count
285}
286
287// ===== nx_gatherer_session_emitted ================================
288//
289// Predicate: did at least one gather event occur in this gatherer?
290// True if any field has been sown. Used by the session-audit gate
291// to confirm gather_count >= 1.
292
293func nx_gatherer_session_emitted(g: *NxGatherer) -> nx_int {
294 if g.count > 0 { return 1 }
295 return 0
296}