직전 커밋(298dac2)이 "정의 파일은 세션 시작 시점 스냅샷으로 고정된다
(에이전트·워크플로 공통)"고 일반화했는데, 그건 증거보다 센 주장이었다 —
scriptPath 경로를 테스트한 적이 없었다. 프로브로 갈랐음:
- Workflow({name}) = 세션 시작 시점 스냅샷 (실행된 스크립트가 세션 시작
상태와 바이트 단위 동일, 같은 세션 편집 반영 0)
- Workflow({scriptPath}) = 디스크 실시간 (세션 시작 후 새로 만든 스크립트가
실행되고, 고친 뒤 다시 부르니 고친 값이 반환됨)
따라서 워크플로 쪽 해법은 세션 재시작이 아니라 scriptPath다 — conventions.md의
핸드오버 감사 절차에 반영. 에이전트 정의 stale은 자기 보고뿐이라 근거 등급이
낮음을 명시하고(Grep/Glob 불일치와 같은 등급), 우회 수단이 없으니 재시작을
보수적 해법으로 유지.
또 첫 실동이 수렴 못 하고 최대 라운드로 끊긴 결과, 마지막 라운드의 발견
6건이 반영만 되고 재감사되지 않은 채 커밋됐다는 것을 todos.md/세션 로그에
명시 — 다음 실동의 첫 임무. README.md의 audit/ "현재 6개"(실제 7개)도
폴더-소스로 전환.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.3 KiB
2026-08-16 두 번째 세션 — 감사 툴링 재시작 검증 + 핸드오버 감사 첫 실동
전 세션(2026-08-16-01-subagent-audit-and-claudemd-split.md)이 남긴
"재시작해야만 확인 가능한 것 3개"를 닫고, quad-handover-audit 워크플로를
처음으로 실제로 감사가 도는 상태에서 돌린 세션.
1. 재시작 검증 3건 — 전부 확인
| 항목 | 결과 | 근거 |
|---|---|---|
@import 3개 로드 |
✅ | conventions.md/project-context.md/todos.md 내용이 실제 컨텍스트에 들어옴 |
quad-doc-auditor 등록 |
✅ | 에이전트 목록에 잡힘. 전 세션 전멸(agentType not found)은 .claude/agents/가 세션 도중 생긴 디렉토리였던 탓 |
frontmatter model: sonnet 반영 |
✅ | 서브에이전트 트랜스크립트에 "model":"claude-sonnet-5" 기록. 워크플로에 opts.model 명시 불필요 |
모델 확인은 처음에 "네 모델과 도구를 보고해라"는 프로브 에이전트로 시도했다가 에이전트가 프롬프트 인젝션으로 판단해 거부했다(원래 과업인 감사를 버리고 시스템 프롬프트를 덤프하라는 지시였으니 정당한 거부). 자기 보고 대신 트랜스크립트 파일을 직접 grep하는 쪽이 1차 증거라 더 낫다.
2. ⭐ 워크플로는 name으로 부르면 스냅샷, scriptPath로 부르면 실시간
전 세션 감사 라운드들이 "캐시냐 frontmatter 무시냐"로 길게 갈라놨던 것을
좁히는 증거가 나왔다. 처음엔 이걸 "정의 파일은 세션 시작 스냅샷으로
고정된다(에이전트·워크플로 공통)"로 일반화해서 적었는데, 그건 증거보다
센 주장이었다 — scriptPath 경로를 테스트한 적이 없었다. 실제로 갈렸다.
Workflow({name})= 세션 시작 시점 스냅샷. 이 세션에서.claude/workflows/quad-handover-audit.js를 편집한 뒤 이름으로 돌렸는데, 런타임이 실제로 실행한 스크립트가 세션 시작 시점 상태(= 당시 HEAD, 작업트리가 깨끗했음)와 바이트 단위로 동일했다. 편집은 하나도 안 실렸다.Workflow({scriptPath})= 디스크에서 실시간. 세션 시작 후 새로 만든 프로브 스크립트(에이전트 0개)가 정상 실행됐고 — 스냅샷이라면 존재할 수 없다 — 그 파일을 고쳐 다시 부르니 고친 값이 그대로 돌아왔다.
실무 규칙: 워크플로 정의를 고쳤으면 재시작하지 말고 scriptPath로
호출할 것. 이름으로 부르면 옛 정의로 돌면서 새 정의로 돈 것처럼 보인다 —
감사 도구에선 이게 조용한 거짓 초록불이다.
에이전트 정의 쪽은 같은 등급의 증거가 없다 — 감사 에이전트들이 "받은
지시문에 그 세션에 추가된 배너가 없었다"고 보고했을 뿐이고 그건 자기
보고다(아래 Grep/Glob과 같은 등급). 에이전트엔 scriptPath 같은 우회가
없으니 확인 전까지는 보수적으로 고쳤으면 재시작 뒤에 감사를 따른다.
미해소로 남은 건 읽기 전용인데 Write/Edit이 주어지는 원인 하나.
memory: project를 뺐지만 그 뒤 재시작 없이 관찰한 것뿐이라 진단 미확정.
전 세션 감사가 남긴 "Grep/Glob이 안 주어졌다"는 서술은 두 소스가 어긋나는 미해결 불일치다 — 호출 세션이 보는 에이전트 등록 목록엔 Grep/Glob이 포함돼 있는데, 실행된 에이전트는 자기 도구를 Read/Bash/Write/Edit으로 보고했다. (처음엔 "자기 보고라 근거가 약하다"고 깎으려 했으나, 에이전트는 자기 함수 목록을 직접 볼 수 있으므로 그건 과한 판단이었다.) 어느 쪽도 확정하지 말고 Write/Edit 원인과 함께 재시작 직후 실행에서 볼 것.
3. "존재하지 않는 원칙 인용" 3건 — 재분류 결과 2건은 인용 오류였음
전 세션은 셋 다 같은 성격(가짜 원칙)으로 넘겼는데, 코퍼스 grep +
git log -S로 다시 보니 갈렸다.
research/v1-compat-plan.md:50— 원칙 자체는 실재. 실제 소스는base/component-composition-plan.md§1(자동 store 생성/자동 흡수 매직 폐기, 사용자 확정)과base/store-plan.md"Store 값 설정 문법" 절 (__newindex자동 위임 폐기). → 재조준.research/pre-implementation-audit.md:434— 역시 실재. 실제 소스는 루트ROADMAP.md의 quad-debug 백로그 항목 +question.md. 다만research/debug-tooling-plan.md쪽은 더 약한 표현("존재 가능성만 인지")이라 그 온도차도 같이 적었다. → 재조준.base/modifier-plan.md:536— 이것만 진짜로 출처가 없다. 코퍼스 전체에도,git log -S로 본CLAUDE.md전 히스토리에도 그런 서술이 존재한 적 없다. 임의로 정하지 않고 날짜 붙인 대기 배너 +question.md3번 항목(선택지 (a)conventions.md에 명문화 / (b) 지역 논거로만 유지)로 올려 사용자 판단 대기.
4. quad-handover-audit 첫 실동 — 6라운드, 수렴 실패
에이전트 67개 / 라운드별 새 발견 28 → 15 → 16 → 7 → 11 → 6. 최대
라운드(6)를 소진할 때까지 새 발견이 마르지 않아 converged:false로 끝났다.
과거 수동 감사가 4~6라운드에 수렴했던 것과 다른 양상.
- 라운드 5에서 발견이 7→11로 다시 늘었다 — 감사가 코퍼스를 훑는 순서/
관점이 라운드마다 달라서 생기는 것으로 보이고, 단조 감소를 전제한
MAX_ROUNDS=6이 이 코퍼스엔 부족하다는 신호. - 이번 실행은 위 2번 때문에 옛 스크립트로 돌았다(이름으로 호출) — 즉 이
결과 자체가 그 함정의 사례다. 다음 실동은
scriptPath로. - 마지막 라운드(6)의 새 발견 6건은 반영만 되고 재감사되지 않았다. 수렴 조건을 못 채우고 최대 라운드로 끊겼기 때문이다. 그 6건을 포함한 diff 전체를 이 세션이 손으로 검토하고 핵심 주장(절 제목·archive 파일 존재·spikes 실제 개수)은 1차 근거로 확인했지만, dry 라운드 하나가 주는 확인과 같지는 않다 — 다음 실동의 첫 임무가 이걸 재확인하는 것.
수정 품질 자체는 높았다. 실제로 잡힌 것 중 값진 것:
base/slot-plan.md:218의 정정 배너가 "폐기로 정정됨"에서 멈춰 있었는데, 그 "폐기"가 2026-08-13에 다시 뒤집혀 지금 정본은retract=언마운트다. 배너만 보고 지나가면 구현자가 옛 결론을 믿을 자리였다.spikes 44개류 하드코딩 개수가 여러 문서에 흩어져 있었는데 실제로는 48개(0043+21b21e)였다. 전부 "폴더가 소스"로 바꿈 —conventions.md의 "개수·목록·상태는 소스를 하나만" 규칙 적용.tools/doc-check.pydocstring이 1·2번 검사 심각도를 실제 코드와 다르게 적어놨던 것(둘 다 ERROR라 했지만 코드는 그렇게 동작한 적 없음). 검사 로직은 안 건드리고 서술만 정정.
5. 워크플로 스크립트 개선(다음 실행부터 적용됨)
- 반환값에
findings배열 추가. 기존엔roundLog에 파일명·개수만 있어 커밋 전 diff 리뷰 때 "이 수정이 왜 들어갔는지"를 알 방법이journal.jsonl고고학뿐이었다. totalFindingsFixed→findingsSentToFix로 개명. "의심"으로 표시돼 반영 에이전트가 확인 후 건드리지 않은 것도 "고쳐짐"으로 세던 과대계상.- 반영 에이전트에
model: 'sonnet'명시(감사 패스는 frontmatter로 이미 sonnet, 반영 쪽만 메인 모델을 상속하고 있었음).
남은 것
MAX_ROUNDS재검토 + 미재감사분 확인 — 수렴 실패가 재현되는지scriptPath호출로 재실동. 단조 감소 전제가 안 맞으니 "연속 dry 2회" 조건 자체도 같이 볼 것. 라운드 6의 미재감사 6건도 이때 걸러진다.- (d) Write/Edit 원인 — 다음 세션 시작 직후 확인.
.claude/agent-memory/— 감사 에이전트가 스스로 쓰는 영속 메모리가 생겼고 지금 untracked. 커밋할지.gitignore로 뺄지는 사용자 판단.modifier-plan.md:536원칙 —question.md3번, 사용자 판단 대기.