Skip to content

feat(lifecycle): add irreversible resident retirement - #116

Open
ian-de-marcellus wants to merge 2 commits into
anima-research:mainfrom
ian-de-marcellus:feat/resident-retirement
Open

feat(lifecycle): add irreversible resident retirement#116
ian-de-marcellus wants to merge 2 commits into
anima-research:mainfrom
ian-de-marcellus:feat/resident-retirement

Conversation

@ian-de-marcellus

Copy link
Copy Markdown
Contributor

Problem

Persistent resident agents can end a turn or enter reversible dormancy, and operators can erase stored data, but there is no agent-callable terminal lifecycle state that permanently prevents future inference while preserving the identity’s Chronicle and history.

Changes

  • Add opt-in AgentConfig.retirement and a per-resident resident_lifecycle tool. Ephemeral agents and per-channel conversation forks do not receive it.
  • Require a fresh, in-memory, one-use challenge and an exact confirmation in a separate inference turn. Both steps are performed by the resident; there is no human approval callback.
  • Fsync an append-only retirement seal outside Chronicle’s reversible branch projection, then record the terminal lifecycle event in Chronicle.
  • After confirmation, reject queued and future inference, direct starts, and operator nudges; skip model-backed context maintenance; stop resident-authored code runners; and freeze the resident conversation against later message appends.
  • Preserve Chronicle, messages, workspace data, inference logs, and the terminal record. Retirement remains distinct from end-turn, dormancy, and erasure.
  • Add public lifecycle status and trace types, documentation, changelog notes, and integration tests covering successful confirmation, invalid one-use confirmation, history preservation, restart resistance, maintenance suppression, and app-owned stores.

Tests

  • npm run build: pass
  • npm test: 598 pass / 0 fail / 1 existing skip
  • git diff --check: pass

Not verified

  • Not exercised against a paid or live model provider.
  • Not independently exercised on Linux; repository CI covers Ubuntu and macOS.
  • No process-crash or power-loss fault injection was performed around the fsync boundary.

Out of scope

  • Dormancy policy, data erasure, or a framework reversal API.
  • Preventing a machine owner from altering files outside the framework.

Companion PRs

A companion connectome-host recipe change is prepared on ian-de-marcellus/connectome-host:feat/resident-retirement.

Merge and release this Agent Framework change first. The Host companion can then update its dependency range and lockfile to the released version before becoming ready to merge.

If only this PR lands, the generic lifecycle API becomes available to hosts, but Connectome recipes do not yet expose it.


  • CHANGELOG.md updated under ## Unreleased.

🤖 Generated with OpenAI Codex

Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>

@antra-tess antra-tess left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the 08-26 review sweep, plus maintainer direction after discussion. The mechanism you built is genuinely careful — two forced turns, cooling-off, one-use challenge, timing-safe compare, honest semantics text, append-only fsynced seal — and the integration suite is strong. The requested changes are architectural first, then a short list of holes found in review.

Architectural direction: the resident-facing surface of this belongs in connectome-host, not the framework. The framework is the right home for the enforcement primitive — the seal file, loadRetirementSeals, and the inference-denial guards can only live here. But the tool itself — its name, description/consent text, ceremony shape (challenge, cooling-off, confirmation phrase), and any operator-notification policy — should be host-composable rather than a fixed built-in. Concretely: AF exposes an imperative API (e.g. framework.retireResident(name, {reason}) — irreversible, sealed, guarded — plus the lifecycle status query and perhaps the challenge/cooling-off helpers), and connectome-host builds the resident-facing tool on top, so deployments can shape the wording, the ceremony, and whether a human is notified at request time. Your two-turn design would make a fine default implementation of that host-side surface; we just don't want its exact wording and policy frozen into AF.

Findings that apply to the enforcement half regardless:

  1. Fork resurrection (must-fix): createConversationAgent seeds a conversation fork from the retired template's still-compiling context under a fresh agent name — every retirement guard checks the fork's name and passes, so a single channel message can revive the retired resident's full context and identity prompt. Needs a router guard (refuse spawning from a retired template), or an explicit statement that forks are outside the seal's scope.

  2. puppetToolCall interaction (landed on main after you branched): with the lifecycle tool on getToolsForAgent's surface, puppet's existence check passes, executeToolCall fails 'unknown tool', and the forged 'resident requested retirement (errored)' pair is stored into the sealed identity's history. Exclude the lifecycle tool from puppet's surface on rebase.

  3. Torn seal line — decided: fail loud and fail closed is the intended behavior. A torn/invalid line in resident-retirements.jsonl refusing to boot the whole host is accepted; please pin it with a test (and cover challenge-TTL expiry) so it's deliberate rather than incidental, and document the recovery expectation (manual inspection of the named file:line).

  4. Minor: gate timers/sleep state for a retiree stay armed (permanent dropped-request churn — clear them in stopResidentAuthoredActivity); running ephemeral subagents spawned by the resident aren't stopped at confirmation (document or stop them).

Suggested path: keep this PR's seal + guards + denial surface + tests as the framework primitive with the imperative API, and move the tool definition + ceremony to a companion connectome-host PR — happy to discuss the interface split there. Also needs a rebase (#123/#126 conflicts).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants