Repository navigation
nightly 2026-10-05 (v0.3.38-beta.47): exit status on record, three stuck-card fixes, daemon RSS under load cut - #412
Merged
Conversation
…file bumps - Toolchain 2026-10-02 -> 2026-10-03, the newest nightly that builds the workspace: 2026-10-04 removed `core::intrinsics::abort` (rust#163574), which `branches 0.4.6` calls, and `branches` arrives through `turso_core` (^0.4.3 even in 0.8.2-pre.2). Release build of nanna-daemon green from cold in 7m51s. CI mirrors moved with it. - Lockfile: powerfmt 0.2.1, signal-hook 0.4.5, twox-hash 2.1.5. - GUI: postcss 8.5.29 (with nanoid 3.3.20, @oxc-project/types 0.153). - Still blocked: rten 0.27 (ocrs 0.13.1 wants ^0.26), TypeScript 7 (vue-tsc 3.3.12). - Roadmap: the branches blocker filed with its upstream fix; the stale boa_engine 0.22 box closed (done in 69a68aa); glibc arena research folded into the idle-RSS item. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…tatus on record The exit record said only "it died through a path no hook could see" for exactly the deaths worth explaining: the AppImage SIGBUS and the unexplained 2026-09-28 15:31Z death (no core, no OOM, no panic). The GUI waits on its sidecar and gets the status, but only logged it. - The record type moves to `nanna_core::exit_record` (the GUI links nanna-core, not nanna-daemon); `nanna_daemon::exit_reason` re-exports. - On a sidecar exit the GUI adds `observed_exit` (code or signal, and whether it sent the kill) when the record is still that process's `running` marker: same PID AND written after the spawn, so a reused PID never matches. Written before the exit is flagged, so no respawn races it. The record still reads as unclean. - The next boot logs "... the app saw it end by signal 9 (SIGKILL) at". - `nanna doctor` gains `daemon.last_exit`: a live daemon (Linux checks /proc/<pid>/comm), a clean stop, or a WARN for an unclean death, a panic or an IPC-server failure, with the log path and coredumpctl. Verified live: isolated GUI + daemon, SIGKILL the daemon, the record gains the signal, the auto-restarted daemon's warning names SIGKILL, and doctor reports ok while it runs and warn after it is killed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ts, hand-backs reset on completion Found by reviewing the Stage 3 card-run code: - The pause marker was looked for in a card's newest 64 activity rows; 64 renames or reorders after a Stop pushed it out and the stall sweep took the paused card back for the router. New `TaskRepository::newest_activity_of(task_id, actions)` reads markers by action (run start/end, and the rate-limit wait). - A stopped card reassigned to another member stayed `in_progress` with no run forever. A pause now holds only for the member it stopped (the `run_ended` row names who held the card); on the reassignment wake the card goes back to `pending` (actor `handover`) and the new member's run starts. An unnamed marker is never un-paused. - `hand_backs_in_a_row` now stops at a `completed` row, so hand-backs in different recurrence rounds no longer add up to the bound. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…vector `MemoryService::list_all`, `stats` and `with_store_timescale` read the store through `all_entries()`, which clones every entry whole: the current embedding and every model bucket (6 KiB per 1536-dim vector per model). They need content, FSRS state, or a timestamp. They now project under the read lock with `map_entries`, as the export already does. Measured on the release daemon, isolated, on a copy of the operator's 3 730-memory store, `memory.list` + search + stats every 2 min: RSS after nine cycles ~425 MB before, ~292-306 MB after (MALLOC_ARENA_MAX=2 on the old code: ~352 MB). Idle it is flat at 142.5 MB either way. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
glibc keeps freed pages at the high water. Each 14 MB `memory.list` reply (a Value tree, then a string, then a frame) stepped a long-lived daemon's RSS up and it never came back: on a copy of the operator's store, idle 142.5 MB -> 608 MB after ~40 light load cycles, still climbing. `crate::heap::after_large_reply` runs `malloc_trim(0)` on the blocking pool after the IPC writer has sent a reply of >= 1 MiB (so its string is dropped), at most once per 10 s (~4.5 ms each). The boot trim moves into the same module. Linux glibc only; elsewhere a no-op. Same load, nine cycles: old ~425 MB, MALLOC_ARENA_MAX=2 ~352 MB, clone fix ~300 MB, clone fix + trim ~178 MB, and it holds (192 MB later). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ore and after Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Version 0.3.37 -> 0.3.38 in the workspace, root package, GUI and Tauri config (the guard: base matches tauri.conf.json and differs from the published 0.3.37). Release notes for this run; README names doctor's new daemon.last_exit check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ld flat A longer sample of the trimmed daemon (15 cycles) reads ~213 MB with one 267 MB peak, not the ~178-192 MB it showed at 9. Say so: still about a third of the untrimmed rate (~439 MB at the same point). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nightly run 2026-10-05, which also prepares v0.3.38-beta.47. Ten commits: one dependency increment, four fix or performance increments, a benchmark baseline, release prep, and two doc corrections. Every code commit's gate was green.
Dependencies
cargo build --release -p nanna-daemontakes 7m51s from cold. The CI mirrors moved with it.core::intrinsics::abort(renamed in intrinsics: Renameaborttoabort_immediaterust-lang/rust#163574).branches 0.4.6calls it, and that crate comes in only throughturso_core, which requires^0.4.3even in 0.8.2-pre.2.ocrs0.13.1 wants^0.26, so dependabot chore(deps): bump rten from 0.26.0 to 0.27.0 #411 cannot build), and TypeScript 7 (vue-tsc3.3.12). The braces and node-forge advisories still have no fixed release.What shipped
nanna-core::exit_record, GUIdaemon_manager, doctor).observed_exit(code or signal, and whether it sent the kill itself) to the record. It does so only when the record is still that process'srunningmarker: same PID, and written after the spawn, so a reused PID never matches.nanna doctorcheckdaemon.last_exitreports the same verdict.TaskRepository::newest_activity_ofreads markers by action. On the old read, the extended stall test released the paused card.in_progressforever. A pause now holds only for the member it stopped, and the new member's run starts.hand_backs_in_a_rowcounted across completions. It now stops atcompleted. It deliberately does not stop atreopened, which the harness writes mid-cycle.list_all,statsand the dream timescale stopped cloning every vector. They went throughall_entries(), which clones every embedding and model bucket in order to read text, state or a timestamp. They now usemap_entries.malloc_trim(0)once a reply of ≥ 1 MiB has been sent, at most once per 10 s, at ~4.5 ms each. The boot trim moved into the same module (crate::heap).Measurements (items 3 and 4)
Setup: release daemons, isolated, each on a copy of the operator's store (3 730 memories). Every 2 min a stdlib-Python WebSocket client sent
memory.list(a 14.4 MB reply), a keyword search and stats.MALLOC_ARENA_MAX=2bench/BASELINE.mdSuite 5.memory.listwithout the intermediateserde_json::Value.Verification
cargo clippy --workspace --all-targets --exclude nanna-gui0 warnings.cargo test --workspace --exclude nanna-gui2828 passed / 0 failed (2811 on master).cargo test -p nanna-client --test e2e_daemon56/56.pnpm generategreen.tauri.conf.jsonvalidates against the Tauri 2 schema.conf true | published true.SIGKILL. The record gained"observed_exit": {"signal": 9, …}.Previous exit was UNCLEAN: … the app saw it end by signal 9 (SIGKILL) at ….nanna doctorreported[ok] daemon.last_exit a daemon is running (PID …)while it ran, and[warn] … the app saw it end by signal 9 (SIGKILL)with the log path after it was killed.kill -BUSsent to a running daemon is swallowed by Rust std's stack-overflow handler, which resets the handler and returns. A real fault still kills the process (the AppImage cores show that). Benign.Not done, and why
crates/nanna-daemon/src/appimage.rs) has sat uncommitted in.claude/worktrees/elegant-jackson-2ab1efsince 2026-09-28. It is someone else's work in progress, so I did not touch or duplicate it. Land or drop it.panic = "abort".cargo fmt.Research folded into ROADMAP
abortrename and its upstream fix (above).M_ARENA_MAXplus trim-on-idle (ctox#248, ivygrep#409, scrypted#2027). Measured here instead of assumed.onyums0.5.0 andarti-client0.47 unchanged; rmcp 3.5.0 is out (not yet evaluated).fsrs6.6.2, and burn 0.22 still pre-release.boa_engine 0.22was already taken on 2026-09-08.Shipped
6dbb5daeonce every check passed (build-release 41m, compile-tests 27m, deterministic-budgets 11m, daemon e2e, Playwright, Vitest, both typechecks, aarch64 under qemu, cargo audit, pnpm audit).3e32ad7f. Both signatures are byte-identical to the release's.sigfiles, and both download URLs answer 200. Thebasic-automationand legacyphysics515raw URLs both serve 0.3.38.🤖 Generated with Claude Code