stellavault 0.1.0 โ†’ 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,322 +1,322 @@
1
- import { Client } from '@notionhq/client';
2
-
3
- const notion = new Client({ auth: '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' });
4
- const PARENT_PAGE_ID = '330dcee017df808d92d4d9ff46fa7697';
5
-
6
- function h2(t) { return { type: 'heading_2', heading_2: { rich_text: [{ text: { content: t } }] } }; }
7
- function p(t) { return { type: 'paragraph', paragraph: { rich_text: [{ text: { content: t } }] } }; }
8
- function d() { return { type: 'divider', divider: {} }; }
9
- function callout(t, e = '๐Ÿ’ก') { return { type: 'callout', callout: { rich_text: [{ text: { content: t } }], icon: { emoji: e } } }; }
10
-
11
- function table(headers, rows) {
12
- return {
13
- type: 'table', table: {
14
- table_width: headers.length,
15
- has_column_header: true,
16
- has_row_header: false,
17
- children: [
18
- { type: 'table_row', table_row: { cells: headers.map(h => [{ type: 'text', text: { content: h } }]) } },
19
- ...rows.map(row => ({
20
- type: 'table_row', table_row: { cells: row.map(c => [{ type: 'text', text: { content: c } }]) }
21
- })),
22
- ],
23
- }
24
- };
25
- }
26
-
27
- function columnList(columns) {
28
- return {
29
- type: 'column_list', column_list: {
30
- children: columns.map(col => ({
31
- type: 'column', column: { children: col }
32
- }))
33
- }
34
- };
35
- }
36
-
37
- async function main() {
38
- console.log('Creating Stellavault project page...');
39
-
40
- const part1 = [
41
- // Callout header
42
- callout('Stellavault โ€” Notes die in folders. Stellavault keeps your knowledge alive.', '๐Ÿง '),
43
-
44
- // ํ”„๋กœ์ ํŠธ ๊ฐœ์š”
45
- h2('ํ”„๋กœ์ ํŠธ ๊ฐœ์š”'),
46
- table(['ํ•ญ๋ชฉ', '๋‚ด์šฉ'], [
47
- ['ํ”„๋กœ์ ํŠธ๋ช…', 'Stellavault (์Šคํ…”๋ผ๋ณผํŠธ)'],
48
- ['์œ ํ˜•', '๊ฐœ์ธ ์ง€์‹ ์ธํ…”๋ฆฌ์ „์Šค ํ”Œ๋žซํผ (์˜คํ”ˆ์†Œ์Šค + Pro)'],
49
- ['๋ชฉ์ ', 'Obsidian vault๋ฅผ ๋ฒกํ„ฐํ™”ํ•˜์—ฌ 3D ์‹œ๊ฐํ™”, AI ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰, ๊ธฐ์–ต ๊ฐ์‡  ์ถ”์ , MCP๋กœ AI ์—์ด์ „ํŠธ ์—ฐ๊ฒฐ'],
50
- ['๋Œ€์ƒ', 'AI ๊ฐœ๋ฐœ์ž, ์ง€์‹ ๋…ธ๋™์ž, Obsidian ์‚ฌ์šฉ์ž'],
51
- ['ํ•ต์‹ฌ ๊ฐ€์น˜', '์ง€์‹ ๊ฐ„ ์—ฐ๊ฒฐ ์ž๋™ ๋ฐœ๊ฒฌ + ์žŠํ˜€๊ฐ€๋Š” ์ง€์‹ ๊ฐ์ง€ + AI ์—์ด์ „ํŠธ์— ์ง€์‹ ์ ‘์†'],
52
- ['๋ผ์ด์„ ์Šค', 'MIT (์˜คํ”ˆ์†Œ์Šค)'],
53
- ['GitHub', 'github.com/Evanciel/stellavault'],
54
- ['CLI', 'stellavault (alias: sv) โ€” 19๊ฐœ ๋ช…๋ น์–ด'],
55
- ['MCP', '13+ tools โ€” Claude Code ๋“ฑ AI ์—์ด์ „ํŠธ ์—ฐ๋™'],
56
- ]),
57
- d(),
58
-
59
- // ํ•ต์‹ฌ ๊ธฐ๋Šฅ
60
- h2('ํ•ต์‹ฌ ๊ธฐ๋Šฅ'),
61
- columnList([
62
- [
63
- callout('3D Knowledge Graph\nReact Three Fiber ๊ธฐ๋ฐ˜ ๋‰ด๋Ÿด ๋„คํŠธ์›Œํฌ ์‹œ๊ฐํ™”\nConstellation View + LOD 3๋‹จ๊ณ„\nTimeline ์Šฌ๋ผ์ด๋” + Type/Source ํ•„ํ„ฐ', '๐ŸŒ'),
64
- ],
65
- [
66
- callout('AI Semantic Search\nBM25 + Cosine + RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ\n384์ฐจ์› ๋กœ์ปฌ ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ\n์‹œ๋งจํ‹ฑ + ํ‚ค์›Œ๋“œ ์œตํ•ฉ', '๐Ÿ”'),
67
- ],
68
- ]),
69
- columnList([
70
- [
71
- callout('Intelligence Layer\nFSRS ๊ธฐ์–ต ๊ฐ์‡  ์ถ”์ \n๊ฐญ ํƒ์ง€ + ๋ชจ์ˆœ ํƒ์ง€\n์ค‘๋ณต ํƒ์ง€ + ์˜ˆ์ธก์  ๊ฐญ ๋ถ„์„\nAI ํ•™์Šต ๊ฒฝ๋กœ ์ƒ์„ฑ', '๐Ÿงฌ'),
72
- ],
73
- [
74
- callout('MCP + Plugin\n13๊ฐœ MCP ๋„๊ตฌ (AI ์—์ด์ „ํŠธ ์—ฐ๋™)\nPlugin SDK (์ด๋ฒคํŠธ ๋ฒ„์Šค)\nWebhook ์‹œ์Šคํ…œ\n์ปค์Šคํ…€ MCP ๋„๊ตฌ ๋นŒ๋” (YAML)', '๐Ÿ”Œ'),
75
- ],
76
- ]),
77
- d(),
78
-
79
- // ๊ธฐ์ˆ  ์Šคํƒ
80
- h2('๊ธฐ์ˆ  ์Šคํƒ'),
81
- table(['์นดํ…Œ๊ณ ๋ฆฌ', '๊ธฐ์ˆ ', '๋ฒ„์ „ / ๋น„๊ณ '], [
82
- ['Runtime', 'Node.js (ESM)', '20+'],
83
- ['Language', 'TypeScript', 'Strict mode'],
84
- ['Monorepo', 'npm workspaces', '4 packages (core, cli, graph, sync)'],
85
- ['Vector DB', 'SQLite-vec (better-sqlite3)', '384์ฐจ์› ์ž„๋ฒ ๋”ฉ'],
86
- ['Embedding', '@xenova/transformers', 'all-MiniLM-L6-v2 (๋กœ์ปฌ, API ํ‚ค ๋ถˆํ•„์š”)'],
87
- ['Search', 'BM25 + Cosine + RRF', 'K=60, ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํ“จ์ „'],
88
- ['3D ์‹œ๊ฐํ™”', 'React Three Fiber + drei + Three.js', 'R3F 9.0 / Three 0.170'],
89
- ['State', 'Zustand', '5.0'],
90
- ['Memory Model', 'FSRS (Free Spaced Repetition)', 'SM2 ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ณ€ํ˜•'],
91
- ['AI ์—ฐ๋™', 'MCP (@modelcontextprotocol/sdk)', 'stdio + Streamable HTTP'],
92
- ['Build', 'Vite (graph) + tsc (core/cli)', 'Vite 6.0'],
93
- ['Testing', 'Vitest', '116 tests'],
94
- ]),
95
- d(),
96
-
97
- // ๊ทœ๋ชจ ์ง€ํ‘œ
98
- h2('๊ทœ๋ชจ ์ง€ํ‘œ'),
99
- columnList([
100
- [
101
- callout('์ฝ”๋“œ ๊ทœ๋ชจ\n175+ ์†Œ์Šค ํŒŒ์ผ\n30,000+ LOC (TypeScript)\n4 workspace packages\n19 CLI ๋ช…๋ น์–ด\n13+ MCP ๋„๊ตฌ', '๐Ÿ“Š'),
102
- ],
103
- [
104
- callout('๊ธฐ๋Šฅ ํ˜„ํ™ฉ\nPRD 22๊ฐœ ๊ธฐ๋Šฅ ์ค‘ 18๊ฐœ ๊ตฌํ˜„\nP0 (4/4) + P1 (7/7) + P2 (7/7)\nIntelligence ๋ชจ๋“ˆ 8๊ฐœ\ni18n 4๊ฐœ ์–ธ์–ด (en/ko/ja/zh)', 'โœ…'),
105
- ],
106
- [
107
- callout('์•„ํ‚คํ…์ฒ˜\nHybrid Search (BM25+Vector+RRF)\nPlugin SDK + Webhook\nEmbed Widget (iframe)\nStreamable HTTP MCP\nKeyboard Navigation', '๐Ÿ—๏ธ'),
108
- ],
109
- ]),
110
- ];
111
-
112
- const page = await notion.pages.create({
113
- parent: { page_id: PARENT_PAGE_ID },
114
- icon: { emoji: '๐Ÿง ' },
115
- properties: { title: [{ text: { content: 'Stellavault (AI ์ง€์‹ ๊ทธ๋ž˜ํ”„ ํ”Œ๋žซํผ)' } }] },
116
- children: part1,
117
- });
118
- console.log(`Page created: ${page.url}`);
119
-
120
- // Part 2: ํ•˜์œ„ ํŽ˜์ด์ง€๋“ค
121
- // ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜
122
- await notion.pages.create({
123
- parent: { page_id: page.id },
124
- properties: { title: [{ text: { content: '๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜' } }] },
125
- children: [
126
- h2('Monorepo ๊ตฌ์กฐ'),
127
- { type: 'code', code: { rich_text: [{ text: { content:
128
- `stellavault/
129
- โ”œโ”€โ”€ packages/
130
- โ”‚ โ”œโ”€โ”€ core/ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์—”์ง„ + MCP ์„œ๋ฒ„ + REST API + Intelligence
131
- โ”‚ โ”‚ โ”œโ”€โ”€ indexer/ Vault ์Šค์บ๋„ˆ + ์ฒญํ‚น + ์ž„๋ฒ ๋”ฉ
132
- โ”‚ โ”‚ โ”œโ”€โ”€ search/ BM25 + Cosine + RRF
133
- โ”‚ โ”‚ โ”œโ”€โ”€ store/ SQLite-vec ๋ฒกํ„ฐ ์Šคํ† ์–ด
134
- โ”‚ โ”‚ โ”œโ”€โ”€ intelligence/ FSRS + Gap + Duplicate + Contradiction + Learning Path
135
- โ”‚ โ”‚ โ”œโ”€โ”€ mcp/ MCP ์„œ๋ฒ„ (13+ tools) + Custom Tool Builder
136
- โ”‚ โ”‚ โ”œโ”€โ”€ plugins/ Plugin SDK + Webhook Manager
137
- โ”‚ โ”‚ โ”œโ”€โ”€ api/ REST API + Graph Data + Embed + Profile
138
- โ”‚ โ”‚ โ”œโ”€โ”€ pack/ Knowledge Pack (.sv-pack)
139
- โ”‚ โ”‚ โ”œโ”€โ”€ i18n/ ๋‹ค๊ตญ์–ด (en/ko/ja/zh)
140
- โ”‚ โ”‚ โ””โ”€โ”€ utils/ Error Recovery (retry + StellavaultError)
141
- โ”‚ โ”œโ”€โ”€ cli/ 19 CLI ๋ช…๋ น์–ด
142
- โ”‚ โ”‚ โ””โ”€โ”€ commands/ init, index, search, graph, serve, decay, learn,
143
- โ”‚ โ”‚ brief, digest, review, gaps, duplicates, contradictions,
144
- โ”‚ โ”‚ clip, sync, card, status, pack
145
- โ”‚ โ”œโ”€โ”€ graph/ 3D Knowledge Graph (React Three Fiber)
146
- โ”‚ โ”‚ โ”œโ”€โ”€ components/ Layout, Graph3D, GraphNodes, GraphEdges,
147
- โ”‚ โ”‚ โ”‚ SearchBar, ClusterFilter, TypeFilter, Timeline,
148
- โ”‚ โ”‚ โ”‚ HealthDashboard, ToolsPanel, NodeDetail, etc.
149
- โ”‚ โ”‚ โ”œโ”€โ”€ hooks/ useGraph, useSearch, useLayout, useDecay,
150
- โ”‚ โ”‚ โ”‚ useKeyboardNav, useExport, useMotion, usePulse
151
- โ”‚ โ”‚ โ”œโ”€โ”€ stores/ Zustand graph-store (์ „์ฒด ์ƒํƒœ ๊ด€๋ฆฌ)
152
- โ”‚ โ”‚ โ””โ”€โ”€ embed/ EmbedGraph (iframe ์œ„์ ฏ)
153
- โ”‚ โ””โ”€โ”€ sync/ Notion-Obsidian ๋™๊ธฐํ™”
154
- โ””โ”€โ”€ scripts/ api-only.mjs` } }], language: 'plain text' } },
155
- d(),
156
- h2('Intelligence Layer'),
157
- table(['๋ชจ๋“ˆ', '๊ธฐ๋Šฅ', 'ํŒŒ์ผ'], [
158
- ['FSRS Decay Engine', '๊ธฐ์–ต ๊ฐ์‡  ์ถ”์  (SM2 ์•Œ๊ณ ๋ฆฌ์ฆ˜)', 'intelligence/fsrs.ts + decay-engine.ts'],
159
- ['Gap Detector', 'ํด๋Ÿฌ์Šคํ„ฐ ๊ฐ„ ์ง€์‹ ๊ฐญ ํƒ์ง€', 'intelligence/gap-detector.ts'],
160
- ['Duplicate Detector', '๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ๊ธฐ๋ฐ˜ ์ค‘๋ณต ํƒ์ง€', 'intelligence/duplicate-detector.ts'],
161
- ['Contradiction Detector', '๋ชจ์ˆœ ์ง„์ˆ  ํƒ์ง€ (NLI ํŒจํ„ด)', 'intelligence/contradiction-detector.ts'],
162
- ['Learning Path', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ƒ์„ฑ', 'intelligence/learning-path.ts'],
163
- ['Predictive Gaps', '๊ทธ๋ž˜ํ”„ ํ† ํด๋กœ์ง€ ๊ธฐ๋ฐ˜ ์˜ˆ์ธก', 'intelligence/predictive-gaps.ts'],
164
- ['Semantic Versioning', '์ž„๋ฒ ๋”ฉ ๋“œ๋ฆฌํ”„ํŠธ ์ถ”์ ', 'intelligence/semantic-versioning.ts'],
165
- ['Notifications', '์„ค์ • ๊ฐ€๋Šฅํ•œ ์•Œ๋ฆผ ์‹œ์Šคํ…œ', 'intelligence/notifications.ts'],
166
- ]),
167
- d(),
168
- h2('MCP Tools (13+)'),
169
- table(['#', 'Tool', '๊ธฐ๋Šฅ'], [
170
- ['1', 'search', 'RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰'],
171
- ['2', 'get-document', '๋ฌธ์„œ ์ „๋ฌธ ์กฐํšŒ'],
172
- ['3', 'list-topics', 'ํ† ํ”ฝ ํด๋ผ์šฐ๋“œ'],
173
- ['4', 'get-related', '๊ด€๋ จ ๋ฌธ์„œ ํƒ์ƒ‰'],
174
- ['5', 'generate-claude-md', 'CLAUDE.md ์ž๋™ ์ƒ์„ฑ'],
175
- ['6', 'create-snapshot', '์ปจํ…์ŠคํŠธ ์Šค๋ƒ…์ƒท'],
176
- ['7', 'load-snapshot', '์Šค๋ƒ…์ƒท ๋ณต์›'],
177
- ['8', 'log-decision', '๊ธฐ์ˆ  ๊ฒฐ์ • ๊ธฐ๋ก'],
178
- ['9', 'find-decisions', '๊ฒฐ์ • ๊ฒ€์ƒ‰'],
179
- ['10', 'export', 'JSON/CSV ๋‚ด๋ณด๋‚ด๊ธฐ'],
180
- ['11', 'get-decay-status', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
181
- ['12', 'get-morning-brief', '์•„์นจ ์ง€์‹ ๋ธŒ๋ฆฌํ•‘'],
182
- ['13', 'get-learning-path', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ถ”์ฒœ'],
183
- ]),
184
- ],
185
- });
186
- console.log(' + ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜');
187
-
188
- // PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ
189
- await notion.pages.create({
190
- parent: { page_id: page.id },
191
- properties: { title: [{ text: { content: 'PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ' } }] },
192
- children: [
193
- h2('PM ๋ถ„์„'),
194
- table(['๋ฌธ์„œ', '๋‚ด์šฉ'], [
195
- ['core.prd.md', 'Phase 4 ๊ธฐ๋Šฅ ๋ถ„์„ (FSRS, ๊ฐญ ํƒ์ง€, ํด๋ฆฌํ•‘ ๋“ฑ)'],
196
- ['stellavault-advanced.prd.md', 'Advanced 22 features PRD (P0-P3, 5 tiers)'],
197
- ['stellavault-federation.prd.md', 'Federation Protocol PRD (P2P ๋ถ„์‚ฐ ์ง€์‹ ๋„คํŠธ์›Œํฌ)'],
198
- ]),
199
- d(),
200
- h2('๊ตฌํ˜„ ์™„๋ฃŒ ๊ธฐ๋Šฅ (18/22)'),
201
- table(['Tier', '๊ธฐ๋Šฅ', '์ƒํƒœ'], [
202
- ['P0', 'F-A01 Onboarding Wizard (stellavault init)', 'โœ…'],
203
- ['P0', 'F-A02 Error Recovery System (withRetry + StellavaultError)', 'โœ…'],
204
- ['P0', 'F-A03 Performance Optimization (์ธ๋ฑ์„œ resilience)', 'โœ…'],
205
- ['P0', 'F-A08 Embeddable Graph Widget (/api/embed)', 'โœ…'],
206
- ['P1', 'F-A21 CLI Output Polish (--json, --quiet)', 'โœ…'],
207
- ['P1', 'F-A11 AI Learning Path Generator (sv learn + MCP)', 'โœ…'],
208
- ['P1', 'F-A05 Notification Center', 'โœ…'],
209
- ['P1', 'F-A09 Knowledge Profile (/api/profile)', 'โœ…'],
210
- ['P1', 'F-A22 Streamable HTTP MCP', 'โœ…'],
211
- ['P1', 'F-A20 10K+ Performance (maxVisibleNodes)', 'โœ…'],
212
- ['P1', 'F-A15 Plugin SDK (PluginManager + ์ด๋ฒคํŠธ ๋ฒ„์Šค)', 'โœ…'],
213
- ['P2', 'F-A12 Contradiction Detector', 'โœ…'],
214
- ['P2', 'F-A17 Webhook/Event System', 'โœ…'],
215
- ['P2', 'F-A16 Custom MCP Tool Builder (YAML)', 'โœ…'],
216
- ['P2', 'F-A18 Keyboard Graph Navigation', 'โœ…'],
217
- ['P2', 'F-A13 Semantic Versioning (์ž„๋ฒ ๋”ฉ ๋“œ๋ฆฌํ”„ํŠธ)', 'โœ…'],
218
- ['P2', 'F-A14 Predictive Gap Analysis', 'โœ…'],
219
- ['P2', 'F-A19 i18n (en/ko/ja/zh)', 'โœ…'],
220
- ]),
221
- d(),
222
- h2('๋ฏธ๊ตฌํ˜„ (์ธํ”„๋ผ ํ•„์š”)'),
223
- table(['๊ธฐ๋Šฅ', 'ํ•„์š” ์ธํ”„๋ผ', '์ƒํƒœ'], [
224
- ['F-A04 Cloud Sync Engine', 'S3/R2 ์Šคํ† ๋ฆฌ์ง€', '๋Œ€๊ธฐ'],
225
- ['F-A06 Team Vault', '์ธ์ฆ ์„œ๋ฒ„', '๋Œ€๊ธฐ'],
226
- ['F-A07 Pack Marketplace', '์›น ์„œ๋น„์Šค', '๋Œ€๊ธฐ'],
227
- ['P3 (5๊ฑด)', '์žฅ๊ธฐ ๋น„์ „', '๋Œ€๊ธฐ'],
228
- ]),
229
- ],
230
- });
231
- console.log(' + PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ');
232
-
233
- // ๊ธฐ๋Šฅ ์ƒ์„ธ
234
- await notion.pages.create({
235
- parent: { page_id: page.id },
236
- properties: { title: [{ text: { content: '๊ธฐ๋Šฅ ์ƒ์„ธ ๋ช…์„ธ' } }] },
237
- children: [
238
- h2('CLI ๋ช…๋ น์–ด (19๊ฐœ)'),
239
- table(['๋ช…๋ น์–ด', '๊ธฐ๋Šฅ'], [
240
- ['sv init', '์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ 3๋‹จ๊ณ„ ์…‹์—… ์œ„์ €๋“œ'],
241
- ['sv index <path>', 'Obsidian vault ๋ฒกํ„ฐํ™” ์ธ๋ฑ์‹ฑ'],
242
- ['sv search <query>', 'ํ„ฐ๋ฏธ๋„ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰'],
243
- ['sv graph', '3D Knowledge Graph + API ์„œ๋ฒ„ ์‹คํ–‰'],
244
- ['sv serve', 'MCP ์„œ๋ฒ„ (stdio)'],
245
- ['sv status', '์ธ๋ฑ์Šค ์ƒํƒœ ํ™•์ธ'],
246
- ['sv decay', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
247
- ['sv learn', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ถ”์ฒœ'],
248
- ['sv brief', '์˜ค๋Š˜์˜ ์ง€์‹ ๋ธŒ๋ฆฌํ•‘'],
249
- ['sv digest', '์ฃผ๊ฐ„ ํ™œ๋™ ๋ฆฌํฌํŠธ'],
250
- ['sv review', 'FSRS ๊ธฐ๋ฐ˜ ์ผ์ผ ๋ฆฌ๋ทฐ ์„ธ์…˜'],
251
- ['sv gaps', '์ง€์‹ ๊ฐญ ํƒ์ง€'],
252
- ['sv duplicates', '์ค‘๋ณต ๋…ธํŠธ ํƒ์ง€'],
253
- ['sv contradictions', '๋ชจ์ˆœ ์ง„์ˆ  ํƒ์ง€'],
254
- ['sv clip <url>', '์›น/YouTube ํด๋ฆฌํ•‘'],
255
- ['sv sync', 'Notion โ†’ Obsidian ๋™๊ธฐํ™”'],
256
- ['sv card', 'SVG ํ”„๋กœํ•„ ์นด๋“œ ์ƒ์„ฑ'],
257
- ['sv pack <cmd>', 'Knowledge Pack ๊ด€๋ฆฌ'],
258
- ]),
259
- d(),
260
- h2('3D Graph UI ์ปดํฌ๋„ŒํŠธ'),
261
- table(['์ปดํฌ๋„ŒํŠธ', '๊ธฐ๋Šฅ'], [
262
- ['Graph3D', 'R3F Canvas + OrbitControls + ์ž๋™ ํšŒ์ „'],
263
- ['GraphNodes', 'Points ํด๋ผ์šฐ๋“œ ๋ Œ๋”๋ง + ํด๋Ÿฌ์Šคํ„ฐ ์ƒ‰์ƒ + Decay ์˜ค๋ฒ„๋ ˆ์ด'],
264
- ['ConstellationView', 'MST ๊ธฐ๋ฐ˜ ๋ณ„์ž๋ฆฌ ๋ทฐ + LOD 3๋‹จ๊ณ„'],
265
- ['SearchBar', '์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰ + ๊ฒ€์ƒ‰ ํžˆ์Šคํ† ๋ฆฌ ๋“œ๋กญ๋‹ค์šด'],
266
- ['ClusterFilter', 'ํด๋Ÿฌ์Šคํ„ฐ ํ† ๊ธ€ ํ•„ํ„ฐ'],
267
- ['TypeFilter', 'source/type ํ•„ํ„ฐ ๋“œ๋กญ๋‹ค์šด'],
268
- ['Timeline', '๋‚ ์งœ ๋ฒ”์œ„ ์Šฌ๋ผ์ด๋” + ํžˆ์Šคํ† ๊ทธ๋žจ'],
269
- ['HealthDashboard', '์ข…ํ•ฉ ๊ฑด๊ฐ•๋„ (decay/gaps/dups/growth)'],
270
- ['ToolsPanel', 'Intelligence 6ํƒญ (Gaps/Duplicates/Decay/Clip/Sync/Health)'],
271
- ['NodeDetail', '๋…ธ๋“œ ์ƒ์„ธ ํŒจ๋„ + ๊ด€๋ จ ๋ฌธ์„œ + Obsidian ์—ด๊ธฐ'],
272
- ['EmbedGraph', 'iframe ์ž„๋ฒ ๋“œ์šฉ ๋ฏธ๋‹ˆ ๊ทธ๋ž˜ํ”„'],
273
- ]),
274
- d(),
275
- h2('API Endpoints'),
276
- table(['Method', 'Path', '๊ธฐ๋Šฅ'], [
277
- ['GET', '/api/graph', '์ „์ฒด ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ (cached)'],
278
- ['GET', '/api/search', 'RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰'],
279
- ['GET', '/api/document/:id', '๋ฌธ์„œ ์ „๋ฌธ + ๊ด€๋ จ ๋ฌธ์„œ'],
280
- ['GET', '/api/stats', '์ธ๋ฑ์Šค ํ†ต๊ณ„'],
281
- ['GET', '/api/decay', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
282
- ['GET', '/api/duplicates', '์ค‘๋ณต ๋…ธํŠธ ํƒ์ง€'],
283
- ['GET', '/api/gaps', '์ง€์‹ ๊ฐญ ๋ฆฌํฌํŠธ'],
284
- ['GET', '/api/health', '์ข…ํ•ฉ ๊ฑด๊ฐ•๋„ ๋Œ€์‹œ๋ณด๋“œ'],
285
- ['GET', '/api/profile', '์ง€์‹ ํ”„๋กœํ•„ (๊ณต๊ฐœ์šฉ)'],
286
- ['GET', '/api/embed', '์ž„๋ฒ ๋“œ์šฉ ๊ฒฝ๋Ÿ‰ ๊ทธ๋ž˜ํ”„'],
287
- ['GET', '/api/profile-card', 'SVG ํ”„๋กœํ•„ ์นด๋“œ'],
288
- ['POST', '/api/clip', '์›น ํด๋ฆฌํ•‘'],
289
- ['POST', '/api/sync', 'Notion ๋™๊ธฐํ™” ํŠธ๋ฆฌ๊ฑฐ'],
290
- ['POST', '/api/duplicates/merge', '์ค‘๋ณต ๋…ธํŠธ ๋ณ‘ํ•ฉ'],
291
- ['POST', '/api/gaps/create-bridge', '๊ฐญ ๋ธŒ๋ฆฟ์ง€ ๋…ธํŠธ ์ƒ์„ฑ'],
292
- ]),
293
- ],
294
- });
295
- console.log(' + ๊ธฐ๋Šฅ ์ƒ์„ธ ๋ช…์„ธ');
296
-
297
- // Next Steps
298
- await notion.pages.create({
299
- parent: { page_id: page.id },
300
- properties: { title: [{ text: { content: '๐Ÿ”ฎ Next: Stella Network (Federation)' } }] },
301
- children: [
302
- callout('Stellavault์˜ ๋‹ค์Œ ๋‹จ๊ณ„: ๋ถ„์‚ฐ ์ง€์‹ ๋„คํŠธ์›Œํฌ (Federation Protocol)', '๐ŸŒ'),
303
- p('๊ฐ Stellavault ์ธ์Šคํ„ด์Šค๋ฅผ P2P ๋…ธ๋“œ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ "์ง€์‹ ํ† ๋ ŒํŠธ" ๊ตฌํ˜„.'),
304
- p('์ž„๋ฒ ๋”ฉ๋งŒ ๊ณต์œ  (์›๋ฌธ ๋น„๊ณต๊ฐœ), AI ์—์ด์ „ํŠธ๊ฐ€ ์ง‘๋‹จ ์ง€์„ฑ์— ์ ‘๊ทผ.'),
305
- p('์ƒ์„ธ: Stella Network ํŽ˜์ด์ง€ ์ฐธ์กฐ'),
306
- d(),
307
- h2('Git History'),
308
- table(['Commit', '๋‚ด์šฉ'], [
309
- ['94dceb4', 'feat: initial release of Stellavault'],
310
- ['d1b01c6', 'docs: rewrite README with core value proposition'],
311
- ['9b8caac', 'feat: P0 features (init, error recovery, perf, embed)'],
312
- ['1a72d52', 'feat: P1 features (CLI polish, learning path, notifications, profile, HTTP MCP, plugin SDK)'],
313
- ['6175b80', 'feat: P2 features (contradictions, webhooks, custom MCP, keyboard nav, semantic versioning, predictive gaps, i18n)'],
314
- ]),
315
- ],
316
- });
317
- console.log(' + Next Steps');
318
-
319
- console.log(`\nโœ… Done! ${page.url}`);
320
- }
321
-
322
- main().catch(console.error);
1
+ import { Client } from '@notionhq/client';
2
+
3
+ const notion = new Client({ auth: 'process.env.NOTION_TOKEN' });
4
+ const PARENT_PAGE_ID = '330dcee017df808d92d4d9ff46fa7697';
5
+
6
+ function h2(t) { return { type: 'heading_2', heading_2: { rich_text: [{ text: { content: t } }] } }; }
7
+ function p(t) { return { type: 'paragraph', paragraph: { rich_text: [{ text: { content: t } }] } }; }
8
+ function d() { return { type: 'divider', divider: {} }; }
9
+ function callout(t, e = '๐Ÿ’ก') { return { type: 'callout', callout: { rich_text: [{ text: { content: t } }], icon: { emoji: e } } }; }
10
+
11
+ function table(headers, rows) {
12
+ return {
13
+ type: 'table', table: {
14
+ table_width: headers.length,
15
+ has_column_header: true,
16
+ has_row_header: false,
17
+ children: [
18
+ { type: 'table_row', table_row: { cells: headers.map(h => [{ type: 'text', text: { content: h } }]) } },
19
+ ...rows.map(row => ({
20
+ type: 'table_row', table_row: { cells: row.map(c => [{ type: 'text', text: { content: c } }]) }
21
+ })),
22
+ ],
23
+ }
24
+ };
25
+ }
26
+
27
+ function columnList(columns) {
28
+ return {
29
+ type: 'column_list', column_list: {
30
+ children: columns.map(col => ({
31
+ type: 'column', column: { children: col }
32
+ }))
33
+ }
34
+ };
35
+ }
36
+
37
+ async function main() {
38
+ console.log('Creating Stellavault project page...');
39
+
40
+ const part1 = [
41
+ // Callout header
42
+ callout('Stellavault โ€” Notes die in folders. Stellavault keeps your knowledge alive.', '๐Ÿง '),
43
+
44
+ // ํ”„๋กœ์ ํŠธ ๊ฐœ์š”
45
+ h2('ํ”„๋กœ์ ํŠธ ๊ฐœ์š”'),
46
+ table(['ํ•ญ๋ชฉ', '๋‚ด์šฉ'], [
47
+ ['ํ”„๋กœ์ ํŠธ๋ช…', 'Stellavault (์Šคํ…”๋ผ๋ณผํŠธ)'],
48
+ ['์œ ํ˜•', '๊ฐœ์ธ ์ง€์‹ ์ธํ…”๋ฆฌ์ „์Šค ํ”Œ๋žซํผ (์˜คํ”ˆ์†Œ์Šค + Pro)'],
49
+ ['๋ชฉ์ ', 'Obsidian vault๋ฅผ ๋ฒกํ„ฐํ™”ํ•˜์—ฌ 3D ์‹œ๊ฐํ™”, AI ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰, ๊ธฐ์–ต ๊ฐ์‡  ์ถ”์ , MCP๋กœ AI ์—์ด์ „ํŠธ ์—ฐ๊ฒฐ'],
50
+ ['๋Œ€์ƒ', 'AI ๊ฐœ๋ฐœ์ž, ์ง€์‹ ๋…ธ๋™์ž, Obsidian ์‚ฌ์šฉ์ž'],
51
+ ['ํ•ต์‹ฌ ๊ฐ€์น˜', '์ง€์‹ ๊ฐ„ ์—ฐ๊ฒฐ ์ž๋™ ๋ฐœ๊ฒฌ + ์žŠํ˜€๊ฐ€๋Š” ์ง€์‹ ๊ฐ์ง€ + AI ์—์ด์ „ํŠธ์— ์ง€์‹ ์ ‘์†'],
52
+ ['๋ผ์ด์„ ์Šค', 'MIT (์˜คํ”ˆ์†Œ์Šค)'],
53
+ ['GitHub', 'github.com/Evanciel/stellavault'],
54
+ ['CLI', 'stellavault (alias: sv) โ€” 19๊ฐœ ๋ช…๋ น์–ด'],
55
+ ['MCP', '13+ tools โ€” Claude Code ๋“ฑ AI ์—์ด์ „ํŠธ ์—ฐ๋™'],
56
+ ]),
57
+ d(),
58
+
59
+ // ํ•ต์‹ฌ ๊ธฐ๋Šฅ
60
+ h2('ํ•ต์‹ฌ ๊ธฐ๋Šฅ'),
61
+ columnList([
62
+ [
63
+ callout('3D Knowledge Graph\nReact Three Fiber ๊ธฐ๋ฐ˜ ๋‰ด๋Ÿด ๋„คํŠธ์›Œํฌ ์‹œ๊ฐํ™”\nConstellation View + LOD 3๋‹จ๊ณ„\nTimeline ์Šฌ๋ผ์ด๋” + Type/Source ํ•„ํ„ฐ', '๐ŸŒ'),
64
+ ],
65
+ [
66
+ callout('AI Semantic Search\nBM25 + Cosine + RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ\n384์ฐจ์› ๋กœ์ปฌ ๋ฒกํ„ฐ ์ž„๋ฒ ๋”ฉ\n์‹œ๋งจํ‹ฑ + ํ‚ค์›Œ๋“œ ์œตํ•ฉ', '๐Ÿ”'),
67
+ ],
68
+ ]),
69
+ columnList([
70
+ [
71
+ callout('Intelligence Layer\nFSRS ๊ธฐ์–ต ๊ฐ์‡  ์ถ”์ \n๊ฐญ ํƒ์ง€ + ๋ชจ์ˆœ ํƒ์ง€\n์ค‘๋ณต ํƒ์ง€ + ์˜ˆ์ธก์  ๊ฐญ ๋ถ„์„\nAI ํ•™์Šต ๊ฒฝ๋กœ ์ƒ์„ฑ', '๐Ÿงฌ'),
72
+ ],
73
+ [
74
+ callout('MCP + Plugin\n13๊ฐœ MCP ๋„๊ตฌ (AI ์—์ด์ „ํŠธ ์—ฐ๋™)\nPlugin SDK (์ด๋ฒคํŠธ ๋ฒ„์Šค)\nWebhook ์‹œ์Šคํ…œ\n์ปค์Šคํ…€ MCP ๋„๊ตฌ ๋นŒ๋” (YAML)', '๐Ÿ”Œ'),
75
+ ],
76
+ ]),
77
+ d(),
78
+
79
+ // ๊ธฐ์ˆ  ์Šคํƒ
80
+ h2('๊ธฐ์ˆ  ์Šคํƒ'),
81
+ table(['์นดํ…Œ๊ณ ๋ฆฌ', '๊ธฐ์ˆ ', '๋ฒ„์ „ / ๋น„๊ณ '], [
82
+ ['Runtime', 'Node.js (ESM)', '20+'],
83
+ ['Language', 'TypeScript', 'Strict mode'],
84
+ ['Monorepo', 'npm workspaces', '4 packages (core, cli, graph, sync)'],
85
+ ['Vector DB', 'SQLite-vec (better-sqlite3)', '384์ฐจ์› ์ž„๋ฒ ๋”ฉ'],
86
+ ['Embedding', '@xenova/transformers', 'all-MiniLM-L6-v2 (๋กœ์ปฌ, API ํ‚ค ๋ถˆํ•„์š”)'],
87
+ ['Search', 'BM25 + Cosine + RRF', 'K=60, ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํ“จ์ „'],
88
+ ['3D ์‹œ๊ฐํ™”', 'React Three Fiber + drei + Three.js', 'R3F 9.0 / Three 0.170'],
89
+ ['State', 'Zustand', '5.0'],
90
+ ['Memory Model', 'FSRS (Free Spaced Repetition)', 'SM2 ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ณ€ํ˜•'],
91
+ ['AI ์—ฐ๋™', 'MCP (@modelcontextprotocol/sdk)', 'stdio + Streamable HTTP'],
92
+ ['Build', 'Vite (graph) + tsc (core/cli)', 'Vite 6.0'],
93
+ ['Testing', 'Vitest', '116 tests'],
94
+ ]),
95
+ d(),
96
+
97
+ // ๊ทœ๋ชจ ์ง€ํ‘œ
98
+ h2('๊ทœ๋ชจ ์ง€ํ‘œ'),
99
+ columnList([
100
+ [
101
+ callout('์ฝ”๋“œ ๊ทœ๋ชจ\n175+ ์†Œ์Šค ํŒŒ์ผ\n30,000+ LOC (TypeScript)\n4 workspace packages\n19 CLI ๋ช…๋ น์–ด\n13+ MCP ๋„๊ตฌ', '๐Ÿ“Š'),
102
+ ],
103
+ [
104
+ callout('๊ธฐ๋Šฅ ํ˜„ํ™ฉ\nPRD 22๊ฐœ ๊ธฐ๋Šฅ ์ค‘ 18๊ฐœ ๊ตฌํ˜„\nP0 (4/4) + P1 (7/7) + P2 (7/7)\nIntelligence ๋ชจ๋“ˆ 8๊ฐœ\ni18n 4๊ฐœ ์–ธ์–ด (en/ko/ja/zh)', 'โœ…'),
105
+ ],
106
+ [
107
+ callout('์•„ํ‚คํ…์ฒ˜\nHybrid Search (BM25+Vector+RRF)\nPlugin SDK + Webhook\nEmbed Widget (iframe)\nStreamable HTTP MCP\nKeyboard Navigation', '๐Ÿ—๏ธ'),
108
+ ],
109
+ ]),
110
+ ];
111
+
112
+ const page = await notion.pages.create({
113
+ parent: { page_id: PARENT_PAGE_ID },
114
+ icon: { emoji: '๐Ÿง ' },
115
+ properties: { title: [{ text: { content: 'Stellavault (AI ์ง€์‹ ๊ทธ๋ž˜ํ”„ ํ”Œ๋žซํผ)' } }] },
116
+ children: part1,
117
+ });
118
+ console.log(`Page created: ${page.url}`);
119
+
120
+ // Part 2: ํ•˜์œ„ ํŽ˜์ด์ง€๋“ค
121
+ // ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜
122
+ await notion.pages.create({
123
+ parent: { page_id: page.id },
124
+ properties: { title: [{ text: { content: '๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜' } }] },
125
+ children: [
126
+ h2('Monorepo ๊ตฌ์กฐ'),
127
+ { type: 'code', code: { rich_text: [{ text: { content:
128
+ `stellavault/
129
+ โ”œโ”€โ”€ packages/
130
+ โ”‚ โ”œโ”€โ”€ core/ ๋ฒกํ„ฐ ๊ฒ€์ƒ‰ ์—”์ง„ + MCP ์„œ๋ฒ„ + REST API + Intelligence
131
+ โ”‚ โ”‚ โ”œโ”€โ”€ indexer/ Vault ์Šค์บ๋„ˆ + ์ฒญํ‚น + ์ž„๋ฒ ๋”ฉ
132
+ โ”‚ โ”‚ โ”œโ”€โ”€ search/ BM25 + Cosine + RRF
133
+ โ”‚ โ”‚ โ”œโ”€โ”€ store/ SQLite-vec ๋ฒกํ„ฐ ์Šคํ† ์–ด
134
+ โ”‚ โ”‚ โ”œโ”€โ”€ intelligence/ FSRS + Gap + Duplicate + Contradiction + Learning Path
135
+ โ”‚ โ”‚ โ”œโ”€โ”€ mcp/ MCP ์„œ๋ฒ„ (13+ tools) + Custom Tool Builder
136
+ โ”‚ โ”‚ โ”œโ”€โ”€ plugins/ Plugin SDK + Webhook Manager
137
+ โ”‚ โ”‚ โ”œโ”€โ”€ api/ REST API + Graph Data + Embed + Profile
138
+ โ”‚ โ”‚ โ”œโ”€โ”€ pack/ Knowledge Pack (.sv-pack)
139
+ โ”‚ โ”‚ โ”œโ”€โ”€ i18n/ ๋‹ค๊ตญ์–ด (en/ko/ja/zh)
140
+ โ”‚ โ”‚ โ””โ”€โ”€ utils/ Error Recovery (retry + StellavaultError)
141
+ โ”‚ โ”œโ”€โ”€ cli/ 19 CLI ๋ช…๋ น์–ด
142
+ โ”‚ โ”‚ โ””โ”€โ”€ commands/ init, index, search, graph, serve, decay, learn,
143
+ โ”‚ โ”‚ brief, digest, review, gaps, duplicates, contradictions,
144
+ โ”‚ โ”‚ clip, sync, card, status, pack
145
+ โ”‚ โ”œโ”€โ”€ graph/ 3D Knowledge Graph (React Three Fiber)
146
+ โ”‚ โ”‚ โ”œโ”€โ”€ components/ Layout, Graph3D, GraphNodes, GraphEdges,
147
+ โ”‚ โ”‚ โ”‚ SearchBar, ClusterFilter, TypeFilter, Timeline,
148
+ โ”‚ โ”‚ โ”‚ HealthDashboard, ToolsPanel, NodeDetail, etc.
149
+ โ”‚ โ”‚ โ”œโ”€โ”€ hooks/ useGraph, useSearch, useLayout, useDecay,
150
+ โ”‚ โ”‚ โ”‚ useKeyboardNav, useExport, useMotion, usePulse
151
+ โ”‚ โ”‚ โ”œโ”€โ”€ stores/ Zustand graph-store (์ „์ฒด ์ƒํƒœ ๊ด€๋ฆฌ)
152
+ โ”‚ โ”‚ โ””โ”€โ”€ embed/ EmbedGraph (iframe ์œ„์ ฏ)
153
+ โ”‚ โ””โ”€โ”€ sync/ Notion-Obsidian ๋™๊ธฐํ™”
154
+ โ””โ”€โ”€ scripts/ api-only.mjs` } }], language: 'plain text' } },
155
+ d(),
156
+ h2('Intelligence Layer'),
157
+ table(['๋ชจ๋“ˆ', '๊ธฐ๋Šฅ', 'ํŒŒ์ผ'], [
158
+ ['FSRS Decay Engine', '๊ธฐ์–ต ๊ฐ์‡  ์ถ”์  (SM2 ์•Œ๊ณ ๋ฆฌ์ฆ˜)', 'intelligence/fsrs.ts + decay-engine.ts'],
159
+ ['Gap Detector', 'ํด๋Ÿฌ์Šคํ„ฐ ๊ฐ„ ์ง€์‹ ๊ฐญ ํƒ์ง€', 'intelligence/gap-detector.ts'],
160
+ ['Duplicate Detector', '๋ฒกํ„ฐ ์œ ์‚ฌ๋„ ๊ธฐ๋ฐ˜ ์ค‘๋ณต ํƒ์ง€', 'intelligence/duplicate-detector.ts'],
161
+ ['Contradiction Detector', '๋ชจ์ˆœ ์ง„์ˆ  ํƒ์ง€ (NLI ํŒจํ„ด)', 'intelligence/contradiction-detector.ts'],
162
+ ['Learning Path', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ƒ์„ฑ', 'intelligence/learning-path.ts'],
163
+ ['Predictive Gaps', '๊ทธ๋ž˜ํ”„ ํ† ํด๋กœ์ง€ ๊ธฐ๋ฐ˜ ์˜ˆ์ธก', 'intelligence/predictive-gaps.ts'],
164
+ ['Semantic Versioning', '์ž„๋ฒ ๋”ฉ ๋“œ๋ฆฌํ”„ํŠธ ์ถ”์ ', 'intelligence/semantic-versioning.ts'],
165
+ ['Notifications', '์„ค์ • ๊ฐ€๋Šฅํ•œ ์•Œ๋ฆผ ์‹œ์Šคํ…œ', 'intelligence/notifications.ts'],
166
+ ]),
167
+ d(),
168
+ h2('MCP Tools (13+)'),
169
+ table(['#', 'Tool', '๊ธฐ๋Šฅ'], [
170
+ ['1', 'search', 'RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰'],
171
+ ['2', 'get-document', '๋ฌธ์„œ ์ „๋ฌธ ์กฐํšŒ'],
172
+ ['3', 'list-topics', 'ํ† ํ”ฝ ํด๋ผ์šฐ๋“œ'],
173
+ ['4', 'get-related', '๊ด€๋ จ ๋ฌธ์„œ ํƒ์ƒ‰'],
174
+ ['5', 'generate-claude-md', 'CLAUDE.md ์ž๋™ ์ƒ์„ฑ'],
175
+ ['6', 'create-snapshot', '์ปจํ…์ŠคํŠธ ์Šค๋ƒ…์ƒท'],
176
+ ['7', 'load-snapshot', '์Šค๋ƒ…์ƒท ๋ณต์›'],
177
+ ['8', 'log-decision', '๊ธฐ์ˆ  ๊ฒฐ์ • ๊ธฐ๋ก'],
178
+ ['9', 'find-decisions', '๊ฒฐ์ • ๊ฒ€์ƒ‰'],
179
+ ['10', 'export', 'JSON/CSV ๋‚ด๋ณด๋‚ด๊ธฐ'],
180
+ ['11', 'get-decay-status', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
181
+ ['12', 'get-morning-brief', '์•„์นจ ์ง€์‹ ๋ธŒ๋ฆฌํ•‘'],
182
+ ['13', 'get-learning-path', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ถ”์ฒœ'],
183
+ ]),
184
+ ],
185
+ });
186
+ console.log(' + ๊ธฐ์ˆ  ์•„ํ‚คํ…์ฒ˜');
187
+
188
+ // PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ
189
+ await notion.pages.create({
190
+ parent: { page_id: page.id },
191
+ properties: { title: [{ text: { content: 'PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ' } }] },
192
+ children: [
193
+ h2('PM ๋ถ„์„'),
194
+ table(['๋ฌธ์„œ', '๋‚ด์šฉ'], [
195
+ ['core.prd.md', 'Phase 4 ๊ธฐ๋Šฅ ๋ถ„์„ (FSRS, ๊ฐญ ํƒ์ง€, ํด๋ฆฌํ•‘ ๋“ฑ)'],
196
+ ['stellavault-advanced.prd.md', 'Advanced 22 features PRD (P0-P3, 5 tiers)'],
197
+ ['stellavault-federation.prd.md', 'Federation Protocol PRD (P2P ๋ถ„์‚ฐ ์ง€์‹ ๋„คํŠธ์›Œํฌ)'],
198
+ ]),
199
+ d(),
200
+ h2('๊ตฌํ˜„ ์™„๋ฃŒ ๊ธฐ๋Šฅ (18/22)'),
201
+ table(['Tier', '๊ธฐ๋Šฅ', '์ƒํƒœ'], [
202
+ ['P0', 'F-A01 Onboarding Wizard (stellavault init)', 'โœ…'],
203
+ ['P0', 'F-A02 Error Recovery System (withRetry + StellavaultError)', 'โœ…'],
204
+ ['P0', 'F-A03 Performance Optimization (์ธ๋ฑ์„œ resilience)', 'โœ…'],
205
+ ['P0', 'F-A08 Embeddable Graph Widget (/api/embed)', 'โœ…'],
206
+ ['P1', 'F-A21 CLI Output Polish (--json, --quiet)', 'โœ…'],
207
+ ['P1', 'F-A11 AI Learning Path Generator (sv learn + MCP)', 'โœ…'],
208
+ ['P1', 'F-A05 Notification Center', 'โœ…'],
209
+ ['P1', 'F-A09 Knowledge Profile (/api/profile)', 'โœ…'],
210
+ ['P1', 'F-A22 Streamable HTTP MCP', 'โœ…'],
211
+ ['P1', 'F-A20 10K+ Performance (maxVisibleNodes)', 'โœ…'],
212
+ ['P1', 'F-A15 Plugin SDK (PluginManager + ์ด๋ฒคํŠธ ๋ฒ„์Šค)', 'โœ…'],
213
+ ['P2', 'F-A12 Contradiction Detector', 'โœ…'],
214
+ ['P2', 'F-A17 Webhook/Event System', 'โœ…'],
215
+ ['P2', 'F-A16 Custom MCP Tool Builder (YAML)', 'โœ…'],
216
+ ['P2', 'F-A18 Keyboard Graph Navigation', 'โœ…'],
217
+ ['P2', 'F-A13 Semantic Versioning (์ž„๋ฒ ๋”ฉ ๋“œ๋ฆฌํ”„ํŠธ)', 'โœ…'],
218
+ ['P2', 'F-A14 Predictive Gap Analysis', 'โœ…'],
219
+ ['P2', 'F-A19 i18n (en/ko/ja/zh)', 'โœ…'],
220
+ ]),
221
+ d(),
222
+ h2('๋ฏธ๊ตฌํ˜„ (์ธํ”„๋ผ ํ•„์š”)'),
223
+ table(['๊ธฐ๋Šฅ', 'ํ•„์š” ์ธํ”„๋ผ', '์ƒํƒœ'], [
224
+ ['F-A04 Cloud Sync Engine', 'S3/R2 ์Šคํ† ๋ฆฌ์ง€', '๋Œ€๊ธฐ'],
225
+ ['F-A06 Team Vault', '์ธ์ฆ ์„œ๋ฒ„', '๋Œ€๊ธฐ'],
226
+ ['F-A07 Pack Marketplace', '์›น ์„œ๋น„์Šค', '๋Œ€๊ธฐ'],
227
+ ['P3 (5๊ฑด)', '์žฅ๊ธฐ ๋น„์ „', '๋Œ€๊ธฐ'],
228
+ ]),
229
+ ],
230
+ });
231
+ console.log(' + PDCA ์‚ฐ์ถœ๋ฌผ ์š”์•ฝ');
232
+
233
+ // ๊ธฐ๋Šฅ ์ƒ์„ธ
234
+ await notion.pages.create({
235
+ parent: { page_id: page.id },
236
+ properties: { title: [{ text: { content: '๊ธฐ๋Šฅ ์ƒ์„ธ ๋ช…์„ธ' } }] },
237
+ children: [
238
+ h2('CLI ๋ช…๋ น์–ด (19๊ฐœ)'),
239
+ table(['๋ช…๋ น์–ด', '๊ธฐ๋Šฅ'], [
240
+ ['sv init', '์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ 3๋‹จ๊ณ„ ์…‹์—… ์œ„์ €๋“œ'],
241
+ ['sv index <path>', 'Obsidian vault ๋ฒกํ„ฐํ™” ์ธ๋ฑ์‹ฑ'],
242
+ ['sv search <query>', 'ํ„ฐ๋ฏธ๋„ ์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰'],
243
+ ['sv graph', '3D Knowledge Graph + API ์„œ๋ฒ„ ์‹คํ–‰'],
244
+ ['sv serve', 'MCP ์„œ๋ฒ„ (stdio)'],
245
+ ['sv status', '์ธ๋ฑ์Šค ์ƒํƒœ ํ™•์ธ'],
246
+ ['sv decay', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
247
+ ['sv learn', 'AI ํ•™์Šต ๊ฒฝ๋กœ ์ถ”์ฒœ'],
248
+ ['sv brief', '์˜ค๋Š˜์˜ ์ง€์‹ ๋ธŒ๋ฆฌํ•‘'],
249
+ ['sv digest', '์ฃผ๊ฐ„ ํ™œ๋™ ๋ฆฌํฌํŠธ'],
250
+ ['sv review', 'FSRS ๊ธฐ๋ฐ˜ ์ผ์ผ ๋ฆฌ๋ทฐ ์„ธ์…˜'],
251
+ ['sv gaps', '์ง€์‹ ๊ฐญ ํƒ์ง€'],
252
+ ['sv duplicates', '์ค‘๋ณต ๋…ธํŠธ ํƒ์ง€'],
253
+ ['sv contradictions', '๋ชจ์ˆœ ์ง„์ˆ  ํƒ์ง€'],
254
+ ['sv clip <url>', '์›น/YouTube ํด๋ฆฌํ•‘'],
255
+ ['sv sync', 'Notion โ†’ Obsidian ๋™๊ธฐํ™”'],
256
+ ['sv card', 'SVG ํ”„๋กœํ•„ ์นด๋“œ ์ƒ์„ฑ'],
257
+ ['sv pack <cmd>', 'Knowledge Pack ๊ด€๋ฆฌ'],
258
+ ]),
259
+ d(),
260
+ h2('3D Graph UI ์ปดํฌ๋„ŒํŠธ'),
261
+ table(['์ปดํฌ๋„ŒํŠธ', '๊ธฐ๋Šฅ'], [
262
+ ['Graph3D', 'R3F Canvas + OrbitControls + ์ž๋™ ํšŒ์ „'],
263
+ ['GraphNodes', 'Points ํด๋ผ์šฐ๋“œ ๋ Œ๋”๋ง + ํด๋Ÿฌ์Šคํ„ฐ ์ƒ‰์ƒ + Decay ์˜ค๋ฒ„๋ ˆ์ด'],
264
+ ['ConstellationView', 'MST ๊ธฐ๋ฐ˜ ๋ณ„์ž๋ฆฌ ๋ทฐ + LOD 3๋‹จ๊ณ„'],
265
+ ['SearchBar', '์‹œ๋งจํ‹ฑ ๊ฒ€์ƒ‰ + ๊ฒ€์ƒ‰ ํžˆ์Šคํ† ๋ฆฌ ๋“œ๋กญ๋‹ค์šด'],
266
+ ['ClusterFilter', 'ํด๋Ÿฌ์Šคํ„ฐ ํ† ๊ธ€ ํ•„ํ„ฐ'],
267
+ ['TypeFilter', 'source/type ํ•„ํ„ฐ ๋“œ๋กญ๋‹ค์šด'],
268
+ ['Timeline', '๋‚ ์งœ ๋ฒ”์œ„ ์Šฌ๋ผ์ด๋” + ํžˆ์Šคํ† ๊ทธ๋žจ'],
269
+ ['HealthDashboard', '์ข…ํ•ฉ ๊ฑด๊ฐ•๋„ (decay/gaps/dups/growth)'],
270
+ ['ToolsPanel', 'Intelligence 6ํƒญ (Gaps/Duplicates/Decay/Clip/Sync/Health)'],
271
+ ['NodeDetail', '๋…ธ๋“œ ์ƒ์„ธ ํŒจ๋„ + ๊ด€๋ จ ๋ฌธ์„œ + Obsidian ์—ด๊ธฐ'],
272
+ ['EmbedGraph', 'iframe ์ž„๋ฒ ๋“œ์šฉ ๋ฏธ๋‹ˆ ๊ทธ๋ž˜ํ”„'],
273
+ ]),
274
+ d(),
275
+ h2('API Endpoints'),
276
+ table(['Method', 'Path', '๊ธฐ๋Šฅ'], [
277
+ ['GET', '/api/graph', '์ „์ฒด ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ (cached)'],
278
+ ['GET', '/api/search', 'RRF ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ๊ฒ€์ƒ‰'],
279
+ ['GET', '/api/document/:id', '๋ฌธ์„œ ์ „๋ฌธ + ๊ด€๋ จ ๋ฌธ์„œ'],
280
+ ['GET', '/api/stats', '์ธ๋ฑ์Šค ํ†ต๊ณ„'],
281
+ ['GET', '/api/decay', '๊ธฐ์–ต ๊ฐ์‡  ๋ฆฌํฌํŠธ'],
282
+ ['GET', '/api/duplicates', '์ค‘๋ณต ๋…ธํŠธ ํƒ์ง€'],
283
+ ['GET', '/api/gaps', '์ง€์‹ ๊ฐญ ๋ฆฌํฌํŠธ'],
284
+ ['GET', '/api/health', '์ข…ํ•ฉ ๊ฑด๊ฐ•๋„ ๋Œ€์‹œ๋ณด๋“œ'],
285
+ ['GET', '/api/profile', '์ง€์‹ ํ”„๋กœํ•„ (๊ณต๊ฐœ์šฉ)'],
286
+ ['GET', '/api/embed', '์ž„๋ฒ ๋“œ์šฉ ๊ฒฝ๋Ÿ‰ ๊ทธ๋ž˜ํ”„'],
287
+ ['GET', '/api/profile-card', 'SVG ํ”„๋กœํ•„ ์นด๋“œ'],
288
+ ['POST', '/api/clip', '์›น ํด๋ฆฌํ•‘'],
289
+ ['POST', '/api/sync', 'Notion ๋™๊ธฐํ™” ํŠธ๋ฆฌ๊ฑฐ'],
290
+ ['POST', '/api/duplicates/merge', '์ค‘๋ณต ๋…ธํŠธ ๋ณ‘ํ•ฉ'],
291
+ ['POST', '/api/gaps/create-bridge', '๊ฐญ ๋ธŒ๋ฆฟ์ง€ ๋…ธํŠธ ์ƒ์„ฑ'],
292
+ ]),
293
+ ],
294
+ });
295
+ console.log(' + ๊ธฐ๋Šฅ ์ƒ์„ธ ๋ช…์„ธ');
296
+
297
+ // Next Steps
298
+ await notion.pages.create({
299
+ parent: { page_id: page.id },
300
+ properties: { title: [{ text: { content: '๐Ÿ”ฎ Next: Stella Network (Federation)' } }] },
301
+ children: [
302
+ callout('Stellavault์˜ ๋‹ค์Œ ๋‹จ๊ณ„: ๋ถ„์‚ฐ ์ง€์‹ ๋„คํŠธ์›Œํฌ (Federation Protocol)', '๐ŸŒ'),
303
+ p('๊ฐ Stellavault ์ธ์Šคํ„ด์Šค๋ฅผ P2P ๋…ธ๋“œ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ "์ง€์‹ ํ† ๋ ŒํŠธ" ๊ตฌํ˜„.'),
304
+ p('์ž„๋ฒ ๋”ฉ๋งŒ ๊ณต์œ  (์›๋ฌธ ๋น„๊ณต๊ฐœ), AI ์—์ด์ „ํŠธ๊ฐ€ ์ง‘๋‹จ ์ง€์„ฑ์— ์ ‘๊ทผ.'),
305
+ p('์ƒ์„ธ: Stella Network ํŽ˜์ด์ง€ ์ฐธ์กฐ'),
306
+ d(),
307
+ h2('Git History'),
308
+ table(['Commit', '๋‚ด์šฉ'], [
309
+ ['94dceb4', 'feat: initial release of Stellavault'],
310
+ ['d1b01c6', 'docs: rewrite README with core value proposition'],
311
+ ['9b8caac', 'feat: P0 features (init, error recovery, perf, embed)'],
312
+ ['1a72d52', 'feat: P1 features (CLI polish, learning path, notifications, profile, HTTP MCP, plugin SDK)'],
313
+ ['6175b80', 'feat: P2 features (contradictions, webhooks, custom MCP, keyboard nav, semantic versioning, predictive gaps, i18n)'],
314
+ ]),
315
+ ],
316
+ });
317
+ console.log(' + Next Steps');
318
+
319
+ console.log(`\nโœ… Done! ${page.url}`);
320
+ }
321
+
322
+ main().catch(console.error);