fix(729-5): 별칭 체크 줄이 못옮김 남은 차이 SK 를 가리키면 남은 줄 · 만들기 응답 남은못옮김

- M02_Hopyo_SkLink.kept: 확인한 로직 줄이 차이 SK 바탕일 때 그 SK 에 못옮김이 남으면 남은 줄 {까닭, 단산, SK, 못옮김}(sk_line 과 같은 규칙) — hopyo-unlinked 에 나오고 hopyo-build 409
- M02_Hopyo_Sangeun.build: 응답에 남은못옮김 [{번, 이름, 키, 못옮김}](그대로 SK 중 못옮김 남은 것) · 잇기만 보냈는데 1위 기초가 고름 대기면 그 SK 바탕으로 다시 셈(고른 기초 SK 잇기)
- 시험: test_729 에 별칭 체크 줄 · 그대로 SK 남은못옮김 · 잇기 뒤 사라짐 · 차이 SK 참조

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-02 12:13:54 +09:00
co-authored by Claude Opus 5.5
parent ee2c5b1de3
commit 0c8c31cadd
4 changed files with 91 additions and 14 deletions
@@ -186,6 +186,46 @@ def test_단위_성격_다름_계수_못옮김_잇기_남으면_일위대가_막
assert master_hash() == before
def test_별칭_체크_줄_못옮김_SK_남은줄_그대로_SK_남은못옮김(client):
"""729-5 — 확인한 로직 줄이 못옮김 남은 차이 SK 의 바탕이면 남은 줄(차이 잃지 않음) · 만들기 409 ·
그대로 SK 의 못옮김 = 응답 남은못옮김 · 잇기 뒤 사라짐."""
before = master_hash()
folder = layers.personal_dir(7, 42)
key = _post(client).json()["키"]
url = f"{URL.format('personal')}/{key}/sangeun"
fit.run_job(folder, key)
made = {x["번"]: x for x in client.post(url, json={}).json()["만듦"]}
sk = made[60] # 제27호표 2째 줄 와이어메시바닥깔기 — SK(바탕 GC000665) · 엑셀만 와이어메쉬
assert sk["갈래"] == "SK" and len(sk["못옮김"]) == 1
check = {"차례": 2, "대상": [{"로직": "GC000665", "배": 1}]} # 별칭 자동 체크와 같은 꼴
body = {"층": "personal", "키": key, "번": 27, "줄": [check]}
def mine(rows: list) -> list:
return [x for x in rows if x["차례"] == 2]
left = client.post(LEFT, json=body).json()["남은줄"]
assert [(x["단산"], x["SK"], x["못옮김"]) for x in mine(left)] == [(60, sk["키"], sk["못옮김"])]
res = client.post(BUILD, json=body)
assert res.status_code == 409 and mine(res.json()["detail"]["남은줄"]) == mine(left)
# 그대로 SK 의 못옮김 = 응답 남은못옮김(만듦[].못옮김 과 같은 꼴)
again = client.post(url, json={}).json()
rest = {x["번"]: x for x in again["남은못옮김"]}
assert again["만듦"] == [] and set(rest) == {n for n, x in made.items() if x["못옮김"]}
assert rest[60] == {"번": 60, "이름": sk["이름"], "키": sk["키"], "못옮김": sk["못옮김"]}
cut = {"id": sk["못옮김"][0]["id"], "자재": "MT000010"} # 이음 = SK 더한줄(차이 남음)
linked = client.post(url, json={"바탕": {"60": {"잇기": [cut]}}}).json()
assert [(x["번"], x["키"], x["못옮김"]) for x in linked["만듦"]] == [(60, sk["키"], [])]
assert 60 not in {x["번"] for x in client.post(url, json={}).json()["남은못옮김"]}
left = client.post(LEFT, json=body).json()["남은줄"]
assert mine(left) == []
picks = [{"차례": x["차례"], "뺌": "우리에 없음"} for x in left]
ok = client.post(BUILD, json={**body, "줄": [check, *picks]})
assert ok.status_code == 200, ok.text
doc = json.loads((folder / "precombo" / f"{ok.json()['참조']['키']}.json").read_bytes())
assert any((x.get("참조") or {}).get("키") == sk["키"] for x in doc["담은로직"]) # 차이 SK 참조
assert master_hash() == before
def _eq(one: dict) -> str:
return str((one.get("입력값") or {}).get("기계") or "")