release(v4.9.5): a claude purge removes every path the session owns (Issue #31, PR #59) - archive the review reports, bump the lockstep version, load logroot eagerly
Review loop (--review-only, --all-reviewer, focused on this Mac: macOS, /usr/bin/python3 3.9.6, bash 3.2): round 1 (@6f4f40a) agy and grok PASS, claude and codex NOT PASS (a non-uuid id `memory` purged the auto-memory dir, a linked dir below a root was followed, a NaN startedAt counted as dead), sent as a PR comment and fixed by the author in eleven commits; round 2 (@2a8d738) confirmed all three fixed but 4/4 NOT PASS on one test holder (`sh -c "sleep 120" <uuid>` loses the uuid on macOS /bin/sh), fixed in de6f3fc; round 3 (@de6f3fc) 4/4 PASS. Full suite on macOS / Python 3.9.6 @de6f3fc: 1934 passed, 56 skipped, 1 error (the known #55 false positive: agy conversations of another workspace). The real ~/.claude, /private/tmp/claude-<uid> and herdr panes unchanged. Also names lib_py.delegation.logroot in eager.CORE_MODULES (the v4.9.4 review's non-blocking note). 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
de6f3fc81f
commit
6fd417a7b7
32 files changed
+916
-26
No files matched your search
@@ -0,0 +1,77 @@
|
||||
# PR #59 3차 Mac 리뷰
|
||||
|
||||
판정: **PASS**. base..head 누적 변경에 대해 병합을 막을 추가 결함을 발견하지 않았다. 2차 리뷰에서 남았던 macOS UUID 명령행 보유자 테스트 실패가 해결됐으며, 수정한 테스트가 정규화 회귀를 실제로 검출하는 것도 확인했다.
|
||||
|
||||
## 리뷰 identity
|
||||
|
||||
- Job: `d5e47fc2`
|
||||
- Loop: `loop-20261017T145452Z-6c5aa6`
|
||||
- Base: `26e2c43753169671b600d03274901dbe203988dd`
|
||||
- Head: `de6f3fc81f8c33a9d2335320742dc5a47f566cda`
|
||||
- Tree: `ffc291e6fc93822070f2b9f1d17009e83f176fcf`
|
||||
- 검증 경로: `/var/folders/q_/68sxgw3j073dgjg8wl9s08vw0000gn/T/mam-review/loop-20261017T145452Z-6c5aa6/1`
|
||||
- macOS / 시스템 Python 3.9.6 / bash 3.2 / BSD ps. pytest는 지정된 제어 저장소 `.venv/bin/python` 사용.
|
||||
|
||||
시작과 종료 시 HEAD/tree가 브리프와 일치했고 `git status --short` 출력은 없었다. creator 트리에서 실행하거나 수정하지 않았다. 제품 코드, 원본 테스트, 브랜치 및 커밋 변경 없음. 회귀 대조군만 검증 HEAD의 별도 임시 archive 복사본에서 변경했다.
|
||||
|
||||
## 이번 수정 검증
|
||||
|
||||
`git diff 2a8d738..HEAD`는 `tests/test_issue31_purge_residual.py`의 프로세스 생성 한 줄 변경과 설명 주석 두 줄뿐이다. `.agents` 제품 코드와 문서, 다른 테스트 및 공통 fixture는 이전 리뷰 HEAD와 동일하다.
|
||||
|
||||
- `tests/test_issue31_purge_residual.py:317`: `[sys.executable, "-c", "import time; time.sleep(120)", conv]`로 UUID를 Python argv에 남긴다. macOS sh의 마지막 명령 exec 최적화를 피하는 적절한 최소 수정이다.
|
||||
- 독립 확인에서 새 UUID로 동일한 Python 프로세스를 만들고 0.05초 뒤 BSD `ps -p <pid> -o args=`를 읽었다. 명령행 끝에 lowercase UUID가 유지됐다.
|
||||
- `:320`의 보유자 단언은 그대로이며 `:321`~`:323`의 finally kill/wait도 유지됐다. 독립 프로브에서 kill/wait 후 반환 코드 -9, 해당 PID의 ps 출력 없음으로 정리를 확인했다.
|
||||
- 원본 HEAD의 upper/mixed 테스트는 둘 다 통과했다. 세션 metadata 기반 live 및 CLI exit 4, 그 프로세스를 죽인 후 명령행 기반 live, 이후 purge/잔여물 없음까지 기존 검증을 그대로 수행한다.
|
||||
|
||||
### 회귀 검출 대조군
|
||||
|
||||
검증 HEAD를 `/tmp/review-d5e47fc2-oqyptnum/mutation`으로 git archive하고, **제품 원본이 아닌 복사본에서만** `.agents/skills/lib_py/agents/adapters/claude.py:354`의 `for u in {canon, uuid}`를 `for u in {uuid}`로 바꿨다. 세션 파일 조회의 정규화 및 다른 코드는 유지해 명령행 소문자 검색만 제거했다.
|
||||
|
||||
동일 테스트 노드 `tests/test_issue31_purge_residual.py::test_any_spelling_of_the_uuid_is_the_lowercase_session`를 실행한 결과 **2 failed in 1.52s**, pytest 종료 코드 1. upper/mixed 모두 `:320`의 `a command line naming the lowercase id` 단언에서 실패했다. 그 앞의 세션 파일 기반 판정 및 CLI exit 4는 통과했다. 따라서 이번 픽스처 변경은 단언을 약화하지 않으며, 정확히 명령행 UUID 철자 처리 회귀를 검출한다. 이 의도적인 실패는 원본 HEAD의 실패가 아니다.
|
||||
|
||||
## 실행 결과
|
||||
|
||||
원본 HEAD에서 다음 네 모듈을 함께 실행했다.
|
||||
|
||||
- `tests/test_issue31_purge_residual.py`
|
||||
- `tests/test_issue42_skill_blocks.py`
|
||||
- `tests/test_issue55_agent_homes.py`
|
||||
- `tests/test_a4_adapter_contract.py`
|
||||
|
||||
결과: **148 passed, 1 skipped in 38.52s**, pytest 종료 코드 0. 전체 스위트는 브리프대로 오케스트레이터 범위이며 이 리뷰에서 전체 통과를 주장하지 않는다.
|
||||
|
||||
실행 형식은 `PYTHONDONTWRITEBYTECODE=1 <제어저장소>/.venv/bin/python -m pytest -p no:cacheprovider --basetemp=/tmp/review-d5e47fc2-oqyptnum/pytest-head -q <위 네 모듈>`이다. 테스트 실행 전 HERDR/MAM/WORKSPACE/DELEGATE_JOB 바인딩 및 CLAUDE_CONFIG_DIR를 제거하고 HOME/HOME_DIR, CLAUDE_PROJECT_DIR, CLAUDE_CODE_TMPDIR, TMPDIR를 임시 경로로 설정했다. 실제 config 대신 임시 HOME/.claude 또는 각 테스트가 지정하는 임시 config만 사용한다. issue31의 own_tmp_roots fixture는 자식 Python까지 고정 /tmp fallback을 임시화한다. 다른 모듈에는 테스트 프로세스 전용 sitecustomize로 실제 `/tmp/claude-<uid>` 후보를 제외하는 추가 가드를 적용했다.
|
||||
|
||||
- base..head `git diff --check` 통과.
|
||||
- 변경 Python 파일 모두 시스템 Python 3.9의 AST 구문 검사 통과.
|
||||
- 변경 shell 파일 모두 `/bin/bash -n` 통과.
|
||||
- 실제 Claude나 다른 실제 에이전트를 실행/중지/purge하지 않았다. 실제 세션에 대한 in-use 호출도 없었다. 실제 .mam/.mam.env/monitor/herdr 설정을 변경하지 않았다. 지정된 잡 이벤트와 보고서만 제어 평면에 기록한다.
|
||||
|
||||
## 누적 변경 재확인 및 이전 리뷰 근거
|
||||
|
||||
2차 리뷰 리포트: `/Users/godopu16/PuKi/laa/canary_projects/multi-agent-mux/.mam/jobs/a59e709d/codex-reports/report-final.md`.
|
||||
|
||||
이번 제품 코드가 그 HEAD와 동일함을 diff로 확인했다. 누적 diff의 공통 base/CLI/stop 변경과 Claude 소유 경로 선택·삭제 흐름을 재검토하고 관련 테스트를 재실행했다.
|
||||
|
||||
- 잘못된 UUID로 memory 등 공유 폴더에 도달하는 문제: canonical UUID 가드 및 소문자 경로 처리 유지. malformed/non-UUID 보존 테스트 통과.
|
||||
- 상위 링크를 통한 범위 밖 삭제: `_inside`의 lstat 검사와 `_owned_paths` 필터 유지. 링크 뒤 잔여물 보존·보고, leaf 링크만 제거, 루트 자체 링크 허용 테스트 통과.
|
||||
- NaN/inf/float 범위 초과 startedAt: 유효 시각이 아니면 live로 처리하는 가드 유지. 관련 숫자 경계와 CLI 테스트 통과.
|
||||
- 기존 세 결함의 수정 전 실패 검증은 2차 리뷰에서 수행한 결과를 재사용한다. memory/상위 링크/NaN 및 추가 OverflowError 회귀 테스트가 각 수정 직전 코드에서 실패했다. 이번에는 그 옛 커밋 테스트를 반복하지 않았다.
|
||||
- BSD ps/UTC 시작 시각 비교, PID 재사용 판별, 판정 불가 시 live 처리, tmp root 우선순위와 realpath 중복 제거, 소유권 state.json을 통한 jobs 선택, 다른 세션/공유 파일 보존 테스트 통과.
|
||||
- `dd292c1`의 링크 뒤 orphan만 남은 경우도 Claude로 선택되어 residual로 보고하는 테스트 통과.
|
||||
- `base.py`의 residual 헬퍼 및 in-use 힌트, CLI stdout JSON/stderr 안내 분리, stop exit 4와 records preserved, 정상 purge 후 registry 행 제거 및 residual 출력 계약을 재확인했다.
|
||||
- CLAUDE_CONFIG_DIR 적용, codex/grok/opencode residual 테스트, stop SKILL/code-block 정합성 테스트 통과.
|
||||
- 실제 Mac 홈/tmp 구조의 read-only 메타데이터 확인은 동일 환경의 2차 리뷰 관측을 재사용했다. `/tmp`→`/private/tmp`, 별도 TMPDIR, per-uid workspace-key/UUID scratchpad 배치 및 ~/.claude 부속 디렉터리 구조는 그 보고서에 기록돼 있다. 이번에는 실제 세션 내용을 읽거나 실제 경로에 파괴적 검증을 추가하지 않았다.
|
||||
|
||||
브리프에서 수용한 비차단 제한은 유지된다: 링크된 projects/<key> 뒤 transcript는 삭제하지 않고 residual로 보고, lowercase 질의가 uppercase argv만 가진 보유자를 못 보는 경우, 직접 purge_artifacts 호출에는 in-use gate가 없는 점. 이를 이번 수정의 신규 차단 결함으로 재분류하지 않는다. 동시 파일시스템 경로 교체까지 원자적으로 방어함을 검증한 것은 아니다.
|
||||
|
||||
## 증거 파일
|
||||
|
||||
`/tmp/review-d5e47fc2-oqyptnum` (실경로 `/private/tmp/...`):
|
||||
|
||||
- `head.log`: 원본 HEAD 148 passed / 1 skipped.
|
||||
- `mutation.log`: 명령행 정규화 제거 대조군의 의도된 2건 실패.
|
||||
- `argv-probe.json`: lowercase UUID가 남은 BSD ps 결과, kill/wait 후 PID 부재.
|
||||
- `mutation/`: 원본과 분리된 회귀 대조군 복사본.
|
||||
|
||||
[VERDICT: PASS]
|
||||
Reference in new issue
Block a user