@deepseek-ai/dsh-tool-todo 0.2.0-rc.2 → 0.2.1-alpha.2
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.i18n.yaml +4 -7
- package/README.md +1 -6
- package/README.zh.md +1 -6
- package/package.json +20 -27
- package/lib/invariant.js +0 -88
- package/lib/types/invariant.d.ts +0 -13
- package/lib/types/invariant.js +0 -95
package/README.i18n.yaml
CHANGED
|
@@ -33,20 +33,17 @@
|
|
|
33
33
|
en: 8d94a7381bca3fa9
|
|
34
34
|
zh: f4bd2866fff6fa8d
|
|
35
35
|
/deepseek-ai-dsh-tool-todo/understand-the-implementation/design-philosophy:
|
|
36
|
-
en:
|
|
37
|
-
zh:
|
|
36
|
+
en: e9cf462797eaf9f2
|
|
37
|
+
zh: 02d9a7fce90936c3
|
|
38
38
|
/deepseek-ai-dsh-tool-todo/understand-the-implementation/source-map:
|
|
39
|
-
en:
|
|
40
|
-
zh:
|
|
39
|
+
en: 51328ad8c7fcbfd0
|
|
40
|
+
zh: 2614ec42b61ff3ef
|
|
41
41
|
/deepseek-ai-dsh-tool-todo/understand-the-implementation/export-shape:
|
|
42
42
|
en: 35b4f6c718e60dab
|
|
43
43
|
zh: 9bffe86c88a7ad6d
|
|
44
44
|
/deepseek-ai-dsh-tool-todo/understand-the-implementation/session-projection:
|
|
45
45
|
en: 2d49c8af46b16dd2
|
|
46
46
|
zh: 71a3073433b579d4
|
|
47
|
-
/deepseek-ai-dsh-tool-todo/understand-the-implementation/durable-log-invariant:
|
|
48
|
-
en: 3234e0405b88e314
|
|
49
|
-
zh: 135a5b12d810e6dd
|
|
50
47
|
/deepseek-ai-dsh-tool-todo/understand-the-implementation/call-mechanics:
|
|
51
48
|
en: d55f6a32b05ed686
|
|
52
49
|
zh: c815f930a2acebda
|
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ The tool is built on four commitments:
|
|
|
71
71
|
|
|
72
72
|
- **Whole-list replace, log-backed state.** The model resends the entire list; the `todo/write` snapshot lives on the event-sourced session log, so durability, replay, and resume reconstruction come from the log rather than a service.
|
|
73
73
|
- **Single owner.** The list belongs to the calling agent session; there is no shared or swarm scope, and non-agent callers are rejected.
|
|
74
|
-
- **Deployment policy, not a coded rule.** `allowParallelInProgress` is a required composition choice because the tool cannot observe runtime concurrency
|
|
74
|
+
- **Deployment policy, not a coded rule.** `allowParallelInProgress` is a required composition choice because the tool cannot observe runtime concurrency.
|
|
75
75
|
- **Validation keeps the logged snapshot honest.** Schema-level rejection of unknown keys and `execute`-level rejection of empty or duplicate content keep the durable snapshot equal to what the model believes it wrote.
|
|
76
76
|
|
|
77
77
|
The [todo_write tool Agent Note](../../../.agents/notes/archived/feature/2026-06-29-todo-write-tool.md) records the original design and alternatives; the [parallel in-progress Agent Note](../../../.agents/notes/archived/feature/2026-07-26-todo-parallel-in-progress.md) records the policy decision.
|
|
@@ -83,7 +83,6 @@ The [todo_write tool Agent Note](../../../.agents/notes/archived/feature/2026-06
|
|
|
83
83
|
| [`src/index.ts`](src/index.ts) | Plugin entry: `Config` schema, tool registration, `todos` projection unit |
|
|
84
84
|
| [`src/types.ts`](src/types.ts) | The one home of the `todos` projection-key declaration and its payload types |
|
|
85
85
|
| [`src/client.ts`](src/client.ts) | Client-namespace re-export of the types outlet |
|
|
86
|
-
| [`src/invariant.ts`](src/invariant.ts) | Invariant companion: validates durable whole-list snapshots and open-turn ownership |
|
|
87
86
|
|
|
88
87
|
### Export shape
|
|
89
88
|
|
|
@@ -93,10 +92,6 @@ The plugin is a function/namespace plugin: it exports `name` / `inject` / `apply
|
|
|
93
92
|
|
|
94
93
|
When the composition mounts `ctx.sessionProjections` ([`@deepseek-ai/dsh-session-projection`](../../session/session-projection/README.md)), this package registers the `todos` unit on an injected child: the projection is the standing plan — the latest whole `todo/write` list, `null` before the first write, cleared when the next turn starts while `turn/end` keeps the finished checklist visible. The key merges into `SessionProjectionMap` here; carriers serve the value on the history tail page and the `session/projection` push frame. Compositions without the registry are unaffected; see [src/index.ts](src/index.ts) for the unit registration.
|
|
95
94
|
|
|
96
|
-
### Durable-log invariant
|
|
97
|
-
|
|
98
|
-
The invariant companion registers on `ctx.invariants`, validates existing and newly announced sessions once, and then advances a committed per-session turn trace for live appends. It rejects malformed entries, empty or duplicated content, unknown statuses, and any durable `todo/write` outside an open turn; core session treats declaration-merged events generically, while this producing package owns todo-specific rules. It deliberately says nothing about how many items are `in_progress`, because that is the tool's per-deployment policy, not a durable-data rule.
|
|
99
|
-
|
|
100
95
|
### Call mechanics
|
|
101
96
|
|
|
102
97
|
Each call validates the submitted list against the schema, rejects incoherent input, and on success appends the full snapshot as a `todo/write` session event and returns the new counts; the current list is always the most recent `todo/write` in the log (last-write-wins on replay). See [src/index.ts](src/index.ts) for the exact validation and append steps.
|
package/README.zh.md
CHANGED
|
@@ -71,7 +71,7 @@ agent 每次更新都发送完整列表;新列表替换旧列表,因此没
|
|
|
71
71
|
|
|
72
72
|
- **整表替换、日志承载状态。** 模型重新发送整个列表;`todo/write` 快照存放在事件溯源的会话日志上,持久性、回放与恢复重建都来自日志而非服务。
|
|
73
73
|
- **单一所有者。** 列表属于调用 agent 会话;不存在共享或 swarm 作用域,非 agent 调用方会被拒绝。
|
|
74
|
-
- **部署策略,而非编码规则。** `allowParallelInProgress`
|
|
74
|
+
- **部署策略,而非编码规则。** `allowParallelInProgress` 是必填组合选择,因为工具无法观测运行时并发。
|
|
75
75
|
- **校验确保日志快照如实反映输入。** schema 层拒绝未知键、`execute` 层拒绝空或重复 content,使持久快照与模型自认为写入的内容一致。
|
|
76
76
|
|
|
77
77
|
[todo_write 工具 Agent Note](../../../.agents/notes/archived/feature/2026-06-29-todo-write-tool.md) 记录原始设计与备选方案;[并行 in-progress Agent Note](../../../.agents/notes/archived/feature/2026-07-26-todo-parallel-in-progress.md) 记录该策略决策。
|
|
@@ -83,7 +83,6 @@ agent 每次更新都发送完整列表;新列表替换旧列表,因此没
|
|
|
83
83
|
| [`src/index.ts`](src/index.ts) | 插件入口:`Config` schema、工具注册、`todos` 投影单元 |
|
|
84
84
|
| [`src/types.ts`](src/types.ts) | `todos` 投影键声明及其载荷类型的唯一归属地 |
|
|
85
85
|
| [`src/client.ts`](src/client.ts) | 客户端命名空间对类型出口的再导出 |
|
|
86
|
-
| [`src/invariant.ts`](src/invariant.ts) | 不变式伴生插件:校验持久整表快照与开放轮次归属 |
|
|
87
86
|
|
|
88
87
|
### 导出形状
|
|
89
88
|
|
|
@@ -93,10 +92,6 @@ agent 每次更新都发送完整列表;新列表替换旧列表,因此没
|
|
|
93
92
|
|
|
94
93
|
当组合挂载 `ctx.sessionProjections`([`@deepseek-ai/dsh-session-projection`](../../session/session-projection/README.zh.md))时,本包在注入的子插件中注册 `todos` 单元:投影即有效计划——最新的整份 `todo/write` 列表,首次写入前为 `null`,下一轮次开始时清空,而 `turn/end` 保留刚完成的清单。该键在此处合并进 `SessionProjectionMap`;载体通过历史尾页与 `session/projection` 推送帧提供该值。未挂载注册表的组合不受影响;单元注册见 [src/index.ts](src/index.ts)。
|
|
95
94
|
|
|
96
|
-
### 持久日志不变式
|
|
97
|
-
|
|
98
|
-
不变式伴生插件注册到 `ctx.invariants`,先分别校验既有会话与新公布会话一次,再为实时追加推进按会话提交的轮次轨迹。它会拒绝畸形条目、空或重复 content、未知状态,以及开放轮次之外的持久 `todo/write`;核心 session 通用处理声明合并事件,而本生产包拥有 todo 专用规则。它刻意不约束有多少条目处于 `in_progress`,因为那是工具按部署制定的策略,而非持久数据规则。
|
|
99
|
-
|
|
100
95
|
### 调用机制
|
|
101
96
|
|
|
102
97
|
每次调用都会先校验提交的列表是否符合 schema,拒绝不一致的输入,成功后把完整快照作为 `todo/write` 会话事件追加并返回新的计数;当前列表始终是日志中最近一次 `todo/write`(回放时后写覆盖先写)。确切的校验与追加步骤见 [src/index.ts](src/index.ts)。
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-tool-todo",
|
|
3
3
|
"description": "Model-facing todo_write tool over the DeepSeek Harness event-sourced session log",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -18,10 +18,6 @@
|
|
|
18
18
|
"types": "./lib/types/index.d.ts",
|
|
19
19
|
"default": "./lib/index.js"
|
|
20
20
|
},
|
|
21
|
-
"./invariant": {
|
|
22
|
-
"types": "./lib/types/invariant.d.ts",
|
|
23
|
-
"default": "./lib/invariant.js"
|
|
24
|
-
},
|
|
25
21
|
"./client": {
|
|
26
22
|
"types": "./lib/types/client.d.ts",
|
|
27
23
|
"default": "./lib/types/client.js"
|
|
@@ -31,36 +27,33 @@
|
|
|
31
27
|
},
|
|
32
28
|
"files": [
|
|
33
29
|
"lib/index.js",
|
|
34
|
-
"lib/invariant.js",
|
|
35
30
|
"lib/types/**/*.js",
|
|
36
31
|
"lib/types/**/*.d.ts"
|
|
37
32
|
],
|
|
38
33
|
"license": "MIT",
|
|
39
34
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"
|
|
35
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.1",
|
|
36
|
+
"zod": "^4.4.3"
|
|
42
37
|
},
|
|
43
38
|
"peerDependencies": {
|
|
44
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
45
|
-
"@deepseek-ai/dsh-
|
|
46
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
47
|
-
"@deepseek-ai/dsh-
|
|
48
|
-
"@deepseek-ai/
|
|
49
|
-
"@deepseek-ai/cordis": "~4.0.4"
|
|
39
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
40
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
41
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
|
|
42
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
43
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
50
44
|
},
|
|
51
45
|
"devDependencies": {
|
|
52
|
-
"@deepseek-ai/cordis-plugin-include": "~1.0.
|
|
53
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.
|
|
54
|
-
"@deepseek-ai/dsh-agent
|
|
55
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
56
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.
|
|
57
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/cordis": "~4.0.
|
|
64
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2"
|
|
46
|
+
"@deepseek-ai/cordis-plugin-include": "~1.0.10-alpha.1",
|
|
47
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.1",
|
|
48
|
+
"@deepseek-ai/dsh-agent": "0.2.1-alpha.2",
|
|
49
|
+
"@deepseek-ai/dsh-agent-loop": "0.2.1-alpha.2",
|
|
50
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "0.2.1-alpha.2",
|
|
51
|
+
"@deepseek-ai/dsh-llm": "0.2.1-alpha.2",
|
|
52
|
+
"@deepseek-ai/dsh-session": "0.2.1-alpha.2",
|
|
53
|
+
"@deepseek-ai/dsh-session-projection": "0.2.1-alpha.2",
|
|
54
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.1-alpha.2",
|
|
55
|
+
"@deepseek-ai/dsh-tools": "0.2.1-alpha.2",
|
|
56
|
+
"@deepseek-ai/dsh-user-questions": "0.2.1-alpha.2",
|
|
57
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.1"
|
|
65
58
|
}
|
|
66
59
|
}
|
package/lib/invariant.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
//#region lib/types/invariant.js
|
|
2
|
-
/** Package-owned durable todo-snapshot invariants. @module @deepseek-ai/dsh-tool-todo/invariant */
|
|
3
|
-
const PACKAGE_NAME = "@deepseek-ai/dsh-tool-todo";
|
|
4
|
-
const TODO_STATUSES = new Set([
|
|
5
|
-
"pending",
|
|
6
|
-
"in_progress",
|
|
7
|
-
"completed"
|
|
8
|
-
]);
|
|
9
|
-
/** Cordis companion plugin name. */
|
|
10
|
-
const name = "tool-todo-invariant";
|
|
11
|
-
/** Service required before the companion can reserve package ownership. */
|
|
12
|
-
const inject = ["invariants"];
|
|
13
|
-
/**
|
|
14
|
-
* Validate one whole-list todo snapshot before it reaches the durable log.
|
|
15
|
-
*
|
|
16
|
-
* Deliberately silent on how many items are `in_progress`. That is the tool's
|
|
17
|
-
* per-deployment policy (`Config.allowParallelInProgress`), not a durable-shape
|
|
18
|
-
* rule: a log written while parallel work was allowed must still replay after a
|
|
19
|
-
* deployment tightens the policy, so tying the invariant to the current config
|
|
20
|
-
* would reject history that was valid when it was written.
|
|
21
|
-
*/
|
|
22
|
-
function validateTodos(value, fail) {
|
|
23
|
-
if (!Array.isArray(value)) fail("todo/write todos must be an array");
|
|
24
|
-
const seen = /* @__PURE__ */ new Set();
|
|
25
|
-
for (const item of value) {
|
|
26
|
-
if (typeof item !== "object" || item === null) fail("todo/write entries must be objects");
|
|
27
|
-
const { content, status } = item;
|
|
28
|
-
if (typeof content !== "string" || content.length === 0 || content.trim() !== content) fail("todo/write content must be non-empty and already trimmed");
|
|
29
|
-
if (seen.has(content)) fail(`todo/write repeats content ${JSON.stringify(content)}`);
|
|
30
|
-
seen.add(content);
|
|
31
|
-
if (typeof status !== "string" || !TODO_STATUSES.has(status)) fail(`todo/write carries unknown status ${JSON.stringify(status)}`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/** Advance the trace after one event has committed. */
|
|
35
|
-
function advanceTrace(trace, event) {
|
|
36
|
-
if (event.type === "turn/start") trace.open = true;
|
|
37
|
-
if (event.type === "turn/end") trace.open = false;
|
|
38
|
-
}
|
|
39
|
-
/** Validate one package-owned event against the preceding committed trace. */
|
|
40
|
-
function validateEvent(event, trace, fail) {
|
|
41
|
-
if (event.type !== "todo/write") return;
|
|
42
|
-
validateTodos(event.data.todos, fail);
|
|
43
|
-
if (!trace.open) fail("todo/write appended outside any open turn");
|
|
44
|
-
}
|
|
45
|
-
/** Validate one existing log in a single pass and return its tail trace. */
|
|
46
|
-
function seedTrace(session, fail) {
|
|
47
|
-
const trace = { open: false };
|
|
48
|
-
for (const event of session.snapshotEvents()) {
|
|
49
|
-
validateEvent(event, trace, fail);
|
|
50
|
-
advanceTrace(trace, event);
|
|
51
|
-
}
|
|
52
|
-
return trace;
|
|
53
|
-
}
|
|
54
|
-
/** Install validation for loaded and newly appended whole-list todo snapshots. */
|
|
55
|
-
const install = Object.assign((ctx, fail) => {
|
|
56
|
-
const traces = /* @__PURE__ */ new WeakMap();
|
|
57
|
-
const seed = (session) => {
|
|
58
|
-
traces.set(session, seedTrace(session, fail));
|
|
59
|
-
};
|
|
60
|
-
const traceFor = (session) => {
|
|
61
|
-
let trace = traces.get(session);
|
|
62
|
-
if (trace === void 0) {
|
|
63
|
-
trace = seedTrace(session, fail);
|
|
64
|
-
traces.set(session, trace);
|
|
65
|
-
}
|
|
66
|
-
return trace;
|
|
67
|
-
};
|
|
68
|
-
for (const session of ctx.sessions.list()) seed(session);
|
|
69
|
-
ctx.on("session/created", (session) => {
|
|
70
|
-
seed(session);
|
|
71
|
-
}, { global: true });
|
|
72
|
-
ctx.on("internal/dispatch", (_mode, eventName, args) => {
|
|
73
|
-
if (eventName !== "session/event") return;
|
|
74
|
-
const [session, event] = args;
|
|
75
|
-
validateEvent(event, traceFor(session), fail);
|
|
76
|
-
}, { global: true });
|
|
77
|
-
ctx.on("session/event", (session, event) => {
|
|
78
|
-
advanceTrace(traceFor(session), event);
|
|
79
|
-
}, { global: true });
|
|
80
|
-
}, { inject: ["sessions"] });
|
|
81
|
-
/**
|
|
82
|
-
* Register the todo invariant companion.
|
|
83
|
-
* @param ctx - Cordis context carrying the invariant service.
|
|
84
|
-
* @returns the installed registration's disposer after setup succeeds.
|
|
85
|
-
*/
|
|
86
|
-
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
87
|
-
//#endregion
|
|
88
|
-
export { apply, inject, name };
|
package/lib/types/invariant.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/** Package-owned durable todo-snapshot invariants. @module @deepseek-ai/dsh-tool-todo/invariant */
|
|
2
|
-
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
-
/** Cordis companion plugin name. */
|
|
4
|
-
export declare const name = "tool-todo-invariant";
|
|
5
|
-
/** Service required before the companion can reserve package ownership. */
|
|
6
|
-
export declare const inject: string[];
|
|
7
|
-
/**
|
|
8
|
-
* Register the todo invariant companion.
|
|
9
|
-
* @param ctx - Cordis context carrying the invariant service.
|
|
10
|
-
* @returns the installed registration's disposer after setup succeeds.
|
|
11
|
-
*/
|
|
12
|
-
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
13
|
-
//# sourceMappingURL=invariant.d.ts.map
|
package/lib/types/invariant.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/** Package-owned durable todo-snapshot invariants. @module @deepseek-ai/dsh-tool-todo/invariant */
|
|
2
|
-
const PACKAGE_NAME = '@deepseek-ai/dsh-tool-todo';
|
|
3
|
-
const TODO_STATUSES = new Set(['pending', 'in_progress', 'completed']);
|
|
4
|
-
/** Cordis companion plugin name. */
|
|
5
|
-
export const name = 'tool-todo-invariant';
|
|
6
|
-
/** Service required before the companion can reserve package ownership. */
|
|
7
|
-
export const inject = ['invariants'];
|
|
8
|
-
/**
|
|
9
|
-
* Validate one whole-list todo snapshot before it reaches the durable log.
|
|
10
|
-
*
|
|
11
|
-
* Deliberately silent on how many items are `in_progress`. That is the tool's
|
|
12
|
-
* per-deployment policy (`Config.allowParallelInProgress`), not a durable-shape
|
|
13
|
-
* rule: a log written while parallel work was allowed must still replay after a
|
|
14
|
-
* deployment tightens the policy, so tying the invariant to the current config
|
|
15
|
-
* would reject history that was valid when it was written.
|
|
16
|
-
*/
|
|
17
|
-
function validateTodos(value, fail) {
|
|
18
|
-
if (!Array.isArray(value))
|
|
19
|
-
fail('todo/write todos must be an array');
|
|
20
|
-
const seen = new Set();
|
|
21
|
-
for (const item of value) {
|
|
22
|
-
if (typeof item !== 'object' || item === null)
|
|
23
|
-
fail('todo/write entries must be objects');
|
|
24
|
-
const { content, status } = item;
|
|
25
|
-
if (typeof content !== 'string' || content.length === 0 || content.trim() !== content) {
|
|
26
|
-
fail('todo/write content must be non-empty and already trimmed');
|
|
27
|
-
}
|
|
28
|
-
if (seen.has(content))
|
|
29
|
-
fail(`todo/write repeats content ${JSON.stringify(content)}`);
|
|
30
|
-
seen.add(content);
|
|
31
|
-
if (typeof status !== 'string' || !TODO_STATUSES.has(status)) {
|
|
32
|
-
fail(`todo/write carries unknown status ${JSON.stringify(status)}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/** Advance the trace after one event has committed. */
|
|
37
|
-
function advanceTrace(trace, event) {
|
|
38
|
-
if (event.type === 'turn/start')
|
|
39
|
-
trace.open = true;
|
|
40
|
-
if (event.type === 'turn/end')
|
|
41
|
-
trace.open = false;
|
|
42
|
-
}
|
|
43
|
-
/** Validate one package-owned event against the preceding committed trace. */
|
|
44
|
-
function validateEvent(event, trace, fail) {
|
|
45
|
-
if (event.type !== 'todo/write')
|
|
46
|
-
return;
|
|
47
|
-
validateTodos(event.data.todos, fail);
|
|
48
|
-
if (!trace.open)
|
|
49
|
-
fail('todo/write appended outside any open turn');
|
|
50
|
-
}
|
|
51
|
-
/** Validate one existing log in a single pass and return its tail trace. */
|
|
52
|
-
function seedTrace(session, fail) {
|
|
53
|
-
const trace = { open: false };
|
|
54
|
-
// oxlint-disable-next-line typescript/no-deprecated -- Existing Session history read; migration deferred.
|
|
55
|
-
for (const event of session.snapshotEvents()) {
|
|
56
|
-
validateEvent(event, trace, fail);
|
|
57
|
-
advanceTrace(trace, event);
|
|
58
|
-
}
|
|
59
|
-
return trace;
|
|
60
|
-
}
|
|
61
|
-
/** Install validation for loaded and newly appended whole-list todo snapshots. */
|
|
62
|
-
const install = Object.assign((ctx, fail) => {
|
|
63
|
-
const traces = new WeakMap();
|
|
64
|
-
const seed = (session) => {
|
|
65
|
-
traces.set(session, seedTrace(session, fail));
|
|
66
|
-
};
|
|
67
|
-
const traceFor = (session) => {
|
|
68
|
-
let trace = traces.get(session);
|
|
69
|
-
if (trace === undefined) {
|
|
70
|
-
trace = seedTrace(session, fail);
|
|
71
|
-
traces.set(session, trace);
|
|
72
|
-
}
|
|
73
|
-
return trace;
|
|
74
|
-
};
|
|
75
|
-
for (const session of ctx.sessions.list())
|
|
76
|
-
seed(session);
|
|
77
|
-
ctx.on('session/created', (session) => { seed(session); }, { global: true });
|
|
78
|
-
ctx.on('internal/dispatch', (_mode, eventName, args) => {
|
|
79
|
-
if (eventName !== 'session/event')
|
|
80
|
-
return;
|
|
81
|
-
const [session, event] = args;
|
|
82
|
-
validateEvent(event, traceFor(session), fail);
|
|
83
|
-
}, { global: true });
|
|
84
|
-
ctx.on('session/event', (session, event) => {
|
|
85
|
-
advanceTrace(traceFor(session), event);
|
|
86
|
-
}, { global: true });
|
|
87
|
-
}, { inject: ['sessions'] });
|
|
88
|
-
/* jscpd:ignore-end */
|
|
89
|
-
/**
|
|
90
|
-
* Register the todo invariant companion.
|
|
91
|
-
* @param ctx - Cordis context carrying the invariant service.
|
|
92
|
-
* @returns the installed registration's disposer after setup succeeds.
|
|
93
|
-
*/
|
|
94
|
-
export const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
95
|
-
//# sourceMappingURL=invariant.js.map
|