Настройка процесса генерации документации
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.steps.step3_parse_requirements.parser import (
|
||||
FunctionalRequirementsParser,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.steps.step4_prepare_tasks.services import (
|
||||
RequirementTaskBuilder,
|
||||
RequirementTaskOrderer,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.steps.step5_execute_subprocesses.classifier import (
|
||||
DeleteIntentHeuristic,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.subprocesses.common.source_sections import (
|
||||
RequirementSourceSections,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.subprocesses.common.template_parser import (
|
||||
TemplateParser,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.workflow_runtime.context import (
|
||||
DocUpdateFromFeatureV2Context,
|
||||
)
|
||||
from app.core.agent.processes.v2.workflows.doc_update_from_feature_v2.workflow_runtime.models import (
|
||||
AnalyticsMeta,
|
||||
RequirementUnit,
|
||||
)
|
||||
|
||||
|
||||
class _UnexpectedLlmCall:
|
||||
def generate(self, *args, **kwargs): # noqa: ANN002, ANN003
|
||||
raise AssertionError("LLM should not be called for explicit happy-path metadata.")
|
||||
|
||||
|
||||
def test_parser_reads_section_6_metadata_and_units() -> None:
|
||||
parser = FunctionalRequirementsParser()
|
||||
content = """
|
||||
analysis_id: AN-42
|
||||
application: loyalty
|
||||
platform: web
|
||||
|
||||
# 6. Функциональные требования
|
||||
domain: billing
|
||||
sub_domain: payments
|
||||
|
||||
## 6.1 Экран статуса платежа
|
||||
id: payment-status
|
||||
doc_type: ui_page
|
||||
application: loyalty
|
||||
platform: pprb
|
||||
|
||||
### Функциональные требования
|
||||
- Показываем статус и ошибку.
|
||||
|
||||
## 6.2 Метод получения статуса
|
||||
id: get-payment-status
|
||||
doc_type: api_method
|
||||
application: loyalty
|
||||
platform: ufs
|
||||
|
||||
### Контракт метода
|
||||
- GET /payments/status
|
||||
""".strip()
|
||||
|
||||
meta, units = parser.parse(content)
|
||||
|
||||
assert meta.analysis_id == "AN-42"
|
||||
assert meta.application == "loyalty"
|
||||
assert meta.platform == "web"
|
||||
assert meta.domain == "billing"
|
||||
assert meta.subdomain == "payments"
|
||||
assert [unit.section_key for unit in units] == ["6.1", "6.2"]
|
||||
assert [unit.heading for unit in units] == ["Экран статуса платежа", "Метод получения статуса"]
|
||||
assert units[0].metadata["doc_type"] == "ui_page"
|
||||
assert "Показываем статус" in units[0].body
|
||||
|
||||
|
||||
def test_parser_reads_backticked_root_metadata_format() -> None:
|
||||
parser = FunctionalRequirementsParser()
|
||||
content = """
|
||||
# 6. Описание изменений
|
||||
|
||||
- `domain`: `orders`
|
||||
- `sub_domain`: `list_read`
|
||||
|
||||
## 6.1 Страница списка заказов
|
||||
id: orders.ui.list
|
||||
doc_type: ui_page
|
||||
application: orders_web
|
||||
platform: web
|
||||
|
||||
### Требования к UI
|
||||
- Таблица заказов.
|
||||
""".strip()
|
||||
|
||||
meta, units = parser.parse(content)
|
||||
|
||||
assert meta.domain == "orders"
|
||||
assert meta.subdomain == "list_read"
|
||||
assert len(units) == 1
|
||||
assert units[0].metadata["doc_type"] == "ui_page"
|
||||
|
||||
|
||||
def test_task_builder_orders_platforms_and_inherits_root_context() -> None:
|
||||
context = DocUpdateFromFeatureV2Context(
|
||||
runtime=SimpleNamespace(),
|
||||
route=SimpleNamespace(),
|
||||
rag_session_id="",
|
||||
analytics_meta=AnalyticsMeta(
|
||||
analysis_id="AN-42",
|
||||
application="loyalty",
|
||||
domain="billing",
|
||||
subdomain="payments",
|
||||
),
|
||||
requirements=[
|
||||
RequirementUnit(
|
||||
section_key="6.3",
|
||||
heading="WEB страница",
|
||||
body="Описание",
|
||||
metadata={"id": "web-page", "doc_type": "ui_page", "platform": "web", "op": "create"},
|
||||
),
|
||||
RequirementUnit(
|
||||
section_key="6.1",
|
||||
heading="PPRB страница",
|
||||
body="Описание",
|
||||
metadata={"id": "pprb-page", "doc_type": "ui_page", "platform": "pprb", "op": "create"},
|
||||
),
|
||||
RequirementUnit(
|
||||
section_key="6.2",
|
||||
heading="UFS метод",
|
||||
body="Описание",
|
||||
metadata={"id": "ufs-method", "doc_type": "api_method", "platform": "ufs", "op": "create"},
|
||||
),
|
||||
],
|
||||
)
|
||||
builder = RequirementTaskBuilder(_UnexpectedLlmCall())
|
||||
orderer = RequirementTaskOrderer()
|
||||
|
||||
tasks = orderer.order(builder.build(context))
|
||||
|
||||
assert [task.platform for task in tasks] == ["pprb", "ufs", "web"]
|
||||
assert [task.section_key for task in tasks] == ["6.1", "6.2", "6.3"]
|
||||
assert all(task.application == "loyalty" for task in tasks)
|
||||
assert all(task.domain == "billing" for task in tasks)
|
||||
assert all(task.subdomain == "payments" for task in tasks)
|
||||
assert tasks[0].path == "docs/billing/pprb/ui_page/pprb-page.md"
|
||||
|
||||
|
||||
def test_task_builder_uses_create_when_path_is_new_and_no_delete_markers() -> None:
|
||||
context = DocUpdateFromFeatureV2Context(
|
||||
runtime=SimpleNamespace(),
|
||||
route=SimpleNamespace(),
|
||||
rag_session_id="",
|
||||
analytics_meta=AnalyticsMeta(
|
||||
application="orders_web",
|
||||
domain="orders",
|
||||
subdomain="list_read",
|
||||
),
|
||||
requirements=[
|
||||
RequirementUnit(
|
||||
section_key="6.1",
|
||||
heading="Страница списка заказов",
|
||||
body="### Требования к UI\n- Показывать таблицу заказов.",
|
||||
metadata={
|
||||
"id": "orders.ui.list",
|
||||
"doc_type": "ui_page",
|
||||
"application": "orders_web",
|
||||
"platform": "web",
|
||||
},
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
tasks = RequirementTaskBuilder(_UnexpectedLlmCall()).build(context)
|
||||
|
||||
assert len(tasks) == 1
|
||||
assert tasks[0].action.value == "create"
|
||||
assert tasks[0].path == "docs/orders/web/ui_page/orders.ui.list.md"
|
||||
|
||||
|
||||
def test_delete_heuristic_does_not_match_phrase_ne_udalos() -> None:
|
||||
heuristic = DeleteIntentHeuristic()
|
||||
|
||||
assert heuristic.is_delete("Не удалось загрузить список заказов.") is False
|
||||
assert heuristic.is_delete("Нужно удалить существующую страницу документации.") is True
|
||||
|
||||
|
||||
def test_template_parser_extracts_ordered_sections_from_ui_template() -> None:
|
||||
parser = TemplateParser()
|
||||
template = """
|
||||
---
|
||||
doc_type: ui_page
|
||||
---
|
||||
|
||||
# <title>
|
||||
|
||||
## Summary
|
||||
Правила оформления: `../common-elements/summary.md`
|
||||
|
||||
## Details
|
||||
Правила оформления: `../common-elements/details.md`
|
||||
|
||||
### Требования к UI
|
||||
Правила оформления: `../common-elements/ui-requirements.md`
|
||||
""".strip()
|
||||
|
||||
spec = parser.parse("templates/ui_page.template.md", template)
|
||||
|
||||
assert spec.doc_type == "ui_page"
|
||||
assert spec.title_level == 1
|
||||
assert [(item.level, item.title, item.rule_path) for item in spec.sections] == [
|
||||
(2, "Summary", "common-elements/summary.md"),
|
||||
(2, "Details", "common-elements/details.md"),
|
||||
(3, "Требования к UI", "common-elements/ui-requirements.md"),
|
||||
]
|
||||
assert spec.sections[1].has_children is True
|
||||
|
||||
|
||||
def test_requirement_source_sections_match_template_titles() -> None:
|
||||
locator = RequirementSourceSections()
|
||||
body = """
|
||||
### Технический use case (тезисно)
|
||||
1. Открыть экран.
|
||||
|
||||
### Контракт метода
|
||||
| Поле | Тип |
|
||||
|
||||
### Нефункциональные требования
|
||||
- Метрики.
|
||||
""".strip()
|
||||
|
||||
sections = locator.extract(body)
|
||||
|
||||
assert "открыть экран" not in sections
|
||||
assert locator.find_for_title(sections, "Технический use case") == "1. Открыть экран."
|
||||
assert "| Поле | Тип |" in locator.find_for_title(sections, "Контракт")
|
||||
Reference in New Issue
Block a user