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>
This commit is contained in:
@@ -258,3 +258,24 @@ def test_claude_md_and_readme_reference_traceability_standard():
|
||||
assert "TRACEABILITY.md" in _read_repo("docs", "architecture", "README.md"), (
|
||||
"architecture README does not reference docs/_standards/TRACEABILITY.md"
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ORCH-079 (ORCH-52f): reviewer overview-docs axis (layer 5 of epic ORCH-52).
|
||||
# Pure-text anti-drift check (TRZ §FR-6 / AC-5), NO `src/` import.
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
def test_reviewer_carries_overview_docs_axis():
|
||||
"""ORCH-079 TC-01 (AC-5): reviewer.md covers the README overview-docs axis.
|
||||
|
||||
The reviewer must require README ("Известные ограничения") to be updated when
|
||||
a PR closes a documented limitation. This guards the rule against silent drift
|
||||
in a future prompt refactor, exactly like the traceability control axis.
|
||||
"""
|
||||
text = _read("reviewer")
|
||||
assert "Известные ограничения" in text, (
|
||||
"reviewer.md does not mention the README 'Известные ограничения' overview-docs axis"
|
||||
)
|
||||
assert "ORCH-079" in text, (
|
||||
"reviewer.md does not anchor the overview-docs axis to ORCH-079"
|
||||
)
|
||||
|
||||
88
tests/test_readme_limitations.py
Normal file
88
tests/test_readme_limitations.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""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"
|
||||
)
|
||||
Reference in New Issue
Block a user