[Test] mam_sandbox 를 쓰지 않는 테스트가 WORKSPACE_ROOT=저장소일 때 실제 .mam/delegate_job_logs 에 감사 로그를 남김 (T1-11/T1-12/T1-17, j1/job_1) #20

Closed
opened 2026-09-13 14:22:03 +00:00 by Godopu · 3 comments
Owner

증상

에이전트(creator/reviewer)가 저장소 루트에서 pytest tests/test_issue6_fail_closed.py 등을 실행하면, 실제 .mam/delegate_job_logs/ 아래에 레지스트리 레코드가 없는 감사 로그 디렉터리가 남는다(2026-09-13 관측: 8c9ea839, e47569e1 = T1-12/T1-11, test_t1_17_job, j1, job_1 외 다수).

같은 시각에 오케스트레이터가 돌리던 전체 스위트의 tests/test_issue15_registry_isolation.py::test_onboarding_job_follows_workspace_root_alone 이 이 디렉터리들을 "누수"로 잡아 거짓 실패했다(재실행 시 통과).

원인

  • #15 는 mam_sandbox 픽스처에 MAM_JOBS_DIR/DELEGATE_JOB_LOGS_DIR 를 넣어 격리했지만, mam_sandbox 를 쓰지 않고 tmp_path 레지스트리만 넘기는 테스트(T1-11, T1-12, T1-17, phase1 의 j1/job_1 등)는 감사 로그 경로를 지정하지 않는다.
  • 감사 로그 경로는 DELEGATE_JOB_LOGS_DIR → $WORKSPACE_ROOT/.mam/delegate_job_logs → cwd 순으로 풀리므로, 에이전트 세션처럼 WORKSPACE_ROOT 가 저장소로 잡힌 환경에서는 실제 디렉터리에 쓴다.
  • 오케스트레이터의 Bash 환경에서는 WORKSPACE_ROOT 가 없어서 재현되지 않았고, #15 의 세션 가드도 .mam/jobs 만 센다.

제안

  1. tests/conftest.py 에 function-scope autouse 픽스처를 두어 모든 테스트의 기본값으로 MAM_JOBS_DIR/DELEGATE_JOB_LOGS_DIR 를 tmp_path 아래로 설정한다(mam_sandbox 는 그 위에 덮어쓰고, 기본 해석 규칙을 검증하는 #15 테스트는 명시적으로 delenv 한다).
  2. #15 의 세션 스코프 가드를 .mam/delegate_job_logs 에도 적용한다.
  3. 동시 실행 오탐 방지: test_issue15_registry_isolation.py 의 전/후 비교는 자기 테스트가 만든 잡 id 만 대상으로 판정한다.

우선순위: Low — 실제 동작 결함이 아니라 테스트 위생. 발견 경위: #18 리뷰 루프와 전체 스위트를 병행 실행하던 중.

## 증상 에이전트(creator/reviewer)가 저장소 루트에서 `pytest tests/test_issue6_fail_closed.py` 등을 실행하면, 실제 `.mam/delegate_job_logs/` 아래에 레지스트리 레코드가 없는 감사 로그 디렉터리가 남는다(2026-09-13 관측: `8c9ea839`, `e47569e1` = T1-12/T1-11, `test_t1_17_job`, `j1`, `job_1` 외 다수). 같은 시각에 오케스트레이터가 돌리던 전체 스위트의 `tests/test_issue15_registry_isolation.py::test_onboarding_job_follows_workspace_root_alone` 이 이 디렉터리들을 "누수"로 잡아 거짓 실패했다(재실행 시 통과). ## 원인 - #15 는 `mam_sandbox` 픽스처에 `MAM_JOBS_DIR`/`DELEGATE_JOB_LOGS_DIR` 를 넣어 격리했지만, `mam_sandbox` 를 쓰지 않고 `tmp_path` 레지스트리만 넘기는 테스트(T1-11, T1-12, T1-17, phase1 의 `j1`/`job_1` 등)는 감사 로그 경로를 지정하지 않는다. - 감사 로그 경로는 `DELEGATE_JOB_LOGS_DIR` → `$WORKSPACE_ROOT/.mam/delegate_job_logs` → cwd 순으로 풀리므로, 에이전트 세션처럼 `WORKSPACE_ROOT` 가 저장소로 잡힌 환경에서는 실제 디렉터리에 쓴다. - 오케스트레이터의 Bash 환경에서는 `WORKSPACE_ROOT` 가 없어서 재현되지 않았고, #15 의 세션 가드도 `.mam/jobs` 만 센다. ## 제안 1. `tests/conftest.py` 에 function-scope autouse 픽스처를 두어 모든 테스트의 기본값으로 `MAM_JOBS_DIR`/`DELEGATE_JOB_LOGS_DIR` 를 `tmp_path` 아래로 설정한다(`mam_sandbox` 는 그 위에 덮어쓰고, 기본 해석 규칙을 검증하는 #15 테스트는 명시적으로 `delenv` 한다). 2. #15 의 세션 스코프 가드를 `.mam/delegate_job_logs` 에도 적용한다. 3. 동시 실행 오탐 방지: `test_issue15_registry_isolation.py` 의 전/후 비교는 자기 테스트가 만든 잡 id 만 대상으로 판정한다. 우선순위: Low — 실제 동작 결함이 아니라 테스트 위생. 발견 경위: #18 리뷰 루프와 전체 스위트를 병행 실행하던 중.
Author
Owner

추가 관측 2건(PR #22 병합 검토 중): (1) tests/test_issue14_delivery_ack.py::_job_for_inprocess_publish 가 ambient WORKSPACE_ROOT 때문에 실제 .mam/delegate_job_logs 에 감사 로그를 남김 — 같은 원인. (2) tests/test_issue18_liveness_contract.py::test_acceptance5_remote_runner_completes_a_job_over_the_broker_only 는 공용 브로커에서 두 실행이 겹치면 같은 세션 이름(sim-worker)의 러너가 서로의 dispatch 를 소비함 — 세션 이름을 uuid4 로 만들어 격리할 것.

추가 관측 2건(PR #22 병합 검토 중): (1) `tests/test_issue14_delivery_ack.py::_job_for_inprocess_publish` 가 ambient `WORKSPACE_ROOT` 때문에 실제 `.mam/delegate_job_logs` 에 감사 로그를 남김 — 같은 원인. (2) `tests/test_issue18_liveness_contract.py::test_acceptance5_remote_runner_completes_a_job_over_the_broker_only` 는 공용 브로커에서 두 실행이 겹치면 같은 세션 이름(`sim-worker`)의 러너가 서로의 dispatch 를 소비함 — 세션 이름을 uuid4 로 만들어 격리할 것.
Author
Owner

해결 — PR #29 (병합 시 닫힘)

#21 항목 7 의 시험 운영으로, 워크트리 creator 가 fix/issue-20 에서 구현했다(PR #22 권고 ④ 포함). 커밋은 PR #29 에 포함된다.

커밋 내용
3433ffd 수집 전에 ambient 제어 평면 바인딩(WORKSPACE_ROOT·AGENT_SESSIONS_YAML·MAM_JOBS_DIR·DELEGATE_JOB_LOGS_DIR)을 기록·제거하고, 테스트마다 레지스트리·감사 로그 기본 루트를 tmp 로
7bd695c 권고 ④: issue14 in-process publish 헬퍼의 감사 로그를 tmp_path 로
c5844a8 기록된 제어 평면의 .mam/jobs·.mam/delegate_job_logs 새 항목 세션 가드
a2be70d issue15 누수 검사는 자기 잡 id 와 세션만 판정(동시 실행 오탐 방지)
46ea4cc 상태 격리 회귀 테스트 (tests/test_issue20_state_isolation.py)

검증

  • 워크트리 creator pane 과 같은 조건(바인딩 4개가 본 체크아웃을 가리킴)에서 전체 스위트: 980 passed / 33 failed / 2 skipped.
  • 실행 전·후 본 체크아웃의 실제 .mam/jobs·.mam/delegate_job_logs 항목: 787 → 787, 새 항목 0.
  • 실패 33건은 이 호스트의 기준 실패(#28)이며, test_t1_4_broker_unavailable_fail_closed 는 이번 격리로 해소됐다.
  • 리뷰: claude·agy·opencode 1회차 만장일치 PASS.

수정 전 누적돼 있던 누수 항목(j1, job_1, test_t1_17_job — 레지스트리 레코드 없는 테스트 산출물)은 이 호스트의 .mam/delegate_job_logs 에서 정리했다.

## 해결 — PR #29 (병합 시 닫힘) #21 항목 7 의 시험 운영으로, 워크트리 creator 가 `fix/issue-20` 에서 구현했다(PR #22 권고 ④ 포함). 커밋은 PR #29 에 포함된다. | 커밋 | 내용 | |---|---| | `3433ffd` | 수집 전에 ambient 제어 평면 바인딩(`WORKSPACE_ROOT`·`AGENT_SESSIONS_YAML`·`MAM_JOBS_DIR`·`DELEGATE_JOB_LOGS_DIR`)을 기록·제거하고, 테스트마다 레지스트리·감사 로그 기본 루트를 tmp 로 | | `7bd695c` | 권고 ④: issue14 in-process publish 헬퍼의 감사 로그를 tmp_path 로 | | `c5844a8` | 기록된 제어 평면의 `.mam/jobs`·`.mam/delegate_job_logs` 새 항목 세션 가드 | | `a2be70d` | issue15 누수 검사는 자기 잡 id 와 세션만 판정(동시 실행 오탐 방지) | | `46ea4cc` | 상태 격리 회귀 테스트 (`tests/test_issue20_state_isolation.py`) | ### 검증 - 워크트리 creator pane 과 **같은 조건**(바인딩 4개가 본 체크아웃을 가리킴)에서 전체 스위트: 980 passed / 33 failed / 2 skipped. - 실행 전·후 본 체크아웃의 실제 `.mam/jobs`·`.mam/delegate_job_logs` 항목: 787 → 787, **새 항목 0**. - 실패 33건은 이 호스트의 기준 실패(#28)이며, `test_t1_4_broker_unavailable_fail_closed` 는 이번 격리로 해소됐다. - 리뷰: claude·agy·opencode 1회차 만장일치 PASS. 수정 전 누적돼 있던 누수 항목(`j1`, `job_1`, `test_t1_17_job` — 레지스트리 레코드 없는 테스트 산출물)은 이 호스트의 `.mam/delegate_job_logs` 에서 정리했다.
Author
Owner

v4.7.0 (PR #29, main 6fc9194) 로 해결. tests/conftest.py 가 수집 전에 ambient 제어 평면 바인딩을 기록·제거하고 테스트마다 레지스트리·감사 로그 기본 루트를 tmp 로 보낸다. 기록된 제어 평면의 .mam/jobs·.mam/delegate_job_logs 에 새 항목이 생기면 세션 가드가 실패시키고, 기본 해석 규칙을 검증하는 #15 테스트는 명시적으로 옵트아웃한다. MAM_ENV_FILE 도 존재하지 않는 경로로 고정된다. 병합 워크스페이스에서 전체 스위트 전후 실제 .mam/jobs 레코드 추가 0건(creator 검증 잡 7af872b6, 리뷰 리포트 .agents/reports/).

v4.7.0 (PR #29, main `6fc9194`) 로 해결. `tests/conftest.py` 가 수집 전에 ambient 제어 평면 바인딩을 기록·제거하고 테스트마다 레지스트리·감사 로그 기본 루트를 tmp 로 보낸다. 기록된 제어 평면의 `.mam/jobs`·`.mam/delegate_job_logs` 에 새 항목이 생기면 세션 가드가 실패시키고, 기본 해석 규칙을 검증하는 #15 테스트는 명시적으로 옵트아웃한다. `MAM_ENV_FILE` 도 존재하지 않는 경로로 고정된다. 병합 워크스페이스에서 전체 스위트 전후 실제 `.mam/jobs` 레코드 추가 0건(creator 검증 잡 7af872b6, 리뷰 리포트 `.agents/reports/`).
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tmpl/multi-agent-mux#20