Skip to content

chore: enforce python docstring coverage#41

Closed
seonghobae wants to merge 3 commits into
developfrom
feat/issue-40-docstring-gate
Closed

chore: enforce python docstring coverage#41
seonghobae wants to merge 3 commits into
developfrom
feat/issue-40-docstring-gate

Conversation

@seonghobae
Copy link
Copy Markdown
Owner

@seonghobae seonghobae commented Mar 11, 2026

Summary

  • add a repo-local Python docstring gate to the existing quickcheck and CI path without introducing a new dependency
  • document the new 100% docstring expectation and fill the missing docstrings across tracked Python scripts and analysis-engine tests
  • align the issue roadmap with the new docstring-coverage requirement

Verification

  • npm run check:python-docstrings
  • ./scripts/harness/quickcheck.sh
📝 Walkthrough

Walkthrough

저장소 전반에 걸쳐 Python docstring 요구사항과 검사 스크립트를 추가·강화하고, 일부 테스트와 릴리스 포장 로직의 경미한 조정이 포함되었습니다. 대부분은 문서화(도큐스트링) 추가이며 기능 변경은 제한적입니다.

Changes

Cohort / File(s) Summary
Repository policy & root scripts
ARCHITECTURE.md, package.json
ARCHITECTURE.md에 services/analysis-engine 범위에 대한 Python docstring 100% 요구사항 추가. package.jsoncheck:python-docstrings 스크립트 추가 및 lint 스크립트에 해당 검사 삽입.
Quality check scripts
scripts/checks/...
scripts/checks/security_gates.py, scripts/checks/verify_docs.py, scripts/checks/verify_github_bootstrap_policy.py, scripts/checks/verify_security_notes.py, scripts/checks/verify_supply_chain.py
모듈 및 주요 함수들에 docstring 추가. verify_security_notes에 보안 노트 섹션 추출/정규화 로직(소문자화 및 구분자 기반 경계 판단) 추가. 기능·시그니처는 대체로 동일.
Release packaging script
scripts/release/package_desktop_artifact.py
대부분 함수에 docstring 추가. expected_binary_path에 target_triple 기반 오버라이드 로직(Windows/macOS 대상 처리) 및 walrus 연산자 제거로 인한 구현 단순화 변경 포함.
Analysis engine source
services/analysis-engine/src/bandscope_analysis/health.py
공개 TypedDict HealthReport에 모듈/inline docstring 추가(건강 페이로드 문서화).
Analysis engine tests
services/analysis-engine/tests/...
conftest.py, test_api.py, test_health.py, test_release_packaging.py, test_supply_chain_policy.py
테스트 및 conftest에 docstring 추가. test_api.py·test_health.py의 기대 페이로드에 pipeline_stages 필드 (["decode","draft","separate","persist"]) 추가. test_release_packaging.py에 플랫폼/타깃 관련 새 테스트 3건 추가.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 새 문서로 깔끔히 정리했네
한 줄 한 줄, 설명을 깔고
테스트도 웃고 릴리스도 춤추네
작은 토끼가 박수 칩니다 🥕✨

@seonghobae
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

📝 Walkthrough

Walkthrough

services/analysis-engine 범위에 대한 Python 도큐스트링 요구사항과 검사 스크립트가 추가·강화되고, 여러 검사 스크립트와 테스트에 도큐스트링이 삽입되었으며 릴리스 패키징의 바이너리 경로 결정 로직에 타깃 트리플 기반 오버라이드가 추가되었습니다. 테스트 기대값에 pipeline_stages 필드가 포함되었습니다.

Changes

Cohort / File(s) Summary
Repository policy & root scripts
ARCHITECTURE.md, package.json
ARCHITECTURE.mdservices/analysis-engine 및 관련 테스트/스크립트에 대해 Python docstring 100% 요구 추가. 루트 package.jsoncheck:python-docstrings 스크립트 추가 및 lint 시퀀스에 삽입.
Quality check scripts
scripts/checks/...
scripts/checks/security_gates.py, scripts/checks/verify_docs.py, scripts/checks/verify_github_bootstrap_policy.py, scripts/checks/verify_security_notes.py, scripts/checks/verify_supply_chain.py
여러 검사 스크립트에 모듈/함수 도큐스트링 추가. verify_security_notes는 보안 노트 섹션을 소문자화·정규화하여 추출하는 로직을 도입(구분자 기반 경계 판단). 전반적 동작·시그니처는 동일.
Release packaging script
scripts/release/package_desktop_artifact.py
대부분 함수에 도큐스트링 추가. expected_binary_pathtarget_triple 기반 오버라이드 로직 추가(Windows/macOS 대상 처리), walrus 연산자 제거로 구현 단순화.
Analysis engine source
services/analysis-engine/src/bandscope_analysis/health.py
공개 HealthReport TypedDict에 인라인 도큐스트링 추가(헬스 페이로드 문서화).
Analysis engine tests
services/analysis-engine/tests/...
conftest.py, test_api.py, test_health.py, test_release_packaging.py, test_supply_chain_policy.py
테스트 파일 및 conftest.py에 도큐스트링 추가. test_api.py·test_health.py의 기대 페이로드에 pipeline_stages 필드(["decode","draft","separate","persist"]) 추가. test_release_packaging.py에 플랫폼/타깃 관련 신규 테스트 3건 추가.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 새 도큐스트링 깃발을 꽂았네
한 줄의 말이 흐름을 밝히고
테스트는 짹짹, 릴리스는 똑똑
당근 들고 환호하는 토끼 한 마리 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 주요 변경사항인 Python docstring 적용 강제화를 명확하게 요약하고 있습니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed 풀 리퀘스트 설명이 변경 사항과 관련이 있으며, Python docstring 게이트 추가, 누락된 docstring 채우기, 테스트 업데이트 등 변경 내용을 설명합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/issue-40-docstring-gate

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae seonghobae enabled auto-merge (squash) March 11, 2026 13:52
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/release/package_desktop_artifact.py (1)

61-70: ⚠️ Potential issue | 🟠 Major

BANDSCOPE_TARGET_TRIPLE만 설정된 Windows 크로스 빌드가 깨집니다.

여기서는 바이너리 확장자를 normalized_platform()로 결정하므로, 호스트가 Linux/macOS이고 BANDSCOPE_TARGET_TRIPLE=x86_64-pc-windows-msvc처럼 타깃만 지정되면 경로를 bandscope-desktop으로 계산합니다. 실제 산출물은 .exe라서 main()FileNotFoundError로 끝납니다. 타깃 트리플이 있으면 플랫폼/확장자도 그 값에서 파생시키거나, 최소한 BANDSCOPE_ARTIFACT_OS가 함께 없을 때 명시적으로 실패시키는 편이 안전합니다.

🔧 제안 수정안
 def expected_binary_path(repo_root: Path) -> Path:
     """Return the expected desktop binary path for the selected target triple."""
-    system = normalized_platform()
+    target_triple = os.environ.get("BANDSCOPE_TARGET_TRIPLE")
+    if target_triple and "windows" in target_triple:
+        system = "windows"
+    elif target_triple and "apple-darwin" in target_triple:
+        system = "macos"
+    else:
+        system = normalized_platform()
     binary_name = (
         "bandscope-desktop.exe" if system == "windows" else "bandscope-desktop"
     )
     target_root = repo_root / "apps" / "desktop" / "src-tauri" / "target"
-    if target_triple := os.environ.get("BANDSCOPE_TARGET_TRIPLE"):
+    if target_triple:
         target_root = target_root / target_triple
     return target_root / "release" / binary_name
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/package_desktop_artifact.py` around lines 61 - 70,
expected_binary_path currently picks the binary extension from
normalized_platform(), so when only BANDSCOPE_TARGET_TRIPLE is set (e.g.,
x86_64-pc-windows-msvc) on a non-Windows host you compute "bandscope-desktop"
and later main() raises FileNotFoundError; change expected_binary_path to derive
the OS/extension from BANDSCOPE_TARGET_TRIPLE when present (detect "windows" in
the triple and use ".exe"), or if you prefer require an explicit override use
BANDSCOPE_ARTIFACT_OS and fail fast with a clear error if neither
BANDSCOPE_ARTIFACT_OS nor a recognizable BANDSCOPE_TARGET_TRIPLE is provided;
update logic around normalized_platform(), BANDSCOPE_TARGET_TRIPLE and
BANDSCOPE_ARTIFACT_OS in expected_binary_path accordingly so the computed path
matches the actual artifact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@scripts/release/package_desktop_artifact.py`:
- Around line 61-70: expected_binary_path currently picks the binary extension
from normalized_platform(), so when only BANDSCOPE_TARGET_TRIPLE is set (e.g.,
x86_64-pc-windows-msvc) on a non-Windows host you compute "bandscope-desktop"
and later main() raises FileNotFoundError; change expected_binary_path to derive
the OS/extension from BANDSCOPE_TARGET_TRIPLE when present (detect "windows" in
the triple and use ".exe"), or if you prefer require an explicit override use
BANDSCOPE_ARTIFACT_OS and fail fast with a clear error if neither
BANDSCOPE_ARTIFACT_OS nor a recognizable BANDSCOPE_TARGET_TRIPLE is provided;
update logic around normalized_platform(), BANDSCOPE_TARGET_TRIPLE and
BANDSCOPE_ARTIFACT_OS in expected_binary_path accordingly so the computed path
matches the actual artifact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: feff9db4-b1c0-4375-b882-01da316ce6d2

📥 Commits

Reviewing files that changed from the base of the PR and between 032852f and 5de4078.

📒 Files selected for processing (14)
  • ARCHITECTURE.md
  • package.json
  • scripts/checks/security_gates.py
  • scripts/checks/verify_docs.py
  • scripts/checks/verify_github_bootstrap_policy.py
  • scripts/checks/verify_security_notes.py
  • scripts/checks/verify_supply_chain.py
  • scripts/release/package_desktop_artifact.py
  • services/analysis-engine/src/bandscope_analysis/health.py
  • services/analysis-engine/tests/conftest.py
  • services/analysis-engine/tests/test_api.py
  • services/analysis-engine/tests/test_health.py
  • services/analysis-engine/tests/test_release_packaging.py
  • services/analysis-engine/tests/test_supply_chain_policy.py

Comment thread package.json
Comment on lines +21 to +24
"check:python-docstrings": "sh -c 'cd services/analysis-engine && uv run ruff check src tests ../../scripts --select D100,D101,D102,D103,D104,D105,D106,D107'",
"ruff:check": "sh -c 'cd services/analysis-engine && uv run ruff check src tests'",
"ruff:format:check": "sh -c 'cd services/analysis-engine && uv run ruff format --check src tests'",
"lint": "npm run lint:workspaces && npm run check:docs && npm run check:security-notes && npm run check:security-gates && npm run check:supply-chain && npm run check:github-bootstrap && npm run ruff:check && npm run ruff:format:check",
"lint": "npm run lint:workspaces && npm run check:docs && npm run check:security-notes && npm run check:security-gates && npm run check:supply-chain && npm run check:github-bootstrap && npm run check:python-docstrings && npm run ruff:check && npm run ruff:format:check",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What do Ruff pydocstyle rules D100-D107 cover? Do they apply only to public modules/classes/functions/methods, or also private underscore-prefixed ones?

💡 Result:

Ruff’s pydocstyle D100–D107 rules are the “missing docstring” checks:

Do they apply to private (underscore-prefixed) definitions?

For D100–D104 and D106, they apply only to public constructs. In pydocstyle (which Ruff derives these from), a construct is public only if its parent is public and its name does not start with _ or __ (with the special case that names like __init__.py are treated as public for this purpose). Also, if __all__ is defined, only names listed there are considered public. (pydocstyle.readthedocs.io)

So, e.g. _foo() / _Bar / _baz.py won’t trigger D1xx “missing docstring” errors just because they lack docstrings. (pydocstyle.readthedocs.io)

D105 is different: it targets magic methods (dunders), not “public vs private” by underscore prefix. (pydocstyle.readthedocs.io)

Citations:


D100-D107 규칙만으로는 "100% docstring coverage"를 실제로 강제하지 못합니다.

현재 선택한 Ruff 규칙은 public 심볼만을 대상으로 합니다. 따라서 _helper() 같은 private 함수나 _PrivateClass 같은 private 클래스는 docstring 검사 대상에서 제외되어 통과합니다. PR의 목표와 ARCHITECTURE.md에서 명시한 "100% docstring coverage" 정책을 일치시키려면, 정책 문구를 public 범위로 명확히 좁히거나 private 심볼까지 포함하는 추가 검사를 도입해야 합니다.

@seonghobae
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/release/package_desktop_artifact.py`:
- Around line 61-76: expected_binary_path() currently uses
BANDSCOPE_TARGET_TRIPLE to choose a binary name/path while artifact_identity()
and manifest generation still use host-derived
normalized_platform()/normalized_architecture(), causing mismatched artifact
names; update code so the target triple is parsed once into
platform/architecture values and both expected_binary_path() and
artifact_identity() consume those derived values (e.g., add a helper that parses
BANDSCOPE_TARGET_TRIPLE into target_platform and target_arch, fall back to
normalized_platform()/normalized_architecture() when unset, then use those
values inside expected_binary_path() to pick binary_name and path and in
artifact_identity() to build the artifact name) ensuring both functions
reference the same canonical target info.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: da838430-bade-43c6-a742-eb154ba72959

📥 Commits

Reviewing files that changed from the base of the PR and between 5de4078 and 913dcf2.

📒 Files selected for processing (2)
  • scripts/release/package_desktop_artifact.py
  • services/analysis-engine/tests/test_release_packaging.py

Comment on lines 61 to 76
def expected_binary_path(repo_root: Path) -> Path:
system = normalized_platform()
"""Return the expected desktop binary path for the selected target triple."""
target_triple = os.environ.get("BANDSCOPE_TARGET_TRIPLE")
if target_triple and "windows" in target_triple:
system = "windows"
elif target_triple and "apple-darwin" in target_triple:
system = "macos"
else:
system = normalized_platform()
binary_name = (
"bandscope-desktop.exe" if system == "windows" else "bandscope-desktop"
)
target_root = repo_root / "apps" / "desktop" / "src-tauri" / "target"
if target_triple := os.environ.get("BANDSCOPE_TARGET_TRIPLE"):
if target_triple:
target_root = target_root / target_triple
return target_root / "release" / binary_name
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

BANDSCOPE_TARGET_TRIPLE가 패키징 결과의 단일 기준이 아닙니다.

여기서는 target triple로 바이너리 경로와 확장자를 일부 덮어쓰지만, artifact_identity()와 manifest는 여전히 호스트 기반 normalized_platform() / normalized_architecture()를 사용합니다. 그래서 Linux 호스트에서 x86_64-pc-windows-msvc만 설정하면 .exe를 패키징하면서도 산출물 이름은 bandscope-linux-amd64-...로 기록되고, 반대로 Windows 호스트에서 Linux triple을 쓰면 여기서는 여전히 .exe 경로를 기대합니다. 플랫폼/아키텍처를 target triple에서 한 번만 파생해서 expected_binary_path()artifact_identity()가 같이 쓰도록 맞춰야 합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/package_desktop_artifact.py` around lines 61 - 76,
expected_binary_path() currently uses BANDSCOPE_TARGET_TRIPLE to choose a binary
name/path while artifact_identity() and manifest generation still use
host-derived normalized_platform()/normalized_architecture(), causing mismatched
artifact names; update code so the target triple is parsed once into
platform/architecture values and both expected_binary_path() and
artifact_identity() consume those derived values (e.g., add a helper that parses
BANDSCOPE_TARGET_TRIPLE into target_platform and target_arch, fall back to
normalized_platform()/normalized_architecture() when unset, then use those
values inside expected_binary_path() to pick binary_name and path and in
artifact_identity() to build the artifact name) ensuring both functions
reference the same canonical target info.

@seonghobae
Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@seonghobae
Copy link
Copy Markdown
Owner Author

Superseded by #42 to clear stale CodeRabbit review state after all checks passed.

@seonghobae seonghobae closed this Mar 11, 2026
auto-merge was automatically disabled March 11, 2026 15:36

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant