자동 트리거는 자기개선 루프의 변이 러너 (SelfImprovingLoopRunner.run_once)를 스케줄러에 연결해, 키보드 앞에 운영자가 없어도 루프가 cron 주기로 도는 사이드카입니다. 구현은 core/self_improving/loop/auto_trigger.py, 배선은 core/wiring/scheduling.py의 build_scheduling입니다.
한때 이 자리에 있던 별도 자동화 파이프라인(drift 감지, 모델 프로모션, 전문가 패널이 있던 core/automation/)은 v0.99.149에서 삭제되었습니다. 그 체인의 모든 진입점이 emitter가 사라진 파이프라인 이벤트였고, 부팅마다 만들어지되 일을 하지 않는 구성물이었기 때문입니다. 지금 남아 있는 자동화는 이 페이지의 사이드카와 스케줄러가 전부입니다.
동작 방식
[self_improving_loop.scheduler] enabled=true (~/.geode/config.toml, 기본 off)
│ cron 발화 (trigger_id: self_improving_loop_auto_trigger)
▼
1. fcntl flock ~/.geode/autoresearch/handoff/auto_trigger.lock
│ 다른 보유자가 있으면 no-op (INFO 로그)
▼
2. 최소 간격 게이트 auto_trigger_last_run.txt
│ 직전 성공 발화가 min_interval_minutes 안이면 skip
▼
3. SelfImprovingLoopRunner.run_once (mutate → audit → gate)
│ 소스 디스패치는 [self_improving_loop.mutator].source 상속
▼
status dict 반환 (절대 raise하지 않음) + 히스토리 append세 가지 방어선이 핵심입니다. 락은 cron 발화 둘 또는 cron과 수동 실행이 같은 SoT 파일을 두고 경합하는 것을 막습니다. fcntl advisory lock이라 프로세스가 죽으면 커널이 자동 해제합니다. 인터벌 게이트는 재시작이나 클록 스큐로 cron이 과발화해도 바닥 주기를 지킵니다. 타임스탬프는 성공한 발화만 갱신하므로, 설정이 망가져 실패가 반복되어도 스케줄이 몇 시간씩 잠기지 않습니다. 마지막으로 모든 결과는 status dict로 돌아옵니다. 한 번의 발화 실패가 스케줄러 루프를 죽이지 못합니다.
설정
키 ([self_improving_loop.scheduler]) | 의미 |
|---|---|
enabled | opt-in 스위치. 기본 false면 register_auto_trigger가 no-op입니다 |
cron | 발화 주기 cron 표현식 |
min_interval_minutes | 성공 발화 간 최소 간격 |
max_generation | 누적 발화 세대 상한. 0이면 무제한 |
관측
| 표면 | 내용 |
|---|---|
HookEvent.SELF_IMPROVING_AUTO_TRIGGER_* | 발화 결과별 이벤트. FIRED, LOCK_BUSY, INTERVAL_BLOCKED, RUNNER_ERROR, PARSE_ERROR, MAX_GENERATION_REACHED (core/hooks/system.py) |
auto_trigger_history.jsonl | 발화 기록 append-only 로그 (~/.geode/autoresearch/handoff/) |
geode outer-bundle | 발화 기록을 mutations.jsonl, baseline.json과 교차해 하나의 타임라인으로 보여 주는 뷰어 (core/cli/outer_bundle.py) |
/schedule | 등록된 트리거 목록에서 self_improving_loop_auto_trigger로 식별 |
실패 모드
| 증상 | 원인 | 해법 |
|---|---|---|
| cron 시각에 아무 일도 없음 | enabled=false(기본) | ~/.geode/config.toml의 [self_improving_loop.scheduler]에서 켭니다. |
LOCK_BUSY가 반복 | 수동 실행이나 캠페인이 락을 보유 | 정상 동작입니다. 동시 발화는 의도적으로 no-op입니다. |
| 발화는 되는데 변이가 없음 | MAX_GENERATION_REACHED | max_generation을 올리거나 0으로 되돌립니다. |