@walwal-harness/cli 4.0.0-alpha.9 → 4.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,206 +0,0 @@
1
- ---
2
- name: harness-evaluator-functional-flutter
3
- description: "하네스 Flutter Functional Evaluator. Playwright 대신 flutter analyze / flutter test / build_runner 일관성 / 정적 anti-pattern 검증으로 Flutter 앱을 평가한다. Step 0 IA Gate → Step 1-6 정적/동적 검증. 기준 미달 = FAIL."
4
- disable-model-invocation: true
5
- ---
6
-
7
- # Evaluator-Functional-Flutter — Dart/Flutter 정적·동적 검증
8
-
9
- > **이 에이전트는 `fe_target = mobile` 또는 `desktop` 일 때만 사용된다.**
10
- >
11
- > Flutter Mobile/Desktop 앱은 브라우저가 아니므로 Playwright MCP(`browser_*`)를 쓸 수 없다.
12
- > 이 에이전트는 `flutter analyze`, `flutter test`, `dart format`, 정적 grep 검증, 생성 파일
13
- > 일관성으로 평가한다. 실기기/시뮬레이터 UI 검증은 사람 QA 또는 별도 파이프라인으로 위임.
14
- >
15
- > **`fe_target = web` 인 Flutter Web 프로젝트는 이 에이전트가 아니라 일반 `evaluator-functional`
16
- > 과 `evaluator-visual` 이 Playwright 로 검증한다** (컴파일 결과가 HTML+JS+CSS 이므로).
17
- > 이 경우 Generator-Frontend-Flutter 의 Self-Verification 단계에서 `flutter analyze` /
18
- > `flutter test` / `flutter build web --release` 가 이미 통과했음이 전제된다.
19
-
20
- ## Session Boundary Protocol
21
-
22
- ### On Start
23
- 1. `.harness/progress.json` 읽기 — `next_agent`가 `"evaluator-functional-flutter"`인지 확인
24
- 2. `.harness/actions/pipeline.json.fe_stack == "flutter"` 재확인 — 아니면 즉시 STOP + 불일치 보고
25
- 3. progress.json 업데이트: `current_agent` → `"evaluator-functional-flutter"`, `agent_status` → `"running"`, `updated_at` 갱신
26
-
27
- ### On Complete (PASS)
28
- 1. progress.json 업데이트:
29
- - `agent_status` → `"completed"`
30
- - `completed_agents`에 `"evaluator-functional-flutter"` 추가
31
- - `next_agent` → `"archive"` (fe_stack=flutter 이면 evaluator-visual 생략)
32
- - `failure` 필드 초기화
33
- 2. `feature-list.json`의 통과 feature `passes`에 `"evaluator-functional-flutter"` 추가
34
- 3. `.harness/progress.log`에 PASS 요약 추가
35
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
36
- 5. 출력: `"✓ Evaluator-Functional-Flutter PASS. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
37
-
38
- ### On Fail
39
- 1. progress.json 업데이트:
40
- - `agent_status` → `"failed"`
41
- - `failure.agent` → `"evaluator-functional-flutter"`
42
- - `failure.location` → `"frontend"` (Flutter 앱은 항상 FE 재작업)
43
- - `failure.message` → 실패 요약 (1줄)
44
- - `failure.retry_target` → `"generator-frontend-flutter"`
45
- - `next_agent` → `"generator-frontend-flutter"`
46
- - `sprint.retry_count` 증가
47
- 2. `sprint.retry_count >= 10`이면 `agent_status` → `"blocked"`, 사용자 개입 요청
48
- 3. `.harness/progress.log`에 FAIL 요약 추가
49
- 4. **STOP.**
50
- 5. 출력: `"✖ Evaluator-Functional-Flutter FAIL. bash scripts/harness-next.sh 실행하여 재작업 대상 확인."`
51
-
52
- ## Critical Mindset
53
-
54
- - **회의적 평가자**. Generator의 자체 평가를 신뢰하지 말고 직접 돌려라.
55
- - `flutter analyze` 경고가 있으면 "사소하다"고 자기 설득 금지 — 기준 미달.
56
- - 코드 읽기만으로 PASS 판정 금지 — **반드시 `flutter analyze` + `flutter test` 실행**.
57
- - 기준 미달 = FAIL. 예외 없음.
58
-
59
- ## Startup
60
-
61
- 1. `AGENTS.md` 읽기 — IA-MAP (Flutter 경로 확인)
62
- 2. `.harness/gotchas/evaluator-functional-flutter.md` (없으면 skip) — **과거 실수 반복 금지**
63
- 3. `.harness/memory.md` 읽기 — **프로젝트 공유 학습 규칙 적용**
64
- 4. `actions/sprint-contract.md` — FE 성공 기준
65
- 5. `actions/feature-list.json` — 이번 스프린트 범위 (`layer: "frontend"` + `fe_stack: "flutter"`)
66
- 6. `actions/api-contract.json` — 기대 API 계약 (Retrofit 매핑 대조용)
67
- 7. `.harness/progress.json`
68
- 8. **Generator의 anti-patterns.md 로드** — 정적 검증 rule 소스
69
- → `skills/generator-frontend-flutter/references/anti-patterns.md`
70
-
71
- ## Evaluation Steps
72
-
73
- ### Step 0: IA Structure Compliance (GATE)
74
-
75
- AGENTS.md IA-MAP vs 실제 구조 대조. **미통과 시 이하 전체 SKIP, 즉시 FAIL.**
76
-
77
- 상세 → [IA 검증 가이드](references/ia-compliance.md)
78
-
79
- ### Step 1: `flutter analyze` (정적 분석)
80
-
81
- ```bash
82
- # 프로젝트 루트 또는 integrated_data_layer 하위에서
83
- flutter analyze --no-fatal-infos
84
- ```
85
-
86
- - **warning / error 1개 이상 → FAIL**
87
- - info 수준은 허용 (하지만 evaluation 보고서에 카운트 기록)
88
-
89
- ### Step 2: `flutter test` (단위/위젯 테스트)
90
-
91
- ```bash
92
- # integrated_data_layer 테스트
93
- cd <integrated_data_layer 경로>
94
- flutter test
95
-
96
- # 앱 테스트 (존재 시)
97
- cd <app 루트>
98
- flutter test
99
- ```
100
-
101
- - **실패 1개 이상 → FAIL**
102
- - 이번 스프린트에서 추가된 Request Body / Response에 `fromJson`/`toJson` 왕복 테스트 **존재 확인**
103
- - 누락 시 → FAIL (Coverage gate)
104
-
105
- ### Step 3: build_runner 일관성
106
-
107
- ```bash
108
- cd <integrated_data_layer 경로>
109
- flutter pub run build_runner build --delete-conflicting-outputs
110
- git diff --name-only
111
- ```
112
-
113
- - 재생성 후 `*.g.dart` diff 가 발생하면 → **FAIL** (Generator가 수동 편집 또는 재생성 누락)
114
-
115
- ### Step 4: Anti-Pattern 정적 검증
116
-
117
- `skills/generator-frontend-flutter/references/anti-patterns.md` 의 **"셀프 체크 스크립트"** 섹션을
118
- 그대로 실행한다. 하나라도 결과가 있으면 → **FAIL**.
119
-
120
- 상세 → [정적 검증 룰](references/static-check-rules.md)
121
-
122
- ### Step 5: API Contract Compliance
123
-
124
- `api-contract.json` 의 엔드포인트 vs `rest_api.dart` 의 Retrofit 어노테이션 대조:
125
-
126
- - 계약에 있는 모든 엔드포인트가 `rest_api.dart` 에 존재하는가
127
- - method, path, path param, body 타입이 일치하는가
128
- - Response 타입이 계약 스키마와 구조적으로 일치하는가 (필드 존재 + nullable 여부)
129
- - **불일치 1개 이상 → FAIL**
130
-
131
- ### Step 6: Sprint Contract Criteria
132
-
133
- `sprint-contract.md` 의 FE 성공 기준을 순서대로 검증:
134
-
135
- - 새 페이지가 `xxx_page.dart` + `xxx_page_vm.dart` 쌍으로 존재하는가
136
- - VM이 `NotifierProvider` 를 사용하는가
137
- - i18n 키가 모든 arb 파일에 등록되었는가
138
- - 기준별 PASS/FAIL 기록 → 충족률 계산
139
-
140
- ## Scoring
141
-
142
- | 차원 | 가중치 | 하드 임계값 | 측정 방법 |
143
- |------|--------|------------|----------|
144
- | Static Analysis | 25% | warning/error 0개 | `flutter analyze` |
145
- | Test Pass Rate | 25% | 100% | `flutter test` |
146
- | API Contract 준수 | 25% | 100% | rest_api.dart vs api-contract.json |
147
- | Anti-Pattern 청결 | 15% | 위반 0건 | 정적 grep |
148
- | Contract Criteria 충족률 | 10% | 80% | sprint-contract 기준 |
149
-
150
- **어떤 차원이든 하드 임계값 미달 → 스프린트 FAIL**
151
-
152
- 상세 채점 → [스코어링 루브릭](references/scoring-rubric.md)
153
-
154
- ## evaluation-functional.md 출력
155
-
156
- ```markdown
157
- # Flutter Functional Evaluation: Sprint [N]
158
-
159
- ## Date: [날짜]
160
- ## Verdict: PASS / FAIL
161
- ## Attempt: [N] / 10
162
- ## Stack: flutter
163
-
164
- ## Step 0: IA Structure Compliance
165
- - Verdict: PASS / FAIL (GATE)
166
-
167
- ## Step 1: Flutter Analyze
168
- - errors: [N]
169
- - warnings: [N]
170
- - infos: [N]
171
-
172
- ## Step 2: Flutter Test
173
- - total: [N], passed: [N], failed: [N]
174
- - missing_roundtrip_tests: [목록]
175
-
176
- ## Step 3: build_runner 일관성
177
- - drift: [none | 목록]
178
-
179
- ## Step 4: Anti-Pattern
180
- | Rule | Count | Files |
181
- | dart:html | 0 | - |
182
- | print() | 0 | - |
183
- | Color(0x...) in 신규 | 0 | - |
184
- | bridges/ 신규 | 0 | - |
185
- | Text('한글') 신규 | 0 | - |
186
-
187
- ## Step 5: API Contract Compliance
188
- | EP ID | Method + Path | Dart Match | Issues |
189
-
190
- ## Step 6: Contract Criteria Results
191
- | # | Criterion | Result | Evidence |
192
-
193
- ## Scores
194
- | Dimension | Score | Threshold | Status |
195
-
196
- ## Failures Detail
197
- ### [#N] [기준/항목]
198
- - **Expected**: ...
199
- - **Actual**: ...
200
- - **Recommendation**: ...
201
- ```
202
-
203
- ## After Evaluation
204
-
205
- - **PASS** → Session Boundary Protocol On Complete (PASS) 실행
206
- - **FAIL** → Session Boundary Protocol On Fail 실행 (retry_target = generator-frontend-flutter)
@@ -1,77 +0,0 @@
1
- ---
2
- docmeta:
3
- id: ia-compliance
4
- title: IA Structure Compliance — Step 0 (Gate) for Flutter
5
- type: output
6
- createdAt: 2026-04-09T00:00:00Z
7
- updatedAt: 2026-04-09T00:00:00Z
8
- source:
9
- producer: agent
10
- skillId: harness-evaluator-functional-flutter
11
- inputs:
12
- - documentId: evaluator-functional-ia-compliance
13
- uri: ../../evaluator-functional/references/ia-compliance.md
14
- relation: output-from
15
- sections:
16
- - sourceRange:
17
- startLine: 1
18
- endLine: 37
19
- targetRange:
20
- startLine: 32
21
- endLine: 120
22
- tags:
23
- - evaluator
24
- - flutter
25
- - ia-compliance
26
- - gate
27
- ---
28
-
29
- # IA Structure Compliance — Step 0 (Gate) for Flutter
30
-
31
- ## 검증 방법
32
-
33
- ```bash
34
- # 1. 실제 Flutter 구조 확인
35
- ls -R lib/ integrated_data_layer/lib/ 2>/dev/null
36
-
37
- # 2. git diff로 소유권 위반 검출 (이번 스프린트 범위)
38
- git log --name-only --pretty=format: HEAD~[sprint_commits].. | sort -u
39
- ```
40
-
41
- ## 검증 항목
42
-
43
- | 검증 | 판정 | 예시 |
44
- |------|------|------|
45
- | IA-MAP 경로가 실제 존재하는가 | 누락 → FAIL | `lib/ui/pages/` 미생성 |
46
- | IA-MAP에 없는 경로가 생겼는가 | 미등록 → DRIFT 기록 | `lib/services/` 무단 생성 |
47
- | `[FE]` 소유를 BE가 수정했는가 | 침범 → FAIL | `lib/ui/` BE 수정 |
48
- | `[META]`/`[HARNESS]` 침범 | 침범 → FAIL | `AGENTS.md` 수정 |
49
- | `pubspec.yaml` 의존성 추가가 계약 범위 내인가 | 범위 이탈 → DRIFT 기록 | 승인 없는 의존성 추가 |
50
-
51
- ## Flutter 전용 추가 검증
52
-
53
- | 검증 | 판정 |
54
- |------|------|
55
- | `integrated_data_layer/lib/2_data_sources/remote/` 내 파일이 프로젝트 컨벤션(`request/body/`, `response/`, `rest_api.dart`)을 지키는가 | 위반 → FAIL |
56
- | `lib/ui/pages/` 내 새 페이지가 `xxx_page.dart` + `xxx_page_vm.dart` 쌍으로 존재하는가 | 파트너 누락 → FAIL |
57
- | `bridges/` 하위에 신규 파일이 추가되었는가 | 추가 → FAIL (레거시 금지) |
58
- | `lib/l10n/` 의 arb 파일 키 집합이 모든 언어에서 동일한가 | 불일치 → FAIL |
59
-
60
- ## 판정 규칙
61
-
62
- - **경로 누락 / 소유권 침범 / 파트너 누락** → 즉시 FAIL, Step 1 이하 SKIP
63
- - **미등록 경로 (Drift)** → FAIL 아님, evaluation에 `## AGENTS.md Drift` 기록
64
- - **arb 키 불일치** → FAIL (i18n 원칙 위반)
65
-
66
- ## Output (evaluation-functional.md에 포함)
67
-
68
- ```markdown
69
- ## Step 0: IA Structure Compliance
70
- - Verdict: PASS / FAIL (GATE)
71
- - IA-MAP paths checked: [N]개
72
- - Missing paths: [목록 또는 "none"]
73
- - Unregistered paths: [목록 또는 "none"]
74
- - Ownership violations: [목록 또는 "none"]
75
- - Page/VM pair check: [N pages checked, N missing partners]
76
- - arb key diff: [none | "app_ja.arb missing: cancel, confirm"]
77
- ```
@@ -1,132 +0,0 @@
1
- ---
2
- docmeta:
3
- id: scoring-rubric
4
- title: Flutter Functional Evaluation 스코어링 루브릭
5
- type: output
6
- createdAt: 2026-04-09T00:00:00Z
7
- updatedAt: 2026-04-09T00:00:00Z
8
- source:
9
- producer: agent
10
- skillId: harness-evaluator-functional-flutter
11
- inputs:
12
- - documentId: react-evaluator-scoring-rubric
13
- uri: ../../evaluator-functional/references/scoring-rubric.md
14
- relation: output-from
15
- sections:
16
- - sourceRange:
17
- startLine: 1
18
- endLine: 53
19
- targetRange:
20
- startLine: 32
21
- endLine: 160
22
- tags:
23
- - evaluator
24
- - flutter
25
- - scoring
26
- - rubric
27
- ---
28
-
29
- # Flutter Functional Evaluation 스코어링 루브릭
30
-
31
- ## 차원별 채점
32
-
33
- | 차원 | 가중치 | 하드 임계값 | 측정 방법 |
34
- |------|--------|------------|----------|
35
- | Static Analysis | 25% | warning/error 0개 | `flutter analyze --no-fatal-infos` |
36
- | Test Pass Rate | 25% | 100% | `flutter test` 모든 스위트 |
37
- | API Contract 준수 | 25% | 100% | rest_api.dart vs api-contract.json 대조 — 불일치 즉시 FAIL |
38
- | Anti-Pattern 청결 | 15% | 위반 0건 | static-check-rules.md 의 FL-01 ~ FL-08 |
39
- | Contract Criteria 충족률 | 10% | 80% | sprint-contract.md FE 기준 통과 수 / 전체 |
40
-
41
- **어떤 차원이든 하드 임계값 미달 → 스프린트 FAIL**
42
-
43
- ## 차원별 점수 계산
44
-
45
- ### Static Analysis (25점)
46
-
47
- | 결과 | 점수 |
48
- |------|------|
49
- | error 0, warning 0 | 25 |
50
- | error 0, warning 1~2 | 0 (하드 임계값 미달 → FAIL) |
51
- | error 1+ | 0 (즉시 FAIL) |
52
-
53
- info 수준은 점수에 반영하지 않지만 보고서에 카운트 기록.
54
-
55
- ### Test Pass Rate (25점)
56
-
57
- ```
58
- score = 25 * (passed / total)
59
- ```
60
-
61
- - `total == 0` (테스트 존재하지 않음) → **0점 + FAIL** (Coverage gate)
62
- - `fromJson/toJson` 왕복 테스트 누락 (이번 스프린트 추가분) → **FAIL**
63
-
64
- ### API Contract 준수 (25점)
65
-
66
- ```
67
- score = 25 * (matched_endpoints / total_endpoints)
68
- ```
69
-
70
- 불일치 허용 없음 — 1개라도 불일치면 즉시 FAIL (하드 임계값 100%).
71
-
72
- 매칭 체크:
73
- - method (GET/POST/PUT/DELETE)
74
- - path (변수명 포함)
75
- - path param → `@Path(...)` 매핑
76
- - body → `@Body() XxxBody`
77
- - response 타입 → 계약 스키마의 code/data/errors 구조
78
-
79
- ### Anti-Pattern 청결 (15점)
80
-
81
- ```
82
- score = 15 * (passed_rules / total_rules)
83
- ```
84
-
85
- - 8개 룰 중 1개라도 FAIL → **0점 + 스프린트 FAIL**
86
- - 위반 0건이면 15점
87
-
88
- ### Contract Criteria 충족률 (10점)
89
-
90
- ```
91
- score = 10 * (passed_criteria / total_criteria)
92
- ```
93
-
94
- - 80% 미달 → FAIL
95
- - 개별 기준의 실패 사유를 "Failures Detail"에 기록
96
-
97
- ## Total
98
-
99
- ```
100
- total = static_analysis + test_pass + api_contract + anti_pattern + contract_criteria
101
- verdict = PASS (if all hard thresholds met AND total >= 80) else FAIL
102
- ```
103
-
104
- ## failure_location 라우팅
105
-
106
- Flutter 앱은 항상 FE 재작업이므로:
107
-
108
- | location | 재작업 대상 |
109
- |----------|-----------|
110
- | `frontend` (기본) | `generator-frontend-flutter` |
111
-
112
- 예외: API Contract 불일치가 **서버 측 계약 오류**로 확인된 경우 → Planner에게 계약 수정 요청 필요.
113
- 이 경우 evaluation에 `## Change Request` 섹션 추가.
114
-
115
- ## evaluation-functional.md 헤더
116
-
117
- ```markdown
118
- # Flutter Functional Evaluation: Sprint [N]
119
-
120
- ## Date: [YYYY-MM-DD]
121
- ## Verdict: PASS / FAIL
122
- ## Attempt: [N] / 10
123
- ## Stack: flutter
124
-
125
- ## Total Score: [N] / 100
126
- | Dimension | Score | Threshold | Status |
127
- | Static Analysis | X/25 | warning=0 | PASS/FAIL |
128
- | Test Pass Rate | X/25 | 100% | PASS/FAIL |
129
- | API Contract | X/25 | 100% | PASS/FAIL |
130
- | Anti-Pattern | X/15 | 0 violations | PASS/FAIL |
131
- | Contract Criteria | X/10 | 80% | PASS/FAIL |
132
- ```
@@ -1,99 +0,0 @@
1
- ---
2
- docmeta:
3
- id: static-check-rules
4
- title: Flutter 정적 검증 룰 (Anti-Pattern Gate)
5
- type: output
6
- createdAt: 2026-04-09T00:00:00Z
7
- updatedAt: 2026-04-09T00:00:00Z
8
- source:
9
- producer: agent
10
- skillId: harness-evaluator-functional-flutter
11
- inputs:
12
- - documentId: flutter-anti-patterns
13
- uri: ../../generator-frontend-flutter/references/anti-patterns.md
14
- relation: output-from
15
- sections:
16
- - sourceRange:
17
- startLine: 1
18
- endLine: 280
19
- targetRange:
20
- startLine: 32
21
- endLine: 180
22
- tags:
23
- - evaluator
24
- - flutter
25
- - static-check
26
- - anti-pattern
27
- ---
28
-
29
- # Flutter 정적 검증 룰
30
-
31
- Generator의 `anti-patterns.md` 를 Source of Truth 로 삼아 정적 검증을 수행한다.
32
- Generator가 신규 룰을 추가하면 Evaluator는 자동으로 그 룰을 따르게 된다 — **두 문서 간 drift 금지.**
33
-
34
- ## 실행 방법
35
-
36
- **Evaluator는 반드시** `skills/generator-frontend-flutter/references/anti-patterns.md` 의
37
- "셀프 체크 스크립트" 섹션을 **파일로 읽어서 그대로 실행**한다. 하네스의 단일 진실 원칙.
38
-
39
- ```bash
40
- # anti-patterns.md 에서 bash 블록만 추출해서 실행
41
- awk '/^```bash$/,/^```$/' skills/generator-frontend-flutter/references/anti-patterns.md
42
- ```
43
-
44
- ## 룰 요약 (Evaluator가 결과를 표로 정리)
45
-
46
- | Rule ID | 설명 | 명령 | Fail 조건 |
47
- |---------|------|------|----------|
48
- | FL-01 | 웹 API 직접 참조 | `grep -rn "dart:html\|universal_html" lib/ integrated_data_layer/lib/` | 매치 1+ |
49
- | FL-02 | print/console 남발 | `grep -rn "^\s*print(" lib/ integrated_data_layer/lib/` | 매치 1+ |
50
- | FL-03 | 하드코딩 색상 (신규) | `git diff --name-only --diff-filter=A HEAD~N..HEAD \| grep '\.dart$' \| xargs grep -n "Color(0x"` | 매치 1+ (`ColorManager` 참조 제외) |
51
- | FL-04 | StatefulWidget 직접 API 호출 | 수동 감사 — `_page.dart` 에 `dataLayer\|DataLayer` 호출이 있는데 짝 `_page_vm.dart` 없음 | 패턴 발견 |
52
- | FL-05 | bridges/ 신규 참조 | `git diff HEAD~N..HEAD \| grep "^+.*bridges/"` | 매치 1+ |
53
- | FL-06 | 하드코딩 한글 (신규 UI) | `git diff --name-only --diff-filter=AM HEAD~N..HEAD \| grep 'lib/ui/.*\.dart$' \| xargs grep -n "Text('[가-힣]"` | 매치 1+ |
54
- | FL-07 | JsonSerializable includeIfNull 누락 | `grep -rn "@JsonSerializable" integrated_data_layer/lib/2_data_sources/remote/request/body/ \| grep -v "includeIfNull: false"` | 매치 1+ |
55
- | FL-08 | API 키/시크릿 하드코딩 | `grep -rEn "(api[_-]?key\|secret\|token)\s*=\s*['\"][A-Za-z0-9]{16,}['\"]" lib/ integrated_data_layer/lib/` | 매치 1+ |
56
-
57
- > `HEAD~N` 의 N은 sprint_commits 수 — `git log --format=%h HEAD~sprint_start..HEAD` 로 결정.
58
-
59
- ## FL-04 수동 감사 방법
60
-
61
- ```bash
62
- # 1. 신규/수정된 page 파일 목록
63
- PAGES=$(git diff --name-only HEAD~N..HEAD | grep '_page\.dart$')
64
-
65
- # 2. 각 page에서 API 호출 존재 여부
66
- for p in $PAGES; do
67
- if grep -q "dataLayer\|DataLayer" "$p"; then
68
- vm="${p%_page.dart}_page_vm.dart"
69
- if [ -f "$vm" ] && grep -q "dataLayer\|DataLayer" "$vm"; then
70
- echo "OK (VM handles API): $p"
71
- else
72
- echo "FAIL (page calls API without VM): $p"
73
- fi
74
- fi
75
- done
76
- ```
77
-
78
- VM이 없고 페이지가 직접 호출하면 **FL-04 FAIL**.
79
-
80
- ## 결과 집계
81
-
82
- ```markdown
83
- ## Step 4: Anti-Pattern
84
-
85
- | Rule | Status | Count | Files |
86
- |------|--------|-------|-------|
87
- | FL-01 dart:html | PASS/FAIL | 0 | - |
88
- | FL-02 print | PASS/FAIL | 0 | - |
89
- | FL-03 color hardcode | PASS/FAIL | 0 | - |
90
- | FL-04 stateful API call | PASS/FAIL | 0 | - |
91
- | FL-05 bridges/ new | PASS/FAIL | 0 | - |
92
- | FL-06 ko hardcode | PASS/FAIL | 0 | - |
93
- | FL-07 includeIfNull missing | PASS/FAIL | 0 | - |
94
- | FL-08 secret hardcode | PASS/FAIL | 0 | - |
95
-
96
- Overall: PASS / FAIL
97
- ```
98
-
99
- **어떤 룰이든 FAIL 1건 → Step 4 전체 FAIL → 스프린트 FAIL** (하드 임계값: 위반 0건).
@@ -1,173 +0,0 @@
1
- ---
2
- name: harness-generator-frontend-flutter
3
- description: "하네스 Flutter Frontend Generator. Flutter(Dart) + Riverpod + integrated_data_layer(Retrofit) 기반 모바일 앱을 구현한다. ARB 다국어, JsonSerializable, NotifierProvider 패턴 준수. api-contract.json이 Source of Truth — UI 추론 금지."
4
- disable-model-invocation: true
5
- ---
6
-
7
- # Generator-Frontend-Flutter — Dart + Riverpod + integrated_data_layer
8
-
9
- ## Session Boundary Protocol
10
-
11
- ### On Start
12
- 1. `.harness/progress.json` 읽기 — `next_agent`가 `"generator-frontend-flutter"`인지 확인
13
- 2. `.harness/actions/pipeline.json`의 `fe_stack == "flutter"` 재확인 — 아니면 즉시 STOP + 사용자에게 불일치 보고
14
- 3. progress.json 업데이트: `current_agent` → `"generator-frontend-flutter"`, `agent_status` → `"running"`, `updated_at` 갱신
15
- 4. `failure` 필드 확인 — retry인 경우 평가 문서의 실패 사유 우선 읽기
16
-
17
- ### On Complete
18
- 1. progress.json 업데이트:
19
- - `agent_status` → `"completed"`
20
- - `completed_agents`에 `"generator-frontend-flutter"` 추가
21
- - `next_agent` → `"evaluator-functional-flutter"`
22
- - `failure` 필드 초기화
23
- 2. `feature-list.json`의 해당 feature `passes`에 `"generator-frontend-flutter"` 추가
24
- 3. `.harness/progress.log`에 요약 추가
25
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
26
- 5. 출력: `"✓ Generator-Frontend-Flutter 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
27
-
28
- ## Startup
29
-
30
- 1. `AGENTS.md` 읽기 — IA-MAP, 권한 확인 (Flutter 소유 경로)
31
- 2. `.harness/gotchas/generator-frontend-flutter.md` 읽기 (없으면 skip) — **과거 실수 반복 금지**
32
- 3. `.harness/memory.md` 읽기 — **프로젝트 공유 학습 규칙 적용**
33
- 4. `pwd` + `.harness/progress.json` + `git log --oneline -20`
34
- 5. `.harness/actions/api-contract.json` 읽기 — **서버 API 계약이 Source of Truth**
35
- 6. `.harness/actions/feature-list.json` — `layer: "frontend"` 필터
36
- 7. `.harness/actions/pipeline.json` 의 **`fe_target`** 확인 (`web` | `mobile` | `desktop`)
37
- - 이 값에 따라 허용되는 API, 빌드 명령, 안티패턴이 달라진다 (아래 "fe_target 분기" 섹션 참조)
38
- 8. `pubspec.yaml` 확인 — Flutter 버전, Riverpod/Retrofit/json_serializable 의존성 존재 확인
39
- - `fe_target = web` 인 경우 `flutter config --enable-web` 활성화 + `web/index.html` 존재 확인
40
-
41
- ## AGENTS.md — 읽기 전용
42
-
43
- `[FE]` + `→ Generator-Frontend-Flutter` 소유 경로만 쓰기 가능. 일반적으로:
44
- - `lib/ui/pages/`, `lib/ui/component/`, `lib/l10n/`
45
- - `integrated_data_layer/lib/`, `integrated_data_layer/test/`
46
- - `assets/strings/`
47
-
48
- Backend 코드, `.harness/`, `AGENTS.md` 수정 금지.
49
-
50
- ## Sprint Workflow
51
-
52
- 1. **Sprint Contract FE 섹션 추가** — 페이지, VM, API 연동, 성공 기준
53
- 2. **api-contract.json → Retrofit/JsonSerializable 변환**
54
- 3. **구현** — 아래 4개 레퍼런스를 반드시 참조
55
- 4. **코드 생성**: `flutter pub run build_runner build --delete-conflicting-outputs`
56
- 5. **Self-Verification** — `flutter analyze` + `flutter test` 통과
57
- 6. **Handoff** → Evaluator-Functional-Flutter
58
-
59
- ## 개발론 레퍼런스 (점진적 로딩)
60
-
61
- | 문서 | 내용 | 언제 로드 |
62
- |------|------|----------|
63
- | [API Layer Pattern](references/api-layer-pattern.md) | integrated_data_layer 구조, Request/Response, Retrofit | API 연동 시 |
64
- | [Riverpod Pattern](references/riverpod-pattern.md) | Page+VM 쌍, NotifierProvider, family 패턴 | 페이지/위젯 구현 시 |
65
- | [i18n Pattern](references/i18n-pattern.md) | ARB 파일, LocaleAssist, 키 네이밍 | 문자열 추가 시 |
66
- | [Anti-Patterns](references/anti-patterns.md) | 금지 API, 하드코딩, bridges/, StatefulWidget 직접 호출 (fe_target 별 차이 포함) | 구현 완료 후 셀프 체크 |
67
- | [Flutter Web Pattern](references/flutter-web-pattern.md) | Web 전용 — `dart:html`/`package:web` 허용, 라우팅, 빌드, hosting | `fe_target = web` 일 때만 |
68
-
69
- ## fe_target 분기
70
-
71
- `pipeline.json.fe_target` 에 따라 적용되는 규칙이 다르다:
72
-
73
- ### `fe_target = web` (Flutter Web)
74
-
75
- - **빌드**: `flutter build web --release` / 개발 서버: `flutter run -d chrome`
76
- - **HTML/JS 인터롭 허용**: `dart:html`, `package:web`, `dart:js_interop` 사용 가능
77
- - 단, 가능하면 cross-platform 코드를 우선하고 web 전용 코드는 `if (kIsWeb)` 가드 또는 conditional import
78
- - **라우팅**: `go_router` 권장 (URL 동기화). `Navigator 1.0` 의 `MaterialApp.routes` 도 OK 지만 hash routing 주의
79
- - **자산**: `web/index.html`, `web/manifest.json`, `web/icons/` 관리. SEO 가 필요하면 `<meta>` 태그 명시
80
- - **CORS**: 백엔드 API 가 `localhost:포트` 에서 다른 origin 일 수 있으므로 CORS 설정 확인
81
- - **Eval 흐름**: Playwright 기반 `evaluator-functional` + `evaluator-visual` 이 정상 작동 (브라우저 E2E + 시각 검증)
82
- - 상세 → [Flutter Web Pattern](references/flutter-web-pattern.md)
83
-
84
- ### `fe_target = mobile` (Android / iOS)
85
-
86
- - **빌드**: `flutter build apk` / `flutter build ios` / 개발: `flutter run -d <device>`
87
- - **HTML/JS 인터롭 금지**: `dart:html`, `package:web`, `universal_html` 직접 참조 → 빌드 실패
88
- - **플랫폼 채널**: 네이티브 기능 사용 시 `MethodChannel` 또는 검증된 plugin 사용
89
- - **권한**: `AndroidManifest.xml` / `Info.plist` 에 권한 명시
90
- - **Eval 흐름**: 정적 분석 기반 `evaluator-functional-flutter` 사용 (Playwright 불가)
91
-
92
- ### `fe_target = desktop` (macOS / Windows / Linux)
93
-
94
- - **빌드**: `flutter build macos` / `flutter build windows` / `flutter build linux`
95
- - **HTML/JS 인터롭 금지**: 모바일과 동일
96
- - **윈도우 관리**: `window_manager` 등 플러그인으로 윈도우 크기/위치 제어
97
- - **Eval 흐름**: 정적 분석 기반 `evaluator-functional-flutter` 사용
98
-
99
- ## 핵심 규칙
100
-
101
- ### api-contract.json → Dart 변환 규칙
102
-
103
- - 각 엔드포인트 → `rest_api.dart`에 Retrofit 어노테이션 (`@GET`, `@POST`, `@PUT`, `@DELETE`)
104
- - Request body → `2_data_sources/remote/request/body/xxx_body.dart` (`@JsonSerializable(includeIfNull: false)`)
105
- - Response → `2_data_sources/remote/response/xxx_response.dart` (`ClueResponseImpl<T>` 상속 or 재사용)
106
- - **필수 지시가 없으면 모든 필드는 Nullable** — 서버가 언제든 필드를 누락할 수 있음
107
- - **기존 응답 타입 재사용 우선** — 동일 구조면 새 클래스 생성 금지
108
- - Repository 래퍼 메서드 추가 → `1_repositories/xxx_repository.dart`
109
-
110
- ### UI / 상태관리
111
-
112
- - 모든 페이지 = `xxx_page.dart` + `xxx_page_vm.dart` 쌍
113
- - Page는 `ConsumerStatefulWidget` 또는 `ConsumerWidget`
114
- - VM은 `NotifierProvider<Notifier, State>` (다중 인스턴스는 `.family`)
115
- - State는 `Equatable` + `copyWith` 불변성
116
- - `ref.watch` (build 내) / `ref.read` (이벤트 핸들러, initState)
117
- - API 호출은 반드시 VM 안에서 `ref.read(dataLayer).xxx.method()`
118
- - Provider 네이밍: `p` + PascalCase + `Provider` (예: `pHomePageProvider`)
119
-
120
- ### 다국어 (i18n)
121
-
122
- - 영문 전용 지시가 없는 한 **모든 사용자 노출 문자열은 ARB 경유 필수**
123
- - ARB: `lib/l10n/app_en.arb`, `app_ko.arb`, `app_ja.arb`
124
- - 코드 접근: `LocaleAssist().of.키이름`
125
- - 키 네이밍: camelCase (예: `doorOpen`, `networkError`)
126
- - 모든 언어 파일에 동일 키 동시 추가
127
-
128
- ### 코드 생성
129
-
130
- Request Body / Response / rest_api.dart 수정 후 **반드시** 실행:
131
-
132
- ```bash
133
- cd <integrated_data_layer 경로>
134
- flutter pub run build_runner build --delete-conflicting-outputs
135
- ```
136
-
137
- ## Self-Verification (Handoff 전)
138
-
139
- 1. `flutter analyze` → 경고 0개 (info 수준은 허용, warning/error 금지)
140
- 2. `flutter test` → 100% 통과
141
- 3. integrated_data_layer의 새 Request Body / Response에 `fromJson`/`toJson` 왕복 테스트 존재
142
- 4. `grep -rn 'dart:html\|universal_html\|print(\|console\.log' lib/ integrated_data_layer/lib/` → 0개
143
- 5. `grep -rn "bridges/" lib/` → 신규 코드 내 참조 0개
144
- 6. 하드코딩 색상(`Color(0xFF...`) → `ColorManager` 경유 확인
145
- 7. 새 페이지/위젯은 `StatefulWidget`에서 직접 API 호출하지 않는지 확인 (VM/Provider 경유)
146
-
147
- ## 금지 사항
148
-
149
- - Backend 코드 수정, 서버 API 경로 임의 변경
150
- - api-contract.json에 없는 엔드포인트 호출/추가
151
- - `dart:html`, `universal_html` 직접 참조
152
- - `print()` / `debugPrint` 남발 — `logger` 사용
153
- - 하드코딩 색상 → `ColorManager` 강제
154
- - `StatefulWidget` 내 직접 API 호출 → VM/Provider 경유
155
- - `bridges/` 신규 개발 — BLOC 기반 레거시, 유지보수만 허용
156
- - AI 추측으로 서버 응답 구조를 만들지 말 것 (계약이 Source of Truth)
157
- - API 키/시크릿 하드코딩
158
-
159
- ## 명령어
160
-
161
- ```bash
162
- flutter pub get # 의존성
163
- flutter run # 실행
164
- flutter test # 테스트
165
- flutter analyze # 정적 분석
166
- flutter pub run build_runner build --delete-conflicting-outputs # 코드 생성
167
- ```
168
-
169
- ## After Completion
170
-
171
- 1. sprint-contract.md의 FE 섹션에 완료 항목 체크
172
- 2. Self-Verification 체크리스트 결과 요약
173
- 3. Session Boundary Protocol On Complete 실행