Second-round reports of the fix/issue-12-8-7 review loop on ea911d7:
planner-reviewer-claude-01 (b368210a), reviewer-agy-01 (3f5d1cd4) and
reviewer-grok-01 (cc059645), all [VERDICT: PASS]. The codex review is
deferred until its usage limit resets; the branch merges only after it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
ea911d7842
commit
9d52bb7024
3 files changed
+357
No files matched your search
@@ -0,0 +1,144 @@
|
||||
# 🔍 Review Report — Job b368210a (branch `fix/issue-12-8-7` 2회차, HEAD `ea911d7`)
|
||||
|
||||
- **Reviewer**: `planner-reviewer-claude-01` (role: planner,reviewer) · 2026-09-13
|
||||
- **대상**: `git log 8a09e02..HEAD` 의 네 커밋. 1회차에서 PASS 한 부분은 회귀 중심으로, 새 커밋 2건은 정밀 검토했다.
|
||||
- `e629cc1`: fix #12·#8·#7
|
||||
- `4176d75`: release v4.4.4
|
||||
- **`0fedae2`**: N1 수정 — 새 커밋
|
||||
- **`ea911d7`**: 비차단 권고 반영 — 새 커밋
|
||||
- **HEAD 고정**: 리뷰 시작(12:31)부터 끝까지 HEAD 는 `ea911d7`, 작업 트리는 깨끗했다. 같은 HEAD 에 대한 고아 잡 `0cf8d1c0` 의 PASS 판단을 이 잡에서 **새 증거로 다시 확인**했다(샌드박스·테스트 모두 이 잡에서 재실행).
|
||||
- **방법**:
|
||||
- 코드 정독
|
||||
- `$TMPDIR` 샌드박스 재현(모두 끝나고 삭제)
|
||||
- `scrub-secrets` 레지스트리
|
||||
- `update.sh` 병합 블록 이전/이후 비교
|
||||
- `git archive` 사본에서 #7 테스트 변이 검사
|
||||
- 실제 레지스트리는 **읽기 전용** 집계만 했다(`scrub-secrets` 는 실제 `.mam/jobs` 에 `--dry-run` 으로도 실행하지 않음)
|
||||
- 브리프 지정 테스트(실제 `.mam/jobs` 스냅샷 비교)
|
||||
- 정적 검사
|
||||
- 리뷰 중 45초 간격 `progress` heartbeat 발행. 코드 수정 없음.
|
||||
|
||||
## 0. 1회차 결과와 처리 (브리프 기준)
|
||||
|
||||
| 리뷰어 | 1회차(`4176d75`) 판정 |
|
||||
|---|---|
|
||||
| claude | **NOT PASS** — N1: `scrub-secrets` 가 키의 존재로 대상을 골라 null 비밀번호 레코드 901건을 재기록 |
|
||||
| agy | PASS |
|
||||
| grok | PASS |
|
||||
| codex | 사용량 한도로 리뷰 불가(이번 회차 제외, 한도 복구 후 별도 리뷰 예정) |
|
||||
|
||||
creator 는 N1 을 `0fedae2` 로 고쳤고, 비차단 권고 1·2번(`update.sh` 병합 견고화, #7 테스트 보강)을 `ea911d7` 로 반영했다.
|
||||
|
||||
## 1. `0fedae2` — `scrub-secrets` 선택 조건 — ✅
|
||||
|
||||
### 1-1. 코드·문서
|
||||
- `registry.py` `_cmd_scrub_secrets` 의 선택 조건이 `"password" in broker` → **`broker.get("password")`** 로 바뀌었다. 저장된 값이 있는 레코드만 대상이다.
|
||||
- `registry_lock` 아래에서 동작하고, `--dry-run` 이면 기록하지 않으며, 기록은 `_atomic_write_record` 를 거친다.
|
||||
- 서술도 코드와 일치한다.
|
||||
- `registry.md:60`: "cleaned on their next write; `registry.py scrub-secrets [--dry-run]` strips …"
|
||||
- `VERSIONS.md:46`: "비밀번호 값이 실제로 저장된 레코드만 … null 키는 … 대상도 보고도 아니며, 다음 쓰기 때 `_atomic_write_record` 가 정리"
|
||||
- `registry.py` 는 `0fedae2` 이후 무변경이다(`git diff --stat 0fedae2..HEAD` 는 `update.sh`·#7 테스트뿐).
|
||||
|
||||
### 1-2. 샌드박스 재현 (이 잡에서 새로 실행)
|
||||
- 레코드 네 개를 만들었다: `password: None` / `""` / 가짜 값(uuid4) / 키 없음. 모두 `host/port/tls/username`·`prompt` 를 가진다.
|
||||
- 대상 안전장치: 최상위 `--registry-dir`(`registry.py:270`, 서브파서는 `--dry-run` 만 정의)에 더해 `MAM_JOBS_DIR` 도 샌드박스로 지정했다. dry-run 출력이 샌드박스 경로를 가리킬 때만 실제 실행으로 넘어가게 했다.
|
||||
|
||||
| 단계 | 결과 |
|
||||
|---|---|
|
||||
| `--dry-run` | rc 0, "would scrub **1** record(s) under `<sandbox>`: **k_real**", 네 파일 모두 바이트 동일 |
|
||||
| 실제 실행 | rc 0, "scrubbed 1 record(s) under `<sandbox>`: k_real", 바뀐 파일은 `k_real` 하나 |
|
||||
| 실행 후 | `k_real` 만 `password` 키 제거. `k_null`·`k_empty` 는 키 유지(다음 쓰기에 맡김), `k_absent` 무변경. 네 레코드 모두 나머지 broker 필드와 `prompt` 보존 |
|
||||
|
||||
### 1-3. 실제 레지스트리 (읽기 전용 집계, 명령 미실행)
|
||||
910건 중 새 규칙으로 선택되는 레코드는 **0건**이다. null/빈 password 키를 가진 901건은 선택되지 않는다.
|
||||
|
||||
### 1-4. 회귀 테스트
|
||||
`test_scrub_secrets_cli_migrates_a_registry` 가 레거시 `password: null` 레코드를 포함한다. dry-run 목록에 없고, 실제 실행 후에도 바이트 단위로 동일함을 단정한다.
|
||||
|
||||
## 2. `ea911d7` — `deploy/update.sh:239-257` `install_state` 병합 — ✅
|
||||
|
||||
**코드**
|
||||
- **끝 개행 보장**(241-245): `[ -s … ] && [ -n "$(tail -c1 …)" ]`.
|
||||
- 명령 치환이 끝 개행을 지우므로, 마지막 바이트가 개행이 아닐 때만 `\n` 을 붙인다. 빈 파일은 건너뛴다.
|
||||
- **`=` 없는 줄 무시**(247-250): `case "$line" in *=*)`.
|
||||
- **정확 키 매칭**(254): `awk -F= -v k="$key" '$1 == k …'`.
|
||||
- `key="${line%%=*}"` 와 awk `$1` 은 둘 다 첫 `=` 앞부분이라 기준이 같다.
|
||||
- `if !` 조건 안이라 `update.sh:8` 의 `set -euo pipefail` 아래에서도 안전하다.
|
||||
- 실패 경로 `restore_on_failure` 는 무변경이다.
|
||||
|
||||
**샌드박스 비교**(이 잡에서 새로 실행): HEAD 와 `0fedae2` 의 블록을 그대로 추출해, 같은 입력을 `bash -euo pipefail` 로 실행했다.
|
||||
- 새 파일: `axb=new`, `version=2`(끝 개행 없음)
|
||||
- 이전 파일: `a.b=old`, `axb=old`, `gitignore_created=1`, `# comment`, `noequals`, `=emptykey`, `k=v=w`, `version=1`(끝 개행 없음)
|
||||
|
||||
| 블록 | 결과 |
|
||||
|---|---|
|
||||
| `0fedae2` | 두 키가 한 줄로 붙어 `version=2gitignore_created=1` 이 됨. `a.b=old` 유실(정규식 `^a.b=` 가 `axb=` 에 일치). `# comment`·`noequals` 추가 |
|
||||
| `ea911d7` | `axb=new` / `version=2` / `a.b=old` / `gitignore_created=1` / `k=v=w` — 기대와 일치, rc 0 |
|
||||
| `ea911d7` 추가 확인 | 두 번째 실행 결과 동일(멱등). 새 파일이 빈 경우·없는 경우 모두 `gitignore_created=1` 한 줄 |
|
||||
|
||||
**참고(무해)**: `awk -v` 는 값의 역슬래시 이스케이프를 해석한다. 하지만 `install_state` 키는 `install.sh:597,601` 의 `gitignore_created` 뿐이라 영향이 없다.
|
||||
|
||||
`test_issue8_update_state.py`(실제 install→update 사이클), `test_deploy_layout.py`, `test_deploy_freshness.py` 모두 통과했다(§5).
|
||||
|
||||
## 3. `ea911d7` — #7 테스트 2건이 실제 코드 경로를 검증하는가 — ✅
|
||||
|
||||
### 3-1. 코드 경로
|
||||
**`test_idle_pane_in_a_later_workspace_is_reused`**
|
||||
- 상황: w1 은 가득 찼고(4), w2 에 agent 없는 pane `w2:p_idle` 이 있다.
|
||||
- `lib.sh` 가 따라가는 경로:
|
||||
1. `lib.sh:764-777`: 후보마다 idle 필터 `not p.get('agent')` 를 적용한다. w1 에서는 찾지 못한다.
|
||||
2. `lib.sh:812-815`: layout 이 overflow 이므로 `continue`.
|
||||
3. `lib.sh:778-786`: w2 의 idle pane 을 선택하고 `break`.
|
||||
- 단정: split·create 가 없고, `agent start` 대상이 `w2:p_idle` 이다.
|
||||
|
||||
**`test_ws_label_rename_targets_only_the_chosen_workspace`**
|
||||
- 단정: rename 호출이 정확히 `["workspace","rename","w2","team-b"]` 하나다(`lib.sh:854-856`).
|
||||
|
||||
`lib.sh` 는 `e629cc1` 이후 무변경이다.
|
||||
|
||||
### 3-2. 변이 검사 (`git archive HEAD` 사본, 저장소 무변경)
|
||||
- `conftest.py:22` 가 자기 위치 기준으로 `.agents/skills` 를 복사하므로, 사본의 테스트는 사본의 `lib.sh` 를 실행한다.
|
||||
|
||||
| 사본 | 변이 | idle 재사용 테스트 | rename 대상 테스트 |
|
||||
|---|---|---|---|
|
||||
| control | 없음 | PASSED | PASSED |
|
||||
| M1 | `lib.sh:771` idle 필터를 `if False:` 로(idle pane 을 찾지 못함) | **FAILED** — "an idle pane must be reused, not split around"(`w2:p1` 에서 split 발생) | PASSED |
|
||||
| M2 | `lib.sh:855` rename 대상을 첫 후보(`${candidate_wss%%[[:space:]]*}`)로 | PASSED | **FAILED** — `[['workspace','rename','w1','team-b']]` ≠ 기대값(w2) |
|
||||
|
||||
- 각 테스트는 자기 코드 경로의 변이에서만 실패하고, 다른 테스트의 변이에는 영향받지 않는다. 두 테스트가 브리프의 "idle pane 우선"과 "rename 대상"을 **각각 독립적으로 고정**함이 확인되었다.
|
||||
- 변이 실행 전후 실제 `.mam/jobs` 항목 수는 2401 로 동일했다. 사본은 끝나고 삭제했다.
|
||||
|
||||
## 4. 버전 락스텝 · 릴리스 커밋 — ✅
|
||||
- `lib.sh:32` `MAM_VERSION="4.4.4"`, `eager.py:16` `FRAMEWORK_VERSION = "4.4.4"`, SKILL.md 8개 `version: 4.4.4`.
|
||||
- `verify_framework_version()` 통과(`env -u MAM_VERSION`).
|
||||
- 현재 문서(README·README.ko·BOOTSTRAP·BOOTSTRAP.ko·MESSAGING) 모두 4.4.4.
|
||||
- `VERSIONS.md` 밖에 남은 `4.4.3` 은 보관된 리뷰 리포트(`.agents/reports/…`)의 이력 서술뿐이다.
|
||||
- 릴리스 커밋 `4176d75` 제목은 `release(v4.4.4): bump framework and eight skills to 4.4.4 in lockstep` 그대로다.
|
||||
- ⚠️ 비차단: `VERSIONS.md:51` "신규 테스트 **8개** … `test_issue7_workspace_packing.py` **3개**" 는 `ea911d7` 이후 **10개 / 5개**다(§6-1).
|
||||
|
||||
## 5. 테스트 · 정적 검사 (HEAD `ea911d7`)
|
||||
- **브리프 지정 10파일 + `test_version_consistency` + `test_deploy_freshness`**: **275 passed in 154.9 s, rc 0**.
|
||||
- 실행 시점 HEAD `ea911d7` 을 기록으로 확인했다.
|
||||
- 실행 전후 실제 `.mam/jobs` 레코드 목록이 동일했다(추가 0건).
|
||||
- **정적 검사**:
|
||||
- `git diff --check 8a09e02...HEAD` 클린
|
||||
- `bash -n deploy/update.sh` 통과
|
||||
- 작업 트리 깨끗
|
||||
- shellcheck 는 미설치라 실행하지 못했다(대신 §2 샌드박스 실행으로 확인).
|
||||
|
||||
## 6. 비차단 권고 (후속)
|
||||
1. **`VERSIONS.md:51` 신규 테스트 수 정정**: 8 → 10, #7 3 → 5. 설명에 "뒤 후보의 idle pane 재사용, 선택된 워크스페이스만 rename" 추가. 병합 전 한 줄 수정을 권한다.
|
||||
2. `scrub-secrets` 서브커맨드 요약 도움말 `"remove broker.password from every job record"` 은 이제 약간 과장이다. `--dry-run` 도움말은 정확하다. 고정 캡처 `help-registry.txt` 와 함께 갱신할 것.
|
||||
3. `DelegationService` 를 라이브러리로 쓸 때 `ensure_env_loaded()` 선행, 명시 broker override 의 비밀번호를 env 로 제공한다는 점을 문서화.
|
||||
4. 토큰 우발 노출 심층 방어(이전 트리아지 권고 유지).
|
||||
|
||||
## 7. GM 참고
|
||||
- 이 판단은 `0cf8d1c0` 리포트와 같은 HEAD(`ea911d7`)에 대한 것이고, 결론도 같다.
|
||||
- `0cf8d1c0` 에서 지적한 "리뷰 중 커밋" 문제는 이번 브리프가 `ea911d7` 을 대상으로 명시하면서 해소되었다. 병합 시에는 agy·grok 의 2회차 리포트도 `ea911d7` 을 대상으로 했는지 확인할 것.
|
||||
|
||||
## 8. 종합
|
||||
- N1 은 최소 수정으로 해소되었다. 샌드박스, 실제 레지스트리 읽기 전용 집계(선택 0건), 회귀 테스트로 확인했다.
|
||||
- `ea911d7` 의 `update.sh` 병합 보강은 세 가지 가장자리를 바르게 고쳤다. 새 #7 테스트 2건은 해당 코드 경로를 실제로 고정한다(§3-2).
|
||||
- 버전 락스텝은 완전하다. 남은 것은 `VERSIONS.md:51` 테스트 수 한 줄(비차단)뿐이다. 설계 재검토는 필요 없다.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,151 @@
|
||||
# Peer Review Report: Branch `fix/issue-12-8-7` (Round 2 — Commits `0fedae2` & `ea911d7`)
|
||||
|
||||
- **Reviewer**: agy (session: `herdr:reviewer-agy-01`)
|
||||
- **Job ID**: `3f5d1cd4`
|
||||
- **Role**: Reviewer
|
||||
- **Target Branch**: `fix/issue-12-8-7`
|
||||
- **Base Commit**: `8a09e02` (v4.4.3)
|
||||
- **Evaluated Commits**:
|
||||
- `e629cc1` — `fix(issue-12,8,7): keep broker password out of records, keep fresh install stamps, pack sibling workspaces`
|
||||
- `4176d75` — `release(v4.4.4): bump framework and eight skills to 4.4.4 in lockstep`
|
||||
- `0fedae2` — `fix(issue-12): scrub-secrets selects only records with a stored password`
|
||||
- `ea911d7` — `fix(issue-8,7): harden install_state merge and pin sibling-workspace edge cases`
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
This Round 2 peer review evaluated the complete branch `fix/issue-12-8-7` up to `ea911d7`, focusing specifically on the resolutions introduced in commits `0fedae2` (N1 fix from Claude's Round 1 review: value-based filtering in `scrub-secrets`) and `ea911d7` (non-blocking hardening recommendations for `update.sh` `install_state` merge and two new edge-case tests for Issue #7 workspace packing).
|
||||
|
||||
Key verifications completed:
|
||||
1. **Commit `0fedae2` (N1 Resolution)**: `_cmd_scrub_secrets` now strictly tests `broker.get("password")` (value truthiness) rather than key presence. Unauthenticated records with `"password": null` (~900 in realistic registries) are ignored, preventing spurious rewrite churn and lock contention. Dry-run verified on live `.mam/jobs` (0 records reported).
|
||||
2. **Commit `ea911d7` (Update Hardening)**: `deploy/update.sh` ensures trailing newline on preexisting `install_state`, skips lines missing `=`, and utilizes `awk` with literal variable passing for exact key comparison (`$1 == k`). Failure recovery via `restore_on_failure` is intact.
|
||||
3. **Commit `ea911d7` (Issue #7 Workspace Edge Cases)**: Two new automated tests in `test_issue7_workspace_packing.py` confirm:
|
||||
- An idle pane in a subsequent candidate workspace is reused before attempting splits or workspace creation.
|
||||
- `MAM_WS_LABEL` rename applies exclusively to the chosen target workspace.
|
||||
4. **Version Lockstep v4.4.4**: Maintained consistently across `lib.sh`, `eager.py`, 8 `SKILL.md` manifests, `VERSIONS.md`, and documentation files.
|
||||
5. **Test Suite Verification**: 13/13 targeted tests and 231/231 regression tests passed cleanly with 0 job registry leaks.
|
||||
|
||||
---
|
||||
|
||||
## 2. Review of Commit `0fedae2` (Issue #12: Value-Based Password Scrubbing)
|
||||
|
||||
### 2.1 Value-Based Record Selection
|
||||
- In `.agents/skills/lib_py/delegation/registry.py` (`_cmd_scrub_secrets`):
|
||||
```python
|
||||
# Old:
|
||||
if not (isinstance(broker, dict) and "password" in broker):
|
||||
continue
|
||||
|
||||
# New (0fedae2):
|
||||
if not (isinstance(broker, dict) and broker.get("password")):
|
||||
continue
|
||||
```
|
||||
- **Analysis**:
|
||||
- Legacy records created under previous versions without authentication stored `"password": null`.
|
||||
- Testing `broker.get("password")` ensures only truthy values (non-empty strings containing actual passwords) trigger migration.
|
||||
- Records with `None`, `""`, or omitted `"password"` keys are untouched.
|
||||
- Verified on live workspace: `registry.py --registry-dir .mam/jobs scrub-secrets --dry-run` reports `would scrub 0 record(s) under .mam/jobs`, avoiding unnecessary rewrites.
|
||||
|
||||
### 2.2 Documentation & Specification Alignment
|
||||
- `registry.md`: Clarifies that `scrub-secrets` strips stored passwords, leaving empty/null keys to be dropped naturally on the record's next write via `_atomic_write_record`.
|
||||
- `VERSIONS.md`: Section 2 updated to emphasize that `"password": null` is not treated as a secret and is neither reported nor rewritten.
|
||||
|
||||
### 2.3 Automated Test Coverage
|
||||
- In `tests/test_issue12_registry_secrets.py`, `test_scrub_secrets_cli_migrates_a_registry` was expanded to create an unauthenticated job record with `"password": None`.
|
||||
- Verifies:
|
||||
- `empty not in dry.stdout` (dry run ignores null password).
|
||||
- `empty_path.read_text() == empty_before` (file is not modified).
|
||||
- Only genuine leaked passwords are reported and scrubbed.
|
||||
|
||||
---
|
||||
|
||||
## 3. Review of Commit `ea911d7` (Issue #8: `update.sh` Merge Hardening)
|
||||
|
||||
### 3.1 Install State Trailing Newline Guard
|
||||
- In `deploy/update.sh`:
|
||||
```bash
|
||||
if [ -s .mam/install_state ] && [ -n "$(tail -c1 .mam/install_state)" ]; then
|
||||
printf '\n' >> .mam/install_state
|
||||
fi
|
||||
```
|
||||
Guarantees that an existing `install_state` missing a final newline does not concatenate appended keys onto the last line.
|
||||
|
||||
### 3.2 Non-KV Line Rejection
|
||||
- Lines lacking `=` are skipped safely:
|
||||
```bash
|
||||
case "$line" in
|
||||
*=*) ;;
|
||||
*) continue ;;
|
||||
esac
|
||||
```
|
||||
|
||||
### 3.3 Exact Key Matching without Regex Side-Effects
|
||||
- Previously used `grep -q "^${key}="`, which could interpret regex metacharacters in key names.
|
||||
- Now uses `awk`:
|
||||
```bash
|
||||
if ! awk -F= -v k="$key" '$1 == k { found = 1 } END { exit !found }' .mam/install_state; then
|
||||
printf '%s\n' "$line" >> .mam/install_state
|
||||
fi
|
||||
```
|
||||
- Exact literal string equality `$1 == k` prevents false matches and escapes.
|
||||
- Full cycle verified via `tests/test_issue8_update_state.py`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Review of Commit `ea911d7` (Issue #7: Workspace Packing Edge Cases)
|
||||
|
||||
Two new regression tests were added to `tests/test_issue7_workspace_packing.py`:
|
||||
|
||||
1. `test_idle_pane_in_a_later_workspace_is_reused`:
|
||||
- Configures `w1` as full (4 agents) and `w2` with 1 active agent and 1 idle pane (`w2:p_idle`).
|
||||
- Starts 7th agent: verifies the candidate traversal checks `w1`, continues past overflow, checks `w2`, finds the idle pane, and starts the agent directly on `w2:p_idle` without splitting or creating a workspace.
|
||||
2. `test_ws_label_rename_targets_only_the_chosen_workspace`:
|
||||
- Configures `w1` (4 agents, full) and `w2` (1 agent).
|
||||
- Starts 8th agent with `MAM_WS_LABEL="team-b"`.
|
||||
- Confirms that only the target workspace `w2` is renamed: `[["workspace", "rename", "w2", "team-b"]]`. Preceding full candidate workspaces are untouched.
|
||||
|
||||
Both tests pass and accurately pin critical edge-case behaviors.
|
||||
|
||||
---
|
||||
|
||||
## 5. Version Lockstep v4.4.4 Verification
|
||||
|
||||
All components remain strictly locked at `4.4.4`:
|
||||
- `.agents/skills/lib.sh`: `MAM_VERSION="4.4.4"`
|
||||
- `.agents/skills/lib_py/loop/eager.py`: `FRAMEWORK_VERSION = "4.4.4"`
|
||||
- Frontmatter `version: 4.4.4` across all 8 skills (`create`, `stop`, `resume`, `status`, `monitor`, `delegate-job`, `loop`, `orc-onboard`).
|
||||
- `VERSIONS.md`: Current release v4.4.4, 8-row skills matrix, v4.4.4 changelog.
|
||||
- Badges and headers in `README.md`, `README.ko.md`, `BOOTSTRAP.md`, `BOOTSTRAP.ko.md`, and `MESSAGING.md`.
|
||||
- `lib_py.loop.eager.verify_framework_version()`: Verified OK.
|
||||
|
||||
---
|
||||
|
||||
## 6. Test Suite & Registry Integrity Audit
|
||||
|
||||
### 6.1 Targeted Test Execution
|
||||
Command:
|
||||
```bash
|
||||
.venv/bin/python -m pytest tests/test_issue7_workspace_packing.py tests/test_issue8_update_state.py tests/test_issue12_registry_secrets.py tests/test_version_consistency.py
|
||||
```
|
||||
**Result**: 13 passed in 19.47s (100% success).
|
||||
|
||||
### 6.2 Regression Test Execution
|
||||
Command:
|
||||
```bash
|
||||
.venv/bin/python -m pytest tests/test_herdr_shim_contract.py tests/test_layout.py tests/test_deploy_layout.py tests/test_issue5_phase1_delegation.py tests/test_issue5_phase2a_loop.py tests/test_loop_cli.py tests/test_issue5_phase4_runtime.py
|
||||
```
|
||||
**Result**: 231 passed in 128.99s (100% success).
|
||||
|
||||
### 6.3 Sandboxing & Leak Verification
|
||||
- Baseline `.mam/jobs` file count before execution: **2405**
|
||||
- File count after full test execution: **2405**
|
||||
- Leak delta: **0 files created or modified** in live registry.
|
||||
|
||||
---
|
||||
|
||||
## 7. Conclusion
|
||||
|
||||
The updates in `0fedae2` and `ea911d7` cleanly resolve the N1 finding and further harden update and workspace packing operations. All verification criteria are fully satisfied.
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,62 @@
|
||||
# 🔍 Review Report — Job cc059645 (`fix/issue-12-8-7` 2회차 @ `ea911d7`)
|
||||
|
||||
- **Reviewer**: `reviewer-grok-01` (role: reviewer) · 2026-09-13
|
||||
- **범위**: `git log`/`git diff` **`8a09e02...HEAD`** (루프 수집 diff 는 비어 있음)
|
||||
- **HEAD**: `ea911d7` `fix(issue-8,7): harden install_state merge and pin sibling-workspace edge cases`
|
||||
- **1회차 HEAD**: `4176d75` (grok PASS). 이번 초점: `0fedae2` (claude N1) + `ea911d7` (비차단 권고)
|
||||
- **안전**: 실제 `.mam/jobs` 에 `scrub-secrets` 미실행. 실제 홈 purge 없음. 소스 무변경. codex 세션 미접촉.
|
||||
|
||||
커밋: `e629cc1` → `4176d75` → **`0fedae2`** → **`ea911d7`**. `git diff --check 8a09e02...HEAD` 클린.
|
||||
|
||||
## (1) `0fedae2` N1 — scrub-secrets 값 기준 선택
|
||||
|
||||
`_cmd_scrub_secrets` (`registry.py:360`): `"password" in broker` → `broker.get("password")`. JSON `null`·빈 문자열·키 없음은 모두 falsy 라 목록에도 재기록에도 안 넣음. 값이 있는 문자열만 pop 후 `_atomic_write_record`. lock 범위는 그대로 전체 순회지만 **쓰기는 비밀이 있는 레코드만**.
|
||||
|
||||
`test_scrub_secrets_cli_migrates_a_registry`: dirty(`"leaked-earlier"`) 1건만 dry-run/실제 대상. `password: null` 레코드는 stdout 에 id 가 없고 파일 바이트 불변. 키 없는 clean 레코드도 불변. `--dry-run` 은 dirty 파일의 유출 문자열을 그대로 둠. 4176d75 에서는 null 키까지 세어 `would scrub 2` 가 났을 테스트.
|
||||
|
||||
`_atomic_write_record` 의 `_scrub_record_secrets` 는 여전히 키만 보면 pop — null 키는 **다음 일반 쓰기** 때 정리. scrub 가 901건을 재기록하지 않는 분업과 맞음.
|
||||
|
||||
문서: `VERSIONS.md` v4.4.4 항목 2, `registry.md:60-62` 가 “저장된 값만 / null 은 다음 쓰기”로 정합.
|
||||
|
||||
## (2) `ea911d7` #8 — install_state 병합 보강
|
||||
|
||||
`deploy/update.sh:243-256`:
|
||||
- 비어 있지 않고 마지막 바이트가 개행이 아니면 (`tail -c1` + `$(…)` 가 trailing newline 을 지우는 관용) `printf '\n'` — 첫 병합 키가 마지막 줄에 붙지 않음.
|
||||
- `case *=*` 로 `=` 없는 줄 무시.
|
||||
- `awk -F= -v k="$key" '$1 == k'` 정확 문자열 비교. `grep -q "^${key}="` 의 정규식 해석 없음.
|
||||
- 실패 `restore_on_failure` (`:168-171`) 는 세 파일 `cp -f` 그대로. 성공 경로만 변경.
|
||||
|
||||
`test_issue8_update_state.py` 실제 install→stale stamps→`update.sh --force` 통과(아래 스위트).
|
||||
|
||||
## (3) `ea911d7` #7 테스트 2건 — 실제 경로
|
||||
|
||||
`test_idle_pane_in_a_later_workspace_is_reused`: w1=4(overflow) + w2=1 + `state["panes"]` 에 agent 없는 `w2:p_idle`. mock `pane list` 는 에이전트 pane 에 `agent` 를 넣고 extra pane 은 안 넣으므로, `lib.sh:771` `not p.get('agent')` 가 w2 에서 idle 을 고름. split/create 없음, `agent start … --pane w2:p_idle`. idle 우선이 깨지면 w2 split 으로 실패.
|
||||
|
||||
`test_ws_label_rename_targets_only_the_chosen_workspace`: 같은 4+1 에서 `MAM_WS_LABEL=team-b`. `lib.sh:854-856` 은 선택된 `existing_ws` 에만 `workspace rename`. 호출 로그가 정확히 `["workspace", "rename", "w2", "team-b"]` — w1 이나 생성 경로 `--label` 이 아님.
|
||||
|
||||
## (4) 1회차 PASS 회귀 + 락스텝
|
||||
|
||||
#12 `to_registry_block` password 제외, env 복원, G6 `_cmd_scrub_secrets` 예외, `auth_token` 유지. #7 후보 순회·overflow `continue`·단일 ws 동치. #8 성공 경로 version/hashes 비복원. 회귀 없음.
|
||||
|
||||
`lib.sh`/`eager.py`/8 SKILL.md/VERSIONS.md 개요·매트릭스 / README·BOOTSTRAP·MESSAGING = **4.4.4**. 릴리스 커밋 `4176d75` 제목 유지. `env -u MAM_VERSION` 아래 `verify_framework_version` 통과. 현재 버전 안내 문서에 잔여 `4.4.3` 없음.
|
||||
|
||||
Non-blocking (1회차와 동일): 락스텝이 v4.4.3 품질 문장을 24/17 → 26/19 로 고친 것은 `fae70c1` 작업이지 이 베이스가 아님. v4.4.4 품질 불릿은 아직 “테스트 8개/issue7 3개” — 이후 테스트 2건·N1 보강은 changelog 항목 2·코드에만 반영. 기능 결함 아님.
|
||||
|
||||
## (5) 테스트
|
||||
|
||||
```
|
||||
env -u MAM_VERSION .venv/bin/python -m pytest -q \
|
||||
tests/test_issue7_workspace_packing.py tests/test_issue8_update_state.py \
|
||||
tests/test_issue12_registry_secrets.py tests/test_issue5_phase1_delegation.py \
|
||||
tests/test_issue5_phase2a_loop.py tests/test_herdr_shim_contract.py \
|
||||
tests/test_layout.py tests/test_deploy_layout.py tests/test_loop_cli.py \
|
||||
tests/test_issue5_phase4_runtime.py tests/test_version_consistency.py
|
||||
```
|
||||
|
||||
**244 passed in 134.54s** (1회차 242 + #7 테스트 2). `bash -n` lib.sh/`update.sh` 클린. 전체 스위트 미실행.
|
||||
|
||||
## 종합
|
||||
|
||||
N1(null password 901건 재기록)은 값 기준으로 닫혔고, install_state 병합과 #7 idle/rename 경로가 테스트로 고정됐다. 1회차 PASS 항목 회귀 없음. 설계 재작업 불필요.
|
||||
|
||||
[VERDICT: PASS]
|
||||
Reference in new issue
Block a user