4c34ae00a009

add nina mood: plain-language machine health (systemctl is-system-running + current gen + last-applied age + system closure size); registered in dispatch and help

time
2026-06-04 23:17 UTC · 4 months ago
machine
koh2
agent
claude-opus-4-8
session
mood command
parent
11ccaf00b0c5
4 files src/commands.zig+10 −0src/exec.zig+13 −0src/main.zig+1 −0src/output.zig+14 −0
src/commands.zig+10 −0
@@ -169,6 +169,16 @@169169     }170170 }171171 172+pub fn mood(ctx: Ctx) !void {173+    const gen = exec.getCurrentGeneration(ctx.gpa, ctx.io, &ctx.machine) catch 0;174+    const st = exec.systemStatus(ctx.gpa, ctx.io, &ctx.machine);175+    defer ctx.gpa.free(st.size);176+    defer ctx.gpa.free(st.age);177+    const state = exec.systemRunningState(ctx.gpa, ctx.io, &ctx.machine) catch try ctx.gpa.dupe(u8, "unknown");178+    defer ctx.gpa.free(state);179+    output.mood(ctx.machine.name, state, gen, st.age, st.size);180+}181+172182 pub fn doctor(ctx: Ctx) !void {173183     output.doctorHeader(ctx.machine.name);174184     const checks = try exec.runDoctorChecks(ctx.gpa, ctx.io, &ctx.machine);

view file

src/exec.zig+13 −0
@@ -394,6 +394,19 @@394394     };395395 }396396 397+// `systemctl is-system-running` -> "running" / "degraded" / "starting" ... A398+// one-word health signal; exits non-zero when degraded, so we read stdout, not399+// the code. Caller owns the returned slice.400+pub fn systemRunningState(gpa: std.mem.Allocator, io: std.Io, machine: *const types.Machine) ![]u8 {401+    const r = capture(gpa, io, machine, &.{ "systemctl", "is-system-running" }) catch402+        return gpa.dupe(u8, "unknown");403+    defer gpa.free(r.stderr);404+    const state = std.mem.trim(u8, r.stdout, " \t\n\r");405+    const owned = try gpa.dupe(u8, if (state.len > 0) state else "unknown");406+    gpa.free(r.stdout);407+    return owned;408+}409+397410 fn humanAgo(gpa: std.mem.Allocator, secs: u64) ![]u8 {398411     if (secs < 60) return std.fmt.allocPrint(gpa, "{d}s ago", .{secs});399412     if (secs < 3600) return std.fmt.allocPrint(gpa, "{d}m ago", .{secs / 60});

view file

src/main.zig+1 −0
@@ -159,6 +159,7 @@159159     if (std.mem.eql(u8, cmd, "status")) return commands.statusCmd(ctx);160160     if (std.mem.eql(u8, cmd, "diff")) return commands.diff(ctx);161161     if (std.mem.eql(u8, cmd, "doctor")) return commands.doctor(ctx);162+    if (std.mem.eql(u8, cmd, "mood")) return commands.mood(ctx);162163     if (std.mem.eql(u8, cmd, "update")) return commands.update(ctx);163164     if (std.mem.eql(u8, cmd, "upgrade")) return commands.upgrade(ctx);164165     if (std.mem.eql(u8, cmd, "log")) return commands.log(ctx);

view file

src/output.zig+14 −0
@@ -475,6 +475,19 @@475475     p("{s}removing {s}{s}{s}\n", .{ hdr(), c(PINK), pkg, c(RESET) });476476 }477477 478+// Plain-language health summary. No kaomoji, no hearts — just the facts.479+pub fn mood(machine: []const u8, state: []const u8, gen: u32, age: []const u8, size: []const u8) void {480+    const healthy = std.mem.eql(u8, state, "running");481+    const verdict = if (healthy) "all good" else state;482+    const color = if (healthy) GREEN else YELLOW;483+    p("{s}{s}  {s}{s}{s}\n", .{ hdr(), machine, c(color), verdict, c(RESET) });484+    if (age.len > 0 or size.len > 0) {485+        p("   generation {d}, last applied {s}, {s} system closure\n", .{ gen, age, size });486+    } else {487+        p("   generation {d}\n", .{gen});488+    }489+}490+478491 pub fn installEditorPrompt(pkg: []const u8, config_path: []const u8, line: u32, editor: []const u8) void {479492     p("{s}opening {s}  add {s}{s}{s} to systemPackages\n", .{ hdr(), config_path, c(PINK), pkg, c(RESET) });480493     const cmd = std.fmt.allocPrint(std.heap.page_allocator, "{s} {s} +{d}", .{ editor, config_path, line }) catch editor;@@ -560,6 +573,7 @@560573         .{ "upgrade", "update and rebuild" },561574         .{ "log", "operation history" },562575         .{ "doctor", "diagnose issues" },576+        .{ "mood", "plain-language health" },563577         .{ "develop", "enter dev shell" },564578         .{ "flake", "flake management" },565579         .{ "build", "build a package" },

view file