INTEGRATION-AUDIT-01 (#50) §10.4 / §10.5 housekeeping carry-over. F-4: annotate 14 remaining legacy Phase R'/Q sample-text hits across 10 src/ files with inline marker `# [legacy Phase R'/Q example -- INTEGRATION-AUDIT-01 §10.4]`. Comment-only. No string-literal / regex / sample dict value mutated. fit_verifier.py L612 marker keeps Phase Z partial-live import graph (FitAnalysis / RoleFit / redistribute / salvage) byte-precise. F-5: docs-only addendum -- §10.5.1 in INTEGRATION-AUDIT-01-REPORT.md + tests/CLAUDE.md fixture convention note. No root tests/fixtures/ dir created; existing tests/phase_z2/fixtures/ convention preserved. Documents test-only sample-reference allowance vs src/** runtime prohibition. Out of scope: Phase Z source 11 hits (phase_z2_content_extractor / failure_router / mapper / retry), production behavior change, #19 work. Verified: pytest -q tests/phase_z2/ = 157 PASS. git diff +210/-0 (35 src/docs lines + 175 new tests/CLAUDE.md). No behavioral delta. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 KiB
INTEGRATION-AUDIT-01 -- Phase Z closed-issue cumulative consistency review
Section 1. Audit anchor
Anchor (cited verbatim per Stage 1 exit report) :
This audit verifies pipeline contracts. It does not optimize any single MDX sample.
Scope : 22 closed Gitea issues #2-#18 + #45-#49 on Kyeongmin/C.E.L_Slide_test2 against the 22-step Phase Z pipeline (docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md, Steps 1-22 plus Step 0 precondition).
Mode : audit-only -- no source code changes. Report-only file changes under docs/architecture/INTEGRATION-AUDIT-*.md and one row in docs/architecture/PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md (u7).
Parent / child relationship : Gitea #15 = parent (IMP-15 Step 14 visual_check reinforcement). Execution children = #45 / #46 / #47 / #48 / #49. Locked child SHAs (Stage 1 exit report) :
#45->e9b3d2e(execution-1, image_aspect_mismatch detection)#46->2827622(execution-2, table_self_overflow detection; commit message label saysIMP-16but the closed Gitea issue is#46; flagged in Section 3)#47->535c484(execution-3, classifier consumes image+table events)#48->614c533(execution-4, debug.json event surfacing + spec taxonomy)#49-> no new SHA (verification-only per#15body; re-uses614c533evidence)
Close timestamp anomaly (Stage 1 lock, recorded; NOT reopened) :
#15closed2026-05-19T02:35:05+09:00#45 / #46 / #47 / #48all closed BEFORE#15(correct ordering)#49closed2026-05-19T02:49:56+09:00-- about 15 minutes AFTER#15close (anomaly)- Disposition : record-only in Section 3 / Section 6 finding column; no remediation row in backlog beyond the existing audit completion row (u7).
Excluded (open / not in audit) : #1, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #38, #39, #40, #41, #42, #43, #44.
Sample budget : samples/mdx_batch/03.mdx (smoke) plus samples/mdx_batch/04.mdx (details + images). Pipeline runs captured in Section 7.
Section 2. Baseline pytest
Method : pytest -q tests is the project regression suite. The audit captures it twice -- once before any u5 / u6 / u7 edits, once after Section 7 / 8 grep + render evidence is collected. Equality of both runs proves the audit-only work surface (docs/architecture/INTEGRATION-AUDIT-*.md + backlog row in u7) did not perturb production code.
Command : pytest -q tests (working dir = repo root D:\ad-hoc\kei\design_agent\).
Pytest BEFORE audit u5 edits (audit date 2026-05-19) :
- Result :
303 passed in 40.80s - Last 5 progress dots aggregated to
[100%]thenRunning teardown with pytest sessionfinish...-- expected suite teardown banner.
Pytest AFTER audit u5 edits (post §7 / §8 evidence collection, same audit date) :
- Result :
303 passed in 40.54s - 303 == 303 ; 0 new failures, 0 skipped, 0 errored. Test count parity proves no test discovery side-effect from new audit docs.
Verdict : OK. Audit-only edits under docs/architecture/INTEGRATION-AUDIT-*.md introduce no regression. Baseline stable across u5 assembly.
Section 3. Axis 1 -- Scope myopia (22 issues x adjacent-contract cross-reference)
Method : per closed issue, list (a) its own scope as declared in body / backlog row / closing commits, (b) adjacent pipeline contracts the change could have leaked into, (c) downstream consumers of its outputs, (d) finding label OK / Warning / Blocker. Each row cites src/, tests/, docs/, or templates/ paths.
De-dup convention : #15 is treated as the integration parent; the actual code/test changes are owned by execution children #45-#49. #15 row records integration glue only (parent close evidence + cross-child reconciliation). No change is double-counted across parent + child.
Pipeline step shorthand (per PHASE-Z-PIPELINE-OVERVIEW.md, full 22-step list) :
- Step 0 precondition / 1 MDX upload / 2 normalize / 3 content_object / 4 internal composition planning / 5 V4 evidence / 6 composition planning / 7 layout vocabulary / 8 zone+region ratio / 9 region-level frame/display / 10 frame contract / 11 region-to-slot mapping / 12 slot payload / 13 render / 14 visual_check / 15 fit_classification / 16 router / 17 action / 18 failure_classify / 19 next_action / 20 slide_status / 21 debug.json / 22 user UI.
Section 3 table -- 22 rows
| # | issue (title) | declared own_scope | adjacent contracts (potential leak surface) | downstream consumers | finding | evidence path |
|---|---|---|---|---|---|---|
| 1 | #2 IMP-02 A-1 Stage 0 normalize chained adapter |
Step 2 -- chained normalize_mdx_content + extract_major_sections + extract_conclusion_text with dual-write, preserve raw MDX |
Step 3 content_object input shape (raw chunk handoff); Step 21 debug.json schema (step02_* keys) |
Step 3 (IMP-03 ContentObject extractor); Step 21 trace writer; Step 7/8 layout planner (consumes normalized section list) | OK -- additive; preserves prior extract_* semantics via dual-write; no AI in path |
src/phase_z2_pipeline.py (commit bac13c0, +165/-3) |
| 2 | #3 IMP-03 A-1 popup/image/table trace |
Step 3 -- normalize popups/images/tables into ContentObject (B1 v0 extension); slide-level rich ContentObject trace | Step 2 normalize output shape (consumer); Step 4 internal composition planning (Step 4 itself still not implemented, so this row only emits trace); Step 21 debug.json schema | Step 4 (not yet implemented; receives data only via trace); Step 21 debug.json (content_objects field) |
OK -- emits trace without coupling to downstream Step 4 (Step 4 still pending); raw content preserved (no AI summarization; satisfies feedback_ai_isolation_contract) |
src/phase_z2_content_extractor.py + src/phase_z2_pipeline.py (commit fc3f7d8) |
| 3 | #4 IMP-04 A-2 catalog expansion |
Step 0 + Step 9 -- register/expand 16 frame_partials + frame_contracts.yaml schema; F17 paired_rows_4x2 + pill alternation + theme |
Step 5 V4 evidence (catalog size affects evidence pool); Step 10 frame contract validator (consumes new contracts); Step 12 mapper PAYLOAD_BUILDERS (consumes new schema); Step 13 render template surface (16 new templates/phase_z2/families/*.html) |
Step 5/9/10/12/13; smoke tests scripts/smoke_frame_render.py |
OK -- pre-render planning only; catalog is read-only data for V4; frame DB extension matches Step 0 contract; commit 73a98b8 corrected F17 schema after first land (factual_verification path active) |
templates/phase_z2/catalog/frame_contracts.yaml; templates/phase_z2/families/*.html; src/phase_z2_mapper.py; docs/architecture/IMP-04-FRAME-SUITABILITY-MATRIX.md |
| 4 | #5 IMP-05 A-5 V4 fallback |
Step 9 + Step 16/17 -- deterministic V4 candidate bridge (pre-render rank-2/3 fallback); trace schema; dedup invariant test; new PASS_WITH_FALLBACK status semantics in Step 20 |
Step 5 evidence (candidate dedup must agree with rank-1 path); Step 6 composition (candidates[0] backward-compat); Step 9 application_plan; Step 20 status enum; debug.json trace | Step 9/16/17/20; tests/test_phase_z2_v4_fallback.py; tests/test_catalog_invariant.py |
OK -- pre-render bridge (Block A); deterministic (no AI); rank-1 path unchanged (backward compat per backlog guardrail); dedup invariant test guards collision with #4 catalog expansion |
src/phase_z2_pipeline.py + src/phase_z2_composition.py + src/phase_z2_router.py (commits 15c5b9a, 21476ae, 23d1b25) |
| 5 | #6 IMP-06 B-1 zone-section override |
Step 6 + Step 1/22 input -- CLI arg + composition planner override (replaced_auto_unit, render_records, plan-aware traces, units rebuild, empty zone) |
Step 1 CLI surface; Step 6 plan_composition schema (CompositionUnit); Step 7/8/9 downstream (units rebuild forces re-planning); Step 13 render (Catch K render-path) |
Step 7/8/9/13; debug.json render_records; Front/ (later wired via #8 U3) |
Warning -- wide blast radius (4 commits + Stage 4 blocker-fix 52ccb7f); units-rebuild touches Step 7/8/9 implicitly; verified by tests/test_phase_z2_section_assignment_override.py (285 + 42 + 228 lines). No AI; deterministic. Risk = override path widens Step 6 surface where Step 4 is still pending |
src/phase_z2_pipeline.py (commits d596fab b81e564 1f15495 52ccb7f) |
| 6 | #7 IMP-07 B-2 edited HTML to MDX reverse path |
Step 22 + Step 1/2 input -- Vite/React Front/ plus reverse path glue; pipeline re-entry |
Step 1 MDX upload; Step 2 normalize (must accept reverse-path MDX); CLI plus service API; feedback_ai_isolation_contract (reverse must not invoke AI rewrite) |
Step 2 (reverse-path consumer); Front/client/src/services/designAgentApi.ts; pipeline CLI |
OK -- frontend-shipped (0f0d3fa); reverse path schema aligned with #2 Stage 0 normalize via hard-link declared in backlog. AI isolation preserved (no normal-path LLM in reverse). |
Front/; src/phase_z2_pipeline.py; backlog row IMP-07 |
| 7 | #8 IMP-08 B-3 sub-section drag-drop |
Step 3 schema -- sub_sections schema + V4 alias resolver + aligner canonical sub-id + decimal alias guard (N-R5) + frontend wire | Step 3 ContentObject schema (extends #3); Step 5 V4 alias surface; Step 6 composition planner (consumer); Step 9 application_plan; Front/ zoneSections override (U3) |
Step 5/6/9/13; tests/test_phase_z2_subsection_schema.py (82+100+61 lines) |
OK -- additive schema with explicit backward-compat guard (alias resolver at 4 lookup sites); Stage 5 R2 blocker-fix 8f6cffc force-drills aligner only on override targets (scope contained) |
src/phase_z2_pipeline.py + src/phase_z2_composition.py (commits a422d72 5191aca ab2764c 8f6cffc) |
| 8 | #9 IMP-09 B-4 non-default layout zone-geometry |
Step 8 -- col-axis solver + per-zone geometry mapper + retry gate; 2-D dynamic dispatch for 5 preset families (single + horizontal-2 + vertical-2 + top-1-bottom-2 + top-2-bottom-1 + left-1-right-2 + left-2-right-1 + grid-2x2) | Step 7 layout vocabulary (consumer); Step 9 region-level (zone geometry feeds region ratios; Step 9 region-level still warning); Step 17 zone_ratio_retry (#12 IMP-12 retry path); Step 13 render build_layout_css |
Step 9/13/17; tests/phase_z2/fixtures/build_layout_css/*.yaml (16 fixtures); tests/phase_z2/fixtures/retry_gate/*.yaml |
OK -- all 8 vocabulary entries enabled in build_layout_css; fixtures supply provable diff per preset; no Kei/Phase R' regression (existing build_containers_type_b untouched) |
src/phase_z2_pipeline.py (commits 201099e PR1, 1fb9732 PR2) |
| 9 | #10 IMP-10 D-1 filtered_section_reasons UI |
Step 20/22 -- frontend read-only display of filtered_section_reasons artifact |
Step 20 slide_status enum (read-only consumer); Front/ service API; no backend mutation |
Front/client/src/pages/Home.tsx; Front/client/src/services/designAgentApi.ts |
OK -- frontend-only; backend artifact strictly read-only per backlog guardrail | Front/ (commit 0fb168b, +45 lines) |
| 10 | #11 IMP-11 D-2 Frame min_height display |
Step 22 -- min_height_px hint exposed backend to UI; resize hint read-only; Step 9 v4 all-judgments min_height test |
Step 0 frame contract (min_height_px field); Step 9 region-level (consumer); Front/ SlideCanvas |
Step 9; Front/client/src/components/SlideCanvas.tsx; tests/test_phase_z2_step9_v4_all_judgments_min_height.py |
OK -- contract read-only; backend exposure is additive payload field (src/phase_z2_pipeline.py +32/-12 in a79bd8b) |
src/phase_z2_pipeline.py + Front/client/src/components/SlideCanvas.tsx; tests/test_phase_z2_step9_v4_all_judgments_min_height.py |
| 11 | #12 IMP-12 Step 16/17 retry refinement |
Step 16 + Step 17 -- multi-donor + 3-stage salvage cascade; redistribute + glue + font compression; new router action; new failure_router taxonomy |
Step 14 visual_check (donor selection consumes overflow events); Step 18 failure_classify (cascade adds new failure types); Step 19 next_action (downstream router consumer); Step 20 status semantics; feedback_phase_z_spacing_direction (cross-zone redistribute is grant-changing, not common-shrink) |
Step 18/19/20; tests/phase_z2/test_phase_z2_* (cross_zone, font_step, glue, multi_donor, step17_salvage_chain -- 5 new test modules) |
Warning -- large blast radius (4 src files + 5 test modules in 56619a0); multi-donor introduces cross-zone state in Step 17; verified by 5 dedicated test modules. Risk = cascade may interact with #5 V4 fallback path in Step 20 status enum (mitigated by separate status enums per #5 exit report) |
src/phase_z2_failure_router.py + src/phase_z2_pipeline.py + src/phase_z2_retry.py + src/phase_z2_router.py (commit 56619a0) |
| 12 | #13 IMP-13 A-3 frame preview consistency |
Step 0 + Step 14/21 -- build-time frame preview generator (salvage of capture_slide_screenshot) |
Step 0 catalog frame_partials (consumer for snapshot); Step 14 visual_check (uses preview for sanity, read-only); no Phase R' regression | scripts/generate_frame_previews.py; tests/test_generate_frame_previews.py |
OK -- build-time only (not in runtime pipeline); deterministic; no Phase R' coupling (script lives in scripts/) |
scripts/generate_frame_previews.py (commit 7d5639a, 239 LOC + 50 LOC test) |
| 13 | #14 IMP-14 A-4 slide-base iframe mode |
Step 13 render -- slide-base.html conditional CSS (embedded vs standalone); Step 0 contract bit |
Step 0 slide_base template; Step 13 Jinja2 deterministic render; Front/ SlideCanvas (consumer) |
Step 13; Front/client/src/components/SlideCanvas.tsx; tests/phase_z2/test_slide_base_embedded_mode.py |
OK -- render-time contract only; Jinja2 deterministic; embedded mode reduces SlideCanvas friction (34 LOC simplified) | templates/phase_z2/slide_base.html + src/phase_z2_pipeline.py (commit 7a52ceb) |
| 14 | #15 IMP-15 Step 14 visual_check reinforcement (PARENT -- execution children #45-#49) |
Integration glue only -- no direct code under #15; closure depends on #45-#49 SHAs. De-duped against children (real change attribution = #45-#49 rows below) |
Step 14 (parent contract); Step 15 fit_classification consumer; Step 21 debug.json trace; PHASE-Z-FIT-CLASSIFIER-ROUTER-SPEC.md (taxonomy row added by #48) |
Step 15/21; spec doc | Warning -- close-timestamp anomaly only : #49 closed at 2026-05-19T02:49:56+09:00, about 15 minutes AFTER #15 close 02:35:05+09:00. All other children (#45-#48) close BEFORE #15. #49 body declares verification-only path (no new SHA; re-uses 614c533), so post-close #49 close does not leak code into #15. Disposition : record-only, no reopen. |
docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.md Step 14/15; child rows below |
| 15 | #16 IMP-16 B-2 verification helper axis |
Step 1/2/14/21/22 -- phase_z2_verification_utils.py port + 8 verification test modules + U2 wiring design doc |
Step 22 reverse path verification (consumer is #7 IMP-07 once activated); no normal-path coupling |
Step 14/21 trace consumers (utility); future #7 reverse-path verification |
OK -- utility module plus design doc only; no normal-path coupling (gated by #7 activation); commit 23ba8b6 is design + utility port (335 LOC utility + 8 test modules + wiring doc) |
src/phase_z2_verification_utils.py; docs/architecture/IMP-16-U2-WIRING-DESIGN.md (commit 23ba8b6) |
| 16 | #17 IMP-17 AI repair fallback infra (carve-out -- outside normal path) |
Design-only boundary + 3-cond AND gate (User GO AND B4 frame_selection evidence AND IMP-04/05 live); httpx + SSE + retry + JSON parse pattern reference |
Step 12 (AI position contract; carve-out body asserts normal path AI = 0); Step 16/17 fallback path (gated activation); feedback_ai_isolation_contract (foundational rule); backlog row + INSIGHT-MAP cross-ref |
Step 12 (design boundary); future activation gated by 3-cond AND | OK -- design-only carve-out; src/phase_z2_pipeline.py change = 1 line (comment anchor for orchestrator test); no runtime AI added |
docs/architecture/IMP-17-CARVE-OUT.md + tests/orchestrator_unit/test_imp17_comment_anchor.py (commit e10ec36) |
| 17 | #18 IMP-18 I3 SVG coordinate reinforcement |
Doc-only carve-out -- SVG gap report; renderer._preprocess_svg_data pattern reference |
Step 0 frame_partials SVG geometry (reference); Phase R' (renderer.py) read-only | doc consumers; backlog row | OK -- doc-only (docs/architecture/IMP-18-SVG-GAP-REPORT.md + 1-line backlog status flip from pending to documented); no code touched |
docs/architecture/IMP-18-SVG-GAP-REPORT.md (commit cbbc163) |
| 18 | #45 (#15 execution-1) image_aspect_mismatch detection + runtime test |
Step 14 -- image_aspect_mismatch detection in visual_check; runtime test test_phase_z2_step14_image_check.py |
Step 15 fit_classification consumer; Step 21 debug.json event surfacing (delegated to #48); #15 parent close evidence |
Step 15 (consumer via classifier event); #47 (classifier integration) |
OK -- Step 14 detection only (no Step 15 wiring yet; delegated to #47). Test scope local. |
src/phase_z2_pipeline.py + tests/phase_z2/test_phase_z2_step14_image_check.py (commit e9b3d2e) |
| 19 | #46 (#15 execution-2) table overflow + element-identity dedup + Selenium test |
Step 14 -- table_self_overflow detection; element-identity dedup; Selenium integration test |
Step 14 dedup logic (must agree with image events from #45); Step 15 consumer (delegated to #47); #15 parent |
Step 15 (consumer); #47 |
Warning -- commit-message label drift only (Step 14 scope-discipline pattern itself matches #45). Commit 2827622 message reads feat(IMP-16): ..., which mis-labels the closing Gitea issue (actually closes #46 = #15 execution-2; IMP-16 backlog row is the verification utility carved out separately). Audit attribution corrected here; SHA 2827622 is the authoritative anchor. No code/contract leak; risk is record-keeping only. |
src/phase_z2_pipeline.py + tests/phase_z2/test_phase_z2_step14_table_check.py (commit 2827622) |
| 20 | #47 (#15 execution-3) classifier consumer (image + table) + pure-dict test |
Step 15 -- classifier consumes image+table events from Step 14; pure-dict test (no Selenium) | Step 14 producers (#45 + #46); Step 15 CONTENT_TYPE_PATTERNS taxonomy; Step 16 router (consumer) |
Step 16; tests/phase_z2/test_phase_z2_visual_classifier.py |
OK -- classifier wiring with pure-dict tests isolates Step 15 from Selenium dependency; aligns Step 14 producer to Step 15 consumer (Axis 3 invariant -- to be re-verified in Section 5) | src/phase_z2_classifier.py (commit 535c484) |
| 21 | #48 (#15 execution-4) debug.json event surfacing + spec doc trace + regression |
Step 21 debug.json event surfacing + PHASE-Z-FIT-CLASSIFIER-ROUTER-SPEC.md taxonomy row + regression test |
Step 21 trace schema (additive); spec doc; regression guard | spec doc consumers; debug.json consumers (Front/, audit tooling) | OK -- 3-line pipeline change + 2 test modules + 1-line spec doc row; smallest blast radius of #15 children | src/phase_z2_pipeline.py + docs/architecture/PHASE-Z-FIT-CLASSIFIER-ROUTER-SPEC.md (commit 614c533) |
| 22 | #49 (#15 execution-5) final integration + parent close |
Verification-only -- re-uses #48 614c533 evidence; no new SHA per #15 body |
#15 parent close; integration-only |
#15 parent |
Warning -- close-timestamp anomaly (closed 2026-05-19T02:49:56+09:00, about 15 minutes AFTER #15 close 02:35:05+09:00). Verification-only path has no code change, so anomaly is administrative only; no contract leak. |
#15 body + 614c533 (re-used) |
Section 3 finding summary
- OK rows :
#2 #3 #4 #5 #7 #8 #9 #10 #11 #13 #14 #16 #17 #18 #45 #47 #48(17) - Warning rows :
#6(wide override blast radius, contained by tests);#12(multi-donor + cascade, contained by 5 test modules);#15(close-timestamp anomaly via#49);#46(commit-message label drift only, SHA correct);#49(close-timestamp anomaly, verification-only) -- 5 rows - Blocker rows : 0
- Total : 17 OK + 5 Warning + 0 Blocker = 22 rows (matches 22 closed issues under audit).
- De-dup audit :
#15row carries no code attribution; all code/test work attributed to#45-#48(and#49= verification-only). No double-count.
Section 3 cross-issue scope-myopia adjacency check
Adjacent-contract pairs flagged for Section 5 Axis 3 re-verification (producer to consumer continuity) :
#2Step 2 normalize output ->#3Step 3 content_object input#3content_object schema ->#8sub_sections schema extension#4catalog expansion ->#5V4 fallback candidate pool dedup#4catalog expansion ->#10-#11min_height_pxexposure#9layout vocabulary ->#12retry zone-ratio donor selection#9layout vocabulary ->#11Step 9 min_height v4-all-judgments test#45 + #46Step 14 events ->#47Step 15 classifier -> Step 16 router#48debug.json event surfacing ->#21(Step 21 debug consumer; open, excluded)#17AI carve-out ->#5 + #4activation 3-cond AND gate (gated, not active)
Axis 3 (Section 5) will verify each pair has agreeing producer-line / consumer-line on the live code.
Section 4. Axis 2 -- 22 issues x 22 steps pipeline matrix
Split rationale : at u1 completion the combined REPORT was 21,070 bytes / 136 lines -- over the 10 KB readability threshold defined in the Stage 2 plan. Per the split rule (combined REPORT >= 10 KB grid moves to MATRIX.md + back-pointer), the 22 x 22 grid lives in the companion file :
docs/architecture/INTEGRATION-AUDIT-01-MATRIX.md
What MATRIX.md contains :
- Step 0 precondition NOTE (NOT a grid column) -- 5 issues (
#4 #11 #13 #14 #18) recorded with scope summary + evidence path. - 22 x 22 grid (Step 1 through Step 22 columns x 22 issue rows). Cell legend :
P= primary touch,A= adjacent contract,.= no touch. ASCII-only. - Row footer (touched-step count) and column footer (touching-issue count +
HHOTSPOT marker for col total >= 4). - HOTSPOT enumeration (9 steps :
S2 S9 S13 S14 S15 S16 S17 S21 S22). - Cross-check against the 9 adjacent-contract pairs flagged in Section 3.
- Empty / low-touch column notes (Step 4 and Step 11 are
missingper PHASE-Z-PIPELINE-OVERVIEW -- 0 touches expected). - Parent/child de-dup sum check :
#15row carries 3 adjacencies and zeroPcells ; only#45 #46 #47 #48carry the 4 primary cells for the#15family ;#49is verification-only with all-A.
Section 4 summary (for readers staying in REPORT) :
- 9 hotspot steps (col total >= 4) : Step 2 (4), Step 9 (6), Step 13 (5), Step 14 (9 highest), Step 15 (6), Step 16 (4), Step 17 (4), Step 21 (8), Step 22 (7).
- 2 empty columns : Step 4 + Step 11. Consistent with master pipeline
missingstatus -- no audit gap. - Total grid cells filled = 77 (row sum = col sum, cross-checked).
- Top row-total issues :
#6(7),#5(6),#8(6),#12(6) -- the 2Warningrows (#6 #12) sit at the top, consistent with Section 3 wide-blast-radius finding.
Section 5. Axis 3 -- Cross-issue conflict per invariant category
Method : 6 invariant categories listed in the issue body. Per category, identify producer file:line, consumer file:line, the named state key / contract, the closed issues that touch it, agree-or-conflict verdict, plus grep evidence path. Categories are evaluated against the live tracked code at audit time, not against historical snapshots.
5.1 Invariant category roster (from issue body)
| # | category | issue-body wording |
|---|---|---|
| C1 | debug.json schema |
phase_z2 debug payload paths; no conflicting key type / semantics |
| C2 | visual_check_passed |
src/phase_z2_pipeline.py Step 14 / 17; set-site <-> read-site agree |
| C3 | fit_classification / router |
src/phase_z2_mapper.py + consumers; labels consistent producer -> consumer (charter mis-cite; live producer = src/phase_z2_classifier.py -- see §10 F-1) |
| C4 | Step 14 / 17 / 21 interactions | expected state values stay aligned across the trio |
| C5 | Phase R vs Phase Z boundary | no R regression, Z additions don't leak into R |
| C6 | template / catalog / frame count | all docs / code use same numbers (family = 13) |
5.2 Producer / consumer / agreement table
| C# | invariant key | producer (file : line) | consumer(s) (file : line) | touching closed issues | verdict | grep evidence |
|---|---|---|---|---|---|---|
| C1 | per-step JSON schema = step_num, step_name, step_status, pipeline_path_connected, input, output, note, data (locked) |
src/phase_z2_pipeline.py:2593 _write_step_artifact definition; locked schema docstring at 2605-2611 (Locked schema lines 2607-2610) |
every step writer in src/phase_z2_pipeline.py -- 24 call sites at lines 2782, 2812, 2857, 2934, 3184, 3619, 3652, 3674, 3793, 3804, 3826, 3881, 4056, 4308, 4481, 4507, 4527, 4549, 4658, 4677, 4688, 4706, 4761, 4780; Front/ reads data/runs/.../steps/*.json; audit tooling |
#2 step02_*; #3 content_objects; #5 v4_fallback_summary + selection_paths + fallback_selection_count; #6 render_records; #11 min_height_px payload; #48 image_events / table_events event surfacing |
AGREE -- all step writers go through the single _write_step_artifact site with the locked field set; additive data payload only; no conflicting key types observed |
Grep _write_step_artifact src/phase_z2_pipeline.py = 1 definition (line 2593) + 24 call sites = 25 total occurrences (all 24 call sites enumerated in consumer column); all share the same _write_step_artifact(run_dir, step_num, name, data, *, step_status, pipeline_path_connected, inputs, outputs, note) kwargs surface |
| C2 | visual_check_passed: bool set at Step 14 / read at Step 17 |
src/phase_z2_classifier.py:495 visual_check_passed = bool(overflow.get("passed", False)) and not classifications returned at 497 |
src/phase_z2_router.py:128 if fit_classification.get("visual_check_passed", True): ... router_active = False; src/phase_z2_pipeline.py:2560 sets slide_status["visual_check_passed"] = visual_passed; pipeline summary reads at 4800, 4804, 4830 |
#15 parent; #45 (image_events flip the flag); #46 (table_events flip the flag); #47 (classifier widens semantic to passed AND no classifications) |
AGREE -- single set-site (classifier.py:495) + slide_status mirror (pipeline.py:2560); router.py:128 + pipeline.py:4800/4804/4830 read the same key. Default .get(..., True) at router.py:128 is safe because absent key = no classification = pass |
Grep visual_check_passed src = 14 hits across classifier.py + router.py + pipeline.py -- producer / consumer line set matches |
| C3 | fit_classification dict keys = visual_check_passed, classifications, summary, categories_seen, unclassified_signals, placement_diagnostics; classifier <-> router consumer |
src/phase_z2_classifier.py:496-506 classify_visual_runtime_check return dict |
src/phase_z2_router.py:109 route_fit_classification(fit_classification); src/phase_z2_pipeline.py:4524 fit_classification = classify_visual_runtime_check(overflow, debug_zones); pipeline re-classify after retry at 4582 / 4643; router decision call at 4540 / 4583 / 4644; retry consumer src/phase_z2_retry.py:47 reads fit_classification |
#5 (V4 fallback PASS_WITH_FALLBACK semantics); #12 (retry router multi-donor + cascade); #15 parent; #47 (classifier feed); #48 (debug surfacing) |
AGREE -- producer key set is the exact set consumed downstream. NOTE : the issue body says src/phase_z2_mapper.py for invariant C3, but the live producer is src/phase_z2_classifier.py (mapper.py owns slot payload, not fit classification). This is a record-keeping mismatch in the issue body, not a code conflict. Recorded as Section 10 follow-up candidate F-1 |
Grep fit_classification src = 30 total occurrences across 4 files (classifier.py 3 hits incl. docstring/comments; pipeline.py 20 hits; router.py 5 hits; retry.py 2 hits). Active code use sites = producer at classifier.py:497; consumers at router.py:128 / 139 + pipeline.py 2732 / 4524 / 4540 / 4571 / 4582 / 4583 / 4643 / 4644 / 4754 / 4804 / 4805 + retry.py:47 / 67. Remaining occurrences are imports / function-parameter declarations / docstring references |
| C4 | Step 14 visual_check overflow events (image_events, table_events, passed) -> Step 15/16 (fit + router) -> Step 17 retry action -> Step 21 debug surface |
Step 14 emit sites src/phase_z2_pipeline.py:2236 (image_events), 2282 (table_events), 2367 / 2386 (aggregation); Step 15 classifier consumes both event lists at src/phase_z2_classifier.py:429 / 453; Step 16 router at src/phase_z2_router.py:142; Step 17 retry orchestration at src/phase_z2_pipeline.py:4571 / 4583 / 4644; Step 21 trace producer at src/phase_z2_pipeline.py:4762-4777 (step21_debug_index.json + debug.json outputs) |
Step 21 debug.json index reader (Front/ + audit tooling); pipeline summary 4791-4841 |
#12 (retry cascade Step 17 multi-donor + glue + font compression); #15 / #45 / #46 / #47 / #48 (Step 14 producer / Step 15 classifier consumer / Step 21 surface); #10 filtered_section_reasons (Step 22 read-only, Step 21 source) |
AGREE with one DOCUMENTED PARTIAL -- Step 21 writer at pipeline.py:4772 is step_status="partial" with note region marker partial 미주입 -- Step 21 ⚠ partial. This is an acknowledged partial state recorded in trace, not a contract conflict between issues. Recorded as Section 6 status row |
Grep step_num.*=.*21|outputs.*debug\.json src/phase_z2_pipeline.py = single producer at line 4762-4777 |
| C5 | Phase R' (src/renderer.py, src/content_editor.py, src/html_validator.py, src/block_selector.py) <-> Phase Z (src/phase_z2_*.py) module boundary; no cross-import |
src/phase_z2_pipeline.py (Phase Z entry) has zero imports of Phase R' modules; verified via Grep "from renderer|import renderer|from phase_q|from src\.renderer" src/phase_z2_pipeline.py = No matches found |
inverse direction src/renderer.py and src/block_selector.py have zero references to phase_z2; verified via Grep phase_z2 src/renderer.py = 0 and Grep phase_z2 src/block_selector.py = 0 |
#13 (build-time frame preview generator, scripts/ only); #14 (slide-base iframe mode -- Phase Z only); #16 (verification utility for Phase Z, no Phase R coupling); #17 (AI carve-out, design-only no R coupling); #18 (SVG gap report doc-only) |
AGREE -- boundary clean both directions for the closed-issue scope. No Phase R' regression observed; Phase Z additions stay in phase_z2_*.py modules |
Grep results above |
| C6 | family templates count vs frame_contracts.yaml count (= 11 in tracked baseline); docs cite "family = 13" including 2 in-progress untracked files | templates/phase_z2/families/*.html tracked = 11 (git ls-files templates/phase_z2/families/ produces 11 entries); templates/phase_z2/catalog/frame_contracts.yaml top-level entries = 11 (grep -cE "^[a-z_]+:$" = 11) |
src/phase_z2_mapper.py PAYLOAD_BUILDERS / ITEM_PARSERS / COLUMN_BODY_PARSERS registries (mapper.py:10-16 docstring + 262 / 306 / 332 / 369 / 414 / 424 / 471 registry sites); render surface templates/phase_z2/families/*.html |
#4 (16 frame_partials + F17 paired_rows_4x2 schema + theme); #5 (V4 fallback candidate pool dedup); #13 (frame preview generator); #18 (SVG gap report cites families/*.html (13)) |
AGREE FOR TRACKED BASELINE -- 11 tracked family templates <-> 11 frame_contracts entries. SURFACE NOTE : 2 untracked WIP family templates (app_sw_package_vs_solution.html, pre_construction_model_info_stacked.html) exist on disk but are NOT in any closed issue and NOT yet contracted. IMP-18 doc "families/*.html (13)" is forward-looking, includes the 2 WIP files. No closed-issue contract is broken; documentation drift is recorded as Section 10 follow-up candidate F-2 |
git ls-files templates/phase_z2/families/ = 11; ls templates/phase_z2/families/*.html = 13 (2 untracked); grep -cE "^[a-z_]+:$" frame_contracts.yaml = 11 |
5.3 Cross-issue adjacency continuity (Section 3 pairs re-verified)
| Section 3 adjacent pair | invariant carrying the contract | live continuity verdict |
|---|---|---|
#2 Step 2 normalize -> #3 Step 3 content_object input |
C1 (debug.json step02_* + content_objects) |
OK -- additive payload, schema preserved via _write_step_artifact |
#3 content_object schema -> #8 sub_sections schema |
C1 + C4 (alias resolver state) | OK -- alias resolver covers 4 lookup sites (REPORT Section 3 row #8 evidence) |
#4 catalog -> #5 V4 fallback dedup |
C3 + C6 (frame count + classifier consumer) | OK -- candidates[0] backward-compat verified by tests/test_catalog_invariant.py (REPORT Section 3 row #5) |
#4 catalog -> #10 / #11 min_height_px exposure |
C1 + C6 | OK -- min_height_px is additive read-only field |
#9 layout vocabulary -> #12 retry donor selection |
C3 + C4 (Step 17 cascade) | OK -- multi-donor cross-zone state lives inside Step 17 retry; spacing direction matches feedback_phase_z_spacing_direction (no common-shrink) |
#9 layout vocabulary -> #11 Step 9 min_height v4-all-judgments |
C6 | OK -- guarded by tests/test_phase_z2_step9_v4_all_judgments_min_height.py |
#45 + #46 Step 14 events -> #47 Step 15 classifier -> Step 16 router |
C2 + C3 + C4 | OK -- live trace image_events / table_events enter classifier at classifier.py:429 / 453, flow into router at router.py:142 |
#48 debug.json event surfacing -> #21 (open, excluded) |
C1 | OK for closed scope -- open consumer #21 is outside audit window |
#17 AI carve-out -> #5 / #4 activation 3-cond AND gate |
C5 (boundary not yet crossed) | OK -- gate is closed (User GO AND B4 frame_selection evidence AND IMP-04/05 live); no normal-path AI active |
5.4 Axis 3 summary
- 6 invariant categories evaluated. All AGREE for the closed-issue audit scope.
- 2 surface notes recorded as Section 10 follow-up candidates :
- F-1 : issue body cites
src/phase_z2_mapper.pyfor invariant C3 (fit_classification), but the live producer issrc/phase_z2_classifier.py. Record-keeping correction needed in any future audit charter, not a code conflict. RESOLVED via IMP-53 (2026-05-19) - F-2 : 2 untracked family templates exist on disk without
frame_contracts.yamlentries; IMP-18 doc cites "families/*.html (13)" forward-looking. Tracked baseline (11 / 11) is consistent. Contract drift is not present for any closed issue; the WIP delta belongs to open work. RESOLVED via #52 option (c) (2026-05-19) -- WIP allowlist captured intemplates/phase_z2/families/_WIP_FILES.md; tracked + contracted baseline unchanged at 11/11; promote / remove gated on #42.
- F-1 : issue body cites
- 1 documented partial recorded :
- Step 21
_write_step_artifactatpipeline.py:4772carriesstep_status="partial"with noteregion marker partial 미주입 -- Step 21 ⚠ partial. This is self-honest acknowledged perfeedback_artifact_status_naming; no cross-issue conflict.
- Step 21
- Phase R' <-> Phase Z boundary clean both directions for the 22 closed issues.
- 0 Blocker findings in Axis 3.
5.5 Live-grep re-verification stamp (audit date 2026-05-19)
All numerical claims in Section 5.2 re-verified against live source on the audit date. Commands and results :
| Claim | Command | Live result | Status |
|---|---|---|---|
| C1 producer + consumer count | Grep _write_step_artifact src/phase_z2_pipeline.py -n |
1 definition (pipeline.py:2593) + 24 call sites at lines 2782, 2812, 2857, 2934, 3184, 3619, 3652, 3674, 3793, 3804, 3826, 3881, 4056, 4308, 4481, 4507, 4527, 4549, 4658, 4677, 4688, 4706, 4761, 4780 = 25 total occurrences |
MATCH (Section 5.2 C1 row already lists all 24 call sites) |
| C2 consumer scan | Grep visual_check_passed src |
14 hits across 3 files (classifier.py:5, pipeline.py:6, router.py:3) |
MATCH (Section 5.2 C2 row says "14 hits across classifier.py + router.py + pipeline.py") |
| C3 consumer scan | Grep fit_classification src |
30 hits across 4 files (classifier.py:3, pipeline.py:20, retry.py:2, router.py:5) |
MATCH (Section 5.2 C3 row says "30 total occurrences across 4 files") |
| C6 family templates -- tracked | git ls-files templates/phase_z2/families/ |
11 entries | MATCH (Section 5.2 C6 row says "tracked = 11") |
| C6 family templates -- on disk | `ls templates/phase_z2/families/*.html | wc -l` | 13 files (11 tracked + 2 WIP untracked : app_sw_package_vs_solution.html, pre_construction_model_info_stacked.html) |
| C6 frame_contracts entries | grep -cE "^[a-z_]+:$" templates/phase_z2/catalog/frame_contracts.yaml |
11 | MATCH (Section 5.2 C6 row says "= 11") |
No discrepancy between Section 5.2 grep evidence and live code. Re-verification re-confirms u3 Axis 3 conclusion : 6 invariant categories all AGREE; 2 record-keeping follow-up candidates (F-1, F-2); 1 documented partial (Step 21); 0 Blocker findings.
Section 6. Axis 4 -- Backlog vs code reality status matrix
Method : per closed issue, compare (a) docs/architecture/PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md status column at audit time (live read 2026-05-19), (b) live src/ + templates/ + tests/ + docs/ evidence (grep hits + file existence), (c) the audit-allowed status enum implemented | documented (deferred) | pending, (d) mismatch flag.
Per issue-body rule set :
implemented-> live grep onsrc/**MUST show wired call site(s); not just a single declaration with no consumer.documented (deferred)-> live grep onsrc/**MUST NOT show a production code path that assumes the feature is active (carve-out only).pending-> live grep onsrc/**MUST NOT show wired implementation (or evidence shows incomplete).pending -> documentedflip -> reason cited in backlog row must match whatsrc/**actually contains.
6.1 Backlog status legend (live read on audit date)
| backlog status | IMP rows under audit | meaning |
|---|---|---|
documented |
IMP-18 (1 row) |
doc-only carve-out, no production path |
pending |
IMP-02 through IMP-17 (16 rows) |
backlog status column has NOT been flipped, despite Gitea issue being closed |
| (no backlog row) | #45 / #46 / #47 / #48 / #49 (5 rows) |
execution children of #15; backlog tracks the parent IMP-15 only -- and IMP-15 is itself still marked pending in §2 row |
Headline Axis 4 finding : PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md status column is stale across the entire closed-issue audit scope -- 16 of 22 audited issues are flagged BACKLOG_STALE (backlog pending vs Gitea closed + live code wired); additionally 5 of 22 carry NO_BACKLOG_ROW for the #15 execution children (#45-#49), and only 1 of 22 (#18) is AGREE. Reconciliation: 16 BACKLOG_STALE + 5 NO_BACKLOG_ROW + 1 AGREE = 22 (matches Section 6.3 summary and the 15+1=16 flip plan in §6.3 follow-up reference). This is documentation drift, not a code-side contract conflict; recorded as Section 10 follow-up candidate F-3.
6.2 Axis 4 -- 22 row backlog vs code reality matrix
Status meaning (audit verdict column) :
implemented_live= backlog should be flipped toimplemented; live src/ wiring proves it (grep evidence below).documented_live= backlogdocumentedmatches code reality (doc-only carve-out; no prod path).child_of_parent= no backlog row by design (execution child of parent IMP-15); status tracked via parent row.
Mismatch flag :
BACKLOG_STALE= backlog sayspendingbut code is wired live. Documentation drift only; no code conflict.AGREE= backlog status matches live code reality.NO_BACKLOG_ROW= execution child, child not represented in backlog; not an error, but parentIMP-15row is itself stale.
| # | issue (title) | backlog status (live read) | audit verdict | mismatch flag | live grep evidence |
|---|---|---|---|---|---|
| 1 | #2 IMP-02 A-1 Stage 0 normalize chained adapter |
pending (§1 row 2) |
implemented_live |
BACKLOG_STALE | Grep "normalize_mdx_content|extract_major_sections|extract_conclusion_text" src/ = 24 hits across 6 files (mdx_normalizer.py, phase_z2_content_extractor.py, phase_z2_pipeline.py 9 hits, pipeline.py, pipeline_v2.py, section_parser.py); commit bac13c0 +165/-3 |
| 2 | #3 IMP-03 A-1 popup/image/table trace |
pending (§1 row 3) |
implemented_live |
BACKLOG_STALE | src/phase_z2_content_extractor.py file exists (Glob hit); commit fc3f7d8 |
| 3 | #4 IMP-04 A-2 catalog expansion |
pending (§1 row 4) |
implemented_live |
BACKLOG_STALE | git ls-files templates/phase_z2/families/ = 11 tracked; frame_contracts.yaml top-level entries = 11; commit 73a98b8 corrects F17 schema; matches Axis 3 C6 |
| 4 | #5 IMP-05 A-5 V4 fallback |
pending (§1 row 5) |
implemented_live |
BACKLOG_STALE | Grep "PASS_WITH_FALLBACK|v4_fallback|fallback_selection" src/ = 28 hits in phase_z2_pipeline.py; commits 15c5b9a, 21476ae, 23d1b25 |
| 5 | #6 IMP-06 B-1 Zone-section override |
pending (§1 row 6) |
implemented_live |
BACKLOG_STALE | Grep "replaced_auto_unit|render_records|zone_section_override" src/ = 33 hits in phase_z2_pipeline.py; commits d596fab / b81e564 / 1f15495 / 52ccb7f |
| 6 | #7 IMP-07 B-2 edited HTML to MDX reverse path |
pending (§1 row 7) |
implemented_live |
BACKLOG_STALE | Front/client/src/services/designAgentApi.ts file exists (Glob hit); commit 0f0d3fa |
| 7 | #8 IMP-08 B-3 sub-section drag-drop |
pending (§1 row 8) |
implemented_live |
BACKLOG_STALE | Grep "sub_sections|sub_section_id|subsection_alias" src/ = 14 hits across block_assembler.py (12) + phase_z2_pipeline.py (2); commits a422d72 / 5191aca / ab2764c / 8f6cffc |
| 8 | #9 IMP-09 B-4 non-default layout zone-geometry |
pending (§1 row 9) |
implemented_live |
BACKLOG_STALE | Grep "build_layout_css|preset_layout|zone_geometry" src/ = 11 hits in phase_z2_pipeline.py; commits 201099e / 1fb9732 |
| 9 | #10 IMP-10 D-1 filtered_section_reasons UI |
pending (§1 row 10) |
implemented_live |
BACKLOG_STALE | Grep "filtered_section_reasons" Front/ = 4 hits (Home.tsx, designAgentApi.ts); + src/phase_z2_pipeline.py 6 hits (read-only consumer); commit 0fb168b +45 lines |
| 10 | #11 IMP-11 D-2 Frame min_height display |
pending (§1 row 11) |
implemented_live |
BACKLOG_STALE | Grep "min_height_px" src/ = 50 hits across 6 files (block_reference.py, block_selector.py, fit_verifier.py, phase_z2_pipeline.py 21 hits, phase_z2_retry.py, space_allocator.py); + Front/ 21 hits across 7 files including SlideCanvas.tsx (8); commit a79bd8b |
| 11 | #12 IMP-12 Step 16/17 retry refinement |
pending (§2 row 12 IMP-12) |
implemented_live |
BACKLOG_STALE | Grep "phase_z2_failure_router|phase_z2_retry|redistribute|font_compression" src/ = 63 hits across 7 files (incl. phase_z2_failure_router.py 17, phase_z2_retry.py 16, phase_z2_router.py 6, phase_z2_pipeline.py 17); commit 56619a0 |
| 12 | #13 IMP-13 A-3 frame preview consistency |
pending (§2 row 13) |
implemented_live |
BACKLOG_STALE | scripts/generate_frame_previews.py file exists (Glob hit); build-time only (scripts/, not runtime src/) -- matches documented (deferred) semantics for runtime path but verdict here = implemented_live because the script is the deliverable per issue body; commit 7d5639a |
| 13 | #14 IMP-14 A-4 slide-base iframe mode |
pending (§2 row 14) |
implemented_live |
BACKLOG_STALE | templates/phase_z2/slide_base.html file exists (Glob hit); Grep "slide_base|embedded_mode|standalone_mode" src/ = 25 hits across 5 files (incl. block_assembler.py 8, phase_z2_pipeline.py 11); commit 7a52ceb |
| 14 | #15 IMP-15 Step 14 visual_check reinforcement (PARENT) |
pending (§2 row 15) |
implemented_live (via children #45-#49) |
BACKLOG_STALE | parent integration only; live code attribution belongs to child rows below (Stage 1 de-dup rule). All 4 child SHAs present in repo (e9b3d2e / 2827622 / 535c484 / 614c533) |
| 15 | #16 IMP-16 B-2 verification helper axis |
pending (§2 row 16) |
implemented_live |
BACKLOG_STALE | src/phase_z2_verification_utils.py file exists (Glob hit); docs/architecture/IMP-16-U2-WIRING-DESIGN.md exists; commit 23ba8b6 |
| 16 | #17 IMP-17 AI repair fallback infra (carve-out) |
pending (§2 row 17) |
documented_live |
BACKLOG_STALE (status semantics) | docs/architecture/IMP-17-CARVE-OUT.md file exists (Glob hit); src/ runtime AI = 0 (verified Axis 3 C5 boundary); 3-cond AND gate closed; commit e10ec36 -- 1 line in src/phase_z2_pipeline.py is comment anchor only, not a runtime path. Mismatch FLAG semantics : backlog says pending, but reality = documented (deferred). The flag is BACKLOG_STALE with status-class shift, distinguished from rows above. |
| 17 | #18 IMP-18 I3 SVG coordinate reinforcement |
documented (§2 row 18) |
documented_live |
AGREE | docs/architecture/IMP-18-SVG-GAP-REPORT.md file exists (Glob hit); pure doc carve-out; no src/** touched; commit cbbc163 -- the ONLY closed audited issue whose backlog status already reflects code reality |
| 18 | #45 (#15 execution-1) image_aspect_mismatch detection |
no backlog row | child_of_parent |
NO_BACKLOG_ROW | tests/phase_z2/test_phase_z2_step14_image_check.py file exists (Glob hit); Grep "image_aspect_mismatch" src/ = 6 hits across phase_z2_classifier.py (2 : lines 426, 435) + phase_z2_pipeline.py (4 : lines 131, 2236, 2367, 4517); commit e9b3d2e |
| 19 | #46 (#15 execution-2) table_self_overflow detection |
no backlog row | child_of_parent |
NO_BACKLOG_ROW | tests/phase_z2/test_phase_z2_step14_table_check.py file exists (Glob hit); Grep "table_self_overflow" src/ = 3 hits all in phase_z2_pipeline.py (lines 136, 2282, 2386); commit 2827622 (commit-message label drift feat(IMP-16) flagged in Section 3 row 19) |
| 20 | #47 (#15 execution-3) classifier consumer (image + table) |
no backlog row | child_of_parent |
NO_BACKLOG_ROW | tests/phase_z2/test_phase_z2_visual_classifier.py file exists (Glob hit); Grep "classify_visual_runtime_check|CONTENT_TYPE_PATTERNS" src/ = 8 hits across phase_z2_classifier.py (4) + phase_z2_pipeline.py (4); commit 535c484 |
| 21 | #48 (#15 execution-4) debug.json event surfacing + spec doc + regression |
no backlog row | child_of_parent |
NO_BACKLOG_ROW | Grep "step21_debug_index|step21_debug" src/ = 1 hit (phase_z2_pipeline.py); docs/architecture/PHASE-Z-FIT-CLASSIFIER-ROUTER-SPEC.md has taxonomy row (Section 3 row 21 evidence); commit 614c533; Axis 3 C4 confirms image_events / table_events end-to-end |
| 22 | #49 (#15 execution-5) final integration + parent close |
no backlog row | child_of_parent (verification-only) |
NO_BACKLOG_ROW + close-timestamp anomaly (recorded Section 3 row 22) | verification-only per #15 body; no new SHA; re-uses 614c533 evidence; no fresh grep needed |
6.3 Axis 4 summary
- BACKLOG_STALE rows :
#2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14 #15 #16 #17= 16 rows (status column readspendingbut live code is wired; for#17the right target status isdocumented (deferred)while for the other 15 it isimplemented). - AGREE rows :
#18= 1 row (the only issue whose backlog status truthfully reflects code reality). - NO_BACKLOG_ROW rows :
#45 #46 #47 #48 #49= 5 rows (execution children, by-design no backlog row; parentIMP-15row exists but is itself BACKLOG_STALE). - Total : 16 + 1 + 5 = 22 rows (matches 22 closed issues under audit).
- Implementation-vs-documented split (audit verdict, ignoring backlog wording) :
implemented_live(runtime path wired) :#2 #3 #4 #5 #6 #7 #8 #9 #10 #11 #12 #13 #14 #15(via children) #16= 15 rowsdocumented_live(doc-only / design-only carve-out, no runtime path) :#17 #18= 2 rowschild_of_parent(no backlog row, attribution via parent) :#45-#49= 5 rows
- 0 Blocker findings in Axis 4. No closed issue is
pendingand unimplemented; the only mismatches are documentation drift in the backlog status column. - Cross-axis consistency :
- Axis 3 C6 frame count
11 tracked / 11 contract entries / 13 on disk (2 WIP)matches the IMP-04 evidence in Axis 4 row 3 (BACKLOG_STALE but live code present). - Axis 3 C5 boundary (Phase R' <-> Phase Z) clean both ways re-confirms
#17 #18as documented_live (no R' leak). - Axis 1 (Section 3)
Warningrows#6 #12 #15 #46 #49are all stillimplemented_livein Axis 4 -- the warnings are about blast radius and administrative drift, not implementation absence.
- Axis 3 C6 frame count
- Follow-up candidate F-3 (Section 10) :
PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.mdstatus column needs a sweep to flip 15 rowspending->implemented, 1 rowpending->documented (deferred)forIMP-17, and either add child-row stubs for#45-#49or add a footnote on theIMP-15row pointing at the 5 execution children. This is a single-file documentation-only edit; orthogonal to source-code Stage 3 work; safe under audit-only scope (deferred to a separate follow-up issue, NOT this audit's u7 backlog row).
Section 7. Representative pipeline runs
Method : run the Phase Z runtime entry (python -m src.phase_z2_pipeline <mdx_path> <run_id>) on the two locked samples (samples/mdx_batch/03.mdx smoke + samples/mdx_batch/04.mdx details+images). Per run capture (from data/runs/<run_id>/phase_z2/debug.json) : top-level keys, slide_status.visual_check_passed, slide_status.overall, zone count, per-zone frame template + slot keys + slot key count, slide_status.visual_fail_reasons, slide_status.filtered_section_reasons, selection_paths, image_events / table_events count. Compare invariants across both runs.
Audit date : 2026-05-19. Both runs are fresh on this audit pass (run_ids audit50_run_03_smoke + audit50_run_04_details).
7.1 Run #1 -- samples/mdx_batch/03.mdx (smoke baseline)
| field | value |
|---|---|
run_id |
audit50_run_03_smoke |
| MDX title parsed | DX 실행 체계 구축 방안 |
| sections parsed | 2 (03-1, 03-2) |
| layout preset | horizontal-2 (composition v0 count-based) |
| mode | composition_v0_layout_8preset |
| debug.json top-level keys | composition_planner_debug, fit_classification, image_events, layout_css, layout_preset, mode, mode_note, mvp1_allowed_statuses, retry_trace, router_decision, slide_status, table_events, v4_label_to_phase_z_status, v4_source, visual_runtime_check, zone_geometries_px, zones (17 keys) |
slide_status.visual_check_passed |
True |
slide_status.full_mdx_coverage |
True |
slide_status.rendered |
True |
slide_status.overall |
PASS |
slide_status.visual_fail_reasons |
[] (empty) |
slide_status.filtered_section_reasons |
[] (empty) |
slide_status.fallback_selection_count |
0 |
fit_classification.visual_check_passed |
True (mirrors slide_status) |
fit_classification.classifications |
[] |
fit_classification.categories_seen |
[] |
router_decision.action |
None (no retry path triggered) |
image_events count |
0 |
table_events count |
0 |
| zone count | 2 |
| zone[0] (top) | template three_parallel_requirements (frame 13), contract three_parallel_requirements, label use_as_is, slot keys ['pillars', 'title'] (2), sections ['03-1'], height_px=228, width_px=1180 |
| zone[1] (bottom) | template process_product_two_way (frame 29), contract process_product_two_way, label use_as_is, slot keys ['banner_left', 'banner_right', 'process', 'product', 'title'] (5), sections ['03-2'], height_px=343, width_px=1180 |
selection_paths |
both rank_1 (no fallback) |
| fail / overflow events | none |
7.2 Run #2 -- samples/mdx_batch/04.mdx (details + images)
| field | value |
|---|---|
run_id |
audit50_run_04_details |
| MDX title parsed | DX 지연 요인 |
| sections parsed | 2 (04-1, 04-2) |
| sections aligned | 3 (04-1, 04-2-sub-1, 04-2-sub-2) -- IMP-08 sub_section schema active |
| layout preset | single (composition v0 count-based; only 1 unit survived filtering) |
| mode | composition_v0_layout_8preset |
| debug.json top-level keys | identical 17 keys as Run #1 (composition_planner_debug, fit_classification, image_events, layout_css, layout_preset, mode, mode_note, mvp1_allowed_statuses, retry_trace, router_decision, slide_status, table_events, v4_label_to_phase_z_status, v4_source, visual_runtime_check, zone_geometries_px, zones) |
slide_status.visual_check_passed |
True |
slide_status.full_mdx_coverage |
False |
slide_status.rendered |
True (partial artifact -- viable units only) |
slide_status.overall |
PARTIAL_COVERAGE |
slide_status.visual_fail_reasons |
[] (visual side OK; coverage failure is upstream of visual_check) |
slide_status.filtered_section_reasons |
[] (filtering recorded via selection_paths chain_exhausted / no_v4_candidate, not via filtered_section_reasons) |
slide_status.fallback_selection_count |
0 |
fit_classification.visual_check_passed |
True |
fit_classification.classifications |
[] |
fit_classification.categories_seen |
[] |
router_decision.action |
None |
image_events count |
0 |
table_events count |
0 |
| zone count | 1 (single preset) |
| zone[0] (primary) | template bim_issues_quadrant_four (frame 16), contract bim_issues_quadrant_four, label light_edit, slot keys ['quadrant_1_body', 'quadrant_1_label', 'quadrant_2_body', 'quadrant_2_label', 'quadrant_3_body', 'quadrant_3_label', 'quadrant_4_body', 'quadrant_4_label', 'title'] (9), sections ['04-2-sub-2'], height_px=585, width_px=1180 |
selection_paths |
04-1=chain_exhausted, 04-2-sub-1=chain_exhausted, 04-2-sub-2=rank_1, 04-2=no_v4_candidate |
| fail / overflow events | none |
7.3 Cross-run invariants
| invariant | run #1 (03.mdx) | run #2 (04.mdx) | verdict |
|---|---|---|---|
| debug.json top-level key set | 17 keys (above) | identical 17 keys | AGREE -- Step 21 schema stable across both runs (Axis 3 C1) |
slide_status schema keys |
19 keys (visual_check_passed, full_mdx_coverage, rendered, overall, visual_fail_reasons, filtered_section_ids, filtered_section_reasons, aligned_section_ids, covered_section_ids, adapter_needed_count, adapter_needed_units, content_truncated_count, content_truncated_units, fallback_selection_count, fallback_selections, fallback_used, selection_path, selection_paths, note) |
identical 19 keys | AGREE -- slide_status surface stable (Axis 3 C2 + C4) |
fit_classification shape |
{visual_check_passed, classifications, summary, categories_seen, ...} -- matches Axis 3 C3 row |
identical shape | AGREE -- classifier output schema invariant |
visual_check_passed semantic |
True AND classifications=[] -> overall PASS |
True AND classifications=[] AND full_mdx_coverage=False -> overall PARTIAL_COVERAGE |
AGREE -- visual side passing under both runs; PARTIAL_COVERAGE is composition-planner side (upstream of Step 14), so visual_check_passed does NOT contradict overall status (Axis 3 C2 verdict re-confirmed) |
| zone count vs layout preset | horizontal-2 -> 2 zones (top + bottom) |
single -> 1 zone (primary) |
AGREE -- preset-to-zone arity matches IMP-09 B-4 vocabulary (Axis 1 row 8) |
| frame contract resolution | both zones resolved to a contract id (rank_1 path) | only 1 of 4 selection paths resolved (3 chain_exhausted / no_v4_candidate) |
DIFF EXPECTED -- 04.mdx exhibits v4 candidate gap; this is the composition-planner maturity gap (not in any closed-issue scope). Not a contract conflict. |
image_events / table_events arity |
both = 0 | both = 0 | AGREE -- neither sample triggers Step 14 image/table self-overflow; #45 image_aspect_mismatch and #46 table_self_overflow event-arrays exist in the schema and are correctly empty when no overflow is detected |
| router action triggered | None |
None |
AGREE -- Step 16 router is dormant when classifications=[] (Axis 3 C3 verdict re-confirmed; #12 retry cascade not exercised by these samples) |
| pipeline final banner | PASS (full MDX coverage + visual OK) |
PARTIAL_COVERAGE (visual OK + composition-planner filter) |
self-honest status naming per feedback_artifact_status_naming |
7.4 Run-level findings
- Both runs pass the visual_check axis (Axis 3 C2 contract).
visual_check_passed=Trueagrees betweenfit_classificationandslide_statusmirror in both runs. - 04.mdx
PARTIAL_COVERAGEis a composition-planner side filter (3 sections drop tochain_exhausted/no_v4_candidatebefore reaching Step 14). This is NOT an audit Blocker because (a) no closed issue under audit targets composition-planner coverage, (b) the status field is self-honestly namedPARTIAL_COVERAGErather than misnamedPASS(matches feedback_artifact_status_naming). - Step 21
debug.jsonwriter surfaces a stable 17-key top-level surface across both runs; Axis 3 C1 invariant re-confirmed at runtime. - Zero Blocker findings in Section 7.
Section 8. Anti-hardcoding grep checklist
Method : run the 6 anti-hardcoding patterns enumerated in the Issue #50 body. For each, capture the live hit set, classify hits (Phase Z scope vs. legacy Phase R'/Q out-of-scope vs. docstring/comment vs. test fixture), then return a verdict. Raw output preserved at D:\ad-hoc\kei\design_agent\.orchestrator\tmp\50_grep_checklist_raw.txt (evidence-only, not staged for commit per Stage 3 directive).
Audit date : 2026-05-19. Searched against tracked source on this date.
8.1 Checklist
| # | pattern (issue body) | expected | live hit count (src/) | hit classification | verdict |
|---|---|---|---|---|---|
| G1 | grep -E 'if .* == ["'\\''].*\.mdx' src/ |
0 hits | 0 | none | PASS |
| G2 | grep -E 'OVERRIDES\s*=\s*\{' src/ |
each match sample-agnostic | 0 | none | PASS (vacuously sample-agnostic) |
| G3 | grep -E '재구성|건설산업 DX|BIM' src/ -- sample text leak |
0 hits | 31 source hits across 14 .py files (binary .pyc matches ignored) |
(a) 20 hits in legacy Phase R'/Q files (block_assembler_b2.py 1, block_matcher_tfidf.py 1, block_reference.py 3, content_editor.py 3, design_director.py 2, design_tokens.py 1, fit_verifier.py 1, frame_extractor.py 1, kei_client.py 4, pipeline.py 3) -- pre-Phase-Z; not in audit window; (b) 11 hits in Phase Z files (phase_z2_content_extractor.py 7 -- all inside if __name__ == "__main__" self-test data blocks at lines 466/493/511/556/565/573/591; phase_z2_failure_router.py:123 1 -- internal taxonomy string "topology 부터 재구성. frame_reselect 는 그 다음 단계"; phase_z2_mapper.py:519/529 2 -- docstring examples; phase_z2_retry.py:59 1 -- docstring). Per-file count sum = 20 + 11 = 31, matching the live total. |
PASS for the audit scope -- 0 closed-issue (#2-#18 + #45-#49) introduces new sample-specific hardcoded BIM/재구성/건설산업 string literals into runtime code paths. All 11 Phase Z hits are docstring/taxonomy/self-test fixtures, none injected into runtime contracts. Legacy 20 hits are out of audit window. Recorded as Section 10 follow-up candidate F-4 for future cleanup (doc-only, optional). |
| G4 | grep -E 'height\s*=\s*720|aspect\s*=\s*0\.5' src/ -- magic literal pinning |
0 hits | 0 | none | PASS |
| G5 | sample paths come from CLI args / config, not hardcoded | sample-agnostic | 4 occurrences across 2 files (src/block_assembler.py:1390/1393 + src/image_utils.py:62/65) |
all 4 hits use samples/mdx_batch as one of several generic asset search directories alongside samples/images (image asset discovery fallback). The directory is treated as a discovery namespace, not as a path to a specific MDX file. CLI entry (src/phase_z2_pipeline.py:4861) takes mdx_path as positional arg -- no hardcoded MDX path on the runtime entry. |
PASS -- sample-agnostic asset discovery default; not a per-sample pin. |
| G6 | tests/ : sample-specific fixtures only under tests/fixtures/, not in production pipeline |
fixtures isolated | tests/fixtures/ directory does not exist; closest hits = tests/phase_z2/test_pz2_vu_integration.py:6, 82 referencing samples/mdx_batch/02.mdx as smoke-coverage MDX |
the references in test_pz2_vu_integration.py are inside a verification-utility integration test (#16 IMP-16 scope). The test file is named with the test prefix and lives in tests/phase_z2/, so pytest discovery treats it as a test, not as a production module. No production pipeline file imports a sample MDX path literal. |
PASS WITH NOTE -- no tests/fixtures/ directory exists today; the existing integration tests already keep sample references inside tests/phase_z2/test_*.py, which discharges the spirit of the rule. Optional follow-up: formalize a tests/fixtures/ directory if sample inventory grows. Recorded as Section 10 follow-up candidate F-5 (low priority, doc-only). |
8.2 Anti-hardcoding verdict
- 4 patterns PASS cleanly with 0 hits (G1, G2, G4) and 1 PASS with sample-agnostic hits (G5).
- 1 pattern PASS-for-audit-scope with classification (G3) : 11 Phase Z hits are all docstrings/taxonomy/self-test fixtures; 20 legacy hits are out of the 22-closed-issue audit window. Per-file counts sum to 31, matching the live grep total. No closed issue introduces new hardcoded sample text into a runtime code path.
- 1 pattern PASS WITH NOTE (G6) :
tests/fixtures/directory not yet established; existing integration test references stay insidetests/phase_z2/. Already aligned with the spirit of the rule. - 0 Blocker findings in Section 8.
- Cross-axis : the F-4 / F-5 follow-up candidates are doc-only optional cleanup; they do not alter any closed-issue contract.
Section 9. Final decision
Decision : CONDITIONAL GO for #19.
9.1 Summary across all 4 audit axes + supporting sections
| section | axis | Blocker | Warning | OK | follow-up candidates |
|---|---|---|---|---|---|
| §3 | Axis 1 -- scope myopia | 0 | 5 (#6 #12 #15 #46 #49) |
17 | none Blocker; warnings are blast-radius + administrative drift |
| §4 + MATRIX.md | Axis 2 -- 22 x 22 pipeline matrix | 0 | (9 hotspot steps, 2 expected-empty cols) | 22 issues mapped | none Blocker; hotspots match expected Step 14 / 21 attention |
| §5 | Axis 3 -- cross-issue conflict (6 invariants) | 0 | 0 | 6 categories AGREE | F-1 (body cites mapper.py; live producer is classifier.py for fit_classification); F-2 (13 family templates on disk vs. 11 tracked / contracted -- 2 WIP outside any closed issue) |
| §6 | Axis 4 -- backlog vs code reality | 0 | -- | 1 AGREE, 16 BACKLOG_STALE (doc drift), 5 NO_BACKLOG_ROW (by design for #45-#49) |
F-3 (backlog status sweep : flip 15 rows pending -> implemented, 1 row pending -> documented (deferred) for IMP-17, footnote IMP-15 row with 5 children) |
| §7 | representative runs (03.mdx + 04.mdx) | 0 | -- | both runs visual_check_passed = True; debug.json schema stable; 04.mdx PARTIAL_COVERAGE is composition-planner side (no audit-window contract conflict) | none new |
| §8 | grep checklist (6 patterns from issue body) | 0 | -- | G1/G2/G4/G5 PASS; G3/G6 PASS WITH NOTE | F-4 (legacy Phase R'/Q BIM literals -- optional cleanup); F-5 (formalize tests/fixtures/ -- optional) |
| §2 | baseline pytest | -- | -- | 303 passed BEFORE + 303 passed AFTER audit | none |
9.2 Blocker tally
- 0 Blocker findings across all four axes and all supporting sections.
- 5 Warning rows in §3 are about blast radius (
#6 #12), administrative commit-label drift (#46), and parent/child close-timestamp anomaly (#15 #49). None of them indicate broken code contracts. - All BACKLOG_STALE rows in §6 are documentation drift, not implementation absence. Live grep on
src/**confirms each closed issue is wired (or carved-out as designed for#17 #18). - 5 follow-up candidates (F-1 .. F-5) are all doc-only. None require source code changes.
9.3 Why CONDITIONAL GO, not unconditional GO
Audit found zero Blocker, but the conditions for upgrading to unconditional GO are not met because:
- F-3 (backlog sweep) is the largest doc-drift surface (16 of 22 audited rows mislabeled). Issue #19 will read the backlog when scoping next-step coverage; running #19 against a stale backlog risks a planner who treats already-implemented features as still pending. The F-3 follow-up should be filed and merged before -- or at minimum in parallel with -- #19 Stage 2 planning.
- F-2 (family template count drift) matters if #19 touches the catalog /
frame_contracts.yaml(likely). The audit confirms 11 tracked entries are consistent today, but #19 should reconcile the 2 WIP files (app_sw_package_vs_solution.html,pre_construction_model_info_stacked.html) before adding any new family templates. - F-1 (record-keeping for invariant C3 producer file path) -- a small but real mismatch between the issue body wording (
src/phase_z2_mapper.py) and the live producer (src/phase_z2_classifier.py). Should be fixed in the audit charter / spec doc before the next integration audit so future audits do not repeat the same drift check.
F-4 / F-5 are optional and do not gate #19.
9.4 Conditions to satisfy for #19 progression
- File F-1 / F-2 / F-3 as Section 10 follow-up issues (text-only drafts produced in u6).
- F-3 backlog sweep should land before #19 Stage 2 (so #19 plans against accurate status).
- F-2 family template reconciliation should land before #19 introduces new family templates (whichever comes first).
- F-1 is a one-line spec-doc edit, can land any time before the next INTEGRATION-AUDIT issue is opened.
9.5 Decision sentence
Issue #19 is approved for entry under CONDITIONAL GO, with the explicit dependency that follow-up F-3 (backlog status sweep) must land before #19 Stage 2 planning consumes the backlog, and F-2 (family template reconciliation) must land before any #19 work that extends the catalog. No production source code change is required from this audit. Pytest baseline stable (303 passed BEFORE + AFTER).
Section 10. Follow-up issue drafts (text-only, not auto-posted)
Scope rule (Stage 2 u6 contract) : per-draft fields = title + source_axis (1-4) + scope (what files / what change) + evidence_link (REPORT section that produced the finding). No Gitea post. Final disposition of each candidate is the orchestrator / human triage decision after #50 closes; this REPORT only records the audit-side text.
Five candidates were produced by Axes 1-4. F-3 + F-2 + F-1 are blocking conditions for upgrading §9 CONDITIONAL GO -> unconditional GO for #19; F-4 + F-5 are optional housekeeping. None require source-code changes inside this audit.
10.1 F-1 -- audit charter record-keeping : invariant C3 producer file path -- RESOLVED via IMP-53 (2026-05-19)
- title :
[AUDIT-CHARTER-FIX] invariant C3 (fit_classification) producer cited as src/phase_z2_mapper.py; live producer is src/phase_z2_classifier.py - source_axis : Axis 3 (cross-issue conflict, invariant category C3) -- recorded in §5.2 C3 row + §5.4 follow-up bullet F-1.
- scope :
- one-line fix in any future INTEGRATION-AUDIT-* issue body or in
docs/architecture/PHASE-Z-PIPELINE-OVERVIEW.mdif it cites the wrong file forfit_classificationproducer. - replace text
src/phase_z2_mapper.py->src/phase_z2_classifier.pyonly in the context offit_classificationinvariant (mapper.py legitimately owns slot payload and registries, so do not blanket-rename). - update audit charter template (if one exists) so the next integration audit does not repeat the drift check.
- one-line fix in any future INTEGRATION-AUDIT-* issue body or in
- scope-lock : doc-only, zero
src/**/templates/**/tests/**edits. - evidence_link :
- REPORT §5.2 row C3 (issue body wording vs. live producer).
- REPORT §5.4 follow-up bullet F-1.
- Live producer site :
src/phase_z2_classifier.py:495-497(return dict withvisual_check_passed,classifications,summary,categories_seen,unclassified_signals,placement_diagnostics).
- priority / gating : low priority on its own; required for charter cleanliness; not a blocker for #19 Stage 2.
10.2 F-2 -- family template count reconciliation : 11 tracked / 11 contracted / 13 on disk -- RESOLVED via #52 (option c, 2026-05-19)
- title :
[FAMILY-TEMPLATE-RECONCILE] templates/phase_z2/families/ has 13 .html files on disk but 11 tracked + 11 frame_contracts entries; 2 WIP files (app_sw_package_vs_solution.html, pre_construction_model_info_stacked.html) untracked - source_axis : Axis 3 (invariant category C6 template / catalog / frame count) -- recorded in §5.2 C6 row + §5.4 follow-up bullet F-2 + §6.3 Axis 4 cross-axis consistency bullet.
- scope :
- decide whether the 2 untracked WIP family templates (
app_sw_package_vs_solution.html,pre_construction_model_info_stacked.html) should be (a) tracked + contracted (add toframe_contracts.yaml, add togit ls-files), (b) removed if abandoned, or (c) explicitly noted as in-progress with a parent issue. - reconcile the IMP-18 SVG-gap report doc citation
families/*.html (13)against whichever decision is chosen (so the doc count matches code reality).
- decide whether the 2 untracked WIP family templates (
- scope-lock : touches
templates/phase_z2/families/*.html,templates/phase_z2/catalog/frame_contracts.yaml,docs/architecture/IMP-18-SVG-GAP-REPORT.md. Must NOT be folded into #19 silently: any catalog growth needs a dedicated issue per feedback_workflow_atomicity_rules (one commit = one decision). - evidence_link :
- REPORT §5.2 row C6 ("AGREE FOR TRACKED BASELINE -- 11 tracked family templates <-> 11 frame_contracts entries").
- REPORT §5.5 row "C6 family templates -- on disk" (
ls templates/phase_z2/families/*.html= 13). - REPORT §6.3 Axis 4 cross-axis consistency bullet (matches IMP-04 evidence).
- priority / gating : must land before #19 introduces any new family template (per §9.3 condition 2). Until #19's catalog touch surface is known, this can be filed independently.
- resolution : option (c) -- 2 WIP family templates explicitly noted as in-progress and tracked outside
frame_contracts.yaml(RESOLVED via Gitea #52, 2026-05-19) :- WIP allowlist :
templates/phase_z2/families/_WIP_FILES.md(added by #52 u1) -- names both files with Figma frame IDs (app_sw_package_vs_solution.html-> frame 23 /1171281203;pre_construction_model_info_stacked.html-> frame 9 /1171281180) and explicit "not inframe_contracts.yaml, not in runtime matcher set" status; promote / remove gated on Gitea #42. - IMP-18 doc reconciled :
docs/architecture/IMP-18-SVG-GAP-REPORT.mdL28 + L30 + L51 corrected from disk-only "13 files" / "15 partials" wording to "11 contracted + 2 WIP untracked = 13 on disk" (#52 u2) -- runtime matcher consumes the contracted set only; doc / tracked / contracted surfaces agree at 11 active. - baseline guard (planned by #52 u4) :
tests/test_family_contract_baseline.pywill enforce tracked families <->frame_contracts.yaml1:1 set-equality modulo WIP allowlist parsed from_WIP_FILES.md; future drift (#42 or otherwise) fails CI. - tracked baseline (11 contracted families <-> 11
frame_contracts.yamlentries) unchanged; no contract entries added or removed; no runtime matcher mutation; C6 invariant remains AGREE for the closed-issue audit scope. - F-2 closed-by-#52 under feedback_workflow_atomicity_rules (one commit = one decision unit), without re-opening any §5 C-invariant or §6.3 Axis 4 conclusion. #19 catalog-touch gate (per §9.3 condition 2) is now satisfied for the current 11/11 baseline; any #19 / #42 catalog growth must reconcile the WIP allowlist before merge.
- WIP allowlist :
10.3 F-3 -- backlog status sweep : 15 rows pending->implemented + 1 row pending->documented(deferred) + IMP-15 children footnote
- title :
[BACKLOG-STATUS-SWEEP] PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md has 16 of 22 audited rows mislabeled as pending; flip 15 to implemented, 1 (IMP-17) to documented (deferred), footnote IMP-15 with 5 execution children - source_axis : Axis 4 (backlog vs code reality) -- recorded in §6.1 headline finding + §6.2 22-row matrix + §6.3 follow-up candidate F-3 + §9.1 §6 row + §9.3 condition 1.
- scope :
- 15 rows to flip
pending->implemented: IMP-02, IMP-03, IMP-04, IMP-05, IMP-06, IMP-07, IMP-08, IMP-09, IMP-10, IMP-11, IMP-12, IMP-13, IMP-14, IMP-15 (parent), IMP-16. - 1 row to flip
pending->documented (deferred): IMP-17 (status-class shift; runtime AI = 0, 3-cond AND gate closed; matches §6.2 row 16). - IMP-15 row : add inline footnote citing the 5 execution children commits
#45 (e9b3d2e),#46 (2827622),#47 (535c484),#48 (614c533),#49 (verification-only, re-uses 614c533). Either as a footnote on the IMP-15 row or as 5 child stub rows -- pick one and apply consistently. - IMP-18 row : leave as
documented(already AGREE per §6.2 row 17).
- 15 rows to flip
- scope-lock : single-file edit to
docs/architecture/PHASE-Z-IMPLEMENTATION-ISSUE-BACKLOG.md. Doc-only, zerosrc/**/templates/**/tests/**edits. Must be filed as a separate Gitea issue with its own Stage 5 commit (not merged into #19 or any other improvement issue). - evidence_link :
- REPORT §6.1 headline finding (16 BACKLOG_STALE + 5 NO_BACKLOG_ROW + 1 AGREE = 22).
- REPORT §6.2 22-row matrix (per-row grep evidence + commit SHAs).
- REPORT §6.3 follow-up reference.
- REPORT §9.1 / §9.3 condition 1 ("F-3 backlog sweep should land before #19 Stage 2 planning consumes the backlog").
- priority / gating : highest of the 5 candidates. Must land before #19 Stage 2 planning (per §9.3 condition 1) so that #19's planner reads accurate
implemented/documented (deferred)status and does not treat already-wired features as still pending.
10.4 F-4 -- legacy Phase R' / Q sample-literal cleanup (OPTIONAL)
- title :
[LEGACY-LITERAL-CLEANUP] 20 hits of 재구성 / 건설산업 DX / BIM across 10 legacy Phase R'/Q files (block_assembler_b2.py, block_matcher_tfidf.py, block_reference.py, content_editor.py, design_director.py, design_tokens.py, fit_verifier.py, frame_extractor.py, kei_client.py, pipeline.py) - source_axis : Axis-supporting Section 8 (anti-hardcoding grep checklist) -- recorded in §8.1 row G3 + §8.2 third bullet + §9.1 §8 row.
- scope :
- per-file review of the 20 legacy hits to determine which are docstrings / comments (keep), legacy taxonomy (keep with annotation), or true sample-literal pins (remove or generalize).
- per-file counts to triage :
block_assembler_b2.py1,block_matcher_tfidf.py1,block_reference.py3,content_editor.py3,design_director.py2,design_tokens.py1,fit_verifier.py1,frame_extractor.py1,kei_client.py4,pipeline.py3. - NOT touching the 11 Phase Z hits (
phase_z2_content_extractor.py7 self-test data,phase_z2_failure_router.py:123taxonomy,phase_z2_mapper.py:519/529docstring examples,phase_z2_retry.py:59docstring) -- those passed audit verdict G3.
- scope-lock : potentially touches legacy
src/**files NOT in the Phase Z 22-step pipeline. Must be filed as a deliberate cleanup issue with its own scope-lock. If any file flagged here turns out to be on a live Phase Z code path on review, demote the candidate or split it. - evidence_link :
- REPORT §8.1 row G3 (per-file count breakdown, audit date 2026-05-19).
- REPORT §8.2 third bullet (20 legacy + 11 Phase Z = 31, reconciliation).
- Raw grep output :
D:\ad-hoc\kei\design_agent\.orchestrator\tmp\50_grep_checklist_raw.txt.
- priority / gating : optional, low priority, doc-only follow-up note. Does NOT gate #19; §8 verdict already PASS for audit scope. Recorded for completeness so future audits do not re-discover the same 20-hit baseline.
10.5 F-5 -- formalize tests/fixtures/ directory (OPTIONAL)
- title :
[TESTS-FIXTURES-FORMALIZE] tests/fixtures/ directory does not exist; sample MDX references currently live in tests/phase_z2/test_pz2_vu_integration.py - source_axis : Axis-supporting Section 8 (anti-hardcoding grep checklist G6) -- recorded in §8.1 row G6 + §8.2 fourth bullet.
- scope :
- if-and-only-if sample inventory grows beyond what fits inside
tests/phase_z2/test_*.pyfiles, formalize atests/fixtures/directory holding sample-specific fixtures. - migrate existing
samples/mdx_batch/02.mdxreferences intests/phase_z2/test_pz2_vu_integration.py:6, 82only if migration is part of a broader test-fixture refactor (otherwise leave them as integration smoke). - update the issue-body rule wording to acknowledge that
tests/phase_z2/test_*.pyalready discharges the spirit of "no sample-specific fixtures in production pipeline".
- if-and-only-if sample inventory grows beyond what fits inside
- scope-lock : touches
tests/fixtures/(new directory if filed) + the cited test files. Must NOT be folded into any unrelated test refactor. - evidence_link :
- REPORT §8.1 row G6 verdict "PASS WITH NOTE".
- REPORT §8.2 fourth bullet (
tests/fixtures/not yet established).
- priority / gating : optional, very low priority. Filing is only justified when sample inventory grows; the current state is already aligned with the spirit of the rule.
10.5.1 F-5 docs-only resolution addendum (#54 Stage 3 u5, 2026-05-19)
Per issue #54 Stage 2 plan, F-5 is closed as docs-only; no root tests/fixtures/ directory is created in this work. The current fixture inventory does not justify migration, and the existing convention is sufficient. The convention is recorded here so future anti-hardcoding audits can distinguish fixture / test-only paths from production paths without re-discovering the §8 G6 PASS-WITH-NOTE baseline.
- Existing convention (DO NOT CHANGE) :
tests/phase_z2/fixtures/exists as a YAML regression fixture root (loaded bytests/phase_z2/test_fixtures_loader.py). Subdirectories present at audit time :tests/phase_z2/fixtures/build_layout_css/,tests/phase_z2/fixtures/retry_gate/. This is the canonical home for Phase Z regression fixtures. - Root
tests/fixtures/(ABSENT) : not created in #54. If a future change requires a non-Phase-Z, non-YAML fixture corpus (for example, multi-file MDX golden inputs that grow beyond whattests/phase_z2/test_*.pycan hold inline), the migration must be filed as its own Gitea issue with its own scope-lock per §10.5. - Allowed sample references :
samples/mdx_batch/**andsamples/mdx/**may be referenced fromtests/**(test-only paths) for integration smoke -- e.g. the existingsamples/mdx_batch/02.mdxreferences intests/phase_z2/test_pz2_vu_integration.py. These do not violate the §8 anti-hardcoding rule because the spirit of the rule targets production pipeline code, not test runners. - Forbidden sample references : production pipeline code (
src/**runtime path) must NOT hardcode sample-specific MDX filenames or content (e.g.02.mdx,03.mdx, frame-specific labels keyed to a sample). The 20 legacy Phase R'/Q hits annotated under F-4 (#54 Stage 3 u1-u4) are intentional documented examples in docstrings / comments / glossary regex / sample-data dicts, not runtime input pins; they are out of scope for this rule by §10.4 verdict. - AI-isolation contract : this addendum is text-only. No production behavior change, no runtime sample-path mutation, no new fixture file. Compatible with PZ-1 (AI = 0 on normal path) and feedback_ai_isolation_contract.
- Cross-reference :
tests/CLAUDE.mdfixture convention note (#54 Stage 3 u5) mirrors the test-only / production rule split documented here.
10.6 Follow-up summary
| candidate | source axis | doc-only? | gates #19? | priority |
|---|---|---|---|---|
| F-1 audit-charter producer file path | Axis 3 (§5) | YES | NO | low (charter cleanup) |
| F-2 family template count reconcile | Axis 3 (§5) | NO -- touches templates / catalog / docs | gate IF #19 extends catalog | medium |
| F-3 backlog status sweep | Axis 4 (§6) | YES | YES -- must land before #19 Stage 2 plan | highest |
| F-4 legacy R'/Q literal cleanup | §8 (anti-hardcoding) | NO -- legacy src/ touch surface | NO | low (optional) |
| F-5 tests/fixtures/ formalize | §8 (anti-hardcoding) | NO -- tests/ migration | NO | very low (optional) |
- Counts : 5 candidates total. 3 are blocking conditions for upgrading §9 CONDITIONAL GO to unconditional GO for #19 (F-3 hard-gates, F-2 conditional-gates on catalog touch, F-1 nice-to-have before next audit). 2 are optional housekeeping (F-4, F-5).
- Compliance with Stage 2 u6 contract : per-draft fields (title / source_axis / scope / evidence_link) populated for each of F-1 .. F-5. Zero auto-posts -- this section is text-only. Filing decisions = orchestrator / human after #50 closes.
- AI-isolation contract : none of the 5 follow-up candidates require AI on a normal path. F-2 / F-4 / F-5 are scope decisions to be made by a human reviewer. Compatible with feedback_ai_isolation_contract and PZ-1 (AI = 0 on normal path).