@su-record/vibe 2.9.2 → 2.9.3
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 +30 -10
- package/README.ko.md +90 -25
- package/README.md +139 -25
- package/agents/teams/figma/figma-builder.md +29 -1
- package/agents/teams/review-debate-team.md +1 -1
- package/commands/vibe.analyze.md +324 -170
- package/commands/vibe.figma.md +549 -34
- package/commands/vibe.harness.md +177 -0
- package/commands/vibe.run.md +44 -27
- package/commands/vibe.scaffold.md +195 -0
- package/commands/vibe.spec.md +375 -947
- package/commands/vibe.trace.md +17 -0
- package/commands/vibe.verify.md +19 -10
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +29 -1
- 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 -2
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/postinstall/constants.d.ts +1 -1
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +6 -1
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/setup/ProjectSetup.d.ts +12 -1
- package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
- package/dist/cli/setup/ProjectSetup.js +259 -72
- 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/figma-guard.js +220 -0
- package/package.json +1 -1
- package/skills/arch-guard/SKILL.md +1 -1
- package/skills/capability-loop/SKILL.md +106 -2
- package/skills/chub-usage/SKILL.md +43 -43
- package/skills/claude-md-guide/SKILL.md +175 -175
- package/skills/design-teach/SKILL.md +33 -33
- package/skills/devlog/SKILL.md +38 -38
- package/skills/event-comms/SKILL.md +23 -13
- package/skills/event-ops/SKILL.md +28 -19
- package/skills/event-planning/SKILL.md +13 -1
- package/skills/priority-todos/SKILL.md +1 -1
- package/skills/vibe.figma/SKILL.md +234 -154
- package/skills/vibe.figma.convert/SKILL.md +123 -112
- package/skills/vibe.figma.extract/SKILL.md +141 -129
- package/skills/vibe.interview/SKILL.md +358 -0
- package/skills/vibe.interview/checklists/api.md +101 -0
- package/skills/vibe.interview/checklists/feature.md +88 -0
- package/skills/vibe.interview/checklists/library.md +95 -0
- package/skills/vibe.interview/checklists/mobile.md +89 -0
- package/skills/vibe.interview/checklists/webapp.md +97 -0
- package/skills/vibe.interview/checklists/website.md +99 -0
- package/skills/vibe.plan/SKILL.md +216 -0
- package/skills/vibe.spec/SKILL.md +1155 -0
- package/{commands/vibe.spec.review.md → skills/vibe.spec.review/SKILL.md} +269 -108
- package/vibe/templates/claudemd-template.md +74 -0
- package/vibe/templates/constitution-template.md +15 -0
- package/vibe/templates/plan-template.md +194 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Figma Guard — vibe.figma 작업 시 스킬 우회 차단
|
|
4
|
+
*
|
|
5
|
+
* 차단 대상:
|
|
6
|
+
* 1. /tmp/{feature}/ 하위에 자체 정제/생성 스크립트(.mjs/.js) 작성
|
|
7
|
+
* → figma-refine.js / figma-to-scss.js 호출하라고 차단
|
|
8
|
+
* 2. SCSS 파일을 직접 작성 (figma-to-scss.js 호출 흔적 없이)
|
|
9
|
+
* 3. Vue/React <style> 블록에 figma 관련 SCSS 클래스 직접 작성
|
|
10
|
+
*
|
|
11
|
+
* 작동 조건:
|
|
12
|
+
* - tool: Write 또는 Edit
|
|
13
|
+
* - file_path가 figma 작업 컨텍스트에 해당
|
|
14
|
+
*
|
|
15
|
+
* Exit codes:
|
|
16
|
+
* 0 — 통과
|
|
17
|
+
* 2 — 차단
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'fs';
|
|
21
|
+
import path from 'path';
|
|
22
|
+
import os from 'os';
|
|
23
|
+
|
|
24
|
+
// ─── stdin 읽기 ─────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
function readStdinSync() {
|
|
27
|
+
try {
|
|
28
|
+
if (process.stdin.isTTY) return null;
|
|
29
|
+
const fd = fs.openSync('/dev/stdin', 'r');
|
|
30
|
+
const buf = Buffer.alloc(1024 * 1024); // 1MB
|
|
31
|
+
const bytesRead = fs.readSync(fd, buf, 0, buf.length, null);
|
|
32
|
+
fs.closeSync(fd);
|
|
33
|
+
if (bytesRead > 0) {
|
|
34
|
+
return JSON.parse(buf.toString('utf-8', 0, bytesRead));
|
|
35
|
+
}
|
|
36
|
+
} catch { /* fallback */ }
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ─── 검사 1: /tmp/{feature}/ 자체 작성 스크립트 ─────────────────────
|
|
41
|
+
|
|
42
|
+
const FORBIDDEN_TMP_SCRIPT_PATTERNS = [
|
|
43
|
+
/\/tmp\/[^/]+\/refine[\w-]*\.(mjs|js)$/i,
|
|
44
|
+
/\/tmp\/[^/]+\/.*sections.*\.(mjs|js)$/i,
|
|
45
|
+
/\/tmp\/[^/]+\/.*to-scss.*\.(mjs|js)$/i,
|
|
46
|
+
/\/tmp\/[^/]+\/.*generate-scss.*\.(mjs|js)$/i,
|
|
47
|
+
/\/tmp\/[^/]+\/analyze-tree\.(mjs|js)$/i,
|
|
48
|
+
/\/tmp\/[^/]+\/analyze-section\.(mjs|js)$/i,
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
function checkForbiddenTmpScript(filePath) {
|
|
52
|
+
if (!filePath) return null;
|
|
53
|
+
for (const pattern of FORBIDDEN_TMP_SCRIPT_PATTERNS) {
|
|
54
|
+
if (pattern.test(filePath)) {
|
|
55
|
+
return {
|
|
56
|
+
block: true,
|
|
57
|
+
reason: `자체 작성 figma 스크립트 금지: ${path.basename(filePath)}`,
|
|
58
|
+
suggestion: 'figma-refine.js / figma-to-scss.js / figma-validate.js 사용. ' +
|
|
59
|
+
'결과가 마음에 안 들면 ~/.vibe/hooks/scripts/figma-*.js 자체를 수정하세요.'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── 검사 2: SCSS 직접 작성 ─────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Figma 작업 컨텍스트인지 판단:
|
|
70
|
+
* - 현재 작업 디렉토리 또는 file_path에 figma 관련 흔적이 있어야 함
|
|
71
|
+
* - /tmp/ 하위에 sections.json이 존재 → 활성 figma 작업으로 판단
|
|
72
|
+
*/
|
|
73
|
+
function isFigmaContext() {
|
|
74
|
+
try {
|
|
75
|
+
const tmpDirs = fs.readdirSync('/tmp', { withFileTypes: true });
|
|
76
|
+
for (const entry of tmpDirs) {
|
|
77
|
+
if (!entry.isDirectory()) continue;
|
|
78
|
+
const moSections = path.join('/tmp', entry.name, 'mo-main', 'sections.json');
|
|
79
|
+
const pcSections = path.join('/tmp', entry.name, 'pc-main', 'sections.json');
|
|
80
|
+
if (fs.existsSync(moSections) || fs.existsSync(pcSections)) {
|
|
81
|
+
return { active: true, feature: entry.name };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} catch { /* ignore */ }
|
|
85
|
+
return { active: false };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* SCSS 파일 작성 시도 검사
|
|
90
|
+
*/
|
|
91
|
+
function checkScssWrite(filePath, content) {
|
|
92
|
+
if (!filePath) return null;
|
|
93
|
+
if (!filePath.endsWith('.scss')) return null;
|
|
94
|
+
|
|
95
|
+
// figma 컨텍스트가 아니면 통과
|
|
96
|
+
const ctx = isFigmaContext();
|
|
97
|
+
if (!ctx.active) return null;
|
|
98
|
+
|
|
99
|
+
// 자동 생성 표시 코멘트 있으면 통과
|
|
100
|
+
if (typeof content === 'string' && content.includes('Auto-generated from sections.json')) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 빈 파일 또는 @import만 있는 경우 통과
|
|
105
|
+
if (typeof content === 'string') {
|
|
106
|
+
const meaningfulLines = content
|
|
107
|
+
.split('\n')
|
|
108
|
+
.map(l => l.trim())
|
|
109
|
+
.filter(l => l && !l.startsWith('//') && !l.startsWith('/*'));
|
|
110
|
+
const hasOnlyImports = meaningfulLines.every(l =>
|
|
111
|
+
l.startsWith('@import') || l.startsWith('@use') || l.startsWith('@forward')
|
|
112
|
+
);
|
|
113
|
+
if (hasOnlyImports) return null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
block: true,
|
|
118
|
+
reason: `SCSS 직접 작성 금지: ${filePath}`,
|
|
119
|
+
suggestion: `figma-to-scss.js로 생성하세요:\n` +
|
|
120
|
+
` node ~/.vibe/hooks/scripts/figma-to-scss.js \\\n` +
|
|
121
|
+
` /tmp/${ctx.feature}/{bp}-main/sections.json \\\n` +
|
|
122
|
+
` --out=$(dirname ${filePath})`
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ─── 검사 3: Vue/React <style> 블록에 CSS 값 작성 ───────────────────
|
|
127
|
+
|
|
128
|
+
function checkVueStyleBlock(filePath, content) {
|
|
129
|
+
if (!filePath) return null;
|
|
130
|
+
if (!/\.(vue|jsx|tsx)$/.test(filePath)) return null;
|
|
131
|
+
|
|
132
|
+
const ctx = isFigmaContext();
|
|
133
|
+
if (!ctx.active) return null;
|
|
134
|
+
|
|
135
|
+
// 파일 경로에 feature 이름이 있는지 확인
|
|
136
|
+
if (!filePath.includes(ctx.feature)) return null;
|
|
137
|
+
|
|
138
|
+
if (typeof content !== 'string') return null;
|
|
139
|
+
|
|
140
|
+
// <style ...> ... </style> 블록 추출
|
|
141
|
+
const styleBlocks = content.match(/<style[^>]*>([\s\S]*?)<\/style>/g);
|
|
142
|
+
if (!styleBlocks || styleBlocks.length === 0) return null;
|
|
143
|
+
|
|
144
|
+
for (const block of styleBlocks) {
|
|
145
|
+
const inner = block.replace(/<style[^>]*>/, '').replace(/<\/style>/, '');
|
|
146
|
+
const meaningfulLines = inner
|
|
147
|
+
.split('\n')
|
|
148
|
+
.map(l => l.trim())
|
|
149
|
+
.filter(l => l && !l.startsWith('//') && !l.startsWith('/*'));
|
|
150
|
+
|
|
151
|
+
// @import / @use 만 있으면 통과
|
|
152
|
+
const hasOnlyImports = meaningfulLines.every(l =>
|
|
153
|
+
l.startsWith('@import') || l.startsWith('@use') || l.startsWith('@forward')
|
|
154
|
+
);
|
|
155
|
+
if (hasOnlyImports) continue;
|
|
156
|
+
|
|
157
|
+
// CSS 값으로 보이는 라인 검출 (px, rem, color, flex 등)
|
|
158
|
+
const hasCssValue = meaningfulLines.some(l =>
|
|
159
|
+
/:\s*[^;]*(?:px|rem|em|%|vh|vw|#[0-9a-fA-F]|rgba?\(|flex|grid|absolute|relative|inherit)/.test(l)
|
|
160
|
+
);
|
|
161
|
+
if (hasCssValue) {
|
|
162
|
+
return {
|
|
163
|
+
block: true,
|
|
164
|
+
reason: `Vue/React <style> 블록에 CSS 직접 작성 금지: ${path.basename(filePath)}`,
|
|
165
|
+
suggestion: `<style> 블록은 @import만 허용:\n` +
|
|
166
|
+
` <style lang="scss" scoped>\n` +
|
|
167
|
+
` @import '~/assets/scss/${ctx.feature}/index.scss';\n` +
|
|
168
|
+
` </style>`
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ─── 메인 ───────────────────────────────────────────────────────────
|
|
177
|
+
|
|
178
|
+
const stdinPayload = readStdinSync();
|
|
179
|
+
if (!stdinPayload) {
|
|
180
|
+
process.exit(0);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const toolName = stdinPayload.tool_name || '';
|
|
184
|
+
const toolInput = stdinPayload.tool_input || {};
|
|
185
|
+
|
|
186
|
+
// Write 또는 Edit만 검사
|
|
187
|
+
if (toolName !== 'Write' && toolName !== 'Edit') {
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const filePath = toolInput.file_path || '';
|
|
192
|
+
const content = toolInput.content || toolInput.new_string || '';
|
|
193
|
+
|
|
194
|
+
// 3단계 검사
|
|
195
|
+
const checks = [
|
|
196
|
+
checkForbiddenTmpScript(filePath),
|
|
197
|
+
checkScssWrite(filePath, content),
|
|
198
|
+
checkVueStyleBlock(filePath, content),
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
const violations = checks.filter(c => c !== null);
|
|
202
|
+
|
|
203
|
+
if (violations.length === 0) {
|
|
204
|
+
process.exit(0);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 차단
|
|
208
|
+
const messages = ['🚫 FIGMA GUARD: 스킬 규칙 위반'];
|
|
209
|
+
for (const v of violations) {
|
|
210
|
+
messages.push('');
|
|
211
|
+
messages.push(` ${v.reason}`);
|
|
212
|
+
messages.push(` 💡 ${v.suggestion}`);
|
|
213
|
+
}
|
|
214
|
+
messages.push('');
|
|
215
|
+
messages.push('⛔ vibe.figma 작업 중에는 스크립트 파이프라인을 우회하지 마세요.');
|
|
216
|
+
messages.push(' ~/.vibe/hooks/scripts/figma-{refine,to-scss,validate}.js만 사용.');
|
|
217
|
+
|
|
218
|
+
// PreToolUse hook은 stderr 출력 + exit 2로 차단
|
|
219
|
+
console.error(messages.join('\n'));
|
|
220
|
+
process.exit(2);
|
package/package.json
CHANGED
|
@@ -178,4 +178,4 @@ The test generator reads this file and adds custom rules to the test suite.
|
|
|
178
178
|
- `vibe init` → auto-detect and generate initial arch-guard tests
|
|
179
179
|
- `vibe update` → refresh rules if directory structure changed
|
|
180
180
|
- Pre-commit hook → run arch-guard tests before commit
|
|
181
|
-
-
|
|
181
|
+
- `vibe.review` (skill) → architecture-reviewer checks against arch-rules.json
|
|
@@ -107,6 +107,92 @@ Based on classification, build the appropriate artifact:
|
|
|
107
107
|
4. If the capability is a test, verify it FAILS without the fix
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
+
**Termination branches:**
|
|
111
|
+
- ✅ **Capability prevents the failure** → Step 5 PERSIST
|
|
112
|
+
- ❌ **Capability does NOT prevent the failure** → Step 4.5 ESCALATE (re-diagnose or ask user)
|
|
113
|
+
|
|
114
|
+
### Step 4.5: ESCALATE — When VERIFY Fails
|
|
115
|
+
|
|
116
|
+
> **Problem**: The built capability didn't actually prevent the failure. This usually means the initial diagnosis was wrong (picked `Tool` when it needed `Guardrail`), or the failure has multiple missing capabilities.
|
|
117
|
+
>
|
|
118
|
+
> **Do NOT silently proceed** — a sub-standard capability log pollutes `.claude/vibe/capabilities-log.md` and the failure will recur.
|
|
119
|
+
|
|
120
|
+
**Escalation loop:**
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
tried = [current_diagnosis.category] # e.g., ["Tool"]
|
|
124
|
+
|
|
125
|
+
while True:
|
|
126
|
+
# Re-diagnose excluding already-tried categories
|
|
127
|
+
next_diagnosis = diagnose(failure, exclude=tried)
|
|
128
|
+
|
|
129
|
+
if next_diagnosis is None:
|
|
130
|
+
# All 5 categories (Tool/Guardrail/Abstraction/Documentation/Feedback) exhausted
|
|
131
|
+
escalate_to_user(failure, tried)
|
|
132
|
+
break
|
|
133
|
+
|
|
134
|
+
if next_diagnosis.category in tried:
|
|
135
|
+
# Stuck: diagnose keeps returning the same category
|
|
136
|
+
escalate_to_user(failure, tried)
|
|
137
|
+
break
|
|
138
|
+
|
|
139
|
+
tried.append(next_diagnosis.category)
|
|
140
|
+
capability = build(next_diagnosis)
|
|
141
|
+
|
|
142
|
+
if verify(capability, failure):
|
|
143
|
+
persist(capability)
|
|
144
|
+
return # Success — go to Step 5
|
|
145
|
+
|
|
146
|
+
# Still failing — next iteration
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**User escalation prompt (interactive mode):**
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
153
|
+
⚠️ CAPABILITY LOOP STUCK
|
|
154
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
155
|
+
|
|
156
|
+
Failure: {original failure description}
|
|
157
|
+
|
|
158
|
+
Tried capabilities (all failed to prevent the failure):
|
|
159
|
+
❌ Tool: {what was built, why it didn't work}
|
|
160
|
+
❌ Guardrail: {what was built, why it didn't work}
|
|
161
|
+
❌ Documentation: {what was built, why it didn't work}
|
|
162
|
+
|
|
163
|
+
Automated diagnosis has run out of angles. This failure may require
|
|
164
|
+
human judgment (process issue, cross-category solution, or external factor).
|
|
165
|
+
|
|
166
|
+
How would you like to proceed?
|
|
167
|
+
1. Suggest a different angle (e.g., "this is a process issue", "needs Tool+Guardrail combination")
|
|
168
|
+
→ Attempt custom approach per user instruction, then enter next verify
|
|
169
|
+
2. "manual" — resolve this failure via manual intervention, end capability loop
|
|
170
|
+
(record "escalated to manual" in capabilities-log.md)
|
|
171
|
+
3. "abort" — give up, record failure only
|
|
172
|
+
(record "diagnosis exhausted" in capabilities-log.md, do not halt the rest of the workflow)
|
|
173
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**ultrawork mode exception:**
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
if ultrawork_mode:
|
|
180
|
+
# Skip user prompt: try all 5 categories in sequence, record final state
|
|
181
|
+
all_tried_exhausted = exhaust_all_categories(failure, tried)
|
|
182
|
+
record_failure_to_log(
|
|
183
|
+
status="diagnosis_exhausted",
|
|
184
|
+
tried=all_tried_exhausted,
|
|
185
|
+
failure=failure
|
|
186
|
+
)
|
|
187
|
+
return # Proceed without blocking downstream workflow
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Rollback of failed builds:**
|
|
191
|
+
|
|
192
|
+
- Each failed capability build should be rolled back before trying the next category (unless it's non-destructive documentation).
|
|
193
|
+
- For code additions (tool/guardrail/abstraction): `git checkout -- {files}` or delete created files.
|
|
194
|
+
- For docs-only additions: leave in place (low risk) but note in escalation prompt.
|
|
195
|
+
|
|
110
196
|
### Step 5: PERSIST — Record for Future Reference
|
|
111
197
|
|
|
112
198
|
Save the capability-building decision:
|
|
@@ -126,11 +212,14 @@ Update `.claude/vibe/capabilities-log.md`:
|
|
|
126
212
|
```markdown
|
|
127
213
|
## {date} — {capability-name}
|
|
128
214
|
|
|
215
|
+
**Status**: resolved | escalated_to_manual | diagnosis_exhausted
|
|
129
216
|
**Failure**: {what happened}
|
|
130
217
|
**Missing**: {what capability was absent}
|
|
131
|
-
**
|
|
218
|
+
**Tried**: {list of categories attempted, e.g., [Tool, Guardrail]}
|
|
219
|
+
**Built**: {what was created (if resolved)}
|
|
132
220
|
**Files**: {list}
|
|
133
|
-
**Prevents**: {what class of failures this prevents}
|
|
221
|
+
**Prevents**: {what class of failures this prevents (if resolved)}
|
|
222
|
+
**Notes**: {for escalated/exhausted — what the user decided or what remains unsolved}
|
|
134
223
|
```
|
|
135
224
|
|
|
136
225
|
## Decision Tree
|
|
@@ -152,6 +241,21 @@ Agent failed
|
|
|
152
241
|
│
|
|
153
242
|
└─ Did the agent not KNOW it was wrong?
|
|
154
243
|
YES → Build feedback (types/errors/tests)
|
|
244
|
+
|
|
245
|
+
↓
|
|
246
|
+
VERIFY: Does the built capability actually prevent the failure?
|
|
247
|
+
│
|
|
248
|
+
├─ YES → PERSIST (log as "resolved")
|
|
249
|
+
│
|
|
250
|
+
└─ NO → ESCALATE (Step 4.5)
|
|
251
|
+
│
|
|
252
|
+
├─ Other categories untried? → Re-diagnose with exclusion list
|
|
253
|
+
│ → BUILD next category → VERIFY
|
|
254
|
+
│
|
|
255
|
+
└─ All categories tried OR same diagnosis loops:
|
|
256
|
+
│
|
|
257
|
+
├─ Interactive: Ask user (custom angle / manual / abort)
|
|
258
|
+
└─ ultrawork: Auto-record "diagnosis_exhausted" → continue
|
|
155
259
|
```
|
|
156
260
|
|
|
157
261
|
## Anti-patterns
|
|
@@ -1,86 +1,86 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: chub-usage
|
|
3
3
|
tier: optional
|
|
4
|
-
description: "Context Hub (chub) —
|
|
4
|
+
description: "Context Hub (chub) — fetch vetted, up-to-date API documentation. Write accurate code based on the latest docs instead of training data when working with external APIs/SDKs."
|
|
5
5
|
triggers: [chub, context hub, API docs, latest API, deprecated API, SDK documentation, api reference, 최신 문서]
|
|
6
6
|
priority: 65
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Context Hub (chub) Usage
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A skill for fetching vetted, up-to-date documentation before writing external API/SDK code.
|
|
12
|
+
Solves the knowledge cutoff problem inherent in training data.
|
|
13
13
|
|
|
14
14
|
## Why?
|
|
15
15
|
|
|
16
16
|
| Problem | Solution |
|
|
17
17
|
|---------|----------|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
18
|
+
| Relying on training data → using deprecated APIs | chub get → code based on vetted latest docs |
|
|
19
|
+
| Web search → noisy results | chub search → curated docs only |
|
|
20
|
+
| Repeating the same mistakes every session | chub annotate → accumulated learnings |
|
|
21
21
|
|
|
22
22
|
## When to Use
|
|
23
23
|
|
|
24
24
|
| Situation | Example |
|
|
25
25
|
|-----------|---------|
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
26
|
+
| Writing external API code | "Integrate Stripe payments" |
|
|
27
|
+
| Checking latest SDK version | "Call the latest OpenAI model" |
|
|
28
|
+
| Need official documentation | "Set up Supabase auth" |
|
|
29
|
+
| Preventing deprecated patterns | "Firebase v10 migration" |
|
|
30
30
|
|
|
31
31
|
## Workflow
|
|
32
32
|
|
|
33
33
|
```
|
|
34
|
-
|
|
34
|
+
Request to write external API/SDK code
|
|
35
35
|
↓
|
|
36
|
-
Step 0: chub
|
|
36
|
+
Step 0: Check if chub is installed (auto-install if not)
|
|
37
37
|
↓
|
|
38
|
-
Step 1: chub search "
|
|
38
|
+
Step 1: chub search "<library name>"
|
|
39
39
|
↓
|
|
40
40
|
Step 2: chub get <id> --lang ts
|
|
41
41
|
↓
|
|
42
|
-
Step 3:
|
|
42
|
+
Step 3: Write code based on the docs
|
|
43
43
|
↓
|
|
44
|
-
Step 4:
|
|
44
|
+
Step 4: chub annotate when a gotcha is discovered
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
## Step 0 —
|
|
47
|
+
## Step 0 — Auto-install
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
**Always perform this step before running the skill.**
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
# 1.
|
|
52
|
+
# 1. Check if chub exists
|
|
53
53
|
which chub || command -v chub
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
chub
|
|
56
|
+
If chub is not found, attempt automatic installation:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
npm install -g @aisuite/chub
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
If installation fails, fall back to running via `npx @aisuite/chub`:
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
# search
|
|
65
|
+
# search example
|
|
66
66
|
npx @aisuite/chub search "stripe"
|
|
67
|
-
# get
|
|
67
|
+
# get example
|
|
68
68
|
npx @aisuite/chub get stripe/api --lang ts
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
`npx
|
|
71
|
+
If `npx` also fails, fall back to context7 or Web Search (see Fallback Chain).
|
|
72
72
|
|
|
73
73
|
## Usage
|
|
74
74
|
|
|
75
|
-
### Step 1 —
|
|
75
|
+
### Step 1 — Search for docs
|
|
76
76
|
|
|
77
77
|
```bash
|
|
78
78
|
chub search "stripe"
|
|
79
79
|
chub search "openai"
|
|
80
|
-
chub search "" #
|
|
80
|
+
chub search "" # View full list
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
### Step 2 —
|
|
83
|
+
### Step 2 — Fetch latest docs
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
86
|
chub get stripe/api --lang ts
|
|
@@ -88,26 +88,26 @@ chub get openai/chat --lang py
|
|
|
88
88
|
chub get supabase/auth --lang js
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
### Step 3 —
|
|
91
|
+
### Step 3 — Write code based on the docs
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
Write accurate code based on the fetched documentation.
|
|
94
|
+
**Never rely on training data. Docs first, code second.**
|
|
95
95
|
|
|
96
|
-
### Step 4 —
|
|
96
|
+
### Step 4 — Record learnings
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
Gotchas, workarounds, and version issues discovered during work:
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
|
-
chub annotate stripe/api "
|
|
102
|
-
chub annotate openai/chat "streaming
|
|
103
|
-
chub annotate firebase/auth "
|
|
101
|
+
chub annotate stripe/api "pg parameter is required for Korean payments"
|
|
102
|
+
chub annotate openai/chat "tool_calls in streaming comes as delta"
|
|
103
|
+
chub annotate firebase/auth "getAuth() import path changed in v10"
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Annotations are stored locally and automatically included the next time you run `chub get`.
|
|
107
107
|
|
|
108
108
|
## Implementation Pattern (Subagent)
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
Run via subagent to prevent context bloat:
|
|
111
111
|
|
|
112
112
|
```
|
|
113
113
|
Task tool call:
|
|
@@ -116,24 +116,24 @@ Task tool call:
|
|
|
116
116
|
- prompt: "Run `chub search <library>` then `chub get <id> --lang <lang>` to fetch latest API documentation for [topic]. Return only the relevant API usage examples, key changes from previous versions, and any annotations."
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
The subagent handles the chub calls and returns only a summary — keeping the main context clean.
|
|
120
120
|
|
|
121
121
|
## Supported APIs (1,000+)
|
|
122
122
|
|
|
123
|
-
OpenAI, Anthropic, Stripe, Firebase, Supabase, Vercel, AWS S3, Cloudflare Workers, Auth0, Clerk
|
|
123
|
+
OpenAI, Anthropic, Stripe, Firebase, Supabase, Vercel, AWS S3, Cloudflare Workers, Auth0, Clerk, and more.
|
|
124
124
|
|
|
125
125
|
```bash
|
|
126
|
-
chub search #
|
|
126
|
+
chub search # Run without arguments to view the full list
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
## Fallback Chain
|
|
130
130
|
|
|
131
131
|
```
|
|
132
|
-
which chub
|
|
132
|
+
which chub fails
|
|
133
133
|
↓
|
|
134
|
-
npm install -g @aisuite/chub (
|
|
134
|
+
npm install -g @aisuite/chub (auto attempt)
|
|
135
135
|
↓
|
|
136
|
-
|
|
136
|
+
On failure: npx @aisuite/chub <command> (temporary execution)
|
|
137
137
|
↓
|
|
138
|
-
npx
|
|
138
|
+
If npx also fails: context7 or Web Search fallback
|
|
139
139
|
```
|