iop/agent-roadmap/sdd/automation-runtime-bridge/agent-task-runtime-target-selector/SDD.md

17 KiB

SDD: Agent Task 동적 실행 Target Selector

위치

상태

[승인됨]

SDD 잠금

  • 상태: 해제
  • 사용자 리뷰: 없음
  • 잠금 항목:
    • 없음

문제 / 비목표

  • 문제: 정적 lane/G 파일명만으로는 시간대, cloud quota, 이전 실행 실패, 재개 여부를 반영할 수 없고, dispatcher가 호출 시마다 route를 다시 계산하면 시간 경계에서 같은 work unit의 target과 selfcheck 정책이 바뀔 수 있다. 실행 대상 선택과 failover를 결정적 상태 계약으로 분리하면서도 한 branch의 실패나 user review가 독립 branch까지 중단시키지 않아야 한다.
  • 비목표:
    • finalize-task-routing의 lane/G 의미 판정 변경
    • cloud quota 구매·credential 회전·billing 시스템 구축
    • adapter 간 native session protocol 통합
    • 알림 UI와 운영 dashboard 구현

Source of Truth

영역 기준 메모
Roadmap Milestone 문서 정책 범위, 기능 Task와 완료 상태의 장기 원장
Selector Code agent-ops/skills/project/orchestrate-agent-task-loop/scripts/select_execution_target.py 구현 후 selector 입출력, policy matrix와 reason code의 원본
Dispatcher State agent-ops/skills/project/orchestrate-agent-task-loop/scripts/dispatch.py.git/agent-task-dispatcher/state.json task/plan/tag 세대별 route pin, stage별 failure budget, failover와 resume의 실행 원본
Quota Status apps/node/internal/adapters/cli/status를 호출하는 좁은 JSON probe Go parser를 중복 구현하지 않고 cloud available, exhausted, unknown snapshot을 제공함
External Provider Gemini/Claude/Codex CLI adapter가 보고한 normalized status와 runtime result generic stderr만으로 provider/quota 상태를 추정하지 않음
User Decision 없음 시간, route, failover, selfcheck, 실패 예산, 동시성 정책이 확정됨

State Machine

상태 진입 조건 다음 상태 근거
unselected PLAN task/plan/tag 세대에 persisted decision이 없음 selected 또는 blocked_task task file, worker/review stage, KST 시간 구간, quota snapshot, route rule
selected selector가 eligible adapter + target을 반환하고 decision을 work unit에 저장함 executing selector JSON과 persisted decision
executing 선택 target invocation이 시작됨 completed, selfcheck, recovering, blocked_task, review_blocked invocation result, normalized error, review 상태
recovering 동일 stage 실패 예산이 10 미만이고 same-target recovery 또는 아직 사용하지 않은 eligible failover가 있음 executing 또는 failover_selected stage별 누적 failure count, reason code, quota snapshot
failover_selected primary target의 첫 실행 실패 뒤 정책이 단방향 다음 target을 선택하고 logical context package를 준비함 executing 이전 decision, PLAN/locator, normalized output·raw log, workspace; 이전 target으로 bounce하지 않음
selfcheck 실제 worker 완료 target이 local model임 completed, recovering, blocked_task completing target의 pinned local target과 selfcheck stage 결과; 새 route를 평가하지 않음
review_blocked 해당 work unit 진행에 필요한 user review가 미해결임 selected 또는 blocked_task review evidence; 해결 후에도 같은 pinned decision을 사용하고 해당 task의 의존 branch만 대기
blocked_task 실패 예산 10회 도달, 야간 Laguna 실패 뒤 Gemini quota exhausted 또는 eligible target 부재 terminal persisted blocker와 실패 evidence; 독립 branch는 계속 실행
completed 현재 stage가 성공했고 worker인 경우 필요한 local selfcheck까지 성공함 terminal stage 성공 시 해당 stage failure budget 초기화, 결과 artifact와 완료 evidence
  • blocked_task는 현재 자동 실행의 terminal state다. 명시적 retry_blocked는 해당 task group의 blocker와 stage 실패 카운터만 초기화하고 route history는 보존한다. quota exhaustion으로 대기하던 단방향 failover는 새 snapshot으로 eligibility를 다시 평가할 수 있지만, 시간 변화만으로 새 initial route를 만들거나 이미 사용한 이전 target으로 bounce하지 않는다.

Interface Contract

  • 계약 원문: 없음
  • 입력:
    • CLI 필수 입력: select_execution_target.py <task-file>
    • stage: worker | review. 생략하면 task file의 PLAN-* / CODE_REVIEW-* prefix에서 판별함
    • task_file: 정적 routing source인 *-{local|cloud}-GNN.md 경로
    • work_unit_id: PLAN 첫머리 task/plan/tag 세대로 selector가 파생하는 안정적인 identity. PLAN 본문만 바뀌면 유지하고 plan 또는 tag 세대가 바뀌면 새 identity가 됨
    • prior_decision: dispatcher state에서 불러오는 선택 target, 사용한 candidate와 transition history; 최초 선택이면 없음
    • quota_snapshot: 선택 입력에서 생략할 수 있는 cloud usage normalized JSON. runtime 기본은 selector가 좁은 JSON probe를 호출하고, dispatcher의 같은 admission batch 재사용 또는 테스트에서는 snapshot id, adapter, target/profile, status, 관측 시각을 가진 값을 주입할 수 있음
    • evaluated_at: 기본은 runtime clock의 평가 시각. 시간 정책은 Asia/Seoul로 변환하며 테스트에서는 고정 시각을 주입할 수 있음
    • transition: initial | resume | failover. resume은 prior decision을 그대로 쓰고 failover만 다음 candidate를 선택함
  • 출력:
    • schema_version, work_unit_id, stage, lane, grade
    • selected: canonical adapter, target, execution_class=local_model|cloud_model, selfcheck_required
    • candidates: candidate_rank가 낮을수록 먼저 시도하는 ordered 후보와 각 후보의 eligibility/rejection reason. task DAG scheduling priority와는 별개임
    • decision: rule_id, 낮을수록 먼저 적용되는 policy_priority, reason_codes, evaluated_at, timezone, time_window, pinned
    • quota: snapshot_id, mode=bounded|unbounded, status=available|exhausted|unknown|not_applicable, source, checked_at
    • transition: 이전 target, 다음 target, trigger, context_transfer=logical|native_resume|none
  • 금지:
    • active/resume work unit의 persisted decision을 시간 변화만으로 교체하지 않는다.
    • generic stderr나 model list만으로 quota exhausted 또는 provider 장애를 단정하지 않는다.
    • cross-adapter 전환을 native session transfer로 기록하지 않는다.
    • local quota_mode=unbounded를 실패 예산 무제한 또는 동시 실행 강제 상한으로 해석하지 않는다.
    • user review/blocker가 없는 독립 task를 다른 branch의 실패 때문에 중단하지 않는다.
    • selfcheck와 resume을 새 최초 선택으로 처리하거나 공식 CODE_REVIEW를 worker route matrix로 재라우팅하지 않는다.
  • quota 정규화:
    • JSON probe는 target/profile별 required cap set을 선언한다. Gemini처럼 overall과 matching model cap을 모두 제공하는 profile은 둘을 required로 사용할 수 있고, 제공하지 않는 cap을 임의로 만들어내지 않는다.
    • required cap 중 하나라도 confirmed 0% remaining이면 exhausted다.
    • required cap이 모두 관측되고 모두 positive remaining이면 available이다.
    • checker 오류, parse 실패, required cap 누락 또는 상충하는 evidence는 unknown이다.
    • unknown cloud candidate는 각 work unit에서 1회만 시도하되 unknown 자체로 target 전역 동시 실행 cap을 만들지 않는다. runtime quota 오류가 확인되면 같은 snapshot을 exhausted로 갱신해 다음 candidate 또는 task-local blocker로 전환한다.
  • decision 고정:
    • 최초 initial decision은 task/plan/tag 세대에 저장한다. KST 구간 변화, PLAN 본문 수정과 dispatcher 재시작은 재선택 사유가 아니다.
    • failover는 ordered candidate에서 아직 사용하지 않은 다음 target으로만 이동한다. 시간대 또는 quota 회복만으로 이전 target에 bounce하지 않는다.
    • selfcheck는 worker를 완료한 pinned local target을 그대로 사용하며 selector의 새 initial 호출 대상이 아니다.
    • selector는 실패 횟수를 증가시키거나 초기화하지 않는다. dispatcher가 recovery_failures[stage]를 소유하고 target 전환에서는 보존하며 해당 stage 성공에서만 초기화한다.
  • 정책 matrix:
    • local-G01~G06: pi + iop/ornith-fast, local selfcheck
    • local-G07~G08, KST [07:00, 23:00): agy + Gemini 3.6 Flash Medium; 실패 시 pi + iop/laguna-s:2.1로 logical context transfer 후 계속 실행
    • local-G07~G08, KST [23:00, 07:00): pi + iop/laguna-s:2.1; 실패 시 Gemini quota가 available 또는 unknown이면 agy + Gemini 3.6 Flash Medium, confirmed exhausted이면 해당 task 차단
    • local-G09~G10: claude + claude-opus-4-8, cloud completion이므로 selfcheck 없음
    • cloud-G01~G06: claude + sonnet target. adapter가 호출 시 canonical concrete target을 기록함
    • cloud-G07~G08: claude + claude-opus-4-8
    • cloud-G09~G10: codex + gpt-5.6-sol xhigh
    • 모든 공식 CODE_REVIEW-*: Codex gpt-5.6-sol xhigh 고정. worker candidate matrix와 quota 기반 재선택을 적용하지 않음
    • dynamic local-G07~G08 failover는 primary에서 alternate로 한 번만 이동한다. alternate 실패는 같은 target에서 남은 동일-stage 예산으로 복구하며 primary로 돌아가지 않음
    • 그 밖의 cloud worker는 기존 promotable failure chain을 유지하되 같은 stage의 10회 예산을 공유함
    • cloud completion은 selfcheck 없음. local completion만 selfcheck를 실행함
    • target별 정책 semaphore는 두지 않으며 dependency-ready task를 모두 dispatch함

Acceptance Scenarios

ID Milestone Task Given When Then
S01 selector-contract 유효한 task file, task/plan/tag 세대, 고정 시각·quota·prior decision selector를 반복 호출함 candidate rank와 decision evidence를 포함한 JSON이 완전하며 동일 입력은 동일 결정을 반환하고 invalid 입력은 명시 오류가 됨
S02 time-route local-G07 또는 local-G08과 네 KST 경계 시각 최초 route를 평가함 [07:00,23:00)은 Gemini Medium, [23:00,07:00)은 Laguna가 선택됨
S03 grade-route worker local/cloud G01~G10과 CODE_REVIEW matrix 모든 최초 route를 평가함 빈 grade 없이 확정된 adapter+target에 매핑되고 cloud G01~G06에 Gemini가 남지 않으며 CODE_REVIEW는 Codex로 고정됨
S04 quota-input target/profile required cap set, overall/model-specific remaining, parse 실패 및 local 후보 JSON probe와 admission을 평가함 required cap 중 0은 exhausted, 모두 양수는 available, 누락·충돌은 unknown이고 unknown은 work unit별 1회만 시도되되 target 전역 cap은 생기지 않으며 local은 unbounded/not_applicable로 반환됨
S05 route-pin 주간에 선택된 task/plan/tag 세대가 PLAN 본문 변경, 야간 경계와 dispatcher 재시작을 지남 resume함 시간·본문 변경만으로 target이 바뀌지 않고 plan/tag 세대가 바뀔 때만 새 initial decision이 생성됨
S06 context-failover 주간 Gemini 실패 또는 야간 Laguna 실패 failover를 평가함 주간은 Laguna로, 야간은 quota가 있는 Gemini로 한 번만 이어지고 quota가 없으면 해당 task만 차단되며 이전 target으로 bounce하지 않음
S07 failure-budget 같은 work unit의 동일 stage에서 target 전환을 포함한 연속 실패 자동 복구를 반복함 stage budget이 target 간 공유되고 다른 stage와는 분리되며 10회 전에는 단일 Pi/provider/SSE 오류로 전체 루프가 차단되지 않고 stage 성공 시 초기화됨
S08 dependency-drain 병렬 DAG의 한 branch가 user review 또는 terminal blocker에 걸림 scheduler가 drain함 해당 branch와 의존 task만 대기/차단되고 다른 dependency-ready branch는 완료됨
S09 dispatch-integration selector decision이 저장된 worker/review initial, resume와 failover 작업 dispatcher가 invocation함 실행 target, task/plan/tag persisted decision 및 transition history가 일치함
S10 selfcheck-policy Gemini→Laguna 완료, Laguna→Gemini 완료, cloud lane 완료 completion stage를 처리함 첫 경우만 pinned Laguna로 selfcheck가 실행되고 나머지는 selfcheck 없이 완료됨
S11 throughput-policy 동일 target을 쓰는 독립 dependency-ready task 여러 개와 같은 admission batch quota 조회 dispatch함 target별 정적 cap 없이 admission되며 같은 snapshot id가 batch에서 재사용되고 조회 실패는 unknown으로 격리됨
S12 audit-tests 성공, failover, quota block, budget block, review block 실행 evidence를 수집함 work unit, rule, candidate, reason, transition이 테스트·로그·운영 설명에서 추적됨

Evidence Map

Scenario Required Evidence agent-task 연결 완료 Evidence 기대
S01 selector schema/invalid input 단위 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: selector-contract, 테스트 결과
S02 KST 네 경계값 단위 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: time-route, 경계 matrix 결과
S03 worker local/cloud G01~G10 및 CODE_REVIEW route matrix 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: grade-route, matrix snapshot
S04 Go usage checker JSON bridge, required-cap tri-state, unknown 1회와 local unbounded 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: quota-input, quota snapshot evidence
S05 persisted route resume/restart 통합 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: route-pin, decision state evidence
S06 주간·야간 failover와 logical context 통합 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: context-failover, transition evidence
S07 동일 stage target 전환, stage 분리와 성공 초기화를 포함한 10회 failure budget 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: failure-budget, stage counter evidence
S08 user review/blocker 병렬 DAG drain 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: dependency-drain, 독립 branch 완료 evidence
S09 dispatcher worker/review initial, resume와 failover 통합 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: dispatch-integration, invocation audit
S10 completing target 기반 selfcheck 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: selfcheck-policy, stage evidence
S11 동시 dispatch와 batch quota snapshot 테스트 agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: throughput-policy, admission evidence
S12 회귀 테스트, reason/transition 로그, 운영 문서 diff agent-task/m-agent-task-runtime-target-selector/... Roadmap Completion: audit-tests, 최종 test summary

Cross-repo Dependencies

  • 없음

Drift Check

  • Milestone 기능 Task와 Acceptance Scenario가 일치한다.
  • Evidence Map이 code-review/complete.log에서 검증 가능하다.
  • agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
  • 사용자 리뷰가 필요한 항목은 USER_REVIEW.md에만 남겼다.

사용자 리뷰 이력

  • 2026-07-25: KST 주간/야간 구간, target matrix, Medium reasoning, failover, quota, local selfcheck, 10회 실패 예산, work-unit pin, task-local blocker와 무제한 target별 처리량 정책을 대화에서 확정했다.

작업 컨텍스트

  • 표준선: selector는 adapter + target을 결정적으로 반환하고, skill은 호출 시점과 persisted decision 소비 절차를 정의한다. static lane/G 분류는 기존 finalize-task-routing 책임으로, 공식 review는 기존 Codex 고정 lifecycle로 남긴다.
  • 후속 SDD: 없음