nx_edgar_submissions.nx source
↩ module page · 160 lines · 8357 B
1// nx_edgar_submissions.nx -- THE PERSON BINDING: a filer CIK -> what that filer actually IS.
2//
3// WHY THIS EXISTS: nx_edgar_lib extracts issuer-keyed FACTS (Apple, StockholdersEquity, a value).
4// Nothing mapped a PERSON to the corpora holding their work -- measured 2026-08-15, nx_capsearch over
5// 1,092 registered tools for "career filings company executive officer history" returned nothing
6// relevant. SEC assigns a CIK to INDIVIDUALS as well as companies, and
7// data.sec.gov/submissions/CIK##########.json enumerates that filer's own history. This is the first
8// rung of that binding: name the filer and classify the CIK from its FORM DISTRIBUTION.
9//
10// THE DISCRIMINATOR IS STRUCTURAL, NOT A TUNED THRESHOLD: Forms 3/4/5 are filed BY an insider ABOUT
11// an issuer -- a company does not file a Form 4 about itself -- while 10-K/10-Q are filed BY the
12// issuer. Those form codes are SEC SPEC CONSTANTS (like a DNS label limit), not policy anyone tunes.
13// VERDICT HAS THREE STATES and abstains rather than guessing: PERSON (insider forms, no issuer forms),
14// ISSUER (issuer forms, no insider forms), UNDETERMINED (both or neither). A two-state classifier here
15// would have to invent a ratio, and an invented ratio is a magic number wearing a verdict's name.
16//
17// Composes, never re-implements: edgar_ua_header (declared identity, fail-closed), edgar_arr_bounds,
18// edgar_arr_count_val, edgar_str_first -- all from nx_edgar_lib. license_tier: ORIGINAL
19import "nx_syscalls.nx"
20import "nx_x509_trust_store.nx"
21import "nx_trust_store_load_from_certdata.nx"
22import "nx_https_fetch_follow.nx"
23import "nx_edgar_lib.nx"
24
25const ES_CAP: i64 = 16777216 // submissions JSON for a long-lived filer runs to a few MB
26const ES_TRUST: i64 = 4194304
27const ES_CIKDIGITS: i64 = 10 // SEC pads CIK to exactly 10 digits in the submissions path
28// SEC's filings.recent window holds at most this many entries. MEASURED: Apple returned exactly 1000,
29// which is the CAP, not the population. A cap reported as a total is a measurement nobody knows is
30// partial -- so the count is named forms_in_recent and carries an explicit capped flag beside it.
31// Older filings live in filings.files[] (paged archives); reading those is the next rung, not a guess.
32const ES_RECENT_CAP: i64 = 1000
33
34func sp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
35func sn(v: i64) -> i64 {
36 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
37 var m: i64 = v
38 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
39 let d: *u8 = sys_mmap(24); var k: i64 = 0
40 while m > 0 { d[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
41 let o: *u8 = sys_mmap(24); var i: i64 = 0
42 while i < k { o[i] = d[k - 1 - i]; i = i + 1 }
43 sys_write(1, o, k)
44 return 0
45}
46func scat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } return off + i }
47func slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
48
49// left-pad the caller's CIK to ES_CIKDIGITS. REFUSES a non-digit or an over-long CIK rather than
50// truncating: a silently shortened CIK is a VALID-LOOKING request for a DIFFERENT filer.
51func es_pad_cik(src: *u8, out: *u8) -> i64 {
52 let n: i64 = slen(src)
53 if n <= 0 { return 0 }
54 if n > ES_CIKDIGITS { return 0 }
55 var i: i64 = 0
56 while i < n { let c: i64 = src[i] as i64; if c < 48 { return 0 } if c > 57 { return 0 } i = i + 1 }
57 let pad: i64 = ES_CIKDIGITS - n
58 var o: i64 = 0
59 while o < pad { out[o] = 48 as u8; o = o + 1 }
60 var j: i64 = 0
61 while j < n { out[pad + j] = src[j]; j = j + 1 }
62 out[ES_CIKDIGITS] = 0 as u8
63 return ES_CIKDIGITS
64}
65
66func main(argc: i64, argv: *i64) -> i64 {
67 if argc < 2 { sp("usage: nx_edgar_submissions <CIK> (person or company; 1-10 digits)\n" as *u8); return 2 }
68 let cik: *u8 = sys_mmap(32)
69 if es_pad_cik(argv[1] as *u8, cik) <= 0 { sp("REFUSED: CIK must be 1-10 digits (never truncated -- a short CIK is a DIFFERENT filer)\n" as *u8); return 2 }
70
71 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, ES_TRUST)
72 if r <= 0 { sp("certdata load failed\n" as *u8); return 1 }
73 let store: *TrustStore = r as *TrustStore
74
75 let url: *u8 = sys_mmap(256)
76 var o: i64 = scat(url, 0, "https://data.sec.gov/submissions/CIK" as *u8)
77 o = scat(url, o, cik)
78 o = scat(url, o, ".json" as *u8)
79 url[o] = 0 as u8
80
81 let xh: *u8 = sys_mmap(320)
82 let xo: i64 = edgar_ua_header(xh, 320)
83 if xo <= 0 { sp("NO UA DECLARED (knowledge/fetch_identity.conf absent) -- sending none, never a placeholder\n" as *u8) }
84
85 let buf: *u8 = sys_mmap(ES_CAP)
86 let status: *i64 = sys_mmap(16) as *i64
87 let n: i64 = nx_https_fetch_follow_hdr_best(url, store, buf, ES_CAP, 6, status, xh, xo)
88 sp("url=" as *u8); sp(url); sp("\n status=" as *u8); sn(status[0]); sp(" bytes=" as *u8); sn(n); sp("\n" as *u8)
89 if n <= 0 { sp("FETCH-FAIL (no body) -- reporting nothing rather than a fabricated filer\n" as *u8); return 1 }
90
91 let nm: *u8 = sys_mmap(256)
92 let nml: i64 = edgar_str_first(buf, n, "name" as *u8, nm)
93 if nml <= 0 { nm[0] = 0 as u8 }
94
95 let box: *i64 = sys_mmap(32) as *i64
96 let okb: i64 = edgar_arr_bounds(buf, n, "form" as *u8, box)
97 if okb == 0 { sp("NO form[] ARRAY -- cannot classify; reporting UNDETERMINED rather than guessing\n" as *u8) }
98
99 var f3: i64 = 0
100 var f4: i64 = 0
101 var f5: i64 = 0
102 var k10: i64 = 0
103 var q10: i64 = 0
104 var elems: i64 = 0
105 if okb == 1 {
106 let s: i64 = box[0]
107 let e: i64 = box[1]
108 f3 = edgar_arr_count_val(buf, s, e, "3" as *u8)
109 f4 = edgar_arr_count_val(buf, s, e, "4" as *u8)
110 f5 = edgar_arr_count_val(buf, s, e, "5" as *u8)
111 k10 = edgar_arr_count_val(buf, s, e, "10-K" as *u8)
112 q10 = edgar_arr_count_val(buf, s, e, "10-Q" as *u8)
113 // element count = quote pairs in the span. Printed so the histogram can be RECONCILED against
114 // the population instead of being trusted: counts that do not sum are a leak, not a detail.
115 var qc: i64 = 0
116 var i2: i64 = s
117 while i2 < e { if (buf[i2] as i64) == 34 { qc = qc + 1 } i2 = i2 + 1 }
118 elems = qc / 2
119 }
120 let insider: i64 = f3 + f4 + f5
121 let issuer: i64 = k10 + q10
122 // MEASURED 2026-08-16 AND IT REFUTED MY OWN DISCRIMINATOR: Apple Inc. (CIK 320193) returns
123 // insider_forms=599. The submissions feed lists filings where this CIK is the SUBJECT, so a
124 // company's feed is FULL of Forms 3/4/5 filed by its insiders ABOUT it. The form histogram cannot
125 // separate person from company, and the comment above claiming it could was wrong.
126 // The real structural signal: an ISSUER has registrant identity fields (SIC classification, EIN,
127 // exchange tickers); a natural person has none. Those are reported here as MEASURED VALUES rather
128 // than asserted, so the next reader can see what the discriminator actually rests on.
129 let sic: *u8 = sys_mmap(256)
130 let sicl: i64 = edgar_str_first(buf, n, "sicDescription" as *u8, sic)
131 if sicl <= 0 { sic[0] = 0 as u8 }
132 let ein: *u8 = sys_mmap(64)
133 let einl: i64 = edgar_str_first(buf, n, "ein" as *u8, ein)
134 if einl <= 0 { ein[0] = 0 as u8 }
135
136 sp("{\"tool\":\"nx_edgar_submissions\",\"cik\":\"" as *u8); sp(cik)
137 sp("\",\"name\":\"" as *u8); sp(nm)
138 sp("\",\"forms_in_recent\":" as *u8); sn(elems)
139 sp(",\"recent_window_capped\":" as *u8)
140 if elems >= ES_RECENT_CAP { sn(1) }
141 if elems < ES_RECENT_CAP { sn(0) }
142 sp(",\"form_3\":" as *u8); sn(f3)
143 sp(",\"form_4\":" as *u8); sn(f4)
144 sp(",\"form_5\":" as *u8); sn(f5)
145 sp(",\"form_10K\":" as *u8); sn(k10)
146 sp(",\"form_10Q\":" as *u8); sn(q10)
147 sp(",\"insider_forms\":" as *u8); sn(insider)
148 sp(",\"issuer_forms\":" as *u8); sn(issuer)
149 sp(",\"sic\":\"" as *u8); sp(sic)
150 sp("\",\"ein\":\"" as *u8); sp(ein)
151 sp("\",\"kind\":\"" as *u8)
152 var registrant: i64 = 0
153 if sicl > 0 { registrant = 1 }
154 if einl > 0 { registrant = 1 }
155 if registrant == 1 { sp("ISSUER" as *u8) }
156 if registrant == 0 { if insider > 0 { sp("PERSON" as *u8) } }
157 if registrant == 0 { if insider == 0 { sp("UNDETERMINED" as *u8) } }
158 sp("\"}\nEDGAR-SUBMISSIONS-OK\n" as *u8)
159 return 0
160}