--- name: code-to-docs description: 문서 없이 만들어진 코드베이스(바이브 코딩 프로젝트, 인수받은 레거시, README 한 줄뿐인 앱)를 읽고 "이렇게 만들자"가 아니라 "지금 이렇게 되어 있다"를 적은 as-is 문서 셋 — docs/PRD.md·docs/TRD.md·docs/ARCHITECTURE/ — 를 만든 뒤, plan-generator(phase-01 현행 고정 — as-is 동작을 붙잡는 테스트 태스크만) → harness-setup → loop-setup 을 원래 순서대로 불러 그 프로젝트를 하네스-루프 풀스택 플러그인으로 만든 프로젝트와 같은 상태로 올린다. 사용자가 "이 코드 문서화해줘", "문서 없는 프로젝트인데 이 플러그인에 올리고 싶어", "바이브 코딩으로 만든 건데 정리해줘", "기존 코드 읽고 PRD/TRD 뽑아줘", "레거시 코드에 테스트부터 붙이자", "이 저장소 현재 상태를 문서로 남겨줘"라고 하거나, docs/PRD.md 가 없는 코드베이스에서 리팩토링·기능 추가·버그 수정·하네스 세팅을 시작하려 할 때 반드시 이 스킬을 먼저 사용한다. 코드는 있는데 PRD·TRD·아키텍처·플랜·하네스·LOOP.md 가 하나도 없는 상태에서 refactor-plan·feature-add·bug-fix·harness-setup 을 부르려 하면 그 대신 이 스킬이 먼저다. 이미 docs/PRD.md 가 있는 프로젝트에는 쓰지 않는다 — 그건 feature-add·refactor-plan 의 몫이다. --- # 코드 → 문서 (Layer 6 · 진입) ## 이 스킬의 목적 Layer 0~5 는 "문서 → 코드" 한 방향이다. 그런데 실제로 손에 들어오는 프로젝트의 상당수는 반대다 — 코드는 돌아가는데 무엇을 만들었는지 적힌 문서가 없다. 이 플러그인의 모든 스킬은 **앞 레이어의 파일**을 읽고 움직이므로, 문서가 없으면 refactor-plan 도 feature-add 도 bug-fix 도 설 자리가 없다. 이 스킬은 그 코드베이스를 플러그인에 **올리는 진입로**다. 코드를 읽어 세 문서를 쓰고, 기존 스킬 셋을 불러 플랜·하네스·루프를 세운다. 끝나면 그 프로젝트는 처음부터 이 플러그인으로 만든 완료 프로젝트와 같은 상태가 된다. ``` 문서 없는 코드 → docs/PRD.md · TRD.md · ARCHITECTURE/ (as-is — 지금 이렇게 되어 있다) ← 이 스킬이 직접 쓴다 → plan_setup/ phase-01-baseline (as-is 동작을 붙잡는 테스트 태스크만) ← plan-generator 를 부른다 → harness_setup/ (게이트 넷 + local-dev) ← harness-setup 을 부른다 → loop_setup/LOOP.md ← loop-setup 을 부른다 → 개발 루프 한 번 → phase-01 completed → 게이트 활성 ← 사용자가 돌린다 ``` **왜 문서만 만들고 끝내지 않는가.** 문서 없는 코드를 고칠 때 가장 위험한 것은 **무엇이 깨졌는지 모르는 것**이다. 리팩토링이나 기능 추가 전에 지금 동작을 붙잡는 게이트가 실제로 활성이어야 하고, 게이트는 플랜의 태스크 ID 를 활성 시점으로 갖는다(Layer 4). 그래서 하네스는 플랜 없이는 서지 않고, 플랜은 문서 없이는 서지 않는다. 셋을 한 번에 세워야 진입이 끝난다. ### 여기서 하는 일과 하지 않는 일 | 하지 않는 것 | 어디서 하는가 | |---|---| | 코드를 고치는 것 — 버그처럼 보여도, 중복이 눈에 띄어도 | 버그는 `bug-fix`, 구조는 `refactor-plan`. 둘 다 phase-01 완료 뒤 | | "이렇게 되어야 한다"를 적는 것 — 목표 요구사항, 바꿀 기술 결정, 더 나은 구조 | `feature-add`·`refactor-plan` 이 후미 절로 더한다 | | 플랜·하네스·루프의 내용을 정하는 것 | `plan-generator`·`harness-setup`·`loop-setup`. 이 스킬은 **부를 때 넘길 지시**만 정한다 | | 개발 루프를 도는 것 (phase-01 완료) | 사용자가 `LOOP.md` 대로 한 번 돌린다 | | 이미 문서가 있는 프로젝트의 문서 갱신 | `feature-add`·`refactor-plan`. 이 스킬은 `docs/PRD.md` 가 없을 때만 들어간다 | ### as-is 문서는 합의문이 아니다 Layer 1·2 의 문서는 "무엇을 만들 것인가"에 대한 **합의**이고, 뒤 스킬은 거기 적힌 것을 전부 "합의된 목표"로 읽는다. 이 스킬이 만드는 문서는 형식은 같지만 **뜻이 다르다** — 코드에서 역으로 적은 **현재 상태**다. 그래서 세 가지를 지킨다. - **코드에 없는 것은 적지 않는다.** 화면·라우트에서 기능 요구사항을, 패키지·설정 파일에서 기술 결정을, 폴더·모듈 구조에서 설계 단위를 뽑는다. 그럴듯한 목표·이유·사용자를 채워 넣는 순간 뒤 스킬이 그것을 합의로 읽고, 실제로 아무도 원한 적 없는 방향으로 태스크가 생긴다 - **코드만으로 모르는 것은 미결(OQ)로 남긴다.** 왜 이렇게 했는가, 누가 쓰는가, 이 동작이 의도인가 — 종류는 대개 `확인`이다(사용자도 모를 수 있고, 코드 작성자나 사용 현장에서 확인해야 한다). 객관식으로 묻지 않는다 — 모르는 것을 찍게 만들면 그 답이 합의로 박힌다 - **문서 머리에 as-is 표기를 둔다.** `> 코드에서 역으로 작성 (as-is, <날짜>)` 한 줄. 뒤 스킬이 "합의된 목표"와 "현재 상태"를 구별하지 못하면 refactor-plan 의 고칠 목록이 전부 결함으로 읽히고, feature-add 가 있는 기능을 다시 만든다 --- ## 1단계. 진입 조건과 코드 훑기 ### 들어가도 되는가 먼저 프로젝트 루트를 본다. **`docs/PRD.md` 가 있으면 들어가지 않는다.** 이미 문서가 있는 프로젝트다 — 고치거나 더할 것은 `feature-add`·`refactor-plan` 의 일이고, as-is 문서를 그 위에 덮어쓰면 합의된 요구사항이 현재 상태로 바뀐다. 사용자에게 그 사실과 갈 곳을 알리고 멈춘다. `plan_setup/`·`harness_setup/`·`loop_setup/` 중 하나라도 있으면 마찬가지다 — 문서만 지워진 프로젝트일 수 있으니 무엇이 남아 있는지 보고하고 사용자가 정하게 한다. `README.md`·주석·설계 메모처럼 **사양이 아닌 문서**는 막지 않는다. 그것은 입력이다 — 다만 코드와 다르면 코드가 이긴다(README 는 대개 낡았다). 어긋난 곳은 OQ(`확인`)로 남긴다: "README 는 X 라 하는데 코드는 Y 다. 어느 쪽이 현재 의도인가". **git 저장소인지 확인한다.** 뒤에서 부를 `loop-setup` 은 기본 브랜치 이름을 알아내야 하고, 루프는 커밋과 워크트리 위에서 돈다. 저장소가 아니면 `git init` 하고 지금 상태를 첫 커밋으로 남기자고 제안한다 — 이 커밋이 "as-is 기준점"이 되어, phase-01 의 테스트가 붙잡은 동작이 어느 시점의 것인지 남는다. 저장소인데 미커밋 변경이 있으면 그것도 알린다. 사용자가 정하기 전에는 커밋하지 않는다. ### 코드를 어떤 순서로 읽는가 문서가 없으니 코드가 유일한 근거다. 전체를 한 번에 읽으려 들지 말고 **여섯 자리를 순서대로** 본다. 각 자리에서 나오는 것이 다르다. | 순서 | 어디를 보나 | 무엇이 나오나 | 어느 문서로 가나 | |---|---|---|---| | ① 진입점 | `package.json`·`pyproject`·`go.mod` 의 스크립트, `main`·`server`·`app` 파일, Dockerfile·compose | 언어·프레임워크·버전, 실행 방법, 포트 | TRD 3절·9.3절 | | ② 라우트·핸들러 | 라우터 파일, 컨트롤러, API 정의, CLI 명령 | 기능 하나하나(엔드포인트·입력·응답·오류 분기) | PRD 4절 FR | | ③ 화면 | 페이지·컴포넌트·템플릿, 화면에서 부르는 API | 사용자가 하는 일의 단위, 화면 흐름 | PRD 2·3절, ARCHITECTURE 핵심 흐름 | | ④ 데이터 | 스키마·마이그레이션·모델·저장 파일, 저장소 접근 코드 | 개체·필드·관계, 저장 방식 | TRD 4절, ARCHITECTURE database | | ⑤ 인증·설정 | 로그인·세션·쿠키·토큰 코드, 환경변수, 설정 파일 | 인증 모델, 권한 검사가 있는 곳과 **없는 곳** | TRD 6·7절, ARCHITECTURE auth | | ⑥ 테스트·도구 | 테스트 디렉터리, lint·format 설정, CI 파일 | 테스트 개수(대개 0), 도구 유무 | TRD 8절 | 읽으면서 **관찰 목록 넷**을 만든다. 이후 모든 문서는 이 넷에서만 나온다. 1. **기능 관찰** — 라우트·화면 하나마다 "입력 → 동작 → 응답, 오류 분기". 코드의 `if` 하나가 수용 기준 한 줄이다 2. **기술 관찰** — 패키지·버전·설정값. 파일 이름과 줄을 함께 적는다(근거 열에 쓴다) 3. **구조 관찰** — 폴더·모듈·계층과 실제 의존 방향. "누가 누구를 import 하는가"를 있는 그대로 4. **모르는 것** — 코드로는 답이 안 나오는 질문. 왜, 누가, 의도인가. 여기서 OQ 가 나온다 **버그로 보이는 것도 기능 관찰에 그대로 적는다.** 예를 들어 필터가 항상 빈 결과를 내거나 권한 검사가 빠져 있어도, 그것이 지금 동작이다. 고치지 않고, 판단도 넣지 않고("버그"라고 쓰지 않고), 관찰만 적은 뒤 **"이것이 의도인가"를 OQ(`확인`)로** 올린다. 이유가 있다 — 뒤에서 `bug-fix` 가 그것을 고칠 때 "무엇이 바뀌었는지"를 아는 유일한 방법이 지금 동작을 붙잡은 테스트이고, 그 테스트는 이 문서의 수용 기준에서 나온다. 이 스킬이 슬쩍 고쳐 두면 고친 기록도, 회귀 검사도, 분리 검증도 없이 코드가 바뀐다. **리팩토링 재료도 문서에 넣지 않는다.** 같은 함수가 두 파일에 있다든지, 계층을 건너뛰어 저장소를 직접 만진다든지 하는 것은 구조 관찰이지 설계가 아니다. ARCHITECTURE 에는 "지금 이렇게 되어 있다"만 적고, 눈에 띈 것은 **6단계 보고의 "문서에 일부러 넣지 않은 것"** 에 모아 사용자에게 준다. 목록을 만드는 것은 `refactor-plan` 의 일이다. ### 읽어서 모르면 돌려 본다 동작이 코드만으로 확정되지 않을 때(동적 라우팅, 런타임 설정, 프레임워크 기본값)는 실제로 띄워 보고 관찰한다. 단 **저장된 데이터를 바꾸는 요청은 사용자 확인 없이 보내지 않는다** — 실데이터 파일·DB 위에서 돌고 있을 수 있다. 읽기 요청과 화면 관찰까지만 스스로 한다. --- ## 2단계. `docs/PRD.md` — 지금 무엇이 되는가 형식은 `prd-generator` 의 것과 같다(같은 절 번호, 같은 표). 달라지는 것은 **내용의 출처와 몇 개 절의 채우는 법**이다. 아래는 그 차이만 적는다. **머리** — 버전·작성일 아래에 `> 코드에서 역으로 작성 (as-is, <날짜>)` 한 줄. `입력 문서` 는 `코드베이스 (<루트 경로>)`, 필요하면 README 를 함께. **1절 개요** — 한 줄 정의는 화면과 라우트가 하는 일을 묶어 쓴다("이름으로 로그인한 사용자가 프로젝트를 만들고 할 일을 나눠 갖는 웹 앱"). **배경·문제·목표·비목표는 코드에 없다.** 채우지 말고 "코드에 없음 — OQ-00x" 로 두고, OQ 는 `확인` 종류로 8절에 올린다. 그럴듯한 배경을 지어 넣으면 feature-add 가 그것을 방향으로 삼는다. **2절 사용자** — 코드에 있는 역할만. 권한 분기가 없으면 사용자 유형은 하나다. "관리자"가 코드에 없으면 표에도 없다. "누가 실제로 쓰는가"는 OQ 다. **3절 유저 스토리** — 화면·라우트에서 관찰되는 행위 단위로 쓴다. `왜냐하면` 은 코드에 없으므로 **비워 두지 말고 `(코드에 없음)`** 으로 적는다. 빈칸은 뒤 스킬이 누락으로 읽고, 지어낸 이유는 합의로 읽는다. 둘 다 아니라는 것을 표기로 남긴다. **4절 기능 요구사항** — 라우트·화면 하나가 FR 하나다. 수용 기준은 **지금 관찰되는 동작**이고, 코드의 오류 분기가 실패 경로다. ```markdown #### FR-004. 할 일 목록 조회 - **관련 스토리**: US-003 - **우선순위**: P0 (as-is) - **차단 미결**: 없음 - **설명**: `GET /api/tasks` 가 저장된 할 일 전체를 돌려준다. `projectId`·`done` 쿼리로 거른다. - **수용 기준**: - [ ] 쿼리 없이 부르면 저장된 할 일 전부가 배열로 온다 (200) - [ ] `projectId=` 를 주면 그 프로젝트의 할 일만 온다 - [ ] `done=true` 를 주면 빈 배열이 온다 — 저장값(불리언)과 쿼리값(문자열)을 `===` 로 비교한다 (`routes/tasks.js` 22행). 의도 여부: OQ-004 - [ ] 로그인하지 않아도 조회된다 (인증 검사 없음) ``` 셋째 기준처럼 **관찰이 이상해 보여도 관찰대로 적고 근거 줄과 OQ 를 붙인다.** 넷째처럼 **"검사가 없다"도 관찰이다** — 없는 것을 빼면 뒤 스킬이 있다고 가정한다. **우선순위는 전부 `P0 (as-is)`** 다. 지금 동작하는 것은 전부 보존 대상이고, 코드로는 무엇이 더 중요한지 알 수 없다. prd-generator 의 "P0 가 절반을 넘으면 범위 과다" 점검은 여기서는 적용하지 않는다 — 범위를 정한 것이 아니라 현재 상태를 적은 것이다. **5절 비기능 요구사항** — 코드에서 **확인되는** 속성만: 저장이 재시작 후에도 남는가, 입력 길이 제한, 동시 쓰기 시 무엇이 이기는가, 응답 형식. "보안을 준수한다" 같은 것은 물론이고 "응답 500ms" 같은 것도 코드에 없으면 적지 않는다. 확인되는 것이 없으면 절을 비우지 말고 "코드에서 확인되는 비기능 속성 없음" 한 줄. **6절 범위 밖** — 여기서는 "일부러 안 하기로 한 것"이 아니라 **코드에 없음이 확인된 것 중 기존 기능이 명백히 전제하는 것**만 적는다 (예: 로그인은 있는데 비밀번호가 없다, 삭제는 있는데 소유자 검사가 없다). `이유` 열은 `코드에 없음`, `언제 다시 볼 것인가` 는 `feature-add` 또는 `bug-fix`(OQ 답에 따라). 셋에서 다섯 개를 넘기지 않는다 — 길어지면 그것은 관찰이 아니라 기능 제안 목록이고, 그건 이 스킬의 일이 아니다. **7절 성공 지표** — 코드에 없다. 빈 표 대신 "코드에 없음 — 측정 코드·분석 도구 없음. OQ-00x" 한 줄. **8절 가정과 미결** — `확정된 가정` 에는 코드를 읽으며 한 가정("쿠키 `uid` 가 로그인 상태의 전부다 — 다른 세션 저장소 없음")을 근거 파일과 함께. 미결은 대부분 `확인` 이고, `질문` 은 사용자가 방침으로 바로 답할 수 있는 것에만 쓴다(테스트 도구 선택이 그렇다 — 3단계). 미결 규칙(ID·종류·차단·기본값·되돌리기 비용)은 prd-generator 와 같다. **as-is 미결은 원칙적으로 차단이 아니다** — 기능이 이미 있으니 "구현을 막을" 것이 없다. 차단으로 표시할 미결은 "이 동작이 의도인지 모르면 테스트를 쓸 수 없는" 경우뿐이고 그건 드물다. **9절 추적표** — `담당 태스크` 는 `(Layer 3에서 채움)` 그대로, **`상태` 는 `구현됨 (as-is)`** 다. ```markdown | 요구사항 | 관련 스토리 | 우선순위 | 차단 미결 | 담당 태스크 | 상태 | |---|---|---|---|---|---| | FR-004 | US-003 | P0 (as-is) | — | (Layer 3에서 채움) | 구현됨 (as-is) | ``` `정의됨` 으로 두면 plan-generator 가 이미 있는 기능을 구현하는 태스크를 만든다. `구현됨 (as-is)` 는 그 표의 세 번째 값이고 plan-generator 는 이 행의 상태를 올리지 않는다(7단계). --- ## 3단계. `docs/TRD.md` — 지금 무엇으로 되어 있는가 형식은 `trd-generator` 와 같다. 머리에 as-is 한 줄, `입력 문서` 는 `docs/PRD.md (as-is)` 와 코드베이스. **기술 결정은 패키지·설정·코드에서 나온다.** 결정 하나의 여섯 항목을 이렇게 채운다. ```markdown #### TD-002. 데이터 저장: JSON 파일 하나 - **영역**: 데이터 - **근거 요구사항**: FR-001~FR-009 (저장이 필요한 모든 기능), NFR-001(재시작 후 보존) - **결정**: `data/db.json` 한 파일에 users·projects·tasks 배열을 통째로 읽고 쓴다 - **검토한 대안**: — (코드에서 역으로 작성. 대안 검토 없음) - **확정도**: 확정 — 코드에 있음 (`db.js` 전체, `data/db.json`) - **되돌리기 비용**: 저장 접근이 `db.read()/write()` 두 함수에 모여 있어 그 파일과 호출부 3곳. 기존 데이터 이전은 별도 - **검증 방법**: 할 일을 만든 뒤 프로세스를 재시작해도 목록에 남아 있다 ``` - **확정도는 기존 세 값 중 `확정`** 이고 근거는 "코드에 있음(파일)" 이다. `as-is` 같은 새 확정도 값을 만들지 않는다 — 뒤 스킬이 아는 값은 셋뿐이다 - **검토한 대안은 `—`** 로 둔다. 코드에 없는 것을 지어 "이래서 골랐다"고 쓰면 refactor-plan 이 그 이유를 지켜야 할 제약으로 읽는다 - **되돌리기 비용은 적는다.** 코드를 읽었으니 "어디를 고쳐야 바뀌는가"를 실제로 안다. 이것이 refactor-plan 이 범위를 정할 때 쓰는 값이다 - **버전이 고정되어 있으면 그것도 결정이다.** `"express": "4.17.1"` 처럼 정확한 버전이 박혀 있으면 TD 본문에 적는다. 라이브러리 최신화가 refactor-plan 의 범위 하나이므로 지금 값이 문서에 있어야 한다 - **없는 것도 결정으로 적는다** — 보안 절에 "비밀번호 없음, 쿠키 서명 없음, CSRF 대책 없음(코드에 있음: `server.js` 로그인 핸들러)". 없는 것을 절 자체에서 빼면 뒤 스킬이 있다고 가정한다 **TD 로 세는 기준은 trd-generator 와 같다** — 되돌리기 비용이 독립인 것만. 프레임워크를 고르면 딸려 오는 것은 상위 TD 본문에 흡수한다. **1.3절 프로젝트 여건** — 코드에서 나오는 값(개발자 OS 는 지금 세션의 OS, 기존 자산은 이 코드)만 채우고 나머지는 `코드에 없음`. 표를 억지로 채우지 않는다. **8절 테스트 — 이 문서에서 유일하게 as-is 가 아닌 결정이 들어가는 자리다.** 코드에 테스트가 0건이면 그 사실을 먼저 적는다("테스트 0건, 러너 없음, lint 설정 없음 — 코드에 있음: `package.json` scripts 에 `test` 없음"). 그런데 뒤에서 plan-generator 가 만들 phase-01 태스크는 **테스트를 쓰는 것**이고, 무엇으로 쓸지가 없으면 태스크마다 도구를 즉흥으로 고른다. 그래서 **테스트 도구 TD 하나**를 더한다 — 이 스택에서 설정이 가장 적은 표준 러너와, 화면이 있으면 e2e 도구를 한 TD 에 묶어서. 딸려 오는 것이라 하나로 센다. 이 TD 만은 코드에 없으므로 **확정도 `잠정(OQ-0xx 대기)`**, 결정 문장 끝에 `(가정)`, OQ 는 종류 `질문` 이다 — 사용자가 방침으로 바로 답할 수 있다. 기본값(답이 없을 때 쓸 도구)을 반드시 적는다. 6단계 보고에서 이 하나는 선택지로 묻는다. `8.1 반드시 덮어야 할 영역` 표는 **as-is FR 전부**다 — phase-01 이 붙잡을 것이 그것이다. 근거 열에 FR 을 적는다. **9절 배포·운영** — 배포 설정(Dockerfile, CI, 호스팅 설정)이 코드에 없으면 `코드에 없음 — OQ-0xx(확인)`. **9.3 로컬 개발 환경의 구성 요소 표는 반드시 채운다** — harness-setup 의 local-dev 가 이 표를 그대로 구현한다. 앱 서버, 데이터 저장소(파일이면 그 파일), 외부 서비스. 코드가 직접 읽고 쓰는 데이터 파일은 여기 적어야 하네스가 테스트와 실데이터를 떼어 놓는다. **12절 미결** — PRD 의 마지막 OQ 번호 다음부터. **13절 추적표**는 모든 FR·NFR 이 최소 하나의 TD 에 걸리게 한다. --- ## 4단계. `docs/ARCHITECTURE/` — 지금 어떻게 놓여 있는가 형식은 `architecture-generator` 와 같다 — `overview.md` 는 항상, 영역 문서는 **코드에 그 영역이 실제로 있을 때만**. 파일 셋뿐인 앱에 `frontend.md`·`backend.md`·`database.md`·`auth.md` 를 다 만들 필요는 없다. 영역이 작아 절이 두세 개면 상위 문서에 흡수한다. 빈 문서는 plan-generator 에서 빈 태스크가 된다. **overview.md** - 2절 구성 요소는 실제 프로세스·파일 단위로("정적 프런트(`public/`) / Express 서버(`server.js`) / JSON 파일(`data/db.json`)"). `근거` 는 TD - 3절 의존 방향은 **실제 import 관계**다. 계층이 없으면 "계층 없음 — 라우터가 저장 모듈을 직접 부른다"로 적는다. 있어야 할 방향을 적지 않는다 - 4절 핵심 흐름은 화면에서 시작하는 실제 경로. 실패 시 어디로 가는지도 코드대로 - 5절 횡단 규칙은 관찰되는 것만 — 오류 표현이 `{ error: "..." }` JSON 이면 그것, 시간이 ISO 문자열이면 그것. 규칙이 없으면 "없음(파일마다 다름 — `a.js` 는 X, `b.js` 는 Y)". 이 불일치는 리팩토링 재료이지만 여기서는 관찰로만 남긴다 - **7절 충돌 검토는 0건이 정상이다** — PRD·TRD·ARCHITECTURE 가 같은 코드에서 나왔으니 서로 충돌할 수 없다. 표를 비우고 "같은 코드에서 역으로 작성 — 충돌 0건" 한 줄. 코드 안의 모순(README 와 다르다, 두 라우터의 인증 검사가 다르다)은 CF 가 아니라 OQ(`확인`)다 - 8절 추적표는 모든 FR·NFR → 설계 단위. 9절 미결은 TRD 다음 번호 **영역 문서의 설계 단위** — 폴더·모듈·파일 하나가 절 하나다. 다섯 항목을 이렇게 채운다. ```markdown ### 3.2 할 일 라우터 (`routes/tasks.js`) - **근거**: FR-004~FR-007 / TD-001(Express), TD-002(JSON 파일) - **설계**: `express.Router` 하나에 GET·POST·PATCH·DELETE 네 핸들러. 인증은 쿠키 `uid` 를 핸들러마다 직접 읽는 `getUserId` 로(GET·DELETE 는 읽지 않음). 저장은 `db.read()` → 배열 수정 → `db.write()` - **왜 이 모양인가**: 코드에 없음 - **검증 기준**: FR-004~FR-007 의 수용 기준과 같다. 로그인 없이 POST 하면 401, 없는 id 로 PATCH 하면 404 - **바뀔 수 있는 지점**: 없음 (잠정 TD 없음, CF 없음) ``` - **"왜 이 모양인가"는 `코드에 없음`** 으로 둔다. 주석이나 커밋 메시지에 이유가 있으면 그것을 출처와 함께 적는다. 지어내지 않는다 — 이유를 아는 모델은 지키고, 지어낸 이유도 지킨다 - **검증 기준은 FR 을 가리킨다.** 설계 단위와 FR 이 같은 코드에서 나왔으니 따로 쓸 것이 없다. 다만 FR 에 안 잡히는 구조 조건(예: 정적 파일이 `public/` 에서 나간다)은 여기 적는다 - **관찰된 중복·경계 어김은 설계에 쓰지 않는다.** `getUserId` 가 두 라우터에 따로 있다는 사실은 각 절의 `설계` 항목에 사실로 남지만, "합쳐야 한다"는 어디에도 쓰지 않는다. 6단계 보고로 간다 --- ## 5단계. `CLAUDE.md` · `AGENTS.md` 갱신 세 문서를 쓴 뒤 프로젝트 루트의 `CLAUDE.md` 와 `AGENTS.md` 를 **같은 내용으로** 갱신한다. 사용자가 직접 연 세션과 루프의 자식 세션은 이 스킬을 읽지 않고 시작하는데, 그때 자동으로 읽히는 파일은 Claude Code 는 `CLAUDE.md`, Codex 는 `AGENTS.md` 뿐이다. 그래서 **지금 어느 호스트에서 돌든 둘 다 쓴다** — 한쪽만 쓰면 다른 호스트의 세션이 규칙을 모른 채 시작한다. 내용은 **어느 세션에서든 반드시 지킬 것**만 두고 세부 규칙은 문서를 가리킨다 — 규칙을 옮겨 적으면 두 곳이 곧 어긋나고, 어긋나면 세션은 짧은 쪽을 믿는다. - 둘 다 없으면 아래 뼈대로 만든다. 있으면 **`## 제품`·`## 기술`·`## 구조` 세 절과 `현재 단계` 줄만** 고친다. 다른 절과 사용자가 손으로 적은 내용은 건드리지 않는다 - 바이브 코딩 프로젝트에는 `/init` 이 만든 `CLAUDE.md` 가 있는 경우가 많다. 파일은 있는데 `## 문서 지도`·`## 공통 규칙` 이 없으면 기존 내용 **아래에** 뼈대 두 절을 더한다. 기존 내용은 손대지 않는다 - 두 파일이 서로 다르면 지금 호스트의 파일을 기준으로 다른 쪽을 맞춘다. 손으로 적은 줄은 양쪽에 남긴다 - 절이 없으면 `공통 규칙` 뒤에 제품·기술·구조·플랜·하네스·루프 순서의 자리에 더한다. **플랜·하네스·루프 절은 만들지 않는다** — 7~9단계에서 부르는 스킬이 자기 절을 쓴다 - 전체 **100줄 안팎, 200줄을 넘기지 않는다.** 넘치면 규칙을 문서 쪽으로 돌려보내고 가리키는 줄만 남긴다 ```markdown # <프로젝트 이름> > harness-loop-fullstack 스킬이 만들고 갱신하는 파일이다. 각 절은 그 레이어의 스킬만 고친다. > `CLAUDE.md` 와 `AGENTS.md` 는 같은 내용이다. 한쪽을 손으로 고치면 다른 쪽도 같이 고친다. > 세부 규칙은 각 문서에 있다 — 여기에는 어느 세션에서든 반드시 지킬 것만 둔다. 200줄을 넘기지 않는다. ## 문서 지도 - `docs/IDEA.md` → `docs/PRD.md` → `docs/TRD.md` → `docs/ARCHITECTURE/` → `plan_setup/` → `harness_setup/` → `loop_setup/LOOP.md` - 뒤 문서는 앞 문서를 근거로 한다. 어긋나면 앞 문서가 이긴다 — 바꿔야 하면 사용자 확인 뒤 **가장 앞 문서부터** 고치고(버전·`변경 이력` 한 줄. 프로젝트 완료 뒤에는 `feature-add`·`refactor-plan` 의 후미 절로) 사이 문서를 맞춘 다음 이어 간다(변경 전파). 손으로 고칠 때도 같다. 루프 세션은 앞 문서를 고치지 않고 LOOP.md 대로 멈춘다 - 현재 단계: <마지막으로 끝낸 스킬> → 다음: <다음 스킬> ## 공통 규칙 - 앞 레이어의 **파일**만 입력이다. 대화 기억이나 추측으로 요구사항·기술 결정을 만들지 않는다 - ID(`FR-`·`NFR-`·`US-`·`OQ-`·`TD-`·`phase-NN-task-MM`)는 참조만 한다. 새 ID 는 마지막 번호 다음으로만 만든다 — OQ 는 프로젝트 전체(`HARNESS.md`·`LOOP.md` 의 미결 표까지)에서, 나머지는 그 문서에서 센다(변경 전파로 앞 문서에 더할 때도) - 사용자가 말하지 않은 값은 `(가정)` 으로 표시한다. 모호하면 추측하지 말고 묻는다 - 요청된 범위를 조용히 넓히거나 줄이지 않는다. 범위 판단은 보고한다 ``` 세 절에는 이것만 적는다. **첫 줄의 as-is 표기가 핵심이다** — 이 파일만 읽은 세션이 PRD 를 목표로 읽지 않게 한다. ```markdown ## 제품 (docs/PRD.md) - **as-is 문서** — 코드에서 역으로 작성 (<날짜>). 합의된 목표가 아니라 현재 상태다 - <한 줄 정의> - FR 개 전부 P0 (as-is) · 차단 OQ: · 의도 확인 대기 OQ: - PRD 에 없는 기능을 만들지 않는다. 더하려면 feature-add 로 PRD 후미 절과 9절 추적표를 먼저 고친다 ## 기술 (docs/TRD.md) - **as-is 문서** — 코드에서 역으로 작성 (<날짜>). 테스트 도구(TD-0xx)만 잠정 - 스택: <언어/프레임워크 · 저장소 · 배포 — 한 줄> - 되돌리기 비용이 큰 결정: (2~3개) - TRD 에 없는 라이브러리·외부 서비스를 들이지 않는다. 필요하면 TD 를 더한 뒤 쓴다 ## 구조 (docs/ARCHITECTURE/) - **as-is 문서** — 코드에서 역으로 작성 (<날짜>). "왜 이 모양인가"는 대부분 코드에 없음 - 의존 방향: <실제 import 방향 한 줄. 계층이 없으면 없다고> - <경계 규칙 — 코드에서 관찰되는 것 2~3개> - 설계 단위(영역 문서 3절)에 없는 모듈을 만들지 않는다. 필요하면 영역 문서를 먼저 고친다 ``` `현재 단계` 줄은 지금은 `code-to-docs(문서) → 다음: plan-generator` 로 쓴다. 10단계에서 다시 덮어쓴다. --- ## 6단계. 자체 점검과 중간 보고 세 문서를 쓴 뒤 처음부터 다시 읽으면서 확인한다. 열은 `확인할 것 | 통과 조건 | 걸렸을 때` 다. | 확인할 것 | 통과 조건 | 걸렸을 때 | |---|---|---| | as-is 표기 | PRD·TRD·overview.md·영역 문서 전부 머리에 `> 코드에서 역으로 작성 (as-is, <날짜>)` 이 있음 | 더한다 | | 코드에 없는 것 | 배경·목표·이유·성공 지표·검토한 대안·"왜 이 모양인가"에 지어낸 문장이 0건 — 전부 `코드에 없음` 또는 OQ | 지우고 `코드에 없음` 으로 되돌린다 | | 근거 줄 | 모든 FR 수용 기준과 TD 결정에 파일(·줄) 근거가 있음 | 찾아 적는다. 못 찾으면 그 관찰은 코드에 없는 것이다 — 지운다 | | 라우트·화면 누락 | 코드의 모든 라우트·화면·CLI 명령이 어느 FR 에 걸림 | FR 을 더한다 | | "없음" 관찰 | 인증·권한·검증이 **없는** 곳이 수용 기준 또는 TRD 보안 절에 사실로 적혀 있음 | 더한다. 빠지면 뒤 스킬이 있다고 가정한다 | | 버그 판단 | 수용 기준에 "버그"·"잘못"·"고쳐야" 같은 판단어가 0건. 이상해 보이는 동작은 관찰 + OQ(`확인`) | 판단어를 지우고 OQ 를 만든다 | | 우선순위 | 모든 FR 이 `P0 (as-is)` | 맞춘다 | | 9절 상태 | 모든 행이 `구현됨 (as-is)`, `담당 태스크` 는 `(Layer 3에서 채움)` | 맞춘다. `정의됨` 이 남으면 plan-generator 가 구현 태스크를 만든다 | | TD 확정도 | 테스트 도구 TD 하나만 `잠정(OQ 대기)`, 나머지 전부 `확정 — 코드에 있음(파일)`. 새 확정도 값 0건 | 맞춘다 | | 9.3 구성 요소 표 | 앱 서버·데이터 저장소(파일이면 그 파일)·외부 서비스가 다 있음 | 채운다. local-dev 가 이 표를 구현한다 | | CF 표 | 0건이고 그 이유 한 줄이 있음 | 코드 안의 모순은 CF 가 아니라 OQ 로 옮긴다 | | OQ 종류 | `확인` 이 대부분이고 `질문` 은 테스트 도구처럼 사용자가 방침으로 답할 수 있는 것뿐 | 재분류한다. `확인` 을 객관식으로 묻지 않는다 | | OQ 번호 | PRD → TRD → ARCHITECTURE 로 이어짐 | 다시 매긴다 | | 리팩토링·제안 혼입 | "합쳐야", "분리해야", "추가하면 좋을" 이 세 문서에 0건 | 지우고 보고의 "문서에 일부러 넣지 않은 것"으로 옮긴다 | | 추적표 | TRD 13절·overview 8절이 모든 FR·NFR 을 덮음 | 채운다 | | `CLAUDE.md` · `AGENTS.md` | 두 파일이 같고 제품·기술·구조 세 절에 as-is 첫 줄이 있고 각 200줄 이하 | 자기 절만 고친다 | **자체 점검 결과는 문서에 남기지 않는다.** 보고로 간다. 그다음 사용자에게 **중간 보고**를 한다. 뒤 스킬 셋을 부르기 전에 문서를 사람이 한 번 보는 지점이다 — 코드 읽기가 틀렸으면 그 위에 세운 플랜·하네스·루프가 다 틀린다. 1. 세 문서를 만들었다는 사실과 크기 — FR n개(전부 P0 as-is), NFR n개, TD n개, 설계 단위 n개, OQ n개(`확인` n, `질문` n) 2. **테스트 도구 선택(질문 OQ)** — 선택지와 기본값. 이것 하나만 객관식이다. 답이 없으면 기본값으로 진행한다고 알린다 3. **의도 확인이 필요한 동작 목록**(`확인` OQ) — 이상해 보이지만 관찰대로 적은 것들. "답을 못 주셔도 지금 동작대로 테스트를 씁니다. 나중에 버그로 판명되면 bug-fix 가 그 테스트를 바꿉니다" 4. **문서에 일부러 넣지 않은 것** — 눈에 띈 중복·경계 어김·버그 후보. "리팩토링·버그 재료입니다. phase-01 이 완료되면 refactor-plan·bug-fix 로 다룹니다" 5. git 상태(저장소 아님 / 미커밋 변경 있음)와 첫 커밋 제안 6. 다음 단계 안내: "검토하시고 괜찮으면 plan-generator → harness-setup → loop-setup 을 이어서 부릅니다" 사용자가 "그냥 진행"이라 하면 기본값으로 이어서 간다. 사용자와 대화할 수 없는 환경이면 위 여섯을 기록으로 남기고 기본값으로 진행한다. --- ## 7단계. `plan-generator` 호출 — phase 하나, 태스크는 현행 고정 테스트만 plan-generator 는 평소처럼 세 문서를 읽고 자기 절차(태스크 도출·frontmatter·STATE.md·LOG.md·PRD 추적표·자체 점검)를 다 한다. **이 스킬은 그 절차를 옮겨 적지 않는다.** 부를 때 아래 지시를 넘긴다. 지시가 없으면 plan-generator 는 설계 단위마다 "만드는" 태스크를 자르고, 그러면 이미 있는 것을 다시 만드는 플랜이 나온다. ``` plan-generator 호출 지시 (code-to-docs 에서) - 입력 docs/PRD.md·TRD.md·ARCHITECTURE/ 는 as-is 문서다 — 합의된 목표가 아니라 현재 상태. 머리의 as-is 표기를 확인하라 - phase 는 하나만 만든다: phase-01, 파일 이름 phase-01-baseline.md (현행 고정). 파일 이름은 영문으로 둔다 - 태스크는 두 종류뿐이다: ① phase-01-task-01 — 테스트 도구 설정 (TRD 8절의 테스트 도구 TD 대로 러너·설정·`test` 스크립트를 두는 것). files 는 package/설정 파일 ② as-is FR 마다 하나 — 지금 동작을 그대로 붙잡는 테스트 파일을 쓰는 것. files 는 그 테스트 파일 하나. depends_on 은 task-01. NFR 은 어느 FR 의 테스트에 흡수하거나 전용 테스트 태스크로 - 기능을 구현·수정하는 태스크는 0건이다. FR 의 수용 기준이 이상해 보여도(OQ 확인 대기) 지금 동작을 붙잡는다 — 고치는 것은 bug-fix 의 일이다 - 태스크 acceptance_criteria 는 관찰 가능하게: "FR-00x 의 수용 기준 각 줄에 대응하는 테스트 케이스가 있다", "현재 코드에서 전부 통과한다", 실패 경로로 "그 동작을 바꾸면(예: 응답 코드를 바꾸면) 그 케이스가 실패한다" - verification 은 넷 그대로. 화면이 있는 FR 의 테스트 태스크는 e2e 도구로 쓴다 - PRD 9절: `구현됨 (as-is)` 행에는 그 FR 의 테스트 태스크를 담당으로 붙이되 상태는 올리지 않는다(7단계 규칙). `계획됨` 으로 바꾸지 않는다 - phase-01 의 Acceptance Criteria: 모든 as-is FR 에 테스트 태스크가 완료됨, 테스트 전부 통과, 게이트 넷이 활성 - 차단: as-is 미결은 원칙적으로 막지 않는다. 테스트 도구 TD 가 잠정이면 그 기본값으로 진행하고 task-01 의 '바뀔 수 있는 지점'에 OQ 를 적는다 - CLAUDE.md·AGENTS.md 의 `## 플랜` 절은 평소대로 쓰되 `현재 단계` 줄은 code-to-docs 가 끝에 다시 쓴다 ``` plan-generator 가 끝나면 그 보고를 그대로 사용자에게 전한다. 여기서 확인할 것은 셋 — phase 가 하나인가, 구현 태스크가 0건인가, PRD 9절 상태가 그대로인가. 어긋나면 plan-generator 10단계로 고친다. --- ## 8단계. `harness-setup` 호출 — 활성 시점은 phase-01 의 태스크 harness-setup 도 평소처럼 다섯 입력을 읽고 게이트 넷과 local-dev 를 세운다. 넘길 지시는 아래다. 평소와 다른 점은 하나 — **코드가 이미 있다.** 하네스는 "코드 0줄"을 전제로 미활성에서 시작하는데, 여기서는 앱이 실제로 뜬다. local-dev 는 지금 바로 검증할 수 있고, 게이트는 phase-01 태스크가 끝나는 대로 활성이 된다. ``` harness-setup 호출 지시 (code-to-docs 에서) - docs/ 는 as-is 문서다. E2E 흐름 목록은 PRD 의 as-is 스토리에서, 필수 커버 영역은 TRD 8.1(= as-is FR 전부)에서 - 활성 시점은 phase-01 태스크 중 **그 게이트가 처음으로 판정할 것이 생기는 태스크**다 — lint 는 phase-01-task-01(도구 설정) 완료, unit 은 unit 러너로 쓰는 첫 테스트 태스크, e2e 는 e2e 도구로 쓰는 첫 테스트 태스크(화면 FR 뿐 아니라 실행 중인 앱을 상대로 쓰는 API 테스트도 그 도구면 그 태스크), task_validation 은 phase-01-task-02 부터. 도구만 깔린 시점(task-01)에 unit 을 활성으로 두면 0건 실행이 초록불로 샌다. 어느 태스크가 어느 도구를 쓰는지는 태스크 문서의 `files` 경로로 읽는다. phase 가 하나뿐이니 그 밖의 태스크 ID 를 가리키지 않는다 - 코드가 이미 있으므로 local-dev 는 지금 실제로 돌려 확인한다(띄우기·상태·내리기). TRD 9.3 구성 요소 표를 그대로 구현한다 - 코드가 직접 읽고 쓰는 데이터 파일·DB 가 있으면 테스트·e2e 가 실데이터를 건드리지 않게 분리한다(환경변수로 경로·이름을 바꾸거나 사본). 방법은 하네스가 정한다 - 테스트 도구는 TRD 의 테스트 도구 TD(잠정이면 그 기본값). 도구 설치는 phase-01-task-01 의 일이므로 하네스가 대신 설치하지 않는다 - 테스트 0건 상태에서 게이트가 초록불이 되지 않게 미활성 규칙을 평소대로 ``` --- ## 9단계. `loop-setup` 호출 — 평소대로 loop-setup 은 지시가 거의 필요 없다. 플랜과 하네스를 읽고 자기 규칙대로 세운다. 넘길 것은 둘이다. ``` loop-setup 호출 지시 (code-to-docs 에서) - 이 프로젝트는 code-to-docs 로 진입했다. phase 는 phase-01-baseline 하나이고 태스크는 전부 테스트 작성이다 - 첫 태스크 전에는 게이트 넷이 전부 미활성이다 — Standing Decisions 의 미활성 승인을 세팅 때 게이트별로 받아 적어 둔다(비면 첫 태스크에서 구동기가 선다) - phase-01 이 completed 되면 루프를 멈추고 사용자에게 돌아온다 — 그다음은 refactor-plan·feature-add·bug-fix 의 진입 조건이 된다 ``` 병렬 여부·동시 수·역할별 모델·격리 방식은 loop-setup 이 평소대로 묻는다. 이 스킬이 대신 답하지 않는다. --- ## 10단계. 마무리 — 상태 확인과 루프 안내 셋이 끝나면 프로젝트 루트가 원본이 그린 모양인지 확인한다. ``` docs/PRD.md · TRD.md · ARCHITECTURE/ (as-is) plan_setup/PLAN.md · STATE.md · LOG.md plan_setup/phase-01/phase-01-baseline.md plan_setup/phase-01/phase-01-tasks/phase-01-task-*.md harness_setup/HARNESS.md · quality_gates/{lint,unit,e2e,task_validation}.md · scripts/ loop_setup/LOOP.md (· DAG.md) CLAUDE.md · AGENTS.md ``` | 확인할 것 | 통과 조건 | 걸렸을 때 | |---|---|---| | phase 개수 | `plan_setup/` 에 phase-01 하나 | plan-generator 10단계 | | 구현 태스크 | 모든 태스크의 Goal 이 "테스트를 쓴다" 또는 "도구를 설정한다". 코드를 고치는 태스크 0건 | plan-generator 10단계 | | PRD 9절 | 모든 행이 `구현됨 (as-is)` 그대로이고 `담당 태스크` 에 테스트 태스크가 있음 | 되돌린다 | | 활성 시점 | 게이트 정의서의 활성 시점이 전부 phase-01 태스크 ID | harness-update ① | | STATE.md | `Current Phase` 1, `Phase Overview` 에 phase-01 `pending`, `Standing Decisions` 에 미활성 승인이 있음 | loop-setup 이 채운다 | | `현재 단계` 줄 | `CLAUDE.md`·`AGENTS.md` 둘 다 아래 값 | 덮어쓴다 | **`현재 단계` 줄을 이 스킬이 맨 끝에 덮어쓴다** — 중간에 부른 plan-generator 가 그 줄을 "plan-generator → 다음: harness-setup" 으로 썼고 뒤 둘도 각자 썼으므로, 끝에서 한 번 더 쓴다. ``` - 현재 단계: code-to-docs(as-is 문서 + plan·harness·loop 세팅) → 다음: 개발 루프 1회 (phase-01-baseline 완료) ``` 그리고 사용자에게 마지막 보고를 한다. 1. 만들어진 것 — 문서 셋(as-is), phase-01 태스크 n개(도구 1 + 테스트 n-1), 게이트 넷과 활성 시점, LOOP.md 의 구동 모드 2. **"루프를 한 번 돌려 phase-01 을 완료시키세요"** — `LOOP.md` 0절부터, 구동기는 8절. phase-01 이 `completed` 가 되면 게이트 넷이 활성이고, 그때부터 이 프로젝트는 이 플러그인으로 만든 완료 프로젝트와 같다 3. 그다음 갈 수 있는 곳 — 코드 정리는 `refactor-plan`, 기능 추가는 `feature-add`, 안 되는 것은 `bug-fix`. **refactor-plan 과 bug-fix 는 phase-01 completed 를 조건으로 본다** — 게이트가 활성이어야 "기존 게이트 통과"가 뜻을 가진다 4. 남은 OQ — 특히 의도 확인 대기 목록. 답이 "버그다"이면 phase-01 완료 뒤 `bug-fix` 로 5. 6단계에서 넘긴 "문서에 일부러 넣지 않은 것" 을 한 번 더 — 어디로 가는지와 함께 --- ## 범위를 넘는 요청이 함께 오면 이 스킬은 "정리해 달라"는 말과 같이 오는 요청이 많다. 셋은 **하지 않고, 어디로 가는지 답한다.** 조용히 무시하지도, 조용히 하지도 않는다. | 요청 | 이 스킬이 하는 것 | 왜 | |---|---|---| | "PRD 부터 제대로 새로 써 줘" / "이런 제품으로 만들 거니까 그 기준으로" | as-is PRD 를 먼저 만들고, 목표는 `feature-add` 가 후미 `## 추가 N` 절로 더하게 한다. 사용자가 말한 목표는 보고에 그대로 옮겨 둔다 | 목표만 적은 PRD 는 있는 기능도 "만들 것"이 되어 플랜이 다시 만든다. as-is 위에 델타로 얹어야 이미 있는 것과 더할 것이 갈린다 | | "리팩토링까지 해 줘" / "구조 좀 잡아 줘" | 하지 않는다. 눈에 띈 것은 보고의 "일부러 넣지 않은 것"에. phase-01 완료 뒤 `refactor-plan` | 지금 동작을 붙잡는 게이트 없이 구조를 바꾸면 무엇이 깨졌는지 모른다. 그 게이트를 만드는 것이 이 스킬이다 | | "이거 버그 같은데 고쳐 줘" | 고치지 않는다. 관찰대로 적고 OQ(`확인`). phase-01 완료 뒤 `bug-fix` | 지금 고치면 회귀 검사도 기록도 분리 검증도 없다. 현행 테스트가 먼저 있어야 고친 것이 무엇인지 남는다 | | "테스트는 나중에, 문서만" | 문서 셋까지 만들고 멈추되, 플랜·하네스·루프 없이는 뒤 스킬 셋이 진입하지 못한다는 것과 다음에 이 스킬을 다시 부르면 7단계부터 이어진다는 것을 알린다 | 문서만으로는 refactor-plan 의 "기존 게이트 통과"가 뜻이 없다 | 요청을 돌려보낼 때는 그 요청의 내용을 **보고에 그대로 옮겨** 둔다. 사용자가 다음 스킬을 부를 때 다시 설명하지 않게. --- ## 산출물 요약 이 스킬이 직접 쓰는 것과 부른 스킬이 쓰는 것을 구별한다. **형식은 전부 Layer 1~5 의 것이고 여기서는 머리와 달라지는 칸만 보여 준다.** ### `docs/PRD.md` 머리와 9절 ```markdown # PRD: <제품 이름> - **버전**: 0.1 (as-is) - **작성일**: YYYY-MM-DD - **입력 문서**: 코드베이스 (<루트 경로>), README.md - **상태**: 사람 검토 대기 > 코드에서 역으로 작성 (as-is, YYYY-MM-DD) — 이 문서는 합의된 목표가 아니라 지금 코드가 하는 일이다. > 코드에 없는 것은 `코드에 없음` 또는 OQ 로 남겼다. 목표를 더하려면 feature-add 로 후미 절을 붙인다. ## 1. 개요 ### 1.1 한 줄 정의 ### 1.2 배경과 문제 코드에 없음 — OQ-001 ### 1.3 목표와 비목표 코드에 없음 — OQ-001 (2~8절은 prd-generator 형식 그대로) ## 9. 요구사항 추적표 | 요구사항 | 관련 스토리 | 우선순위 | 차단 미결 | 담당 태스크 | 상태 | |---|---|---|---|---|---| | FR-001 | US-001 | P0 (as-is) | — | (Layer 3에서 채움) | 구현됨 (as-is) | ``` ### `docs/TRD.md` 머리와 8절 ```markdown # TRD: <제품 이름> - **버전**: 0.1 (as-is) - **작성일**: YYYY-MM-DD - **입력 문서**: docs/PRD.md (0.1 as-is), 코드베이스 - **상태**: 사람 검토 대기 > 코드에서 역으로 작성 (as-is, YYYY-MM-DD) — 결정은 전부 `확정 — 코드에 있음(파일)` 이고 검토한 대안은 없다. > 예외는 테스트 도구(TD-0xx) 하나 — 코드에 없어 잠정(가정)이다. (1~7절은 trd-generator 형식 그대로) ## 8. 테스트 현재: 테스트 0건, 러너 없음, lint 설정 없음 — 코드에 있음: `package.json` scripts 에 `test` 없음 #### TD-0xx. 테스트 도구 (phase-01 현행 고정용) - **영역**: 테스트 - **근거 요구사항**: as-is FR 전부 — 지금 동작을 붙잡을 테스트가 필요하다 - **결정**: <스택에서 설정이 가장 적은 표준 러너> + <화면이 있으면 e2e 도구> (가정) - **검토한 대안**: <같은 스택의 다른 러너 하나> — 설정 파일이 더 필요하다 - **확정도**: 잠정(OQ-0xx 대기) - **되돌리기 비용**: phase-01 의 테스트 파일 전부 다시 씀. 도구 설정 태스크 1개 재작업 - **검증 방법**: phase-01-task-01 이 끝난 뒤 `test` 스크립트가 0건 실행이 아니라 케이스 n개를 돌린다 ### 8.1 반드시 덮어야 할 영역 | 영역 | 근거 요구사항 | |---|---| | | FR-00x~FR-00y | ``` ### `docs/ARCHITECTURE/overview.md` 머리와 7절 ```markdown # 아키텍처 개요: <제품 이름> - **버전**: 0.1 (as-is) - **작성일**: YYYY-MM-DD - **입력 문서**: docs/PRD.md (0.1 as-is), docs/TRD.md (0.1 as-is), 코드베이스 - **상태**: 사람 검토 대기 > 코드에서 역으로 작성 (as-is, YYYY-MM-DD) — 있어야 할 구조가 아니라 지금 놓여 있는 구조다. "왜 이 모양인가"는 대부분 코드에 없다. (1~6절은 architecture-generator 형식 그대로. 3절 의존 방향은 실제 import 관계) ## 7. PRD·TRD 충돌 검토 결과 같은 코드에서 역으로 작성 — 충돌 0건. 코드 안의 모순(README 와 코드, 라우터 간 인증 검사 차이)은 CF 가 아니라 9절 OQ 다. ``` 영역 문서의 머리도 같다 — `근거 문서` 줄 아래에 as-is 한 줄, `잠정인 부분` 은 `없음`(테스트 도구 TD 위에 세운 설계는 없다). ### 부른 스킬이 쓰는 것 `plan_setup/`·`harness_setup/`·`loop_setup/` 은 각 스킬의 산출물 템플릿 그대로다. 이 스킬은 형식을 갖고 있지 않고, 7~9단계의 호출 지시만 넘긴다. 그 결과가 10단계 표를 통과하는지만 본다. --- ## 에이전트별 참고 - Claude Code에서 실행 중이면: `references/claude-code.md` - Codex에서 실행 중이면: `references/codex.md`