fix(studio): cross-file tripwire guard + stale-session disk check

Two resolver-shadow noise classes from production telemetry:

- Cross-file guard (0.7.41: 479 false element_not_found from ONE
  session): the dom-edit tripwire ran for edits targeting a different
  file than the session models. The cutover gates already decline these
  (wrongCompositionFile); the tripwire now skips the same way — no
  event, no attempt, since the op structurally cannot cut over.

- Stale-session disambiguation (0.7.48: 53 animation_not_found across
  keyframe ops): the GSAP panel derives animationIds from the CURRENT
  on-disk script every render, while the session's parsed id space
  dates from the last reload. Position edits shift every
  selector-method-position id, so panel ops landing before the reload
  target ids the session has never seen. Parser id-space parity was
  verified across legacy/acorn read/write paths (9 script shapes) —
  the ids agree; the session is just behind. On a miss with a reader
  wired, recordAnimationResolverParity now re-parses the on-disk file:
  a hit there = stale session (suppress); a miss there = genuine
  divergence, tagged diskChecked so the dashboard can trust the class.

Attempt-counter machinery moved to sdkResolverAttempts.ts (600-LOC
studio file gate); re-exported from sdkResolverShadow for API compat.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Vance Ingalls
2026-07-14 12:28:47 -07:00
co-authored by Claude Fable 5
parent e05debe1af
commit 405af8f8ba
5 changed files with 296 additions and 97 deletions
@@ -260,8 +260,13 @@ export function useDomEditSession({
? (selection, operations, originalContent, targetPath, options) => {
// Resolver shadow runs regardless of the cutover flag — decoupled tripwire.
// Pass originalContent so the runtime-node filter can suppress hf-ids
// absent from source (script-created nodes the SDK can't model).
runResolverShadow(sdkSession, selection.hfId, operations, originalContent);
// absent from source (script-created nodes the SDK can't model), and
// the paths so cross-file edits (session models only the active comp)
// skip instead of emitting structural element_not_found noise.
runResolverShadow(sdkSession, selection.hfId, operations, originalContent, {
targetPath,
compositionPath: activeCompPath,
});
return sdkCutoverPersist(
selection,
operations,