Files
codewhale/crates
Hunter Bown 256f59dd33 feat(agents): session-boundary classification for sub-agents (#405)
\`agent_list\` previously surfaced every persisted sub-agent the manager
had on disk — including agents from prior sessions still hanging around
in \`subagents.v1.json\`. In long-lived sessions this piled up and the
model had to reason past 13 listed agents when only four were live.

Now: each \`SubAgentManager\` assigns a fresh \`session_boot_id\` at
construction. Every agent it spawns is stamped with that id, persisted
alongside the existing fields, and reloaded as-is by future managers.
At list time the manager classifies any agent whose stamp doesn't match
the current id (or that loaded with no stamp at all from pre-#405
records) as \`from_prior_session\`.

\`agent_list\` defaults to the current-session view: prior-session
agents are dropped from the listing **unless** they're still
\`Running\` (which can happen after a process restart — the manager
flagged them as \`Interrupted\` on load). Pass \`include_archived=true\`
to surface every record, with the \`from_prior_session\` flag on each
result so the model can tell live vs archived apart at a glance.

### What's wired

- \`SubAgentManager::current_session_boot_id\` — UUID-derived,
  generated in \`new\`.
- \`SubAgent::session_boot_id\` and \`PersistedSubAgent::session_boot_id\` —
  the latter \`#[serde(default)]\` for backward compat (pre-#405 records
  load with empty string and classify as prior-session).
- \`SubAgentResult::from_prior_session\` — \`#[serde(default,
  skip_serializing_if = "is_false")]\` so today's clients reading
  archived snapshots see the field, while default-false snapshots
  serialize without an extra noisy key.
- \`SubAgentManager::list_filtered(include_archived)\` — the new
  user-facing API. \`SubAgent::snapshot()\` still defaults the flag
  to \`false\`; \`snapshot_for_listing\` (manager-only) fills it in.
- \`AgentListTool\` accepts \`include_archived: bool\` (default
  false) and routes through the filter. The model-facing description
  explains the behaviour.

### Tests

- \`session_boot_ids_are_unique_per_manager\` — each manager mints
  its own id.
- \`list_filtered_drops_prior_session_terminals_by_default\` — the
  three-agent matrix (current running / prior completed / prior
  running) collapses to the right two with the right flags.
- \`list_filtered_with_include_archived_returns_everything\` —
  archived view returns all records with correct flags.
- \`agents_with_empty_boot_id_classify_as_prior_session\` — pre-#405
  records load and behave as expected.
- \`persist_round_trip_preserves_session_boot_id\` — write with one
  manager, reload with a fresh manager, confirm the agent flips to
  prior-session in the new manager's view.

### Verification

cargo fmt --all -- --check                                          ✓
cargo clippy --workspace --all-targets --all-features --locked --   -D warnings   ✓
cargo test --workspace --all-features --locked                      ✓ 1847 + supporting

Closes #405

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 03:57:06 -05:00
..