From 97b7833a1be8e3c5bf98649a622c9b09b33d4ad3 Mon Sep 17 00:00:00 2001 From: kyeongmin Date: Wed, 27 May 2026 18:18:53 +0900 Subject: [PATCH] docs(#95): IMP-95 u11 status-board markers + idempotence/regex tests (docs+test only) - Add section 9 to PHASE-Z-PIPELINE-STATUS-BOARD.md carving section 3 item (j) into 8 IMP-95 sub-axes (j1-j8). j1-j5 = trace-only, j6-j8 = guarded. - Marker grammar: VALUE (distinct from IMP-91 grammar so scripts/update_status_board.py MARKER_RE cannot rewrite IMP-95 cells). - Allowed value enum: {pending, trace-only, guarded, active}. - tests/scripts/test_update_status_board.py: +1 import, +4 module-level constants, +3 test functions verifying marker presence/count (8), value domain enum, IMP-91 updater isolation against IMP-95 cells, and IMP-95 regex rewrite idempotence. IMP-91 tests untouched. - No production-code touched. Default-OFF flag posture preserved; all cells trace-only or guarded. --- .../PHASE-Z-PIPELINE-STATUS-BOARD.md | 24 +++++++++ tests/scripts/test_update_status_board.py | 50 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md b/docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md index cca41d5..da6a8b9 100644 --- a/docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md +++ b/docs/architecture/PHASE-Z-PIPELINE-STATUS-BOARD.md @@ -203,6 +203,30 @@ Invocation: `python -m scripts.measure_reuse_savings samples/mdx_batch/02.mdx -- --- +## 9. IMP-95 (V4 evidence → B4 `_select_frame` integration) sub-axis markers + +> Sub-axis carve-out of section 3 item (j) for IMP-95. Pair-comment markers +> `VALUE`. Closing tag `` +> is intentionally distinct from IMP-91's `` so the IMP-91 +> updater (`scripts/update_status_board.py`) cannot rewrite IMP-95 cells. +> Allowed values: `pending` (not implemented), `trace-only` (default-OFF flag +> `PHASE_Z_B4_V4_EVIDENCE`, additive telemetry only — no render-path change), +> `guarded` (default-OFF regression harness landed and runs locally), `active` +> (default-ON — not the current IMP-95 target). + +| sub-axis | status | +|---|---| +| j1 V4-aware selector under `accepted_content_types ⊇` (u2) | trace-only | +| j2 `plan_placement` v4_candidates kwarg + selection_trace (u3) | trace-only | +| j3 Step 11 `placement_trace` hoist (u4) | trace-only | +| j4 Gatekeeper `v4_short_circuit` telemetry (u5) | trace-only | +| j5 `partial_exists` precheck (u6) | trace-only | +| j6 Flag-OFF SHA parity regression on mdx 01/02/04/05 (u8) | guarded | +| j7 Flag-ON adapter_needed monotone regression (u9) | guarded | +| j8 Flag-ON `placement_trace` field presence regression (u10) | guarded | + +--- + ## 사용 방법 - 새 작업 들어오면 → 본 board 의 *어느 step* 의 status 를 바꾸는 작업인지 식별 diff --git a/tests/scripts/test_update_status_board.py b/tests/scripts/test_update_status_board.py index f26cd3b..f379536 100644 --- a/tests/scripts/test_update_status_board.py +++ b/tests/scripts/test_update_status_board.py @@ -6,6 +6,7 @@ into the GitHub Actions workflow; these tests guard the contract. """ from __future__ import annotations +import re import sys from pathlib import Path @@ -14,6 +15,15 @@ sys.path.insert(0, str(REPO_ROOT / "scripts")) import update_status_board as usb # noqa: E402 +IMP95_BOARD_PATH = ( + REPO_ROOT / "docs" / "architecture" / "PHASE-Z-PIPELINE-STATUS-BOARD.md" +) +IMP95_MARKER_RE = re.compile( + r"()(.*?)()", re.DOTALL +) +IMP95_EXPECTED_AXES = {"j1", "j2", "j3", "j4", "j5", "j6", "j7", "j8"} +IMP95_ALLOWED_VALUES = {"pending", "trace-only", "guarded", "active"} + SAMPLE_REPORT = { "tests": [ @@ -60,3 +70,43 @@ def test_update_board_text_is_idempotent() -> None: once = usb.update_board_text(board, outcomes) twice = usb.update_board_text(once, outcomes) assert once == twice == "PASS" + + +def test_imp95_markers_present_and_well_formed() -> None: + """IMP-95 sub-axis markers all present in section 9 with allowed values.""" + board = IMP95_BOARD_PATH.read_text(encoding="utf-8") + matches = IMP95_MARKER_RE.findall(board) + axes = {axis for _, axis, _, _ in matches} + assert axes == IMP95_EXPECTED_AXES, ( + f"IMP-95 axes drift: expected {IMP95_EXPECTED_AXES}, got {axes}" + ) + for _, axis, value, _ in matches: + assert value in IMP95_ALLOWED_VALUES, ( + f"IMP-95 {axis} value {value!r} outside allowed set {IMP95_ALLOWED_VALUES}" + ) + + +def test_imp95_markers_isolated_from_imp91_updater() -> None: + """`update_board_text` (IMP-91) MUST NOT rewrite IMP-95 markers — distinct closing tag.""" + sample = ( + "trace-only " + "?" + ) + outcomes = {("F0", "01"): "PASS"} + rewritten = usb.update_board_text(sample, outcomes) + assert "trace-only" in rewritten + assert "PASS" in rewritten + + +def test_imp95_marker_rewrite_is_idempotent() -> None: + """Regex-driven IMP-95 cell rewrite is byte-identical on second application.""" + board = "pending" + + def rewrite(text: str, value: str) -> str: + return IMP95_MARKER_RE.sub( + lambda m: f"{m.group(1)}{value}{m.group(4)}", text + ) + + once = rewrite(board, "trace-only") + twice = rewrite(once, "trace-only") + assert once == twice == "trace-only"