code wiki / (root) / nx_module_registry.nx

nx_module_registry.nx source

↩ module page · 279 lines · 11156 B

1// nx_module_registry.nx -- modular stdlib backbone. 2// 3// module: nishi-core.install.module_registry 4// depends: nishi-core.io.csv, nishi-core.io.syscalls 5// disk_kb: 8 6// capability: CORE_SYSCALLS 7// 8// license_tier: PUBLIC_NISHI_SUBSTRATE 9// genealogy_id: debian_apt_package_dependency_resolution + 10// rust_cargo_feature_flags + 11// python_pep_440_optional_dependencies + 12// freebsd_pkg_sets + 13// nishi_modular_stdlib_opt_in_cardinal_2026 14// 15// Per cardinal [[feedback-modular-stdlib-opt-in-at-install-time]]: 16// Nishi family substrate is NOT a monolithic stdlib. Each `.nx` 17// file declares MODULE METADATA at the top of the file (the header 18// comment block above this one is the canonical shape). This 19// primitive READS the module manifest, resolves capability-tag 20// selections + transitive dependencies, and reports the disk- 21// footprint of any install configuration. 22// 23// User experience: 24// 25// $ nishi install --capability greenhouse,iot 26// Resolving 47 modules + 12 transitive deps. 27// Total disk: 14.2 MB (3.1 MB compressed). 28// Confirm? [y/N]: 29// 30// ===== Module manifest record shape =============================== 31// 32// Each module is one record in nishi-core/modules/manifest.jsonl: 33// 34// { "module": "nishi-greenhouse.crop.potato", 35// "path": "nishi-greenhouse/runtime/nx_crop_potato.nx", 36// "version": "0.1.0", 37// "capabilities": ["GREENHOUSE"], 38// "depends": [ 39// "nishi-core.math.q10", 40// "nishi-core.math.exp", 41// "nishi-greenhouse.eq.potato_aero_tower" 42// ], 43// "disk_bytes": 12288, 44// "license_tier": "PUBLIC_NISHI_SUBSTRATE", 45// "genealogy_id": "stoner_1983_nasa_celss_aeroponic_potato", 46// "stability": "BETA" // ALPHA | BETA | STABLE | DEPRECATED 47// } 48// 49// nishi-library generates the manifest via `nishi-library/scripts/ 50// build_module_manifest.py` which scans every `.nx` file's header 51// comment block + computes disk_bytes from filesystem. 52 53// nx_safety_envelope: 54// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 55// sil_target: SIL1 56// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 57// verdict: NOT_YET_EVALUATED 58 59import "nx_syscalls.nx" 60 61// ===== ModuleCapability sealed enum =============================== 62 63const NX_CAP_KERNEL: i64 = 1 64const NX_CAP_BROWSER: i64 = 2 65const NX_CAP_COMMS: i64 = 3 66const NX_CAP_IOT: i64 = 4 67const NX_CAP_GREENHOUSE: i64 = 5 68const NX_CAP_SEEDBANK: i64 = 6 69const NX_CAP_GAME_ENGINE: i64 = 7 70const NX_CAP_MARKETPLACE: i64 = 8 71const NX_CAP_STORAGE: i64 = 9 72const NX_CAP_CRYPTO: i64 = 10 73const NX_CAP_ML: i64 = 11 74const NX_CAP_COMPILER: i64 = 12 75const NX_CAP_BENCH: i64 = 13 76const NX_CAP_CORE_MATH: i64 = 14 77const NX_CAP_CORE_NET: i64 = 15 78const NX_CAP_CORE_SYSCALLS: i64 = 16 79const NX_CAP_CORE_IO: i64 = 17 80const NX_CAP_CURRICULUM: i64 = 18 // game-curriculum modules (Pillar replenisher) 81const NX_CAP_REGULATORY: i64 = 19 // state-law + tax + KYC routers 82const NX_CAP_PROCGEN: i64 = 20 // causal-growth + biome + procgen substrate 83 84func nx_cap_name(c: i64) -> *u8 { 85 if c == NX_CAP_KERNEL { return "KERNEL" } 86 if c == NX_CAP_BROWSER { return "BROWSER" } 87 if c == NX_CAP_COMMS { return "COMMS" } 88 if c == NX_CAP_IOT { return "IOT" } 89 if c == NX_CAP_GREENHOUSE { return "GREENHOUSE" } 90 if c == NX_CAP_SEEDBANK { return "SEEDBANK" } 91 if c == NX_CAP_GAME_ENGINE { return "GAME_ENGINE" } 92 if c == NX_CAP_MARKETPLACE { return "MARKETPLACE" } 93 if c == NX_CAP_STORAGE { return "STORAGE" } 94 if c == NX_CAP_CRYPTO { return "CRYPTO" } 95 if c == NX_CAP_ML { return "ML" } 96 if c == NX_CAP_COMPILER { return "COMPILER" } 97 if c == NX_CAP_BENCH { return "BENCH" } 98 if c == NX_CAP_CORE_MATH { return "CORE_MATH" } 99 if c == NX_CAP_CORE_NET { return "CORE_NET" } 100 if c == NX_CAP_CORE_SYSCALLS { return "CORE_SYSCALLS" } 101 if c == NX_CAP_CORE_IO { return "CORE_IO" } 102 if c == NX_CAP_CURRICULUM { return "CURRICULUM" } 103 if c == NX_CAP_REGULATORY { return "REGULATORY" } 104 if c == NX_CAP_PROCGEN { return "PROCGEN" } 105 return "UNKNOWN" 106} 107 108// ===== Stability tier sealed enum ================================= 109 110const NX_STABILITY_ALPHA: i64 = 1 // unstable; may change/disappear 111const NX_STABILITY_BETA: i64 = 2 // mostly stable; minor breaks possible 112const NX_STABILITY_STABLE: i64 = 3 // API frozen per Cardinal 19 113const NX_STABILITY_DEPRECATED: i64 = 4 // scheduled for removal; alternative exists 114 115func nx_stability_name(s: i64) -> *u8 { 116 if s == NX_STABILITY_ALPHA { return "ALPHA" } 117 if s == NX_STABILITY_BETA { return "BETA" } 118 if s == NX_STABILITY_STABLE { return "STABLE" } 119 if s == NX_STABILITY_DEPRECATED { return "DEPRECATED" } 120 return "UNKNOWN" 121} 122 123// ===== Module record struct ======================================= 124// 125// One row per installable module. Read from manifest.jsonl at 126// startup. Maximum module-name string length is 128 bytes. 127 128struct ModuleRecord { 129 module_hk: i64, 130 module_name_ptr: *u8, // e.g. "nishi-greenhouse.crop.potato" 131 path_ptr: *u8, // relative file path 132 version_major: i64, 133 version_minor: i64, 134 version_patch: i64, 135 capability_bitmask: i64, // bits 1..20 = NX_CAP_* 136 depends_count: i64, 137 depends_ptr: *u8, // pointer to flat-buffer of dep names 138 disk_bytes: i64, 139 stability: i64, 140 license_tier_id: i64, 141 is_installed: i64, 142} 143 144const NX_MODULE_RECORD_BYTES: i64 = 96 // 12 fields * 8 bytes 145 146// ===== Capability-bitmask helpers ================================= 147 148func nx_cap_bitmask_has(bitmask: i64, capability: i64) -> i64 { 149 let bit: i64 = 1 << (capability - 1) 150 if (bitmask & bit) != 0 { return 1 } 151 return 0 152} 153 154func nx_cap_bitmask_set(bitmask: i64, capability: i64) -> i64 { 155 let bit: i64 = 1 << (capability - 1) 156 return bitmask | bit 157} 158 159// ===== Install-resolution verdict ================================= 160 161const NX_INSTALL_OK: i64 = 1 162const NX_INSTALL_MISSING_DEPENDENCY: i64 = 2 // user excluded a transitive dep 163const NX_INSTALL_CIRCULAR_DEPENDENCY: i64 = 3 // manifest data error 164const NX_INSTALL_UNKNOWN_CAPABILITY: i64 = 4 // typo'd capability flag 165const NX_INSTALL_DISK_BUDGET_EXCEEDED: i64 = 5 // user --max-disk-mb set 166 167func nx_install_verdict_name(v: i64) -> *u8 { 168 if v == NX_INSTALL_OK { return "OK" } 169 if v == NX_INSTALL_MISSING_DEPENDENCY { return "MISSING_DEPENDENCY" } 170 if v == NX_INSTALL_CIRCULAR_DEPENDENCY { return "CIRCULAR_DEPENDENCY" } 171 if v == NX_INSTALL_UNKNOWN_CAPABILITY { return "UNKNOWN_CAPABILITY" } 172 if v == NX_INSTALL_DISK_BUDGET_EXCEEDED { return "DISK_BUDGET_EXCEEDED" } 173 return "UNKNOWN" 174} 175 176// ===== InstallPlan struct ========================================= 177 178struct InstallPlan { 179 plan_hk: i64, 180 requested_capabilities: i64, // bitmask of NX_CAP_* 181 selected_module_count: i64, 182 transitive_dep_count: i64, 183 total_disk_bytes: i64, 184 verdict: i64, // NX_INSTALL_* 185 missing_dep_name_ptr: *u8, // first missing dep if any 186} 187 188const NX_INSTALL_PLAN_BYTES: i64 = 56 // 7 fields * 8 bytes 189 190func nx_install_plan_new(requested_capabilities: i64) -> *InstallPlan { 191 let raw: *u8 = sys_mmap(NX_INSTALL_PLAN_BYTES) 192 let p: *InstallPlan = raw as *InstallPlan 193 p.plan_hk = 0 194 p.requested_capabilities = requested_capabilities 195 p.selected_module_count = 0 196 p.transitive_dep_count = 0 197 p.total_disk_bytes = 0 198 p.verdict = 0 199 p.missing_dep_name_ptr = 0 as *u8 200 return p 201} 202 203// ===== Per-module install decision ================================ 204// 205// Given a module record + the user's requested capability bitmask, 206// return 1 if the module is INCLUDED in the install, 0 if not. 207// Inclusion criteria: 208// - Module has at least one capability matching the requested mask, OR 209// - Module is a transitive dependency of an included module 210// (transitive-dep walk is the caller's job; this primitive answers 211// the "direct match" question) 212 213func nx_module_direct_match(record: *ModuleRecord, requested_capabilities: i64) -> i64 { 214 if (record.capability_bitmask & requested_capabilities) != 0 { return 1 } 215 return 0 216} 217 218// ===== Disk-budget aggregator ===================================== 219// 220// Walks an array of selected modules + sums disk_bytes. Bounded 221// per [[feedback-bounded-loop-discipline-jpl-rule-2]]. 222 223const NX_MODULE_MAX_PER_INSTALL: i64 = 4096 224 225func nx_install_sum_disk_bytes(modules: **ModuleRecord, n_modules: i64) -> i64 { 226 if n_modules <= 0 { return 0 } 227 if n_modules > NX_MODULE_MAX_PER_INSTALL { return -1 } 228 var total: i64 = 0 229 var i: i64 = 0 230 var iter: i64 = 0 231 var verdict: i64 = 0 232 while verdict == 0 && iter < NX_MODULE_MAX_PER_INSTALL { 233 if i >= n_modules { verdict = 1 } 234 if verdict == 0 { 235 let m: *ModuleRecord = modules[i] 236 total = total + m.disk_bytes 237 i = i + 1 238 } 239 iter = iter + 1 240 } 241 return total 242} 243 244// ===== Capability-tag parsing ===================================== 245// 246// CLI argument "greenhouse,iot,seedbank" -> bitmask. Caller passes 247// each capability ID separately after parsing the CSV string. 248 249func nx_capability_string_to_id(name: *u8) -> i64 { 250 // Caller compares against the known names; substrate doesn't ship 251 // a string-table here because nx_string equality is a separate 252 // primitive (substrate composes nx_string against this). 253 // v1 returns 0 (unknown); the install CLI does the string match 254 // and passes the resolved ID. Future v1.1: integrate nx_string 255 // table directly when it's stable. 256 return 0 257} 258 259// ===== Sovereign distribution metadata ============================ 260// 261// Per [[nishi-stack-is-bits-up-sovereign-always-no-third-party]]: 262// no apt / npm / pip — modules are distributed via Nishi-sovereign 263// channels. Default channel: HTTPS over Nishi sovereign DNS. 264// Alternative: BitTorrent magnet, IPFS CID, local NAS rsync. 265 266const NX_DIST_CHANNEL_HTTPS: i64 = 1 267const NX_DIST_CHANNEL_BITTORRENT: i64 = 2 268const NX_DIST_CHANNEL_IPFS: i64 = 3 269const NX_DIST_CHANNEL_LOCAL_RSYNC: i64 = 4 270const NX_DIST_CHANNEL_USB_OFFLINE: i64 = 5 // air-gapped install 271 272func nx_dist_channel_name(c: i64) -> *u8 { 273 if c == NX_DIST_CHANNEL_HTTPS { return "HTTPS" } 274 if c == NX_DIST_CHANNEL_BITTORRENT { return "BITTORRENT" } 275 if c == NX_DIST_CHANNEL_IPFS { return "IPFS" } 276 if c == NX_DIST_CHANNEL_LOCAL_RSYNC { return "LOCAL_RSYNC" } 277 if c == NX_DIST_CHANNEL_USB_OFFLINE { return "USB_OFFLINE" } 278 return "UNKNOWN" 279}