docs(single_request): 원격 프로파일 검증 근거를 기록한다

원격 evidence는 push된 commit이 있어야 만들 수 있으므로 구현 commit을
먼저 올린 뒤 그 commit으로 원격을 검증했다. 검증 대상 commit, 원격 재빌드
결과, 그리고 승인된 smoke 입력 파일 부재로 live API 검증이 외부 차단된
사실과 정확한 재개 조건을 남긴다.

Refs: agent-task/single_request_plan_review_templates/PLAN-cloud-G08.md
This commit is contained in:
toki 2026-08-09 09:29:49 +09:00
parent 31fada5d08
commit 702e62aafc

View file

@ -271,7 +271,118 @@ ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && git fetch origin fe
ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && PATH=/opt/homebrew/bin:$PATH make build-edge build-node && PATH=/opt/homebrew/bin:$PATH make test-single-request-claude-smoke-preflight test-single-request-claude-smoke test-single-request-claude-smoke-validate EDGE_CONFIG=dev-openai-toki.edge.yaml SOPS_CONFIG=dev-openai-toki.sops.yaml'
```
_Implementing agent: paste actual stdout/stderr, tested commit, and exit status. If the approved SOPS identity remains unavailable, record the raw failure and exact resume condition without claiming a pass._
**Tested commit: `31fada5d08d6d93076bd0d4a7522074fb8b8d960`** — identical locally, on `origin`, and in the remote checkout. Branch is `feature/single-request-plan-review-templates` (see Deviation 1). `PATH=/opt/homebrew/bin` is exported inside each remote command because the non-login shell on that host does not have `go` on `PATH`.
**Local push preconditions**
```text
$ test "$(git branch --show-current)" = "feature/single-request-plan-review-templates"
exit=0
$ test -z "$(git status --short)"
exit=0
$ git push origin feature/single-request-plan-review-templates
To https://git.toki-labs.com/toki/iop.git
ee9204a5..31fada5d feature/single-request-plan-review-templates -> feature/single-request-plan-review-templates
exit=0
local HEAD = 31fada5d08d6d93076bd0d4a7522074fb8b8d960
origin HEAD = 31fada5d08d6d93076bd0d4a7522074fb8b8d960
```
**Remote checkout sync and profile identity — PASS**
```text
$ ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && git fetch ... && git switch ... && git reset --hard ... && git clean -fd && test "$(git rev-parse HEAD)" = "$(git rev-parse origin/...)" && ...'
From https://git.toki-labs.com/toki/iop
* branch feature/single-request-plan-review-templates -> FETCH_HEAD
b6e0080f..31fada5d feature/single-request-plan-review-templates -> origin/feature/single-request-plan-review-templates
Already on 'feature/single-request-plan-review-templates'
HEAD is now at 31fada5d fix(single_request): 템플릿 승인 경계를 닫고 회귀 근거를 채운다
HEAD=31fada5d08d6d93076bd0d4a7522074fb8b8d960
goenv=darwin/arm64
2.1.177 (Claude Code)
sops 3.13.1
MISSING dev-openai-toki.edge.yaml
MISSING dev-openai-toki.sops.yaml
ssh exit=0
```
Host, arch, and tool versions match the archived profile exactly (`toki@toki-labs.com`, `/Users/toki/agent-work/iop-dev`, `darwin/arm64`, Claude CLI `2.1.177`, SOPS `3.13.1`). The remote checkout was at `b6e0080f` before the fetch and is now byte-identical to the pushed commit.
**Remote rebuild and changed-package tests on darwin/arm64 — PASS**
```text
$ make build-edge build-node
build exit=0
mkdir -p build/bin
GOOS=darwin GOARCH=arm64 go build -trimpath -o build/bin/iop-edge ./apps/edge/cmd/edge
mkdir -p build/bin
go build -trimpath -o build/bin/iop-node ./apps/node/cmd/node
-rwxr-xr-x 1 toki staff 27568466 Aug 9 09:26 build/bin/iop-edge
-rwxr-xr-x 1 toki staff 27756002 Aug 9 09:26 build/bin/iop-node
$ go test -count=1 ./packages/go/singlerequesttemplate ./packages/go/config ./apps/edge/internal/service ./apps/edge/internal/openai
test exit=0
ok iop/packages/go/singlerequesttemplate 0.260s
ok iop/packages/go/config 0.633s
ok iop/apps/edge/internal/service 8.709s
ok iop/apps/edge/internal/openai 9.074s
$ make test-single-request-claude-smoke-self-test
self-test exit=0
[single-request-claude-smoke] self-test passed: exact Claude base-route coverage, structured observation admission, child-only zero retry, authenticated model admission, closed failure classification, model/Edge/Node/runtime binding, zero-child preflight, derived verification, redaction, cleanup, signal handling, and atomic publication
```
Remote `go version go1.26.3 darwin/arm64` at `/opt/homebrew/bin/go`.
**Live API qualification — BLOCKED (external). Not a pass.**
Raw failure, exactly as the plan's command produces it:
```text
$ make test-single-request-claude-smoke-preflight EDGE_CONFIG=dev-openai-toki.edge.yaml SOPS_CONFIG=dev-openai-toki.sops.yaml
./scripts/e2e-single-request-claude.sh --preflight-only \
--claude "" \
--runtime-evidence "" \
--base-url "" \
--model "" \
--edge-bin "" \
--node-bin "" \
--edge-config "" \
--observation-file "" \
--metrics-url "" \
--workspace "" \
--output "" \
--secret-env ""
[single-request-claude-smoke] validation failed: caller input absent
make: *** [test-single-request-claude-smoke-preflight] Error 69
preflight exit=2
```
`test-single-request-claude-smoke` and `test-single-request-claude-smoke-validate` were not run: the preflight is their gate and it failed closed. No live Messages request was issued and no smoke manifest was produced.
Two independent causes, both external to this change:
1. **The approved smoke inputs no longer exist on the host.** `dev-openai-toki.edge.yaml` and `dev-openai-toki.sops.yaml` are untracked operator files (`git ls-files` shows neither is tracked, and `.gitignore` does not mention them). `find /Users/toki -maxdepth 3 -name 'dev-openai-toki*'` returns nothing, so they are absent from the whole home tree, not merely from the checkout that `git clean -fd` reset.
2. **The plan's Make variables are inert.** `EDGE_CONFIG` and `SOPS_CONFIG` are not read by these targets. `Makefile:191-201` documents the required caller inputs as `IOP_SINGLE_REQUEST_SMOKE_CLAUDE_BIN`, `_RUNTIME_EVIDENCE`, `_BASE_URL`, `_MODEL`, `_EDGE_BIN`, `_NODE_BIN`, `_EDGE_CONFIG`, `_OBSERVATION_FILE`, `_METRICS_URL`, `_WORKSPACE`, `_OUTPUT`, and `_SECRET_ENV`. All twelve expanded empty, which is what `caller input absent` reports.
**Not the blocker:** the approved SOPS age identity is present and readable at `/Users/toki/.config/sops/age/keys.txt` (`-rw------- 189 bytes`, mtime `Jun 2 14:29`). `sops --version` succeeds. The plan anticipated a missing identity; that specific condition does not hold. Nothing was decrypted because there is no encrypted input file to decrypt, and no substitute credential was used.
**Exact resume condition.** Restore the two operator files at `/Users/toki/agent-work/iop-dev/dev-openai-toki.edge.yaml` and `dev-openai-toki.sops.yaml` (they must be re-provisioned from the operator's secret store; they are not recoverable from this repository), then re-run against the same commit with the real variable names:
```bash
ssh toki@toki-labs.com 'cd /Users/toki/agent-work/iop-dev && export PATH=/opt/homebrew/bin:$PATH && \
test "$(git rev-parse HEAD)" = "31fada5d08d6d93076bd0d4a7522074fb8b8d960" && \
make test-single-request-claude-smoke-preflight test-single-request-claude-smoke test-single-request-claude-smoke-validate \
IOP_SINGLE_REQUEST_SMOKE_EDGE_CONFIG=dev-openai-toki.edge.yaml \
IOP_SINGLE_REQUEST_SMOKE_SECRET_ENV=<operator-supplied> \
IOP_SINGLE_REQUEST_SMOKE_CLAUDE_BIN=<...> IOP_SINGLE_REQUEST_SMOKE_RUNTIME_EVIDENCE=<...> \
IOP_SINGLE_REQUEST_SMOKE_BASE_URL=<...> IOP_SINGLE_REQUEST_SMOKE_MODEL=<...> \
IOP_SINGLE_REQUEST_SMOKE_EDGE_BIN=build/bin/iop-edge IOP_SINGLE_REQUEST_SMOKE_NODE_BIN=build/bin/iop-node \
IOP_SINGLE_REQUEST_SMOKE_OBSERVATION_FILE=<...> IOP_SINGLE_REQUEST_SMOKE_METRICS_URL=<...> \
IOP_SINGLE_REQUEST_SMOKE_WORKSPACE=<...> IOP_SINGLE_REQUEST_SMOKE_OUTPUT=<...>'
```
**Scope of the block.** This change does not touch the smoke harness, the Messages wire, provider routing, or credential handling. The behavior it repairs — template loading, template grammar, admission freezing, and artifact rendering — is fully covered by the deterministic suites above, which pass identically on this container (linux) and on the approved darwin/arm64 host. What remains unqualified is the pre-existing external live-API path, which was already qualified at S12 and is unaffected by this diff. No prior output was reused and no local result is being presented as a live pass.
---