experiment journal · 2026-07-09 · 실행 근거 기반

오늘 확정된 무누수 파이프라인 — wake → OBSERVED → trigger → sleep → package

각 노드는 세 칸으로 읽는다: 이상 기대치(설계가 요구하는 것) · 코드 위치(실제 구현 file:line) · 실측(오늘 런의 진짜 숫자 — runs/stageB_v3/logs/*.ledger.jsonl와 런 final에서 그대로 가져옴). 이 페이지의 모든 수치는 실제 아티팩트에서 검증된 것만 적었다.

01

깨어 있는 동안 — 4블록 프롬프트에서 행동까지

WAKE — 4블록 프롬프트 → 메커니즘 가설 → 행동

이상 기대치

에이전트는 (A) 환경 (B) 액션 API (C) 플레이 방법 (D) 세계모델+스킬 사용법, 딱 네 블록만 안다. 매 턴 “무엇이 무엇과 관계 맺는가”로 2-3개 메커니즘 가설(HYPOTHESIS:)을 세우고 가장 판별력 있는 하나에만 행동한다. 절대좌표 목표 금지.

코드 위치

ttso/auto/thin_run.py:56 (PROMPT 상수, 4블록) · 가설 규율은 블록 C(thin_run.py:90-99) · 한 라운드 = python 블록 1개, 지속 샌드박스에서 exec.

실측 (B1, 30라운드)

on_s1: 79액션으로 3레벨, on_s0: 35액션으로 1레벨 (runs/stageB_v3/logs/B1_on_*.log final). 시뮬레이션 상한 SIM_CAP=3/라운드, 클릭 상한은 턴마다 피드백에 명시.

↓ 매 행동은 진짜 엔진에 제출되고, 엔진의 다음 그리드만 관측으로 돌아온다

LEAK BOUNDARY — 프롬프트는 환경+API만 노출 (오늘 3개 표면 소거 완료)

이상 기대치

에이전트-대면 텍스트 어디에도 이 게임의 메카닉/승리조건 어휘가 없어야 한다. 프롬프트 주석 원문: “It exposes the ARC environment and the action API but NEVER this game's mechanics/win-condition — the agent DISCOVERS what an action does.”

코드 위치

ttso/auto/thin_run.py:52-55 (PROMPT 경계 주석) · ttso/eval/g2_run.py:60 (_MINER_CTX: 마이너에게도 인터페이스+“(hidden) win condition”만) · sleep 프롬프트 ttso/prompts/miner.txt·refine.txt.

실측 (커밋 타임라인)

표면 3개를 순차 제거: ① scaffold PROMPT/PROMPT_ACI 삭제 + miner/refine에서 coupled·distant·neighbours·toggle-family 어휘 제거(83ab400, 19:05) → ② WAKE_MODES/BOARD DRIFT 문구 중립화(같은 커밋) → ③ store 시드 렌즈의 COUPLED/orthogonal-neighbours/distant 어휘(a921b9c, 19:25). 이후 전 표면 프로그램 스윕 CLEAN(커밋 메시지 원문).

OBSERVED full-diff — 클릭이 바꾼 모든 셀을 에코

이상 기대치

클릭 셀만이 아니라 그 클릭이 실제로 바꾼 모든 셀(결합 이웃, 원거리 토글 포함)을 관측 라인으로 돌려준다 — 승리조건 읽기 없음, fork 없음. 결합/간접 동역학은 이 라인 없이는 학습 불가능했다.

코드 위치

ttso/auto/thin_run.py:188 (_diff_entry: 클릭셀 before→after 선두 + 나머지 변화셀을 맨해튼 거리순, DIFF_CAP=20) · 피드백 부착 thin_run.py:557 (“OBSERVED: …”, 라운드당 OBS_CAP=12 클릭).

실측 (sleep가 소비한 관측)

sleep 리포트의 observed 트랜지션: B1_on_s0 sleep#1에서 14개, B1_on_s1 sleep#4에서 21개. predict-verify 행 누계: B1_on_s0 16, B1_on_s1 22 (final의 2_eval_predict_verify_rows).

↓ 로깅된 실제 전이는 매번 MAP 메커닉으로 즉시 예측-검증된다

TRIGGER — surprise(예측 빗나감) 또는 stuck(레벨 무진행)

이상 기대치

둘 중 하나면 sleep: (a) 최고-credence 메커닉의 부분점수 예측 정확도가 실제 전이에서 τ=0.8 미만(surprise — 세계가 모델과 다르다) → 즉시, (b) 레벨 무진행 3턴 연속(stuck) + 새 증거 8개 이상 축적(ripe) → 발화. 그리드 novelty가 아니라 레벨 진행만이 stuck의 기준.

코드 위치

ttso/core/control.py:69 (control; stuck_k=3은 :42) · control.py:119 (force_sleep_on_mismatch, tau=0.8) · 평가 지점 ttso/eval/g2_run.py:282 (_check_transition; 임계 0.8은 :296) · 런 파라미터 g2_run.py:215 (cooldown 4, min_evidence 8).

실측 (sleep 발화 횟수)

30라운드 B1: on_s0 3회, on_s1 5회. 진행 중 B3(60라운드 상한, 라운드 50 시점): s0 9회, s1 6회 (각 ledger의 고유 sleep_index 수).

↓ sleep 진입 — 진짜 게임에는 아무것도 적용되지 않는 오프라인 구간
02

sleep — MINE → advantage → PARK → (다음 sleep) CONFIRM

MINE — 잔차(residual)를 겨냥한 후보 k=4 제안

이상 기대치

마이너는 현재 룰셋이 커버하지 못한 잔차 셀(관측됐지만 예측 안 되는 변화)을 명시적으로 겨냥해 mechanic 후보를 쓴다. 스텝 크기 ∝ 잔차: 잔차가 크면 구조적으로 다른 룰, 작으면 국소 수정.

코드 위치

ttso/sleep/mine.py:320 (mine) · 잔차 프롬프트 ttso/sleep/sleep.py:796 (_residual_prompt) · 스텝 크기 sleep.py:842 (_step_size) · 오케스트레이션 sleep.py:865 (sleep).

실측

sleep당 proposed=4 (k=4). 잔차 하강의 실례: B3_on_s0 L0 잔차 306셀 → 0셀 (sleep#0의 residual_before 306 → sleep#1의 residual_before 0); B1_on_s0은 residual 1.0 → 0.403 (ledger/sleep 리포트).

↓ 후보마다

GATE — advantage_on_union > 0 (fail-closed)

이상 기대치

후보가 라이브 룰셋 union의 predict-accuracy를 올릴 때만(ΔIG > 0) 통과. 잔차를 덮되 기존을 후퇴시키지 않으면 >0, 허위 셀만 발명하면 <0. fork도 oracle도 ground-truth 손실도 없다.

코드 위치

ttso/sleep/judge.py:384 (advantage_on_union = predict_accuracy(ruleset+[cand]) − predict_accuracy(ruleset)).

실측 (v3 전 런 합산)

mechanic 후보 판정: rejected 43 / parked 13; diff-검증 불가한 strategy 레코드는 별도로 accepted 24 (4개 ledger 집계, B3는 라운드 50 시점).

↓ 통과해도 커밋 아님

PARK — mine ≠ commit: 라이브러리 바깥에 주차

이상 기대치

mine 시점 buffer로 뽑힌 후보는 그 buffer에 과적합일 수 있다. 즉시 커밋하지 않고, 마이너가 본 트랜지션 키(mine_keys)를 스탬프해서 주차한다. 주차 스펙은 확정 전까지 세계모델에 보이지 않는다.

코드 위치

ttso/sleep/store.py:249 (park) · 주차 결정 지점 ttso/sleep/sleep.py:1014-1025.

실측 (ledger 원문)

B3_on_s0 sleep#0, fp a882f2ec6f: advantage 0.6216>0 → “PARKED for post-park confirm (not yet committed)”. v3 전 런 parked 13.

↓ 다음 sleep은 mining보다 먼저 CONFIRM 패스를 돈다

CONFIRM — 생성기가 못 본(post-park unseen) 트랜지션으로 재채점

이상 기대치

주차 이후 게임이 쌓은 트랜지션 중 mine_keys에 없는 것(strictly held-out)으로 advantage_on_union을 다시 잰다. >0이면 승격, ≤0이면 과적합으로 드롭 — 일반화한 룰만 라이브러리에 들어간다.

코드 위치

ttso/sleep/commit.py:49 (confirm) · CONFIRM-first 순서 ttso/sleep/sleep.py:904 · 승격/격리 store.py:271 (resolve).

실측 (ledger 원문)

B3_on_s0 sleep#1: adv 0.9086 > 0 on 4 post-park transition(s) the generator never saw → promote. v3 합산 confirmed 7 / dropped 3 (드롭 사유 원문: “overfit the mine-time buffer, does not generalize”).

↓ 승격된 레코드의 신념은 이후 실제 전이마다 갱신

BETA CREDENCE — 신념 = Beta 사후평균, 재적용은 idempotent

이상 기대치

credence = α/(α+β). 로깅된 실제 전이 하나당 부분점수(F1)로 α+=hit, β+=1−hit — 반쯤 맞으면 반만 인정. 같은 트랜지션 키는 두 번 세지 않는다(replay가 사후분포를 더블카운트하지 않음).

코드 위치

ttso/sleep/store.py:105-111 (alpha/beta 필드, credence 프로퍼티) · 갱신 store.py:289 (observe_transition; α+=credit은 :307).

실측

Stage-A A2 게이트(결정적 하네스): α 1.0 → 2.33, 동일 트랜지션 replay 후에도 2.33 (idempotent). 라이브 예: M1이 브리핑에 쓴 B3 mechanic의 credence 0.798 (/tmp/m1_summary.json).

↻ package — sleep의 산출물이 wake로 돌아간다

PACKAGE — 브리핑 렌더 → 매 라운드 피드백에 재주입

이상 기대치

확정 스킬을 credence 순으로, 지금 보드에서 when이 성립하는 것만 골라 브리핑으로 렌더(cap 8000자). 판별 probe는 VoI 게이트(EIG×가치 > RHAE 한계비용)를 통과할 때만 노출; 못 넘으면 “합의된 것에 커밋하라”로 바뀐다. wake가 이 브리핑을 실제로 읽고 써야 루프가 닫힌다.

코드 위치

ttso/sleep/package.py:107 (render) · 라운드마다 재렌더 ttso/eval/g2_run.py:202 (_package; 라이브 보드로 when-검색) · thin_run이 피드백 메시지에 부착.

실측 (M1 측정)

동일 보드·동일 프롬프트 쌍대 비교: 브리핑 arm 인용률 6/6 vs 무브리핑 0/6 vs 브리핑 전 라운드 0/12 — 재주입된 브리핑을 wake가 진짜로 사용한다 (/tmp/m1_summary.json; 상세는 experiments 페이지).

03

무결성 펜스 — fork 금지

FORK-BAN — Game.fork는 raise하도록 몽키패치, 종료 시 assert

이상 기대치

파이프라인 어느 경로도 진짜 엔진을 복제해 미리 돌려볼 수 없다. 스킬 검증은 전부 자기 세계모델 위의 predict-verify. 과거의 “WIN”이 fork-브루트포스 아티팩트였던 전력이 있으므로, 소프트 규약이 아니라 하드 펜스로 강제한다.

코드 위치

ttso/eval/g2_run.py:226-234 (_banned_fork: 호출 즉시 RuntimeError + 카운트) · g2_run.py:430 (assert fork_dep["n"] == 0) · 결과 필드 fork_dependence.

실측

완주한 모든 final에서 fork_dependence = 0: B1 on/off × seed 0/1 네 런 전부 (runs/stageB_v3/logs/B1_*.log 마지막 줄). 시도 자체가 0회 — raise가 아니라 카운터가 0.

경계 요약: 에이전트가 아는 것 = 4블록 프롬프트(환경+API) + 자기 관측 + 자기 브리핑. 에이전트가 못 하는 것 = 엔진 fork, 승리조건 읽기, 게임별 어휘가 실린 힌트 수신. 이 페이지의 각 실측 칸이 그 경계 안에서 나온 숫자다.