ltcai 10.2.0 → 10.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.
- package/README.md +39 -44
- package/docs/CHANGELOG.md +48 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/MYPY_BACKLOG.md +98 -0
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +1 -1
- package/docs/TRUST_MODEL.md +1 -1
- package/docs/WHY_LATTICE.md +1 -1
- package/docs/kg-schema.md +1 -1
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/graph/_kg_fsutil.py +1 -1
- package/lattice_brain/runtime/agent_runtime.py +7 -2
- package/lattice_brain/runtime/hooks.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/app_factory.py +43 -67
- package/latticeai/core/legacy_compatibility.py +1 -1
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os_constants.py +1 -1
- package/latticeai/runtime/history_writer.py +138 -0
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/product_readiness.py +1 -1
- package/package.json +4 -2
- package/scripts/check_current_release_docs.mjs +1 -1
- package/src-tauri/Cargo.lock +1 -1
- package/src-tauri/Cargo.toml +1 -1
- package/src-tauri/tauri.conf.json +1 -1
- package/static/app/asset-manifest.json +37 -37
- package/static/app/assets/{Act-CbdGD-2i.js → Act-DrKIGZeJ.js} +1 -1
- package/static/app/assets/{AdminConsole-LgCkXpnf.js → AdminConsole-CEV1VefA.js} +1 -1
- package/static/app/assets/{Brain-CoPGJI1L.js → Brain-BZSXnwWU.js} +1 -1
- package/static/app/assets/{BrainHome-gVnaxSwp.js → BrainHome-CEBd86k6.js} +1 -1
- package/static/app/assets/{BrainSignals-ChxAYHtj.js → BrainSignals-O4s6R7av.js} +1 -1
- package/static/app/assets/{Capture-DBtgkHZg.js → Capture-AGbOxsg-.js} +1 -1
- package/static/app/assets/{CommandPalette-Ovtv5I0Y.js → CommandPalette-CeqBjCn2.js} +1 -1
- package/static/app/assets/Library-CXnbNiQW.js +1 -0
- package/static/app/assets/{LivingBrain-CNz-6NSd.js → LivingBrain-D9Iei2ZJ.js} +1 -1
- package/static/app/assets/{ProductFlow-ePX-Y73J.js → ProductFlow-JlXiDfMM.js} +1 -1
- package/static/app/assets/{ReviewCard-C4mpvkwH.js → ReviewCard-QQly2bTV.js} +1 -1
- package/static/app/assets/{System-BvWNK1zc.js → System-Bp9ZY4ER.js} +1 -1
- package/static/app/assets/{activity-CiauPV_3.js → activity-CxRPOQ2F.js} +1 -1
- package/static/app/assets/{bot-Dwct-Q1x.js → bot-1bcsWB2s.js} +1 -1
- package/static/app/assets/{brain-BKDW1F0T.js → brain-CxaeKCRM.js} +1 -1
- package/static/app/assets/{button-CCB9Kuw7.js → button-ZYFqGan7.js} +1 -1
- package/static/app/assets/{circle-pause-DNa8WHC5.js → circle-pause-B5NOIqvk.js} +1 -1
- package/static/app/assets/{circle-play-8jmxn5mf.js → circle-play-BiJVFXf7.js} +1 -1
- package/static/app/assets/{cpu-mxvF3V1I.js → cpu-Vvq0OKTr.js} +1 -1
- package/static/app/assets/{download--SmCcx0p.js → download-SEcXzkx1.js} +1 -1
- package/static/app/assets/{folder-open-D4Wy5roo.js → folder-open-Dw1ff_Qa.js} +1 -1
- package/static/app/assets/{hard-drive-BwQcSPlS.js → hard-drive-B00fR7_r.js} +1 -1
- package/static/app/assets/index-CEkL4_M-.css +2 -0
- package/static/app/assets/{index-DDV2YZwM.js → index-Dm9VXl1o.js} +3 -3
- package/static/app/assets/{input-DFhSjmLS.js → input-DtdWYQEa.js} +1 -1
- package/static/app/assets/{network-Bts7VO94.js → network-CpjBu0kI.js} +1 -1
- package/static/app/assets/{primitives-BuSMEJY8.js → primitives-CwsudBwc.js} +1 -1
- package/static/app/assets/search-CwEJWBEA.js +1 -0
- package/static/app/assets/{shield-alert-BfTO6X_G.js → shield-alert-CpjBc-gQ.js} +1 -1
- package/static/app/assets/{textarea-BjctW1oh.js → textarea-DUPyjHQs.js} +1 -1
- package/static/app/assets/{useFocusTrap-CE43-LrA.js → useFocusTrap-BWcMtCWH.js} +1 -1
- package/static/app/assets/{useQuery-Bv3ejLL5.js → useQuery-Dg5fPqTS.js} +1 -1
- package/static/app/assets/{users-CsNqLZAj.js → users-BgcdTQGM.js} +1 -1
- package/static/app/assets/{utils-KFFdVG_t.js → utils-a3YXFtEO.js} +1 -1
- package/static/app/assets/{workspace-wdCvdyPF.js → workspace-BMUEiXUm.js} +1 -1
- package/static/app/index.html +4 -4
- package/static/sw.js +1 -1
- package/static/app/assets/Library-CBia2Fvm.js +0 -1
- package/static/app/assets/index-CQWdDU3z.css +0 -2
- package/static/app/assets/search-DZzxhWaQ.js +0 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
[](https://github.com/TaeSooPark-PTS/LatticeAI/actions/workflows/ci.yml)
|
|
12
12
|
[](LICENSE)
|
|
13
13
|
|
|
14
|
-

|
|
15
15
|
|
|
16
16
|
Chat, files, folders, notes, and web pages all flow into one durable knowledge
|
|
17
17
|
graph on your computer. Any model — local MLX or cloud — can speak with that
|
|
@@ -24,9 +24,9 @@ memory. Nothing leaves your machine without explicit consent.
|
|
|
24
24
|
|
|
25
25
|
| | |
|
|
26
26
|
| --- | --- |
|
|
27
|
-
| **Chat with a Brain that remembers** — every conversation grows durable, source-linked memory  | **See how knowledge connects** — a real relationship graph, not a file list  |
|
|
28
|
+
| **Capture anything** — files, whole folders, notes, screenshots, web pages  | **Automate with review** — agent changes become proposals you approve first  |
|
|
29
|
+
| **Pick a model in one click** — recommended local models for your hardware  | **Stay in control** — audit, roles, retention in a separate admin surface  |
|
|
30
30
|
|
|
31
31
|
## Why Lattice AI
|
|
32
32
|
|
|
@@ -57,53 +57,47 @@ First-run flow — wake the Brain, pick the owner, load a recommended model:
|
|
|
57
57
|
|
|
58
58
|
| | | |
|
|
59
59
|
| --- | --- | --- |
|
|
60
|
-
|  |  |  |
|
|
61
61
|
|
|
62
62
|
Screenshot index and capture notes:
|
|
63
|
-
[output/release/v10.
|
|
63
|
+
[output/release/v10.3.0/SCREENSHOT_INDEX.md](output/release/v10.3.0/SCREENSHOT_INDEX.md)
|
|
64
64
|
|
|
65
65
|
## Current Release
|
|
66
66
|
|
|
67
|
-
The current release is **10.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
optional path is no longer indistinguishable from the optional thing being
|
|
92
|
-
absent.
|
|
93
|
-
- **The lint net was widened to the bug classes that actually bit** — loop
|
|
94
|
-
variable capture, truncating `zip`, silent handlers — and mypy now runs on
|
|
95
|
-
the trust-critical modules. CI gained macOS and Python 3.14, so the machine
|
|
96
|
-
this is developed on and the platform it ships a `.dmg` for are both tested.
|
|
67
|
+
The current release is **10.3.0 — Measured Ground**:
|
|
68
|
+
|
|
69
|
+
10.2.0 answered a code review. 10.3.0 is about knowing where things actually
|
|
70
|
+
stand: several numbers this project reported about itself turned out to be
|
|
71
|
+
wrong, and those corrections matter more than the features around them.
|
|
72
|
+
|
|
73
|
+
- **Frontend coverage was never really measured.** Vitest only reports files a
|
|
74
|
+
test already imports, so every untested module quietly left the denominator
|
|
75
|
+
and the tool read 54%. With `all: true` the honest figure is **28.5%** — and
|
|
76
|
+
208 tests now cover pages that had none, including every settings and memory
|
|
77
|
+
screen.
|
|
78
|
+
- **Python coverage was reported as 80%. It is 71.6%.** The `omit` pattern did
|
|
79
|
+
not match the paths coverage records, so the suite was counting itself — and
|
|
80
|
+
test files run start to finish by construction.
|
|
81
|
+
- **mypy went from 13 modules to 193 of 270**, finding three real defects on
|
|
82
|
+
the way: a log line inside an error handler referenced an attribute that does
|
|
83
|
+
not exist (turning a recoverable failure into a crash), an annotation used a
|
|
84
|
+
name that was never imported, and one call could dereference `None`.
|
|
85
|
+
- **The chat-turn writer left the composition root.** 66 lines that decide what
|
|
86
|
+
a message looks like after redaction, and what the audit log records about
|
|
87
|
+
it, are now a module with 14 tests instead of a closure nothing could reach.
|
|
88
|
+
- **What is not measured is written down.** `docs/MYPY_BACKLOG.md` lists the 77
|
|
89
|
+
modules still outside type checking with their error counts, so the boundary
|
|
90
|
+
is a fact rather than an intention.
|
|
97
91
|
|
|
98
92
|
Release notes: [RELEASE.md](RELEASE.md) · Full history: [docs/CHANGELOG.md](docs/CHANGELOG.md)
|
|
99
93
|
|
|
100
|
-
Expected artifacts for 10.
|
|
94
|
+
Expected artifacts for 10.3.0 release must use exact filenames:
|
|
101
95
|
|
|
102
|
-
- `dist/ltcai-10.
|
|
103
|
-
- `dist/ltcai-10.
|
|
104
|
-
- `ltcai-10.
|
|
105
|
-
- `dist/ltcai-10.
|
|
106
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_10.
|
|
96
|
+
- `dist/ltcai-10.3.0-py3-none-any.whl`
|
|
97
|
+
- `dist/ltcai-10.3.0.tar.gz`
|
|
98
|
+
- `ltcai-10.3.0.tgz`
|
|
99
|
+
- `dist/ltcai-10.3.0.vsix`
|
|
100
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_10.3.0_aarch64.dmg`
|
|
107
101
|
|
|
108
102
|
Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
|
|
109
103
|
|
|
@@ -123,7 +117,7 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
|
|
|
123
117
|
|
|
124
118
|
- External package registries are owner-published and can lag behind GitHub.
|
|
125
119
|
- PostgreSQL/pgvector is optional scale/migration tooling. SQLite remains the
|
|
126
|
-
live local Brain store in 10.
|
|
120
|
+
live local Brain store in 10.3.0.
|
|
127
121
|
- Docker, model downloads, cloud model calls, Telegram, Brain Network, and
|
|
128
122
|
update checks require explicit user action.
|
|
129
123
|
- Conversation does not fabricate answers when no model is loaded. Agent and
|
|
@@ -132,12 +126,13 @@ See [ARCHITECTURE.md](ARCHITECTURE.md) for details and
|
|
|
132
126
|
model success.
|
|
133
127
|
- Some backend-generated messages (for example the Postgres DSN notice) are
|
|
134
128
|
produced server-side in English and are shown as-is; server-side i18n is not
|
|
135
|
-
part of 10.
|
|
129
|
+
part of 10.3.0.
|
|
136
130
|
|
|
137
131
|
## Release History
|
|
138
132
|
|
|
139
133
|
| Version | Theme |
|
|
140
134
|
| --- | --- |
|
|
135
|
+
| 10.3.0 | Measured Ground |
|
|
141
136
|
| 10.2.0 | Load-Bearing Fixes |
|
|
142
137
|
| 10.1.1 | Reachable Boundary |
|
|
143
138
|
| 10.1.0 | Hybrid Brain |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,54 @@ 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
|
+
## [10.3.0] - 2026-07-29
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **Frontend coverage was not being measured.** Vitest reports only files a
|
|
11
|
+
test imports unless `all: true`; untested modules left the denominator
|
|
12
|
+
instead of counting against it. Reported 54%, actual **28.5%**.
|
|
13
|
+
- **Python coverage was over-reported.** `omit = ["*/tests/*"]` does not match
|
|
14
|
+
the repo-relative `tests/...` paths coverage records, so the suite counted
|
|
15
|
+
itself. Reported 80%, actual **71.6%**.
|
|
16
|
+
- `lattice_brain/runtime/hooks.py` referenced `self._path` (does not exist)
|
|
17
|
+
inside the handler for an unreadable registry, turning a recoverable failure
|
|
18
|
+
into `AttributeError`.
|
|
19
|
+
- `lattice_brain/graph/_kg_fsutil.py` used `Iterable` in an annotation without
|
|
20
|
+
importing it.
|
|
21
|
+
- `lattice_brain/runtime/agent_runtime.py` could call `.get` on `None`.
|
|
22
|
+
- `pages/Library.tsx` printed the raw registry coordinate
|
|
23
|
+
(`mlx-community/gemma-4-…`) when a catalog entry had no display name; it now
|
|
24
|
+
falls through `humanizeModelId` like every other model surface.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- `latticeai/runtime/history_writer.py` — `save_to_history` extracted from the
|
|
28
|
+
`app_factory._build` closure with its ordering contract documented, plus 14
|
|
29
|
+
tests (`tests/unit/test_history_writer.py`).
|
|
30
|
+
- `frontend/src/test/renderPage.tsx` — a page-level harness that stubs the
|
|
31
|
+
whole `latticeApi` surface, making error states, empty states and both
|
|
32
|
+
languages reachable in unit tests.
|
|
33
|
+
- First unit tests for every page: `System` (11), `Library` (7), `Capture` (6),
|
|
34
|
+
`Act` (8), `Brain` (8). Frontend suite 154 → 208 tests.
|
|
35
|
+
- Python tests for boundaries that had none: Telegram allowlist (26),
|
|
36
|
+
`run_command` containment (34), audit log and sensitivity report (22),
|
|
37
|
+
model-load consent gates (14), connection lifecycle guards. 1,786 → 1,896.
|
|
38
|
+
- `docs/MYPY_BACKLOG.md` — the 77 modules still outside type checking with
|
|
39
|
+
per-module error counts, smallest first.
|
|
40
|
+
- ARCHITECTURE.md "Verification Surface" diagram: which figures gate CI and
|
|
41
|
+
which are only reported.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
- mypy adopted set: 13 → **193 of 270** modules.
|
|
45
|
+
- `vitest.config.ts` gains a coverage block with `all: true`.
|
|
46
|
+
- `npm run test:frontend:coverage` added.
|
|
47
|
+
|
|
48
|
+
### Known
|
|
49
|
+
- `app_factory._build` remains ~1,300 lines; only the history writer was
|
|
50
|
+
extracted this release.
|
|
51
|
+
- Frontend coverage (28.5%) is reported but not gated — flooring it at today's
|
|
52
|
+
figure would freeze it there.
|
|
53
|
+
- 77 modules remain outside mypy; see the backlog.
|
|
54
|
+
|
|
7
55
|
## [10.2.0] - 2026-07-29
|
|
8
56
|
|
|
9
57
|
Response to a full code review of 10.1.1 (71/100). All twelve findings.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Community And Plugins
|
|
2
2
|
|
|
3
|
-
Current release: **10.
|
|
3
|
+
Current release: **10.3.0 — Measured Ground**.
|
|
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
|
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: **10.
|
|
6
|
+
Current release: **10.3.0 — Measured Ground**.
|
|
7
7
|
|
|
8
8
|
This document is for contributors working on the local-first Digital Brain
|
|
9
9
|
codebase. Product positioning and quick start stay in `README.md`; release
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# mypy backlog
|
|
2
|
+
|
|
3
|
+
`[tool.mypy] files` in `pyproject.toml` lists every module that type-checks
|
|
4
|
+
today — **193 of 270** as of 10.3.0, up from 13 in 10.2.0.
|
|
5
|
+
This file is the remainder, smallest first, so the boundary is a measured
|
|
6
|
+
fact rather than an open-ended intention.
|
|
7
|
+
|
|
8
|
+
Adding a module to the checked set is a decision to fix that module, not its
|
|
9
|
+
dependencies (`follow_imports = silent`). Work from the top: the short ones
|
|
10
|
+
are usually one missing annotation.
|
|
11
|
+
|
|
12
|
+
Three of these turned out to be real defects when 10.3.0 measured them:
|
|
13
|
+
`hooks.py` referenced a non-existent `self._path` inside the handler for an
|
|
14
|
+
unreadable registry, `_kg_fsutil.py` used `Iterable` without importing it,
|
|
15
|
+
and `agent_runtime.py` called `.get` on a value that could be `None`. Those
|
|
16
|
+
are fixed; the list below is what is left.
|
|
17
|
+
|
|
18
|
+
| errors | module | dominant codes |
|
|
19
|
+
| ---: | --- | --- |
|
|
20
|
+
| 1 | `lattice_brain/graph/_kg_fsutil.py` | `union-attr` ×1 |
|
|
21
|
+
| 1 | `latticeai/api/admin.py` | `call-overload` ×1 |
|
|
22
|
+
| 1 | `latticeai/api/computer_use.py` | `var-annotated` ×1 |
|
|
23
|
+
| 1 | `latticeai/api/hooks.py` | `unreachable` ×1 |
|
|
24
|
+
| 1 | `latticeai/api/local_files.py` | `arg-type` ×1 |
|
|
25
|
+
| 1 | `latticeai/api/static_routes.py` | `assignment` ×1 |
|
|
26
|
+
| 1 | `latticeai/core/marketplace.py` | `arg-type` ×1 |
|
|
27
|
+
| 1 | `latticeai/core/model_compat.py` | `unreachable` ×1 |
|
|
28
|
+
| 1 | `latticeai/core/plugins.py` | `unreachable` ×1 |
|
|
29
|
+
| 1 | `latticeai/core/project_sessions.py` | `var-annotated` ×1 |
|
|
30
|
+
| 1 | `latticeai/core/workspace_os.py` | `unreachable` ×1 |
|
|
31
|
+
| 1 | `latticeai/core/workspace_os_state.py` | `arg-type` ×1 |
|
|
32
|
+
| 1 | `latticeai/runtime/sso_config_runtime.py` | `arg-type` ×1 |
|
|
33
|
+
| 1 | `latticeai/services/command_center.py` | `assignment` ×1 |
|
|
34
|
+
| 1 | `latticeai/services/search_service.py` | `assignment` ×1 |
|
|
35
|
+
| 1 | `latticeai/services/triggers.py` | `truthy-function` ×1 |
|
|
36
|
+
| 1 | `latticeai/setup/auto_setup.py` | `attr-defined` ×1 |
|
|
37
|
+
| 2 | `lattice_brain/ingestion.py` | `assignment` ×2 |
|
|
38
|
+
| 2 | `latticeai/api/chat_stream.py` | `var-annotated` ×1, `arg-type` ×1 |
|
|
39
|
+
| 2 | `latticeai/api/mcp.py` | `var-annotated` ×2 |
|
|
40
|
+
| 2 | `latticeai/core/mcp_registry.py` | `index` ×1, `return-value` ×1 |
|
|
41
|
+
| 2 | `latticeai/core/run_explain.py` | `union-attr` ×1, `call-overload` ×1 |
|
|
42
|
+
| 2 | `latticeai/core/workspace_snapshots.py` | `var-annotated` ×2 |
|
|
43
|
+
| 2 | `latticeai/runtime/review_wiring.py` | `call-arg` ×2 |
|
|
44
|
+
| 2 | `latticeai/services/brain_intelligence.py` | `operator` ×1, `index` ×1 |
|
|
45
|
+
| 2 | `latticeai/services/memory_service.py` | `misc` ×1, `index` ×1 |
|
|
46
|
+
| 2 | `latticeai/services/model_loading.py` | `arg-type` ×1, `call-overload` ×1 |
|
|
47
|
+
| 2 | `latticeai/services/multimodal_streaming.py` | `attr-defined` ×1, `arg-type` ×1 |
|
|
48
|
+
| 2 | `latticeai/setup/wizard.py` | `attr-defined` ×1, `dict-item` ×1 |
|
|
49
|
+
| 2 | `latticeai/tools/documents.py` | `arg-type` ×2 |
|
|
50
|
+
| 3 | `lattice_brain/quality.py` | `var-annotated` ×2, `return-value` ×1 |
|
|
51
|
+
| 3 | `latticeai/api/models.py` | `call-overload` ×2, `attr-defined` ×1 |
|
|
52
|
+
| 3 | `latticeai/cli/entrypoint.py` | `operator` ×1, `union-attr` ×1, `arg-type` ×1 |
|
|
53
|
+
| 3 | `latticeai/core/audit.py` | `assignment` ×1, `index` ×1, `operator` ×1 |
|
|
54
|
+
| 3 | `latticeai/integrations/telegram_bot.py` | `union-attr` ×2, `arg-type` ×1 |
|
|
55
|
+
| 3 | `latticeai/runtime/stages.py` | `arg-type` ×3 |
|
|
56
|
+
| 3 | `latticeai/services/cloud_streaming.py` | `arg-type` ×2, `attr-defined` ×1 |
|
|
57
|
+
| 3 | `latticeai/services/hybrid_chat.py` | `arg-type` ×3 |
|
|
58
|
+
| 3 | `latticeai/services/tool_dispatch.py` | `arg-type` ×3 |
|
|
59
|
+
| 4 | `lattice_brain/graph/_kg_common.py` | `misc` ×3, `return-value` ×1 |
|
|
60
|
+
| 4 | `latticeai/api/chat_agent_http.py` | `arg-type` ×2, `misc` ×1, `assignment` ×1 |
|
|
61
|
+
| 4 | `latticeai/api/chat_helpers.py` | `call-overload` ×2, `union-attr` ×1, `arg-type` ×1 |
|
|
62
|
+
| 4 | `latticeai/api/security_dashboard.py` | `assignment` ×3, `unreachable` ×1 |
|
|
63
|
+
| 4 | `latticeai/services/evidence_actions.py` | `union-attr` ×4 |
|
|
64
|
+
| 5 | `lattice_brain/context.py` | `arg-type` ×4, `misc` ×1 |
|
|
65
|
+
| 5 | `latticeai/api/permissions.py` | `arg-type` ×5 |
|
|
66
|
+
| 5 | `latticeai/services/model_engines.py` | `attr-defined` ×2, `call-overload` ×2, `unreachable` ×1 |
|
|
67
|
+
| 5 | `latticeai/services/run_executor.py` | `unreachable` ×3, `arg-type` ×1, `return-value` ×1 |
|
|
68
|
+
| 6 | `lattice_brain/runtime/contracts.py` | `union-attr` ×6 |
|
|
69
|
+
| 6 | `latticeai/core/agent.py` | `arg-type` ×4, `return-value` ×2 |
|
|
70
|
+
| 7 | `lattice_brain/graph/proactive.py` | `assignment` ×2, `arg-type` ×2, `index` ×1 |
|
|
71
|
+
| 7 | `latticeai/app_factory.py` | `arg-type` ×3, `assignment` ×2, `attr-defined` ×2 |
|
|
72
|
+
| 7 | `latticeai/core/embedding_providers.py` | `unreachable` ×2, `assignment` ×2, `union-attr` ×2 |
|
|
73
|
+
| 7 | `latticeai/services/openai_compatible_adapter.py` | `arg-type` ×7 |
|
|
74
|
+
| 8 | `lattice_brain/graph/curator.py` | `operator` ×8 |
|
|
75
|
+
| 8 | `lattice_brain/workflow.py` | `arg-type` ×5, `index` ×2, `assignment` ×1 |
|
|
76
|
+
| 8 | `latticeai/api/setup.py` | `index` ×5, `attr-defined` ×3 |
|
|
77
|
+
| 8 | `latticeai/services/local_knowledge.py` | `union-attr` ×3, `misc` ×2, `operator` ×2 |
|
|
78
|
+
| 10 | `latticeai/api/tools.py` | `arg-type` ×10 |
|
|
79
|
+
| 13 | `latticeai/api/search.py` | `return` ×12, `return-value` ×1 |
|
|
80
|
+
| 15 | `lattice_brain/graph/store.py` | `name-defined` ×15 |
|
|
81
|
+
| 16 | `latticeai/api/chat.py` | `arg-type` ×12, `misc` ×3, `call-overload` ×1 |
|
|
82
|
+
| 16 | `latticeai/tools/computer.py` | `union-attr` ×16 |
|
|
83
|
+
| 19 | `lattice_brain/graph/retrieval_docgen.py` | `name-defined` ×12, `attr-defined` ×7 |
|
|
84
|
+
| 35 | `latticeai/services/model_runtime.py` | `index` ×15, `arg-type` ×8, `attr-defined` ×6 |
|
|
85
|
+
| 45 | `lattice_brain/graph/retrieval_reads.py` | `name-defined` ×30, `attr-defined` ×15 |
|
|
86
|
+
| 46 | `latticeai/models/router.py` | `arg-type` ×26, `assignment` ×7, `attr-defined` ×4 |
|
|
87
|
+
| 57 | `lattice_brain/graph/write_master.py` | `name-defined` ×48, `attr-defined` ×9 |
|
|
88
|
+
| 64 | `lattice_brain/graph/documents.py` | `name-defined` ×45, `attr-defined` ×19 |
|
|
89
|
+
| 71 | `lattice_brain/graph/provenance.py` | `name-defined` ×59, `attr-defined` ×12 |
|
|
90
|
+
| 77 | `lattice_brain/graph/retrieval.py` | `name-defined` ×61, `attr-defined` ×16 |
|
|
91
|
+
| 79 | `lattice_brain/graph/discovery.py` | `name-defined` ×72, `attr-defined` ×7 |
|
|
92
|
+
| 107 | `lattice_brain/graph/retrieval_vector.py` | `name-defined` ×68, `attr-defined` ×39 |
|
|
93
|
+
| 108 | `latticeai/api/workspace.py` | `misc` ×105, `arg-type` ×2, `call-overload` ×1 |
|
|
94
|
+
| 127 | `lattice_brain/graph/discovery_index.py` | `name-defined` ×98, `attr-defined` ×29 |
|
|
95
|
+
| 143 | `lattice_brain/graph/projection.py` | `name-defined` ×122, `attr-defined` ×21 |
|
|
96
|
+
| 177 | `lattice_brain/graph/ingest.py` | `name-defined` ×122, `attr-defined` ×55 |
|
|
97
|
+
|
|
98
|
+
Total outstanding: **1407** errors across **77** modules.
|
package/docs/ONBOARDING.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI Onboarding
|
|
2
2
|
|
|
3
|
-
Current release: **10.
|
|
3
|
+
Current release: **10.3.0 — Measured Ground**.
|
|
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/TRUST_MODEL.md
CHANGED
package/docs/WHY_LATTICE.md
CHANGED
package/docs/kg-schema.md
CHANGED
|
@@ -18,7 +18,7 @@ import platform
|
|
|
18
18
|
import re
|
|
19
19
|
from datetime import datetime
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import Any, Dict, List, Optional, Tuple
|
|
21
|
+
from typing import Any, Dict, Iterable, List, Optional, Tuple
|
|
22
22
|
|
|
23
23
|
from ..quiet import quiet
|
|
24
24
|
from ..utils import now_iso as _now
|
|
@@ -518,8 +518,13 @@ class AgentRuntime:
|
|
|
518
518
|
if sentence.strip(" -•\t")
|
|
519
519
|
]
|
|
520
520
|
facts = [_compact_text(sentence, limit=180) for sentence in sentences[:4]]
|
|
521
|
-
|
|
522
|
-
|
|
521
|
+
# `or {}` rather than the isinstance ternary: the ternary could still
|
|
522
|
+
# yield None when the attribute was a dict-typed None, and the next
|
|
523
|
+
# line calls .get on both.
|
|
524
|
+
review = getattr(result, "review", None)
|
|
525
|
+
review = review if isinstance(review, dict) else {}
|
|
526
|
+
plan_review = getattr(result, "plan_review", None)
|
|
527
|
+
plan_review = plan_review if isinstance(plan_review, dict) else {}
|
|
523
528
|
decision_seed = review.get("decision") or review.get("status") or plan_review.get("decision") or getattr(result, "status", "")
|
|
524
529
|
decisions = [
|
|
525
530
|
_compact_text(f"Run finished with {decision_seed}", limit=160),
|
|
@@ -344,7 +344,7 @@ class HooksRegistry:
|
|
|
344
344
|
data.setdefault("overrides", {})
|
|
345
345
|
return data
|
|
346
346
|
except (OSError, json.JSONDecodeError, TypeError, ValueError) as exc:
|
|
347
|
-
LOGGER.warning("hook registry state is unreadable at %s: %s", self.
|
|
347
|
+
LOGGER.warning("hook registry state is unreadable at %s: %s", self.path, exc)
|
|
348
348
|
return {"custom": [], "overrides": {}}
|
|
349
349
|
|
|
350
350
|
def _save(self) -> None:
|
|
@@ -47,7 +47,7 @@ from typing import Any, Callable, Dict, List, Optional
|
|
|
47
47
|
from ..utils import now_iso as _now
|
|
48
48
|
from .contracts import multi_agent_contract
|
|
49
49
|
|
|
50
|
-
MULTI_AGENT_VERSION = "10.
|
|
50
|
+
MULTI_AGENT_VERSION = "10.3.0"
|
|
51
51
|
|
|
52
52
|
AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
|
|
53
53
|
CORE_PIPELINE = ("planner", "executor", "reviewer")
|
package/latticeai/__init__.py
CHANGED
package/latticeai/app_factory.py
CHANGED
|
@@ -31,6 +31,7 @@ from latticeai.runtime.chat_wiring import (
|
|
|
31
31
|
from latticeai.runtime.config_runtime import build_config_runtime
|
|
32
32
|
from latticeai.runtime.context_runtime import build_context_runtime
|
|
33
33
|
from latticeai.runtime.history_runtime import build_history_query_runtime
|
|
34
|
+
from latticeai.runtime.history_writer import HistoryWriterDeps, write_chat_turn
|
|
34
35
|
from latticeai.runtime.hooks_runtime import (
|
|
35
36
|
bind_builtin_hook_runners,
|
|
36
37
|
bind_trigger_hook_runner,
|
|
@@ -258,7 +259,6 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
|
|
|
258
259
|
except Exception:
|
|
259
260
|
keyring = None
|
|
260
261
|
|
|
261
|
-
from datetime import datetime
|
|
262
262
|
|
|
263
263
|
# ── App-level config — parsed once, in one place (latticeai.core.config) ──────
|
|
264
264
|
# The module-level names below are kept as a compatibility surface for the rest
|
|
@@ -409,6 +409,46 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
|
|
|
409
409
|
# free). Legacy chat_history.json is imported once, idempotently, and the
|
|
410
410
|
# file is left untouched on disk as the import source.
|
|
411
411
|
CONVERSATIONS = _brain_runtime["CONVERSATIONS"]
|
|
412
|
+
|
|
413
|
+
def save_to_history(
|
|
414
|
+
role: str,
|
|
415
|
+
message: str,
|
|
416
|
+
user_email: Optional[str] = None,
|
|
417
|
+
user_nickname: Optional[str] = None,
|
|
418
|
+
source: Optional[str] = None,
|
|
419
|
+
conversation_id: Optional[str] = None,
|
|
420
|
+
workspace_id: Optional[str] = None,
|
|
421
|
+
) -> None:
|
|
422
|
+
"""Persist one chat turn. Logic lives in runtime/history_writer.py.
|
|
423
|
+
|
|
424
|
+
This stays a closure on purpose: `append_audit_event`,
|
|
425
|
+
`classify_sensitive_message` and `redact_secret_text` are bound further
|
|
426
|
+
down this composition root, and a closure resolves them at call time.
|
|
427
|
+
Hoisting the construction instead would reorder the whole function.
|
|
428
|
+
"""
|
|
429
|
+
write_chat_turn(
|
|
430
|
+
role,
|
|
431
|
+
message,
|
|
432
|
+
user_email=user_email,
|
|
433
|
+
user_nickname=user_nickname,
|
|
434
|
+
source=source,
|
|
435
|
+
conversation_id=conversation_id,
|
|
436
|
+
workspace_id=workspace_id,
|
|
437
|
+
deps=HistoryWriterDeps(
|
|
438
|
+
conversations=CONVERSATIONS,
|
|
439
|
+
append_audit_event=append_audit_event,
|
|
440
|
+
classify_sensitive_message=classify_sensitive_message,
|
|
441
|
+
redact_secret_text=redact_secret_text,
|
|
442
|
+
normalize_branding=normalize_branding,
|
|
443
|
+
ingestion_pipeline=INGESTION_PIPELINE,
|
|
444
|
+
ingestion_item_factory=IngestionItem,
|
|
445
|
+
enable_graph=ENABLE_GRAPH,
|
|
446
|
+
knowledge_graph=KNOWLEDGE_GRAPH,
|
|
447
|
+
),
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
412
452
|
# Hooks registry is constructed here (ahead of the watcher) so folder-watch
|
|
413
453
|
# reindexes can fire the pre_index/post_index lifecycle hooks. The registry
|
|
414
454
|
# + watcher pair is assembled behind the hooks_runtime seam.
|
|
@@ -534,72 +574,7 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
|
|
|
534
574
|
|
|
535
575
|
# audit build moved after redact_secret_text is defined (see below)
|
|
536
576
|
|
|
537
|
-
|
|
538
|
-
role: str,
|
|
539
|
-
message: str,
|
|
540
|
-
user_email: Optional[str] = None,
|
|
541
|
-
user_nickname: Optional[str] = None,
|
|
542
|
-
source: Optional[str] = None,
|
|
543
|
-
conversation_id: Optional[str] = None,
|
|
544
|
-
workspace_id: Optional[str] = None,
|
|
545
|
-
):
|
|
546
|
-
try:
|
|
547
|
-
message = redact_secret_text(message)
|
|
548
|
-
if role == "assistant":
|
|
549
|
-
message = normalize_branding(message)
|
|
550
|
-
item = {"role": role, "content": message, "timestamp": datetime.now().isoformat()}
|
|
551
|
-
if user_email:
|
|
552
|
-
item["user_email"] = user_email
|
|
553
|
-
if user_nickname:
|
|
554
|
-
item["user_nickname"] = user_nickname
|
|
555
|
-
if source:
|
|
556
|
-
item["source"] = source
|
|
557
|
-
if conversation_id:
|
|
558
|
-
item["conversation_id"] = conversation_id
|
|
559
|
-
if workspace_id:
|
|
560
|
-
item["workspace_id"] = workspace_id
|
|
561
|
-
sensitive = classify_sensitive_message(item, -1)
|
|
562
|
-
append_audit_event(
|
|
563
|
-
"chat_message",
|
|
564
|
-
role=role,
|
|
565
|
-
user_email=user_email,
|
|
566
|
-
user_nickname=user_nickname,
|
|
567
|
-
source=source,
|
|
568
|
-
conversation_id=conversation_id,
|
|
569
|
-
workspace_id=workspace_id,
|
|
570
|
-
content_preview=sensitive.get("preview"),
|
|
571
|
-
content_chars=len(message or ""),
|
|
572
|
-
sensitivity=sensitive.get("sensitivity"),
|
|
573
|
-
sensitive_labels=sensitive.get("labels") or [],
|
|
574
|
-
)
|
|
575
|
-
# v4: conversations are durable episodic memory — unbounded SQLite
|
|
576
|
-
# store (the 50-message chat_history.json cap is dead).
|
|
577
|
-
CONVERSATIONS.append(item)
|
|
578
|
-
try:
|
|
579
|
-
if ENABLE_GRAPH and KNOWLEDGE_GRAPH:
|
|
580
|
-
# v4: chat messages enter the brain through the unified
|
|
581
|
-
# ingestion pipeline (provenance + hook lifecycle), not by
|
|
582
|
-
# bypassing it with a direct store call.
|
|
583
|
-
INGESTION_PIPELINE.ingest(
|
|
584
|
-
IngestionItem(
|
|
585
|
-
source_type="chat_message",
|
|
586
|
-
text=message,
|
|
587
|
-
owner=user_email,
|
|
588
|
-
workspace_id=workspace_id,
|
|
589
|
-
conversation_id=conversation_id,
|
|
590
|
-
metadata={
|
|
591
|
-
"role": role,
|
|
592
|
-
"user_nickname": user_nickname,
|
|
593
|
-
"source": source,
|
|
594
|
-
"raw": item,
|
|
595
|
-
},
|
|
596
|
-
),
|
|
597
|
-
user_email=user_email,
|
|
598
|
-
)
|
|
599
|
-
except Exception as graph_error:
|
|
600
|
-
logging.warning("knowledge graph message ingest failed: %s", graph_error)
|
|
601
|
-
except Exception as e:
|
|
602
|
-
logging.warning("save_to_history failed: %s", e)
|
|
577
|
+
|
|
603
578
|
|
|
604
579
|
def redact_secret_text(text: str) -> str:
|
|
605
580
|
return _redact_secret_text(text)
|
|
@@ -692,6 +667,7 @@ def _build(config: "Optional[Config]" = None) -> Dict[str, Any]:
|
|
|
692
667
|
def build_sensitivity_report(history: List[Dict]) -> Dict:
|
|
693
668
|
return _build_sensitivity_report(history)
|
|
694
669
|
|
|
670
|
+
|
|
695
671
|
# ── Admin audit report — delegated to latticeai.core.audit ───────────────────
|
|
696
672
|
def build_admin_audit_report(users: Dict, audit_events: Optional[List[Dict]] = None) -> Dict:
|
|
697
673
|
graph_stats = None
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
from copy import deepcopy
|
|
11
11
|
from typing import Any, Dict, List, Optional
|
|
12
12
|
|
|
13
|
-
MARKETPLACE_VERSION = "10.
|
|
13
|
+
MARKETPLACE_VERSION = "10.3.0"
|
|
14
14
|
TEMPLATE_KINDS = ("plugin", "workflow", "agent", "ingestion_bridge")
|
|
15
15
|
|
|
16
16
|
|
|
@@ -10,7 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
from typing import Dict
|
|
12
12
|
|
|
13
|
-
WORKSPACE_OS_VERSION = "10.
|
|
13
|
+
WORKSPACE_OS_VERSION = "10.3.0"
|
|
14
14
|
|
|
15
15
|
# Workspace types separate single-user Personal workspaces from shared
|
|
16
16
|
# Organization workspaces. Both keep the same local-first JSON store; the type
|