nx_heal.nx source
↩ module page · 88 lines · 4507 B
1// nx_heal.nx -- CLI half of the consolidated heal-plane tool (verb-router over nx_heal_lib).
2// One MCP stub (tool #11 of the 15-tool architecture). READ-ONLY increment: status | log tools|edge |
3// remediations, each with optional basedir (default "." = ~/nishihost on the NAS).
4// Exit codes: status -> number of DOWN services (0 = GREEN, visible in MCP _meta.exit_code);
5// log/remediations -> 0 on success; 2 on usage. license_tier: ORIGINAL
6import "nx_heal_lib.nx"
7const NH_MAGIC_18095: i64 = 18095
8const NH_MAGIC_18094: i64 = 18094
9
10const NH_USAGE_RC: i64 = 2
11const NH_ARG_VERB: i64 = 1 // argv slot of the verb
12const NH_ARG_P1: i64 = 2 // argv slot of the first verb arg
13const NH_ARG_P2: i64 = 3 // argv slot of the second verb arg
14const NH_ARGC_VERB: i64 = 2 // argc when just a verb is present
15const NH_ARGC_P1: i64 = 3 // argc when one verb arg is present
16const NH_ARGC_P2: i64 = 4 // argc when two verb args are present
17const NH_ARG_P3: i64 = 4 // argv slot of the third verb arg
18const NH_ARGC_P3: i64 = 5 // argc when three verb args are present
19
20// fork+exec ./nx_metrics.elf <verb> metrics.ring <name> <arg>, inheriting stdout -> flows to MCP.
21func nh_metrics(verb: *u8, name: *u8, arg: *u8) -> i64 {
22 let pid: i64 = sys_fork()
23 if pid == 0 {
24 let av: *i64 = sys_mmap(8 * 8) as *i64
25 av[0] = ("./nx_metrics.elf" as *u8) as i64
26 av[1] = verb as i64
27 av[2] = ("metrics.ring" as *u8) as i64
28 av[3] = name as i64
29 av[4] = arg as i64
30 av[5] = 0
31 let ev: *i64 = sys_mmap(8 * 2) as *i64
32 ev[0] = 0
33 sys_execve("./nx_metrics.elf" as *u8, av, ev)
34 sys_exit(127)
35 }
36 if pid < 0 { nh_puts("nx_heal: metrics fork failed\n" as *u8); return 1 }
37 let st: *i64 = sys_mmap(8) as *i64
38 sys_wait4(pid, st, 0)
39 return 0
40}
41
42func main(argc: i64, argv: *i64) -> i64 {
43 if argc < NH_ARGC_VERB { nh_puts("usage: nx_heal status|log tools|edge|remediations [basedir]\n" as *u8); return NH_USAGE_RC }
44 let verb: *u8 = argv[NH_ARG_VERB] as *u8
45 var base: *u8 = "." as *u8
46 if nh_streq(verb, "status" as *u8) == 1 {
47 if argc >= NH_ARGC_P1 { base = argv[NH_ARG_P1] as *u8 }
48 return nh_status(base)
49 }
50 if nh_streq(verb, "log" as *u8) == 1 {
51 if argc < NH_ARGC_P1 { nh_puts("usage: nx_heal log tools|edge [basedir]\n" as *u8); return NH_USAGE_RC }
52 if argc >= NH_ARGC_P2 { base = argv[NH_ARG_P2] as *u8 }
53 let r: i64 = nh_log(base, argv[NH_ARG_P1] as *u8)
54 if r < 0 { return NH_USAGE_RC }
55 return 0
56 }
57 if nh_streq(verb, "remediations" as *u8) == 1 {
58 if argc >= NH_ARGC_P1 { base = argv[NH_ARG_P1] as *u8 }
59 nh_remediations(base)
60 return 0
61 }
62 // fleet | tenancy -> the LIVE organ state (loopback :18095 / :18094 body), straight onto MCP
63 if nh_streq(verb, "fleet" as *u8) == 1 { if nh_organ_body(NH_MAGIC_18095) < 0 { return 1 } return 0 }
64 if nh_streq(verb, "tenancy" as *u8) == 1 { if nh_organ_body(NH_MAGIC_18094) < 0 { return 1 } return 0 }
65 // uptime|history <daemon> [window|n] -> the sovereign metrics TSDB (nx_metrics), straight onto MCP
66 if nh_streq(verb, "uptime" as *u8) == 1 {
67 if argc < NH_ARGC_P1 { nh_puts("usage: nx_heal uptime <daemon> [window_sec=3600]\n" as *u8); return NH_USAGE_RC }
68 var win: *u8 = "3600" as *u8
69 if argc >= NH_ARGC_P2 { win = argv[NH_ARG_P2] as *u8 }
70 return nh_metrics("uptime" as *u8, argv[NH_ARG_P1] as *u8, win)
71 }
72 if nh_streq(verb, "history" as *u8) == 1 {
73 if argc < NH_ARGC_P1 { nh_puts("usage: nx_heal history <daemon> [n=20]\n" as *u8); return NH_USAGE_RC }
74 var hn: *u8 = "20" as *u8
75 if argc >= NH_ARGC_P2 { hn = argv[NH_ARG_P2] as *u8 }
76 return nh_metrics("history" as *u8, argv[NH_ARG_P1] as *u8, hn)
77 }
78 // diagnose <daemon> [plane tools|edge|-] [basedir] -> WHY-verdict (exit = verdict code)
79 if nh_streq(verb, "diagnose" as *u8) == 1 {
80 if argc < NH_ARGC_P1 { nh_puts("usage: nx_heal diagnose <daemon> [tools|edge|-] [basedir]\n" as *u8); return NH_USAGE_RC }
81 var plane: *u8 = "-" as *u8
82 if argc >= NH_ARGC_P2 { plane = argv[NH_ARG_P2] as *u8 }
83 if argc >= NH_ARGC_P3 { base = argv[NH_ARG_P3] as *u8 }
84 return nh_diagnose(argv[NH_ARG_P1] as *u8, plane, base)
85 }
86 nh_puts("usage: nx_heal status|fleet|tenancy|log fleet|tenancy|tools|edge|remediations|diagnose [args]\n" as *u8)
87 return NH_USAGE_RC
88}