ltcai 12.1.0 → 12.2.1

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 (77) hide show
  1. package/README.md +86 -88
  2. package/docs/CHANGELOG.md +48 -4
  3. package/docs/CI_AND_RELEASE_GATES.md +7 -4
  4. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  5. package/docs/DEVELOPMENT.md +11 -11
  6. package/docs/ONBOARDING.md +1 -1
  7. package/docs/OPERATIONS.md +1 -1
  8. package/docs/ROADMAP.md +8 -8
  9. package/docs/TRUST_MODEL.md +2 -2
  10. package/docs/WHY_LATTICE.md +1 -1
  11. package/docs/kg-schema.md +1 -1
  12. package/lattice_brain/__init__.py +1 -1
  13. package/latticeai/__init__.py +1 -1
  14. package/latticeai/core/vector_index/hnsw.py +49 -10
  15. package/latticeai/core/vector_index/sidecar.py +120 -31
  16. package/latticeai/services/architecture_readiness.py +1 -1
  17. package/latticeai/services/product_readiness.py +2 -2
  18. package/package.json +1 -1
  19. package/scripts/check_current_release_docs.mjs +1 -1
  20. package/scripts/release_screen_claims.json +34 -0
  21. package/src-tauri/Cargo.lock +10 -10
  22. package/src-tauri/Cargo.toml +1 -1
  23. package/src-tauri/tauri.conf.json +1 -1
  24. package/static/app/asset-manifest.json +45 -45
  25. package/static/app/assets/{Act-DCRUH46a.js → Act-DC676bqE.js} +2 -2
  26. package/static/app/assets/{AdminConsole-BFBj6OvN.js → AdminConsole-aCxQgD2L.js} +1 -1
  27. package/static/app/assets/{Brain-BXcoxIvb.js → Brain-Dbd0xvsc.js} +2 -2
  28. package/static/app/assets/BrainHome-N00B-MAJ.js +2 -0
  29. package/static/app/assets/{BrainSignals-DrfYSNjR.js → BrainSignals-CNA0d6xS.js} +1 -1
  30. package/static/app/assets/{Capture-BsO_OAeh.js → Capture-BB19fo7P.js} +1 -1
  31. package/static/app/assets/{Chronicle-BUj_UH3D.js → Chronicle-D8p3dqxZ.js} +1 -1
  32. package/static/app/assets/{CommandPalette-B4SWOaR-.js → CommandPalette-uVFYAa-6.js} +1 -1
  33. package/static/app/assets/{DigitalBrainExplorer-S1GSsyIT.js → DigitalBrainExplorer-mH6ZSuvK.js} +1 -1
  34. package/static/app/assets/{Library-CKUR2eVb.js → Library-0q8Sdke7.js} +1 -1
  35. package/static/app/assets/{LivingBrain--2UoV3Ki.js → LivingBrain-wess-qJZ.js} +1 -1
  36. package/static/app/assets/ProductFlow-DeBGF6qz.js +1 -0
  37. package/static/app/assets/{ReviewCard-UzQZ1ULT.js → ReviewCard-DyTrDpy0.js} +1 -1
  38. package/static/app/assets/{RunsListPanel-CDGFQYMo.js → RunsListPanel-CHJv2Qyw.js} +1 -1
  39. package/static/app/assets/System-CyKGHQrW.js +1 -0
  40. package/static/app/assets/{WorkflowGraph-BIcWZTUQ.js → WorkflowGraph-B5nKCCGa.js} +1 -1
  41. package/static/app/assets/{WorkflowsPanel-BeT5fmbk.js → WorkflowsPanel-C7RZNRGo.js} +2 -2
  42. package/static/app/assets/{actHelpers-DhutJObL.js → actHelpers-6MYDH2kW.js} +1 -1
  43. package/static/app/assets/arrow-left-DOnpwsVV.js +1 -0
  44. package/static/app/assets/{bot-D8tZzKMD.js → bot-Dm3fmXAE.js} +1 -1
  45. package/static/app/assets/brain-C2XwdQL1.js +1 -0
  46. package/static/app/assets/{button-Tzf5D7L1.js → button-xXPeemQr.js} +1 -1
  47. package/static/app/assets/circle-check-D44VI2ZE.js +1 -0
  48. package/static/app/assets/{circle-pause-Druue_tZ.js → circle-pause-B_lmNicW.js} +1 -1
  49. package/static/app/assets/{circle-play-BAht4SSW.js → circle-play-DSYCP0RD.js} +1 -1
  50. package/static/app/assets/{cpu-BPbmZRPp.js → cpu-D7x-dtxi.js} +1 -1
  51. package/static/app/assets/{download-BmxPZEwU.js → download-BHuJr-5V.js} +1 -1
  52. package/static/app/assets/{folder-open-DokOmFQJ.js → folder-open-BiO31EwS.js} +1 -1
  53. package/static/app/assets/{hard-drive-Cw6aEA2h.js → hard-drive-CFEaZ-wP.js} +1 -1
  54. package/static/app/assets/{index-CB93CZWW.css → index-C8gwOf0C.css} +1 -1
  55. package/static/app/assets/{index-DhszK7A3.js → index-DCT79wzR.js} +3 -3
  56. package/static/app/assets/{input-BCdHoZXA.js → input-D3YrgxvO.js} +1 -1
  57. package/static/app/assets/{link-2-CCModn4z.js → link-2-3O-By3qc.js} +1 -1
  58. package/static/app/assets/{permissionCopy-BSp1jYG7.js → permissionCopy-CNK2tfkz.js} +1 -1
  59. package/static/app/assets/{primitives-D01WcJn7.js → primitives-B6DzQC3H.js} +1 -1
  60. package/static/app/assets/search-BwMK0hjs.js +1 -0
  61. package/static/app/assets/{share-2-DMMkM8Iu.js → share-2-BljIPAku.js} +1 -1
  62. package/static/app/assets/{shield-alert--mrCWQko.js → shield-alert-WDP2DSTM.js} +1 -1
  63. package/static/app/assets/{sourceMeta-nvd3Cdz3.js → sourceMeta-By2WIjlN.js} +1 -1
  64. package/static/app/assets/{textarea-DfayhQiX.js → textarea-5v8vtDlK.js} +1 -1
  65. package/static/app/assets/{useFocusTrap-C5NsTvsI.js → useFocusTrap-ssiDeh6P.js} +1 -1
  66. package/static/app/assets/{useMutation-D7IMQTeI.js → useMutation-Bi0PXQMC.js} +1 -1
  67. package/static/app/assets/workspace-BsxrRYQI.js +1 -0
  68. package/static/app/index.html +2 -2
  69. package/static/sw.js +1 -1
  70. package/static/app/assets/BrainHome-IhcEPC3v.js +0 -2
  71. package/static/app/assets/ProductFlow-D7rB6Xsu.js +0 -1
  72. package/static/app/assets/System-0OSxZrTp.js +0 -1
  73. package/static/app/assets/arrow-left-BwJfcH8J.js +0 -1
  74. package/static/app/assets/brain-DP2JPXSV.js +0 -1
  75. package/static/app/assets/circle-check-D68nHcgS.js +0 -1
  76. package/static/app/assets/search-C_zAGfvO.js +0 -1
  77. package/static/app/assets/workspace-C7xidB7c.js +0 -1
@@ -118,6 +118,11 @@ class HnswIndex:
118
118
  def model_id(self) -> str:
119
119
  return self._model_id
120
120
 
121
+ @property
122
+ def labels(self) -> List[str]:
123
+ """Live label order — the sidecar's identity, loaded or rebuilt."""
124
+ return list(self._labels)
125
+
121
126
  def _identity_matches(self, dim: int, space: str, model_id: str) -> bool:
122
127
  return (
123
128
  int(dim) == self._dim
@@ -177,10 +182,12 @@ class HnswIndex:
177
182
  doors without guessing.
178
183
 
179
184
  Full rebuild when the embedder identity changed, when any currently
180
- indexed id is missing from the incoming set (a deletion), when
181
- deletes would exceed :data:`DELETE_REBUILD_RATIO`, or when this
182
- instance was loaded from a sidecar and cannot append (no source
183
- vectors to keep the label map honest).
185
+ indexed id is missing from a *full* incoming snapshot (a deletion),
186
+ or when deletes would exceed :data:`DELETE_REBUILD_RATIO`. A sidecar
187
+ that was loaded without source vectors still **appends**: the
188
+ caller passes only the new ids (COUNT+delta) and ``_append_live``
189
+ extends the graph. A disjoint incoming set is that delta, not a
190
+ wipe.
184
191
  """
185
192
  incoming: Dict[str, IndexItem] = {}
186
193
  for item_id, vector, metadata in items:
@@ -197,13 +204,36 @@ class HnswIndex:
197
204
  return "rebuild"
198
205
 
199
206
  if self._loaded:
207
+ current = set(self._labels)
208
+ incoming_ids = set(incoming)
209
+ overlap = current & incoming_ids
210
+ deleted = current - incoming_ids
211
+ # Delta-only: the caller passed new ids, none of the live labels.
212
+ # A full snapshot that dropped ids is a deletion and must rebuild.
213
+ delta_only = bool(incoming_ids) and not overlap
214
+ if deleted and not delta_only:
215
+ self.rebuild(incoming.values())
216
+ return "rebuild"
217
+ new_ids = [item_id for item_id in incoming if item_id not in current]
218
+ if not new_ids:
219
+ return "append"
220
+ for item_id in new_ids:
221
+ _, vector, metadata = incoming[item_id]
222
+ self._vectors[item_id] = [float(value) for value in vector]
223
+ self._metadata[item_id] = dict(metadata or {})
224
+ if self._ann is not None and self._module is not None:
225
+ self._append_live(new_ids)
226
+ return "append"
200
227
  self.rebuild(incoming.values())
201
228
  return "rebuild"
202
229
 
203
230
  current = set(self._vectors)
204
231
  incoming_ids = set(incoming)
205
232
  deleted = current - incoming_ids
206
- if deleted:
233
+ overlap = current & incoming_ids
234
+ # Same discriminant as the loaded path: a disjoint incoming set is
235
+ # COUNT+delta, not a snapshot that deleted every live id.
236
+ if deleted and not (bool(incoming_ids) and not overlap):
207
237
  ratio = len(deleted) / max(1, len(current))
208
238
  if ratio >= DELETE_REBUILD_RATIO or not current:
209
239
  self.rebuild(incoming.values())
@@ -339,18 +369,25 @@ class HnswIndex:
339
369
  return False
340
370
  return True
341
371
 
342
- def load(self, db_path: Any, *, fingerprint: str) -> bool:
343
- """Adopt a sidecar graph when it provably matches ``fingerprint``."""
372
+ def load(self, db_path: Any, *, fingerprint: str, strict: bool = True) -> bool:
373
+ """Adopt a sidecar graph when it matches this embedder identity.
374
+
375
+ ``strict`` (the default) also requires the stored fingerprint — size
376
+ included — so a grown store does not search a stale graph. Relaxed
377
+ load keeps dim/model and leaves COUNT+delta to append the missing
378
+ ids rather than dumping the whole table.
379
+ """
344
380
  module = self._module
345
381
  if module is None:
346
382
  return False
347
383
  index_path, meta_path = sidecar_paths(db_path)
348
384
  try:
349
385
  meta = json.loads(meta_path.read_text(encoding="utf-8"))
350
- matches = str(meta["fingerprint"]) == str(fingerprint)
351
- matches = matches and int(meta["dim"]) == self._dim
386
+ matches = int(meta["dim"]) == self._dim
352
387
  if meta.get("model_id") not in (None, "", self._model_id):
353
388
  matches = False
389
+ if strict:
390
+ matches = matches and str(meta["fingerprint"]) == str(fingerprint)
354
391
  labels = [str(label) for label in meta["labels"]]
355
392
  except Exception: # noqa: BLE001 — absent/corrupt sidecar = rebuild
356
393
  return False
@@ -358,7 +395,9 @@ class HnswIndex:
358
395
  return False
359
396
  try:
360
397
  graph = module.Index(space=self._space, dim=self._dim)
361
- graph.load_index(str(index_path), max_elements=len(labels))
398
+ # Headroom so an in-process append does not have to rebuild
399
+ # just because load_index pinned max_elements to the old size.
400
+ graph.load_index(str(index_path), max_elements=max(len(labels) + 64, 1))
362
401
  except Exception: # noqa: BLE001 — corrupt binary = rebuild
363
402
  return False
364
403
  self._ann = graph
@@ -2,10 +2,10 @@
2
2
 
3
3
  The live graph is cached per ``(db_path, model_id, dim)``. A missing sidecar
4
4
  is ``index: "none"``. When the store has vectors the cache (or a rebuild from
5
- ``vector_embeddings``) can serve, the reply is ``index: "hnsw"``. Staleness is
6
- sidecar size vs ``COUNT(*)`` for that identity — reported honestly, and
7
- refreshed through :meth:`HnswIndex.add_items` so an ingest append does not
8
- rebuild the whole graph.
5
+ ``vector_embeddings``) can serve, the reply is ``index: "hnsw"``. Freshness is
6
+ sidecar size vs ``COUNT(*)`` for that identity. A warm COUNT match never
7
+ opens embedding blobs. Growth loads **missing ids only** and appends; a
8
+ shrink still rebuilds from the remaining rows.
9
9
  """
10
10
 
11
11
  from __future__ import annotations
@@ -81,6 +81,83 @@ def load_store_items(
81
81
  return items
82
82
 
83
83
 
84
+ def load_store_ids(conn: sqlite3.Connection, model_id: str, dim: int) -> List[str]:
85
+ """Item ids only — the COUNT+delta path must not pull embedding blobs."""
86
+ rows = conn.execute(
87
+ "SELECT item_id FROM vector_embeddings "
88
+ "WHERE embedding_model=? AND embedding_dim=? ORDER BY indexed_at ASC, item_id ASC",
89
+ (model_id, int(dim)),
90
+ )
91
+ return [str(item_id) for (item_id,) in rows]
92
+
93
+
94
+ def load_store_items_for(
95
+ conn: sqlite3.Connection,
96
+ model_id: str,
97
+ dim: int,
98
+ item_ids: Sequence[str],
99
+ ) -> List[Tuple[str, List[float], Dict[str, Any]]]:
100
+ """Blobs for ``item_ids`` only, preserving the caller's order."""
101
+ if not item_ids:
102
+ return []
103
+ by_id: Dict[str, List[float]] = {}
104
+ wanted = [str(item_id) for item_id in item_ids]
105
+ # SQLite caps bound parameters; 400 leaves room for the identity pair.
106
+ for start in range(0, len(wanted), 400):
107
+ chunk = wanted[start : start + 400]
108
+ qmarks = ",".join("?" * len(chunk))
109
+ query = "SELECT item_id, embedding FROM vector_embeddings WHERE embedding_model=? AND embedding_dim=? AND item_id IN (%s)" % qmarks # noqa: S608
110
+ for item_id, blob in conn.execute(query, (model_id, int(dim), *chunk)):
111
+ vector = decode_f32le(bytes(blob or b""), int(dim))
112
+ if len(vector) != int(dim):
113
+ continue
114
+ by_id[str(item_id)] = vector
115
+ return [
116
+ (item_id, by_id[item_id], {})
117
+ for item_id in wanted
118
+ if item_id in by_id
119
+ ]
120
+
121
+
122
+ def _open_and_count(path: Path, model_id: str, dim: int) -> int:
123
+ conn = _open_readonly(path)
124
+ if conn is None:
125
+ return 0
126
+ try:
127
+ return store_vector_count(conn, model_id, dim)
128
+ finally:
129
+ conn.close()
130
+
131
+
132
+ def _load_all_items(
133
+ path: Path, model_id: str, dim: int
134
+ ) -> List[Tuple[str, List[float], Dict[str, Any]]]:
135
+ conn = _open_readonly(path)
136
+ if conn is None:
137
+ return []
138
+ try:
139
+ return load_store_items(conn, model_id, dim)
140
+ finally:
141
+ conn.close()
142
+
143
+
144
+ def _load_missing_items(
145
+ path: Path,
146
+ model_id: str,
147
+ dim: int,
148
+ have: Sequence[str],
149
+ ) -> List[Tuple[str, List[float], Dict[str, Any]]]:
150
+ conn = _open_readonly(path)
151
+ if conn is None:
152
+ return []
153
+ try:
154
+ have_set = set(have)
155
+ missing = [item_id for item_id in load_store_ids(conn, model_id, dim) if item_id not in have_set]
156
+ return load_store_items_for(conn, model_id, dim, missing)
157
+ finally:
158
+ conn.close()
159
+
160
+
84
161
  def sidecar_meta_size(db_path: Path) -> Optional[int]:
85
162
  """Label count from the sidecar meta file, or ``None`` when it is absent."""
86
163
  _, meta_path = sidecar_paths(db_path)
@@ -185,17 +262,8 @@ def query_sidecar(
185
262
  if not model_id:
186
263
  return _none_reply(detail="embedding_model is required")
187
264
 
188
- conn = _open_readonly(path)
189
- store_size = 0
190
- items: List[Tuple[str, List[float], Dict[str, Any]]] = []
191
- if conn is not None:
192
- try:
193
- store_size = store_vector_count(conn, model_id, dim)
194
- if store_size > 0:
195
- items = load_store_items(conn, model_id, dim)
196
- store_size = len(items)
197
- finally:
198
- conn.close()
265
+ # COUNT first. Warm queries that already match never open embedding blobs.
266
+ store_size = _open_and_count(path, model_id, dim)
199
267
 
200
268
  key = (str(path), model_id, dim)
201
269
  with _LOCK:
@@ -203,8 +271,20 @@ def query_sidecar(
203
271
  refreshed: Optional[str] = None
204
272
  if index is None:
205
273
  index = HnswIndex(dim=dim, model_id=model_id)
206
- loaded = index.load(path, fingerprint=sidecar_fingerprint(model_id, dim, store_size))
274
+ loaded = index.load(
275
+ path, fingerprint=sidecar_fingerprint(model_id, dim, store_size)
276
+ )
277
+ if not loaded and store_size > 0:
278
+ # Sidecar exists for this identity but the COUNT moved —
279
+ # load the graph and append the missing ids below.
280
+ loaded = index.load(
281
+ path,
282
+ fingerprint=sidecar_fingerprint(model_id, dim, store_size),
283
+ strict=False,
284
+ )
207
285
  if not loaded:
286
+ items = _load_all_items(path, model_id, dim)
287
+ store_size = len(items)
208
288
  if not items:
209
289
  return _none_reply(
210
290
  store_size=store_size,
@@ -216,25 +296,31 @@ def query_sidecar(
216
296
 
217
297
  cached_size = int(index.stats().get("size") or 0)
218
298
  stale = cached_size != store_size
219
- if stale:
220
- if not items and store_size > 0:
221
- conn = _open_readonly(path)
222
- if conn is not None:
223
- try:
224
- items = load_store_items(conn, model_id, dim)
225
- finally:
226
- conn.close()
299
+ if stale and store_size == 0:
300
+ _CACHE.pop(key, None)
301
+ return _none_reply(
302
+ store_size=0,
303
+ detail="vector store is empty for this embedding identity",
304
+ )
305
+ if stale and store_size > cached_size:
306
+ delta = _load_missing_items(path, model_id, dim, index.labels)
307
+ if delta:
308
+ refreshed = _refresh_index(index, delta, model_id, dim)
309
+ cached_size = int(index.stats().get("size") or 0)
310
+ index.save(
311
+ path, fingerprint=sidecar_fingerprint(model_id, dim, cached_size)
312
+ )
313
+ stale = cached_size != store_size
314
+ elif stale:
315
+ items = _load_all_items(path, model_id, dim)
316
+ store_size = len(items)
227
317
  if items:
228
318
  refreshed = _refresh_index(index, items, model_id, dim)
229
- index.save(path, fingerprint=sidecar_fingerprint(model_id, dim, len(items)))
230
319
  cached_size = int(index.stats().get("size") or 0)
231
- stale = cached_size != len(items)
232
- elif store_size == 0:
233
- _CACHE.pop(key, None)
234
- return _none_reply(
235
- store_size=0,
236
- detail="vector store is empty for this embedding identity",
320
+ index.save(
321
+ path, fingerprint=sidecar_fingerprint(model_id, dim, cached_size)
237
322
  )
323
+ stale = cached_size != store_size
238
324
 
239
325
  if cached_size <= 0:
240
326
  return _none_reply(
@@ -326,4 +412,7 @@ __all__ = [
326
412
  "sidecar_freshness",
327
413
  "sidecar_meta_size",
328
414
  "store_vector_count",
415
+ "load_store_ids",
416
+ "load_store_items",
417
+ "load_store_items_for",
329
418
  ]
@@ -19,7 +19,7 @@ from dataclasses import dataclass
19
19
  from pathlib import Path
20
20
  from typing import Any, Dict, List
21
21
 
22
- ARCHITECTURE_VERSION_TARGET = "12.1.0"
22
+ ARCHITECTURE_VERSION_TARGET = "12.2.1"
23
23
 
24
24
  PREFERRED_REFACTORING_ORDER = [
25
25
  "agent-runtime",
@@ -28,7 +28,7 @@ from typing import Any, Dict, List
28
28
 
29
29
  from latticeai.services.architecture_readiness import architecture_readiness
30
30
 
31
- PRODUCT_VERSION_TARGET = "12.1.0"
31
+ PRODUCT_VERSION_TARGET = "12.2.1"
32
32
 
33
33
 
34
34
  @dataclass(frozen=True)
@@ -123,7 +123,7 @@ PRODUCT_GATES: List[ProductGate] = [
123
123
  f"vscode-extension/README.md::**{PRODUCT_VERSION_TARGET}",
124
124
  f"docs/CHANGELOG.md::## [{PRODUCT_VERSION_TARGET}]",
125
125
  "FEATURE_STATUS.md",
126
- f"RELEASE_NOTES_v{PRODUCT_VERSION_TARGET}.md",
126
+ f"docs/releases/RELEASE_NOTES_v{PRODUCT_VERSION_TARGET}.md",
127
127
  "rust/lattice-agent/src/kernel/permission.rs::pub fn block_reason_for_tool",
128
128
  "rust/lattice-agent/src/kernel/mod.rs::pub mod agentloop",
129
129
  "latticeai/api/agent_worker_seam.py::create_agent_worker_seam_router",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ltcai",
3
- "version": "12.1.0",
3
+ "version": "12.2.1",
4
4
  "description": "Lattice AI — local-first Digital Brain that keeps your knowledge durable across any AI model.",
5
5
  "homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
6
6
  "repository": {
@@ -6,7 +6,7 @@ const root = process.cwd();
6
6
  const pkg = JSON.parse(readFileSync(path.join(root, "package.json"), "utf8"));
7
7
  const version = pkg.version;
8
8
  const releaseDir = `output/release/v${version}`;
9
- const releaseTheme = "Fast Path";
9
+ const releaseTheme = "True Count";
10
10
  const title = `${version} — ${releaseTheme}`;
11
11
  const escapedVersion = version.replaceAll(".", "\\.");
12
12
 
@@ -20,6 +20,40 @@
20
20
  "whole-image delta: naming where the change is makes the claim more",
21
21
  "specific, not less."
22
22
  ],
23
+ "12.2.1": {
24
+ "_why": [
25
+ "True Count is a backend honesty release: HNSW COUNT+delta, SkipByHash",
26
+ "restamp, watch graph prune, summary salvage, MCP CORE, api_key /models",
27
+ "probe, and hash-search copy. The library embedding panel and first-run",
28
+ "hint changed wording; that is below a redesign floor.",
29
+ "",
30
+ "No screen was redesigned. Empty claim set on purpose. Unclaimed screens",
31
+ "are still measured and printed; they are not gated."
32
+ ]
33
+ },
34
+ "12.2.0": {
35
+ "_why": [
36
+ "Small Voice is a 2B tool-calling release with two visible surfaces.",
37
+ "",
38
+ "1. Brain home composer: four plain-language chips (folder search, read",
39
+ " and summarize, memory, skill review) sit under the textarea. The",
40
+ " Living Brain still dominates the shot, so the whole-image delta sits",
41
+ " under the 8% live floor; the claim uses the measured 3.96% as the",
42
+ " floor, not a redesign of the shell.",
43
+ "",
44
+ "2. Settings: a new 'small models can use tools' card with four badges.",
45
+ " That card is why 08 grew 168px.",
46
+ "",
47
+ "No other screen was redesigned. Unclaimed screens are measured and",
48
+ "printed; they are not gated."
49
+ ],
50
+ "04-brain-chat-home.png": {
51
+ "min_pct": 3.0
52
+ },
53
+ "08-system.png": {
54
+ "min_pct": 1.5
55
+ }
56
+ },
23
57
  "12.1.0": {
24
58
  "_why": [
25
59
  "Fast Path is a backend ingest/search release. Folder ingest overlaps",
@@ -1863,7 +1863,7 @@ dependencies = [
1863
1863
 
1864
1864
  [[package]]
1865
1865
  name = "lattice-agent"
1866
- version = "12.1.0"
1866
+ version = "12.2.1"
1867
1867
  dependencies = [
1868
1868
  "axum",
1869
1869
  "base64 0.22.1",
@@ -1880,7 +1880,7 @@ dependencies = [
1880
1880
 
1881
1881
  [[package]]
1882
1882
  name = "lattice-ai-desktop"
1883
- version = "12.1.0"
1883
+ version = "12.2.1"
1884
1884
  dependencies = [
1885
1885
  "lattice-host",
1886
1886
  "lattice-jobs",
@@ -1895,7 +1895,7 @@ dependencies = [
1895
1895
 
1896
1896
  [[package]]
1897
1897
  name = "lattice-auth"
1898
- version = "12.1.0"
1898
+ version = "12.2.1"
1899
1899
  dependencies = [
1900
1900
  "axum",
1901
1901
  "base64 0.22.1",
@@ -1912,7 +1912,7 @@ dependencies = [
1912
1912
 
1913
1913
  [[package]]
1914
1914
  name = "lattice-chat"
1915
- version = "12.1.0"
1915
+ version = "12.2.1"
1916
1916
  dependencies = [
1917
1917
  "axum",
1918
1918
  "bytes",
@@ -1934,7 +1934,7 @@ dependencies = [
1934
1934
 
1935
1935
  [[package]]
1936
1936
  name = "lattice-core"
1937
- version = "12.1.0"
1937
+ version = "12.2.1"
1938
1938
  dependencies = [
1939
1939
  "blake2",
1940
1940
  "bytes",
@@ -1950,7 +1950,7 @@ dependencies = [
1950
1950
 
1951
1951
  [[package]]
1952
1952
  name = "lattice-host"
1953
- version = "12.1.0"
1953
+ version = "12.2.1"
1954
1954
  dependencies = [
1955
1955
  "axum",
1956
1956
  "lattice-agent",
@@ -1971,7 +1971,7 @@ dependencies = [
1971
1971
 
1972
1972
  [[package]]
1973
1973
  name = "lattice-ingest"
1974
- version = "12.1.0"
1974
+ version = "12.2.1"
1975
1975
  dependencies = [
1976
1976
  "axum",
1977
1977
  "lattice-auth",
@@ -1986,7 +1986,7 @@ dependencies = [
1986
1986
 
1987
1987
  [[package]]
1988
1988
  name = "lattice-jobs"
1989
- version = "12.1.0"
1989
+ version = "12.2.1"
1990
1990
  dependencies = [
1991
1991
  "axum",
1992
1992
  "lattice-auth",
@@ -2001,7 +2001,7 @@ dependencies = [
2001
2001
 
2002
2002
  [[package]]
2003
2003
  name = "lattice-platform"
2004
- version = "12.1.0"
2004
+ version = "12.2.1"
2005
2005
  dependencies = [
2006
2006
  "axum",
2007
2007
  "base64 0.22.1",
@@ -2024,7 +2024,7 @@ dependencies = [
2024
2024
 
2025
2025
  [[package]]
2026
2026
  name = "lattice-retrieval"
2027
- version = "12.1.0"
2027
+ version = "12.2.1"
2028
2028
  dependencies = [
2029
2029
  "axum",
2030
2030
  "fancy-regex",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "lattice-ai-desktop"
3
- version = "12.1.0"
3
+ version = "12.2.1"
4
4
  description = "Lattice AI Digital Brain desktop shell"
5
5
  authors = ["TaeSoo Park"]
6
6
  edition = "2021"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schema.tauri.app/config/2",
3
3
  "productName": "Lattice AI",
4
- "version": "12.1.0",
4
+ "version": "12.2.1",
5
5
  "identifier": "ai.lattice.desktop",
6
6
  "build": {
7
7
  "beforeDevCommand": "npm run frontend:dev",
@@ -1,55 +1,55 @@
1
1
  {
2
- "version": "12.1.0",
2
+ "version": "12.2.1",
3
3
  "generated_at": "vite",
4
4
  "entrypoints": {
5
- "app": "/static/app/assets/index-DhszK7A3.js"
5
+ "app": "/static/app/assets/index-DCT79wzR.js"
6
6
  },
7
7
  "assets": {
8
8
  "../node_modules/@tauri-apps/api/core.js": "/static/app/assets/core-CwxXejkd.js",
9
- "_BrainSignals-DrfYSNjR.js": "/static/app/assets/BrainSignals-DrfYSNjR.js",
10
- "_LivingBrain--2UoV3Ki.js": "/static/app/assets/LivingBrain--2UoV3Ki.js",
9
+ "_BrainSignals-CNA0d6xS.js": "/static/app/assets/BrainSignals-CNA0d6xS.js",
10
+ "_LivingBrain-wess-qJZ.js": "/static/app/assets/LivingBrain-wess-qJZ.js",
11
11
  "_QueryClientProvider-B3OjqSyJ.js": "/static/app/assets/QueryClientProvider-B3OjqSyJ.js",
12
- "_ReviewCard-UzQZ1ULT.js": "/static/app/assets/ReviewCard-UzQZ1ULT.js",
13
- "_actHelpers-DhutJObL.js": "/static/app/assets/actHelpers-DhutJObL.js",
14
- "_arrow-left-BwJfcH8J.js": "/static/app/assets/arrow-left-BwJfcH8J.js",
15
- "_bot-D8tZzKMD.js": "/static/app/assets/bot-D8tZzKMD.js",
16
- "_brain-DP2JPXSV.js": "/static/app/assets/brain-DP2JPXSV.js",
17
- "_button-Tzf5D7L1.js": "/static/app/assets/button-Tzf5D7L1.js",
18
- "_circle-check-D68nHcgS.js": "/static/app/assets/circle-check-D68nHcgS.js",
19
- "_circle-pause-Druue_tZ.js": "/static/app/assets/circle-pause-Druue_tZ.js",
20
- "_circle-play-BAht4SSW.js": "/static/app/assets/circle-play-BAht4SSW.js",
21
- "_cpu-BPbmZRPp.js": "/static/app/assets/cpu-BPbmZRPp.js",
22
- "_download-BmxPZEwU.js": "/static/app/assets/download-BmxPZEwU.js",
23
- "_folder-open-DokOmFQJ.js": "/static/app/assets/folder-open-DokOmFQJ.js",
24
- "_hard-drive-Cw6aEA2h.js": "/static/app/assets/hard-drive-Cw6aEA2h.js",
25
- "_input-BCdHoZXA.js": "/static/app/assets/input-BCdHoZXA.js",
12
+ "_ReviewCard-DyTrDpy0.js": "/static/app/assets/ReviewCard-DyTrDpy0.js",
13
+ "_actHelpers-6MYDH2kW.js": "/static/app/assets/actHelpers-6MYDH2kW.js",
14
+ "_arrow-left-DOnpwsVV.js": "/static/app/assets/arrow-left-DOnpwsVV.js",
15
+ "_bot-Dm3fmXAE.js": "/static/app/assets/bot-Dm3fmXAE.js",
16
+ "_brain-C2XwdQL1.js": "/static/app/assets/brain-C2XwdQL1.js",
17
+ "_button-xXPeemQr.js": "/static/app/assets/button-xXPeemQr.js",
18
+ "_circle-check-D44VI2ZE.js": "/static/app/assets/circle-check-D44VI2ZE.js",
19
+ "_circle-pause-B_lmNicW.js": "/static/app/assets/circle-pause-B_lmNicW.js",
20
+ "_circle-play-DSYCP0RD.js": "/static/app/assets/circle-play-DSYCP0RD.js",
21
+ "_cpu-D7x-dtxi.js": "/static/app/assets/cpu-D7x-dtxi.js",
22
+ "_download-BHuJr-5V.js": "/static/app/assets/download-BHuJr-5V.js",
23
+ "_folder-open-BiO31EwS.js": "/static/app/assets/folder-open-BiO31EwS.js",
24
+ "_hard-drive-CFEaZ-wP.js": "/static/app/assets/hard-drive-CFEaZ-wP.js",
25
+ "_input-D3YrgxvO.js": "/static/app/assets/input-D3YrgxvO.js",
26
26
  "_jsx-runtime-bzQ4Vb5N.js": "/static/app/assets/jsx-runtime-bzQ4Vb5N.js",
27
- "_link-2-CCModn4z.js": "/static/app/assets/link-2-CCModn4z.js",
28
- "_permissionCopy-BSp1jYG7.js": "/static/app/assets/permissionCopy-BSp1jYG7.js",
29
- "_primitives-D01WcJn7.js": "/static/app/assets/primitives-D01WcJn7.js",
30
- "_search-C_zAGfvO.js": "/static/app/assets/search-C_zAGfvO.js",
31
- "_share-2-DMMkM8Iu.js": "/static/app/assets/share-2-DMMkM8Iu.js",
32
- "_shield-alert--mrCWQko.js": "/static/app/assets/shield-alert--mrCWQko.js",
33
- "_sourceMeta-nvd3Cdz3.js": "/static/app/assets/sourceMeta-nvd3Cdz3.js",
34
- "_textarea-DfayhQiX.js": "/static/app/assets/textarea-DfayhQiX.js",
35
- "_useFocusTrap-C5NsTvsI.js": "/static/app/assets/useFocusTrap-C5NsTvsI.js",
36
- "_useMutation-D7IMQTeI.js": "/static/app/assets/useMutation-D7IMQTeI.js",
37
- "_workspace-C7xidB7c.js": "/static/app/assets/workspace-C7xidB7c.js",
38
- "index.html": "/static/app/assets/index-DhszK7A3.js",
39
- "assets/index-CB93CZWW.css": "/static/app/assets/index-CB93CZWW.css",
40
- "src/components/ProductFlow.tsx": "/static/app/assets/ProductFlow-D7rB6Xsu.js",
41
- "src/features/act/RunsListPanel.tsx": "/static/app/assets/RunsListPanel-CDGFQYMo.js",
42
- "src/features/act/WorkflowGraph.tsx": "/static/app/assets/WorkflowGraph-BIcWZTUQ.js",
43
- "src/features/act/WorkflowsPanel.tsx": "/static/app/assets/WorkflowsPanel-BeT5fmbk.js",
44
- "src/features/admin/AdminConsole.tsx": "/static/app/assets/AdminConsole-BFBj6OvN.js",
45
- "src/features/brain/BrainHome.tsx": "/static/app/assets/BrainHome-IhcEPC3v.js",
46
- "src/features/command/CommandPalette.tsx": "/static/app/assets/CommandPalette-B4SWOaR-.js",
47
- "src/pages/Act.tsx": "/static/app/assets/Act-DCRUH46a.js",
48
- "src/pages/Brain.tsx": "/static/app/assets/Brain-BXcoxIvb.js",
49
- "src/pages/Capture.tsx": "/static/app/assets/Capture-BsO_OAeh.js",
50
- "src/pages/Chronicle.tsx": "/static/app/assets/Chronicle-BUj_UH3D.js",
51
- "src/pages/Library.tsx": "/static/app/assets/Library-CKUR2eVb.js",
52
- "src/pages/System.tsx": "/static/app/assets/System-0OSxZrTp.js",
53
- "src/pages/brain/DigitalBrainExplorer.tsx": "/static/app/assets/DigitalBrainExplorer-S1GSsyIT.js"
27
+ "_link-2-3O-By3qc.js": "/static/app/assets/link-2-3O-By3qc.js",
28
+ "_permissionCopy-CNK2tfkz.js": "/static/app/assets/permissionCopy-CNK2tfkz.js",
29
+ "_primitives-B6DzQC3H.js": "/static/app/assets/primitives-B6DzQC3H.js",
30
+ "_search-BwMK0hjs.js": "/static/app/assets/search-BwMK0hjs.js",
31
+ "_share-2-BljIPAku.js": "/static/app/assets/share-2-BljIPAku.js",
32
+ "_shield-alert-WDP2DSTM.js": "/static/app/assets/shield-alert-WDP2DSTM.js",
33
+ "_sourceMeta-By2WIjlN.js": "/static/app/assets/sourceMeta-By2WIjlN.js",
34
+ "_textarea-5v8vtDlK.js": "/static/app/assets/textarea-5v8vtDlK.js",
35
+ "_useFocusTrap-ssiDeh6P.js": "/static/app/assets/useFocusTrap-ssiDeh6P.js",
36
+ "_useMutation-Bi0PXQMC.js": "/static/app/assets/useMutation-Bi0PXQMC.js",
37
+ "_workspace-BsxrRYQI.js": "/static/app/assets/workspace-BsxrRYQI.js",
38
+ "index.html": "/static/app/assets/index-DCT79wzR.js",
39
+ "assets/index-C8gwOf0C.css": "/static/app/assets/index-C8gwOf0C.css",
40
+ "src/components/ProductFlow.tsx": "/static/app/assets/ProductFlow-DeBGF6qz.js",
41
+ "src/features/act/RunsListPanel.tsx": "/static/app/assets/RunsListPanel-CHJv2Qyw.js",
42
+ "src/features/act/WorkflowGraph.tsx": "/static/app/assets/WorkflowGraph-B5nKCCGa.js",
43
+ "src/features/act/WorkflowsPanel.tsx": "/static/app/assets/WorkflowsPanel-C7RZNRGo.js",
44
+ "src/features/admin/AdminConsole.tsx": "/static/app/assets/AdminConsole-aCxQgD2L.js",
45
+ "src/features/brain/BrainHome.tsx": "/static/app/assets/BrainHome-N00B-MAJ.js",
46
+ "src/features/command/CommandPalette.tsx": "/static/app/assets/CommandPalette-uVFYAa-6.js",
47
+ "src/pages/Act.tsx": "/static/app/assets/Act-DC676bqE.js",
48
+ "src/pages/Brain.tsx": "/static/app/assets/Brain-Dbd0xvsc.js",
49
+ "src/pages/Capture.tsx": "/static/app/assets/Capture-BB19fo7P.js",
50
+ "src/pages/Chronicle.tsx": "/static/app/assets/Chronicle-D8p3dqxZ.js",
51
+ "src/pages/Library.tsx": "/static/app/assets/Library-0q8Sdke7.js",
52
+ "src/pages/System.tsx": "/static/app/assets/System-CyKGHQrW.js",
53
+ "src/pages/brain/DigitalBrainExplorer.tsx": "/static/app/assets/DigitalBrainExplorer-mH6ZSuvK.js"
54
54
  }
55
55
  }