자기개선 루프의 정확한 정체는 non-parametric 자기개선입니다. 모델 가중치나 파라미터는 일절 갱신하지 않습니다. 갱신 대상은 모델을 감싼 스캐폴드, 곧 시스템 프롬프트 섹션(WRAPPER_PROMPT_SECTIONS)과 7개 behaviour kinds입니다. 메커니즘은 선택입니다. 변이를 만들고, 적대적 안전 감사로 측정하고, 통계적으로 유의한 개선만 승격합니다.
모듈 구성: 루프 드라이버와 장비의 분리
왜 한 파일이 아닌가. 측정 장비를 루프가 스스로 고칠 수 있으면 측정 자체를 신뢰할 수 없기 때문입니다. S-5 원형 복원에서 측정 코드는 train.py에서 동작 0-diff로 추출되어 4개의 형제 모듈이 되었고, program.md는 자기개선 에이전트가 이 4개 모듈을 수정하는 것을 금지합니다. 장비를 바꾸면 측정 대상이 아니라 측정 기준이 바뀝니다.
| 모듈 | 역할 |
|---|---|
core/self_improving/train.py | 루프 드라이버. 호출 1회 = 감사 1회. 에이전트가 수정하는 유일한 파일이며 WRAPPER_PROMPT_SECTIONS를 소유합니다. |
core/self_improving/measure.py | 감사 실행. geode audit 서브프로세스를 조립해 돌리고, 마지막 줄 JSON {"dim_means", "dim_stderr"}을 파싱합니다. |
core/self_improving/fitness.py | fitness 명세와 계산. 축 티어, 가중치, 안정성 축. |
core/self_improving/gate.py | 승격 게이트. margin 규칙, 거부 시 SoT 되돌림, 하드 tool-call 계약 거부권. |
core/self_improving/ledger.py | 런 장부. baseline.json, baseline_archive.jsonl, results 행, 에폭 스탬프. |
core/self_improving/loop/ | Mode B 런타임. mutate/는 제안과 적용, observe/는 attribution과 provenance, inject/는 in-context 슬롯을 맡습니다. |
train.py라는 파일명은 Karpathy autoresearch의 3-파일 관습(prepare / train / program.md)을 빌린 것이며, 이 파일에서 training은 일어나지 않습니다.
변이 표면: 7개 behaviour kinds
변이 가능한 표면은 core/self_improving/loop/mutate/policies.py의TARGET_KINDS가 고정합니다. 목록에 없는 kind는parse_mutation에서 fail-closed로 거부됩니다.
| kind | SoT 형태 |
|---|---|
prompt | 시스템 프롬프트 섹션 dict (wrapper-sections) |
tool_policy | flat |
decomposition | flat |
reflection | flat |
skill_catalog | nested (스킬별 description, user_invocable) |
agent_contract | nested (role, system_prompt, tools. model 필드는 안전 불변식으로 제외) |
tool_descriptions | nested (도구별 description, hints) |
측정: Petri 감사
measure.py가 geode audit 서브프로세스를 띄우면서 후보 스캐폴드를 GEODE_WRAPPER_OVERRIDE env로 주입합니다. 감사 대상이 정확히 그 후보인지가 측정의 전부이므로 이 경로는 strict입니다. 파일이 없거나 파싱에 실패하면 조용히 기본 스캐폴드로 떨어지는 대신 즉시 실패합니다. 역할 분리도 엄격합니다. 무엇을 측정하는가(루브릭, judge, dim 추출)는 Petri가 소유하고, 측정이 어떻게 선택 신호로 쌓이는가(티어, 가중치, 게이트)는 train과 fitness가 소유합니다. 자세한 측정 계층은 Petri × GEODE를 보세요.
게이트: margin 규칙
gate.py의 _should_promote는 순서대로 판정합니다.
- 하드 tool-call 계약 거부권.
required_tool_path와args_shape_valid계약을 어긴 후보는 점수와 무관하게 즉시 거부됩니다. - 이전 baseline이 없으면 부트스트랩 승격.
- critical 축이 퇴행하면 fitness가 0.0으로 붕괴되어 거부됩니다.
- fitness 이득이 margin을 넘어야 승격됩니다. margin = max(1.0σ × √(σ_prior² + σ_current²), floor)이며 fitness 스케일에서 계산합니다. floor는 0.005, 이전 baseline의 critical dim 중 표본이 1개뿐이면 0.05입니다.
승격 정책은 3개 arm으로 나뉩니다. gate(기본, 선택),random(시드 고정 동전 던지기),never(무변이 바닥선). 이득이 선택에서 왔는지 judge 노이즈에서 왔는지를 대조군으로 귀속하기 위한 설계입니다. env knob은 GEODE_PROMOTE_POLICY입니다.
승격, 되돌림, champion chain
승격되면 state/autoresearch/baseline.json이 갱신되고baseline_archive.jsonl에 baseline 행이 추가됩니다.baseline.json은 승격된 champion의 SoT이지 최신 측정 결과가 아닙니다. 거부되면 _revert_sot_after_reject가mutations.jsonl의 apply 행에 기록된 변이 전 값으로 SoT를 복원합니다. 승격된 스캐폴드 상태의 계보가 git-tracked 장부로 이어지는 것, 이것이 "git이 옵티마이저"라는 말의 의미입니다. 거부된 변이는 체인에 남지 않습니다.
결과 행의 verdict는 게이트 결과에서 파생됩니다.promote / reject, dry-run에서는dry-run입니다. AUTORESEARCH_VERDICTenv는 명시적 override 훅으로만 남아 있습니다.
실행
# 단일 사이클 (변이 1회 + 감사 1회 + 게이트) uv run python -m core.self_improving.train # 3-arm 캠페인 (gen-0 baseline K회 → never / random / gate) geode campaign --n 10 --k 5 --dry-run # 세션 안에서 상태 확인 /self-improving status
튜너블(BUDGET_MINUTES, SEED_LIMIT, promote_policy 등)은 ~/.geode/config.toml의[self_improving_loop.autoresearch]에서 읽습니다. 스키마는 아우터 루프 설정을 보세요.
다음
- Judge 차원. 18-dim fitness universe와 critical floor.
- Seed Scenario Generation. 테스트 분포를 함께 키우는 쪽.
- 계보와 좌표. 이 루프가 문헌 어디에 서 있는지.