Merge remote-tracking branch 'origin/master' into worktree/preset-plane-fallout-p1

Only `docs/module-graph.*` conflicted; generated, so taken from master and
regenerated. `api-proxy.ts` auto-merged — this branch's history read
(`historySourceFor` / `presenterScopeFor` / `historyCutOf`, in that order)
is intact.

Hook bypassed as before: the staged-pairing check hands an archived note path
to `verify-translation-pairing`. The full-corpus gate passes.
This commit is contained in:
Yichen Jiang
2026-08-11 14:32:59 +08:00
56 changed files with 1730 additions and 77 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/config-catalog.md
config-catalog.md: a00005d0c9e802b4973a0046d9e0ceed2b58d07f
config-catalog.md: fbd88a9137e61f97209f2f136f46a95806da399d
config-catalog.zh.md: 8794093955984c7c12dabeed742a4717c16741a5

View File

@@ -1430,7 +1430,7 @@ export interface Config {
export type JsonlCompression = 'zstd' | 'none'
```
Source: [`packages/session/session-persistence-jsonl/src/index.ts:59`](../packages/session/session-persistence-jsonl/src/index.ts)
Source: [`packages/session/session-persistence-jsonl/src/index.ts:60`](../packages/session/session-persistence-jsonl/src/index.ts)
## `@deepseek-ai/dsh-session-persistence-sqlite`

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/module-graph.md
module-graph.md: 430b8ee4dbc27a592d626612158081241be97495
module-graph.zh.md: 4c79e784974bd2b56a6152cc55fac75faa2314fa
module-graph.md: 84fcd63100fb16a0ac26bc8f2f33fdd65bcf4e91
module-graph.zh.md: 7aa6a57be53fbc74ed3017dd9d06400f176b99a6

View File

@@ -904,6 +904,7 @@ flowchart TD
pkg_client_test_runtime --> pkg_host_apiproxy
pkg_client_test_runtime --> pkg_invariants
pkg_client_ui_trajectory --> pkg_agent
pkg_client_ui_trajectory --> pkg_client_locale
pkg_client_ui_trajectory --> pkg_client_runtime
pkg_client_ui_trajectory --> pkg_client_ui_primitives
pkg_client_ui_trajectory --> pkg_compact
@@ -1423,7 +1424,7 @@ flowchart TD
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |

View File

@@ -906,6 +906,7 @@ flowchart TD
pkg_client_test_runtime --> pkg_host_apiproxy
pkg_client_test_runtime --> pkg_invariants
pkg_client_ui_trajectory --> pkg_agent
pkg_client_ui_trajectory --> pkg_client_locale
pkg_client_ui_trajectory --> pkg_client_runtime
pkg_client_ui_trajectory --> pkg_client_ui_primitives
pkg_client_ui_trajectory --> pkg_compact
@@ -1425,7 +1426,7 @@ flowchart TD
| [`agent-loop-testkit`](../packages/support/agent-loop-testkit) | `support` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`tools`](../packages/core/tools) |
| [`llm-replay`](../packages/support/llm-replay) | `support` | [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
| [`client-test-runtime`](../packages/client/test-runtime) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-slots`](../packages/client/ui-slots), [`client-web-react`](../packages/client/web-react), [`host-apiproxy`](../packages/host/apiproxy), [`invariants`](../packages/support/invariants) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
| [`client-ui-trajectory`](../packages/client/ui-trajectory) | `client` | [`agent`](../packages/core/agent), [`client-locale`](../packages/client/locale), [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |
| [`session-reference`](../packages/context/session-reference) | `context` | [`agent`](../packages/core/agent), [`compact`](../packages/compact/compact), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`retention`](../packages/util/retention), [`session`](../packages/core/session), [`session-query`](../packages/session-query/session-query) |
| [`workspace-context`](../packages/context/workspace-context) | `context` | [`agent`](../packages/core/agent), [`fs`](../packages/fs/fs), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`paths`](../packages/util/paths), [`session`](../packages/core/session), [`tools`](../packages/core/tools) |
| [`repeat-tool-guard`](../packages/guard/repeat-tool-guard) | `guard` | [`agent`](../packages/core/agent), [`invariants`](../packages/support/invariants), [`tools`](../packages/core/tools) |

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/subsystems/persistence.md
persistence.md: 7deaa9b30b5a6b1e3cbdcc38255b3974b5abf477
persistence.zh.md: c5afcf67319da408b739d41b2b7ad3eb434ffbad
persistence.md: fd694161ed8ae4c364de5c22d8eb06f1b0a91aec
persistence.zh.md: b616b282204e946e18e90271d1eaeb2d4ed70fc3

View File

@@ -122,6 +122,22 @@ interface CreateSessionOptions {
Replay/fork is therefore `ctx.sessions.create(id, { seed: seedEvents })`; resuming a *persisted* session into a live agent is `ctx.agents.resume({ resumeSessionId })`.
## `SessionRawArtifact` — verbatim stored artifact text
A backend's own artifact text for one session, byte-identical to what it durably wrote (decoded from its physical encoding). `readRaw` returns it without reconstructing from parsed events, so backend-specific serialization (chunk packing, key order, line breaks) survives; backends without a per-session artifact, such as SQLite, inherit the `undefined` default.
```ts type-equiv
/** A backend's own raw artifact text for one session, verbatim. */
interface SessionRawArtifact {
/** The session header parsed from the artifact's own first line. */
readonly meta: SessionHeader
/** The artifact's base filename on disk, without any physical encoding suffix. */
readonly filename: string
/** The artifact's full text content, decoded from the backend's physical encoding. */
readonly content: string
}
```
## Preparation and restoration ownership
`SessionStore.prepare()` accepts ordinary creation options or fresh persistence graphs transferred through `RestoredSessionOptions`. The restoration branch validates and freezes the transferred header and events in place, so callers must retain no mutable aliases. `SessionPreparation` then owns the exact unpublished Session until publication or rollback; disposal is synchronous and idempotent. Persistence inspection exposes only `SessionInspection`, an immutable logical view borrowed from the same prepared Session.
@@ -241,6 +257,21 @@ Durable append-only session storage. Implementations preserve contiguous, lossle
*/
abstract locate(meta: SessionHeader): SessionLocation | undefined
/**
* Read a session's backend-owned artifact text verbatim — the exact durable
* bytes the backend wrote (decoded from its physical encoding, e.g. a
* decompressed JSONL). The returned `content` is the raw text, not a
* reconstruction from parsed events, so it preserves backend-specific
* serialization (chunk packing, key order, line breaks). Backends without a
* per-session artifact (SQLite) inherit the `undefined` default.
* @param _id - the persisted session to read (unused by the default: no
* per-session artifact).
* @param signal - optional cancellation for backend read work.
* @returns the raw artifact plus its parsed header, or `undefined` when the
* session is absent or the backend owns no per-session artifact.
*/
readRaw(_id: SessionId, signal?: AbortSignal): Promise<SessionRawArtifact | undefined>
/**
* Register a new session's metadata. A backend MAY defer the physical write
* until the first {@link append} (lazy materialization), in which case a
@@ -346,5 +377,5 @@ abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot
Types: [SessionEvent](session.md) · [SessionId](core.md)
Source: [`packages/session/session-persistence/src/index.ts:74`](../../packages/session/session-persistence/src/index.ts)
Source: [`packages/session/session-persistence/src/index.ts:84`](../../packages/session/session-persistence/src/index.ts)
<!-- END GENERATED cordis-surface -->

View File

@@ -122,6 +122,22 @@ interface CreateSessionOptions {
因此,回放/fork 的调用方式为 `ctx.sessions.create(id, { seed: seedEvents })`;将一个*持久化*会话恢复为活跃 agent 的调用方式为 `ctx.agents.resume({ resumeSessionId })`。
## `SessionRawArtifact`——逐字存储工件文本
后端为单个会话自持的工件文本,与其持久化写入的字节逐字一致(按物理编码解码)。`readRaw` 返回它而不从解析后事件重建因此后端特定的序列化chunk 打包、键序、换行)得以保留;没有每会话工件的后端(如 SQLite继承 `undefined` 默认。
```ts type-equiv
/** A backend's own raw artifact text for one session, verbatim. */
interface SessionRawArtifact {
/** The session header parsed from the artifact's own first line. */
readonly meta: SessionHeader
/** The artifact's base filename on disk, without any physical encoding suffix. */
readonly filename: string
/** The artifact's full text content, decoded from the backend's physical encoding. */
readonly content: string
}
```
## 准备与恢复所有权
`SessionStore.prepare()` 接收普通创建选项,或通过 `RestoredSessionOptions` 转移所有权的新鲜持久化对象图。恢复分支会直接验证并冻结转移来的 header 与事件,因此调用方不得保留可变别名。`SessionPreparation` 随后持有该精确的未发布 Session直至发布或回滚dispose 是同步且幂等的。持久化检查只暴露 `SessionInspection`,即从同一个已准备 Session 借用的不可变逻辑视图。
@@ -241,6 +257,21 @@ Durable append-only session storage. Implementations preserve contiguous, lossle
*/
abstract locate(meta: SessionHeader): SessionLocation | undefined
/**
* Read a session's backend-owned artifact text verbatim — the exact durable
* bytes the backend wrote (decoded from its physical encoding, e.g. a
* decompressed JSONL). The returned `content` is the raw text, not a
* reconstruction from parsed events, so it preserves backend-specific
* serialization (chunk packing, key order, line breaks). Backends without a
* per-session artifact (SQLite) inherit the `undefined` default.
* @param _id - the persisted session to read (unused by the default: no
* per-session artifact).
* @param signal - optional cancellation for backend read work.
* @returns the raw artifact plus its parsed header, or `undefined` when the
* session is absent or the backend owns no per-session artifact.
*/
readRaw(_id: SessionId, signal?: AbortSignal): Promise<SessionRawArtifact | undefined>
/**
* Register a new session's metadata. A backend MAY defer the physical write
* until the first {@link append} (lazy materialization), in which case a
@@ -346,5 +377,5 @@ abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot
Types: [SessionEvent](session.md) · [SessionId](core.md)
Source: [`packages/session/session-persistence/src/index.ts:74`](../../packages/session/session-persistence/src/index.ts)
Source: [`packages/session/session-persistence/src/index.ts:84`](../../packages/session/session-persistence/src/index.ts)
<!-- END GENERATED cordis-surface -->