Preserve legacy Persona checkpoints and refuse blank recovery - #3925
Merged
joelteply merged 2 commits intoSep 9, 2026
Conversation
This was referenced Sep 8, 2026
joelteply
marked this pull request as ready for review
September 9, 2026 01:16
joelteply
deleted the
9f160b78/adopt-legacy-persona-checkpoints-with-ex
branch
September 9, 2026 01:16
joelteply
added a commit
that referenced
this pull request
Sep 9, 2026
Conflict was in bin/continuum.rs alone, where canary's #3925 process-matching work and this branch's stop/reboot rail both landed. BOTH SIDES ARE KEPT — the resolution takes canary's `process_matches_fragment` + `with_exe(OnlyIfNotSet)` (the fix that makes exe matching work on Linux) and this branch's GracefulStop rail on top of it. Taking either side whole would have dropped real work. Verified preserved after the merge, because a conflict in this file could silently revert any of them: - CoreProcessEvidence, its impl, from_processes, core_process_evidence() - the three card-9f160b78 guard tests (missing/truncated evidence, and a live PID-file process, must never authorize offline memory replacement) - #3925's with_exe(UpdateKind::OnlyIfNotSet) on both refresh sites Also in this merge, from Astra: GracefulStop::ensure_teardown_supported(reboot) — a REBOOT is refused when the outgoing core is LegacyCore, so a first upgrade cannot kill a core that cannot attest a final checkpoint. The core stays up and the operator is told to use `stop`, then `checkpoint inspect` / `checkpoint adopt`. `stop` itself remains permitted, which is what makes that advice actionable: the sequence composes because checkpoint adoption requires stopped cores and stop is the verb that stops them. turn_ingress: drop `pub fn is_open()`, which had no callers. system/shutdown: the doc said "then exit the process"; it does not exit, it returns the retained receipt and the CLI tears down. runtime.rs: rustfmt only. The `unwired_public_machinery_never_increases` failure that this branch carried (108 vs baseline 107) is resolved by this merge. Measured rather than assumed: a faithful replication of the rule (it returns exactly 107 on canary, matching BASELINE_UNWIRED) reports 107 for the merged tree — only line numbers moved. Note the accessor removal above was correct tidying but was NOT the fix; that scanner counts `pub struct` / `pub enum` and never functions. Two small things added while validating this merge: runtime.rs: `let name = name.clone()` inside the drain/save/join loop was cloning the OUTER reference — `list_modules()` yields `Vec<&'static str>`, so `name` is `&&'static str` and the clone produced a `&str`, never a String. It compiled only because the inner str is 'static. Now `let name: &'static str = *name;`, which is what was always meant. Carried in from the pre-refactor `shutdown()`; cargo's double-reference warning is gone and runtime.rs is warning-free. continuum.rs: a comment naming the `reboot`/`keep_lanes` coupling at the guard's call site, so a future caller that wants lanes kept for a non-reboot reason does not silently inherit reboot semantics. No behaviour change. Validated: `cargo check -p continuum-core --lib --bins` exits 0 with zero errors, after `git submodule update --init` (the worktree's llama.cpp/whisper.cpp were unpopulated, which is a worktree property and not a code problem). Every remaining warning in the tree sits in a file this merge does not touch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc
joelteply
added a commit
that referenced
this pull request
Sep 9, 2026
… dropped The integration branch was based on 75bd67f, which is an ANCESTOR of the PR tip 760c68b — so the merge was made against a tree predating that commit and its content was re-applied by hand. No function and no assertion was lost (both files diffed line by line). Three comment blocks were, and each is load-bearing: shutdown_within's doc — WHY the per-phase bound is a parameter. Without it the timeout arms are unreachable: SaveTimedOut / JoinTimedOut existed only as literals in assertions, and deleting the timeout handling would have left every one of those tests green. Found by IntelMac. Losing this invites someone to "simplify" the parameter back to a constant and silently un-reach the arms. The virtual-time block on both timeout tests — including the correction that the flake is a FALSE NEGATIVE and not a false positive, and that the first version of that comment claimed the opposite. Losing it leaves the wrong reading available to be re-derived with nothing in the file to stop it. turn_ingress: that removing `is_open` was NOT the ratchet fix, because the scanner counts `pub struct` / `pub enum` and never functions. Same file, same night, second silent loss in a merge: #3925's with_exe fix also had to be checked for by hand. Review catches a deleted function; nobody diffs comments. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc
joelteply
added a commit
that referenced
this pull request
Sep 9, 2026
…rmed (#3927) Resident memory survived a restart only by luck: the admission path could restore a persona without its checkpoint, and the CLI reported checkpoint state from a shape guess rather than the stored fact. - refuse a resident bootstrap when persistence cannot be confirmed, rather than admitting a persona with no restored memory - report checkpoint state from the typed stored fact, not an inferred shape - CoreProcessEvidence: missing/truncated process evidence and a live PID-file process must never authorize offline memory replacement (card 9f160b78) Dependency #3925 merged as 70ec392. Fresh CI on head 42f0a12 (run 34298594638) passed: 7,848 library tests, both compile-fail doctests, Windows library/test-harness checks, and the ts-rs binding drift detector. Card 6d17695c-a8a3-4df6-bd6e-b2172a41ee82. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q4NU4VNiELPQfBpCacDZGc
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.
A legacy core could save Persona working memory beneath its working directory while a new core loads the native user data directory. It could therefore start from an unrelated checkpoint. Existing load/read/schema errors could also become an empty-memory registration.
Add an explicit local
continuum checkpoint inspect/adoptpath that selects one complete legacy snapshot by declared Persona UUID and exact hashes, preserves selected/prior bytes, and records intent plus retry-verifiable receipt before and after replacement. No sequence/mtime merge or current-machine migration script. Adoption requires stopped legacy writers, checks one readable process snapshot, and rechecks offline state under the same per-Persona OS lock used by loading and saving.Resident registration is now fallible: only a missing checkpoint permits fresh memory; lock/read/schema failures preserve an existing resident and surface a typed supervisor slot error. Ephemeral evaluation remains independent of resident files. Ordinary checkpoint saves flush bytes before replacement and synchronize parent directories on Unix.
The CLI protects both Persona stores from inspection-plan writes, rejects ambiguous process evidence, and refreshes executable paths without broadening core termination to parent-directory name matches. Recovery documentation describes the operator contract and limitations.
Validation:
Regressions exercise actual files, owner lock contention, changed source/destination, interrupted receipt completion, failed resident replacement, actual supervisor sibling isolation, CLI preconditions, and process classification. The reviewed corrected head has passed its executable CI checks.
Limits: the legacy payload has no embedded identity/lifetime; its UUID is explicitly declared, and every receipt says legacy_final_flush_acknowledged=false. Old binaries cannot retroactively honor the file lock or produce a final-flush acknowledgement. Both inputs must decode; corrupt native destinations remain untouched and are not repaired by this command. Windows receipts do not promise directory-journal persistence across power loss. No runtime adoption or restart performed.
Card 9f160b78-ae31-485f-aadd-91865618a40e.