ltcai 7.8.0 → 8.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Lattice AI
2
2
 
3
- **Lattice AI 7.8 is the glanceable local-first Digital Brain product. It keeps your knowledge durable across any AI model, with Brain Chat Home rebuilt around immediate use instead of dashboard clutter.**
3
+ **Lattice AI 8.0 is the local-first Digital Brain platform with hardened runtime architecture. It keeps your knowledge durable across any AI model, with AgentRuntime, ToolRegistry, central Config, and Knowledge Graph stability tracked by explicit release contracts.**
4
4
 
5
5
  **Lattice AI는 모델이 바뀌어도 내 지식과 맥락을 보존하는 로컬 우선 AI 브레인입니다.**
6
6
 
@@ -11,7 +11,7 @@ downloads, update checks, and other external communication happen only after
11
11
  explicit consent.
12
12
 
13
13
  It is not a ChatGPT clone, a model launcher, a graph database, or a note app.
14
- It is the finished private AI memory layer wrapped in a Living Brain experience — now with a cleaner 7.8 Brain Chat Home.
14
+ It is the finished private AI memory layer wrapped in a Living Brain experience — now with the 8.0 runtime architecture contract behind it.
15
15
 
16
16
  [![PyPI Version](https://img.shields.io/pypi/v/ltcai?label=PyPI)](https://pypi.org/project/ltcai/)
17
17
  [![npm Version](https://img.shields.io/npm/v/ltcai?label=npm)](https://www.npmjs.com/package/ltcai)
@@ -64,7 +64,7 @@ You need Lattice AI when:
64
64
 
65
65
  ## Living Brain Flow
66
66
 
67
- The screenshots below are release evidence captures. The 7.8 line keeps the
67
+ The screenshots below are release evidence captures. The 8.0 line keeps the
68
68
  same first-run flow and rebuilds the Brain Chat Home layout so chat and the
69
69
  composer are the first visible action.
70
70
 
@@ -78,28 +78,28 @@ confirm owner, check the computer, choose the Brain voice.
78
78
  Choose the owner of the Brain. The profile is not a SaaS account by default; it
79
79
  is the local identity for the knowledge you keep.
80
80
 
81
- ![Login](output/release/v7.7.0/screenshots/01-login.png)
81
+ ![Login](output/release/v7.8.0/screenshots/01-login.png)
82
82
 
83
83
  ### 3. Environment Analysis
84
84
 
85
85
  See what kind of local AI experience this computer can support before choosing a
86
86
  model.
87
87
 
88
- ![Environment Analysis](output/release/v7.7.0/screenshots/02-environment-analysis.png)
88
+ ![Environment Analysis](output/release/v7.8.0/screenshots/02-environment-analysis.png)
89
89
 
90
90
  ### 4. Recommended Models
91
91
 
92
92
  Start with a short list: safest recommendation, faster model, stronger model.
93
93
  Advanced details stay available without overwhelming first-time users.
94
94
 
95
- ![Recommended Models](output/release/v7.7.0/screenshots/03-recommended-models.png)
95
+ ![Recommended Models](output/release/v7.8.0/screenshots/03-recommended-models.png)
96
96
 
97
97
  ### 5. Install And Load
98
98
 
99
99
  Download and load only after consent. Lattice explains model size, local
100
100
  execution, and network use before work starts.
101
101
 
102
- ![Install and Load](output/release/v7.7.0/screenshots/04-install-load-progress.png)
102
+ ![Install and Load](output/release/v7.8.0/screenshots/04-install-load-progress.png)
103
103
 
104
104
  ### 6. Brain Chat
105
105
 
@@ -107,14 +107,14 @@ Talk normally. Useful decisions and context become memory, then appear later as
107
107
  topics, relationships, graph structure, and the concentric memory rings around
108
108
  the Brain.
109
109
 
110
- ![Brain Chat Home](output/release/v7.7.0/screenshots/05-brain-chat-home.png)
110
+ ![Brain Chat Home](output/release/v7.8.0/screenshots/05-brain-chat-home.png)
111
111
 
112
112
  ### 7. Review Center
113
113
 
114
114
  Automation results are staged for review before they become durable decisions.
115
115
  Snooze, unsnooze, run now, approve, and dismiss actions stay explicit.
116
116
 
117
- ![Review Center](output/release/v7.7.0/screenshots/13-review-center.png)
117
+ ![Review Center](output/release/v7.8.0/screenshots/13-review-center.png)
118
118
 
119
119
  ## Brain Depths
120
120
 
@@ -130,10 +130,10 @@ The user travels inward from everyday memory to deeper structure:
130
130
 
131
131
  Walkthrough:
132
132
 
133
- ![v7.7.0 Living Brain walkthrough](output/release/v7.7.0/gifs/v7.7.0-living-brain-walkthrough.gif)
133
+ ![v7.8.0 Living Brain walkthrough](output/release/v7.8.0/gifs/v7.8.0-living-brain-walkthrough.gif)
134
134
 
135
135
  Screenshot index and capture notes:
136
- [output/release/v7.7.0/SCREENSHOT_INDEX.md](output/release/v7.7.0/SCREENSHOT_INDEX.md)
136
+ [output/release/v7.8.0/SCREENSHOT_INDEX.md](output/release/v7.8.0/SCREENSHOT_INDEX.md)
137
137
 
138
138
  ## Install
139
139
 
@@ -210,33 +210,39 @@ See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for developer workflow details.
210
210
 
211
211
  ## Current Release
212
212
 
213
- The current release is **7.8.0 — Brain Chat Home UX Simplification**:
214
-
215
- - Brain Chat Home now opens with chat, starter prompts, and the composer as the
216
- first action. Source ingestion, readiness, proof, timeline, and care controls
217
- move behind a single utility drawer instead of occupying the first viewport.
218
- - The default Brain surface now keeps workspace navigation visible, removes
219
- permanent marketing intro copy, and only reveals deep memory controls after
220
- the user chooses to travel deeper.
221
- - Obsolete Brain conversation and first-run guide components were removed so the
222
- canonical Brain/onboarding implementation is the only path.
213
+ The current release is **8.0.0Runtime Architecture Contract**:
214
+
215
+ - `architecture_readiness()` now emits `lattice-architecture-contract/v1`,
216
+ including the preferred refactoring order and concrete ownership for
217
+ AgentRuntime, ToolRegistry, central Config, server decomposition, and KG
218
+ hardening.
219
+ - The product AgentRuntime facade in `lattice_brain.runtime.agent_runtime`
220
+ remains the unambiguous `/agents` execution and observability boundary.
221
+ - ToolRegistry manifest output now carries `tool-registry-contract/v1` with
222
+ dispatch, policy, and permission ownership, so runtime/admin surfaces can
223
+ detect catalog drift from one source of truth.
224
+ - Knowledge Graph hardening is represented as an additive reprojection strategy
225
+ with legacy read compatibility and non-destructive rollback/export paths.
226
+ - KG v2 read-equivalence is locked for document listing, node lookup,
227
+ relationship search, and traversal, while logical imports preserve colliding
228
+ legacy edge labels without breaking native canonical dedupe.
223
229
  - Product readiness is machine-checkable through `product_readiness()`, which
224
230
  composes the architecture contract with exact artifact/docs/workflow evidence.
225
- - CI and release workflows now run frontend lint/typecheck/build gates plus the
226
- 7.8 product readiness score before a tag can be treated as release-safe.
231
+ - CI and release workflows continue to run frontend lint/typecheck/build gates
232
+ plus the 8.0 product readiness score before a tag can be treated as release-safe.
227
233
 
228
- Expected artifacts for 7.8.0 release must use exact filenames:
234
+ Expected artifacts for 8.0.0 release must use exact filenames:
229
235
 
230
- - `dist/ltcai-7.8.0-py3-none-any.whl`
231
- - `dist/ltcai-7.8.0.tar.gz`
232
- - `ltcai-7.8.0.tgz`
233
- - `dist/ltcai-7.8.0.vsix`
234
- - `src-tauri/target/release/bundle/dmg/Lattice AI_7.8.0_aarch64.dmg`
236
+ - `dist/ltcai-8.0.0-py3-none-any.whl`
237
+ - `dist/ltcai-8.0.0.tar.gz`
238
+ - `ltcai-8.0.0.tgz`
239
+ - `dist/ltcai-8.0.0.vsix`
240
+ - `src-tauri/target/release/bundle/dmg/Lattice AI_8.0.0_aarch64.dmg`
235
241
 
236
- Do not upload `dist/*`. Package registry publishing remains owner-run.
242
+ Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
237
243
 
238
244
  See [docs/ROADMAP_RECOMMENDATIONS.md](docs/ROADMAP_RECOMMENDATIONS.md) for the
239
- strategic roadmap slices applied through 7.8.0 and the follow-up tracks.
245
+ strategic roadmap slices applied through 8.0.0 and the follow-up tracks.
240
246
 
241
247
  ## Known Limitations
242
248
 
@@ -253,6 +259,8 @@ strategic roadmap slices applied through 7.8.0 and the follow-up tracks.
253
259
 
254
260
  | Version | Theme |
255
261
  | --- | --- |
262
+ | 8.0.0 | Runtime Architecture Contract: AgentRuntime, ToolRegistry, central Config, server decomposition, and KG hardening are captured as machine-checkable release boundaries with exact 8.0.0 artifacts |
263
+ | 7.9.0 | Agent Runtime Boundary Hardening: explicit `SingleAgentRuntime`, compatibility alias preservation, injected rollback port, and release/readiness docs aligned to the product AgentRuntime facade |
256
264
  | 7.8.0 | Brain Chat Home UX Simplification: chat-first first viewport, visible workspace navigation, collapsed source/status utilities, hidden default depth controls, and removal of obsolete Brain UX components |
257
265
  | 7.7.0 | Complete Product Polish: command-center Brain Home, repaired Review Center evidence, exact 7.7 docs/artifacts, product readiness gate, and stronger CI/release checks |
258
266
  | 7.6.0 | Brain-Centered UX & Architecture Closure: Wake Brain first-run surface, concentric memory rings with direct depth controls, and machine-checkable closure of the two architecture/UX review files |
package/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,42 @@ existed at that release.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [8.0.0] - 2026-06-24
10
+
11
+ ### Changed
12
+ - Added `lattice-architecture-contract/v1` to make the AgentRuntime,
13
+ ToolRegistry, Config, server decomposition, and Knowledge Graph stabilization
14
+ boundaries explicit and testable for the major architecture line.
15
+ - Added `tool-registry-contract/v1` to the ToolRegistry manifest, including
16
+ dispatch, policy, and permission ownership.
17
+ - Updated architecture and product readiness targets to 8.0.0.
18
+ - Synchronized package/runtime/static/Tauri metadata to 8.0.0.
19
+ - Updated current-release docs and exact artifact names to 8.0.0 while
20
+ preserving historical 7.x entries.
21
+
22
+ ### Fixed
23
+ - Made logical Knowledge Graph `replace` imports transactional so malformed
24
+ imports roll back without clearing the existing graph.
25
+ - Locked v2 read-equivalence coverage for `list_documents`, `get_node`,
26
+ `relationship_search`, and `traverse`.
27
+ - Preserved colliding legacy edge labels during logical import/backfill while
28
+ keeping native write-door synonym dedupe canonical.
29
+
30
+ ## [7.9.0] - 2026-06-23
31
+
32
+ ### Changed
33
+ - Added `SingleAgentRuntime` as the explicit name for the legacy single-agent
34
+ state machine while preserving `AgentRuntime` as a compatibility alias.
35
+ - Updated tool dispatch to build `SingleAgentRuntime` directly.
36
+ - Moved single-agent git rollback behind an injected `rollback_file` port owned
37
+ by `ToolDispatchService`, keeping shell execution out of the core state
38
+ machine.
39
+ - Added a shared `runtime-boundary/v1` descriptor so product and single-agent
40
+ runtime boundaries are machine-readable in config/tests.
41
+ - Added `RuntimeBoundaryProtocol` as the minimal shared inspection surface for
42
+ runtime-boundary-aware dependency injection.
43
+ - Updated architecture and product readiness targets to 7.9.0.
44
+
9
45
  ## [7.8.0] - 2026-06-22
10
46
 
11
47
  ### Changed
@@ -23,6 +59,8 @@ existed at that release.
23
59
  - Moved draft onboarding polish out of inline styles and into the shared design
24
60
  stylesheet with responsive behavior and bilingual copy.
25
61
  - Updated architecture and product readiness targets to 7.8.0.
62
+ - Refreshed 7.8.0 release screenshots, walkthrough video/GIF, and capture
63
+ notes under `output/release/v7.8.0/`.
26
64
 
27
65
  ## [7.7.0] - 2026-06-22
28
66
 
@@ -95,5 +95,4 @@ For user-facing, API, runtime, release, or packaging changes, check:
95
95
  - `docs/LEGACY_COMPATIBILITY.md` when root compatibility files change
96
96
 
97
97
  Release/publish examples must use exact target-version filenames. Do not
98
- document wildcard upload commands such as `dist/*`.
99
-
98
+ document wildcard artifact upload commands.
@@ -2,7 +2,7 @@
2
2
 
3
3
  The Multi-Agent Runtime is the **orchestration layer** introduced in v2.0.0 and
4
4
  operationalized in v2.2.0. It sits
5
- *above* the v1.x single-agent state machine ([`AgentRuntime`](../latticeai/core/agent.py))
5
+ *above* the v1.x single-agent state machine ([`SingleAgentRuntime`](../latticeai/core/agent.py))
6
6
  and coordinates a pipeline of named **roles** that hand off work to one another,
7
7
  retry on a failing review, and emit a fully observable, replayable timeline.
8
8
 
@@ -34,20 +34,21 @@ objects durable and inspectable:
34
34
 
35
35
  ## How it relates to the v1 single-agent runtime
36
36
 
37
- v1.x shipped a single-agent state machine — `AgentRuntime` driving
37
+ v1.x shipped a single-agent state machine — `SingleAgentRuntime` driving
38
38
  `PLAN → EXECUTE → VERIFY → DONE` (with `ROLLBACK` / `FAILED` recovery paths) over an
39
- injected `AgentDeps` port. That runtime is unchanged.
39
+ injected `AgentDeps` port. The historical `AgentRuntime` import remains as a
40
+ compatibility alias.
40
41
 
41
42
  v2.0 adds the *orchestration* layer on top: instead of one agent looping through
42
43
  internal phases, the `MultiAgentOrchestrator` drives a **pipeline of distinct roles**
43
44
  (researcher, planner, executor, reviewer, release) that hand off to one another and
44
45
  can rewind on a failing review. The two layers are complementary — the v2
45
46
  orchestrator coordinates roles; an individual role's runner could itself be backed by
46
- the v1 `AgentRuntime` loop or an LLM, but that is an implementation choice behind the
47
+ the v1 `SingleAgentRuntime` loop or an LLM, but that is an implementation choice behind the
47
48
  injected runner port.
48
49
 
49
50
  > **Compatibility.** The Multi-Agent Runtime is purely additive. The v1
50
- > `AgentRuntime` state machine and its `/agent` endpoints are untouched, and the v2
51
+ > `SingleAgentRuntime` state machine and its `/agent` endpoints are untouched, and the v2
51
52
  > API is namespaced under `/agents` (plural) so it never collides with the existing
52
53
  > single-agent `/agent` routes. Existing v1.x data is preserved; new runs are appended
53
54
  > to workspace state and the Knowledge Graph alongside it.
@@ -141,8 +141,9 @@ portable JSON representation (definition only — no run history or scope).
141
141
 
142
142
  ### 1.3 Multi-Agent Runtime 2.0 (`latticeai.core.multi_agent`)
143
143
 
144
- v1.x shipped a single-agent state machine (`latticeai.core.agent.AgentRuntime`:
145
- PLAN → EXECUTE → VERIFY → DONE). v2.0 adds the **orchestration** layer above it:
144
+ v1.x shipped a single-agent state machine (`latticeai.core.agent.SingleAgentRuntime`;
145
+ `latticeai.core.agent.AgentRuntime` remains a compatibility alias) that drives
146
+ PLAN → EXECUTE → VERIFY → DONE. v2.0 adds the **orchestration** layer above it:
146
147
  a pipeline of named roles that hand off to one another, retry on a failing
147
148
  review, and emit a structured timeline that drops straight into the Workspace
148
149
  timeline / Knowledge Graph.
@@ -26,7 +26,7 @@ from .storage import (
26
26
  storage_from_env,
27
27
  )
28
28
 
29
- __version__ = "7.8.0"
29
+ __version__ = "8.0.0"
30
30
 
31
31
  __all__ = [
32
32
  "AgentRuntime",
@@ -331,17 +331,31 @@ class KnowledgeGraphProjectionMixin:
331
331
  edge_id: Optional[str] = None,
332
332
  created_at: Optional[str] = None,
333
333
  strict: bool = False,
334
+ legacy_type: Optional[str] = None,
334
335
  ) -> None:
335
336
  if KGStoreV2 is None:
336
337
  if strict:
337
338
  raise RuntimeError("Knowledge Graph v2 schema is unavailable")
338
339
  return
339
- eid = (
340
- edge_id or f"edge:{_sha256_text(f'{from_node}|{edge_type}|{to_node}')[:24]}"
341
- )
340
+ explicit_legacy_type = legacy_type is not None
341
+ leg_type = legacy_type if explicit_legacy_type else edge_type
342
+ # Native canonical writes (and write-door dedupes) use legacy_type=''
343
+ # so (source,target,type) is the effective key.
344
+ # Import paths can pass distinct legacy_type to keep colliding legacy
345
+ # labels as separate rows (lossless for old data).
346
+ if leg_type and EdgeType is not None:
347
+ try:
348
+ if EdgeType.from_legacy(leg_type).value == leg_type:
349
+ leg_type = ""
350
+ except ValueError:
351
+ pass
342
352
  norm_type = (
343
353
  EdgeType.from_legacy(edge_type).value if EdgeType is not None else edge_type
344
354
  )
355
+ if explicit_legacy_type and leg_type:
356
+ eid = f"edge:{_sha256_text(f'{from_node}|{norm_type}|{to_node}|{leg_type}')[:24]}"
357
+ else:
358
+ eid = edge_id or f"edge:{_sha256_text(f'{from_node}|{norm_type}|{to_node}')[:24]}"
345
359
  meta_str = metadata_json if metadata_json is not None else "{}"
346
360
  confidence = float(_safe_loads(meta_str).get("confidence", 1.0))
347
361
  try:
@@ -360,7 +374,7 @@ class KnowledgeGraphProjectionMixin:
360
374
  from_node,
361
375
  to_node,
362
376
  norm_type,
363
- edge_type,
377
+ leg_type,
364
378
  float(weight),
365
379
  confidence,
366
380
  meta_str,
@@ -371,7 +385,7 @@ class KnowledgeGraphProjectionMixin:
371
385
  # (the UNIQUE upsert + weight=max alone would erase recurrence).
372
386
  row = conn.execute(
373
387
  "SELECT id FROM edges_v2 WHERE source=? AND target=? AND type=? AND legacy_type=?",
374
- (from_node, to_node, norm_type, edge_type),
388
+ (from_node, to_node, norm_type, leg_type),
375
389
  ).fetchone()
376
390
  if row is not None:
377
391
  conn.execute(
@@ -292,10 +292,24 @@ class KnowledgeGraphProvenanceMixin:
292
292
  plan["dry_run"] = True
293
293
  return plan
294
294
 
295
- if mode == "replace":
296
- self.clear_all()
297
-
298
295
  with self._connect() as conn:
296
+ if mode == "replace":
297
+ # Keep replacement imports transactional. The old clear_all()
298
+ # path committed before the import started, so a malformed
299
+ # artifact could leave a cleared or partially rebuilt graph.
300
+ # These deletes roll back with the rest of the import.
301
+ for table in (
302
+ "local_file_index",
303
+ "knowledge_sources",
304
+ "chunks",
305
+ "edges",
306
+ "nodes",
307
+ "vector_embeddings",
308
+ ):
309
+ conn.execute(f"DELETE FROM {table}")
310
+ if KGStoreV2 is not None:
311
+ conn.execute("DELETE FROM edges_v2")
312
+ conn.execute("DELETE FROM nodes_v2")
299
313
  for n in nodes:
300
314
  self._upsert_node(
301
315
  conn,
@@ -315,13 +329,21 @@ class KnowledgeGraphProvenanceMixin:
315
329
  metadata=_safe_loads(c.get("metadata_json")),
316
330
  )
317
331
  for e in edges:
332
+ e_meta = _safe_loads(e.get("metadata_json")) or {}
333
+ leg_label = e_meta.get("legacy_label")
334
+ if not leg_label:
335
+ orig = e.get("type") or ""
336
+ if orig:
337
+ # preserve whatever label came from export (legacy or canon)
338
+ leg_label = orig
318
339
  self._upsert_edge(
319
340
  conn,
320
341
  e["from_node"],
321
342
  e["to_node"],
322
343
  e["type"],
323
344
  weight=float(e.get("weight") or 1.0),
324
- metadata=_safe_loads(e.get("metadata_json")),
345
+ metadata=e_meta,
346
+ legacy_label=leg_label,
325
347
  )
326
348
  for s in sources:
327
349
  conn.execute(
@@ -73,20 +73,46 @@ class KnowledgeGraphWriteMixin:
73
73
  edge_type: str,
74
74
  weight: float = 1.0,
75
75
  metadata: Optional[Dict[str, Any]] = None,
76
+ *,
77
+ legacy_label: Optional[str] = None,
76
78
  ) -> str:
77
79
  # v4 write door: every new edge stores the canonical EdgeType value —
78
80
  # free-string types (e.g. '포함함', '언급함') are normalized here, so no
79
81
  # caller can mint new legacy taxonomy. The original label survives in
80
82
  # metadata.legacy_label for traceability.
83
+ #
84
+ # legacy_type in edges_v2:
85
+ # - normal write door: synonyms always dedupe to ONE row with legacy_type=''
86
+ # - import (passes legacy_label=) : preserves distinct legacy labels as
87
+ # separate v2 rows (lossless collision for old artifacts / backfill)
88
+ passed_for_legacy = legacy_label or edge_type
81
89
  if EdgeType is not None:
82
90
  canonical = EdgeType.from_legacy(edge_type).value
83
- if canonical != edge_type:
91
+ if canonical != edge_type or (legacy_label and legacy_label != canonical):
84
92
  metadata = dict(metadata or {})
85
- metadata.setdefault("legacy_label", edge_type)
93
+ ll = legacy_label or edge_type
94
+ if ll != canonical:
95
+ metadata.setdefault("legacy_label", ll)
86
96
  edge_type = canonical
87
97
  edge_id = f"edge:{_sha256_text(f'{from_node}|{edge_type}|{to_node}')[:24]}"
88
98
  now = _now()
89
99
  meta_json = _json(metadata) # canonical string shared with the projection
100
+ v2_legacy = ""
101
+ if passed_for_legacy and passed_for_legacy != edge_type:
102
+ if legacy_label is not None:
103
+ # explicit legacy_label from import path forces distinct legacy_type
104
+ # rows in v2 for collision preservation
105
+ v2_legacy = passed_for_legacy
106
+ else:
107
+ # normal write-door dedupes even for synonym labels (legacy_type='')
108
+ v2_legacy = ""
109
+ # v2 may use distinct eid when preserving legacy collisions (different from
110
+ # the canon-based edge_id used for legacy edges table which always dedupes)
111
+ v2_eid = (
112
+ f"edge:{_sha256_text(f'{from_node}|{edge_type}|{to_node}|{v2_legacy}')[:24]}"
113
+ if v2_legacy
114
+ else edge_id
115
+ )
90
116
  self._v2_project_edge(
91
117
  conn,
92
118
  from_node,
@@ -94,9 +120,10 @@ class KnowledgeGraphWriteMixin:
94
120
  edge_type,
95
121
  float(weight),
96
122
  meta_json,
97
- edge_id=edge_id,
123
+ edge_id=v2_eid,
98
124
  created_at=now,
99
125
  strict=True,
126
+ legacy_type=v2_legacy,
100
127
  )
101
128
  conn.execute(
102
129
  """
@@ -44,9 +44,9 @@ orchestrator, and the agent runtime service. Lazy-loaded so importing
44
44
  /agents/api/runtime/* , POST /agents (start via runtime.start or executor)
45
45
  api/chat.py
46
46
  from latticeai.services.tool_dispatch import build_agent_runtime
47
- -> latticeai/core/agent.py:AgentRuntime (별도 state/plan/transcript 머신, single-agent /agent 경로. dispatch_tool 만 공유)
47
+ -> latticeai/core/agent.py:SingleAgentRuntime (별도 state/plan/transcript 머신, single-agent /agent 경로. dispatch_tool 만 공유)
48
48
  latticeai/services/tool_dispatch.py:14
49
- from latticeai.core.agent import AgentRuntime as CoreAgentRuntime
49
+ from latticeai.core.agent import SingleAgentRuntime
50
50
  (tool governance + core single-agent용)
51
51
  latticeai/services/platform_runtime.py
52
52
  from lattice_brain.runtime.{hooks, multi_agent}
@@ -54,6 +54,7 @@ orchestrator, and the agent runtime service. Lazy-loaded so importing
54
54
 
55
55
  core/tool_registry.py (신규) + services/tool_dispatch.py 가 tool build 주도.
56
56
  lattice_brain/runtime 는 multi-agent + hooks + facade 에 집중. core/agent 는 chat/agent 단일 루프.
57
+ 기존 latticeai.core.agent.AgentRuntime import 는 SingleAgentRuntime 호환 alias 로 유지.
57
58
 
58
59
  이 매핑으로 중복 제거 및 wiring 명확화 완료 (feat(Act, automation) 방향).
59
60
  """
@@ -64,6 +65,7 @@ __all__ = [
64
65
  "AgentRuntime",
65
66
  "AgentRuntimeUnavailable",
66
67
  "MultiAgentOrchestrator",
68
+ "RuntimeBoundaryProtocol",
67
69
  "HooksRegistry",
68
70
  "dispatch_tool",
69
71
  ]
@@ -78,6 +80,10 @@ def __getattr__(name: str):
78
80
  from .multi_agent import MultiAgentOrchestrator
79
81
 
80
82
  return MultiAgentOrchestrator
83
+ if name == "RuntimeBoundaryProtocol":
84
+ from .contracts import RuntimeBoundaryProtocol
85
+
86
+ return RuntimeBoundaryProtocol
81
87
  if name in {"HooksRegistry", "dispatch_tool"}:
82
88
  from . import hooks
83
89
 
@@ -37,7 +37,13 @@ from .multi_agent import (
37
37
  MULTI_AGENT_VERSION,
38
38
  ROLE_AGENT_IDS,
39
39
  )
40
- from .contracts import contract_view, contract_views, extract_contract, multi_agent_contract
40
+ from .contracts import (
41
+ contract_view,
42
+ contract_views,
43
+ extract_contract,
44
+ multi_agent_contract,
45
+ runtime_boundary_contract,
46
+ )
41
47
 
42
48
  ROLE_DESCRIPTIONS = {
43
49
  "researcher": "Gathers workspace context and memory for the goal.",
@@ -91,10 +97,20 @@ class AgentRuntime:
91
97
  def _execution_mode(self) -> str:
92
98
  return "async" if self._run_executor is not None else "synchronous"
93
99
 
100
+ def boundary(self) -> Dict[str, Any]:
101
+ return runtime_boundary_contract(
102
+ name="AgentRuntime",
103
+ runtime="multi_agent",
104
+ entrypoint="lattice_brain.runtime.agent_runtime.AgentRuntime",
105
+ surface="/agents",
106
+ owns="product agent execution, observability, status, health, events, replay, and stop",
107
+ )
108
+
94
109
  # ── configuration ─────────────────────────────────────────────────────
95
110
  def config(self) -> Dict[str, Any]:
96
111
  return {
97
112
  "version": MULTI_AGENT_VERSION,
113
+ "boundary": self.boundary(),
98
114
  "roles": list(AGENT_ROLES),
99
115
  "default_pipeline": list(CORE_PIPELINE),
100
116
  "max_retries_cap": self._max_retries_cap,
@@ -30,7 +30,7 @@ from __future__ import annotations
30
30
 
31
31
  from dataclasses import dataclass, field
32
32
  from datetime import datetime
33
- from typing import Any, Dict, Iterable, List, Optional
33
+ from typing import Any, Dict, Iterable, List, Optional, Protocol, runtime_checkable
34
34
 
35
35
 
36
36
  def runtime_timestamp() -> str:
@@ -69,6 +69,8 @@ CONTRACT_VIEW_KEYS = (
69
69
  "blocking_reasons",
70
70
  )
71
71
 
72
+ RUNTIME_BOUNDARY_SCHEMA = "runtime-boundary/v1"
73
+
72
74
  _SCHEMA_FOR_KIND = {
73
75
  "agent_run": AGENT_RUN_SCHEMA,
74
76
  "workflow_run": WORKFLOW_RUN_SCHEMA,
@@ -223,6 +225,67 @@ def multi_agent_contract(
223
225
  ).as_dict()
224
226
 
225
227
 
228
+ @dataclass(frozen=True)
229
+ class RuntimeBoundaryContract:
230
+ """Machine-readable descriptor for an execution runtime boundary.
231
+
232
+ This is intentionally separate from run records: it lets tests, routers, and
233
+ docs assert which class owns which execution surface without importing the
234
+ wrong runtime by name.
235
+ """
236
+
237
+ name: str
238
+ runtime: str
239
+ entrypoint: str
240
+ surface: str
241
+ owns: str
242
+ compatibility_aliases: List[str] = field(default_factory=list)
243
+
244
+ def as_dict(self) -> Dict[str, Any]:
245
+ return {
246
+ "schema_version": RUNTIME_BOUNDARY_SCHEMA,
247
+ "name": self.name,
248
+ "runtime": self.runtime,
249
+ "entrypoint": self.entrypoint,
250
+ "surface": self.surface,
251
+ "owns": self.owns,
252
+ "compatibility_aliases": list(self.compatibility_aliases),
253
+ }
254
+
255
+
256
+ def runtime_boundary_contract(
257
+ *,
258
+ name: str,
259
+ runtime: str,
260
+ entrypoint: str,
261
+ surface: str,
262
+ owns: str,
263
+ compatibility_aliases: Optional[List[str]] = None,
264
+ ) -> Dict[str, Any]:
265
+ return RuntimeBoundaryContract(
266
+ name=name,
267
+ runtime=runtime,
268
+ entrypoint=entrypoint,
269
+ surface=surface,
270
+ owns=owns,
271
+ compatibility_aliases=list(compatibility_aliases or []),
272
+ ).as_dict()
273
+
274
+
275
+ @runtime_checkable
276
+ class RuntimeBoundaryProtocol(Protocol):
277
+ """Minimal shared surface for runtime boundary discovery.
278
+
279
+ Product ``AgentRuntime`` and core ``SingleAgentRuntime`` intentionally keep
280
+ different execution methods. This protocol only fixes the common inspection
281
+ surface that DI, readiness gates, and tests can depend on safely.
282
+ """
283
+
284
+ def boundary(self) -> Dict[str, Any]: ...
285
+
286
+ def config(self) -> Dict[str, Any]: ...
287
+
288
+
226
289
  def run_record_contract(run: Dict[str, Any], *, runtime: str = "multi_agent") -> Dict[str, Any]:
227
290
  """Build the family contract from a persisted agent run row."""
228
291
  run = dict(run or {})
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, List, Optional
21
21
  from .contracts import multi_agent_contract
22
22
 
23
23
 
24
- MULTI_AGENT_VERSION = "7.8.0"
24
+ MULTI_AGENT_VERSION = "8.0.0"
25
25
 
26
26
  AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
27
27
  CORE_PIPELINE = ("planner", "executor", "reviewer")
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "7.8.0"
3
+ __version__ = "8.0.0"
@@ -1,7 +1,7 @@
1
- """Agent Runtime — the Discover→Plan→Implement→Verify state machine.
1
+ """Single-agent runtime — the Discover→Plan→Implement→Verify state machine.
2
2
 
3
- This module is the deep one: a small interface (``AgentDeps`` ports +
4
- ``AgentRuntime.run_to_completion``) over the whole multi-role agent loop
3
+ This module is the deep single-agent loop: a small interface (``AgentDeps`` ports +
4
+ ``SingleAgentRuntime.run_to_completion``) over the whole role-phased state machine
5
5
  (planner → executor → critic → rollback → memory). It carries no FastAPI,
6
6
  no globals, and no I/O of its own — every collaborator is injected through
7
7
  ``AgentDeps``.
@@ -23,14 +23,13 @@ from __future__ import annotations
23
23
  import json
24
24
  import logging
25
25
  import re
26
- import subprocess
27
26
  from dataclasses import dataclass
28
27
  from enum import Enum
29
28
  from pathlib import Path
30
29
  from typing import Any, Awaitable, Callable, Dict, FrozenSet, List, Optional
31
30
 
32
31
  from lattice_brain.runtime.hooks import dispatch_tool
33
- from lattice_brain.runtime.contracts import single_agent_contract
32
+ from lattice_brain.runtime.contracts import runtime_boundary_contract, single_agent_contract
34
33
  from tools import ToolError
35
34
 
36
35
 
@@ -92,7 +91,7 @@ def extract_action(raw: str) -> Dict:
92
91
 
93
92
  @dataclass
94
93
  class AgentDeps:
95
- """The ports an :class:`AgentRuntime` needs from the outside world.
94
+ """The ports a :class:`SingleAgentRuntime` needs from the outside world.
96
95
 
97
96
  Everything the state machine touches is here, so the loop can be exercised
98
97
  against fakes. See module docstring for the two-adapter rationale.
@@ -125,6 +124,11 @@ class AgentDeps:
125
124
  memory_updater_prompt: str
126
125
  agent_root: Path
127
126
 
127
+ # ── rollback port (optional) ─────────────────────────────────────
128
+ # Production injects this from the tool dispatch service so this pure
129
+ # state machine does not shell out directly. Tests can pass a recorder.
130
+ rollback_file: Optional[Callable[[str], Dict[str, Any]]] = None
131
+
128
132
  # ── lifecycle hooks port (optional) ──────────────────────────────
129
133
  # When present, every tool execution fires the shared pre_tool/post_tool
130
134
  # lifecycle, so the agent tool path no longer bypasses hooks.
@@ -137,12 +141,30 @@ class AgentDeps:
137
141
  brain_memory: Any = None
138
142
 
139
143
 
140
- class AgentRuntime:
144
+ class SingleAgentRuntime:
141
145
  """Drives the agent state machine over injected :class:`AgentDeps`."""
142
146
 
143
147
  def __init__(self, deps: AgentDeps) -> None:
144
148
  self.deps = deps
145
149
 
150
+ def boundary(self) -> Dict[str, Any]:
151
+ return runtime_boundary_contract(
152
+ name="SingleAgentRuntime",
153
+ runtime="single_agent",
154
+ entrypoint="latticeai.core.agent.SingleAgentRuntime",
155
+ surface="/agent",
156
+ owns="single-agent PLAN / EXECUTE / VERIFY state machine over injected ports",
157
+ compatibility_aliases=["latticeai.core.agent.AgentRuntime"],
158
+ )
159
+
160
+ def config(self) -> Dict[str, Any]:
161
+ return {
162
+ "boundary": self.boundary(),
163
+ "states": [state.value for state in AgentState],
164
+ "terminal_states": sorted(state.value for state in AGENT_TERMINAL_STATES),
165
+ "execution_mode": "injected_ports",
166
+ }
167
+
146
168
  def contract(self, ctx: AgentRunContext, req: Any, *, run_id: Optional[str] = None) -> Dict[str, Any]:
147
169
  """Expose the shared agent-run contract for the single-agent loop."""
148
170
  return single_agent_contract(ctx=ctx, goal=getattr(req, "message", ""), run_id=run_id)
@@ -405,12 +427,11 @@ class AgentRuntime:
405
427
  path = result.get("path") or (step.get("args") or {}).get("path", "")
406
428
  if not path:
407
429
  continue
430
+ if d.rollback_file is None:
431
+ rolled.append({"path": path, "ok": False, "error": "rollback_file port is not configured"})
432
+ continue
408
433
  try:
409
- r = subprocess.run(
410
- ["git", "checkout", "--", path], cwd=str(d.agent_root),
411
- capture_output=True, text=True, timeout=10,
412
- )
413
- rolled.append({"path": path, "ok": r.returncode == 0, "stderr": r.stderr[:200]})
434
+ rolled.append(d.rollback_file(str(path)))
414
435
  except Exception as exc:
415
436
  rolled.append({"path": path, "ok": False, "error": str(exc)})
416
437
 
@@ -491,3 +512,9 @@ class AgentRuntime:
491
512
  ctx.state = AgentState.FAILED
492
513
 
493
514
  ctx.state_history.append(ctx.state.value)
515
+
516
+
517
+ # Backward compatibility: external callers historically imported
518
+ # ``latticeai.core.agent.AgentRuntime`` for the single-agent state machine.
519
+ # The product/runtime facade lives at ``lattice_brain.runtime.agent_runtime``.
520
+ AgentRuntime = SingleAgentRuntime
@@ -11,7 +11,7 @@ from copy import deepcopy
11
11
  from typing import Any, Dict, List, Optional
12
12
 
13
13
 
14
- MARKETPLACE_VERSION = "7.8.0"
14
+ MARKETPLACE_VERSION = "8.0.0"
15
15
  TEMPLATE_KINDS = ("plugin", "workflow", "agent")
16
16
 
17
17
 
@@ -292,7 +292,14 @@ class ToolRegistry:
292
292
  })
293
293
  diagnostics = self.diagnostics()
294
294
  return {
295
+ "schema_version": "tool-registry-contract/v1",
295
296
  "status": "ok" if diagnostics["ready"] else "degraded",
297
+ "boundary": {
298
+ "owner": "latticeai.core.tool_registry.ToolRegistry",
299
+ "dispatch_owner": "tools.DEFAULT_TOOL_REGISTRY",
300
+ "policy_owner": "latticeai.core.tool_registry.ToolRegistry",
301
+ "permission_owner": "latticeai.services.tool_dispatch.ToolDispatchService",
302
+ },
296
303
  "catalog_brief": self.catalog_brief.strip(),
297
304
  "diagnostics": diagnostics,
298
305
  "tools": tools,
@@ -21,7 +21,7 @@ from typing import Any, Callable, Dict, Iterable, List, Optional
21
21
  from lattice_brain.runtime.contracts import realtime_event_contract, run_record_contract, workflow_run_contract
22
22
 
23
23
 
24
- WORKSPACE_OS_VERSION = "7.8.0"
24
+ WORKSPACE_OS_VERSION = "8.0.0"
25
25
 
26
26
  # Workspace types separate single-user Personal workspaces from shared
27
27
  # Organization workspaces. Both keep the same local-first JSON store; the type
@@ -1,10 +1,9 @@
1
1
  """Machine-checkable architecture readiness gates for release work.
2
2
 
3
- The 7.7 complete-product line preserves the 7.6 closure of the two local review
4
- notes by keeping their architectural claims in a small contract: AgentRuntime,
5
- ToolRegistry, central Config,
6
- decomposed API routers, and Knowledge Graph portability must all be discoverable
7
- and testable before the release can be called complete.
3
+ 8.0.0 turns the major architecture priorities into an explicit release
4
+ contract. AgentRuntime, ToolRegistry, central Config, decomposed server runtime,
5
+ and Knowledge Graph stabilization must be discoverable, ordered, and backed by
6
+ tests before the release can be called complete.
8
7
  """
9
8
 
10
9
  from __future__ import annotations
@@ -15,6 +14,19 @@ from pathlib import Path
15
14
  from typing import Any, Dict, List
16
15
 
17
16
 
17
+ ARCHITECTURE_VERSION_TARGET = "8.0.0"
18
+
19
+ PREFERRED_REFACTORING_ORDER = [
20
+ "agent-runtime",
21
+ "tool-registry",
22
+ "config-centralization",
23
+ "server-decomposition",
24
+ "kg-hardening",
25
+ "documentation-sync",
26
+ "ui-enhancements",
27
+ ]
28
+
29
+
18
30
  @dataclass(frozen=True)
19
31
  class ArchitectureGate:
20
32
  id: str
@@ -108,12 +120,43 @@ def architecture_readiness(root: Path | None = None) -> Dict[str, Any]:
108
120
 
109
121
  api_router_count = len(list((root / "latticeai" / "api").glob("*.py")))
110
122
  runtime_module_count = len(list((root / "latticeai" / "runtime").glob("*.py")))
123
+ ordered_gate_ids = [gate.id for gate in gates]
124
+ contract = {
125
+ "schema_version": "lattice-architecture-contract/v1",
126
+ "version_target": ARCHITECTURE_VERSION_TARGET,
127
+ "refactoring_order": list(PREFERRED_REFACTORING_ORDER),
128
+ "boundaries": {
129
+ "agent-runtime": {
130
+ "owner": "lattice_brain.runtime.agent_runtime.AgentRuntime",
131
+ "surface": "/agents",
132
+ "status": "facade",
133
+ },
134
+ "tool-registry": {
135
+ "owner": "latticeai.core.tool_registry.ToolRegistry",
136
+ "surface": "/tools",
137
+ "status": "registry",
138
+ },
139
+ "config-centralization": {
140
+ "owner": "latticeai.core.config.Config",
141
+ "surface": "composition root",
142
+ "status": "typed-config",
143
+ },
144
+ "kg-hardening": {
145
+ "owner": "lattice_brain.graph.store.KnowledgeGraphStore",
146
+ "strategy": "additive reprojection with legacy read compatibility",
147
+ "rollback": "portable export/import and non-destructive migration paths",
148
+ },
149
+ },
150
+ "ordered_gate_ids": ordered_gate_ids,
151
+ }
111
152
  return {
112
153
  "status": "complete" if all(gate.status == "complete" for gate in gates) else "incomplete",
113
- "version_target": "7.8.0",
154
+ "version_target": ARCHITECTURE_VERSION_TARGET,
155
+ "contract": contract,
114
156
  "gates": [gate.__dict__ for gate in gates],
115
157
  "metrics": {
116
158
  "api_router_modules": api_router_count,
117
159
  "runtime_modules": runtime_module_count,
160
+ "architecture_gates": len(gates),
118
161
  },
119
162
  }
@@ -1,12 +1,13 @@
1
- """Machine-checkable *product* readiness gates for the 7.8 line.
1
+ """Machine-checkable *product* readiness gates for the 8.0 line.
2
2
 
3
3
  Where ``architecture_readiness`` proves the internal structure is sound, this
4
- module answers the product question the 7.8 release exists to settle: *can
5
- someone understand and use the Brain at a glance?* It does so honestly — every
6
- gate is backed by evidence that is probed on disk, so a gate only reports
7
- ``complete`` when its evidence actually resolves. The same report can be printed
8
- by ``scripts/product_readiness.py`` and re-run after every change, which is the
9
- point: completeness is something we keep measuring, not a one-time claim.
4
+ module answers the product question the 8.0 release exists to settle: *are the
5
+ runtime boundaries still clear and release-ready after hardening?* It does so
6
+ honestly — every gate is backed by evidence that is probed on disk, so a gate
7
+ only reports ``complete`` when its evidence actually resolves. The same report
8
+ can be printed by ``scripts/product_readiness.py`` and re-run after every
9
+ change, which is the point: completeness is something we keep measuring, not a
10
+ one-time claim.
10
11
  """
11
12
 
12
13
  from __future__ import annotations
@@ -17,7 +18,7 @@ from typing import Any, Dict, List
17
18
 
18
19
  from latticeai.services.architecture_readiness import architecture_readiness
19
20
 
20
- PRODUCT_VERSION_TARGET = "7.8.0"
21
+ PRODUCT_VERSION_TARGET = "8.0.0"
21
22
 
22
23
 
23
24
  @dataclass(frozen=True)
@@ -64,10 +65,10 @@ PRODUCT_GATES: List[ProductGate] = [
64
65
  evidence=[
65
66
  "package.json::release:artifacts",
66
67
  "package.json::release:validate",
67
- "README.md::dist/ltcai-7.8.0-py3-none-any.whl",
68
- "README.md::dist/ltcai-7.8.0.tar.gz",
69
- "README.md::dist/ltcai-7.8.0.vsix",
70
- "README.md::ltcai-7.8.0.tgz",
68
+ "README.md::dist/ltcai-8.0.0-py3-none-any.whl",
69
+ "README.md::dist/ltcai-8.0.0.tar.gz",
70
+ "README.md::dist/ltcai-8.0.0.vsix",
71
+ "README.md::ltcai-8.0.0.tgz",
71
72
  "scripts/validate_release_artifacts.py",
72
73
  "scripts/release_smoke.py",
73
74
  "Dockerfile",
@@ -83,12 +84,20 @@ PRODUCT_GATES: List[ProductGate] = [
83
84
  title="Release story is documented and honest",
84
85
  evidence=[
85
86
  "README.md",
86
- "README.md::The current release is **7.8.0",
87
- "SECURITY.md::7.8.x (latest)",
88
- "vscode-extension/README.md::**7.8.0",
89
- "docs/CHANGELOG.md::## [7.8.0]",
87
+ "README.md::The current release is **8.0.0",
88
+ "SECURITY.md::8.0.x (latest)",
89
+ "vscode-extension/README.md::**8.0.0",
90
+ "docs/CHANGELOG.md::## [8.0.0]",
90
91
  "FEATURE_STATUS.md",
91
- "RELEASE_NOTES_v7.8.0.md",
92
+ "RELEASE_NOTES_v8.0.0.md",
93
+ "latticeai/core/agent.py::SingleAgentRuntime",
94
+ "latticeai/core/agent.py::AgentRuntime = SingleAgentRuntime",
95
+ "lattice_brain/runtime/contracts.py::runtime-boundary/v1",
96
+ "lattice_brain/runtime/contracts.py::RuntimeBoundaryProtocol",
97
+ "lattice_brain/runtime/agent_runtime.py::def boundary",
98
+ "latticeai/core/agent.py::def boundary",
99
+ "latticeai/services/architecture_readiness.py::lattice-architecture-contract/v1",
100
+ "latticeai/services/tool_dispatch.py::rollback_file",
92
101
  ],
93
102
  ),
94
103
  ProductGate(
@@ -8,11 +8,12 @@ from __future__ import annotations
8
8
 
9
9
  from dataclasses import dataclass, field
10
10
  from pathlib import Path
11
+ import subprocess
11
12
  from typing import Any, Callable, Dict, Mapping, Optional
12
13
 
13
14
  from fastapi import HTTPException
14
15
 
15
- from latticeai.core.agent import AgentDeps, AgentRuntime
16
+ from latticeai.core.agent import AgentDeps, SingleAgentRuntime
16
17
  from latticeai.core.agent_prompts import (
17
18
  CRITIC_PROMPT,
18
19
  EXECUTOR_PROMPT,
@@ -106,6 +107,16 @@ class ToolDispatchService:
106
107
  detail=f"'{tool_name}' 툴은 관리자 전용입니다.",
107
108
  )
108
109
 
110
+ def rollback_file(self, path: str) -> Dict[str, Any]:
111
+ r = subprocess.run(
112
+ ["git", "checkout", "--", path],
113
+ cwd=str(AGENT_ROOT),
114
+ capture_output=True,
115
+ text=True,
116
+ timeout=10,
117
+ )
118
+ return {"path": path, "ok": r.returncode == 0, "stderr": r.stderr[:200]}
119
+
109
120
 
110
121
  DEFAULT_TOOL_DISPATCH_SERVICE = ToolDispatchService()
111
122
 
@@ -185,7 +196,7 @@ def build_agent_runtime(
185
196
  hooks: Any = None,
186
197
  brain_memory: Any = None,
187
198
  dispatch_service: ToolDispatchService = DEFAULT_TOOL_DISPATCH_SERVICE,
188
- ) -> AgentRuntime:
199
+ ) -> SingleAgentRuntime:
189
200
  ensure_agent_root()
190
201
  deps = AgentDeps(
191
202
  generate_as=model_router.generate_as,
@@ -205,10 +216,11 @@ def build_agent_runtime(
205
216
  critic_prompt=CRITIC_PROMPT,
206
217
  memory_updater_prompt=MEMORY_UPDATER_PROMPT,
207
218
  agent_root=AGENT_ROOT,
219
+ rollback_file=dispatch_service.rollback_file,
208
220
  hooks=hooks,
209
221
  brain_memory=brain_memory,
210
222
  )
211
- return AgentRuntime(deps)
223
+ return SingleAgentRuntime(deps)
212
224
 
213
225
 
214
226
  def tool_response(fn, *args):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ltcai",
3
- "version": "7.8.0",
3
+ "version": "8.0.0",
4
4
  "description": "Lattice AI — local-first Digital Brain that keeps your knowledge durable across any AI model.",
5
5
  "homepage": "https://github.com/TaeSooPark-PTS/LatticeAI#readme",
6
6
  "repository": {
@@ -1584,7 +1584,7 @@ dependencies = [
1584
1584
 
1585
1585
  [[package]]
1586
1586
  name = "lattice-ai-desktop"
1587
- version = "7.7.0"
1587
+ version = "8.0.0"
1588
1588
  dependencies = [
1589
1589
  "plist",
1590
1590
  "serde",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "lattice-ai-desktop"
3
- version = "7.8.0"
3
+ version = "8.0.0"
4
4
  description = "Lattice AI Digital Brain desktop shell"
5
5
  authors = ["TaeSoo Park"]
6
6
  edition = "2021"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://schema.tauri.app/config/2",
3
3
  "productName": "Lattice AI",
4
- "version": "7.8.0",
4
+ "version": "8.0.0",
5
5
  "identifier": "ai.lattice.desktop",
6
6
  "build": {
7
7
  "beforeDevCommand": "npm run frontend:dev",
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.8.0",
2
+ "version": "8.0.0",
3
3
  "generated_at": "vite",
4
4
  "entrypoints": {
5
5
  "app": "/static/app/index.html"