Cline이 텍스트 XML 블록으로 도구 호출을 내보내는 경우 OpenAI-compatible tool_calls 응답으로 변환해야 클라이언트 실행 루프가 멈추지 않는다. Node resource model 로드맵과 agent-task 문서는 요청된 전체 변경 범위에 포함한다.
12 KiB
Node Resource Model Contract Plan
이 파일을 읽는 구현 에이전트에게
이 계획을 구현한 뒤에는 반드시 같은 디렉터리의 CODE_REVIEW-cloud-G07.md에서 구현 에이전트 소유 섹션을 실제 구현 내용, 설계 결정, 검증 출력으로 채운다. 구현 중 선택된 Milestone의 구현 잠금 > 결정 필요가 실구현을 막을 때만 review stub의 사용자 리뷰 요청 섹션을 채우고 멈춘다. 직접 사용자에게 질문하거나 선택지를 제시하거나 request_user_input을 호출하지 않는다. 외부 환경, secret, 서비스 준비, 증거 공백은 사용자 리뷰 요청이 아니라 검증/후속 계획으로 기록한다.
배경
현재 config와 wire는 nodes[].adapters와 nodes[].providers를 이미 갖고 있지만, 계약 문서는 NodeRuntimeConfig.concurrency를 node-wide 실행 제한으로 정의한다. 사용자가 정리한 방향은 node가 global gate가 아니라 하나의 identity/connection owner이고, provider/CLI 같은 resource가 node 아래에 명시되는 구조다. 첫 단계는 구현 전 계약과 validation 기준을 맞춰 이후 Node/Edge 변경이 같은 의미를 공유하게 하는 것이다.
사용자 리뷰 요청 흐름
구현 중 사용자 리뷰 요청은 선택된 Milestone lock 결정이 직접 막을 때만 CODE_REVIEW-cloud-G07.md의 사용자 리뷰 요청 섹션에 기록한다. 선택된 Milestone의 구현 잠금은 해제되어 있으므로 기본값은 없음이다.
Roadmap Targets
- Milestone:
agent-roadmap/phase/operational-observability-provider-management/milestones/node-resource-model-unification.md - Task ids:
contract-schema: Node runtime contract and resource catalog validation
- Completion mode: check-on-pass
분석 결과
읽은 파일
agent-ops/rules/project/rules.mdagent-ops/rules/common/rules-roadmap.mdagent-ops/skills/common/router.mdagent-ops/skills/common/plan/SKILL.mdagent-ops/skills/common/_templates/implementation-user-review-request-section.mdagent-roadmap/current.mdagent-roadmap/phase/operational-observability-provider-management/PHASE.mdagent-roadmap/phase/operational-observability-provider-management/milestones/node-resource-model-unification.mdagent-roadmap/sdd/operational-observability-provider-management/node-resource-model-unification/SDD.mdagent-roadmap/phase/update-plane-self-update-foundation/PHASE.mdagent-roadmap/phase/update-plane-self-update-foundation/milestones/update-plane-stable-protocol.mdagent-test/local/rules.mdagent-test/local/node-smoke.mdagent-test/local/edge-smoke.mdagent-test/local/platform-common-smoke.mdagent-test/dev/inventory.yamlagent-test/dev/edge-smoke.mdagent-test/dev/node-smoke.mdagent-test/dev/platform-common-smoke.mdagent-contract/index.mdagent-contract/inner/edge-node-runtime-wire.mdagent-contract/inner/control-plane-edge-wire.mdagent-contract/inner/edge-config-runtime-refresh.mdagent-contract/outer/openai-compatible-api.mdproto/iop/runtime.protoproto/iop/control.protopackages/go/config/config.goapps/edge/internal/edgevalidate/validate.goapps/edge/internal/configrefresh/classify.goapps/edge/internal/node/mapper.goapps/node/internal/adapters/config_set.gopackages/go/config/config_test.goapps/edge/internal/configrefresh/classify_test.goapps/edge/internal/node/mapper_test.goapps/node/internal/adapters/config_set_test.go
SDD 기준
선택된 Milestone은 SDD: 필요이며 agent-roadmap/sdd/operational-observability-provider-management/node-resource-model-unification/SDD.md가 [승인됨], SDD 잠금 해제 상태다. 이 subtask는 Acceptance Scenario S01, S02와 Milestone Task contract-schema를 대상으로 한다.
Evidence Map은 contract/proto/comment diff, config validation unit test, missing/disabled adapter validation output을 요구한다. 따라서 구현 체크리스트는 NodeRuntimeConfig.concurrency legacy/no-op 계약 정리, nodes[].providers[] resource catalog 문서화, provider adapter reference validation, 관련 regression test를 포함한다.
테스트 환경 규칙
test_env는 기본값 local이다. agent-test/local/rules.md와 matching profile node-smoke, edge-smoke, platform-common-smoke를 읽었다. 이 subtask는 packages/go/**, proto/**, agent-contract/**를 건드리므로 go test -count=1 ./packages/go/... ./proto/gen/...와, proto를 바꾸는 경우 make proto를 적용한다. dev-runtime 문서와 원격 smoke는 이 subtask의 필수 검증이 아니며 04번 subtask가 맡는다.
테스트 커버리지 공백
NodeRuntimeConfig.concurrency의미를 legacy/no-op으로 바꾸는 계약 문구는 문서성 변경이라 unit coverage가 없다.- provider adapter reference validation은 config/edgevalidate regression test가 필요하다.
ProviderSnapshot을 resource snapshot으로 취급하는 compat 의미는 proto field 추가 없이 문서와 status tests로 검증한다.
심볼 참조
삭제/rename 예정 symbol은 없다. 의미 변경 대상은 NodeRuntimeConfig.concurrency, ProviderSnapshot, nodes[].providers[].adapter, runtime.concurrency 문자열이다.
분할 판단
split policy를 먼저 평가했다. 공유 task group은 m-node-resource-model-unification이다.
01_contract_schema: 계약/config validation 기준.02+01_node_admission: 01 완료 후 Node admission 의미 변경.03+01_edge_dispatch_status: 01 완료 후 Edge dispatch/status 의미 변경.04+01,02,03_dev_runtime_profile: 앞선 세 구현 완료 후 dev-runtime 문서/config/smoke 정리.
이 subtask는 선행 의존성이 없다.
범위 결정 근거
새 외부 API endpoint나 gRPC 도입은 제외한다. proto는 가능하면 field 추가 없이 legacy ProviderSnapshot을 resource snapshot compat surface로 문서화하고, 실제 새 field가 꼭 필요하다고 구현 중 판단될 때만 make proto와 생성물 diff를 포함한다.
빌드 등급
cloud-G07: config/proto/contract 의미가 여러 런타임 경계에 영향을 주며, wrong-local implementation이 dev/runtime status를 깨뜨릴 수 있다.
구현 체크리스트
NodeRuntimeConfig.concurrency를 node-wide admission source가 아닌 legacy/compat runtime payload로 계약 문서와 comments에서 정리한다.nodes[].providers[]를 현재 wire의 resource catalog로 해석한다는 compat 기준을 문서화하고,category=cli|api|local_inference가 CLI/provider/resource 구분자임을 명시한다.nodes[].providers[].adapter가 같은 node 안의 enabled adapter instance로 해석되어야 한다는 config validation을 추가한다.- provider adapter reference, duplicate/resource category, legacy config compatibility regression test를 추가한다.
- proto 변경이 발생하면
make proto를 실행하고 generated diff가 원본 proto와 일치하는지 확인한다. - CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 실제 구현 내용과 검증 출력으로 채운다. 이 항목이 완료되기 전에는 구현이 완료된 것이 아니다.
[API-1] Runtime Concurrency Contract
문제: agent-contract/inner/edge-node-runtime-wire.md는 NodeRuntimeConfig.concurrency를 node-wide 실행 제한으로 정의하고, apps/edge/internal/configrefresh/classify.go:220도 live-applyable node-wide concurrency로 주석화한다. 사용자의 방향과 충돌한다.
해결 방법: contract, proto comment, Go comments를 legacy compatibility payload; provider/resource capacity owns admission 의미로 바꾼다. Wire field를 즉시 제거하지 않는다.
Before:
// proto/iop/runtime.proto:251
message NodeRuntimeConfig {
int32 concurrency = 1;
reserved 2;
}
After:
// NodeRuntimeConfig carries legacy node runtime metadata. Execution admission
// must not use this as a node-wide global gate; provider/resource capacity owns concurrency.
message NodeRuntimeConfig {
int32 concurrency = 1; // legacy compatibility, 0/unset means no node-wide limit
reserved 2;
}
수정 파일 및 체크리스트:
proto/iop/runtime.protoagent-contract/inner/edge-node-runtime-wire.mdagent-contract/inner/edge-config-runtime-refresh.mdapps/edge/internal/configrefresh/classify.goapps/edge/internal/configrefresh/classify_test.go
테스트 작성: TestClassifyRuntimeConcurrencyLegacyAppliedOrIgnored 형태로 기존 runtime.concurrency only diff의 기대 의미를 갱신한다. 즉시 제거가 아니면 refresh result는 compat상 applied여도 admission 변경을 뜻하지 않는다고 확인한다.
중간 검증:
go test -count=1 ./apps/edge/internal/configrefresh
[API-2] Resource Catalog Validation
문제: packages/go/config/config.go:112의 NodeProviderConf는 Adapter를 문자열로 받지만, LoadEdge의 provider loop(packages/go/config/config.go:512)와 edgevalidate.ValidateEdgeConfig는 adapter가 같은 node의 enabled adapter instance인지 확인하지 않는다. Edge dispatch의 providerDispatchable도 apps/edge/internal/service/run_dispatch.go:476에서 non-empty만 본다.
해결 방법: edgevalidate 또는 config helper에 provider adapter reference resolver를 추가한다. Exact instance key를 우선하고, type-name route는 enabled instance가 정확히 1개일 때만 허용한다. category=cli resource는 CLI enabled를 요구한다.
수정 파일 및 체크리스트:
apps/edge/internal/edgevalidate/validate.gopackages/go/config/config.gopackages/go/config/config_test.goapps/edge/internal/edgevalidate/*_test.go또는 기존 test package
테스트 작성: bad adapter, disabled adapter, ambiguous type route, valid CLI resource, valid OpenAI-compatible provider instance를 table test로 추가한다.
중간 검증:
go test -count=1 ./packages/go/config ./apps/edge/internal/edgevalidate
[API-3] Resource Snapshot Compatibility
문제: wire는 proto/iop/runtime.proto:118의 ProviderSnapshot과 proto/iop/control.proto:83의 provider_snapshots만 갖는다. 이름은 provider지만 사용자는 CLI/provider 등 resource 목록을 node 아래에 보고 싶어 한다.
해결 방법: field rename 없이 ProviderSnapshot을 legacy wire name으로 유지하고, 계약 문서에서 category가 resource kind를 나타내며 provider-pool 대상은 models[].providers에 참조된 catalog resource뿐이라고 명시한다. 실제 status 정리는 03번 subtask에서 수행한다.
수정 파일 및 체크리스트:
proto/iop/runtime.protoproto/iop/control.protoagent-contract/inner/control-plane-edge-wire.mdagent-contract/inner/edge-config-runtime-refresh.md
테스트 작성: proto field 추가가 없으면 새 generated test는 생략한다. 문서/comment-only면 go test regression으로 충분하다.
중간 검증:
go test -count=1 ./proto/gen/...
수정 파일 요약
| 파일 | 항목 |
|---|---|
proto/iop/runtime.proto |
API-1, API-3 |
proto/iop/control.proto |
API-3 |
agent-contract/inner/edge-node-runtime-wire.md |
API-1 |
agent-contract/inner/control-plane-edge-wire.md |
API-3 |
agent-contract/inner/edge-config-runtime-refresh.md |
API-1, API-3 |
packages/go/config/config.go |
API-2 |
packages/go/config/config_test.go |
API-2 |
apps/edge/internal/edgevalidate/validate.go |
API-2 |
apps/edge/internal/configrefresh/classify.go |
API-1 |
apps/edge/internal/configrefresh/classify_test.go |
API-1 |
최종 검증
go test -count=1 ./packages/go/... ./proto/gen/... ./apps/edge/internal/configrefresh ./apps/edge/internal/node
Proto 원본을 변경했다면 추가로 실행한다.
make proto
git diff -- proto/gen/iop
모든 코드 변경 완료 후 반드시 CODE_REVIEW-*-G??.md의 구현 에이전트 소유 섹션을 채운다. 이 파일 작성이 구현의 마지막 단계다.