5탭 계약 대조 — 계약 원본 사본을 앱 저장소에 두어 어느 체크아웃에서도 검증
This commit is contained in:
@@ -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
|
`brew install --cask temurin@17` 은 sudo 를 요구한다. sudo 없이 쓰려면 Adoptium
|
||||||
tar.gz 를 `~/.jdks/` 에 풀면 된다.
|
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
|
```bash
|
||||||
|
|||||||
@@ -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]
|
||||||
@@ -300,8 +300,31 @@ Future<void> _enterShell(WidgetTester tester) async {
|
|||||||
|
|
||||||
/// `design/craft-allowlist.yaml` 의 `APP_TABS` 를 읽어 온다.
|
/// `design/craft-allowlist.yaml` 의 `APP_TABS` 를 읽어 온다.
|
||||||
/// 앱 코드가 계약 표기에서 벗어나면 여기서 깨진다.
|
/// 앱 코드가 계약 표기에서 벗어나면 여기서 깨진다.
|
||||||
|
///
|
||||||
|
/// 계약 정본은 상위 저장소(p-fancake)에 있고 이 저장소(p-fanuzu)는 분리돼 있어
|
||||||
|
/// 상대 경로가 체크아웃 위치를 탄다. 그래서 저장소 안에 사본을 두고
|
||||||
|
/// **FANUZU_DESIGN_DIR → 저장소 내 design/ → 형제 경로** 순으로 본다.
|
||||||
|
/// 사본이 있으므로 git worktree 에서도 환경 변수 없이 통과한다.
|
||||||
|
///
|
||||||
|
/// 하나도 없으면 **통과가 아니라 실패**로 끝낸다 — 못 읽은 것을 「맞다」로 세면
|
||||||
|
/// 계약 대조가 조용히 사라진다.
|
||||||
List<String> _contractTabs() {
|
List<String> _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(
|
final line = file.readAsLinesSync().firstWhere(
|
||||||
(l) => l.trimLeft().startsWith('APP_TABS:'),
|
(l) => l.trimLeft().startsWith('APP_TABS:'),
|
||||||
orElse: () =>
|
orElse: () =>
|
||||||
|
|||||||
Reference in New Issue
Block a user