Custom Steps
The @custom convention — a documented escape hatch for test steps that don’t fit any existing Control × Action combination yet.
← Back to overview · 🇩🇪 Deutsch · ← CI Integration · Step-Description Localization →
What is a Custom Step?
A test-case author working in a test-management tool sometimes needs a step that has no existing View × Control × Action combination to reuse — a check or action nobody has automated yet. Rather than blocking the manual test run on that gap, the step is recorded as a Custom Step: free text describing what should happen, plus a small set of optional structured hints about which UI element it targets.
A Custom Step runs fine as part of a manual test execution from day one — it renders like any other step, with its own outcome. What it doesn’t have yet is an automated implementation. This page documents the convention that makes such steps discoverable and machine-readable, so that automated implementation — by your own tooling, or by future framework capabilities — has something stable to build on.
💡 Why not just skip automation for these steps? Because the convention lets you track which steps are still manual, how many there are, and what they’re about — all without writing a single line of automation code up front. See Discovering and validating Custom Steps below for a ready-to-run coverage script.
Where Custom Steps come from
If your test-management tool has a “Custom” option for a step that doesn’t match an existing combination, it typically writes a Custom Step directly into your App’s step-library file, following the convention on this page — check your tool’s own documentation for exactly how it authors the file. You can also write one by hand at any time; the convention doesn’t require any particular authoring tool.
Writing a Custom Step by hand
A Custom Step is a normal TS_* exported function in your App’s 2_Steps folder, marked with a @custom JSDoc block. The template ships at 2_Apps/_Skeleton/2_Steps/TS_Custom.ts:
// 2_Apps/<YourApp>/2_Steps/TS_Custom.ts
import * as Core from '@meintest/cc-testframework';
/**
* @custom
* @step s_example
* @intent check
* @target { view: Main, control: Textfield, label: 'Email' }
* @property color
* @operator equals
* @expected red
*/
export const TS_Custom_Example = async (_pageLogName: string) => {
await Core.Step.numberedStep(`Check that the 'Email' field's color is red`, async () => {
throw new Error('Custom step not yet automated');
});
};
Copy this file, rename the export to something descriptive (e.g. TS_Custom_CheckEmailFieldColor), and adjust the JSDoc tags and the numberedStep description to match your case. Until it’s implemented, the step’s body stays exactly as shown — the throw new Error('Custom step not yet automated') line is what marks it as pending.
💡 Why is the description in the step body, not in the JSDoc? The tester-facing text a manual run displays comes from the
numberedStep(…)argument, not from a separate JSDoc tag. There is deliberately no@descriptiontag — keeping the wording in one single place means the description shown to a manual tester can never drift out of sync with what any tooling reads. Need that description to show up in a tester’s own language instead of English? See Localizing Custom-Steps below — a sibling catalog file, not a JSDoc tag, is where a translation lives.
💡 Custom Step vs.
Core.defineExecutionStep. These solve different problems. A Custom Step targets a concrete Control — an element check or interaction nobody has automated yet — and is either hand-written or agent-generated at authoring time.Core.defineExecutionStepis a framework-level scaffold for an App’s own lifecycle (Start/Close/Restart/NavigateTo); it injectspage/url(Web) orexecutable/appiumUrl(Desktop) for you fromGlobalConfig.apps, so you never target a specific Control at all. See API Reference — Section 16 for its signature.
Tag reference
| Tag | Required | Values | Meaning |
|---|---|---|---|
@custom | Yes | (presence only, no value) | Marks this export as a Custom Step. |
@step | Yes | s_ + at least 4 lowercase letters/digits, e.g. s_ab12 | Stable step identity. Keep this value unchanged once assigned — it’s what ties a manual run’s outcome and history to this exact step, even after it gets an automated implementation. |
@intent | Yes | check | action | Whether the step verifies something or performs something. |
@target | No | { view: Main\|Dialog\|Message, section: '...', control: '...', label: '...' } | Hints at which UI element the step targets. Quotes around values are optional. The more slots you fill, the less guessing an automated implementation has to do. |
@property | No | free text, e.g. color, text, visible | The property being checked or acted upon. |
@operator | No | equals | contains | not | exists | greater | less | Comparison operator — only meaningful when @intent is check. |
@expected | No | free text, e.g. red | The expected value, when applicable. |
💡 What if I don’t know the exact Control name yet? Fill in as much of
@targetas you can and leave the rest out —sectionandlabelalone are often enough for a human (or tool) to locate the right element later. An empty@targetis valid too; it just means more guesswork downstream.
You’ll never write @custom’s counterpart tag by hand: once the Authoring Agent implements a step, it replaces @custom with @implementedAt <timestamp> as an audit trail — every other tag, @step included, stays untouched.
Localizing Custom-Steps
The shipped TS_Custom.ts template calls Core.i18n.t(...) directly, instead of passing a raw string to numberedStep(...):
export const TS_Custom_Example = async (_pageLogName: string) => {
await Core.Step.numberedStep(
Core.i18n.t('TS_Custom_Example', {}, {
fallback: `Check that the 'Email' field's color is red`,
}),
async () => {
throw new Error('Custom step not yet automated');
},
);
};
Core.i18n.t(key, values, { fallback }) looks up key in the sibling TS_Custom.i18n.json catalog for the tester’s current locale — auto-detected from the step file’s own location, you never pass a path yourself — and falls back to the fallback string when no catalog, key, or locale entry exists.
Custom-Step code is generated at the moment it’s authored — typically by the Authoring Agent — with no catalog file existing yet for the new key. That’s why fallback stays inline here rather than being omitted the way a catalog-backed factory step would: until a translator adds a TS_Custom.i18n.json entry for this key, fallback is the runtime source-of-truth for this step’s English text — there’s nothing else to fall back to. See When to use fallback for the full reasoning, and Step-Description Localization for the full catalog convention. Add translated entries to TS_Custom.i18n.json the same way you would for any other step file; Runtime localization covers how GlobalConfig.language/CC_TESTFRAMEWORK_LOCALE determine the locale t() resolves against.
Discovering and validating Custom Steps
Two functions, exported from the framework’s public API, let you scan your project for Custom Steps and check them for authoring mistakes — independent of any test-management tool:
import { discoverCustomSteps, validateCustomStep } from '@meintest/cc-testframework';
import * as path from 'path';
const discoveries = await discoverCustomSteps(path.join(process.cwd(), 'tests'));
for (const discovery of discoveries) {
const result = validateCustomStep(discovery);
const status = discovery.isNotImplemented ? 'pending' : 'implemented';
console.log(`${discovery.spec.stepId} (${discovery.stepName}) in ${discovery.file}:${discovery.line} — ${status}`);
if (!result.isValid) {
console.error(' errors:', result.errors);
}
if (result.warnings.length > 0) {
console.warn(' warnings:', result.warnings);
}
}
discoverCustomSteps(rootDir) walks <rootDir>/2_Apps/*/2_Steps/*.ts, parses every @custom-marked export via the TypeScript compiler, and returns one CustomStepDiscovery per step — in file order, top-to-bottom. If your project has no 2_Apps folder yet, it returns an empty array rather than an error.
validateCustomStep(discovery) checks a single discovery for common authoring mistakes and separates blocking issues from informational ones:
| Check | Severity |
|---|---|
stepId missing or doesn’t match s_[a-z0-9]{4,} | Error |
intent missing or not check/action | Error |
description missing or empty | Error |
operator set but not a recognized value | Error |
target.view set but not Main/Dialog/Message | Error |
target missing entirely | Warning |
intent is check but neither property nor expected is set | Warning |
intent is action but operator is set | Warning |
Errors mean the step can’t reliably be implemented as-is and should go back to its author for correction. Warnings are informational — the step can still be worked on, just with less guidance.
💡 Duplicate step IDs. If two Custom Steps across different Apps share the same
@stepvalue,discoverCustomStepslogs a warning to the console but still returns both — resolving the collision (e.g. renaming one) is up to whoever consumes the discovery results.
Types
import type { CustomSpec, CustomStepDiscovery, ValidationResult } from '@meintest/cc-testframework';
See API Reference — Section 12 for the full field-by-field breakdown of these three types.
Automated implementation: the Authoring Agent
Turning a discovered Custom Step into a working implementation no longer has to be done by hand. runAuthoringAgent(options), exported from the framework’s public API, takes your project’s Custom Steps plus a digest of your application’s current UI tree, and — for each step it’s confident about — generates a real implementation and writes it into the owning file.
import { runAuthoringAgent } from '@meintest/cc-testframework';
import * as path from 'path';
const result = await runAuthoringAgent({
rootDir: path.join(process.cwd(), 'tests'),
treeDigest: myLiveTreeDigest, // a live-app UI-tree digest — see below
dryRun: true, // preview only; no file is written yet
onProgress: (event) => console.log(`[${event.phase}] ${event.message}`),
});
console.log(`${result.applied.length} applied, ${result.skipped.length} skipped, ${result.errors.length} errored`);
Set dryRun: false (or omit it — that’s the default) once you’ve reviewed a preview run and are ready to have the agent write real files.
💡 Where does
treeDigestcome from? The agent needs a snapshot of your application’s current UI tree — the same format the framework’s own inspection tooling produces internally. Capturing that snapshot yourself (boot the app, capture the tree, pass it in) is only necessary when callingrunAuthoringAgentdirectly. The command-line entry point further down this page captures it for you end-to-end — see Running the agent from the command line.
What gets generated
Each applied step gets one of two shapes, recorded in AppliedStep.implementation:
control-action— a call into an existing framework method (Core.Action.click,Core.Check.textContentEquals, and similar) on a freshly resolved locator. This is what most@intent: actionsteps and well-specified@intent: checksteps get.inline-script— a reviewable stub for a@customcombination the agent has no concrete template for yet. The generated body is marked with a// TODO(agent)comment and deliberately throws, so it’s unmistakable to a human reviewer that this call-site still needs a real implementation.
Every generated locator uses the Core.xpath tag (see Self-Healing Locators), so agent-written call-sites are self-healing-eligible from the moment they’re created — no extra step needed. Writes go through the same coordination layer Self-Healing writeback uses (see Self-Healing Locators — Multi-user coordination), so an agent run is safe to enable in a shared repository.
Once a step is implemented, its @custom JSDoc tag is replaced with @implementedAt <timestamp>. Every other tag — critically @step — is left completely untouched, so the step’s identity in your test-management tool’s history never changes, even after it gains an automated implementation.
💡 One template currently generates code that doesn’t compile yet. A
@property color/@operator equalscheck calls aCheckmethod the framework doesn’t ship yet. Until that method lands, review any applied color-check Custom Step and adjust the assertion by hand before relying on the test to pass — the agent still records it asapplied, since it did write something, but it isn’t runnable as-is.
How generated code is verified
Every step the Authoring Agent writes is checked against the Skeleton Conventions rule set before it lands in your source file — the same check that guards a hand-written step. If a fatal issue turns up, the agent retries with a focused fix description, up to three attempts in total; if it still fails, the step is skipped instead of writing code that wouldn’t pass validation.
What you see.
| Case | What happens |
|---|---|
| The generated code passes | Nothing — the step is written and the run continues silently. This is the common case. |
| The check finds a fatal issue | A line such as retry attempt 2/3 — fixing convention violations appears in the run’s output while the Authoring Agent tries again. |
| All 3 attempts still fail | The step is skipped. It appears in AuthoringResult.skipped[] with reason: 'convention-guard-rejected' — see Why a step gets skipped below for the full table of skip reasons — and the accompanying detail lists exactly which rule(s) the generated code violated. |
A rejected step doesn’t stay silently broken — you have two options: fix the underlying ambiguity by hand (make the Custom Step’s @target/@property/@expected tags more specific, or implement the step yourself) and re-run the agent, or accept the skip for now and revisit it later. Either way, the step keeps behaving as a normal, unautomated Custom Step in the meantime.
💡 Which rules apply here? The same six described in Skeleton Conventions — R2 (naming), R3 (signature), and R4 (XPath style) do most of the work, since those are what LLM-generated code is most likely to drift on from one generation to the next.
Configuration
| Env-var | Effect |
|---|---|
ANTHROPIC_API_KEY | Required (BYOK) — the same key used for Self-Healing’s Vision calls. The agent’s default element-finder throws immediately if this is unset, no anthropicApiKey option was passed to runAuthoringAgent, and nothing is resolvable via the OS credential store either. |
AI_VISION_MODEL | Optional. Overrides the Claude model used to identify target elements. Defaults to claude-opus-4-7. Also settable via npx cc-testframework set-ai-vision-model <model> or the aiVisionModel config field. |
CC_AUTHORING_MAX_STEPS_PER_RUN | Optional safety circuit-breaker. Caps how many Custom Steps a single run processes; any remainder is reported as skipped (max-steps-reached, see below) instead of attempted. Unlimited if unset. The maxSteps option, if passed, takes precedence over the env-var. |
Why a step gets skipped
AuthoringResult.skipped[] entries carry a reason explaining why the agent didn’t implement that step:
reason | Meaning |
|---|---|
validation-failed | The step’s @custom tags don’t pass validateCustomStep — fix the authoring mistake and re-run. |
duplicate-step-id | The same @step id is declared in more than one App. Resolve the collision (rename one) before re-running — both copies are skipped until you do. |
already-implemented | The body no longer throws the “not yet automated” placeholder even though @custom is still present — the agent never overwrites an existing implementation. |
element-not-found | No element in the supplied treeDigest matched this step’s target hints. |
agent-uncertain | A candidate element was found, but confidence was too low to act on — the agent skips rather than implement against a guess. |
agent-uncertain-underspecified | @intent: check is set but neither @property nor @expected is — there isn’t enough information to generate a meaningful assertion. |
max-steps-reached | The run’s step budget (CC_AUTHORING_MAX_STEPS_PER_RUN / maxSteps) was already used up when this step’s turn came. |
file-locked-by-human | Another writer (a colleague, another CI job, or any tool sharing the same write-coordination protocol) currently holds the write lock for this file — see Self-Healing Locators — Multi-user coordination. |
convention-guard-rejected | The generated code didn’t pass the Skeleton Conventions check within 3 attempts. See How generated code is verified above for what leads up to this. |
The result object
runAuthoringAgent returns an AuthoringResult — it doesn’t persist a report file on its own, so if you call it directly and want a JSON artifact for a CI step (e.g. to post a PR comment), write it yourself, similar in spirit to Self-Healing’s .self-healing-report.json. The command-line entry point below persists exactly this shape automatically, at the --report-path you choose (default .custom-step-authoring-report.json):
{
"schemaVersion": 1,
"runTimestamp": "2026-07-14T10:03:21.000Z",
"mode": "applied",
"totalDiscovered": 2,
"applied": [
{
"stepId": "s_ab12",
"file": "2_Apps/<YourApp>/2_Steps/TS_Custom.ts",
"stepName": "TS_Custom_CheckEmailFieldColor",
"implementation": "control-action",
"elementId": "txtEmail",
"confidence": "high",
"reasoning": "Digest lists a Textfield with AutomationId='txtEmail' matching the target label 'Email'.",
"filesWritten": ["2_Apps/<YourApp>/2_Steps/TS_Custom.ts"]
}
],
"skipped": [
{
"stepId": "s_cd34",
"file": "2_Apps/<YourApp>/2_Steps/TS_Custom.ts",
"stepName": "TS_Custom_SubmitOrder",
"reason": "agent-uncertain",
"reasonDetail": "Two buttons labelled 'Submit' are visible; the target hint doesn't disambiguate them."
}
],
"errors": [],
"commitSha": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"
}
commitSha and lockedByHumans appear under the same conditions as their Self-Healing counterparts — see Self-Healing Locators — The report file for the underlying coordination semantics.
Running the agent from the command line
npx cc-testframework author runs in one of two mutually exclusive modes. Both ship as part of the framework’s own package — no extra install step, available the moment @meintest/cc-testframework is installed.
| Mode | Flag | What it does |
|---|---|---|
| Runtime (default) | --test <path> | Runs a whole Test-Case iteratively — on every failure it classifies the cause and, for the failure kinds it has a strategy for, dispatches the Authoring Agent, then re-runs the test — until it passes end-to-end or hits a non-fixable failure or a circuit-breaker. |
| Batch (legacy) | --batch-mode --app <name> | The original behavior: implements every @custom-tagged step in a single App’s 2_Steps/ folder against one live snapshot of that App. |
Passing both flags, or neither, exits with code 2 before either mode starts.
Runtime mode: fixing a whole Test-Case
From inside pm/:
export ANTHROPIC_API_KEY="sk-ant-..."
npx cc-testframework author --test 3_Cases/TC_<YourFlow>.spec.ts --dry-run
💡 Rather not export the key every session?
export ANTHROPIC_API_KEY=...keeps working exactly as shown, but it’s no longer the only option —npx cc-testframework config set anthropic-api-keystores it once in your OS’s credential store, and the CLI prompts for it interactively on first use if you skip both. See Credential Management for the full setup.
Runtime mode never boots a live-App session or reads apps.json itself — it spawns your Test-Case as a real Playwright subprocess (--workers=1 --reporter=json) and lets whatever Control/Step code the test already exercises talk to your app(s) normally. That’s also what makes a Multi-App Test-Case work (e.g. a web-app step followed by a mailbox-check step): the loop only cares about the test’s pass/fail outcome and, on failure, which file:line the failure points at.
On every failed run, the failure is classified into one of three fixable kinds — the only ones the agent attempts to act on:
| Classification | What it means |
|---|---|
custom-not-implemented | A @custom-tagged step’s placeholder is still throwing — the same trigger as batch mode, just discovered per-failure instead of upfront. |
element-not-found-no-refid | A locator search failed to find its element, and the failing line has no Inspector.bindReference call nearby — so Self-Healing had no reference screenshot to repair it against. |
timeout-no-refid | Same as above, but the failure was a timeout rather than “not found”. |
Every other shape (a genuine assertion mismatch, a code-level error, a network failure, a crashed browser, or an “element not found” case where a reference screenshot IS nearby — Self-Healing already had its chance) is left for a human: the loop stops immediately with finalStatus: 'failed-non-fixable'.
💡 What happens when an already-implemented step breaks?
element-not-found-no-refidandtimeout-no-refidcover exactly this: a step that isn’t a Custom Step at all, but started failing after your application changed, with no Self-Healing reference image to fall back on. The agent diagnoses the failure and identifies the likely correct element the same way it does for a Custom Step — but writing that fix back into the file automatically is not yet supported for this category. An already-implemented step’s JSDoc has no@customtag, and the writer deliberately refuses to touch a file with no such marker, the same rule that stops every Custom-Step write from silently overwriting hand-written code. In practice, this classification retries up to--max-attempts-per-steptimes and the run then stops withfinalStatus: 'stuck-in-loop'. Re-run the same Test-Case with--dry-run— the resulting report’sapplied[]entry for that location shows the element and reasoning the agent identified, for you to apply by hand. Full automation for this category is planned for a later release.
Options
| Option | Effect |
|---|---|
--test <path> | Required for Runtime mode. Path to the Test-Case spec file to run and fix. |
--dry-run | Preview mode — classification, Vision, and code generation still run, but no file is written. |
--max-iterations <N> | Global circuit-breaker across the whole run. Default 20 (env-var CC_AUTHORING_MAX_ITERATIONS). |
--max-attempts-per-step <N> | Per-location circuit-breaker — how many times the same file:line may be retried before the run gives up on it. Default 3 (env-var CC_AUTHORING_MAX_ATTEMPTS_PER_STEP). |
--report-path <path> | Where to write the JSON report. Default: <cwd>/.custom-step-authoring-runtime-report.json — a separate file/schema from batch mode’s report. |
--help, -h | Prints the options for both modes and exits. |
Configuration otherwise matches above (ANTHROPIC_API_KEY, AI_VISION_MODEL, or the OS credential store as an alternative to the env-var), plus SELF_HEALING_AGENT_IDENTITY for the auto-commit’s author identity — see Self-Healing Locators — Commit identity.
💡 Typo’d
--testpath? When Playwright’s own JSON report confirms the given path/pattern matched zero test files — the most common cause is a typo, e.g. a missing underscore — the loop doesn’t stay silent about it: it prints[AuthorTestRunner] Warning: Playwright matched 0 test files for pattern '<path>'. Possible typo? Run 'npx playwright test --list' to see all detected test files., emits aplaywright-0-testsprogress event, and records an entry in the report’scredentialIssuesarray (kind: 'playwright-0-tests', with the offendingpattern). NeitherfinalStatusnor the exit code change because of this alone — matching zero tests via a deliberate--grepfilter is legitimate — but because Playwright itself exits0for “0 tests matched”, the same run can otherwise look like a cleanfinalStatus: 'passed'. Always checkcredentialIssueseven after an apparent pass.
Example output
[test-run] iteration 1: Running '3_Cases/TC_<YourFlow>.spec.ts' (attempt 1/20)...
[test-fail] iteration 1: Test failed (exitCode=1) — classifying...
[classify] iteration 1: Classified as 'custom-not-implemented' (fixable=true).
[fix-attempt] iteration 1: Dispatching the Authoring Agent for '2_Apps/<YourApp>/2_Steps/TS_Custom.ts:12' (attempt 1/3)...
[fix-applied] iteration 1: Fix applied (commit a1b2c3d).
[test-run] iteration 2: Running '3_Cases/TC_<YourFlow>.spec.ts' (attempt 2/20)...
[test-pass] iteration 2: Test passed.
[done] iteration 2: Runtime-Authoring-Loop finished: passed (2 iteration(s), 1 distinct fix location(s)).
finalStatus, persisted in the report, is one of:
finalStatus | Meaning |
|---|---|
passed | The Test-Case ran green. |
failed-non-fixable | A failure with no fix strategy was hit — see the classification table above. |
stuck-in-loop | The same file:line location exceeded --max-attempts-per-step. |
max-iterations-reached | The whole run exceeded --max-iterations before converging. |
Batch mode (legacy): one App, one pass
export ANTHROPIC_API_KEY="sk-ant-..."
npx cc-testframework author --batch-mode --app <YourApp> --dry-run
Unchanged since its original release: boots a live session for the named App, captures its UI-tree digest, implements every @custom-tagged step under that App’s 2_Steps/ folder in one pass, and persists an AuthoringResult report (see The result object and the skip-reason table above for its shape).
| Option | Effect |
|---|---|
--batch-mode | Required to select this mode. |
--app <name> | Required. The App to author Custom Steps for — must match a key in your apps.json. One App per run. |
--tests-root <path> | Path to your tests root. Default: <cwd>/tests. |
--apps-config <path> | Path to apps.json. Default: the same auto-discovery order the Inspector CLIs already use — explicit path, then CCTF_APPS_CONFIG, then <project root>/apps.json, then <cwd>/apps.json. |
--dry-run | Preview mode — Vision and code generation still run, but no file is written. |
--max-steps <N> | Caps how many Custom Steps this run attempts. CC_AUTHORING_MAX_STEPS_PER_RUN takes precedence if both are set. |
--report-path <path> | Where to write the JSON report. Default: <cwd>/.custom-step-authoring-report.json. |
Exit codes (both modes)
| Code | Runtime mode | Batch mode |
|---|---|---|
0 | finalStatus: 'passed'. | Every attempted step applied, or zero Custom Steps were found. |
1 | Non-fixable failure, stuck-in-loop, or max-iterations reached. | The agent recorded at least one entry in errors[]. |
2 | User error — missing/conflicting --test/--batch-mode, the --test path not found, or projectRoot not a git repository. | User error — missing --app, a plainly missing Anthropic API key (nothing resolvable anywhere in the priority chain), an invalid --tests-root, or an --app value not present in apps.json. |
3 | (not used) | Every attempted step was skipped with reason: 'file-locked-by-human' — a colleague (or another CI job) holds the coordination lock on every targeted file. A partial lock still exits 0. |
4 | finalStatus: 'credential-error' — the Anthropic API key could not be resolved for ANY reason (missing, expired, invalid, or a non-interactive context where the first-run prompt cannot run). See AuthorTestResult.credentialIssues and Credential Management. | Only when the resolved credential is expired — a plainly missing key still exits 2 (see above); Batch mode doesn’t otherwise distinguish credential-resolution failure reasons. |
💡 Wiring this into CI. Because the exit codes separate agent/loop-errors (
1) from a lock stand-off (3, batch mode only), a pipeline can treat them differently — see FAQ — How do I wire the Authoring Agent into my CI pipeline? for a short example.
💡 Prefer calling this programmatically instead of shelling out?
runAuthorCli(options)covers both modes with the same behavior, plus test-injection hooks for advanced tooling. Only need Runtime mode’s loop, without the CLI’s argv-shaped options?runAuthorTestRunner(options)is the same logicrunAuthorClidelegates to internally. See API Reference — Section 12.
Where to go next
- Writing Your First TestCase — the
TS_Custom_<Action>naming convention and how a Custom Step’s name fits alongsideCore.defineExecutionStep-scaffolded steps - API Reference —
discoverCustomSteps,validateCustomStep,runAuthoringAgent,runAuthorCli,runAuthorTestRunner,classifyFailure,synthesizeCustomStepFromFailure, and every related type - Skeleton Conventions — the naming, signature, and XPath-style rules the generated code above is checked against
- Step-Description Localization — showing a step’s description in a tester’s own language via a sibling
.i18n.jsoncatalog, and howCore.i18n.t(...)renders it at runtime - Credential Management — storing the Anthropic API key in your OS credential store instead of an env-var, the
configCLI, and what exit code4means - FAQ — tracking Custom Steps that aren’t automated yet, plus Authoring-Agent troubleshooting
- Self-Healing Locators —
Core.xpath, multi-user write coordination, and BYOK cost details shared by the Authoring Agent
📧 Questions? Contact: jens.szelag@itsbusiness.ch
itsbusiness AG · Bern · Switzerland