release(v4.8.8): Issue #17 follow-up - archive the review reports and bump the lockstep version
Merge-workspace review loop (--all-reviewer): round 1 (@d198dd5) claude agy PASS, grok codex NOT PASS (the same inherited WORKSPACE_ROOT in eleven more modules; test_orc_onboard's import-time env); fixed in8b47cc7. Round 2 claude grok NOT PASS (test_o2_race_free_lock, test_o1_rebuttal missed), agy codex PASS; fixed inac48cb7. Round 3 (@ac48cb7) 4/4 PASS. Full suite atac48cb7on macOS / Python 3.9 / herdr 0.9.3 with WORKSPACE_ROOT set to an empty sentinel: 1751 passed / 0 failed / 38 skipped; the sentinel stayed empty and the main checkout's shim was not touched. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
ac48cb7861
commit
e0181ea9be
32 files changed
+1192
-26
No files matched your search
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"loop_id": "loop-20261008T133858Z-9e7f5b",
|
||||
"base_sha": "6b00b6e06f55299cb60f156ccef09ede4bae5bdd",
|
||||
"head_sha": "ac48cb78617af88584db529b5766acf02f4af73c",
|
||||
"tree_sha": "b043034eda891bd83b547dcb34d7422a6977b89d",
|
||||
"review_commit": "ac48cb78617af88584db529b5766acf02f4af73c",
|
||||
"reviewer": "planner-reviewer-claude-01",
|
||||
"job_id": "1364df46",
|
||||
"verdict": "PASS",
|
||||
"transport": "herdr",
|
||||
"evidence": "review-tree",
|
||||
"isolation": "worktree",
|
||||
"verified_at": "2026-10-08T18:40:20Z"
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# 리뷰 리포트 — Job 1364df46 (Issue #17 후속 3회차: 상속 WORKSPACE_ROOT, 6b00b6e..ac48cb7)
|
||||
|
||||
- 리뷰어: planner-reviewer-claude-01 (claude)
|
||||
- 리뷰 identity: loop-20261008T133858Z-9e7f5b / base 6b00b6e / head ac48cb7 / tree b043034 — 검증 경로(…/3)에서 `git rev-parse HEAD 'HEAD^{tree}'` 일치, 미커밋 변경 없음
|
||||
- 범위: 2회차 head 8b47cc7 위에 커밋 1개(ac48cb7, +9줄): test_o2_race_free_lock.py 의 o2_12 에 테스트 단위 `own_workspace_root` 마크, test_o1_rebuttal.py 에 모듈 마크, W1 NODES 에 두 노드 추가. 제품 코드·버전·VERSIONS 변경 없음.
|
||||
|
||||
## 결론 요약
|
||||
2회차의 차단 지적(test_o2_race_free_lock.py:196-203 이 run_loop.sh → lib.sh 로 자기 체크아웃의 `.mam/shim/herdr` 를 씀)이 닫혔고, grok 이 지적한 test_o1_rebuttal 도 같은 방식으로 덮였다. 2회차에서 깨끗했던 나머지 후보들은 그대로 깨끗하다. 차단 결함 없음.
|
||||
|
||||
## 1. 지적 종결
|
||||
| 지적 | 수정 | 확인 |
|
||||
|---|---|---|
|
||||
| claude(2회차): o2_12 가 `dict(os.environ)` 로 run_loop.sh 실행, 마크·sandbox 없음 → 체크아웃 shim 재작성 | test_o2_race_free_lock.py:196-198 — o2_12 에만 `@pytest.mark.usefixtures("own_workspace_root")`(모듈 마크를 피한 이유: o2_7 이 tmp_path 항목 수를 센다 — 타당); W1 NODES 에 o2_12 추가(:41) | HEAD 사본에서 `WORKSPACE_ROOT=<사본>` 으로 o2_12 단독·파일 전체(22 passed) 모두 `.mam` **미생성**; `WORKSPACE_ROOT` 미설정으로도 미생성(2회차에는 두 경우 모두 생성) |
|
||||
| grok: test_o1_rebuttal 도 run_loop.sh 실행 | 모듈 마크(:10-12), W1 NODES 에 v3 노드 추가(:42) | HEAD 사본 파일 전체(10 passed) 미생성. 새 W1 노드가 의미 있는지: base 트리에서 그 노드 1개를 `WORKSPACE_ROOT=<base 사본>` 으로 실행 → `.mam/shim/herdr` **생성** — 수정 전 결함을 실제로 고정한다 |
|
||||
|
||||
## 2. 놓친 모듈이 더 없는가 (2회차 방법 반복)
|
||||
HEAD 트리 사본에서 `WORKSPACE_ROOT=<사본>` 으로 내 후보 13개 파일(test_o2, test_o1, test_issue30_stall_watch_stop, test_issue36_prompt_transport, test_issue19, test_a4, test_issue21_acceptance, test_issue20, test_issue34, test_issue23_24, test_b4, test_issue15, test_issue10_13; lib.sh 를 source 하는 코드를 실행하면서 sandbox 인자가 없는 테스트 50개)을 파일별로 돌리고 매번 `.mam` 을 확인: **13개 모두 clean**. 2회차에 유일하게 썼던 o2 가 이제 깨끗하다.
|
||||
|
||||
## 3. 할 일 4 — 실행 (검증 경로, 워크트리 .venv Python 3.9.6, `env -i` 로 HERDR_*·MAM_*·MQTT_* 제거)
|
||||
| 실행 | 결과 |
|
||||
|---|---|
|
||||
| (a) WORKSPACE_ROOT 없이: 수정 16개 파일(W1·W2 포함) + test_issue33_budget, test_issue5_phase1_delegation, test_tier1_unit | **675 passed / 0 failed** (862 s) |
|
||||
| (b) WORKSPACE_ROOT=<워크트리 밖 센티널>: 수정 16개 파일 | **522 passed / 0 failed** (707 s); 실행 뒤 센티널 **비어 있음** |
|
||||
| 본 체크아웃 .mam/shim/herdr mtime | 전후 동일(1791480333); 실제 .mam/jobs 항목 수 불변 |
|
||||
- W1 은 (a)(b) 양쪽에서 통과했고, 이제 15개 노드(모듈 15개)를 체크아웃 사본에서 돌려 `.mam` 미생성을 고정한다.
|
||||
- 이식성: Python 테스트 코드만. bash 3.2·macOS 영향 없음.
|
||||
|
||||
## 4. 1·2회차 판단 유지
|
||||
`_env` 의 tmp_path 지정(lib.sh:26 기본값 때문), conftest `pytest_configure` 의 "다른 체크아웃만 제거" 정책과 opt-in fixture 설계(autouse 불가 이유 포함), unittest 클래스의 명시 env, test_orc_onboard 의 호출 시점 root — 모두 이전 리포트대로 타당하다. W1·W2 가 base 에서 실패함은 2회차에 확인했다.
|
||||
|
||||
## 5. 비차단
|
||||
- W1 의 모듈 목록은 수동 유지다(2회차 비차단 그대로). 새 테스트가 lib.sh 를 source 하는 모듈을 추가하면 목록도 늘려야 한다는 점을 conftest 의 fixture docstring 이나 W1 머리말에 한 줄 적어 두면 좋다.
|
||||
- 새 관찰 없음.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,44 @@
|
||||
# 리뷰 리포트 — Job 24b1f07f (Issue #17 후속: 테스트의 상속 WORKSPACE_ROOT, 6b00b6e..d198dd5)
|
||||
|
||||
- 리뷰어: planner-reviewer-claude-01 (claude)
|
||||
- 리뷰 identity: loop-20261008T133858Z-9e7f5b / base 6b00b6e / head d198dd5 / tree 114ec21 — 검증 경로에서 `git rev-parse HEAD 'HEAD^{tree}'` 일치, 미커밋 변경 없음
|
||||
- 범위: 커밋 1개(d198dd5), tests/test_issue17_item4_decisions.py 만(+36/−2). 제품 코드(.agents/skills)·버전·VERSIONS 변경 없음(브리프대로).
|
||||
|
||||
## 결론 요약
|
||||
할 일 1·3·4 가 요구대로 반영됐고, 새 회귀 테스트는 수정 전 `_env` 에서 실제로 실패한다(센티널에 `.mam/shim/herdr` 생성). 할 일 2(다른 테스트 조사)는 이 PR 에 코드 변경이 없는데, 내가 직접 grep 한 결과로도 **같은 결함(다른 워크스페이스에 쓰기)은 conftest 가 이미 프로세스 수준에서 막고 있어** 추가 수정 대상이 없다 — 다만 남는 두 파일(§3)은 creator 리포트의 표에 있어야 한다. 차단 결함 없음.
|
||||
|
||||
## 1. 할 일 1 — `_env` (tests/test_issue17_item4_decisions.py:224-233)
|
||||
- 상속 제외 목록에 `WORKSPACE_ROOT` 추가(:229), `env.update(... WORKSPACE_ROOT=str(tmp_path) ...)`(:231) 로 테스트별 임시 경로를 명시. "제거"가 아니라 "지정"을 고른 이유는 주석(:225-227)에 있고 맞다: lib.sh:26 은 `WORKSPACE_ROOT` 가 비어 있으면 `$SKILL_DIR/../..` = **체크아웃 자신**을 쓰므로, 제거만 하면 래퍼를 source 하는 헬퍼 4곳(_run_both :246/:372/:561/:586 등)이 체크아웃의 `.mam/shim/herdr` 를 다시 쓴다. 지정하면 shim 이 tmp_path 아래에 생긴다(회귀 테스트가 `(work/.mam/shim/herdr).is_file()` 로 고정, :498).
|
||||
- `extra` 로 넘기는 명시 WORKSPACE_ROOT(:692 의 wait-rc 테스트)는 `env.update(extra)` 가 뒤에 오므로 그대로 이긴다 — 의도적 지정 테스트가 깨지지 않는다.
|
||||
|
||||
## 2. 할 일 3 — 회귀 테스트 test_c_helpers_write_nothing_to_an_inherited_workspace (:477-498)
|
||||
- 센티널 디렉터리를 `WORKSPACE_ROOT` 로 monkeypatch 한 뒤 `_run_both`(옛·새 양쪽)와 래퍼 직접 source 를 돌리고, 센티널 아래 파일 없음·체크아웃 shim mtime 불변·셸이 보는 `$WORKSPACE_ROOT` 가 테스트 tmp 임·shim 이 tmp 에 생김을 단언한다.
|
||||
- **수정 전 코드에서 실패 확인**: HEAD 의 테스트 파일에서 `_env` 두 줄만 base(6b00b6e) 판으로 되돌린 스크래치 사본 → `AssertionError: written into the sentinel`, `['.mam', '.mam/shim', '.mam/shim/herdr'] == []` (1 failed). 현재 코드에서 통과.
|
||||
- conftest 의 `pytest_configure` 는 다른 체크아웃을 가리키는 WORKSPACE_ROOT 를 수집 전에 지우므로(tests/conftest.py:139-148), 이 테스트가 monkeypatch 로 다시 설정하는 것이 맞는 설계다(지우지 않으면 센티널이 보이지 않는다).
|
||||
|
||||
## 3. 할 일 2 — 같은 결함이 다른 테스트에 있는가 (직접 grep)
|
||||
- **conftest 가 막는 범위**: `pytest_configure`(conftest.py:139-148)가 AGENT_SESSIONS_YAML·MAM_JOBS_DIR·DELEGATE_JOB_LOGS_DIR 을 항상, `WORKSPACE_ROOT` 는 **realpath 가 이 체크아웃이 아닐 때만** os.environ 에서 지운다(주석 :122-124: 이 체크아웃을 가리키면 "lib.sh 가 어차피 유도하는 값"). 따라서 어떤 테스트든 os.environ 을 복사해 lib.sh 를 돌려도 **다른 워크스페이스에는 쓸 수 없다**. 남는 경우는 (i) 체크아웃 자신의 shim 재작성, (ii) 테스트가 monkeypatch 로 다시 설정한 값, (iii) pytest 밖에서 헬퍼를 직접 돌리는 경우(PR #51 리뷰 때의 사고는 리뷰어의 수동 탐침, 즉 (iii)).
|
||||
- **이 파일이 "빠진" 이유**: 빠진 것이 아니라 (i)(iii) 에 노출돼 있었다 — `_env` 가 WORKSPACE_ROOT 를 남겨 둔 채 래퍼→lib.sh 를 source 했으므로, 스위트 실행 중에는 체크아웃 자신의 shim 을 매번 다시 썼고, 수동 실행에서는 상속값 그대로 썼다. 이번 수정이 둘 다 막는다.
|
||||
- os.environ 을 복사하고 lib.sh/래퍼를 돌리는 테스트 파일 36개를 grep 했다. `mam_sandbox` 를 쓰는 파일은 fixture 가 `WORKSPACE_ROOT=tmp_path` 를 설정하므로(conftest.py:215) 복사본이 sandbox 를 물려받아 안전하다. fixture 없이 lib.sh 를 실제로 source 하는 파일은 둘뿐이며, 둘 다 (i) 에만 해당한다:
|
||||
|
||||
| 파일:라인 | 동작 | 판단 |
|
||||
|---|---|---|
|
||||
| tests/test_b19_headless_reconcile_fixes.py:326-329, :366-369, :401-402 | `source "$SKILL_DIR/lib.sh"` 하는 스크립트를 SKS_* 만 뺀 os.environ 으로 실행 | 다른 체크아웃은 conftest 가 지움; 이 체크아웃이면 자신의 shim 재작성(conftest 가 명시적으로 허용하는 경우). 고치지 않아도 되나 표에 있어야 함 |
|
||||
| tests/test_version_consistency.py:30 | `bash -c 'source lib.sh …'` 를 env 지정 없이 cwd=REPO_ROOT 로 실행 | 위와 같음 |
|
||||
| tests/test_deploy_freshness.py, test_deploy_layout.py | lib.sh 를 복사·읽기만, source 안 함 | 해당 없음 |
|
||||
- 제품 코드 변경 필요 여부: 없음. conftest 한 곳에서 "이 체크아웃" 경우까지 지우는 방법은 lib.sh 가 어차피 같은 값을 유도하므로 효과가 없고(주석 :122-124 의 근거), 체크아웃 shim 재작성을 피하려면 각 헬퍼가 tmp 를 지정해야 한다 — 이 PR 의 방식이 맞다.
|
||||
|
||||
## 4. 할 일 4 — 실행 (검증 경로, 워크트리 .venv Python 3.9.6, `env -i` 로 HERDR_*·MAM_*·MQTT_* 제거)
|
||||
| 실행 | 결과 |
|
||||
|---|---|
|
||||
| (a) WORKSPACE_ROOT 없이: test_issue17_item4_decisions, test_issue33_budget, test_issue5_phase1_delegation, test_tier1_unit | **443 passed / 0 failed** (478 s) |
|
||||
| (b) WORKSPACE_ROOT=<워크트리 밖 센티널>: test_issue17_item4_decisions | **290 passed / 0 failed** (319 s); 실행 뒤 센티널 **비어 있음**(`find` 출력 없음) |
|
||||
| 회귀 테스트, 수정 전 `_env` 사본 | 1 failed(센티널에 .mam/shim/herdr) |
|
||||
- 본 체크아웃 `.mam/shim/herdr` mtime 실행 전후 동일(1791469013). 실제 .mam/jobs 항목 수 불변. 브로커 bind 제약 없음.
|
||||
- (b) 에서 센티널은 realpath 가 체크아웃이 아니라 conftest 가 지우므로, 대부분의 테스트는 conftest 로, 회귀 테스트는 `_env` 로 보호되는 셈이다 — 둘 다 통과했으니 브리프 (b) 의 목적(어느 층이든 센티널에 쓰지 않음)은 충족된다.
|
||||
|
||||
## 5. 이식성·비차단
|
||||
- 변경은 Python 테스트 코드뿐(3.9 문법, `stat().st_mtime_ns`, `Path.rglob`). bash 3.2·macOS 영향 없음.
|
||||
- 비차단: §3 표의 두 파일이 creator 리포트의 "고치지 않은 후보" 표에 없다면 추가를 권한다. 새 관찰 없음.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,45 @@
|
||||
# 리뷰 리포트 — Job cd288bf2 (Issue #17 후속 2회차: 상속 WORKSPACE_ROOT, 6b00b6e..8b47cc7)
|
||||
|
||||
- 리뷰어: planner-reviewer-claude-01 (claude)
|
||||
- 리뷰 identity: loop-20261008T133858Z-9e7f5b / base 6b00b6e / head 8b47cc7 / tree bfe5fcb — 검증 경로(…/2)에서 `git rev-parse HEAD 'HEAD^{tree}'` 일치, 미커밋 변경 없음
|
||||
- 범위: 커밋 2개(d198dd5 = 1회차, 8b47cc7 = grok·codex 지적 반영). conftest.py 의 `own_workspace_root` fixture + 테스트 파일 14개 + 새 tests/test_issue17_workspace_root_isolation.py(W1·W2). 제품 코드(.agents/skills)·버전·VERSIONS 변경 없음(브리프대로).
|
||||
|
||||
## 결론 요약
|
||||
설계(opt-in fixture `own_workspace_root`, W1 가 모듈별 대표 노드를 체크아웃 사본에서 돌려 `.mam` 미생성을 고정, W2 가 test_orc_onboard 의 import 시점 root 전파를 고정)는 적절하고, 수정된 14개 파일·회귀 테스트·(a)(b) 실행은 모두 요구대로다. 그러나 **조사(2)가 모듈 하나를 놓쳤다**: tests/test_o2_race_free_lock.py 의 `test_o2_12_run_loop_exits_on_lock_failure` 는 HEAD 에서도 자신이 도는 체크아웃의 `.mam/shim/herdr` 를 쓴다(§3). 이 커밋의 제목("every test that sources lib.sh does it under its own WORKSPACE_ROOT")과 W1 의 전제("one test per module that sourced lib.sh … with the inherited root")에 어긋나는 같은 결함이며, 브리프가 리뷰어에게 직접 grep 으로 확인하라고 한 항목이다. 수정은 두 줄(§3)이고 재설계는 아니므로 ESCALATE 는 아니다.
|
||||
|
||||
## 1. 할 일 1·3·4 — 요구대로
|
||||
- `_env`(test_issue17_item4_decisions.py:224-233): 1회차 그대로(제외 + tmp_path 지정). lib.sh:26 이 미설정 시 체크아웃을 유도하므로 "지정"이 맞다.
|
||||
- 회귀 테스트: 1회차의 test_c_helpers_write_nothing_to_an_inherited_workspace 에 더해 W1·W2(새 파일). **수정 전 코드에서 실패 확인**:
|
||||
- W1 상당: base(6b00b6e) 트리 사본 안에서 W1 의 NODES 13개를 `WORKSPACE_ROOT=<사본>` 으로 실행(24 passed) → 사본에 `.mam/shim/herdr` 생성됨(W1 의 `written == []` 단언이 실패하는 조건).
|
||||
- W2 상당: base 의 test_orc_onboard 를 `WORKSPACE_ROOT=<센티널>` 로 import 한 뒤 `run_find_uuid(ws, …)` 호출 → **센티널**에 `.mam/shim/herdr` 생성, ws 에는 없음(import 시점 root 전파 재현). HEAD 의 `_scrubbed_env(root)`(test_orc_onboard.py:24-29)는 호출 시점 root 를 쓴다.
|
||||
- (a)(b) 실행(검증 경로, 워크트리 .venv Python 3.9.6, `env -i` 로 HERDR_*·MAM_*·MQTT_* 제거):
|
||||
|
||||
| 실행 | 결과 |
|
||||
|---|---|
|
||||
| (a) WORKSPACE_ROOT 없이: 수정 14개 파일 + test_issue33_budget, test_issue5_phase1_delegation, test_tier1_unit | **643 passed / 0 failed** (815 s) |
|
||||
| (b) WORKSPACE_ROOT=<워크트리 밖 센티널>: 수정 14개 파일 | **490 passed / 0 failed** (656 s); 실행 뒤 센티널 **비어 있음** |
|
||||
| 본 체크아웃 .mam/shim/herdr mtime | 전후 동일(1791473441); 실제 .mam/jobs 항목 수 불변 |
|
||||
- 이식성: Python 테스트 코드만(3.9 문법); W1 은 `git ls-files` 와 nested pytest 로 이 Mac 에서 통과.
|
||||
|
||||
## 2. 할 일 2 — 설계 판단
|
||||
- conftest 의 `pytest_configure`(:139-148)는 **다른** 체크아웃을 가리키는 WORKSPACE_ROOT 만 지우고 이 체크아웃을 가리키면 남긴다(lib.sh 가 어차피 유도하는 값). 위험은 "이 체크아웃 자신"(에이전트 pane 에서 main 체크아웃으로 스위트를 돌릴 때 = 실제 워크스페이스)이며, 그 근본은 lib.sh:3088 이 **source 시점마다** `_init_herdr_isolation`(:143-146) 으로 `$WORKSPACE_ROOT/.mam/shim/herdr` 를 쓰는 것이다(직접 확인: `source lib.sh && find_workspace_uuid` 만으로 센티널에 shim 생성).
|
||||
- `own_workspace_root` 를 autouse 로 두지 않은 이유(docstring: runner.py·mqtt_common 이 in-process 로 WORKSPACE_ROOT 를 읽음)는 타당하고, usefixtures 마크는 autouse 뒤·테스트 인자(mam_sandbox) 앞에 적용되므로 "mam_sandbox 와 테스트 자신의 지정이 이긴다"는 주장도 맞다. unittest.TestCase(test_workspace_scope)는 마크가 적용되지 않아 env 를 직접 지정한 것도 일관된다.
|
||||
- test_issue21_worktree_prereqs `_mutate`(:546-547)와 test_workspace_scope(:30-32)의 명시 지정, test_orc_onboard 의 `_scrubbed_env` 도 적절.
|
||||
|
||||
## 3. 놓친 모듈 (차단) — tests/test_o2_race_free_lock.py:196-203
|
||||
```
|
||||
196 def test_o2_12_run_loop_exits_on_lock_failure(tmp_path):
|
||||
200 cmd = ["bash", str(RUN_LOOP), "--creator", "dummy-agent", "--task", "test"]
|
||||
201 run_env = dict(os.environ)
|
||||
203 res = subprocess.run(cmd, …, cwd=str(tmp_path), env=run_env)
|
||||
```
|
||||
- run_loop.sh:17 이 lib.sh 를 source 하고, 이 테스트는 os.environ 을 그대로 물려주며(WORKSPACE_ROOT 미지정, cwd 만 tmp_path), 파일에 `own_workspace_root` 마크도 mam_sandbox 도 없다(:5 `import pytest` 는 이미 있음).
|
||||
- 재현(W1 과 같은 방법, HEAD 트리 사본): `WORKSPACE_ROOT=<사본>` 으로 이 테스트 1개 → 사본에 `.mam/shim/herdr` **생성**; `WORKSPACE_ROOT` 미설정으로도 **생성**(lib.sh 가 체크아웃을 유도); 파일 전체(22 passed)도 생성. 같은 방법으로 돌린 내 다른 후보 11개 파일 40개 테스트(test_issue30_stall_watch_stop, test_issue36_prompt_transport, test_issue19, test_a4, test_issue21_acceptance, test_issue20, test_issue34, test_issue23_24, test_b4, test_issue15, test_issue10_13)는 모두 깨끗했다 — 놓친 것은 이 모듈뿐이다.
|
||||
- 따라서 W1 의 "every module whose shells used to inherit the root" 목록(NODES, test_issue17_workspace_root_isolation.py:26-40)이 불완전하고, 커밋 8b47cc7 의 제목이 참이 아니다.
|
||||
- 수정(같은 방식): test_o2_race_free_lock.py 에 `pytestmark = pytest.mark.usefixtures("own_workspace_root")` 추가(o2_13 의 mam_sandbox 는 그대로 이김), W1 NODES 에 `tests/test_o2_race_free_lock.py::test_o2_12_run_loop_exits_on_lock_failure` 추가. 그러면 W1 이 이 회귀를 앞으로 잡는다.
|
||||
|
||||
## 4. 비차단
|
||||
- W1 은 모듈당 대표 노드 1개만 돌리므로 같은 모듈의 다른 테스트가 새로 lib.sh 를 source 하면 잡지 못한다 — 마크가 모듈 전체에 걸리므로 현재 설계에서는 문제없지만, 목록 유지가 수동이라는 한계는 적어 둔다.
|
||||
- 1회차 표의 두 파일(test_b19, test_version_consistency)은 이번에 마크로 덮였다.
|
||||
|
||||
[VERDICT: NOT PASS]
|
||||
Reference in new issue
Block a user