DeepSeek 이 2026-08-13 에 deepseek-harness 를 공개했다. 보도는 대체로 두 가지에 몰렸다 — 스타 수가 폭발했다는 것, 그리고 “모든 것이 플러그인” 이라는 아키텍처. 둘 다 사실이다. 그런데 클론해서 파일을 세어보니 기사에서 한 번도 못 본 게 하나 나왔다.

이 리포에는 결정 739건의 원장이 들어 있다. 그중 11건은 거절된 제안인데, 지우지 않고 보관돼 있다.

사실관계

2026-08-27 기준 GitHub REST API 응답값과 리포 파일(b150a55, 얕은 클론) 실측이다.

항목
생성 / 최근 push 2026-08-13 / 2026-08-21
스타 / 포크 199,396 / 22,740
라이선스 / 주 언어 MIT / TypeScript
버전 0.1.1-rc.2 (루트 package.json)
Node 요구사항 ^22.19.0 \|\| >=24.0.0
워크스페이스 package.json 256개
packages/ 하위 그룹 약 50개 (llm session sandbox shell fs mcp skill …)

버전을 먼저 봐야 한다. 0.1.1-rc.2 이고, README 는 호환성 깨지는 변경이 있을 것이라고 대문자로 못박아 뒀다. 아래 내용은 오늘의 스냅샷이지 안정된 API 가 아니다.

성능·벤치마크 이야기는 이 글에서 다루지 않는다. 중립적인 제3자 헤드투헤드 측정이 아직 없고, 검색 상위에 뜨는 수치들은 대부분 출처를 확인할 수 없는 애그리게이터 글이다.

보도된 층: 플러그인 아키텍처

공식 페이지의 요지는 간명하다. 모델·툴·스킬·세션·샌드박스·스토리지·루프·스케줄링·UI 가 전부 플러그인이고, 그 조립을 Cordis 라는 별도 프레임워크가 맡는다. 256개 워크스페이스 패키지는 그 선언의 결과물이다. packages/llm 안에 llm-deepseek 이 다른 프로바이더와 나란히 한 칸을 차지하고 있는 게 이 설계의 상징이다.

여기에 단서를 하나 붙여야 공정하다. 프로바이더 중립성은 DeepSeek 이 직접 구현한 게 아니다. 멀티 프로바이더 지원은 서드파티 라이브러리(@earendil-works/pi-ai)에 위임돼 있고, 그 카탈로그에 있는 프로바이더를 붙이는 일은 코드 변경이 아니라 설정이라고 패키지 README 가 명시한다. 구조로 뒷받침된 중립성이라는 점에서 마케팅 문구보다 낫지만, 대신 프로바이더 지원 범위가 외부 의존성의 갱신 속도에 묶인다. 이건 트레이드오프지 결함이 아니다.

세어보니 나온 것: .agents/

리포 루트에 .agents/ 가 있다. 안에는 스킬 11개와, Agent Note 라고 부르는 결정 기록이 들어 있다.

파일을 세면 이렇다. 노트 하나는 영문 .md + 중문 .zh.md + .i18n.yaml 사이드카의 세 쪽이 한 벌이라, 파일 수를 그대로 결정 수로 읽으면 안 된다.

라이프사이클 결정 수
implemented/ 559 이미 반영된 결정
archived/ 143 반영됐으나 앞으로의 판단에 쓸모가 다한 것
proposed/ 26 아직 제안 상태
rejected/ 11 검토 후 기각된 제안
합계 739 (파일로는 2,217개)

경로 자체가 메타데이터다. {lifecycle}/{class}/yyyy-mm-dd-제목.md 꼴이고, 클래스는 architecture feature bug-fix simplification process testing 여섯 개의 닫힌 집합이다. 다른 폴더를 만들면 검사 스크립트가 거부한다. 클래스를 늘리려면 정본 집합과 문서를 같이 고쳐야 한다.

규율이 몇 겹 더 있다.

  • 라이프사이클 이동은 형식 재작성을 강제한다. proposed/implemented/ 로 옮기면 “제안” 절을 현재형 “결정” 으로 다시 쓰고 수용 기준·위험을 “결과” 로 접어야 한다. 게이트가 이걸 검사해서, 계획을 그대로 둔 채 폴더만 옮기는 건 통과하지 못한다.
  • 노트끼리의 상호 참조는 상대 마크다운 링크여야 한다. 산문이나 번호로 가리키는 걸 금지한다 — 기계로 검증 가능하고 파일이 옮겨져도 살아남게 하려는 것이다.
  • 중앙 INDEX.md 는 금지돼 있다. 그리고 그 금지의 근거를 담은 노트가 따로 있어서, 규칙이 어디서 왔는지 문서 안에서 추적된다.
  • 아카이브는 영구 동결이다. 옮길 때만 정해진 메타데이터 한 줄이 들어가고, 그 뒤로는 편집·번역·재포맷·삭제가 전부 금지된다. 문서 검사도 아카이브를 건너뛰고, 현재 동작의 근거로 인용하지 못한다.

그리고 이게 장식이 아니라는 증거. README.md 135개가 이 노트들을 308번 인용한다. 패키지 문서가 “왜 이렇게 설계했나” 를 자기 안에서 설명하지 않고, 그 결정을 소유한 노트를 가리킨다. 근거의 소유권이 한 곳에 있다는 뜻이다.

rejected/ 11건이 진짜 흥미로운 부분

코드는 무엇을 했는가를 남긴다. 커밋 로그도 결국 한 일의 목록이다. 어느 쪽도 무엇을 하지 않기로 했는가는 남기지 않는다. 그런데 팀이 반복해서 잃는 지식은 대개 후자다. 6개월 뒤 새로 온 사람이 “이거 왜 이렇게 안 하고 저렇게 했지” 라고 묻고, 아무도 답을 모르고, 그래서 한 번 기각했던 설계를 다시 시도한다.

rejected/ 는 그 자리를 겨냥한다. 보관 조건도 명시돼 있는데 — 원문 표현으로는 “Keep it only while its rationale prevents a tempting, meaningful mistake” — 근거가 유혹적인 실수를 막아주는 동안만 남기고, 그 효용이 끝나면 세 쪽을 통째로 지우라고 돼 있다.

이 조건이 중요하다. 기각 기록을 무한정 쌓으면 그건 그냥 쓰레기장이 된다. “막아주는 실수가 있는 동안만” 이라는 단서가 원장을 살아 있게 만든다. 실제로 11건뿐인 것도 그래서일 것이다 — 739건 중 1.5%다.

나도 같은 규율을 다른 맥락에서 쓰고 있다. 이 블로그에서 여러 번 쓴 얘기지만, 보호를 제공하지 않는 안전 통제는 남겨두면 안 된다. 남아 있으면 보호받고 있다는 착각을 주기 때문이다. 그럴 땐 통제를 지우고 “미완화 노출” 로 등재하는 편이 정직하다. rejected/ 의 보관 조건은 정확히 같은 사고를 문서 쪽에서 한 것이다. 근거가 아무 실수도 막지 않는 순간, 그 문서는 지식이 아니라 부채가 된다.

fail-closed 가 두 군데 박혀 있다

원장 다음으로 눈에 띈 건 실패 처리 방식이다. 두 곳에서 같은 선택을 한다.

샌드박스. 리눅스는 bwrap 을 먼저 찾고 안 되면 Landlock, macOS 는 Seatbelt, 윈도우는 ACL 제한 토큰 러너를 쓴다. 그리고 지원되지 않는 플랫폼이나 쓸 수 없는 러너를 만나면 SANDBOX_UNAVAILABLE실패한다. 격리 없이 조용히 실행되는 경로가 없다.

크리덴셜. 설정 파일에 API 키 값을 적지 않고 환경변수 이름(apiKeyEnv)만 적는다. 값이 아니라 참조다. 그리고 그 참조가 아무것도 가리키지 않으면 MISSING_CREDENTIAL실패한다. 환경에 우연히 들어 있는 다른 키로 인증을 시도하지 않는다.

둘 다 흔한 선택이 아니다. 대부분의 도구는 이런 자리에서 폴백을 “친절” 로 구현한다 — 샌드박스가 없으면 그냥 실행하고, 키가 없으면 다른 키를 찾아본다. 그 친절이 만드는 게 정확히 신호 없는 실패다. 격리 없이 돌고 있는데 로그는 정상이고, 엉뚱한 계정으로 과금되는데 에러가 안 난다. 에이전트 하네스처럼 남의 코드를 실행하는 물건에서는 시끄럽게 죽는 쪽이 옳다.

조사하면서 밟은 함정 하나

검색 상위에 app-deepseek-harness/deepseek-harness 라는 리포가 뜬다. 이름만 보면 공식 같다. GitHub API 로 조회하면 404 다. 공식은 deepseek-ai/deepseek-harness 하나뿐이다.

이름이 그럴듯한 미러와, 출처를 밝히지 않은 채 커밋 수·팀 구성·내부 코드명 같은 걸 단정적으로 적어둔 애그리게이터 글이 상당수 상위에 노출된다. 이 글은 그런 출처에만 존재하는 사실은 하나도 쓰지 않았다. 확인 방법은 단순하다 — 리포를 클론해서 직접 세면 된다.

가져갈 것

하네스를 직접 만들 일이 없어도 이 리포에서 복제할 수 있는 건 명확하다. 결정 원장이다.

거창한 도구가 필요하지도 않다. 필요한 건 네 가지뿐이다.

  1. 경로에 라이프사이클과 종류를 인코딩한다 (implemented/architecture/…).
  2. 종류를 닫힌 집합으로 두고 검사 스크립트로 강제한다. 열어두면 반년 안에 30개가 된다.
  3. 참조는 기계로 검증 가능한 형태로만 쓴다.
  4. 기각한 것도 남기되, 막아주는 실수가 있는 동안만 남긴다.

4번이 핵심이고, 동시에 대부분의 팀이 안 하는 것이다. ADR 을 쓰는 조직은 많은데 기각된 ADR 을 관리하는 조직은 드물다. 그런데 실제로 반복되는 사고는 “이미 검토했고 안 하기로 했던 걸 아무도 몰라서 다시 하는 것” 쪽에서 나온다.

739건 중 11건. 비율로는 작지만, 그 11건이 이 리포에서 제일 비싼 문서일 가능성이 높다.


출처와 검증 범위. 위 수치는 2026-08-27 기준 main(b150a55)을 얕은 클론해 직접 센 값이고, 스타·포크 수는 같은 시점의 GitHub REST API 응답값이라 시간에 따라 변한다. 결정 수는 영문 .md 파일만 세고 중문 번역본과 사이드카를 제외한 값이다 — 파일 수(2,217)와 다르다는 점을 본문에 밝혔다. 이 글은 리포의 설계 문서와 디렉터리 구조를 읽은 결과이며, 하네스를 실제로 실행해 동작을 검증하지는 않았다. 샌드박스·크리덴셜의 fail-closed 동작은 각 패키지 README 의 서술이지 내가 재현한 관측이 아니다. 성능·품질 비교는 중립 측정이 없어 다루지 않았다.

References