wip: phase_z2 evidence 파이프라인 + matching 실험(phase2~26) + 프론트 trace 패널 진행분 스냅샷
- src: phase_z2 composition/mapper/pipeline/placement_planner/retry, ai_fallback(prompts/schema/validate), mdx_text_atoms 신규 - Front: PipelineTracePanel 신규, FramePanel/SlideCanvas/Home/designAgentApi 등 갱신 + 테스트 4종 추가 - templates/phase_z2: catalog(component_expansion_registry, node_slot_mapping 신규), frames, families, slide_base 갱신 - tests/matching: phase2~26 매칭 실험 스크립트·리포트·온톨로지 전체 (미커밋 진행분) - tests: b4_v4 evidence, task5~28.5 시리즈, regression(imp95 baseline) 등 신규 테스트 대량 추가 - docs/reference: MDX 구조 인벤토리, MDX→Frame 구조 계약 문서 - scripts: mdx 계약/parity/coverage/viewport 체크, gitea comment, run sync 유틸 - .gitignore: tmp*.json, chromedriver, .orchestrator, *.pkl, Front_test* 등 임시/스냅샷 제외 미완성 작업의 보존용 스냅샷 커밋 (2026-07-02) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
"""IMP-95 u8 — capture final.html SHA baseline via the FULL Phase Z pipeline
|
||||
under PHASE_Z_B4_V4_EVIDENCE=OFF (default) for mdx 01/02/04/05.
|
||||
|
||||
Runs ``src.phase_z2_pipeline.run_phase_z2_mvp1`` end-to-end for each mdx file
|
||||
in the Stage 2 u8 scope (01/02/04/05; mdx 03 is excluded per the ``mdx 03
|
||||
정비`` lock). Each run writes a real ``final.html`` to disk at the production
|
||||
write site ``src/phase_z2_pipeline.py:5994-5996``; bytes are IMP-94-normalized
|
||||
and SHA-256 hashed, then frozen to
|
||||
``tests/regression/fixtures/imp95_pre_baseline_sha.json``.
|
||||
|
||||
The accompanying regression test
|
||||
``tests/regression/test_b4_v4_evidence_off_sha_parity.py`` re-runs the same
|
||||
pipeline shape under flag OFF and asserts SHA equality with the frozen
|
||||
values. Under flag OFF, IMP-95 (u1~u7) is a strict no-op for ``final.html``
|
||||
bytes — see the trace-only docstring at ``src/phase_z2_pipeline.py:86`` —
|
||||
so the captured baseline IS the immediate pre-IMP-95 reference even when
|
||||
captured with IMP-95 code already in tree.
|
||||
|
||||
Reason for a separate baseline (vs. reusing 89a_pre_baseline_sha.json)
|
||||
======================================================================
|
||||
|
||||
The 89a baseline was captured at HEAD ``6e9e3ee`` before subsequent
|
||||
working-tree changes accumulated (e.g. the Emergency P3/P4/P4b verbatim
|
||||
slot_payload builders), so the 89a SHAs no longer match the current
|
||||
flag-OFF pipeline output for mdx 02/04/05 — a pre-existing baseline
|
||||
drift orthogonal to IMP-95. A fresh baseline keyed to the current
|
||||
flag-OFF state isolates IMP-95's u8 regression axis from that upstream
|
||||
drift; the 89a baseline remains the load-bearing guard for the 89-a
|
||||
axis.
|
||||
|
||||
IMP-94 marker normalization
|
||||
===========================
|
||||
|
||||
IMP-94 ``data-region-id`` / ``data-content-unit-id`` tokens (stamped at
|
||||
``src/region_marker_stamper.py:131-135``) are stripped before hashing.
|
||||
The strip is anchored on ``leading space + attr token`` shape and is
|
||||
disjoint from the IMP-96 ``data-frame-slot-id`` axis by attribute name.
|
||||
|
||||
Run from repo root::
|
||||
|
||||
python tests/regression/scripts/capture_imp95_pre_baseline.py
|
||||
|
||||
Idempotent. Re-run only when an upstream mapper/render/template delta is
|
||||
reviewed and accepted as the new pre-IMP-95 reference. Refuses to run
|
||||
with PHASE_Z_B4_V4_EVIDENCE enabled (the flag-ON state is not the
|
||||
baseline axis).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
_REPO_ROOT = Path(__file__).resolve().parents[3]
|
||||
sys.path.insert(0, str(_REPO_ROOT))
|
||||
sys.path.insert(0, str(_REPO_ROOT / "src"))
|
||||
|
||||
import src.phase_z2_pipeline as pz2 # noqa: E402
|
||||
|
||||
_SAMPLES_DIR = _REPO_ROOT / "samples" / "mdx_batch"
|
||||
_MDX_BATCH = ("01.mdx", "02.mdx", "04.mdx", "05.mdx") # Stage 2 u8 scope
|
||||
_OUT_PATH = (
|
||||
_REPO_ROOT
|
||||
/ "tests"
|
||||
/ "regression"
|
||||
/ "fixtures"
|
||||
/ "imp95_pre_baseline_sha.json"
|
||||
)
|
||||
|
||||
# IMP-94 additive marker strip patterns — must stay in sync with
|
||||
# tests/regression/test_b4_v4_evidence_off_sha_parity.py.
|
||||
_STRIP_REGION_ID_RE = re.compile(rb' data-region-id="[^"]*"')
|
||||
_STRIP_CONTENT_UNIT_ID_RE = re.compile(rb' data-content-unit-id="[^"]*"')
|
||||
|
||||
|
||||
def _strip_imp94_markers(raw_bytes: bytes) -> bytes:
|
||||
stripped = _STRIP_REGION_ID_RE.sub(b"", raw_bytes)
|
||||
stripped = _STRIP_CONTENT_UNIT_ID_RE.sub(b"", stripped)
|
||||
return stripped
|
||||
|
||||
|
||||
def _capture_one(mdx_file: str, runs_root: Path) -> dict:
|
||||
mdx_path = _SAMPLES_DIR / mdx_file
|
||||
assert mdx_path.exists(), f"sample missing: {mdx_path}"
|
||||
|
||||
run_id = f"imp95_baseline_{mdx_path.stem}"
|
||||
pipeline_exit_code: int | None = None
|
||||
try:
|
||||
pz2.run_phase_z2_mvp1(mdx_path, run_id=run_id)
|
||||
except SystemExit as exc:
|
||||
pipeline_exit_code = (
|
||||
int(exc.code) if isinstance(exc.code, int) else 1
|
||||
)
|
||||
|
||||
final_html_path = runs_root / run_id / "phase_z2" / "final.html"
|
||||
assert final_html_path.exists(), (
|
||||
f"final.html not written by pipeline: {final_html_path} "
|
||||
f"(pipeline_exit_code={pipeline_exit_code})"
|
||||
)
|
||||
raw_bytes = final_html_path.read_bytes()
|
||||
assert len(raw_bytes) > 0, f"final.html is empty: {final_html_path}"
|
||||
normalized_bytes = _strip_imp94_markers(raw_bytes)
|
||||
|
||||
return {
|
||||
"mdx_file": mdx_file,
|
||||
"run_id": run_id,
|
||||
"final_html_size_bytes": len(normalized_bytes),
|
||||
"sha256": hashlib.sha256(normalized_bytes).hexdigest(),
|
||||
"pipeline_exit_code": pipeline_exit_code,
|
||||
}
|
||||
|
||||
|
||||
def capture() -> dict:
|
||||
assert os.environ.get("PHASE_Z_B4_V4_EVIDENCE", "") == "", (
|
||||
"PHASE_Z_B4_V4_EVIDENCE must be unset when capturing baseline "
|
||||
"(default-OFF state is the production-equivalent axis for u8). "
|
||||
"Refusing to run with the flag enabled."
|
||||
)
|
||||
assert os.environ.get("PHASE_Z_B4_MAPPER_SOURCE", "") == "", (
|
||||
"PHASE_Z_B4_MAPPER_SOURCE must also be unset — the u8 baseline "
|
||||
"is captured under both flags OFF (full pre-IMP-89/95 path)."
|
||||
)
|
||||
|
||||
_OUT_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="imp95_baseline_") as tmp:
|
||||
runs_root = Path(tmp)
|
||||
original_runs_dir = pz2.RUNS_DIR
|
||||
pz2.RUNS_DIR = runs_root
|
||||
try:
|
||||
entries = [_capture_one(mf, runs_root) for mf in _MDX_BATCH]
|
||||
finally:
|
||||
pz2.RUNS_DIR = original_runs_dir
|
||||
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"axis": (
|
||||
"IMP-95 u8 — final.html SHA baseline captured via FULL "
|
||||
"run_phase_z2_mvp1 pipeline under PHASE_Z_B4_V4_EVIDENCE=OFF "
|
||||
"and PHASE_Z_B4_MAPPER_SOURCE=OFF (defaults)"
|
||||
),
|
||||
"description": (
|
||||
"Frozen SHA-256 of `final.html` bytes (production write site "
|
||||
"src/phase_z2_pipeline.py:5994-5996) for mdx 01/02/04/05 "
|
||||
"under PHASE_Z_B4_V4_EVIDENCE OFF. Under flag OFF, IMP-95 "
|
||||
"(u1~u7) is strictly no-op for final.html (planner branch "
|
||||
"falls through to legacy _select_frame at u3; u4/u5/u6 "
|
||||
"additive telemetry confined to placement_trace per the "
|
||||
"trace-only docstring at src/phase_z2_pipeline.py:86). The "
|
||||
"u8 regression test asserts SHA equality with these frozen "
|
||||
"values, so any future code change that drifts the flag-OFF "
|
||||
"render output produces a mismatch and breaks the test. "
|
||||
"mdx 03 is excluded per Stage 2 u8 scope (mdx 03 정비 LOCK). "
|
||||
"Regenerate only when an upstream delta is reviewed and "
|
||||
"accepted as the new pre-IMP-95 reference."
|
||||
),
|
||||
"captured_at_utc": (
|
||||
datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
),
|
||||
"renderer": {
|
||||
"entrypoint": "src.phase_z2_pipeline.run_phase_z2_mvp1",
|
||||
"write_site": "src/phase_z2_pipeline.py:5994-5996",
|
||||
"artifact_relpath": "<RUNS_DIR>/<run_id>/phase_z2/final.html",
|
||||
},
|
||||
"mdx_batch": list(_MDX_BATCH),
|
||||
"mdx_files": {entry["mdx_file"]: entry for entry in entries},
|
||||
"total_files": len(entries),
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
data = capture()
|
||||
_OUT_PATH.write_text(
|
||||
json.dumps(data, indent=2, ensure_ascii=False) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(
|
||||
f"wrote {_OUT_PATH} ({data['total_files']} files: "
|
||||
f"{', '.join(data['mdx_files'].keys())})"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user