code wiki / (root) / nx_plan_svc.nx

nx_plan_svc.nx source

↩ module page · 133 lines · 5336 B

1// nx_plan_svc.nx -- PRODUCTION-PLAN SERVICE FACADE. The fourth organ on the 2// nx_service base, and the one that answers the operator's actual question: 3// "help us get a plan on what we need to do." One call takes a product 4// concept and returns the readiness score, the single next gap in kill-order, 5// the concrete action to close it, and whether what remains is a broken 6// concept or just paperwork. 7// 8// This is the recombination layer -- it composes the ingredient, jurisdiction, 9// formulation and economics libraries through nx_prodready into one plan. Four 10// facades now share the nx_service base (go-to-market, lab-science, QC, plan). 11// 12// USAGE: nx_plan_svc <verb> [args...] 13// describe 14// assess <mask> <market> <format> <retail_cents> <margin_permil> 15// <servings> <max_units> <identity> <gmp> <claims> <coa> 16// mask = bitmask of ingredient ids (bit i => ingredient i present) 17// market = SJ_* (0=US 1=EAEU/Belarus ...) 18// format = 1 capsule, 2 powder 19// the last four are 0/1 operator attestations 20// 21// Every number comes from the gated nx_prodready engine; this facade only 22// shapes the plan into JSON. 23// 24// genealogy_id: supplement_gtm + service_infrastructure 25 26import "nx_syscalls.nx" 27import "nx_service.nx" 28import "nx_grounding.nx" 29import "nx_supp_ingredient.nx" 30import "nx_supp_jurisdiction.nx" 31import "nx_prodready.nx" 32const PLAN_MAGIC_8192: i64 = 8192 33 34const PLAN_SVC: *u8 = "plan" as *u8 35 36// ===== describe ======================================================= 37 38func plan_describe(j: *NxJson) -> i64 { 39 nsvc_ok_open(j, PLAN_SVC, "describe" as *u8) 40 nj_kv_str(j, "service" as *u8, "production-readiness plan (recombines all GTM inputs)" as *u8) 41 nj_comma(j) 42 nj_kv_int(j, "verb_count" as *u8, 1) 43 nj_comma(j) 44 nj_kv_int(j, "readiness_dimensions" as *u8, PR_N_DIM) 45 nj_comma(j) 46 nj_key(j, "verbs" as *u8) 47 nj_puts(j, "[" as *u8) 48 nj_puts(j, "{\"verb\":\"assess\",\"args\":[\"mask:int\",\"market:int\",\"format:int\",\"retail_cents:int\",\"margin_permil:int\",\"servings:int\",\"max_units:int\",\"identity:int\",\"gmp:int\",\"claims:int\",\"coa:int\"]}" as *u8) 49 nj_puts(j, "]" as *u8) 50 nsvc_ok_close_g(j, GND_ASSERTED) 51 return 0 52} 53 54// ===== assess: the plan =============================================== 55 56func plan_build(argc: i64, argv: *i64) -> *NxProduct { 57 let p: *NxProduct = nx_product_new() 58 p.ingredient_mask = nsvc_arg_int(argc, argv, 2) 59 p.market = nsvc_arg_int(argc, argv, 3) 60 let fmt: i64 = nsvc_arg_int(argc, argv, 4) 61 if fmt > 0 { p.format = fmt } 62 p.retail_cents = nsvc_arg_int(argc, argv, 5) 63 let mg: i64 = nsvc_arg_int(argc, argv, 6) 64 if mg > 0 { p.target_margin_permil = mg } 65 let sv: i64 = nsvc_arg_int(argc, argv, 7) 66 if sv > 0 { p.servings = sv } 67 let mu: i64 = nsvc_arg_int(argc, argv, 8) 68 if mu > 0 { p.max_units = mu } 69 p.identity_ready = nsvc_arg_int(argc, argv, 9) 70 p.gmp_qualified = nsvc_arg_int(argc, argv, 10) 71 p.claims_reviewed = nsvc_arg_int(argc, argv, 11) 72 p.coa_on_file = nsvc_arg_int(argc, argv, 12) 73 return p 74} 75 76func plan_assess(j: *NxJson, argc: i64, argv: *i64) -> i64 { 77 let p: *NxProduct = plan_build(argc, argv) 78 if p.ingredient_mask == 0 { 79 nsvc_error(j, PLAN_SVC, "assess" as *u8, NSVC_ERR_BAD_ARGS, "empty product: ingredient mask is 0" as *u8) 80 return 0 81 } 82 let gap: i64 = pr_first_gap(p) 83 nsvc_ok_open(j, PLAN_SVC, "assess" as *u8) 84 nj_kv_int(j, "readiness_permil" as *u8, pr_readiness_permil(p)) 85 nj_comma(j) 86 nj_kv_int(j, "dimensions_passed" as *u8, pr_dims_passed(p)) 87 nj_comma(j) 88 nj_kv_int(j, "dimensions_total" as *u8, PR_N_DIM) 89 nj_comma(j) 90 nj_kv_bool(j, "production_ready" as *u8, pr_is_production_ready(p)) 91 nj_comma(j) 92 nj_kv_int(j, "next_gap" as *u8, gap) 93 if gap != PR_READY { 94 nj_comma(j) 95 nj_kv_str(j, "next_gap_name" as *u8, pr_dim_name(gap)) 96 nj_comma(j) 97 nj_kv_str(j, "next_action" as *u8, pr_action(gap)) 98 } 99 nj_comma(j) 100 nj_kv_int(j, "open_computed_blockers" as *u8, pr_open_computed_blockers(p)) 101 nj_comma(j) 102 nj_kv_int(j, "open_attestations" as *u8, pr_open_attestations(p)) 103 // If legally blocked, name the offending ingredient -- the precise fix. 104 if gap == PR_LEGAL { 105 let bad: i64 = pr_first_unlawful(p) 106 if bad != SI_INVALID { 107 nj_comma(j) 108 nj_kv_str(j, "unlawful_ingredient" as *u8, si_name(bad)) 109 nj_comma(j) 110 nj_kv_int(j, "unlawful_class" as *u8, si_class(bad)) 111 } 112 } 113 nsvc_ok_close_g(j, GND_ASSERTED) 114 return 0 115} 116 117// ===== dispatch ======================================================= 118 119func plan_dispatch(argc: i64, argv: *i64, j: *NxJson) -> i64 { 120 let verb: *u8 = nsvc_arg(argc, argv, 1) 121 if verb[0] == (0 as u8) { plan_describe(j); return 0 } 122 if nsvc_streq(verb, "describe" as *u8) == 1 { plan_describe(j); return 0 } 123 if nsvc_streq(verb, "assess" as *u8) == 1 { plan_assess(j, argc, argv); return 0 } 124 nsvc_error(j, PLAN_SVC, verb, NSVC_ERR_UNKNOWN_VERB, "unknown verb; call describe for the catalog" as *u8) 125 return 1 126} 127 128func main(argc: i64, argv: *i64) -> i64 { 129 let j: *NxJson = nx_json_new(PLAN_MAGIC_8192) 130 let rc: i64 = plan_dispatch(argc, argv, j) 131 nj_flush(j) 132 return rc 133}