Skip to content

feat(ateapi): track actor_template_uid per snapshot on ExternalSnapshot - #1713

Open
shrutiyam-glitch wants to merge 8 commits into
agent-substrate:mainfrom
shrutiyam-glitch:snapshot-template-uid
Open

shrutiyam-glitch wants to merge 8 commits into
agent-substrate:mainfrom
shrutiyam-glitch:snapshot-template-uid

Conversation

@shrutiyam-glitch

@shrutiyam-glitch shrutiyam-glitch commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Follow up on the comment - #1675 (comment)

Stamps actor_template_uid onto ExternalSnapshot so template provenance travels with the snapshot itself, rather than being inferred from the single ActorStatus.current_actor_template_uid.

Motivation

current_actor_template_uid records the template the last sprint booted with (finalizeRunning stamps it on every resume). It does not record the template the snapshot was captured under. Those two diverge as soon as an actor runs a sprint that does not produce a new durable snapshot, and loadActorForResume was using the former to decide whether to force a DATA-only restore instead of FULL.

Walking an actor through a repoint and a crash:

Step Action current_…_uid ExternalSnapshot
a Suspend on template A A captured on A
b UpdateActor repoints the spec to B A captured on A
c Resume → A != B, restores DATA, sprint boots on B B still on A
d Actor crashes (or is reverted) — no new snapshot taken B still on A
e Resume → current == target == B, so no repoint is detected B still on A

At step e the old check reports "template not replaced" and restores the external snapshot in FULL — replaying a memory image captured under A's sandbox on B. That is exactly the case the guard exists to prevent; it was silently defeated by the sprint at step c advancing current_actor_template_uid past the snapshot.

(Note: Paused actors do not face this divergence. Because UpdateActor is only allowed in the SUSPENDED state, a paused actor cannot have its template updated. Therefore, local checkpoints do not need separate template provenance tracking).

Changes

  • Data Model Updates: Added the actor_template_uid field to ExternalSnapshot.
  • Snapshot Stamping: Updated the capture logic to stamp external snapshots with the active sandbox's ActorTemplate UID when suspending an actor or creating an actor from a tag.
  • Resume Evaluation Logic: Modified the external resume logic to compare the target template UID against the specific snapshot's UID (ExternalSnapshot.actor_template_uid) rather than the actor's overall status. Local restores bypass this check entirely since templates cannot change during a pause.

Tests

  • TestResumeActor_AteletWireRequest (unit): snapshot fixtures now carry actor_template_uid, since provenance is read from the snapshot rather than from actor status.
  • Functional expectations for create/update/resume/pause updated for the new field on the external snapshot golden files.
  • TestUpdateTemplateLifecycle (e2e): asserts external_snapshot.actor_template_uid after suspend and re-suspend.

A TODO marks the resume → crash/revert → resume e2e sequence to be added once RevertActor lands — that is the path described in the table above.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

Add actor_template_uid to ExternalSnapshot and LocalSnapshotInfo so each
snapshot records the UID of the ActorTemplate whose sandbox its guest state
was captured from. A paused actor can hold a local checkpoint and an external
snapshot captured under different templates after a template repoint, so
template provenance must be tracked per snapshot rather than relying solely
on ActorStatus.current_actor_template_uid.
Stamp ExternalSnapshot.actor_template_uid and LocalSnapshotInfo.actor_template_uid
with the active sandbox's ActorTemplate UID when suspending or pausing an actor,
and when creating an actor from a tag.
Compare targetTemplateUID against LocalSnapshotInfo.actor_template_uid for
local checkpoint restores and against ExternalSnapshot.actor_template_uid for
external snapshot restores. This ensures resuming a paused actor whose local
checkpoint matches the target template restores in FULL even when an older
external snapshot on the actor came from a previous template.
Extend TestUpdateTemplateLifecycle to assert external_snapshot.actor_template_uid
after suspend, and add a pause-then-resume sequence under template B while the
actor still holds template A's external snapshot to verify local checkpoint
provenance preserves memory state on FULL restores.
@shrutiyam-glitch shrutiyam-glitch changed the title Snapshot template uid feat(ateapi): track actor_template_uid per snapshot on ExternalSnapshot and LocalSnapshotInfo Sep 17, 2026
CreateActor now stamps the resolved template UID onto the golden
ExternalSnapshot it seeds, so the functional test expectations for create,
update, resume, and pause must carry it too.
@shrutiyam-glitch
shrutiyam-glitch marked this pull request as ready for review September 17, 2026 20:09
@bowei Bowei Du (bowei) added kind/feature An enhancement / feature request or implementation area/api User-facing API changes area/api-machinery labels Sep 17, 2026
}

//
// Pause under template B while the external snapshot is still from

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.

// Pause under template B while the external snapshot is still from
// template A: LocalSnapshotInfo records template B while ExternalSnapshot
// retains template A.

Is that true? After pause, the ExternalSnapshot entry should be cleared from the Actor.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ensurePausedFinalized sets LocalSnapshotInfo and clears WorkerAssignment, leaving ExternalSnapshot intact.

// captured under a template other than the actor's current one. They are
// tracked separately because the two can have been captured under
// different templates, and each restore path reads only its own.
LocalTemplateReplaced bool

@zoez7 Zoe Zhao (zoez7) Sep 18, 2026

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.

LocalTemplateReplaced should not be possible, updating an actor template is only allowed for suspended actors, this might be an existing bug.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

my bad, I went through the flow again, updating an actor's template is only possible in suspended state.
whenever an actor resumes from a local pause checkpoint (LocalSnapshotInfo != nil), its template could not have been changed via UpdateActor since the pause checkpoint was taken. So LocalTemplateReplaced is not required, removed and update the title and pr desc.

@shrutiyam-glitch shrutiyam-glitch changed the title feat(ateapi): track actor_template_uid per snapshot on ExternalSnapshot and LocalSnapshotInfo feat(ateapi): track actor_template_uid per snapshot on ExternalSnapshot Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/api User-facing API changes area/api-machinery kind/feature An enhancement / feature request or implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants