Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1d9b87a
docs(tape): specify layering refactor
yyhhyyyyyy Jul 17, 2026
e4eeefc
test(tape): split behavior contracts
yyhhyyyyyy Jul 17, 2026
bf9786c
refactor(tape): establish domain ports
yyhhyyyyyy Jul 17, 2026
2ee6d21
refactor(tape): split application services
yyhhyyyyyy Jul 17, 2026
efab784
refactor(tape): close storage bypasses
yyhhyyyyyy Jul 17, 2026
afc61a5
test(tape): enforce layer boundaries
yyhhyyyyyy Jul 17, 2026
42f80e9
test(tape): align writer mock naming
yyhhyyyyyy Jul 17, 2026
4e69cef
docs(tape): refresh architecture map
yyhhyyyyyy Jul 17, 2026
1d71e9c
fix(tape): make generation resets atomic
yyhhyyyyyy Jul 17, 2026
292c2be
refactor(tape): narrow consumer ports
yyhhyyyyyy Jul 17, 2026
8a8bfe0
refactor(tape): align service ownership
yyhhyyyyyy Jul 17, 2026
0a6d11a
test(tape): harden layer boundaries
yyhhyyyyyy Jul 17, 2026
9d85ebb
test(tape): guard semantics compatibility path
yyhhyyyyyy Jul 17, 2026
6102610
test(tape): guard project sqlite driver
yyhhyyyyyy Jul 17, 2026
12edd0b
fix(tape): invalidate legacy projections
yyhhyyyyyy Jul 17, 2026
922bbed
refactor(tape): require capability injection
yyhhyyyyyy Jul 17, 2026
468e36a
refactor(tape): narrow anchor reader port
yyhhyyyyyy Jul 17, 2026
ae52a06
refactor(tape): narrow storage protocols
yyhhyyyyyy Jul 17, 2026
4fbf219
docs(tape): clarify layer contracts
yyhhyyyyyy Jul 17, 2026
38902ef
docs(tape): specify follow-up hardening
yyhhyyyyyy Jul 17, 2026
10604a3
test(memory): restore native tape scope
yyhhyyyyyy Jul 17, 2026
52e0c48
test(tape): restore layered settings fixture
yyhhyyyyyy Jul 17, 2026
c696907
fix(tape): harden generation cleanup
yyhhyyyyyy Jul 17, 2026
16274f7
refactor(tape): harden compatibility boundaries
yyhhyyyyyy Jul 17, 2026
df1cd3a
test(tape): repair memory type contracts
yyhhyyyyyy Jul 17, 2026
13a8678
docs(tape): finalize hardening record
yyhhyyyyyy Jul 17, 2026
a25ff46
fix(tape): validate durable link identities
yyhhyyyyyy Jul 17, 2026
756ec81
fix(tape): harden derived state recovery
yyhhyyyyyy Jul 17, 2026
a0470d5
test(tape): align boundary fixtures
yyhhyyyyyy Jul 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/FLOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ Provider、Tool、Skill、Memory 和 Session data 都通过创建时传入的必
不会伪造新的 outer round。
- Memory prompt contribution 必须等待结果、清理内容、限制大小并允许失败;terminal extraction 在后台
执行,并保持 epoch、cursor 和 fence 约束。
- `TapeRecorder.appendToolFact` 在 message projection 完成后写 terminal tool call/result;写入失败不影响
当前回复完成
- `TapeToolFactWriter.appendToolFact` 在 message projection 完成后写 terminal tool call/result;
写入失败不影响当前回复完成

## 4. ACP 执行

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"schemaVersion": 2,
"goal": "agent-system-layered-runtime",
"headCommit": "d87cb4f69dca7af499e153d9a1d71015e1bfad60",
"headCommit": "df1cd3ae5b19d78e6c3cab79cdc9e4c5938fb2d4",
"relevantWorkingTree": {
"dirty": false,
"files": []
Expand Down Expand Up @@ -127,11 +127,12 @@
"src/main/agent/shared/storage/sessionPaths.ts",
"src/main/provider/providers/acpProvider.ts",
"src/main/session/assignment.ts",
"src/main/session/data/tape.ts",
"src/main/session/data/transcript.ts",
"src/main/session/lifecycle.ts",
"src/main/session/query.ts",
"src/main/session/turn.ts"
"src/main/session/turn.ts",
"src/main/tape/application/sessionTape.ts",
"src/main/tape/ports/capabilities.ts"
],
"expectedFiles": {
"src/main/agent/acp/instance/acpAgentInstance.ts": true,
Expand All @@ -155,11 +156,12 @@
"src/main/agent/shared/appSessionService.ts": true,
"src/main/provider/providers/acpProvider.ts": true,
"src/main/session/assignment.ts": true,
"src/main/session/data/tape.ts": true,
"src/main/session/data/transcript.ts": true,
"src/main/session/lifecycle.ts": true,
"src/main/session/query.ts": true,
"src/main/session/turn.ts": true
"src/main/session/turn.ts": true,
"src/main/tape/application/sessionTape.ts": true,
"src/main/tape/ports/capabilities.ts": true
},
"ownerEvidence": {
"agentManager": {
Expand Down Expand Up @@ -192,8 +194,8 @@
"exists": true,
"declarationCount": 1
},
"tapeRecorder": {
"file": "src/main/agent/deepchat/loop/ports.ts",
"tapeToolFactWriter": {
"file": "src/main/tape/ports/capabilities.ts",
"exists": true,
"declarationCount": 1
},
Expand Down Expand Up @@ -297,11 +299,12 @@
"src/main/agent/deepchat/runtime/process.ts",
"src/main/provider/providers/acpProvider.ts",
"src/main/session/assignment.ts",
"src/main/session/data/tape.ts",
"src/main/session/data/transcript.ts",
"src/main/session/lifecycle.ts",
"src/main/session/query.ts",
"src/main/session/turn.ts"
"src/main/session/turn.ts",
"src/main/tape/application/sessionTape.ts",
"src/main/tape/ports/capabilities.ts"
]
},
"contracts": {
Expand Down Expand Up @@ -366,7 +369,7 @@
"src/shared/contracts/routes/window.routes.ts",
"src/shared/contracts/routes/workspace.routes.ts"
],
"sha256": "406ef501353454e8677f773c556b8938141d931229eebabae6fcb9b0c37abe3c"
"sha256": "e624008521f11befaa0497a325cb65b4bf38f36e575dd4285622ad3705955b9e"
},
"storage": {
"sqlite": {
Expand All @@ -376,7 +379,7 @@
"src/main/data/schemaTypes.ts"
],
"tableIdentifiers": [],
"sha256": "411d0c6078cf4264f2241e1198315e52dcf085342975d344e5d8967333b8129b"
"sha256": "3465d92dff615489b7037de640077ce95bda7a7abbb0144ce84bb144dcd85a9e"
},
"memoryDuckDbSidecar": {
"files": [
Expand All @@ -396,7 +399,7 @@
"src/main/app/mainProcess.ts",
"src/main/appMain.ts"
],
"sha256": "dc13adbe8b76f0c4bb463605c780fc83e4a78696b8875d6765e767a4c2dcf70f"
"sha256": "394cd861f9fe06a29159d06f87f83b7ba1866287f129fae2a42a382e7e2e6c95"
},
"dependencyMetrics": {
"loopFiles": [
Expand Down
25 changes: 24 additions & 1 deletion docs/architecture/memory-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ flowchart LR
epoch、cursor 和 fence。
- Session 保存 Memory cursor/settings,不拥有 Memory row 或 vector store。
- App 负责 shutdown/database maintenance 时的全局 fence 和停止顺序,不解释 Memory 业务状态。
- Memory runtime 通过 `TapeRawEntryReader` 和 `TapeAnchorWriter` 读取执行事实、记录
`memory/view_assembled` 与 `memory/extract` anchor;Memory routes 只通过 `TapeInspectionReader`
获取 effective source span 和 manifest DTO,不接收 Tape table 或 raw Tape row。

## 数据与状态

Expand Down Expand Up @@ -61,6 +64,8 @@ Vector store v2 使用 `<agentId>.v2.duckdb`、plain `FLOAT[]` table 和 exact s

```text
terminal turn projection
-> read bounded ingestion projection range
-> rebuild from effective Tape or fall back when projection is stale/unavailable
-> collect bounded text chunks
-> extraction / reflection
-> normalize candidates
Expand All @@ -76,6 +81,23 @@ terminal turn projection
- stale result、partial batch 和 provider cancellation 有明确 terminal outcome;
- vector store 异常进入 typed error/quarantine,不得把消息发送永久挂起。

## Tape 与 ingestion projection 边界

`DeepChatMemoryIngestionProjectionTable.readCurrentRange` 在一条只读 SQL 中同时观察 Tape head 和
projection head。这是明确的基础设施例外:拆成两次查询会让并发 append 产生 false-current 窗口。
除此之外 Memory 不得直接读取物理 Tape 表。

projection current 时只 materialize cursor 区间;head 不一致时,runtime 通过 `TapeRawEntryReader`
构建 effective Tape view 并重建 projection。projection 查询或重建失败时保留既有 Tape fallback 和
cursor commit 保护,不能因为拆层新增全历史 hot-path 查询,也不能在不完整 projection 上推进 cursor。

`TapeRawEntryReader` 只提供 `getBySession`。Memory management route 先验证 memory row 属于请求 Agent,
再用 `getEffectiveMessageSourceSpan` 读取 retraction/replacement 生效后的最小 message DTO;manifest
列表通过 `listMemoryViewManifestsByAgent` 在 storage query 中执行 Agent、Session、message 和 limit
过滤,route 不自行解析 `payload_json` 或 `meta_json`。架构守卫同时扫描 static import、dynamic
import、CommonJS require、type import 和 re-export,Memory route 不能绕过 inspection port 重新取得
raw reader、facade 或 domain helper。

## Privacy 与隔离

- 所有查询显式携带 Agent identity;不得依赖进程全局“当前 Agent”。
Expand All @@ -101,7 +123,8 @@ metric 名称、retrieval evaluation 和 artifact upload 的未完成工作保
5. `src/main/memory/infra/vectorStoreManager.ts`
6. `src/main/memory/infra/memoryVectorStore.ts`
7. `src/main/agent/deepchat/memory/memoryRuntimeCoordinator.ts`
8. `test/main/memory/`
8. `src/main/tape/ports/capabilities.ts`
9. `test/main/memory/`

Memory tests 必须防止旧 `src/main/presenter/memoryPresenter`、HNSW hot path、
无 Agent namespace 查询和无 deadline provider call 回流。
32 changes: 30 additions & 2 deletions docs/architecture/session-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ Session 是可长期保存的产品对象;window、renderer、Remote endpoint
| list、restore、status、projection query | `src/main/session/query.ts` |
| full delete transaction | `src/main/session/deletion.ts` |
| transcript | `src/main/session/data/transcript.ts` |
| Tape / ViewManifest | `src/main/session/data/tape*.ts` |
| Tape public port / composition | `src/main/session/data/index.ts` |
| Tape domain / application / SQLite adapters | `src/main/tape/` |
| generation settings / Memory cursor | `src/main/session/data/settings.ts` |
| pending input | `src/main/session/data/pendingInputs.ts` |
| renderer binding | `src/main/desktop/sessionBinding.ts` |
Expand Down Expand Up @@ -54,6 +55,33 @@ send input;Remote、Scheduler 和 renderer 不得各自维护不同的默认
- history search 优先使用 search document / FTS path,失败时回退受控 SQL search;坐标和 scroll
归 renderer viewport owner,不写回 Session。

## Tape boundary

Session data composition 创建一个 `SessionTape`,对外继续暴露现有 `SessionTapePort`,并按每个 IPC
操作原有的条件和时序调用 `ensureSessionTapeReady`。`src/main/session/data/tape*.ts` 和旧 table path
只是显式冻结并标记 deprecated 的 compatibility re-export,不再拥有 Tape policy 或 persistence。

- transcript 只接收 `TapeMessageFactWriter`;message replace/retract 与对应 Tape fact 继续共享调用方
SQLite transaction;
- settings/compaction 只接收 anchor reader/writer 与 lifecycle admin;summary 更新和 anchor append
继续使用同一个 connection;
- loop runner 分别接收 reconciliation、ViewManifest reader/writer 和 tool fact writer;Turn coordinator
与 ACP compatibility 只接收 reconciliation;Memory 和 routes 分别接收自己的最小 Tape capability,
不接收物理 table;
- Tape 的运行中修订通过 append 表达;物理 delete/reset 只由 Session lifecycle 触发。

`SessionTranscript` 和 `SessionSettingsStore` 不提供隐式 `new SessionTape(...)` fallback,必须由正常
composition 注入共享 connection 上的最小 capability。legacy import 作为 migration consumer 复用
`sessionData.tapeStore` 的 message fact writer,不再构造第二个 facade,避免隐藏的独立 writer 或事务
上下文。

`clearSessionMessages` 会创建新的 Tape incarnation:pending input 删除、transcript 删除和 Tape reset
位于同一个外层 SQLite transaction;Tape 内部的 entry、mutation projection、search/FTS projection
删除和新 bootstrap 作为 savepoint 嵌套。lifecycle、cleanup 或 bootstrap hard failure 会同时恢复上述
数据并完整保留旧 incarnation。mutation projection 沿用 fail-open:新 bootstrap 的 projection apply
失败时旧 projection row 已删除且 meta 标 stale。最终 Session delete 不创建新 incarnation,继续遵循
下面的 staged cleanup 顺序。

## Binding

`DesktopSessionBinding` 维护 `webContentsId -> sessionId`:
Expand All @@ -70,7 +98,7 @@ send input;Remote、Scheduler 和 renderer 不得各自维护不同的默认
```text
cleanup both backend caches without hydration
-> remove ACP durable binding
-> remove transcript / Tape / pending / settings
-> remove transcript / Tape lifecycle data / pending / settings
-> clear permission and active Skill state
-> delete app-session row
```
Expand Down
Loading
Loading