Files
orchestrator/tests/test_readme_limitations.py
claude-bot d97b26a59f docs(ORCH-079): ORCH-52f — sync README with code + reviewer overview-docs axis
Layer 5 (final) of epic ORCH-52. Docs + prompt-only; src/ untouched.

- README.md «Известные ограничения»: fix numbering (was 1,2,3,4,3,4),
  move 6 resolved/obsolete items to «Закрыто (история)» trail with ORCH
  refs, keep only really-open limitations (Telegram-48h ORCH-087,
  task-deps intra-repo ORCH-026, serial-gate ORCH-088). Point-sync stage
  table (development → check_ci_green) and event-routing (ORCH-045).
- reviewer.md: overview-docs axis (axis 4 + constraints) — closing a
  README limitation without updating README → finding ≥P1 (canon 52d
  «»; verdict key + 5 XML sections + 6 schema fields byte-intact).
- tests: new tests/test_readme_limitations.py (numbering + no resolved
  items as open); test_agent_prompts_canon.py asserts the new axis.
- CLAUDE.md / CHANGELOG.md updated; epic ORCH-52 closed (52b→…→52f).

Refs: ORCH-079

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 16:33:33 +03:00

89 lines
3.6 KiB
Python

"""ORCH-079 (ORCH-52f): structural anti-drift for README "Известные ограничения".
Layer 5 (final) of epic ORCH-52: the root README overview showcase must not lie
about the project state. These are pure-text structural checks (NO `src/` import,
NO agent runs) guarding two invariants (TRZ §FR-1/FR-2, AC-1/AC-2):
* the OPEN limitations list is numbered strictly 1, 2, 3, … without repeats
(the historical bug was `1,2,3,4,3,4`);
* resolved/obsolete items (single-task worktree, in-process daemon, "Gitea CI
not configured", "no retry") are NOT listed as OPEN limitations — if mentioned
at all, only under the "Закрыто (история)" trail.
Covers test-plan TC-05.
"""
import os
import re
_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
_README = os.path.join(_REPO_ROOT, "README.md")
# Heading of the limitations section and the closed-history subsection that ends
# the OPEN portion.
_SECTION_HEAD = "## Известные ограничения"
_CLOSED_HEAD = "Закрыто (история)"
# Phrases that mark a RESOLVED/obsolete item. They must not appear in the OPEN
# portion of the section (only allowed under "Закрыто (история)").
_RESOLVED_MARKERS = (
"Single-task",
"shared `/repos`",
"daemon-потоки",
"не настроен", # "Gitea CI не настроен"
"No retry",
)
def _read_readme() -> str:
with open(_README, encoding="utf-8") as f:
return f.read()
def _limitations_section() -> str:
"""Text of the '## Известные ограничения' section up to the next '## ' heading."""
text = _read_readme()
idx = text.find(_SECTION_HEAD)
assert idx != -1, "README.md has no '## Известные ограничения' section"
rest = text[idx + len(_SECTION_HEAD):]
# Stop at the next top-level (##) heading, if any.
nxt = re.search(r"\n## ", rest)
return rest[: nxt.start()] if nxt else rest
def _open_portion(section: str) -> str:
"""The OPEN-limitations portion: everything before the 'Закрыто (история)' trail."""
cut = section.find(_CLOSED_HEAD)
return section[:cut] if cut != -1 else section
def test_open_limitations_numbered_sequentially():
"""AC-1: the OPEN limitations list is numbered 1, 2, 3, … with no repeats/gaps."""
open_part = _open_portion(_limitations_section())
# Leading numbered list items: lines like "1. **...".
numbers = [int(m) for m in re.findall(r"^(\d+)\.\s", open_part, flags=re.MULTILINE)]
assert numbers, "no numbered OPEN limitations found in README section"
assert numbers == list(range(1, len(numbers) + 1)), (
f"OPEN limitations numbering is not strictly sequential: {numbers}"
)
def test_resolved_items_not_listed_as_open():
"""AC-2: resolved/obsolete items are not present as OPEN limitations."""
open_part = _open_portion(_limitations_section())
leaked = [m for m in _RESOLVED_MARKERS if m in open_part]
assert not leaked, (
f"resolved items leaked into OPEN limitations (must be under 'Закрыто'): {leaked}"
)
def test_closed_history_trail_present_with_orch_refs():
"""AC-2: the 'Закрыто (история)' trail exists and carries ORCH references."""
section = _limitations_section()
assert _CLOSED_HEAD in section, (
"README limitations section lacks the 'Закрыто (история)' trail"
)
closed = section[section.find(_CLOSED_HEAD):]
assert re.search(r"ORCH-\d+", closed), (
"the 'Закрыто (история)' trail has no ORCH-NNN references"
)