Files

123 lines
7.9 KiB
Markdown
Raw Permalink Normal View History

# 7교시 바이브 코딩 · `tver` 정답본
> **강사용 정답본** · 학생 저장소에는 수업 뒤에 올립니다. 학생용은 [VIBE-REQ-TVER.md](VIBE-REQ-TVER.md)(요청서) → [VIBE-Q-TVER.md](VIBE-Q-TVER.md).
> 강사가 직접 만든 본: [tver/](tver/README.md) (2026-10-27, Claude Code가 아래 SPEC · IMP-PLAN을 보고 직접 씀, 테스트 11개). CLI 에이전트에 아래 요청문을 보내 재지는 않았습니다. 강사 바이브 코딩 시간은 6절에 수업 때 적습니다.
## 1. `Doc/TODO.md` 예
```markdown
# tver TODO
## 만들고 싶은 것
어느 폴더에서나 `tver`로 n8n 워크플로우를 git에 버전으로 남기고, 두 버전을 노드 단위로 비교해
바뀐 것을 모델 · 지시문 · 흐름으로 나눠 보여 주는 도구. 화면(TUI)도, 다른 프로그램용 결과도.
## 요청의 말 → 할 일
| # | 요청의 말 | 할 일 | 꼭 · 나중 |
| --- | --- | --- | --- |
| ① | 노드 단위 비교 | 이름으로 짝지어 더함 · 뺌 · 바뀐 설정 · 연결 | 꼭 |
| ② | 뜻 없는 차이 빼기 | 위치 · id · 순서는 비교에서도 저장에서도 뺌 | 꼭 |
| ③ | 어느 문장이 | 긴 글은 줄 단위 | 꼭 |
| ④ | 셋으로 나눠 한 줄 | 모델 · 지시문 · 흐름 개수 | 꼭 |
| ⑤ | 버전으로, 같으면 저장 X | git 커밋, 요약을 메시지로 | 꼭 |
| ⑥ | 목록 · 두 버전 비교 | log, 두 커밋 비교 | 꼭 |
| ⑦ | 키가 있으면 저장 X | 키 모양을 찾으면 거부, 메시지도 가려서 | 나중 |
| ⑧ | 화면에서 | 목록 · 트리 · 자세히 | 꼭 |
| ⑨ | n8n에서 바로 | 컨테이너에서 내보내 모두 저장 (읽기만) | 나중 |
| ⑩ | 예전 버전을 파일로 | 꺼내기만, 올리는 건 사람 | 나중 |
| ⑪ | 다른 프로그램이 읽게 | JSON, 종료 코드 | 나중 |
| ⑫ | 이름만 바뀐 것 | renamed | 나중 |
| 끝 | 폴더 → 워크플로우만 | nodes · connections가 있는 것만 | 나중 |
| 끝 | n8n을 망가뜨리지 않기 | 저장소는 따로, n8n에 쓰지 않음 | 꼭 |
## 걱정되는 것
- 저장할 때도 정리해야 "같다"를 알 수 있다
- 이름에 공백 · 한글 · `/`가 있는 워크플로우의 파일 이름
- 키를 거부할 때 메시지에 키가 그대로 나오면 안 됨
```
## 2. `Doc/SPEC.md` 요점
VIBE-Q의 요구 표(R1~R14)와 같습니다. 학생 SPEC과 비교할 때 자주 빠지는 것:
| 자주 빠지는 것 | 왜 필요한가 |
| --- | --- |
| R2를 **저장에도** 적용 (정리한 글로 저장) | 그래야 R5 "같으면 저장 안 함"이 글자 비교로 되고 저장소의 git diff도 읽힘 |
| 분류 규칙을 글로 정해 둠 | 정해 두지 않으면 에이전트가 웹훅 경로를 "모델"로 세기도 함 |
| R10 꺼내기가 저장소를 바꾸지 않음 | 꺼낼 때마다 버전이 생기면 목록이 엉킴 |
| 테스트 저장소는 `tmp_path` | 진짜 `~/.tver/store`가 테스트로 더러워짐 |
| 종료 코드 (diff 0 · 1, 오류 2) | 배포 전 검사(게이트)에서 씀 |
## 3. `Doc/IMP-PLAN.md`
[tver/Doc/IMP-PLAN.md](tver/Doc/IMP-PLAN.md) — 엔진 1단계(R1~R4) → 엔진 2단계(R5 · R6) → TUI 1단계(R8) → 설치(R14) → 엔진 3단계(R7 · R11 · R13) → 엔진 4단계(R9 · R10 · R12).
## 4. 단계별 요청문 예
### 엔진 1단계
```text
Doc/SPEC.md 와 Doc/IMP-PLAN.md 를 읽고 "엔진 1단계"만 만들어 줘. uv 프로젝트, 명령 이름 tver, 코드와 화면 글자는 영어.
- workflow.clean(): 노드에서 id, position, webhookId 와 내보내기 도장(versionId, updatedAt ...)을 빼고 노드를 name 순으로. dumps() 는 키 정렬 JSON.
- diff.compare(old, new): 노드를 name 으로 짝지어 +node, -node, ~set(점 경로 key, before, after), +link, -link.
80자 넘거나 여러 줄인 값은 difflib 줄 diff 를 lines 에.
- category: Chat model 노드의 parameters.model.value 는 model, systemMessage · text · jsCode 는 prompt, 나머지와 연결은 flow.
summary 한 줄 "N change(s) · model N · prompt N · flow N".
- tver diff a.json b.json. tests: tests/data 의 helpdesk-v1 → v2 가 7개 · model 1 · prompt 1 · flow 5,
위치 · id 를 바꾸고 노드 순서를 뒤집은 파일은 0개, systemMessage 의 lines 에 "[FAQ-003]" 이 있는 + 줄.
끝나면 IMP-PLAN 체크를 표시하고 확인 명령을 알려 줘.
```
### 엔진 2단계
```text
엔진 2단계만: Store(repo, 기본 ~/.tver/store, --repo, $TVER_REPO).
- save(파일): dumps 한 글이 저장소의 같은 이름 파일과 같으면 "no change", 다르면 쓰고 git commit. 메시지 "<이름>: " + 바로 전 버전과의 summary 한 줄 (처음이면 new).
- log(이름): 커밋 · 시각 · 메시지. show(rev, 이름): git show rev:이름. tver diff <rev1> <rev2> <이름>.
- tests 는 tmp_path 저장소만: 두 번 저장 → 1개, v2 로 바꿔 저장 → 메시지에 "model 1 · prompt 1 · flow 5".
```
### TUI 1단계
```text
TUI 1단계만: tver <파일> 이면 Textual 화면. 왼쪽 ListView 버전 목록, 오른쪽 Tree(노드 → 바뀐 것, 고른 버전 vs 바로 전 버전, worker 로 비교),
트리의 잎을 고르면 아래 Static 에 줄 diff 또는 전 · 후. [s] 지금 파일을 버전으로 저장하고 목록을 다시, [q] 끝.
엔진(diff · store)은 고치지 말고 불러 쓰기만. pytest 로 [s] 뒤 목록이 하나 늘고 트리 제목에 요약이 나오는지.
```
## 5. 결과 확인 (강사 본, 2026-10-27)
| 요구 | 확인 | 결과 |
| --- | --- | --- |
| R1 · R3 · R4 | `tver diff reference/helpdesk-v1.json reference/helpdesk-v2.json` | 7줄 (`flow.py diff`와 같음), systemMessage 줄 diff, `model 1 · prompt 1 · flow 5` |
| R2 | 위치 · id · 순서만 바꾼 파일 (pytest) | 0개 |
| R5 · R6 | 같은 파일 두 번 save → `log` | 1개, 바꿔 저장 → 2개 |
| R7 | 가짜 키(테스트 안에서 만듦)를 넣고 save | 거부, 메시지에 원래 값 없음 |
| R8 | pytest `run_test` | `[s]` 뒤 목록 2개, 트리 제목 요약 |
| R9 | `tver pull` (강사 n8n) | 192 new version(s) |
| R10 | `restore` → 원본과 `diff` | 0 change(s), 버전 수 그대로 |
| R11 | `diff a a` · `a b` · 없는 파일 | 0 · 1 · 2 |
| R12 | `Search FAQ` → `Find FAQ` (pytest) | `renamed` 1개 |
| R13 | `tver save answers` | 5개 저장, golden 테스트 파일 skipped |
| R14 | `uv tool install --editable .`, `/tmp`에서 `tver --help` | 됨 |
오늘 Lab의 helpdesk 정답 여섯 단계를 차례로 저장했을 때의 `log` (위가 최신):
```text
87090f0 helpdesk.json: 1 change(s) · model 0 · prompt 1 · flow 0 ← Lab 03 예제 2 (카나리: Pick release의 jsCode)
9e2ac9a helpdesk.json: 14 change(s) · model 0 · prompt 2 · flow 12 ← Lab 02 과제 2 (응답 코드 · 400)
e0dc13e helpdesk.json: 15 change(s) · model 1 · prompt 1 · flow 13 ← Lab 02 예제 1 (릴리스를 밖에서)
b8461aa helpdesk.json: 12 change(s) · model 0 · prompt 2 · flow 10 ← Lab 01 과제 2 (기본 지시문)
76c5e18 helpdesk.json: 6 change(s) · model 0 · prompt 2 · flow 4 ← Lab 01 과제 1 (지시문 저장소)
7c337b5 helpdesk.json: new ← Lab 01 예제 2
```
- 풀이 거리: 카나리(87090f0)는 `Pick release`의 **Code** 한 칸이라 "prompt 1"로 셉니다. 규칙상 `jsCode`를 지시문으로 셌기 때문입니다. 코드와 지시문을 나눠 세고 싶으면 `code` 분류를 하나 더 두면 됩니다 — 분류 규칙은 **팀이 정하는 것**이라는 예.
## 6. 강사 바이브 코딩 (8교시, 수업 때 적음)
| 주제 | 요청문 요지 | 걸린 시간 · 결과 |
| --- | --- | --- |
| 게이트 붙이기 | "tver save 전에 지정한 테스트 파일로 flow.py gate 를 돌려 FAIL 이면 저장 안 함" | |
| 지시문만 따로 | "systemMessage 를 꺼내 prompts/<노드>.md 로 저장, 지시문 diff 만 보기" | |
| 코드 분류 | "jsCode 는 prompt 가 아니라 code 로 따로 세기" | |