@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.
- package/CLAUDE.md +2 -1
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/info.d.ts +3 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +12 -3
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts +0 -7
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +5 -37
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +4 -6
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/commands/upgrade.d.ts +1 -1
- package/dist/cli/commands/upgrade.d.ts.map +1 -1
- package/dist/cli/commands/upgrade.js +7 -2
- package/dist/cli/commands/upgrade.js.map +1 -1
- package/dist/cli/postinstall/claude-agents.js +1 -1
- package/dist/cli/postinstall/claude-agents.js.map +1 -1
- package/dist/cli/postinstall/constants.d.ts +0 -1
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +0 -8
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +20 -13
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/cli/postinstall.d.ts +0 -3
- package/dist/cli/postinstall.d.ts.map +1 -1
- package/dist/cli/postinstall.js +0 -3
- package/dist/cli/postinstall.js.map +1 -1
- package/dist/cli/setup/InstallHome.d.ts +27 -0
- package/dist/cli/setup/InstallHome.d.ts.map +1 -0
- package/dist/cli/setup/InstallHome.js +105 -0
- package/dist/cli/setup/InstallHome.js.map +1 -0
- package/dist/cli/setup/ProjectSetup.d.ts +0 -8
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +0 -96
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/hooks/scripts/utils.js +32 -2
- package/package.json +1 -1
- package/skills/vibe/SKILL.md +15 -0
- package/skills/vibe.spec/SKILL.md +42 -9
- package/dist/cli/postinstall/cursor-agents.d.ts +0 -13
- package/dist/cli/postinstall/cursor-agents.d.ts.map +0 -1
- package/dist/cli/postinstall/cursor-agents.js +0 -89
- package/dist/cli/postinstall/cursor-agents.js.map +0 -1
- package/dist/cli/postinstall/cursor-rules.d.ts +0 -11
- package/dist/cli/postinstall/cursor-rules.d.ts.map +0 -1
- package/dist/cli/postinstall/cursor-rules.js +0 -205
- package/dist/cli/postinstall/cursor-rules.js.map +0 -1
- package/dist/cli/postinstall/cursor-skills.d.ts +0 -9
- package/dist/cli/postinstall/cursor-skills.d.ts.map +0 -1
- package/dist/cli/postinstall/cursor-skills.js +0 -796
- package/dist/cli/postinstall/cursor-skills.js.map +0 -1
package/hooks/scripts/utils.js
CHANGED
|
@@ -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
|
-
|
|
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)
|
|
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
package/skills/vibe/SKILL.md
CHANGED
|
@@ -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
|
-
-
|
|
126
|
-
- 합리적 기본값을 SPEC 의 Assumptions 로 명시하는 것으로 대체할 수 없다
|
|
125
|
+
#### 3-a. 커버리지 스윕 (내부 단계 — 사용자에게 출력하지 않는다)
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
"이 요구사항으로 SPEC 을 쓸 때 결정이 필요한 지점" 을 **개수 제한 없이** 열거한다. 각 항목에 제안 기본값을 붙인다:
|
|
129
128
|
|
|
130
|
-
|
|
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] 승인 →
|
|
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":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,8CAA8C;AAC9C,MAAM,qBAAqB,GAA0B;IACnD,kBAAkB;IAClB,sBAAsB;CACvB,CAAC;AAEF;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAAe,EAAE,QAAgB;IAC7D,wBAAwB;IACxB,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAE9E,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IAEnD,QAAQ;IACR,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvD,wCAAwC;IACxC,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,SAAS;QACzB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;aACT,KAAK,CAAC,IAAI,CAAC;aACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;aAC9C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;aACpD,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,YAAY,GAA2B;QAC3C,eAAe,EAAE,gJAAgJ,QAAQ,4DAA4D;QACrO,mBAAmB,EAAE,yCAAyC,QAAQ,yFAAyF;KAChK,CAAC;IACF,MAAM,WAAW,GACf,YAAY,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,KAAK,QAAQ,qCAAqC,CAAC;IAEnF,iEAAiE;IACjE,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAE3E,OAAO;QACD,IAAI;SACH,KAAK;eACC,WAAW;;;;;;;;;EASxB,IAAI;CACL,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB,EAAE,eAAuB;IAC/E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,qCAAqC,YAAY,EAAE,CAAC,CAAC;QACjE,OAAO;IACT,CAAC;IAED,SAAS,CAAC,eAAe,CAAC,CAAC;IAE3B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;QACzC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;YAC9D,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACrD,MAAM,aAAa,GAAG,oBAAoB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC1D,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;YAC3E,SAAS,EAAE,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,2BAA2B,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,wBAAwB,SAAS,IAAI,qBAAqB,CAAC,MAAM,YAAY,CAAC,CAAC;AAC7F,CAAC"}
|
|
@@ -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"}
|