17 KiB
17 KiB
SDD: [route-02] IOP 단일 요청 Agent 실행
위치
- Milestone: IOP 단일 요청 Agent 실행
- Phase: PHASE.md
상태
[승인됨]
SDD 잠금
- 상태: 해제
- 사용자 리뷰: 없음
- 잠금 항목:
- [D01] one-shot은 사용자 prompt나 logical
request_id가 아니라 Claude→IOP/v1/messagesPOST 정확히 1회다. - [D02] IOP Edge가 외부 요청과 stage state machine, 하나의 outer Anthropic stream과 최종 terminal을 소유한다.
- [D03] request-scoped workspace와 tool execution은 preset이 승인한 Mac IOP Node가 소유한다.
- [D04] 외부 Claude는 internal tool call/result를 실행하지 않으며 IOP가 두 번째 Messages 요청을 요구하지 않는다.
- [D05] 초기 stage는 Gemini 3.6 Flash high plan → ornith-fast work → Gemini 3.6 Flash high review/repair 순서다.
- [D06] 범용 interactive shell·desktop·scheduler는 제외하고 bounded request-scoped tool executor만 포함한다.
- [D07] Pi/OpenAI Chat Completions는 이 마일스톤에서 사용하지 않는다.
- [D08] workspace tool wire/runtime은 provider
RunRequest, provider execution package와 closedNodeCommand를 확장하지 않고 별도 typed request-scoped 경계로 둔다. - [D09] 초기 preset은 mode selection 없는 fixed
lightPlan/Work/Review 경로이며 direct/heavy/mixed mode 선택은 후속 마일스톤 범위다. - [D10] outer stream에는 진행 요약과 최종 사용자 결과만 공개하고 internal provider reasoning, tool protocol과 stage terminal은 공개하지 않는다.
- [D01] one-shot은 사용자 prompt나 logical
문제 / 비목표
- 문제: 현재 compatibility 경로는 provider tool call을 Claude-facing
tool_use로 종료하고 caller의 다음/v1/messagestool-result 요청에 의존할 수 있다. 이는 사용자가 확정한 단일 요청 모델 동작이 아니다. IOP가 외부 요청을 열린 상태로 유지하면서 plan, workspace 작업, review/repair와 tool result를 모두 내부에서 소유해야 한다. - 비목표:
- 범용 shell/desktop/PTY 서비스와 장기 agent process
heavy의 재계획·여러 review cycle·durable resume- Pi/OpenAI Chat Completions one-shot 지원
- cross-Edge coordinator state replication
Source of Truth
| 영역 | 기준 | 메모 |
|---|---|---|
| Roadmap | Milestone 문서 | 목표, Task와 완료 상태 원장 |
| Edge Runtime | apps/edge/internal/openai, apps/edge/internal/service |
single ingress, coordinator, stage dispatch, Anthropic outer stream |
| Node Runtime | apps/node/internal/node, apps/node/internal/transport와 전용 workspace executor |
Mac Node request-scoped workspace/tool 실행; provider execution runtime과 분리 |
| Config/Wire | packages/go/config, proto/iop, configs/edge.yaml |
새 preset model/workspace reference와 전용 Edge-Node tool request/result 계약의 구현 원본 |
| Stream Runtime | packages/go/streamgate |
internal terminal hold, repetition/no-progress와 final commit |
| API Contract | Anthropic-Compatible Messages API | 외부 단일 Messages request/stream/error 계약 |
| Runtime Contract | Edge-Node Runtime Wire | 현재 provider wire 기준; 전용 workspace tool wire 구현 시 함께 갱신 |
| User Decision | D01-D10 | 2026-08-05 최종 합의와 기존 provider/runtime 계약에 따른 책임 분리, 추가 사용자 결정 없음 |
State Machine
| 상태 | 진입 조건 | 다음 상태 | 근거 |
|---|---|---|---|
accepted |
Claude /v1/messages POST 하나를 인증·admission하고 request/preset/workspace generation을 고정 |
planning, failed, cancelled |
ingress count, request id, principal/preset/workspace binding |
planning |
Gemini 3.6 Flash high가 작은 plan과 검증 기준을 생성하고 internal write를 요청 | internal_tool, working, failed, cancelled |
plan stage/provider attempt/tool call |
working |
ornith-fast가 plan을 읽고 workspace 작업·검증을 수행 | internal_tool, reviewing, failed, cancelled |
work stage/provider attempt/tool call/completion candidate |
reviewing |
Gemini 3.6 Flash high가 결과·검증 evidence를 검사 | internal_tool, repairing, finalizing, failed, cancelled |
review stage verdict/tool call |
repairing |
같은 review stage가 잔존 작업을 수정·재검증 | internal_tool, finalizing, failed, cancelled |
review/repair tool call/result |
internal_tool |
active stage가 canonical workspace tool call을 생성 | 저장된 active stage, failed, cancelled |
Node tool request/result; 외부 Anthropic terminal 없음 |
finalizing |
review pass 또는 repair 완료, cleanup 대기 | completed, failed, cancelled |
cleanup result, pending final terminal |
completed |
cleanup과 최종 response commit 성공 | 종료 | Anthropic terminal 1회, ingress count 1 |
failed |
admission/provider/tool/validation/timeout/context 실패 | 종료 | endpoint-native error terminal 1회 |
cancelled |
caller disconnect/abort | 종료 | provider/tool process cancel과 bounded cleanup |
State invariant:
- 한 external request에는 하나의 active stage만 있으며 planner, worker, reviewer binding과 workspace generation은 시작 시 고정한다.
internal_tool은 외부tool_useterminal이 아니다. IOP Node result가 active stage provider continuation으로 돌아가고 outer Anthropic stream은 열린 상태를 유지한다.- Gemini plan/review stage에는
reasoning_effort=high를 적용하고 ornith-fast work stage에는 그 옵션을 전파하지 않는다. - internal provider response-start/terminal은 stage transition evidence이며 public Anthropic envelope을 새로 열거나 닫지 않는다.
- stage별 tool iteration/output/deadline과 request 전체 wall-clock budget은 request 시작 시 고정하고, exhaustion은 다른 stage/model 또는 외부 Claude 요청으로 우회하지 않는다.
- cleanup은 request-owned process와
.iop/job/<request_id>artifact만 회수한다. 사용자 요청으로 생성·수정한 workspace 결과는 success/failure cleanup 대상이 아니다. - completed/failed/cancelled는 서로 배타적이고 final terminal은 exactly-once다.
Interface Contract
- 계약 원문: Anthropic-Compatible Messages API, Edge Config And Runtime Refresh, Edge-Node Runtime Wire
- 외부 입력:
POST /v1/messages: Claude가 보내는 유일한 작업 ingress다.model: fixedlightsingle-request execution preset에 매핑되는 public model id다.- caller body의
tools[]는 이 preset의 workspace 실행 권한이나 Node/path selector가 아니다.
- preset/config 입력:
plan: canonicalgemini-3.6-flashreference와 high reasoning option.work: canonicalornith-fastreference; planner/reviewer high option을 상속하지 않는다.review: canonicalgemini-3.6-flashreference와 high reasoning option.workspace_ref: operator가 승인한 Mac IOP Node와 workspace root capability reference다. raw absolute path나 credential을 preset에 직접 넣지 않는다.limits: requestwall_clock_ms와 stage별timeout_ms,max_tool_iterations,max_output_bytes를 양수와 server absolute cap 안에서 고정한다. refresh는 active request limit을 바꾸지 않는다.- 초기 preset은 dynamic selector나
allowed_modesadvisory를 실행하지 않고 plan → work → review entry를 고정한다. unknown/direct/heavy/mixed binding은 시작 전에 거부한다.
- 내부 tool 입력/출력:
- provider
RunRequest.metadata, provider execution package나 closedNodeCommand를 workspace 실행 표면으로 재사용하지 않고 전용 typed Edge-Node request/result를 사용한다. - canonical operation은 read/list/write/delete/command이며 Edge가 bounded typed request로 만들고 Node가 structured result를 반환한다.
- command는 fixed workspace cwd, process group, timeout, output cap과 environment allowlist를 가진다.
- path는 workspace root containment와 symlink escape 방지를 통과해야 한다.
- provider
- 외부 출력:
- plan/work/review/repair의 redacted 진행 요약과 최종 사용자 결과는 하나의 Anthropic stream에서 보일 수 있고, 긴 내부 stage 동안 endpoint-native ping으로 연결 liveness를 유지할 수 있다.
- internal provider reasoning, tool protocol, provider id, credential, raw command output과 stage terminal은 공개하지 않는다.
- 최종 response model은 caller가 선택한 public model id를 유지하고 terminal은 한 번만 emit한다.
- 금지:
tool_useterminal로 외부 Claude에 internal workspace 작업을 넘기거나 두 번째/v1/messages를 요구한다.- “사용자 prompt 1회” 또는 “request_id 1개”만 확인하고 one-shot PASS로 판정한다.
- caller가 arbitrary Node, absolute path, command environment, provider credential 또는 preset 밖 model을 선택하게 한다.
- review defect를 숨기고 work candidate를 성공으로 반환하거나 provider 실패를 다른 stage/model로 암묵 fallback한다.
Acceptance Scenarios
| ID | Milestone Task | Given | When | Then |
|---|---|---|---|---|
| S01 | single-ingress |
Claude가 작은 workspace 작업을 public preset model로 요청 | 작업이 최종 종료 | Edge가 관측한 /v1/messages POST가 정확히 1회이고 추가 caller ingress가 없다. |
| S02 | preset-binding |
authorized Gemini, ornith-fast와 Mac workspace route가 있는 principal | preset을 list/admit/execute | fixed light plan/work/review/workspace binding이 immutable하게 고정되고 public model id가 유지되며 dynamic mode binding은 거부된다. |
| S03 | stream-terminal |
여러 internal provider stage가 response-start/content/terminal을 생성하고 stage 사이 대기가 발생 | outer Anthropic SSE를 관측 | redacted progress/ping으로 연결을 유지하고 private reasoning/tool wire 없이 outer envelope 하나, 충돌 없는 block 순서와 최종 terminal 하나만 보인다. |
| S04 | workspace-binding |
승인/미승인 workspace, 다른 Node/path와 symlink escape 후보 | request admission과 tool 실행 | 승인된 Mac workspace만 실행되고 임의 path/Node/escape는 provider/tool 실행 전에 거부된다. |
| S05 | tool-executor |
read/list/write/delete/command 성공·실패·timeout·large output | Node tool을 실행 | typed result, containment, process cancel과 output bound가 일관되게 적용된다. |
| S06 | tool-loop |
internal model이 여러 workspace tool call을 생성 | IOP가 결과를 stage에 반환 | tool loop가 IOP 내부에서 계속되고 Claude-facing tool_use terminal이나 두 번째 HTTP request가 없다. |
| S07 | cleanup-observation |
성공·오류·cancel 요청이 request artifact/process와 사용자 결과 파일을 생성 | terminal 정리를 수행 | request process와 .iop/job artifact만 정책대로 정리되고 사용자 결과는 보존되며 raw content 없이 stage/tool/total timing과 outcome이 연결된다. |
| S08 | plan-stage |
immutable user task와 empty request job | plan stage 실행 | Gemini 3.6 Flash high가 작은 plan·검증 기준을 만들고 internal plan.md write가 성공한다. |
| S09 | work-stage |
plan과 writable workspace | work stage 실행 | ornith-fast가 high 옵션 없이 plan을 읽고 실제 변경·검증과 completion candidate를 만든다. |
| S10 | review-stage |
pass 또는 defect work candidate | review stage 실행 | Gemini 3.6 Flash high가 pass를 확정하거나 잔존 작업을 수정·재검증하고 final 결과를 만든다. |
| S11 | error-cancel |
stage/request budget exhaustion, repetition/no-progress, malformed tool call, provider/tool timeout, output/context limit 또는 disconnect | 요청이 종료 | 추가 Claude 요청, 암묵 stage/model fallback이나 partial-success 없이 표준 error/cancel/length terminal과 내부 cancel로 수렴한다. |
| S12 | claude-smoke |
실제 Claude와 writable Mac test workspace | 작은 수정·검증 작업을 한 번 요청 | Gemini → ornith-fast → Gemini 순서, stage/total 순수 시간, 최종 파일/검증, ingress POST 1회와 terminal 1회를 redacted 로그로 재현한다. |
Evidence Map
| Scenario | Required Evidence | agent-task 연결 |
완료 Evidence 기대 |
|---|---|---|---|
| S01 | Edge ingress counter, Claude invocation integration test와 Anthropic contract sync | agent-task/m-iop-owned-single-request-agent-execution/single-ingress/ |
single-ingress request-count=1/API contract evidence |
| S02 | preset decode/authorization/model echo/workspace snapshot test와 config contract sync | agent-task/m-iop-owned-single-request-agent-execution/preset-binding/ |
preset-binding immutable fixed-light binding evidence |
| S03 | multi-stage fragmented SSE와 single terminal test | agent-task/m-iop-owned-single-request-agent-execution/stream-terminal/ |
stream-terminal one-envelope/one-terminal evidence |
| S04 | workspace route/path/symlink admission table test | agent-task/m-iop-owned-single-request-agent-execution/workspace-binding/ |
workspace-binding fail-closed evidence |
| S05 | Node tool operation/process/output bound integration test, proto와 Edge-Node contract sync | agent-task/m-iop-owned-single-request-agent-execution/tool-executor/ |
tool-executor typed wire/success/error/cancel evidence |
| S06 | internal multi-tool round-trip test with zero public tool terminal | agent-task/m-iop-owned-single-request-agent-execution/tool-loop/ |
tool-loop no-external-continuation evidence |
| S07 | cleanup race, user-result preservation과 raw-free timing/log/metric allowlist test | agent-task/m-iop-owned-single-request-agent-execution/cleanup-observation/ |
cleanup-observation scoped lifecycle/timing evidence |
| S08 | Gemini plan request/options/artifact fixture | agent-task/m-iop-owned-single-request-agent-execution/plan-stage/ |
plan-stage high option과 small-plan evidence |
| S09 | ornith-fast tool work fixture와 high-option absence test | agent-task/m-iop-owned-single-request-agent-execution/work-stage/ |
work-stage actual workspace/verification evidence |
| S10 | review pass/defect/repair fixture와 finalization test | agent-task/m-iop-owned-single-request-agent-execution/review-stage/ |
review-stage review/repair evidence |
| S11 | budget/error/cancel/length/repetition terminal matrix test | agent-task/m-iop-owned-single-request-agent-execution/error-cancel/ |
error-cancel bounded/no-partial/no-second-request evidence |
| S12 | actual Claude, ingress counter, Edge/Node/provider stage+total timing log와 workspace before/after | agent-task/m-iop-owned-single-request-agent-execution/claude-smoke/ |
claude-smoke request-count=1 end-to-end/elapsed evidence |
공통 완료 검증은 최소 go test -race -count=1 ./packages/go/config ./packages/go/streamgate ./apps/edge/internal/openai ./apps/edge/internal/service ./apps/node/internal/node ./apps/node/internal/transport, 전용 workspace executor package test, make proto, git diff --check를 포함한다.
실제 provider smoke는 credential과 writable test workspace를 갖춘 Mac Node에서 실행하되 secret과 raw prompt/tool output을 tracked evidence에 기록하지 않는다.
Cross-repo Dependencies
- 없음
Drift Check
- Milestone 기능 Task와 Acceptance Scenario가 일치한다.
- Evidence Map이 code-review/complete.log에서 검증 가능하다.
- agent-contract를 쓰는 경우 SDD에 계약 원문을 복제하지 않았다.
- 사용자 리뷰가 필요한 항목은 없고 확정된 D01-D10을 반영했다.
사용자 리뷰 이력
- 2026-08-05: 사용자가 Claude→IOP 요청 정확히 1회, IOP/Mac Node-owned workspace tool execution, Gemini 3.6 Flash high plan → ornith-fast work → Gemini 3.6 Flash high review/잔존 수정과 Pi 제외를 최종 방향으로 확정했다.
작업 컨텍스트
- 표준선: 기존 Anthropic bridge, provider-pool authorization/lease, Stream Evidence Gate와 Edge-Node transport를 재사용하되 caller tool continuation을 one-shot 내부 tool runtime으로 대체한다.
- 구현 순서: preset/workspace config → Edge-Node tool wire와 Mac executor → single-request coordinator → plan/work/review stage → stream/error/cleanup → actual Claude smoke.
- 후속 SDD: Heavy Plan/Review 실행과 검증 MVP