TaskSultan Docs tasksultan.com

Migrating from UiPath

Turning UiPath selectors into targets

How stored UiPath selectors become semantic targets, how the Object Repository is read first and how the live bind pass proves each one.

uipath targets reads every stored UiPath selector and tells you which ones become a semantic target, which need a human and which are refused. uipath bind then opens the running pages and binds each target against the live accessibility surface.

#What a stored target is

A UiPath workflow stores an element as a selector string inside a TargetAnchorable node. Two attributes matter. The element selector lives in FullSelectorArgument (older activities use Selector and a fuzzy-only target uses FuzzySelectorArgument). The page it lives on is the scope anchor in ScopeSelectorArgument, an <html> node whose title names the page.

Selectors arrive HTML-escaped in the XAML, so the reader unescapes them before parsing.

#Synthesising a semantic locator

TaskSultan automation code addresses elements by role, label or text. CSS selectors, XPath, .nth() and generated class chains are forbidden and enforced by a locator policy. So the synthesiser never translates a selector. It decides, from the selector's own attributes, whether a semantic locator can be derived and refuses by name when it cannot.

Class What it means
SYNTHESISED A role is implied by the tag or type and an accessible name is present, so the result is getByRole.
SYNTHESISED_TEXT A name is present but no role, so the result is getByText.
SYNTHESISED_DESCRIPTOR Both halves of the locator were stated by the Object Repository.
NEEDS_REVIEW_ID Only an id is present. A test-id proposal that a human confirms.
REFUSED_AMBIGUOUS A role but no name: several elements could match.
REFUSED_POSITIONAL Only an index or a CSS chain. Positional by definition.
REFUSED_NO_EVIDENCE Nothing usable at all.
REFUSED_DYNAMIC The selector is null or an expression, built at run time.
WINDOW A page or window anchor, not an element.
DESKTOP A desktop surface, out of scope for an automation.

A synthesised target carries a policy-clean strategy() snippet in the Target Repository's own shape. A refused target carries a TODO(review) with the reason. Positional evidence is checked before an id: an id beside an index is the id that matched more than one element.

#The Object Repository is the primary input

A modern project keeps its descriptors under <project>/.objects/, as .metadata nodes joined by Reference and ParentRef, each with a .content payload. The Reference a workflow's target carries is the same string as the descriptor's own Reference, so the join needs no name matching.

When a target cites a reference, the repository is the primary input and the inline selector is corroboration. A descriptor whose TaxonomyType and Name are both present becomes a SYNTHESISED_DESCRIPTOR, because nothing was inferred from a selector. The measured mapping is small: Button, Input and Password map to getByRole, Label to getByText. Any other taxonomy is refused rather than guessed. So are a descriptor that names an object the store does not carry, one whose payload cannot be read, one whose SearchSteps is not Selector and one with an unknown Version.

npx tsx orchestrator/cli.ts uipath targets ./MyProject

#The live pass

uipath bind treats the selector as a hint about which element to find, then asks the live page for that element's accessible identity. A binding holds only when the hint finds exactly one element, a semantic locator built from that element's live identity resolves to exactly one node and a stamp proves the node is the same one.

Class What it means
BOUND Unique and proven to be the hinted element.
BOUND_CHAINED As bound, disambiguated through a landmark ancestor.
NEEDS_REVIEW_ID No semantic identity on the page; only a test-id is possible.
REFUSED_AMBIGUOUS Still matches more than one element, never resolved with .nth().
NOT_FOUND The hint found no element on that page.
REFUSED_UNBINDABLE The selector is a window anchor, not an element.

The pass is read-only: it types nothing and clicks nothing. With --credential <name> it also binds targets behind a login, resolving the credential by name from the vault, never printing a value. It exits 0 when every target bound, 1 when a human is needed and 2 when the pass could not run.

#Things that catch people out

  • The static snippet and the live binding are different artefacts. A NEEDS_REVIEW_ID from targets may still bind through the page.
  • Bound targets are referenced by name; no selector is emitted into an automation.