todo (코어)
저장소는 이미 존재하는 파일들로 구축된 폐쇄 루프 상태 머신입니다. 그 외에는 어떤 것도 상태를 저장하지 않습니다.
| 계층 | 파일 | 역할 | 쓰기 정책 |
|---|---|---|---|
| 요구사항 | README.md, docs/*.md | 진실 공급원: 계약, 명세, 설정, 장기 계획 | 읽기 전용 위주. todo-continue의 "문서 드리프트"에서 편집; todo-init/todo-plan/todo-add/todo-update로 계획 문서(docs/plans/) 편집; todo-init에서 예/아니오 응답 시 README Tests: 줄 편집; 선택적 RTM(reference/rtm.md)은 이미 존재할 때만 todo-plan/todo-add/todo-continue로 편집; todo-report로 docs/status.html 편집 |
| 활성 큐 | TODO.md | 하나의 작업 트리. 작업 항목 추적기이며, 설계 공간이 아님 | todo-* 스킬만 편집 가능 |
| 검증 | 소스 코드 + 테스트 스위트 | "완료"에 대한 진실 공급원 | 현재 작업에 대해서만 변경 |
| 아카이브 | CHANGELOG.md | 영구적, 추가 전용 (Keep a Changelog + Conventional Commits) | ## [Unreleased] (릴리스 시: 버전으로 이름 변경, 그 위에 새로운 빈 항목 추가, 마지막 링크 줄 수정)만 루트 드레인 및 확인된 /todo-release가 수정; todo-init이 파일을 생성하거나 누락된 [Unreleased]를 추가 |
| 검사 (선택 사항) | .todo/check.sh, .todo/todo-lint.sh, CI 작업 | 린트 + 테스트, CI, pre-push 훅 및 /todo-continue 실행 | check.sh는 /todo-init --ci 예 응답 시 작성; todo-lint.sh는 사용자가 복사; 사용자가 커밋 |
| 버전 저장소 | git | 작업당 브랜치 또는 워크트리. 검증되지 않은 것은 기본 브랜치에 도달하지 않음 | "Git 모드" 참조 |
파일 편집에는 네이티브 파일 도구(Read/Edit/Write)를 선호합니다. 편집 방식과 관계없이 의도한 줄만 변경하고 파일의 마지막 개행 문자를 유지하세요. 쉘은 git, 테스트 및 Done when 명령어, 선택적 스크립트, 그리고 스킬이 명명하는 파일 명령어(cp, chmod, mkdir -p, date, grep, cmp, mv, rm (스킬 자체 임시 파일))에만 사용하세요.
백로그 파일은 TODO.md, CHANGELOG.md, docs/plans/PROJECT.md, Ref:로 명명된 docs/plans/<ROOT-ID>-*.md, 그리고 todo-* 스킬이 작성한 README Tests: 및 Base: 줄입니다. README.md는 git diff README.md가 해당 줄들만 정확히 추가(선택적으로 빈 줄 다음)할 때만 백로그 커밋에 스테이징됩니다. 노드가 "문서 드리프트"에서 편집하는 README는 해당 노드의 파일이며 노드와 함께 커밋됩니다. 다른 모든 README 변경은 사용자의 것입니다: 클린 트리 검사에 포함되며 백로그 커밋에 의해 스테이징되지 않습니다. 백로그 편집은 스킬이 todo/ 브랜치에서 다음 커밋(보통 트리 클레임)할 때까지 커밋되지 않은 상태로 유지되며, 해당 커밋이 명시적 경로로 스테이징합니다. 새 루트와 클레임되지 않은 트리의 노드 변경은 기본 브랜치에서만 이루어집니다. todo/ 브랜치에서는 스킬이 이를 거부하고 기본 브랜치를 명명합니다. 클린 트리 검사(reference/git-flow.md)는 백로그를 무시합니다.
직접 사용
/todo 단독은 읽기 전용입니다: 명령어 목록 출력, TODO.md가 있으면 불변 조건 검사 실행, 보고. 아무것도 변경하지 않습니다.
| 명령어 | 목적 |
|---|---|
/todo-init | 부트스트랩 파일, 테스트 명령어 및 git 감지, 선택적 사전 계획 및 CI 설정, 이전 형식 마이그레이션 |
/todo-plan | 작업을 레인과 트리로 계획; 언제든지 계획 수정 |
/todo-add | 작업 추가 또는 요청을 트리로 분해 |
/todo-continue | 다음 작업 노드 실행, 검증, 상위 노드에 병합 |
/todo-update | 수동 상태 및 필드 변경 |
/todo-status | 읽기 전용 트리, 레인, 히스토리 및 검색 |
/todo-report | 대화형 HTML 상태 페이지를 docs/status.html에 작성 |
/todo-release | 사용자 확인 후 [Unreleased]를 버전으로 전환 |
각 스킬은 자신의 명령어만 실행하며 프롬프트 없이 다른 명령어로 체이닝하지 않습니다.
Git 모드
모든 명령어 시작 시 git rev-parse --is-inside-work-tree를 실행합니다.
- Git 저장소: 각 노드는 자체 브랜치 또는 워크트리에서 작업합니다(
reference/git-flow.md). 기본 브랜치는 사용자가 지정하는 브랜치이고, 그렇지 않으면 READMEBase:줄에 명시된 브랜치이고, 그렇지 않으면main,master,trunk,develop중 첫 번째로 존재하는 브랜치입니다; 이 중 아무것도 없으면 한 번 묻습니다. 사용자가 이 기본값과 다른 기본 브랜치를 지정하면 README에Base: <branch>를 추가할 것을 제안합니다(예 응답 시 작성;Tests:줄과 같은 백로그 파일). 기본 체크아웃(클레임, 클레임 해제, 기본 병합, 릴리스)으로 체크아웃하거나 병합하는 모든 단계는 메인 체크아웃(git worktree list의 첫 번째 항목)에서 실행됩니다: 연결된 워크트리에서 먼저cd로 이동; 해당 워크트리가 다른 브랜치에 있고 변경 사항이 있으면 중지하고 명령어를 출력합니다. - Git 저장소 아님: 명령어당 한 번 경고: "이것은 git 저장소가 아닙니다. todo 스킬은 여전히 작동하지만, 브랜치, 워크트리, 커밋 또는 병합이 없으므로 격리 및 히스토리가 없습니다. 활성화하려면
git init을 실행하세요." 그런 다음 no-git 모드를 사용합니다: 모든 git 단계를 건너뛰고,State:(files:포함)에서 진행 상황을 추적하며, 마커를 업데이트하고 CHANGELOG.md로 드레인합니다. 검증은 변경되지 않습니다.
태그, force-push, hard reset 또는 clean을 절대 사용하지 마십시오. 유일한 강제 브랜치 삭제는 스킬 자체의 게시되지 않은 클레임 커밋만 포함하는 브랜치의 삭제입니다(reference/git-flow.md, 트리 클레임 단계 2 및 5). 스킬의 자체 git 명령어는 네트워크에 절대 접근하지 않습니다: fetch, pull 또는 push 없음. 커밋 공유는 git과 사용자의 몫입니다. 테스트 명령어가 의존성을 다운로드할 수 있으며, 네트워크 부족으로 실패하면 재시도하지 않고 해당 이유로 차단합니다.
TODO.md 스키마
# Active Backlog
## 🌳 Task Tree
정확히 이 제목과 하나의 섹션입니다. In Progress, Ready 또는 Blocked 섹션이 없습니다: 각 작업의 마커가 상태입니다. 빈 트리는 두 개의 제목과 작업이 없는 상태입니다.
작업은 2~4줄입니다: 수행할 작업, 검증 방법, 선택적 링크 및 상태.
- [ ] **FEAT-002** · P1 · mid · XL · Add token refresh to the auth service
- Done when: old token rejected after refresh; `npx jest tests/auth`; regression: `npm test`
- Links: Ref: docs/auth.md#refresh · Depends: TASK-001 · From: FIX-001
- State: branch todo/FEAT-002-add-token-refresh-auth from main; next: build children
- [ ] **FEAT-002.1** · mid · Refresh endpoint
- Done when: endpoint covered by an integration test; `npx jest tests/auth/refresh.test.ts`
- [/] **FEAT-002.1.1** · high · Token store interface
- Done when: store round-trips a token; `npx jest tests/auth/store.test.ts`
- State: attempts 1/3; baseline 42 passing; branch todo/FEAT-002.1.1-token-store-interface from todo/FEAT-002.1-refresh-endpoint; next: build
| 부분 | 규칙 |
|---|---|
| 헤더 | - [m] **ID** · [P0-P2, 루트만 ·] COMPLEXITY [· SIZE] · 수행할 작업, 한 문장: 복잡도 low, mid 또는 high (필수); 크기 S, M, L 또는 XL (선택 사항) |
Done when: | 필수. 기준, ; , 그 다음 최소 하나의 정확한 명령어를 백틱으로 묶음. 선택적 ; regression: \cmd``; 없으면 회귀 테스트는 프로젝트 전체 스위트 |
Links: | 선택 사항. Ref: <path#anchor>, Depends: <IDs>, From: <ID>, Lane: <name> (루트만), ·로 구분 |
State: | 선택 사항, 컨텍스트 재설정에도 유지. ; 로 구분된 항목, 각 항목 최대 한 번, 순서: attempts n/3, baseline <n> passing (또는 none, 또는 red: <failing test ids, comma-separated>), `tier: <low |
Blocked: | [!] 작업의 경우, State 대신 그 자리 (마지막 필드 줄)에: <reason> → <command in backticks> <error, at most 5 lines joined with " / "> → <action required>. 수동 차단은 중간에 n/a (manual)을 작성 |
이 네 가지 필드만 존재합니다. 작업은 State와 Blocked를 동시에 가질 수 없습니다. 4줄을 초과하면 설계 산문이며 docs/에 속합니다 (Ref:로 링크). 작업에 더 많은 내용이 필요하면 분할하세요.
마커: [ ] 열림, [/] 활성 (파일당 최대 하나), [!] 차단됨, [x] 검증 및 병합됨 (또는 병합 중) 상위 노드로, 루트가 드레인될 때까지 대기.
트리, 레벨 및 복잡도
레벨 L의 노드는 헤더가 2L 공백으로 들여쓰기되고 필드는 2L+2 공백으로 들여쓰기됩니다. 최대 3레벨.
범위 규칙. 모든 리프는 하나의 컨텍스트 윈도우에 맞고 최대 5개 파일을 수정하는 하나의 변경입니다. 더 큰 작업은 자식으로 분할됩니다(/todo-add). 아직 분할하기엔 너무 큰 노드는 State: next: decompose를 유지하며, /todo-continue가 분해할 때까지 기다립니다.
크기 (복잡도 뒤, 선택 사항)는 독자에게 도움이 될 때 범위를 기록합니다. 존재할 경우 트리와 일치해야 하며, 노드를 추가하거나 제거하면 모든 조상의 크기가 업데이트됩니다:
| 크기 | 의미 | 위치 |
|---|---|---|
S | 하나의 변경, 최대 2개 파일 | 리프 |
M | 하나의 컨텍스트 윈도우, 최대 5개 파일 | 리프 |
L | 자식 있음, 모두 리프 | 부모 |
XL | 손자 있음 | 부모 |
State: next: decompose가 있는 리프는 L/XL을 가질 수 있습니다.
복잡도는 변경이 얼마나 큰지가 아니라 추론이 얼마나 어려운지를 나타내므로, 에이전트가 적합한 모델을 선택할 수 있습니다:
| 복잡도 | 의미 | 예시 |
|---|---|---|
low | 기계적: 원인과 변경 사항이 이미 알려져 있으며, 조사가 필요 없음 | 이름 변경, 문서, 설정, 작업 라인에 수정 사항이 명시된 가드 또는 작은 함수 |
mid | 약간의 조사나 설계가 필요한 일반적인 작업 (기본값) | 새 엔드포인트, 원인을 찾아야 하는 버그 |
high | 어려운 추론 또는 높은 위험 | 동시성, 보안, 데이터 마이그레이션, 불명확한 명세, 모듈 간 설계, 까다로운 알고리즘 |
부모는 통합 단계만으로 평가됩니다(보통 low 또는 mid); 자식은 자체 수준을 가집니다. 루트는 우선순위와 레인을 가지며, 자식은 이를 상속합니다.
모델 라우팅 (선택 사항)
프로젝트는 README 한 줄로 레벨을 모델에 매핑합니다(예: Models: low=haiku, mid=sonnet, high=opus - 에이전트가 이해하는 모든 이름). 이 줄이 없거나 하위 에이전트 도구가 없으면 복잡도는 힌트일 뿐이며 작업은 현재 모델에서 실행됩니다. 둘 다 있으면:
/todo-continue --delegate및 레인 실행은 각 노드(또는 레인 루트, 가장 높은 복잡도 기준)에 대해 매핑된 모델의 하위 에이전트를 제공합니다.- 리뷰어는 노드의 티어 이상에서 실행됩니다.
- 에스컬레이션: 검증 시도 실패 후 다음 시도는 한 티어 높게 실행됩니다(
low→mid→high),State:에tier:로 기록됨. 잘못된low레이블은 노드를 차단하지 않고 하나의 저렴한 시도를 소모합니다.
ID
- 루트
<PREFIX>-<NNN>, 하나의 전역 시퀀스, 3자리. 자식은.n을 추가:FEAT-002.1,FEAT-002.1.2. 점은 레벨과 같습니다. - ID는 재사용되지 않습니다. 다음 루트 번호 =
TODO.md,CHANGELOG.md(Includes:이후 ID 포함),docs/plans/*.md및, git 모드에서는 커밋 제목 (git log --all --format=%s, 드롭된 ID를 명명)에서 찾은 가장 높은 FEAT-/FIX-/TASK- 번호에 1을 더한 값입니다. 다음 자식 번호 = 동일한 위치에서 해당 부모 아래에서 찾은 가장 높은 자식 번호에 1을 더한 값입니다.
| 접두사 | 의미 | CHANGELOG 제목 | 커밋 유형 |
|---|---|---|---|
FEAT | 새 기능 | ### Added | feat |
FIX | 버그 또는 회귀 | ### Fixed | fix |
TASK | 리팩터, 유지보수, 문서, 테스트, 성능, 빌드 | ### Changed | 적합한 것 |
자식은 루트의 접두사를 사용합니다.
다음 노드는 무엇인가
노드가 작업 가능하려면: [ ] 상태이고; 모든 자식이 [x]이고; 모든 Depends: ID가 충족되고(CHANGELOG.md에 항목 ID로 또는 Includes: 뒤에, git 모드에서는 git show <base>:CHANGELOG.md에도, 또는 TODO.md에서 [x] 상태; 기본 브랜치의 CHANGELOG만 충족하면 /todo-continue는 노드를 시작하기 전에 기본 브랜치를 노드가 시작될 브랜치에 병합, 3단계); 차단된 조상이 없으며([!]); git 모드에서는 루트가 다른 브랜치에 의해 클레임되지 않아야 합니다. 루트가 클레임되었는지는 기본 브랜치의 TODO.md(git show <base>:TODO.md)에 있는 State:가 브랜치를 명명하는지로 확인합니다. 해당 트리는 해당 패밀리의 브랜치(todo/<ROOT-ID>-… 또는 todo/<ROOT-ID>.…)에서만 작업 가능합니다. 건너뛴 클레임 트리는 claimed by <branch>로 보고되며, 해당 브랜치가 이 클론에 존재하면 "이것이 당신의 작업인 경우: git switch <branch> (또는 해당 워크트리로 cd)하고 다시 실행하여 재개하세요"를 추가합니다. 이 클론의 브랜치는 다른 세션에 속할 수 있으므로 기본 브랜치에서 자동으로 재개되지 않습니다. 백로그 파일이 기본 브랜치에 커밋되지 않은 편집 내용을 보유하고 있으면 git switch가 실패합니다: 그렇게 말하고 먼저 git stash push -- <backlog paths>를 제안하고 기본 브랜치로 돌아와 git stash pop을 실행합니다.
중단된 작업이 우선입니다 (git 모드). 트리 브랜치(모든 todo/ 브랜치)에서 트리의 브랜치를 나열하고 (git branch --list 'todo/<ROOT-ID>-*' 'todo/<ROOT-ID>.*'), 각 브랜치의 노드를 git show <branch>:TODO.md에서 읽습니다. 아직 부모 브랜치에 병합되지 않은 브랜치에 [x]인 노드(git merge-base --is-ancestor <branch> <parent branch> 실패)는 병합 전에 중단되었습니다: 해당 병합을 완료하고 다른 작업은 하지 않습니다(/todo-continue 2단계). [/]인 노드는 가장 깊은 것부터 재개됩니다. 트리 브랜치 중 하나에 [!]인 노드는 모든 곳에서 [!]로 간주됩니다(작업 불가능, 조상이 대기), 다른 브랜치에서 여전히 [ ]로 표시되더라도 마찬가지입니다. 부모 브랜치의 TODO.md에 더 이상 노드가 없는 브랜치는 무시됩니다. 이미 부모 브랜치에 병합된 브랜치는 git branch -d로 삭제됩니다. 기본 브랜치에서는 이 과정을 건너뜁니다.
레인
레인은 하나의 에이전트 컨텍스트가 단독으로 순서대로 작업하는 루트 트리의 명명된 트랙입니다. 루트에 Lane: <name>(소문자, 그 다음 소문자, 숫자 또는 대시)이 있으면 전체 트리가 해당 레인에 속합니다. 자식은 이를 상속하며, 레인이 없는 루트는 main 레인에 있습니다 (--lane main은 해당 루트를 선택). 레인은 작업이 아닌 컨텍스트입니다: 하나의 레인은 하나의 작업 또는 여러 작업을 보유할 수 있으며, 레인은 서로 병렬로 실행됩니다 (/todo-continu
…
[번역을 위해 잘림]