ltcai 7.8.0 → 7.9.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 +34 -30
- package/docs/CHANGELOG.md +17 -0
- package/docs/DEVELOPMENT.md +1 -2
- package/docs/MULTI_AGENT_RUNTIME.md +6 -5
- package/docs/V2_ARCHITECTURE.md +3 -2
- package/lattice_brain/__init__.py +1 -1
- package/lattice_brain/runtime/__init__.py +8 -2
- package/lattice_brain/runtime/agent_runtime.py +17 -1
- package/lattice_brain/runtime/contracts.py +64 -1
- package/lattice_brain/runtime/multi_agent.py +1 -1
- package/latticeai/__init__.py +1 -1
- package/latticeai/core/agent.py +39 -12
- package/latticeai/core/marketplace.py +1 -1
- package/latticeai/core/workspace_os.py +1 -1
- package/latticeai/services/architecture_readiness.py +1 -1
- package/latticeai/services/product_readiness.py +20 -13
- package/latticeai/services/tool_dispatch.py +15 -3
- package/package.json +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 +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Lattice AI
|
|
2
2
|
|
|
3
|
-
**Lattice AI 7.
|
|
3
|
+
**Lattice AI 7.9 is the local-first Digital Brain product with cleaner runtime boundaries. It keeps your knowledge durable across any AI model, with Brain Chat Home ready for immediate use and agent execution hardened behind explicit runtime ports.**
|
|
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
|
|
14
|
+
It is the finished private AI memory layer wrapped in a Living Brain experience — now with a clearer 7.9 agent-runtime boundary.
|
|
15
15
|
|
|
16
16
|
[](https://pypi.org/project/ltcai/)
|
|
17
17
|
[](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.
|
|
67
|
+
The screenshots below are release evidence captures. The 7.9 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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
134
134
|
|
|
135
135
|
Screenshot index and capture notes:
|
|
136
|
-
[output/release/v7.
|
|
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,36 @@ 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.
|
|
214
|
-
|
|
215
|
-
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
the
|
|
221
|
-
-
|
|
222
|
-
|
|
213
|
+
The current release is **7.9.0 — Agent Runtime Boundary Hardening**:
|
|
214
|
+
|
|
215
|
+
- The single-agent state machine is now named `SingleAgentRuntime`, while the
|
|
216
|
+
historical `AgentRuntime` import remains as a compatibility alias.
|
|
217
|
+
- The product AgentRuntime facade in `lattice_brain.runtime.agent_runtime`
|
|
218
|
+
remains the unambiguous `/agents` execution and observability boundary.
|
|
219
|
+
- Agent rollback is now an injected runtime port wired through
|
|
220
|
+
`ToolDispatchService`, so the core state machine no longer shells out directly.
|
|
221
|
+
- Both runtime surfaces expose a `runtime-boundary/v1` descriptor so tests and
|
|
222
|
+
API clients can identify the owning execution boundary without relying on
|
|
223
|
+
ambiguous class names.
|
|
224
|
+
- A shared `RuntimeBoundaryProtocol` now fixes the common inspection surface
|
|
225
|
+
while letting each runtime keep its own execution methods.
|
|
223
226
|
- Product readiness is machine-checkable through `product_readiness()`, which
|
|
224
227
|
composes the architecture contract with exact artifact/docs/workflow evidence.
|
|
225
228
|
- CI and release workflows now run frontend lint/typecheck/build gates plus the
|
|
226
|
-
7.
|
|
229
|
+
7.9 product readiness score before a tag can be treated as release-safe.
|
|
227
230
|
|
|
228
|
-
Expected artifacts for 7.
|
|
231
|
+
Expected artifacts for 7.9.0 release must use exact filenames:
|
|
229
232
|
|
|
230
|
-
- `dist/ltcai-7.
|
|
231
|
-
- `dist/ltcai-7.
|
|
232
|
-
- `ltcai-7.
|
|
233
|
-
- `dist/ltcai-7.
|
|
234
|
-
- `src-tauri/target/release/bundle/dmg/Lattice AI_7.
|
|
233
|
+
- `dist/ltcai-7.9.0-py3-none-any.whl`
|
|
234
|
+
- `dist/ltcai-7.9.0.tar.gz`
|
|
235
|
+
- `ltcai-7.9.0.tgz`
|
|
236
|
+
- `dist/ltcai-7.9.0.vsix`
|
|
237
|
+
- `src-tauri/target/release/bundle/dmg/Lattice AI_7.9.0_aarch64.dmg`
|
|
235
238
|
|
|
236
|
-
Do not
|
|
239
|
+
Do not use wildcard artifact uploads. Package registry publishing remains owner-run.
|
|
237
240
|
|
|
238
241
|
See [docs/ROADMAP_RECOMMENDATIONS.md](docs/ROADMAP_RECOMMENDATIONS.md) for the
|
|
239
|
-
strategic roadmap slices applied through 7.
|
|
242
|
+
strategic roadmap slices applied through 7.9.0 and the follow-up tracks.
|
|
240
243
|
|
|
241
244
|
## Known Limitations
|
|
242
245
|
|
|
@@ -253,6 +256,7 @@ strategic roadmap slices applied through 7.8.0 and the follow-up tracks.
|
|
|
253
256
|
|
|
254
257
|
| Version | Theme |
|
|
255
258
|
| --- | --- |
|
|
259
|
+
| 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
260
|
| 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
261
|
| 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
262
|
| 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,21 @@ existed at that release.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [7.9.0] - 2026-06-23
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Added `SingleAgentRuntime` as the explicit name for the legacy single-agent
|
|
13
|
+
state machine while preserving `AgentRuntime` as a compatibility alias.
|
|
14
|
+
- Updated tool dispatch to build `SingleAgentRuntime` directly.
|
|
15
|
+
- Moved single-agent git rollback behind an injected `rollback_file` port owned
|
|
16
|
+
by `ToolDispatchService`, keeping shell execution out of the core state
|
|
17
|
+
machine.
|
|
18
|
+
- Added a shared `runtime-boundary/v1` descriptor so product and single-agent
|
|
19
|
+
runtime boundaries are machine-readable in config/tests.
|
|
20
|
+
- Added `RuntimeBoundaryProtocol` as the minimal shared inspection surface for
|
|
21
|
+
runtime-boundary-aware dependency injection.
|
|
22
|
+
- Updated architecture and product readiness targets to 7.9.0.
|
|
23
|
+
|
|
9
24
|
## [7.8.0] - 2026-06-22
|
|
10
25
|
|
|
11
26
|
### Changed
|
|
@@ -23,6 +38,8 @@ existed at that release.
|
|
|
23
38
|
- Moved draft onboarding polish out of inline styles and into the shared design
|
|
24
39
|
stylesheet with responsive behavior and bilingual copy.
|
|
25
40
|
- Updated architecture and product readiness targets to 7.8.0.
|
|
41
|
+
- Refreshed 7.8.0 release screenshots, walkthrough video/GIF, and capture
|
|
42
|
+
notes under `output/release/v7.8.0/`.
|
|
26
43
|
|
|
27
44
|
## [7.7.0] - 2026-06-22
|
|
28
45
|
|
package/docs/DEVELOPMENT.md
CHANGED
|
@@ -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
|
|
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 ([`
|
|
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 — `
|
|
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.
|
|
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 `
|
|
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
|
-
> `
|
|
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.
|
package/docs/V2_ARCHITECTURE.md
CHANGED
|
@@ -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.
|
|
145
|
-
|
|
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.
|
|
@@ -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:
|
|
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
|
|
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
|
|
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.
|
|
24
|
+
MULTI_AGENT_VERSION = "7.9.0"
|
|
25
25
|
|
|
26
26
|
AGENT_ROLES = ("researcher", "planner", "executor", "reviewer", "release")
|
|
27
27
|
CORE_PIPELINE = ("planner", "executor", "reviewer")
|
package/latticeai/__init__.py
CHANGED
package/latticeai/core/agent.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Single-agent runtime — the Discover→Plan→Implement→Verify state machine.
|
|
2
2
|
|
|
3
|
-
This module is the deep
|
|
4
|
-
``
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
@@ -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.
|
|
24
|
+
WORKSPACE_OS_VERSION = "7.9.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
|
|
@@ -110,7 +110,7 @@ def architecture_readiness(root: Path | None = None) -> Dict[str, Any]:
|
|
|
110
110
|
runtime_module_count = len(list((root / "latticeai" / "runtime").glob("*.py")))
|
|
111
111
|
return {
|
|
112
112
|
"status": "complete" if all(gate.status == "complete" for gate in gates) else "incomplete",
|
|
113
|
-
"version_target": "7.
|
|
113
|
+
"version_target": "7.9.0",
|
|
114
114
|
"gates": [gate.__dict__ for gate in gates],
|
|
115
115
|
"metrics": {
|
|
116
116
|
"api_router_modules": api_router_count,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"""Machine-checkable *product* readiness gates for the 7.
|
|
1
|
+
"""Machine-checkable *product* readiness gates for the 7.9 line.
|
|
2
2
|
|
|
3
3
|
Where ``architecture_readiness`` proves the internal structure is sound, this
|
|
4
|
-
module answers the product question the 7.
|
|
5
|
-
|
|
4
|
+
module answers the product question the 7.9 release exists to settle: *are the
|
|
5
|
+
runtime boundaries still clear and release-ready after hardening?* It does so honestly — every
|
|
6
6
|
gate is backed by evidence that is probed on disk, so a gate only reports
|
|
7
7
|
``complete`` when its evidence actually resolves. The same report can be printed
|
|
8
8
|
by ``scripts/product_readiness.py`` and re-run after every change, which is the
|
|
@@ -17,7 +17,7 @@ from typing import Any, Dict, List
|
|
|
17
17
|
|
|
18
18
|
from latticeai.services.architecture_readiness import architecture_readiness
|
|
19
19
|
|
|
20
|
-
PRODUCT_VERSION_TARGET = "7.
|
|
20
|
+
PRODUCT_VERSION_TARGET = "7.9.0"
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
@dataclass(frozen=True)
|
|
@@ -64,10 +64,10 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
64
64
|
evidence=[
|
|
65
65
|
"package.json::release:artifacts",
|
|
66
66
|
"package.json::release:validate",
|
|
67
|
-
"README.md::dist/ltcai-7.
|
|
68
|
-
"README.md::dist/ltcai-7.
|
|
69
|
-
"README.md::dist/ltcai-7.
|
|
70
|
-
"README.md::ltcai-7.
|
|
67
|
+
"README.md::dist/ltcai-7.9.0-py3-none-any.whl",
|
|
68
|
+
"README.md::dist/ltcai-7.9.0.tar.gz",
|
|
69
|
+
"README.md::dist/ltcai-7.9.0.vsix",
|
|
70
|
+
"README.md::ltcai-7.9.0.tgz",
|
|
71
71
|
"scripts/validate_release_artifacts.py",
|
|
72
72
|
"scripts/release_smoke.py",
|
|
73
73
|
"Dockerfile",
|
|
@@ -83,12 +83,19 @@ PRODUCT_GATES: List[ProductGate] = [
|
|
|
83
83
|
title="Release story is documented and honest",
|
|
84
84
|
evidence=[
|
|
85
85
|
"README.md",
|
|
86
|
-
"README.md::The current release is **7.
|
|
87
|
-
"SECURITY.md::7.
|
|
88
|
-
"vscode-extension/README.md::**7.
|
|
89
|
-
"docs/CHANGELOG.md::## [7.
|
|
86
|
+
"README.md::The current release is **7.9.0",
|
|
87
|
+
"SECURITY.md::7.9.x (latest)",
|
|
88
|
+
"vscode-extension/README.md::**7.9.0",
|
|
89
|
+
"docs/CHANGELOG.md::## [7.9.0]",
|
|
90
90
|
"FEATURE_STATUS.md",
|
|
91
|
-
"RELEASE_NOTES_v7.
|
|
91
|
+
"RELEASE_NOTES_v7.9.0.md",
|
|
92
|
+
"latticeai/core/agent.py::SingleAgentRuntime",
|
|
93
|
+
"latticeai/core/agent.py::AgentRuntime = SingleAgentRuntime",
|
|
94
|
+
"lattice_brain/runtime/contracts.py::runtime-boundary/v1",
|
|
95
|
+
"lattice_brain/runtime/contracts.py::RuntimeBoundaryProtocol",
|
|
96
|
+
"lattice_brain/runtime/agent_runtime.py::def boundary",
|
|
97
|
+
"latticeai/core/agent.py::def boundary",
|
|
98
|
+
"latticeai/services/tool_dispatch.py::rollback_file",
|
|
92
99
|
],
|
|
93
100
|
),
|
|
94
101
|
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,
|
|
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
|
-
) ->
|
|
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
|
|
223
|
+
return SingleAgentRuntime(deps)
|
|
212
224
|
|
|
213
225
|
|
|
214
226
|
def tool_response(fn, *args):
|
package/package.json
CHANGED
package/src-tauri/Cargo.lock
CHANGED
package/src-tauri/Cargo.toml
CHANGED