---
domain: command
last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872
last_rule_updated_at: 2026-06-13
---

# command

## 목적 / 책임

외부 시스템(Git, Jenkins, FTP, Slack, iOS 빌드 등)과의 실제 연동을 구현하는 커맨드 계층과, 커맨드 파라미터 데이터 모델을 담당한다.
파이프라인은 커맨드를 호출만 하며, 실제 I/O·프로세스 실행·외부 API 호출은 이 도메인에 둔다.

## 포함 경로

- `apps/runner/lib/oto/commands/` — 커맨드 구현체 (카테고리별 하위 폴더)
- `apps/runner/lib/oto/data/` — 커맨드 파라미터 데이터 모델 (`*_data.dart`, `*.g.dart`). `pipeline_data.dart`는 pipeline 도메인
- `apps/runner/assets/template/` — 커맨드 실행 중 사용하는 템플릿 파일

## 제외 경로

- `apps/runner/lib/oto/pipeline/` — 실행 흐름 제어 (커맨드 dispatch 이전)
- `apps/runner/lib/oto/core/` — 태그 치환, 데이터 합성 (커맨드 실행 이전)
- `apps/runner/lib/oto/data/pipeline_data.dart` — workflow/조건/반복 데이터 모델 (`pipeline` 도메인)
- `apps/runner/assets/yaml/sample/` — YAML 사용 예시 (`sample` 도메인)

## 주요 구성 요소

- `Command` (`command.dart`) — 커맨드 베이스 클래스, `CommandType` enum
- `CommandSpec` (`command.dart`) — CommandType → category/dataModel/samplePath 메타데이터
- `registerAllCommands()` (`command_registry.dart`) — 카테고리별 register 함수를 호출해 CommandType → Command 매핑 구성
- `CommandCatalog` / `CommandCatalogEntry` (`command_catalog.dart`) — 등록된 CommandSpec 목록과 sample 존재 여부 조회
- `CommandRuntime` / `DefaultCommandRuntime` (`command_runtime.dart`) — 커맨드 외부 프로세스 실행 추상화
- `CommandCatalogRunnerCapabilityProvider` (`runner_command_capability_provider.dart`) — agent 등록 시 현재 command catalog를 runner capability summary로 변환
- `DataParam` (`base_data.dart`) — 모든 커맨드 파라미터의 베이스
- `DataBuild` / `DataScheduler` (`command_data.dart`) — YAML 최상위 build/scheduler 데이터
- `DataCommand` (`command_data.dart`) — 모든 커맨드에 전달되는 통합 컨테이너

배포/패키징 보조 파일 및 스크립트는 이 도메인의 대상이 아니다.

커맨드 카테고리와 우선 참조 파일:

| 범주 | 구현 경로 | 데이터 모델 |
|------|-----------|-------------|
| build | `apps/runner/lib/oto/commands/build/` | `apps/runner/lib/oto/data/build_data.dart` |
| file | `apps/runner/lib/oto/commands/file/` | `apps/runner/lib/oto/data/file_data.dart` |
| git / GitHub | `apps/runner/lib/oto/commands/git/` | `apps/runner/lib/oto/data/git_data.dart` |
| ftp / web | `apps/runner/lib/oto/commands/ftp/`, `apps/runner/lib/oto/commands/web/` | `apps/runner/lib/oto/data/network_data.dart` |
| notification | `apps/runner/lib/oto/commands/notification/`, `apps/runner/lib/oto/utils/mattermost/` | `apps/runner/lib/oto/data/notification_data.dart` |
| jira / jenkins | `apps/runner/lib/oto/commands/jira/`, `apps/runner/lib/oto/commands/jenkins/` | `apps/runner/lib/oto/data/integration_data.dart`, `apps/runner/lib/oto/data/jira_data.dart` |
| infra / external tool | `apps/runner/lib/oto/commands/aws/`, `apps/runner/lib/oto/commands/docker/`, `apps/runner/lib/oto/commands/gradle/`, `apps/runner/lib/oto/commands/infra/`, `apps/runner/lib/oto/commands/proto/` | `apps/runner/lib/oto/data/infra_data.dart`, `apps/runner/lib/oto/data/util_data.dart` |
| shell / process / util | `apps/runner/lib/oto/commands/shell/`, `apps/runner/lib/oto/commands/process/`, `apps/runner/lib/oto/commands/util/` | `apps/runner/lib/oto/data/util_data.dart` |

현재 등록된 command type은 `CommandType` enum과 `registerAllCommands()`를 기준으로 한다.
대표 신규/확장 type은 `BuildDart`, `BuildDartCompile`, `CreateAppData`, `PublishiOS`, `TestflightStatusCheck`, `XcodeprojAddFile`, `Notarize`, `Files`, `GitPull`, `GitCheckout`, `GitReset`, `GitStashPush`, `GitStashApply`, `StringReplacePattern`, `StringIndex`를 포함한다.

커맨드 asset:

| asset | 사용처 |
|-------|--------|
| `apps/runner/assets/template/index.html` | iOS publish HTML 템플릿 |
| `apps/runner/assets/template/manifest.plist` | iOS publish manifest 템플릿 |

## 유지할 패턴

- 새 커맨드는 반드시 `Command` 상속 후 카테고리별 `register*Command(s)()` 함수와 `registerAllCommands()` 경로에 등록
- `Command.register()`에는 `CommandSpec`을 함께 전달해 category, dataModel, samplePath를 기록
- 파라미터 모델은 `DataParam` 상속 + `@JsonSerializable`
- `CommandCatalog`와 CLI `catalog` 출력은 `CommandSpec`을 기준으로 하므로 신규 커맨드의 category/dataModel/samplePath 누락 여부를 함께 확인한다
- agent runner capability는 `CommandCatalogRunnerCapabilityProvider`가 `registerAllCommands()`와 `Command.catalogRows`를 통해 생성하므로, command type 추가/삭제 시 capability 노출도 함께 바뀐다
- `*.g.dart`는 `dart run build_runner build`로 생성한다. 생성 파일 직접 수정은 생성 불가한 긴급 상황에서만 한다
- `getWorkspace()`: workspace 필드 → `property['workspace']` → `commonData.workspace` 순으로 resolve
- 커맨드 파라미터는 `getParam(command)`를 통해 태그 치환과 workspace resolve를 거친 뒤 `Data*` 모델로 파싱한다
- 결과 저장은 `<@property.key>` 형태의 쓰기 태그와 `setProperty()` / `complete()`의 `setResult`, `setExitCode` 흐름을 우선 사용한다
- 외부 프로세스 실행은 `Command.runtime`을 통해 `CommandRuntime.start()`, `run()`, `runExecutable()`, `startDetached()` 중 목적에 맞게 사용한다
- 커맨드 추가/파라미터 변경 시 관련 `apps/runner/assets/yaml/sample/**`와 README 커맨드 목록 갱신 필요 여부를 확인한다
- 커맨드가 `apps/runner/assets/template/**`를 읽거나 출력 형식에 의존하면 템플릿 경로와 placeholder 계약을 함께 확인한다
- 데이터 모델 변경 후 `dart run build_runner build`와 `dart analyze`를 실행한다

## 다른 도메인과의 경계

- **pipeline**: `Command.execute(DataCommand)`를 호출하는 시점이 경계. 커맨드는 흐름을 모른다
- **core**: 태그 치환은 core가 완료한 후 DataCommand가 커맨드에 전달됨
- **cli**: CLI `catalog`/`validate`는 command/core 정보를 읽어 출력하거나 검증하지만 커맨드 실행 로직은 command 도메인에 남긴다
- **sample**: YAML 사용 예시는 sample 도메인이 담당한다. 커맨드 파라미터 변경 시 sample 도메인과 동기화한다
- **agent**: agent 등록 payload에 들어가는 command catalog summary는 command 도메인이 제공하고, agent 도메인은 `RunnerCapabilityProvider` interface를 소비한다
- **framework**: `dart_framework`의 `ProcessExecutor`, path/system 유틸은 외부 런타임 의존성으로 사용한다. OTO 비즈니스 로직을 framework 의존성 쪽으로 옮기지 않는다

## 금지 사항

- 커맨드에서 다른 커맨드를 직접 인스턴스화하거나 호출하지 않는다
- 흐름 제어(if/loop) 로직을 커맨드 내부에 넣지 않는다
- 카테고리별 register 함수와 `registerAllCommands()` 경로 외 장소에서 CommandType 매핑을 추가하지 않는다
- 커맨드 구현 중 `Application.instance.dataCommandMap`을 직접 순회하거나 파이프라인 구조를 해석하지 않는다
- 샘플 YAML에 실제 토큰, 비밀번호, API 키를 넣지 않는다
