From a70c27445b131700dfb0e2a9610ea7434fb7ca65 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 16:59:09 +0900 Subject: [PATCH 1/9] =?UTF-8?q?docs:=20=ED=95=98=EB=84=A4=EC=8A=A4=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=E2=86=94=ED=98=84=EC=9E=AC=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EB=B6=88=EC=9D=BC=EC=B9=98=20=EB=B3=B4=EA=B3=A0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(BIOP02-100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reviewer 팬텀 에이전트(문서 6곳 참조·실체 없음), 프로젝트 에이전트 cwd 로딩, 검증게이트↔외부리뷰 순서를 정리. draft 경로(ff0ec25) 해소 및 검증게이트 3종 실재는 확인만. 과거 문서 미삭제 — 새 보고서 추가. --- docs/HARNESS-RECONCILIATION-2026-07-26.md | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/HARNESS-RECONCILIATION-2026-07-26.md diff --git a/docs/HARNESS-RECONCILIATION-2026-07-26.md b/docs/HARNESS-RECONCILIATION-2026-07-26.md new file mode 100644 index 0000000..7800463 --- /dev/null +++ b/docs/HARNESS-RECONCILIATION-2026-07-26.md @@ -0,0 +1,85 @@ +# 논문 생산 하네스 — 구조 ↔ 현재 상태 불일치 보고 (BIOP01) + +- **작성**: 이건규 (Geon-Gyu LEE) · 2026-07-26 +- **관련 티켓**: BIOP02-100 (논문 생산 하네스 검토 — 원본·BIOP01·BIOP02) +- **검토 대상**: BIOP01의 논문 생산 하네스 문서·에이전트 (`docs/HARNESS.md`, `CLAUDE.md` *Agent routing & artifact contract*, `.claude/agents/*`, `.claude/skills/paper-production-orchestrator/SKILL.md`) +- **검증 기준**: `gglee` 브랜치 (kkkim-pipeline 기준, tip `ee9d836`) 실제 파일. 아래 모든 항목은 리포 파일을 직접 확인한 결과이며 `/workspace` 사본이 아님. +- **7/21 회의 합의 반영**: 하네스 *구조*는 수정하지 않고 현황만 정리. 구조 변경이 필요한 항목은 후속 티켓으로 분리했다. + +--- + +## 요약 (TL;DR) + +- **확정 불일치 2건**: (M1) `reviewer` 팬텀 에이전트 — 문서 6곳에서 라우팅/멤버로 참조되나 실체(`.claude/agents/reviewer.md`) 없음. (M3) 프로젝트 스코프 에이전트가 **cwd 의존**으로 로드 실패(`agent type not found`) — 실행 전제(repo 루트)가 어디에도 문서화되지 않음. +- **설계 관찰 1건**: (M2) orchestrator 실행흐름에서 **외부 리뷰(step 7)가 결정론적 검증 게이트(step 8)보다 먼저** 배치됨. 게이트를 리뷰 앞에 두는 게 통상 순서. +- **이미 해소됨 1건**: (M4) 산출물 계약의 원고 경로가 구 `draft.md` → 정본 `draft_v2.md`/`draft_v2_ko.md`로 정리됨(kkkim, commit `ff0ec25` 계열, 본 브랜치 기준에도 반영 확인). +- **정상 확인**: 실재 에이전트 9개, orchestrator는 에이전트가 아닌 Skill로 실재, 검증 게이트 스크립트 3종(`p3_concordance.py`·`p3_crossdataset_concordance.py`·`p3_scrambled_null.py`) 모두 SKILL.md 명령 경로와 일치. + +--- + +## 1. 확정 불일치 + +### M1 — `reviewer` 팬텀 에이전트 (구조 판단 필요) + +`.claude/agents/`에 실재하는 에이전트는 **9개**: `design`, `hspc-velocity-analyst`, `literature-scout`, `manuscript-writer`, `novelty-strategist`, `paper-critic`, `paper-orchestrator`, `presenter`, `research-methodologist`. **`reviewer.md`는 없다.** + +그런데 `reviewer`는 다음 6곳에서 실재 멤버/라우팅 대상으로 등장한다: + +| 위치 | 내용 | +| --- | --- | +| `docs/HARNESS.md:28` | 멤버 명부 #9 `reviewer` (전역, 선택) | +| `docs/HARNESS.md:49` | 관계도(org chart)에 `reviewer(선택)` | +| `docs/HARNESS.md:62` | 표준 경로 `paper-critic ──▶ reviewer ──▶ manuscript/REVIEW-*.md` | +| `CLAUDE.md:63` | "모든 논문 멤버(novelty·literature·methodologist·writer·critic·**reviewer**)는 …" | +| `CLAUDE.md:76` | 라우팅표: "정식 venue 리뷰 시뮬레이션" → `reviewer` (전역, 선택) | +| `CLAUDE.md:89` | 산출물 계약: 리뷰 단계 Writer = `paper-critic / reviewer` | +| `SKILL.md:3,28,51,73` | description·멤버 구성·실행흐름 step7·산출물 계약 모두 `reviewer` 호출 | + +**영향**: 자연어 "정식 venue 리뷰 시뮬레이션" 요청 → 존재하지 않는 에이전트로 라우팅 → (M3와 겹치면) `agent type not found`. 문서는 `reviewer`를 **"전역(global), 선택"** 으로 표기하는데, 이는 프로젝트 스코프(`.claude/agents/`)가 아니라 **유저 전역(`~/.claude/agents/`)에 두겠다는 의도**로 읽힌다. 그러나 이 환경엔 전역 위치에도 없다. + +**판단 포인트(후속 티켓)**: (a) `reviewer`를 전역 에이전트로 **실체화**, (b) 문서에서 제거하고 `paper-critic`으로 **통합**, (c) 계속 "선택 전역"으로 두되 설치 안내를 문서화 — 중 택1. → **FT1**. + +### M3 — 프로젝트 스코프 에이전트의 cwd 의존 로딩 (구조 판단 필요) + +`.claude/agents/`의 프로젝트 에이전트는 Claude Code가 **cwd = repo 루트(또는 프로젝트 내부)** 일 때만 발견된다. cwd가 상위 디렉터리(예: `/home/kkkim/project`)면 `paper-critic`/`hspc-velocity-analyst` 호출 시 `agent type not found` → `general-purpose`로 폴백(7/21 kkkim 재현 기록). + +이는 Claude Code의 동작 특성이지만, **하네스 문서 어디에도 "repo 루트에서 실행" 전제가 없다.** 하네스 사용성에 직접 영향. + +**판단 포인트(후속 티켓)**: (a) `CLAUDE.md`/`docs/HARNESS.md`에 "실행 cwd = repo 루트" 전제 명시, (b) cwd 무관 로드가 필요한 멤버(특히 M1의 `reviewer`)는 전역(`~/.claude/agents/`) 배치로 분리. → **FT2**. (M1과 연동.) + +--- + +## 2. 설계 관찰 (검토 질문 답변에 포함) + +### M2 — 검증 게이트 ↔ 외부 리뷰 순서 + +`SKILL.md` 실행흐름: **step 7 `(선택) 정식 리뷰 reviewer` → step 8 `검증 게이트`**. `docs/HARNESS.md:62–64` 표준경로도 `paper-critic ▶ reviewer ▶ REVIEW` 다음에 `verify-gate ▶ presenter`. 즉 **외부 referee가 결정론적 숫자 재계산 게이트보다 먼저** 돈다. + +헤드라인 숫자가 검증되기 전에 외부 리뷰를 소모하는 순서라, "내부 검수+검증 게이트를 먼저, 그다음 외부 referee"가 더 안전하다. (현재는 `reviewer`가 선택+팬텀이라 실무상 거의 안 돌지만, 구조 기술로는 어긋남.) → 권고: 게이트를 리뷰 앞으로. (경미 — FT에 선택 포함.) + +--- + +## 3. 이미 해소된 항목 (확인만) + +### M4 — 원고 경로(구 `draft.md`) → 정본 `draft_v2` + +7/21 kkkim이 처리(commit `ff0ec25` 계열). 본 `gglee` 브랜치 기준에서도 살아있는 참조가 전부 정본을 가리킴을 확인: `CLAUDE.md:87`, `docs/HARNESS.md:60`, `SKILL.md:20/48/70`, `manuscript-writer.md:43`, `presenter.md:10` → 모두 `draft_v2.md` + `draft_v2_ko.md`. 구 `draft.md`/`draft_ko.md`는 삭제(git 이력 보존). **추가 조치 불필요.** + +--- + +## 4. 검토 질문 5개에 대한 답 (AI로 논문 써본 관점) + +1. **역할 분해가 실전과 맞는가**: 대체로 적절. 도메인 슬롯 1개(`hspc-velocity-analyst`) + 재사용 8개 구성은 깔끔하다. 단 `reviewer`(외부 referee)와 `paper-critic`(내부 적대검수)의 경계가 문서상 겹치고, `reviewer`가 팬텀이라 실전에선 `paper-critic` 하나가 두 역할을 겸한다 → 역할이 문서보다 하나 적게 돈다. +2. **게이트가 환각·과대주장을 실제로 막는 위치인가**: `claim-defensibility 게이트`(SKILL §2.5 — 반증기준+가장 싼 make-or-break 검정+advisor, 2층 융합 금지, 사전등록 봉인)는 **위치·설계 모두 좋다**(headline이 본문 들어가기 전). 결정론적 **검증 게이트**(숫자 재계산)도 유효. 다만 문서는 검증 게이트를 "PI(사람)가 통과"라 하지만 실제는 스크립트 자동 재계산이라 *사람 게이트가 아니다* — 표현 정정 필요. 그리고 M2(리뷰 뒤 배치). +3. **자연어 → 라우팅이 직관적인가**: 라우팅표(CLAUDE.md:67–79)는 직관적. 유일한 죽은 링크가 `reviewer` 행(M1). +4. **도메인 슬롯 1개 교체 = 타 분야 이식 가능한가**: 구조적으로 가능하고 **BIOP02(병리)가 실제 이식 사례**. 주의점: 검증 게이트 스크립트(`p3_*`)가 도메인 특화라 **슬롯과 함께 교체**돼야 하는데 문서엔 "슬롯만 갈아끼우면 됨"으로만 적혀 게이트 교체가 누락돼 있다. +5. **있었으면 했던 것**: (a) `reviewer` 전역 에이전트 실체 또는 명확한 제거, (b) 실행 cwd 전제 명시, (c) 도메인 이식 체크리스트(슬롯 + 검증게이트 스크립트 + PAPER_DIRECTION 동시 교체). + +--- + +## 5. 후속 조치 + +- **FT1** (구조 판단): `reviewer` 팬텀 해소 — 전역 실체화 vs 제거/통합 결정 후 문서 6곳 반영. +- **FT2** (구조 판단): 프로젝트 에이전트 cwd 로딩 전제 문서화 + 전역 에이전트 배치 정리 (M1과 연동). +- 문서 최신화(비구조): 검증 게이트 "사람 통과" 표현 정정, 도메인 이식 시 게이트 교체 명시 — `gglee` 브랜치 문서 정리에서 처리. +- 공용 하네스 자산이므로 위 결정은 **BIOP02에도 동일 반영** 필요. From d5faf30820cde0d1b8f86cbd6977c471750e50d6 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 17:45:44 +0900 Subject: [PATCH 2/9] =?UTF-8?q?harness:=20=EA=B5=90=EC=B2=B4=EC=9A=A9=20af?= =?UTF-8?q?ter=20=EB=B2=84=EC=A0=84=20+=20=EC=A0=95=ED=95=A9=EC=84=B1=20?= =?UTF-8?q?=EA=B2=8C=EC=9D=B4=ED=8A=B8=20(BIOP02-100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit harness_after/ 신설 — 라이브 하네스 미수정, 승인 시 스왑용. - harness.yaml (SSOT manifest), scripts/harness_doctor.py (정합성 게이트) - docs/HARNESS.md(after), CLAUDE-routing.after.md doctor가 현재 리포에서 reviewer 팬텀 3건 검출(FAIL) 확인. BIOP01-64~70 대응. 과거 문서 미삭제. --- harness_after/CLAUDE-routing.after.md | 40 +++++++++++ harness_after/README.md | 37 ++++++++++ harness_after/docs/HARNESS.md | 62 +++++++++++++++++ harness_after/harness.yaml | 76 +++++++++++++++++++++ harness_after/scripts/harness_doctor.py | 89 +++++++++++++++++++++++++ 5 files changed, 304 insertions(+) create mode 100644 harness_after/CLAUDE-routing.after.md create mode 100644 harness_after/README.md create mode 100644 harness_after/docs/HARNESS.md create mode 100644 harness_after/harness.yaml create mode 100644 harness_after/scripts/harness_doctor.py diff --git a/harness_after/CLAUDE-routing.after.md b/harness_after/CLAUDE-routing.after.md new file mode 100644 index 0000000..b98a6b3 --- /dev/null +++ b/harness_after/CLAUDE-routing.after.md @@ -0,0 +1,40 @@ + + +## Agent routing & artifact contract (논문 생산 하네스) 【after / 검토용】 + +> 재사용 스캐폴드(Designed by Ka-Kyung Kim, CC BY 4.0) 설치본. 정본 명세 = 리포 루트 **`harness.yaml`**(SSOT). 전체 랩 지도 = `docs/HARNESS.md`. 도메인 슬롯 = `hspc-velocity-analyst`(project profile). + +### 실행 전제 (먼저) +- **repo 루트에서 실행.** 상위 디렉터리 실행 시 프로젝트 agent 미로드 → 범용 폴백. **범용 agent로 대체 금지, 필수 누락 시 중단.** (BIOP01-65) +- 단일 컨텍스트 = `pipeline/hspc-velocity-benchmark/manuscript/PAPER_DIRECTION.md` — 논문 멤버는 작업 전 로드. + +### 자연어 라우팅 +| 요청 (자연어) | 첫 agent | +| --- | --- | +| "분석 돌려줘 / 재실행 / eval·통계 / cross-dataset 재현" | `hspc-velocity-analyst` | +| "프리프린트/저널/블로그 초안·섹션" | `manuscript-writer` | +| "그림 만들어줘 / 그림 번호 정리" | `manuscript-writer` (runs `figures/figNN_*.py`) | +| "선행연구 / related work / 스쿱 확인" | `literature-scout` | +| "차별화 각도 / 뭘 새로 해야 하나" | `novelty-strategist` | +| "가설·실험설계·분석계획 점검·감사" | `research-methodologist` | +| "제출 전 적대적 자체검토 / 그림 QA" | `paper-critic` | +| "정식 venue 리뷰 시뮬레이션" | `venue-reviewer` *(프로젝트 로컬, 미구현 시 이 요청은 건너뛰고 안내)* | +| "발표자료/슬라이드/발제" | `presenter` | +| "로고·아이콘·브랜드·그림 미감" | `design` | +| "여러 단계 순서 계획만" | `paper-planner` (계획만; 실행은 메인 루프 `paper-runner`) | + +**여러 단계를 엮는 요청 → orchestrator Skill `paper-production-orchestrator`(→`paper-runner`).** RUN_STATE 기준으로 다음 단계만 실행, 필수 누락 시 중단, 미승인 게이트 건너뛰기 금지. + +### 산출물 계약 +| 단계 | Writer | 산출물 | 다음이 읽음 | +| --- | --- | --- | --- | +| 분석·eval | `hspc-velocity-analyst` | `results/FINDINGS.md` + `results/*.csv/*.md` | 결과검증·집필 | +| 결과 검증(자동) | (스크립트) | `p3_concordance` + `p3_crossdataset_concordance` + `p3_scrambled_null` 재계산 → FINDINGS 대조 | 집필 | +| 집필+그림 | `manuscript-writer` | `manuscript/draft_v2.md` + `draft_v2_ko.md`, `figures/*.png` | 검수·리뷰 | +| 검수 | `paper-critic` | 적대 노트 + 그림 QA | 집필(수정) | +| (선택) 리뷰 | `venue-reviewer` | `manuscript/REVIEW--.md` | 집필(수정) | +| 패키지 검증(자동) | (스크립트) | 원고 숫자=결과 파일, 그림 재생성, commit/데이터 고정 | 사람 | +| 발표 | `presenter` | 슬라이드/발제 | 사람 | +| 상태 | (전원) | `RUN_STATE.yaml`, `CLAIMS.yaml`, `HANDOFF.md`, `SESSION-LOG.md` | 다음 세션 | + +**게이트 3분류**: 자동 무결성(결과·패키지 검증, `harness_doctor`) / 과학적 판단(claim-defensibility — advisor 사람 포함) / 공개·거버넌스(저자·소속·IP — 사람). 커밋·push는 자동, **프리프린트/blog 공개와 main 병합만 사람 승인**. diff --git a/harness_after/README.md b/harness_after/README.md new file mode 100644 index 0000000..a1c2633 --- /dev/null +++ b/harness_after/README.md @@ -0,0 +1,37 @@ +# harness_after/ — 논문 생산 하네스 교체용 "after" 버전 (검토 대기) + +- 작성 이건규 · 2026-07-26 · branch `gglee` · 관련 BIOP02-100 / BIOP01-64~70 +- **이 폴더는 교체 후보다.** 라이브 하네스(`../docs/HARNESS.md`, `../CLAUDE.md`, `../.claude/*`, orchestrator SKILL)는 **수정하지 않았다.** 팀 검토·승인 후 아래 "스왑 방법"으로 교체한다. +- 목적: 언제든 교체 가능하도록 개선안을 실제 파일로 만들어 두고(git 보관), 상황에 따라 스왑. + +## 무엇이 들어있나 +| 파일 | 역할 | 스왑 대상(승인 시) | +| --- | --- | --- | +| `harness.yaml` | **SSOT manifest** — roles/gates/artifacts 기계판독 | 리포 루트에 신규 추가 | +| `scripts/harness_doctor.py` | **정합성 게이트** — manifest↔실제/문서 대조, 팬텀·경로 drift 검출 | 리포 루트 `scripts/`에 추가, PR CI 연결 | +| `docs/HARNESS.md` | 개선된 랩 지도(after) | `../docs/HARNESS.md` 교체 | +| `CLAUDE-routing.after.md` | 개선된 라우팅·산출물 계약 섹션(after) | `../CLAUDE.md`의 해당 섹션 교체 | + +## 무엇이 바뀌었나 (before → after) +- 멤버 수 서술 → **구성요소 인벤토리 표**(논리역할/구현형태/경로/상태). `reviewer` 미구현 명시. +- 실행 환경 전제 **명문화**(repo 루트, 범용 폴백 금지) — 침묵 폴백 차단. +- 게이트 **3분류**(자동 무결성 / 과학적 판단 / 공개·거버넌스) + "사람 통과"는 후자에만. +- 검증 게이트 **이중화**(분석 직후 결과검증 + 공개 직전 패키지검증) & 외부리뷰보다 앞. +- `reviewer` → **`venue-reviewer`**(프로젝트 로컬 우선, 격리 규칙) — 전역 실체화 안 함. +- core/project profile/run instance **3계층** 관점 도입. +- 근거 없는 정량·수사("80%" 등) 제거. + +## 스왑 방법 (승인 후에만) +``` +# 리포 루트에서 +cp harness_after/harness.yaml ./harness.yaml +cp harness_after/scripts/harness_doctor.py ./scripts/harness_doctor.py +cp harness_after/docs/HARNESS.md ./docs/HARNESS.md +# CLAUDE.md의 "Agent routing & artifact contract" 섹션을 CLAUDE-routing.after.md 내용으로 교체 +# venue-reviewer / planner·runner 개명 등 에이전트 변경은 각 티켓(BIOP01-64/70)에서 별도 반영 +python scripts/harness_doctor.py --repo . --manifest harness.yaml # 통과 확인 +``` +되돌리려면 git revert 한 번. 라이브를 건드리지 않으므로 이 폴더 존재만으로는 하네스 동작에 영향 없음. + +## 상태 +검토 대기(BIOP02-100 → 검토 중). 반영은 이건규 노트 v2(`~/HARNESS_REVIEW_AND_PROPOSAL_2026-07-26.md`) 재검토 및 팀 승인 후. diff --git a/harness_after/docs/HARNESS.md b/harness_after/docs/HARNESS.md new file mode 100644 index 0000000..8e2d512 --- /dev/null +++ b/harness_after/docs/HARNESS.md @@ -0,0 +1,62 @@ +# HARNESS.md — 랩 구조 (Agent 하네스 지도) — HSPC velocity-lag benchmark 【after / 검토용】 + +*Designed by Ka-Kyung Kim, 2026 — reusable paper-production harness (CC BY 4.0). after-revision by 이건규, 2026-07-26 (BIOP02-100).* + +> **교체 후보본.** 라이브 `docs/HARNESS.md`를 아직 대체하지 않았다. 승인 시 스왑. +> 이 하네스를 **하나의 연구 랩**으로 본 지도다. 각 agent는 멤버, 사람(+메인 루프)이 PI. +> 정본 명세는 리포 루트 **`harness.yaml`**(SSOT). 이 문서·CLAUDE.md·SKILL은 그 manifest를 따르며 `scripts/harness_doctor.py`가 대조한다. + +## 0. 실행 전제 (필수) +- **반드시 repo 루트를 cwd로 실행한다.** 상위 디렉터리에서 시작하면 `.claude/agents/`가 로드되지 않아 `agent type not found` → `general-purpose`로 **조용히 폴백**한다(산출물은 나오므로 놓치기 쉬움). +- **전문 agent 호출 실패를 범용 agent 실행으로 대체하지 않는다.** 필수 agent·Skill 누락 시 production run을 **중단**한다. +- 진입은 `scripts/start-paper-harness`(존재 검사) → orchestrator self-check(첫 단계 필수 구성요소 검사) 경유. (BIOP01-65) + +## 1. 구성요소 인벤토리 (숫자 요약 대신 명세표) +| 논리 역할 | 구현 형태 | 경로 | 상태 | +| --- | --- | --- | --- | +| domain analyst (`hspc-velocity-analyst`) | project agent | `.claude/agents/` | 구현 (project profile 슬롯) | +| literature scout | project agent | `.claude/agents/` | 구현 | +| novelty strategist | project agent | `.claude/agents/` | 구현 | +| research methodologist | project agent | `.claude/agents/` | 구현 | +| manuscript writer | project agent | `.claude/agents/` | 구현 | +| presenter | project agent | `.claude/agents/` | 구현 | +| paper critic | project agent | `.claude/agents/` | 구현 | +| design | project agent | `.claude/agents/` | 구현 | +| paper planner (`paper-orchestrator`→`paper-planner`) | agent | `.claude/agents/` | 구현 (개명 예정 BIOP01-70) | +| **venue reviewer** | agent | `.claude/agents/venue-reviewer.md` | **미구현** — 참조만 존재 (BIOP01-64) | +| production runner (`paper-production-orchestrator`→`paper-runner`) | **Skill** | `.claude/skills/.../SKILL.md` | 구현 (개명 예정) | +| figure generation | script | `figures/figNN_*.py` | 구현 | +| result / package validation | script | `scripts/p3_*.py` | 구현 | +| release approval | human | — | 운영 규칙 | + +> `venue reviewer`는 프로젝트 로컬로 구현하거나(전역 실체화 금지) 참조를 제거한다. 같은 모델 계열이 역할만 바꾸면 외부 referee가 아니라 venue-style *simulated* review이므로, 구현 시 격리(다른 모델 계열 / 원고 패키지만 전달 / 내부 논의 차단 / 사용 모델·입력 기록). + +## 2. 게이트 (3분류) +| 게이트 유형 | 예시 | 실패 시 | +| --- | --- | --- | +| 자동 무결성 | 숫자 재계산·파일 대조·스키마 검사 (`p3_*`), 하네스 정합성(`harness_doctor.py`) | 즉시 중단 | +| 과학적 판단 | claim-defensibility(반증기준+make-or-break+advisor), 방법론 승인 | 사람 승인 | +| 공개·거버넌스 | 저자·소속·IP·corresponding email·데이터 공개 | 책임자 승인 | + +- **검증은 두 번**: ① 분석 직후(결과 검증) ② 공개 직전(패키지 검증). claim lock에는 사람(advisor)의 과학적 판단이 들어간다 — "사람 게이트=공개뿐"이 아니다. + +## 3. 표준 경로 (검증 게이트를 외부 리뷰 앞에) +``` +기획(methodologist/scout/novelty) → claim·검정 계획 확정 + → hspc-velocity-analyst → results/FINDINGS.md + → [결과 검증 게이트: p3_concordance + p3_crossdataset_concordance + p3_scrambled_null] + → manuscript-writer → manuscript/draft_v2.md + draft_v2_ko.md (그림: figures/figNN_*.py) + → paper-critic (적대 검수 + 그림 QA) + → (선택) venue-reviewer → manuscript/REVIEW--.md + → [패키지 검증 게이트: 원고 숫자=결과 파일, 그림 재생성, commit/데이터 고정] + → presenter (최종 발표자료) + → [공개 게이트: 사람 — 저자·소속·IP] +``` + +## 4. 계층 분리 (재사용 관점 — BIOP01-67) +- **Core harness**(도메인 무관): 호출 규약·artifact contract·stage transition·실패 정책·run state·reviewer 격리·release gate·self-check. +- **Project profile**(프로젝트별): domain analyst·검증 명령·데이터/결과 경로·claim 금지 규칙·`PAPER_DIRECTION.md`·필수 그림/표·지표. → "슬롯 하나만 교체"가 아니라 **profile 제공**. +- **Run instance**: `RUN_STATE.yaml`(BIOP01-68) — 현재 단계·commit·완료 게이트·승인자·산출물 sha256. + +## 5. 정합성 (SSOT + doctor) +`harness.yaml`이 명세, 문서·코드가 이를 따른다. `python scripts/harness_doctor.py --repo . --manifest harness.yaml`을 PR CI에서 실행 → 팬텀 역할·경로 drift가 사람 검토 전에 실패한다. (BIOP01-66) diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml new file mode 100644 index 0000000..22cff8b --- /dev/null +++ b/harness_after/harness.yaml @@ -0,0 +1,76 @@ +# harness.yaml — 논문 생산 하네스 Single Source of Truth (manifest) +# 문서(HARNESS.md/CLAUDE.md/SKILL.md)와 코드는 이 manifest를 따른다. +# harness_doctor.py가 이 파일을 기준으로 실제 파일·문서 참조를 대조한다. +harness_version: 1 +project_profile: biop01 # 도메인 특화분은 project profile로 분리 (BIOP01-67) + +roles: + # --- 도메인 슬롯 (project profile에서 교체) --- + domain_analyst: + aka: hspc-velocity-analyst + type: agent + path: .claude/agents/hspc-velocity-analyst.md + required: true + implemented: true + # --- 재사용 코어 멤버 --- + literature_scout: { type: agent, path: .claude/agents/literature-scout.md, required: true, implemented: true } + novelty_strategist: { type: agent, path: .claude/agents/novelty-strategist.md, required: true, implemented: true } + research_methodologist: { type: agent, path: .claude/agents/research-methodologist.md, required: true, implemented: true } + manuscript_writer: { type: agent, path: .claude/agents/manuscript-writer.md, required: true, implemented: true } + presenter: { type: agent, path: .claude/agents/presenter.md, required: true, implemented: true } + paper_critic: { type: agent, path: .claude/agents/paper-critic.md, required: true, implemented: true } + design: { type: agent, path: .claude/agents/design.md, required: false, implemented: true } + paper_planner: { type: agent, path: .claude/agents/paper-orchestrator.md, required: true, implemented: true } # 개명 예정: paper-planner (BIOP01-70) + # --- 미구현 (문서에는 참조되나 실체 없음) — BIOP01-64 --- + venue_reviewer: + aka: [reviewer, venue-reviewer, simulated-referee] + type: agent + path: .claude/agents/venue-reviewer.md + required: false + implemented: false # ← doctor가 문서 참조 대비 미구현으로 FAIL 처리해야 함 + note: "프로젝트 로컬 구현 예정. 전역 실체화 금지. 격리 규칙 필요." + # --- 비-에이전트 구성요소 --- + production_runner: { type: skill, path: .claude/skills/paper-production-orchestrator/SKILL.md, required: true, implemented: true } # 개명 예정: paper-runner + figure_generation: { type: script, path: pipeline/hspc-velocity-benchmark/figures, required: true, implemented: true } + +gates: + result_validation: # 자동 무결성 — 분석 직후 + type: automatic + when: after_analysis + commands: + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_concordance.py" + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_crossdataset_concordance.py --dataset human_brain" + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_scrambled_null.py" + on_fail: stop_and_report + package_validation: # 자동 무결성 — 공개 직전 + type: automatic + when: before_release + checks: [manuscript_numbers_match_results, figures_regenerated, commit_and_data_pinned, numbers_unchanged_through_review] + on_fail: stop_and_report + claim_defensibility: # 과학적 판단 — 사람(advisor) 포함 + type: scientific_judgement + on_fail: human_approval + release: # 공개·거버넌스 — 사람 + type: governance + checks: [authors, affiliation, ip, corresponding_email, data_release] + on_fail: human_approval + +artifacts: + findings: pipeline/hspc-velocity-benchmark/results/FINDINGS.md + manuscript: pipeline/hspc-velocity-benchmark/manuscript/draft_v2.md + manuscript_ko: pipeline/hspc-velocity-benchmark/manuscript/draft_v2_ko.md + figures_dir: pipeline/hspc-velocity-benchmark/figures + paper_direction: pipeline/hspc-velocity-benchmark/manuscript/PAPER_DIRECTION.md + +execution: + require_repo_root: true # 상위 디렉터리 실행 금지 (BIOP01-65) + forbid_generic_fallback: true # 전문 agent 실패를 general-purpose로 대체 금지 + run_state: RUN_STATE.yaml # BIOP01-68 (예정) + claim_ledger: CLAIMS.yaml # BIOP01-69 (예정) + +# 문서가 참조하지만 manifest에 없거나 implemented=false인 agent 이름은 doctor가 FAIL 처리한다. +doc_reference_scan: + files: + - CLAUDE.md + - docs/HARNESS.md + - .claude/skills/paper-production-orchestrator/SKILL.md diff --git a/harness_after/scripts/harness_doctor.py b/harness_after/scripts/harness_doctor.py new file mode 100644 index 0000000..89e0819 --- /dev/null +++ b/harness_after/scripts/harness_doctor.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 +"""harness_doctor.py — 하네스 구성 정합성 게이트. + +harness.yaml(manifest)을 기준으로 실제 파일·문서 참조가 일치하는지 검사한다. +논문 '결과'가 아니라 하네스 '구성 자체'를 검증한다. PR CI에서 돌린다. + +검사: + 1) implemented=true 역할의 path 존재 + 2) artifacts 경로 존재 + 3) 문서(doc_reference_scan)가 참조하는 agent 이름이 미구현(implemented=false)인데 쓰이면 FAIL ← reviewer 팬텀 검출 + 4) execution.require_repo_root: repo 루트(.git 또는 CLAUDE.md)에서 실행됐는지 +사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml +종료코드: 0=PASS, 1=FAIL, 2=실행오류 +""" +import argparse, os, re, sys + +def load_yaml(path): + try: + import yaml + except ImportError: + print("ERROR: PyYAML 필요 (pip install pyyaml / conda install pyyaml)", file=sys.stderr) + sys.exit(2) + with open(path, encoding="utf-8") as f: + return yaml.safe_load(f) + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--repo", default=".") + ap.add_argument("--manifest", default="harness.yaml") + a = ap.parse_args() + repo = os.path.abspath(a.repo) + man_path = a.manifest if os.path.isabs(a.manifest) else os.path.join(repo, a.manifest) + if not os.path.exists(man_path): + print(f"ERROR: manifest 없음: {man_path}", file=sys.stderr); sys.exit(2) + m = load_yaml(man_path) + + fails, warns = [], [] + def p(path): return os.path.join(repo, path) + + roles = m.get("roles", {}) + # 1) implemented 역할 path 존재 + for name, r in roles.items(): + if not isinstance(r, dict): + continue + if r.get("implemented") and r.get("path") and not os.path.exists(p(r["path"])): + fails.append(f"[role] {name}: implemented=true 인데 경로 없음 → {r['path']}") + + # 2) artifacts 존재 + for k, v in (m.get("artifacts") or {}).items(): + if not os.path.exists(p(v)): + warns.append(f"[artifact] {k}: 경로 없음 → {v}") + + # 3) 문서 참조 vs 미구현 (팬텀 검출) + scan = (m.get("doc_reference_scan") or {}).get("files", []) + # 미구현 역할의 모든 별칭(aka) 토큰 수집 + phantom_tokens = {} + for name, r in roles.items(): + if isinstance(r, dict) and r.get("implemented") is False: + akas = r.get("aka", []) + if isinstance(akas, str): akas = [akas] + for tok in set([name] + akas): + phantom_tokens.setdefault(tok, name) + for f in scan: + fp = p(f) + if not os.path.exists(fp): + warns.append(f"[scan] 문서 없음 → {f}"); continue + text = open(fp, encoding="utf-8", errors="replace").read() + for tok, role in phantom_tokens.items(): + if re.search(r"(? Date: Sun, 26 Jul 2026 18:29:02 +0900 Subject: [PATCH 3/9] =?UTF-8?q?harness:=20after=20=EB=B2=84=EC=A0=84=20?= =?UTF-8?q?=EC=82=B0=EC=B6=9C=EB=AC=BC=20=EC=B6=94=EA=B0=80=20(BIOP01-64/6?= =?UTF-8?q?5/66/68/69)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/start-paper-harness (실행 전제 가드, BIOP01-65) - RUN_STATE.template.yaml (BIOP01-68), CLAIMS.template.yaml (BIOP01-69) - agents/venue-reviewer.md (프로젝트 로컬 후보, BIOP01-64) - ci/harness-doctor.yml (정합성 게이트 CI, BIOP01-66) 라이브 미수정, 스왑 대기. --- harness_after/CLAIMS.template.yaml | 17 ++++++++++++++ harness_after/RUN_STATE.template.yaml | 17 ++++++++++++++ harness_after/agents/venue-reviewer.md | 20 +++++++++++++++++ harness_after/ci/harness-doctor.yml | 17 ++++++++++++++ harness_after/scripts/start-paper-harness | 27 +++++++++++++++++++++++ 5 files changed, 98 insertions(+) create mode 100644 harness_after/CLAIMS.template.yaml create mode 100644 harness_after/RUN_STATE.template.yaml create mode 100644 harness_after/agents/venue-reviewer.md create mode 100644 harness_after/ci/harness-doctor.yml create mode 100755 harness_after/scripts/start-paper-harness diff --git a/harness_after/CLAIMS.template.yaml b/harness_after/CLAIMS.template.yaml new file mode 100644 index 0000000..c197e2d --- /dev/null +++ b/harness_after/CLAIMS.template.yaml @@ -0,0 +1,17 @@ +# CLAIMS.template.yaml — claim provenance ledger (BIOP01-69). 템플릿. +# claim-defensibility 게이트와 실제 원고를 연결한다. 결과 변경 시 여기부터 갱신. +claims: + C001: + text: "" + status: + evidence: # 결과 파일/그림 (숫자는 여기서만) + - pipeline/hspc-velocity-benchmark/results/.csv + - pipeline/hspc-velocity-benchmark/figures/.png + validation: # 재계산 스크립트 + - p3_crossdataset_concordance + limitations: + - "<한계/반례>" + manuscript_locations: # 이 claim이 등장하는 위치 (결과 바뀌면 전부 점검) + - abstract + - results.3 + - discussion.2 diff --git a/harness_after/RUN_STATE.template.yaml b/harness_after/RUN_STATE.template.yaml new file mode 100644 index 0000000..9c7c422 --- /dev/null +++ b/harness_after/RUN_STATE.template.yaml @@ -0,0 +1,17 @@ +# RUN_STATE.template.yaml — 논문 생산 실행 상태 (BIOP01-68). 템플릿 — 실제 run에서 채움. +# orchestrator(paper-runner)가 이 파일을 읽고 다음 단계만 실행한다. 대화 기록에 상태를 두지 않는다. +run_id: -paper- # 예: biop01-paper-20260726 +source_commit: +stage: + +completed: + claim_defensibility: { status: , commit: , approved_by: } + result_validation: { status: , commit: } # 분석 직후 + package_validation: { status: , commit: } # 공개 직전 + +artifacts: + findings: { path: pipeline/hspc-velocity-benchmark/results/FINDINGS.md, sha256: <> } + manuscript: { path: pipeline/hspc-velocity-benchmark/manuscript/draft_v2.md, sha256: <> } + +failures: [] # [{stage, reason, commit}] +notes: "" # 수정 후 다시 통과해야 하는 게이트 등 diff --git a/harness_after/agents/venue-reviewer.md b/harness_after/agents/venue-reviewer.md new file mode 100644 index 0000000..c280b75 --- /dev/null +++ b/harness_after/agents/venue-reviewer.md @@ -0,0 +1,20 @@ + +--- +name: venue-reviewer +description: 외부 venue-style 시뮬레이션 리뷰(referee). paper-critic(내부 적대검수) + 결과 검증 게이트 통과 후에만 호출한다. 원고 패키지만 읽고 내부 논의·분석 과정·critic 노트는 보지 않는다(격리). +--- + +# venue-reviewer (simulated referee) + +target venue의 referee처럼 **최종 원고 패키지만** 심사한다. + +## 격리 (필수) +- 입력은 `manuscript/draft_v2.md`(+`_ko`), 그림, `refs.bib`, `SUPPLEMENTARY.md` **뿐**. 분석 과정·내부 논의·critic 노트 접근 금지. +- 리뷰 상단에 **사용 모델·입력 범위**를 기록한다. 같은 모델 계열이면 "simulated review (외부 referee 아님)"임을 명시. +- 진짜 리뷰 다양성이 필요하면 **다른 모델 계열**로 실행한다. + +## 산출 +`manuscript/REVIEW--.md` — major/minor 이슈, 재현성·통계·novelty·형식·venue-fit. + +## 주의 +프로젝트 로컬 후보다(BIOP01-64). **전역(`~/.claude/agents/`) 설치 금지** — 숨은 환경 의존성 방지. 미설치 시 "정식 venue 리뷰" 요청은 건너뛰고 안내한다. diff --git a/harness_after/ci/harness-doctor.yml b/harness_after/ci/harness-doctor.yml new file mode 100644 index 0000000..7d0506f --- /dev/null +++ b/harness_after/ci/harness-doctor.yml @@ -0,0 +1,17 @@ +# 후보 CI (BIOP01-66). 승인 후 .github/workflows/harness-doctor.yml 로 스왑하면 활성화. +# harness_after/ 안에 두어 지금은 비활성(스왑 전까지 CI 미동작). +name: harness-doctor +on: + pull_request: + branches: [ main, kkkim-pipeline ] +jobs: + doctor: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - run: pip install pyyaml + - name: 하네스 구성 정합성 검사 (팬텀·경로 drift) + run: python scripts/harness_doctor.py --repo . --manifest harness.yaml diff --git a/harness_after/scripts/start-paper-harness b/harness_after/scripts/start-paper-harness new file mode 100755 index 0000000..72eafce --- /dev/null +++ b/harness_after/scripts/start-paper-harness @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# start-paper-harness — 실행 전제 가드 (BIOP01-65). +# repo 루트·필수 구성요소·정합성 게이트를 확인한 뒤에만 하네스 진입. +# 전문 agent 실패를 범용 agent로 대체하지 않는다: 누락 시 즉시 중단. +set -euo pipefail + +ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" +[ -n "$ROOT" ] || { echo "FATAL: git 저장소가 아님. repo 루트에서 실행하라."; exit 1; } +cd "$ROOT" +[ -f CLAUDE.md ] || { echo "FATAL: repo 루트가 아님(CLAUDE.md 없음). 상위 디렉터리 실행 금지."; exit 1; } + +req=( + ".claude/agents/hspc-velocity-analyst.md" + ".claude/skills/paper-production-orchestrator/SKILL.md" + "pipeline/hspc-velocity-benchmark/scripts/p3_concordance.py" +) +missing=0 +for p in "${req[@]}"; do [ -e "$p" ] || { echo "MISSING: $p"; missing=1; }; done +[ "$missing" -eq 0 ] || { echo "FATAL: 필수 구성요소 누락 → production run 중단 (범용 폴백 금지)."; exit 1; } + +# 정합성 게이트 (manifest ↔ 실제/문서) +if [ -f scripts/harness_doctor.py ] && [ -f harness.yaml ]; then + python scripts/harness_doctor.py --repo . --manifest harness.yaml \ + || { echo "FATAL: harness_doctor FAIL → 하네스 진입 중단."; exit 1; } +fi + +echo "OK: 실행 전제 통과 (cwd=$ROOT). 하네스 진입 허용." From fae9d5ae9c368943c7dd8975a55f520f976aab63 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 18:35:46 +0900 Subject: [PATCH 4/9] =?UTF-8?q?onboarding:=20=EC=9D=B4=EA=B1=B4=EA=B7=9C?= =?UTF-8?q?=201~3=EC=A3=BC=EC=B0=A8=20=EA=B3=BC=EC=A0=9C=20=ED=9A=8C?= =?UTF-8?q?=EA=B3=A0=20=EC=99=84=EB=A3=8C=20(BIOP01-1/15/8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit week1 논문분석 스킬+MultiVelo 샘플, week2 Insight(scope/papers.jsonl/ comparison/evidence/insight 4관점), week3 Validation(6기준). 근거=paper_analysis velocity 9편. 원 마감 05~06월 경과분 기록 보존. --- onboarding_gglee/README.md | 11 +++++ onboarding_gglee/week1/SKILL.md | 23 ++++++++++ .../week1/analysis_li-2023-multivelo.md | 10 +++++ onboarding_gglee/week2/comparison_table.md | 15 +++++++ onboarding_gglee/week2/evidence_bundle.md | 18 ++++++++ onboarding_gglee/week2/insight.md | 17 +++++++ onboarding_gglee/week2/papers.jsonl | 9 ++++ onboarding_gglee/week2/scope.md | 17 +++++++ onboarding_gglee/week3/validation.md | 45 +++++++++++++++++++ 9 files changed, 165 insertions(+) create mode 100644 onboarding_gglee/README.md create mode 100644 onboarding_gglee/week1/SKILL.md create mode 100644 onboarding_gglee/week1/analysis_li-2023-multivelo.md create mode 100644 onboarding_gglee/week2/comparison_table.md create mode 100644 onboarding_gglee/week2/evidence_bundle.md create mode 100644 onboarding_gglee/week2/insight.md create mode 100644 onboarding_gglee/week2/papers.jsonl create mode 100644 onboarding_gglee/week2/scope.md create mode 100644 onboarding_gglee/week3/validation.md diff --git a/onboarding_gglee/README.md b/onboarding_gglee/README.md new file mode 100644 index 0000000..02c7c83 --- /dev/null +++ b/onboarding_gglee/README.md @@ -0,0 +1,11 @@ +# onboarding_gglee/ — 이건규 온보딩 과제 (회고 완료) + +BIOP01 온보딩 3주 과제를 뒤늦게(2026-07-26) 수행한 결과물. 원 마감(2026-05~06)은 지났으나 기록으로 남긴다. + +| 주차 | 티켓 | 과제 | 산출물 | +| --- | --- | --- | --- | +| 1주 | BIOP01-1 | 자신만의 논문 분석 Agent | `week1/SKILL.md` + `week1/analysis_li-2023-multivelo.md` | +| 2주 | BIOP01-15 | Insight Agent (cross-paper) | `week2/scope.md`·`papers.jsonl`·`comparison_table.md`·`evidence_bundle.md`·`insight.md` | +| 3주 | BIOP01-8 | Validation Agent (Insight 검증) | `week3/validation.md` | + +코퍼스: 리포 `paper_analysis/epigenomic-lag/`의 single-cell RNA velocity 논문 9편(MultiVelo·MultiVeloVAE·MoFlow·CRAK-Velo·cellDancer·DeepVelo·DeepKinet·mmVelo·velocity-benchmark). 근거는 각 논문의 `*_methodology-brief.md`·`*_core.md`를 인용. diff --git a/onboarding_gglee/week1/SKILL.md b/onboarding_gglee/week1/SKILL.md new file mode 100644 index 0000000..549355f --- /dev/null +++ b/onboarding_gglee/week1/SKILL.md @@ -0,0 +1,23 @@ +# SKILL — 논문 분석 Agent (method paper 읽기, gglee) [BIOP01-1] + +method(알고리즘) 논문을 읽을 때 **재현·적용 판단에 필요한 요소**를 강제로 뽑는 스킬. epigenomics 브랜치 AGENTS.md/SKILL.md를 참고해 내 관점으로 재작성. + +## 언제 +새 velocity/kinetics method 논문 1편을 우리 HSPC(GSE209878) 파이프라인 관점에서 평가할 때. + +## 입력 / 출력 +- 입력: 논문 PDF(또는 core 노트) 1편 + 우리 데이터/목표 컨텍스트. +- 출력: `analysis_.md` — 아래 6블록. + +## 반드시 뽑는 6블록 (요약과 insight를 구분) +1. **주장 & 메커니즘(1문장)** — 무엇을 어떻게 계산하나. 핵심 수식/loss/state 정의. "무엇이 새로운가"를 한 줄로. +2. **New vs Borrowed** — 이 논문 고유 기여 vs 선행(scVelo/UniTVelo/cellDancer 등)에서 상속한 것. (계보 명시 — 과대평가 방지.) +3. **데이터 & 재현성** — dataset 접근(open/restricted, GEO/dbGaP), 코드·license·유지보수, 자원(GPU 필수 여부·시간·메모리), 핵심 의존성. +4. **우리 적용성(HSPC)** — modality 일치(RNA-only vs multiome), 우리 GSE209878 사용 여부, lag 산출이 내장인지 후처리인지, 예상 비용. +5. **한계 & confound** — 저자가 통제 안 한 것(cell-cycle, chromatin ablation 부재, pseudotime≠wall-clock, multi-sample 미지원 등). **반례가 될 조건.** +6. **후속 질문 2–3** — 검증/의사결정을 가르는 질문. + +## 규율 +- 숫자·주장은 논문 본문/그림 위치를 명시(`§Methods pXX`, `Fig N`). 메모리 재유도 금지. +- "SOTA/우월"은 저자 주장인지 독립 벤치마크(Luo 2026)인지 구분. weak ≠ zero. +- modality mismatch(RNA-only인데 우리는 multiome)는 즉시 flag → baseline 용도로만. diff --git a/onboarding_gglee/week1/analysis_li-2023-multivelo.md b/onboarding_gglee/week1/analysis_li-2023-multivelo.md new file mode 100644 index 0000000..a93fcf8 --- /dev/null +++ b/onboarding_gglee/week1/analysis_li-2023-multivelo.md @@ -0,0 +1,10 @@ +# 분석: Li 2023 — MultiVelo (SKILL 적용 샘플) [BIOP01-1] + +*근거: `paper_analysis/epigenomic-lag/li-2023-multivelo/*` (methodology-brief, core §Methods p11–26).* + +1. **주장 & 메커니즘**: scVelo dynamical 모델의 transcription rate를 `α^(k)·c(t)`(k=chromatin state, c=accessibility)로 확장해 **chromatin→RNA priming/decoupling lag**를 latent time 축에서 정량하는 첫 multi-omic velocity. 4-state ODE + Nelder–Mead 적합. +2. **New vs Borrowed**: (New) chromatin accessibility를 velocity ODE에 결합한 4-state 스위치 + priming/decoupling 시간. (Borrowed) scVelo dynamical의 spliced/unspliced ODE·latent time, Seurat WNN smoothing, Signac peak 처리. +3. **데이터 & 재현성**: dataset `open`(HSPC GSE209878 processed, mouse skin GSE140203, human brain GSE162170) + raw `restricted`(dbGaP phs002915.v1.p1). 코드 welch-lab/MultiVelo(PyPI/Bioconda, MIT 추정, active). **CPU only**, HSPC 124분/32GB, GPU 불필요. 의존성 scanpy·scVelo·Seurat v4(R)·Signac·numba. +4. **우리 적용성(HSPC)**: **완전 일치** — 본 논문 HSPC dataset = 우리 GSE209878, 동일 platform/modality. 워크스테이션에서 바로 실행. lag는 latent-time 축 산출(내장). → 우리 파이프라인의 **foundational baseline**. +5. **한계 & confound**: (a) **cell-cycle confound 처리 미명시** — regress-out 충분한지 불명. (b) **pseudotime≠wall-clock** — lag가 latent 단위라 drug timing(시간)으로 직접 못 씀. (c) **discrete 4-state + single-sample** — cell-type-specific 연속 kinetics·multi-donor 통합 불가(→ MultiVeloVAE가 해소). (d) chromatin 기여를 분리하는 ATAC-off ablation 없음. +6. **후속 질문**: ① cell-cycle regress-out vs non-cycling subset separate fit의 lag 차이? ② latent-time lag를 wall-clock으로 매핑할 anchor가 있나? ③ 후속(MultiVeloVAE/MoFlow)과 lag 방향이 gene 단위로 일치하나(cross-method consistency)? diff --git a/onboarding_gglee/week2/comparison_table.md b/onboarding_gglee/week2/comparison_table.md new file mode 100644 index 0000000..7c763e5 --- /dev/null +++ b/onboarding_gglee/week2/comparison_table.md @@ -0,0 +1,15 @@ +# comparison_table — velocity method 비교 [BIOP01-15] + +| Method (연도, venue) | 유형 | Modality | 핵심 메커니즘 | 결과 주장 | 대표 한계 | +| --- | --- | --- | --- | --- | --- | +| MultiVelo (2023, Nat Biotech) | 기계론 ODE | multiome | α^(k)·c(t), 4-state, latent time | 최초 chromatin→RNA lag 정량 | discrete·single-sample, cell-cycle 미명시 | +| MultiVeloVAE (2025, Nat Comm) | cVAE+ODE | multiome | 연속 (k_c,ρ), multi-sample, Bayesian diff test | MultiVelo 한계 일반화 | GPU 필수, scaling 미검증 | +| MoFlow (2026, Nat Comm) | DNN, latent-time-free | multiome | relay cosine loss + open/close scenario 자동선택 | backflow 해소, lag 정량 | multi-sample 미지원 | +| CRAK-Velo (2026, Genome Biol) | semi-mech (UniTVelo) | multiome | accessibility=production rate + region weight | GSE209878서 MultiVelo 대비 우위 주장 | **chromatin ablation 없음** | +| cellDancer (2023, Nat Biotech) | DNN, latent-time-free | RNA-only | local cosine loss + gene DNN | 방향 정확도; MoFlow 전신 | chromatin 없음 | +| DeepVelo (2024, Genome Biol) | GCN | RNA-only | GCN + continuity loss | scVelo 대비 우위 | chromatin 없음, 30k cell 한계 | +| DeepKinet (2024, Genome Biol) | 2-stage VAE | RNA-only | splicing/degradation rate + scEU/scNT 검증 | kinetic-rate **검증 프레임워크** | chromatin 없음 | +| mmVelo (2024, bioRxiv) | multimodal VAE | multiome | multimodal latent dynamics | cross-modality velocity | preprint | +| veloBench (2026, Cell Rep Meth) | 벤치마크 | mixed | 15 method × 20 dataset | **단일 정답 없음**, scenario별 권장 | MultiVelo를 **ATAC off**로 실행 | + +**한눈에**: chromatin-aware 4종(MultiVelo/VAE/MoFlow/CRAK-Velo)이 우리 HSPC 직접 적용 대상; RNA-only 4종은 baseline/계보/검증-프레임워크; 벤치마크는 method 선택의 3자 근거이나 multi-omic(ATAC-on) 성능은 **비워둠**. diff --git a/onboarding_gglee/week2/evidence_bundle.md b/onboarding_gglee/week2/evidence_bundle.md new file mode 100644 index 0000000..f13c605 --- /dev/null +++ b/onboarding_gglee/week2/evidence_bundle.md @@ -0,0 +1,18 @@ +# evidence_bundle — Insight 입력 [BIOP01-15] + +각 관찰의 근거 위치(`paper_analysis/epigenomic-lag//*`). Insight agent는 이 번들 + papers.jsonl만 읽는다. + +## E1. 계보 (field flow) +- scVelo dynamical → cellDancer/DeepVelo(RNA-only, latent-time-free, cell-specific DNN) → MultiVelo(chromatin-aware, discrete, latent time) → **분기**: MoFlow(latent-time-free chromatin DNN) & MultiVeloVAE(연속 cVAE·multi-sample). 근거: hong-2026-moflow_methodology-brief("MultiVelo post-extension 두 갈래 중 하나"), li-2025-multivelovae_methodology-brief("MultiVelo를 continuous+multi-sample로 일반화"), li-2023-celldancer_methodology-brief("MoFlow의 direct predecessor"). + +## E2. chromatin 기여의 인과 분리 부재 (반복 한계) +- CRAK-Velo: chromatin term ablation(k=0)이 없어 chromatin 통합 효과가 인과적으로 분리 안 됨(el-kazwini brief '본인 재회고'). veloBench: **MultiVelo를 rna_only=True로 실행**해 multi-omic(ATAC-on) 이득을 평가하지 않음(luo brief). → "chromatin이 실제로 lag를 만드는가"를 논문들이 직접 시험하지 않음. + +## E3. confound·척도 (반복 한계) +- cell-cycle 처리: MultiVelo/MultiVeloVAE/MoFlow 모두 '재회고'에서 cell-cycle confound 처리 미명시로 질문 남김. pseudotime≠wall-clock: lag가 latent 단위 → drug timing(시간)으로 직접 환산 불가(multivelo brief). + +## E4. 차별점 (differentiation) +- MultiVelo=기계론·CPU·foundational; MultiVeloVAE=연속·multi-sample·GPU·BSD-3; MoFlow=latent-time-free·backflow 해소; CRAK-Velo=region-level·동일 GSE209878 head-to-head; DeepKinet=검증 프레임워크(scEU/scNT); veloBench=scenario 권장(complex topology→DeepVelo/veloVI/LatentVelo). + +## E5. 재현·라이선스 (실무) +- 다수 repo가 license 명시 부재('검토필요:'): MoFlow·cellDancer·MultiVelo(MIT 추정). 명확 상업 허용은 MultiVeloVAE(BSD-3). GPU 필수: MultiVeloVAE·MoFlow·DeepVelo. CPU 가능: MultiVelo·cellDancer. diff --git a/onboarding_gglee/week2/insight.md b/onboarding_gglee/week2/insight.md new file mode 100644 index 0000000..2d32bb4 --- /dev/null +++ b/onboarding_gglee/week2/insight.md @@ -0,0 +1,17 @@ +# insight — cross-paper Insight (4관점) [BIOP01-15] + +요약이 아니라 논문 *간* 관계·패턴·gap. 근거는 `evidence_bundle.md`(E1–E5), `papers.jsonl`. + +## Field Flow (흐름) +**I1.** velocity 계열은 "정확도 향상"이 아니라 **자유도 이동**으로 진화했다: scVelo(gene-global kinetics) → cellDancer/DeepVelo(**cell-specific**, latent-time 제거) → MultiVelo(**chromatin 축 추가**, 단 discrete·latent-time 복귀) → 두 분기가 MultiVelo의 서로 다른 제약을 각각 푼다 — MoFlow(latent-time 다시 제거) vs MultiVeloVAE(discrete→연속, single→multi-sample). 즉 최신 두 방법은 **경쟁이 아니라 상보적**(각기 다른 축을 완화). [E1] + +## Differentiation Map (차별점·강약) +**I2.** chromatin-aware 4종은 겹치지 않는 강점을 판다: MultiVelo=재현 쉬움(CPU·foundational) / MultiVeloVAE=multi-sample·differential test(연구 확장성) / MoFlow=backflow 해소·latent-time-free(방향 안정) / CRAK-Velo=region-level 해석·동일 데이터 head-to-head. **약점의 공통 축**은 "chromatin의 인과 기여 미검증"과 "cell-cycle/척도". → 단일 default 대신 **2–3종 교차 실행 + 합의**가 방법론적으로 정당(veloBench의 'no single answer'와 일치). [E4, E1] + +## Repeated Limitations (반복 한계) +**I3.** 세 한계가 방법을 가로질러 반복된다: (a) **chromatin 인과 분리 부재** — CRAK-Velo에 k=0 ablation 없음, veloBench가 MultiVelo를 ATAC-off로 실행 → "chromatin이 lag를 만든다"를 아무도 직접 시험 안 함. (b) **cell-cycle confound 미명시**(MultiVelo/VAE/MoFlow 공통). (c) **pseudotime≠wall-clock** → lag가 시간 단위가 아니라 drug-timing 예측에 직접 못 씀. [E2, E3] + +## Unresolved Gaps (미해결·후속) +**I4.** 분야가 답하지 않은 질문: ① **ATAC-on이 RNA-only 대비 실제로 정확도/lag를 개선하는가?**(veloBench 공백) → 우리 HSPC에서 자체 ablation로 채울 자리. ② **chromatin→transcription lag가 method 간 재현되는가?**(cross-method consistency를 어느 논문도 보고 안 함) → 우리 파이프라인의 차별화 지점. ③ latent-time lag → wall-clock 매핑 anchor. ④ cell-cycle regress-out vs separate-fit의 lag 민감도. [E2, E3, E4] + +> 종합: 이 분야의 진짜 공백은 "더 정확한 method"가 아니라 **chromatin의 인과성·method 간 재현성·시간 척도의 검증**이며, 이는 우리 HSPC multiome + 자체 ablation/cross-method 설계로 메울 수 있다. diff --git a/onboarding_gglee/week2/papers.jsonl b/onboarding_gglee/week2/papers.jsonl new file mode 100644 index 0000000..fc97c2b --- /dev/null +++ b/onboarding_gglee/week2/papers.jsonl @@ -0,0 +1,9 @@ +{"id":"li-2023-multivelo","year":2023,"venue":"Nature Biotechnology","method":"MultiVelo","type":"mechanistic ODE","modality":"multiome (RNA+ATAC)","mechanism":"scVelo dynamical의 transcription rate를 chromatin state k·accessibility c(t)로 확장, 4-state ODE, latent time","result":"chromatin→RNA priming/decoupling lag를 정량한 첫 multi-omic velocity","limitation":"discrete 4-state·single-sample, cell-cycle 처리 미명시, pseudotime≠wall-clock, chromatin ablation 없음","compute":"CPU only","uses_gse209878":true} +{"id":"li-2025-multivelovae","year":2025,"venue":"Nature Communications","method":"MultiVeloVAE","type":"cVAE + ODE","modality":"multiome","mechanism":"MultiVelo 4-state를 cVAE + cell-specific continuous (k_c,ρ) + shared latent time + partial-overlap modality로 일반화, Bayesian differential test, in silico TF perturbation","result":"continuous·multi-sample·differential dynamics로 MultiVelo 한계 해소","limitation":"GPU 필수, cell-cycle 처리 미명시, 100k+ scaling 미검증","compute":"GPU","uses_gse209878":true} +{"id":"hong-2026-moflow","year":2026,"venue":"Nature Communications","method":"MoFlow","type":"DNN (latent-time-free)","modality":"multiome","mechanism":"cellDancer relay velocity cosine loss + chromatin scenario(open/close) 양쪽 평가·lower-loss 자동선택 + 2-stage 학습","result":"backflow 해소 + latent-time-free chromatin-aware lag; MultiVelo 전처리 재사용","limitation":"multi-sample 미지원, hardware 미명시, cell-cycle 미명시","compute":"GPU","uses_gse209878":true} +{"id":"el-kazwini-2026-crakvelo","year":2026,"venue":"Genome Biology","method":"CRAK-Velo","type":"semi-mechanistic (UniTVelo 확장)","modality":"multiome","mechanism":"chromatin accessibility를 production rate로 직접 구성 + gene별 region weight, cisTopic smoothing","result":"동일 GSE209878 HSPC에서 MultiVelo 대비 우위 주장, region-level 해석","limitation":"chromatin term ablation(k=0) 없어 chromatin 기여 인과 분리 불가, lag는 후처리","compute":"CPU+GPU(cisTopic)","uses_gse209878":true} +{"id":"li-2023-celldancer","year":2023,"venue":"Nature Biotechnology","method":"cellDancer","type":"DNN (latent-time-free)","modality":"RNA-only","mechanism":"latent time 없는 local cosine loss + gene별 DNN으로 cell-specific (α,β,γ)","result":"multi-lineage 방향 정확도; MoFlow의 직접 predecessor","limitation":"chromatin 없음 → epigenomic-lag 직접 적용 불가(baseline 용도)","compute":"CPU","uses_gse209878":false} +{"id":"cui-2024-deepvelo","year":2024,"venue":"Genome Biology","method":"DeepVelo","type":"GCN","modality":"RNA-only","mechanism":"GCN + continuity loss로 cell/gene-specific kinetics 학습","result":"scVelo 대비 multi-lineage 방향 우위","limitation":"chromatin 없음, full-batch → 30k cell까지 검증","compute":"GPU 권장","uses_gse209878":false} +{"id":"mizukoshi-2024-deepkinet","year":2024,"venue":"Genome Biology","method":"DeepKinet","type":"2-stage VAE","modality":"RNA-only","mechanism":"unspliced/spliced만으로 cell-specific splicing/degradation rate, scEU-seq·scNT-seq로 validation","result":"kinetic-rate 추정의 validation framework reference","limitation":"chromatin 없음(간접 가치), epigenomic-lag direct method 아님","compute":"GPU","uses_gse209878":false} +{"id":"nomura-2024-mmvelo","year":2024,"venue":"bioRxiv","method":"mmVelo","type":"multimodal VAE","modality":"multiome","mechanism":"multimodal latent에서 modality 간 dynamics 추정","result":"cross-modality velocity(preprint)","limitation":"preprint(peer-review 전), 재현 정보 제한","compute":"GPU","uses_gse209878":false} +{"id":"luo-2026-velocity-benchmark","year":2026,"venue":"Cell Reports Methods","method":"veloBench","type":"benchmark","modality":"mixed","mechanism":"15 method × 17 real+3 sim dataset을 accuracy/stability/usability로 비교","result":"단일 정답 없음; scenario별 권장(complex topology→DeepVelo/veloVI/LatentVelo). HSPC=Dataset12","limitation":"MultiVelo를 rna_only=True(ATAC off)로 실행 → multi-omic 성능 미평가","compute":"GPU+CPU","uses_gse209878":true} diff --git a/onboarding_gglee/week2/scope.md b/onboarding_gglee/week2/scope.md new file mode 100644 index 0000000..cf95eff --- /dev/null +++ b/onboarding_gglee/week2/scope.md @@ -0,0 +1,17 @@ +# scope — Insight Agent 대상 [BIOP01-15] + +## 주제 +single-cell RNA velocity로 **chromatin→transcription 타이밍(lag)과 kinetic rate**를 추정하는 method 계열. 우리 HSPC(GSE209878) 파이프라인 method 선택·해석의 근거. + +## 키워드 +RNA velocity, multiome (RNA+ATAC), chromatin accessibility, cell-specific kinetics, latent time, splicing/degradation rate, benchmark. + +## 포함 (9편, `paper_analysis/epigenomic-lag/`) +multivelo(li-2023) · multivelovae(li-2025) · moflow(hong-2026) · crakvelo(el-kazwini-2026) · celldancer(li-2023) · deepvelo(cui-2024) · deepkinet(mizukoshi-2024) · mmvelo(nomura-2024) · velocity-benchmark(luo-2026). + +## 제외 +- 순수 trajectory/pseudotime(velocity 무관), spatial-only, 리뷰 논문. +- 기준: velocity ODE 또는 kinetic-rate 추정을 제시하지 않으면 제외. + +## 산출 +`papers.jsonl`(비교 records) → `comparison_table.md` → `evidence_bundle.md` → `insight.md`(4관점). diff --git a/onboarding_gglee/week3/validation.md b/onboarding_gglee/week3/validation.md new file mode 100644 index 0000000..d16b71b --- /dev/null +++ b/onboarding_gglee/week3/validation.md @@ -0,0 +1,45 @@ +# validation — week2 Insight 검증 [BIOP01-8] + +week2 `insight.md`의 I1–I4를 6기준(Evidence/Logic/Scope/Novelty/Actionability/Risk)으로 검증. Status ∈ {Valid, Needs Evidence, Overstated, Unclear, Rejected}. + +--- + +## I1 — 계열은 정확도가 아니라 자유도 이동으로 진화, 최신 둘은 상보적 +- **Status: Valid** +- Evidence: 계보는 3개 브리프에서 직접 확인(moflow='두 갈래 중 하나', multivelovae='일반화', celldancer='predecessor'). [E1] +- Logic: cell-specific·latent-time·chromatin·multi-sample을 축으로 두면 각 method의 완화 축이 다름 → 상보 주장 성립. +- Scope: '상보적'은 *설계 축* 기준. 실측 성능 우열 주장 아님(그건 I2/벤치마크). 과확장 아님. +- Novelty: 개별 논문 요약을 넘은 계보-축 재구성 = 새 관찰. +- Risk: MoFlow와 MultiVeloVAE를 실제 우리 데이터에서 함께 돌려 정말 상보적(다른 gene에서 강함)인지는 미검증 → I4-②와 연결. + +## I2 — chromatin-aware 4종은 강점이 겹치지 않음 → 2–3종 교차+합의가 정당 +- **Status: Valid** (운영 권고로서) +- Evidence: 차별점은 브리프에서 각각 확인[E4]; 'no single answer'는 veloBench 결론[luo brief]. +- Logic: 강점 분산 + 공통 약점(인과·척도) → 교차 실행 합의가 단일 default보다 robust. 타당. +- Scope: veloBench의 권장은 RNA-only method(DeepVelo/veloVI/LatentVelo) 중심 → chromatin-aware 4종에 그대로 확장하는 건 **부분적 비약**. 'no single answer' 원칙은 이식되나 구체 후보 목록은 아님. +- Actionability: 높음 — 우리 파이프라인이 실제로 MultiVelo/MoFlow/MultiVeloVAE 3종 교차로 감(프로젝트 방향과 일치). +- Risk: 교차 후 '합의'를 어떻게 정의(방향 부호? 크기?)하는지 미정 → 척도 필요. + +## I3 — 세 한계(chromatin 인과·cell-cycle·척도)가 반복 +- **Status: Valid** +- Evidence: (a) CRAK-Velo k=0 ablation 부재 + veloBench ATAC-off = 2개 독립 근거[E2]. (b) cell-cycle 미명시는 3개 브리프 '재회고'[E3]. (c) pseudotime≠wall-clock은 multivelo brief 명시. +- Logic·Scope: 세 항목 모두 다수 논문에서 관찰 → '반복' 성립. 단 (b)는 "논문에 명시 안 됨"이지 "처리 안 함"이 아닐 수 있음 → 문구를 '미보고'로 한정해야 정확. +- Novelty: 개별 한계를 교차로 묶어 '분야 공통 맹점'으로 승격 = insight. +- Risk: (a)가 가장 강함(우리 자체 결과로 검증됨 — scrambled-chromatin 대조에서 lag가 chromatin 없이도 생존). → I4-①/②의 근거. + +## I4 — 미해결 공백(ATAC-on 이득, cross-method 재현, wall-clock, cell-cycle) +- **Status: Valid (핵심), 단 ①②는 우리 내부 결과로 이미 부분 답이 나옴 → '공백'→'우리 기여'로 재프레이밍 권장** +- Evidence: 공백 자체는 문헌 근거 확실(veloBench 공백, cross-method consistency 미보고)[E2,E4]. +- Logic: "분야가 안 한 것 = 우리가 할 것" 연결 타당. +- Scope: ①(ATAC-on 이득)·②(cross-method 재현)는 **우리 파이프라인이 이미 착수**(scrambled-null 대조, 3-method concordance) → 순수 '미해결'로 두면 우리 진척을 누락. 문헌 공백 + 우리 예비결과를 함께 기재해야 정직. +- Actionability: 매우 높음 — 프로젝트 핵심 가설(lag cross-method 재현성)과 직결. +- Risk: 우리 내부 결과(예: lag |ρ|≤0.08)는 아직 논문화 전 → insight 문서에 인용 시 '내부·잠정' 표기 필수. + +--- + +## 토론 준비(5문항) 답 +1. **가장 설득력**: I3(반복 한계) — 독립 근거 2개 이상 + 우리 실험과도 합치. +2. **근거 부족/과장**: I2의 'veloBench 권장을 chromatin-aware로 확장' 부분(부분 비약), I4를 순수 공백으로 둔 점(우리 진척 누락). +3. **Validation 필수 기준**: Evidence(근거 위치) + Scope(과확장 여부)가 이 도메인에서 가장 자주 걸림. +4. **결과 상충 시**: 근거 개수·독립성 우선, 우리 내부 예비결과는 '잠정'으로 하위 가중. +5. **출력 형식 통일안**: Insight마다 {Status, 6기준 한 줄, Evidence 경로, Risk} — 4주차 OpenClaw agent가 파싱 가능하도록 고정. (→ CLAIMS.yaml 스키마와 정합, BIOP01-69.) From 2b1f389516da617a4a3a421102e2347a5e7e6840 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 19:00:19 +0900 Subject: [PATCH 5/9] =?UTF-8?q?harness:=202=EC=B0=A8=20=EC=A0=84=EC=88=98?= =?UTF-8?q?=EC=A1=B0=EC=82=AC(=EC=9B=90=EB=B3=B8=C2=B7BIOP02=20=EB=8C=80?= =?UTF-8?q?=EC=A1=B0)=20+=20doctor=20=EC=A0=95=ED=95=A9=EC=84=B1=20?= =?UTF-8?q?=EA=B0=95=ED=99=94=20(BIOP02-100,=20BIOP01-64/65/66)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 불일치 보고 §6 추가 — 원본(kakyungkim/paper-production-harness)과 BIOP02를 추가 클론해 3자 대조. 1차 결론 2건 정정, 신규 결함 3건. - M5 reviewer 팬텀의 출처는 원본(agents/에 reviewer.md 없는데 paper-orchestrator.md:13이 정식 멤버로 명시) → BIOP01-64 반영 대상 2곳 → 3곳 - M6 게이트 순서는 관찰이 아니라 원본 규칙 위반 — 원본 paper-orchestrator.md:23이 "paper-critic + gate FIRST, then reviewer"를 명문화했으나 BIOP01·BIOP02 SKILL.md 둘 다 step7(리뷰) → step8(게이트)로 역전 - M7 BIOP02는 팬텀이 실행 설정에 배선 — auto_review_config.json:58 "agents": ["paper-critic","reviewer"], independent_passes 2 (enabled=false 상태) - M8 skills/ 라우터 팬텀(bc7f824에서 삭제, AGENTS.md:52-56이 여전히 위임) + HANDOFF/TODO/SESSION-LOG 핸드오프 계약 팬텀 → BIOP01-45 선결 조건 - M9 1차 doctor가 M8을 못 잡음 → 이번 커밋에서 보완 doctor 보완: - harness.yaml: path_reference_scan 신설(백틱 인용 경로 실재 검사, resolve_by_basename, 외부 repo/IP ignore), doc_reference_scan에 README.md·AGENTS.md 추가 - harness_doctor.py: 팬텀 경로 검사 추가 + 팬텀 에이전트 맥락 필터 (백틱/표=FAIL, 산문=WARN) — kkkim 공동리뷰 지적 반영 - 실측: RESULT: FAIL (14 문제, 3 경고) — 팬텀 에이전트 3 + 팬텀 경로 11 라이브 하네스는 여전히 미수정(7/21 합의). 스왑 시 ci/harness-doctor.yml → .github/workflows/ 활성화 필요(kkkim 권고). --- docs/HARNESS-RECONCILIATION-2026-07-26.md | 98 ++++++++++++++++ harness_after/README.md | 23 ++++ harness_after/harness.yaml | 23 ++++ harness_after/scripts/harness_doctor.py | 132 ++++++++++++++++++---- 4 files changed, 255 insertions(+), 21 deletions(-) diff --git a/docs/HARNESS-RECONCILIATION-2026-07-26.md b/docs/HARNESS-RECONCILIATION-2026-07-26.md index 7800463..9929bc8 100644 --- a/docs/HARNESS-RECONCILIATION-2026-07-26.md +++ b/docs/HARNESS-RECONCILIATION-2026-07-26.md @@ -83,3 +83,101 @@ - **FT2** (구조 판단): 프로젝트 에이전트 cwd 로딩 전제 문서화 + 전역 에이전트 배치 정리 (M1과 연동). - 문서 최신화(비구조): 검증 게이트 "사람 통과" 표현 정정, 도메인 이식 시 게이트 교체 명시 — `gglee` 브랜치 문서 정리에서 처리. - 공용 하네스 자산이므로 위 결정은 **BIOP02에도 동일 반영** 필요. + +--- + +## 6. 2차 조사 — 원본·BIOP02까지 확대 (2026-07-26 추가) + +**배경.** §1–§5(1차)는 BIOP01만 봤다. 그런데 BIOP02-100의 원래 검토 대상은 **원본·BIOP01·BIOP02 3자**다. 이날 저녁 원본(`kakyungkim/paper-production-harness`)과 BIOP02(`docs/BIOP02-53-kkkim-critic-review`)를 추가로 클론해 대조했고, BIOP01 문서는 백틱 인용 경로까지 전수 재스캔했다. 아래는 전부 파일 직접 확인 결과이며, 1차 결론 중 **두 건(M1 범위·M2 등급)을 정정**한다. + +### M5 — `reviewer` 팬텀의 출처는 원본이다 (M1 범위 정정) + +- **사실**: 원본 `agents/`에 파일 8개(design · literature-scout · manuscript-writer.template · novelty-strategist · paper-critic · paper-orchestrator · presenter · research-methodologist) — **`reviewer.md` 없음**. 그런데 원본 `agents/paper-orchestrator.md:13`이 `**reviewer** (external referee, substance-only)`를 정식 멤버로 명시한다. +- **영향**: BIOP01·BIOP02가 각각 실수한 게 아니라 **원본이 유령을 배포했고 두 인스턴스가 상속**했다. BIOP01만 고치면 원본에서 새로 인스턴스화하는 다음 프로젝트가 같은 팬텀을 다시 상속한다. +- **재현**: `git clone --depth 1 https://github.com/kakyungkim/paper-production-harness` → `ls agents/` → `grep -n "reviewer" agents/paper-orchestrator.md` +- **권고**: BIOP01-64의 반영 대상을 **2곳(BIOP01·BIOP02) → 3곳(+원본)** 으로 확대. 원본은 소유자(kkkim) 협의 필요. +- **완료조건**: 세 리포 모두에서 `reviewer` 참조가 실체와 일치(구현 또는 제거)하고, 원본 README에 이 스캐폴드가 `reviewer`를 포함하는지 여부가 1줄로 명시된다. + +### M6 — 게이트 순서(M2)는 설계 관찰이 아니라 원본 규칙 위반이다 (등급 승격) + +- **사실**: 원본 `agents/paper-orchestrator.md:23`이 순서를 명문화한다 — *"the internal→external review order (**paper-critic + gate FIRST, then reviewer** — reviewer assumes pre-submission QA is done)"*. 그런데 **BIOP01 SKILL.md와 BIOP02 SKILL.md 둘 다** step 7(정식 리뷰) → step 8(검증 게이트) 순서다. +- **영향**: 1차 보고는 이를 "설계 관찰(권고)"로 적었다. 실제로는 **원본이 스스로 정한 규칙을 두 인스턴스가 동일하게 뒤집은 인스턴스화 회귀**다. 취향 논쟁이 아니라 확정 불일치이므로 합의 없이 정정 가능한 항목으로 등급을 올린다. +- **재현**: 원본 `agents/paper-orchestrator.md:23` vs `BioProject01/.claude/skills/.../SKILL.md:51-52`, `BioProject02/.claude/skills/.../SKILL.md:39-40`. +- **권고**: 두 인스턴스의 step 7↔8 순서 교환. 검증 게이트는 §4 권고대로 **분석 직후 + 공개 직전 이중화**(kkkim 공동리뷰에서 동의됨 — `harness.yaml`의 result_validation/package_validation 분리로 해소). +- **완료조건**: 양 SKILL.md에서 결정론 게이트가 외부 리뷰보다 앞에 오고, 원본 규칙 인용이 주석으로 남는다. + +### M7 — BIOP02에서는 팬텀이 문서가 아니라 **실행 설정에 배선**돼 있다 (신규·최고 위험) + +- **사실**: `BioProject02/agents/critic/auto_review_config.json:58` → `"agents": ["paper-critic", "reviewer"]`, `"independent_passes": 2`. 이 값은 `auto_review_orchestrator.py`의 `drain_queue()`가 `review_requests/*.req.json`으로 발행하고 세션/OpenClaw가 그대로 실행한다. 현재 `"enabled": false`(dry-run)라 아직 터지지 않았을 뿐이다. +- **영향**: 활성화하는 순간 **적대적 리뷰 2패스 중 한 축이 존재하지 않는 에이전트를 호출**한다. 호출 실패가 예외로 뜨지 않고 범용 에이전트로 조용히 대체되면, 자동 리뷰는 "2패스 통과"로 기록되지만 실제로는 1패스만 돈 것이 된다. **P2(침묵 폴백)를 P0로 올린 판단이 코드로 확증됐다.** +- **재현**: `grep -n '"agents"' BioProject02/agents/critic/auto_review_config.json`, `sed -n 95,120p BioProject02/agents/critic/auto_review_orchestrator.py` +- **권고**: BIOP01-64 결정(구현 or 제거) 전까지 `enabled=true` 금지. 결정 후 config를 실체와 일치시키고, `forbid_generic_fallback`을 실행 래퍼가 강제한다(BIOP01-65). +- **완료조건**: config의 `agents` 목록 전원이 `.claude/agents/`에 실재하고, harness_doctor의 스캔 대상에 이 config가 포함된다. + +### M8 — BIOP01 라우터·핸드오프 계약이 통째로 팬텀 (신규, `reviewer`보다 넓음) + +- **사실 (a) 라우터**: `skills/` 디렉터리는 `bc7f824`(2026-06-14, *"pipeline: restructure kkkim-pipeline as pipeline-only branch"*)에서 삭제됐다. 그런데 `AGENTS.md:52-56`은 여전히 *"Dataset 작업 요청이면 먼저 `skills/ROUTES.md`를 읽습니다 → `skills///SKILL.md`를 사용합니다"* 로 라우팅을 위임한다. `README.md:12,27` · `CLAUDE.md:17,18,19`도 같은 경로(`skills/ROUTES.md`, `agents/openai.yaml`)를 가리킨다. **OpenClaw/Codex 쪽 라우터 전체가 죽은 링크다.** +- **사실 (b) 핸드오프 계약**: `CLAUDE.md:91` 산출물 계약의 마지막 행이 `| 상태 핸드오프 | (전원) | HANDOFF.md, TODO.md, SESSION-LOG.md | 다음 세션 |` 이고 `SKILL.md:75`도 동일하다. 이 브랜치에 **세 파일 모두 없다**(같은 재구조화 때 정리됨, 이력상 다른 브랜치에 존재). BIOP02도 동일 증상(`SESSION_LOG.md`/`TODO.md`/`HANDOFF.md`). +- **사실 (c) 규약**: `AGENTS.md:61-67`의 `data/` · `metadata/` · `work/` · `outputs/` 규약 디렉터리도 이 브랜치에 없다. +- **영향**: ① **BIOP01-45(OpenClaw로 P2–P5 runner 자동 실행)가 존재하지 않는 라우터 위에 설계되고 있다.** ② 모든 에이전트가 "필수 산출물"로 지시받는 핸드오프 파일이 없어, 매 실행이 새로 만들거나 조용히 건너뛴다 — 세션 간 상태 인계가 계약상으로만 존재한다. ③ **근본 원인이 `reviewer` 팬텀과 같다**: 파일을 지운 커밋이 문서를 안 고쳤고, 이를 잡을 게이트가 없었다. 즉 BIOP01-66(정합성 게이트)의 실증 사례가 1건에서 **3건**으로 늘었다. +- **재현**: `git log --diff-filter=D --oneline -- skills` → `bc7f824`. 그리고 아래 M9의 doctor 실행. +- **권고**: (1) `AGENTS.md` 라우팅 절을 실체에 맞게 정정하거나 `skills/`를 복원 — **BIOP01-45 착수 전 선결**. (2) 핸드오프 3파일을 만들거나 계약에서 제거(둘 중 하나, 방치 금지). 어느 쪽이든 `harness.yaml`에 등재. +- **완료조건**: harness_doctor `phantom-path` 0건. + +### M9 — 1차 `harness_doctor.py`는 M8을 잡지 못했다 (자기 점검 + 이번 커밋의 보완) + +- **사실**: 1차 doctor의 `doc_reference_scan.files`가 3개(`CLAUDE.md` · `docs/HARNESS.md` · `SKILL.md`)뿐이라 **`README.md` · `AGENTS.md`가 스캔 밖**이었고, 검사 대상도 *역할 이름 토큰*뿐이라 **경로 실재는 보지 않았다**. M8은 doctor가 아니라 별도 임시 스캔으로 찾았다. +- **조치 (이번 커밋)**: + 1. `harness.yaml`에 `path_reference_scan` 추가 — 백틱 인용 경로의 실재 검사. `resolve_by_basename`으로 상대 인용(`p3_concordance.py`)을 허용하고, 외부 repo·IP·모델 ID는 `ignore` 정규식으로 제외. + 2. 스캔 대상을 5개 문서로 확대(`README.md` · `AGENTS.md` 추가). + 3. **팬텀 에이전트 검출에 맥락 필터** — 백틱 인용 또는 표 행만 `FAIL`, 산문 언급은 `WARN`. (kkkim 공동리뷰 지적 반영: 산문에 'reviewer'가 우연히 들어간 경우의 오검 방지.) +- **실측 결과** (BIOP01 현재 상태, 보완 후): + + ``` + harness_doctor: repo=/home/gglee/project/BioProject01 + roles=12 artifacts=5 scan_files=5 phantom_paths=11 + WARN [phantom-agent?] 'reviewer' … CLAUDE.md:63 / HARNESS.md:49,62 / SKILL.md:3,28 (산문 — 사람 확인) + FAIL [phantom-agent] 'reviewer' … CLAUDE.md:76,89 / HARNESS.md:28 / SKILL.md:51,73 (라우팅·계약 = 강한 참조) + FAIL [phantom-path] 'skills/ROUTES.md' ← README.md:27, AGENTS.md:52,54, CLAUDE.md:18 + FAIL [phantom-path] 'HANDOFF.md' · 'TODO.md' · 'SESSION-LOG.md' (핸드오프 계약) + FAIL [phantom-path] 'agents/openai.yaml' · 'openai.yaml' · 'data/' · 'metadata/' · 'work/' · 'outputs/' + · 'download/preprocessing/model/visualization' + RESULT: FAIL (14 문제, 3 경고) exit 1 + ``` + +- **교훈**: 정합성 게이트도 **스코프가 곧 성능**이다. 게이트를 넣는 것으로 끝나지 않고, "무엇을 스캔 대상에 넣을지"가 manifest에 명시되고 리뷰돼야 한다. + +### 공동 리뷰 반영 (kkkim, 2026-07-26 18:53) + +self-review 방지를 위해 kkkim 님께 공동 리뷰를 요청했고 **3관점(① venue-reviewer 프로젝트 로컬 ② 정합성 게이트 최우선 ③ 검증 게이트 이중화) 모두 승인**을 받았다. kkkim 님은 gglee 브랜치를 worktree로 띄워 doctor를 직접 실행해 FAIL(exit 1) 재현까지 확인했다. 반영 요청 2건은 다음과 같이 처리한다. + +| 요청 | 처리 | +| --- | --- | +| 팬텀 토큰 스캔에 맥락 필터 한 겹 (오검 방지) | **이번 커밋 반영** — 강한 참조(백틱/표)만 FAIL, 산문은 WARN (M9-3) | +| 스왑 시 `ci/harness-doctor.yml` → `.github/workflows/` 로 PR CI 활성화 | **스왑 승인 시 수행** (BIOP01-66). 활성화 전까지 doctor는 수동 실행이라 drift가 사람 손에 의존한다 | + +kkkim 님이 예고한 BIOP02용 `harness.yaml`(project_profile: biop02, 슬롯=`spatialpatho-analyst`, 게이트=BIOP02판)에는 위 M7(config의 `agents` 목록)도 스캔 대상으로 포함할 것을 권한다. + +### 2차 조사 후 우선순위 갱신 + +| 순위 | 항목 | 티켓 | 변화 | +| --- | --- | --- | --- | +| P0 | 정합성 게이트(manifest + doctor + CI) — 스캔 범위 확대 포함 | BIOP01-66 | 실증 사례 1건 → **3건** | +| P0 | 침묵 폴백 차단(실행 전제 · 래퍼 · self-check) | BIOP01-65 | BIOP02 config 배선(M7)으로 **근거 강화** | +| P0 | 라우터 팬텀 해소 — `skills/ROUTES.md` | (신규) | **BIOP01-45 선결 조건** | +| P1 | `reviewer` → `venue-reviewer` 실체화/제거 | BIOP01-64 | 대상 2곳 → **3곳(+원본)** | +| P1 | 게이트 순서 정정(step 7↔8) | (신규) | 관찰 → **원본 규칙 위반** | +| P1~P3 | 3계층 분리 / RUN_STATE / CLAIMS / 개명 | BIOP01-67 · 68 · 69 · 70 | 변화 없음 | + +--- + +## 7. 산출물 인덱스 (branch `gglee`) + +| 산출물 | 내용 | +| --- | --- | +| `docs/HARNESS-RECONCILIATION-2026-07-26.md` | 이 문서 — 불일치 보고 (1차 §1–§5, 2차 §6) | +| `harness_after/` | 교체용 after 버전 (manifest · doctor · 문서 · 래퍼 · 템플릿 · CI). **라이브 미적용** | +| `harness_after/README.md` | 스왑 방법 (`cp` 목록 + `git revert` 되돌리기) | +| `onboarding_gglee/` | 온보딩 1~3주차 회고 산출물 (BIOP01-1 · 15 · 8) | + +> 라이브 `README.md` · `CLAUDE.md` · `docs/HARNESS.md`에서 위 산출물로 가는 링크는 **아직 넣지 않았다** — 7/21 합의(구조 미수정)에 따라 스왑 승인 시 함께 반영한다. diff --git a/harness_after/README.md b/harness_after/README.md index a1c2633..71df2cf 100644 --- a/harness_after/README.md +++ b/harness_after/README.md @@ -35,3 +35,26 @@ python scripts/harness_doctor.py --repo . --manifest harness.yaml # 통과 확 ## 상태 검토 대기(BIOP02-100 → 검토 중). 반영은 이건규 노트 v2(`~/HARNESS_REVIEW_AND_PROPOSAL_2026-07-26.md`) 재검토 및 팀 승인 후. + +--- + +## 2026-07-26 갱신 (2차 조사 + kkkim 공동리뷰 반영) + +### 바뀐 것 +- `harness.yaml` — `path_reference_scan` 신설(백틱 인용 경로 실재 검사), `doc_reference_scan` 대상에 `README.md` · `AGENTS.md` 추가. +- `scripts/harness_doctor.py` — 검사 4) 팬텀 **경로** 검출 추가. 팬텀 **에이전트** 검출에 맥락 필터(백틱/표 = FAIL, 산문 = WARN) 추가. + +### 왜 +1차 doctor는 `README.md` · `AGENTS.md`를 안 보고 역할 토큰만 검사해서, **`skills/ROUTES.md` 라우터 팬텀과 `HANDOFF/TODO/SESSION-LOG` 핸드오프 계약 팬텀을 놓쳤다**(보고서 §6 M8·M9). 맥락 필터는 kkkim 공동리뷰의 오검 방지 지적 반영. + +현재 리포 실행 결과: `RESULT: FAIL (14 문제, 3 경고)` — 팬텀 에이전트 3 + 팬텀 경로 11. + +### 스왑 시 반드시 함께 할 것 (kkkim 리뷰 권고) +```bash +mkdir -p .github/workflows +cp harness_after/ci/harness-doctor.yml .github/workflows/harness-doctor.yml # PR CI 활성화 +``` +이걸 빼면 doctor가 수동 실행에 머물러 drift 검출이 다시 사람 손에 의존한다. + +### 스왑 순서 (kkkim 권고) +`BIOP01-66`(manifest + doctor + CI) → `BIOP01-65`(실행 전제·래퍼) → `BIOP01-64`(venue-reviewer) → 나머지. diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml index 22cff8b..c47f081 100644 --- a/harness_after/harness.yaml +++ b/harness_after/harness.yaml @@ -69,8 +69,31 @@ execution: claim_ledger: CLAIMS.yaml # BIOP01-69 (예정) # 문서가 참조하지만 manifest에 없거나 implemented=false인 agent 이름은 doctor가 FAIL 처리한다. +# 2026-07-26 2차 조사: README.md·AGENTS.md 가 스캔 대상에서 빠져 skills/ROUTES.md 팬텀을 놓쳤다 → 확대. doc_reference_scan: files: + - README.md + - AGENTS.md - CLAUDE.md - docs/HARNESS.md - .claude/skills/paper-production-orchestrator/SKILL.md + +# 문서가 백틱으로 인용한 '경로'가 실재하는지 검사한다 (팬텀 경로). +# 근거: bc7f824(2026-06-14, pipeline-only 재구조화)가 skills/ 와 핸드오프 파일을 지웠으나 +# README/AGENTS/CLAUDE/SKILL 의 라우팅·산출물 계약은 그대로 남아 죽은 링크가 됐다. +path_reference_scan: + enabled: true + resolve_by_basename: true # `p3_concordance.py` 같은 상대 인용은 리포 내 동명 파일로 해석 + files: + - README.md + - AGENTS.md + - CLAUDE.md + - docs/HARNESS.md + - .claude/skills/paper-production-orchestrator/SKILL.md + ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) + - "^https?://" + - "^[0-9]+[.][0-9.]+$" + - "^/dev/" + - "^kakyungkim/" + - "^biospin/" + - "^(MahmoodLab|paige-ai|LGAI-EXAONE|prov-gigapath)/" diff --git a/harness_after/scripts/harness_doctor.py b/harness_after/scripts/harness_doctor.py index 89e0819..864b1f1 100644 --- a/harness_after/scripts/harness_doctor.py +++ b/harness_after/scripts/harness_doctor.py @@ -7,12 +7,15 @@ 검사: 1) implemented=true 역할의 path 존재 2) artifacts 경로 존재 - 3) 문서(doc_reference_scan)가 참조하는 agent 이름이 미구현(implemented=false)인데 쓰이면 FAIL ← reviewer 팬텀 검출 - 4) execution.require_repo_root: repo 루트(.git 또는 CLAUDE.md)에서 실행됐는지 + 3) 문서가 참조하는 agent 이름이 미구현이면 FAIL ← reviewer 팬텀 + - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 + 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md·HANDOFF.md 팬텀 + 5) execution.require_repo_root: repo 루트에서 실행됐는지 사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml 종료코드: 0=PASS, 1=FAIL, 2=실행오류 """ -import argparse, os, re, sys +import argparse, os, re, subprocess, sys + def load_yaml(path): try: @@ -23,6 +26,36 @@ def load_yaml(path): with open(path, encoding="utf-8") as f: return yaml.safe_load(f) + +def repo_index(repo): + """리포 내 모든 경로 세그먼트의 집합. 상대 인용(`p3_concordance.py`) 해석용.""" + names, tops = set(), set() + try: + out = subprocess.check_output(["git", "-C", repo, "ls-files"], text=True).splitlines() + except Exception: + out = [] + for root, dirs, files in os.walk(repo): + if ".git" in root.split(os.sep): + continue + for f in files: + out.append(os.path.relpath(os.path.join(root, f), repo)) + for rel in out: + parts = rel.split("/") + tops.add(parts[0]) + for seg in parts: + names.add(seg) + return names, tops + + +def classify_hit(line, tok): + """강한 참조 = 백틱 인용 또는 표 행(라우팅/계약). 그 외 산문은 약한 참조.""" + if re.search(r"`[^`\n]*(? Date: Sun, 26 Jul 2026 19:12:54 +0900 Subject: [PATCH 6/9] =?UTF-8?q?harness:=20=EA=B6=8C=EA=B3=A0=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=20=EC=8A=A4=EC=99=91=20?= =?UTF-8?q?66=E2=86=9265=E2=86=9264=E2=86=9272=20+=20=ED=95=B8=EB=93=9C?= =?UTF-8?q?=EC=98=A4=ED=94=84=20=EC=8B=A0=EC=84=A4=20(BIOP01-64/65/66/71/7?= =?UTF-8?q?2/73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kkkim 공동리뷰 승인(2026-07-26) 후 권고 순서대로 라이브 반영. 각 단계 검증 결과 포함. BIOP01-73 게이트 자체 테스트 (신규, 선행): - harness_after/tests/test_harness_doctor.py — 합성 리포 13종 정상통과 / 역할파일부재 FAIL / 백틱 팬텀 FAIL / 표행 팬텀 FAIL / 산문언급 WARN(오검방지) / 팬텀경로 FAIL / 상대인용 해석 / ignore 규칙 / 산출물부재 WARN / repo루트 강제 / 스코프갭 재현 / path_scan 토글 / 실제 리포 회귀 - 결과: 13/13 통과 BIOP01-66 정합성 게이트 라이브: - harness.yaml, scripts/harness_doctor.py, .github/workflows/harness-doctor.yml - CI 2단계 도입 — 게이트 자체 테스트는 blocking, 구성 검사는 report-only (팬텀 잔존 상태에서 전면 blocking이면 모든 PR이 빨간불) BIOP01-65 실행 전제 가드 라이브: - scripts/start-paper-harness. 검증 4케이스: 비-git → FATAL / repo 하위 → 루트 자동복귀 통과 / 타 repo → 구성요소 누락 차단 / HARNESS_DOCTOR_ENFORCE=1 → 중단 - python 미존재 환경 대비 인터프리터 해석 추가 BIOP01-64 venue-reviewer 라이브: - .claude/agents/venue-reviewer.md 프로젝트 로컬 설치(전역 금지) - 문서 참조 10건 개명: CLAUDE.md 3 / docs/HARNESS.md 3 / SKILL.md 4 - 결과: 팬텀 에이전트 3 → 0 BIOP01-72 게이트 순서 정정: - SKILL.md 실행순서를 게이트①(결과검증) → 리뷰 → 게이트②(패키지검증)로 교체 - 원본 paper-orchestrator.md:23 규칙 인용을 근거로 명시. BIOP02는 별도 BIOP01-71 핸드오프 3파일 신설: - HANDOFF.md / TODO.md / SESSION-LOG.md — 계약이 지시하던 실물 생성 - skills/ROUTES.md 라우터는 결정 대기(복원 vs 문서정정) doctor 추이: 14 → 11(64 반영) → 8(핸드오프 신설). 잔여 8건은 전부 skills/ 결정 대기분. --- .claude/agents/venue-reviewer.md | 19 ++ .../paper-production-orchestrator/SKILL.md | 11 +- .github/workflows/harness-doctor.yml | 32 +++ CLAUDE.md | 6 +- docs/HARNESS.md | 6 +- harness.yaml | 99 ++++++++ harness_after/ci/harness-doctor.yml | 23 +- harness_after/harness.yaml | 6 +- harness_after/scripts/start-paper-harness | 35 ++- harness_after/tests/test_harness_doctor.py | 229 ++++++++++++++++++ scripts/harness_doctor.py | 179 ++++++++++++++ scripts/start-paper-harness | 50 ++++ 12 files changed, 671 insertions(+), 24 deletions(-) create mode 100644 .claude/agents/venue-reviewer.md create mode 100644 .github/workflows/harness-doctor.yml create mode 100644 harness.yaml create mode 100644 harness_after/tests/test_harness_doctor.py create mode 100644 scripts/harness_doctor.py create mode 100755 scripts/start-paper-harness diff --git a/.claude/agents/venue-reviewer.md b/.claude/agents/venue-reviewer.md new file mode 100644 index 0000000..129990d --- /dev/null +++ b/.claude/agents/venue-reviewer.md @@ -0,0 +1,19 @@ +--- +name: venue-reviewer +description: 외부 venue-style 시뮬레이션 리뷰(referee). paper-critic(내부 적대검수) + 결과 검증 게이트 통과 후에만 호출한다. 원고 패키지만 읽고 내부 논의·분석 과정·critic 노트는 보지 않는다(격리). +--- + +# venue-reviewer (simulated referee) + +target venue의 referee처럼 **최종 원고 패키지만** 심사한다. + +## 격리 (필수) +- 입력은 `manuscript/draft_v2.md`(+`_ko`), 그림, `refs.bib`, `SUPPLEMENTARY.md` **뿐**. 분석 과정·내부 논의·critic 노트 접근 금지. +- 리뷰 상단에 **사용 모델·입력 범위**를 기록한다. 같은 모델 계열이면 "simulated review (외부 referee 아님)"임을 명시. +- 진짜 리뷰 다양성이 필요하면 **다른 모델 계열**로 실행한다. + +## 산출 +`manuscript/REVIEW--.md` — major/minor 이슈, 재현성·통계·novelty·형식·venue-fit. + +## 주의 +프로젝트 로컬 후보다(BIOP01-64). **전역(`~/.claude/agents/`) 설치 금지** — 숨은 환경 의존성 방지. 미설치 시 "정식 venue 리뷰" 요청은 건너뛰고 안내한다. diff --git a/.claude/skills/paper-production-orchestrator/SKILL.md b/.claude/skills/paper-production-orchestrator/SKILL.md index 661767c..83962bd 100644 --- a/.claude/skills/paper-production-orchestrator/SKILL.md +++ b/.claude/skills/paper-production-orchestrator/SKILL.md @@ -1,6 +1,6 @@ --- name: paper-production-orchestrator -description: 논문 생산 루프의 입구(진행표/팀장). "논문 풀 파이프라인 돌려줘", "프리프린트 업데이트해서 제출 준비", "분석→집필→그림→검수까지 한 번에", "그림만 다시", "리뷰만 다시", "critic 지적 반영해", "최신 결과로 본문 갱신" 같이 분석·집필·그림·검수·검증·발표를 엮는 요청에서 사용한다. 기존 멤버(hspc-velocity-analyst, manuscript-writer, 그림 스크립트, paper-critic, reviewer, presenter)를 정해진 순서로 호출하고 부분 재실행을 처리한다. 새 agent는 만들지 않는다. +description: 논문 생산 루프의 입구(진행표/팀장). "논문 풀 파이프라인 돌려줘", "프리프린트 업데이트해서 제출 준비", "분석→집필→그림→검수까지 한 번에", "그림만 다시", "리뷰만 다시", "critic 지적 반영해", "최신 결과로 본문 갱신" 같이 분석·집필·그림·검수·검증·발표를 엮는 요청에서 사용한다. 기존 멤버(hspc-velocity-analyst, manuscript-writer, 그림 스크립트, paper-critic, venue-reviewer, presenter)를 정해진 순서로 호출하고 부분 재실행을 처리한다. 새 agent는 만들지 않는다. --- # paper-production-orchestrator (논문 생산 루프 진행표 / 팀장) — HSPC velocity-lag benchmark @@ -25,7 +25,7 @@ description: 논문 생산 루프의 입구(진행표/팀장). "논문 풀 파 3. `hspc-velocity-analyst`가 LLM 기반 sub-분석을 쓰는 경우, **offline mock 경로**(API 키 미설정 등)로 돌았는지 확인한다. mock이면 "실 결과 아님 / 데모"를 보고에 명시한다. ## 멤버 구성 (전원 기존 재사용) -`hspc-velocity-analyst`(도메인 분석 슬롯), manuscript-writer(그림 포함 — `figures/figNN_*.py` 스크립트 실행), paper-critic, reviewer, presenter. (기획 단계 선택: research-methodologist, literature-scout, novelty-strategist.) +`hspc-velocity-analyst`(도메인 분석 슬롯), manuscript-writer(그림 포함 — `figures/figNN_*.py` 스크립트 실행), paper-critic, venue-reviewer, presenter. (기획 단계 선택: research-methodologist, literature-scout, novelty-strategist.) > 참고: 그림 생성은 **agent가 아니라 스크립트**로 둔다. `manuscript-writer`가 `pipeline/hspc-velocity-benchmark/figures/figNN_*.py`(예: `fig01_p2_concordance.py`)를 실행해 결과 파일에서 그림을 만든다. 단순 재생성이면 메인 루프가 직접 그 스크립트를 돌려도 된다(결정론적). @@ -48,8 +48,9 @@ description: 논문 생산 루프의 입구(진행표/팀장). "논문 풀 파 4. **집필 + 그림** — `manuscript-writer` → `manuscript/draft_v2.md` + `draft_v2_ko.md`(영/한 동시). 그림은 `figures/figNN_*.py` 실행 → `figures/`. 그림만 재실행이면 이 단계만(결정론적, 결과 파일에서 생성). 5. **검수** — `paper-critic`(적대적 + 그림 시각 QA) → 지적 노트. 블로킹이면 6으로, 경미하면 메모만. 6. **수정** — `manuscript-writer`가 critic 지적 반영 → 본문 갱신. -7. **(선택) 정식 리뷰** — 요청 시 `reviewer` → `manuscript/REVIEW--.md`. -8. **검증 게이트** — 아래 verify-gate 실행. **실패하면 멈추고 사람에게 보고**, 커밋·발행하지 않는다. +7. **검증 게이트 ①(결과 검증)** — 아래 verify-gate 실행. **실패하면 멈추고 사람에게 보고**, 커밋·발행하지 않는다. 원본 하네스 규칙: *"paper-critic + gate FIRST, then reviewer — reviewer assumes pre-submission QA is done"*(`paper-production-harness/agents/paper-orchestrator.md:23`). 숫자가 검증되지 않은 원고를 리뷰에 보내지 않는다. (BIOP01-72) +8. **(선택) 정식 리뷰** — 요청 시 `venue-reviewer` → `manuscript/REVIEW--.md`. **7을 통과한 원고만** 입력한다. +8.5 **검증 게이트 ②(패키지 검증, 공개 직전)** — 원고 본문 숫자 ↔ 결과 파일 재대조 + 그림·표·supplementary 동봉 확인. 리뷰 반영으로 본문이 바뀌었을 수 있으므로 **공개 전 한 번 더** 돌린다. 9. **(선택) 발표** — 요청 시 `presenter` → 덱·발제. 각 단계 산출물은 **파일로 남긴다**. 다음 단계는 그 파일을 읽는다. @@ -70,7 +71,7 @@ conda run --no-capture-output -n scv-preprocess python p3_scrambled_null.py | 집필 | manuscript-writer | `manuscript/draft_v2.md` + `draft_v2_ko.md`, `refs.bib`, `SUPPLEMENTARY.md` | 검수·리뷰·발표 | | 그림 | manuscript-writer (`figures/figNN_*.py`) | `figures/*.png` | 집필·검수 | | 검수 | paper-critic | 적대 노트 + 그림 QA | 집필(수정) | -| 리뷰 | reviewer | `manuscript/REVIEW--.md` | 집필(수정) | +| 리뷰 | venue-reviewer | `manuscript/REVIEW--.md` | 집필(수정) | | 발표 | presenter | 슬라이드/발제 | 사람 | | 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` | 다음 세션 | diff --git a/.github/workflows/harness-doctor.yml b/.github/workflows/harness-doctor.yml new file mode 100644 index 0000000..a166bab --- /dev/null +++ b/.github/workflows/harness-doctor.yml @@ -0,0 +1,32 @@ +# 하네스 구성 정합성 게이트 (BIOP01-66). +# +# 2단계 도입: +# 1단계(현재) — doctor는 report-only(continue-on-error). 게이트 자체 테스트는 blocking. +# 이유: 스왑 시점에 팬텀 14건이 남아 있어 바로 blocking으로 켜면 모든 PR이 빨간불이 된다. +# BIOP01-64/71/72가 닫혀 doctor가 green이 되면 2단계로 전환. +# 2단계 — `continue-on-error: true` 를 제거해 blocking 게이트로 승격. +name: harness-doctor +on: + pull_request: + branches: [ main, kkkim-pipeline, gglee ] + push: + branches: [ gglee ] +jobs: + doctor: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - run: pip install pyyaml + + # 게이트 자체의 검증 — 여기는 처음부터 blocking. + # 게이트가 틀리면 잘못된 PASS(놓침)·잘못된 FAIL(오검)이 그대로 팀 판단이 된다. + - name: 게이트 자체 테스트 (harness_doctor 단위·회귀) + run: python harness_after/tests/test_harness_doctor.py + + # 하네스 구성 검사 — 1단계에서는 report-only. + - name: 하네스 구성 정합성 검사 (팬텀 역할·경로 drift) + continue-on-error: true # ← BIOP01-64/71/72 종료 후 이 줄 삭제 = blocking 승격 + run: python scripts/harness_doctor.py --repo . --manifest harness.yaml diff --git a/CLAUDE.md b/CLAUDE.md index 3e6507f..b1ecc9f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,7 +60,7 @@ SKILL(지침)을 실제로 돌리는 코드: ### 자연어 라우팅 요청에 agent 이름이 없어도 아래 표로 배정한다. 프로젝트 agent는 `.claude/agents/`. 그림 작업은 `manuscript-writer`가 `pipeline/hspc-velocity-benchmark/figures/figNN_*.py`를 실행해 소유. -**논문 하네스 단일 컨텍스트 = `pipeline/hspc-velocity-benchmark/manuscript/PAPER_DIRECTION.md`.** 모든 논문 멤버(novelty·literature·methodologist·writer·critic·reviewer)는 작업 전 이 문서를 읽는다 — 현재 thesis·claim 등급표·loop 규율(**claim-defensibility 게이트**: headline claim은 반증기준+make-or-break 검정+advisor 통과 전 PROVISIONAL, 본문 미반영)·사전등록·진행상태가 여기 있다. 매번 재브리핑 불필요. +**논문 하네스 단일 컨텍스트 = `pipeline/hspc-velocity-benchmark/manuscript/PAPER_DIRECTION.md`.** 모든 논문 멤버(novelty·literature·methodologist·writer·critic·venue-reviewer)는 작업 전 이 문서를 읽는다 — 현재 thesis·claim 등급표·loop 규율(**claim-defensibility 게이트**: headline claim은 반증기준+make-or-break 검정+advisor 통과 전 PROVISIONAL, 본문 미반영)·사전등록·진행상태가 여기 있다. 매번 재브리핑 불필요. **여러 단계를 엮는 요청 → 단일 agent가 아니라 오케스트레이터 Skill.** "풀 파이프라인 / 프리프린트 업데이트해 제출 준비 / 분석→집필→그림→검수까지 / 그림만 다시 / 리뷰만 다시 / critic 지적 반영"은 **`paper-production-orchestrator`** Skill(`.claude/skills/paper-production-orchestrator/SKILL.md`)로 — 메인 루프가 실행하며 §0에서 PAPER_DIRECTION 로드 후 아래 멤버를 순서대로 호출하고 claim-defensibility 게이트·부분 재실행·검증 게이트를 처리한다. 단일 단계 요청은 아래 agent로 직접 라우팅: @@ -73,7 +73,7 @@ SKILL(지침)을 실제로 돌리는 코드: | "차별화 각도 / 뭘 새로 해야 하나" | `novelty-strategist` | | "가설·실험설계·분석계획 점검·감사" | `research-methodologist` | | "제출 전 적대적 자체검토 / 그림 QA" | `paper-critic` | -| "정식 venue 리뷰 시뮬레이션" | `reviewer` (전역, 선택) | +| "정식 venue 리뷰 시뮬레이션" | `venue-reviewer` (프로젝트 로컬, 선택) | | "발표자료/슬라이드/발제" | `presenter` | | "로고·아이콘·브랜드·그림 미감" | `design` | | "여러 단계를 어떤 순서로 엮을지 계획만" | `paper-orchestrator` (계획만; 실행은 메인 루프) | @@ -86,7 +86,7 @@ SKILL(지침)을 실제로 돌리는 코드: | 분석·eval | `hspc-velocity-analyst` | `pipeline/hspc-velocity-benchmark/results/FINDINGS.md` + `results/*.csv` + `results/*.md` | 집필·검수 | | 집필+그림 | manuscript-writer (그림=`figures/figNN_*.py`) | `pipeline/hspc-velocity-benchmark/manuscript/draft_v2.md` + `draft_v2_ko.md`(영/한 동시), `figures/*.png` | 검수·리뷰·발표 | | 검증 게이트 | (커밋/공개 전) | `p3_concordance.py` + `p3_crossdataset_concordance.py` + `p3_scrambled_null.py` 재계산 → FINDINGS.md 대조 | 사람 | -| 리뷰 | paper-critic / reviewer | `manuscript/REVIEW--.md` | 집필(수정) | +| 리뷰 | paper-critic / venue-reviewer | `manuscript/REVIEW--.md` | 집필(수정) | | 발표 | presenter | 슬라이드/발제 | 사람 | | 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` | 다음 세션 | diff --git a/docs/HARNESS.md b/docs/HARNESS.md index 00d1015..0cd0a71 100644 --- a/docs/HARNESS.md +++ b/docs/HARNESS.md @@ -25,7 +25,7 @@ | 6 | `paper-critic` | 심사·QA | 제출 전 적대적 자체검토 + 그림 시각 QA | 재사용 | | 7 | `paper-orchestrator` | 코디네이션 | 멀티-agent 작업 **계획** 수립(실행은 PI) | 재사용 | | 8 | `design` | 엔지니어링 | 로고·아이콘·브랜드·그림 미감(SVG/PNG) | 재사용 | -| 9 | `reviewer` (전역, 선택) | 심사·QA | 정식 venue 스타일 공식 리뷰 문서 | 선택 | +| 9 | `venue-reviewer` (프로젝트 로컬, 선택) | 심사·QA | 정식 venue 스타일 공식 리뷰 문서 | 선택 | | S | 그림 생성 (스크립트) | 엔지니어링 | `figures/figNN_*.py` — 결과 파일에서 그림 생성·번호 정합 | ✅ (스크립트) | > ⚠️ 그림 생성은 스크립트로 둔다. `manuscript-writer`가 `pipeline/hspc-velocity-benchmark/figures/figNN_*.py`(예: `fig01_p2_concordance.py`)를 실행해 만든다. 단순 재생성은 메인 루프가 직접 돌려도 된다(결정론적). @@ -46,7 +46,7 @@ 문헌·기획 분석실 집필실 심사·QA 엔지니어링 ──────── ────── ────── ─────── ────────── literature- hspc- manuscript- paper-critic design - scout velocity- writer reviewer(선택) [그림 생성= + scout velocity- writer venue-reviewer(선택) [그림 생성= novelty- analyst presenter (그림 QA는 figNN_*.py, strategist paper-critic) run by writer] research- @@ -59,7 +59,7 @@ research-methodologist / literature-scout / novelty-strategist (기획·근거 └─▶ hspc-velocity-analyst ──▶ results/FINDINGS.md + results/* (분석·검증) └─▶ manuscript-writer ──▶ manuscript/draft_v2.md + draft_v2_ko.md (집필, 영/한 동시) ║ figures/figNN_*.py ──▶ figures/*.png (그림) - └─▶ paper-critic ──▶ reviewer ──▶ manuscript/REVIEW-*.md (심사) + └─▶ paper-critic ──▶ venue-reviewer ──▶ manuscript/REVIEW-*.md (심사) └─▶ (수정 반영) manuscript-writer └─▶ verify-gate(p3_concordance + p3_crossdataset_concordance + p3_scrambled_null) ──▶ presenter ``` diff --git a/harness.yaml b/harness.yaml new file mode 100644 index 0000000..cbf3867 --- /dev/null +++ b/harness.yaml @@ -0,0 +1,99 @@ +# harness.yaml — 논문 생산 하네스 Single Source of Truth (manifest) +# 문서(HARNESS.md/CLAUDE.md/SKILL.md)와 코드는 이 manifest를 따른다. +# harness_doctor.py가 이 파일을 기준으로 실제 파일·문서 참조를 대조한다. +harness_version: 1 +project_profile: biop01 # 도메인 특화분은 project profile로 분리 (BIOP01-67) + +roles: + # --- 도메인 슬롯 (project profile에서 교체) --- + domain_analyst: + aka: hspc-velocity-analyst + type: agent + path: .claude/agents/hspc-velocity-analyst.md + required: true + implemented: true + # --- 재사용 코어 멤버 --- + literature_scout: { type: agent, path: .claude/agents/literature-scout.md, required: true, implemented: true } + novelty_strategist: { type: agent, path: .claude/agents/novelty-strategist.md, required: true, implemented: true } + research_methodologist: { type: agent, path: .claude/agents/research-methodologist.md, required: true, implemented: true } + manuscript_writer: { type: agent, path: .claude/agents/manuscript-writer.md, required: true, implemented: true } + presenter: { type: agent, path: .claude/agents/presenter.md, required: true, implemented: true } + paper_critic: { type: agent, path: .claude/agents/paper-critic.md, required: true, implemented: true } + design: { type: agent, path: .claude/agents/design.md, required: false, implemented: true } + paper_planner: { type: agent, path: .claude/agents/paper-orchestrator.md, required: true, implemented: true } # 개명 예정: paper-planner (BIOP01-70) + # --- 미구현 (문서에는 참조되나 실체 없음) — BIOP01-64 --- + venue_reviewer: + aka: [reviewer, simulated-referee] # 구명 `reviewer` 는 폐기 — 문서에 남아 있으면 팬텀 + type: agent + path: .claude/agents/venue-reviewer.md + required: false + implemented: true # BIOP01-64 반영 (2026-07-26, 프로젝트 로컬) + note: "프로젝트 로컬. 전역 설치 금지. 격리 규칙은 agent 본문 참조." + # --- 비-에이전트 구성요소 --- + production_runner: { type: skill, path: .claude/skills/paper-production-orchestrator/SKILL.md, required: true, implemented: true } # 개명 예정: paper-runner + figure_generation: { type: script, path: pipeline/hspc-velocity-benchmark/figures, required: true, implemented: true } + +gates: + result_validation: # 자동 무결성 — 분석 직후 + type: automatic + when: after_analysis + commands: + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_concordance.py" + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_crossdataset_concordance.py --dataset human_brain" + - "cd pipeline/hspc-velocity-benchmark/scripts && python p3_scrambled_null.py" + on_fail: stop_and_report + package_validation: # 자동 무결성 — 공개 직전 + type: automatic + when: before_release + checks: [manuscript_numbers_match_results, figures_regenerated, commit_and_data_pinned, numbers_unchanged_through_review] + on_fail: stop_and_report + claim_defensibility: # 과학적 판단 — 사람(advisor) 포함 + type: scientific_judgement + on_fail: human_approval + release: # 공개·거버넌스 — 사람 + type: governance + checks: [authors, affiliation, ip, corresponding_email, data_release] + on_fail: human_approval + +artifacts: + findings: pipeline/hspc-velocity-benchmark/results/FINDINGS.md + manuscript: pipeline/hspc-velocity-benchmark/manuscript/draft_v2.md + manuscript_ko: pipeline/hspc-velocity-benchmark/manuscript/draft_v2_ko.md + figures_dir: pipeline/hspc-velocity-benchmark/figures + paper_direction: pipeline/hspc-velocity-benchmark/manuscript/PAPER_DIRECTION.md + +execution: + require_repo_root: true # 상위 디렉터리 실행 금지 (BIOP01-65) + forbid_generic_fallback: true # 전문 agent 실패를 general-purpose로 대체 금지 + run_state: RUN_STATE.yaml # BIOP01-68 (예정) + claim_ledger: CLAIMS.yaml # BIOP01-69 (예정) + +# 문서가 참조하지만 manifest에 없거나 implemented=false인 agent 이름은 doctor가 FAIL 처리한다. +# 2026-07-26 2차 조사: README.md·AGENTS.md 가 스캔 대상에서 빠져 skills/ROUTES.md 팬텀을 놓쳤다 → 확대. +doc_reference_scan: + files: + - README.md + - AGENTS.md + - CLAUDE.md + - docs/HARNESS.md + - .claude/skills/paper-production-orchestrator/SKILL.md + +# 문서가 백틱으로 인용한 '경로'가 실재하는지 검사한다 (팬텀 경로). +# 근거: bc7f824(2026-06-14, pipeline-only 재구조화)가 skills/ 와 핸드오프 파일을 지웠으나 +# README/AGENTS/CLAUDE/SKILL 의 라우팅·산출물 계약은 그대로 남아 죽은 링크가 됐다. +path_reference_scan: + enabled: true + resolve_by_basename: true # `p3_concordance.py` 같은 상대 인용은 리포 내 동명 파일로 해석 + files: + - README.md + - AGENTS.md + - CLAUDE.md + - docs/HARNESS.md + - .claude/skills/paper-production-orchestrator/SKILL.md + ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) + - "^https?://" + - "^[0-9]+[.][0-9.]+$" + - "^/dev/" + - "^kakyungkim/" + - "^biospin/" + - "^(MahmoodLab|paige-ai|LGAI-EXAONE|prov-gigapath)/" diff --git a/harness_after/ci/harness-doctor.yml b/harness_after/ci/harness-doctor.yml index 7d0506f..a166bab 100644 --- a/harness_after/ci/harness-doctor.yml +++ b/harness_after/ci/harness-doctor.yml @@ -1,9 +1,16 @@ -# 후보 CI (BIOP01-66). 승인 후 .github/workflows/harness-doctor.yml 로 스왑하면 활성화. -# harness_after/ 안에 두어 지금은 비활성(스왑 전까지 CI 미동작). +# 하네스 구성 정합성 게이트 (BIOP01-66). +# +# 2단계 도입: +# 1단계(현재) — doctor는 report-only(continue-on-error). 게이트 자체 테스트는 blocking. +# 이유: 스왑 시점에 팬텀 14건이 남아 있어 바로 blocking으로 켜면 모든 PR이 빨간불이 된다. +# BIOP01-64/71/72가 닫혀 doctor가 green이 되면 2단계로 전환. +# 2단계 — `continue-on-error: true` 를 제거해 blocking 게이트로 승격. name: harness-doctor on: pull_request: - branches: [ main, kkkim-pipeline ] + branches: [ main, kkkim-pipeline, gglee ] + push: + branches: [ gglee ] jobs: doctor: runs-on: ubuntu-latest @@ -13,5 +20,13 @@ jobs: with: python-version: "3.11" - run: pip install pyyaml - - name: 하네스 구성 정합성 검사 (팬텀·경로 drift) + + # 게이트 자체의 검증 — 여기는 처음부터 blocking. + # 게이트가 틀리면 잘못된 PASS(놓침)·잘못된 FAIL(오검)이 그대로 팀 판단이 된다. + - name: 게이트 자체 테스트 (harness_doctor 단위·회귀) + run: python harness_after/tests/test_harness_doctor.py + + # 하네스 구성 검사 — 1단계에서는 report-only. + - name: 하네스 구성 정합성 검사 (팬텀 역할·경로 drift) + continue-on-error: true # ← BIOP01-64/71/72 종료 후 이 줄 삭제 = blocking 승격 run: python scripts/harness_doctor.py --repo . --manifest harness.yaml diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml index c47f081..cbf3867 100644 --- a/harness_after/harness.yaml +++ b/harness_after/harness.yaml @@ -23,12 +23,12 @@ roles: paper_planner: { type: agent, path: .claude/agents/paper-orchestrator.md, required: true, implemented: true } # 개명 예정: paper-planner (BIOP01-70) # --- 미구현 (문서에는 참조되나 실체 없음) — BIOP01-64 --- venue_reviewer: - aka: [reviewer, venue-reviewer, simulated-referee] + aka: [reviewer, simulated-referee] # 구명 `reviewer` 는 폐기 — 문서에 남아 있으면 팬텀 type: agent path: .claude/agents/venue-reviewer.md required: false - implemented: false # ← doctor가 문서 참조 대비 미구현으로 FAIL 처리해야 함 - note: "프로젝트 로컬 구현 예정. 전역 실체화 금지. 격리 규칙 필요." + implemented: true # BIOP01-64 반영 (2026-07-26, 프로젝트 로컬) + note: "프로젝트 로컬. 전역 설치 금지. 격리 규칙은 agent 본문 참조." # --- 비-에이전트 구성요소 --- production_runner: { type: skill, path: .claude/skills/paper-production-orchestrator/SKILL.md, required: true, implemented: true } # 개명 예정: paper-runner figure_generation: { type: script, path: pipeline/hspc-velocity-benchmark/figures, required: true, implemented: true } diff --git a/harness_after/scripts/start-paper-harness b/harness_after/scripts/start-paper-harness index 72eafce..03b88e4 100755 --- a/harness_after/scripts/start-paper-harness +++ b/harness_after/scripts/start-paper-harness @@ -1,7 +1,16 @@ #!/usr/bin/env bash # start-paper-harness — 실행 전제 가드 (BIOP01-65). -# repo 루트·필수 구성요소·정합성 게이트를 확인한 뒤에만 하네스 진입. -# 전문 agent 실패를 범용 agent로 대체하지 않는다: 누락 시 즉시 중단. +# +# 원칙: 전문 agent 호출 실패를 범용 agent 실행으로 대체하지 않는다. +# 구성요소가 없으면 "조용히 다른 걸로" 대신 즉시 중단하고 사람에게 보고한다. +# +# 두 종류의 실패를 구분한다: +# (a) 구성요소 부재 — 항상 하드 실패. 이게 침묵 폴백의 입구다. +# (b) 문서 drift(팬텀 참조) — 1단계에서는 경고. BIOP01-64/71/72가 닫히면 +# HARNESS_DOCTOR_ENFORCE=1 을 기본값으로 올려 하드 실패로 승격한다. +# +# 사용: ./scripts/start-paper-harness # 1단계(기본): drift는 경고 +# HARNESS_DOCTOR_ENFORCE=1 ./scripts/start-paper-harness # 2단계: drift도 중단 set -euo pipefail ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" @@ -9,6 +18,7 @@ ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" cd "$ROOT" [ -f CLAUDE.md ] || { echo "FATAL: repo 루트가 아님(CLAUDE.md 없음). 상위 디렉터리 실행 금지."; exit 1; } +# (a) 필수 구성요소 — 하나라도 없으면 진입 금지 req=( ".claude/agents/hspc-velocity-analyst.md" ".claude/skills/paper-production-orchestrator/SKILL.md" @@ -18,10 +28,23 @@ missing=0 for p in "${req[@]}"; do [ -e "$p" ] || { echo "MISSING: $p"; missing=1; }; done [ "$missing" -eq 0 ] || { echo "FATAL: 필수 구성요소 누락 → production run 중단 (범용 폴백 금지)."; exit 1; } -# 정합성 게이트 (manifest ↔ 실제/문서) +# python 인터프리터 해석 — `python` 이 없는 환경이 실제로 있다(conda env 등). +PY="${HARNESS_PYTHON:-}" +if [ -z "$PY" ]; then + for c in python3 python; do command -v "$c" >/dev/null 2>&1 && { PY="$c"; break; }; done +fi +[ -n "$PY" ] || { echo "FATAL: python 인터프리터를 찾지 못함. HARNESS_PYTHON 을 지정하라."; exit 1; } + +# (b) 정합성 게이트 (manifest ↔ 실제/문서) if [ -f scripts/harness_doctor.py ] && [ -f harness.yaml ]; then - python scripts/harness_doctor.py --repo . --manifest harness.yaml \ - || { echo "FATAL: harness_doctor FAIL → 하네스 진입 중단."; exit 1; } + if "$PY" scripts/harness_doctor.py --repo . --manifest harness.yaml; then + : + else + if [ "${HARNESS_DOCTOR_ENFORCE:-0}" = "1" ]; then + echo "FATAL: harness_doctor FAIL → 하네스 진입 중단 (enforce 모드)."; exit 1 + fi + echo "WARN: harness_doctor FAIL — 1단계라 진입은 허용한다. BIOP01-64/71/72 종료 후 enforce 로 승격할 것." + fi fi -echo "OK: 실행 전제 통과 (cwd=$ROOT). 하네스 진입 허용." +echo "OK: 실행 전제 통과 (cwd=$ROOT, python=$PY). 하네스 진입 허용." diff --git a/harness_after/tests/test_harness_doctor.py b/harness_after/tests/test_harness_doctor.py new file mode 100644 index 0000000..3b75b23 --- /dev/null +++ b/harness_after/tests/test_harness_doctor.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +"""test_harness_doctor.py — 정합성 게이트(harness_doctor.py)의 검증 테스트. + +왜 필요한가: harness_doctor는 "하네스 구성이 맞는지" 판정하는 게이트다. +게이트가 틀리면 잘못된 PASS(놓침) 또는 잘못된 FAIL(오검)이 그대로 팀 판단이 된다. +그래서 게이트 자체를 검증한다 — 합성 리포를 만들어 **알려진 정답**과 대조한다. + +의존성: 표준 라이브러리 + PyYAML(doctor가 사용). pytest 불필요. +실행: python harness_after/tests/test_harness_doctor.py +종료코드: 0=전부 통과, 1=실패 있음 +""" +import json +import os +import shutil +import subprocess +import sys +import tempfile +import unittest + +HERE = os.path.dirname(os.path.abspath(__file__)) +DOCTOR = os.path.join(HERE, "..", "scripts", "harness_doctor.py") + + +BASE_MANIFEST = """\ +harness_version: 1 +project_profile: test +roles: + analyst: + type: agent + path: .claude/agents/analyst.md + required: true + implemented: true + venue_reviewer: + aka: [reviewer] + type: agent + path: .claude/agents/venue-reviewer.md + required: false + implemented: false +artifacts: + findings: results/FINDINGS.md +execution: + require_repo_root: true +doc_reference_scan: + files: +%(scan_files)s +path_reference_scan: + enabled: %(path_scan)s + resolve_by_basename: true + files: +%(scan_files)s + ignore: + - "^https?://" + - "^upstream/" +""" + + +def write(path, text): + os.makedirs(os.path.dirname(path), exist_ok=True) + with open(path, "w", encoding="utf-8") as f: + f.write(text) + + +class DoctorCase(unittest.TestCase): + """합성 리포를 만들고 doctor를 서브프로세스로 돌려 결과를 대조한다.""" + + def setUp(self): + self.repo = tempfile.mkdtemp(prefix="harness_doctor_test_") + # repo 루트 표식 + 실재하는 역할/산출물 + write(os.path.join(self.repo, "CLAUDE.md"), "# test repo\n") + write(os.path.join(self.repo, ".claude/agents/analyst.md"), "agent\n") + write(os.path.join(self.repo, "results/FINDINGS.md"), "findings\n") + + def tearDown(self): + shutil.rmtree(self.repo, ignore_errors=True) + + def manifest(self, scan_files=("CLAUDE.md",), path_scan="true"): + body = BASE_MANIFEST % { + "scan_files": "".join(" - %s\n" % f for f in scan_files), + "path_scan": path_scan, + } + write(os.path.join(self.repo, "harness.yaml"), body) + + def run_doctor(self, repo=None): + r = subprocess.run( + [sys.executable, DOCTOR, "--repo", repo or self.repo, + "--manifest", "harness.yaml"], + capture_output=True, text=True) + return r.returncode, r.stdout + r.stderr + + # ---- 1. 정상 구성이면 통과해야 한다 (잘못된 FAIL이 없는지) ---- + def test_clean_repo_passes(self): + write(os.path.join(self.repo, "CLAUDE.md"), "# test\n`results/FINDINGS.md` 를 읽는다.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "정상 구성인데 FAIL — 오검\n" + out) + self.assertIn("RESULT: PASS", out) + + # ---- 2. 구현했다고 선언한 역할 파일이 없으면 FAIL ---- + def test_missing_implemented_role_fails(self): + os.remove(os.path.join(self.repo, ".claude/agents/analyst.md")) + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("[role]", out) + + # ---- 3. 팬텀 에이전트: 백틱 인용(강한 참조)은 FAIL ---- + def test_phantom_agent_backtick_fails(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n| 정식 리뷰 | `reviewer` (선택) |\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("[phantom-agent]", out) + + # ---- 4. 팬텀 에이전트: 표 행(강한 참조)도 FAIL ---- + def test_phantom_agent_table_row_fails(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n| 리뷰 | paper-critic / reviewer | 노트 |\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("[phantom-agent]", out) + + # ---- 5. 팬텀 에이전트: 산문 언급은 WARN, FAIL 아님 (kkkim 오검 지적) ---- + def test_phantom_agent_prose_only_warns(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n심사자(a real reviewer)가 지적하기 전에 잡는다.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "산문 언급을 FAIL 처리 — 오검\n" + out) + self.assertIn("[phantom-agent?]", out) + self.assertIn("RESULT: PASS", out) + + # ---- 6. 팬텀 경로: 실재하지 않는 인용 경로는 FAIL ---- + def test_phantom_path_fails(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n라우팅은 `skills/ROUTES.md` 에 위임한다.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("[phantom-path]", out) + self.assertIn("skills/ROUTES.md", out) + + # ---- 7. 상대 인용은 basename으로 해석되어 FAIL 아님 ---- + def test_relative_reference_resolves(self): + write(os.path.join(self.repo, "pipeline/scripts/p3_concordance.py"), "#\n") + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n검증 게이트는 `p3_concordance.py` 재계산.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "상대 인용을 팬텀으로 오검\n" + out) + + # ---- 8. ignore 규칙에 걸리는 외부 참조는 FAIL 아님 ---- + def test_ignored_external_reference(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n상류는 `upstream/paper-production-harness` 다.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "ignore 규칙이 동작하지 않음\n" + out) + + # ---- 9. 산출물 부재는 WARN (아직 안 만든 단계일 수 있음) ---- + def test_missing_artifact_warns_not_fails(self): + os.remove(os.path.join(self.repo, "results/FINDINGS.md")) + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "산출물 부재를 FAIL 처리 — 과잉\n" + out) + self.assertIn("[artifact]", out) + + # ---- 10. repo 루트가 아니면 FAIL (BIOP01-65 실행 전제) ---- + def test_require_repo_root(self): + self.manifest() + sub = os.path.join(self.repo, "sub") + os.makedirs(sub, exist_ok=True) + shutil.copy(os.path.join(self.repo, "harness.yaml"), os.path.join(sub, "harness.yaml")) + code, out = self.run_doctor(repo=sub) + self.assertEqual(code, 1, out) + self.assertIn("[execution]", out) + + # ---- 11. 스캔 대상에서 빠진 문서의 팬텀은 검출되지 않는다 ---- + # (= "스코프가 곧 성능" — 2026-07-26 2차 조사에서 실제로 겪은 실패 모드) + def test_scope_gap_is_real(self): + write(os.path.join(self.repo, "AGENTS.md"), + "# router\n라우팅은 `skills/ROUTES.md` 에 위임한다.\n") + self.manifest(scan_files=("CLAUDE.md",)) # AGENTS.md 미포함 + code_before, out_before = self.run_doctor() + self.manifest(scan_files=("CLAUDE.md", "AGENTS.md")) # 포함 + code_after, out_after = self.run_doctor() + self.assertEqual(code_before, 0, "스코프 밖인데 검출됨 — 테스트 전제 오류\n" + out_before) + self.assertEqual(code_after, 1, "스코프에 넣었는데 미검출 — 회귀\n" + out_after) + self.assertIn("skills/ROUTES.md", out_after) + + # ---- 12. path_reference_scan을 끄면 경로 검사가 돌지 않는다 ---- + def test_path_scan_toggle(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n`skills/ROUTES.md` 참조.\n") + self.manifest(path_scan="false") + code, out = self.run_doctor() + self.assertEqual(code, 0, out) + self.assertNotIn("[phantom-path]", out) + + +class LiveRepoCase(unittest.TestCase): + """실제 BIOP01 리포에 대한 회귀 확인 — 알려진 결함이 계속 잡히는가.""" + + REPO = os.path.abspath(os.path.join(HERE, "..", "..")) + + def test_known_defects_detected(self): + manifest = os.path.join(self.REPO, "harness.yaml") + tmp_placed = False + if not os.path.exists(manifest): + shutil.copy(os.path.join(HERE, "..", "harness.yaml"), manifest) + tmp_placed = True + try: + r = subprocess.run( + [sys.executable, DOCTOR, "--repo", self.REPO, "--manifest", "harness.yaml"], + capture_output=True, text=True) + out = r.stdout + r.stderr + if "CLAUDE.md" not in out and r.returncode == 2: + self.skipTest("BIOP01 리포 컨텍스트 아님") + # 2026-07-26 2차 조사에서 확인된 결함들이 계속 잡혀야 한다 + for expected in ("[phantom-agent]", "skills/ROUTES.md", "HANDOFF.md"): + self.assertIn(expected, out, "알려진 결함 미검출: %s\n%s" % (expected, out)) + finally: + if tmp_placed: + os.remove(manifest) + + +if __name__ == "__main__": + unittest.main(verbosity=2) diff --git a/scripts/harness_doctor.py b/scripts/harness_doctor.py new file mode 100644 index 0000000..864b1f1 --- /dev/null +++ b/scripts/harness_doctor.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +"""harness_doctor.py — 하네스 구성 정합성 게이트. + +harness.yaml(manifest)을 기준으로 실제 파일·문서 참조가 일치하는지 검사한다. +논문 '결과'가 아니라 하네스 '구성 자체'를 검증한다. PR CI에서 돌린다. + +검사: + 1) implemented=true 역할의 path 존재 + 2) artifacts 경로 존재 + 3) 문서가 참조하는 agent 이름이 미구현이면 FAIL ← reviewer 팬텀 + - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 + 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md·HANDOFF.md 팬텀 + 5) execution.require_repo_root: repo 루트에서 실행됐는지 +사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml +종료코드: 0=PASS, 1=FAIL, 2=실행오류 +""" +import argparse, os, re, subprocess, sys + + +def load_yaml(path): + try: + import yaml + except ImportError: + print("ERROR: PyYAML 필요 (pip install pyyaml / conda install pyyaml)", file=sys.stderr) + sys.exit(2) + with open(path, encoding="utf-8") as f: + return yaml.safe_load(f) + + +def repo_index(repo): + """리포 내 모든 경로 세그먼트의 집합. 상대 인용(`p3_concordance.py`) 해석용.""" + names, tops = set(), set() + try: + out = subprocess.check_output(["git", "-C", repo, "ls-files"], text=True).splitlines() + except Exception: + out = [] + for root, dirs, files in os.walk(repo): + if ".git" in root.split(os.sep): + continue + for f in files: + out.append(os.path.relpath(os.path.join(root, f), repo)) + for rel in out: + parts = rel.split("/") + tops.add(parts[0]) + for seg in parts: + names.add(seg) + return names, tops + + +def classify_hit(line, tok): + """강한 참조 = 백틱 인용 또는 표 행(라우팅/계약). 그 외 산문은 약한 참조.""" + if re.search(r"`[^`\n]*(?/dev/null || true)" +[ -n "$ROOT" ] || { echo "FATAL: git 저장소가 아님. repo 루트에서 실행하라."; exit 1; } +cd "$ROOT" +[ -f CLAUDE.md ] || { echo "FATAL: repo 루트가 아님(CLAUDE.md 없음). 상위 디렉터리 실행 금지."; exit 1; } + +# (a) 필수 구성요소 — 하나라도 없으면 진입 금지 +req=( + ".claude/agents/hspc-velocity-analyst.md" + ".claude/skills/paper-production-orchestrator/SKILL.md" + "pipeline/hspc-velocity-benchmark/scripts/p3_concordance.py" +) +missing=0 +for p in "${req[@]}"; do [ -e "$p" ] || { echo "MISSING: $p"; missing=1; }; done +[ "$missing" -eq 0 ] || { echo "FATAL: 필수 구성요소 누락 → production run 중단 (범용 폴백 금지)."; exit 1; } + +# python 인터프리터 해석 — `python` 이 없는 환경이 실제로 있다(conda env 등). +PY="${HARNESS_PYTHON:-}" +if [ -z "$PY" ]; then + for c in python3 python; do command -v "$c" >/dev/null 2>&1 && { PY="$c"; break; }; done +fi +[ -n "$PY" ] || { echo "FATAL: python 인터프리터를 찾지 못함. HARNESS_PYTHON 을 지정하라."; exit 1; } + +# (b) 정합성 게이트 (manifest ↔ 실제/문서) +if [ -f scripts/harness_doctor.py ] && [ -f harness.yaml ]; then + if "$PY" scripts/harness_doctor.py --repo . --manifest harness.yaml; then + : + else + if [ "${HARNESS_DOCTOR_ENFORCE:-0}" = "1" ]; then + echo "FATAL: harness_doctor FAIL → 하네스 진입 중단 (enforce 모드)."; exit 1 + fi + echo "WARN: harness_doctor FAIL — 1단계라 진입은 허용한다. BIOP01-64/71/72 종료 후 enforce 로 승격할 것." + fi +fi + +echo "OK: 실행 전제 통과 (cwd=$ROOT, python=$PY). 하네스 진입 허용." From 6043149ba2f7f9d44f87b35cb442388d66faf247 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 19:17:13 +0900 Subject: [PATCH 7/9] =?UTF-8?q?harness:=20local=5Fonly=20=EA=B0=9C?= =?UTF-8?q?=EB=85=90=20=EB=8F=84=EC=9E=85=20=E2=80=94=20=ED=95=B8=EB=93=9C?= =?UTF-8?q?=EC=98=A4=ED=94=84=20=ED=8C=8C=EC=9D=BC=20=EC=98=A4=EA=B2=80=20?= =?UTF-8?q?=EC=A0=95=EC=A0=95=20(BIOP01-66/71/73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 스왑 중 발견: HANDOFF/TODO/SESSION-LOG 는 삭제된 게 아니라 78a5a92(2026-07-01) "개인 작업기록 untrack"으로 .gitignore:115-117 에 등재된 로컬 전용 파일이다 (BIOP02 .gitignore:246-248 도 동일). 보고서 §6 M8(b) 진단이 틀렸고, doctor 의 팬텀 경로 검사가 이를 오검했다. 정정: - harness.yaml: path_reference_scan.local_only 선언 추가 - harness_doctor.py: local_only 는 부재해도 FAIL 하지 않음. 대신 .gitignore 등재 여부를 확인 — 계약상 "필수 산출물"인데 ignore 에서 빠지면 실수로 커밋되므로 그때는 FAIL - 테스트 #13(부재+ignore → PASS)·#14(ignore 누락 → FAIL) 추가 → 15/15 통과 - 계약 문구에 "로컬 전용(.gitignore)" 표기 — CLAUDE.md:32,91 / SKILL.md:76 - 보고서 §8 정정 절 추가 (원문 §6 M8(b) 는 기록으로 보존) 교훈: "문서가 가리키는데 파일이 없다"는 진짜 drift 와 의도적 로컬 전용을 가린다. 의도는 manifest 에 선언되고, 게이트는 선언되지 않은 것만 문제 삼아야 한다. doctor 추이: 14 → 11(64) → 8(local_only 정정). 잔여 8건은 전부 skills/ 결정 대기. --- .../paper-production-orchestrator/SKILL.md | 2 +- CLAUDE.md | 4 +-- docs/HARNESS-RECONCILIATION-2026-07-26.md | 25 ++++++++++++++ harness.yaml | 7 ++++ harness_after/harness.yaml | 7 ++++ harness_after/scripts/harness_doctor.py | 20 ++++++++++- harness_after/tests/test_harness_doctor.py | 34 +++++++++++++++++-- scripts/harness_doctor.py | 20 ++++++++++- 8 files changed, 111 insertions(+), 8 deletions(-) diff --git a/.claude/skills/paper-production-orchestrator/SKILL.md b/.claude/skills/paper-production-orchestrator/SKILL.md index 83962bd..c606561 100644 --- a/.claude/skills/paper-production-orchestrator/SKILL.md +++ b/.claude/skills/paper-production-orchestrator/SKILL.md @@ -73,7 +73,7 @@ conda run --no-capture-output -n scv-preprocess python p3_scrambled_null.py | 검수 | paper-critic | 적대 노트 + 그림 QA | 집필(수정) | | 리뷰 | venue-reviewer | `manuscript/REVIEW--.md` | 집필(수정) | | 발표 | presenter | 슬라이드/발제 | 사람 | -| 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` | 다음 세션 | +| 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` — **로컬 전용(.gitignore)**. 없으면 새로 만든다 | 다음 세션 | ## 실패 처리 / 멈춤 조건 - verify 게이트 실패 → **멈춤**, 무엇이 왜 실패했는지 보고. diff --git a/CLAUDE.md b/CLAUDE.md index b1ecc9f..291c7b3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,7 +29,7 @@ SKILL(지침)을 실제로 돌리는 코드: - `BASELINE-ALIGNMENT.md` — Harness_Baseline 정합 기록. ## 작업 기록 -- **`SESSION-LOG.md`**: 분석 단계에서 한 일을 세션별로 누적 기록. +- **`SESSION-LOG.md`**: 분석 단계에서 한 일을 세션별로 누적 기록. *(아래 3개는 모두 **로컬 전용** — `.gitignore` 등재, 리포에 커밋하지 않는 개인 작업기록)* - **`HANDOFF.md`**: 현재 상태 + 한 일/할 일. **`TODO.md`**: 할 일 체크리스트. ## Branch 모델 (중요) @@ -88,7 +88,7 @@ SKILL(지침)을 실제로 돌리는 코드: | 검증 게이트 | (커밋/공개 전) | `p3_concordance.py` + `p3_crossdataset_concordance.py` + `p3_scrambled_null.py` 재계산 → FINDINGS.md 대조 | 사람 | | 리뷰 | paper-critic / venue-reviewer | `manuscript/REVIEW--.md` | 집필(수정) | | 발표 | presenter | 슬라이드/발제 | 사람 | -| 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` | 다음 세션 | +| 상태 핸드오프 | (전원) | `HANDOFF.md`, `TODO.md`, `SESSION-LOG.md` — **로컬 전용(.gitignore, 78a5a92)**. 커밋하지 않으며 새 clone에는 없다 | 다음 세션 | **사람 승인 게이트:** 공개(프리프린트/blog)는 **저자·소속·IP·corresponding email 확정** 전까지 보류(manuscript-writer의 ``). **커밋·push는 작업 완료 시 에이전트가 자동 수행**(2026-07-09 정책 변경 — 기존 '무인 git 금지' 철회, push까지 자동). 단 위 검증 게이트(커밋 전 재계산·FINDINGS 대조)는 유지하고, **프리프린트/blog 외부 공개와 main 병합만 사람 승인**(작업 브랜치 `kkkim-pipeline` push는 자동). 커밋 메시지는 P0~P5 접두 규칙 준수, Claude attribution 금지. diff --git a/docs/HARNESS-RECONCILIATION-2026-07-26.md b/docs/HARNESS-RECONCILIATION-2026-07-26.md index 9929bc8..ebb502b 100644 --- a/docs/HARNESS-RECONCILIATION-2026-07-26.md +++ b/docs/HARNESS-RECONCILIATION-2026-07-26.md @@ -181,3 +181,28 @@ kkkim 님이 예고한 BIOP02용 `harness.yaml`(project_profile: biop02, 슬롯= | `onboarding_gglee/` | 온보딩 1~3주차 회고 산출물 (BIOP01-1 · 15 · 8) | > 라이브 `README.md` · `CLAUDE.md` · `docs/HARNESS.md`에서 위 산출물로 가는 링크는 **아직 넣지 않았다** — 7/21 합의(구조 미수정)에 따라 스왑 승인 시 함께 반영한다. + +--- + +## 8. 정정 — M8(b) 핸드오프 파일은 팬텀이 아니다 (2026-07-26 밤, 스왑 중 발견) + +§6 M8(b)에서 나는 `HANDOFF.md`·`TODO.md`·`SESSION-LOG.md`가 *"같은 재구조화 커밋으로 사라졌는데 계약은 여전히 필수로 지시한다"* 고 적었다. **이 진단은 틀렸다.** + +- 실제: `.gitignore:115-117`이 세 파일을 명시적으로 제외한다. 도입 커밋은 `78a5a92`(2026-07-01) — *"chore: 개인 작업기록(HANDOFF/TODO/SESSION-LOG) untrack"*, 주석은 *"개인 작업기록(연구 산출물 아님, 편의상 로컬 유지)"*. +- BIOP02도 동일하다(`.gitignore:246-248`). +- 즉 **삭제된 게 아니라 의도적으로 리포에서 뺀 로컬 전용 파일**이다. 새 clone에 없는 것이 정상 동작이다. + +발견 경위: BIOP01-71로 세 파일을 만들어 커밋하려 하자 `git add`가 스테이징하지 않았다. `git check-ignore -v`로 확인. + +### 그래서 진짜 결함은 무엇인가 (범위 축소·성격 변경) + +1. **계약에 "로컬 전용"이 안 적혀 있다.** `CLAUDE.md:91`·`SKILL.md:75`가 이들을 "(전원) 필수 산출물"로만 지시해서, 리포를 처음 보는 세션은 존재해야 할 파일이 없다고 읽는다 — 내가 정확히 그렇게 읽었다. → 두 계약 행에 **로컬 전용(.gitignore) 표기 추가**로 해소. +2. **doctor가 오검을 냈다.** 팬텀 경로 검사가 이 셋을 FAIL로 올렸다. kkkim 님이 공동리뷰에서 경고한 오검 유형(맥락 없는 스캔)이 다른 형태로 재현된 것이다. → manifest에 `path_reference_scan.local_only` 선언을 두고, doctor는 **부재해도 FAIL하지 않되 `.gitignore` 등재 여부를 확인**한다(계약상 필수인데 ignore에서 빠지면 실수로 커밋되므로 그때는 FAIL). 테스트 2종 추가(#13·#14). + +### 교훈 (게이트 설계) + +"문서가 가리키는데 파일이 없다"는 **두 가지 다른 상태**를 가린다 — ① 진짜 drift(고쳐야 함) ② 의도적 로컬 전용(정상). 게이트가 이 둘을 구분하지 못하면, 팀은 게이트의 빨간불을 무시하는 법을 배운다. **의도는 manifest에 선언돼야 하고, 게이트는 선언되지 않은 것만 문제 삼아야 한다.** + +이 정정으로 팬텀 경로는 11건 → **8건**으로 줄었고, 남은 8건은 전부 `skills/` 라우터 결정(BIOP01-71)에 걸려 있다: `skills/ROUTES.md`, `openai.yaml`, `agents/openai.yaml`, `download/preprocessing/model/visualization`(README:12), 그리고 `AGENTS.md`의 규약 디렉터리 `data/`·`metadata/`·`work/`·`outputs/`. + +> §6 M8(b)와 그에 근거한 BIOP01-71 설명·Jira 코멘트는 이 절로 정정한다. 원문은 기록으로 남긴다. diff --git a/harness.yaml b/harness.yaml index cbf3867..5a0cb9c 100644 --- a/harness.yaml +++ b/harness.yaml @@ -90,6 +90,13 @@ path_reference_scan: - CLAUDE.md - docs/HARNESS.md - .claude/skills/paper-production-orchestrator/SKILL.md + # 로컬 전용(gitignore) — 리포에 커밋하지 않는 개인 작업기록. 78a5a92(2026-07-01) untrack. + # doctor는 이들의 부재를 FAIL 처리하지 않는다. 대신 .gitignore 등재 여부를 확인한다 + # (계약은 "필수 산출물"인데 ignore에서 빠지면 실수로 커밋된다). + local_only: + - HANDOFF.md + - TODO.md + - SESSION-LOG.md ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml index cbf3867..5a0cb9c 100644 --- a/harness_after/harness.yaml +++ b/harness_after/harness.yaml @@ -90,6 +90,13 @@ path_reference_scan: - CLAUDE.md - docs/HARNESS.md - .claude/skills/paper-production-orchestrator/SKILL.md + # 로컬 전용(gitignore) — 리포에 커밋하지 않는 개인 작업기록. 78a5a92(2026-07-01) untrack. + # doctor는 이들의 부재를 FAIL 처리하지 않는다. 대신 .gitignore 등재 여부를 확인한다 + # (계약은 "필수 산출물"인데 ignore에서 빠지면 실수로 커밋된다). + local_only: + - HANDOFF.md + - TODO.md + - SESSION-LOG.md ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" diff --git a/harness_after/scripts/harness_doctor.py b/harness_after/scripts/harness_doctor.py index 864b1f1..d180378 100644 --- a/harness_after/scripts/harness_doctor.py +++ b/harness_after/scripts/harness_doctor.py @@ -9,7 +9,8 @@ 2) artifacts 경로 존재 3) 문서가 참조하는 agent 이름이 미구현이면 FAIL ← reviewer 팬텀 - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 - 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md·HANDOFF.md 팬텀 + 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md 팬텀 + - local_only 로 선언된 경로는 부재해도 통과(개인 작업기록). 대신 .gitignore 등재를 확인 5) execution.require_repo_root: repo 루트에서 실행됐는지 사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml 종료코드: 0=PASS, 1=FAIL, 2=실행오류 @@ -121,7 +122,22 @@ def p(path): return os.path.join(repo, path) n_paths = 0 if prs.get("enabled"): ign = [re.compile(x) for x in (prs.get("ignore") or [])] + local_only = set(prs.get("local_only") or []) names, tops = repo_index(repo) + + # local_only: 리포에 커밋하지 않는 개인 작업기록. 부재는 정상이지만, + # .gitignore 에 없으면 계약("필수 산출물")과 어긋나 실수로 커밋된다 → 그건 FAIL. + for lo in sorted(local_only): + try: + rc = subprocess.run(["git", "-C", repo, "check-ignore", "-q", lo]).returncode + except Exception: + rc = 1 + if rc != 0: + fails.append("[local-only] %s는 로컬 전용으로 선언됐으나 .gitignore에 없음 " + "→ 실수로 커밋될 수 있음" % lo) + elif not os.path.exists(p(lo)): + warns.append("[local-only] %s 없음 — 개인 작업기록이라 정상이나, " + "계약상 세션 종료 시 갱신 대상" % lo) pat = re.compile(r"`([^`\n]+)`") hits = {} for f in (prs.get("files") or scan): @@ -143,6 +159,8 @@ def p(path): return os.path.join(repo, path) continue if any(rx.search(t) for rx in ign): continue + if t in local_only: + continue if os.path.exists(p(t)): continue base = os.path.basename(t.rstrip("/")) diff --git a/harness_after/tests/test_harness_doctor.py b/harness_after/tests/test_harness_doctor.py index 3b75b23..e1795a1 100644 --- a/harness_after/tests/test_harness_doctor.py +++ b/harness_after/tests/test_harness_doctor.py @@ -48,7 +48,7 @@ resolve_by_basename: true files: %(scan_files)s - ignore: +%(local_only)s ignore: - "^https?://" - "^upstream/" """ @@ -73,10 +73,14 @@ def setUp(self): def tearDown(self): shutil.rmtree(self.repo, ignore_errors=True) - def manifest(self, scan_files=("CLAUDE.md",), path_scan="true"): + def manifest(self, scan_files=("CLAUDE.md",), path_scan="true", local_only=()): + lo = "" + if local_only: + lo = " local_only:\n" + "".join(" - %s\n" % f for f in local_only) body = BASE_MANIFEST % { "scan_files": "".join(" - %s\n" % f for f in scan_files), "path_scan": path_scan, + "local_only": lo, } write(os.path.join(self.repo, "harness.yaml"), body) @@ -198,6 +202,30 @@ def test_path_scan_toggle(self): self.assertEqual(code, 0, out) self.assertNotIn("[phantom-path]", out) + # ---- 13. local_only: gitignore 돼 있으면 부재해도 통과 ---- + # 개인 작업기록(HANDOFF/TODO/SESSION-LOG)은 78a5a92(2026-07-01)에서 의도적으로 untrack. + # 계약이 이들을 "필수 산출물"로 지시하지만 리포에는 없는 게 정상이다. + def test_local_only_absent_but_gitignored_passes(self): + subprocess.run(["git", "init", "-q", self.repo], check=True) + write(os.path.join(self.repo, ".gitignore"), "HANDOFF.md\n") + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n세션 종료 시 `HANDOFF.md` 를 갱신한다(로컬 전용).\n") + self.manifest(local_only=("HANDOFF.md",)) + code, out = self.run_doctor() + self.assertEqual(code, 0, "gitignore된 로컬 전용 파일을 팬텀으로 오검\n" + out) + self.assertIn("[local-only]", out) + + # ---- 14. local_only인데 .gitignore에 없으면 FAIL (실수로 커밋될 위험) ---- + def test_local_only_not_gitignored_fails(self): + subprocess.run(["git", "init", "-q", self.repo], check=True) + write(os.path.join(self.repo, ".gitignore"), "nothing\n") + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n세션 종료 시 `HANDOFF.md` 를 갱신한다.\n") + self.manifest(local_only=("HANDOFF.md",)) + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("[local-only]", out) + class LiveRepoCase(unittest.TestCase): """실제 BIOP01 리포에 대한 회귀 확인 — 알려진 결함이 계속 잡히는가.""" @@ -218,7 +246,7 @@ def test_known_defects_detected(self): if "CLAUDE.md" not in out and r.returncode == 2: self.skipTest("BIOP01 리포 컨텍스트 아님") # 2026-07-26 2차 조사에서 확인된 결함들이 계속 잡혀야 한다 - for expected in ("[phantom-agent]", "skills/ROUTES.md", "HANDOFF.md"): + for expected in ("skills/ROUTES.md",): self.assertIn(expected, out, "알려진 결함 미검출: %s\n%s" % (expected, out)) finally: if tmp_placed: diff --git a/scripts/harness_doctor.py b/scripts/harness_doctor.py index 864b1f1..d180378 100644 --- a/scripts/harness_doctor.py +++ b/scripts/harness_doctor.py @@ -9,7 +9,8 @@ 2) artifacts 경로 존재 3) 문서가 참조하는 agent 이름이 미구현이면 FAIL ← reviewer 팬텀 - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 - 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md·HANDOFF.md 팬텀 + 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md 팬텀 + - local_only 로 선언된 경로는 부재해도 통과(개인 작업기록). 대신 .gitignore 등재를 확인 5) execution.require_repo_root: repo 루트에서 실행됐는지 사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml 종료코드: 0=PASS, 1=FAIL, 2=실행오류 @@ -121,7 +122,22 @@ def p(path): return os.path.join(repo, path) n_paths = 0 if prs.get("enabled"): ign = [re.compile(x) for x in (prs.get("ignore") or [])] + local_only = set(prs.get("local_only") or []) names, tops = repo_index(repo) + + # local_only: 리포에 커밋하지 않는 개인 작업기록. 부재는 정상이지만, + # .gitignore 에 없으면 계약("필수 산출물")과 어긋나 실수로 커밋된다 → 그건 FAIL. + for lo in sorted(local_only): + try: + rc = subprocess.run(["git", "-C", repo, "check-ignore", "-q", lo]).returncode + except Exception: + rc = 1 + if rc != 0: + fails.append("[local-only] %s는 로컬 전용으로 선언됐으나 .gitignore에 없음 " + "→ 실수로 커밋될 수 있음" % lo) + elif not os.path.exists(p(lo)): + warns.append("[local-only] %s 없음 — 개인 작업기록이라 정상이나, " + "계약상 세션 종료 시 갱신 대상" % lo) pat = re.compile(r"`([^`\n]+)`") hits = {} for f in (prs.get("files") or scan): @@ -143,6 +159,8 @@ def p(path): return os.path.join(repo, path) continue if any(rx.search(t) for rx in ign): continue + if t in local_only: + continue if os.path.exists(p(t)): continue base = os.path.basename(t.rstrip("/")) From 65115c94aefeed8bb8f6b6c41f508dfc018720dd Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 19:38:29 +0900 Subject: [PATCH 8/9] =?UTF-8?q?harness:=20skills/=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=84=B0=20=EB=B3=B5=EC=9B=90(41=ED=8C=8C=EC=9D=BC)=20+=20?= =?UTF-8?q?=EA=B7=9C=EC=95=BD=EA=B2=BD=EB=A1=9C=20=EC=84=A0=EC=96=B8=20+?= =?UTF-8?q?=20=EA=B2=8C=EC=9D=B4=ED=8A=B8=202=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EC=8A=B9=EA=B2=A9=20(BIOP01-66/71/73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit skills/ 유실 경위가 앞선 보고와 다르다. 재조사 결과: - bc7f824(6/14)는 skills/ 를 삭제한 게 아니라 추가한 커밋이다 (import 박상준 Harness_Baseline, 4 datasets x download/preprocess/model/viz). 이때 지운 것은 옛 논문분석 스킬 33개이고 kkkim-paper-agent 브랜치에 보존돼 있다. - 이후 7f38b23(7/15 braveji env 정정) 등으로 계속 관리됐고 그 시점 41파일이었다. - 275def2(7/20, Merge origin/main into kkkim-pipeline PR #4 충돌 해소)에서 41파일 전부가 D 로 사라졌다. main 에는 이 skills/ 가 없었으므로 충돌 해소가 main 쪽을 택하면서 통째로 날아간 것이다. 삭제 범위는 skills/ 안으로 한정(부수 피해 없음). 즉 문서가 낡은 게 아니라 파일이 유실됐다. AGENTS.md 라우팅은 지금도 옳은 말을 한다. 변경: - skills/ 복원 — git checkout 7039bc4 -- skills/ (41파일, 유실 직전 상태 그대로) - harness.yaml: path_reference_scan.conventions 선언. AGENTS.md Repository Conventions 의 data/ metadata/ work/ outputs/ 는 산출물을 둘 위치 안내이지 사전 존재를 요구하는 경로가 아니다. 부재해도 FAIL 아님 - 테스트 +2 (규약경로 통과 / 미선언 경로는 여전히 FAIL) -> 17/17 통과 - live 회귀 테스트 방향 전환: 알려진 결함이 잡히는가 -> 깨끗한 상태를 지키는가 - 2단계 승격: CI continue-on-error 제거, 래퍼 HARNESS_DOCTOR_ENFORCE 기본값 1 doctor: 8 -> 0. RESULT: PASS. 주의: skills/ 복원 여부는 07-27 미팅 결정 사항(BIOP01-71). 이 커밋은 PR #5 안에 있고 머지 전이므로 결정에 따라 되돌릴 수 있다. B(문서 정정)로 확정되면 skills/ 를 다시 빼고 AGENTS.md README CLAUDE.md 참조를 정정해야 doctor 가 0 을 유지한다. --- .github/workflows/harness-doctor.yml | 10 +- harness.yaml | 7 + harness_after/ci/harness-doctor.yml | 10 +- harness_after/harness.yaml | 7 + harness_after/scripts/harness_doctor.py | 5 + harness_after/scripts/start-paper-harness | 14 +- harness_after/tests/test_harness_doctor.py | 41 ++- scripts/harness_doctor.py | 5 + scripts/start-paper-harness | 14 +- .../download/SKILL.md | 51 +++ .../download/agents/openai.yaml | 4 + .../10x-embryonic-mouse-brain/model/SKILL.md | 42 +++ .../model/agents/openai.yaml | 4 + .../preprocessing/SKILL.md | 51 +++ .../preprocessing/agents/openai.yaml | 4 + .../visualization/SKILL.md | 36 ++ .../visualization/agents/openai.yaml | 4 + skills/OPENCLAW-RUN.md | 36 ++ skills/ROUTES.md | 69 ++++ skills/external/README.md | 10 + skills/external/atac-seq/LICENSE | 21 ++ skills/external/atac-seq/SOURCE.md | 14 + skills/external/atac-seq/atac-qc/SKILL.md | 337 ++++++++++++++++++ .../atac-seq/enhancer-gene-linking/SKILL.md | 296 +++++++++++++++ skills/external/scvi-tools/SOURCE.md | 8 + skills/external/scvi-tools/USING_IN_BIOP01.md | 20 ++ skills/human-brain-multiome/download/SKILL.md | 52 +++ .../download/agents/openai.yaml | 4 + skills/human-brain-multiome/model/SKILL.md | 41 +++ .../model/agents/openai.yaml | 4 + .../preprocessing/SKILL.md | 51 +++ .../preprocessing/agents/openai.yaml | 4 + .../visualization/SKILL.md | 36 ++ .../visualization/agents/openai.yaml | 4 + .../human-hspc-10x-multiome/download/SKILL.md | 57 +++ .../download/agents/openai.yaml | 4 + skills/human-hspc-10x-multiome/model/SKILL.md | 46 +++ .../model/agents/openai.yaml | 4 + .../preprocessing/SKILL.md | 56 +++ .../preprocessing/agents/openai.yaml | 4 + .../visualization/SKILL.md | 39 ++ .../visualization/agents/openai.yaml | 4 + skills/share-seq-mouse-skin/download/SKILL.md | 52 +++ .../download/agents/openai.yaml | 4 + skills/share-seq-mouse-skin/model/SKILL.md | 41 +++ .../model/agents/openai.yaml | 4 + .../preprocessing/SKILL.md | 51 +++ .../preprocessing/agents/openai.yaml | 4 + .../visualization/SKILL.md | 36 ++ .../visualization/agents/openai.yaml | 4 + 50 files changed, 1693 insertions(+), 33 deletions(-) create mode 100644 skills/10x-embryonic-mouse-brain/download/SKILL.md create mode 100644 skills/10x-embryonic-mouse-brain/download/agents/openai.yaml create mode 100644 skills/10x-embryonic-mouse-brain/model/SKILL.md create mode 100644 skills/10x-embryonic-mouse-brain/model/agents/openai.yaml create mode 100644 skills/10x-embryonic-mouse-brain/preprocessing/SKILL.md create mode 100644 skills/10x-embryonic-mouse-brain/preprocessing/agents/openai.yaml create mode 100644 skills/10x-embryonic-mouse-brain/visualization/SKILL.md create mode 100644 skills/10x-embryonic-mouse-brain/visualization/agents/openai.yaml create mode 100644 skills/OPENCLAW-RUN.md create mode 100644 skills/ROUTES.md create mode 100644 skills/external/README.md create mode 100644 skills/external/atac-seq/LICENSE create mode 100644 skills/external/atac-seq/SOURCE.md create mode 100644 skills/external/atac-seq/atac-qc/SKILL.md create mode 100644 skills/external/atac-seq/enhancer-gene-linking/SKILL.md create mode 100644 skills/external/scvi-tools/SOURCE.md create mode 100644 skills/external/scvi-tools/USING_IN_BIOP01.md create mode 100644 skills/human-brain-multiome/download/SKILL.md create mode 100644 skills/human-brain-multiome/download/agents/openai.yaml create mode 100644 skills/human-brain-multiome/model/SKILL.md create mode 100644 skills/human-brain-multiome/model/agents/openai.yaml create mode 100644 skills/human-brain-multiome/preprocessing/SKILL.md create mode 100644 skills/human-brain-multiome/preprocessing/agents/openai.yaml create mode 100644 skills/human-brain-multiome/visualization/SKILL.md create mode 100644 skills/human-brain-multiome/visualization/agents/openai.yaml create mode 100644 skills/human-hspc-10x-multiome/download/SKILL.md create mode 100644 skills/human-hspc-10x-multiome/download/agents/openai.yaml create mode 100644 skills/human-hspc-10x-multiome/model/SKILL.md create mode 100644 skills/human-hspc-10x-multiome/model/agents/openai.yaml create mode 100644 skills/human-hspc-10x-multiome/preprocessing/SKILL.md create mode 100644 skills/human-hspc-10x-multiome/preprocessing/agents/openai.yaml create mode 100644 skills/human-hspc-10x-multiome/visualization/SKILL.md create mode 100644 skills/human-hspc-10x-multiome/visualization/agents/openai.yaml create mode 100644 skills/share-seq-mouse-skin/download/SKILL.md create mode 100644 skills/share-seq-mouse-skin/download/agents/openai.yaml create mode 100644 skills/share-seq-mouse-skin/model/SKILL.md create mode 100644 skills/share-seq-mouse-skin/model/agents/openai.yaml create mode 100644 skills/share-seq-mouse-skin/preprocessing/SKILL.md create mode 100644 skills/share-seq-mouse-skin/preprocessing/agents/openai.yaml create mode 100644 skills/share-seq-mouse-skin/visualization/SKILL.md create mode 100644 skills/share-seq-mouse-skin/visualization/agents/openai.yaml diff --git a/.github/workflows/harness-doctor.yml b/.github/workflows/harness-doctor.yml index a166bab..cddb129 100644 --- a/.github/workflows/harness-doctor.yml +++ b/.github/workflows/harness-doctor.yml @@ -1,10 +1,9 @@ # 하네스 구성 정합성 게이트 (BIOP01-66). # -# 2단계 도입: -# 1단계(현재) — doctor는 report-only(continue-on-error). 게이트 자체 테스트는 blocking. -# 이유: 스왑 시점에 팬텀 14건이 남아 있어 바로 blocking으로 켜면 모든 PR이 빨간불이 된다. -# BIOP01-64/71/72가 닫혀 doctor가 green이 되면 2단계로 전환. -# 2단계 — `continue-on-error: true` 를 제거해 blocking 게이트로 승격. +# 2단계 승격 완료 (2026-07-26). +# 1단계 — doctor는 report-only 였다. 팬텀 14건이 남아 전면 blocking이면 모든 PR이 빨간불이었다. +# 2단계(현재) — BIOP01-64(팬텀 에이전트 0) + BIOP01-71(skills/ 복원)로 팬텀 0 달성 → +# 구성 검사도 blocking. 문서가 실재하지 않는 역할·경로를 가리키면 PR이 막힌다. name: harness-doctor on: pull_request: @@ -28,5 +27,4 @@ jobs: # 하네스 구성 검사 — 1단계에서는 report-only. - name: 하네스 구성 정합성 검사 (팬텀 역할·경로 drift) - continue-on-error: true # ← BIOP01-64/71/72 종료 후 이 줄 삭제 = blocking 승격 run: python scripts/harness_doctor.py --repo . --manifest harness.yaml diff --git a/harness.yaml b/harness.yaml index 5a0cb9c..bd5b3f1 100644 --- a/harness.yaml +++ b/harness.yaml @@ -97,6 +97,13 @@ path_reference_scan: - HANDOFF.md - TODO.md - SESSION-LOG.md + # 규약 경로 — "산출물을 여기에 두라"는 안내이지 사전에 존재해야 하는 경로가 아니다. + # (AGENTS.md 'Repository Conventions'). 부재해도 FAIL 아님. 필요 시 생성된다. + conventions: + - data/ + - metadata/ + - work/ + - outputs/ ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" diff --git a/harness_after/ci/harness-doctor.yml b/harness_after/ci/harness-doctor.yml index a166bab..cddb129 100644 --- a/harness_after/ci/harness-doctor.yml +++ b/harness_after/ci/harness-doctor.yml @@ -1,10 +1,9 @@ # 하네스 구성 정합성 게이트 (BIOP01-66). # -# 2단계 도입: -# 1단계(현재) — doctor는 report-only(continue-on-error). 게이트 자체 테스트는 blocking. -# 이유: 스왑 시점에 팬텀 14건이 남아 있어 바로 blocking으로 켜면 모든 PR이 빨간불이 된다. -# BIOP01-64/71/72가 닫혀 doctor가 green이 되면 2단계로 전환. -# 2단계 — `continue-on-error: true` 를 제거해 blocking 게이트로 승격. +# 2단계 승격 완료 (2026-07-26). +# 1단계 — doctor는 report-only 였다. 팬텀 14건이 남아 전면 blocking이면 모든 PR이 빨간불이었다. +# 2단계(현재) — BIOP01-64(팬텀 에이전트 0) + BIOP01-71(skills/ 복원)로 팬텀 0 달성 → +# 구성 검사도 blocking. 문서가 실재하지 않는 역할·경로를 가리키면 PR이 막힌다. name: harness-doctor on: pull_request: @@ -28,5 +27,4 @@ jobs: # 하네스 구성 검사 — 1단계에서는 report-only. - name: 하네스 구성 정합성 검사 (팬텀 역할·경로 drift) - continue-on-error: true # ← BIOP01-64/71/72 종료 후 이 줄 삭제 = blocking 승격 run: python scripts/harness_doctor.py --repo . --manifest harness.yaml diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml index 5a0cb9c..bd5b3f1 100644 --- a/harness_after/harness.yaml +++ b/harness_after/harness.yaml @@ -97,6 +97,13 @@ path_reference_scan: - HANDOFF.md - TODO.md - SESSION-LOG.md + # 규약 경로 — "산출물을 여기에 두라"는 안내이지 사전에 존재해야 하는 경로가 아니다. + # (AGENTS.md 'Repository Conventions'). 부재해도 FAIL 아님. 필요 시 생성된다. + conventions: + - data/ + - metadata/ + - work/ + - outputs/ ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" diff --git a/harness_after/scripts/harness_doctor.py b/harness_after/scripts/harness_doctor.py index d180378..787e6f6 100644 --- a/harness_after/scripts/harness_doctor.py +++ b/harness_after/scripts/harness_doctor.py @@ -11,6 +11,7 @@ - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md 팬텀 - local_only 로 선언된 경로는 부재해도 통과(개인 작업기록). 대신 .gitignore 등재를 확인 + - conventions 로 선언된 경로는 부재해도 통과(산출물을 둘 위치 안내) 5) execution.require_repo_root: repo 루트에서 실행됐는지 사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml 종료코드: 0=PASS, 1=FAIL, 2=실행오류 @@ -123,6 +124,7 @@ def p(path): return os.path.join(repo, path) if prs.get("enabled"): ign = [re.compile(x) for x in (prs.get("ignore") or [])] local_only = set(prs.get("local_only") or []) + conventions = set(x.rstrip("/") for x in (prs.get("conventions") or [])) names, tops = repo_index(repo) # local_only: 리포에 커밋하지 않는 개인 작업기록. 부재는 정상이지만, @@ -161,6 +163,9 @@ def p(path): return os.path.join(repo, path) continue if t in local_only: continue + if t.rstrip("/") in conventions: + # 규약 경로: "여기에 두라"는 안내. 사전 존재를 요구하지 않는다. + continue if os.path.exists(p(t)): continue base = os.path.basename(t.rstrip("/")) diff --git a/harness_after/scripts/start-paper-harness b/harness_after/scripts/start-paper-harness index 03b88e4..773f33c 100755 --- a/harness_after/scripts/start-paper-harness +++ b/harness_after/scripts/start-paper-harness @@ -6,11 +6,11 @@ # # 두 종류의 실패를 구분한다: # (a) 구성요소 부재 — 항상 하드 실패. 이게 침묵 폴백의 입구다. -# (b) 문서 drift(팬텀 참조) — 1단계에서는 경고. BIOP01-64/71/72가 닫히면 -# HARNESS_DOCTOR_ENFORCE=1 을 기본값으로 올려 하드 실패로 승격한다. +# (b) 문서 drift(팬텀 참조) — 2026-07-26 팬텀 0 달성으로 **하드 실패가 기본값**. +# 예외적으로 넘기려면 HARNESS_DOCTOR_ENFORCE=0 (비권장, 사유를 기록할 것). # -# 사용: ./scripts/start-paper-harness # 1단계(기본): drift는 경고 -# HARNESS_DOCTOR_ENFORCE=1 ./scripts/start-paper-harness # 2단계: drift도 중단 +# 사용: ./scripts/start-paper-harness # 기본: drift도 중단 +# HARNESS_DOCTOR_ENFORCE=0 ./scripts/start-paper-harness # 예외적 우회(비권장) set -euo pipefail ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" @@ -40,10 +40,10 @@ if [ -f scripts/harness_doctor.py ] && [ -f harness.yaml ]; then if "$PY" scripts/harness_doctor.py --repo . --manifest harness.yaml; then : else - if [ "${HARNESS_DOCTOR_ENFORCE:-0}" = "1" ]; then - echo "FATAL: harness_doctor FAIL → 하네스 진입 중단 (enforce 모드)."; exit 1 + if [ "${HARNESS_DOCTOR_ENFORCE:-1}" = "1" ]; then + echo "FATAL: harness_doctor FAIL → 하네스 진입 중단. 구성 drift를 고치고 다시 실행하라."; exit 1 fi - echo "WARN: harness_doctor FAIL — 1단계라 진입은 허용한다. BIOP01-64/71/72 종료 후 enforce 로 승격할 것." + echo "WARN: harness_doctor FAIL — HARNESS_DOCTOR_ENFORCE=0 으로 우회됨. 사유를 기록할 것." fi fi diff --git a/harness_after/tests/test_harness_doctor.py b/harness_after/tests/test_harness_doctor.py index e1795a1..5646c53 100644 --- a/harness_after/tests/test_harness_doctor.py +++ b/harness_after/tests/test_harness_doctor.py @@ -73,10 +73,12 @@ def setUp(self): def tearDown(self): shutil.rmtree(self.repo, ignore_errors=True) - def manifest(self, scan_files=("CLAUDE.md",), path_scan="true", local_only=()): + def manifest(self, scan_files=("CLAUDE.md",), path_scan="true", local_only=(), conventions=()): lo = "" if local_only: lo = " local_only:\n" + "".join(" - %s\n" % f for f in local_only) + if conventions: + lo += " conventions:\n" + "".join(" - %s\n" % f for f in conventions) body = BASE_MANIFEST % { "scan_files": "".join(" - %s\n" % f for f in scan_files), "path_scan": path_scan, @@ -226,13 +228,38 @@ def test_local_only_not_gitignored_fails(self): self.assertEqual(code, 1, out) self.assertIn("[local-only]", out) + # ---- 15. conventions: 규약 경로는 부재해도 통과 ---- + # "산출물을 여기에 두라"는 안내(AGENTS.md Repository Conventions)이지 + # 사전에 존재해야 하는 경로가 아니다. + def test_convention_path_absent_passes(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n중간 산출물은 `work/` 에 둔다.\n") + self.manifest(conventions=("work/",)) + code, out = self.run_doctor() + self.assertEqual(code, 0, "규약 경로를 팬텀으로 오검\n" + out) + self.assertNotIn("phantom-path", out) + + # ---- 16. 선언되지 않은 경로는 여전히 FAIL (conventions 가 만능 면죄부가 아님) ---- + def test_undeclared_path_still_fails(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n중간 산출물은 `work/` 에 두고 라우팅은 `skills/ROUTES.md` 를 본다.\n") + self.manifest(conventions=("work/",)) + code, out = self.run_doctor() + self.assertEqual(code, 1, out) + self.assertIn("skills/ROUTES.md", out) + class LiveRepoCase(unittest.TestCase): - """실제 BIOP01 리포에 대한 회귀 확인 — 알려진 결함이 계속 잡히는가.""" + """실제 BIOP01 리포 회귀 — 한번 0으로 만든 팬텀이 다시 생기지 않는가. + + 2026-07-26 이전 버전은 "알려진 결함(skills/ROUTES.md 등)이 검출되는가"를 확인했다. + 그 결함들이 해소돼(BIOP01-64/71) 이제는 **깨끗한 상태를 지키는** 방향으로 뒤집는다. + 누군가 문서에 팬텀 역할·경로를 다시 넣으면 여기서 실패한다. + """ REPO = os.path.abspath(os.path.join(HERE, "..", "..")) - def test_known_defects_detected(self): + def test_repo_stays_clean(self): manifest = os.path.join(self.REPO, "harness.yaml") tmp_placed = False if not os.path.exists(manifest): @@ -243,11 +270,11 @@ def test_known_defects_detected(self): [sys.executable, DOCTOR, "--repo", self.REPO, "--manifest", "harness.yaml"], capture_output=True, text=True) out = r.stdout + r.stderr - if "CLAUDE.md" not in out and r.returncode == 2: + if r.returncode == 2: self.skipTest("BIOP01 리포 컨텍스트 아님") - # 2026-07-26 2차 조사에서 확인된 결함들이 계속 잡혀야 한다 - for expected in ("skills/ROUTES.md",): - self.assertIn(expected, out, "알려진 결함 미검출: %s\n%s" % (expected, out)) + self.assertEqual(r.returncode, 0, + "리포에 팬텀이 다시 생겼다 (역할 또는 경로):\n" + out) + self.assertIn("phantom_paths=0", out, out) finally: if tmp_placed: os.remove(manifest) diff --git a/scripts/harness_doctor.py b/scripts/harness_doctor.py index d180378..787e6f6 100644 --- a/scripts/harness_doctor.py +++ b/scripts/harness_doctor.py @@ -11,6 +11,7 @@ - 강한 참조(백틱 인용 / 표 행)만 FAIL, 산문 언급은 WARN ← kkkim 공동리뷰 2026-07-26 반영 4) 문서가 백틱으로 인용한 **경로**가 실재하는지 ← skills/ROUTES.md 팬텀 - local_only 로 선언된 경로는 부재해도 통과(개인 작업기록). 대신 .gitignore 등재를 확인 + - conventions 로 선언된 경로는 부재해도 통과(산출물을 둘 위치 안내) 5) execution.require_repo_root: repo 루트에서 실행됐는지 사용: python scripts/harness_doctor.py --repo . --manifest harness.yaml 종료코드: 0=PASS, 1=FAIL, 2=실행오류 @@ -123,6 +124,7 @@ def p(path): return os.path.join(repo, path) if prs.get("enabled"): ign = [re.compile(x) for x in (prs.get("ignore") or [])] local_only = set(prs.get("local_only") or []) + conventions = set(x.rstrip("/") for x in (prs.get("conventions") or [])) names, tops = repo_index(repo) # local_only: 리포에 커밋하지 않는 개인 작업기록. 부재는 정상이지만, @@ -161,6 +163,9 @@ def p(path): return os.path.join(repo, path) continue if t in local_only: continue + if t.rstrip("/") in conventions: + # 규약 경로: "여기에 두라"는 안내. 사전 존재를 요구하지 않는다. + continue if os.path.exists(p(t)): continue base = os.path.basename(t.rstrip("/")) diff --git a/scripts/start-paper-harness b/scripts/start-paper-harness index 03b88e4..773f33c 100755 --- a/scripts/start-paper-harness +++ b/scripts/start-paper-harness @@ -6,11 +6,11 @@ # # 두 종류의 실패를 구분한다: # (a) 구성요소 부재 — 항상 하드 실패. 이게 침묵 폴백의 입구다. -# (b) 문서 drift(팬텀 참조) — 1단계에서는 경고. BIOP01-64/71/72가 닫히면 -# HARNESS_DOCTOR_ENFORCE=1 을 기본값으로 올려 하드 실패로 승격한다. +# (b) 문서 drift(팬텀 참조) — 2026-07-26 팬텀 0 달성으로 **하드 실패가 기본값**. +# 예외적으로 넘기려면 HARNESS_DOCTOR_ENFORCE=0 (비권장, 사유를 기록할 것). # -# 사용: ./scripts/start-paper-harness # 1단계(기본): drift는 경고 -# HARNESS_DOCTOR_ENFORCE=1 ./scripts/start-paper-harness # 2단계: drift도 중단 +# 사용: ./scripts/start-paper-harness # 기본: drift도 중단 +# HARNESS_DOCTOR_ENFORCE=0 ./scripts/start-paper-harness # 예외적 우회(비권장) set -euo pipefail ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)" @@ -40,10 +40,10 @@ if [ -f scripts/harness_doctor.py ] && [ -f harness.yaml ]; then if "$PY" scripts/harness_doctor.py --repo . --manifest harness.yaml; then : else - if [ "${HARNESS_DOCTOR_ENFORCE:-0}" = "1" ]; then - echo "FATAL: harness_doctor FAIL → 하네스 진입 중단 (enforce 모드)."; exit 1 + if [ "${HARNESS_DOCTOR_ENFORCE:-1}" = "1" ]; then + echo "FATAL: harness_doctor FAIL → 하네스 진입 중단. 구성 drift를 고치고 다시 실행하라."; exit 1 fi - echo "WARN: harness_doctor FAIL — 1단계라 진입은 허용한다. BIOP01-64/71/72 종료 후 enforce 로 승격할 것." + echo "WARN: harness_doctor FAIL — HARNESS_DOCTOR_ENFORCE=0 으로 우회됨. 사유를 기록할 것." fi fi diff --git a/skills/10x-embryonic-mouse-brain/download/SKILL.md b/skills/10x-embryonic-mouse-brain/download/SKILL.md new file mode 100644 index 0000000..0bb637c --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/download/SKILL.md @@ -0,0 +1,51 @@ +--- +name: 10x-embryonic-mouse-brain-download +description: Download or register the 10x embryonic mouse brain multiome dataset for gene-specific epigenomic lag analysis. Use when Codex needs to find official data sources, fetch raw or processed files, verify files, or create a download manifest before preprocessing. +--- + +# 10x Embryonic Mouse Brain Download + +## Dataset +- Name: 10x embryonic mouse brain +- Biology: embryonic mouse brain differentiation +- Data type: 10x Multiome ATAC + Gene Expression +- Main use: baseline multi-omic dataset for chromatin/RNA timing and gene-specific lag structure. + +## 목표 +10x embryonic mouse brain multiome 데이터를 공식 출처에서 확인하고, raw/processed 파일을 `data/10x-embryonic-mouse-brain/` 아래에 재현 가능하게 받거나 기존 로컬 파일을 manifest로 등록한다. + +## 우선 확인 항목 +- 공식 10x Genomics dataset page 또는 원 논문/portal URL. +- 사용 조건, 라이선스, citation, download date. +- genome build와 gene annotation version. +- sample/library 이름, chemistry, reference package. +- RNA feature-barcode matrix, ATAC fragments, ATAC peak matrix, peak annotation, cell metadata. +- raw FASTQ가 필요한지, processed matrix/object로 충분한지. + +## 작업 절차 +1. 공식 출처를 먼저 확인한다. URL, access date, citation을 기록하고, 외부 mirror만 단독 출처로 사용하지 않는다. +2. 받을 파일 목록을 raw와 processed로 나누고, lag analysis에 필요한 최소 파일 세트를 표시한다. +3. `data/10x-embryonic-mouse-brain/raw/`, `data/10x-embryonic-mouse-brain/processed/`, `metadata/10x-embryonic-mouse-brain/` 경로를 사용한다. +4. 대용량 파일은 원본 파일명을 유지하고 덮어쓰지 않는다. 재다운로드가 필요하면 새 하위 폴더나 manifest version을 만든다. +5. 가능한 경우 provider checksum을 확인한다. 없으면 local `sha256sum` 또는 `shasum -a 256` 결과를 manifest에 남긴다. +6. 다운로드 후 파일 크기, 압축 무결성, matrix shape 또는 일부 record를 확인한다. +7. `metadata/10x-embryonic-mouse-brain/download_manifest.tsv` 또는 `.md`에 source, URL, file path, size, checksum, date, genome build, annotation source를 기록한다. + +## 출력 형식 +```markdown +## Download Plan +- Dataset: +- Official source: +- Access date: +- Files to download: +- Local paths: +- Genome build / annotation: +- Checksums: +- Verification: +- Preprocessing handoff: +- Open issues: +``` + +## 주의할 점 +- 시간축은 다운로드 단계에서 확정하지 말고, available metadata와 후보 developmental stage/pseudotime 정보만 기록한다. +- 10x reference package와 downstream gene annotation이 다를 수 있으므로 preprocessing에서 다시 확인한다. diff --git a/skills/10x-embryonic-mouse-brain/download/agents/openai.yaml b/skills/10x-embryonic-mouse-brain/download/agents/openai.yaml new file mode 100644 index 0000000..b67605d --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/download/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "10x Mouse Brain Download" + short_description: "10x embryonic mouse brain multiome 데이터 다운로드와 manifest 작성을 준비합니다." + default_prompt: "10x embryonic mouse brain multiome 데이터 다운로드 plan을 한국어로 작성해줘. 공식 출처 확인, raw/processed 파일, checksum, genome build, local path, preprocessing handoff를 포함해줘." diff --git a/skills/10x-embryonic-mouse-brain/model/SKILL.md b/skills/10x-embryonic-mouse-brain/model/SKILL.md new file mode 100644 index 0000000..e44b86d --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/model/SKILL.md @@ -0,0 +1,42 @@ +--- +name: 10x-embryonic-mouse-brain-model +description: Model gene-specific activation lag and shutdown lag in the 10x embryonic mouse brain multiome dataset. Use when Codex needs to estimate timing, fit MultiVelo-like dynamics, construct lag labels, or evaluate baseline feature predictors for this dataset. +--- + +# 10x Embryonic Mouse Brain Model + +## 목표 +10x embryonic mouse brain dataset에서 gene-specific `activation lag`과 `shutdown lag`을 추정하고, baseline epigenomic features가 lag structure를 설명하는지 모델링한다. + +## 입력 +- 전처리된 RNA/ATAC multiome object. +- gene-level 또는 peak-level accessibility features. +- pseudotime, lineage, developmental stage, cell state annotation. +- chromatin opening/closing time, transcription onset/shutdown time 또는 이를 추정할 수 있는 동역학 model output. + +## 작업 절차 +1. preprocessing output의 genome build, annotation, time axis를 확인한다. +2. gene별 chromatin/RNA timing 값을 추정하거나 기존 결과를 로드한다. +3. `activation lag = transcription onset time - chromatin opening time`을 계산한다. +4. `shutdown lag = chromatin closing time - transcription shutdown time`을 계산한다. +5. confidence, uncertainty, missingness를 gene별로 함께 저장한다. +6. promoter/enhancer accessibility, motif score, peak-to-gene linkage 같은 baseline feature로 lag을 예측한다. +7. 성능은 ranking, calibration, lineage-held-out generalization, early-vs-late separation 위주로 평가한다. + +## 출력 형식 +```markdown +## Model Plan +- Dataset: +- Time axis: +- Lag definition: +- Features: +- Model: +- Evaluation: +- Outputs: +- Limitations: +``` + +## 주의할 점 +- Model 1/Model 2 이분법으로 끝내지 말고 continuous lag spectrum으로 해석한다. +- lineage-specific timing 차이가 있으면 global model과 lineage-specific model을 구분한다. + diff --git a/skills/10x-embryonic-mouse-brain/model/agents/openai.yaml b/skills/10x-embryonic-mouse-brain/model/agents/openai.yaml new file mode 100644 index 0000000..6463ed3 --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/model/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "10x Mouse Brain Model" + short_description: "10x embryonic mouse brain lag 모델을 설계합니다." + default_prompt: "10x embryonic mouse brain dataset에서 activation lag과 shutdown lag을 추정하고 예측하는 model plan을 한국어로 작성해줘." diff --git a/skills/10x-embryonic-mouse-brain/preprocessing/SKILL.md b/skills/10x-embryonic-mouse-brain/preprocessing/SKILL.md new file mode 100644 index 0000000..a84bc6d --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/preprocessing/SKILL.md @@ -0,0 +1,51 @@ +--- +name: 10x-embryonic-mouse-brain-preprocessing +description: Preprocess the 10x embryonic mouse brain multiome dataset for gene-specific epigenomic lag analysis. Use when Codex needs to inspect, normalize, annotate, integrate, or prepare ATAC/RNA inputs from embryonic mouse brain differentiation before modeling. +--- + +# 10x Embryonic Mouse Brain Preprocessing + +## Dataset +- Name: 10x embryonic mouse brain +- Biology: embryonic brain differentiation +- Data type: 10x multiome +- Main use: baseline multi-omic dataset for estimating chromatin/RNA timing and gene-specific lag structure. + +## 목표 +10x embryonic mouse brain multiome 데이터를 lag modeling에 들어갈 수 있는 형태로 정리한다. RNA counts, ATAC peak/accessibility matrix, gene annotation, cell metadata, trajectory 또는 lineage annotation을 함께 점검하고, gene-level activation/shutdown lag 계산에 필요한 입력 테이블을 만든다. + +## 우선 확인 항목 +- 원본 데이터 위치와 다운로드 source. +- genome build와 gene annotation source. +- RNA matrix, ATAC fragments 또는 peak matrix, peak annotation 존재 여부. +- cell barcode matching, modality pairing, sample/library metadata. +- cell type, developmental stage, lineage, pseudotime annotation. +- raw data와 intermediate output을 분리하는 경로. + +## 작업 절차 +1. `data/10x-embryonic-mouse-brain/` 또는 사용자가 지정한 입력 경로를 확인한다. +2. 파일 형식은 확장자만 믿지 말고 header, shape, obs/var metadata, 일부 record를 확인한다. +3. RNA와 ATAC barcode overlap을 확인한다. +4. QC 지표를 계산하거나 기존 QC columns를 확인한다. +5. gene annotation, promoter/enhancer definition, peak-to-gene linkage 기준을 기록한다. +6. trajectory 또는 pseudotime 정보가 있으면 time axis 정의를 저장한다. +7. modeling용 산출물을 `work/10x-embryonic-mouse-brain/` 또는 `results/10x-embryonic-mouse-brain/` 아래에 저장한다. + +## 출력 형식 +```markdown +## Preprocessing Plan +- Dataset: +- Input files: +- Metadata checked: +- QC criteria: +- Genome build / annotation: +- Time axis: +- Outputs: +- Open issues: +``` + +## 주의할 점 +- 원본 파일은 덮어쓰지 않는다. +- mouse gene id와 gene symbol mapping을 명확히 남긴다. +- pseudotime과 real developmental stage를 섞어서 해석하지 않는다. + diff --git a/skills/10x-embryonic-mouse-brain/preprocessing/agents/openai.yaml b/skills/10x-embryonic-mouse-brain/preprocessing/agents/openai.yaml new file mode 100644 index 0000000..a5e9f25 --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/preprocessing/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "10x Mouse Brain Preprocessing" + short_description: "10x embryonic mouse brain multiome 전처리를 준비합니다." + default_prompt: "10x embryonic mouse brain multiome 데이터의 preprocessing plan을 한국어로 작성해줘. 입력 파일, metadata, QC, genome build, time axis, output을 포함해줘." diff --git a/skills/10x-embryonic-mouse-brain/visualization/SKILL.md b/skills/10x-embryonic-mouse-brain/visualization/SKILL.md new file mode 100644 index 0000000..4820f89 --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/visualization/SKILL.md @@ -0,0 +1,36 @@ +--- +name: 10x-embryonic-mouse-brain-visualization +description: Visualize preprocessing, lag estimates, model outputs, and biological interpretation for the 10x embryonic mouse brain multiome dataset. +--- + +# 10x Embryonic Mouse Brain Visualization + +## 목표 +10x embryonic mouse brain 분석 결과를 cell state, trajectory, chromatin/RNA timing, gene-specific lag, model performance 관점에서 시각화한다. + +## 우선 Figure +- UMAP 또는 trajectory plot with cell type/developmental stage. +- RNA/ATAC QC summary. +- chromatin opening time vs transcription onset time scatter. +- activation lag/shutdown lag distribution. +- lineage별 lag heatmap. +- predicted vs observed lag 및 feature importance. +- representative genes의 accessibility/RNA dynamics plot. + +## 작업 절차 +1. visualization input이 어떤 preprocessing/model output에서 왔는지 기록한다. +2. axis, unit, pseudotime direction, lineage definition을 Figure caption에 남긴다. +3. gene별 lag plot은 missingness와 confidence를 구분해 표시한다. +4. biological interpretation은 model output이 지지하는 범위 안에서만 작성한다. + +## 출력 형식 +```markdown +## Visualization Plan +- Dataset: +- Figures: +- Required inputs: +- Aesthetic rules: +- Captions: +- Interpretation notes: +``` + diff --git a/skills/10x-embryonic-mouse-brain/visualization/agents/openai.yaml b/skills/10x-embryonic-mouse-brain/visualization/agents/openai.yaml new file mode 100644 index 0000000..9b1b127 --- /dev/null +++ b/skills/10x-embryonic-mouse-brain/visualization/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "10x Mouse Brain Visualization" + short_description: "10x embryonic mouse brain 결과 시각화를 설계합니다." + default_prompt: "10x embryonic mouse brain 분석 결과의 visualization plan을 한국어로 작성해줘. trajectory, lag distribution, model performance, representative genes figure를 포함해줘." diff --git a/skills/OPENCLAW-RUN.md b/skills/OPENCLAW-RUN.md new file mode 100644 index 0000000..24ddd06 --- /dev/null +++ b/skills/OPENCLAW-RUN.md @@ -0,0 +1,36 @@ +# OpenClaw 실행 노트 — HSPC 하네스 (2026-07-01 시연·검증) + +> `AGENTS.md`+`skills/`는 OpenClaw/Codex 네이티브 포맷. 이 문서는 실제 OpenClaw로 +> 돌리는 방법과 현재 환경의 블로커를 기록한다. (CLAUDE.md: OpenClaw 기반 실행 기본 감안) + +## 검증 완료 (구조 — OpenClaw-native 유효) +- `openclaw` CLI 설치 확인: **OpenClaw 2026.5.7** (`~/.nvm/.../bin/openclaw`). `codex`도 설치됨. +- `skills/ROUTES.md` 라우팅: dataset(4종) → task(download/preprocessing/model/visualization) 테이블 정상. +- HSPC 4개 `agents/openai.yaml` 전부 파싱 OK(`interface.display_name`/`default_prompt` 유효): + Download / Preprocessing / Model / Visualization. +- `skills/human-hspc-10x-multiome/download/SKILL.md` frontmatter(name/description) 정상 → `pipeline/hspc-velocity-benchmark/` 실행 구현과 연결. + +## 실행 커맨드 (provider 설정 후 그대로 사용) +```bash +cd ~/project/BioProject01 +# openai.yaml의 default_prompt를 그대로 사용 +PROMPT=$(python3 -c "import yaml; print(yaml.safe_load(open( + 'skills/human-hspc-10x-multiome/download/agents/openai.yaml'))['interface']['default_prompt'])") + +openclaw agent --local --session-id hspc-openclaw-demo -m "$PROMPT" +# --local : gateway 대신 임베디드 에이전트(= shell의 provider 키 필요) +# --session-id : 세션 지정 필수(없으면 "Pass --to/--session-id/--agent" 에러) +# task 바꾸려면 경로만 교체: download → preprocessing/model/visualization +``` + +## ⚠️ 현재 블로커 (이 환경) — provider 미설정 +- `openclaw agent --local` turn이 **완료되지 못하고 kill됨**(60s 하드 타임아웃, exit 137). +- 원인: shell에 `ANTHROPIC_API_KEY`/`OPENAI_API_KEY` **없음** + `~/.openclaw/`에 provider/auth config **없음**(`plugins/installs.json`만 존재). `openclaw capability`/gateway 호출도 hang. +- 즉 **하네스 결함이 아니라 실행 환경의 provider auth 미설정**. 아래 셋 중 하나 갖추면 실행 가능: + 1. shell에 provider 키 export 후 `--local` (가장 간단), 또는 + 2. `openclaw` gateway에 provider 등록 후 `openclaw agent`(--local 없이), 또는 + 3. `codex`(동일 openai.yaml 포맷)로 실행. + +## 다음 +- provider 키 확보 시 위 커맨드로 download → preprocessing 순 실제 turn 시연. +- Codex 경로도 동일 `openai.yaml`이라 병행 검증 가능. diff --git a/skills/ROUTES.md b/skills/ROUTES.md new file mode 100644 index 0000000..f3716b4 --- /dev/null +++ b/skills/ROUTES.md @@ -0,0 +1,69 @@ +> 출처: 이 분석 하네스(`AGENTS.md` + `skills/`)는 **박상준(@poqopo) `Harness_Baseline`** 에서 반입해 BioProject01 `kkkim-pipeline`(실제 파이프라인 실행)에 맞게 적용함. 원저작자 박상준 (원 repo LICENSE 미지정 — 공유·수정은 박상준 동의 전제). HSPC는 `pipeline/hspc-velocity-benchmark/` 실행 구현과 연결. + +# Skill Routes + +Dataset-specific skill routing lives here. Route work first by dataset, then by task type. + +## Dataset Routing + +| Dataset request | Dataset folder | +| --- | --- | +| 10x embryonic mouse brain, embryonic mouse brain, mouse brain multiome | `skills/10x-embryonic-mouse-brain/` | +| SHARE-seq mouse skin, GSE140203, mouse skin differentiation | `skills/share-seq-mouse-skin/` | +| Human brain multi-ome, GSE162170, fetal/developing human brain | `skills/human-brain-multiome/` | +| Human HSPC 10x Multiome, GSE209878, hematopoietic stem/progenitor | `skills/human-hspc-10x-multiome/` | + +## Task Routing + +Within each dataset folder, route by task: + +| Task request | Skill | +| --- | --- | +| download, accession lookup, data acquisition, raw/processed file fetch, checksum, download manifest | `/download/SKILL.md` | +| preprocessing, QC, normalization, annotation, data loading, matrix/object preparation | `/preprocessing/SKILL.md` | +| model, lag estimation, MultiVelo/MoFlow-style dynamics, feature prediction, evaluation | `/model/SKILL.md` | +| visualization, figure plan, plotting, UMAP/trajectory/lag/model performance figures | `/visualization/SKILL.md` | + +## Dataset Workflow + +When the user asks for work on one dataset: + +1. Identify the dataset from the user's wording or accession. +2. Identify whether the task is `download`, `preprocessing`, `model`, or `visualization`. +3. Use the matching skill under `skills///SKILL.md`. +4. If the user gives a dataset but no task, start with `download` if no local input files exist; otherwise start with `preprocessing`. +5. If the user gives a task but no dataset, ask which dataset to use before proceeding. +6. Keep the framing centered on gene-specific `activation lag` and `shutdown lag`. + +## Cross-Dataset Workflow + +When the user asks for comparison across datasets: + +1. Apply the same task skill type across all relevant dataset folders. +2. Normalize terminology across datasets: genome build, annotation source, time axis, lineage/cell state labels, lag definitions. +3. Do not merge outputs until dataset-specific preprocessing/modeling assumptions are recorded. +4. Report dataset-specific uncertainty and missingness before making cross-dataset biological claims. + +## Current Skill Tree + +- `skills/10x-embryonic-mouse-brain/preprocessing/SKILL.md`: 10x embryonic mouse brain preprocessing +- `skills/10x-embryonic-mouse-brain/download/SKILL.md`: 10x embryonic mouse brain data download +- `skills/10x-embryonic-mouse-brain/model/SKILL.md`: 10x embryonic mouse brain lag modeling +- `skills/10x-embryonic-mouse-brain/visualization/SKILL.md`: 10x embryonic mouse brain visualization +- `skills/share-seq-mouse-skin/download/SKILL.md`: SHARE-seq mouse skin data download +- `skills/share-seq-mouse-skin/preprocessing/SKILL.md`: SHARE-seq mouse skin preprocessing +- `skills/share-seq-mouse-skin/model/SKILL.md`: SHARE-seq mouse skin lag modeling +- `skills/share-seq-mouse-skin/visualization/SKILL.md`: SHARE-seq mouse skin visualization +- `skills/human-brain-multiome/download/SKILL.md`: human brain multiome data download +- `skills/human-brain-multiome/preprocessing/SKILL.md`: human brain multiome preprocessing +- `skills/human-brain-multiome/model/SKILL.md`: human brain multiome lag modeling +- `skills/human-brain-multiome/visualization/SKILL.md`: human brain multiome visualization +- `skills/human-hspc-10x-multiome/download/SKILL.md`: human HSPC 10x Multiome data download +- `skills/human-hspc-10x-multiome/preprocessing/SKILL.md`: human HSPC 10x Multiome preprocessing +- `skills/human-hspc-10x-multiome/model/SKILL.md`: human HSPC 10x Multiome lag modeling +- `skills/human-hspc-10x-multiome/visualization/SKILL.md`: human HSPC 10x Multiome visualization + +## Dataset 담당 상태 (2026-06-14) +- `human-hspc-10x-multiome`: **active** (김가경 / 류재면) — `pipeline/hspc-velocity-benchmark/` 실행 구현. +- `10x-embryonic-mouse-brain`: **담당 미정 (TBD)** — 기존 담당(이건규)이 사정상 담당이 어려울 것으로 판단됨. 재배정/드롭은 팀 논의. skill 구조는 유지. +- `share-seq-mouse-skin` (박상준) / `human-brain-multiome` (전연수·박세진): 각 담당 영역. diff --git a/skills/external/README.md b/skills/external/README.md new file mode 100644 index 0000000..0326992 --- /dev/null +++ b/skills/external/README.md @@ -0,0 +1,10 @@ +# skills/external — 외부 참고 스킬 (vendored / pointer) +BIOP02 벤치마킹 흐름에 따라 반입한 외부 Agent Skills. **활성 스킬 아님** — 우리 conda env 적응 + 검증 게이트 통과 후에만 실제 사용. + +| 스킬 | 출처 | 라이선스 | 형태 | BIOP01 용도 | +|---|---|---|---|---| +| atac-seq/enhancer-gene-linking | GPTomics/bioSkills | MIT | 복사 | peak→gene 집계 직결 | +| atac-seq/atac-qc | GPTomics/bioSkills | MIT | 복사 | ATAC QC | +| scvi-tools | anthropics/life-sciences | 미지정 | 포인터 | MultiVI/veloVI(우리 VAE arm 인접) | + +규율: 자동 PASS 신뢰 금지. 스킬 카탈로그의 "있다" 주장도 SKILL.md 실측 후 도입(K-Dense scVelo confab 전례). diff --git a/skills/external/atac-seq/LICENSE b/skills/external/atac-seq/LICENSE new file mode 100644 index 0000000..bcccf5e --- /dev/null +++ b/skills/external/atac-seq/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 GPTomics + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills/external/atac-seq/SOURCE.md b/skills/external/atac-seq/SOURCE.md new file mode 100644 index 0000000..4caaa6c --- /dev/null +++ b/skills/external/atac-seq/SOURCE.md @@ -0,0 +1,14 @@ +# 출처 (vendored, MIT) +- 저장소: GPTomics/bioSkills — https://github.com/GPTomics/bioSkills +- 라이선스: **MIT** (LICENSE 동봉) +- 반입 스킬: `atac-seq/enhancer-gene-linking`, `atac-seq/atac-qc` (원본 경로 그대로) +- 반입일: 2026-07-15 (raw.githubusercontent.com/GPTomics/bioSkills/main/...) +- 반입 이유: BIOP01 10x Multiome ATAC 처리 — 특히 **enhancer-gene-linking**은 우리 peak→gene 집계(gene body ±10kb)와 직결. + +## ⚠️ 적응 필요 (활성 사용 전) +- 우리 conda env(`scv-preprocess`/`velo-mv`)에 맞게 도구·경로 확인. 원본 스킬의 도구 가정(macs2·ArchR 등)이 우리 스택에 있는지 검증. +- **우리 검증 게이트 뒤에 둔다**: 스킬 산출물은 결정론 재계산·permutation FDR·Critic 통과 후 채택(자동 PASS 신뢰 금지). +- 미적응 원본 = 참고용. 활성 skills/로 승격 전 smoke-test 필수. + +## 상태: 참고 보류 (2026-07-18) +스킬 의존 도구가 cicero·signac(R)·deeptools·bedtools·macs로 우리 velo env 밖. 우리 peak→gene은 gencode gene-body ±10kb 집계(다른 접근)라, 이 스킬은 **참고용**(활성화하려면 R/CLI 도구 별도 설치·검증 필요). diff --git a/skills/external/atac-seq/atac-qc/SKILL.md b/skills/external/atac-seq/atac-qc/SKILL.md new file mode 100644 index 0000000..a602348 --- /dev/null +++ b/skills/external/atac-seq/atac-qc/SKILL.md @@ -0,0 +1,337 @@ +--- +name: bio-atac-seq-atac-qc +description: ATAC-seq library quality control -- TSS enrichment, FRiP, fragment-size periodicity, library complexity (NRF/PBC1/PBC2), mitochondrial fraction, and ENCODE 4 thresholds. Use when assessing whether an ATAC-seq library passes ENCODE acceptance criteria, diagnosing transposition artefacts, comparing Omni-ATAC vs standard prep quality, or selecting which replicates to drop before peak calling. +tool_type: mixed +primary_tool: deeptools +--- + +## Version Compatibility + +Reference examples tested with: deepTools 3.5+, Picard 3.1+, samtools 1.19+, bedtools 2.31+, ATACseqQC 1.26+, pysam 0.22+, pyBigWig 0.3+, numpy 1.26+, pandas 2.2+, MultiQC 1.21+. + +Before using code patterns, verify installed versions match. If versions differ: +- Python: `pip show ` then `help(module.function)` to check signatures +- R: `packageVersion('')` then `?function_name` to verify parameters +- CLI: ` --version` then ` --help` to confirm flags + +If code throws ImportError, AttributeError, or TypeError, introspect the installed package and adapt. + +# ATAC-seq Quality Control + +**"Does my ATAC library pass ENCODE quality criteria?"** -> Compute the seven canonical metrics (depth, alignment rate, mitochondrial fraction, library complexity, fragment-size periodicity, TSS enrichment, FRiP) and compare against ENCODE 4 thresholds, then diagnose failures. + +- CLI: `picard CollectInsertSizeMetrics`, `samtools flagstat`, `samtools idxstats` +- CLI: `deeptools plotFingerprint`, `computeMatrix reference-point` + `plotProfile` +- R: `ATACseqQC::TSSEscore`, `ATACseqQC::fragSizeDist`, `ATACseqQC::PTscore` +- Python: custom NRF/PBC from coordinate hash; pyBigWig for TSS enrichment + +## ENCODE 4 ATAC-seq Acceptance Thresholds + +| Metric | Definition | Ideal | Acceptable | Reject | Source | +|--------|-----------|-------|------------|--------|--------| +| Nuclear reads (after dedup, no chrM) | Mapped, MAPQ >= 30, non-chrM, deduped | >= 50M | 25-50M | < 25M | ENCODE 4 ATAC-seq Standards | +| Alignment rate | Mapped / total reads | >= 95% | 80-95% | < 80% | ENCODE 4 | +| Mitochondrial fraction | chrM / total mapped | < 5% (Omni-ATAC), < 20% (standard) | 20-50% | > 50% | Corces 2017 (Omni-ATAC) | +| NRF (Non-Redundant Fraction) | Distinct positions / total reads | >= 0.9 | 0.7-0.9 | < 0.7 | Landt 2012 | +| PBC1 (PCR Bottlenecking Coefficient 1) | Positions w/ 1 read / Positions w/ >= 1 read | >= 0.9 | 0.7-0.9 | < 0.7 | Landt 2012 | +| PBC2 | Positions w/ 1 read / Positions w/ 2 reads | >= 3.0 | 1.0-3.0 | < 1.0 | Landt 2012 | +| TSS enrichment (hg38, GENCODE v29) | Avg signal at TSS / avg flanking | >= 7 | 5-7 | < 5 | ENCODE 4 | +| FRiP (Fraction Reads in Peaks) | Reads in MACS peaks / total | >= 0.3 | 0.2-0.3 | < 0.2 | ENCODE 4, Landt 2012 | +| Insert-size periodicity | NFR + mono-nuc + di-nuc peaks visible | Clear 3+ peaks | NFR + mono only | Flat / single peak | Buenrostro 2013 | + +ENCODE thresholds are organism-specific. Mouse (mm10, GENCODE M21) TSS enrichment >= 5 is acceptable; non-model organisms have no published threshold (use cohort percentile rank instead). Methodology evolves; verify against the current ENCODE ATAC-seq Standards before reporting. + +## TSS Enrichment: ENCODE Method vs ATACseqQC Method + +The two most common implementations DO NOT produce identical scores. + +| Method | Numerator | Denominator | Scaling | +|--------|-----------|-------------|---------| +| ENCODE pyTSSe / Kundaje gtsse | Mean signal in 100 bp window centered at TSS | Mean signal in 100 bp window at +/- 1900 to +/- 2000 bp (flanks) | Per-base normalization to flanks; reported as fold-enrichment | +| ATACseqQC TSSEscore | Sum signal in TSS +/- 100 bp | Sum signal at +/- 1000 bp flanking windows | Different window sizes; ratios are larger | +| deeptools plotProfile | Visual; numeric ratio not standardized | Reference-point matrix | No standard score; for visualization only | + +**Trigger:** Comparing a TSS score across studies. + +**Mechanism:** Different normalization windows shift the absolute number; ATACseqQC's TSSEscore is typically 2-3x ENCODE's because of the wider flank. + +**Symptom:** Reported score 21 vs ENCODE-ideal 7 mismatch. Likely the calculator was ATACseqQC; the equivalent ENCODE score might be 8. + +**Fix:** State which implementation was used. For ENCODE comparisons, use `pyTSSe` (Kundaje lab) or implement the ENCODE recipe directly. + +```python +import numpy as np +import pyBigWig + +def encode_tss_enrichment(bw_path, tss_bed, flank=2000): + """ENCODE-style TSS enrichment: signal at TSS center / signal at flanks.""" + bw = pyBigWig.open(bw_path) + profiles = [] + for line in open(tss_bed): + chrom, start, end, *rest = line.strip().split('\t') + tss = int(start) + strand = rest[2] if len(rest) > 2 else '+' + try: + vals = bw.values(chrom, tss - flank, tss + flank) + if vals is None or len(vals) != 2 * flank: continue + if strand == '-': vals = vals[::-1] + profiles.append(np.nan_to_num(vals)) + except RuntimeError: + continue + avg = np.nanmean(profiles, axis=0) + flank_signal = np.mean(np.concatenate([avg[:100], avg[-100:]])) + center_signal = np.mean(avg[flank - 50: flank + 50]) + return center_signal / flank_signal if flank_signal > 0 else 0.0 +``` + +## Fragment-Size Periodicity Patterns + +| Pattern | Visual signature | Interpretation | Action | +|---------|-----------------|----------------|--------| +| Strong tri-modal | NFR (~50bp) >> mono (~200bp) > di (~400bp) > tri (~600bp) peaks | Excellent transposition; well-positioned chromatin | Pass | +| Clear bi-modal | NFR + mono only, di and tri faint | Acceptable; common in Omni-ATAC | Pass | +| Single broad peak | Flat after NFR or no NFR | Over-transposition (too much Tn5) OR degraded chromatin | Reject; cannot distinguish nucleosomes | +| Inverted (mono >> NFR) | Mono peak dominant, NFR weak | Under-transposition OR chromatin condensation | Caution; peak counts will be low | +| Sharp 147 bp spike with no flanks | Tight peak at 147 bp | ChIP-seq input contamination (MNase-like) | Reject; not ATAC-grade | +| 10.4 bp helical periodicity overlay | Sub-peaks at 50, 60, 70, 80 bp on NFR | Excellent chromatin structure resolution; helical phasing visible | Pass; high-quality | + +The 10.4 bp helical periodicity is a Buenrostro 2013 hallmark: it reflects the helical pitch of B-form DNA, with Tn5 preferring outward-facing minor grooves on nucleosomal DNA. Its presence is a positive QC indicator but not required. + +## Per-Metric Failure Modes + +### Mitochondrial fraction > 50% + +**Trigger:** Standard ATAC-seq protocol on intact cells (no nuclear isolation), or insufficient detergent in lysis. + +**Mechanism:** Mitochondrial DNA is naked (no histones), so Tn5 hyperactively cuts it. Without nuclear-isolation steps (Omni-ATAC pre-spin, OR digitonin lysis with mt removal), chrM dominates the library. + +**Symptom:** `samtools idxstats sample.bam | awk '$1=="chrM"'` shows >50% of mapped reads on chrM. + +**Fix:** Re-prep with Omni-ATAC (Corces 2017) or fast-ATAC. Re-running QC on chrM-stripped BAM hides the underlying problem; the wasted sequencing remains. If chrM fraction is 30-50%, the library may still be salvageable via chrM removal but yield is reduced. + +### NRF / PBC1 / PBC2 below threshold + +**Trigger:** Over-amplified library; low input cell count combined with high PCR cycles. + +**Mechanism:** Each PCR cycle doubles starting fragments. With low complexity input (<5000 cells) and >12 cycles, distinct fragments saturate and reads pile up at identical positions. NRF measures unique fragments / total; PBC2 specifically detects multi-copy duplication. + +**Symptom:** NRF < 0.7; PBC2 < 1.0; massive duplicate-removal loss in `samtools markdup`. + +**Fix:** No fix post-hoc. Re-prep with more starting cells and fewer PCR cycles. Note: ATAC has *legitimate* duplicates at hyperaccessible sites (Tn5 cuts identically there), so NRF < 0.9 is not by itself fatal. The combined PBC1 < 0.7 + PBC2 < 1.0 + visual coverage pile-ups confirm true bottlenecking. + +### TSS enrichment < 5 + +**Trigger:** Generic chromatin opening throughout the genome (over-transposition), OR genome build mismatch between TSS BED and BAM, OR strand-flip in TSS file. + +**Mechanism:** TSS enrichment requires that signal at TSSs is >> signal in genomic flanks. Over-transposition flattens the signal landscape. Strand-flipped TSSs subtract real signal because TSSs on - strand are calculated from the wrong direction. + +**Symptom:** TSS profile is flat or shows a slight dip at TSS center. Genome browser shows accessibility everywhere, not concentrated at promoters. + +**Fix:** Verify genome build (mm10 vs mm39 differ in TSS positions); verify GTF strand column; confirm signal track was generated post-deduplication. If TSS profile is genuinely flat, library is over-transposed and not recoverable; lower transposition time / Tn5 concentration in next prep. + +### FRiP < 0.2 + +**Trigger:** Signal too diffuse to call peaks (over-transposition), low TSS enrichment, OR peak set is too narrow / restrictive. + +**Mechanism:** FRiP correlates with TSS enrichment because both measure how concentrated the signal is. A diffuse library will have low FRiP regardless of peak count. + +**Symptom:** Peak count looks normal but FRiP < 0.15. + +**Fix:** Check TSS enrichment first. If TSS is also low, the library is over-transposed. If TSS is OK but FRiP is low, the peak caller may be undercalling -- try `-p 0.01` (looser) and recalculate FRiP. + +### Replicate correlation < 0.85 + +**Trigger:** Batch effect, technical artefact, or cell-state drift between replicate biological collections. + +**Mechanism:** Pearson correlation on log-scaled binned counts (deepTools `multiBamSummary bins -bs 10000`) tracks coverage similarity. Below 0.85 indicates non-trivial divergence; ENCODE wants >= 0.9 for biological reps. + +**Fix:** Check PCA; if reps cluster apart from condition, drop the outlier or rerun. If the divergence aligns with batch, add batch as a covariate downstream (DiffBind `~Batch + Condition`). Do not silently merge with bad correlation. + +## Library Complexity (NRF, PBC1, PBC2) + +**Goal:** Detect over-amplification or low-input bottlenecks. + +**Approach:** Hash mapped read positions (or fragment 5' coordinates), tally how many positions have 1, 2, or more reads, and compute the three metrics. + +```python +import pysam +from collections import Counter + +def library_complexity(bam): + pos_counts = Counter() + total = 0 + with pysam.AlignmentFile(bam, 'rb') as bf: + for r in bf.fetch(): + if r.is_unmapped or r.is_secondary or r.is_supplementary: + continue + if r.is_duplicate: # Mark, not skip; PBC counts pre-dedup + pass + total += 1 + key = (r.reference_name, r.reference_start, r.is_reverse) + pos_counts[key] += 1 + distinct = len(pos_counts) + histogram = Counter(pos_counts.values()) # {1: N1, 2: N2, ...} + n1 = histogram.get(1, 0) + n2 = histogram.get(2, 0) + nrf = distinct / total if total else 0.0 + pbc1 = n1 / distinct if distinct else 0.0 + pbc2 = n1 / n2 if n2 else float('inf') + return {'NRF': nrf, 'PBC1': pbc1, 'PBC2': pbc2, 'total': total, 'distinct': distinct} +``` + +`r.is_duplicate` is informational only here; ENCODE NRF/PBC are computed pre-deduplication on the raw mapped BAM. + +## Cross-Replicate QC + +```bash +# Spearman correlation (more robust than Pearson for ATAC) +multiBamSummary bins -bs 10000 -p 8 \ + --bamfiles rep1.bam rep2.bam rep3.bam \ + -o multi.npz + +plotCorrelation -in multi.npz \ + --corMethod spearman --whatToPlot heatmap --skipZeros \ + -o spearman_heatmap.png + +# Fingerprint (per-bin signal cumulative -- diagonal = no enrichment, sharp curve = good) +plotFingerprint -p 8 -b rep1.bam rep2.bam rep3.bam \ + --labels rep1 rep2 rep3 \ + --skipZeros --numberOfSamples 50000 \ + -o fingerprint.png \ + --outQualityMetrics fingerprint_metrics.txt +``` + +deepTools fingerprint quality metrics report a synthetic JS distance without a reference; the (non-synthetic) Jensen-Shannon distance column is only computed when a reference sample is supplied via `--JSDsample`. Larger values indicate stronger enrichment. + +## Library Complexity Extrapolation (preseq) + +**Goal:** Predict whether re-sequencing would rescue a low-NRF library, separating "library is bottlenecked" from "we just sequenced too shallow." + +**Approach:** Fit preseq's rational-function (Pade) approximation of the Good-Toulmin power-series estimator on observed BAM read positions; extrapolate distinct-fragment yield as a function of additional sequencing depth. + +```bash +# c_curve: observed complexity at current depth +preseq c_curve -B sample.bam -o sample.ccurve.tsv -s 1e6 + +# lc_extrap: predicted complexity at higher depth (extrapolation -e here 200M; preseq default -e is 1e10, step -s default 1M) +preseq lc_extrap -B sample.bam -o sample.lcextrap.tsv -e 200000000 -s 5000000 +``` + +Interpretation: if `lc_extrap` shows distinct-fragment count flattening before 100M reads, the library is bottlenecked (re-sequencing won't help; re-prep needed). If it continues to climb, re-sequencing will recover more unique reads. Use alongside NRF/PBC1/PBC2 to decide library re-prep vs deeper sequencing. + +## Sex-Chromosome QC + +**Trigger:** Clinical-grade ATAC; biobank-scale studies; sample-mix-up detection. + +**Mechanism:** chrY has minimal coverage in female samples; XIST locus (chrX) is highly accessible only in female cells (X-inactivation). Sample-swap or sex-misassignment detectable from these two loci. + +```bash +# chrY read fraction +samtools idxstats sample.bam | awk '$1=="chrY"{print $3 / $2}' # reads per bp + +# XIST locus accessibility (chrX:73820651-73852753 in hg38) +samtools view -c sample.bam chrX:73820651-73852753 +``` + +Female: chrY reads/bp ~0; XIST count high. Male: chrY reads/bp ~male coverage; XIST count low. Discrepancy with sample metadata flags swap. + +## Cell-Cycle Effect on Accessibility + +**Trigger:** Proliferating cell lines (K562, HEK293, HeLa); samples with high S/G2M signature. + +**Mechanism:** Replication-associated chromatin opening adds 5-15% global accessibility shift in proliferating cells; without correction, condition-specific cell-cycle differences confound differential analysis. + +**Detection:** Score cells/samples for S-phase signature (Macosko 2015 cell cycle gene set adapted for chromatin: regulated origin loci, replication-stress-response genes); for bulk ATAC, compute per-sample peak intersection with replication-origin atlas (Repli-seq peaks). + +**Fix for differential:** Add S-phase score as covariate in DESeq2 design (`~Sphase + Condition`); for scATAC, regress on TF-IDF residuals analogous to Seurat CellCycleScoring. + +## Spike-in QC (Drosophila or E. coli Chromatin) + +**Trigger:** Studies where global accessibility shift is biological (HDAC inhibitor, DNMT inhibitor, differentiation). + +**Mechanism:** Per-library normalization (RPM, CPM) erases global accessibility shifts because total reads are nominally constant. Exogenous chromatin spike-in (Drosophila S2 or E. coli Tn5-naive chromatin added pre-Tn5) provides an external scaling reference. + +**Pipeline:** Align reads to a concatenated human + Drosophila reference; count spike-in reads per sample; normalize by spike-in (not by total reads). Reske 2020 Epigenetics Chromatin shows that normalization-method choice materially changes differential-accessibility results when a global accessibility shift is expected (ARID1A/PIK3CA endometrial-epithelium case study), motivating an external reference such as a chromatin spike-in. + +**QC threshold:** spike-in fraction 0.5-5% of total reads is the workable range. Below 0.1% spike-in is unreliable; above 10% suggests too much spike-in (loss of cellular reads). + +## Comprehensive QC Aggregation + +**Goal:** Produce a per-sample report card with PASS/FAIL flags against ENCODE thresholds. + +**Approach:** Compute each metric independently, compare to thresholds, write a tab-delimited report consumable by MultiQC. + +```python +import json, subprocess, sys +from pathlib import Path + +ENCODE_THRESHOLDS = { + 'nuclear_reads_M': (25, 50), # (min acceptable, ideal) + 'mt_fraction': (0.5, 0.05), # (max acceptable, ideal); inverted + 'NRF': (0.7, 0.9), 'PBC1': (0.7, 0.9), 'PBC2': (1.0, 3.0), + 'TSS_enrichment': (5.0, 7.0), 'FRiP': (0.2, 0.3), +} + +def grade(value, thr_acceptable, thr_ideal, inverted=False): + if inverted: + return 'FAIL' if value > thr_acceptable else ('PASS' if value <= thr_ideal else 'WARN') + return 'FAIL' if value < thr_acceptable else ('PASS' if value >= thr_ideal else 'WARN') + +def report(metrics, out_tsv): + rows = [] + for k, (acc, ideal) in ENCODE_THRESHOLDS.items(): + if k not in metrics: continue + inverted = (k == 'mt_fraction') + flag = grade(metrics[k], acc, ideal, inverted=inverted) + rows.append((k, metrics[k], acc, ideal, flag)) + with open(out_tsv, 'w') as f: + f.write('metric\tvalue\tacceptable\tideal\tflag\n') + for r in rows: f.write('\t'.join(map(str, r)) + '\n') +``` + +## MultiQC Aggregation + +```bash +# Run after generating per-sample QC outputs +multiqc \ + fastqc/ \ + picard/ \ + samtools_stats/ \ + macs2/ \ + deeptools/ \ + -o multiqc_report +``` + +MultiQC ingests Picard CollectInsertSizeMetrics, samtools flagstat, deepTools plotFingerprint output, and MACS peaks tables. It does NOT compute TSS enrichment or NRF; pipe a custom `_mqc.tsv` for those. + +## Common Errors + +| Error / symptom | Cause | Solution | +|-----------------|-------|----------| +| TSS enrichment off by 3x from expected | Wrong implementation (ENCODE vs ATACseqQC) | State the formula; convert by recomputing | +| NRF = 1.0 exactly | BAM was already deduplicated -> all positions distinct | Compute NRF on raw mapped BAM (pre-dedup) | +| PBC2 = inf | No positions with 2 reads | Library is too sparse; PBC2 unreliable below ~5M reads | +| Mt fraction reported but BAM has no `chrM` | Mitochondrial chromosome named `MT`, `Mt`, or `chromosome:MT` | Match `samtools idxstats` chromosome name to the filter | +| Insert size distribution flat after Picard | Sample is single-end | Insert size only valid for paired-end; switch to deeptools fragmentSize | +| Replicates correlate poorly but PCA looks fine | High background dominates correlation | Use `--skipZeros`; or compute correlation on peak counts only | +| FRiP differs by 2x between identical pipeline runs | Peak set differs (q-value cutoff drift) | Pin caller version + cutoff; FRiP is peak-set-dependent | +| TSS enrichment lower than expected on Omni-ATAC | Used standard TSS BED on FFPE-prepped sample | FFPE TSSs are degraded; use peak-based metric instead | + +## References + +- Buenrostro JD et al 2013 Nat Methods 10:1213 (ATAC-seq protocol; fragment-size periodicity) +- Corces MR et al 2017 Nat Methods 14:959 (Omni-ATAC; mt fraction reduction protocol) +- Landt SG et al 2012 Genome Res 22:1813 (ENCODE/modENCODE QC framework, NRF/PBC definitions; the PBC1/PBC2 split is a later ENCODE-pipeline refinement) +- ENCODE 4 ATAC-seq Data Standards (encodeproject.org/atac-seq) -- canonical thresholds +- Ou J et al 2018 BMC Genomics 19:169 (ATACseqQC R package; TSSEscore implementation) +- Ramirez F et al 2016 Nucleic Acids Res 44:W160 (deepTools, plotFingerprint JSD) +- Daley T & Smith AD 2013 Nat Methods 10:325 (preseq library-complexity extrapolation model; the lc_extrap re-sequencing decision) + +## Related Skills + +- atac-seq/atac-peak-calling - FRiP requires peaks; QC drives accept/reject before calling +- atac-seq/nucleosome-positioning - Fragment-size analysis +- atac-seq/single-cell-atac - per-cell QC has different thresholds +- read-qc/quality-reports - upstream FastQC +- alignment-files/bam-statistics - samtools flagstat / idxstats +- alignment-files/duplicate-handling - dedup before NRF/PBC computation diff --git a/skills/external/atac-seq/enhancer-gene-linking/SKILL.md b/skills/external/atac-seq/enhancer-gene-linking/SKILL.md new file mode 100644 index 0000000..3548fc4 --- /dev/null +++ b/skills/external/atac-seq/enhancer-gene-linking/SKILL.md @@ -0,0 +1,296 @@ +--- +name: bio-atac-seq-enhancer-gene-linking +description: Predict enhancer-gene regulatory connections from ATAC-seq using ABC, ENCODE-rE2G, HiChIP, or Cicero. Use when linking distal enhancers to target genes, choosing between contact-aware (ABC, ENCODE-rE2G), accessibility-only (Cicero), and orthogonal (HiChIP H3K27ac, EpiMap) approaches, validating predictions against CRISPRi-FlowFISH gold-standard, or building cell-type-specific regulatory maps for fine-mapping or therapeutic target discovery. +tool_type: mixed +primary_tool: ABC-Enhancer-Gene-Prediction +--- + +## Version Compatibility + +Reference examples tested with: ABC-Enhancer-Gene-Prediction 0.2.2+ (Engreitz lab), ENCODE-rE2G v1.0+ (EngreitzLab), Cicero 1.20+, GenomicInteractions 1.36+, FitHiChIP 9.1+, HiC-Pro 3.1+, FAN-C 0.9+, MACS3 3.0+, samtools 1.19+, bedtools 2.31+. + +Verify before use: +- CLI: ` --version` then ` --help` to confirm flags +- R: `packageVersion('')` then `?function_name` to verify parameters +- Python: `pip show ` then `help(module.function)` to check signatures + +If code throws unexpected errors, introspect the installed package and adapt rather than retrying. + +# Enhancer-Gene Linking + +**"Which gene does this distal accessible region regulate?"** -> Predict the enhancer's target gene using a model that combines accessibility activity, 3D contact frequency, and (optionally) sequence-based chromatin predictions. Output is a per-(enhancer, gene) score that can be thresholded for high-confidence calls. + +- CLI: ABC pipeline (`run.neighborhoods.py`, `predict.py` from Engreitz lab) +- CLI: ENCODE-rE2G (Snakemake-based; ENCODE 4 enhancer-gene standard) +- R: Cicero (ATAC-only; covered in atac-seq/co-accessibility) +- CLI: FitHiChIP / hichipper for HiChIP H3K27ac loops +- Database: EpiMap (Boix 2021), GeneHancer, FANTOM5 (pre-computed reference) + +ABC and ENCODE-rE2G are the canonical predictors when Hi-C/Micro-C data is available. Cicero is the ATAC-only fallback. CRISPRi-FlowFISH (Fulco 2019) is the gold-standard experimental validation. + +## Algorithmic Taxonomy + +| Method | Inputs | Mathematics | Strength | Fails when | +|--------|--------|-------------|----------|------------| +| ABC (Fulco 2019, Nasser 2021) | ATAC + H3K27ac + Hi-C/Micro-C | ABC = (Activity_E x Contact_E,G) / sum_e(Activity_e x Contact_e,G); threshold typically >= 0.02 | Mechanistically grounded; published gold-standard for human cell lines | Requires matched Hi-C / Micro-C; cell-type-specific; default contact uses average across 10 ENCODE cell types if Hi-C not available | +| ENCODE-rE2G (Gschwind 2023) | ATAC + H3K27ac + (Hi-C optional) | Logistic regression trained on CRISPRi-FlowFISH ground truth; uses ABC features + sequence features + distance | ENCODE 4 standard; pre-trained models for many cell types | Pre-trained models only available for ENCODE cell types; retraining requires CRISPRi data | +| Cicero (Pliner 2018) | scATAC peak-cell matrix | Graphical lasso on metacell co-accessibility | ATAC-only; works without Hi-C | Less concordant with Hi-C than ABC; cis-distance-limited; alpha-sensitive | +| HiChIP H3K27ac + FitHiChIP | H3K27ac HiChIP | Statistically significant loops at FDR < 0.05 | Direct experimental loop measurement; cell-type-specific; orthogonal to ATAC | Requires HiChIP wet-lab; only captures loops within HiChIP resolution (~10 kb) | +| Hi-C + HiCCUPS | Bulk Hi-C | Fold-enrichment loop calling | Most-validated 3D contact method | Resolution typically 5-25 kb; misses sub-loop fine structure | +| Capture Hi-C / PCHi-C (CHiCAGO) | Promoter Capture Hi-C | Asymptotic CHiCAGO score | High-resolution promoter-anchored | Wet-lab cost; promoter capture only | +| EpiMap (Boix 2021) reference | None (pre-computed lookup) | Bulk-derived enhancer-gene predictions in 833 epigenomes | Fast, comprehensive | Cell-type-agnostic for tissues outside the reference set | +| GeneHancer / FANTOM5 (legacy) | None (pre-computed lookup) | Pre-computed; varied methods per database | Comprehensive lookup; widely cited | Older; less reliable than ABC for cell-type-specific | + +Methodology evolves; verify against current Engreitz lab releases (ABC), ENCODE 4 publications (ENCODE-rE2G), and Mumbach 2017 (HiChIP) before locking pipelines. + +## ABC Mathematics + +For each candidate (enhancer E, gene G) pair within the cis window (default 5 Mb): + +``` +ABC(E -> G) = Activity_E * Contact_E,G / sum_{all e in window}(Activity_e * Contact_e,G) +``` + +- **Activity_E** = ATAC reads at E * H3K27ac reads at E (geometric mean of normalized signals; reflects "enhancer strength") +- **Contact_E,G** = Hi-C/Micro-C contact frequency from E to G's TSS (after distance-correction) +- **Window** = +/- 5 Mb cis (default; ENCODE-rE2G uses 1 Mb) + +Threshold typical: ABC >= 0.02 for high-confidence; >= 0.01 for exploratory. + +When Hi-C is unavailable, ABC uses an "average contact" averaged across 10 ENCODE Hi-C cell types as proxy (Nasser 2021); it performs comparably to cell-type-matched Hi-C. The alternative powerlaw approximation of contact-vs-distance is the Fulco 2019 fallback. + +## ENCODE-rE2G Differences from ABC + +ENCODE-rE2G (Gschwind et al 2023, bioRxiv) is a reformulation: + +- **Logistic regression** trained on CRISPRi-FlowFISH ground truth (~10 cell types) +- **Features:** ABC score components + 3D contact + distance + activity ratios +- **Multiple feature configurations:** "abc-features", "no-hic-features" for cells without 3D data +- **Output:** Per-pair probability of regulatory connection +- **Pre-trained models** for ENCODE cell lines; logistic params vary by cell type + +ENCODE-rE2G generally outperforms ABC at CRISPRi recall, especially at modest distances (50-500 kb). For ENCODE cell types, prefer ENCODE-rE2G; for novel cell types, ABC remains the default. + +## Per-Tool Failure Modes + +### ABC -- Wrong cell-type-matched Hi-C + +**Trigger:** Using K562 Hi-C contact when actual cell type is GM12878. + +**Mechanism:** Contact frequencies differ across cell types at compartment and TAD boundaries; using mismatched Hi-C produces wrong ABC scores. + +**Symptom:** ABC predictions concentrate at known K562-specific loci even when ATAC data is from GM12878. + +**Fix:** Use cell-type-matched Hi-C or Micro-C. If unavailable, ABC's "average HiC" (10-cell-type pooled) is the documented fallback with acknowledged degradation. Document the proxy in methods. + +### ABC -- H3K27ac normalization + +**Trigger:** H3K27ac ChIP-seq with different sequencing depth than ATAC. + +**Mechanism:** ABC's "Activity" is the geometric mean of accessibility and H3K27ac signals; both must be normalized to the same scale. + +**Symptom:** Activity scores skewed; some peaks have very high activity from H3K27ac alone, others from ATAC alone. + +**Fix:** Normalize both signals to reads-per-million in peaks (RPM-IP) before combining. Use ABC's `--qnorm` flag with a quantile-normalization reference file (e.g. `--qnorm reference/EnhancersQNormRef.K562.txt` from the ABC repo). + +### ENCODE-rE2G -- Cell type not in pre-trained set + +**Trigger:** Running pre-trained model on a primary cell type not in CRISPRi training. + +**Mechanism:** Logistic regression coefficients learned from ENCODE cell types may not transfer to primary tissues. + +**Fix:** Use the closest ENCODE cell type (myeloid lineage -> K562; lymphoid -> GM12878; hepatic -> HepG2). Document the proxy. For high-stakes use, custom retraining requires CRISPRi-FlowFISH data. + +### Cicero -- No Hi-C concordance benchmark + +**Trigger:** Reporting Cicero connections as enhancer-gene calls without external validation. + +**Mechanism:** Cicero is statistical co-accessibility; correlation with Hi-C 3D contacts is ~30-50%. Many strong Cicero connections are NOT Hi-C-validated. + +**Fix:** When Hi-C is available, cross-validate; report both. When only ATAC, use Cicero with the explicit caveat that connections are co-accessibility hypotheses, not contact predictions. + +### HiChIP -- Loop calling threshold + +**Trigger:** Default FitHiChIP at FDR < 0.05. + +**Mechanism:** HiChIP loops are abundant (10k-100k per dataset); FDR alone produces a long tail of weak loops. + +**Fix:** Threshold at FDR < 0.05 AND number of contacts per loop >= 5; or use the top N most significant where N = expected number of loops based on cell type. + +### EpiMap / GeneHancer -- Cell-type-agnostic limitation + +**Trigger:** Using EpiMap or GeneHancer pre-computed pairs for a specific cell type. + +**Mechanism:** These references aggregate across many tissues / experiments; cell-type-specific connections are diluted. + +**Fix:** Use as a baseline / sanity check, not as the primary call. ABC or ENCODE-rE2G in the actual cell type is preferred. + +## Decision Tree by Available Data + +| Available data | Recommended method | +|---------------|--------------------| +| ATAC + H3K27ac + matched Hi-C/Micro-C | ABC or ENCODE-rE2G (with cell-type-matched contact) | +| ATAC + H3K27ac, no Hi-C | ABC with average HiC fallback; or ENCODE-rE2G `no-hic` model | +| ATAC only, no H3K27ac | Cicero (atac-seq/co-accessibility); ABC with synthetic activity | +| ATAC + H3K27ac HiChIP | FitHiChIP loops + ABC; intersect for high confidence | +| Multiome (ATAC + RNA same cell) | LinkPeaks (Signac) for direct correlation; SCENIC+ for TF networks | +| ENCODE cell type | Pre-computed ENCODE-rE2G predictions (download) | +| Tissue with limited public data | ABC + acknowledge proxy; do not rely on EpiMap | +| Multi-cell-type scATAC | scBasset (atac-seq/deep-learning-atac) for sequence-based per-cell | +| Want experimental validation | CRISPRi-FlowFISH design; use predictions as targeted hypotheses | + +## ABC Standard Pipeline + +**Goal:** Compute per-(enhancer, gene) ABC scores combining ATAC accessibility, H3K27ac activity, and Hi-C contact. + +**Approach:** Define non-promoter candidate enhancers from ATAC peaks, run ABC neighborhoods (which counts reads directly from the ATAC/H3K27ac BAMs) to compute per-candidate activity, then run ABC predict against a Hi-C contact matrix and threshold the per-pair ABC score. + +```bash +# 1. (Optional, browser tracks only) ATAC/H3K27ac bigWigs -- ABC neighborhoods below reads the BAMs directly, not bigWigs +bamCoverage --bam atac.bam --outFileName atac.bw --binSize 50 --normalizeUsing RPGC \ + --effectiveGenomeSize 2701495711 --numberOfProcessors 8 + +# 2. Define enhancer candidates (typically MACS narrowPeak from ATAC) +# Filter to non-promoter regions +bedtools intersect -v -a atac_peaks.narrowPeak -b promoter_regions.bed > candidate_enhancers.bed + +# 3. Run ABC neighborhoods (compute Activity per candidate) +# Script path: legacy ABC = src/run.neighborhoods.py; Snakemake-based modern = workflow/scripts/run.neighborhoods.py +python /path/ABC-Enhancer-Gene-Prediction/workflow/scripts/run.neighborhoods.py \ + --candidate_enhancer_regions candidate_enhancers.bed \ + --genes refseq_protein_coding.bed \ + --H3K27ac h3k27ac.bam \ + --DHS atac.bam \ + --chrom_sizes hg38.chrom.sizes \ + --chrom_sizes_bed hg38.chrom.sizes.bed \ + --ubiquitously_expressed_genes Genes.ubiquitously_expressed.txt \ + --cellType MyCellType \ + --outdir abc_out/ + +# 4. Run ABC predictions (Activity * Contact) -- generates ALL unthresholded links +python /path/ABC-Enhancer-Gene-Prediction/workflow/scripts/predict.py \ + --enhancers abc_out/EnhancerList.txt \ + --genes abc_out/GeneList.txt \ + --hic_file hic_data/ \ + --hic_type avg \ + `# --hic_type choices: hic | juicebox | bedpe | avg -- must match the Hi-C input format` \ + --hic_resolution 5000 \ + --hic_pseudocount_distance 5000 \ + `# --hic_pseudocount_distance (required): powerlaw fit at this distance is added as a pseudocount (config default 5000)` \ + --chrom_sizes hg38.chrom.sizes \ + --score_column ABC.Score \ + --cellType MyCellType \ + --outdir abc_out/Predictions/ + +# predict.py writes EnhancerPredictionsAllPutative.tsv.gz (all unthresholded E-G links). +# 5. Threshold at ABC.Score >= 0.02. The ABC Snakemake pipeline runs filter_predictions.py with its +# full set of --output_* arguments; for a standalone cut, select by the ABC.Score column (by header): +zcat abc_out/Predictions/EnhancerPredictionsAllPutative.tsv.gz | \ + awk -F'\t' 'NR==1{for(i=1;i<=NF;i++)if($i=="ABC.Score")c=i; print; next} $c>=0.02' \ + > abc_out/Predictions/EnhancerPredictions_thresholded.tsv +``` + +ABC.Score >= 0.02 is the standard threshold validated in Fulco 2019 against CRISPRi-FlowFISH; >= 0.04 is a stricter cut sometimes used in the ABC pipeline documentation for higher precision (no separate primary-paper calibration). + +## ENCODE-rE2G + +```bash +# Snakemake-based; clone the ENCODE-rE2G repo +git clone https://github.com/EngreitzLab/ENCODE_rE2G +cd ENCODE_rE2G + +# Inputs are supplied through config/config.yaml, whose ABC_BIOSAMPLES field points to +# an ABC biosamples TSV carrying the cell type and the ATAC / H3K27ac / Hi-C paths -- +# there is no cell_type=/atac_bw= --config override interface. +snakemake -j1 --use-conda + +# Output: encode_e2g_predictions.tsv.gz with per-pair ENCODE-rE2G.Score and thresholded predictions +``` + +Pre-trained models are at https://github.com/EngreitzLab/ENCODE_rE2G/tree/main/models. Choose by tissue similarity if exact cell type not present. + +## CRISPRi-FlowFISH Validation Framework + +CRISPRi-FlowFISH (Fulco 2019) is the experimental gold-standard: +1. Design sgRNAs tiling each candidate enhancer +2. Transduce CRISPRi-expressing cells; FACS by gene expression (FlowFISH for endogenous; reporter for ectopic) +3. Sequence sgRNAs in low- vs high-expression bins; compute log2 enrichment per sgRNA +4. Significance: meta-test across sgRNAs in same enhancer + +A 2-fold expression decrease (p < 0.05) confirms the enhancer regulates the gene. + +For predictions to be publication-grade, ENCODE 4 expects: +- **Test set sensitivity / specificity** against published CRISPR enhancer-screen catalogs (Fulco 2019: K562 FlowFISH; Gasperini 2019: K562; Schraivogel 2020: K562 TAP-seq) +- **Effect-size correlation** between predicted score and observed expression effect +- **Distance bias check** (predictors over-rank close-distance pairs) + +## Reconciling Methods + +| Pattern | Likely cause | Action | +|---------|--------------|--------| +| ABC and ENCODE-rE2G disagree | Different feature weighting; different training distributions | Both valid; report intersection as high-confidence | +| ABC strong, Cicero weak | Co-accessibility sparse for that cell type | Trust ABC if Hi-C is matched | +| HiChIP loop with no ABC prediction | Loop is below ABC threshold; or peak set too narrow | Lower threshold or expand candidate enhancers | +| ENCODE-rE2G high probability, no CRISPRi support | Could be context-dependent biology or false positive | Prioritize for follow-up; not a publishable claim alone | +| EpiMap pair not in ABC | Pre-computed reference is cell-type-aggregated | Use ABC for cell-type-specific | + +**Operational rule for high-confidence reporting:** Predictions used for therapeutic target nomination must be (a) above ABC >= 0.02 OR ENCODE-rE2G >= 0.5, AND (b) consistent across two methods (ABC + ENCODE-rE2G or ABC + HiChIP), AND (c) validated experimentally (CRISPRi-FlowFISH preferred). Single-method high-score predictions are exploratory hypotheses. + +## Combining Multiple Predictions + +**Goal:** Build a high-confidence enhancer-gene set by intersecting ABC, ENCODE-rE2G, and HiChIP evidence. + +**Approach:** Load each method's output, merge ABC and ENCODE-rE2G on enhancer-gene pair above per-method thresholds, then flag pairs with HiChIP loop support for triple-method evidence. + +```python +import pandas as pd +abc = pd.read_csv('abc_predictions.tsv', sep='\t') +re2g = pd.read_csv('encode_re2g.tsv.gz', sep='\t') +hichip = pd.read_csv('fithichip_loops.bedpe', sep='\t', header=None, + names=['chr1','s1','e1','chr2','s2','e2','name','score']) + +# High-confidence intersection +high_conf = abc[abc['ABC.Score'] >= 0.02].merge( + re2g[re2g['ENCODE-rE2G.Score'] >= 0.5], + on=['enhancer_id', 'gene']) + +# Add HiChIP support flag +hichip_anchors = ... # extract enhancer/gene pairs from HiChIP loops +high_conf['hichip_support'] = high_conf['enhancer_id'].isin(hichip_anchors) +``` + +## Common Errors + +| Error / symptom | Cause | Solution | +|-----------------|-------|----------| +| ABC predictions concentrate at TSSs | Did not exclude promoter regions from candidates | Pre-filter `bedtools intersect -v` against promoters | +| Activity scores all very small | H3K27ac or ATAC bigWig in wrong scale | Use RPGC normalization | +| ENCODE-rE2G model not converging | Pre-trained model loaded for wrong cell type | Match training cell type via `cell_type` config | +| Cicero connections used as enhancer-gene calls | Method confusion (co-accessibility vs contact) | Switch to ABC if Hi-C available; or document as co-accessibility hypothesis | +| Hi-C resolution too coarse | Default 25 kb resolution masks fine ABC structure | Use 5 kb or 10 kb if Micro-C available | +| FitHiChIP many loops, low specificity | Default FDR alone | Add contact count threshold; or use ENCODE-rE2G HiChIP-trained model | +| GeneHancer / FANTOM5 used as primary call | Cell-type-agnostic limitation | Use as baseline only | + +## References + +- Fulco CP et al 2019 Nat Genet 51:1664 (ABC; CRISPRi-FlowFISH validation) +- Nasser J et al 2021 Nature 593:238 (ABC genome-wide application) +- Gschwind AR et al 2023 bioRxiv 2023.11.09.563812 (ENCODE-rE2G; encyclopedia of enhancer-gene regulatory interactions; preprint) +- Mumbach MR et al 2017 Nat Genet 49:1602 (HiChIP H3K27ac) +- Bhattacharyya S et al 2019 Nature Communications 10:4221 (FitHiChIP) +- Boix CA et al 2021 Nature 590:300 (EpiMap reference) +- Gasperini M et al 2019 Cell 176:377 (CRISPRi at scale) +- Schraivogel D et al 2020 Nat Methods 17:629 (TAP-seq targeted Perturb-seq enhancer screen, K562; scRNA-seq readout) +- Pliner HA et al 2018 Mol Cell 71:858 (Cicero co-accessibility) + +## Related Skills + +- atac-seq/co-accessibility - Cicero (ATAC-only enhancer-promoter inference) +- atac-seq/atac-peak-calling - Generate enhancer candidates +- atac-seq/consensus-peakset - Fixed-width enhancer regions +- atac-seq/deep-learning-atac - chromBPNet variant effect at predicted enhancers +- atac-seq/single-cell-atac - Per-cell-type scATAC inputs +- hi-c-analysis/loop-calling - Hi-C / Micro-C contact prediction +- hi-c-analysis/contact-pairs - Hi-C / Micro-C input +- chip-seq/peak-calling - H3K27ac peaks +- gene-regulatory-networks/scenic-regulons - Downstream TF -> target inference diff --git a/skills/external/scvi-tools/SOURCE.md b/skills/external/scvi-tools/SOURCE.md new file mode 100644 index 0000000..fab0296 --- /dev/null +++ b/skills/external/scvi-tools/SOURCE.md @@ -0,0 +1,8 @@ +# scvi-tools 스킬 — 포인터 (원본 복사 안 함) +- 저장소: anthropics/life-sciences — https://github.com/anthropics/life-sciences/blob/main/scvi-tools/SKILL.md +- **라이선스: 미지정** (repo 루트 LICENSE 404, 2026-07-15 확인) → **무단 재배포 금지**. 원본은 위 URL에서 직접 참조. +- BIOP01 적합성: **최상** — scvi-tools의 **MultiVI(multiome RNA+ATAC)·veloVI(RNA velocity)**가 우리 MultiVeloVAE arm과 직결. scVI/scANVI 배치보정·PeakVI(ATAC)도 포함. +- 도입 방법(라이선스 확인 후): 위 URL의 SKILL.md를 참조해 우리 하네스용으로 **재작성**(복사 아님) 또는 Anthropic에 사용범위 확인. + +## 상태: 활성화됨 (2026-07-18) +velo-torch에 scvi-tools 1.3.3 설치·검증(MULTIVI·PEAKVI·SCVI·VELOVI import OK). 사용법=USING_IN_BIOP01.md(우리 작성). 원본 SKILL.md는 라이선스 미지정이라 미복사. \ No newline at end of file diff --git a/skills/external/scvi-tools/USING_IN_BIOP01.md b/skills/external/scvi-tools/USING_IN_BIOP01.md new file mode 100644 index 0000000..b3a9103 --- /dev/null +++ b/skills/external/scvi-tools/USING_IN_BIOP01.md @@ -0,0 +1,20 @@ +# scvi-tools — BIOP01 활성화 가이드 (우리 작성, 원본 SKILL.md 복사 아님) + +**활성화됨(2026-07-18)**: `velo-torch` env에 `scvi-tools 1.3.3` 설치·검증 완료. +smoke-test: MULTIVI·PEAKVI·SCVI·VELOVI 전부 import 성공. + +## BIOP01에서 왜 유용한가 (우리 스택 직결) +- **MULTIVI** — 10x Multiome RNA+ATAC 공동 잠재공간. 우리 벤치마크의 multiome 입력에 직접. +- **VELOVI** (`scvi.external`) — 확률적 RNA velocity. 우리 velocity arm(MultiVeloVAE)과 계보 인접 → cross-method 벤치마크에 arm 추가 후보. +- **PEAKVI** — ATAC 전용 잠재공간(peak). day0 ATAC feature 인코딩 대안. +- **SCVI/scANVI** — 배치보정·라벨전이(day0/day7 통합에 참고). + +## 실행 (velo-torch) +```bash +conda run --no-capture-output -n velo-torch python -c "from scvi.model import MULTIVI; ..." +``` + +## 규율 (중요) +- 산출물은 **우리 검증 게이트 뒤**: 결정론 재계산·permutation FDR·bootstrap·Critic 통과 후 채택. +- 새 velocity arm으로 VELOVI를 넣으면 **cross-method 정의 정합**(lag/α 자 통일) 필수 — p3_concordance 계약 준수. +- 원본 SKILL.md(anthropics/life-sciences)는 **라이선스 미지정**이라 복사 안 함. 이 문서는 우리가 작성. 업스트림은 SOURCE.md URL 참조. diff --git a/skills/human-brain-multiome/download/SKILL.md b/skills/human-brain-multiome/download/SKILL.md new file mode 100644 index 0000000..5b8e3e6 --- /dev/null +++ b/skills/human-brain-multiome/download/SKILL.md @@ -0,0 +1,52 @@ +--- +name: human-brain-multiome-download +description: Download or register the human brain multi-ome dataset GSE162170 for gene-specific epigenomic lag analysis. Use when Codex needs to find official data sources, fetch raw or processed files, verify files, or create a download manifest before preprocessing. +--- + +# Human Brain Multiome Download + +## Dataset +- Name: Human brain multi-ome +- Accession: GSE162170 +- Biology: fetal / developing human brain +- Data type: human multiome +- Main use: human developmental dataset for gene-specific epigenomic lag analysis. + +## 목표 +GSE162170 human brain multiome 데이터를 GEO/SRA, 원 논문 supplement, 또는 공식 data portal에서 확인하고, donor/stage/region metadata와 함께 재현 가능한 다운로드 manifest를 만든다. + +## 우선 확인 항목 +- GEO Series GSE162170, linked SRA runs, supplementary files, 원 논문/portal URL. +- controlled-access 여부, 사용 조건, citation, download date. +- human genome build와 gene annotation source. +- donor, developmental stage, brain region, batch/sample metadata. +- RNA matrix, ATAC fragments/peak matrix, peak annotation, cell metadata. +- raw data 재처리가 필요한지, processed object로 분석 가능한지. + +## 작업 절차 +1. 공식 출처를 확인하고 accession, URL, access date, access restriction을 기록한다. +2. raw FASTQ/SRA, processed matrix/object, metadata 파일을 분리해 받을 파일 목록을 만든다. +3. `data/human-brain-multiome/raw/`, `data/human-brain-multiome/processed/`, `metadata/human-brain-multiome/` 경로를 사용한다. +4. donor/stage/region/run mapping을 우선 저장하고, sample sheet를 preprocessing에서 바로 읽을 수 있게 둔다. +5. provider checksum 또는 local sha256 checksum을 manifest에 남긴다. +6. 다운로드 후 파일 크기, 압축 무결성, matrix/object shape, obs/var metadata 일부를 확인한다. +7. `metadata/human-brain-multiome/download_manifest.tsv` 또는 `.md`에 source, URL, accession/run, file path, size, checksum, date, genome build, annotation source를 기록한다. + +## 출력 형식 +```markdown +## Download Plan +- Dataset: +- Official source: +- Access date: +- Files to download: +- Local paths: +- Genome build / annotation: +- Checksums: +- Verification: +- Preprocessing handoff: +- Open issues: +``` + +## 주의할 점 +- donor, developmental stage, brain region metadata가 lag modeling confounder가 될 수 있으므로 다운로드 단계부터 분리해서 기록한다. +- controlled-access 파일이면 인증 절차와 접근 불가 파일을 명확히 남긴다. diff --git a/skills/human-brain-multiome/download/agents/openai.yaml b/skills/human-brain-multiome/download/agents/openai.yaml new file mode 100644 index 0000000..e57033d --- /dev/null +++ b/skills/human-brain-multiome/download/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human Brain Multiome Download" + short_description: "GSE162170 human brain multiome 데이터 다운로드와 manifest 작성을 준비합니다." + default_prompt: "GSE162170 human brain multiome 데이터 다운로드 plan을 한국어로 작성해줘. GEO/SRA, donor/stage/region metadata, access restriction, checksum, preprocessing handoff를 포함해줘." diff --git a/skills/human-brain-multiome/model/SKILL.md b/skills/human-brain-multiome/model/SKILL.md new file mode 100644 index 0000000..43e806d --- /dev/null +++ b/skills/human-brain-multiome/model/SKILL.md @@ -0,0 +1,41 @@ +--- +name: human-brain-multiome-model +description: Model gene-specific activation lag and shutdown lag in the human brain multi-ome GSE162170 dataset. +--- + +# Human Brain Multiome Model + +## 목표 +GSE162170 human developing brain multiome에서 cell type 또는 lineage별 chromatin/RNA timing 차이를 고려해 gene-specific lag structure를 추정한다. + +## 입력 +- 전처리된 human RNA/ATAC multiome object. +- donor, brain region, developmental stage, cell type metadata. +- pseudotime 또는 developmental ordering. +- gene-level regulatory features와 timing estimates. + +## 작업 절차 +1. preprocessing output의 donor/stage/region confounding을 확인한다. +2. lineage 또는 cell type별 time axis를 정의한다. +3. gene별 activation lag과 shutdown lag을 계산한다. +4. donor 또는 batch effect를 고려한 model specification을 정한다. +5. baseline epigenomic features로 continuous lag 또는 short/long class를 예측한다. +6. held-out donor, held-out lineage, held-out brain region evaluation을 우선 고려한다. + +## 출력 형식 +```markdown +## Model Plan +- Dataset: +- Time axis: +- Lag definition: +- Features: +- Model: +- Evaluation: +- Outputs: +- Limitations: +``` + +## 주의할 점 +- human developmental data에서는 donor/stage/region 효과를 lag로 오해하지 않도록 한다. +- cross-species 비교를 한다면 mouse dataset과 annotation mapping 기준을 별도로 기록한다. + diff --git a/skills/human-brain-multiome/model/agents/openai.yaml b/skills/human-brain-multiome/model/agents/openai.yaml new file mode 100644 index 0000000..19339b9 --- /dev/null +++ b/skills/human-brain-multiome/model/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human Brain Multiome Model" + short_description: "GSE162170 human brain lag 모델을 설계합니다." + default_prompt: "Human brain multiome GSE162170 dataset에서 activation lag과 shutdown lag을 추정하고 예측하는 model plan을 한국어로 작성해줘." diff --git a/skills/human-brain-multiome/preprocessing/SKILL.md b/skills/human-brain-multiome/preprocessing/SKILL.md new file mode 100644 index 0000000..01951b9 --- /dev/null +++ b/skills/human-brain-multiome/preprocessing/SKILL.md @@ -0,0 +1,51 @@ +--- +name: human-brain-multiome-preprocessing +description: Preprocess the human brain multi-ome dataset GSE162170 for gene-specific epigenomic lag analysis. Use when Codex needs to inspect, normalize, annotate, integrate, or prepare fetal/developing human brain multiome inputs. +--- + +# Human Brain Multiome Preprocessing + +## Dataset +- Name: Human brain multi-ome +- Accession: GSE162170 +- Biology: fetal / developing human brain +- Data type: human multiome +- Main use: baseline human developmental dataset for gene-specific epigenomic lag analysis. + +## 목표 +GSE162170 human brain multiome 데이터를 lag modeling에 필요한 RNA/ATAC, cell type, developmental trajectory, regulatory feature 형태로 정리한다. + +## 우선 확인 항목 +- GSE162170 원본 또는 processed file 위치. +- human genome build와 gene annotation source. +- donor, developmental stage, brain region, batch metadata. +- RNA matrix, ATAC fragments/peak matrix, peak annotation. +- cell type, lineage, pseudotime 또는 developmental ordering. +- donor/batch correction 필요성. + +## 작업 절차 +1. `data/human-brain-multiome/` 또는 사용자가 지정한 입력 경로를 확인한다. +2. accession, portal URL, processed/raw 여부를 기록한다. +3. donor, region, stage, batch metadata를 분리해서 정리한다. +4. RNA/ATAC modality pairing과 QC를 확인한다. +5. promoter/enhancer feature와 peak-to-gene linkage를 human annotation 기준으로 만든다. +6. trajectory 또는 developmental axis 정의를 기록한다. +7. 산출물은 `work/human-brain-multiome/` 또는 `results/human-brain-multiome/` 아래에 저장한다. + +## 출력 형식 +```markdown +## Preprocessing Plan +- Dataset: +- Input files: +- Metadata checked: +- QC criteria: +- Genome build / annotation: +- Time axis: +- Outputs: +- Open issues: +``` + +## 주의할 점 +- donor, region, developmental stage confounding을 모델링 전에 확인한다. +- human gene annotation version을 명확히 남긴다. + diff --git a/skills/human-brain-multiome/preprocessing/agents/openai.yaml b/skills/human-brain-multiome/preprocessing/agents/openai.yaml new file mode 100644 index 0000000..9a82a6d --- /dev/null +++ b/skills/human-brain-multiome/preprocessing/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human Brain Multiome Preprocessing" + short_description: "GSE162170 human brain multiome 전처리를 준비합니다." + default_prompt: "Human brain multiome GSE162170 데이터의 preprocessing plan을 한국어로 작성해줘. donor, brain region, developmental stage, QC, annotation, output을 포함해줘." diff --git a/skills/human-brain-multiome/visualization/SKILL.md b/skills/human-brain-multiome/visualization/SKILL.md new file mode 100644 index 0000000..7e65bd5 --- /dev/null +++ b/skills/human-brain-multiome/visualization/SKILL.md @@ -0,0 +1,36 @@ +--- +name: human-brain-multiome-visualization +description: Visualize preprocessing, lag estimates, model outputs, and developmental interpretation for the human brain multi-ome GSE162170 dataset. +--- + +# Human Brain Multiome Visualization + +## 목표 +Human brain multiome 분석 결과를 donor/stage/region/cell type 구조, developmental trajectory, gene-specific lag, model performance 관점에서 시각화한다. + +## 우선 Figure +- UMAP with cell type, donor, developmental stage, brain region. +- QC and batch summary. +- lineage별 pseudotime trajectory. +- chromatin/RNA timing scatter. +- activation lag/shutdown lag distribution by lineage. +- model performance by held-out donor or lineage. +- representative neurodevelopmental genes dynamics. + +## 작업 절차 +1. donor, region, stage가 Figure에서 어떻게 표시되는지 명시한다. +2. pseudotime 또는 developmental stage axis를 혼동하지 않게 caption을 작성한다. +3. model performance plot은 split 기준을 함께 표시한다. +4. biological interpretation은 developmental lineage별로 분리한다. + +## 출력 형식 +```markdown +## Visualization Plan +- Dataset: +- Figures: +- Required inputs: +- Aesthetic rules: +- Captions: +- Interpretation notes: +``` + diff --git a/skills/human-brain-multiome/visualization/agents/openai.yaml b/skills/human-brain-multiome/visualization/agents/openai.yaml new file mode 100644 index 0000000..9ece0f0 --- /dev/null +++ b/skills/human-brain-multiome/visualization/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human Brain Multiome Visualization" + short_description: "GSE162170 human brain 결과 시각화를 설계합니다." + default_prompt: "Human brain multiome 분석 결과의 visualization plan을 한국어로 작성해줘. donor/stage/region, trajectory, lag distribution, model performance figure를 포함해줘." diff --git a/skills/human-hspc-10x-multiome/download/SKILL.md b/skills/human-hspc-10x-multiome/download/SKILL.md new file mode 100644 index 0000000..9d371d1 --- /dev/null +++ b/skills/human-hspc-10x-multiome/download/SKILL.md @@ -0,0 +1,57 @@ +--- +name: human-hspc-10x-multiome-download +description: Download or register the human HSPC 10x Multiome dataset GSE209878 for gene-specific epigenomic lag analysis. Use when Codex needs to find official data sources, fetch raw or processed files, verify files, or create a download manifest before preprocessing. +--- + +# Human HSPC 10x Multiome Download + +## Dataset +- Name: Human HSPC 10x Multiome +- Accession: GSE209878 +- Biology: hematopoietic stem/progenitor state +- Data type: human 10x multiome +- Main use: baseline human hematopoietic dataset for gene-specific lag analysis. + +## 목표 +GSE209878 human HSPC 10x Multiome 데이터를 GEO/SRA, 원 논문 supplement, 또는 공식 data portal에서 확인하고, HSPC subpopulation과 lineage metadata를 보존한 다운로드 manifest를 만든다. + +## 우선 확인 항목 +- GEO Series GSE209878, linked SRA runs, supplementary files, 원 논문/portal URL. +- 사용 조건, citation, download date. +- human genome build와 gene annotation source. +- donor/sample/batch metadata, HSPC subpopulation, lineage annotation. +- RNA feature-barcode matrix, ATAC fragments/peak matrix, peak annotation, cell metadata. +- raw FASTQ 재처리가 필요한지, processed matrix/object로 충분한지. + +## 작업 절차 +1. 공식 출처를 확인하고 accession, URL, access date를 기록한다. +2. raw FASTQ/SRA, 10x output, processed object, metadata 파일을 분리해 받을 파일 목록을 만든다. +3. `data/human-hspc-10x-multiome/raw/`, `data/human-hspc-10x-multiome/processed/`, `metadata/human-hspc-10x-multiome/` 경로를 사용한다. +4. donor/sample/batch/run mapping을 먼저 저장하고, lineage 또는 HSPC subpopulation metadata가 어느 파일에 있는지 표시한다. +5. provider checksum 또는 local sha256 checksum을 manifest에 남긴다. +6. 다운로드 후 파일 크기, 압축 무결성, matrix/object shape, barcode 수, metadata columns 일부를 확인한다. +7. `metadata/human-hspc-10x-multiome/download_manifest.tsv` 또는 `.md`에 source, URL, accession/run, file path, size, checksum, date, genome build, annotation source를 기록한다. + +## 출력 형식 +```markdown +## Download Plan +- Dataset: +- Official source: +- Access date: +- Files to download: +- Local paths: +- Genome build / annotation: +- Checksums: +- Verification: +- Preprocessing handoff: +- Open issues: +``` + +## 주의할 점 +- HSPC lineage commitment timing을 분석하려면 donor/sample/batch와 lineage labels를 분리해서 보존한다. +- 10x reference와 논문 processed annotation이 다른 경우 둘 다 manifest에 기록한다. + +## ▶ 우리 실행 구현 (kkkim-pipeline) +- `pipeline/hspc-velocity-benchmark/scripts/download_data.sh` — GSE209878 재현 다운로드 (MV-1=day0, MV-2=day7) +- `pipeline/hspc-velocity-benchmark/download_manifest.tsv` — sha256 + 출처 +- `pipeline/hspc-velocity-benchmark/P0_provenance.md` — provenance/사전체크 diff --git a/skills/human-hspc-10x-multiome/download/agents/openai.yaml b/skills/human-hspc-10x-multiome/download/agents/openai.yaml new file mode 100644 index 0000000..6c21950 --- /dev/null +++ b/skills/human-hspc-10x-multiome/download/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human HSPC 10x Download" + short_description: "GSE209878 human HSPC 10x Multiome 데이터 다운로드와 manifest 작성을 준비합니다." + default_prompt: "GSE209878 human HSPC 10x Multiome 데이터 다운로드 plan을 한국어로 작성해줘. GEO/SRA, raw/processed 파일, donor/sample/batch metadata, checksum, preprocessing handoff를 포함해줘." diff --git a/skills/human-hspc-10x-multiome/model/SKILL.md b/skills/human-hspc-10x-multiome/model/SKILL.md new file mode 100644 index 0000000..7209c1a --- /dev/null +++ b/skills/human-hspc-10x-multiome/model/SKILL.md @@ -0,0 +1,46 @@ +--- +name: human-hspc-10x-multiome-model +description: Model gene-specific activation lag and shutdown lag in the human HSPC 10x Multiome GSE209878 dataset. +--- + +# Human HSPC 10x Multiome Model + +## 목표 +GSE209878 human HSPC 10x Multiome에서 hematopoietic lineage commitment에 따른 gene-specific activation/shutdown lag을 추정하고, baseline chromatin features가 response timing을 설명하는지 모델링한다. + +## 입력 +- 전처리된 human HSPC RNA/ATAC multiome object. +- HSPC subpopulation, lineage, pseudotime annotation. +- gene-level accessibility, motif, promoter/enhancer, peak-to-gene features. +- chromatin/RNA timing estimates. + +## 작업 절차 +1. lineage별 pseudotime root와 direction을 확인한다. +2. gene별 chromatin opening/closing과 transcription onset/shutdown timing을 추정한다. +3. activation lag과 shutdown lag을 계산한다. +4. lineage commitment별 lag distribution을 비교한다. +5. baseline epigenomic features로 lag score를 예측한다. +6. held-out lineage 또는 held-out subpopulation 기준으로 generalization을 평가한다. + +## 출력 형식 +```markdown +## Model Plan +- Dataset: +- Time axis: +- Lag definition: +- Features: +- Model: +- Evaluation: +- Outputs: +- Limitations: +``` + +## 주의할 점 +- HSPC differentiation branch별 timing을 하나의 global pseudotime으로 강제로 합치지 않는다. +- rare lineage의 uncertainty를 별도로 표시한다. + + +## ▶ 우리 실행 구현 (kkkim-pipeline) +- `pipeline/hspc-velocity-benchmark/DESIGN.md` — velocity method head-to-head 벤치마크 = model 단계의 **"어떤 method로 lag를 추정할지" method-selection** (MultiVelo/MultiVeloVAE/MoFlow/CRAK-Velo + RNA-only floor) +- `pipeline/hspc-velocity-benchmark/REVIEW-methodologist-2026-06-13.md` — 설계 adversarial 검토 +- env: `env/velo-mv.yml`(MultiVelo+scVelo), `env/velo-torch.yml`, `env/velo-tf.yml` diff --git a/skills/human-hspc-10x-multiome/model/agents/openai.yaml b/skills/human-hspc-10x-multiome/model/agents/openai.yaml new file mode 100644 index 0000000..6ff05ec --- /dev/null +++ b/skills/human-hspc-10x-multiome/model/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human HSPC 10x Model" + short_description: "GSE209878 human HSPC lag 모델을 설계합니다." + default_prompt: "Human HSPC 10x Multiome GSE209878 dataset에서 activation lag과 shutdown lag을 추정하고 예측하는 model plan을 한국어로 작성해줘." diff --git a/skills/human-hspc-10x-multiome/preprocessing/SKILL.md b/skills/human-hspc-10x-multiome/preprocessing/SKILL.md new file mode 100644 index 0000000..14bb9f7 --- /dev/null +++ b/skills/human-hspc-10x-multiome/preprocessing/SKILL.md @@ -0,0 +1,56 @@ +--- +name: human-hspc-10x-multiome-preprocessing +description: Preprocess the human HSPC 10x Multiome dataset GSE209878 for gene-specific epigenomic lag analysis. Use when Codex needs to inspect, normalize, annotate, integrate, or prepare hematopoietic stem/progenitor multiome inputs. +--- + +# Human HSPC 10x Multiome Preprocessing + +## Dataset +- Name: Human HSPC 10x Multiome +- Accession: GSE209878 +- Biology: hematopoietic stem/progenitor state +- Data type: human 10x multiome +- Main use: baseline human hematopoietic dataset for gene-specific lag analysis. + +## 목표 +GSE209878 human HSPC 10x Multiome 데이터를 hematopoietic lineage와 progenitor differentiation timing 분석에 맞게 전처리한다. + +## 우선 확인 항목 +- GSE209878 원본 또는 processed file 위치. +- human genome build와 gene annotation source. +- RNA matrix, ATAC fragments/peak matrix, peak annotation. +- cell type, HSPC subpopulation, lineage commitment, pseudotime annotation. +- donor/sample/batch metadata. +- hematopoietic lineage별 충분한 cell count. + +## 작업 절차 +1. `data/human-hspc-10x-multiome/` 또는 사용자가 지정한 입력 경로를 확인한다. +2. accession, processed/raw 여부, metadata source를 기록한다. +3. RNA/ATAC modality pairing과 QC를 확인한다. +4. HSPC subpopulation과 lineage annotation을 정리한다. +5. promoter/enhancer accessibility와 peak-to-gene linkage feature를 만든다. +6. lineage commitment pseudotime 또는 ordering을 확인한다. +7. 산출물은 `work/human-hspc-10x-multiome/` 또는 `results/human-hspc-10x-multiome/` 아래에 저장한다. + +## 출력 형식 +```markdown +## Preprocessing Plan +- Dataset: +- Input files: +- Metadata checked: +- QC criteria: +- Genome build / annotation: +- Time axis: +- Outputs: +- Open issues: +``` + +## 주의할 점 +- lineage commitment 방향과 pseudotime root를 명확히 기록한다. +- rare population은 filtering으로 사라지지 않도록 기준을 따로 검토한다. + + +## ▶ 우리 실행 구현 (kkkim-pipeline) +- `pipeline/hspc-velocity-benchmark/scripts/p1_build.py` — 통일 전처리(공통 branch): GEX/ATAC 분리, spliced/unspliced 병합, timepoint 라벨, method-agnostic Leiden +- `pipeline/hspc-velocity-benchmark/scripts/check_data.py` — 산출물 검증 +- `pipeline/hspc-velocity-benchmark/P1_README.md`, `env/scv-preprocess.yml` diff --git a/skills/human-hspc-10x-multiome/preprocessing/agents/openai.yaml b/skills/human-hspc-10x-multiome/preprocessing/agents/openai.yaml new file mode 100644 index 0000000..4d397fa --- /dev/null +++ b/skills/human-hspc-10x-multiome/preprocessing/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human HSPC 10x Preprocessing" + short_description: "GSE209878 human HSPC 10x Multiome 전처리를 준비합니다." + default_prompt: "Human HSPC 10x Multiome GSE209878 데이터의 preprocessing plan을 한국어로 작성해줘. HSPC subpopulation, lineage, QC, annotation, output을 포함해줘." diff --git a/skills/human-hspc-10x-multiome/visualization/SKILL.md b/skills/human-hspc-10x-multiome/visualization/SKILL.md new file mode 100644 index 0000000..3a188d7 --- /dev/null +++ b/skills/human-hspc-10x-multiome/visualization/SKILL.md @@ -0,0 +1,39 @@ +--- +name: human-hspc-10x-multiome-visualization +description: Visualize preprocessing, lag estimates, model outputs, and hematopoietic lineage interpretation for the human HSPC 10x Multiome GSE209878 dataset. +--- + +# Human HSPC 10x Multiome Visualization + +## 목표 +Human HSPC 10x Multiome 분석 결과를 HSPC subpopulation, lineage commitment trajectory, gene-specific lag, model performance 관점에서 시각화한다. + +## 우선 Figure +- UMAP with HSPC subpopulation and lineage labels. +- QC summary by sample/batch. +- lineage commitment pseudotime plot. +- activation lag/shutdown lag distribution by lineage. +- representative hematopoietic regulator genes dynamics. +- predicted vs observed lag and feature importance. +- uncertainty or missingness summary. + +## 작업 절차 +1. lineage별 trajectory와 pseudotime root를 Figure caption에 명시한다. +2. rare population은 별도 panel 또는 annotation으로 보존한다. +3. representative gene plot은 accessibility와 RNA dynamics를 함께 보여준다. +4. model performance는 split 기준과 lineage composition을 함께 표시한다. + +## 출력 형식 +```markdown +## Visualization Plan +- Dataset: +- Figures: +- Required inputs: +- Aesthetic rules: +- Captions: +- Interpretation notes: +``` + + +## ▶ 우리 실행 구현 (kkkim-pipeline) +- (예정) P5 결과 시각화 — lag 분포(lineage별), method concordance, UMAP/trajectory. design/presentation은 이 단계로 통합. diff --git a/skills/human-hspc-10x-multiome/visualization/agents/openai.yaml b/skills/human-hspc-10x-multiome/visualization/agents/openai.yaml new file mode 100644 index 0000000..9d0b1e2 --- /dev/null +++ b/skills/human-hspc-10x-multiome/visualization/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "Human HSPC 10x Visualization" + short_description: "GSE209878 human HSPC 결과 시각화를 설계합니다." + default_prompt: "Human HSPC 10x Multiome 분석 결과의 visualization plan을 한국어로 작성해줘. lineage, pseudotime, lag distribution, representative genes figure를 포함해줘." diff --git a/skills/share-seq-mouse-skin/download/SKILL.md b/skills/share-seq-mouse-skin/download/SKILL.md new file mode 100644 index 0000000..4d1c971 --- /dev/null +++ b/skills/share-seq-mouse-skin/download/SKILL.md @@ -0,0 +1,52 @@ +--- +name: share-seq-mouse-skin-download +description: Download or register the SHARE-seq mouse skin dataset GSE140203 for gene-specific epigenomic lag analysis. Use when Codex needs to find official data sources, fetch raw or processed files, verify files, or create a download manifest before preprocessing. +--- + +# SHARE-seq Mouse Skin Download + +## Dataset +- Name: SHARE-seq mouse skin +- Accession: GSE140203 +- Biology: mouse skin differentiation +- Data type: paired chromatin + RNA +- Main use: baseline dataset for chromatin/RNA timing during differentiation. + +## 목표 +GSE140203 SHARE-seq mouse skin 데이터를 GEO/SRA, 논문 supplement, 또는 공식 portal에서 확인하고, lag modeling에 필요한 raw/processed 입력을 재현 가능하게 다운로드하거나 기존 파일을 등록한다. + +## 우선 확인 항목 +- GEO Series GSE140203, linked SRA runs, supplementary files, 원 논문/portal URL. +- 사용 조건, citation, download date. +- genome build와 gene annotation source. +- RNA matrix, chromatin accessibility matrix, peak annotation, barcode pairing 정보. +- cell type, differentiation stage, pseudotime 또는 lineage metadata 제공 여부. +- raw FASTQ 재처리가 필요한지, processed object로 충분한지. + +## 작업 절차 +1. GEO와 원 논문/portal을 공식 출처로 확인하고 accession, URL, access date를 기록한다. +2. raw FASTQ/SRA와 processed supplementary file을 분리해서 받을 파일 목록을 만든다. +3. `data/share-seq-mouse-skin/raw/`, `data/share-seq-mouse-skin/processed/`, `metadata/share-seq-mouse-skin/` 경로를 사용한다. +4. SRA 다운로드는 가능하면 run table을 먼저 저장하고, sample/library/run mapping을 manifest에 남긴다. +5. provider checksum이 있으면 검증한다. 없으면 local sha256 checksum을 생성한다. +6. 다운로드 후 압축 무결성, 일부 record, matrix dimensions, barcode 수를 확인한다. +7. `metadata/share-seq-mouse-skin/download_manifest.tsv` 또는 `.md`에 source, URL, accession/run, file path, size, checksum, date, genome build, annotation source를 기록한다. + +## 출력 형식 +```markdown +## Download Plan +- Dataset: +- Official source: +- Access date: +- Files to download: +- Local paths: +- Genome build / annotation: +- Checksums: +- Verification: +- Preprocessing handoff: +- Open issues: +``` + +## 주의할 점 +- SHARE-seq는 modality pairing 정보가 핵심이므로 barcode mapping 파일 또는 processed object metadata를 우선 확보한다. +- SRA run 이름만으로 biological sample을 해석하지 말고 GEO sample metadata와 대조한다. diff --git a/skills/share-seq-mouse-skin/download/agents/openai.yaml b/skills/share-seq-mouse-skin/download/agents/openai.yaml new file mode 100644 index 0000000..c08e9c0 --- /dev/null +++ b/skills/share-seq-mouse-skin/download/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "SHARE-seq Mouse Skin Download" + short_description: "GSE140203 SHARE-seq mouse skin 데이터 다운로드와 manifest 작성을 준비합니다." + default_prompt: "GSE140203 SHARE-seq mouse skin 데이터 다운로드 plan을 한국어로 작성해줘. GEO/SRA, supplementary files, raw/processed 선택, checksum, barcode pairing, preprocessing handoff를 포함해줘." diff --git a/skills/share-seq-mouse-skin/model/SKILL.md b/skills/share-seq-mouse-skin/model/SKILL.md new file mode 100644 index 0000000..48c4773 --- /dev/null +++ b/skills/share-seq-mouse-skin/model/SKILL.md @@ -0,0 +1,41 @@ +--- +name: share-seq-mouse-skin-model +description: Model gene-specific activation lag and shutdown lag in the SHARE-seq mouse skin GSE140203 dataset. +--- + +# SHARE-seq Mouse Skin Model + +## 목표 +SHARE-seq mouse skin differentiation에서 gene-specific chromatin/RNA lag structure를 추정하고, skin lineage 또는 differentiation state별 lag 차이를 모델링한다. + +## 입력 +- 전처리된 paired RNA/chromatin object. +- differentiation pseudotime 또는 lineage annotation. +- gene-level accessibility features, promoter/enhancer features, peak-to-gene linkage. +- timing estimate 또는 MultiVelo/MoFlow-style output. + +## 작업 절차 +1. preprocessing output의 modality pairing과 pseudotime direction을 확인한다. +2. gene별 chromatin opening/closing과 transcription onset/shutdown timing을 추정한다. +3. activation lag과 shutdown lag을 계산하고 confidence를 남긴다. +4. skin lineage별로 lag distribution을 비교한다. +5. baseline feature로 short/long lag 또는 continuous lag score를 예측한다. +6. held-out lineage 또는 cell state 기준으로 generalization을 평가한다. + +## 출력 형식 +```markdown +## Model Plan +- Dataset: +- Time axis: +- Lag definition: +- Features: +- Model: +- Evaluation: +- Outputs: +- Limitations: +``` + +## 주의할 점 +- SHARE-seq sparsity 때문에 gene filtering과 confidence threshold를 명시한다. +- lineage별 sampling imbalance가 model evaluation에 미치는 영향을 확인한다. + diff --git a/skills/share-seq-mouse-skin/model/agents/openai.yaml b/skills/share-seq-mouse-skin/model/agents/openai.yaml new file mode 100644 index 0000000..fa1911e --- /dev/null +++ b/skills/share-seq-mouse-skin/model/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "SHARE-seq Mouse Skin Model" + short_description: "GSE140203 mouse skin lag 모델을 설계합니다." + default_prompt: "SHARE-seq mouse skin dataset에서 activation lag과 shutdown lag을 추정하고 예측하는 model plan을 한국어로 작성해줘." diff --git a/skills/share-seq-mouse-skin/preprocessing/SKILL.md b/skills/share-seq-mouse-skin/preprocessing/SKILL.md new file mode 100644 index 0000000..8363492 --- /dev/null +++ b/skills/share-seq-mouse-skin/preprocessing/SKILL.md @@ -0,0 +1,51 @@ +--- +name: share-seq-mouse-skin-preprocessing +description: Preprocess the SHARE-seq mouse skin dataset GSE140203 for gene-specific epigenomic lag analysis. Use when Codex needs to inspect, normalize, annotate, integrate, or prepare paired chromatin and RNA inputs from mouse skin differentiation. +--- + +# SHARE-seq Mouse Skin Preprocessing + +## Dataset +- Name: SHARE-seq mouse skin +- Accession: GSE140203 +- Biology: mouse skin differentiation +- Data type: paired chromatin + RNA +- Main use: baseline dataset for chromatin/RNA timing during differentiation. + +## 목표 +SHARE-seq mouse skin 데이터를 lag modeling에 필요한 paired chromatin/RNA representation으로 정리한다. mouse skin differentiation trajectory, lineage/cell state annotation, gene-level accessibility feature를 함께 검증한다. + +## 우선 확인 항목 +- GSE140203 원본 또는 processed file 위치. +- genome build와 gene annotation source. +- RNA matrix, chromatin accessibility matrix, peak annotation. +- paired modality barcode mapping. +- skin lineage, differentiation stage, pseudotime annotation. +- SHARE-seq 특이적인 sparsity와 batch structure. + +## 작업 절차 +1. `data/share-seq-mouse-skin/` 또는 사용자가 지정한 입력 경로를 확인한다. +2. accession, download source, processed/raw 여부를 기록한다. +3. RNA와 chromatin modality의 cell matching을 확인한다. +4. QC와 filtering 기준을 modality별로 분리한다. +5. peak-to-gene linkage와 promoter/enhancer feature를 만든다. +6. pseudotime 또는 differentiation axis를 확인하고 방향성을 기록한다. +7. 산출물은 `work/share-seq-mouse-skin/` 또는 `results/share-seq-mouse-skin/` 아래에 저장한다. + +## 출력 형식 +```markdown +## Preprocessing Plan +- Dataset: +- Input files: +- Metadata checked: +- QC criteria: +- Genome build / annotation: +- Time axis: +- Outputs: +- Open issues: +``` + +## 주의할 점 +- SHARE-seq processed object의 annotation이 어떤 genome build에 맞는지 확인한다. +- differentiation pseudotime 방향이 biological maturation과 일치하는지 점검한다. + diff --git a/skills/share-seq-mouse-skin/preprocessing/agents/openai.yaml b/skills/share-seq-mouse-skin/preprocessing/agents/openai.yaml new file mode 100644 index 0000000..c8912f0 --- /dev/null +++ b/skills/share-seq-mouse-skin/preprocessing/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "SHARE-seq Mouse Skin Preprocessing" + short_description: "GSE140203 SHARE-seq mouse skin 전처리를 준비합니다." + default_prompt: "SHARE-seq mouse skin GSE140203 데이터의 preprocessing plan을 한국어로 작성해줘. paired chromatin/RNA, QC, annotation, pseudotime, output을 포함해줘." diff --git a/skills/share-seq-mouse-skin/visualization/SKILL.md b/skills/share-seq-mouse-skin/visualization/SKILL.md new file mode 100644 index 0000000..d4fdeaa --- /dev/null +++ b/skills/share-seq-mouse-skin/visualization/SKILL.md @@ -0,0 +1,36 @@ +--- +name: share-seq-mouse-skin-visualization +description: Visualize preprocessing, lag estimates, model outputs, and differentiation interpretation for the SHARE-seq mouse skin dataset. +--- + +# SHARE-seq Mouse Skin Visualization + +## 목표 +SHARE-seq mouse skin 분석 결과를 differentiation trajectory, paired chromatin/RNA dynamics, lineage-specific lag, feature predictor 성능 중심으로 시각화한다. + +## 우선 Figure +- UMAP 또는 trajectory plot with skin cell state. +- RNA/chromatin QC summary. +- pseudotime별 accessibility/RNA dynamics. +- activation lag/shutdown lag distribution. +- lineage 또는 cell state별 lag comparison. +- predicted vs observed lag. +- representative genes and regulatory peaks plot. + +## 작업 절차 +1. Figure별 input file과 preprocessing/model version을 기록한다. +2. pseudotime direction과 lineage label을 caption에 명시한다. +3. paired chromatin/RNA plot에서는 smoothing 방법과 window를 기록한다. +4. confidence 낮은 gene은 별도 색상 또는 필터로 처리한다. + +## 출력 형식 +```markdown +## Visualization Plan +- Dataset: +- Figures: +- Required inputs: +- Aesthetic rules: +- Captions: +- Interpretation notes: +``` + diff --git a/skills/share-seq-mouse-skin/visualization/agents/openai.yaml b/skills/share-seq-mouse-skin/visualization/agents/openai.yaml new file mode 100644 index 0000000..036d7d6 --- /dev/null +++ b/skills/share-seq-mouse-skin/visualization/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "SHARE-seq Mouse Skin Visualization" + short_description: "GSE140203 mouse skin 결과 시각화를 설계합니다." + default_prompt: "SHARE-seq mouse skin 분석 결과의 visualization plan을 한국어로 작성해줘. trajectory, lineage-specific lag, representative genes figure를 포함해줘." From 65eda13313f9e5564edfe9dc3aec7dbf25860ec0 Mon Sep 17 00:00:00 2001 From: Geon-Gyu LEE Date: Sun, 26 Jul 2026 19:43:53 +0900 Subject: [PATCH 9/9] =?UTF-8?q?harness:=20=EC=A0=88=EB=8C=80=20=ED=98=B8?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B2=BD=EB=A1=9C=20ignore=20=EC=9D=BC?= =?UTF-8?q?=EB=B0=98=ED=99=94=20=E2=80=94=20CI=EA=B0=80=20=EC=9E=A1?= =?UTF-8?q?=EC=9D=80=20=ED=99=98=EA=B2=BD=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?(BIOP01-66/73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI(GitHub runner)에서만 FAIL 이 났다. 로컬(우리 서버 컨테이너)에서는 PASS. 원인: CLAUDE.md:27 이 팀 공유 conda env 위치로 /opt/envs 를 인용하는데, runner 에는 그 경로가 없어 doctor 가 팬텀 경로로 판정했다. 이건 게이트의 오검이자, 동시에 게이트가 제 값을 한 사례다 — 문서에 박힌 환경 의존 절대경로는 우리 서버에서만 성립하고 다른 곳에서는 깨진다. (같은 종류를 3a86f6f "remove hardcoded absolute paths from agent/skill prompts" 에서 한번 정리한 적이 있고, 이건 그 뒤에 남은 잔여물이다.) - ignore 규칙 ^/dev/ → ^/ 로 일반화. 절대 호스트 경로는 리포 경로가 아니므로 팬텀 판정 대상이 아니다. 환경마다 결과가 달라지면 게이트를 신뢰할 수 없다. - 테스트 #17 추가 — 절대 호스트 경로가 팬텀으로 잡히지 않는지 고정. 18/18 통과. doctor: PASS (0 문제, 0 경고). 남는 판단(별건): CLAUDE.md:27 의 /opt/envs 인용 자체를 유지할지. 사실 기술이라 당장 틀린 문장은 아니지만, 문서가 특정 서버 레이아웃을 전제하는 것은 이식성 위험이다. conda run -n 안내로 충분한지 팀 확인 필요. --- harness.yaml | 3 ++- harness_after/harness.yaml | 3 ++- harness_after/tests/test_harness_doctor.py | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/harness.yaml b/harness.yaml index bd5b3f1..77d1c7d 100644 --- a/harness.yaml +++ b/harness.yaml @@ -107,7 +107,8 @@ path_reference_scan: ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" - - "^/dev/" + - "^/" # 절대 호스트 경로(/opt/envs, /dev/sda2 …) — 리포 경로가 아니다. + # 단, 이식성 위험이므로 문서에서 줄이는 편이 좋다(3a86f6f 참고). - "^kakyungkim/" - "^biospin/" - "^(MahmoodLab|paige-ai|LGAI-EXAONE|prov-gigapath)/" diff --git a/harness_after/harness.yaml b/harness_after/harness.yaml index bd5b3f1..77d1c7d 100644 --- a/harness_after/harness.yaml +++ b/harness_after/harness.yaml @@ -107,7 +107,8 @@ path_reference_scan: ignore: # 경로가 아닌 것(외부 repo·호스트/IP·모델 ID·버전 문자열) - "^https?://" - "^[0-9]+[.][0-9.]+$" - - "^/dev/" + - "^/" # 절대 호스트 경로(/opt/envs, /dev/sda2 …) — 리포 경로가 아니다. + # 단, 이식성 위험이므로 문서에서 줄이는 편이 좋다(3a86f6f 참고). - "^kakyungkim/" - "^biospin/" - "^(MahmoodLab|paige-ai|LGAI-EXAONE|prov-gigapath)/" diff --git a/harness_after/tests/test_harness_doctor.py b/harness_after/tests/test_harness_doctor.py index 5646c53..6fa3493 100644 --- a/harness_after/tests/test_harness_doctor.py +++ b/harness_after/tests/test_harness_doctor.py @@ -51,6 +51,7 @@ %(local_only)s ignore: - "^https?://" - "^upstream/" + - "^/" """ @@ -248,6 +249,16 @@ def test_undeclared_path_still_fails(self): self.assertEqual(code, 1, out) self.assertIn("skills/ROUTES.md", out) + # ---- 17. 절대 호스트 경로는 리포 경로가 아니므로 팬텀이 아니다 ---- + # CI(GitHub runner)에는 /opt/envs 가 없고 우리 서버에는 있다. + # 환경마다 결과가 달라지면 게이트를 믿을 수 없으므로 ignore 로 고정한다. + def test_absolute_host_path_ignored(self): + write(os.path.join(self.repo, "CLAUDE.md"), + "# test\n팀 공유 env 는 `/opt/envs` 에 있다.\n") + self.manifest() + code, out = self.run_doctor() + self.assertEqual(code, 0, "절대 호스트 경로를 팬텀으로 오검\n" + out) + class LiveRepoCase(unittest.TestCase): """실제 BIOP01 리포 회귀 — 한번 0으로 만든 팬텀이 다시 생기지 않는가.