Record bindings
A binding is a file under bindings/<app>/<page>/<element>.yaml that names an
element by a ranked bundle of candidates and a structural fingerprint. Recording
is the only time an element is chosen; replay reads the file.
yam recordwith nothing after it does something else: it records a new flow from what you do in the browser (see your first flow). This guide is about binding the targets of a flow that was written or drafted, which isyam record --flow <file>oryam record --all.
In a plain Playwright project
YAM_MODE=record YAM_HEADED=1 npx playwright test
Each bind(id, phrase) whose id is unbound opens a picker in the headed browser:
click the element, and the binding is synthesised with provenance.model: "human". No model is involved.
In CI there is nobody to click, so YAM_PICK names the element per id:
YAM_MODE=record YAM_PICK='{"login.username-field":"username"}' npx playwright test
A bare word is a test id, anything else a CSS selector. It is a test affordance for exercising the record path headless, not a way to write selectors again.
In a flow project
yam record --all # you click: the default at a terminal with no credential
yam record --gateway anthropic # a model grounds each phrase
yam record --flow flows/login.flow --story "Sign in" --rebind
The recorder drives the compiled plan on the configured adapter. For every
target phrase it takes a snapshot and grounds the phrase to a reference. With
the human gateway the browser that opened shows an overlay naming the phrase
and waits for your click; Escape stops the session. With a model gateway the
model reads the snapshot and proposes. Either way the recorder then calls
describe() on the element and synthesises candidates and a fingerprint. With a model, every proposal is
shown for review before anything is written, and the binding carries the model,
the prompt version and the snapshot hash as provenance.
--rebind re-records elements that already have a binding. --input k=v
supplies signature inputs; secrets come from YAM_INPUT_<NAME> in the
environment, never the command line.
What a binding contains
id: login.username-field
phrases: ["the username field"]
context: { hash: "…", role: form }
candidates:
- { by: testId, value: username }
- { by: role, role: textbox, name: Username }
- { by: css, value: "form#login input[name=username]" }
fingerprint: { role: textbox, name: Username, neighbours: [...], box: [...] }
provenance: { model: human, at: "…" }
Candidates are tried in order at replay until exactly one element matches. The
fingerprint is what healing scores against when none does.
The store format is LLD §3.3 and §6.1; yam bindings list, show and
verify read it from a terminal.