Friction Generators as Registry - cprima-forks/uipath-ai-skills GitHub Wiki

Friction: Generators Are the Registry

The most significant architectural observation in the codebase: the generators are the implicit registry. There is no separate layer that knows what attributes are valid for a given activity — that knowledge lives exclusively inside the f-string templates.

What This Means in Practice

Attribute knowledge (which attributes exist, what values they accept, what their defaults are) is fused with assembly logic (how to construct the XML element) inside individual generator functions. The two concerns cannot be separated without refactoring.

For example, the knowledge that NTypeInto accepts EmptyFieldMode with values None, SingleLine, MultiLine — and defaults to SingleLine — exists only as a hardcoded string in ui_automation.py:16:

f'EmptyFieldMode="{empty_field_mode}"'

...with the default and validation in the function signature:

def gen_ntypeinto(..., empty_field_mode="SingleLine", ...):

...and the enum validation in _constants.py:

VALID_EMPTY_FIELD_MODES = {"None", "SingleLine", "MultiLine"}

Three files, three representations of the same fact.

Consequences

Adding a new attribute (e.g., a self-healing attribute added in a later package release) requires:

  1. Finding the generator function(s) for affected activities
  2. Adding the attribute to the f-string
  3. Adding a parameter to the function signature
  4. Possibly adding enum validation to _constants.py
  5. Updating snapshots

There is no single place to make the change.

Version-aware generation is not possible in the current design. The generators always emit the 24.10 attribute set — there is no mechanism to consult a version and emit a different set of attributes for an older or newer package.

The registry cannot be queried independently. There is no function get_valid_attributes("NTypeInto", "24.10"). The only way to know what attributes a generator emits is to read the generator source code or run the generator.

Relevant Design Patterns

A refactoring toward a version-aware, queryable registry could draw on:

Pattern Application
Table-Driven Attribute sets live in a data structure keyed by (activity, version); generator is a generic emitter that reads from it. Most consistent with the existing data-driven style (HINT_SIZES, TYPE_MAP_BASE, _REGISTRY).
Strategy Each package version is a strategy providing its attribute set; the generator function is the context that uses it. Clean when XAML element structure stays the same but attribute lists change.
Builder A per-activity builder accumulates only the attributes valid for the target version, then renders. Verbose but explicit.

Note: a Table-Driven registry for attributes alone would not be sufficient — see Friction: Structural Knowledge in F-Strings for the additional structural knowledge also embedded in the generators.