LearnNewsExamplesServices
Frontmatter
id13248
titleNL undo Slice-1 Sub A1: capture set_instance_properties reverses onto the undo stack
stateClosed
labels
aiarchitecture
assigneesneo-opus-vega
createdAtJun 14, 2026, 7:37 PM
updatedAtJun 14, 2026, 8:54 PM
githubUrlhttps://github.com/neomjs/neo/issues/13248
authorneo-opus-vega
commentsCount0
parentIssue13221
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 14, 2026, 8:54 PM

NL undo Slice-1 Sub A1: capture set_instance_properties reverses onto the undo stack

neo-opus-vega
neo-opus-vega commented on Jun 14, 2026, 7:37 PM

Context

Sub A1 of #13221 (Neural Link mutation undo, Slice-1), built on the merged #13238 (agentId, sessionId) 2-tuple TransactionService core. The first wiring slice: capture the reverse of a set_instance_properties write so it becomes undoable. (The undo NL tool + two-agent e2e = Sub A2; create_component / remove_component capture = Sub B.)

The Fix

  • Neo.ai.Client owns a per-heap TransactionService (sibling to WriteGuard, same singleton shape).
  • Neo.ai.client.InstanceService.setInstanceProperties captures the reverse-op (set⁻¹ = set(oldValues)) post-enforcement-grant, keyed on the live {agentId, sessionId} context, via a begin/record/commit per write. buildSetReverse captures the pre-set values + the audit targetSubtreePath; recordUndo commits the single-op tx best-effort.

Acceptance Criteria

  • Client owns a per-heap TransactionService.
  • An enforcement-granted set_instance_properties agent write captures set⁻¹ (the pre-set values) onto the writer's (agentId, sessionId) stack; multiple writes accumulate as separate committed transactions.
  • A legacy write (no context) applies but is not captured (no writer identity ⇒ no per-writer stack).
  • The capture is best-effort + fail-closed: a malformed / unserializable reverse, or an absent stack authority, is dropped (abort), never thrown into the forward write path.
  • Unit-tested.

Out of Scope

  • The undo NL tool (6-site wiring) + the two-agent e2e — Sub A2.
  • create_component / remove_component capture (needs a node-side marker, since they arrive app-side as generic call_method add/destroy) — Sub B.

Related

Authored by @neo-opus-vega (Claude Opus 4.8, Claude Code). Origin Session ID: 4cc428e3-cf36-4324-8646-1b96cb23fa4a.