Skip to main content

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:

  1. выбранный built-in profile или profiles.<name>;
  2. inherited custom profile chain через extends;
  3. root-level stages, excludes, warnings_as_errors, max_console_diagnostics;
  4. 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 keep content[0].text compact and place the complete payload in structuredContent.
  • 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 и paged limit/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) добавляет returned match_entity_ids; search/entity(include_related=true) возвращают bounded related preview с related_total/related_omitted; search/entity используются для точных сущностей и scoped diagnostics. Page entity возвращает page_ref и page_element_ref на nested elements для typed operation args. Scenario entity возвращает bounded executable outline с imports, persona call sequence и referenced page/component ids; generated API operation entity возвращает 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-scope accessible_name overlap без exact=True, equal role/name matches без scope/index, plain-message Status(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 записывает Page description, для placed element записывает Element description выбранного 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, а не через raw yaml.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-команд содержит bounded result_summary с draft_identifiers, generated_elements, generated_collections, refactor_targets previews and counts, чтобы агент мог продолжить semantic refactor в той же session без повторной генерации. browser.aria_snapshot_summary.name_field_meaning="ARIA accessible name" отделяет поле name ARIA/YAML snapshot от PageObject-контракта, где public Page/Element name отсутствует; full_snapshot_operation подсказывает штатный typed persona_get payload для расширенного snapshot.
  • persona_make, persona_get, persona_check принимают typed operation payload из persona_knowledge, persona_project, generation manifest или support plan и пишут каждый вызов в history. Operation args/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 и wsdl support 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-file imports, 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, возвращает advisory support_plan с ролями history, candidates, target classification, source_operations, final_file_imports, reuse_operation и live_reuse, затем write_support_file с support_kind, canonical support/{actions,steps,combined_steps,goals,facts,expectations}/**/*.py target_path и full module code, затем возвращает written_paths, final-file imports, project_entities и operations. Для check history setup statements остаются setup-кодом, а только финальное expression рендерится как persona.check(...). EN: for check history, setup statements stay as setup code and only the final expression is rendered as persona.check(...).
  • persona_test_run запускает уже записанный тестовый файл или native scenario_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_run returns structured runner evidence; agents use report_refs and 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.toml
  • config/<env>.yaml
  • config/auth.yaml
  • scenarios/**/test_*.py
  • scenarios/**/__suite__.py
  • scenario_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_stream
  • PERSONA_EVENT_REDIS_URL=redis://localhost:6379/0
  • PERSONA_EVENT_STREAM_KEY=persona:{launch_id}:events
  • PERSONA_EVENT_STREAM_MAXLEN=10000
  • PERSONA_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/0
  • PERSONA_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

persona_dsl-2026.7.3.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

persona_dsl-2026.7.3-py3-none-any.whl (1.3 MB view details)

Uploaded Python 3

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

Hashes for persona_dsl-2026.7.3.tar.gz
Algorithm Hash digest
SHA256 363af4399aa1c0187c042d53c05cdf9e66ea1ea5c186ce6efc07433ff6a3d0bd
MD5 2aa50bf480215110359f25c673f48fc2
BLAKE2b-256 e2e62183ce83ce7703252387895246a70fe01250ac35f021f72f55154fc107b6

See more details on using hashes here.

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

Hashes for persona_dsl-2026.7.3-py3-none-any.whl
Algorithm Hash digest
SHA256 6d7c01d3a1da5b6bfcf1a6371bd7a96e79ce3529ee4276c23d90ef621fb83abb
MD5 71140cad0e15f0321e3b3e570dc0b2f7
BLAKE2b-256 9e6f797fe9ab2029dc2daa63aaeaddcee74f7a2cb84a6459defc51c5733a1d04

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page