프레임워크
harness2는 모델 가중치를 고정한 채 에이전트의 실행 환경을 반복해서 개선하는 프레임워크입니다. 여기서 실행 환경은 프롬프트, 행동 제약, 기억, 도구 사용 안내, 하위 에이전트, 스킬, 보조 스크립트, 플러그인을 말합니다. 이 저장소가 바꾸는 것은 모델의 머릿속 지식이 아니라, 그 모델이 과제를 수행하는 방법입니다.
요리사인 모델은 그대로 둡니다. 기본 조리법으로 만든 음식과, 재료 확인 절차를 바꾼 음식과, 전문 조리법을 추가한 음식을 비교합니다. 그 차이를 보고 다음 조리 지침을 만들며, 다른 주문에도 쓸 만한 교훈은 주방의 기록장에 남깁니다.
한 주문 안에서 조리법을 다듬는 것이 과제 수준 재귀이고, 다음 주문을 위해 기록장을 갱신하는 것이 하네스 개선 수준 재귀입니다.
harness2/demo.py의 BASE_SCRIPT는 거래 금액을 합산하면서 양수만 포함하는 잘못된 스크립트입니다.
DemoProposer.call()은 그 필터를 제거합니다. 이는 모델을 호출하는 구현이 아니라, 수정 결과를 정해 둔 교육용 구현입니다.
# harness2/demo.py의 BASE_SCRIPT에서 핵심 부분 발췌
amounts = [Decimal(row['amount']) for row in csv.DictReader(source)]
total = sum((amount for amount in amounts if amount > 0), Decimal(0))
# DemoProposer.call()이 적용하는 수정
script.write_text(script.read_text().replace(" if amount > 0", ""))
첫 과제의 금액은 100.25, -20.10, 5.00입니다.
기존 스크립트의 합계는 손으로 계산하면 105.25, 수정 후에는 85.15입니다.
이 작은 차이가 제안·실행·비교·기억이라는 전체 흐름을 보여 줍니다.
데모의 수정 내용은 정해져 있지만 실행기는 실제 Python 스크립트를 실행하도록 작성돼 있습니다. 소스만 읽어도 인터페이스 분리, 실행 예산 계산, 재시도, 결과 보존을 하나의 사례로 연결할 수 있습니다.
TrendShift Weekly #4의 선정 대상이며, 2026-10-23 GitHub 기준 스타는 18,196개입니다. 저장소 생성일은 2026-10-06입니다. 짧은 기간에 관심을 모았다는 것은 알 수 있지만, 이 수치만으로 유입 경로나 사용자의 만족도를 설명할 수는 없습니다. 여기서는 코드에서 드러나는 주목할 이유를 살펴봅니다.
하네스를 바꾼 뒤 말로만 좋아졌다고 설명하는 대신, 같은 과제를 다시 수행한 기록을 비교 재료로 삼습니다.
harness2/core/recursion.py의 run_parallel()과 run_sequential()이 이 과정을 구체화합니다.
수정안의 설득력보다 수정 전후의 행동 차이를 근거로 삼는 점이 핵심입니다.
OpenCode와 Codex는 이 저장소에서 과제를 수행하는 실행기로 연결됩니다. Harness²는 그 위에서 설정을 고치고 비교하는 역할을 맡습니다. 따라서 둘을 완전히 대체하는 경쟁 제품으로 읽으면 구조를 오해하게 됩니다.
| 선택지 | 주된 역할 | Harness²의 장점과 대가 |
|---|---|---|
| OpenCode·Codex 실행기 | 주어진 환경에서 과제를 수행 | 실행기를 유지하며 환경 개선 루프를 추가할 수 있음. 실행 횟수와 설정 복잡도는 늘어남 |
| 수동 하네스 수정 | 개발자가 로그를 읽고 설정을 교체 | 제안·시험·합성·기록을 같은 절차로 반복. 자동 수정의 타당성은 검토해야 함 |
| 여러 답안 중 선택 | 답안을 여러 번 생성하고 하나를 채택 | 답안 외에 다음 실행에 재사용할 하네스와 경험도 남김 |
| 모델 미세 조정 | 학습으로 모델 가중치를 갱신 | 가중치 학습 없이 파일 수준에서 변경을 추적. 모델 자체의 능력 한계까지 해결하지는 않음 |
비교 표는 제품별 성능 순위가 아니라 개입하는 위치의 차이입니다. 다른 방법보다 무조건 빠르거나 저렴하다는 뜻은 아닙니다.
README는 세 전문 업무 벤치마크와 네 모델–하네스 구성에서 개선을 보고합니다. 최대 향상 폭은 WorkBuddy-Bench 11.5점, JobBench 4.5점, LAB의 부분 통과율 11.8퍼센트포인트라고 설명합니다. 이는 README의 연구 결과 주장이며 독립 재현 수치는 아닙니다.
점수와 퍼센트포인트는 같은 단위가 아닙니다. 또 최대값은 모든 모델·모든 과제에서 얻는 평균 향상을 뜻하지 않습니다.
dependencies/PINNED.md도 과거 논문 실험이 공개 실행 절차와 다른 과제·모델 배포·추가 도구를 사용했을 수 있다고 밝힙니다.
운동 루틴을 고치는 앱의 최고 기록과, 내가 같은 루틴으로 낼 기록은 다릅니다. 모델, 과제, 평가자, 네트워크 조건을 맞춘 뒤 비교해야 방법의 효과를 판단할 수 있습니다.
tests/test_workflow.py는 예산·재개, 증거 완전성, 잘못된 수정 재시도,
경험 미생성 처리, 선택 실패 후 평가 방지를 다루는 5개 테스트 메서드를 담고 있습니다.
성공하는 경로만큼 실패했을 때 무엇을 남기고 무엇을 재사용하지 않는지가 학습 재료입니다.
일반적인 웹 서비스의 상시 백엔드 서버가 중심은 아닙니다.
argparse로 명령을 받고, 파일과 하위 프로세스를 조정하는 Python 패키지가 중심입니다.
pyproject.toml의 프로젝트 버전은 0.1.0이며 지원 Python 범위는 아래와 같습니다.
# pyproject.toml에서 발췌
[build-system]
requires = ["setuptools>=77", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "harness2"
version = "0.1.0"
requires-python = ">=3.12,<3.14"
dependencies = []
dependencies = []는 핵심 패키지의 필수 Python 배포 의존성이 없다는 뜻입니다.
실제 모델 실행, 벤치마크 데이터, 문서 변환 도구까지 필요 없다는 뜻으로 넓혀 읽어서는 안 됩니다.
| 표준 라이브러리 | 실제 사용 위치 | 배울 개념 |
|---|---|---|
| dataclasses·typing | harness2/core/spec.py, harness2/core/tree.py | 설정값과 인터페이스를 명시적으로 표현 |
| concurrent.futures | harness2/core/recursion.py, harness2/core/schedule.py | 독립 작업만 동시에 실행하고 기록 순서는 고정 |
| pathlib·json·shutil | harness2/core/context.py, harness2/core/library.py | 파일 기반 증거·경험 저장 |
| subprocess·threading | harness2/core/proposer.py | 외부 실행기 호출과 동시 호출 수 제한 |
| fcntl·os.replace | harness2/core/schedule.py | 프로세스 간 잠금과 원자적 결과 교체 |
| 구분 | 버전·범위 | 근거와 역할 |
|---|---|---|
| 표 계산·발표자료 해석 | openpyxl>=3.1,<4python-pptx>=1,<2 | pyproject.toml의 render 추가 의존성 |
| 모델 연결 브리지 | litellm[proxy]==1.95.0fastapi==0.139.2google-auth==2.56.3 | 같은 파일의 bridge 추가 의존성. 기본 설치와 분리됨 |
| 패키지 빌드 | setuptools>=77, wheel | 정확히 고정한 버전이 아니라 하한 또는 버전 미지정 |
| OpenCode용 Bun | 1.3.11 | harness2/cli/setup.py에서 설치 버전 지정 |
| Codex 실행기 | 0.144.6 | harness2/config.py의 CODEX_VERSION |
| WorkBuddy OpenCode | 1.14.18 | WB_OC_HARNESS_VER와 버전 YAML에 명시 |
| 컨테이너 빌드 도구 | node:20-slimripgrep 14.1.1 | third_party/wb_runner/configs/harnesses/opencode/docker/Dockerfile |
이 버전은 커밋 1cfe254에 기록된 요구값입니다. 현재 권장 최신 버전이라는 의미는 아닙니다.
node:20-slim도 이미지 다이제스트로 고정한 형태는 아닙니다.
이 커밋에는 자체 웹 프론트엔드의 package.json, React·Vue 코드, 프론트엔드 빌드 설정이 없습니다.
사용자의 접점은 CLI와 결과 파일입니다. harness2-report도 캐시된 평가 JSON을 읽는 보고 명령입니다.
harness2/cli/bridge.py는 LiteLLM 프로세스를 시작해 모델 호출 인터페이스를 연결합니다.
직접 FastAPI 앱을 정의한 웹 제품으로 읽으면 안 됩니다.
WorkBuddy의 web 하위 집합은 평가 대상 과제 종류이지 이 프로젝트의 화면이 아닙니다.
harness2/cli/setup.py는 외부 저장소를 고정 커밋으로 가져오고 패치를 적용한 뒤,
OpenCode에는 bun install --frozen-lockfile --ignore-scripts,
벤치마크에는 uv sync --locked --python 3.12를 사용하도록 작성돼 있습니다.
주요 고정 커밋은 config.DEPENDENCY_PINS 기준으로 다음과 같습니다.
| 외부 저장소 | 고정 커밋 앞 12자리 | 역할 |
|---|---|---|
| job-bench-eval | fa03a17f9ff6 | 전문 직무 과제와 평가 연동 |
| workbuddy-bench | b516950be5b5 | 문서·웹·코드 과제 환경 |
| harvey-labs | b58a28ae9fde | 법률 업무 과제 환경 |
| opencode | 23fb5e0516c9 | 기본 에이전트 실행기 |
루트에 .github/workflows/는 없으므로 자동 CI가 구성됐다고 단정할 수 없습니다.
pyproject.toml에는 Ruff 대상 py312, 줄 길이 100,
검사 선택 E4/E7/E9/F/I가 있습니다. Ruff 자체의 설치 버전은 이 파일에서 고정하지 않습니다.
>=3.1,<4는 허용 범위이고, ==1.95.0은 정확한 버전입니다.
Git 커밋 고정은 저장소의 특정 내용을 선택합니다. 범위·태그·커밋·잠금 파일은 재현성의 강도가 서로 다릅니다.진입점은 pyproject.toml의 harness2 = "harness2.cli.run_sweep:main"입니다.
CLI가 벤치마크 어댑터와 편집자를 만든 뒤 schedule.run_sweep()에 넘깁니다.
핵심 호출 관계를 단순화하면 다음과 같습니다.
harness2/core/spec.py의 BenchmarkAdapter(Protocol)은
과제 목록, 도메인, 지시문, 실행, 산출물 읽기 등의 계약을 선언합니다.
harness2/benchmarks/jobbench.py의 JobBenchAdapter,
harness2/benchmarks/lab.py의 LabAdapter, harness2/benchmarks/workbuddy.py의 WbAdapter가 실제 차이를 담당합니다.
# harness2/core/spec.py의 계약 일부를 줄여 표시
class BenchmarkAdapter(Protocol):
spec: BenchSpec
substrate: SubstrateLike
def tasks(self, split: str = "all") -> list[str]: ...
def task_prompt(self, task_id: str) -> str: ...
def execute(self, task_id: str, harness_dir: Path | None,
run_id: str, *, timeout: int | None = None) -> Path: ...
방법은 제안·합성 절차, 실행 기반은 OpenCode·Codex,
벤치마크는 과제와 평가 방식입니다. 여기에 편집 모델로 연결하는 ChannelSpec도 별도 값으로 둡니다.
편집자가 사용하는 채널과 과제를 푸는 실행기를 같은 개념으로 취급하지 않는 것이 중요합니다.
Protocol은 필요한 메서드의 모양을 적은 약속입니다.
어댑터는 서로 다른 외부 도구를 그 약속에 맞춰 연결합니다.
알고리즘이 벤치마크별 폴더 구조나 실행 명령을 모두 알 필요가 없어집니다.recursion.run_parallel()은 기본 실행을 공유한 상태에서 일반 개선 INV와
도메인 개선 DOM을 각각 k개 제안합니다.
이 2k개 후보를 시험한 뒤, 전체 증거를 보고 독립적인 합성 하네스 agg1..aggk를 만듭니다.
recursion.run_sequential()은 현재 하네스로부터 INV·DOM을 제안하고 시험한 뒤
c1을 합성합니다. 그 하네스와 누적 기록이 다음 회차에 들어갑니다.
코드의 current_harness = comp.tree와 history 갱신이 깊이를 만드는 연결점입니다.
harness2/core/ledger.py는 한 모드·한 과제의 논리적 예산을 다음처럼 검사합니다.
실행 예산을 코드의 불변식으로 두면, 실험 방식이 달라도 같은 기준으로 비교할 수 있습니다.
# harness2/core/ledger.py의 예산 정의
def expected_rollouts(k: int) -> int:
return 4 * int(k)
def expected_sessions(k: int) -> int:
return 3 * int(k)
# R = 기본 k + 후보 2k + 합성 k
# P = INV 제안 k + DOM 제안 k + 합성 k
Ledger.assert_identity()는 개수뿐 아니라 중복 라벨도 검사합니다.
k=1이면 한 모드의 R은 4, P는 3입니다.
두 모드를 함께 실행할 때 기본 실행은 공유하므로 과제 실행 예산은 k + 3k + 3k = 7k개입니다.
이 수식은 API 요청 총횟수나 총요금이 아닙니다. 편집 세션 안에도 여러 모델 호출이 있을 수 있고,
재시도·선택·회고·평가는 별도입니다. session_attempts와 논리적 단계 수를 구분해야 합니다.
harness2/core/context.py의 build()는 편집자가 읽을 증거 디렉토리를 구성합니다.
mission()은 거대한 본문을 붙이는 대신 어디에 무엇이 있는지 알려 줍니다.
파일을 필요할 때 읽는 방식은 입력을 구조화하지만, 모델의 읽기 비용과 문맥 한도까지 없애 주지는 않습니다.
build()는 assert_no_leak_paths()와 assert_no_grader_verdicts()를 호출합니다.
정답 파일 경로와 평가 결과의 알려진 표식을 검사합니다.
WorkBuddy의 harness2/benchmarks/wb_render.py:_admit()는 산출물로 읽을 위치를 허용 목록으로 제한합니다.
다만 “전체 기록”이라는 표현에도 범위가 있습니다.
BenchSpec.obs_trunc의 기본값은 관찰 하나당 50,000자이며,
WorkBuddy의 TRAJ_MAX_CHARS는 2,000,000자입니다.
파일로 제공한다는 것과 원시 로그를 한 글자도 자르지 않는다는 것은 다릅니다.
harness2/core/library.py의 Library.add()는 채택한 하네스 전체와
EXPERIENCE.md를 저장합니다. 경험은 cue·lesson·evidence가 모두 있어야 합니다.
벡터 검색이나 별도 데이터베이스가 아니라, 도메인별 파일과 INDEX.md를 사용하는 구조입니다.
schedule.run_domain()은 과제를 순서대로 처리하며 Library.retain()에 이전 과제 목록만 넘깁니다.
agg와 seq의 경험 저장소도 나뉩니다.
이후 과제의 결과가 앞선 과제에 섞이는 시간 순서 누출을 줄이는 설계입니다.
harness2/core/tree.py는 하네스를 dict[str, str], 즉 “상대 경로 → 내용”으로 표현합니다.
SurfaceSpec은 실행기별 허용 경로·길이·스킬 규칙을 값으로 기술합니다.
normalize_rel()은 절대 경로와 .. 경로를 거부합니다.
| 검증 대상 | 소스의 처리 |
|---|---|
| 허용된 파일인가 | read_tree()·is_allowed()가 편집 가능 경로를 판별 |
| 설정과 문법이 유효한가 | validate()가 길이·스킬·스크립트 문법·훅 등을 검사 |
| 수정이 실패했는가 | recursion._run_stage()가 잘못된 제안을 한 번 재시도하고 이후 현재 하네스로 대체 |
| 완료 결과를 재사용해도 되는가 | schedule._resume()이 산출물·하네스·지문을 확인 |
| 기록이 쓰다 끊기지 않는가 | _write_summary()가 잠금 후 임시 파일을 os.replace()로 교체 |
harness2/substrate/opencode.py의 상시 지침 상한은 24,000자,
harness2/substrate/codex.py의 상한은 8,000자입니다.
이는 len(body)로 검사하는 문자 수이며 토큰 수가 아닙니다.
Codex는 AGENTS.md, OpenCode는 네 상시 지침 파일을 사용하므로 같은 개념도 실제 배치는 다릅니다.
파일 이름이 있다고 완료로 취급하지도 않습니다.
harness2/core/runmark.py는 .adapt_complete와 하네스 지문을 기록합니다.
harness2/cli/run_sweep.py:_check_identity()는 모델·과제·시드 등이 다른 실험을 기존 결과에 섞지 못하게 합니다.
selection_pool()은 합성된 최종 후보 k개만 선택 대상으로 삼습니다. 기본 실행은 제외됩니다.
따라서 “기본보다 나쁠 때 항상 기본으로 돌아간다”는 보장은 없습니다.
k=1에서는 별도 선택 세션 없이 유효한 단일 최종 후보를 채택합니다.
평가 점수는 채택 후 별도로 계산하지만, 공개 정답이 네트워크로 유입되는 것까지 파일 검사만으로 막지는 못합니다. 편집 경로 검증도 운영체제 샌드박스를 대신하지 않습니다.
| 읽을 위치 | 답을 얻을 질문 |
|---|---|
harness2/demo.py | 가장 작은 과제·수정·산출물은 어떻게 생겼나 |
harness2/core/spec.py | 벤치마크가 구현해야 하는 계약은 무엇인가 |
harness2/core/recursion.py | 후보는 언제 생성되고 어떤 증거로 합성되는가 |
harness2/core/schedule.py | 과제 순서·재개·모드 간 공유는 어디서 정하는가 |
harness2/core/selection.py | 후보를 어떻게 익명화하고 경험을 어떻게 추출하는가 |
harness2/benchmarks/wb_render.py | 산출물 내용과 평가자 출력을 어떻게 구분하는가 |
third_party/patches/ | 외부 도구 원본과 통합 코드의 차이는 무엇인가 |
커밋 1cfe254의 텍스트 파일 규모는 확장자별로 다음과 같습니다.
아래는 빈 줄·주석을 포함한 물리적 줄 수이며, .git과 바이너리 자산은 제외합니다.
외부 저장소를 설치했을 때 추가되는 코드까지 포함한 수치가 아닙니다.
| 언어·형식 | 파일 수 | 대략 줄 수 |
|---|---|---|
| Python | 58 | 15,861 |
| Shell | 4 | 668 |
| YAML | 7 | 155 |
| TOML | 1 | 44 |
| Dockerfile | 1 | 81 |
| Markdown | 21 | 853 |
| JSON | 2 | 67 |
Python 중 harness2/가 39파일·12,747줄,
third_party/가 13파일·2,591줄,
scripts/가 5파일·294줄, 테스트가 1파일·229줄입니다.
본체 안의 harness2/core/는 5,688줄로, 인터페이스와 실험 제어를 집중해서 읽기 좋은 크기입니다.
harness2/core/는 실험 절차서, harness2/substrate/는 기계 연결 규격,
harness2/benchmarks/는 시험 종목별 담당자입니다.
외부 실행기 코드를 먼저 전부 읽기보다 이 세 경계가 주고받는 값을 먼저 확인하세요.
초보자가 가져갈 가장 큰 기술은 AI 호출법보다, 바뀌는 외부 환경을 작은 계약 뒤에 가두는 설계법입니다. 아래 항목은 서로 독립적으로 연습할 수 있습니다.
harness2/core/spec.py의 ChannelSpec·BenchSpec은 데이터 클래스이고,
BenchmarkAdapter는 Protocol입니다. __post_init__()는 잘못된 설정을 생성 시점에 거부합니다.
연습: 채널만 바꾸거나 모델만 바꾸면 왜 오류가 나도록 했는지
resolve_channel_model()을 따라 적어 보세요. 외부 API의 식별자 형식까지 계약의 일부라는 점을 배울 수 있습니다.
recursion._roll_many()는 독립 실행을 스레드 풀로 보낸 뒤 입력 순서에 맞춰 ledger를 기록합니다.
schedule.run_domain()은 경험 의존성이 있는 과제들을 순차 처리합니다.
연습: 후보 실행 시간이 서로 달라도 라벨과 예산 기록이 같아야 하는 이유를 설명해 보세요. 병렬화할 수 있는 작업과 순서를 지켜야 하는 작업을 선으로 나누는 것이 목표입니다.
context.build()는 지시문·원자료·실행 기록·산출물을 구분하고,
ContextTree.layout은 실제 존재하는 항목만 안내합니다.
spec.proposer_deliverables에 따라 편집자에게 내용 또는 파일 이름만 보여 줄 수도 있습니다.
연습: 디렉토리마다 누가 쓰고 누가 읽는지 표를 만드세요. 파일 기반 증거가 검색 가능한 지식베이스와 어떻게 다른지도 정리해 보세요.
harness2/core/judge.py의 Scored.graded와 frac은
평가 실패와 낮은 점수를 구분합니다. 평가에 실패한 값은 None이며 분모에서 제외하도록 설계돼 있습니다.
연습: 점수가 1.0, 0.5, None일 때 유효 평가 평균과
실패를 0점 처리한 평균을 각각 계산하세요. 평균과 함께 완료 건수·미평가 건수를 보고해야 하는 이유가 드러납니다.
runmark.fingerprint()는 파일을 경로순으로 읽어 경로와 내용의 지문을 만들고,
schedule._resume()은 채택 하네스와 산출물이 유지되는지 확인합니다.
_check_identity()는 실행 조건이 달라진 결과의 혼합을 막습니다.
연습: 모델 이름, 과제 목록, 하네스 내용, 로그 수정 중 어떤 변경이 어떤 검사에 걸리는지 분류하세요. 이 지문은 결과 재사용을 위한 식별 수단이며, 악의적 변조를 막는 서명 체계는 아닙니다.
하네스 개선은 모델 학습이 아니므로, 먼저 챙길 자원은 GPU보다 실행 환경과 반복 호출 예산입니다. 다만 이 말이 모든 외부 벤치마크가 가볍다는 뜻은 아닙니다.
| 목적 | 필요 환경 | 자원 판단 |
|---|---|---|
| 소스 읽기·손계산 | 텍스트 편집기와 Python 문법 이해 | 모델 계정·GPU·Docker 불필요 |
| 공식 로컬 데모 | Python 3.12 또는 3.13, 패키지 실행 환경 | 모델 인증 불필요. 작은 CSV와 Python 하위 프로세스 사용 |
| JobBench·LAB | 문서 권장 Linux·Python 3.12, Node.js 20+, uv, Google Cloud CLI | 외부 실행기·데이터·모델 접근 권한 필요. LAB는 Pandoc·Poppler 추가 |
| WorkBuddy | 위 환경에 Docker Engine과 컨테이너 실행 권한 추가 | 이미지·과제 데이터·동시 컨테이너가 메모리와 디스크 사용량을 좌우 |
| Codex 연결 | 지정된 실행기와 모델 엔드포인트. 필요 시 bridge 추가 의존성 | 컨테이너에서 브리지까지 도달할 수 있는 네트워크 구성 필요 |
README와 설치 문서에는 최소 CPU 코어 수, RAM 용량, 디스크 용량, GPU VRAM이 수치로 정리돼 있지 않습니다. 따라서 “메모리 몇 GB면 전체 벤치마크가 된다”고 단정할 근거는 없습니다. 기본 경로는 원격 모델 호출이므로 자체 모델 가중치를 GPU에 올리는 과정은 포함하지 않습니다.
schedule._write_summary()가 사용하는 fcntl,
Shell 실행기, 외부 도구 의존성을 함께 보면 Linux 권장에는 이유가 있습니다.
pyproject.toml의 POSIX 분류만으로 모든 macOS·Windows 조합이 검증됐다고 해석해서는 안 됩니다.
한 과제·한 모드에서 k=2면 과제 실행 8개와 개선 단계 6개가 논리적 기본량입니다.
여기에 최종 후보 선택, 회고, 재시도, 사후 평가를 더해야 합니다.
토큰 길이와 모델 단가가 없으므로 이 횟수를 달러 요금으로 바로 바꿀 수는 없습니다.
| 설정값 | 코드 기준값 | 의미 |
|---|---|---|
--workers | 기본 1 | 동시에 처리할 도메인 수. 과제 하나의 모든 내부 호출 수와는 다름 |
PHASE_WIDTH | 2 | 후보 생성·실행 단계의 기본 병렬 폭 |
PROPOSER_CONCURRENCY | 2 | 편집 세션 동시 호출 제한 |
WB_MAX_JOBS / WB_MAX_TRIALS | 실행기별 1 / 2 | WorkBuddy 작업·시도 동시성 제한에 사용 |
ChannelSpec.timeout | 3,600초 | 편집 채널의 기본 제한 시간. 실제 작업의 보장 실행 시간은 아님 |
README와 docs/EXPERIMENTS.md는 실행기 네트워크가 제한되지 않으며 Codex 샌드박스가 비활성화된다고 명시합니다.
이 구조를 그대로 개인 자료나 운영 시스템에 연결하는 것을 안전한 기본값으로 볼 수 없습니다.
공개 과제의 평가 기준 접근 여부도 결과 해석에 영향을 줍니다.
아래 과제는 저장소 파일을 변경하지 않고 수행할 수 있습니다. 실행 전에 예상 결과와 실패 조건을 적어 보는 습관이, 자동화된 에이전트를 이해하는 가장 빠른 연습입니다.
읽을 곳: harness2/demo.py의 BASE_SCRIPT,
DemoAdapter.__init__(), DemoProposer.call().
완료 기준: 첫 과제의 105.25 → 85.15,
두 번째 과제의 35.50 → 20.25를 설명하고,
이 데모는 실제 LLM의 개선 능력을 측정하는 예제가 아니라는 점을 구분합니다.
읽을 곳: harness2/core/recursion.py의 두 실행 함수와 harness2/core/ledger.py.
c1, c2로 바꿔 나열합니다.완료 기준: 각 모드의 R=8, P=6과 두 모드 합산 과제 실행 예산 14개를 구분합니다. 재시도·선택·회고가 왜 이 원장의 기본식 밖에 있는지도 적습니다.
읽을 곳: harness2/core/context.py:build(),
harness2/benchmarks/wb_render.py:ALLOWLIST, _admit().
verifier/score.json과 verifier/raw_artifacts/report.xlsx를 비교합니다.완료 기준: office 하위 집합에서 전자는 허용 경로가 아니고 후자는 허용 경로에 해당함을 설명합니다. 경로 허용 후에도 평가자 작성 흔적 검사가 별도로 있다는 점까지 찾으면 좋습니다.
읽을 곳: schedule._resume(), runmark.fingerprint(),
harness2/cli/run_sweep.py:_check_identity(), tests/test_workflow.py.
완료 기준: summary.json의 존재만으로 재개하지 않는 이유와,
결과 재사용 여부 검사와 실험 설정 혼합 방지의 차이를 설명합니다.
읽을 곳: harness2/core/spec.py:BenchmarkAdapter,
harness2/demo.py:DemoAdapter, harness2/core/library.py:Library.
tasks·task_prompt·execute·trajectory·score의 계약을 적습니다.완료 기준: 재귀 알고리즘을 바꾸지 않고 새 어댑터로 연결할 수 있는 명세를 만듭니다. 구현보다 먼저 정답 누출 경로와 완료 판정을 적는 것이 목표입니다.
주당 4~6시간을 기준으로 한 학습 제안입니다. Python 기본 문법이 낯설다면 1주 차를 더 길게 잡으세요. 매주 읽은 코드의 입력·출력·실패 조건을 한 장으로 정리하면, 추상적인 설계 용어가 실제 동작과 연결됩니다.
| 주차 | 학습 내용·읽을 코드 | 남길 결과물 |
|---|---|---|
| 1주 차 | Path, 타입 힌트, 데이터 클래스, Decimal과 CSV.harness2/demo.py → harness2/core/spec.py | 데모 합계 계산표, 어댑터 메서드별 입력·출력 목록 |
| 2주 차 | Protocol, 의존성 분리, 병렬 작업의 의존 관계.harness2/substrate/base.py → harness2/core/recursion.py → harness2/core/ledger.py | 병렬·순차 흐름도와 k=1·2·3 예산표 |
| 3주 차 | 파일 기반 문맥, 허용 목록, 경험의 시간 순서.harness2/core/context.py → harness2/benchmarks/wb_render.py → harness2/core/library.py | 데이터 접근 경계 표와 경험 저장 형식 설명 |
| 4주 차 | 원자적 저장, 멱등성, 평가 결측값, 회귀 테스트.harness2/core/schedule.py → harness2/core/runmark.py → harness2/core/judge.py → 테스트 | 재개 판정표와 새 벤치마크 설계 명세 |
“재귀적으로 개선한다”를 current_harness의 갱신과
Library.add()의 저장이라는 두 동작으로 설명할 수 있으면 핵심을 이해한 것입니다.
이후에는 성능 그래프를 볼 때도 무엇을 바꾸고 무엇을 고정했는지 먼저 질문할 수 있습니다.
| 용어 | 쉬운 설명 |
|---|---|
| 하네스 | 모델이 일하는 방식을 정하는 지침·도구·기억·실행 제어의 묶음 |
| 과제 수준 재귀 | 현재 과제 안에서 하네스를 수정하고 다시 시험하는 반복 |
| 하네스 개선 수준 재귀 | 채택 결과와 교훈을 다음 과제의 개선 재료로 남기는 반복 |
| Propose–Probe–Compose | 수정안을 제안하고, 실제로 시험하고, 차이를 근거로 합성하는 세 단계 |
| INV·DOM | 여러 업무에 통할 일반 개선과 특정 업무 영역에 맞춘 개선의 두 범위 |
| 실행 기반·substrate | 실제로 과제를 수행하는 에이전트 실행 환경. 여기서는 OpenCode 또는 Codex |
| 어댑터 | 외부 시스템의 다른 사용법을 내부의 공통 계약으로 바꿔 주는 연결 부품 |
| 롤아웃·rollout | 어떤 하네스로 과제 하나를 수행한 한 번의 실행 |
| 실행 기록·trajectory | 에이전트가 취한 행동과 도구의 응답을 시간 흐름에 맞춰 표현한 기록 |
| 산출물·deliverable | 과제가 요구한 최종 파일이나 결과. 단순히 실행이 종료됐다는 사실과 다름 |
| 편집 표면·SurfaceSpec | 실행기별로 수정할 수 있는 경로, 길이, 형식 규칙을 모아 둔 명세 |
| 문맥·context | 이번 판단에 필요한 지시문과 증거. 이 프로젝트는 이를 파일 트리로 구성 |
| 경험 라이브러리 | 같은 도메인의 앞선 과제에서 얻은 하네스와 근거 있는 교훈의 저장소 |
| 블라인드 선택 | 후보의 원래 라벨 대신 익명 식별자를 보여 주고 산출물이나 허용된 실행 기록을 비교하는 방식 |
| 정답 누출 | 정답·평가 기준·채점 결과가 풀이 또는 개선 단계의 입력에 섞이는 문제 |
| 불변식·invariant | 실행 방식이 바뀌어도 반드시 성립해야 하는 규칙. 예: R=4k, P=3k |
| 멱등성 | 같은 실행 식별자로 반복 요청해도 완료 결과를 불필요하게 다시 만들지 않는 성질 |
| 원자적 교체 | 임시 파일을 다 쓴 뒤 최종 이름으로 한 번에 교체해 중간 내용을 노출하지 않는 방식 |
| 지문·fingerprint | 파일 경로와 내용을 요약한 식별값. 하네스가 바뀌었는지 판단하는 데 사용 |
| 회귀 테스트 | 수정 뒤에도 기존의 중요한 동작과 실패 처리가 유지되는지 검사하는 테스트 |
| 시드·seed | 과제 순서를 재현하기 위한 값. 모델이 생성하는 답변까지 같게 고정하는 값은 아님 |
| 퍼센트포인트 | 두 비율의 단순 차이. 통과율 50%에서 60%는 10퍼센트포인트 증가 |
| 항목 | 상태 |
|---|---|
| 저장소 | google-research/harness2 |
| 선정 | TrendShift Weekly #4 |
| 스타 / 포크 | 18,196 / 1,769 — 2026-10-23 GitHub 기준 |
| 생성일 | 2026-10-06 |
| 주 언어 | Python |
| GitHub 설명 | 비어 있음. 패키지 설명은 pyproject.toml에 별도로 존재 |
| 최신 릴리스 | 없음 — 2026-10-23 GitHub 기준. 패키지 내부 버전은 0.1.0 |
| 최근 push | 2026-10-14 — GitHub 기준 |
| 분석 기준 커밋 | 1cfe254 · 2026-10-13 · Fix arXiv link커밋 시각은 -05:00 기준이며 UTC·한국 시각으로는 10월 14일 |
| 코드 규모 | Python 58파일·약 15,861줄. 본체 12,747줄, core 5,688줄. 주석·빈 줄 포함 |
| 테스트 | tests/test_workflow.py 229줄·테스트 메서드 5개 |
| 라이선스 | 본체 Apache-2.0. 외부 실행기·데이터에는 각자의 조건이 적용됨 |
| 제품 지원 | README는 Google이 공식 지원하는 제품이 아니라고 명시 |
dependencies/PINNED.md에는 실행기 파일이 harness2/third_party/에 속하며
이 사본에는 없다는 문장이 남아 있습니다. 그러나 이 커밋에는 루트 third_party/에 파일이 있고,
config.THIRD_PARTY = ROOT / "third_party"와 install.overlays()도 그 경로를 사용합니다.
해당 문장을 실제 디렉토리 구조보다 우선해서 읽으면 안 됩니다.
배포 설명도 일치 여부를 추가 확인해야 합니다.
third_party/README.md는 실행기 자산이 wheel에 포함된다고 설명하지만,
MANIFEST.in의 관련 경로는 harness2/third_party이고 실제 위치와 다릅니다.
이 정적 차이만으로 특정 배포 파일의 구성을 확정할 수는 없으므로,
소스 트리에서 확인한 구조와 wheel 설치 환경의 동작을 동일시하지 않는 편이 정확합니다.
성능 향상 수치는 README의 연구 결과 주장입니다. 모델 배포·과제 데이터·웹 접근·평가자 조건이 바뀌면 결과도 달라질 수 있습니다. 시드는 과제 순서를 재현하지만 모델의 답변까지 고정하지 않습니다.
합성 후보만 선택하므로 항상 기본 성능 이상을 보장하지 않습니다. 잘못된 편집의 대체 처리, 평가 데이터 표식 검사, 완료 지문은 각각 유용하지만 완전한 품질 보증이나 실행 격리는 아닙니다.
전체 실행 시간·요금·최소 하드웨어 사양은 이 코드만으로 확정할 수 없습니다. 본체의 Apache-2.0 표기는 외부 벤치마크와 데이터까지 같은 조건이라는 뜻이 아닙니다. 가장 먼저 배울 대상은 성과 수치보다 증거를 구성하고 실패를 기록하는 설계입니다.