<!-- task=m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture plan=3 tag=REVIEW_REVIEW_REVIEW_REFACTOR milestone-task=transfer -->

# Make state-clause verification exact and clause-driven

## For the Implementing Agent

Filling the implementation-owned sections in `CODE_REVIEW-cloud-G04.md` is mandatory. Reconfirm the encoded predecessor PASS, implement only this oracle follow-up, run every verification command exactly, paste actual output, keep the active pair in place, and report ready for review. If blocked, record only the exact blocker, attempted commands/output, and resume condition in implementation-owned evidence fields. Do not ask the user, call user-input tools, create control-plane stop files, classify the next state, archive logs, or write `complete.log`; finalization belongs to the code-review skill.

## Background

The oracle now rejects missing or inverted headline clauses, but it still accepts schema mutations that change the conditional's real JSON Schema semantics. Extra required fields and ignored `allOf` clauses can make the canonical fixture invalid or weaken the forbidden-reason rule while the oracle continues to print `STATE_SCHEMA_CONTRACT_PASS`. The verifier must require the exact supported clause shape and drive record presence checks from the validated clause keys.

## Archive Evidence Snapshot

- The current failed pair will archive as `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/plan_cloud_G04_2.log` and `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/code_review_cloud_G04_2.log`; verdict: FAIL.
- Required finding: `scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq:12-22,39-51,57-61` uses `contains(...)`, accepts any non-empty `allOf`, and hardcodes `quarantine_reason`, so it does not enforce or consume the exact required/forbidden clause semantics.
- Fresh reviewer mutations appended a missing field to `if.required`, `then.required`, or `else.not.required`, or appended a second rejecting `allOf` clause; every mutated schema still exited 0 with `STATE_SCHEMA_CONTRACT_PASS`. The canonical oracle, predecessor check, parsing, removed-conditional rejection, provenance, sensitive-text scan, and `git diff --check` passed.
- Roadmap carryover remains `milestone-task=transfer`, SDD scenario S02, with no roadmap mutation or completion claim in this follow-up.

## Analysis

### Files Read

- `scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq`
- `scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json`
- `scripts/fixtures/iop-agent-chronos-transfer-state-v1.json`
- `scripts/fixtures/iop-agent-chronos-ownership-manifest.tsv`
- `cmd/iop-chronos-transfer/main.go`
- `cmd/iop-chronos-transfer/main_test.go`
- `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/PLAN-cloud-G04.md`
- `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/CODE_REVIEW-cloud-G04.md`
- `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/plan_local_G04_1.log`
- `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/code_review_cloud_G04_1.log`
- `agent-task/archive/2026/08/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log`
- `agent-roadmap/phase/automation-runtime-bridge/PHASE.md`
- `agent-roadmap/phase/automation-runtime-bridge/milestones/iop-agent-chronos-extraction-decoupling.md`
- `agent-roadmap/sdd/automation-runtime-bridge/iop-agent-chronos-extraction-decoupling/SDD.md`
- `agent-spec/runtime/iop-agent-cli-runtime.md`
- `agent-contract/inner/iop-agent-cli-runtime.md`

### SDD Criteria

- `agent-roadmap/sdd/automation-runtime-bridge/iop-agent-chronos-extraction-decoupling/SDD.md` is `[approved]` with its lock released. The unchanged first-line scope is `milestone-task=transfer`.
- Acceptance Scenario S02 and its Evidence Map require a trustworthy full-state transfer fixture before isolated bundle verification. The checklist keeps the canonical schema and fixture unchanged while making the tracked verifier reject every unsupported conditional shape that could invalidate or weaken their published semantics.

### Verification Context

- No external verification handoff was supplied. Repository-native evidence came from the tracked schema, fixture, jq oracle, the production checks at `cmd/iop-chronos-transfer/main.go:785-844`, the quarantine test at `cmd/iop-chronos-transfer/main_test.go:180-214`, and the exact predecessor completion.
- Local preflight is Go `go1.26.2 linux/arm64`, module `/config/workspace/iop-s1/go.mod`, with `/bin/jq` available. No service, credential, provider, or external host is required.
- All seven current plan commands passed. A focused four-case schema-mutation probe then changed `if.required`, `then.required`, `else.not.required`, and `allOf` cardinality; each case exited 0 and printed `STATE_SCHEMA_CONTRACT_PASS`.
- Preconditions: index 03 resolves to the one archived PASS at `agent-task/archive/2026/08/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log`.
- Constraints: do not change the canonical schema, fixture, ownership manifest, exporter, roadmap, contract, or spec. Confidence is high because each false-positive is deterministic and isolated to exact-shape validation in the jq oracle.

### Test Coverage Gaps

- Existing internal schema mutations cover a removed conditional, a changed mode constant, zero reason length, and inverted quarantine resumability.
- They do not cover extra guard/required/forbidden entries or additional `allOf` clauses. Those variants change actual schema admission while passing `contains(...)` and the hardcoded record checker.
- Extend the same tracked jq regression with the complete known semantic-drift set; no Go test change is needed because production behavior and the canonical schema remain unchanged.

### Symbol References

- None. No Go or JSON symbol is renamed or removed.

### Split Judgment

- Keep one compact follow-up. Exact shape validation, clause-key extraction, record evaluation, and semantic-mutation rejection are one verifier-trust invariant and cannot independently PASS.
- Encoded predecessor index `03` remains satisfied by `agent-task/archive/2026/08/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log`.

### Scope Rationale

- Exclude `scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json`: its canonical clause set is correct; only the oracle accepts unsupported mutations.
- Exclude the canonical fixture, ownership manifest, and `cmd/iop-chronos-transfer/**`: their current data and production validation pass, and changing them would expand beyond the Required finding.
- Exclude roadmap/spec/contract updates: this is a regression-verifier repair for the existing S02 evidence contract. Spec update not needed.

### Final Routing

- `evaluation_mode=isolated-reassessment`; finalizer=`finalize-task-policy.sh`, mode=`pair`.
- Build closures are all true. Scores are `scope=1,state=0,blast=1,evidence=1,verification=1`, grade `G04`, base `local-fit`, final route `recovery-boundary`, lane `cloud`.
- Review closures are all true. Scores are `scope=1,state=0,blast=1,evidence=1,verification=1`, route `official-review`, lane `cloud`, grade `G04`.
- `large_indivisible_context=false`; positive loop risks are `boundary_contract` and `structured_interpretation` (2); `review_rework_count=3`; `evidence_integrity_failure=true`; no capability gap.
- Canonical files: `PLAN-cloud-G04.md`, `CODE_REVIEW-cloud-G04.md`.

## Dependencies and Execution Order

1. Reconfirm the exact PASS in `agent-task/archive/2026/08/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log`.
2. Make exact-shape validation and clause-driven record evaluation one change, then run canonical and semantic-mutation verification.

## Implementation Checklist

- [ ] Reconfirm that predecessor index 03 resolves to exactly one PASS `complete.log` before changing the oracle.
- [ ] Require exactly one supported `allOf` conditional and exact singleton guard, required-reason, and forbidden-reason arrays; reject added keywords or properties that the oracle does not evaluate.
- [ ] Extract the validated category, resumability, and reason-presence keys into the schema contract and use those keys in record evaluation instead of hardcoding presence semantics.
- [ ] Retain the canonical case and existing record/schema mutations, add all four observed semantic-drift mutations, and make each invalid external schema exit nonzero.
- [ ] Re-run parsing, canonical oracle, exact manifest/addendum provenance, sensitive-text, focused semantic-mutation, and diff checks without changing the canonical schema, fixture, or manifest.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [REVIEW_REVIEW_REVIEW_REFACTOR-1] Make schema verification exact and clause-driven

**Problem**

`scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq:12-22` accepts arrays that merely contain the expected key and any `allOf` with at least one entry. Lines 39-51 then hardcode category and reason field access rather than consuming the validated clause keys. Appending an unsatisfied required field or a second rejecting clause changes actual JSON Schema semantics but remains invisible to the oracle.

```jq
# before: scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq:16-22
and ($rec.allOf != null and ($rec.allOf | length) > 0)
and ($rec.allOf[0].if.required | contains(["category"]))
and ($rec.allOf[0].then.required | contains(["quarantine_reason"]))
and ($rec.allOf[0].else.not.required | contains(["quarantine_reason"]));
```

**Solution**

Require the supported conditional object, keyword sets, property sets, and singleton arrays exactly. Extract the category/resumability/reason keys from that validated object and use dynamic record access for the presence and minimum-length checks. Retain the existing mutations and add the four reviewer reproductions so the aggregate fails closed whenever a clause is added, weakened, or made unsatisfiable.

```jq
# after
($rec.allOf | length) == 1
and ($cond | keys) == ["else", "if", "then"]
and ($cond.if.required == ["category"])
and ($cond.then.required == ["quarantine_reason"])
and ($cond.else.not.required == ["quarantine_reason"])

def check_record($contract; $record):
  ($record[$contract.category_key] == $contract.quarantine_category)
  and ($record | has($contract.required_reason_key));
```

**Modified Files and Checklist**

- [ ] `scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq` — enforce exact supported shape, consume clause keys, and cover the known semantic-drift mutations.
- [ ] `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/CODE_REVIEW-cloud-G04.md` — record implementation notes and actual command output.

**Test Strategy**

- Update the existing tracked jq regression rather than adding a second harness. Preserve all canonical, record-mutation, and schema-mutation cases, and add four cases for an extra `if.required`, extra `then.required`, extra `else.not.required`, and a second `allOf` clause.
- The final shell probe independently applies the same four schema mutations and requires a nonzero oracle result for each, proving the internal assertions cannot pass vacuously.

**Verification**

- `jq -nr --slurpfile schema scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json --slurpfile fixture scripts/fixtures/iop-agent-chronos-transfer-state-v1.json -f scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq` — prints exactly `STATE_SCHEMA_CONTRACT_PASS` and exits 0.
- `bash -lc 'set -euo pipefail; probe_dir=$(mktemp -d); trap '\''rm -rf -- "$probe_dir"'\'' EXIT; mutations=('\''."$defs".record.allOf[0].if.required += ["missing_guard"]'\'' '\''."$defs".record.allOf[0].then.required += ["missing_required"]'\'' '\''."$defs".record.allOf[0].else.not.required += ["missing_forbidden_guard"]'\'' '\''."$defs".record.allOf += [{"not": {}}]'\''); for i in "${!mutations[@]}"; do jq "${mutations[$i]}" scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json >"$probe_dir/schema-$i.json"; set +e; output=$(jq -nr --slurpfile schema "$probe_dir/schema-$i.json" --slurpfile fixture scripts/fixtures/iop-agent-chronos-transfer-state-v1.json -f scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq 2>&1); rc=$?; set -e; test "$rc" -ne 0; test "$output" != "STATE_SCHEMA_CONTRACT_PASS"; done; printf "SCHEMA_SEMANTIC_MUTATIONS_REJECTED\n"'` — prints exactly `SCHEMA_SEMANTIC_MUTATIONS_REJECTED` and exits 0.

## Modified Files Summary

| File | Item |
|------|------|
| `scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq` | REVIEW_REVIEW_REVIEW_REFACTOR-1 |
| `agent-task/m-iop-agent-chronos-extraction-decoupling/05+03_state_fixture/CODE_REVIEW-cloud-G04.md` | REVIEW_REVIEW_REVIEW_REFACTOR-1 |

## Final Verification

1. `bash -lc 'set -euo pipefail; mapfile -t predecessor_logs < <({ test ! -f agent-task/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log || printf "%s\n" agent-task/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log; find agent-task/archive -path "*/m-iop-agent-chronos-extraction-decoupling/03+02_inventory_closure/complete.log" -type f -print 2>/dev/null; } | sort -u); test "${#predecessor_logs[@]}" -eq 1; awk "BEGIN {in_summary=0; found=0} /^## Summary$/ {in_summary=1; next} in_summary && /^## / {in_summary=0} in_summary && /final verdict: PASS/ {found++} END {exit found==1?0:1}" "${predecessor_logs[0]}"; printf "%s\n" "${predecessor_logs[0]}"'` — exactly one predecessor PASS.
2. `jq -e . scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json scripts/fixtures/iop-agent-chronos-transfer-state-v1.json >/dev/null && printf 'JSON_PARSE_PASS\n'` — both JSON documents parse.
3. `jq -nr --slurpfile schema scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json --slurpfile fixture scripts/fixtures/iop-agent-chronos-transfer-state-v1.json -f scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq` — prints exactly `STATE_SCHEMA_CONTRACT_PASS` and exits 0.
4. `bash -lc 'set -euo pipefail; probe_dir=$(mktemp -d); trap '\''rm -rf -- "$probe_dir"'\'' EXIT; mutations=('\''."$defs".record.allOf[0].if.required += ["missing_guard"]'\'' '\''."$defs".record.allOf[0].then.required += ["missing_required"]'\'' '\''."$defs".record.allOf[0].else.not.required += ["missing_forbidden_guard"]'\'' '\''."$defs".record.allOf += [{"not": {}}]'\''); for i in "${!mutations[@]}"; do jq "${mutations[$i]}" scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json >"$probe_dir/schema-$i.json"; set +e; output=$(jq -nr --slurpfile schema "$probe_dir/schema-$i.json" --slurpfile fixture scripts/fixtures/iop-agent-chronos-transfer-state-v1.json -f scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq 2>&1); rc=$?; set -e; test "$rc" -ne 0; test "$output" != "STATE_SCHEMA_CONTRACT_PASS"; done; printf "SCHEMA_SEMANTIC_MUTATIONS_REJECTED\n"'` — all four semantic mutations are rejected.
5. `bash -lc 'set -euo pipefail; manifest_ids=$(mktemp); fixture_ids=$(mktemp); trap '\''rm -f -- "$manifest_ids" "$fixture_ids"'\'' EXIT; awk -F "\t" '\''NR>1 && $2=="state" {print $1}'\'' scripts/fixtures/iop-agent-chronos-ownership-manifest.tsv | LC_ALL=C sort >"$manifest_ids"; jq -r '\''.records[] | select(.source_manifest=="original") | .logical_id'\'' scripts/fixtures/iop-agent-chronos-transfer-state-v1.json | LC_ALL=C sort >"$fixture_ids"; test "$(wc -l <"$manifest_ids")" -eq 10; cmp "$manifest_ids" "$fixture_ids"; test "$(jq -r '\''[.records[] | select(.source_manifest=="d04-addendum") | .logical_id] | sort | join(",")'\'' scripts/fixtures/iop-agent-chronos-transfer-state-v1.json)" = "state:cache-root,state:temp-root"; printf "STATE_ID_PROVENANCE_PASS\n"'` — original and addendum IDs remain exact.
6. `bash -lc 'set -euo pipefail; set +e; rg -n '\''/home/|/Users/|token|credential|secret|private_key'\'' scripts/fixtures/iop-agent-chronos-transfer-state-v1.schema.json scripts/fixtures/iop-agent-chronos-transfer-state-v1.json scripts/fixtures/iop-agent-chronos-transfer-state-v1.contract-test.jq; scan_rc=$?; set -e; case "$scan_rc" in 0) exit 1;; 1) :;; *) exit "$scan_rc";; esac; printf "SENSITIVE_SCAN_PASS\n"'` — no host path or sensitive pattern appears and scanner errors fail closed.
7. `git diff --check` — exits 0 with no output.

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