Skip to content

refactor(interaction): resolve the CapturedSnapshot name collision - #1371

Merged
thymikee merged 1 commit into
mainfrom
refactor/captured-snapshot-collision
Jul 23, 2026
Merged

refactor(interaction): resolve the CapturedSnapshot name collision#1371
thymikee merged 1 commit into
mainfrom
refactor/captured-snapshot-collision

Conversation

@thymikee

Copy link
Copy Markdown
Member

The collision

src/commands/interaction/runtime/resolution.ts and its sibling selector-read-shared.ts each exported an unrelated type named CapturedSnapshot:

  • resolution.ts: { snapshot: SnapshotState }
  • selector-read-shared.ts: { sessionName: string; session?: CommandSessionRecord; snapshot: SnapshotState }

Same name, different shapes, same directory.

What changed

Renamed resolution.ts's narrow type to InteractionSnapshot, kept selector-read-shared.ts's CapturedSnapshot as-is. Did not unify into one type.

Why rename instead of unify: resolution.ts's CapturedSnapshot/InteractionSnapshot is purely internal — nothing outside resolution.ts imports it (verified via grep across src/, including src/index.ts, src/sdk/, and package.json exports — neither type reaches the public surface). Its three producers (captureInteractionSnapshot, resolveSnapshotForRef, reconcileFreshObservation) never populate or consume sessionName/session — they only ever read .snapshot. resolution.ts already separately consumes the other CapturedSnapshot (via requireSnapshotSession, intersected with { session: CommandSessionRecord }) exactly where session identity is actually needed for ref freshness reconciliation. Force-merging the two would mean threading unused sessionName/session fields through resolution's internal plumbing purely to satisfy a shared name — manufacturing data no consumer reads, not "truthfully supplying" it in any meaningful sense. Kept them distinct instead.

Optionality decision (session?: on selector-read-shared's CapturedSnapshot)

Left as optional. Evidence: requireSnapshotSession guarantees session (throws SESSION_NOT_FOUND first, already reflected via its & { session: CommandSessionRecord } return-type intersection). But the other producer, captureSelectorSnapshot, does not guarantee it — const session = await runtime.sessions.get(sessionName); has no presence check, and the function deliberately tolerates an absent session (captureOptions.updateSession && session && ... at line 84 skips the session-store write rather than failing). This is a live, intentional code path, not a theoretical gap, so the field must stay optional.

Shared guard opportunity (skipped)

captureInteractionSnapshot in resolution.ts re-inlines a runtime.sessions.get + SESSION_NOT_FOUND guard that looks like requireSnapshotSession. Not reused: requireSnapshotSession additionally requires an existing refFrameSnapshot ?? snapshot and throws INVALID_ARGS when absent. captureInteractionSnapshot must work for a session that has no snapshot yet (it captures one fresh) — swapping in the shared helper would introduce a new failure mode and change behavior. Skipped to keep this behavior-identical.

Verification

  • pnpm typecheck — pass
  • pnpm lint — pass
  • pnpm check:fallow — pass, no issues in the 1 changed file
  • pnpm vitest run src/commands --project unit-core — 40 files / 339 tests, all pass

Files changed

  • src/commands/interaction/runtime/resolution.ts (rename only; 4 lines)

resolution.ts and selector-read-shared.ts (both in
src/commands/interaction/runtime/) each exported an unrelated
CapturedSnapshot type with a different shape. resolution.ts's export
is never imported anywhere else, so rename it to InteractionSnapshot
rather than force a merge with the richer, session-carrying shape
that selector-read.ts/settle.ts/stable-capture.ts actually depend on.
@github-actions

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.8 MB 1.8 MB 0 B
JS gzip 577.7 kB 577.7 kB 0 B
npm tarball 692.3 kB 692.3 kB 0 B
npm unpacked 2.4 MB 2.4 MB 0 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 22.8 ms 24.3 ms +1.5 ms
CLI --help 47.4 ms 47.9 ms +0.5 ms

Top changed chunks: no changes in the largest emitted chunks.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Jul 23, 2026
@thymikee

Copy link
Copy Markdown
Member Author

Review clean at fec31f0. The change only renames resolution.ts’s internal { snapshot: SnapshotState } type and its three local signatures; the richer sibling CapturedSnapshot remains separate, no external import/export exists, and production behavior is unchanged. All 24 exact-head checks pass. No device evidence is needed for this type-only rename. No separately authorized cross-vendor review was performed.

@thymikee
thymikee merged commit 0b0deb3 into main Jul 23, 2026
24 checks passed
@thymikee
thymikee deleted the refactor/captured-snapshot-collision branch July 23, 2026 07:57
@github-actions

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-23 07:57 UTC

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

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant