hypomnema 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +11 -0
- package/LICENSE +21 -0
- package/README.ko.md +160 -0
- package/README.md +160 -0
- package/commands/.gitkeep +0 -0
- package/commands/crystallize.md +116 -0
- package/commands/doctor.md +66 -0
- package/commands/feedback.md +67 -0
- package/commands/graph.md +54 -0
- package/commands/ingest.md +85 -0
- package/commands/init.md +101 -0
- package/commands/lint.md +55 -0
- package/commands/query.md +55 -0
- package/commands/resume.md +48 -0
- package/commands/stats.md +39 -0
- package/commands/uninstall.md +52 -0
- package/commands/upgrade.md +63 -0
- package/commands/verify.md +60 -0
- package/docs/.gitkeep +0 -0
- package/docs/ARCHITECTURE.md +183 -0
- package/docs/CONTRIBUTING.md +115 -0
- package/docs/TEST-CASES.md +580 -0
- package/hooks/.gitkeep +0 -0
- package/hooks/hooks.json +109 -0
- package/hooks/hypo-auto-commit.mjs +36 -0
- package/hooks/hypo-auto-stage.mjs +30 -0
- package/hooks/hypo-compact-guard.mjs +71 -0
- package/hooks/hypo-cwd-change.mjs +91 -0
- package/hooks/hypo-file-watch.mjs +47 -0
- package/hooks/hypo-first-prompt.mjs +59 -0
- package/hooks/hypo-hot-rebuild.mjs +95 -0
- package/hooks/hypo-lookup.mjs +178 -0
- package/hooks/hypo-personal-check.mjs +195 -0
- package/hooks/hypo-session-start.mjs +141 -0
- package/hooks/hypo-shared.mjs +213 -0
- package/package.json +37 -0
- package/scripts/.gitkeep +0 -0
- package/scripts/bump-version.mjs +53 -0
- package/scripts/crystallize.mjs +153 -0
- package/scripts/doctor.mjs +361 -0
- package/scripts/feedback.mjs +130 -0
- package/scripts/graph.mjs +183 -0
- package/scripts/ingest.mjs +130 -0
- package/scripts/init.mjs +515 -0
- package/scripts/lib/frontmatter.mjs +11 -0
- package/scripts/lib/hypo-ignore.mjs +54 -0
- package/scripts/lib/hypo-root.mjs +53 -0
- package/scripts/lint.mjs +210 -0
- package/scripts/query.mjs +124 -0
- package/scripts/resume.mjs +115 -0
- package/scripts/stats.mjs +132 -0
- package/scripts/uninstall.mjs +188 -0
- package/scripts/upgrade.mjs +538 -0
- package/scripts/verify.mjs +172 -0
- package/skills/.gitkeep +0 -0
- package/skills/crystallize/SKILL.md +85 -0
- package/skills/graph/SKILL.md +54 -0
- package/skills/ingest/SKILL.md +83 -0
- package/skills/lint/SKILL.md +55 -0
- package/skills/query/SKILL.md +58 -0
- package/skills/verify/SKILL.md +92 -0
- package/templates/.gitkeep +0 -0
- package/templates/.hypoignore +18 -0
- package/templates/Home.md +34 -0
- package/templates/Overview.md +50 -0
- package/templates/SCHEMA.md +106 -0
- package/templates/hot.md +22 -0
- package/templates/hypo-automation.md +69 -0
- package/templates/hypo-config.md +41 -0
- package/templates/hypo-guide.md +146 -0
- package/templates/hypo-help.md +53 -0
- package/templates/index.md +44 -0
- package/templates/log.md +25 -0
- package/templates/pages/_index.md +61 -0
- package/templates/projects/_template/hot.md +28 -0
- package/templates/projects/_template/index.md +39 -0
- package/templates/projects/_template/prd.md +29 -0
- package/templates/projects/_template/session-state.md +9 -0
- package/templates/session-state.md +12 -0
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
# Hypomnema — 완성본 테스트 케이스
|
|
2
|
+
|
|
3
|
+
> 이 문서는 BACKLOG.md 갭 분석을 기반으로 작성된 인수 테스트 케이스다.
|
|
4
|
+
> 각 케이스는 **설정(Given) → 실행(When) → 기대 결과(Then)** 형식으로 기술한다.
|
|
5
|
+
> 자동화 가능 항목은 `[AUTO]`, 수동 검증 항목은 `[MANUAL]`로 표시한다.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## TC-01. `/hypo:init` — 기본 설치
|
|
10
|
+
|
|
11
|
+
### TC-01-1. 빈 디렉토리 0-config 설치 [AUTO]
|
|
12
|
+
|
|
13
|
+
**Given**: 빈 디렉토리 `/tmp/wiki-test-01`
|
|
14
|
+
**When**: `node scripts/init.mjs --hypo-dir=/tmp/wiki-test-01 --no-hooks --no-git-init`
|
|
15
|
+
**Then**:
|
|
16
|
+
- `pages/`, `projects/`, `sources/` 디렉토리 존재
|
|
17
|
+
- `hypo-config.md` 존재 (root marker)
|
|
18
|
+
- `index.md`, `hot.md`, `log.md`, `SCHEMA.md`, `hypo-guide.md` 존재
|
|
19
|
+
- `.hypoignore` 존재
|
|
20
|
+
- 이미 존재하는 파일은 덮어쓰지 않음 (idempotent)
|
|
21
|
+
|
|
22
|
+
### TC-01-2. journal 디렉토리 및 추가 템플릿 생성 [AUTO]
|
|
23
|
+
|
|
24
|
+
**Given**: 빈 디렉토리
|
|
25
|
+
**When**: `node scripts/init.mjs --hypo-dir=/tmp/wiki-test-01b --no-hooks --no-git-init`
|
|
26
|
+
**Then**:
|
|
27
|
+
- `journal/daily/`, `journal/weekly/`, `journal/monthly/` 존재
|
|
28
|
+
- `Home.md`, `Overview.md`, `hypo-automation.md`, `hypo-help.md` 복사됨
|
|
29
|
+
- `pages/_index.md` 존재
|
|
30
|
+
- `projects/_template/` 구조 존재
|
|
31
|
+
|
|
32
|
+
### TC-01-3. Git remote 설정 + first commit + push [AUTO]
|
|
33
|
+
|
|
34
|
+
**Given**: git remote URL 입력
|
|
35
|
+
**When**: `node scripts/init.mjs --hypo-dir=/tmp/wiki-git --git-remote=<url>`
|
|
36
|
+
**Then**:
|
|
37
|
+
- `.git/` 존재
|
|
38
|
+
- `git remote get-url origin` = 입력한 URL
|
|
39
|
+
- `git log --oneline` 에 `init: hypomnema wiki` 커밋 존재
|
|
40
|
+
- `git status` clean (push 완료)
|
|
41
|
+
|
|
42
|
+
### TC-01-6. Dry-run 모드 [AUTO]
|
|
43
|
+
|
|
44
|
+
**When**: `node scripts/init.mjs --hypo-dir=/tmp/wiki-dry --dry-run --no-hooks --no-git-init`
|
|
45
|
+
**Then**:
|
|
46
|
+
- 출력에 `[DRY RUN — no changes made]` 포함
|
|
47
|
+
- `/tmp/wiki-dry` 디렉토리 미생성
|
|
48
|
+
|
|
49
|
+
### TC-01-7. Idempotent 재실행 [AUTO]
|
|
50
|
+
|
|
51
|
+
**When**: 동일 경로에 init 2회 실행
|
|
52
|
+
**Then**:
|
|
53
|
+
- 기존 파일 내용 변경 없음
|
|
54
|
+
- 두 번째 실행 결과에 `⊘ Skipped` 항목만 나타남
|
|
55
|
+
|
|
56
|
+
### TC-01-8. Hooks 설치 후 `~/.claude/settings.json` 병합 [AUTO]
|
|
57
|
+
|
|
58
|
+
**When**: `node scripts/init.mjs` (hooks 활성화)
|
|
59
|
+
**Then**:
|
|
60
|
+
- `~/.claude/hooks/` 에 모든 `.mjs` 훅 파일 존재
|
|
61
|
+
- `~/.claude/settings.json`의 `hooks` 객체에 hypo 훅 항목 추가됨
|
|
62
|
+
- 기존 비-hypo 훅 항목은 보존됨
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## TC-02. Plugin 검증
|
|
67
|
+
|
|
68
|
+
### TC-02-1. `claude plugin validate .` 오류 0건 [AUTO]
|
|
69
|
+
|
|
70
|
+
**When**: `claude plugin validate .` (프로젝트 루트에서)
|
|
71
|
+
**Then**: 오류 0건, 경고만 허용
|
|
72
|
+
|
|
73
|
+
### TC-02-2. hooks.json 스키마 형식 [AUTO]
|
|
74
|
+
|
|
75
|
+
**Given**: `hooks/hooks.json`
|
|
76
|
+
**Then**: 각 이벤트 항목이 다음 형식을 따름:
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"hooks": [
|
|
80
|
+
{ "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/<file>.mjs" }
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
(raw string 배열 형식 `["file.mjs"]` 사용 금지)
|
|
85
|
+
|
|
86
|
+
### TC-02-3. skills/ 구조 호환성 [AUTO]
|
|
87
|
+
|
|
88
|
+
**Then**: `skills/` 디렉토리가 플러그인 문서의 skill 배포 스펙과 일치
|
|
89
|
+
(flat `*.md` 또는 `<name>/SKILL.md` 중 결정된 방식 준수)
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## TC-03. `/hypo:ingest` — 소스 인제스트
|
|
94
|
+
|
|
95
|
+
### TC-03-1. 신규 소스 인제스트 [MANUAL]
|
|
96
|
+
|
|
97
|
+
**Given**: 빈 위키 (`index.md` 비어있음)
|
|
98
|
+
**When**: `/hypo:ingest` 실행 → URL 또는 텍스트 입력
|
|
99
|
+
**Then**:
|
|
100
|
+
- `sources/<slug>.<ext>` 에 원본 내용 저장 (수정 없음)
|
|
101
|
+
- `pages/<slug>.md` 생성 (합성본, 원본 복사 아님)
|
|
102
|
+
- frontmatter에 `type: source-summary`, `source: <slug>`, `confidence:`, `evidence_strength: direct` 포함
|
|
103
|
+
- `index.md`에 `[[pages/<slug>]]` 항목 추가됨
|
|
104
|
+
- `log.md`에 ingest 항목 추가됨
|
|
105
|
+
|
|
106
|
+
### TC-03-2. 기존 페이지가 있을 때 업데이트 [MANUAL]
|
|
107
|
+
|
|
108
|
+
**Given**: `pages/kubernetes-networking.md` 이미 존재
|
|
109
|
+
**When**: 동일 주제 소스 인제스트
|
|
110
|
+
**Then**:
|
|
111
|
+
- 기존 파일 덮어쓰기가 아닌 내용 병합
|
|
112
|
+
- `updated:` 필드가 오늘 날짜로 갱신
|
|
113
|
+
- 기존 내용 보존됨 (레거시 내용 유실 없음)
|
|
114
|
+
- `sources/` 에 새 소스 별도 저장
|
|
115
|
+
|
|
116
|
+
### TC-03-3. 레거시 페이지 append/update 시 기존 기록 보존 [MANUAL]
|
|
117
|
+
|
|
118
|
+
**Given**: `verify_by_date`가 만료된 기존 페이지
|
|
119
|
+
**When**: 동일 주제 새 소스 인제스트
|
|
120
|
+
**Then**:
|
|
121
|
+
- 기존 섹션에 `> [2026-MM-DD update]` 형태로 변경 내용 append
|
|
122
|
+
- 기존 내용 삭제 없음
|
|
123
|
+
- `verify_by_date` 갱신됨
|
|
124
|
+
|
|
125
|
+
### TC-03-4. 孤兒 소스(orphaned source) 처리 [MANUAL]
|
|
126
|
+
|
|
127
|
+
**Given**: `sources/`에 페이지 미생성 소스 존재
|
|
128
|
+
**When**: `/hypo:ingest` 실행
|
|
129
|
+
**Then**: "N개의 미처리 소스가 있습니다 — 먼저 인제스트하시겠습니까?" 안내 출력
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## TC-04. hypo-lookup 훅 — 위키 검색 자동 주입
|
|
134
|
+
|
|
135
|
+
### TC-04-1. BM25 hit — 관련 페이지 주입 [AUTO]
|
|
136
|
+
|
|
137
|
+
**Given**: `pages/kubernetes-networking.md` 존재
|
|
138
|
+
**When**: `echo '{"prompt":"kubernetes pod CIDR 할당"}' | node hooks/hypo-lookup.mjs`
|
|
139
|
+
**Then**:
|
|
140
|
+
- 출력에 `[WIKI LOOKUP: 1 page(s) matched]` 포함
|
|
141
|
+
- 페이지 내용(최대 2000자) 주입됨
|
|
142
|
+
- `continue: true`
|
|
143
|
+
|
|
144
|
+
### TC-04-2. BM25 miss — 리서치 권유 메시지 [AUTO]
|
|
145
|
+
|
|
146
|
+
**Given**: 위키에 관련 페이지 없음
|
|
147
|
+
**When**: `echo '{"prompt":"zk-SNARKs 영지식 증명"}' | node hooks/hypo-lookup.mjs`
|
|
148
|
+
**Then**:
|
|
149
|
+
- 출력에 `[WIKI LOOKUP: miss]` 포함
|
|
150
|
+
- "리서치 후 /hypo:ingest 로 저장을 권장합니다" 메시지 포함
|
|
151
|
+
- 가장 가까운 slug 3개 표시
|
|
152
|
+
- `continue: true`
|
|
153
|
+
|
|
154
|
+
### TC-04-3. hit — verify_by_date 만료 경고 [AUTO]
|
|
155
|
+
|
|
156
|
+
**Given**: `verify_by_date`가 과거인 페이지 존재
|
|
157
|
+
**When**: 해당 주제 프롬프트
|
|
158
|
+
**Then**: 주입된 내용에 `⚠ 이 페이지는 verify_by_date가 만료됐습니다` 경고 포함
|
|
159
|
+
|
|
160
|
+
### TC-04-4. `.hypoignore` 패턴 파일 제외 [AUTO]
|
|
161
|
+
|
|
162
|
+
**Given**: `.hypoignore`에 `*private*` 패턴 존재, `pages/my-private-notes.md` 존재
|
|
163
|
+
**When**: 관련 키워드 프롬프트
|
|
164
|
+
**Then**: 해당 페이지 주입 안됨
|
|
165
|
+
|
|
166
|
+
### TC-04-5. 빈 프롬프트 / 키워드 없음 [AUTO]
|
|
167
|
+
|
|
168
|
+
**When**: `echo '{"prompt":""}' | node hooks/hypo-lookup.mjs`
|
|
169
|
+
**Then**: `{"continue": true, "suppressOutput": true}` (오류 없이 통과)
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## TC-05. 세션 종료 커맨드 (session-close)
|
|
174
|
+
|
|
175
|
+
### TC-05-1. session-state.md 업데이트 [MANUAL]
|
|
176
|
+
|
|
177
|
+
**When**: 세션 종료 커맨드 실행
|
|
178
|
+
**Then**:
|
|
179
|
+
- `projects/<name>/session-state.md`의 "다음 이어받기" 항목이 현재 세션 결과 반영
|
|
180
|
+
- 완료된 태스크는 `[x]` 처리
|
|
181
|
+
- 신규 미결 항목 추가
|
|
182
|
+
|
|
183
|
+
### TC-05-2. hot.md 갱신 [MANUAL]
|
|
184
|
+
|
|
185
|
+
**Then**: `projects/<name>/hot.md`에 직전 세션 요약 (~500자) 갱신
|
|
186
|
+
|
|
187
|
+
### TC-05-3. ingest 대상 소스 안내 [MANUAL]
|
|
188
|
+
|
|
189
|
+
**Given**: 세션 중 신뢰할 만한 외부 지식 습득
|
|
190
|
+
**Then**: "인제스트할 소스가 있습니까?" 안내 → `/hypo:ingest` 흐름 연결
|
|
191
|
+
|
|
192
|
+
### TC-05-4. commit/push 상태 확인 [MANUAL]
|
|
193
|
+
|
|
194
|
+
**Then**: git status 확인 → unstaged 변경 있으면 경고 출력
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## TC-06. `/hypo:verify` — 페이지 최신성 검증
|
|
199
|
+
|
|
200
|
+
### TC-06-1. 만료 페이지 감지 [AUTO]
|
|
201
|
+
|
|
202
|
+
**Given**: `verify_by_date: 2026-01-01`이 포함된 페이지
|
|
203
|
+
**When**: `node scripts/verify.mjs --hypo-dir=<path> --due`
|
|
204
|
+
**Then**: 해당 페이지가 만료 목록에 포함됨
|
|
205
|
+
|
|
206
|
+
### TC-06-2. Claude API 의미론적 판정 [MANUAL]
|
|
207
|
+
|
|
208
|
+
**Given**: `ANTHROPIC_API_KEY` 설정됨, `verify_by: "이 내용은 아직 유효한가?"` 포함 페이지
|
|
209
|
+
**When**: `node scripts/verify.mjs --hypo-dir=<path> --model=haiku`
|
|
210
|
+
**Then**:
|
|
211
|
+
- Claude Haiku 호출로 YES/NO 판정
|
|
212
|
+
- NO 판정 시 `pages/open-questions.md`에 해당 항목 append
|
|
213
|
+
- 결과에 `confidence: high|medium|low` 포함
|
|
214
|
+
|
|
215
|
+
### TC-06-3. API key 없을 때 graceful exit [AUTO]
|
|
216
|
+
|
|
217
|
+
**When**: `ANTHROPIC_API_KEY` 미설정 상태로 실행
|
|
218
|
+
**Then**: 오류 메시지 출력 후 exit code 1 (프로그램 crash 없음)
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## TC-07. `/hypo:lint` — 구조 검사
|
|
223
|
+
|
|
224
|
+
### TC-08-1. `commands/lint.md` 커맨드 존재 [MANUAL]
|
|
225
|
+
|
|
226
|
+
**When**: Claude에서 `/hypo:lint` 실행
|
|
227
|
+
**Then**: `scripts/lint.mjs` 호출됨, 결과 출력됨
|
|
228
|
+
|
|
229
|
+
### TC-07-2. Blocker 감지 [AUTO]
|
|
230
|
+
|
|
231
|
+
**Given**: frontmatter에 `title:` 없는 페이지
|
|
232
|
+
**When**: `node scripts/lint.mjs`
|
|
233
|
+
**Then**: `B1` blocker 항목에 해당 파일 표시, exit code 1
|
|
234
|
+
|
|
235
|
+
### TC-07-3. `.hypoignore` 패턴 파일에 민감 정보 → B5 blocker [AUTO]
|
|
236
|
+
|
|
237
|
+
**Given**: `sources/credentials.pem` 존재 (`.hypoignore`에 `*.pem` 패턴)
|
|
238
|
+
**Then**: B5 blocker 발생
|
|
239
|
+
|
|
240
|
+
### TC-07-4. Warning 항목 (non-blocking) [AUTO]
|
|
241
|
+
|
|
242
|
+
**Given**: `verify_by_date`가 6개월 이상 지난 페이지
|
|
243
|
+
**Then**: W 항목에 표시되나 exit code 0
|
|
244
|
+
|
|
245
|
+
### TC-07-5. lint 결과 0 blockers 유지 [AUTO]
|
|
246
|
+
|
|
247
|
+
**When**: `npm run lint`
|
|
248
|
+
**Then**: blockers 0건
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## TC-09. `/hypo:doctor` — 설치 상태 점검
|
|
253
|
+
|
|
254
|
+
### TC-09-1. 정상 설치 상태 [MANUAL]
|
|
255
|
+
|
|
256
|
+
**Given**: init 완료 후
|
|
257
|
+
**When**: `/hypo:doctor`
|
|
258
|
+
**Then**:
|
|
259
|
+
- ✓ Wiki root 탐지 (`hypo-config.md` 존재)
|
|
260
|
+
- ✓ 훅 설치 상태 (모든 훅 파일 존재)
|
|
261
|
+
- ✓ SCHEMA 버전
|
|
262
|
+
- ✓ lint blockers 0
|
|
263
|
+
- ✓ git remote 설정 (설정된 경우)
|
|
264
|
+
|
|
265
|
+
### TC-09-2. 미설치 항목 감지 [MANUAL]
|
|
266
|
+
|
|
267
|
+
**Given**: 훅 파일 일부 삭제
|
|
268
|
+
**Then**: ✗ 항목으로 표시 + 재설치 안내
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## TC-10. `/hypo:upgrade` — 버전 업그레이드
|
|
273
|
+
|
|
274
|
+
### TC-10-1. JSON 출력 필수 필드 [AUTO]
|
|
275
|
+
|
|
276
|
+
**When**: `node scripts/upgrade.mjs --hypo-dir=<path> --json`
|
|
277
|
+
**Then**: 출력 JSON에 `schema`, `hooks`, `settings`, `applied` 필드 존재
|
|
278
|
+
`applied.hooks`와 `applied.settings`가 배열
|
|
279
|
+
|
|
280
|
+
### TC-10-2. 사용자 파일 보존 [AUTO]
|
|
281
|
+
|
|
282
|
+
**Given**: 기존 `pages/my-notes.md` 존재
|
|
283
|
+
**When**: upgrade 실행
|
|
284
|
+
**Then**: `my-notes.md` 내용 변경 없음
|
|
285
|
+
|
|
286
|
+
### TC-10-3. Dry-run 먼저 출력 [MANUAL]
|
|
287
|
+
|
|
288
|
+
**Then**: diff 출력 → 사용자 confirm → 실제 적용 순서
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## TC-11. `/hypo:uninstall` — 제거
|
|
293
|
+
|
|
294
|
+
### TC-11-1. settings.json에서 hypo 훅만 제거 [AUTO]
|
|
295
|
+
|
|
296
|
+
**Given**: settings.json에 hypo 훅 3개 + 비-hypo 훅 2개
|
|
297
|
+
**When**: `node scripts/uninstall.mjs`
|
|
298
|
+
**Then**:
|
|
299
|
+
- hypo 훅 3개 제거됨
|
|
300
|
+
- 비-hypo 훅 2개 보존됨
|
|
301
|
+
- `~/.claude/hooks/hypo-*.mjs` 파일 삭제됨
|
|
302
|
+
|
|
303
|
+
### TC-11-2. Dry-run 기본값 [AUTO]
|
|
304
|
+
|
|
305
|
+
**When**: `node scripts/uninstall.mjs` (--dry-run 없이)
|
|
306
|
+
**Then**: `[DRY RUN]` 모드로 동작, 실제 파일 삭제 없음
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## TC-12. Git 동기화
|
|
311
|
+
|
|
312
|
+
### TC-12-1. SessionStart — git pull [AUTO]
|
|
313
|
+
|
|
314
|
+
**Given**: 원격 레포에 새 커밋 존재, hypo-session-start.mjs 실행
|
|
315
|
+
**When**: `echo '{"cwd":"/some/project"}' | node hooks/hypo-session-start.mjs`
|
|
316
|
+
**Then**:
|
|
317
|
+
- `git pull` 실행됨
|
|
318
|
+
- pull 결과(`pulled N commits` 또는 `up to date`)가 additionalContext에 포함됨
|
|
319
|
+
|
|
320
|
+
### TC-12-2. SessionStart — remote 없을 때 pull 생략 [AUTO]
|
|
321
|
+
|
|
322
|
+
**Given**: git remote 없는 위키
|
|
323
|
+
**Then**: pull 생략, 오류 없이 계속 진행
|
|
324
|
+
|
|
325
|
+
### TC-12-3. Stop 훅 — 자동 commit + push [AUTO]
|
|
326
|
+
|
|
327
|
+
**Given**: 위키 파일 수정됨, remote 존재
|
|
328
|
+
**When**: `node hooks/hypo-auto-commit.mjs`
|
|
329
|
+
**Then**:
|
|
330
|
+
- `git add -A` → `git commit` → `git pull --no-rebase` → `git push` 순서
|
|
331
|
+
- commit 메시지: `auto: YYYY-MM-DD wiki update`
|
|
332
|
+
- staged 없으면 commit 생략, push만
|
|
333
|
+
|
|
334
|
+
### TC-12-4. init — first commit + push [AUTO]
|
|
335
|
+
|
|
336
|
+
**Given**: git remote 설정됨
|
|
337
|
+
**When**: init 완료
|
|
338
|
+
**Then**: `git log --oneline` 에 `init: hypomnema wiki` 커밋 존재, 원격에 push됨
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## TC-13. Lifecycle 훅 — 세션 시작/종료
|
|
343
|
+
|
|
344
|
+
### TC-13-1. SessionStart — 프로젝트 hit (hot.md + session-state.md 주입) [AUTO]
|
|
345
|
+
|
|
346
|
+
**Given**: `projects/my-project/index.md`에 `working_dir: /path/to/project`
|
|
347
|
+
**When**: `echo '{"cwd":"/path/to/project"}' | node hooks/hypo-session-start.mjs`
|
|
348
|
+
**Then**:
|
|
349
|
+
- 출력에 `[WIKI HOT CACHE: project=my-project]` 포함
|
|
350
|
+
- hot.md 내용 (최대 2000자) 주입됨
|
|
351
|
+
- session-state.md 내용 (최대 1000자) 주입됨
|
|
352
|
+
- terminal에 프로젝트 이름 + next 작업 출력됨 (stderr)
|
|
353
|
+
|
|
354
|
+
### TC-13-2. SessionStart — 프로젝트 miss (global hot.md 주입) [AUTO]
|
|
355
|
+
|
|
356
|
+
**Given**: cwd가 어떤 project의 working_dir도 아닌 경우
|
|
357
|
+
**When**: `echo '{"cwd":"/unrelated/path"}' | node hooks/hypo-session-start.mjs`
|
|
358
|
+
**Then**: `[WIKI HOT CACHE: global — no project matched cwd=...]` 포함
|
|
359
|
+
|
|
360
|
+
### TC-13-3. hypo-compact-guard — /compact 차단 [AUTO]
|
|
361
|
+
|
|
362
|
+
**When**: `echo '{"prompt":"/compact"}' | HYPO_DIR=/tmp/no-wiki node hooks/hypo-compact-guard.mjs`
|
|
363
|
+
**Then**: `additionalContext`에 세션 close 체크리스트 안내 포함, `continue: true`
|
|
364
|
+
|
|
365
|
+
### TC-13-4. hypo-compact-guard — 일반 프롬프트 통과 [AUTO]
|
|
366
|
+
|
|
367
|
+
**When**: `echo '{"prompt":"hello world"}' | node hooks/hypo-compact-guard.mjs`
|
|
368
|
+
**Then**: `{"continue": true, "suppressOutput": true}` (차단 없음)
|
|
369
|
+
|
|
370
|
+
### TC-13-5. hypo-personal-check — HYPO_SKIP_GATE=1 통과 [AUTO]
|
|
371
|
+
|
|
372
|
+
**When**: `echo '{}' | HYPO_SKIP_GATE=1 node hooks/hypo-personal-check.mjs`
|
|
373
|
+
**Then**: `{"continue": true, "suppressOutput": true}`
|
|
374
|
+
|
|
375
|
+
### TC-13-6. hypo-personal-check — 위키 없을 때 block [AUTO]
|
|
376
|
+
|
|
377
|
+
**When**: `echo '{}' | HYPO_DIR=/tmp/no-wiki-xxx node hooks/hypo-personal-check.mjs`
|
|
378
|
+
**Then**: `{"decision": "block", ...}` (compact 차단)
|
|
379
|
+
|
|
380
|
+
### TC-13-7. hypo-auto-stage — 위키 파일 수정 후 자동 스테이징 [AUTO]
|
|
381
|
+
|
|
382
|
+
**Given**: `pages/test.md` 수정
|
|
383
|
+
**When**: PostToolUse 훅 실행
|
|
384
|
+
**Then**: `git -C <wiki> status --porcelain` 에 해당 파일이 staged 상태
|
|
385
|
+
|
|
386
|
+
### TC-13-8. CwdChanged — 다른 프로젝트 전환 시 context 재주입 [AUTO]
|
|
387
|
+
|
|
388
|
+
**Given**: project-A → project-B로 cwd 변경
|
|
389
|
+
**When**: `echo '{"cwd":"/path/to/project-b"}' | node hooks/hypo-cwd-change.mjs`
|
|
390
|
+
**Then**: project-B의 hot.md 주입됨, project-A context 미포함
|
|
391
|
+
|
|
392
|
+
### TC-13-9. 동일 프로젝트 subdirectory 이동 시 false re-injection 방지 [AUTO]
|
|
393
|
+
|
|
394
|
+
**Given**: `/project/src` → `/project/tests` 이동 (같은 프로젝트)
|
|
395
|
+
**Then**: 동일 프로젝트 중복 주입 없음
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## TC-14. OMC 의존성 제거 검증
|
|
400
|
+
|
|
401
|
+
### TC-14-1. `OMC_SKIP_WIKI_GATE` 참조 0건 [AUTO]
|
|
402
|
+
|
|
403
|
+
**When**: `grep -r 'OMC_SKIP_WIKI_GATE' hooks/ scripts/ tests/`
|
|
404
|
+
**Then**: 결과 없음 (0건)
|
|
405
|
+
|
|
406
|
+
### TC-14-2. `OMC|oh-my-claude` 참조 0건 (정책 합의 범위 내) [AUTO]
|
|
407
|
+
|
|
408
|
+
**When**: `grep -ri 'oh-my-claude\|omc-teams\|omc skill' hooks/ scripts/ docs/ commands/ skills/`
|
|
409
|
+
**Then**: 결과 없음
|
|
410
|
+
|
|
411
|
+
### TC-14-3. OMC-absent 환경에서 전체 테스트 통과 [AUTO]
|
|
412
|
+
|
|
413
|
+
**When**:
|
|
414
|
+
```bash
|
|
415
|
+
env -i HOME=$HOME PATH=$PATH \
|
|
416
|
+
HYPO_SKIP_GATE="" OMC_SKIP_WIKI_GATE="" OMC_SKIP_HOOKS="" HYPO_DIR="" \
|
|
417
|
+
npm test
|
|
418
|
+
```
|
|
419
|
+
**Then**: 51/51 (또는 그 이상) PASS
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## TC-15. Privacy 보호
|
|
424
|
+
|
|
425
|
+
### TC-15-1. `.hypoignore` 패턴 파일이 hook context에 포함되지 않음 [AUTO]
|
|
426
|
+
|
|
427
|
+
**Given**: `pages/my-private-notes.md`, `.hypoignore`에 `*private*`
|
|
428
|
+
**When**: hypo-lookup.mjs, hypo-session-start.mjs 실행
|
|
429
|
+
**Then**: `my-private-notes.md` 내용이 additionalContext에 없음
|
|
430
|
+
|
|
431
|
+
### TC-15-2. `.hypoignore` 패턴 파일이 lint.mjs에서 스킵됨 [AUTO]
|
|
432
|
+
|
|
433
|
+
**When**: `node scripts/lint.mjs`
|
|
434
|
+
**Then**: `.hypoignore` 매칭 파일은 lint 대상에서 제외됨
|
|
435
|
+
|
|
436
|
+
### TC-15-3. sources/에 민감 파일 → B5 blocker [AUTO]
|
|
437
|
+
|
|
438
|
+
**Given**: `sources/aws-credentials.pem` (`.hypoignore`에 `*.pem`)
|
|
439
|
+
**When**: `node scripts/lint.mjs`
|
|
440
|
+
**Then**: B5 blocker 발생, exit 1
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## TC-16. CI 검증
|
|
445
|
+
|
|
446
|
+
### TC-16-1. 전체 CI jobs green [AUTO]
|
|
447
|
+
|
|
448
|
+
**When**: main 브랜치 push
|
|
449
|
+
**Then**: 다음 jobs 모두 green:
|
|
450
|
+
- `test` (Node 18, 20, 22)
|
|
451
|
+
- `lint-runner`
|
|
452
|
+
- `init-snapshot`
|
|
453
|
+
- `upgrade-snapshot`
|
|
454
|
+
- `privacy` (personal, shared, public)
|
|
455
|
+
- `replay`
|
|
456
|
+
- `omc-absent` (Node 18, 20, 22)
|
|
457
|
+
- `uninstall` (신규)
|
|
458
|
+
|
|
459
|
+
### TC-16-2. nightly verify-pages [AUTO]
|
|
460
|
+
|
|
461
|
+
**When**: nightly 실행 (또는 `workflow_dispatch`)
|
|
462
|
+
**Then**: `verify-pages` job 실행됨, `ANTHROPIC_API_KEY` 없으면 skip (graceful)
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## TC-17. `/hypo:query` — 질의 응답
|
|
467
|
+
|
|
468
|
+
### TC-17-1. 근거 있는 답변 + wikilink 인용 [MANUAL]
|
|
469
|
+
|
|
470
|
+
**Given**: 관련 페이지 3개 존재
|
|
471
|
+
**When**: `/hypo:query "pod CIDR 할당은 어떻게 동작하나요?"`
|
|
472
|
+
**Then**:
|
|
473
|
+
- 답변에 `[[page-slug]]` 형식의 인용 포함
|
|
474
|
+
- 페이지 내용에 없는 추정 내용 없음 (근거 기반)
|
|
475
|
+
|
|
476
|
+
### TC-17-2. 관련 페이지 없을 때 솔직한 미답변 [MANUAL]
|
|
477
|
+
|
|
478
|
+
**Given**: 위키에 관련 내용 없음
|
|
479
|
+
**Then**: "관련 위키 페이지가 없습니다" 안내 + 인제스트 권유
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## TC-18. `/hypo:crystallize` — 지식 합성
|
|
484
|
+
|
|
485
|
+
### TC-18-1. 태그 클러스터 합성 [MANUAL]
|
|
486
|
+
|
|
487
|
+
**Given**: `kubernetes` 태그 페이지 5개 분산
|
|
488
|
+
**When**: `/hypo:crystallize` → 태그 클러스터 선택
|
|
489
|
+
**Then**:
|
|
490
|
+
- `pages/syntheses/kubernetes.md` 생성 (`type: synthesis`)
|
|
491
|
+
- 각 페이지에 `[[syntheses/kubernetes]]` backlink 추가
|
|
492
|
+
- `index.md` 업데이트
|
|
493
|
+
|
|
494
|
+
### TC-18-2. 세션 종료와 crystallize 혼동 없음 [MANUAL]
|
|
495
|
+
|
|
496
|
+
**When**: `/hypo:crystallize` 실행
|
|
497
|
+
**Then**: 세션 close 체크리스트(session-state 업데이트, hot.md 갱신 등)를 실행하지 않음
|
|
498
|
+
→ 세션 종료는 별도 커맨드로 분리
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## TC-19. stats / graph
|
|
503
|
+
|
|
504
|
+
### TC-19-1. `/hypo:stats` — 핵심 지표 출력 [MANUAL]
|
|
505
|
+
|
|
506
|
+
**Then**: 다음 지표 포함:
|
|
507
|
+
- 총 페이지 수
|
|
508
|
+
- link density (페이지당 평균 outbound link)
|
|
509
|
+
- orphan count
|
|
510
|
+
- broken link count
|
|
511
|
+
- stale page count (`verify_by_date` 만료)
|
|
512
|
+
- hot-cache freshness
|
|
513
|
+
- source/week (최근 4주 ingest 속도)
|
|
514
|
+
|
|
515
|
+
### TC-19-2. `/hypo:graph` — JSON 생성 [AUTO]
|
|
516
|
+
|
|
517
|
+
**When**: `node scripts/graph.mjs --hypo-dir=<path>`
|
|
518
|
+
**Then**: `graph.json` 생성, `nodes`/`edges` 배열 포함
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
## TC-20. 외부 사용자 dogfooding (E2E)
|
|
523
|
+
|
|
524
|
+
### TC-20-1. 완전 신규 설치 → 첫 인제스트 → 쿼리 [MANUAL]
|
|
525
|
+
|
|
526
|
+
**Given**: Hypomnema 미설치 환경 (다른 macOS 머신 또는 VM)
|
|
527
|
+
**When**:
|
|
528
|
+
1. `npm install -g hypomnema` 또는 `npx hypomnema`
|
|
529
|
+
2. `/hypo:init` (remote URL 입력)
|
|
530
|
+
3. URL 하나 `/hypo:ingest`
|
|
531
|
+
4. `/hypo:query` 로 방금 인제스트한 내용 질의
|
|
532
|
+
|
|
533
|
+
**Then**:
|
|
534
|
+
- 각 단계 오류 없음
|
|
535
|
+
- 쿼리 결과가 인제스트한 내용을 근거로 답변
|
|
536
|
+
- Claude Code 재시작 후 훅이 자동으로 동작
|
|
537
|
+
|
|
538
|
+
### TC-20-2. OMC 미설치 환경 [MANUAL]
|
|
539
|
+
|
|
540
|
+
**Given**: OMC(`oh-my-claudecode`) 설치 안 된 환경
|
|
541
|
+
**Then**: 모든 `/hypo:*` 커맨드 정상 동작, OMC 관련 오류 없음
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## 부록 A. 테스트 환경 설정
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
# 테스트용 임시 wiki 디렉토리
|
|
549
|
+
export TEST_WIKI=/tmp/hypo-test-$(date +%s)
|
|
550
|
+
|
|
551
|
+
# OMC-absent 환경
|
|
552
|
+
env -i HOME=$HOME PATH=$PATH HYPO_DIR=$TEST_WIKI npm test
|
|
553
|
+
|
|
554
|
+
# plugin 검증
|
|
555
|
+
claude plugin validate .
|
|
556
|
+
|
|
557
|
+
# 전체 CI 로컬 실행
|
|
558
|
+
npm test && npm run lint
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## 부록 B. 테스트 픽스처 위치
|
|
562
|
+
|
|
563
|
+
| 픽스처 | 경로 |
|
|
564
|
+
|---|---|
|
|
565
|
+
| hook replay 픽스처 | `tests/fixtures/hooks/` |
|
|
566
|
+
| lint 케이스 픽스처 | `tests/fixtures/lint/` |
|
|
567
|
+
| init snapshot | `tests/fixtures/init/` |
|
|
568
|
+
| e2e PreCompact 시나리오 | `tests/fixtures/e2e/` |
|
|
569
|
+
|
|
570
|
+
## 부록 C. 합격 기준 (DoD)
|
|
571
|
+
|
|
572
|
+
| 항목 | 기준 |
|
|
573
|
+
|---|---|
|
|
574
|
+
| `npm test` | 전체 PASS (0 fail) |
|
|
575
|
+
| `npm run lint` | blocker 0건 |
|
|
576
|
+
| `claude plugin validate .` | 오류 0건 |
|
|
577
|
+
| CI all jobs | green |
|
|
578
|
+
| OMC 참조 | 0건 (정책 합의 범위 내) |
|
|
579
|
+
| 외부 dogfooding | 1인 이상 PASS |
|
|
580
|
+
| README "로컬 저장" vs Git-sync | 모순 없음 |
|
package/hooks/.gitkeep
ADDED
|
File without changes
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"hooks": [
|
|
6
|
+
{
|
|
7
|
+
"type": "command",
|
|
8
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-session-start.mjs",
|
|
9
|
+
"timeout": 30
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"UserPromptSubmit": [
|
|
15
|
+
{
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-first-prompt.mjs",
|
|
20
|
+
"timeout": 10
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"hooks": [
|
|
26
|
+
{
|
|
27
|
+
"type": "command",
|
|
28
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-lookup.mjs",
|
|
29
|
+
"timeout": 30
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"hooks": [
|
|
35
|
+
{
|
|
36
|
+
"type": "command",
|
|
37
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-compact-guard.mjs",
|
|
38
|
+
"timeout": 10
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"PreCompact": [
|
|
44
|
+
{
|
|
45
|
+
"hooks": [
|
|
46
|
+
{
|
|
47
|
+
"type": "command",
|
|
48
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-personal-check.mjs",
|
|
49
|
+
"timeout": 30
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"PostToolUse": [
|
|
55
|
+
{
|
|
56
|
+
"hooks": [
|
|
57
|
+
{
|
|
58
|
+
"type": "command",
|
|
59
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-auto-stage.mjs",
|
|
60
|
+
"timeout": 10
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"Stop": [
|
|
66
|
+
{
|
|
67
|
+
"hooks": [
|
|
68
|
+
{
|
|
69
|
+
"type": "command",
|
|
70
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-hot-rebuild.mjs",
|
|
71
|
+
"timeout": 30
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"hooks": [
|
|
77
|
+
{
|
|
78
|
+
"type": "command",
|
|
79
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-auto-commit.mjs",
|
|
80
|
+
"timeout": 60
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"CwdChanged": [
|
|
86
|
+
{
|
|
87
|
+
"hooks": [
|
|
88
|
+
{
|
|
89
|
+
"type": "command",
|
|
90
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-cwd-change.mjs",
|
|
91
|
+
"timeout": 10
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
],
|
|
96
|
+
"FileChanged": [
|
|
97
|
+
{
|
|
98
|
+
"hooks": [
|
|
99
|
+
{
|
|
100
|
+
"type": "command",
|
|
101
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/hypo-file-watch.mjs",
|
|
102
|
+
"timeout": 10
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"shared": ["hypo-shared.mjs"]
|
|
109
|
+
}
|