feat: iop-agent-cli-runtime milestone & SDD, update roadmap phases and SDDs

This commit is contained in:
toki 2026-07-27 20:21:28 +09:00
parent 0e12a540c8
commit cc5f99bd11
12 changed files with 352 additions and 69 deletions

View file

@ -75,7 +75,7 @@ Phase는 실행 순서가 아니라 도메인/책임 영역의 구조적 지도
- [진행중] Automation Runtime과 Bridge 확장
- 경로: [PHASE.md](phase/automation-runtime-bridge/PHASE.md)
- 요약: 정적 lane/G 이후의 시간대·quota 기반 `adapter + target` 선택과 작업별 failover를 우선 구현하고, provider/grade routing 뒤에는 Node와 Edge 없는 Desktop Agent가 공유하는 공통 Go Agent Task runtime으로 현재 Python 감시 루프를 전체 동등성 기준에서 이전한다. 원격 터널링과 oto scheduler/CI-CD는 2차로 잠근다.
- 요약: 정적 lane/G 이후의 시간대·quota 기반 `adapter + target` 선택과 작업별 failover를 우선 구현하고, provider/grade routing 뒤에는 Node와 독립 `iop-agent` CLI가 공유하는 공통 Go Agent Task runtime으로 현재 Python 감시 루프를 전체 동등성 기준에서 이전한다. Flutter 설정 UI와 Unity 3D Character는 CLI 이후 별도 Milestone으로 두고, 원격 터널링과 oto scheduler/CI-CD는 2차로 잠근다.
- [계획] 지식과 도구 최적화 확장
- 경로: [PHASE.md](phase/knowledge-tool-optimization-extension/PHASE.md)

View file

@ -8,7 +8,7 @@
Runtime과 Automation 실행 흐름을 공통화하고, agent 설치형 대상과 비설치형 대상의 제어 경로를 분리해 확장한다.
CLI 실행, specialized agent 등록, bootstrap/enrollment, OpenAI-compatible workspace agent 실행 계약을 서로 충돌하지 않는 운영 경로로 정리했다.
NomadCode가 IOP를 실행 백엔드로 사용할 수 있도록 하는 Responses 기반 workspace agent 실행 계약과 정적 lane/G 결과를 시간대·quota·실행 상태와 결합하는 Agent Task 동적 실행 Target Selector를 완료했다. 후속으로 provider/grade routing을 닫고, Node와 Edge 없는 Desktop Agent가 함께 사용하는 공통 Go Agent Task runtime으로 현재 Python 감시 루프를 전체 동등성 기준에서 이전한다.
NomadCode가 IOP를 실행 백엔드로 사용할 수 있도록 하는 Responses 기반 workspace agent 실행 계약과 정적 lane/G 결과를 시간대·quota·실행 상태와 결합하는 Agent Task 동적 실행 Target Selector를 완료했다. 후속으로 provider/grade routing을 닫고, Node와 독립 `iop-agent` CLI가 함께 사용하는 공통 Go Agent Task runtime으로 현재 Python 감시 루프를 전체 동등성 기준에서 이전한다. Flutter 설정 UI와 Unity 3D Character는 CLI 이후의 별도 Milestone으로 둔다.
원격 터미널/CLI 터널링과 oto scheduler/CI-CD 자동화는 2차 스케치로 잠그고, 현재 활성 구현 범위로 끌어오지 않는다.
## Milestone 흐름
@ -94,9 +94,9 @@ Phase를 가로지르는 실제 다음 작업 선택은 [전역 마일스톤 실
- 경로: [cli-agent-group-grade-routing](milestones/cli-agent-group-grade-routing.md)
- 요약: `PLAN-local-G08.md`, `CODE_REVIEW-cloud-G07.md` 같은 예약어/lane/grade 파일명을 기준으로 CLI provider agent를 목적별 agent group에 라우팅하고, 수동/자동 grade range assignment와 OpenAI-compatible `metadata.agent_group.task_file` 계약을 정리한다.
- [계획] 공통 Agent Task Runtime과 Desktop Agent
- 경로: [shared-agent-task-runtime-desktop-agent](milestones/shared-agent-task-runtime-desktop-agent.md)
- 요약: 현재 Python 감시·dispatcher 동작과 Node CLI runtime을 공통 Go CLI Provider·AgentTaskManager로 이전하고, Node와 Edge 없는 Flutter macOS Desktop Agent가 단일 구현을 공유한다.
- [스케치] IOP Agent CLI Runtime
- 경로: [iop-agent-cli-runtime](milestones/iop-agent-cli-runtime.md)
- 요약: 현재 Python 감시·dispatcher와 Node CLI runtime의 전체 동등성을 공통 Go CLI Provider·AgentTaskManager 및 독립 `iop-agent` binary로 이전하고 UI 구현은 후속 Milestone으로 분리한다.
- [스케치] 에이전트 작업 루프 오케스트레이션 MVP
- 경로: [agent-workflow-loop-orchestration-mvp](milestones/agent-workflow-loop-orchestration-mvp.md)
@ -114,6 +114,10 @@ Phase를 가로지르는 실제 다음 작업 선택은 [전역 마일스톤 실
- 경로: [oto-automation-scheduler-second-wave](milestones/oto-automation-scheduler-second-wave.md)
- 요약: oto를 이용한 자동화, scheduler, CI-CD 연동은 MVP 이후 2차 후보로 스케치한다.
- [보류] 공통 Agent Task Runtime과 Desktop Agent
- 경로: [shared-agent-task-runtime-desktop-agent](milestones/shared-agent-task-runtime-desktop-agent.md)
- 요약: 공통 runtime, Flutter Desktop과 배포를 결합한 기존 계획은 IOP Agent CLI와 후속 Flutter·Unity Milestone으로 분리하기 위해 보류하고 요구사항 참조로 유지한다.
- [보류] 원격 터미널/CLI 터널링 POC (2차)
- 경로: [remote-terminal-bridge-poc](milestones/remote-terminal-bridge-poc.md)
- 요약: Agent를 설치하기 어려운 host/device 또는 특정 Node의 CLI agent를 Socket 경유로 다른 원격지에 연결하는 터널링 POC는 MVP 이후 2차로 보류한다.
@ -122,15 +126,15 @@ Phase를 가로지르는 실제 다음 작업 선택은 [전역 마일스톤 실
- OpenAI-compatible API와 A2A API에 terminal 제어 기능을 억지로 싣지 않는다.
- Edge는 실행 요청의 broker 역할을 하고, Node는 대상 transport 실행자 역할을 유지한다.
- 독립 Desktop Agent는 Edge를 포함하거나 요구하지 않으며, Node와 동일한 공통 Go CLI Provider·AgentTaskManager를 host adapter로 소비한다.
- `iop-agent`는 Edge를 포함하거나 요구하지 않는 독립 headless CLI이며, Node와 동일한 공통 Go CLI Provider·AgentTaskManager를 host adapter로 소비한다.
- 설치 가능한 대상은 bootstrap/enrollment 경로로, 설치가 어렵거나 일회성 유지보수 대상은 remote terminal bridge 경로로 구분한다.
- OpenAI-compatible Responses 표면은 외부 모델 호출 호환을 위한 입력 표면이며, IOP 고유 운영 제어는 native protocol이나 명시 운영 API로 분리한다.
- NomadCode 지원을 위한 `metadata.workspace` 실행 계약은 provider 확장, Lemonade 추가, remote terminal bridge보다 먼저 닫는다.
- Agent Task runtime은 사용자 workspace의 Milestone/Plan/Review/work-log 파일을 durable source of truth로 사용하고 app store는 provider/global 설정, project registry와 최소 checkpoint만 소유한다.
- 에이전트 작업 루프 오케스트레이션은 사용자가 agent-ops 스킬을 직접 실행하지 않은 일반 요청을 direct, Plan, Milestone으로 분류하고, Plan/Milestone이면 사용자 agent의 tool call로 작업 파일을 만들고 그 파일 상태를 연결하는 상위 IOP 기능으로 별도 소유한다.
- 공통 Agent Task runtime은 위 오케스트레이션과 Node/Desktop host가 공통으로 소비하는 provider 실행·선택·관측·복구 기반이며, 최초 요청 분류와 작업 파일 생성의 의미를 대체하지 않는다.
- 공통 Agent Task runtime은 위 오케스트레이션과 Node/`iop-agent` host가 공통으로 소비하는 provider 실행·선택·관측·복구 기반이며, 최초 요청 분류와 작업 파일 생성의 의미를 대체하지 않는다.
- Python dispatcher/selector는 동작·정책·오류 evidence의 참조로만 사용하며 production runtime에서 실행하거나 가져오지 않는다.
- provider 실행, quota/status, stream/session, failure와 AgentTaskManager는 공통 Go package가 단일 구현으로 소유한다. Node와 Desktop host에 이를 복사하거나 중복 선언하지 않는다.
- provider 실행, quota/status, stream/session, failure와 AgentTaskManager는 공통 Go package가 단일 구현으로 소유한다. Node와 `iop-agent` host에 이를 복사하거나 중복 선언하지 않는다. Flutter와 Unity는 후속 client이며 이 실행 로직을 소유하지 않는다.
- 선택 엔진은 하나의 provider/model을 반환하는 공통 evaluator와 host별 정책 입력을 분리하며, app 기본값 뒤 project override와 ordered rule priority를 적용한다.
- Provider 사용량 알림은 공통 runtime의 quota/status/failure event를 소비하는 운영 표면으로 두고, provider 선택·retry/failover·task continuation을 다시 구현하지 않는다.
- 원격 터미널/CLI 터널링 POC와 oto scheduler/CI-CD 연동은 현재 활성 작업에서 제외하고, provider 상태/capacity queue와 운영 관측 MVP 이후 재개 후보로 둔다.

View file

@ -117,8 +117,8 @@ MVP는 사용자 로컬 workspace를 작업 상태의 원본으로 유지하고,
- 표준선(선택): direct는 상위 모델 직접 실행을 뜻하지 않는다. local capability가 충족되면 저비용 local 실행을 우선하고, cloud 간 위임만 추가 hop의 비용·지연을 비교한다.
- 표준선(선택): 라우팅 모듈은 계획 승격 시 재설계하며, 현재 스케치에서는 교체 가능 경계와 분류·lane·grade·capability·confidence/abstain 의미만 후보로 둔다.
- 표준선(선택): 생성된 Plan의 lane/grade는 다시 추론하지 않고 실행 라우팅 입력으로 소비하며, route outcome 관측은 별도 Usage Ledger가 소비할 수 있는 접점까지만 둔다.
- 표준선(선택): provider/model 선택, CLI process, stream/session, quota, failure와 cancellation은 [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md)의 실행 경계를 소비한다. 이 Milestone은 일반 요청 분류, IOP 소유 Plan/Milestone 작업 의미, 사용자 agent tool call 주입과 workflow 단계 연결을 소유한다.
- 큐 배치: [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md) 뒤, [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md) 앞
- 선행 작업: [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md), [Stream Evidence Gate Core](../../knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md), [OpenAI-compatible 출력 검증 필터](../../knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
- 표준선(선택): provider/model 선택, CLI process, stream/session, quota, failure와 cancellation은 [IOP Agent CLI Runtime](iop-agent-cli-runtime.md)의 실행 경계를 소비한다. 이 Milestone은 일반 요청 분류, IOP 소유 Plan/Milestone 작업 의미, 사용자 agent tool call 주입과 workflow 단계 연결을 소유한다.
- 큐 배치: [IOP Agent CLI Runtime](iop-agent-cli-runtime.md) 뒤, [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md) 앞
- 선행 작업: [IOP Agent CLI Runtime](iop-agent-cli-runtime.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md), [Stream Evidence Gate Core](../../knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md), [OpenAI-compatible 출력 검증 필터](../../knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
- 후속 작업: 중단 후 재개와 filesystem 정합성 복구, agent family 확대, 운영 관측과 비용 예산 정책
- 확인 필요: `구현 잠금 > 결정 필요`와 승격 조건

View file

@ -107,5 +107,5 @@ CLI provider agent와 목적별 agent group, 예약어 설정을 runtime이 해
- 표준선(선택): selector는 provider/agent 하나만 반환한다. known failure의 retry/failover는 공통 runtime이 소유하고 unknown 오류는 추정 복구 없이 표면화한다.
- 표준선(선택): 같은 provider credential/profile의 cloud quota는 project별로 분할하지 않는 app-global 공유 snapshot이며 group routing은 공통 quota 입력을 읽기만 한다.
- 선행 작업: CLI Automation Runtime 안정화, OpenAI Responses Input Surface, OpenAI Workspace Agent Execution Contract
- 후속 작업: [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md), [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md)
- 후속 작업: [IOP Agent CLI Runtime](iop-agent-cli-runtime.md), [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md)
- 확인 필요: 없음

View file

@ -0,0 +1,115 @@
# Milestone: IOP Agent CLI Runtime
## 위치
- Roadmap: [ROADMAP.md](../../../ROADMAP.md)
- Phase: [PHASE.md](../PHASE.md)
## 목표
모델이 감시하던 Agent Task 실행 루프를 프로덕션 Go runtime과 독립 실행 가능한 `iop-agent` CLI로 이전한다.
현재 Python dispatcher와 Node CLI runtime에서 검증된 provider 실행, 선택, quota, 오류, 복구, review와 관측 동작을 축소하지 않고 흡수하며, Node도 같은 공통 CLI Provider·AgentTaskManager 구현을 소비하게 한다.
## 상태
[스케치]
## 승격 조건
- [ ] 보류된 [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md)와 [기존 SDD](../../../sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md)의 runtime 요구사항을 CLI 범위로 이관하고 Python·Node 참조 동작의 parity inventory를 고정한다.
- [x] 공통 runtime lifecycle, YAML config, checkpoint, provider process와 binary 측 local proto-socket 경계를 [SDD](../../../sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md)에 고정하고 필요한 agent-contract 작성 범위를 확정했다.
- [x] 기능 Task와 Acceptance Scenario·Evidence Map을 연결했다.
- [ ] Flutter 설정 UI와 Unity 3D Character를 각각 후속 Milestone 후보로 분리하고 현재 범위에 UI 구현이 섞이지 않았는지 확인한다.
## 구현 잠금
- 상태: 잠금
- SDD: 필요
- SDD 문서: [SDD.md](../../../sdd/automation-runtime-bridge/iop-agent-cli-runtime/SDD.md)
- SDD 사유: 공통 runtime/Node host 경계, lifecycle, retry·identity·checkpoint, config/proto event 계약과 실제 로그인 환경 smoke를 함께 변경한다.
- 잠금 해제 조건: 아래 체크리스트
- [x] SDD 잠금이 해제되어 있다.
- [x] SDD 사용자 리뷰가 없거나 승인·해결되었다.
- [x] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
- [x] Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- [ ] 나머지 승격 조건을 충족해 `[계획]`으로 전환되어 있다.
- 결정 필요: 없음
## 범위
- `packages/go`의 공통 CLI Provider·AgentTaskManager와 이를 실행하는 독립 `iop-agent` binary/CLI
- Node 내부 CLI provider를 공통 모듈 소비 방식으로 전환하고 Node·`iop-agent`에 provider나 manager 구현을 중복하지 않는 경계
- 선언된 provider와 provider/model/profile 공식 이름, one-shot/persistent 실행, stream/session/resume, quota/status, cancel, retry/failover와 오류 표면화
- app-owned YAML의 provider/global 설정, 명시 등록 project와 project override, ordered selection rule, file watcher와 다음 agent 호출부터의 revision 적용
- 자동 실행은 기본 on이고 사용자가 언제든 중단할 수 있다. 등록 project별 남은 agent-task를 우선 실행한 뒤 `priority-queue.md`의 최상위 ready Milestone을 순차 실행하며, 서로 다른 project와 clone/worktree/branch workspace instance는 병렬 실행한다.
- project-owned Milestone/Plan/Code Review/USER_REVIEW/completion artifact를 해석하는 workflow adapter, provider-neutral review submission matcher와 Pi same-context evidence repair
- workspace lease, durable route/checkpoint, process/session locator, failure budget, restart reconciliation과 task-local blocker
- project-local `agent-log`와 runtime-owned `WORK_LOG.md`의 task별 pinned `loop`, attempt, locator 및 exactly-once archive reconciliation
- 향후 Flutter·Unity client가 같은 binary를 제어할 수 있도록 `iop-agent`가 제공할 local proto-socket의 server-side 상태·event·control 경계. 실제 protocol 원문은 계획 승격 시 agent-contract로 고정한다.
## 기능
### Epic: [runtime-core] 공통 Provider와 AgentTaskManager
Node와 독립 CLI가 같은 실행 구현을 소비하는 runtime capability를 묶는다.
- [ ] [common-runtime] CLI Provider, emitter/stream/session, quota/status, failure codec과 AgentTaskManager가 공통 Go package의 단일 구현으로 제공된다.
- [ ] [provider-catalog] YAML에 선언된 지원 provider/model/profile을 discovery하고 이미 인증된 실행 환경에서 run, resume, cancel과 status를 수행한다.
- [ ] [task-manager] AgentTaskManager가 모델 감시 없이 project 작업 상태를 읽고 dependency-ready task, review, 후속 작업과 Milestone을 끝까지 진행한다.
- [ ] [node-consumer] Node가 공통 runtime을 소비하는 얇은 bridge로 전환되고 기존 Node 실행 계약과 provider 동작을 보존한다.
### Epic: [policy-state] 선택 정책과 내구 상태
여러 project와 provider를 무인 실행하면서 선택·복구 결과를 재현할 수 있는 상태를 묶는다.
- [ ] [config-registry] app-owned YAML defaults와 project override, ordered rule array 전체 교체, file watcher와 immutable execution revision 경계가 제공된다.
- [ ] [target-policy] 공통 evaluator가 host/project 정책을 주입받아 조건과 배열 순서에 따라 provider/model 하나를 반환하고 durable route plan에 판단 근거와 후보 이력을 보존한다.
- [ ] [quota-failure] provider별 quota/status와 알려진 오류를 typed result로 정규화하고 선언 정책 안에서만 retry/failover하며 unknown 오류는 해당 work unit에 표면화한다.
- [ ] [workflow-evidence] 모든 provider/model/execution class에 같은 artifact matcher와 review gate를 적용하고 Pi의 selfcheck 후 미작성 review artifact는 같은 native context에서 보완한다.
- [ ] [state-recovery] workspace 단일 manager lease, checkpoint, process/session locator, failure budget과 completion reconciliation이 restart·cancel·부분 실패에서도 중복 실행 없이 복구된다.
### Epic: [cli-delivery] Headless CLI와 운영 검증
UI 없이도 설치·설정·실행·관측 가능한 제품 표면을 묶는다.
- [ ] [cli-surface] `iop-agent`가 binary와 기본 YAML 배포물, YAML 검증, provider/project 조회, preview, serve/auto-run, stop/resume와 상태 확인을 일관된 CLI command로 제공한다.
- [ ] [local-control] 후속 client가 사용할 local proto-socket의 binary 측 lifecycle, 상태, event와 control endpoint가 UI 구현과 분리된 경계로 제공된다.
- [ ] [project-logs] 현재 최소 관측 수준을 축소하지 않는 project-local event/log와 task별 loop·attempt·locator가 연결된 `WORK_LOG` timeline을 제공한다.
- [ ] [parity-cutover] Python·Node 동작을 `absorb | replace | not-applicable`로 분류하고 미분류 동작, Python runtime 의존성과 Node provider 중복 없이 Go runtime으로 전환한다.
- [ ] [logged-smoke] 실제 로그인된 macOS CLI 환경에서 discovery, 실행, stream, quota/status, cancel, 재호출, restart와 다중 project 동작을 검증한다.
## 완료 리뷰
- 상태: 없음
- 요청일: 없음
- 완료 근거: 최초 CLI 범위 스케치이며 승격 조건과 구현 gate가 아직 남아 있다.
- 검토 항목: 없음
- agent-ui 상태 반영: 해당 없음
- 리뷰 코멘트: 없음
## 범위 제외
- Flutter 설정·운영 UI, tray, macOS `.app` shell과 UI가 binary lifecycle을 관리하는 기능
- Unity 3D Character, transparent window, animation, click-through와 Flutter package 통합
- Flutter·Unity client 구현과 화면 정의. 현재 범위는 binary 측 local protocol 경계까지만 포함한다.
- provider 로그인, credential/token 저장, 계정 전환과 billing 구매 자동화
- 사용자 승인 prompt와 interactive approval gate. 현재 기본은 provider별 approval bypass다.
- agent-ops를 사용하지 않는 일반 요청의 direct/Plan/Milestone 분류와 합성 tool call 주입. 이는 [에이전트 작업 루프 오케스트레이션 MVP](agent-workflow-loop-orchestration-mvp.md)의 범위다.
- Edge, Control Plane, remote terminal tunnel, 외부 알림/dashboard, oto scheduler/CI-CD와 Windows/Linux desktop packaging
- Python 코드를 production에서 import·실행·번역 호출하거나 진행 중 Python process 상태를 승계하는 방식
## 작업 컨텍스트
- 관련 경로: `packages/go`, `apps/node`, `proto/iop`, `agent-task`, `agent-roadmap`
- 표준선(선택): `iop-agent`는 headless runtime과 CLI entry이며 설정·project registry·최소 checkpoint의 관리 주체다. workspace는 작업 파일의 source of truth이지 runtime 설정 소유자가 아니다.
- 표준선(선택): Node와 `iop-agent`는 공통 provider/manager package를 소비하고 host-specific command, wire와 lifecycle adapter만 가진다.
- 표준선(선택): Python은 정책·오류·관측 behavior fixture로만 사용하고 Go 타입과 테스트로 재구현한다. Python에 없는 선택 엔진은 완료된 selector와 group routing Milestone을 기준으로 작성한다.
- 표준선(선택): CLI는 모든 선언 provider를 대상으로 전체 동등성을 제공하며 지원 provider, 선택 엔진, quota, review와 복구 기능을 축소한 선행판을 두지 않는다.
- 표준선(선택): local proto-socket은 binary가 소유하는 client-neutral 경계다. Flutter와 Unity는 후속 Milestone에서 서로 통신하지 않고 각자 이 경계를 소비한다.
- 표준선(선택): 자동 실행과 provider approval bypass는 기본 on이며 사용자는 언제든 project를 중단할 수 있다. provider authentication과 credential은 각 CLI가 소유하고 `iop-agent`는 이미 인증된 실행만 사용한다.
- 표준선(선택): 세부 command 이름, package/file 배치, proto field, retry backoff 수치와 log serialization은 계획·SDD·contract 단계에서 기존 구조와 표준안으로 정하며 사용자 결정 항목으로 올리지 않는다.
- 이전 설계 참조: [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md)와 [기존 SDD](../../../sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md). 결합된 Desktop delivery는 구현하지 않고 CLI parity 요구사항만 계획 승격 시 이관한다.
- 큐 배치: [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md) 뒤, [에이전트 작업 루프 오케스트레이션 MVP](agent-workflow-loop-orchestration-mvp.md) 앞
- 선행 작업: [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md)
- 후속 작업: Flutter Desktop 설정·운영 UI Milestone, Unity 3D Character Milestone, [에이전트 작업 루프 오케스트레이션 MVP](agent-workflow-loop-orchestration-mvp.md), [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md)
- 확인 필요: 없음

View file

@ -8,7 +8,7 @@
## 목표
공통 Agent Task runtime이 생성하는 provider quota/status, 선택, retry/failover와 terminal error event를 운영자가 놓치지 않도록 Desktop과 후속 외부 채널에 전달하는 알림·이력 표면을 스케치한다.
작업 이어받기, provider 재선택과 실패 복구 상태 머신은 [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md)가 소유하며, 이 Milestone은 그 동작을 중복 구현하지 않는 event consumer다.
작업 이어받기, provider 재선택과 실패 복구 상태 머신은 [IOP Agent CLI Runtime](iop-agent-cli-runtime.md)이 소유하며, 이 Milestone은 그 동작을 중복 구현하지 않는 event consumer다.
## 상태
@ -75,6 +75,6 @@
- 표준선(선택): quota는 provider credential/profile 기준 app-global 공유 상태이며 알림은 project별 선택 결과와 같은 snapshot identity를 참조한다.
- 표준선(선택): 사용자 표면은 provider/model/profile 공식 계열 이름을 사용하고 generic `cli` adapter id를 주 식별자로 보여주지 않는다.
- 표준선(선택): known failure의 retry/failover와 unknown terminal error 결정은 공통 runtime이 먼저 끝낸다. 알림은 확정 event를 소비할 뿐 실행 동작을 바꾸지 않는다.
- 선행 작업: [공통 Agent Task Runtime과 Desktop Agent](shared-agent-task-runtime-desktop-agent.md)
- 선행 작업: [IOP Agent CLI Runtime](iop-agent-cli-runtime.md)
- 후속 작업: Control Plane 운영 알림, 외부 webhook/메신저 delivery, 사용량 dashboard
- 확인 필요: `구현 잠금 > 결정 필요` 항목

View file

@ -12,7 +12,12 @@
## 상태
[계획]
[보류]
## 보류 사유
- 공통 runtime, Flutter Desktop과 배포를 한 번에 구현하는 결합 범위는 더 이상 실행하지 않는다.
- 현재 첫 구현 범위는 [IOP Agent CLI Runtime](iop-agent-cli-runtime.md)으로 분리했으며, 이 문서와 SDD는 CLI 요구사항 이관 및 후속 Flutter·Unity Milestone 작성의 참조로만 유지한다.
## 승격 조건
@ -29,8 +34,7 @@
- [ ] SDD 사용자 리뷰가 없거나 승인·해결되었다.
- [ ] Acceptance Scenario가 Milestone 기능 Task와 연결되어 있다.
- [ ] Evidence Map이 완료 시 `Roadmap Completion`과 최종 검증 evidence로 검증 가능하게 연결되어 있다.
- 결정 필요: 아래 체크리스트
- [ ] [SDD USER_REVIEW D01](../../../sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/USER_REVIEW.md)에서 macOS 창 닫기·명시 종료·로그인 시 시작의 Desktop background lifecycle을 결정한다.
- 결정 필요: 현재 보류. [D01 범위 이관 기록](../../../sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/user_review_0.log)은 후속 Flutter Desktop Milestone 범위이며 IOP Agent CLI 결정 항목이 아니다.
## 범위
@ -42,7 +46,7 @@
- Pi selfcheck process가 성공 종료한 뒤에도 동일 matcher가 CODE_REVIEW 미완성을 반환하면 `selfcheck_done` 또는 review-ready로 전환하지 않는다. runtime은 완료된 selfcheck attempt의 native session/context locator를 보존하고 matcher snapshot, incomplete ordinal과 prompt dispatch intent를 먼저 durable하게 기록한 뒤 새 route·새 session·quota probe 없이 같은 Pi selfcheck context를 resume해 `The code review file has not been filled in. Fill in every missing implementation-owned field in {CODE_REVIEW_PATH}. Do not perform the official review.`를 영문으로 보낸 다음 matcher를 다시 실행한다. 각 ordinal의 정상 전송은 exactly-once이고 host restart에서는 기록된 live/terminal attempt를 먼저 reconcile하며 delivery outcome이 불명확하면 같은 prompt를 무작정 재전송하지 않고 task-local blocker로 표면화한다. matcher 통과 시에만 `selfcheck_done`, repair `validated`, pending intent 제거 및 official-review work-ready 전이를 하나의 checkpoint commit으로 확정한다. 이 evidence repair는 기존 selfcheck incomplete budget에 누적하며 context/task/plan/tag/review identity가 없거나 불일치하면 fresh context로 대체하지 않고 task-local error/blocker로 표면화한다.
- 공식 review lifecycle은 review artifact가 provider에 노출되는지 preflight하고 정확한 verdict section, 새 review artifact와 filesystem progress, USER_REVIEW/후속 plan/완료 archive 상태를 함께 판정한다. no-progress fingerprint는 plan이 선언한 write-set source와 review/finding artifact만 사용하고 runtime 소유 WORK_LOG/heartbeat 갱신은 진척으로 세지 않는다. review agent의 금지된 제어 동작, 무변경 반복, 잘못된 PASS/WARN/FAIL finalization과 verdict 이후 crash/restart 복구 실패는 typed blocker/error로 표면화한다.
- 일반 사용자 요청을 direct/Plan/Milestone으로 분류하고 IOP가 소유한 작업 의미로 사용자 agent에 합성 tool call을 주입해 작업 파일을 만드는 기능은 [에이전트 작업 루프 오케스트레이션 MVP](agent-workflow-loop-orchestration-mvp.md)의 별도 책임이다. 이 runtime은 그 오케스트레이션의 공통 실행 기반이 될 수 있지만 진입 요청 라우터나 Plan/Milestone skill 소유자가 되지 않는다.
- 동등성 기준은 구현 계획 시점의 [Agent Task 동적 실행 Target Selector](agent-task-runtime-target-selector.md), 관련 active `WORK_LOG.md`, Python dispatcher/selector, Node CLI runtime과 Go usage checker를 함께 대조해 고정한다. 충돌 시 Milestone/SDD, 현재 agent-contract, 참조 구현 순으로 우선한다.
- 동등성 기준은 구현 계획 시점의 [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), 관련 active `WORK_LOG.md`, Python dispatcher/selector, Node CLI runtime과 Go usage checker를 함께 대조해 고정한다. 충돌 시 Milestone/SDD, 현재 agent-contract, 참조 구현 순으로 우선한다.
- 사용자 환경에 선언된 provider가 실제 실행 대상이다. runtime은 현재 Node와 선행 Milestone이 지원하는 one-shot/persistent CLI, Codex, Claude, Antigravity/Agy, OpenCode, Pi 등 provider profile과 emitter family를 공통 catalog에서 해석하며 임의의 축소된 고정 목록만 지원하지 않는다.
- 외부 표기는 `codex/gpt-5.6-sol-xhigh`처럼 provider/model/profile을 사용자가 이해할 수 있는 공식 계열 이름으로 표현한다. Desktop config/event/UI는 generic `cli` adapter를 주 식별자로 노출하지 않고, 내부 Node bridge만 기존 `adapter + target`과 안정된 provider/profile id를 유지한다.
- provider 인증과 credential은 각 CLI가 소유한다. 앱은 binary/version/authenticated readiness를 조회·검증할 뿐 로그인, token 저장, 계정 전환을 관리하지 않는다.
@ -66,7 +70,7 @@
- 실패 예산은 work-unit/stage identity에 귀속해 자동 target 변경·failover·host 재시작을 지나도 유지하고 해당 stage의 검증된 성공에서 초기화한다. 명시적 identity-matched `retry_blocked`만 blocker와 해당 stage budget을 초기화하며 persisted route/history는 보존한다. worker와 review budget은 서로 독립이고 failure count 자체를 새 route 선택 입력으로 사용하지 않는다. same-target retry는 선언된 bounded backoff를 따르고 stop/cancel에서 즉시 해제되며 restart가 이미 예정·수행한 retry를 중복 실행하지 않는다.
- 현재 Python에서 검증된 raw/normalized stream, heartbeat, PID/process-group, session locator, silence inspection, exact tool-call/result phase, cancellation, route pin, logical context transfer, failure budget, dependency drain, review-control 위반 감지와 알려진 provider 오류 예외를 공통 runtime 동등성 matrix에 흡수한다. 동일 normalized chunk의 연속 반복은 새 tool/file/state 변화가 없을 때 observation으로만 기록하고 그 신호만으로 종료·block·retry·failover하지 않는다. Python의 함수명·marker·state key는 계약으로 복사하지 않고 관측된 상태 전이와 불변 조건만 Go 타입·테스트로 옮긴다. 최종 parity audit는 한 work unit의 select→pin/resume→same-target recovery 또는 failover→quota/budget/review blocker→selfcheck/completion을 rule/candidate/reason/quota/transition evidence로 연결하고 stale Python monitoring 의존성과 정적 route/cap 문구를 검출한다.
- 오류는 모두 runtime event와 project log에 표면화한다. 알려진 오류만 선언된 policy에 따라 retry/failover하고, unknown 오류는 추정 복구하지 않고 해당 work unit을 명시적으로 중단한다.
- 프로젝트별 최소 관측 로그는 각 프로젝트의 `agent-log` 계열 경로에 보존하고 현재 수준보다 축소하지 않는다. provider/model 선택, quota snapshot, config revision, runtime build, process/session locator, stream/heartbeat, failure evidence, retry/failover, stop/completion을 동일 execution/attempt identity로 추적한다. runtime 소유 START/FINISH timeline과 project-owned 완료 archive를 재시작 후 대조하고, 유일한 valid `complete.log`가 확인된 뒤 마지막 writer가 종료된 경우에만 group `WORK_LOG`를 archive하며 그 뒤에만 완료 attempt 임시 로그를 정리한다.
- 프로젝트별 최소 관측 로그는 각 프로젝트의 `agent-log` 계열 경로에 보존하고 현재 수준보다 축소하지 않는다. provider/model 선택, quota snapshot, config revision, runtime build, process/session locator, stream/heartbeat, failure evidence, retry/failover, stop/completion을 동일 execution/attempt identity로 추적한다. task-group `WORK_LOG.md``seq | time | loop | event | task | role | attempt | model | result | locator` 순서의 runtime-owned START/FINISH timeline이다. 각 attempt의 `loop`는 그 `task`의 현재 active PLAN/CODE_REVIEW pair가 향후 archive될 suffix 회차로 START 전에 checkpoint/ledger/locator에 고정한다. 같은 task에 `plan_*.log``code_review_*.log`가 각각 0~10까지 있고 pair identity/count가 일치하면 current-pair attempt는 11이며, review가 실행 중 pair 11을 archive하고 follow-up pair 12를 만들더라도 그 attempt의 FINISH는 locator에 고정된 loop 11을 사용한다. 같은 pair의 worker/selfcheck/review retry·resume은 loop를 유지하고 `attempt`만 증가하며, follow-up pair가 생성된 뒤 시작하는 새 attempt부터 loop 12가 된다. 선행 task 완료로 2·3, 이어서 5·6처럼 dependency-ready frontier가 동적으로 확장되어도 하나의 active `WORK_LOG`를 유지하되 서로 다른 task 행은 각자의 loop를 기록한다. `work_log_N.log`의 N은 task-group timeline 자체의 archive 회차로 task별 loop와 독립이며 같은 task group의 모든 월별 exact archive suffix 최대값 다음 수(없으면 0)를 별도로 고정한다. `locator`는 pinned task loop와 native context/session id를 포함한 attempt 메타데이터의 권위 포인터이므로 `context_id`를 별도 `WORK_LOG` 컬럼으로 중복하지 않는다. runtime ledger와 project-owned 완료 archive를 재시작 후 대조하고, 동적으로 확장된 lineage의 모든 task에 유일한 valid `complete.log`가 있으며 ready/running/pending follow-up·blocker와 마지막 writer가 모두 없는 terminal closure에서만 `WORK_LOG.md`를 고정된 다음 `work_log_N.log`로 archive한 뒤 완료 attempt 임시 로그를 정리한다.
- Desktop Agent는 Go runtime host, YAML 운영 entry, app-owned registry/state와 Flutter macOS shell을 포함한다. UI 설정 화면은 scaffold만 두지만 설치 산출물에는 runtime binary, 기본 YAML과 Flutter macOS app wrapper가 함께 있어야 한다.
- Desktop Agent는 기본적으로 provider별 approval bypass를 사용하며 사용자 승인 flow를 추가하지 않는다. 자동 연결·실행은 설정으로 끌 수 있게 하되 최초 기본값은 켜짐이다.
- 단위·통합 fake provider 검증과 별도로 실제 로그인된 CLI 환경에서 provider discovery, 짧은 실행, stream, quota/status, cancel, 재호출을 확인하는 macOS smoke를 완료 근거로 남긴다.
@ -81,7 +85,7 @@ Node와 Desktop Agent가 하나의 실행 구현을 공유하고 각 제품에
- [ ] [agent-task-manager] 공통 AgentTaskManager가 project filesystem 상태, work-unit identity, route pin, plan/review loop, sequential Milestone 실행과 stop/resume을 모델 감시 없이 수행하고 같은 판정기의 read-only preview를 제공한다. 검증: supervisor 모델 호출 없이 남은 task 우선과 priority queue 다음 작업 선택이 결정적으로 재현되며 initial/resume preview 전후의 checkpoint, route/history, budget, blocker/intent, quota cache와 project 파일이 deep-equal이고 provider process가 시작되지 않는다.
- [ ] [workflow-ownership-boundary] AgentTaskManager는 project-owned agent-ops 작업 파일과 이미 선택된 작업 지시만 실행하며 일반 요청의 direct/Plan/Milestone 분류, IOP 소유 skill, 합성 tool call 기반 작업 파일 생성을 구현하지 않는다. 검증: 기존 작업 파일 dispatch는 동작하고 일반 요청 입력만으로는 runtime이 Milestone/Plan을 분류하거나 생성하지 않으며 별도 오케스트레이션 경계가 유지된다.
- [ ] [host-boundary] Node bridge와 Desktop host가 동일 runtime API를 사용하되 Node는 기존 wire/config/command mapping을, Desktop은 app lifecycle/registry/local events를 소유한다. 검증: Edge를 포함하지 않은 Desktop 실행과 기존 Node run/session/status 경로가 모두 같은 core를 통과한다.
- [ ] [parity-cutover] 현재 Milestone·SDD, finalized/active work evidence, Python dispatcher/selector와 Node 구현을 provider, scheduler, workflow artifact, review/finalization, process/session, quota/error 영역별로 inventory하고 각 동작을 `absorb | replace | not-applicable`로 판정한 뒤 공통 runtime으로 cutover한다. 검증: 전체 Node compatibility policy/behavior fixture와 한 work unit의 end-to-end audit chain을 포함해 미분류 동작이 없고 모든 absorb/replace 행에 Go test 또는 field-smoke evidence가 연결되며 stale Python monitoring 의존성·정적 route/cap 문구와 Node provider 중복이 남지 않는다.
- [ ] [parity-cutover] 현재 Milestone·SDD, finalized/active work evidence, Python dispatcher/selector와 Node 구현을 provider, scheduler, workflow artifact, review/finalization, process/session, quota/error 영역별로 inventory하고 각 동작을 `absorb | replace | not-applicable`로 판정한 뒤 공통 runtime으로 cutover한다. loop 컬럼이 없는 과거 archived `work_log_N.log`는 immutable history로 유지하고, 같은 task group의 active legacy `WORK_LOG.md`가 남아 있으면 기존 owner가 drain/archive하기 전에는 새 runtime이 mixed-schema 행을 append하거나 ownership을 넘겨받지 않는다. 검증: 전체 Node compatibility policy/behavior fixture와 한 work unit의 end-to-end audit chain을 포함해 미분류 동작이 없고 모든 absorb/replace 행에 Go test 또는 field-smoke evidence가 연결되며 stale Python monitoring 의존성·정적 route/cap 문구와 Node provider 중복이 남지 않는다. legacy archive byte equality와 active legacy log cutover blocker도 검증한다.
### Epic: [provider-policy] Provider Catalog와 선택 정책
@ -111,7 +115,7 @@ route와 실행 evidence를 fault-atomic하게 복구하고 project-owned review
- [ ] [review-artifact-lifecycle] project workflow adapter가 모든 worker provider 종료부터 official review 전까지 actual completing target과 persisted route, PLAN/CODE_REVIEW pair·identity 및 active CODE_REVIEW의 worker-owned 필수 섹션/placeholder/체크리스트를 동일한 versioned 정규식/구조 matcher로 검사하고, completing route policy의 selfcheck까지 충족한 작업만 official review로 전이한다. review preflight, exact verdict, 새 artifact/fingerprint, no-progress budget과 PASS archive·WARN/FAIL follow-up·USER_REVIEW 및 restart recovery를 검증한다. pinned selfcheck 대상 worker는 actual completing target·persisted route와 PLAN/CODE_REVIEW pair·task/plan/tag identity를 먼저 검증한 뒤 selector 재평가 없이 selfcheck를 수행하고, 그 성공 결과에 worker-owned field matcher를 적용한다. Pi selfcheck가 성공했지만 matcher가 미완성을 반환하면 직전 성공 selfcheck의 native context를 같은 locator로 resume해 고정 영문 evidence-repair prompt를 보내고 matcher를 재실행한다. 검증: Pi를 포함한 declared provider/model과 local/cloud·one-shot/persistent worker 전체가 동일 matcher matrix를 통과해야 하며 runtime identity mismatch·placeholder·unchecked·pair/identity mismatch에서는 bounded 보완 또는 task-local blocker가 되고 official review invocation은 0회다. Pi evidence repair는 동일 native session/context·route/config identity를 유지하고 새 selector·quota probe·session 없이 수행한다. 각 incomplete ordinal은 matcher snapshot과 prompt dispatch intent/attempt identity를 먼저 저장해 정상 경로에서 prompt를 exactly-once 보내며 restart는 live/terminal attempt를 reconcile하고 delivery outcome 불명 상태를 blind resend 없이 task-local blocker로 만든다. 첫 selfcheck에서 이미 완성됐으면 재프롬프트 0회이고, 보완 뒤 통과하면 selfcheck pin·pending repair 해제와 official-review work-ready를 원자적으로 commit한 뒤 review 1회가 된다. 반복 미완성·restart에서는 durable incomplete budget과 pending repair를 exactly-once 복원하고, cancel은 이를 보존한 채 stopped/resumable로 전이하며, identity mismatch는 fresh-context fallback 없는 task-local blocker가 된다. selfcheck는 completing target을 재사용한다. active/archive recovery source는 exact basename grammar, ASCII numeric suffix ordering, regular-file와 work-unit identity로 결정하며 mtime이나 유사 이름을 사용하지 않는다. no-progress fingerprint는 plan write-set source와 review/finding artifact만 포함해 runtime WORK_LOG/heartbeat-only 변경이 budget을 초기화하지 않는다. 체크 표시만 있는 허위 완료·artifact 비노출·임의 위치 verdict·무변경 review·잘못된 archive는 통과하지 않고 재시작에도 정상 PASS만 한 번 완료된다.
- [ ] [blocked-failover-recovery] typed blocker, persisted route/work-unit/selected-target identity와 readable retry evidence package의 execution/attempt·stage/role·terminal failure·artifact identity가 모두 일치할 때만 복구 intent를 만들고 사용자 재시도 또는 policy-authorized status refresh에서 기존 route의 unused alternate와 현재 blocked target에 허용된 same-target retry만 재평가한다. 검증: malformed/missing/mismatched locator 또는 role/failure/attempt identity는 marker 없는 pinned same-target resume으로 남고 현재 시각 정책으로 새 candidate를 만들거나 이미 떠난 target으로 bounce하지 않는다. selector/context/transition/attempt save 실패에는 key 존재 여부를 포함한 기존 decision/history/intent/pending handoff와 정상 sibling의 in-memory/on-disk 전체 state가 보존되며, successful handoff는 attempt locator 기록 뒤 한 번만 소비되어 exact continuation으로 이어진다.
- [ ] [stage-failure-budget] work-unit/stage별 budget을 route decision과 함께 durable하게 유지하고 자동 target 변경·failover·restart에서는 누적하며 해당 stage 성공에서 초기화한다. 명시적 identity-matched `retry_blocked`는 blocker와 해당 stage budget만 초기화하고 route/history는 보존한다. same-target retry는 bounded backoff policy를 사용한다. 검증: primary/alternate와 restart가 하나의 worker budget을 공유하고 review budget과 분리되며 한도 소진은 task-local blocker가 되고 failure count가 selector 재평가나 새 initial route를 유발하지 않는다. backoff는 상한을 지키고 stop/cancel에서 즉시 해제되며 restart 후 같은 retry가 중복 실행되지 않는다.
- [ ] [completion-ledger-reconciliation] runtime 소유 execution/attempt START·FINISH ledger, active filesystem, archive baseline과 valid `complete.log`를 재조정해 exactly-once completion을 확정한다. 검증: verdict/archive 사이 crash, task 소실, 새 archive 없음·복수 archive, orphan START, 마지막 writer와 archive 이동 실패 matrix에서 false completion이나 로그 유실 없이 재시도 가능 오류를 남기고, 유일한 완료 archive 뒤에만 `WORK_LOG` archive와 해당 task attempt-log cleanup이 수행된다.
- [ ] [completion-ledger-reconciliation] runtime 소유 execution/attempt START·FINISH ledger, active filesystem, archive baseline과 valid `complete.log`를 재조정해 exactly-once completion을 확정한다. task-group `WORK_LOG`의 각 attempt에는 해당 task의 active PLAN/CODE_REVIEW pair archive 회차인 `loop`를 START 전에 pin하고 matching FINISH에도 같은 값을 기록한다. locator가 pinned loop와 context/session id를 포함한 attempt 메타데이터를 소유하며 별도 `context_id` 컬럼은 만들지 않는다. 검증: `11+10_unknown_isolation` task에 paired `plan_*.log`/`code_review_*.log` suffix 0~10과 active pair가 있으면 그 pair의 worker/selfcheck/review START·FINISH 행은 loop 11이다. 동일 pair의 retry·restart는 loop 11과 locator identity를 유지하고 attempt만 증가한다. WARN/FAIL review가 실행 중 pair를 suffix 11에 exactly-once archive하고 follow-up pair를 만들어도 그 review FINISH는 11이며, follow-up pair의 다음 START부터 12가 된다. 동시에 실행되는 다른 task는 자신의 active-pair loop를 같은 `WORK_LOG`에 기록한다. task group에 기존 `work_log_0.log`~`work_log_2.log`가 있다면 이 task loop와 무관하게 현재 timeline의 terminal archive는 `work_log_3.log`다. verdict/partial-pair-archive 사이 crash, task 소실, 새 completion archive 없음·복수 archive, orphan START, 마지막 writer와 `WORK_LOG` archive 이동 실패 matrix에서 false completion이나 로그 유실 없이 재시도 가능 오류를 남기고, 동적 DAG terminal closure 뒤에만 고정된 `work_log_3.log` archive 및 attempt-log cleanup을 수행한다. active pair metadata·plan/review count·checkpoint/locator/row loop 또는 timeline archive ordinal 불일치는 추정 renumber 없이 명시 오류가 된다.
### Epic: [failure-observe] 오류·관측·로그 동등성
@ -147,7 +151,7 @@ Edge 없이 실행되는 macOS 제품 껍데기와 설치·운영 기준을 제
- [ ] Pi를 포함한 모든 declared worker provider/model·execution 방식에 동일한 CODE_REVIEW 정규식/구조 제출 gate가 적용되고 official review의 verdict/progress/finalization 상태 전이가 project-owned artifact contract 기준으로 검증되었다.
- [ ] Pi selfcheck 후 CODE_REVIEW 미완성은 직전 성공 selfcheck의 동일 native context에 고정 영문 보완 prompt를 보내 재검증하며, matcher 통과 전 review 0회·통과 뒤 1회, ordinal별 prompt 중복 방지, restart의 live/terminal/unknown-delivery 조정, 성공 시 selfcheck pin·pending repair 원자 해제와 budget/identity 오류의 fresh-context fallback 부재가 검증되었다.
- [ ] workspace single-owner, live child 인계, dependency drain과 stage failure budget이 restart·오류 상황에서도 중복 호출이나 독립 branch 취소 없이 검증되었다.
- [ ] runtime ledger, valid completion archive와 group `WORK_LOG`/attempt-log 정리가 last-writer 및 exactly-once 기준으로 재조정된다.
- [ ] runtime ledger, valid completion archive와 task-group `WORK_LOG`/attempt-log 정리가 last-writer 및 exactly-once 기준으로 재조정되고, 각 attempt의 START·FINISH가 동일한 pinned task/pair `loop`를 사용하며 같은 pair retry에서는 유지되고 follow-up pair의 다음 START에서만 증가한다. 서로 다른 task의 loop는 같은 `WORK_LOG`에서 독립적이고 별도로 고정된 `work_log_N.log` archive 회차와 혼동하지 않으며 context/session id는 locator 메타데이터에서 조회된다.
- [ ] Node와 Desktop이 동일 provider/runtime conformance suite를 통과하고 중복 provider 구현이 없다.
- [ ] 실제 로그인된 macOS smoke와 project-local log evidence가 남아 있다.
- agent-ui 상태 반영: 해당 없음
@ -170,12 +174,12 @@ Edge 없이 실행되는 macOS 제품 껍데기와 설치·운영 기준을 제
- 관련 경로: `packages/go/agentruntime`, `apps/node/internal/adapters/cli`, `apps/node/internal/runtime`, `apps/desktop-agent`, `apps/desktop-agent-ui`, `packages/go/config`, `agent-ops/skills/project/orchestrate-agent-task-loop`, `agent-task`, `agent-roadmap`
- 표준선(선택): 공통 구현은 `packages/go/agentruntime`에 두고 Node와 Desktop host가 의존한다. provider-specific codec은 core 내부 확장점일 수 있지만 host app에 복제하지 않는다.
- 표준선(선택): Python은 동작과 오류 사례의 참조이며 production dependency가 아니다. 아직 Python에 없는 선택 엔진은 [Agent Task 동적 실행 Target Selector](agent-task-runtime-target-selector.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md)과 승인된 SDD를 기준으로 Go에서 구현한다.
- 표준선(선택): Python은 동작과 오류 사례의 참조이며 production dependency가 아니다. 아직 Python에 없는 선택 엔진은 [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md)과 승인된 SDD를 기준으로 Go에서 구현한다.
- 표준선(선택): Python의 active pair 검사, contract-valid USER_REVIEW, local selfcheck, exact verdict/fingerprint, no-progress와 finalization 판정은 흡수하되 Pi에만 적용되던 CODE_REVIEW 정규식 완료 gate, non-empty checkbox 판정과 cloud worker 사전 gate 부재는 동등성 기준으로 복사하지 않는다. Go workflow adapter는 provider/model/execution class와 무관하게 같은 versioned 정규식/구조 matcher로 필수 worker-owned field를 검사하고 semantic correctness는 공식 review agent에 맡긴다. write-set은 review progress fingerprint 입력이지 dispatch barrier가 아니며 runtime WORK_LOG/heartbeat만 바뀐 것은 review progress가 아니다.
- 표준선(선택): 관측된 Pi 보완 fixture는 작업·검증·selfcheck가 끝났어도 CODE_REVIEW가 미완성이면 직전 성공 selfcheck native context에 짧은 영문 지시를 다시 보내 파일을 완성하는 동작이다. 이 fixture는 모든 provider에 적용하는 matcher gate를 약화하지 않고 Pi profile의 same-context evidence-repair policy로 흡수하며, 새 selfcheck session이나 새 route를 만드는 현재 Python 반복 동작은 parity 대상으로 삼지 않는다.
- 표준선(선택): Python의 non-blocking workspace lock, 임시 파일 교체, PID/start token/attempt marker와 archive baseline은 구현을 복사하지 않고 workspace lease, atomic versioned checkpoint, live execution identity와 completion reconciliation 계약으로 대체한다. 손상 상태를 빈 상태로 초기화하거나 시간 경과만으로 stale process를 판정하지 않는다.
- 표준선(선택): `WORK_LOG`는 agent가 작성하는 완료 주장 문서가 아니라 runtime-owned 실행 timeline이다. split group의 마지막 writer가 끝나고 모든 관찰 task의 유일한 valid completion archive가 확인된 뒤 project archive로 이동한다.
- 표준선(선택): 구현 계획 직전에 [Agent Task 동적 실행 Target Selector](agent-task-runtime-target-selector.md)의 최종 PASS·`complete.log` evidence를 다시 freeze한다. 미종결 active plan/review는 결함·검증 후보로만 참고하고 Python 내부 함수명이나 persisted key 자체를 Go parity 요구로 승격하지 않는다.
- 표준선(선택): `WORK_LOG`는 agent가 작성하는 완료 주장 문서가 아니라 runtime-owned 실행 timeline이다. `seq`는 한 로그 안의 event 순서, `loop`는 해당 attempt가 시작한 task의 active PLAN/CODE_REVIEW pair archive 회차, `attempt`는 그 pair 안의 task/role별 호출 회차다. loop는 START 전에 locator/ledger에 pin하고 pair가 실행 중 archive·교체되더라도 matching FINISH까지 유지한다. 같은 pair의 retry·restart·blocker 복구는 loop를 유지하고 attempt만 증가하며 WARN/FAIL follow-up pair의 다음 attempt에서 loop가 증가한다. 병렬 task는 각자의 loop를 같은 timeline에 기록하고, `work_log_N.log`의 N은 같은 task group의 전체 월별 archive에서 별도로 계산·고정하는 timeline archive 회차이므로 task loop와 별개다. locator가 pinned loop와 context/session id를 포함한 attempt 메타데이터를 소유하므로 별도 context id 컬럼은 두지 않는다. split group의 동적으로 확장된 lineage가 terminal closure에 도달하고 마지막 writer와 모든 task의 유일한 valid completion archive가 확인된 뒤에만 project archive로 이동한다.
- 표준선(선택): 구현 계획 직전에 [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md)의 최종 PASS·`complete.log` evidence를 다시 freeze한다. 미종결 active plan/review는 결함·검증 후보로만 참고하고 Python 내부 함수명이나 persisted key 자체를 Go parity 요구로 승격하지 않는다.
- 표준선(선택): 외부 RouteDecision은 하나의 provider/model을 반환하지만 checkpoint의 persisted route plan은 ordered candidates, eligibility/rejection, rule/priority, used history와 transition을 보존하고 malformed/tampered identity를 silent reselection하지 않는다. 선행 selector의 KST/G01~G10/공식 review/failover/selfcheck는 Node compatibility policy fixture다. Python의 10회 budget/no-progress, unknown-once, no-target/write-set-barrier, 3분 silence와 3회 exact-repeat observation 및 USER_REVIEW 판정은 별도 behavior fixture다. 둘 다 공통 core나 Desktop 정책에 하드코딩하지 않는다.
- 표준선(선택): quota probe는 credential/profile, adapter, target, status command/profile과 ordered required caps 전체가 같을 때만 재사용한다. 최초 worker의 필요한 후보만 조회하고 local-first 뒤 cloud, persisted resume, selfcheck와 공식 review는 선행 probe하지 않으며 unknown admission 사용은 work-unit/candidate에 durable하게 기록한다.
- 표준선(선택): Python dry-run은 read-only preview의 동일 판정/no-side-effect fixture로 흡수하고 CLI flag나 출력 형식은 복사하지 않는다.
@ -185,6 +189,6 @@ Edge 없이 실행되는 macOS 제품 껍데기와 설치·운영 기준을 제
- 표준선(선택): 설정 merge는 app-owned defaults 뒤 app registry의 project override를 적용하며 ordered rule array는 전체 교체한다. 현재 실행은 immutable revision을 사용하고 hot reload는 다음 agent invocation 경계에서만 활성화한다.
- 표준선(선택): 자동 실행과 approval bypass는 기본 on이다. auth는 CLI가 소유하고 app은 이미 인증된 실행만 사용한다.
- 큐 배치: [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md) 뒤, [Provider 사용량 알림과 운영 표면](provider-usage-notification-operations-surface.md) 앞의 기존 작업 루프 위치를 유지한다.
- 선행 작업: [Agent Task 동적 실행 Target Selector](agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md)
- 선행 작업: [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](cli-agent-group-grade-routing.md)
- 후속 작업: [에이전트 작업 루프 오케스트레이션 MVP](agent-workflow-loop-orchestration-mvp.md), 완성형 Flutter 설정 UI, Windows/Linux packaging, 외부 알림·운영 dashboard, signing/notarization과 배포 채널
- 확인 필요: [USER_REVIEW.md](../../../sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/USER_REVIEW.md)의 Desktop background lifecycle 결정
- 확인 필요: 현재 없음. Desktop background lifecycle은 후속 Flutter Desktop Milestone을 만들 때 다시 검토한다.

View file

@ -7,30 +7,30 @@
1. [Stream Evidence Gate Core](phase/knowledge-tool-optimization-extension/milestones/stream-evidence-gate-core.md)
staged response-start, rolling/terminal/fragment hold, bounded ingress snapshot, model/provider별 Registry, single-flight all-complete evaluation과 strategy/request-total cap 아래 abort·optional one-shot plan prepare·host rebuild/re-admission을 공통 mechanics로 제공한다.
2. [OpenAI-compatible 출력 검증 필터](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
2. [IOP Agent CLI Runtime](phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
현재 Python 감시·dispatcher와 Node CLI runtime의 전체 동등성을 단일 Go CLI Provider·AgentTaskManager 및 독립 `iop-agent` binary로 이전한다.
3. [OpenAI-compatible 출력 검증 필터](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-output-validation-filters.md)
OpenAI-compatible single-stream 반복과 incoming request history에 누적된 assistant 반복, JSON contract 검증/repair 경로를 안정화한다.
3. [OpenAI-compatible Incomplete Tool Call Syntax Gate](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md)
4. [OpenAI-compatible Incomplete Tool Call Syntax Gate](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-incomplete-tool-call-syntax-gate.md)
terminal provider 응답의 incomplete tool-call syntax를 deterministic하게 판정한다.
4. [OpenAI-compatible Runtime Output Integrity Filter](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md)
5. [OpenAI-compatible Runtime Output Integrity Filter](phase/knowledge-tool-optimization-extension/milestones/openai-compatible-runtime-output-integrity-filter.md)
terminal output invariant와 공통 filter/retry pipeline을 정의한다.
5. [LLM 판별 기반 Missing Tool Call 재시도 Gate](phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md)
6. [LLM 판별 기반 Missing Tool Call 재시도 Gate](phase/knowledge-tool-optimization-extension/milestones/llm-judged-missing-tool-call-retry-gate.md)
tool 사용 의도 누락 케이스를 LLM judge와 buffered retry 후보로 검토한다.
6. [Tool Call 판정 모델 Gate 리뷰](phase/knowledge-tool-optimization-extension/milestones/tool-call-validator-model-gate-review.md)
7. [Tool Call 판정 모델 Gate 리뷰](phase/knowledge-tool-optimization-extension/milestones/tool-call-validator-model-gate-review.md)
schema만으로 어려운 tool-call 후보에 validator 모델을 쓸지 검토한다.
7. [Pi CLI Provider Integration](phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md)
8. [Pi CLI Provider Integration](phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md)
Pi를 Node CLI provider 실행 후보에 추가하고 OpenAI-compatible route smoke로 안정화한다.
8. [CLI Agent Group Grade Routing](phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)
9. [CLI Agent Group Grade Routing](phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)
lane/grade 파일명과 `metadata.agent_group.task_file` 기반 CLI agent group 라우팅 계약을 정리한다.
9. [공통 Agent Task Runtime과 Desktop Agent](phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md)
현재 Python 감시·dispatcher와 Node CLI runtime을 단일 Go CLI Provider·AgentTaskManager로 이전하고 Edge 없는 Flutter macOS Desktop Agent가 같은 구현을 사용한다.
10. [에이전트 작업 루프 오케스트레이션 MVP](phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)
일반 사용자 요청을 direct/Plan/Milestone으로 분류하고, 사용자 agent의 tool call로 만든 작업 파일을 IOP가 읽어 다음 실행·리뷰·완료 단계까지 연결한다.

View file

@ -157,4 +157,4 @@
- agent-ops 결합 기준: `plan`/`code-review` 스킬은 `PLAN-*`/`CODE_REVIEW-*` 파일과 각 루프의 lifecycle을 소유하고, CLI provider agent 선택은 Edge/runtime routing 책임으로 둔다. 스킬이 provider/agent를 직접 고르거나 다른 스킬 그룹 절차를 자동 호출하지 않는다.
- `metadata.agent_group`은 OpenAI-compatible 요청의 라우팅 metadata 컨테이너다. 실제 목적별 agent group assignment는 예약어 `default_agent=auto`일 때만 사용하며, direct `default_agent=<agent-id>` 요청은 같은 task file path와 filename validation을 사용하되 group 후보 산출로 넘어가지 않는다.
- `DOC-*` 같은 추가 prefix는 이 Milestone에서는 route prefix 계약으로만 다룬다. 별도 문서 작성 skill lifecycle이 필요하면 후속 Milestone/SDD에서 추가하고, 이번 라우팅 계약은 prefix config와 runtime dispatch 경계만 고정한다.
- 후속 SDD: [공통 Agent Task Runtime과 Desktop Agent](../shared-agent-task-runtime-desktop-agent/SDD.md)가 known failure retry/failover, context transfer, 중복 실행 방지와 Desktop runtime lifecycle을 소유한다. [Provider 사용량 알림과 운영 표면](../../../phase/automation-runtime-bridge/milestones/provider-usage-notification-operations-surface.md)은 runtime event 소비자로 다룬다.
- 후속 Milestone: [IOP Agent CLI Runtime](../../../phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)이 known failure retry/failover, context transfer와 중복 실행 방지를 소유하고 계획 승격 시 SDD를 작성한다. Flutter lifecycle은 후속 Desktop Milestone으로 분리하며 [Provider 사용량 알림과 운영 표면](../../../phase/automation-runtime-bridge/milestones/provider-usage-notification-operations-surface.md)은 runtime event 소비자로 다룬다.

View file

@ -0,0 +1,157 @@
# SDD: IOP Agent CLI Runtime
## 위치
- Milestone: [IOP Agent CLI Runtime](../../../phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md)
- Phase: [PHASE.md](../../../phase/automation-runtime-bridge/PHASE.md)
## 상태
[승인됨]
## SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목: 없음
## 문제 / 비목표
- 문제: Agent Task 실행·관측·복구 책임이 현재 Python dispatcher를 모델이 감시하는 흐름과 Node 내부 CLI runtime에 나뉘어 있다. 이 SDD는 검증된 동작을 축소하지 않고 공통 Go runtime과 독립 `iop-agent` CLI로 이전하면서 Node가 같은 provider·manager 구현을 소비하는 책임, lifecycle, 상태와 evidence 경계를 고정한다.
- 비목표:
- Flutter 설정 UI, tray, macOS `.app` shell과 Unity 3D Character를 구현하지 않는다.
- Python 코드를 production dependency로 사용하거나 진행 중 Python process state를 승계하지 않는다.
- provider 로그인, credential 저장, 사용자 승인 UI와 billing 자동화를 구현하지 않는다.
- agent-ops를 사용하지 않는 일반 요청의 direct/Plan/Milestone 분류나 합성 tool call 주입을 구현하지 않는다.
- local proto-socket의 세부 field를 SDD에 계약 원문으로 복제하지 않는다.
## Source of Truth
| 영역 | 기준 | 메모 |
|------|------|------|
| Roadmap | [IOP Agent CLI Runtime](../../../phase/automation-runtime-bridge/milestones/iop-agent-cli-runtime.md) | CLI 목표, 기능 Task, 범위와 완료 상태의 원본 |
| 이전 설계 | [공통 Agent Task Runtime과 Desktop Agent](../../../phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md), [기존 SDD](../shared-agent-task-runtime-desktop-agent/SDD.md) | CLI parity 요구를 이관할 참조이며 결합된 Desktop delivery는 구현 입력이 아님 |
| Node Wire | [Edge-Node Runtime Wire](../../../../agent-contract/inner/edge-node-runtime-wire.md) | Node bridge가 보존해야 할 기존 `RunRequest`/`RunEvent`, cancel, command와 config 의미 |
| Config Compatibility | [Edge Config Runtime Refresh](../../../../agent-contract/inner/edge-config-runtime-refresh.md) | 기존 Node provider/config 의미의 호환 기준이며 `iop-agent` app-owned YAML 원문을 대신하지 않음 |
| Project Workflow | 등록 project의 agent-ops Milestone·Plan·Code Review·USER_REVIEW 계약과 workflow adapter | 작업 의미와 artifact contract는 project가 소유하고 runtime은 구조 판정과 실행을 소유함 |
| Project State | 각 workspace의 `agent-task`, `agent-roadmap`, `WORK_LOG.md`, `agent-log` | 작업 원문, 진행, review와 완료 evidence의 durable source of truth |
| Host State | `iop-agent` app-owned YAML, project registry, versioned checkpoint와 workspace lease | provider/global 설정, project override와 최소 복구 상태의 source of truth |
| External Provider | 사용자가 YAML에 선언하고 이미 인증한 CLI provider | runtime은 discovery, status, 실행과 cancel만 수행하며 인증을 소유하지 않음 |
| User Decision | 없음 | 현재 제품·범위 결정은 모두 확정됐고 세부 command, field, backoff와 파일 배치는 표준안으로 정함 |
## State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|------|-----------|-----------|------|
| `starting` | `iop-agent serve` 또는 Node host가 공통 runtime을 시작했다 | `config-validating` 또는 `failed` | runtime build와 host identity |
| `config-validating` | app-owned YAML과 project override revision을 읽었다 | `provider-discovering`, `config-error` | schema validation과 immutable config revision |
| `provider-discovering` | 선언 provider의 binary/version/authenticated readiness/status를 조회한다 | `project-watching`, `provider-error` | provider discovery snapshot |
| `project-watching` | 명시 등록 workspace와 config watcher가 활성화됐다 | `workspace-claiming`, `idle`, `stopped` | registry와 filesystem event |
| `workspace-claiming` | auto-run, manual run 또는 resume가 요청됐다 | `reconciling`, `blocked` | canonical workspace identity, lease와 checkpoint revision |
| `reconciling` | lease 획득 또는 host restart 뒤 filesystem, checkpoint, process/session과 completion ledger를 대조한다 | `idle`, `work-ready`, `running`, `blocked`, `failed` | execution/attempt, locator, active pair, archive와 last-writer state |
| `idle` | ready work가 없고 watcher가 활성 상태다 | `work-ready`, `config-pending`, `stopped` | project scan과 watcher event |
| `work-ready` | 남은 agent-task, pinned resume/selfcheck 또는 최상위 ready Milestone이 있다 | `previewing`, `selecting`, `running`, `stopped` | dependency와 persisted route state |
| `previewing` | read-only preview가 요청됐다 | 영속 전이 없이 caller에 반환 | 동일 selector/dependency 판정과 no-side-effect evidence |
| `selecting` | 새 worker stage에 config와 quota snapshot을 적용한다 | `running`, `blocked`, `selection-error` | 하나의 RouteDecision과 durable candidate/rule history |
| `running` | provider process/session이 pinned config·route로 실행 중이다 | `submission-validating`, `review-validating`, `retrying`, `failing-over`, `cancelling`, `blocked`, `failed` | normalized stream, process/session locator와 typed failure |
| `submission-validating` | worker 또는 selfcheck가 성공 종료했다 | pinned selfcheck의 `work-ready`, official review의 `work-ready`, Pi `evidence-repairing`, `retrying`, `blocked` | completing route, pair/identity와 provider-neutral artifact matcher |
| `evidence-repairing` | Pi selfcheck 뒤 review artifact의 worker-owned field가 미완성이고 같은 native context가 유효하다 | 같은 context의 `running`, official review의 `work-ready`, `blocked`, `cancelling` | durable repair intent, incomplete ordinal, locator와 matcher snapshot |
| `review-validating` | official review process가 종료했다 | PASS의 `reconciling`, WARN/FAIL의 `work-ready`, USER_REVIEW의 `blocked`, `retrying`, `failed` | exact verdict, filesystem progress, follow-up과 completion artifact |
| `retrying` | 알려진 same-target 복구 가능 오류와 stage budget이 남았다 | bounded backoff 뒤 `running`, `blocked`, `cancelling` | failure budget과 retry ordinal/deadline |
| `failing-over` | typed quota/context/model/stream failure와 unused eligible alternate가 있다 | fault-atomic route/context commit 뒤 `running`, `blocked` | persisted route history, runtime quota observation과 continuation handoff |
| `config-pending` | 실행 중 새 유효 config revision이 관측됐다 | 현재 실행 종료 뒤 `work-ready` 또는 `idle` | 실행 snapshot은 유지하고 다음 agent 호출부터 새 revision 적용 |
| `blocked` | invalid state, unknown error, budget 소진 또는 eligible target 부재로 work unit을 진행할 수 없다 | identity-matched resume/retry의 `reconciling`, 사용자 stop의 `stopped` | task-local blocker와 project log |
| `cancelling` | 사용자 또는 host가 project 실행 중단을 요청했다 | `stopped`, `failed` | process group/session cancel evidence |
| `stopped` | auto-run off 또는 명시 stop이 완료됐다 | `config-validating`, `project-watching` | 사용자 재개 또는 config enable event |
| `failed` | unrecoverable runtime/config/provider 오류가 발생했다 | 독립 project는 계속되고 해당 project는 수정 후 `reconciling` | surfaced error와 보존된 route/checkpoint |
## Interface Contract
- 계약 원문:
- Node 호환 경계는 [Edge-Node Runtime Wire](../../../../agent-contract/inner/edge-node-runtime-wire.md)를 유지한다.
- `iop-agent` app-owned YAML과 local proto-socket의 client-neutral 상태·event·control 계약은 현재 `agent-contract`에 없으므로 구현 계획의 첫 계약 작업에서 생성한다. 계약 생성 전 proto/config 코드를 확정하지 않는다.
- 입력:
- `RuntimeConfig`: config revision, provider catalog, global defaults, selection policy와 log/state root다.
- `ProjectRegistration`: stable registry id, canonical workspace instance, enabled/auto-run과 project override다.
- `ProviderProfile`: stable provider/model/profile id, command/env reference, execution/session/status capability와 approval bypass mapping이다.
- `SelectionPolicy`: default target과 시간, quota/token, agent/stage/lane/grade, capability, known failure 조건을 가진 ordered rule array다.
- `WorkRequest`: project/workspace, 이미 선택된 task 또는 Milestone, stage/work-unit와 dependency/persisted route identity다.
- `PreviewRequest`: 같은 판정기를 side effect 없이 실행할 project/workspace와 optional work identity다.
- `ProjectWorkflowAdapter`: project-owned artifact contract를 normalized active pair, submission completeness, review verdict, USER_REVIEW blocker와 completion state로 반환한다.
- 출력:
- `RouteDecision`: 외부에 노출할 provider/model 하나와 내부에 저장할 ordered candidate, rule/reason, eligibility/rejection와 used history다.
- `RuntimeEvent`: execution/attempt, project/work-unit/stage, lifecycle, stream/heartbeat, config/quota reference와 terminal result다.
- `ProviderStatus`: official provider/model/profile id, readiness, capability, quota/status와 오류 근거다.
- `PreviewResult`: 실행과 같은 selection/dependency/blocker 판단 및 no-side-effect 증명이다.
- `ProjectLogRecord`: route, quota, process/session locator, task별 loop/attempt, failure/retry/failover/review/completion을 연결한다.
- 금지:
- Node와 `iop-agent` host에 provider 또는 AgentTaskManager 구현을 복사하지 않는다.
- Python process, function name, marker와 persisted key를 production 계약으로 가져오지 않는다.
- malformed checkpoint/route/locator를 빈 상태나 현재 정책으로 조용히 초기화·재선택하지 않는다.
- Flutter·Unity가 provider 선택, task scheduling, retry/failover 또는 project state를 다시 소유하지 않는다.
- worker exit code나 완료 문구만으로 review-ready/completed를 확정하지 않는다.
- runtime `WORK_LOG`/heartbeat 변화만 review progress로 세지 않는다.
## Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|----|----------------|-------|------|------|
| S01 | `common-runtime` | Node와 `iop-agent`가 같은 provider profile을 선언했다 | run, stream, resume와 cancel을 각각 수행한다 | 두 host가 같은 common implementation과 lifecycle/failure 의미를 사용하고 중복 구현이 없다 |
| S02 | `provider-catalog` | provider가 설치·인증됨, 미설치, 미인증 또는 model 미지원 상태다 | discovery와 status를 실행한다 | 공식 provider/model/profile 이름으로 readiness가 반환되고 실행 불가 상태는 구체적인 오류가 된다 |
| S03 | `task-manager` | 등록 project에 남은 task와 ready Milestone이 있다 | supervisor 모델 없이 auto-run한다 | 남은 task를 먼저 처리한 뒤 priority queue의 ready Milestone을 순차 실행하고 독립 project는 병렬 진행한다 |
| S04 | `node-consumer` | 기존 Node run/session/status 요청과 config fixture가 있다 | Node를 common runtime bridge로 전환한다 | 기존 Edge-Node wire 의미와 provider behavior가 보존되고 Node 내부 duplicate provider가 없다 |
| S05 | `config-registry` | defaults와 project override, 겹치는 ordered rules 및 실행 중 revision 변경이 있다 | config를 load/watch한다 | override와 array 전체 교체가 결정적으로 적용되고 현재 실행은 기존 revision, 다음 호출은 새 revision을 사용한다 |
| S06 | `target-policy` | 시간·quota·stage·grade 조건이 겹치고 persisted route가 있거나 손상됐다 | selection 또는 resume한다 | 첫 일치 rule의 provider/model 하나가 반환되고 판단 이력이 저장되며 손상 상태는 silent reselection 없이 오류가 된다 |
| S07 | `quota-failure` | provider별 available/exhausted/unknown/not-applicable와 runtime quota error가 있다 | admission, 실행 실패와 failover를 처리한다 | typed evidence와 immutable snapshot이 격리되고 알려진 정책 안에서만 retry/failover하며 unknown은 work-unit blocker가 된다 |
| S08 | `workflow-evidence` | worker/selfcheck/review artifact에 완성, placeholder, identity mismatch와 Pi selfcheck 후 미완성이 있다 | submission/review gate를 평가한다 | 모든 provider에 같은 matcher가 적용되고 Pi만 같은 native context repair 후 재검증하며 통과 전 official review는 호출되지 않는다 |
| S09 | `state-recovery` | duplicate manager, restart, live child, corrupt checkpoint, partial archive와 failure budget이 있다 | lease 획득과 reconciliation을 수행한다 | invocation owner는 하나이고 valid live work를 중복 실행하지 않으며 불명확 상태는 추정 복구 없이 blocker/error가 된다 |
| S10 | `cli-surface` | binary와 YAML만 설치된 로그인 macOS 환경이다 | validate, list, preview, serve, stop/resume와 status command를 사용한다 | UI 없이 설정·실행·제어·관측 가능하고 기본 auto-run과 명시 stop이 일관되게 동작한다 |
| S11 | `local-control` | 둘 이상의 후속 client가 같은 `iop-agent` 상태를 소비할 수 있다 | local control contract를 생성하고 server-side endpoint를 검증한다 | client-neutral protobuf 상태·event·control 의미가 고정되고 UI/runtime 책임이 분리된다 |
| S12 | `project-logs` | 같은 task의 pair loop 11 retry/follow-up과 다른 task의 병렬 loop, 독립 work-log archive ordinal이 있다 | START/FINISH와 completion archive를 기록·복구한다 | task별 loop/attempt/locator가 안정되고 terminal closure 뒤에만 exactly-once archive와 cleanup이 수행된다 |
| S13 | `parity-cutover` | 기존 combined SDD, Python/Node behavior와 완료된 selector evidence가 있다 | 각 동작을 absorb/replace/not-applicable로 분류한다 | 미분류 동작과 Python runtime 의존성, 정적 route/cap 문구 및 Node duplicate implementation이 남지 않는다 |
| S14 | `logged-smoke` | 실제 로그인된 provider와 둘 이상의 등록 project/clone workspace가 있다 | discovery부터 실행, quota, cancel, 재호출, restart와 completion까지 수행한다 | credential을 기록하지 않고 project별 로그와 E2E evidence가 남으며 한 project 오류가 다른 project를 멈추지 않는다 |
## Evidence Map
| Scenario | Required Evidence | `agent-task` 연결 | 완료 Evidence 기대 |
|----------|-------------------|------------------|---------------------------|
| S01 | common provider conformance와 duplicate implementation search | `agent-task/m-iop-agent-cli-runtime/...` | `common-runtime` Roadmap Completion과 Node/CLI test output |
| S02 | provider discovery/status table test와 authenticated smoke | `agent-task/m-iop-agent-cli-runtime/...` | `provider-catalog` Roadmap Completion과 readiness/error evidence |
| S03 | deterministic multi-project scheduler integration test | `agent-task/m-iop-agent-cli-runtime/...` | `task-manager` Roadmap Completion과 no-supervisor trace |
| S04 | Node wire/config compatibility suite | `agent-task/m-iop-agent-cli-runtime/...` | `node-consumer` Roadmap Completion과 기존 contract conformance evidence |
| S05 | config merge, invalid config, watcher와 revision integration test | `agent-task/m-iop-agent-cli-runtime/...` | `config-registry` Roadmap Completion과 revision A/B trace |
| S06 | ordered selector, persisted route와 tamper matrix | `agent-task/m-iop-agent-cli-runtime/...` | `target-policy` Roadmap Completion과 selected rule/reason/history evidence |
| S07 | quota parser, runtime observation, isolation과 failover test | `agent-task/m-iop-agent-cli-runtime/...` | `quota-failure` Roadmap Completion과 snapshot/failure transition evidence |
| S08 | provider-neutral matcher와 Pi same-context repair matrix | `agent-task/m-iop-agent-cli-runtime/...` | `workflow-evidence` Roadmap Completion과 review invocation/locator evidence |
| S09 | lease, process identity, checkpoint, restart와 archive fault matrix | `agent-task/m-iop-agent-cli-runtime/...` | `state-recovery` Roadmap Completion과 no-duplicate/exact-state evidence |
| S10 | binary/YAML CLI command integration test | `agent-task/m-iop-agent-cli-runtime/...` | `cli-surface` Roadmap Completion과 headless operation transcript |
| S11 | 신규 local control agent-contract와 proto-socket server contract test | `agent-task/m-iop-agent-cli-runtime/...` | `local-control` Roadmap Completion, contract link와 event/control trace |
| S12 | WORK_LOG loop/attempt/locator, dynamic frontier와 archive reconciliation fixture | `agent-task/m-iop-agent-cli-runtime/...` | `project-logs` Roadmap Completion과 exactly-once archive evidence |
| S13 | disposition-complete parity matrix, stale dependency와 duplicate search | `agent-task/m-iop-agent-cli-runtime/...` | `parity-cutover` Roadmap Completion과 zero-unclassified/zero-match evidence |
| S14 | actual logged-in macOS multi-project field smoke manifest | `agent-task/m-iop-agent-cli-runtime/...` | `logged-smoke` Roadmap Completion과 redacted environment/result manifest |
## Cross-repo Dependencies
- 없음. 같은 IOP monorepo 안에서 공통 package, Node bridge, `iop-agent` binary와 protocol source를 관리한다.
- 구현 순서 선행 조건은 [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](../../../phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](../../../phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)의 결과다.
## Drift Check
- [x] Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- [x] Evidence Map이 code-review/complete.log에서 검증 가능하다.
- [x] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- [x] 사용자 리뷰가 필요한 항목은 없으며 `USER_REVIEW.md`를 만들지 않았다.
## 사용자 리뷰 이력
- 없음
## 작업 컨텍스트
- 표준선: `iop-agent`는 headless runtime·CLI와 app-owned YAML/project registry/checkpoint의 관리 주체이고 workspace는 project 작업 파일의 source of truth다.
- 표준선: 자동 실행과 provider approval bypass는 기본 on이며 사용자는 언제든 project를 stop할 수 있다. provider authentication과 credential은 각 CLI가 소유한다.
- 표준선: Node와 `iop-agent`는 공통 provider/manager package를 소비하고 host-specific wire, command와 lifecycle adapter만 가진다.
- 표준선: Python과 [기존 SDD](../shared-agent-task-runtime-desktop-agent/SDD.md)는 behavior fixture다. 계획 승격 시 provider, scheduler, workflow artifact, review/finalization, process/session, quota/error, log/reconciliation 전 영역을 `absorb | replace | not-applicable`로 분류하며 production dependency로 남기지 않는다.
- 표준선: local proto-socket은 binary가 소유하는 client-neutral 경계다. Flutter와 Unity는 서로 통신하지 않고 후속 Milestone에서 각자 이 계약을 소비한다.
- 표준선: command 이름, package/file 배치, proto field, retry backoff 수치와 log serialization은 기존 구조와 표준안으로 정하고 사용자 결정으로 올리지 않는다.
- 후속 SDD: Flutter Desktop 설정·운영 UI와 Unity 3D Character Milestone을 만들 때 각각 필요 여부를 판정한다.

View file

@ -7,14 +7,13 @@
## 상태
[검토중]
[대체됨]
## SDD 잠금
- 상태: 잠금
- 사용자 리뷰: [USER_REVIEW.md](USER_REVIEW.md)
- 잠금 항목:
- [ ] [D01] macOS에서 창 닫기, 명시 Quit, 로그인 시 시작이 Desktop runtime과 실행 중 agent에 미치는 background lifecycle을 결정한다.
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목: 없음
## 문제 / 비목표
@ -32,7 +31,7 @@
| 영역 | 기준 | 메모 |
|------|------|------|
| Roadmap | [공통 Agent Task Runtime과 Desktop Agent](../../../phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md) | 제품 목표, 전체 동등성 범위, 기능 Task와 제외 범위 |
| Policy | [Agent Task 동적 실행 Target Selector](../../../phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [CLI Agent Group Grade Routing](../../../phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md) | 선택, route pin, quota, failover와 agent/model rule의 우선 기준 |
| Policy | [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [CLI Agent Group Grade Routing](../../../phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md) | 선택, route pin, quota, failover와 agent/model rule의 우선 기준 |
| Project Workflow | 등록 workspace의 `agent-ops/rules/project`, `agent-ops/skills/project`, Milestone·Plan·Code Review 파일과 project workflow adapter | workflow 의미와 artifact contract는 project가 소유하고, 공통 runtime은 adapter의 구조 판정으로 이미 선택된 work step과 review lifecycle을 실행한다 |
| Separate Orchestration | [에이전트 작업 루프 오케스트레이션 MVP](../../../phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md) | agent-ops를 직접 쓰지 않는 사용자의 일반 요청 분류, IOP 소유 Plan/Milestone skill과 합성 tool call은 별도 상위 기능이다 |
| Reference Behavior | `agent-ops/skills/project/orchestrate-agent-task-loop/scripts`, target-selector의 최종 PASS·`complete.log`·fixture와 `WORK_LOG.md` | Python은 동작·오류·관측 evidence일 뿐 production dependency가 아니다. 미종결 active plan/review는 결함 후보로만 사용하고 공통 계약으로 승격하지 않는다 |
@ -41,7 +40,7 @@
| Project State | 각 등록 workspace의 `agent-task`, `agent-roadmap`, `WORK_LOG.md`, `agent-log` | 작업 원문·진행·evidence의 durable source of truth |
| App State | app-owned YAML config tree, project registry, 최소 runtime checkpoint | provider/global 설정과 registry id별 project override를 모두 소유한다. workspace config나 project 작업 원문을 중앙 권위로 복제하지 않는다 |
| External Provider | 사용자가 YAML에 선언하고 이미 인증한 CLI provider | app은 discovery/readiness/status/실행만 하며 인증을 소유하지 않는다 |
| User Decision | D01 | macOS window/quit/login-start lifecycle만 사용자 결정으로 남기고 package/API/config/state 세부는 문서의 표준선을 따른다 |
| User Decision | 없음 | D01은 결합 범위 분리에 따라 [범위 이관 기록](user_review_0.log)으로 남기고 후속 Flutter Desktop Milestone에서 다시 검토한다 |
## State Machine
@ -52,7 +51,7 @@
| `provider-discovering` | 선언 provider의 binary/version/authenticated readiness/model capability를 read-only 조회한다 | `project-watching` 또는 `provider-error` | discovery snapshot |
| `project-watching` | 명시 등록 workspace의 기존 agent-ops task/roadmap watcher와 app-owned config watcher가 활성화됐다 | `workspace-claiming`, `config-pending` 또는 `stopped` | project registry와 watcher event |
| `workspace-claiming` | enabled workspace에서 auto-run 또는 resume가 요청됐다 | lease와 checkpoint가 유효하면 `reconciling`, 충돌·손상·판독 실패면 `failed` | canonical workspace identity, lease owner, checkpoint schema/runtime build revision |
| `reconciling` | lease 획득 또는 host restart 뒤 active task/checkpoint/process/archive/ledger를 대조한다 | `idle`, `work-ready`, live execution의 `running`, 재시도 가능한 `blocked` 또는 `failed` | process start identity, execution/attempt id, archive baseline, valid complete evidence와 last-writer state |
| `reconciling` | lease 획득 또는 host restart 뒤 active task/checkpoint/process/archive/ledger를 대조한다 | `idle`, 동적 lineage의 다음 dependency-ready `work-ready`, live execution의 `running`, 재시도 가능한 `blocked` 또는 `failed` | process start identity, execution/attempt id, task별 active-pair loop와 locator, WORK_LOG archive baseline, valid complete evidence와 last-writer state |
| `config-pending` | agent 실행 중 새 유효 config revision이 관측됐다 | `running``work-ready` 또는 `idle` | 현재 execution은 기존 snapshot을 유지하고 다음 호출에 새 revision 적용 |
| `work-ready` | 기존 agent-task 또는 기존 priority-queue의 최상위 ready Milestone이 있거나 persisted route에 pinned selfcheck/resume이 준비됐다 | pinned selfcheck/resume은 selector 재평가 없이 `running`, 그 밖의 실행은 `selecting`, preview이면 비영속 `previewing`, 또는 `stopped` | project filesystem scan과 persisted route/continuation. 일반 요청으로 새 work item을 합성하지 않는다 |
| `previewing` | 사용자가 initial/resume/dependency/blocker preview를 요청했다 | persistent state transition 없이 caller로 반환 | 현재 filesystem, config revision과 immutable quota view로 만든 `PreviewResult`; checkpoint/project 파일/provider process를 변경하지 않는다 |
@ -64,7 +63,7 @@
| `retrying` | 알려진 동일-target 복구 가능 오류와 failure budget이 남았다 | bounded backoff 뒤 `running`, stop/cancel이면 `cancelling`, 한도·비복구 오류면 `blocked` 또는 `failed` | typed failure, transition history, retry ordinal/deadline과 cancellation evidence; restart에도 같은 retry를 중복 예약하지 않는다 |
| `failing-over` | provider adapter가 quota/context/model/stream failure를 확정해 failover 평가가 필요하다. quota이면 base admission snapshot을 참조하는 별도 runtime observation을 생성하고 app-global key 갱신을 요청한다 | route/context의 fault-atomic commit 뒤 `running`, alternate 부재 또는 준비·commit 오류 시 exact pre-state를 보존한 `blocked` | 같은 work-unit/candidate order/used history, runtime observation, selected route와 identity가 일치하는 readable locator package 및 durable continuation handoff |
| `cancelling` | 사용자가 project/app 자동 실행을 중단했다 | `stopped` 또는 `failed` | cancel event, process group/session termination evidence |
| `completed` | official review valid PASS, 유일한 project-owned complete archive와 runtime ledger finalization이 함께 확인됐다 | 다음 project work의 `work-ready` 또는 `idle` | review artifact, complete evidence, START/FINISH ledger와 project filesystem state |
| `completed` | 한 task의 official review valid PASS, 유일한 project-owned complete archive와 runtime ledger finalization이 함께 확인됐다 | 새로 해제된 dependency-ready task는 자신의 active-pair loop로 `work-ready`, lineage terminal closure면 `reconciling` `idle` | review artifact, complete evidence, START/FINISH ledger, task별 loop와 project filesystem state. 개별 task 완료는 task-group WORK_LOG archive가 아니다 |
| `blocked` | 알려진 failure에서 eligible alternate가 없거나 failure budget이 소진되어 해당 work unit을 더 진행할 수 없다 | identity가 일치하는 사용자 재시도 또는 policy-authorized status refresh의 `recovery-pending`, 그 밖에는 유지 | work-unit blocker와 project log. 독립 project/branch는 계속 실행 |
| `recovery-pending` | recovery trigger의 blocker/route/work-unit/selected-target과 readable locator package identity가 현재 persisted state와 일치한다 | persisted route와 continuation handoff commit 뒤 `running`, 재입장 불가 시 `blocked`, validation·준비·commit 오류 시 기존 state를 보존한 `recovery-pending` | recovery intent, fresh provider status, pending handoff/attempt locator와 exactly-once consume evidence |
| `failed` | unknown/unrecoverable 오류, invalid provider/config 또는 전이 준비·commit 오류가 발생했다 | `idle`, 독립 project의 `work-ready`, 또는 사용자 수정 뒤 `config-validating` | surfaced error와 project log. 기존 route/history/recovery intent는 손상하지 않는다 |
@ -93,8 +92,9 @@
- `PersistedRoutePlan`: schema revision, task/plan/tag generation, stage/work-unit pin, ordered candidates와 각 eligibility/rejection reason, applied rule/priority, selected target, used/unknown-admission history, transition과 pin revision이다. resume/failover는 이를 재사용하고 현재 시각으로 새 candidate를 만들지 않는다. schema나 selected/candidate/history identity가 손상되면 명시 오류가 된다.
- `PreviewResult`: 선택된 target 또는 blocked/waiting 상태, persisted/예상 route evidence, dependency와 quota view 및 side-effect counter다. preview 전후 state/filesystem deep equality와 provider invocation 0회를 검증할 수 있어야 한다.
- `RuntimeEvent`: start, stdout/stderr delta, normalized delta, provider phase와 matching tool-call/result activity, silence/repetition inspection, heartbeat, session/process locator, selfcheck evidence-repair ordinal·dispatch·response·validation, retry/failover, complete, error, cancelled다.
- `WorkspaceCheckpoint`: schema revision, runtime build/config revision, active work-unit/stage/persisted route plan, execution/attempt/process/session identity, continuation handoff, pending selfcheck evidence-repair의 ordinal·matcher snapshot·dispatch/response state, retry deadline, failure budgets와 finalization state다. 원자적으로 저장하며 project 작업 원문을 복제하지 않는다.
- `ExecutionLedgerRecord`: monotonic sequence, execution/work-unit/attempt identity, runtime build, START/FINISH·transition·terminal result와 locator/archive reference다. runtime이 작성하고 project log/`WORK_LOG` lifecycle을 재조정하는 근거다.
- `WorkspaceCheckpoint`: schema revision, runtime build/config revision, active work-unit/stage/persisted route plan, attempt별 pinned task/pair loop, execution/attempt/process/session identity, active task-group WORK_LOG path와 전체 월별 archive에서 계산해 별도로 고정한 timeline archive ordinal, continuation handoff, pending selfcheck evidence-repair의 ordinal·matcher snapshot·dispatch/response state, retry deadline, failure budgets와 finalization state다. 원자적으로 저장하며 project 작업 원문을 복제하지 않는다.
- `ExecutionLedgerRecord`: monotonic sequence, pinned task/pair loop, execution/work-unit/attempt identity, runtime build, START/FINISH·transition·terminal result와 locator/archive reference다. runtime이 작성하고 project log/`WORK_LOG` lifecycle을 재조정하는 근거다.
- `WorkLogRecord`: `seq | time | loop | event | task | role | attempt | model | result | locator`의 고정 schema다. `seq`는 active task-group log의 event 순서, `loop`는 그 attempt가 시작한 task의 active PLAN/CODE_REVIEW pair future archive suffix, `attempt`는 같은 task/pair/role의 호출 회차다. 정상 active pair에서는 같은 task의 exact `plan_*.log`/`code_review_*.log` count와 pair metadata가 loop에 일치해야 하며, 0~10 archive 뒤 active pair는 loop 11이다. loop는 START 전에 checkpoint/ledger/locator에 pin하고 matching FINISH가 filesystem의 후속 pair나 task archive 상태를 다시 계산하지 않고 같은 값을 사용한다. 같은 pair의 retry·resume은 loop를 유지하고 WARN/FAIL archive와 follow-up pair materialization 뒤 다음 attempt에서만 증가한다. 서로 다른 task 행은 각자의 loop를 가지며 task-group `work_log_N.log` suffix와 독립이다. timeline archive N은 같은 task group의 전체 월별 exact `work_log_N.log` suffix 최대값 다음 수(없으면 0)를 별도로 고정한다. locator가 pinned loop, provider native context/session id, process identity와 stream/heartbeat 경로를 포함한 attempt metadata의 권위 포인터이므로 별도 `context_id` 컬럼은 만들지 않는다.
- `WorkflowArtifactAssessment`: adapter/schema/matcher revision, task/plan/tag identity, actual provider/model/execution class, pair validity, USER_REVIEW validity/blocking reason, matched/missing/placeholder/unchecked worker fields, artifact visibility preflight, review verdict/fingerprint/finalization과 allowed next action이다. provider별 bypass 없이 같은 matcher 결과를 반환하며 Pi selfcheck 뒤 미완성에는 `same-context-selfcheck-evidence-repair`만 허용한다. review progress fingerprint는 plan-declared write-set source와 review/finding artifact를 사용하고 runtime-owned WORK_LOG/heartbeat는 제외한다.
- `SelfcheckEvidenceRepair`: work-unit/task/plan/tag와 CODE_REVIEW path, completing route/config revision, 직전 성공 Pi selfcheck execution/attempt/native session/context locator, matcher revision·artifact fingerprint·missing fields, 고정 영문 prompt/hash, incomplete ordinal, dispatch attempt identity와 `pending | dispatch-recorded | response-observed | validated` 상태다. matcher를 prompt 직전에 다시 실행하고 incomplete이면 해당 ordinal의 dispatch intent를 원자 저장한 뒤 같은 native context를 resume한다. 정상 경로는 ordinal당 exactly-once이고 restart는 live/terminal attempt를 reconcile한다. dispatch 여부가 불명확하면 blind resend 대신 task-local blocker가 되며, matcher 통과 commit은 `selfcheck_done`, repair `validated`, pending 제거와 official-review work-ready를 함께 확정한다. 새 selection, quota probe 또는 fresh session을 만들지 않고 worker/review failure budget과 route used history를 변경하지 않는다.
- `ProviderFailure`: provider/profile, typed class, provider-confirmed 여부, source, bounded evidence, signal과 observed-at이다. provider codec이 생성하며 work-unit role이나 route 결정을 포함하지 않는다.
@ -102,7 +102,7 @@
- `WorkUnitBlocker`: work-unit/stage, persisted route plan id, selected target, terminal failure class, retry evidence package와 provider failure 또는 runtime observation reference다. AgentTaskManager가 생성한다.
- `ContinuationHandoff`: handoff id, work-unit/route/previous-next target, source locator와 workspace/task/PLAN/raw/normalized artifact identity, exact continuation payload 및 `pending | locator-recorded | consumed` 상태다.
- `RecoveryIntent`: blocker/route/work-unit/selected-target identity, trigger, persisted candidate order/used history, validated locator package reference, continuation handoff id와 commit 상태다. attempt locator가 handoff identity와 source context를 durable하게 기록한 뒤 한 번만 소비한다.
- `ProjectLogRecord`: execution/work-unit/project identity로 persisted route plan/rule/candidate/reason, quota, config, process/session, stream/heartbeat, transition과 terminal 결과를 연결한다.
- `ProjectLogRecord`: execution/work-unit/project/task-pair loop identity로 persisted route plan/rule/candidate/reason, quota, config, process/session, stream/heartbeat, transition과 terminal 결과를 연결한다.
- `ProviderStatus`: 외부에는 official provider/model/profile id로 보이는 discovery/readiness/authenticated state, capability, app-global quota/status와 오류 근거다. generic `cli` adapter는 Desktop 주 식별자가 아니다.
- 금지:
- WorkRequest를 일반 사용자 요청 triage 계약으로 확장하거나 그 입력만으로 runtime core가 direct/Plan/Milestone을 분류·생성하지 않는다. 명시 요청한 task group이 관측·persist된 적이 없을 때 이를 empty completion으로 보고하지 않는다.
@ -113,7 +113,9 @@
- dependency가 없는 서로 다른 task를 같은 target, overlapping/unknown plan write-set이라는 이유로 직렬화하지 않는다. write-set은 review progress 입력이며 dispatch lock이 아니다.
- USER_REVIEW 파일 존재만으로 user-review terminal state를 만들거나 contract가 불완전·충돌한 문서를 정상 사용자 대기로 숨기지 않는다.
- 자동 target 변경·failover·restart에서 stage failure budget을 초기화하거나 failure count를 새 initial route의 선택 조건으로 사용하지 않는다. 명시적 identity-matched `retry_blocked`만 blocker와 해당 stage budget을 초기화하고 route/history는 보존한다.
- worker/reviewer에게 runtime START/FINISH timeline 작성을 맡기거나 last writer 종료와 유일한 valid completion 확인 전에 `WORK_LOG`를 이동·attempt log를 삭제하지 않는다.
- worker/reviewer에게 runtime START/FINISH timeline 작성을 맡기거나 동적 dependency lineage의 terminal closure, last writer 종료와 모든 task의 유일한 valid completion 확인 전에 task-group `WORK_LOG`를 이동·attempt log를 삭제하지 않는다.
- dependency frontier가 새로 열릴 때 active `WORK_LOG`를 static batch별로 분리하지 않는다. 서로 다른 task의 loop를 하나의 group-wide 값으로 강제하거나 task loop를 `work_log_N.log` suffix에서 계산하지 않고, 같은 active pair의 restart·blocker·retry 또는 START 뒤 filesystem pair가 바뀐 FINISH에서 loop를 다시 계산하지 않는다. active pair metadata·plan/review count·checkpoint/locator/row loop나 독립 timeline archive ordinal 불일치를 추정 renumber로 숨기지 않는다.
- loop 컬럼이 없는 archived `work_log_N.log`를 backfill·재작성하거나 active legacy `WORK_LOG.md`에 새 schema 행을 섞지 않는다. active legacy log는 기존 owner가 terminal closure로 archive한 뒤에만 새 runtime이 해당 task group의 다음 WORK_LOG를 생성한다.
- worker process exit 0, 체크박스 표시 하나 또는 worker의 자체 완료 문구만으로 review-ready/completed를 확정하지 않는다.
- 출력 silence나 동일 normalized chunk 반복 관측만으로 live process를 종료·block·retry·failover하지 않고, tool-running phase는 call/result identity가 모두 닫히기 전에 완료로 판정하지 않는다.
- runtime-owned WORK_LOG/heartbeat 변화만으로 official review no-progress counter를 초기화하지 않는다.
@ -149,7 +151,7 @@
| S01 | `provider-runtime` | Node와 Desktop이 동일 provider profile을 선언했다 | 각각 짧은 실행과 cancel을 수행한다 | 동일 common provider implementation과 event/failure 의미를 사용하고 host별 provider 복제가 없다 |
| S02 | `agent-task-manager` | agent-ops 작업 체계를 가진 project에 기존 task와 ready Milestone이 있다 | supervisor 모델 없이 auto-run을 시작한다 | 남은 task를 먼저 처리하고 이후 기존 priority queue를 순차 소비한다 |
| S03 | `host-boundary` | Node run request와 Desktop local request가 같은 logical provider target을 가리킨다 | 두 host가 실행한다 | Node는 기존 wire event로, Desktop은 local event로 변환하되 core lifecycle은 동일하다 |
| S04 | `parity-cutover` | current Milestone/work evidence, Python dispatcher/selector와 Node behavior inventory가 있다 | 영역별 동작을 absorb/replace/not-applicable로 분류하고 cutover를 검증한다 | 미분류 동작이 없고 absorb/replace 행이 test/smoke evidence를 가지며 Python runtime dependency와 Node provider duplicate가 남지 않는다 |
| S04 | `parity-cutover` | current Milestone/work evidence, Python dispatcher/selector와 Node behavior inventory, loop 컬럼이 없는 archived work logs 및 active legacy WORK_LOG 유무가 있다 | 영역별 동작을 absorb/replace/not-applicable로 분류하고 cutover를 검증한다 | 미분류 동작이 없고 absorb/replace 행이 test/smoke evidence를 가지며 Python runtime dependency와 Node provider duplicate가 남지 않는다. legacy archive는 byte-identical이고 active legacy log가 있으면 mixed-schema append 없이 기존 owner의 terminal archive까지 cutover가 차단된다 |
| S05 | `provider-catalog` | declared provider가 설치·인증됨, 미설치, 미인증, model 미지원 상태 중 하나다 | read-only discovery를 실행한다 | 공식 계열 이름과 내부 id가 정규화되고 실행 불가 상태는 구체적인 오류가 된다 |
| S06 | `config-ownership` | agent가 revision A로 실행 중이고 app-owned project override revision B가 저장된다 | watcher가 B를 검증한다 | 현재 agent는 A로 끝나고 다음 호출은 B를 사용하며 invalid B면 새 dispatch가 config error로 중단된다 |
| S07 | `selector-policy` | default와 둘 이상의 겹치는 ordered rule이 있다 | Node 또는 Desktop 정책을 평가한다 | 첫 일치 rule의 provider/model 하나만 반환되고 host별 policy 차이가 core evaluator 의미를 바꾸지 않는다 |
@ -173,7 +175,7 @@
| S25 | `workspace-runtime-ownership` | 같은 canonical workspace에 중복 manager, PID가 재사용된 locator, live child, 손상 checkpoint 또는 scheduler 예외가 있다 | host가 lease를 획득하거나 재시작 reconciliation을 수행한다 | invocation owner는 하나뿐이고 live child는 process start/attempt identity로 drain·인계되며 충돌·손상은 명시 오류가 되고 새 agent가 중복 시작되지 않는다 |
| S26 | `workflow-state-drain` | duplicate/incomplete active pair, valid·filename-only·불완전·충돌 USER_REVIEW, malformed identity, missing/ambiguous predecessor와 동일 target 또는 overlapping/unknown write-set의 독립 ready branch가 함께 있다 | project workflow adapter와 scheduler가 work set을 평가한다 | contract-valid USER_REVIEW와 invalid work unit만 대기·차단되고 target/write-set barrier 없이 독립 branch와 실행 중 agent는 계속되며 동일 task 중복 attempt만 배제되고 predecessor의 유일한 완료 뒤 follow-up이 정확히 한 번 실행된다 |
| S27 | `stage-failure-budget` | 한 worker가 primary와 alternate에서 실패하고 host가 재시작되며 별도 review stage도 실패했다 | 자동 retry/failover, stage success와 identity-matched `retry_blocked`를 수행한다 | worker budget은 자동 target/restart를 넘어 누적되고 review budget과 분리되며 stage 성공은 해당 budget을 초기화한다. 명시 retry는 해당 blocker/budget만 초기화하고 route/history를 보존하며 failure count는 새 route를 만들지 않는다 |
| S28 | `completion-ledger-reconciliation` | official PASS 전후 crash, task 소실, 새 archive 없음·복수 archive, orphan START, active last writer 또는 archive 이동 실패가 있다 | manager가 checkpoint/filesystem/ledger를 재조정한다 | 유일한 valid completion만 exactly-once 완료되고 불명확 상태는 재시도 가능 오류가 되며 마지막 writer 뒤 `WORK_LOG` archive와 해당 attempt-log cleanup이 순서대로 수행된다 |
| S28 | `completion-ledger-reconciliation` | `11+10_unknown_isolation` task에 paired plan/review logs suffix 0~10과 active pair가 있고, task group에는 `work_log_0.log`~`work_log_2.log`가 있으며 다른 task들은 각자 다른 loop에서 병렬 실행된다. 1 완료 뒤 2·3, 2 완료 뒤 5·6이 해제되는 동안 same-pair retry/restart, WARN/FAIL follow-up, partial pair archive crash, task 소실, 새 completion archive 없음·복수 archive, orphan START, active last writer 또는 WORK_LOG archive 이동 실패가 있다 | manager가 checkpoint/filesystem/ledger, attempt별 pinned task/pair loop, 독립 timeline archive ordinal과 동적 dependency closure를 재조정한다 | 예시 task의 current-pair worker/selfcheck/review START·FINISH는 loop 11이고 same-pair retry는 attempt만 증가한다. WARN/FAIL review가 pair 11을 archive하고 follow-up을 만들어도 그 FINISH는 11이며 다음 START부터 12가 된다. 다른 task의 독립 loop도 같은 WORK_LOG에 기록된다. locator metadata에서 pinned loop와 context/session id를 조회하고 별도 context_id 컬럼은 없다. 유일한 valid task completion만 exactly-once 확정되고 lineage terminal closure와 last writer 뒤에만 task loop와 독립적인 `work_log_3.log` archive와 attempt-log cleanup이 수행된다. pair/count/checkpoint/locator/row identity나 timeline ordinal이 불명확하면 추정 renumber 없이 오류가 된다 |
| S29 | `selector-policy` | Node compatibility policy fixture에 KST 경계, G01~G10 worker, 공식 review route와 failover/selfcheck가 있고 일부 rule이 겹친다 | selection과 persisted route 저장 및 policy conformance를 실행한다 | 외부에는 우선 rule의 target 하나만 반환되며 내부 plan에는 ordered candidate/eligibility/rejection/rule/used history가 보존되고 공식 review는 worker quota route로 재평가되지 않으며 route/failover/selfcheck는 injected policy로 재현된다 |
| S30 | `quota-admission` | adapter/target/command-profile/required-cap 조합이 같거나 일부만 다른 후보와 local-first, resume, selfcheck, official review work가 여러 batch와 host restart를 지난다 | admission quota를 평가한다 | full probe identity가 같은 initial worker 조회만 재사용하고 다른 identity는 분리되며 local-first 뒤 cloud와 resume/selfcheck/review는 zero-probe이고 unknown의 1회 admission은 work-unit/candidate에 격리되어 batch/restart에도 초기화되지 않는다 |
| S31 | `agent-task-manager` | persisted state가 없거나 있는 여러 ready task에 initial/resume preview를 요청한다 | read-only preview를 반복한다 | 실행과 같은 route/dependency/blocker 결과를 반환하지만 state/filesystem/quota cache는 deep-equal이고 provider invocation은 0회이며 task 결과가 서로 오염되지 않는다 |
@ -189,7 +191,7 @@
| S01 | shared provider conformance test와 duplicate implementation search | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `provider-runtime` Roadmap Completion, Node/Desktop test output |
| S02 | deterministic scheduler integration test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `agent-task-manager` Roadmap Completion, no-supervisor execution trace |
| S03 | Node wire adapter와 Desktop host contract test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `host-boundary` Roadmap Completion, event mapping evidence |
| S04 | 영역별 Python/Node inventory, disposition-complete parity matrix, code search와 cutover verification | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `parity-cutover` Roadmap Completion, zero-unclassified matrix evidence links |
| S04 | 영역별 Python/Node inventory, disposition-complete parity matrix, code search, legacy archive byte-equality와 active legacy WORK_LOG cutover-block test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `parity-cutover` Roadmap Completion, zero-unclassified matrix·no-mixed-schema·legacy preservation evidence links |
| S05 | provider discovery table tests와 authenticated readiness smoke | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `provider-catalog` Roadmap Completion, discovery/error output |
| S06 | config merge/watcher/revision integration test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `config-ownership` Roadmap Completion, A/B revision trace |
| S07 | ordered selector rule matrix for Node/Desktop policies | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `selector-policy` Roadmap Completion, selected rule/reason output |
@ -213,7 +215,7 @@
| S25 | duplicate manager/lease, process identity, corrupt checkpoint, scheduler-exception/restart integration matrix | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `workspace-runtime-ownership` Roadmap Completion, single-owner와 no-duplicate evidence |
| S26 | task topology/dependency ambiguity, USER_REVIEW contract와 same-target/overlapping-write-set independent-branch drain test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `workflow-state-drain` Roadmap Completion, task-local blocker·no-write-set-barrier·follow-up once trace |
| S27 | cross-target/restart stage budget, explicit retry와 worker/review isolation test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `stage-failure-budget` Roadmap Completion, durable counter/reset evidence |
| S28 | checkpoint/filesystem/archive/ledger crash reconciliation and log cleanup ordering test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `completion-ledger-reconciliation` Roadmap Completion, exactly-once archive evidence |
| S28 | same-task paired plan/review archive 0~10→active loop 11→follow-up loop 12 fixture, START/FINISH loop pin, concurrent task별 독립 loop, group work_log 0~2→independent archive 3, 1→2·3→5·6 dynamic frontier, row/checkpoint/locator/pair-count identity, partial archive/restart/blocker/retry/crash와 cleanup ordering test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `completion-ledger-reconciliation` Roadmap Completion, per-attempt pair loop·same-pair retry stability·no-static-batch-split·exact independent `work_log_3.log`·exactly-once archive evidence |
| S29 | Node compatibility policy fixture와 external decision/persisted plan golden test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `selector-policy` Roadmap Completion, KST/G/review/failover/selfcheck와 route-plan evidence |
| S30 | full probe identity dedupe, initial-worker-only/zero-probe와 unknown-once restart test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `quota-admission` Roadmap Completion, probe/admission call ledger와 durable isolation evidence |
| S31 | initial/resume multi-task preview state/filesystem deep-equality와 invocation-zero test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `agent-task-manager` Roadmap Completion, preview result와 no-side-effect evidence |
@ -225,21 +227,22 @@
## Cross-repo Dependencies
- 없음. 같은 IOP monorepo 안에서 공통 package, Node host, Desktop host와 Flutter shell을 함께 관리한다.
- 구현 순서 선행 조건은 [Agent Task 동적 실행 Target Selector](../../../phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](../../../phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](../../../phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)의 활성 Milestone 결과다.
- 구현 순서 선행 조건은 [Agent Task 동적 실행 Target Selector](../../../archive/phase/automation-runtime-bridge/milestones/agent-task-runtime-target-selector.md), [Pi CLI Provider Integration](../../../phase/automation-runtime-bridge/milestones/pi-cli-provider-integration.md), [CLI Agent Group Grade Routing](../../../phase/automation-runtime-bridge/milestones/cli-agent-group-grade-routing.md)의 Milestone 결과다.
## Drift Check
- [x] Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- [x] Evidence Map이 code-review/complete.log에서 검증 가능하다.
- [x] agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- [x] 사용자 리뷰가 필요한 항목은 [USER_REVIEW.md](USER_REVIEW.md)에만 남겼다.
- [x] 기존 D01은 [범위 이관 기록](user_review_0.log)으로 남겼고 현재 구현 gate의 사용자 결정으로 사용하지 않는다.
## 사용자 리뷰 이력
- 없음
- [user_review_0.log](user_review_0.log) — 결합된 Desktop 범위를 후속 Flutter·Unity Milestone으로 분리하면서 D01을 현재 CLI gate에서 이관했다.
## 작업 컨텍스트
- 대체 상태: 결합된 runtime/Desktop 구현 입력으로는 사용하지 않는다. CLI 요구사항은 [IOP Agent CLI Runtime SDD](../iop-agent-cli-runtime/SDD.md)로 이관했고 Flutter·Unity lifecycle은 후속 Milestone에서 다시 작성한다.
- 표준선: `packages/go/agentruntime`이 provider와 AgentTaskManager의 유일한 구현이 되고, Node는 기존 runtime wire bridge, Desktop은 app lifecycle/registry/local IPC host가 된다. Desktop은 Flutter가 Go sidecar를 관리하는 topology를 기본안으로 삼는다.
- 표준선: app-owned YAML config tree가 provider/global 설정과 registry id별 project override를 모두 소유한다. map/scalar는 project override가 덮어쓰고 ordered selection rule array는 전체 교체한다. workspace-local runtime YAML은 권위가 아니다. 실행 중 agent는 immutable config revision으로 끝나며 다음 호출에만 새 revision을 적용한다.
- 표준선: project task/roadmap/work-log/log가 durable source of truth이고 app store는 provider/global config, registry와 최소 checkpoint만 소유한다. canonical workspace instance가 clone/worktree/branch 병렬성의 identity 경계다.
@ -253,5 +256,5 @@
- 표준선: Python의 active pair, contract-valid USER_REVIEW, local selfcheck checklist, exact verdict/fingerprint, no-progress와 archive 판정을 fixture로 가져오되 Pi에만 적용되던 CODE_REVIEW 정규식 완료 gate, non-empty checkbox 판정과 다른 provider의 사전 gate 부재는 gap evidence다. Go workflow adapter는 provider/model/local-cloud/one-shot-persistent 구분 없이 동일한 versioned 정규식/구조 matcher gate를 적용하고 semantic review는 official review role에 남긴다. plan write-set은 dispatch barrier가 아니라 review progress fingerprint 입력이고 runtime WORK_LOG/heartbeat-only 변화는 progress가 아니다. exact repeated normalized output과 silence inspection은 observation-only이며 terminal evidence를 대신하지 않는다.
- 표준선: Pi 작업·검증·selfcheck 완료 뒤 CODE_REVIEW가 비어 있어도 직전 성공 selfcheck context에 짧은 영문 지시를 주면 파일을 완성하는 관측을 필수 behavior fixture로 둔다. matcher는 provider-neutral하게 유지하고 보완 동작만 Pi profile의 same-context policy로 선언한다. 현재 Python처럼 incomplete 반복마다 새 selfcheck session을 만드는 동작은 흡수하지 않는다.
- 표준선: Python의 non-blocking lock, temporary replace, PID/start token/attempt marker와 archive baseline은 각각 workspace lease, atomic versioned checkpoint, live execution identity와 completion reconciliation의 behavior fixture다. Linux/Python 구현 세부를 공통 계약으로 복사하지 않는다.
- 표준선: stage failure budget은 work-unit/stage scope를 유지하고 자동 target 전환·restart에서는 보존한다. 명시적 identity-matched `retry_blocked`만 blocker와 해당 stage budget을 초기화하고 route/history는 유지한다. `WORK_LOG`는 runtime-owned timeline이며 worker/reviewer의 완료 주장을 manager ledger 대신 신뢰하지 않는다.
- 표준선: stage failure budget은 work-unit/stage scope를 유지하고 자동 target 전환·restart에서는 보존한다. 명시적 identity-matched `retry_blocked`만 blocker와 해당 stage budget을 초기화하고 route/history는 유지한다. `WORK_LOG`는 runtime-owned timeline이며 worker/reviewer의 완료 주장을 manager ledger 대신 신뢰하지 않는다. 각 attempt의 loop는 task별 active PLAN/CODE_REVIEW pair archive 회차로 START부터 FINISH까지 고정되고 같은 pair retry에서도 유지되며 follow-up pair의 다음 attempt에서만 증가한다. task-group `work_log_N.log` archive 회차는 전체 월별 suffix에서 별도로 고정하고 locator metadata가 pinned loop와 context/session id의 권위 위치다.
- 후속 SDD: 완성형 Flutter 설정 UI, Windows/Linux package, 외부 알림/dashboard 또는 remote control을 별도 Milestone으로 올릴 때 작성한다.

View file

@ -1,8 +1,8 @@
# SDD User Review
# SDD User Review Log
## 상태
요청됨
범위 이관
## 검토 대상
@ -25,17 +25,17 @@
- SDD: `State Machine`, `Interface Contract`, `Acceptance Scenarios S11/S18`, `작업 컨텍스트`
- Milestone: `구현 잠금`, `flutter-shell`, `desktop-host`
## 승인 항목
## 처리 항목
- [ ] D01 추천안을 승인하거나 수정 사항을 기록했다.
- [ ] SDD 잠금 해제를 승인했다.
- [x] D01은 현재 IOP Agent CLI 범위의 결정 항목에서 제거했다.
- [x] 결합된 Desktop SDD를 `[대체됨]`으로 전환하고 현재 사용자 리뷰 gate를 종료했다.
## 답변 기록
- 없음
- 2026-07-27: 사용자는 현재 Milestone을 `iop-agent` CLI까지만 구현하고 Flutter 설정 UI와 Unity Character를 후속 Milestone으로 분리하기로 결정했다.
- D01의 lifecycle 선택 자체는 확정하지 않았으며 후속 Flutter Desktop Milestone을 작성할 때 다시 검토한다.
## 해결 조건
## 처리 결과
- D01의 승인 또는 수정 사항이 SDD와 Milestone에 반영되어 있다.
- [USER_REVIEW.md](USER_REVIEW.md)가 `user_review_N.log`로 이동되어 있다.
- 남은 잠금 항목이 없으면 SDD 상태가 `[승인됨]`이고 `SDD 잠금` 상태가 `해제`다.
- 이 기록은 D01 추천안 승인 기록이 아니라 현재 범위에서의 이관 근거다.
- 현재 IOP Agent CLI Milestone에는 사용자 결정 항목이 남아 있지 않다.