<!-- task=02_antigravity_usage_status plan=1 tag=REVIEW_ANTIGRAVITY -->

# Antigravity Usage Status 리뷰 후속 수정

## 배경

plan 0 구현은 Gemini checker/parser/formatter 명명을 Antigravity/generic으로 전환했고 대상 패키지 테스트는 통과했다. 코드리뷰에서는 Antigravity checker의 PTY 대기 조건이 parser가 지원하는 단순 quota 출력과 raw fallback 경로를 실제 checker 경로까지 연결하지 못한다는 Required 이슈가 발견되었다.

이 후속 작업은 `apps/node/internal/adapters/cli/status` 안에서 Antigravity checker의 `/usage`와 `/model` 수집 흐름만 보정한다. Edge formatter, config rollout, docs rollout, 실제 외부 `agy` 계정 검증은 범위에 포함하지 않는다.

## 분석 결과

### 리뷰 지적

- `apps/node/internal/adapters/cli/status/antigravity.go:108`의 `/usage` 대기 조건이 `Usage limit:`, `Limit reached`, `No API calls have been made`만 인정해, parser가 지원하는 `quota` + `0% used` 또는 `0% used (Limit resets in ...)` 형태가 실제 checker에서 timeout 될 수 있다.
- `apps/node/internal/adapters/cli/status/antigravity.go:116`의 `/model` 대기 조건이 `Model usage`를 필수로 만들어, `/usage` raw output만 확보한 상태에서도 `/model` 미지원/무출력/다른 문구 때문에 전체 status check가 실패할 수 있다.

### 범위 결정

- `ParseStatusOutput`의 metadata contract와 edge formatter는 유지한다.
- Antigravity checker는 `/usage` 응답을 확보하면 가능한 한 `/model`도 수집하되, `/model` 수집 실패가 `/usage` 결과 반환을 막지 않게 한다.
- 테스트는 fake PTY 기반으로 추가한다. 실제 `agy` 설치, 로그인, 원격 endpoint 검증은 후속 full verification task 범위다.

## 구현 체크리스트

- [ ] [REVIEW_ANTIGRAVITY-1] `/usage` 대기 조건이 parser-supported quota 출력(`quota` + used percent, used percent with reset)을 인정하도록 보정하고 fake PTY 회귀 테스트를 추가한다.
- [ ] [REVIEW_ANTIGRAVITY-2] `/model` 출력이 없거나 `Model usage`가 없을 때도 이미 확보한 `/usage` raw output을 `ParseStatusOutput`으로 반환하도록 보정하고 raw fallback fake PTY 테스트를 추가한다.
- [ ] 중간 검증과 최종 검증 명령을 실행하고 결과를 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [REVIEW_ANTIGRAVITY-1] `/usage` readiness 보정

### 문제

`AntigravityChecker.Check`는 `/usage` 전송 후 아래 정규식이 나올 때까지 기다린다.

```go
resultRegex := regexp.MustCompile(`(?i)Usage limit:|Limit reached|No API calls have been made`)
```

하지만 parser는 `0% used (Limit resets in 24h)`와 `Auto (Antigravity) quota\n0% used`도 정상 quota 출력으로 처리한다. 실제 CLI가 usage limit 숫자를 출력하지 않는 경우 checker가 timeout 되면 parser fallback이 의미가 없어진다.

### 해결 방법

`/usage` readiness regex에 parser가 지원하는 quota 형태를 포함한다. 예를 들어 `\d+(?:\.\d+)?%\s+used` 또는 `\bquota\b`와 used percent 조합을 인정하되, 너무 넓게 잡아 startup 잡음만으로 통과하지 않도록 `/usage` 전송 이후 누적 출력에서 의미 있는 quota/used 문구를 확인한다.

### 수정 파일 및 체크리스트

- [ ] `apps/node/internal/adapters/cli/status/antigravity.go`의 `/usage` 대기 regex를 보정한다.
- [ ] `apps/node/internal/adapters/cli/status/antigravity_test.go`에 `Usage limit:` 없이 `0% used (Limit resets in 24h)`만 출력하는 fake PTY 테스트를 추가한다.
- [ ] 같은 테스트에서 `DailyLimit`, `DailyResetTime`, `used_percent`가 파싱되는지 확인한다.

### 중간 검증

```bash
go test -count=1 ./apps/node/internal/adapters/cli/status
```

### [REVIEW_ANTIGRAVITY-2] `/model` optional fallback 보정

### 문제

현재 checker는 `/usage` 응답을 이미 확보했더라도 `/model` 전송 후 `Model usage`가 나오지 않으면 에러를 반환한다.

```go
if _, err := waitForAny([]waitPattern{{name: "model-usage", pattern: modelUsageRegex}}, 20*time.Second); err != nil {
	return nil, fmt.Errorf("failed waiting for antigravity /model output: %w", err)
}
```

이 때문에 raw fallback이 필요한 상황에서 `/model`이 미지원이거나 출력 schema가 다르면 status command 전체가 실패한다.

### 해결 방법

`/model` 수집은 best-effort로 전환한다. `/model`에서 `Model usage`를 찾으면 기존처럼 trailing output을 flush하고 model usage metadata를 추가한다. timeout, EOF, unsupported 문구, no model usage 문구처럼 model usage를 확보하지 못한 경우에는 이미 수집한 `/usage` raw output을 유지한 채 graceful exit을 시도하고 `ParseStatusOutput(fullOutput)`을 반환한다. 단, context cancellation은 호출자가 중단한 것이므로 기존처럼 에러로 반환한다.

### 수정 파일 및 체크리스트

- [ ] `apps/node/internal/adapters/cli/status/antigravity.go`에서 `/model` wait 실패를 context cancellation과 best-effort miss로 구분한다.
- [ ] `/model` miss여도 `ParseStatusOutput(fullOutput)`을 반환하는 경로를 추가한다.
- [ ] `apps/node/internal/adapters/cli/status/antigravity_test.go`의 raw fallback 테스트가 `Model usage` 없이도 성공하도록 바꾸거나 새 테스트를 추가한다.
- [ ] raw fallback 테스트에서 `DailyLimit`/`WeeklyLimit`은 비어 있고 `RawOutput`은 유지되는지 확인한다.

### 중간 검증

```bash
go test -count=1 ./apps/node/internal/adapters/cli/status
```

## 최종 검증

```bash
go test -count=1 ./apps/node/internal/adapters/cli/status ./apps/edge/internal/opsconsole
```

```bash
rg --sort path -n "GeminiChecker|NewGeminiChecker|parseGemini|gemini[A-Z]|formatGemini|failed waiting for gemini|gemini startup" apps/node/internal/adapters/cli/status apps/edge/internal/opsconsole
```

기대: Go test는 fresh test 통과. `rg`는 match가 없어야 한다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다.
