<!-- task=m-field-bootstrap-test-port-readiness/02+01_one_line_node plan=0 tag=TEST -->

# One-Line Node Bootstrap Plan - TEST

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

구현을 마친 뒤 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 실제 변경 내용과 검증 출력으로 채워야 한다. 검증은 계획에 적힌 명령을 실행한 실제 stdout/stderr로 기록하고, active 파일은 그대로 둔 채 리뷰 준비 완료를 보고한다. 최종 판정, 로그 rename, `complete.log`, archive 이동은 code-review-skill 전용이다.

## 배경

현재 Milestone의 `[one-line-node]`는 Apple Silicon Mac에서 한 줄 명령으로 Node binary 다운로드, checksum 확인, config 생성, Edge 접속까지 이어져야 완료된다. 작업트리에는 `bin/build/field-binaries.sh`가 `darwin/arm64` Node artifact와 `bootstrap/node-darwin-arm64.sh`를 생성하는 변경이 이미 들어와 있다. 이 계획은 선행 `01_serve_lifecycle` 완료 뒤 실제 artifact URL과 Apple Silicon 실행 경로를 검증해 one-line UX를 마무리한다.

## 의존 관계 및 구현 순서

- 이 subtask 디렉터리 이름은 `02+01_one_line_node`이며, 같은 task group의 `01_serve_lifecycle`이 먼저 `complete.log`를 만들어야 한다.
- 선행 완료 전에는 Mac one-line bootstrap 검증을 시작하지 않는다.

## 분석 결과

### 읽은 파일

- `agent-ops/roadmap/current.md`
- `agent-ops/roadmap/phase/serving-routing-optimization/PHASE.md`
- `agent-ops/roadmap/phase/serving-routing-optimization/milestones/field-bootstrap-test-port-readiness.md`
- `agent-task/m-field-bootstrap-test-port-readiness/reboot-handoff.md`
- `docs/deploy-dev.md`
- `bin/build/field-binaries.sh`
- `bin/node.sh`
- `Makefile`
- `packages/config/config.go`
- `configs/edge.yaml`

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

- Artifact layout: 임시 `darwin/arm64` build로 `iop-node`, `iop-node.sha256`, `SHA256SUMS`, `manifest.env`, `bootstrap/node-darwin-arm64.sh` 생성이 확인됐다. 별도 자동 테스트는 없다.
- One-line bootstrap: generated shell script가 실제 Apple Silicon Mac에서 실행되어 Edge에 등록되는지는 아직 검증되지 않았다.
- External artifact server: `python3 -m http.server 18080 ...`와 외부 `toki-labs.com:18080` 접근성은 환경 의존이며 자동 테스트가 없다.

### 심볼 참조

- 이름 변경 또는 제거 없음.

### 분할 판단

- 분할 판단 정책을 계획 파일 선택 전에 평가했다.
- 공유 task group은 `m-field-bootstrap-test-port-readiness`다.
- `01_serve_lifecycle`는 Edge listener와 local registration smoke를 선행 검증한다.
- `02+01_one_line_node`는 `01_serve_lifecycle` 완료 뒤 artifact publish와 Apple Silicon one-line execution을 검증한다.
- 이 작업은 remote host, HTTP artifact serving, Mac execution이 필요해 Edge lifecycle 작업과 독립적으로 리뷰 가능한 후속 subtask다.

### 범위 결정 근거

- 이 계획은 `[one-line-node]`만 소유한다.
- `serve-lifecycle` 코드는 선행 subtask가 소유하므로 여기서 수정하지 않는다.
- Control Plane enrollment, 장기 credential 관리, OTO agent 구현은 Milestone 범위 제외라 다루지 않는다.
- `code-server` compose 재시작/recreate는 사용자가 명시하지 않으면 실행하지 않는다. 이미 적용된 포트를 관찰하는 검증은 가능하다.

### 빌드 등급

- build=`cloud-G07`, review=`cloud-G07`: shell script generation, artifact HTTP serving, real Mac process execution, Edge registration 확인이 포함된 terminal-agent 작업이다.

## 구현 체크리스트

- [ ] `01_serve_lifecycle`의 `complete.log`가 있는지 확인한다.
- [ ] Apple Silicon용 Node artifact와 bootstrap script를 생성하고 layout을 검증한다. 검증: Apple Silicon용 `iop-node`를 정해진 URL에서 다운로드할 수 있다.
- [ ] artifact/bootstrap HTTP를 열고 `iop-node`, `SHA256SUMS`, `bootstrap/node-darwin-arm64.sh`가 HTTP로 다운로드되는지 확인한다.
- [ ] Apple Silicon Mac에서 one-line command를 실행하고 Edge에서 node registration을 확인한다. 검증: Mac 테스트 환경에서 command 한 줄 실행 후 Edge에서 node registration을 확인한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

## [TEST-1] Artifact Layout and HTTP Download

### 문제

`[artifact-layout]`는 artifact 고정 위치와 URL 규칙이 실제 build output과 HTTP document root에 맞아야 한다. 현재 [field-binaries.sh](/config/workspace/iop/bin/build/field-binaries.sh:83)는 bootstrap script를 만들고, [deploy-dev.md](/config/workspace/iop/docs/deploy-dev.md:157)는 version directory를 document root로 두는 URL 규칙을 설명한다.

### 해결 방법

임시 `DIST_DIR`에 `darwin/arm64` Node artifact를 빌드한 뒤, version directory를 HTTP root로 열어 URL 다운로드를 확인한다. build script 또는 문서가 불일치하면 둘 중 실제 동작 기준으로 최소 수정한다.

현재 기준:

```bash
# docs/deploy-dev.md:146
VERSION=<field-version> \
APPS=node \
TARGETS="darwin/arm64" \
ARTIFACT_BASE_URL="http://toki-labs.com:18080" \
BOOTSTRAP_EDGE_ADDR="toki-labs.com:19090" \
BOOTSTRAP_NODE_TOKEN="CHANGE_ME_FIELD_TOKEN" \
DIST_DIR=dist/field \
./bin/build/field-binaries.sh
```

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

- [ ] `bin/build/field-binaries.sh`: generated bootstrap script가 `ARTIFACT_BASE_URL/<target>/iop-node`와 `SHA256SUMS`를 받는지 확인한다.
- [ ] `docs/deploy-dev.md`: documented layout과 actual output이 일치하는지 확인하고, 다르면 문서를 수정한다.

### 테스트 작성

별도 테스트 파일은 작성하지 않는다. 이 항목은 cross-compile artifact와 HTTP download 검증이 목적이며 shell test framework가 없다.

### 중간 검증

```bash
tmpdir=$(mktemp -d /tmp/iop-field-artifact.XXXXXX)
VERSION=field-check APPS=node TARGETS="darwin/arm64" ARTIFACT_BASE_URL="http://127.0.0.1:18080" BOOTSTRAP_EDGE_ADDR="127.0.0.1:39090" BOOTSTRAP_NODE_TOKEN="field-token" DIST_DIR="$tmpdir" ./bin/build/field-binaries.sh
python3 -m http.server 18080 --bind 127.0.0.1 -d "$tmpdir/field-check" > "$tmpdir/http.log" 2>&1 &
http_pid=$!
for _ in $(seq 1 10); do
  if curl -fsS http://127.0.0.1:18080/bootstrap/node-darwin-arm64.sh >/dev/null; then
    break
  fi
  sleep 1
done
cleanup() {
  kill "$http_pid" 2>/dev/null || true
  wait "$http_pid" 2>/dev/null || true
  rm -rf "$tmpdir"
}
trap cleanup EXIT
curl -fsS http://127.0.0.1:18080/darwin-arm64/iop-node -o /tmp/iop-node.download
curl -fsS http://127.0.0.1:18080/darwin-arm64/SHA256SUMS
curl -fsS http://127.0.0.1:18080/bootstrap/node-darwin-arm64.sh | sed -n '1,80p'
rm -f /tmp/iop-node.download
```

기대 결과: 세 URL이 모두 `2xx`로 응답하고 bootstrap script에 `EDGE_ADDR`, `NODE_TOKEN`, `exec "$BIN_FILE" serve --config "$CONFIG_FILE"`가 포함된다.

## [TEST-2] Apple Silicon One-Line Registration

### 문제

`[one-line-node]`는 generated script가 실제 Apple Silicon Mac에서 실행되어 Edge에 등록되는지 확인해야 완료된다. [docs/deploy-dev.md](/config/workspace/iop/docs/deploy-dev.md:175)의 한 줄 명령은 아직 실제 registration evidence가 없다.

### 해결 방법

선행 `01_serve_lifecycle` 완료 후 field Edge를 실행하고 artifact HTTP를 연다. Apple Silicon Mac에서 환경변수 override를 포함한 한 줄 명령을 실행해 token/config/binary 흐름을 확인하고, Edge 로그 또는 console에서 node registration을 증거로 남긴다.

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

- [ ] Mac 실행에서 checksum, quarantine xattr, config 생성, `iop-node serve` 중 실패가 있으면 `bin/build/field-binaries.sh`의 generated script를 최소 수정한다.
- [ ] 문서 명령이 실제 성공 명령과 다르면 `docs/deploy-dev.md`를 수정한다.
- [ ] Edge registration 근거와 Mac command stdout/stderr를 `CODE_REVIEW-cloud-G07.md`에 붙인다.

### 테스트 작성

별도 자동 테스트는 작성하지 않는다. 이 항목은 Mac 실기기와 Edge transport 연결이 완료 조건이다.

### 중간 검증

```bash
IOP_ARTIFACT_BASE_URL="http://toki-labs.com:18080" IOP_EDGE_ADDR="toki-labs.com:19090" IOP_NODE_TOKEN="CHANGE_ME_FIELD_TOKEN" curl -fsSL http://toki-labs.com:18080/bootstrap/node-darwin-arm64.sh | bash
```

기대 결과: Apple Silicon Mac에서 `~/iop-field/iop-node`와 `~/iop-field/node.yaml`이 생성되고, Edge 로그 또는 console에서 해당 node registration이 확인된다.

## 수정 파일 요약

| 파일 | 항목 |
|------|------|
| `bin/build/field-binaries.sh` | TEST-1, TEST-2 필요 시 |
| `docs/deploy-dev.md` | TEST-1, TEST-2 필요 시 |
| `/tmp/iop-field-artifact.*` | TEST-1 검증 전용, repo에 남기지 않음 |

## 최종 검증

```bash
go test ./...
```

기대 결과: 모든 Go 패키지가 `ok` 또는 `[no test files]`로 종료한다. 캐시 출력은 허용한다.

모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.
