docs(ORCH-078): ORCH-52e — стандарт трассировки ORCH-NNN + правило чтения ADR
Слой 4 (трассировка) эпика ORCH-52, замыкающий цепочку 52b/52c/52d. Docs + prompts-only: src/**, STAGE_TRANSITIONS, QG_CHECKS, src/frontmatter.py, схема БД — не тронуты; новый QG не вводится; ретро-фит 51 маркера вне объёма. - Новый нормативный стандарт docs/_standards/TRACEABILITY.md: формат маркера, правило размещения, чтение истории с реальным проверяемым примером (src/serial_gate.py → ORCH-088 → ADR-001-serial-gate.md), fallback-доступ (git show origin/main:...), анти-археология (3+ → сводный сквозной ADR), каноничный текст правила чтения (единый источник). - Точечные аддитивные врезки в промпты (52d-канон не переписан): developer.md (правило чтения чужого маркера + fallback, «❌ X → ✅ Y»), architect.md (правило чтения + анти-археология), reviewer.md (усиление оси «Соответствие ADR» под-пунктом: слом маркированного инварианта → finding ≥P1). Все три ссылаются на единый текст в TRACEABILITY.md, не копируют (анти-дубль BR-6). - Сопутствующе: CLAUDE.md, docs/architecture/README.md (слой 4 эпика 52), CHANGELOG.md. - Анти-регресс: расширен tests/test_agent_prompts_canon.py (9 новых проверок); проверки 52d и test_agent_frontmatter_no_model.py зелёные; полный pytest tests/ -q зелёный (1253 passed), src/ не изменён. Refs: ORCH-078 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -17,10 +17,11 @@ import pytest
|
||||
_AGENTS = ("analyst", "architect", "developer", "reviewer", "tester", "deployer")
|
||||
|
||||
# tests/ is one level under the repo root; .openclaw/agents lives at the root.
|
||||
_AGENTS_DIR = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
".openclaw", "agents",
|
||||
)
|
||||
_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
_AGENTS_DIR = os.path.join(_REPO_ROOT, ".openclaw", "agents")
|
||||
|
||||
# ORCH-078 (ORCH-52e): the traceability-marker standard (layer 4 of epic ORCH-52).
|
||||
_TRACEABILITY = os.path.join(_REPO_ROOT, "docs", "_standards", "TRACEABILITY.md")
|
||||
|
||||
# The 5 mandatory XML sections, in normative order (D1 / AC-1).
|
||||
_REQUIRED_SECTIONS = ("context", "task", "deliverables", "constraints", "output_format")
|
||||
@@ -94,6 +95,11 @@ def _read(agent: str) -> str:
|
||||
return f.read()
|
||||
|
||||
|
||||
def _read_repo(*parts: str) -> str:
|
||||
with open(os.path.join(_REPO_ROOT, *parts), encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("agent", _AGENTS)
|
||||
def test_five_xml_sections_present(agent):
|
||||
"""TC-01: each prompt carries all 5 XML sections (open + close tag)."""
|
||||
@@ -163,3 +169,92 @@ def test_role_anti_regress_markers(agent):
|
||||
text = _read(agent)
|
||||
for marker in _ANTI_REGRESS[agent]:
|
||||
assert marker in text, f"{agent}.md lost anti-regress marker {marker!r}"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ORCH-078 (ORCH-52e): traceability-marker standard + reading-rule anti-regress
|
||||
# (TRZ §FR-1..FR-8; AC-1..AC-5, AC-8). Pure-text checks, NO `src/` import.
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
def test_traceability_standard_exists_and_nonempty():
|
||||
"""TC-01 (AC-1): docs/_standards/TRACEABILITY.md exists and is non-empty."""
|
||||
assert os.path.isfile(_TRACEABILITY), "docs/_standards/TRACEABILITY.md is missing"
|
||||
assert _read_repo("docs", "_standards", "TRACEABILITY.md").strip(), (
|
||||
"TRACEABILITY.md is empty"
|
||||
)
|
||||
|
||||
|
||||
def test_traceability_describes_marker_format_and_placement():
|
||||
"""TC-02 (AC-1): standard describes the ORCH-NNN marker and where it is placed."""
|
||||
text = _read_repo("docs", "_standards", "TRACEABILITY.md")
|
||||
assert "ORCH-NNN" in text, "TRACEABILITY.md does not describe the ORCH-NNN marker"
|
||||
# placement rule: next to a non-trivial invariant (not on trivial code).
|
||||
assert "инвариант" in text, "TRACEABILITY.md does not state the placement rule"
|
||||
|
||||
|
||||
def test_traceability_has_real_verifiable_example():
|
||||
"""TC-03 (AC-1): the worked example points at files that really exist in main.
|
||||
|
||||
A traceability standard whose example references a missing file/ADR would
|
||||
refute itself, so the example must be checkable against the repo tree.
|
||||
"""
|
||||
text = _read_repo("docs", "_standards", "TRACEABILITY.md")
|
||||
assert "src/serial_gate.py" in text and "ORCH-088" in text, (
|
||||
"TRACEABILITY.md lacks the serial_gate/ORCH-088 worked example"
|
||||
)
|
||||
assert os.path.isfile(os.path.join(_REPO_ROOT, "src", "serial_gate.py")), (
|
||||
"example references src/serial_gate.py which does not exist"
|
||||
)
|
||||
assert os.path.isfile(os.path.join(
|
||||
_REPO_ROOT, "docs", "work-items", "ORCH-088", "06-adr",
|
||||
"ADR-001-serial-gate.md",
|
||||
)), "example references an ORCH-088 ADR that does not exist"
|
||||
|
||||
|
||||
def test_traceability_documents_fallback_access():
|
||||
"""TC-04 (AC-4): standard documents the git show origin/main fallback."""
|
||||
text = _read_repo("docs", "_standards", "TRACEABILITY.md")
|
||||
assert "git show origin/main:docs/work-items/" in text, (
|
||||
"TRACEABILITY.md does not document the cross-branch ADR fallback"
|
||||
)
|
||||
|
||||
|
||||
def test_traceability_documents_anti_archeology():
|
||||
"""TC-05 (AC-5): standard documents the 3+ markers -> cross-cutting ADR rule."""
|
||||
text = _read_repo("docs", "_standards", "TRACEABILITY.md")
|
||||
assert "docs/architecture/adr/" in text, (
|
||||
"TRACEABILITY.md anti-archeology rule does not point at the cross-cutting ADR dir"
|
||||
)
|
||||
assert "3+" in text, "TRACEABILITY.md does not state the 3+ markers threshold"
|
||||
|
||||
|
||||
def test_developer_carries_reading_rule_and_fallback():
|
||||
"""TC-06 (AC-2, AC-4): developer.md carries the reading rule + standard + fallback."""
|
||||
text = _read("developer")
|
||||
assert "TRACEABILITY.md" in text, "developer.md does not reference TRACEABILITY.md"
|
||||
assert "git show origin/main:docs/work-items/" in text, (
|
||||
"developer.md does not carry the cross-branch ADR fallback"
|
||||
)
|
||||
|
||||
|
||||
def test_architect_carries_reading_rule_and_anti_archeology():
|
||||
"""TC-07 (AC-2, AC-5): architect.md carries reading rule + anti-archeology."""
|
||||
text = _read("architect")
|
||||
assert "TRACEABILITY.md" in text, "architect.md does not reference TRACEABILITY.md"
|
||||
assert "3+" in text, "architect.md does not carry the 3+ markers anti-archeology rule"
|
||||
|
||||
|
||||
def test_reviewer_carries_traceability_control_axis():
|
||||
"""TC-08 (AC-3): reviewer.md carries the traceability-compliance control axis."""
|
||||
text = _read("reviewer")
|
||||
assert "TRACEABILITY.md" in text, "reviewer.md does not reference TRACEABILITY.md"
|
||||
|
||||
|
||||
def test_claude_md_and_readme_reference_traceability_standard():
|
||||
"""TC-12 (AC-8): CLAUDE.md and architecture README reference the standard."""
|
||||
assert "TRACEABILITY.md" in _read_repo("CLAUDE.md"), (
|
||||
"CLAUDE.md does not reference docs/_standards/TRACEABILITY.md"
|
||||
)
|
||||
assert "TRACEABILITY.md" in _read_repo("docs", "architecture", "README.md"), (
|
||||
"architecture README does not reference docs/_standards/TRACEABILITY.md"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user