Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Type the rect-requiring resolution rows as ref-bearing instead of proving it by comment

Closed
#3,576 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

A pull request for this has already been merged.

  • #3608 by @kkkhs — merged

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
22/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript
Domain
devtools

Research direction

Start with the producer-fact paragraph in packages/kernel/src/snapshot.ts (the JSDoc on SnapshotNode.ref), then the pipeline entry in packages/selectors that resolves targets. Add a narrowing entry keyed on resolution.requireRect, and move the four ref-printing sites in find.ts (lines 200 and 426), target-visibility-stages.ts, resolution-disclosure.ts, selector-action-resolution.ts:43 and selector-pipeline.ts:245 onto it. Done means tsc -b (repo and examples/sdk) and pnpm check:affected pass with no new ?? '' coercions and no output changes.

Written by the indexing model from the issue text.

Description

ready-for-agent refactor

Purpose

SnapshotNode.ref became optional in #3547. The type still lets a pipeline row that requires a rect carry a ref-less node, and four acting-path sites print node.ref unguarded. They are safe today only because of a producer fact recorded in the field's JSDoc (packages/kernel/src/snapshot.ts, the "A ref-less node also carries no rect" paragraph): producers measure geometry only for refs they issued, so a rect-bearing node always has a ref. That invariant is currently a runtime fact, not a type fact. Make it one.

Required behavior

A resolution row whose policy declares resolution.requireRect: true is typed so its node cannot be ref-less, and the acting-path prints stop being provable-by-comment.

  • Add the narrow type beside SnapshotNode (name it for the domain, e.g. an addressable-node type = SnapshotNode & { ref: string }), and a pipeline entry point that narrows a resolved target through the row's requireRect policy — one place that turns the producer fact into the type fact.
  • The rect-requiring consumers take the narrowed type: src/commands/interaction/runtime/target-visibility-stages.ts, resolution-disclosure.ts, the acting rows in src/daemon/interaction/internal/find.ts (find.ts:200, :426), and selector-action-resolution.ts:43 / selector-pipeline.ts:245 as the narrowing demands.
  • Read rows keep returning plain SnapshotNode — a ref-less node is legitimately selectable by text and by find/wait/get. One outcome type cannot serve both rows; that is why this needs a narrowing entry, not a field type.

Measured cost (why this was deferred)

A first attempt typed the resolver and classifier as addressable (SnapshotAddressableNode + a hasSnapshotRef guard) instead of narrowing at the pipeline entry: tsc -b produced 28 errors across 5 files (18 in packages/selectors/src/__tests__/interaction-targeting.test.ts, 7 inside interaction-targeting.ts, one each at selector-pipeline.ts:245, selector-action-resolution.ts:43, and the new test). The guards relocate inward — tree walks yield SnapshotNode[] — and the four named prints are fed by the pipeline outcome, not by the resolver, so typing the resolver does not reach them. The narrowing entry is the smaller change; expect test-fixture widening more than new logic.

Completion conditions

  • The four prints listed above read a ref the checker knows is present; no new ?? ''-style coercion appears.
  • tsc -b (repo + examples/sdk) green, pnpm check:affected green.
  • No behavior change is possible; if a test's observable output moves, that is a bug in the narrowing, not an expected diff.

Dependencies

#3547 (optional ref, the producer-fact JSDoc) and #3515 (the router case proving a ref-less text line is selectable but never a target — the runtime side of this invariant).

Dominant language
TypeScript
Stars
5k
Forks
334
Avg merge
13h 19m
Merged PRs (30d)
630

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from callstack/agent-device

All issues in callstack/agent-device

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.