ltcai 11.2.0 → 11.4.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 (247) hide show
  1. package/README.md +46 -53
  2. package/docs/CHANGELOG.md +61 -0
  3. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  4. package/docs/DEVELOPMENT.md +1 -1
  5. package/docs/MULTI_AGENT_RUNTIME.md +1 -1
  6. package/docs/ONBOARDING.md +1 -1
  7. package/docs/OPERATIONS.md +6 -2
  8. package/docs/PERMISSION_MODE.md +1 -1
  9. package/docs/TRUST_MODEL.md +1 -1
  10. package/docs/WHY_LATTICE.md +1 -1
  11. package/docs/kg-schema.md +2 -2
  12. package/docs/v11.3.0_PLAN.md +202 -0
  13. package/docs/v11.4.0_RUST_FOUNDATION_PLAN.md +176 -0
  14. package/lattice_brain/__init__.py +1 -1
  15. package/lattice_brain/graph/_kg_common/__init__.py +287 -0
  16. package/lattice_brain/graph/_kg_common/extraction.py +516 -0
  17. package/lattice_brain/graph/_kg_common/relations.py +161 -0
  18. package/lattice_brain/graph/_kg_common/text.py +479 -0
  19. package/lattice_brain/graph/discovery_index/__init__.py +35 -0
  20. package/lattice_brain/graph/discovery_index/cleanup.py +182 -0
  21. package/lattice_brain/graph/discovery_index/extract.py +137 -0
  22. package/lattice_brain/graph/discovery_index/scan.py +411 -0
  23. package/lattice_brain/graph/discovery_index/upsert.py +495 -0
  24. package/lattice_brain/graph/projection/__init__.py +42 -0
  25. package/lattice_brain/graph/projection/curation.py +500 -0
  26. package/lattice_brain/graph/{projection.py → projection/v2_schema.py} +15 -477
  27. package/lattice_brain/graph/retrieval/__init__.py +54 -0
  28. package/lattice_brain/graph/retrieval/context.py +197 -0
  29. package/lattice_brain/graph/retrieval/graph_view.py +319 -0
  30. package/lattice_brain/graph/retrieval/hybrid.py +488 -0
  31. package/lattice_brain/graph/retrieval/maintenance.py +121 -0
  32. package/lattice_brain/graph/retrieval/signals.py +95 -0
  33. package/lattice_brain/graph/retrieval_vector/__init__.py +42 -0
  34. package/lattice_brain/graph/retrieval_vector/fingerprint.py +97 -0
  35. package/lattice_brain/graph/retrieval_vector/indexing.py +347 -0
  36. package/lattice_brain/graph/retrieval_vector/search.py +560 -0
  37. package/lattice_brain/graph/retrieval_vector/status.py +374 -0
  38. package/lattice_brain/ingestion/__init__.py +130 -0
  39. package/lattice_brain/ingestion/_contract.py +90 -0
  40. package/lattice_brain/ingestion/constants.py +127 -0
  41. package/lattice_brain/ingestion/folder_scan.py +57 -0
  42. package/lattice_brain/ingestion/folders.py +258 -0
  43. package/lattice_brain/ingestion/hashing.py +26 -0
  44. package/lattice_brain/ingestion/jobs_api.py +107 -0
  45. package/lattice_brain/ingestion/models.py +80 -0
  46. package/lattice_brain/ingestion/pipeline.py +486 -0
  47. package/lattice_brain/ingestion/quality.py +209 -0
  48. package/lattice_brain/ingestion/routing.py +295 -0
  49. package/lattice_brain/multimodal/__init__.py +164 -0
  50. package/lattice_brain/multimodal/audio.py +77 -0
  51. package/lattice_brain/multimodal/common.py +118 -0
  52. package/lattice_brain/multimodal/images.py +498 -0
  53. package/lattice_brain/multimodal/ports.py +169 -0
  54. package/lattice_brain/multimodal/video.py +410 -0
  55. package/lattice_brain/portability/__init__.py +90 -0
  56. package/lattice_brain/portability/_contract.py +42 -0
  57. package/lattice_brain/portability/backups.py +338 -0
  58. package/lattice_brain/portability/bundles.py +136 -0
  59. package/lattice_brain/portability/constants.py +93 -0
  60. package/lattice_brain/portability/fsops.py +138 -0
  61. package/lattice_brain/portability/service.py +41 -0
  62. package/lattice_brain/{portability.py → portability/sharing.py} +44 -677
  63. package/lattice_brain/runtime/__init__.py +1 -1
  64. package/lattice_brain/runtime/multi_agent.py +1 -1
  65. package/latticeai/__init__.py +1 -1
  66. package/latticeai/api/chronicle.py +63 -0
  67. package/latticeai/core/agent/__init__.py +93 -0
  68. package/latticeai/core/agent/_contract.py +79 -0
  69. package/latticeai/core/agent/context.py +57 -0
  70. package/latticeai/core/agent/deps.py +125 -0
  71. package/latticeai/core/agent/execution.py +622 -0
  72. package/latticeai/core/agent/planning.py +145 -0
  73. package/latticeai/core/agent/recovery.py +157 -0
  74. package/latticeai/core/agent/runtime.py +210 -0
  75. package/latticeai/core/agent/verification.py +231 -0
  76. package/latticeai/core/embedding_providers/__init__.py +151 -0
  77. package/latticeai/core/embedding_providers/base.py +199 -0
  78. package/latticeai/core/embedding_providers/captions.py +162 -0
  79. package/latticeai/core/embedding_providers/profiles.py +126 -0
  80. package/latticeai/core/embedding_providers/text.py +350 -0
  81. package/latticeai/core/embedding_providers/vision.py +352 -0
  82. package/latticeai/core/file_generation/__init__.py +115 -0
  83. package/latticeai/core/file_generation/bundles.py +76 -0
  84. package/latticeai/core/file_generation/extraction.py +154 -0
  85. package/latticeai/core/file_generation/inference.py +235 -0
  86. package/latticeai/core/file_generation/orchestration.py +152 -0
  87. package/latticeai/core/file_generation/prompting.py +117 -0
  88. package/latticeai/core/file_generation/repair.py +114 -0
  89. package/latticeai/core/file_generation/sanitize.py +61 -0
  90. package/latticeai/core/file_generation/validation.py +201 -0
  91. package/latticeai/core/legacy_compatibility.py +1 -1
  92. package/latticeai/core/marketplace.py +1 -1
  93. package/latticeai/core/messages.py +9 -0
  94. package/latticeai/core/workspace_os_constants.py +1 -1
  95. package/latticeai/integrations/telegram_bot/__init__.py +123 -0
  96. package/latticeai/integrations/telegram_bot/__main__.py +17 -0
  97. package/latticeai/integrations/telegram_bot/config.py +86 -0
  98. package/latticeai/integrations/telegram_bot/dispatch.py +311 -0
  99. package/latticeai/integrations/telegram_bot/flows.py +478 -0
  100. package/latticeai/integrations/telegram_bot/helpers.py +322 -0
  101. package/latticeai/integrations/telegram_bot/screens.py +394 -0
  102. package/latticeai/models/router/__init__.py +88 -0
  103. package/latticeai/models/router/_contract.py +66 -0
  104. package/latticeai/models/router/branding.py +56 -0
  105. package/latticeai/models/router/catalog.py +69 -0
  106. package/latticeai/models/router/documents.py +199 -0
  107. package/latticeai/models/router/errors.py +37 -0
  108. package/latticeai/models/router/generation.py +258 -0
  109. package/latticeai/models/router/loading.py +291 -0
  110. package/latticeai/models/router/local_models.py +85 -0
  111. package/latticeai/models/router/registry.py +147 -0
  112. package/latticeai/runtime/build_phases/__init__.py +82 -0
  113. package/latticeai/runtime/build_phases/features.py +407 -0
  114. package/latticeai/runtime/build_phases/foundation.py +555 -0
  115. package/latticeai/runtime/build_phases/web.py +492 -0
  116. package/latticeai/runtime/runtime_context.py +1 -0
  117. package/latticeai/services/architecture_readiness.py +48 -19
  118. package/latticeai/services/brain_intelligence/__init__.py +58 -0
  119. package/latticeai/services/brain_intelligence/_contract.py +71 -0
  120. package/latticeai/services/brain_intelligence/consistency.py +193 -0
  121. package/latticeai/services/brain_intelligence/constants.py +47 -0
  122. package/latticeai/services/brain_intelligence/digest.py +258 -0
  123. package/latticeai/services/brain_intelligence/health.py +331 -0
  124. package/latticeai/services/brain_intelligence/proposals.py +264 -0
  125. package/latticeai/services/brain_intelligence/sampling.py +84 -0
  126. package/latticeai/services/brain_intelligence/service.py +48 -0
  127. package/latticeai/services/chronicle.py +557 -0
  128. package/latticeai/services/memory_service/__init__.py +52 -0
  129. package/latticeai/services/memory_service/_contract.py +100 -0
  130. package/latticeai/services/memory_service/brief.py +431 -0
  131. package/latticeai/services/memory_service/constants.py +57 -0
  132. package/latticeai/services/memory_service/maintenance.py +138 -0
  133. package/latticeai/services/memory_service/manager.py +186 -0
  134. package/latticeai/services/memory_service/proof.py +136 -0
  135. package/latticeai/services/memory_service/recall.py +225 -0
  136. package/latticeai/services/memory_service/service.py +48 -0
  137. package/latticeai/services/memory_service/stores.py +110 -0
  138. package/latticeai/services/model_runtime/__init__.py +322 -0
  139. package/latticeai/services/model_runtime/cloud.py +87 -0
  140. package/latticeai/services/model_runtime/download.py +282 -0
  141. package/latticeai/services/model_runtime/engines.py +341 -0
  142. package/latticeai/services/model_runtime/loading.py +178 -0
  143. package/latticeai/services/model_runtime/service.py +129 -0
  144. package/latticeai/services/model_runtime/state.py +131 -0
  145. package/latticeai/services/model_runtime/status.py +255 -0
  146. package/latticeai/services/product_readiness.py +15 -7
  147. package/latticeai/setup/wizard/__init__.py +126 -0
  148. package/latticeai/setup/wizard/catalog.py +172 -0
  149. package/latticeai/setup/wizard/detect.py +323 -0
  150. package/latticeai/setup/wizard/install.py +348 -0
  151. package/latticeai/setup/wizard/paths.py +168 -0
  152. package/latticeai/setup/wizard/plans.py +74 -0
  153. package/latticeai/setup/wizard/recommend.py +320 -0
  154. package/package.json +6 -2
  155. package/scripts/bump_version.py +14 -0
  156. package/scripts/capture_release_evidence.mjs +33 -21
  157. package/scripts/check_current_release_docs.mjs +1 -1
  158. package/scripts/check_i18n_namespace_coverage.mjs +41 -4
  159. package/scripts/check_max_file_lines.mjs +102 -0
  160. package/scripts/check_release_evidence_bound.mjs +30 -15
  161. package/scripts/check_screenshot_pixel_delta.py +34 -4
  162. package/scripts/check_server_i18n.mjs +1 -0
  163. package/scripts/generate_rust_parity_fixtures.py +562 -0
  164. package/scripts/lib/mock_server_fingerprint.mjs +94 -0
  165. package/scripts/release_screen_claims.json +31 -2
  166. package/src-tauri/Cargo.lock +361 -3
  167. package/src-tauri/Cargo.toml +6 -1
  168. package/src-tauri/src/backend.rs +349 -0
  169. package/src-tauri/src/folder.rs +33 -0
  170. package/src-tauri/src/main.rs +97 -399
  171. package/src-tauri/tauri.conf.json +1 -1
  172. package/static/app/asset-manifest.json +41 -37
  173. package/static/app/assets/Act-yYpYnn0v.js +1 -0
  174. package/static/app/assets/AdminConsole-DL3Cr5pL.js +1 -0
  175. package/static/app/assets/{Brain-tuhI4sOC.js → Brain-C1HBN0Wf.js} +2 -2
  176. package/static/app/assets/BrainHome-DoXRhUUC.js +2 -0
  177. package/static/app/assets/BrainSignals-6yR6ir5t.js +1 -0
  178. package/static/app/assets/Capture-CFIRsFNE.js +1 -0
  179. package/static/app/assets/Chronicle-BZbEgiwN.js +1 -0
  180. package/static/app/assets/CommandPalette-D2pMxC2I.js +1 -0
  181. package/static/app/assets/Library-DwO3yZST.js +1 -0
  182. package/static/app/assets/{LivingBrain-DBwhto14.js → LivingBrain-Jn1GK0-S.js} +1 -1
  183. package/static/app/assets/ProductFlow-B-w1R4Oo.js +1 -0
  184. package/static/app/assets/ReviewCard-6B27X8Vg.js +3 -0
  185. package/static/app/assets/System-DW8F-2xL.js +1 -0
  186. package/static/app/assets/arrow-left-DXvKg9U6.js +1 -0
  187. package/static/app/assets/{bot-Cia42c2h.js → bot-IM_E_Y12.js} +1 -1
  188. package/static/app/assets/brain-Ci1CkWjM.js +1 -0
  189. package/static/app/assets/{button-2j2Ijzgq.js → button-COwyqfHM.js} +1 -1
  190. package/static/app/assets/circle-check-DfInj-qD.js +1 -0
  191. package/static/app/assets/{circle-pause-BEFeWpVW.js → circle-pause-DEM4A1Y5.js} +1 -1
  192. package/static/app/assets/{circle-play-ujXMcHxl.js → circle-play-C9djDuLd.js} +1 -1
  193. package/static/app/assets/{cpu-k4awryFq.js → cpu-DFdo1gw-.js} +1 -1
  194. package/static/app/assets/{download-DFbLJ_ig.js → download-SnJL6oqk.js} +1 -1
  195. package/static/app/assets/{folder-open-7y_b6xkM.js → folder-open-CqZeDkjE.js} +1 -1
  196. package/static/app/assets/{hard-drive-Bidh02Kr.js → hard-drive-j1jJXYYf.js} +1 -1
  197. package/static/app/assets/{index-DwDl9-8Y.css → index-BLPb5lmE.css} +1 -1
  198. package/static/app/assets/index-_u5iUHDr.js +10 -0
  199. package/static/app/assets/input-B0lPdRQZ.js +1 -0
  200. package/static/app/assets/link-2-CoFbooHS.js +1 -0
  201. package/static/app/assets/{permissionCopy-Bpb83Hx9.js → permissionCopy-BsyLxtao.js} +1 -1
  202. package/static/app/assets/primitives-DEbN-d6p.js +1 -0
  203. package/static/app/assets/search-BybIWPNd.js +1 -0
  204. package/static/app/assets/{share-2-BH1M-WNi.js → share-2-CVtZ_ewX.js} +1 -1
  205. package/static/app/assets/{shield-alert-BlKdBXcG.js → shield-alert-CBi2GNWM.js} +1 -1
  206. package/static/app/assets/{textarea-CCWbUfFB.js → textarea-DNMpB5ih.js} +1 -1
  207. package/static/app/assets/{useFocusTrap-YdHQ7pJ1.js → useFocusTrap-C83t3GXF.js} +1 -1
  208. package/static/app/assets/useMutation-DtbJDoyz.js +1 -0
  209. package/static/app/assets/{useQuery-CXQiwbVT.js → useQuery-Dcp1OChy.js} +1 -1
  210. package/static/app/assets/utils-BlZr7Pd4.js +4 -0
  211. package/static/app/assets/workspace-jJY4RuAV.js +1 -0
  212. package/static/app/index.html +4 -4
  213. package/static/sw.js +1 -1
  214. package/lattice_brain/graph/_kg_common.py +0 -1331
  215. package/lattice_brain/graph/discovery_index.py +0 -1141
  216. package/lattice_brain/graph/retrieval.py +0 -1120
  217. package/lattice_brain/graph/retrieval_vector.py +0 -1293
  218. package/lattice_brain/ingestion.py +0 -1525
  219. package/lattice_brain/multimodal.py +0 -1258
  220. package/latticeai/core/agent.py +0 -1465
  221. package/latticeai/core/embedding_providers.py +0 -1196
  222. package/latticeai/core/file_generation.py +0 -1047
  223. package/latticeai/integrations/telegram_bot.py +0 -1390
  224. package/latticeai/models/router.py +0 -1007
  225. package/latticeai/runtime/build_phases.py +0 -1450
  226. package/latticeai/services/brain_intelligence.py +0 -1083
  227. package/latticeai/services/memory_service.py +0 -1177
  228. package/latticeai/services/model_runtime.py +0 -1281
  229. package/latticeai/setup/wizard.py +0 -1310
  230. package/static/app/assets/Act-AWf0SAKp.js +0 -1
  231. package/static/app/assets/AdminConsole-D0u8Tiyj.js +0 -1
  232. package/static/app/assets/BrainHome-Ts7G_Ila.js +0 -2
  233. package/static/app/assets/BrainSignals-jMYgQ2Ar.js +0 -1
  234. package/static/app/assets/Capture-CqOSzyPr.js +0 -1
  235. package/static/app/assets/CommandPalette-DC0Bzh-I.js +0 -1
  236. package/static/app/assets/Library-CX-bbhmK.js +0 -1
  237. package/static/app/assets/ProductFlow-BHA2cfKI.js +0 -1
  238. package/static/app/assets/ReviewCard-BUhCKRNM.js +0 -3
  239. package/static/app/assets/System-Bu2t5hn1.js +0 -1
  240. package/static/app/assets/arrow-left-Dzwa5zRb.js +0 -1
  241. package/static/app/assets/brain-DJMoqrwx.js +0 -1
  242. package/static/app/assets/index-BpYkzcVm.js +0 -10
  243. package/static/app/assets/input-DSlJJxRs.js +0 -1
  244. package/static/app/assets/primitives-BCx6TvfG.js +0 -1
  245. package/static/app/assets/search-Cgy8cCFJ.js +0 -1
  246. package/static/app/assets/utils-zqPZJxdx.js +0 -4
  247. package/static/app/assets/workspace-DXTihhfU.js +0 -1
@@ -0,0 +1,176 @@
1
+ # v11.4.0 — Rust Foundation (설계 문서)
2
+
3
+ > 상태: 계획 → 구현 → **출하됨(v11.4.0)**. Rust 전환의 단일 출처 설계
4
+ > 문서. 설계·기획: 본 문서. 목표 아키텍처는 아래 다이어그램, 이번
5
+ > 릴리스는 그 **Phase 1**이다.
6
+
7
+ ## 목표 아키텍처 (전환 완료 시점의 모습)
8
+
9
+ ```
10
+ Desktop(Tauri) Browser Ext VS Code Ext
11
+ └────────────────┼────────────────┘
12
+ React / TypeScript
13
+ │
14
+ ┌───────▼───────┐
15
+ │ Lattice Host │ Rust
16
+ │ (supervisor + │
17
+ │ IPC/API 관문) │
18
+ └───────┬───────┘
19
+ ┌────────────────────┼────────────────────┐
20
+ lattice-core Agent Runtime IPC / API
21
+ (Brain·Graph· (Tools·Sandbox· (gateway,
22
+ Memory·Storage) Permission·Jobs) native routes)
23
+ │ │
24
+ Ingestion ──── Retrieval(Vector·BM25·KG → Fusion → Rerank
25
+ │ → Context Builder)
26
+ └──────────────┬──────────────┘
27
+ ▼
28
+ Python AI Worker ← 최종적으로 Python이 맡는 유일한 층
29
+ (MLX · Ollama · Cloud → LLM, chat/agent 추론)
30
+ ```
31
+
32
+ ## 왜 단계적인가 (정직성 원칙)
33
+
34
+ 현 Python 플랫폼은 44개 라우터 파일 · ~448 라우트 · 40,488문 100.00%
35
+ 커버리지 플로어 위에 있다. 이것을 한 릴리스에 재작성하는 것은 "전체
36
+ 시스템에 지장 없음"과 양립할 수 없다. 그래서 각 릴리스가 **실제로
37
+ 작동하고 증명된 Rust 조각**을 늘려가고, Python은 마지막에 AI Worker
38
+ (모델 추론)로 수렴한다. 11.4.0은 그 뼈대를 세운다.
39
+
40
+ ## Phase 1 스코프 (11.4.0)
41
+
42
+ `rust/` cargo workspace 신설 — 3개 크레이트, 전부 tauri 비의존(우분투
43
+ CI에서 시스템 패키지 없이 테스트 가능):
44
+
45
+ ### 1. `lattice-core` — Brain 저장소 읽기 층 + 임베딩 산술
46
+
47
+ - 데이터 디렉터리 해석: `LATTICEAI_DATA_DIR` → 기본 `~/.ltcai`,
48
+ DB는 `knowledge_graph.sqlite` (Python과 동일 파일).
49
+ - 읽기 전용 SQLite 접속(rusqlite `bundled` + **fts5 필수**): WAL,
50
+ `busy_timeout` 명시(Python은 미설정 — Rust가 양보하는 쪽).
51
+ - 스키마 리더: `kgv2_nodes`/`kgv2_edges` 뷰(어휘·그래프 lane),
52
+ `nodes`/`chunks`/`vector_embeddings`(벡터 lane),
53
+ `nodes_v2`(워크스페이스 스코핑) — **lane별 테이블 이원화는 Python
54
+ 현행 그대로** 재현한다.
55
+ - 임베딩 모듈 = `lattice_brain/embeddings.py`의 1:1 포트:
56
+ 토크나이저(`[a-z0-9][a-z0-9_.:/+-]{1,}` + latin 3-gram(len≥5) +
57
+ 한국어 2-gram(len≥3)), blake2b-8 해시 bag-of-features(하위 비트 부호),
58
+ L2 정규화, `<f32` LE 인코딩/디코딩(4B/dim, 헤더 없음), 유사도는
59
+ **순수 내적**(dim 불일치는 하드 에러). 기본 dim 384,
60
+ 모델 id `lattice-local-hash-v1:{dim}`.
61
+
62
+ ### 2. `lattice-retrieval` — 네이티브 하이브리드 검색 (패리티 증명 동반)
63
+
64
+ 패리티 대상은 **graph-layer `KnowledgeGraphStore.hybrid_search`**
65
+ (2채널 alpha 융합)와 그 구성 lane인 `search()`(키워드),
66
+ `vector_search()`(벡터). 서비스 층 3채널 융합(`SearchService`)은
67
+ traverse/relationship 의존이 커서 Phase 2로 명시 이월.
68
+
69
+ 기본 env 구성(brute 백엔드, RRF/그래프 확장/이미지 융합/CE rerank 꺼짐)
70
+ 에서 다음을 정확 재현:
71
+
72
+ - **키워드 lane**: trigram FTS5 `MATCH '"…"'`(내부 `"` 이중화,
73
+ len<3 → 빈 결과) → LIKE 폴백(`%q%`, `updated_at DESC, id ASC`) →
74
+ topic-term 보충(`limit*3`) → **(hits, type_boost, updated_at) 재점수**
75
+ (hits = topic 후보 12개의 대소문자 무시 부분일치 수, type_boost
76
+ 집합 고정) + **2-pass 안정 정렬(id ASC → score DESC)**. 점수는
77
+ 호출측 1/rank.
78
+ - **벡터 lane**: `embedding_model+dim` 필터, `indexed_at DESC` 후보
79
+ 상한(기본 10000, `LATTICEAI_VECTOR_MAX_CANDIDATES`), 순차 f64 내적
80
+ (Python과 동일 누적 순서 → bit-exact), min_score 필터,
81
+ `(score, updated_at) DESC` 안정 정렬, recall/honesty 필드 동일.
82
+ - **정책**: `classify_query`(ko/en 정규식, code→recency→person→fact
83
+ 우선순위)는 **원 질의**에, rewrite(공백 축약 + filler 3규칙,
84
+ remainder≥4)는 검색 질의에. recency 클래스만 half-life 14일 감쇠
85
+ `0.5 + 0.5*recency`.
86
+ - **융합**: lexical 1/rank, vector max-정규화, `alpha*vec+(1-α)*lex`,
87
+ `round(x,6)`(**banker's rounding** — CPython round와 동치 구현),
88
+ 정렬 `(-score, node_id)`, identity rerank(`rerank_score=score`,
89
+ top_k 절단), 결과 JSON 필드·라벨(`fusion`, `sources`, `policy`,
90
+ `vector.*`) 전부 동형.
91
+ - **스코핑**: `allowed_workspaces=None` ⇒ 스코핑 없음(로컬 신뢰 소유자
92
+ 기본 경로) — fail-closed로 바꾸지 않는다. 빈 집합 ⇒ 아무것도 매치
93
+ 안 됨. legacy-global(NULL)은 `include_legacy_global`로만 포함.
94
+
95
+ **패리티 하네스(양방향 계약)**:
96
+ - `scripts/generate_rust_parity_fixtures.py`(Python)가 실제 Python
97
+ 쓰기 경로로 소형 스토어를 빚어 `rust/fixtures/parity_store.sqlite`
98
+ + 질의 세트(ko/en, 4 클래스, len<3, 무결과, 동점 tie) +
99
+ `rust/fixtures/golden/*.json`(Python 엔진의 hybrid/keyword/vector
100
+ 출력)을 커밋 산출물로 생성.
101
+ - `tests/unit/test_rust_parity_contract.py`: 커밋된 fixture DB에 대해
102
+ Python 엔진을 다시 돌려 golden과 일치함을 상시 단언 — Python 쪽
103
+ 의미 변경이 골든을 조용히 무효화하지 못한다.
104
+ - `lattice-retrieval`의 cargo 테스트: 같은 DB·같은 질의에 대해 Rust
105
+ 출력 == 같은 golden. 점수는 기본 완전 일치(불가피한 tie 케이스만
106
+ 1e-12, 사유 주석).
107
+
108
+ ### 3. `lattice-host` — 수퍼바이저 + IPC/API 게이트웨이
109
+
110
+ - **수퍼바이저(lib + bin)**: Python 워커 스폰(명령 해석은 현행 Tauri
111
+ 규칙 승계: `LATTICEAI_DESKTOP_BACKEND_CMD` → `ltcai` → python 후보 →
112
+ 번들 트리; 현행 `sort()+dedup()`이 우선순위를 파괴하던 버그는 수정),
113
+ **`/health` HTTP 프로브**(현행 TCP 접속 프로브 대체), 크래시 시
114
+ 지수 백오프 자동 재시작(상한·수동 정지 존중), 우아한 종료(SIGTERM →
115
+ 유예 → SIGKILL), **포트 통일**: 기본 4825에서 시작해 빈 포트 탐색,
116
+ 선택 포트를 워커 env(`LATTICEAI_PORT`)와 상위(Tauri `backend_origin`)
117
+ 에 단일 출처로 공급. 로그는 기존 `~/.ltcai/desktop-sidecar.log` 계승.
118
+ - **게이트웨이(axum, 127.0.0.1 전용)**: `/host/health`·`/host/status`
119
+ (수퍼바이저 상태), 네이티브 `/rust/search/{hybrid,keyword,vector}`
120
+ (lattice-retrieval 직결, 읽기 전용), 그 외 전 경로는 워커로 리버스
121
+ 프록시(스트리밍/SSE 통과). Phase 1에서는 **옵트인 front-door**
122
+ (`lattice-host` 바이너리 실행 시) — 기존 진입 경로(ltcai CLI,
123
+ 브라우저 직접 접속)는 그대로 둔다. 비-loopback 바인드 거부.
124
+
125
+ ### 4. Tauri 통합 (DMG가 새 기초 위에 올라탐)
126
+
127
+ `src-tauri`는 `lattice-host`를 path 의존으로 소비: `main.rs`의 ad-hoc
128
+ 스폰/프로브/재시작 로직을 크레이트 호출로 대체(451줄 → 얇은 셸).
129
+ Tauri 명령 5종(`backend_origin`/`backend_status`/`restart_backend`/
130
+ `shutdown_backend`/`select_folder`)의 프론트 계약은 불변. 네트워크
131
+ 토폴로지도 불변(웹뷰는 여전히 `{origin}/app`) — 사용자 가시 변화 없이
132
+ 수퍼바이저 품질만 오른다(HTTP 헬스, 자동 재시작, 포트 충돌 처리).
133
+
134
+ ### 5. 게이트/CI/버전
135
+
136
+ - ci.yml에 `rust` 잡 신설: ubuntu, stable 툴체인(핀), `cargo fmt
137
+ --check` + `clippy -D warnings` + `cargo test` — `rust/` workspace만
138
+ (tauri 시스템 의존 없음). src-tauri 빌드는 종전대로 릴리스 플로우
139
+ (macOS)에서.
140
+ - `check_max_file_lines.mjs`에 `*.rs` 추가(상한 1,000, `src-tauri/gen`
141
+ ·`target` 제외). 모든 신규 Rust 파일 목표 ≤500줄.
142
+ - `scripts/bump_version.py`와 `test_version_consistency.py`에
143
+ `rust/Cargo.toml`(workspace.package.version, 크레이트는
144
+ `version.workspace = true`) 편입 — 버전 단일 출처 유지.
145
+ - Python 커버리지 플로어(문·분기 100%)와 프론트 100%는 그대로. Rust는
146
+ cargo 테스트 + 패리티 골든이 게이트.
147
+
148
+ ### 명시적 비-목표 (Phase 1에서 하지 않는 것)
149
+
150
+ - 3채널 `SearchService.hybrid_search`/KG 읽기 API의 네이티브화(Phase 2),
151
+ - Ingestion(Watch/Parse/Chunk/Dedup)·Jobs/Events/Scheduler(Phase 2~3),
152
+ - Agent Runtime(Tools/Sandbox/Permission)의 Rust화(Phase 4),
153
+ - 게이트웨이의 기본 front-door 승격(Phase 2에서 e2e로 검증 후),
154
+ - HNSW/quantized 백엔드·CE rerank·이미지 late fusion 패리티(브루트
155
+ 기본 경로만; 나머지는 요청 시 워커로 프록시되므로 기능 손실 없음).
156
+
157
+ ## 로드맵 (다이어그램 → 릴리스 매핑)
158
+
159
+ | Phase | 릴리스 | 내용 |
160
+ |---|---|---|
161
+ | 1 | **11.4.0** | workspace + core 읽기층 + retrieval 패리티 + host 수퍼바이저/게이트웨이(옵트인) + Tauri 통합 |
162
+ | 2 | 11.5.x | 게이트웨이 front-door 기본화, KG 읽기·3채널 검색·history 네이티브, Ingestion Watch/Chunk/Dedup |
163
+ | 3 | 11.6.x | Jobs/Events/Pipeline/Scheduler, Context Builder 네이티브 |
164
+ | 4 | 12.0 | Agent Runtime(Tools·Process·Sandbox·Permission) Rust화 — Python은 AI Worker로 수렴 |
165
+
166
+ ## 릴리스 체크리스트 (11.4.0)
167
+
168
+ 1. W1(host) ∥ W2(core+retrieval+패리티) → W3(Tauri·CI·게이트·버전 배선).
169
+ 2. 전 게이트 로컬 그린(pytest 100% 플로어·프론트·lint 체인·cargo 3종)
170
+ + fresh venv 재검증.
171
+ 3. `bump_version.py 11.4.0`(rust workspace 포함) → OpenAPI 재생성 →
172
+ 문서·releaseTheme("Rust Foundation") → claims(화면 무변경) →
173
+ `release:evidence` 재촬영(스크린샷 13종 + GIF) →
174
+ `release:artifacts`(DMG 포함) → validate/smoke.
175
+ 4. 브랜치 `release/v11.4.0` 커밋·푸시 → PR로 CI 그린 → 태그
176
+ `v11.4.0` → GitHub Release(정확한 파일명 5종).
@@ -26,7 +26,7 @@ from .storage import (
26
26
  storage_from_env,
27
27
  )
28
28
 
29
- __version__ = "11.2.0"
29
+ __version__ = "11.4.0"
30
30
 
31
31
  __all__ = [
32
32
  "AgentRuntime",
@@ -0,0 +1,287 @@
1
+ """
2
+ SQLite knowledge graph for Lattice AI workspace memory.
3
+
4
+ The graph keeps raw event JSON, normalized node metadata, and edges in one
5
+ portable database so it can later migrate to Neo4j/Postgres without changing
6
+ the ingestion contract.
7
+ """
8
+
9
+ # ruff: noqa: F401,F841
10
+
11
+ import asyncio
12
+ import hashlib
13
+ import json
14
+ import logging
15
+ import math
16
+ import os
17
+ import platform
18
+ import re
19
+ import shutil
20
+ import sqlite3
21
+ import time
22
+ import zipfile
23
+ from collections import Counter
24
+ from contextlib import contextmanager
25
+ from datetime import datetime
26
+ from pathlib import Path
27
+ from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple
28
+
29
+ try:
30
+ from ..schema import EdgeType, KGStoreV2, NodeType, _exec_script
31
+ except Exception: # pragma: no cover - v2 schema is optional at import time
32
+ KGStoreV2 = None # type: ignore[assignment,misc]
33
+ NodeType = None # type: ignore[assignment,misc]
34
+ EdgeType = None # type: ignore[assignment,misc]
35
+ _exec_script = None # type: ignore[assignment]
36
+
37
+ from ...embeddings import LocalEmbeddingModel
38
+ from ..json_utils import _json, _safe_loads
39
+ from ..runtime import get_llm_router, set_llm_router
40
+
41
+ # Default read source for the graph queries: v2 reconstruction views.
42
+ # Override with LATTICEAI_KG_READ_V2=0 to fall back to the legacy tables.
43
+ _READ_FROM_V2_DEFAULT = os.getenv("LATTICEAI_KG_READ_V2", "1") != "0"
44
+
45
+ # Static constants (projection/format versions, local-ingestion classification
46
+ # tables, OS exclusion lists) live in ._kg_constants; re-exported here so every
47
+ # existing ``from ._kg_common import <CONST>`` site is unaffected.
48
+ from ...quiet import quiet
49
+ from .._kg_constants import ( # noqa: E402
50
+ _KG_DB_FORMAT_KEY,
51
+ _KG_DB_FORMAT_VERSION,
52
+ _PROJECTION_VERSION,
53
+ _V2_WRITE_MASTER_KEY,
54
+ COMMON_EXCLUDED_DIRS,
55
+ COMMON_EXCLUDED_FILE_NAMES,
56
+ COMMON_EXCLUDED_FILE_SUFFIXES,
57
+ GRAPH_SCHEMA_VERSION,
58
+ LINUX_EXCLUDED_PREFIXES,
59
+ LOCAL_CODE_EXTENSIONS,
60
+ LOCAL_DOCUMENT_EXTENSIONS,
61
+ LOCAL_IMAGE_EXTENSIONS,
62
+ LOCAL_SIZE_LIMITS,
63
+ LOCAL_SLIDE_EXTENSIONS,
64
+ LOCAL_SPREADSHEET_EXTENSIONS,
65
+ LOCAL_SUPPORTED_EXTENSIONS,
66
+ LOCAL_TEXT_EXTENSIONS,
67
+ MACOS_EXCLUDED_PREFIXES,
68
+ SENSITIVE_PATH_KEYWORDS,
69
+ WINDOWS_EXCLUDED_NAMES,
70
+ )
71
+
72
+ # Pure fs/path/hash/classification helpers → ._kg_fsutil, re-exported so the
73
+ # static __all__ below forwards them to the graph mixins. Listed explicitly
74
+ # rather than star-imported: a star import here made every name in this
75
+ # module unverifiable to both ruff and mypy.
76
+ from .._kg_fsutil import ( # noqa: E402,F401
77
+ _current_os_type,
78
+ _drive_id_for_path,
79
+ _excluded_directory_reason,
80
+ _file_category,
81
+ _is_hidden_path,
82
+ _is_relative_to,
83
+ _node_type_for_category,
84
+ _now,
85
+ _parse_iso,
86
+ _parser_type_for_category,
87
+ _path_fingerprint,
88
+ _path_parts_lower,
89
+ _recency_score,
90
+ _root_warning,
91
+ _safe_iso_from_stat_mtime,
92
+ _sample_file,
93
+ _sensitive_file_reason,
94
+ _sha256_bytes,
95
+ _sha256_text,
96
+ _size_limit_for_category,
97
+ _slug,
98
+ )
99
+
100
+ # The logic this module used to hold inline lives in three cohesive submodules
101
+ # (v11.3.0 decomposition). Every name is re-exported below, so the twelve
102
+ # `from ._kg_common import *` consumers are unaffected — and `__all__` is still
103
+ # the single written-down star-import contract.
104
+ from .extraction import ( # noqa: E402
105
+ _CONCEPT_STOP,
106
+ _LLM_EXTRACT_CONCEPT_PROMPT,
107
+ _LLM_EXTRACT_TRIPLE_PROMPT,
108
+ ENABLE_LLM_EXTRACTION,
109
+ _extract_concepts,
110
+ _extract_concepts_rules,
111
+ _extract_triples,
112
+ _extract_triples_rules,
113
+ _llm_extract_concepts,
114
+ _llm_extract_triples,
115
+ _semantic_items,
116
+ _topic_candidates,
117
+ )
118
+ from .relations import ( # noqa: E402
119
+ _NOT_PERSON_WORDS,
120
+ COOCCURRENCE_CONCEPT_LIMIT,
121
+ COOCCURRENCE_EDGE_WEIGHT,
122
+ EDGE_VERB,
123
+ VERB_EDGE_WEIGHT,
124
+ _classify_node_type,
125
+ _infer_edge,
126
+ infer_edge_relation,
127
+ )
128
+ from .text import ( # noqa: E402
129
+ _CHUNK_STRATEGIES,
130
+ _CODE_BLANK_RUN_RE,
131
+ _CODE_BOUNDARY_LINE_RE,
132
+ _CODE_CHUNK_EXTENSIONS,
133
+ _MARKDOWN_CHUNK_EXTENSIONS,
134
+ _MARKDOWN_HEADING_RE,
135
+ _MARKDOWN_MIN_SECTION_CHARS,
136
+ _PROSE_CHUNK_EXTENSIONS,
137
+ _PROSE_MIN_SPAN_RATIO,
138
+ _PROSE_STRONG_BOUNDARY_RE,
139
+ _PROSE_WEAK_BOUNDARY_RE,
140
+ _chunks,
141
+ _clean_text,
142
+ _code_chunks,
143
+ _code_segment_spans,
144
+ _last_boundary,
145
+ _markdown_chunks,
146
+ _markdown_section_spans,
147
+ _merge_small_sections,
148
+ _plain_windows,
149
+ _prose_chunks,
150
+ chunk_strategy_for,
151
+ citation_locator,
152
+ page_for_offset,
153
+ pdf_page_offsets,
154
+ typed_chunk_meta_fields,
155
+ typed_chunks,
156
+ )
157
+
158
+ # Static export list. This used to be `[name for name in globals() if not
159
+ # name.startswith("__")]`, which is invisible to a type checker: every
160
+ # `from ._kg_common import *` consumer then had *no* resolvable names, and
161
+ # mypy reported ~750 spurious `name-defined` errors across the graph
162
+ # package. `tests/unit/test_kg_common_exports.py` asserts this list still
163
+ # equals what the computed expression would produce, so it cannot drift.
164
+ __all__ = [
165
+ "Any",
166
+ "COMMON_EXCLUDED_DIRS",
167
+ "COMMON_EXCLUDED_FILE_NAMES",
168
+ "COMMON_EXCLUDED_FILE_SUFFIXES",
169
+ "COOCCURRENCE_CONCEPT_LIMIT",
170
+ "COOCCURRENCE_EDGE_WEIGHT",
171
+ "Counter",
172
+ "Dict",
173
+ "EDGE_VERB",
174
+ "ENABLE_LLM_EXTRACTION",
175
+ "EdgeType",
176
+ "GRAPH_SCHEMA_VERSION",
177
+ "Iterable",
178
+ "Iterator",
179
+ "KGStoreV2",
180
+ "LINUX_EXCLUDED_PREFIXES",
181
+ "LOCAL_CODE_EXTENSIONS",
182
+ "LOCAL_DOCUMENT_EXTENSIONS",
183
+ "LOCAL_IMAGE_EXTENSIONS",
184
+ "LOCAL_SIZE_LIMITS",
185
+ "LOCAL_SLIDE_EXTENSIONS",
186
+ "LOCAL_SPREADSHEET_EXTENSIONS",
187
+ "LOCAL_SUPPORTED_EXTENSIONS",
188
+ "LOCAL_TEXT_EXTENSIONS",
189
+ "List",
190
+ "LocalEmbeddingModel",
191
+ "MACOS_EXCLUDED_PREFIXES",
192
+ "NodeType",
193
+ "Optional",
194
+ "Path",
195
+ "SENSITIVE_PATH_KEYWORDS",
196
+ "Tuple",
197
+ "VERB_EDGE_WEIGHT",
198
+ "WINDOWS_EXCLUDED_NAMES",
199
+ "_CHUNK_STRATEGIES",
200
+ "_CODE_BLANK_RUN_RE",
201
+ "_CODE_BOUNDARY_LINE_RE",
202
+ "_CODE_CHUNK_EXTENSIONS",
203
+ "_CONCEPT_STOP",
204
+ "_KG_DB_FORMAT_KEY",
205
+ "_KG_DB_FORMAT_VERSION",
206
+ "_LLM_EXTRACT_CONCEPT_PROMPT",
207
+ "_LLM_EXTRACT_TRIPLE_PROMPT",
208
+ "_MARKDOWN_CHUNK_EXTENSIONS",
209
+ "_MARKDOWN_HEADING_RE",
210
+ "_MARKDOWN_MIN_SECTION_CHARS",
211
+ "_NOT_PERSON_WORDS",
212
+ "_PROJECTION_VERSION",
213
+ "_PROSE_CHUNK_EXTENSIONS",
214
+ "_PROSE_MIN_SPAN_RATIO",
215
+ "_PROSE_STRONG_BOUNDARY_RE",
216
+ "_PROSE_WEAK_BOUNDARY_RE",
217
+ "_READ_FROM_V2_DEFAULT",
218
+ "_V2_WRITE_MASTER_KEY",
219
+ "_chunks",
220
+ "_classify_node_type",
221
+ "_clean_text",
222
+ "_code_chunks",
223
+ "_code_segment_spans",
224
+ "_current_os_type",
225
+ "_drive_id_for_path",
226
+ "_excluded_directory_reason",
227
+ "_exec_script",
228
+ "_extract_concepts",
229
+ "_extract_concepts_rules",
230
+ "_extract_triples",
231
+ "_extract_triples_rules",
232
+ "_file_category",
233
+ "_infer_edge",
234
+ "_is_hidden_path",
235
+ "_is_relative_to",
236
+ "_json",
237
+ "_last_boundary",
238
+ "_llm_extract_concepts",
239
+ "_llm_extract_triples",
240
+ "_markdown_chunks",
241
+ "_markdown_section_spans",
242
+ "_merge_small_sections",
243
+ "_node_type_for_category",
244
+ "_now",
245
+ "_parse_iso",
246
+ "_parser_type_for_category",
247
+ "_path_fingerprint",
248
+ "_path_parts_lower",
249
+ "_plain_windows",
250
+ "_prose_chunks",
251
+ "_recency_score",
252
+ "_root_warning",
253
+ "_safe_iso_from_stat_mtime",
254
+ "_safe_loads",
255
+ "_sample_file",
256
+ "_semantic_items",
257
+ "_sensitive_file_reason",
258
+ "_sha256_bytes",
259
+ "_sha256_text",
260
+ "_size_limit_for_category",
261
+ "_slug",
262
+ "_topic_candidates",
263
+ "asyncio",
264
+ "chunk_strategy_for",
265
+ "citation_locator",
266
+ "contextmanager",
267
+ "datetime",
268
+ "get_llm_router",
269
+ "hashlib",
270
+ "infer_edge_relation",
271
+ "json",
272
+ "logging",
273
+ "math",
274
+ "os",
275
+ "page_for_offset",
276
+ "pdf_page_offsets",
277
+ "platform",
278
+ "quiet",
279
+ "re",
280
+ "set_llm_router",
281
+ "shutil",
282
+ "sqlite3",
283
+ "time",
284
+ "typed_chunk_meta_fields",
285
+ "typed_chunks",
286
+ "zipfile",
287
+ ]