diff --git a/.clinerules b/.clinerules index c34b043..258ee50 100644 --- a/.clinerules +++ b/.clinerules @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 @@ -48,3 +48,4 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- dev-corp: `agent-test/dev-corp/rules.md` diff --git a/.cursorrules b/.cursorrules index c34b043..258ee50 100644 --- a/.cursorrules +++ b/.cursorrules @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 @@ -48,3 +48,4 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- dev-corp: `agent-test/dev-corp/rules.md` diff --git a/AGENTS.md b/AGENTS.md index c34b043..258ee50 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 @@ -48,3 +48,4 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- dev-corp: `agent-test/dev-corp/rules.md` diff --git a/CLAUDE.md b/CLAUDE.md index c34b043..258ee50 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 @@ -48,3 +48,4 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- dev-corp: `agent-test/dev-corp/rules.md` diff --git a/GEMINI.md b/GEMINI.md index c34b043..258ee50 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 @@ -48,3 +48,4 @@ **테스트 실행/검증 작업이 포함된 경우, 작업 환경에 맞게 최초 1회 읽고 수행한다. 환경 미지정은 local로 본다.** - local: `agent-test/local/rules.md` (없으면 `create-test`) +- dev-corp: `agent-test/dev-corp/rules.md` diff --git a/README.md b/README.md index 4794564..72d3267 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ adapter = cli target = codex-local ``` -외부 OpenAI API 호환 계층에서는 호환성을 위해 `model` 필드가 남을 수 있다. 그러나 내부 실행 개념에서는 모델 이름만으로 전체 실행을 설명하지 않고, `adapter`, `target`, `execution`, `node adapter`, `adapter execution` 같은 용어를 우선한다. IOP의 외부 실행 호출 계약은 OpenAI-compatible API 방식을 기본 표면으로 채택하되, IOP 고유의 workspace, session, agent, approval, artifact, notification 의미는 별도 `iop` wrapper field를 만들지 않고 `metadata` 또는 IOP native endpoint의 명시 필드로 전달한다. 외부 프로젝트가 참조할 OpenAI-compatible 요청 계약 원문은 [agent-contract/provided/openai-compatible-api.md](agent-contract/provided/openai-compatible-api.md)에 둔다. +외부 OpenAI API 호환 계층에서는 호환성을 위해 `model` 필드가 남을 수 있다. 그러나 내부 실행 개념에서는 모델 이름만으로 전체 실행을 설명하지 않고, `adapter`, `target`, `execution`, `node adapter`, `adapter execution` 같은 용어를 우선한다. IOP의 외부 실행 호출 계약은 OpenAI-compatible API 방식을 기본 표면으로 채택하되, IOP 고유의 workspace, session, agent, approval, artifact, notification 의미는 별도 `iop` wrapper field를 만들지 않고 `metadata` 또는 IOP native endpoint의 명시 필드로 전달한다. 외부 프로젝트가 참조할 OpenAI-compatible 요청 계약 원문은 [agent-contract/outer/openai-compatible-api.md](agent-contract/outer/openai-compatible-api.md)에 둔다. ## 아키텍처 @@ -175,7 +175,7 @@ IOP 내부 실행은 model 중심이 아니라 adapter 중심으로 정리한다 - `node adapter`: Node 안에 등록되어 실제 실행을 담당하는 adapter - `adapter execution`: Node adapter가 수행하는 실행 단위 -현재 코드에는 `RunRequest`, `ExecutionSpec`, `RuntimeEvent`, `NodeCommandRequest`, `EdgeNodeEvent`처럼 이 방향을 담기 위한 타입들이 있다. `RunEvent`는 adapter execution stream에, `EdgeNodeEvent`는 node 연결/해제 같은 edge-node lifecycle과 이후 제어/상태성 이벤트에 사용한다. 세부 계약과 schema는 작업을 진행하면서 점진적으로 정리한다. +현재 코드에는 `RunRequest`, `ExecutionSpec`, `RuntimeEvent`, `NodeCommandRequest`, `EdgeNodeEvent`처럼 이 방향을 담기 위한 타입들이 있다. `RunEvent`는 adapter execution stream에, `EdgeNodeEvent`는 node 연결/해제 같은 edge-node lifecycle과 이후 제어/상태성 이벤트에 사용한다. 세부 계약과 schema는 [agent-contract/index.md](agent-contract/index.md)에서 inner/outer 계약으로 라우팅한다. ### 런타임 도메인(Runtime Domain) @@ -260,12 +260,13 @@ Client의 장기 UI 기준은 Flutter 앱이며, 필요한 웹 표면은 Flutter ## 개발 메모 - 기존 구조를 우선하며, 세부 구현은 각 작업의 domain rule과 현재 코드 경계를 먼저 확인한 뒤 진행한다. +- API, wire protocol, runtime, event/config schema 계약은 [agent-contract/index.md](agent-contract/index.md)를 기준으로 확인하고, README에는 사람용 방향과 포인터만 둔다. - Edge-Node 내부 통신은 TCP/protobuf 기반 소켓 흐름을 우선한다. - Client-Control Plane처럼 앱/브라우저 표면이 필요한 경계는 proto-socket WebSocket/WSS를 사용할 수 있다. Edge-Node 기본 transport를 WebSocket으로 전환하거나 gRPC, actor/FSM/plugin framework를 도입하는 것은 현재 단계의 기본 방향이 아니다. - OpenAI-compatible API 계층은 외부 모델 호출 호환을 위한 표면이며, 내부 실행 모델 전체를 대표하지 않는다. - OpenAI-compatible API는 현재 chat completions baseline을 가지며, Responses API 호환 표면까지 지원하는 방향으로 확장한다. -- IOP의 외부 통신 규약은 OpenAI-compatible API 방식을 기본 계약으로 채택하고, 나머지 IOP 전용 실행 문맥은 `metadata` 확장으로 전달한다. `iop` 같은 별도 wrapper field를 기본 표면에 추가하지 않는다. 구체 요청 계약은 [agent-contract/provided/openai-compatible-api.md](agent-contract/provided/openai-compatible-api.md)를 기준으로 한다. -- A2A API 계층은 agent 간 작업 위임과 상태 공유를 위한 표면이며, 단순 모델 호출 호환은 OpenAI-compatible API를 사용한다. NomadCode의 A2A 도입 시점은 아직 강제하지 않는다. +- IOP의 외부 통신 규약은 OpenAI-compatible API 방식을 기본 계약으로 채택하고, 나머지 IOP 전용 실행 문맥은 `metadata` 확장으로 전달한다. `iop` 같은 별도 wrapper field를 기본 표면에 추가하지 않는다. 구체 요청 계약은 [agent-contract/outer/openai-compatible-api.md](agent-contract/outer/openai-compatible-api.md)를 기준으로 한다. +- A2A API 계층은 agent 간 작업 위임과 상태 공유를 위한 표면이며, 단순 모델 호출 호환은 OpenAI-compatible API를 사용한다. A2A 요청 계약은 [agent-contract/outer/a2a-json-rpc-api.md](agent-contract/outer/a2a-json-rpc-api.md)를 기준으로 한다. - IOP native protocol은 OpenAI-compatible API나 A2A API를 대체하는 것이 아니라, Edge/Node 운영 제어와 CLI/session/command/event 같은 IOP 고유 기능을 제공하는 병행 표면이다. - Remote terminal bridge는 Edge/Node 운영 제어 기능으로 분류하며, OpenAI-compatible API가 아니라 IOP native protocol과 정책/audit 계층에서 다룬다. - 앱별 README에는 현재 수동 테스트나 구현 세부가 더 많이 남아 있을 수 있다. 루트 README는 전체 방향과 경계를 설명하는 문서로 유지한다. diff --git a/agent-contract/index.md b/agent-contract/index.md index 2f8d158..ed5ec6d 100644 --- a/agent-contract/index.md +++ b/agent-contract/index.md @@ -2,19 +2,24 @@ ## 읽기 규칙 -- 현재 작업이 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약에 닿을 때만 이 문서를 사용한다. +- 현재 작업이 API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약에 닿을 때만 이 문서를 사용한다. - 매칭되는 계약 문서만 읽는다. - 계약 문서 경로가 없으면 계약을 추정하지 않고 사용자에게 확인한다. -- 계약 원문은 `agent-contract/provided/**` 또는 외부 프로젝트의 `agent-contract/provided/**` 한 곳에 둔다. +- 계약 원문은 `agent-contract/outer/**` 또는 `agent-contract/inner/**` 한 곳에 둔다. - `docs/`, `README`, `rules.md`에는 계약 원문을 복제하지 않고 계약 원문 경로만 둔다. -## 제공 계약 +## Outer Contracts -| id | 읽는 조건 | path | -|----|-----------|------| -| `iop.openai-compatible-api` | OpenAI-compatible API, Responses API, Chat Completions, legacy Completions, `model` route, Codex/CLI workspace, generic authoring metadata, `metadata.workspace`, `metadata.task_id` | `agent-contract/provided/openai-compatible-api.md` | +| id | 읽는 조건 | 원본 경로 | path | +|----|-----------|-----------|------| +| `iop.openai-compatible-api` | OpenAI-compatible API, Responses API, Chat Completions, legacy Completions, `model` route, Codex/CLI workspace, generic authoring metadata, `metadata.workspace`, `metadata.task_id` | `apps/edge/internal/openai/*`, `packages/go/config/config.go`, `configs/edge.yaml` | `agent-contract/outer/openai-compatible-api.md` | +| `iop.a2a-json-rpc-api` | A2A JSON-RPC API, `message/send`, `tasks/get`, `tasks/cancel`, A2A task state, agent card, `a2a.bearer_token`, Edge A2A input surface | `apps/edge/internal/input/a2a/*`, `packages/go/config/config.go`, `configs/edge.yaml` | `agent-contract/outer/a2a-json-rpc-api.md` | -## 소비 계약 +## Inner Contracts -| id | 읽는 조건 | source | -|----|-----------|--------| +| id | 읽는 조건 | 원본 경로 | path | +|----|-----------|-----------|------| +| `iop.edge-node-runtime-wire` | Edge-Node TCP/protobuf, proto-socket transport, `RegisterRequest`, `RegisterResponse`, `RunRequest`, `RunEvent`, `CancelRequest`, `NodeCommandRequest`, `NodeConfigPayload`, `NodeConfigRefreshRequest` | `proto/iop/runtime.proto`, `apps/edge/internal/transport/*`, `apps/node/internal/transport/*`, `apps/edge/internal/node/mapper.go`, `apps/node/internal/adapters/config_set.go` | `agent-contract/inner/edge-node-runtime-wire.md` | +| `iop.control-plane-edge-wire` | Control Plane-Edge wire, `EdgeHelloRequest`, `EdgeStatusRequest`, `EdgeStatusResponse`, `EdgeCommandRequest`, `EdgeCommandEvent`, Edge connection registry | `proto/iop/control.proto`, `apps/control-plane/internal/wire/*`, `apps/edge/internal/controlplane/*` | `agent-contract/inner/control-plane-edge-wire.md` | +| `iop.client-control-plane-wire` | Client-Control Plane wire, `/client` WebSocket, proto-socket WS, `ClientHelloRequest`, `ClientHelloResponse`, Flutter client wire | `proto/iop/control.proto`, `apps/control-plane/internal/wire/client.go`, `apps/client/lib/iop_wire/*` | `agent-contract/inner/client-control-plane-wire.md` | +| `iop.edge-config-runtime-refresh` | Edge config schema, `configs/edge.yaml`, `packages/go/config`, provider pool, `models[]`, `nodes[].providers[]`, `openai.model_routes`, config refresh, restart/applied classification | `packages/go/config/config.go`, `configs/edge.yaml`, `apps/edge/internal/configrefresh/*`, `proto/iop/runtime.proto` | `agent-contract/inner/edge-config-runtime-refresh.md` | diff --git a/agent-contract/inner/client-control-plane-wire.md b/agent-contract/inner/client-control-plane-wire.md new file mode 100644 index 0000000..7b96117 --- /dev/null +++ b/agent-contract/inner/client-control-plane-wire.md @@ -0,0 +1,56 @@ +# Client-Control Plane Wire Contract + +## 계약 메타 + +- id: `iop.client-control-plane-wire` +- boundary: `inner` +- status: active-mvp +- 원본 경로: + - `proto/iop/control.proto` + - `apps/control-plane/internal/wire/wire.go` + - `apps/control-plane/internal/wire/client.go` + - `apps/client/lib/iop_wire/client_wire_client.dart` + - `apps/client/lib/iop_wire/parser_map.dart` +- human docs: + - `apps/control-plane/README.md` + - `apps/client/README.md` + +## 읽는 조건 + +- Client `/client` WebSocket proto-socket endpoint를 바꿀 때 +- `ClientHelloRequest` 또는 `ClientHelloResponse`를 바꿀 때 +- Client가 Control Plane을 통해 Edge/Node 운영 상태를 관찰하는 wire baseline을 검토할 때 + +## 범위 + +이 계약은 Flutter/Web/Desktop Client와 Control Plane 사이의 proto-socket WebSocket 경계다. +현재 MVP는 hello baseline이며, Client는 Edge나 Node TCP/protobuf transport에 직접 연결하지 않는다. + +## 주요 흐름 + +- Client는 `/client` WebSocket으로 Control Plane에 연결한다. +- Client가 `ClientHelloRequest`를 보내면 Control Plane은 `ClientHelloResponse`로 readiness, protocol, server time, message를 응답한다. +- Control Plane listen 주소는 server config와 `IOP_WIRE_LISTEN`/compose port 기준으로 주입한다. + +## 필드 의미 + +- `ClientHelloRequest.client_id`: client instance 식별자다. +- `ClientHelloRequest.client_version`: client build/version 관찰값이다. +- `ClientHelloResponse.ready`: Control Plane이 client 요청을 받을 수 있는지 나타낸다. +- `ClientHelloResponse.protocol`: 현재 `protobuf-socket` 값을 사용한다. +- `server_time_unix_nano`: client가 Control Plane time 기준을 관찰하는 값이다. + +## 금지 사항 + +- Client가 Edge나 Node 내부 TCP/protobuf transport에 직접 연결하는 계약을 만들지 않는다. +- Client를 특정 외부 제품 shell 또는 navigation 계약으로 고정하지 않는다. +- Client wire에 실제 환경 endpoint, credential, private host 값을 tracked 문서로 기록하지 않는다. +- Dart protobuf 생성물을 proto 원본과 불일치하게 두지 않는다. + +## 변경 시 확인할 코드/테스트 + +- `proto/iop/control.proto` +- `apps/control-plane/internal/wire/client_test.go` +- `apps/client/test/iop_wire/client_wire_client_test.dart` +- `apps/client/test/iop_wire/parser_map_test.dart` +- proto 변경 시 `make proto`와 `make proto-dart` diff --git a/agent-contract/inner/control-plane-edge-wire.md b/agent-contract/inner/control-plane-edge-wire.md new file mode 100644 index 0000000..dc0d247 --- /dev/null +++ b/agent-contract/inner/control-plane-edge-wire.md @@ -0,0 +1,58 @@ +# Control Plane-Edge Wire Contract + +## 계약 메타 + +- id: `iop.control-plane-edge-wire` +- boundary: `inner` +- status: active-mvp +- 원본 경로: + - `proto/iop/control.proto` + - `apps/control-plane/internal/wire/wire.go` + - `apps/control-plane/internal/wire/edge.go` + - `apps/control-plane/internal/wire/edge_server.go` + - `apps/edge/internal/controlplane/connector.go` +- human docs: `apps/control-plane/README.md` + +## 읽는 조건 + +- Control Plane-Edge TCP proto-socket endpoint를 바꿀 때 +- `EdgeHello*`, `EdgeStatus*`, `EdgeCommand*`, `EdgeNodeSnapshot`, `EdgeNodeEvent`를 바꿀 때 +- Edge status/command/event relay가 Edge-owned node registry나 runtime state를 어떻게 노출하는지 검토할 때 + +## 범위 + +이 계약은 Edge가 Control Plane으로 outbound 연결하는 내부 운영 wire다. +Control Plane은 Edge 연결 view와 제어 요청/결과를 관리하고, Edge는 자신의 Node registry와 runtime 상태를 소유한 채 snapshot과 event를 보고한다. + +## 주요 흐름 + +- hello: Edge가 `EdgeHelloRequest`를 보내고 Control Plane이 `EdgeHelloResponse`로 enrollment를 승인 또는 거부한다. +- status: Control Plane이 `EdgeStatusRequest`를 보내고 Edge가 `EdgeStatusResponse`로 Edge-owned snapshot을 반환한다. +- command: Control Plane이 `EdgeCommandRequest`를 보내고 Edge가 `EdgeCommandResponse`와 `EdgeCommandEvent`로 처리 결과와 phase를 보고한다. +- lifecycle event: Edge는 `EdgeNodeEvent`로 node/edge lifecycle event를 relay한다. + +## 필드 의미 + +- `EdgeHelloRequest.edge_id`: Control Plane connection registry의 Edge identity다. 비어 있으면 hello는 거부된다. +- `EdgeStatusResponse.nodes`: Edge가 소유한 node snapshot view다. +- `EdgeNodeSnapshot.config`: Node에 내려간 config payload의 관찰용 요약이다. +- `EdgeCommandRequest.operation`: Edge-owned operation 이름이다. Node 직접 scheduling 명령으로 사용하지 않는다. +- `EdgeCommandRequest.target_selector`: Edge 내부 operation이 해석할 대상 selector다. Node address나 token을 외부화하지 않는다. +- `metadata`: 필요한 Edge identity 또는 운영 보조 정보만 담는다. secret과 private endpoint 원문은 tracked 계약에 쓰지 않는다. + +## 금지 사항 + +- Control Plane에서 Node를 직접 연결하거나 직접 스케줄링하는 계약을 만들지 않는다. +- `ScheduleRequest`/`ScheduleResponse` legacy tombstone을 활성 계약으로 되살리지 않는다. +- Edge가 보고하지 않은 Node address, token, transport internals를 status/command 응답에 넣지 않는다. +- Control Plane을 Edge 설정, Node registry, runtime/automation 상태의 원본 저장소로 만들지 않는다. +- gRPC를 기본 Control Plane-Edge wire로 도입하지 않는다. + +## 변경 시 확인할 코드/테스트 + +- `proto/iop/control.proto` +- `apps/control-plane/internal/wire/edge_server_test.go` +- `apps/control-plane/internal/wire/edge_test.go` +- `apps/edge/internal/controlplane/connector_test.go` +- `apps/edge/internal/controlplane/heartbeat_test.go` +- proto 변경 시 `make proto` diff --git a/agent-contract/inner/edge-config-runtime-refresh.md b/agent-contract/inner/edge-config-runtime-refresh.md new file mode 100644 index 0000000..b774110 --- /dev/null +++ b/agent-contract/inner/edge-config-runtime-refresh.md @@ -0,0 +1,60 @@ +# Edge Config And Runtime Refresh Contract + +## 계약 메타 + +- id: `iop.edge-config-runtime-refresh` +- boundary: `inner` +- status: active +- 원본 경로: + - `packages/go/config/config.go` + - `configs/edge.yaml` + - `apps/edge/internal/configrefresh/request.go` + - `apps/edge/internal/configrefresh/result.go` + - `apps/edge/internal/configrefresh/classify.go` + - `proto/iop/runtime.proto` + - `apps/edge/internal/node/mapper.go` + - `apps/node/internal/adapters/config_set.go` +- human docs: `apps/edge/README.md` + +## 읽는 조건 + +- `configs/edge.yaml`, `packages/go/config`, provider pool, `openai.model_routes`, `models[]`, `nodes[].providers[]`, adapter instance 설정을 바꿀 때 +- `iop-edge config refresh`의 dry-run/apply 결과 schema나 restart/applied 분류를 바꿀 때 +- Edge가 Node에 전달하는 `NodeConfigPayload` 또는 `NodeConfigRefresh*` payload를 바꿀 때 + +## 범위 + +이 계약은 Edge 설정 YAML, Go config struct, config refresh 결과, Edge-to-Node runtime config payload의 연결 규칙이다. +tracked config에는 public 예시와 기본 구조만 두고, 실제 endpoint/credential/private host 값은 환경별 private 설정으로 주입한다. + +## 핵심 규칙 + +- `openai.model_routes[]`는 외부 OpenAI-compatible `model` id를 내부 `adapter + target` route로 매핑하는 compatibility catalog다. +- `models[]`는 provider pool 방향의 canonical routing key이며 `nodes[].providers[].id`를 참조한다. +- `nodes[].providers[].id`는 전체 Edge config 안에서 중복되면 안 된다. +- legacy single-instance adapter 설정은 load 시 named instance slice로 normalize된다. +- `NodeConfigPayload`는 Edge가 Node에 내려주는 실행 adapter/runtime payload다. +- refresh 결과는 `applied`, `restart_required`, `rejected`를 구분하고, changed node/provider/model/report slice는 안정적으로 non-nil이어야 한다. + +## refresh 분류 기준 + +- live apply 가능: provider capacity, provider max queue, provider queue timeout, `models[]` display/provider mapping, node runtime concurrency. +- restart required: Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, node workspace root, provider type/category/adapter/models/health/lifecycle capability. +- rejected: candidate config load/validate 실패, invalid refresh mode, apply failure. + +## 금지 사항 + +- 설정 파일만 바꾸고 `packages/go/config` loading/default/validation과 불일치하게 두지 않는다. +- provider id, model id, route id의 의미를 섞지 않는다. 외부 `model`은 OpenAI-compatible 경계의 route key이고, 내부 실행은 `adapter + target`이다. +- credential, bearer token, private endpoint 원문을 tracked docs/roadmap/contract에 기록하지 않는다. +- Node bootstrap 기본 경로에서 사용자가 직접 node config를 작성하거나 adapter/provider 값을 명령줄로 넣어야 하는 계약을 만들지 않는다. + +## 변경 시 확인할 코드/테스트 + +- `packages/go/config/config_test.go` +- `apps/edge/internal/configrefresh/classify_test.go` +- `apps/edge/internal/edgecmd/edgecmd_test.go` +- `apps/edge/internal/node/mapper_test.go` +- `apps/node/internal/adapters/config_set_test.go` +- `agent-test/local/platform-common-smoke.md` +- `agent-test/local/edge-smoke.md` diff --git a/agent-contract/inner/edge-node-runtime-wire.md b/agent-contract/inner/edge-node-runtime-wire.md new file mode 100644 index 0000000..8083831 --- /dev/null +++ b/agent-contract/inner/edge-node-runtime-wire.md @@ -0,0 +1,68 @@ +# Edge-Node Runtime Wire Contract + +## 계약 메타 + +- id: `iop.edge-node-runtime-wire` +- boundary: `inner` +- status: active +- 원본 경로: + - `proto/iop/runtime.proto` + - `apps/edge/internal/transport/server.go` + - `apps/node/internal/transport/client.go` + - `apps/node/internal/transport/session.go` + - `apps/node/internal/transport/parser.go` + - `apps/edge/internal/node/mapper.go` + - `apps/node/internal/adapters/config_set.go` +- human docs: + - `apps/edge/README.md` + - `apps/node/README.md` + +## 읽는 조건 + +- Edge-Node TCP/protobuf transport, register handshake, run stream, cancel, node command, node config refresh를 바꿀 때 +- `RunRequest`, `RunEvent`, `CancelRequest`, `NodeCommandRequest`, `NodeCommandResponse`, `NodeConfigPayload`, `NodeConfigRefresh*` 필드를 바꿀 때 +- node adapter 설정 payload나 runtime config가 Edge에서 Node로 전달되는 방식을 바꿀 때 + +## 범위 + +이 계약은 Edge와 Node 사이의 내부 TCP proto-socket 경계다. +Edge는 Node 연결을 수락하고, Node는 연결 직후 등록 요청을 보낸다. +실행 요청과 이벤트 스트림, 취소, 조회성 명령, 설정 refresh는 같은 내부 wire 계열에서 처리한다. + +## 주요 흐름 + +- register: Node가 `RegisterRequest`를 보내고 Edge가 `RegisterResponse`로 수락 여부와 `NodeConfigPayload`를 돌려준다. +- execution: Edge가 `RunRequest`를 보내고 Node가 `RunEvent` stream으로 실행 상태를 보낸다. +- cancel: Edge가 `CancelRequest`를 보내며 `CANCEL_RUN`과 `TERMINATE_SESSION`을 구분한다. +- command: Edge가 `NodeCommandRequest`를 보내고 Node가 `NodeCommandResponse`로 usage/capabilities/session/transport/provider 상태를 응답한다. +- refresh: Edge가 `NodeConfigRefreshRequest`로 새 config payload를 보내고 Node가 `NodeConfigRefreshResponse`로 적용/재시작 필요/실패를 응답한다. + +## 필드 의미 + +- `RunRequest.adapter`, `RunRequest.target`: 내부 실행 식별자다. 외부 OpenAI-compatible `model`은 Edge 입력 표면에서 이 둘로 변환되어야 한다. +- `RunRequest.workspace`: CLI agent route 같은 workspace-bound 실행의 작업 디렉터리다. +- `RunRequest.input`: adapter가 해석할 실행 입력이다. CLI 실행에서는 prompt 계열 입력으로 변환된다. +- `RunRequest.metadata`: caller-defined 실행 metadata다. workspace 자체는 별도 `workspace` 필드로 전달한다. +- `RunEvent.type`: `start`, `delta`, `complete`, `error`, `cancelled` 같은 실행 이벤트 종류다. +- `NodeCommandRequest.type`: 실행이 아닌 조회/제어성 명령이다. adapter execution 요청과 섞지 않는다. +- `NodeConfigPayload.adapters`: Edge가 Node에 내려주는 adapter instance 설정이다. +- `AdapterConfig.name`: node 내부 stable adapter instance identity다. 비어 있으면 legacy single-instance type 이름과 동등하다. +- `NodeRuntimeConfig.workspace_root`: node runtime/store/workspace 기준 경로다. OS별 경로를 섞어 쓰지 않는다. + +## 금지 사항 + +- Control Plane이나 Client가 Node에 직접 연결하거나 직접 스케줄링하는 계약을 만들지 않는다. +- 외부 API의 `model` 용어를 이 내부 경계의 대표 실행 식별자로 되살리지 않는다. +- `proto/gen/iop/*.pb.go` 생성물을 직접 수정하지 않는다. +- transport handler에서 console/HTTP/A2A 표면 응답을 직접 만들지 않는다. 표면별 변환은 Edge service/input 계층에 둔다. +- Node address, token, transport internals를 Control Plane status 계약으로 노출하지 않는다. + +## 변경 시 확인할 코드/테스트 + +- `proto/iop/runtime.proto` +- `apps/edge/internal/transport/*_test.go` +- `apps/node/internal/transport/*_test.go` +- `apps/edge/internal/node/mapper_test.go` +- `apps/node/internal/adapters/config_set_test.go` +- `apps/node/internal/adapters/adapters_blackbox_test.go` +- proto 변경 시 `make proto`, Client가 소비하면 `make proto-dart` diff --git a/agent-contract/outer/a2a-json-rpc-api.md b/agent-contract/outer/a2a-json-rpc-api.md new file mode 100644 index 0000000..c272b3a --- /dev/null +++ b/agent-contract/outer/a2a-json-rpc-api.md @@ -0,0 +1,63 @@ +# A2A JSON-RPC API Contract + +## 계약 메타 + +- id: `iop.a2a-json-rpc-api` +- boundary: `outer` +- status: active-mvp +- 원본 경로: + - `apps/edge/internal/input/a2a/types.go` + - `apps/edge/internal/input/a2a/server.go` + - `packages/go/config/config.go` + - `configs/edge.yaml` +- human docs: `apps/edge/README.md` + +## 읽는 조건 + +- Edge A2A HTTP 입력 표면, JSON-RPC, `message/send`, `tasks/get`, `tasks/cancel`을 다룰 때 +- 외부 agent 또는 다른 프로젝트가 Edge 실행 그룹에 작업을 위임하는 요청/응답을 바꿀 때 +- A2A task 상태, artifact, blocking/background 동작, bearer auth를 검토할 때 + +## 범위 + +이 계약은 Edge의 A2A JSON-RPC HTTP 입력 표면이다. +외부 caller는 JSON-RPC 2.0 envelope로 작업을 보내고, Edge는 내부 `adapter + target` 실행으로 변환한다. + +OpenAI-compatible API와 달리 A2A는 task 상태 공유와 agent-to-agent 작업 위임에 맞춘 표면이다. +내부 Edge-Node protobuf transport를 대체하지 않는다. + +## 최소 요청 형태 + +- endpoint: `POST `; 기본 path는 `/a2a` +- agent card: `GET /.well-known/agent.json` +- auth: `a2a.bearer_token`이 비어 있지 않으면 `Authorization: Bearer ` 필요 +- supported methods: `message/send`, `tasks/get`, `tasks/cancel` + +`message/send`의 최소 params는 `message.role`과 text `parts[]`다. +`configuration.blocking`은 생략 시 `true`로 동작한다. + +## 필드 의미 + +- `jsonrpc`: 반드시 `"2.0"`이어야 한다. +- `method`: 지원 method 중 하나다. +- `params.message.parts[].text`: 내부 실행 prompt로 추출되는 text다. +- `configuration.blocking`: `true` 또는 생략이면 완료까지 대기하고, `false`이면 working task를 즉시 반환한다. +- `Task.id`: Edge-local task id다. +- `Task.status.state`: 현재 MVP 값은 `working`, `completed`, `failed`, `canceled`다. +- `Artifact.parts`: 완료 결과 text를 담는 최소 artifact 표현이다. + +## 금지 사항 + +- A2A 요청에 특정 외부 제품 전용 wrapper field를 추가하지 않는다. +- A2A를 OpenAI-compatible chat/completions 대체 표면으로 만들지 않는다. +- Edge 내부 실행을 `model` 중심으로 표현하지 않는다. 입력 표면에서만 A2A Task/JSON-RPC 표현을 유지하고 내부는 `adapter + target`으로 변환한다. +- Node address, token, transport client 내부 상태를 A2A 응답에 노출하지 않는다. + +## 변경 시 확인할 코드/테스트 + +- `apps/edge/internal/input/a2a/types.go` +- `apps/edge/internal/input/a2a/server.go` +- `apps/edge/internal/input/a2a/server_test.go` +- `apps/edge/internal/input/a2a/task_store_test.go` +- `packages/go/config/config.go` +- `apps/edge/README.md` diff --git a/agent-contract/provided/openai-compatible-api.md b/agent-contract/outer/openai-compatible-api.md similarity index 96% rename from agent-contract/provided/openai-compatible-api.md rename to agent-contract/outer/openai-compatible-api.md index da3ba8f..deaf2fc 100644 --- a/agent-contract/provided/openai-compatible-api.md +++ b/agent-contract/outer/openai-compatible-api.md @@ -3,8 +3,15 @@ ## 계약 메타 - id: `iop.openai-compatible-api` -- provider: `iop` +- boundary: `outer` - status: active +- 원본 경로: + - `apps/edge/internal/openai/routes.go` + - `apps/edge/internal/openai/chat_handler.go` + - `apps/edge/internal/openai/responses_handler.go` + - `apps/edge/internal/openai/types.go` + - `packages/go/config/config.go` + - `configs/edge.yaml` - human docs: `docs/openai-compatible-api-contract.md` ## 범위 diff --git a/agent-ops/rules/common/rules.md b/agent-ops/rules/common/rules.md index 4335a24..258ee50 100644 --- a/agent-ops/rules/common/rules.md +++ b/agent-ops/rules/common/rules.md @@ -12,7 +12,7 @@ - `agent-ui/` 디렉터리가 있는 프로젝트에서도 `agent-ui/definition/archive/**`와 `agent-ui/archive/user-review/**`는 일반 작업에서 읽지 않는다. UI 과거 결정, 복원, 비교, 해결된 user review 확인이 필요한 경우에만 `agent-ops/rules/common/rules-agent-ui.md`의 archive 접근 규칙을 따른다. - agent-ops 구조, 규칙, 스킬, 로드맵, 런타임 책임 경계를 설계하거나 수정할 때만 `agent-ops/rules/common/philosophy.md`를 읽는다. - tracked `docs/`는 사람용 최신 가이드와 공개 설명만 둔다. -- 외부 API, 런타임 호출, 프로젝트 간 연동, 요청/응답 스키마 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. +- API, wire protocol, 런타임 호출, event/config schema, 프로젝트 간 또는 내부 프로세스/컴포넌트 간 요청/응답 계약을 확인해야 하는 작업은 `agent-contract/index.md` 파일이 있을 때만 세션 1회 읽고, 매칭되는 계약 문서만 읽는다. **세션 최초 1회 아래 파일을 순서대로 반드시 읽는다.** 파일이나 디렉터리가 없는 항목은 건너뛴다. 그외에 스킵은 금지한다. @@ -32,7 +32,7 @@ - skill 생성 - agent-ui 생성/갱신/검증/코드 동기화, UI 스캐폴드, 화면 정의서, view/component/frame/wireframe 정의, agent-ui USER_REVIEW - 테스트 룰 작성/생성/수정, 도메인별/검증 시나리오별 테스트 문서, create-test/update-test -- agent-contract 생성/갱신, 계약 문서 작성/정리, 제공/소비 계약 포인터 관리 +- 계약 생성/업데이트, agent-contract 생성/갱신, inner/outer 계약 문서 작성/정리, 계약 포인터 관리 - README 생성 - 핸즈오프 작성 / handoff / 인수인계 / 다른 세션에서 이어가기 - 로드맵/마일스톤 생성·갱신 diff --git a/agent-ops/rules/project/domain/client/rules.md b/agent-ops/rules/project/domain/client/rules.md index d26b644..7d0c3c3 100644 --- a/agent-ops/rules/project/domain/client/rules.md +++ b/agent-ops/rules/project/domain/client/rules.md @@ -57,6 +57,7 @@ IOP의 공식 Flutter client UI/UX 영역이다. Control Plane HTTP/WS endpoint - Client는 Control Plane을 통해 Edge/Node 운영 상태를 조회한다. Client에서 Edge-Node TCP transport나 Node execution 경로에 직접 붙지 않는다. - Client-Control Plane native 경계는 `/client` WebSocket proto-socket과 `ClientHelloRequest`/`ClientHelloResponse` baseline을 따른다. +- Client-Control Plane wire 상세는 `agent-contract/inner/client-control-plane-wire.md`를 기준으로 확인한다. - Control Plane URL은 `IOP_CONTROL_PLANE_HTTP_URL`, `IOP_CONTROL_PLANE_WIRE_URL` `--dart-define`으로 주입한다. 실제 환경값이나 private endpoint를 tracked source에 고정하지 않는다. - Dart protobuf binding은 `proto/iop/*.proto`에서 생성한다. proto 계약 변경 시 `make proto-dart` 산출물과 Go 생성물 갱신 여부를 함께 확인한다. - `apps/client/lib/gen/proto/iop/*.dart` 생성물은 사람이 직접 수정하지 않는다. diff --git a/agent-ops/rules/project/domain/control-plane/rules.md b/agent-ops/rules/project/domain/control-plane/rules.md index 32da936..c490f44 100644 --- a/agent-ops/rules/project/domain/control-plane/rules.md +++ b/agent-ops/rules/project/domain/control-plane/rules.md @@ -52,6 +52,7 @@ last_rule_updated_at: 2026-06-03 - `net/http`는 health/readiness와 단순 조회성 status endpoint에 우선 사용하고, IOP 고유 양방향 운영 통신은 proto-socket 기반 wire protocol로 확장한다. - 브라우저/앱 경계는 WebSocket/WSS proto-socket을 사용할 수 있다. Edge-Node TCP transport 기준을 이 경계에 억지로 적용하지 않는다. - Control Plane-Edge native wire는 Edge가 outbound로 연결하는 TCP proto-socket 경계로 둔다. Client WebSocket listener와 Edge TCP listener를 혼동하지 않는다. +- Control Plane-Edge wire 상세는 `agent-contract/inner/control-plane-edge-wire.md`, Client-Control Plane wire 상세는 `agent-contract/inner/client-control-plane-wire.md`를 기준으로 확인한다. - Edge registry는 현재 in-memory connection/control view이다. durable history, audit, 정책 저장소를 이 registry에 섞지 않는다. - Edge status 조회는 Edge가 보고한 `EdgeStatusResponse`를 관찰한다. Control Plane에서 Node address, token, transport internals, Edge 설정 원본을 직접 소유하지 않는다. - `ScheduleRequest`/`ScheduleResponse`는 legacy placeholder로만 취급하고, 새 orchestration 계약은 Edge-owned runtime state를 우회하지 않도록 다시 설계한다. diff --git a/agent-ops/rules/project/domain/edge/rules.md b/agent-ops/rules/project/domain/edge/rules.md index d50c0d2..d552750 100644 --- a/agent-ops/rules/project/domain/edge/rules.md +++ b/agent-ops/rules/project/domain/edge/rules.md @@ -85,6 +85,7 @@ last_rule_updated_at: 2026-06-21 - OpenAI-compatible 경계의 `model`과 A2A 경계의 `Task`/JSON-RPC 표현은 입력 표면 안에서만 유지하고, edge 내부 실행은 `service.SubmitRun()`의 `adapter + target` 요청으로 변환한다. - OpenAI-compatible `/v1/models`는 `openai.models`를 우선하고, 없으면 `openai.target`을 advertised model로 사용한다. 내부 target override와 외부 model echo 정책을 혼동하지 않는다. - OpenAI/Ollama passthrough성 옵션은 입력 표면에서 명시적으로 변환하고, node adapter의 Ollama 실행 계약을 우회하지 않는다. +- OpenAI-compatible, A2A, Edge-Node, Control Plane connector, config/runtime refresh 계약 상세는 `agent-contract/index.md`에서 매칭 문서를 확인하고 README/rules에 schema 본문을 반복하지 않는다. - run/node event fanout은 `events.Bus`를 통해 수행하고, transport handler에서 console/HTTP 표면으로 직접 출력하거나 응답하지 않는다. - 입력 서버 lifecycle은 `input.Manager`가 소유하며, bootstrap runtime이 transport server와 함께 시작/종료한다. - Control Plane connector는 disabled 설정 또는 빈 `wire_addr`에서 no-op이어야 한다. 연결 재시도와 stop은 Edge serve lifecycle에 묶으며, Control Plane attachment 변경이 Edge-owned 설정/상태의 소유권을 바꾸지 않는다. diff --git a/agent-ops/rules/project/domain/node/rules.md b/agent-ops/rules/project/domain/node/rules.md index 8ea54f9..3945476 100644 --- a/agent-ops/rules/project/domain/node/rules.md +++ b/agent-ops/rules/project/domain/node/rules.md @@ -58,6 +58,7 @@ Edge에 연결되어 실제 adapter execution을 수행하는 IOP 노드 에이 - `runtime` 패키지에는 도메인 타입과 인터페이스를 두고 구체 구현 의존성을 넣지 않는다. - transport/proto 타입은 `node.Node` 경계에서 runtime 타입으로 변환한다. - 내부 실행 식별자는 `adapter + target`을 사용한다. 외부 OpenAI-compatible API나 legacy placeholder를 제외하고 `model`을 내부 실행 대표 용어로 되돌리지 않는다. +- Edge-Node runtime wire와 Edge가 내려주는 config payload 계약 상세는 `agent-contract/inner/edge-node-runtime-wire.md`와 `agent-contract/inner/edge-config-runtime-refresh.md`를 기준으로 확인한다. - 어댑터 추가 시 `runtime.Adapter`를 구현하고 `adapters.BuildFromPayload()` 또는 bootstrap registry에 등록한다. - field Node의 기본 시작 경로는 Edge bootstrap script가 만든 최소 config와 Edge가 RegisterResponse로 내려주는 adapter/runtime payload다. 사용자가 기본 경로에서 node config를 직접 작성하거나 adapter/provider 세부값을 명령줄에 넣는 흐름을 만들지 않는다. - Node runtime 작업 디렉터리나 store/workspace 경로는 대상 OS에서 쓰기 가능한 기본값이어야 한다. Edge가 특정 node에 `workspace_root`를 내려줄 때 macOS/dev host 절대 경로(`/Users/...`) 같은 값을 Linux/Windows node에 재사용하지 않으며, OS별 경로가 필요하면 Edge 설정에 미리 굽는다. diff --git a/agent-ops/rules/project/domain/platform-common/rules.md b/agent-ops/rules/project/domain/platform-common/rules.md index eb71397..fa41676 100644 --- a/agent-ops/rules/project/domain/platform-common/rules.md +++ b/agent-ops/rules/project/domain/platform-common/rules.md @@ -52,6 +52,7 @@ last_rule_updated_at: 2026-06-01 - `ClientHelloRequest` / `ClientHelloResponse` — Client-Control Plane hello baseline 계약 - `EdgeHelloRequest` / `EdgeHelloResponse` — Edge가 Control Plane으로 연결할 때 쓰는 hello baseline 계약 - `EdgeStatusRequest` / `EdgeStatusResponse` / `EdgeNodeSnapshot` — Control Plane이 Edge-owned node snapshot을 조회하는 wire 계약 +- 상세 계약 라우팅은 `agent-contract/index.md`를 따르고, schema 원본은 `proto/iop/*.proto`와 `packages/go/config/config.go`를 우선한다. ## 유지할 패턴 @@ -61,6 +62,7 @@ last_rule_updated_at: 2026-06-01 - protobuf 계약 변경은 `proto/iop/*.proto`에서 시작하고 `make proto`로 Go 생성물을 갱신한다. - Client가 소비하는 proto 계약을 변경하면 `make proto-dart`로 `apps/client/lib/gen/proto/iop/*.dart` 생성물도 갱신한다. - 생성 파일(`proto/gen/iop/*.pb.go`)은 사람이 직접 편집하지 않는다. +- Edge-Node, Control Plane-Edge, Client-Control Plane, config/runtime refresh 계약 상세는 `agent-contract/inner/**` 문서를 기준으로 확인하고 domain rule에는 소유권과 금지 사항만 둔다. - 공통 패키지는 작고 명확한 계약을 유지하고 앱별 정책을 과도하게 끌어올리지 않는다. - 공통 event helper는 envelope 생성과 상수 정의까지만 담당하고, edge 내부 fanout/replay/store 정책은 edge 도메인에 둔다. - `RunRequest`, `ExecutionSpec`, `NodeCommandRequest`, `CLIProfileConfig`, job/history 계열 계약을 변경할 때 내부 실행 용어는 `target`을 우선하고, `model`은 외부 호환 경계인지 확인한다. diff --git a/agent-ops/skills/common/agent-contract/SKILL.md b/agent-ops/skills/common/agent-contract/SKILL.md deleted file mode 100644 index 82a8bbd..0000000 --- a/agent-ops/skills/common/agent-contract/SKILL.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -name: agent-contract -version: 1.0.0 -description: agent-contract index와 제공/소비 계약 문서를 생성하거나 갱신한다. ---- - -# agent-contract - -## 목적 - -프로젝트 간 API, 런타임 호출, 요청/응답 스키마 계약을 `agent-contract/` 구조로 관리한다. -계약 원문을 한 곳에 두고, README/docs/rules에는 라우팅 포인터만 남긴다. - -## 언제 호출할지 - -- 외부 프로젝트가 참조할 API 또는 런타임 계약을 생성하거나 갱신할 때 -- 다른 프로젝트의 계약을 소비 계약으로 등록할 때 -- `agent-contract/index.md`의 제공/소비 계약 라우팅을 정리할 때 -- 계약 원문을 수정한 뒤 index, README, docs 포인터와 정합성을 확인할 때 - -## 입력 - -- `contract-id`: 계약 식별자, 예: `billing.public-api` 또는 `auth.session-events` (필수) -- `mode`: `provided` 또는 `consumed` (필수) -- `contract-path`: 계약 원문 경로 또는 외부 source 경로 (필수) -- `trigger-conditions`: 계약 문서를 읽어야 하는 조건 목록 (필수) - -## 먼저 확인할 것 - -- [ ] `agent-contract/index.md`가 있는지 확인하고, 없으면 최초 생성 대상으로 본다. -- [ ] 동일 `contract-id`가 이미 제공 또는 소비 계약에 있는지 확인한다. -- [ ] 계약 원문이 `docs/`, `README`, `rules.md`에 중복 복제되어 있지 않은지 확인한다. -- [ ] agent-ops 공통 규칙에는 특정 계약명이 아니라 `agent-contract/index.md` 조건부 진입 규칙만 있는지 확인한다. - -## 실행 절차 - -1. **초기 구조 확인** - - `agent-contract/index.md`가 없으면 생성한다. - - `agent-contract/provided/`가 없으면 생성한다. - - 소비 계약 원문을 저장하지 않는 한 `agent-contract/consumed/`는 만들지 않는다. - - index에는 읽기 규칙, 제공 계약 표, 소비 계약 표를 둔다. - -2. **계약 위치 결정** - - 제공 계약은 `agent-contract/provided/.md`에 둔다. - - 소비 계약은 `agent-contract/index.md`의 소비 계약 표에 외부 source만 둔다. - - 소비 계약 원문을 현재 프로젝트에 복제하지 않는다. - -3. **index 갱신** - - `agent-contract/index.md`의 읽기 규칙을 유지한다. - - 제공 계약 표는 `id`, `읽는 조건`, `path` 열을 유지한다. - - 소비 계약 표는 `id`, `읽는 조건`, `source` 열을 유지한다. - - 제공 계약 또는 소비 계약 표에 `id`, 읽는 조건, 경로를 추가하거나 갱신한다. - - 매칭 조건은 agent가 판단할 수 있는 API 이름, field 이름, runtime 이름, protocol 이름을 포함한다. - -4. **계약 원문 갱신** - - 계약 원문에는 범위, 최소 요청/응답 형태, 필드 의미, 금지 사항, 구현 메모를 둔다. - - 사람용 설명 문서에는 계약 원문을 복제하지 않고 링크만 둔다. - - 기존 계약을 수정할 때는 index의 읽는 조건과 path/source가 수정 후 계약 원문과 여전히 맞는지 확인한다. - -5. **읽기 흐름 확인** - - 계약 확인 작업은 common rule이 `agent-contract/index.md`를 조건부로 읽고, index가 매칭 계약 원문으로 라우팅한다. - - 읽기 전용 작업에서는 계약 원문이나 index를 수정하지 않는다. - - 매칭 계약이 없으면 계약을 추정하지 않고 사용자에게 확인한다. - -6. **라우팅 문서 갱신** - - README/docs/rules에는 계약 원문 경로만 남긴다. - - common rule에는 특정 계약 id나 프로젝트명을 넣지 않는다. - - project rule에는 해당 프로젝트 고유 코드/도메인 규칙만 두고 agent-contract 공통 라우팅을 반복하지 않는다. - -7. **결과 보고** - - 변경한 계약 index와 원문 경로를 보고한다. - - 중복 제거한 문서와 남긴 포인터를 보고한다. - -## 실행 결과 검증 - -- [ ] `agent-contract/index.md`가 계약 id와 경로를 포함하는가 -- [ ] `agent-contract/index.md`가 없던 프로젝트에서는 읽기 규칙, 제공 계약 표, 소비 계약 표가 생성되었는가 -- [ ] 제공 계약 원문이 `agent-contract/provided/` 아래에 있는가 -- [ ] 소비 계약 원문을 복제하지 않았는가 -- [ ] 소비 계약은 `source`만 가리키는가 -- [ ] 수정된 계약의 index 조건과 path/source가 계약 원문과 일치하는가 -- [ ] README/docs/rules가 계약 본문을 반복하지 않고 원문 경로만 가리키는가 -- [ ] common rule에 특정 계약명이 들어가지 않았는가 -- [ ] project rule에 agent-contract 공통 라우팅을 반복하지 않았는가 -- 검증 실패 시: 계약 원문을 한 곳으로 모으고 나머지 문서는 포인터로 축소한다. - -## 출력 형식 - -```text -계약 정리 완료 - -- index: agent-contract/index.md -- contract: agent-contract/provided/.md -- pointers: <갱신한 README/docs/rules 경로> -``` - -## 금지 사항 - -- 같은 계약 본문을 `docs/`, `README`, `rules.md`에 복제하지 않는다. -- common rule에 특정 계약 id, 특정 프로젝트명, 특정 API 이름을 추가하지 않는다. -- 소비 계약 원문을 현재 프로젝트에 복사하지 않는다. -- 계약과 무관한 코드나 로드맵 상태를 함께 수정하지 않는다. diff --git a/agent-ops/skills/common/create-contract/SKILL.md b/agent-ops/skills/common/create-contract/SKILL.md new file mode 100644 index 0000000..799dc3f --- /dev/null +++ b/agent-ops/skills/common/create-contract/SKILL.md @@ -0,0 +1,121 @@ +--- +name: create-contract +version: 1.0.0 +description: agent-contract 구조와 inner/outer 계약 문서를 생성한다. 계약 생성해, 프로젝트 계약 생성해, contract 생성, agent-contract 생성, inner/outer 계약 생성 요청에서 사용한다. +--- + +# create-contract + +## 목적 + +프로젝트에 계약 관리가 필요해진 시점에 `agent-contract/` 구조를 생성하고, 흩어진 문서와 코드에서 확인한 계약을 `inner/outer` 기준으로 정리한다. +계약 문서는 schema 원본을 복제하지 않고, agent가 읽을 수 있는 라우팅, 원본 경로, 필드 의미, 변경 규칙, 검증 포인터를 한 곳에 모은다. + +## 언제 호출할지 + +- 사용자가 계약 생성, 프로젝트 계약 생성, contract 생성, agent-contract 생성을 요청할 때 +- API, runtime 호출, wire protocol, event/config schema 같은 계약을 처음 문서화할 때 +- 프로젝트에 `agent-contract/`가 없고, 둘 이상의 프로젝트/프로세스/앱/도메인이 맞춰야 하는 요청/응답 경계가 확인될 때 +- 기존 README/docs/rules/code에 흩어진 계약 설명을 새 계약 구조로 모아야 할 때 + +## 입력 + +- `contract-id`: 계약 식별자, kebab-case 또는 dotted id (선택, 없으면 분석으로 후보 산출) +- `boundary`: `inner` 또는 `outer` (선택, 없으면 실제 소비자와 경계로 판정) +- `scope`: 계약 범위 요약. 예: public HTTP API, worker-runtime protocol, app-server wire (선택, 없으면 코드/문서에서 산출) +- `canonical-path`: proto/OpenAPI/config/code 등 schema 원본 경로 (선택, 없으면 분석으로 찾음) +- `trigger-conditions`: 계약 문서를 읽어야 하는 조건 목록 (선택) + +## 분류 기준 + +- `outer`: 프로젝트 바깥 caller나 다른 프로젝트가 직접 맞춰야 하는 계약이다. 예: 공개 HTTP API, webhook, 외부 SDK, 외부 agent handoff. +- `inner`: 같은 프로젝트 안이어도 프로세스, 앱, 도메인, runtime 경계를 넘는 계약이다. 예: controller-worker proto, service-service wire, app-server WebSocket, runtime request/event/config schema. +- 제외: 한 패키지 내부 private interface, 코드만 보면 충분한 DTO, 안정화되지 않은 실험 구조, 단일 구현 내부 helper. + +## 먼저 확인할 것 + +- [ ] `agent-contract/` 존재 여부를 확인한다. +- [ ] `agent-contract/index.md`가 있으면 읽고 기존 구조와 중복 id를 확인한다. +- [ ] 요청 범위와 관련된 코드, proto, config, README/docs/rules를 읽어 원본 경로와 흩어진 계약 설명을 찾는다. +- [ ] 계약 원문을 이미 docs/README/rules에 길게 복제하고 있는지 확인한다. + +## 실행 절차 + +1. **필요성 판정** + - 둘 이상의 프로젝트/프로세스/앱/도메인이 맞춰야 하는 안정 경계인지 확인한다. + - 단일 패키지 내부 구현이면 계약 문서를 만들지 않고 이유를 보고한다. + - 단건 `contract-id`가 없으면 코드와 문서에서 계약 후보를 수집하고, 안정 경계가 확인된 후보만 생성한다. + - 후보는 있지만 boundary나 원본 경로가 불명확하면 문서를 억지로 만들지 않고 `확인 필요`로 보고한다. + +2. **구조 생성** + - `agent-contract/index.md`가 없으면 생성한다. + - `agent-contract/inner/`와 `agent-contract/outer/`가 없으면 생성한다. + - legacy `provided/consumed/`가 있으면 덮어쓰지 않고, 이번 생성 결과와 충돌하는지 보고한다. + +3. **코드와 문서 분석** + - 관련 schema 원본을 먼저 찾는다. 우선순위는 proto/OpenAPI/schema 파일, config struct, public DTO/interface, handler/parser, 테스트 fixture 순서다. + - README/docs/rules에 흩어진 계약 설명을 찾고, 계약 문서에 필요한 내용만 추린다. + - 필드 의미는 코드와 테스트에서 확인한 것만 쓴다. 추측은 `확인 필요`로 남긴다. + +4. **계약 문서 작성** + - 경로는 `agent-contract//.md`로 둔다. + - 여러 계약을 생성해야 하면 각 문서는 독립된 경계 단위로 나누고, 공통 설명은 index가 아니라 각 계약의 원본 경로 포인터로 해결한다. + - 문서는 짧게 유지하고 다음 항목을 포함한다. + - 계약 메타: id, boundary, 원본 경로, status(필요한 경우) + - 읽는 조건 + - 범위와 비범위 + - 최소 요청/응답 또는 message/event 형태 + - 필드 의미와 금지 사항 + - 변경 시 확인할 코드/테스트 + - 원본 schema 전체를 복제하지 않는다. 긴 schema는 원본 경로와 핵심 필드 의미만 둔다. + +5. **index 갱신** + - `Outer Contracts`와 `Inner Contracts` 섹션을 둔다. + - outer/inner 표는 `id`, `읽는 조건`, `원본 경로`, `path`를 둔다. + - 매칭 조건은 agent가 검색/판단할 수 있는 API 이름, message 이름, field 이름, runtime 이름, protocol 이름을 포함한다. + - 프로젝트 전용 path trigger는 공통 rule이 아니라 `agent-contract/index.md`의 `읽는 조건`/`원본 경로` 또는 project/domain rule 포인터로 둔다. + +6. **흩어진 문서 정리** + - README/docs/rules에 계약 본문이 중복되어 있으면 원문 경로 포인터로 줄인다. + - domain rule에는 소유권, 경계, 금지 사항만 남기고 상세 schema는 계약 문서 또는 원본 경로를 가리킨다. + - common rule에는 특정 프로젝트 경로, 계약 id, API 이름을 추가하지 않는다. common rule은 `agent-contract/index.md` 조건부 진입까지만 담당한다. + - 사람용 최신 가이드가 필요한 README 문구는 유지하되 계약 원문과 충돌하지 않게 축소한다. + +7. **결과 보고** + - 생성한 index와 계약 문서 + - boundary 판정 근거 + - 원본 경로 + - 중복 제거 또는 포인터화한 문서 + - 확인 필요 항목 + +## 실행 결과 검증 + +- [ ] `agent-contract/index.md`가 생성되고 inner/outer 라우팅 표를 포함하는가 +- [ ] 계약 문서가 `agent-contract/inner/` 또는 `agent-contract/outer/` 아래에 있는가 +- [ ] 계약 id가 index와 문서 메타에서 일치하는가 +- [ ] 원본 경로가 실제 존재하거나 외부 원본으로 명확히 적혀 있는가 +- [ ] README/docs/rules에 계약 본문이 중복 복제되지 않고 포인터만 남았는가 +- [ ] 코드/proto/config/test 분석 없이 계약을 추정하지 않았는가 +- 검증 실패 시: 누락된 index, 문서 메타, 포인터, 원본 경로만 보완한다. + +## 출력 형식 + +```md +## 계약 생성 완료 + +- index: agent-contract/index.md +- contracts: agent-contract//.md +- boundary: (<근거>) +- 원본 경로: +- pointers: <갱신한 README/docs/rules 경로 또는 없음> +- 확인 필요: <항목 또는 없음> +``` + +## 금지 사항 + +- 모든 내부 interface를 계약 문서로 만들지 않는다. +- 원본 schema 전체를 계약 문서에 장황하게 복제하지 않는다. +- 코드/proto/config/test 확인 없이 필드 의미를 단정하지 않는다. +- README/docs/rules에 계약 본문을 계속 중복 유지하지 않는다. +- 프로젝트 전용 path trigger를 common rule에 넣지 않는다. +- legacy `provided/consumed/` 구조가 있어도 사용자 요청 없이 대량 이동하지 않는다. diff --git a/agent-ops/skills/common/router.md b/agent-ops/skills/common/router.md index 3f617d1..8ace4fd 100644 --- a/agent-ops/skills/common/router.md +++ b/agent-ops/skills/common/router.md @@ -18,7 +18,8 @@ | agent-ui와 코드 동기화, agent-ui와 코드 전체 동기화, 화면정의서대로 코드 반영, 화면 정의서 변경사항 구현, wireframe 변경사항 구현 | `agent-ops/skills/common/sync-agent-ui/SKILL.md` | | create-test, 테스트 룰 작성, 테스트 룰 생성, 테스트 규칙 작성, 테스트 규칙 생성, 테스트 환경 생성, 상황별 테스트 문서 생성, 도메인별 테스트 문서 생성, 검증 시나리오별 테스트 문서 생성, test rule 생성, agent-test 생성 | `agent-ops/skills/common/create-test/SKILL.md` | | update-test, 테스트 룰 수정, 테스트 룰 갱신, 테스트 규칙 수정, 테스트 규칙 갱신, 테스트 환경 수정, 상황별 테스트 문서 수정, 도메인별 테스트 문서 수정, 검증 시나리오별 테스트 문서 수정, test rule 수정, agent-test 수정 | `agent-ops/skills/common/update-test/SKILL.md` | -| agent-contract 생성, agent-contract 갱신, 계약 문서 작성, 계약 문서 정리, 제공 계약 추가, 소비 계약 추가, 외부 계약 포인터 관리 | `agent-ops/skills/common/agent-contract/SKILL.md` | +| 계약 생성해, 프로젝트 계약 생성해, 프로젝트 계약 생성, contract 생성, agent-contract 생성, 계약 문서 생성, inner 계약 생성, outer 계약 생성 | `agent-ops/skills/common/create-contract/SKILL.md` | +| 계약 업데이트해, 프로젝트 계약 업데이트해, 프로젝트 계약 업데이트, 계약 갱신해, 계약 갱신, 계약 수정, 계약 정리, contract update, agent-contract 갱신, inner 계약 갱신, outer 계약 갱신 | `agent-ops/skills/common/update-contract/SKILL.md` | | README 작성해줘, README 만들어줘, 프로젝트 설명 문서 만들어줘 | `agent-ops/skills/common/create-readme/SKILL.md` | | 핸즈오프 남겨, handoff 작성, 인수인계 작성, 다른 세션에서 이어가게 정리, 작업을 이어받도록 기록 | `agent-ops/skills/common/create-handoff/SKILL.md` | | 로드맵 만들어줘, roadmap 생성, 마일스톤 설계, goal/phase 구조 잡아줘 | `agent-ops/skills/common/create-roadmap/SKILL.md` | diff --git a/agent-ops/skills/common/update-contract/SKILL.md b/agent-ops/skills/common/update-contract/SKILL.md new file mode 100644 index 0000000..caec6b2 --- /dev/null +++ b/agent-ops/skills/common/update-contract/SKILL.md @@ -0,0 +1,111 @@ +--- +name: update-contract +version: 1.0.0 +description: agent-contract inner/outer 계약 문서를 갱신하고 흩어진 계약 설명을 정리한다. 계약 업데이트해, 프로젝트 계약 업데이트해, 계약 갱신/수정/정리, contract update 요청에서 사용한다. +--- + +# update-contract + +## 목적 + +기존 `agent-contract/`의 inner/outer 계약 문서를 최신 코드와 문서 기준으로 갱신한다. +계약 원문은 한 곳에 모으고, README/docs/rules에는 포인터와 경계 규칙만 남긴다. + +## 언제 호출할지 + +- 사용자가 계약 업데이트, 프로젝트 계약 업데이트, 계약 갱신, 계약 수정, 계약 정리를 요청할 때 +- API, runtime 호출, wire protocol, event/config schema 변경이 기존 계약에 영향을 줄 때 +- 계약 설명이 README/docs/rules/code review 과정에서 다시 흩어진 것을 정리할 때 +- legacy `provided/consumed` 계약을 `inner/outer` 모델로 점진 정리할 때 + +## 입력 + +- `contract-id`: 갱신할 계약 식별자 (선택, 없으면 index와 변경 diff에서 탐색) +- `change`: 바뀐 내용 또는 정리할 문제 요약 (선택, 없으면 최근 변경/요청 맥락에서 산출) +- `boundary`: `inner` 또는 `outer` (선택, 기존 문서 우선) +- `canonical-path`: 갱신 기준이 되는 proto/OpenAPI/config/code 원본 경로 (선택) + +## 먼저 확인할 것 + +- [ ] `agent-contract/index.md` 존재 여부를 확인한다. 없으면 create-contract 흐름으로 전환할지 판단한다. +- [ ] index에서 대상 계약 문서를 찾는다. 없으면 새 계약 생성 대상인지 판단한다. +- [ ] 대상 계약 문서와 원본 경로를 읽는다. +- [ ] 변경 범위와 관련된 코드, proto, config, 테스트를 읽어 실제 동작을 확인한다. +- [ ] README/docs/rules에 계약 본문이 새로 중복 작성되었는지 검색한다. +- [ ] legacy `provided/consumed/` 구조가 남아 있으면 현재 요청이 구조 migration인지 단순 계약 갱신인지 구분한다. + +## 실행 절차 + +1. **대상 확정** + - index의 `Outer Contracts`/`Inner Contracts`에서 계약을 찾는다. + - `contract-id`가 없으면 요청 키워드, 변경 파일, 코드 diff, README/docs/rules의 계약 설명을 기준으로 영향을 받는 계약을 좁힌다. + - legacy index만 있으면 `provided`는 outer 후보, 프로젝트 내부 runtime/wire 계약은 inner 후보로 분류하되 즉시 이동하지 말고 변경 범위와 함께 판단한다. + - 대상이 없고 요청이 계약 생성/정리까지 허용하면 create-contract 흐름으로 전환한다. + - 대상이 없고 사용자가 특정 기존 계약 갱신만 요청했다면 대상 부재를 보고한다. + +2. **코드 우선 분석** + - 원본 경로를 먼저 확인한다. + - 실제 parser/handler/DTO/interface/test에서 필드 의미와 허용/거부 동작을 확인한다. + - 문서와 코드가 다르면 코드를 근거로 계약 문서를 갱신하고, 코드가 틀렸을 가능성이 있으면 사용자에게 후보를 제시한다. + +3. **계약 문서 갱신** + - 필드 의미, 금지 사항, 읽는 조건, 변경 시 테스트를 최신 상태로 맞춘다. + - schema 원본 전체를 복제하지 않고 핵심 의미와 원본 경로를 유지한다. + - 불확실한 값은 단정하지 않고 `확인 필요`로 남긴다. + - `last updated` 같은 날짜 메타가 이미 있는 문서에서만 갱신한다. 없는 문서에 날짜 관례를 새로 만들지 않는다. + +4. **index 갱신** + - 읽는 조건이 새 API/field/message/protocol 이름을 포함하는지 확인한다. + - path, 원본 경로, boundary가 실제 문서와 일치하는지 확인한다. + - 중복 id, dead path, 존재하지 않는 원본 경로를 제거하거나 수정한다. + - 프로젝트 전용 path trigger가 필요하면 `agent-contract/index.md` 또는 project/domain rule 포인터에 둔다. common rule에는 넣지 않는다. + +5. **흩어진 문서 정리** + - README/docs/rules에 계약 본문이 들어간 경우 계약 문서 포인터로 축소한다. + - domain rule에는 책임 경계와 금지 사항만 남기고 상세 요청/응답 schema를 반복하지 않는다. + - 테스트 문서에는 검증 기준만 남기고 계약 본문을 복제하지 않는다. + - common rule에 특정 프로젝트 경로, 계약 id, API 이름이 새로 들어갔으면 제거하고 프로젝트 문서로 옮긴다. + +6. **검증 판단** + - 계약 문서만 바꿨으면 링크/path/index 정합성을 확인한다. + - 원본 schema 또는 runtime 코드를 함께 바꿨으면 해당 domain/test rule의 검증 기준을 따른다. + - proto/config schema를 바꿨으면 생성물 갱신 명령과 관련 테스트를 실행한다. + +7. **결과 보고** + - 수정한 계약 문서와 index + - 코드 분석 근거 + - 중복 제거한 문서 + - 실행한 검증 + - 남은 확인 필요 항목 + +## 실행 결과 검증 + +- [ ] index가 대상 계약의 최신 path와 읽는 조건을 가리키는가 +- [ ] 계약 문서의 원본 경로가 실제 코드/proto/config와 맞는가 +- [ ] README/docs/rules에 같은 계약 본문이 중복 남아 있지 않은가 +- [ ] inner/outer boundary가 계약의 실제 소비자와 맞는가 +- [ ] 코드 분석 없이 문서만 추측해 갱신하지 않았는가 +- [ ] 변경 범위에 필요한 테스트 또는 링크 검증을 실행했는가 +- 검증 실패 시: index/path/원본 경로/중복 문서/테스트 누락을 보완한다. + +## 출력 형식 + +```md +## 계약 업데이트 완료 + +- contract: agent-contract//.md +- index: agent-contract/index.md +- code evidence: <확인한 코드/proto/config/test> +- pointers: <갱신한 README/docs/rules 경로 또는 없음> +- verification: <실행한 명령 또는 생략 사유> +- 확인 필요: <항목 또는 없음> +``` + +## 금지 사항 + +- 코드와 원본 경로를 확인하지 않고 계약 문서만 고치지 않는다. +- README/docs/rules에 계약 본문을 새로 복제하지 않는다. +- 프로젝트 전용 path trigger를 common rule에 넣지 않는다. +- 사용자 요청 없이 전체 계약 구조를 대량 migration하지 않는다. +- 한 패키지 내부 구현 세부를 inner 계약으로 승격하지 않는다. +- 계약 갱신과 무관한 리팩터링을 함께 수행하지 않는다. diff --git a/agent-roadmap/phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md b/agent-roadmap/phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md index ba4953f..08d349e 100644 --- a/agent-roadmap/phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md +++ b/agent-roadmap/phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md @@ -102,7 +102,7 @@ CLI provider agent와 목적별 agent group, 예약어 설정을 runtime이 해 ## 작업 컨텍스트 -- 관련 경로: `agent-contract/provided/openai-compatible-api.md`, `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/adapters/cli`, `packages/go/config`, `configs`, `apps/edge/README.md` +- 관련 경로: `agent-contract/outer/openai-compatible-api.md`, `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/adapters/cli`, `packages/go/config`, `configs`, `apps/edge/README.md` - 표준선(선택): 내부 실행 개념은 `adapter + target`을 유지하고, OpenAI-compatible 경계의 agent group routing 문맥은 `metadata.agent_group` 아래에 둔다. 파일명은 routing 계약의 source of truth이며 prefix/lane/grade 중복 metadata는 만들지 않는다. - 선행 작업: CLI Automation Runtime 안정화, OpenAI Responses Input Surface, OpenAI Workspace Agent Execution Contract - 후속 작업: CLI Agent 사용량 알림과 자동 이어받기 MVP, 운영 관측과 Provider 관리의 provider quota/usage 고도화 diff --git a/agent-roadmap/phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md b/agent-roadmap/phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md index 4c889ed..9f157f4 100644 --- a/agent-roadmap/phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md +++ b/agent-roadmap/phase/automation-runtime-bridge/milestones/remote-workspace-operations-environment.md @@ -65,7 +65,7 @@ CLI Agent와 workspace-bound execution을 이용해 원격 코딩 환경과 원 ## 작업 컨텍스트 -- 관련 경로: `apps/edge`, `apps/node`, `apps/control-plane`, `apps/client`, `agent-contract/provided/openai-compatible-api.md` +- 관련 경로: `apps/edge`, `apps/node`, `apps/control-plane`, `apps/client`, `agent-contract/outer/openai-compatible-api.md` - 표준선(선택): 외부 실행 호출은 OpenAI-compatible shape와 `metadata.workspace`를 유지하고, lifecycle/artifact/approval은 IOP native 운영 표면에서 다룬다. - 선행 작업: OpenAI Workspace Agent Execution Contract - 후속 작업: 원격 터미널/CLI 터널링 POC, 정책/이력/감사 diff --git a/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md index 9d472e8..6f8146b 100644 --- a/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md +++ b/agent-roadmap/phase/knowledge-tool-optimization-extension/milestones/knowledge-tool-validation-optimization.md @@ -68,7 +68,7 @@ ## 작업 컨텍스트 -- 관련 경로: `apps/edge`, `apps/node`, `apps/control-plane`, `packages/go/policy`, `packages/go/jobs`, `proto/iop`, `agent-contract/provided/openai-compatible-api.md` +- 관련 경로: `apps/edge`, `apps/node`, `apps/control-plane`, `packages/go/policy`, `packages/go/jobs`, `proto/iop`, `agent-contract/outer/openai-compatible-api.md` - 표준선(선택): 외부 실행 호출 계약은 OpenAI-compatible shape를 우선 유지하고, IOP 고유 문맥은 `metadata`나 IOP native endpoint의 명시 필드로 전달한다. - 표준선(선택): 단계 호출은 단순 provider 라우팅과 충돌하는 책임이 아니라, 사용자가 선택할 수 있는 IOP 실행 모드 후보로 본다. - 선행 작업: Edge 모델 그룹 Queue 스케줄링 전환, 운영 관측과 Provider 관리 diff --git a/agent-roadmap/sdd/automation-runtime-bridge/cli-agent-group-grade-routing/SDD.md b/agent-roadmap/sdd/automation-runtime-bridge/cli-agent-group-grade-routing/SDD.md index 63db1f4..546586e 100644 --- a/agent-roadmap/sdd/automation-runtime-bridge/cli-agent-group-grade-routing/SDD.md +++ b/agent-roadmap/sdd/automation-runtime-bridge/cli-agent-group-grade-routing/SDD.md @@ -30,7 +30,7 @@ | 영역 | 기준 | 메모 | |------|------|------| | Roadmap | `agent-roadmap/phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md` | 목표, 기능 Task, 잠금 항목, 범위 제외 기준 | -| Contract | `agent-contract/provided/openai-compatible-api.md` | OpenAI-compatible `metadata.agent_group.task_file`와 `metadata.agent_group.params` 계약을 추가할 원문 | +| Contract | `agent-contract/outer/openai-compatible-api.md` | OpenAI-compatible `metadata.agent_group.task_file`와 `metadata.agent_group.params` 계약을 추가할 원문 | | Code | `packages/go/config`, `apps/edge/internal/openai`, `apps/edge/internal/service`, `apps/node/internal/adapters/cli`, `configs` | config schema, OpenAI metadata parsing, routing decision, CLI adapter execution 연결 기준 | | External Provider | CLI provider agent catalog | opencode/codex/claude/gemini 등 provider-specific 실행 대상은 cli provider agent id로 참조한다 | | User Decision | D01 | 실행 실패/중단/quota 소진 시 자동 retry/fallback/중단 정책은 사용자 결정 전까지 잠금 | @@ -55,7 +55,7 @@ ## Interface Contract -- 계약 원문: `agent-contract/provided/openai-compatible-api.md` +- 계약 원문: `agent-contract/outer/openai-compatible-api.md` - 입력: - `metadata.agent_group.task_file`: agent group routing에 사용할 task file 경로다. 절대 경로와 상대 경로를 모두 허용한다. OpenAI-compatible CLI route에서 상대 경로는 `metadata.workspace` 기준으로 해석하고, 상대 경로인데 `metadata.workspace`가 없으면 실패한다. - `metadata.agent_group.params`: 예약어 `user_params_schema`로 검증한 사용자 parameter 객체다. 예약어 prompt renderer가 CLI별 prompt 또는 argument로 변환할 수 있다. diff --git a/apps/client/README.md b/apps/client/README.md index e475380..8a11e38 100644 --- a/apps/client/README.md +++ b/apps/client/README.md @@ -23,6 +23,7 @@ flutter test ### Dart Protobuf 생성 이 프로젝트는 Go/Dart 등 다중 언어 환경의 메시지 계약을 공유하기 위해 protobuf를 사용합니다. Dart proto 코드를 새로 생성하려면 루트 `Makefile`에서 `make proto-dart`를 실행하세요. +Client-Control Plane wire 계약 원문은 repo root의 `agent-contract/inner/client-control-plane-wire.md`를 기준으로 합니다. 필요 조건: 1. `protoc` 설치 diff --git a/apps/control-plane/README.md b/apps/control-plane/README.md index 5322b4c..8ce9fdc 100644 --- a/apps/control-plane/README.md +++ b/apps/control-plane/README.md @@ -14,6 +14,8 @@ Control Plane은 상시 운영, multi-edge 연결/health 확인, fleet-wide 명 Control Plane-Edge wire protocol은 Edge가 소유한 operation을 원격 운영면으로 소비한다. Edge 상태 조회, node 및 후속 agent 등록 상태 조회, command 전달, event 수신, run/cancel/status, bootstrap 발급 상태처럼 CLI와 Control Plane에 모두 필요한 작업은 Edge 내부의 표면 중립 service/operation boundary로 수렴시키고, Control Plane에서 Edge-local registry, run dispatch, stream relay 구현을 복제하지 않는다. Control Plane이 보관할 수 있는 정보는 연결 view, 제어 요청/결과, audit에 필요한 최소 운영 기록으로 제한한다. +계약 원문은 Control Plane-Edge wire는 repo root의 `agent-contract/inner/control-plane-edge-wire.md`, Client-Control Plane wire는 `agent-contract/inner/client-control-plane-wire.md`를 기준으로 한다. + ## 현재 실행 표면 - `GET /healthz` diff --git a/apps/edge/README.md b/apps/edge/README.md index 93ad5bb..b31c9a0 100644 --- a/apps/edge/README.md +++ b/apps/edge/README.md @@ -24,6 +24,8 @@ ops console은 edge-local diagnostic surface이고, HTTP/API는 central/remote m 실행 요청과 이벤트는 같은 TCP 연결을 공유하지만, 메시지 타입과 내부 파이프라인은 분리한다. `RunRequest`, `CancelRequest`, `NodeCommandRequest`는 edge가 node에 보내는 command/request 계열이고, `RunEvent`, `EdgeNodeEvent`는 node와 edge 내부에서 발생한 event 계열이다. +계약 원문은 Edge-Node runtime wire는 repo root의 `agent-contract/inner/edge-node-runtime-wire.md`, Edge config/runtime refresh는 `agent-contract/inner/edge-config-runtime-refresh.md`를 기준으로 한다. + `internal/events.Bus`는 Edge 안의 in-process fanout과 bounded replay를 담당한다. 현재 replay는 늦게 붙은 console/API handler를 위한 최근 이벤트 버퍼이지 durable history가 아니며, Node local SQLite 실행 이력과 다른 책임이다. 전역 이력 저장, audit, query API는 후속 Control Plane/Client 경계에서 별도 설계한다. ## 원격 CLI adapter 개발 진단 흐름 @@ -193,7 +195,7 @@ Edge 외부 입력은 OpenAI-compatible HTTP API와 A2A JSON-RPC HTTP API 두 이 표면은 외부 모델 클라이언트 호환을 위한 표준 경로다. Edge/Node 운영 제어, CLI logical session, background run, cancel/terminate-session, capabilities/status/session/transport command, node lifecycle event 같은 IOP 고유 기능은 OpenAI-compatible 요청에 억지로 싣지 않고 IOP native protocol(protobuf-socket) 계열에서 다룬다. -외부 프로젝트가 참조할 요청 계약 원문은 repo root의 `agent-contract/provided/openai-compatible-api.md`에 둔다. CLI agent route에서 사용할 workspace는 OpenAI request의 `metadata.workspace`에 둔다. Workspace authoring handoff의 요청 shape도 같은 계약 원문을 기준으로 한다. +외부 프로젝트가 참조할 요청 계약 원문은 repo root의 `agent-contract/outer/openai-compatible-api.md`에 둔다. CLI agent route에서 사용할 workspace는 OpenAI request의 `metadata.workspace`에 둔다. Workspace authoring handoff의 요청 shape도 같은 계약 원문을 기준으로 한다. ```yaml openai: @@ -253,6 +255,8 @@ vLLM 같은 OpenAI-compatible inference server는 `openai_compat` adapter와 `pr 현재 `openai.model_routes`는 외부 model id를 단일 `adapter + target`으로 연결하는 호환 catalog다. 새 provider pool 계약에서는 `models[].id`를 OpenAI-compatible model key이자 queue/routing canonical key로 유지하고, `models[].providers`가 provider id별 실제 served model name을 가리킨다. +config/provider pool 변경 계약은 repo root의 `agent-contract/inner/edge-config-runtime-refresh.md`를 기준으로 한다. + 마이그레이션 기준은 1:1 route를 단일 provider를 가진 `models[]` 항목으로 표현하는 것이다. 기존 Node provider instance 설정(`openai_compat_instances`, legacy `vllm` instance 등)은 provider id, provider type/category, served models, capacity/queue policy를 채우는 입력으로 사용하고, Edge는 선택된 provider의 served model name으로 target을 rewrite한 뒤 Node에는 기존처럼 `adapter + target` 실행 요청을 전달한다. provider pool이 구현되기 전까지 `openai.model_routes`는 fallback/compat 경로로 유지한다. 최신 provider pool schema 예시: @@ -331,6 +335,8 @@ nodes: A2A JSON-RPC HTTP API는 NomadCode Core나 외부 agent가 Edge 실행 그룹에 작업을 위임하고 `Task` 상태, artifact, cancel/polling을 공유해야 할 때 사용하는 입력 표면이다. OpenAI-compatible API가 단순 모델/chat completion 호환에 맞는 경로라면, A2A는 agent-to-agent 작업 위임과 상태 공유에 맞는 경로다. +외부 caller가 참조할 A2A 요청 계약 원문은 repo root의 `agent-contract/outer/a2a-json-rpc-api.md`를 기준으로 한다. + 1차 지원 범위는 `message/send`, `tasks/get`, `tasks/cancel`이다. `message/stream`, push notification, `tasks/list`는 후속 단계에서 다룬다. 구현은 OpenAI-compatible serving과 같은 Edge input 관리 계층에서 lifecycle/config를 묶고, 내부 실행은 동일하게 `adapter + target`으로 변환한다. #### 설정 예시 diff --git a/apps/node/README.md b/apps/node/README.md index 975c60c..737122f 100644 --- a/apps/node/README.md +++ b/apps/node/README.md @@ -1,6 +1,6 @@ # node — Node Agent -디바이스당 1개 실행되는 IOP 노드 에이전트. +디바이스당 1개 실행되는 IOP 노드 에이전트. Edge에 연결되어 `adapter + target` 실행을 수행하고, TCP/protobuf 소켓을 통해 요청, 명령, 이벤트 스트림을 처리한다. mTLS helper는 `packages/go/auth`에 있지만 현재 Edge-Node transport에는 아직 연결하지 않았다. ## 내부 구조 (Hexagonal Architecture) @@ -67,6 +67,7 @@ edge에서 실행 요청을 받으면 node는 해당 입력을 선택된 adapter ## Edge-Node 메시지 경계 node는 같은 TCP/protobuf session 위에서 여러 메시지 계열을 처리한다. +계약 원문은 repo root의 `agent-contract/inner/edge-node-runtime-wire.md`를 기준으로 한다. - `RunRequest`: adapter execution 시작. CLI adapter에서는 prompt 전달로 해석된다. - `CancelRequest`: 실행 취소 또는 logical session 종료. diff --git a/docs/openai-compatible-api-contract.md b/docs/openai-compatible-api-contract.md index 1abca9a..6f3808e 100644 --- a/docs/openai-compatible-api-contract.md +++ b/docs/openai-compatible-api-contract.md @@ -1,6 +1,6 @@ # OpenAI-Compatible API Contract -계약 원문은 [agent-contract/provided/openai-compatible-api.md](../agent-contract/provided/openai-compatible-api.md)다. +계약 원문은 [agent-contract/outer/openai-compatible-api.md](../agent-contract/outer/openai-compatible-api.md)다. 이 문서는 사람용 안내와 기존 링크 유지를 위한 포인터다. 요청 스키마, 필드 의미, 금지 사항, 구현 메모는 계약 원문을 기준으로 한다.