@walwal-harness/cli 2.0.1 → 2.3.0
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.
- package/assets/templates/config.json +41 -1
- package/bin/init.js +65 -3
- package/package.json +5 -2
- package/scripts/harness-next.sh +36 -1
- package/scripts/harness-user-prompt-submit.sh +106 -0
- package/scripts/lib/harness-render-progress.sh +15 -1
- package/scripts/scan-project.sh +24 -2
- package/skills/brainstorming/SKILL.md +200 -0
- package/skills/brainstorming/references/attribution.md +109 -0
- package/skills/brainstorming/references/spec-document-reviewer-prompt.md +49 -0
- package/skills/brainstorming/references/visual-companion.md +287 -0
- package/skills/brainstorming/scripts/frame-template.html +214 -0
- package/skills/brainstorming/scripts/helper.js +88 -0
- package/skills/brainstorming/scripts/server.cjs +354 -0
- package/skills/brainstorming/scripts/start-server.sh +148 -0
- package/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/skills/dispatcher/SKILL.md +114 -2
- package/skills/dispatcher/references/pipeline-definitions.md +53 -5
- package/skills/evaluator-functional-flutter/SKILL.md +198 -0
- package/skills/evaluator-functional-flutter/references/ia-compliance.md +77 -0
- package/skills/evaluator-functional-flutter/references/scoring-rubric.md +132 -0
- package/skills/evaluator-functional-flutter/references/static-check-rules.md +99 -0
- package/skills/generator-frontend-flutter/SKILL.md +138 -0
- package/skills/generator-frontend-flutter/references/anti-patterns.md +288 -0
- package/skills/generator-frontend-flutter/references/api-layer-pattern.md +233 -0
- package/skills/generator-frontend-flutter/references/i18n-pattern.md +102 -0
- package/skills/generator-frontend-flutter/references/riverpod-pattern.md +199 -0
- package/skills/planner/SKILL.md +23 -1
- package/skills/planner/references/fe-stack-detection.md +131 -0
|
@@ -16,13 +16,31 @@ disable-model-invocation: false
|
|
|
16
16
|
1. progress.json 업데이트:
|
|
17
17
|
- `agent_status` → `"completed"`
|
|
18
18
|
- `completed_agents`에 `"dispatcher"` 추가
|
|
19
|
-
- `next_agent` →
|
|
19
|
+
- `next_agent` → **브레인스토밍 결정 트리에 따라 결정** ([섹션 6](#6-brainstormer-routing-decision) 참조)
|
|
20
|
+
- 신규/재플래닝 + 사용자가 브레인스토밍 선택 → `"brainstorming"`
|
|
21
|
+
- 신규/재플래닝 + 사용자가 건너뛰기 선택 → `"planner"`
|
|
22
|
+
- 특정 에이전트 직접 명령 → 해당 에이전트 (예: `"evaluator-functional"`)
|
|
23
|
+
- Gotcha 교정 후 재작업 → `failure.retry_target` (해당 에이전트)
|
|
20
24
|
- `pipeline` → 선택된 파이프라인 (FULLSTACK/FE-ONLY/BE-ONLY)
|
|
21
|
-
- `sprint.number` → `1`, `sprint.status` → `"in_progress"`
|
|
25
|
+
- `sprint.number` → `1`, `sprint.status` → `"in_progress"` (신규 파이프라인인 경우에만)
|
|
22
26
|
2. `.harness/progress.log`에 요약 한 줄 추가
|
|
23
27
|
3. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
|
|
24
28
|
4. 출력: `"✓ Dispatcher 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
|
|
25
29
|
|
|
30
|
+
## Auto-Routing (UserPromptSubmit Hook)
|
|
31
|
+
|
|
32
|
+
walwal-harness v2.2.0+ 부터 **UserPromptSubmit 훅** 이 모든 사용자 프롬프트 앞에
|
|
33
|
+
`[walwal-harness] Auto-routing is ACTIVE` 안내를 자동 주입한다. 이 훅이 켜져 있으면
|
|
34
|
+
Claude 는 기본적으로 Dispatcher 경유로 분류/라우팅해야 한다.
|
|
35
|
+
|
|
36
|
+
- **활성 조건**: `.harness/config.json` 의 `behavior.auto_route_dispatcher == true`
|
|
37
|
+
- **per-message opt-out**: 사용자가 `harness skip`, `harness 없이`, `without harness`,
|
|
38
|
+
`just answer` 등을 말하면 그 메시지 한정으로 훅이 pass-through
|
|
39
|
+
- **전역 비활성**: `behavior.auto_route_dispatcher = false`
|
|
40
|
+
|
|
41
|
+
훅이 주입하는 컨텍스트에는 `pipeline`, `current_agent`, `next_agent`, `sprint`,
|
|
42
|
+
`fe_stack` 현재값이 포함되므로 Dispatcher 는 별도 상태 조회 없이 판단 가능.
|
|
43
|
+
|
|
26
44
|
## 1. Request Classification (최우선)
|
|
27
45
|
|
|
28
46
|
사용자 입력을 먼저 분류합니다:
|
|
@@ -30,6 +48,7 @@ disable-model-invocation: false
|
|
|
30
48
|
- **실수 지적** ("아니", "잘못", "그렇게 하면 안 돼", "X로 해야지") → **Gotcha Flow**
|
|
31
49
|
- **기능 요청** ("만들어", "추가", "시작", PRD, OpenAPI) → **Pipeline Flow**
|
|
32
50
|
- **혼합** → Gotcha 먼저 기록 → Pipeline 이어서
|
|
51
|
+
- **메타/인사/Claude 자체 질문** → Dispatcher skip, 짧은 일반 응답 허용
|
|
33
52
|
|
|
34
53
|
## 2. Gotcha Flow
|
|
35
54
|
|
|
@@ -68,3 +87,96 @@ AGENTS.md 비하네스 → 기존 백업 + 리빌드
|
|
|
68
87
|
## 5. Output
|
|
69
88
|
|
|
70
89
|
`.harness/actions/pipeline.json` 생성 → 사용자 확인 → Session Boundary Protocol On Complete 실행
|
|
90
|
+
|
|
91
|
+
### fe_stack 필드 (FE 파이프라인에서 필수)
|
|
92
|
+
|
|
93
|
+
FE-ONLY 또는 FULLSTACK 선택 시, `pipeline.json`에 **`fe_stack`** 필드를 포함해야 한다:
|
|
94
|
+
|
|
95
|
+
- `scan-result.json.tech_stack.fe_stack` 값을 기본으로 사용 (`react` | `flutter`)
|
|
96
|
+
- 값이 없거나 불명확하면 Planner가 확정하도록 위임 (Dispatcher는 `"unknown"` 기록 + `notes` 에 메모)
|
|
97
|
+
- Flutter 선택 시 `agents_active`/`agents_skipped`에 치환된 에이전트명을 기록
|
|
98
|
+
- active: `generator-frontend-flutter`, `evaluator-functional-flutter`
|
|
99
|
+
- skipped: `generator-frontend`, `evaluator-functional`, `evaluator-visual`
|
|
100
|
+
|
|
101
|
+
## 6. Brainstormer Routing Decision
|
|
102
|
+
|
|
103
|
+
**원칙**: Brainstormer 는 파이프라인의 고정 스텝이 **아니다**. Dispatcher 가 조건부로 삽입한다.
|
|
104
|
+
|
|
105
|
+
### 6.1 결정 트리
|
|
106
|
+
|
|
107
|
+
Dispatcher 는 사용자 요청을 분류한 뒤 아래 순서로 판단:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
1. Gotcha / 실수 지적인가?
|
|
111
|
+
→ YES: gotcha 기록 → next_agent = failure.retry_target (해당 에이전트)
|
|
112
|
+
(브레인스토밍 없음)
|
|
113
|
+
|
|
114
|
+
2. 특정 에이전트 직접 명령인가?
|
|
115
|
+
("evaluator 다시 돌려", "generator-frontend 재작업", "planner plan.md 고쳐" 등)
|
|
116
|
+
→ YES: next_agent = <대상 에이전트> (브레인스토밍 없음)
|
|
117
|
+
|
|
118
|
+
3. Planner 가 동작해야 하는 케이스인가?
|
|
119
|
+
(신규 파이프라인 / 신규 PRD / 기존 plan.md 대폭 수정 / 신규 feature 대규모 추가)
|
|
120
|
+
→ YES: 사용자에게 확인 질문 → 6.2 "브레인스토밍 확인 플로우"
|
|
121
|
+
→ NO: 다른 에이전트로 라우팅 (generator 이어서 등)
|
|
122
|
+
|
|
123
|
+
4. 그 외 (메타/인사/Claude 자체 질문) → Dispatcher skip
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 6.2 브레인스토밍 확인 플로우
|
|
127
|
+
|
|
128
|
+
Planner 를 호출해야 한다고 판단되면, **사용자에게 단 하나의 질문을 출력한 뒤 대기한다:**
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
이 요청은 Planner 가 처리할 신규/재플래닝 건으로 보입니다.
|
|
132
|
+
러프한 요구사항을 먼저 구체화하는 Brainstormer 과정을 거칠까요?
|
|
133
|
+
|
|
134
|
+
(Y) 예 — Brainstormer 와 대화하며 요구사항을 fit 하게 만든 뒤 Planner
|
|
135
|
+
(N) 아니오 — 이미 PRD/OpenAPI 가 명확하므로 바로 Planner
|
|
136
|
+
|
|
137
|
+
답변: Y / N
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
사용자 응답 처리:
|
|
141
|
+
- **Y (긍정)** — "네", "y", "yes", "필요해", "해줘" 등
|
|
142
|
+
→ `next_agent = "brainstorming"`
|
|
143
|
+
- **N (부정)** — "아니오", "n", "no", "필요없어", "바로", "skip" 등
|
|
144
|
+
→ `next_agent = "planner"`
|
|
145
|
+
- **불명확 / 무응답** — 한 번 더 "Y 또는 N 으로 답해주세요" 요청
|
|
146
|
+
|
|
147
|
+
### 6.3 Skip 케이스 정리
|
|
148
|
+
|
|
149
|
+
브레인스토밍이 **실행되지 않는** 경우 (Dispatcher 가 직접 다른 에이전트로 라우팅):
|
|
150
|
+
|
|
151
|
+
| 상황 | next_agent |
|
|
152
|
+
|------|-----------|
|
|
153
|
+
| "Eval, X 다시 검증해" | `evaluator-functional` (또는 `evaluator-visual`) |
|
|
154
|
+
| "Generator-FE, Y 버그 고쳐" | `generator-frontend` (또는 Flutter 변형) |
|
|
155
|
+
| "Generator-BE, API 재생성해" | `generator-backend` |
|
|
156
|
+
| Eval FAIL → retry | `failure.retry_target` |
|
|
157
|
+
| Gotcha 수정 | `failure.retry_target` 또는 현재 에이전트 |
|
|
158
|
+
| 기존 plan.md 소폭 수정 (Dispatcher 판단) | `planner` (직접) |
|
|
159
|
+
| 사용자가 "Brainstormer 없이" / "skip brainstorming" 명시 | `planner` (직접) |
|
|
160
|
+
|
|
161
|
+
### 6.4 강제 호출 케이스
|
|
162
|
+
|
|
163
|
+
사용자가 명시적으로 원하면 브레인스토밍은 언제든 재호출 가능:
|
|
164
|
+
|
|
165
|
+
- "Brainstormer 다시 돌려줘"
|
|
166
|
+
- "요구사항 다시 잡자"
|
|
167
|
+
- "plan 처음부터"
|
|
168
|
+
|
|
169
|
+
이 경우 기존 `.harness/actions/brainstorm-spec.md` 는 Brainstormer 의 On Start 에서
|
|
170
|
+
`.harness/archive/brainstorm-spec-<timestamp>.md` 로 백업된다.
|
|
171
|
+
|
|
172
|
+
## 7. Handoff 라우팅 (fe_stack 반영)
|
|
173
|
+
|
|
174
|
+
Dispatcher가 `next_agent` 를 세팅할 때 pipeline.json.fe_stack 을 참조해 치환:
|
|
175
|
+
|
|
176
|
+
| 원본 next_agent | fe_stack=react | fe_stack=flutter |
|
|
177
|
+
|-----------------|----------------|------------------|
|
|
178
|
+
| generator-frontend | generator-frontend | generator-frontend-flutter |
|
|
179
|
+
| evaluator-functional (FE 단계) | evaluator-functional | evaluator-functional-flutter |
|
|
180
|
+
| evaluator-visual | evaluator-visual | (skip → 다음 단계로 이동) |
|
|
181
|
+
|
|
182
|
+
**Brainstormer 는 fe_stack 치환 대상이 아니다** — 언어/스택 무관 공통 에이전트.
|
|
@@ -1,5 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
docmeta:
|
|
3
|
+
id: pipeline-definitions
|
|
4
|
+
title: Pipeline Definitions
|
|
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-dispatcher
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: harness-dispatcher-skill
|
|
13
|
+
uri: ../SKILL.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
sections:
|
|
16
|
+
- sourceRange:
|
|
17
|
+
startLine: 58
|
|
18
|
+
endLine: 70
|
|
19
|
+
targetRange:
|
|
20
|
+
startLine: 30
|
|
21
|
+
endLine: 95
|
|
22
|
+
tags:
|
|
23
|
+
- dispatcher
|
|
24
|
+
- pipeline
|
|
25
|
+
- fe-stack
|
|
26
|
+
- flutter
|
|
27
|
+
---
|
|
28
|
+
|
|
1
29
|
# Pipeline Definitions
|
|
2
30
|
|
|
31
|
+
> **FE Stack 차원**: 모든 FE 관련 파이프라인은 `fe_stack` 필드로 React/Flutter를 구분한다.
|
|
32
|
+
> Planner가 scan-result.json(`tech_stack.fe_stack`) 또는 사용자 질문으로 확정한다.
|
|
33
|
+
|
|
34
|
+
## fe_stack 스위치 매트릭스
|
|
35
|
+
|
|
36
|
+
| fe_stack | FE Generator | FE Evaluator(Functional) | Evaluator-Visual |
|
|
37
|
+
|----------|--------------|--------------------------|------------------|
|
|
38
|
+
| `react` | `generator-frontend` | `evaluator-functional` (Playwright MCP) | `evaluator-visual` |
|
|
39
|
+
| `flutter`| `generator-frontend-flutter` | `evaluator-functional-flutter` (flutter analyze/test) | **SKIP** (브라우저 없음) |
|
|
40
|
+
|
|
41
|
+
Dispatcher는 `next_agent`를 설정할 때 다음 규칙으로 치환한다:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
if pipeline.json.fe_stack == "flutter":
|
|
45
|
+
"generator-frontend" → "generator-frontend-flutter"
|
|
46
|
+
"evaluator-functional" (FE 단계) → "evaluator-functional-flutter"
|
|
47
|
+
"evaluator-visual" → skip (agents_skipped로 이동)
|
|
48
|
+
```
|
|
49
|
+
|
|
3
50
|
## FE-ONLY
|
|
4
51
|
|
|
5
52
|
```yaml
|
|
@@ -7,16 +54,17 @@ trigger: 외부 API 존재 + FE 작업 요청
|
|
|
7
54
|
agents:
|
|
8
55
|
- planner (light):
|
|
9
56
|
skip: MSA 서비스 설계, BE 기능 목록
|
|
10
|
-
do: OpenAPI → api-contract.json 변환, FE 컴포넌트 설계, feature-list (layer: frontend만)
|
|
11
|
-
- generator-frontend
|
|
12
|
-
- evaluator-functional
|
|
13
|
-
- evaluator-visual
|
|
57
|
+
do: OpenAPI → api-contract.json 변환, FE 컴포넌트 설계, feature-list (layer: frontend만), fe_stack 확정
|
|
58
|
+
- generator-frontend OR generator-frontend-flutter # fe_stack에 따라
|
|
59
|
+
- evaluator-functional OR evaluator-functional-flutter
|
|
60
|
+
- evaluator-visual # fe_stack == "flutter" 이면 SKIP
|
|
14
61
|
skip:
|
|
15
62
|
- generator-backend
|
|
16
63
|
notes:
|
|
17
64
|
- api-contract.json은 OpenAPI에서 파생 (Planner가 변환)
|
|
18
|
-
- Eval-Func의 API Health Check는 외부 서버 대상
|
|
65
|
+
- Eval-Func(React)의 API Health Check는 외부 서버 대상
|
|
19
66
|
- AGENTS.md IA-MAP에 BE 경로 없음 (외부 서버)
|
|
67
|
+
- fe_stack=flutter 인 경우 evaluator-visual 생략
|
|
20
68
|
```
|
|
21
69
|
|
|
22
70
|
## BE-ONLY
|
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
> **주의**: Flutter 앱은 브라우저가 아니므로 Playwright MCP(`browser_*`)를 쓸 수 없다.
|
|
10
|
+
> 이 에이전트는 `flutter analyze`, `flutter test`, `dart format`, 정적 grep 검증, 생성 파일 일관성으로 평가한다.
|
|
11
|
+
> 실기기/시뮬레이터 UI 검증은 사람 QA 또는 별도 파이프라인으로 위임.
|
|
12
|
+
|
|
13
|
+
## Session Boundary Protocol
|
|
14
|
+
|
|
15
|
+
### On Start
|
|
16
|
+
1. `.harness/progress.json` 읽기 — `next_agent`가 `"evaluator-functional-flutter"`인지 확인
|
|
17
|
+
2. `.harness/actions/pipeline.json.fe_stack == "flutter"` 재확인 — 아니면 즉시 STOP + 불일치 보고
|
|
18
|
+
3. progress.json 업데이트: `current_agent` → `"evaluator-functional-flutter"`, `agent_status` → `"running"`, `updated_at` 갱신
|
|
19
|
+
|
|
20
|
+
### On Complete (PASS)
|
|
21
|
+
1. progress.json 업데이트:
|
|
22
|
+
- `agent_status` → `"completed"`
|
|
23
|
+
- `completed_agents`에 `"evaluator-functional-flutter"` 추가
|
|
24
|
+
- `next_agent` → `"archive"` (fe_stack=flutter 이면 evaluator-visual 생략)
|
|
25
|
+
- `failure` 필드 초기화
|
|
26
|
+
2. `feature-list.json`의 통과 feature `passes`에 `"evaluator-functional-flutter"` 추가
|
|
27
|
+
3. `.harness/progress.log`에 PASS 요약 추가
|
|
28
|
+
4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
|
|
29
|
+
5. 출력: `"✓ Evaluator-Functional-Flutter PASS. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
|
|
30
|
+
|
|
31
|
+
### On Fail
|
|
32
|
+
1. progress.json 업데이트:
|
|
33
|
+
- `agent_status` → `"failed"`
|
|
34
|
+
- `failure.agent` → `"evaluator-functional-flutter"`
|
|
35
|
+
- `failure.location` → `"frontend"` (Flutter 앱은 항상 FE 재작업)
|
|
36
|
+
- `failure.message` → 실패 요약 (1줄)
|
|
37
|
+
- `failure.retry_target` → `"generator-frontend-flutter"`
|
|
38
|
+
- `next_agent` → `"generator-frontend-flutter"`
|
|
39
|
+
- `sprint.retry_count` 증가
|
|
40
|
+
2. `sprint.retry_count >= 10`이면 `agent_status` → `"blocked"`, 사용자 개입 요청
|
|
41
|
+
3. `.harness/progress.log`에 FAIL 요약 추가
|
|
42
|
+
4. **STOP.**
|
|
43
|
+
5. 출력: `"✖ Evaluator-Functional-Flutter FAIL. bash scripts/harness-next.sh 실행하여 재작업 대상 확인."`
|
|
44
|
+
|
|
45
|
+
## Critical Mindset
|
|
46
|
+
|
|
47
|
+
- **회의적 평가자**. Generator의 자체 평가를 신뢰하지 말고 직접 돌려라.
|
|
48
|
+
- `flutter analyze` 경고가 있으면 "사소하다"고 자기 설득 금지 — 기준 미달.
|
|
49
|
+
- 코드 읽기만으로 PASS 판정 금지 — **반드시 `flutter analyze` + `flutter test` 실행**.
|
|
50
|
+
- 기준 미달 = FAIL. 예외 없음.
|
|
51
|
+
|
|
52
|
+
## Startup
|
|
53
|
+
|
|
54
|
+
1. `AGENTS.md` 읽기 — IA-MAP (Flutter 경로 확인)
|
|
55
|
+
2. `.harness/gotchas/evaluator-functional-flutter.md` (없으면 skip) — **과거 실수 반복 금지**
|
|
56
|
+
3. `actions/sprint-contract.md` — FE 성공 기준
|
|
57
|
+
4. `actions/feature-list.json` — 이번 스프린트 범위 (`layer: "frontend"` + `fe_stack: "flutter"`)
|
|
58
|
+
5. `actions/api-contract.json` — 기대 API 계약 (Retrofit 매핑 대조용)
|
|
59
|
+
6. `.harness/progress.json`
|
|
60
|
+
7. **Generator의 anti-patterns.md 로드** — 정적 검증 rule 소스
|
|
61
|
+
→ `skills/generator-frontend-flutter/references/anti-patterns.md`
|
|
62
|
+
|
|
63
|
+
## Evaluation Steps
|
|
64
|
+
|
|
65
|
+
### Step 0: IA Structure Compliance (GATE)
|
|
66
|
+
|
|
67
|
+
AGENTS.md IA-MAP vs 실제 구조 대조. **미통과 시 이하 전체 SKIP, 즉시 FAIL.**
|
|
68
|
+
|
|
69
|
+
상세 → [IA 검증 가이드](references/ia-compliance.md)
|
|
70
|
+
|
|
71
|
+
### Step 1: `flutter analyze` (정적 분석)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# 프로젝트 루트 또는 integrated_data_layer 하위에서
|
|
75
|
+
flutter analyze --no-fatal-infos
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
- **warning / error 1개 이상 → FAIL**
|
|
79
|
+
- info 수준은 허용 (하지만 evaluation 보고서에 카운트 기록)
|
|
80
|
+
|
|
81
|
+
### Step 2: `flutter test` (단위/위젯 테스트)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# integrated_data_layer 테스트
|
|
85
|
+
cd <integrated_data_layer 경로>
|
|
86
|
+
flutter test
|
|
87
|
+
|
|
88
|
+
# 앱 테스트 (존재 시)
|
|
89
|
+
cd <app 루트>
|
|
90
|
+
flutter test
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
- **실패 1개 이상 → FAIL**
|
|
94
|
+
- 이번 스프린트에서 추가된 Request Body / Response에 `fromJson`/`toJson` 왕복 테스트 **존재 확인**
|
|
95
|
+
- 누락 시 → FAIL (Coverage gate)
|
|
96
|
+
|
|
97
|
+
### Step 3: build_runner 일관성
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd <integrated_data_layer 경로>
|
|
101
|
+
flutter pub run build_runner build --delete-conflicting-outputs
|
|
102
|
+
git diff --name-only
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- 재생성 후 `*.g.dart` diff 가 발생하면 → **FAIL** (Generator가 수동 편집 또는 재생성 누락)
|
|
106
|
+
|
|
107
|
+
### Step 4: Anti-Pattern 정적 검증
|
|
108
|
+
|
|
109
|
+
`skills/generator-frontend-flutter/references/anti-patterns.md` 의 **"셀프 체크 스크립트"** 섹션을
|
|
110
|
+
그대로 실행한다. 하나라도 결과가 있으면 → **FAIL**.
|
|
111
|
+
|
|
112
|
+
상세 → [정적 검증 룰](references/static-check-rules.md)
|
|
113
|
+
|
|
114
|
+
### Step 5: API Contract Compliance
|
|
115
|
+
|
|
116
|
+
`api-contract.json` 의 엔드포인트 vs `rest_api.dart` 의 Retrofit 어노테이션 대조:
|
|
117
|
+
|
|
118
|
+
- 계약에 있는 모든 엔드포인트가 `rest_api.dart` 에 존재하는가
|
|
119
|
+
- method, path, path param, body 타입이 일치하는가
|
|
120
|
+
- Response 타입이 계약 스키마와 구조적으로 일치하는가 (필드 존재 + nullable 여부)
|
|
121
|
+
- **불일치 1개 이상 → FAIL**
|
|
122
|
+
|
|
123
|
+
### Step 6: Sprint Contract Criteria
|
|
124
|
+
|
|
125
|
+
`sprint-contract.md` 의 FE 성공 기준을 순서대로 검증:
|
|
126
|
+
|
|
127
|
+
- 새 페이지가 `xxx_page.dart` + `xxx_page_vm.dart` 쌍으로 존재하는가
|
|
128
|
+
- VM이 `NotifierProvider` 를 사용하는가
|
|
129
|
+
- i18n 키가 모든 arb 파일에 등록되었는가
|
|
130
|
+
- 기준별 PASS/FAIL 기록 → 충족률 계산
|
|
131
|
+
|
|
132
|
+
## Scoring
|
|
133
|
+
|
|
134
|
+
| 차원 | 가중치 | 하드 임계값 | 측정 방법 |
|
|
135
|
+
|------|--------|------------|----------|
|
|
136
|
+
| Static Analysis | 25% | warning/error 0개 | `flutter analyze` |
|
|
137
|
+
| Test Pass Rate | 25% | 100% | `flutter test` |
|
|
138
|
+
| API Contract 준수 | 25% | 100% | rest_api.dart vs api-contract.json |
|
|
139
|
+
| Anti-Pattern 청결 | 15% | 위반 0건 | 정적 grep |
|
|
140
|
+
| Contract Criteria 충족률 | 10% | 80% | sprint-contract 기준 |
|
|
141
|
+
|
|
142
|
+
**어떤 차원이든 하드 임계값 미달 → 스프린트 FAIL**
|
|
143
|
+
|
|
144
|
+
상세 채점 → [스코어링 루브릭](references/scoring-rubric.md)
|
|
145
|
+
|
|
146
|
+
## evaluation-functional.md 출력
|
|
147
|
+
|
|
148
|
+
```markdown
|
|
149
|
+
# Flutter Functional Evaluation: Sprint [N]
|
|
150
|
+
|
|
151
|
+
## Date: [날짜]
|
|
152
|
+
## Verdict: PASS / FAIL
|
|
153
|
+
## Attempt: [N] / 10
|
|
154
|
+
## Stack: flutter
|
|
155
|
+
|
|
156
|
+
## Step 0: IA Structure Compliance
|
|
157
|
+
- Verdict: PASS / FAIL (GATE)
|
|
158
|
+
|
|
159
|
+
## Step 1: Flutter Analyze
|
|
160
|
+
- errors: [N]
|
|
161
|
+
- warnings: [N]
|
|
162
|
+
- infos: [N]
|
|
163
|
+
|
|
164
|
+
## Step 2: Flutter Test
|
|
165
|
+
- total: [N], passed: [N], failed: [N]
|
|
166
|
+
- missing_roundtrip_tests: [목록]
|
|
167
|
+
|
|
168
|
+
## Step 3: build_runner 일관성
|
|
169
|
+
- drift: [none | 목록]
|
|
170
|
+
|
|
171
|
+
## Step 4: Anti-Pattern
|
|
172
|
+
| Rule | Count | Files |
|
|
173
|
+
| dart:html | 0 | - |
|
|
174
|
+
| print() | 0 | - |
|
|
175
|
+
| Color(0x...) in 신규 | 0 | - |
|
|
176
|
+
| bridges/ 신규 | 0 | - |
|
|
177
|
+
| Text('한글') 신규 | 0 | - |
|
|
178
|
+
|
|
179
|
+
## Step 5: API Contract Compliance
|
|
180
|
+
| EP ID | Method + Path | Dart Match | Issues |
|
|
181
|
+
|
|
182
|
+
## Step 6: Contract Criteria Results
|
|
183
|
+
| # | Criterion | Result | Evidence |
|
|
184
|
+
|
|
185
|
+
## Scores
|
|
186
|
+
| Dimension | Score | Threshold | Status |
|
|
187
|
+
|
|
188
|
+
## Failures Detail
|
|
189
|
+
### [#N] [기준/항목]
|
|
190
|
+
- **Expected**: ...
|
|
191
|
+
- **Actual**: ...
|
|
192
|
+
- **Recommendation**: ...
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## After Evaluation
|
|
196
|
+
|
|
197
|
+
- **PASS** → Session Boundary Protocol On Complete (PASS) 실행
|
|
198
|
+
- **FAIL** → Session Boundary Protocol On Fail 실행 (retry_target = generator-frontend-flutter)
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
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
|
+
```
|