ltcai 12.2.1 → 12.3.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 (75) hide show
  1. package/README.md +40 -33
  2. package/docs/CHANGELOG.md +34 -0
  3. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  4. package/docs/DEVELOPMENT.md +11 -11
  5. package/docs/ONBOARDING.md +1 -1
  6. package/docs/OPERATIONS.md +1 -1
  7. package/docs/ROADMAP.md +1 -1
  8. package/docs/TRUST_MODEL.md +1 -1
  9. package/docs/WHY_LATTICE.md +1 -1
  10. package/docs/kg-schema.md +1 -1
  11. package/lattice_brain/__init__.py +1 -1
  12. package/latticeai/__init__.py +1 -1
  13. package/latticeai/core/embedding_providers/autodetect.py +0 -1
  14. package/latticeai/core/model_compat.py +2 -2
  15. package/latticeai/models/model_providers.py +10 -11
  16. package/latticeai/services/architecture_readiness.py +1 -1
  17. package/latticeai/services/model_capability_registry.py +2 -2
  18. package/latticeai/services/model_catalog.py +20 -12
  19. package/latticeai/services/model_engines.py +26 -14
  20. package/latticeai/services/model_runtime/download.py +53 -6
  21. package/latticeai/services/product_readiness.py +1 -1
  22. package/package.json +4 -6
  23. package/scripts/check_current_release_docs.mjs +1 -1
  24. package/scripts/release_screen_claims.json +13 -0
  25. package/src-tauri/Cargo.lock +10 -10
  26. package/src-tauri/Cargo.toml +1 -1
  27. package/src-tauri/tauri.conf.json +1 -1
  28. package/static/app/asset-manifest.json +44 -44
  29. package/static/app/assets/{Act-DC676bqE.js → Act-CZXyMcfJ.js} +2 -2
  30. package/static/app/assets/{AdminConsole-aCxQgD2L.js → AdminConsole-CAkZk0BI.js} +1 -1
  31. package/static/app/assets/{Brain-Dbd0xvsc.js → Brain-DN_7_HSV.js} +2 -2
  32. package/static/app/assets/{BrainHome-N00B-MAJ.js → BrainHome-BBP0ouU-.js} +1 -1
  33. package/static/app/assets/{BrainSignals-CNA0d6xS.js → BrainSignals-nyRNxvQ3.js} +1 -1
  34. package/static/app/assets/{Capture-BB19fo7P.js → Capture-DBvFoZKL.js} +1 -1
  35. package/static/app/assets/{Chronicle-D8p3dqxZ.js → Chronicle-BC5zmR44.js} +1 -1
  36. package/static/app/assets/{CommandPalette-uVFYAa-6.js → CommandPalette-Bs-Fk6HT.js} +1 -1
  37. package/static/app/assets/{DigitalBrainExplorer-mH6ZSuvK.js → DigitalBrainExplorer-CNcCktPP.js} +1 -1
  38. package/static/app/assets/{Library-0q8Sdke7.js → Library-CxUA4xai.js} +1 -1
  39. package/static/app/assets/{LivingBrain-wess-qJZ.js → LivingBrain-CiyjvwKy.js} +1 -1
  40. package/static/app/assets/{ProductFlow-DeBGF6qz.js → ProductFlow-DccERGr3.js} +1 -1
  41. package/static/app/assets/{ReviewCard-DyTrDpy0.js → ReviewCard-lawM1khV.js} +1 -1
  42. package/static/app/assets/{RunsListPanel-CHJv2Qyw.js → RunsListPanel-DQC-zQ7m.js} +1 -1
  43. package/static/app/assets/{System-CyKGHQrW.js → System-DwqYJQaj.js} +1 -1
  44. package/static/app/assets/{WorkflowGraph-B5nKCCGa.js → WorkflowGraph-pJ2eFrhy.js} +1 -1
  45. package/static/app/assets/{WorkflowsPanel-C7RZNRGo.js → WorkflowsPanel-BIGjfM7h.js} +2 -2
  46. package/static/app/assets/{actHelpers-6MYDH2kW.js → actHelpers-DfIqS92u.js} +1 -1
  47. package/static/app/assets/arrow-left-DvwQxqcD.js +1 -0
  48. package/static/app/assets/{bot-Dm3fmXAE.js → bot-CAfN5QD1.js} +1 -1
  49. package/static/app/assets/{brain-C2XwdQL1.js → brain-DNNLFQgq.js} +1 -1
  50. package/static/app/assets/{button-xXPeemQr.js → button-D0k7_k6e.js} +1 -1
  51. package/static/app/assets/circle-check-hH6updC-.js +1 -0
  52. package/static/app/assets/{circle-pause-B_lmNicW.js → circle-pause-Dxw6SJuA.js} +1 -1
  53. package/static/app/assets/{circle-play-DSYCP0RD.js → circle-play-DuoLDLEg.js} +1 -1
  54. package/static/app/assets/{cpu-D7x-dtxi.js → cpu-BGOpEdGX.js} +1 -1
  55. package/static/app/assets/{download-BHuJr-5V.js → download-wXD9L5vN.js} +1 -1
  56. package/static/app/assets/{folder-open-BiO31EwS.js → folder-open-CittV8Ey.js} +1 -1
  57. package/static/app/assets/{hard-drive-CFEaZ-wP.js → hard-drive-CLQPYYBF.js} +1 -1
  58. package/static/app/assets/{index-DCT79wzR.js → index-C0VEkbAp.js} +3 -3
  59. package/static/app/assets/{input-D3YrgxvO.js → input-RZ8aKj6d.js} +1 -1
  60. package/static/app/assets/{link-2-3O-By3qc.js → link-2-B7QYeNdJ.js} +1 -1
  61. package/static/app/assets/{permissionCopy-CNK2tfkz.js → permissionCopy-DFGEuU2d.js} +1 -1
  62. package/static/app/assets/{primitives-B6DzQC3H.js → primitives-EKxh12KR.js} +1 -1
  63. package/static/app/assets/search-BA5Ge197.js +1 -0
  64. package/static/app/assets/{share-2-BljIPAku.js → share-2-Drg0MPgx.js} +1 -1
  65. package/static/app/assets/{shield-alert-WDP2DSTM.js → shield-alert-CFKdCGM8.js} +1 -1
  66. package/static/app/assets/{sourceMeta-By2WIjlN.js → sourceMeta-BzqJiEPI.js} +1 -1
  67. package/static/app/assets/{textarea-5v8vtDlK.js → textarea-n_69mQP_.js} +1 -1
  68. package/static/app/assets/{useFocusTrap-ssiDeh6P.js → useFocusTrap-B0w4AxK1.js} +1 -1
  69. package/static/app/assets/{useMutation-Bi0PXQMC.js → useMutation-Dvcq6J6b.js} +1 -1
  70. package/static/app/assets/{workspace-BsxrRYQI.js → workspace-BgBHikYl.js} +1 -1
  71. package/static/app/index.html +1 -1
  72. package/static/sw.js +1 -1
  73. package/static/app/assets/arrow-left-DOnpwsVV.js +0 -1
  74. package/static/app/assets/circle-check-D44VI2ZE.js +0 -1
  75. package/static/app/assets/search-BwMK0hjs.js +0 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![CD Status](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/publish.yml/badge.svg)](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/publish.yml)
13
13
  [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
14
14
 
15
- ![v12.2.1 Living Brain walkthrough](output/release/v12.2.1/gifs/v12.2.1-living-brain-walkthrough.gif)
15
+ ![v12.3.0 Living Brain walkthrough](output/release/v12.3.0/gifs/v12.3.0-living-brain-walkthrough.gif)
16
16
 
17
17
  Lattice AI is a Digital Brain that lives on your computer. Chat, files,
18
18
  folders, notes, and web pages all land in one knowledge graph you own.
@@ -42,19 +42,19 @@ LTCAI # then open http://127.0.0.1:4825/app
42
42
 
43
43
  | | | |
44
44
  | --- | --- | --- |
45
- | ![Login](output/release/v12.2.1/screenshots/01-login.png) | ![Model install](output/release/v12.2.1/screenshots/03-install-load-progress.png) | ![Model library](output/release/v12.2.1/screenshots/07-model-library.png) |
45
+ | ![Login](output/release/v12.3.0/screenshots/01-login.png) | ![Model install](output/release/v12.3.0/screenshots/03-install-load-progress.png) | ![Model library](output/release/v12.3.0/screenshots/07-model-library.png) |
46
46
 
47
47
  Screenshot index:
48
- [output/release/v12.2.1/SCREENSHOT_INDEX.md](output/release/v12.2.1/SCREENSHOT_INDEX.md)
48
+ [output/release/v12.3.0/SCREENSHOT_INDEX.md](output/release/v12.3.0/SCREENSHOT_INDEX.md)
49
49
 
50
50
  ## What you can do
51
51
 
52
52
  | | |
53
53
  | --- | --- |
54
- | **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story ![Brain Chronicle](output/release/v12.2.1/screenshots/13-chronicle.png) | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory ![Brain Chat](output/release/v12.2.1/screenshots/04-brain-chat-home.png) |
55
- | **See how knowledge connects** — a real relationship graph, not a file list ![Memory Graph](output/release/v12.2.1/screenshots/05-memory-graph.png) | **Capture anything** — files, whole folders, notes, screenshots, web pages ![Capture](output/release/v12.2.1/screenshots/06-capture.png) |
56
- | **Automate with review** — agent changes become proposals you approve first ![Review Center](output/release/v12.2.1/screenshots/12-review-center.png) | **Pick a model in one click** — recommended local models for your hardware ![Recommended Models](output/release/v12.2.1/screenshots/02-recommended-models.png) |
57
- | **Watch a file become memory** — three named steps, not a pipeline diagram ![Material to memory](output/release/v12.2.1/screenshots/11-knowledge-journey.png) | **Say how much it may do alone** — one dial in plain words ![Settings](output/release/v12.2.1/screenshots/08-system.png) |
54
+ | **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story ![Brain Chronicle](output/release/v12.3.0/screenshots/13-chronicle.png) | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory ![Brain Chat](output/release/v12.3.0/screenshots/04-brain-chat-home.png) |
55
+ | **See how knowledge connects** — a real relationship graph, not a file list ![Memory Graph](output/release/v12.3.0/screenshots/05-memory-graph.png) | **Capture anything** — files, whole folders, notes, screenshots, web pages ![Capture](output/release/v12.3.0/screenshots/06-capture.png) |
56
+ | **Automate with review** — agent changes become proposals you approve first ![Review Center](output/release/v12.3.0/screenshots/12-review-center.png) | **Pick a model in one click** — recommended local models for your hardware ![Recommended Models](output/release/v12.3.0/screenshots/02-recommended-models.png) |
57
+ | **Watch a file become memory** — three named steps, not a pipeline diagram ![Material to memory](output/release/v12.3.0/screenshots/11-knowledge-journey.png) | **Say how much it may do alone** — one dial in plain words ![Settings](output/release/v12.3.0/screenshots/08-system.png) |
58
58
 
59
59
  ## Why this is yours
60
60
 
@@ -70,36 +70,42 @@ Screenshot index:
70
70
 
71
71
  ## Current Release
72
72
 
73
- The current release is **12.2.1 — True Count**:
74
-
75
- Search, skip, watch, and small-model answers now count what is actually
76
- there instead of dumping, rehashing, or pretending. The door is still
77
- **422 operations / 41 families** over a **20-route worker**. Cloud is
78
- still optional and the default is still local.
79
-
80
- - **Search does not dump the Brain.** A warm HNSW query is `COUNT(*)`
81
- then, if needed, the missing vectors only. Writes stay on one
82
- `GraphWriter`.
83
- - **A touch is a stamp, not a re-ingest.** Same bytes with a new mtime
84
- restamp provenance so the next scan skips by stamp.
85
- - **A vanished watched file leaves the graph.** Disk is never deleted.
86
- - **A thin summary is filled from the file that was read**, or held for
87
- review — never marked done with empty words.
88
- - **MCP tools stay in the compact nine-row list.** `api_key` cloud
89
- verifies with a live `GET /models` (no billed completion). Hash
90
- search is named as hash, with a path to a meaning model.
73
+ The current release is **12.3.0 — Live Wire**:
74
+
75
+ Model catalog routes, GGUF quantization tags, small-model tool/MCP calling,
76
+ and HTML generation/inspection/download are verified end-to-end against live
77
+ repositories and a loaded local model. The door is still **422 operations /
78
+ 41 families** over a **20-route worker**. Cloud is still optional and the
79
+ default is still local.
80
+
81
+ - **Verified Hugging Face GGUF tags & routes.** `ggml-org/gemma-4-*-GGUF`
82
+ uses `Q4_0`, `ggml-org/gpt-oss-20b-GGUF` uses `MXFP4`, and `Qwen3.5-9B` /
83
+ `Qwen3.6-35B-A3B` GGUF routes are wired across `ollama`, `lmstudio`, and
84
+ `llamacpp`.
85
+ - **Auxiliary GGUF filtering, `--mmproj` companion load, and shard checks.**
86
+ `mmproj-`/`mtp-`/`dflash-`/`eagle3-`/`imatrix` GGUFs are excluded from
87
+ primary weight selection, companion `mmproj-*.gguf` files are downloaded
88
+ for `llama-server`, and `model.safetensors.index.json` shards are verified.
89
+ - **Small-model tool calling & MCP calling hardening.** Expanded
90
+ `KNOWN_ACTIONS`, stringified `arguments` recovery, OpenAI `tool_calls`
91
+ array unwrapping, fenced HTML/code block salvage, and `adopt_named_args`
92
+ in `perform_action`.
93
+ - **HTML structure inspection & RFC 5987 UTF-8 download.**
94
+ `POST /tools/inspect_html` extracts `title`, `links`, `scripts`,
95
+ `stylesheets`, `images`, `forms`, and `headings`; `GET /tools/download`
96
+ decodes UTF-8 paths and sends `filename*=UTF-8''...`.
91
97
 
92
98
  Release notes live in [docs/releases/](docs/releases/). This version:
93
- [docs/releases/RELEASE_NOTES_v12.2.1.md](docs/releases/RELEASE_NOTES_v12.2.1.md).
99
+ [docs/releases/RELEASE_NOTES_v12.3.0.md](docs/releases/RELEASE_NOTES_v12.3.0.md).
94
100
  Guide: [RELEASE.md](RELEASE.md) · History: [docs/CHANGELOG.md](docs/CHANGELOG.md).
95
101
 
96
- Expected artifacts for 12.2.1 must use exact filenames:
102
+ Expected artifacts for 12.3.0 must use exact filenames:
97
103
 
98
- - `dist/ltcai-12.2.1-py3-none-any.whl`
99
- - `dist/ltcai-12.2.1.tar.gz`
100
- - `ltcai-12.2.1.tgz`
101
- - `dist/ltcai-12.2.1.vsix`
102
- - `src-tauri/target/release/bundle/dmg/Lattice AI_12.2.1_aarch64.dmg`
104
+ - `dist/ltcai-12.3.0-py3-none-any.whl`
105
+ - `dist/ltcai-12.3.0.tar.gz`
106
+ - `ltcai-12.3.0.tgz`
107
+ - `dist/ltcai-12.3.0.vsix`
108
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_12.3.0_aarch64.dmg`
103
109
 
104
110
  Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
105
111
 
@@ -170,7 +176,7 @@ Validation via `npm run lint`, `npm run test:unit`, `npm run test:visual`.
170
176
  pending-only, no Self-Model refiner, `delete_node` leaving `PART_OF`,
171
177
  review events silent without an owner, KG-api ingest text-only, two
172
178
  store cycles per review mutation) are listed with their reasons in
173
- [docs/releases/RELEASE_NOTES_v12.2.1.md](docs/releases/RELEASE_NOTES_v12.2.1.md)
179
+ [docs/releases/RELEASE_NOTES_v12.3.0.md](docs/releases/RELEASE_NOTES_v12.3.0.md)
174
180
  and prioritized in [docs/ROADMAP.md](docs/ROADMAP.md).
175
181
 
176
182
  ## Release History
@@ -182,6 +188,7 @@ same boundary. Earlier notes live in [docs/releases/](docs/releases/).
182
188
 
183
189
  | Version | Theme |
184
190
  | --- | --- |
191
+ | 12.3.0 | Live Wire |
185
192
  | 12.2.1 | True Count |
186
193
  | 12.2.0 | Small Voice |
187
194
  | 12.1.0 | Fast Path |
package/docs/CHANGELOG.md CHANGED
@@ -4,6 +4,40 @@ The top entry is either the current unreleased main-branch work or the current
4
4
  release line. Older entries are historical and may describe behavior as it
5
5
  existed at that release.
6
6
 
7
+ ## [12.3.0] - 2026-10-19 — Live Wire
8
+
9
+ ### Added
10
+ - Full HTML structure parser in `POST /tools/inspect_html`: extracts `title`,
11
+ `links`, `scripts`, `stylesheets`, `images`, `forms`, and `headings`
12
+ (`h1`–`h6`) with `MAX_FILE_BYTES` enforcement.
13
+ - RFC 5987 `filename*=UTF-8''...` `Content-Disposition` attachment headers and
14
+ UTF-8 percent-decoding in `GET /tools/download`.
15
+ - Verified GGUF routing for `mlx-community/Qwen3.5-9B-MLX-4bit`
16
+ (`unsloth/Qwen3.5-9B-GGUF`) and `mlx-community/Qwen3.6-35B-A3B-4bit`
17
+ (`ggml-org/Qwen3.6-35B-A3B-GGUF`) across `ollama`, `lmstudio`, and `llamacpp`.
18
+ - Companion `mmproj-*.gguf` download and `--mmproj` flag in
19
+ `ensure_llamacpp_server`, plus `is_auxiliary_gguf` filtering (`mmproj-`,
20
+ `mtp-`, `dflash-`, `eagle3-`, `imatrix`) and `_shards_complete` verification
21
+ for `model.safetensors.index.json`.
22
+ - Small-model tool/MCP calling tolerances in `lattice-agent`: expanded
23
+ `KNOWN_ACTIONS`, stringified `arguments` recovery (trailing comma, truncation,
24
+ Python dict literal), OpenAI `tool_calls` array unwrapping, fenced HTML/code
25
+ block salvage for `write_file`/`local_write`, and `adopt_named_args` in
26
+ `perform_action`.
27
+
28
+ ### Changed
29
+ - `_gguf_routes` now accepts per-repository `ollama_tag` (`Q4_0` for
30
+ `ggml-org/gemma-4-*-GGUF`, `MXFP4` for `ggml-org/gpt-oss-20b-GGUF`).
31
+ - Cloud and local provider defaults updated to current models (`grok-4.6`,
32
+ `Qwen/Qwen3.6-27B`, `qwen/qwen3.6-35b-a3b`, `x-ai/grok-4.6`,
33
+ `hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_0`, `google/gemma-4-12B-it`).
34
+
35
+ ### Fixed
36
+ - Removed nonexistent `mlx-community/bge-m3` from `LOCAL_MLX_MODELS` while
37
+ retaining `bge-m3` in `OLLAMA_EMBEDDING_MODELS`.
38
+ - Fixed Latin-1 byte-to-char corruption on non-ASCII percent-encoded paths in
39
+ `/tools/download`.
40
+
7
41
  ## [12.2.1] - 2026-08-29 — True Count
8
42
 
9
43
  ### Added
@@ -1,6 +1,6 @@
1
1
  # Community And Plugins
2
2
 
3
- Current release: **12.2.1 — True Count**.
3
+ Current release: **12.3.0 — Live Wire**.
4
4
 
5
5
  LatticeAI defines the path from a strong local-first framework (8.4.0
6
6
  action-aware baseline, 8.5.0 registry+DI hardening, 8.6.0 capture/navigation
@@ -3,7 +3,7 @@
3
3
  > **Status: canonical** — current contributor guidance, kept in sync with the
4
4
  > current release.
5
5
 
6
- Current release: **12.2.1 — True Count**.
6
+ Current release: **12.3.0 — Live Wire**.
7
7
 
8
8
  This document is the contributor onboarding path: how to boot the tree, where
9
9
  a change belongs, which gates will go red, and the house rules that keep the
@@ -80,7 +80,7 @@ worker interpreter with `LTCAI_PYTHON` when both exist.
80
80
  `rust/target/release/lattice-host`, then `rust/target/debug/lattice-host`. If
81
81
  none exist it runs `cargo build -p lattice-host` (debug). A stale
82
82
  `rust/target/release/lattice-host` wins over a current debug binary — pin or
83
- rebuild (`cargo build -p lattice-host --release`) if `-V` is not 12.2.1.
83
+ rebuild (`cargo build -p lattice-host --release`) if `-V` is not 12.3.0.
84
84
 
85
85
  Do not run `npm start` and `npm run dev` on the same port. The worker
86
86
  entrypoint defaults to `LATTICEAI_PORT` or **4825**, the same port as the
@@ -237,7 +237,7 @@ in `rust/`.
237
237
  Markdown) and `scripts/check_doc_status.mjs` (every relative link under the
238
238
  root canonical docs and `docs/**`). A red line is a broken relative path —
239
239
  fix the href or put the file where the href says. Canonical docs (this one
240
- included) must carry `Current release: **12.2.1 — …**` matching
240
+ included) must carry `Current release: **12.3.0 — …**` matching
241
241
  `package.json`; do not bump that marker here ahead of the release lane.
242
242
  `npm run docs:check-current` is the release-set version pin
243
243
  ([`scripts/check_current_release_docs.mjs`](../scripts/check_current_release_docs.mjs)).
@@ -248,7 +248,7 @@ changelog entries that mention old versions stay.
248
248
  ### Release-evidence binding
249
249
 
250
250
  `scripts/check_release_evidence_bound.mjs` (lint member 9) checks that
251
- `output/release/v12.2.1/SCREENSHOT_INDEX.md` still names the live
251
+ `output/release/v12.3.0/SCREENSHOT_INDEX.md` still names the live
252
252
  `static/app/asset-manifest.json` digest and the visual mock-server
253
253
  fingerprint. It exists so a later `npm run build:assets` cannot ship
254
254
  screenshots of an older UI, and so a mock-server edit cannot leave the
@@ -317,19 +317,19 @@ For user-facing, API, runtime, release, or packaging changes, check:
317
317
  appears
318
318
 
319
319
  The release-docs lane owns README / ARCHITECTURE / FEATURE_STATUS version
320
- bumps. Do not move this file's `Current release` marker off 12.2.1 ahead of
320
+ bumps. Do not move this file's `Current release` marker off 12.3.0 ahead of
321
321
  that lane.
322
322
 
323
323
  Release/publish examples must use exact target-version filenames. Do not
324
324
  document wildcard artifact upload commands.
325
325
 
326
- For 12.2.1 release work, exact artifacts are:
326
+ For 12.3.0 release work, exact artifacts are:
327
327
 
328
- - `dist/ltcai-12.2.1-py3-none-any.whl`
329
- - `dist/ltcai-12.2.1.tar.gz`
330
- - `ltcai-12.2.1.tgz`
331
- - `dist/ltcai-12.2.1.vsix`
332
- - `src-tauri/target/release/bundle/dmg/Lattice AI_12.2.1_aarch64.dmg`
328
+ - `dist/ltcai-12.3.0-py3-none-any.whl`
329
+ - `dist/ltcai-12.3.0.tar.gz`
330
+ - `ltcai-12.3.0.tgz`
331
+ - `dist/ltcai-12.3.0.vsix`
332
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_12.3.0_aarch64.dmg`
333
333
 
334
334
  The dmg is ad-hoc signed (effectively unsigned); `npm run release:validate`
335
335
  checks the names and presence, not a Developer ID signature.
@@ -1,6 +1,6 @@
1
1
  # Lattice AI Onboarding
2
2
 
3
- Current release: **12.2.1 — True Count**.
3
+ Current release: **12.3.0 — Live Wire**.
4
4
 
5
5
  The first-run goal is a five-minute path from "I opened the app" to "my Brain
6
6
  has a source, a question, and proof." This page is the product contract behind
@@ -1,4 +1,4 @@
1
- # Lattice AI — Operations Guide (v12.2.1)
1
+ # Lattice AI — Operations Guide (v12.3.0)
2
2
 
3
3
  > **Status: canonical** — kept in sync with the current release. Storage layout
4
4
  > below reflects the SQLite live Brain store and workspace scoping, not the
package/docs/ROADMAP.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **Status: reference** — point-in-time inventory, redated at v12.0.0. Not a
4
4
  > canonical current-release document; version gates do not bind it.
5
5
 
6
- As of **2026-08-29**, against the 12.2.1 — True Count tree. The rows below
6
+ As of **2026-10-19**, against the 12.3.0 — Live Wire tree. The rows below
7
7
  were gathered against 11.9.0 and re-checked when 12.0.0 shipped; what that
8
8
  release closed is marked closed rather than deleted, so the ledger still
9
9
  shows what was owed.
@@ -1,6 +1,6 @@
1
1
  # Lattice AI Trust Model
2
2
 
3
- Current release: **12.2.1 — True Count**.
3
+ Current release: **12.3.0 — Live Wire**.
4
4
 
5
5
  Lattice AI is local-first, explicit about external communication, and honest
6
6
  when a capability is unavailable.
@@ -1,6 +1,6 @@
1
1
  # Why Lattice AI Exists
2
2
 
3
- Current release: **12.2.1 — True Count**.
3
+ Current release: **12.3.0 — Live Wire**.
4
4
 
5
5
  **Lattice AI is a local-first Digital Brain that keeps your knowledge durable
6
6
  across any AI model.**
package/docs/kg-schema.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Knowledge Graph Schema
2
2
 
3
- Current release: **12.2.1 — True Count**.
3
+ Current release: **12.3.0 — Live Wire**.
4
4
 
5
5
  명세 출처: `lattice_ai_full_spec.pptx` 슬라이드 20·21·22
6
6
  구현: `lattice_brain/graph/schema.py`
@@ -31,7 +31,7 @@ from .multimodal import (
31
31
  transcribe_audio,
32
32
  )
33
33
 
34
- __version__ = "12.2.1"
34
+ __version__ = "12.3.0"
35
35
 
36
36
  __all__ = [
37
37
  "AudioFacts",
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "12.2.1"
3
+ __version__ = "12.3.0"
@@ -58,7 +58,6 @@ LOCAL_MLX_MODELS: Tuple[Tuple[str, int, bool], ...] = (
58
58
  ("mlx-community/multilingual-e5-large-mlx", 1024, True),
59
59
  ("mlx-community/snowflake-arctic-embed-l-v2.0-8bit", 1024, False),
60
60
  ("mlx-community/embeddinggemma-300m-4bit", 768, False),
61
- ("mlx-community/bge-m3", 1024, False),
62
61
  )
63
62
 
64
63
  #: Ollama model names that are embedders rather than chat models.
@@ -256,7 +256,7 @@ def _gemma4_runtime_candidates(raw_model_id: str) -> List[Dict[str, Any]]:
256
256
  {
257
257
  "engine": "ollama",
258
258
  "runtime": "Ollama GGUF",
259
- "load_id": "ollama:hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_K_M",
259
+ "load_id": "ollama:hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_0",
260
260
  "available": None,
261
261
  "role": "gguf_local_server",
262
262
  },
@@ -354,7 +354,7 @@ def model_runtime_compatibility(model_id: str, engine: Optional[str] = None) ->
354
354
  ],
355
355
  "alternatives": [
356
356
  {"id": "mlx-community/gemma-4-26b-a4b-it-4bit", "name": "Gemma 4 26B A4B", "engine": "local_mlx"},
357
- {"id": "ollama:hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_K_M", "name": "Gemma 4 12B GGUF", "engine": "ollama"},
357
+ {"id": "ollama:hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_0", "name": "Gemma 4 12B GGUF", "engine": "ollama"},
358
358
  {"id": "lmstudio:ggml-org/gemma-4-12B-it-GGUF", "name": "Gemma 4 12B GGUF", "engine": "lmstudio"},
359
359
  ],
360
360
  "action": "Runtime update needed",
@@ -27,29 +27,28 @@ OPENAI_COMPATIBLE_PROVIDERS = {
27
27
  "together": {
28
28
  "env_key": "TOGETHER_API_KEY",
29
29
  "base_url": "https://api.together.xyz/v1",
30
- "default_model": "Qwen/Qwen3-VL-32B-Instruct",
30
+ "default_model": "Qwen/Qwen3.6-27B",
31
31
  },
32
32
  "xai": {
33
33
  "env_key": "XAI_API_KEY",
34
34
  "base_url": "https://api.x.ai/v1",
35
35
  # ``grok-beta`` was xAI's 2024 preview id and has been decommissioned;
36
- # a request naming it now 404s at the provider. ``grok-4.5`` is the
37
- # current flagship on api.x.ai and is multimodal, which is also why the
38
- # separate ``grok-vision-beta`` row below is gone rather than renamed.
39
- "default_model": "grok-4.5",
36
+ # a request naming it now 404s at the provider. ``grok-4.6`` is the
37
+ # current flagship on api.x.ai and matches the Rust cloud adapter.
38
+ "default_model": "grok-4.6",
40
39
  },
41
40
  "ollama": {
42
41
  "env_key": "OLLAMA_API_KEY",
43
42
  "base_url_env": "OLLAMA_BASE_URL",
44
43
  "base_url": "http://localhost:11434/v1",
45
- "default_model": "hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_K_M",
44
+ "default_model": "hf.co/ggml-org/gemma-4-12B-it-GGUF:Q4_0",
46
45
  "api_key_fallback": "ollama",
47
46
  },
48
47
  "vllm": {
49
48
  "env_key": "VLLM_API_KEY",
50
49
  "base_url_env": "VLLM_BASE_URL",
51
50
  "base_url": "http://localhost:8000/v1",
52
- "default_model": "Qwen/Qwen3-VL-8B-Instruct",
51
+ "default_model": "google/gemma-4-12B-it",
53
52
  "api_key_fallback": "vllm",
54
53
  },
55
54
  "lmstudio": {
@@ -85,9 +84,9 @@ PROVIDER_MODEL_CATALOG = {
85
84
  {"id": "anthropic/claude-opus-4.7", "name": "Claude Opus 4.7 via OpenRouter", "family": "Claude"},
86
85
  {"id": "anthropic/claude-sonnet-4.6", "name": "Claude Sonnet 4.6 via OpenRouter", "family": "Claude"},
87
86
  {"id": "anthropic/claude-haiku-4.5", "name": "Claude Haiku 4.5 via OpenRouter", "family": "Claude"},
88
- {"id": "qwen/qwen3-vl-235b-a22b-instruct", "name": "Qwen3-VL 235B A22B via OpenRouter", "family": "Qwen"},
87
+ {"id": "qwen/qwen3.6-35b-a3b", "name": "Qwen3.6 35B A3B via OpenRouter", "family": "Qwen"},
89
88
  {"id": "google/gemma-4-12b-it", "name": "Gemma 4 12B via OpenRouter", "family": "Gemma"},
90
- {"id": "x-ai/grok-4.5", "name": "Grok 4.5 via OpenRouter", "family": "Grok"},
89
+ {"id": "x-ai/grok-4.6", "name": "Grok 4.6 via OpenRouter", "family": "Grok"},
91
90
  {"id": "meta-llama/llama-4-scout-17b-16e-instruct", "name": "Llama 4 Scout via OpenRouter", "family": "Llama"},
92
91
  {"id": "google/gemini-2.5-flash", "name": "Gemini 2.5 Flash via OpenRouter", "family": "Gemini"},
93
92
  ],
@@ -95,7 +94,7 @@ PROVIDER_MODEL_CATALOG = {
95
94
  {"id": "meta-llama/llama-4-scout-17b-16e-instruct", "name": "Llama 4 Scout", "family": "Llama"},
96
95
  ],
97
96
  "together": [
98
- {"id": "Qwen/Qwen3-VL-32B-Instruct", "name": "Qwen3-VL 32B", "family": "Qwen"},
97
+ {"id": "Qwen/Qwen3.6-27B", "name": "Qwen3.6 27B", "family": "Qwen"},
99
98
  {"id": "google/gemma-4-12b-it", "name": "Gemma 4 12B", "family": "Gemma"},
100
99
  {"id": "meta-llama/Llama-4-Scout-17B-16E-Instruct", "name": "Llama 4 Scout", "family": "Llama"},
101
100
  ],
@@ -105,7 +104,7 @@ PROVIDER_MODEL_CATALOG = {
105
104
  # (grok-beta / grok-vision-beta) are not carried as fallbacks: a model
106
105
  # the provider no longer serves is not compatibility, it is a 404 the
107
106
  # user has to discover for themselves.
108
- {"id": "grok-4.5", "name": "Grok 4.5", "family": "Grok"},
107
+ {"id": "grok-4.6", "name": "Grok 4.6", "family": "Grok"},
109
108
  ],
110
109
  }
111
110
 
@@ -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.2.1"
22
+ ARCHITECTURE_VERSION_TARGET = "12.3.0"
23
23
 
24
24
  PREFERRED_REFACTORING_ORDER = [
25
25
  "agent-runtime",
@@ -300,7 +300,7 @@ _REGISTRY: List[ModelCapability] = [
300
300
  architecture="qwen3_5",
301
301
  download_size_gb=5.98,
302
302
  quantization="4bit",
303
- provider_hints=["local_mlx", "vllm"],
303
+ provider_hints=["local_mlx", "ollama", "vllm", "lmstudio", "llamacpp"],
304
304
  download_strategy="hf_hub",
305
305
  load_strategy="mlx_vlm",
306
306
  hardware=HardwareProfile(
@@ -381,7 +381,7 @@ _REGISTRY: List[ModelCapability] = [
381
381
  architecture="qwen3_5_moe",
382
382
  download_size_gb=20.43,
383
383
  quantization="4bit",
384
- provider_hints=["local_mlx", "vllm"],
384
+ provider_hints=["local_mlx", "ollama", "vllm", "lmstudio", "llamacpp"],
385
385
  download_strategy="hf_hub",
386
386
  load_strategy="mlx_vlm",
387
387
  hardware=HardwareProfile(
@@ -102,11 +102,17 @@ ENGINE_MODEL_CATALOG: Dict[str, List[Dict[str, Any]]] = {}
102
102
  # gated — the download could never succeed without Hub credentials.
103
103
 
104
104
 
105
- def _gguf_routes(mlx_repo: str, gguf_repo: str, hf_repo: str) -> Dict[str, str]:
105
+ def _gguf_routes(
106
+ mlx_repo: str,
107
+ gguf_repo: str,
108
+ hf_repo: str,
109
+ *,
110
+ ollama_tag: str = "Q4_K_M",
111
+ ) -> Dict[str, str]:
106
112
  """One model's engine map: MLX weights, a GGUF repo, and the upstream HF repo."""
107
113
  return {
108
114
  "local_mlx": mlx_repo,
109
- "ollama": f"hf.co/{gguf_repo}:Q4_K_M",
115
+ "ollama": f"hf.co/{gguf_repo}:{ollama_tag}",
110
116
  "vllm": hf_repo,
111
117
  "lmstudio": gguf_repo,
112
118
  "llamacpp": gguf_repo,
@@ -119,36 +125,38 @@ _ENGINE_ROUTES: Dict[str, Dict[str, str]] = {
119
125
  ),
120
126
  "mlx-community/gemma-4-e2b-it-4bit": _gguf_routes(
121
127
  "mlx-community/gemma-4-e2b-it-4bit", "ggml-org/gemma-4-E2B-it-GGUF", "google/gemma-4-E2B-it",
128
+ ollama_tag="Q4_0",
122
129
  ),
123
130
  "mlx-community/gemma-4-e4b-it-4bit": _gguf_routes(
124
131
  "mlx-community/gemma-4-e4b-it-4bit", "ggml-org/gemma-4-E4B-it-GGUF", "google/gemma-4-E4B-it",
132
+ ollama_tag="Q4_0",
125
133
  ),
126
134
  "mlx-community/gemma-4-12B-it-4bit": _gguf_routes(
127
135
  "mlx-community/gemma-4-12B-it-4bit", "ggml-org/gemma-4-12B-it-GGUF", "google/gemma-4-12B-it",
136
+ ollama_tag="Q4_0",
128
137
  ),
129
138
  "mlx-community/gemma-4-26b-a4b-it-4bit": _gguf_routes(
130
139
  "mlx-community/gemma-4-26b-a4b-it-4bit", "ggml-org/gemma-4-26B-A4B-it-GGUF",
131
140
  "google/gemma-4-26B-A4B-it",
141
+ ollama_tag="Q4_0",
132
142
  ),
133
143
  "mlx-community/gemma-4-31b-it-4bit": _gguf_routes(
134
144
  "mlx-community/gemma-4-31b-it-4bit", "ggml-org/gemma-4-31B-it-GGUF", "google/gemma-4-31B-it",
145
+ ollama_tag="Q4_0",
135
146
  ),
136
147
  "mlx-community/Qwen3.6-27B-4bit": _gguf_routes(
137
148
  "mlx-community/Qwen3.6-27B-4bit", "ggml-org/Qwen3.6-27B-GGUF", "Qwen/Qwen3.6-27B",
138
149
  ),
139
150
  "mlx-community/gpt-oss-20b-MXFP4-Q8": _gguf_routes(
140
151
  "mlx-community/gpt-oss-20b-MXFP4-Q8", "ggml-org/gpt-oss-20b-GGUF", "openai/gpt-oss-20b",
152
+ ollama_tag="MXFP4",
153
+ ),
154
+ "mlx-community/Qwen3.5-9B-MLX-4bit": _gguf_routes(
155
+ "mlx-community/Qwen3.5-9B-MLX-4bit", "unsloth/Qwen3.5-9B-GGUF", "Qwen/Qwen3.5-9B",
156
+ ),
157
+ "mlx-community/Qwen3.6-35B-A3B-4bit": _gguf_routes(
158
+ "mlx-community/Qwen3.6-35B-A3B-4bit", "ggml-org/Qwen3.6-35B-A3B-GGUF", "Qwen/Qwen3.6-35B-A3B",
141
159
  ),
142
- # No community GGUF build verified for these two, so they offer the MLX
143
- # weights and the upstream repo only rather than a route that would 404.
144
- "mlx-community/Qwen3.5-9B-MLX-4bit": {
145
- "local_mlx": "mlx-community/Qwen3.5-9B-MLX-4bit",
146
- "vllm": "Qwen/Qwen3.5-9B",
147
- },
148
- "mlx-community/Qwen3.6-35B-A3B-4bit": {
149
- "local_mlx": "mlx-community/Qwen3.6-35B-A3B-4bit",
150
- "vllm": "Qwen/Qwen3.6-35B-A3B",
151
- },
152
160
  }
153
161
 
154
162
  # Names people actually type that are not the repo's own short name. Kept
@@ -332,6 +332,10 @@ def ensure_llamacpp_server(model_name: str) -> None:
332
332
  hf_model_dir,
333
333
  hf_model_ready,
334
334
  )
335
+ from latticeai.services.model_runtime.download import (
336
+ GGUF_QUANT_PREFERENCE,
337
+ is_auxiliary_gguf,
338
+ )
335
339
 
336
340
  served_models = get_openai_compatible_server_models("llamacpp")
337
341
  if model_name in served_models:
@@ -347,23 +351,31 @@ def ensure_llamacpp_server(model_name: str) -> None:
347
351
  download_hf_model(model_name, "llamacpp")
348
352
 
349
353
  gguf_files = sorted(hf_model_dir(model_name).rglob("*.gguf"))
350
- if not gguf_files:
354
+ primary_ggufs = [p for p in gguf_files if not is_auxiliary_gguf(p.name)]
355
+ if not primary_ggufs:
351
356
  raise ModelRuntimeError(status_code=500, detail="다운로드된 GGUF 파일을 찾지 못했습니다.")
352
357
 
353
- preferred = next((p for p in gguf_files if "q4_k_m" in p.name.lower()), None)
354
- model_file = preferred or gguf_files[0]
358
+ preferred = next(
359
+ (p for pref in GGUF_QUANT_PREFERENCE for p in primary_ggufs if pref in p.name.lower()),
360
+ None,
361
+ )
362
+ model_file = preferred or primary_ggufs[0]
363
+ command = [
364
+ "llama-server",
365
+ "-m",
366
+ str(model_file),
367
+ "--alias",
368
+ model_name,
369
+ "--host",
370
+ "127.0.0.1",
371
+ "--port",
372
+ "8080",
373
+ ]
374
+ mmprojs = [p for p in gguf_files if p.name.lower().startswith("mmproj-")]
375
+ if mmprojs:
376
+ command.extend(["--mmproj", str(mmprojs[0])])
355
377
  LOCAL_SERVER_PROCESSES["llamacpp"] = subprocess.Popen(
356
- [
357
- "llama-server",
358
- "-m",
359
- str(model_file),
360
- "--alias",
361
- model_name,
362
- "--host",
363
- "127.0.0.1",
364
- "--port",
365
- "8080",
366
- ],
378
+ command,
367
379
  stdout=subprocess.DEVNULL,
368
380
  stderr=subprocess.DEVNULL,
369
381
  start_new_session=True,