<!-- task=m-cross-os-runner-bootstrap/02_unix_bootstrap plan=0 tag=BOOTSTRAP_UNIX -->

# PLAN: Linux/macOS shell bootstrap 확장

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

이 계획은 `[unix-bootstrap]` 완료만 목표로 한다. Windows PowerShell, Core API schema 변경, runner registry 연결 smoke는 다른 split의 책임이다.

## 배경

현재 shell bootstrap은 Linux arch만 감지해 `oto-linux-x64.tar.gz` 또는 `oto-linux-arm64.tar.gz`를 내려받는다. README와 테스트 fixture에는 macOS asset 이름까지 고정됐으므로 shell script가 OS/arch를 함께 감지해야 한다.

## Roadmap Targets

- Milestone: `agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md`
- Epic: `[bootstrap-platforms] Cross-OS bootstrap contract`
- Task id: `[unix-bootstrap]`
- Completion mode: check-on-pass

## 분석 결과

### 읽은 파일

- `apps/runner/assets/script/shell/oto_agent_bootstrap.sh`
- `services/core/internal/httpserver/oto_agent_bootstrap.sh`
- `services/core/internal/httpserver/bootstrap_provider.go`
- `services/core/internal/httpserver/server_test.go`
- `apps/runner/test/oto_agent_bootstrap_script_test.dart`
- `README.md`
- `agent-test/local/rules.md`
- `agent-test/local/agent-smoke.md`

### 테스트 환경 규칙

기본 환경은 local이며 agent smoke는 runner bootstrap script 변경 후 `cd apps/runner && dart test test/oto_agent_bootstrap_script_test.dart`와 Core embedded copy 검증을 요구한다.

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

현재 script 실행 테스트는 Linux archive fixture만 실제 실행한다. macOS는 이 workspace에서 실행할 수 없으므로 script text/fixture 기반 검증으로 asset 선택 분기와 경로 생성 계약을 확인해야 한다.

### 심볼 참조

`oto_agent_bootstrap.sh`는 runner asset과 Core embedded copy가 byte-identical이어야 한다. `TestEmbeddedBootstrapScriptMatchesRunnerAsset`가 이 계약을 검증한다.

### 분할 판단

이 작업은 `01_core_command` 없이도 shell asset 자체를 확장할 수 있다. `04+02,03_binary_contract`는 이 작업 완료 후 Unix binary check를 보강한다.

### 범위 결정 근거

Linux/macOS POSIX shell 흐름만 수정한다. Windows zip 압축 해제와 PowerShell quoting은 `03+01_windows_bootstrap`에서 다룬다.

### 빌드 등급

`cloud-G07`: shell process 흐름, OS command output, archive extraction 계약이 핵심이므로 terminal-agent 판단과 꼼꼼한 테스트가 필요하다.

## 구현 체크리스트

- [ ] shell script가 `uname -s`와 `uname -m` 조합으로 Linux/macOS x64/arm64 asset을 선택한다.
- [ ] macOS 기본 install/config/workspace/log 경로가 기존 설정 의미를 보존한다.
- [ ] runner asset과 Core embedded script copy를 동기화한다.
- [ ] script fixture 테스트가 Linux/macOS asset matrix와 unsupported OS/arch 실패를 검증한다.
- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.

### [BOOTSTRAP_UNIX-1] OS/arch asset 선택

문제: script가 Linux만 지원하고 macOS asset을 선택하지 않는다.

해결 방법: `uname -s` 결과를 정규화해 `linux` 또는 `macos`로 매핑하고, arch는 x64/arm64로 매핑한다. unsupported 조합은 설치 전 명확히 실패한다.

수정 파일 및 체크리스트:

- `apps/runner/assets/script/shell/oto_agent_bootstrap.sh`
- `services/core/internal/httpserver/oto_agent_bootstrap.sh`
- `apps/runner/test/oto_agent_bootstrap_script_test.dart`

테스트 작성: script text에 네 asset이 모두 포함되고 unsupported OS/arch 메시지가 token 없이 실패하는지 검증한다.

중간 검증: `cd apps/runner && dart test test/oto_agent_bootstrap_script_test.dart`

### [BOOTSTRAP_UNIX-2] embedded copy 동기화

문제: Core는 embedded shell copy를 따로 들고 있어 drift가 생길 수 있다.

해결 방법: runner asset 변경 후 Core embedded copy를 동일 내용으로 갱신한다.

수정 파일 및 체크리스트:

- `services/core/internal/httpserver/oto_agent_bootstrap.sh`
- `services/core/internal/httpserver/server_test.go`

테스트 작성: 기존 embedded copy 일치 테스트가 계속 통과해야 한다.

중간 검증: `cd services/core && go test ./...`

## 수정 파일 요약

| 경로 | 목적 |
|------|------|
| `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` | Linux/macOS bootstrap 구현 |
| `services/core/internal/httpserver/oto_agent_bootstrap.sh` | Core embedded script 동기화 |
| `apps/runner/test/oto_agent_bootstrap_script_test.dart` | OS/arch fixture 검증 |
| `services/core/internal/httpserver/server_test.go` | embedded copy 회귀 검증 |

## 최종 검증

- `cd apps/runner && dart test test/oto_agent_bootstrap_script_test.dart`
- `cd services/core && go test ./...`

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