ab2b04787858

fix log --last N truncation (OF-7) — readNinaLog now keeps only the final N non-empty lines when last>0 (was '_ = last'), copying out before freeing content; default last=50 unaffected when fewer entries — build+tests green, --last 2 verified returns exactly 2 of 4 entries

time
2026-06-05 02:18 UTC · 4 months ago
machine
koh2
agent
claude-opus-4-8
session
nina finishing brief
parent
f1e9d723cc0f
1 file src/exec.zig+22 −2
src/exec.zig+22 −2
@@ -786,8 +786,28 @@786786     const home = environ.get("HOME") orelse return error.FileNotFound;787787     const path = try std.fmt.allocPrint(gpa, "{s}/.nina.log", .{home});788788     defer gpa.free(path);789-    _ = last;790-    return std.Io.Dir.readFileAlloc(.cwd(), io, path, gpa, .unlimited) catch return error.FileNotFound;789+    const content = std.Io.Dir.readFileAlloc(.cwd(), io, path, gpa, .unlimited) catch return error.FileNotFound;790+    if (last == 0) return content;791+792+    // Collect non-empty lines, then keep only the final `last`. Slices point into793+    // `content`, so copy them out before freeing it.794+    var lines: std.ArrayList([]const u8) = .empty;795+    defer lines.deinit(gpa);796+    var it = std.mem.splitScalar(u8, content, '\n');797+    while (it.next()) |line| {798+        if (std.mem.trim(u8, line, " \t\r").len == 0) continue;799+        try lines.append(gpa, line);800+    }801+    if (lines.items.len <= last) return content;802+803+    var out: std.ArrayList(u8) = .empty;804+    errdefer out.deinit(gpa);805+    for (lines.items[lines.items.len - last ..]) |line| {806+        try out.appendSlice(gpa, line);807+        try out.append(gpa, '\n');808+    }809+    gpa.free(content);810+    return out.toOwnedSlice(gpa);791811 }792812 793813 // nina is a one-shot process, so "did the last apply fail this session?" can't

view file