code wiki / (root) / nx_edgar_submissions.nx

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}