GITHUB 레포 딥다이브 · 2026-08-03 · DANNYMAC180/SOL-ADVISOR · 짓는 사람과 검사하는 사람을 갈라놓은 코딩 에이전트 규율

sol-advisor 딥다이브
— 설계·시공·검사를 강제로 분리한 Codex 오케스트레이션

DannyMac180/sol-advisor는 OpenAI Codex(코덱스) 위에서 도는 "건축가 + 시공팀 + 준공검사관" 워크플로를 코드가 아니라 규율(discipline)로 못 박은 플러그인이다. 주 세션(Sol)은 건축가로서 요구사항·아키텍처·명세·검증만 맡고, 실제 구현은 전부 Terra 에이전트에게 넘긴 뒤, 맥락을 처음 보는 신선한 Sol 리뷰어가 "통과(ship)"라고 말하기 전엔 완료를 선언하지 못한다.

대부분의 "AI에게 코딩 시키기"는 한 명이 설계·구현·자평을 다 한다. 그래서 자기가 짠 코드를 자기가 검사하는 확증 편향에 빠진다. sol-advisor는 이 셋을 물리적으로 다른 세션·다른 역할로 쪼개고, 각 역할의 모델·추론 강도를 TOML 파일에 못(pin)으로 박아 아무도 몰래 성능을 낮추지 못하게 한다. 코드량은 작지만(설정·셸 스크립트 중심), "어떻게 하면 에이전트에게 규율 있게 일을 시킬 수 있나"라는 방법론이 알맹이다.

(저장소 DannyMac180/sol-advisor · 라이선스 MIT · 플랫폼 OpenAI Codex CLI/데스크톱(플러그인·네이티브 서브에이전트) · 플러그인 버전 v0.3.0 · 구성 POSIX 셸 + jq + Python 검증 · 역할 모델 GPT-5.6 Sol / Terra(High) · 파일 ~13개 · ★134 · 커밋 3개 · 저자 Daniel McAteer · TrendShift Daily #9)
목차
  1. 한 줄 정체
  2. 왜 주목받는가 — "역할을 못 박는다"는 각도
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 — 역할·핀·설치·관찰
  5. 디렉토리 구조 해부
  6. 학습 포인트 — 기술별 배울 것
  7. 시스템 / 실행 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 로드맵 (주차별)
  10. 핵심 키워드 사전
  11. 참고 링크

1한 줄 정체

이 프로젝트가 정확히 무엇인지 한 문장으로

sol-advisor는 "OpenAI Codex에게 코딩을 시킬 때, 설계하는 세션 · 구현하는 세션 · 검사하는 세션을 강제로 분리하고, 각 세션이 쓸 모델과 추론 강도를 파일에 못 박아, 아무도 몰래 대충 하지 못하게 만드는 워크플로 플러그인"이다. 한마디로 에이전트판 "역할 분리 + 준공검사" 제도다. 코드를 짜는 도구가 아니라, 코드를 짜게 시키는 방식을 규율로 정한 것이다.

한 장의 비유

"건축가 · 시공팀 · 준공검사관을 딴사람으로 두는 건설 현장"

제대로 된 건설 현장에서는 건축가가 도면을 그리고, 시공팀이 그 도면대로만 짓고, 마지막에 준공검사관이 실제로 지어진 것을 검사한다. 핵심은 셋이 다른 사람이라는 점이다. 건축가는 망치를 들지 않고, 검사관은 시공 회의에 끼지 않았기에 "이건 이렇게 하기로 했잖아요" 같은 현장 합의에 물들지 않은 눈으로 본다. 게다가 검사관에게는 열람 권한만(read-only) 주어져, 보기만 할 뿐 손대서 몰래 고치지 못한다.

sol-advisor가 정확히 이 구조다. Sol 오케스트레이터(건축가)가 요구사항·아키텍처·명세를 쥐고, Terra 구현자(시공팀)가 그 명세대로만 짓고, 신선한 Sol 리뷰어(검사관)가 실제 diff를 처음 보는 맥락으로 검사해 ship / fix-first / rethink 중 하나를 판정한다. 검사관이 "ship"이라 하기 전엔 완료가 없다.

용어
오케스트레이션 (Orchestration, 지휘)
여러 AI 에이전트/작업을 하나의 지휘자가 역할을 나눠 조율하는 것. 오케스트라 지휘자가 직접 악기를 연주하지 않고 연주자들을 조율하듯, sol-advisor의 주 세션(Sol)은 직접 코드를 타이핑하지 않고 구현·검토를 다른 역할에게 시키고 그 결과를 검증·종합한다.
용어
Codex (코덱스) · 커스텀 에이전트
Codex는 OpenAI의 코딩 에이전트(CLI/데스크톱)로, Claude Code나 Cursor 같은 부류다. sol-advisor는 Codex 전용이며 Claude Code용이 아니다. Codex의 커스텀 에이전트(custom agent) 기능은 TOML 파일 하나로 "이런 성격·이런 모델·이런 권한의 하위 에이전트"를 정의해 두고, 주 세션이 agent_type 이름만 대면 그 프로필로 하위 스레드를 띄우는 장치다. 이 프로젝트의 Terra·Sol 리뷰어가 바로 이 커스텀 에이전트다.

사용자가 "이 기능 만들어 줘"라고 하면 sol-advisor 규율 아래서 벌어지는 일을 압축하면 이렇다:

사용자 "이 기능 만들고, 검증까지 끝낸 다음에 완료라고 해줘" │ ▼ ① 사전점검(preflight) 역할 파일이 배포 템플릿과 바이트까지 일치하나 확인(--check) Terra·Sol 두 역할 이름이 실제로 노출되나 확인 │ ▼ ② Sol 건축가(주 세션) 요구사항 확정 → 아키텍처 결정 → 5부 구현 명세 작성 │ │ agent_type: sol_advisor_terra_implementer (모델·강도는 TOML에 고정) ▼ ③ Terra 시공(하위 스레드) 명세대로만 구현 → 파일별 변경+검증 증거를 보고 │ ▼ ④ Sol 건축가 재검증 diff 직접 열람 → 검증 명령 재실행 → 범위 밖 변경 없나 확인 │ │ agent_type: sol_advisor_sol_reviewer (read-only 샌드박스 요청) ▼ ⑤ 신선한 Sol 검사관 맥락 없이 실제 diff·증거만 보고 → ship / fix-first / rethink │ ▼ ⑥ ship 판정이어야만 완료 선언 (fix-first면 고쳐서 다시 검사, rethink면 설계 재검토)

여기서 핵심은 ①의 사전점검⑤의 신선한 검사다. ①은 "일을 시키기 전에 역할이 위조·변조되지 않았는지"를 해시로 확인하고, ⑤는 "짓는 동안 오간 대화에 물들지 않은 눈"으로 결과만 본다. 이 둘이 sol-advisor를 단순 "서브에이전트 띄우기"와 갈라놓는 지점이다.

2왜 주목받는가 — "역할을 못 박는다"는 각도

작은 신생 레포가 TrendShift 상위에 오른 이유

첫째, 지금 가장 뜨거운 주제인 "에이전트 오케스트레이션"의 실전 규율이다. TrendShift 데일리 1위 토픽이 AI agent일 만큼, "에이전트 여러 개를 어떻게 잘 부릴까"가 최대 관심사다. Codex가 최근 커스텀 에이전트·플러그인·네이티브 서브에이전트를 갖추면서, 그 새 기능을 규율 있게 쓰는 법을 보여 주는 참조 구현으로 딱 맞물렸다.

둘째, "몰래 성능을 낮추는" 실전 고통을 정면으로 때린다. AI 코딩 도구를 오래 쓴 사람은 안다 — 에이전트가 슬그머니 더 싼 모델로 갈아타거나 추론 강도를 낮춰, 겉으론 일하는 척하며 품질이 떨어지는 일이 잦다. sol-advisor는 모델·강도를 커스텀 에이전트 TOML에 못 박고(pin), "호출할 때 모델을 지정하지 말라"고 규정한다. 조용한 대체(silent fallback)를 금지한다는 이 원칙이 실무자의 공감을 얻는다.

비유

공사 자재 스펙을 계약서에 못 박는 것과 같다. "철근은 SD400 이상"이라고 계약서(TOML)에 박아 두면, 시공사가 현장에서 몰래 싸구려 철근으로 바꿔치기할 수 없다. 그리고 매번 자재를 넣기 전에 납품 증명서(런타임 라우팅 증거)를 확인한다. sol-advisor는 "이 역할은 반드시 Terra/High"라고 못 박고, 하위 스레드가 진짜 그 모델·강도로 돌고 있는지 실제 실행 메타데이터로 확인한 뒤에야 결과를 받아들인다.

셋째, 정직한 설계 서술이 신뢰를 준다. 이 레포는 자기 한계를 숨기지 않는다. 문서 곳곳에 "Sol이 Sol을 검토하는 것은 맥락이 신선할 뿐, 모델 계열이 독립적인 것은 아니다"라고 못 박는다. 즉 "완벽한 교차검증"이라 과장하지 않고, "같은 모델 계열이라 잡지 못하는 것도 있다"는 잔여 위험을 명시한다. 과대광고가 넘치는 에이전트 판에서 이런 절제가 오히려 눈에 띈다.

넷째, 저자의 배포력이다. 저자 Daniel McAteer(DannyMac180)는 Attention Heads라는 뉴스레터에서 "Agentic Engineering Field Notes"(에이전트 엔지니어링 현장 노트) 시리즈를 연재한다. 방법론을 글로 설파하는 저자가 그 방법론을 코드로 구현해 내놓은 것이라, 글 독자층이 곧 레포의 초기 별점으로 이어졌다.

이 레포의 진짜 강점
"에이전트 규율"을 말이 아니라 검증 가능한 장치로 만들었다

대부분의 "AI 코딩 잘하는 법"은 프롬프트 조언에 그친다. sol-advisor는 그 규율을 강제되는 장치로 바꿨다 — 역할 파일의 바이트 무결성을 SHA-256으로 검사하고, 하위 에이전트의 실제 모델·강도·샌드박스를 런타임 메타데이터로 관찰하며, 어긋나면 그 lane을 멈춘다. "믿지 말고 확인하라(trust, but verify)"를 프롬프트가 아니라 셸 스크립트로 구현한 것이 이 프로젝트의 심장이다.

오해 주의
Claude Code용이 아니다 · 매우 작고 새로운 레포다

이름·구조가 "AI 코딩 스킬"처럼 보여 Claude Code 플러그인으로 착각하기 쉽지만, sol-advisor는 OpenAI Codex 전용이다(GPT-5.6 Sol/Terra 모델, codex plugin 명령, Codex 네이티브 서브에이전트 의존). 또한 커밋 3개·별 134개(분석 시점)의 아주 새로운 소규모 레포다 — 거대한 프레임워크가 아니라 "잘 벼려진 방법론 한 벌"로 보는 게 정확하다. 그래서 배울 것은 코드량이 아니라 설계 원칙에 있다.

3기술 스택 전체 지도

거창한 프레임워크가 없다 — 셸·jq·TOML로 규율을 구현한다

sol-advisor에는 웹서버도, 빌드 도구도, 무거운 런타임도 없다. 이 프로젝트의 "스택"은 Codex라는 숙주 플랫폼 위에 얹히는 설정 파일과 이식성 높은 셸 스크립트가 전부다. 바로 이 미니멀함이 요점이다 — 규율은 거대한 코드가 아니라 정확한 몇 개의 파일로 강제된다.

구성요소무엇왜 이걸 썼나
OpenAI Codex숙주 플랫폼(CLI/데스크톱)커스텀 에이전트·플러그인·네이티브 서브에이전트를 제공. sol-advisor는 이 위에 얹히는 규율 레이어
POSIX sh설치·검증·관찰 스크립트 3종bash 전용 문법 없이 순수 POSIX로 작성 → macOS·Linux 어디서나 동일 동작(이식성)
TOML커스텀 에이전트 역할 정의(2개)Codex가 읽는 역할 파일 포맷. model·model_reasoning_effort·sandbox_mode·developer_instructions못 박는(pin)
jqJSON·JSONL 처리런타임 로그(JSONL)에서 허용목록(allowlist)만 뽑아 새 객체를 만들 때. 프롬프트·토큰 유출 방지의 핵심 도구
shasum -a 256파일 바이트 지문설치된 역할 파일이 배포 템플릿과 바이트까지 일치하는지, 혹은 알려진 구버전인지 SHA-256으로 판별
Python 3 (tomllib)검증 스크립트(verify.sh) 내부TOML 역할 파일의 필드 값을 파싱·검증. 표준 라이브러리만 사용(외부 의존 0)
Markdown 스킬SKILL.md + role-contracts.mdCodex 스킬 규격. 오케스트레이션 절차·역할 계약을 실행 지침으로 기술
플러그인 매니페스트plugin.json·marketplace.jsonCodex 플러그인/마켓플레이스 등록 정보(JSON). 버전 0.3.0
용어
GPT-5.6 Sol / Terra / Luna
이 레포가 역할에 못 박아 참조하는 모델 이름들이다. 레포 규약상 Sol은 오케스트레이터·리뷰어(판단·검토용), Terra는 유일한 구현 lane(실제 코딩)에 배정된다. Luna는 과거 v0.2.0에서 "가벼운 작업" 담당이었으나 v0.3.0에서 폐기(retire)됐다. 이 문서는 이 이름들을 레포가 쓰는 방식 그대로 다룬다 — 모델의 실제 성능 서열을 단정하지는 않는다.
용어
추론 강도 (reasoning effort) · High / Max
같은 모델이라도 얼마나 오래·깊이 생각하게 할지를 정하는 값. 높을수록 더 신중하지만 느리고 비싸다. sol-advisor v0.3.0은 구현·검토 모두 high로 고정했다(구버전 v0.2.0은 구현에 max를 썼다). 이 값을 TOML에 박아, 호출 시점에 몰래 낮추지 못하게 한다.

4아키텍처 심화 — 역할·핀·설치·관찰

이 레포의 진짜 알맹이. 네 개의 축으로 나눠 본다

축 1 — 세 역할과 단방향 위임 (누가 무엇을 하는가)

사용자에겐 하나의 Codex 세션으로 보이지만, sol-advisor는 일을 세 역할로 쪼갠다. 위임은 위에서 아래로만 흐르고, 각 역할은 자기 소관만 한다.

┌──────────────────────────────────────────────────────────┐ │ ① Sol 오케스트레이터 (건축가 · 주 세션) │ │ · GPT-5.6 Sol / High │ │ · 요구사항·아키텍처·분해·5부 명세·검증·최종 수락 │ │ · 구현 코드를 직접 타이핑하지 않는다 → 아래로 위임 │ └───────────────────────────┬──────────────────────────────┘ │ agent_type: sol_advisor_terra_implementer ▼ ┌──────────────────────────────────────────────────────────┐ │ ② Terra 구현자 (시공팀 · 유일한 구현 lane) │ │ · GPT-5.6 Terra / High │ │ · 5부 명세대로만 구현, 소유한 파일만 수정 │ │ · 아키텍처를 재설계하지 않고 모호함은 되물어 올린다 │ └───────────────────────────┬──────────────────────────────┘ │ (①이 diff를 직접 검증한 뒤) │ agent_type: sol_advisor_sol_reviewer ▼ ┌──────────────────────────────────────────────────────────┐ │ ③ 신선한 Sol 리뷰어 (준공검사관 · read-only) │ │ · GPT-5.6 Sol / High · sandbox_mode = read-only │ │ · 맥락 없이 실제 diff·증거만 검사 │ │ · 판정: ship / fix-first / rethink (직접 고치지 않음) │ └──────────────────────────────────────────────────────────┘

규칙이 엄격하다. 구현자는 자기가 소유한 파일만 건드리고, 리뷰어는 어떤 파일도 수정하지 못한다. 그리고 리뷰어가 스스로 버그를 고치는 것은 금지다 — 고치면 그 diff는 "검토받지 않은 변경"이 되므로, 반드시 구현 lane으로 되돌려 고친 뒤 새 신선한 리뷰를 다시 받는다. "검토"와 "수정"을 절대 한 손에 쥐지 않게 한 것이다.

축 2 — 역할 핀(role pinning): 몰래 못 낮추게 하는 법

핵심 안전장치는 모델과 추론 강도를 스폰(호출) 시점이 아니라 역할 파일에 박는다는 것이다. 주 세션은 agent_type 이름만 대고, 모델·강도는 절대 지정하지 않는다. 값은 TOML이 소유한다:

# agents/sol-advisor-terra-implementer.toml — 유일한 구현 lane
name = "sol_advisor_terra_implementer"
model = "gpt-5.6-terra"
model_reasoning_effort = "high"          # ← 여기 박힌 값이 진실

# agents/sol-advisor-sol-reviewer.toml — 신선한 read-only 리뷰
name = "sol_advisor_sol_reviewer"
model = "gpt-5.6-sol"
model_reasoning_effort = "high"
sandbox_mode = "read-only"          # ← 검사관에겐 열람권만

그런데 "박아 뒀다"는 선언만으론 부족하다. sol-advisor는 실제로 그 값으로 돌고 있는지를 스폰 후에 확인한다(SKILL.md 사전점검 3단계). 확인 순서가 영리하다:

설계에서 배우는 것
"조용한 대체 금지(no silent fallback)"를 강제로

많은 시스템이 "안 되면 알아서 대체"를 편의로 넣는다. 그러나 품질이 걸린 곳에서 조용한 대체는 곧 조용한 저하다. sol-advisor는 정반대를 택한다 — 모델·강도가 누락·불일치·관찰 불가면 그 즉시 실행 가능한 에러로 멈춘다. "애매하면 진행"이 아니라 "애매하면 정지". 신뢰성이 중요한 파이프라인 설계에서 두고두고 참고할 원칙이다.

축 3 — 바이트 정확 설치기(install-agents.sh): 사용자 파일을 절대 덮지 않는다

역할 파일은 사용자 소유다(각자 자기 Codex 설정 폴더에 둔다). 플러그인을 설치·업데이트해도 자동 등록되지 않으므로, 별도 설치 스크립트가 이걸 안전하게 깐다. 이 스크립트가 이 레포에서 가장 정교한 엔지니어링이다. 목적지 파일을 SHA-256으로 여섯 상태로 분류한다:

목적지 파일 분류 (classify) missing 없음 → 새로 설치해도 됨 current 배포 템플릿과 바이트 일치 → 이미 최신, 건드리지 않음 legacy 알려진 v0.2.0 지문과 일치 → 마이그레이션 대상 conflict 내용이 다름(사용자가 수정?) → 절대 덮지 않음, 정지 unsafe 심볼릭 링크/일반파일 아님 → 절대 덮지 않음, 정지 unreadable 읽을 수 없음 → 정지

이 분류가 왜 중요한가? "설치"라는 단순 작업조차 사용자가 손수 고친 파일을 말없이 날려버릴 위험이 있기 때문이다. 스크립트는 current·legacy·missing만 진행하고, conflict·unsafe는 건드리지 않고 멈춘 뒤 사용자에게 경로를 알려 준다. 설치 자체도 원자적으로 한다:

# 임시 파일에 먼저 복사 → 하드링크로 목적지에 "원자적" 배치
staged=$(mktemp "$target_dir/.sol-advisor-agent.XXXXXX")
cp "$template" "$staged"
ln "$staged" "$destination"   # 목적지가 이미 있으면 실패 → 덮어쓰기 사고 원천 차단
rm -f "$staged"
# 설치 직전에 상태를 한 번 더 확인(same_state)해 경쟁 조건(TOCTOU) 방어
용어
TOCTOU (Time-Of-Check to Time-Of-Use, 검사–사용 시차 취약점)
"괜찮은지 확인한 순간"과 "실제로 쓰는 순간" 사이에 파일이 바뀌어 생기는 버그·보안 구멍. 예: 확인할 땐 없던 파일이 설치 직전에 생겨 덮여버리는 것. install-agents.sh는 변경 직전에 상태를 다시 검사하고, 하드링크(ln)로 "이미 있으면 실패"하게 해 이 시차를 좁힌다. 파일을 다루는 모든 설치기가 신경 써야 하는 고전 문제다.

여기에 버전 마이그레이션까지 얹혀 있다. v0.2.0의 Terra·Luna 파일의 SHA-256 지문이 스크립트에 불변 상수로 하드코딩돼 있어, 구버전 파일을 정확히 알아보고 → 구 Terra는 새 템플릿으로 교체, 폐기된 Luna는 삭제한다. 단, 사용자가 조금이라도 손댄 구버전 파일이면(지문 불일치) 건드리지 않는다. "정확히 아는 것만 자동 처리, 조금이라도 다르면 사람에게"라는 태도가 일관된다.

축 4 — 안전한 런타임 관찰(inspect-agent-runtime.sh): 필요한 것만 내보낸다

축 2에서 "실제 모델·강도를 확인한다"고 했다. 그 확인을 로컬 로그에서 할 때 쓰는 도구가 이것인데, 최소 공개(least disclosure) 원칙으로 설계됐다. 로그 파일(rollout JSONL)에는 프롬프트·토큰 등 민감정보가 가득한데, 이 스크립트는 라우팅 관련 허용목록 필드만 뽑아 새 JSON으로 만든다:

# 1) 입력부터 엄격 검증: thread_id는 소문자 UUID여야만
grep -Eq '^[0-9a-f]{8}-[0-9a-f]{4}-...-[0-9a-f]{12}$'

# 2) 파일 내용은 "정확히 1개"가 매칭될 때까지 열지 않는다
find "$sessions_dir" -type f -name "rollout-*-$thread_id.jsonl"
#    0개 → 에러, 2개 이상 → 에러 (모호하면 정지)

# 3) jq로 "허용된 필드만" 새 객체를 구성 (원본을 그대로 뱉지 않음)
jq ... '{ thread_id, agent_role, model, effort,
       sandbox_policy_type, permission_profile_type, cwd }'
#    model/effort가 없거나 서로 충돌하면 추론하지 않고 에러

포인트는 "원본을 필터링"이 아니라 "허용된 것만 새로 구성"이라는 점이다. 필터링은 빠뜨린 민감정보가 새어나갈 수 있지만, 허용목록 구성은 명시적으로 나열한 필드 외에는 태생적으로 나올 수 없다. 검증 스크립트(verify.sh)는 실제로 로그에 DO_NOT_LEAK_PROMPT를 심어 두고, 인스펙터 출력에 그게 안 나오는지까지 테스트한다.

용어
최소 공개 / 허용목록 (least disclosure / allowlist)
"막을 것을 나열(차단목록)"하는 대신 "내보낼 것만 나열(허용목록)"하는 보안 습관. 차단목록은 빠뜨린 항목이 곧 유출이지만, 허용목록은 나열하지 않은 건 절대 안 나간다. 민감한 로그·API 응답을 가공해 외부로 줄 때의 정석. inspect-agent-runtime.sh가 jq새 객체를 짓는 방식이 바로 이것이다.

축 4-b — 5부 구현 명세: 위임의 계약서

Sol이 Terra에게 일을 넘길 때는 반드시 다섯 부분을 모두 채운 명세를 준다(role-contracts.md). 이 계약 양식 자체가 재사용 가치가 크다 — 어떤 에이전트에게든 일을 시킬 때 쓸 수 있다:

OBJECTIVE 관찰 가능한 결과 + 그게 왜 중요한지 FILES/OWNERSHIP 네가 소유한 파일 목록 (그 밖은 건드리지 마라) "너는 혼자가 아니다 — 동시 편집을 보존하라" INTERFACES 유지해야 할 시그니처·타입·스키마·명령·동작 CONSTRAINTS 레포 관례·안전 경계·제외 범위·이미 정해진 결정 VERIFICATION 실행할 정확한 명령 + 기대되는 구체적 결과 검사할 파일/diff + 기대되는 구체적 증거 ───────────────────────────────────────────────────── RETURN "증거 없는 완료 주장은 무효" IMPLEMENTATION REPORT STATUS / CHANGES(파일별) / VERIFIED(명령+출력) / JUDGMENT CALLS / GAPS

이 계약의 철학은 "완료했다는 말은 믿지 않는다, 증거를 본다"이다. 구현자는 "다 됐어요"가 아니라 실행한 명령과 그 실제 출력을 첨부해야 하고, 주 세션은 그 diff를 직접 열어 검증 명령을 스스로 재실행한다. 워커의 보고는 "주장(claim)"일 뿐, 검증 전엔 사실이 아니다.

축 4-c — 요청한 격리 vs 관찰된 격리

리뷰어 TOML은 sandbox_mode = "read-only"요청한다. 하지만 sol-advisor는 "요청했으니 됐다"고 넘어가지 않는다. 숙주(host) 환경이 그 요청을 넓혀버릴 수 있기 때문이다. 그래서 규약은 실제로 관찰된 샌드박스 정책으로만 판단하라고 못 박는다:

"요청한 것"과 "실제로 벌어진 것"을 구분하고, 후자로만 안전을 주장하는 이 정직함이 sol-advisor 설계 전반을 관통한다.

5디렉토리 구조 해부

파일 ~13개. 작기 때문에 오히려 한 파일 한 파일이 또렷하다
sol-advisor/ ├─ README.md 저장소 소개·설치·라우팅 설명(사용자 관점) ├─ LICENSE MIT ├─ .gitignore .DS_Store · *.log · __pycache__/ │ ├─ .agents/plugins/ │ └─ marketplace.json Codex 마켓플레이스 등록(로컬 소스 → ./plugins/sol-advisor) │ └─ plugins/sol-advisor/ ★ 실제 플러그인 본체 ├─ .codex-plugin/ │ └─ plugin.json ★ 플러그인 매니페스트(name·version 0.3.0·capabilities·기본 프롬프트) │ ├─ agents/ ★ 커스텀 에이전트 역할 정의(모델·강도를 "못 박는" 곳) │ ├─ sol-advisor-terra-implementer.toml 유일한 구현 lane (Terra/High) │ └─ sol-advisor-sol-reviewer.toml 신선한 리뷰 lane (Sol/High, read-only) │ ├─ skills/orchestration/ ★ 오케스트레이션 스킬(실행 지침) │ ├─ SKILL.md 건축가·위임·검증·최종리뷰 절차 전체 │ ├─ references/ │ │ └─ role-contracts.md 5부 명세 계약 + 리뷰어 프롬프트 양식 │ └─ agents/openai.yaml 스킬 인터페이스 표시명·기본 프롬프트 │ └─ scripts/ ★ 규율을 "강제"하는 셸 3종 ├─ install-agents.sh 바이트 정확 설치 + v0.2.0 마이그레이션(287줄) ├─ inspect-agent-runtime.sh 최소공개 런타임 관찰기(156줄) └─ verify.sh 레포 자체 검증 하네스(267줄)

구조가 알려주는 힌트 셋. 첫째, 가장 큰 파일이 셋 다 scripts/의 셸이다(install 287 · verify 267 · inspect 156줄). 이 프로젝트의 무게중심이 "AI에게 줄 프롬프트"가 아니라 "사람·기계가 검증할 수 있는 장치"에 실려 있음을 그대로 보여 준다. 둘째, agents/(무엇을)·skills/(어떻게)·scripts/(강제)로 역할이 폴더로 갈려 있다 — 정의, 절차, 집행이 코드 트리에 1:1로 대응한다. 셋째, plugin.json의 버전 0.3.0과 설치기 안의 v0.2.0 지문이 공존한다 — 이 레포가 이미 한 번 세대교체(3-lane → 2-lane)를 거쳤다는 흔적이다.

소스 vs README 함정
README 표는 Luna를 아직 보여 준다 (하지만 폐기됨)

README의 역할 표에는 아직 Luna(routine)+Terra(harder) 2-구현-lane에 강도 Max로 적혀 있다. 그러나 실제 배포되는 진실은 다르다 — plugin.json은 v0.3.0, 배포 TOML은 Terra 단일 구현 lane + Sol 리뷰어(둘 다 High)뿐이고, 설치기는 Luna 파일을 삭제한다. README가 소스 교체를 다 못 따라온 문서 드리프트다. 이 문서가 "현재 설계=2-lane"을 기준으로 삼는 이유이며, 레포를 볼 땐 README보다 TOML·SKILL.md·plugin.json을 진실로 삼아야 한다는 교훈이기도 하다.

6학습 포인트 — 기술별 배울 것

코드량은 작지만, 뽑아낼 설계 원칙은 밀도가 높다

① 역할 핀 & 조용한 대체 금지 (가장 값진 배움)

모델·추론 강도를 호출 시점이 아니라 선언(TOML)에 못 박고, 실제 실행값을 관찰해 어긋나면 멈추는 패턴. "편의를 위한 자동 대체가 곧 조용한 품질 저하"라는 통찰과, 그걸 강제 가능한 장치로 바꾸는 법을 배운다. LLM 파이프라인뿐 아니라 어떤 다단계 시스템에서도 "묵시적 폴백은 위험하다"는 원칙은 그대로 통한다.

② TOCTOU-안전한 파일 설치

사용자 파일을 절대 말없이 덮지 않는 설치기 설계. SHA-256으로 목적지를 6상태로 분류하고, mktemp+하드링크(ln)로 원자적으로 설치하며, 변경 직전에 상태를 재검사한다. 점표(dotfiles) 설치기, 마이그레이션 도구, 배포 스크립트를 짤 때 "조금이라도 다르면 사람에게 넘긴다"는 안전한 기본값을 배운다.

③ 최소 공개 introspection

민감정보가 든 로그에서 허용목록 필드만 새 객체로 구성해 내보내는 jq 패턴. "필터로 빼기"가 아니라 "허용된 것만 짓기"의 차이, 입력 검증(UUID 강제), "정확히 1개 매칭 전엔 내용을 안 연다"는 절제. 로그·API 응답을 안전하게 가공해야 할 때 두고두고 쓰는 기술이다.

④ 검증을 1급 시민으로 (verify.sh)

267줄짜리 verify.sh는 이 레포의 자가 테스트 하네스다 — 매니페스트 버전·TOML 핀을 검사하고, 깨끗한 설치·멱등성·마이그레이션·거부(수정된 파일/심볼릭 링크/오래된 파일)를 실제로 재현해 보고, 런타임 인스펙터의 라우팅 정확성과 유출 방지까지 시험한다. "문서가 코드와 어긋나지 않는지"(폐기된 스폰이 남아 있나)도 grep으로 잡는다. 규율을 말로만 두지 않고 CI로 집행하는 법의 표본.

⑤ 5부 위임 계약 (재사용성 최고)

OBJECTIVE / FILES·OWNERSHIP / INTERFACES / CONSTRAINTS / VERIFICATION로 짜인 명세 양식은 Codex가 아니어도 쓸 수 있다. Claude Code 서브에이전트, 동료에게 맡기는 작업 지시, 심지어 이슈 템플릿에도 그대로 적용된다. 특히 "증거 없는 완료 주장은 무효"라는 반환 규칙은 위임의 품질을 극적으로 끌어올린다.

⑥ 정직한 보안 서술 (관찰 vs 요청)

"read-only를 요청했다"와 "실제로 read-only로 관찰됐다"를 구분하고, 후자로만 안전을 주장하는 태도. 그리고 "Sol이 Sol을 보는 건 맥락만 신선할 뿐 모델 독립이 아니다"라며 잔여 위험을 스스로 명시하는 것. 과장 없이 한계를 적는 것이 오히려 신뢰를 만든다는, 문서화의 좋은 본보기다.

실습 아이디어(가볍게)
Codex가 없어도 "규율"만 흉내 내 보기

이 레포의 진짜 가치는 Codex 실행이 아니라 규율이다. Codex가 없다면, 자기가 쓰는 아무 AI 코딩 도구에서 "① 나는 명세만 쓴다 → ② 새 창에서 구현만 시킨다 → ③ 또 다른 새 창에 맥락 없이 diff만 붙여 검토시킨다"를 손으로 해 보라. 특히 ③에서 "직접 고치지 말고 ship/fix-first/rethink만 말하라"고 지시하면, 자기 코드를 자기가 검토할 때와 얼마나 다른 지적이 나오는지 곧바로 체감된다.

7시스템 / 실행 요구사항

돌려 보려면 무엇이 필요한가 (Codex 환경 전제)
항목필요한 것
플랫폼OpenAI Codex CLI 또는 ChatGPT 데스크톱 앱 — 플러그인·네이티브 서브에이전트·커스텀 에이전트가 활성화돼 있어야 함. Claude Code에서는 동작하지 않는다
모델 접근GPT-5.6 Sol·Terra를 요구되는 추론 강도(High)로 쓸 수 있는 계정/권한
도구jq(설치·관찰 스크립트가 사용). 검증까지 돌리려면 Python 3(tomllib 포함, 표준)
설치(마켓)codex plugin marketplace add DannyMac180/sol-advisor --ref maincodex plugin add sol-advisor@sol-advisor
역할 파일(별도)플러그인 설치는 역할 TOML을 자동 등록하지 않는다. scripts/install-agents.sh를 따로 실행해 Terra·Sol 역할을 설치하고 --check로 검증
새 태스크 시작네이티브 역할은 태스크 생성 시점에 발견된다 → 설치·검증 후 새 Codex 태스크를 열어야 역할이 보임

8직접 해볼 수 있는 실습 과제

난이도별로. Codex가 없어도 대부분 가능하게 구성했다
과제 1 난이도 ●○○○○

두 역할 TOML + SKILL.md 읽고 "세 lane" 지도 그리기

git clone --depth 1로 받아 agents/*.toml 2개와 skills/orchestration/SKILL.md를 읽는다. 오케스트레이터·구현자·리뷰어가 각각 어떤 모델·강도·샌드박스인지, 위임이 어느 방향으로 흐르는지 한 장으로 그려 보자. "왜 리뷰어만 read-only인가"를 스스로 답해 보는 게 목표.

과제 2 난이도 ●●○○○

verify.sh를 돌려 각 PASS가 무엇을 보장하는지 읽기

클론한 폴더에서 sh plugins/sol-advisor/scripts/verify.sh를 실행한다(jq·python3 필요). 통과하는 각 PASS 줄이 실제로 무엇을 검사했는지 스크립트에서 찾아 대응시켜 보자 — 특히 "modified Luna 거부", "symlink 거부", "런타임 인스펙터 유출 방지" 항목이 어떻게 실패를 일부러 만들어 확인하는지 관찰하는 게 핵심.

과제 3 난이도 ●●●○○

5부 명세 계약을 "내 도구"에 이식하기

role-contracts.md의 5부 양식(OBJECTIVE/FILES/INTERFACES/CONSTRAINTS/VERIFICATION)을 그대로 복사해, 자기가 쓰는 AI 코딩 도구(Claude Code 서브에이전트 등)에 작업 지시 템플릿으로 붙여 본다. 같은 작업을 (a)평소처럼 대충 (b)5부 계약으로 두 번 시켜, "증거를 요구했을 때" 결과 품질이 어떻게 달라지는지 비교하라.

과제 4 난이도 ●●●●○

바이트 정확 설치기 패턴을 내 dotfiles에 적용

install-agents.shclassify(missing/current/legacy/conflict/unsafe) + 원자적 설치(mktemp+ln) + 사후 검증 패턴을 참고해, 자기 dotfile(예: .vimrc) 설치 스크립트를 짜 본다. 핵심은 "사용자가 손댄 파일이면 절대 덮지 않고 멈추기". SHA-256으로 "내가 지난번에 깐 그대로인가"를 판별하는 감각을 익힌다.

과제 5 난이도 ●●●●●

최소 공개 introspection 스크립트 직접 만들기

inspect-agent-runtime.sh를 본떠, 아무 JSONL 로그(민감 필드 포함)를 입력받아 허용목록 필드만 새 JSON으로 뽑는 스크립트를 jq로 짜 본다. 일부러 로그에 SECRET_TOKEN을 심고, 출력에 그게 절대 안 나오는지 테스트까지 작성하라. "필터링"이 아니라 "허용목록 구성"이어야 하는 이유를 코드로 증명하는 과제.

9관련 기술 심화 로드맵 (주차별)

이 레포를 계기로 공부 계획을 짠다면
주차주제구체적으로
1주에이전트 오케스트레이션 패턴orchestrator–worker(지휘자–일꾼), reflection/critic(자기검토), 역할 분리. sol-advisor의 3역할을 이 이론에 대응시켜 보기
2주위임 명세 & 검증 루프5부 계약, "증거 없는 완료는 무효", diff 재검증, ship/fix-first/rethink 게이트. role-contracts.md·SKILL.md를 표본으로
3주안전한 셸 & 원자적 파일 조작TOCTOU, mktemp+ln 원자성, SHA-256 분류, POSIX 이식성(bashism 회피). install-agents.sh 정독
4주최소 공개 & 로그 위생허용목록 vs 차단목록, jq로 새 객체 구성, 입력 검증, 유출 테스트. inspect-agent-runtime.sh+verify의 leak 테스트
5주(선택)Codex 플러그인 생태계커스텀 에이전트 TOML, 플러그인/마켓플레이스 매니페스트, 스킬(SKILL.md) 규격, 네이티브 서브에이전트 스폰

10핵심 키워드 사전

이 문서에 나온 개념 압축 정리
용어
오케스트레이터 / 구현자 / 리뷰어
sol-advisor의 세 역할. Sol 오케스트레이터(건축가·명세·검증), Terra 구현자(유일한 시공 lane), 신선한 Sol 리뷰어(read-only 준공검사). 위임은 위→아래 단방향, 검토와 수정은 절대 한 손에 쥐지 않는다.
용어
역할 핀 (role pinning)
모델·추론 강도를 호출 시점이 아니라 커스텀 에이전트 TOML에 못 박는 것. 스폰 호출은 모델을 지정하지 않는다 → 몰래 성능을 낮출 수 없다.
용어
조용한 대체 금지 (no silent fallback)
모델·강도·역할이 누락·불일치·관찰 불가면 자동 대체하지 않고 즉시 멈춘다. "애매하면 진행"이 아니라 "애매하면 정지".
용어
ship / fix-first / rethink
리뷰어의 세 판정. ship=완료 보고 가능, fix-first=고쳐서 재검증·재리뷰, rethink=아키텍처 재검토(완료 불가). 리뷰어가 직접 고치는 것은 금지.
용어
5부 구현 명세
OBJECTIVE·FILES/OWNERSHIP·INTERFACES·CONSTRAINTS·VERIFICATION로 위임하는 계약 양식. "증거 없는 완료 주장은 무효"가 핵심 반환 규칙.
용어
TOCTOU · 원자적 설치
검사–사용 시차 취약점. install-agents.sh는 변경 직전 상태 재검사 + mktemp+하드링크(ln, 이미 있으면 실패)로 덮어쓰기 사고를 원천 차단한다.
용어
SHA-256 분류 (classify)
목적지 파일을 missing/current/legacy/conflict/unsafe/unreadable 6상태로 판별. current·legacy·missing만 진행, conflict·unsafe는 건드리지 않고 정지.
용어
최소 공개 / 허용목록
민감 로그에서 "막을 것을 나열"하는 대신 "내보낼 것만 나열"해 새 객체를 구성. inspect-agent-runtime.sh가 jq로 허용 필드만 짓는 방식.
용어
관찰된 격리 vs 요청된 격리
리뷰어는 read-only를 요청하지만, 안전은 실제로 관찰된 샌드박스 정책으로만 주장한다. 관찰 불가·변조 시 "read-only였다" 거짓 주장 금지.
용어
커스텀 에이전트 (Codex)
TOML 하나로 정의하는 하위 에이전트 프로필(이름·모델·강도·권한·지침). 주 세션이 agent_type 이름만 대면 그 프로필로 네이티브 스레드가 뜬다.
용어
GPT-5.6 Sol / Terra / Luna
레포가 역할에 못 박아 참조하는 모델 이름. Sol=지휘·검토, Terra=구현, Luna=v0.2.0의 경량 lane(현재 폐기). 이 문서는 레포 용법 그대로 다루며 실제 모델 서열을 단정하지 않는다.

11참고 링크

더 파고들 때