# 구조화된 자동화 표면

## 목표

외부 자동화가 OTO를 안정적으로 호출하고 결과를 해석할 수 있도록, 이미 존재하는 command catalog와 YAML validation 기반을 외부 소비 가능한 출력 계약으로 확장한다.
구조화된 실행 결과와 step event 계약을 함께 정리하고, `oto exe --json`의 최종 실행 결과를 외부 도구가 안정적으로 파싱할 수 있게 한다.

## 단계

CLI 자동화 표면 정리

## 상태

완료

## 구현 잠금

- 상태: 해제
- 이유: 완료된 Milestone이며 완료 기준과 완료 근거가 문서화되어 있다. 후속 확장은 별도 Milestone에서 다룬다.
- 해제 근거: 완료된 Milestone으로 완료 근거가 `작업 컨텍스트`에 문서화되어 있다.
- 잠금 중 금지:
  - 해당 없음

## 범위

- `Command.specs`와 `Command.catalogRows`를 command catalog의 내부 단일 진실 소스로 유지한다.
- 기존 YAML build/pipeline validation 흐름을 외부 자동화가 호출하고 해석할 수 있는 계약으로 정리한다.
- 실행 결과와 step event를 외부 도구가 파싱하기 쉬운 형태로 구조화한다.
- 기존 사람이 읽는 로그 출력과 자동화용 구조화 출력의 관계를 정리한다.

## 필수 기능

- [x] [catalog-cli] command catalog를 CLI 또는 다른 안정된 조회 경로로 노출하는 방식이 정의되어 있다. (oto catalog CLI 추가로 달성)
- [x] [yaml-validation] YAML validation의 입력, 출력, 실패 기준이 외부 자동화용 계약으로 정의되어 있다. (`oto validate -f <file> --json`, `YamlValidationResult` JSON 계약으로 달성)
- [x] [result-envelope] 실행 결과의 성공/실패, exit code, 에러 정보 표현이 출력 envelope로 구조화되어 있다. (`BuildResult.toJson`, `CommandExe --json` 출력 계약으로 달성)
- [x] [step-events] step event의 최소 필드와 발생 시점이 정의되어 있다. (`StepEvent` 모델, `Pipeline.execute()`의 started/completed/failed 기록, `ExecutionContext` 수집으로 달성)
- [x] [event-snapshot] `executionResult.stepEvents`가 build 완료 시점의 이벤트 히스토리를 안정적으로 보존한다. (`Application.build()`의 `List<StepEvent>.of(context.stepEvents)` 스냅샷 전달과 회귀 테스트로 달성)

## 완료 기준

- [x] 외부 자동화가 내부 Dart API에 직접 의존하지 않고 command catalog를 조회할 수 있다.
- [x] 외부 자동화가 실행 전에 파이프라인 구성을 검증하고 실패 원인을 해석할 수 있다. (`schemaVersion`, `type`, `valid`, `phase`, `message`, `exitCode` 출력으로 달성)
- [x] 외부 자동화가 실행 후 성공/실패와 실패 원인을 안정적으로 해석할 수 있다. (`BuildResult.toJson` 및 `oto exe --json` 출력으로 달성)
- [x] step 단위 진행 상황을 사람이 읽는 로그에만 의존하지 않고 소비할 수 있다. (`BuildResult.toJson` 내 `stepEvents` 배열 포함으로 달성)
- [x] 같은 프로세스에서 build가 연속 실행되어도 이전 `BuildResult`의 step event JSON이 다음 `resetStepEvents()`에 의해 비워지지 않는다. (`BuildResult regression - stepEvents snapshot` 테스트로 달성)

## 범위 제외

- Edge agent 네트워크 프로토콜을 구현하지 않는다.
- 웹 UI나 대시보드를 만들지 않는다.
- 기존 YAML 커맨드 모델을 대체하지 않는다.

## 작업 컨텍스트

- `lib/oto/commands/command.dart`, `lib/oto/commands/command_registry.dart`, `lib/oto/core/build_result.dart`, `lib/oto/pipeline/**`, `assets/yaml/sample/**`를 우선 확인한다.
- 완료 근거는 `Command.specs`, `Command.catalogRows`, `Application.validateYamlContent()`, `YamlValidationResult`, `StepEvent`, `ExecutionContext`, `Pipeline.execute()`, `BuildResult.toJson()`, `CommandExe --json`이다.
- command, pipeline, sample 도메인 rule이 관련될 수 있다.
- 완료된 기준선:
  - `Command.specs`와 `Command.catalogRows`가 등록된 커맨드의 내부 catalog 소스로 존재한다.
  - `Application.build()`와 `Pipeline.pipelineInitialize()` 경로에 YAML build/pipeline validation 흐름이 존재한다.
  - `Application.validateYamlContent()`와 `CommandValidateCli`가 실행 없이 YAML을 검증하고 `YamlValidationResult.toJson()`으로 자동화용 결과를 출력한다.
  - `BuildResult.toJson()`은 `schemaVersion`, `type: executionResult`, `success`, `exitCode`, `message`, `error`, `stepEvents`를 포함한다.
  - `Application.build()`는 success/failure 결과 모두에 완료 시점의 `stepEvents` 스냅샷을 전달한다.
  - `CommandExe --json`은 사람이 읽는 실행 로그를 섞지 않고 parseable execution result JSON을 출력한다.
  - `test/oto_application_test.dart`, `test/oto_core_test.dart`, `test/oto_context_test.dart`가 result envelope, CLI JSON 출력, step event 수집과 스냅샷 보존을 검증한다.
