code wiki / _hdl_build / nx_reorder_gate.nx

nx_reorder_gate.nx source

↩ module page · 146 lines · 9057 B

1// nx_reorder_gate.nx -- GATE: R-REORDER. The supply-chain management layer that closes the loop: par levels -> 2// low-stock detection -> a shopping list generated from what a meal plan consumed. Proves: T1 par set/get, 3// T2 low-stock detection (qty<par, with correct buy quantity), T3 meal-plan integration (consuming ingredients 4// drops them below par -> onto the list), T4 sovereign shopping-list render, T5 SHIPPED via publisher. 5// license_tier: ORIGINAL 6import "nx_shopping.nx" 7import "nx_pantry.nx" 8import "nx_inventory.nx" 9import "nx_food_science.nx" 10import "nx_publisher.nx" 11import "nx_syscalls.nx" 12import "nx_gate_verdict.nx" 13 14const RO_FOOD: *u8 = "knowledge/store/food-" 15const RO_INV: *u8 = "knowledge/store/inv-" 16const RO_DOM: *u8 = "home" 17const RO_Q: *u8 = "knowledge/publish/shop-queue.tsv" 18const RO_LED: *u8 = "knowledge/publish/shop-ledger.tsv" 19const RO_STG: *u8 = "knowledge/publish/shop-stage" 20const RO_LIVE: *u8 = "knowledge/publish/shop-live" 21const RO_STAGE_FILE: *u8 = "knowledge/staging/shop/list.html" 22const RO_LIVE_FILE: *u8 = "knowledge/publish/shop-live/shopping-list.html" 23 24func g_p(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 25func g_i(v: i64) -> i64 { 26 let bb: *u8 = sys_mmap(28); var m: i64 = v 27 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 28 let t: *u8 = sys_mmap(28); var k: i64 = 0 29 if m == 0 { t[0] = 48 as u8; k = 1 } 30 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 31 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } sys_write(1, bb, k); return 0 32} 33func g_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 34func g_exists(path: *u8) -> i64 { let fd: i64 = sys_openat_rd(path); if fd < 0 { return 0 } sys_close(fd); return 1 } 35// need for a given id in (ids,need)[0..n); -1 if absent 36func g_need(ids: *i64, need: *i64, n: i64, target: *u8) -> i64 { var i: i64 = 0; while i < n { if g_streq(ids[i] as *u8, target) == 1 { return need[i] } i = i + 1 } return 0 - 1 } 37 38// stock a stir-fry ingredient with par == qty (so cooking one drops it below par) 39func ro_stock(id: *u8, name: *u8, cat: *u8, qty: i64, unit: *u8) -> i64 { 40 iv_add(RO_INV, RO_DOM, id, name, cat, qty, unit, "kitchen" as *u8, 0, 0, "-" as *u8) 41 iv_set_par(RO_INV, RO_DOM, id, qty) 42 return 0 43} 44 45func main() -> i64 { 46 g_p("=== nx_reorder_gate (R-REORDER: par -> low-stock -> shopping list from a meal plan) ===\n" as *u8) 47 fd_seed(RO_FOOD) 48 49 // stir-fry ingredients (par = qty) 50 ro_stock("chicken" as *u8, "Chicken" as *u8, "protein" as *u8, 2, "lb" as *u8) 51 ro_stock("tofu" as *u8, "Tofu" as *u8, "protein" as *u8, 2, "block" as *u8) 52 ro_stock("broccoli" as *u8, "Broccoli" as *u8, "produce" as *u8, 2, "head" as *u8) 53 ro_stock("onion" as *u8, "Onion" as *u8, "produce" as *u8, 3, "ea" as *u8) 54 ro_stock("snowpea" as *u8, "Snow Peas" as *u8, "produce" as *u8, 2, "bag" as *u8) 55 ro_stock("garlic" as *u8, "Garlic" as *u8, "produce" as *u8, 2, "bulb" as *u8) 56 ro_stock("ginger" as *u8, "Ginger" as *u8, "produce" as *u8, 2, "knob" as *u8) 57 ro_stock("soy" as *u8, "Soy Sauce" as *u8, "condiment" as *u8, 2, "bottle" as *u8) 58 ro_stock("oyster" as *u8, "Oyster Sauce" as *u8, "condiment" as *u8, 2, "bottle" as *u8) 59 ro_stock("rice" as *u8, "Rice" as *u8, "grain" as *u8, 2, "bag" as *u8) 60 // household staples already low (test detection independent of cooking) 61 iv_add(RO_INV, RO_DOM, "eggs" as *u8, "Eggs" as *u8, "dairy" as *u8, 1, "dozen" as *u8, "fridge" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "eggs" as *u8, 3) 62 iv_add(RO_INV, RO_DOM, "milk" as *u8, "Milk" as *u8, "dairy" as *u8, 0, "carton" as *u8, "fridge" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "milk" as *u8, 2) 63 iv_add(RO_INV, RO_DOM, "flour" as *u8, "Flour" as *u8, "baking" as *u8, 5, "bag" as *u8, "pantry" as *u8, 0, 0, "-" as *u8); iv_set_par(RO_INV, RO_DOM, "flour" as *u8, 2) 64 65 let world: *i64 = fd_world_open(RO_FOOD) 66 let names: *i64 = world[4] as *i64 67 68 var pass: i64 = 0 69 var tot: i64 = 0 70 71 // T1 par set/get 72 tot = tot + 1 73 var ok1: i64 = 1 74 if iv_get_par(RO_INV, RO_DOM, "eggs" as *u8) != 3 { ok1 = 0 } 75 if iv_get_par(RO_INV, RO_DOM, "chicken" as *u8) != 2 { ok1 = 0 } 76 if iv_get_par(RO_INV, RO_DOM, "nope" as *u8) != 0 { ok1 = 0 } // untracked -> 0 77 if ok1 == 1 { pass = pass + 1; g_p("PASS T1 par levels set/get\n" as *u8) } else { g_p("FAIL T1\n" as *u8) } 78 79 // T2 low-stock BEFORE cooking (only the already-low staples) 80 let lid: *i64 = sys_mmap(8 * 256) as *i64 81 let lneed: *i64 = sys_mmap(8 * 256) as *i64 82 let nlo0: i64 = iv_low_stock(RO_INV, RO_DOM, lid, lneed) 83 g_p("low before cooking=" as *u8); g_i(nlo0); g_p(" (eggs need " as *u8); g_i(g_need(lid, lneed, nlo0, "eggs" as *u8)); g_p(", milk need " as *u8); g_i(g_need(lid, lneed, nlo0, "milk" as *u8)); g_p(")\n" as *u8) 84 tot = tot + 1 85 var ok2: i64 = 1 86 if nlo0 != 2 { ok2 = 0 } 87 if g_need(lid, lneed, nlo0, "eggs" as *u8) != 2 { ok2 = 0 } // par3 - qty1 88 if g_need(lid, lneed, nlo0, "milk" as *u8) != 2 { ok2 = 0 } // par2 - qty0 89 if g_need(lid, lneed, nlo0, "flour" as *u8) != (0 - 1) { ok2 = 0 } // well-stocked -> not listed 90 if ok2 == 1 { pass = pass + 1; g_p("PASS T2 low-stock detection (eggs+milk to buy, flour not)\n" as *u8) } else { g_p("FAIL T2\n" as *u8) } 91 92 // T3 cook a meal from the pantry -> consumed ingredients drop below par -> onto the reorder list 93 let avail: *i64 = sys_mmap(8 * 64) as *i64 94 fp_pantry_avail(world, RO_INV, RO_DOM, avail) 95 let b1: *i64 = sys_mmap(8 * 16) as *i64; let r1: *i64 = sys_mmap(8 * 16) as *i64 96 let nb1: i64 = fp_choose(RO_FOOD, world, avail, b1, r1) 97 g_p("cooked: " as *u8) 98 var si: i64 = 0; while si < nb1 { if si > 0 { g_p(" | " as *u8) } g_p(names[b1[si]] as *u8); si = si + 1 } g_p("\n" as *u8) 99 fp_consume_build(RO_INV, RO_DOM, world, b1, nb1) 100 let nlo1: i64 = iv_low_stock(RO_INV, RO_DOM, lid, lneed) 101 g_p("low after cooking=" as *u8); g_i(nlo1); g_p("\n" as *u8) 102 let widx: *i64 = world[1] as *i64 103 let protein_id: *u8 = widx[b1[0]] as *u8 104 g_p(" cooked protein id=" as *u8); g_p(protein_id); g_p(" need=" as *u8); g_i(g_need(lid, lneed, nlo1, protein_id)); g_p("\n" as *u8) 105 tot = tot + 1 106 var ok3: i64 = 1 107 if nb1 != 5 { ok3 = 0 } 108 if nlo1 != 7 { ok3 = 0 } // 2 staples + 5 cooked ingredients 109 if g_need(lid, lneed, nlo1, protein_id) != 1 { ok3 = 0 } // cooked protein now short by 1 110 if ok3 == 1 { pass = pass + 1; g_p("PASS T3 meal -> reorder: cooking dropped 5 ingredients below par (low 2 -> 7)\n" as *u8) } else { g_p("FAIL T3 nlo1=" as *u8); g_i(nlo1); g_p("\n" as *u8) } 111 112 // T4 render the shopping list (sovereign, lists low items + buy quantities) 113 let page: *u8 = sys_mmap(65536) 114 let np: i64 = sh_render_list(RO_INV, RO_DOM, "Your shopping list" as *u8, page) 115 tot = tot + 1 116 var ok4: i64 = 1 117 if as_has_thirdparty_js(page, np) != 0 { ok4 = 0 } 118 if as_contains(page, np, "Milk" as *u8) != 1 { ok4 = 0 } 119 if as_contains(page, np, names[b1[0]] as *u8) != 1 { ok4 = 0 } // cooked protein on the list 120 if as_contains(page, np, "Buy 7 item" as *u8) != 1 { ok4 = 0 } 121 if ok4 == 1 { pass = pass + 1; g_p("PASS T4 sovereign shopping list (" as *u8); g_i(np); g_p(" bytes, 7 items, 0 JS)\n" as *u8) } else { g_p("FAIL T4\n" as *u8) } 122 123 // T5 ship via the publisher 124 sys_mkdir("knowledge/staging" as *u8, 0x1ed) 125 sys_mkdir("knowledge/staging/shop" as *u8, 0x1ed) 126 let sfd: i64 = sys_openat_wr(RO_STAGE_FILE, 420); if sfd >= 0 { sys_write(sfd, page, np); sys_close(sfd) } 127 pub_init() 128 sys_mkdir(RO_STG, 0x1ed) 129 sys_mkdir(RO_LIVE, 0x1ed) 130 pub_submit_to(RO_Q, RO_STAGE_FILE, "shopping-list.html" as *u8, "nishifamily" as *u8, "nishi-home" as *u8, "internal" as *u8) 131 let pubd: i64 = pub_run_full(RO_Q, RO_LED, RO_STG, RO_LIVE, "publish:shop" as *u8) 132 g_p(" pub_run_full -> published_this_pass=" as *u8); g_i(pubd); g_p("\n" as *u8) 133 tot = tot + 1 134 if g_exists(RO_LIVE_FILE) == 1 { pass = pass + 1; g_p("PASS T5 SHIPPED the shopping list to liveroot\n" as *u8) } else { g_p("FAIL T5\n" as *u8) } 135 136 g_p("nx_reorder_gate pass=" as *u8); g_i(pass); g_p("/" as *u8); g_i(tot) 137 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 138 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 139 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 140 let ctr__dry: *i64 = gv_ctr() 141 ctr__dry[0] = pass 142 ctr__dry[1] = tot 143 let rc__dry: i64 = gv_verdict("REORDER-GATE" as *u8, ctr__dry, "supply-chain loop CLOSED: consume -> low-stock -> shopping list -> shipped)" as *u8) 144 sys_exit(rc__dry) 145 return rc__dry 146}