Skip to content

[orchestrator] 단일 main 실행 슬롯이 요청 단위로 격리되지 않아 다른 대화의 런에 멘션이 얹힌다 #743

Description

@cosmosjeon

공통 인시던트 컨텍스트
2026-09-11 20:10:29 KST, Slack 채널 C0AKXLE61J5(#ceo_lead_align_input)의 스레드 1789104278.881179 에서 사용자가 봇을 멘션했다. 봇은 2초 뒤 "경과 531초 / 8분째 실행 중" 진행 카드를 올렸고(=이미 돌던 다른 런의 진행 상태), 약 3분 뒤 전혀 무관한 ReelBrain 티켓(exp3-cardnews-reunion-conditions, qa-delivery BLOCKED)의 ## Terminal phase summary 본문을 그 스레드에 게시했다. 게시된 두 메시지는 이후 수동 삭제했다.
로그: ~/.cli-jaw/logs/serve.log 19555-19670, jaw-serve.err. DB: ~/.cli-jaw/jaw.db messages 1666/1676/1677.
라벨 제안: 본문 상단 표기 참조.

제안 라벨: bug priority:P1 area:orchestrator runtime

단일 main 실행 슬롯이 요청 단위로 격리되지 않음

요약

2026-09-11 20:10:29 KST #ceo_lead_align_input(C0AKXLE61J5 / ts=1789104278.881179) 멘션이, 이미 ~8분째 돌던 다른 런의 진행 카드(경과 531초)와 ReelBrain exp3 qa-delivery 요약을 그대로 받았다. 세션 행은 분리됐지만 main 실행·진행·배달이 requestId에 고정되지 않는다.

재현·증거

  • 설정: multiSession.enabled=true, maxConcurrent=2, midRunPolicy=steer.
  • 멘션 세션: binding jaw:slack:channel:C0AKXLE61J5:thread:1789104278.8811796c6e4301. messages 1676 user/slack 같은 세션.
  • 오배송 본문: 1677 assistant b25ca0b8(web qa-delivery, 10:47:34) ## Terminal phase summary. 멘션 본답은 1678(11:24:53).
  • serve.log:19555-19566: [slack:in] C0AKXLE61J5: 너도 한번 해봐![jaw:pabcd] state=IDLE, spawning/resuming agent → 기존 C0BJW306TE3 송신 지속 → exited 0, 19613 charsslack.post C0AKXLE61J5.
  • slack.progress.elapsed/longRunning은 카드 createdAt 기준(progress-activity.ts:122,208-223). 멘션 2초 만에 “경과 531초 / 8분째”면 기존 런 진행이 새 target에 게시된 것.

원인

세션 키는 대화별이 맞다. buildRemoteBindingKey (session-key.ts:34-46; 합성 thread 제외 #520) → Slack resolveOrCreateRemoteSession (ingress.ts:237-258).

실행 격리는 여기서 끊긴다.

  1. scopeForChatSession: sessionId==='default'면 remoteKey 있어도 'default' (scope.ts:43-54). findActiveScope는 항상 'default'.
  2. busy는 그 scope의 activeMainProcesses만 (spawn.ts:518-524). 새 스레드는 IDLE → 즉시 spawn. 전역 한도는 SessionLanes.maxConcurrent=2. orc_state는 default 한 행.
  3. 같은 scope busy면 기본 steer (gateway.ts:71-76,312-331). 합성 스레드만 followup. steer가 새 target/requestId를 기존 런 배달 주소로 쓴다.
  4. 큐는 배열 하나. groupQueueKey는 로그용. collect는 같은 scope N건을 join하고 나머지는 merged.
  5. 매칭이 느슨: matchesSlackReply는 scope/sessionId/origin 없으면 통과 (bot.ts:461-472). print agent_done이 세 필드를 빼먹음 (lifecycle-handler.ts:821).

가설: web 런 b25ca0b8의 진행/target이 새 멘션 때 C0AKXLE61J5로 바뀌었거나, 신원 없는 agent_done을 새 waiter가 주웠다.

수정 제안

  1. 입학 시 requestId/remoteKey/target/sessionId 런 핀. progress·post·orchestrate_done은 이 핀만. 불일치면 드롭.
  2. 매칭 fail-closed: 세 필드 누락은 비매칭. print agent_done에 필수.
  3. 교차 remoteKey Slack은 steer 금지, 기본 followup.
  4. 큐 drain을 remoteKey로. 교차 대화 join/collect 금지. 실행 중 런에 새 요청을 얹지 말고 키별 FIFO.
  5. 진행 createdAt = 이 request 시작. 다른 런 snapshot을 새 target에 게시 금지.

대안: request당 main lease. 최소 수정은 1+2. queued_messages v2 pin은 additive. binding UNIQUE 유지. #399 collapse를 remote에 재적용하지 말 것.

영향

Slack/web 동시 런. 잘못된 스레드로 본문/진행 유출(내부 티켓 → CEO 채널).

검증

긴 web 런 중 다른 Slack 스레드 멘션 → 경과 <5s, exp3 요약 없음. 신원 없는 done 이벤트 비매칭. 교차 remoteKey collect 금지. 회귀 #399 #453 #520 #655.

관련

#399 기본 세션 collapse · #407 큐 drain · #453 큐 순서 · #520 합성 thread 키 · #655 steer 고아 waiter · #673 진행 UX


같은 인시던트에서 갈라진 이슈: #742 · #744 · #745

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:orchestratorOrchestration, workers, queue, lifecyclebugSomething isn't workingpriority:P1Next up after stabilizationruntimeRuntime behavior

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions