virtual-insanity
← 리포트 목록

launchd 일정성 리포트 4개 복구

2026-04-15 launchd [launchd, hermes-migration, reports, schedule]

launchd 일정성 리포트 4개 복구

시작 시각: 2026-04-15 16:08:07 KST

1. 현재 plist 원본 스냅샷

com.openclaw.morning-routine.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin"
  }
  "Label" => "com.openclaw.morning-routine"
  "ProgramArguments" => [
    0 => "/bin/bash"
    1 => "/Users/ron/.openclaw/skills/smart-home/scripts/tts_morning.sh"
  ]
  "StandardErrorPath" => "/Users/ron/.openclaw/logs/morning-routine.err.log"
  "StandardOutPath" => "/Users/ron/.openclaw/logs/morning-routine.log"
  "StartCalendarInterval" => {
    "Hour" => 6
    "Minute" => 30
  }
}

com.openclaw.weekly-report.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin"
  }
  "Label" => "com.openclaw.weekly-report"
  "ProgramArguments" => [
    0 => "/bin/bash"
    1 => "/Users/ron/.openclaw/skills/smart-home/scripts/tts_weekly.sh"
  ]
  "StandardErrorPath" => "/Users/ron/.openclaw/logs/weekly-report.err.log"
  "StandardOutPath" => "/Users/ron/.openclaw/logs/weekly-report.log"
  "StartCalendarInterval" => {
    "Hour" => 20
    "Minute" => 0
    "Weekday" => 0
  }
}

com.openclaw.kpi-daily.plist

{
  "Label" => "com.openclaw.kpi-daily"
  "ProgramArguments" => [
    0 => "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python"
    1 => "/Users/ron/.openclaw/workspace/scripts/ron_kpi_tracker.py"
  ]
  "StandardErrorPath" => "/Users/ron/.openclaw/logs/kpi_error.log"
  "StandardOutPath" => "/Users/ron/.openclaw/logs/kpi_daily.log"
  "StartCalendarInterval" => {
    "Hour" => 0
    "Minute" => 0
  }
}

com.openclaw.kpi-weekly.plist

{
  "Label" => "com.openclaw.kpi-weekly"
  "ProgramArguments" => [
    0 => "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python"
    1 => "/Users/ron/.openclaw/workspace/scripts/ron_kpi_tracker.py"
    2 => "--weekly"
  ]
  "StandardErrorPath" => "/Users/ron/.openclaw/logs/kpi_weekly_error.log"
  "StandardOutPath" => "/Users/ron/.openclaw/logs/kpi_weekly.log"
  "StartCalendarInterval" => {
    "Hour" => 9
    "Minute" => 0
    "Weekday" => 1
  }
}

2. 복사/Rewrite 내역

  • smart-home skill 복사: /Users/ron/.openclaw/skills/smart-home → /Users/ron/.hermes/skills/smart-home
  • 복사본 내부 OpenClaw 루트 문자열을 Hermes 루트로 보정(민감값 미출력).
  • plist 백업: /Users/ron/.hermes/backups/launchagents_20260415T160807

Rewrite 후 plist

com.openclaw.morning-routine.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    "PYTHONPATH" => "/Users/ron/.hermes/workspace/scripts:/Users/ron/.hermes/workspace/scripts/shared:/Users/ron/.hermes/workspace/scripts/pipeline"
  }
  "Label" => "com.openclaw.morning-routine"
  "ProgramArguments" => [
    0 => "/bin/bash"
    1 => "/Users/ron/.hermes/skills/smart-home/scripts/tts_morning.sh"
  ]
  "StandardErrorPath" => "/Users/ron/.hermes/logs/morning-routine.err.log"
  "StandardOutPath" => "/Users/ron/.hermes/logs/morning-routine.log"
  "StartCalendarInterval" => {
    "Hour" => 6
    "Minute" => 30
  }
  "WorkingDirectory" => "/Users/ron/.hermes/workspace"
}

com.openclaw.weekly-report.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    "PYTHONPATH" => "/Users/ron/.hermes/workspace/scripts:/Users/ron/.hermes/workspace/scripts/shared:/Users/ron/.hermes/workspace/scripts/pipeline"
  }
  "Label" => "com.openclaw.weekly-report"
  "ProgramArguments" => [
    0 => "/bin/bash"
    1 => "/Users/ron/.hermes/skills/smart-home/scripts/tts_weekly.sh"
  ]
  "StandardErrorPath" => "/Users/ron/.hermes/logs/weekly-report.err.log"
  "StandardOutPath" => "/Users/ron/.hermes/logs/weekly-report.log"
  "StartCalendarInterval" => {
    "Hour" => 20
    "Minute" => 0
    "Weekday" => 0
  }
  "WorkingDirectory" => "/Users/ron/.hermes/workspace"
}

com.openclaw.kpi-daily.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    "PYTHONPATH" => "/Users/ron/.hermes/workspace/scripts:/Users/ron/.hermes/workspace/scripts/shared:/Users/ron/.hermes/workspace/scripts/pipeline"
  }
  "Label" => "com.openclaw.kpi-daily"
  "ProgramArguments" => [
    0 => "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python"
    1 => "/Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py"
  ]
  "StandardErrorPath" => "/Users/ron/.hermes/logs/kpi_error.log"
  "StandardOutPath" => "/Users/ron/.hermes/logs/kpi_daily.log"
  "StartCalendarInterval" => {
    "Hour" => 0
    "Minute" => 0
  }
  "WorkingDirectory" => "/Users/ron/.hermes/workspace"
}

com.openclaw.kpi-weekly.plist

{
  "EnvironmentVariables" => {
    "HOME" => "/Users/ron"
    "PATH" => "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    "PYTHONPATH" => "/Users/ron/.hermes/workspace/scripts:/Users/ron/.hermes/workspace/scripts/shared:/Users/ron/.hermes/workspace/scripts/pipeline"
  }
  "Label" => "com.openclaw.kpi-weekly"
  "ProgramArguments" => [
    0 => "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python"
    1 => "/Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py"
    2 => "--weekly"
  ]
  "StandardErrorPath" => "/Users/ron/.hermes/logs/kpi_weekly_error.log"
  "StandardOutPath" => "/Users/ron/.hermes/logs/kpi_weekly.log"
  "StartCalendarInterval" => {
    "Hour" => 9
    "Minute" => 0
    "Weekday" => 1
  }
  "WorkingDirectory" => "/Users/ron/.hermes/workspace"
}

3. launchctl bootout/bootstrap

===== com.openclaw.morning-routine =====
$ launchctl bootout gui/501/com.openclaw.morning-routine
bootout_exit=0
$ launchctl bootstrap gui/501 /Users/ron/Library/LaunchAgents/com.openclaw.morning-routine.plist
Bootstrap failed: 5: Input/output error
Try re-running the command as root for richer errors.
bootstrap_exit=5
$ launchctl print gui/501/com.openclaw.morning-routine | head -40
Bad request.
Could not find service "com.openclaw.morning-routine" in domain for user gui: 501

## 4. 직접 1회 실행 검증(launchctl bootstrap 실패 보완)
launchctl bootstrap이 이 세션에서 error 5로 실패해 kickstart 대상 서비스가 등록되지 않았다. 따라서 rewrite된 ProgramArguments를 같은 stdout/stderr 경로로 직접 실행했다.

### com.openclaw.morning-routine direct run
```text
$ /bin/bash /Users/ron/.hermes/skills/smart-home/scripts/tts_morning.sh
exit_code=0
stdout_before=missing stdout_after=1776237061 1000
stderr_before=missing stderr_after=1776237058 270
--- stdout tail ---
/Users/ron/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
Traceback (most recent call last):
  File "<string>", line 5, in <module>
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_core.py", line 182, in __init__
    listen_socket, respond_sockets = create_sockets(interfaces, unicast, ip_version, apple_p2p=apple_p2p)
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_utils/net.py", line 451, in create_sockets
    listen_socket = new_socket(bind_addr=("",), ip_version=ip_version, apple_p2p=apple_p2p)
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_utils/net.py", line 291, in new_socket
    s.bind(bind_tup)
PermissionError: [Errno 1] Operation not permitted
[ERR] TTS 캐스팅 실패
[OK] 아침 루틴 완료
--- stderr tail ---
/Users/ron/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(

com.openclaw.weekly-report direct run

$ /bin/bash /Users/ron/.hermes/skills/smart-home/scripts/tts_weekly.sh
exit_code=1
stdout_before=missing stdout_after=1776237062 974
stderr_before=missing stderr_after=1776237061 270
--- stdout tail ---
/Users/ron/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(
Traceback (most recent call last):
  File "<string>", line 5, in <module>
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_core.py", line 182, in __init__
    listen_socket, respond_sockets = create_sockets(interfaces, unicast, ip_version, apple_p2p=apple_p2p)
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_utils/net.py", line 451, in create_sockets
    listen_socket = new_socket(bind_addr=("",), ip_version=ip_version, apple_p2p=apple_p2p)
  File "/Users/ron/Library/Python/3.9/lib/python/site-packages/zeroconf/_utils/net.py", line 291, in new_socket
    s.bind(bind_tup)
PermissionError: [Errno 1] Operation not permitted
[ERR] TTS 캐스팅 실패
--- stderr tail ---
/Users/ron/Library/Python/3.9/lib/python/site-packages/urllib3/__init__.py:35: NotOpenSSLWarning: urllib3 v2 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'LibreSSL 2.8.3'. See: https://github.com/urllib3/urllib3/issues/3020
  warnings.warn(

com.openclaw.kpi-daily direct run

$ /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python /Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py
exit_code=0
stdout_before=missing stdout_after=1776237062 504
stderr_before=missing stderr_after=1776237062 0
--- stdout tail ---

==================================================
📊 KPI 수집 실행 - 2026-04-15 16:11:02
==================================================

✅ 일일 KPI 저장 완료
   날짜: 2026-04-15
   ron: 0 done, 0 failed, 100% success
   codex: 0 done, 0 failed, 100% success
   cowork: 1 done, 0 failed, 100.0% success
   analyst-fundamental: 0 done, 0 failed, 100% success
   analyst-macro: 0 done, 0 failed, 100% success
   analyst-technical: 0 done, 0 failed, 100% success

   크론: 8/8 활성
--- stderr tail ---

com.openclaw.kpi-weekly direct run

$ /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/MacOS/Python /Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py --weekly
exit_code=0
stdout_before=missing stdout_after=1776237062 316
stderr_before=missing stderr_after=1776237062 0
--- stdout tail ---

==================================================
📊 주간 KPI 리포트 - 2026-04-15
==================================================
데이터 부족 (1일)

==================================================
📋 개선안
==================================================
✅ 개선 필요 영역 없음
--- stderr tail ---

5. 최종 plist 상태 / launchd 등록 상태

최종 plist 요약

label 스케줄 호출 스크립트 stdout/stderr OpenClaw 경로 잔존
com.openclaw.morning-routine 매일 06:30 /Users/ron/.hermes/skills/smart-home/scripts/tts_morning.sh /Users/ron/.hermes/logs/morning-routine*.log 0
com.openclaw.weekly-report Weekday=0, 20:00 /Users/ron/.hermes/skills/smart-home/scripts/tts_weekly.sh /Users/ron/.hermes/logs/weekly-report*.log 0
com.openclaw.kpi-daily 매일 00:00 /Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py /Users/ron/.hermes/logs/kpi_daily.log, kpi_error.log 0
com.openclaw.kpi-weekly Weekday=1, 09:00 /Users/ron/.hermes/workspace/scripts/ron_kpi_tracker.py --weekly /Users/ron/.hermes/logs/kpi_weekly*.log 0

최종 4개 plist와 대상 실행 스크립트에서 /Users/ron/.openclaw, ~/.openclaw 경로 grep 결과는 0건이다.

launchctl 결과

  • bootout: 기존 로드 제거는 성공했다.
  • bootstrap: 이 Codex 세션에서는 모든 대상이 Bootstrap failed: 5: Input/output error로 실패했다.
  • /tmp의 최소 테스트 plist(/bin/echo)도 동일하게 bootstrap error 5였으므로, plist 내용 문제라기보다 현재 실행 환경의 launchctl bootstrap 제한으로 판단한다.
  • kickstart: 서비스가 등록되지 않아 Could not find service, rc=113.
  • launchctl enable gui/501/<label>은 4개 모두 성공했고 print-disabled 기준 enabled 상태다.

재등록을 로컬 GUI 터미널에서 직접 실행할 수 있도록 보조 스크립트를 만들었다:

/Users/ron/.hermes/scripts/revive_launchd_reports.sh

6. 라이브 직접 실행 결과

launchd 등록이 막혀 kickstart는 못 했지만, rewrite된 ProgramArguments를 같은 로그 경로로 직접 1회 실행했다.

label 직접 실행 로그 증거 발송/도달 결과
com.openclaw.morning-routine exit 0 /Users/ron/.hermes/logs/morning-routine.log, .err.log 생성 TTS 캐스팅 단계에서 zeroconf socket PermissionError: [Errno 1] Operation not permitted, [ERR] TTS 캐스팅 실패; 스크립트는 [OK] 아침 루틴 완료 출력
com.openclaw.weekly-report exit 1 /Users/ron/.hermes/logs/weekly-report.log, .err.log 생성 TTS 캐스팅 단계에서 동일한 zeroconf socket PermissionError. 실제 스피커 도달은 실패
com.openclaw.kpi-daily exit 0 /Users/ron/.hermes/logs/kpi_daily.log, kpi_error.log 생성 /Users/ron/.hermes/logs/kpi_daily.json 생성. 2026-04-15 KPI 1건 저장, cron 8/8 활성으로 집계
com.openclaw.kpi-weekly exit 0 /Users/ron/.hermes/logs/kpi_weekly.log, kpi_weekly_error.log 생성 주간 KPI는 데이터 1일뿐이라 데이터 부족 (1일). 전송 로직 없음

7. 발송 경로 grep 결과

  • tts_morning.sh: Telegram이 아니라 Home Assistant/Google Home TTS 경로다. google_home_tts.sh, Home Assistant curl, docker exec homeassistant, pychromecast/zeroconf를 사용한다.
  • tts_weekly.sh: 동일하게 Home Assistant/Google Home TTS 경로다.
  • ron_kpi_tracker.py: send_dm, send_sector, Telegram 호출 없음. stdout/log와 ~/.hermes/logs/kpi_daily.json 저장만 수행한다.

특히 morning-routine은 현재 plist 기준으로 pipeline/morning_briefing.py --send가 아니라 smart-home TTS 루틴이다. 따라서 fed_liquidity oneliner + briefing 모음 Telegram 발송 여부는 이 plist로는 충족되지 않는다. fed-liquidity oneliner는 별도 pipeline/morning_briefing.py에 구현되어 있다.

8. 결과 표

label 스케줄 호출 스크립트 재기동 라이브 실행 발송경로
com.openclaw.morning-routine 매일 06:30 ~/.hermes/skills/smart-home/scripts/tts_morning.sh bootout OK, bootstrap 실패(error 5), enable OK 직접 실행 exit 0 Home Assistant/Google Home TTS. 현재 sandbox socket 제한으로 실제 캐스팅 실패
com.openclaw.weekly-report 일요일 20:00 (Weekday=0) ~/.hermes/skills/smart-home/scripts/tts_weekly.sh bootout OK, bootstrap 실패(error 5), enable OK 직접 실행 exit 1 Home Assistant/Google Home TTS. 현재 sandbox socket 제한으로 실제 캐스팅 실패
com.openclaw.kpi-daily 매일 00:00 ~/.hermes/workspace/scripts/ron_kpi_tracker.py bootout OK, bootstrap 실패(error 5), enable OK 직접 실행 exit 0 Telegram 없음. ~/.hermes/logs/kpi_daily.json + stdout log
com.openclaw.kpi-weekly 월요일 09:00 (Weekday=1) ~/.hermes/workspace/scripts/ron_kpi_tracker.py --weekly bootout OK, bootstrap 실패(error 5), enable OK 직접 실행 exit 0 Telegram 없음. stdout log. 데이터 7일 미만이라 주간 리포트는 부족 상태

9. 변경 파일 목록

  • /Users/ron/Library/LaunchAgents/com.openclaw.morning-routine.plist
  • /Users/ron/Library/LaunchAgents/com.openclaw.weekly-report.plist
  • /Users/ron/Library/LaunchAgents/com.openclaw.kpi-daily.plist
  • /Users/ron/Library/LaunchAgents/com.openclaw.kpi-weekly.plist
  • /Users/ron/.hermes/skills/smart-home/ 신규 복사본
  • /Users/ron/.hermes/scripts/revive_launchd_reports.sh
  • /Users/ron/.hermes/logs/kpi_daily.json
  • /Users/ron/knowledge-agent/400-reports/260415_launchd_schedules_revival.md

백업:

  • /Users/ron/.hermes/backups/launchagents_20260415T160807/

10. 남은 리스크 / 다음 조치

  1. 현재 세션에서는 launchctl bootstrap 자체가 막혀 4개 서비스가 launchd에 등록되지 않았다. 로컬 GUI 터미널에서 아래를 실행해야 실제 일정성이 살아난다.
/Users/ron/.hermes/scripts/revive_launchd_reports.sh
  1. morning-routine, weekly-report는 Telegram 리포트가 아니라 Google Home TTS 루틴이다. 해리가 원한 “아침 브리핑 Telegram 발송”이라면 plist를 pipeline/morning_briefing.py --send 또는 별도 wrapper로 바꾸는 후속 작업이 필요하다.
  2. kpi-daily, kpi-weekly도 Telegram 발송이 없다. “해리에게 도달”을 알림센터 기준으로 보려면 ron_kpi_tracker.pysend_sector('ops' 또는 'report') 연동 또는 wrapper가 필요하다.
  3. 직접 실행에서 TTS 캐스팅은 zeroconf socket 권한 문제로 실패했다. 일반 GUI launchd 환경에서는 달라질 수 있지만, 이 세션에서는 실제 스피커 도달을 확인하지 못했다.

자체평가

  • 정확성: 4.2/5 — plist rewrite, 스케줄/스크립트/로그/발송 경로 확인은 완료. 다만 launchctl bootstrap이 환경 제한으로 실패했다.
  • 완성도: 4.0/5 — Hermes 경로 파일은 준비됐지만 실제 launchd 등록은 미완료. 대신 보조 bootstrap 스크립트와 직접 실행 증거를 남겼다.
  • 검증: 4.4/5 — plutil, grep, 직접 실행, 로그, KPI JSON 생성까지 확인. 실제 launchd kickstart/스피커 도달은 실패.
  • 최소 변경: 4.6/5 — 대상 4개 plist와 필요한 smart-home 복사본만 변경.

종합: 4.3/5