<!-- task=m-iop-agent-cli-runtime/08+06,07_quota_failure plan=2 tag=REVIEW_API -->

# Quota Projection Integrity Review Rework

## For the Implementing Agent

Run every verification command and fill the implementation-owned sections of `CODE_REVIEW-*-G??.md` with actual notes and stdout/stderr. Keep the active pair in place and report ready for review; only the code-review skill may append a verdict, archive files, write `complete.log`, or classify the next state. If blocked, record the exact blocker, attempted command/output, and resume condition in implementation-owned evidence fields; do not ask the user, call user-input tools, create control-plane stop files, or classify the next state.

## Background

The second review proved that the content-bound quota snapshot loses its integrity guarantee after projection into the public `QuotaObservation` value. The manager sanitizes that mutable projection, but a state, validity/time, or identity change can remain structurally valid and authorize continuation under evidence that no longer matches the sealed snapshot. This follow-up seals the durable projection itself and proves the seal survives persistence and manager use.

## Archive Evidence Snapshot

- Prior plan: `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/plan_cloud_G09_1.log`
- Prior review: `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/code_review_cloud_G09_1.log`
- Verdict: `FAIL`
- Findings: 1 Required, 0 Suggested, 0 Nit.
- Required summary:
  - Bind every manager-visible quota projection field to validated snapshot evidence so post-projection state, validity/time, reason, or target mutation becomes canonical corrupt evidence.
- Affected files: `packages/go/agentpolicy/quota.go`, its policy tests, manager continuation tests, durable store tests, and the two runtime contracts.
- Reviewer verification:
  - The raw snapshot tamper/not-applicable tests, manager continuation tests, race suites, vet, full shared-package suite, deterministic searches, formatting, and `git diff --check` passed on fresh reruns.
  - A focused reviewer reproducer changed a projected quota state from `exhausted` to `available` without changing `snapshot_id`; `SanitizeQuotaObservation` retained `Validity: valid` and the reproducer failed.
  - One affected-package run observed the unrelated timing-sensitive `TestSchedulerProviderCapacityAndParallelRelease` at concurrency 1 instead of 2. Twenty focused repetitions, an isolated `agenttask` rerun, the race suite, and the later full shared-package run passed. This remains outside the S07 repair scope.
- Routing signals: `review_rework_count=2`, `evidence_integrity_failure=true`.
- Roadmap carryover: S07 / `quota-failure` remains incomplete; the Milestone was not modified.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md`
- Milestone link: [Milestone document](agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
- Task ids:
  - `quota-failure`: typed quota/failure and policy-only retry/failover
- Completion mode: check-on-pass

## Analysis

### Files Read

- `packages/go/agentprovider/cli/status/quota.go`
- `packages/go/agentprovider/cli/status/quota_test.go`
- `packages/go/agentruntime/status.go`
- `packages/go/agentruntime/failure.go`
- `packages/go/agentruntime/failure_test.go`
- `packages/go/agentpolicy/decision.go`
- `packages/go/agentpolicy/evaluator.go`
- `packages/go/agentpolicy/quota.go`
- `packages/go/agentpolicy/failure_policy.go`
- `packages/go/agentpolicy/failure_policy_test.go`
- `packages/go/agenttask/ports.go`
- `packages/go/agenttask/dispatch.go`
- `packages/go/agenttask/types.go`
- `packages/go/agenttask/state_machine.go`
- `packages/go/agenttask/manager.go`
- `packages/go/agenttask/failure_continuation_test.go`
- `packages/go/agentstate/store.go`
- `packages/go/agentstate/store_test.go`
- `agent-contract/index.md`
- `agent-contract/inner/agent-runtime.md`
- `agent-contract/inner/iop-agent-cli-runtime.md`
- `agent-spec/index.md`
- `agent-spec/runtime/edge-node-execution.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md`
- `agent-roadmap/sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md`
- `agent-test/local/rules.md`
- `agent-test/local/platform-common-smoke.md`
- `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/plan_cloud_G09_1.log`
- `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/code_review_cloud_G09_1.log`

### SDD Criteria

- SDD: `agent-roadmap/sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md`; status `[승인됨]`, lock `해제`.
- Target: S07 / `quota-failure`.
- Acceptance: available/exhausted/unknown/not-applicable evidence, immutable isolated snapshots, declared-policy-only retry/failover, and unknown as a work-unit blocker.
- Evidence Map: quota parser, runtime observation, isolation, and failover tests; PASS must provide snapshot/failure transition evidence in `Roadmap Completion`.
- The implementation checklist therefore requires a content-bound durable projection, strict persistence round trips, manager fail-closed regression coverage, and the original S07 package/race/contract verification.

### Test Environment Rules

- `test_env=local`.
- Read `agent-test/local/rules.md` and matched `agent-test/local/platform-common-smoke.md`.
- Apply Go preflight, focused fresh tests, affected package tests, race tests for durable state transitions, `go vet ./packages/go/...`, full shared-package tests, formatting, deterministic searches, and `git diff --check`.
- No external service or credential is required. No current user executable instantiates this standalone manager path; S14 owns logged-in full-cycle smoke.

### Test Coverage Gaps

- Existing status tests cover sealed `QuotaSnapshot` field tampering and unsafe reason rejection.
- Existing policy tests cover malformed IDs/reasons and caller-slice copying, but not a structurally valid post-projection state, validity/time, or identity mutation with the original snapshot ID.
- Existing manager tests cover malformed observations, unused-target history, and budgets, but not post-projection mutation reaching `SanitizeAttemptObservation`.
- Existing durable store tests do not round-trip an `AttemptObservationRecord`, so a new private projection seal could be lost silently during JSON persistence.

### Symbol References

- No public symbol rename is required.
- `QuotaObservation` is produced in `packages/go/agentpolicy/quota.go`, consumed by `DecideContinuation`, carried through `FailureObservedInvocation`, persisted in `agenttask.AttemptObservationRecord`, and serialized by `packages/go/agentstate/store.go`.
- `SanitizeQuotaObservation` is called by `SanitizeAttemptObservation` and candidate construction in `packages/go/agenttask/dispatch.go`.

### Split Judgment

- Keep one plan: projection creation, sanitizer validation, disk serialization, and manager continuation are one content-integrity invariant. Splitting could accept an intermediate state whose seal is not durable or whose manager path still trusts mutable evidence.
- Predecessor `06` is satisfied by `agent-task/archive/2026/07/m-iop-agent-cli-runtime/06+05_config_registry/complete.log`.
- Predecessor `07` is satisfied by `agent-task/archive/2026/07/m-iop-agent-cli-runtime/07+06_target_policy/complete.log`.

### Scope Rationale

- Include only quota projection integrity, strict durable serialization, focused policy/manager/store tests, and authoritative runtime contract wording.
- Exclude raw status snapshot hashing, selection policy redesign, provider transport/parser changes, standalone CLI wiring, Edge provider-pool behavior, unrelated scheduler timing cleanup, living-spec expansion, and S08/S09/S14/S19 work.

### Final Routing

- `evaluation_mode=isolated-reassessment`; `finalizer=finalize-task-policy.sh`, mode `pair`.
- Build closures: scope/context/verification/evidence/ownership/decision are all closed; no capability gap.
- Build scores: scope=2, state=1, blast=2, evidence=2, verification=1; grade `G08`.
- `large_indivisible_context=false`.
- Positive loop risks: `temporal_state`, `boundary_contract`, `variant_product`; count=3.
- Recovery signals: `review_rework_count=2`, `evidence_integrity_failure=true`; recovery boundary matched.
- Build: base basis `local-fit`, final basis `recovery-boundary`, lane `cloud`, filename `PLAN-cloud-G08.md`.
- Review closures are closed; scores 2/1/2/2/1; route `official-review`, cloud `G08`, Codex `gpt-5.6-sol` xhigh, filename `CODE_REVIEW-cloud-G08.md`.

## Implementation Checklist

- [ ] Seal every valid/stale `QuotaObservation` projection and make sanitizer, validation, cloning, and strict JSON round trips reject field/seal drift as canonical corrupt evidence.
- [ ] Add policy and durable-store regressions for post-projection state, validity/time, reason/identity mutation and seal-preserving disk round trips.
- [ ] Add manager regression coverage proving mutated projected evidence persists only as a typed corrupt blocker and never authorizes another invocation.
- [ ] Synchronize the shared and standalone runtime contracts and run focused, affected, race, vet, full shared-package, search, formatting, and diff verification.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_API-1] Seal the durable quota projection

**Problem:** `packages/go/agentpolicy/quota.go:147-149` sends a public `QuotaObservation` through shape-only validation. At lines 209-228, a valid-looking snapshot ID plus structurally compatible fields is enough; the validator cannot prove those fields are the projection originally derived from the validated snapshot.

**Solution:** Add a package-owned projection integrity value computed only after `ValidateQuotaSnapshot` succeeds and after stale/valid status is final. Cover the snapshot ID, adapter, target, quota state, normalized checked time, validity, and ordered reasons with the existing length-prefixed digest helper. Verify the seal in every valid/stale observation validation, retain it across defensive copies, and add strict custom JSON encoding/decoding so the seal survives durable state persistence without becoming a caller-settable Go field. Any mismatch must canonicalize to `CorruptQuotaObservation`.

Before (`packages/go/agentpolicy/quota.go:209`):

```go
if !validQuotaSnapshotIdentity(observation.SnapshotID) ||
    !safeObservationIdentity(observation.Adapter) ||
    !safeObservationIdentity(observation.Target) {
    return false
}
```

After:

```go
if !validQuotaSnapshotIdentity(observation.SnapshotID) ||
    !safeObservationIdentity(observation.Adapter) ||
    !safeObservationIdentity(observation.Target) ||
    observation.projectionIntegrity != quotaObservationIntegrity(observation) {
    return false
}
```

**Modified Files and Checklist:**

- [ ] `packages/go/agentpolicy/quota.go`: private projection seal, strict JSON round trip, seal-aware normalization/sanitization/validation.
- [ ] `packages/go/agentpolicy/failure_policy_test.go`: field mutation, reason mutation, stale-to-valid mutation, defensive copy, and JSON tamper matrices.

**Test Strategy:** Add `TestSanitizeQuotaObservationRejectsProjectionTampering` and `TestQuotaObservationJSONRoundTripRejectsTampering`. Start from real normalized snapshots, mutate each projected integrity field independently, and assert canonical corrupt output or strict decode failure. Confirm valid, stale, not-applicable, and corrupt observations round-trip without sharing reason slices.

**Verification:**

```bash
go test -count=1 -run 'Test(SanitizeQuotaObservationRejectsProjectionTampering|QuotaObservationJSONRoundTripRejectsTampering)$' ./packages/go/agentpolicy
```

Expected: both projection-integrity regressions pass.

### [REVIEW_API-2] Prove manager and disk fail closed

**Problem:** `packages/go/agenttask/failure_continuation_test.go:85-136` covers malformed IDs and unsafe reasons, but not a projection that remains structurally valid after its state/validity/identity changes. `packages/go/agentstate/store_test.go:154-207` persists recovery records without any attempt observation, so it cannot detect a seal lost during JSON persistence.

**Solution:** Extend the manager regression with valid snapshots projected first and mutated afterward; every mutation must become `BlockerFailureObservationCorrupt`, persist one canonical corrupt observation, and cause exactly one provider invocation. Add a real `AttemptObservationRecord` to a store round-trip and a checksum-valid but projection-seal-invalid fixture that must be rejected as corrupt manager state.

Before (`packages/go/agentstate/store_test.go:178`):

```go
FailureBudgets: map[agenttask.FailureStage]agenttask.FailureBudgetRecord{
    agenttask.FailureStageDispatch: { /* ... */ },
},
```

After:

```go
FailureBudgets: map[agenttask.FailureStage]agenttask.FailureBudgetRecord{
    agenttask.FailureStageDispatch: { /* ... */ },
},
AttemptObservations: []agenttask.AttemptObservationRecord{
    sealedAttemptObservation,
},
```

**Modified Files and Checklist:**

- [ ] `packages/go/agenttask/failure_continuation_test.go`: manager mutation matrix and zero-continuation assertions.
- [ ] `packages/go/agentstate/store_test.go`: sealed observation persistence and tampered serialized projection rejection.

**Test Strategy:** Add `TestFailureContinuationProjectionTamperBecomesTypedBlocker` and `TestStorePersistsSealedQuotaObservation`. Cover state, target, checked time, validity, and allowlisted reason drift; assert canonical corrupt durable evidence, typed blocker, one invocation, exact disk round trip, and corrupt-load rejection.

**Verification:**

```bash
go test -count=1 -run 'Test(FailureContinuationProjectionTamperBecomesTypedBlocker|StorePersistsSealedQuotaObservation)$' ./packages/go/agenttask ./packages/go/agentstate
```

Expected: manager and disk regressions pass.

### [REVIEW_API-3] Synchronize contract and completion evidence

**Problem:** `agent-contract/inner/agent-runtime.md:105-113` promises fail-closed projection and durable immutable attempt evidence but does not state how the validated snapshot remains bound after projection and disk serialization. The standalone S07 evidence row likewise lacks projection-integrity round-trip evidence.

**Solution:** State that every valid/stale projection carries a private runtime integrity seal over all policy-visible fields and that strict durable decoding rejects seal drift before state use. Add the policy, manager, and disk regressions to the S07 evidence expectation, then fill the active review evidence with exact command output.

**Modified Files and Checklist:**

- [ ] `agent-contract/inner/agent-runtime.md`: projection integrity and strict durable decode semantics.
- [ ] `agent-contract/inner/iop-agent-cli-runtime.md`: S07 projection/disk evidence expectation.
- [ ] `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/CODE_REVIEW-cloud-G08.md`: implementation notes, decisions, deviations, and actual output.

**Test Strategy:** No separate document-only test. Deterministic anchor searches and the focused behavior/persistence suites prove the contract claims.

**Verification:**

```bash
rg --sort path -n 'projection integrity|SanitizeQuotaObservation|AttemptObservationRecord|corrupt quota' packages/go/agentpolicy packages/go/agenttask packages/go/agentstate agent-contract/inner/agent-runtime.md agent-contract/inner/iop-agent-cli-runtime.md
```

Expected: code, tests, and both contracts expose consistent projection-integrity anchors.

## Modified Files Summary

| File | Item |
|---|---|
| `packages/go/agentpolicy/quota.go` | REVIEW_API-1 |
| `packages/go/agentpolicy/failure_policy_test.go` | REVIEW_API-1 |
| `packages/go/agenttask/failure_continuation_test.go` | REVIEW_API-2 |
| `packages/go/agentstate/store_test.go` | REVIEW_API-2 |
| `agent-contract/inner/agent-runtime.md` | REVIEW_API-3 |
| `agent-contract/inner/iop-agent-cli-runtime.md` | REVIEW_API-3 |
| `agent-task/m-iop-agent-cli-runtime/08+06,07_quota_failure/CODE_REVIEW-cloud-G08.md` | REVIEW_API-3 |

## Dependencies and Execution Order

1. Implement REVIEW_API-1 before the manager/store tests so every fixture uses the final durable projection representation.
2. Implement REVIEW_API-2 against that representation.
3. Synchronize contracts and implementation evidence after behavior and verification are final.

## Final Verification

```bash
command -v go && go version && go env GOROOT
gofmt -d packages/go/agentpolicy/quota.go packages/go/agentpolicy/failure_policy_test.go packages/go/agenttask/failure_continuation_test.go packages/go/agentstate/store_test.go
go test -count=1 -run 'Test(ValidateQuotaSnapshotRejectsTampering|NormalizeQuotaObservationSanitizesCorruptEvidence|SanitizeQuotaObservationRejectsProjectionTampering|QuotaObservationJSONRoundTripRejectsTampering)$' ./packages/go/agentprovider/cli/status ./packages/go/agentpolicy
go test -count=1 -run 'Test(FailureContinuationProjectionTamperBecomesTypedBlocker|StorePersistsSealedQuotaObservation)$' ./packages/go/agenttask ./packages/go/agentstate
go test -count=1 ./packages/go/agentpolicy ./packages/go/agenttask ./packages/go/agentstate
go test -count=1 -race ./packages/go/agentpolicy ./packages/go/agenttask ./packages/go/agentstate
go vet ./packages/go/...
go test -count=1 ./packages/go/...
rg --sort path -n 'projection integrity|SanitizeQuotaObservation|AttemptObservationRecord|corrupt quota' packages/go/agentpolicy packages/go/agenttask packages/go/agentstate agent-contract/inner/agent-runtime.md agent-contract/inner/iop-agent-cli-runtime.md
if rg --sort path -n 'RawOutput' packages/go/agentpolicy packages/go/agenttask; then exit 1; else test $? -eq 1; fi
git diff --check
```

Expected: preflight resolves Go; formatting emits no diff; raw-snapshot, projection-integrity, manager, store, affected/race/full tests and vet pass; contract anchors are present; no `RawOutput` reference exists in durable policy/task packages; and the diff check is clean. Fresh `-count=1` output is required. Run these commands sequentially so unrelated timing-sensitive package tests are not amplified by concurrent verification.

After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
