iop/agent-roadmap/archive/phase/automation-runtime-bridge/milestones/agent-readable-repository-refactor.md

14 KiB

Milestone: 에이전트 작업성 중심 저장소 구조 리팩터링

위치

목표

생성물과 대형 데이터 파일을 제외한 사람이 관리하는 프로젝트 소스와 테스트를 책임과 변경 이유가 드러나는 단위로 재구성한다. 기존 API, wire, config schema와 런타임 동작을 유지하면서 에이전트가 한 기능을 수정하기 위해 읽어야 하는 파일 수와 task-local context를 줄이고, 이후 변경에서 다시 거대 파일이 생기지 않도록 측정 가능한 기준선을 둔다.

상태

[완료]

승격 조건

  • 없음

구현 잠금

  • 상태: 해제
  • SDD: 불필요
  • SDD 문서: 없음
  • SDD 사유: 외부 API/proto/config schema나 runtime 책임 경계를 바꾸지 않고 동일 패키지 내 책임 분리, 테스트 재배치와 저장소 위생 개선을 수행하는 동작 보존형 리팩터링이다.
  • 잠금 해제 조건: 없음
  • 결정 필요: 없음

범위

  • 추적 중인 빌드 바이너리와 파일 길이 측정 노이즈를 정리하고, 생성물·lockfile·PBX·대형 fixture 예외를 구분하는 저장소 가독성 기준선을 둔다.
  • apps/edge/internal/openai, apps/edge/internal/service, apps/edge/cmd/edge, apps/node/internal/node, apps/node/internal/adapters, apps/control-plane/cmd/control-plane, packages/go/config, Flutter client와 E2E script의 거대 파일을 책임과 변경 이유 기준으로 분해한다.
  • 거대 테스트 파일을 기능 시나리오별로 나누고, 만능 fake와 반복 fixture setup을 feature-local stub/helper로 정리한다.
  • 120줄 이상 장기 함수, 과도한 parameter list와 closure 기반 상태 처리를 명명된 context/session 객체와 단계별 함수 후보로 정리한다.
  • agent-test inventory의 canonical 데이터는 유지하면서 프로젝트 전용 query 경로로 전체 읽기 비용을 줄인다.
  • agent-ops/rules/common/**agent-ops/skills/common/**는 공유 Agent-Ops 경계이므로 이 프로젝트 리팩터링의 측정·수정·분해 대상에서 제외한다.
  • 파일 이동 뒤 domain rule, agent-spec source evidence와 현재 계약 포인터가 실제 구현 경로를 계속 가리키도록 동기화한다.

기능

Epic: [hygiene] 저장소 노이즈와 가독성 기준선

에이전트 탐색을 오염시키는 artifact를 제거하고 신규 구조 부채를 조기에 확인할 수 있는 기준을 만든다.

  • [tracked-artifacts] 루트의 추적 중 ELF 빌드 산출물 node, edge, openai.test를 Git 추적에서 제거하고 공식 빌드 산출 위치와 ignore 규칙을 정렬한다. Git history 재작성은 수행하지 않는다. 검증: git ls-files node edge openai.test가 비어 있고 공식 build target이 build/ 아래 산출물을 만든다.
  • [readability-baseline] 생성물과 data-only 예외를 제외한 파일 LOC, 함수 크기와 task-local read set을 점검하는 기준선과 ratchet 정책을 둔다. 기본 code/test 입력은 Git이 추적하는 Go/Dart/Shell/Python/Kotlin/Swift 파일로 정의하고 protobuf·Dart 생성 경로와 공유 Agent-Ops common 경계는 제외한다. 운영 파일 500줄 경고/800줄 분리 검토/1,000줄 예외, 테스트 800줄 경고/1,000줄 분리 검토, 함수 80줄 경고/120줄 분리 검토, 프로젝트 전용 Skill 진입 파일 300줄 경고/500줄 분리 검토를 기본값으로 기록한다. 검증: 동일 입력에서 재현 가능한 audit 결과가 생성되고 신규 초과 또는 기존 초과 증가가 실패하거나 명시적 allowlist 사유를 요구한다.

Epic: [tests] 기능 시나리오 기반 테스트 분해

기능 변경 시 관련 테스트와 fixture만 읽어도 회귀 조건을 이해할 수 있게 테스트 토폴로지를 재구성한다.

  • [openai-tests] apps/edge/internal/openai/server_test.go를 auth/routes/models, chat handler/stream, Responses, provider tunnel, workspace/metadata, tool parsing/validation 시나리오로 분리하고 거대 fakeRunService를 feature-local stub 또는 함수 필드 기반 test double로 축소한다. 검증: go test ./apps/edge/internal/openai가 통과하고 기존 테스트 케이스가 누락되지 않는다.
  • [core-tests] packages/go/config/config_test.go, apps/node/internal/node/node_test.go, apps/edge/internal/service/model_queue_test.go, apps/edge/internal/service/service_test.go, apps/edge/internal/bootstrap/runtime_test.go를 config 영역과 run/cancel/command/refresh/tunnel, admission/scheduling/long-context/snapshot, runtime refresh 책임별로 분리하고 반복 setup을 명시적 helper로 정리한다. 검증: go test ./packages/go/config ./apps/node/internal/node ./apps/edge/internal/service ./apps/edge/internal/bootstrap가 통과한다.
  • [adapter-command-tests] apps/node/internal/adapters의 1,000줄 이상 adapter/CLI 테스트와 apps/edge/cmd/edge, apps/control-plane/cmd/control-plane, apps/edge/internal/configrefresh의 거대 command/config refresh 테스트를 실행 모드와 command 책임별로 분리한다. 검증: 대상 패키지 테스트가 통과하고 audit 결과에 사유 없는 1,000줄 초과 테스트가 남지 않는다.
  • [client-tests] apps/client/test/widget_test.dart를 app shell과 panel/integration 시나리오별 파일로 분리하고 공통 harness가 개별 테스트 의도를 가리지 않게 축소한다. 검증: make client-test가 통과한다.

Epic: [modules] 동일 패키지 내 책임 중심 소스 분해

새 package/API를 먼저 만들지 않고 기존 package 경계를 유지한 채 파일명만으로 주요 책임을 찾을 수 있게 한다.

  • [openai-modules] types.go, stream.go, chat_handler.go, responses_handler.go를 chat/Responses DTO, text tool parser, schema/command normalization, normalized SSE, provider tunnel/rewrite, route/policy 책임별 파일로 분리한다. 검증: 공개·내부 동작 계약을 바꾸지 않고 go test ./apps/edge/internal/openai가 통과한다.
  • [config-modules] packages/go/config/config.go를 Node/Edge/provider/adapter 타입, load/default, normalization, validation 책임별 파일로 분리하고 테스트 파일과 대응시킨다. 검증: config 예시 roundtrip과 go test ./packages/go/config가 통과한다.
  • [service-node-modules] Edge run_dispatch.go/model_queue.go와 Node node.go를 run/provider resolution/provider pool/tunnel/cancel/session, admission/release/snapshot, run/tunnel/command/refresh/sink 책임별 파일로 분리한다. 검증: go test ./apps/edge/internal/service ./apps/node/internal/node가 통과한다.
  • [secondary-modules] OpenAI-compatible/vLLM/Ollama/CLI adapter, Flutter runtime panel, E2E shell처럼 500~800줄 이상인 후순위 후보를 동일한 책임/변경 이유 기준으로 분해하고, 단순 LOC 충족을 위한 micro-package나 utils 집합은 만들지 않는다.

Epic: [complexity] 장기 함수와 상태 전달 구조화

파일 이동만으로 남는 함수 내부 인지 복잡도를 명명된 상태와 단계별 처리 경계로 낮춘다.

  • [stream-session] streamChatCompletion의 content/reasoning/tool/usage/trace 상태와 terminal event 처리를 명명된 stream session/context와 event별 단계로 분리한다. 검증: live SSE, buffered strict output, tool-call, cancel/timeout, usage 회귀 테스트가 통과한다.
  • [dispatch-context] 10개 이상 parameter를 전달하는 Chat/Responses/provider-pool 경로를 명명된 request/dispatch context로 바꾸고, queue reservation과 release의 성공/실패 경로를 한눈에 추적할 수 있게 한다.
  • [long-functions] 120줄 이상 함수의 책임 혼합 여부를 점검하고 Classify, adapter Execute, Node/transport handler와 E2E orchestration을 단계별 함수로 축소하거나 응집된 예외 사유를 남긴다.

Epic: [agent-context] 구조화 인벤토리 읽기 비용 절감

큰 프로젝트 인벤토리는 필요한 조각만 결정적으로 조회할 수 있게 한다.

  • [inventory-query] agent-test/dev/inventory.yamlagent-test/dev-corp/inventory.yaml의 canonical machine-readable 역할은 유지하면서 env/model/node/provider selector로 필요한 bounded 결과만 얻는 결정적 query 경로를 제공한다.
  • [evidence-links] 활성 코드의 bare SDD section anchor를 현재 invariant 또는 contract/spec 식별자로 보강하고, 파일 분해 뒤 domain rule과 agent-spec source_evidence가 실제 현재 경로를 가리키도록 갱신한다.

Epic: [verification] 동작 보존과 가독성 회귀 검증

구조 변경이 사용자 실행 계약을 바꾸지 않았고 새 기준선이 실질적인 읽기 범위 축소로 이어졌음을 검증한다.

  • [regression] 전체 Go/Flutter 회귀와 변경 범위의 E2E/full-cycle 검증을 수행한다. 검증: go test ./..., make client-test와 testing domain rule이 요구하는 관련 smoke/full-cycle 경로가 통과한다.
  • [read-set] 대표 프로젝트 변경 시나리오인 OpenAI chat stream, provider-pool dispatch, Node config refresh, Flutter runtime panel마다 필수 규칙·주요 소스·직접 테스트 파일 목록과 LOC 합계를 재현 가능한 audit evidence로 남긴다. 각 task-local read set은 가능한 경우 1,500~2,000줄 안으로 축소하고, 공유 Agent-Ops common 경로는 포함하지 않는다.

완료 리뷰

  • 상태: 통과
  • 요청일: 2026-07-19
  • 완료 근거: 전체 저장소 회귀runtime full-cycle이 PASS했고, 후자는 현재 구현 HEAD에서 Go/Flutter/readability 회귀와 E2E 및 실제 CLI 4종 검증을 완료했다.
  • 완료 근거: 모든 기능 Task가 evidence와 함께 충족됐고 구현 잠금과 SDD 차단 항목이 없다.
  • 코드레벨 감사: 현재 소스가 runtime full-cycle 검증 커밋과 동일하며, 현재 워크트리에서 Go/Flutter/readability/E2E 회귀를 다시 통과했다. 리팩터링 전 통합 테스트를 가리키던 활성 계약 포인터는 현재 분할 테스트 경로로 보정했다.
  • Spec sync: Spec update not needed. 관련 현재 구현 스펙인 Edge-Node 실행, Provider Pool Config Refresh, OpenAI-compatible 입력 표면의 source evidence와 불변식이 현재 코드와 일치한다.
  • 검토 항목:
    • 생성물 예외를 제외한 P0/P1 거대 파일이 기준선 아래로 분해되거나 명시적 예외 근거를 가진다
    • 전체 Go/Flutter 회귀와 관련 E2E/full-cycle 검증이 통과한다
    • 공유 Agent-Ops common 경계가 프로젝트 readability 측정·수정 대상에서 제외되고 마일스톤 중 유입된 common 변경이 복구된다
    • domain rule, agent-spec, contract pointer가 이동된 현재 코드 경로와 일치한다
  • agent-ui 상태 반영: 해당 없음
  • 리뷰 코멘트: 종료 차단 이슈 없음. 작은 계약 포인터 불일치는 검증 후 즉시 보정했다.

범위 제외

  • OpenAI-compatible/A2A API, proto wire, config schema, runtime routing 정책의 기능 변경
  • LOC를 맞추기 위한 package 남발, 타입 하나당 파일 하나 생성, 범용 utils/common 패키지 승격
  • protobuf/Dart 생성물, lockfile, PBX project, data-only fixture에 대한 동일 LOC 제한 강제
  • 기존 Git history에서 binary blob을 제거하는 history rewrite
  • archive 문서 재포맷이나 과거 완료 작업의 일반 컨텍스트 로딩
  • agent-ops/rules/common/**, agent-ops/skills/common/**의 규칙·스킬·템플릿 변경 또는 프로젝트 readability ratchet 편입
  • 리팩터링 과정에서 발견한 신규 제품 기능의 동시 구현

작업 컨텍스트

  • 관련 경로: apps/edge/internal/openai, apps/edge/internal/service, apps/edge/cmd/edge, apps/node/internal/node, apps/node/internal/adapters, apps/control-plane/cmd/control-plane, packages/go/config, apps/client, scripts, agent-ops/skills/project, agent-test, agent-spec
  • 표준선(선택): 같은 package 안에서 테스트와 파일을 먼저 기계적으로 분해하고 회귀 검증을 확보한 뒤 장기 함수와 상태 전달을 구조화한다. 파일 수보다 변경 이유의 응집도와 task-local read set을 우선한다. 공유 Agent-Ops common 경계는 수정하거나 프로젝트 ratchet 대상으로 삼지 않는다.
  • 기준선(2026-07-16): Git이 추적하는 Go/Dart/Shell/Python/Kotlin/Swift 중 proto/gen/**apps/client/lib/gen/**를 제외한 사람이 관리하는 코드·테스트는 242개, 파일 LOC 중앙값은 216줄, 500줄 이상은 54개, 1,000줄 이상은 22개이며 이 중 테스트가 14개, 운영 코드가 8개다. 루트 추적 ELF 3개는 합계 65,474,597byte(약 65.5MB)다.
  • SDD 재판정 조건: 리팩터링 중 외부 API/proto/config schema, runtime routing 정책 또는 공유 Agent-Ops common 경계 변경이 필요해지면 해당 변경을 현재 범위에서 중단하고 roadmap/SDD gate를 재판정한다.
  • 선행 작업: 없음
  • 후속 작업: 필요하면 Epic별 split 구현 계획으로 나누되 같은 Milestone 완료 근거로 수렴한다.
  • 확인 필요: 없음