diff --git a/.agents/skills/harness-plan/SKILL.md b/.agents/skills/harness-plan/SKILL.md index 91e3f77..f83618e 100644 --- a/.agents/skills/harness-plan/SKILL.md +++ b/.agents/skills/harness-plan/SKILL.md @@ -10,7 +10,7 @@ Codex에서 Claude Code `/harness-plan`에 해당하는 절차를 직접 수행 ## 절차 -1. `AGENTS.md`, `CLAUDE.md`, `agents/quality-gates.md`, `tasks/index.json`, `Plans.md`, 필요한 기획 문서를 읽는다. +1. 필요한 기획 문서를 읽는다. 이미 세션에 로드된 규칙 문서(`AGENTS.md`, `CLAUDE.md`, `agents/quality-gates.md`)는 재독하지 않는다. 기존 Task 현황은 `tasks/index.json` 전체 대신 `python3 scripts/report_tasks.py` 요약으로 확인한다(기존 Task ID 목록은 step 2의 context.json에 포함된다). `Plans.md`는 읽지 않는다. 2. `python3 scripts/build_planning_context.py`로 planning context를 만든다. 3. 현재 Codex 세션이 `agents/task-decomposer.md` 기준으로 proposal 파일 계약을 채운다. 4. `harness.toml [plan].decomposer_command`가 명시되어 있으면 외부 명령으로 proposal 생성을 위임할 수 있다. 실패하면 쉬운 실패 로그를 남기고 inline fallback으로 돌아온다. diff --git a/.agents/skills/harness-progress/SKILL.md b/.agents/skills/harness-progress/SKILL.md index dd0eafe..4ce53f9 100644 --- a/.agents/skills/harness-progress/SKILL.md +++ b/.agents/skills/harness-progress/SKILL.md @@ -9,8 +9,8 @@ description: tasks/index.json 기준으로 진행 상황을 읽기 전용 요약 ## 절차 -1. `AGENTS.md`, `CLAUDE.md`, `tasks/index.json`을 읽는다. -2. 필요하면 `python3 scripts/report_tasks.py`를 실행한다. +1. 이미 세션에 로드된 규칙 문서(`AGENTS.md`, `CLAUDE.md`)는 재독하지 않는다. `tasks/index.json`을 전체 Read 하지 않는다. +2. `python3 scripts/report_tasks.py`를 실행해 요약을 얻는다. 특정 Task 상세가 필요하면 `grep -n -A12 '"id": ""' tasks/index.json`으로 해당 블록만 읽는다. 3. `todo`, `wip`, `blocked`, `done` 수와 다음에 착수 가능한 Task를 요약한다. 4. `Plans.md`가 stale일 가능성이 있으면 `python3 scripts/sync_plans.py --check` 결과를 보고한다. diff --git a/.agents/skills/harness-review/SKILL.md b/.agents/skills/harness-review/SKILL.md index 06af9e7..6348462 100644 --- a/.agents/skills/harness-review/SKILL.md +++ b/.agents/skills/harness-review/SKILL.md @@ -9,7 +9,7 @@ Codex에서 Claude Code `/harness-review`에 해당하는 리뷰 절차를 수 ## 절차 -1. `AGENTS.md`, `CLAUDE.md`, `agents/quality-gates.md`, 대상 Task, Acceptance evidence, 현재 diff를 읽는다. +1. 대상 Task 상세, Acceptance evidence, 현재 diff를 읽는다. 현재 세션에 이미 로드된 규칙 문서(`AGENTS.md`, `CLAUDE.md`, `agents/quality-gates.md`)는 재독하지 않고, 세션에 없는 것만 읽는다. 2. Spec compliance 관점으로 Task DoD, Acceptance, TDD evidence, fresh verification evidence, scope/YAGNI 위반을 먼저 확인한다. 3. Code quality 관점으로 버그, 회귀 위험, 누락된 테스트, 유지보수성 문제, `agents/quality-gates.md` 위반을 찾는다. 4. findings를 심각도순으로 먼저 보고하고, 각 항목은 파일·라인 근거를 포함한다. diff --git a/.agents/skills/harness-sync/SKILL.md b/.agents/skills/harness-sync/SKILL.md index 75ed547..65f182f 100644 --- a/.agents/skills/harness-sync/SKILL.md +++ b/.agents/skills/harness-sync/SKILL.md @@ -9,7 +9,7 @@ description: tasks/index.json을 검증하고 Plans.md snapshot을 재생성한 ## 절차 -1. `AGENTS.md`, `CLAUDE.md`, `tasks/index.json`, `Plans.md`를 읽는다. +1. 이미 세션에 로드된 규칙 문서(`AGENTS.md`, `CLAUDE.md`)는 재독하지 않는다. `tasks/index.json`과 `Plans.md`는 직접 읽지 않는다 — 검증과 재생성은 아래 스크립트가 수행한다. 2. `python3 scripts/validate_tasks.py`를 실행한다. 3. 검증이 통과하면 `python3 scripts/sync_plans.py`를 실행한다. 4. 다시 `python3 scripts/sync_plans.py --check`로 동기화 여부를 확인한다. diff --git a/.agents/skills/harness-work/SKILL.md b/.agents/skills/harness-work/SKILL.md index 937f97c..0a75e7c 100644 --- a/.agents/skills/harness-work/SKILL.md +++ b/.agents/skills/harness-work/SKILL.md @@ -9,11 +9,11 @@ Codex에서 Claude Code `/harness-work`에 해당하는 절차를 직접 수행 ## 절차 -1. `AGENTS.md`, `CLAUDE.md`, `agents/quality-gates.md`, `tasks/index.json`, `Plans.md`, 최근 `.harness/LESSONS.md`를 읽는다. 진행 중인 Task가 있으면 `.harness/tasks//STATE.md`도 읽는다. -2. 수행할 `todo` Task 하나를 고른다. 사용자가 지정한 Task가 있으면 그 Task를 우선한다. -3. 구현 전 `agents/task-decomposer.md`의 세분화 기준과 `agents/quality-gates.md`의 scope/YAGNI 체크를 확인한다. +1. 최소 컨텍스트만 로드한다. 이미 세션에 로드된 규칙 문서(`CLAUDE.md`, `AGENTS.md`, `agents/quality-gates.md`)는 다시 읽지 않는다. Claude Code에서는 `CLAUDE.md`가 자동 로드되고 `AGENTS.md`는 Codex 세션 전용이다. `agents/quality-gates.md`는 루프당 1회만 읽는다. `Plans.md`는 생성물이므로 읽지 않는다(쓰기 전용). `.harness/LESSONS.md`는 전체가 아니라 최근 5개 항목만 부분 읽기한다. 진행 중인 Task가 있으면 `.harness/tasks//STATE.md`도 읽는다. +2. 수행할 `todo` Task 하나를 고른다. `tasks/index.json`을 전체 Read 하지 않는다 — `python3 scripts/report_tasks.py`로 WIP/next TODO 요약을 보고 고른 뒤, 선택한 Task의 상세(dod/acceptance/depends)는 `grep -n -A12 '"id": ""' tasks/index.json`으로 해당 블록만 읽는다. 사용자가 지정한 Task가 있으면 그 Task를 우선한다. +3. 구현 전 1차 게이트로 DoD/Acceptance 존재, 단일 관심사, 1 PR 이내 규모를 확인하고, `agents/quality-gates.md`의 scope/YAGNI 체크를 적용한다. 미달이 의심될 때만 `agents/task-decomposer.md` 전체를 읽어 세분화 기준으로 판정한다. 4. 기준 미달이면 구현하지 말고 `$harness-plan` 절차로 하위 Task proposal을 만든다. -5. 기준 통과 시 `.harness/tasks//STATE.md`를 갱신하고 구현한다. Task 디렉토리가 없으면 루트 `.harness/*.md` 템플릿을 복사해 만든다. +5. 기준 통과 시 구현 전에 반드시 대상 Task 전용 브랜치로 이동한다. `git branch --show-current`로 현재 브랜치를 확인하고, main/master이거나 다른 Task의 브랜치이면 `$branch-checkout` 절차로 `task/{task-id}-{short-slug}` 브랜치를 새로 만들거나 기존 Task 브랜치로 전환한다. main/master에서 직접 구현하지 않는다. 이미 main에 커밋하지 않은 작업이 쌓여 있으면 `$rescue-from-main` 절차로 옮긴다. 그 다음 `.harness/tasks//STATE.md`를 갱신하고 구현한다. Task 디렉토리가 없으면 루트 템플릿 중 `STATE.md`, `LOG.md`, `RUN_REPORT.md` 3종만 복사해 만든다. `HANDOFF.md`, `TASKS.md`, `CHECKPOINTS.md`는 실제로 필요해질 때만 추가한다. 6. 작업 중 범위가 커지면 중단하고 `agents/quality-gates.md`의 split 조건과 task-decomposer 기준으로 재분해한다. 7. 기능, 버그 수정, 동작 변경은 구현 전 failing test 또는 failing Acceptance를 먼저 확인한다. 문서, 설정, 생성 코드, throwaway prototype은 TDD 예외 사유를 기록한다. 8. 구현 후 `agents/test-agent.md` 절차대로 해당 Task Acceptance 명령과 관련 테스트 스위트를 fresh verification으로 실행한다. @@ -22,6 +22,7 @@ Codex에서 Claude Code `/harness-work`에 해당하는 절차를 직접 수행 ## 완료 기준 +- 구현 커밋이 대상 Task 전용 브랜치에 있어야 한다. main/master 직접 커밋은 완료로 인정하지 않는다. - Acceptance와 관련 테스트가 fresh verification으로 통과해야 한다. - TDD evidence 또는 명시적 예외 사유가 있어야 한다. - `.harness/tasks//RUN_REPORT.md`에 변경 요약, 주요 결정 근거, diff --git a/.claude/commands/harness-plan.md b/.claude/commands/harness-plan.md new file mode 100644 index 0000000..1df9a89 --- /dev/null +++ b/.claude/commands/harness-plan.md @@ -0,0 +1,12 @@ +--- +description: PRD·기획 문서를 Task proposal로 분해하고 검증 후 tasks/index.json에 반영한다. +--- + +# /harness-plan + +절차 원본은 `.agents/skills/harness-plan/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-plan/SKILL.md`를 읽고 같은 절차를 따른다. +2. proposal 검증(`validate_task_proposal.py`) 통과 전에는 `tasks/index.json`을 수정하지 않는다. +3. `Plans.md`는 직접 편집하지 않는다 — `sync_plans.py`로만 재생성한다. +4. 인자: `$ARGUMENTS` (기획 문서 경로 또는 분해 대상 설명) diff --git a/.claude/commands/harness-progress.md b/.claude/commands/harness-progress.md new file mode 100644 index 0000000..5191800 --- /dev/null +++ b/.claude/commands/harness-progress.md @@ -0,0 +1,13 @@ +--- +description: tasks/index.json 기준으로 진행 상황을 읽기 전용 요약한다. +allowed-tools: Bash(python3 scripts/report_tasks.py:*), Bash(python3 scripts/sync_plans.py --check:*), Bash(grep:*), Read +--- + +# /harness-progress + +절차 원본은 `.agents/skills/harness-progress/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-progress/SKILL.md`를 읽고 같은 절차를 따른다. +2. `python3 scripts/report_tasks.py`로 요약한다. `tasks/index.json` 전체를 Read 하지 않는다. +3. Task 상태를 바꾸지 않고, 요청 없이 `Plans.md`를 재생성하지 않는다. +4. 인자: `$ARGUMENTS` diff --git a/.claude/commands/harness-review.md b/.claude/commands/harness-review.md new file mode 100644 index 0000000..4add3fc --- /dev/null +++ b/.claude/commands/harness-review.md @@ -0,0 +1,13 @@ +--- +description: 현재 diff를 Task, CLAUDE.md 규칙, Acceptance evidence 기준으로 코드 리뷰한다. +allowed-tools: Bash(git diff:*), Bash(git status:*), Bash(git log:*), Bash(grep:*), Bash(python3 scripts/report_tasks.py:*), Read, Grep, Glob +--- + +# /harness-review + +절차 원본은 `.agents/skills/harness-review/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-review/SKILL.md`를 읽고 같은 절차를 따른다. +2. 이미 세션에 로드된 규칙 문서는 재독하지 않는다. 대상 Task 상세, Acceptance evidence, 현재 diff만 새로 읽는다. +3. 리뷰 중 직접 수정하지 않는다. 판정은 `APPROVE` / `REQUEST_CHANGES` 두 축(Spec compliance, Code quality) 기준. +4. 인자: `$ARGUMENTS` (대상 Task ID) diff --git a/.claude/commands/harness-sync.md b/.claude/commands/harness-sync.md new file mode 100644 index 0000000..e2b03e9 --- /dev/null +++ b/.claude/commands/harness-sync.md @@ -0,0 +1,13 @@ +--- +description: tasks/index.json을 검증하고 Plans.md snapshot을 재생성한다. +allowed-tools: Bash(python3 scripts/validate_tasks.py:*), Bash(python3 scripts/sync_plans.py:*), Read +--- + +# /harness-sync + +절차 원본은 `.agents/skills/harness-sync/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-sync/SKILL.md`를 읽고 같은 절차를 따른다. +2. `validate_tasks.py` 통과 후에만 `sync_plans.py`를 실행하고, `--check`로 동기화를 확인한다. +3. `Plans.md`는 생성물이다 — 직접 편집하지 않는다. +4. 인자: `$ARGUMENTS` diff --git a/.claude/commands/harness-work.md b/.claude/commands/harness-work.md new file mode 100644 index 0000000..3c6c175 --- /dev/null +++ b/.claude/commands/harness-work.md @@ -0,0 +1,13 @@ +--- +description: todo Task 하나를 선택해 세분화 게이트 확인 후 구현, Acceptance, 테스트, 리뷰까지 진행한다. +--- + +# /harness-work + +절차 원본은 `.agents/skills/harness-work/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-work/SKILL.md`를 읽고 같은 절차를 따른다. +2. 최소 컨텍스트 원칙을 지킨다: `tasks/index.json` 전체 Read 금지 (`report_tasks.py` 요약 + Task grep 블록), `Plans.md` 읽기 금지, 이미 로드된 규칙 문서 재독 금지. +3. 구현 전 반드시 Task 전용 브랜치로 이동한다. main/master이면 `/branch-checkout`으로 `task/{task-id}-{short-slug}` 브랜치를 만든다. main/master에서 직접 구현하지 않는다. +4. 완료 기준(Task 브랜치 커밋, fresh verification, TDD evidence, RUN_REPORT 기록)은 SKILL.md의 완료 기준을 따른다. +5. 인자: `$ARGUMENTS` (Task ID 지정 시 해당 Task 우선) diff --git a/.claude/commands/harness-yagni-trimmer.md b/.claude/commands/harness-yagni-trimmer.md new file mode 100644 index 0000000..4575089 --- /dev/null +++ b/.claude/commands/harness-yagni-trimmer.md @@ -0,0 +1,12 @@ +--- +description: harness/template 구조를 solo-builder 기준으로 점검하고 과한 복잡도를 줄인다. +--- + +# /harness-yagni-trimmer + +절차 원본은 `.agents/skills/harness-yagni-trimmer/SKILL.md`다. 이 command는 Claude Code 호출용 wrapper다. + +1. `.agents/skills/harness-yagni-trimmer/SKILL.md`를 읽고 같은 절차를 따른다. +2. `agents/quality-gates.md`의 YAGNI 기준을 적용한다. +3. 제거 제안은 근거(사용처 없음, 중복, 미참조)를 파일 경로와 함께 제시한다. +4. 인자: `$ARGUMENTS` diff --git a/.gitignore b/.gitignore index c16b565..5b62469 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,7 @@ docs/.pdca-status.json # harness sync 산출물 (harness.toml → 자동 생성 — 커밋 금지) .claude-plugin/ + +# Python 테스트 부산물 +__pycache__/ +*.pyc diff --git a/.harness/CHECKPOINTS.md b/.harness/CHECKPOINTS.md index b3b894b..4638446 100644 --- a/.harness/CHECKPOINTS.md +++ b/.harness/CHECKPOINTS.md @@ -1,7 +1,7 @@ # CHECKPOINTS.md — Task 완료 지점 템플릿 > 이 루트 파일은 실제 checkpoint 기록이 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//CHECKPOINTS.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//CHECKPOINTS.md`로 복사해서 사용한다. | 일시 | Task | 내용 | 커밋 | 검증 | |------|------|------|------|------| diff --git a/.harness/CONTEXT_INDEX.md b/.harness/CONTEXT_INDEX.md index 7e95e6a..e5f07eb 100644 --- a/.harness/CONTEXT_INDEX.md +++ b/.harness/CONTEXT_INDEX.md @@ -4,12 +4,13 @@ ## 세션 재개 읽는 순서 -1. `tasks/index.json`에서 `wip` Task 또는 사용자가 지정한 Task를 확인한다. +1. `python3 scripts/report_tasks.py`로 `wip` Task 또는 사용자가 지정한 Task를 확인한다. + Task 상세는 `grep -n -A12 '"id": ""' tasks/index.json`으로 해당 블록만 읽는다. 2. 해당 Task의 `.harness/tasks//STATE.md`를 읽는다. 3. 있으면 `.harness/tasks//RUN_REPORT.md`를 읽는다. -4. `.harness/LESSONS.md` 최근 항목을 읽는다. -5. `Plans.md`를 확인한다. -6. 아래 표에서 필요한 추가 문서만 고른다. +4. `.harness/LESSONS.md` 최근 5개 항목만 읽는다. +5. 아래 표에서 필요한 추가 문서만 고른다. `Plans.md`는 사람용 snapshot이므로 + 에이전트는 읽지 않는다. ## Task별 맥락 @@ -19,10 +20,11 @@ - `.harness/tasks/4.17-review-verdict/`: review verdict 이원화 evidence - `.harness/tasks/4.18-git-helper-safety/`: git helper 안전 흐름 evidence - `.harness/tasks/4.19-skeleton-evidence-template/`: skeleton RUN_REPORT 갱신 evidence +- `.harness/tasks/context-budget-patch/`: harness-work 루프 컨텍스트 로드 최소화 evidence - `.harness/tasks//STATE.md`: 현재 스냅샷 - `.harness/tasks//LOG.md`: 작업·에러 원문 - `.harness/tasks//RUN_REPORT.md`: 변경·결정·검증 요약 -- `.harness/tasks//{HANDOFF,TASKS,CHECKPOINTS}.md`: 필요할 때만 읽는 보조 기록 +- `.harness/tasks//{HANDOFF,TASKS,CHECKPOINTS}.md`: 기본 복사 대상이 아니며, 필요할 때만 생성·읽는 보조 기록 - `.harness/tasks//tasks.index.snapshot.json`: 시작 시점 비교가 필요할 때만 읽는 참고본 ## 기본 파일 diff --git a/.harness/HANDOFF.md b/.harness/HANDOFF.md index 888a81a..b425c33 100644 --- a/.harness/HANDOFF.md +++ b/.harness/HANDOFF.md @@ -1,7 +1,7 @@ # HANDOFF.md — Task 인수인계 템플릿 > 이 루트 파일은 실제 인수인계가 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//HANDOFF.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//HANDOFF.md`로 복사해서 사용한다. ## 다음 세션이 먼저 읽을 최소 파일 diff --git a/.harness/LESSONS.md b/.harness/LESSONS.md index e53ea3e..43daa0e 100644 --- a/.harness/LESSONS.md +++ b/.harness/LESSONS.md @@ -1,8 +1,10 @@ # LESSONS.md — 재발 방지 기록 > 에러·실수를 해결한 뒤 "다음에 같은 실수를 안 하려면"을 한 항목으로 남긴다. -> 최신 항목이 위. 세션 재개 시 최근 5개를 먼저 읽는다. +> 최신 항목이 위. 세션 재개 시 최근 5개 항목만 읽는다 (전체 읽기 금지). > 항상 지켜야 할 규칙으로 승격되면 CLAUDE.md에도 반영하고 여기 표시한다. +> 최대 8개 항목만 유지한다. 초과하면 가장 오래된 항목을 CLAUDE.md 규칙으로 +> 승격하거나 삭제해서 파일을 rewrite한다 — append로 무한히 키우지 않는다. ## 2026-07-07 — README 환경 구성 절차 팩트 체크 diff --git a/.harness/TASKS.md b/.harness/TASKS.md index fdecc78..ae48fc0 100644 --- a/.harness/TASKS.md +++ b/.harness/TASKS.md @@ -1,7 +1,7 @@ # TASKS.md — Task 내부 체크리스트 템플릿 > 이 루트 파일은 실제 체크리스트가 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//TASKS.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//TASKS.md`로 복사해서 사용한다. ## 현재 Task: [id] [title] diff --git a/.harness/tasks/context-budget-patch/LOG.md b/.harness/tasks/context-budget-patch/LOG.md new file mode 100644 index 0000000..cd1918f --- /dev/null +++ b/.harness/tasks/context-budget-patch/LOG.md @@ -0,0 +1,14 @@ +# LOG.md — Task 작업·에러 로그 + +## 2026-07-09 + +- Context Budget Audit 수행: harness-work 루프가 step 1에서 ~62.9KB + (AGENTS 5.6 + CLAUDE 7.3 + quality-gates 4.0 + index.json 22.1 + Plans.md 15.8 + + LESSONS 7.5), step 3에서 task-decomposer 10.9KB, step 10 리뷰에서 규칙 문서 + 16.9KB를 재독 — 루프당 규칙/상태 문서 약 94KB 로드로 측정. +- 패치 적용: harness-work/review/plan/progress/sync SKILL 읽기 지시 축소, + CLAUDE.md·AGENTS.md·README.md·CONTEXT_INDEX(루트+skeleton) 재개 순서 갱신, + LESSONS.md(루트+skeleton) cap 8개 rewrite 규칙, HANDOFF/TASKS/CHECKPOINTS + 템플릿 헤더를 "필요 시 복사"로 정정. +- 에러 1건: 검증 중 `python -m pytest` 실패 (No module named pytest) — + `pip install pytest` 후 18 passed. 환경 문제이며 코드 문제 아님. diff --git a/.harness/tasks/context-budget-patch/RUN_REPORT.md b/.harness/tasks/context-budget-patch/RUN_REPORT.md new file mode 100644 index 0000000..35beabb --- /dev/null +++ b/.harness/tasks/context-budget-patch/RUN_REPORT.md @@ -0,0 +1,48 @@ +# RUN_REPORT.md — 변경·결정·검증 요약 + +## 변경 요약 + +harness-work 루프의 토큰 소모를 줄이기 위해 스킬/규칙 문서의 "읽기 지시"를 +선택적 로드로 변경. 기능 동작(게이트·TDD·검증·리뷰 순서, 스크립트)은 불변. + +- Task 선택: `tasks/index.json` 전체 Read → `report_tasks.py` 요약 + + `grep -n -A12 '"id": ""'` 블록 읽기 +- `Plans.md`: 루프 읽기 목록 전부에서 제거 (사람용 생성물, 쓰기 전용) +- 규칙 문서(AGENTS/CLAUDE/quality-gates): 세션 내 재독 금지 (리뷰 단계 포함) +- `task-decomposer.md`: 1차 게이트 통과 시 로드 생략, 미달 의심 시만 전체 읽기 +- `LESSONS.md`: 최근 5개만 읽기 + 최대 8개 유지 rewrite 규칙 (append 누수 차단) +- Task 디렉토리: 템플릿 복사 6종 → 3종(STATE/LOG/RUN_REPORT) + +## 주요 결정 근거 + +- done Task 아카이브 분리는 sync_plans/plans-guard 계약 변경이 필요해 스코프 제외. +- `.harness/context/`·`index/` 신규 디렉토리는 기존 CONTEXT_INDEX/STATE/LESSONS가 + 같은 역할이므로 미도입 (문서 증식 금지). +- grep 블록 패턴은 LESSONS.md 2026-07-08 항목의 기존 검증 패턴 재사용, + depends 배열 다중 행 대비 `-A8` → `-A12`. + +## Evidence + +| 항목 | 명령 | 결과 | +|---|---|---| +| TDD | - | 예외: 문서/규칙 변경만, 런타임 코드·스크립트 무변경 (CLAUDE.md TDD 예외 조항) | +| 구조 검증 | `python3 scripts/validate_tasks.py` | PASS (47 tasks) | +| Sync 검증 | `python3 scripts/sync_plans.py --check` | PASS (Plans.md 미변경) | +| 테스트 스위트 | `python3 -m pytest tests/ -q` | PASS (18 passed) | +| grep 패턴 | `grep -n -A12 '"id": "4.19"' tasks/index.json` | 단일 블록 온전 출력 | + +## 루프 로드 Before/After (harness-work step 1~3 기준, 추정) + +- Before: AGENTS 5.6 + CLAUDE 7.3(재독) + quality-gates 4.0 + index.json 22.1 + + Plans.md 15.8 + LESSONS 7.5 + decomposer 10.9 = 약 73KB, 리뷰 재독 +16.9KB +- After: quality-gates 4.0 + report_tasks.py 출력(<1KB) + Task grep 블록(<0.5KB) + + LESSONS 최근 5개(~5KB 상한) + STATE.md(~0.6KB) = 약 10~11KB, 리뷰 재독 0 +- 약 85% 감소 (추정치, 토큰 실측 아님) + +## 남은 위험 / 후속 후보 + +- done Task가 index.json에 계속 누적 (현재 47개 전부 done) — 아카이브 분리는 + 후속 Task로 (sync_plans/plans-guard 계약 동반 변경 필요). +- `.harness/shared/planning/runs/` retention 미설정 — 현재 1KB 미만, 누적 관찰 후 판단. +- grep -A12는 Task 객체가 12행을 넘으면(긴 depends) 잘릴 수 있음 — 잘리면 -A 값을 + 늘려 재실행하면 됨. diff --git a/.harness/tasks/context-budget-patch/STATE.md b/.harness/tasks/context-budget-patch/STATE.md new file mode 100644 index 0000000..e092246 --- /dev/null +++ b/.harness/tasks/context-budget-patch/STATE.md @@ -0,0 +1,30 @@ +# STATE.md — Task 상태 스냅샷 + +## 현재 목표 + +harness-work 루프의 매 실행 컨텍스트 로드를 최소화한다 (Context Budget Audit 패치). + +## 진행 중인 Task + +- Task ID: `context-budget-patch` (사용자 직접 요청 — tasks/index.json 미등록) +- 상태: `done` +- 기준 문서: Context Budget Audit 보고서 (세션 산출물) + +## 마지막 검증 결과 + +- `python3 scripts/validate_tasks.py` PASS (47 tasks) +- `python3 scripts/sync_plans.py --check` PASS (Plans.md 미변경) +- `python3 -m pytest tests/ -q` PASS (18 passed) +- `grep -n -A12 '"id": "4.19"' tasks/index.json` — 단일 Task 블록(dod/acceptance/depends/status) 온전 출력 확인 + +## 차단 요소 + +- 없음 + +## 마지막 커밋 + +- (커밋 예정: harness-work 루프 컨텍스트 로드 최소화) + +## 최종 갱신 + +- 2026-07-09 diff --git a/AGENTS.md b/AGENTS.md index 254ceb8..8d02c61 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,19 +8,23 @@ project rules, task sources, and verification gates that Claude Code uses. At the start of a session, read these files before planning or editing: 1. `CLAUDE.md` -2. `harness.toml` -3. `tasks/index.json` -4. `Plans.md` -5. `BLUEPRINT.md` when architecture or command provenance matters +2. task state via `python3 scripts/report_tasks.py`; for one task's detail, read + only its block with `grep -n -A12 '"id": ""' tasks/index.json` — + do not read `tasks/index.json` in full +3. `harness.toml` only when configuration needs checking +4. `BLUEPRINT.md` when architecture or command provenance matters + +Do not read `Plans.md` — it is a generated snapshot for humans, write-only for +agents. On resumed work, follow the recovery order in `CLAUDE.md`: -1. `tasks/index.json` to identify the `wip` or user-specified Task +1. `report_tasks.py` summary and the target task's grep block to identify the + `wip` or user-specified Task 2. `.harness/tasks//STATE.md` 3. `.harness/tasks//RUN_REPORT.md` if it exists -4. latest entries in `.harness/LESSONS.md` -5. `Plans.md` -6. only the extra files listed in `.harness/CONTEXT_INDEX.md` that are needed +4. only the 5 most recent entries in `.harness/LESSONS.md` +5. only the extra files listed in `.harness/CONTEXT_INDEX.md` that are needed ## Source Of Truth diff --git a/BLUEPRINT.md b/BLUEPRINT.md index 6577c88..3a0aab7 100644 --- a/BLUEPRINT.md +++ b/BLUEPRINT.md @@ -68,12 +68,13 @@ ponytail/caveman의 durable 원칙은 Codex에서 별도 plugin으로 실행된 1. `todo` Task 선택 2. `agents/task-decomposer.md` 세분화 게이트 확인 3. `agents/quality-gates.md` scope/YAGNI 확인 -4. `.harness/tasks//STATE.md` 갱신 -5. TDD red evidence 확인 또는 예외 사유 기록 -6. 구현 -7. Acceptance와 관련 테스트를 fresh verification으로 실행 -8. 리뷰 -9. 통과 시 `tasks/index.json` 상태 변경과 `Plans.md` 재생성 +4. Task 전용 브랜치(`task/{task-id}-{short-slug}`) 생성·전환 — main/master 직접 구현 금지 +5. `.harness/tasks//STATE.md` 갱신 +6. TDD red evidence 확인 또는 예외 사유 기록 +7. 구현 +8. Acceptance와 관련 테스트를 fresh verification으로 실행 +9. 리뷰 +10. 통과 시 `tasks/index.json` 상태 변경과 `Plans.md` 재생성 Actions는 Task 상태를 쓰지 않고 PR 검증만 수행한다. diff --git a/CLAUDE.md b/CLAUDE.md index c8e28fe..b132856 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,11 +48,13 @@ Planning 로그의 최상위 `step`, `result`, `message`, `next_action`은 사 ## 상태 문서 규칙 - 터미널 세션은 언제든 끊길 수 있다고 가정한다. -- 작업 시작 전과 의미 있는 작업 단위 후 `.harness/tasks//STATE.md`를 갱신한다. +- 작업 시작 전과 의미 있는 작업 단위 후 `.harness/tasks//STATE.md`를 갱신한다. `STATE.md`는 append가 아니라 현재 스냅샷으로 rewrite한다. - Task 상태는 `tasks/index.json`만 믿는다. `.harness/tasks//`는 세션 맥락만 담는다. +- `tasks/index.json`은 전체를 읽지 않는다. 상태 요약은 `python3 scripts/report_tasks.py`, 특정 Task 상세는 `grep -n -A12 '"id": ""' tasks/index.json`으로 해당 블록만 읽는다. +- `Plans.md`는 생성물이다. 에이전트가 루프 중 읽지 않고, 사람에게 진행률을 보여줄 때만 참조한다. - 루트 `.harness/{STATE,HANDOFF,TASKS,LOG,CHECKPOINTS,RUN_REPORT}.md`는 새 Task용 템플릿이다. -- 새 Task 착수 시 루트 템플릿을 `.harness/tasks//`로 복사한다. 필요하면 `tasks.index.snapshot.json`도 저장한다. -- 세션 재개 읽기 순서: `tasks/index.json` -> `.harness/tasks//STATE.md` -> 있으면 `RUN_REPORT.md` -> `.harness/LESSONS.md` 최근 항목 -> `Plans.md` -> 필요한 파일만 `.harness/CONTEXT_INDEX.md`에서 선택. +- 새 Task 착수 시 루트 템플릿 중 `STATE.md`, `LOG.md`, `RUN_REPORT.md` 3종만 `.harness/tasks//`로 복사한다. `HANDOFF.md`, `TASKS.md`, `CHECKPOINTS.md`와 `tasks.index.snapshot.json`은 실제로 필요할 때만 추가한다. +- 세션 재개 읽기 순서: `report_tasks.py` 요약과 대상 Task grep 블록 -> `.harness/tasks//STATE.md` -> 있으면 `RUN_REPORT.md` -> `.harness/LESSONS.md` 최근 5개 항목만 -> 필요한 파일만 `.harness/CONTEXT_INDEX.md`에서 선택. - 에러는 Task `LOG.md`에 원문 기록한다. 반복 방지 규칙은 `.harness/LESSONS.md`에 남긴다. - 새 파일을 만들거나 파일 역할이 바뀌면 `.harness/CONTEXT_INDEX.md`를 갱신한다. - 요청이 전제한 파일이 없으면 임의 생성하지 말고 사용자에게 보고한다. @@ -72,8 +74,9 @@ Planning 로그의 최상위 `step`, `result`, `message`, `next_action`은 사 ## 구현 규칙 (세분화 게이트) +- `/harness-work` 구현은 반드시 대상 Task 전용 브랜치에서 한다. main/master에서 직접 구현하지 않는다. 브랜치가 없으면 `/branch-checkout`으로 `task/{task-id}-{short-slug}`를 새로 만들고, main에 이미 작업이 쌓였으면 `/rescue-from-main`으로 옮긴다. GitHub 연동 여부와 무관하게 적용한다. - 구현 전 `agents/quality-gates.md`를 scope/YAGNI gate로 적용한다. -- `/harness-work` 실행 전 대상 `todo` Task가 `agents/task-decomposer.md`의 세분화 기준을 통과했는지 확인한다. +- `/harness-work` 실행 전 대상 `todo` Task가 `agents/task-decomposer.md`의 세분화 기준을 통과했는지 확인한다. 1차 게이트는 DoD/Acceptance 존재, 단일 관심사, 1 PR 이내 규모 확인으로 하고, 미달이 의심될 때만 `agents/task-decomposer.md` 전체를 읽는다. - DoD/Acceptance 미기재, 뭉뚱그린 표현, 여러 관심사 혼재, 1 PR 초과 징후가 있으면 구현하지 않는다. `/harness-plan`으로 하위 Task proposal을 먼저 만든다. - 작업 중 범위가 커지면 멈추고 `agents/task-decomposer.md`와 `agents/quality-gates.md` 기준으로 재분해한다. - 기능, 버그 수정, 동작 변경은 TDD가 기본 완료 조건이다. 먼저 실패하는 테스트나 Acceptance evidence를 확인하고, 최소 구현 후 green을 확인해야 한다. diff --git a/README.md b/README.md index 6deabd8..7a8c311 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Claude Code의 ponytail/caveman plugin hook은 Codex에서 자동 실행되지 ```text AGENTS.md를 읽어줘. -tasks/index.json과 Plans.md 기준으로 현재 상태를 확인해줘. +python3 scripts/report_tasks.py로 현재 상태를 확인해줘. $harness-progress로 진행 상황을 요약해줘. ``` @@ -47,7 +47,8 @@ harness doctor ```text 먼저 CLAUDE.md를 읽어줘. -그다음 harness.toml, tasks/index.json, Plans.md, BLUEPRINT.md를 확인해줘. +그다음 python3 scripts/report_tasks.py로 Task 현황을 확인해줘. +harness.toml과 BLUEPRINT.md는 설정·구조 확인이 필요할 때만 읽어줘. 구현 전 agents/quality-gates.md와 agents/task-decomposer.md를 적용해줘. 구현 후 tasks/index.json의 Acceptance 명령과 관련 테스트를 실행해줘. ``` @@ -71,12 +72,11 @@ TDD는 기능, 버그 수정, 동작 변경의 기본 완료 조건이다. 문 재개 시 읽는 순서: -1. `tasks/index.json` +1. `python3 scripts/report_tasks.py` 요약과 대상 Task grep 블록 (`tasks/index.json` 전체 읽기 금지) 2. `.harness/tasks//STATE.md` 3. `.harness/tasks//RUN_REPORT.md`가 있으면 확인 -4. `.harness/LESSONS.md` 최근 항목 -5. `Plans.md` -6. 필요할 때만 `.harness/CONTEXT_INDEX.md`에서 추가 파일 선택 +4. `.harness/LESSONS.md` 최근 5개 항목만 +5. 필요할 때만 `.harness/CONTEXT_INDEX.md`에서 추가 파일 선택 (`Plans.md`는 사람용 snapshot — 에이전트는 읽지 않음) 루트 `.harness/{STATE,HANDOFF,TASKS,LOG,CHECKPOINTS,RUN_REPORT}.md`는 템플릿이다. 실제 작업 상태는 `.harness/tasks//` 아래에 둔다. diff --git a/templates/skeleton/.harness/CHECKPOINTS.md b/templates/skeleton/.harness/CHECKPOINTS.md index b3b894b..4638446 100644 --- a/templates/skeleton/.harness/CHECKPOINTS.md +++ b/templates/skeleton/.harness/CHECKPOINTS.md @@ -1,7 +1,7 @@ # CHECKPOINTS.md — Task 완료 지점 템플릿 > 이 루트 파일은 실제 checkpoint 기록이 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//CHECKPOINTS.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//CHECKPOINTS.md`로 복사해서 사용한다. | 일시 | Task | 내용 | 커밋 | 검증 | |------|------|------|------|------| diff --git a/templates/skeleton/.harness/CONTEXT_INDEX.md b/templates/skeleton/.harness/CONTEXT_INDEX.md index ac6f0f1..98e4db5 100644 --- a/templates/skeleton/.harness/CONTEXT_INDEX.md +++ b/templates/skeleton/.harness/CONTEXT_INDEX.md @@ -4,11 +4,12 @@ ## 세션 재개 읽는 순서 -1. `tasks/index.json`에서 `wip` Task 또는 사용자가 지정한 Task를 확인한다. +1. `python3 scripts/report_tasks.py`로 `wip` Task 또는 사용자가 지정한 Task를 확인한다. + Task 상세는 `grep -n -A12 '"id": ""' tasks/index.json`으로 해당 블록만 읽는다. 2. 해당 Task의 `.harness/tasks//STATE.md`를 읽는다. -3. 루트 `.harness/LESSONS.md` 최근 항목을 읽는다. -4. `Plans.md`를 읽어 사람이 보는 snapshot을 확인한다. -5. 이 파일에서 필요한 추가 문서만 고른다. +3. 루트 `.harness/LESSONS.md` 최근 5개 항목만 읽는다. +4. 이 파일에서 필요한 추가 문서만 고른다. `Plans.md`는 사람용 snapshot이므로 + 에이전트는 읽지 않는다. ## Task별 맥락 디렉토리 @@ -17,7 +18,7 @@ - `STATE.md`: 현재 스냅샷 - `LOG.md`: 작업·에러 원문 - `RUN_REPORT.md`: 변경·결정·검증 요약 -- `HANDOFF.md`, `TASKS.md`, `CHECKPOINTS.md`: 필요할 때만 읽는 보조 기록 +- `HANDOFF.md`, `TASKS.md`, `CHECKPOINTS.md`: 기본 복사 대상이 아니며, 필요할 때만 생성·읽는 보조 기록 - `tasks.index.snapshot.json`: 시작 시점 비교가 필요할 때만 읽는 참고본 ## 루트 템플릿과 전역 파일 diff --git a/templates/skeleton/.harness/HANDOFF.md b/templates/skeleton/.harness/HANDOFF.md index 888a81a..b425c33 100644 --- a/templates/skeleton/.harness/HANDOFF.md +++ b/templates/skeleton/.harness/HANDOFF.md @@ -1,7 +1,7 @@ # HANDOFF.md — Task 인수인계 템플릿 > 이 루트 파일은 실제 인수인계가 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//HANDOFF.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//HANDOFF.md`로 복사해서 사용한다. ## 다음 세션이 먼저 읽을 최소 파일 diff --git a/templates/skeleton/.harness/LESSONS.md b/templates/skeleton/.harness/LESSONS.md index 225372c..6f583e0 100644 --- a/templates/skeleton/.harness/LESSONS.md +++ b/templates/skeleton/.harness/LESSONS.md @@ -1,7 +1,9 @@ # LESSONS.md — 재발 방지 기록 > 에러·실수를 해결한 뒤 "다음에 같은 실수를 안 하려면"을 한 항목으로 남긴다. -> 최신 항목이 위. 세션 재개 시 최근 5개를 먼저 읽는다. +> 최신 항목이 위. 세션 재개 시 최근 5개 항목만 읽는다 (전체 읽기 금지). > 항상 지켜야 할 규칙으로 승격되면 CLAUDE.md에도 반영하고 여기 표시한다. +> 최대 8개 항목만 유지한다. 초과하면 가장 오래된 항목을 CLAUDE.md 규칙으로 +> 승격하거나 삭제해서 파일을 rewrite한다 — append로 무한히 키우지 않는다. (아직 기록 없음 — 초기 상태) diff --git a/templates/skeleton/.harness/TASKS.md b/templates/skeleton/.harness/TASKS.md index fdecc78..ae48fc0 100644 --- a/templates/skeleton/.harness/TASKS.md +++ b/templates/skeleton/.harness/TASKS.md @@ -1,7 +1,7 @@ # TASKS.md — Task 내부 체크리스트 템플릿 > 이 루트 파일은 실제 체크리스트가 아니라 템플릿이다. -> 새 Task를 시작할 때 `.harness/tasks//TASKS.md`로 복사해서 사용한다. +> 기본 복사 대상이 아니다. 실제로 필요할 때만 `.harness/tasks//TASKS.md`로 복사해서 사용한다. ## 현재 Task: [id] [title]