tick
backend/services/heartbeat.py 가 schedule 에 따라 도는 async _tick(). 매 tick:
- 아빠가 지금 chat 중이면 skip (streaming guard, lesson 4).
- vault 자동 인덱싱 실행 (변경된 file 의 incremental ChromaDB update).
vault/todos/아래 Markdown task를 읽어.- 현재 시간 + 최근 context 와 함께 LLM 에 pass.
- LLM 이 행동 결정하면 실행 (Telegram 메시지, cwk-site post, 시장 데이터 fetch, 뭐든).
- 판단과 실행 결과를 heartbeat log와 task가 소유한 durable surface에 남겨.
왜 LLM 이 옳은 스케줄러
'every Monday morning unless holiday' 는 cron 으로 표현 어려움. 'when market closes red 3 days in a row' 는 어느 DSL 으로도 표현 어려움. LLM 이 todo + 세계 상태 + 최근 context 읽고 결정. scheduler 는 cron 아냐 — 판단이지.
Registry-first cron 프롬프트
Scheduled task 프롬프트 (weather brief, daily comment check, market dispatch 등) 는 Python 안 박지 않고 editable registry 에 살아. Admin 이 프롬프트 다시 쓰면 다음 tick 이 restart 없이 픽업. <app-data>/cron_jobs.json 의 cron snapshot 이 어느 registry 프롬프트가 언제 fire 했는지 기록해서 API endpoint 만으로 trail 디버깅 가능.
일반 heartbeat tick과 scheduled cron을 구분해. tick은 vault todo를 훑는 느슨한 판단 loop고, cron은 cron_jobs.json과 prompt registry에 등록된 정확한 trigger야. 둘 다 같은 brain fallback과 streaming guard를 쓰지만 task source와 실행 영수증은 달라.
긴 작업은 model의 한 turn 기억에 맡기지 않아. scheduled conversation에 stateful task를 붙이고 step status와 artifact를 durable store에 남겨. 다음 tick이나 rollover가 와도 unfinished task를 이어 갈 수 있어. heartbeat가 똑똑하다는 말은 매번 처음부터 다시 생각한다는 뜻이 아니야.