ltcai 11.5.2 → 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 (439) hide show
  1. package/README.md +91 -148
  2. package/bin/ltcai.js +234 -24
  3. package/docs/CHANGELOG.md +75 -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/MULTI_AGENT_RUNTIME.md +12 -5
  8. package/docs/ONBOARDING.md +1 -1
  9. package/docs/OPERATIONS.md +6 -3
  10. package/docs/REALTIME_COLLABORATION.md +1 -1
  11. package/docs/TRUST_MODEL.md +1 -1
  12. package/docs/WHY_LATTICE.md +1 -1
  13. package/docs/WORKFLOW_DESIGNER.md +3 -2
  14. package/docs/kg-schema.md +1 -1
  15. package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
  16. package/lattice_brain/__init__.py +42 -79
  17. package/lattice_brain/graph/__init__.py +9 -24
  18. package/lattice_brain/graph/_kg_common/__init__.py +13 -24
  19. package/lattice_brain/ingestion/__init__.py +19 -58
  20. package/lattice_brain/ingestion/pipeline.py +20 -398
  21. package/lattice_brain/multimodal/__init__.py +7 -18
  22. package/lattice_brain/multimodal/images.py +6 -264
  23. package/lattice_brain/multimodal/video.py +8 -247
  24. package/lattice_brain/runtime/__init__.py +8 -79
  25. package/lattice_brain/runtime/hooks.py +22 -584
  26. package/latticeai/__init__.py +1 -1
  27. package/latticeai/api/agent_worker_seam.py +7 -80
  28. package/latticeai/api/health.py +6 -20
  29. package/latticeai/api/local_files.py +16 -613
  30. package/latticeai/api/models.py +12 -87
  31. package/latticeai/api/search.py +17 -255
  32. package/latticeai/api/tools.py +69 -750
  33. package/latticeai/api/voice_capture.py +8 -70
  34. package/latticeai/api/worker_compute.py +842 -0
  35. package/latticeai/api/worker_seams.py +216 -0
  36. package/latticeai/app_factory.py +23 -232
  37. package/latticeai/cli/entrypoint.py +36 -249
  38. package/latticeai/core/agent_permission.py +16 -91
  39. package/latticeai/core/messages.py +89 -531
  40. package/latticeai/runtime/access_runtime.py +0 -14
  41. package/latticeai/runtime/bootstrap.py +10 -21
  42. package/latticeai/runtime/brain_runtime.py +35 -43
  43. package/latticeai/runtime/build_phases/__init__.py +21 -37
  44. package/latticeai/runtime/build_phases/features.py +99 -389
  45. package/latticeai/runtime/build_phases/foundation.py +82 -392
  46. package/latticeai/runtime/build_phases/web.py +91 -408
  47. package/latticeai/runtime/build_phases/worker_profile.py +244 -0
  48. package/latticeai/runtime/lifespan_runtime.py +7 -16
  49. package/latticeai/runtime/platform_services_runtime.py +1 -15
  50. package/latticeai/runtime/runtime_context.py +13 -130
  51. package/latticeai/runtime/security_runtime.py +10 -103
  52. package/latticeai/services/architecture_readiness.py +82 -43
  53. package/latticeai/services/model_runtime/__init__.py +2 -11
  54. package/latticeai/services/model_runtime/service.py +4 -28
  55. package/latticeai/services/p_reinforce.py +10 -261
  56. package/latticeai/services/product_readiness.py +31 -38
  57. package/latticeai/services/search_service.py +37 -795
  58. package/latticeai/services/tool_dispatch.py +30 -386
  59. package/latticeai/services/voice_capture.py +13 -107
  60. package/latticeai/tools/__init__.py +22 -49
  61. package/latticeai/tools/commands.py +0 -163
  62. package/latticeai/tools/computer.py +0 -39
  63. package/latticeai/tools/documents.py +1 -134
  64. package/latticeai/tools/filesystem.py +1 -247
  65. package/latticeai/tools/knowledge.py +1 -52
  66. package/latticeai/tools/local_files.py +0 -20
  67. package/latticeai/worker_app.py +75 -0
  68. package/package.json +2 -3
  69. package/requirements.txt +0 -5
  70. package/scripts/agent_eval.py +16 -28
  71. package/scripts/brain_quality_eval.py +20 -183
  72. package/scripts/bump_version.py +5 -5
  73. package/scripts/check_current_release_docs.mjs +7 -4
  74. package/scripts/check_openapi_drift.mjs +10 -0
  75. package/scripts/check_server_i18n.mjs +2 -18
  76. package/scripts/compose_openapi.py +377 -0
  77. package/scripts/export_openapi.py +32 -4
  78. package/scripts/gen_messages_catalog_fixture.py +302 -0
  79. package/scripts/gen_openapi_fragments.py +365 -0
  80. package/scripts/gen_redact_fixture.py +196 -0
  81. package/scripts/gen_worker_allowlist_fixture.py +115 -0
  82. package/scripts/generate_agent_parity_fixtures.py +33 -14
  83. package/scripts/openapi_route_families.json +2161 -0
  84. package/scripts/release_screen_claims.json +21 -0
  85. package/scripts/run_integration_tests.mjs +134 -29
  86. package/scripts/run_sidecar_e2e.mjs +104 -11
  87. package/scripts/wheel_smoke.py +32 -22
  88. package/src-tauri/Cargo.lock +375 -9
  89. package/src-tauri/Cargo.toml +1 -1
  90. package/src-tauri/src/backend.rs +151 -45
  91. package/src-tauri/src/main.rs +18 -18
  92. package/src-tauri/src/topology.rs +58 -88
  93. package/src-tauri/tauri.conf.json +1 -2
  94. package/static/app/asset-manifest.json +41 -41
  95. package/static/app/assets/{Act-DcQizkl1.js → Act-CToZnOHz.js} +1 -1
  96. package/static/app/assets/{AdminConsole-cf4npybT.js → AdminConsole-D5kbrBu8.js} +1 -1
  97. package/static/app/assets/{Brain-3VCSHFcn.js → Brain-C6zCdv4S.js} +1 -1
  98. package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-D4n3EDUt.js} +1 -1
  99. package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-CzeZ-vQ9.js} +1 -1
  100. package/static/app/assets/{Capture-DiQ219jW.js → Capture-DPcyTczq.js} +1 -1
  101. package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-D3Nx-oWS.js} +1 -1
  102. package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-DPPvpp28.js} +1 -1
  103. package/static/app/assets/{Library-BV6NnF0a.js → Library-Co2qTu3I.js} +1 -1
  104. package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-Bsmzwy8_.js} +1 -1
  105. package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-CBLdmesT.js} +1 -1
  106. package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-CfR6DLs7.js} +1 -1
  107. package/static/app/assets/{System-CieofHQa.js → System-Ce-P2YL6.js} +1 -1
  108. package/static/app/assets/arrow-left-DD5jFGHV.js +1 -0
  109. package/static/app/assets/{bot-B_K1Tdmw.js → bot-C5-XIww2.js} +1 -1
  110. package/static/app/assets/{brain-DWyaV1L1.js → brain-CFRJUvdX.js} +1 -1
  111. package/static/app/assets/{button-aTn4s84A.js → button-DI1KcQP-.js} +1 -1
  112. package/static/app/assets/circle-check-CY20XMCh.js +1 -0
  113. package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-C8HHyood.js} +1 -1
  114. package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-Cufc235E.js} +1 -1
  115. package/static/app/assets/{cpu-85xYObUC.js → cpu-DW2_JVsv.js} +1 -1
  116. package/static/app/assets/{download-B5Fm7YXo.js → download-gbdKTBb8.js} +1 -1
  117. package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-C9ydyX33.js} +1 -1
  118. package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-BxNMzBM3.js} +1 -1
  119. package/static/app/assets/index-BovSWRmQ.css +2 -0
  120. package/static/app/assets/{index-BMPdTmlY.js → index-q9XyDY7A.js} +3 -3
  121. package/static/app/assets/{input-B0nRf2jO.js → input-GLD94Y_K.js} +1 -1
  122. package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-B4Y0gz1S.js} +1 -1
  123. package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-CxrV0fvU.js} +1 -1
  124. package/static/app/assets/{primitives-SNp0LRJz.js → primitives-2ANdAsu2.js} +1 -1
  125. package/static/app/assets/search-DTxtjQ07.js +1 -0
  126. package/static/app/assets/{share-2-BsrxFglO.js → share-2-DxArfiuI.js} +1 -1
  127. package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-CgftuFFs.js} +1 -1
  128. package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-BHVBAoCr.js} +1 -1
  129. package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-Dzq2j_OG.js} +1 -1
  130. package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-BcqfMLNq.js} +1 -1
  131. package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-DBzLKCOv.js} +1 -1
  132. package/static/app/assets/{utils-Ddol2RWD.js → utils-B-Aah1bO.js} +1 -1
  133. package/static/app/assets/{workspace-BqDwOz_p.js → workspace-B6fFhoko.js} +1 -1
  134. package/static/app/index.html +4 -4
  135. package/static/sw.js +1 -1
  136. package/lattice_brain/archive.py +0 -522
  137. package/lattice_brain/context.py +0 -325
  138. package/lattice_brain/conversations.py +0 -382
  139. package/lattice_brain/core.py +0 -82
  140. package/lattice_brain/graph/_kg_contract.py +0 -249
  141. package/lattice_brain/graph/curator.py +0 -676
  142. package/lattice_brain/graph/discovery.py +0 -595
  143. package/lattice_brain/graph/discovery_index/__init__.py +0 -35
  144. package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
  145. package/lattice_brain/graph/discovery_index/extract.py +0 -137
  146. package/lattice_brain/graph/discovery_index/scan.py +0 -411
  147. package/lattice_brain/graph/discovery_index/upsert.py +0 -495
  148. package/lattice_brain/graph/documents.py +0 -380
  149. package/lattice_brain/graph/fusion.py +0 -395
  150. package/lattice_brain/graph/identity.py +0 -175
  151. package/lattice_brain/graph/image_vectors.py +0 -230
  152. package/lattice_brain/graph/ingest.py +0 -829
  153. package/lattice_brain/graph/network.py +0 -205
  154. package/lattice_brain/graph/proactive.py +0 -724
  155. package/lattice_brain/graph/projection/__init__.py +0 -42
  156. package/lattice_brain/graph/projection/curation.py +0 -500
  157. package/lattice_brain/graph/projection/v2_schema.py +0 -518
  158. package/lattice_brain/graph/provenance.py +0 -524
  159. package/lattice_brain/graph/rerank.py +0 -163
  160. package/lattice_brain/graph/retrieval/__init__.py +0 -54
  161. package/lattice_brain/graph/retrieval/context.py +0 -197
  162. package/lattice_brain/graph/retrieval/graph_view.py +0 -319
  163. package/lattice_brain/graph/retrieval/hybrid.py +0 -488
  164. package/lattice_brain/graph/retrieval/maintenance.py +0 -121
  165. package/lattice_brain/graph/retrieval/signals.py +0 -95
  166. package/lattice_brain/graph/retrieval_docgen.py +0 -253
  167. package/lattice_brain/graph/retrieval_policy.py +0 -180
  168. package/lattice_brain/graph/retrieval_reads.py +0 -769
  169. package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
  170. package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
  171. package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
  172. package/lattice_brain/graph/retrieval_vector/search.py +0 -560
  173. package/lattice_brain/graph/retrieval_vector/status.py +0 -374
  174. package/lattice_brain/graph/schema.py +0 -792
  175. package/lattice_brain/graph/store.py +0 -268
  176. package/lattice_brain/graph/vector_index/__init__.py +0 -85
  177. package/lattice_brain/graph/vector_index/base.py +0 -167
  178. package/lattice_brain/graph/vector_index/brute_force.py +0 -110
  179. package/lattice_brain/graph/vector_index/hnsw.py +0 -290
  180. package/lattice_brain/graph/vector_index/jobs.py +0 -287
  181. package/lattice_brain/graph/vector_index/quantized.py +0 -148
  182. package/lattice_brain/graph/vector_index/selector.py +0 -161
  183. package/lattice_brain/graph/write_master.py +0 -308
  184. package/lattice_brain/ingestion/_contract.py +0 -90
  185. package/lattice_brain/ingestion/folder_scan.py +0 -57
  186. package/lattice_brain/ingestion/folders.py +0 -258
  187. package/lattice_brain/ingestion/jobs_api.py +0 -107
  188. package/lattice_brain/ingestion/routing.py +0 -295
  189. package/lattice_brain/ingestion_jobs.py +0 -380
  190. package/lattice_brain/memory.py +0 -75
  191. package/lattice_brain/portability/__init__.py +0 -90
  192. package/lattice_brain/portability/_contract.py +0 -42
  193. package/lattice_brain/portability/backups.py +0 -338
  194. package/lattice_brain/portability/bundles.py +0 -136
  195. package/lattice_brain/portability/constants.py +0 -93
  196. package/lattice_brain/portability/fsops.py +0 -138
  197. package/lattice_brain/portability/service.py +0 -41
  198. package/lattice_brain/portability/sharing.py +0 -710
  199. package/lattice_brain/quality.py +0 -543
  200. package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
  201. package/lattice_brain/runtime/agent_runtime.py +0 -859
  202. package/lattice_brain/runtime/contracts.py +0 -460
  203. package/lattice_brain/runtime/multi_agent.py +0 -942
  204. package/lattice_brain/runtime/statuses.py +0 -10
  205. package/lattice_brain/sealed_box.py +0 -240
  206. package/lattice_brain/self_model.py +0 -675
  207. package/lattice_brain/sensitivity.py +0 -94
  208. package/lattice_brain/storage/__init__.py +0 -22
  209. package/lattice_brain/storage/base.py +0 -100
  210. package/lattice_brain/storage/docker.py +0 -105
  211. package/lattice_brain/storage/factory.py +0 -31
  212. package/lattice_brain/storage/migration.py +0 -191
  213. package/lattice_brain/storage/postgres.py +0 -123
  214. package/lattice_brain/storage/sqlite.py +0 -143
  215. package/lattice_brain/synthesis.py +0 -824
  216. package/lattice_brain/workflow.py +0 -497
  217. package/latticeai/api/admin.py +0 -471
  218. package/latticeai/api/agent_registry.py +0 -105
  219. package/latticeai/api/agents.py +0 -228
  220. package/latticeai/api/auth.py +0 -383
  221. package/latticeai/api/automation_intelligence.py +0 -401
  222. package/latticeai/api/brain_intelligence.py +0 -199
  223. package/latticeai/api/browser.py +0 -493
  224. package/latticeai/api/change_proposals.py +0 -89
  225. package/latticeai/api/chat.py +0 -572
  226. package/latticeai/api/chat_agent_http.py +0 -892
  227. package/latticeai/api/chat_contracts.py +0 -73
  228. package/latticeai/api/chat_documents.py +0 -276
  229. package/latticeai/api/chat_helpers.py +0 -460
  230. package/latticeai/api/chat_history.py +0 -101
  231. package/latticeai/api/chat_hybrid.py +0 -113
  232. package/latticeai/api/chat_intents.py +0 -646
  233. package/latticeai/api/chat_stream.py +0 -216
  234. package/latticeai/api/chronicle.py +0 -63
  235. package/latticeai/api/command_center.py +0 -51
  236. package/latticeai/api/computer_use.py +0 -474
  237. package/latticeai/api/evidence_actions.py +0 -48
  238. package/latticeai/api/features.py +0 -70
  239. package/latticeai/api/funnel_metrics.py +0 -31
  240. package/latticeai/api/garden.py +0 -34
  241. package/latticeai/api/hooks.py +0 -165
  242. package/latticeai/api/index_jobs.py +0 -145
  243. package/latticeai/api/invitations.py +0 -100
  244. package/latticeai/api/knowledge_graph.py +0 -536
  245. package/latticeai/api/marketplace.py +0 -105
  246. package/latticeai/api/mcp.py +0 -482
  247. package/latticeai/api/memory.py +0 -270
  248. package/latticeai/api/network.py +0 -81
  249. package/latticeai/api/network_boundary.py +0 -225
  250. package/latticeai/api/permission_mode.py +0 -61
  251. package/latticeai/api/permissions.py +0 -436
  252. package/latticeai/api/plugins.py +0 -126
  253. package/latticeai/api/portability.py +0 -391
  254. package/latticeai/api/project_sessions.py +0 -114
  255. package/latticeai/api/realtime.py +0 -118
  256. package/latticeai/api/review_queue.py +0 -364
  257. package/latticeai/api/security_dashboard.py +0 -604
  258. package/latticeai/api/setup.py +0 -319
  259. package/latticeai/api/static_routes.py +0 -354
  260. package/latticeai/api/ui_redirects.py +0 -26
  261. package/latticeai/api/workflow_designer.py +0 -394
  262. package/latticeai/api/workspace.py +0 -856
  263. package/latticeai/api/workspace_scope.py +0 -125
  264. package/latticeai/core/agent/__init__.py +0 -93
  265. package/latticeai/core/agent/_contract.py +0 -79
  266. package/latticeai/core/agent/context.py +0 -57
  267. package/latticeai/core/agent/deps.py +0 -125
  268. package/latticeai/core/agent/execution.py +0 -622
  269. package/latticeai/core/agent/planning.py +0 -145
  270. package/latticeai/core/agent/recovery.py +0 -157
  271. package/latticeai/core/agent/runtime.py +0 -210
  272. package/latticeai/core/agent/verification.py +0 -231
  273. package/latticeai/core/agent_eval.py +0 -739
  274. package/latticeai/core/agent_helpers.py +0 -493
  275. package/latticeai/core/agent_profiles.py +0 -110
  276. package/latticeai/core/agent_prompts.py +0 -171
  277. package/latticeai/core/agent_registry.py +0 -232
  278. package/latticeai/core/agent_state.py +0 -41
  279. package/latticeai/core/agent_trace.py +0 -104
  280. package/latticeai/core/artifact_ledger.py +0 -109
  281. package/latticeai/core/audit.py +0 -260
  282. package/latticeai/core/builtin_hooks.py +0 -105
  283. package/latticeai/core/context_builder.py +0 -394
  284. package/latticeai/core/document_generator.py +0 -103
  285. package/latticeai/core/enterprise.py +0 -154
  286. package/latticeai/core/enterprise_admin.py +0 -158
  287. package/latticeai/core/file_generation/__init__.py +0 -115
  288. package/latticeai/core/file_generation/bundles.py +0 -76
  289. package/latticeai/core/file_generation/extraction.py +0 -154
  290. package/latticeai/core/file_generation/inference.py +0 -235
  291. package/latticeai/core/file_generation/orchestration.py +0 -152
  292. package/latticeai/core/file_generation/prompting.py +0 -117
  293. package/latticeai/core/file_generation/repair.py +0 -114
  294. package/latticeai/core/file_generation/sanitize.py +0 -61
  295. package/latticeai/core/file_generation/validation.py +0 -201
  296. package/latticeai/core/invitations.py +0 -132
  297. package/latticeai/core/legacy_compatibility.py +0 -243
  298. package/latticeai/core/logging_safety.py +0 -46
  299. package/latticeai/core/marketplace.py +0 -293
  300. package/latticeai/core/mcp_catalog.py +0 -452
  301. package/latticeai/core/mcp_registry.py +0 -506
  302. package/latticeai/core/network_boundary.py +0 -168
  303. package/latticeai/core/oidc.py +0 -208
  304. package/latticeai/core/plugins.py +0 -432
  305. package/latticeai/core/product_hardening.py +0 -218
  306. package/latticeai/core/project_sessions.py +0 -337
  307. package/latticeai/core/realtime.py +0 -238
  308. package/latticeai/core/run_explain.py +0 -426
  309. package/latticeai/core/run_store.py +0 -252
  310. package/latticeai/core/timezones.py +0 -80
  311. package/latticeai/core/workspace_computer_memory.py +0 -84
  312. package/latticeai/core/workspace_graph_trace.py +0 -155
  313. package/latticeai/core/workspace_indexing.py +0 -102
  314. package/latticeai/core/workspace_memory.py +0 -77
  315. package/latticeai/core/workspace_onboarding.py +0 -104
  316. package/latticeai/core/workspace_os.py +0 -978
  317. package/latticeai/core/workspace_os_constants.py +0 -126
  318. package/latticeai/core/workspace_os_state.py +0 -180
  319. package/latticeai/core/workspace_os_utils.py +0 -103
  320. package/latticeai/core/workspace_permissions.py +0 -101
  321. package/latticeai/core/workspace_plugins.py +0 -97
  322. package/latticeai/core/workspace_relationships.py +0 -99
  323. package/latticeai/core/workspace_reorganization.py +0 -335
  324. package/latticeai/core/workspace_review_items.py +0 -112
  325. package/latticeai/core/workspace_runs.py +0 -726
  326. package/latticeai/core/workspace_skills.py +0 -109
  327. package/latticeai/core/workspace_snapshots.py +0 -198
  328. package/latticeai/core/workspace_timeline.py +0 -110
  329. package/latticeai/integrations/__init__.py +0 -0
  330. package/latticeai/integrations/telegram_bot/__init__.py +0 -123
  331. package/latticeai/integrations/telegram_bot/__main__.py +0 -17
  332. package/latticeai/integrations/telegram_bot/config.py +0 -86
  333. package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
  334. package/latticeai/integrations/telegram_bot/flows.py +0 -478
  335. package/latticeai/integrations/telegram_bot/helpers.py +0 -322
  336. package/latticeai/integrations/telegram_bot/screens.py +0 -394
  337. package/latticeai/runtime/audit_runtime.py +0 -76
  338. package/latticeai/runtime/automation_runtime.py +0 -81
  339. package/latticeai/runtime/chat_wiring.py +0 -141
  340. package/latticeai/runtime/context_runtime.py +0 -66
  341. package/latticeai/runtime/feature_toggle_wiring.py +0 -157
  342. package/latticeai/runtime/history_runtime.py +0 -163
  343. package/latticeai/runtime/history_writer.py +0 -138
  344. package/latticeai/runtime/hooks_runtime.py +0 -77
  345. package/latticeai/runtime/model_wiring.py +0 -68
  346. package/latticeai/runtime/namespace_runtime.py +0 -163
  347. package/latticeai/runtime/network_boundary_wiring.py +0 -117
  348. package/latticeai/runtime/network_config_runtime.py +0 -56
  349. package/latticeai/runtime/permission_mode_wiring.py +0 -112
  350. package/latticeai/runtime/persistence_runtime.py +0 -159
  351. package/latticeai/runtime/platform_runtime_wiring.py +0 -89
  352. package/latticeai/runtime/review_wiring.py +0 -42
  353. package/latticeai/runtime/router_registration.py +0 -693
  354. package/latticeai/runtime/service_singletons.py +0 -55
  355. package/latticeai/runtime/sso_config_runtime.py +0 -128
  356. package/latticeai/runtime/user_key_runtime.py +0 -106
  357. package/latticeai/runtime/web_runtime.py +0 -92
  358. package/latticeai/server_app.py +0 -51
  359. package/latticeai/services/app_context.py +0 -130
  360. package/latticeai/services/automation_execution.py +0 -266
  361. package/latticeai/services/automation_intelligence.py +0 -614
  362. package/latticeai/services/brain_automation.py +0 -191
  363. package/latticeai/services/brain_intelligence/__init__.py +0 -58
  364. package/latticeai/services/brain_intelligence/_contract.py +0 -71
  365. package/latticeai/services/brain_intelligence/consistency.py +0 -193
  366. package/latticeai/services/brain_intelligence/constants.py +0 -47
  367. package/latticeai/services/brain_intelligence/digest.py +0 -258
  368. package/latticeai/services/brain_intelligence/health.py +0 -331
  369. package/latticeai/services/brain_intelligence/proposals.py +0 -259
  370. package/latticeai/services/brain_intelligence/sampling.py +0 -84
  371. package/latticeai/services/brain_intelligence/service.py +0 -48
  372. package/latticeai/services/change_proposals.py +0 -471
  373. package/latticeai/services/chat_service.py +0 -243
  374. package/latticeai/services/chronicle.py +0 -555
  375. package/latticeai/services/cloud_egress_audit.py +0 -85
  376. package/latticeai/services/cloud_extraction.py +0 -129
  377. package/latticeai/services/cloud_streaming.py +0 -268
  378. package/latticeai/services/cloud_token_guard.py +0 -84
  379. package/latticeai/services/command_center.py +0 -548
  380. package/latticeai/services/evidence_actions.py +0 -258
  381. package/latticeai/services/feature_toggles.py +0 -502
  382. package/latticeai/services/folder_watch.py +0 -520
  383. package/latticeai/services/funnel_metrics.py +0 -307
  384. package/latticeai/services/hybrid_chat.py +0 -316
  385. package/latticeai/services/hybrid_context.py +0 -228
  386. package/latticeai/services/hybrid_policy.py +0 -129
  387. package/latticeai/services/interop_bridges.py +0 -978
  388. package/latticeai/services/local_knowledge.py +0 -465
  389. package/latticeai/services/memory_service/__init__.py +0 -52
  390. package/latticeai/services/memory_service/_contract.py +0 -100
  391. package/latticeai/services/memory_service/brief.py +0 -431
  392. package/latticeai/services/memory_service/constants.py +0 -57
  393. package/latticeai/services/memory_service/maintenance.py +0 -138
  394. package/latticeai/services/memory_service/manager.py +0 -186
  395. package/latticeai/services/memory_service/proof.py +0 -136
  396. package/latticeai/services/memory_service/recall.py +0 -225
  397. package/latticeai/services/memory_service/service.py +0 -48
  398. package/latticeai/services/memory_service/stores.py +0 -110
  399. package/latticeai/services/mode_store.py +0 -132
  400. package/latticeai/services/model_recommendation.py +0 -224
  401. package/latticeai/services/model_runtime/cloud.py +0 -87
  402. package/latticeai/services/network_boundary_service.py +0 -117
  403. package/latticeai/services/obsidian_bridge.py +0 -609
  404. package/latticeai/services/openai_compatible_adapter.py +0 -101
  405. package/latticeai/services/permission_mode_service.py +0 -122
  406. package/latticeai/services/platform_runtime.py +0 -366
  407. package/latticeai/services/review_queue.py +0 -380
  408. package/latticeai/services/router_context.py +0 -59
  409. package/latticeai/services/run_executor.py +0 -387
  410. package/latticeai/services/self_model_service.py +0 -171
  411. package/latticeai/services/setup_detection.py +0 -147
  412. package/latticeai/services/triggers.py +0 -378
  413. package/latticeai/services/upload_service.py +0 -172
  414. package/latticeai/services/workspace_service.py +0 -165
  415. package/latticeai/setup/__init__.py +0 -25
  416. package/latticeai/setup/auto_setup.py +0 -846
  417. package/latticeai/setup/demo_corpus.py +0 -98
  418. package/latticeai/setup/wizard/__init__.py +0 -126
  419. package/latticeai/setup/wizard/catalog.py +0 -175
  420. package/latticeai/setup/wizard/detect.py +0 -302
  421. package/latticeai/setup/wizard/install.py +0 -348
  422. package/latticeai/setup/wizard/paths.py +0 -165
  423. package/latticeai/setup/wizard/plans.py +0 -74
  424. package/latticeai/setup/wizard/recommend.py +0 -320
  425. package/scripts/bench_agent_smoke.py +0 -409
  426. package/scripts/bench_models.py +0 -540
  427. package/scripts/bench_vector_index.py +0 -295
  428. package/scripts/funnel_soft_gate.py +0 -192
  429. package/scripts/generate_agent_loop_fixtures.py +0 -994
  430. package/scripts/generate_rust_parity_fixtures.py +0 -908
  431. package/scripts/migrate_brain_storage.py +0 -57
  432. package/scripts/parity_fixture_corpus_context.py +0 -162
  433. package/scripts/parity_fixture_corpus_docgen.py +0 -341
  434. package/scripts/profile_kg.py +0 -355
  435. package/server.py +0 -30
  436. package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
  437. package/static/app/assets/circle-check-qqLug9nU.js +0 -1
  438. package/static/app/assets/index-DxmOfNRi.css +0 -2
  439. package/static/app/assets/search-BcHqkjoy.js +0 -1
@@ -1,543 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- lattice_brain/quality.py
4
- Pure Python Quality Layer for Lattice Brain (v6.4+ hardening)
5
- - Does not modify any DB schema or existing APIs
6
- - Self-contained, dependency-free core (stdlib only)
7
- """
8
-
9
- from __future__ import annotations
10
-
11
- import hashlib
12
- import math
13
- import re
14
- import time
15
- from collections import defaultdict
16
- from dataclasses import dataclass, field
17
- from typing import Any, Dict, List, Optional
18
-
19
-
20
- # -----------------------------
21
- # 1. Embedding Fallback Labelling + Drift/Reindex Plan
22
- # -----------------------------
23
- @dataclass
24
- class EmbeddingLabel:
25
- vector_id: str
26
- label: str
27
- confidence: float
28
- drift_score: float = 0.0
29
- needs_reindex: bool = False
30
-
31
- class EmbeddingFallbackLabeller:
32
- """Fallback labelling when primary embedding unavailable + drift detection"""
33
-
34
- def __init__(self, drift_threshold: float = 0.15):
35
- self.drift_threshold = drift_threshold
36
- self.label_cache: Dict[str, EmbeddingLabel] = {}
37
- self.vector_cache: Dict[str, List[float]] = {}
38
-
39
- def label(self, vector_id: str, embedding: Optional[List[float]] = None,
40
- metadata: Optional[Dict] = None) -> EmbeddingLabel:
41
- if embedding is None:
42
- label = "unembedded_fallback"
43
- conf = 0.3
44
- else:
45
- # Simple hash-based pseudo-label for determinism
46
- # Not a security hash: a short, stable label for grouping
47
- # vectors in reports. usedforsecurity=False states that and
48
- # keeps it working on FIPS builds where md5 is restricted.
49
- h = hashlib.md5(
50
- str(embedding[:4]).encode(), usedforsecurity=False
51
- ).hexdigest()[:8]
52
- label = f"emb_cluster_{h}"
53
- conf = 0.85
54
-
55
- drift = self._compute_drift(vector_id, embedding)
56
- needs_reindex = drift > self.drift_threshold
57
-
58
- el = EmbeddingLabel(vector_id, label, conf, drift, needs_reindex)
59
- self.label_cache[vector_id] = el
60
- if embedding is not None:
61
- self.vector_cache[vector_id] = [float(value) for value in embedding]
62
- return el
63
-
64
- def _compute_drift(self, vector_id: str, new_emb: Optional[List[float]]) -> float:
65
- old = self.vector_cache.get(vector_id)
66
- if old is None or new_emb is None:
67
- return 0.0
68
- return self._cosine_distance(old, new_emb)
69
-
70
- def _cosine_distance(self, a: List[float], b: List[float]) -> float:
71
- if not a or not b or len(a) != len(b):
72
- return 1.0
73
- dot = sum(x * y for x, y in zip(a, b, strict=True))
74
- na = math.sqrt(sum(x*x for x in a))
75
- nb = math.sqrt(sum(x*x for x in b))
76
- return 1.0 - (dot / (na*nb + 1e-9))
77
-
78
- def generate_reindex_plan(self) -> List[str]:
79
- return [vid for vid, lab in self.label_cache.items() if lab.needs_reindex]
80
-
81
- # -----------------------------
82
- # 2. BM25 Lexical Scoring + Hybrid Fusion + Reranker Interface
83
- # -----------------------------
84
- class BM25Scorer:
85
- def __init__(self, k1: float = 1.5, b: float = 0.75):
86
- self.k1 = k1
87
- self.b = b
88
- self.doc_freqs: Dict[str, int] = defaultdict(int)
89
- self.doc_lens: Dict[str, int] = {}
90
- self.corpus_size = 0
91
- self.avgdl = 0.0
92
-
93
- def fit(self, corpus: Dict[str, str]):
94
- self.corpus_size = len(corpus)
95
- total_len = 0
96
- for did, text in corpus.items():
97
- tokens = self._tokenize(text)
98
- self.doc_lens[did] = len(tokens)
99
- total_len += len(tokens)
100
- for t in set(tokens):
101
- self.doc_freqs[t] += 1
102
- self.avgdl = total_len / max(1, self.corpus_size)
103
-
104
- def score(self, query: str, doc_id: str, doc_text: str) -> float:
105
- tokens = self._tokenize(query)
106
- doc_tokens = self._tokenize(doc_text)
107
- score = 0.0
108
- for t in tokens:
109
- if t not in doc_tokens:
110
- continue
111
- tf = doc_tokens.count(t)
112
- df = self.doc_freqs.get(t, 0)
113
- idf = math.log((self.corpus_size - df + 0.5) / (df + 0.5) + 1)
114
- denom = tf + self.k1 * (1 - self.b + self.b * self.doc_lens.get(doc_id, 0) / self.avgdl)
115
- score += idf * tf * (self.k1 + 1) / (denom + 1e-9)
116
- return score
117
-
118
- def _tokenize(self, text: str) -> List[str]:
119
- return re.findall(r'\w+', text.lower())
120
-
121
- class HybridFusion:
122
- """Hybrid fusion of lexical (BM25) + vector scores"""
123
- def __init__(self, alpha: float = 0.6):
124
- self.alpha = alpha # weight for vector score
125
- self.bm25 = BM25Scorer()
126
-
127
- def fuse(self, query: str, candidates: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
128
- # candidates: [{"id": , "text": , "vector_score": }]
129
- corpus = {c["id"]: c.get("text", "") for c in candidates}
130
- self.bm25.fit(corpus)
131
- results = []
132
- for c in candidates:
133
- lex = self.bm25.score(query, c["id"], c.get("text", ""))
134
- vec = c.get("vector_score", 0.5)
135
- fused = self.alpha * vec + (1 - self.alpha) * (lex / 10.0) # normalize rough
136
- c["fused_score"] = round(fused, 4)
137
- results.append(c)
138
- return sorted(results, key=lambda x: x["fused_score"], reverse=True)
139
-
140
- class RerankerInterface:
141
- """Pluggable reranker interface.
142
-
143
- Default is identity (fused score). When
144
- ``LATTICEAI_CROSS_ENCODER_RERANK=1`` and a CrossEncoder is importable,
145
- delegates to :func:`lattice_brain.graph.rerank.rerank_matches`. Failures
146
- never raise — always returns a ranked list.
147
- """
148
-
149
- def rerank(self, query: str, candidates: List[Dict], top_k: int = 5) -> List[Dict]:
150
- try:
151
- from lattice_brain.graph.rerank import rerank_matches
152
-
153
- # Map fused_score → score so the shared helper ranks consistently.
154
- prepared = []
155
- for c in candidates:
156
- item = dict(c)
157
- if "score" not in item:
158
- item["score"] = item.get("fused_score", 0.0)
159
- prepared.append(item)
160
- result = rerank_matches(query, prepared, top_k=top_k)
161
- return list(result.get("matches") or [])
162
- except Exception: # noqa: BLE001 — quality path must never raise
163
- for c in candidates:
164
- c["rerank_score"] = c.get("fused_score", 0.0)
165
- return sorted(
166
- candidates, key=lambda x: x.get("rerank_score", 0), reverse=True
167
- )[:top_k]
168
-
169
- # -----------------------------
170
- # 3. Memory Candidate Extraction / Scoring / Dedupe / Merge / Conflict / Retention
171
- # -----------------------------
172
-
173
- # Public content-signature helpers (v9.6.x graph-layer proactive seam).
174
- # Extracted from MemoryQualityManager so the graph layer
175
- # (lattice_brain.graph.proactive) and future ingestion gating can reuse the
176
- # exact same dedupe semantics without instantiating the manager. Behaviour is
177
- # byte-for-byte identical to the pre-existing private logic.
178
-
179
- _SIGNATURE_STOPWORDS = {
180
- "a", "an", "and", "for", "i", "is", "it", "mode", "the", "to",
181
- "user", "users", "does", "do", "not", "like", "likes", "prefer",
182
- "prefers", "want", "wants",
183
- }
184
-
185
-
186
- def dedupe_key(content: str) -> str:
187
- """Stable near-exact signature for a piece of content.
188
-
189
- sha256 prefix over the normalized text head plus a coarse length bucket —
190
- the same key ``MemoryQualityManager.dedupe`` uses to collapse duplicates.
191
- Two texts with the same key are treated as exact/near-exact duplicates.
192
- """
193
- text = str(content or "")
194
- norm = " ".join(text.lower().split())[:200]
195
- return hashlib.sha256((norm + f"|{len(text)//50}").encode()).hexdigest()[:16]
196
-
197
-
198
- def content_signature(content: str) -> set:
199
- """Token-set signature (stopword-filtered) for overlap/jaccard comparison.
200
-
201
- Mirrors ``MemoryQualityManager._content_signature`` — kept public so
202
- graph-layer duplicate/contradiction detection shares one definition.
203
- """
204
- tokens = set(re.findall(r"\w+", str(content or "").lower()))
205
- return {
206
- token
207
- for token in tokens
208
- if len(token) > 2 and token not in _SIGNATURE_STOPWORDS
209
- }
210
-
211
-
212
- @dataclass
213
- class MemoryCandidate:
214
- id: str
215
- content: str
216
- score: float = 0.0
217
- source: str = "unknown"
218
- timestamp: float = field(default_factory=time.time)
219
- conflicts: List[str] = field(default_factory=list)
220
-
221
- class MemoryQualityManager:
222
- _NEGATION_PATTERNS = (
223
- "not",
224
- "does not",
225
- "don't",
226
- "do not",
227
- "싫어",
228
- "원하지 않",
229
- "하지 않",
230
- "반대",
231
- )
232
- _POSITIVE_PATTERNS = (
233
- "prefers",
234
- "prefer",
235
- "likes",
236
- "like",
237
- "wants",
238
- "want",
239
- "좋아",
240
- "선호",
241
- "원해",
242
- )
243
-
244
- def extract_candidates(self, memories: List[Dict]) -> List[MemoryCandidate]:
245
- return [MemoryCandidate(m["id"], m["content"], m.get("score", 0.6), m.get("source", "mem")) for m in memories]
246
-
247
- def score_candidates(self, cands: List[MemoryCandidate], query: str) -> List[MemoryCandidate]:
248
- for c in cands:
249
- # simple lexical overlap score
250
- overlap = sum(1 for w in query.lower().split() if w in c.content.lower())
251
- c.score = min(1.0, 0.4 + overlap * 0.15)
252
- return sorted(cands, key=lambda x: x.score, reverse=True)
253
-
254
- def dedupe(self, cands: List[MemoryCandidate], threshold: float = 0.85) -> List[MemoryCandidate]:
255
- """Advanced content dedup (KG scale slice).
256
-
257
- Uses sha256 prefix + normalized length bucket for better collision resistance
258
- than plain md5. Future: plug embedding cosine or simhash here.
259
- """
260
- kept = []
261
- seen = set()
262
- for c in cands:
263
- h = dedupe_key(c.content)
264
- if h not in seen:
265
- seen.add(h)
266
- kept.append(c)
267
- return kept
268
-
269
- def merge(self, cands: List[MemoryCandidate]) -> List[MemoryCandidate]:
270
- # naive merge by content prefix
271
- merged: Dict[str, MemoryCandidate] = {}
272
- for c in cands:
273
- key = c.content[:30]
274
- if key not in merged or c.score > merged[key].score:
275
- merged[key] = c
276
- return list(merged.values())
277
-
278
- def detect_conflicts(self, cands: List[MemoryCandidate]) -> List[MemoryCandidate]:
279
- """Flag local contradiction signals before proactive synthesis.
280
-
281
- The heuristic stays deterministic/offline: direct negation marks a row
282
- as risky, and pairwise token overlap catches common preference conflicts
283
- such as "prefers light mode" vs "does not like light mode".
284
- """
285
- for c in cands:
286
- lowered = c.content.lower()
287
- if any(pattern in lowered for pattern in self._NEGATION_PATTERNS):
288
- c.conflicts.append("conflict:possible_negation")
289
-
290
- signatures = [(c, self._content_signature(c.content)) for c in cands]
291
- for left_index, (left, left_sig) in enumerate(signatures):
292
- for right, right_sig in signatures[left_index + 1:]:
293
- if not left_sig or len(left_sig & right_sig) < 2:
294
- continue
295
- left_negative = self._is_negative(left.content)
296
- right_negative = self._is_negative(right.content)
297
- left_positive = self._is_positive(left.content)
298
- right_positive = self._is_positive(right.content)
299
- if left_negative == right_negative:
300
- continue
301
- if not (left_positive or right_positive):
302
- continue
303
- left.conflicts.append(f"conflict:contradicts:{right.id}")
304
- right.conflicts.append(f"conflict:contradicts:{left.id}")
305
- return cands
306
-
307
- def _is_negative(self, content: str) -> bool:
308
- lowered = content.lower()
309
- return any(pattern in lowered for pattern in self._NEGATION_PATTERNS)
310
-
311
- def _is_positive(self, content: str) -> bool:
312
- lowered = content.lower()
313
- return any(pattern in lowered for pattern in self._POSITIVE_PATTERNS)
314
-
315
- def _content_signature(self, content: str) -> set[str]:
316
- return content_signature(content)
317
-
318
- # --- Large candidate #4 slice: proactive / temporal contradiction detection ---
319
- def detect_temporal_contradictions(self, memories: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
320
- """Simple temporal + contradiction detector over memory list (proactive synthesis extension).
321
-
322
- Looks at negation keywords across similar contents + differing timestamps.
323
- Real version would walk graph historical projections + LLM judge.
324
- Returns flagged items with 'contradiction' tag.
325
- """
326
- flagged = []
327
- neg_tokens = ("not ", "반대", "거짓", "no longer", "never", "중단", "사용하지")
328
- pos_group = []
329
- neg_group = []
330
- for m in memories:
331
- c = (m.get("content") or "").lower()
332
- if any(t in c for t in neg_tokens):
333
- neg_group.append(m)
334
- else:
335
- pos_group.append(m)
336
- # cross check: if both pos and neg exist with time spread
337
- all_t = [m.get("timestamp") or m.get("created_at") or 0 for m in memories]
338
- if neg_group and pos_group and len(set(all_t)) > 1:
339
- for g in (pos_group + neg_group):
340
- gg = dict(g)
341
- gg["proactive_flag"] = "contradiction:temporal_negation"
342
- flagged.append(gg)
343
- return flagged
344
-
345
- def apply_retention(self, cands: List[MemoryCandidate], max_age_days: int = 90) -> List[MemoryCandidate]:
346
- now = time.time()
347
- return [c for c in cands if (now - c.timestamp) < max_age_days * 86400]
348
-
349
- # -----------------------------
350
- # 4. Graph Edge Validation / Confidence / Evidence / Duplicate Merge / Quality Metrics
351
- # -----------------------------
352
- @dataclass
353
- class GraphEdgeQuality:
354
- edge_id: str
355
- confidence: float
356
- evidence_count: int
357
- is_duplicate: bool = False
358
- quality_score: float = 0.0
359
-
360
- class GraphEdgeQualityManager:
361
- def validate_edge(self, edge: Dict[str, Any]) -> GraphEdgeQuality:
362
- conf = edge.get("confidence", 0.7)
363
- ev = len(edge.get("evidence", []))
364
- q = min(1.0, conf * 0.75 + min(ev, 5) / 5 * 0.3)
365
- return GraphEdgeQuality(edge.get("id", "e0"), conf, ev, quality_score=q)
366
-
367
- def detect_duplicate_edges(self, edges: List[Dict]) -> List[str]:
368
- seen: Dict[Any, Any] = {}
369
- dups: List[str] = []
370
- for e in edges:
371
- key = (e.get("source"), e.get("target"), e.get("type"))
372
- if key in seen:
373
- dups.append(str(e.get("id") or ""))
374
- else:
375
- seen[key] = e.get("id")
376
- return dups
377
-
378
- def compute_quality_metrics(self, edges: List[Dict]) -> Dict[str, float]:
379
- if not edges:
380
- return {"avg_conf": 0.0, "avg_evidence": 0.0, "dup_rate": 0.0}
381
- confs = [e.get("confidence", 0.5) for e in edges]
382
- evs = [len(e.get("evidence", [])) for e in edges]
383
- dups = len(self.detect_duplicate_edges(edges))
384
- return {
385
- "avg_conf": round(sum(confs)/len(confs), 3),
386
- "avg_evidence": round(sum(evs)/len(evs), 2),
387
- "dup_rate": round(dups / len(edges), 3)
388
- }
389
-
390
- # -----------------------------
391
- # 5. Structured Context Assembly + Guardrails
392
- # -----------------------------
393
- @dataclass
394
- class ContextGuardrails:
395
- known: bool = True
396
- inferred: bool = False
397
- stale: bool = False
398
- unknown: bool = False
399
- confidence: float = 0.8
400
- timestamp: float = field(default_factory=time.time)
401
- attribution: str = "system"
402
-
403
- class StructuredContextAssembler:
404
- SECTIONS = ["Facts", "Decisions", "Preferences", "Relationships", "Projects", "Recent Events"]
405
-
406
- def assemble(self, items: List[Dict[str, Any]]) -> Dict[str, List[Dict]]:
407
- ctx: Dict[str, List[Dict]] = {s: [] for s in self.SECTIONS}
408
- for item in items:
409
- section = item.get("section", "Facts")
410
- if section not in ctx:
411
- section = "Facts"
412
- guard = ContextGuardrails(
413
- known=item.get("known", True),
414
- inferred=item.get("inferred", False),
415
- stale=item.get("stale", False),
416
- unknown=item.get("unknown", False),
417
- confidence=item.get("confidence", 0.75),
418
- attribution=item.get("attribution", "user")
419
- )
420
- item["guardrails"] = guard.__dict__
421
- ctx[section].append(item)
422
- return ctx
423
-
424
- def apply_guardrails(self, ctx: Dict[str, List[Dict]]) -> Dict[str, List[Dict]]:
425
- cleaned = {}
426
- for sec, items in ctx.items():
427
- cleaned[sec] = [i for i in items if not i.get("guardrails", {}).get("unknown", False)]
428
- return cleaned
429
-
430
- # -----------------------------
431
- # 6. Retrieval Benchmark Fixture Runner
432
- # -----------------------------
433
- def _relevance_grades(relevant: Any) -> Dict[str, float]:
434
- """Normalize a ``relevant`` spec into a ``{doc_id: grade}`` map.
435
-
436
- Accepts a graded dict (``{"doc": 3}``) or a binary list/set/tuple (grade 1
437
- for every id), so judged fixtures can express graded relevance for nDCG
438
- while older binary fixtures keep working unchanged.
439
- """
440
- if isinstance(relevant, dict):
441
- return {str(k): float(v) for k, v in relevant.items()}
442
- return {str(doc_id): 1.0 for doc_id in (relevant or [])}
443
-
444
-
445
- class RetrievalBenchmarkRunner:
446
- def __init__(self):
447
- self.results: List[Dict] = []
448
-
449
- def run_fixture(self, fixture_name: str, queries: List[Any], top_k: int = 5) -> Dict[str, Any]:
450
- start = time.time()
451
- judged = [q for q in queries if isinstance(q, dict)]
452
- if judged:
453
- recalls = []
454
- precisions = []
455
- ndcgs = []
456
- for query in judged:
457
- grades = _relevance_grades(query.get("relevant"))
458
- relevant = set(grades)
459
- retrieved = list(query.get("retrieved") or [])[:top_k]
460
- if not relevant:
461
- continue
462
- hits = [doc_id for doc_id in retrieved if doc_id in relevant]
463
- recalls.append(len(hits) / len(relevant))
464
- precisions.append(len(hits) / max(1, len(retrieved)))
465
- # Graded DCG: each retrieved doc contributes its relevance grade
466
- # discounted by log2(rank + 2). IDCG ranks the highest grades
467
- # first, so nDCG rewards putting the *most* relevant docs on top.
468
- # Binary fixtures fall back to grade 1 via _relevance_grades.
469
- dcg = sum(
470
- grades.get(doc_id, 0.0) / math.log2(rank + 2)
471
- for rank, doc_id in enumerate(retrieved)
472
- )
473
- ideal_grades = sorted(grades.values(), reverse=True)[:top_k]
474
- ideal = sum(g / math.log2(rank + 2) for rank, g in enumerate(ideal_grades))
475
- ndcgs.append(dcg / ideal if ideal else 0.0)
476
- recall = sum(recalls) / len(recalls) if recalls else 0.0
477
- precision = sum(precisions) / len(precisions) if precisions else 0.0
478
- ndcg = sum(ndcgs) / len(ndcgs) if ndcgs else 0.0
479
- else:
480
- recall = precision = ndcg = 0.0
481
- must_include = [
482
- bool(set(query.get("must_include") or []).intersection(set(list(query.get("retrieved") or [])[:top_k])))
483
- for query in judged
484
- if query.get("must_include")
485
- ]
486
- must_include_hit_rate = sum(1 for hit in must_include if hit) / len(must_include) if must_include else 1.0
487
- metrics = {
488
- "fixture": fixture_name,
489
- "queries": len(queries),
490
- "avg_latency_ms": round((time.time() - start) * 1000 / max(1, len(queries)), 2),
491
- "recall@5": round(recall, 4),
492
- "precision@5": round(precision, 4),
493
- "ndcg@5": round(ndcg, 4),
494
- f"recall@{top_k}": round(recall, 4),
495
- f"precision@{top_k}": round(precision, 4),
496
- f"ndcg@{top_k}": round(ndcg, 4),
497
- "must_include_hit_rate": round(must_include_hit_rate, 4),
498
- "top_k": top_k,
499
- "judged": len(judged),
500
- }
501
- self.results.append(metrics)
502
- return metrics
503
-
504
- def summary(self) -> Dict[str, Any]:
505
- if not self.results:
506
- return {"status": "no runs"}
507
- return {
508
- "total_runs": len(self.results),
509
- "avg_recall": round(sum(r["recall@5"] for r in self.results) / len(self.results), 3)
510
- }
511
-
512
- # -----------------------------
513
- # Main Quality Layer Facade
514
- # -----------------------------
515
- class LatticeBrainQuality:
516
- """Main entry point - pure Python quality hardening layer"""
517
- def __init__(self):
518
- self.embed_labeller = EmbeddingFallbackLabeller()
519
- self.hybrid = HybridFusion()
520
- self.reranker = RerankerInterface()
521
- self.memory_mgr = MemoryQualityManager()
522
- self.graph_mgr = GraphEdgeQualityManager()
523
- self.context_assembler = StructuredContextAssembler()
524
- self.benchmark = RetrievalBenchmarkRunner()
525
-
526
-
527
- __all__ = [
528
- "BM25Scorer",
529
- "ContextGuardrails",
530
- "content_signature",
531
- "dedupe_key",
532
- "EmbeddingFallbackLabeller",
533
- "EmbeddingLabel",
534
- "GraphEdgeQuality",
535
- "GraphEdgeQualityManager",
536
- "HybridFusion",
537
- "LatticeBrainQuality",
538
- "MemoryCandidate",
539
- "MemoryQualityManager",
540
- "RetrievalBenchmarkRunner",
541
- "RerankerInterface",
542
- "StructuredContextAssembler",
543
- ]
@@ -1,92 +0,0 @@
1
- """Corpus-scale retrieval fixture for the 7.5.0 Brain quality gate."""
2
-
3
- from __future__ import annotations
4
-
5
- FIXTURE_NAME = "7.5.0-corpus-scale-hybrid-retrieval"
6
- TOP_K = 5
7
-
8
- CORE_DOCUMENTS = [
9
- {"id": "doc:agent-runtime-contract", "type": "Decision", "title": "Agent runtime contract", "content": "Workflow run, agent run, audit event, and realtime event records must carry the agent-run-contract/v1 family envelope with run id, runtime, status, timeline, and artifacts."},
10
- {"id": "doc:workflow-observability", "type": "Document", "title": "Workflow observability", "content": "Workflow Designer persists queued, running, awaiting approval, cancelled, interrupted, partial, failed, and ok runs with replayable timeline events."},
11
- {"id": "doc:audit-trust", "type": "Security", "title": "Audit trust", "content": "Audit events are append-only, redacted before persistence, and linked to execution contracts for admin review without leaking secrets."},
12
- {"id": "doc:realtime-feed", "type": "Document", "title": "Realtime execution feed", "content": "The realtime SSE bus publishes workspace, agent, workflow, and execution events with workspace scope, event type, payload, sequence, and contract metadata."},
13
- {"id": "doc:retrieval-benchmark", "type": "Benchmark", "title": "Retrieval benchmark strategy", "content": "Hybrid retrieval quality must be checked with corpus-scale fixtures, judged queries, recall, precision, ndcg, and must-include hit rate."},
14
- {"id": "doc:hybrid-search", "type": "Architecture", "title": "Hybrid search", "content": "SearchService fuses keyword, vector, and graph retrieval channels with weighted scores and scoped workspace filtering."},
15
- {"id": "doc:knowledge-graph", "type": "Architecture", "title": "Knowledge graph stabilization", "content": "The Knowledge Graph preserves legacy read compatibility, non-destructive migrations, vector indexing, relationship traversal, and provenance."},
16
- {"id": "doc:local-first", "type": "Strategy", "title": "Local-first product wedge", "content": "Lattice AI is local-first: durable knowledge, private workspace memory, local LLM routing, and model-independent context are the product wedge."},
17
- {"id": "doc:brain-proof", "type": "UX", "title": "Brain proof and citations", "content": "Brain proof shows durable recall, source citation, graph counts, vector counts, and model continuity evidence in chat."},
18
- {"id": "doc:onboarding", "type": "UX", "title": "Five minute onboarding loop", "content": "The first loop asks users to add a source, ask a question, see Brain proof, and understand expected installation time."},
19
- {"id": "doc:vscode-sync", "type": "Integration", "title": "VS Code extension state", "content": "VS Code extension integration shows app connection state, indexing status, command routing, and extension-to-app sync health."},
20
- {"id": "doc:workspace-admin", "type": "Workspace", "title": "Workspace profile admin discovery", "content": "Personal workspace, organization workspace, profile, admin, members, roles, permissions, and security surfaces must be discoverable."},
21
- {"id": "doc:empty-error-consent", "type": "UX", "title": "Empty error consent states", "content": "Empty states, error states, consent prompts, retries, and privacy feedback should be explicit across ingestion, graph, chat, and workspace flows."},
22
- {"id": "doc:tool-registry", "type": "Architecture", "title": "Tool registry separation", "content": "ToolRegistry separates tool definitions, permissions, dispatch, audit, and UI discovery from AgentRuntime orchestration."},
23
- {"id": "doc:config-centralization", "type": "Architecture", "title": "Config centralization", "content": "Configuration should be centralized into explicit objects instead of hidden globals so runtime, tests, and packaging are predictable."},
24
- {"id": "doc:server-decomposition", "type": "Architecture", "title": "Server decomposition", "content": "Server decomposition moves routers, services, runtime context, and persistence seams into focused modules with dependency injection."},
25
- {"id": "doc:incremental-ingestion", "type": "Pipeline", "title": "Incremental ingestion", "content": "Background indexing needs duplicate detection, conflict resolution, incremental updates, and merge behavior for large personal corpora."},
26
- {"id": "doc:vector-index-evolution", "type": "Pipeline", "title": "Vector index evolution", "content": "sqlite-vec migration, HNSW evaluation, query caching, embedding caching, and retrieval caching support larger corpora."},
27
- {"id": "doc:security-zero-trust", "type": "Security", "title": "Zero trust defaults", "content": "Zero-trust defaults include audit logging, secret redaction, dependency vulnerability monitoring, and automated security scanning."},
28
- {"id": "doc:agentic-hitl", "type": "Workflow", "title": "Agentic human review", "content": "Agentic workflows need human-in-the-loop review, approval gates, rollback paths, review queues, and auditable decisions."},
29
- {"id": "doc:temporal-reasoning", "type": "Brain", "title": "Temporal reasoning", "content": "Temporal graph states, historical memory, contradiction detection, synthesis, and recommendations make the Brain proactive."},
30
- {"id": "doc:multimodal-memory", "type": "Brain", "title": "Multimodal memory", "content": "Images, audio, video, documents, and chat should ingest into one durable Brain with retrieval and citation proof."},
31
- {"id": "doc:developer-api", "type": "API", "title": "Developer API", "content": "A secure developer API exposes third-party access to workspace knowledge, tools, runs, contracts, and audit trails."},
32
- {"id": "doc:team-brains", "type": "Business", "title": "Team Brains", "content": "Team Brains, encrypted sharing, premium cloud sync, hosted models, plugin marketplace, and public benchmarks support monetization."},
33
- {"id": "doc:docker-tauri", "type": "Deployment", "title": "Deployment operations", "content": "Docker Compose deployment, one-click installation, Tauri auto-updates, rollback support, and exact release artifacts improve operations."},
34
- {"id": "doc:model-routing", "type": "Runtime", "title": "Model orchestration", "content": "Ollama, LM Studio, MLX, and cloud models need automatic fallback, routing, and replaceable model boundaries."},
35
- {"id": "doc:strict-quality", "type": "Quality", "title": "Strict code quality", "content": "Async-first architecture, dependency injection, centralized exceptions, mypy or pyright, TypeScript strict mode, E2E tests, and property tests reduce regressions."},
36
- {"id": "distractor:theme-editor", "type": "Distractor", "title": "Theme editor", "content": "Color palettes, typography, and sidebar icon sizing are useful visual polish topics."},
37
- {"id": "distractor:calendar", "type": "Distractor", "title": "Calendar reminders", "content": "Calendar reminders and meeting agenda formatting are productivity integrations."},
38
- {"id": "distractor:billing", "type": "Distractor", "title": "Billing invoices", "content": "Invoices, payment receipts, and subscription emails can be stored but are not the Brain quality gate."},
39
- {"id": "distractor:mobile-shell", "type": "Distractor", "title": "Mobile shell", "content": "A mobile companion can improve access with push notifications and offline cache."},
40
- {"id": "distractor:marketing", "type": "Distractor", "title": "Marketing landing page", "content": "Landing pages and hero copy shape positioning and campaign messaging."},
41
- ]
42
-
43
- _DISTRACTOR_TOPICS = [
44
- ("finance", "quarterly planning", "budget variance vendor renewal procurement forecast"),
45
- ("design", "component polish", "spacing typography icon density color token accessibility"),
46
- ("support", "customer escalation", "ticket triage priority response macro satisfaction"),
47
- ("ops", "incident rotation", "oncall handoff status page maintenance window"),
48
- ("sales", "pipeline review", "lead scoring opportunity stage forecast account"),
49
- ("calendar", "meeting schedule", "agenda reminder availability invite followup"),
50
- ("email", "inbox policy", "thread label archive template unsubscribe"),
51
- ("mobile", "companion shell", "push notification offline cache deep link"),
52
- ("billing", "invoice lifecycle", "receipt tax subscription entitlement payment"),
53
- ("analytics", "dashboard report", "cohort funnel metric annotation export"),
54
- ("theme", "appearance settings", "palette contrast sidebar density motion"),
55
- ("legal", "compliance packet", "clause obligation renewal signature counterparty"),
56
- ]
57
-
58
-
59
- def _generated_distractors() -> list[dict[str, str]]:
60
- """Create a deterministic local corpus large enough to exercise ranking."""
61
- docs: list[dict[str, str]] = []
62
- for batch in range(20):
63
- for topic, title, terms in _DISTRACTOR_TOPICS:
64
- docs.append({
65
- "id": f"distractor:{topic}:{batch:02d}",
66
- "type": "Distractor",
67
- "title": f"{title.title()} {batch + 1}",
68
- "content": (
69
- f"{title} note {batch + 1}. This record discusses {terms}. "
70
- "It is intentionally unrelated to the judged Brain quality topics "
71
- "and exists to make local ranking tests compete against realistic noise."
72
- ),
73
- })
74
- return docs
75
-
76
-
77
- DOCUMENTS = CORE_DOCUMENTS + _generated_distractors()
78
-
79
- QUERIES = [
80
- {"query": "agent workflow audit realtime contract run status timeline", "relevant": {"doc:agent-runtime-contract": 3, "doc:workflow-observability": 2, "doc:audit-trust": 2, "doc:realtime-feed": 2}, "must_include": ["doc:agent-runtime-contract"]},
81
- {"query": "workflow queued running cancelled interrupted replay approval", "relevant": {"doc:workflow-observability": 3, "doc:agentic-hitl": 2}, "must_include": ["doc:workflow-observability"]},
82
- {"query": "audit log redacted secrets admin review contract", "relevant": {"doc:audit-trust": 3}, "must_include": ["doc:audit-trust"]},
83
- {"query": "SSE realtime workspace event payload sequence contract", "relevant": {"doc:realtime-feed": 3, "doc:agent-runtime-contract": 2}, "must_include": ["doc:realtime-feed"]},
84
- {"query": "hybrid retrieval keyword vector graph weighted scoped search", "relevant": {"doc:hybrid-search": 3, "doc:knowledge-graph": 2, "doc:retrieval-benchmark": 2}, "must_include": ["doc:hybrid-search"]},
85
- {"query": "corpus scale recall precision ndcg judged queries", "relevant": {"doc:retrieval-benchmark": 3}, "must_include": ["doc:retrieval-benchmark"]},
86
- {"query": "local first model independent durable memory brain proof citation", "relevant": {"doc:local-first": 3, "doc:brain-proof": 2}, "must_include": ["doc:local-first"]},
87
- {"query": "incremental indexing duplicate conflict merge background ingestion", "relevant": {"doc:incremental-ingestion": 3}, "must_include": ["doc:incremental-ingestion"]},
88
- {"query": "workspace admin profile organization members roles permissions", "relevant": {"doc:workspace-admin": 3}, "must_include": ["doc:workspace-admin"]},
89
- {"query": "tool registry separation dependency injection runtime context", "relevant": {"doc:tool-registry": 3, "doc:server-decomposition": 2, "doc:config-centralization": 2}, "must_include": ["doc:tool-registry"]},
90
- {"query": "human in the loop approval review queue rollback", "relevant": {"doc:agentic-hitl": 3}, "must_include": ["doc:agentic-hitl"]},
91
- {"query": "model routing ollama lm studio mlx cloud fallback replaceable", "relevant": {"doc:model-routing": 3, "doc:local-first": 2}, "must_include": ["doc:model-routing"]},
92
- ]