This release is a pre-release and may not be stable for production use.
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/— правила и инженерные принципы.
Установка
Новый проект создаётся standalone bootstrap-скриптом из выбранного release tag.
Скрипт проверяет Python >=3.12, создаёт project-local .venv, устанавливает
выбранную Persona distribution и выполняет полный project reconcile, настройку
агентской среды и doctor. Значение latest включает stable, alpha, beta и RC.
POSIX shell:
PERSONA_RELEASE="<release-tag>"
PERSONA_RELEASE_URL="https://github.com/pglyanenko/persona/releases/download/${PERSONA_RELEASE}"
curl -fLO "${PERSONA_RELEASE_URL}/install-persona.py"
curl -fLO "${PERSONA_RELEASE_URL}/install-persona.py.sha256"
shasum -a 256 -c install-persona.py.sha256
python3 install-persona.py --project-root ./persona-project --version latest
PowerShell:
$PersonaRelease = "<release-tag>"
$PersonaReleaseUrl = "https://github.com/pglyanenko/persona/releases/download/$PersonaRelease"
Invoke-WebRequest "$PersonaReleaseUrl/install-persona.py" -OutFile install-persona.py
Invoke-WebRequest "$PersonaReleaseUrl/install-persona.py.sha256" -OutFile install-persona.py.sha256
$Expected = (Get-Content install-persona.py.sha256).Split()[0].ToLowerInvariant()
$Actual = (Get-FileHash install-persona.py -Algorithm SHA256).Hash.ToLowerInvariant()
if ($Actual -ne $Expected) { throw "SHA-256 checksum mismatch" }
py install-persona.py --project-root ./persona-project --version latest
Для уже созданного проекта единый lifecycle запускается из его корня:
make install
make agent
Разработка framework
make install
make checks
make knowledge-check
make package-smoke
Artemis AMQP
UseArtemis предоставляет AMQP 1.0 transport для Apache ActiveMQ Artemis.
persona.make(SendMessage(...)) отправляет bytes, строку или модель с
зарегистрированным schema codec в address и ожидает broker settlement.
persona.get(MessageInQueue(...)) читает одну доставку из queue или FQQN
address::queue, подтверждает её и возвращает metadata, application properties,
JSON envelope либо типизированную XSD/XML-модель через as_type.
Environment profile находится в skills.artemis.<name> и содержит url,
auth_key, timeout, heartbeat, optional tls_ca_file и явный
allow_insecure_auth для SASL через amqp://. Учётные данные хранятся в
config/auth.yaml или environment resolver, а не в URL.
Agent knowledge и browser authoring / Agent knowledge and browser authoring
Project Profile поддерживает источники кода тестируемого приложения: Git URL и
необязательную рабочую ветку для frontend, backend и микросервисов. Репозитории
не скачиваются при project update/init/install/agent launch; on-demand lifecycle
выполняется через persona project repos status|checkout|update, а Project Map
анализирует код и записывает commit-bound выводы в Project Memory. Контракт
описан в docs/tested-application-code-context.md.
RU: Любой запрос через make agent начинает навигацию с package-owned
persona_knowledge(action="agent_flows"). Slash-команда уже подключает нужный
skill и bounded route contract. Для точного route вызов
persona_knowledge(action="agent_route", route="<route>") возвращает
копируемые tool payloads, канонический Markdown state, current action,
continuation/recovery и browser contract. Обычные project/file tools доступны
для исходников и чтения возвращённых artifact paths.
Короткий eN ref текущего browser state передаётся как
persona_browser(session_id=<session_id>, action=<action>, ref=<current_eN_ref>).
find ищет текст, properties и semantic paths в сохранённом index; inspect
возвращает точный узел, ancestry, table context и subtree без нового capture.
persona_session_state восстанавливает единственное текущее состояние session.
persona_generate_support(kind="element") принимает текущий ref, сохраняет
ref-free semantic fragment и мержит элемент в Page structure. Durable
Page/Element/test code хранит semantic identity без ref. Native semantic
observation является основным generation input; Rich snapshot API остаётся
deprecated compatibility-входом на линейке 0.2.x.
Публичный Python/package contract:
- distribution:
persona-dsl - import package:
persona_dsl - CLI:
persona,persona-page-gen,persona-api-gen,persona-schema-gen,persona-mcp,persona-lsp - Version diagnostics:
persona --versionandpersona-mcp --version - Agent bootstrap CLI:
persona agent init,persona agent list-profiles,persona agent doctor
Persona Language Server
persona-lsp работает рядом с Pyright, Pylance или другим Python language
server. Persona отвечает за framework diagnostics, completion, navigation,
semantic rename, code actions, semantic presentation и безопасные generation
transactions. Python companion отвечает за syntax, imports, typing, generic
refactors и formatting. Сервер использует STDIO и стандартный LSP lifecycle.
persona-lsp --client-config all
persona-lsp --client-config vscode
persona-lsp --client-config qwen
persona lsp --client-config neovim
persona-lsp --project-root .
Typed profiles предусмотрены для VS Code, Neovim, Helix, Zed, Qwen Code CLI и
GigaCode CLI. make install добавляет Persona в project-local .lsp.json и
включает native LSP для Qwen/GigaCode независимо от MCP. Валидный .lsp.json
объединяется по зарезервированному ключу persona с сохранением остальных
серверов; некорректный файл заменяется канонической Persona-конфигурацией в той
же транзакции. VS Code client собирается через
make vscode-lsp-package; полный контракт описывает
установку, trust, multi-root, recovery и поддерживаемые клиенты.
Проверка 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 |
Delegated stages only. Unavailable or failing required commands fail the run; advisory delegated stages can skip or warn. Built-in stage failure is driven by diagnostics severity, and a built-in required override is rejected as invalid policy. |
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, 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 |
Pip-audit of the installed virtual environment for pyproject.toml projects after make install; requirements-only projects are audited through their requirements files. |
command, args, required. |
semgrep |
Optional external Semgrep SAST through project-pinned local rules. Persona does not install Semgrep into the audited project environment. Default discovery uses semgrep.yml, semgrep.yaml, .semgrep.yml, .semgrep.yaml, rules/semgrep or semgrep-rules; use command for another reviewed executable/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.
format, ruff, mypy, security and maintainability delegated stages inspect
maintained human-authored roots. Generated API/XSD/JSON/WSDL modules under
support/contracts are owned by generated-contracts; project initialization
and update add a scoped Mypy override for support.contracts without weakening
type checking of scenarios or maintained support code.
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.
RU: persona.make(...), yield-операции внутри Step и
persona.check(actual, expectation) формируют вложенные шаги canonical report и
Allure projection. При окончательном падении сценария runner прикладывает
failure-page.html и failure-page.png для активной страницы каждого уже
загруженного browser skill. Перед чтением HTML runner обновляет Persona Runtime
snapshot, поэтому актуальные элементы получают свежие data-persona-id. Если
runtime refresh недоступен, сохраняется raw DOM без маскирования исходной ошибки.
Сбор выполняется после исчерпания test-level retry и управляется
reporting.enabled, reporting.pagesource_on_fail и
reporting.screenshot_on_fail; явное false отключает соответствующий
артефакт.
EN: persona.make(...), yielded operations inside a Step, and
persona.check(actual, expectation) produce nested canonical report steps and
Allure projection entries. On a terminal scenario failure, the runner attaches
failure-page.html and failure-page.png for the active page of every already
loaded browser skill. Before reading HTML, the runner refreshes the Persona
Runtime snapshot so current elements receive fresh data-persona-id values. If
runtime refresh is unavailable, raw DOM is still captured without masking the
original failure.
Capture runs after test-level retries are exhausted and is controlled by
reporting.enabled, reporting.pagesource_on_fail, and
reporting.screenshot_on_fail; explicit false disables the corresponding
artifact.
RU: wait_until(..., description="Ожидание статуса READY во внешнем API")
использует переданный текст как полный заголовок canonical/Allure шага, runtime
events и диагностики таймаута. Значение None сохраняет заголовок по имени
класса expectation. Вложенный шаг Получено значение: ... и поле
step_end.result содержат полное строковое представление результата без
ограничения длины.
EN: wait_until(..., description="Wait for READY status in the external API")
uses the supplied text as the complete canonical/Allure step title, runtime
event description, and timeout diagnostic. None keeps the expectation class
name title. The nested Received value: ... equivalent and step_end.result
retain the complete string representation without a length cap.
Генераторы контрактов
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. Snapshot ref остаётся временной координатой только
внутри Persona MCP browser session; готовый Page/Element связывается через
semantic identity и Page.element_path и не хранит 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 коллекции. Прототип содержит
стабильные поля вроде product_image, price, product_name, add_to_cart,
view_product; item_scope связывает контейнер с уникальным semantic descendant
через repeated_item_scope(ancestors=...). Генератор сохраняет структурную
глубину схлопнутых layout-обёрток, а runtime refs, CSS structural classes,
item-specific URLs и глобальные индексы не попадают в прототип.
ElementList, Repeated, Table.rows, Table.body_rows и Table.headers
являются ленивыми locator contracts, а не Python sequences. Прямая итерация
через for, enumerate, list и comprehensions отклоняется до browser-вызова.
Bounded traversal получает размер через
persona.get(ElementsCount(collection)) и обращается к
collection.nth(index) внутри range(count). Значения столбца читаются одним
persona.get(TableColumnData(table, column)).
Native <select multiple>, ARIA multiple listbox/combobox и Ant/UiKit multiple
select моделируются через Page-owned MultiSelect. Сценарий задаёт точный набор
через persona.make(SelectMultipleOptions(page.tags, values)), читает состояние
через persona.get(MultiSelectValues(page.tags)) и очищает control через
ClearTypedControl. Методы Page element select, add, remove, clear и
selected_values остаются typed runtime для собственных Ops. Они используют
полное совпадение option label, связанный popup и наблюдаемое selected-состояние.
Для виртуализированного Ant/UiKit select связь aria-controls адресует popup
через служебный listbox, кликабельные options принадлежат virtual list, а
выбранный label читается из содержимого chip независимо от его comment-title.
Успешные select и add закрывают связанный Ant/UiKit popup через keyboard
owner и ожидают его скрытия. Открытие соседнего MultiSelect сначала закрывает
точно связанный видимый popup, поэтому portal не перехватывает следующий control.
Page generator распознаёт multiple, aria-multiselectable=true и Ant/UiKit
multiple class markers и генерирует MultiSelect с variants.
Native date, datetime-local, time и Ant Design picker моделируются через
Page-owned DatePicker, DateTimePicker, DateRangePicker и TimePicker.
Сценарий вызывает SelectDate, SelectDateTime, SelectDateRange и
SelectTime через persona.make, а значения читает через
persona.get(PickerValue(...)) или persona.get(DateRangeValues(...)).
Операции принимают date/datetime/time либо канонические ISO-строки,
выбирают точную календарную ячейку или time-column value и ожидают наблюдаемое
значение input. Generator сохраняет picker одним полем Page и исключает
календарный popup и его ячейки из PageObject.
После генерации поддерживаемый 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,
html_name, title, url, alt_text и связанных 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 или
структурную семантику; 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 uses stable semantic or structural Page contracts. Snapshot
refs are temporary coordinates inside one Persona MCP browser session and are
never persisted in a ready Page/Element.
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 stable child fields such as
product_image, price, product_name, add_to_cart and view_product.
The generated item_scope connects the item container to one unique semantic
descendant through repeated_item_scope(ancestors=...), preserving structural
depth without persisting snapshot refs or structural CSS classes.
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 structural semantics; heading text remains a child element by itself.
RU: Web expectations проверяют составные UI-контролы через их семантические
targets. ToBeEnabled/ToBeDisabled читают состояние native и Ant/UiKit
Select, а ToBeClickable проверяет enabled, visibility, stability и получение
pointer events без выполнения клика. Видимое отключённое поле проверяется
композицией BeVisible(), ToBeDisabled(), визуально отсутствующее поле —
WaitForElementState(element, "hidden"); удалённый DOM-узел имеет состояние
detached.
EN: Web expectations evaluate composite controls through semantic targets.
ToBeEnabled/ToBeDisabled read native and Ant/UiKit Select state, while
ToBeClickable verifies enabled state, visibility, stability, and pointer-event
reception without clicking. Use BeVisible(), ToBeDisabled() for a visible
disabled field, WaitForElementState(element, "hidden") for a visually absent
field, and detached for a removed DOM node.
Автоматическая готовность UI-действий
UI-действия работают с ленивыми Playwright locator и сами ожидают готовность
целевого элемента. Structural Table, TableRow, TableCell,
ColumnHeader, indexed Select, relative_to(...) и текущий browser ref
сначала ожидают адресуемый DOM-узел, затем действие использует стандартную
Playwright actionability. PressKey ожидает видимый target, UploadFile —
прикреплённый file input. Selection и expansion таблицы ожидают соответствующий
checkbox или expander.
timeout действия применяется и к structural/semantic resolve, и к самому
Playwright-действию. Ошибка resolve содержит тип и описание target, structural
координаты и ожидаемый UI-контракт. Отдельный WaitFor* перед тем же действием
не нужен только ради появления его target.
Явное ожидание остаётся частью сценария, когда требуется самостоятельный
наблюдаемый сигнал: navigation/load state, popup или новая вкладка, network
response, завершение загрузки доменных данных, изменение атрибута либо другое
состояние, которое нельзя вывести из actionability целевого элемента.
force=True сохраняет Playwright-семантику и осознанно обходит часть проверок
actionability, но не structural/semantic resolve.
Конфигурация окружения / Environment Configuration
Persona автоматически определяет ОС процесса: win32 использует
platforms.windows, linux — platforms.linux, darwin —
platforms.macos. Параметр платформы в CLI и переменная
PERSONA_PLATFORM отсутствуют. Если блок текущей ОС не объявлен, действует
базовый YAML.
Persona detects the process OS automatically: win32 uses
platforms.windows, linux uses platforms.linux, and darwin uses
platforms.macos. There is no platform CLI option or
PERSONA_PLATFORM. An omitted current-platform block keeps the base YAML.
persona:
base-url: "https://example.test"
skills:
browser:
default:
base-url: "${persona.base-url}"
type: "chromium"
platforms:
windows:
skills:
browser:
default:
channel: "msedge"
linux:
skills:
browser:
default:
type: "chromium"
macos:
skills:
browser:
default:
channel: "chrome"
Окружение config/{env}.yaml выбирается в порядке: явный --env,
process PERSONA_ENV, PERSONA_ENV из общего .env,
[tool.persona].default_env. Значения свойств имеют приоритет:
process environment → .env.{env} → общий .env → platform overlay →
базовый YAML. Dotenv-файлы читаются отдельно для каждого Config и не
изменяют глобальный os.environ.
The environment selector order is explicit --env, process
PERSONA_ENV, common .env PERSONA_ENV, then
[tool.persona].default_env. Property precedence is process environment,
.env.{env}, common .env, the platform overlay, then base YAML. Dotenv
files are scoped to each Config and never mutate global os.environ.
Имена свойств используют relaxed binding: точки, дефисы и подчёркивания
преобразуются в одно подчёркивание, повторяющиеся разделители сворачиваются,
регистр переводится в верхний. Поэтому persona.base-url,
persona.base_url и persona.base.url соответствуют
PERSONA_BASE_URL; skills.browser.default.base-url соответствует
SKILLS_BROWSER_DEFAULT_BASE_URL. Env override применяется только к
существующему canonical property. Коллизия canonical имён является ошибкой.
Property names use relaxed binding: dots, hyphens, and underscores become one
underscore, repeated separators collapse, and letters become uppercase.
Therefore persona.base-url, persona.base_url, and
persona.base.url map to PERSONA_BASE_URL, while
skills.browser.default.base-url maps to
SKILLS_BROWSER_DEFAULT_BASE_URL. Environment overrides apply only to an
existing canonical property; canonical collisions are errors.
PERSONA_ENV=dev
PERSONA_BASE_URL=https://stage.example.test
SKILLS_BROWSER_DEFAULT_BASE_URL=https://browser.example.test
SKILLS_BROWSER_DEFAULT_HEADLESS=false
Корневые группы persona, service, project и другие custom property
groups допустимы, если хотя бы одно их свойство используется через
${...}. Точная ссылка сохраняет тип; ссылка внутри строки принимает scalar.
Env scalars читаются как YAML, списки — только как JSON arrays. Ссылки, циклы,
типы, дубликаты и коллизии диагностируются с файлом, строкой, столбцом и
property path. YAML-наследование extends не используется.
Custom root groups such as persona, service, and project are valid
when at least one property is consumed through ${...}. An exact reference
preserves its type, while string interpolation accepts scalars. Environment
scalars use YAML parsing and lists require JSON arrays. Reference, cycle, type,
duplicate, and collision errors include file, line, column, and property path.
There is no YAML extends inheritance.
config/{env}.yaml поддерживает batch generation documents:
generator.api.documents[]generator.json.documents[]generator.xsd.documents[]generator.soap.documents[]
XSD document задаёт корневую схему, output routing и необязательные XML prefixes:
generator:
xsd:
output_root: "support/contracts"
documents:
- name: "arrow_guides"
schema: "scenario_data/schemas/ArrowGuides.xsd"
package: "support.contracts.arrow_guides"
namespace_prefixes:
ns2: "urn:example:arrow-guides"
Генерация выполняется командой
persona-schema-gen xsd --xsd-document arrow_guides --project-root ..
namespace_prefixes управляет только написанием XML prefix. Namespace
элементов определяется XSD: импортированная схема без targetNamespace
остаётся no-namespace, а chameleon xs:include наследует namespace
включающей схемы. Generated codec проверяет XML через локальный XSD bundle и
явно отклоняет schema и payload с DOCTYPE.
MCP authoring surface использует единый Persona runtime:
- MCP
tools/callвозвращает вcontent[0].textсамодостаточный предметный результат: outcome, текущее состояние, diagnostics, точные следующие действия, recovery и переход.structuredContentсериализует тот же контракт для машинной обработки. Большие snapshot/history artifacts доступны по возвращённым путям через обычные файловые инструменты и MCP detail routes. persona_knowledgeчитает compact guide, guide_search, framework catalog и config catalog;include_examples=trueдобавляет package-owned examples выбранной темы или entity. Guide details/examples, search results, constructor properties, public methods и config fields всегда возвращаются server-owned страницами; продолжение выполняется только через returnednext_page/next_pagesи точныеtopic_index_offset,details_offset,examples_offset,constructor_offset,methods_offset,fields_offsetили searchoffset.framework_search.invocation_modesвыбирает symbols, которые поддерживают хотя бы один указанный live command mode; для web Ops используется точныйquery, затем returned entity route.persona_knowledge(action="agent_problem_resolution")возвращает единый рабочий цикл основного агента, primary roles и subagents: перечитать активный packet, получить project profile, пройти от memory record к source refs и code repositories, выбрать релевантные retrieval/project/Knowledge/domain/runtime источники, задать один вопрос пользователю и сохранить ответ. Task-local open question не является gap; evidence-backed gap или отдельная внешняя задача появляются только в финальной агрегации нерешённого остатка.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_retrievalобъединяет package core knowledge и discovery corpus текущего проекта.mode=auto|hybridможет использовать lexical ranking; structured и compact ответы явно сообщаютeffective_modeиsemantic_providerс CSS configured/used/status и фактическими model/dimension из query embedding response.mode=semanticвозвращает только semantic-ranked entries либоeffective_mode=semantic_unavailableс пустымentries, bounded diagnostics иnext_action. Project index обновляется черезaction=refresh, scope=project, аaction=wait, scope=project, wait_timeout_seconds=1..20возвращает текущую фазу и числовой прогресс job без остановки фоновой сборки по истечении bounded wait. Core index является package data и обновляется официальной knowledge/package сборкой..persona/**не входит в project discovery corpus, поэтому local runtime и retrieval artifacts не делают собственный index stale. EN: retrieval responses explicitly expose the effective mode and actual CSS provider metadata, semantic mode never substitutes lexical entries, project rebuild jobs expose bounded waits and progress, and the core index is immutable package data.persona_project_memoryуправляет памятью проекта:action=status|ingest|remember|recall|context|assess|retire|delete, typed records сmemory_type=semantic|episodic|procedural, evidence refs, validity window, supersede/conflict links, context packs, source/evidence packs and test sufficiency assessment. Agent-facingrecall/contextпо умолчанию возвращают только active records со статусамиaccepted|open;proposed|rejected|superseded|resolvedдоступны только при явномinclude_inactive=trueдля аудита. Ошибочные или устаревшие записи переводятся черезaction=retireвrejected|superseded|resolvedс обязательнымreason;action=deleteявляется hard-delete для явно выбранныхrecord_idsи также требуетreason.[tool.persona.project_memory].provider = "local"использует reviewed audit mirror.persona/project_memory/memory.jsonl;provider = "cognee"подключает optional Cognee library backend под.persona/project_memory/cogneeбез отдельного MCP server. Источники Jira/Confluence/repo/Persona inventory/run/session ingest-ятся как source evidence с content hash и parent/child refs, а не становятся памятью сами по себе. Context/source/evidence packs доступны через MCP resourcespersona-memory://..., включаяpersona-memory://sourcesandpersona-memory://context/<context_pack_id>. Human-facing views генерируются вне MCP черезpersona memory view,persona memory renderили Make targets; HTML graph viewer строит memory/kind/topic/source anchors из records, tags and source audit tree. EN:persona_project_memorystores verified active project memory records, keeps inactive audit records out of default agent context, and returns task-specific context packs instead of making the agent reinterpret raw sources on every task.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 той жеtask_id;new_session=trueсоздаёт отдельную session для subagent, аlifecycle=trueвыполняет runner lifecycle setup для указанногоscenario_id.persona_session_list(task_id=...)возвращает compact summaries active/suspended/completed sessions, последний snapshot и точныйcontinuationсpersona_session_stateлибоpersona_session_resume.persona_session_stateвозвращает сохранённыйlatest_observationи свежее состояние session: 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 MCP session владеет одним current browser state. Публичный ref имеет короткий вид
eNи используется черезpersona_browser(session_id=..., action=..., ref=...);snapshot_idиoccurrenceне входят в публичный browser action.findищет по тексту, properties, semantic path и необязательной role, аinspectчитает точный узел и окружение из сохранённого semantic index без нового browser capture.persona_session_resumeвосстанавливает checkpoint; если live state требует повторного наблюдения, Persona снимает current snapshot и выдаёт егоeNrefs. Generated Page/Element, Ant/UiKit Select, Table и Repeated разрешаются по стабильному semantic/structural контракту без ref. persona_make,persona_get,persona_checkпринимают typedoperationpayload изpersona_knowledge,persona_project, generation manifest или support plan и пишут каждый вызов в history. После любой команды, включая произвольные вложенные Web Ops, Step и CombinedStep, ответ содержит revisionedobservation: boundedresult_summary, orderedoperations_preview, artifact refs и при наличии browser page единыйbrowser.currentс URL/title/load state, snapshot path/revision и actionable refs;browser.changed_areaсодержит текущую область после navigation/tab change либо bounded diff после локального изменения. Отдельныйpersona_browser(action="snapshot")не требуется после каждой команды; полный ref index доступен по пути сохранённого snapshot. Tool schema содержит копируемыеpersona_valueexamples; например, текущий Pythondatetimeпередаётся как{"persona_value":"datetime","preset":"now"}, а точный — как{"persona_value":"datetime","iso":"2026-07-17T00:00:00"}.persona_valueявляется строковым discriminator, остальные поля находятся рядом с ним. Projectentityи ошибочная operation возвращаютaccepted_encodings, ожидаемый Python type и точныйinput_path; postponed annotations разрешаются до materialization. Одна authoring-команда сохраняет единую import identity project Step, generated XSD dataclass, Enum и SchemaBuilder от создания operation до завершения Step, поэтому live MCP и native runner используют один schema contract. 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. EN: every authoring command returns the current browser projection and bounded changed area independently of the nested operation type.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всегда создаёт durable launch и сохраняет UUIDrun_idдо запуска процесса. Начальныйaction="run"ждёт результат в пределахtest_run_inline_wait_ms: быстрый тест возвращает terminal status, item counts иreport_refsтем же MCP-вызовом; продолжающийся тест возвращаетstatus="running",run_id,launch_idи точныйcontinuationдляaction="wait".action="status"читает сохранённое состояние без ожидания,action="wait"продолжает bounded ожидание,action="cancel"записывает cancel request. Послеrunningагент продолжает тот жеrun_idи не запускает тест повторно.persona_session_close(status=passed|failed|partial)сохраняет browser checkpoint, history, receipts, snapshots и suspension record, переводит task-owned session вsuspendedи оставляет её доступной дляpersona_session_resumeс тем же ID.persona_session_finalize(session_id=...|task_id=..., status=...)вызывается только при завершении task, выполняет lifecycle close/failure hooks, освобождает runtime resources и сохраняет durable evidence в registry. EN: close suspends a durable session; finalize completes one session or every session owned by the task.persona_make,persona_get,persona_checkиpersona_browserподдерживают необязательныеcommand_idиidempotency_key. Append-only task/session journal фиксирует started/committed events, request digest, history, receipt и artifact hashes; повтор committed payload возвращает прежний результат без повторного действия, а конфликт или незавершённая запись завершаетсяPERSONA_SESSION_RECOVERY_FAILED. Browser resume загружает storage state в новый Playwright context, открывает реальный URL и снимает свежий semantic snapshot; сохранённый HTML не исполняется и не подставляется в страницу. EN: durable command identities provide at-most-once retry, while browser recovery restores native context state without DOM replay.
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 .venv/bin/persona migrate page-names --project-root . является thin wrapper над этой Persona CLI
командой. EN: starter .venv/bin/persona migrate page-names --project-root . is a thin wrapper over this
Persona CLI command.
Миграция snapshot refs / Snapshot ref migration
RU: persona migrate page-refs сканирует production Page DSL и удаляет
snapshot-scoped aria_ref, header_ref и Strategy.REF. Элементы со
стабильной semantic/structural strategy переписываются напрямую. Ref-only
элемент материализуется из scoped project-owned snapshots: объявленный
static_aria_snapshot_path имеет приоритет, затем проверяются локальные
support/pages/aria/<page>_*.yaml, а project-wide snapshots используются как
последняя область для вынесенного holder-файла. Persona проверяет SHA-256,
выбирает element subtree либо полный table subtree для header_ref,
последовательно запускает штатный generator/merge и атомарно пишет ref-free
Page и связанные Python component updates. Входные snapshots остаются
неизменяемым evidence:
миграция не сериализует выбранный subtree в новый YAML и не меняет объявленный
static_aria_snapshot_path. Одинаковая semantic identity в нескольких
состояниях дедуплицируется; разные identities одного legacy ref дают
диагностируемую snapshot_identity_ambiguous только внутри выбранной
Page-области. Совпавший snapshot-scoped ref другой страницы не конкурирует с
объявленным snapshot. Объявленные и локальные snapshots страницы валидируются
всегда; project-wide fallback читается только для оставшихся legacy refs, а
нерелевантный повреждённый snapshot другой страницы не блокирует миграцию.
Команда не требует Persona MCP session, task ID или session ID. При отсутствии
generated state snapshots apply сохраняет все доказанно безопасные rewrite,
materialization и удаления no_known_usages, а unresolved used/unknown поля
оставляет с точными coordinates, usages и typed remediation action. После
сохранения недостающего состояния Page повторяется та же команда. Generated и
мигрированные Generic, Ant/UiKit, Table и Repeated элементы используют stable
semantics и specialized structural resolvers; runtime ref в готовый Page или
тест не переносится. Для безымянных Ant Select мигратор восстанавливает
локальный index внутри доказанного owner-контейнера и сохраняет объявленные
enum/options. Generator result без доказуемой semantic/structural strategy не
считается materialization и не заменяет используемое Page field.
Project reference graph строится один раз на invocation, различает прямое
использование, by_variant(...) и composition holder через дочерний путь.
Ref поля, которое во всех usages выбирается через by_variant(...), удаляется
только когда вариант сам задаёт полную semantic identity; прямой resolve того
же Text(variants=...) остаётся unresolved. Один apply удаляет все доказанно
неиспользуемые поля, включая поля вложенных generated-классов, и записывает
проект одной атомарной транзакцией. Удаление другого unused-поля не стирает
reason, snapshot paths и usage evidence оставшегося unresolved элемента.
Одинаковые имена вложенных классов различаются по exact legacy ref; при
реальной неоднозначности ошибка перечисляет файл, source coordinates и все
candidate assignments.
CLI по умолчанию немедленно печатает line-oriented progress в stderr:
discovery Page-файлов, текущий Page N/total, чтение snapshot, parse/usages
каждого Python-файла при построении reference index, атомарную запись и
финальные счётчики. Jenkins и перенаправленный shell log показывают активную
фазу без смешивания с итоговым Markdown в stdout. --progress never отключает
только progress и сохраняет отчёт и exit code. Каждый project snapshot
проверяется и парсится один раз на invocation, затем его typed artifact
переиспользуется для остальных Page. Согласованные отступы 2 или 4 пробела в
persisted Rich ARIA snapshots сохраняют одну и ту же иерархию; конфликтующий
отступ прямых потомков остаётся ошибкой структуры. Беззначные boolean
properties checked, disabled, expanded, hidden, pressed и selected
записываются как - /<property>; остальные properties требуют форму
- /<property>: "<value>".
Итоговый Markdown группирует снятые refs, восстановленные элементы, удалённые
unused-поля и unresolved-действия по project-relative файлам. Восстановленное
поле ссылается на конкретный snapshot evidence path; абсолютные пути и
дублирующие технические action-строки в отчёт не выводятся.
EN: persona migrate page-refs replaces production snapshot refs using a
Page-scoped priority: declared static_aria_snapshot_path, local Page state
snapshots, then project-wide fallback for a separate holder module. It verifies
every artifact, resolves refs across separate Page/Elements modules, and
regenerates exact element or table subtrees through the normal structural merge
without an MCP session. A ref reused by another Page cannot make the declared
snapshot ambiguous. Input snapshots remain immutable evidence: migration never
persists the selected subtree as a new YAML artifact or replaces the Page's
declared static_aria_snapshot_path. Declared and local Page snapshots are
always validated; project-wide fallback is loaded only for unresolved legacy
refs, so an unrelated malformed snapshot from another Page cannot block the
migration.
Unnamed Ant Select controls receive an owner-local index when the verified
snapshot proves their container, while authored enum/options remain intact.
An unresolved generator result is retained as a typed remediation action and
never replaces a used Page field.
The project reference graph is built once per invocation and distinguishes
direct, by_variant(...), and composition-path usage. Variant-bound fields are
rewritten only when the selected variant supplies a complete semantic identity;
direct resolution remains unresolved. A single apply removes every
proven-unused field, including fields in nested generated classes, and writes
the project through one atomic transaction. Existing reason, snapshot paths,
and usage evidence survive coordinate-changing removals. Exact legacy refs
disambiguate repeated nested class names; genuine ambiguity reports the file,
source coordinates, and every candidate assignment.
The CLI streams Page, snapshot, per-file reference-index, atomic-write and
summary progress to stderr by default, including in CI and redirected logs.
The final Markdown report remains isolated in stdout; --progress never
disables only progress output. Each project snapshot is parsed once per
invocation and its typed artifact is reused across Page files. Persisted Rich
ARIA snapshots may use a consistent two- or four-space child indentation;
conflicting direct-child indentation remains a structural error. Bare
checked, disabled, expanded, hidden, pressed, and selected
properties represent true; every other property requires
- /<property>: "<value>".
The report groups rewrites, materializations, unused removals, and unresolved
actions under project-relative paths. Every materialized field links to its
snapshot evidence path; absolute paths and duplicate raw action lines are not
emitted.
persona migrate page-refs --project-root .
persona migrate page-refs --project-root . --apply
persona migrate page-refs --project-root . --apply --progress never
make migrate-page-refs APPLY=1
make migrate-page-refs
Пользовательский проект
Официальный starter расположен в template/.
pyproject.tomlconfig/<env>.yamlconfig/auth.yamlscenarios/**/test_*.pyscenarios/**/__suite__.pyscenario_data/support/
Сценарий или ветка suite может быть отключена через disabled(reason) на
test_* или suite(disabled=True, disabled_reason=...) в __suite__.py.
Такие сценарии остаются в discovery/catalog с причиной, но не попадают в
обычный persona run / make test; контролируемый запуск требует
--include-disabled.
Команды starter:
cd template
make install
make checks
make redis
make redis action=status
Создание и обновление Persona-проекта
RU: persona project init создаёт пустой Persona-проект из template,
упакованного внутрь установленного persona-dsl wheel/sdist. Команда по
умолчанию работает в текущей директории; --project-root <path> указывает
другой каталог. Пакетный template содержит только production skeleton:
Makefile, pyproject.toml, .gitignore, persona.check.yaml, минимальный
config/, пустые scenarios/ и support/, а также managed Make targets в
.persona/make/persona.mk. Starter tests, starter data, учебные сценарии,
reports, caches, .venv и egg-info не входят в project bootstrap.
persona project init владеет только package-owned scaffold и lifecycle state;
команда не создаёт .venv. Package-owned runtime phase для интеграционных
клиентов запускается managed Python без Make и без standalone-скрипта:
<MANAGED_PYTHON> -m persona_dsl.cli project install-runtime \
--project-root <PROJECT_ROOT> --json
Эквивалентная команда установленного managed executable: persona project install-runtime --project-root <PROJECT_ROOT> --json. Она создаёт project
.venv, устанавливает build/runtime/dev requirements проекта без преждевременного
разрешения Persona requirement и закрепляет package-owned безопасный минимум
pip для локального dependency audit, последней закрепляет distribution и точную
версию Persona, которой принадлежит managed runtime, устанавливает editable
project metadata с --no-deps, затем проверяет project Python, Persona CLI, MCP
и LSP. Имя distribution и версия не принимаются от consumer, поэтому public и
corporate builds используют identity фактически запущенного package.
Install source также принадлежит producer. Retained local source или wheel из
direct_url.json преобразуется в проверенный PEP 508 direct reference и входит
в content fingerprint; путь не публикуется в machine payload. При отсутствии
доступного local artifact используется exact distribution==version через
настроенный pip registry. Изменение retained source меняет fingerprint и
запускает повторную установку той же development version.
В machine mode stderr содержит последовательные JSONL-события
persona.project-runtime-install-progress, а stdout содержит один итоговый
payload persona.project-runtime-install. Progress использует закрытые phase
preflight, environment, dependencies, distribution, metadata,
verification. Успех возвращает installed или noop и exit code 0; ошибка
возвращает error, bounded diagnostic и exit code 1; ошибка синтаксиса CLI
использует exit code 2. Receipt содержит exact distribution/version,
проверенные executables, dependency fingerprint и путь к durable local state.
Повторный вызов из проверенного project runtime возвращает исходный receipt со
статусом noop без install phases. Вызов из managed runtime продолжает
сравнивать provider source fingerprint и выполняет установку при его изменении.
После runtime phase Qompanion получает preview от project .venv, сохраняет
plan_digest и применяет только этот plan:
<PROJECT_ROOT>/.venv/bin/persona project reconcile \
--project-root <PROJECT_ROOT> \
--persona-package-name <RECEIPT_DISTRIBUTION> \
--persona-version-spec ==<RECEIPT_VERSION> \
--dependency-mode add --json
<PROJECT_ROOT>/.venv/bin/persona project reconcile \
--project-root <PROJECT_ROOT> \
--persona-package-name <RECEIPT_DISTRIBUTION> \
--persona-version-spec ==<RECEIPT_VERSION> \
--dependency-mode add --approved-plan-digest <PLAN_DIGEST> --yes --json
stale_plan требует нового preview; consumer не применяет изменившийся plan по
старому digest. Direct CLI lifecycle остаётся доступен через make install и
standalone install-persona.py, но они не являются runtime API Qompanion.
RU: persona project update обновляет только Persona-owned scaffolding
существующего проекта с pyproject.toml. Для пустой директории используется
persona project init; update не создаёт проект и не добавляет отсутствующие
README, config, scenarios/, support/, persona.check.yaml или
.gitattributes. Update синхронизирует Persona sections в существующем
pyproject.toml, восстанавливает отсутствующий .gitignore, синхронизирует
один Persona-managed блок в существующем .gitignore и поддерживает managed
Make infrastructure .persona/make/persona.mk с include в корневом Makefile.
Пользовательские правила до и после bounded-блока .gitignore сохраняются;
повреждённые или повторённые Persona-границы пересобираются в один канонический
блок. Обычный вызов сразу применяет весь детерминированный plan без вопросов и
одинаково работает в TTY и non-TTY. Результат проверяется через Git diff и
историю проекта. --check, --dry-run и --diff-only являются явными
read-only режимами; --interactive включает необязательный поэлементный
просмотр. Для зарегистрированного packaged Makefile lifecycle синхронизирует
актуальные targets в .persona/make/persona.mk и оставляет в root Makefile один
include. Изменённый Makefile с Persona targets сохраняет project-owned команды
и получает canonical include. Полный контент package-owned persona.mk
доступен через --diff-only. Update
сохраняет [project].name, [project].version, пользовательские Make targets,
бизнес-тесты и данные. Corporate package задаётся явно через
--persona-package-name и --persona-version-spec; Persona dependency не
угадывается и не переписывается молча. persona project update предоставляет
отдельный diff-first CLI, а make update-project является переходным алиасом
полного make install.
Настройка agent-клиентов
make install является единым lifecycle Persona-проекта. Команда создаёт
.venv, устанавливает зависимости, применяет content-addressed project plan,
материализует package-owned agent surface, настраивает локальные интеграции и
завершает работу через persona agent doctor. make init и
make update-project являются алиасами того же пути. Установка package и
согласование изменившейся project surface завершаются в одном вызове без
последующей отдельной команды. Зарегистрированный старый Make lifecycle с
project audit передаёт управление установленной Persona и завершает reconcile,
init и doctor внутри того же make install, в том числе для Windows-проектов с
CRLF. Persona-reserved MCP definitions Atlassian и Zephyr синхронизируются как
secret-free project definitions; unrelated project MCP servers сохраняются.
Project-local surface содержит полный version-matched набор Persona:
.qwenили.gigacodeс context, slash-командами, primary roles и subagents;- package-owned skills и workflow templates;
- Persona-owned fragments client settings и lifecycle hooks;
.lsp.jsonс portable Persona LSP;- Persona MCP с точным project/worktree root для каждой сессии;
.persona/project_memoryи.persona/workflowsкак durable state проекта.
Reconcile вычисляет владение из package contract и текущих файлов, без
project-local ownership manifest. Package-owned файлы синхронизируются с
установленной Persona, bounded Persona sections в .gitignore, client context,
settings, hooks и LSP объединяются структурно, а durable memory/workflow state
не перезаписывается. LF и CRLF являются одной Git-проекцией package-owned UTF-8
текста; запись выполняется в canonical LF. Устаревший
.persona/project/ownership.json удаляется без чтения его содержимого.
Повторный make install для актуального проекта завершается без повторной
материализации и без registry-операций.
Выбор встроенного agent profile задаётся при сборке Persona. Дефолт объявлен в
pyproject.toml:
[tool.persona.agent_distribution]
default = "gigacode"
CI/release сборка может выпустить другой distribution без изменения template-проекта:
PERSONA_AGENT_DISTRIBUTION=qwen make build
PERSONA_AGENT_DISTRIBUTION=qwen make package-smoke
default_profile = "gigacode"
enabled_profiles = ["gigacode"]
[[profiles]]
id = "gigacode"
adapter = "gigacode"
display_name = "GigaCode Persona Agent"
scope = "project"
mcp_servers = ["persona"]
workflows = [
"project-profile",
"project-map",
"test-plan",
"test-sufficiency",
"author-test",
"test-run",
"test-integration",
"acceptance",
"run-analysis",
"memory-refresh",
"quality-refactor",
]
client_command = "gigacode"
Starter user flow:
make install
make agent
make install выполняет interactive setup для локального checkout, сохраняет
typed integration settings вне Git и рендерит surface выбранного клиента.
Каждый запуск агента проверяет current lifecycle, binding, client runtime,
project-local surface, Persona MCP и LSP. После обновления Persona повторный
make install применяет только изменившийся package-owned контракт.
make agent launches the selected client with the current project .venv
first in PATH and with VIRTUAL_ENV set. The agent can call persona,
python and rendered skill scripts without activating the environment or
probing executables. make agent-continue, make agent-resume and every
stage shortcut use the same runtime contract. Slash commands provide the exact
initial Persona CLI invocation with the user's natural-language scope. Each
successful response returns task_id, packet/state paths and one named next
action; continuation uses the printed high-level route without shell JSON.
Parallel tasks use isolated Git worktrees and isolated Python environments:
make agent worktree=test-login
make agent-worktree-list
make agent worktree=test-login
make agent worktree=api-refactor worktree_root=../task-worktrees
make agent-worktree-close worktree=test-login
make agent-worktree-close worktree=test-login force=true
make agent-worktree-close worktree=test-login delete_branch=true
The first command creates branch persona/test-login from the current HEAD,
then materializes the base checkout staged, unstaged and non-ignored untracked
files before dependency installation. Git staging is preserved. The snapshot
base, digest and paths are stored under ignored .persona/local; a reused
worktree rejects a different dirty source snapshot instead of overwriting task
work. Each worktree owns its .venv, and make install runs when its dependency
fingerprint changes. The worktree .venv/bin/persona renders its own
project-local surface and proves the high-level route contract before the model
client starts.
Project-local settings and runtime files are synchronized separately:
.persona/local/agent-bootstrap.local.json, config/auth.yaml, .env,
.env.* and config/auth.*.yaml; *.example* files are excluded.
make agent-worktree-list prints registered Persona worktrees with path, branch
and clean status. make agent-worktree-close worktree=<name> runs
git worktree remove for a clean Persona-owned worktree and then
git worktree prune. Dirty worktrees stop with a warning; force=true removes
the working directory through git worktree remove --force. delete_branch=true
also removes the local persona/<name> branch; with force=true it uses
git branch -D.
Client runtime lifecycle is distribution-owned. A required Qwen profile writes
private settings to
.persona/local/client-runtime/<profile-id>/settings.json and passes the file
through QWEN_CODE_SYSTEM_SETTINGS_PATH; Persona does not rewrite user or
project Qwen settings. Qwen SessionStart, PreCompact, Stop, StopFailure,
SessionEnd and scoped tool-failure hooks bind the exact client session and
attach the current task, flow, route, packet, finding, knowledge lookup and
continuation. Hook diagnostics are context and do not block model, tool,
command or delegation execution. persona agent client-status
renders the read-only task/stage/gap/context status line. Managed Qwen automatic,
team and dream memory are disabled because Persona project memory owns durable
project knowledge.
The tracked .qwenignore excludes local runtime/cache/view paths from Qwen file
discovery without hiding durable workflow packets, reviewed memory or project
sources. persona agent doctor --project-root . validates lifecycle state,
client version, binding, project-local inventory, settings ownership, MCP, LSP
and context policy.
Direct CLI flow:
persona agent init --project-root .
persona agent launch --project-root . --mode new
persona agent launch --project-root . --mode continue
persona agent launch --project-root . --mode resume --session-id <session-id>
make agent delegates to the same typed launcher and starts the selected client
without choosing a workflow. A raw qwen or gigacode command remains an
ordinary non-Persona session. The user selects a concrete route with
/persona.<route> inside the Persona session.
Long-running role entrypoints keep separate commands because they select a
package-owned primary prompt rather than a route.
Long-running test work can start with a primary role without choosing a route, task or packet:
make agent-test-analysis
make agent-test-author
agent-test-analysis starts the current client as the test-analysis owner and
waits for /persona.test-sufficiency .... agent-test-author starts it as the
test-authoring owner and waits for /persona.author-test .... The slash command
binds the concrete route and task inside the open session; the current agent
executes that route directly. Files under agents/persona-*.md define bounded
child-agent assignments.
Qwen и GigaCode получают одинаковый capability catalog: route-команды, четыре bundled skill, route reference, system prompt, workflow packet templates, primary roles и subagent assignments. Renderer размещает эти файлы в namespace конкретного проекта и сверяет Persona-reserved paths с package contract. Project path, credentials и runtime settings не встраиваются в package-owned тексты.
persona agent init проверяет current project lifecycle, настраивает private
client runtime и binding, проверяет MCP/LSP и выполняет resumable migration
старых project-specific registry entries. persona agent legacy-scan доступен
только для аудита legacy installations. Registry entry удаляется после успешной
проверки project-local surface и launch; старый generated source удаляется при
полном совпадении ownership hashes. Доказанный managed source с
client-generated cache сохраняется в content-addressed private recovery
.persona/local/recovery/legacy-agent-extensions/ и удаляется из
.persona/agent_extensions; изменённый или не подтверждённый source остаётся
на месте с явным conflict.
Typed launcher читает system prompt из .<client>/persona, проверяет обычные
project MCP definitions и запускает vendor CLI без shell, extension flags и
временного MCP config. Slash-команда выбирает workflow внутри открытой сессии.
Route использует durable Markdown packet, project-memory receipts и обязательные
views; stdout агента не является workflow evidence.
Локальные интеграции настраиваются во время интерактивного make install или
точными recovery-командами persona agent init --project-root . --configure-atlassian, --configure-css и --configure-zephyr. Значения
Atlassian, CSS и Zephyr хранятся в git-ignored
.persona/local/agent-bootstrap.local.json; process environment проецируется в
git-ignored .env с сохранением пользовательских переменных.
Atlassian runtime находится в
.persona/local/atlassian-mcp/.venv, содержит закреплённые версии
mcp-atlassian, redis и Authlib и запускается с READ_ONLY_MODE=false и
TOOLSETS=all. Zephyr использует persona-zephyr-mcp из project .venv,
project-local журнал .persona/mcp/zephyr-mcp.log и trust=false. Credentials
не попадают в tracked client settings, workflow packets или MCP definition.
make install добавляет Persona и настроенные Atlassian/Zephyr integrations в
обычный project-local .qwen/settings.json или .gigacode/settings.json.
Definitions содержат переносимые команды, cwd, timeout и trust без credentials.
Приватные значения хранятся в .persona/local/agent-bootstrap.local.json,
проецируются в .env и передаются дочернему client process через environment.
make agent проверяет executable каждого настроенного сервера и передаёт
клиенту точный список разрешённых имён отдельными значениями
--allowed-mcp-server-names. Persona MCP получает фактический project/worktree
root. Обычный vendor CLI, запущенный в проекте, использует ту же project MCP
поверхность без global extension.
Для transport-диагностики .venv/bin/persona-zephyr-mcp --project-root .
запускает long-lived server в foreground. Журнал содержит JSON-RPC request
start/end, safe issue/test keys, status, diagnostic и elapsed time; PAT,
Authorization и protocol bodies не записываются. zephyr_test_case_get читает
до 50 шагов на страницу, а большие значения продолжает через точный JSON
Pointer в zephyr_test_case_value.
Tracked project state включает Persona-managed client surface,
.persona/make/persona.mk,
.persona/project_memory/memory.jsonl, .persona/project_memory/sources/** и
.persona/workflows/**. Binding, local settings, runtime projections, context
packs, rendered views, retrieval indexes, MCP logs, dependencies, databases,
locks и временные файлы игнорируются Git. .gitattributes назначает
merge=union для memory JSONL; derived views пересобираются через
make memory action=render.
artifact-hygiene использует тот же закрытый path contract: managed Make,
memory JSONL, source provenance и workflow packets разрешены;
runtime, backups и неизвестные пути внутри .persona считаются локальными
артефактами и не должны попадать в Git.
Повторный make install сверяет dependency fingerprint, report runtime,
content-addressed project plan, client binding, MCP/LSP и doctor. Совпадающий
контракт возвращает noop; устаревший package-owned artifact обновляется одной
project transaction. Локальные secrets при reconcile не переписываются.
Сценарии Persona Agent
task_id идентифицирует один flow, объявленный в Identity.flow. Route видит packets и receipts этого flow. Project-discovery передаёт другим flows принятую project memory, но не свои packets.
| Flow | Тип | Entry | Completion | Routes |
|---|---|---|---|---|
project-discovery |
composed | project-profile, project-map |
project-profile, project-map |
project-profile, project-map |
memory-maintenance |
atomic | memory-refresh |
memory-refresh |
memory-refresh |
new-test |
composed | test-plan |
test-integration, acceptance |
test-plan, test-sufficiency, author-test, test-run, run-analysis, test-integration, acceptance |
manual-case-automation |
composed | test-sufficiency, author-test |
test-integration, acceptance |
test-sufficiency, author-test, test-run, run-analysis, test-integration, acceptance |
test-execution |
composed | test-run, run-analysis, acceptance |
test-run, test-integration, acceptance |
test-run, run-analysis, author-test, test-integration, acceptance |
quality-campaign |
atomic | quality-refactor |
quality-refactor |
quality-refactor |
Индекс: persona_knowledge(action="agent_flows"). Полный flow: persona_knowledge(action="agent_flow", flow_id="<flow>"). Точный route: persona_knowledge(action="agent_route", route="<route>").
Bundled skills are domain playbooks, not extra slash-command stages:
persona-project-memoryis used by project-map, memory-refresh and source-backed test planning. It owns scoped source evidence, Confluence parent/child checklists, reviewed memory records, gaps, context packs and view refresh decisions.persona-test-authoringis used by live test-sufficiency, author-test and code-changing test-integration. In sufficiency mode it owns runtime traversal evidence without code writes; authoring mode owns support generation, Page/Step/Fact/Expectation structure,persona_test_authordraft/write and runner verification.persona-run-evidenceis used by test-run, run-analysis and acceptance. It owns UUIDrun_id, session/run binding, report refs, failure taxonomy, acceptance packets and post-run memory updates.persona-quality-refactoris used by quality-refactor. It owns the strict baseline, structure/guides/suppression reviews, dependency-ordered root-cause plan, bounded remediation checkpoints, repeated gates and final evidence.
Slash commands remain the user workflow; skills are the reusable professional behavior the launched agent applies inside that workflow.
Atlassian-scoped project-map examples:
/persona.project-map agent_args="source=confluence:SPACE-123 include_children=true"
/persona.project-map agent_args="source=confluence:987654 include_children=false"
/persona.test-plan jira=PROJ-123
Inside GigaCode the same parameters are passed directly to slash workflows:
/persona.project-map task_id=auth-map source=confluence:SPACE-123 include_children=true
/persona.project-map task_id=repo-map source=repo:pyproject.toml
/persona.test-plan jira=PROJ-123 source=confluence:987654
/persona.project-map составь карту по Confluence page 987654 с дочерними страницами
/persona.test-plan подготовь план по Jira PROJ-123 и Confluence 987654
include_children=true means the agent must build a Source Checklist for the
parent Confluence page and each discovered child before extraction. Missing
Atlassian access or unreadable child pages become project-memory gap records.
Natural-language slash input is accepted when it contains a concrete Jira key,
Confluence page id or scope ref; the agent canonicalizes it to the same scoped
arguments and must ask for the missing identifier instead of broad searching.
Cognee-backed project memory is an optional package extra and project config:
pip install "persona-dsl[memory-cognee]"
[tool.persona.project_memory]
provider = "cognee"
dataset_name = "persona_project"
top_k = 15
use_domain_graph_model = true
self_improvement = false
include_backend_context = true
Persona keeps one MCP server. GigaCode/Qwen calls persona_project_memory; Persona
ingests raw sources into Cognee as the project-local graph/vector backend and
keeps reviewed records in .persona/project_memory/memory.jsonl.
persona memory status --project-root .
persona memory view --project-root .
persona memory serve --project-root . --host 127.0.0.1 --port 8776
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
make redis action=status
Data Pools
runtime.data_pools описывает эксклюзивные элементы для параллельных запусков.
Типизированный resource объявляется обычным классом в support/resources:
from persona_dsl import Persona, leased_resource
@leased_resource("parallel.user", pool="parallel_users")
class ParallelUser:
item_id: str
username: str
password: str
def test_parallel_login(persona: Persona) -> None:
user = persona.resource(ParallelUser)
login(user.username, user.password)
@leased_resource сам создаёт strict frozen/slotted dataclass. item_id
берётся из lease envelope, остальные поля класса — из одноимённых ключей
payload. Лишние, отсутствующие и несовместимые по типу поля завершают
получение ресурса диагностируемой ошибкой. Runtime берёт lease при фактическом
persona.resource(ParallelUser) и освобождает его через lifecycle test-scoped
resource. define_lease_resource(...) остаётся для ресурсов с пользовательской
фабрикой, преобразованием или cleanup.
config/dev.yaml связывает pool с отдельным YAML-файлом:
runtime:
data_pools:
parallel_users:
backend: "local_sqlite"
acquire_timeout_sec: 30
lease_ttl_sec: 300
heartbeat_interval_sec: 30
items_source:
path: "scenario_data/data_pools/parallel_users.yaml"
format: "yaml"
scenario_data/data_pools/parallel_users.yaml содержит элементы пула:
- item_id: "parallel_user_01"
payload:
username: "test-user-01"
password: "credential-placeholder-01"
Элемент пула требует только 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 включает guide, framework/config catalogs, retrieval corpus и build-time completeness inventory. Проверка выполняется через:
make knowledge-generate
make knowledge-check
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.8.4rc167.tar.gz.
File metadata
- Download URL: persona_dsl-2026.8.4rc167.tar.gz
- Upload date:
- Size: 10.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
383227b5ee185edafee70b447c66197c7189674d0c57bfc932f6c2438b8b07de
|
|
| MD5 |
21a2c00aed6b82158b818a0c4fcb72a5
|
|
| BLAKE2b-256 |
dfb2a3c92a53e0cb05c6790d23d9411d3718bbf6c67153970a95da3ec0b0a9a2
|
File details
Details for the file persona_dsl-2026.8.4rc167-py3-none-any.whl.
File metadata
- Download URL: persona_dsl-2026.8.4rc167-py3-none-any.whl
- Upload date:
- Size: 11.2 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25fe1e0ea4ec9192975728f557e0074351d6047c964bb572dffa653e96fad64d
|
|
| MD5 |
173fd3a68d522889c81e8c3804a990b8
|
|
| BLAKE2b-256 |
f135cb75eff9e2b0fa176ac23d16f370d59fbbfc221ef1993425b9ff1d6a2b1d
|