Skip to content

Queue approval prompts so a parallel run is not stranded forever - #63

Merged
Seungpyo1007 merged 1 commit into
developfrom
fix/approval-queue
Aug 5, 2026
Merged

Queue approval prompts so a parallel run is not stranded forever#63
Seungpyo1007 merged 1 commit into
developfrom
fix/approval-queue

Conversation

@Seungpyo1007

Copy link
Copy Markdown
Member

The bug

askRunApproval stored its resolve in a single field:

this._askRunResolve = resolve;
this.setState({ askRun: { command, rationale, agent, ... } });

That holds only while one run exists. This app runs several at once — a round with two delegate_task calls starts two sub-runs in parallel (flying in runAgentTurn), and either can hit the shell-command or game-engine approval gate.

When two gates land, the second overwrites the first's resolve. Answering the dialog settles only the second. The first run stays parked on await forever:

  • its agent is stuck at status edit,
  • the finally that releases fileLocks is never reached, so other agents asking for that file keep hearing "another agent is working on it",
  • nothing is shown to the user. There is no error, no timeout, no way back except restarting.

The fix

src/engine/askQueue.ts queues them: show one, resolve the one that was answered, then raise the next. The invariant is that every request settles exactly once.

Stopping an agent now also drops that agent's queued requests, not just the visible one — otherwise a stopped agent's dialog resurfaces later while its run stays parked. Stop-all rejects the whole queue.

Verification

  • 9 unit tests on the queue, including the overwrite case that used to strand the first request. 963 passing (was 954).
  • npm run typecheck clean.
  • Real-app regression probe (open/edit/external-change/save): 5/5.

Scope note: the collision needs two live model runs to reproduce end-to-end, so it is covered by unit tests rather than a CDP probe. The real-app run here checks that the single-dialog path did not regress.

askRunApproval 이 resolve 를 필드 하나(_askRunResolve)에 담고 있었다. 실행이
하나뿐일 때는 맞는데, 이 앱은 위임으로 여러 실행이 동시에 돈다 — 한 라운드에
delegate_task 가 둘이면 하위 실행 둘이 나란히 돌고, 둘 다 셸 명령이나 엔진
작업 승인을 물을 수 있다.

그때 뒤에 온 물음이 앞의 resolve 를 덮었다. 사용자가 답하면 뒤엣것만 풀리고
앞의 실행은 영원히 await 에 매달린다. 상태는 "편집 중" 인 채로 멈추고, 그
실행이 쥔 파일 락은 finally 에 도달하지 못해 풀리지 않으며, 화면에는 아무
말도 안 나온다. 그 파일을 건드리려는 다른 에이전트는 계속 "작업 중입니다"
만 듣는다.

engine/askQueue.ts 로 줄을 세운다. 하나씩 보여 주고, 답한 것만 풀고, 다음을
올린다. 모든 물음은 정확히 한 번 풀린다.

에이전트 중지는 이제 보이는 물음뿐 아니라 줄에서 기다리는 그 에이전트의
물음까지 걷어낸다. 안 그러면 중지한 에이전트가 나중에 모달로 되살아나고
그 실행은 계속 매달려 있다. 전체 중지는 줄 전체를 거절로 푼다.

단위 9개 추가(963개 통과). 실제 앱 회귀 확인 5/5.
@Seungpyo1007 Seungpyo1007 added this to the v0.3 (2026-09-30) milestone Aug 5, 2026
@Seungpyo1007 Seungpyo1007 added the bug Something isn't working label Aug 5, 2026
@Seungpyo1007 Seungpyo1007 self-assigned this Aug 5, 2026
@Seungpyo1007
Seungpyo1007 merged commit 331113e into develop Aug 5, 2026
1 check passed
@Seungpyo1007
Seungpyo1007 deleted the fix/approval-queue branch August 5, 2026 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant