Persona DSL - Framework for implementing Screenplay pattern in Python tests
Project description
persona-dsl
persona-dsl — Python framework для E2E-, API- и интеграционных тестов на Screenplay-подходе, native runner, discovery, reporting, generators и MCP/read-only tooling.
Структура
src/persona_dsl/— framework package.tests/— package tests.scripts/— package tooling.template/— официальный starter project.docs/— правила и инженерные принципы.
Установка
pip install persona-dsl
python -m playwright install --with-deps
Разработка framework
make install
make checks
make knowledge-check
make package-smoke
Публичный Python/package contract:
- distribution:
persona-dsl - import package:
persona_dsl - CLI:
persona,persona-page-gen,persona-api-gen,persona-schema-gen,persona-mcp
Проверка Persona-проекта / Persona Project Check
RU: persona check — packaged analyzer проекта, написанного на Persona, для
before-merge проверки качества. Команда читает persona.check.yaml, применяет
выбранный profile и возвращает агрегированный отчёт по стадиям. persona check
не запускает authored scenarios, не строит Allure/runtime report UI и не
очищает runtime outputs. Команда сохраняет machine-readable report в
reports/persona-check/latest.json и human Markdown report в
reports/persona-check/latest.md. Для interactive text runs команда печатает
line-based progress по стадиям в stderr; --progress always|never управляет
этим явно.
EN: persona check is the packaged before-merge project analyzer for projects
written on Persona. It reads persona.check.yaml, applies the selected profile,
and returns an aggregated staged report. persona check does not run authored
scenarios, build the Allure/runtime report UI, or clean runtime outputs. It
writes the machine-readable report to reports/persona-check/latest.json and
the human Markdown report to reports/persona-check/latest.md. Interactive
text runs print line-based stage progress to stderr; use
--progress always|never to control it explicitly.
persona check --project-root . --profile merge
persona check --project-root . --profile strict --warnings-as-errors
persona check --project-root . --profile max
persona check --project-root . --stage scenario-metadata --stage secrets
persona check --project-root . --format json
persona check --project-root . --report-dir reports/persona-check
persona check --project-root . --progress always
persona check --list-stages
Исправления и форматирование Persona-проекта / Persona Project Fixing and Formatting
RU: persona fix применяет безопасные packaged автоисправления качества к
проекту. Текущий safe-fix pipeline включает Ruff check --fix --no-cache и
Black по существующим code roots scenarios, support и scripts.
persona format оставлен как явный алиас formatter pipeline. Команды
принимают --path для ограничения области и завершаются с non-zero exit code,
если fixer/formatter недоступен или выбранный путь отсутствует.
EN: persona fix applies safe packaged quality autofixes to a project. The
current safe-fix pipeline runs Ruff check --fix --no-cache and Black over the
existing scenarios, support and scripts code roots. persona format
remains an explicit formatter-pipeline alias. Use repeated --path values to
restrict the scope. Commands exit non-zero when a fixer/formatter is unavailable
or a selected path is missing.
persona fix
persona fix --path scenarios --path support/pages
persona format
persona format --path scenarios --path support/pages
Profiles:
advisory— Persona-semantic analyzer без delegated quality/security stages.merge— default static gate для проекта перед merge.strict— broad gate with warnings promoted to errors.security— artifact hygiene, secrets-only scan, Ruff S security rules, dependency audit and optional local Semgrep SAST.audit,maxиpublic-template— broad packaged profiles for deeper review.
Project-local custom profiles are declared in persona.check.yaml under
profiles.<name>. A custom profile extends a built-in or another custom profile
and can set warnings_as_errors, max_console_diagnostics, excludes and
stage overrides. The starter includes a project-max example profile that
extends built-in max and promotes advisory Persona-quality findings to
failures.
persona.check.yaml reference
RU: файл policy опционален. Если persona.check.yaml отсутствует, команда
использует профиль merge. Корень YAML должен быть mapping; неизвестные ключи,
неверные типы, неизвестный profile и custom profile inheritance cycle дают
ошибку policy до запуска стадий.
EN: this is the public YAML reference for Persona project checks.
Порядок применения effective policy:
- выбранный built-in profile или
profiles.<name>; - inherited custom profile chain через
extends; - root-level
stages,excludes,warnings_as_errors,max_console_diagnostics; - CLI overrides:
--profile, repeated--stage,--warnings-as-errors.
Root fields:
| Field | Type | Default | Meaning |
|---|---|---|---|
profile |
non-empty string | merge |
Built-in или custom profile, который выбирает набор стадий. |
warnings_as_errors |
boolean | false |
Promotes all warning diagnostics in the run to errors. |
max_console_diagnostics |
positive integer | selected profile default, usually 20 |
Caps console diagnostics. Saved JSON and Markdown reports keep full diagnostics. |
excludes |
list of non-empty strings | default source/cache excludes | Extra fnmatch globs appended to default excludes for source collection. |
profiles |
mapping | {} |
Project-local named profiles under profiles.<name>. |
stages |
mapping | {} |
Root stage overrides applied after selected profile inheritance. |
Custom profile fields under profiles.<name>:
| Field | Type | Default | Meaning |
|---|---|---|---|
extends |
non-empty string | merge |
Built-in or custom parent profile. Names must not override built-in profiles; cycles fail policy validation. |
warnings_as_errors |
boolean | inherited | Promotes warnings for this profile. |
max_console_diagnostics |
positive integer | inherited | Console diagnostic cap for this profile. |
excludes |
list of non-empty strings | inherited/default excludes | Extra source globs appended before root excludes. |
stages |
mapping | inherited stages | Per-stage overrides for this profile. |
Stage fields under stages.<id> or profiles.<name>.stages.<id>:
| Field | Type | Default | Meaning |
|---|---|---|---|
title |
non-empty string | built-in title or stage id | Human report title. |
kind |
built-in or delegated |
inherited | Built-in stage uses packaged analyzer code; delegated stage runs a command. |
enabled |
boolean | profile membership | Selects the stage when no explicit --stage is passed. |
required |
boolean | inherited, usually true |
For delegated stages, unavailable/failing required commands fail the run; advisory delegated stages can skip or warn. Built-in stage failure is driven by diagnostics severity. |
severity |
info, warning, error |
inherited | Default severity for policy-controlled diagnostics emitted by that stage. Hard contract errors remain errors. |
warnings_as_errors |
boolean | inherited | Promotes warnings only for this stage. |
command |
shell-like string or list of strings | built-in delegated command, if any | Command for delegated stage. Unknown external stage ids must declare command. |
args |
list of strings | [] |
Extra arguments appended to command. |
paths |
list of strings | stage-specific | Stage input roots for built-in stages and built-in delegated commands. Custom commands must include their path arguments in command or args. |
thresholds |
mapping of string to non-negative integer | stage-specific | Numeric knobs read by built-in stages. Project-defined threshold keys are valid YAML, but packaged stages only act on the documented keys listed below. |
max_diagnostics |
positive integer | stage-specific or unlimited | Caps console diagnostics for this stage. Saved JSON and Markdown reports keep full diagnostics. |
Built-in profiles:
| Profile | Stages |
|---|---|
advisory |
Persona semantic and hygiene stages without delegated quality/security stages. |
merge |
format, ruff, mypy, Ruff S security rules, pip-audit, Vulture and all semantic/hygiene stages. |
strict |
Same stages as merge, with stage warnings promoted to errors. |
security |
artifact-hygiene, secrets, Ruff S security rules, pip-audit and optional Semgrep/Gitleaks/OSV stages. |
audit |
Same stage set as merge plus optional Semgrep, Gitleaks, OSV, dependency hygiene, SBOM, license, shell, CI, Docker, Docker Compose and Markdown audit stages. |
max |
Strongest packaged analyzer profile; projects can extend it with local requiredness and warning policy. |
public-template |
Same stage set as merge; intended for public starter/template checks. |
Built-in stage ids and stage-specific knobs:
| Stage | Checks | Useful fields |
|---|---|---|
project-shape |
Required Persona project paths and forbidden legacy paths. | paths lists required project paths; default is config, scenarios, scenario_data, support. |
artifact-hygiene |
Tracked env files, runtime outputs and cache artifacts. | enabled, severity, max_diagnostics. |
file-length |
Python file length in selected roots. | paths; thresholds.max_lines; thresholds.warning_lines; severity. |
importability |
Python source compile/importability check for maintained roots. | paths, required, max_diagnostics. |
complexity |
Function-level complexity policy for scenarios/support/scripts. | paths; thresholds.max_complexity; thresholds.warning_complexity; severity; max_diagnostics. |
strict-code |
Inline suppressions, broad typing escapes and forbidden legacy patterns. | enabled, max_diagnostics. |
duplicate-identities |
Duplicate scenario names, traceability ids and public support class names. | severity, max_diagnostics. |
duplicate-code |
Repeated Python code blocks in maintained project roots. | thresholds.min_duplicate_lines; severity; max_diagnostics. |
format |
python -m black --check over code roots. |
command, args, paths, required. |
ruff |
python -m ruff check --no-cache over code roots. |
command, args, paths, required. |
mypy |
python -m mypy, using pyproject.toml when present. |
command, args, paths, required. |
security-code |
python -m ruff check --select S --ignore S101 --no-cache over project code roots. S101 is excluded because Persona scenarios use pytest-style assert as a supported observable check. |
command, args, paths, required. |
dependency-audit |
Dependency vulnerability audit through pip-audit. | command, args, required. |
semgrep |
Optional Semgrep SAST through project-pinned local rules. Default discovery uses semgrep.yml, semgrep.yaml, .semgrep.yml, .semgrep.yaml, rules/semgrep or semgrep-rules; use command for another local rules path. |
command, args, required; default required: false. |
gitleaks |
Optional Gitleaks repository secret scan. | command, args, required; default required: false. |
osv-audit |
Optional OSV dependency vulnerability audit. | command, args, required; default required: false. |
dependency-hygiene |
Optional dependency/import hygiene through deptry. | command, args, required; default required: false. |
sbom |
Optional CycloneDX SBOM generation. | command, args, required; default required: false. |
license-audit |
Optional license report through pip-licenses. | command, args, required; default required: false. |
dead-code |
Vulture dead-code scan for support/scripts; advisory by default. | command, args, required; default required: false. |
suite-topology |
__suite__.py presence, shape and supported suite(...) keywords. |
enabled, max_diagnostics. |
scenario-metadata |
Required @title, @story, @tag; traceability advisory metadata. |
thresholds.traceability_warnings; severity; max_diagnostics. Set traceability_warnings: 0 to disable owner/severity/id advisories. |
scenario-body-quality |
Sleep calls are hard errors; unasserted persona.get, formal/no-op checks, missing observable checks, missing readiness chain and long raw Ops flows are advisory by default and can fail under strict or warnings_as_errors. |
thresholds.raw_ops_warning; thresholds.readiness_ops_warning; severity; warnings_as_errors; max_diagnostics. |
support-quality |
Persona discovery diagnostics for maintained support/page objects. | severity, max_diagnostics. |
data-config |
YAML/JSON/TOML/CSV parse checks under config and scenario_data. |
enabled, max_diagnostics. |
generated-contracts |
Python compilation for support/contracts. |
enabled, max_diagnostics. |
reference-integrity |
Static lifecycle/retry/resource/scenario-data/config/upload file reference checks from suite and scenario metadata. | severity, max_diagnostics. |
secrets |
Credentials, tokens, private keys, real env/auth files and secret-like assignments. | enabled, max_diagnostics; branding and organization names are not findings. |
shellcheck |
Optional shell script lint. | command, args, required; default required: false. |
actionlint |
Optional GitHub Actions workflow lint. | command, args, required; default required: false. |
hadolint |
Optional Dockerfile lint. | command, args, required; default required: false. |
compose-config |
Optional Docker Compose config validation. | command, args, required; default required: false. |
markdownlint |
Optional Markdown lint. | command, args, required; default required: false. |
Example maximum project profile:
profile: merge
profiles:
project-max:
extends: max
warnings_as_errors: true
max_console_diagnostics: 80
stages:
complexity:
severity: error
thresholds:
max_complexity: 10
warning_complexity: 6
scenario-metadata:
severity: error
max_diagnostics: 80
scenario-body-quality:
severity: error
max_diagnostics: 80
support-quality:
severity: error
max_diagnostics: 80
dead-code:
required: true
semgrep:
required: true
command:
- semgrep
- scan
- --config
- rules/semgrep
- --quiet
- .
gitleaks:
required: true
osv-audit:
required: true
dependency-hygiene:
required: true
sbom:
required: false
license-audit:
required: false
shellcheck:
required: false
actionlint:
required: false
hadolint:
required: false
compose-config:
required: false
markdownlint:
required: false
Example advisory external stage:
profiles:
security-local:
extends: security
stages:
external-sca:
title: External SCA
kind: delegated
command:
- python
- -m
- pip_audit
required: false
Consolidated report shape
RU: text report сначала показывает semantic summary, затем сводку по стадиям,
диагностические блоки по стадиям и финальную строку Summary. Каждая
диагностика содержит stable PCS-... code и machine-readable reason.
max_console_diagnostics
ограничивает только console output. persona check сохраняет полный
machine-readable report в reports/persona-check/latest.json и полный
human Markdown report в reports/persona-check/latest.md. Для CI используйте
--format json. В интерактивном text-терминале live progress показывает
обновляемую строку активной стадии в stderr; в non-TTY text runs и при
--progress always progress печатается отдельными строками:
[i/N] START <stage> и [i/N] PASS|WARN|FAIL|SKIP <stage> (...). При
--format json default auto progress выключен, чтобы stdout оставался
валидным JSON.
Для исправления diagnostics агенту следует опираться на machine-readable
code, reason, stage_id, path, line и полный
reports/persona-check/latest.json. Локализованный message является
человеческим пояснением, а не единственным repair contract.
EN: text output starts with semantic summary, then grouped stages, diagnostic
blocks and the final summary line. Interactive text terminals render the active
stage as an updating stderr line; non-TTY text runs and --progress always
write line-based stage events. --format json keeps stdout valid JSON. The
command also writes full JSON and Markdown reports under
reports/persona-check/. Agents should use JSON fields such as code,
reason, stage_id, path, line and semantic_summary for remediation;
localized console messages are human explanations.
Persona check: profile=strict status=failed
Project: /workspace/example-project
Semantic summary:
project: scenarios=42 modules=18 suites=9 support=31
quality: direct_ops=14 raw_scenarios=3 missing_checks=1
domains: checkout=18, accounts=12, admin=8, root=4
suites: Root / Checkout=18, Root / Accounts=12, Root / Admin=8, Root=4
support: shared=4 domain_owned=23 top=support.steps.login=8, support.facts.account=6, support.expectations.order=5
metadata: title=100.0%, story=100.0%, tag=97.62%, severity=90.48%, owner=76.19%, identity=83.33%
references: lifecycle_profiles: declared=4, used=3, missing=0; retry_profiles: declared=2, used=2, missing=0; resources: declared=5, used=4, missing=1; data_files: declared=0, used=3, missing=0; config_paths: declared=0, used=1, missing=0; files: declared=0, used=2, missing=0
decision: profile=strict status=failed; failing stages: reference-integrity, scenario-metadata, scenario-body-quality
Stages:
[PASS] project-shape (4 ms, errors=0 warnings=0 info=0)
[PASS] artifact-hygiene (12 ms, errors=0 warnings=0 info=0)
[PASS] importability (10 ms, errors=0 warnings=0 info=0)
[WARN] complexity (17 ms, errors=0 warnings=2 info=0)
[PASS] format (180 ms, errors=0 warnings=0 info=0)
[PASS] ruff (145 ms, errors=0 warnings=0 info=0)
[PASS] mypy (920 ms, errors=0 warnings=0 info=0)
[FAIL] reference-integrity (11 ms, errors=1 warnings=0 info=0)
[FAIL] scenario-metadata (32 ms, errors=3 warnings=0 info=0)
[FAIL] scenario-body-quality (28 ms, errors=1 warnings=0 info=0)
[PASS] secrets (35 ms, errors=0 warnings=0 info=0)
scenario-metadata: diagnostics
- error scenarios/checkout/test_checkout.py:42 PCS-MET-004 missing-owner: Сценарий должен иметь owner label для владения.
- error scenarios/checkout/test_checkout.py:42 PCS-MET-006 missing-id: Сценарий должен иметь id/link/issue/testcase для трассировки.
- error scenarios/checkout/test_checkout.py:42 PCS-MET-005 missing-severity: Сценарий должен иметь severity для приоритета triage.
scenario-body-quality: diagnostics
- error scenarios/checkout/test_checkout.py:58 PCS-BDY-006 raw-ops-flow: Сценарий содержит длинную цепочку прямых Ops; для поддерживаемого production flow лучше вынести поток в Step/CombinedStep/Expectation.
reference-integrity: diagnostics
- error scenarios/checkout/test_checkout.py:42 PCS-REF-003 missing-resource: Resource не найден: checkout.account.
Summary: status=failed exit_code=1 duration=1356 ms
JSON report has stable machine-readable keys:
{
"profile": "strict",
"project_root": "/workspace/example-project",
"status": "failed",
"exit_code": 1,
"counts": {
"severity": {"info": 0, "warning": 2, "error": 5},
"status": {"passed": 8, "warning": 1, "failed": 3, "skipped": 0}
},
"excludes": ["reports/**", "artifacts/**"],
"semantic_summary": {
"project": {
"scenarios_total": 42,
"test_modules_total": 18,
"suites_total": 9,
"support_modules_total": 31
},
"metadata_coverage": {
"title": {"present": 42, "missing": 0, "percent": 100.0},
"story": {"present": 42, "missing": 0, "percent": 100.0},
"tag": {"present": 41, "missing": 1, "percent": 97.62},
"severity": {"present": 38, "missing": 4, "percent": 90.48},
"owner": {"present": 32, "missing": 10, "percent": 76.19},
"identity": {"present": 35, "missing": 7, "percent": 83.33}
},
"scenario_quality": {
"direct_ops_total": 14,
"scenarios_with_raw_ops": 3,
"scenarios_missing_observable_check": 1,
"readiness_calls_total": 6,
"formal_checks_total": 1
},
"domains": {"checkout": 18, "accounts": 12, "admin": 8, "root": 4},
"suites": {"Root / Checkout": 18, "Root / Accounts": 12, "Root / Admin": 8, "Root": 4},
"support": {
"layers": {"pages": 6, "steps": 10, "expectations": 5, "shared": 4},
"shared_modules": 4,
"domain_owned_modules": 23,
"top_reused_modules": [
{"module": "support.steps.login", "usages": 8}
]
},
"references": {
"lifecycle_profiles": {"declared": 4, "used": 3, "missing": []},
"retry_profiles": {"declared": 2, "used": 2, "missing": []},
"resources": {"declared": 5, "used": 4, "missing": ["checkout.account"]},
"data_files": {"declared": 0, "used": 3, "missing": []},
"config_paths": {"declared": 0, "used": 1, "missing": []},
"files": {"declared": 0, "used": 2, "missing": []}
},
"top_risky_files": [
{"path": "scenarios/checkout/test_checkout.py", "score": 7, "errors": 1, "warnings": 1, "info": 0}
]
},
"stages": [
{
"id": "scenario-metadata",
"title": "Scenario metadata",
"status": "failed",
"duration_ms": 32,
"counts": {"info": 0, "warning": 0, "error": 3},
"diagnostics": [
{
"stage_id": "scenario-metadata",
"severity": "error",
"code": "PCS-MET-004",
"message": "Сценарий должен иметь owner label для владения.",
"reason": "missing-owner",
"path": "scenarios/checkout/test_checkout.py",
"line": 42
}
]
}
]
}
Built-in stages cover project shape, tracked artifact hygiene, importability, complexity, strict code policy, duplicate identities, duplicate code, suite topology, effective scenario metadata through suite tree, scenario body quality, support quality diagnostics, data/config parsing, generated contracts, reference integrity and secrets-only scanning. Delegated stages run Black, Ruff, Mypy, Ruff S security rules, pip-audit, Vulture, optional audit tools or configured external commands through policy.
Privacy contract: default scan fails credentials, tokens, private keys, real env or auth files and secret-like literal assignments. Organization names, product names and normal project branding are not default findings.
Локальный Runner / Local Runner
RU: persona run, persona launch ... и make-цели starter-проекта пишут
выходной слой запуска в reports/<env>/<launch_id>/,
artifacts/<env>/<launch_id>/ и reports/latest/.
EN: persona run, persona launch ..., and starter Make targets write launch
outputs to reports/<env>/<launch_id>/, artifacts/<env>/<launch_id>/, and
reports/latest/.
RU: persona report info --project-root <project> --env <env> --launch-id <launch_id> читает summary.json и journal.jsonl. Для failed launch команда
печатает Ошибки сценариев: work item, название, Место ошибки в формате
path:line[:column] function, тип и сообщение исключения, фрагмент
пользовательского стека, а также ссылки на traceback, runtime log, stdout и
stderr artifacts. JSON-режим отдаёт те же данные в
failed_items[].failure_diagnostics.
EN: persona report info --project-root <project> --env <env> --launch-id <launch_id> reads summary.json and journal.jsonl. For a failed launch, it
prints Ошибки сценариев: work item, title, Место ошибки as
path:line[:column] function, exception type and message, user stack excerpt,
and links to traceback, runtime log, stdout, and stderr artifacts. JSON mode
returns the same data in failed_items[].failure_diagnostics.
Генераторы контрактов
Persona генерирует committed contract packages для проекта:
persona-page-gen— page object из browser/runtime snapshot.persona-api-gen— OpenAPI API package с Pydantic models, builders, Ops, responses и catalog.persona-schema-gen xsd— XSD/XML package с models, builders и schema metadata.persona-schema-gen json— JSON Object Pydantic package из JSON Schema или явно выбранного sample JSON.persona-schema-gen wsdl— WSDL/SOAP package с models, builders, service/port/operation catalog и generated SOAP Ops.
RU: Page generation сохраняет atomic semantic controls с ARIA role/name как
Button/Link/Checkbox/Switch/Radio/Tab(accessible_name=...); общий
component test_id используется как stable key вместе с семантическим ключом,
scoped owner или index, а runtime выбирает test_id раньше aria_ref.
Heading/accordion wrapper с единственным одноимённым Link/Button child
генерируется как action-field на owner level.
Безымянные list/listitem wrappers наследуют semantic hint от единственного
содержательного child: навигация, breadcrumb и pagination получают executable
ids вроде tips, home, page_1, next, tools_list, а не numeric
wrapper class names. Common chrome (Header/Sidebar/Footer, Banner,
Navigation, ContentInfo) извлекается или переиспользуется как page component
из support/pages; для page-specific generation используется explicit target
scope вместо копирования всего сайта в один PageObject.
Повторяющиеся product/card/tile/item контейнеры с пользовательскими полями и
действиями генерируются как composite Repeated коллекции: прототип получает
locator по structural class, стабильные поля вроде product_image, price,
product_name, add_to_cart, view_product, а runtime refs, item-specific
URLs и глобальные индексы не попадают в прототип.
После генерации поддерживаемый PageObject проходит refactor pass и доводится до
доменной структуры: classes используют PascalCase, Python fields/methods и
Page/Element public metadata разделены. Python fields/methods используют
readable English snake_case, protocol keys остаются английскими.
Page class, PageDefinition.class_name и element field не локализуются, не
заполняются русским описанием и не записываются транслитом; у Page/Element нет
public name, а русское доменное описание страницы или элемента заполняется
через Page/Element description, report label или другой human metadata. При
пустом Element description runtime использует Python field alias только как
display label для отчётов и диагностики; locator contract остаётся в
accessible_name, text, label, placeholder, test_id, locator,
aria_ref и связанных selector-полях. Static persona check сообщает
missing_element_description (PCS-SUP-005) как support-quality warning.
Если Element задаёт literal text и literal variants, static
persona check сообщает element_text_not_in_variants (PCS-SUP-020), когда
text не входит в список variants; runtime импорт PageObject не
останавливается, а явный выбор через by_variant(...)/get_option(...)
остаётся строгим.
При refactor pass поля с одинаковым effective role в одном owner scope и
пересекающимся accessible_name, например Пароль / Новый пароль, получают
exact=True; полностью одинаковые role/name matches требуют более узкий
owner/locator или index, потому что exact=True их не различает. Custom
element subclasses наследуют role от доказанного Persona base class
(TextField, Button, ...); если role не доказана, locator-quality не
выдаёт overlap warning. Plain visible message описывается как
Text(text=..., exact=True), а Status(accessible_name=...) используется
только для подтверждённого ARIA status node. Region/Main/Dialog
boundaries опираются на реальный DOM/ARIA owner, locator, test_id или
aria_ref; heading text сам по себе остаётся child element.
EN: Page generation keeps atomic semantic controls with ARIA role/name as
Button/Link/Checkbox/Switch/Radio/Tab(accessible_name=...); a shared
component test_id is stable with a semantic key, scoped owner, or index, and
runtime resolution chooses test_id before aria_ref.
Heading/accordion wrappers with one same-name Link/Button child are generated
as owner-level action fields.
Unnamed list/listitem wrappers inherit a semantic hint from the single
meaningful child: navigation, breadcrumb and pagination generate executable ids
such as tips, home, page_1, next, tools_list, not numeric wrapper
class names. Common chrome (Header/Sidebar/Footer, Banner, Navigation,
ContentInfo) is extracted or reused as a page component from support/pages;
page-specific generation uses an explicit target scope instead of copying the
whole site into one PageObject.
Repeated product/card/tile/item containers with user-facing fields and actions
generate composite Repeated collections with a structural-class prototype and
stable child fields such as product_image, price, product_name,
add_to_cart and view_product.
After generation, maintained PageObjects go through a refactor pass and are
refined into domain structure: classes use PascalCase, Python fields/methods
and Page/Element public metadata are separated. Python fields/methods use
readable English snake_case, protocol keys stay English. Page class,
PageDefinition.class_name and element fields are not localized and are not
transliterated; Page/Element has no public name, and localized domain wording goes
into Page/Element description, report label or other human metadata. Empty
Element description uses the Python field alias only as a runtime display label
for reports and diagnostics; locator semantics stay in explicit selector fields,
and static persona check reports missing_element_description
(PCS-SUP-005) as a support-quality warning. When an Element declares literal
text and literal variants, static
persona check reports element_text_not_in_variants (PCS-SUP-020) if
text is outside the variants list; PageObject import remains runtime-safe,
while explicit by_variant(...)/get_option(...) selection stays strict. During
the refactor pass, same effective-role fields in the same owner scope with
substring-overlapping accessible_name values such as Password / New password get
exact=True; equal role/name matches require a narrower owner/locator or
index because exact=True cannot distinguish them. Custom element subclasses
inherit role from a proven Persona base class (TextField, Button, ...); when
the role is not proven, locator-quality does not emit an overlap warning. Plain
visible messages are modeled as Text(text=..., exact=True), while
Status(accessible_name=...) is reserved for a confirmed ARIA status node.
Region/Main/Dialog boundaries use a real DOM/ARIA owner, locator,
test_id, or aria_ref; heading text remains a child element by itself.
config/{env}.yaml поддерживает batch generation documents:
generator.api.documents[]generator.json.documents[]generator.soap.documents[]
MCP authoring surface использует единый Persona runtime:
- MCP
tools/callвозвращает короткий text summary вcontent[0].textи полный machine-readable payload вstructuredContent; агенты читают поля, diagnostics, matches, refs и generated manifests изstructuredContent, а не из text dump. EN: MCP tool calls keepcontent[0].textcompact and place the complete payload instructuredContent. persona_knowledgeчитает compact guide, guide_search, framework catalog и config catalog;include_examplesиinclude_source_refsвключают расширенный authoring context явно.guide_search,framework_searchиconfig_searchвсегда возвращают bounded page:limit=0означает max page, а не unbounded all; продолжение читается черезoffset.framework_search.invocation_modesвыбирает symbols, которые поддерживают хотя бы один указанный live command mode; для web Ops используйте точныйqueryи pagedlimit/offset, а catalog audit выполняйте постранично.persona_projectчитает inventory/search/entity/lifecycle/retry данные текущего project-root и обновляет discovery cache при изменении файлов.inventory(include_ids=true, limit=N, filters={...})возвращает bounded key id previews, totals и omitted counts;filtersсужают key ids и facet_counts previews без изменения full summary.domain_support_mapв inventory является compact overview с layers/status counts/totals/omitted and paged domains;domain_support_domains_limit/domain_support_domains_offsetуправляют страницей доменов и возвращаютdomains_total/domains_omitted/domains_offset;include_domain_support_details=trueиdomain_support_limit=Nдобавляют bounded details от 0 до 10 для small review.diagnostics_limit=Nуправляет inventory diagnostics preview от 0 до 25 и возвращаетdiagnostics_total/diagnostics_omitted;search(filters={support_domains, support_layers, support_statuses}, limit, offset)используется для paged domain/layer/status drill-down;search(include_ids=true)добавляет returnedmatch_entity_ids;search/entity(include_related=true)возвращают bounded related preview сrelated_total/related_omitted;search/entityиспользуются для точных сущностей и scoped diagnostics. Pageentityвозвращаетpage_refиpage_element_refна nested elements для typed operation args. Scenarioentityвозвращает bounded executable outline с imports, persona call sequence и referenced page/component ids; generated API operationentityвозвращаетconstructor_signature,constructor_parameters,response_contractиusage_examples. Diagnostics сcontext=support_qualityиseverity=warningподсвечивают PageObject/support ids, требующие refactor: localized/transliterated Page class names, Step/CombinedStep/Goal and reusable page-component class names, transliteration, numeric/generic/value-derived/overlong fields, missing Page/Element description for generated/refactor-needed support, same-role/same-scopeaccessible_nameoverlap безexact=True, equal role/name matches без scope/index, plain-messageStatus(accessible_name=...)без DOM anchor и label-only owner boundaries.suggested_identifier_kindможет бытьpage_class,python_fieldилиcomponent_class; suggestion является review candidate, а не автоматическим rename. EN: scenario and API operation entities expose authoring-critical structure without opening project source files first; support_quality diagnostics mark generated support that must be refactored before production authoring.persona_generate_support(page|element)принимаетpayload.description: для page записывает Pagedescription, для placed element записывает Elementdescriptionвыбранного field, не меняя English executable names. MCP page/element payload принимаетsnapshot_path,page_path,wait_for_stateиwait_timeout;snapshot_pathчитает persisted RichAriaSnapshot artifact внутри project-root черезRichAriaSnapshot.from_yaml_file, а не через rawyaml.safe_load. Python-only поляwait_for_element,wait_for_element_stateиwait_for_element_timeoutотносятся кGeneratePageObject, а не кpersona_generate_support.persona_session_openоткрывает live session;lifecycle=trueвыполняет runner lifecycle setup для указанногоscenario_id.persona_session_stateвозвращает URL, title, load state, page errors, active element, visible summary, bounded ARIA structure summary, loaded skills/resources, lifecycle state, history summaries, draft, artifact summaries, current-state diagnostics и project fingerprint.history_tailдля generation-команд содержит boundedresult_summaryсdraft_identifiers,generated_elements,generated_collections,refactor_targetspreviews and counts, чтобы агент мог продолжить semantic refactor в той же session без повторной генерации.browser.aria_snapshot_summary.name_field_meaning="ARIA accessible name"отделяет полеnameARIA/YAML snapshot от PageObject-контракта, где public Page/Elementnameотсутствует;full_snapshot_operationподсказывает штатный typedpersona_getpayload для расширенного snapshot.persona_make,persona_get,persona_checkпринимают typedoperationpayload изpersona_knowledge,persona_project, generation manifest или support plan и пишут каждый вызов в history. Operationargs/kwargsмогут ссылаться на PageObject или вложенный element через{"persona_ref":"page","entity_id":"page::..."}и{"persona_ref":"page_element","entity_id":"page::...","path":"form.submit"}; runtime импортирует страницу внутри, агент не пишетfrom support.pages.... Полеcodeостаётся debug/escape hatch для безопасных Persona/Python expressions, которые ещё не представлены typed operation route.persona_generate_supportпишетpage,element,api,xsd,jsonиwsdlsupport artifacts в проект, обновляет import caches/discovery и возвращает bounded manifest сwritten_paths, preview/count/omitted полями дляgenerated_pages,generated_elements,generated_collections,draft_identifiers,generated_api_operations,generated_models,generated_builders,project_entities, а также final-fileimports, artifact summaries иdiagnostics; file content читается из записанных project files.generated_elementsсодержитpage_element_ref,description_source,description_refactor_required,identifier_qualityиowner_boundary_evidence, чтобы semantic refactor и immediate reuse выполнялись по MCP data без чтения generated source.draft_identifiersперечисляет generated generic/value-derived/numeric/transliterated Python fields сaccess_path,example_ref, path/support classification и review suggestions.generated_collectionsописывает reusable repeated/list/grid regions черезaccess_path,example_ref,example_item_ref,page_element_ref,prototype_type,field_countи field refs вродеpage.products[0].price.- Успешная generation с diagnostic
severity=info, напримерpage_component_reused, возвращаетstatus=ok;partialозначает записанные артефакты с warning/error diagnostics, skipped artifacts или failed sub-operations. EN: successful generation with informational diagnostics is not a partial failure. - Command diagnostics относятся к текущему tool call.
persona_session_state.diagnosticsпоказывает active lifecycle/refresh/latest failed-command diagnostics and does not repeat passed generation diagnostics. persona_test_authorредактирует draft поверх history:state,include,remove,reorder,edit,render,write_file,reset; для semantic support refactor дополнительно принимаетplan_support_fileс выбраннымиhistory_ids,support_kindиtarget_path, возвращает advisorysupport_planс ролями history, candidates, target classification,source_operations,final_file_imports,reuse_operationиlive_reuse, затемwrite_support_fileсsupport_kind, canonicalsupport/{actions,steps,combined_steps,goals,facts,expectations}/**/*.pytarget_pathи full modulecode, затем возвращаетwritten_paths, final-fileimports,project_entitiesиoperations. Дляcheckhistory setup statements остаются setup-кодом, а только финальное expression рендерится какpersona.check(...). EN: forcheckhistory, setup statements stay as setup code and only the final expression is rendered aspersona.check(...).persona_test_runзапускает уже записанный тестовый файл или nativescenario_idчерез изолированный native runner path/scenario selector, поэтому final runner check можно выполнять до закрытия live authoring session; ответ содержитlaunch_id,launch_status, item counts,output_summaryиreport_refs.- EN:
persona_test_runreturns structured runner evidence; agents usereport_refsand counts instead of parsing localized stdout. persona_session_closeзакрывает session с явнымstatus=passed|failed|partial;failedзапускает failure lifecycle hook,partialосвобождает exploratory session безrun_on_test_failure, cleanup and resource release выполняются при закрытии.
Generated API operations support request-level API profile binding:
GetHealth().with_api_profile("bgt").as_response() uses
skills.api.bgt, while raw JsonExchange(..., api_profile="bgt") uses the same
profile selector. persona.skill("api.bgt") is accepted as shorthand for
persona.skill("api", "bgt").
Element generation принимает live target и explicit placement: action
add|replace|extract, scope page|section|dialog|table|component,
field_name/field_path и owner/class context. Package-owned knowledge
surface для генераторов проверяется командами:
make knowledge-generate
make knowledge-check
Миграция Page DSL name / Page DSL name migration
RU: persona migrate page-names сканирует Page DSL-файлы проекта и формирует
перенос literal name=... в description, accessible_name, text или
locator по явным правилам. Команда по умолчанию работает в dry-run режиме;
запись изменений включается через --apply. --path, --snapshot-root и
--report задают область сканирования, RichAriaSnapshot confidence gate и путь
отчёта. Мигратор распознаёт direct Page DSL classes and local component
subclasses, declared in the same page file. Неперенесённые случаи остаются в
исходном файле и попадают в report warnings с координатами.
Для Text/Paragraph с уже заданным variants literal name=... переносится
только в description, чтобы не создавать конфликт text и variants.
EN: persona migrate page-names scans project Page DSL files and prepares a
literal name=... migration to description, accessible_name, text, or
locator through explicit rules. The command defaults to dry-run mode; --apply
enables writes. --path, --snapshot-root and --report configure the scan
scope, RichAriaSnapshot confidence gate and report path. The migrator recognizes
direct Page DSL classes and local component subclasses declared in the same page
file. Unmigrated cases stay in source files and are listed in report warnings
with coordinates.
For Text/Paragraph elements that already declare variants, literal
name=... migrates only to description so the migration does not create a
text/variants conflict.
persona migrate page-names --project-root . --report reports/page-name-migration-report.txt
persona migrate page-names --project-root . --snapshot-root artifacts/snapshots --apply
RU: starter make migrate-page-names является thin wrapper над этой Persona CLI
командой. EN: starter make migrate-page-names is a thin wrapper over this
Persona CLI command.
Пользовательский проект
Официальный starter расположен в template/.
pyproject.tomlconfig/<env>.yamlconfig/auth.yamlscenarios/**/test_*.pyscenarios/**/__suite__.pyscenario_data/support/
Команды starter:
cd template
make install
make checks
make redis-up
make redis-status
Runtime Event Sink
Persona публикует runtime-события во внешний sink через нейтральный contract:
PERSONA_EVENT_SINK=redis_streamPERSONA_EVENT_REDIS_URL=redis://localhost:6379/0PERSONA_EVENT_STREAM_KEY=persona:{launch_id}:eventsPERSONA_EVENT_STREAM_MAXLEN=10000PERSONA_EVENT_STRICT_CONNECT=false
При отключённом sink локальные runtime/report artifacts продолжают писаться в проектные директории.
Starter поднимает локальный Redis через template/compose.yaml:
cd template
make redis-up
make redis-status
Data Pools
runtime.data_pools описывает эксклюзивные элементы для параллельных запусков.
Сценарий получает не пул, а resource:
user = persona.resource("auth.user")
Resource объявляется в support/resources через
define_lease_resource("auth.user", pool="ui_users"). Runtime берёт lease при
фактическом вызове resource и освобождает его через cleanup test-scoped
resource.
Элемент пула требует только item_id. auth_key задаётся для ресурсов, которые
читают credentials через persona.auth(...); несекретные значения хранятся в
payload.
Redis backend для data pools читает URL из env-переменной, указанной в
runtime.data_pools.<pool_id>.redis.url_env. Starter содержит env=redis и
пример .env.redis.example:
PERSONA_DATA_POOL_REDIS_URL=redis://localhost:6379/0PERSONA_EVENT_REDIS_URL=redis://localhost:6379/0
dev и staging используют local_sqlite; Redis-режим выбирается явно через
env=redis.
Knowledge
Package-owned knowledge surface находится в src/persona_dsl/knowledge/ и проверяется через:
make knowledge-generate
make knowledge-check
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file persona_dsl-2026.7.3.tar.gz.
File metadata
- Download URL: persona_dsl-2026.7.3.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
363af4399aa1c0187c042d53c05cdf9e66ea1ea5c186ce6efc07433ff6a3d0bd
|
|
| MD5 |
2aa50bf480215110359f25c673f48fc2
|
|
| BLAKE2b-256 |
e2e62183ce83ce7703252387895246a70fe01250ac35f021f72f55154fc107b6
|
File details
Details for the file persona_dsl-2026.7.3-py3-none-any.whl.
File metadata
- Download URL: persona_dsl-2026.7.3-py3-none-any.whl
- Upload date:
- Size: 1.3 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d7c01d3a1da5b6bfcf1a6371bd7a96e79ce3529ee4276c23d90ef621fb83abb
|
|
| MD5 |
71140cad0e15f0321e3b3e570dc0b2f7
|
|
| BLAKE2b-256 |
9e6f797fe9ab2029dc2daa63aaeaddcee74f7a2cb84a6459defc51c5733a1d04
|