release(v4.8.3): bump framework and eight skills to 4.8.3 in lockstep; archive PR #46 reviews (two rounds)
Issue #42 stages 1-2: the SKILL.md code-block inventory as test data and the removal of blocks the entry scripts already do. Merge-workspace review: round 1 (@8d26106) claude agy grok PASS, codex NOT PASS (R1-R3); fixed in17eba09(docs, inventory data and the guard test only); round 2 4/4 PASS. Full suite at8d261061408 passed / 0 failed. Reports and the round-2 identity sidecars go to .agents/reports/<session>/. 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
17eba0904e
commit
44999ff2fb
28 files changed
+824
-26
No files matched your search
@@ -0,0 +1,100 @@
|
||||
# 리뷰 리포트 — Job 2f19fe7f (PR #46, fix/issue-42 단계 1·2)
|
||||
|
||||
- 리뷰어: planner-reviewer-claude-01 (claude)
|
||||
- 리뷰 identity: loop-20261003T222707Z-a0de27 / base 45d1621 / head 8d26106 / tree b579380 — 검증 경로에서 `git rev-parse HEAD 'HEAD^{tree}'` 로 일치 확인, 미커밋 변경 없음
|
||||
- 커밋: 7670b41(단계 1·2), e6a46cd(R1: stop exit 1 이 stop 뒤에도 남), 8d26106(R2: passthrough 코드는 표에 있어야 함)
|
||||
|
||||
## 결론 요약
|
||||
차단 결함 없음. 지운 (a) 블록 5개는 모두 진입 스크립트가 그대로 하는 일이고, 새 옵션·종료 코드 표와 "정정" 다섯 곳은 스크립트 코드 및 샌드박스 실행 결과와 일치한다. 제품 코드 변경 없음. 비차단 관찰 4건(아래 §6).
|
||||
|
||||
## 1. 분류의 정확성
|
||||
### resume Workflow (base resume SKILL.md:59-118) → resume_session.sh
|
||||
| 지운 단계 | 스크립트 위치 |
|
||||
|---|---|
|
||||
| 세션 ID 해석 (`resolve_session_id.sh --session`) | resume_session.sh:111-112 |
|
||||
| Class A fresh-spawn 폴백 / claude·grok exit 1 | :122-130 (spawn-spec :173-184) |
|
||||
| HERDR_SESSION_NAME·MAM_WS_LABEL 해석 | :132-144 |
|
||||
| herdr alive 분기 | :147-158 — **attach 하지 않고** `update_yaml_resumed.sh` 후 exit 0 |
|
||||
| CMD_FULL (에이전트별) | :185-197 (adapter resume-spec + 동일 표 폴백) |
|
||||
| 기동 | :237 `_herdr new-session` |
|
||||
| handle_startup_dialogs | :241 |
|
||||
| update_yaml_resumed.sh | :247-250 |
|
||||
| attach | **스크립트에 없음** |
|
||||
|
||||
attach 만 스크립트에 없는 단계(= (b))인데, 문서는 이를 지우지 않고 "It never attaches; attaching is a separate step: `herdr agent attach <name>`" 로 남겼다(resume SKILL.md Workflow 아래 문단, Case 3 정정). 따라서 절차 유실 없음. 문서에만 있던 `$CLAUDE_ID_FLAG`(정의되지 않은 변수)도 함께 사라졌다(인벤토리 mismatch R4) — 정정이 맞다.
|
||||
|
||||
### stop pre-flight (base stop:38-63) → stop_session.sh
|
||||
YAML 존재 :99(exit 1), 등록 확인 :127-143(exit 1), 이미 stopped no-op :184-188(exit 0). 문서에만 있던 `--force-no-yaml` 은 어떤 스크립트도 받지 않는다(:76-90 파서에 없음) — 삭제가 맞다.
|
||||
|
||||
### create pre-flight (base create:35-52) → create_session.sh
|
||||
워크스페이스 :111, has_real_herdr :114, CLI in PATH :115, 인증 :117-157(선택된 에이전트만). B-3 함정(command -v / type -P) 설명은 산문으로 보존.
|
||||
|
||||
### create Workflow (base create:168-220) → create_session.sh
|
||||
이미 존재 :166-168(**exit 3**, 문서는 1이었음), spawn-spec :207, spawn :252-276, TUI 대기 :361-398(exit 42), 롤백 trap :320-352(exit 43). `sleep 6` 하드코딩과 claude 무플래그 기동은 문서 쪽 오류였다.
|
||||
|
||||
### create YAML 수동 추가 (base create:226-252)
|
||||
행 기록은 create_session.sh:491-610 heredoc 이 한다. lib.sh shim 주석은 Output format 아래 산문으로 이동.
|
||||
|
||||
### (b) 로 남은 블록 5개
|
||||
create:217·resume:103·stop:127 (사후 확인), monitor:182 (에이전트 폴링 지침), status:30 (status.sh 에 has_real_herdr 검사가 없음 — status.sh:22 는 YAML 만). 각 스크립트를 grep 해 같은 명령을 제공하는 진입점이 없음을 확인했다. 3단계 입력으로 타당하다.
|
||||
|
||||
### 블록 수 대조
|
||||
base 의 펜스 블록을 테스트의 `parse_blocks` 로 세면 37개(create 11, delegate-job 1, loop 5, monitor 7, orc-onboard 2, resume 2, status 4, stop 5). 지운 (a) 5개의 base_start/base_sha 는 모두 base 와 일치한다. 현재 33개 = 37 − 5(a) − 1 + 2(새 Workflow 호출 블록). 이 "− 1"은 관찰 O1 참고.
|
||||
|
||||
## 2. 옵션·종료 코드 표 대조
|
||||
- create 옵션 표 ↔ 파서 create_session.sh:76-92: 12개 항목 모두 일치(별칭 `--name`, `--herdr-server` 포함; `--isolate` no-op :89-90; `--wrapper` 는 :257 에서 존재 여부와 무관하게 강제).
|
||||
- create 종료: 1 = :111-156 사전 검사 + :636·:659 (spawn 뒤 브리프/주입 실패, trap 롤백); 2 = :92-110 인자, :234 바인딩 거부, :245 공백; 3 = :168; 4 = heredoc `raise SystemExit(4)` :515 (중복 running 행, set -e 로 통과 → trap 롤백); 42 = :398; 43 = :348.
|
||||
- resume 옵션 표 ↔ :37-46 일치. 종료 0 = :150·:158(alive, attach 없음)·:227(dry-run)·정상 종료; 1 = :128·:204·:209 + update_yaml_resumed.sh:47; 2 = :46-56·:73·:77·:104·:221 + update_yaml_resumed.sh:42-46·:74.
|
||||
- stop 종료 0 = :188; 1 = :99·:142 + heredoc :310(R7); 2 = :86·:89·:95·:98·:121; 3 = :198; 4 = :281.
|
||||
- status `--json` 키: reconcile.sh:1081-1088 의 6개 최상위 키 + status.sh:213-232 의 sessions_detail 17개 키와 정확히 일치. resume_state 값 yes/MISSING/scan/no 도 status.sh 의 resume_on_disk 반환값과 일치.
|
||||
|
||||
샌드박스 실행(임시 HOME·WORKSPACE_ROOT·AGENT_SESSIONS_YAML, `env -i`, herdr 미호출 경로만):
|
||||
| 실행 | rc | 표 |
|
||||
|---|---|---|
|
||||
| stop `--purge-conversation` (no --yes) | 3 | 3 ✓ |
|
||||
| stop 미등록 세션 | 1 | 1 ✓ |
|
||||
| stop `--mode x` | 2 | 2 ✓ |
|
||||
| resume 원래 cwd 없음 `--dry-run` | 2 | 2 ✓ |
|
||||
| create 없는 워크스페이스 | 1 | 1 ✓ |
|
||||
| create `--agent foo` | 2 | 2 ✓ |
|
||||
샌드박스 YAML 은 변경되지 않았다.
|
||||
|
||||
## 3. 문서만으로 같은 작업이 가능한가
|
||||
- 세 진입점 모두 호출 한 줄에 필수 옵션이 표시되어 있고, 지운 절차는 전부 스크립트 안에 있으므로 호출 한 줄로 충분하다.
|
||||
- 사람이 판단할 지점은 보존·강화됐다: stop 예제가 `--purge-conversation --yes` 로 바뀌면서 "되돌릴 수 없다, 사용자가 확인한 뒤에만 `--yes`" 문장이 추가됐다(실제로 --yes 없으면 exit 3 이므로 이전 예제는 동작하지 않았다).
|
||||
- resume 은 spawn 뒤 실패 시 롤백하지 않는다는 점과 `multi-agent-mux-status` 로 먼저 확인하라는 복구 지침이 새로 들어갔다(resume_session.sh 에 trap 없음 — 사실과 일치). stop 표 아래 복구 문단도 같다.
|
||||
|
||||
## 4. 문서 가드 테스트 견고성
|
||||
스크래치 사본에서 변이 시험:
|
||||
| 변이 | 결과 |
|
||||
|---|---|
|
||||
| create `exit 43`→`exit 44` | 2 failed ✓ |
|
||||
| create `exit 42` 제거(표 행이 낡음) | 2 failed ✓ |
|
||||
| 주석 `# exit 9` 추가 | 통과 ✓ (주석 제외 규칙) |
|
||||
| 실제 `exit 9` 추가 | 2 failed ✓ |
|
||||
| stop 표의 3 행 삭제 | 2 failed ✓ |
|
||||
| stop 예제의 `--yes` 제거 | 1 failed ✓ |
|
||||
| base 의 create pre-flight 블록 되살림 | 1 failed ✓ |
|
||||
| stop SKILL.md 블록 위에 산문 한 줄 추가(정상 편집) | 1 failed (관찰 O2) |
|
||||
| `$(( 1 << 2 ))` 뒤 `exit 9` | 통과 ✗ (관찰 O3) |
|
||||
|
||||
추출 규칙: `(?<![\w.])exit\s+(\d+)` 은 `sys.exit(7)`(stop:139) 을 세지 않고, heredoc 본문은 `SystemExit(N)` 만 passthrough 로 모은다. `<<<` here-string 은 lookbehind 로 제외된다. 기존 가드 test_tier2_component.py::test_comp_docs_stop_examples_pass_agent(stop 예제 ≥3, 모두 --agent)는 아래 테스트 실행에서 통과한다.
|
||||
|
||||
## 5. 범위
|
||||
`git diff --stat 45d1621 8d26106`: SKILL.md 4개 + tests/data/skill_code_blocks.json + tests/test_issue42_skill_blocks.py. 스크립트·Python·버전 파일 변경 없음(버전 bump 없음).
|
||||
|
||||
## 6. 비차단 관찰
|
||||
- **O1 인벤토리 누락 1건**: base create SKILL.md:263-266 의 (c) 호출 블록(`create_session.sh … --session "$SESSION_NAME"`, sha ceb96a8c1293)이 지워졌지만 skill_code_blocks.json 의 blocks·removed 어디에도 없다. 내용은 새 Workflow 호출 블록이 대체하므로 정보 유실은 없지만, "37개를 분류했다"는 데이터는 실제로 36개만 다룬다. 가드는 현재 블록만 비교하므로 잡지 못한다. removed 에 class "c" 로 기록하거나 test_no_duplicate_block_left 의 `class == "a"` 를 완화하는 정리를 권한다.
|
||||
- **O2 줄 번호 결합**: 인벤토리가 start/end 줄 번호를 고정하므로 블록 위에 산문 한 줄만 넣어도 실패한다. 실패 메시지가 실제 튜플을 출력해 갱신은 기계적이지만, 3단계에서 산문 편집이 잦다면 sha+순서만 비교하거나 재생성 스크립트를 두는 편이 낫다.
|
||||
- **O3 산술 시프트 오인**: `_HEREDOC` 이 `$(( 1 << 2 ))` 를 heredoc 시작으로 읽어 이후 모든 줄을 건너뛴다. 현재 세 진입 스크립트에는 이 패턴이 없어(grep 확인) 실제 영향은 없다.
|
||||
- **O4 표 세부 문구**: (a) create exit 42 는 "프로세스가 사라짐" 외에 `MAM_KILL_ON_READY_TIMEOUT=1` 이면 살아 있어도 42 (create_session.sh:388-398). (b) stop "이미 stopped 면 no-op" 은 `--purge-conversation` 이 아닐 때만(:185). (c) resume 문서의 "lines 50-223" 은 사전 검사의 실제 범위(:50-221)와 대략 맞다. 모두 문서 정밀도 수준이다.
|
||||
|
||||
## 7. 항목 6 — purge 기준 실패
|
||||
이 호스트에서 검증 경로의 tests/test_issue10_13_purge.py: **23 passed**. 이 PR 은 제품 코드를 바꾸지 않으므로 Linux 의 12건(#28)과 무관하다. "알려진 기준 실패" 표현은 Linux 기준이라는 한정이 필요하다.
|
||||
|
||||
## 8. 테스트
|
||||
지정 6개 파일(test_issue42_skill_blocks, test_tier2_component, test_orc_onboard, test_loop_cli, test_o1_rebuttal, test_version_consistency): **129 passed / 0 failed / 1 skipped** (296 s, rc 0). skip 은 test_claude_skills_link_resolves_to_agents_skills(워크트리에 .claude/skills 없음 — 브리프상 정상). test_issue42_skill_blocks.py 단독: 28 passed / 1 skipped.
|
||||
|
||||
외부 브로커 미사용(MQTT_* unset, .mam.env 미export). 실제 .mam/jobs 항목 수 변화: +0 (이 잡 디렉터리 외 생성 없음).
|
||||
|
||||
[VERDICT: PASS]
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"loop_id": "loop-20261003T230658Z-e7866a",
|
||||
"base_sha": "8d26106195a0a24621f140e76389d206332f84c0",
|
||||
"head_sha": "17eba0904ebbf54c1d2243ad61a6f2ba17263889",
|
||||
"tree_sha": "a0f1ffede44be7c86267a56b25871e1d081feafb",
|
||||
"review_commit": "17eba0904ebbf54c1d2243ad61a6f2ba17263889",
|
||||
"reviewer": "planner-reviewer-claude-01",
|
||||
"job_id": "95b63371",
|
||||
"verdict": "PASS",
|
||||
"transport": "herdr",
|
||||
"evidence": "review-tree",
|
||||
"isolation": "worktree",
|
||||
"verified_at": "2026-10-03T23:35:18Z"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
# 리뷰 리포트 — Job 95b63371 (PR #46 2회차 델타, 8d26106..17eba09)
|
||||
|
||||
- 리뷰어: planner-reviewer-claude-01 (claude)
|
||||
- 리뷰 identity: loop-20261003T230658Z-e7866a / base 8d26106 / head 17eba09 / tree a0f1ffe — 검증 경로에서 `git rev-parse HEAD 'HEAD^{tree}'` 일치, 미커밋 변경 없음
|
||||
- 범위: 커밋 17eba09 한 개. `git diff --stat 8d26106 17eba09 -- . ':!*.md' ':!tests'` 결과가 비어 있음 → 제품 코드·버전 변경 없음(항목 4 ✓)
|
||||
|
||||
## 결론 요약
|
||||
codex R1~R3, claude O1·O4 가 모두 닫혔다. 차단 결함 없음. 비차단 관찰 2건(§5).
|
||||
|
||||
## 1. 지적 사항 종결 여부
|
||||
| 지적 | 수정 | 확인 |
|
||||
|---|---|---|
|
||||
| codex R1 (attach 대상 서버) | resume SKILL.md Case 3·Workflow 설명·When NOT 이 `herdr --session <server> agent attach <name>` 로 서버를 명시, Verification 이 행에서 SERVER 를 읽어 `--session "$SERVER"` 사용 | ✓ 아래 §2 |
|
||||
| codex R2 (--dry-run 문구) | create·resume 옵션 표: "no spawn and no registry (YAML/DB) update; 앞선 검사는 돌고 macOS 에서 quarantine 속성을 지운다" | ✓ create_session.sh:196 xattr → :280 dry-run 종료, spawn() 은 :264-274 정의만, YAML 쓰기 :305·:491 은 그 뒤. resume_session.sh:169 xattr → :225 dry-run 종료, spawn :237 |
|
||||
| codex R3 (삭제 본문 복귀 가드) | test_no_deleted_body_came_back 이 DATA["blocks"] 를 읽지 않고 현재 모든 블록을 removed+superseded 의 base_sha / base_fingerprint 와 비교 | ✓ §3 탐침 |
|
||||
| claude O1 (create:263-266 누락) | superseded 에 class c / invocation, base_sha ceb96a8c1293 으로 기록 | ✓ base 45d1621 에서 parse_blocks 로 다시 계산한 sha·fingerprint 일치 (removed 5 + superseded 1 모두 True/True) |
|
||||
| claude O4 (표 문구) | create 42 에 `MAM_KILL_ON_READY_TIMEOUT=1` 경우, stop 0 에 "--purge-conversation 에서는 no-op 아님" | ✓ create_session.sh:388-398, stop_session.sh:185 와 일치 |
|
||||
|
||||
## 2. R1 — 안내 명령이 실제로 격리 서버로 가는가
|
||||
herdr 서버를 건드리지 않도록 `--help` 의 Logs 경로(세션 해석 결과)만으로 확인했다(`env -i` 로 상속 변수 제거):
|
||||
| 호출 | 해석된 세션 디렉터리 |
|
||||
|---|---|
|
||||
| `herdr --help` | ~/.config/herdr/ (기본 서버) |
|
||||
| `herdr --session zz-probe --help` | ~/.config/herdr/sessions/zz-probe/ |
|
||||
| `herdr --session default --help` | ~/.config/herdr/ (기본 서버와 동일) |
|
||||
| `HERDR_SESSION=zz-probe herdr --help` | sessions/zz-probe/ |
|
||||
| `HERDR_SESSION_NAME=zz-probe herdr --help` | ~/.config/herdr/ (무시됨) |
|
||||
| `herdr --session "" --help` | `error: session name cannot be empty` |
|
||||
(탐침 뒤 ~/.config/herdr/sessions 에 zz-probe·default 디렉터리 생성 없음 확인.)
|
||||
|
||||
- 따라서 `herdr --session <row.herdr_session> agent attach` 는 그 격리 서버로 간다. 행이 `herdr_session: default` 여도 `--session default` 가 기본 서버로 해석되므로 맞다. lib.sh shim(`_real_herdr`, lib.sh:255-268)이 default 일 때 `--session` 을 빼는 것과 결과가 같다.
|
||||
- resume_session.sh 가 export 하는 것은 `HERDR_SESSION_NAME` 이고 native herdr 는 이를 읽지 않으므로(위 표), 서버 명시가 필요하다는 수정 근거가 맞다.
|
||||
- Verification SERVER 계산: 행에 herdr_session 없음 → `'default'` → 기본 서버(올바름). 행 자체가 없음 → python IndexError, SERVER="" → herdr 가 "session name cannot be empty" 로 즉시 실패. 검증 블록으로서는 조용히 엉뚱한 서버를 보는 것보다 낫다. 행 기록자는 create_session.sh:524-525, update_yaml_resumed.sh:140-141·155-156 에서 herdr_session 과 herdr_server 를 항상 같이 쓰므로 herdr_session 만 읽어도 된다.
|
||||
|
||||
## 3. R3 가드 — 견고성과 엄격성(스크래치 사본 변이 시험)
|
||||
| 변이 | 새 테스트(17eba09) | 이전 테스트(8d26106) |
|
||||
|---|---|---|
|
||||
| 기준 | 31 passed / 1 skipped | — |
|
||||
| codex 탐침: base resume Workflow 본문(45d1621 :59-118)을 목록 항목 안에 2칸 들여 다시 넣고 인벤토리에 class c 로 등록 | **1 failed** (test_no_deleted_body_came_back) | 28 passed (못 잡음) |
|
||||
| 정상 편집: create 에 새로운(다른) 호출 예시 추가 | R3 가드 통과, 인벤토리 테스트만 실패(의도된 동작) | — |
|
||||
| 삭제 본문 + 주석 한 줄을 앞에 붙여 다시 넣음 | R3 가드 통과(인벤토리 테스트만 실패) | — |
|
||||
- fingerprint(공백 접기 후 sha256 12자)는 재들여쓰기·줄 바꿈 변화에 강하고, 정확 일치만 보므로 다른 예시를 막지 않는다. 정상 편집을 막을 정도로 엄격하지 않다.
|
||||
- test_a_returned_body_is_caught_reindented_and_with_the_inventory_updated 는 가드 함수 자체를 현재 stop 블록으로 검사한다(정확 sha + 재들여쓰기 fingerprint) — 유효.
|
||||
|
||||
## 4. 인벤토리 재생성
|
||||
8d26106 과 17eba09 의 skill_code_blocks.json 비교: blocks 33개의 (skill, class, kind) 순서가 **동일**. 바뀐 값은 resume Verification 블록(start 103)의 sha·end(124→128) 뿐이고, removed 5개는 base_fingerprint 추가만, entry_points 동일, superseded 신설. 분류 변경 없음(항목 3 ✓).
|
||||
|
||||
## 5. 비차단 관찰
|
||||
- **N1 가드의 한계**: R3 가드는 블록 본문 전체 일치만 본다. 삭제된 본문 앞에 한 줄만 붙여도(§3 셋째 행) 인벤토리를 갱신하면 통과한다. 이번 지적(R3)의 범위인 "인벤토리 재등록으로 숨기기"는 막았으므로 차단은 아니며, 필요하면 후속에서 줄 단위 포함 비율로 넓힐 수 있다.
|
||||
- **N2 문구 정밀도**: resume SKILL.md Workflow 설명의 "the native `herdr` binary does not route on environment variables" 는 정확히는 "`HERDR_SESSION_NAME` 으로는 라우팅하지 않는다"이다 — native herdr 는 `HERDR_SESSION` 을 읽는다(§2 표). 특히 herdr 패널 안에서는 `HERDR_SESSION` 이 호출자 서버로 설정되어 있어, 서버를 빼면 호출자 서버로 간다. 결론(`--session` 명시)은 그대로 옳다.
|
||||
- 미반영으로 명시된 codex C2, claude O2·O3 는 후속 범위로 동의한다.
|
||||
|
||||
## 6. 테스트
|
||||
검증 경로에서 지정 6개 파일: **132 passed / 0 failed / 1 skipped** (300 s, rc 0). skip 은 test_claude_skills_link_resolves_to_agents_skills(워크트리, 정상). test_issue42_skill_blocks.py 단독 31 passed / 1 skipped. MQTT_* unset, .mam.env 미export. 실제 .mam/jobs 항목 수 변화 +0.
|
||||
|
||||
[VERDICT: PASS]
|
||||
Reference in new issue
Block a user