ltcai 10.2.0 → 10.4.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 +40 -44
- package/docs/CHANGELOG.md +125 -0
- package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/MYPY_BACKLOG.md +65 -0
- package/docs/ONBOARDING.md +1 -1
- package/docs/OPERATIONS.md +1 -1
- package/docs/SURFACE_PARITY.md +33 -6
- 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/context.py +23 -3
- package/lattice_brain/graph/_kg_common.py +164 -9
- package/lattice_brain/graph/_kg_contract.py +223 -0
- package/lattice_brain/graph/_kg_fsutil.py +2 -2
- package/lattice_brain/graph/curator.py +4 -4
- package/lattice_brain/graph/discovery.py +12 -1
- package/lattice_brain/graph/discovery_index.py +12 -1
- package/lattice_brain/graph/documents.py +17 -2
- package/lattice_brain/graph/ingest.py +12 -1
- package/lattice_brain/graph/proactive.py +9 -5
- package/lattice_brain/graph/projection.py +12 -1
- package/lattice_brain/graph/provenance.py +12 -1
- package/lattice_brain/graph/retrieval.py +12 -1
- package/lattice_brain/graph/retrieval_docgen.py +12 -1
- package/lattice_brain/graph/retrieval_reads.py +12 -1
- package/lattice_brain/graph/retrieval_vector.py +12 -1
- package/lattice_brain/graph/schema.py +6 -2
- package/lattice_brain/graph/write_master.py +12 -1
- package/lattice_brain/ingestion.py +1 -1
- package/lattice_brain/quality.py +5 -5
- package/lattice_brain/runtime/agent_runtime.py +7 -2
- package/lattice_brain/runtime/contracts.py +2 -1
- package/lattice_brain/runtime/hooks.py +1 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/lattice_brain/workflow.py +10 -7
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/admin.py +2 -2
- package/latticeai/api/chat.py +19 -15
- package/latticeai/api/chat_agent_http.py +19 -7
- package/latticeai/api/chat_helpers.py +9 -8
- package/latticeai/api/chat_stream.py +2 -2
- package/latticeai/api/computer_use.py +2 -2
- package/latticeai/api/hooks.py +4 -2
- package/latticeai/api/local_files.py +8 -4
- package/latticeai/api/mcp.py +2 -2
- package/latticeai/api/models.py +5 -5
- package/latticeai/api/permissions.py +2 -2
- package/latticeai/api/search.py +5 -3
- package/latticeai/api/security_dashboard.py +3 -5
- package/latticeai/api/setup.py +3 -3
- package/latticeai/api/static_routes.py +7 -2
- package/latticeai/api/tools.py +9 -4
- package/latticeai/api/workspace.py +25 -22
- package/latticeai/app_factory.py +132 -1346
- package/latticeai/cli/entrypoint.py +1 -1
- package/latticeai/core/agent.py +28 -14
- package/latticeai/core/audit.py +5 -3
- package/latticeai/core/embedding_providers.py +19 -6
- package/latticeai/core/legacy_compatibility.py +1 -1
- package/latticeai/core/marketplace.py +2 -2
- package/latticeai/core/mcp_catalog.py +3 -1
- package/latticeai/core/model_compat.py +1 -1
- package/latticeai/core/plugins.py +1 -1
- package/latticeai/core/project_sessions.py +1 -1
- package/latticeai/core/run_explain.py +6 -4
- package/latticeai/core/workspace_os.py +0 -4
- package/latticeai/core/workspace_os_constants.py +1 -1
- package/latticeai/core/workspace_os_state.py +1 -1
- package/latticeai/core/workspace_snapshots.py +3 -3
- package/latticeai/integrations/telegram_bot.py +52 -3
- package/latticeai/models/router.py +61 -34
- package/latticeai/runtime/access_runtime.py +3 -1
- package/latticeai/runtime/build_phases.py +1417 -0
- package/latticeai/runtime/history_writer.py +138 -0
- package/latticeai/runtime/review_wiring.py +6 -1
- package/latticeai/runtime/runtime_context.py +276 -0
- package/latticeai/runtime/sso_config_runtime.py +1 -1
- package/latticeai/runtime/stages.py +8 -2
- package/latticeai/services/app_context.py +23 -0
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/brain_intelligence.py +4 -2
- package/latticeai/services/cloud_streaming.py +5 -3
- package/latticeai/services/command_center.py +1 -1
- package/latticeai/services/evidence_actions.py +2 -1
- package/latticeai/services/hybrid_chat.py +1 -1
- package/latticeai/services/local_knowledge.py +25 -9
- package/latticeai/services/memory_service.py +8 -4
- package/latticeai/services/model_catalog.py +12 -12
- package/latticeai/services/model_engines.py +15 -17
- package/latticeai/services/model_loading.py +1 -1
- package/latticeai/services/model_runtime.py +31 -33
- package/latticeai/services/multimodal_streaming.py +10 -4
- package/latticeai/services/openai_compatible_adapter.py +4 -3
- package/latticeai/services/product_readiness.py +1 -1
- package/latticeai/services/run_executor.py +12 -3
- package/latticeai/services/search_service.py +1 -1
- package/latticeai/services/triggers.py +1 -1
- package/latticeai/setup/auto_setup.py +1 -1
- package/latticeai/setup/wizard.py +12 -3
- package/latticeai/tools/computer.py +3 -1
- package/latticeai/tools/documents.py +2 -2
- 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-BK__Y5VE.js} +1 -1
- package/static/app/assets/{AdminConsole-LgCkXpnf.js → AdminConsole-ZrTyN8_F.js} +1 -1
- package/static/app/assets/{Brain-CoPGJI1L.js → Brain-CYHDXpPB.js} +1 -1
- package/static/app/assets/{BrainHome-gVnaxSwp.js → BrainHome-bbJulb5g.js} +1 -1
- package/static/app/assets/{BrainSignals-ChxAYHtj.js → BrainSignals-CesSPtUP.js} +1 -1
- package/static/app/assets/{Capture-DBtgkHZg.js → Capture-p5upXmz2.js} +1 -1
- package/static/app/assets/{CommandPalette-Ovtv5I0Y.js → CommandPalette-0zkyC0RY.js} +1 -1
- package/static/app/assets/Library-Dt-vABI2.js +1 -0
- package/static/app/assets/{LivingBrain-CNz-6NSd.js → LivingBrain-Bz-h6LBH.js} +1 -1
- package/static/app/assets/{ProductFlow-ePX-Y73J.js → ProductFlow-DAZ7DJCE.js} +1 -1
- package/static/app/assets/{ReviewCard-C4mpvkwH.js → ReviewCard-Bv0WGbY6.js} +1 -1
- package/static/app/assets/{System-BvWNK1zc.js → System-BhrJQSD_.js} +1 -1
- package/static/app/assets/{activity-CiauPV_3.js → activity-AolpZJCH.js} +1 -1
- package/static/app/assets/{bot-Dwct-Q1x.js → bot-CsVsT2nd.js} +1 -1
- package/static/app/assets/{brain-BKDW1F0T.js → brain-vuppco5y.js} +1 -1
- package/static/app/assets/{button-CCB9Kuw7.js → button-1BP1PJZ3.js} +1 -1
- package/static/app/assets/{circle-pause-DNa8WHC5.js → circle-pause-5paeCOtq.js} +1 -1
- package/static/app/assets/{circle-play-8jmxn5mf.js → circle-play-By8mFYRV.js} +1 -1
- package/static/app/assets/{cpu-mxvF3V1I.js → cpu-DvUQxdKe.js} +1 -1
- package/static/app/assets/{download--SmCcx0p.js → download-CFqYG90a.js} +1 -1
- package/static/app/assets/{folder-open-D4Wy5roo.js → folder-open-CVSnp-Dp.js} +1 -1
- package/static/app/assets/{hard-drive-BwQcSPlS.js → hard-drive-Ckr4Vd6-.js} +1 -1
- package/static/app/assets/{index-DDV2YZwM.js → index--0zKF5Ow.js} +3 -3
- package/static/app/assets/index-CEkL4_M-.css +2 -0
- package/static/app/assets/{input-DFhSjmLS.js → input-D-JKquXU.js} +1 -1
- package/static/app/assets/{network-Bts7VO94.js → network-DB88FZ2T.js} +1 -1
- package/static/app/assets/{primitives-BuSMEJY8.js → primitives-D8U9OaIo.js} +1 -1
- package/static/app/assets/search-B8jsVTw_.js +1 -0
- package/static/app/assets/{shield-alert-BfTO6X_G.js → shield-alert-DnsvO79P.js} +1 -1
- package/static/app/assets/{textarea-BjctW1oh.js → textarea-4RchwbTa.js} +1 -1
- package/static/app/assets/{useFocusTrap-CE43-LrA.js → useFocusTrap-CFJjy7cS.js} +1 -1
- package/static/app/assets/{useQuery-Bv3ejLL5.js → useQuery-3Reu-A4a.js} +1 -1
- package/static/app/assets/{users-CsNqLZAj.js → users-BTxYksxa.js} +1 -1
- package/static/app/assets/{utils-KFFdVG_t.js → utils-D02Vf-fw.js} +1 -1
- package/static/app/assets/{workspace-wdCvdyPF.js → workspace-CSJNgX-C.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.4.0/SCREENSHOT_INDEX.md](output/release/v10.4.0/SCREENSHOT_INDEX.md)
|
|
64
64
|
|
|
65
65
|
## Current Release
|
|
66
66
|
|
|
67
|
-
The current release is **10.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
that
|
|
71
|
-
|
|
72
|
-
- **
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- **
|
|
78
|
-
|
|
79
|
-
is
|
|
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.4.0 — Named Ground**:
|
|
68
|
+
|
|
69
|
+
10.3.0 wrote down what was not measured. 10.4.0 emptied that list — and the
|
|
70
|
+
things that made the list long turned out not to be typing problems.
|
|
71
|
+
|
|
72
|
+
- **The type backlog went from 1,407 errors across 77 modules to zero across
|
|
73
|
+
274.** Two root causes accounted for 954 of them, and both were readability
|
|
74
|
+
problems: a computed `__all__` that made every star-imported name invisible
|
|
75
|
+
to a checker, and an eleven-mixin contract that existed but was written down
|
|
76
|
+
nowhere. Both are now explicit, and both are guarded by tests.
|
|
77
|
+
- **The composition root is no longer one function.** `app_factory._build` went
|
|
78
|
+
from 1,318 lines to 26, split into ten ordered phases sharing a typed
|
|
79
|
+
`RuntimeContext`. The phase order is a contract with a test, not a comment —
|
|
80
|
+
and reading a value before its phase has run fails by name.
|
|
81
|
+
- **Four real defects surfaced on the way**, including one that meant
|
|
82
|
+
`python -m latticeai.server_app` had never worked: `main` was a local inside
|
|
83
|
+
the old closure and was never on the export list.
|
|
84
|
+
- **The surface-parity matrix has no ◐ left.** VS Code gained folder capture,
|
|
85
|
+
artifact cards with their repair/validation flags, and a hardware-derived
|
|
86
|
+
model recommendation; Telegram gained the same artifact card. All four were
|
|
87
|
+
rendering gaps — the sidecar was already reporting the data.
|
|
88
|
+
- **Coverage moved honestly, not to target.** Frontend 28.5% → 32.3% (208 → 337
|
|
89
|
+
tests), Python 71.6% → 71.8% (1,896 → 1,956). Frontend 70% is still roughly
|
|
90
|
+
2,200 statements away, and this release does not claim otherwise.
|
|
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.4.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.4.0-py3-none-any.whl`
|
|
97
|
+
- `dist/ltcai-10.4.0.tar.gz`
|
|
98
|
+
- `ltcai-10.4.0.tgz`
|
|
99
|
+
- `dist/ltcai-10.4.0.vsix`
|
|
100
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_10.4.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,14 @@ 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.4.0 | Named Ground |
|
|
136
|
+
| 10.3.0 | Measured Ground |
|
|
141
137
|
| 10.2.0 | Load-Bearing Fixes |
|
|
142
138
|
| 10.1.1 | Reachable Boundary |
|
|
143
139
|
| 10.1.0 | Hybrid Brain |
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,131 @@ 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.4.0] - 2026-08-02
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- **`app_factory._build` is decomposed.** 1,318 lines → 26. The assembly now
|
|
11
|
+
lives in `latticeai/runtime/build_phases.py` as ten ordered phases sharing a
|
|
12
|
+
typed `latticeai/runtime/runtime_context.py::RuntimeContext`:
|
|
13
|
+
`platform → config → identity → brain → domain → web → services →
|
|
14
|
+
foundation_routes → platform_features → interaction`.
|
|
15
|
+
The single closure worked because closures resolve free variables at call
|
|
16
|
+
time; several sections depend on names bound far below them. The
|
|
17
|
+
RuntimeContext preserves that late binding while naming the shared state.
|
|
18
|
+
`tests/unit/test_runtime_context.py` fixes the phase order, which phase
|
|
19
|
+
produces which attribute, and that reading one early fails by name.
|
|
20
|
+
- **mypy covers the whole tree: 274 of 274 modules, 0 errors** (was 193 of 270
|
|
21
|
+
with 1,407 outstanding). `pyproject.toml`'s `[tool.mypy] files` is no longer
|
|
22
|
+
a curated subset.
|
|
23
|
+
- `lattice_brain/graph/_kg_common.py`'s `__all__` is a literal instead of a
|
|
24
|
+
comprehension over `globals()`. The computed form was invisible to a type
|
|
25
|
+
checker, so twelve modules resolved no names behind
|
|
26
|
+
`from ._kg_common import *` (~750 false `name-defined` errors).
|
|
27
|
+
`tests/unit/test_kg_common_exports.py` keeps the literal honest.
|
|
28
|
+
- The star import of `._kg_fsutil` inside `_kg_common` is now an explicit list
|
|
29
|
+
for the same reason.
|
|
30
|
+
- JSON-shaped payloads in `services/model_runtime.py`, `model_engines.py`,
|
|
31
|
+
`model_catalog.py`, `api/setup.py` and `api/models.py` are typed
|
|
32
|
+
`Dict[str, Any]` rather than `Dict[str, object]`, which forced a cast at
|
|
33
|
+
every nested access without catching anything.
|
|
34
|
+
- Optional dependencies (`AsyncOpenAI`, `mx`, `vlm_load`, `lm_load`,
|
|
35
|
+
`pyautogui`) are aliased on import and re-exported as `Any`, so "installed"
|
|
36
|
+
and "absent" have one declared type.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- `lattice_brain/graph/_kg_contract.py` — the 23-member surface the eleven
|
|
40
|
+
graph mixins share, written down for the first time. Typing-only: `_Core` is
|
|
41
|
+
`object` at runtime, so `KnowledgeGraphStore`'s MRO is unchanged.
|
|
42
|
+
`tests/unit/test_kg_contract.py` asserts both the contract and that it never
|
|
43
|
+
becomes a real base class.
|
|
44
|
+
- `AppContext.require(field)` — binds a dependency a router cannot run without,
|
|
45
|
+
so an absent one names itself at router construction instead of surfacing as
|
|
46
|
+
`'NoneType' object is not callable` inside a request handler.
|
|
47
|
+
- VS Code `ltcai.captureFolder` — folder ingestion through the same
|
|
48
|
+
`/api/ingestion/folder` endpoint and the same local-read approval dance the
|
|
49
|
+
web Capture view uses.
|
|
50
|
+
- VS Code `ltcai.showArtifacts` — `artifacts[]` rendered as cards with the
|
|
51
|
+
server's repair and validation flags, so a deterministically repaired
|
|
52
|
+
scaffold no longer looks identical to clean model output.
|
|
53
|
+
- VS Code model picker now shows the hardware-derived recommendation from
|
|
54
|
+
`GET /setup/scan`, with the server's own reasoning. No scan, no banner.
|
|
55
|
+
- Telegram sends the same `artifacts[]` card summary before the files.
|
|
56
|
+
- Frontend tests for four previously untested modules with real logic:
|
|
57
|
+
`routes.ts`, `store/appStore.ts`, `api/base.ts` error translation, and
|
|
58
|
+
`pages/brain/graphExplorer.ts`.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
- **`python -m latticeai.server_app` raised `AttributeError`.** `main` was a
|
|
62
|
+
local inside the old `_build` closure and was never on the export allowlist,
|
|
63
|
+
so `get_shared_runtime().main()` could never resolve it. `main()` now serves
|
|
64
|
+
the shared runtime directly and needs no export.
|
|
65
|
+
- `core/workspace_os.py`: four lines duplicated after a `return` in
|
|
66
|
+
`remove_member` — dead since the merge that introduced them.
|
|
67
|
+
- `models/router.py`: a `str` shadowed a `dict` in the custom cloud-model loop,
|
|
68
|
+
so those entries built their ids from the wrong variable.
|
|
69
|
+
- `lattice_brain/context.py`: an unconfigured retrieval seam was called
|
|
70
|
+
unguarded and died as a `TypeError` inside failure isolation instead of
|
|
71
|
+
naming itself.
|
|
72
|
+
- `runtime/review_wiring.py` declared its injected `HTTPException` as
|
|
73
|
+
`type[Exception]`, which does not accept `(status_code=, detail=)`.
|
|
74
|
+
- `api/security_dashboard.py`: a defensive `isinstance(rows, list)` re-check
|
|
75
|
+
that every branch above already guaranteed.
|
|
76
|
+
|
|
77
|
+
### Documentation
|
|
78
|
+
- `docs/MYPY_BACKLOG.md` is now the record of how the boundary closed, not a
|
|
79
|
+
list of what is left — including the conventions the sweep settled on.
|
|
80
|
+
- `docs/SURFACE_PARITY.md`: no ◐ remains in the matrix. A stale v9.9.6 note
|
|
81
|
+
claiming the live step timeline was web-only is corrected (v9.9.7's
|
|
82
|
+
`runAgentLive` provides it).
|
|
83
|
+
|
|
84
|
+
## [10.3.0] - 2026-07-29
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
- **Frontend coverage was not being measured.** Vitest reports only files a
|
|
88
|
+
test imports unless `all: true`; untested modules left the denominator
|
|
89
|
+
instead of counting against it. Reported 54%, actual **28.5%**.
|
|
90
|
+
- **Python coverage was over-reported.** `omit = ["*/tests/*"]` does not match
|
|
91
|
+
the repo-relative `tests/...` paths coverage records, so the suite counted
|
|
92
|
+
itself. Reported 80%, actual **71.6%**.
|
|
93
|
+
- `lattice_brain/runtime/hooks.py` referenced `self._path` (does not exist)
|
|
94
|
+
inside the handler for an unreadable registry, turning a recoverable failure
|
|
95
|
+
into `AttributeError`.
|
|
96
|
+
- `lattice_brain/graph/_kg_fsutil.py` used `Iterable` in an annotation without
|
|
97
|
+
importing it.
|
|
98
|
+
- `lattice_brain/runtime/agent_runtime.py` could call `.get` on `None`.
|
|
99
|
+
- `pages/Library.tsx` printed the raw registry coordinate
|
|
100
|
+
(`mlx-community/gemma-4-…`) when a catalog entry had no display name; it now
|
|
101
|
+
falls through `humanizeModelId` like every other model surface.
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
- `latticeai/runtime/history_writer.py` — `save_to_history` extracted from the
|
|
105
|
+
`app_factory._build` closure with its ordering contract documented, plus 14
|
|
106
|
+
tests (`tests/unit/test_history_writer.py`).
|
|
107
|
+
- `frontend/src/test/renderPage.tsx` — a page-level harness that stubs the
|
|
108
|
+
whole `latticeApi` surface, making error states, empty states and both
|
|
109
|
+
languages reachable in unit tests.
|
|
110
|
+
- First unit tests for every page: `System` (11), `Library` (7), `Capture` (6),
|
|
111
|
+
`Act` (8), `Brain` (8). Frontend suite 154 → 208 tests.
|
|
112
|
+
- Python tests for boundaries that had none: Telegram allowlist (26),
|
|
113
|
+
`run_command` containment (34), audit log and sensitivity report (22),
|
|
114
|
+
model-load consent gates (14), connection lifecycle guards. 1,786 → 1,896.
|
|
115
|
+
- `docs/MYPY_BACKLOG.md` — the 77 modules still outside type checking with
|
|
116
|
+
per-module error counts, smallest first.
|
|
117
|
+
- ARCHITECTURE.md "Verification Surface" diagram: which figures gate CI and
|
|
118
|
+
which are only reported.
|
|
119
|
+
|
|
120
|
+
### Changed
|
|
121
|
+
- mypy adopted set: 13 → **193 of 270** modules.
|
|
122
|
+
- `vitest.config.ts` gains a coverage block with `all: true`.
|
|
123
|
+
- `npm run test:frontend:coverage` added.
|
|
124
|
+
|
|
125
|
+
### Known
|
|
126
|
+
- `app_factory._build` remains ~1,300 lines; only the history writer was
|
|
127
|
+
extracted this release.
|
|
128
|
+
- Frontend coverage (28.5%) is reported but not gated — flooring it at today's
|
|
129
|
+
figure would freeze it there.
|
|
130
|
+
- 77 modules remain outside mypy; see the backlog.
|
|
131
|
+
|
|
7
132
|
## [10.2.0] - 2026-07-29
|
|
8
133
|
|
|
9
134
|
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.4.0 — Named 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.4.0 — Named 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,65 @@
|
|
|
1
|
+
# mypy backlog
|
|
2
|
+
|
|
3
|
+
> **Status: reference**
|
|
4
|
+
> 10.2.0: 13 modules checked. 10.3.0: 193 of 270, with the remaining 77 listed
|
|
5
|
+
> here by error count. **10.4.0: 274 of 274 — the backlog is empty.**
|
|
6
|
+
|
|
7
|
+
`[tool.mypy] files` in `pyproject.toml` now lists **every** module in
|
|
8
|
+
`lattice_brain/` and `latticeai/`. There is no "adopted set" any more; adding a
|
|
9
|
+
module to the tree adds it to the checked set, and CI fails if it does not
|
|
10
|
+
type-check.
|
|
11
|
+
|
|
12
|
+
This file stays as the record of how the boundary closed, because two of the
|
|
13
|
+
1,407 errors 10.3.0 measured turned out to be worth more than the annotations.
|
|
14
|
+
|
|
15
|
+
## Two root causes were 68% of the backlog
|
|
16
|
+
|
|
17
|
+
**`_kg_common.__all__` was computed** (`[name for name in globals() if not
|
|
18
|
+
name.startswith("__")]`). Correct at runtime, opaque to a checker: mypy could
|
|
19
|
+
not resolve a single name behind `from ._kg_common import *`, so twelve graph
|
|
20
|
+
modules reported **~750 false `name-defined` errors** and stayed unchecked.
|
|
21
|
+
Freezing the list to a literal fixed all of them.
|
|
22
|
+
`tests/unit/test_kg_common_exports.py` asserts the literal still equals what
|
|
23
|
+
the expression would produce, so it cannot drift.
|
|
24
|
+
|
|
25
|
+
**The eleven graph mixins had an unwritten contract.** `ingest` calls
|
|
26
|
+
`_upsert_node` from `write_master`, which calls `_v2_project_node` from
|
|
27
|
+
`projection`, and everything calls `_connect` — 229 `attr-defined` errors,
|
|
28
|
+
because from a checker's position each mixin is a bare class calling methods it
|
|
29
|
+
does not have. `lattice_brain/graph/_kg_contract.py` writes that contract down:
|
|
30
|
+
23 declared members, typing-only (`_Core` is `object` at runtime, so the MRO is
|
|
31
|
+
unchanged), verified by `tests/unit/test_kg_contract.py`.
|
|
32
|
+
|
|
33
|
+
Neither was a typing problem. Both were *readability* problems that a reader
|
|
34
|
+
had to solve by grepping eleven files.
|
|
35
|
+
|
|
36
|
+
## Real defects the remaining work surfaced
|
|
37
|
+
|
|
38
|
+
| defect | module | why it mattered |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| four lines duplicated after a `return` | `core/workspace_os.py` | dead since the merge that introduced it; `remove_member` looked like it did its work twice |
|
|
41
|
+
| `main` was never exported | `app_factory.py` | `python -m latticeai.server_app` raised `AttributeError` — the module entrypoint did not run |
|
|
42
|
+
| `str` shadowed a `dict` in a loop | `models/router.py` | the custom-cloud-model branch built ids from the wrong variable |
|
|
43
|
+
| `Optional` seam called unguarded | `lattice_brain/context.py` | an unconfigured retrieval port raised `TypeError` inside failure isolation instead of naming itself |
|
|
44
|
+
|
|
45
|
+
(10.3.0 found three more the same way: `self._path` inside an error handler,
|
|
46
|
+
`Iterable` used without importing it, and `.get` on a possible `None`.)
|
|
47
|
+
|
|
48
|
+
## Conventions the sweep settled on
|
|
49
|
+
|
|
50
|
+
* **JSON-shaped payloads are `Dict[str, Any]`, not `Dict[str, object]`.**
|
|
51
|
+
`object` forced a cast at every nested access without catching anything;
|
|
52
|
+
the value really is arbitrary JSON.
|
|
53
|
+
* **Optional dependencies are aliased, then re-exported as `Any`**
|
|
54
|
+
(`AsyncOpenAI`, `mx`, `vlm_load`, `pyautogui`), so "installed" and "absent"
|
|
55
|
+
have the same declared type and call sites keep their historical name.
|
|
56
|
+
* **Async generators in Protocols are declared with `def`, not `async def`.**
|
|
57
|
+
`async def … -> AsyncIterator[T]` says "a coroutine resolving to an
|
|
58
|
+
iterator", which no implementation does.
|
|
59
|
+
* **A router dependency it cannot run without is bound through
|
|
60
|
+
`AppContext.require("name")`** — an absent dependency names itself at router
|
|
61
|
+
construction instead of surfacing as `'NoneType' object is not callable`
|
|
62
|
+
inside a request handler.
|
|
63
|
+
* **A defensive `isinstance` check on a parameter means the annotation is
|
|
64
|
+
wrong.** Widen the parameter (`Any`, `Optional[str]`) rather than deleting
|
|
65
|
+
the guard: the guard is what the callers actually need.
|
package/docs/ONBOARDING.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI Onboarding
|
|
2
2
|
|
|
3
|
-
Current release: **10.
|
|
3
|
+
Current release: **10.4.0 — Named 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/SURFACE_PARITY.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> **Status: reference**
|
|
4
4
|
> 도입: v9.9.4 (2026-07-25, 리뷰 Wave 1.4 "표면 패리티 체크리스트").
|
|
5
|
-
> 갱신: v9.9.7 — 표에 남아 있던 ✖ 갭을 **전부** 해소.
|
|
5
|
+
> 갱신: v9.9.7 — 표에 남아 있던 ✖ 갭을 **전부** 해소.
|
|
6
|
+
> 갱신: **v10.4.0 — 남아 있던 ◐(부분 제공)를 전부 해소.** 표에 ◐ 는 더 이상 없다.
|
|
6
7
|
> 목적: 각 표면(서피스)이 Brain 계약의 어디까지를 제공하는지 **정직하게** 기록한다.
|
|
7
8
|
> "앱마다 다른 Lattice"를 방지하는 기준표이며, 기능을 과장하지 않는다.
|
|
8
9
|
|
|
@@ -22,9 +23,9 @@
|
|
|
22
23
|
|
|
23
24
|
| 루프 순간 | Web `/app` | Desktop | VS Code | Browser | Telegram |
|
|
24
25
|
| --- | --- | --- | --- | --- | --- |
|
|
25
|
-
| 첫 저장 (Capture) | ✅ DnD·폴더·웹 수집, 품질 경고 | ✅ (웹과 동일) |
|
|
26
|
+
| 첫 저장 (Capture) | ✅ DnD·폴더·웹 수집, 품질 경고 | ✅ (웹과 동일) | ✅ `sendToLattice` 파일/선택 + `captureFolder` 폴더 수집 (v10.4.0) | ✅ 페이지 캡처 (단일 목적) | ✅ 메시지 + 문서/사진 업로드 수집 |
|
|
26
27
|
| 첫 회상 (Recall) | ✅ 하이브리드 검색 + grounding 배지 + 출처→청크 | ✅ (동일) | ✅ `askCurrentFile`/`askBrain` — 동일 `/chat` grounding 배지 | ✅ 팝업 질문 + 동일 grounding 배지 (v9.9.7) | ✅ 답변 + grounding 배지 (v9.9.7) |
|
|
27
|
-
| 첫 산출물 (Artifact) | ✅ artifacts[] 카드·미리보기·Brain 기억 칩 | ✅ (동일) |
|
|
28
|
+
| 첫 산출물 (Artifact) | ✅ artifacts[] 카드·미리보기·Brain 기억 칩 | ✅ (동일) | ✅ `createFile` + `showArtifacts` 카드(보정/검증 플래그 포함, v10.4.0) | — (의도: 브라우저에서 파일 쓰기 없음) | ✅ 파일 + artifacts[] 카드 요약 (v10.4.0) |
|
|
28
29
|
| 첫 보호 (Approval) | ✅ 승인 카드 + TTL 카운트다운 + 재시작 생존 | ✅ (동일) | ✅ List/Approve/Reject 커맨드 + 토큰 캐시 | ✅ 대기 건수 표시 (승인은 웹에서, v9.9.7) | ✅ 인라인 Done/Cancel + run_id/token 재개 |
|
|
29
30
|
|
|
30
31
|
## 기능 상세 × 표면
|
|
@@ -42,14 +43,14 @@
|
|
|
42
43
|
| Watch 상태 신호 (v9.9.4) | ✅ 홈 카드 | ✅ | — | — | — |
|
|
43
44
|
| Review Center (제안 승인/거절) | ✅ | ✅ | ✅ `ltcai.reviewCenter` (409 충돌 정직 보고) | — (의도: 승인은 웹/에디터/봇에서) | ✅ `/review` + 인라인 승인/거절 (v9.9.7) |
|
|
44
45
|
| 데모 코퍼스 First Value Loop | ✅ | ✅ | — | — | — |
|
|
45
|
-
| 모델 로드/추천 | ✅ | ✅ |
|
|
46
|
+
| 모델 로드/추천 | ✅ | ✅ | ✅ `loadModel` + 하드웨어 기반 추천·근거 (v10.4.0) | — (의도) | — (의도) |
|
|
46
47
|
| 코드 편집 보조 (edit/explain/refactor/tests) | — | — | ✅ | — | — |
|
|
47
48
|
|
|
48
49
|
## 규칙
|
|
49
50
|
|
|
50
51
|
1. **API 계약이 기준이다.** 모든 표면은 동일한 sidecar API를 소비한다. 표면별 전용 API를 만들지 않는다.
|
|
51
52
|
2. **◐/✖ 는 문서화된 상태로만 존재한다.** 새 기능을 Web에 추가할 때 이 표를 갱신하고, 다른 표면에 제공하지 않을 경우 "—(의도)" 인지 "✖(갭)" 인지 명시한다.
|
|
52
|
-
3. **✖ 갭은 릴리스 노트의 Honest Limitations 후보다.** v9.9.7
|
|
53
|
+
3. **✖ 갭은 릴리스 노트의 Honest Limitations 후보다.** v9.9.7 이후 표에 남은 ✖는 **없고**, v10.4.0 이후 ◐ 도 **없다**.
|
|
53
54
|
- 남은 "—"는 전부 **설계 경계**이며, 각 항목에 이유를 함께 적는다. 예: 브라우저 확장은 파일을 쓰지 않으므로 산출물 생성이 없고, 승인 *결정*은 서명된 토큰이 필요한 흐름이라 대기 건수만 보여 주고 승인은 웹/에디터/봇에서 한다.
|
|
54
55
|
- 경계를 새로 만들 때는 "왜 제공하지 않는가"를 이 문서에 남긴다. 이유 없는 "—"는 갭이지 경계가 아니다.
|
|
55
56
|
4. 릴리스마다 이 표를 검토한다 (release checklist의 docs 단계).
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
|
|
64
65
|
- **회상 배지**: `askCurrentFile` / `askBrain`은 웹과 동일한 `POST /chat` 응답의 `grounding` 판정을 그대로 읽는다. 판정이 없으면 "근거 있음"으로 승격하지 않고 `unknown`으로 보고한다 (`vscode-extension/surface.ts::groundingBadge`).
|
|
65
66
|
- **Review Center**: `ltcai.reviewCenter`는 웹과 같은 `/api/proposals` 표면을 쓴다. 승인은 검토한 내용 그대로 적용하고, 409(스테이징 이후 파일 변경)는 "아무것도 쓰지 않았다"고 정직하게 알린다.
|
|
66
|
-
- **스텝 요약**: `ltcai.runAgent`는 실행 후 `steps`/`created_files`/`explanation`을 출력 채널에 요약한다. 라이브 SSE 타임라인은
|
|
67
|
+
- **스텝 요약**: `ltcai.runAgent`는 실행 후 `steps`/`created_files`/`explanation`을 출력 채널에 요약한다. (라이브 SSE 타임라인은 v9.9.7의 `ltcai.runAgentLive`가 같은 `agent_step` 프레임으로 제공한다 — 이 메모는 v9.9.6 시점 기준이었다.)
|
|
67
68
|
- 파싱 계약은 `tests/vscode-extension.test.cjs`가 sidecar 페이로드 모양 그대로 검증한다.
|
|
68
69
|
|
|
69
70
|
## v9.9.7 — 남은 갭을 닫은 방법
|
|
@@ -81,3 +82,29 @@
|
|
|
81
82
|
- **Browser 확장**: 캡처 전용 경계를 넘어 `/chat` 질문과 `agent/approvals` 대기
|
|
82
83
|
건수를 보여 준다. **판정을 로컬에서 계산하지 않는다** — 판정이 없으면
|
|
83
84
|
"근거 확인 불가"이며 절대 "근거 있음"으로 승격하지 않는다.
|
|
85
|
+
|
|
86
|
+
## v10.4.0 — 마지막 ◐ 셋을 닫은 방법
|
|
87
|
+
|
|
88
|
+
세 갭 모두 **계약의 문제가 아니라 렌더링의 문제**였다. 사이드카는 이미 필요한
|
|
89
|
+
데이터를 내고 있었고, 에디터/봇이 그것을 버리고 있었다.
|
|
90
|
+
|
|
91
|
+
- **VS Code 폴더 수집** (`ltcai.captureFolder`): 웹 Capture 와 **같은**
|
|
92
|
+
`POST /api/ingestion/folder` 를 쓴다. 로컬 디스크를 읽으므로 승인 절차도
|
|
93
|
+
동일하다 — 토큰 없는 첫 호출은 `permission_required` 이고, 확장은 그것을
|
|
94
|
+
그대로 보여 준다(조용히 재시도하지 않는다). 백그라운드 job 으로 큐잉되며
|
|
95
|
+
진행 상황은 웹에서 본다.
|
|
96
|
+
- **VS Code 산출물 카드** (`ltcai.showArtifacts`): `/agent` 응답의
|
|
97
|
+
`artifacts[]` 를 그대로 읽는다. 결정적으로 **보정된(repaired) 스캐폴드와
|
|
98
|
+
깨끗한 모델 출력이 구분된다** — 이전에는 평평한 경로 목록이라 둘이 같아
|
|
99
|
+
보였다. 서버의 `valid=false` 판정을 확장이 성공으로 승격하지 않는다.
|
|
100
|
+
구형 사이드카(`created_files` 만 있는 응답)는 "세부 정보 없음"이라고
|
|
101
|
+
정직하게 말한다.
|
|
102
|
+
- **VS Code 모델 추천**: `GET /setup/scan` 의 `zero_config.recommend` 를
|
|
103
|
+
읽어 **이 기기에 왜 이 모델인지**를 근거와 함께 보여 준다. 스캔이 없으면
|
|
104
|
+
배너도 없다 — 이유를 지어내지 않는다.
|
|
105
|
+
- **Telegram 산출물 카드**: 같은 `artifacts[]` 플래그를 파일 전송 직전에
|
|
106
|
+
요약한다. 8개까지 나열하고 나머지는 `… +N` 으로 정직하게 줄인다.
|
|
107
|
+
|
|
108
|
+
계약 테스트: `tests/vscode-extension.test.cjs` (19), `tests/unit/test_telegram_security.py`.
|
|
109
|
+
전부 사이드카 페이로드 모양 그대로 검증하며, 확장/봇이 서버 판정을 재계산하지
|
|
110
|
+
않는지도 함께 고정한다.
|
package/docs/TRUST_MODEL.md
CHANGED
package/docs/WHY_LATTICE.md
CHANGED
package/docs/kg-schema.md
CHANGED
package/lattice_brain/context.py
CHANGED
|
@@ -24,14 +24,27 @@ def approx_tokens(text: str) -> int:
|
|
|
24
24
|
return max(0, (len(text or "") + 3) // 4)
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
class _SeamUnavailable(RuntimeError):
|
|
28
|
+
"""Raised when a context seam is called but was never configured."""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _call_context_seam(
|
|
32
|
+
callback: Optional[Callable[..., Any]], query: str, **context: Any
|
|
33
|
+
) -> Any:
|
|
28
34
|
"""Pass identity/scope only when a legacy seam declares support for it.
|
|
29
35
|
|
|
30
36
|
Signature inspection preserves old one-argument adapters without catching
|
|
31
37
|
a callback's own ``TypeError`` and retrying it with less restrictive scope.
|
|
32
38
|
If a callable cannot be inspected, the secure behavior is to pass every
|
|
33
39
|
context field and let the caller's failure isolation omit that section.
|
|
40
|
+
|
|
41
|
+
``callback`` is Optional because the seams themselves are: an assembler
|
|
42
|
+
built without a hybrid-search port simply has no knowledge section. The
|
|
43
|
+
section builders already run inside failure isolation, so an unconfigured
|
|
44
|
+
seam degrades to "section omitted" rather than crashing the turn.
|
|
34
45
|
"""
|
|
46
|
+
if callback is None:
|
|
47
|
+
raise _SeamUnavailable("seam is not configured")
|
|
35
48
|
try:
|
|
36
49
|
parameters = inspect.signature(callback).parameters
|
|
37
50
|
except (TypeError, ValueError):
|
|
@@ -47,8 +60,12 @@ def _call_context_seam(callback: Callable[..., Any], query: str, **context: Any)
|
|
|
47
60
|
return callback(query, **supported)
|
|
48
61
|
|
|
49
62
|
|
|
50
|
-
def _call_keyword_seam(
|
|
63
|
+
def _call_keyword_seam(
|
|
64
|
+
callback: Optional[Callable[..., Any]], **context: Any
|
|
65
|
+
) -> Any:
|
|
51
66
|
"""Invoke a keyword-only seam while preserving legacy narrow signatures."""
|
|
67
|
+
if callback is None:
|
|
68
|
+
raise _SeamUnavailable("seam is not configured")
|
|
52
69
|
try:
|
|
53
70
|
parameters = inspect.signature(callback).parameters
|
|
54
71
|
except (TypeError, ValueError):
|
|
@@ -177,7 +194,10 @@ class ContextAssembler:
|
|
|
177
194
|
# ── section builders (each failure-isolated and honest) ───────────────
|
|
178
195
|
def _memories_section(self, query, user_email, workspace_id, limit) -> ContextSection:
|
|
179
196
|
try:
|
|
180
|
-
|
|
197
|
+
recall_seam = self._memory_recall
|
|
198
|
+
if recall_seam is None:
|
|
199
|
+
raise _SeamUnavailable("memory_recall is not configured")
|
|
200
|
+
recall = recall_seam(query, user_email=user_email, workspace_id=workspace_id, limit=limit)
|
|
181
201
|
results = [r for r in recall.get("results", []) if r.get("source") == "workspace"][:limit]
|
|
182
202
|
except Exception as exc:
|
|
183
203
|
logging.debug("context: memory recall failed: %s", exc)
|