From 1c51662c25e0978bbbc88323c2d889412ddd6b4e Mon Sep 17 00:00:00 2001 From: Sn-Kinos Date: Mon, 14 Sep 2026 13:30:26 +0900 Subject: [PATCH] =?UTF-8?q?5=ED=83=AD=20=EA=B3=84=EC=95=BD=20=EB=8C=80?= =?UTF-8?q?=EC=A1=B0=20=E2=80=94=20=EA=B3=84=EC=95=BD=20=EC=9B=90=EB=B3=B8?= =?UTF-8?q?=20=EC=82=AC=EB=B3=B8=EC=9D=84=20=EC=95=B1=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=EC=86=8C=EC=97=90=20=EB=91=90=EC=96=B4=20=EC=96=B4=EB=8A=90=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=EC=95=84=EC=9B=83=EC=97=90=EC=84=9C=EB=8F=84?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/BUILD.md | 29 +++++++++++++++++++++++++++++ app/design/craft-allowlist.yaml | 23 +++++++++++++++++++++++ app/test/app_smoke_test.dart | 25 ++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/design/craft-allowlist.yaml diff --git a/app/BUILD.md b/app/BUILD.md index 38b3fe1..a24db2f 100644 --- a/app/BUILD.md +++ b/app/BUILD.md @@ -27,6 +27,35 @@ fvm flutter config --jdk-dir ~/.jdks/jdk-17.0.20.1+1/Contents/Home `brew install --cask temurin@17` 은 sudo 를 요구한다. sudo 없이 쓰려면 Adoptium tar.gz 를 `~/.jdks/` 에 풀면 된다. +## 테스트 + +```bash +export ANDROID_HOME=/opt/homebrew/share/android-commandlinetools +fvm flutter analyze +FANUZU_DESIGN_DIR=/path/to/p-fancake/design fvm flutter test +``` + +`FANUZU_DESIGN_DIR` 은 5탭 계약 대조용이다. 스모크 테스트가 +`craft-allowlist.yaml` 의 `APP_TABS` 를 직접 읽어 앱의 `appTabs` 와 정확 일치를 검증한다. +**정본은 상위 저장소 `p-fancake/design/craft-allowlist.yaml`** 이고 이 저장소는 분리돼 +있으므로, 같은 파일의 사본을 `design/craft-allowlist.yaml` 로 두었다. 탐색 순서는 아래와 같다. + +1. `$FANUZU_DESIGN_DIR/craft-allowlist.yaml` — 정본을 직접 가리킬 때 쓴다. +2. `design/craft-allowlist.yaml` — 이 저장소의 사본. +3. `../design/craft-allowlist.yaml` · `../p-fancake/design/craft-allowlist.yaml` — p-fancake 와 + 형제로 둔 체크아웃. + +사본이 있으므로 **git worktree 에서도 변수 없이 통과한다.** 그래도 못 찾으면 통과가 아니라 +실패한다 — 계약 대조가 조용히 사라지면 안 된다. + +사본은 정본과 갈리면 저장소마다 다른 답을 내므로, **정본을 고칠 때 사본에도 함께 복사한다.** +파일 머리에 같은 문장을 적어 두었다. + +```bash +cp /path/to/p-fancake/design/craft-allowlist.yaml design/craft-allowlist.yaml +# 머리 주석 5줄은 사본에만 있으니 지우지 말고 APP_TABS·CAPS_OK 만 맞춘다. +``` + ## 빌드 ```bash diff --git a/app/design/craft-allowlist.yaml b/app/design/craft-allowlist.yaml new file mode 100644 index 0000000..bf3c06f --- /dev/null +++ b/app/design/craft-allowlist.yaml @@ -0,0 +1,23 @@ +# ⚠️ 이 파일은 사본이다. 정본은 상위 저장소 p-fancake/design/craft-allowlist.yaml 이며, +# 정본을 갱신할 때 이 사본에도 함께 복사한다. 두 파일이 갈리면 계약 대조(APP_TABS)가 +# 저장소마다 다른 답을 내므로, 사본만 고치는 일은 없어야 한다. +# 사본을 둔 이유는 git worktree 에서 형제 경로(../design/)가 없어 스모크 테스트가 +# 계약 대조를 못 하고 실패하기 때문이다(BUILD.md 「테스트」). + +# craft-allowlist.yaml — 크래프트 체커의 "분류 결정"을 적는 곳. +# 경고를 끄는 곳이 아니다. 각 항목에 근거(reason)가 없으면 킷이 읽지 않는다. +# 계약: 하네스/디자인/resources/codex/check_craft_render.py C2 + +CAPS_OK: + # ── 5탭 라벨 — 견적서 v2.1 「5탭 네비게이션」으로 고정된 화면 이름이다. + # 모든 앱 화면의 하단 탭바에 그대로 들어가므로 화면당 대문자 예산을 통째로 먹는다. + - {term: STATION, reason: "견적서 v2.1 5탭 라벨 · 한글 대체 불가(계약 표기)"} + - {term: INSIDE, reason: "견적서 v2.1 5탭 라벨 · 한글 대체 불가(계약 표기)"} + - {term: GALAXY, reason: "견적서 v2.1 5탭 라벨 · 한글 대체 불가(계약 표기)"} + # ── 지표·재화 약어 — 화면 전반에서 단위처럼 쓰인다. + - {term: FPI, reason: "Fandom Planet Index 약어 · PRD v9.0 PRD-03 공식 명칭"} + +# ── 앱 하단 5탭 라벨 (게이트 C15) ────────────────────────── +# 견적서 v2.1 「5탭 네비게이션」으로 확정된 제품 IA다. 렌더러가 화면마다 한글화하거나 +# 순서를 바꾸면 계약 산출물과 어긋난다. 순서까지 정확히 일치해야 한다. +APP_TABS: [HOME, INSIDE, GALAXY, STATION, MY] diff --git a/app/test/app_smoke_test.dart b/app/test/app_smoke_test.dart index 1e8e014..1c645ff 100644 --- a/app/test/app_smoke_test.dart +++ b/app/test/app_smoke_test.dart @@ -300,8 +300,31 @@ Future _enterShell(WidgetTester tester) async { /// `design/craft-allowlist.yaml` 의 `APP_TABS` 를 읽어 온다. /// 앱 코드가 계약 표기에서 벗어나면 여기서 깨진다. +/// +/// 계약 정본은 상위 저장소(p-fancake)에 있고 이 저장소(p-fanuzu)는 분리돼 있어 +/// 상대 경로가 체크아웃 위치를 탄다. 그래서 저장소 안에 사본을 두고 +/// **FANUZU_DESIGN_DIR → 저장소 내 design/ → 형제 경로** 순으로 본다. +/// 사본이 있으므로 git worktree 에서도 환경 변수 없이 통과한다. +/// +/// 하나도 없으면 **통과가 아니라 실패**로 끝낸다 — 못 읽은 것을 「맞다」로 세면 +/// 계약 대조가 조용히 사라진다. List _contractTabs() { - final file = File('../design/craft-allowlist.yaml'); + final candidates = [ + if (Platform.environment['FANUZU_DESIGN_DIR'] case final dir?) + '$dir/craft-allowlist.yaml', + 'design/craft-allowlist.yaml', + '../design/craft-allowlist.yaml', + '../p-fancake/design/craft-allowlist.yaml', + ]; + final file = candidates + .map(File.new) + .firstWhere( + (f) => f.existsSync(), + orElse: () => throw StateError( + 'craft-allowlist.yaml 을 찾지 못했다. FANUZU_DESIGN_DIR 로 지정하라. ' + '찾아본 곳: ${candidates.join(' · ')}', + ), + ); final line = file.readAsLinesSync().firstWhere( (l) => l.trimLeft().startsWith('APP_TABS:'), orElse: () =>