ltcai 12.2.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.
- package/README.md +85 -84
- package/docs/CHANGELOG.md +30 -4
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +11 -11
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +1 -1
- package/docs/ROADMAP.md +8 -8
- package/docs/TRUST_MODEL.md +2 -2
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/kg-schema.md +1 -1
- package/lattice_brain/__init__.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/core/vector_index/hnsw.py +49 -10
- package/latticeai/core/vector_index/sidecar.py +120 -31
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/product_readiness.py +2 -2
- package/package.json +1 -1
- package/scripts/check_current_release_docs.mjs +1 -1
- package/scripts/release_screen_claims.json +11 -0
- package/src-tauri/Cargo.lock +10 -10
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +44 -44
- package/static/app/assets/{Act-BjGgeuQd.js → Act-DC676bqE.js} +2 -2
- package/static/app/assets/{AdminConsole-C6hcJGMr.js → AdminConsole-aCxQgD2L.js} +1 -1
- package/static/app/assets/{Brain-CNQnIaA8.js → Brain-Dbd0xvsc.js} +2 -2
- package/static/app/assets/{BrainHome-CGJ6O69l.js → BrainHome-N00B-MAJ.js} +1 -1
- package/static/app/assets/{BrainSignals-DONPljxz.js → BrainSignals-CNA0d6xS.js} +1 -1
- package/static/app/assets/{Capture-BMCC5544.js → Capture-BB19fo7P.js} +1 -1
- package/static/app/assets/{Chronicle-DF6sOonx.js → Chronicle-D8p3dqxZ.js} +1 -1
- package/static/app/assets/{CommandPalette-DiWyutdM.js → CommandPalette-uVFYAa-6.js} +1 -1
- package/static/app/assets/{DigitalBrainExplorer-BL3V6Dqz.js → DigitalBrainExplorer-mH6ZSuvK.js} +1 -1
- package/static/app/assets/{Library-B-ue9hXL.js → Library-0q8Sdke7.js} +1 -1
- package/static/app/assets/{LivingBrain-b1RiM5Rh.js → LivingBrain-wess-qJZ.js} +1 -1
- package/static/app/assets/ProductFlow-DeBGF6qz.js +1 -0
- package/static/app/assets/{ReviewCard-D1fGTEn7.js → ReviewCard-DyTrDpy0.js} +1 -1
- package/static/app/assets/{RunsListPanel-DAirtLkS.js → RunsListPanel-CHJv2Qyw.js} +1 -1
- package/static/app/assets/{System-BEI1eoC4.js → System-CyKGHQrW.js} +1 -1
- package/static/app/assets/{WorkflowGraph-qrI6GU4R.js → WorkflowGraph-B5nKCCGa.js} +1 -1
- package/static/app/assets/{WorkflowsPanel-CIMNTw-O.js → WorkflowsPanel-C7RZNRGo.js} +2 -2
- package/static/app/assets/{actHelpers-BMukIRnQ.js → actHelpers-6MYDH2kW.js} +1 -1
- package/static/app/assets/arrow-left-DOnpwsVV.js +1 -0
- package/static/app/assets/{bot-Dkd-DbiP.js → bot-Dm3fmXAE.js} +1 -1
- package/static/app/assets/{brain-BsexlNOA.js → brain-C2XwdQL1.js} +1 -1
- package/static/app/assets/{button-BA0N_zId.js → button-xXPeemQr.js} +1 -1
- package/static/app/assets/circle-check-D44VI2ZE.js +1 -0
- package/static/app/assets/{circle-pause-918Kuvk0.js → circle-pause-B_lmNicW.js} +1 -1
- package/static/app/assets/{circle-play-CS0IbVDV.js → circle-play-DSYCP0RD.js} +1 -1
- package/static/app/assets/{cpu-BpvoWsjk.js → cpu-D7x-dtxi.js} +1 -1
- package/static/app/assets/{download-BvkMLLLN.js → download-BHuJr-5V.js} +1 -1
- package/static/app/assets/{folder-open-YmGugIBf.js → folder-open-BiO31EwS.js} +1 -1
- package/static/app/assets/{hard-drive-BOzmS-cq.js → hard-drive-CFEaZ-wP.js} +1 -1
- package/static/app/assets/{index-CfeqZ9Ri.js → index-DCT79wzR.js} +3 -3
- package/static/app/assets/{input-CFfCfMjO.js → input-D3YrgxvO.js} +1 -1
- package/static/app/assets/{link-2-CcYzeM7M.js → link-2-3O-By3qc.js} +1 -1
- package/static/app/assets/{permissionCopy-B23r24oX.js → permissionCopy-CNK2tfkz.js} +1 -1
- package/static/app/assets/{primitives-BDryQl6H.js → primitives-B6DzQC3H.js} +1 -1
- package/static/app/assets/search-BwMK0hjs.js +1 -0
- package/static/app/assets/{share-2-B-gPv2ec.js → share-2-BljIPAku.js} +1 -1
- package/static/app/assets/{shield-alert-CfyRO1p0.js → shield-alert-WDP2DSTM.js} +1 -1
- package/static/app/assets/{sourceMeta-C4LDEy1S.js → sourceMeta-By2WIjlN.js} +1 -1
- package/static/app/assets/{textarea-BdVMYEb1.js → textarea-5v8vtDlK.js} +1 -1
- package/static/app/assets/{useFocusTrap-CV73DLHn.js → useFocusTrap-ssiDeh6P.js} +1 -1
- package/static/app/assets/{useMutation-B8QKq2NW.js → useMutation-Bi0PXQMC.js} +1 -1
- package/static/app/assets/workspace-BsxrRYQI.js +1 -0
- package/static/app/index.html +1 -1
- package/static/sw.js +1 -1
- package/static/app/assets/ProductFlow-wZIKJW7G.js +0 -1
- package/static/app/assets/arrow-left-iVa1goff.js +0 -1
- package/static/app/assets/circle-check-BxaDWjPR.js +0 -1
- package/static/app/assets/search-DHsPwmPw.js +0 -1
- package/static/app/assets/workspace-BmfVs66W.js +0 -1
package/README.md
CHANGED
|
@@ -12,100 +12,97 @@
|
|
|
12
12
|
[](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/publish.yml)
|
|
13
13
|
[](LICENSE)
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
Lattice AI is a Digital Brain that lives on your computer. Chat, files,
|
|
18
|
+
folders, notes, and web pages all land in one knowledge graph you own.
|
|
19
|
+
The default is local. Cloud is optional, and nothing leaves the machine
|
|
20
|
+
without your consent.
|
|
21
21
|
|
|
22
22
|
대화·파일·폴더·웹페이지가 전부 내 컴퓨터 안의 지식 그래프로 쌓입니다.
|
|
23
|
-
기본은 로컬이고, 클라우드는
|
|
23
|
+
기본은 로컬이고, 클라우드는 선택입니다.
|
|
24
24
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
| | |
|
|
28
|
-
| --- | --- |
|
|
29
|
-
| **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story, rewindable to any past moment  | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory  |
|
|
30
|
-
| **See how knowledge connects** — a real relationship graph, not a file list  | **Capture anything** — files, whole folders, notes, screenshots, web pages  |
|
|
31
|
-
| **Automate with review** — agent changes become proposals you approve first  | **Pick a model in one click** — recommended local models for your hardware  |
|
|
32
|
-
| **Watch a file become memory** — three named steps, not a pipeline diagram  | **Say how much it may do alone** — one dial in plain words; dangerous actions stay blocked either way  |
|
|
33
|
-
|
|
34
|
-
## Why Lattice AI
|
|
35
|
-
|
|
36
|
-
- **Own your memory** — knowledge lives in a local SQLite Brain you can back up,
|
|
37
|
-
export, inspect, and restore (`.latticebrain` encrypted archive).
|
|
38
|
-
- **Model-independent** — switch between local MLX models and cloud models
|
|
39
|
-
without rebuilding context from zero.
|
|
40
|
-
- **Honest by design** — the Brain tells you when retrieval context is limited,
|
|
41
|
-
when captured pages extracted poorly, and when the vector index is catching up.
|
|
42
|
-
- **Safe automation** — automations are consent-first drafts; edits to existing
|
|
43
|
-
content always pass through a reviewable proposal with a diff.
|
|
44
|
-
- **Runs on the model your machine can hold** — the loop measures what a model
|
|
45
|
-
can actually produce and adapts: a model too small to emit a tool call is
|
|
46
|
-
walked through numbered choices instead, with the same permission gates,
|
|
47
|
-
snapshots and sanitizers as every other profile.
|
|
48
|
-
|
|
49
|
-
매번 AI에게 프로젝트 맥락을 다시 설명하고 있다면, 지식이 여러 서비스에 흩어져
|
|
50
|
-
있다면, 그 기억을 특정 회사가 아니라 내가 소유하고 싶다면 — Lattice AI가 그
|
|
51
|
-
브레인입니다.
|
|
52
|
-
|
|
53
|
-
## Quick Start
|
|
25
|
+
## Install
|
|
54
26
|
|
|
55
27
|
```bash
|
|
56
28
|
pip install ltcai # or: npm install -g ltcai
|
|
57
29
|
LTCAI # then open http://127.0.0.1:4825/app
|
|
58
30
|
```
|
|
59
31
|
|
|
60
|
-
Apple Silicon local models: `pip install "ltcai[local]"
|
|
61
|
-
|
|
32
|
+
- Apple Silicon local models: `pip install "ltcai[local]"`
|
|
33
|
+
- Mac app: the `.dmg` on each [GitHub Release](https://github.com/TaeSooPark-PTS/LatticeAI/releases)
|
|
34
|
+
- Editor: the [VS Code / Cursor / Open VSX](https://marketplace.visualstudio.com/items?itemName=parktaesoo.ltcai) extension
|
|
62
35
|
|
|
63
|
-
First
|
|
36
|
+
## First five minutes
|
|
37
|
+
|
|
38
|
+
1. Open the app and sign in as the owner.
|
|
39
|
+
2. Pick a recommended local model for this computer.
|
|
40
|
+
3. Drop a folder, a file, or a note into Capture.
|
|
41
|
+
4. Ask the Brain a question in your own words.
|
|
64
42
|
|
|
65
43
|
| | | |
|
|
66
44
|
| --- | --- | --- |
|
|
67
|
-
|  |  |  |
|
|
46
|
+
|
|
47
|
+
Screenshot index:
|
|
48
|
+
[output/release/v12.2.1/SCREENSHOT_INDEX.md](output/release/v12.2.1/SCREENSHOT_INDEX.md)
|
|
68
49
|
|
|
69
|
-
|
|
70
|
-
|
|
50
|
+
## What you can do
|
|
51
|
+
|
|
52
|
+
| | |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| **See your Brain's story in time** — a growth curve, an activity heatmap, and each day's story  | **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory  |
|
|
55
|
+
| **See how knowledge connects** — a real relationship graph, not a file list  | **Capture anything** — files, whole folders, notes, screenshots, web pages  |
|
|
56
|
+
| **Automate with review** — agent changes become proposals you approve first  | **Pick a model in one click** — recommended local models for your hardware  |
|
|
57
|
+
| **Watch a file become memory** — three named steps, not a pipeline diagram  | **Say how much it may do alone** — one dial in plain words  |
|
|
58
|
+
|
|
59
|
+
## Why this is yours
|
|
60
|
+
|
|
61
|
+
- **The memory stays.** Knowledge lives in a local SQLite Brain you can back up, export, inspect, and restore (`.latticebrain`).
|
|
62
|
+
- **The model is replaceable.** Switch local MLX and optional cloud without rebuilding context from zero.
|
|
63
|
+
- **It says when it does not know.** Thin retrieval, a poor page extract, or hash-only search is named, not dressed as meaning.
|
|
64
|
+
- **Edits wait for you.** New files can land with little friction. Changing or deleting existing files becomes a proposal with a diff.
|
|
65
|
+
- **Small models can still act.** A 2B-class local model can call tools and skills; a model too small to emit JSON is walked through numbered choices.
|
|
66
|
+
|
|
67
|
+
매번 AI에게 프로젝트 맥락을 다시 설명하고 있다면, 지식이 여러 서비스에 흩어져
|
|
68
|
+
있다면, 그 기억을 특정 회사가 아니라 내가 소유하고 싶다면 — Lattice AI가 그
|
|
69
|
+
브레인입니다.
|
|
71
70
|
|
|
72
71
|
## Current Release
|
|
73
72
|
|
|
74
|
-
The current release is **12.2.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
- **
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- **
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
[
|
|
96
|
-
|
|
97
|
-
Expected artifacts for 12.2.
|
|
98
|
-
|
|
99
|
-
- `dist/ltcai-12.2.
|
|
100
|
-
- `dist/ltcai-12.2.
|
|
101
|
-
- `ltcai-12.2.
|
|
102
|
-
- `dist/ltcai-12.2.
|
|
103
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_12.2.
|
|
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.
|
|
91
|
+
|
|
92
|
+
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).
|
|
94
|
+
Guide: [RELEASE.md](RELEASE.md) · History: [docs/CHANGELOG.md](docs/CHANGELOG.md).
|
|
95
|
+
|
|
96
|
+
Expected artifacts for 12.2.1 must use exact filenames:
|
|
97
|
+
|
|
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
103
|
|
|
105
104
|
Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
|
|
106
105
|
|
|
107
|
-
Release notes: [RELEASE.md](RELEASE.md) · Full history: [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
|
108
|
-
|
|
109
106
|
## Architecture At A Glance
|
|
110
107
|
|
|
111
108
|
One Rust server on localhost is the source of truth: `lattice-host` answers
|
|
@@ -132,8 +129,9 @@ Validation via `npm run lint`, `npm run test:unit`, `npm run test:visual`.
|
|
|
132
129
|
migration tooling is not part of the 12.1.0 worker.
|
|
133
130
|
- Docker, model downloads, cloud model calls, Brain Network, and update checks
|
|
134
131
|
require explicit user action. Cloud is optional: `cli_oauth` (`agy` /
|
|
135
|
-
`grok`) was live-checked at zero billing; the `api_key` path
|
|
136
|
-
|
|
132
|
+
`grok`) was live-checked at zero billing; the `api_key` path probes
|
|
133
|
+
`GET /models` with the key and fail-closes if the provider is
|
|
134
|
+
unreachable — it does not run a billed completion to verify.
|
|
137
135
|
- **The Telegram bridge was removed in 11.6.0** — it lived in the platform code
|
|
138
136
|
that became the AI worker. **SSO/OIDC login and callback flows were removed
|
|
139
137
|
with it**; the configuration surface remains and password login is native.
|
|
@@ -153,16 +151,18 @@ Validation via `npm run lint`, `npm run test:unit`, `npm run test:visual`.
|
|
|
153
151
|
100%-lines-and-branches gate was removed). The enforced claim is the
|
|
154
152
|
floor, not whatever a given run measures.
|
|
155
153
|
- **Small-model *content* quality is gated honestly.** With the `guided`
|
|
156
|
-
profile even a 0.5B model writes the requested file and reaches DONE
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
profile even a 0.5B model writes the requested file and reaches DONE.
|
|
155
|
+
A requested summary is filled from the file that was actually read;
|
|
156
|
+
if those words are still missing the run is held for review, not
|
|
157
|
+
marked done.
|
|
159
158
|
- Vector search env still defaults to `brute` — exact and byte-compatible
|
|
160
159
|
on a small Brain. At 512+ vectors with a bound worker sidecar it tries
|
|
161
160
|
`hnsw+rescore` first and falls back to the exact scan if the sidecar
|
|
162
161
|
cannot answer. `LATTICEAI_VECTOR_INDEX=hnsw` is still the explicit
|
|
163
162
|
opt-in.
|
|
164
|
-
- Watch
|
|
165
|
-
|
|
163
|
+
- Watch prune removes vanished files from the **graph**, never from
|
|
164
|
+
disk. A one-shot folder ingest still reports vanished files and
|
|
165
|
+
waits for the confirmed prune door.
|
|
166
166
|
- The macOS dmg is ad-hoc signed — effectively unsigned — so first launch
|
|
167
167
|
needs the usual Gatekeeper step.
|
|
168
168
|
- Pointer-control tools execute in the worker and are installed with
|
|
@@ -170,18 +170,19 @@ Validation via `npm run lint`, `npm run test:unit`, `npm run test:visual`.
|
|
|
170
170
|
pending-only, no Self-Model refiner, `delete_node` leaving `PART_OF`,
|
|
171
171
|
review events silent without an owner, KG-api ingest text-only, two
|
|
172
172
|
store cycles per review mutation) are listed with their reasons in
|
|
173
|
-
[RELEASE_NOTES_v12.2.
|
|
174
|
-
[docs/ROADMAP.md](docs/ROADMAP.md).
|
|
173
|
+
[docs/releases/RELEASE_NOTES_v12.2.1.md](docs/releases/RELEASE_NOTES_v12.2.1.md)
|
|
174
|
+
and prioritized in [docs/ROADMAP.md](docs/ROADMAP.md).
|
|
175
175
|
|
|
176
176
|
## Release History
|
|
177
177
|
|
|
178
178
|
Public history starts at 11.0.0. 11.6.0 rebuilt the product server in Rust and
|
|
179
179
|
reduced the Python package to an AI worker, so a 10.x or 9.x install is a
|
|
180
180
|
different program; `SECURITY.md` supports only 11.x, and this table states the
|
|
181
|
-
same boundary. Earlier notes
|
|
181
|
+
same boundary. Earlier notes live in [docs/releases/](docs/releases/).
|
|
182
182
|
|
|
183
183
|
| Version | Theme |
|
|
184
184
|
| --- | --- |
|
|
185
|
+
| 12.2.1 | True Count |
|
|
185
186
|
| 12.2.0 | Small Voice |
|
|
186
187
|
| 12.1.0 | Fast Path |
|
|
187
188
|
| 12.0.0 | Open House |
|
|
@@ -199,4 +200,4 @@ same boundary. Earlier notes stay in the tree as `RELEASE_NOTES_v*.md` files.
|
|
|
199
200
|
| 11.0.1 | Both Branches |
|
|
200
201
|
| 11.0.0 | Full Measure |
|
|
201
202
|
|
|
202
|
-
Per-release details: [RELEASE_NOTES.md](RELEASE_NOTES.md)
|
|
203
|
+
Per-release details: [RELEASE_NOTES.md](RELEASE_NOTES.md) · folder: [docs/releases/](docs/releases/)
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,32 @@ 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.2.1] - 2026-08-29 — True Count
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- HNSW sidecar COUNT+delta load: a warm query never dumps `vector_embeddings`;
|
|
11
|
+
growth fetches missing ids only and appends.
|
|
12
|
+
- Skip-by-hash restamps size/mtime on the existing provenance row via
|
|
13
|
+
`GraphWriter`.
|
|
14
|
+
- Watch prune: a vanished watched file is removed from the graph
|
|
15
|
+
(`delete_document_tree`, confirm=true). Disk is never deleted.
|
|
16
|
+
- `complete_a_summary`: a thin "I summarized" answer is filled from the
|
|
17
|
+
`read_file` / `mcp.read_file` result already on the transcript.
|
|
18
|
+
- Compact catalog CORE now keeps `mcp.grep`, `mcp.list_dir`, `mcp.read_file`,
|
|
19
|
+
`mcp.knowledge_search` through the nine-row cap.
|
|
20
|
+
- `api_key` cloud `GET /models` probe (no completion). Unreachable keys
|
|
21
|
+
fail-close status.
|
|
22
|
+
- First-run and library copy name hash search as hash, with a path to a
|
|
23
|
+
meaning model.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Per-version `RELEASE_NOTES_v*.md` files live in `docs/releases/`.
|
|
27
|
+
- README is user-first: install, first five minutes, then the release.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- Loaded HNSW graphs can append a delta instead of rebuilding from the
|
|
31
|
+
incoming set alone (which wiped live labels).
|
|
32
|
+
|
|
7
33
|
## [12.2.0] - 2026-08-29 — Small Voice
|
|
8
34
|
|
|
9
35
|
### Added
|
|
@@ -210,7 +236,7 @@ existed at that release.
|
|
|
210
236
|
- DMG는 ad-hoc 서명(미서명)이다.
|
|
211
237
|
- 11.8.0이 열어 둔 항목(커버리지 바닥 라인 90, 멀티모달 이미지/비디오
|
|
212
238
|
HTTP 문 없음, 11.7.0 leftover)은 그대로다. 전문은
|
|
213
|
-
[RELEASE_NOTES_v11.9.0.md](
|
|
239
|
+
[RELEASE_NOTES_v11.9.0.md](releases/RELEASE_NOTES_v11.9.0.md).
|
|
214
240
|
|
|
215
241
|
## [11.8.0] - 2026-08-16 — Travel Light
|
|
216
242
|
|
|
@@ -292,7 +318,7 @@ existed at that release.
|
|
|
292
318
|
- `tests/visual/mock_server`가 고아 mock 라우트 하나를 아직 서빙합니다
|
|
293
319
|
(현재 증거가 해시로 묶여 있어 다음 캡처 사이클에 정리).
|
|
294
320
|
- 11.7.0이 열어 둔 항목은 그대로입니다. 전문은
|
|
295
|
-
[RELEASE_NOTES_v11.8.0.md](
|
|
321
|
+
[RELEASE_NOTES_v11.8.0.md](releases/RELEASE_NOTES_v11.8.0.md).
|
|
296
322
|
|
|
297
323
|
## [11.7.0] - 2026-08-15 — Clean Sweep
|
|
298
324
|
|
|
@@ -336,7 +362,7 @@ existed at that release.
|
|
|
336
362
|
`delete_node`는 `PART_OF`를 남김. owner 없는 리뷰 이벤트는 침묵.
|
|
337
363
|
KG-api ingest는 텍스트 전용. 리뷰 변이 = 스토어 사이클 2회.
|
|
338
364
|
snooze 422 detail은 영문 리터럴. 전문은
|
|
339
|
-
[RELEASE_NOTES_v11.7.0.md](
|
|
365
|
+
[RELEASE_NOTES_v11.7.0.md](releases/RELEASE_NOTES_v11.7.0.md).
|
|
340
366
|
|
|
341
367
|
## [11.6.0] - 2026-08-15 — One Door
|
|
342
368
|
|
|
@@ -411,7 +437,7 @@ existed at that release.
|
|
|
411
437
|
비어 있음 · 리뷰 스누즈 offset-aware 500 · 제안 이중 거절 500),
|
|
412
438
|
업로드 추출 UTF-8 전용, 공급 벡터 1차 노드 한정, 네이티브 도구의 사용자
|
|
413
439
|
훅 미발화, `sanitize_write_content` 미적용, 워커 원점으로 남은 seam 호출
|
|
414
|
-
3건. 전문은 [RELEASE_NOTES_v11.6.0.md](
|
|
440
|
+
3건. 전문은 [RELEASE_NOTES_v11.6.0.md](releases/RELEASE_NOTES_v11.6.0.md).
|
|
415
441
|
|
|
416
442
|
## [11.5.2] - 2026-08-12 — Tight Ship
|
|
417
443
|
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -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.
|
|
6
|
+
Current release: **12.2.1 — True Count**.
|
|
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.
|
|
83
|
+
rebuild (`cargo build -p lattice-host --release`) if `-V` is not 12.2.1.
|
|
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.
|
|
240
|
+
included) must carry `Current release: **12.2.1 — …**` 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.
|
|
251
|
+
`output/release/v12.2.1/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.
|
|
320
|
+
bumps. Do not move this file's `Current release` marker off 12.2.1 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.
|
|
326
|
+
For 12.2.1 release work, exact artifacts are:
|
|
327
327
|
|
|
328
|
-
- `dist/ltcai-12.2.
|
|
329
|
-
- `dist/ltcai-12.2.
|
|
330
|
-
- `ltcai-12.2.
|
|
331
|
-
- `dist/ltcai-12.2.
|
|
332
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_12.2.
|
|
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`
|
|
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.
|
package/docs/ONBOARDING.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI Onboarding
|
|
2
2
|
|
|
3
|
-
Current release: **12.2.
|
|
3
|
+
Current release: **12.2.1 — True Count**.
|
|
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
|
package/docs/OPERATIONS.md
CHANGED
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.1
|
|
6
|
+
As of **2026-08-29**, against the 12.2.1 — True Count 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.
|
|
@@ -17,8 +17,8 @@ the contributor path is [DEVELOPMENT.md](DEVELOPMENT.md). This page is the
|
|
|
17
17
|
honest leftover list, gathered from
|
|
18
18
|
[FEATURE_STATUS.md](../FEATURE_STATUS.md) Known Limitations and the §정직한
|
|
19
19
|
고지 sections of
|
|
20
|
-
[RELEASE_NOTES_v11.9.0.md](
|
|
21
|
-
[RELEASE_NOTES_v12.0.0.md](
|
|
20
|
+
[releases/RELEASE_NOTES_v11.9.0.md](releases/RELEASE_NOTES_v11.9.0.md) and
|
|
21
|
+
[releases/RELEASE_NOTES_v12.0.0.md](releases/RELEASE_NOTES_v12.0.0.md).
|
|
22
22
|
|
|
23
23
|
Four items those ledgers named **closed in 12.0.0**. They are kept below so
|
|
24
24
|
they are not re-opened as work. Everything else is still open.
|
|
@@ -43,18 +43,18 @@ rather than being deleted: the small-model harness (P1) and the HNSW index
|
|
|
43
43
|
|
|
44
44
|
| 무엇 | 왜 남았나 | 난이도 | 우선순위 | 제안 경로 |
|
|
45
45
|
| --- | --- | --- | --- | --- |
|
|
46
|
-
| **Small-model agent-run content quality** | **
|
|
47
|
-
| **Real-embedding default rollout** | **Narrowed in 12.
|
|
46
|
+
| **Small-model agent-run content quality** | **Narrowed in 12.2.1.** Mechanical half closed in 12.0.0 (`guided`, measured probe). 12.2.1 fills a thin summary from the `read_file` / `mcp.read_file` result already on the transcript; missing evidence is `NEEDS_REVIEW`, not a false DONE. Remaining: a 2B that never read the file, and writing that is fluent but wrong. | L | **P1** — still the voice on 8GB. | Keep measuring with the loop's own parser. Do not add a per-model branch. |
|
|
47
|
+
| **Real-embedding default rollout** | **Narrowed again in 12.2.1.** First-run and the library name hash search as hash and point at a meaning model. Auto-detection still adopts a real downloaded embedder when one is present. The no-download default is still `lattice-local-hash-v1`. | M | **P1** — recall is the product. | Offer an embedding model in first-run the way a chat model is offered. Drain through `lattice-jobs` on switch. No second embedder in `lattice-core`. |
|
|
48
48
|
| **Worker-side batch embed** | **Closed in 12.1.0 on the ingest-time door**: one `/worker/embed` body is the document vector followed by every chunk, extract runs beside it, and `write_vectors_with` files those vectors. The drain planner stays the backlog path. Folder/watch overlap up to four files. What remains for a real-embed default is auto-detection on first run, not a second embedder. | M | **P1 → closed for the ingest door; the real-embed default row above is still open.** | Keep. Do not open a second embedder inside `lattice-core`. |
|
|
49
49
|
|
|
50
50
|
## P2 — real, but the product still works without them
|
|
51
51
|
|
|
52
52
|
| 무엇 | 왜 남았나 | 난이도 | 우선순위 | 제안 경로 |
|
|
53
53
|
| --- | --- | --- | --- | --- |
|
|
54
|
-
| **HNSW whole-rebuild** | **Closed in 12.0.0
|
|
54
|
+
| **HNSW whole-rebuild / full-table dump** | **Closed in 12.2.1.** 12.0.0 appended instead of invalidating. 12.2.1 warm queries are `COUNT(*)` then missing ids only; a loaded sidecar appends a delta instead of rebuilding from the incoming set. Env default stays `brute`. | L | **P2 → closed for the dump; the default stays `brute`.** | Flip the default only after recall@10 vs exact scan on a live Brain. |
|
|
55
55
|
| **Unsigned DMG** | `Lattice AI_12.0.0_aarch64.dmg` is ad-hoc signed (= unsigned). First launch needs the Gatekeeper bypass. `npm run release:validate` checks names and presence, not a Developer ID. | M | **P2** — first-run tax on desktop, not a Brain bug. Needs an Apple identity. | Developer ID Application + notarization in the release path. Exact artifact name stays `dist/…` / `src-tauri/target/release/bundle/dmg/Lattice AI_X.Y.Z_aarch64.dmg`. Credentials stay off the tree. |
|
|
56
|
-
| **`api_key` cloud path is mock-only** |
|
|
57
|
-
| **Vault-watch full-resync** | **
|
|
56
|
+
| **`api_key` cloud path is mock-only** | **Narrowed in 12.2.1.** Status now live-probes `GET /models` with the key (no completion) and fail-closes when the provider is unreachable. Chat completions are still not billed in CI. Live E2E remains `cli_oauth`. | S | **P2** — the key is proven to work; a billed completion is still a budget. | One live contract completion once a budget exists. Keep `local_only` winning on the request. |
|
|
57
|
+
| **Vault-watch full-resync** | **Closed the remaining two holes in 12.2.1**: skip-by-hash restamps so a `touch` is not re-hashed forever, and vanished watched files are pruned from the graph (`delete_document_tree`). Disk is never deleted. Cap is still 2,000 notes/run. | M | **P2 → closed for skip and prune.** | Attach links from ids that already landed so the bridge does not need a whole pass. Keep the cap. |
|
|
58
58
|
| **Self-Model has no screen** | Writes were restored in 11.7.0. `GET/POST/DELETE /api/memory/self-model*` and Review Center proposals work. `/app` has no profile view — "Brain이 나에 대해 뭐라고 생각하나" is an API call. | M | **P2** — the data path is real; the reader cannot see it. | A panel under `frontend/src/features/brain/` + `frontend/src/i18n/brain/`, reading the existing API. No new writer. Vitest 100% `all: true`. |
|
|
59
59
|
|
|
60
60
|
## P3 — honesty leftovers that should not grow
|
package/docs/TRUST_MODEL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI Trust Model
|
|
2
2
|
|
|
3
|
-
Current release: **12.2.
|
|
3
|
+
Current release: **12.2.1 — True Count**.
|
|
4
4
|
|
|
5
5
|
Lattice AI is local-first, explicit about external communication, and honest
|
|
6
6
|
when a capability is unavailable.
|
|
@@ -87,7 +87,7 @@ does not mean secrets should appear in clear text.
|
|
|
87
87
|
- Cloud model prompts follow the selected provider's policy once the user
|
|
88
88
|
explicitly chooses that provider (or the `auto`/`always` escalation
|
|
89
89
|
policy does, behind `cloud_allowed`). The `api_key` path is
|
|
90
|
-
|
|
90
|
+
probed with `GET /models` (no billed completion); live OAuth used `cli_oauth` at
|
|
91
91
|
zero billing. Extracted cloud knowledge is proposal-first.
|
|
92
92
|
- A local admin can inspect local files and process memory outside Lattice AI.
|
|
93
93
|
- Marketplace and model registries are third-party services when explicitly
|
package/docs/WHY_LATTICE.md
CHANGED
package/docs/kg-schema.md
CHANGED
package/latticeai/__init__.py
CHANGED
|
@@ -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
|
|
181
|
-
deletes would exceed :data:`DELETE_REBUILD_RATIO
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|