feat(M02): 50-3 ①②⑤ 일위대가 조합 서고 서버 — 단가승격 SP · 사전조합 SC · 참조 펼침 · 굳힘

- 층 양식 길 새 종류 promote · precombo(키 = 파일 이름 · 층마다 다음 번호) · 새로 · 복사 길 POST /layers/{층}/library/{종류}
- 참조 {층 · 주인 · 키} — 위 층만 · 같은 참조 두 번 400 · 순환 422 · 쓰는 곳 있으면 지우기 409(모든 층 일위대가 · 사전조합 훑음)
- calc 가 참조 줄 펼침(재귀 · 캐시 · 깊이 상한 8 · 까닭) · 알약 키 「참조|층|주인|키」 · 분모 = 가리킨 문서 단위 · 배 1 · settle TS 짝 lineId
- 층 사이 복사 = 못 읽는 참조 같이 복사(본뜬) · 프로젝트 가져오기 = 참조사본으로 굳힘 · 로직 지우기 검사에 단가승격 더함 · 새 프로젝트 씨앗은 서고 뺌
- 시험 test_m02_labor_ref.py(펼침 · 순환 · 층 규칙 · 409 · 복사 · 굳힘 · 거울)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EYJJRCfHfdCGNhmXTjQKV7
This commit is contained in:
2026-10-05 18:47:02 +09:00
co-authored by Claude Opus 5.5
parent 3e572ef210
commit 9ee6c9f3fd
12 changed files with 966 additions and 53 deletions
@@ -25,6 +25,7 @@ from common_util import common_util_spreadsheet as spreadsheet
from common_util.common_util_auth import verify_session
from common_util.common_util_storage import resolve_stored_project_path
from config.config_db import get_db_pool, run_with_connection
from M02_MasterTemplete import M02_Labor_Ref as refs
from M02_MasterTemplete import M02_Layer_Access as access
from M02_MasterTemplete import M02_MasterTemplete_Items as items_store
from M02_MasterTemplete import M02_MasterTemplete_Router_Items as items_router
@@ -278,6 +279,8 @@ async def list_layer(
row["출처"] = manifest.get(f"{row['종류']}/{row['이름']}")
if (row["종류"], row["이름"]) in store.IN_USE: # 화면이 지우기 확인 창 전에 막음
row["쓰는곳"] = store.IN_USE[(row["종류"], row["이름"])]
if row["종류"] in layers.LIBRARY_KINDS: # 서고(50-3) — 보이는 이름 · 단위
row.update(refs.summary(folder, row["종류"], row["이름"]))
return {"층": layer, "양식": rows}
@@ -324,6 +327,8 @@ async def save_layer_template(
session, layer, project_id=project_id, user_id=user_id, owner=owner, write=True
)
document = body.문서
if layer == "project" and kind in layers.LIBRARY_KINDS:
raise HTTPException(status_code=400, detail="프로젝트는 서고 문서를 안 둠 — 굳힌 사본만")
try:
layers.check_skeleton(kind, document) # 빈 `{}` · 뼈대 없는 문서는 파일 안 씀
except ValueError as error:
@@ -406,6 +411,10 @@ async def delete_layer_template(
layers.check_name(name)
except ValueError as error:
raise _bad(error) from error
try: # 서고 문서를 담은 일위대가 · 사전조합이 있으면 409(50-3)
await asyncio.to_thread(refs.refuse_used, folder, kind, name)
except store.StoreError as error:
raise HTTPException(status_code=error.status, detail=error.detail) from error
if not 판:
raise HTTPException(status_code=400, detail="지울 양식의 판이 필요합니다.")
try: