OpenClaw 프로세스 감독: 안정적인 생명주기 관리 구현
오랫동안 실행되는 커맨드를 관리하다 보면 프로세스가 제대로 종료되지 않거나, PTY 설정이 꼬여서 고생한 적 있으시죠? 특히 백그라운드 실행과 포그라운드 실행이 섞여 있을 때 프로세스 수명 주기를 일관되게 관리하는 건 정말 까다로운 일이에요.
이번 작업에서는 이러한 프로세스 관리의 복잡함을 해결하고, 더 안전하고 예측 가능한 실행 환경을 만들기 위한 PTY 및 프로세스 관리(Process Supervision) 계획을 정리했습니다.
1. 문제와 목표
섹션 제목: “1. 문제와 목표”우리는 다음과 같은 다양한 상황에서 오랫동안 실행되는 커맨드에 대해 신뢰할 수 있는 단일 수명 주기가 필요해요.
exec포그라운드 실행exec백그라운드 실행process후속 작업 (poll,log,send-keys,paste,submit,kill,remove)- CLI agent runner 서브프로세스
단순히 PTY를 지원하는 것이 목표가 아니에요. 불안정한 프로세스 매칭 휴리스틱 없이, 예측 가능한 소유권 확인, 취소, 타임아웃, 그리고 깔끔한 정리를 구현하는 것이 핵심입니다.
2. 범위 및 경계
섹션 제목: “2. 범위 및 경계”- 구현체는
src/process/supervisor내부에 유지해요. - 이를 위한 새로운 패키지를 만들지는 않습니다.
- 실용적인 선에서 현재 동작과의 호환성을 유지해요.
- 터미널 리플레이나 tmux 스타일의 세션 유지까지 범위를 넓히지는 않기로 했습니다.
3. 이번 브랜치에서 구현된 내용
섹션 제목: “3. 이번 브랜치에서 구현된 내용”Supervisor 베이스라인 구축 완료
섹션 제목: “Supervisor 베이스라인 구축 완료”- Supervisor 모듈이
src/process/supervisor/*경로에 배치되었습니다. - Exec 런타임과 CLI runner가 이미 supervisor의 spawn 및 wait를 통해 라우팅되고 있어요.
- Registry 종료 처리는 멱등성(idempotent)을 유지합니다.
이번 패스에서 완료된 작업
섹션 제목: “이번 패스에서 완료된 작업”- 명시적인 PTY 커맨드 계약(Contract)
SpawnInput이src/process/supervisor/types.ts에서 discriminated union으로 변경되었습니다.- PTY 실행 시 일반적인
argv를 재사용하는 대신ptyCommand가 필수적으로 요구됩니다. - Supervisor는 더 이상
src/process/supervisor/supervisor.ts에서 argv를 join하여 PTY 커맨드 문자열을 다시 만들지 않아요. - Exec 런타임은 이제
src/agents/bash-tools.exec-runtime.ts에서ptyCommand를 직접 전달합니다.
- 프로세스 레이어 타입 디커플링
- Supervisor 타입은 더 이상 agent에서
SessionStdin을 가져오지 않아요. - 프로세스 로컬 stdin 계약은
src/process/supervisor/types.ts(ManagedRunStdin)에 위치합니다. - 어댑터는 이제 프로세스 레벨 타입에만 의존해요:
src/process/supervisor/adapters/child.tssrc/process/supervisor/adapters/pty.ts
- 프로세스 도구 수명 주기 소유권 개선
src/agents/bash-tools.process.ts는 이제 supervisor를 통해 먼저 취소를 요청합니다.process kill/remove실행 시 supervisor에서 조회가 실패하면 process-tree 폴백 종료 방식을 사용해요.remove는 종료 요청 직후에 실행 중인 세션 항목을 즉시 제거하여 결정론적인 삭제 동작을 유지합니다.
- 단일 소스 기반의 Watchdog 기본값
src/agents/cli-watchdog-defaults.ts에 공유 기본값을 추가했습니다.src/agents/cli-backends.ts에서 이 공유 기본값을 사용해요.src/agents/cli-runner/reliability.ts에서도 동일한 공유 기본값을 사용합니다.
- 미사용 헬퍼 정리
src/agents/bash-tools.shared.ts에서 사용하지 않는killSession헬퍼 경로를 제거했습니다.
- 직접적인 Supervisor 경로 테스트 추가
- supervisor 취소를 통한 kill 및 remove 라우팅을 확인하기 위해
src/agents/bash-tools.process.supervisor.test.ts를 추가했습니다.
- 안정성 공백 해결 완료
src/agents/bash-tools.process.ts는 이제 supervisor 조회가 실패할 경우 실제 OS 레벨의 프로세스 종료 방식을 사용합니다.src/process/supervisor/adapters/child.ts는 기본 취소/타임아웃 kill 경로에 process-tree 종료 의미론(semantics)을 사용해요.src/process/kill-tree.ts에 공유 process-tree 유틸리티를 추가했습니다.
- PTY 계약 엣지 케이스 커버리지 추가
- PTY 커맨드의 그대로의 전달(verbatim forwarding) 및 빈 커맨드 거절을 테스트하기 위해
src/process/supervisor/supervisor.pty-command.test.ts를 추가했습니다. - child 어댑터 취소 시의 process-tree kill 동작을 위해
src/process/supervisor/adapters/child.test.ts를 추가했습니다.
4. 남은 과제 및 결정 사항
섹션 제목: “4. 남은 과제 및 결정 사항”안정성 상태
섹션 제목: “안정성 상태”이번 패스에서 필요했던 두 가지 안정성 공백이 해결되었습니다:
process kill/remove실행 시 supervisor 조회가 실패하면 실제 OS 종료 폴백이 작동합니다.- child 취소/타임아웃 시 기본 kill 경로로 process-tree kill 방식을 사용합니다.
- 두 동작 모두에 대해 회귀 테스트가 추가되었습니다.
지속성 및 시작 시 조정(Reconciliation)
섹션 제목: “지속성 및 시작 시 조정(Reconciliation)”재시작 동작은 이제 명시적으로 메모리 내 수명 주기로만 정의됩니다.
src/process/supervisor/supervisor.ts의reconcileOrphans()는 의도적으로 아무 작업도 수행하지 않는 no-op 상태를 유지해요.- 프로세스 재시작 후에는 활성 실행 상태가 복구되지 않습니다.
- 이는 부분적인 지속성(persistence)으로 인한 리스크를 피하기 위해 이번 구현 패스에서 의도적으로 설정한 경계입니다.
유지보수 후속 작업
섹션 제목: “유지보수 후속 작업”src/agents/bash-tools.exec-runtime.ts의runExecProcess는 여전히 여러 책임을 가지고 있어서, 나중에 집중화된 헬퍼들로 분리할 수 있습니다.
5. 구현 계획
섹션 제목: “5. 구현 계획”필수적인 안정성 및 계약 항목에 대한 구현 패스가 완료되었습니다.
완료된 항목:
process kill/remove폴백 실제 종료 구현- child 어댑터 기본 kill 경로에 process-tree 취소 적용
- 폴백 kill 및 child 어댑터 kill 경로에 대한 회귀 테스트
- 명시적
ptyCommand하에서의 PTY 커맨드 엣지 케이스 테스트 reconcileOrphans()no-op 설계를 통한 명시적인 메모리 내 재시작 경계 설정
선택적 후속 작업:
- 동작 변경 없이
runExecProcess를 집중화된 헬퍼들로 분리
6. 파일 맵
섹션 제목: “6. 파일 맵”Process supervisor
섹션 제목: “Process supervisor”src/process/supervisor/types.ts: discriminated spawn input 및 프로세스 로컬 stdin 계약으로 업데이트되었습니다.src/process/supervisor/supervisor.ts: 명시적인ptyCommand를 사용하도록 업데이트되었습니다.src/process/supervisor/adapters/child.ts및src/process/supervisor/adapters/pty.ts: agent 타입으로부터 분리되었습니다.src/process/supervisor/registry.ts: 멱등성을 가진 finalize 로직은 변경 없이 유지되었습니다.
Exec 및 프로세스 통합
섹션 제목: “Exec 및 프로세스 통합”src/agents/bash-tools.exec-runtime.ts: PTY 커맨드를 명시적으로 전달하고 폴백 경로를 유지하도록 업데이트되었습니다.src/agents/bash-tools.process.ts: 실제 process-tree 폴백 종료와 함께 supervisor를 통해 취소하도록 업데이트되었습니다.src/agents/bash-tools.shared.ts: 직접적인 kill 헬퍼 경로가 제거되었습니다.
CLI 안정성
섹션 제목: “CLI 안정성”src/agents/cli-watchdog-defaults.ts: 공유 베이스라인으로 추가되었습니다.src/agents/cli-backends.ts및src/agents/cli-runner/reliability.ts: 이제 동일한 기본값을 사용합니다.
7. 이번 패스의 검증 실행
섹션 제목: “7. 이번 패스의 검증 실행”Unit 테스트:
pnpm vitest src/process/supervisor/registry.test.tspnpm vitest src/process/supervisor/supervisor.test.tspnpm vitest src/process/supervisor/supervisor.pty-command.test.tspnpm vitest src/process/supervisor/adapters/child.test.tspnpm vitest src/agents/cli-backends.test.tspnpm vitest src/agents/bash-tools.exec.pty-cleanup.test.tspnpm vitest src/agents/bash-tools.process.poll-timeout.test.tspnpm vitest src/agents/bash-tools.process.supervisor.test.tspnpm vitest src/process/exec.test.tsE2E 대상:
pnpm vitest src/agents/cli-runner.test.tspnpm vitest run src/agents/bash-tools.exec.pty-fallback.test.ts src/agents/bash-tools.exec.background-abort.test.ts src/agents/bash-tools.process.send-keys.test.ts타입 체크 참고:
- 이 레포지토리에서는
pnpm build(전체 lint/docs 검사는pnpm check)를 사용하세요.pnpm tsgo를 언급하는 이전 노트들은 이제 유효하지 않습니다.
8. 유지된 운영 보장 사항
섹션 제목: “8. 유지된 운영 보장 사항”- Exec 환경 강화(hardening) 동작은 변경되지 않았습니다.
- 승인 및 허용 목록(allowlist) 흐름은 변경되지 않았습니다.
- 출력 정리(sanitization) 및 출력 제한(caps)은 변경되지 않았습니다.
- PTY 어댑터는 강제 종료 및 리스너 폐기 시 여전히 대기 정착(wait settlement)을 보장합니다.
9. 완료 정의 (Definition of Done)
섹션 제목: “9. 완료 정의 (Definition of Done)”- Supervisor가 관리되는 실행 건에 대한 수명 주기 소유권을 가집니다.
- PTY spawn은 argv 재구성 없이 명시적인 커맨드 계약을 사용합니다.
- 프로세스 레이어는 supervisor stdin 계약을 위해 agent 레이어에 대한 타입 의존성을 가지지 않습니다.
- Watchdog 기본값이 단일 소스에서 관리됩니다.
- 타겟팅된 유닛 및 e2e 테스트가 통과(green) 상태를 유지합니다.
- 재시작 지속성 경계가 명시적으로 문서화되었거나 완전히 구현되었습니다.
10. 요약
섹션 제목: “10. 요약”이제 이 브랜치는 더 일관성 있고 안전한 관리 구조를 갖추게 되었습니다.
- 명시적인 PTY 계약
- 더 깔끔해진 프로세스 레이어링
- 프로세스 작업을 위한 supervisor 기반 취소 경로
- supervisor 조회가 실패할 경우의 실제 폴백 종료 처리
- child 실행 기본 kill 경로에 대한 process-tree 취소 적용
- 통합된 watchdog 기본값
- 명시적인 메모리 내 재시작 경계 (이번 패스에서는 재시작 시 고립된 프로세스 조정을 하지 않음)
다음 단계
섹션 제목: “다음 단계”OpenClaw Expert
아직 막혀 있나요?
이 문서에서 답을 못 찾았다면 OpenClaw Expert에게 바로 물어보세요.