uipath-test · diff
git:20261106.5c0d1ef to git:20261106.9222806
98 added, 129 removed. Audit A to A.
---
name: uipath-test
- description: "UiPath Test Manager — manage test projects, requirements, cases, sets, executions, defects; schedule test sets on a recurring cadence; AI-generate test cases from requirements, evaluate requirements, find obsolete test cases; run every test in an uploaded package from CI; performance (load) test scenarios; generate reports; package and run external Playwright test suites. For Orchestrator→uipath-platform. For Studio/RPA test automation authoring→uipath-rpa."
+ description: "UiPath Test Manager (`uip tm`) — test projects, requirements, cases, sets, executions, logs, defects; recurring test set schedules; AI test case generation, requirement evaluation, obsolete test case search; CI run of every test in an uploaded package; performance (load) test scenarios; test reports; package/run external Playwright suites. Orchestrator→uipath-platform. Studio/RPA test authoring→uipath-rpa."
allowed-tools: Bash, Read, Write, Glob, Grep
user-invocable: true
---
# UiPath Test Assistant
- Manage UiPath Test Manager projects, requirements (including AI test case generation, requirement evaluation and obsolete test case search), test cases, test sets, executions, logs, defects, attachments, results, custom fields, performance (load) test scenarios, labels, and persona-tailored shareable test reports.
+ Manage UiPath Test Manager projects, requirements (AI generation/evaluation/obsolete-case search), cases/sets, executions/logs, defects, attachments/results, custom fields, performance scenarios, labels, and persona-tailored reports.
## Use For
- Test Manager CRUD; CI runs of every test in an uploaded package; execution analysis, coverage, regression trends, failure rates, go/no-go summaries; failed-run triage; flaky-versus-regression analysis; failure evidence; load-testing an automated test case and finding why a load run failed; and shareable QA-engineer, developer, or release-manager reports.
+ Use for Test Manager CRUD; CI runs of every test in an uploaded package; execution analysis, coverage, regression trends, failure rates, go/no-go summaries, failed-run triage, flaky-versus-regression analysis, failure evidence, load testing/failure diagnosis, and QA-engineer, developer, or release-manager reports.
When the request asks to operate Test Manager through its Integration Service connector (not `uip tm`), run `uip is resources run` per `/uipath-platform` (`references/integration-service/resources.md`). Building a `.flow`/`.bpmn`/API workflow that uses the connector→its authoring skill.
## Critical Rules
- 1. **Always check login first:** run `uip login status --output json` before any Test Manager operation. If unauthenticated, run `uip login`.
- 2. **Always pass `--output json`** to every `uip` command, without exception.
- 3. **Cap retries at 3** for any failing `uip` command. After three failures, stop and report the error; never use direct REST APIs.
- 4. An empty list stops the operation and informs the user rather than proceeding with a null key. Exception: empty `tm testcases list --filter` may be a prefix miss; use Rule 8's prefix fallback and stop only if it also finds nothing. Empty filtered project or customfield lookups are real empty results and stop normally.
- 5. **Confirm before delete:** confirm the target resource key unless the user already authorized that exact delete. Every delete requires `--yes` or `-y`; omission exits without deleting.
- 6. For a required folder key, use `uip or folders list -n <folder-name> --all --output json` when the user named the folder; when choosing one yourself, omit `--all` to list only member folders. Run `/uipath-platform` for folder-management details.
- 7. **Discover before assuming:** never guess automation names, folder keys, project IDs, or testcase keys; run the matching list first, such as `uip tm testcases list-automations` or `uip or folders list -n <folder-name> --all`.
- 8. **Narrow named-entity list calls server-side:** when given a name, key, label, or tag, inspect `uip tm <resource> list --help` or `uip or <resource> list --help` for its narrowing flag and use it. Never list all then filter client-side; this applies to every entity across `uip tm` and `uip or`, and to result filters too: a failed run's logs are `executions testcaselogs list --only-failed`, a case's failures are `testcases list-result-history --only-failed`. Exception: `tm testcases list --filter` is prefix matching. If a mid-name term returns zero, retry with a broader contextual prefix; relist without `--filter` only if no workable prefix exists, walking every page (Rule 11) before concluding absence.
- 9. **Default-folder recovery:** `uip tm testcases run` and `uip tm testsets run` require a project default folder. Attempt the run first. Only when failure text exactly includes `"Message": "HTTP 400: Please assign folder to project level before executing testcases."` and `errorCode: itemNotFound`, run `uip tm project set-default-folder --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY> --output json`, then retry once. Get keys with `uip or folders list -n <folder-name> --all --output json`. Do not interpret other errors as missing folders: an unusable default gives opaque `HTTP 5xx`; a nonexistent folder key gives `"HTTP 400: Internal Server Error."` with `errorCode: unknown`. Both stop under Rule 10. Never overwrite a working default folder; an arbitrary folder may be rejected by Test Manager and break later runs. This is the only named run exception to Rule 10; all other run failures stop.
- 10. **Any `uip` failure or ambiguity stops and asks the user:** this includes command errors, malformed output, unclear flags/values, multiple matches, missing identifiers, or unexpected schemas. Never fall back to REST. Exceptions are expected outcomes identified exactly, plus one fixable mistake of your own: (a) the Rule 9 missing-folder error, handled there; (b) `uip tm wait` exit code 2 with `Timed out after <N>s waiting for execution '<EXECUTION_ID>'. Last status: <status>.`, which means bounded timeout worked—report non-finish and continue remaining steps. `Polling failed/interrupted/aborted ...` and exit code 1 are real wait failures; (c) a requirement AI command exiting 2 with `ErrorCode: timeout`: the job is still running, so resume it with the `--activity-id … --wait` command its `Instructions` name, never a new start; (d) `uip tm run --type package` exit code 1 with `"Code": "RunPackageTestsFailed"` or `"RunPackageCancelled"` and `"ErrorCode": "execution_failed"`, which means the run finished with failed or no tests, or was cancelled—report `Data` (counts, `OutputPath`, `ExecutionUrl`) and do not retry; (e) a `ValidationError` about a flag you passed (`unknown option`, `missing required option`): read `<command> --help`, fix the flags, and run it again once (counts toward Rule 3); a second usage error on the same command stops. Every other failure stops.
- 11. **Walk the pages before concluding an item is absent:** list responses carry only `Data`, with no total, cursor, or has-more flag. A page that returns exactly as many rows as `--limit` (default 50) may have more, so when the item you need is not on it, rerun the same list with `--offset` raised by the page size until a page comes back short. Page size is capped at 100: `--limit` above 100 fails with `HTTP 400 … Page size cannot be greater than 100.` For a list without `--limit`/`--offset`, such as `tm testcases list`, narrow with its filter flags instead (Rule 8).
+ 1. Before any Test Manager operation run `uip login status --output json`; if unauthenticated run `uip login`.
+ 2. Pass `--output json` to every `uip` command.
+ 3. Retry a failing `uip` command at most 3 times; after three failures stop and report the error. Never use REST.
+ 4. An empty list stops and informs the user rather than proceeding with a null key. Exception: empty `tm testcases list --filter` may be a prefix miss; apply Rule 8 and stop only if that also finds nothing. Empty filtered project/customfield lookups are real empty results and stop normally.
+ 5. Confirm a target key before deletion unless the user authorized that exact delete. Every delete requires `--yes` or `-y`; omission exits without deleting.
+ 6. For a required named folder run `uip or folders list -n <folder-name> --all --output json`; when choosing a folder omit `--all` to list only member folders. Run `/uipath-platform` for folder details.
+ 7. Discover before assuming: never guess automation names, folder keys, project IDs, or testcase keys; list first, e.g. `uip tm testcases list-automations` or `uip or folders list -n <folder-name> --all`.
+ 8. Narrow named entities server-side. Inspect `uip tm <resource> list --help` or `uip or <resource> list --help` and use the narrowing flag; never list all and filter client-side. This applies to every `uip tm`/`uip or` entity and result filter: failed-run logs use `executions testcaselogs list --only-failed`; case failures use `testcases list-result-history --only-failed`. `tm testcases list --filter` is prefix matching. If a mid-name term returns zero, retry with a broader contextual prefix; relist without `--filter` only when no workable prefix exists, walking every page under Rule 11 before concluding absence.
+ 9. `uip tm testcases run` and `uip tm testsets run` require a project default folder. Attempt the run first. Only when failure text exactly includes `"Message": "HTTP 400: Please assign folder to project level before executing testcases."` and `errorCode: itemNotFound`, run `uip tm project set-default-folder --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY> --output json`, then retry once. Obtain keys with `uip or folders list -n <folder-name> --all --output json`. Never overwrite a working default. Do not interpret other errors as missing folders: an unusable default gives opaque `HTTP 5xx`; a nonexistent folder gives `"HTTP 400: Internal Server Error."` with `errorCode: unknown`; both stop under Rule 10. This is the only named run exception; all other run failures stop.
+ 10. Any `uip` failure or ambiguity stops and asks the user: command errors, malformed output, unclear flags/values, multiple matches, missing identifiers, or unexpected schemas. Never use REST. Exceptions: (a) Rule 9 missing-folder error; (b) `uip tm wait` exit code 2 with `Timed out after <N>s waiting for execution '<EXECUTION_ID>'. Last status: <status>.`, which means bounded timeout worked—report non-finish and continue remaining steps; `Polling failed/interrupted/aborted ...` or exit code 1 is a real failure; (c) requirement AI exit 2 with `ErrorCode: timeout`: the job is still running, so resume it with the `--activity-id … --wait` command its `Instructions` name, never a new start; (d) `uip tm run --type package` exit 1 with `"Code": "RunPackageTestsFailed"` or `"RunPackageCancelled"` and `"ErrorCode": "execution_failed"`, which means the run finished with failed or no tests, or was cancelled: report `Data` (counts, `OutputPath`, `ExecutionUrl`) and do not retry; (e) `ValidationError` about a passed flag (`unknown option`, `missing required option`): read `<command> --help`, fix the flags, and run it again once (counts toward Rule 3); a second usage error on the same command stops. Every other failure stops.
+ 11. Walk pages before concluding absence. Responses contain only `Data`, with no total/cursor/has-more. If absent and the page has exactly `--limit` rows (default 50), increase `--offset` by the page size until a short page; maximum page size is 100. `--limit` above 100 fails with `HTTP 400 … Page size cannot be greater than 100.` Lists without `--limit`/`--offset`, such as `tm testcases list`, must use filter flags (Rule 8).
## Quick Start
- 1. Verify auth: run `uip login status --output json`; if unauthenticated, run `uip login`. If needed, set the tenant with `uip login tenant set <TENANT_NAME> --output json`. Run `/uipath-platform` for more authentication details.
- 2. Ask for the project name/key before any Test Manager call, except new work with no project named, which goes to the default project (see Default project); for multiple projects collect all names/keys in one prompt. Resolve each with `uip tm project list --filter <NAME_OR_KEY> --output json`. Zero matches stop and ask; multiple matches require presenting candidates and asking the user to choose. Reuse the confirmed `PROJECT_KEY` downstream.
- 3. Use as needed: `uip tm testsets list --project-key <PROJECT_KEY> --filter <TEST_SET_NAME_OR_KEY> --output json`; `uip tm testsets list-testcases --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY> --output json`; `uip tm executions list --project-key <PROJECT_KEY> --test-set-id <TEST_SET_ID> --limit 100 --output json`; `uip tm executions testcaselogs list --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY> --output json` (triaging a red run: add `--only-failed` so only the failed logs come back, then `testcases list-result-history --test-case-id <TEST_CASE_ID> --only-failed` to tell a regression from a flake — [references/failure-triage-guide.md](references/failure-triage-guide.md)); `uip tm testcaselog list-assertions --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json`; `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json`.
+ 1. Verify auth under Rule 1; if needed set the tenant with `uip login tenant set <TENANT_NAME> --output json`; run `/uipath-platform` for authentication details.
+ 2. Ask for the project name/key before any Test Manager call, except new work with no project named, which goes to the default project. For multiple projects ask once for all. Resolve each with `uip tm project list --filter <NAME_OR_KEY> --output json`; zero matches stops and asks; multiple matches require presenting candidates and asking the user to choose. Reuse confirmed `PROJECT_KEY`.
+ 3. Common reads: `uip tm testsets list --project-key <PROJECT_KEY> --filter <TEST_SET_NAME_OR_KEY> --output json`; `uip tm testsets list-testcases --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY> --output json`; `uip tm executions list --project-key <PROJECT_KEY> --test-set-id <TEST_SET_ID> --limit 100 --output json`; `uip tm executions testcaselogs list --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY> --output json` (add `--only-failed` for a red run, then `testcases list-result-history --test-case-id <TEST_CASE_ID> --only-failed` for regression versus flake — [references/failure-triage-guide.md](references/failure-triage-guide.md)); `uip tm testcaselog list-assertions --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json`; `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json`.
## Concepts and CLI
- Requirements define what must be tested; test cases define scenarios and may contain **teststeps**; test sets group cases; executions are created when a test set or testcase runs. Testcase logs record a testcase in an execution and provide navigation; test-step logs record steps; testcase-log assertions are assertion steps. Test Manager's **AI** works from a requirement's description and attachments: it proposes test cases, suggests improvements to the requirement, or flags linked test cases that look obsolete. Each runs as a background job with an activity id. A **defect** is a bug raised from one testcase log and synced to the project's defect tracker (Jira, Azure DevOps, …).
+ Requirements define what must be tested; cases define scenarios and may contain **teststeps**; sets group cases; executions arise from set/case runs; testcase logs lead to step logs; assertions are assertion steps. Test Manager AI uses requirement descriptions and attachments to propose cases, improve requirements, or flag linked obsolete cases; each is a background job with an activity id. Defects originate from one testcase log and sync to Jira, Azure DevOps, or another tracker.
- Performance scenarios load-test automated test cases. A scenario holds **load groups**: a test case, the Orchestrator package and folder it runs from, and a load profile (virtual users, ramp-up, peak, ramp-down). Running a scenario creates an execution; a **dry run** checks it works, a **performance run** applies the full load and draws on the tenant's performance testing licence.
+ Performance scenarios load-test automated cases through load groups containing case, Orchestrator package/folder, and profile (virtual users, ramp-up, peak, ramp-down). Dry runs check scenarios; performance runs apply full load and consume tenant performance-testing licence.
- External Playwright packages are suites packaged and uploaded to Orchestrator. Ingestion auto-creates one testcase per Playwright test, without a link step, and labels each `PW_Tag_*`, `PW_Project_*`, `PW_Suite_*`, and `PW_File_*`. They run on serverless cloud runtimes; see [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md).
+ External Playwright packages are uploaded Orchestrator suites. Ingestion creates one testcase per Playwright test, without a link step, labels each `PW_Tag_*`, `PW_Project_*`, `PW_Suite_*`, and `PW_File_*`, and runs on serverless cloud runtimes. See [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md).
- Use `uip tm`; discover syntax with `uip tm --help` and `uip tm <command> <subcommand> --help`. **Always pass `--output json` to every `uip` command; all commands below require it.** When a value comes from a file, pass it as `"$(cat <FILE>)"`; never retype it from what you read.
+ Use `uip tm`; discover syntax with `uip tm --help` and `uip tm <command> <subcommand> --help`; **Always pass `--output json` to every `uip` command; all commands below require it.** For file values pass `"$(cat <FILE>)"`, never retype read content.
## Commands
- ### Projects, folders, and requirements
+ ### Projects, folders, requirements
- - Projects: `uip tm project list --filter <NAME_OR_KEY>` finds by name/key; `project create --name <PROJECT_NAME> --project-key <PROJECT_KEY>` creates; `project update --project-key <PROJECT_KEY> --name <PROJECT_NAME>` updates name/description; `project delete --project-key <PROJECT_KEY>` deletes; `project set-default-folder --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY>` sets the default Orchestrator folder; `project clear-default-folder --project-key <PROJECT_KEY>` clears it; `project owners list --project-key <PROJECT_KEY> [<PROJECT_KEY> ...]` lists owners.
- - Default project: one per tenant, for runs with no project of their own (CI). Rows of `project list`, `create` and `update` carry `IsDefault`.
- - To find which project is the default, run `uip tm project list --limit 1 --output json` without `--filter`. Test Manager lists the default first, so it is the default only when `Data[0].IsDefault` is `true`. Otherwise this login sees no default: the tenant has none yet, or it has one this login cannot open (the list leaves out projects the caller cannot open). Report that as "no default visible", not as "the tenant has none".
- - `uip tm project get-default --output json` returns the default and **creates one when there is none**: `Default Project` (key `TMDP`), opened to the tenant's Everyone group. Run it only when the user needs a project to work in, never just to look.
- <!-- Intended: get-default may create the tenant's default without asking; the agent then says which project it used. -->
- - **New work with no project named goes to the default project.** When the user asks to create test cases, test sets or requirements, or to run a package, and names no project, run `get-default`, use its `ProjectKey`, and tell the user the work went into that project (name and key). Only for new work: to read, change or delete existing items, ask for the project (Quick Start step 2).
- - `uip tm project update --project-key <PROJECT_KEY> --set-default --output json` makes an existing project the default (needs `TM.Administration`, or a tenant administrator). Who can open that project does not change, so callers without access to it then get `permission_denied` from `get-default`. There is no `project create --set-default`.
- - `permission_denied` from either command: report its `Message` and `Instructions` and stop (Rule 10).
- - Permissions: `uip tm project-permissions get` returns `Data.Permissions` (the permission names the **caller** holds on that project) and `Data.Count`. Gated on `Project.Read`, so a successful `get` always carries at least `Project.Read` (`Count >= 1`); no read access fails with a 403 (or 404 for a project you cannot see), never a `Success` with an empty array. Only `get` is exposed.
- - Project settings: `uip tm project settings get --project-key <PROJECT_KEY>` reads time zone, execution name format, step cap, default folder and governance; `project settings update --project-key <PROJECT_KEY> [--time-zone <IANA_NAME>] [--execution-name-format <TEMPLATE>]` writes only those first two. IANA names, placeholders, read-only fields and half-applied updates: [references/project-settings-guide.md](references/project-settings-guide.md).
- - Get folder keys with `uip or folders list -n <name> --all --output json`; it returns all folders visible to the current user.
- - Prefix with `uip tm requirements`: `list --project-key <PROJECT_KEY>` optionally `--test-case-id <UUID>` (requirements a test case covers — use this, never scan `list-testcase-ids` per requirement), `--filter`, `--labels`, `--requirement-ids`, `--limit`, `--offset`; `list-by-test-execution --project-key <PROJECT_KEY> --execution-id <uuid>`; `get --project-key <PROJECT_KEY> (--requirement-id <uuid> | --requirement-key <key>)` (mutually exclusive UUID/key); `create --project-key <PROJECT_KEY> --name <name>`; `update --project-key <PROJECT_KEY> --requirement-id <uuid>` (updates name/description and requires at least one of `--name` or `--description`); `delete --project-key <PROJECT_KEY> --requirement-ids <uuid...>` (variadic IDs); `export --project-key <PROJECT_KEY> --output-file <path>` (exports `.xlsx`); `list-testcase-ids --project-key <PROJECT_KEY> --requirement-id <uuid>`; `testcases --project-key <PROJECT_KEY> --requirement-id <uuid> (--add-testcase-ids <uuid...> | --remove-testcase-ids <uuid...>)` (mutually exclusive attach/detach selectors).
- - Move or back up a whole project with `uip tm project export` → `uip tm project import` (a `.tmh` package): [references/project-migration-guide.md](references/project-migration-guide.md). Jobs are read with `uip tm migration get|list|download`; package schemas with `uip tm migration schemas list|download`.
- - Both are jobs of minutes. Pass `--wait` (export also `--output-file`); without it you get a job id for `migration get`. Never start a second export or import to check on one.
- - Automation goes in by default (`--exclude automation` drops it); governance, project config (Test Cloud only, else 403) and prompts only with `--include`.
- - Test sets travel only as `.tmh`; test cases and requirements can also go to Excel (`testcases export`, `requirements export`). "Export these" with no format or purpose: ask which.
- - Before importing, ask: into an existing project, or a new one (`--create-project`)? A taken key: ask for `--new-project-key`.
+ Projects: `uip tm project list --filter <NAME_OR_KEY>`; `project create --name <PROJECT_NAME> --project-key <PROJECT_KEY>`; `project update --project-key <PROJECT_KEY> --name <PROJECT_NAME>` (name/description); `project delete --project-key <PROJECT_KEY>`; `project set-default-folder --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY>`; `project clear-default-folder --project-key <PROJECT_KEY>`; `project owners list --project-key <PROJECT_KEY> [<PROJECT_KEY> ...]`. Folders: `uip or folders list -n <name> --all --output json` returns all visible folders.
- ### AI on requirements
+ `project list`, `create`, and `update` rows carry `IsDefault`. Inspect with `uip tm project list --limit 1 --output json` without `--filter`; first row is default only when `Data[0].IsDefault` is `true`, otherwise report "no default visible", not as "the tenant has none" (it may have none, or this login may lack access). `uip tm project get-default --output json` returns or creates `Default Project`, key `TMDP`, opened to the tenant's Everyone group; run only when work needs a project, never merely to inspect. <!-- Intended: get-default may create the tenant's default without asking; the agent then says which project it used. --> When the user asks to create test cases, test sets or requirements, or to run a package, and names no project, run `get-default`, use its `ProjectKey`, and tell the user the work went into that project (name and key). Only for new work: to read, change or delete existing items, ask for the project (Quick Start step 2). `uip tm project update --project-key <PROJECT_KEY> --set-default --output json` makes an existing project default (needs `TM.Administration` or tenant administrator); access does not change, so inaccessible projects yield `permission_denied` from `get-default`. There is no `project create --set-default`. For `permission_denied` from either command report `Message` and `Instructions` and stop (Rule 10).
- `uip tm requirements generate-testcases`, `uip tm requirements evaluate` and `uip tm requirements find-obsolete-testcases` each run a background AI job and return an `ActivityId`. **Each start spends AI units: start once, then reuse `--activity-id <ACTIVITY_ID>` to wait, show, create, unlink or delete; never start again to retry.** Bound waits with `--timeout 540` and a 600 s shell limit. Scenarios, field meanings (`Score`, `ConfidenceLevel`) and the outcome rules: [references/requirement-ai-guide.md](references/requirement-ai-guide.md).
+ `uip tm project-permissions get` returns `Data.Permissions` (the permission names the **caller** holds on that project) and `Data.Count`; it requires `Project.Read`, so success includes `Project.Read` (`Count >= 1`). No access is 403 (or 404 for unseen project), never successful empty permissions. Only `get` is exposed. `uip tm project settings get --project-key <PROJECT_KEY>` reads time zone, execution-name format, step cap, default folder, and governance; `project settings update --project-key <PROJECT_KEY> [--time-zone <IANA_NAME>] [--execution-name-format <TEMPLATE>]` writes only the first two. IANA names, placeholders, read-only fields and half-applied updates: [references/project-settings-guide.md](references/project-settings-guide.md).
- ### Prompt library
+ Requirements: `uip tm requirements list --project-key <PROJECT_KEY>` optionally `--test-case-id <UUID>` (requirements a test case covers — use this, never scan `list-testcase-ids` per requirement), `--filter`, `--labels`, `--requirement-ids`, `--limit`, `--offset`. Also `list-by-test-execution --project-key <PROJECT_KEY> --execution-id <uuid>`; `get --project-key <PROJECT_KEY> (--requirement-id <uuid> | --requirement-key <key>)` (mutually exclusive); `create --project-key <PROJECT_KEY> --name <name>`; `update --project-key <PROJECT_KEY> --requirement-id <uuid>` (name/description, at least one); `delete --project-key <PROJECT_KEY> --requirement-ids <uuid...>`; `export --project-key <PROJECT_KEY> --output-file <path>` (`.xlsx`); `list-testcase-ids --project-key <PROJECT_KEY> --requirement-id <uuid>`; `testcases --project-key <PROJECT_KEY> --requirement-id <uuid> (--add-testcase-ids <uuid...> | --remove-testcase-ids <uuid...>)` (mutually exclusive).
- `uip tm prompts list|get|create` manage a project's reusable AI guidelines. `ModeOfUse` (`--mode-of-use` on `create`, `--modes-of-use` on `list`) is the Autopilot feature that offers the prompt; ask when the user names none.
+ Migration: `uip tm project export` → `uip tm project import` moves or backs up a whole project as `.tmh`; see [references/project-migration-guide.md](references/project-migration-guide.md). Jobs: `uip tm migration get|list|download`; schemas: `uip tm migration schemas list|download`. These are minutes-long jobs: pass `--wait` (export also `--output-file`), otherwise use the job id with `migration get`; never start another export/import to check. Automation is included by default (`--exclude automation` drops it); governance, project config (Test Cloud only, otherwise 403), and prompts require `--include`. Test sets travel only as `.tmh`; cases/requirements may also use Excel (`testcases export`, `requirements export`). If export format/purpose is unspecified ask. Before import ask existing versus new project (`--create-project`); for a taken key ask for `--new-project-key`.
- - No `update` or `delete` in the CLI, and names are not unique. Before `create`, run `get --name <NAME>` (exact, case-sensitive); `ErrorCode: not_found` means absent, not a Rule 10 stop. Found: do not create again; report it, and say changing it needs the Test Manager UI. Several matches: `get` fails; use `--prompt-id` from `list`.
- - `list` mixes built-in samples (`PromptType: Internal`) with team prompts (`UserDefined`); `--filter` is a prefix match on name or description.
- - Guidelines are required, max 4096 characters: `--guidelines`, or `--guidelines-file` for multi-line text. Over a limit fails before anything is sent.
- - `requirements generate-testcases`, `evaluate` and `find-obsolete-testcases` take no prompt id: to apply a library prompt, pass its `Guidelines` as `--instructions`.
- - To export prompts, run `uip tm project export --include prompts`; a default export leaves them out.
+ ### AI on requirements and prompt library
+ `uip tm requirements generate-testcases`, `uip tm requirements evaluate`, and `uip tm requirements find-obsolete-testcases` start jobs and return `ActivityId`; **each start spends AI units: start once, then reuse `--activity-id <ACTIVITY_ID>` to wait/show/create/unlink/delete; never start again to retry.** Use bounded `--timeout 540` and a 600 s shell limit. Scenarios, `Score`, `ConfidenceLevel`, and outcomes: [references/requirement-ai-guide.md](references/requirement-ai-guide.md).
+
+ `uip tm prompts list|get|create` manages reusable project AI guidelines. `ModeOfUse` (`--mode-of-use` on `create`, `--modes-of-use` on `list`) is the Autopilot offering; ask when none is named. There is no `update` or `delete`; names are not unique. Before create run `get --name <NAME>` (exact, case-sensitive); `ErrorCode: not_found` means absent, not Rule 10 stop. If found, do not recreate; report it and say changes require Test Manager UI. Several matches: `get` fails; use `--prompt-id` from `list`. `list` mixes `PromptType: Internal` samples and `UserDefined` team prompts; `--filter` is a prefix match on name or description. Guidelines are required, max 4096 characters, via `--guidelines` or multiline `--guidelines-file`; over-limit fails before sending. AI requirement commands take no prompt id: pass library `Guidelines` as `--instructions`. Export with `uip tm project export --include prompts`; default export omits them.
+
### Test cases
- - `uip tm testcases create --project-key <PROJECT_KEY> --name <TEST_CASE_NAME>`; `list --project-key <PROJECT_KEY>` optionally `--filter <text>` matching name/key by **PREFIX**, not substring; `update --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY> --name <TEST_CASE_NAME>` updates name, description, precondition, or postcondition and requires at least one field; `delete --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>` deletes by key.
- - `link-automation --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY> --folder-key <FOLDER_KEY> --package-name <PACKAGE_NAME> --test-name <TEST_NAME>` links Orchestrator package automation, optionally `--entry-point-id <PACKAGE_ENTRY_POINT_ID>` (from `list-automations`) to bind by id, which overrides `--test-name`; `unlink-automation --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>` unlinks; `list-automations --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY>` lists folder test entry points, optionally `--package-name <PACKAGE_NAME>`, each row carrying `PackageEntryPointId`; `list-testsets --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>` lists containing sets.
- - Look up, inventory, copy and bulk-create test cases with `uip tm testcases` (flags via `--help`):
- - `get --test-case-key` adds what `list` rows lack: pre/postcondition, `Created`, `PackageEntryPointId`. `get --automation-id <PACKAGE_ENTRY_POINT_ID>` returns one case behind an automation; several may share it, so to find all, `list` and match `PackageEntryPointId`. `list-requirements --test-case-key` lists the requirements covering a case. `list-packages` / `list-studio-projects` list the distinct package / Studio project names of automated cases (`--filter` is a prefix).
- - "Which sets include the cases labelled X" is one `list-testsets --labels X`, never a loop over cases. It shows explicit assignments only, not sets that pull a case in by a dynamic label; say so.
- - `clone` returns `Accepted` with no key and copies in the background, steps last. Find the copy with the `list --filter` from `Instructions`. Never clone again to check or retry; after a 5xx, list first, as a copy may exist. Labels, documents, requirements and parameters copy only with `--include`.
- - `bulk-create --file` takes a JSON array of `{"name", "labels": [...], "steps": [{"description", "expectedResult"}]}`. Names are not unique, so a re-run duplicates. Pass `--skip-existing` when some names may already exist. A file error (exit 3) creates nothing. If a later batch fails, earlier ones stay: report and ask before re-running. `KeysResolved: false` still means created.
- - `list --automated` leaves out Playwright-linked cases. A 403 on `group-by` (licence or feature off): stop and tell the user.
- - Steps: `uip tm testcases steps list --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID>` lists manual steps using `--test-case-id <UUID>`, not `--test-case-key`. `steps get --project-key <PROJECT_KEY> --step-id <UUID>` gets; `steps add --project-key <PROJECT_KEY> --test-case-id <UUID> --description <text>` adds flag-mode steps (`--description` required), or `steps add --project-key <PROJECT_KEY> --test-case-id <UUID> --step '<json>' [--step '<json>' ...]` adds repeated JSON steps (mutually exclusive with flag mode and **not atomic**: earlier steps persist if a later one fails); `steps update --project-key <PROJECT_KEY> --step-id <UUID>` updates passed fields only; `steps move --project-key <PROJECT_KEY> --step-id <UUID> --target-position <n>` moves to 0-based position; `steps delete --project-key <PROJECT_KEY> --step-id <UUID> --yes` deletes.
- - `list-result-history --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID>` lists history, optionally `--only-failed`, `--filter`, `--limit`, `--offset`. `run --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID> --name <EXECUTION_NAME> --execution-type <manual|automated|none|mixed>` starts an execution for one or more space-separated testcase UUIDs; optionally `--async`, `--folder-key`, `--robot-user-key`, `--machine-key`.
- - `uip tm testcases add --test-set-key <TEST_SET_KEY> (--test-case-keys <KEY1> <KEY2> … | --labels <Label1> <Label2> …)` adds by explicit keys or every testcase carrying at least one label; selectors are mutually exclusive and variadic space-separated. Keys also accept comma form (`DEMO:1,DEMO:2`), labels do not (`--labels A,B` is one label). Label matching is OR, exact, and case-insensitive; quote labels containing spaces. Without `--dynamic`, `--labels` copies the current matches into the set once; testcases labeled later are not added. `uip tm testcases remove --test-set-key <TEST_SET_KEY> --test-case-keys <KEY1,KEY2,...>` removes comma-separated static links; it succeeds but does nothing for a testcase included only by a dynamic label — change its labels or the set's dynamic labels instead.
- - Assign testcases dynamically (membership follows labels): `uip tm testcases add --test-set-key <TEST_SET_KEY> --labels <Label1> <Label2> … --dynamic` stores the labels on the test set; every testcase carrying at least one (OR, exact, case-insensitive) is part of the set and every run, including testcases labeled later. Merges with labels already set (max 30), keeps static links, returns `DynamicLabels` and `MatchedTestCases`; `--limit` and `--test-case-keys` are rejected with `--dynamic`. `uip tm testcases remove --test-set-key <TEST_SET_KEY> --dynamic [--labels <Label1> …] --yes` removes those labels, or all when `--labels` is omitted (`Result` `Removed`, `Cleared`, or `NotSet`). Not allowed on test sets linked from an external source. Pick `--dynamic` for suites that must track labels (CI "everything labeled smoke"); omit it for a fixed snapshot. If `uip tm testcases add --help` lists no `--dynamic`, the CLI predates it: use `--labels` without it and re-run when labels change.
- - Parameters (`uip tm testcases parameters`, test cases only): the value flag is `--default-value`, not `--value`.
- - Names are unique per test case, match exactly ignoring case, never fuzzily (`User name` ≠ `Username`). Check existence with `list --search` and an exact `Name`; empty means absent, not a Rule 4/10 stop. Read one value with `get --parameter-name <NAME>`; its `not_found` also means absent. Near miss: ask the user to confirm the closest.
- - **An existing parameter is never changed by an "add" request**, even when the request gives a different value: never run `update` for it. Single add: say it exists and ask for another name. Adding to several test cases: skip it, leave its value, and list it as skipped. Changing a missing name: ask before creating it. A rename onto a name in use is refused; report it. Confirm deletes (Rule 5).
- - `delete` returns `Success` even when nothing went; report `Data.Passed`/`Data.Failed`. Adding to many test cases: `list` each, `add` only missing names, then summarise added vs skipped per test case.
- - Use `--test-case-id <UUID>` with `run`, `steps list`, `steps add`, `list-result-history`, and `testcaselog start`/`finish`; obtain it from `uip tm testcases list --output json` (`Id`), or — when you are recording results into a run you just opened — from that run's own logs, which give every id in one call (see Execution lifecycle). Use singular `--test-case-key <PROJECT_KEY:NUMBER>` with `update`, `delete`, `link-automation`, `unlink-automation`, and `list-testsets`. Use plural `--test-case-keys <KEY1,KEY2,...>` for comma-separated test-set bulk membership. Use `--step-id <UUID>` with all `steps` commands except `list` and `add`; obtain it from `steps list` (`Id`).
+ CRUD: `uip tm testcases create --project-key <PROJECT_KEY> --name <TEST_CASE_NAME>`; `list --project-key <PROJECT_KEY>` optionally `--filter <text>` (name/key PREFIX); `update --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY> --name <TEST_CASE_NAME>` (name, description, precondition, or postcondition; one required); `delete --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>`; `get --test-case-key` adds pre/postcondition, `Created`, and `PackageEntryPointId`; `get --automation-id <PACKAGE_ENTRY_POINT_ID>` returns one case though several may share it, so list and match `PackageEntryPointId` for all; `list-requirements --test-case-key <TEST_CASE_KEY>` lists the requirements covering a case (run it to answer which requirements cover a test case); `list-packages`/`list-studio-projects` list distinct names with prefix `--filter`. “Which sets include cases labelled X” is one `list-testsets --labels X`, never a per-case loop; it shows explicit assignments only, not dynamic-label inclusion—say so.
+ Automation: `link-automation --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY> --folder-key <FOLDER_KEY> --package-name <PACKAGE_NAME> --test-name <TEST_NAME>`; optional `--entry-point-id <PACKAGE_ENTRY_POINT_ID>` from `list-automations`, overriding `--test-name`; `unlink-automation --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>`; `list-automations --project-key <PROJECT_KEY> --folder-key <FOLDER_KEY>` optionally `--package-name <PACKAGE_NAME>` (rows carry `PackageEntryPointId`); `list-testsets --project-key <PROJECT_KEY> --test-case-key <TEST_CASE_KEY>`.
+
+ Clone: `clone` returns `Accepted` without a key and copies in background, steps last. Find it using the `list --filter` in `Instructions`; never clone again to check/retry. After 5xx list first because it may exist. Labels, documents, requirements, and parameters copy only with `--include`.
+
+ `bulk-create --file` accepts a JSON array of `{"name", "labels": [...], "steps": [{"description", "expectedResult"}]}`. Names are not unique, so reruns duplicate; pass `--skip-existing` when some names may already exist. File error exit 3 creates nothing. Later-batch failure leaves earlier items: report and ask before rerunning. `KeysResolved: false` still means created. `list --automated` omits Playwright-linked cases. A 403 on `group-by` (licence/feature off): stop and tell the user.
+
+ Steps: `uip tm testcases steps list --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID>` uses UUID, not key; `steps get --project-key <PROJECT_KEY> --step-id <UUID>`; flag mode `steps add --project-key <PROJECT_KEY> --test-case-id <UUID> --description <text>` (`--description` required), or repeated JSON mode `steps add --project-key <PROJECT_KEY> --test-case-id <UUID> --step '<json>' [--step '<json>' ...]` (mutually exclusive, non-atomic; earlier steps persist); `steps update --project-key <PROJECT_KEY> --step-id <UUID>` updates passed fields only; `steps move --project-key <PROJECT_KEY> --step-id <UUID> --target-position <n>` uses 0-based position; `steps delete --project-key <PROJECT_KEY> --step-id <UUID> --yes`.
+
+ History/run: `list-result-history --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID>` optionally `--only-failed`, `--filter`, `--limit`, `--offset`; `run --project-key <PROJECT_KEY> --test-case-id <TEST_CASE_ID> --name <EXECUTION_NAME> --execution-type <manual|automated|none|mixed>` starts one or more space-separated testcase UUIDs and optionally accepts `--async`, `--folder-key`, `--robot-user-key`, `--machine-key`.
+
+ Membership: `uip tm testcases add --test-set-key <TEST_SET_KEY> (--test-case-keys <KEY1> <KEY2> … | --labels <Label1> <Label2> …)` (mutually exclusive/variadic); keys also accept comma form (`DEMO:1,DEMO:2`), labels do not (`--labels A,B` is one label). Labels match OR, exact, case-insensitive; quote spaces. Without `--dynamic`, current matches copy once; testcases labeled later are not added. `uip tm testcases remove --test-set-key <TEST_SET_KEY> --test-case-keys <KEY1,KEY2,...>` removes static links; it succeeds but does nothing for a testcase included only by a dynamic label — change its labels or the set's dynamic labels instead. `uip tm testcases add --test-set-key <TEST_SET_KEY> --labels <Label1> <Label2> … --dynamic` stores labels on the set and includes every current and future case carrying any matching label; it merges labels (max 30), keeps static links, and returns `DynamicLabels` and `MatchedTestCases`; `--limit` and `--test-case-keys` are rejected. `uip tm testcases remove --test-set-key <TEST_SET_KEY> --dynamic [--labels <Label1> …] --yes` removes the named labels, or all of them when `--labels` is omitted, returning `Result` `Removed`, `Cleared`, or `NotSet`; disallowed for externally sourced sets. Use dynamic for tracking suites and omission for snapshots. If `uip tm testcases add --help` lacks `--dynamic`, use labels without it and rerun when labels change.
+
+ Parameters (`uip tm testcases parameters`, test cases only): use `--default-value`, not `--value`. Names are exact, case-insensitive, unique per case, never fuzzy (`User name` ≠ `Username`). Check `list --search` and exact `Name`; empty or `get --parameter-name <NAME>` `not_found` means absent, not Rule 4/10 stop. Near miss: ask the user to confirm the closest. **An existing parameter is never changed by an "add" request**, even when the request gives a different value: never run `update` for it. Single add: say it exists and ask for another name. Adding to several test cases: skip it, leave its value, and list it as skipped. Adding to many test cases: `list` each, `add` only missing names, then summarise added vs skipped per test case. Changing a missing name requires confirmation before creation. A rename onto a name in use is refused; report it. `delete` may return `Success` with no change; report `Data.Passed`/`Data.Failed`. Confirm deletes under Rule 5.
+
+ IDs: use `--test-case-id <UUID>` with `run`, `steps list`, `steps add`, `list-result-history`, and `testcaselog start`/`finish`; obtain from `testcases list` (`Id`) or newly opened run logs (see Execution lifecycle). Use singular `--test-case-key <PROJECT_KEY:NUMBER>` with `update`, `delete`, `link-automation`, `unlink-automation`, `list-testsets`; plural `--test-case-keys <KEY1,KEY2,...>` for bulk membership. Use `--step-id <UUID>` with every `steps` command except `list` and `add`, from `steps list` (`Id`).
+
### Test sets and executions
- - `uip tm testsets create --project-key <PROJECT_KEY> --name <TEST_SET_NAME>`, optionally `--dynamic-labels <Label1> …` to create the set with testcases assigned dynamically by those labels (returns `DynamicLabels`, `MatchedTestCases`); `list --project-key <PROJECT_KEY>` optionally `--filter <text>`, `--folder-key`, `--include-last-execution`; `update --test-set-key <TEST_SET_KEY> --name <TEST_SET_NAME>` updates name/description; `delete --test-set-key <TEST_SET_KEY>`; `list-testcases --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY>` lists the cases a run executes — static links plus dynamic-label matches — with `AssignmentType` `Static`, `Dynamic`, or `Both`; `get-dynamic-assignment --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY>` returns its `DynamicLabels` (`[]` when none) and `MatchedTestCases`.
- - `uip tm testsets run --test-set-key <TEST_SET_KEY>` runs and returns an execution ID; optionally `--execution-type <automated|manual|mixed|none>` (default `automated`), `--input-path <FILE>`, and for Playwright `--playwright-project <name>`. `uip tm testsets playwright-context --test-set-key <TEST_SET_KEY>` probes status and returns `IsPlaywright`, available projects, and selected projects.
- - Keys are `PROJECT_KEY:NUMBER`. Add/remove membership — static or `--dynamic` — with `uip tm testcases add`/`uip tm testcases remove`, not `testsets` verbs. For Playwright sets, `--playwright-project <name>` takes one case-sensitive `playwright.config` name — at most one project per execution — and persists the selection. Every testcase must come from one Playwright package; an unknown name fails fast listing the valid ones. Probe first with `playwright-context` and branch on `IsPlaywright`. Both require Test Manager Playwright support and a CLI carrying external-package commands. See [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md), which begins with the availability check and absent-support action.
- - Configure a set with `uip tm testsets` (`get`, `clone`, `set-execution-order`, `settings get`, `settings set`, `assign-user`, `set-folder`, `set-robot`, `set-execution-target`, `autoselect-packages`, `group-by`, `list --labels`):
- - `clone` waits and returns the copy's `TestSetKey`; `--no-wait` returns `Accepted` with no key. A timeout is a failure: stop and never clone again. Names can repeat, so give the copy one no other set has. Folder, robot, packages, the enforce flag and the order are not copied.
- - `set-execution-order` must list every assigned case (read `list-testcases` first; it does not show the order). Runs follow the order only after `settings set --enforce-execution-order`.
- - In `settings` only the enforce flag is writable; stop-on-failure, coverage, video, remote control and Autopilot are read-only — say so.
- - Name options (`--folder-path`, `--robot-name`, `--assignee-email`) resolve in Orchestrator. A 403 there, or on `set-execution-target`/`group-by` (licence or feature off): stop and tell the user. `autoselect-packages` saves nothing.
- - `uip tm executions list --project-key <PROJECT_KEY>` lists top n, optionally `--test-set-id <UUID>`, `--filter <text>`, `--status`, `--execution-type`, `--execution-finished-interval`, `--limit`, `--offset`; use for the common one-test-set or single-project query. `list-filtered --project-key <PROJECT_KEY>` takes `--test-set-id`, `--status`, `--execution-type`, `--execution-finished-interval`, `--limit`, `--offset` and additionally `--updated-by`, `--labels`, `--test-execution-ids`, `--sort-by`; it has no `--filter` — the name search there is `--search`. Use it for label filtering, multiple execution IDs, custom ordering, or `--updated-by`. Both share the same enum values, which are lower-case and rejected otherwise: `--status <pending|running|cancelling|finished|cancelled>`, `--execution-type <manual|automated|none|mixed|autonomous>`, `--execution-finished-interval <lastHour|lastDay|lastWeek|last15Days|last30Days>`. Responses report `Status` capitalised (`Running`, `Finished`); do not feed a response value back as a filter.
- - `get-stats --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>` aggregates a run's pass/fail/none totals (`report get` also summarizes a completed run). Each `executions list`/`list-filtered` row already carries that run's `Passed`/`Failed`/`None`, equal to `get-stats`, so one list call answers the totals for every run on a set; `run --execution-id <EXECUTION_ID> --execution-type <TYPE>` reruns, optionally `--test-case-log-ids <UUID...>` (space-separated) and `--async`; `retry --execution-id <EXECUTION_ID>` retries only failed cases, optionally `--project-key`, `--test-set-key`, `--execution-type`; `testcaselogs list --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>` lists case logs (`--only-failed`, `--filter`, `--limit`, `--offset`) and is nested, not a top-level `executions` verb. Use `uip tm testcases run` for testcase UUIDs, `uip tm testsets run` for a test-set key, and `uip tm executions run` to rerun an execution.
+ Sets: `uip tm testsets create --project-key <PROJECT_KEY> --name <TEST_SET_NAME>` optionally `--dynamic-labels <Label1> …` (assigns cases dynamically by those labels; returns `DynamicLabels`, `MatchedTestCases`); `list --project-key <PROJECT_KEY>` optionally `--filter <text>`, `--folder-key`, `--include-last-execution`; `update --test-set-key <TEST_SET_KEY> --name <TEST_SET_NAME>`; `delete --test-set-key <TEST_SET_KEY>`; `list-testcases --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY>` lists the cases a run executes — static plus dynamic matches — with `AssignmentType` `Static`, `Dynamic`, or `Both`; `get-dynamic-assignment --project-key <PROJECT_KEY> --test-set-key <TEST_SET_KEY>` returns `DynamicLabels` (`[]` if none) and `MatchedTestCases`.
+ Run: `uip tm testsets run --test-set-key <TEST_SET_KEY>` runs and returns an execution ID; optionally `--execution-type <automated|manual|mixed|none>` (default `automated`), `--input-path <FILE>`, Playwright `--playwright-project <name>`. `playwright-context --test-set-key <TEST_SET_KEY>` returns `IsPlaywright`, available projects, selected projects. Keys are `PROJECT_KEY:NUMBER`; Add/remove membership — static or `--dynamic` — with `uip tm testcases add`/`uip tm testcases remove`, not `testsets` verbs. Probe first and branch on `IsPlaywright`; support and CLI external-package commands are required. `--playwright-project` is one case-sensitive `playwright.config` name, at most one per execution, and persists; every case must come from one Playwright package; unknown names fail listing valid ones. See [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md), beginning with availability and absent-support action.
+
+ Other set commands: `get`, `clone`, `set-execution-order`, `settings get`, `settings set`, `assign-user`, `set-folder`, `set-robot`, `set-execution-target`, `autoselect-packages`, `group-by`, `list --labels`. `clone` waits and returns `TestSetKey`; `--no-wait` returns `Accepted` without key. Timeout fails: stop and never clone again. Names may repeat, so give copies unique names. Folder, robot, packages, enforce flag, and order are not copied. Read `list-testcases` first; `set-execution-order` must include every assigned case and applies only after `settings set --enforce-execution-order`. Only enforce is writable; stop-on-failure, coverage, video, remote control, and Autopilot are read-only — say so. `--folder-path`, `--robot-name`, and `--assignee-email` resolve in Orchestrator. A 403 there or on `set-execution-target`/`group-by` (licence/feature off): stop and tell the user. `autoselect-packages` saves nothing.
+
+ Executions: `uip tm executions list --project-key <PROJECT_KEY>` optionally `--test-set-id <UUID>`, `--filter <text>`, `--status`, `--execution-type`, `--execution-finished-interval`, `--limit`, `--offset`; use it for the common one-test-set or single-project query. `list-filtered --project-key <PROJECT_KEY>` uses `--test-set-id`, `--status`, `--execution-type`, `--execution-finished-interval`, `--limit`, `--offset`, `--updated-by`, `--labels`, `--test-execution-ids`, `--sort-by`; it has no `--filter`, using `--search` for names. Use it for label filtering, multiple execution IDs, custom ordering, or `--updated-by`. Both share the same enum values, lower-case and rejected otherwise: `--status <pending|running|cancelling|finished|cancelled>`, `--execution-type <manual|automated|none|mixed|autonomous>`, `--execution-finished-interval <lastHour|lastDay|lastWeek|last15Days|last30Days>`. Response `Status` is capitalized (`Running`, `Finished`); do not reuse response values as filters.
+
+ `get-stats --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>` aggregates pass/fail/none; `report get` summarizes completed runs. List rows already carry `Passed`/`Failed`/`None`, equal to `get-stats`, so one list call answers the totals for every run on a set. `uip tm executions run --execution-id <EXECUTION_ID> --execution-type <TYPE>` reruns, optionally `--test-case-log-ids <UUID...>` and `--async`; `retry --execution-id <EXECUTION_ID>` retries only failed cases, optionally `--project-key`, `--test-set-key`, `--execution-type`; nested `testcaselogs list --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>` optionally `--only-failed`, `--filter`, `--limit`, `--offset`. Use `testcases run` for testcase UUIDs, `testsets run` for a set key, and `uip tm executions run` to rerun an execution.
+
### Execution lifecycle
- Recording a by-hand test session (manual results produced outside any robot) follows an exact order with several easily-missed rules: there is **no `executions create`** — open the run with `uip tm testsets run --test-set-key <KEY> --execution-type manual` (or `uip tm testcases run --test-case-id <TCID> --execution-type manual` for specific cases); **all three of `--result`, `--has-error`, `--executed-by` are required** on `finish`, or it fails `ValidationError`/exit 3 with an **empty message** (the biggest cause of an unrecorded run); `--executed-by` is stored as the authenticated caller whatever you pass, so pass your own login email; and the run **self-closes only when its _last_ log finishes**. Report totals with `uip tm executions get-stats`, never a hand tally. Full step-by-step, force-close, and `set-reporting-date` rules: [references/executions-guide.md](references/executions-guide.md).
+ There is no `executions create`. Open a manual run with `uip tm testsets run --test-set-key <KEY> --execution-type manual` or `uip tm testcases run --test-case-id <TCID> --execution-type manual` for specific cases. `finish` requires **all three of `--result`, `--has-error`, and `--executed-by`**; omission yields `ValidationError`/exit 3 with an **empty message** (the biggest cause of an unrecorded run). `--executed-by` is stored as the authenticated caller regardless of value, so pass the login email. The run self-closes only when its last log finishes. Report totals with `uip tm executions get-stats`, never a hand tally. Full open/record/finish, force-close, and `set-reporting-date` rules: [references/executions-guide.md](references/executions-guide.md).
### Test set schedules
- - Verbs (`--help` for flags): `uip tm schedules create|update|list|next-runs|enable|disable|delete`. `list` is the only read — no get by id — so recover values there before `update`, which replaces the **whole** definition (pass every flag you want kept; it cannot change the enabled state — use `enable`/`disable`). `delete` and `--all` need `--yes`.
- - `--cron` is **6 or 7 fields starting with seconds**, not Unix cron (daily at 02:00 is `0 0 2 1/1 * ? *`; the CLI refuses a five-field expression client-side). `--cron-details` is the recurrence JSON and is **required for every recurrence type**. `--start-time`/`--disable-time` are wall-clock `YYYY-MM-DDTHH:mm` read in `--timezone` — seconds or a `Z` are refused. Pass `next-runs` the ids `list` prints — the endpoint underneath is keyed by a different GUID and answers `200` with an empty list for a bad id. Cron/recurrence rules and gotchas: [references/schedules-guide.md](references/schedules-guide.md).
- ### Run an uploaded package (CI)
+ Verbs: `uip tm schedules create|update|list|next-runs|enable|disable|delete`; `list` is the only read and has no get by id. Recover values with `list` before `update`; update replaces the whole definition (pass every flag you want kept) and cannot change enabled state (use enable/disable). `delete` and `--all` require `--yes`. `--cron` has 6 or 7 fields starting with seconds, not Unix cron; daily 02:00 is `0 0 2 1/1 * ? *`; five fields are refused client-side. Every recurrence requires `--cron-details` JSON. `--start-time`/`--disable-time` are wall-clock `YYYY-MM-DDTHH:mm` in `--timezone`; seconds and `Z` are refused. Pass `next-runs` ids from `list`; the underlying endpoint uses another GUID and returns `200` with an empty list for a bad id. See [references/schedules-guide.md](references/schedules-guide.md).
- `uip tm run --type package --package-name <PACKAGE_NAME> --package-version <VERSION> --folder-path <FOLDER_PATH> --project-key <PROJECT_KEY> --output json` runs every test in a package already uploaded to Orchestrator, re-runs failures with `--max-retries <N>`, and writes a report. Pack and upload first with `uip rpa pack` / `uip or packages upload`.
+ ### Run an uploaded package (CI)
- - No project named: run `uip tm project get-default --output json` and pass its `ProjectKey` as `--project-key` (see Default project).
- - Get `<VERSION>` from `uip or packages versions <PACKAGE_NAME> --folder-path <FOLDER_PATH> --output json`. An app version (`1.0`) runs its latest `1.0.x` patch; an exact version must be the latest patch, and an older one exits 3 with nothing created.
- - Under a CI step time limit, pass `--timeout <SECONDS>` below that limit (default 7200): a step killed first leaves no report.
- - Exit 1 with `RunPackageTestsFailed` or `RunPackageCancelled` is a test result: report it, see Rule 10(d). Exit 4 is a timeout: the execution may still be running and `Data.OutputPath` holds a partial report with unfinished tests marked skipped. Report the timeout; never count skipped tests as passed. Every other non-zero exit stops (Rule 10).
- - `--input-path` names that no test declares are listed in `Data.IgnoredInputs`; tell the user (usually a typo).
+ `uip tm run --type package --package-name <PACKAGE_NAME> --package-version <VERSION> --folder-path <FOLDER_PATH> --project-key <PROJECT_KEY> --output json` runs every test in an uploaded Orchestrator package, re-runs failures with `--max-retries <N>`, and writes a report. Pack/upload first with `uip rpa pack` / `uip or packages upload`. Without a project run `uip tm project get-default --output json` and use `ProjectKey`. Get `<VERSION>` from `uip or packages versions <PACKAGE_NAME> --folder-path <FOLDER_PATH> --output json`; app version `1.0` selects latest `1.0.x`; exact versions must be latest patch, while older versions exit 3 with nothing created. Under a CI limit pass `--timeout <SECONDS>` below it (default 7200); a step killed first leaves no report. Exit 1 with `RunPackageTestsFailed`/`RunPackageCancelled` is a test result: report it (Rule 10(d)). Exit 4 means timeout: execution may continue and `Data.OutputPath` contains a partial report with unfinished tests skipped; report timeout and never count skipped as passed. Other nonzero exits stop (Rule 10). `--input-path` names that no test declares are listed in `Data.IgnoredInputs`; tell the user (usually a typo).
### Logs, reports, attachments, and results
- - `uip tm testcaselog start --project-key <PROJECT_KEY> --execution-id <EXECUTION_ID> --test-case-id <TEST_CASE_ID>` starts, optionally `--run-id <NUMBER>`. `finish --project-key <PROJECT_KEY> --execution-id <EXECUTION_ID> --test-case-id <TEST_CASE_ID> --result <None|Passed|Failed|Restricted> --has-error <true|false> --executed-by <EMAIL>` finishes and records the result — how a manual run's case is marked `Failed`. **All three of `--result`, `--has-error`, `--executed-by` are required** — omit any and `finish` returns a `ValidationError`/exit 3 with an empty message, not a usage hint. **`--executed-by` takes an email but is validated non-empty then discarded** — the stored `ExecutedBy` is the authenticated caller, so when the user names no executor pass your own login email (`uip login status` → `Data.UserEmail`), and never tell the user a result was attributed to whoever they named. <!-- Verified 2026-10-22, CLI 1.205.0 on alpha: finish without --executed-by fails ValidationError/exit 3 even with --has-error. --> Optionally `--detail-link <URL>`, `--run-id`, `--is-post-condition-met`, `--step-logs <json>` or `--step-logs-file <path>`. `start` needs an existing execution — there is no `executions create`; open one with `uip tm testcases run … --execution-type manual` or `testsets run … --execution-type manual`.
- - Record manual step results on finish: `start` returns the testcase log `Id` and creates one step log per step; `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json` returns one step log per step; pass each back as `{"id":"<STEP_LOG_ID>","testCaseLogId":"<TEST_CASE_LOG_ID>","result":"Passed","comment":"<text>","hasError":false}`. Entries match by step-log `id` (not `testStepId`); unknown ids are silently ignored, and only `result`, `comment`, `hasError`, `hasAttachment` persist.
- - Read logs: `testcaselog list` (filters `--results`/`--statuses`/`--labels`/`--search`/`--assignees`; no date/execution filter — narrow a run with `executions testcaselogs list`); `get --test-case-log-id <ID>` (`--include-assertions`); `latest --test-case-ids <ID...>` (newest per case). **A result is overridden only when `Result` and `OriginalResult` are both populated and differ — an empty `OriginalResult` means not overridden.** Correct a settled result with `override create|update|delete|get` (`create` needs `--result` and `--reason`). Assign a failure with `assign --assignee-email <EMAIL>` (CLI resolves it) or `--assignee-id <IDP_UUID>` (a UUID). `cancel --test-case-log-id <ID> --yes` stops one automated case's Orchestrator job; it answers `CancelRequested` even for a manual or finished log, which it ignores, so confirm with `get` (`Status` `Cancelling`). Whole run: `executions cancel`. Full surface + gotchas: [references/testcaselog-guide.md](references/testcaselog-guide.md).
- - `uip tm testcaselog list-assertions --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID>` lists assertions; `render-assertions` returns them as markdown; `get-robot-logs` returns an expiring link (or downloads with `--output-file`); `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID>` lists step logs.
- - `uip tm report get --execution-id <EXECUTION_ID> (--project-key <KEY> | --test-set-key <KEY>)` summarizes a completed execution (`TotalTests`/`Passed`/`Failed`/`None`, `PassRate` as a number over passed + failed, so unrun `None` tests do not lower it, and `FailedTests`); exactly one project-identifying option is required. Passing only `--execution-id` exits with `Provide --project-key or --test-set-key`.
- - `uip tm attachment download --execution-id <EXECUTION_ID>` downloads testcase attachments; `attachment upload --object-id <UUID> --object-type <type> --file <path>` uploads to a Test Manager object, such as `--object-type testCaseLog`; `uip tm result download --execution-id <EXECUTION_ID>` downloads JUnit XML, optionally `--project-key`, `--test-set-key`, `--result-path <DIR>`.
- - Single files (`uip tm attachment`, `upload` returns `AttachmentId`): find the object first (`list --test-case-keys` / `--requirement-keys`), pick the file by `FileName`, then use its `AttachmentId`; no match or a duplicate name: ask. Already holding an id (from `upload` or an export job): `get --attachment-id <ID> --object-type <TYPE>` reads its metadata.
- - `list` shows only `userBased` files unless you pass `--source` (robot or Studio evidence: `orchestrator`, `studio`, `taskCapture`). Keys that don't resolve come back under `Unresolved` beside the rest — name them. An unknown `--object-ids` id also shows `AttachmentCount: 0`.
- - `--object-type` is the parent object's type, not the file's; a wrong one can still succeed.
- - `download --attachment-id` writes to the current folder under the server name unless `--result-path`/`--output-file`, and never replaces a file: on `already exists`, stop and ask; pass `--overwrite` only when the user asked.
- - `update` only renames (`--file-name`). `--all` is one page per call; follow `Pagination`. `delete --attachment-id <ID> --object-type <TYPE> --yes`: confirm first (Rule 5).
- - Files out: `uip tm testcases export` (test cases to `.xlsx`; `--test-case-ids`, else the whole project) and `uip tm report export` (an execution's report, `--execution-id --format excel|pdf|junit`, or chosen results as PDFs, `--test-case-log-ids`, two or more as one `.zip`):
- - When the user wants the file, pass `--wait --output-file <path>`. Without `--wait` only a job starts: poll `uip tm export-jobs get --job-id` while `Initiated`/`InProgress`, stop on `Failed`/`Cancelled`, then `attachment download --attachment-id <AttachmentId>` as `Instructions` prints. Never start the same export twice to check on it.
- - An existing `--output-file` is refused before anything starts: ask, and pass `--overwrite` only when told.
- - `export-jobs get` needs the project that started the job (others return 404). JUnit off on the tenant (`feature is not enabled`) or a 403 on result PDFs (licence): report it, don't retry.
+ Start/finish: `uip tm testcaselog start --project-key <PROJECT_KEY> --execution-id <EXECUTION_ID> --test-case-id <TEST_CASE_ID>` optionally `--run-id <NUMBER>`. Finish with `finish --project-key <PROJECT_KEY> --execution-id <EXECUTION_ID> --test-case-id <TEST_CASE_ID> --result <None|Passed|Failed|Restricted> --has-error <true|false> --executed-by <EMAIL>`; all mandatory; omission gives `ValidationError`/exit 3 with empty message. `--executed-by` is validated non-empty then discarded; stored `ExecutedBy` is authenticated caller. If no executor is named, use `uip login status` → `Data.UserEmail`; never say the result was attributed to the named executor. Optional: `--detail-link <URL>`, `--run-id`, `--is-post-condition-met`, `--step-logs <json>`, `--step-logs-file <path>`. `start` needs an existing execution; open one with `uip tm testcases run … --execution-type manual` or `testsets run … --execution-type manual`. <!-- Verified 2026-10-22, CLI 1.205.0 on alpha: finish without --executed-by fails ValidationError/exit 3 even with --has-error. -->
+ Record manual step results on finish (`--step-logs`/`--step-logs-file`): `start` returns testcase-log `Id` and creates one step log per step. List with `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json`; pass each back as `{"id":"<STEP_LOG_ID>","testCaseLogId":"<TEST_CASE_LOG_ID>","result":"Passed","comment":"<text>","hasError":false}`. Match step-log `id`, not `testStepId`; unknown ids are silently ignored; only `result`, `comment`, `hasError`, and `hasAttachment` persist.
+
+ Read logs with `testcaselog list` (filters `--results`/`--statuses`/`--labels`/`--search`/`--assignees`; no date/execution filter—use `executions testcaselogs list`), `get --test-case-log-id <ID>` (`--include-assertions`), and `latest --test-case-ids <ID...>` (newest per case). A result is overridden only when `Result` and `OriginalResult` are both populated and differ; empty `OriginalResult` means not overridden. Correct settled results with `override create|update|delete|get`; `create` needs `--result` and `--reason`. Assign with `assign --assignee-email <EMAIL>` (CLI resolves) or `--assignee-id <IDP_UUID>`. `cancel --test-case-log-id <ID> --yes` stops one automated Orchestrator job but returns `CancelRequested` even for manual/finished logs, which ignore it; confirm with `get` (`Status` `Cancelling`). Whole runs use `executions cancel`. See [references/testcaselog-guide.md](references/testcaselog-guide.md).
+
+ `uip tm testcaselog list-assertions --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID>` lists assertions; `render-assertions` returns markdown; `get-robot-logs` returns an expiring link or downloads with `--output-file`; `uip tm teststeplog list --project-key <PROJECT_KEY> --test-case-log-id <TEST_CASE_LOG_ID> --output json` lists steps.
+
+ `uip tm report get --execution-id <EXECUTION_ID> (--project-key <KEY> | --test-set-key <KEY>)` summarizes completed runs (`TotalTests`/`Passed`/`Failed`/`None`, `PassRate` over passed + failed so `None` does not lower it, and `FailedTests`). Exactly one project identifier is required; execution alone exits `Provide --project-key or --test-set-key`.
+
+ Attachments/results: `uip tm attachment download --execution-id <EXECUTION_ID>` downloads testcase attachments; `attachment upload --object-id <UUID> --object-type <type> --file <path>` uploads to an object such as `--object-type testCaseLog`; `uip tm result download --execution-id <EXECUTION_ID>` downloads JUnit XML, optionally `--project-key`, `--test-set-key`, `--result-path <DIR>`. For one file, use `uip tm attachment` (`upload` returns `AttachmentId`): find the object first with `list --test-case-keys` / `--requirement-keys`, select by `FileName`, then use `AttachmentId`; no match or a duplicate name: ask the user. Existing id: `get --attachment-id <ID> --object-type <TYPE>` reads metadata. `list` shows only `userBased` unless `--source` is passed (`orchestrator`, `studio`, `taskCapture`); unresolved keys appear under `Unresolved` and must be named; unknown `--object-ids` yields `AttachmentCount: 0`. `--object-type` is parent type, not file type; wrong type may still succeed. `download --attachment-id` writes to current folder under server name unless `--result-path`/`--output-file`, and never replaces a file: on `already exists`, stop and ask the user; pass `--overwrite` only when the user asked. `update` only renames with `--file-name`. `--all` is one page per call; follow `Pagination`. `delete --attachment-id <ID> --object-type <TYPE> --yes` requires Rule 5 confirmation.
+
+ Exports: `uip tm testcases export` writes `.xlsx` (`--test-case-ids`, otherwise whole project); `uip tm report export` writes reports with `--execution-id --format excel|pdf|junit`, or selected result PDFs with `--test-case-log-ids` (two or more become one `.zip`). When the user wants a file, pass `--wait --output-file <path>`. Without `--wait`, poll `uip tm export-jobs get --job-id` while `Initiated`/`InProgress`, stop on `Failed`/`Cancelled`, then run `attachment download --attachment-id <AttachmentId>` as `Instructions` says. Never start the same export twice. Existing `--output-file` is refused before start; ask and use `--overwrite` only when told. `export-jobs get` requires starting project (others 404). JUnit disabled (`feature is not enabled`) or 403 result PDFs (licence): report it, don't retry.
+
### Playwright pack
- `uip tm pack --project-path <dir> --type playwright --project-key <PROJECT_KEY> --name <PackageName> --package-version <ver> -o <out-dir>` packs a Playwright suite into a `.nupkg`; a lockfile and `@playwright/test` are required. `--package-version` is NuGet/SemVer-style with three or four numeric parts and an optional prerelease/build suffix (`1.0.0`, `1.0.0.0`, `1.0.1-beta.1`); `1.0` and nonnumeric values are rejected. `--project-key` targets the Test Manager project for automatic testcase ingestion; `--no-create-test-cases` skips it; `--dry-run` previews. Upload with `uip or packages upload <nupkg>`. Packing is offline and needs no auth. The upload → ingestion → label-fill → run pipeline is in [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md).
+ `uip tm pack --project-path <dir> --type playwright --project-key <PROJECT_KEY> --name <PackageName> --package-version <ver> -o <out-dir>` packs a Playwright suite into `.nupkg`; lockfile and `@playwright/test` are required. `--package-version` is NuGet/SemVer-style with three or four numeric parts and optional prerelease/build suffix (`1.0.0`, `1.0.0.0`, `1.0.1-beta.1`); `1.0` and nonnumeric values are rejected. `--project-key` enables automatic testcase ingestion; `--no-create-test-cases` skips it; `--dry-run` previews. Upload with `uip or packages upload <nupkg>`. Packing is offline and needs no auth. The upload → ingestion → label-fill → run pipeline is in [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md).
### Defects
- `uip tm defects` `create | list | get | update | delete | get-external-issue | get-related | attachments list|download` — raise a defect from a failed result, change its status/priority/tracker link, and trace it. Defects are UUID-only: find the one on a result through `DefectId` in `executions testcaselogs list`. Before any `defects` call, read [references/defects-guide.md](references/defects-guide.md): `update` and `delete` often take 10–40 s and need a shell time limit of at least 120 s.
+ `uip tm defects` supports `create | list | get | update | delete | get-external-issue | get-related | attachments list|download`; raise from failed results, change status/priority/tracker link, and trace it. Defects are UUID-only: find `DefectId` in `executions testcaselogs list`. Before any defects call, read [references/defects-guide.md](references/defects-guide.md); `update`/`delete` often take 10–40 s and require a shell limit of at least 120 s.
- ### Wait and user
+ ### Wait, user, custom fields, and labels
- `uip tm wait --execution-id <EXECUTION_ID>` waits for terminal state; optionally `--project-key`, `--test-set-key`, `--timeout <SECONDS>`. `uip tm user get` gets the authenticated user's profile.
+ `uip tm wait --execution-id <EXECUTION_ID>` waits for terminal state; optionally `--project-key`, `--test-set-key`, `--timeout <SECONDS>`. `uip tm user get` gets the authenticated profile.
- ### Custom fields
+ Project-scoped custom-field definitions attach to Requirement/TestCase/TestSet, with per-object label/value rows, via `uip tm customfield …`. For full surface, scopes, case-sensitive `--object-type`/`--data-type` enums (`Requirement|TestCase|TestSet`, `Text|Label`), `--values` JSON semantics, and every label/value verb, read [references/custom-fields-guide.md](references/custom-fields-guide.md).
- Project-scoped custom-field **definitions** (attach to Requirement/TestCase/TestSet) plus per-object `label` and `value` rows, via `uip tm customfield …`. Full command surface — scopes, `--object-type`/`--data-type` enums (case-sensitive: `Requirement|TestCase|TestSet`, `Text|Label`), `--values` JSON semantics, and every label/value verb: [references/custom-fields-guide.md](references/custom-fields-guide.md).
+ Use `uip tm objectlabel …` for metadata on `Requirement`, `TestCase`, `TestSet`, `TestExecution`, or `TestCaseLog`. Read [references/object-labels-guide.md](references/object-labels-guide.md), especially label id versus object id and `--remove-other-labels` deleting hidden internal labels.
- ### Object labels
+ ### Performance (load) testing
- Tag metadata via `uip tm objectlabel …` on `Requirement`, `TestCase`, `TestSet`, `TestExecution`, or `TestCaseLog`. Anti-patterns (label id vs object id; `--remove-other-labels` deleting hidden internal labels): [references/object-labels-guide.md](references/object-labels-guide.md).
+ 1. Find the automated case with `testcases list`, then folder/package with `testcases list-automations`. `IsAutomated: false` with `PackageName` is still a legacy link: use that package and never say it lacks automation.
+ 2. Create `uip tm perf-scenario create --project-key <PROJECT_KEY> --name <NAME>`, then `perf-scenario load-groups add --scenario-key <SCENARIO_KEY> --test-case-key <TEST_CASE_KEY> --folder-key <FOLDER_KEY> --package-name <PACKAGE_NAME>`. `add` ignores profile flags and resets to 20 virtual users. Update with `perf-scenario load-groups update --load-group-id <LOAD_GROUP_ID> --project-key <PROJECT_KEY> --virtual-users <N>` using returned id; omit `--package-version` (latest resolves). Robot defaults to `standard`, requiring connected machine with Performance Testing runtimes; serverless requires `--robot-type serverless` on `update` with the profile.
+ 3. Dry-run with `perf-scenario execute --scenario-key <SCENARIO_KEY> --wait`; it ignores profile and uses one virtual user, so do not ask load values first. Full run requires passing `list-dry-run-reports` and enough units from `licenses get`. Before full execution show profile from `get` and have the user confirm/change it with `load-groups update`. Dry-run `RecommendedMultiplexingFactor`/`--multiplexing-factor` applies only to machine robots; leave unset for serverless.
+ 4. Full run: `perf-scenario execute --scenario-key <SCENARIO_KEY> --execution-type performanceTesting --wait`; inspect groups with `load-groups list --execution-id <EXECUTION_ID>` and numbers with `results get`. `report generate --format pdf|html --report-file <FILE>` only publishes a report you write from those results (markdown for pdf, HTML for html) and returns `ViewUrl`.
- ### Performance (load) testing
+ `get`, `delete`, `execute`, and `list-dry-run-reports` take only `--scenario-key` (the key, such as `CLAIM:7441`, already carries the project); `--project-key` fails `unknown option`. `create`, `list`, `stop`, and `licenses get` take `--project-key`; `licenses get` requires one although any project gives the same number. `execute --wait` exit 1 means cancellation, automation failure, or any `SloViolationReasons`, even if output says `Success`: report reasons and never rerun. Exit 4 means `--timeout-sec` (default 1800) passed and run continues: read `results get --execution-id <EXECUTION_ID>`; a new execute starts another run. If shell limit is too short, start without `--wait`, give `ExecutionId`, and use `results get` and `stop --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>`.
- Typical request: "can checkout handle 50 users?"
+ Perf-service reads reject `--project-key` (`unknown option`): `results get`, `http-errors list`, `automation-errors list`, `transaction-metrics list`. The latter three require `--start-time-ms 0 --end-time-ms <DURATION_MS>` with `Duration` from `executions list`. `transaction-metrics` has rows only for API groups; `[]` elsewhere means no data, not zero latency. `--full` and `results get` include per-second series; slim with `--query` and omit series for go/no-go summaries.
- 1. Find the automated test case (`testcases list`), its folder and package (`testcases list-automations`). `IsAutomated: false` with a `PackageName` is still linked (legacy link): use that package, never tell the user it has no automation.
- 2. `uip tm perf-scenario create --project-key <PROJECT_KEY> --name <NAME>`, then `perf-scenario load-groups add --scenario-key <SCENARIO_KEY> --test-case-key <TEST_CASE_KEY> --folder-key <FOLDER_KEY> --package-name <PACKAGE_NAME>`. `add` ignores load-profile flags: Test Manager resets the new load group to its defaults (20 virtual users). Set the profile afterwards with `perf-scenario load-groups update --load-group-id <LOAD_GROUP_ID> --project-key <PROJECT_KEY> --virtual-users <N>`, using the load-group id `add` returns. Omit `--package-version` (resolves the latest). Robot type defaults to `standard`, which needs a connected machine with Performance Testing runtimes; for a serverless folder pass `--robot-type serverless` to `update` with the profile.
- 3. `perf-scenario execute --scenario-key <SCENARIO_KEY> --wait` runs a dry run. It ignores the load profile (one virtual user), so don't ask about load values before it. A full run needs a passing dry run (`list-dry-run-reports`) and enough licence units (`licenses get`). Before the full run, show the load profile from `get` and have the user confirm or change it (`load-groups update`). The dry run's `RecommendedMultiplexingFactor` (`--multiplexing-factor`) is for machine robots only; leave it unset on serverless load groups.
- 4. `perf-scenario execute --scenario-key <SCENARIO_KEY> --execution-type performanceTesting --wait`, then `load-groups list --execution-id <EXECUTION_ID>` for each load group's result, and `results get` for the numbers. `report generate --format pdf|html --report-file <FILE>` only publishes a report you write from them (markdown for pdf, HTML for html) and returns `ViewUrl`.
+ There are two load-group ids: the scenario's load-group ids from `get`/`load-groups add` are for `load-groups update`/`remove`; execution ids from `load-groups list --execution-id <EXECUTION_ID>` are for `load-groups get`, `jobs list`, `robot-logs list`, `http-errors`, `automation-errors`, and `transaction-metrics`; the wrong one returns 404 `not_found`.
- - Which key each verb takes: `get`, `delete`, `execute` and `list-dry-run-reports` take only `--scenario-key` (the key, such as `CLAIM:7441`, already carries the project); passing `--project-key` to them fails with `unknown option`. `create`, `list`, `stop` and `licenses get` take `--project-key`; `licenses get` fails without one, though any project gives the same number.
- - `execute --wait` exits 1 when the run is cancelled, its automation fails, or any `SloViolationReasons` is set, though the output still says `Success`: report the reasons, never re-run to "fix" it. Exit 4 = `--timeout-sec` (default 1800) passed and the run continues: read it with `results get --execution-id <EXECUTION_ID>`; a new `execute` starts another run. A full run longer than your shell limit: start it without `--wait`, give the user the `ExecutionId`, `results get` and `stop --execution-id <EXECUTION_ID> --project-key <PROJECT_KEY>`.
- - Perf-service reads take no `--project-key` (`unknown option`): `results get`, `http-errors list`, `automation-errors list`, `transaction-metrics list`. The last three need `--start-time-ms 0 --end-time-ms <DURATION_MS>` (`Duration` from `executions list`). `transaction-metrics` returns rows for API load groups only; `[]` elsewhere means no data, not zero latency. `--full` and `results get` carry per-second series; slim with `--query` and skip them for go/no-go summaries.
- - Two different load-group ids. `load-groups update` / `remove` take the scenario's load-group id (from `get` or `load-groups add`). `load-groups get`, `jobs list`, `robot-logs list`, `http-errors`, `automation-errors` and `transaction-metrics` take the load group **execution** id from `load-groups list --execution-id <EXECUTION_ID>`. The wrong one returns 404 `not_found`.
- - Find a scenario's key with `perf-scenario list --project-key <PROJECT_KEY> --search <NAME>` (rows under `Data.Scenarios`). Past runs: `perf-scenario executions list --project-key <PROJECT_KEY> --scenario-id <SCENARIO_ID>`, optionally `--execution-type dryRun|performanceTesting` (rows under `Data.Data`; responses capitalise `ExecutionType`). The scenario UUID is not in `list` or `get`. `list-dry-run-reports --scenario-key <SCENARIO_KEY>` returns `ScenarioId` only when a load group's test case has an `AutomationId` (Studio-linked; `link-automation` sets none); otherwise list without `--scenario-id` and match rows whose `Name` starts with the scenario name.
- - `report compare --scenario-id <SCENARIO_ID> --execution-ids <ID...> --report-file <HTML_FILE>` publishes an HTML comparison you write from each run's `results get` (ids oldest to newest, one scenario) and returns `ViewUrl`; add `--project-key` for an in-app link.
- - `licenses get` returns `RemainingVirtualUserUnits` for the whole tenant; it can lag up to 4 hours. A full run uses virtual users × 1 (API), 10 (Chrome/Edge) or 100 (other targets); dry runs use none. If units are short, stop and tell the user.
- - Triage a failed load group with `robot-logs list --load-group-id <ID> --level Error` and `jobs list --load-group-id <ID>`. A 403 means the tenant's performance testing feature or the user's permission is off: stop under Rule 10.
- - `delete --scenario-key <SCENARIO_KEY> --yes` removes the scenario and its load groups for good (Rule 5) and keeps past executions, unlinked. It does not stop a running execution; run `stop` first.
+ Find scenarios with `perf-scenario list --project-key <PROJECT_KEY> --search <NAME>` (`Data.Scenarios`). Past runs: `perf-scenario executions list --project-key <PROJECT_KEY> --scenario-id <SCENARIO_ID>`, optionally `--execution-type dryRun|performanceTesting` (`Data.Data`; response `ExecutionType` capitalized). Scenario UUID is absent from `list`/`get`. `list-dry-run-reports --scenario-key <SCENARIO_KEY>` returns `ScenarioId` only when a group's case has `AutomationId` (Studio-linked; `link-automation` sets none); otherwise list without `--scenario-id` and match rows whose `Name` starts with the scenario name. `report compare --scenario-id <SCENARIO_ID> --execution-ids <ID...> --report-file <HTML_FILE>` publishes an HTML comparison you write from each run's `results get` (oldest to newest, one scenario) and returns `ViewUrl`; add `--project-key` for an in-app link.
+ `licenses get` returns tenant-wide `RemainingVirtualUserUnits` and can lag up to 4 hours. A full run consumes virtual users × 1 (API), 10 (Chrome/Edge), or 100 (other targets); dry runs consume none. If units are short, stop and tell the user. Triage a failed group with `robot-logs list --load-group-id <ID> --level Error` and `jobs list --load-group-id <ID>`; A 403 means the tenant's performance testing feature or the user's permission is off: stop under Rule 10. `delete --scenario-key <SCENARIO_KEY> --yes` permanently removes scenario/groups (confirm first, Rule 5) but keeps past executions unlinked; it does not stop a running execution, so run `stop` first.
+
## Troubleshooting
- For `401 Unauthorized` on a REST API, run `uip login` to re-authenticate. For an unexpected command failure, first verify syntax with `uip tm <command> --help`, then authentication with `uip login status --output json`; Critical Rule 10 still governs whether to proceed.
+ For `401 Unauthorized` on a REST API, run `uip login` to re-authenticate. For unexpected command failure, first verify syntax with `uip tm <command> --help`, then authentication with `uip login status --output json`; Rule 10 still controls whether to proceed.
## Navigate to a Workflow
- Read, correct (`override`), assign, or manually record a test case log, and `Result` vs `OriginalResult`: [references/testcaselog-guide.md](references/testcaselog-guide.md)
- Back up, copy or move a project, in one tenant or across tenants and environments (`uip tm project export` → `import`): [references/project-migration-guide.md](references/project-migration-guide.md)
- Execution lifecycle (manual open/record/finish), filtered reads, cancel, delete, xlsx export, and reporting date (`uip tm executions`): [references/executions-guide.md](references/executions-guide.md)
- Failed-run root cause, assertions, step logs, evidence, and flaky-versus-regression analysis: [references/failure-triage-guide.md](references/failure-triage-guide.md)
- Raise a defect from a failed result, trace it to its test case/requirements, link it to a tracker issue (`uip tm defects`): [references/defects-guide.md](references/defects-guide.md)
- AI on a requirement: propose and create test cases, evaluate the requirement, find and unlink or delete obsolete test cases (`uip tm requirements generate-testcases`, `evaluate`, `find-obsolete-testcases`): [references/requirement-ai-guide.md](references/requirement-ai-guide.md)
- Shareable tester or release-manager report: [references/test-result-report-guide.md](references/test-result-report-guide.md)
- Publish a project and link it to a Test Manager testcase (Studio/RPA): [references/publish-and-link-guide.md](references/publish-and-link-guide.md)
- Pack, ingest, label, and run Playwright on serverless: [references/playwright-first-mile-guide.md](references/playwright-first-mile-guide.md)
- Run a test set on a cadence, cron shapes, and single-vs-bulk batch semantics (`uip tm schedules`): [references/schedules-guide.md](references/schedules-guide.md)
- Custom-field definitions, labels, and values (`uip tm customfield`): [references/custom-fields-guide.md](references/custom-fields-guide.md)
- Object labels / tag metadata on test entities (`uip tm objectlabel`): [references/object-labels-guide.md](references/object-labels-guide.md)
- Project time zone, execution name format, and what is read-only (`uip tm project settings`): [references/project-settings-guide.md](references/project-settings-guide.md)
## Anti-patterns
- - **Do not proceed if authentication fails:** all Test Manager API calls require a valid bearer token; fail fast rather than causing later 401s.
- - **Do not guess command names:** verb-noun composites are required; bare verbs do not exist. Confirm with `uip tm <resource> --help --output json`.
- - **Do not hand-build a package run:** to run all tests of an uploaded package, use `uip tm run --type package`, not `link-package` → `testsets create` → `testcases add` → `testsets run` → `wait` → `result download`.
- - **Do not run `project get-default` to see which project is the default:** it creates one, open to the tenant's Everyone group, when the tenant has none. Read the first `project list` row instead.
- - **Do not `link-automation` Playwright test cases:** ingestion links them automatically; manual linking is only for the Studio/RPA pipeline.
+ - Do not proceed if authentication fails; all Test Manager API calls require a valid bearer token.
+ - Do not guess command names: verb-noun composites are required; bare verbs do not exist. Confirm with `uip tm <resource> --help --output json`.
+ - Do not hand-build a package run; use `uip tm run --type package`, not `link-package` → `testsets create` → `testcases add` → `testsets run` → `wait` → `result download`.
+ - Do not run `project get-default` to inspect the default; it creates one, opened to tenant Everyone, when none exists. Read the first `project list` row.
+ - Do not `link-automation` Playwright cases; ingestion links them automatically. Manual linking is only for Studio/RPA.