티켓 직접 발행하기
요구사항 접수하기는 하고 싶은 말을 그대로 넣고 pm이 쪼개 주기를 기다리는 길입니다. 이 장은 반대쪽입니다. 무엇을 시킬지 이미 알고 있을 때 쓰세요. 버그 하나, 오타 하나, 이미 잘게 갈라져 있는 일에는 해석할 것이 없습니다. 없는 해석을 하자고 pm 세션을 한 번 태울 이유도 없고요. 그럴 때는 티켓을 직접 씁니다.
밑에서 파일 하나가 만들어지는 것은 똑같습니다. 그 파일을 쓰는 손이 pm 세션이 아니라 폼일 뿐입니다.
발행 다이얼로그
보드 우상단에 버튼이 둘 있는데, 왼쪽이 티켓 발행입니다(오른쪽 primary는 요구 접수).
보드에서 ⌘I를 눌러도 열립니다. 이 키는 기본값이고 설정의 키맵에서 바꿉니다. 페이지가 아니라
다이얼로그라서 취소가 곧 닫기이고, 뒤에는 보드가 필터·검색·스크롤 그대로 남아 있습니다.
칸은 일곱입니다.
| 칸 | 무엇 |
|---|---|
title | 필수. 한 줄 제목 |
kind | select — work · request · feedback |
persona | select — personas/ 아래 프로필이 실제로 있는 이름만 뜹니다 |
우선순위 | select 1~5. 기본값 3 |
마감 | 날짜와 시간. 비워두면 마감 없음입니다 |
deps | 기존 티켓 멀티셀렉트. 자유 입력 없음 |
| 본문 | ## Goal · ## Done when 골격이 미리 채워져 나옵니다 |
- 해시는 서버가 만듭니다. 0~9와 a~f로 된 여덟 글자(hex)를 뽑고 이미 있는 값이면 다시
뽑습니다. 파일 생성이
O_EXCL이라 같은 이름이 두 번 나올 일도 없고요. 사람이 해시를 타이핑할 자리는 이 화면 어디에도 없습니다. deps에 자유 입력이 없는 것이 그 칸의 요점입니다. 손으로 해시를 적던 시절에는 오타 한 글자가 존재하지 않는 선행이 됐습니다. 없는 티켓은 영원히 완료되지 않으니, 그것을 기다리는 티켓도 영원히 대기합니다. 고르기만 할 수 있으면 그런 사고가 구조적으로 생기지 않습니다.- 발행에 성공하면 그 티켓 상세로 넘어갑니다. 그 이동이 다이얼로그를 닫습니다. 자기 티켓이 큐에 들어간 것을 그 자리에서 보게 됩니다.
- 본문 아래에 첨부 손잡이가 있습니다. 이미지를 붙여넣거나 파일을 골라 올리면 바이트가 아니라 경로가 본문 끝에 붙습니다(도는 세션에 말 걸기의 파일 첨부와 같은 방식입니다).
- 쓰다 만 것이 있으면 닫기를 한 번 막습니다.
쓰던 내용이 있습니다를 묻고,버리고 닫기를 고를 때만 지웁니다. 발행이 실패해도 다이얼로그는 열린 채 사유만 그 안에 뜹니다. 닫는 바람에 쓴 글을 날리는 일은 없습니다.
## Done when을 쓰는 법
이 장에서 제일 중요한 자리입니다. ## Goal이 왜 필요한지와 무엇을 만드는지를 2~4줄로 적는
칸이라면, ## Done when은 끝났는지를 판정하는 문장입니다.
판정할 수 있는 문장은 "명령 X를 돌리면 Y가 나온다" 꼴입니다.
나쁜 예:
## Done when
- [ ] CSV 내보내기가 잘 동작한다
- [ ] 필터도 개선한다좋은 예:
## Done when
- [ ] `/orders`에 `CSV 내보내기` 버튼이 보인다
- [ ] 누르면 지금 화면의 필터가 적용된 행만 담긴 파일이 떨어진다
- [ ] 헤더 행의 컬럼명이 한글이다"잘 동작한다"는 세션이 자기 손으로 판정할 수 없는 문장입니다. 그러면 세션은 그 항목을 못 켜거나,
근거 없이 켭니다. 어느 쪽이든 화면이 거짓말을 하게 됩니다. 세션은 항목을 하나 만족시킬 때마다
그 자리에서 - [ ]를 - [x]로 바꾸고, 도는 티켓을 열어 어디까지 갔는지 보는 자리가 정확히
그 체크박스입니다(화면 소개의 진행 표시). 검증할 수 있는 문장이어야
그 표시가 사실이 됩니다.
"필터도 개선한다"는 다른 문제입니다. 한 티켓에 두 가지가 들어 있습니다. 항목이 여섯 개를 넘으면 쪼갤 신호로 보세요. 티켓 하나는 한 세션(5~25분)이 리뷰할 수 있는 변경 하나여야 합니다. 화면 3개와 그 테스트가 필요하다면 그건 티켓 하나가 아니라 넷입니다.
kind — 티켓의 분류 넷
값은 넷인데 셋만 select에 있습니다. 넷째는 앱이 씁니다.
work — 지시입니다. 받은 페르소나가 수행하고 끝나면 완료로 넘어갑니다. 직접 발행하는
티켓은 대부분 이것입니다.
request — 부탁이나 질문입니다. 받은 사람은 답을 원본에 덧붙이지 않고 새 티켓으로
만듭니다. 원본은 질문의 기록으로 그대로 남습니다. 요구 접수가 세우는 티켓이 이 값에
persona: pm이 붙은 것입니다.
feedback — 결과보고나 지적입니다. 받은 사람은 조치가 필요하면 새 티켓을 만들고
아니면 그냥 끝냅니다.
answer — 답변 파일입니다. 선택지에는 없습니다. 답변 대기 티켓에 사람이 답을 쓰면 앱이
이 값으로 파일을 하나 만드는데, 태어날 때부터 완료입니다. 아무도 그것을 수행하지 않기
때문입니다(다음 장 티켓이 지나는 상태 참고).
엔진은 kind 값을 강제하지 않습니다. 발행 폼은 강제합니다. select 밖의 값이 넘어오면 사유를 붙여
거부합니다. 보드의 kind 필터도 이 값으로 걸립니다. 다음에 이 티켓을 읽는 사람이나 세션이
지시인지 질문인지 보고인지를 알아볼 단서는 이 한 줄뿐입니다. 비워두지 마세요.
persona — 이 일을 맡는 역할
고른 이름의 personas/<이름>/PROFILE.md 본문이 세션 프롬프트 머리에 그대로 인라인됩니다.
같은 일이라도 developer가 받으면 코드를 짜고 qa가 받으면 그 코드를 깨러 갑니다. 이 칸
하나가 그 차이를 만듭니다(페르소나 참고).
- 페르소나는 워커가 아니라 티켓에 붙습니다. 아무 워커나 집어 가고 집은 워커가 그 티켓의
persona:대로 세션을 엽니다. - select에는 프로필이 실제로 있는 이름만 뜹니다. 이름만 있고
PROFILE.md가 없으면 엔진이 경고만 남기고 그냥 돌지만, 그런 이름은 새 티켓의 선택지가 되지 않습니다. - 비워도 됩니다. 워커가 열린 티켓 하나를 집어 세션을 여는 일을 디스패치라고 하는데, 페르소나가 비어 있어도 디스패치는 그대로 되고 그게 정상 경로입니다. 역할이 판단을 가르는 티켓에만 붙이세요.
deps — 없으면 착수가 불가능한 것에만
멀티셀렉트에서 고른 티켓이 전부 완료여야 이 티켓이 큐에 뜹니다. 하나라도 안 끝났으면 보드
대기 레인에 주황색 deps 태그를 달고 앉아 있고 그동안 어떤 워커도 집어가지 않습니다.
병렬로 돌 수 있는 일에는 걸지 마세요. 남발하면 워커가 놀고 큐가 직렬화됩니다. 워커가 여섯이어도
사슬로 엮인 티켓 여섯은 한 번에 하나씩 돕니다. 기준은 하나입니다. 그것이 안 끝나면 착수 자체가
불가능한가. "먼저 끝나 있으면 참고하기 좋다"는 deps가 아닙니다.
우선순위와 마감 — 큐에서 몇 번째로 뜨는가
deps가 착수할 수 있는지를 가르고 이 둘은 그다음 순서를 정합니다. 기본값은 3이고 숫자가 클수록
먼저 뜹니다. 같은 값끼리는 만든 순서입니다.
양 끝 둘만 동작이 다릅니다.
- 1은 진행중 티켓이 0건일 때만 후보입니다. 다른 티켓이 하나라도 돌고 있으면 순서가 와도 건너뜁니다.
- 5는 도는 세션 하나를 끊습니다. 남은 워커가 없으면 유효 우선순위가 가장 낮은 세션에
TERM을 보내고 그 자리를 가져갑니다. 끊긴 티켓은 열림으로 돌아가고 무슨 일이 있었는지가 자기 본문## 선점절에 적힙니다. 세션은 이 값을 쓰지 않습니다. 사람만 씁니다.
선행은 자기를 기다리는 티켓의 값을 물려받습니다. 5짜리 티켓이 3짜리 선행에 막혀 있으면 그
선행이 5로 떠서 먼저 풀립니다. 그러지 않으면 5가 3 뒤에 섭니다. 물려받은 값은 매번 다시 세는
값이라 파일의 priority:를 고치지 않습니다.
마감은 그 순서를 시계로 덮습니다. 남은 시간이 5시간 이하면 5로, 7일 이상이면 1로
취급합니다. 마감이 이미 지난 것도 5입니다. 그 사이 구간에서는 적어둔 우선순위가 그대로 섭니다.
그러니 2주 뒤 마감을 적으면 처음 며칠은 오히려 뒤로 밀립니다. 급한 것을 앞으로 당기려면
우선순위를 올리세요. 마감은 언제까지인지를 적는 칸입니다.
선행의 마감이 이 티켓보다 늦으면 발행 버튼이 잠기고 어긋난 해시가 입력 아래에 뜹니다. 선행이 후행보다 늦게 끝날 수는 없으니까요.
복제 — 이미 있는 티켓에서 시작하기
티켓 상세 머리의 복제는 이 발행 다이얼로그를 원본 값으로 채워서 여는 버튼입니다. 새 화면이
아니라 같은 폼이라, 열린 자리에서 제목과 본문을 고쳐 발행하면 됩니다. 상태는 가리지 않습니다.
원본을 읽기만 하므로 진행중 티켓에서도 안전합니다.
넘어오는 값은 넷입니다. title · kind · persona · 본문 전문. 본문에는 워커가 붙인
## 결과·## 블록도 그대로 딸려 옵니다. 절 이름으로 잘라내는 규칙은 멀쩡한 절까지 먹기
때문이고, 지우는 자리가 눈앞의 textarea입니다.
deps는 비운 채로 열립니다. 미충족 선행을 그대로 복제하면 사본이 조용히 대기하게 됩니다.
선후는 그때의 큐 상태에 달린 값이라 멀티셀렉트에서 다시 고르세요. 우선순위와 마감도 같은 이유로
안 물려받습니다. 기본값 3과 빈칸으로 열립니다. 엔진이 쓰는
키(session_id·owner·pid·awaiting…)도 넘어오지 않습니다. 새 티켓에 그 값이 들어가면
이미 할당된 것으로 보여 영원히 디스패치되지 않습니다.
고칠 수 있는 티켓, 못 고치는 티켓
발행한 티켓의 title·kind·persona·우선순위·마감·본문은 상세 화면에서 계속 고칠 수 있습니다.
deps는 그 폼에 없습니다. 손으로 치는 칸을 두면 오타 해시로 영구 대기가 생기고 고를 목록을
세우는 자리는 아직 발행 다이얼로그 하나뿐입니다. 선후를 바꿔야 하면 복제해서 다시 고르거나 티켓
파일의 deps: 줄을 직접 고치세요. 상태에 따라 둘은 더 잠깁니다.
- 완료 티켓은 읽기 전용입니다. 편집·삭제·할당 해제가 전부 막힙니다.
.done파일이 있다는 것 자체가 이 큐의 이력이라서 그렇습니다. 같은 일을 조건만 바꿔 다시 시키고 싶다면 그 자리가 위의복제입니다. - 진행중 티켓은 할당을 푼 뒤에야 고칩니다. 세션이 지금 그 파일을 쥐고 쓰는 중이라, 밑에서
고치면 도는 세션의 작업을 밟습니다. 잠금 카드의
할당 해제를 누르면 티켓이 큐로 되돌아오고 그다음에 편집 폼이 열립니다.
나머지 frontmatter 키
다이얼로그가 묻는 일곱 칸이 사람이 쓰는 값의 전부입니다. 나머지 키는 디스패처와 엔진이
씁니다. 티켓 파일 맨 위 --- 두 줄 사이에 키: 값으로 적히는 그 머리말을 frontmatter라고
부릅니다. 키 하나하나의 뜻과 누가 언제 쓰는지는 frontmatter 필드에
표로 정리해 두었습니다. 여기서 다시 세우지 않습니다.
다음은 티켓이 지나는 상태입니다.