@su-record/vibe 3.2.15 → 3.2.17

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.
Files changed (61) hide show
  1. package/CLAUDE.md +2 -1
  2. package/dist/cli/commands/index.d.ts +1 -1
  3. package/dist/cli/commands/index.d.ts.map +1 -1
  4. package/dist/cli/commands/index.js +1 -1
  5. package/dist/cli/commands/index.js.map +1 -1
  6. package/dist/cli/commands/info.d.ts +3 -1
  7. package/dist/cli/commands/info.d.ts.map +1 -1
  8. package/dist/cli/commands/info.js +12 -3
  9. package/dist/cli/commands/info.js.map +1 -1
  10. package/dist/cli/commands/init.d.ts +0 -7
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +5 -37
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/update.d.ts.map +1 -1
  15. package/dist/cli/commands/update.js +4 -6
  16. package/dist/cli/commands/update.js.map +1 -1
  17. package/dist/cli/commands/upgrade.d.ts +1 -1
  18. package/dist/cli/commands/upgrade.d.ts.map +1 -1
  19. package/dist/cli/commands/upgrade.js +7 -2
  20. package/dist/cli/commands/upgrade.js.map +1 -1
  21. package/dist/cli/postinstall/claude-agents.js +1 -1
  22. package/dist/cli/postinstall/claude-agents.js.map +1 -1
  23. package/dist/cli/postinstall/constants.d.ts +0 -1
  24. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  25. package/dist/cli/postinstall/constants.js +0 -8
  26. package/dist/cli/postinstall/constants.js.map +1 -1
  27. package/dist/cli/postinstall/main.d.ts.map +1 -1
  28. package/dist/cli/postinstall/main.js +20 -13
  29. package/dist/cli/postinstall/main.js.map +1 -1
  30. package/dist/cli/postinstall.d.ts +0 -3
  31. package/dist/cli/postinstall.d.ts.map +1 -1
  32. package/dist/cli/postinstall.js +0 -3
  33. package/dist/cli/postinstall.js.map +1 -1
  34. package/dist/cli/setup/InstallHome.d.ts +27 -0
  35. package/dist/cli/setup/InstallHome.d.ts.map +1 -0
  36. package/dist/cli/setup/InstallHome.js +105 -0
  37. package/dist/cli/setup/InstallHome.js.map +1 -0
  38. package/dist/cli/setup/ProjectSetup.d.ts +0 -8
  39. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  40. package/dist/cli/setup/ProjectSetup.js +0 -96
  41. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  42. package/dist/cli/setup.d.ts +1 -1
  43. package/dist/cli/setup.d.ts.map +1 -1
  44. package/dist/cli/setup.js +1 -1
  45. package/dist/cli/setup.js.map +1 -1
  46. package/hooks/scripts/utils.js +32 -2
  47. package/package.json +1 -1
  48. package/skills/vibe/SKILL.md +15 -0
  49. package/skills/vibe.spec/SKILL.md +42 -9
  50. package/dist/cli/postinstall/cursor-agents.d.ts +0 -13
  51. package/dist/cli/postinstall/cursor-agents.d.ts.map +0 -1
  52. package/dist/cli/postinstall/cursor-agents.js +0 -89
  53. package/dist/cli/postinstall/cursor-agents.js.map +0 -1
  54. package/dist/cli/postinstall/cursor-rules.d.ts +0 -11
  55. package/dist/cli/postinstall/cursor-rules.d.ts.map +0 -1
  56. package/dist/cli/postinstall/cursor-rules.js +0 -205
  57. package/dist/cli/postinstall/cursor-rules.js.map +0 -1
  58. package/dist/cli/postinstall/cursor-skills.d.ts +0 -9
  59. package/dist/cli/postinstall/cursor-skills.d.ts.map +0 -1
  60. package/dist/cli/postinstall/cursor-skills.js +0 -796
  61. package/dist/cli/postinstall/cursor-skills.js.map +0 -1
@@ -201,11 +201,18 @@ function npmRootFallback() {
201
201
  }
202
202
  const homeDir = os.homedir();
203
203
  const candidates = [
204
+ // node 바이너리에서 유도 — prefix 를 어떻게 잡았든 따라간다. 가장 확실하므로 먼저 본다.
205
+ // (/usr/bin/node → /usr/lib/node_modules, ~/.local/bin/node → ~/.local/lib/node_modules)
206
+ path.resolve(path.dirname(process.execPath), '..', 'lib', 'node_modules'),
204
207
  '/usr/local/lib/node_modules',
208
+ '/usr/lib/node_modules', // 배포판 npm (apt/dnf, prefix=/usr)
209
+ path.join(homeDir, '.local', 'lib', 'node_modules'), // 사용자 prefix — 격리 서버에서 흔하다
205
210
  path.join(homeDir, '.npm-global', 'lib', 'node_modules'),
206
211
  path.join(homeDir, '.nvm', 'versions', 'node', process.version, 'lib', 'node_modules'),
207
212
  ];
208
- return candidates.find(p => fs.existsSync(p)) || candidates[0];
213
+ // 패키지가 실제로 있는 후보를 고른다 — 디렉토리 존재만으로는 엉뚱한 prefix 를 집는다
214
+ const withPackage = candidates.find(p => fs.existsSync(path.join(p, '@su-record', 'vibe')));
215
+ return withPackage || candidates.find(p => fs.existsSync(p)) || candidates[0];
209
216
  }
210
217
 
211
218
  // L1 인-프로세스 캐시
@@ -248,6 +255,23 @@ function hasRuntimeDeps(packageRoot) {
248
255
  * 프로세스 내 메모이제이션: getToolsBaseUrl/getLibBaseUrl/getCliBaseUrl이 한 훅
249
256
  * 프로세스에서 각각 호출되면 최악 6회 동기 stat이 반복되므로 결과를 캐싱한다.
250
257
  */
258
+ /**
259
+ * 패키지 루트 해석 실패를 1회만 보고한다.
260
+ *
261
+ * 훅 호출부는 전부 fail-open(try/catch) 이라, 해석이 틀려도 사용자에게는
262
+ * "아무 일도 안 일어남" 으로만 보인다 — 조용히 죽은 가드다. 진단 단서를 남긴다.
263
+ */
264
+ let _warnedUnresolved = false;
265
+ function warnUnresolvedPackageRoot(subpath, candidates) {
266
+ if (_warnedUnresolved) return;
267
+ _warnedUnresolved = true;
268
+ process.stderr.write(
269
+ `[vibe] 패키지 루트를 찾지 못했습니다 (${subpath}).\n`
270
+ + ` 확인한 경로: ${candidates.join(', ')}\n`
271
+ + ` VIBE_PATH 를 설치 경로로 지정하거나 'vibe upgrade' 로 재설치하세요.\n`
272
+ );
273
+ }
274
+
251
275
  const _packageUrlCache = new Map();
252
276
  function getPackageUrl(subpath, probeFile) {
253
277
  const cacheKey = `${subpath}|${probeFile}`;
@@ -267,7 +291,13 @@ function getPackageUrl(subpath, probeFile) {
267
291
  break;
268
292
  }
269
293
  }
270
- if (result === null) result = toFileUrl(path.join(globalRoot, subpath));
294
+ if (result === null) {
295
+ // 후보가 전부 검증에 실패했다 — 지어낸 경로를 돌려주면 이후 모든 import 가
296
+ // 조용히 실패하고 도구 계층 전체가 죽은 채로 돈다. 경로는 종전대로 돌려주되
297
+ // (호출부는 fail-open 이므로 동작은 유지) 무슨 일이 있었는지는 남긴다.
298
+ result = toFileUrl(path.join(globalRoot, subpath));
299
+ warnUnresolvedPackageRoot(subpath, candidates);
300
+ }
271
301
  _packageUrlCache.set(cacheKey, result);
272
302
  return result;
273
303
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "3.2.15",
3
+ "version": "3.2.17",
4
4
  "description": "AI Coding Framework for Claude Code — 7+ agents, 52 skills, multi-LLM orchestration",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -177,6 +177,21 @@ Phase 4: /vibe.verify → 검증
177
177
  직역 하네스가 문자 그대로 실행하려다 실패한다 (dual-harness doctrine: 명시성 공통분모).
178
178
  스킬 **이름과 인자**가 계약이고, 그것을 실제 호출로 바꾸는 것은 각 하네스의 몫이다.
179
179
 
180
+ **세션 경계 (`vibe.spec` Step 6 의 `[2]` 선택):** 사용자가 승인 메시지에서 `[2] 승인 → 새 세션에서 run` 을 골랐으면 **체인을 계속하지 않는다.** `vibe.run` 을 호출하지 말고 아래를 출력한 뒤 종료한다:
181
+
182
+ ```
183
+ ✅ SPEC 승인 완료: {feature-name}
184
+ .vibe/specs/{feature-name}.md · .vibe/features/{feature-name}.feature
185
+
186
+ 새 세션에서 재개하세요:
187
+ /vibe.run "{feature-name}"
188
+ ```
189
+
190
+ - execution packet 은 여기서 컴파일하지 않는다 — 새 세션의 `vibe.run` Step 1-0 이 담당한다 (컴파일 시점 불변).
191
+ - 별도 핸드오프 아티팩트를 만들지 않는다 — SPEC·Feature·`.vibe/.last-feature` 가 재개에 필요한 전부다.
192
+ - `automationLevel: autonomous` 에서는 `[2]` 가 선택될 수 없으므로(권고 자체를 띄우지 않음) 이 분기는 발생하지 않는다.
193
+ - 이 종료는 stuck 도 실행 실패도 아니다 — 루프 종료 사유가 아니라 **사용자 선택에 의한 정상 일시 중단**으로 기록한다.
194
+
180
195
  각 phase 종료 후 JUDGE 단계:
181
196
  - 게이트 통과 (**측정된** P1=0 ∧ verifyPassed) → 루프 종료, Phase 5 보고. 판정된 P1(리뷰어 findings)은 단독으로 게이트를 막지 않는다 — SSOT: `vibe/rules/loop-contract.md` Judge 권한 경계
182
197
  - 게이트 미통과 → RECORD(run-ledger + loop-history.jsonl) 후 다음 ANCHOR로
@@ -118,16 +118,32 @@ Worker: Find existing implementations related to [FEATURE]. Return the tech stac
118
118
  relevant files, and patterns in under 200 tokens.
119
119
  ```
120
120
 
121
- ### 3. Clarify — 진짜 모호할 때만
121
+ ### 3. Clarify — 넓게 훑고, 좁게 묻는다
122
122
 
123
- 별도 인터뷰 단계가 아니다. 요구사항·첨부·레거시 아티팩트·코드베이스 컨텍스트로 답을 합리적으로 정할 있으면 **묻지 않는다**. 다음 조건을 모두 만족할 때만 질문한다:
123
+ 별도 인터뷰 단계가 아니다. 단계가 제한하는 것은 **질문 수가 아니라 사용자가 반드시 답해야 하는 수**다. 결정 지점은 전부 훑되(3-a), 사용자에게는 최대 3개만 묻는다(3-b). 나머지는 전부 Assumptions 로 편입된다 — 훑지 않아서 SPEC 에 아예 존재하지 않는 결정 지점을 없애는 것이 목적이다.
124
124
 
125
- - 답에 따라 Done Criteria 나 구현 방향이 실제로 갈라진다 (인증 방식, 데이터 모델의 필수 필드, 외부 연동 여부 등)
126
- - 합리적 기본값을 SPEC 의 Assumptions 로 명시하는 것으로 대체할 수 없다
125
+ #### 3-a. 커버리지 스윕 (내부 단계 사용자에게 출력하지 않는다)
127
126
 
128
- 질문할 때는 **한 번에 묶어서** (번호 목록, 최대 5개), 질문에 제안 기본값을 붙인다. `automationLevel: autonomous` 질문 없이 기본값을 채택하고 전부 SPEC 의 Assumptions 섹션에 기록한다.
127
+ "이 요구사항으로 SPEC 결정이 필요한 지점" **개수 제한 없이** 열거한다. 항목에 제안 기본값을 붙인다:
129
128
 
130
- 사소한 값(타임아웃, 페이지 크기, 재시도 횟수 등)은 묻지 말고 상식적 기본값을 채택 + Assumptions 에 기록.
129
+ ```
130
+ {결정 지점} → {제안 기본값} → {갈라짐: Done Criteria 가 실제로 달라지는가 yes/no}
131
+ ```
132
+
133
+ 훑을 축(최소): 범위 경계 · 데이터 모델의 필수 필드 · 외부 연동 여부 · 인증/권한 · 오류 처리 방침 · 수치 파라미터(타임아웃·크기·재시도) · 하위 호환 · 기존 테스트/계약 영향 · 산출물 위치 · 언어·표기 규약.
134
+
135
+ 이 목록 자체는 출력하지 않는다. 출력 대상은 3-b 의 질문과 최종 SPEC 의 Assumptions 뿐이다.
136
+
137
+ #### 3-b. 답변 요청 (사용자에게 출력)
138
+
139
+ 3-a 결과에서 `갈라짐: yes` 인 항목만 남기고, 그중 **최대 3개**만 묻는다. 3개를 넘으면 영향 범위가 큰 순으로 3개를 고르고 나머지는 기본값을 채택한다.
140
+
141
+ - 질문은 **한 번에 묶어서** (번호 목록), 각 질문에 제안 기본값을 붙인다.
142
+ - **3-b 로 묻지 않은 3-a 항목은 전부** SPEC 의 Assumptions 섹션에 기록한다. 누락 0건 — Step 5 체크리스트가 이를 점검한다.
143
+ - Assumptions 를 사용자에게 보일 때(Step 6)는 3개 이하면 전부, 3개 초과면 핵심 3개 + `그 외 N건은 SPEC 참조` 로 접어서 제시한다.
144
+ - `automationLevel: autonomous` 면 3-b 질문을 생략하고 3-a 전 항목의 기본값을 채택해 Assumptions 에 기록한다.
145
+
146
+ 사소한 값(타임아웃, 페이지 크기, 재시도 횟수 등)은 3-a 에서 `갈라짐: no` 로 판정해 묻지 말고 상식적 기본값 + Assumptions 로 처리한다.
131
147
 
132
148
  ### 4. Write SPEC — one pass
133
149
 
@@ -164,6 +180,7 @@ relevant files, and patterns in under 200 tokens.
164
180
  - [ ] 수치가 필요한 곳에 수치가 있는가 (제한·타임아웃·크기 — 없으면 기본값 + Assumptions)
165
181
  - [ ] Out of Scope 가 비어 있지 않은가
166
182
  - [ ] 요구사항에 있던 것 중 SPEC 에서 빠진 것이 없는가
183
+ - [ ] 3-a 커버리지 스윕에서 나온 결정 지점이 **전부** 3-b 질문 또는 Assumptions 중 하나로 귀결됐는가 (누락 0건)
167
184
  - [ ] 설계 선택지가 있었던 결정에 기각 대안이 Rejected Alternatives (Traps) 로 남았는가 — 기계적 사유 포함 (production 만; 선택지가 없었으면 통과)
168
185
  - [ ] 헤더에 `Stakes:` 필드가 있고, demo/prototype 인데 SPEC 이 분할·대형화되지 않았는가
169
186
 
@@ -179,14 +196,28 @@ SPEC 요약(Goal, Done Criteria, 시나리오 수, Out of Scope, 열린 Assumpti
179
196
  Stakes: {demo|prototype|production} — {판정 근거 1구}
180
197
  Done Criteria: {N}개 (전부 결정론 게이트)
181
198
  Scenarios: {M}개 · Out of Scope: {K}항목
182
- Assumptions: {요약 또는 "없음"}
199
+ Assumptions: {3개 이하면 전부 · 초과면 핵심 3개 + "그 외 N건은 SPEC 참조"}
183
200
 
184
201
  승인하면 이 SPEC 이 루프의 Done 정의가 됩니다.
185
- [1] 승인 → 구현 진행 [2] 수정 요청 [3] 중단
202
+ [1] 승인 → 세션에서 계속 [2] 승인 새 세션에서 run{권장 표시}
203
+ [3] 수정 요청 [4] 중단
186
204
  ```
187
205
 
188
206
  - 수정 요청 → 반영 후 재제시 (사용자 주도 반복 — 자동 루프 아님).
189
- - `automationLevel: autonomous` → 승인 생략, 요약만 출력하고 진행.
207
+ - `automationLevel: autonomous` → 승인 생략, 요약만 출력하고 `[1]` 로 진행 (세션 경계 권고 없음 — 비대화형이라 리셋 불가).
208
+
209
+ #### 세션 경계 선택지 (`[2]`)
210
+
211
+ 승인 게이트에 **편승하는 선택지**다. 별도 프롬프트를 만들지 않는다 — loop-contract 의 "의무적 사람 개입은 SPEC 승인 1회" 불변식을 지킨다.
212
+
213
+ - **선택지 개수는 항상 4개로 고정한다.** 트리거 충족 여부와 무관하게 `[1]`~`[4]` 를 그대로 출력한다. 조건에 따라 다르게 출력하지 않는다.
214
+ - 아래 관측 가능한 프록시 중 **하나라도** 충족하면 `{권장 표시}` 자리에 ` (권장)` 을 넣는다. 하나도 충족하지 않으면 빈 문자열로 둔다:
215
+ 1. 명확화 왕복 ≥ 2회 — 3-b 질문 배치 1회 = 1왕복, SPEC 수정 요청 1회 = 1왕복
216
+ 2. SPEC 수정 요청 ≥ 1회
217
+ 3. 분할 SPEC (5+ phase 로 폴더 분할됨)
218
+ - 컨텍스트 사용률(%)은 트리거로 쓰지 않는다 — 하네스 중립적으로 읽을 수단이 없어 CC 와 Codex 에서 권고 시점이 갈린다.
219
+ - `[2]` 를 권하는 근거: 명확화 왕복·SPEC 수정 과정·Rejected Alternatives 논의 텍스트가 구현 컨텍스트에 잔류하면 노이즈가 된다. 특히 기각안은 SPEC 에 "기각됨" 으로 적혀 있어도 대화 히스토리에는 살아있는 형태로 남는다.
220
+ - `[2]` 선택 시 SPEC·Feature·`.vibe/.last-feature` 는 이미 디스크에 있으므로 별도 핸드오프 아티팩트를 만들지 않는다. execution packet 은 지금 컴파일하지 않는다 — 새 세션의 `vibe.run` Step 1-0 이 그대로 담당한다.
190
221
  - 승인 후 SPEC 변경은 코드 변경과 같은 커밋으로 (SPEC-First — `vibe.run` 참조).
191
222
  - **Stakes 편승 질문**: 디스패처의 stakes 판정(`vibe/rules/loop-contract.md` Stakes 표)이 불확실하거나 신호가 상충하면, 이 승인 메시지에 stakes 확인 질문 1개(demo/prototype/production 선택지)를 포함한다. 별도의 추가 확인 왕복을 만들지 않는다 — 승인 게이트가 유일한 질문 지점이다.
192
223
 
@@ -198,6 +229,8 @@ SPEC 요약(Goal, Done Criteria, 시나리오 수, Out of Scope, 열린 Assumpti
198
229
  | Feature (BDD) | `.vibe/features/{feature-name}.feature` (또는 분할 폴더) |
199
230
  | Pointer | `.vibe/.last-feature` |
200
231
 
232
+ Step 6 에서 `[2]` (새 세션에서 run) 를 선택했으면 여기서 종료하고, 새 세션에서 `/vibe.run "{feature-name}"` 로 재개한다 — 위 세 파일이 재개에 필요한 전부다.
233
+
201
234
  승인된 SPEC 은 루프의 ANCHOR 로 쓰인다: `/vibe.run` 이 시나리오 단위로 구현·검증하고, `/vibe.verify` 가 Done Criteria 를 판정해 `.vibe/metrics/run-ledger.json` 의 `verifyPassed` 를 기록한다. 게이트 통과 여부는 항상 run-ledger·테스트 exit code 가 판정한다.
202
235
 
203
236
  ## Next Step
@@ -1,13 +0,0 @@
1
- /**
2
- * Cursor 에이전트 변환 및 설치
3
- *
4
- * 통합 리뷰어 2종(code-reviewer, security-reviewer)을 Cursor 서브에이전트로 설치.
5
- * (구 12종 리뷰어 매트릭스는 harness-review-2026-07-01 P2-1 에서 통합됨 —
6
- * survivor 에이전트는 goal+constraints 본문이라 Checklist/Output 섹션 파싱 대신
7
- * 본문 전체를 그대로 싣는다.)
8
- */
9
- /**
10
- * Cursor 서브에이전트 설치
11
- */
12
- export declare function installCursorAgents(agentsSource: string, cursorAgentsDir: string): void;
13
- //# sourceMappingURL=cursor-agents.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor-agents.d.ts","sourceRoot":"","sources":["../../../src/cli/postinstall/cursor-agents.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAgEH;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,CA0BvF"}
@@ -1,89 +0,0 @@
1
- /**
2
- * Cursor 에이전트 변환 및 설치
3
- *
4
- * 통합 리뷰어 2종(code-reviewer, security-reviewer)을 Cursor 서브에이전트로 설치.
5
- * (구 12종 리뷰어 매트릭스는 harness-review-2026-07-01 P2-1 에서 통합됨 —
6
- * survivor 에이전트는 goal+constraints 본문이라 Checklist/Output 섹션 파싱 대신
7
- * 본문 전체를 그대로 싣는다.)
8
- */
9
- import path from 'path';
10
- import fs from 'fs';
11
- import { ensureDir } from './fs-utils.js';
12
- import { CURSOR_MODEL_MAPPING } from './constants.js';
13
- /** Cursor 로 내보낼 리뷰어 에이전트 (agents/ 최상위 파일명) */
14
- const CURSOR_REVIEWER_FILES = [
15
- 'code-reviewer.md',
16
- 'security-reviewer.md',
17
- ];
18
- /**
19
- * VIBE 에이전트를 Cursor 서브에이전트 형식으로 변환
20
- */
21
- function convertAgentToCursor(content, filename) {
22
- // Windows CRLF → LF 정규화
23
- const normalizedContent = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
24
- const name = path.basename(filename, '.md');
25
- const model = CURSOR_MODEL_MAPPING[name] || 'auto';
26
- // 제목 추출
27
- const titleMatch = normalizedContent.match(/^# (.+)$/m);
28
- const title = titleMatch ? titleMatch[1].trim() : name;
29
- // Role 섹션 추출 (## Role 다음 내용을 다음 ## 전까지)
30
- const roleMatch = normalizedContent.match(/## Role\s*\n([\s\S]*?)(?=\n## )/);
31
- const roleLines = roleMatch
32
- ? roleMatch[1]
33
- .split('\n')
34
- .filter((line) => line.trim().startsWith('- '))
35
- .map((line) => line.trim().replace(/^- /, '').trim())
36
- .slice(0, 3)
37
- : [];
38
- const roleDesc = roleLines.join(', ');
39
- const descriptions = {
40
- 'code-reviewer': `Parameterized code reviewer (focus: correctness, architecture, performance, complexity, data-integrity, test-coverage, idioms, git-history). ${roleDesc}. Use proactively after code edits with an explicit focus.`,
41
- 'security-reviewer': `Threat-model-first security reviewer. ${roleDesc}. Use proactively after changes involving authentication, user input, or data handling.`,
42
- };
43
- const description = descriptions[name] || `${title}. ${roleDesc}. Use proactively after code edits.`;
44
- // 기존 frontmatter 제거 후 본문 유지 (survivor 에이전트는 goal+constraints 본문)
45
- const body = normalizedContent.replace(/^---\n[\s\S]*?\n---\n/, '').trim();
46
- return `---
47
- name: ${name}
48
- model: ${model}
49
- description: ${description}
50
- ---
51
-
52
- ## When Invoked
53
-
54
- 1. Run \`git diff\` to see recent changes
55
- 2. Focus on modified files relevant to this review
56
- 3. Begin review immediately without asking questions
57
-
58
- ${body}
59
- `;
60
- }
61
- /**
62
- * Cursor 서브에이전트 설치
63
- */
64
- export function installCursorAgents(agentsSource, cursorAgentsDir) {
65
- if (!fs.existsSync(agentsSource)) {
66
- console.log(` ⚠️ agents directory not found: ${agentsSource}`);
67
- return;
68
- }
69
- ensureDir(cursorAgentsDir);
70
- let installed = 0;
71
- for (const file of CURSOR_REVIEWER_FILES) {
72
- const sourcePath = path.join(agentsSource, file);
73
- if (!fs.existsSync(sourcePath)) {
74
- console.warn(` ⚠️ Cursor reviewer source missing: ${file}`);
75
- continue;
76
- }
77
- try {
78
- const content = fs.readFileSync(sourcePath, 'utf-8');
79
- const cursorContent = convertAgentToCursor(content, file);
80
- fs.writeFileSync(path.join(cursorAgentsDir, file), cursorContent, 'utf-8');
81
- installed++;
82
- }
83
- catch (err) {
84
- console.warn(` ⚠️ Failed to convert ${file}: ${err.message}`);
85
- }
86
- }
87
- console.log(` 📦 Cursor agents: ${installed}/${CURSOR_REVIEWER_FILES.length} installed`);
88
- }
89
- //# sourceMappingURL=cursor-agents.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor-agents.js","sourceRoot":"","sources":["../../../src/cli/postinstall/cursor-agents.ts"],"names":[],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Cursor 룰 변환 및 생성
3
- */
4
- /**
5
- * Cursor 프로젝트 룰 템플릿 생성 (VIBE 언어 룰 기반)
6
- * @param cursorRulesDir - 룰 파일 저장 경로
7
- * @param detectedStacks - 감지된 기술 스택 배열 (예: ['typescript-react', 'python-fastapi'])
8
- * @param languagesDir - VIBE 언어 룰 디렉토리 (optional)
9
- */
10
- export declare function generateCursorRules(cursorRulesDir: string, detectedStacks?: string[], languagesDir?: string): void;
11
- //# sourceMappingURL=cursor-rules.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor-rules.d.ts","sourceRoot":"","sources":["../../../src/cli/postinstall/cursor-rules.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiGH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,cAAc,GAAE,MAAM,EAAO,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,IAAI,CAiIN"}
@@ -1,205 +0,0 @@
1
- /**
2
- * Cursor 룰 변환 및 생성
3
- */
4
- import path from 'path';
5
- import fs from 'fs';
6
- import { ensureDir } from './fs-utils.js';
7
- import { STACK_TO_LANGUAGE_FILE, LANGUAGE_GLOBS, LANGUAGE_RULE_PREFIXES, LEGACY_RULE_FILES, } from './constants.js';
8
- /**
9
- * VIBE 언어 룰 파일을 Cursor .mdc 형식으로 변환
10
- */
11
- function convertLanguageRuleToCursor(content, filename) {
12
- // Windows CRLF → LF 정규화
13
- const normalizedContent = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
14
- // 제목 추출
15
- const titleMatch = normalizedContent.match(/^# (.+)$/m);
16
- const title = titleMatch ? titleMatch[1].trim() : filename.replace('.md', '');
17
- // 설명 생성 - 제목에서 "Quality Rules" 제거하고 간결하게
18
- const description = title
19
- .replace(' Quality Rules', ' coding standards')
20
- .replace(' Specific Rules', ' best practices');
21
- // glob 패턴 가져오기
22
- const globs = LANGUAGE_GLOBS[filename] || '**/*';
23
- // .mdc frontmatter + 본문
24
- return `---
25
- description: ${description} - complexity limits, type safety, error handling
26
- globs: "${globs}"
27
- alwaysApply: false
28
- ---
29
-
30
- ${normalizedContent}
31
- `;
32
- }
33
- /**
34
- * VIBE 언어 룰 디렉토리에서 .mdc 파일 생성
35
- * @param languagesDir - VIBE 언어 룰 디렉토리 (~/.claude/vibe/languages/ 또는 패키지 내 languages/)
36
- * @param outputDir - Cursor 룰 출력 디렉토리 (~/.cursor/rules-template/)
37
- * @param detectedStacks - 감지된 기술 스택 배열 (예: ['typescript-react', 'python-fastapi'])
38
- * @returns 생성된 파일 수
39
- */
40
- function generateCursorRulesFromCoreLanguages(languagesDir, outputDir, detectedStacks = []) {
41
- if (!fs.existsSync(languagesDir)) {
42
- return 0;
43
- }
44
- ensureDir(outputDir);
45
- // 감지된 스택에 해당하는 언어 파일 결정
46
- const targetFiles = new Set();
47
- if (detectedStacks.length === 0) {
48
- // 스택 감지 없으면 공통 룰만 생성 (hardcoded fallback)
49
- return 0;
50
- }
51
- for (const stack of detectedStacks) {
52
- const languageFile = STACK_TO_LANGUAGE_FILE[stack.toLowerCase()];
53
- if (languageFile) {
54
- targetFiles.add(languageFile);
55
- }
56
- }
57
- let generated = 0;
58
- for (const file of targetFiles) {
59
- const sourcePath = path.join(languagesDir, file);
60
- if (!fs.existsSync(sourcePath)) {
61
- continue;
62
- }
63
- try {
64
- const content = fs.readFileSync(sourcePath, 'utf-8');
65
- const mdcContent = convertLanguageRuleToCursor(content, file);
66
- const destPath = path.join(outputDir, file.replace('.md', '.mdc'));
67
- fs.writeFileSync(destPath, mdcContent, 'utf-8');
68
- generated++;
69
- }
70
- catch {
71
- // 무시 - 파일 읽기/쓰기 실패
72
- }
73
- }
74
- return generated;
75
- }
76
- /**
77
- * Cursor 프로젝트 룰 템플릿 생성 (VIBE 언어 룰 기반)
78
- * @param cursorRulesDir - 룰 파일 저장 경로
79
- * @param detectedStacks - 감지된 기술 스택 배열 (예: ['typescript-react', 'python-fastapi'])
80
- * @param languagesDir - VIBE 언어 룰 디렉토리 (optional)
81
- */
82
- export function generateCursorRules(cursorRulesDir, detectedStacks = [], languagesDir) {
83
- ensureDir(cursorRulesDir);
84
- // 0. 기존 언어 룰 + 레거시 파일 정리
85
- try {
86
- const existingFiles = fs.readdirSync(cursorRulesDir).filter(f => f.endsWith('.mdc'));
87
- for (const file of existingFiles) {
88
- const isLanguageRule = LANGUAGE_RULE_PREFIXES.some(prefix => file.startsWith(prefix));
89
- const isLegacy = LEGACY_RULE_FILES.includes(file);
90
- if (isLanguageRule || isLegacy) {
91
- fs.unlinkSync(path.join(cursorRulesDir, file));
92
- }
93
- }
94
- }
95
- catch {
96
- // 무시
97
- }
98
- // 1. VIBE 언어 룰에서 .mdc 생성 시도
99
- let coreRulesGenerated = 0;
100
- if (languagesDir && detectedStacks.length > 0) {
101
- coreRulesGenerated = generateCursorRulesFromCoreLanguages(languagesDir, cursorRulesDir, detectedStacks);
102
- }
103
- // 2. 공통 룰 (모든 프로젝트에 적용)
104
- const commonRules = [
105
- {
106
- filename: 'code-quality.mdc',
107
- content: `---
108
- description: General code quality rules for all files
109
- alwaysApply: true
110
- ---
111
-
112
- # Code Quality Rules
113
-
114
- ## Core Principles
115
- - **Modify only requested scope** - Don't touch unrelated code
116
- - **Preserve existing style** - Follow project conventions
117
- - **Keep working code** - No unnecessary refactoring
118
-
119
- ## Forbidden Patterns
120
- - No \`console.log\` in production code (remove after debugging)
121
- - No hardcoded strings/numbers → Extract to constants
122
- - No commented-out code in commits
123
- - No incomplete code without TODO marker
124
-
125
- ## Naming Conventions
126
- - Variables/functions: camelCase
127
- - Classes/types: PascalCase
128
- - Constants: UPPER_SNAKE_CASE
129
- - Files: kebab-case or PascalCase (match project style)
130
-
131
- ## Function Design
132
- - Single responsibility per function
133
- - Max 5 parameters (use object for more)
134
- - Descriptive names (verb + noun)
135
- - Document non-obvious behavior
136
-
137
- ## Complexity Limits
138
- | Metric | Limit |
139
- |--------|-------|
140
- | Function length | ≤30 lines (recommended), ≤50 lines (max) |
141
- | Nesting depth | ≤3 levels |
142
- | Parameters | ≤5 |
143
- | Cyclomatic complexity | ≤10 |
144
-
145
- ## Dependency Management
146
- - Avoid circular dependencies
147
- - Keep loose coupling (depend on interfaces)
148
- - High cohesion (group related functions)
149
- `,
150
- },
151
- {
152
- filename: 'security-checklist.mdc',
153
- content: `---
154
- description: Security checklist for code changes
155
- globs: "**/*.ts,**/*.tsx,**/*.js,**/*.jsx,**/*.py,**/*.go,**/*.rs,**/*.java,**/*.kt,**/*.swift"
156
- alwaysApply: false
157
- ---
158
-
159
- # Security Checklist
160
-
161
- ## Input Validation
162
- - [ ] Validate all user inputs
163
- - [ ] Sanitize data before database queries
164
- - [ ] Use parameterized queries (prevent SQL injection)
165
-
166
- ## Authentication
167
- - [ ] Secure password handling (never store plain text)
168
- - [ ] Session management is secure
169
- - [ ] Tokens have appropriate expiry
170
-
171
- ## Data Protection
172
- - [ ] Sensitive data is encrypted
173
- - [ ] API keys not committed to code
174
- - [ ] Error messages don't leak sensitive info
175
-
176
- ## OWASP Top 10 Awareness
177
- - Injection (SQL, XSS, Command)
178
- - Broken authentication
179
- - Sensitive data exposure
180
- - XML external entities (XXE)
181
- - Broken access control
182
- - Security misconfiguration
183
- - Cross-site scripting (XSS)
184
- - Insecure deserialization
185
- - Using components with known vulnerabilities
186
- - Insufficient logging & monitoring
187
- `,
188
- },
189
- ];
190
- let commonUpdated = 0;
191
- for (const rule of commonRules) {
192
- const destPath = path.join(cursorRulesDir, rule.filename);
193
- try {
194
- fs.writeFileSync(destPath, rule.content, 'utf-8');
195
- commonUpdated++;
196
- }
197
- catch {
198
- // 무시 - 권한 문제 등
199
- }
200
- }
201
- const totalUpdated = coreRulesGenerated + commonUpdated;
202
- const stackInfo = detectedStacks.length > 0 ? ` (${detectedStacks.slice(0, 3).join(', ')}${detectedStacks.length > 3 ? '...' : ''})` : '';
203
- console.log(` 📏 Cursor rules: ${totalUpdated} updated (${coreRulesGenerated} language + ${commonUpdated} common)${stackInfo}`);
204
- }
205
- //# sourceMappingURL=cursor-rules.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor-rules.js","sourceRoot":"","sources":["../../../src/cli/postinstall/cursor-rules.ts"],"names":[],"mappings":"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"}
@@ -1,9 +0,0 @@
1
- /**
2
- * Cursor Skills 생성 (VIBE 커맨드 → Cursor 스킬 변환)
3
- */
4
- /**
5
- * Cursor Skills 생성 (VIBE 커맨드 → Cursor 스킬 변환)
6
- * 설치 경로: ~/.cursor/skills/[skill-name]/SKILL.md
7
- */
8
- export declare function generateCursorSkills(cursorSkillsDir: string): void;
9
- //# sourceMappingURL=cursor-skills.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor-skills.d.ts","sourceRoot":"","sources":["../../../src/cli/postinstall/cursor-skills.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAixBlE"}