update agent-spec templates and skills, add agent-spec dir
This commit is contained in:
parent
f7dcf9118e
commit
ae243a03c1
11 changed files with 697 additions and 46 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
## 목적
|
||||
|
||||
`agent-spec/`는 AI agent가 현재 구현된 기능의 동작, 책임 경계, 코드 진입점, 계약 링크, 검증 방법을 빠르게 파악하기 위한 living spec 저장소다.
|
||||
`agent-spec/`는 사람과 AI agent가 현재 구현된 기능 목록, 동작 흐름, 계약 링크, 검증 방법을 함께 파악하기 위한 living spec 저장소다.
|
||||
로드맵 완료 이력, SDD 설계 논의, 계약 원문, 사람용 가이드를 대체하지 않는다.
|
||||
|
||||
## 기본 구조
|
||||
|
|
@ -28,9 +28,11 @@ agent-spec/
|
|||
|
||||
- `agent-spec/**`는 현재 구현 지도를 제공하지만 최종 truth는 코드, `agent-contract/`, 테스트, 설정 예시다.
|
||||
- API, wire protocol, runtime call, event/config schema, 프로세스 간 요청/응답 계약 원문은 `agent-contract/`에 두고 agent-spec에는 링크와 사용 맥락만 남긴다.
|
||||
- 코드 배치, 주요 구성 요소, 구현 진입점, 도메인 간 책임 경계, 유지할 패턴, 금지 사항은 domain rule에 둔다.
|
||||
- agent-spec에는 기능 이해에 필요한 최소 경계만 적고, 코딩할 때 따라야 하는 경계 규칙을 반복하지 않는다.
|
||||
- SDD는 구현 전 설계 게이트다. agent-spec은 구현 후 현재 상태를 설명한다.
|
||||
- 로드맵과 complete.log는 완료 근거와 변경 힌트로 사용한다. 현재 동작은 코드와 계약으로 재확인한다.
|
||||
- 사람용 최신 가이드는 `docs/`에 둔다. agent-spec은 agent 작업 문맥을 우선한다.
|
||||
- 사람용 최신 가이드는 `docs/`에 둔다. agent-spec은 기능 파악과 작업 문맥을 우선한다.
|
||||
|
||||
## Frontmatter Schema
|
||||
|
||||
|
|
@ -51,10 +53,11 @@ agent-spec/
|
|||
## 읽기 규칙
|
||||
|
||||
- 일반 작업마다 `agent-spec/`를 읽지 않는다.
|
||||
- 기존 기능의 현재 동작, 책임 경계, 코드 진입점, 계약 링크가 필요한 작업에서만 세션 1회 `agent-spec/index.md`를 읽는다.
|
||||
- 기존 기능의 기능 목록, 주요 흐름, 계약 링크, 현재 구현 상태가 필요한 작업에서만 세션 1회 `agent-spec/index.md`를 읽는다.
|
||||
- `index.md`에서 매칭되는 spec 문서만 읽는다.
|
||||
- 매칭 spec이 없으면 스펙이 없다고 보고하고 코드, 계약, 테스트에서 직접 확인한다. 추측으로 spec 내용을 만들지 않는다.
|
||||
- spec 문서가 코드/계약과 충돌하면 코드/계약을 우선하고 `update-spec` 필요를 보고한다.
|
||||
- 코드 배치, 구현 위치, 패턴, 금지 사항, 도메인 간 상세 책임 경계가 필요하면 프로젝트 규칙의 도메인 매핑에 따라 domain rule을 읽는다.
|
||||
- API, wire protocol, runtime call, event/config schema, 프로세스 간 요청/응답 계약에 닿으면 `agent-contract/index.md`의 규칙에 따라 매칭 계약 문서도 읽는다.
|
||||
- `agent-spec/archive/**`는 일반 작업에서 읽지 않는다.
|
||||
- 예외: 사용자가 과거 스펙 확인, 복원, 비교, 특정 archive 경로 확인을 요청한 경우에만 필요한 archive 문서만 좁게 읽는다.
|
||||
|
|
@ -73,26 +76,31 @@ agent-spec/
|
|||
|
||||
- 현재형으로 작성한다.
|
||||
- 과거 작업 일지, 설계 논쟁 전문, 완료된 roadmap task 전체 복사, 함수 단위 코드 설명을 넣지 않는다.
|
||||
- 스펙 본문은 기능 단위의 작동 지도여야 한다.
|
||||
- 스펙 본문은 기능 단위의 작동 지도여야 한다. 먼저 기능 목록을 두고, 필요한 흐름만 뒤에 보강한다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 작성한다. 활성 spec은 구현된 기능만 기록하므로 기능별 `상태` 칼럼을 기본으로 두지 않는다.
|
||||
- 기능별 부분 지원, 조건부 동작, 한계는 설명 또는 `한계와 주의사항`에 짧게 적는다.
|
||||
- 주요 흐름은 텍스트만 길게 나열하지 말고 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다. 단순 기능은 짧은 목록으로 충분하다.
|
||||
- 책임 경계는 기능 오해를 막는 최소 수준만 허용한다. 패키지 배치, 구현 진입점, 유지할 패턴, 금지 사항은 domain rule에 둔다.
|
||||
- `코드 진입점` 섹션은 기본 섹션으로 두지 않는다. 필요한 코드 근거는 frontmatter `source_evidence`와 domain rule로 좁힌다.
|
||||
- 계약 원문, proto field 전체 목록, config schema 원문을 복제하지 말고 `agent-contract/` 또는 코드 경로를 링크한다.
|
||||
- 불확실한 내용은 단정하지 말고 `불명확` 또는 `확인 필요`로 남긴다.
|
||||
- spec 갱신이 필요 없으면 `Spec update not needed: <사유>`를 결과 보고나 Milestone 완료 리뷰에 남긴다.
|
||||
|
||||
## 표준 섹션
|
||||
## 기본 섹션
|
||||
|
||||
spec 문서는 아래 섹션 순서를 유지한다.
|
||||
spec 문서는 아래 섹션을 기본 순서로 작성한다. 해당 spec에 의미가 없는 섹션은 만들지 않는다.
|
||||
|
||||
1. `목적`
|
||||
2. `현재 동작`
|
||||
2. `기능 목록`
|
||||
3. `범위`
|
||||
4. `주요 흐름`
|
||||
5. `책임 경계`
|
||||
6. `계약`
|
||||
7. `코드 진입점`
|
||||
8. `설정/데이터/이벤트`
|
||||
9. `검증`
|
||||
10. `한계와 주의사항`
|
||||
11. `변경 기록`
|
||||
5. `계약`
|
||||
6. `설정/데이터/이벤트`
|
||||
7. `검증`
|
||||
8. `한계와 주의사항`
|
||||
9. `변경 기록`
|
||||
|
||||
`책임 경계`가 기능 이해에 꼭 필요하면 별도 섹션으로 짧게 둘 수 있다. 이때 domain rule의 구성 요소, 코드 배치, 금지 사항을 반복하지 않는다.
|
||||
|
||||
## 템플릿
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ spec_doc_type: index
|
|||
status: 활성
|
||||
---
|
||||
|
||||
# Agent Spec Index
|
||||
# 구현 스펙 색인
|
||||
|
||||
## 목적
|
||||
|
||||
이 디렉터리는 현재 구현된 기능의 agent-facing living spec을 관리한다.
|
||||
이 디렉터리는 사람과 agent가 함께 보는 현재 구현 기능 living spec을 관리한다.
|
||||
로드맵 완료 이력, SDD, 계약 원문, 사람용 docs를 대체하지 않는다.
|
||||
|
||||
## 읽기 규칙
|
||||
|
|
@ -15,16 +15,19 @@ status: 활성
|
|||
- 필요한 작업에서만 이 index를 읽고, 매칭되는 spec 문서만 읽는다.
|
||||
- `archive/**`는 과거 비교, 복원, 특정 근거 확인 요청이 있을 때만 읽는다.
|
||||
- API, wire protocol, config/event schema, 프로세스 간 계약 원문은 `agent-contract/`를 따른다.
|
||||
- 코드 배치, 구현 진입점, 도메인 간 상세 책임 경계는 domain rule을 따른다.
|
||||
|
||||
## Spec Map
|
||||
|
||||
| id | 상태 | 읽는 조건 | path | 주요 evidence |
|
||||
|----|------|-----------|------|---------------|
|
||||
| id | 상태 | 언제 읽나 | path | 주요 근거 |
|
||||
|----|------|-----------|------|-----------|
|
||||
| 없음 | 없음 | 없음 | 없음 | 없음 |
|
||||
|
||||
## 작성 규칙
|
||||
|
||||
- 현재 구현 기준으로 작성한다.
|
||||
- 기능 목록과 주요 흐름을 먼저 파악할 수 있게 작성한다.
|
||||
- 코드/계약/테스트 evidence를 우선한다.
|
||||
- 계약 원문은 복제하지 않고 링크한다.
|
||||
- 코드 진입점과 도메인룰 성격의 상세 경계는 반복하지 않는다.
|
||||
- 불확실한 내용은 `불명확`으로 남긴다.
|
||||
|
|
|
|||
|
|
@ -8,15 +8,17 @@ source_evidence:
|
|||
notes: <현재 구현 근거>
|
||||
---
|
||||
|
||||
# Spec: <title>
|
||||
# 스펙: <title>
|
||||
|
||||
## 목적
|
||||
|
||||
<이 spec이 설명하는 현재 구현 기능과 agent가 이 문서를 읽어야 하는 이유>
|
||||
<이 spec이 설명하는 현재 구현 기능과 이 문서를 읽어야 하는 이유>
|
||||
|
||||
## 현재 동작
|
||||
## 기능 목록
|
||||
|
||||
- <현재 코드와 계약으로 확인된 동작>
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| <기능명> | <현재 코드와 계약으로 확인된 동작> |
|
||||
|
||||
## 범위
|
||||
|
||||
|
|
@ -25,31 +27,28 @@ source_evidence:
|
|||
|
||||
## 주요 흐름
|
||||
|
||||
1. <주요 실행 흐름>
|
||||
|
||||
## 책임 경계
|
||||
|
||||
- <컴포넌트/프로세스/계층별 책임 경계>
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as <주체>
|
||||
participant B as <주체>
|
||||
A->>B: <주요 메시지 또는 동작>
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- <관련 agent-contract 문서 또는 없음>
|
||||
|
||||
## 코드 진입점
|
||||
|
||||
- `<path>` - <역할>
|
||||
- <관련 agent-contract 문서 또는 코드 계약 포인터>
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- <관련 config, 저장소, event, runtime state 요약. 원문 schema는 링크만 둔다.>
|
||||
- <관련 config, 저장소, event, runtime state 요약. 원문 schema는 복제하지 않는다.>
|
||||
|
||||
## 검증
|
||||
|
||||
- `<command or profile>` - <기대 결과 또는 근거>
|
||||
- `<command or profile>` - <기대 결과>
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- <현재 구현 한계, known limitation, 수정 시 주의점>
|
||||
- <현재 구현 한계 또는 조건부 동작>
|
||||
|
||||
## 변경 기록
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec
|
|||
|
||||
## 목적
|
||||
|
||||
현재 구현된 기능의 agent-facing living spec을 새로 만든다.
|
||||
스펙은 로드맵 완료 이력이나 계약 원문을 복제하지 않고, agent가 작업 전에 현재 동작과 코드 진입점을 빠르게 찾는 지도로 유지한다.
|
||||
현재 구현된 기능의 living spec을 새로 만든다.
|
||||
스펙은 로드맵 완료 이력이나 계약 원문을 복제하지 않고, 사람과 agent가 구현된 기능, 동작 흐름, 계약/검증 포인터를 함께 확인하는 문서로 유지한다.
|
||||
|
||||
## 언제 호출할지
|
||||
|
||||
|
|
@ -55,14 +55,19 @@ description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec
|
|||
- 기존 같은 `spec-id` 문서가 있으면 새로 만들지 말고 `update-spec` 대상이라고 보고한다.
|
||||
|
||||
4. **spec 문서 작성**
|
||||
- spec template의 표준 섹션 순서를 유지한다.
|
||||
- spec template의 기본 섹션 구조를 따른다.
|
||||
- frontmatter의 `spec_doc_type`, `spec_id`, `status`, `source_evidence`를 채운다.
|
||||
- `status`는 evidence 수준에 따라 `구현됨`, `부분`, `가정`, `불명확` 중 하나로 둔다.
|
||||
- `기능 목록`을 `목적` 다음에 바로 둔다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 작성한다. 기능별 `상태` 칼럼은 기본 생성하지 않는다.
|
||||
- `주요 흐름`은 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다. 단순 기능은 짧은 목록으로 둔다.
|
||||
- 책임 경계는 기능 이해에 필요한 최소 수준만 적고, 도메인별 코드 배치나 금지 사항은 domain rule로 넘긴다.
|
||||
- 계약 원문, proto field 전체 목록, config schema 원문은 복제하지 않고 링크한다.
|
||||
- 주요 코드 진입점과 검증 방법을 경로와 명령으로 남긴다.
|
||||
- `코드 진입점` 섹션은 만들지 않는다. 코드 근거는 `source_evidence`에 남긴다.
|
||||
- 검증 방법은 실행 가능한 명령 또는 확인 기준으로 남긴다.
|
||||
|
||||
5. **index 갱신**
|
||||
- `Spec Map`에 새 spec id, 상태, 읽는 조건, path, 주요 evidence를 추가하거나 보정한다.
|
||||
- `Spec Map`에 새 spec id, 상태, 읽는 조건, path, 주요 근거를 추가하거나 보정한다.
|
||||
- 매칭 조건은 agent가 좁게 읽을 수 있도록 기능명, 코드 경로, 계약 id, 운영 표면 중심으로 쓴다.
|
||||
- 기존 행을 삭제하거나 재정렬하지 않는다. 명백히 placeholder인 `없음` 행은 첫 실제 spec 추가 시 제거할 수 있다.
|
||||
|
||||
|
|
@ -73,7 +78,9 @@ description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec
|
|||
## 실행 결과 검증
|
||||
|
||||
- [ ] `agent-spec/index.md`가 존재하고 Spec Map에 생성한 spec이 들어 있는가
|
||||
- [ ] 생성한 spec 문서가 `rules-agent-spec.md`의 표준 섹션 순서를 유지하는가
|
||||
- [ ] 생성한 spec 문서가 `rules-agent-spec.md`의 기본 섹션 기준을 따르는가
|
||||
- [ ] 기능 목록이 기능/설명 중심이며 불필요한 상태 칼럼이나 과한 상세 설명을 만들지 않았는가
|
||||
- [ ] 코드 진입점, 패키지 배치, 도메인별 금지 사항을 spec 본문에 반복하지 않았는가
|
||||
- [ ] frontmatter의 `spec_doc_type`, `spec_id`, `status`, `source_evidence`가 채워졌는가
|
||||
- [ ] source evidence path가 실제 파일이거나 `path: null`인 사용자 근거인가
|
||||
- [ ] 계약 원문을 복제하지 않고 `agent-contract/` 또는 코드 링크로 연결했는가
|
||||
|
|
@ -91,7 +98,7 @@ description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec
|
|||
- [index.md](agent-spec/index.md)
|
||||
- [<spec-id>.md](agent-spec/<area>/<spec-id>.md)
|
||||
- 상태: <구현됨 | 부분 | 가정 | 불명확>
|
||||
- 주요 evidence:
|
||||
- 주요 근거:
|
||||
- <path 또는 사용자 근거> - <요약>
|
||||
|
||||
## TODO 항목
|
||||
|
|
@ -105,5 +112,6 @@ description: agent-spec 최초 생성, 현재 구현 스펙 작성, living spec
|
|||
- 현재 코드/계약으로 확인하지 않은 내용을 구현 사실처럼 쓰지 않는다.
|
||||
- archive 전체를 훑지 않는다.
|
||||
- 기존 spec이 있으면 중복 spec을 만들지 않는다.
|
||||
- 코드 진입점, 구현 배치, 도메인 간 상세 책임 경계, 유지할 패턴, 금지 사항을 domain rule 대신 agent-spec에 길게 쓰지 않는다.
|
||||
- 사람용 공개 가이드를 agent-spec에 장황하게 작성하지 않는다.
|
||||
- spec 생성과 무관한 코드 파일을 수정하지 않는다.
|
||||
|
|
|
|||
|
|
@ -50,7 +50,9 @@ description: agent-spec 갱신, 구현 스펙 업데이트, 완료 기능 스펙
|
|||
- spec과 코드/계약이 충돌하면 코드/계약을 우선하고 spec을 수정한다.
|
||||
|
||||
3. **영향 판정**
|
||||
- 현재 동작, 범위, 주요 흐름, 책임 경계, 계약 링크, 코드 진입점, 설정/데이터/이벤트, 검증, 한계 중 바뀐 항목을 식별한다.
|
||||
- 기능 목록, 범위, 주요 흐름, 계약 링크, 설정/데이터/이벤트, 검증, 한계 중 바뀐 항목을 식별한다.
|
||||
- 기능 이해에 필요한 최소 책임 설명이 바뀐 경우만 spec에 반영한다.
|
||||
- 코드 배치, 구현 진입점, 유지할 패턴, 금지 사항 변경은 domain rule 갱신 대상으로 본다.
|
||||
- 변경이 테스트 fixture, 내부 리팩터링, 문구 정리처럼 현재 구현 spec에 영향을 주지 않으면 `Spec update not needed: <사유>`를 남긴다.
|
||||
- 판단 불가이면 spec을 추정 갱신하지 않고 `Spec blocked: <필요 evidence>`로 보고한다.
|
||||
|
||||
|
|
@ -58,12 +60,15 @@ description: agent-spec 갱신, 구현 스펙 업데이트, 완료 기능 스펙
|
|||
- `mode=check-only`이면 쓰지 않고 갱신 후보만 보고한다.
|
||||
- 영향이 있는 spec 문서만 수정한다.
|
||||
- frontmatter `status`와 `source_evidence`를 현재 evidence에 맞게 보강한다.
|
||||
- 표준 섹션 순서를 유지한다.
|
||||
- `rules-agent-spec.md`의 기본 섹션 기준을 따른다.
|
||||
- 기능 목록은 `기능`과 `설명` 중심으로 유지한다. 기능별 `상태` 칼럼은 기본 추가하지 않는다.
|
||||
- `주요 흐름`은 긴 텍스트보다 Mermaid `sequenceDiagram` 또는 `flowchart`를 우선 고려한다.
|
||||
- `코드 진입점` 섹션은 추가하지 않는다. 기존 spec에 있으면 현재 기준에 맞춰 제거하거나 `source_evidence`로 옮긴다.
|
||||
- 계약 원문을 복제하지 않고 링크만 보강한다.
|
||||
- 변경 기록에 날짜, 변경 근거, 관련 Milestone/complete.log/코드 경로를 남긴다.
|
||||
|
||||
5. **index 동기화**
|
||||
- spec 상태, 읽는 조건, path, 주요 evidence가 바뀌었으면 `agent-spec/index.md`의 Spec Map을 갱신한다.
|
||||
- spec 상태, 읽는 조건, path, 주요 근거가 바뀌었으면 `agent-spec/index.md`의 Spec Map을 갱신한다.
|
||||
- 새 spec 문서가 필요하면 `create-spec` 대상으로 보고하고 index를 추정 갱신하지 않는다.
|
||||
- 폐기된 spec은 활성 문서에 남기지 않고 archive log로 이동할 후보로 보고한다. 명시 요청 없이 archive 이동하지 않는다.
|
||||
|
||||
|
|
@ -77,7 +82,9 @@ description: agent-spec 갱신, 구현 스펙 업데이트, 완료 기능 스펙
|
|||
|
||||
- [ ] `agent-spec/index.md`에서 관련 spec만 읽었는가
|
||||
- [ ] 코드/계약/테스트 기준으로 현재 동작을 재확인했는가
|
||||
- [ ] spec 문서의 표준 섹션과 frontmatter가 유지되는가
|
||||
- [ ] spec 문서의 기본 섹션 기준과 frontmatter가 유지되는가
|
||||
- [ ] 기능 목록이 기능/설명 중심이며 불필요한 상태 칼럼이나 과한 상세 설명을 만들지 않았는가
|
||||
- [ ] 코드 진입점, 패키지 배치, 도메인별 금지 사항을 spec 본문에 반복하지 않았는가
|
||||
- [ ] index의 Spec Map이 갱신한 spec 상태와 일치하는가
|
||||
- [ ] 계약 원문을 복제하지 않았는가
|
||||
- [ ] 갱신/불필요/create 필요/차단 중 하나의 결과가 명확한가
|
||||
|
|
@ -114,3 +121,4 @@ description: agent-spec 갱신, 구현 스펙 업데이트, 완료 기능 스펙
|
|||
- 매칭되지 않는 spec을 광범위하게 읽거나 전부 갱신하지 않는다.
|
||||
- archive spec을 명시 요청 없이 읽거나 갱신하지 않는다.
|
||||
- complete.log나 roadmap 문구만으로 현재 동작을 단정하지 않는다.
|
||||
- 코드 진입점, 구현 배치, 도메인 간 상세 책임 경계, 유지할 패턴, 금지 사항을 domain rule 대신 agent-spec에 길게 쓰지 않는다.
|
||||
|
|
|
|||
111
agent-spec/control/control-plane-operations.md
Normal file
111
agent-spec/control/control-plane-operations.md
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: control/control-plane-operations
|
||||
status: 부분
|
||||
source_evidence:
|
||||
- type: contract
|
||||
path: agent-contract/inner/control-plane-edge-wire.md
|
||||
notes: Control Plane-Edge proto-socket TCP 계약
|
||||
- type: contract
|
||||
path: agent-contract/inner/client-control-plane-wire.md
|
||||
notes: Client-Control Plane proto-socket WebSocket 계약
|
||||
- type: code
|
||||
path: apps/control-plane/internal/wire/edge_server.go
|
||||
notes: Control Plane Edge TCP server, hello, status request, command dispatch
|
||||
- type: code
|
||||
path: apps/edge/internal/controlplane/connector.go
|
||||
notes: Edge outbound connector, hello, status response, command event relay
|
||||
- type: code
|
||||
path: apps/control-plane/cmd/control-plane/http_edge_handlers.go
|
||||
notes: Control Plane HTTP edge registry/status/events/commands view
|
||||
- type: code
|
||||
path: apps/client/lib/control_plane_status_repository.dart
|
||||
notes: Flutter client HTTP status repository
|
||||
- type: code
|
||||
path: apps/client/lib/iop_wire/client_wire_client.dart
|
||||
notes: Flutter proto-socket Client hello baseline
|
||||
- type: test
|
||||
path: apps/control-plane/internal/wire/edge_server_test.go
|
||||
notes: Control Plane-Edge wire 검증
|
||||
---
|
||||
|
||||
# 스펙: Control Plane 운영 기능
|
||||
|
||||
## 목적
|
||||
|
||||
Control Plane과 Client가 Edge 운영 상태를 어떻게 관찰하고 명령을 전달하는지 설명한다.
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| Control Plane server | HTTP health/readiness endpoint, Client proto-socket WebSocket endpoint, Edge proto-socket TCP endpoint를 함께 시작한다. |
|
||||
| Client hello wire | `/client` WebSocket proto-socket에서 `ClientHelloRequest`/`ClientHelloResponse` baseline을 제공한다. |
|
||||
| Edge outbound enrollment | Edge가 Control Plane TCP wire로 outbound 연결하고 `EdgeHelloRequest`를 보낸다. `edge_id`가 비어 있으면 거부된다. |
|
||||
| Edge connection registry | Control Plane은 Edge connection을 in-memory로 관리하고 reconnect stale cleanup을 connection token으로 방지한다. |
|
||||
| Edge status request | Control Plane이 connected Edge에 `EdgeStatusRequest`를 보내 node/provider snapshot을 받는다. |
|
||||
| Edge command dispatch | Control Plane이 `EdgeCommandRequest`를 connected Edge에 보내고 response와 lifecycle event를 bounded audit view에 기록한다. |
|
||||
| Edge/Fleet HTTP view | `/edges`, `/edges/{id}`, `/edges/{id}/status`, `/edges/{id}/events`, `/edges/{id}/operations`, `/edges/{id}/commands`와 fleet status 계열을 제공한다. |
|
||||
| Flutter status repository | Flutter Client가 HTTP repository로 Edge/fleet status, events, operations, command response를 가져온다. |
|
||||
| Flutter proto-socket client | Flutter proto-socket client는 현재 hello baseline을 지원한다. |
|
||||
| IOP console package | `packages/flutter/iop_console`은 embeddable console shell/panel contract를 제공한다. |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: Control Plane process endpoints, Edge outbound enrollment, Edge registry, status request/response, command dispatch/event audit, Client hello wire, Flutter status repository.
|
||||
- 제외: Control Plane이 Edge config/state canonical store가 되는 기능, Node 직접 연결/스케줄링, durable audit DB, 정책/권한 model, full UI 정의 동기화.
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant CP as Control Plane
|
||||
participant Edge
|
||||
|
||||
Edge->>CP: EdgeHelloRequest
|
||||
CP->>CP: connection registry 갱신
|
||||
Client->>CP: HTTP edge/fleet status
|
||||
CP->>Edge: EdgeStatusRequest
|
||||
Edge-->>CP: EdgeStatusResponse
|
||||
CP-->>Client: status view
|
||||
Client->>CP: command request
|
||||
CP->>Edge: EdgeCommandRequest
|
||||
Edge-->>CP: command response/event
|
||||
CP-->>Client: command result
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- `iop.control-plane-edge-wire`: `agent-contract/inner/control-plane-edge-wire.md`
|
||||
- `iop.client-control-plane-wire`: `agent-contract/inner/client-control-plane-wire.md`
|
||||
- proto 원문: `proto/iop/control.proto`
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- Control Plane config는 `configs/control-plane.yaml`과 `apps/control-plane/cmd/control-plane/main.go` config loader를 기준으로 한다.
|
||||
- Client WS listen은 `IOP_WIRE_LISTEN`, Edge TCP listen은 `IOP_EDGE_WIRE_LISTEN`으로 override할 수 있다.
|
||||
- Edge connector 설정은 `configs/edge.yaml`의 `control_plane` 섹션이다.
|
||||
- Edge registry recent node events와 command audit는 bounded in-memory buffer다. durable audit store가 아니다.
|
||||
- Client build-time endpoint는 `IOP_CONTROL_PLANE_HTTP_URL`, `IOP_CONTROL_PLANE_WIRE_URL` Dart define으로 주입된다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `go test ./apps/control-plane/internal/wire`
|
||||
- `go test ./apps/control-plane/cmd/control-plane`
|
||||
- `go test ./apps/edge/internal/controlplane`
|
||||
- `make test-control-plane-edge-wire`
|
||||
- `make client-test` - Flutter 환경과 dependency가 준비되어 있을 때 실행한다.
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- Control Plane은 현재 MVP/scaffold 성격이 강하며 DB/Redis 설정은 예약되어 있다.
|
||||
- Client-Control Plane proto-socket wire는 hello baseline이고, 운영 상태 조회는 현재 HTTP repository가 담당한다.
|
||||
- Edge/command/event registry는 in-memory bounded view다. audit, 권한, durable history는 별도 설계가 필요하다.
|
||||
- Control Plane status/command 응답에 Node address, token, transport internals를 넣지 않는다.
|
||||
- Control Plane이 Node를 직접 연결하거나 스케줄링하는 구조를 만들지 않는다.
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- 2026-07-07: 현재 Control Plane/Client 코드와 wire 계약 기준으로 bootstrap spec 작성.
|
||||
- 2026-07-07: 기능 목록 중심으로 축소하고 주요 흐름을 Mermaid sequence diagram으로 정리.
|
||||
48
agent-spec/index.md
Normal file
48
agent-spec/index.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
spec_doc_type: index
|
||||
status: 활성
|
||||
---
|
||||
|
||||
# 구현 스펙 색인
|
||||
|
||||
## 목적
|
||||
|
||||
이 디렉터리는 IOP의 현재 구현을 빠르게 파악하기 위한 living spec이다.
|
||||
AI agent가 작업 전에 읽는 지도이기도 하지만, 사람도 "지금 무엇이 어디까지 구현됐는지" 확인할 수 있어야 한다.
|
||||
|
||||
로드맵 완료 이력, SDD 설계 논의, 계약 원문, 사람용 가이드를 대체하지 않는다. 최종 기준은 항상 코드, `agent-contract/`, 테스트, 설정 예시다.
|
||||
|
||||
## 읽기 규칙
|
||||
|
||||
- 먼저 아래 "영역별 요약"으로 현재 찾는 주제를 고른다.
|
||||
- 필요한 작업에서만 이 index를 읽고, 매칭되는 spec 문서만 읽는다.
|
||||
- `archive/**`는 과거 비교, 복원, 특정 근거 확인 요청이 있을 때만 읽는다.
|
||||
- API, wire protocol, config/event schema, 프로세스 간 계약 원문은 `agent-contract/`를 따른다.
|
||||
- 코드 배치, 구현 진입점, 도메인 간 상세 책임 경계는 domain rule을 따른다.
|
||||
|
||||
## 영역별 요약
|
||||
|
||||
- 실행 경로: Edge와 Node 사이의 등록, 실행, 이벤트, 취소, command 흐름은 `runtime/edge-node-execution`에서 본다.
|
||||
- 런타임 라우팅/설정: provider-pool, `models[]`, `nodes[].providers[]`, live config refresh는 `runtime/provider-pool-config-refresh`에서 본다.
|
||||
- 외부 HTTP 입력: OpenAI-compatible 호출은 `input/openai-compatible-surface`, A2A JSON-RPC 호출은 `input/a2a-json-rpc-surface`에서 본다.
|
||||
- 운영 제어: Control Plane, Edge enrollment, fleet/edge status, Flutter Client 상태 소비는 `control/control-plane-operations`에서 본다.
|
||||
|
||||
## 스펙 목록
|
||||
|
||||
| id | 상태 | 언제 읽나 | path | 주요 근거 |
|
||||
|----|------|-----------|------|-----------|
|
||||
| `runtime/edge-node-execution` | 부분 | Edge-Node TCP/protobuf transport, Node 등록, run/cancel/command, adapter 실행, Node local run store를 확인할 때 | `agent-spec/runtime/edge-node-execution.md` | `agent-contract/inner/edge-node-runtime-wire.md`, `apps/edge/internal/service/run_dispatch.go`, `apps/node/internal/node/node.go` |
|
||||
| `runtime/provider-pool-config-refresh` | 부분 | `models[]`, `nodes[].providers[]`, provider-pool dispatch, long-context admission, Edge/Node config refresh를 확인할 때 | `agent-spec/runtime/provider-pool-config-refresh.md` | `agent-contract/inner/edge-config-runtime-refresh.md`, `packages/go/config/config.go`, `apps/edge/internal/configrefresh/classify.go` |
|
||||
| `input/openai-compatible-surface` | 부분 | `/v1/models`, `/v1/chat/completions`, `/v1/responses`, OpenAI-compatible auth/metadata/workspace/tool handling, 외부 `model` route를 확인할 때 | `agent-spec/input/openai-compatible-surface.md` | `agent-contract/outer/openai-compatible-api.md`, `apps/edge/internal/openai/chat_handler.go`, `apps/edge/internal/openai/responses_handler.go` |
|
||||
| `input/a2a-json-rpc-surface` | 부분 | Edge A2A JSON-RPC, `message/send`, `tasks/get`, `tasks/cancel`, A2A task store와 bearer auth를 확인할 때 | `agent-spec/input/a2a-json-rpc-surface.md` | `agent-contract/outer/a2a-json-rpc-api.md`, `apps/edge/internal/input/a2a/server.go`, `apps/edge/internal/input/a2a/task_store.go` |
|
||||
| `control/control-plane-operations` | 부분 | Control Plane-Edge wire, Client-Control Plane wire, Control Plane HTTP Edge/fleet status view, Flutter Client status consumer를 확인할 때 | `agent-spec/control/control-plane-operations.md` | `agent-contract/inner/control-plane-edge-wire.md`, `agent-contract/inner/client-control-plane-wire.md`, `apps/control-plane/internal/wire/edge_server.go` |
|
||||
|
||||
## 작성 규칙
|
||||
|
||||
- 한국어 설명을 우선하고, 코드/계약 식별자는 원문을 유지한다.
|
||||
- 현재 구현 기준으로 작성한다.
|
||||
- 기능 목록과 주요 흐름을 먼저 파악할 수 있게 작성한다.
|
||||
- 코드/계약/테스트 evidence를 우선한다.
|
||||
- 계약 원문은 복제하지 않고 링크한다.
|
||||
- 코드 진입점과 도메인룰 성격의 상세 경계는 반복하지 않는다.
|
||||
- 불확실한 내용은 단정하지 않고 `부분`, `불명확`, `확인 필요`로 남긴다.
|
||||
102
agent-spec/input/a2a-json-rpc-surface.md
Normal file
102
agent-spec/input/a2a-json-rpc-surface.md
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: input/a2a-json-rpc-surface
|
||||
status: 부분
|
||||
source_evidence:
|
||||
- type: contract
|
||||
path: agent-contract/outer/a2a-json-rpc-api.md
|
||||
notes: A2A JSON-RPC 외부 HTTP 계약
|
||||
- type: code
|
||||
path: apps/edge/internal/input/a2a/server.go
|
||||
notes: A2A HTTP server, JSON-RPC method dispatch, auth, SubmitRun 연동
|
||||
- type: code
|
||||
path: apps/edge/internal/input/a2a/task_store.go
|
||||
notes: in-memory task store와 RunEvent drain
|
||||
- type: code
|
||||
path: apps/edge/internal/input/a2a/types.go
|
||||
notes: JSON-RPC envelope와 A2A task/message/artifact DTO
|
||||
- type: test
|
||||
path: apps/edge/internal/input/a2a/server_test.go
|
||||
notes: A2A handler 동작 검증
|
||||
- type: test
|
||||
path: apps/edge/internal/input/a2a/task_store_test.go
|
||||
notes: task store drain 상태 검증
|
||||
---
|
||||
|
||||
# 스펙: A2A JSON-RPC 입력 표면
|
||||
|
||||
## 목적
|
||||
|
||||
Edge가 A2A JSON-RPC 요청을 받아 내부 `adapter + target` 실행으로 넘기는 현재 MVP 동작을 설명한다.
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| A2A HTTP server | `a2a.enabled=true`이면 Edge input manager가 A2A HTTP server를 시작한다. 기본 RPC path는 `/a2a`다. |
|
||||
| agent card | `GET /.well-known/agent.json`으로 현재 agent card를 제공한다. |
|
||||
| bearer auth | `a2a.bearer_token`이 있으면 matching bearer authorization header를 요구한다. |
|
||||
| JSON-RPC method 처리 | JSON-RPC 2.0 envelope를 검증하고 `message/send`, `tasks/get`, `tasks/cancel`만 처리한다. |
|
||||
| message/send 실행 | text parts를 newline으로 이어 prompt를 만들고 Edge service `SubmitRun`을 호출한다. |
|
||||
| blocking task | `configuration.blocking`이 true이거나 생략되면 HTTP 요청 안에서 run stream을 drain한 뒤 최종 task snapshot을 반환한다. |
|
||||
| background task | non-blocking 요청은 working snapshot을 먼저 반환하고 background goroutine이 run stream을 drain한다. |
|
||||
| task 조회 | `tasks/get`이 process-local task store의 task snapshot을 반환한다. |
|
||||
| task 취소 | `tasks/cancel`은 working task에 대해 service `CancelRun`을 호출한다. |
|
||||
| task artifact | completed task는 adapter output delta를 text artifact 하나에 누적한다. |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: A2A HTTP listener, agent card, bearer auth, JSON-RPC envelope, message text extraction, blocking/background task drain, task get/cancel.
|
||||
- 제외: A2A streaming, durable task persistence, OpenAI-compatible chat 대체 표면, provider-pool model catalog route, full A2A spec 호환.
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller
|
||||
participant A2A as A2A server
|
||||
participant Service as Edge service
|
||||
participant Store as TaskStore
|
||||
|
||||
Caller->>A2A: message/send(text parts)
|
||||
A2A->>Service: SubmitRun(prompt)
|
||||
Service-->>A2A: run id + stream
|
||||
A2A->>Store: task working 저장
|
||||
alt blocking
|
||||
A2A->>A2A: run stream drain
|
||||
A2A-->>Caller: final task snapshot
|
||||
else non-blocking
|
||||
A2A-->>Caller: working task snapshot
|
||||
A2A->>A2A: background drain
|
||||
end
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- `iop.a2a-json-rpc-api`: `agent-contract/outer/a2a-json-rpc-api.md`
|
||||
- 내부 실행 wire: `agent-contract/inner/edge-node-runtime-wire.md`
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- `configs/edge.yaml`의 `a2a` 섹션이 listener, path, node ref, adapter, target, session id, timeout, bearer token을 제공한다.
|
||||
- A2A run metadata에는 현재 `source=a2a`와 `blocking=true` 또는 `blocking=false`가 들어간다. 이 metadata는 OpenAI-compatible request metadata 계약과 별개인 내부 run metadata다.
|
||||
- TaskStore는 run event `delta`, `complete`, `error`, `cancelled`와 node disconnect를 관찰해 task status를 갱신한다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `go test ./apps/edge/internal/input/a2a`
|
||||
- `go test ./apps/edge/internal/input`
|
||||
- `go test ./apps/edge/internal/service`
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- task state는 메모리에만 있고 Edge 재시작 시 사라진다.
|
||||
- agent card URL은 현재 listen/path 기반 단순 표현이다. reverse proxy/public URL 계약은 별도로 확정해야 한다.
|
||||
- A2A 표면은 현재 configured adapter/target으로만 run을 보낸다. request별 provider-pool model route는 이 spec의 현재 동작이 아니다.
|
||||
- streaming capability는 agent card에서 false다.
|
||||
- OpenAI-compatible chat/completions 대체 표면으로 쓰지 않는다.
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- 2026-07-07: 현재 코드와 A2A 계약 기준으로 bootstrap spec 작성.
|
||||
- 2026-07-07: 기능 목록 중심으로 축소하고 주요 흐름을 Mermaid sequence diagram으로 정리.
|
||||
105
agent-spec/input/openai-compatible-surface.md
Normal file
105
agent-spec/input/openai-compatible-surface.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: input/openai-compatible-surface
|
||||
status: 부분
|
||||
source_evidence:
|
||||
- type: contract
|
||||
path: agent-contract/outer/openai-compatible-api.md
|
||||
notes: OpenAI-compatible 외부 HTTP 계약
|
||||
- type: code
|
||||
path: apps/edge/internal/openai/routes.go
|
||||
notes: OpenAI-compatible route와 bearer auth 처리
|
||||
- type: code
|
||||
path: apps/edge/internal/openai/chat_handler.go
|
||||
notes: Chat Completions request validation, route dispatch, tool/reasoning 정책
|
||||
- type: code
|
||||
path: apps/edge/internal/openai/responses_handler.go
|
||||
notes: Responses API request validation, metadata/workspace 처리, non-stream completion
|
||||
- type: code
|
||||
path: apps/edge/internal/openai/run_result.go
|
||||
notes: RunEvent stream을 OpenAI-compatible result로 수집
|
||||
- type: test
|
||||
path: apps/edge/internal/openai/server_test.go
|
||||
notes: OpenAI-compatible route, provider-pool, workspace, tool handling 검증
|
||||
---
|
||||
|
||||
# 스펙: OpenAI-Compatible 입력 표면
|
||||
|
||||
## 목적
|
||||
|
||||
Edge가 OpenAI-compatible HTTP 요청을 받아 내부 `adapter + target` 실행으로 넘기는 현재 동작을 설명한다.
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| OpenAI-compatible HTTP server | `openai.enabled=true`이면 Edge input manager가 `/healthz`, `/v1/models`, `/v1/chat/completions`, `/v1/responses`, `/api/` route를 제공한다. |
|
||||
| bearer auth | `openai.bearer_token`이 있으면 matching bearer authorization header를 요구한다. |
|
||||
| model catalog | `/v1/models`는 provider-pool `models[]`, legacy `openai.model_routes[]`, `openai.models` 또는 `openai.target` 순서로 노출 모델을 만든다. |
|
||||
| model dispatch | request `model`은 provider-pool catalog, legacy model route, single target fallback 순서로 해석된다. |
|
||||
| provider-pool handoff | provider-pool catalog에 model이 있으면 service 요청은 `ProviderPool=true`로 전달되고 adapter/target은 provider selection 이후 확정된다. |
|
||||
| legacy route 변환 | legacy route는 외부 `model`을 route entry의 `adapter`, `target`, `node`, `session_id`, queue policy로 변환한다. |
|
||||
| metadata/workspace 처리 | `metadata.workspace`는 `RunRequest.workspace`로 분리하고, 일반 metadata는 최대 16개 string key/value만 허용한다. |
|
||||
| Chat Completions | `/v1/chat/completions`는 non-streaming과 streaming SSE를 지원한다. |
|
||||
| Responses API | `/v1/responses`는 현재 string input의 non-streaming 요청만 지원한다. |
|
||||
| strict output | strict output이 켜져 있으면 XML completion contract 기반 instruction 또는 prompt prefix를 추가할 수 있다. |
|
||||
| tool call 처리 | Chat Completions `tools`는 provider native metadata 복원 또는 text tool-call synthesis/validation 경로를 사용한다. |
|
||||
| cancel 전파 | HTTP caller timeout/cancel이 cancel-worthy error이면 Node `CancelRun`으로 전파한다. |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: OpenAI-compatible HTTP auth, request validation, route resolution, metadata/workspace 처리, chat/responses 변환, provider-pool dispatch handoff, tool/reasoning/strict output 처리.
|
||||
- 제외: OpenAI 원문 API 전체 호환, legacy `/v1/completions`, A2A JSON-RPC, Node adapter별 provider HTTP 세부, Control Plane 운영 API.
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller
|
||||
participant OpenAI as OpenAI handler
|
||||
participant Service as Edge service
|
||||
participant Runtime as Edge-Node runtime
|
||||
|
||||
Caller->>OpenAI: chat/responses request(model)
|
||||
OpenAI->>OpenAI: auth, metadata, route 검증
|
||||
OpenAI->>Service: SubmitRun(adapter/target or ProviderPool)
|
||||
Service->>Runtime: RunRequest
|
||||
Runtime-->>Service: RunEvent stream
|
||||
Service-->>OpenAI: run stream
|
||||
OpenAI-->>Caller: OpenAI-compatible response or SSE
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- `iop.openai-compatible-api`: `agent-contract/outer/openai-compatible-api.md`
|
||||
- 내부 실행 wire: `agent-contract/inner/edge-node-runtime-wire.md`
|
||||
- config/provider pool: `agent-contract/inner/edge-config-runtime-refresh.md`
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- `configs/edge.yaml`의 `openai` 섹션이 listener, bearer token, legacy adapter/target, model routes, strict output을 제공한다.
|
||||
- top-level `models[]`가 있으면 OpenAI model list와 provider-pool dispatch에서 legacy route보다 우선한다.
|
||||
- OpenAI request의 `metadata.workspace`는 absolute path가 필요한 route에서만 필수 검증된다.
|
||||
- run metadata에는 `openai_model`, `openai_stream`, `strict_output`, `estimated_input_tokens`, `context_class`가 들어갈 수 있다.
|
||||
- Node complete event metadata의 `openai_tool_calls`와 `openai_text_tool_fallback`은 response tool call 복원에 쓰인다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `go test ./apps/edge/internal/openai`
|
||||
- `go test ./apps/edge/internal/service`
|
||||
- `make test-openai-ollama`
|
||||
- provider별 실제 runtime smoke는 환경별 agent-test/dev 또는 dev-corp profile을 따른다.
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- `/v1/responses`는 현재 non-streaming string input만 지원한다.
|
||||
- `/v1/completions`는 제공하지 않는다.
|
||||
- OpenAI-compatible request에 provider/Ollama 전용 root field를 추가하지 않는다.
|
||||
- workspace는 prompt 본문에 섞지 않고 metadata에서 분리한다.
|
||||
- text tool-call synthesis는 요청 `tools[]` schema를 기준으로만 수행한다. 자연어 추론으로 tool call을 만들지 않는다.
|
||||
- private token이나 endpoint 원문은 tracked spec/docs에 남기지 않는다.
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- 2026-07-07: 현재 코드와 OpenAI-compatible 계약 기준으로 bootstrap spec 작성.
|
||||
- 2026-07-07: 기능 목록 중심으로 축소하고 주요 흐름을 Mermaid sequence diagram으로 정리.
|
||||
144
agent-spec/runtime/edge-node-execution.md
Normal file
144
agent-spec/runtime/edge-node-execution.md
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: runtime/edge-node-execution
|
||||
status: 부분
|
||||
source_evidence:
|
||||
- type: contract
|
||||
path: agent-contract/inner/edge-node-runtime-wire.md
|
||||
notes: Edge-Node register, run stream, cancel, node command, config refresh wire 계약
|
||||
- type: code
|
||||
path: proto/iop/runtime.proto
|
||||
notes: RunRequest, RunEvent, CancelRequest, NodeCommandRequest, RegisterRequest, NodeConfigPayload 원문
|
||||
- type: code
|
||||
path: apps/edge/internal/transport/server.go
|
||||
notes: Edge TCP proto-socket server, node register handshake, event relay
|
||||
- type: code
|
||||
path: apps/edge/internal/service/run_dispatch.go
|
||||
notes: surface-neutral SubmitRun, direct dispatch, cancel request 생성
|
||||
- type: code
|
||||
path: apps/node/internal/node/node.go
|
||||
notes: Node transport handler, adapter 실행, cancel, command, config refresh 처리
|
||||
- type: test
|
||||
path: apps/edge/internal/transport/server_test.go
|
||||
notes: Edge transport server 단위 검증
|
||||
- type: test
|
||||
path: apps/node/internal/node/node_test.go
|
||||
notes: Node 실행 처리 단위 검증
|
||||
---
|
||||
|
||||
# 스펙: Edge-Node 실행 경로
|
||||
|
||||
## 목적
|
||||
|
||||
Edge와 Node 사이에 현재 구현된 실행 기능을 기능 단위로 정리한다. 코드 배치 규칙이나 도메인별 작업 지침은 domain rule을 따른다.
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| Node token 등록 | Node가 Edge TCP proto-socket endpoint에 연결한 뒤 `RegisterRequest.token`으로 등록한다. |
|
||||
| Node config payload 전달 | Edge가 token에 매칭되는 node record를 찾아 `NodeConfigPayload`를 `RegisterResponse`에 담아 내려준다. |
|
||||
| 등록 실패 처리 | unknown token, duplicate connection, config payload build failure를 register response와 node lifecycle event로 표현한다. |
|
||||
| 실행 요청 전달 | Edge service가 `SubmitRun` 요청을 `RunRequest`로 만들어 선택된 Node에 보낸다. 명시 node가 없고 연결 node가 1개면 single-node fallback을 사용한다. |
|
||||
| adapter 실행 | Node가 `RunRequest.adapter`로 adapter instance를 찾고 adapter `Execute`를 호출한다. admission은 adapter `Capabilities().MaxConcurrency` 기준이다. |
|
||||
| 실행 이벤트 스트림 | Node adapter가 낸 start, delta, reasoning_delta, complete, error, cancelled 이벤트를 `RunEvent`로 Edge에 relay한다. |
|
||||
| terminal event 합성 | adapter가 terminal event 없이 종료하면 Node가 terminal event를 합성한다. |
|
||||
| run cancel | Edge가 `CancelRequest`를 보내면 Node run manager가 active run context를 cancel한다. |
|
||||
| logical session 종료 | adapter가 `SessionTerminator`를 구현한 경우 `TERMINATE_SESSION`으로 session을 종료한다. 모든 adapter 공통 기능은 아니다. |
|
||||
| Node command | capabilities, transport status, usage status, session list, ollama API 계열 조회/제어성 command를 실행 요청과 분리해 처리한다. |
|
||||
| Node local run store | Node가 run id, adapter, target, session id, background, status, timestamps, error를 SQLite에 기록한다. |
|
||||
| Edge event fanout | Edge event bus가 run event와 node lifecycle event를 in-process subscriber에게 fanout한다. |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: Edge-Node TCP/protobuf transport, register handshake, run/cancel/command, Node adapter execution, Edge event bus fanout, Node local run store.
|
||||
- 제외: OpenAI-compatible/A2A HTTP request shape, Control Plane 운영 wire, provider-pool config refresh 상세, durable global history/audit.
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
### Node 등록
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Node
|
||||
participant EdgeTransport as Edge transport
|
||||
participant NodeStore as Edge NodeStore
|
||||
|
||||
Node->>EdgeTransport: TCP connect
|
||||
Node->>EdgeTransport: RegisterRequest(token)
|
||||
EdgeTransport->>NodeStore: token으로 NodeRecord 조회
|
||||
alt token valid
|
||||
EdgeTransport->>EdgeTransport: NodeConfigPayload 생성
|
||||
EdgeTransport-->>Node: RegisterResponse(accepted=true, config)
|
||||
EdgeTransport->>EdgeTransport: live registry 등록
|
||||
else token invalid or duplicate
|
||||
EdgeTransport-->>Node: RegisterResponse(accepted=false, reason)
|
||||
end
|
||||
```
|
||||
|
||||
### 실행 요청과 이벤트
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller
|
||||
participant EdgeService as Edge service
|
||||
participant EdgeTransport as Edge transport
|
||||
participant Node
|
||||
participant Adapter
|
||||
|
||||
Caller->>EdgeService: SubmitRun(adapter, target, input)
|
||||
EdgeService->>EdgeService: Node 선택
|
||||
EdgeService->>EdgeTransport: RunRequest
|
||||
EdgeTransport->>Node: RunRequest
|
||||
Node->>Node: adapter instance resolve
|
||||
Node->>Adapter: Execute(spec)
|
||||
Adapter-->>Node: RuntimeEvent(delta/start/complete)
|
||||
Node-->>EdgeTransport: RunEvent
|
||||
EdgeTransport-->>Caller: run stream
|
||||
```
|
||||
|
||||
### 취소와 session 종료
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant EdgeService as Edge service
|
||||
participant Node
|
||||
participant Adapter
|
||||
|
||||
alt cancel run
|
||||
EdgeService->>Node: CancelRequest(CANCEL_RUN, run_id)
|
||||
Node->>Node: active run context cancel
|
||||
else terminate session
|
||||
EdgeService->>Node: CancelRequest(TERMINATE_SESSION, adapter, target, session_id)
|
||||
Node->>Adapter: TerminateSession(target, session_id)
|
||||
end
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- `iop.edge-node-runtime-wire`: `agent-contract/inner/edge-node-runtime-wire.md`
|
||||
- proto 원문: `proto/iop/runtime.proto`
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- Edge의 node source of truth는 `configs/edge.yaml`과 `packages/go/config`의 `nodes[]` 구조다.
|
||||
- `RunEvent`는 adapter execution stream이고, `EdgeNodeEvent`는 node lifecycle/control event다.
|
||||
- Node local DB는 기본 `file:iop.db?cache=shared&mode=rwc`로 열린다.
|
||||
- heartbeat는 Edge와 Node transport 양쪽에서 30초 interval, 45초 wait 기준을 사용한다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `go test ./apps/edge/internal/transport ./apps/edge/internal/service ./apps/edge/internal/node`
|
||||
- `go test ./apps/node/internal/transport ./apps/node/internal/node ./apps/node/internal/router ./apps/node/internal/adapters ./apps/node/internal/store`
|
||||
- `make test-e2e` - Edge-Node와 OpenAI 보조 smoke를 함께 실행한다. runtime path 변경 시 사용자 흐름 검증을 대체하지 않는다.
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- mTLS helper는 존재하지만 현재 Edge-Node transport 설정에는 연결되어 있지 않다.
|
||||
- `TERMINATE_SESSION`은 모든 adapter에 공통으로 보장되는 기능이 아니다.
|
||||
- Node store는 전역 query/audit API가 아니다. 상위 운영 이력은 별도 설계가 필요하다.
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- 2026-07-07: 현재 코드, 계약, README 기준으로 bootstrap spec 작성.
|
||||
- 2026-07-07: 기능 목록 중심으로 축소하고 주요 흐름을 Mermaid sequence diagram으로 정리.
|
||||
115
agent-spec/runtime/provider-pool-config-refresh.md
Normal file
115
agent-spec/runtime/provider-pool-config-refresh.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
spec_doc_type: spec
|
||||
spec_id: runtime/provider-pool-config-refresh
|
||||
status: 부분
|
||||
source_evidence:
|
||||
- type: contract
|
||||
path: agent-contract/inner/edge-config-runtime-refresh.md
|
||||
notes: Edge config, provider pool, config refresh, Node payload 연결 계약
|
||||
- type: code
|
||||
path: packages/go/config/config.go
|
||||
notes: Edge config struct, provider/model validation, adapter normalization
|
||||
- type: code
|
||||
path: configs/edge.yaml
|
||||
notes: provider-pool 권장 설정 예시와 live refresh 설정 예시
|
||||
- type: code
|
||||
path: apps/edge/internal/service/model_queue.go
|
||||
notes: provider/resource capacity, priority, queue, long-context slot admission
|
||||
- type: code
|
||||
path: apps/edge/internal/configrefresh/classify.go
|
||||
notes: dry-run/apply classification과 changed path report 생성
|
||||
- type: code
|
||||
path: apps/edge/internal/bootstrap/runtime.go
|
||||
notes: mutable config apply, runtime snapshot 교체, Node refresh push
|
||||
- type: test
|
||||
path: packages/go/config/config_test.go
|
||||
notes: config load/validation 검증
|
||||
- type: test
|
||||
path: apps/edge/internal/configrefresh/classify_test.go
|
||||
notes: refresh classification 검증
|
||||
---
|
||||
|
||||
# 스펙: Provider Pool과 Config Refresh
|
||||
|
||||
## 목적
|
||||
|
||||
Edge 설정에서 provider-pool이 어떻게 모델 실행 후보를 고르고, 어떤 설정 변경이 재시작 없이 반영되는지 설명한다.
|
||||
|
||||
## 기능 목록
|
||||
|
||||
| 기능 | 설명 |
|
||||
|------|------|
|
||||
| model catalog | `models[].id`는 외부 OpenAI-compatible `model` key이자 provider-pool `ModelGroupKey`다. |
|
||||
| provider mapping | `models[].providers`는 provider id를 실제 served model name으로 매핑한다. |
|
||||
| node provider catalog | `nodes[].providers[]`는 Node 아래 resource/provider catalog이며 provider id는 Edge config에서 전역 유일해야 한다. |
|
||||
| config validation | config load가 provider id 참조, served model membership, numeric bounds, long-context budget을 검증한다. |
|
||||
| provider 후보 필터링 | dispatch는 connected node의 provider 후보 중 catalog match, enabled, healthy/available, capacity 조건을 만족하는 후보만 사용한다. |
|
||||
| capacity/priority dispatch | in-flight가 capacity 미만인 후보를 고르고, 동률이면 낮은 `priority`와 round-robin을 적용한다. |
|
||||
| long-context admission | estimated input token이 threshold 이상이면 `context_class=long`으로 분류하고, provider long slot이 있으면 일반 capacity slot과 함께 점유한다. |
|
||||
| config refresh dry-run/apply | loopback admin HTTP `POST /refresh`가 candidate config를 dry-run 또는 apply한다. |
|
||||
| refresh classification | listener, Edge identity, bootstrap path, adapter structural 변경 등은 restart-required로 분류한다. |
|
||||
| mutable apply | 적용 가능한 변경은 Edge `Cfg`, `NodeStore`, service/input model catalog, OpenAI long-context threshold를 copy-on-write로 교체한다. |
|
||||
| Node config refresh push | 변경이 있으면 Edge가 연결된 Node에 node-specific `NodeConfigRefreshRequest`를 push한다. |
|
||||
| Node registry swap | Node는 refresh payload로 새 adapter registry를 만들고 router registry를 swap한다. old registry stop은 active run이 있으면 drain 이후로 지연한다. |
|
||||
|
||||
## 범위
|
||||
|
||||
- 포함: Edge config load/default/validation, provider-pool dispatch, queue admission, long-context admission, config refresh classification/apply, Node config refresh payload.
|
||||
- 제외: 개별 adapter의 provider API 호출 세부, OpenAI HTTP request/response shape, Control Plane 원격 config 변경 UX, private credential 관리.
|
||||
|
||||
## 주요 흐름
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller
|
||||
participant Service as Edge service
|
||||
participant Queue as Provider queue
|
||||
participant Node
|
||||
|
||||
Caller->>Service: SubmitRun(model)
|
||||
Service->>Queue: provider 후보 선택
|
||||
Queue-->>Service: adapter + served target
|
||||
Service->>Node: RunRequest(adapter, target)
|
||||
|
||||
participant Operator
|
||||
participant Refresh as Config refresh
|
||||
Operator->>Refresh: POST /refresh(apply)
|
||||
Refresh->>Refresh: load, validate, classify
|
||||
Refresh->>Node: NodeConfigRefreshRequest
|
||||
```
|
||||
|
||||
## 계약
|
||||
|
||||
- `iop.edge-config-runtime-refresh`: `agent-contract/inner/edge-config-runtime-refresh.md`
|
||||
- `iop.edge-node-runtime-wire`: `agent-contract/inner/edge-node-runtime-wire.md`
|
||||
- proto 원문: `proto/iop/runtime.proto`
|
||||
|
||||
## 설정/데이터/이벤트
|
||||
|
||||
- `long_context_threshold_tokens` 기본 예시는 `100000`이고 0 이하 값은 config load에서 거부된다.
|
||||
- provider `enabled=false`는 dispatch pool에서 제외하지만 adapter process lifecycle 변경을 의미하지 않는다.
|
||||
- provider capacity, priority, max queue, queue timeout, enabled toggle, model generation policy는 live apply 대상으로 분류된다.
|
||||
- Edge listener, control plane, openai/a2a listener, bootstrap artifact path, node 추가/삭제, node token/alias, adapter 설정 변경은 restart-required 대상이다.
|
||||
- refresh result는 changed nodes/providers/models와 restart-required paths를 stable non-nil slice로 보고한다.
|
||||
|
||||
## 검증
|
||||
|
||||
- `go test ./packages/go/config`
|
||||
- `go test ./apps/edge/internal/configrefresh`
|
||||
- `go test ./apps/edge/internal/service`
|
||||
- `go test ./apps/edge/internal/node`
|
||||
- `go test ./apps/node/internal/adapters ./apps/node/internal/node`
|
||||
|
||||
## 한계와 주의사항
|
||||
|
||||
- provider health는 현재 config/provider snapshot 기반이다. 모든 runtime에 대한 active health probe가 완성된 것은 아니다.
|
||||
- refresh admin API는 operator-local 표면이다. 접근 제어 없이 public interface에 노출하지 않는다.
|
||||
- adapter structural 변경은 contract상 restart-required로 분류된다. Node handler가 registry swap을 지원하더라도 Edge refresh classifier가 허용한 변경만 apply해야 한다.
|
||||
- no-change apply는 runtime snapshot을 교체하지만 Node push는 생략한다.
|
||||
- `NodeRuntimeConfig.concurrency`는 legacy metadata이며 provider-pool admission의 node-wide capacity로 쓰지 않는다.
|
||||
- credential, private endpoint, bearer token 원문은 tracked config/docs/spec에 남기지 않는다.
|
||||
|
||||
## 변경 기록
|
||||
|
||||
- 2026-07-07: 현재 코드, 계약, config 예시 기준으로 bootstrap spec 작성.
|
||||
- 2026-07-07: 기능 목록 중심으로 축소하고 주요 흐름을 Mermaid sequence diagram으로 정리.
|
||||
Loading…
Reference in a new issue