Runtime Delivery Model — Bake vs Reconcile (SSOT)
Runtime Delivery Model — Bake vs Reconcile (SSOT)
Section titled “Runtime Delivery Model — Bake vs Reconcile (SSOT)”왜 이 문서가 존재하나: bake할 것과 reconcile(런타임 pull)할 것, 그리고 각 버전 핀의 **주체(owner)**가 문서화되지 않아 매 인시던트마다 재발견되었다(예: workspace-tools 소비자 핀이 0.1.121에 6버전 고착 → AgentSquad 8/8 완주 실패의 메타-근본). 이 문서가 그 SSOT다. 새 딜리버리 메커니즘/핀을 추가하면 반드시 여기 표에 주체와 bump 경로를 등록한다.
관련: 디스크리스 레이어드 런타임 · cliproxy 런타임 크레덴셜 · 코드 승격 티어링
BAKE = 느리고-안정. 이미지에 굽는다. 드물게 바뀜. 새 도구 버전 나올 때만 리빌드. 정당한 물리 복잡도.
RECONCILE(PULL) = 빠르게-바뀜. 이미지에 굽지 않는다. 런타임 부트스트랩에서 cosign-서명 OCI로 중앙 pull. 코드/설정이 자주 바뀌므로 이미지 리빌드 없이 중앙 업그레이드. 핀은 GitOps values SSOT에서, bump는 릴리스 워크플로가 자동으로 (사람 손 X = 고착 방지).
핵심 실패 모드: reconcile 레이어인데 핀 bump 주체가 없으면 → 조용히 고착 → 모든 롤이 무의미해짐. 이게 우리가 계속 맴돈 이유.
레이어 지도 (누가 무엇을 언제)
Section titled “레이어 지도 (누가 무엇을 언제)”| 레이어 | BAKE/PULL | 내용물 | 버전 핀 (SSOT) | 핀 bump 주체 | 소비 시점 |
|---|---|---|---|---|---|
| base runtime | BAKE | OS, Serena/LSP, code-server, 모델 CLI(codex/claude/agy), oras/cosign/age, STUB bins(docker/gh/fractalops-* → “부트스트랩에서 설치, exit 127”). workspace-tools src 없음, backend src 없음. | daytona-agent-workspace 이미지 태그 = daytona DEFAULT_SNAPSHOT (platform/k8s/apps/daytona/daytona-values.yaml) | runtime-release build_daytona_workspace=true → runtime-gitops-bump가 daytona snapshot 태그 bump (주의: 이 auto-bump가 daytona-values를 항상 건드리진 않음 — 검증 필요) | daytona가 이 이미지에서 샌드박스를 생성 |
| workspace-tools (agent-session 러너 mjs) | PULL | ops/workspace-tools/src의 빌드된 dist. agent-session-{core,codex,claude,antigravity}.mjs = 완료/핸드오프/first-tool 계약 실행부. | .Values.runtime.workspaceToolsPackage = FRACTALOPS_WORKSPACE_TOOLS_PACKAGE_SPEC = @fractalops/workspace-tools@<ver> (api/worker/preview/test values) | workspace-tools-release.yml publish 후 Assembly workspace_tools promotion이 모든 소비자 핀을 원자적으로 갱신 | 샌드박스 부트스트랩(daytona_bootstrap.py)이 Nexus에서 oras pull (cosign verify + age decrypt) |
| fractalops-runtime (backend 오버레이) | PULL | pyproject.toml + backend/src + ops/cli (ops/nexus/push_runtime_oci.sh). 샌드박스가 실행하는 백엔드(hooks/fops CLI). | FRACTALOPS_RUNTIME_OCI_VERSION = worker 빌드 스탬프(= worker 이미지 gha-N 태그, daytona_runner.py:1168-1205에서 env/스탬프로 resolve) | runtime-release publish_runtime_oci=true (빌드마다 OCI publish + “Promote runtime OCI pin”). worker 이미지 롤 = 새 스탬프 = 새 버전. | 부트스트랩이 fractalops-runtime:<gha-N> pull → /opt/fractalops/runtime에 overlay |
| cliproxy 크레덴셜/OCI pull 크레덴셜 | RECONCILE(비밀) | Nexus/cosign/age pull 크레덴셜 | OpenBao fractalops/default/runtime → ESO → secret | OpenBao(SSOT). ⚠️ CT125가 재봉인되면 pull 크레덴셜 503 → 부트스트랩 실패 → 샌드박스가 STALE 베이크로 폴백. | 부트스트랩이 pull 전에 소비 |
daytona 스냅샷의 실제 역할 (자주 오해)
Section titled “daytona 스냅샷의 실제 역할 (자주 오해)”daytona DEFAULT_SNAPSHOT(=daytona-workspace-gha-N 이미지)은 base 레이어(BAKE)만 제공한다 — workspace-tools도 backend src도 그 안에 없다. 그래서 스냅샷을 bump해도 workspace-tools/#기능은 안 바뀐다(그건 PULL 레이어). 인시던트에서 스냅샷 bump로 완료-벽을 고치려던 시도(PR #2585)가 무의미했던 이유. 스냅샷 bump는 새 도구버전/base 변경 때만 의미.
부트스트랩 시퀀스 (홉)
Section titled “부트스트랩 시퀀스 (홉)”daytona가 base 이미지로 샌드박스 생성 → 부트스트랩(daytona_bootstrap.py): 1. OpenBao→ESO 크레덴셜 (Nexus/cosign/age) 2. oras pull fractalops-runtime:<gha-N> (backend overlay) ─┐ 캐시된 버전과 다르면만 재설치 3. oras pull workspace-tools:<ver> (러너 mjs) ─┘ 4. agent-session 러너 실행 → cliproxy로 모델 호출cliproxy → (round-robin, cliproxy-native) → OpenAI/Anthropic/Google홉/중첩 축소 지도 (AgentSquad ↔ DevPod 공유)
Section titled “홉/중첩 축소 지도 (AgentSquad ↔ DevPod 공유)”두 평면(AgentSquad=daytona 샌드박스, DevPod=k8s 워크스페이스)이 같은 델리버리 메커니즘을 사투리로 중복 구현 중. 합칠 지점:
- OCI 오버레이 pull — 둘 다 부트스트랩에서 workspace-tools + fractalops-runtime을 pull. 부트스트랩 로직 공유(단일 함수/계약). [Backend bootstrap contract]
- cliproxy 라우팅 + 메터링 — DevPod은
/u/<employee>미터 경유, AgentSquad는 raw cliproxy 직결(미터 우회 → 토큰 미계측). Track 8이 AgentSquad를 같은 미터(/u/as:<project>:<agent>:<provider>)로 통합 → 단일 경로, 캐시-세이프(경로 스트립), 라운드로빈 무터치. [Backend routing contract] - 세션 auth env 빌더 —
coding_agent_auth_env(AgentSquad) vsdeveloper_devpod_workspaceenv(DevPod)가 둘 다 cliproxy endpoint+key+모델 env를 조립. 공통 코어로 수렴. [Backend authentication environment contract] - 핀 bump 자동화 — workspace-tools/runtime 핀을 두 평면이 공유하므로 auto-bump는 한 곳에서. [Release workflow + Assembly values contract]
원칙: 한 능력당 한 구현. base=BAKE, 코드/툴=PULL(중앙, auto-bump), 비밀=OpenBao, 라우팅=cliproxy-native. 사투리 금지.
재발방지 (주체 미할당 → 할당)
Section titled “재발방지 (주체 미할당 → 할당)”- workspace-tools values 핀 auto-bump — publish와 Assembly promotion을 한 release contract로 유지하고 소비자 누락을 테스트합니다.
- CT125 OpenBao 재봉인 auto-unseal — 스케줄 리콘실(멱등, 키는 OpenBao/secret)로 재봉인이 모든 빌드/샌드박스 pull을 막지 않게. 주체: Assembly runtime observation. [[always-guarantee-settings-reproducibility]]
- daytona snapshot auto-bump 검증 —
runtime-gitops-bump가 daytona-valuesDEFAULT_SNAPSHOT을 실제로 올리는지 확정(안 올린 이력 있음). 주체: 릴리스 워크플로.
이 3개가 걸리기 전까지는 “롤했는데 안 바뀜”류 인시던트가 재발한다.