refactor(storage): rename dsh-domain to dsh-storage-domain

The bare 'domain' name was too generic for a published package. The
directory moves to packages/storage/storage-domain, the package becomes
@deepseek-ai/dsh-storage-domain, and the plugin/invariant names follow;
the ctx surface (ctx.storage.domain), the domain/changed event, and all
runtime behavior are unchanged. References, catalogs, graphs, and the
bilingual design note move together.
This commit is contained in:
imccyu
2026-07-25 11:08:04 +08:00
parent 71923d7213
commit f5506cf35f
34 files changed
+86 -86

No files matched your search

@@ -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
2026-07-24-domain-kv-storage-and-workspace.md: f6b74b656270f4791fd9369438235c7fc1b1edb8
2026-07-24-domain-kv-storage-and-workspace.zh.md: f6649fc0c387d9c1240d45efda4b4a0ab9372486
2026-07-24-domain-kv-storage-and-workspace.md: cd666a47a3cba4dea8846cd0f1373224e6fc456f
2026-07-24-domain-kv-storage-and-workspace.zh.md: 81adf1eb6bc32aa3ca8b9ef4c352fb94f95ace91
@@ -22,7 +22,7 @@ Create the `packages/storage/` group — the `ctx.storage` hub (backend registry
| `@deepseek-ai/dsh-storage` | `packages/storage/storage/` | `ctx.storage` (the hub) | ✓ |
| `@deepseek-ai/dsh-storage-json` | `packages/storage/storage-json/` | registers backend `json` | ✓ |
| `@deepseek-ai/dsh-storage-sqlite` | `packages/storage/storage-sqlite/` | registers backend `sqlite` | ✓ |
| `@deepseek-ai/dsh-domain` | `packages/storage/domain/` | mounts `ctx.storage.domain` | ✓ |
| `@deepseek-ai/dsh-storage-domain` | `packages/storage/storage-domain/` | mounts `ctx.storage.domain` | ✓ |
| `@deepseek-ai/dsh-workspace` | `packages/workspace/workspace/` | `ctx.workspace` | ✓ |
| `SessionPersistence.delete` extension + cascade orchestration | `packages/session-persistence/*` | new method on the existing seam | ✗ future work (session side untouched this phase) |
| `workspace.*` / `session.delete` RPC, GUI wiring, boot assembly | — | — | ✗ next phase |
@@ -157,7 +157,7 @@ Rules:
- **Records are plain data**: immutable, directly JSON-serializable POJOs; values returned by `get`/`entries` must not be mutated in place (TypeScript readonly projection, no runtime freezing). Behavior-carrying domain objects belong to consumer packages.
- **Serialized writes**: one promise chain per domain; `put`/`delete`/`update`/`global.set` all queue on it; `update`'s fn runs on the chain, so concurrency cannot interleave. No active-record (pulling out a mutable object that auto-persists — uncontrollable persist timing, in conflict with the whole-unit atomic-rewrite model).
- **Version fails loud**: a stored version differing from the spec throws outright; no migration, no rebuild (the data is not regenerable; pre-release rejects old formats).
- **Change events**: after each write's durability resolves, emit `domain/changed` (`@mode emit`), one per record, no old value (matching the repository's "new snapshot + operation discriminant" convention, template `goal/changed`); the payload `DomainChanged` is a put/deleted discriminated union — domain + table + key (both `''` for global changes) + operation, with the put branch carrying the new snapshot value and the deleted branch carrying none (`packages/storage/domain/src/events.ts`). This is next phase's RPC push-frame event source. The error vocabulary is `DomainError`, codes: `already-open` / `facet-unsupported` / `invalid-record` (with `{ table, key }`) / `missing-key` / `closed`.
- **Change events**: after each write's durability resolves, emit `domain/changed` (`@mode emit`), one per record, no old value (matching the repository's "new snapshot + operation discriminant" convention, template `goal/changed`); the payload `DomainChanged` is a put/deleted discriminated union — domain + table + key (both `''` for global changes) + operation, with the put branch carrying the new snapshot value and the deleted branch carrying none (`packages/storage/storage-domain/src/events.ts`). This is next phase's RPC push-frame event source. The error vocabulary is `DomainError`, codes: `already-open` / `facet-unsupported` / `invalid-record` (with `{ table, key }`) / `missing-key` / `closed`.
### Future work: session-side deletion (design settled, not implemented this phase)
@@ -22,7 +22,7 @@ host 侧唯一的持久化面是 session 事件日志(`packages/session-persis
| `@deepseek-ai/dsh-storage` | `packages/storage/storage/` | `ctx.storage`(枢纽) | ✓ |
| `@deepseek-ai/dsh-storage-json` | `packages/storage/storage-json/` | 注册 backend `json` | ✓ |
| `@deepseek-ai/dsh-storage-sqlite` | `packages/storage/storage-sqlite/` | 注册 backend `sqlite` | ✓ |
| `@deepseek-ai/dsh-domain` | `packages/storage/domain/` | 挂载 `ctx.storage.domain` | ✓ |
| `@deepseek-ai/dsh-storage-domain` | `packages/storage/storage-domain/` | 挂载 `ctx.storage.domain` | ✓ |
| `@deepseek-ai/dsh-workspace` | `packages/workspace/workspace/` | `ctx.workspace` | ✓ |
| `SessionPersistence.delete` 扩面 + 级联删编排 | `packages/session-persistence/*` | 既有 seam 新方法 | ✗ future work(本期不动 session 侧) |
| `workspace.*` / `session.delete` RPC、GUI 接线、boot 组装 | — | — | ✗ 下期 |
@@ -157,7 +157,7 @@ export interface KvTable<K extends string, V> {
- **记录是纯数据**:可直接 JSON 序列化的不可变 POJO;`get`/`entries` 返回值不得原地改(TypeScript readonly 投影,不做运行时冻结)。带行为的领域对象属于消费者包。
- **写串行**:域内一条 promise 链,`put`/`delete`/`update`/`global.set` 全排队;`update` 的 fn 在链上执行,并发不交错。不做 active-record(取出可变对象自动落盘——落盘时机不可控,与整域原子覆写冲突)。
- **版本 fail loud**:盘上版本与 spec 不符直接报错,不迁移不重建(数据不可再生,pre-release 拒绝旧格式)。
- **变更事件**:每次写落盘 resolve 后 emit `domain/changed``@mode emit`),逐条发、不带旧值(对齐仓库"新快照 + 操作判别"惯例,范本 `goal/changed`);payload `DomainChanged` 是 put/deleted 判别联合——域名 + 表名 + key(global 变更两者为 `''`+ operationput 支带新快照 value、deleted 支无 value`packages/storage/domain/src/events.ts`)。此为下期 RPC 推帧的事件源。错误词汇 `DomainError`,码表:`already-open` / `facet-unsupported` / `invalid-record`(带 `{ table, key }`/ `missing-key` / `closed`。
- **变更事件**:每次写落盘 resolve 后 emit `domain/changed``@mode emit`),逐条发、不带旧值(对齐仓库"新快照 + 操作判别"惯例,范本 `goal/changed`);payload `DomainChanged` 是 put/deleted 判别联合——域名 + 表名 + key(global 变更两者为 `''`+ operationput 支带新快照 value、deleted 支无 value`packages/storage/storage-domain/src/events.ts`)。此为下期 RPC 推帧的事件源。错误词汇 `DomainError`,码表:`already-open` / `facet-unsupported` / `invalid-record`(带 `{ table, key }`/ `missing-key` / `closed`。
### Future worksession 侧删除(设计定案,本期不实施)
+3 -3
View File
@@ -40,7 +40,7 @@ flowchart LR
svc_storage["ctx.storage<br/>Non-session storage hub"]
pkg_storage_json["storage-json"]
pkg_storage_sqlite["storage-sqlite"]
pkg_domain["domain"]
pkg_storage_domain["storage-domain"]
pkg_workspace["workspace"]
svc_workspace["ctx.workspace<br/>Workspace entity registry"]
svc_sessionQuery["ctx.sessionQuery<br/>Session reads, traces, filters, and search"]
@@ -246,7 +246,7 @@ flowchart LR
svc_sessions --> pkg_subagent_inprocess
svc_skills --> pkg_tool_skill
svc_spillStore --> pkg_spill_policy
svc_storage --> pkg_domain
svc_storage --> pkg_storage_domain
svc_storage --> pkg_workspace
svc_subagents --> pkg_tool_ralph
svc_subagents --> pkg_tool_subagent
@@ -289,7 +289,7 @@ flowchart LR
| `ctx.sessions` | `core` | [`session`](../packages/core/session) | - | [`agent-loop`](../packages/core/agent-loop), [`agent`](../packages/core/agent), [`cli-demo`](../packages/examples/cli-demo), [`session-persistence`](../packages/session-persistence/session-persistence), [`session-query`](../packages/session-query/session-query), [`session-query-sqlite`](../packages/session-query/session-query-sqlite), [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`invariants`](../packages/support/invariants) | - | Owns append-only Session instances and emits the durable session event feed. |
| `ctx.invariants` | `core` | [`invariants`](../packages/support/invariants) | - | [`session`](../packages/core/session), [`agent`](../packages/core/agent), [`scope`](../packages/core/scope), [`agent-loop`](../packages/core/agent-loop) | - | Companion subpaths register owner-local checks; the service owns selection, uniqueness, child fibers, and package-attributed failures. |
| `ctx.sessionPersistence` | `seam` | [`session-persistence`](../packages/session-persistence/session-persistence) | [`session-persistence-jsonl`](../packages/session-persistence/session-persistence-jsonl), [`session-persistence-sqlite`](../packages/session-persistence/session-persistence-sqlite) | [`agent-loop`](../packages/core/agent-loop), [`tool-bash`](../packages/bash/tool-bash), [`hooks-claude`](../packages/hooks/hooks-claude), [`hooks-codex`](../packages/hooks/hooks-codex), [`acp`](../packages/ui/acp), [`session-query`](../packages/session-query/session-query), [`session-query-sqlite`](../packages/session-query/session-query-sqlite) | - | Backends persist the same SessionEvent vocabulary; apps choose a backend at composition time. |
| `ctx.storage` | `seam` | [`storage`](../packages/storage/storage) | [`storage-json`](../packages/storage/storage-json), [`storage-sqlite`](../packages/storage/storage-sqlite) | [`domain`](../packages/storage/domain), [`workspace`](../packages/workspace/workspace) | - | Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives. |
| `ctx.storage` | `seam` | [`storage`](../packages/storage/storage) | [`storage-json`](../packages/storage/storage-json), [`storage-sqlite`](../packages/storage/storage-sqlite) | [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) | - | Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives. |
| `ctx.workspace` | `core` | [`workspace`](../packages/workspace/workspace) | - | - | - | Owns WorkspaceId-branded records over the domain form; sessionIds is the single source of ownership truth. RPC and GUI consumers arrive next phase. |
| `ctx.sessionQuery` | `seam` | [`session-query`](../packages/session-query/session-query) | [`session-query-sqlite`](../packages/session-query/session-query-sqlite) | [`session-reference`](../packages/context/session-reference) | - | The interface supplies exact reads, filters, and traces; its concrete backend adds full-text reconciliation, ranking, snippets, and cursor generations on the same service. |
| `ctx.sessionReferences` | `core` | [`session-reference`](../packages/context/session-reference) | - | [`tui`](../packages/ui/tui), [`acp`](../packages/ui/acp) | - | Projects bounded current-surface conversation snapshots into durable untrusted message context; host adapters own mention syntax. |
+21 -21
View File
@@ -369,27 +369,6 @@ export interface ToolResultPruneConfig {
Source: [`packages/compact/compact-tool-result-prune/src/types.ts:4`](../packages/compact/compact-tool-result-prune/src/types.ts)
## `@deepseek-ai/dsh-domain`
Requires: `storage`
```ts config-catalog
/**
* Plugin config. Which backend serves which domain is decided here, not
* globally on the hub: `backend` is the default route and `routes` overrides
* it per domain name. A route naming an unregistered backend fails loud at
* `open` with `backend-not-found`.
*/
export interface Config {
/** Default backend name for every domain without an explicit route. Required: there is no universally correct medium. */
backend: string
/** Per-domain overrides: domain name → backend name. */
routes?: Record<string, string>
}
```
Source: [`packages/storage/domain/src/index.ts:45`](../packages/storage/domain/src/index.ts)
## `@deepseek-ai/dsh-fs-local`
```ts config-catalog
@@ -1176,6 +1155,27 @@ export interface Config {
Source: [`packages/spill/spill-policy/src/index.ts:51`](../packages/spill/spill-policy/src/index.ts)
## `@deepseek-ai/dsh-storage-domain`
Requires: `storage`
```ts config-catalog
/**
* Plugin config. Which backend serves which domain is decided here, not
* globally on the hub: `backend` is the default route and `routes` overrides
* it per domain name. A route naming an unregistered backend fails loud at
* `open` with `backend-not-found`.
*/
export interface Config {
/** Default backend name for every domain without an explicit route. Required: there is no universally correct medium. */
backend: string
/** Per-domain overrides: domain name → backend name. */
routes?: Record<string, string>
}
```
Source: [`packages/storage/storage-domain/src/index.ts:45`](../packages/storage/storage-domain/src/index.ts)
## `@deepseek-ai/dsh-storage-json`
Requires: `storage`
+1 -1
View File
@@ -507,7 +507,7 @@ A domain record or the global singleton changed, emitted once per write strictly
'domain/changed'(change: DomainChanged): void
```
Source: [`packages/storage/domain/src/events.ts:46`](../../packages/storage/domain/src/events.ts)
Source: [`packages/storage/storage-domain/src/events.ts:46`](../../packages/storage/storage-domain/src/events.ts)
## `fs/*`
+1 -1
View File
@@ -28,7 +28,7 @@ This matrix shows which packages dispatch each harness-owned event and which pac
| `agent/turn-stop` | `serial` | [`packages/core/agent/src/types.ts:485`](../packages/core/agent/src/types.ts) | [`agent-loop`](../packages/core/agent-loop) (`serial`) | [`subagent-inprocess`](../packages/subagent/subagent-inprocess), [`tool-goal`](../packages/goal/tool-goal) |
| `approval/request` | `waterfall` | [`packages/ui/user-approval/src/index.ts:30`](../packages/ui/user-approval/src/index.ts) | [`user-approval`](../packages/ui/user-approval) (`waterfall`) | [`acp`](../packages/ui/acp) |
| `commands/change` | `emit` | [`packages/ui/commands/src/index.ts:103`](../packages/ui/commands/src/index.ts) | [`commands`](../packages/ui/commands) (`events.dispatch`) | [`acp`](../packages/ui/acp), [`tui`](../packages/ui/tui) |
| `domain/changed` | `emit` | [`packages/storage/domain/src/events.ts:46`](../packages/storage/domain/src/events.ts) | [`domain`](../packages/storage/domain) (`emit`) | [`domain`](../packages/storage/domain), [`workspace`](../packages/workspace/workspace) |
| `domain/changed` | `emit` | [`packages/storage/storage-domain/src/events.ts:46`](../packages/storage/storage-domain/src/events.ts) | [`storage-domain`](../packages/storage/storage-domain) (`emit`) | [`storage-domain`](../packages/storage/storage-domain), [`workspace`](../packages/workspace/workspace) |
| `fs/edit-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:62`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/observed` | `emit` | [`packages/fs/fs/src/index.ts:71`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`emit`) | [`fs-policy`](../packages/fs/fs-policy) |
| `fs/write-intent` | `waterfall` | [`packages/fs/fs/src/index.ts:54`](../packages/fs/fs/src/index.ts) | [`tool-fs`](../packages/fs/tool-fs) (`waterfall`) | [`fs-policy`](../packages/fs/fs-policy) |
+6 -6
View File
@@ -196,8 +196,8 @@ flowchart TD
pkg_telemetry["telemetry"]
end
subgraph group_storage["packages/storage"]
pkg_domain["domain"]
pkg_storage["storage"]
pkg_storage_domain["storage-domain"]
pkg_storage_json["storage-json"]
pkg_storage_sqlite["storage-sqlite"]
end
@@ -260,8 +260,8 @@ flowchart TD
pkg_telemetry --> pkg_brand
pkg_telemetry --> pkg_invariants
pkg_telemetry --> pkg_paths
pkg_domain --> pkg_invariants
pkg_domain --> pkg_storage
pkg_storage_domain --> pkg_invariants
pkg_storage_domain --> pkg_storage
pkg_storage_json --> pkg_invariants
pkg_storage_json --> pkg_storage
pkg_storage_sqlite --> pkg_invariants
@@ -430,11 +430,11 @@ flowchart TD
pkg_workflow --> pkg_llm
pkg_workflow --> pkg_session
pkg_workspace --> pkg_brand
pkg_workspace --> pkg_domain
pkg_workspace --> pkg_invariants
pkg_workspace --> pkg_session
pkg_workspace --> pkg_session_persistence
pkg_workspace --> pkg_storage
pkg_workspace --> pkg_storage_domain
pkg_tools --> pkg_agent
pkg_tools --> pkg_code_runtime
pkg_tools --> pkg_invariants
@@ -835,7 +835,7 @@ flowchart TD
| [`client-ui-sidebar`](../packages/client/ui-sidebar) | `client` | [`client-runtime`](../packages/client/runtime), [`client-ui-primitives`](../packages/client/ui-primitives), [`client-ui-slots`](../packages/client/ui-slots), [`invariants`](../packages/support/invariants) |
| [`helper`](../packages/sdk/helper) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants) |
| [`telemetry`](../packages/sdk/telemetry) | `sdk` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`paths`](../packages/util/paths) |
| [`domain`](../packages/storage/domain) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
| [`storage-domain`](../packages/storage/storage-domain) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
| [`storage-json`](../packages/storage/storage-json) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
| [`storage-sqlite`](../packages/storage/storage-sqlite) | `storage` | [`invariants`](../packages/support/invariants), [`storage`](../packages/storage/storage) |
| [`llm-deepseek`](../packages/llm/llm-deepseek) | `llm` | [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`timeout`](../packages/util/timeout) |
@@ -885,7 +885,7 @@ flowchart TD
| [`scripts`](../packages/sdk/scripts) | `sdk` | [`app-boot`](../packages/ui/app-boot), [`invariants`](../packages/support/invariants) |
| [`tasks`](../packages/tasks/tasks) | `tasks` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`timeout`](../packages/util/timeout) |
| [`workflow`](../packages/workflow/workflow) | `workflow` | [`agent`](../packages/core/agent), [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
| [`workspace`](../packages/workspace/workspace) | `workspace` | [`brand`](../packages/util/brand), [`domain`](../packages/storage/domain), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`storage`](../packages/storage/storage) |
| [`workspace`](../packages/workspace/workspace) | `workspace` | [`brand`](../packages/util/brand), [`invariants`](../packages/support/invariants), [`session`](../packages/core/session), [`session-persistence`](../packages/session-persistence/session-persistence), [`storage`](../packages/storage/storage), [`storage-domain`](../packages/storage/storage-domain) |
| [`tools`](../packages/core/tools) | `core` | [`agent`](../packages/core/agent), [`code-runtime`](../packages/code-runtime/code-runtime), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`scope`](../packages/core/scope), [`session`](../packages/core/session), [`system-prompt`](../packages/core/system-prompt), [`user-approval`](../packages/ui/user-approval) |
| [`command-goal`](../packages/goal/command-goal) | `goal` | [`commands`](../packages/ui/commands), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants) |
| [`goal-session`](../packages/goal/goal-session) | `goal` | [`agent`](../packages/core/agent), [`goal`](../packages/goal/goal), [`invariants`](../packages/support/invariants), [`llm`](../packages/llm/llm), [`session`](../packages/core/session) |
@@ -10,7 +10,7 @@ packages/storage/
storage/ dsh-storage 枢纽:Storage service + BackendRegistry + StorageForms
storage-json/ dsh-storage-json JsonStorageBackendkv facet
storage-sqlite/ dsh-storage-sqlite SqliteStorageBackendkv facet
domain/ dsh-domain DomainFacility + Domain + KvTable + domain/changed
storage-domain/ dsh-storage-domain DomainFacility + Domain + KvTable + domain/changed
packages/workspace/
workspace/ dsh-workspace WorkspaceRegistry + WorkspaceEntity + workspaceDomainSpec
```
@@ -56,7 +56,7 @@ class/接口逐条(签名以 Note 为准,此处列实现要点):
| `const UNIT_NAME_RE = /^[a-z][a-z0-9_]*$/` | 导出;descriptor 校验用(backend open 时验,fail loud |
| invariant | 枢纽自身无运行时不变量(纯注册表,无事件流/可变盘面),写"explained empty"(措辞照抄 sqlite 后端 invariant.ts 的 "No runtime invariant:" 模板) |
事件面:本包**无**事件(`domain/changed` 归 dsh-domain)。
事件面:本包**无**事件(`domain/changed` 归 dsh-storage-domain)。
## 2. W2a`dsh-storage-json` —— teammate **json-backend**
@@ -99,10 +99,10 @@ packages/storage/storage-sqlite/
| `class SqliteKvUnit` | 预编译语句(每表 upsert/delete/select-all + global upsert);`loadAll` 全表 SELECT 组装;`putRecord` = `INSERT … ON CONFLICT(key) DO UPDATE`;单语句原子,无显式事务;value `JSON.stringify`/parse |
| invariant | 断言候选:STRICT 表 + user_version 与常量一致(open 后检);或 explained empty |
## 4. W3`dsh-domain` —— teammate **domain-layer**
## 4. W3`dsh-storage-domain` —— teammate **domain-layer**
```
packages/storage/domain/
packages/storage/storage-domain/
src/index.ts # Config + apply + DomainFacility
src/spec.ts # DomainSpec/defineDomain/domainTable + descriptorOf
src/domain.ts # DomainImpl + KvTableImpl + 写链
@@ -1,4 +1,4 @@
# @deepseek-ai/dsh-domain
# @deepseek-ai/dsh-storage-domain
Domain data form for the DeepSeek Harness storage hub: mounts `ctx.storage.domain`, opening schema-validated KV domains over configured storage backends. A domain is declared once with `defineDomain` (zod record schemas, `z.infer`-derived types), opened through `DomainFacility.open`, and served from authoritative in-memory state — reads are synchronous, writes serialize on one per-domain chain, reach durability on the routed backend first, then update memory and emit `domain/changed`. The opening consumer owns the handle's lifecycle and releases it with `Domain.close()` (idempotent; typically its own `ctx.effect` disposer); domains still open when the plugin unmounts are closed by the facility.
@@ -1,5 +1,5 @@
{
"name": "@deepseek-ai/dsh-domain",
"name": "@deepseek-ai/dsh-storage-domain",
"description": "Domain data form (ctx.storage.domain): schema-validated, event-emitting KV domains over storage backends for the DeepSeek Harness",
"version": "0.0.1",
"private": true,
@@ -6,7 +6,7 @@
* backend write leaves memory untouched (no divergence between reads and the
* medium), and events carry values that equal the in-memory state at
* emission, in write order.
* @module @deepseek-ai/dsh-domain/src/domain
* @module @deepseek-ai/dsh-storage-domain/src/domain
*/
import type { Context } from 'cordis'
@@ -1,6 +1,6 @@
/**
* Error vocabulary of the domain data form.
* @module @deepseek-ai/dsh-domain/src/error
* @module @deepseek-ai/dsh-storage-domain/src/error
*/
/** Discriminant codes carried by every {@link DomainError}. */
@@ -4,7 +4,7 @@
* and an operation discriminant never the old value (a diffing consumer
* keeps its own previous snapshot). This is the event source for cross-process
* change push (RPC frames) in a later phase.
* @module @deepseek-ai/dsh-domain/src/events
* @module @deepseek-ai/dsh-storage-domain/src/events
*/
/** Shared location fields of one durable domain change. */
@@ -4,7 +4,7 @@
* layer consumers depend on this package and never touch backends directly.
* Plugin `Config` is schemastery; record schemas inside domain specs are zod
* (see `src/spec.ts` for the split rationale).
* @module @deepseek-ai/dsh-domain
* @module @deepseek-ai/dsh-storage-domain
*/
import type { Context } from 'cordis'
@@ -32,7 +32,7 @@ declare module '@deepseek-ai/dsh-storage' {
}
/** Cordis plugin name. */
export const name = 'domain'
export const name = 'storage-domain'
/** The storage hub must be present before the form can mount. */
export const inject = ['storage']
@@ -1,22 +1,22 @@
/**
* Package-owned invariant companion for `@deepseek-ai/dsh-domain`: every
* Package-owned invariant companion for `@deepseek-ai/dsh-storage-domain`: every
* `domain/changed` event must agree with the emitting domain's authoritative
* in-memory state (the owned event-stream mutable-data relationship of this
* package). Writes emit strictly after mutating memory and the write chain
* serializes them, so at emission time the event's snapshot equals the
* current read any divergence means a write path skipped the chain or
* emitted a stale value.
* @module @deepseek-ai/dsh-domain/invariant
* @module @deepseek-ai/dsh-storage-domain/invariant
*/
import type { Context } from 'cordis'
import type { InvariantFailure, InvariantInstaller } from '@deepseek-ai/dsh-invariants'
import type { DomainChanged } from './events.ts'
const PACKAGE_NAME = '@deepseek-ai/dsh-domain'
const PACKAGE_NAME = '@deepseek-ai/dsh-storage-domain'
/** Cordis companion plugin name. */
export const name = 'domain-invariant'
export const name = 'storage-domain-invariant'
/** Service required before the companion can reserve package ownership. */
export const inject = ['invariants']
@@ -5,7 +5,7 @@
* (validation, descriptor projection) derive from it. Record schemas are zod
* (`z.infer` keeps types un-duplicated and the same schemas later project to
* RPC wire schemas); plugin `Config` stays schemastery.
* @module @deepseek-ai/dsh-domain/src/spec
* @module @deepseek-ai/dsh-storage-domain/src/spec
*/
import type { ZodType } from 'zod'
@@ -3,7 +3,7 @@ import { Context } from 'cordis'
import { z } from 'zod'
import Storage from '@deepseek-ai/dsh-storage'
import InvariantService, { InvariantError } from '@deepseek-ai/dsh-invariants'
import * as DomainInvariantCompanion from '@deepseek-ai/dsh-domain/invariant'
import * as DomainInvariantCompanion from '@deepseek-ai/dsh-storage-domain/invariant'
import { DomainFacility, defineDomain, domainTable } from '../src/index.ts'
import type { DomainChanged } from '../src/events.ts'
import { MemoryStorageBackend } from './helpers/memory-backend.ts'
@@ -31,7 +31,7 @@ async function setup() {
const invariantViolation: unknown = expect.objectContaining<Partial<InvariantError>>({
code: 'INVARIANT',
packageName: '@deepseek-ai/dsh-domain',
packageName: '@deepseek-ai/dsh-storage-domain',
})
describe('domain change-event invariants', () => {
+1 -1
View File
@@ -15,7 +15,7 @@ Storage hub (`ctx.storage`) for non-session data: a named backend registry plus
| `dsh-storage` | The hub service + backend vocabulary + shared conformance suite |
| `dsh-storage-json` | JSON backend: one unit per human-readable file, atomic whole-file rewrite |
| `dsh-storage-sqlite` | SQLite backend: one database hosting all routed units, document-per-row |
| `dsh-domain` | Domain data form (`ctx.storage.domain`): typed schemas, write chain, change events |
| `dsh-storage-domain` | Domain data form (`ctx.storage.domain`): typed schemas, write chain, change events |
## Model Experience
+2 -2
View File
@@ -28,7 +28,7 @@
"license": "BSD-3-Clause",
"peerDependencies": {
"@deepseek-ai/dsh-brand": "^0.0.1",
"@deepseek-ai/dsh-domain": "^0.0.1",
"@deepseek-ai/dsh-storage-domain": "^0.0.1",
"@deepseek-ai/dsh-invariants": "^0.0.1",
"@deepseek-ai/dsh-session": "^0.0.1",
"@deepseek-ai/dsh-session-persistence": "^0.0.1",
@@ -40,7 +40,7 @@
},
"devDependencies": {
"@deepseek-ai/dsh-brand": "workspace:^",
"@deepseek-ai/dsh-domain": "workspace:^",
"@deepseek-ai/dsh-storage-domain": "workspace:^",
"@deepseek-ai/dsh-invariants": "workspace:^",
"@deepseek-ai/dsh-session": "workspace:^",
"@deepseek-ai/dsh-session-persistence": "workspace:^",
+1 -1
View File
@@ -10,7 +10,7 @@
import { stat } from 'node:fs/promises'
import type { SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
import type { KvTable } from '@deepseek-ai/dsh-domain'
import type { KvTable } from '@deepseek-ai/dsh-storage-domain'
import type { WorkspaceRecord } from './spec.ts'
import type { Workspace, WorkspaceId } from './types.ts'
import { realpathNormalize } from './paths.ts'
+1 -1
View File
@@ -14,7 +14,7 @@ import type { SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
// Type-only: merges `sessionPersistence` into the Context service map for the
// optional `ctx.get` lookups below.
import type {} from '@deepseek-ai/dsh-session-persistence'
import type { KvTable } from '@deepseek-ai/dsh-domain'
import type { KvTable } from '@deepseek-ai/dsh-storage-domain'
import { workspaceDomainSpec } from './spec.ts'
import type { WorkspaceRecord } from './spec.ts'
import { WorkspaceEntity } from './entity.ts'
@@ -5,7 +5,7 @@
import type { Context } from 'cordis'
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
import type { DomainChanged } from '@deepseek-ai/dsh-domain'
import type { DomainChanged } from '@deepseek-ai/dsh-storage-domain'
import { WorkspaceId } from '@deepseek-ai/dsh-workspace'
const PACKAGE_NAME = '@deepseek-ai/dsh-workspace'
+1 -1
View File
@@ -7,7 +7,7 @@
import { z } from 'zod'
import { SessionId } from '@deepseek-ai/dsh-session'
import { defineDomain, domainTable } from '@deepseek-ai/dsh-domain'
import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'
import type { WorkspaceId } from './types.ts'
/**
@@ -1,7 +1,7 @@
import { describe, expect, it } from 'vitest'
import { Context } from 'cordis'
import InvariantService from '@deepseek-ai/dsh-invariants'
import type { DomainChanged } from '@deepseek-ai/dsh-domain'
import type { DomainChanged } from '@deepseek-ai/dsh-storage-domain'
import * as WorkspaceInvariant from '../src/invariant.ts'
import { WorkspaceId } from '../src/index.ts'
@@ -5,11 +5,11 @@ import { basename, join } from 'node:path'
import { Context } from 'cordis'
import Storage from '@deepseek-ai/dsh-storage'
import type { StorageBackend } from '@deepseek-ai/dsh-storage'
import { DomainFacility } from '@deepseek-ai/dsh-domain'
import type { DomainChanged } from '@deepseek-ai/dsh-domain'
import { DomainFacility } from '@deepseek-ai/dsh-storage-domain'
import type { DomainChanged } from '@deepseek-ai/dsh-storage-domain'
import { SessionId } from '@deepseek-ai/dsh-session'
import type { SessionHeader } from '@deepseek-ai/dsh-session'
import { MemoryMediaPool, MemoryStorageBackend } from '../../../storage/domain/tests/helpers/memory-backend.ts'
import { MemoryMediaPool, MemoryStorageBackend } from '../../../storage/storage-domain/tests/helpers/memory-backend.ts'
import WorkspaceRegistry, { WorkspaceId } from '../src/index.ts'
import type { WorkspaceRecord } from '../src/index.ts'
+1 -1
View File
@@ -21,7 +21,7 @@
"path": "../../storage/storage"
},
{
"path": "../../storage/domain"
"path": "../../storage/storage-domain"
},
{
"path": "../../core/session"
+13 -13
View File
@@ -3167,7 +3167,16 @@ importers:
specifier: ^4.0.0-rc.6
version: 4.0.0-rc.7(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.5)
packages/storage/domain:
packages/storage/storage:
devDependencies:
'@deepseek-ai/dsh-invariants':
specifier: workspace:^
version: link:../../support/invariants
cordis:
specifier: ^4.0.0-rc.7
version: 4.0.0-rc.7(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.5)
packages/storage/storage-domain:
dependencies:
schemastery:
specifier: ^3.18.0
@@ -3186,15 +3195,6 @@ importers:
specifier: ^4.0.0-rc.7
version: 4.0.0-rc.7(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.5)
packages/storage/storage:
devDependencies:
'@deepseek-ai/dsh-invariants':
specifier: workspace:^
version: link:../../support/invariants
cordis:
specifier: ^4.0.0-rc.7
version: 4.0.0-rc.7(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.5)
packages/storage/storage-json:
dependencies:
schemastery:
@@ -4342,9 +4342,6 @@ importers:
'@deepseek-ai/dsh-brand':
specifier: workspace:^
version: link:../../util/brand
'@deepseek-ai/dsh-domain':
specifier: workspace:^
version: link:../../storage/domain
'@deepseek-ai/dsh-invariants':
specifier: workspace:^
version: link:../../support/invariants
@@ -4357,6 +4354,9 @@ importers:
'@deepseek-ai/dsh-storage':
specifier: workspace:^
version: link:../../storage/storage
'@deepseek-ai/dsh-storage-domain':
specifier: workspace:^
version: link:../../storage/storage-domain
cordis:
specifier: ^4.0.0-rc.7
version: 4.0.0-rc.7(@cordisjs/plugin-include@1.0.4)(@cordisjs/plugin-loader@1.0.0-rc.5)
+3 -3
View File
@@ -207,9 +207,9 @@ const TYPE_LINK_EXEMPTIONS: Readonly<Record<string, string>> = {
BashEnvVariableInfo: 'service-local metadata type is owned by packages/bash/tool-bash/src/index.ts',
CompactAgentContext: 'compaction service input is owned by packages/compact/compact/src/index.ts',
CreateAgentOptions: 'agent creation contract is owned by packages/core/agent/README.md',
DomainChanged: 'event-local snapshot is owned by packages/storage/domain/src/events.ts',
DomainFacility: 'domain form facility is owned by packages/storage/domain/README.md',
DomainSpec: 'domain declaration contract is owned by packages/storage/domain/README.md',
DomainChanged: 'event-local snapshot is owned by packages/storage/storage-domain/src/events.ts',
DomainFacility: 'domain form facility is owned by packages/storage/storage-domain/README.md',
DomainSpec: 'domain declaration contract is owned by packages/storage/storage-domain/README.md',
StorageBackend: 'backend contract is owned by packages/storage/storage/src/backend.ts',
StorageForms: 'merge-extensible form map is owned by packages/storage/storage/src/index.ts',
InvariantInstaller: 'service-local contribution contract is owned by packages/support/invariants/README.md',
+1 -1
View File
@@ -140,7 +140,7 @@ const SERVICE_ROLES: ServiceRole[] = [
title: 'Non-session storage hub',
mode: 'seam',
implementations: ['storage-json', 'storage-sqlite'],
consumers: ['domain', 'workspace'],
consumers: ['storage-domain', 'workspace'],
note: 'Backends register side by side under names; data forms (domain first) mount on the hub and translate typed operations into opaque KV-unit primitives.',
},
{
+1 -1
View File
@@ -47,7 +47,7 @@
{ "path": "./packages/storage/storage" },
{ "path": "./packages/storage/storage-json" },
{ "path": "./packages/storage/storage-sqlite" },
{ "path": "./packages/storage/domain" },
{ "path": "./packages/storage/storage-domain" },
{ "path": "./packages/workspace/workspace" },
{ "path": "./packages/session-title/session-title" },
{ "path": "./packages/session-title/session-title-llm" },