From 5cecc55905f338e2e3694b8f77e830e8ccae1c41 Mon Sep 17 00:00:00 2001 From: toki Date: Mon, 15 Jun 2026 13:35:11 +0900 Subject: [PATCH] update domain rules and roadmap --- agent-ops/rules/project/domain/agent/rules.md | 68 ++++++++++++------- agent-ops/rules/project/domain/cli/rules.md | 18 +++-- .../rules/project/domain/command/rules.md | 10 ++- agent-ops/rules/project/domain/core/rules.md | 22 ++++-- .../rules/project/domain/framework/rules.md | 23 +++++-- .../rules/project/domain/pipeline/rules.md | 8 ++- .../rules/project/domain/sample/rules.md | 18 ++--- .../rules/project/domain/scheduler/rules.md | 4 +- agent-ops/rules/project/rules.md | 6 ++ agent-roadmap/ROADMAP.md | 3 + .../control-plane-product-surface/PHASE.md | 30 ++++++++ .../milestones/cross-os-runner-bootstrap.md | 68 +++++++++++++++++++ .../milestones/flutter-console-skeleton.md | 67 ++++++++++++++++++ 13 files changed, 286 insertions(+), 59 deletions(-) create mode 100644 agent-roadmap/phase/control-plane-product-surface/PHASE.md create mode 100644 agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md create mode 100644 agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md diff --git a/agent-ops/rules/project/domain/agent/rules.md b/agent-ops/rules/project/domain/agent/rules.md index 5762517..e1baa80 100644 --- a/agent-ops/rules/project/domain/agent/rules.md +++ b/agent-ops/rules/project/domain/agent/rules.md @@ -1,21 +1,21 @@ --- domain: agent -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # agent ## 목적 / 책임 -OTO Edge 서버에 CLI 기반 agent 노드를 등록하고, agent 실행에 필요한 config 파싱, Edge endpoint 해석, protobuf 등록 요청, bootstrap 스크립트를 담당한다. -파이프라인 실행 엔진이나 scheduler 등록 정책이 아니라 `oto agent run --config ` 실행 흐름과 Edge 연결 초기화가 이 도메인의 책임이다. +OTO Server에 CLI 기반 runner agent를 등록하고, agent config 파싱, 등록/heartbeat/disconnect, remote job claim, remote pipeline 실행, 실행 결과/로그/artifact 보고, bootstrap 스크립트를 담당한다. +파이프라인 실행 엔진이나 scheduler 등록 정책이 아니라 `oto agent run --config ` 실행 흐름과 OTO Server runner 세션 초기화가 이 도메인의 책임이다. ## 포함 경로 - `apps/runner/lib/cli/commands/command_agent.dart` — `agent run --config ` CLI 표면과 오류 출력 -- `apps/runner/lib/oto/agent/` — agent config, runner, Edge 등록 client, generated protobuf 런타임 코드 -- `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` — Linux agent 다운로드, config 생성, background 실행 bootstrap +- `apps/runner/lib/oto/agent/` — agent config, runner, OTO Server 등록/job client, remote run executor, legacy iop Edge compatibility client, generated protobuf 런타임 코드 +- `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` — Linux agent 다운로드, server config 생성, background 실행 bootstrap ## 제외 경로 @@ -23,51 +23,67 @@ OTO Edge 서버에 CLI 기반 agent 노드를 등록하고, agent 실행에 필 - `apps/runner/lib/cli/commands/command_catalog.dart` — command catalog 출력 (`cli` 도메인) - `apps/runner/lib/cli/commands/command_validate.dart` — pipeline YAML 검증 (`cli`/`core` 도메인) - `apps/runner/lib/cli/commands/command_scheduler.dart` — scheduler 명령 진입 (`scheduler` 도메인) -- `apps/runner/lib/oto/application.dart` — pipeline build 오케스트레션 (`core` 도메인) +- `apps/runner/lib/oto/application.dart` — pipeline build 오케스트레이션 (`core` 도메인) +- `apps/runner/lib/oto/core/build_result.dart` — 실행 결과/step event/artifact 결과 모델 (`core` 도메인) +- `apps/runner/lib/oto/core/output_port.dart` — runner 출력 포트 추상화 (`core` 도메인) +- `apps/runner/lib/cli/runner_output_adapter.dart` — CLI 출력 포트 adapter (`cli` 도메인) - `apps/runner/lib/oto/pipeline/` — pipeline workflow 실행 (`pipeline` 도메인) - `apps/runner/lib/oto/commands/` — pipeline에서 호출되는 커맨드 구현체 (`command` 도메인) +- `apps/runner/lib/oto/commands/runner_command_capability_provider.dart` — agent 등록용 command catalog capability provider (`command` 도메인) - `apps/runner/assets/script/`의 기타 build/package helper — CLI/배포 보조 asset (`cli` 도메인) ## 주요 구성 요소 - `CommandAgent` — `agent` CLI subcommand 파싱, config 로딩, runner 호출, exit code 처리 -- `AgentConfig` / `AgentIdentityConfig` / `EdgeConnectionConfig` / `AgentRuntimeConfig` — agent bootstrap YAML 구조와 필수 필드 검증 +- `AgentConfig` / `AgentIdentityConfig` / `ServerConnectionConfig` / `EdgeConnectionConfig` / `AgentRuntimeConfig` — agent bootstrap YAML 구조와 필수 필드 검증 - `AgentConfigException` — config 파일/필드/타입 오류 표현 -- `AgentRunner` / `DefaultAgentRunner` — Edge 등록 workflow 실행과 결과 로그 출력 -- `RegistrationException` — Edge 등록 거절 또는 연결 실패 표현 -- `EdgeEndpoint` — Edge URL host/port 정규화와 기본 포트 결정 -- `EdgeRegistrationClient` — `proto_socket` 기반 RegisterRequest 전송 -- `RegistrationResult` — RegisterResponse accepted/rejected 결과 변환 -- `_OtoIopClient` — agent iop protobuf message registry를 가진 proto_socket client -- `apps/runner/lib/oto/agent/iop/*.pb*.dart` — `iop/runtime.proto` generated protobuf 코드 -- `apps/runner/lib/oto/agent/google/protobuf/*.pb*.dart` — `google/protobuf/struct.proto` generated protobuf 코드 +- `AgentRunner` / `DefaultAgentRunner` — OTO Server 등록 workflow, remote job loop, 결과 로그 출력 +- `RegistrationException` — OTO Server 등록 거절 또는 연결 실패 표현 +- `RegistrationClient` / `AgentSession` / `OtoServerJobSession` — 등록 transport와 세션 수명주기 추상화 +- `OtoServerRegistrationClient` — HTTP 기반 runner register, heartbeat, disconnect 요청 +- `OtoServerJobClient` — job claim, execution report, log append, artifact report, cancel, status, self-update 요청 +- `RemoteRunExecutor` / `RunRequestParser` / `RemoteRunInput` — OTO Server `RunRequest`를 workspace-confined YAML 실행 입력으로 변환하고 `Application.build()` 결과를 보고 +- `RunnerCapabilityProvider` / `RunnerCapabilitySnapshot` — 등록 시 runner capability와 command catalog 요약 제공 계약 +- `RegistrationResult` — OTO Server/iop response의 accepted/rejected 결과 변환 +- `EdgeEndpoint` / `EdgeRegistrationClient` / `_OtoIopClient` — legacy iop Edge compatibility 경로. 기본 runner 경로에서는 `OtoServerRegistrationClient`를 사용 +- `apps/runner/lib/oto/agent/oto/*.pb*.dart` — `proto/oto/runner.proto` generated Dart protobuf 코드 +- `apps/runner/lib/oto/agent/iop/*.pb*.dart` — legacy `iop/runtime.proto` generated protobuf 코드 - `oto_agent_bootstrap.sh` — agent config 파일 생성, 권한 설정, background 실행 bootstrap ## 유지할 패턴 - `CommandAgent`는 subcommand/argument 파싱과 출력만 담당하고, config 파싱은 `AgentConfig`, 등록 실행은 `AgentRunner`에 위임한다. - `--config `와 `--config=` 형식을 모두 유지하고, 누락/알 수 없는 인자는 실행 전에 오류 처리한다. -- `AgentConfig`는 YAML root와 `agent`, `edge`, `runtime` section이 map인지 확인한 뒤 required string을 검증한다. +- `AgentConfig`는 YAML root와 `agent`, `server`(또는 legacy `edge`), `runtime` section이 map인지 확인한 뒤 required string을 검증한다. - agent config의 required field는 빈 문자열을 거부하고, optional `agent.alias`는 누락 시 `null`, 빈 문자열이면 빈 문자열로 보존한다. -- `EdgeEndpoint.parse()`는 scheme 없는 host도 허용하고, port가 없으면 https는 443, 그 외는 80을 기본값으로 둔다. -- Edge 등록 통신은 `EdgeRegistrationClient.register()`에서 열고 `finally`에서 client를 닫는다. -- RegisterResponse 변환은 `RegistrationResult.fromResponse()`에 모아 accepted/rejected와 runtime config 추출을 한 곳에서 처리한다. +- OTO Server URL은 scheme 없는 host도 허용하고, HTTP endpoint 생성 시 기본 `http://`로 해석한다. +- OTO Server 등록 세션은 `openSession()`에서 열고 세션 소유자가 `finally`에서 `AgentSession.close()`를 호출해 heartbeat timer와 HTTP client를 정리한다. +- 기본 agent loop는 job claim 실패를 "대기할 작업 없음"으로 보고 polling을 계속하고, claim된 `RunRequest`는 `RemoteRunExecutor.runOnce()`로 실행한다. +- remote YAML path는 `workspaceRoot` 아래로 confinement를 강제하고, inline YAML이 있으면 path보다 우선한다. +- remote variables는 YAML `property` map 위에 overlay하되, 기존 `property`가 map이 아니면 원본 YAML을 유지해 `Application.build()` 검증이 실패하게 한다. +- `property.artifacts` 선언은 `name`/`path` map list만 허용하고, artifact path도 workspace confinement를 통과해야 한다. +- RegisterResponse/JSON 변환은 `RegistrationResult`에 모아 accepted/rejected와 runner id/alias 추출을 한 곳에서 처리한다. - generated protobuf 파일은 직접 수정하지 않고 원본 proto와 생성 절차를 확인해 재생성한다. +- bootstrap 스크립트는 `--server-url`을 기본 인자로 사용하고 legacy `--edge-url`도 server URL로 받는다. - bootstrap 스크립트는 `--release-base-url`에 https만 허용하고, 생성한 config 파일은 `chmod 600`을 유지한다. -- agent 변경 후 `dart analyze`와 agent 관련 테스트(`apps/runner/test/oto_agent_*`, 필요 시 `apps/runner/test/oto_iop_connection_smoke_test.dart`)를 확인한다. +- legacy iop Edge 경로는 `edge_registration_client.dart` 안에 격리하고, 기본 production runner 경로에서 직접 import하지 않는다. +- agent 변경 후 `dart analyze`와 agent 관련 테스트(`apps/runner/test/oto_agent_*`, `apps/runner/test/oto_server_connection_smoke_test.dart`, 필요 시 `apps/runner/test/oto_iop_connection_smoke_test.dart`)를 확인한다. ## 다른 도메인과의 경계 -- **cli**: `apps/runner/bin/main.dart` 등록과 일반 출력/스타일은 cli 도메인이다. `CommandAgent` 내부의 agent subcommand 정책부터는 agent 도메인이다. -- **core/pipeline/command**: agent 등록은 pipeline build 실행과 별개다. agent 도메인에서 `Application.build()`, `Pipeline.pipelineInitialize()`, `Command.byType()`을 직접 호출하지 않는다. +- **cli**: `apps/runner/bin/main.dart` 등록, 일반 출력/스타일, `CliRunnerOutputPort` adapter는 cli 도메인이다. `CommandAgent` 내부의 agent subcommand 정책부터는 agent 도메인이다. +- **core/pipeline/command**: agent 등록은 pipeline build 실행과 별개다. remote job 실행은 `Application.build()` 진입점까지만 호출하고, `Pipeline.pipelineInitialize()`나 `Command.byType()`을 직접 호출하지 않는다. +- **core**: remote run 실행 결과를 담는 `BuildResult`, `StepEvent`, `BuildArtifact`, `RunnerOutputPort`는 core 도메인이다. agent 도메인은 이를 서버 보고 payload로 변환해 전송한다. +- **command**: runner capability의 command catalog 계산은 command 도메인의 `CommandCatalogRunnerCapabilityProvider`가 담당한다. agent 도메인은 provider interface만 소비한다. - **scheduler**: scheduler는 YAML 파이프라인을 cron/interval로 실행한다. agent bootstrap의 background 실행과 scheduler 등록/로그 정책을 섞지 않는다. -- **framework**: `proto_socket`, `protobuf`, `fixnum` dependency 선언은 framework 도메인에서 관리하고, Edge protocol 사용 방식은 agent 도메인에서 관리한다. +- **framework**: `http`, `proto_socket`, `protobuf`, `fixnum` dependency 선언과 `proto/oto/runner.proto` 생성 절차는 framework 도메인에서 관리하고, OTO Server/iop protocol 사용 방식은 agent 도메인에서 관리한다. - **sample**: agent config YAML은 pipeline sample YAML이 아니다. `apps/runner/assets/yaml/sample/**`에 agent bootstrap config를 섞지 않는다. ## 금지 사항 -- agent 도메인에서 pipeline workflow나 command catalog를 직접 실행/해석하지 않는다. -- enrollment token, generated config, Edge 응답 중 민감 정보가 로그에 노출되도록 하지 않는다. +- agent 도메인에서 pipeline workflow나 command catalog를 직접 해석하지 않는다. remote job 실행은 `Application.build()` 진입점까지만 호출한다. +- enrollment token, generated config, server/Edge 응답 중 민감 정보가 로그에 노출되도록 하지 않는다. - generated protobuf 파일을 수동 편집하지 않는다. +- remote run의 YAML path나 artifact path가 `workspaceRoot` 밖으로 빠져나가도록 허용하지 않는다. - bootstrap 스크립트에서 사용자가 지정한 config/log/workspace 경로 외 임의의 프로젝트 파일을 수정하지 않는다. - agent background 실행 정책을 scheduler 등록/해제 로직에 섞지 않는다. diff --git a/agent-ops/rules/project/domain/cli/rules.md b/agent-ops/rules/project/domain/cli/rules.md index ca926a6..27714fe 100644 --- a/agent-ops/rules/project/domain/cli/rules.md +++ b/agent-ops/rules/project/domain/cli/rules.md @@ -1,7 +1,7 @@ --- domain: cli -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # cli @@ -17,6 +17,7 @@ last_rule_updated_at: 2026-06-01 - `apps/runner/lib/cli/cli.dart` — CLI 루트 객체, 출력/스타일 처리 - `apps/runner/lib/cli/printer.dart` — OS별 콘솔 출력과 ANSI 스타일 처리 - `apps/runner/lib/cli/cli_style.dart` — 콘솔 색상/스타일 enum +- `apps/runner/lib/cli/runner_output_adapter.dart` — core `RunnerOutputPort`를 CLI 출력으로 연결하는 adapter - `apps/runner/lib/cli/commands/command_base.dart` — CLI 커맨드 공통 베이스 - `apps/runner/lib/cli/commands/command_manager.dart` — CLI 커맨드 라우팅 - `apps/runner/lib/cli/commands/command_const.dart` — OS별 설치 경로 상수 @@ -35,10 +36,11 @@ last_rule_updated_at: 2026-06-01 ## 제외 경로 - `apps/runner/lib/oto/` — 비즈니스 로직·파이프라인 엔진 (cli는 진입만 담당) -- `apps/runner/lib/cli/commands/command_agent.dart` — OTO Edge agent 실행 명령 (`agent` 도메인) +- `apps/runner/lib/cli/commands/command_agent.dart` — OTO Server runner agent 실행 명령 (`agent` 도메인) - `apps/runner/lib/cli/commands/command_scheduler.dart` — scheduler 명령 파싱과 등록/실행 진입점 (`scheduler` 도메인) - `apps/runner/lib/cli/commands/scheduler/` — 스케줄러 실행/등록/OS별 백그라운드 처리 (`scheduler` 도메인) -- `apps/runner/lib/oto/agent/` — agent 설정/등록/Edge 통신 (`agent` 도메인) +- `apps/runner/lib/oto/agent/` — agent 설정, OTO Server 등록/job 통신, legacy iop Edge compatibility (`agent` 도메인) +- `apps/runner/lib/oto/core/output_port.dart` — runner 출력 포트 추상화 (`core` 도메인) - `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` — agent 설치/실행 bootstrap (`agent` 도메인) - `apps/runner/assets/template/` — 커맨드 실행 중 사용하는 템플릿 (`command` 도메인) @@ -57,6 +59,7 @@ last_rule_updated_at: 2026-06-01 - `CommandTemplate` — 템플릿 출력 - `CommandManager` — CLI 커맨드 등록 관리 - `RegistPath` — OS별 PATH 등록/해제 +- `CliRunnerOutputPort` / `setCliOutputLogHandler()` — `Application.build()` 출력 포트를 CLI 출력과 log handler에 연결 - `apps/runner/bin/main.dart` — CLI 초기화 시 등록할 top-level 명령 목록을 정의 ## 유지할 패턴 @@ -67,6 +70,7 @@ last_rule_updated_at: 2026-06-01 - `CommandExe`는 `BuildType` 선택과 YAML 파일 읽기까지만 담당 - `catalog`/`validate`처럼 JSON 출력을 지원하는 CLI는 stdout에 구조화 결과만 쓰고 일반 실행 로그는 억제한다 - 콘솔 출력은 `CLI.print*`, `CLI.style`, `Printer`, 또는 `CommandBase` 출력 헬퍼를 사용 +- `Application.build()`에 CLI 출력을 연결할 때는 `RunnerOutputPort`를 직접 구현하지 말고 `CliRunnerOutputPort` adapter를 우선 사용한다. - CLI 변경 후 `dart analyze`를 실행하고, CLI 진입 변경이면 최소 `dart run apps/runner/bin/main.dart` 수준의 스모크 실행 가능 여부를 확인 - 배포/설치 asset 변경 시 관련 CLI 설치/패키징 경로가 실제 파일명을 참조하는지 확인 @@ -74,7 +78,8 @@ last_rule_updated_at: 2026-06-01 - **pipeline/command**: cli는 `Application.build()`만 호출. 파이프라인·커맨드 내부를 직접 참조하지 않는다 - **core**: DataComposer 호출은 Application 내부에서 이루어지며 cli는 관여하지 않는다 -- **agent**: `agent` 명령과 `CommandAgent`는 agent 도메인이다. 일반 CLI 변경에서 Edge 등록/agent config 정책을 함께 수정하지 않는다 +- **core output**: `RunnerOutputPort` 계약은 core 도메인이고, CLI 색상/출력으로 변환하는 adapter만 cli 도메인이다 +- **agent**: `agent` 명령과 `CommandAgent`는 agent 도메인이다. 일반 CLI 변경에서 OTO Server 등록/agent config 정책을 함께 수정하지 않는다 - **scheduler**: `CommandScheduler`, `apps/runner/lib/cli/commands/command_scheduler.dart`, `apps/runner/lib/cli/commands/scheduler/**`는 scheduler 도메인이다. 일반 CLI 변경에서 scheduler 내부 동작을 함께 수정하지 않는다 - **framework**: `apps/runner/bin/main.dart`는 외부 framework Application을 소비하지만 framework 의존성 자체는 framework 도메인에서 다룬다 @@ -82,5 +87,6 @@ last_rule_updated_at: 2026-06-01 - cli 레이어에서 Pipeline 또는 Command를 직접 인스턴스화하지 않는다 - 비즈니스 로직을 cli 커맨드 핸들러에 넣지 않는다 -- 일반 CLI 변경에 agent 등록, Edge 연결, bootstrap 스크립트 정책을 섞지 않는다 +- core `RunnerOutputPort` 계약 자체를 cli 도메인에서 변경하지 않는다 +- 일반 CLI 변경에 agent 등록, OTO Server/legacy Edge 연결, bootstrap 스크립트 정책을 섞지 않는다 - 일반 CLI 변경에 scheduler 명령, 등록 파일, 로그 파일, OS 시작 프로그램 로직을 섞지 않는다 diff --git a/agent-ops/rules/project/domain/command/rules.md b/agent-ops/rules/project/domain/command/rules.md index a77315e..9e31e92 100644 --- a/agent-ops/rules/project/domain/command/rules.md +++ b/agent-ops/rules/project/domain/command/rules.md @@ -1,7 +1,7 @@ --- domain: command -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # command @@ -31,6 +31,7 @@ last_rule_updated_at: 2026-06-01 - `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`) — 모든 커맨드에 전달되는 통합 컨테이너 @@ -50,6 +51,9 @@ last_rule_updated_at: 2026-06-01 | 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 | 사용처 | @@ -63,6 +67,7 @@ last_rule_updated_at: 2026-06-01 - `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*` 모델로 파싱한다 @@ -78,6 +83,7 @@ last_rule_updated_at: 2026-06-01 - **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 의존성 쪽으로 옮기지 않는다 ## 금지 사항 diff --git a/agent-ops/rules/project/domain/core/rules.md b/agent-ops/rules/project/domain/core/rules.md index f67f7f2..fa7e3d9 100644 --- a/agent-ops/rules/project/domain/core/rules.md +++ b/agent-ops/rules/project/domain/core/rules.md @@ -1,15 +1,15 @@ --- domain: core -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # core ## 목적 / 책임 -파이프라인 실행 전 단계에서 YAML 파싱, Jenkins 환경 변수 합성, 태그 치환, 실행 컨텍스트 생성을 담당하는 공통 인프라 레이어다. `Application` 싱글턴이 전체 빌드 흐름을 오케스트레이션한다. -런타임 property, command state, build data 생성처럼 pipeline/command가 공유하는 실행 컨텍스트도 이 도메인에서 시작된다. +파이프라인 실행 전 단계에서 YAML 파싱, Jenkins 환경 변수 합성, 태그 치환, 실행 컨텍스트 생성, 빌드 결과/step event/artifact 결과 모델을 담당하는 공통 인프라 레이어다. `Application` 싱글턴이 전체 빌드 흐름을 오케스트레이션한다. +런타임 property, command state, build data, output port처럼 pipeline/command/agent가 공유하는 실행 컨텍스트도 이 도메인에서 시작된다. ## 포함 경로 @@ -23,7 +23,7 @@ last_rule_updated_at: 2026-06-01 - `apps/runner/lib/oto/pipeline/` — 실행 흐름 (core 처리 이후) - `apps/runner/lib/oto/commands/` — 커맨드 구현체 (core 결과물을 소비) -- `apps/runner/lib/oto/agent/` — OTO Edge agent 설정/등록/통신 (`agent` 도메인) +- `apps/runner/lib/oto/agent/` — OTO Server runner agent 설정/등록/remote job 통신 (`agent` 도메인) - `apps/runner/assets/script/`의 빌드/패키징 보조 스크립트 — CLI/배포 보조 asset이며 core가 직접 해석하지 않는다 ## 주요 구성 요소 @@ -33,6 +33,9 @@ last_rule_updated_at: 2026-06-01 - `DefinedData` (`defined_data.dart`) — 내장 YAML 템플릿 (빌트인 정의) - `ExecutionContext` (`execution_context.dart`) — commonData, property, command state, command map 런타임 컨테이너 - `BuildResult` (`build_result.dart`) — CLI 진입점에 전달되는 빌드 성공/실패 결과 +- `BuildArtifact` (`build_result.dart`) — remote consumer에 보고할 artifact 선언 metadata +- `RunnerOutputPort` / `RunnerOutputStyle` / `NoopRunnerOutputPort` (`output_port.dart`) — CLI/agent가 교체할 수 있는 runner 출력 포트 계약 +- `StepEvent` (`execution_context.dart`) — pipeline step started/completed/failed event 직렬화 모델 - `YamlValidationResult` (`application.dart`) — YAML 검증 CLI가 사용하는 구조화 검증 결과 - `SystemRuntime` / `DefaultSystemRuntime` (`system_runtime.dart`) — OS 환경·프로세스 실행 추상화 - `MattermostSender` / `MattermostData` (`utils/mattermost/`) — 공통 알림 헬퍼 @@ -46,6 +49,9 @@ last_rule_updated_at: 2026-06-01 - 커맨드 등록은 `registerAllCommands()` 호출 이후 command catalog validation과 pipeline validate를 수행 - 실행 없는 YAML 검증은 `Application.validateYamlContent()`에서 build map, command list, command map, pipeline 초기화 순서로 확인한다 - property 기본값에 `workspace`가 없으면 `Application.current`를 채우는 흐름을 유지 +- `Application.build()` 시작 시 `ExecutionContext.output`, step event, command map, command state를 새 실행 단위에 맞게 초기화한다 +- `BuildResult`는 `ExecutionContext.stepEvents`와 전달받은 artifact 선언을 복사해서 반환한다 +- 출력은 직접 `print`를 추가하기보다 `RunnerOutputPort` 또는 기존 `Application.log()` 경로를 사용한다 - 테스트 가능한 OS/프로세스 의존 로직은 `SystemRuntime`을 통해 주입 가능한 구조를 유지 - Jenkins env helper script 변경 시 `DataComposer`의 호출 경로와 환경 변수 파싱 결과를 함께 확인한다 - core 변경 후 `dart analyze`를 실행하고, 태그/파싱 변경이면 관련 단위 테스트 또는 최소 샘플 YAML 파싱 검증을 추가/확인한다 @@ -53,15 +59,17 @@ last_rule_updated_at: 2026-06-01 ## 다른 도메인과의 경계 - **pipeline**: DataComposer가 DataCommand 리스트 생성을 완료한 후 Pipeline이 실행 시작 +- **pipeline events**: pipeline은 step event를 기록하지만 event 모델과 저장 위치는 core `ExecutionContext`다 - **command**: 커맨드 실행 중 쓰기 태그(`<@...>`) 처리는 TagSystem에 위임 - **cli/scheduler**: build type, YAML content, scheduler build data는 cli/scheduler에서 넘기지만 실제 build 흐름과 `BuildResult` 생성은 Application이 담당 -- **agent**: agent config 파싱과 Edge 등록은 core가 아니라 agent 도메인이다. core의 YAML 파싱/검증 흐름과 agent bootstrap config를 섞지 않는다 +- **cli output**: CLI 색상/출력 adapter는 cli 도메인이고, output port interface는 core 도메인이다 +- **agent**: agent config 파싱, OTO Server 등록, remote job claim/report는 core가 아니라 agent 도메인이다. core의 YAML 파싱/검증 흐름과 agent bootstrap config를 섞지 않는다 - **sample**: 태그 문법이나 YAML 구조가 변경되면 sample 도메인의 YAML 예시를 함께 점검 ## 금지 사항 - core에서 외부 시스템(Git, Jenkins API 등)을 직접 호출하지 않는다 -- core에서 OTO Edge agent 등록 또는 proto socket 통신을 수행하지 않는다 +- core에서 OTO Server/iop Edge agent 등록, HTTP job polling, proto socket 통신을 수행하지 않는다 - 커맨드별 파싱 로직을 DataComposer에 넣지 않는다 - pipeline 흐름 제어(if/foreach/switch 등)를 core에 넣지 않는다 - command별 실행 결과 처리 로직을 `Application`에 추가하지 않는다 diff --git a/agent-ops/rules/project/domain/framework/rules.md b/agent-ops/rules/project/domain/framework/rules.md index a639d8f..8eac236 100644 --- a/agent-ops/rules/project/domain/framework/rules.md +++ b/agent-ops/rules/project/domain/framework/rules.md @@ -1,7 +1,7 @@ --- domain: framework -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # framework @@ -9,17 +9,23 @@ last_rule_updated_at: 2026-06-01 ## 목적 / 책임 현재 프로젝트에는 `lib/framework/` 모듈이 없다. -이 도메인은 runner, client, console, core service의 패키지 선언(manifest), 분석기(analyzer/lint), protobuf 계약 정의 및 생성 코드 관리, 외부 의존성 경계와 빌드 도구 설정을 기록한다. +이 도메인은 runner, client, console, core service의 패키지 선언(manifest), lockfile, 분석기(analyzer/lint), protobuf 계약 정의 및 생성 코드 관리, 외부 의존성 경계와 빌드 도구 설정을 기록한다. 단, 전용 도메인 규칙(dedicated domain rule)이 아직 존재하지 않는 `apps/client/lib/**`, `packages/flutter/oto_console/lib/**`, `services/core/internal/**` 등의 구현 코드가 가진 구체적인 비즈니스 동작 규칙은 이 framework 도메인이나 기존 runner 도메인 규칙으로 무리하게 확장하여 단정하지 않고, 추후 별도 도메인 규칙 생성 또는 후속 milestone 작업을 통해 정리한다. ## 포함 경로 +- `Makefile` — runner/client/core 검증 명령, proto 생성 명령, 로컬 실행 포트 기본값 - `apps/runner/pubspec.yaml` — runner Dart dependency와 `dart_framework` Git 의존성 선언 +- `apps/runner/pubspec.lock` — runner dependency resolution snapshot - `apps/runner/analysis_options.yaml` — runner Dart analyzer/lint 기준 - `apps/client/pubspec.yaml` — Flutter client dependency 선언 +- `apps/client/pubspec.lock` — Flutter client dependency resolution snapshot - `apps/client/analysis_options.yaml` — Flutter client analyzer/lint 기준 - `packages/flutter/oto_console/pubspec.yaml` — embeddable console package dependency 선언 +- `packages/flutter/oto_console/analysis_options.yaml` — console package analyzer/lint 기준 - `services/core/go.mod` — Go core service dependency 선언 +- `services/core/go.sum` — Go core service dependency checksum +- `services/core/oto/` — `proto/oto/runner.proto`에서 생성된 Go protobuf 코드 - `proto/` — runner/server protobuf 계약 정의 ## 제외 경로 @@ -35,17 +41,22 @@ last_rule_updated_at: 2026-06-01 - `dart_framework/platform/isolate_manager.dart` — CLI 실행/스케줄러 isolate 처리에서 사용 - `dart_framework/utils/*` — `simpleFuture`, path/system/string/os startup 유틸 사용 - `dart_framework/log/log.dart` — `Application.logWithType()`의 로그 타입에 사용 -- `proto_socket` — agent Edge 등록 통신에서 사용하는 workspace 상위 path dependency +- `proto_socket` — legacy iop Edge compatibility 경로에서 사용하는 workspace 상위 path dependency - `protobuf` / `fixnum` — generated protobuf 코드 런타임 의존성 - `resource_importer` — `apps/runner/lib/resources.resource_importer.dart` 생성 파일과 asset 임베딩 설정 +- `proto/oto/runner.proto` — OTO Server runner 등록, heartbeat, bootstrap, job claim, execution/log/artifact report, cancel/status/self-update 계약 +- `services/core/oto/runner.pb.go` — `make proto-go` 생성물 +- `apps/runner/lib/oto/agent/oto/*.pb*.dart` — `make proto-dart` 생성물 ## 유지할 패턴 - 프로세스 실행은 `ProcessExecutor.start()` (스트리밍, stdout/stderr 실시간 수신) 또는 `ProcessExecutor.run()` (블로킹, 결과만 필요) 중 목적에 맞게 선택 - `dart_framework` API 사용 시 기존 import 패턴을 따른다 - 외부 의존성 ref 변경은 각 `pubspec.yaml` 또는 `go.mod`에서 수행하고, 변경 후 패키지 갱신 및 `dart analyze` 또는 빌드 확인을 한다 +- tracked lockfile이 있는 package의 dependency 변경은 대응하는 `pubspec.lock` 또는 `go.sum` 갱신 여부를 확인한다 - analyzer/lint 기준 변경은 기존 코드 전체에 영향을 줄 수 있으므로 `dart analyze` 결과와 필요한 수정 범위를 함께 확인한다 - generated protobuf lint 예외는 `analysis_options.yaml`의 analyzer exclude 또는 파일 생성 주석으로 관리한다 +- protobuf 계약 변경 후 `make proto-go`와 `make proto-dart`를 실행해 Go/Dart 생성물을 함께 갱신한다 - 로컬에 `lib/framework/`를 되살리는 대신 필요한 OTO 로직은 `apps/runner/lib/oto/` 또는 `apps/runner/lib/cli/`의 해당 도메인에 둔다 ## 다른 도메인과의 경계 @@ -53,7 +64,8 @@ last_rule_updated_at: 2026-06-01 - **core**: `apps/runner/lib/oto/application.dart`는 OTO 오케스트레이터이며 외부 framework의 Application과 별개다 - **cli/scheduler**: isolate, process, OS startup 유틸을 소비하지만 스케줄러 정책은 scheduler 도메인에 둔다 - **command**: 커맨드들은 `ProcessExecutor`를 소비하지만 커맨드별 비즈니스 로직은 command 도메인에 둔다 -- **agent**: `proto_socket`, `protobuf`, `fixnum` 의존성은 framework 도메인에서 관리하지만 Edge 등록 프로토콜과 agent 정책은 agent 도메인에 둔다 +- **agent**: `http`, `proto_socket`, `protobuf`, `fixnum` 의존성은 framework 도메인에서 관리하지만 OTO Server/legacy iop protocol 사용 방식과 agent 정책은 agent 도메인에 둔다 +- **services/core/internal**: Go core service business logic은 아직 dedicated domain rule이 없다. framework 도메인은 `go.mod`, `go.sum`, generated proto, build/test command 경계만 다룬다 ## 금지 사항 @@ -61,3 +73,4 @@ last_rule_updated_at: 2026-06-01 - 외부 `dart_framework` 내부 코드를 이 저장소의 도메인 rule 기준으로 직접 수정한다고 가정하지 않는다 - OTO 비즈니스 로직(파이프라인, 커맨드 등록 등)을 framework 의존성 변경으로 해결하려 하지 않는다 - generated dependency/runtime 코드를 수동 수정으로 문제 해결하려 하지 않는다 +- dedicated domain rule이 없는 `apps/client/lib/**`, `packages/flutter/oto_console/lib/**`, `services/core/internal/**`의 비즈니스 동작을 framework 규칙으로 단정하지 않는다 diff --git a/agent-ops/rules/project/domain/pipeline/rules.md b/agent-ops/rules/project/domain/pipeline/rules.md index d4fef6f..ca793be 100644 --- a/agent-ops/rules/project/domain/pipeline/rules.md +++ b/agent-ops/rules/project/domain/pipeline/rules.md @@ -1,7 +1,7 @@ --- domain: pipeline -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # pipeline @@ -35,6 +35,7 @@ YAML에서 파싱된 `DataCommand` 리스트를 순차 실행하고, 조건 분 - `PipelineContain` — 중첩 파이프라인 - `PipelineWaitUntil` / `PipelineWaitUntilSeconds` — 조건 기반 또는 초 단위 대기 흐름 - `DataPipeline`, `DataIf`, `DataForeach`, `DataWhile`, `DataSwitch`, `DataExeHandle` — pipeline YAML 구조 검증/파싱 모델 +- `StepEvent` 기록 — `Pipeline.execute()`가 각 workflow task의 started/completed/failed event를 core `ExecutionContext`에 기록 ## 유지할 패턴 @@ -43,6 +44,7 @@ YAML에서 파싱된 `DataCommand` 리스트를 순차 실행하고, 조건 분 - 새 흐름 제어 유형은 `Pipeline.exeMap`에 등록하고, 필요한 데이터 모델은 `apps/runner/lib/oto/data/pipeline_data.dart`에 둔다 - 파이프라인 validate 단계에서 workflow task key, command ID 존재 여부, 하위 task 구조를 가능한 한 먼저 확인한다 - 조건식은 `PipelineCondition`의 type caster와 `Command.replaceTagValue()` 흐름을 유지한다 +- workflow task 실행 전후 event는 core `ExecutionContext.addStepEvent()`에 기록하고, event schema 자체는 core 도메인에서 관리한다 - pipeline 변경 후 `dart analyze`를 실행하고, if/foreach/while/switch/wait-until 중 영향을 받는 샘플 YAML 파싱 또는 실행 테스트를 확인한다 ## 다른 도메인과의 경계 @@ -50,6 +52,7 @@ YAML에서 파싱된 `DataCommand` 리스트를 순차 실행하고, 조건 분 - **command**: `Pipeline`이 `Command.byType()`을 호출하는 시점이 경계. 커맨드 내부 로직은 pipeline이 모른다 - **command data**: `DataCommand`와 커맨드 파라미터 모델은 command 도메인이고, workflow 흐름 모델인 `pipeline_data.dart`만 pipeline 도메인이다 - **core**: `DataComposer`가 YAML → `DataCommand` 변환을 마친 후 pipeline이 실행 시작 +- **core events**: step event 저장소와 `BuildResult` 직렬화는 core 도메인이다. pipeline은 실행 지점에서 event를 추가만 한다 - **sample**: workflow 문법 변경 시 `apps/runner/assets/yaml/sample/02_*`~`05_*`와 README 흐름 제어 예시를 함께 점검 ## 금지 사항 @@ -58,3 +61,4 @@ YAML에서 파싱된 `DataCommand` 리스트를 순차 실행하고, 조건 분 - 커맨드별 비즈니스 로직을 pipeline에 넣지 않는다 - pipeline에서 파일 시스템, 네트워크, shell 실행을 직접 수행하지 않는다 - command param의 세부 필드를 pipeline에서 해석하지 않는다 +- step event schema나 build result JSON schema를 pipeline 도메인에서 바꾸지 않는다 diff --git a/agent-ops/rules/project/domain/sample/rules.md b/agent-ops/rules/project/domain/sample/rules.md index 3cc0b21..05bf8e2 100644 --- a/agent-ops/rules/project/domain/sample/rules.md +++ b/agent-ops/rules/project/domain/sample/rules.md @@ -1,7 +1,7 @@ --- domain: sample -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # sample @@ -35,17 +35,17 @@ AI가 파이프라인 YAML을 작성하거나 검토할 때 가장 먼저 읽는 | `03_pipeline_foreach.yaml` | foreach (List·Map 순회, 중첩) | | `04_pipeline_exe_handle.yaml` | exe-handle (on-success / on-fail) | | `05_pipeline_while_switch.yaml` | while, switch, wait-until | -| `06_git.yaml` | Git, GitCommit, GitPush, GitRev, GitCount, GitBranch | +| `06_git.yaml` | Git, GitPull, GitCheckout, GitCommit, GitPush, GitRev, GitCount, GitBranch, GitStashPush, GitStashApply, GitReset | | `07_file.yaml` | Copy, Delete, FileRead, FileWrite, Zip, FileInfo | -| `07_file_utils.yaml` | DirectoryCreate, Rename 등 파일 보조 커맨드 | +| `07_file_utils.yaml` | DirectoryCreate, Files, Rename 등 파일 보조 커맨드 | | `08_notification.yaml` | Slack, SlackBuild, Mattermost, MattermostBuild | -| `09_network.yaml` | WebRequest, WebFile, Upload(FTP), Download(FTP) | -| `10_build_ios.yaml` | BuildiOS, ArchiveiOS, ExportiOS, TestflightUpload, TestflightDistribute | -| `10_build_tools.yaml` | BuildDotNet, BuildMSBuild, CodeSign, ProductBuild 등 빌드 보조 도구 | +| `09_network.yaml` | WebRequest, WebFile, Upload(FTP), Download(FTP), GitHub, GitHubPullRequestCreate, GitHubPullRequestList, GitHubPullRequestClose | +| `10_build_ios.yaml` | BuildiOS, ArchiveiOS, ExportiOS, TestflightUpload, TestflightStatusCheck, TestflightDistribute, CodeSign, ProductBuild, Notarize | +| `10_build_tools.yaml` | XcodeprojAddFile, BuildDotNet, BuildMSBuild, PublishiOS 등 빌드 보조 도구 | | `11_build_flutter.yaml` | BuildFlutter (멀티플랫폼) | | `11_utils.yaml` | URLInfo, Delay | | `12_scheduler.yaml` | scheduler 섹션 (cron / interval) | -| `13_string_json.yaml` | StringSub, StringReplace, JsonReader, JsonReaderFile, JsonWriterFile | +| `13_string_json.yaml` | StringSub, StringReplace, StringReplacePattern, StringIndex, JsonReader, JsonReaderFile, JsonWriterFile | | `14_shell_process.yaml` | Shell, ShellFile, ProcessRun, ProcessKill, ProcessPortUse | | `15_smb_auth.yaml` | SMBAuth | | `16_docker.yaml` | Docker | @@ -93,7 +93,7 @@ AI가 파이프라인 YAML을 작성하거나 검토할 때 가장 먼저 읽는 ## 유지할 패턴 - 파일명은 `NN_카테고리.yaml` 형식 (번호 + 언더스코어 + 카테고리) -- 각 파일 상단에 `# [샘플] 제목` 주석으로 목적 명시 +- 각 파일은 YAML document marker `---`로 시작하고, 바로 아래 `# [샘플] 제목` 주석으로 목적을 명시한다 - 실제 작동 가능한 파라미터 구조를 유지한다 (추측 값 사용 금지) - 새 커맨드가 추가되면 관련 샘플 파일도 함께 갱신한다 - 샘플은 placeholder 값을 사용하고 실제 토큰·비밀번호·API 키를 넣지 않는다 diff --git a/agent-ops/rules/project/domain/scheduler/rules.md b/agent-ops/rules/project/domain/scheduler/rules.md index ed32322..6fd8a69 100644 --- a/agent-ops/rules/project/domain/scheduler/rules.md +++ b/agent-ops/rules/project/domain/scheduler/rules.md @@ -1,7 +1,7 @@ --- domain: scheduler -last_rule_review_commit: 67d7b6e411b8a28d6d42cac550a29872a7ef6b7e -last_rule_updated_at: 2026-06-01 +last_rule_review_commit: 99cc06767f82a32a9106f3a483bce2b6aeed5872 +last_rule_updated_at: 2026-06-13 --- # scheduler diff --git a/agent-ops/rules/project/rules.md b/agent-ops/rules/project/rules.md index 624e393..6622605 100644 --- a/agent-ops/rules/project/rules.md +++ b/agent-ops/rules/project/rules.md @@ -152,12 +152,18 @@ proto/ # OTO runner/server protobuf contract | `apps/runner/assets/bin/**` | cli | `agent-ops/rules/project/domain/cli/rules.md` | | `apps/runner/assets/script/shell/oto_agent_bootstrap.sh` | agent | `agent-ops/rules/project/domain/agent/rules.md` | | `apps/runner/assets/script/**` | cli | `agent-ops/rules/project/domain/cli/rules.md` | +| `Makefile` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `apps/runner/pubspec.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | +| `apps/runner/pubspec.lock` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `apps/runner/analysis_options.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `apps/client/pubspec.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | +| `apps/client/pubspec.lock` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `apps/client/analysis_options.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `packages/flutter/oto_console/pubspec.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | +| `packages/flutter/oto_console/analysis_options.yaml` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `services/core/go.mod` | framework | `agent-ops/rules/project/domain/framework/rules.md` | +| `services/core/go.sum` | framework | `agent-ops/rules/project/domain/framework/rules.md` | +| `services/core/oto/**` | framework | `agent-ops/rules/project/domain/framework/rules.md` | | `proto/**` | framework | `agent-ops/rules/project/domain/framework/rules.md` | `test/**`는 별도 도메인으로 고정하지 않는다. 테스트 변경 시 검증 대상 production 경로의 domain rule을 읽고, 여러 도메인을 검증하는 테스트면 관련 domain rule을 함께 읽는다. diff --git a/agent-roadmap/ROADMAP.md b/agent-roadmap/ROADMAP.md index e593047..90e6e52 100644 --- a/agent-roadmap/ROADMAP.md +++ b/agent-roadmap/ROADMAP.md @@ -23,6 +23,9 @@ OTO는 YAML 기반 빌드/배포 파이프라인을 실행하는 Dart CLI에서 - [완료] 메시지 기반 빌드 에이전트 - 경로: `agent-roadmap/archive/phase/message-based-build-agent/PHASE.md` - 요약: `oto agent` 또는 `oto daemon` 모드에서 OTO Server와 양방향 메시지 통신을 사용하는 build/deploy 전용 runner 경계를 정리하고 archive로 이동했다. +- [계획] Control Plane 제품 표면 완성 + - 경로: `agent-roadmap/phase/control-plane-product-surface/PHASE.md` + - 요약: 현재 분리된 Core API, Flutter client, runner bootstrap 경계를 실제 운영 가능한 UI 스켈레톤과 OS별 설치 흐름으로 연결한다. ## 로딩 정책 diff --git a/agent-roadmap/phase/control-plane-product-surface/PHASE.md b/agent-roadmap/phase/control-plane-product-surface/PHASE.md new file mode 100644 index 0000000..e8a7bbf --- /dev/null +++ b/agent-roadmap/phase/control-plane-product-surface/PHASE.md @@ -0,0 +1,30 @@ +# Phase: Control Plane 제품 표면 완성 + +## 상태 + +[계획] + +## 목표 + +현재 분리된 OTO Core API 서버, Flutter client, runner bootstrap 경계를 실제 사용자가 조작할 수 있는 Control Plane 제품 표면으로 끌어올린다. +먼저 Flutter UI 스켈레톤을 만들어 Control Plane의 주요 화면과 연결 지점을 고정하고, 이어서 OTO Core bootstrap 흐름이 Linux, macOS, Windows 대상 runner 설치를 지원하도록 확장한다. + +## Milestone 흐름 + +완료된 Milestone은 archive 경로를 가리키고, 검토중, 진행중, 계획, 스케치 또는 보류 Milestone은 이 Phase 하위 `milestones/` 경로를 가리킨다. +완료, 검토중, 진행중, 계획, 스케치 순서로 두어 아래로 갈수록 미래 작업에 가까워지게 정렬한다. +스케치 Milestone은 아직 구현 가능한 계획이 아니므로 계획 Milestone보다 아래에 둔다. + +- [계획] Flutter 콘솔 스켈레톤 + - 경로: `agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md` + - 요약: `apps/client`와 `packages/flutter/oto_console`에 Control Plane 주요 화면, 상태 표시, 빈 상태, Core 연결 기준을 갖춘 UI 스켈레톤을 만든다. +- [계획] OS별 runner bootstrap 설치 지원 + - 경로: `agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md` + - 요약: OTO Core bootstrap command와 bootstrap asset이 Linux, macOS, Windows에서 OTO runner를 내려받고 설정/실행할 수 있도록 확장한다. + +## Phase 경계 + +- 이 Phase는 기존 `services/core`, `apps/client`, `packages/flutter/oto_console`, `apps/runner` 경계를 유지하면서 제품 표면과 bootstrap 실행성을 보강한다. +- Jenkins 전체 기능, 장기 권한/감사 모델, durable artifact storage 운영 정책은 이 Phase의 기본 범위가 아니다. +- iop Edge 직접 연결 경로는 복원하지 않는다. OTO Core와 OTO runner의 독립 Control Plane 경로를 기준으로 한다. +- private release host, enrollment token, credential 원문은 tracked 문서에 남기지 않는다. diff --git a/agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md b/agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md new file mode 100644 index 0000000..e716b16 --- /dev/null +++ b/agent-roadmap/phase/control-plane-product-surface/milestones/cross-os-runner-bootstrap.md @@ -0,0 +1,68 @@ +# Milestone: OS별 runner bootstrap 설치 지원 + +## 위치 + +- Roadmap: `agent-roadmap/ROADMAP.md` +- Phase: `agent-roadmap/phase/control-plane-product-surface/PHASE.md` + +## 목표 + +OTO Core가 발급하는 bootstrap 흐름을 Linux 단일 shell script 기준에서 확장해 Linux, macOS, Windows 대상 runner 설치를 지원한다. +완료 후 대상 머신은 OTO가 미리 설치되어 있지 않아도 OS별 bootstrap command로 release asset을 내려받고, agent 설정을 만들고, `oto agent run` 실행 준비 또는 시작까지 진행할 수 있어야 한다. + +## 상태 + +[계획] + +## 승격 조건 + +- 없음 + +## 구현 잠금 + +- 상태: 해제 +- 결정 필요: 없음 + +## 범위 + +- OTO Core bootstrap command/API와 embedded bootstrap asset 제공 경로를 OS별로 확장한다. +- Linux와 macOS는 POSIX shell 기반 설치 흐름을 우선 재사용하고, Windows는 PowerShell 기반 설치 흐름을 둔다. +- release asset 이름, OS/arch 감지, 설치 경로, config 경로, log/workspace 경로를 OS별 표준선으로 정리한다. +- bootstrap script와 server handler 테스트를 OS별 케이스로 확장한다. + +## 기능 + +### Epic: [bootstrap-platforms] Cross-OS bootstrap contract + +OS별 bootstrap command와 release asset 선택 기준을 OTO Core와 runner asset이 같은 의미로 해석하도록 만든다. + +- [ ] [platform-matrix] Linux, macOS, Windows의 우선 지원 OS/arch와 release asset naming 규칙을 정리한다. 검증: 문서와 테스트 fixture가 동일한 asset 이름을 사용한다. +- [ ] [core-command] OTO Core bootstrap command 요청/응답이 대상 OS 또는 script 종류를 표현하고 올바른 bootstrap URL/command를 반환한다. 검증: `cd services/core && go test ./...`가 OS별 command 케이스를 포함해 통과한다. +- [ ] [unix-bootstrap] Linux/macOS shell bootstrap이 OS/arch를 감지해 올바른 release asset을 내려받고 config/runtime 경로를 생성한다. 검증: `cd apps/runner && dart test test/oto_agent_bootstrap_script_test.dart` 또는 대응 smoke가 통과한다. +- [ ] [windows-bootstrap] Windows PowerShell bootstrap이 release asset 다운로드, 압축 해제, config 생성, agent 실행 안내 또는 시작 흐름을 제공한다. 검증: script parsing/fixture 테스트가 Windows 경로와 quoting을 검증한다. +- [ ] [docs-smoke] README와 `agent-test/local/agent-smoke.md`가 OS별 bootstrap command, secret 기록 금지, release URL 검증 기준을 최신화한다. + +## 완료 리뷰 + +- 상태: 없음 +- 요청일: 없음 +- 완료 근거: 없음 +- 리뷰 필요: + - [ ] 사용자가 완료 결과를 확인했다 + - [ ] archive 이동을 승인했다 +- 리뷰 코멘트: 없음 + +## 범위 제외 + +- checksum/signature 검증, certificate pinning, enrollment token rotation은 기본 구현을 막지 않는 후속 보안 강화로 둔다. +- OS별 system service 설치를 완성형 daemon 관리까지 확대하지 않는다. 필요하면 user-level background 실행 또는 수동 실행 안내를 먼저 둔다. +- private release host, credential, token 원문을 tracked 문서에 기록하지 않는다. + +## 작업 컨텍스트 + +- 관련 경로: `services/core/internal/httpserver/**`, `apps/runner/assets/script/**`, `apps/runner/test/**`, `README.md`, `agent-test/local/**` +- 표준선(선택): 우선 지원 OS는 Linux, macOS, Windows로 보고, 각 OS의 x64/arm64 지원 여부는 release asset 존재와 테스트 fixture로 명시한다. +- 표준선(선택): Linux/macOS는 shell, Windows는 PowerShell을 사용하며, 공통 설정 의미는 `agent.id`, `agent.alias`, `agent.enrollment_token`, `server.url`, `runtime.install_dir`, `runtime.workspace_root`, `runtime.log_dir`를 유지한다. +- 선행 작업: `독립 Control Plane 분리 마이그레이션`의 bootstrap command, `워크스페이스 포트/환경 표준화`의 release URL 기준, 폐기된 `Edge bootstrap 계약`의 Linux 설치 근거 +- 후속 작업: release packaging 자동화, checksum/signature 검증, OS별 service manager 통합 +- 확인 필요: 없음 diff --git a/agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md b/agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md new file mode 100644 index 0000000..c52b7ce --- /dev/null +++ b/agent-roadmap/phase/control-plane-product-surface/milestones/flutter-console-skeleton.md @@ -0,0 +1,67 @@ +# Milestone: Flutter 콘솔 스켈레톤 + +## 위치 + +- Roadmap: `agent-roadmap/ROADMAP.md` +- Phase: `agent-roadmap/phase/control-plane-product-surface/PHASE.md` + +## 목표 + +현재 endpoint 표시와 placeholder 중심인 Flutter client를 Control Plane 작업 표면의 스켈레톤으로 확장한다. +완료 후 사용자는 OTO Core 연결 상태, runner, pipeline/job, execution, log/artifact, settings 영역의 기본 화면 구조와 빈 상태를 확인할 수 있고, 후속 API 연동을 넣을 위치가 명확해야 한다. + +## 상태 + +[계획] + +## 승격 조건 + +- 없음 + +## 구현 잠금 + +- 상태: 해제 +- 결정 필요: 없음 + +## 범위 + +- `apps/client` host app과 `packages/flutter/oto_console` 패키지의 현재 shell/contract 경계를 유지한다. +- Overview, Runners, Pipelines/Jobs, Executions, Artifacts, Settings 화면의 스켈레톤과 상태 표현을 만든다. +- OTO Core HTTP URL 설정값을 기준으로 health/readiness 연결 상태를 표시할 수 있는 최소 adapter 또는 port를 둔다. +- 실제 API 데이터가 없거나 비어 있을 때의 empty/loading/error 상태를 제품 표면에 맞게 정리한다. + +## 기능 + +### Epic: [ui-skeleton] Control Plane UI skeleton + +OTO Console이 placeholder가 아니라 후속 기능을 얹을 수 있는 제품 화면 골격을 갖추도록 한다. + +- [ ] [overview-status] Overview가 `OTO_SERVER_HTTP_URL` 기준 Core health/readiness 상태를 보여줄 수 있는 구조를 갖춘다. 검증: `make client-test` 또는 `cd apps/client && flutter test`에서 상태 표시 위젯 테스트가 통과한다. +- [ ] [section-surfaces] Runners, Pipelines/Jobs, Executions, Artifacts, Settings 섹션이 각각 독립 화면 스켈레톤과 빈 상태를 가진다. 검증: `cd packages/flutter/oto_console && flutter test`에서 navigation/section 렌더링 테스트가 통과한다. +- [ ] [api-port] Flutter UI가 Core API를 직접 호출할 구현 위치를 contract/adapter로 분리하고, 브라우저 CORS 또는 same-origin proxy 필요성을 작업 컨텍스트에 드러낸다. +- [ ] [preview-flow] 원격 preview 명령 `make client-run-web OTO_SERVER_HTTP_URL=http://toki-labs.com:18020` 기준으로 첫 화면이 Core API endpoint와 UI 스켈레톤을 안정적으로 렌더링한다. 검증: 원격 runner 또는 local smoke에서 Flutter web preview 접속 확인을 남긴다. + +## 완료 리뷰 + +- 상태: 없음 +- 요청일: 없음 +- 완료 근거: 없음 +- 리뷰 필요: + - [ ] 사용자가 완료 결과를 확인했다 + - [ ] archive 이동을 승인했다 +- 리뷰 코멘트: 없음 + +## 범위 제외 + +- runner/job/execution 전체 CRUD와 고급 운영 정책을 한 번에 완성하지 않는다. +- auth, 권한, 감사 로그, durable persistence UI를 완성하지 않는다. +- production 정적 웹 배포 파이프라인은 이 Milestone의 필수 산출물이 아니다. + +## 작업 컨텍스트 + +- 관련 경로: `apps/client/**`, `packages/flutter/oto_console/**`, `services/core/internal/httpserver/**`, `agent-test/local/**` +- 표준선(선택): 현재 `OtoConsoleShell`과 `OtoConsoleConfig`를 유지하고, 화면별 구현은 `oto_console` 패키지 안에 둔다. +- 표준선(선택): 현재 Core는 CORS 헤더를 제공하지 않으므로 브라우저 직접 API 호출을 붙일 때 CORS middleware 또는 same-origin proxy 정책을 함께 판단한다. +- 선행 작업: `oto_console 계약 경계 정리`, `워크스페이스 포트/환경 표준화` +- 후속 작업: 실제 runner/job/execution API 데이터 바인딩, 인증/권한, 운영 대시보드 고도화 +- 확인 필요: 없음