diff --git a/modules/shared/programs/claude/default.nix b/modules/shared/programs/claude/default.nix index a982a3864..fd0415cce 100644 --- a/modules/shared/programs/claude/default.nix +++ b/modules/shared/programs/claude/default.nix @@ -231,6 +231,10 @@ in ".claude/skills/codex-fan-out".source = config.lib.file.mkOutOfStoreSymlink "${claudeFilesPath}/skills/codex-fan-out"; + # finding-unknowns 스킬 (user-scope) + ".claude/skills/finding-unknowns".source = + config.lib.file.mkOutOfStoreSymlink "${claudeFilesPath}/skills/finding-unknowns"; + # Statusline script - 양방향 수정 가능 # 인접 디렉토리 정책: `scripts/tests/` 는 repo 검증 전용이라 # mkOutOfStoreSymlink로 home 에 노출하지 않는다. bats 단위 테스트는 devShell diff --git a/modules/shared/programs/claude/files/skills/create-pr/SKILL.md b/modules/shared/programs/claude/files/skills/create-pr/SKILL.md index 9baf11e72..1815b000d 100644 --- a/modules/shared/programs/claude/files/skills/create-pr/SKILL.md +++ b/modules/shared/programs/claude/files/skills/create-pr/SKILL.md @@ -55,10 +55,17 @@ PR을 생성하기 전에, 작업 결과의 처리 방향을 결정한다: 1. 변경 분석: `git diff main...HEAD`와 커밋 히스토리(`git log main..HEAD --oneline`)를 분석하여 변경 범위를 파악한다. 2. 연관 이슈 탐색: 커밋 메시지, 브랜치명, 변경 내용에서 이슈 번호를 추출한다. 관련 이슈가 있으면 Summary에 `Closes #N`을 포함한다. -3. CIR 수집: 코드 인라인 주석(`# CIR:`, `# === Change Intent Record ===`)과 커밋 메시지에서 의사결정 이력을 추출한다. 현재 대화 컨텍스트에서도 방향 전환/대안 거부 이력을 수집한다. +3. CIR 수집: 코드 인라인 주석(`# CIR:`, `# === Change Intent Record ===`)과 커밋 메시지에서 의사결정 이력을 추출한다. 현재 대화 컨텍스트에서도 방향 전환/대안 거부 이력을 수집한다. 워크트리에 `implementation-notes.md`가 있으면 아래 흡수 계약을 적용한다. + + 흡수 계약 (finding-unknowns 방법론 — 이 정의가 정본이며 update 경로도 동일 적용): + - provenance 확인: 파일 1행이 owner header ``이고, `git ls-files --error-unmatch -- implementation-notes.md`가 실패(=untracked)해야 흡수 대상이다. header가 없거나 tracked 파일이면 방법론 산출물로 단정하지 말고 흡수·삭제 없이 충돌로 보고한다. + - 흡수 범위: Decisions / Deviations / 새로 발견된 미지 세 섹션 전부를 CIR의 1차 소스로 반영한다. + - durable marker: 흡수한 PR 본문에는 hidden marker ``를 포함한다 — finish-pr 퀴즈 게이트가 별도 세션에서도 방법론 적용 PR을 판별하는 1차 신호다. + - 수명: 흡수 완료를 보고하기 전까지 그 파일을 삭제·이동하지 않는다 (수명 규칙 SoT: finding-unknowns 스킬). 4. ADR 테이블 구성: 검토한 대안들을 비교 테이블로 정리한다. 대안이 1개뿐이면 ADR 섹션을 간소화한다. 5. 7섹션 템플릿 작성: [references/pr-template.md](references/pr-template.md)의 템플릿에 따라 전체 PR 본문을 작성한다. -6. PR 생성: `gh pr create --title "<제목>" --body "<본문>"`으로 PR을 생성한다. 제목은 70자 미만, conventional commit 형식을 따른다. +6. PR 생성: 본문을 임시 파일로 작성한 뒤 `gh pr create --title "<제목>" --body-file <파일>`로 PR을 생성한다 — 본문을 shell 인자로 싣지 않는다 (multiline 본문의 프로세스 목록/로그 노출 방지, review-pr-feedback의 파일/stdin 전달 규칙과 동일). 제목은 70자 미만, conventional commit 형식을 따른다. +7. 구현 노트 정리: 3단계에서 `implementation-notes.md`를 흡수한 경우, 다음 세 조건을 모두 확인한 뒤에만 그 파일을 삭제한다 (남겨두면 finish-pr의 워크트리 정리가 dirty로 중단됨) — ① 1행 owner header 일치, ② `git ls-files --error-unmatch -- implementation-notes.md` 실패(untracked; tracked면 Git 밖 삭제 금지), ③ 생성된 PR 본문에 Decisions·Deviations·새로 발견된 미지 세 섹션 각각과 durable marker가 모두 반영되었는지 확인 (일부 섹션만 반영된 상태로 통과 금지). 하나라도 어긋나거나 PR 생성이 실패하면 파일을 보존하고 중단한다. ### 기존 PR 업데이트 (`update`) @@ -66,8 +73,9 @@ PR을 생성하기 전에, 작업 결과의 처리 방향을 결정한다: 1. 현재 PR 확인: `gh pr view --json body,title,number`로 현재 PR 본문을 가져온다. 2. 누락 섹션 탐지: 7섹션 중 빠진 섹션을 식별한다. -3. 부실 섹션 강화: 있지만 내용이 부실한 섹션(예: Summary만 있고 CIR 없음)을 보강한다. 커밋 히스토리, 코드 변경, 대화 컨텍스트에서 추가 정보를 수집한다. -4. 업데이트 적용: `gh pr edit --body "<새 본문>"`으로 PR 본문을 업데이트한다. +3. 부실 섹션 강화: 있지만 내용이 부실한 섹션(예: Summary만 있고 CIR 없음)을 보강한다. 커밋 히스토리, 코드 변경, 대화 컨텍스트에서 추가 정보를 수집한다. 워크트리에 `implementation-notes.md`가 있으면 새 PR 생성 절차의 흡수 계약을 그대로 적용한다 (provenance 확인, 세 섹션 전부, durable marker — marker가 본문에 없으면 이때 기록). +4. 업데이트 적용: 새 본문을 임시 파일로 작성해 `gh pr edit --body-file <파일>`로 업데이트한다 (본문 shell 인자 전달 금지 — 새 PR 생성 절차와 동일). +5. 구현 노트 정리: `implementation-notes.md`를 흡수한 경우 새 PR 생성 절차의 구현 노트 정리 단계와 동일하게, 세 조건(owner header · untracked · 세 섹션 각각+marker 반영) 확인 후에만 삭제하고 실패 시 보존한다. ## 주의사항 diff --git a/modules/shared/programs/claude/files/skills/finding-unknowns/SKILL.md b/modules/shared/programs/claude/files/skills/finding-unknowns/SKILL.md new file mode 100644 index 000000000..18d80fa7a --- /dev/null +++ b/modules/shared/programs/claude/files/skills/finding-unknowns/SKILL.md @@ -0,0 +1,70 @@ +--- +name: finding-unknowns +description: | + 장기작업의 지도(프롬프트·계획·컨텍스트)와 영토(코드베이스·현실·제약) 간극인 미지(unknowns)를 + 구현 전·중·후 반복 발견해 좁히는 오케스트레이션. + Trigger: '장기작업 시작', '미지 찾기', 'unknowns', 'blindspot pass', 'map-territory', + '방법론 적용', 새 대형 기능/프로젝트 킥오프, 낯선 도메인·API 진입, 가정 때문에 실패한 재시도. + NOT for 인터뷰 단독 실행 (use grilling). NOT for 계획/코드 검증 루프 (use run-da). + NOT for PR 생성/머지 절차 자체 (use create-pr / finish-pr — 이 스킬은 그 안의 게이트만 정의). +--- + +# 미지 찾기 (Finding Unknowns) + +지도(map)는 에이전트에게 주어진 것 — 프롬프트·계획·스킬·컨텍스트. 영토(territory)는 작업이 실제 일어나는 곳 — 코드베이스·API·테스트·배포 환경·사용자 취향. 그 간극이 미지(unknowns)다. 장기작업의 품질은 미지를 얼마나 일찍, 싸게 발견하느냐에 병목이 걸린다 — 문제가 비싸지기 전의 발견 수단이 설명·프로토타입·인터뷰이고, 비싸진 후의 발견 수단이 재작업이다. + +목표는 질문을 많이 하는 것이 아니라, 계획을 실질적으로 바꿀 소수의 답을 찾아내고 공유 이해를 기록하는 것이다. + +## 미지 4분면 + +| 유형 | 의미 | 노출 수단 | +|---|---|---| +| Known knowns | 프롬프트/문서에 이미 있는 사실 | 재진술 + 출처 인용 | +| Known unknowns | 미해결임을 아는 결정 | 인터뷰 (`grilling`) | +| Unknown knowns | 보면 알지만 미리 말 못 하는 취향/기준 | 대비되는 프로토타입·레퍼런스 (`prototype`) | +| Unknown unknowns | 아무도 고려 못 한 제약/가능성 | blindspot pass | + +## 적용 판단 + +적용: 다일(multi-day)·다세션·PR 규모 장기작업, 낯선 도메인/API/코드베이스 영역, 모호한 제품 방향, 이전 시도가 잘못된 가정으로 실패한 작업. + +비적용: 사소·기계적 변경, 수용 기준이 이미 명확하고 도구 호출 한두 번으로 검증 가능한 작업. 비적용 판단 시에도 그 판단을 한 줄로 보고한다. + +## 국면 1 — 구현 전 + +각 단계는 프로젝트 성격에 따라 스킵할 수 있으나, 스킵하면 사유 한 줄을 미지 원장에 기록한다. 무단 생략은 스킵이 아니라 unknown unknown의 방치다. + +1. 영토 정찰 — 관련 소스·테스트·설정·공식 문서를 사용자에게 묻기 전에 직접 읽는다(필요 시 정찰 서브에이전트 병렬). 코드/문서가 답할 수 있는 것을 사용자에게 묻지 않는다. 완료 기준: 정찰한 경로/문서 목록이 미지 원장에 적혀 있음. +2. Blindspot pass — unknown unknowns를 [references/tactics.md](references/tactics.md)의 출력 형식으로 나열한다: 리스크 순위 + 저렴한 해소 수단 + 결정 소유자(사용자/에이전트/문서/프로토타입). 완료 기준: 최고 리스크 미지마다 해소 수단이 지정됨. +3. 프로토타입 — unknown knowns가 많은 영역(시각 디자인, UX 흐름, "보면 아는" 기준)이면 `prototype`으로 의미 있게 대비되는 방향 여러 개를 만들어 반응을 받는다. 완료 기준: 사용자 반응이 명시적 기준 문장으로 원장에 언어화됨. +4. 인터뷰 — `grilling`으로 남은 known unknowns를 좁힌다. 모든 질문은 Material(답이 설계를 바꿈)·Grounded(증거 기반)·Answerable(선택지/기본값/레퍼런스로 답 가능) 3기준을 충족해야 한다 (상세와 블로킹 질문 템플릿: [references/tactics.md](references/tactics.md)). 아키텍처를 바꿀 질문 우선, 한 번에 하나. 저위험 미지는 질문하는 대신 기본값을 선택하고 가정 라벨을 붙인다. +5. 레퍼런스 — 사용자가 원하는 바를 말로 다 못 하면 레퍼런스를 요청한다. 소스 코드가 최고의 레퍼런스다 — 다른 언어여도 가리키는 폴더를 읽고 의미를 재구현한다. +6. 구현 계획 — 변경 가능성 높은 결정(데이터 모델·타입 인터페이스·권한·사용자 대면 흐름)을 앞에, 기계적 작업을 뒤에 배치한다. 잔존 가정 목록과 "이 계획이 통제하지 못하는 것" 리스크 대장을 포함한다. `run-da` for_plan으로 검증한다. + +게이트 A (빌드 전): 사용자가 공유 이해를 확인하기 전에 구현을 시작하지 않는다. 예외는 사용자가 "라벨된 가정과 함께 진행"을 명시 허용한 경우뿐이다. + +## 국면 2 — 구현 중 + +- 워크트리 루트에 `implementation-notes.md`를 유지한다 (1행은 owner header, 최소 섹션: [references/tactics.md](references/tactics.md)). 아무리 계획해도 unknown unknowns는 구현 깊숙한 곳에서 나타난다 — 그것이 정상이며, 기록이 방법론의 산출물이다. +- 계획 이탈 시: 저위험·국소적이면 보수적 선택 → Deviations 기록 → 계속. 아키텍처·데이터 마이그레이션·보안·비용·사용자 대면 동작이 바뀌면 멈추고 질문한다. +- 영토(실측·공식 문서)가 계획과 모순되면 영토를 신뢰하고 계획을 갱신한다. +- 소실 방지 불변식: 이 파일은 커밋 대상이 아니다. 대신 `create-pr`이 PR 본문에 Decisions/Deviations를 흡수했음을 확인하기 전까지 삭제·이동하지 않는다. 임시 디렉토리로 옮기는 것도 이동이다. 흡수가 확인된 뒤에는 파일을 삭제한다 — 남겨두면 워크트리 정리(`finish-pr`)가 dirty 상태로 중단되고, 이후 발견되는 미지는 PR 본문 CIR을 직접 갱신하므로 파일이 더 필요하지 않다. + +## 국면 3 — 구현 후 + +- 설명자료 — `create-pr`의 7섹션 본문이 설명자료다 (별도 산출물 불필요). 구현 노트의 Decisions/Deviations 흡수는 create-pr 절차가 수행한다. +- 퀴즈 — 머지 전 퀴즈 게이트는 `finish-pr`이 소유한다. 출제 규칙은 [references/tactics.md](references/tactics.md). 이 국면에서 에이전트의 책임은 퀴즈를 출제할 수 있는 상태(노트가 PR 본문에 흡수됨)를 유지하는 것이다. +- 리뷰 루프도 영토다: PR 리뷰(`review-pr-feedback`)에서 실버그·설계 반전이 발견되면 그것도 미지 발견이다 — `review-pr-feedback`의 CIR 동기화 단계가 resolve 전에 PR 본문의 CIR/Deviations를 갱신한다. 방법론은 PR 초안에서 끝나지 않고 머지에서 끝난다. + +## 하네스 매핑 + +| 방법론 단계 | 이 하네스에서 | 소유 | +|---|---|---| +| blindspot pass | 이 스킬이 직접 (정찰 + 4분면 정리) | finding-unknowns | +| 브레인스토밍/프로토타입 | prototype 스킬 | prototype | +| 인터뷰 | grilling 스킬 + 질문 3기준 | grilling / 이 스킬 | +| 구현 계획 검증 | run-da for_plan | run-da | +| 구현 노트 | implementation-notes.md → PR 본문 흡수 | 이 스킬 / create-pr | +| 설명자료 | PR 7섹션 본문 | create-pr | +| 퀴즈 게이트 | 머지 전 통과 확인 | finish-pr | +| 리뷰 국면 기록 | CIR/Deviations 갱신 | review-pr-feedback + 이 스킬 | diff --git a/modules/shared/programs/claude/files/skills/finding-unknowns/references/tactics.md b/modules/shared/programs/claude/files/skills/finding-unknowns/references/tactics.md new file mode 100644 index 000000000..8849a507a --- /dev/null +++ b/modules/shared/programs/claude/files/skills/finding-unknowns/references/tactics.md @@ -0,0 +1,98 @@ +# 미지 노출 전술 + +`finding-unknowns` 국면들이 참조하는 출력 형식·품질 기준·템플릿 모음. + +## 미지 원장 (grill session ledger) + +구현 전 국면의 작업 문서. 계획 artifact나 세션 노트 안의 섹션으로 유지해도 된다 — 형태보다 항목이 중요하다. + +```md +## 미지 원장 +### 영토 정찰 +- 읽은 경로/문서: <목록> +### Known knowns +- <사실> — 출처: <경로/문서/사용자 발언> +### Known unknowns +- <결정> — 왜 중요한가: <설계에 미치는 영향> +### Unknown knowns (보면 아는 기준) +- <노출할 취향/기준> → 프로토타입 반응: <언어화된 기준> +### Unknown unknowns 의심 목록 +- — 리스크: 상/중/하 — 저렴한 해소: <수단> +### 스킵한 단계 +- <단계> — 사유: <한 줄> +### 가정 라벨 (저위험 기본값) +- <가정> — 왜 안전한가, 나중에 어떻게 검증하나 +``` + +## Blindspot pass 출력 형식 + +```md +## Blindspot Pass +### 최고 리스크 unknown unknowns +1. <미지> + - 왜 중요한가: + - 증거: <문서/소스/테스트 인용> + - 저렴한 해소: <프로토타입/문서 확인/실측 1회/...> + - 결정 소유자: 사용자 / 에이전트 / 문서 / 프로토타입 +### 안전해 보이는 가정 +- <가정> — 왜 안전한가, 나중 검증 방법 +### 지금 물을 가치가 있는 질문 +1. +``` + +## 질문 품질 3기준 + +좋은 그릴 질문은 셋 다 충족한다: + +- Material — 답이 아키텍처·범위·UX·데이터 모델·보안·권한·수용 기준을 바꿀 수 있다. +- Grounded — 문서/소스의 구체적 동작이나 실재하는 불확실성을 가리킨다. 막연한 취향 낚시가 아니다. +- Answerable — 사용자가 선택지를 고르거나, 기본값을 승인하거나, 레퍼런스를 건네는 방식으로 답할 수 있다. + +나쁜 질문 안티패턴: 유능한 에이전트가 기본값으로 처리할 자명한 선호 묻기 · 조사 없이 설문지 폭탄 · 코드/문서가 답할 수 있는 것을 사용자에게 묻기 · 맥락 없는 "더 필요한 거 있나요?". + +### 블로킹 질문 템플릿 + +진행에 답이 꼭 필요할 때 한 번에 하나씩: + +```md +블로킹 질문: <질문> +왜 중요한가: <답 A vs B에 따라 무엇이 달라지나> +증거: <문서/소스/테스트/레퍼런스 인용> +추천 답: <기본값 + 근거> +신경 안 쓰시면: <기본값>으로 진행합니다. +``` + +유용하지만 블로킹이 아닌 질문은 큐에 두고, 미해결 material 결정부터 순서대로 묻는다. + +## 프로토타입 계약 + +- 실제 시스템 배선 전에 가짜 데이터의 단일 파일 목업으로 충분하다. +- 방향은 의미 있게 대비되어야 한다 — 미세 변형 여러 개는 unknown knowns를 노출하지 못한다. +- 사용자 반응을 받으면 즉시 명시적 기준 문장으로 언어화해 원장에 기록한다 ("너무 enterprise함, operator 느낌으로" 같은 반응도 기준이다). + +## implementation-notes.md 최소 섹션 + +```md + +# Implementation Notes +## 계획 스냅샷 +- <계획 버전/artifact 링크/날짜> +## Decisions +- <결정> — 근거/증거 +## Deviations +- 계획: <원래> / 실제: <변경> / 왜: <발견된 제약> / 리스크: 상/중/하 +## 새로 발견된 미지 +- <미지> — 해소됨 / 이관됨(이슈 #) / 사용자 결정 필요 +## 검증 +- <명령/테스트/수동 확인> — 결과 +``` + +1행의 owner header는 provenance 표식이다 — create-pr 흡수 계약이 이 header와 untracked 여부를 확인한 뒤에만 흡수·삭제하므로, 파일 생성 시 반드시 포함한다. 수명 규칙은 SKILL.md 국면 2의 소실 방지 불변식을 따른다. PR 리뷰 루프에서 발견된 실버그·설계 반전도 Deviations 대상이다 — review-pr-feedback의 CIR 동기화 단계가 PR 본문 CIR을 갱신한다. + +## 퀴즈 출제 규칙 (finish-pr 게이트가 사용) + +- 목적: 사용자가 변경의 동작을 이해했는지 확인 — 코드 diff 눈도장이 아니라 "이 입력이면 무슨 일이 일어나나"를 묻는다. +- 출제: 질문 도구로 총 3~5문항(변경 규모 비례)을 한 문항씩 답을 기다려 순차 출제한다. 질문 도구는 blocking tool call이어야 하며 plain-text 질문으로 퇴행하지 않는다 — 런타임별 binding(Claude=AskUserQuestion, Codex=request_user_input)은 [run-da의 런타임 도구 매핑](../../run-da/references/runtime-mapping.md#런타임-도구-매핑)이 정본. 각 문항은 PR 본문(설명자료)만 읽어도 답할 수 있어야 한다 — 본문에 없는 지식을 묻게 되면 퀴즈가 아니라 본문의 결함이므로 본문을 먼저 보강한다. +- 좋은 문항 소재: 경계 조건에서의 동작, 실패 시 폴백, 남아 있는 가정 라벨, Deviations가 생긴 이유, 이 변경이 통제하지 못하는 것. +- 오답이면: 해당 부분을 설명하고 그 주제로 재출제한다. 전 문항 정답이 통과다. +- 통과 또는 명시적 스킵(사유 기록) 전에는 머지하지 않는다 — 게이트 자체는 finish-pr 절차가 소유한다. diff --git a/modules/shared/programs/claude/files/skills/finish-pr/SKILL.md b/modules/shared/programs/claude/files/skills/finish-pr/SKILL.md index cf62232b4..3589d279e 100644 --- a/modules/shared/programs/claude/files/skills/finish-pr/SKILL.md +++ b/modules/shared/programs/claude/files/skills/finish-pr/SKILL.md @@ -2,7 +2,7 @@ name: finish-pr argument-hint: "[pr-number|pr-url|branch]" description: | - PR 머지 후 종결 절차를 수행한다. 대상 PR 확인, CI 상태 확인, squash merge, main pull 후 로컬 실측 검증, PR 후속 코멘트, 관련 이슈 동기화, 산출물 위생 점검, worktree cleanup까지 다룬다. + PR 머지 후 종결 절차를 수행한다. 대상 PR 확인, CI 상태 확인, 퀴즈 게이트(finding-unknowns 방법론 적용 작업), squash merge, main pull 후 로컬 실측 검증, PR 후속 코멘트, 관련 이슈 동기화, 산출물 위생 점검, worktree cleanup까지 다룬다. Trigger: '머지해줘', 'squash merge', '머지 후 정리', 'PR 마무리', 'PR 종결', 'finish-pr'. NOT for PR 생성 (use create-pr). NOT for PR 코멘트 처리 (use review-pr-feedback). --- @@ -30,9 +30,21 @@ Skip 조건: - PR이 이미 merge된 상태면 squash merge 단계는 건너뛰고, 머지된 main을 최신화한 뒤 로컬 검증부터 진행한다. - 사용자가 CI 실패를 알고도 강행하라고 한 경우에도 required gate를 우회하지 않는다. 가능한 우회가 정책상 허용되는지 먼저 보고한다. -### 2. squash merge +### 2. 퀴즈 게이트 (finding-unknowns 방법론 적용 작업) -1. `gh pr merge --squash`로 squash merge한다. +1. 이 PR이 finding-unknowns 방법론 적용 작업인지 판별한다. 1차 신호는 PR 본문의 durable marker ``다 (기록 주체·정본: create-pr 흡수 계약 — 별도 세션에서도 남는 유일한 신호). 보조 신호는 세션·메모리 컨텍스트의 방법론 적용 선언, 워크트리에 남은 `implementation-notes.md`이며, 보조 신호만으로 판별할 때는 일반 PR 오탐에 주의한다. +2. 해당되면 머지 전에 변경의 동작 이해를 확인하는 퀴즈를 질문 도구로 출제한다 (런타임별 질문 도구 binding: [run-da의 런타임 도구 매핑](../run-da/references/runtime-mapping.md#런타임-도구-매핑) — blocking tool call 필수, plain-text 질문으로 퇴행 금지). 출제 규칙의 SoT는 finding-unknowns 스킬의 `references/tactics.md` — 요지: 변경 규모에 따라 총 3~5문항을 한 문항씩 답을 기다려 순차 출제하고, 모든 문항은 PR 본문만 읽어도 답할 수 있어야 하며, 오답이면 설명 후 그 주제로 재출제한다. +3. 전 문항 정답이 통과다. 통과 전에는 squash merge를 진행하지 않는다. +4. 퀴즈 통과 직후 merge 대상을 다시 고정한다: `gh pr view --json headRefOid,body,statusCheckRollup,reviewDecision,mergeStateStatus`를 재조회하고, 퀴즈 시작 시점 대비 head 또는 본문이 바뀌었으면 바뀐 내용 기준으로 퀴즈를 다시 시작한다 (이전 head에 대한 통과로 새 head를 머지하지 않는다). 재확정한 `headRefOid`를 3단계 merge에 전달한다. + +Skip 조건: +- 방법론 적용 작업이 아니면 해당 없음으로 넘어간다. +- 사용자가 명시적으로 퀴즈 스킵을 지시하면 스킵하되, 스킵 사유 한 줄을 5단계의 PR 후속 코멘트에 포함한다. +- finding-unknowns 스킬이 설치되지 않은 환경이면 위 요지만으로 출제한다. + +### 3. squash merge + +1. 직전에 확인한 head commit SHA를 고정해 `gh pr merge --squash --match-head-commit "$HEAD_OID"`로 squash merge한다 (확인~merge 사이에 새 push가 끼어들면 merge가 실패하도록 — 퀴즈 게이트를 거친 PR은 2단계 4항에서 재확정한 SHA를 사용한다). 2. merge 실패, 충돌, 미승인, 권한 오류가 나면 STOP하고 원문 오류를 요약해 보고한다. 3. merge 성공 후 PR 번호, URL, merge 결과 메시지, squash commit SHA를 가능한 범위에서 기록해 둔다. @@ -40,7 +52,7 @@ Skip 조건: - 이미 merge된 PR이면 이 단계는 건너뛴다. - 사용자가 merge 방식 변경을 명시하지 않는 한 squash를 유지한다. -### 3. main pull + 로컬 실측 검증 +### 4. main pull + 로컬 실측 검증 1. 현재 레포 관례에 맞는 main checkout 또는 main worktree로 이동해 기본 브랜치를 최신화한다. 2. 로컬 검증 명령은 레포 컨텍스트에 위임한다. 이 레포 기본값은 main pull 후 `nrs`를 실행하고, 변경 영향 범위에 맞는 실측을 추가하는 것이다. @@ -55,7 +67,7 @@ Skip 조건: - `nrs`가 명백히 불필요한 레포에서는 해당 레포의 빌드/테스트 관례를 따른다. - 검증이 환경 제약으로 불가능하면 대체 확인을 수행하고, 불가능한 항목과 이유를 PR 코멘트에 명시한다. -### 4. PR 후속 코멘트로 검증 결과 박제 +### 5. PR 후속 코멘트로 검증 결과 박제 1. PR에 후속 코멘트를 남긴다. 포함 항목: - merge 결과와 main 최신화 여부 @@ -67,7 +79,7 @@ Skip 조건: Skip 조건: - GitHub API 장애로 코멘트 게시가 실패하면 로컬에 본문을 남기고 사용자에게 재시도 명령을 보고한다. -### 5. 관련 이슈 동기화 +### 6. 관련 이슈 동기화 1. PR 본문, 커밋 메시지, 브랜치명에서 참조 이슈를 수집한다. 2. `gh issue list --search`로 제목, 브랜치 키워드, 주요 변경 키워드를 검색해 누락된 관련 이슈를 확인한다. @@ -79,7 +91,7 @@ Skip 조건: - 검증 실패, 범위 불명확, 일부 미완료가 있으면 close하지 않는다. - 이슈가 다른 repo에 속할 수 있으면 URL 또는 repo를 재확인한 뒤 진행한다. -### 6. 산출물 위생 점검 +### 7. 산출물 위생 점검 1. 선택 단계로 머지된 diff를 훑어 코드/문서에 남은 프로세스 메타데이터, 임시 이슈 번호, 라운드 번호, finding ID, dangling partial hash, 작업용 절대경로를 확인한다. 2. 발견하면 이번 PR 후속 정리로 처리할지 별도 이슈/PR로 남길지 제안한다. @@ -87,7 +99,7 @@ Skip 조건: Skip 조건: - 바이너리, lockfile, 단순 버전 핀처럼 사람이 읽는 산출물이 아닌 변경은 이 단계를 생략할 수 있다. -### 7. 워크트리 정리 +### 8. 워크트리 정리 1. `CLAUDE.md`의 비대화형 `wt` 규칙을 따른다. 2. 현재 작업이 완료됐고 dirty/unpushed 변경이 없으면 `wt cleanup ` 또는 `wt cleanup --auto`로 정리한다. diff --git a/modules/shared/programs/claude/files/skills/review-pr-feedback/SKILL.md b/modules/shared/programs/claude/files/skills/review-pr-feedback/SKILL.md index b438e513f..91d5a116c 100644 --- a/modules/shared/programs/claude/files/skills/review-pr-feedback/SKILL.md +++ b/modules/shared/programs/claude/files/skills/review-pr-feedback/SKILL.md @@ -150,6 +150,14 @@ actionable로 분류된 각 피드백을 다음 7개 기준으로 검증한다. - conventional commit 형식을 따른다 (예: `fix(module): address PR feedback`). - 반영할 피드백이 여러 영역에 걸쳐 있으면 논리적으로 분리하여 복수 커밋으로 나눈다. +### Step 5.5: 방법론 PR의 CIR 동기화 (finding-unknowns) + +PR 본문에 durable marker ``가 있고(기록 주체·정본: create-pr 흡수 계약) 이번 run이 새 CIR 기록을 만들었다면, Step 6의 답글·resolve 전에 PR 본문의 CIR/Deviations를 동기화한다 — create-pr의 `update` 절차를 수행하는 handoff이며, 본문 전면 재작성이 아니라 CIR/Deviations 증분 갱신이다. "새 CIR 기록"은 코드에 반영한 실버그·설계 반전만이 아니라, `DESIGN_TRADEOFF`/`TECHNICAL_DISAGREEMENT`/`SCOPE_DEFERRAL` 기각이 남긴 설계 결정과 이관된 미지(분리 이슈 #N)도 포함한다 — 코드 무변경이 skip 기준이 아니다. 이 동기화를 건너뛰면 이후 finish-pr 퀴즈가 stale한 본문을 기준으로 출제된다. + +Skip 조건: +- marker가 없는 일반 PR이면 해당 없음. +- 이번 run에서 새 CIR 기록(반영·기각·이관 어느 쪽에서도)이 전혀 발생하지 않은 경우에만 건너뛴다. + ### Step 6: 답글 + resolve 모든 피드백(반영 여부 무관)에 대해 사유를 담은 답글/follow-up을 남기고 review thread는 resolve한다. diff --git a/modules/shared/programs/codex/default.nix b/modules/shared/programs/codex/default.nix index dfa47ddd8..5aa9e8ab8 100644 --- a/modules/shared/programs/codex/default.nix +++ b/modules/shared/programs/codex/default.nix @@ -65,6 +65,9 @@ let # codex-fan-out: Codex 세션은 native subagent fan-out이 기본 경로이므로 자기 참조가 된다. # 이 스킬은 Claude/headless 세션에서 codex exec subprocess를 구동하는 패턴용. "codex-fan-out" + # finding-unknowns: Claude 하네스 전용 오케스트레이터 — grilling/prototype/run-da/create-pr/finish-pr + # 조합과 AskUserQuestion 인터뷰·퀴즈에 결합되어 있어 Codex 단독 세션에선 의미가 없다. + "finding-unknowns" ]; mkCodexSkillEntry = name: { diff --git a/scripts/ai/verify-ai-compat.sh b/scripts/ai/verify-ai-compat.sh index dc255d761..19e0579eb 100755 --- a/scripts/ai/verify-ai-compat.sh +++ b/scripts/ai/verify-ai-compat.sh @@ -50,6 +50,7 @@ SHARED_EXPOSURE_EXCLUDE=( using-claude-p using-codex-exec codex-fan-out + finding-unknowns ) # Split retired names so the public stale-reference scan scope can stay # zero-match while this verifier still checks deployed residue. @@ -61,13 +62,15 @@ RETIRED_EXECUTABLES=( ) # SKILL.md tool-neutral lint has its own exclusion policy. It currently matches -# the shared exposure exclusions because these four skills are legacy adapters, -# but future exposure-only exclusions must be added deliberately. +# the shared exposure exclusions (legacy adapters + Claude-harness-only +# orchestrators), but future exposure-only exclusions must be added deliberately. SKILL_NEUTRAL_LINT_EXCLUDE=( set-icons using-claude-p using-codex-exec codex-fan-out + # finding-unknowns: Claude 하네스 전용 오케스트레이터 — AskUserQuestion 퀴즈 출제 규칙을 명시적으로 소유 + finding-unknowns ) errors=0