{"slug":"handoff-12","title":"handoff","summary":"세션을 끊고 다음 세션에 넘긴다 — 협업 인프라(GitHub·GitLab·Forgejo·Jira·Plane·Slack)가 있으면 재개 가능한 상태를 그 트래커 이슈 본문으로 남기고 HANDOFF.md 에는 이슈 URL 을 가리키는 포인터만 적어 URL 하나로 건네고, 없으면 HANDOFF.md 자체에 전체 내용을 적어 그 파일로 끝낸다. 작업 이슈를 닫은 경계에서는 전용 이슈 대신 다음 작업 이슈에 코멘트 하나로 남긴다. 넘겨받은 쪽은 포인터나 파일을 읽고 적힌 단언을 실제와 대조한 뒤 이어서 착","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-24T15:42:50.795248Z","repo":{"url":"https://github.com/LeeYudok/doksam-skills","stars":12,"forks":2,"license":"MIT","updatedAt":"2026-09-24T05:35:27Z"},"bodyHtml":"<hr>\n<h2>name: handoff\ndescription: 세션을 끊고 다음 세션에 넘긴다 — 협업 인프라(GitHub·GitLab·Forgejo·Jira·Plane·Slack)가 있으면 재개 가능한 상태를 그 트래커 이슈 본문으로 남기고 HANDOFF.md 에는 이슈 URL 을 가리키는 포인터만 적어 URL 하나로 건네고, 없으면 HANDOFF.md 자체에 전체 내용을 적어 그 파일로 끝낸다. 작업 이슈를 닫은 경계에서는 전용 이슈 대신 다음 작업 이슈에 코멘트 하나로 남긴다. 넘겨받은 쪽은 포인터나 파일을 읽고 적힌 단언을 실제와 대조한 뒤 이어서 착수하고, 끝나면 결과를 남기고 닫는다. 컨텍스트가 40~50% 에 닿았을 때, \"여기서 끊자 / 상태 남겨 / 이어받아 / 재개\" 라고 하거나 핸드오프 URL·파일 경로를 붙여넣었을 때 쓴다.</h2>\n<h1>세션 핸드오프</h1>\n<p><code>.ai-sdlc/</code> 파이프라인 실행 중간의 단계 상태만 저장할 때는 <code>ai-sdlc-skills-handoff</code>의 실행 아티팩트를 따른다. 세션을 넘길 때는 이 스킬로 전달 경로와 다음 작업 이슈를 정한다.</p>\n<p>핸드오프는 <strong>요약이 아니라 재개 가능한 상태</strong>다. 다음 세션이 이것만 읽고 같은\n자리에서 다음 명령을 칠 수 있어야 한다. \"뭘 했는지\" 보다 <strong>\"지금 어디에 서 있고\n다음에 뭘 치는지\"</strong> 가 본체다.</p>\n<p>컨텍스트 사용량이 40~50% 에 닿으면 하던 걸 멈추고 이 스킬을 부른다. compaction 은\n모델이 뭘 버릴지 스스로 고르므로 안전망일 뿐이다.</p>\n<h2>어디에 남기나 — 상황당 한 곳</h2>\n<p>재개 상태를 <strong>두 군데에 나눠 적지 않는다.</strong> 나눠 적으면 어느 쪽도 혼자서는 재개\n가능한 상태가 아니게 되고, 다음에 쓸 때 한쪽 내용이 조용히 빠진다(2026-09-21 실측,\n이슈 #152 — 함정·기동 명령은 핸드오프 이슈에만, 새로 확정된 패턴은 다음 이슈\n메모에만 있었다).</p>\n<table>\n<thead>\n<tr>\n<th>상황</th>\n<th>남기는 곳</th>\n<th>다음 세션이 받는 것</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>이슈 도중</strong> — 작업 이슈가 아직 열려 있다(컨텍스트 40~50% 등)</td>\n<td>전용 핸드오프 이슈 + <code>HANDOFF.md</code>(포인터, 아래 \"두 갈래\")</td>\n<td>핸드오프 이슈 URL</td>\n</tr>\n<tr>\n<td><strong>이슈 경계</strong> — 작업 이슈를 닫았고 <strong>다음 작업 이슈가 이미 있다</strong></td>\n<td><strong>다음 작업 이슈에 코멘트 하나</strong> (1-6) — 전용 핸드오프 이슈는 만들지 않는다</td>\n<td>다음 작업 이슈 URL</td>\n</tr>\n<tr>\n<td>인프라 없음</td>\n<td><code>HANDOFF.md</code></td>\n<td>파일 경로</td>\n</tr>\n</tbody>\n</table>\n<p>이슈 경계인데 다음 작업 이슈가 아직 없으면 그 이슈를 먼저 만든다. 다음에 할 일이\n정해지지 않았다면 경계가 아니라 그냥 끝난 것이므로 핸드오프를 쓰지 않는다.</p>\n<h2>두 갈래, 인프라 있으면 원본은 이슈</h2>\n<table>\n<thead>\n<tr>\n<th></th>\n<th>하는 일</th>\n<th><code>HANDOFF.md</code></th>\n<th>다음 세션이 받는 것</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>인프라 있음</strong></td>\n<td>본문을 스크래치 파일에 쓰고 <strong>그 내용으로 이슈/티켓/스레드를 만든다</strong></td>\n<td><strong>포인터만</strong>(이슈 URL·작성 시각·요약·목록 링크)</td>\n<td><strong>전체 URL</strong></td>\n</tr>\n<tr>\n<td><strong>인프라 없음</strong></td>\n<td><code>HANDOFF.md</code> 에 전체 내용을 쓴다</td>\n<td><strong>본문 그대로 = 원본</strong></td>\n<td><strong>파일 경로</strong></td>\n</tr>\n</tbody>\n</table>\n<p>이슈 도중에 끊을 때 본문은 <strong>항상</strong> 만든다. 인프라가 있으면 그 본문은 이슈에\n들어가고 <code>HANDOFF.md</code> 는 위치만 가리킨다 — 레포에 재개 상태를 평문으로 남기지\n않고, 다음 세션은 파일 한 줄만 읽어도 어디로 가야 하는지 안다. 인프라가 없으면\n갈 곳이 없으므로 본문 자체가 <code>HANDOFF.md</code> 에 남는다(파일 모드) — 절차가 멈추지\n않는다.</p>\n<h2>모드</h2>\n<table>\n<thead>\n<tr>\n<th>호출</th>\n<th>하는 일</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>/handoff</code> (인자 없음)</td>\n<td><strong>작성</strong> — 이슈 도중이면 인프라 있을 때 이슈를 만들고 <code>HANDOFF.md</code> 엔 포인터만, 인프라 없으면 <code>HANDOFF.md</code> 에 전체 내용; 이슈 경계면 다음 작업 이슈 코멘트 → URL 또는 파일 경로 출력</td>\n</tr>\n<tr>\n<td><code>/handoff &lt;URL · #N · 파일경로&gt;</code></td>\n<td><strong>재개</strong> — 내용을 읽고 단언을 검증한 뒤 이어서 착수</td>\n</tr>\n<tr>\n<td><code>/handoff done</code></td>\n<td><strong>종료</strong> — 결과를 남기고 닫는다(이슈) / 파일에 적는다(파일 모드)</td>\n</tr>\n</tbody>\n</table>\n<p>사용자가 URL 이나 <code>HANDOFF.md</code> 경로만 붙여넣어도(설명 없이) 재개 모드로 본다.</p>\n<hr>\n<h2>0. 트래커 판별 (제일 먼저, 추측 금지)</h2>\n<p><strong>\"이 레포는 GitLab 이니까\" 같은 추정으로 명령을 고르지 않는다.</strong> 아래를 순서대로\n확인하고, 처음 성립하는 것을 쓴다.</p>\n<pre><code># 1) 레포 문서가 트래커를 지정했는가 (가장 강한 신호)\ngrep -riE 'jira|plane|linear|이슈는|트래커' AGENTS.md CLAUDE.md README.md 2&gt;/dev/null | head -5\n\n# 2) git 포지\ngit remote get-url origin\n\n# 3) 인증이 실제로 되는가 (설치돼 있다 ≠ 쓸 수 있다)\ngh auth status 2&gt;&amp;1 | tail -2\nglab auth status 2&gt;&amp;1 | tail -2\n\n# 4) 포지 밖 트래커의 자격증명이 있는가 — 이름만 본다, 값은 출력하지 않는다\nenv | grep -oE '^(JIRA|PLANE|SLACK|LINEAR)_[A-Z_]+' | sort -u\n</code></pre>\n<p>MCP 도구 목록에 Jira·Plane·Slack 도구가 있으면 그쪽을 <strong>CLI 보다 먼저</strong> 쓴다\n(자격증명을 셸로 꺼낼 일이 없다).</p>\n<table>\n<thead>\n<tr>\n<th>판별 결과</th>\n<th>쓰는 것</th>\n<th>프로젝트 지정</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>github.com/&lt;owner&gt;/&lt;repo&gt;</code></td>\n<td><code>gh</code></td>\n<td><code>--repo &lt;owner&gt;/&lt;repo&gt;</code></td>\n</tr>\n<tr>\n<td>GitLab (self-hosted 포함)</td>\n<td><code>glab</code></td>\n<td><code>projects/&lt;owner&gt;%2F&lt;repo&gt;</code> (슬래시는 <code>%2F</code>)</td>\n</tr>\n<tr>\n<td>Forgejo / Gitea</td>\n<td><code>curl</code> + 토큰</td>\n<td><code>/api/v1/repos/&lt;owner&gt;/&lt;repo&gt;/issues</code></td>\n</tr>\n<tr>\n<td>Jira</td>\n<td>MCP 도구 또는 REST</td>\n<td><code>/rest/api/3/issue</code> · 프로젝트 키 필요</td>\n</tr>\n<tr>\n<td>Plane</td>\n<td>MCP 도구 또는 REST</td>\n<td><code>/api/v1/workspaces/&lt;ws&gt;/projects/&lt;id&gt;/issues/</code></td>\n</tr>\n<tr>\n<td>Slack (티켓 없이 채널로 협업)</td>\n<td>MCP 도구 또는 <code>curl</code></td>\n<td>채널 ID · 스레드 permalink 가 URL</td>\n</tr>\n<tr>\n<td>아무것도 없음</td>\n<td><strong>파일 모드</strong></td>\n<td><code>HANDOFF.md</code> 경로가 곧 주소</td>\n</tr>\n</tbody>\n</table>\n<p><strong>애매하면 파일 모드로 내려간다.</strong> 잘못된 트래커에 이슈를 만드는 것보다,\n파일 하나를 정확히 남기고 사용자에게 \"트래커를 쓰려면 알려달라\" 고 하는 게 낫다.\n권한이 없어 이슈 생성이 실패한 경우도 마찬가지 — 실패를 삼키지 말고 파일 모드로\n끝낸 뒤 <strong>실패 사실과 원인을 한 줄로 알린다</strong>.</p>\n<hr>\n<h2>1. 작성</h2>\n<h3>1-1. 상태를 모은다 (추측 금지, 전부 실측)</h3>\n<pre><code>git branch --show-current &amp;&amp; git status --short\ngit log --oneline -5\ngit worktree list\n\n# 열린 작업 — 트래커에 맞는 것만\ngh pr list &amp;&amp; gh issue list --label handoff --state open      # GitHub\nglab mr list -P 10 &amp;&amp; glab issue list --label handoff -P 5    # GitLab\n\n# 띄워 둔 로컬 서버 — 포트는 이 레포 것으로 바꿔 적는다\nlsof -nP -iTCP -sTCP:LISTEN | grep -E '&lt;앱이름&gt;|&lt;포트&gt;' || true\n</code></pre>\n<p>검증 게이트를 돌렸다면 <strong>결과 원문</strong>(통과/실패 줄)을 그대로 옮긴다. 안 돌렸으면\n\"안 돌림\" 이라고 적는다 — 돌린 척이 제일 위험하다.</p>\n<h3>1-2. 본문을 스크래치 파일에 쓴다 (템플릿은 아래)</h3>\n<p>레포의 <code>HANDOFF.md</code> 에 바로 쓰지 않는다 — 인프라가 있으면 이 본문은 이슈로 가고\n파일에는 포인터만 남기 때문이다. 세션 스크래치 디렉터리(또는 <code>/tmp</code>) 에 임시\n파일로 아래 \"본문 템플릿\" 전 항목을 채워 쓴다.</p>\n<p>인프라가 전혀 없을 때만(0번 판별 결과 \"아무것도 없음\") 이 본문을 그대로 레포\n루트 <code>HANDOFF.md</code> 에 쓴다 — 이미 있으면 <strong>덮어쓴다</strong>. 핸드오프는 항상 \"지금\n상태\" 한 장이고, 과거 이력은 트래커와 그 레포의 작업 로그 파일\n(<code>CURRENT_TASK.md</code> 등)이 갖는다. 레포가 이 파일을 추적하지 않는다면\n(<code>.gitignore</code>) 커밋 대신 <strong>절대경로</strong>를 알린다.</p>\n<h3>1-3. 인프라가 있으면 이슈를 만든다</h3>\n<p>본문은 인라인 <code>--body \"$(...)\"</code> 나 <code>jq --arg</code> 말고 <strong>파일 경유</strong> — fenced code·표·\n백슬래시가 들어가면 escape 가 깨지고, 큰 본문은 ARG_MAX 를 넘겨 빈 요청이 된다.\n아래 <code>&lt;본문파일&gt;</code> 은 1-2 에서 쓴 스크래치 파일이다(레포의 <code>HANDOFF.md</code> 가 아니다).</p>\n<pre><code># GitHub\ngh issue create --title \"핸드오프: &lt;한 줄 요약&gt; (&lt;YYYY-MM-DD&gt;)\" \\\n  --label handoff --body-file &lt;본문파일&gt;.md\n\n# GitLab\nglab api --method POST \"projects/&lt;owner&gt;%2F&lt;repo&gt;/issues\" \\\n  -F \"title=핸드오프: &lt;한 줄 요약&gt; (&lt;YYYY-MM-DD&gt;)\" \\\n  -F \"labels=handoff\" \\\n  -F \"description=@&lt;본문파일&gt;.md\" \\\n  | python3 -c \"import json,sys;d=json.load(sys.stdin);print(d['iid'], d['web_url'])\"\n\n# Forgejo / Gitea — payload 를 파일로 만든 뒤 넘긴다(본문에 백틱·표가 들어가므로)\npython3 -c \"\nimport json;json.dump({'title':'핸드오프: &lt;요약&gt;','body':open('&lt;본문파일&gt;.md').read()}, open('payload.json','w'))\"\ncurl -s -X POST \"$FORGEJO_URL/api/v1/repos/&lt;owner&gt;/&lt;repo&gt;/issues\" \\\n  -H \"Authorization: token $FORGEJO_TOKEN\" -H 'Content-Type: application/json' \\\n  --data-binary @payload.json \\\n  | python3 -c \"import json,sys;d=json.load(sys.stdin);print(d['number'], d['html_url'])\"\n</code></pre>\n<p><strong>Jira / Plane / Slack 은 MCP 도구가 있으면 그것을 쓴다.</strong> 없을 때만 REST:</p>\n<pre><code># Jira — description 은 ADF 가 기본이지만 대부분 wiki/plain 도 받는다. 프로젝트 키 필수.\ncurl -s -X POST \"$JIRA_URL/rest/api/3/issue\" \\\n  -H \"Authorization: Bearer $JIRA_TOKEN\" -H 'Content-Type: application/json' \\\n  --data-binary @payload.json \\\n  | python3 -c \"import json,sys;d=json.load(sys.stdin);print(d['key'])\"\n# → URL 은 $JIRA_URL/browse/&lt;KEY&gt;\n\n# Plane\ncurl -s -X POST \"$PLANE_URL/api/v1/workspaces/$PLANE_WS/projects/$PLANE_PROJECT/issues/\" \\\n  -H \"X-API-Key: $PLANE_TOKEN\" -H 'Content-Type: application/json' \\\n  --data-binary @payload.json \\\n  | python3 -c \"import json,sys;d=json.load(sys.stdin);print(d['id'], d.get('sequence_id'))\"\n\n# Slack — 티켓 대신 채널 스레드로 협업하는 팀. 본문이 길면 스니펫 업로드가 낫다.\n#   메시지 1건 → permalink 를 URL 로 쓴다 (chat.getPermalink).\n</code></pre>\n<p>payload 는 셸에 인라인하지 말고 <strong>파일로 만든 뒤 <code>--data-binary @</code></strong> 로 넘긴다\n(위 두 명령의 <code>payload.json</code>). 토큰은 같은 줄에서 변수로만 쓰고 <code>-v</code>/<code>--trace</code> 를\n붙이지 않는다 — verbose 메타라인이 마스킹을 우회한다.</p>\n<p><code>handoff</code> 라벨(또는 그에 해당하는 Jira/Plane 라벨)이 없으면 먼저 만든다. 라벨이\n있어야 다음 세션이 \"열린 핸드오프\" 를 한 번에 찾는다.</p>\n<h3>1-4. <code>HANDOFF.md</code> 에 포인터를 쓰고 커밋한다</h3>\n<p>인프라가 있으면 레포 루트 <code>HANDOFF.md</code> 를 아래 \"포인터 템플릿\"으로 (덮어)쓴다 —\n스크래치 파일의 본문을 옮기지 않는다, 이슈 URL·작성 시각·한 줄 요약·<code>handoff</code>\n라벨 이슈 목록 링크만 남긴다. 레포에 작업 로그 파일이 있으면 맨 위에도 이슈\nURL 한 줄을 남긴다.</p>\n<p>파일 모드(인프라 없음)면 이 단계를 건너뛴다 — 1-2 에서 이미 전체 본문을\n<code>HANDOFF.md</code> 에 썼다. 그 경우 파일 맨 위에 \"트래커 없음 — 이 파일이 원본\" 이라고\n적는다.</p>\n<pre><code>git add HANDOFF.md &amp;&amp; git commit -m \"docs: 세션 핸드오프 (&lt;#N 또는 파일 모드&gt;)\"\n</code></pre>\n<p>브랜치에 커밋 중이면 <strong>푸시까지</strong> 한다 — 새 세션이 다른 워크트리에서 이어받을 수 있어야 한다.</p>\n<h3>1-5. 사용자에게는 한 줄</h3>\n<p>인프라가 있으면 <strong>전체 URL</strong>, 없으면 <strong>파일 절대경로</strong>. <code>/clear</code> 후 그것만\n붙여넣으면 이어진다고 알린다. 파일 모드였다면 \"트래커를 붙이면 다음부터 이슈로\n만든다\" 도 한 줄 덧붙인다.</p>\n<h3>1-6. 이슈 경계 — 다음 작업 이슈에 코멘트 하나</h3>\n<p>작업 이슈를 닫은 직후라면 1-2~1-4 대신 이 절차를 밟는다. 상태 수집(1-1)과 사용자\n안내(1-5)는 같다.</p>\n<ol>\n<li><strong>직전 핸드오프·착수 메모를 다시 읽는다.</strong> 방금 닫은 작업 이슈의 코멘트, 그 세션이\n이어받았던 핸드오프 이슈·<code>HANDOFF.md</code> 가 대상이다. 항목마다 <strong>유효 / 소멸</strong>을\n가른다 — 함정·검증 환경 기동 명령·미결 판단은 대부분 다음 이슈에서도 유효하다.</li>\n<li><strong>템플릿 전 항목을 채운 코멘트 본문을 파일로 쓴다</strong>(아래 \"본문 템플릿\" 그대로,\n제목만 <code>## 착수 메모 — &lt;YYYY-MM-DD&gt;</code>). 유효한 항목은 <strong>옮겨 적는다.</strong> \"이전 이슈·MR 을\n본다\" 로 떠넘기지 않는다 — 링크는 출처 표시일 뿐 내용을 대신하지 못한다. 이번\n세션에서 새로 확정된 것과 물려받은 것을 구분해 적으면 다음 경계에서 다시 가르기 쉽다.</li>\n<li><strong>자기완결 점검.</strong> 게시 전에 묻는다: 이 코멘트 밖의 다른 이슈·MR 을 열어야만 알 수\n있는 것이 있는가? 있으면 옮겨 적는다. 다음 작업 이슈 <strong>본문</strong>에 이미 있는 것(범위·\n설계·검증 기준)은 되풀이하지 않는다 — 본문과 코멘트를 합쳐 한 장이면 된다.</li>\n<li><strong>코멘트 하나로 게시한다</strong>(본문은 파일 경유 — 1-3 과 같은 이유).</li>\n</ol>\n<pre><code># GitHub\ngh issue comment &lt;다음 N&gt; --body-file &lt;메모파일&gt;.md\n# GitLab\nglab api --method POST \"projects/&lt;owner&gt;%2F&lt;repo&gt;/issues/&lt;다음 N&gt;/notes\" -F \"body=@&lt;메모파일&gt;.md\"\n# Jira / Plane / Slack — MCP 도구로 해당 티켓·스레드에 댓글\n</code></pre>\n<p>게시한 뒤 빠진 것을 발견하면 코멘트를 <strong>하나 더 달지 말고 그 코멘트를 고친다</strong> —\n읽을 곳이 둘이 되는 순간 같은 문제가 다시 생긴다. 이 세션이 이어받았던 핸드오프\n이슈가 열려 있으면 3장대로 닫고, 닫는 코멘트에 다음 작업 이슈 URL 을 적는다.</p>\n<p><code>HANDOFF.md</code> 는 이 갈래에서 쓰지 않는다. 레포에 이전 것이 남아 있으면 맨 위에\n<code># 종료 — &lt;날짜&gt;</code> 와 다음 작업 이슈 URL 을 적어 낡은 포인터를 최신으로 오해하지\n않게 한다.</p>\n<hr>\n<h2>2. 재개</h2>\n<h3>2-1. 내용을 읽는다</h3>\n<p>인프라가 있으면 <code>HANDOFF.md</code> 는 <strong>포인터</strong>다 — 먼저 그 파일을 읽고 적힌 이슈\nURL 을 연다. 파일 자체를 재개 상태로 쓰지 않는다. 인프라가 없으면 파일 자체가\n본문 전체다.</p>\n<pre><code>cat HANDOFF.md   # 포인터: 이슈 URL 을 얻는다 (인프라 없으면 이 파일이 본문 전체)\n\n# GitHub\ngh issue view &lt;N&gt; --comments\n# GitLab\nglab issue view &lt;N&gt;\nglab api \"projects/&lt;owner&gt;%2F&lt;repo&gt;/issues/&lt;N&gt;/notes\" | python3 -c \"\nimport json,sys\nfor n in json.load(sys.stdin): print('---', n['author']['username'], n['created_at']); print(n['body'][:2000])\"\n# Jira / Plane / Slack — MCP 도구로 본문과 댓글/스레드 답글을 함께 읽는다\n</code></pre>\n<p><strong>코멘트가 본문보다 최신일 수 있다</strong> — 이슈 모드면 항상 둘 다 읽는다. 받은 URL 이\n핸드오프 이슈가 아니라 <strong>작업 이슈</strong>여도 절차는 같다(이슈 경계 갈래로 넘겨받은 경우):\n본문이 범위·검증 기준이고 착수 메모 코멘트가 재개 상태다. 파일 모드는\n파일 하나가 전부이지만, 그만큼 <strong>git log 로 언제 갱신됐는지</strong>를 같이 본다\n(<code>git log -1 --format='%ci' -- HANDOFF.md</code>).</p>\n<h3>2-2. 단언을 검증한다 (본문도 decay 한다)</h3>\n<p>적힌 것 중 <strong>행동을 바꾸는 단언 1~2개</strong>는 실제와 대조한 뒤 움직인다. 실전에서\n\"열려 있다\" 던 PR 이 이미 머지돼 있던 적이 있다.</p>\n<table>\n<thead>\n<tr>\n<th>적혀 있는 것</th>\n<th>확인</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>브랜치/워크트리</td>\n<td><code>git worktree list</code>, <code>git branch -a --contains &lt;sha&gt;</code></td>\n</tr>\n<tr>\n<td>PR/MR 상태</td>\n<td><code>gh pr view &lt;N&gt;</code> / <code>glab mr view &lt;N&gt;</code> — 이미 머지됐을 수 있다</td>\n</tr>\n<tr>\n<td>이슈/티켓 상태</td>\n<td><code>gh issue view &lt;N&gt;</code> / <code>glab issue view &lt;N&gt;</code> / Jira·Plane 조회 — 이미 닫혔을 수 있다</td>\n</tr>\n<tr>\n<td>띄워 둔 서버</td>\n<td><code>curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:&lt;port&gt;/</code></td>\n</tr>\n<tr>\n<td>배포된 버전</td>\n<td>서비스의 <code>/version</code>·<code>/healthz</code> 를 직접 친다</td>\n</tr>\n<tr>\n<td>다음 명령</td>\n<td>경로·스크립트가 아직 있는지 (<code>ls</code>, <code>git show --stat</code>)</td>\n</tr>\n</tbody>\n</table>\n<p>충돌하면 <strong>실제 상태를 믿고</strong> 이슈에 코멘트로(파일 모드면 파일에) 교정한다.</p>\n<h3>2-3. 이어서 착수</h3>\n<ul>\n<li>워크트리가 남아 있으면 그 안에서, 없으면 <code>git worktree add ../&lt;repo&gt;-&lt;n&gt; &lt;branch&gt;</code>.</li>\n<li>정식 클론에서는 <code>checkout</code>/<code>switch</code> 금지(pull·읽기만) — 다른 세션의 발밑이 바뀐다.</li>\n<li>핸드오프는 <strong>작업 이슈가 아니다</strong> — 실제 작업 이슈 번호가 적혀 있으면 그걸\n브랜치/커밋/PR 에 박는다. 핸드오프는 세션 사이를 잇는 표식일 뿐이다.</li>\n</ul>\n<hr>\n<h2>3. 종료</h2>\n<p>이어받은 작업이 끝나면(또 다른 핸드오프를 쓰는 경우 포함) 핸드오프를 닫는다.</p>\n<pre><code># GitHub\ngh issue comment &lt;N&gt; --body-file &lt;결과파일&gt;.md &amp;&amp; gh issue close &lt;N&gt;\n# GitLab\nglab api --method POST \"projects/&lt;owner&gt;%2F&lt;repo&gt;/issues/&lt;N&gt;/notes\" -F \"body=@&lt;결과파일&gt;.md\"\nglab issue close &lt;N&gt;\n# Jira / Plane — MCP 도구로 댓글 + 상태를 Done/Completed 로\n# Slack — 같은 스레드에 결과를 답글로 달고 해결 이모지 등 팀 규약을 따른다\n</code></pre>\n<p>파일 모드면 <code>HANDOFF.md</code> 맨 위에 <strong><code># 종료 — &lt;날짜&gt;</code></strong> 와 결과를 적고 커밋한다.\n다음 핸드오프를 쓰는 경우라면 그 파일을 새 내용으로 덮어쓰는 것이 종료다.</p>\n<p>이슈 경계 갈래로 받은 세션은 닫을 핸드오프 이슈가 없다 — 작업 이슈의 통상 종료(결과\n코멘트 + 클로즈)가 곧 종료이고, 다음 작업이 이어지면 1-6 으로 그 이슈에 메모를 남긴다.</p>\n<p>닫을 때 한 줄: 무엇이 끝났고, 다음 핸드오프가 있으면 그 URL/경로.\n열린 핸드오프가 둘 이상 쌓이면 어느 게 최신인지 모른다 — <strong>동시에 하나만</strong> 연다.</p>\n<hr>\n<h2>템플릿</h2>\n<h3>본문 — 스크래치 파일 → 이슈/코멘트 본문, 인프라 없으면 <code>HANDOFF.md</code></h3>\n<pre><code># HANDOFF — &lt;한 줄 요약&gt;\n\n- 이슈: &lt;URL&gt;  (트래커가 없으면 \"없음 — 이 파일이 원본\")\n- 작성: &lt;YYYY-MM-DD HH:MM:SS.mmm&gt;\n- 작업 이슈/PR: #&lt;N&gt; · #&lt;M&gt; (&lt;상태&gt;)\n- 브랜치: `&lt;branch&gt;`  ·  워크트리: `&lt;path&gt;` (없으면 \"없음 — 새로 만들 것\")\n- HEAD: `&lt;sha&gt;` (&lt;push 여부&gt;)\n\n## 지금 어디까지\n\n&lt;끝난 것 / 안 끝난 것을 사실로. \"대체로 됨\" 금지.&gt;\n\n## 검증 결과 (원문)\n\n```\n&lt;테스트·빌드·게이트의 마지막 실행 결과 그대로. 안 돌렸으면 \"안 돌림\"&gt;\n```\n\n## 실행 중인 것\n\n| 대상 | 주소 | 어떻게 띄웠나 |\n| --- | --- | --- |\n| &lt;로컬 서버&gt; | &lt;http://127.0.0.1:포트&gt; | &lt;명령 + 실행 디렉터리&gt; |\n| &lt;터널/프록시&gt; | &lt;127.0.0.1:포트&gt; | &lt;스크립트 경로, pid&gt; |\n\n## 미결 판단\n\n&lt;사람이 정해야 하는 것. 선택지와 각 선택의 결과까지.&gt;\n\n## 다음에 칠 명령\n\n```bash\n# 복붙 가능한 형태로, 실행 디렉터리 포함\ncd &lt;절대경로&gt;\n&lt;command&gt;\n```\n\n## 함정\n\n&lt;이번에 밟은 것. 도구·플랫폼 차이, 잘못 읽기 쉬운 신호 등.&gt;\n</code></pre>\n<h3>포인터 — 인프라가 있을 때 레포 <code>HANDOFF.md</code> (본문은 위 템플릿으로 만든 이슈에 있다)</h3>\n<pre><code># HANDOFF (포인터)\n\n세션 인계 본문은 &lt;트래커&gt; 이슈에 있다. 이 파일은 그 위치만 가리킨다.\n\n- 현재 핸드오프: &lt;이슈 URL&gt;\n- 작성: &lt;YYYY-MM-DD HH:MM:SS.mmm&gt;\n- 요약: &lt;한 줄 — 무엇이 막혀 있고 뭘 기다리는지&gt;\n- 전체 목록: &lt;handoff 라벨 이슈 목록 URL&gt;\n</code></pre>\n<hr>\n<h2>원칙</h2>\n<ul>\n<li><strong>인프라 있으면 원본은 이슈, <code>HANDOFF.md</code> 는 포인터. 인프라 없으면 원본은 파일</strong>.\n트래커가 없거나 실패해도 핸드오프는 완성된다.</li>\n<li><strong>상황당 한 곳</strong>. 이슈 도중이면 핸드오프 이슈, 이슈 경계면 다음 작업 이슈의 코멘트\n하나. 둘 다 쓰지 않고, 어느 쪽이든 그것만 읽고 시작할 수 있어야 한다.</li>\n<li><strong>사실만</strong>. 날짜·이슈번호·수치는 실측으로 채우고, 모르면 \"모름\" 이라고 쓴다.</li>\n<li><strong>명령은 복붙 가능하게</strong>. 실행 디렉터리 포함, 상대경로 금지.</li>\n<li><strong>큰 tool output 은 붙여넣지 않는다</strong> — 파일로 남기고 경로와 마지막 몇 줄만.</li>\n<li>본문에 <code>.env</code> 값·토큰·비밀번호를 넣지 않는다. 키 <strong>이름</strong>까지만. 트래커가 공개\n채널이면 내부 호스트명·경로도 한 번 더 걸러 본다.</li>\n<li>한 세션 = 한 작업 이슈. 핸드오프는 그 경계를 넘기는 장치지, 한 세션을 늘리는 장치가 아니다.</li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":20455,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"notes-only","suspicious":0,"notes":2,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-24T15:43:24.679982Z","sha256":"10596AFEDB5FC5FE09339AD91168D1FC21DF407FDDB9B6CBEBDC8DF0B31A7D79","sizeBytes":8359},"review":null,"source":{"repositoryUrl":"https://github.com/LeeYudok/doksam-skills","path":"skills/handoff","license":"MIT","commit":"841cccdaa8b607e9c5d0adc9c95151c286a8f229","subtreeSha":"9068E60F34ED4BD365E6138522F667A6080E854B5E061E3DF8B16DA1AD1AC361","lastSyncedAt":"2026-09-24T15:42:49.340415Z"},"reviewedAt":"2026-09-24T15:44:58.315804Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/LeeYudok/doksam-skills/tree/main/skills/handoff"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install leeyudok-doksam-skills@llmmart"},{"target":"git","command":"git clone https://github.com/LeeYudok/doksam-skills.git"}]}