@su-record/vibe 2.8.41 → 2.8.44

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 (29) hide show
  1. package/CLAUDE.md +1 -0
  2. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  3. package/dist/cli/postinstall/constants.js +1 -0
  4. package/dist/cli/postinstall/constants.js.map +1 -1
  5. package/dist/infra/lib/VerificationLoop.d.ts +62 -0
  6. package/dist/infra/lib/VerificationLoop.d.ts.map +1 -1
  7. package/dist/infra/lib/VerificationLoop.js +115 -0
  8. package/dist/infra/lib/VerificationLoop.js.map +1 -1
  9. package/dist/infra/lib/evolution/GuardAnalyzer.d.ts +44 -0
  10. package/dist/infra/lib/evolution/GuardAnalyzer.d.ts.map +1 -0
  11. package/dist/infra/lib/evolution/GuardAnalyzer.js +116 -0
  12. package/dist/infra/lib/evolution/GuardAnalyzer.js.map +1 -0
  13. package/dist/infra/lib/evolution/HookTraceReader.d.ts +45 -0
  14. package/dist/infra/lib/evolution/HookTraceReader.d.ts.map +1 -0
  15. package/dist/infra/lib/evolution/HookTraceReader.js +108 -0
  16. package/dist/infra/lib/evolution/HookTraceReader.js.map +1 -0
  17. package/dist/infra/lib/evolution/index.d.ts +4 -0
  18. package/dist/infra/lib/evolution/index.d.ts.map +1 -1
  19. package/dist/infra/lib/evolution/index.js +3 -0
  20. package/dist/infra/lib/evolution/index.js.map +1 -1
  21. package/hooks/scripts/evolution-engine.js +23 -1
  22. package/hooks/scripts/pre-tool-guard.js +9 -0
  23. package/hooks/scripts/sentinel-guard.js +3 -0
  24. package/hooks/scripts/utils.js +38 -0
  25. package/package.json +1 -1
  26. package/skills/chub-usage/SKILL.md +115 -0
  27. package/skills/vibe.figma/SKILL.md +42 -42
  28. package/skills/vibe.figma/templates/component-index.md +126 -0
  29. package/skills/vibe.figma/templates/remapped-tree.md +277 -0
@@ -0,0 +1,108 @@
1
+ // HookTraceReader — JSONL hook trace 파일 읽기 및 집계
2
+ // Guard hooks가 ~/.vibe/hook-traces.jsonl에 기록한 로그를 읽고 분석
3
+ import { readFileSync, existsSync } from 'fs';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ const TRACE_FILENAME = 'hook-traces.jsonl';
7
+ const MIN_CLUSTER_SIZE = 3;
8
+ /**
9
+ * hook-traces.jsonl 파일 경로 반환
10
+ */
11
+ function getTracePath() {
12
+ const home = os.homedir();
13
+ return path.join(home, '.vibe', TRACE_FILENAME);
14
+ }
15
+ /**
16
+ * JSONL 파일에서 최근 N일간 trace 항목 읽기
17
+ */
18
+ export function readTraces(daysBack = 7) {
19
+ const tracePath = getTracePath();
20
+ if (!existsSync(tracePath))
21
+ return [];
22
+ const cutoff = new Date();
23
+ cutoff.setDate(cutoff.getDate() - daysBack);
24
+ const cutoffIso = cutoff.toISOString();
25
+ const raw = readFileSync(tracePath, 'utf-8');
26
+ const traces = [];
27
+ for (const line of raw.split('\n')) {
28
+ if (!line.trim())
29
+ continue;
30
+ try {
31
+ const entry = JSON.parse(line);
32
+ if (entry.ts >= cutoffIso) {
33
+ traces.push(entry);
34
+ }
35
+ }
36
+ catch {
37
+ // 깨진 줄 무시
38
+ }
39
+ }
40
+ return traces;
41
+ }
42
+ /**
43
+ * 사유 문자열을 정규화 (파일 경로, 명령어 세부 사항 제거)
44
+ */
45
+ function normalizeReason(reason) {
46
+ return reason
47
+ .replace(/\/[\w/._-]+/g, '<path>')
48
+ .replace(/`[^`]+`/g, '<cmd>')
49
+ .replace(/:\s+.*$/, '')
50
+ .trim();
51
+ }
52
+ /**
53
+ * Trace 목록을 패턴별로 클러스터링
54
+ */
55
+ export function clusterTraces(traces) {
56
+ const actionable = traces.filter(t => t.decision !== 'allow');
57
+ const groups = new Map();
58
+ for (const trace of actionable) {
59
+ const key = `${trace.hook}:${normalizeReason(trace.reason)}`;
60
+ const group = groups.get(key) ?? [];
61
+ group.push(trace);
62
+ groups.set(key, group);
63
+ }
64
+ const clusters = [];
65
+ for (const [, group] of groups) {
66
+ if (group.length < MIN_CLUSTER_SIZE)
67
+ continue;
68
+ const sorted = group.sort((a, b) => a.ts.localeCompare(b.ts));
69
+ const tools = [...new Set(group.map(t => t.tool))];
70
+ clusters.push({
71
+ pattern: normalizeReason(group[0].reason),
72
+ hook: group[0].hook,
73
+ decision: group[0].decision,
74
+ count: group.length,
75
+ tools,
76
+ firstSeen: sorted[0].ts,
77
+ lastSeen: sorted[sorted.length - 1].ts,
78
+ });
79
+ }
80
+ return clusters.sort((a, b) => b.count - a.count);
81
+ }
82
+ /**
83
+ * 전체 통계 + 클러스터 분석 수행
84
+ */
85
+ export function analyzeTraces(daysBack = 7) {
86
+ const traces = readTraces(daysBack);
87
+ const byHook = {};
88
+ const byTool = {};
89
+ let blockCount = 0;
90
+ let warnCount = 0;
91
+ for (const t of traces) {
92
+ byHook[t.hook] = (byHook[t.hook] ?? 0) + 1;
93
+ byTool[t.tool] = (byTool[t.tool] ?? 0) + 1;
94
+ if (t.decision === 'block')
95
+ blockCount++;
96
+ if (t.decision === 'warn')
97
+ warnCount++;
98
+ }
99
+ return {
100
+ totalTraces: traces.length,
101
+ blockCount,
102
+ warnCount,
103
+ byHook,
104
+ byTool,
105
+ clusters: clusterTraces(traces),
106
+ };
107
+ }
108
+ //# sourceMappingURL=HookTraceReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HookTraceReader.js","sourceRoot":"","sources":["../../../../src/infra/lib/evolution/HookTraceReader.ts"],"names":[],"mappings":"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"}
@@ -32,4 +32,8 @@ export { DeprecationDetector } from './DeprecationDetector.js';
32
32
  export type { DeprecationCandidate, DeprecationReport } from './DeprecationDetector.js';
33
33
  export { ParityTester, PARITY_THRESHOLDS } from './ParityTester.js';
34
34
  export type { ParityTestResult, ModelVersion, EvalComparison } from './ParityTester.js';
35
+ export { readTraces, clusterTraces, analyzeTraces } from './HookTraceReader.js';
36
+ export type { HookTrace, TraceCluster, TraceStats } from './HookTraceReader.js';
37
+ export { GuardAnalyzer } from './GuardAnalyzer.js';
38
+ export type { GuardAnalysisResult } from './GuardAnalyzer.js';
35
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/evolution/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGnH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC7G,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAC3D,UAAU,EAAE,YAAY,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,GAC3E,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EACV,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,GAC3E,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGxF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/infra/lib/evolution/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGnH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC7G,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EACV,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAC3D,UAAU,EAAE,YAAY,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EACV,eAAe,EAAE,gBAAgB,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,GAC3E,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAY,EACV,gBAAgB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,GAC3E,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGxF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGxF,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -26,4 +26,7 @@ export { DescriptionOptimizer } from './DescriptionOptimizer.js';
26
26
  export { DeprecationDetector } from './DeprecationDetector.js';
27
27
  // Phase 5b: Model Parity Testing
28
28
  export { ParityTester, PARITY_THRESHOLDS } from './ParityTester.js';
29
+ // Phase 6: Harness Self-Improvement (Hook Trace Analysis)
30
+ export { readTraces, clusterTraces, analyzeTraces } from './HookTraceReader.js';
31
+ export { GuardAnalyzer } from './GuardAnalyzer.js';
29
32
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/infra/lib/evolution/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAE9B,2BAA2B;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D,8BAA8B;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,2BAA2B;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,sCAAsC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,iCAAiC;AACjC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/infra/lib/evolution/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAE9B,2BAA2B;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D,8BAA8B;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,2BAA2B;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,kCAAkC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD,sCAAsC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAIjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAG/D,iCAAiC;AACjC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGpE,0DAA0D;AAC1D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEhF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
@@ -39,7 +39,29 @@ async function main() {
39
39
  const extractor = new extractorMod.InsightExtractor(storage);
40
40
  const extractResult = extractor.extractFromRecent(20);
41
41
 
42
- if (extractResult.newInsights.length === 0 && extractResult.mergedInsights.length === 0) {
42
+ // Phase 2b: Guard trace 분석 (하네스 자기 개선)
43
+ let guardInsightCount = 0;
44
+ try {
45
+ const guardMod = await import(`${LIB_BASE}evolution/GuardAnalyzer.js`);
46
+ const insightMod = await import(`${LIB_BASE}evolution/InsightStore.js`);
47
+ const insightStore = new insightMod.InsightStore(storage);
48
+ const guardAnalyzer = new guardMod.GuardAnalyzer(insightStore);
49
+ const guardResult = guardAnalyzer.analyze(7);
50
+ guardInsightCount = guardResult.newInsights.length;
51
+ if (guardInsightCount > 0) {
52
+ process.stderr.write(
53
+ `[Evolution] Guard analysis: ${guardInsightCount} new insights from hook traces\n`
54
+ );
55
+ }
56
+ } catch (e) {
57
+ process.stderr.write(`[Evolution] Guard analysis skipped: ${e.message}\n`);
58
+ }
59
+
60
+ if (
61
+ extractResult.newInsights.length === 0 &&
62
+ extractResult.mergedInsights.length === 0 &&
63
+ guardInsightCount === 0
64
+ ) {
43
65
  storage.close();
44
66
  return;
45
67
  }
@@ -139,6 +139,8 @@ const toolInput = stdinPayload?.tool_input
139
139
  : JSON.stringify(stdinPayload.tool_input))
140
140
  : (process.argv[3] || process.env.TOOL_INPUT || '');
141
141
 
142
+ import { logHookDecision } from './utils.js';
143
+
142
144
  const validation = validateCommand(toolName, toolInput);
143
145
  const output = formatOutput(toolName, validation);
144
146
 
@@ -146,5 +148,12 @@ if (output) {
146
148
  console.log(output);
147
149
  }
148
150
 
151
+ // Hook trace logging
152
+ if (!validation.allowed) {
153
+ logHookDecision('pre-tool-guard', toolName, 'block', validation.warnings.join('; '));
154
+ } else if (validation.warnings.length > 0) {
155
+ logHookDecision('pre-tool-guard', toolName, 'warn', validation.warnings.join('; '));
156
+ }
157
+
149
158
  // Exit code: 0 = allowed, 2 = denied (claw-code 규약), 1 = 레거시 호환
150
159
  process.exit(validation.allowed ? 0 : 2);
@@ -118,9 +118,12 @@ const toolInput = stdinPayload?.tool_input
118
118
  : JSON.stringify(stdinPayload.tool_input))
119
119
  : (process.argv[3] || process.env.TOOL_INPUT || '');
120
120
 
121
+ import { logHookDecision } from './utils.js';
122
+
121
123
  const result = guard(toolName, toolInput);
122
124
 
123
125
  if (result) {
126
+ logHookDecision('sentinel-guard', toolName, 'block', result.reason);
124
127
  console.log(JSON.stringify(result));
125
128
  process.exit(2); // deny 규약
126
129
  }
@@ -146,3 +146,41 @@ export function getToolsBaseUrl() {
146
146
  export function getLibBaseUrl() {
147
147
  return getPackageUrl(path.join('dist', 'infra', 'lib'), 'gpt-api.js');
148
148
  }
149
+
150
+ // ─── Hook Trace Logging ───
151
+
152
+ const HOOK_TRACE_PATH = path.join(VIBE_HOME_DIR, 'hook-traces.jsonl');
153
+ const MAX_TRACE_SIZE_BYTES = 5 * 1024 * 1024; // 5MB rotation
154
+
155
+ /**
156
+ * Guard/Hook 결정 사항을 JSONL로 로깅
157
+ * evolution GuardAnalyzer가 이 로그를 분석해 하네스 자기 개선에 활용
158
+ *
159
+ * @param {string} hookName - 훅 이름 (e.g., 'sentinel-guard', 'pre-tool-guard')
160
+ * @param {string} toolName - 대상 도구 (e.g., 'Bash', 'Write')
161
+ * @param {'allow'|'block'|'warn'} decision - 판정 결과
162
+ * @param {string} reason - 판정 사유
163
+ */
164
+ export function logHookDecision(hookName, toolName, decision, reason) {
165
+ try {
166
+ // 로그 로테이션: 5MB 초과 시 이전 파일 교체
167
+ if (fs.existsSync(HOOK_TRACE_PATH)) {
168
+ const stat = fs.statSync(HOOK_TRACE_PATH);
169
+ if (stat.size > MAX_TRACE_SIZE_BYTES) {
170
+ const rotated = HOOK_TRACE_PATH + '.prev';
171
+ try { fs.unlinkSync(rotated); } catch { /* ignore */ }
172
+ fs.renameSync(HOOK_TRACE_PATH, rotated);
173
+ }
174
+ }
175
+
176
+ const entry = JSON.stringify({
177
+ ts: new Date().toISOString(),
178
+ hook: hookName,
179
+ tool: toolName,
180
+ decision,
181
+ reason,
182
+ project: PROJECT_DIR,
183
+ });
184
+ fs.appendFileSync(HOOK_TRACE_PATH, entry + '\n');
185
+ } catch { /* 트레이스 실패가 훅 실행을 방해해선 안 됨 */ }
186
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@su-record/vibe",
3
- "version": "2.8.41",
3
+ "version": "2.8.44",
4
4
  "description": "AI Coding Framework for Claude Code — 56 agents, 45 skills, multi-LLM orchestration",
5
5
  "type": "module",
6
6
  "main": "dist/cli/index.js",
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: chub-usage
3
+ tier: optional
4
+ description: "Context Hub (chub) — 검수된 최신 API 문서 조회. 외부 API/SDK 코드 작성 시 training data 대신 최신 문서를 기반으로 정확한 코드 작성."
5
+ triggers: [chub, context hub, API docs, latest API, deprecated API, SDK documentation, api reference, 최신 문서]
6
+ priority: 65
7
+ ---
8
+
9
+ # Context Hub (chub) Usage
10
+
11
+ 외부 API/SDK 코드 작성 전 검수된 최신 문서를 가져오는 스킬.
12
+ Training data의 지식 컷오프 문제를 해결합니다.
13
+
14
+ ## Why?
15
+
16
+ | Problem | Solution |
17
+ |---------|----------|
18
+ | Training data에 의존 → deprecated API 사용 | chub get → 검수된 최신 문서 기반 코드 |
19
+ | 웹 검색 → 노이즈 섞인 결과 | chub search → 큐레이션된 문서만 |
20
+ | 세션마다 같은 실수 반복 | chub annotate → 학습 누적 |
21
+
22
+ ## Prerequisites
23
+
24
+ ```bash
25
+ npm install -g @aisuite/chub
26
+ ```
27
+
28
+ ## When to Use
29
+
30
+ | Situation | Example |
31
+ |-----------|---------|
32
+ | 외부 API 코드 작성 | "Stripe 결제 연동해줘" |
33
+ | SDK 최신 버전 확인 | "OpenAI 최신 모델 호출" |
34
+ | 공식 문서 필요 | "Supabase auth 설정" |
35
+ | Deprecated 패턴 방지 | "Firebase v10 마이그레이션" |
36
+
37
+ ## Workflow
38
+
39
+ ```
40
+ 외부 API/SDK 코드 작성 요청
41
+
42
+ Step 1: chub search "<라이브러리명>"
43
+
44
+ Step 2: chub get <id> --lang ts
45
+
46
+ Step 3: 문서 기반 코드 작성
47
+
48
+ Step 4: gotcha 발견 시 chub annotate
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### Step 1 — 문서 검색
54
+
55
+ ```bash
56
+ chub search "stripe"
57
+ chub search "openai"
58
+ chub search "" # 전체 목록 확인
59
+ ```
60
+
61
+ ### Step 2 — 최신 문서 fetch
62
+
63
+ ```bash
64
+ chub get stripe/api --lang ts
65
+ chub get openai/chat --lang py
66
+ chub get supabase/auth --lang js
67
+ ```
68
+
69
+ ### Step 3 — 문서 기반 코드 작성
70
+
71
+ fetch한 문서 내용을 기반으로 정확한 코드 작성.
72
+ **절대 training data에 의존하지 않는다. 문서 먼저, 코드 나중.**
73
+
74
+ ### Step 4 — 학습 내용 기록
75
+
76
+ 작업 중 발견한 gotcha, workaround, 버전 이슈:
77
+
78
+ ```bash
79
+ chub annotate stripe/api "한국 결제는 pg 파라미터 필수"
80
+ chub annotate openai/chat "streaming에서 tool_calls는 delta로 옴"
81
+ chub annotate firebase/auth "v10에서 getAuth() import 경로 변경"
82
+ ```
83
+
84
+ Annotation은 로컬 저장, 다음 세션에서 `chub get` 시 자동으로 같이 나옴.
85
+
86
+ ## Implementation Pattern (Subagent)
87
+
88
+ 컨텍스트 블로트 방지를 위해 서브에이전트에서 실행:
89
+
90
+ ```
91
+ Task tool call:
92
+ - subagent_type: Explore
93
+ - model: haiku
94
+ - 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."
95
+ ```
96
+
97
+ 서브에이전트가 chub 호출을 처리하고 요약만 반환 → 메인 컨텍스트 깨끗하게 유지.
98
+
99
+ ## Supported APIs (1,000+)
100
+
101
+ OpenAI, Anthropic, Stripe, Firebase, Supabase, Vercel, AWS S3, Cloudflare Workers, Auth0, Clerk 등.
102
+
103
+ ```bash
104
+ chub search # 인자 없이 실행하면 전체 목록 확인 가능
105
+ ```
106
+
107
+ ## Fallback Chain
108
+
109
+ ```
110
+ chub 설치 안 됨
111
+
112
+ Prompt: npm install -g @aisuite/chub
113
+
114
+ If still unavailable: context7 또는 Web Search fallback
115
+ ```
@@ -36,44 +36,44 @@ Figma 트리가 코드의 원천이다. 스크린샷은 검증용이다.
36
36
 
37
37
  ```
38
38
  /vibe.figma
39
+ 입력: 모든 URL을 한번에 받는다
40
+ Storyboard: https://figma.com/...?node-id=aaa (있으면)
41
+ MO Design: https://figma.com/...?node-id=xxx
42
+ PC Design: https://figma.com/...?node-id=yyy (있으면)
43
+
39
44
  → Phase 0: Setup (스택 감지, 디렉토리 생성, 기존 자산 인덱싱)
40
45
  → Phase 1: Storyboard (스토리보드 → 기능 스펙 문서 작성, 파일 생성 없음)
41
- → Phase 2: 재료 확보 (디자인 URL 트리 + 노드 렌더링 이미지 + 스크린샷)
42
- → Phase 3: 구조적 코드 생성 (트리HTML+SCSS 매핑 + 시맨틱 보강)
43
- → Phase 3.5: 컴파일 게이트 (tscbuild → dev 확인)
44
- → Phase 4: 시각 검증 루프 (렌더링 vs 스크린샷 비교 수정)
45
- ─── 추가 브레이크포인트가 있으면 Phase 2~4 반복 ───
46
- → Phase 5: 공통화 (브레이크포인트별 작업 병합 → 최종 프로젝트 구조)
47
-
48
- 브레이크포인트별 작업 구조:
46
+ → Phase 2: 재료 확보 (모든 BP의 트리 + 노드 렌더링 이미지 + 스크린샷)
47
+ → Phase 3: 리매핑 (tree.jsonremapped.json, BP 간 노드 매칭 + CSS diff)
48
+ → Phase 4: 순차 코드 생성 (remapped.json섹션별 HTML+SCSS)
49
+ → Phase 5: 컴파일 게이트 (tsc builddev 확인)
50
+ Phase 6: 시각 검증 루프 (렌더링 vs 스크린샷 비교 → 수정)
51
+
52
+ 작업 디렉토리 구조:
49
53
  각 Figma URL의 ROOT name에서 폴더명 추출 (kebab-case):
50
54
  "MO_Main ..." → /tmp/{feature}/mo-main/
51
55
  "PC_Main ..." → /tmp/{feature}/pc-main/
52
56
 
53
57
  /tmp/{feature}/
54
- ├── mo-main/ ← 번째 URL (모바일)
55
- │ ├── tree.json
56
- │ ├── bg/
57
- │ ├── content/
58
- │ └── sections/
59
- ├── pc-main/ ← 두 번째 URL (데스크탑)
58
+ ├── mo-main/ ← 모바일 Phase 2 추출 결과
60
59
  │ ├── tree.json
61
- │ ├── bg/
62
- │ ├── content/
63
- │ └── sections/
64
- └── final/ ← Phase 5 공통화 결과
65
- ├── components/{feature}/
66
- └── styles/{feature}/
60
+ │ ├── bg/ ← BG 프레임 렌더링
61
+ │ ├── content/ ← 콘텐츠 노드 렌더링
62
+ │ └── sections/ ← Phase 4 검증용 스크린샷
63
+ ├── pc-main/ 데스크탑 Phase 2 추출 결과
64
+ │ └── (동일 구조)
65
+ └── remapped.json ← Phase 3 리매핑 결과 (모든 BP 통합)
66
+
67
+ remapped.json이 Phase 4의 유일한 입력.
68
+ → BP 간 노드 매칭 완료
69
+ → CSS diff (mo/pc) 포함
70
+ → 이미지 렌더링 파일 경로 포함
71
+ → Phase 4에서 바로 코드 생성 가능
67
72
 
68
- Phase 5 공통화:
69
- 1. 각 브레이크포인트의 컴포넌트 diff
70
- 구조 동일: 1개로 병합
71
- → 구조 다름: props로 분기 또는 별도 유지
72
- 2. SCSS diff
73
- → 같은 값: 기본 스타일
74
- → 다른 값: @media 오버라이드
75
- 3. 토큰 diff → 합집합 정리
76
- 4. /tmp/ 임시 폴더 → 프로젝트 디렉토리에 최종 배치
73
+ 코드 출력: 프로젝트 디렉토리에 직접 배치
74
+ components/{feature}/HeroSection.vue
75
+ styles/{feature}/layout/_hero.scss (모바일 기본 + @media PC)
76
+ styles/{feature}/components/_hero.scss
77
77
  ```
78
78
 
79
79
  ---
@@ -202,7 +202,7 @@ Phase 5 공통화:
202
202
  - question: "스토리보드 Figma URL을 입력해주세요. (없으면 '없음')"
203
203
  - options 제공 금지 — 자유 텍스트 입력만 허용
204
204
 
205
- "없음" 응답 시 → Phase 2로 건너뜀
205
+ "없음" 응답 시 → 스토리보드 분석 스킵
206
206
 
207
207
  ### 1-1. 스토리보드 분석
208
208
 
@@ -238,8 +238,8 @@ URL에서 fileKey, nodeId 추출
238
238
 
239
239
  ```
240
240
  ❌ Phase 1에서 코드 파일을 생성하지 않는다.
241
- → Phase 1 HTML 구조와 Phase 3 트리 매핑이 충돌하면 이중 작업
242
- → Phase 3에서 tree.json 기반으로 코드를 생성
241
+ → Phase 1 HTML 구조와 Phase 4 트리 매핑이 충돌하면 이중 작업
242
+ → Phase 4에서 remapped.json 기반으로 코드를 생성
243
243
 
244
244
  ✅ Phase 1의 출력물은 기능 스펙 문서 (텍스트):
245
245
 
@@ -283,7 +283,7 @@ Phase 1 완료 조건:
283
283
  □ 공통 컴포넌트가 식별되어 있다
284
284
  □ 파일을 하나도 생성하지 않았다
285
285
 
286
- Phase 3에서 이 스펙 + tree.json을 합쳐서 코드를 생성한다.
286
+ Phase 4에서 이 스펙 + remapped.json을 합쳐서 코드를 생성한다.
287
287
  ```
288
288
 
289
289
  ---
@@ -425,7 +425,7 @@ UI 요소 → vw 비례:
425
425
 
426
426
  ---
427
427
 
428
- ## Phase 2.5: 공통 패턴 분석 (멀티 프레임 전용)
428
+ ## Phase 3: 리매핑 (tree.json remapped.json)
429
429
 
430
430
  **URL 2개 이상일 때만 실행. 단일 URL이면 Phase 3으로 건너뜀.**
431
431
  **프레임 간 공통 요소를 식별하여 공유 컴포넌트로 추출한다.**
@@ -466,7 +466,7 @@ UI 요소 → vw 비례:
466
466
 
467
467
  ---
468
468
 
469
- ## Phase 3: 퍼즐 조립
469
+ ## Phase 4: 순차 코드 생성
470
470
 
471
471
  **Phase 1에서 만든 컴포넌트에 Phase 2의 재료로 디자인을 입힌다.**
472
472
  **스크린샷을 보면서 퍼즐을 맞추듯 조립한다.**
@@ -688,11 +688,11 @@ URL 있으면:
688
688
 
689
689
  ---
690
690
 
691
- ## Phase 3.5: 컴파일 게이트
691
+ ## Phase 5: 컴파일 게이트
692
692
 
693
693
  **Phase 3 퍼즐 조립 완료 후, 브라우저 검증 전에 컴파일 성공을 보장한다.**
694
694
  **컴파일 에러는 스킵 불가 — 반드시 수정 또는 사용자 보고.**
695
- **Phase 3.5 실패 시 Phase 4 진행 불가 (hard gate).**
695
+ **Phase 5 실패 시 Phase 4 진행 불가 (hard gate).**
696
696
 
697
697
  ```
698
698
  자동 반복: 컴파일 성공까지. 최대 3라운드.
@@ -705,7 +705,7 @@ Phase 3 시작 전에 기존 프로젝트의 에러를 캡처:
705
705
  1. 타입 체크 베이스라인: (3.5-1에서 선택한 동일 명령 사용) > /tmp/{feature}/baseline-typecheck.txt 2>&1
706
706
  2. 빌드 베이스라인: npm run build > /tmp/{feature}/baseline-build.txt 2>&1
707
707
 
708
- Phase 3.5에서는 baseline에 없는 **새로 발생한 에러만** 수정 대상.
708
+ Phase 5에서는 baseline에 없는 **새로 발생한 에러만** 수정 대상.
709
709
  baseline에 존재하던 에러는 무시하고 별도 보고 ("기존 에러 {N}개 유지").
710
710
  vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
711
711
  ```
@@ -783,13 +783,13 @@ vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
783
783
  컴파일 게이트 결과 보고:
784
784
 
785
785
  ✅ 통과:
786
- "Phase 3.5: 컴파일 게이트 PASS (라운드 {N})"
786
+ "Phase 5: 컴파일 게이트 PASS (라운드 {N})"
787
787
  - tsc: 0 errors
788
788
  - build: success
789
789
  - dev server: running on localhost:{port}
790
790
 
791
791
  ❌ 실패 (3라운드 후):
792
- "Phase 3.5: 컴파일 게이트 FAIL"
792
+ "Phase 5: 컴파일 게이트 FAIL"
793
793
  - 남은 에러 목록 (파일, 줄, 메시지)
794
794
  - 시도한 수정 내역
795
795
  - 사용자 수동 수정 필요
@@ -798,7 +798,7 @@ vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
798
798
 
799
799
  ---
800
800
 
801
- ## Phase 4: 검증 루프
801
+ ## Phase 6: 시각 검증 루프
802
802
 
803
803
  **Puppeteer + CDP로 실제 렌더링 결과를 확인하며 자동 수정한다.**
804
804
  **사람이 브라우저 보면서 고치는 것과 동일한 루프.**
@@ -812,7 +812,7 @@ vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
812
812
 
813
813
  ```
814
814
  1. dev 서버 시작:
815
- Phase 3.5에서 이미 시작된 dev 서버 사용 (재시작 불필요)
815
+ Phase 5에서 이미 시작된 dev 서버 사용 (재시작 불필요)
816
816
  → localhost:{port} 확인
817
817
 
818
818
  2. Puppeteer 브라우저 시작: