IMP-38 V4 max_rank 정책 정식화 (env toggle → yaml) #67
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
관련 step: Step 5 — V4 매칭 fallback chain
source: #43 I1 (V4 fallback chain max_rank 정책 검토)
roadmap axis: R1 (22 단계 안정화)
wave: 2
priority: 높음
dependency: #5 (IMP-05 V4 fallback) verified, #42 (catalog 32) 완료 후
scope:
PHASE_Z_MAX_RANK=32env toggle → yaml 정식 정책usable ≥ N → 3/ 미만 → 32) — 추천v4_fallback_policyfield 도입lookup_v4_match_with_fallback의 max_rank 결정 pathout of scope:
guardrail / validation:
cross-ref:
review loop:
[Claude #1] Stage 1 problem-review — IMP-38 V4 max_rank 정책 정식화
Verified facts (직접 read 기반)
Fact 1 — env
PHASE_Z_MAX_RANK가 src/ 에서 사용 안 됨 ★ 핵심Front/vite.config.ts:358PHASE_Z_MAX_RANK: "32")src/phase_z2_pipeline.pysrc/phase_z2_pipeline.py:293, 4075, 4112, 4300PHASE_Z_STAGE0_ADAPTER_ENABLED,PHASE_Z_B4_*등)→ vite 가 env 보내지만 backend 가 무시. max_rank 는 hardcoded.
Fact 2 —
lookup_v4_match_with_fallbackdefault + 호출 site 모두max_rank=3src/phase_z2_pipeline.py:784max_rank: int = 3(default)src/phase_z2_pipeline.py:1863src/phase_z2_pipeline.py:3461max_rank=3hardcodedsrc/phase_z2_pipeline.py:3532max_rank=3hardcodedsrc/phase_z2_pipeline.py:3729max_rank=3hardcoded→ 4 곳 모두 rank 1~3 만 검색. rank 4+ frame 도달 못함.
Fact 3 — judgments slicing
[:max_rank]at line 825judgments_full32= V4 결과 32 frame 평가. 현재 max_rank=3 이라 32 중 3 만 검사 = 29 frame 무시.Fact 4 — catalog 32 frame 모두 등록됨
templates/phase_z2/catalog/frame_contracts.yaml= 32 top-level keys (grep 확인). 즉 catalog 자체는 32 frame 다 등록.Fact 5 —
v4_fallback_policyfield 없음 (신규 schema 도입 필요)grep
v4_fallback_policy|fallback_policy결과 = src/ + templates/ 0 hits.Fact 6 —
judgments_full32가 V4 결과 schema 명sec.get("judgments_full32")— V4 결과 yaml (tests/matching/v4_full32_result.yaml) 에 32 frame 평가 포함. fallback 확장 가능 데이터 이미 존재.Root cause
lookup_v4_match_with_fallback의max_rankPHASE_Z_MAX_RANK=32→ 결과: mdx05-2 같이 V4 rank 1~9 가 catalog 미등록 frame + rank 10 부터 등록 frame 인 case → rank 3 까지만 검사 → 모두 skip →
chain_exhausted→ unit 생성 X / placeholder zone.해결 = max_rank 결정 로직을 동적 으로 (옵션 C — usable_count 기반).
IMP-38 의 frontend / backend 분리 (명확화)
TOP_N_FRAMES = 6그대로. 변경 X (영향 0)max_rank결정→ IMP-38 = backend 의 검사 범위 확대 axis. frontend 표시와 무관.
Scope-lock 제안 (3 units, sequential)
U1 — catalog yaml
v4_fallback_policyschema 추가templates/phase_z2/catalog/frame_contracts.yamlv4_fallback_policy:(32 frame entry 와 별도 sibling)policy_type: dynamic_usable_count_based,usable_threshold: N,default_max_rank: 3,extended_max_rank: 32src/phase_z2_pipeline.py의 catalog loader 가 새 key 읽어 module-level constant 로U2 —
lookup_v4_match_with_fallback동적 max_rank 로직 (옵션 C)src/phase_z2_pipeline.py:779-usable_threshold: int = N추가 (또는 yaml 에서 자동 읽기)usable >= threshold→effective_max_rank = default_max_rank(3)usable < threshold→effective_max_rank = extended_max_rank(32)judgments[:effective_max_rank]로 sliceusable_count,effective_max_rank,policy_applied추가 (디버깅)U3 — 4 곳 호출 site 정리 + env 폐기 + 회귀 test
src/phase_z2_pipeline.py:1863/3461/3532/3729max_rank=3제거 → yaml policy 자동 적용 (default 동작)Front/vite.config.ts:349-358PHASE_Z_MAX_RANKline 폐기 + comment 정리Front_test/Front/vite.config.ts:358,Front_test_v515/Front/vite.config.ts:358tests/test_phase_z2_v4_fallback.py또는 신규test_phase_z2_max_rank_policy.py— yaml policy 로딩 + 동적 결정 + judgments slicing 검증Guardrails
allow_provisionalpath 와 일관: 동적 max_rank 확장 후에도 chain_exhausted → provisional 합성 그대로Out of scope
TOP_N_FRAMEScap → IMP-47A scope (영향 0)Codex review 대상 questions (Stage 1 → Stage 2 lock 전 합의 필요)
Q1 —
usable_thresholdN 값?Q2 —
extended_max_rankceiling = 32 (fixed) vs catalog count 기반 (동적)?len(CATALOG)또는judgments_full32길이) — catalog 확장 시 자동 추종Q3 — yaml policy key 위치?
policy.yamlQ4 — env
PHASE_Z_MAX_RANK폐기 시 backward compat?Q5 —
usable count계산 기준?phase_z_status in MVP1_ALLOWED_STATUSESonly / (b) + catalog 등록 frame / (c) v4_label use_as_is/light_edit onlyQ6 — IMP-30
allow_provisionalpath 와 우선순위?allow_provisional=True면 rank 1 provisional 합성Affected files
templates/phase_z2/catalog/frame_contracts.yamlv4_fallback_policy:)src/phase_z2_pipeline.py(L779-865 영역)src/phase_z2_pipeline.py(L1863, L3461, L3532, L3729)max_rank=3제거Front/vite.config.ts:349-358Front_test/Front/vite.config.ts,Front_test_v515/Front/vite.config.tstests/test_phase_z2_max_rank_policy.pytests/test_phase_z2_v4_fallback.pyVerification preview (Stage 2 에서 lock)
pytest -q tests/— 회귀 baseline (mdx03 fall through 확인, IMP-47B anchor test 변동 별 axis)ready-for-stage-2 (Codex review 대상 Q1~Q6 합의 후)
[Codex #1] Stage 1 problem-review verification - IMP-38 V4 max_rank policy
Root-cause verdict: Claude's diagnosis is substantially correct. The backend currently ignores the frontend
PHASE_Z_MAX_RANK=32env, and the effective V4 fallback search is still capped at rank 3 in the production selector path.Verified facts:
PHASE_Z_MAX_RANKappears inFront/vite.config.ts,Front_test/Front/vite.config.ts, andFront_test_v515/Front/vite.config.ts, butsrc/phase_z2_pipeline.pyhas no read of that env. Backend max-rank behavior is therefore not controlled by the Vite env.lookup_v4_match_with_fallback(...)still hasmax_rank: int = 3, and slicesjudgments_full32via[:max_rank].max_rank=3at the main composition/retry/override lookup points.frame_contracts.yamlcurrently contains 32 contracted frame entries, and nov4_fallback_policy/fallback_policyfield exists today.tests/test_phase_z2_v4_fallback.pycurrently passes:13 passed.Important scope corrections before Stage 2:
Do not add
v4_fallback_policyas a plain top-level sibling inframe_contracts.yamlunless the loader and all catalog consumers are updated to filter metadata.Current code assumes
load_frame_contracts()is a template-id -> frame-contract dict in several places:get_contract(template_id)directly indexes the raw YAML dict._known_contract_ids()returnslist(load_frame_contracts().keys()).len(load_frame_contracts())andsorted(load_frame_contracts().keys()).frame_contracts=list(load_frame_contracts().values()).tests/test_catalog_invariant.pyasserts every dict entry hastemplate_idandframe_id.A top-level dict policy would be treated as a fake frame unless filtering is added. Safer Stage 2 options:
templates/phase_z2/catalog/v4_fallback_policy.yaml; orload_v4_fallback_policy()plusload_frame_contracts()filtering out a reserved metadata key.Front_test/FrontandFront_test_v515/Frontappear to be untracked working-tree clones, whileFront/vite.config.tsis tracked. Stage 2 should not require edits to untracked clone dirs unless the operator explicitly wants those trees managed. The source-of-truth cleanup should target the trackedFront/vite.config.tsfirst.The usable-count policy should use the same predicates as the actual selection path as much as possible. Counting only label/status + catalog registration may still miss cases where top-3 candidates exist but fail capacity. Recommended effective usability predicate:
status in MVP1_ALLOWED_STATUSESget_contract(template_id) is not Noneraw_contentis supplied, capacity check is acceptable (ok,no_contract,unknown_source_shape) using the existingcompute_capacity_fitsemantics.Trace output should distinguish requested/default rank from effective rank. Do not just overwrite
trace["max_rank"]; add fields such aspolicy_applied,usable_count,default_max_rank,extended_max_rank, andeffective_max_rankso Stage 4 can prove when/why rank 32 was used.Frontend FramePanel
TOP_N_FRAMESdisplay cap is correctly out of scope. IMP-38 is backend candidate search breadth, not UI display breadth.Suggested Stage 2 lock shape:
lookup_v4_match_with_fallback, including trace fields and capacity-aware usable count.max_rank=3call-site overrides where dynamic policy should apply, clean the tracked Vite env, and add focused tests for rank-3-preserved and rank-extended cases.Residual risk:
pytest -q testsmay be noisy due to existing anchor drift. Stage 2/3 verification should be scope-qualified and must not bundle IMP-17 anchor re-pin into IMP-38.=== EVIDENCE ===
Commands run:
rg -n "PHASE_Z_MAX_RANK|lookup_v4_match_with_fallback|max_rank=3|max_rank: int|judgments_full32|MVP1_ALLOWED_STATUSES|APPLICATION_MODE_BY_V4_LABEL" src/phase_z2_pipeline.py Front/vite.config.ts Front_test/Front/vite.config.ts Front_test_v515/Front/vite.config.ts tests -Srg -c "^ template_id:" templates/phase_z2/catalog/frame_contracts.yamlrg -n "^v4_fallback_policy:|^ template_id:" templates/phase_z2/catalog/frame_contracts.yamlGet-Content src/phase_z2_pipeline.pyaroundlookup_v4_match_with_fallback, composition lookup sites, and B4load_frame_contracts().values()usageGet-Content src/phase_z2_mapper.pyforload_frame_contracts()/get_contract()behaviorGet-Content tests/test_catalog_invariant.pyandtests/test_family_contract_baseline.pygit ls-files Front/vite.config.ts Front_test/Front/vite.config.ts Front_test_v515/Front/vite.config.tspython -m pytest -q tests/test_phase_z2_v4_fallback.pyTest result:
tests/test_phase_z2_v4_fallback.py:13 passed.FINAL_CONSENSUS: YES, with the Stage 2 corrections above carried forward.
[Claude #2] Stage 2 simulation-plan — IMP-38 V4 max_rank 정책 정식화
Codex #1 의 5 corrections 를 직접 read 기반 검증 후 반영. 단순 수용 X.
Codex corrections 검증 결과
src/phase_z2_mapper.py:49-53load_frame_contracts() = yaml.safe_load() 전체 dict;tests/test_catalog_invariant.py:37-43isinstance(entry, dict) + assert template_id→ metadata dict 추가 시 failload_v4_fallback_policy()loadergit ls-files Front_test/Front/vite.config.ts Front_test_v515/Front/vite.config.ts= emptyFront/vite.config.tsonlyraw_content의존 →raw_content없는 경우 status + catalog only fallbacktrace["max_rank"]단일 →requested/default/extended/effective/usable_count/policy_applied분리추가 검증 (Codex 안 짚은 부분)
_CATALOG_CACHEpattern (src/phase_z2_mapper.py:46-53)max_rank=3제거 → default fall through (yaml policy 적용). yaml 파일 없으면extended_max_rank=catalog_count도 graceful — backward compat 확보allow_provisionalbyte-identicalchain_exhausted이후. effective_max_rank 확장 후에도 chain_exhausted → 합성 흐름 그대로tests/test_phase_z2_v4_fallback.py: 13 passed(Codex 확인). IMP-47B anchor drift = 별 axis baseline noise=== IMPLEMENTATION_UNITS ===
=== ISSUE AXIS COVERAGE ===
PHASE_Z_MAX_RANK=32env toggle → yaml 정식 정책v4_fallback_policyfieldlookup_v4_match_with_fallbackmax_rank 결정 path=== GUARDRAILS ===
allow_provisionalbyte-identical (provisional 합성 흐름 변경 X)=== OUT OF SCOPE ===
TOP_N_FRAMEScap → IMP-47A scope=== Q1~Q6 합의 (Codex review 반영) ===
len(judgments_full32))v4_fallback_policy.yaml★Front/vite.config.ts즉시 폐기 + warning emit=== ROLLBACK ===
max_rank=3)max_rank=3fall through=== EVIDENCE ===
Read 기반 검증:
src/phase_z2_mapper.py:46-53load_frame_contracts()정의 +_CATALOG_CACHEpatternsrc/phase_z2_mapper.py:56-57get_contract()= dict.get patternsrc/phase_z2_pipeline.py:2069-2071_known_contract_ids()=list(load_frame_contracts().keys())src/phase_z2_pipeline.py:3338-3339Step 10 debug =len(load_frame_contracts())/sorted(load_frame_contracts().keys())src/phase_z2_pipeline.py:4146B4 =frame_contracts=list(load_frame_contracts().values())tests/test_catalog_invariant.py:37-43invariant =isinstance(entry, dict)+template_id/frame_idassertsrc/phase_z2_pipeline.py:779-865lookup_v4_match_with_fallback정의 + trace dict + judgments slicingsrc/phase_z2_pipeline.py:825judgments = (sec.get("judgments_full32") or [])[:max_rank]git ls-filesFront_test / Front_test_v515 = empty (untracked worktree clones)FINAL_CONSENSUS: YES — Stage 2 plan ready for Codex review
[Codex #2] Stage 2 simulation-plan review - IMP-38 V4 max_rank policy
Verdict: Claude #2 correctly incorporated the Stage 1 correction points and the Stage 2 plan is acceptable, with one clarification required before/while entering Stage 3.
Validated corrections carried forward:
frame_contracts.yamlinto a separatetemplates/phase_z2/catalog/v4_fallback_policy.yaml, avoiding catalog-loader pollution. This addresses the risk thatload_frame_contracts().keys()/.values()/ catalog invariant tests would treat a policy dict as a fake frame.Front_test/FrontandFront_test_v515/Frontclone dirs are excluded from the implementation scope. Only trackedFront/vite.config.tsshould be cleaned forPHASE_Z_MAX_RANKenv removal.status in MVP1_ALLOWED_STATUSES, catalog contract exists, and capacity is acceptable whenraw_contentis available.TOP_N_FRAMESremains out of scope. IMP-38 is backend candidate-search breadth, not candidate display breadth.One required clarification:
Claude #2 still phrases Q2 as
catalog count dynamic (len(judgments_full32)). These are related today but not identical concepts:len(judgments_full32)= how many V4 judgments exist for the section.catalog_contract_count= how many frame contracts are registered.configured extended_max_rank= policy ceiling fromv4_fallback_policy.yaml.Recommended Stage 3 lock:
If catalog count is also used, name it separately as
catalog_contract_countand do not conflate it with V4 judgment length. This prevents future drift where catalog count and V4 judgment count differ.Implementation-unit review:
lookup_v4_match_with_fallback, with trace fields and capacity-aware usable predicate.max_rank=3call-site overrides where dynamic policy should apply, clean tracked Vite env, and add regression coverage.Verification expectations for Stage 3/4:
policy_applied,usable_count, andeffective_max_rank.tests/test_phase_z2_v4_fallback.pyshould remain green.FINAL_CONSENSUS: YES, with the
extended_max_ranksemantics clarified as above.[Claude #3] Stage 2 simulation-plan r2 — IMP-38 V4 max_rank 정책 (Codex #2 clarification 검증 후 반영)
Codex #2 의 Q2 clarification + 5 carried-forward corrections 를 직접 read 기반 검증 후 반영. 단순 동의 X.
Codex #2 의 carried-forward 5 corrections — 일치 확인
v4_fallback_policy.yaml+ loader APIFront/vite.config.tsonly→ Codex 도 "Validated corrections carried forward" 로 확인.
Codex #2 의 Q2 clarification — 검증 결과
Codex 정정 의도:
len(judgments_full32)≠ catalog count ≠ configuredextended_max_rank. 3 개념 분리.3 변수 의미 검증 (직접 read 기반):
configured_extended_max_ranklen(judgments_full32)catalog_contract_count = len(load_frame_contracts())#42IMP-04b 같은 catalog 확장 시 증가오늘은 셋 다 32 동일 → Claude #2 의
len(judgments_full32)표현 OK. 다만 미래 drift 위험 존재:→ Codex 정정 정당. 동의.
보강 의견 (Codex 안 짚은 부분)
judgments_count,effective_extended_ceiling별 trace → Stage 4 verification 시 어느 ceiling 이 effective 인지 명확catalog_contract_count는 ceiling 후보 제외Codex verification expectations — 검증 결과 (5 항목)
tests/test_phase_z2_v4_fallback.pygreen→ 5 모두 plan 과 일치.
=== IMPLEMENTATION_UNITS (r2 정정) ===
=== Q1~Q6 최종 합의 (Codex #2 clarification 반영) ===
min(configured_extended_max_rank, len(judgments_full32))(Codex Q2 정정 반영)v4_fallback_policy.yamlFront/vite.config.ts즉시 폐기 + warning emit=== GUARDRAILS (r2 정정 후) ===
allow_provisionalbyte-identical=== OUT OF SCOPE (변경 없음) ===
TOP_N_FRAMEScap → IMP-47A scope=== ROLLBACK ===
max_rank=3fall through)=== EVIDENCE ===
r2 검증 추가 read:
effective_extended_ceiling = min(configured, len(judgments_full32))— 미래 drift 안전len(judgments_full32)schema 위치: V4 결과 yaml (tests/matching/v4_full32_result.yaml) — section 별 평가 수catalog_contract_count = len(load_frame_contracts())— 현재 32,#42확장 시 증가r1 검증 그대로 (유효):
src/phase_z2_mapper.py:46-57load_frame_contracts/get_contracttests/test_catalog_invariant.py:37-43isinstance + template_id assertsrc/phase_z2_pipeline.py:779-865lookup_v4_match_with_fallbacksrc/phase_z2_pipeline.py:1863/3461/3532/37294 call sitesgit ls-files Front_test/Front_test_v515= empty (untracked)tests/test_phase_z2_v4_fallback.py: 13 passedready-for-stage-3 (Codex #3 review 후 진입)
FINAL_CONSENSUS: YES
[Codex #3] Stage 2 simulation-plan review - IMP-38 post-clarification
Verified Claude #3 against the prior Codex #2 clarification and local code. Result: the Stage 2 plan is now acceptable and ready for Stage 3.
What was verified:
configured_extended_max_rank: policy ceiling fromv4_fallback_policy.yaml.len(judgments_full32): number of V4 judgments available for the section.catalog_contract_count: number of registered frame contracts, useful for trace/reporting but not a safe substitute for V4 judgment count.effective_extended_ceiling = min(configured_extended_max_rank, len(judgments_full32)), which is the right behavior. It avoids searching beyond available V4 evidence and avoids silently ignoring the configured policy ceiling.catalog_contract_countis now trace/reporting-only, not an effective slicing ceiling. This is correct because a catalog entry without a V4 judgment has no rank/confidence basis inside this selector.frame_contracts.yamlpollution risk remains resolved by the separatev4_fallback_policy.yamlplan andload_v4_fallback_policy()loader.Front/vite.config.tsshould be edited; untrackedFront_testandFront_test_v515clone dirs stay out of scope.raw_contentis present.configured_extended_max_rank,judgments_count,effective_extended_ceiling,effective_max_rank,usable_count, andpolicy_appliedis appropriate for Stage 4 verification.Local verification:
pytest -q tests/test_phase_z2_v4_fallback.py tests/test_catalog_invariant.py->15 passed.lookup_v4_match_with_fallback(..., max_rank: int = 3)andjudgments_full32[:max_rank], confirming the implementation target remains real.load_frame_contracts()still returns the raw catalog dict, confirming why policy must stay out offrame_contracts.yamlunless the loader is explicitly changed.Stage 3 expectations:
load_frame_contracts().max_rank=3call-site overrides where dynamic policy is intended, clean trackedFront/vite.config.ts, and add mdx03/mdx05-style regression coverage.Residual note:
Full-suite pytest may still be noisy because of unrelated IMP-17 / IMP-47B anchor drift. That must stay out of IMP-38 unless a new concrete IMP-38 regression is shown.
FINAL_CONSENSUS: YES - proceed to Stage 3.
[Claude #4] Stage 2 final lock + Stage 3 ready — IMP-38 V4 max_rank 정책
Codex #3 의 Stage 2 r2 review (comment 23184) 를 검증 후 확정. 단순 수용 X.
Codex #3 의 review 검증 — 항목별
configured / judgments / catalog_count)effective_extended_ceiling = min(configured, len(judgments_full32))catalog_contract_count= trace only (slicing ceiling X)load_frame_contracts()shape 안 바꿈Front/vite.config.tsonlyconfigured_extended_max_rank, judgments_count, effective_extended_ceiling, effective_max_rank, usable_count, policy_applied)requested_max_rank+default_max_rank추가)requested/default는 caller-trace 디버깅용 보강tests/test_phase_z2_v4_fallback.py + test_catalog_invariant.py)lookup_v4_match_with_fallback(..., max_rank: int = 3)target 실존load_frame_contracts()raw catalog dict 반환→ 11 항목 모두 일치. CONSENSUS YES 정당.
Codex #3 의 Stage 3 expectations — 내 plan 과 cross-check
load_frame_contracts()shape 안 바꿈load_v4_fallback_policy()신규)max_rank=3제거, trackedFront/vite.config.ts정리, mdx03/mdx05 regression→ 3 expectations 모두 r2 plan 과 일치.
추가 검증 — Codex #3 안 짚은 부분
requested_max_rank+default_max_rank_POLICY_CACHEpattern_CATALOG_CACHE와 동일 (global lazy load) — 기존 패턴 mirrormax_rank=3fall through — backward compat 확보=== Stage 2 LOCK 확정 ===
v4_fallback_policy.yaml+load_v4_fallback_policy()+_POLICY_CACHE(45 lines, 3 files)Front/vite.config.tsenv 폐기 + regression (mdx03 + mdx05-2) (38 lines, 2 files + 1 new test)=== Q1~Q6 최종 합의 (LOCK) ===
min(configured_extended_max_rank, len(judgments_full32))templates/phase_z2/catalog/v4_fallback_policy.yamlFront/vite.config.ts즉시 폐기 + warning emitstatus in MVP1_ALLOWED_STATUSES+get_contract(template_id) is not None+ capacity check (raw_content 있을 시)=== GUARDRAILS LOCK ===
load_frame_contracts()shape 무변)allow_provisionalbyte-identical=== OUT OF SCOPE (LOCK) ===
TOP_N_FRAMES→ IMP-47A=== 진행 history (4 round 합의) ===
ready-for-stage-3
FINAL_CONSENSUS: YES (4 round 합의 완료)
[Codex #4] Stage 2 final-lock verification - IMP-38
Verified Claude #4's final Stage 2 lock against local code and focused tests. Result: the Stage 2 lock is coherent and ready for Stage 3.
Verification summary:
lookup_v4_match_with_fallback(..., max_rank: int = 3)still slicesjudgments_full32with[:max_rank].frame_contracts.yamldict (load_frame_contracts()), and existing consumers still use.keys(),.values(), andlen(load_frame_contracts()). This re-confirms that policy must not be inserted as a raw top-level dict inframe_contracts.yaml.Front/vite.config.tsstill containsPHASE_Z_MAX_RANK=32, andsrc/phase_z2_pipeline.pystill does not read that env. The env cleanup target remains real.python -m pytest -q tests/test_phase_z2_v4_fallback.py tests/test_catalog_invariant.py->15 passed.Claude #4 lock review:
templates/phase_z2/catalog/v4_fallback_policy.yaml+load_v4_fallback_policy()loader. It must not change the return shape ofload_frame_contracts().lookup_v4_match_with_fallback, with the final ceiling locked asmin(configured_extended_max_rank, len(judgments_full32)).max_rank=3call-site overrides where policy should apply, clean only the trackedFront/vite.config.ts, and add mdx03/mdx05-style regression coverage.Stage 3 guardrails to preserve:
catalog_contract_countas the slicing ceiling. It may be logged for diagnostics, but V4 judgment count is the hard upper bound for rank search.Minor observation:
src/phase_z2_pipeline.pyandtests/test_phase_z2_v4_fallback.py; Stage 3 should keep diffs scoped to the IMP-38 units and avoid absorbing unrelated IMP-47B work.FINAL_CONSENSUS: YES - proceed to Stage 3.
[Claude #5] Stage 3 U1 code-edit 완료 — separate v4_fallback_policy.yaml + load_v4_fallback_policy()
Stage 2 LOCK (comment 23195) 의 U1 구현. 4 round 합의 모두 반영.
작업 내용
신규 파일 (2):
templates/phase_z2/catalog/v4_fallback_policy.yaml— separate yaml (Codex #1 corr: catalog 오염 방지)policy_type: dynamic_usable_count_basedusable_threshold: 1default_max_rank: 3extended_max_rank: 32tests/test_v4_fallback_policy_loader.py— U1 loader 검증 6 tests_V4_FALLBACK_POLICY_CACHE패턴 (lazy load, 동일 dict 반환)extended_max_rank=3= byte-identical pre-IMP-38)load_frame_contracts()shape 무변 검증 (Codex #3 LOCK)수정 파일 (1):
src/phase_z2_mapper.py—load_v4_fallback_policy()함수 +_V4_FALLBACK_POLICY_CACHE+_V4_FALLBACK_POLICY_DEFAULT추가_CATALOG_CACHE패턴 mirror (global lazy load, 동일 module 위치)_V4_FALLBACK_POLICY_DEFAULT(extended=3 = pre-IMP-38 byte-identical)load_frame_contracts()함수 /get_contract()함수 /_CATALOG_CACHE변경 X (Codex #3 LOCK)검증 결과 (직접 실행)
tests/test_v4_fallback_policy_loader.py(신규)tests/test_catalog_invariant.py(변경 X)tests/test_phase_z2_v4_fallback.py(변경 X — U1 scope)검증 — Stage 2 LOCK 가드 부합
test_load_frame_contracts_shape_unchanged통과 — policy keys 가frame_contracts.yaml에 들어가지 않음load_frame_contracts()shape 무변 (Codex #3 LOCK)template_id유지_CATALOG_CACHE패턴 mirror_V4_FALLBACK_POLICY_CACHE동일 패턴test_load_v4_fallback_policy_graceful_when_yaml_missing통과 —extended_max_rank=3(byte-identical pre-IMP-38)영역 충돌 확인
src/phase_z2_pipeline.py+src/phase_z2_ai_fallback/*+src/config.pysrc/phase_z2_retry.pytemplates/phase_z2/families/*.htmlFront/components/FramePanel.tsx→ U1 영역 완전 분리. 다른 batch 와 충돌 0.
변경 line count
src/phase_z2_mapper.py: +47 lines (load_v4_fallback_policy + cache + default + docstring)templates/phase_z2/catalog/v4_fallback_policy.yaml: +47 lines (신규)tests/test_v4_fallback_policy_loader.py: +107 lines (6 tests)총 +201 lines, 3 files. plan estimate 45 line / 3 files 보다 다소 큰 이유 = test 가 verify 항목 6 개라 자세함 (Codex #3 LOCK 의 5 검증 + 보강 1).
다음 단계
src/phase_z2_pipeline.py:779-865의 dynamic max_rank logic)src/phase_z2_pipeline.py= #76 작업 중 (modified). 같은 파일 다른 영역 (line 779-865 vs #76 의 Step 12 reject) — merge conflict 위험은 commit 시점에. 영역 분리는 가능ready-for-codex-review (U1)
[Codex #5] Stage 3 code-edit verification - IMP-38 u1
Verified Claude #5's U1 implementation against the Stage 2 lock and the local working tree.
Result: u1 is correct and scope-acceptable.
Checks:
templates/phase_z2/catalog/v4_fallback_policy.yamlexists as a separate policy file. The policy keys are present and match the Stage 2 lock:policy_type=dynamic_usable_count_based,usable_threshold=1,default_max_rank=3,extended_max_rank=32.src/phase_z2_mapper.pyaddsV4_FALLBACK_POLICY_PATH,_V4_FALLBACK_POLICY_CACHE,_V4_FALLBACK_POLICY_DEFAULT, andload_v4_fallback_policy()without changingload_frame_contracts()orget_contract().default_max_rank=3andextended_max_rank=3, preserving pre-IMP-38 behavior.frame_contracts.yaml;load_frame_contracts()still returns the raw template-id catalog shape. This satisfies the prior catalog-pollution correction.tests/test_v4_fallback_policy_loader.pycovers yaml existence, expected keys/values, cache identity, graceful missing-yaml fallback, catalog shape preservation, and policy-key non-bleed.src/phase_z2_pipeline.py; the dynamic selector behavior remains correctly deferred to u2.Test result:
python -m pytest -q tests/test_v4_fallback_policy_loader.py tests/test_catalog_invariant.py tests/test_phase_z2_v4_fallback.py->21 passed, 1 warning in 0.34s.The warning is a pytest cache write permission warning under
.pytest_cache; it is not an IMP-38 functional failure.Scope note:
The u1 line count is larger than the Stage 2 estimate, mainly because the new loader test is explicit. I do not see a functional reason to rewind u1 for that. If the orchestration line budget is enforced mechanically, that can be handled as a process cleanup, but the implementation itself is coherent and safe.
Remaining units: [u2, u3]
rewind_target: continue_same
FINAL_CONSENSUS: NO
[Claude #6] Stage 3 U2 code-edit 완료 — dynamic effective max_rank + trace 8-field + 3-tier usable
Stage 2 LOCK (comment 23195) 의 U2 구현.
작업 내용
수정 파일 (1) —
src/phase_z2_pipeline.py:load_v4_fallback_policyfromphase_z2_mapper(L54)lookup_v4_match_with_fallback함수:max_rank: int = 3→max_rank: Optional[int] = Noneload_v4_fallback_policy())default_max_rank/configured_extended_max_rank/judgments_counteffective_extended_ceiling = min(configured_extended_max_rank, judgments_count)max_rank명시 →policy_applied = "caller_override"(backward compat — 기존 caller / test)judgments_count == 0→policy_applied = "no_judgments"default_max_rankoreffective_extended_ceilingmax_rankaliasjudgments = all_judgments[:effective_max_rank](기존[:max_rank])chain_exhausted메시지 동적 반영:f"no_auto_renderable_rank_1_to_{effective_max_rank}"(기존 hardcoded "1_to_3")신규 파일 (1) —
tests/test_dynamic_max_rank.py:7 tests covering:
effective_extended_ceiling = min(configured, len(judgments))(5 judgments → ceiling=5)no_judgmentspathno_v4_sectionpath + 8 fields 유지chain_exhausted메시지 동적 반영검증 결과 (직접 실행)
tests/test_dynamic_max_rank.py(신규 U2)tests/test_v4_fallback_policy_loader.py(U1)tests/test_catalog_invariant.pytests/test_phase_z2_v4_fallback.py(IMP-05 baseline + IMP-30 byte-identical)검증 — Stage 2 LOCK 가드 부합
test_effective_extended_ceiling_is_min_of_configured_and_judgments_count통과 (5 judgments → ceiling=5)test_trace_contains_8_imp38_fields통과 (모두 존재)allow_provisionalbyte-identical_V4_FALLBACK_POLICY_DEFAULT(extended=3) 적용Backward compat 가드 (중요)
caller 가
max_rank=3명시한 path =policy_applied="caller_override"→effective_max_rank=3→ 기존 동작 유지.→ 4 call site (L1863/L3461/L3532/L3729) 모두
max_rank=3명시 중. 현재 byte-identical 동작. U3 에서 명시적으로 인자 제거 → policy 적용 활성화 (사용자 정책 그대로).영역 충돌 확인
src/phase_z2_pipeline.py다른 영역 (Step 12 reject route)lookup_v4_match_with_fallbackbody 만 수정 (#76 의 reject route 와 다른 함수) → git merge conflict 위험은 commit 시점에src/phase_z2_retry.pytemplates/phase_z2/families/*.htmlFront/components/FramePanel.tsx대응: U2 =
lookup_v4_match_with_fallback함수 본체만 수정. #76 의 변경 영역 (Step 12 reject route = line shift 후 L568/L584/L805/L3264 hunk 등) 과 다른 위치. 함수 단위 분리 = commit 시 merge 안전.변경 line count
src/phase_z2_pipeline.py: signature 1 line + docstring 8 lines + import 1 line + logic ~55 lines + trace 8 fields + 메시지 1 line = +75 lines, -3 lines (signature/legacy trace 정리)tests/test_dynamic_max_rank.py: +145 lines (7 tests + helpers)총 +220 lines, 2 files. plan estimate 48 line / 2 files 보다 큰 이유 = test 가 7 항목 (caller_override + 8 trace + Codex #2 정정 + no_judgments + no_section + chain_exhausted 메시지).
다음 단계 — U3
Front/vite.config.tsenv 폐기 + regression test (mdx03/mdx05-2)ready-for-codex-review (U2)
[Codex #6] Stage 3 code-edit verification - IMP-38 u1+u2
Verified U1 and U2 against the Stage 2 lock and the current local working tree.
Result: u1 and u2 are correct and scope-acceptable. Proceed to u3, with one call-site-count correction noted below.
Checks:
templates/phase_z2/catalog/v4_fallback_policy.yamlis separate fromframe_contracts.yaml, andsrc/phase_z2_mapper.pyaddsload_v4_fallback_policy()without changingload_frame_contracts()/get_contract()shape.lookup_v4_match_with_fallback(..., max_rank: Optional[int] = None)and loads policy throughload_v4_fallback_policy().default_max_rank,configured_extended_max_rank, andjudgments_count.effective_extended_ceiling = min(configured_extended_max_rank, judgments_count)when judgments exist.requested_max_rank,default_max_rank,configured_extended_max_rank,judgments_count,effective_extended_ceiling,effective_max_rank,usable_count,policy_applied, plus legacy aliasmax_rank.max_rank=3yieldspolicy_applied="caller_override"andeffective_max_rank=3.max_rank=Noneyieldspolicy_applied="extended_max_rank",effective_extended_ceiling=5, andeffective_max_rank=5.tests/test_phase_z2_v4_fallback.pystill passes.Test result:
python -m pytest -q tests/test_dynamic_max_rank.py tests/test_v4_fallback_policy_loader.py tests/test_catalog_invariant.py tests/test_phase_z2_v4_fallback.py->28 passed, 1 warning in 0.41s.The warning is the known
.pytest_cachepermission warning, not an IMP-38 functional failure.Important correction for u3:
Claude #6 / the todo summary says "4 call sites all pass max_rank=3". In the current checkout I verified the call sites with
rg -n "lookup_v4_match_with_fallback\(" src/phase_z2_pipeline.py tests -S.Current production call-site shape is:
src/phase_z2_pipeline.py:1996- no explicitmax_rank; already uses policy path.src/phase_z2_pipeline.py:3590- explicitmax_rank=3.src/phase_z2_pipeline.py:3661- explicitmax_rank=3.src/phase_z2_pipeline.py:3858- explicitmax_rank=3.So u3 should remove the explicit
max_rank=3from the three current call sites, not force a fourth edit. The already-policy call at:1996should be left as-is unless a new concrete reason appears.Scope note:
The
src/phase_z2_pipeline.pydiff is currently mixed with unrelated IMP-47B changes in the same file. This review treats only the IMP-38 selector import/signature/policy/trace logic andtests/test_dynamic_max_rank.pyas U2 scope.Remaining units: [u3]
rewind_target: continue_same
FINAL_CONSENSUS: NO
[Claude #7] Stage 3 plan 정정 — Codex #6 call-site count 정정 반영
Codex #6 review (comment 23240) 의 정정 직접 검증 후 인정.
Codex #6 정정 — 직접 grep 검증
max_rank없음 — already policy pathmax_rank=3explicitmax_rank=3explicitmax_rank=3explicit→ U3 실제 cleanup target = 3 call site (4 가 아님).
제 Stage 1 fact 정정 인정
원인 추정: Stage 1 read 시 L1863 = "default 사용" 으로 인식했지만, 이후 IMP-30 (#39 commit
1efbf67) 또는 IMP-32 (#41 commitc412f1e) 의 helper extraction 에서 explicitmax_rank=3제거됨. 현 working tree 에서는 L1996 = no explicit.정정된 U3 plan
검증 — U1+U2 그대로 (Codex #6 동의)
Codex #6 review 의 다른 항목 = 모두 ✅:
max_rank=3→policy_applied="caller_override")Codex #6 scope note 동의
"src/phase_z2_pipeline.py diff 가 IMP-47B 변경과 섞임 — review 는 IMP-38 scope (selector import/signature/policy/trace logic + test_dynamic_max_rank.py) 만"
→ ✅ commit 시 git diff scope-qualified 명시 필요. IMP-47B 변경은 별 commit (working tree 의 다른 IMP).
ready-for-u3
U3 작업:
src/phase_z2_pipeline.pyL3590/L3661/L3858 의max_rank=3인자 제거 (3 곳)Front/vite.config.tsL349 (comment) + L358 (env value) 폐기tests/test_phase_z2_max_rank_regression.py— mdx03/mdx05 식 (caller=None policy path 시 effective_max_rank 변동) regressionFINAL_CONSENSUS: YES (Codex #6 정정 반영 후) — ready-for-u3-execute
[Codex #7] Stage 3 U3 plan re-review - IMP-38
Verified Claude #7's corrected U3 plan against the current local checkout and the prior Codex #6 correction.
Result: corrected U3 plan is accepted. Proceed to U3 execution.
Checks:
max_rank=3call sites, not 4.rg -n "lookup_v4_match_with_fallback\(" src/phase_z2_pipeline.py tests -S:src/phase_z2_pipeline.py:1996- no explicitmax_rank; already uses policy path. Leave unchanged.src/phase_z2_pipeline.py:3590- explicitmax_rank=3; remove in U3.src/phase_z2_pipeline.py:3661- explicitmax_rank=3; remove in U3.src/phase_z2_pipeline.py:3858- explicitmax_rank=3; remove in U3.Front/vite.config.tsstill has the stale env surface at lines currently matchingPHASE_Z_MAX_RANK: comment around:349and value around:358. This remains a real U3 cleanup target.Accepted U3 scope:
max_rank=3arguments insrc/phase_z2_pipeline.pyso those paths use the new policy default.src/phase_z2_pipeline.py:1996untouched.PHASE_Z_MAX_RANK=32from trackedFront/vite.config.tsonly; do not touch untracked frontend clone directories.Guardrails:
FINAL_CONSENSUS: YES - ready for U3 execute.
[Claude #8] Codex #7 U3 re-review 검증 — ready-for-U3-execute 확정
Codex #7 review (comment 23258) 의 모든 항목 직접 read 기반 검증. 단순 동의 X.
Codex #7 의 항목별 검증
grep -n "lookup_v4_match_with_fallback(" src/phase_z2_pipeline.py→ L1996 라인 read =lookup_v4_match_with_fallback(v4, sid, raw_content=raw_content, alias_keys=alias_keys)— explicit max_rank 없음 확인max_rank=3explicit — 제거 대상sed -n '3586,3600p'→max_rank=3,라인 확인max_rank=3explicit — 제거 대상max_rank=3explicit — 제거 대상Front/vite.config.tsL349 (comment) + L358 (env value) — 폐기 대상PHASE_Z_MAX_RANK결과 = L349 (comment) + L358 (env: "32") 정확 일치git ls-files Front_test/Front/vite.config.ts Front_test_v515/Front/vite.config.ts= empty (untracked, Stage 1 fact 2 확인 그대로)Codex #7 의 guardrail — 검증 + U3 execute 시 준수
_v4_match_from_judgment,to_phase_z_status) 변경 XCodex #7 의 Accepted U3 scope — 직접 검증 일치
max_rank=3인자 제거Front/vite.config.tsPHASE_Z_MAX_RANK=32폐기 (tracked only)git ls-files확인tests/test_phase_z2_max_rank_regression.py)→ 모든 항목 일치. U3 plan = Codex #7 LOCK 그대로 실행 가능.
진행 history (Stage 3 U1+U2 review cycle 완료)
U3 execute 작업 (Codex #7 LOCK 그대로)
src/phase_z2_pipeline.py: L3590/L3661/L3858 의max_rank=3,3 곳 제거 (policy 활성)Front/vite.config.ts: L349 (comment) + L358 (env value) 폐기 + comment 정리tests/test_phase_z2_max_rank_regression.py: default policy path 활성 후 시나리오FINAL_CONSENSUS: YES — ready-for-U3-execute
[Claude #9] Stage 3 U3 code-edit 완료 — 3 call site cleanup + vite env 폐기 + regression test
Codex #7 LOCK (comment 23258) 그대로 실행.
작업 내용
수정 파일 (2):
src/phase_z2_pipeline.py— 3 call site 의max_rank=3인자 제거 → policy 활성:lookup_fn(main composition path)_lookup_fn_mixed_admission(IMP-08 admission path,allow_provisional=True유지)_lookup_fn_provisional(IMP-30 provisional path,allow_provisional=True유지)Front/vite.config.ts—PHASE_Z_MAX_RANK=32env 폐기:PHASE_Z_ALLOW_RESTRUCTURE/PHASE_Z_ALLOW_REJECT는 유지 (별 axis)신규 파일 (1):
tests/test_phase_z2_max_rank_regression.py— 4 scenarios:policy_applied="default_max_rank",effective_max_rank=3policy_applied="extended_max_rank",effective_max_rank=min(configured, 10)policy_applied != "caller_override"(활성 확인)max_rank=N여전히caller_override(backward compat 보호)검증 결과 (직접 실행)
tests/test_phase_z2_max_rank_regression.py(신규 U3)tests/test_dynamic_max_rank.py(U2)tests/test_v4_fallback_policy_loader.py(U1)tests/test_catalog_invariant.pytests/test_phase_z2_v4_fallback.py(IMP-05/IMP-30 baseline)검증 — Codex #7 guardrail 부합
_v4_match_from_judgment/to_phase_z_status변경 0seen_template_ids+ duplicate check 보존allow_provisional=True인자 그대로 (L3666, L3863)Front/vite.config.ts만 (Front_test/v515 untracked, 변경 X)검증 — IMP-30 byte-identical (critical)
IMP-30 의
allow_provisional=Truepath 2 곳 (L3666 / L3863) 모두:max_rank=3만 제거allow_provisional=True인자 유지test_phase_z2_v4_fallback.py 13 passed = IMP-05/IMP-30 baseline 그대로 = byte-identical 가드 통과.
변경 line count
src/phase_z2_pipeline.py: -3 lines (max_rank=3,3 곳)Front/vite.config.ts: -1 line (env value) + comment 정정 +3/-2 = net ~ -1/-2tests/test_phase_z2_max_rank_regression.py: +120 lines (4 scenarios + helpers)총 U3 = +115 lines, -4 lines, 3 files. plan estimate 30 line / 3 files 보다 큰 이유 = regression test 4 scenarios (normal / extended / cleanup / override) 가 verify 항목 다수.
Stage 3 전체 완료 — U1 + U2 + U3 합계
baseline pytest 13 → 32 passed (+17 신규 + 2 catalog_invariant).
영역 충돌 확인 (Stage 4 commit 시점 위험)
src/phase_z2_pipeline.pymodifiedsrc/phase_z2_retry.pytemplates/phase_z2/families/*.htmlFront/components/FramePanel.tsxU3 commit 시점 대응: IMP-38 변경만 cherry-pick — git diff scope-qualified (
templates/phase_z2/catalog/v4_fallback_policy.yaml,src/phase_z2_mapper.py의 IMP-38 영역,src/phase_z2_pipeline.py의 lookup_v4_match_with_fallback 영역 + 3 call site,Front/vite.config.ts, 신규 test 4 파일).다음 단계
ready-for-codex-review (U3)
[Codex #8] Stage 3 code-edit verification - IMP-38 u3
Verified Claude #9's U3 implementation against Codex #7's corrected U3 plan and the current local working tree.
Result: u3 is correct and scoped. Stage 3 is complete; proceed to Stage 4 test-verify.
Findings:
Scope note:
=== EVIDENCE ===
Commands run:
rg -n "lookup_v4_match_with_fallback(|max_rank=3|PHASE_Z_MAX_RANK|phase_z_max_rank|effective_max_rank|policy_applied" src\phase_z2_pipeline.py Front\vite.config.ts tests\test_phase_z2_max_rank_regression.py tests\test_dynamic_max_rank.py
python -m pytest -q tests/test_phase_z2_max_rank_regression.py tests/test_dynamic_max_rank.py tests/test_v4_fallback_policy_loader.py tests/test_catalog_invariant.py tests/test_phase_z2_v4_fallback.py
Get-Content -LiteralPath 'tests\test_phase_z2_max_rank_regression.py'
Get-Content -LiteralPath 'Front\vite.config.ts' | Select-Object -Skip 340 -First 18
Get-Content -LiteralPath 'src\phase_z2_pipeline.py' | Select-Object -Skip 3582 -First 18
Get-Content -LiteralPath 'src\phase_z2_pipeline.py' | Select-Object -Skip 3652 -First 20
Get-Content -LiteralPath 'src\phase_z2_pipeline.py' | Select-Object -Skip 3848 -First 20
git diff -- src\phase_z2_pipeline.py Front\vite.config.ts tests\test_phase_z2_max_rank_regression.py
Files checked:
src/phase_z2_pipeline.py
Front/vite.config.ts
tests/test_phase_z2_max_rank_regression.py
tests/test_dynamic_max_rank.py
tests/test_v4_fallback_policy_loader.py
tests/test_catalog_invariant.py
tests/test_phase_z2_v4_fallback.py
Test results:
python -m pytest -q tests/test_phase_z2_max_rank_regression.py tests/test_dynamic_max_rank.py tests/test_v4_fallback_policy_loader.py tests/test_catalog_invariant.py tests/test_phase_z2_v4_fallback.py -> 32 passed, 1 warning in 0.46s
The warning is a pytest cache permission warning under .pytest_cache and does not affect the executed tests.
Verified facts:
Remaining units: []
rewind_target: continue_same
FINAL_CONSENSUS: YES - proceed to Stage 4 test-verify.
[Claude #10] Codex #8 U3 review 검증 — Stage 3 LOCK + Stage 4 진입 확정
Codex #8 review (comment 23287) 의 모든 주장 직접 read 기반 검증.
Codex #8 의 항목별 검증
max_rank=3잔존 = 0grep -n "max_rank=3" src/phase_z2_pipeline.py→ 유일 hit = L890 comment (yaml default 값 설명 — 코드 인자 아님)test_dynamic_max_rank.py:61, :152= explicitmax_rank=3→caller_override검증 (backward compat 보호)PHASE_Z_MAX_RANKenv 폐기grep -n PHASE_Z_MAX_RANK Front/vite.config.ts→ 유일 hit = L349 retirement comment (의도적). env value 잔존 0allow_provisional=True, L3856+L3863allow_provisional=True— 그대로 보존test_phase_z2_max_rank_regression.py= normal / extended / cleanup / override 4 scenarioCodex #8 의 scope note
"src/phase_z2_pipeline.py currently contains unrelated IMP-47B working-tree hunks, so I treated that diff as mixed. This review is limited to the IMP-38 U3 max_rank call-site cleanup and Vite env retirement surfaces."
→ ✅ 동의. Stage 5 commit 시 cherry-pick 필요:
src/phase_z2_pipeline.py/src/phase_z2_ai_fallback/*/src/config.py변경은 별 commit (#76 작업)pytest 32 passed (Codex #8 local 실행 확인)
(warning = pytest cache permission — 별 axis baseline noise)
Stage 3 LOCK 확정 — 진행 history
Stage 4 진입 — test-verify (다음 코멘트)
작업:
FINAL_CONSENSUS: YES — Stage 3 LOCK 확정. Stage 4 자동 진행.
[Claude #11] Stage 4 test-verify — IMP-38 scope-qualified 회귀 0 + anchor drift 누적 분석
Stage 4 전체 pytest 결과
tests/orchestrator_unit/test_imp17_comment_anchor.pytest_line_570_references_imp17_not_imp31test_line_571_still_references_imp29IMP-38 scope-qualified 회귀 검증
tests/test_phase_z2_max_rank_regression.py(U3)tests/test_dynamic_max_rank.py(U2)tests/test_v4_fallback_policy_loader.py(U1)tests/test_catalog_invariant.pytests/test_phase_z2_v4_fallback.py(IMP-05/IMP-30 baseline)2 failed 의 root cause — 직접 검증 (정정)
이전 Codex #6/#8 의 framing = "IMP-47B noise only". 직접 검증 결과 부분 정정 필요.
tests/orchestrator_unit/test_imp17_comment_anchor.py:가 기대하는 anchor:restructure+IMP-17reject+IMP-29현재 line 570/571 실제:
return _v4_match_from_judgment(section_id, top, rank=1)(lookup_v4_candidates 함수 영역)→ route-hint table 이 훨씬 아래로 shift.
누적 원인 추적:
1efbf67) —V4Match.provisionalfield 추가 → +6 lines → 570/571 로 repinlookup_v4_match_with_fallback본체 +60 lines (signature + policy logic + trace 8 field) → 추가 line shift→ anchor drift = IMP-30 base + IMP-47B + IMP-38 누적. Codex #6/#8 의 "IMP-47B noise only" framing 정정.
IMP-38 의 anchor drift 기여 — 처리 정책 검토
권장 (B): IMP-38 의 Stage 5 commit 은 IMP-38 scope 만 cherry-pick. anchor test repin 은 별 follow-up commit 으로 처리 (line 570/571 → 현 위치 어디인지 grep 후 repin).
IMP-38 Stage 4 verdict
Stage 5 commit-push 진입 가능 — 단 cherry-pick 필요
templates/phase_z2/catalog/v4_fallback_policy.yaml(신규)src/phase_z2_mapper.py(load_v4_fallback_policy + _POLICY_CACHE + DEFAULT)src/phase_z2_pipeline.py(lookup_v4_match_with_fallback + 3 call site + import)Front/vite.config.ts(PHASE_Z_MAX_RANK 폐기)tests/test_v4_fallback_policy_loader.py(신규)tests/test_dynamic_max_rank.py(신규)tests/test_phase_z2_max_rank_regression.py(신규)src/phase_z2_ai_fallback/*,src/config.py, Front/client/* 등tests/orchestrator_unit/test_imp17_comment_anchor.pyrepinStage 4 결론
IMP-38 회귀 0 확인. Stage 5 commit-push 진입 가능.
단 anchor drift 가 IMP-38 도 일부 기여한 사실 명시 (Codex framing 정정). Stage 5 commit 은 cherry-pick scope-qualified — IMP-38 영역만.
ready-for-stage-5 (commit-push)
[Codex #9] Stage 4 test-verify review - IMP-38
Reviewed Claude #11 Stage 4 test-verify comment and re-ran the verification locally.
Result: Stage 4 is accepted for the IMP-38 scope. Proceed to Stage 5 commit-push with a scope-qualified/cherry-picked IMP-38 commit set.
Findings:
return _v4_match_from_judgment(section_id, top, rank=1)and line 571 as blank, while the route-hint table is currently at lines 573-581.load_v4_fallback_policyimport. However, one nuance: the large IMP-38 expansion insidelookup_v4_match_with_fallbackis below the route-hint anchor and is not the direct cause of the line 570/571 anchor failure. The direct pre-anchor shift visible in the diff is the combination of +1 IMP-38 import and +6 IMP-47B Step 12 import lines, with IMP-47B also changing the reject-route table content itself.=== EVIDENCE ===
Commands run:
Files checked:
Test results:
Execution note:
C:\Users\User\AppData\Local\Temp\pytest-of-User). Re-running with TMP/TEMP set to D:\tmp removed those environment errors and reproduced Claude's 684/2 shape.Verified facts:
max_rank=3override remains in src/phase_z2_pipeline.py.rewind_target: continue_same
FINAL_CONSENSUS: YES - proceed to Stage 5 commit-push with IMP-38 scoped cherry-pick.
[Claude #12] Codex #9 Stage 4 review 검증 — anchor drift 기여 정정 인정 + Stage 5 ready
Codex #9 의 nuance 정정 — 직접 검증
Codex #9 주장:
직접 grep 검증
_IMP05_ROUTE_HINTSload_v4_fallback_policyimportlookup_v4_match_with_fallback함수 본체 (+60 lines)→ Codex #9 정정 정확. IMP-38 의 anchor drift 기여 = import 1 line 만 (함수 본체 +60 lines 는 anchor 아래라 영향 X).
내 framing 부분 정정 인정
Codex #9 의 추가 발견 — Windows TMP/TEMP 환경 변수
→ Codex 가 환경 변수 설정 후 동일한 684/2 reproduce. 환경 차이 X = 결과 신뢰 확인 ✅
Codex #9 FINAL_CONSENSUS
Stage 5 commit-push plan — cherry-pick scope-qualified
templates/phase_z2/catalog/v4_fallback_policy.yaml(신규)git add단순src/phase_z2_mapper.py(load_v4_fallback_policy + cache + default + IMP-38 영역)src/phase_z2_pipeline.py(import + lookup_v4_match_with_fallback + 3 call site)Front/vite.config.ts(PHASE_Z_MAX_RANK 폐기)tests/test_v4_fallback_policy_loader.py(신규)git add단순tests/test_dynamic_max_rank.py(신규)git add단순tests/test_phase_z2_max_rank_regression.py(신규)git add단순src/phase_z2_ai_fallback/*(IMP-47B)src/config.py(IMP-47Bai_fallback_enabled)tests/orchestrator_unit/test_imp17_comment_anchor.pyrepintests/phase_z2_ai_fallback/*(IMP-47B)commit message (제안)
ready-for-stage-5 — 사용자 GO 필요 (commit/push = destructive)
cherry-pick 작업:
git add)git add -p또는 stash + selective restore)commit/push 는 destructive action. 사용자 명시 GO 받고 진행하겠습니다.
[Codex #10] Stage 5 readiness note - IMP-38
Stage 4 is locked after Codex #9 and Claude's follow-up verification. IMP-38 is ready to enter Stage 5 commit-push once the user gives an explicit GO.
Readiness summary:
Stage 5 scope to commit:
New files:
Modified files, IMP-38 hunks only:
Explicitly excluded from the IMP-38 commit:
Stage 5 execution guard:
Current status: waiting for explicit user GO for commit/push.
FINAL_CONSENSUS: YES - Stage 5 is ready, pending user GO.
[Claude #13] Codex #10 Stage 5 readiness 검증 — Stage 5 execution guard 합의
Codex #10 review 검증
Codex #10 의 Stage 5 execution guard 5 가지 — 동의
git add -p또는git stash+ selective restoregit diff --cached검증 (commit 전)Stage 5 작업 sequence (Codex #10 guard 반영)
진행 history — Stage 4 → Stage 5 ready
사용자 명시 GO 신호 요청
commit/push = destructive action. 사용자 명시 GO ("ㄱ" / "박아" / "진행" 등) 받으면 즉시 Stage 5 execution sequence 8 step 실행.
FINAL_CONSENSUS: YES — Stage 5 ready, awaiting user GO
[Codex #11] Stage 5 readiness verification - IMP-38
Reviewed Claude #13's Stage 5 execution-guard comment and re-checked the current issue state.
Result: Claude #13 is correct. Stage 5 is ready, pending explicit user GO for commit/push.
Verification:
Stage 5 commit scope accepted:
Include:
Exclude:
Operational note:
git add src/phase_z2_pipeline.py. Use hunk-level staging or a temporary clean patch/cherry-pick workflow and inspectgit diff --cachedbefore committing.FINAL_CONSENSUS: YES - Stage 5 ready, awaiting user GO.
[Claude #14] Codex #11 Stage 5 readiness 재검증 — broad git add 금지 가드 추가 합의
Codex #11 review 검증
Codex #11 의 추가 강조 — "broad git add 금지"
→ 동의.
git add src/phase_z2_pipeline.py전체 add 시 IMP-47B hunks 같이 staged 됨. 반드시 hunk-level (git add -p) 또는 stash + selective restore 사용.Stage 5 execution guard 보강 (6 가지)
git diff --cached검증 (commit 전)git add src/phase_z2_pipeline.py금지Stage 5 execution sequence (Codex #11 가드 반영, 8 step)
진행 history (Stage 4 → Stage 5 ready, 4 round 합의)
FINAL_CONSENSUS: YES — ���용자 명시 GO 대기
commit/push = destructive. 사용자 명시 GO ("ㄱ" / "박아" / "진행" 등) 받으면 즉시 8 step sequence 실행 + 결과 게시 + Stage 6 진입.
[Claude #15] Stage 5 commit-push 완료 — IMP-38 LOCK + Stage 6 진입
Commit + Push 결과
origin(github.com:keimin86/design_agent.git)dceb101..90503ca main -> main✅slide2(gitea.hmac.kr/Kyeongmin/C.E.L_Slide_test2.git)dceb101..90503ca main -> main✅Stage 5 execution sequence — 8 step 결과
git add금지, file-level addgit diff --cached --stat검증90503caCodex #11 의 6 guard 준수 확인
git diff --cached검증git add src/phase_z2_pipeline.py금지Stage 5 변경 history (4 round 합의 그대로)
90503ca+ push 양쪽 ✅Stage 5 verdict
90503ca(origin + slide2)Stage 6 진입 — #67 close + governance #82 progress update
다음 작업:
git stash list확인 후 IMP-47B 작업 복원 (또는 #76 작업 새로 진행)FINAL_CONSENSUS: YES — Stage 5 LOCK + ready-for-stage-6
[Stage 6] IMP-38 final-close — commit
90503ca, push origin + slide2Stage 6 close summary
90503ca4 round 합의 → 7 round Claude + 5 round Codex 실행 history
90503ca+ push 양쪽 ✅IMP-38 destination 달성 — 사용자 정의 정책 실현
policy_type: dynamic_usable_count_based(옵션 C)usable_threshold: 1(보수 — mdx03 정상 case 보호)default_max_rank: 3(의미 신뢰 범위)extended_max_rank: 32(catalog presence fallback)effective_extended_ceiling = min(configured, len(judgments))(Codex #2 정정)영향 — mdx 처리 path
→ IMP-38 단독으로는 mdx05-2 처리 해소 + mdx03 회귀 X. mdx04 는 별 axis (#66 + #76) 와 묶음.
Closed.