ltcai 3.5.0 → 4.0.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 +73 -35
- package/docs/CARRYOVER_AUDIT_v3.6.0.md +61 -0
- package/docs/CHANGELOG.md +32 -0
- package/docs/HANDOVER_v3.6.0.md +46 -0
- package/docs/RUNTIME_HOOK_COVERAGE_v3.6.0.md +49 -0
- package/docs/V4_BRAIN_ARCHITECTURE.md +322 -0
- package/docs/V4_DIGITAL_BRAIN_RECOVERY.md +509 -0
- package/docs/V4_IMPLEMENTATION_PLAN.md +470 -0
- package/docs/architecture.md +13 -12
- package/docs/kg-schema.md +102 -53
- package/docs/privacy.md +18 -2
- package/docs/security-model.md +17 -0
- package/kg_schema.py +139 -10
- package/knowledge_graph.py +874 -26
- package/knowledge_graph_api.py +11 -127
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/admin.py +1 -1
- package/latticeai/api/agents.py +7 -1
- package/latticeai/api/auth.py +27 -4
- package/latticeai/api/browser.py +217 -0
- package/latticeai/api/chat.py +112 -76
- package/latticeai/api/health.py +1 -1
- package/latticeai/api/hooks.py +1 -1
- package/latticeai/api/knowledge_graph.py +146 -0
- package/latticeai/api/local_files.py +1 -1
- package/latticeai/api/mcp.py +23 -11
- package/latticeai/api/memory.py +1 -1
- package/latticeai/api/models.py +1 -1
- package/latticeai/api/network.py +81 -0
- package/latticeai/api/portability.py +93 -0
- package/latticeai/api/realtime.py +1 -1
- package/latticeai/api/search.py +26 -2
- package/latticeai/api/security_dashboard.py +2 -3
- package/latticeai/api/setup.py +2 -2
- package/latticeai/api/static_routes.py +2 -4
- package/latticeai/api/tools.py +3 -0
- package/latticeai/api/workflow_designer.py +46 -0
- package/latticeai/api/workspace.py +71 -49
- package/latticeai/app_factory.py +1710 -0
- package/latticeai/brain/__init__.py +18 -0
- package/latticeai/brain/context.py +213 -0
- package/latticeai/brain/conversations.py +236 -0
- package/latticeai/brain/identity.py +175 -0
- package/latticeai/brain/memory.py +102 -0
- package/latticeai/brain/network.py +205 -0
- package/latticeai/core/agent.py +31 -7
- package/latticeai/core/audit.py +0 -7
- package/latticeai/core/config.py +1 -1
- package/latticeai/core/context_builder.py +1 -2
- package/latticeai/core/enterprise.py +1 -1
- package/latticeai/core/graph_curator.py +2 -2
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/mcp_registry.py +791 -0
- package/latticeai/core/model_compat.py +1 -1
- package/latticeai/core/model_resolution.py +0 -1
- package/latticeai/core/multi_agent.py +238 -4
- package/latticeai/core/security.py +1 -1
- package/latticeai/core/sessions.py +37 -7
- package/latticeai/core/workflow_engine.py +114 -2
- package/latticeai/core/workspace_os.py +58 -10
- package/latticeai/models/__init__.py +7 -0
- package/latticeai/models/router.py +779 -0
- package/latticeai/server_app.py +29 -1504
- package/latticeai/services/agent_runtime.py +1 -0
- package/latticeai/services/app_context.py +75 -14
- package/latticeai/services/ingestion.py +318 -0
- package/latticeai/services/kg_portability.py +207 -0
- package/latticeai/services/memory_service.py +39 -11
- package/latticeai/services/model_runtime.py +2 -5
- package/latticeai/services/platform_runtime.py +100 -23
- package/latticeai/services/search_service.py +17 -8
- package/latticeai/services/tool_dispatch.py +12 -2
- package/latticeai/services/triggers.py +241 -0
- package/latticeai/services/upload_service.py +37 -12
- package/latticeai/services/workspace_service.py +31 -0
- package/llm_router.py +29 -772
- package/ltcai_cli.py +1 -2
- package/mcp_registry.py +25 -788
- package/p_reinforce.py +124 -14
- package/package.json +11 -8
- package/scripts/build_vsix.mjs +72 -0
- package/scripts/bump_version.py +99 -0
- package/scripts/generate_diagrams.py +0 -1
- package/scripts/lint_v3.mjs +82 -18
- package/scripts/validate_release_artifacts.py +0 -1
- package/scripts/wheel_smoke.py +142 -0
- package/server.py +11 -7
- package/setup_wizard.py +1142 -0
- package/static/account.html +2 -4
- package/static/admin.html +3 -5
- package/static/chat.html +3 -6
- package/static/graph.html +2 -4
- package/static/sw.js +81 -52
- package/static/v3/asset-manifest.json +20 -19
- package/static/v3/css/{lattice.base.e4cdd05d.css → lattice.base.49deefb5.css} +1 -1
- package/static/v3/css/lattice.base.css +1 -1
- package/static/v3/css/{lattice.components.9b49d614.css → lattice.components.cde18231.css} +1 -1
- package/static/v3/css/lattice.components.css +1 -1
- package/static/v3/css/{lattice.shell.8fcc9d33.css → lattice.shell.29d36d85.css} +1 -1
- package/static/v3/css/lattice.shell.css +1 -1
- package/static/v3/css/{lattice.tokens.e7018963.css → lattice.tokens.304cbc40.css} +3 -0
- package/static/v3/css/lattice.tokens.css +3 -0
- package/static/v3/css/{lattice.views.22f69117.css → lattice.views.0a18b6c5.css} +2 -2
- package/static/v3/css/lattice.views.css +2 -2
- package/static/v3/index.html +3 -4
- package/static/v3/js/{app.d086489d.js → app.356e6452.js} +1 -1
- package/static/v3/js/core/{api.12b568ad.js → api.7a308b89.js} +39 -1
- package/static/v3/js/core/api.js +38 -0
- package/static/v3/js/core/{routes.d214b399.js → routes.7222343d.js} +22 -22
- package/static/v3/js/core/routes.js +22 -22
- package/static/v3/js/core/{shell.d05266f5.js → shell.a1657f20.js} +4 -4
- package/static/v3/js/core/shell.js +1 -1
- package/static/v3/js/core/{store.34ebd5e6.js → store.204a08b2.js} +1 -1
- package/static/v3/js/core/store.js +1 -1
- package/static/v3/js/views/graph-canvas.17c15d65.js +509 -0
- package/static/v3/js/views/graph-canvas.js +509 -0
- package/static/v3/js/views/{hybrid-search.b22b97e0.js → hybrid-search.2fb63ed9.js} +1 -2
- package/static/v3/js/views/hybrid-search.js +1 -2
- package/static/v3/js/views/knowledge-graph.5e40cbeb.js +509 -0
- package/static/v3/js/views/knowledge-graph.js +326 -54
- package/static/vendor/chart.umd.min.js +20 -0
- package/static/vendor/fonts/inter-latin-300-normal.woff2 +0 -0
- package/static/vendor/fonts/inter-latin-400-normal.woff2 +0 -0
- package/static/vendor/fonts/inter-latin-500-normal.woff2 +0 -0
- package/static/vendor/fonts/inter-latin-600-normal.woff2 +0 -0
- package/static/vendor/fonts/inter-latin-700-normal.woff2 +0 -0
- package/static/vendor/fonts/inter-latin-800-normal.woff2 +0 -0
- package/static/vendor/fonts/inter.css +44 -0
- package/static/vendor/icons/tabler-icons.min.css +4 -0
- package/static/vendor/icons/tabler-icons.woff2 +0 -0
- package/static/vendor/marked.min.js +69 -0
- package/static/workspace.html +2 -2
- package/telegram_bot.py +1 -2
- package/tools/commands.py +4 -2
- package/tools/computer.py +1 -1
- package/tools/documents.py +1 -3
- package/tools/filesystem.py +0 -4
- package/tools/knowledge.py +1 -3
- package/tools/network.py +1 -3
- package/codex_telegram_bot.py +0 -195
- package/docs/assets/v3.4.0/agent-run.png +0 -0
- package/docs/assets/v3.4.0/agents.png +0 -0
- package/docs/assets/v3.4.0/before/chat-before.png +0 -0
- package/docs/assets/v3.4.0/before/files-before.png +0 -0
- package/docs/assets/v3.4.0/chat.png +0 -0
- package/docs/assets/v3.4.0/connect-folder.png +0 -0
- package/docs/assets/v3.4.0/files.png +0 -0
- package/docs/assets/v3.4.0/home.png +0 -0
- package/docs/assets/v3.4.0/hooks-dispatch.png +0 -0
- package/docs/assets/v3.4.0/knowledge-graph.png +0 -0
- package/docs/assets/v3.4.0/local-agent.png +0 -0
- package/docs/assets/v3.4.0/memory.png +0 -0
- package/docs/assets/v3.4.0/settings.png +0 -0
- package/docs/assets/v3.4.0/vision-input.png +0 -0
- package/docs/assets/v3.4.0/workflows.png +0 -0
- package/docs/assets/v3.4.1/e2e_runtime_log.txt +0 -42
- package/docs/assets/v3.4.1/hooks-dispatch.png +0 -0
- package/docs/assets/v3.4.1/local-agent.png +0 -0
- package/docs/images/admin-dashboard.png +0 -0
- package/docs/images/architecture.png +0 -0
- package/docs/images/enterprise.png +0 -0
- package/docs/images/graph.png +0 -0
- package/docs/images/hero.gif +0 -0
- package/docs/images/knowledge-graph.png +0 -0
- package/docs/images/lattice-ai-demo.gif +0 -0
- package/docs/images/lattice-ai-hero.png +0 -0
- package/docs/images/logo.svg +0 -33
- package/docs/images/mobile-responsive.png +0 -0
- package/docs/images/model-recommendation.png +0 -0
- package/docs/images/onboarding.png +0 -0
- package/docs/images/organization.png +0 -0
- package/docs/images/pipeline.png +0 -0
- package/docs/images/screenshot-admin.png +0 -0
- package/docs/images/screenshot-chat.png +0 -0
- package/docs/images/screenshot-graph.png +0 -0
- package/docs/images/skills.png +0 -0
- package/docs/images/workspace-dark.png +0 -0
- package/docs/images/workspace-light.png +0 -0
- package/docs/images/workspace.png +0 -0
- package/requirements.txt +0 -16
- package/static/v3/js/views/knowledge-graph.a14ea7e7.js +0 -237
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
# Lattice AI v4.0.0 — Brain Architecture Proposal
|
|
2
|
+
|
|
3
|
+
Status: Phase B proposal (post 8-dimension audit, pre-implementation review)
|
|
4
|
+
Audit evidence: `docs/v4-audit/*.json` · Program state: `docs/V4_DIGITAL_BRAIN_RECOVERY.md`
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. The one-sentence architecture
|
|
9
|
+
|
|
10
|
+
**There is exactly one brain: a workspace-scoped, provenance-stamped knowledge
|
|
11
|
+
substrate in SQLite, with a single write door (the Ingestion Pipeline), a single
|
|
12
|
+
read discipline (scoped, scored, honest retrieval), and replaceable everything
|
|
13
|
+
else (models, agents, UI).**
|
|
14
|
+
|
|
15
|
+
v3.6.0 already *claims* this ("every source converges into the graph — no
|
|
16
|
+
silos"). The audit proves the claim false today in four ways:
|
|
17
|
+
|
|
18
|
+
1. A second brain exists (`~/.ltcai-brain` markdown vault, `p_reinforce.py`)
|
|
19
|
+
with its own retrieval path injected into every chat.
|
|
20
|
+
2. The Ingestion Pipeline covers 1 of 4 write paths (browser only); chat,
|
|
21
|
+
uploads, and MCP write to the graph directly, without provenance.
|
|
22
|
+
3. Conversations — the richest episodic source — are capped at 50 messages in a
|
|
23
|
+
JSON file and then destroyed.
|
|
24
|
+
4. The graph is machine-global: workspace isolation excludes the actual brain
|
|
25
|
+
(`SHARED_GLOBAL_AREAS = ('graph', 'skills')`).
|
|
26
|
+
|
|
27
|
+
v4 makes the claim true. That is the release.
|
|
28
|
+
|
|
29
|
+
## 2. Identity
|
|
30
|
+
|
|
31
|
+
- **Product**: *Lattice — the local-first Digital Brain Platform.* The phrase
|
|
32
|
+
"AI workspace" is retired from every shipped artifact (PROJECT_PRINCIPLES,
|
|
33
|
+
pyproject, package.json, vscode-extension, EDITION_STRATEGY, SPA copy).
|
|
34
|
+
- **Honesty is the brand.** FEATURE_STATUS.md's WORKING/PARTIAL/PLACEHOLDER
|
|
35
|
+
ledger is institutionalized: README claims must trace to ledger entries; runs
|
|
36
|
+
that simulate must say so *in the persisted record*, not just in docs.
|
|
37
|
+
- **Naming**: brand "Lattice AI"; packages stay `ltcai` (renaming published
|
|
38
|
+
pip/npm packages is churn without user value). CLI: `ltcai` is canonical,
|
|
39
|
+
`LTCAI` retained as deprecated alias. Env: `LATTICEAI_*` canonical;
|
|
40
|
+
existing `LATTICE_*` vars read as fallback aliases. Data home stays `~/.ltcai`
|
|
41
|
+
(a data migration of every user's brain for a nicer folder name violates
|
|
42
|
+
"knowledge is durable"). `~/.ltcai-brain` is absorbed and retired (§4.2).
|
|
43
|
+
- Concept renames in UI/docs: "Workspace OS" → internal term only; the user
|
|
44
|
+
sees **Brain** (graph+memory), **Capture** (ingestion), **Ask** (chat),
|
|
45
|
+
**Act** (agents/workflows/tools), **Library** (models/skills/plugins),
|
|
46
|
+
**System** (settings/admin).
|
|
47
|
+
|
|
48
|
+
## 3. The Brain Core model
|
|
49
|
+
|
|
50
|
+
All durable state converges on the existing SQLite graph store, extended — not
|
|
51
|
+
replaced (additive migration, the v3 store keeps working).
|
|
52
|
+
|
|
53
|
+
### 3.1 Knowledge System — v2 becomes the authoritative store
|
|
54
|
+
The half-finished strangler-fig migration is **finished in v4**, not deferred:
|
|
55
|
+
|
|
56
|
+
- **Write-mastering flips to the normalized v2 schema.** All write paths write
|
|
57
|
+
canonical `kg_schema.NodeType`/`EdgeType` enums natively (no new Korean
|
|
58
|
+
free-string types are ever minted again) and populate the columns that
|
|
59
|
+
justify v2's existence: `owner_id`, `workspace_id` (new), `visibility`,
|
|
60
|
+
`created_by`, `evidence`, confidence.
|
|
61
|
+
- **Migration strategy** (additive, reversible, backup-first):
|
|
62
|
+
1. automatic pre-migration binary backup via the existing
|
|
63
|
+
`kg_portability` backup machinery;
|
|
64
|
+
2. one-time migrator normalizes legacy rows through the existing
|
|
65
|
+
`from_legacy()` mapping (the same logic the projection uses today),
|
|
66
|
+
preserving original strings in `legacy_type` — nothing is lost;
|
|
67
|
+
3. legacy `nodes`/`edges` tables become a *read-compatibility projection*
|
|
68
|
+
(the exact inverse of today), regenerated on write for one deprecation
|
|
69
|
+
release, then dropped;
|
|
70
|
+
4. the existing `test_kg_v2_read_equivalence.py` suite is extended to prove
|
|
71
|
+
byte-equivalent reads before and after the flip.
|
|
72
|
+
- **Retrieval upgrade**: an FTS5 index over titles/summaries/chunk text
|
|
73
|
+
replaces `LIKE '%q%'` scans; `sqlite-vec` is integrated as an optional
|
|
74
|
+
extra (`ltcai[ann]`) with the brute-force cosine path remaining as the
|
|
75
|
+
honest, capability-reported fallback. The default embedder stays honestly
|
|
76
|
+
labeled `grade='fallback'`; a *real* local embedding model is provisioned
|
|
77
|
+
through the setup wizard **with explicit user consent** (a silent
|
|
78
|
+
multi-hundred-MB download at install would violate privacy-first — this is
|
|
79
|
+
the only "default" we refuse on principle, not effort).
|
|
80
|
+
- **Temporal dimension**: edges gain `observed_at` occurrence records so
|
|
81
|
+
repeated observations no longer collapse silently (`weight=max` losing
|
|
82
|
+
history); nodes gain `superseded_by` for revision chains.
|
|
83
|
+
|
|
84
|
+
### 3.2 Memory System (new, on the same substrate)
|
|
85
|
+
Four first-class record kinds, stored as typed nodes with provenance:
|
|
86
|
+
- **Episodic** — immutable, timestamped: conversation turns, tool runs,
|
|
87
|
+
ingestion events. Source: the new durable conversation store + agent runs.
|
|
88
|
+
- **Semantic** — consolidated facts/preferences/working-style. Today's
|
|
89
|
+
`MEMORY_KINDS` workspace memories become readable at inference (they are
|
|
90
|
+
written today but never read by the model — audit: memory-context critical).
|
|
91
|
+
- **Experience** — completed agent/workflow runs promoted into the graph
|
|
92
|
+
(plan, outcome, retries) — only *real* runs; simulations are labeled and
|
|
93
|
+
never enter the brain as experience.
|
|
94
|
+
- **Decision** — explicit decision records (already a node type in the schema,
|
|
95
|
+
never populated; v4 populates it from agent plan approvals and user-saved
|
|
96
|
+
decisions).
|
|
97
|
+
|
|
98
|
+
### 3.3 Conversation store (new; kills the 50-message cap)
|
|
99
|
+
`conversations`/`messages` tables in the brain DB family: unbounded, per-user,
|
|
100
|
+
per-conversation, redaction applied on write, source of the chat UI and of
|
|
101
|
+
episodic memory. `chat_history.json` becomes a render cache at most.
|
|
102
|
+
|
|
103
|
+
### 3.4 Context System (new: the ContextAssembler)
|
|
104
|
+
One pipeline replaces the ad-hoc string concatenation in `api/chat.py:365-418`:
|
|
105
|
+
ordered, token-budgeted sections (system → semantic memories → hybrid-search
|
|
106
|
+
knowledge → episodic recency → attachments), each with provenance (`why is
|
|
107
|
+
this in my context?` is answerable). It uses the *existing, tested*
|
|
108
|
+
`SearchService.hybrid_search` — fixing the absurdity that the product's search
|
|
109
|
+
engine is never used by its own chat. The recall scoring bug
|
|
110
|
+
(`results` vs `matches`) and the fabricated constant scores die here.
|
|
111
|
+
|
|
112
|
+
### 3.5 Relationship System (exists)
|
|
113
|
+
The graph's edges, plus evidence/confidence threading from the extractors
|
|
114
|
+
(already produced, currently discarded in projection).
|
|
115
|
+
|
|
116
|
+
## 4. One door in: the Ingestion Pipeline
|
|
117
|
+
|
|
118
|
+
### 4.1 Coverage goes 1 of 5 → 5 of 5
|
|
119
|
+
`services/ingestion.py` becomes the only KG write door: alongside the
|
|
120
|
+
already-covered browser/web path, chat messages, document uploads, MCP
|
|
121
|
+
messages, and workspace events are converted to `IngestionItem`s (new source
|
|
122
|
+
types), giving every node provenance and the full pre/post hook lifecycle.
|
|
123
|
+
The direct `ingest_message`/`ingest_document` call sites are rewired.
|
|
124
|
+
|
|
125
|
+
### 4.2 The garden is absorbed — as a living source, not a snapshot
|
|
126
|
+
`p_reinforce` vault content enters the brain through the pipeline
|
|
127
|
+
(source_type=note): an initial idempotent import (content-hash dedup), after
|
|
128
|
+
which the vault directory is registered as a **watched knowledge source**
|
|
129
|
+
using the existing discovery/watch machinery — Obsidian-style edits keep
|
|
130
|
+
flowing into the brain continuously. Notes created through the API are
|
|
131
|
+
written to the brain (authoritative) *and* mirrored as markdown into the
|
|
132
|
+
vault, which remains the user-readable, user-owned artifact. The `/garden`
|
|
133
|
+
API and chat-context injection are re-implemented as views/queries over the
|
|
134
|
+
brain; the O(n) vault rglob at chat time dies. Imported vault notes carry
|
|
135
|
+
legacy-global scope (NULL workspace), matching their pre-v4 visibility.
|
|
136
|
+
**No capability is removed** — notes, classification, Obsidian
|
|
137
|
+
interoperability, and "relevant context in chat" all survive with strictly
|
|
138
|
+
better retrieval.
|
|
139
|
+
|
|
140
|
+
## 5. Personal Brain / Organization Brain
|
|
141
|
+
|
|
142
|
+
The workspace layer stops being a veneer:
|
|
143
|
+
- Graph writes carry `workspace_id` + `owner_id` (from the already-resolved
|
|
144
|
+
`WorkspaceService` scope); reads (`search`, `graph`, `traverse`,
|
|
145
|
+
`vector_search`, context assembly) filter by resolved scope. Personal brains
|
|
146
|
+
are private by construction; organization workspaces share an org brain.
|
|
147
|
+
Pre-v4 rows have no workspace (NULL = legacy-global, readable by all members
|
|
148
|
+
of the machine as today — honest, documented compatibility).
|
|
149
|
+
- The by-id authorization bypasses (snapshots get/area/export/compare, memory
|
|
150
|
+
delete, `/workspace/os` registry leak) are closed.
|
|
151
|
+
- Chat context no longer leaks other users' messages (the
|
|
152
|
+
`role=="assistant"` filter bug).
|
|
153
|
+
- **Identity is unified**: every user gets a stable UUID (assigned by
|
|
154
|
+
non-destructive migration on first load, email becomes a mutable
|
|
155
|
+
attribute); memberships, memories, sessions, and audit entries key on it.
|
|
156
|
+
The three role vocabularies collapse into one policy module
|
|
157
|
+
(`latticeai/core/policy.py`) that defines role→capability mappings and is
|
|
158
|
+
*actually enforced* at the router layer — retiring the false
|
|
159
|
+
"`_ROLE_CAPS` is the real access policy" claim by making it true.
|
|
160
|
+
Organization membership gains a real invitation flow (invite record with
|
|
161
|
+
token + expiry, accept endpoint) instead of freeform member-id strings.
|
|
162
|
+
- **Workspace state becomes transactional**: the single unlocked
|
|
163
|
+
`workspace_os.json` (lost updates, silent `[-200:]`/`[-500:]` truncation)
|
|
164
|
+
is replaced by SQLite-backed workspace state in the brain DB family, with
|
|
165
|
+
a one-time importer for existing JSON state. Truncation caps are removed —
|
|
166
|
+
"knowledge is durable" applies to memories and timelines too.
|
|
167
|
+
|
|
168
|
+
## 6. Act: real runtimes — executing, durable, cancellable
|
|
169
|
+
|
|
170
|
+
- **Agent runtime**: orchestrator roles get an LLM-backed runner built on the
|
|
171
|
+
*real* single-agent runtime (`core/agent.py`) + `llm_router` prompts
|
|
172
|
+
(PLANNER/CRITIC already exist in `agent_prompts.py`). When no model is
|
|
173
|
+
loaded, runs still work deterministically **but the run record persists
|
|
174
|
+
`mode: "simulation"`** and simulated runs never write Experience records
|
|
175
|
+
into the brain. The fabricated-provenance pathway dies. `AgentRegistry`
|
|
176
|
+
entries become executable: a registered agent carries model id, system
|
|
177
|
+
prompt, and a tool allowlist that the runtime actually loads — custom
|
|
178
|
+
agents stop being a UI illusion.
|
|
179
|
+
- **Workflow runtime**: tool/skill nodes execute for real through
|
|
180
|
+
`dispatch_tool` under the existing governance registry. Non-auto-approve
|
|
181
|
+
tools produce an explicit `awaiting_approval` pause — never a silent
|
|
182
|
+
`{recorded: true}` success.
|
|
183
|
+
- **Durable async execution** (in scope, not a gap): runs are persisted
|
|
184
|
+
records (`queued → running → awaiting_approval → succeeded | failed |
|
|
185
|
+
cancelled | interrupted`) executed as asyncio tasks on the server loop
|
|
186
|
+
(synchronous tool/orchestrator work bridged via `asyncio.to_thread`;
|
|
187
|
+
cross-thread bus publishes via `loop.call_soon_threadsafe` — the
|
|
188
|
+
`RealtimeBus` is made thread-safe as part of this work). `stop()` performs
|
|
189
|
+
real cooperative cancellation, checked between steps/tool calls — it
|
|
190
|
+
cannot interrupt an in-flight MLX `generate()`, and agent generation
|
|
191
|
+
serializes with interactive chat on the single inference thread; both
|
|
192
|
+
limits are documented, surfaced honestly, never papered over. Progress
|
|
193
|
+
streams over the existing `/realtime/stream` SSE endpoint (the
|
|
194
|
+
`/agents/.../events` JSON snapshot remains as-is). On startup, any run
|
|
195
|
+
left non-terminal by a crash/restart is reconciled to `interrupted` with
|
|
196
|
+
reason + timestamp — no phantom "running" state survives a restart.
|
|
197
|
+
- **Per-tool approval gate**: when a run hits a non-auto-approve tool it
|
|
198
|
+
pauses into `awaiting_approval`, surfaces the pending decision through the
|
|
199
|
+
API/UI, and resumes (or aborts) on the recorded human decision —
|
|
200
|
+
generalizing the proven `human_in_loop` plan-approval mechanism in
|
|
201
|
+
`api/chat.py`. `approve()` stops auto-approving unconditionally.
|
|
202
|
+
- **Trigger system**: beyond `manual` — (a) interval/cron scheduling via a
|
|
203
|
+
supervised scheduler loop; (b) **brain-event triggers**: workflows subscribe
|
|
204
|
+
to ingestion lifecycle events through the existing hooks bus ("when a new
|
|
205
|
+
document enters the brain, run this workflow"). Trigger firings create
|
|
206
|
+
normal durable runs with provenance pointing at the triggering event.
|
|
207
|
+
|
|
208
|
+
## 7. Sovereignty: portability + Brain Network
|
|
209
|
+
|
|
210
|
+
- **Device identity**: per-installation Ed25519 keypair (`cryptography`, file
|
|
211
|
+
+ keyring storage). Every export and every peer interaction is attributable
|
|
212
|
+
to a device the user controls.
|
|
213
|
+
- **Signed brain bundles**: exports (already sha256-manifested) gain a
|
|
214
|
+
detached signature + device public key; imports verify and record origin
|
|
215
|
+
provenance. Per-workspace export ("take your brain with you") joins the
|
|
216
|
+
existing admin-global export. A bundle is a file — sneakernet is a fully
|
|
217
|
+
supported transport.
|
|
218
|
+
- **Brain Network v1 (Knowledge Exchange)** — implemented, not just
|
|
219
|
+
documented: explicit peer registry (name, base URL, trusted Ed25519 public
|
|
220
|
+
key) with a deliberate pairing step; push/pull of signed workspace bundles
|
|
221
|
+
between Lattice instances over plain HTTP (designed for LAN/tailnet —
|
|
222
|
+
local-first, no cloud rendezvous, no relay service); the receiving brain
|
|
223
|
+
verifies the signature against the *paired* key, imports through the normal
|
|
224
|
+
ingestion/import path, and records origin-device provenance on every
|
|
225
|
+
imported node. Peer requests authenticate independently of user sessions:
|
|
226
|
+
each request carries an Ed25519 signature over (body digest + timestamp),
|
|
227
|
+
verified against the paired key, with a freshness window + seen-nonce check
|
|
228
|
+
for replay protection. Nothing is shared implicitly: exchange is
|
|
229
|
+
per-workspace, per-request, owner-initiated. Identity-aware sync/merge
|
|
230
|
+
conflict resolution beyond idempotent content-hash dedup is v1's documented
|
|
231
|
+
boundary.
|
|
232
|
+
- **Compatibility policy for unsigned artifacts**: pre-v4 export bundles and
|
|
233
|
+
backups have no signatures — local file imports/restores of them are
|
|
234
|
+
accepted and recorded with provenance `origin='unsigned-legacy'`.
|
|
235
|
+
Signatures are mandatory only on the Brain Network peer path. A v3.6
|
|
236
|
+
export must always import into a v4 brain.
|
|
237
|
+
- **Agent collaboration across brains** inherits this substrate: an agent's
|
|
238
|
+
Experience records travel inside bundles like any other knowledge, with
|
|
239
|
+
provenance intact.
|
|
240
|
+
|
|
241
|
+
## 8. Surfaces
|
|
242
|
+
|
|
243
|
+
- **One frontend.** The v3 `/app` SPA is the product; legacy pages
|
|
244
|
+
(`/chat`, `/graph`, `/workspace`, `/admin`, …) 308-redirect into `/app`
|
|
245
|
+
routes. Login flows into `/app`. Legacy HTML/JS/CSS is deleted from the
|
|
246
|
+
shipping set (kept in git history).
|
|
247
|
+
- **Brain-first IA**: nav regrouped (Brain · Ask · Capture · Act · Library ·
|
|
248
|
+
System); the Knowledge Graph view is the post-login landing surface.
|
|
249
|
+
- **A real graph**: the force-directed canvas (drag/zoom/physics — already
|
|
250
|
+
written in legacy `graph.js`) is ported into the v3 explorer, replacing the
|
|
251
|
+
static SVG spiral.
|
|
252
|
+
- **Privacy honesty**: fonts/icons vendored locally; no CDN calls from a
|
|
253
|
+
product that promises "nothing leaves your machine". Service worker
|
|
254
|
+
precaches the v3 bundle, not the deleted legacy one. The hardcoded
|
|
255
|
+
fusion-score meters in hybrid-search view are removed (real scores or no
|
|
256
|
+
meters).
|
|
257
|
+
- **Login joins the design system**: the auth surface is rebuilt token-native,
|
|
258
|
+
dropping its ~8,300 lines of legacy reference CSS.
|
|
259
|
+
- **i18n (en/ko)**: SPA strings externalized into a dictionary module with
|
|
260
|
+
browser-locale default — formalizing the bilingual reality the legacy chat
|
|
261
|
+
already proved demand for, instead of the current ko/en patchwork.
|
|
262
|
+
|
|
263
|
+
## 9. Backend shape: the brain gets a package
|
|
264
|
+
|
|
265
|
+
The dependency inversion (clean `latticeai/` importing dirty root modules)
|
|
266
|
+
ends:
|
|
267
|
+
|
|
268
|
+
- **`latticeai/brain/`** — the 4,633-line `knowledge_graph.py` single class is
|
|
269
|
+
decomposed along its existing seams: `store.py` (authoritative v2 SQLite
|
|
270
|
+
store), `extraction.py` (concept/triple extraction, LLM + rules),
|
|
271
|
+
`documents.py` (pdf/pptx/docx/xlsx structure), `discovery.py` (local roots,
|
|
272
|
+
audit, watch), `conversations.py` (durable conversation store, new),
|
|
273
|
+
`memory.py` (memory-type model, new), `context.py` (ContextAssembler, new),
|
|
274
|
+
`identity.py` (device keypair, new), `network.py` (peer exchange, new).
|
|
275
|
+
A root `knowledge_graph.py` shim re-exports the public surface during the
|
|
276
|
+
deprecation window so nothing external breaks.
|
|
277
|
+
- **Root modules are absorbed or deleted**: `setup.py` → `setup_wizard.py`
|
|
278
|
+
(fixes both the broken wheel and the setuptools collision); `llm_router.py`,
|
|
279
|
+
`mcp_registry.py`, `kg_schema.py` move under `latticeai/`;
|
|
280
|
+
`telegram_bot` decouples from `api/chat.py` by subscribing to the
|
|
281
|
+
`RealtimeBus` instead of being imported unconditionally; dead modules
|
|
282
|
+
(`codex_telegram_bot.py`, `perm_monitor.py`) are deleted (git history
|
|
283
|
+
preserves them). `knowledge_graph_api.py` is **live, not dead** (it serves
|
|
284
|
+
the `/knowledge-graph/*` data endpoints the v3 SPA uses): its data router
|
|
285
|
+
migrates into `latticeai/api/` with endpoint-parity tests; its legacy page
|
|
286
|
+
routes join the frontend redirect work.
|
|
287
|
+
- **`create_app(config)` factory**: `server_app.py`'s import-time singleton
|
|
288
|
+
construction and GPU side effects move into an explicit factory that builds
|
|
289
|
+
the dormant `AppContext` dataclass and hands it to router factories —
|
|
290
|
+
replacing 25-30-kwarg closure wiring with one typed context.
|
|
291
|
+
|
|
292
|
+
## 10. Platform / release engineering
|
|
293
|
+
|
|
294
|
+
- **Fix the broken wheel** (`setup.py` rename above) + an installed-wheel
|
|
295
|
+
smoke test in CI: build, install into a clean venv, import, hit `/health` —
|
|
296
|
+
from a non-repo cwd, so the class of "works in `pip install -e .` only"
|
|
297
|
+
failures dies.
|
|
298
|
+
- ruff (lint) baseline + CI gate; bounded dependency constraints + lockfile;
|
|
299
|
+
single `scripts/bump_version.py` writing all version copies (kept honest by
|
|
300
|
+
the existing consistency test).
|
|
301
|
+
- npm tarball slimmed (no docs images / bots).
|
|
302
|
+
- `.gitignore` covers tarballs/logs/venvs; the 15MB tracked pptx is deleted
|
|
303
|
+
at HEAD (stops the bleeding for new objects).
|
|
304
|
+
|
|
305
|
+
## 11. The only two exclusions, and why they are real blockers
|
|
306
|
+
|
|
307
|
+
Everything previously marked "foundation only" or "documented gap" is now in
|
|
308
|
+
scope (§3.1 v2 flip, §6 async/triggers/approvals, §5 identity+invitations+
|
|
309
|
+
transactional state, §7 Brain Network transport, §9 decomposition). Two items
|
|
310
|
+
remain excluded because they have *true* blockers, not effort blockers:
|
|
311
|
+
|
|
312
|
+
1. **Git history rewrite** (purging the pptx from past commits): requires
|
|
313
|
+
force-pushing rewritten history to the shared remote — an irreversible,
|
|
314
|
+
collaboration-breaking action that is reserved for the repository owner's
|
|
315
|
+
explicit decision at RC review. v4 deletes the file at HEAD.
|
|
316
|
+
2. **Downloading a production embedding model silently at install**: violates
|
|
317
|
+
privacy-first consent. The capability ships, but provisioning happens
|
|
318
|
+
through the setup wizard with explicit user opt-in; until then the
|
|
319
|
+
fallback embedder remains and reports itself honestly as
|
|
320
|
+
`grade='fallback'`.
|
|
321
|
+
|
|
322
|
+
Neither exclusion hides behind fake UI: both are visible, labeled states.
|