Skip to content

2주차 컨텍스트 엔지니어링 + 3주차 루프 #52

Merged
MinCha merged 26 commits into
next-step:joydaheechafrom
JoyDaheeCha:feature/misison2_and_3
Jul 15, 2026
Merged

2주차 컨텍스트 엔지니어링 + 3주차 루프 #52
MinCha merged 26 commits into
next-step:joydaheechafrom
JoyDaheeCha:feature/misison2_and_3

Conversation

@JoyDaheeCha

@JoyDaheeCha JoyDaheeCha commented Jul 15, 2026

Copy link
Copy Markdown

민창님 안녕하세요!
2주차와 3주차 과제 함께 리뷰 요청 드립니다
1주차와 달리 좀 많이 헤맸지만..! 덕분에 단순 채팅형을 벗어나서 좀 더 똑똑하게 ai 사용 과정을 설계할 수 있게 되어 기쁩니다!

skill 이 느려서 고민이었는데 랄프 루프로 속도 개선이 많이 되었습니다!

1. 컨텍스트 엔지니어링

1.1 고민한 사항 : 도메인 컨텍스트 주입 고민 -> 사용자마다 다양해질것 같아 일단 보류

  • 본 OS 는 "할일을 (1) AI가 자동으로 알맞은 카테고리에 넣어준다 (2) 계획을 세부적으로 짜고 수행을 잊지 않도록 리마인드해준다 (3)할 일을 너무 크게 잡았을 경우 잘게 쪼개도록 AI가 제안해준다"가 처음 컨셉이었습니다. 도메인관점에서는 컨텍스트로 주면 좋을 부분이 잘 떠오르지 않더라

1.2 본 과제에서 적용한 사항: 스킬에서 반복적으로 시간을 잡아먹는 부분을 컨텍스트로 분리

  • 일단은 할일메모(plan), 할일 완료처리(done), 할일 리스트업(list)에서 todo의 구조를 하나의 파일을 바라보도록 하여, 매번 각 스킬이 일일히 todo 구조를 분석하지 않도록 개선했습니다.
  • OS 로딩시 기본 컨텍스트가 3%, done 스킬 수행시 6% 였는데, 컨텍스트 최적화 후 5%로 줄었습니다 (이 부분은 기존에 OS가 너무 작아서 비교가 어려운게 아닐까 생각했습니다)

2. 루프

2.1 추후 추가로 구현할 루프

시스템 루프는 "반복할수록 시스템을 견고하게 만들어준다"라는 부분이 인상적이었습니다!

  • 제 OS는 사용자의 행동 패턴을 분석하여, 사용자가 실행하기 쉬운 단위로 TODO를 기록해주는게 목표이기때문에 추후 이 부분을 시스템 루프로 추가 에정입니다. (예를 들어 사용자가 집청소 라고 적어놓은 부분은 자꾸 미룬다면, 거실, 부엌, 서재 등 각 방별로 청소 todo를 분리)

2.2 본 과제 내 루프 구현사항

  • 단순루프

    • 사용자에게 특정 시각에 알럿을 줘서 OS에 할 일 기록하도록 촉진
    • TODO 현황 루프
    • 텔레그램 메시지 감지 루프
  • 탐지형 루프: notion 동기화 루프 , 텔레그램 리스너 health 체크,

  • 축적형 루프 - 스킬 로그 분석하여 OS 개발시 더 나은 방향 제안

3. 루프 다이어그램

세션 밖에서 스스로 도는 루프들의 동작 순서. 이 OS의 자동화는 설계 원칙
§7의 축으로 갈린다.

  • 탐지형(조정) 루프 — "이상·미처리 있나?"를 주기적으로 감지하고 반응 후 잊는다. 잘 돌수록 조용하다.
  • 축적형 루프 — 매 반복이 저장소에 한 겹씩 쌓고 나중에 회수한다. write 절반과 read 절반이 쌍을 이룬다.

노드 색상 범례 — 🔵 트리거/진입 · 🟢 정상·성공 · ⚪ 무소음·종료 · 🔴 경보·실패 · 🟡 축적 저장소


A · 탐지형(조정) 루프 — crontab 4종

주기 감지 → 반응 → 잊기. 버퍼를 0으로 드레인하거나 데몬을 지킨다. 평상시엔 로그도
알림도 없이 조용하고, 이상이 잡힐 때만 소리를 낸다.

flush-cron — outbox 재동기 · 15분마다

capture가 백그라운드로 던진 Notion 반영이 실패해 outbox에 남으면, 이 루프가 재전송해
"모두 동기" 상태로 수렴시킨다.

flowchart TD
  T(["cron · 15분마다"]):::trig --> R["capture-flush.sh 실행"]
  R --> Q{"outbox 비었나?"}
  Q -->|비었음| Z(["즉시 종료 · 무소음"]):::quiet
  Q -->|잔여 있음| S["Notion 재전송 시도"]
  S --> C{"flushed 있음?"}
  C -->|예| L["flush-cron.log 기록 (건수만)"]:::ok
  C -->|아니오| Z
  L --> Z
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef quiet fill:#eef2f6,stroke:#94a3b8,color:#475569;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
Loading

watchdog-cron — 데몬 감시 · 10분마다

telegram-listener가 언로드·비정상이면 KeepAlive만으론 조용히 죽는다. 다운을 감지해
폰에 알리고 자동 재시작한다(상태 전이에만 알림 — 디바운스).

flowchart TD
  T(["cron · 10분마다"]):::trig --> H{"state = running?"}
  H -->|healthy| RC{"직전이 down?"}
  RC -->|예 · 복구| N1["복구 통지 발송"]:::ok
  RC -->|아니오| SV["state 저장"]:::quiet
  N1 --> SV
  H -->|down| DB{"down 신규 전이?"}
  DB -->|예| N2["다운 경보 · 디바운스"]:::alert
  DB -->|아니오| RS["kickstart / bootstrap 재시작"]
  N2 --> RS
  RS --> OK{"재시작 성공?"}
  OK -->|예| SV
  OK -->|아니오| LG["로그 · 다음 주기 재시도"]:::alert
  LG --> SV
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef quiet fill:#eef2f6,stroke:#94a3b8,color:#475569;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
  classDef alert fill:#fee2e2,stroke:#ef4444,color:#7f1d1d;
Loading

digest-cron — 주간 집계 · 매주 일 20:00

할일 현황(상태 분포·카테고리·방치 draft)을 주 1회 요약해 폰으로 보낸다.
집계(결정론)와 발송(부작용)을 분리한다.

flowchart TD
  T(["cron · 매주 일 20:00"]):::trig --> A["digest-report.sh 집계"]
  A --> B{"요약 텍스트 있나?"}
  B -->|없음| Z(["스킵"]):::quiet
  B -->|있음| S["telegram-send.sh 발송"]
  S --> R{"발송 성공?"}
  R -->|성공| L1["digest-cron.log · 성공"]:::ok
  R -->|실패| L2["로그 · 스킵 (자격/네트워크)"]:::alert
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef quiet fill:#eef2f6,stroke:#94a3b8,color:#475569;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
  classDef alert fill:#fee2e2,stroke:#ef4444,color:#7f1d1d;
Loading

remind-cron — draft 재촉 · 매일 17:00

미처리 draft가 남아 있으면 매일 저녁 폰으로 리마인더를 쏜다. 세션 안 스킬(/remind)을
세션 밖 cron이 대신 호출한다.

flowchart TD
  T(["cron · 매일 17:00"]):::trig --> C["claude -p /remind"]
  C --> D["draft 항목 조회"]
  D --> Q{"미처리 draft 있나?"}
  Q -->|있음| S["telegram 리마인더 알럿"]:::ok
  Q -->|없음| Z(["조용히 종료"]):::quiet
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef quiet fill:#eef2f6,stroke:#94a3b8,color:#475569;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
Loading

B · 상시 데몬 루프 — launchd

cron처럼 깨었다 자는 게 아니라 launchd가 상시 띄워 둔다. getUpdates를 long-poll로 걸어
폰 명령이 오는 즉시 처리하고, 보안 3종(chat_id 화이트리스트 · 명령 화이트리스트 ·
eval 미사용)을 통과한 것만 실행한다.

telegram-listener — 인바운드 long-poll · 상시(KeepAlive)

flowchart LR
  B(["launchd 상시 데몬"]):::trig --> P["getUpdates long-poll · 25초"]
  P --> M{"메시지 도착?"}
  M -->|타임아웃| P
  M -->|도착| W1{"chat_id 화이트리스트?"}
  W1 -->|불일치| SK["스킵"]:::alert
  W1 -->|일치| W2{"허용 명령? (/capture /list /plan)"}
  W2 -->|아니오| RJ["거절 안내"]:::alert
  W2 -->|예| EX["로컬 스킬 실행 · eval 미사용"]:::ok
  EX --> RE["응답 발송"]
  RE --> OF["offset 전진 · 저장"]
  SK --> OF
  RJ --> OF
  OF --> P
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
  classDef alert fill:#fee2e2,stroke:#ef4444,color:#7f1d1d;
Loading

C · 축적형 루프 — 자기 관찰

이 레포의 유일한 순수 축적형 루프. 스킬을 부를 때마다 append-only 로그에 한 겹 쌓고(write),
나중에 /usage가 그 축적물을 회수해 사용 패턴을 낸다(read). 저장소는 커질수록 가치가 있어
드레인하지 않는다.

self-observation — PostToolUse 훅 → /usage

flowchart LR
  K["Skill 툴 실행"]:::trig --> HK["PostToolUse 훅 (log-skill-invocation)"]
  HK --> AP["한 줄 append · 시각 · #N · 스킬명"]
  AP --> LOG[("skill-invocations.log · append-only")]:::store
  LOG --> RD["/usage 호출"]:::trig
  RD --> AN["로그 분석"]
  AN --> OUT["자주쓰는 · 연쇄 · 유휴 스킬 표시"]:::ok
  classDef trig fill:#dbeafe,stroke:#3b82f6,color:#1e3a5f;
  classDef ok fill:#dcfce7,stroke:#22c55e,color:#14532d;
  classDef store fill:#fef3c7,stroke:#f59e0b,color:#78350f;
Loading

출처 · .claude/hooks/{flush,watchdog,digest,remind}-cron.sh · telegram-listener.sh ·
log-skill-invocation.sh · 스케줄 launchd/install.sh · 분류 축 context/design-principles.md §7

JoyDaheeCha and others added 26 commits July 15, 2026 13:17
레포에 박혀 있던 절대경로(/Users/joy/...)를 걷어내고, 설치 시점에
현재 clone 경로와 로그인 사용자명으로 자동 구성하도록 변경.

- launchd/install.sh 추가: plist를 heredoc으로 ~/Library/LaunchAgents에
  생성·로드 + remind-cron crontab 멱등 등록. 기존 심링크를 rm -f로 끊고
  실제 파일을 써서, 심링크를 통해 레포 plist가 되살아나는 것을 방지.
- launchd/uninstall.sh 추가: 데몬 언로드 + plist 삭제 + crontab 정리.
- com.joy.telegram-listener.plist 삭제: 절대경로가 커밋에 남지 않도록
  install.sh 생성으로 대체.
- restart-listener-on-change.sh: LABEL·LOG를 id -un / $(dirname) 기반으로
  동적 계산 (하드코딩 제거, install.sh가 만든 Label과 일치).
- README: "세션 밖 자동화 설치" 절 추가, 디렉터리 구조 갱신.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cache.sh(신규): notion.sh read(curl 동기 ~0.5s)를 매번 타던 조회를 로컬 read-model로
뺀다. stale-while-revalidate — 캐시가 신선하면 ~10ms 즉시 반환, 오래되면 백그라운드 갱신.

read-model = 순수 Notion 스냅샷 + 오버레이 2장(읽기 시점 _emit 한 곳에서 병합):
- outbox 오버레이: 아직 동기 안 된 "생성"(방금 캡처) 항목을 스냅샷 위에 얹어 즉시 노출.
- pending-done 오버레이: 아직 Notion 확인 안 된 "완료"를 낙관적으로 done 표시.
스냅샷은 순수 유지 → 백그라운드 refresh와 done이 서로 덮어쓰는 레이스 원천 차단.

list-view.sh: 항목 조회를 notion.sh 직접 호출 → cache.sh read로 전환. 상태 필터는
전체 반환 후 jq 단에서 거른다.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
텔레그램 /capture: 기본 케이스의 claude -p 콜드스타트(실측 10.5s)를 우회하고
결정론 bash 경로로 처리(~0.03s). telegram-listener에 /capture) 케이스 추가(/list와
동일 패턴). 보안 3종(chat_id·명령 화이트리스트·eval 미사용) 유지 — 인자로만 전달.

- classify.sh(신규): 사전 기반 카테고리 분류(모델 0). bash 3.2 호환, "가장 긴 매칭
  키워드 우선" 규칙으로 부분매칭 모호성(약속 vs 약) 완화.
- capture.sh(신규): 입력→분류→저장→노티스 결정론 엔트리.
- capture-fast.sh(신규): 동기 Notion write(~0.48s) 대신 로컬 outbox 즉시 저장 +
  detached 백그라운드 동기. 실패 시 outbox 잔류 → capture-flush.sh(신규) 재시도(유실 방지).
- capture/SKILL.md: 분류 서브에이전트 제거, 저장 비동기화, 두 실행 경로(대화형 메인
  인라인 분류 vs 텔레그램 classify.sh 사전 분류, 저장은 capture-fast.sh 공유) 문서화.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
done-fast.sh(신규): 완료 처리를 read-model 위에서 낙관적으로 즉시 반영한다.
cache.sh mark-done으로 pending-done 오버레이에 id를 넣어 /list·/done에 곧바로 done으로
보이게 하고, Notion status 업데이트는 백그라운드로 던진다. → 네트워크 대기 없이 완료 UX.

done/SKILL.md: 위 흐름에 맞춰 절차 갱신.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tests/smoke_crud.sh: capture→list→plan→done 흐름의 로컬 스모크 테스트.
tests/coverage.sh: 스킬·훅·데이터 파일 대비 테스트 커버리지 점검.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sync-readme 스캔 결과 실제 존재하는 _shared/state-sync-writer.md가
문서에서 누락돼 있어, 에이전트 종류 표·디렉터리 트리·공유 설명에 등록.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
캐시가 없는 cold 경우에만 타던 동기 네트워크(~0.68s)를 SessionStart
훅의 프리워밍으로 제거하는 방식과, 모델 추론 턴이라는 물리적 바닥으로
end-to-end 1초 보장이 불가능하다는 한계를 함께 문서화.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tasks.json·clarified-specs.json·cache/·outbox/ 은 사용자 개인
할일 데이터와 로컬 캐시라 커밋 대상이 아님. secret·로그류를 개별
무시하던 기존 규칙과 같은 맥락으로 무시 처리.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
같은 지식이 스킬·서브에이전트·셸 스크립트에 복제돼 하나 바꾸면 전부
손봐야 하던 문제를 정본(Single Source of Truth)으로 해소한다.

- .claude/context 신설 ("읽히는 지식" 전용):
  data-model / categories / status-lifecycle / design-principles / security
- 연결 방식 A(스킬별 참조): 각 SKILL.md·서브에이전트 상단에 참조 블록 추가
  → 해당 스킬 실행 시에만 로드, 평상시 토큰 비용 없음
- capture SKILL의 잘못된 "분류 단일 출처" 서술을 categories.md로 정정

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
"안 읽으면 사고"가 나는 안전 정본만 무조건 보장이 필요하므로, Lazy(스킬별
Read)에서 Eager(상시 주입)로 승격한다. 나머지 4개 정본은 Lazy 유지(하이브리드).

- CLAUDE.md: @.claude/context/security.md 상시 주입 + "상시 주입 정본" 섹션
- remind/SKILL.md: security를 Lazy Read 목록에서 제외, 상시 주입됨을 명시(중복 Read 방지)
- context/README.md: 연결 방식을 하이브리드로 갱신(로딩 컬럼 + 승격/강등 기준)

검증: 새 헤드리스 세션에서 security 불변 규칙은 컨텍스트에 로드됨(본문 그대로 인용),
status-lifecycle 본문은 미로드 — Eager/Lazy 대조 확인 완료.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SKILL.md는 매 실행 컨텍스트에 로드되므로 실행에 필요한 지시만 남기고,
속도 최적화의 "왜"(조회 캐시화·완료 크리티컬 패스 제거 등 배경 설명)는
런타임 미로드 문서 NOTES.md로 뺐다. 참조 정본도 로직 수정·디버깅 때만 Read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- "언제 무엇이 컨텍스트 창에 들어오나"를 시간축(시퀀스)·순간별 스냅샷으로 도식화
- Eager(security.md)/Lazy(4종)를 시점·주체·상주기간으로 대비
- §2에 스킬·에이전트별 참조 정본 표 + grep 재검증 팁 수록
- 주입 한 주제에 집중 (폴더 성격·지식그래프·갱신규칙은 README 소관)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
정본 컨텍스트가 실제 "주입 배선"에 걸려 있고 문서와 현실이 일치하는지 결정적으로
검증한다. lint.sh(파일 무결성)가 못 보는 배선 무결성을 커밋 전에 잡는다.

- 검사 5종: Eager @import 존재·비어있지 않음(0바이트 빈 주입 포함), 고아 정본,
  context-map 소비자표 ↔ 실제 참조 양방향 드리프트, README Eager 표기 정합성
- 소비자는 하드코딩 대신 실제 파일 존재로 동적 해석 → 표에 가짜 행을 넣어 검증을
  우회하는 것을 차단하고, 해석 불가한 이름은 건너뛰지 않고 실패시킨다
- 표 파서가 깨지면(헤더/열 변경) 무더기 오탐 대신 "파서 못 찾음/열 불일치"로 명확히 실패
- run-tests.sh L1 게이트에 편입(CI l1+l2 자동 포함), tests/README에 계층·알려진 한계 문서화

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sync-readme가 README 전문(13.7KB)과 디렉터리 트리를 메인 컨텍스트에서 직접 Read하던
것을, 읽기 전용 공유 서브에이전트 state-scanner에 위임한다. 스캐너가 자기 컨텍스트에서
스캔·비교를 흡수하고, 메인에는 압축된 "사실 + 불일치" 두 블록만 반환한다.

- 신규 _shared/state-scanner.md: writer와 대칭인 수집 담당 공유 서브에이전트.
  입력 계약(스캔 지시·비교 대상·도메인 관심사) + 불변 규칙(읽기 전용, 원자료 통째
  반환 금지, 비밀값 존재만). "반환 텍스트가 곧 산출물" 명시로 빈 응답(스텁) 방지.
- sync-readme Step1·2(스캔+README Read)를 스캐너 위임으로 교체 → 메인 흡수
  ~5,108토큰 → ~513토큰(89%↓). writer가 어차피 자기 컨텍스트에서 README를 다시
  읽으므로 메인이 중계할 필요가 없다는 게 핵심.
- context-map 소비자표에 state-scanner 행 추가(정본 참조 design-principles 1종).

측정 근거: OLD=스캔4177B+README13703B, NEW=스캐너 압축 반환 1797B.
sync-test는 grep-only(스캔 271토큰)라 위임 시 서브에이전트 비용이 이득을 초과 →
의도적으로 미적용(위임 손익분기: 메인 절감 × 잔존시간 vs 서브에이전트 컨텍스트 비용).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Eager 정본(CLAUDE.md + @import 대상)은 스킬 실행과 무관하게 매 세션 항상 컨텍스트
창에 상주하므로, 여기가 커지면 모든 세션이 그 비용을 영구히 부담한다. "정말 모든
상황에서 필요한가"를 통과 못 한 내용이 슬그머니 Eager로 승격되는 회귀를 L1에서 잡는다.

- @import 목록을 하드코딩하지 않고 CLAUDE.md에서 동적 파싱 → 새 Eager import 자동 포함
- 주 게이트=근사 토큰(EAGER_MAX_TOKENS 기본 1200), 보조=줄 수(EAGER_MAX_LINES 기본 80)
- 초과 시 상한 조정이 아니라 "Lazy로 내릴 내용 재심사"를 유도하는 실패 메시지
- run-tests.sh L1에 편입(lint+inject+budget), tests/README에 inject와의 역할 분담 문서화
- inject.sh(배선 존재)와 상보: budget은 그 배선의 페이로드 크기를 본다

현재 Eager 50줄·783토큰(상한 내). 음성테스트(상한 100→exit 1)로 게이트 실동작 확인.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sync-readme가 scanner→writer 두 서브에이전트를 거치던 것을, 스캔·비교·갱신을 한 창에서
끝내는 readme-sync-agent 한 곳에 위임하도록 통합한다. 서브에이전트를 두 번 열면 메인은
가벼워져도 총 토큰이 오히려 늘고(직전: scanner~42k + writer~40k ≈ 82k), README 갱신은
"스캔한 사실을 그대로 옮기는" 단순 전사라 수집·작성을 나눌 실익이 없었다.

- 신규 _shared/readme-sync-agent.md: 스캔+대상 Read+최소 diff 갱신+요약 반환을 자기 창에서
  전부 수행. 원자료를 메인으로 중계하지 않아 총 토큰 ~42k, 메인 흡수 수십 토큰.
- _shared/state-scanner.md 삭제(통합으로 대체). state-sync-writer는 유지 — 사람이 중간에
  "자동 채움/보고만"을 결정하는 sync-test가 여전히 수집·작성 분리를 필요로 하기 때문.
- context-map §1-3/§1-4/§2를 readme-sync-agent로 정정. §1-4에 "위임은 서브에이전트 창을
  통째로 여는 비용이 있다"는 한계를 명시(89%↓만 강조하던 서술 교정) — 메인이 큰 파일을
  Read할 때만, 또 창을 한 번만 열 때만 이득임을 남긴다.
- state-sync-writer/sync-test 문서의 "sync-readme도 재사용" 서술 정정.

검증: L1(lint·inject·budget) + L2 = 33+9+2+13 pass / 0 fail. state-scanner 잔존 참조 0건.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
inject.sh(배선 존재)와 상보적으로, 정본 주입이 스킬 "동작"을 실제로 바꾸는지를
통제 실험으로 측정한다. 분류 정본 categories.md 주입 有無(Arm A/B)를 같은 모델·
같은 입력 12종·각 3회(72관측)로 대조.

- tests/ab-injection/: 정답셋(ground-truth.tsv)·원자료(raw-runs.tsv)·재현 채점기
  (score.sh)·설계/결과 문서(README.md). 채점은 손계산이 아닌 TSV 재계산이라 검증 가능.
  결과: 정확도 50.0%→97.2%, 6종 어휘 준수 50.0%→100%, 3회 일관성 58.3%→91.7%,
  함정 항목 22.2%→88.9%. 미주입 arm은 스키마 밖 라벨 8종을 지어내 list-view 그룹핑을 깸.
- tests/README.md: ab-injection을 "게이트 아닌 1회성 효과 측정"으로 인덱스에 연결
  (inject=배선 존재 / ab-injection=효과, 상보 관계 명시).
- docs/mission-2-report.md: 미션 5개 과제(필수 3+도전 2) 과제별 판정·근거 리포트.
  GitHub 웹 렌더링용 마크다운(유니코드 막대로 A/B 시각화, mermaid 미지원 환경도 무해).

검증: L1(lint 35 + inject 9 + budget 2) pass / 0 fail. 리포트 상대링크 7개 실재 확인.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
자기 관찰 루프의 write 절반을 배선한다. 그동안 skill-invocations.log는
security.md 정본에 등록만 돼 있고 실제로 기록하는 코드가 없어 6/25 이후
멈춰 있던 고아 로그였다. PostToolUse(matcher=Skill) 훅으로 스킬 실행 시마다
"시각 | #N | 스킬명" 한 줄을 append 해 로그를 되살린다.

동시에 구조적 틈을 메운다: 훅 스크립트는 커밋돼 있었지만 이를 활성화하는
배선(hooks 설정)은 gitignore된 settings.local.json 에만 있어 clone 시
재현되지 않았다. 공유 hooks 블록을 tracked settings.json 으로 승격하고,
개인 permissions 만 settings.local.json 에 남긴다(Claude Code가 둘을 병합).
이제 OS 배선이 repo 안에서 재현된다 — CLAUDE.md의 "OS 파일은 프로젝트
안에" 원칙에 부합.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
매 커밋 직전에 결정적 테스트(run-tests.sh l1 l2, ~1초)를 돌려, 정본이 실제
상태와 어긋난 채 커밋되는 것을 구조적으로 막는다. L1 이 끊어진 참조 링크
(lint) · 정본 주입 배선 끊김/고아 정본/지도 드리프트(inject) · Eager 상주
정본 크기 회귀(context-budget)를 잡고, L2 가 detect-todo.js 계약을 검증한다.
자격증명·LLM 이 필요한 L3(smoke)는 게이트에서 제외 — 느리고 비결정적이라
매 커밋 게이트엔 부적합.

재현성 — .git/hooks 는 버전 관리가 안 돼 클론 시 훅이 사라진다. 훅을 추적되는
.claude/githooks 에 두고 git 의 core.hooksPath 로 연결한다. 클론한 사람은
'bash .claude/githooks/install.sh' 한 번이면 게이트가 산다(uninstall.sh 로 해제).
settings.json 승격과 같은 "배선을 repo 안에서 재현" 원칙.

검증 완료: 고아 정본을 만들어 커밋 시도 → L1 FAIL 로 차단, HEAD 불변 확인.
긴급 우회는 git 네이티브 --no-verify 로 가능.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
log-skill-invocation.sh(write 절반)가 쌓은 skill-invocations.log 를 읽어
사용 패턴을 뽑는다. 이로써 "관찰 → 개선" 루프가 닫힌다.

usage-report.sh(결정론적 공유 스크립트)가 세 가지를 뽑는다:
  ① 빈도  — 자주 쓰는 스킬 순위 (별칭·고속화 후보)
  ② 연쇄  — 바로 이어 부른 쌍(capture→plan 등), 임계 이상 반복 시 콤보 제안
  ③ 유휴  — 등록됐지만 호출 이력 없는 스킬 (폐기·점검 후보)
/usage 스킬은 이 스크립트를 1회 실행하고 출력을 verbatim relay 한다
(/skills·/remind-when 과 같은 "정본 직독 + 결정론 조회" 패턴).

정직한 한계: 로그에 성공/실패 필드가 없어 "실패 반복"은 감지 못 한다.
원하면 write 훅이 tool_response 상태까지 남기도록 스키마를 넓혀야 한다(후속).

검증: 실제 로그(2줄)→"표본 얕음" 경고, 풍부한 합성 로그(11줄)→빈도·연쇄·
콤보 제안·유휴 세 섹션 모두 정확 출력 확인(테스트 후 로그 원상복구).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/sync-readme 로 파일시스템을 스캔해 이번 세션의 추가분을 README에 반영:
  - 스킬 표에 /usage 추가
  - 에이전트 표에 README Sync 추가, State-Sync Writer 범위를 sync-test 전용으로 정정
  - 훅 표에 log-skill-invocation(PostToolUse matcher Skill) 추가
  - 디렉터리 트리에 settings.json·skill-invocations.log·githooks/·usage/·
    readme-sync-agent.md·usage-report.sh 등록
최소 diff, 기존 한국어 톤 유지.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
/sync-test 로 커버리지 빈틈을 스캔한 결과, 이번 세션에 추가된 순수 결정적
스크립트 두 개가 무테스트였다. telegram-listener·remind-cron 같은 외부 의존
.sh 와 달리 이 둘은 네트워크·데몬·claude 의존이 전혀 없어(stdin→append /
로그→stdout) detect-todo.js 처럼 단위 검증이 가능하다.

- tests/unit-scripts.sh 신규: log-skill-invocation(append·카운터 증가·비-Skill
  스킵·네임스페이스 보존)과 usage-report(빈도·연쇄·유휴·빈 로그) 계약 검증.
- 테스트 격리를 위해 두 스크립트에 SKILL_LOG 환경변수 오버라이드 추가 —
  임시 로그를 주입해 실데이터(skill-invocations.log)를 건드리지 않는다. 기본
  동작은 불변.
- run-tests.sh L2 에 배선(CI L1+L2 가 자동 커버), tests/README.md 문서화.

검증: run-tests.sh l1 l2 통과(L2 13+8 pass), 실로그 무접촉 확인.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
세션 밖에서 도는 자동화 루프 3개를 crontab 으로 배선한다(remind 와 같은 방식).

1) outbox 재동기 (조정 루프 완성) — flush-cron.sh, 15분마다
   capture-flush.sh 를 주기 구동해 outbox 미동기 항목을 재전송, "모두 동기됨"
   상태로 수렴. 몸통만 있고 자동 구동이 없던 조정 루프의 나머지 절반.

2) 감시 (watchdog) — watchdog-cron.sh, 10분마다
   telegram-listener 데몬 헬스 체크. 다운 감지 시 폰 알림 + 자동 재시작 시도.
   상태 파일로 healthy↔down 전이에만 알림(디바운스). launchd KeepAlive 가 못
   잡는 "언로드/미기동"을 사용자에게 알린다.

3) 집계 (digest) — digest-cron.sh, 매주 일요일 20:00
   digest-report.sh(결정론 집계)로 상태 분포·카테고리·2일+ 방치 draft 를 요약해
   폰으로 발송. remind 가 매일 재촉이라면 이건 주 1회 회고.

공유·인프라:
- _shared/telegram-send.sh: 알림 루프 공용 sender (security.md 규칙 준수 —
  값 노출 없이 실패, 자격증명 없으면 미발송).
- launchd/install.sh·uninstall.sh: cron 4종 멱등 등록/제거.
- .gitignore·security.md 정본: 새 런타임 상태·로그 파일 등록(양쪽 일치).

테스트·검증:
- unit-scripts.sh 에 digest-report(집계 로직)·telegram-send(빈 메시지 가드)
  결정론 테스트 추가(ITEMS_JSON_FILE 픽스처 주입). run-tests l1 l2 통과(14 pass).
- 게이트가 inject.sh 검사4 로 telegram-send 의 미문서화 정본 참조를 잡아내,
  .sh 는 §2 주입 지도의 소비자가 아니라는 관례에 맞춰 경로 인용을 제거해 해소.
- README·tests/README 를 실제 상태에 동기화.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
로컬-우선(§2)이 데이터를 여러 로컬 파일에 쌓지만 "로컬에 쌓인다"가 같다고
캐시·버퍼·축적을 뭉뚱그리면 안 된다 — 정상 상태가 정반대다. 저장소를 만지기
전에 셋 중 무엇인지 목표 상태로 판정하는 기준을 정본화한다.

- 캐시(원본과 일치·재생성 무해) / 버퍼(0이 목표·지우면 유실) /
  축적(끝없이 성장) 을 표로 레포 실체에 매핑.
- 루프도 같은 축으로 분리: 자율탐지형(조정 — flush·watchdog·digest) vs
  자산 축적형(자기 관찰 루프 = 로그 write ↔ /usage read).
- 혼동 방지: capture 로컬 저장부는 캐시+버퍼이지 축적이 아니며, outbox 는
  데이터일 뿐 루프는 그걸 드레인하는 flush-cron(탐지형)임을 명시.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- context-map.md 를 .claude/context/ → docs/ 로 이동하고 README 링크 보정
- mission-2-report.md 의 context-map 링크를 새 위치 기준으로 보정
- system-loops.md 신규: 세션 밖 시스템 루프 6종(cron 4·데몬·자기관찰)의
  동작 순서를 탐지형/축적형 축으로 정리한 mermaid 다이어그램

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
context-map.md 를 docs/ 로 옮기면서 §4 드리프트 검사가 파일을 못 찾아
조용히 SKIP 되던 것을 되살린다. 검사 8→9 pass 로 복귀.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JoyDaheeCha
JoyDaheeCha changed the base branch from main to joydaheecha July 15, 2026 12:36
@MinCha

MinCha commented Jul 15, 2026

Copy link
Copy Markdown

@JoyDaheeCha

2,3주차 과제 잘 보았습니다! 또한, 구조를 잡으며 긍정적인 부분을 보고 계신 것 같아 강사로서 기쁘네요. 랄프 루프로 성과도 내셨다니 보기 좋습니다.

  1. 금주부터 과제 평가는 AI가 담당하고 있어 평가 테이블을 공유드리오니 참고 부탁드려요. (2,3주차 모두)
완료기준 시도 ★ 달성 ★★ 품질 ★★★ 평가 사유
2주차 필수1 · 컨텍스트 3개+ 자동 주입 필수는 컨텍스트 세 개인데 여섯 개를 만들어 여유 있게 넘기셨고, 매 세션 항상 올리는 방식과 필요할 때만 올리는 방식을 나눠 배선하셨습니다. grep으로 소비자에서 정본으로 이어지는 연결이 15~16개 실제로 잡혀서, 주입이 문서상 약속이 아니라 진짜로 걸려 있음이 확인됩니다.
2주차 필수2 · 주입 전/후 동작 비교 지정된 /skill-creator 대신 같은 입력을 72번 돌린 통제 A/B 실험으로 주입 전후를 비교해, 정확도가 50%에서 97.2%로 오르는 것을 숫자로 보여주셨습니다. 도구는 달랐지만 '주입이 동작을 바꾸는가'라는 취지를 오히려 더 엄밀하게 넘어서서, 다섯 명 중 세 명이 품질로 봤습니다.
2주차 필수3 · 컨텍스트 체계 도식화 컨텍스트 주입이 언제·무엇이·어느 창에 들어오는지를 세 관점의 도식으로 나눠 그리고 색으로 구분해, 그림만 봐도 체계가 한눈에 읽힙니다. 리포트가 이 파일 경로를 옛 위치로 잘못 적은 자잘한 흠은 있지만 도식 자체의 완성도는 높습니다.
2주차 도전1 · 주입 검증 테스트 주입이 조용히 끊기는 걸 막으려고 아홉 가지를 검사하는 테스트를 만들고, 이걸 CI에 걸어 push·PR마다 자동으로 돌게 하셨습니다. 도식과 실제 참조가 서로 어긋나는지 양방향으로 보는 검사까지 있어 회귀를 잘 막습니다.
2주차 도전2 · 최적화+정량 비교 큰 스캔을 서브에이전트로 넘겨 메인 흡수를 89% 줄이고 총 토큰을 절반으로 낮춘 뒤, 상주 컨텍스트가 다시 커지지 않게 예산 게이트까지 두셨습니다. grep만 하는 스킬은 위임이 오히려 손해라 일부러 안 넘긴 손익분기 판단이 특히 좋았습니다.
3주차 필수1 · 개선/자산축적 루프 1개 스킬을 부를 때마다 로그에 쌓고 /usage가 그 로그를 되읽는 자산축적 루프를, 같은 파일을 쓰고 읽는 코드 경로 수준에서 실제로 닫으셨습니다. 여기에 동기화·감시·집계 같은 자율탐지 루프 네 종까지 더해져 단계 분해와 연결이 탄탄합니다.
3주차 필수2 · 루프 1P 문서화 루프를 탐지형·데몬·축적형 세 갈래로 나누고 각각을 도식·색 범례·출처와 함께 한 장에 담아, 자동으로 도는 장치가 한눈에 들어옵니다. 설계원칙 문서의 저장소 분류와도 이어져 문서만 봐도 구조가 이해됩니다.
3주차 도전1 · 나아지는지 정량 지표 빈도·연쇄·유휴를 보는 /usage와 네 개 지표를 내는 A/B처럼 정량 지표를 갖춘 점은 분명합니다. 다만 이 지표들은 사용 패턴과 주입 효과를 재는 것이라, '루프가 회를 거듭할수록 나아지는가'를 직접 재는 데까지는 닿지 못해 다섯 명 모두 달성으로 봤습니다.
3주차 도전2 · 5차원+랄프 2h+ 스냅샷 PR 본문의 랄프 루프 회고와 코드 주석의 측정법 언급으로 시도한 흔적은 보입니다. 그러나 5차원 루브릭 문서도, 두 시간 넘게 돌린 회차별 스냅샷 기록도 트리에 없어서 다섯 명 모두 아직 시도 단계로 봤습니다.
  • 과제별로 5개 독립 에이전트가 다수결로 평가합니다.
  1. 여러 작은 루프를 만드셨는데요. 언급하신대로 이후에는 이 OS의 핵심 목표를 달성하기 위한 방향으로 가치 있는 무엇인가를 남기고, 남긴 것을 토대로 그 다음에는 0.1%라도 더 나아질 수 있는 시스템 루프를 구성해보시면 좋을 것 같습니다. 결국은 무엇을 남기고, 남긴 것을 어떻게 활용할지에 대한 고민이 될 것 같습니다. 또한, 시스템 루프가 더 커진다면 사람과 AI의 역할이 각각 무엇인지, 최상의 협력은 무엇인지도, 주요 화두가 될 것 같습니다.

  2. 현재 트리거 장치(cron)가 여러개인데요. 테스트가 불가능하지는 않겠지만 cron은 상대적으로 테스트하기 어렵고, 많아지다 보면 관리가 어려울 수 있습니다. 따라서 1분 짜리 cron 하나만 유지하고, 1분에 한 번 실행될 때마다 시간 기반 매칭 로직 등으로 트리거되어야 하는 작업들을 선택해 수행하는 구조도 검토해볼만 한 것 같습니다. 테스트가 쉬워지고, 트리거 되는 모든 작업에 대한 공통 로직을 적용하기도 쉬워져 결국 유지보수 하기가 편해질 것 같다는 생각입니다.


바쁘신 와중에 세 번의 과제를 진행하시느라 고생 많으셨습니다. 회사에서는 여러 복잡한 이슈로 AI의 잠재력을 100% 활용하기 어려울텐데요, 개인 OS의 장점은 100% 이상의 잠재력을 제한 없이 이끌어낼 수 있다는 점인 것 같습니다. 본인의 필요에 의한 OS인 만큼 내 필요를 더 탁월하게 채워주는 OS로 계속 발전하면 좋겠습니다.

고맙습니다!

@MinCha
MinCha merged commit 14da1a9 into next-step:joydaheecha Jul 15, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants