diff --git a/Makefile b/Makefile index 0502cfb..2a1b141 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,23 @@ -.PHONY: all setup test runner-get runner-analyze runner-test client-get client-analyze client-test core-test proto proto-go proto-dart +.PHONY: all setup test runner-get runner-analyze runner-test runner-test-legacy-iop client-get client-analyze client-test core-test proto proto-go proto-dart PROTOC_GEN_DART := $(shell command -v protoc-gen-dart 2>/dev/null) +RUNNER_REQUIRED_TESTS := \ + test/oto_agent_bootstrap_script_test.dart \ + test/oto_agent_cli_test.dart \ + test/oto_agent_config_test.dart \ + test/oto_agent_migration_plan_test.dart \ + test/oto_agent_registration_test.dart \ + test/oto_application_test.dart \ + test/oto_catalog_cli_test.dart \ + test/oto_cli_runtime_test.dart \ + test/oto_command_catalog_test.dart \ + test/oto_command_runtime_test.dart \ + test/oto_context_test.dart \ + test/oto_core_test.dart \ + test/oto_scheduler_runtime_test.dart \ + test/oto_server_connection_smoke_test.dart \ + test/oto_system_runtime_test.dart \ + test/oto_validate_cli_test.dart all: setup test @@ -13,7 +30,10 @@ runner-analyze: cd apps/runner && dart analyze runner-test: - cd apps/runner && dart test + cd apps/runner && dart test $(RUNNER_REQUIRED_TESTS) + +runner-test-legacy-iop: + cd apps/runner && OTO_ENABLE_LEGACY_IOP_SMOKE=1 dart test test/oto_iop_connection_smoke_test.dart client-get: cd apps/client && flutter pub get @@ -41,4 +61,3 @@ endif protoc -I proto --dart_out=apps/runner/lib/oto/agent proto/oto/runner.proto test: runner-test client-test core-test - diff --git a/agent-roadmap/phase/message-based-build-agent/PHASE.md b/agent-roadmap/phase/message-based-build-agent/PHASE.md index 17c80a3..1b408a8 100644 --- a/agent-roadmap/phase/message-based-build-agent/PHASE.md +++ b/agent-roadmap/phase/message-based-build-agent/PHASE.md @@ -23,7 +23,7 @@ OTO를 generic remote shell이 아니라 build/deploy 전용 runner로 노출하 - [계획] agent 등록 capability 경계 정리 - 경로: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` - 요약: agent 등록 경로가 command catalog를 직접 해석하지 않도록 capability provider port와 command adapter로 분리한다. -- [계획] runner 검증 기준 정합화 +- [검토중] runner 검증 기준 정합화 - 경로: `agent-roadmap/phase/message-based-build-agent/milestones/runner-verification-baseline.md` - 요약: 현재 OTO Server/Runner 경로 기준으로 runner test, root analyzer, smoke 문서의 기본 검증 범위를 일치시킨다. diff --git a/agent-roadmap/phase/message-based-build-agent/milestones/runner-verification-baseline.md b/agent-roadmap/phase/message-based-build-agent/milestones/runner-verification-baseline.md index b69741c..4f9b597 100644 --- a/agent-roadmap/phase/message-based-build-agent/milestones/runner-verification-baseline.md +++ b/agent-roadmap/phase/message-based-build-agent/milestones/runner-verification-baseline.md @@ -2,7 +2,7 @@ ## 상태 -[계획] +[검토중] ## 목표 @@ -27,15 +27,27 @@ ## 작업 컨텍스트 -- `agent-test/local/agent-smoke.md`는 legacy iop smoke를 필수 agent smoke에서 제외하지만, `Makefile`의 `runner-test`는 전체 `dart test`를 실행한다. -- `apps/runner/test/oto_iop_connection_smoke_test.dart`는 현재 iop Edge가 허용하지 않는 `agent_kind: "oto-agent"`를 사용해 기본 test suite를 실패시킨다. +- `agent-test/local/agent-smoke.md`는 legacy iop smoke를 필수 agent smoke에서 제외한다. +- `Makefile`의 `runner-test`는 현재 필수 runner 회귀 테스트만 실행하고, legacy iop Edge 직접 연결 smoke는 `runner-test-legacy-iop`로 분리했다. - root 임시 Dart 파일 `test_regist.dart`, `check_datapath2.dart`를 제거했고, `dart analyze .`가 통과한다. ## 기능 ### Epic: [baseline] verification baseline -- [ ] [test-scope] `Makefile`의 runner/root 테스트 target과 `agent-test/local` smoke 문서의 필수 검증 범위를 일치시킨다. -- [ ] [legacy-iop] iop Edge 직접 연결 smoke를 기본 runner test에서 제외하거나 legacy 전용 명령으로 명시한다. 검증: `make runner-test`가 현재 필수 검증 기준으로 통과한다. +- [x] [test-scope] `Makefile`의 runner/root 테스트 target과 `agent-test/local` smoke 문서의 필수 검증 범위를 일치시킨다. +- [x] [legacy-iop] iop Edge 직접 연결 smoke를 기본 runner test에서 제외하거나 legacy 전용 명령으로 명시한다. 검증: `make runner-test`가 현재 필수 검증 기준으로 통과한다. - [x] [root-analyze] root analyzer를 깨뜨리는 임시 Dart 파일을 제거, 이동 또는 분석 제외 범위로 정리한다. 검증: root 분석 명령이 실패하지 않는다. -- [ ] [smoke-evidence] 필수 agent smoke 명령과 제외된 legacy smoke의 상태가 문서와 명령 양쪽에서 같은 의미를 갖도록 확인한다. +- [x] [smoke-evidence] 필수 agent smoke 명령과 제외된 legacy smoke의 상태가 문서와 명령 양쪽에서 같은 의미를 갖도록 확인한다. + +## 완료 리뷰 + +- 상태: 요청됨 +- 요청일: 2026-06-10 +- 완료 근거: + - `Makefile`에서 현재 필수 runner 회귀를 `runner-test`로 고정하고 legacy iop smoke를 `runner-test-legacy-iop`로 분리했다. + - `agent-test/local/agent-smoke.md`가 필수 smoke와 legacy iop evidence 전용 명령을 같은 의미로 설명한다. + - `make runner-test`, `make runner-analyze`가 통과했다. +- 리뷰 필요: + - [ ] 사용자가 현재 검증 기준 정합화 Milestone 완료를 승인한다. +- 리뷰 코멘트: 외부 iop Edge 직접 연결 기능은 복원하지 않고, legacy evidence 전용 수동 검증으로만 남겼다. diff --git a/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/code_review_local_G05_0.log b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/code_review_local_G05_0.log new file mode 100644 index 0000000..fb1dfee --- /dev/null +++ b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/code_review_local_G05_0.log @@ -0,0 +1,126 @@ + + +# Code Review Reference - REFACTOR + +> **[IMPLEMENTING AGENT — READ FIRST] Filling in this file is the mandatory final step of implementation.** +> The task is NOT complete until every implementation-owned section below is filled in. +> Complete the `구현 체크리스트`; the final checklist item is mandatory before saving. +> Fill implementation-owned sections, then stop with active files in place and report ready for review. +> If implementation is blocked by a user-only decision, user-owned external environment prerequisite, or scope conflict, fill `사용자 리뷰 요청` with evidence and stop with active files in place; code-review decides whether to write `USER_REVIEW.md`. +> Finalization is review-agent-only. + +## 개요 + +date=2026-06-10 +task=m-agent-registration-capability-boundary/01_agent_port, plan=0, tag=REFACTOR + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `agent-port`: agent 등록에 필요한 capability provider 계약과 기본값 주입 지점을 정의한다. +- Completion mode: check-on-pass + +## 이 파일을 읽는 리뷰 에이전트에게 + +> **[REVIEW AGENT ONLY]** 종결 절차는 코드리뷰 에이전트 전용이다. + +각 항목의 구현을 실제 소스 파일과 대조하고 검증 출력이 코드와 일치하는지 확인하세요. + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [REFACTOR-1] Agent Capability Provider Port | [x] | + +## 구현 체크리스트 + +- [x] agent 등록 capability provider port와 immutable capability model을 agent 도메인 파일에 추가한다. +- [x] `OtoServerRegistrationClient`가 `commandTypes` 직접 list 대신 provider를 받을 수 있는 주입 지점을 준비하되 기존 `commandTypes:` call site는 깨지지 않게 유지한다. +- [x] `oto_agent_registration_test.dart`에 fake provider 기반 request build test를 추가한다. +- [x] 중간/최종 검증을 실행한다. +- [x] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## 코드리뷰 전용 체크리스트 + +- [x] `코드리뷰 결과`에 `PASS`, `WARN`, `FAIL` 중 하나의 판정을 append한다. +- [x] active plan/review 파일을 `.log`로 아카이브한다. +- [x] PASS이면 `complete.log` 작성 후 task directory를 archive로 이동한다. +- [x] PASS이고 task group이 `m-agent-registration-capability-boundary`이면 런타임 완료 이벤트 메타데이터를 보고한다. + +## 계획 대비 변경 사항 + +- 계획 범위대로 `apps/runner/lib/oto/agent/runner_capability_provider.dart`를 추가했다. +- 기존 `commandTypes:` call site 호환을 유지하기 위해 `OtoServerRegistrationClient` 내부에서 static provider로 감싸도록 구현했다. +- command catalog 기반 default provider는 후속 `02` adapter 작업 전까지 `registration_client.dart` 내부에 남겼다. + +## 주요 설계 결정 + +- `RunnerCapabilityProvider.snapshot()`이 registration payload에 필요한 `name`, `version`, `commandTypes`를 한 번에 제공하도록 했다. +- `RunnerCapabilitySnapshot.commandTypes`는 `List.unmodifiable`로 고정해 request build 중 외부 mutable iterable 영향이 없게 했다. +- 명시 `capabilityProvider`가 있으면 우선 사용하고, 없으면 기존 `commandTypes:` 또는 기존 기본 command catalog 계산 경로를 provider 형태로 정규화했다. + +## 사용자 리뷰 요청 + +_기본값은 `없음`이다. 구현 중 사용자 결정, 사용자 소유 외부 환경/secret/서비스 준비, 또는 계획 범위 변경 없이는 안전하게 진행할 수 없으면 아래 항목을 실제 내용으로 교체하고, 구현을 중단한 뒤 active 파일을 그대로 둔 채 리뷰를 요청한다._ + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- agent port가 command 도메인 type을 import하지 않는지 확인 +- 기존 `commandTypes:` call site 호환이 유지되는지 확인 +- fake provider test가 request payload 의미를 검증하는지 확인 + +## 검증 결과 + +### REFACTOR-1 중간 검증 + +```text +$ cd apps/runner && dart test test/oto_agent_registration_test.dart +00:01 +36: All tests passed! +``` + +### 최종 검증 + +```text +$ cd apps/runner && dart analyze +Analyzing runner... +No issues found! + +$ cd apps/runner && dart test test/oto_agent_registration_test.dart +00:01 +36: All tests passed! + +$ cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart +00:10 +74: All tests passed! +``` + +## 코드리뷰 결과 + +- 종합 판정: PASS +- 차원별 평가: + - correctness: Pass + - completeness: Pass + - test coverage: Pass + - API contract: Pass + - code quality: Pass + - plan deviation: Pass + - verification trust: Pass +- 발견된 문제: 없음 +- 다음 단계: PASS이므로 `complete.log`를 작성하고 task directory를 archive로 이동한다. + +리뷰 메모: +- `RunnerCapabilityProvider`와 `RunnerCapabilitySnapshot`은 agent 도메인 파일에 추가되었고, provider port 자체는 command 도메인을 import하지 않는다. +- `OtoServerRegistrationClient`는 `capabilityProvider` 주입 표면을 추가하면서 기존 `commandTypes:` 호출 경로를 유지한다. +- fake provider 기반 request build test가 capability name/version과 command catalog payload를 검증한다. +- 리뷰 중 `apps/runner/test/oto_agent_registration_test.dart`에 `dart format`을 적용해 비동작성 포맷 drift를 정리했다. +- 재검증: + - `cd apps/runner && dart analyze` - PASS; `No issues found!` + - `cd apps/runner && dart test test/oto_agent_registration_test.dart` - PASS; `+36: All tests passed!` + - `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart` - PASS; `+74: All tests passed!` diff --git a/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/complete.log b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/complete.log new file mode 100644 index 0000000..394266f --- /dev/null +++ b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/complete.log @@ -0,0 +1,43 @@ +# Complete - m-agent-registration-capability-boundary/01_agent_port + +## 완료 일시 + +2026-06-10T22:55:15Z + +## 요약 + +Agent capability provider port 도입 및 registration client 주입 표면 준비를 1회 리뷰 루프로 완료했다. 최종 판정은 PASS다. + +## 루프 이력 + +| Plan | Review | Verdict | 메모 | +|------|--------|---------|------| +| `plan_local_G05_0.log` | `code_review_local_G05_0.log` | PASS | provider port, 기존 `commandTypes:` 호환, fake provider request build test가 계획 범위와 검증 기준을 충족했다. | + +## 구현/정리 내용 + +- `RunnerCapabilityProvider`와 immutable `RunnerCapabilitySnapshot`을 agent 도메인에 추가했다. +- `OtoServerRegistrationClient`가 `capabilityProvider`를 받을 수 있게 하면서 기존 `commandTypes:` 호출 경로를 유지했다. +- fake provider 기반 registration request build test를 추가했다. +- 리뷰 중 `apps/runner/test/oto_agent_registration_test.dart` 포맷 drift를 정리했다. + +## 최종 검증 + +- `cd apps/runner && dart analyze` - PASS; `No issues found!` +- `cd apps/runner && dart test test/oto_agent_registration_test.dart` - PASS; `+36: All tests passed!` +- `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart` - PASS; `+74: All tests passed!` + +## Roadmap Completion + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Completed task ids: + - `agent-port`: PASS; evidence=`plan_local_G05_0.log`, `code_review_local_G05_0.log`; verification=`cd apps/runner && dart analyze`, `cd apps/runner && dart test test/oto_agent_registration_test.dart`, `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart` +- Not completed task ids: 없음 + +## 잔여 Nit + +- 없음 + +## 후속 작업 + +- 없음 diff --git a/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/plan_local_G05_0.log b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/plan_local_G05_0.log new file mode 100644 index 0000000..def4bc0 --- /dev/null +++ b/agent-task/archive/2026/06/m-agent-registration-capability-boundary/01_agent_port/plan_local_G05_0.log @@ -0,0 +1,131 @@ + + +# Plan - REFACTOR Agent Capability Port + +## 이 파일을 읽는 구현 에이전트에게 + +`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채우는 것이 필수 마지막 단계다. 구현 후 검증을 실행하고 실제 출력, 설계 결정, 계획 대비 변경 사항을 기록한 뒤 active 파일을 그대로 두고 리뷰 준비를 보고한다. 사용자 결정, 사용자 소유 외부 환경, scope 충돌이 막으면 `사용자 리뷰 요청` 섹션에 근거를 기록하고 중단한다. 구현 중 사용자에게 직접 묻거나 `USER_REVIEW.md`, `complete.log`, archive 로그를 만들지 않는다. + +## 배경 + +`OtoServerRegistrationClient`가 기본 command type 산출을 직접 소유해 agent 도메인이 command registry/catalog를 import한다. agent 등록 경로는 capability provider 계약만 알고, 실제 command catalog 조회는 command 도메인 adapter로 분리되어야 한다. 이 subtask는 downstream adapter가 꽂힐 agent-side port와 기본 주입 표면만 만든다. + +## 사용자 리뷰 요청 흐름 + +구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 prompt는 금지이며, code-review가 검증 후 `USER_REVIEW.md` 작성 여부를 결정한다. + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `agent-port`: agent 등록에 필요한 capability provider 계약과 기본값 주입 지점을 정의한다. +- Completion mode: check-on-pass + +## 분석 결과 + +### 읽은 파일 + +- `agent-roadmap/current.md` +- `agent-roadmap/phase/message-based-build-agent/PHASE.md` +- `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- `agent-test/local/rules.md` +- `agent-test/local/agent-smoke.md` +- `agent-test/local/command-smoke.md` +- `agent-ops/rules/project/domain/agent/rules.md` +- `agent-ops/rules/project/domain/command/rules.md` +- `apps/runner/lib/oto/agent/registration_client.dart` +- `apps/runner/lib/oto/agent/agent_runner.dart` +- `apps/runner/lib/oto/agent/edge_registration_client.dart` +- `apps/runner/lib/oto/commands/command.dart` +- `apps/runner/lib/oto/commands/command_catalog.dart` +- `apps/runner/lib/oto/commands/command_registry.dart` +- `apps/runner/test/oto_agent_registration_test.dart` +- `apps/runner/test/oto_server_connection_smoke_test.dart` +- `apps/runner/test/oto_command_catalog_test.dart` + +### 테스트 환경 규칙 + +`test_env=local`. `agent-test/local/rules.md`를 읽었고 agent/command smoke profile을 적용한다. agent 변경은 `cd apps/runner && dart analyze`와 agent registration test 및 server connection smoke가 기준이다. command adapter 후속 변경은 command catalog/runtime smoke 기준을 함께 쓴다. + +### 테스트 커버리지 공백 + +- agent-side provider 계약은 신규 개념이라 현재 직접 테스트가 없다. `oto_agent_registration_test.dart`에 injectable fake provider test를 추가해야 한다. +- registration payload 의미는 기존 `builds OTO Server registration request from config`와 server smoke가 일부 커버한다. + +### 심볼 참조 + +현재 subtask에서 기존 public symbol rename/removal은 없다. 신규 `RunnerCapabilityProvider`와 capability value class를 추가한다. + +### 분할 판단 + +split 정책을 먼저 평가했다. API/foundation port, command-domain adapter, registration wiring/test가 서로 다른 dependency boundary라 multi-plan이 필요하다. shared task group은 `m-agent-registration-capability-boundary`이고 siblings는 `01_agent_port`(선행 없음), `02+01_command_adapter`(01 완료 필요), `03+01,02_registration_wiring`(01,02 완료 필요)이다. + +### 범위 결정 근거 + +이 subtask는 agent package 안의 port와 `OtoServerRegistrationClient` 생성자 주입 표면까지만 다룬다. command catalog 조회 adapter와 import 제거는 후속 `02`, production wiring과 최종 smoke는 `03`에서 처리한다. + +### 빌드 등급 + +`local-G05`: 신규 port API지만 scope가 agent 파일과 focused unit test로 작고 검증이 결정적이다. + +## 구현 체크리스트 + +- [ ] agent 등록 capability provider port와 immutable capability model을 agent 도메인 파일에 추가한다. +- [ ] `OtoServerRegistrationClient`가 `commandTypes` 직접 list 대신 provider를 받을 수 있는 주입 지점을 준비하되 기존 `commandTypes:` call site는 깨지지 않게 유지한다. +- [ ] `oto_agent_registration_test.dart`에 fake provider 기반 request build test를 추가한다. +- [ ] 중간/최종 검증을 실행한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +### [REFACTOR-1] Agent Capability Provider Port + +문제: [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:9)가 command domain을 import하고, [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:246)의 `_defaultCommandTypes()`가 command registry를 직접 실행한다. + +해결 방법: `apps/runner/lib/oto/agent/runner_capability_provider.dart`를 추가해 agent 등록 client가 소비할 port를 정의한다. + +```dart +abstract class RunnerCapabilityProvider { + RunnerCapabilitySnapshot snapshot(); +} + +class RunnerCapabilitySnapshot { + final String name; + final String version; + final List commandTypes; + const RunnerCapabilitySnapshot({ + required this.name, + required this.version, + required Iterable commandTypes, + }) : commandTypes = List.unmodifiable(commandTypes); +} +``` + +수정 파일 및 체크리스트: + +- [ ] `apps/runner/lib/oto/agent/runner_capability_provider.dart` 추가 +- [ ] `apps/runner/lib/oto/agent/registration_client.dart`가 provider type을 import +- [ ] `apps/runner/test/oto_agent_registration_test.dart` fake provider 추가 + +테스트 작성: 작성. provider snapshot이 request의 `capability`와 `commandCatalog.commandTypes`로 들어가는 단위 테스트를 추가한다. + +중간 검증: + +```bash +cd apps/runner && dart test test/oto_agent_registration_test.dart +``` + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `apps/runner/lib/oto/agent/runner_capability_provider.dart` | REFACTOR-1 | +| `apps/runner/lib/oto/agent/registration_client.dart` | REFACTOR-1 | +| `apps/runner/test/oto_agent_registration_test.dart` | REFACTOR-1 | + +## 최종 검증 + +```bash +cd apps/runner && dart analyze +cd apps/runner && dart test test/oto_agent_registration_test.dart +``` + +모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/CODE_REVIEW-local-G05.md b/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/CODE_REVIEW-local-G05.md new file mode 100644 index 0000000..c3768f3 --- /dev/null +++ b/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/CODE_REVIEW-local-G05.md @@ -0,0 +1,78 @@ + + +# Code Review Reference - REFACTOR + +## 개요 + +date=2026-06-10 +task=m-agent-registration-capability-boundary/02+01_command_adapter, plan=0, tag=REFACTOR + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `command-adapter`: command catalog 조회와 `registerAllCommands()` 호출을 command domain adapter 뒤로 이동한다. +- Completion mode: check-on-pass + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [REFACTOR-1] Command Adapter | [ ] | + +## 구현 체크리스트 + +- [ ] 선행 `agent-task/m-agent-registration-capability-boundary/01_agent_port/**/complete.log` 존재를 확인한다. +- [ ] command domain에 agent port 구현 adapter를 추가한다. +- [ ] adapter가 `registerAllCommands()` 호출 후 `Command.catalogRows`에서 type만 안정적으로 산출하게 한다. +- [ ] command catalog test에 adapter command type parity test를 추가한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## 코드리뷰 전용 체크리스트 + +- [ ] PASS/WARN/FAIL 판정을 append한다. +- [ ] active plan/review 파일을 `.log`로 아카이브한다. +- [ ] PASS이면 `complete.log` 작성 후 archive로 이동한다. + +## 계획 대비 변경 사항 + +_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._ + +## 주요 설계 결정 + +_구현 에이전트가 주요 설계 결정 사항을 기록한다._ + +## 사용자 리뷰 요청 + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- adapter가 command 도메인에 있고 agent implementation 파일에 command import를 추가하지 않았는지 확인 +- `registerAllCommands()` 호출이 adapter 뒤로 이동했는지 확인 +- test가 command catalog와 adapter parity를 검증하는지 확인 + +## 검증 결과 + +### REFACTOR-1 중간 검증 + +```text +$ cd apps/runner && dart test test/oto_command_catalog_test.dart +(output) +``` + +### 최종 검증 + +```text +$ cd apps/runner && dart analyze +(output) + +$ cd apps/runner && dart test test/oto_command_catalog_test.dart test/oto_command_runtime_test.dart +(output) +``` diff --git a/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/PLAN-local-G05.md b/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/PLAN-local-G05.md new file mode 100644 index 0000000..52e277c --- /dev/null +++ b/agent-task/m-agent-registration-capability-boundary/02+01_command_adapter/PLAN-local-G05.md @@ -0,0 +1,122 @@ + + +# Plan - REFACTOR Command Capability Adapter + +## 이 파일을 읽는 구현 에이전트에게 + +`CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션 작성이 필수 마지막 단계다. 선행 `01_agent_port`의 `complete.log`가 없으면 구현을 시작하지 말고 blocker를 review stub에 기록한다. + +## 배경 + +agent 도메인이 command catalog를 직접 해석하지 않게 하려면 command 도메인 쪽 adapter가 agent port를 구현해야 한다. 이 subtask는 command registry/catalog 조회 책임을 command domain 파일로 이동한다. + +## 사용자 리뷰 요청 흐름 + +구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 prompt는 금지이며 code-review가 user review 여부를 결정한다. + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `command-adapter`: command catalog 조회와 `registerAllCommands()` 호출을 command domain adapter 뒤로 이동한다. +- Completion mode: check-on-pass + +## 분석 결과 + +### 읽은 파일 + +- `apps/runner/lib/oto/agent/registration_client.dart` +- `apps/runner/lib/oto/commands/command.dart` +- `apps/runner/lib/oto/commands/command_catalog.dart` +- `apps/runner/lib/oto/commands/command_registry.dart` +- `apps/runner/test/oto_command_catalog_test.dart` +- `agent-test/local/command-smoke.md` +- `agent-ops/rules/project/domain/command/rules.md` + +### 테스트 환경 규칙 + +`test_env=local`. command-smoke에 따라 `cd apps/runner && dart analyze`와 `cd apps/runner && dart test test/oto_command_catalog_test.dart test/oto_command_runtime_test.dart`가 기준이다. 이 subtask는 catalog adapter라 `oto_command_catalog_test.dart`가 focused test다. + +### 테스트 커버리지 공백 + +- command catalog 자체는 [oto_command_catalog_test.dart](/config/workspace/oto/apps/runner/test/oto_command_catalog_test.dart:519)에서 stable field를 검증한다. +- 신규 adapter가 agent port를 구현하는지는 현재 테스트가 없으므로 command catalog test에 command type list parity test를 추가해야 한다. + +### 심볼 참조 + +rename/removal 없음. 신규 adapter class만 추가한다. + +### 분할 판단 + +multi-plan의 두 번째 subtask다. `02+01_command_adapter`는 predecessor `01_agent_port`의 active/archive `complete.log`가 필요하다. 현재 계획 작성 시점에는 predecessor가 아직 완료되지 않았으므로 구현 agent는 시작 전 다시 확인해야 한다. + +### 범위 결정 근거 + +이 subtask는 command domain adapter 추가와 command catalog test만 다룬다. `OtoServerRegistrationClient` production default wiring은 `03`에서 처리한다. + +### 빌드 등급 + +`local-G05`: command domain 내부 adapter와 focused catalog test로 검증 가능하다. + +## 의존 관계 및 구현 순서 + +`01_agent_port`의 `complete.log`가 필요하다. 없으면 구현하지 않고 review stub의 사용자 리뷰 요청이 아니라 계획/의존 blocker로 기록한다. + +## 구현 체크리스트 + +- [ ] 선행 `agent-task/m-agent-registration-capability-boundary/01_agent_port/**/complete.log` 존재를 확인한다. +- [ ] command domain에 agent port 구현 adapter를 추가한다. +- [ ] adapter가 `registerAllCommands()` 호출 후 `Command.catalogRows`에서 type만 안정적으로 산출하게 한다. +- [ ] command catalog test에 adapter command type parity test를 추가한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +### [REFACTOR-1] Command Adapter + +문제: [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:246)가 command registry/catalog 호출을 agent 도메인 내부에서 수행한다. + +해결 방법: `apps/runner/lib/oto/commands/runner_command_capability_provider.dart`를 추가하고 `RunnerCapabilityProvider`를 구현한다. + +```dart +class CommandCatalogRunnerCapabilityProvider implements RunnerCapabilityProvider { + const CommandCatalogRunnerCapabilityProvider(); + + @override + RunnerCapabilitySnapshot snapshot() { + registerAllCommands(); + return RunnerCapabilitySnapshot( + name: otoRunnerCapabilityName, + version: otoRunnerCapabilityVersion, + commandTypes: Command.catalogRows.map((row) => row['type']!), + ); + } +} +``` + +수정 파일 및 체크리스트: + +- [ ] `apps/runner/lib/oto/commands/runner_command_capability_provider.dart` 추가 +- [ ] `apps/runner/test/oto_command_catalog_test.dart` adapter parity test 추가 + +테스트 작성: 작성. adapter output과 `Command.catalogRows.map(type)`이 일치하는지 검증한다. + +중간 검증: + +```bash +cd apps/runner && dart test test/oto_command_catalog_test.dart +``` + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `apps/runner/lib/oto/commands/runner_command_capability_provider.dart` | REFACTOR-1 | +| `apps/runner/test/oto_command_catalog_test.dart` | REFACTOR-1 | + +## 최종 검증 + +```bash +cd apps/runner && dart analyze +cd apps/runner && dart test test/oto_command_catalog_test.dart test/oto_command_runtime_test.dart +``` + +모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/CODE_REVIEW-local-G06.md b/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/CODE_REVIEW-local-G06.md new file mode 100644 index 0000000..a1fdf0c --- /dev/null +++ b/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/CODE_REVIEW-local-G06.md @@ -0,0 +1,86 @@ + + +# Code Review Reference - REFACTOR + +## 개요 + +date=2026-06-10 +task=m-agent-registration-capability-boundary/03+01,02_registration_wiring, plan=0, tag=REFACTOR + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `registration`: 기존 registration payload 의미를 유지하면서 agent registration client가 adapter 계약만 소비하도록 바꾼다. + - `rule-evidence`: 변경 후 agent domain rule 위반 import가 남아 있지 않은지 확인한다. +- Completion mode: check-on-pass + +## 구현 항목별 완료 여부 + +| 항목 | 완료 여부 | +|------|---------| +| [REFACTOR-1] Registration Wiring | [ ] | + +## 구현 체크리스트 + +- [ ] 선행 `01_agent_port`, `02+01_command_adapter` complete evidence를 확인한다. +- [ ] `OtoServerRegistrationClient`에서 command domain imports와 `_defaultCommandTypes()`를 제거한다. +- [ ] default production 생성 경로에서 command adapter provider를 주입하되 기존 `commandTypes:` call site 호환을 유지한다. +- [ ] provider default path request build test와 HTTP payload test를 추가/갱신한다. +- [ ] `rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent` 결과가 의도된 예외 없이 비어 있는지 확인한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +## 코드리뷰 전용 체크리스트 + +- [ ] PASS/WARN/FAIL 판정을 append한다. +- [ ] active plan/review 파일을 `.log`로 아카이브한다. +- [ ] PASS이면 `complete.log` 작성 후 archive로 이동한다. + +## 계획 대비 변경 사항 + +_구현 에이전트가 계획과 다르게 구현한 부분을 이유와 함께 기록한다._ + +## 주요 설계 결정 + +_구현 에이전트가 주요 설계 결정 사항을 기록한다._ + +## 사용자 리뷰 요청 + +- 상태: 없음 +- 사유 유형: 없음 +- 결정 필요: 없음 +- 차단 근거: 없음 +- 실행한 검증/명령: 없음 +- 자동 후속 불가 이유: 없음 +- 재개 조건: 없음 + +## 리뷰어를 위한 체크포인트 + +- `registration_client.dart`가 command domain import를 더 이상 갖지 않는지 확인 +- 기존 explicit `commandTypes:` call site가 깨지지 않는지 확인 +- server connection smoke가 registration payload 의미를 유지하는지 확인 + +## 검증 결과 + +### REFACTOR-1 중간 검증 + +```text +$ rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent +(output) + +$ cd apps/runner && dart test test/oto_agent_registration_test.dart +(output) +``` + +### 최종 검증 + +```text +$ cd apps/runner && dart analyze +(output) + +$ cd apps/runner && dart test test/oto_agent_registration_test.dart test/oto_command_catalog_test.dart test/oto_server_connection_smoke_test.dart +(output) + +$ rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent +(output) +``` diff --git a/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/PLAN-local-G06.md b/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/PLAN-local-G06.md new file mode 100644 index 0000000..da09e87 --- /dev/null +++ b/agent-task/m-agent-registration-capability-boundary/03+01,02_registration_wiring/PLAN-local-G06.md @@ -0,0 +1,128 @@ + + +# Plan - REFACTOR Registration Wiring + +## 이 파일을 읽는 구현 에이전트에게 + +`CODE_REVIEW-*-G??.md` 작성이 필수 마지막 단계다. 선행 `01_agent_port`, `02+01_command_adapter`의 `complete.log`가 없으면 구현을 시작하지 않는다. 최종화와 roadmap 완료 처리는 code-review/runtime 책임이다. + +## 배경 + +port와 adapter가 생긴 뒤에도 production 등록 경로가 adapter 계약만 소비하도록 wiring해야 milestone이 닫힌다. 이 subtask는 `OtoServerRegistrationClient`의 command imports를 제거하고, 기본 client 생성 경로가 command adapter provider를 주입하도록 연결한다. + +## 사용자 리뷰 요청 흐름 + +구현 중 blocker는 active review stub의 `사용자 리뷰 요청` 섹션에 기록한다. 직접 사용자 prompt는 금지이며 code-review가 user review 여부를 결정한다. + +## Roadmap Targets + +- Milestone: `agent-roadmap/phase/message-based-build-agent/milestones/agent-registration-capability-boundary.md` +- Task ids: + - `registration`: 기존 registration payload 의미를 유지하면서 agent registration client가 adapter 계약만 소비하도록 바꾼다. + - `rule-evidence`: 변경 후 agent domain rule 위반 import가 남아 있지 않은지 확인한다. +- Completion mode: check-on-pass + +## 분석 결과 + +### 읽은 파일 + +- `apps/runner/lib/oto/agent/registration_client.dart` +- `apps/runner/lib/oto/agent/agent_runner.dart` +- `apps/runner/lib/oto/commands/command.dart` +- `apps/runner/lib/oto/commands/command_catalog.dart` +- `apps/runner/lib/oto/commands/command_registry.dart` +- `apps/runner/test/oto_agent_registration_test.dart` +- `apps/runner/test/oto_server_connection_smoke_test.dart` +- `agent-test/local/agent-smoke.md` +- `agent-test/local/command-smoke.md` +- `agent-ops/rules/project/domain/agent/rules.md` +- `agent-ops/rules/project/domain/command/rules.md` + +### 테스트 환경 규칙 + +`test_env=local`. agent-smoke 기준으로 `cd apps/runner && dart analyze`, agent registration tests, OTO Server connection smoke를 실행한다. rule evidence는 deterministic `rg --sort path` 검색으로 확인한다. + +### 테스트 커버리지 공백 + +- 기존 request build test는 explicit `commandTypes` path만 검증한다. provider default path로 payload가 동일하게 생성되는 test를 추가해야 한다. +- OTO Server smoke는 explicit commandTypes call site가 많아 default provider path 자체는 별도 unit test로 보강해야 한다. + +### 심볼 참조 + +- `OtoServerRegistrationClient(commandTypes:)` call sites: `oto_agent_registration_test.dart` lines 103, 150, 201, 257, 320, 374, 623 and `oto_server_connection_smoke_test.dart` lines 61, 390, 573, 727, 866, 997, 1114, 1250. 호환 유지 대상이다. +- 제거 대상 import: [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:9), [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:10). + +### 분할 판단 + +multi-plan의 마지막 subtask다. `03+01,02_registration_wiring`는 predecessor `01_agent_port`, `02+01_command_adapter`의 완료가 필요하다. 두 predecessor의 active/archive `complete.log`를 구현 시작 전에 확인해야 한다. + +### 범위 결정 근거 + +이 subtask는 production wiring, compatibility 유지, final smoke/evidence만 다룬다. command catalog 자체의 sample/data model 정책은 변경하지 않는다. + +### 빌드 등급 + +`local-G06`: agent와 command 경계를 함께 연결하고 server smoke까지 확인하지만, schema/storage/concurrency 변경은 없다. + +## 의존 관계 및 구현 순서 + +`01_agent_port`와 `02+01_command_adapter` complete가 선행 조건이다. 둘 중 하나라도 없으면 구현을 시작하지 않는다. + +## 구현 체크리스트 + +- [ ] 선행 `01_agent_port`, `02+01_command_adapter` complete evidence를 확인한다. +- [ ] `OtoServerRegistrationClient`에서 command domain imports와 `_defaultCommandTypes()`를 제거한다. +- [ ] default production 생성 경로에서 command adapter provider를 주입하되 기존 `commandTypes:` call site 호환을 유지한다. +- [ ] provider default path request build test와 HTTP payload test를 추가/갱신한다. +- [ ] `rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent` 결과가 의도된 예외 없이 비어 있는지 확인한다. +- [ ] CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다. + +### [REFACTOR-1] Registration Wiring + +문제: [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:169)의 request build가 [registration_client.dart](/config/workspace/oto/apps/runner/lib/oto/agent/registration_client.dart:246)의 command catalog helper에 fallback한다. + +해결 방법: `OtoServerRegistrationClient`는 `RunnerCapabilityProvider`만 소비한다. `agent_runner.dart`의 기본 client 생성은 command adapter provider를 import해서 전달한다. + +```dart +DefaultAgentRunner({ + RegistrationClient? client, + ... +}) : _client = client ?? OtoServerRegistrationClient( + capabilityProvider: const CommandCatalogRunnerCapabilityProvider(), + ); +``` + +수정 파일 및 체크리스트: + +- [ ] `apps/runner/lib/oto/agent/registration_client.dart` import 제거 및 provider 소비 +- [ ] `apps/runner/lib/oto/agent/agent_runner.dart` default provider wiring +- [ ] `apps/runner/test/oto_agent_registration_test.dart` default/provider tests + +테스트 작성: 작성. default provider path와 explicit `commandTypes:` compatibility를 모두 검증한다. + +중간 검증: + +```bash +rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent +cd apps/runner && dart test test/oto_agent_registration_test.dart +``` + +## 수정 파일 요약 + +| 파일 | 항목 | +|------|------| +| `apps/runner/lib/oto/agent/registration_client.dart` | REFACTOR-1 | +| `apps/runner/lib/oto/agent/agent_runner.dart` | REFACTOR-1 | +| `apps/runner/test/oto_agent_registration_test.dart` | REFACTOR-1 | + +## 최종 검증 + +```bash +cd apps/runner && dart analyze +cd apps/runner && dart test test/oto_agent_registration_test.dart test/oto_command_catalog_test.dart test/oto_server_connection_smoke_test.dart +rg --sort path "package:oto/oto/commands/" apps/runner/lib/oto/agent +``` + +`rg` 명령은 출력이 없어야 통과다. + +모든 코드 변경 완료 후 반드시 `CODE_REVIEW-*-G??.md`의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다. diff --git a/agent-test/local/agent-smoke.md b/agent-test/local/agent-smoke.md index c777209..ef6d854 100644 --- a/agent-test/local/agent-smoke.md +++ b/agent-test/local/agent-smoke.md @@ -3,7 +3,7 @@ test_env: local test_profile: agent-smoke domain: agent verification_type: smoke -last_rule_updated_at: 2026-06-07 +last_rule_updated_at: 2026-06-10 --- # agent-smoke local 테스트 @@ -51,6 +51,7 @@ last_rule_updated_at: 2026-06-07 - runner: `cd apps/runner && dart analyze` (또는 `make runner-analyze`) - unit: - runner: `cd apps/runner && dart test test/oto_agent_migration_plan_test.dart test/oto_agent_bootstrap_script_test.dart test/oto_agent_cli_test.dart test/oto_agent_config_test.dart test/oto_agent_registration_test.dart test/oto_server_connection_smoke_test.dart` (또는 `make runner-test`) + - legacy iop: `make runner-test-legacy-iop` (수동 migration evidence 전용, 기본 `make runner-test`에서는 제외) - core: `cd services/core && go test ./...` (또는 `make core-test`) - smoke: - e2e: @@ -65,7 +66,8 @@ last_rule_updated_at: 2026-06-07 ## 보조 검증 -- 전체 회귀가 필요한 경우 `cd apps/runner && dart test` 또는 `make runner-test`를 실행한다. +- 전체 현재 runner 회귀가 필요한 경우 `make runner-test`를 실행한다. +- legacy iop Edge 직접 연결 증거가 필요할 때만 `make runner-test-legacy-iop`를 수동 실행한다. - OTO Server 전체 회귀가 필요한 경우 `make core-test`를 실행한다. ## 판정 기준 diff --git a/agent-test/local/rules.md b/agent-test/local/rules.md index c4efdfd..3545cfd 100644 --- a/agent-test/local/rules.md +++ b/agent-test/local/rules.md @@ -51,7 +51,8 @@ last_rule_updated_at: 2026-06-10 - **apps/runner** (Dart CLI runner): - Setup: `make runner-get` 또는 `cd apps/runner && dart pub get` - Lint: `make runner-analyze` 또는 `cd apps/runner && dart analyze` - - Test: `make runner-test` 또는 `cd apps/runner && dart test` + - Test: `make runner-test` (현재 필수 runner 회귀) 또는 `cd apps/runner && dart test` + - Legacy iop evidence: `make runner-test-legacy-iop` (수동 실행 전용) - **apps/client** (Flutter OTO client app): - Setup: `make client-get` 또는 `cd apps/client && flutter pub get` - Lint: `make client-analyze` 또는 `cd apps/client && flutter analyze` diff --git a/apps/runner/lib/oto/agent/registration_client.dart b/apps/runner/lib/oto/agent/registration_client.dart index e7d4d68..a91a759 100644 --- a/apps/runner/lib/oto/agent/registration_client.dart +++ b/apps/runner/lib/oto/agent/registration_client.dart @@ -6,6 +6,7 @@ import 'package:http/http.dart' as http; import 'package:oto/oto/agent/agent_config.dart'; import 'package:oto/oto/agent/oto_server_job_client.dart'; import 'package:oto/oto/agent/oto/runner.pb.dart' as oto; +import 'package:oto/oto/agent/runner_capability_provider.dart'; import 'package:oto/oto/commands/command.dart'; import 'package:oto/oto/commands/command_registry.dart'; @@ -114,17 +115,20 @@ abstract class RegistrationClient { class OtoServerRegistrationClient extends RegistrationClient { final http.Client? _client; - final List? _commandTypes; + final RunnerCapabilityProvider _capabilityProvider; final Duration _heartbeatInterval; OtoServerRegistrationClient({ http.Client? client, Iterable? commandTypes, + RunnerCapabilityProvider? capabilityProvider, Duration heartbeatInterval = const Duration(seconds: 30), }) : _client = client, - _commandTypes = commandTypes == null - ? null - : List.unmodifiable(commandTypes), + _capabilityProvider = + capabilityProvider ?? + (commandTypes == null + ? const _DefaultRunnerCapabilityProvider() + : _StaticRunnerCapabilityProvider(commandTypes)), _heartbeatInterval = heartbeatInterval; @override @@ -167,16 +171,17 @@ class OtoServerRegistrationClient extends RegistrationClient { } oto.RegisterRunnerRequest buildRegisterRunnerRequest(AgentConfig config) { + final capability = _capabilityProvider.snapshot(); final request = oto.RegisterRunnerRequest() ..enrollmentToken = config.agent.enrollmentToken ..runnerId = config.agent.id ..alias = config.agent.alias ?? '' ..protocolVersion = otoRunnerProtocolVersion ..capability = (oto.RunnerCapability() - ..name = otoRunnerCapabilityName - ..version = otoRunnerCapabilityVersion) + ..name = capability.name + ..version = capability.version) ..commandCatalog = (oto.CommandCatalogSummary() - ..commandTypes.addAll(_commandTypes ?? _defaultCommandTypes())); + ..commandTypes.addAll(capability.commandTypes)); return request; } @@ -243,12 +248,41 @@ class OtoServerRegistrationClient extends RegistrationClient { }, }; - List _defaultCommandTypes() { + static List _defaultCommandTypes() { registerAllCommands(); return Command.catalogRows.map((row) => row['type']!).toList(); } } +class _DefaultRunnerCapabilityProvider implements RunnerCapabilityProvider { + const _DefaultRunnerCapabilityProvider(); + + @override + RunnerCapabilitySnapshot snapshot() { + return RunnerCapabilitySnapshot( + name: otoRunnerCapabilityName, + version: otoRunnerCapabilityVersion, + commandTypes: OtoServerRegistrationClient._defaultCommandTypes(), + ); + } +} + +class _StaticRunnerCapabilityProvider implements RunnerCapabilityProvider { + final List _commandTypes; + + _StaticRunnerCapabilityProvider(Iterable commandTypes) + : _commandTypes = List.unmodifiable(commandTypes); + + @override + RunnerCapabilitySnapshot snapshot() { + return RunnerCapabilitySnapshot( + name: otoRunnerCapabilityName, + version: otoRunnerCapabilityVersion, + commandTypes: _commandTypes, + ); + } +} + class _OtoServerAgentSession implements OtoServerJobSession { final http.Client _client; final bool _shouldCloseClient; diff --git a/apps/runner/lib/oto/agent/runner_capability_provider.dart b/apps/runner/lib/oto/agent/runner_capability_provider.dart new file mode 100644 index 0000000..fd8c44d --- /dev/null +++ b/apps/runner/lib/oto/agent/runner_capability_provider.dart @@ -0,0 +1,15 @@ +abstract class RunnerCapabilityProvider { + RunnerCapabilitySnapshot snapshot(); +} + +class RunnerCapabilitySnapshot { + final String name; + final String version; + final List commandTypes; + + RunnerCapabilitySnapshot({ + required this.name, + required this.version, + required Iterable commandTypes, + }) : commandTypes = List.unmodifiable(commandTypes); +} diff --git a/apps/runner/test/oto_agent_registration_test.dart b/apps/runner/test/oto_agent_registration_test.dart index dd7b21e..9d09453 100644 --- a/apps/runner/test/oto_agent_registration_test.dart +++ b/apps/runner/test/oto_agent_registration_test.dart @@ -9,6 +9,7 @@ import 'package:oto/oto/agent/edge_registration_client.dart' show EdgeEndpoint; import 'package:oto/oto/agent/registration_client.dart'; import 'package:oto/oto/agent/oto_server_job_client.dart'; import 'package:oto/oto/agent/remote_run_executor.dart'; +import 'package:oto/oto/agent/runner_capability_provider.dart'; import 'package:oto/oto/application.dart'; import 'package:oto/oto/core/build_result.dart'; import 'package:oto/oto/core/execution_context.dart'; @@ -41,6 +42,15 @@ class FakeRegistrationClient extends RegistrationClient { } } +class FakeRunnerCapabilityProvider implements RunnerCapabilityProvider { + final RunnerCapabilitySnapshot _snapshot; + + FakeRunnerCapabilityProvider(this._snapshot); + + @override + RunnerCapabilitySnapshot snapshot() => _snapshot; +} + void main() { const validBootstrapYaml = ''' agent: @@ -114,6 +124,24 @@ runtime: expect(request.commandCatalog.commandTypes, ['Shell', 'Git']); }); + test('builds registration request from injected capability provider', () { + final client = OtoServerRegistrationClient( + capabilityProvider: FakeRunnerCapabilityProvider( + RunnerCapabilitySnapshot( + name: 'custom-runner', + version: '2.0.0', + commandTypes: ['Print', 'ShellFile'], + ), + ), + ); + + final request = client.buildRegisterRunnerRequest(validConfig); + + expect(request.capability.name, 'custom-runner'); + expect(request.capability.version, '2.0.0'); + expect(request.commandCatalog.commandTypes, ['Print', 'ShellFile']); + }); + test('posts registration request to OTO Server endpoint', () async { final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0); final captured = Completer>();