스킬 모음
593377b 기준입니다.scientific-agent-skills는 생물학·화학·의학·물리·데이터 분석 등에 필요한 작업 절차를 AI 에이전트에게 전달하는 라이브러리입니다. 하나의 스킬에는 언제 사용할지, 무엇을 입력받을지, 어떤 검사를 거칠지, 어떤 코드를 호출할지가 들어 있습니다.
이 저장소에서 배우는 핵심은 전문 지식을 긴 설명으로 남기는 데서 나아가, 입력 조건과 검증 가능한 코드까지 묶는 방법입니다. 모델 자체를 학습시키는 코드보다 skills/<이름>/SKILL.md와 그 주변 파일이 중심입니다.
SKILL.md가 필수이고, references/·scripts/·assets/는 필요에 따라 붙습니다. 파일을 배치하는 것과 Python 패키지를 설치하는 것은 별개의 단계입니다.현미경을 쓸 줄 안다고 모든 표본을 올바르게 관찰하는 것은 아닙니다. 표본을 어떻게 준비하고, 어떤 조건에서 다시 측정하며, 어떤 수치를 믿을 수 있는지 알아야 합니다.
여기서 SKILL.md는 절차서, references/는 자세한 매뉴얼, scripts/는 반복 작업용 도구, tests/는 도구를 점검하는 검사대에 해당합니다. 에이전트 실행과 도구 사용 권한은 이를 읽는 호스트가 담당합니다.
예를 들어 “이 단일세포 RNA 데이터의 품질을 확인하고 군집을 나눠 줘”라는 요청을 생각해 봅시다. skills/scanpy/SKILL.md는 원본 카운트를 확인하고, 품질 검사·정규화·차원 축소·군집화로 이어지는 절차를 설명합니다. 반복되는 작업은 skills/scanpy/scripts/run_pipeline.py의 main()이 맡습니다.
사용자 요청
→ 호스트가 scanpy 스킬의 이름·설명을 바탕으로 선택
→ SKILL.md에서 입력 조건과 작업 순서 확인
→ 필요한 참고 문서와 보조 코드 읽기
→ 호스트의 허용된 도구로 분석 수행
→ 결과 파일과 검증 근거를 사용자에게 설명
이 흐름의 스킬 선택과 도구 호출은 호스트의 책임입니다. 저장소 루트의 plugin.json은 이름·버전·작성자 등을 선언하지만, 요청을 받아 작업을 배정하는 상시 실행 서버를 정의하지는 않습니다. 표준 호환성을 선언하는 것과 모든 호스트에서 같은 행동을 보장하는 것은 구분해야 합니다.
| 독자 | 관찰할 부분 | 배울 수 있는 것 |
|---|---|---|
| Python 입문자 | 좌표 변환·입력 검증 스크립트 | 작은 함수, 자료형, 오류 상태, CLI를 연결하는 방법 |
| 에이전트 개발자 | SKILL.md와 plugin.json | 모델 바깥에 절차적 지식을 배포하는 방법 |
| 연구·데이터 개발자 | Scanpy의 데이터 보존과 수치 테스트 | 실행 성공과 분석 타당성을 구별하는 방법 |
첫 학습 대상으로 genomic-coordinates가 적합합니다. 외부 패키지 없이 정수·문자열·자료형을 다루고, “첫 번째 항목을 0으로 셀까 1로 셀까”라는 익숙한 문제를 실제 파일 형식과 연결합니다.
2026-10-23 GitHub 기준 스타는 54,016개, 포크는 4,767개입니다. GitHub Trending Weekly 5위라는 선정 맥락과 함께 보면 관심의 크기를 보여 줍니다. 다만 이 수치만으로 연구 정확도나 생산성 향상률까지 알 수는 없습니다.
README는 프로젝트가 Claude Scientific Skills에서 Scientific Agent Skills로 이름을 바꾸었다고 설명합니다. 특정 클라이언트 이름을 벗고 Agent Skills 표준을 따르는 호스트를 대상으로 한다는 점이 확산에 유리합니다. 실제로 루트에는 Agent Plugins 1.0.0 스키마를 지정한 plugin.json이 있고, 스킬은 독립된 폴더로 배치되어 있습니다.
소스 구조에서 읽을 수 있는 인기 요인은 세 가지입니다. 첫째, 연구 도구의 사용법을 찾는 비용을 줄입니다. 둘째, 스킬별로 선택해 가져가기 쉽습니다. 셋째, 절차 설명에 보조 코드와 검사 조건이 붙습니다. 이는 구조를 근거로 한 해석이며, 트렌딩 순위 상승의 인과관계를 측정한 결과는 아닙니다.
skills/scanpy/scripts/_common.py의 prepare_counts()는 카운트의 수치 조건과 기록된 변환 이력을 검사해 잘못된 입력을 거부합니다. skills/genomic-coordinates/scripts/convert_coords.py의 convert_one()은 변환할 수 없는 구간을 억지로 정상 값으로 바꾸지 않고 상태로 돌려줍니다.
과학 코딩에서 재사용할 가치가 큰 부분은 정상 입력의 계산식뿐 아니라, 그 계산을 적용하면 안 되는 조건까지 명시한 코드입니다. 이 저장소는 그러한 조건을 문서와 함수 양쪽에 두는 사례를 제공합니다.
요리법에서 “180도로 20분 굽기”만 적으면 오븐의 예열 여부와 재료 크기를 놓치기 쉽습니다. 좋은 스킬은 조리 순서와 함께 전제 조건·중간 확인·실패했을 때의 판단을 적은 레시피에 가깝습니다.
비교 기준은 “어느 제품이 더 똑똑한가”보다 어떤 층을 맡는가입니다. 다음 표는 구조와 책임의 차이를 보여 줍니다. 각 제품의 최신 기능을 모두 비교한 성능표는 아닙니다.
| 접근 방식 | 주로 제공하는 것 | 이 저장소를 고를 이유·남는 일 |
|---|---|---|
| 범용 LLM 채팅 | 질문에 대한 설명과 코드 제안 | 반복되는 연구 절차를 파일로 고정할 수 있음. 모델의 해석과 결과 검토는 여전히 필요 |
| 과학 패키지 단독 사용 | Scanpy·RDKit 같은 계산 API | 도구 선택과 작업 순서까지 전달. 실제 계산 패키지는 별도로 준비 |
| MCP 서버 | 에이전트가 호출할 도구·데이터 연결 | 업무 절차를 함께 읽힐 수 있음. 외부 도구 연결 자체는 별도 책임 |
| 워크플로 프레임워크 | 실행 순서·상태·분기 제어 | 분야별 지식을 기존 실행기에 추가. 이 저장소에는 통합 실행 엔진이 없음 |
| 일반 스킬 모음 | 다양한 직무의 작업 지침 | 연구 도구와 데이터 의미에 집중. 모든 일반 개발 업무를 포괄하지 않음 |
| 소개 또는 인상 | 커밋 593377b에서 확인되는 범위 |
|---|---|
| 177개 스킬 | skills/의 직계 하위 폴더와 SKILL.md가 각각 177개로 일치 |
| 100개 이상 데이터베이스 | README 기준 전체 지원 범위. skills/database-lookup/SKILL.md는 80개를 안내하며, 전용 스킬·복수 DB 패키지가 범위를 더함 |
| 25만 명 이상 사용 | 프로젝트 소개의 채택 규모 주장. 코드나 테스트로 검증할 수 있는 수치는 아님 |
| 검증된 스킬 | 구조 검사·단위 테스트·일부 수치 계약이 존재. 모든 외부 API와 과학적 결론을 일괄 검증한다는 뜻은 아님 |
| 설치하면 과학 환경 완성 | 스킬 파일 설치와 과학 의존성 설치는 분리. uv sync도 모든 과학 패키지를 설치하지 않음 |
README의 2.72.0 변경 안내는 문서용 docx·pdf·pptx·xlsx 스킬 네 개가 더 이상 포함되지 않는다고 설명합니다. 이전 2.71.0 소개의 181개와 현재 177개의 차이는 이 맥락에서 읽어야 합니다. 개수가 바뀌었다는 이유만으로 기능 전체의 후퇴나 품질 향상을 단정할 수는 없습니다.
한 스킬이 여러 데이터베이스를 설명할 수 있고, 어떤 스킬은 외부 라이브러리 사용 지침만 제공합니다. 따라서 “177개”를 독립된 모델 177개나 실행 서비스 177개로 이해하면 구조를 잘못 읽게 됩니다.
루트에 웹 API 서버의 엔트리포인트는 없습니다. 실질적인 실행 코드는 개별 스킬의 Python CLI와 저장소 관리 도구에 분산되어 있습니다. 루트 pyproject.toml의 프로젝트 버전은 2.72.0, 관리 도구의 Python 요구 조건은 >=3.13입니다.
# pyproject.toml 발췌
[project]
name = "scientific-agent-skills"
version = "2.72.0"
requires-python = ">=3.13"
dependencies = [
"cisco-ai-skill-scanner>=2.0.12",
"pytest>=9.1.1",
"python-dotenv>=1.0.0",
]
| 의존성·설정 | 실제 선언 | 역할 |
|---|---|---|
| Python | >=3.13 | 저장소 관리·검증의 기준 인터프리터 |
| Cisco 검사기 | cisco-ai-skill-scanner>=2.0.12 | 스킬 문서와 코드의 위험 패턴 검사 |
| pytest | >=9.1.1 | 테스트 수집·실행·건너뛰기 관리 |
| python-dotenv | >=1.0.0 | 검사 도구에서 환경 설정 읽기 |
| jsonschema | 개발 그룹 >=4.26.0 | 플러그인 매니페스트 형식 검사 |
| skills-ref | 개발 그룹의 Git URL 참조 | Agent Skills 규격 검사. 특정 태그·커밋 핀은 없음 |
| pytest import | --import-mode=importlib | 테스트 폴더 이름이 실제 과학 패키지를 가리는 문제 방지 |
pytest>=9.1.1은 그 버전 이상을 허용합니다. scanpy==1.12.4는 정확히 그 버전을 요구합니다. 둘 다 버전 표기지만, 미래 설치에서 같은 환경을 재현하는 힘은 다릅니다. 직접 의존성만 고정해도 그 아래 간접 의존성까지 모두 고정되는 것은 아닙니다.tests/skill-requirements.toml에는 174개 스킬의 환경 항목이 있습니다. 이것은 174개를 한 환경에 설치하는 목록이 아니라, 테스트 실행기가 스킬마다 별도 환경을 만들 때 읽는 설정입니다. 모든 항목에 버전이 고정된 것은 아닙니다.
| 스킬 | 설정에 적힌 패키지·버전 | Python 해석 |
|---|---|---|
| scanpy | scanpy[leiden,skmisc]==1.12.4, anndata==0.13.4, harmonypy==2.0.2, bbknn==1.6.0 | 환경 기본값 3.13. 스킬 문서는 Python 3.12 이상 안내 |
| pydeseq2 | pydeseq2==0.5.4, anndata==0.13.4 | 환경에서 3.13 명시 |
| deepchem | deepchem==2.8.0, torch==2.14.1, transformers==5.18.0 등 | 해당 환경만 3.11 |
| opentrons-integration | opentrons==10.0.0 | 해당 환경만 3.12 |
| histolab | histolab==0.7.0, pooch, matplotlib | 해당 환경만 3.10 |
| genomic-coordinates | packages = [] | 보조 코드는 표준 라이브러리만 사용, 스킬 문서는 3.11 이상 요구 |
스킬 모음 전체의 Python 버전과 개별 분석에 필요한 Python 버전은 다르므로, 실행 환경은 선택한 스킬의 계약을 기준으로 정해야 합니다. 이 구분을 놓치면 “최신 Python을 깔았는데 설치가 실패한다”는 문제에 부딪힐 수 있습니다.
루트에는 package.json·Cargo.toml·go.mod·Dockerfile이 없습니다. 추적된 JavaScript는 두 파일·223줄이며, skills/fictiv/scripts/list_dropdown_options.js와 skills/fictiv/scripts/quote_state.js입니다. 이것을 저장소 전체의 웹 프론트엔드로 해석할 근거는 없습니다.
독자가 만나는 화면은 주로 에이전트 호스트의 UI와 GitHub의 Markdown 문서입니다. docs/skill-guides/와 docs/images/는 스킬을 설명하는 자료입니다. 별도 React 앱을 빌드해 스킬을 서비스하는 구조로 읽으면 실제 설계와 멀어집니다.
| 설정 파일 | 실제 값·도구 | 맡는 일 |
|---|---|---|
| .github/workflows/skill-tests.yml | ubuntu-latest, Python 3.13, actions/checkout@v6, astral-sh/setup-uv@v8.0.0 | 구조 계약 검사 후 일부 격리 테스트 실행 |
| .github/workflows/skill-spec-validation.yml | skills-ref validate와 추가 YAML 검사 | frontmatter 규격과 저장소 고유 규칙 검사 |
| .github/workflows/pr-skill-scan.yml | --fail-on HIGH | 조건을 만족하는 PR의 변경 스킬 검사 |
| .github/workflows/security-scan.yml | cron 0 9 * * 1, 기본 동시 작업 수 8 | 매주 월요일 09:00 UTC에 보고서 갱신 |
| .github/workflows/release.yml | softprops/action-gh-release@v2 | pyproject 버전에서 태그를 만들고 커밋 목록으로 릴리스 작성 |
.github/workflows/release.yml은 main의 pyproject.toml 변경 또는 수동 실행에 반응합니다. 버전을 읽어 v2.72.0 같은 태그 이름을 만들고, 같은 태그가 이미 있으면 생성을 건너뜁니다. 관리 코드와 문서 패키지에 맞춘 배포 자동화입니다.
.gitignore가 uv.lock을 제외하며, CI는 uv sync --python 3.13을 사용합니다. 따라서 최소 버전 선언과 Git 참조만으로 모든 설치가 동일해진다고 보장할 수 없습니다. 스킬별 버전 핀, 실제 해석된 환경, 외부 시스템 버전을 함께 기록해야 재현성을 더 높일 수 있습니다.
아래 도식에서 위쪽은 사용 경로, 아래쪽은 유지보수 경로입니다. 호스트가 스킬을 발견하고 필요한 파일을 읽습니다. 저장소의 테스트와 보안 검사기는 배포할 파일의 구조와 일부 동작을 확인합니다. 둘을 연결하되 같은 실행 흐름으로 혼동하지 않는 것이 출발점입니다.
이 구조의 장점은 지식·계산·검증의 경계를 파일로 드러내어, 한 부분을 읽거나 바꿀 때 확인할 범위를 좁힐 수 있다는 데 있습니다. 다만 폴더 경계 자체가 권한 격리나 보안 경계를 만들어 주지는 않습니다.
진입점은 짧게, 상세 내용은 밖으로라는 패턴입니다. 각 SKILL.md 앞의 YAML frontmatter에는 이름·설명·호환 조건·버전 등이 들어갑니다. 본문은 작업을 안내하고, 긴 설명은 references/로 연결합니다. 177개 중 176개 스킬에 참고 문서 폴더가 있습니다.
# skills/scanpy/SKILL.md의 일부 필드
name: scanpy
license: BSD-3-Clause
metadata:
version: "1.8"
last-reviewed: "2026-10-01"
upstream-version: "1.12.4"
skill-author: K-Dense Inc.
description은 “어떤 작업에 이 스킬을 쓸지”를 설명합니다. compatibility는 필요한 환경을 설명합니다. metadata.version은 스킬 문서·도구 묶음의 버전이고, upstream-version은 대상으로 삼은 외부 라이브러리 버전입니다. 위 예의 1.8과 1.12.4는 서로 다른 대상을 가리킵니다.
이 분리를 흔히 점진적 공개라고 부릅니다. 전체 매뉴얼을 한꺼번에 읽히는 대신 현재 작업에 필요한 설명을 따라갑니다. 실제 로딩 정책은 호스트가 구현하므로, 이 저장소만으로 토큰 사용량이나 선택 정확도를 측정할 수는 없습니다.
--- 사이에 쓰는 기계 판독용 정보입니다. 이름·환경·버전 같은 약속을 자동으로 점검할 수 있게 만듭니다. 본문을 잘 쓰는 것과 함께, 프로그램이 읽을 수 있는 조건을 유지하는 것이 중요합니다.이 설계의 검증 지점은 tests/_meta/test_repo_contract.py의 AgentPluginTests.test_skills_component_is_discoverable()입니다. 직계 하위 폴더의 SKILL.md 존재를 확인합니다. tests/_contract/structure.py의 frontmatter_problems()와 length_problems()는 문서 계약을 검사합니다. 현재 가장 긴 SKILL.md는 499줄입니다.
배울 점: 입력 문서가 커질 때 무작정 요약하기보다, 선택에 필요한 정보와 실행에 필요한 정보를 분리해 보세요. 단, 너무 잘게 나누면 링크 관리 비용이 생기므로 link_problems()처럼 내부 참조도 검사해야 합니다.
skills/genomic-coordinates/scripts/_common.py의 Convention은 @dataclass(frozen=True)로 정의되어 있습니다. 형식 이름, 시작 번호 base, 끝 제외 여부를 나타내는 half_open을 한 객체에 담고, 생성 뒤 필드의 재할당을 막습니다.
핵심은 아래 두 함수입니다. 입력을 0부터 시작하고 끝은 포함하지 않는 구간으로 바꾼 뒤, 목적 형식으로 되돌립니다. 형식 A와 B의 조합마다 별도 계산식을 만드는 부담을 줄입니다.
# skills/genomic-coordinates/scripts/_common.py 발췌
def to_canonical(conv: Convention, start: int, end: int) -> tuple[int, int]:
start0 = start - conv.base
end0 = end if conv.half_open else end - conv.base + 1
return start0, end0
def from_canonical(conv: Convention, start0: int, end0: int) -> tuple[int, int]:
start = start0 + conv.base
end = end0 if conv.half_open else end0 + conv.base - 1
return start, end
| 표현 | 같은 1개 위치의 표기 | 길이를 구하는 법 |
|---|---|---|
| BED / Python 구간 | [999, 1000) | 1000 - 999 = 1 |
| GFF의 포함 구간 | [1000, 1000] | 1000 - 1000 + 1 = 1 |
| 내부 기준 형식 | (999, 1000) | 어떤 입력 형식이든 end0 - start0 |
여러 나라의 화폐를 서로 직접 교환하는 표를 모두 만드는 대신, 하나의 기준 통화를 거치는 방식과 닮았습니다. 이 경우에는 가격 변동이 아니라 시작 번호와 끝 포함 규칙이 바뀝니다.
convert_coords.py의 convert_one()은 계산 결과에 status와 detail을 붙입니다. 길이 0인 BED 구간은 반열린 형식에서는 zero_length, 일반적인 포함 구간 변환에서는 unrepresentable로 보고합니다. 삽입 지점의 의미를 모르는 상태에서 길이 1인 구간으로 바꾸지 않습니다.
tests/genomic-coordinates/test_scripts.py에는 test_round_trip_through_canonical_is_identity(), test_length_is_convention_independent()가 있습니다. 특정 예제 하나뿐 아니라 왕복하면 원래 값으로 돌아온다는 성질을 검사합니다. 좌표 번호 변환은 서로 다른 참조 유전체 사이의 위치 이동인 liftover까지 해결하지는 않습니다.
Scanpy 보조 코드의 중심은 skills/scanpy/scripts/_common.py입니다. validate_counts()는 값이 유한하고 음수가 없으며 정수 값인지 확인하고, 기본 설정에서는 각 세포의 합계가 양수인지도 검사합니다. 희소 행렬이면 전체를 밀집 배열로 바꾸지 않고 저장된 matrix.data를 검사합니다.
정수처럼 생긴 값이라고 원본이라는 사실까지 증명되지는 않습니다. prepare_counts()는 선택한 카운트를 복사하여 adata.X와 adata.layers["counts"]에 둡니다. 원본 레이어를 지정하지 않은 상태에서 log1p 기록이 있거나 보관된 카운트와 X가 다르면, 레이어를 명시적으로 선택하도록 요구합니다.
normalize_hvg()의 기본값은 target_sum=1e4, n_top_genes=2000, flavor="seurat"입니다. seurat_v3 계열은 원본 카운트로 변동이 큰 유전자를 고르고, seurat 계열은 로그 정규화 뒤에 고릅니다. 같은 함수 호출 이름이라도 입력 표현에 따라 순서가 달라집니다.
# normalize_hvg()의 핵심 분기 발췌
count_flavor = flavor in {"seurat_v3", "seurat_v3_paper"}
if count_flavor:
sc.pp.highly_variable_genes(adata, layer="counts", n_top_genes=n_top_genes,
flavor=flavor, batch_key=batch_key)
sc.pp.normalize_total(adata, target_sum=target_sum)
sc.pp.log1p(adata)
if not count_flavor:
sc.pp.highly_variable_genes(adata, n_top_genes=n_top_genes,
flavor=flavor, batch_key=batch_key)
run_pipeline.py의 main()은 품질 검사 뒤 변동이 큰 유전자만 뽑은 work 객체로 PCA·이웃 그래프·군집화를 수행합니다. 이후 군집과 임베딩을 전체 유전자가 있는 객체로 옮깁니다. 계산에 쓴 부분집합 때문에 뒤의 유전자 비교 대상이 사라지는 문제를 줄이는 설계입니다.
이 계약은 tests/scanpy/test_numerical_contracts.py의 test_counts_and_raw_are_independent_and_normalization_is_numerically_correct()가 검사합니다. 밀집·희소 입력 모두에서 정규화 식을 비교하고, 스케일링 뒤에도 원본 카운트와 raw가 보존되는지 확인합니다. 생물학적 발견이 맞다는 검증과는 범위가 다릅니다.
여러 스킬이 skills/<이름>/scripts/_common.py 형태의 경로에 같은 이름의 모듈을 둡니다. 서로 다른 스킬의 테스트를 같은 Python 프로세스에 모으면 먼저 불러온 모듈을 다른 스킬에서도 참조할 수 있습니다. 실제 코드보다 우연히 잡힌 import 순서를 검사하는 셈입니다.
tests/conftest.py의 pytest_sessionstart()는 두 개 이상 스킬을 한 세션에서 수집하면 pytest.UsageError를 발생시킵니다. tests/run_all.py의 main()은 각 스킬을 subprocess.run()으로 분리하고, isolated_command()는 추가로 환경을 분리할 명령을 만듭니다.
# tests/run_all.py의 isolated_command() 핵심 구성
command = [
"uv", "run",
"--no-project",
"--python", entry.get("python", default_python),
"--with", "pytest",
]
# 스킬별 packages에 있는 패키지를 차례로 추가
for package in entry.get("packages", []):
command += ["--with", package]
return [*command, "python", "-m", "pytest", target, *pytest_args]
--no-project는 프로젝트 환경에 기대지 않도록 합니다. 기본 실행은 프로세스만 분리하고, --isolated를 지정해야 스킬별 패키지·인터프리터 환경까지 나눕니다. 가상환경과 프로세스 격리도 파일 접근을 막는 샌드박스는 아닙니다.
공통 검사 자체는 tests/_contract/에 모으고, tests/conftest.py의 _install_contract()가 이를 skill_contract라는 고유 이름으로 불러옵니다. 공통 규칙은 공유하되 스킬별 일반 모듈 이름은 충돌하지 않게 하려는 선택입니다.
스킬마다 도구를 담으면 일부 폴더만 가져가기 쉽습니다. 반면 비슷한 보조 코드가 여러 곳에 생길 수 있습니다. SharedCopyTests.test_shared_scripts_are_identical_across_their_skills()는 공유해야 하는 도식 생성 코드 사본의 차이를 검사합니다. 모든 중복을 없애기보다, 배포 단위와 유지보수 단위를 맞추려는 사례입니다.
skills/는 호스트에 전달할 내용입니다. tests/는 그 내용을 검사하는 유지보수 도구입니다. docs/images/는 사람에게 보여 주는 설명 그림입니다. 이 저장소는 테스트와 그림을 스킬 폴더 밖에 두어, 에이전트가 읽는 패키지와 개발 자료를 나눕니다.
모든 스킬의 구성이 같은 것은 아닙니다. 177개 모두 SKILL.md가 있고, 121개에는 scripts/, 176개에는 references/, 43개에는 assets/가 있습니다. 보조 코드가 없는 스킬도 설명서로서 역할을 할 수 있습니다.
아래는 커밋 593377b의 Git 추적 파일을 대상으로 줄바꿈 바이트를 센 값입니다. 빈 줄·주석·문자열을 포함하며, 실행문만 센 수치가 아닙니다. 이미지·압축 파일의 바이트를 코드 줄 수로 세지 않았고, Markdown 안의 코드 예제는 Markdown 쪽에 포함됩니다.
| 유형 | 파일 수 | 줄 수 | 해석 |
|---|---|---|---|
| Python | 771 | 248,635 | 스킬 도구·관리 도구·테스트를 모두 포함 |
| Markdown | 1,538 | 329,660 | 설명과 참고 지식이 큰 비중을 차지 |
| JavaScript | 2 | 223 | Fictiv 관련 보조 스크립트 |
| Shell | 3 | 244 | 일부 스킬의 예제·검토 도구 |
| YAML | 15 | 1,676 | .yml과 .yaml 합산 |
| TOML | 3 | 938 | 프로젝트·테스트 환경·개별 빌드 설정 |
| JSON | 113 | 105,530 | 보고서·스키마·예제 등 데이터와 설정 |
Python 248,635줄 중 skills/는 167,389줄·531개 파일, tests/는 79,276줄·237개 파일, 루트 검사기 두 개와 scripts/의 관리 도구는 합계 1,970줄·3개 파일입니다. 테스트 줄 수가 많다는 사실은 확인할 수 있지만, 커버리지 측정값으로 바꿔 말할 수는 없습니다.
전체 추적 파일은 2,780개이고, 그 안에는 PNG 177개도 있습니다. 따라서 전체 파일 용량을 곧바로 실행 코드의 규모나 모델 크기로 해석하면 안 됩니다. 개별 스킬 테스트 폴더는 155개이며, 보조 스크립트 폴더를 가진 121개 스킬에는 각각 대응하는 테스트 폴더가 있습니다.
# 같은 범위로 Python 줄 수를 세는 읽기 전용 예시
from pathlib import Path
import subprocess
files = subprocess.check_output(["git", "ls-files"], text=True).splitlines()
python_files = [Path(name) for name in files if name.endswith(".py")]
lines = sum(path.read_bytes().count(b"\n") for path in python_files)
print(len(python_files), lines)
# 커밋 593377b 기준: 771 248635
skills/genomic-coordinates/SKILL.md → 해당 scripts/ → tests/genomic-coordinates/ 순서로 읽으면 “약속 → 구현 → 근거”가 연결됩니다. 한 번 익숙해지면 Scanpy 같은 더 큰 스킬에도 같은 읽기 방법을 적용할 수 있습니다.
genomic-coordinates의 to_canonical()과 from_canonical()은 파일을 열거나 API를 부르지 않습니다. 입력을 받아 계산 결과를 돌려주므로 손으로 예상값을 만들기 쉽습니다. build_parser()와 main()은 명령줄 입력과 출력 형식, 종료 코드를 담당합니다.
이처럼 계산과 입출력을 나누면 “결과가 틀렸다”와 “파일을 읽지 못했다”를 구분하기 쉽습니다. 학습할 때는 convert_one()이 반환하는 사전의 length·status·detail을 먼저 읽고, 마지막에 CLI 옵션을 따라가 보세요.
체크인 날짜는 포함하고 체크아웃 날짜는 제외하는 숙박 예약을 생각해 보세요. 내부 표현을 하나로 정한 뒤 “일수”, “겹침”, “빈 구간”을 처리하면 같은 패턴을 연습할 수 있습니다. 의미가 다른 구간을 숫자만 보고 합치지 않는 것이 목표입니다.
AnnData는 행렬만 담는 통이 아닙니다. X는 현재 표현, obs는 세포별 정보, var는 유전자별 정보, layers는 같은 축의 다른 표현을 담습니다. raw라는 이름도 자동으로 실험 원본을 뜻하지 않습니다. 이 스킬에서는 전체 유전자의 로그 정규화 스냅샷으로 설정합니다.
좋은 데이터 파이프라인은 배열의 모양뿐 아니라 그 값이 원본인지, 정규화되었는지, 어떤 집단을 나타내는지까지 보존해야 합니다. 이 관점은 금융 시계열·로그 분석·이미지 전처리에도 그대로 적용됩니다.
| 읽을 함수 | 핵심 기술 | 연습할 질문 |
|---|---|---|
| validate_counts() | 밀집·희소 행렬 분기, 유효성 검사 | NaN·음수·소수·합계 0인 행을 왜 막을까? |
| prepare_counts() | 명시적 선택, 독립 복사, 이력 검사 | 같은 배열을 참조하면 어느 단계에서 원본이 바뀔까? |
| compute_pca() | 데이터 크기에 맞춘 상한 | 요청 차원보다 세포·유전자 수가 적으면 어떻게 할까? |
| pseudobulk.aggregate_counts() | 그룹 집계와 메타데이터 정렬 | 그룹 이름 충돌이나 표의 순서 불일치를 어떻게 찾을까? |
좌표 변환의 왕복 동일성, 구간 길이 보존, 정규화 후 원본 보존은 계약입니다. 원래 함수의 계산식을 복사한 테스트보다, 서로 다른 입력과 표현 사이에서도 유지되어야 하는 조건을 검사할 수 있습니다.
tests/scanpy/test_numerical_contracts.py는 음수·0.25·NaN·무한대를 매개변수로 넣어 실패를 확인합니다. 정상 데이터 하나를 통과시키는 것보다 입력 경계를 더 구체적으로 설명합니다. 다만 일부 테스트에는 pytest.importorskip()가 있어 패키지가 없으면 실행되지 않습니다.
.github/workflows/skill-tests.yml은 먼저 tests/_meta를 검사합니다. compile_problems()는 ast.parse()로 Python 문법을 읽고, dynamic_execution_problems()는 특정 동적 실행 호출을 찾습니다. 검사 대상 스크립트를 실행하지 않고 얻는 신호입니다.
그다음 CI는 테스트 환경 목록에서 packages = []이고 Python 재지정이 없으며 테스트 폴더가 있는 스킬을 고릅니다. 현재 선택 조건에 맞는 것은 24개입니다. 모든 과학 패키지를 준비하는 전체 --isolated 실행은 이 CI에 포함되어 있지 않습니다.
tests/run_all.py는 pytest의 “수집된 테스트 없음” 종료 코드 5를 empty로 보고하고 전체 실패로 처리하지 않습니다. 통과·건너뜀·빈 테스트를 구분하려면 개별 pytest 출력도 읽어야 합니다. 실행기 요약은 종료 코드에 따라 passed·failed·empty로 나누며 건너뛴 테스트 수를 따로 집계하지 않습니다.
scan_skills.py의 build_scanner()는 BehavioralAnalyzer·TriggerAnalyzer·LLMAnalyzer를 조합합니다. 정책은 balanced, 전체 입력 문자 상한은 500_000으로 설정합니다. LLM 검사는 네트워크와 API 키에 의존합니다.
content_hash()는 상대 경로와 파일 바이트를 함께 SHA-256에 넣습니다. 이름 변경과 삭제도 지문에 영향을 주며, __pycache__는 제외합니다. cache_invalidation_reason()은 검사기 버전·모델·마지막 전체 검사 시점을 확인합니다. 기본 재검사 기한은 30일입니다.
여기서 배울 점은 “내용이 같으면 무조건 이전 결과 사용”으로 끝내지 않는 것입니다. 판정 도구가 바뀌어도 캐시를 무효화해야 합니다. ThreadPoolExecutor와 스레드별 검사기는 API 대기 시간을 겹쳐 처리하되, 서비스의 호출 한도라는 별도 제약을 받습니다.
.github/workflows/pr-skill-scan.yml은 포크·Dependabot PR에서 비밀 키를 사용할 수 없으므로 스캔 생략을 명시합니다. 같은 저장소의 PR도 키가 없으면 래퍼가 생략 보고서를 작성합니다. CI 상태만 보고 모든 분석기가 실행됐다고 단정하지 말고, 실행 조건과 보고서 내용을 함께 확인해야 합니다.
저장소 전체에 적용되는 공식 최소 RAM·CPU·GPU 수치는 없습니다. README의 시스템 안내는 macOS·Linux 또는 WSL2를 사용하는 Windows이며, 관리 도구는 Python 3.13 이상을 요구합니다. 개별 스킬의 compatibility가 더 구체적인 기준입니다.
| 목적 | 필요한 환경 | 하드웨어 판단 |
|---|---|---|
| 문서·소스 읽기 | 텍스트 편집기와 Git | 과학 연산용 GPU 필요 없음. 문서와 이미지 저장 공간 고려 |
| 좌표 변환 학습 | 스킬 기준 Python 3.11 이상, 표준 라이브러리 | 소규모 구간 계산은 일반 CPU로 학습 가능. 큰 참조 파일은 별도 메모리 고려 |
| 저장소 검증 | Python 3.13 이상, uv, 개발 의존성 | 구조 검사에는 과학 패키지 불필요. 전체 테스트는 여러 환경과 시스템 도구 필요 |
| Scanpy 분석 | 해당 스킬의 패키지와 데이터 형식 | 행렬 크기·희소성·중간 복사본에 따라 RAM 증가. GPU는 공통 필수 조건이 아님 |
| 모델·가속 계산 | 스킬에 맞는 런타임·드라이버·모델 파일 | VRAM·CUDA/ROCm/Metal 호환성 또는 원격 계산 환경을 별도로 판단 |
skills/genomic-coordinates/SKILL.md는 변이 정규화에 참조 FASTA가 필요하고, .fai 인덱스가 없으면 전체 FASTA를 메모리에 읽는다고 설명합니다. “표준 라이브러리만 사용”이라는 말도 “입력 크기와 무관하게 가볍다”는 뜻은 아닙니다.
필요한 자원은 저장소의 스타 수나 스킬 수가 아니라, 선택한 작업의 데이터 크기와 중간 계산 방식으로 결정됩니다. 특히 희소 행렬을 밀집 행렬로 바꾸는 연산과 여러 복사본이 공존하는 단계를 먼저 확인하세요.
학습용 계산 예로 세포 100,000개·유전자 20,000개의 밀집 float32 행렬을 생각하면, 원소만 100000 × 20000 × 4 = 8,000,000,000바이트, 약 7.45 GiB입니다. 인덱스·메타데이터·복사본·임시 배열은 포함하지 않은 값입니다. 권장 RAM이나 측정 성능으로 읽으면 안 됩니다.
원본 카운트·정규화본·작업용 부분집합을 별도로 유지하면 신뢰성은 높아지지만 저장 공간과 메모리를 더 씁니다. 희소 행렬은 0이 많을 때 유리하지만 인덱스 비용도 있습니다. skills/scanpy/SKILL.md는 스케일링·회귀가 밀집화를 유발할 수 있고, 이 도구 묶음이 일반적인 디스크 기반 대용량 파이프라인은 아니라고 설명합니다.
skills/get-available-resources/scripts/detect_resources.py의 collect_snapshot()은 호스트 자원, 프로세스 CPU 제한, Linux cgroup v2, 스케줄러 할당을 따로 수집합니다. read_text와 run_command를 인자로 받을 수 있어 테스트에서는 관찰값을 대체할 수 있습니다.
plan_workload.py의 build_plan()은 그 스냅샷을 받아 병렬 작업 수를 계산하지만 실제 작업을 실행하지 않습니다. CPU 작업에서는 유효 CPU, 메모리, 작업 수, 사용자 요청의 상한 가운데 가장 작은 값을 고릅니다. 관찰 실패는 무제한이 아니라 알 수 없음으로 다룹니다.
# build_plan()의 상한 선택을 이해하기 위한 가정
유효 CPU 상한 = 8개
사용 가능 메모리 = 12 GiB
명시한 예비 메모리 = 2 GiB
작업 하나의 메모리 = 3 GiB
전체 작업 수 = 10개
사용자 요청 = 6개
메모리 상한 = floor((12 - 2) / 3) = 3
제안 작업 수 = min(8, 3, 10, 6) = 3
작업당 메모리를 명시하지 않으면 메모리 상한을 적용하지 않으며, I/O 작업에는 별도 휴리스틱이 있습니다. 위 숫자는 CPU 작업의 원리를 설명하는 예입니다. skills/get-available-resources/scripts/accelerator_diagnostics.py의 build_diagnostic_plan()도 고정된 진단 명령을 제안할 뿐 실행하지 않습니다. 관리 도구에 GPU가 보인다는 사실과 현재 프레임워크에서 사용할 수 있다는 사실을 구분합니다.
호스트 CPU가 64개여도 컨테이너 할당은 2개일 수 있습니다. 자원을 발견하는 코드와 병렬 처리 수를 정하는 코드를 나누면, 서버·노트북·스케줄러 환경의 차이를 더 명확하게 다룰 수 있습니다.
실습 명령의 경로는 저장소 루트 기준입니다. 실행·수정 과제는 별도의 학습용 사본과 해당 의존성을 준비한 뒤 진행하세요. 아래 결과값은 소스와 테스트에 근거한 예상값이며, API 응답이나 벤치마크 결과를 재현한 표는 아닙니다.
실습의 완료 기준은 명령이 끝났다는 사실보다, 왜 그 결과가 나와야 하는지와 어떤 입력에서 실패해야 하는지를 설명하는 것입니다.
skills/genomic-coordinates/SKILL.md에서 사용 시점, 필요한 Python, 네트워크 사용 여부, 입력 파일 조건, 실패 상태를 찾아 표 한 장으로 정리하세요. metadata.version이 루트 프로젝트 버전과 다른 이유도 적습니다.
sed -n '1,120p' skills/genomic-coordinates/SKILL.md
sed -n '1,115p' skills/genomic-coordinates/scripts/_common.py
sed -n '1,100p' skills/genomic-coordinates/scripts/convert_coords.py
완료 기준: 좌표 번호의 기준을 바꾸는 것, 참조 유전체를 바꾸는 것, 변이 표현을 정규화하는 것이 서로 다른 작업임을 설명할 수 있어야 합니다.
확인 질문: 이 스킬을 다른 호스트에 복사해도 보존되는 정보는 무엇이고, 호스트가 따로 제공해야 하는 기능은 무엇인가요?
먼저 종이에 BED 999–1000을 GFF로 변환하고 길이를 계산하세요. 다음으로 500–500을 변환하면 왜 같은 방식으로 처리할 수 없는지 적습니다. 환경이 준비되면 아래 CLI와 테스트의 예상값을 대조합니다.
python skills/genomic-coordinates/scripts/convert_coords.py \
--from bed --to gff chr1 999 1000
# 예상 핵심 필드: output=1000-1000, length=1, status=ok
python skills/genomic-coordinates/scripts/convert_coords.py \
--from bed --to gff chr1 500 500
# 예상: status=unrepresentable, 종료 코드 1
완료 기준: 정상 구간·길이 0인 구간·뒤집힌 구간을 구분하는 사례를 각각 하나 이상 작성하고, convert_one()의 어느 분기가 처리하는지 연결하세요.
tests/scanpy/test_numerical_contracts.py의 작은 합성 데이터를 읽고, 2×2 행렬의 정규화 결과를 손으로 계산해 보세요. 아래는 계산 원리를 분리한 학습 코드입니다. 실제 Scanpy 함수와 같은 환경을 구성하지 않아도 먼저 의미를 이해할 수 있습니다.
# NumPy를 사용하는 독립된 학습 예시
import numpy as np
counts = np.array([[1., 3.], [2., 2.]])
saved = counts.copy()
normalized = np.log1p(counts / counts.sum(axis=1, keepdims=True) * 1e4)
assert np.array_equal(counts, saved)
assert np.isfinite(normalized).all()
# 값 하나를 -1, 0.25, NaN으로 바꿀 때 필요한 검사를 설계해 보세요.
완료 기준: X·layers["counts"]·raw의 의미를 적고, 독립 복사를 하지 않았을 때 생길 오류를 재현하는 작은 예제를 만드세요. 숫자만으로 원본의 출처를 증명할 수 없다는 한계도 기록합니다.
tests/run_all.py의 isolated_command()를 읽고 genomic-coordinates와 histolab의 명령 구성을 종이에 써 보세요. 전자는 별도 과학 패키지가 없고, 후자는 Python 3.10과 특정 패키지가 필요합니다.
# 해당 환경이 준비된 학습용 사본에서 선택적으로 실행
python tests/run_all.py --isolated genomic-coordinates
# 한 스킬을 명시하면 전체 _meta 검사는 자동으로 선행하지 않습니다.
# 이름을 생략한 전체 실행에서 run_meta()를 먼저 호출합니다.
완료 기준: 프로세스 격리와 환경 격리의 차이를 설명하고, 서로 다른 _common.py 두 개가 한 프로세스에서 충돌할 수 있는 이유를 sys.modules와 연결하세요.
확장: 테스트가 건너뛰어진 경우와 pytest 종료 코드 5인 경우가 요약에서 어떻게 보일지 예상해 보세요.
scan_skills.py의 content_hash()와 cache_invalidation_reason()을 참고해, 텍스트 파일 하나의 검사 결과를 저장하는 작은 프로그램을 별도로 설계하세요. 실제 보안 검사기와 외부 LLM 호출은 필요하지 않습니다.
완료 기준: 정상 재사용, 이름 변경, 도구 버전 변경, 오래된 결과, 읽을 수 없는 캐시를 구분하는 표와 테스트 사례를 만드세요. 캐시 키에 무엇이 빠지면 잘못된 결과를 믿게 되는지도 설명합니다.
처음부터 177개 스킬을 모두 읽을 필요는 없습니다. 하나의 스킬을 문서부터 테스트까지 따라가고, 다음 스킬에서 비슷한 문제와 다른 제약을 찾아보세요. 아래 주차는 순서를 위한 단위이며 학습 속도에 맞게 조정할 수 있습니다.
학습 범위를 넓히기 전에 작은 입력의 예상 결과와 실패 조건을 직접 설명할 수 있어야, 더 큰 파이프라인도 근거를 갖고 읽을 수 있습니다.
| 주차 | 학습 주제·소스 | 만들어 볼 결과물 | 다음 단계로 갈 기준 |
|---|---|---|---|
| 1주 | Python 함수·자료형·dataclass. skills/genomic-coordinates/scripts/_common.py |
BED와 GFF의 좌표·길이를 비교한 손계산 표 | base와 half_open을 독립된 속성으로 설명 |
| 2주 | argparse·오류 상태·단위 테스트. skills/genomic-coordinates/scripts/convert_coords.py와 대응 테스트 |
정상·빈 구간·역전 구간의 입력/출력 계약 | 계산 결과와 종료 코드의 의미를 함께 설명 |
| 3주 | NumPy·SciPy 희소 행렬·AnnData. skills/scanpy/scripts/_common.py |
원본 보존과 정규화를 검사하는 작은 합성 예제 | 원본·로그 정규화·스케일링 표현을 구별 |
| 4주 | pytest import·subprocess·uv 환경. tests/conftest.py, tests/run_all.py |
서로 다른 Python 버전을 쓰는 두 스킬의 환경 설계표 | 프로세스·패키지 환경·보안 격리의 차이를 설명 |
| 5주 | YAML·JSON Schema·정적 검사. plugin.json, tests/_meta/ |
직접 만든 작은 업무 절차서와 검사 항목 목록 | 필수 필드·버전·로컬 링크·스크립트 검사를 구분 |
| 6주 | 캐시 무효화·API 의존성·관찰 가능성. scan_skills.py와 보고서 |
파일·도구 버전·검사 시간을 포함한 오프라인 결과 캐시 | 재사용 근거와 검사 생략·실패를 결과와 함께 기록 |
SKILL.md의 선택 조건과 작업 절차를 개선하고, 필요한 참고 문서만 연결하는 방법을 연습합니다. 선택 정확도는 호스트와 모델에 따라 따로 평가합니다.스킬을 많이 모으는 것은 책을 많이 꽂는 일이고, 스킬의 계약을 검증하는 것은 책에 나온 실험을 이해하는 일입니다. 다음 단계로 넘어갈 때마다 새로운 도구 이름보다 새로 확인할 수 있게 된 성질을 적어 보세요.
| 용어 | 쉬운 설명 |
|---|---|
| 에이전트 호스트 | 모델과 파일·셸 등의 도구를 연결하고 실행·권한을 관리하는 프로그램. 이 저장소의 스킬을 읽는 쪽입니다. |
| Agent Skill | 특정 작업의 사용 조건·절차·자료·보조 도구를 폴더 하나로 묶은 단위입니다. |
| Agent Plugins | 여러 구성요소를 패키지로 설명하기 위한 규격. 여기서는 루트 plugin.json과 스킬 트리가 핵심입니다. |
| SKILL.md | 스킬의 진입 문서. 기계가 읽는 메타데이터와 에이전트가 따를 작업 설명을 함께 담습니다. |
| YAML frontmatter | Markdown 앞의 --- 구간에 쓰는 구조화된 정보. 이름·설명·호환 조건 등을 담습니다. |
| 점진적 공개 | 선택에 필요한 정보부터 보고, 자세한 설명은 필요할 때 읽는 방식입니다. |
| CLI / argparse | CLI는 명령줄 사용 방식이고, argparse는 Python에서 옵션과 인자를 해석하는 표준 모듈입니다. |
| 기준 형식 | 여러 입력 표현을 처리할 때 중간에 사용하는 하나의 통일된 표현입니다. |
| 0-based / 1-based | 첫 번째 위치를 0으로 부를지 1로 부를지의 차이. 같은 위치도 숫자가 달라집니다. |
| 반열린 구간 | 시작은 포함하고 끝은 제외하는 구간. [3, 5)는 정수 위치 3과 4를 포함합니다. |
| 참조 유전체 | 유전 정보의 위치를 셀 때 기준으로 삼는 서열과 버전. 번호 규칙만 맞아도 기준 서열이 다르면 같은 위치가 아닙니다. |
| 출처·처리 이력 | 데이터가 어디서 왔고 어떤 변환을 거쳤는지의 기록. 값만 보고 추측하기 어려운 의미를 보완합니다. |
| AnnData / h5ad | 단일세포 분석 등에 쓰는 행렬·행/열 정보 묶음과 그 저장 형식입니다. |
| 원본 카운트 | 정규화 이전의 관측 횟수 데이터. 값의 모양뿐 아니라 실제 측정·처리 출처를 확인해야 합니다. |
| 희소 행렬 | 0이 대부분일 때 0이 아닌 값과 위치를 중심으로 저장하는 구조. 전체 배열로 펼치면 메모리가 급증할 수 있습니다. |
| HVG | 분석에서 변동이 큰 유전자를 고르는 기준. 계산 방법에 따라 필요한 입력 표현이 다릅니다. |
| PCA / UMAP | 많은 변수의 데이터를 더 적은 차원의 좌표로 요약하는 방법. 보기 좋은 그림이 곧 생물학적 검증은 아닙니다. |
| 계약·불변 조건 | 단계가 달라져도 지켜야 하는 약속. 예를 들어 좌표 변환 전후의 길이, 전처리 뒤의 원본 보존입니다. |
| Fixture | 테스트에 넣기 위해 준비한 작은 입력 자료. 실제 대용량 자료 없이 경계 사례를 재현할 수 있습니다. |
| AST | 코드 문장을 구조로 표현한 구문 트리. 실행하지 않고 함수 호출이나 문법을 검사할 때 사용합니다. |
| 환경 격리 | 프로젝트마다 다른 패키지·버전을 사용하게 분리하는 것. 시스템 파일 접근 권한까지 자동으로 제한하지는 않습니다. |
| 프로세스 격리 | 별도 Python 실행 단위로 나눠 모듈 캐시와 실행 상태를 분리하는 것. 여기서는 import 충돌을 막습니다. |
| JSON Schema | JSON의 필드·자료형·허용 범위를 검사하기 위한 규칙입니다. |
| 해시·캐시 무효화 | 내용의 지문으로 변경을 감지하고, 입력이나 판정 도구가 바뀌면 이전 결과의 재사용을 중단하는 방법입니다. |
| MCP | 모델을 사용하는 호스트와 도구·데이터 제공자를 연결하는 프로토콜. 업무 절차를 담는 스킬과 역할이 다릅니다. |
| cgroup / 스케줄러 | 프로세스에 주어진 CPU·메모리 등을 제한하거나 작업 자원을 배정하는 시스템. 호스트 전체 자원과 실제 할당이 다를 수 있습니다. |
| 검사 생략 | 필요한 패키지·키·환경이 없어 검사를 수행하지 않은 상태. 위험 없음이나 정상 동작 확인과 구별해야 합니다. |
scanpy 스킬의 metadata.version="1.8", 외부 Scanpy 1.12.4, 전체 모음 2.72.0은 서로 다른 변경 이력을 나타냅니다. 재현 가능한 기록에는 어떤 스킬과 외부 환경을 함께 사용했는지 남겨야 합니다.GitHub 수치는 2026-10-23 기준입니다. 파일 구성과 줄 수, 설정값은 커밋 593377b 기준이며 최신 릴리스의 모든 상태와 동일하다고 가정하지 않습니다. 이후에는 기본 브랜치의 코드와 외부 패키지 API가 달라질 수 있습니다.
| 항목 | 확인 내용 |
|---|---|
| 저장소 | K-Dense-AI/scientific-agent-skills |
| 선정 맥락 | GitHub Trending Weekly #5 · 분석일 2026-10-23 |
| 스타 / 포크 | 54,016 / 4,767 |
| 주 언어 | Python |
| 생성일 | 2025-10-19 |
| 최신 릴리스 | v2.72.0 · 2026-10-01 |
| 최근 push | 2026-10-19 |
| 분석 기준 커밋 | 593377b · 2026-10-19 · chore: update security scan report [skip ci] |
| 매니페스트 버전 | pyproject.toml과 plugin.json 모두 2.72.0 |
| 스킬 구성 | 177개 스킬·177개 SKILL.md, scripts/ 121개·references/ 176개·assets/ 43개 |
| 코드 규모 | Python 771개 파일·248,635줄, JavaScript 223줄, Shell 244줄 |
| 문서 규모 | Markdown 1,538개 파일·329,660줄 |
| 테스트 구성 | 스킬별 테스트 폴더 155개, 환경 설정 항목 174개. 구성 수치이며 실행 커버리지와 다름 |
| 전체 추적 파일 | 2,780개. 그림·자료·설정 포함 |
| 라이선스 | 저장소 MIT. 개별 스킬의 license는 별도 확인 필요. 예: scanpy는 BSD-3-Clause |
| 보안 보고서 | 2026-10-19 생성, 검사기 2.3.0. 177개 스킬·466개 탐지 항목, CRITICAL 32개·HIGH 21개 |
docs/security-report.json의 466개 항목 중 377개는 스킬 간 비교 탐지입니다. 보고서의 safe_skills=159는 스킬별 분류이며 “모든 검증을 마친 159개”나 “탐지 항목이 전혀 없는 159개”를 뜻하지 않습니다. 전체 항목 수와 스킬별 표의 수를 단순히 더해 비교하면 어긋날 수 있습니다.
docs/security-triage.md의 현재 보고서 절은 2026-09-13·165개 스킬을 설명합니다. 10월 19일 자동 보고서와 시점이 다르므로, 이전 검토가 새 탐지 결과를 모두 해소했다고 볼 수 없습니다. 탐지는 코드 검토의 단서이고, 악성 여부의 최종 증명도 안전성 인증도 아닙니다.
과학적 타당성: 합성 데이터의 수치 테스트는 생물학적 결론이나 임상 판단을 검증하지 않습니다. 데이터의 출처·실험 설계·분야별 해석에는 별도 검토가 필요합니다.
실행 범위: 파일과 테스트의 존재는 모든 테스트의 통과를 뜻하지 않습니다. CI는 전체 과학 환경을 실행하지 않으며, 외부 API·모델·인증·시스템 도구의 동작은 환경에 따라 달라집니다.
배포와 권한: 스킬 파일을 가져와도 의존성이 설치되거나 실행 권한이 안전하게 제한되지는 않습니다. 필요한 스킬과 도구를 고르고, 외부 전송과 실행 조건을 확인해야 합니다.
버전과 이용 조건: 루트 라이선스와 각 스킬·외부 패키지·데이터베이스의 조건을 구분하세요. README의 채택 규모와 DB 커버리지는 프로젝트 설명이며 정확도 보증 수치가 아닙니다.