From 09678de615c0843c7853f50531410fe75a6299c2 Mon Sep 17 00:00:00 2001 From: toki Date: Sun, 26 Jul 2026 21:23:55 +0900 Subject: [PATCH] docs: update SDD and milestone for shared-agent-task-runtime-desktop-agent --- ...shared-agent-task-runtime-desktop-agent.md | 17 ++++++--- .../SDD.md | 37 +++++++++++++------ 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/agent-roadmap/phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md b/agent-roadmap/phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md index 23bccd2..8db56c7 100644 --- a/agent-roadmap/phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md +++ b/agent-roadmap/phase/automation-runtime-bridge/milestones/shared-agent-task-runtime-desktop-agent.md @@ -46,11 +46,14 @@ - app-owned YAML config tree가 provider catalog, 기본 정책과 명시 등록 project별 custom override를 모두 소유한다. workspace 안의 YAML은 runtime 설정 권위가 아니며, project override는 app registry id 아래에서 scalar/map을 key 기준으로 덮어쓰고 순서가 의미인 selection rule array는 전체 교체한다. - 선택 엔진은 기본 provider와 조건부 rule array를 평가해 정확히 하나의 provider/model을 반환한다. 시간, quota/token 잔량, agent/stage/lane/grade, capability, 알려진 실패 상태를 조건으로 사용할 수 있고 겹치는 조건은 선언 순서가 우선한다. Node와 Desktop은 공통 evaluator를 사용하되 서로 다른 정책 문서를 주입할 수 있다. - config file watcher가 revision을 검증하며, 실행 중인 agent는 시작 시점 snapshot으로 끝까지 수행한다. 유효한 변경은 다음 agent 호출부터 적용하고 잘못된 변경은 명시적 config error로 표면화하며 영향을 받는 새 dispatch를 중단한다. -- quota/usage는 현재 Go usage checker와 Python의 검증된 해석을 기준으로 `available | exhausted | unknown | not_applicable`과 관측 근거를 제공한다. 같은 provider credential/profile의 quota는 app 전체 project가 공유하고 동일 admission batch는 같은 snapshot을 재사용한다. 조회 오류는 해당 provider key에서 `unknown`으로 격리해 다른 provider/project key로 확산시키지 않는다. +- quota/usage는 현재 Go usage checker와 Python의 검증된 해석을 기준으로 `available | exhausted | unknown | not_applicable`과 관측 근거를 제공한다. 같은 provider credential/profile의 quota는 app 전체 project가 공유하고 동일 admission batch는 같은 immutable snapshot을 재사용한다. 조회 오류는 해당 provider key에서 `unknown`으로 격리해 다른 provider/project key로 확산시키지 않는다. - 앱은 workspace의 소유자가 아니라 관리 주체다. 프로젝트는 명시 등록하며 app-owned provider/global 설정과 project override를 관리하고, `agent-task`, `agent-roadmap`, `priority-queue.md`, `WORK_LOG.md`와 project-local log가 작업 상태의 source of truth가 된다. - 자동 실행은 기본 on이며 사용자가 언제든 중단할 수 있다. 등록 프로젝트의 기존 agent-ops 작업 상태에 남은 agent-task가 있으면 먼저 이어서 처리하고, 없으면 기존 agent-roadmap/priority-queue.md의 최상위 ready Milestone을 선택해 project-owned plan/review/완료 지시를 순차 실행한다. 일반 사용자 요청에서 새 Milestone/Plan을 분류·생성하는 진입 동작은 수행하지 않는다. - 서로 다른 등록 project/workspace instance는 병렬 실행할 수 있다. 같은 저장소를 clone/worktree/branch로 여러 경로에 둔 경우도 canonical workspace instance를 분리해 동시에 관리하며, 한 instance 안에서는 dependency와 work-unit route pin을 따른다. -- 현재 Python에서 검증된 raw/normalized stream, heartbeat, PID/process-group, session locator, silence inspection, cancellation, route pin, logical context transfer, failure budget, dependency drain, review-control 위반 감지와 알려진 provider 오류 예외를 공통 runtime 동등성 matrix에 흡수한다. +- Gemini를 실행하는 Agy adapter를 포함한 각 provider codec은 raw stream/status에서 provider별 강한 quota evidence를 판정해 normalized failure를 내보낸다. AgentTaskManager는 provider 문자열을 다시 해석하지 않고 이 typed result만 작업 전이 입력으로 사용하며 generic·불완전 evidence는 unknown/generic 오류로 표면화한다. +- 실행 중 provider-confirmed quota exhaustion은 admission snapshot을 복제·변조하지 않고 base snapshot을 참조하는 별도 runtime quota observation으로 기록한다. 현재 work unit은 이 observation을 즉시 사용하고 app quota service는 같은 credential/profile key를 무효화·갱신해 후속 admission에 반영하되, 이미 admission된 sibling route는 바꾸지 않는다. +- AgentTaskManager는 같은 work-unit id, persisted candidate 순서와 사용 이력을 보존해 다음 unused eligible target으로 failover하고 session locator와 logical context를 이전한다. 대체 target이 없으면 해당 work unit만 typed blocker로 두며, 사용자 재시도 또는 auto-run policy가 허용한 quota 상태 갱신에서도 새 initial route를 계산하지 않고 persisted route 안에서만 복구한다. +- 현재 Python에서 검증된 raw/normalized stream, heartbeat, PID/process-group, session locator, silence inspection, cancellation, route pin, logical context transfer, failure budget, dependency drain, review-control 위반 감지와 알려진 provider 오류 예외를 공통 runtime 동등성 matrix에 흡수한다. Python의 함수명·marker·state key는 계약으로 복사하지 않고 관측된 상태 전이와 불변 조건만 Go 타입·테스트로 옮긴다. - 오류는 모두 runtime event와 project log에 표면화한다. 알려진 오류만 선언된 policy에 따라 retry/failover하고, unknown 오류는 추정 복구하지 않고 해당 work unit을 명시적으로 중단한다. - 프로젝트별 최소 관측 로그는 각 프로젝트의 `agent-log` 계열 경로에 보존하고 현재 수준보다 축소하지 않는다. provider/model 선택, quota snapshot, config revision, process/session locator, stream/heartbeat, failure evidence, retry/failover, stop/completion을 동일 execution identity로 추적한다. - Desktop Agent는 Go runtime host, YAML 운영 entry, app-owned registry/state와 Flutter macOS shell을 포함한다. UI 설정 화면은 scaffold만 두지만 설치 산출물에는 runtime binary, 기본 YAML과 Flutter macOS app wrapper가 함께 있어야 한다. @@ -76,7 +79,8 @@ Node와 Desktop Agent가 하나의 실행 구현을 공유하고 각 제품에 - [ ] [provider-catalog] YAML 선언과 read-only discovery가 binary, version, authenticated readiness, model/profile capability를 공통 provider catalog로 정규화하고 공식 계열 이름과 내부 identity를 매핑한다. 검증: 누락·미인증·미지원 model/profile은 추정 fallback 없이 명시 오류가 된다. - [ ] [config-ownership] app-owned YAML 안의 기본값과 project registry별 override, file watcher, revision snapshot과 next-invocation 적용 규칙을 구현한다. 검증: 실행 중 변경은 현재 agent에 영향을 주지 않고 다음 호출부터 적용되며 invalid revision은 새 dispatch를 config error로 중단한다. - [ ] [selector-policy] 공통 selector가 default와 ordered conditional rules를 평가해 정확히 하나의 provider/model을 반환하고 Node/Desktop별 정책 차이를 허용한다. 검증: 겹친 조건은 array 순서가 우선하며 결과와 reason/config revision이 audit log에 남는다. -- [ ] [quota-admission] 기존 Go usage checker와 검증된 Python 해석을 공통 quota/status 입력으로 흡수하고 app-global 공유 quota, batch snapshot, unknown 격리와 알려진 quota 오류 기반 failover를 제공한다. 검증: 같은 provider credential/profile을 쓰는 project가 동일 quota 상태를 공유하고 parser 오류가 다른 provider key를 차단하지 않으며 generic stderr만으로 quota exhausted를 추정하지 않는다. +- [ ] [quota-admission] 기존 Go usage checker와 검증된 Python 해석을 공통 quota/status 입력으로 흡수하고 app-global 공유 quota, immutable admission batch snapshot과 unknown 격리를 제공한다. 검증: 같은 provider credential/profile을 쓰는 project가 동일 quota 상태를 공유하고 parser 오류가 다른 provider key를 차단하지 않으며 generic stderr만으로 quota exhausted를 추정하지 않는다. +- [ ] [runtime-quota-failover] provider adapter의 confirmed quota failure를 base admission snapshot과 분리된 runtime observation으로 받아 같은 persisted candidate 순서·사용 이력의 다음 unused eligible target으로 failover한다. 검증: Gemini/Agy positive·negative fixture, locator/context와 work-unit 보존, app-global key 갱신, 원본 batch·in-flight sibling 불변 및 alternate 부재 시 task-local blocker를 확인한다. ### Epic: [execution-lifecycle] 프로젝트 실행과 복구 Lifecycle @@ -86,14 +90,15 @@ Node와 Desktop Agent가 하나의 실행 구현을 공유하고 각 제품에 - [ ] [task-order] 자동 실행이 등록 project의 기존 agent-ops 작업 상태에서 남은 agent-task를 우선하고 없으면 기존 priority-queue.md의 최상위 ready Milestone부터 project-owned plan/review/완료 지시를 수행한다. 검증: task 잔여·빈 task·blocked dependency·사용자 stop matrix에서 선택과 종료가 일관되고 일반 요청에서 새 작업 파일을 생성하지 않는다. - [ ] [concurrency-stop] 서로 다른 workspace instance는 병렬로 실행하고 같은 instance는 dependency/route pin을 지키며, 사용자 stop은 process group과 session을 취소해 후속 자동 호출을 막는다. 검증: 병렬 project, 동일 repo clone, graceful stop과 강제 종료 smoke가 중복 실행을 남기지 않는다. - [ ] [session-recovery] config revision, work-unit route, process/session locator, logical context와 failure budget을 보존해 crash/restart 뒤 현재 filesystem 상태에서 재개한다. 검증: native resume 가능 provider와 logical transfer provider가 각각 중복 실행 없이 현재 stage를 복원한다. +- [ ] [blocked-failover-recovery] typed blocker와 persisted decision identity가 일치할 때만 복구 intent를 만들고 사용자 재시도 또는 policy-authorized status refresh에서 기존 route의 unused alternate와 현재 blocked target에 허용된 same-target retry만 재평가한다. 검증: 현재 시각 정책으로 새 candidate를 만들거나 이미 떠난 target으로 bounce하지 않고 ordinary resume·sibling은 불변이며, 준비 또는 commit 실패에는 기존 decision/history/intent가 보존되고 성공 commit 뒤 intent가 한 번만 소비되어 저장 locator로 이어진다. ### Epic: [failure-observe] 오류·관측·로그 동등성 모델 감시 없이도 현재 Python dispatcher가 제공하는 최소 운영 가시성과 예외 처리를 runtime으로 흡수한다. - [ ] [stream-observer] stdout/stderr 분리, raw/normalized stream, heartbeat, silence inspection, PID/start token/process group, session locator와 completion 단일화를 공통 runtime event로 제공한다. 검증: fake emitter와 실제 CLI smoke에서 delta 순서, 단일 terminal, 취소와 orphan 부재를 확인한다. -- [ ] [failure-taxonomy] context limit, provider quota, model unavailable, connection/stream disconnect, generic error, process termination, review-control violation과 known provider-specific evidence를 typed failure로 정규화한다. 검증: 현재 Python fixture/관측 사례와 Go provider fixture가 동일 class와 evidence source를 반환한다. -- [ ] [project-logs] provider/model decision, quota snapshot, config revision, process/session, stream/heartbeat, retry/failover, 오류 evidence와 completion을 project `agent-log`에서 execution/work-unit identity로 추적한다. 검증: 현재 최소 관측 필드가 누락되지 않고 secret/raw credential이 기록되지 않는다. +- [ ] [failure-taxonomy] provider codec이 context limit, provider quota, model unavailable, connection/stream disconnect, generic error와 process termination을 provider별 fixture로 typed failure에 정규화하고 AgentTaskManager가 review-control violation 및 work-unit blocker와 결합한다. 검증: Gemini/Agy의 structured quota/429/rate-limit positive fixture와 generic·불완전·target 불일치 negative fixture가 올바른 class/source를 반환하며 manager가 raw 문자열을 재분류하지 않는다. +- [ ] [project-logs] provider/model decision, admission snapshot id, runtime quota observation id, app-global quota refresh, config revision, process/session locator, typed blocker, recovery/failover transition과 completion을 project `agent-log`에서 execution/work-unit identity로 추적한다. 검증: provider failure와 manager transition의 연결 근거가 누락되지 않고 secret/raw credential이 기록되지 않는다. - [ ] [surface-errors] invalid config/provider/auth/model/capability와 unknown runtime 오류를 Desktop event/UI scaffold 및 Node event에 모두 표면화하고 unknown은 자동 추정 복구하지 않는다. 검증: 오류 matrix가 silent fallback이나 무한 retry 없이 terminal 상태와 로그를 남긴다. ### Epic: [desktop-delivery] Desktop Agent와 실제 환경 검증 @@ -113,6 +118,7 @@ Edge 없이 실행되는 macOS 제품 껍데기와 설치·운영 기준을 제 - 검토 항목: - [ ] 모든 기능 Task와 Task 안의 검증이 충족되었다. - [ ] 동등성 matrix에 Python 참조, Node 기존 동작, 선행 selector/provider/routing Milestone 결과가 반영되었다. + - [ ] runtime Gemini quota failover와 blocker 복구가 provider/manager 책임 분리, admission snapshot 불변성, app-global 후속 갱신, persisted route, locator/context 및 exactly-once intent 소비까지 검증되었다. - [ ] Node와 Desktop이 동일 provider/runtime conformance suite를 통과하고 중복 provider 구현이 없다. - [ ] 실제 로그인된 macOS smoke와 project-local log evidence가 남아 있다. - agent-ui 상태 반영: 해당 없음 @@ -136,6 +142,7 @@ 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에서 구현한다. +- 표준선(선택): 구현 계획 직전에 [Agent Task 동적 실행 Target Selector](agent-task-runtime-target-selector.md)의 최종 PASS·`complete.log` evidence를 다시 freeze한다. 미종결 active plan/review는 결함·검증 후보로만 참고하고 Python 내부 함수명이나 persisted key 자체를 Go parity 요구로 승격하지 않는다. - 표준선(선택): app config는 provider/global/project override의 운영 소유권을 가지고, project filesystem은 작업 상태의 source of truth다. workspace 안의 runtime config를 권위로 사용하거나 app store가 `agent-task`/roadmap 원문을 중앙 복제하지 않는다. - 표준선(선택): Desktop은 Flutter가 관리하는 local Go sidecar process를 기본 topology로 삼고, Node는 동일 library를 in-process로 사용한다. 정확한 IPC와 lifecycle 계약은 SDD 잠금에서 고정한다. - 표준선(선택): 설정 merge는 app-owned defaults 뒤 app registry의 project override를 적용하며 ordered rule array는 전체 교체한다. 현재 실행은 immutable revision을 사용하고 hot reload는 다음 agent invocation 경계에서만 활성화한다. diff --git a/agent-roadmap/sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md b/agent-roadmap/sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md index 829bbe0..621856b 100644 --- a/agent-roadmap/sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md +++ b/agent-roadmap/sdd/automation-runtime-bridge/shared-agent-task-runtime-desktop-agent/SDD.md @@ -35,7 +35,7 @@ | 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의 우선 기준 | | Project Workflow | 등록 workspace의 `agent-ops/rules/project`, `agent-ops/skills/project`, Milestone·Plan·Code Review 파일 | workflow skill/rule과 작업 파일 의미는 project가 소유하고 runtime은 이미 선택된 work step을 실행한다 | | 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`, active `agent-task/**/WORK_LOG.md` | Python은 동작·오류·관측 evidence일 뿐 production dependency가 아니다 | +| 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는 결함 후보로만 사용하고 공통 계약으로 승격하지 않는다 | | Code | `packages/go/agentruntime`, `apps/node`, `apps/desktop-agent`, `apps/desktop-agent-ui`, `packages/go/config` | 단일 runtime 구현과 host integration의 구현 source of truth 후보 | | Existing Contract | [Edge-Node Runtime Wire](../../../../agent-contract/inner/edge-node-runtime-wire.md), [Edge Config Runtime Refresh](../../../../agent-contract/inner/edge-config-runtime-refresh.md) | Node bridge가 보존해야 할 현재 wire/config 의미. 변경이 필요하면 구현 전 agent-contract를 갱신한다 | | Project State | 각 등록 workspace의 `agent-task`, `agent-roadmap`, `WORK_LOG.md`, `agent-log` | 작업 원문·진행·evidence의 durable source of truth | @@ -54,12 +54,14 @@ | `config-pending` | agent 실행 중 새 유효 config revision이 관측됐다 | `running` 후 `work-ready` 또는 `idle` | 현재 execution은 기존 snapshot을 유지하고 다음 호출에 새 revision 적용 | | `work-ready` | 기존 agent-task 또는 기존 priority-queue의 최상위 ready Milestone이 있다 | `selecting` 또는 `stopped` | project filesystem scan. 일반 요청으로 새 work item을 합성하지 않는다 | | `selecting` | stage/work-unit/config revision/quota snapshot으로 ordered rules를 평가한다 | `running` 또는 `selection-error` | 하나의 provider/model route decision | -| `running` | provider process가 immutable route/config snapshot으로 시작됐다 | `running`, `retrying`, `failing-over`, `completed`, `failed` 또는 `cancelling` | runtime stream, heartbeat, process/session locator | -| `retrying` | 알려진 동일-target 복구 가능 오류와 failure budget이 남았다 | `running` 또는 `failed` | typed failure와 transition history | -| `failing-over` | 선언 정책이 허용하는 quota/context/model/stream 오류가 확인됐다 | `running` 또는 `failed` | logical context package와 route transition | +| `running` | provider process가 immutable route/config snapshot으로 시작됐다 | `running`, `retrying`, `failing-over`, `completed`, `blocked`, `failed` 또는 `cancelling` | runtime stream, heartbeat, process/session locator와 provider adapter의 normalized failure | +| `retrying` | 알려진 동일-target 복구 가능 오류와 failure budget이 남았다 | `running`, `blocked` 또는 `failed` | typed failure와 transition history | +| `failing-over` | provider adapter가 quota/context/model/stream failure를 확정해 failover 평가가 필요하다. quota이면 base admission snapshot을 참조하는 별도 runtime observation을 생성하고 app-global key 갱신을 요청한다 | route/context commit 뒤 `running`, alternate 부재 또는 준비·commit 오류 시 기존 route를 보존한 `blocked` | 같은 work-unit/candidate order/used history, runtime observation, locator와 logical context package | | `cancelling` | 사용자가 project/app 자동 실행을 중단했다 | `stopped` 또는 `failed` | cancel event, process group/session termination evidence | | `completed` | 현재 stage가 성공하고 work log/filesystem이 반영됐다 | `work-ready` 또는 `idle` | terminal event와 project evidence | -| `failed` | unknown 오류, invalid provider/config, eligible target 부재 또는 failure budget 소진이 발생했다 | `idle`, 독립 project의 `work-ready`, 또는 사용자 수정 뒤 `config-validating` | surfaced error와 project log | +| `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 identity가 현재 persisted state와 일치한다 | persisted route 안의 recovery commit 뒤 `running`, 재입장 불가 시 `blocked`, 준비·commit 오류 시 오류를 표면화하고 기존 상태를 보존한 `recovery-pending` | recovery intent, fresh provider status와 exactly-once commit evidence | +| `failed` | unknown/unrecoverable 오류, invalid provider/config 또는 전이 준비·commit 오류가 발생했다 | `idle`, 독립 project의 `work-ready`, 또는 사용자 수정 뒤 `config-validating` | surfaced error와 project log. 기존 route/history/recovery intent는 손상하지 않는다 | | `stopped` | auto-run off, project stop 또는 D01에서 정의한 app 종료가 완료됐다 | `config-validating` 또는 `project-watching` | 명시 재시작/enable event | ## Interface Contract @@ -71,12 +73,15 @@ - `WorkRequest`: project/workspace identity, project workflow가 이미 선택한 task 또는 Milestone path, stage/work-unit identity, dependency state와 optional persisted route다. 일반 사용자 요청이나 direct/Plan/Milestone 분류 입력이 아니다. - `ProviderProfile`: stable provider/profile id, executable/args/env reference, renderer/emitter/session/status capability와 approval bypass mapping이다. - `SelectionPolicy`: default provider/model과 ordered conditional rule array다. app registry의 project override를 적용한 뒤 평가하며 첫 일치 rule이 승리한다. - - `QuotaSnapshot`: provider credential/profile별 app-global `available | exhausted | unknown | not_applicable`, cap/remaining/reason/snapshot id/checked-at이다. 같은 key를 쓰는 모든 project가 공유한다. + - `QuotaSnapshot`: provider credential/profile별 app-global `available | exhausted | unknown | not_applicable`, cap/remaining/reason/snapshot id/checked-at이다. 같은 key를 쓰는 모든 project가 admission에서 공유하며 batch 동안 immutable하다. - `ConfigRevision`: 현재 execution이 고정한 immutable revision이다. watcher의 새 revision은 다음 agent invocation 전에만 교체한다. - 출력: - `RouteDecision`: 정확히 하나의 provider/profile/model, reason, matched rule index, quota snapshot, config revision과 evaluated-at이다. - `RuntimeEvent`: start, stdout/stderr delta, normalized delta, heartbeat, session/process locator, retry/failover, complete, error, cancelled다. - - `FailureEvidence`: typed class, source, provider-confirmed 여부, bounded evidence, signal과 retry/failover eligibility다. + - `ProviderFailure`: provider/profile, typed class, provider-confirmed 여부, source, bounded evidence, signal과 observed-at이다. provider codec이 생성하며 work-unit role이나 route 결정을 포함하지 않는다. + - `RuntimeQuotaObservation`: observation id, credential/profile key, target, status, base admission snapshot id, provider failure reference와 observed-at이다. app quota service의 후속 admission 갱신과 현재 work-unit failover가 같은 관측을 참조한다. + - `WorkUnitBlocker`: work-unit/stage, persisted route decision id, selected target, locator와 provider failure 또는 runtime observation reference다. AgentTaskManager가 생성한다. + - `RecoveryIntent`: blocker/route/work-unit identity, trigger, persisted candidate order/used history와 commit 상태다. 성공한 route/context commit 뒤 한 번만 소비한다. - `ProjectLogRecord`: execution/work-unit/project identity로 route, 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 주 식별자가 아니다. - 금지: @@ -87,6 +92,10 @@ - Python process, Python module 또는 monitoring skill 호출을 runtime correctness에 사용하지 않는다. - invalid config/provider/auth/model/capability 또는 unknown 오류를 silent fallback으로 숨기지 않는다. - generic stderr만으로 provider quota/context/model failure를 확정하지 않는다. + - AgentTaskManager가 provider raw stderr를 재파싱하거나 provider adapter의 unknown/generic result를 quota failure로 승격하지 않는다. + - runtime quota observation을 기존 snapshot id의 수정본으로 저장하거나 immutable admission batch 및 이미 실행 중인 sibling route를 변경하지 않는다. + - blocker 복구에서 현재 시간 기준 selection policy로 새 candidate를 만들거나 이미 떠난 target으로 bounce하거나 ordinary resume·sibling을 probe하지 않는다. + - route/context commit 성공 전에 recovery intent를 소비하거나 기존 decision/history를 덮어쓰지 않는다. - 실행 중 config revision이나 시간 경계만으로 현재 work unit의 pinned route를 바꾸지 않는다. - credential/token/raw secret을 app discovery result나 project log에 기록하지 않는다. - app store에 project의 roadmap/task/work-log 원문을 중앙 복제해 별도 source of truth를 만들지 않는다. @@ -108,14 +117,16 @@ | S11 | `concurrency-stop` | 여러 project가 병렬 실행 중이다 | 한 project를 사용자가 중단한다 | 해당 process group/session과 후속 auto-call만 멈추고 다른 project는 계속된다 | | S12 | `session-recovery` | provider process 또는 Desktop host가 실행 중 비정상 종료됐다 | host를 재시작한다 | filesystem/checkpoint/locator로 현재 stage를 복원하고 native resume 또는 logical transfer를 한 번만 수행한다 | | S13 | `stream-observer` | provider가 stdout/stderr, delta, heartbeat 공백과 terminal을 발생시킨다 | common runtime이 관측한다 | raw/normalized 순서, heartbeat/inspection, process/session locator와 정확히 한 terminal event가 남는다 | -| S14 | `failure-taxonomy` | Python 관측 fixture와 Go provider fixture가 각 known failure를 재현한다 | failure classifier를 실행한다 | context/quota/model/connection/stream/generic/process/review-control class와 evidence source가 일치한다 | -| S15 | `project-logs` | 실행이 select, run, retry/failover와 terminal 단계를 거친다 | project log를 조회한다 | 최소 관측 필드가 하나의 execution/work-unit identity로 연결되고 secret은 없다 | +| S14 | `failure-taxonomy` | Python 관측 fixture를 Go provider codec fixture로 옮겼고 manager에는 normalized result가 입력된다 | provider classifier와 manager transition을 실행한다 | codec은 context/quota/model/connection/stream/generic/process class를 반환하고 manager는 raw 문자열 재해석 없이 review-control/work-unit blocker를 결합한다 | +| S15 | `project-logs` | 실행이 select, run, runtime quota observation, app-global refresh, recovery/failover와 terminal 단계를 거친다 | project log를 조회한다 | admission snapshot·runtime observation·provider failure·manager transition이 하나의 execution/work-unit identity로 연결되고 secret은 없다 | | S16 | `surface-errors` | invalid config/provider/auth/model/capability 또는 unknown 오류가 발생한다 | Node와 Desktop에서 실행한다 | 양쪽 surface와 project log에 오류가 보이고 unknown은 silent retry/fallback하지 않는다 | | S17 | `desktop-host` | 둘 이상의 project가 Desktop registry에 명시 등록됐다 | Edge와 Python 없이 app을 시작·중단·재시작한다 | common AgentTaskManager가 각 project lifecycle을 관리하고 자동 실행 toggle을 지킨다 | | S18 | `flutter-shell` | clean macOS 사용자 환경에 app bundle이 있다 | 설치·실행·창 닫기·명시 Quit·login-start 설정을 확인한다 | Flutter shell과 Go runtime이 D01의 background lifecycle을 지키고 명시 Quit 뒤 orphan process가 없다 | | S19 | `yaml-operations` | UI 편집 화면 없이 app-owned provider/global/project override 설정을 운영한다 | discovery 기반 생성, validation, reload와 조회를 수행한다 | 같은 config service/schema가 roundtrip되고 향후 Flutter UI가 재사용 가능한 scaffold가 있다 | | S20 | `logged-in-smoke` | 실제 로그인된 지원 CLI와 macOS app bundle이 준비됐다 | discovery, run, stream, quota/status, cancel, config-next-call smoke를 실행한다 | provider/model/environment/result/evidence 경로가 smoke manifest와 project log에 남는다 | | S21 | `workflow-ownership-boundary` | 등록 project에 기존 agent-ops work item은 없고 일반 코딩 요청만 있다 | AgentTaskManager auto-run이 작업을 탐색한다 | no-work/idle로 남고 Milestone/Plan을 분류·생성하지 않으며 별도 오케스트레이션이 WorkRequest를 제공해야 한다 | +| S22 | `runtime-quota-failover` | admission에서 available이던 Gemini target에 Agy codec이 confirmed quota failure를 반환했고 persisted route에 unused eligible alternate가 있거나 없다 | quota service와 AgentTaskManager가 normalized failure를 소비한다 | immutable base snapshot과 in-flight sibling은 유지되고 별도 runtime observation이 app-global key의 후속 admission 갱신과 현재 work unit에 연결되며, alternate가 있으면 같은 route/history와 locator/context로 전환하고 없으면 task-local blocker가 된다 | +| S23 | `blocked-failover-recovery` | 알려진 provider failure로 막힌 work unit에 사용자 재시도 또는 policy-authorized status refresh가 발생했다 | AgentTaskManager가 blocker와 persisted decision identity를 검증한다 | 새 initial route 없이 unused alternate와 현재 blocked target에 허용된 same-target retry만 평가하고 성공 commit 뒤 intent를 한 번 소비한다. identity mismatch나 status/route/context/commit 실패에는 기존 decision/history/intent가 유지된다 | ## Evidence Map @@ -134,14 +145,16 @@ | S11 | concurrent project cancellation and orphan-process test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `concurrency-stop` Roadmap Completion, unaffected project trace | | S12 | crash/restart native-resume and logical-transfer test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `session-recovery` Roadmap Completion, single-resume evidence | | S13 | fake emitter tests plus actual CLI stream/cancel smoke | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `stream-observer` Roadmap Completion, ordered events/single terminal evidence | -| S14 | Python reference fixture inventory and Go typed failure tests | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `failure-taxonomy` Roadmap Completion, parity table | -| S15 | project-log schema/golden test and secret scan | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `project-logs` Roadmap Completion, trace and redaction evidence | +| S14 | provider codec conformance fixture와 manager no-raw-reparse test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `failure-taxonomy` Roadmap Completion, provider/manager responsibility table | +| S15 | snapshot/observation/failure/transition log schema golden test와 secret scan | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `project-logs` Roadmap Completion, linked trace and redaction evidence | | S16 | Node/Desktop error matrix integration test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `surface-errors` Roadmap Completion, surfaced terminal/log evidence | | S17 | Desktop multi-project lifecycle integration test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `desktop-host` Roadmap Completion, Edge/Python absence evidence | | S18 | macOS app bundle install/window-close/quit/login-start smoke | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `flutter-shell` Roadmap Completion, bundle contents, lifecycle와 orphan check | | S19 | YAML/discovery roundtrip and config service test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `yaml-operations` Roadmap Completion, schema/reload evidence | | S20 | actual logged-in macOS field-smoke manifest | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `logged-in-smoke` Roadmap Completion, environment/result/evidence manifest | | S21 | workflow ownership contract test와 common package dependency scan | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `workflow-ownership-boundary` Roadmap Completion, no-work/no-artifact trace | +| S22 | Agy quota positive/negative codec fixture, runtime observation/app-global refresh와 alternate/no-alternate integration test | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `runtime-quota-failover` Roadmap Completion, provider/manager boundary와 batch/sibling isolation evidence | +| S23 | manual/auto trigger, identity, persisted-route boundary, status/context/commit failure와 exactly-once continuation matrix | `agent-task/m-shared-agent-task-runtime-desktop-agent/...` | `blocked-failover-recovery` Roadmap Completion, decision/history/intent와 saved-locator evidence | ## Cross-repo Dependencies @@ -164,7 +177,7 @@ - 표준선: `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 경계다. -- 표준선: 동등성 inventory는 구현 계획 직전에 active Milestone과 work log를 다시 읽어 freeze한다. Python behavior는 test fixture/evidence로 변환하되 production dependency로 남기지 않는다. +- 표준선: 동등성 inventory는 구현 계획 직전에 active Milestone, 최종 PASS·`complete.log`와 work log를 다시 읽어 freeze한다. 미종결 active plan/review는 gap evidence로만 사용하고 Python의 function/marker/state key는 복제하지 않는다. Python behavior는 provider fixture와 AgentTaskManager 상태 전이 테스트로 변환하되 production dependency로 남기지 않는다. - 표준선: 실제 로그인 smoke는 fake/unit test를 대체하지 않고 release acceptance evidence로 추가한다. 인증 정보는 기록하지 않는다. Desktop은 official provider/model/profile naming만 사용자 표면에 사용한다. - 표준선: 등록 project의 agent-ops가 Milestone·Plan·Code Review skill/rule과 작업 파일 의미를 소유하고, 공통 runtime은 이미 선택된 work step의 scheduling/provider execution만 소유한다. 일반 요청 분류와 IOP 소유 skill/tool-call 생성은 별도 [에이전트 작업 루프 오케스트레이션 MVP](../../../phase/automation-runtime-bridge/milestones/agent-workflow-loop-orchestration-mvp.md)가 이 runtime을 소비해 수행한다. - 후속 SDD: 완성형 Flutter 설정 UI, Windows/Linux package, 외부 알림/dashboard 또는 remote control을 별도 Milestone으로 올릴 때 작성한다.