<!-- task=m-agent-task-runtime-target-selector/02+01_quota_input plan=4 tag=REVIEW_REVIEW_REVIEW_REVIEW_API -->

# Required-cap 누락 fixture 수정과 S04 Evidence Closure

## 이 파일을 읽는 구현 에이전트에게

구현과 검증을 완료한 뒤 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 내용과 stdout/stderr로 채운다. active PLAN/CODE_REVIEW 파일은 그대로 두고 리뷰 준비 완료만 보고한다. 차단되면 정확한 원인, 시도한 명령과 출력, 재개 조건만 구현 소유 evidence 필드에 기록한다. 사용자에게 질문하거나 user-input 도구를 호출하거나 control-plane stop 파일을 만들거나 다음 상태를 판정하지 않는다. 로그 archive, `complete.log`, 최종 판정은 code-review skill만 수행한다.

## 배경

호스트 Go/GOROOT 정합성은 복구되어 필수 Go 테스트가 실제 assertion까지 실행됐다. 그 결과 `missing` 하위 테스트가 유효한 `overall=50%`만 요구하면서 `unknown`을 기대하는 fixture 오류가 드러났다. 실제 누락 required cap을 구성하도록 테스트를 바로잡고 전체 S04 검증을 통과시킨다.

## Archive Evidence Snapshot

- Prior task: `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input`
- Archived plan: `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/plan_local_G02_3.log`
- Archived review: `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/code_review_cloud_G09_3.log`
- Verdict: `FAIL`
- Findings: Required 1, Suggested 0, Nit 0
  - `quota_test.go`의 `missing` 케이스는 `requiredCaps=["overall"]`과 유효한 `DailyLimit="50%"`를 주므로 `available`이 맞고 실제 누락 cap을 검증하지 않는다.
- Affected files: `apps/node/internal/adapters/cli/status/quota_test.go`
- Verification evidence:
  - host Go: `/config/.local/bin/go` → `/config/opt/go/bin/go`, `go1.26.2 linux/arm64`, `GOROOT=/config/opt/go`
  - `crypto/internal/fips140cache` preflight: PASS
  - Go package tests: status package FAIL 1건, node command package PASS
  - focused evidence: exhausted+missing과 all-positive는 PASS, missing/conflict/parse 중 `missing`만 FAIL
  - Python policy 5개와 selector 32개 테스트, `py_compile`, `gofmt -d`, `git diff --check`: PASS
- Roadmap carryover: SDD S04와 Milestone Task `quota-input`은 corrected fixture와 fresh 전체 검증이 통과할 때까지 미완료다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md)
- Task ids:
  - `quota-input`: Go usage checker 기반 required-cap quota snapshot과 selector admission
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `agent-ops/rules/project/rules.md`
- `agent-ops/rules/common/rules-roadmap.md`
- `agent-ops/rules/project/domain/node/rules.md`
- `agent-ops/rules/project/domain/testing/rules.md`
- `agent-ops/rules/common/rules-agent-spec.md`
- `agent-ops/skills/common/router.md`
- `agent-ops/skills/common/code-review/SKILL.md`
- `agent-ops/skills/common/plan/SKILL.md`
- `agent-ops/skills/common/finalize-task-routing/SKILL.md`
- `agent-ops/skills/common/plan/templates/review-stub-template.md`
- `agent-test/local/rules.md`
- `agent-test/local/node-smoke.md`
- `agent-spec/index.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-contract/index.md`
- `agent-contract/inner/edge-node-runtime-wire.md`
- `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md`
- `agent-roadmap/sdd/automation-runtime-bridge/agent-task-runtime-target-selector/SDD.md`
- `agent-task/archive/2026/07/m-agent-task-runtime-target-selector/01_selector_contract/complete.log`
- `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/plan_local_G02_2.log`
- `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/code_review_cloud_G09_2.log`
- `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/plan_local_G02_3.log`
- `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/code_review_cloud_G09_3.log`
- `apps/node/internal/adapters/cli/status/status.go`
- `apps/node/internal/adapters/cli/status/parser.go`
- `apps/node/internal/adapters/cli/status/quota.go`
- `apps/node/internal/adapters/cli/status/quota_test.go`
- `apps/node/cmd/node/main.go`
- `apps/node/cmd/node/quota_probe.go`
- `apps/node/cmd/node/quota_probe_test.go`
- `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/execution_target_policy.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_execution_target_policy.py`
- `agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py`

### SDD 기준

- SDD: `agent-roadmap/sdd/automation-runtime-bridge/agent-task-runtime-target-selector/SDD.md`
- 상태: `[승인됨]`, SDD 잠금 `해제`, 사용자 리뷰 없음
- 대상: S04 → `quota-input`
- Evidence Map: Go usage checker JSON bridge, required-cap tri-state, unknown 1회 admission, local `unbounded/not_applicable` 테스트
- S04는 required cap이 모두 양수일 때 `available`, 하나라도 누락되면 `unknown`을 요구한다. 따라서 positive overall과 missing model cap을 함께 선언하는 fixture 및 Go/Python 통합 회귀를 구현·완료 evidence로 사용한다.

### 테스트 환경 규칙

- `test_env=local`; `agent-test/local/rules.md`와 `agent-test/local/node-smoke.md`를 읽었다.
- node-smoke의 session/handler/reconnect full-cycle은 hidden quota probe와 직접 일치하지 않으므로 대상 Go package 테스트와 selector black-box 회귀를 fallback으로 사용한다.
- Go cache를 배제하기 위해 `-count=1`을 적용하며 PATH 첫 Go와 `GOROOT`를 바꾸지 않는다.
- 현재 preflight:
  - runner/repo: local `/config/workspace/iop`, branch `main`, HEAD `3f01d08cebdafa1bddd1089e6940677dcb6c90b1`, dirty checkout
  - OS/arch: `Linux/aarch64`
  - Go: `/config/.local/bin/go` → `/config/opt/go/bin/go`, `go1.26.2 linux/arm64`, `GOROOT=/config/opt/go`
  - standard library preflight: `crypto/internal/fips140cache` 존재
  - external provider/credential/port: 필요 없음

### 테스트 커버리지 공백

- exhausted cap이 missing cap보다 우선하는 경우와 모든 required cap이 양수인 경우는 focused Go 테스트가 통과한다.
- conflict와 parse failure의 `unknown` 회귀는 통과한다.
- `missing` 하위 테스트만 실제 누락 cap을 구성하지 않아 required-cap missing 회귀가 비어 있다. 이번 변경이 이 공백을 닫는다.
- Python selector는 tri-state 반영, exhausted alternate/no-eligible, unknown 1회 admission, local unbounded를 32개 회귀에서 검증하며 현재 통과한다.

### 심볼 참조

- renamed/removed symbol: none

### 분할 판단

- split 정책을 파일 선택 전에 적용했다.
- task group: `m-agent-task-runtime-target-selector`
- 현재 subtask: `02+01_quota_input`
- predecessor `01_selector_contract`: `agent-task/archive/2026/07/m-agent-task-runtime-target-selector/01_selector_contract/complete.log`로 충족됐다.
- 남은 변경은 한 Go 테스트 함수의 fixture와 같은 S04 전체 검증으로 구성된 단일 test-only correction이다. 별도 subtask는 구현과 증거를 인위적으로 분리하므로 현재 subtask의 단일 pair를 유지한다.

### 범위 결정 근거

- `apps/node/internal/adapters/cli/status/quota_test.go`만 수정한다.
- `quota.go`는 유효한 positive overall을 `available`로 반환해 SDD와 일치하므로 production 동작을 바꾸지 않는다.
- quota probe, selector, policy, dispatcher, roadmap, spec, contract는 수정하지 않고 회귀 검증 대상으로만 둔다.

### 최종 라우팅

- evaluation_mode: `isolated-reassessment`
- finalizer: `finalize-task-policy.sh`
- finalizer_mode: `pair`
- build closures: scope/context/verification/evidence/ownership/decision 모두 `true`
  - scope/context: 단일 fixture 변경과 직접 관련 source/test/SDD가 고정됐다.
  - verification/evidence: 재현된 assertion과 결정적 focused/full 명령으로 성공 여부를 판정할 수 있다.
  - ownership/decision: 외부 권한·제품 결정 없이 현재 subtask 안에서 완료 가능하다.
- build base route: `local-G02`
- build grade scores: scope_coupling=0, state_concurrency=0, blast_irreversibility=0, evidence_diagnosis=1, verification_complexity=1
- build loop-risk:
  - ordered_transitions: state_count=0, adverse_paths=없음
  - concurrent_consistency: actor_count=0, constraints=없음
  - boundary_contract: component_count=1, consumer_count=1, constraints=없음
  - structured_interpretation: mechanisms/hazards=없음
  - variant_product: independent_axis_count=1, combination_verification_required=false
  - matched signatures: 없음, triggered=`false`
- build final: `local-G02`, `PLAN-local-G02.md`
- review closures: scope/context/verification/evidence/ownership/decision 모두 `true`
  - source, test, SDD와 fresh Go/Python 출력을 함께 대조하면 독립 판정 가능하다.
- review base route: `local-G03`
- review grade scores: scope_coupling=1, state_concurrency=0, blast_irreversibility=0, evidence_diagnosis=1, verification_complexity=1
- review capability floor: official review minimum `cloud-G09`
- review final: `cloud-G09`, `CODE_REVIEW-cloud-G09.md`

## 구현 체크리스트

- [ ] `apps/node/internal/adapters/cli/status/quota_test.go`의 missing/conflict/parse table에 하위 테스트별 required cap을 명시하고, `missing`이 positive overall과 누락된 model cap의 aggregate `unknown`을 실제로 검증하도록 수정한 뒤 focused Go 테스트를 통과시킨다.
- [ ] 동일 PATH Go와 `GOROOT`에서 두 Go 패키지, Python policy/selector 회귀, `py_compile`, `gofmt -d`, `git diff --check`를 fresh 실행해 모두 통과시키고 실제 출력을 기록한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다.

### [REVIEW_REVIEW_REVIEW_REVIEW_API-1] Missing cap fixture와 S04 evidence 수정

#### 문제

`apps/node/internal/adapters/cli/status/quota_test.go:42-58`은 `missing`에 `DailyLimit: "50%"`를 주면서 required cap을 `overall` 하나로 유지한다. 이 입력에는 누락 cap이 없으므로 `NormalizeQuotaSnapshot`의 `available` 결과가 맞고, 테스트의 `unknown` 기대가 SDD S04와 충돌한다.

#### 해결 방법

하위 테스트별 `requiredCaps`와 `usage`를 같은 table fixture에 묶는다. `missing`은 `overall`과 `model:missing`을 요구하고 positive overall만 제공해 누락된 required model cap 때문에 aggregate `unknown`이 되는 경계를 검증한다.

Before (`quota_test.go:42-58`):

```go
for name, usage := range map[string]*UsageStatus{
	"missing": {DailyLimit: "50%"},
	// ...
} {
	t.Run(name, func(t *testing.T) {
		caps := []string{"overall"}
		if name == "conflict" {
			caps = []string{"model:flash"}
		}
		snapshot := NormalizeQuotaSnapshot("agy", "Gemini", caps, quotaCheckedAt, usage, nil)
```

After:

```go
for name, tc := range map[string]struct {
	requiredCaps []string
	usage        *UsageStatus
}{
	"missing": {
		requiredCaps: []string{"overall", "model:missing"},
		usage:        &UsageStatus{DailyLimit: "50%"},
	},
	// conflict와 parse도 각 requiredCaps를 fixture에 명시
} {
	t.Run(name, func(t *testing.T) {
		snapshot := NormalizeQuotaSnapshot("agy", "Gemini", tc.requiredCaps, quotaCheckedAt, tc.usage, nil)
```

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

- [ ] `apps/node/internal/adapters/cli/status/quota_test.go` — missing/conflict/parse fixture에 required cap을 명시하고 기존 assertion을 유지한다.
- [ ] production source는 수정하지 않는다.

#### 테스트 작성

기존 `TestNormalizeQuotaSnapshotUnknownForMissingConflictAndParseFailure`가 의도한 regression test이므로 새 테스트를 추가하지 않고 fixture를 수정한다. `missing`은 positive overall + missing model, `conflict`는 duplicate matching model, `parse`는 malformed overall을 각각 `unknown`으로 assertion한다.

#### 중간 검증

```bash
command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT
test -d "$(go env GOROOT)/src/crypto/internal/fips140cache" && echo "preflight: PASS"
go test -count=1 ./apps/node/internal/adapters/cli/status -run '^TestNormalizeQuotaSnapshotUnknownForMissingConflictAndParseFailure$' -v
```

기대 결과: 동일 Go/GOROOT identity에서 preflight가 통과하고 missing/conflict/parse 하위 테스트가 모두 PASS한다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `apps/node/internal/adapters/cli/status/quota_test.go` | REVIEW_REVIEW_REVIEW_REVIEW_API-1 |
| `agent-task/m-agent-task-runtime-target-selector/02+01_quota_input/CODE_REVIEW-cloud-G09.md` | 구현 evidence |

## 최종 검증

```bash
command -v go && readlink -f "$(command -v go)" && go version && go env GOROOT
test -d "$(go env GOROOT)/src/crypto/internal/fips140cache" && echo "preflight: PASS"
go test -count=1 ./apps/node/internal/adapters/cli/status ./apps/node/cmd/node
python3 -m unittest discover -s agent-ops/skills/project/orchestrate-agent-task-loop/tests -p 'test_execution_target*.py'
python3 agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py -v
python3 -m py_compile agent-ops/skills/project/orchestrate-agent-task-loop/scripts/execution_target_policy.py agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_execution_target_policy.py agent-ops/skills/project/orchestrate-agent-task-loop/tests/test_select_execution_target.py
gofmt -d apps/node/internal/adapters/cli/status/quota.go apps/node/internal/adapters/cli/status/quota_test.go apps/node/cmd/node/quota_probe.go apps/node/cmd/node/quota_probe_test.go apps/node/cmd/node/main.go
git diff --check
```

기대 결과: 동일 Go/GOROOT에서 focused/full Go 회귀, Python policy 5개, selector 32개, `py_compile`, `gofmt -d`, `git diff --check`가 모두 PASS한다. 외부 provider/credential은 호출하지 않는다.

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