<!-- task=m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke plan=0 tag=TEST -->

# Plan - TEST

## For the Implementing Agent

Filling implementation-owned sections in `CODE_REVIEW-cloud-G06.md` is mandatory. Run every verification command exactly, paste actual output, keep both active files in place, and report ready for review. If blocked, record only the exact blocker, attempted commands/output, and resume condition in implementation-owned evidence. Do not ask the user, create control-plane files, classify next state, archive logs, or write `complete.log`; those are review-agent-only actions.

## Background

S10 requires restricted live evidence only where deterministic fixtures cannot establish upstream credential/endpoint behavior. OpenAI Chat and native Anthropic Messages are the two protocol-driver qualification calls selected here, one bounded generation per profile. The evidence stays in the review file and contains only provider, profile, requested/returned model identifier, revision-or-absence, UTC date, usage, and result.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/operational-observability-provider-management/milestones/multi-provider-protocol-profile-native-messages.md`
- Milestone link: [Milestone 문서](agent-roadmap/phase/operational-observability-provider-management/milestones/multi-provider-protocol-profile-native-messages.md)
- Task ids:
  - `live-smoke`: opt-in, one-shot, sanitized live qualification
- Completion mode: check-on-pass

## Analysis

### Files Read

- `apps/node/internal/adapters/openai_compat/protocol_profile_test.go`
- `agent-test/local/edge-smoke.md`

### SDD Criteria

`agent-roadmap/sdd/operational-observability-provider-management/multi-provider-protocol-profile-native-messages/SDD.md` is approved and unlocked. S10 maps `live-smoke` to an opt-in one-shot command and a sanitized qualification record; Evidence Map S10 requires provider/profile/model/date/result with no secret. The checklist therefore permits exactly one short generation for `openai_chat` and one for `anthropic_messages`, after preflight, and makes the review file the sanitized record.

### Verification Context

No handoff was supplied. Read-only preflight on 2026-08-01 found branch `feature/multi-provider-protocol-profile-native-messages` at `125dc83f` with 83 dirty paths and the separate `05+03,04_contract_spec_sync` review still active; no Edge process is running. The current host is user `abc`, Linux `6.10.14-linuxkit` on `aarch64`; Go `1.26.2`, SOPS `3.13.1`, jq, and curl are available at `/config/.local/bin/go`, `/config/.local/bin/sops`, `/bin/jq`, and `/bin/curl`. `/config/.config/sops/age/keys.txt`, `openai.sops.yaml`, and `anthropic.sops.yaml` are readable; no secret was decrypted or inspected.

External verification leaves the checkout and uses direct upstream HTTPS only: `https://api.openai.com` and `https://api.anthropic.com`. There is no repository build, config file, local port, or running Edge process required for this direct-upstream boundary. The source state is contextual rather than execution input, but the task must wait for predecessor `complete.log` evidence; it must record the then-current branch, HEAD, and dirty-path count. The repository-native fallback is S09's deterministic fixture suite; if either predecessor is incomplete or any preflight fails, make no provider call and leave the exact blocker in review evidence.

### Test Coverage Gaps

- S09 fixtures cover profile routing/tunnel behavior without credentials but cannot establish provider-account authentication, model availability, or a real provider terminal response.
- Existing 2026-08-01 direct-upstream records predate the selected OpenAI default and use an older Anthropic model; they do not satisfy this plan's selected calls.
- This task intentionally does not test an Edge-inbound principal, Edge tunnel, or Node runtime; it must not be presented as such evidence.

### Symbol References

None. This is execution evidence only and changes no source symbol.

### Split Judgment

This child has the stable external-evidence contract: after siblings 05 and 06 PASS, run exactly one bounded generation for each selected protocol driver and preserve a sanitized result. Predecessor index 05 (`05+03,04_contract_spec_sync`) is currently active without `complete.log`; predecessor index 06 (`06+01,02_fixture_suite`) is planned without `complete.log`. Both must be satisfied by their active or `agent-task/archive/2026/08/` `complete.log` before execution. This isolation lets fixture qualification PASS independently if a user-controlled credential or external endpoint blocks S10.

### Scope Rationale

No production source, tracked configuration, CI workflow, provider secret, or persistent qualification artifact is created. Gemini, Kimi, GLM, MiniMax, MiMo, Grok, and Seulgi are excluded from this plan; S10 is not a subscription-wide sweep. Edge-inbound and Node-runtime smoke remain excluded because these direct-upstream commands cannot prove them.

### Final Routing

`evaluation_mode=pair`; finalizer `finalize-task-policy.sh` routed the build and review targets with execution closure specified by the preflight contract. `large_indivisible_context=false`; positive loop risks are `boundary_contract` (SOPS-to-provider credential boundary) and `variant_product` (two protocol drivers), count 2; recovery signals and capability-gap evidence are false. Canonical files are `PLAN-local-G06.md` and `CODE_REVIEW-cloud-G06.md`.

## Dependencies and Execution Order

1. Confirm `05+03,04_contract_spec_sync` and `06+01,02_fixture_suite` have PASS `complete.log` in their active directory or the exact August 2026 archive path below.
2. Run preflight once. If it fails, do not decrypt a secret or issue a provider request.
3. Run the OpenAI discovery plus one short generation once, then the Anthropic discovery plus one short generation once. Do not retry, increase token caps, or add a provider.
4. Paste only sanitized output and the required record into the active review file; the review agent decides external-execution state.

## Implementation Checklist

- [ ] [TEST-1] Verify predecessor completion and the local SOPS/tool/host preflight without decrypting credentials or calling a provider.
- [ ] [TEST-2] Run exactly one bounded OpenAI `openai_chat` direct-upstream generation and record only sanitized evidence.
- [ ] [TEST-3] Run exactly one bounded Anthropic `anthropic_messages` direct-upstream generation and record only sanitized evidence.
- [ ] Fill implementation-owned sections in CODE_REVIEW-*-G??.md with actual implementation notes and verification output.

### [TEST-1] Establish the opt-in execution boundary

**Problem**

`agent-roadmap/phase/operational-observability-provider-management/milestones/multi-provider-protocol-profile-native-messages.md:69` forbids live qualification in routine tests, CI, secret maintenance, and automatic retries. At planning time the predecessor `complete.log` files were absent and the worktree was dirty, so source/routing facts must be captured again before an external call.

**Solution**

Use only read-only checks for the two permitted active-or-archive predecessor paths, the host SOPS file readability, required binaries, branch/HEAD, and dirty-path count. This command must finish successfully before either credential is decrypted. No source code or tracked file changes are made.

**Modified Files and Checklist**

- [ ] `agent-task/m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke/CODE_REVIEW-cloud-G06.md`: paste preflight stdout/stderr and the current branch/HEAD/dirty-path count.

**Test Strategy**

No source test is written: this is an external preflight. Do not invoke Go tests, SOPS decryption, curl, model discovery, or generation until this check passes.

**Verification**

```bash
(
set -euo pipefail
test -f agent-task/m-multi-provider-protocol-profile-native-messages/05+03,04_contract_spec_sync/complete.log || test -f agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/05+03,04_contract_spec_sync/complete.log
test -f agent-task/m-multi-provider-protocol-profile-native-messages/06+01,02_fixture_suite/complete.log || test -f agent-task/archive/2026/08/m-multi-provider-protocol-profile-native-messages/06+01,02_fixture_suite/complete.log
printf 'predecessors=complete\n'
command -v sops
command -v jq
command -v curl
sops --version | sed -n '1p'
jq --version
curl --version | sed -n '1p'
test -r /config/.config/sops/age/keys.txt
test -r /config/.config/sops/iop/openai.sops.yaml
test -r /config/.config/sops/iop/anthropic.sops.yaml
printf 'sops_inputs=readable\n'
id -un
uname -srm
git rev-parse --abbrev-ref HEAD
git rev-parse --short HEAD
git status --porcelain=v1 | wc -l
)
```

Expected: both predecessor checks and all tool/file checks exit 0; output records source state only and no secret.

### [TEST-2] Run the bounded OpenAI qualification call

**Problem**

The existing OpenAI record used `gpt-5-mini` with minimal reasoning and cannot establish the Milestone-selected `gpt-5.6-luna`/`high` request.

**Solution**

After TEST-1 passes, use a fail-fast subshell, decrypt the OpenAI key into one shell variable, and pass the auth header to curl through stdin config so it is not present in curl argv. Use one model-discovery request, then one `gpt-5.6-luna` generation with `reasoning_effort=high`, fixed Korean one-word instruction, and `max_completion_tokens=128`. Save raw responses only in a `mktemp` directory under `/tmp`, emit a sanitized jq object before asserting its pass predicate, and remove the directory and shell variable on every subshell exit. A failure remains visible as sanitized evidence and a non-zero status; do not retry or change the request.

**Modified Files and Checklist**

- [ ] `agent-task/m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke/CODE_REVIEW-cloud-G06.md`: record the sanitized OpenAI result only.

**Test Strategy**

No repository test is written. The command is the sole opt-in external test for `openai_chat`; it does not test Edge, Node, or an inbound IOP token.

**Verification**

```bash
(
set -eu
set +x
live_tmp="$(mktemp -d /tmp/iop-live-smoke.XXXXXX)"
openai_age_key_file="/config/.config/sops/age/keys.txt"
openai_sops_secret="/config/.config/sops/iop/openai.sops.yaml"
openai_smoke_key="$(SOPS_AGE_KEY_FILE="$openai_age_key_file" sops --decrypt --input-type yaml --output-type binary "$openai_sops_secret")"
trap 'rm -rf "$live_tmp"; unset openai_smoke_key' EXIT
curl --fail --silent --show-error --max-time 20 --config - --output "$live_tmp/openai-models.json" "https://api.openai.com/v1/models" <<EOF
header = "Authorization: Bearer ${openai_smoke_key}"
EOF
jq -e '.data | type == "array" and length > 0' "$live_tmp/openai-models.json" >/dev/null
curl --fail --silent --show-error --max-time 90 --config - --request POST "https://api.openai.com/v1/chat/completions" --output "$live_tmp/openai-generation.json" --data '{"model":"gpt-5.6-luna","reasoning_effort":"high","messages":[{"role":"developer","content":"반드시 한 단어로만 답하세요: 확인"},{"role":"user","content":"연결 테스트입니다. 지시대로 답하세요."}],"max_completion_tokens":128}' <<EOF
header = "Authorization: Bearer ${openai_smoke_key}"
header = "Content-Type: application/json"
EOF
jq -ce '{provider:"openai",profile:"openai_chat",requested_model:"gpt-5.6-luna",returned_model:(.model // "not-returned"),revision:(if (.model // "") != "" and .model != "gpt-5.6-luna" then .model else "not-returned" end),smoke_date_utc:(now | strftime("%Y-%m-%d")),result:(if .choices[0].finish_reason == "stop" and (.choices[0].message.content | type == "string" and length > 0) and (.usage.total_tokens | type == "number") then "pass" else "fail" end),usage:.usage}' "$live_tmp/openai-generation.json"
jq -e '.choices[0].finish_reason == "stop" and (.choices[0].message.content | type == "string" and length > 0) and (.usage.total_tokens | type == "number")' "$live_tmp/openai-generation.json" >/dev/null
)
```

Expected: discovery contains a model array and the single generation emits one sanitized `result:"pass"` object. Do not print raw response files or credentials.

### [TEST-3] Run the bounded Anthropic native-Messages qualification call

**Problem**

The existing Anthropic record used a prior Haiku model and does not establish the selected native Messages `claude-sonnet-5` request with `output_config.effort=high`.

**Solution**

After TEST-1 passes, use the same fail-fast subshell and stdin curl-config pattern for the Anthropic credential. Run one discovery request and one native Messages generation with `anthropic-version: 2023-06-01`, the fixed one-word instruction, and `max_tokens=64`. Emit only a sanitized jq object before asserting its pass predicate, remove all `/tmp` response files and the shell variable on exit, and return non-zero on a failed predicate. Do not retry, increase the cap, or transform this into an Edge claim.

**Modified Files and Checklist**

- [ ] `agent-task/m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke/CODE_REVIEW-cloud-G06.md`: record the sanitized Anthropic result only.

**Test Strategy**

No repository test is written. The command is the sole opt-in external test for `anthropic_messages`; it is direct upstream and explicitly not an Edge or Node tunnel test.

**Verification**

```bash
(
set -eu
set +x
live_tmp="$(mktemp -d /tmp/iop-live-smoke.XXXXXX)"
anthropic_age_key_file="/config/.config/sops/age/keys.txt"
anthropic_sops_secret="/config/.config/sops/iop/anthropic.sops.yaml"
anthropic_smoke_key="$(SOPS_AGE_KEY_FILE="$anthropic_age_key_file" sops --decrypt --input-type yaml --output-type binary "$anthropic_sops_secret")"
trap 'rm -rf "$live_tmp"; unset anthropic_smoke_key' EXIT
curl --fail --silent --show-error --max-time 20 --config - --output "$live_tmp/anthropic-models.json" "https://api.anthropic.com/v1/models" <<EOF
header = "x-api-key: ${anthropic_smoke_key}"
header = "anthropic-version: 2023-06-01"
EOF
jq -e '.data | type == "array" and length > 0' "$live_tmp/anthropic-models.json" >/dev/null
curl --fail --silent --show-error --max-time 90 --config - --request POST "https://api.anthropic.com/v1/messages" --output "$live_tmp/anthropic-generation.json" --data '{"model":"claude-sonnet-5","max_tokens":64,"output_config":{"effort":"high"},"system":"반드시 한 단어로만 답하세요: 확인","messages":[{"role":"user","content":"연결 테스트입니다. 지시대로 답하세요."}]}' <<EOF
header = "x-api-key: ${anthropic_smoke_key}"
header = "anthropic-version: 2023-06-01"
header = "content-type: application/json"
EOF
jq -ce '{provider:"anthropic",profile:"anthropic_messages",requested_model:"claude-sonnet-5",returned_model:(.model // "not-returned"),revision:(if (.model // "") != "" and .model != "claude-sonnet-5" then .model else "not-returned" end),smoke_date_utc:(now | strftime("%Y-%m-%d")),result:(if .stop_reason == "end_turn" and ([.content[] | select(.type == "text") | .text] | join("") | length > 0) and (.usage.input_tokens | type == "number") and (.usage.output_tokens | type == "number") then "pass" else "fail" end),usage:.usage}' "$live_tmp/anthropic-generation.json"
jq -e '.stop_reason == "end_turn" and ([.content[] | select(.type == "text") | .text] | join("") | length > 0) and (.usage.input_tokens | type == "number") and (.usage.output_tokens | type == "number")' "$live_tmp/anthropic-generation.json" >/dev/null
)
```

Expected: discovery contains a model array and the single generation emits one sanitized `result:"pass"` object. Do not print raw response files or credentials.

## Modified Files Summary

| File | Items |
|---|---|
| `agent-task/m-multi-provider-protocol-profile-native-messages/07+05,06_live_smoke/CODE_REVIEW-cloud-G06.md` | TEST-1, TEST-2, TEST-3 |

## Final Verification

Run TEST-1 once, then exactly the TEST-2 and TEST-3 command blocks once each. Both generation commands must emit a sanitized `result:"pass"` object, and the review evidence must identify provider, profile, requested model, returned identifier/revision-or-absence, UTC date, usage, and result without a raw credential or raw response. If preflight or either call fails, make no retry and record the blocker/output in the review file. After completing all code changes, fill implementation-owned sections in `CODE_REVIEW-*-G??.md`.
