stellavault 0.1.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.
Files changed (294) hide show
  1. package/.env.example +12 -0
  2. package/CLAUDE.md +39 -0
  3. package/CONTRIBUTING.md +65 -0
  4. package/LICENSE +21 -0
  5. package/README.md +182 -0
  6. package/memory/MEMORY.md +25 -0
  7. package/package.json +33 -0
  8. package/packages/cli/bin/ekh.js +2 -0
  9. package/packages/cli/bin/stellavault.js +2 -0
  10. package/packages/cli/dist/commands/brief-cmd.d.ts +2 -0
  11. package/packages/cli/dist/commands/brief-cmd.d.ts.map +1 -0
  12. package/packages/cli/dist/commands/brief-cmd.js +82 -0
  13. package/packages/cli/dist/commands/brief-cmd.js.map +1 -0
  14. package/packages/cli/dist/commands/capture-cmd.d.ts +7 -0
  15. package/packages/cli/dist/commands/capture-cmd.d.ts.map +1 -0
  16. package/packages/cli/dist/commands/capture-cmd.js +31 -0
  17. package/packages/cli/dist/commands/capture-cmd.js.map +1 -0
  18. package/packages/cli/dist/commands/card-cmd.d.ts +4 -0
  19. package/packages/cli/dist/commands/card-cmd.d.ts.map +1 -0
  20. package/packages/cli/dist/commands/card-cmd.js +26 -0
  21. package/packages/cli/dist/commands/card-cmd.js.map +1 -0
  22. package/packages/cli/dist/commands/clip-cmd.d.ts +4 -0
  23. package/packages/cli/dist/commands/clip-cmd.d.ts.map +1 -0
  24. package/packages/cli/dist/commands/clip-cmd.js +151 -0
  25. package/packages/cli/dist/commands/clip-cmd.js.map +1 -0
  26. package/packages/cli/dist/commands/cloud-cmd.d.ts +4 -0
  27. package/packages/cli/dist/commands/cloud-cmd.d.ts.map +1 -0
  28. package/packages/cli/dist/commands/cloud-cmd.js +64 -0
  29. package/packages/cli/dist/commands/cloud-cmd.js.map +1 -0
  30. package/packages/cli/dist/commands/contradictions-cmd.d.ts +2 -0
  31. package/packages/cli/dist/commands/contradictions-cmd.d.ts.map +1 -0
  32. package/packages/cli/dist/commands/contradictions-cmd.js +34 -0
  33. package/packages/cli/dist/commands/contradictions-cmd.js.map +1 -0
  34. package/packages/cli/dist/commands/decay-cmd.d.ts +2 -0
  35. package/packages/cli/dist/commands/decay-cmd.d.ts.map +1 -0
  36. package/packages/cli/dist/commands/decay-cmd.js +48 -0
  37. package/packages/cli/dist/commands/decay-cmd.js.map +1 -0
  38. package/packages/cli/dist/commands/digest-cmd.d.ts +4 -0
  39. package/packages/cli/dist/commands/digest-cmd.d.ts.map +1 -0
  40. package/packages/cli/dist/commands/digest-cmd.js +79 -0
  41. package/packages/cli/dist/commands/digest-cmd.js.map +1 -0
  42. package/packages/cli/dist/commands/duplicates-cmd.d.ts +4 -0
  43. package/packages/cli/dist/commands/duplicates-cmd.d.ts.map +1 -0
  44. package/packages/cli/dist/commands/duplicates-cmd.js +30 -0
  45. package/packages/cli/dist/commands/duplicates-cmd.js.map +1 -0
  46. package/packages/cli/dist/commands/federate-cmd.d.ts +5 -0
  47. package/packages/cli/dist/commands/federate-cmd.d.ts.map +1 -0
  48. package/packages/cli/dist/commands/federate-cmd.js +217 -0
  49. package/packages/cli/dist/commands/federate-cmd.js.map +1 -0
  50. package/packages/cli/dist/commands/gaps-cmd.d.ts +2 -0
  51. package/packages/cli/dist/commands/gaps-cmd.d.ts.map +1 -0
  52. package/packages/cli/dist/commands/gaps-cmd.js +33 -0
  53. package/packages/cli/dist/commands/gaps-cmd.js.map +1 -0
  54. package/packages/cli/dist/commands/graph-cmd.d.ts +2 -0
  55. package/packages/cli/dist/commands/graph-cmd.d.ts.map +1 -0
  56. package/packages/cli/dist/commands/graph-cmd.js +77 -0
  57. package/packages/cli/dist/commands/graph-cmd.js.map +1 -0
  58. package/packages/cli/dist/commands/index-cmd.d.ts +2 -0
  59. package/packages/cli/dist/commands/index-cmd.d.ts.map +1 -0
  60. package/packages/cli/dist/commands/index-cmd.js +57 -0
  61. package/packages/cli/dist/commands/index-cmd.js.map +1 -0
  62. package/packages/cli/dist/commands/init-cmd.d.ts +2 -0
  63. package/packages/cli/dist/commands/init-cmd.d.ts.map +1 -0
  64. package/packages/cli/dist/commands/init-cmd.js +123 -0
  65. package/packages/cli/dist/commands/init-cmd.js.map +1 -0
  66. package/packages/cli/dist/commands/learn-cmd.d.ts +2 -0
  67. package/packages/cli/dist/commands/learn-cmd.d.ts.map +1 -0
  68. package/packages/cli/dist/commands/learn-cmd.js +48 -0
  69. package/packages/cli/dist/commands/learn-cmd.js.map +1 -0
  70. package/packages/cli/dist/commands/pack-cmd.d.ts +15 -0
  71. package/packages/cli/dist/commands/pack-cmd.d.ts.map +1 -0
  72. package/packages/cli/dist/commands/pack-cmd.js +93 -0
  73. package/packages/cli/dist/commands/pack-cmd.js.map +1 -0
  74. package/packages/cli/dist/commands/review-cmd.d.ts +4 -0
  75. package/packages/cli/dist/commands/review-cmd.d.ts.map +1 -0
  76. package/packages/cli/dist/commands/review-cmd.js +107 -0
  77. package/packages/cli/dist/commands/review-cmd.js.map +1 -0
  78. package/packages/cli/dist/commands/search-cmd.d.ts +4 -0
  79. package/packages/cli/dist/commands/search-cmd.d.ts.map +1 -0
  80. package/packages/cli/dist/commands/search-cmd.js +38 -0
  81. package/packages/cli/dist/commands/search-cmd.js.map +1 -0
  82. package/packages/cli/dist/commands/serve-cmd.d.ts +2 -0
  83. package/packages/cli/dist/commands/serve-cmd.d.ts.map +1 -0
  84. package/packages/cli/dist/commands/serve-cmd.js +14 -0
  85. package/packages/cli/dist/commands/serve-cmd.js.map +1 -0
  86. package/packages/cli/dist/commands/status-cmd.d.ts +2 -0
  87. package/packages/cli/dist/commands/status-cmd.d.ts.map +1 -0
  88. package/packages/cli/dist/commands/status-cmd.js +33 -0
  89. package/packages/cli/dist/commands/status-cmd.js.map +1 -0
  90. package/packages/cli/dist/commands/sync-cmd.d.ts +5 -0
  91. package/packages/cli/dist/commands/sync-cmd.d.ts.map +1 -0
  92. package/packages/cli/dist/commands/sync-cmd.js +62 -0
  93. package/packages/cli/dist/commands/sync-cmd.js.map +1 -0
  94. package/packages/cli/dist/commands/vault-cmd.d.ts +10 -0
  95. package/packages/cli/dist/commands/vault-cmd.d.ts.map +1 -0
  96. package/packages/cli/dist/commands/vault-cmd.js +54 -0
  97. package/packages/cli/dist/commands/vault-cmd.js.map +1 -0
  98. package/packages/cli/dist/index.d.ts +2 -0
  99. package/packages/cli/dist/index.d.ts.map +1 -0
  100. package/packages/cli/dist/index.js +156 -0
  101. package/packages/cli/dist/index.js.map +1 -0
  102. package/packages/cli/package.json +24 -0
  103. package/packages/cli/src/commands/brief-cmd.ts +87 -0
  104. package/packages/cli/src/commands/capture-cmd.ts +34 -0
  105. package/packages/cli/src/commands/card-cmd.ts +29 -0
  106. package/packages/cli/src/commands/clip-cmd.ts +172 -0
  107. package/packages/cli/src/commands/cloud-cmd.ts +75 -0
  108. package/packages/cli/src/commands/contradictions-cmd.ts +41 -0
  109. package/packages/cli/src/commands/decay-cmd.ts +57 -0
  110. package/packages/cli/src/commands/digest-cmd.ts +89 -0
  111. package/packages/cli/src/commands/duplicates-cmd.ts +38 -0
  112. package/packages/cli/src/commands/federate-cmd.ts +236 -0
  113. package/packages/cli/src/commands/gaps-cmd.ts +40 -0
  114. package/packages/cli/src/commands/graph-cmd.ts +88 -0
  115. package/packages/cli/src/commands/index-cmd.ts +65 -0
  116. package/packages/cli/src/commands/init-cmd.ts +145 -0
  117. package/packages/cli/src/commands/learn-cmd.ts +56 -0
  118. package/packages/cli/src/commands/pack-cmd.ts +121 -0
  119. package/packages/cli/src/commands/review-cmd.ts +125 -0
  120. package/packages/cli/src/commands/search-cmd.ts +45 -0
  121. package/packages/cli/src/commands/serve-cmd.ts +17 -0
  122. package/packages/cli/src/commands/status-cmd.ts +37 -0
  123. package/packages/cli/src/commands/sync-cmd.ts +68 -0
  124. package/packages/cli/src/commands/vault-cmd.ts +64 -0
  125. package/packages/cli/src/index.ts +187 -0
  126. package/packages/core/package.json +40 -0
  127. package/packages/core/src/api/dashboard.ts +138 -0
  128. package/packages/core/src/api/graph-data.ts +286 -0
  129. package/packages/core/src/api/pwa.ts +82 -0
  130. package/packages/core/src/api/server.ts +660 -0
  131. package/packages/core/src/capture/voice.ts +168 -0
  132. package/packages/core/src/cloud/index.ts +2 -0
  133. package/packages/core/src/cloud/sync.ts +167 -0
  134. package/packages/core/src/config.ts +82 -0
  135. package/packages/core/src/federation/credits.ts +80 -0
  136. package/packages/core/src/federation/hyperswarm.d.ts +19 -0
  137. package/packages/core/src/federation/identity.ts +90 -0
  138. package/packages/core/src/federation/index.ts +8 -0
  139. package/packages/core/src/federation/node.ts +235 -0
  140. package/packages/core/src/federation/privacy.ts +52 -0
  141. package/packages/core/src/federation/reputation.ts +202 -0
  142. package/packages/core/src/federation/search.ts +129 -0
  143. package/packages/core/src/federation/sharing.ts +165 -0
  144. package/packages/core/src/federation/trust.ts +76 -0
  145. package/packages/core/src/federation/types.ts +25 -0
  146. package/packages/core/src/i18n/index.ts +85 -0
  147. package/packages/core/src/index.ts +133 -0
  148. package/packages/core/src/indexer/chunker.ts +180 -0
  149. package/packages/core/src/indexer/embedder.ts +9 -0
  150. package/packages/core/src/indexer/index.ts +113 -0
  151. package/packages/core/src/indexer/local-embedder.ts +35 -0
  152. package/packages/core/src/indexer/scanner.ts +142 -0
  153. package/packages/core/src/indexer/watcher.ts +62 -0
  154. package/packages/core/src/intelligence/contradiction-detector.ts +134 -0
  155. package/packages/core/src/intelligence/decay-engine.ts +229 -0
  156. package/packages/core/src/intelligence/duplicate-detector.ts +71 -0
  157. package/packages/core/src/intelligence/fsrs.ts +79 -0
  158. package/packages/core/src/intelligence/gap-detector.ts +109 -0
  159. package/packages/core/src/intelligence/learning-path.ts +86 -0
  160. package/packages/core/src/intelligence/notifications.ts +106 -0
  161. package/packages/core/src/intelligence/predictive-gaps.ts +94 -0
  162. package/packages/core/src/intelligence/semantic-versioning.ts +97 -0
  163. package/packages/core/src/intelligence/types.ts +28 -0
  164. package/packages/core/src/mcp/custom-tools.ts +97 -0
  165. package/packages/core/src/mcp/index.ts +1 -0
  166. package/packages/core/src/mcp/server.ts +142 -0
  167. package/packages/core/src/mcp/tools/agentic-graph.ts +96 -0
  168. package/packages/core/src/mcp/tools/brief.ts +49 -0
  169. package/packages/core/src/mcp/tools/decay.ts +40 -0
  170. package/packages/core/src/mcp/tools/decision-journal.ts +95 -0
  171. package/packages/core/src/mcp/tools/export.ts +72 -0
  172. package/packages/core/src/mcp/tools/federated-search.ts +43 -0
  173. package/packages/core/src/mcp/tools/generate-claude-md.ts +130 -0
  174. package/packages/core/src/mcp/tools/get-document.ts +26 -0
  175. package/packages/core/src/mcp/tools/get-related.ts +41 -0
  176. package/packages/core/src/mcp/tools/learning-path.ts +52 -0
  177. package/packages/core/src/mcp/tools/list-topics.ts +20 -0
  178. package/packages/core/src/mcp/tools/search.ts +35 -0
  179. package/packages/core/src/mcp/tools/snapshot.ts +98 -0
  180. package/packages/core/src/multi-vault/index.ts +118 -0
  181. package/packages/core/src/pack/creator.ts +127 -0
  182. package/packages/core/src/pack/exporter.ts +21 -0
  183. package/packages/core/src/pack/importer.ts +82 -0
  184. package/packages/core/src/pack/index.ts +5 -0
  185. package/packages/core/src/pack/marketplace.ts +103 -0
  186. package/packages/core/src/pack/pii-masker.ts +38 -0
  187. package/packages/core/src/pack/types.ts +39 -0
  188. package/packages/core/src/plugins/index.ts +100 -0
  189. package/packages/core/src/plugins/webhooks.ts +110 -0
  190. package/packages/core/src/search/bm25.ts +16 -0
  191. package/packages/core/src/search/index.ts +83 -0
  192. package/packages/core/src/search/rrf.ts +31 -0
  193. package/packages/core/src/search/semantic.ts +15 -0
  194. package/packages/core/src/store/index.ts +2 -0
  195. package/packages/core/src/store/sqlite-vec.ts +290 -0
  196. package/packages/core/src/store/types.ts +22 -0
  197. package/packages/core/src/team/index.ts +126 -0
  198. package/packages/core/src/types/chunk.ts +25 -0
  199. package/packages/core/src/types/document.ts +24 -0
  200. package/packages/core/src/types/graph.ts +44 -0
  201. package/packages/core/src/types/index.ts +15 -0
  202. package/packages/core/src/types/search.ts +38 -0
  203. package/packages/core/src/utils/retry.ts +85 -0
  204. package/packages/core/tests/api-card.test.ts +60 -0
  205. package/packages/core/tests/api-routes.test.ts +98 -0
  206. package/packages/core/tests/bm25.test.ts +87 -0
  207. package/packages/core/tests/chunker.test.ts +48 -0
  208. package/packages/core/tests/cluster.test.ts +75 -0
  209. package/packages/core/tests/constellation.test.ts +77 -0
  210. package/packages/core/tests/export-utils.test.ts +97 -0
  211. package/packages/core/tests/fsrs.test.ts +96 -0
  212. package/packages/core/tests/gesture-detector.test.ts +45 -0
  213. package/packages/core/tests/graph-data.test.ts +87 -0
  214. package/packages/core/tests/layout.test.ts +83 -0
  215. package/packages/core/tests/mcp.test.ts +148 -0
  216. package/packages/core/tests/pack.test.ts +127 -0
  217. package/packages/core/tests/pii-masker.test.ts +42 -0
  218. package/packages/core/tests/profile-card.test.ts +62 -0
  219. package/packages/core/tests/rrf.test.ts +29 -0
  220. package/packages/core/tests/search-integration.test.ts +139 -0
  221. package/packages/core/tests/store.test.ts +80 -0
  222. package/packages/graph/click-result.png +0 -0
  223. package/packages/graph/index.html +17 -0
  224. package/packages/graph/package.json +32 -0
  225. package/packages/graph/src/App.tsx +7 -0
  226. package/packages/graph/src/api/client.ts +39 -0
  227. package/packages/graph/src/components/ClusterFilter.tsx +73 -0
  228. package/packages/graph/src/components/ConstellationView.tsx +232 -0
  229. package/packages/graph/src/components/ExportPanel.tsx +177 -0
  230. package/packages/graph/src/components/Graph3D.tsx +230 -0
  231. package/packages/graph/src/components/GraphEdges.tsx +100 -0
  232. package/packages/graph/src/components/GraphNodes.tsx +386 -0
  233. package/packages/graph/src/components/HealthDashboard.tsx +173 -0
  234. package/packages/graph/src/components/Layout.tsx +214 -0
  235. package/packages/graph/src/components/MotionOverlay.tsx +81 -0
  236. package/packages/graph/src/components/MotionToggle.tsx +33 -0
  237. package/packages/graph/src/components/MultiverseView.tsx +286 -0
  238. package/packages/graph/src/components/NodeDetail.tsx +232 -0
  239. package/packages/graph/src/components/PulseParticle.tsx +232 -0
  240. package/packages/graph/src/components/SearchBar.tsx +107 -0
  241. package/packages/graph/src/components/StarField.tsx +197 -0
  242. package/packages/graph/src/components/StatusBar.tsx +53 -0
  243. package/packages/graph/src/components/Timeline.tsx +148 -0
  244. package/packages/graph/src/components/ToolsPanel.tsx +512 -0
  245. package/packages/graph/src/components/Tooltip.tsx +100 -0
  246. package/packages/graph/src/components/TypeFilter.tsx +131 -0
  247. package/packages/graph/src/embed/EmbedGraph.tsx +144 -0
  248. package/packages/graph/src/hooks/useConstellationLOD.ts +76 -0
  249. package/packages/graph/src/hooks/useDecay.ts +37 -0
  250. package/packages/graph/src/hooks/useExport.ts +165 -0
  251. package/packages/graph/src/hooks/useGraph.ts +69 -0
  252. package/packages/graph/src/hooks/useKeyboardNav.ts +122 -0
  253. package/packages/graph/src/hooks/useLayout.ts +45 -0
  254. package/packages/graph/src/hooks/useMotion.ts +120 -0
  255. package/packages/graph/src/hooks/usePulse.ts +58 -0
  256. package/packages/graph/src/hooks/useSearch.ts +71 -0
  257. package/packages/graph/src/lib/constellation.ts +107 -0
  258. package/packages/graph/src/lib/export-utils.ts +48 -0
  259. package/packages/graph/src/lib/gesture-detector.ts +123 -0
  260. package/packages/graph/src/lib/layout.worker.ts +153 -0
  261. package/packages/graph/src/lib/motion-controller.ts +83 -0
  262. package/packages/graph/src/lib/profile-card.ts +122 -0
  263. package/packages/graph/src/main.tsx +4 -0
  264. package/packages/graph/src/stores/graph-store.ts +155 -0
  265. package/packages/graph/success.png +0 -0
  266. package/packages/graph/test-click.mjs +49 -0
  267. package/packages/graph/test-explore.mjs +102 -0
  268. package/packages/graph/test-final.mjs +61 -0
  269. package/packages/graph/test-graph.mjs +139 -0
  270. package/packages/graph/test-hover.mjs +48 -0
  271. package/packages/graph/test-pulse.mjs +68 -0
  272. package/packages/graph/test-screenshot.mjs +56 -0
  273. package/packages/graph/test-v2.mjs +97 -0
  274. package/packages/graph/vite.config.ts +15 -0
  275. package/packages/sync/.env.example +11 -0
  276. package/packages/sync/.sync-state.json +317 -0
  277. package/packages/sync/.upload-state.json +1009 -0
  278. package/packages/sync/create-stella-network-notion.mjs +151 -0
  279. package/packages/sync/create-stellavault-project-notion.mjs +322 -0
  280. package/packages/sync/logs/sync-2026-03-28.log +6 -0
  281. package/packages/sync/logs/sync-2026-03-29.log +12 -0
  282. package/packages/sync/logs/sync-2026-03-30.log +6 -0
  283. package/packages/sync/logs/sync-2026-03-31.log +6 -0
  284. package/packages/sync/logs/sync-2026-04-01.log +6 -0
  285. package/packages/sync/logs/sync-2026-04-02.log +6 -0
  286. package/packages/sync/package-lock.json +373 -0
  287. package/packages/sync/package.json +16 -0
  288. package/packages/sync/run-sync.bat +18 -0
  289. package/packages/sync/run-sync.mjs +46 -0
  290. package/packages/sync/setup-scheduler.mjs +119 -0
  291. package/packages/sync/structured-sync.mjs +187 -0
  292. package/packages/sync/sync-to-obsidian.mjs +264 -0
  293. package/packages/sync/upload-pdca-to-notion.mjs +495 -0
  294. package/tsconfig.base.json +18 -0
@@ -0,0 +1,156 @@
1
+ import { Command } from 'commander';
2
+ import { indexCommand } from './commands/index-cmd.js';
3
+ import { searchCommand } from './commands/search-cmd.js';
4
+ import { serveCommand } from './commands/serve-cmd.js';
5
+ import { statusCommand } from './commands/status-cmd.js';
6
+ import { graphCommand } from './commands/graph-cmd.js';
7
+ import { cardCommand } from './commands/card-cmd.js';
8
+ import { packCreateCommand, packExportCommand, packImportCommand, packListCommand, packInfoCommand } from './commands/pack-cmd.js';
9
+ import { decayCommand } from './commands/decay-cmd.js';
10
+ import { syncCommand } from './commands/sync-cmd.js';
11
+ import { reviewCommand } from './commands/review-cmd.js';
12
+ import { duplicatesCommand } from './commands/duplicates-cmd.js';
13
+ import { gapsCommand } from './commands/gaps-cmd.js';
14
+ import { clipCommand } from './commands/clip-cmd.js';
15
+ import { briefCommand } from './commands/brief-cmd.js';
16
+ import { digestCommand } from './commands/digest-cmd.js';
17
+ import { initCommand } from './commands/init-cmd.js';
18
+ import { learnCommand } from './commands/learn-cmd.js';
19
+ import { contradictionsCommand } from './commands/contradictions-cmd.js';
20
+ import { federateJoinCommand, federateStatusCommand } from './commands/federate-cmd.js';
21
+ import { cloudSyncCommand, cloudRestoreCommand, cloudStatusCommand } from './commands/cloud-cmd.js';
22
+ import { vaultAddCommand, vaultListCommand, vaultRemoveCommand, vaultSearchAllCommand } from './commands/vault-cmd.js';
23
+ import { captureCommand } from './commands/capture-cmd.js';
24
+ const program = new Command();
25
+ program
26
+ .name('stellavault')
27
+ .description('Stellavault — Turn your Obsidian vault into a 3D neural knowledge graph')
28
+ .version('0.1.0')
29
+ .option('--json', 'Output in JSON format (for scripting)')
30
+ .option('--quiet', 'Suppress non-essential output');
31
+ program
32
+ .command('init')
33
+ .description('Interactive setup wizard — get started in 3 minutes')
34
+ .action(initCommand);
35
+ program
36
+ .command('index [vault-path]')
37
+ .description('Obsidian vault를 벡터화하여 인덱싱합니다')
38
+ .action(indexCommand);
39
+ program
40
+ .command('search <query>')
41
+ .description('지식 베이스에서 검색합니다')
42
+ .option('-l, --limit <n>', '결과 수', '5')
43
+ .action(searchCommand);
44
+ program
45
+ .command('serve')
46
+ .description('MCP 서버를 시작합니다 (Claude Code 연동)')
47
+ .action(serveCommand);
48
+ program
49
+ .command('status')
50
+ .description('인덱스 상태를 확인합니다')
51
+ .action(statusCommand);
52
+ program
53
+ .command('graph')
54
+ .description('3D Knowledge Graph API 서버를 시작합니다')
55
+ .action(graphCommand);
56
+ program
57
+ .command('card')
58
+ .description('SVG 프로필 카드를 생성합니다')
59
+ .option('-o, --output <path>', '출력 파일 경로', 'knowledge-card.svg')
60
+ .action(cardCommand);
61
+ program
62
+ .command('learn')
63
+ .description('AI learning path — personalized recommendations based on decay + gaps')
64
+ .action(learnCommand);
65
+ program
66
+ .command('contradictions')
67
+ .description('Detect contradicting statements across your notes')
68
+ .action(contradictionsCommand);
69
+ program
70
+ .command('decay')
71
+ .description('지식 감쇠 리포트를 출력합니다 (잊어가는 노트 확인)')
72
+ .action(decayCommand);
73
+ program
74
+ .command('brief')
75
+ .description('오늘의 지식 브리핑 (감쇠 + 갭 + 활동 요약)')
76
+ .action(briefCommand);
77
+ program
78
+ .command('digest')
79
+ .description('주간 지식 활동 리포트')
80
+ .option('-d, --days <n>', '기간 (일)', '7')
81
+ .action(digestCommand);
82
+ program
83
+ .command('clip <url>')
84
+ .description('웹 페이지/YouTube를 Obsidian에 클리핑')
85
+ .option('-f, --folder <path>', 'vault 내 저장 폴더', '06_Research/clips')
86
+ .action(clipCommand);
87
+ program
88
+ .command('gaps')
89
+ .description('지식 갭을 탐지합니다 (클러스터 간 연결 부족 영역)')
90
+ .action(gapsCommand);
91
+ program
92
+ .command('duplicates')
93
+ .description('중복/유사 노트를 탐지합니다')
94
+ .option('-t, --threshold <n>', '유사도 임계값 (0~1)', '0.88')
95
+ .action(duplicatesCommand);
96
+ program
97
+ .command('review')
98
+ .description('일일 지식 리뷰 — 잊어가는 노트를 Obsidian에서 열어 리뷰')
99
+ .option('-n, --count <n>', '리뷰할 노트 수', '5')
100
+ .action(reviewCommand);
101
+ program
102
+ .command('sync')
103
+ .description('Notion → Obsidian 동기화')
104
+ .option('--upload', 'PDCA 문서를 Notion에 업로드')
105
+ .option('--watch', '5분 간격 자동 동기화')
106
+ .action(syncCommand);
107
+ const federate = program.command('federate').description('Federation — P2P knowledge network');
108
+ federate.command('join')
109
+ .description('Join the federation network (interactive mode)')
110
+ .option('-n, --name <name>', 'Display name for this node')
111
+ .action(federateJoinCommand);
112
+ federate.command('status')
113
+ .description('Show federation identity and status')
114
+ .action(federateStatusCommand);
115
+ program
116
+ .command('capture <audio-file>')
117
+ .description('Voice capture — transcribe audio to knowledge note (requires Whisper)')
118
+ .option('-m, --model <model>', 'Whisper model (tiny/base/small/medium/large)', 'base')
119
+ .option('-l, --language <lang>', 'Language (auto-detect if omitted)')
120
+ .option('-t, --tags <tags>', 'Comma-separated tags')
121
+ .option('-f, --folder <folder>', 'Vault subfolder', '01_Knowledge/voice')
122
+ .action(captureCommand);
123
+ const vault = program.command('vault').description('Multi-Vault — manage and search across vaults');
124
+ vault.command('add <id> <path>').description('Register a vault').option('-n, --name <name>', 'Display name').option('-s, --shared', 'Allow federation sharing').action(vaultAddCommand);
125
+ vault.command('list').description('List registered vaults').action(vaultListCommand);
126
+ vault.command('remove <id>').description('Unregister a vault').action(vaultRemoveCommand);
127
+ vault.command('search-all <query>').description('Search across all registered vaults').option('-l, --limit <n>', 'Max results', '10').action(vaultSearchAllCommand);
128
+ const cloud = program.command('cloud').description('Cloud — E2E encrypted backup');
129
+ cloud.command('sync').description('Upload encrypted DB to cloud').action(cloudSyncCommand);
130
+ cloud.command('restore').description('Download and decrypt DB from cloud').action(cloudRestoreCommand);
131
+ cloud.command('status').description('Show last sync status').action(cloudStatusCommand);
132
+ const pack = program.command('pack').description('Knowledge Pack 관리');
133
+ pack.command('create <name>')
134
+ .description('검색/클러스터 기반 Knowledge Pack 생성')
135
+ .option('--from-search <query>', '검색 쿼리에서 생성')
136
+ .option('--from-cluster <id>', '클러스터 ID에서 생성')
137
+ .option('--author <name>', '작성자', 'anonymous')
138
+ .option('--license <license>', '라이선스', 'CC-BY-4.0')
139
+ .option('--description <desc>', '설명')
140
+ .option('--limit <n>', '최대 청크 수', '100')
141
+ .action(packCreateCommand);
142
+ pack.command('export <name>')
143
+ .description('.sv-pack 파일로 내보내기')
144
+ .option('-o, --output <path>', '출력 경로')
145
+ .action(packExportCommand);
146
+ pack.command('import <file>')
147
+ .description('.sv-pack 파일 가져오기 → 벡터 DB 병합')
148
+ .action(packImportCommand);
149
+ pack.command('list')
150
+ .description('설치된 팩 목록')
151
+ .action(packListCommand);
152
+ pack.command('info <name>')
153
+ .description('팩 상세 정보')
154
+ .action(packInfoCommand);
155
+ program.parse();
156
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@stellavault/cli",
3
+ "version": "0.1.0",
4
+ "description": "Stellavault CLI — stellavault index, search, serve, graph",
5
+ "type": "module",
6
+ "bin": {
7
+ "stellavault": "./bin/stellavault.js",
8
+ "sv": "./bin/stellavault.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc"
12
+ },
13
+ "dependencies": {
14
+ "@stellavault/core": "*",
15
+ "chalk": "^5.6.2",
16
+ "commander": "^14.0.3",
17
+ "open": "^11.0.0",
18
+ "ora": "^9.3.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^25.5.0",
22
+ "typescript": "^5.7.0"
23
+ }
24
+ }
@@ -0,0 +1,87 @@
1
+ // stellavault brief — 아침 브리핑 (decay + gaps + streak 통합)
2
+
3
+ import chalk from 'chalk';
4
+ import { loadConfig, createKnowledgeHub, DecayEngine, detectKnowledgeGaps } from '@stellavault/core';
5
+
6
+ export async function briefCommand() {
7
+ const config = loadConfig();
8
+ const hub = createKnowledgeHub(config);
9
+
10
+ await hub.store.initialize();
11
+ await hub.embedder.initialize();
12
+
13
+ const db = hub.store.getDb() as any;
14
+ if (!db) { console.error(chalk.red('❌ DB 접근 불가')); process.exit(1); }
15
+
16
+ const decayEngine = new DecayEngine(db);
17
+ const stats = await hub.store.getStats();
18
+
19
+ console.log(chalk.green('\n☀️ Good morning! 오늘의 지식 브리핑'));
20
+ console.log(chalk.dim('─'.repeat(50)));
21
+
22
+ // 1. 전체 상태
23
+ console.log(`\n📚 ${chalk.bold(String(stats.documentCount))}개 노트 | ${stats.chunkCount} 청크`);
24
+
25
+ // 2. 감쇠 요약
26
+ const report = await decayEngine.computeAll();
27
+ const avgRColor = report.averageR >= 0.7 ? chalk.green : report.averageR >= 0.5 ? chalk.yellow : chalk.red;
28
+ console.log(`🧠 전체 건강도: ${avgRColor('R=' + report.averageR)} | 감쇠 ${chalk.yellow(String(report.decayingCount))}개 | 위험 ${chalk.red(String(report.criticalCount))}개`);
29
+
30
+ // 3. 리뷰 대상 Top 5
31
+ if (report.topDecaying.length > 0) {
32
+ console.log(chalk.yellow('\n📋 리뷰 추천:'));
33
+ for (const d of report.topDecaying.slice(0, 5)) {
34
+ const bar = '█'.repeat(Math.round(d.retrievability * 10)) + '░'.repeat(10 - Math.round(d.retrievability * 10));
35
+ console.log(` ${chalk.dim(bar)} R=${d.retrievability.toFixed(2)} ${d.title}`);
36
+ }
37
+ console.log(chalk.dim(' → stellavault review 로 리뷰 시작'));
38
+ }
39
+
40
+ // 4. 갭 요약
41
+ try {
42
+ const gapReport = await detectKnowledgeGaps(hub.store);
43
+ const highGaps = gapReport.gaps.filter(g => g.severity === 'high');
44
+ if (highGaps.length > 0) {
45
+ console.log(chalk.yellow(`\n🕳️ 지식 갭 ${highGaps.length}개:`));
46
+ for (const g of highGaps.slice(0, 3)) {
47
+ console.log(` 🔴 ${g.clusterA.replace(/\s*\(\d+\)$/, '')} ↔ ${g.clusterB.replace(/\s*\(\d+\)$/, '')}`);
48
+ }
49
+ }
50
+ } catch { /* gaps 실패해도 무시 */ }
51
+
52
+ // 5. Streak
53
+ try {
54
+ const days = db.prepare(`
55
+ SELECT DISTINCT date(accessed_at) as d FROM access_log
56
+ WHERE access_type = 'view' ORDER BY d DESC LIMIT 30
57
+ `).all() as any[];
58
+
59
+ let streak = 0;
60
+ for (let i = 0; i < days.length; i++) {
61
+ const expected = new Date(Date.now() - i * 86400000).toISOString().slice(0, 10);
62
+ if (days[i]?.d === expected) streak++;
63
+ else break;
64
+ }
65
+ if (streak > 0) console.log(chalk.yellow(`\n🔥 ${streak}일 연속 리뷰!`));
66
+ } catch {}
67
+
68
+ // 6. 최근 활동
69
+ try {
70
+ const recent = db.prepare(`
71
+ SELECT document_id, COUNT(*) as cnt FROM access_log
72
+ WHERE accessed_at > datetime('now', '-7 days')
73
+ GROUP BY document_id ORDER BY cnt DESC LIMIT 3
74
+ `).all() as any[];
75
+
76
+ if (recent.length > 0) {
77
+ console.log(chalk.dim('\n📊 이번 주 가장 많이 본 노트:'));
78
+ for (const r of recent) {
79
+ const doc = db.prepare('SELECT title FROM documents WHERE id = ?').get(r.document_id) as any;
80
+ console.log(` ${r.cnt}회 — ${doc?.title ?? r.document_id}`);
81
+ }
82
+ }
83
+ } catch {}
84
+
85
+ console.log('\n' + chalk.dim('─'.repeat(50)));
86
+ console.log(chalk.dim('💡 stellavault review | stellavault gaps | stellavault graph'));
87
+ }
@@ -0,0 +1,34 @@
1
+ // sv capture <audio-file> — Voice Knowledge Capture (P3)
2
+
3
+ import chalk from 'chalk';
4
+ import { loadConfig, captureVoice, isWhisperAvailable } from '@stellavault/core';
5
+
6
+ export async function captureCommand(audioFile: string, options: { model?: string; language?: string; tags?: string; folder?: string }) {
7
+ if (!isWhisperAvailable()) {
8
+ console.log(chalk.red('\n Whisper not installed.'));
9
+ console.log(chalk.dim(' Install: pip install openai-whisper'));
10
+ console.log(chalk.dim(' Or: brew install whisper-cpp\n'));
11
+ return;
12
+ }
13
+
14
+ const config = loadConfig();
15
+ console.log(chalk.dim(`\n Transcribing ${audioFile}...`));
16
+
17
+ const result = await captureVoice(audioFile, {
18
+ vaultPath: config.vaultPath,
19
+ model: options.model,
20
+ language: options.language,
21
+ tags: options.tags?.split(',').map(t => t.trim()),
22
+ folder: options.folder,
23
+ });
24
+
25
+ if (result.success) {
26
+ console.log(chalk.green(`\n ✅ Captured: "${result.title}"`));
27
+ console.log(` Tags: ${result.tags.join(', ')}`);
28
+ console.log(` File: ${result.filePath}`);
29
+ console.log(chalk.dim(` Transcript: ${result.transcript.slice(0, 100)}...`));
30
+ console.log(chalk.dim('\n 💡 Run stellavault index to add to the graph\n'));
31
+ } else {
32
+ console.log(chalk.red(`\n ❌ Capture failed: ${result.error}\n`));
33
+ }
34
+ }
@@ -0,0 +1,29 @@
1
+ // stellavault card — SVG 프로필 카드 생성
2
+
3
+ import chalk from 'chalk';
4
+ import { writeFileSync } from 'node:fs';
5
+ import { resolve } from 'node:path';
6
+
7
+ export async function cardCommand(options: { output?: string }) {
8
+ const output = options.output ?? 'knowledge-card.svg';
9
+ const outPath = resolve(process.cwd(), output);
10
+
11
+ console.error(chalk.dim('⏳ Generating profile card...'));
12
+
13
+ try {
14
+ // API 서버에서 SVG 가져오기 (서버가 실행 중이어야 함)
15
+ const res = await fetch('http://127.0.0.1:3333/api/profile-card');
16
+ if (!res.ok) throw new Error(`API error: ${res.status}. Is 'stellavault graph' running?`);
17
+
18
+ const svg = await res.text();
19
+ writeFileSync(outPath, svg, 'utf-8');
20
+
21
+ console.error(chalk.green(`✅ Profile card saved: ${outPath}`));
22
+ console.error(chalk.dim(' Embed in GitHub README:'));
23
+ console.error(chalk.dim(` ![Knowledge Card](${output})`));
24
+ } catch (err) {
25
+ console.error(chalk.red(`❌ Failed: ${err}`));
26
+ console.error(chalk.dim(' Make sure API server is running: stellavault graph'));
27
+ process.exit(1);
28
+ }
29
+ }
@@ -0,0 +1,172 @@
1
+ // Design Ref: stellavault clip — 웹 페이지/YouTube를 Obsidian에 클리핑
2
+
3
+ import chalk from 'chalk';
4
+ import { writeFileSync, mkdirSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { loadConfig } from '@stellavault/core';
7
+
8
+ export async function clipCommand(url: string, options: { folder?: string }) {
9
+ if (!url) {
10
+ console.error(chalk.red('❌ URL을 입력하세요: stellavault clip <url>'));
11
+ process.exit(1);
12
+ }
13
+
14
+ const config = loadConfig();
15
+ const vaultPath = config.vaultPath;
16
+ if (!vaultPath) {
17
+ console.error(chalk.red('❌ vaultPath not configured'));
18
+ process.exit(1);
19
+ }
20
+
21
+ const folder = options.folder ?? '06_Research/clips';
22
+ const targetDir = join(vaultPath, folder);
23
+ mkdirSync(targetDir, { recursive: true });
24
+
25
+ console.error(chalk.dim(`📎 Clipping: ${url}`));
26
+
27
+ try {
28
+ // URL 유형 감지
29
+ const isYouTube = /youtube\.com\/watch|youtu\.be\//.test(url);
30
+
31
+ let title: string;
32
+ let content: string;
33
+
34
+ if (isYouTube) {
35
+ // YouTube — 메타데이터 + 설명 추출
36
+ const result = await clipYouTube(url);
37
+ title = result.title;
38
+ content = result.content;
39
+ } else {
40
+ // 일반 웹페이지 — HTML → Markdown
41
+ const result = await clipWebPage(url);
42
+ title = result.title;
43
+ content = result.content;
44
+ }
45
+
46
+ // 파일명 생성 (안전한 문자만)
47
+ const safeTitle = title
48
+ .replace(/[<>:"/\\|?*]/g, '')
49
+ .replace(/\s+/g, ' ')
50
+ .trim()
51
+ .slice(0, 80);
52
+
53
+ const date = new Date().toISOString().slice(0, 10);
54
+ const fileName = `${date} ${safeTitle}.md`;
55
+ const filePath = join(targetDir, fileName);
56
+
57
+ // Frontmatter + 내용 조합
58
+ const md = [
59
+ '---',
60
+ `title: "${safeTitle}"`,
61
+ `source: "${url}"`,
62
+ `clipped: ${date}`,
63
+ `tags: [clip${isYouTube ? ', youtube' : ''}]`,
64
+ '---',
65
+ '',
66
+ `# ${safeTitle}`,
67
+ '',
68
+ `> Source: ${url}`,
69
+ `> Clipped: ${date}`,
70
+ '',
71
+ content,
72
+ ].join('\n');
73
+
74
+ writeFileSync(filePath, md, 'utf-8');
75
+
76
+ console.log(chalk.green(`✅ Saved: ${fileName}`));
77
+ console.log(chalk.dim(` → ${filePath}`));
78
+ console.log(chalk.dim(' 💡 stellavault index로 재인덱싱하면 검색 가능'));
79
+ } catch (err) {
80
+ console.error(chalk.red(`❌ Clip failed: ${(err as Error).message}`));
81
+ process.exit(1);
82
+ }
83
+ }
84
+
85
+ async function clipWebPage(url: string): Promise<{ title: string; content: string }> {
86
+ const res = await fetch(url, {
87
+ headers: { 'User-Agent': 'Mozilla/5.0 stellavault-clipper/1.0' },
88
+ });
89
+ const html = await res.text();
90
+
91
+ // 제목 추출
92
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
93
+ const title = titleMatch ? titleMatch[1].trim() : new URL(url).hostname;
94
+
95
+ // HTML → 간단한 마크다운 변환
96
+ let content = html
97
+ // 스크립트/스타일 제거
98
+ .replace(/<script[\s\S]*?<\/script>/gi, '')
99
+ .replace(/<style[\s\S]*?<\/style>/gi, '')
100
+ // 헤딩
101
+ .replace(/<h1[^>]*>([\s\S]*?)<\/h1>/gi, '\n# $1\n')
102
+ .replace(/<h2[^>]*>([\s\S]*?)<\/h2>/gi, '\n## $1\n')
103
+ .replace(/<h3[^>]*>([\s\S]*?)<\/h3>/gi, '\n### $1\n')
104
+ // 단락/줄바꿈
105
+ .replace(/<p[^>]*>([\s\S]*?)<\/p>/gi, '\n$1\n')
106
+ .replace(/<br\s*\/?>/gi, '\n')
107
+ // 링크
108
+ .replace(/<a[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/gi, '[$2]($1)')
109
+ // 리스트
110
+ .replace(/<li[^>]*>([\s\S]*?)<\/li>/gi, '- $1\n')
111
+ // 강조
112
+ .replace(/<(strong|b)[^>]*>([\s\S]*?)<\/\1>/gi, '**$2**')
113
+ .replace(/<(em|i)[^>]*>([\s\S]*?)<\/\1>/gi, '*$2*')
114
+ // 코드
115
+ .replace(/<code[^>]*>([\s\S]*?)<\/code>/gi, '`$1`')
116
+ .replace(/<pre[^>]*>([\s\S]*?)<\/pre>/gi, '\n```\n$1\n```\n')
117
+ // 나머지 태그 제거
118
+ .replace(/<[^>]+>/g, '')
119
+ // HTML 엔티티
120
+ .replace(/&amp;/g, '&')
121
+ .replace(/&lt;/g, '<')
122
+ .replace(/&gt;/g, '>')
123
+ .replace(/&quot;/g, '"')
124
+ .replace(/&#39;/g, "'")
125
+ .replace(/&nbsp;/g, ' ')
126
+ // 다중 줄바꿈 정리
127
+ .replace(/\n{3,}/g, '\n\n')
128
+ .trim();
129
+
130
+ // 너무 길면 자르기
131
+ if (content.length > 10000) {
132
+ content = content.slice(0, 10000) + '\n\n...(truncated)';
133
+ }
134
+
135
+ return { title, content };
136
+ }
137
+
138
+ async function clipYouTube(url: string): Promise<{ title: string; content: string }> {
139
+ // YouTube 페이지에서 메타데이터 추출
140
+ const res = await fetch(url, {
141
+ headers: { 'User-Agent': 'Mozilla/5.0 stellavault-clipper/1.0' },
142
+ });
143
+ const html = await res.text();
144
+
145
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
146
+ const title = (titleMatch ? titleMatch[1] : 'YouTube Video')
147
+ .replace(/ - YouTube$/, '')
148
+ .trim();
149
+
150
+ // 비디오 설명 추출 시도
151
+ const descMatch = html.match(/"shortDescription":"([\s\S]*?)"/);
152
+ const description = descMatch
153
+ ? descMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"').slice(0, 3000)
154
+ : '(설명 없음)';
155
+
156
+ const videoId = url.match(/(?:v=|youtu\.be\/)([a-zA-Z0-9_-]+)/)?.[1] ?? '';
157
+
158
+ const content = [
159
+ `![thumbnail](https://img.youtube.com/vi/${videoId}/maxresdefault.jpg)`,
160
+ '',
161
+ '## 설명',
162
+ '',
163
+ description,
164
+ '',
165
+ `## 링크`,
166
+ '',
167
+ `- [YouTube](${url})`,
168
+ videoId ? `- [Embed](https://www.youtube.com/embed/${videoId})` : '',
169
+ ].filter(Boolean).join('\n');
170
+
171
+ return { title, content };
172
+ }
@@ -0,0 +1,75 @@
1
+ // sv cloud sync/restore/status — E2E encrypted cloud backup (F-A04)
2
+
3
+ import chalk from 'chalk';
4
+ import { loadConfig } from '@stellavault/core';
5
+ import { syncToCloud, restoreFromCloud, getSyncState } from '@stellavault/core';
6
+ import type { CloudConfig } from '@stellavault/core';
7
+
8
+ function getCloudConfig(): CloudConfig | null {
9
+ const endpoint = process.env.SV_CLOUD_ENDPOINT;
10
+ const bucket = process.env.SV_CLOUD_BUCKET ?? 'stellavault';
11
+ const accessKeyId = process.env.SV_CLOUD_ACCESS_KEY ?? '';
12
+ const secretAccessKey = process.env.SV_CLOUD_SECRET_KEY ?? '';
13
+ const encryptionKey = process.env.SV_CLOUD_ENCRYPTION_KEY;
14
+
15
+ if (!endpoint || !secretAccessKey) return null;
16
+
17
+ return { endpoint, bucket, accessKeyId, secretAccessKey, encryptionKey };
18
+ }
19
+
20
+ export async function cloudSyncCommand() {
21
+ const cloudConfig = getCloudConfig();
22
+ if (!cloudConfig) {
23
+ console.log(chalk.red('\n Cloud not configured. Set environment variables:'));
24
+ console.log(chalk.dim(' SV_CLOUD_ENDPOINT=https://xxx.r2.cloudflarestorage.com'));
25
+ console.log(chalk.dim(' SV_CLOUD_SECRET_KEY=your_api_token'));
26
+ console.log(chalk.dim(' SV_CLOUD_ENCRYPTION_KEY=your_passphrase (optional)\n'));
27
+ return;
28
+ }
29
+
30
+ const config = loadConfig();
31
+ console.log(chalk.dim('\n Encrypting and uploading...'));
32
+
33
+ const result = await syncToCloud(config.dbPath, cloudConfig);
34
+
35
+ if (result.success) {
36
+ console.log(chalk.green('\n ✅ Cloud sync complete'));
37
+ console.log(` DB: ${(result.dbSize / 1024).toFixed(0)}KB → Encrypted: ${(result.encryptedSize / 1024).toFixed(0)}KB`);
38
+ console.log(chalk.dim(` ${result.timestamp}\n`));
39
+ } else {
40
+ console.log(chalk.red(`\n ❌ Sync failed: ${result.error}\n`));
41
+ }
42
+ }
43
+
44
+ export async function cloudRestoreCommand() {
45
+ const cloudConfig = getCloudConfig();
46
+ if (!cloudConfig) {
47
+ console.log(chalk.red('\n Cloud not configured. See: sv cloud sync --help\n'));
48
+ return;
49
+ }
50
+
51
+ const config = loadConfig();
52
+ console.log(chalk.dim('\n Downloading and decrypting...'));
53
+
54
+ const result = await restoreFromCloud(config.dbPath, cloudConfig);
55
+
56
+ if (result.success) {
57
+ console.log(chalk.green('\n ✅ Restore complete'));
58
+ console.log(` Encrypted: ${(result.encryptedSize / 1024).toFixed(0)}KB → DB: ${(result.dbSize / 1024).toFixed(0)}KB`);
59
+ console.log(chalk.dim(' Previous DB backed up as .backup\n'));
60
+ } else {
61
+ console.log(chalk.red(`\n ❌ Restore failed: ${result.error}\n`));
62
+ }
63
+ }
64
+
65
+ export async function cloudStatusCommand() {
66
+ const state = getSyncState();
67
+ if (!state) {
68
+ console.log(chalk.yellow('\n No cloud sync history. Run: sv cloud sync\n'));
69
+ return;
70
+ }
71
+
72
+ console.log(chalk.bold('\n ☁️ Cloud Sync Status'));
73
+ console.log(` Last sync: ${state.lastSync}`);
74
+ console.log(` DB size: ${(state.dbSize / 1024).toFixed(0)}KB\n`);
75
+ }
@@ -0,0 +1,41 @@
1
+ // stellavault contradictions — detect contradicting statements (F-A12)
2
+
3
+ import chalk from 'chalk';
4
+ import { loadConfig, createKnowledgeHub } from '@stellavault/core';
5
+ import { detectContradictions } from '@stellavault/core';
6
+
7
+ export async function contradictionsCommand(_opts: any, cmd: any) {
8
+ const globalOpts = cmd?.parent?.opts?.() ?? {};
9
+ const jsonMode = globalOpts.json;
10
+ const config = loadConfig();
11
+ const hub = createKnowledgeHub(config);
12
+
13
+ console.error(chalk.dim('Scanning for contradictions...'));
14
+ await hub.store.initialize();
15
+ await hub.embedder.initialize();
16
+
17
+ const pairs = await detectContradictions(hub.store, 20);
18
+ await hub.store.close();
19
+
20
+ if (jsonMode) {
21
+ console.log(JSON.stringify({ count: pairs.length, contradictions: pairs }, null, 2));
22
+ return;
23
+ }
24
+
25
+ console.log('');
26
+ console.log(chalk.bold(` ⚡ ${pairs.length} potential contradictions found`));
27
+ console.log('');
28
+
29
+ for (const p of pairs) {
30
+ const confColor = p.confidence >= 0.8 ? chalk.red : p.confidence >= 0.6 ? chalk.yellow : chalk.dim;
31
+ console.log(` ${confColor(`${Math.round(p.confidence * 100)}%`)} ${chalk.dim(`[${p.type}]`)} ${chalk.bold(p.docA.title)} vs ${chalk.bold(p.docB.title)}`);
32
+ console.log(` A: ${chalk.dim(p.docA.statement.slice(0, 80))}`);
33
+ console.log(` B: ${chalk.dim(p.docB.statement.slice(0, 80))}`);
34
+ console.log('');
35
+ }
36
+
37
+ if (pairs.length === 0) {
38
+ console.log(chalk.green(' No contradictions detected. Your knowledge is consistent!'));
39
+ console.log('');
40
+ }
41
+ }