ltcai 11.5.1 → 11.6.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 (473) hide show
  1. package/README.md +92 -117
  2. package/bin/ltcai.js +234 -24
  3. package/docs/CHANGELOG.md +129 -0
  4. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  5. package/docs/DEVELOPMENT.md +8 -6
  6. package/docs/ENTERPRISE.md +2 -1
  7. package/docs/HYBRID_CLOUD_KG_STREAMING.md +8 -4
  8. package/docs/MULTI_AGENT_RUNTIME.md +12 -5
  9. package/docs/ONBOARDING.md +1 -1
  10. package/docs/OPERATIONS.md +6 -3
  11. package/docs/REALTIME_COLLABORATION.md +1 -1
  12. package/docs/TRUST_MODEL.md +1 -1
  13. package/docs/WHY_LATTICE.md +1 -1
  14. package/docs/WORKFLOW_DESIGNER.md +3 -2
  15. package/docs/architecture.md +4 -4
  16. package/docs/kg-schema.md +1 -1
  17. package/docs/v11.5.2_TIGHT_SHIP_PLAN.md +144 -0
  18. package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
  19. package/lattice_brain/__init__.py +42 -79
  20. package/lattice_brain/graph/__init__.py +9 -24
  21. package/lattice_brain/graph/_kg_common/__init__.py +13 -24
  22. package/lattice_brain/ingestion/__init__.py +19 -58
  23. package/lattice_brain/ingestion/pipeline.py +20 -398
  24. package/lattice_brain/multimodal/__init__.py +7 -18
  25. package/lattice_brain/multimodal/images.py +6 -264
  26. package/lattice_brain/multimodal/video.py +8 -247
  27. package/lattice_brain/runtime/__init__.py +8 -79
  28. package/lattice_brain/runtime/hooks.py +22 -597
  29. package/latticeai/__init__.py +1 -1
  30. package/latticeai/api/agent_worker_seam.py +7 -80
  31. package/latticeai/api/health.py +26 -20
  32. package/latticeai/api/local_files.py +25 -608
  33. package/latticeai/api/models.py +12 -87
  34. package/latticeai/api/search.py +17 -231
  35. package/latticeai/api/tools.py +69 -750
  36. package/latticeai/api/voice_capture.py +8 -70
  37. package/latticeai/api/worker_compute.py +842 -0
  38. package/latticeai/api/worker_seams.py +216 -0
  39. package/latticeai/app_factory.py +23 -232
  40. package/latticeai/cli/entrypoint.py +36 -249
  41. package/latticeai/cli/runtime.py +7 -3
  42. package/latticeai/core/agent_permission.py +16 -91
  43. package/latticeai/core/config.py +47 -3
  44. package/latticeai/core/csrf.py +28 -2
  45. package/latticeai/core/embedding_providers/__init__.py +3 -5
  46. package/latticeai/core/embedding_providers/base.py +1 -1
  47. package/latticeai/core/embedding_providers/text.py +1 -1
  48. package/latticeai/core/http_origin.py +146 -0
  49. package/latticeai/core/io_utils.py +2 -11
  50. package/latticeai/core/messages.py +94 -531
  51. package/latticeai/core/model_compat.py +2 -8
  52. package/latticeai/core/module_probe.py +37 -0
  53. package/latticeai/core/security.py +13 -0
  54. package/latticeai/core/sessions.py +3 -2
  55. package/latticeai/core/sse.py +25 -0
  56. package/latticeai/core/users.py +0 -9
  57. package/latticeai/models/router/documents.py +0 -35
  58. package/latticeai/models/router/registry.py +0 -4
  59. package/latticeai/runtime/access_runtime.py +16 -18
  60. package/latticeai/runtime/bootstrap.py +10 -21
  61. package/latticeai/runtime/brain_runtime.py +35 -43
  62. package/latticeai/runtime/build_phases/__init__.py +21 -37
  63. package/latticeai/runtime/build_phases/features.py +101 -389
  64. package/latticeai/runtime/build_phases/foundation.py +82 -392
  65. package/latticeai/runtime/build_phases/web.py +91 -406
  66. package/latticeai/runtime/build_phases/worker_profile.py +244 -0
  67. package/latticeai/runtime/lifespan_runtime.py +7 -16
  68. package/latticeai/runtime/platform_services_runtime.py +1 -15
  69. package/latticeai/runtime/runtime_context.py +14 -143
  70. package/latticeai/runtime/security_runtime.py +10 -103
  71. package/latticeai/services/architecture_readiness.py +82 -43
  72. package/latticeai/services/model_capability_registry.py +0 -15
  73. package/latticeai/services/model_catalog.py +0 -7
  74. package/latticeai/services/model_loading.py +3 -2
  75. package/latticeai/services/model_runtime/__init__.py +2 -68
  76. package/latticeai/services/model_runtime/engines.py +27 -128
  77. package/latticeai/services/model_runtime/loading.py +2 -2
  78. package/latticeai/services/model_runtime/service.py +4 -28
  79. package/latticeai/services/p_reinforce.py +10 -261
  80. package/latticeai/services/product_readiness.py +31 -38
  81. package/latticeai/services/search_service.py +37 -795
  82. package/latticeai/services/tool_dispatch.py +30 -390
  83. package/latticeai/services/voice_capture.py +13 -107
  84. package/latticeai/tools/__init__.py +22 -49
  85. package/latticeai/tools/commands.py +0 -163
  86. package/latticeai/tools/computer.py +0 -39
  87. package/latticeai/tools/documents.py +1 -134
  88. package/latticeai/tools/filesystem.py +1 -247
  89. package/latticeai/tools/knowledge.py +1 -52
  90. package/latticeai/tools/local_files.py +0 -20
  91. package/latticeai/worker_app.py +75 -0
  92. package/package.json +3 -6
  93. package/requirements.txt +0 -5
  94. package/scripts/agent_eval.py +16 -28
  95. package/scripts/brain_quality_eval.py +20 -183
  96. package/scripts/bump_version.py +19 -6
  97. package/scripts/check_current_release_docs.mjs +7 -4
  98. package/scripts/check_legacy_debt.mjs +1 -1
  99. package/scripts/check_openapi_drift.mjs +10 -0
  100. package/scripts/check_server_i18n.mjs +2 -18
  101. package/scripts/compose_openapi.py +377 -0
  102. package/scripts/export_openapi.py +32 -4
  103. package/scripts/gen_messages_catalog_fixture.py +302 -0
  104. package/scripts/gen_openapi_fragments.py +365 -0
  105. package/scripts/gen_redact_fixture.py +196 -0
  106. package/scripts/gen_worker_allowlist_fixture.py +115 -0
  107. package/scripts/generate_agent_parity_fixtures.py +33 -14
  108. package/scripts/openapi_route_families.json +2161 -0
  109. package/scripts/release_screen_claims.json +31 -0
  110. package/scripts/run_integration_tests.mjs +134 -29
  111. package/scripts/run_sidecar_e2e.mjs +104 -11
  112. package/scripts/wheel_smoke.py +32 -22
  113. package/src-tauri/Cargo.lock +375 -9
  114. package/src-tauri/Cargo.toml +1 -1
  115. package/src-tauri/src/backend.rs +223 -43
  116. package/src-tauri/src/main.rs +27 -17
  117. package/src-tauri/src/topology.rs +58 -88
  118. package/src-tauri/tauri.conf.json +2 -3
  119. package/static/app/asset-manifest.json +41 -41
  120. package/static/app/assets/{Act-Drs_jd-O.js → Act-CToZnOHz.js} +1 -1
  121. package/static/app/assets/{AdminConsole-BqNx5oF6.js → AdminConsole-D5kbrBu8.js} +1 -1
  122. package/static/app/assets/{Brain-C7bdNmz-.js → Brain-C6zCdv4S.js} +1 -1
  123. package/static/app/assets/{BrainHome-DcTnINcI.js → BrainHome-D4n3EDUt.js} +1 -1
  124. package/static/app/assets/{BrainSignals-Df1MRIPD.js → BrainSignals-CzeZ-vQ9.js} +1 -1
  125. package/static/app/assets/{Capture-Dgsxvnbx.js → Capture-DPcyTczq.js} +1 -1
  126. package/static/app/assets/{Chronicle-BrkTxJK1.js → Chronicle-D3Nx-oWS.js} +1 -1
  127. package/static/app/assets/{CommandPalette-DDziw7Oj.js → CommandPalette-DPPvpp28.js} +1 -1
  128. package/static/app/assets/{Library-CYxeuraA.js → Library-Co2qTu3I.js} +1 -1
  129. package/static/app/assets/{LivingBrain-CNp6mvCm.js → LivingBrain-Bsmzwy8_.js} +1 -1
  130. package/static/app/assets/{ProductFlow-BVsowu3Z.js → ProductFlow-CBLdmesT.js} +1 -1
  131. package/static/app/assets/{ReviewCard-D1LbOfJS.js → ReviewCard-CfR6DLs7.js} +1 -1
  132. package/static/app/assets/{System-DcRAq7wj.js → System-Ce-P2YL6.js} +1 -1
  133. package/static/app/assets/arrow-left-DD5jFGHV.js +1 -0
  134. package/static/app/assets/{bot-BK2xQ9mN.js → bot-C5-XIww2.js} +1 -1
  135. package/static/app/assets/{brain-BZNztFBb.js → brain-CFRJUvdX.js} +1 -1
  136. package/static/app/assets/{button-CjueubVZ.js → button-DI1KcQP-.js} +1 -1
  137. package/static/app/assets/circle-check-CY20XMCh.js +1 -0
  138. package/static/app/assets/{circle-pause-HRjSmpyY.js → circle-pause-C8HHyood.js} +1 -1
  139. package/static/app/assets/{circle-play-CMcKDVwu.js → circle-play-Cufc235E.js} +1 -1
  140. package/static/app/assets/{cpu-B_MyTfYr.js → cpu-DW2_JVsv.js} +1 -1
  141. package/static/app/assets/{download-CTy0EByV.js → download-gbdKTBb8.js} +1 -1
  142. package/static/app/assets/{folder-open-DF6bLhTg.js → folder-open-C9ydyX33.js} +1 -1
  143. package/static/app/assets/{hard-drive-CpWHG77C.js → hard-drive-BxNMzBM3.js} +1 -1
  144. package/static/app/assets/index-BovSWRmQ.css +2 -0
  145. package/static/app/assets/{index-Dd6abJHX.js → index-q9XyDY7A.js} +3 -3
  146. package/static/app/assets/{input-bVgIRN3s.js → input-GLD94Y_K.js} +1 -1
  147. package/static/app/assets/{link-2-bg6CG5Vk.js → link-2-B4Y0gz1S.js} +1 -1
  148. package/static/app/assets/{permissionCopy-DFTf1HDZ.js → permissionCopy-CxrV0fvU.js} +1 -1
  149. package/static/app/assets/{primitives-D7D-sQ3T.js → primitives-2ANdAsu2.js} +1 -1
  150. package/static/app/assets/search-DTxtjQ07.js +1 -0
  151. package/static/app/assets/{share-2-BLzo7U4L.js → share-2-DxArfiuI.js} +1 -1
  152. package/static/app/assets/{shield-alert-BmngqnsJ.js → shield-alert-CgftuFFs.js} +1 -1
  153. package/static/app/assets/{textarea-DOSlAQQ3.js → textarea-BHVBAoCr.js} +1 -1
  154. package/static/app/assets/{useFocusTrap-pZhgeee4.js → useFocusTrap-Dzq2j_OG.js} +1 -1
  155. package/static/app/assets/{useMutation-BMDwNk4I.js → useMutation-BcqfMLNq.js} +1 -1
  156. package/static/app/assets/{useQuery-CSjKttRo.js → useQuery-DBzLKCOv.js} +1 -1
  157. package/static/app/assets/{utils-D3u_yv7B.js → utils-B-Aah1bO.js} +1 -1
  158. package/static/app/assets/{workspace-H3bMjYXC.js → workspace-B6fFhoko.js} +1 -1
  159. package/static/app/index.html +4 -4
  160. package/static/sw.js +1 -1
  161. package/desktop/electron/README.md +0 -9
  162. package/desktop/electron/main.cjs +0 -58
  163. package/desktop/electron/preload.cjs +0 -5
  164. package/lattice_brain/archive.py +0 -522
  165. package/lattice_brain/context.py +0 -325
  166. package/lattice_brain/conversations.py +0 -382
  167. package/lattice_brain/core.py +0 -82
  168. package/lattice_brain/graph/_kg_contract.py +0 -249
  169. package/lattice_brain/graph/curator.py +0 -676
  170. package/lattice_brain/graph/discovery.py +0 -595
  171. package/lattice_brain/graph/discovery_index/__init__.py +0 -35
  172. package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
  173. package/lattice_brain/graph/discovery_index/extract.py +0 -137
  174. package/lattice_brain/graph/discovery_index/scan.py +0 -411
  175. package/lattice_brain/graph/discovery_index/upsert.py +0 -495
  176. package/lattice_brain/graph/documents.py +0 -380
  177. package/lattice_brain/graph/fusion.py +0 -395
  178. package/lattice_brain/graph/identity.py +0 -175
  179. package/lattice_brain/graph/image_vectors.py +0 -230
  180. package/lattice_brain/graph/ingest.py +0 -829
  181. package/lattice_brain/graph/network.py +0 -205
  182. package/lattice_brain/graph/proactive.py +0 -724
  183. package/lattice_brain/graph/projection/__init__.py +0 -42
  184. package/lattice_brain/graph/projection/curation.py +0 -500
  185. package/lattice_brain/graph/projection/v2_schema.py +0 -546
  186. package/lattice_brain/graph/provenance.py +0 -524
  187. package/lattice_brain/graph/rerank.py +0 -163
  188. package/lattice_brain/graph/retrieval/__init__.py +0 -54
  189. package/lattice_brain/graph/retrieval/context.py +0 -197
  190. package/lattice_brain/graph/retrieval/graph_view.py +0 -319
  191. package/lattice_brain/graph/retrieval/hybrid.py +0 -488
  192. package/lattice_brain/graph/retrieval/maintenance.py +0 -121
  193. package/lattice_brain/graph/retrieval/signals.py +0 -95
  194. package/lattice_brain/graph/retrieval_docgen.py +0 -253
  195. package/lattice_brain/graph/retrieval_policy.py +0 -180
  196. package/lattice_brain/graph/retrieval_reads.py +0 -769
  197. package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
  198. package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
  199. package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
  200. package/lattice_brain/graph/retrieval_vector/search.py +0 -560
  201. package/lattice_brain/graph/retrieval_vector/status.py +0 -374
  202. package/lattice_brain/graph/schema.py +0 -792
  203. package/lattice_brain/graph/store.py +0 -268
  204. package/lattice_brain/graph/vector_index/__init__.py +0 -85
  205. package/lattice_brain/graph/vector_index/base.py +0 -170
  206. package/lattice_brain/graph/vector_index/brute_force.py +0 -114
  207. package/lattice_brain/graph/vector_index/hnsw.py +0 -293
  208. package/lattice_brain/graph/vector_index/jobs.py +0 -287
  209. package/lattice_brain/graph/vector_index/quantized.py +0 -151
  210. package/lattice_brain/graph/vector_index/selector.py +0 -161
  211. package/lattice_brain/graph/write_master.py +0 -308
  212. package/lattice_brain/ingestion/_contract.py +0 -90
  213. package/lattice_brain/ingestion/folder_scan.py +0 -57
  214. package/lattice_brain/ingestion/folders.py +0 -258
  215. package/lattice_brain/ingestion/jobs_api.py +0 -107
  216. package/lattice_brain/ingestion/routing.py +0 -295
  217. package/lattice_brain/ingestion_jobs.py +0 -383
  218. package/lattice_brain/memory.py +0 -102
  219. package/lattice_brain/portability/__init__.py +0 -90
  220. package/lattice_brain/portability/_contract.py +0 -42
  221. package/lattice_brain/portability/backups.py +0 -338
  222. package/lattice_brain/portability/bundles.py +0 -136
  223. package/lattice_brain/portability/constants.py +0 -93
  224. package/lattice_brain/portability/fsops.py +0 -138
  225. package/lattice_brain/portability/service.py +0 -41
  226. package/lattice_brain/portability/sharing.py +0 -714
  227. package/lattice_brain/quality.py +0 -592
  228. package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
  229. package/lattice_brain/runtime/agent_runtime.py +0 -859
  230. package/lattice_brain/runtime/contracts.py +0 -460
  231. package/lattice_brain/runtime/multi_agent.py +0 -942
  232. package/lattice_brain/runtime/statuses.py +0 -10
  233. package/lattice_brain/sealed_box.py +0 -244
  234. package/lattice_brain/self_model.py +0 -675
  235. package/lattice_brain/sensitivity.py +0 -94
  236. package/lattice_brain/storage/__init__.py +0 -22
  237. package/lattice_brain/storage/base.py +0 -100
  238. package/lattice_brain/storage/docker.py +0 -105
  239. package/lattice_brain/storage/factory.py +0 -31
  240. package/lattice_brain/storage/migration.py +0 -191
  241. package/lattice_brain/storage/postgres.py +0 -123
  242. package/lattice_brain/storage/sqlite.py +0 -143
  243. package/lattice_brain/synthesis.py +0 -824
  244. package/lattice_brain/workflow.py +0 -497
  245. package/latticeai/api/admin.py +0 -471
  246. package/latticeai/api/agent_registry.py +0 -105
  247. package/latticeai/api/agents.py +0 -228
  248. package/latticeai/api/auth.py +0 -360
  249. package/latticeai/api/automation_intelligence.py +0 -401
  250. package/latticeai/api/brain_intelligence.py +0 -199
  251. package/latticeai/api/browser.py +0 -493
  252. package/latticeai/api/change_proposals.py +0 -89
  253. package/latticeai/api/chat.py +0 -572
  254. package/latticeai/api/chat_agent_http.py +0 -901
  255. package/latticeai/api/chat_contracts.py +0 -73
  256. package/latticeai/api/chat_documents.py +0 -276
  257. package/latticeai/api/chat_helpers.py +0 -463
  258. package/latticeai/api/chat_history.py +0 -101
  259. package/latticeai/api/chat_hybrid.py +0 -113
  260. package/latticeai/api/chat_intents.py +0 -646
  261. package/latticeai/api/chat_stream.py +0 -216
  262. package/latticeai/api/chronicle.py +0 -63
  263. package/latticeai/api/command_center.py +0 -51
  264. package/latticeai/api/computer_use.py +0 -485
  265. package/latticeai/api/evidence_actions.py +0 -48
  266. package/latticeai/api/features.py +0 -70
  267. package/latticeai/api/funnel_metrics.py +0 -31
  268. package/latticeai/api/garden.py +0 -34
  269. package/latticeai/api/hooks.py +0 -165
  270. package/latticeai/api/index_jobs.py +0 -145
  271. package/latticeai/api/invitations.py +0 -100
  272. package/latticeai/api/knowledge_graph.py +0 -536
  273. package/latticeai/api/marketplace.py +0 -105
  274. package/latticeai/api/mcp.py +0 -482
  275. package/latticeai/api/memory.py +0 -270
  276. package/latticeai/api/network.py +0 -81
  277. package/latticeai/api/network_boundary.py +0 -225
  278. package/latticeai/api/permission_mode.py +0 -61
  279. package/latticeai/api/permissions.py +0 -410
  280. package/latticeai/api/plugins.py +0 -126
  281. package/latticeai/api/portability.py +0 -391
  282. package/latticeai/api/project_sessions.py +0 -114
  283. package/latticeai/api/realtime.py +0 -118
  284. package/latticeai/api/review_queue.py +0 -364
  285. package/latticeai/api/security_dashboard.py +0 -604
  286. package/latticeai/api/setup.py +0 -319
  287. package/latticeai/api/static_routes.py +0 -351
  288. package/latticeai/api/ui_redirects.py +0 -26
  289. package/latticeai/api/workflow_designer.py +0 -394
  290. package/latticeai/api/workspace.py +0 -856
  291. package/latticeai/api/workspace_scope.py +0 -125
  292. package/latticeai/core/agent/__init__.py +0 -93
  293. package/latticeai/core/agent/_contract.py +0 -79
  294. package/latticeai/core/agent/context.py +0 -57
  295. package/latticeai/core/agent/deps.py +0 -125
  296. package/latticeai/core/agent/execution.py +0 -622
  297. package/latticeai/core/agent/planning.py +0 -145
  298. package/latticeai/core/agent/recovery.py +0 -157
  299. package/latticeai/core/agent/runtime.py +0 -210
  300. package/latticeai/core/agent/verification.py +0 -231
  301. package/latticeai/core/agent_eval.py +0 -739
  302. package/latticeai/core/agent_helpers.py +0 -493
  303. package/latticeai/core/agent_profiles.py +0 -110
  304. package/latticeai/core/agent_prompts.py +0 -171
  305. package/latticeai/core/agent_registry.py +0 -232
  306. package/latticeai/core/agent_state.py +0 -41
  307. package/latticeai/core/agent_trace.py +0 -104
  308. package/latticeai/core/artifact_ledger.py +0 -109
  309. package/latticeai/core/audit.py +0 -260
  310. package/latticeai/core/builtin_hooks.py +0 -105
  311. package/latticeai/core/context_builder.py +0 -394
  312. package/latticeai/core/document_generator.py +0 -103
  313. package/latticeai/core/enterprise.py +0 -157
  314. package/latticeai/core/enterprise_admin.py +0 -158
  315. package/latticeai/core/file_generation/__init__.py +0 -115
  316. package/latticeai/core/file_generation/bundles.py +0 -76
  317. package/latticeai/core/file_generation/extraction.py +0 -154
  318. package/latticeai/core/file_generation/inference.py +0 -235
  319. package/latticeai/core/file_generation/orchestration.py +0 -152
  320. package/latticeai/core/file_generation/prompting.py +0 -117
  321. package/latticeai/core/file_generation/repair.py +0 -114
  322. package/latticeai/core/file_generation/sanitize.py +0 -61
  323. package/latticeai/core/file_generation/validation.py +0 -201
  324. package/latticeai/core/graph_curator.py +0 -11
  325. package/latticeai/core/hooks.py +0 -11
  326. package/latticeai/core/invitations.py +0 -131
  327. package/latticeai/core/legacy_compatibility.py +0 -243
  328. package/latticeai/core/local_embeddings.py +0 -104
  329. package/latticeai/core/logging_safety.py +0 -46
  330. package/latticeai/core/marketplace.py +0 -293
  331. package/latticeai/core/mcp_catalog.py +0 -452
  332. package/latticeai/core/mcp_registry.py +0 -506
  333. package/latticeai/core/multi_agent.py +0 -11
  334. package/latticeai/core/network_boundary.py +0 -168
  335. package/latticeai/core/oidc.py +0 -208
  336. package/latticeai/core/plugins.py +0 -432
  337. package/latticeai/core/product_hardening.py +0 -218
  338. package/latticeai/core/project_sessions.py +0 -337
  339. package/latticeai/core/realtime.py +0 -238
  340. package/latticeai/core/run_explain.py +0 -423
  341. package/latticeai/core/run_store.py +0 -252
  342. package/latticeai/core/timezones.py +0 -80
  343. package/latticeai/core/workflow_engine.py +0 -11
  344. package/latticeai/core/workspace_computer_memory.py +0 -84
  345. package/latticeai/core/workspace_graph_trace.py +0 -161
  346. package/latticeai/core/workspace_indexing.py +0 -102
  347. package/latticeai/core/workspace_memory.py +0 -77
  348. package/latticeai/core/workspace_onboarding.py +0 -104
  349. package/latticeai/core/workspace_os.py +0 -988
  350. package/latticeai/core/workspace_os_constants.py +0 -126
  351. package/latticeai/core/workspace_os_state.py +0 -180
  352. package/latticeai/core/workspace_os_utils.py +0 -69
  353. package/latticeai/core/workspace_permissions.py +0 -101
  354. package/latticeai/core/workspace_plugins.py +0 -97
  355. package/latticeai/core/workspace_relationships.py +0 -99
  356. package/latticeai/core/workspace_reorganization.py +0 -335
  357. package/latticeai/core/workspace_review_items.py +0 -118
  358. package/latticeai/core/workspace_runs.py +0 -732
  359. package/latticeai/core/workspace_skills.py +0 -114
  360. package/latticeai/core/workspace_snapshots.py +0 -198
  361. package/latticeai/core/workspace_timeline.py +0 -110
  362. package/latticeai/integrations/__init__.py +0 -0
  363. package/latticeai/integrations/telegram_bot/__init__.py +0 -123
  364. package/latticeai/integrations/telegram_bot/__main__.py +0 -17
  365. package/latticeai/integrations/telegram_bot/config.py +0 -86
  366. package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
  367. package/latticeai/integrations/telegram_bot/flows.py +0 -478
  368. package/latticeai/integrations/telegram_bot/helpers.py +0 -322
  369. package/latticeai/integrations/telegram_bot/screens.py +0 -394
  370. package/latticeai/runtime/audit_runtime.py +0 -76
  371. package/latticeai/runtime/automation_runtime.py +0 -81
  372. package/latticeai/runtime/chat_wiring.py +0 -141
  373. package/latticeai/runtime/context_runtime.py +0 -66
  374. package/latticeai/runtime/feature_toggle_wiring.py +0 -163
  375. package/latticeai/runtime/history_runtime.py +0 -163
  376. package/latticeai/runtime/history_writer.py +0 -138
  377. package/latticeai/runtime/hooks_runtime.py +0 -77
  378. package/latticeai/runtime/model_wiring.py +0 -68
  379. package/latticeai/runtime/namespace_runtime.py +0 -163
  380. package/latticeai/runtime/network_boundary_wiring.py +0 -128
  381. package/latticeai/runtime/network_config_runtime.py +0 -56
  382. package/latticeai/runtime/permission_mode_wiring.py +0 -119
  383. package/latticeai/runtime/persistence_runtime.py +0 -159
  384. package/latticeai/runtime/platform_runtime_wiring.py +0 -89
  385. package/latticeai/runtime/review_wiring.py +0 -42
  386. package/latticeai/runtime/router_registration.py +0 -689
  387. package/latticeai/runtime/sso_config_runtime.py +0 -128
  388. package/latticeai/runtime/user_key_runtime.py +0 -106
  389. package/latticeai/runtime/web_runtime.py +0 -92
  390. package/latticeai/server_app.py +0 -51
  391. package/latticeai/services/app_context.py +0 -130
  392. package/latticeai/services/automation_execution.py +0 -266
  393. package/latticeai/services/automation_intelligence.py +0 -614
  394. package/latticeai/services/brain_automation.py +0 -191
  395. package/latticeai/services/brain_intelligence/__init__.py +0 -58
  396. package/latticeai/services/brain_intelligence/_contract.py +0 -71
  397. package/latticeai/services/brain_intelligence/consistency.py +0 -193
  398. package/latticeai/services/brain_intelligence/constants.py +0 -47
  399. package/latticeai/services/brain_intelligence/digest.py +0 -258
  400. package/latticeai/services/brain_intelligence/health.py +0 -331
  401. package/latticeai/services/brain_intelligence/proposals.py +0 -264
  402. package/latticeai/services/brain_intelligence/sampling.py +0 -84
  403. package/latticeai/services/brain_intelligence/service.py +0 -48
  404. package/latticeai/services/change_proposals.py +0 -505
  405. package/latticeai/services/chat_service.py +0 -243
  406. package/latticeai/services/chronicle.py +0 -557
  407. package/latticeai/services/cloud_egress_audit.py +0 -85
  408. package/latticeai/services/cloud_extraction.py +0 -129
  409. package/latticeai/services/cloud_streaming.py +0 -268
  410. package/latticeai/services/cloud_token_guard.py +0 -84
  411. package/latticeai/services/command_center.py +0 -548
  412. package/latticeai/services/evidence_actions.py +0 -255
  413. package/latticeai/services/feature_toggles.py +0 -502
  414. package/latticeai/services/folder_watch.py +0 -520
  415. package/latticeai/services/funnel_metrics.py +0 -307
  416. package/latticeai/services/hybrid_chat.py +0 -316
  417. package/latticeai/services/hybrid_context.py +0 -228
  418. package/latticeai/services/hybrid_policy.py +0 -178
  419. package/latticeai/services/ingestion.py +0 -11
  420. package/latticeai/services/interop_bridges.py +0 -978
  421. package/latticeai/services/kg_portability.py +0 -11
  422. package/latticeai/services/local_knowledge.py +0 -465
  423. package/latticeai/services/memory_service/__init__.py +0 -52
  424. package/latticeai/services/memory_service/_contract.py +0 -100
  425. package/latticeai/services/memory_service/brief.py +0 -431
  426. package/latticeai/services/memory_service/constants.py +0 -57
  427. package/latticeai/services/memory_service/maintenance.py +0 -138
  428. package/latticeai/services/memory_service/manager.py +0 -186
  429. package/latticeai/services/memory_service/proof.py +0 -136
  430. package/latticeai/services/memory_service/recall.py +0 -225
  431. package/latticeai/services/memory_service/service.py +0 -48
  432. package/latticeai/services/memory_service/stores.py +0 -110
  433. package/latticeai/services/model_recommendation.py +0 -224
  434. package/latticeai/services/model_runtime/cloud.py +0 -87
  435. package/latticeai/services/multimodal_streaming.py +0 -129
  436. package/latticeai/services/network_boundary_service.py +0 -154
  437. package/latticeai/services/obsidian_bridge.py +0 -609
  438. package/latticeai/services/openai_compatible_adapter.py +0 -101
  439. package/latticeai/services/permission_mode_service.py +0 -170
  440. package/latticeai/services/platform_runtime.py +0 -366
  441. package/latticeai/services/review_queue.py +0 -380
  442. package/latticeai/services/router_context.py +0 -59
  443. package/latticeai/services/run_executor.py +0 -387
  444. package/latticeai/services/self_model_service.py +0 -171
  445. package/latticeai/services/setup_detection.py +0 -81
  446. package/latticeai/services/triggers.py +0 -378
  447. package/latticeai/services/upload_service.py +0 -185
  448. package/latticeai/services/workspace_service.py +0 -171
  449. package/latticeai/setup/__init__.py +0 -25
  450. package/latticeai/setup/auto_setup.py +0 -857
  451. package/latticeai/setup/demo_corpus.py +0 -98
  452. package/latticeai/setup/wizard/__init__.py +0 -126
  453. package/latticeai/setup/wizard/catalog.py +0 -172
  454. package/latticeai/setup/wizard/detect.py +0 -323
  455. package/latticeai/setup/wizard/install.py +0 -348
  456. package/latticeai/setup/wizard/paths.py +0 -168
  457. package/latticeai/setup/wizard/plans.py +0 -74
  458. package/latticeai/setup/wizard/recommend.py +0 -320
  459. package/scripts/bench_agent_smoke.py +0 -409
  460. package/scripts/bench_models.py +0 -540
  461. package/scripts/bench_vector_index.py +0 -295
  462. package/scripts/funnel_soft_gate.py +0 -192
  463. package/scripts/generate_agent_loop_fixtures.py +0 -907
  464. package/scripts/generate_rust_parity_fixtures.py +0 -1000
  465. package/scripts/measure_brain_home_fill.mjs +0 -141
  466. package/scripts/migrate_brain_storage.py +0 -57
  467. package/scripts/parity_fixture_corpus_docgen.py +0 -341
  468. package/scripts/profile_kg.py +0 -355
  469. package/server.py +0 -30
  470. package/static/app/assets/arrow-left-BHYmOTWU.js +0 -1
  471. package/static/app/assets/circle-check-CLeWJr67.js +0 -1
  472. package/static/app/assets/index-DxmOfNRi.css +0 -2
  473. package/static/app/assets/search-BgSVX6NG.js +0 -1
package/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
  [![CI Status](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/ci.yml)
12
12
  [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
13
13
 
14
- ![v11.5.1 Living Brain walkthrough](output/release/v11.5.1/gifs/v11.5.1-living-brain-walkthrough.gif)
14
+ ![v11.6.0 Living Brain walkthrough](output/release/v11.6.0/gifs/v11.6.0-living-brain-walkthrough.gif)
15
15
 
16
16
  Chat, files, folders, notes, and web pages all flow into one durable knowledge
17
17
  graph on your computer. Any model — local MLX or cloud — can speak with that
@@ -24,10 +24,10 @@ memory. Nothing leaves your machine without explicit consent.
24
24
 
25
25
  | | |
26
26
  | --- | --- |
27
- | **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story, rewindable to any past moment ![Brain Chronicle](output/release/v11.5.1/screenshots/13-chronicle.png) | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory ![Brain Chat](output/release/v11.5.1/screenshots/04-brain-chat-home.png) |
28
- | **See how knowledge connects** — a real relationship graph, not a file list ![Memory Graph](output/release/v11.5.1/screenshots/05-memory-graph.png) | **Capture anything** — files, whole folders, notes, screenshots, web pages ![Capture](output/release/v11.5.1/screenshots/06-capture.png) |
29
- | **Automate with review** — agent changes become proposals you approve first ![Review Center](output/release/v11.5.1/screenshots/12-review-center.png) | **Pick a model in one click** — recommended local models for your hardware ![Recommended Models](output/release/v11.5.1/screenshots/02-recommended-models.png) |
30
- | **Watch a file become memory** — three named steps, not a pipeline diagram ![Material to memory](output/release/v11.5.1/screenshots/11-knowledge-journey.png) | **Say how much it may do alone** — one dial in plain words; dangerous actions stay blocked either way ![Settings](output/release/v11.5.1/screenshots/08-system.png) |
27
+ | **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story, rewindable to any past moment ![Brain Chronicle](output/release/v11.6.0/screenshots/13-chronicle.png) | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory ![Brain Chat](output/release/v11.6.0/screenshots/04-brain-chat-home.png) |
28
+ | **See how knowledge connects** — a real relationship graph, not a file list ![Memory Graph](output/release/v11.6.0/screenshots/05-memory-graph.png) | **Capture anything** — files, whole folders, notes, screenshots, web pages ![Capture](output/release/v11.6.0/screenshots/06-capture.png) |
29
+ | **Automate with review** — agent changes become proposals you approve first ![Review Center](output/release/v11.6.0/screenshots/12-review-center.png) | **Pick a model in one click** — recommended local models for your hardware ![Recommended Models](output/release/v11.6.0/screenshots/02-recommended-models.png) |
30
+ | **Watch a file become memory** — three named steps, not a pipeline diagram ![Material to memory](output/release/v11.6.0/screenshots/11-knowledge-journey.png) | **Say how much it may do alone** — one dial in plain words; dangerous actions stay blocked either way ![Settings](output/release/v11.6.0/screenshots/08-system.png) |
31
31
 
32
32
  ## Why Lattice AI
33
33
 
@@ -58,72 +58,81 @@ First-run flow — wake the Brain, pick the owner, load a recommended model:
58
58
 
59
59
  | | | |
60
60
  | --- | --- | --- |
61
- | ![Login](output/release/v11.5.1/screenshots/01-login.png) | ![Model install](output/release/v11.5.1/screenshots/03-install-load-progress.png) | ![Model library](output/release/v11.5.1/screenshots/07-model-library.png) |
61
+ | ![Login](output/release/v11.6.0/screenshots/01-login.png) | ![Model install](output/release/v11.6.0/screenshots/03-install-load-progress.png) | ![Model library](output/release/v11.6.0/screenshots/07-model-library.png) |
62
62
 
63
63
  Screenshot index and capture notes:
64
- [output/release/v11.5.1/SCREENSHOT_INDEX.md](output/release/v11.5.1/SCREENSHOT_INDEX.md)
64
+ [output/release/v11.6.0/SCREENSHOT_INDEX.md](output/release/v11.6.0/SCREENSHOT_INDEX.md)
65
65
 
66
66
  ## Current Release
67
67
 
68
- The current release is **11.5.1 — Rust Full Loop**:
69
-
70
- The two explicitly-remaining items are done: the agent loop orchestrator
71
- now runs in Rust — proven by replaying the real Python runtime on scripted
72
- LLM transcripts (**10 trajectories, byte-identical**) and by a live smoke
73
- against the real worker — and the document-generation context builder is
74
- native (53 new goldens, 247 total). Every Rust box in the target diagram
75
- is implemented; Python remains exactly the AI Worker that diagram draws:
76
- LLM inference, tool-handler execution, and all graph writes behind three
77
- new fully-covered worker seams with server-side circuit breakers intact.
78
-
79
- - **The desktop's front door is now the Rust gateway.** The Tauri shell
80
- boots the supervisor + gateway topology by default and the webview
81
- lives at the gateway origin. The one real blocker — a CSRF policy
82
- bound to the worker's own port — is dissolved by environment
83
- injection, proven live against the real Python worker (trusted
84
- origins 200, foreign origins 403). Three escape hatches preserve the
85
- previous topologies.
86
- - **The native surface grew fourfold.** `lattice-retrieval` now serves
87
- the three-channel service search, graph reads (search /
88
- relationships / traverse), the full history read family, and the
89
- chat context assembler — **191/191 exact-parity goldens, zero
90
- epsilon**. `lattice-ingest` carries the typed chunker (332 golden
91
- chunks, and a 26/26 mutation-test pass proving every constant
92
- load-bearing) plus the polling folder watcher; writes stay delegated
93
- to the worker, the single writer. `lattice-agent` carries the
94
- permission kernel — **2,452 exact decision-table verdicts** — and
95
- natively executes only validated read-only commands in a replaced
96
- environment. `lattice-jobs` closes a documented gap: the durable
97
- embed queue now has a scheduler (60s ticks, honest backoff,
98
- `/host/jobs` status) driving a new fully-covered drain endpoint.
99
- - **The honest boundary, stated.** The Python worker keeps the document
100
- parser matrix, embedding production, LLM inference, mutating tool
101
- execution, and all graph writes. The agent loop orchestration port
102
- remains for a future release, for reasons written down in the plan.
103
-
104
- All of it lands with the floor intact: **6,861 Python + 1,761 frontend
105
- tests at 100.00% statement and branch coverage — now 7,006 Python +
106
- 1,761 frontend — and 739 Rust workspace tests**, four bidirectional golden families, mypy/ruff/clippy clean,
107
- verified on macOS 3.14 and a fresh-resolve python 3.11 environment.
108
-
109
- Release notes: [RELEASE.md](RELEASE.md) · Full history: [docs/CHANGELOG.md](docs/CHANGELOG.md)
110
-
111
- Expected artifacts for 11.5.1 release must use exact filenames:
112
-
113
- - `dist/ltcai-11.5.1-py3-none-any.whl`
114
- - `dist/ltcai-11.5.1.tar.gz`
115
- - `ltcai-11.5.1.tgz`
116
- - `dist/ltcai-11.5.1.vsix`
117
- - `src-tauri/target/release/bundle/dmg/Lattice AI_11.5.1_aarch64.dmg`
68
+ The current release is **11.6.0 — One Door**:
69
+
70
+ The product now has one front door, and it is Rust. `lattice-host` serves
71
+ **420 operations across 41 route families** at the paths they always had,
72
+ and the Python package is no longer a web application at all — it is a
73
+ pure-compute **AI worker** with **28 routes**: LLM inference and streaming,
74
+ embedding, extraction, parsing, four document renderers, speech-to-text,
75
+ multimodal description, the model and engine catalog, `sysinfo`, and
76
+ `/health`. Nine crates hold the product; the door forwards exactly the 28
77
+ and answers `404 {"detail":"Not Found"}` for anything else, from a
78
+ committed allowlist that a drift gate regenerates and compares.
79
+
80
+ - **Every write is native.** The knowledge-graph write engine moved into
81
+ `lattice-core`: ingest, curation, provenance, taxonomy and the vector
82
+ queue. It is held to Python's bytes by a **32-step row-parity battery**
83
+ that dumps every table after every step with zero tolerated differences,
84
+ and by a schema comparison over all **67 objects** in `sqlite_master`
85
+ (indexes and FTS shadow tables included). Seventeen graph tables changed
86
+ owner from the worker to Rust, and the single-writer invariant is now a
87
+ test rather than a convention.
88
+ - **The surface is replayed, not re-described.** **1,487 recorded HTTP
89
+ cases** across twelve committed fixture files — captured from the real
90
+ Python app while it still served them — are replayed against the native
91
+ routes, status line and body compared. The retrieval, chunking, agent
92
+ kernel and agent-loop golden families are unchanged and still green.
93
+ - **298 Python files and 73,617 lines were deleted.** What remains is 127
94
+ files and about 20,900 lines, all of it compute, at **100.00% statement
95
+ and branch coverage** with `fail_under=100` and no new pragmas.
96
+ - **What the port found.** The Python oracle's own bugs are documented
97
+ rather than smoothed over: four graph-write divergences (a `kgv2_*` view
98
+ that updates `type` on conflict where `nodes` does not; two writers that
99
+ serialise without `sort_keys`; a hash computed from CPython's default
100
+ JSON separators), a documented redaction rule that never fired, and a
101
+ change-proposal kind whitelist that could never approve a folder
102
+ reorganization. Three known-wrong behaviours were ported **as they are**
103
+ so the surface does not change under users mid-release — they are listed
104
+ in [RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md).
105
+ - **What was removed, and why.** The **Telegram bridge** is gone: it lived
106
+ in the platform code that became the worker, and a bridge with no product
107
+ server to bridge to is not a feature. **SSO/OIDC login and callback
108
+ flows** are gone with it — the configuration surface remains, and
109
+ password login is native. Both are consequences of the worker boundary,
110
+ not decisions taken on their own merits.
111
+
112
+ Full disclosure of gaps, ported bugs and removed surfaces:
113
+ [RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md)
114
+
115
+ Expected artifacts for 11.6.0 release must use exact filenames:
116
+
117
+ - `dist/ltcai-11.6.0-py3-none-any.whl`
118
+ - `dist/ltcai-11.6.0.tar.gz`
119
+ - `ltcai-11.6.0.tgz`
120
+ - `dist/ltcai-11.6.0.vsix`
121
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_11.6.0_aarch64.dmg`
118
122
 
119
123
  Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
120
124
 
125
+ Release notes: [RELEASE.md](RELEASE.md) · Full history: [docs/CHANGELOG.md](docs/CHANGELOG.md)
126
+
121
127
  ## Architecture At A Glance
122
128
 
123
- FastAPI on localhost is the source of truth; the React/Vite frontend and the
124
- Tauri desktop shell sit on top; the independent `lattice_brain` package owns
125
- the graph, memory, ingestion, and portability. Local-first by default — cloud
126
- calls, downloads, Telegram, and update checks are opt-in.
129
+ One Rust server on localhost is the source of truth: `lattice-host` answers
130
+ every product route, owns every write to the Brain, and supervises a Python
131
+ **AI worker** it reaches over loopback for the things a model does — inference,
132
+ embedding, extraction, parsing, rendering, speech-to-text. The React/Vite
133
+ frontend and the Tauri desktop shell sit on top of that one door. Local-first
134
+ by default — cloud model calls, downloads, Brain Network, and update checks are
135
+ opt-in.
127
136
 
128
137
  See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
129
138
  [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the developer workflow
@@ -133,22 +142,37 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
133
142
  ## Known Limitations
134
143
 
135
144
  - External package registries are owner-published and can lag behind GitHub.
136
- - PostgreSQL/pgvector is optional scale/migration tooling. SQLite remains the
137
- live local Brain store in 10.3.0.
138
- - Docker, model downloads, cloud model calls, Telegram, Brain Network, and
139
- update checks require explicit user action.
145
+ - SQLite is the live local Brain store. The optional PostgreSQL/pgvector
146
+ migration tooling is not part of the 11.6.0 worker.
147
+ - Docker, model downloads, cloud model calls, Brain Network, and update checks
148
+ require explicit user action.
149
+ - **The Telegram bridge was removed in 11.6.0** — it lived in the platform code
150
+ that became the AI worker. **SSO/OIDC login and callback flows were removed
151
+ with it**; the configuration surface remains and password login is native.
140
152
  - Conversation does not fabricate answers when no model is loaded. Agent and
141
153
  workflow simulation without a loaded LLM is deterministic and LLM-free (it
142
154
  does not call a model) — labeled as such, never presented as autonomous
143
155
  model success.
144
- - Some backend-generated messages (for example the Postgres DSN notice) are
145
- produced server-side in English and are shown as-is; server-side i18n is not
146
- part of 10.3.0.
156
+ - `POST /worker/render/pdf` ships working out of the box: `reportlab` is a
157
+ required dependency as of 11.6.0 (it used to be an undeclared lazy import
158
+ that raised a 500; `ltcai[pdf]` remains as an empty alias for older
159
+ install instructions).
160
+ - Known gaps carried openly into this release — upload extraction enrichment is
161
+ UTF-8-text only, supplied vectors cover the primary ingest node, and the
162
+ pointer-control tools still execute in the worker — are listed with their
163
+ reasons in [RELEASE_NOTES_v11.6.0.md](RELEASE_NOTES_v11.6.0.md).
147
164
 
148
165
  ## Release History
149
166
 
167
+ Public history starts at 11.0.0. 11.6.0 rebuilt the product server in Rust and
168
+ reduced the Python package to an AI worker, so a 10.x or 9.x install is a
169
+ different program; `SECURITY.md` supports only 11.x, and this table states the
170
+ same boundary. Earlier notes stay in the tree as `RELEASE_NOTES_v*.md` files.
171
+
150
172
  | Version | Theme |
151
173
  | --- | --- |
174
+ | 11.6.0 | One Door |
175
+ | 11.5.2 | Tight Ship |
152
176
  | 11.5.1 | Rust Full Loop |
153
177
  | 11.5.0 | Rust Complete |
154
178
  | 11.4.0 | Rust Foundation |
@@ -157,54 +181,5 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
157
181
  | 11.1.0 | Product Intelligence |
158
182
  | 11.0.1 | Both Branches |
159
183
  | 11.0.0 | Full Measure |
160
- | 10.10.0 | Quiet Station |
161
- | 10.9.0 | Never Blocks |
162
- | 10.8.0 | Within Reach |
163
- | 10.7.0 | Plain Surface |
164
- | 10.6.4 | Loud Limits |
165
- | 10.6.3 | Loud Limits |
166
- | 10.6.2 | Ask First |
167
- | 10.6.1 | First Things |
168
- | 10.6.0 | Promoted Panels |
169
- | 10.5.0 | Everyday Words |
170
- | 10.4.0 | Named Ground |
171
- | 10.3.0 | Measured Ground |
172
- | 10.2.0 | Load-Bearing Fixes |
173
- | 10.1.1 | Reachable Boundary |
174
- | 10.1.0 | Hybrid Brain |
175
- | 10.0.1 | One Source of Truth |
176
- | 10.0.0 | Plain Language |
177
- | 9.9.9 | Lean Shell |
178
- | 9.9.8 | Autonomy Dial |
179
- | 9.9.7 | No Gaps Left |
180
- | 9.9.6 | Same Brain Everywhere |
181
- | 9.9.5 | Closed Gaps |
182
- | 9.9.4 | Durable Loops |
183
- | 9.9.3 | Closed Loops |
184
- | 9.9.2 | Artifact Trust |
185
- | 9.9.1 | Clean Foundations |
186
- | 9.9.0 | Fail-Closed Trust |
187
- | 9.8.0 | Honest Knowledge Pipeline |
188
- | 9.7.0 | Proactive Hybrid Brain |
189
- | 9.6.0 | Trusted Agent Loop |
190
- | 9.5.0 | Command Center |
191
- | 9.4.0 | Question-Driven Everyday Automation |
192
- | 9.3.0 | Proactive Brain Intelligence |
193
- | 9.2.0 | Model-Agnostic File Generation |
194
- | 9.1.0 | Code Review Completion & Fail-Closed Runtime |
195
- | 9.0.0 | Code Review Closure & Runtime Cleanup |
196
184
 
197
185
  Per-release details: [RELEASE_NOTES.md](RELEASE_NOTES.md)
198
-
199
- ## Documentation
200
-
201
- - [docs/WHY_LATTICE.md](docs/WHY_LATTICE.md) — product philosophy
202
- - [docs/TRUST_MODEL.md](docs/TRUST_MODEL.md) — local-first trust model
203
- - [PRIVACY.md](PRIVACY.md) — privacy and external communication policy
204
- - [FEATURE_STATUS.md](FEATURE_STATUS.md) — feature status and limitations
205
- - [SECURITY.md](SECURITY.md) — security posture
206
- - [RELEASE.md](RELEASE.md) — release guide and notes
207
-
208
- ## License
209
-
210
- MIT. See [LICENSE](LICENSE).
package/bin/ltcai.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { spawn } = require("node:child_process");
4
- const { spawnSync } = require("node:child_process");
3
+ const { spawn, spawnSync } = require("node:child_process");
5
4
  const fs = require("node:fs");
6
5
  const os = require("node:os");
7
6
  const path = require("node:path");
@@ -11,6 +10,34 @@ const managedVenv = process.env.LTCAI_NPM_VENV || path.join(os.homedir(), ".ltca
11
10
  const managedPython = process.platform === "win32"
12
11
  ? path.join(managedVenv, "Scripts", "python.exe")
13
12
  : path.join(managedVenv, "bin", "python");
13
+ const hostName = process.platform === "win32" ? "lattice-host.exe" : "lattice-host";
14
+ const WORKER_MODULE = "latticeai.worker_app";
15
+ // Mirrors rust/lattice-host/src/supervisor/command.rs::WORKER_FACTORY — the
16
+ // supervisor appends `--host`/`--port` itself, so this is the whole of what a
17
+ // launcher can name.
18
+ const WORKER_FACTORY = `-m uvicorn ${WORKER_MODULE}:create_worker_app --factory`;
19
+
20
+ const USAGE = `\
21
+ ltcai — Lattice AI front door (lattice-host)
22
+
23
+ USAGE:
24
+ ltcai [OPTIONS]
25
+ ltcai doctor
26
+
27
+ OPTIONS:
28
+ --host <HOST> Bind hint (sets LATTICEAI_HOST). lattice-host listens on 127.0.0.1
29
+ --port <PORT> Gateway port (default: LATTICEAI_PORT, then 4825)
30
+ --worker-port <PORT> Pin the worker port instead of scanning
31
+ --no-spawn Do not start a worker; front an existing one
32
+ --no-jobs Mount /host/jobs but never run the timer
33
+ -h, --help Print this help
34
+ -V, --version Print the version
35
+
36
+ lattice-host is the only front door. It supervises the Python AI worker
37
+ (\`python ${WORKER_FACTORY}\`, with the port it chose).
38
+ LATTICEAI_* environment variables are passed through. Pin the host binary with
39
+ LATTICEAI_HOST_BIN or LTCAI_HOST, and the worker interpreter with LTCAI_PYTHON.
40
+ `;
14
41
 
15
42
  function loadDotEnv(file) {
16
43
  if (!fs.existsSync(file)) return;
@@ -61,7 +88,7 @@ function ensureManagedPython() {
61
88
  if (!canImport(managedPython, "fastapi")) {
62
89
  const requirements = path.join(root, "requirements.txt");
63
90
  if (!fs.existsSync(requirements)) {
64
- console.error(`[LTCAI] Missing ${requirements}. The npm package is incomplete and cannot start the Python server.`);
91
+ console.error(`[LTCAI] Missing ${requirements}. The npm package is incomplete and cannot start the Python worker.`);
65
92
  process.exit(1);
66
93
  }
67
94
  console.log("[LTCAI] Installing Python dependencies. This can take a few minutes on first run.");
@@ -72,34 +99,217 @@ function ensureManagedPython() {
72
99
  return managedPython;
73
100
  }
74
101
 
75
- const bootstrappedPython = ensureManagedPython();
76
- const candidates = [
77
- process.env.LTCAI_PYTHON,
78
- bootstrappedPython,
79
- path.join(root, ".venv", "bin", "python"),
80
- path.join(root, "venv", "bin", "python"),
81
- process.env.PYTHON,
82
- "python3",
83
- "python",
84
- ].filter(Boolean);
85
-
86
- function run(index) {
87
- const python = candidates[index];
88
- if (!python) {
89
- console.error("Could not find Python. Install Python 3.11+ and try again.");
102
+ function pythonCandidates(includeManaged) {
103
+ return [
104
+ process.env.LTCAI_PYTHON,
105
+ includeManaged ? ensureManagedPython() : managedPython,
106
+ path.join(root, ".venv", "bin", "python"),
107
+ path.join(root, "venv", "bin", "python"),
108
+ process.platform === "win32" ? path.join(root, ".venv", "Scripts", "python.exe") : null,
109
+ process.env.PYTHON,
110
+ "python3",
111
+ "python",
112
+ ].filter(Boolean);
113
+ }
114
+
115
+ function resolveWorkerPython(bootstrap) {
116
+ for (const python of pythonCandidates(bootstrap)) {
117
+ if (canImport(python, WORKER_MODULE)) return python;
118
+ }
119
+ return pythonCandidates(bootstrap)[0] || "python3";
120
+ }
121
+
122
+ function whichHost() {
123
+ const tool = process.platform === "win32" ? "where" : "which";
124
+ const result = spawnSync(tool, ["lattice-host"], { encoding: "utf8" });
125
+ if (result.status !== 0) return null;
126
+ const found = String(result.stdout || "").split(/\r?\n/).map((line) => line.trim()).find(Boolean);
127
+ return found && fs.existsSync(found) ? found : null;
128
+ }
129
+
130
+ function existingHostBinary() {
131
+ const pinned = process.env.LATTICEAI_HOST_BIN || process.env.LTCAI_HOST;
132
+ if (pinned && fs.existsSync(pinned)) return pinned;
133
+ const candidates = [
134
+ path.join(root, "rust", "target", "release", hostName),
135
+ path.join(root, "rust", "target", "debug", hostName),
136
+ path.join(root, "src-tauri", "target", "release", hostName),
137
+ path.join(root, "src-tauri", "target", "debug", hostName),
138
+ ];
139
+ for (const candidate of candidates) {
140
+ if (fs.existsSync(candidate)) return candidate;
141
+ }
142
+ return whichHost();
143
+ }
144
+
145
+ function ensureHostBinary() {
146
+ const existing = existingHostBinary();
147
+ if (existing) return existing;
148
+ if (process.env.LTCAI_SKIP_HOST_BUILD === "1") {
149
+ console.error("[LTCAI] lattice-host binary not found and LTCAI_SKIP_HOST_BUILD=1.");
150
+ process.exit(1);
151
+ }
152
+ const manifest = path.join(root, "rust", "Cargo.toml");
153
+ if (!fs.existsSync(manifest)) {
154
+ console.error("[LTCAI] lattice-host binary not found and rust/ workspace is missing.");
155
+ process.exit(1);
156
+ }
157
+ console.log("[LTCAI] Building lattice-host (cargo build -p lattice-host)...");
158
+ if (!runSync("cargo", ["build", "-p", "lattice-host"], { cwd: path.join(root, "rust") })) {
159
+ console.error("[LTCAI] cargo build -p lattice-host failed.");
160
+ process.exit(1);
161
+ }
162
+ const built = path.join(root, "rust", "target", "debug", hostName);
163
+ if (!fs.existsSync(built)) {
164
+ console.error(`[LTCAI] build succeeded but ${built} is missing.`);
90
165
  process.exit(1);
91
166
  }
167
+ return built;
168
+ }
92
169
 
93
- const child = spawn(python, ["-m", "latticeai.cli.entrypoint", ...process.argv.slice(2)], {
94
- cwd: root,
95
- stdio: "inherit",
96
- });
170
+ function parseArgs(argv) {
171
+ const parsed = {
172
+ help: false,
173
+ version: false,
174
+ doctor: false,
175
+ host: null,
176
+ port: null,
177
+ hostArgs: [],
178
+ };
179
+ for (let i = 0; i < argv.length; i += 1) {
180
+ const arg = argv[i];
181
+ if (arg === "doctor") {
182
+ parsed.doctor = true;
183
+ continue;
184
+ }
185
+ if (arg === "-h" || arg === "--help") {
186
+ parsed.help = true;
187
+ continue;
188
+ }
189
+ if (arg === "-V" || arg === "--version") {
190
+ parsed.version = true;
191
+ continue;
192
+ }
193
+ if (arg === "--host" || arg.startsWith("--host=")) {
194
+ parsed.host = arg === "--host" ? argv[++i] : arg.slice("--host=".length);
195
+ continue;
196
+ }
197
+ if (arg === "--port" || arg.startsWith("--port=")) {
198
+ parsed.port = arg === "--port" ? argv[++i] : arg.slice("--port=".length);
199
+ if (parsed.port) parsed.hostArgs.push("--port", parsed.port);
200
+ continue;
201
+ }
202
+ if (arg === "--reload" || arg === "--tunnel") {
203
+ console.error(`[LTCAI] ${arg} is not supported on the lattice-host front door.`);
204
+ continue;
205
+ }
206
+ parsed.hostArgs.push(arg);
207
+ }
208
+ return parsed;
209
+ }
210
+
211
+ /**
212
+ * The interpreter, as an absolute path.
213
+ *
214
+ * `lattice-host` spawns the worker with `PATH` prefixed by
215
+ * `/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin`
216
+ * (supervisor/worker_env.rs — GUI processes inherit a minimal PATH), so a bare
217
+ * `python3` is looked up against a different PATH than the one this launcher
218
+ * validated it on and can land on an interpreter with none of the deps.
219
+ * `sys.executable` is what keeps it the same interpreter on both sides.
220
+ */
221
+ function absoluteInterpreter(python) {
222
+ const probe = spawnSync(python, ["-c", "import sys; print(sys.executable)"], { encoding: "utf8" });
223
+ const resolved = probe.status === 0 ? String(probe.stdout || "").trim() : "";
224
+ return resolved && fs.existsSync(resolved) ? resolved : python;
225
+ }
226
+
227
+ /**
228
+ * Tell the supervisor *which interpreter*, and let it build the command.
229
+ *
230
+ * This used to pin `LATTICEAI_DESKTOP_BACKEND_CMD = "<python> -m
231
+ * latticeai.worker_app"`, and that command serves nothing: `worker_app` exports
232
+ * `main()` but has no `if __name__ == "__main__"` guard, so the module form
233
+ * imports and exits 0 without binding a port — the supervisor restarts it,
234
+ * forever, and the front door answers 502 on every proxied route.
235
+ *
236
+ * The fix is not to pin the uvicorn string instead. `LATTICEAI_DESKTOP_BACKEND_CMD`
237
+ * is the supervisor's rule 1, whose args are passed **verbatim**; `--host` and
238
+ * `--port` are appended only by the module rules (`command.rs::module_args`),
239
+ * and the worker port is chosen at runtime by a free-port scan. A statically
240
+ * pinned `-m uvicorn … --factory` would therefore bind uvicorn's default 8000
241
+ * while the supervisor health-probes the port it actually picked.
242
+ *
243
+ * So pin the input the launcher genuinely knows — the interpreter — and let
244
+ * rule 2 produce its own canonical command (`command.rs::WORKER_FACTORY`):
245
+ * `<python> -m uvicorn latticeai.worker_app:create_worker_app --factory --host
246
+ * 127.0.0.1 --port <chosen>`. An explicit `LATTICEAI_DESKTOP_BACKEND_CMD` from
247
+ * the caller still wins, untouched.
248
+ */
249
+ function pinWorkerInterpreter() {
250
+ if (process.env.LATTICEAI_DESKTOP_BACKEND_CMD) return;
251
+ process.env.LTCAI_PYTHON = absoluteInterpreter(resolveWorkerPython(true));
252
+ }
253
+
254
+ function doctor() {
255
+ let ok = true;
256
+ const host = existingHostBinary();
257
+ if (host) {
258
+ console.log(`[OK] lattice-host: ${host}`);
259
+ } else {
260
+ console.log("[MISS] lattice-host: not built (run without doctor to cargo-build it)");
261
+ ok = false;
262
+ }
263
+ const python = absoluteInterpreter(resolveWorkerPython(false));
264
+ if (canImport(python, WORKER_MODULE)) {
265
+ console.log(`[OK] worker: ${python} ${WORKER_FACTORY}`);
266
+ } else {
267
+ console.log(`[MISS] worker: cannot import ${WORKER_MODULE} (${python})`);
268
+ ok = false;
269
+ }
270
+ process.exit(ok ? 0 : 1);
271
+ }
97
272
 
98
- child.on("error", () => run(index + 1));
273
+ function launchHost(bin, args) {
274
+ const child = spawn(bin, args, { cwd: root, stdio: "inherit" });
275
+ child.on("error", (err) => {
276
+ console.error(`[LTCAI] failed to launch lattice-host (${bin}): ${err.message}`);
277
+ process.exit(1);
278
+ });
99
279
  child.on("exit", (code, signal) => {
100
280
  if (signal) process.kill(process.pid, signal);
101
281
  process.exit(code ?? 0);
102
282
  });
103
283
  }
104
284
 
105
- run(0);
285
+ const parsed = parseArgs(process.argv.slice(2));
286
+
287
+ if (parsed.help) {
288
+ process.stdout.write(USAGE);
289
+ const host = existingHostBinary();
290
+ if (host) {
291
+ process.stdout.write("\n");
292
+ spawnSync(host, ["--help"], { stdio: "inherit" });
293
+ }
294
+ process.exit(0);
295
+ }
296
+
297
+ if (parsed.version) {
298
+ const host = existingHostBinary();
299
+ if (host) {
300
+ spawnSync(host, ["--version"], { stdio: "inherit" });
301
+ } else {
302
+ console.log("ltcai (lattice-host front door)");
303
+ }
304
+ process.exit(0);
305
+ }
306
+
307
+ if (parsed.doctor) {
308
+ doctor();
309
+ }
310
+
311
+ if (parsed.host) process.env.LATTICEAI_HOST = parsed.host;
312
+ if (parsed.port) process.env.LATTICEAI_PORT = parsed.port;
313
+
314
+ pinWorkerInterpreter();
315
+ launchHost(ensureHostBinary(), parsed.hostArgs);