dsh-kingdom 0.3.1
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/LICENSE +29 -0
- package/README.md +184 -0
- package/cordis.patch.yml +6 -0
- package/lib/core/binding.js +57 -0
- package/lib/core/binding.js.map +1 -0
- package/lib/core/db.js +521 -0
- package/lib/core/db.js.map +1 -0
- package/lib/core/execution.js +88 -0
- package/lib/core/execution.js.map +1 -0
- package/lib/core/kingdom.js +117 -0
- package/lib/core/kingdom.js.map +1 -0
- package/lib/core/task-service.js +581 -0
- package/lib/core/task-service.js.map +1 -0
- package/lib/core/task.js +93 -0
- package/lib/core/task.js.map +1 -0
- package/lib/core/territory.js +47 -0
- package/lib/core/territory.js.map +1 -0
- package/lib/gui/contract.js +53 -0
- package/lib/gui/contract.js.map +1 -0
- package/lib/gui/server.js +204 -0
- package/lib/gui/server.js.map +1 -0
- package/lib/gui/snapshot.js +379 -0
- package/lib/gui/snapshot.js.map +1 -0
- package/lib/index.js +489 -0
- package/lib/index.js.map +1 -0
- package/lib/paths.js +23 -0
- package/lib/paths.js.map +1 -0
- package/lib/types/core/binding.d.ts +11 -0
- package/lib/types/core/db.d.ts +261 -0
- package/lib/types/core/execution.d.ts +51 -0
- package/lib/types/core/kingdom.d.ts +34 -0
- package/lib/types/core/task-service.d.ts +107 -0
- package/lib/types/core/task.d.ts +60 -0
- package/lib/types/core/territory.d.ts +9 -0
- package/lib/types/gui/contract.d.ts +226 -0
- package/lib/types/gui/server.d.ts +26 -0
- package/lib/types/gui/snapshot.d.ts +44 -0
- package/lib/types/index.d.ts +80 -0
- package/lib/types/paths.d.ts +6 -0
- package/lib/types/worker/dsh-subagent.d.ts +79 -0
- package/lib/types/worker/executor.d.ts +121 -0
- package/lib/worker/dsh-subagent.js +117 -0
- package/lib/worker/dsh-subagent.js.map +1 -0
- package/lib/worker/executor.js +94 -0
- package/lib/worker/executor.js.map +1 -0
- package/package.json +59 -0
package/lib/core/db.js
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-kingdom — KingdomStore:node:sqlite 封装 + 6 表幂等建表。
|
|
3
|
+
*
|
|
4
|
+
* 治理纪律(Phase 1 轻量实现,基础设施后置):
|
|
5
|
+
* - 全部 CREATE TABLE IF NOT EXISTS,初始化幂等(重复 init = 接入,不覆盖)。
|
|
6
|
+
* - 无 ORM / 无触发器 / 无 hash chain / 无 Command Bus(Phase 3+ 再上)。
|
|
7
|
+
* - 权威状态只经本 Core 的公开方法写入;Agent 只能经 kingdom_* 工具进入。
|
|
8
|
+
*
|
|
9
|
+
* Phase 2 增量(零 migration,Owner 裁决 3/4):
|
|
10
|
+
* - 第 6 张表 worker_results(CREATE TABLE IF NOT EXISTS 幂等追加)。
|
|
11
|
+
* - territories 防御性 UNIQUE index(CREATE UNIQUE INDEX IF NOT EXISTS,旧库直接生效)。
|
|
12
|
+
* - tasks 表**一个字节都不改**:status 无 CHECK(2026-08-17 现场只读核对确认),
|
|
13
|
+
* 状态机只在 Core 代码层(见 ./task.ts)。
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
16
|
+
import { dirname } from 'node:path';
|
|
17
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
18
|
+
import { asTaskStatus, transition } from './task.js';
|
|
19
|
+
import { asExecutionState, isTerminalExecutionState, transitionExecution, } from './execution.js';
|
|
20
|
+
/**
|
|
21
|
+
* 记录在 kingdoms.schema_version 上的值。
|
|
22
|
+
*
|
|
23
|
+
* Phase 2 **刻意保持 1**:本插件没有任何按版本号分支的 migration 逻辑,
|
|
24
|
+
* 建表全部幂等,任何 0.2.0 打开的旧库都会在开库瞬间收敛到同一套 6 表结构。
|
|
25
|
+
* 此时把新库标成 2、旧库留在 1,只会制造一个「同结构不同版本号」的假差异。
|
|
26
|
+
* 真正引入破坏性 migration 时再启用这个字段作为 gate。
|
|
27
|
+
*/
|
|
28
|
+
export const SCHEMA_VERSION = 1;
|
|
29
|
+
export const SCHEMA_SQL = `
|
|
30
|
+
CREATE TABLE IF NOT EXISTS kingdoms (
|
|
31
|
+
kingdom_id TEXT PRIMARY KEY,
|
|
32
|
+
name TEXT NOT NULL,
|
|
33
|
+
created_at TEXT NOT NULL,
|
|
34
|
+
owner_id TEXT NOT NULL,
|
|
35
|
+
owner_name TEXT NOT NULL,
|
|
36
|
+
schema_version INTEGER NOT NULL DEFAULT 1
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE TABLE IF NOT EXISTS territories (
|
|
40
|
+
territory_id TEXT PRIMARY KEY,
|
|
41
|
+
kingdom_id TEXT NOT NULL,
|
|
42
|
+
name TEXT NOT NULL,
|
|
43
|
+
workspace_path TEXT,
|
|
44
|
+
summary TEXT,
|
|
45
|
+
supervisor_binding_id TEXT,
|
|
46
|
+
status TEXT NOT NULL DEFAULT 'ACTIVE',
|
|
47
|
+
created_at TEXT NOT NULL
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS role_bindings (
|
|
51
|
+
binding_id TEXT PRIMARY KEY,
|
|
52
|
+
kingdom_id TEXT NOT NULL,
|
|
53
|
+
role_type TEXT NOT NULL CHECK(role_type IN ('OWNER','CHANCELLOR','SUPERVISOR','WORKER')),
|
|
54
|
+
role_name TEXT NOT NULL,
|
|
55
|
+
runtime_type TEXT NOT NULL DEFAULT 'dsh',
|
|
56
|
+
session_id TEXT,
|
|
57
|
+
principal_id TEXT,
|
|
58
|
+
created_at TEXT NOT NULL,
|
|
59
|
+
updated_at TEXT NOT NULL
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
CREATE TABLE IF NOT EXISTS tasks (
|
|
63
|
+
task_id TEXT PRIMARY KEY,
|
|
64
|
+
territory_id TEXT NOT NULL,
|
|
65
|
+
parent_task_id TEXT,
|
|
66
|
+
title TEXT NOT NULL,
|
|
67
|
+
description TEXT,
|
|
68
|
+
assigned_binding_id TEXT,
|
|
69
|
+
status TEXT NOT NULL DEFAULT 'CREATED',
|
|
70
|
+
acceptance_criteria TEXT,
|
|
71
|
+
result_summary TEXT,
|
|
72
|
+
created_at TEXT NOT NULL,
|
|
73
|
+
updated_at TEXT NOT NULL
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
77
|
+
event_id TEXT PRIMARY KEY,
|
|
78
|
+
kingdom_id TEXT NOT NULL,
|
|
79
|
+
event_type TEXT NOT NULL,
|
|
80
|
+
actor_role TEXT,
|
|
81
|
+
actor_id TEXT,
|
|
82
|
+
target_type TEXT,
|
|
83
|
+
target_id TEXT,
|
|
84
|
+
payload_json TEXT NOT NULL DEFAULT '{}',
|
|
85
|
+
created_at TEXT NOT NULL
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
CREATE TABLE IF NOT EXISTS worker_results (
|
|
89
|
+
result_id TEXT PRIMARY KEY,
|
|
90
|
+
task_id TEXT NOT NULL,
|
|
91
|
+
attempt_no INTEGER NOT NULL,
|
|
92
|
+
worker_binding_id TEXT,
|
|
93
|
+
session_id TEXT,
|
|
94
|
+
outcome TEXT NOT NULL,
|
|
95
|
+
result_json TEXT NOT NULL DEFAULT '{}',
|
|
96
|
+
created_at TEXT NOT NULL,
|
|
97
|
+
UNIQUE(task_id, attempt_no)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
CREATE UNIQUE INDEX IF NOT EXISTS territories_kingdom_name_uk
|
|
101
|
+
ON territories(kingdom_id, name);
|
|
102
|
+
|
|
103
|
+
CREATE TABLE IF NOT EXISTS executions (
|
|
104
|
+
execution_id TEXT PRIMARY KEY,
|
|
105
|
+
task_id TEXT NOT NULL,
|
|
106
|
+
attempt_no INTEGER NOT NULL,
|
|
107
|
+
worker_binding_id TEXT,
|
|
108
|
+
session_id TEXT,
|
|
109
|
+
state TEXT NOT NULL,
|
|
110
|
+
detail TEXT,
|
|
111
|
+
started_at TEXT NOT NULL,
|
|
112
|
+
heartbeat_at TEXT,
|
|
113
|
+
ended_at TEXT,
|
|
114
|
+
pause_requested_at TEXT,
|
|
115
|
+
UNIQUE(task_id, attempt_no)
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
CREATE INDEX IF NOT EXISTS executions_task_idx ON executions(task_id);
|
|
119
|
+
`;
|
|
120
|
+
export class KingdomStore {
|
|
121
|
+
db;
|
|
122
|
+
/** 已打开即存在(表已保证);记录 init 结果供 status 用 */
|
|
123
|
+
existed;
|
|
124
|
+
constructor(dbPath) {
|
|
125
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
126
|
+
const existed = isExistingDatabase(dbPath);
|
|
127
|
+
this.existed = existed;
|
|
128
|
+
this.db = new DatabaseSync(dbPath);
|
|
129
|
+
this.db.exec('PRAGMA journal_mode = WAL');
|
|
130
|
+
this.db.exec(SCHEMA_SQL);
|
|
131
|
+
this.ensureEventSequence();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 给 events 补上单调序号列(0.2.0 → 0.3.0 唯一一处触及既有表的变更)。
|
|
135
|
+
*
|
|
136
|
+
* 仍然是纯增量、可重复执行、无 table-rebuild:
|
|
137
|
+
* 1. `PRAGMA table_info` 做存在性 gate(`ADD COLUMN` 没有 IF NOT EXISTS);
|
|
138
|
+
* 2. 用 rowid(= 插入顺序)回填历史行,历史顺序因此可确定地重建;
|
|
139
|
+
* 3. 索引用 `IF NOT EXISTS`。
|
|
140
|
+
*
|
|
141
|
+
* 注意 SQLite 的 `ALTER TABLE ... ADD COLUMN` 是 O(1) 元数据操作,
|
|
142
|
+
* 不重写数据页,因此旧库开库仍然是瞬时收敛。
|
|
143
|
+
*/
|
|
144
|
+
ensureEventSequence() {
|
|
145
|
+
const columns = this.db.prepare('PRAGMA table_info(events)').all();
|
|
146
|
+
if (!columns.some(c => c.name === 'seq')) {
|
|
147
|
+
this.db.exec('ALTER TABLE events ADD COLUMN seq INTEGER');
|
|
148
|
+
}
|
|
149
|
+
// rowid 即插入顺序;只回填未赋值的历史行,重复执行无副作用。
|
|
150
|
+
this.db.exec('UPDATE events SET seq = rowid WHERE seq IS NULL');
|
|
151
|
+
this.db.exec('CREATE INDEX IF NOT EXISTS events_kingdom_seq_idx ON events(kingdom_id, seq)');
|
|
152
|
+
}
|
|
153
|
+
/** 关闭连接(插件卸载/重载时调用,避免句柄泄漏)。 */
|
|
154
|
+
close() {
|
|
155
|
+
try {
|
|
156
|
+
this.db.close();
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
// 已关闭则忽略
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// ── kingdoms ────────────────────────────────────────────────
|
|
163
|
+
listKingdoms() {
|
|
164
|
+
return this.db
|
|
165
|
+
.prepare('SELECT * FROM kingdoms ORDER BY created_at')
|
|
166
|
+
.all();
|
|
167
|
+
}
|
|
168
|
+
getDefaultKingdom() {
|
|
169
|
+
const rows = this.listKingdoms();
|
|
170
|
+
return rows[0] ?? null;
|
|
171
|
+
}
|
|
172
|
+
insertKingdom(row) {
|
|
173
|
+
const full = {
|
|
174
|
+
schema_version: SCHEMA_VERSION,
|
|
175
|
+
...row,
|
|
176
|
+
};
|
|
177
|
+
this.db
|
|
178
|
+
.prepare(`INSERT INTO kingdoms (kingdom_id, name, created_at, owner_id, owner_name, schema_version)
|
|
179
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
180
|
+
.run(full.kingdom_id, full.name, full.created_at, full.owner_id, full.owner_name, full.schema_version);
|
|
181
|
+
return full;
|
|
182
|
+
}
|
|
183
|
+
// ── territories ─────────────────────────────────────────────
|
|
184
|
+
listTerritories(kingdomId) {
|
|
185
|
+
return this.db
|
|
186
|
+
.prepare('SELECT * FROM territories WHERE kingdom_id = ? ORDER BY created_at')
|
|
187
|
+
.all(kingdomId);
|
|
188
|
+
}
|
|
189
|
+
getTerritoryByName(kingdomId, name) {
|
|
190
|
+
const rows = this.db
|
|
191
|
+
.prepare('SELECT * FROM territories WHERE kingdom_id = ? AND name = ?')
|
|
192
|
+
.all(kingdomId, name);
|
|
193
|
+
return rows[0] ?? null;
|
|
194
|
+
}
|
|
195
|
+
getTerritoryById(territoryId) {
|
|
196
|
+
const rows = this.db
|
|
197
|
+
.prepare('SELECT * FROM territories WHERE territory_id = ?')
|
|
198
|
+
.all(territoryId);
|
|
199
|
+
return rows[0] ?? null;
|
|
200
|
+
}
|
|
201
|
+
insertTerritory(row) {
|
|
202
|
+
this.db
|
|
203
|
+
.prepare(`INSERT INTO territories
|
|
204
|
+
(territory_id, kingdom_id, name, workspace_path, summary, supervisor_binding_id, status, created_at)
|
|
205
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
206
|
+
.run(row.territory_id, row.kingdom_id, row.name, row.workspace_path, row.summary, row.supervisor_binding_id, row.status, row.created_at);
|
|
207
|
+
return row;
|
|
208
|
+
}
|
|
209
|
+
// ── role_bindings ───────────────────────────────────────────
|
|
210
|
+
listBindings(kingdomId) {
|
|
211
|
+
return this.db
|
|
212
|
+
.prepare('SELECT * FROM role_bindings WHERE kingdom_id = ? ORDER BY created_at')
|
|
213
|
+
.all(kingdomId);
|
|
214
|
+
}
|
|
215
|
+
getBindingByRole(kingdomId, roleType) {
|
|
216
|
+
const rows = this.db
|
|
217
|
+
.prepare('SELECT * FROM role_bindings WHERE kingdom_id = ? AND role_type = ?')
|
|
218
|
+
.all(kingdomId, roleType);
|
|
219
|
+
return rows[0] ?? null;
|
|
220
|
+
}
|
|
221
|
+
getBindingById(bindingId) {
|
|
222
|
+
const rows = this.db
|
|
223
|
+
.prepare('SELECT * FROM role_bindings WHERE binding_id = ?')
|
|
224
|
+
.all(bindingId);
|
|
225
|
+
return rows[0] ?? null;
|
|
226
|
+
}
|
|
227
|
+
insertBinding(row) {
|
|
228
|
+
this.db
|
|
229
|
+
.prepare(`INSERT INTO role_bindings
|
|
230
|
+
(binding_id, kingdom_id, role_type, role_name, runtime_type, session_id, principal_id, created_at, updated_at)
|
|
231
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
232
|
+
.run(row.binding_id, row.kingdom_id, row.role_type, row.role_name, row.runtime_type, row.session_id, row.principal_id, row.created_at, row.updated_at);
|
|
233
|
+
return row;
|
|
234
|
+
}
|
|
235
|
+
updateBindingSession(bindingId, sessionId, updatedAt) {
|
|
236
|
+
this.db
|
|
237
|
+
.prepare('UPDATE role_bindings SET session_id = ?, updated_at = ? WHERE binding_id = ?')
|
|
238
|
+
.run(sessionId, updatedAt, bindingId);
|
|
239
|
+
}
|
|
240
|
+
// ── events ──────────────────────────────────────────────────
|
|
241
|
+
listEvents(kingdomId, limit = 50) {
|
|
242
|
+
return this.db
|
|
243
|
+
.prepare('SELECT * FROM events WHERE kingdom_id = ? ORDER BY seq DESC LIMIT ?')
|
|
244
|
+
.all(kingdomId, limit);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* 按序号增量拉取(GUI 轮询用):返回 seq > afterSeq 的事件,**升序**。
|
|
248
|
+
*
|
|
249
|
+
* GUI 据此判断是否漏事件(收到的首个 seq 应等于 afterSeq + 1),
|
|
250
|
+
* 漏了就重新拉一次全量 snapshot,而不是拿残缺事件流去驱动动画。
|
|
251
|
+
*/
|
|
252
|
+
listEventsSince(kingdomId, afterSeq, limit = 200) {
|
|
253
|
+
return this.db
|
|
254
|
+
.prepare('SELECT * FROM events WHERE kingdom_id = ? AND seq > ? ORDER BY seq ASC LIMIT ?')
|
|
255
|
+
.all(kingdomId, afterSeq, limit);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* 王国当前 revision = 最大事件序号。
|
|
259
|
+
*
|
|
260
|
+
* 任何治理动作都会追加事件,所以这个数既是事件游标,也是"数据版本":
|
|
261
|
+
* GUI 比较 revision 就知道要不要重绘,不必 diff 整个 snapshot。
|
|
262
|
+
*/
|
|
263
|
+
revision(kingdomId) {
|
|
264
|
+
const row = this.db
|
|
265
|
+
.prepare('SELECT COALESCE(MAX(seq), 0) AS n FROM events WHERE kingdom_id = ?')
|
|
266
|
+
.get(kingdomId);
|
|
267
|
+
return row?.n ?? 0;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* 追加事件并分配单调 seq。
|
|
271
|
+
*
|
|
272
|
+
* 「读 MAX(seq) + INSERT」放在 IMMEDIATE 事务里,避免并发写出重复序号
|
|
273
|
+
* (SQLite 会串行化写事务)。序号在**全库**范围内单调,跨王国也不会回退。
|
|
274
|
+
*/
|
|
275
|
+
appendEvent(row) {
|
|
276
|
+
this.db.exec('BEGIN IMMEDIATE');
|
|
277
|
+
try {
|
|
278
|
+
const next = this.db
|
|
279
|
+
.prepare('SELECT COALESCE(MAX(seq), 0) AS n FROM events')
|
|
280
|
+
.get();
|
|
281
|
+
const seq = (next?.n ?? 0) + 1;
|
|
282
|
+
this.db
|
|
283
|
+
.prepare(`INSERT INTO events
|
|
284
|
+
(event_id, kingdom_id, event_type, actor_role, actor_id, target_type, target_id, payload_json, created_at, seq)
|
|
285
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
286
|
+
.run(row.event_id, row.kingdom_id, row.event_type, row.actor_role, row.actor_id, row.target_type, row.target_id, row.payload_json, row.created_at, seq);
|
|
287
|
+
this.db.exec('COMMIT');
|
|
288
|
+
return { ...row, seq };
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
this.db.exec('ROLLBACK');
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// ── tasks(Phase 2;schema 未改,状态机在 ./task.ts)──────────
|
|
296
|
+
getTask(taskId) {
|
|
297
|
+
const rows = this.db
|
|
298
|
+
.prepare('SELECT * FROM tasks WHERE task_id = ?')
|
|
299
|
+
.all(taskId);
|
|
300
|
+
return rows[0] ?? null;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* 列出王国内任务。tasks 无 kingdom_id 列(Phase 1 schema),
|
|
304
|
+
* 经 territories 关联收敛到王国边界。
|
|
305
|
+
*/
|
|
306
|
+
listTasks(kingdomId, filter = {}) {
|
|
307
|
+
const clauses = ['te.kingdom_id = ?'];
|
|
308
|
+
const params = [kingdomId];
|
|
309
|
+
if (filter.territoryId) {
|
|
310
|
+
clauses.push('t.territory_id = ?');
|
|
311
|
+
params.push(filter.territoryId);
|
|
312
|
+
}
|
|
313
|
+
if (filter.status) {
|
|
314
|
+
clauses.push('t.status = ?');
|
|
315
|
+
params.push(filter.status);
|
|
316
|
+
}
|
|
317
|
+
return this.db
|
|
318
|
+
.prepare(`SELECT t.* FROM tasks t
|
|
319
|
+
JOIN territories te ON te.territory_id = t.territory_id
|
|
320
|
+
WHERE ${clauses.join(' AND ')}
|
|
321
|
+
ORDER BY t.created_at`)
|
|
322
|
+
.all(...params);
|
|
323
|
+
}
|
|
324
|
+
insertTask(row) {
|
|
325
|
+
this.db
|
|
326
|
+
.prepare(`INSERT INTO tasks
|
|
327
|
+
(task_id, territory_id, parent_task_id, title, description, assigned_binding_id,
|
|
328
|
+
status, acceptance_criteria, result_summary, created_at, updated_at)
|
|
329
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
330
|
+
.run(row.task_id, row.territory_id, row.parent_task_id, row.title, row.description, row.assigned_binding_id, row.status, row.acceptance_criteria, row.result_summary, row.created_at, row.updated_at);
|
|
331
|
+
return row;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* **全库唯一的 tasks.status 写入路径**(治理底线,Owner 裁决 1)。
|
|
335
|
+
*
|
|
336
|
+
* 先过 ./task.ts 的 transition() 校验,非法转移直接抛 TaskTransitionError,
|
|
337
|
+
* 一个字节都不会落库。任何工具都无法绕过它把 Task 直接置 DONE
|
|
338
|
+
* —— DONE 只能从 REVIEW 经 Supervisor 的 ACCEPT 决定到达。
|
|
339
|
+
*
|
|
340
|
+
* @param task 当前任务行(status 取自库,未知值 fail-loud)。
|
|
341
|
+
* @param to 目标状态。
|
|
342
|
+
* @param patch 与状态同事务落库的附带字段(如指派、Claim 摘要)。
|
|
343
|
+
* @returns 落库后的新任务行。
|
|
344
|
+
*/
|
|
345
|
+
transitionTask(task, to, patch = {}) {
|
|
346
|
+
const from = asTaskStatus(task.status);
|
|
347
|
+
const next = transition(from, to);
|
|
348
|
+
const now = new Date().toISOString();
|
|
349
|
+
const assigned = patch.assigned_binding_id === undefined
|
|
350
|
+
? task.assigned_binding_id
|
|
351
|
+
: patch.assigned_binding_id;
|
|
352
|
+
const summary = patch.result_summary === undefined ? task.result_summary : patch.result_summary;
|
|
353
|
+
this.db
|
|
354
|
+
.prepare(`UPDATE tasks SET status = ?, assigned_binding_id = ?, result_summary = ?, updated_at = ?
|
|
355
|
+
WHERE task_id = ?`)
|
|
356
|
+
.run(next, assigned, summary, now, task.task_id);
|
|
357
|
+
return { ...task, status: next, assigned_binding_id: assigned, result_summary: summary, updated_at: now };
|
|
358
|
+
}
|
|
359
|
+
// ── worker_results(Phase 2 第 6 张表;保存 Claim,不是 Fact)──
|
|
360
|
+
listWorkerResults(taskId) {
|
|
361
|
+
return this.db
|
|
362
|
+
.prepare('SELECT * FROM worker_results WHERE task_id = ? ORDER BY attempt_no')
|
|
363
|
+
.all(taskId);
|
|
364
|
+
}
|
|
365
|
+
latestWorkerResult(taskId) {
|
|
366
|
+
const rows = this.db
|
|
367
|
+
.prepare('SELECT * FROM worker_results WHERE task_id = ? ORDER BY attempt_no DESC LIMIT 1')
|
|
368
|
+
.all(taskId);
|
|
369
|
+
return rows[0] ?? null;
|
|
370
|
+
}
|
|
371
|
+
/** 已落库的最大 attempt_no;无结果时为 0。下一次尝试 = 本值 + 1。 */
|
|
372
|
+
maxAttemptNo(taskId) {
|
|
373
|
+
const row = this.db
|
|
374
|
+
.prepare('SELECT COALESCE(MAX(attempt_no), 0) AS n FROM worker_results WHERE task_id = ?')
|
|
375
|
+
.get(taskId);
|
|
376
|
+
return row?.n ?? 0;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* executions 侧的最大 attempt_no。
|
|
380
|
+
*
|
|
381
|
+
* **不能只看 worker_results 来编下一个 attempt 号**:executor 客观失败、
|
|
382
|
+
* 被 abort、以及重载后被回收的僵尸执行都只有 Execution 行、没有 Claim 行。
|
|
383
|
+
* 只按 Claim 计数会重复发号,撞上 `UNIQUE(task_id, attempt_no)`。
|
|
384
|
+
* 下一次尝试号必须取两者的最大值再 +1(见 nextAttemptNo)。
|
|
385
|
+
*/
|
|
386
|
+
maxExecutionAttemptNo(taskId) {
|
|
387
|
+
const row = this.db
|
|
388
|
+
.prepare('SELECT COALESCE(MAX(attempt_no), 0) AS n FROM executions WHERE task_id = ?')
|
|
389
|
+
.get(taskId);
|
|
390
|
+
return row?.n ?? 0;
|
|
391
|
+
}
|
|
392
|
+
/** 下一次执行应使用的 attempt 号:Claim 与 Execution 两侧取大再 +1。 */
|
|
393
|
+
nextAttemptNo(taskId) {
|
|
394
|
+
return Math.max(this.maxAttemptNo(taskId), this.maxExecutionAttemptNo(taskId)) + 1;
|
|
395
|
+
}
|
|
396
|
+
insertWorkerResult(row) {
|
|
397
|
+
this.db
|
|
398
|
+
.prepare(`INSERT INTO worker_results
|
|
399
|
+
(result_id, task_id, attempt_no, worker_binding_id, session_id, outcome, result_json, created_at)
|
|
400
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
401
|
+
.run(row.result_id, row.task_id, row.attempt_no, row.worker_binding_id, row.session_id, row.outcome, row.result_json, row.created_at);
|
|
402
|
+
return row;
|
|
403
|
+
}
|
|
404
|
+
// ── executions(Phase 3 第 7 张表;运行事实,非治理事实)──────
|
|
405
|
+
getExecution(executionId) {
|
|
406
|
+
const rows = this.db
|
|
407
|
+
.prepare('SELECT * FROM executions WHERE execution_id = ?')
|
|
408
|
+
.all(executionId);
|
|
409
|
+
return rows[0] ?? null;
|
|
410
|
+
}
|
|
411
|
+
listExecutions(taskId) {
|
|
412
|
+
return this.db
|
|
413
|
+
.prepare('SELECT * FROM executions WHERE task_id = ? ORDER BY attempt_no')
|
|
414
|
+
.all(taskId);
|
|
415
|
+
}
|
|
416
|
+
latestExecution(taskId) {
|
|
417
|
+
const rows = this.db
|
|
418
|
+
.prepare('SELECT * FROM executions WHERE task_id = ? ORDER BY attempt_no DESC LIMIT 1')
|
|
419
|
+
.all(taskId);
|
|
420
|
+
return rows[0] ?? null;
|
|
421
|
+
}
|
|
422
|
+
/** 王国内所有未终结的 Execution(人物应当在场的那些)。 */
|
|
423
|
+
listLiveExecutions(kingdomId) {
|
|
424
|
+
return this.db
|
|
425
|
+
.prepare(`SELECT e.* FROM executions e
|
|
426
|
+
JOIN tasks t ON t.task_id = e.task_id
|
|
427
|
+
JOIN territories te ON te.territory_id = t.territory_id
|
|
428
|
+
WHERE te.kingdom_id = ?
|
|
429
|
+
AND e.state IN ('STARTING', 'RUNNING', 'PAUSED')
|
|
430
|
+
ORDER BY e.started_at`)
|
|
431
|
+
.all(kingdomId);
|
|
432
|
+
}
|
|
433
|
+
insertExecution(row) {
|
|
434
|
+
this.db
|
|
435
|
+
.prepare(`INSERT INTO executions
|
|
436
|
+
(execution_id, task_id, attempt_no, worker_binding_id, session_id, state, detail,
|
|
437
|
+
started_at, heartbeat_at, ended_at, pause_requested_at)
|
|
438
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
439
|
+
.run(row.execution_id, row.task_id, row.attempt_no, row.worker_binding_id, row.session_id, row.state, row.detail, row.started_at, row.heartbeat_at, row.ended_at, row.pause_requested_at);
|
|
440
|
+
return row;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* **全库唯一的 executions.state 写入路径**(与 transitionTask 同构)。
|
|
444
|
+
*
|
|
445
|
+
* 先过 ./execution.ts 的 `transitionExecution()` 校验,非法转移抛错、不落库。
|
|
446
|
+
* 终态自动补 `ended_at`,避免"已结束但没有结束时间"的半截记录。
|
|
447
|
+
*/
|
|
448
|
+
transitionExecution(execution, to, patch = {}) {
|
|
449
|
+
const from = asExecutionState(execution.state);
|
|
450
|
+
const next = transitionExecution(from, to);
|
|
451
|
+
const now = new Date().toISOString();
|
|
452
|
+
const ended = isTerminalExecutionState(next) ? now : execution.ended_at;
|
|
453
|
+
const detail = patch.detail === undefined ? execution.detail : patch.detail;
|
|
454
|
+
const sessionId = patch.sessionId === undefined ? execution.session_id : patch.sessionId;
|
|
455
|
+
const pauseRequestedAt = patch.pauseRequestedAt === undefined
|
|
456
|
+
? execution.pause_requested_at
|
|
457
|
+
: patch.pauseRequestedAt;
|
|
458
|
+
this.db
|
|
459
|
+
.prepare(`UPDATE executions
|
|
460
|
+
SET state = ?, detail = ?, session_id = ?, heartbeat_at = ?, ended_at = ?, pause_requested_at = ?
|
|
461
|
+
WHERE execution_id = ?`)
|
|
462
|
+
.run(next, detail, sessionId, now, ended, pauseRequestedAt, execution.execution_id);
|
|
463
|
+
return {
|
|
464
|
+
...execution,
|
|
465
|
+
state: next,
|
|
466
|
+
detail,
|
|
467
|
+
session_id: sessionId,
|
|
468
|
+
heartbeat_at: now,
|
|
469
|
+
ended_at: ended,
|
|
470
|
+
pause_requested_at: pauseRequestedAt,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
/** 登记暂停请求(不改状态;生效点见 ExecutionRow.pause_requested_at 注释)。 */
|
|
474
|
+
setExecutionPauseRequest(executionId, at) {
|
|
475
|
+
this.db
|
|
476
|
+
.prepare('UPDATE executions SET pause_requested_at = ? WHERE execution_id = ?')
|
|
477
|
+
.run(at, executionId);
|
|
478
|
+
}
|
|
479
|
+
// ── status 汇总 ─────────────────────────────────────────────
|
|
480
|
+
statusSummary() {
|
|
481
|
+
const kingdom = this.getDefaultKingdom();
|
|
482
|
+
if (!kingdom) {
|
|
483
|
+
return '尚未初始化王国。请先执行 /kingdom init 或说“初始化王国”。';
|
|
484
|
+
}
|
|
485
|
+
const territories = this.listTerritories(kingdom.kingdom_id);
|
|
486
|
+
const bindings = this.listBindings(kingdom.kingdom_id);
|
|
487
|
+
const events = this.listEvents(kingdom.kingdom_id, 10);
|
|
488
|
+
const tasks = this.listTasks(kingdom.kingdom_id);
|
|
489
|
+
const lines = [
|
|
490
|
+
`王国:${kingdom.name}(id=${kingdom.kingdom_id})`,
|
|
491
|
+
`Owner:${kingdom.owner_name}(id=${kingdom.owner_id})`,
|
|
492
|
+
`领地数:${territories.length}`,
|
|
493
|
+
`角色绑定:${bindings.length}(${bindings.map(b => b.role_type).join('、') || '无'})`,
|
|
494
|
+
`任务数:${tasks.length}${tasks.length > 0 ? `(${summariseTaskStatuses(tasks)})` : ''}`,
|
|
495
|
+
];
|
|
496
|
+
if (territories.length > 0) {
|
|
497
|
+
lines.push('领地:');
|
|
498
|
+
for (const t of territories) {
|
|
499
|
+
lines.push(` - ${t.name}(${t.status}${t.workspace_path ? `,${t.workspace_path}` : ''})`);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (events.length > 0) {
|
|
503
|
+
lines.push('最近事件:');
|
|
504
|
+
for (const e of events.slice(0, 5)) {
|
|
505
|
+
lines.push(` - ${e.created_at} ${e.event_type}${e.target_id ? ` → ${e.target_id}` : ''}`);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return lines.join('\n');
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
function isExistingDatabase(path) {
|
|
512
|
+
return existsSync(path);
|
|
513
|
+
}
|
|
514
|
+
/** "CREATED×1、REVIEW×2" 形式的状态直方图,供 status 一行展示。 */
|
|
515
|
+
function summariseTaskStatuses(tasks) {
|
|
516
|
+
const counts = new Map();
|
|
517
|
+
for (const t of tasks)
|
|
518
|
+
counts.set(t.status, (counts.get(t.status) ?? 0) + 1);
|
|
519
|
+
return [...counts.entries()].map(([status, n]) => `${status}×${n}`).join('、');
|
|
520
|
+
}
|
|
521
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* dsh-kingdom — Execution 生命周期(Phase 3 / GUI 适配)。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么 Execution 必须独立于 Task
|
|
5
|
+
*
|
|
6
|
+
* `Task.status === 'RUNNING'` **不能**可靠表示"骑士正在工作":
|
|
7
|
+
* REWORK 之后任务立刻回到 RUNNING,但新的 Worker 执行还没启动;
|
|
8
|
+
* 此时 GUI 若按 Task.status 播放工作动画,人物就在假装干活。
|
|
9
|
+
*
|
|
10
|
+
* 所以治理事实(Task)与运行事实(Execution)分开建模:
|
|
11
|
+
*
|
|
12
|
+
* ```text
|
|
13
|
+
* Task.status = 组织对这件事的裁定进度(CREATED..DONE/FAILED)
|
|
14
|
+
* Execution.state = 某一次具体执行此刻的运行状况(STARTING..ABORTED)
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* 一个 Task 的每个 attempt 至多一个 Execution(`UNIQUE(task_id, attempt_no)`)。
|
|
18
|
+
*
|
|
19
|
+
* 本模块与 `./task.ts` 一样**零 schema 依赖**:只描述合法转移。
|
|
20
|
+
*/
|
|
21
|
+
/** Execution 的全部状态。 */
|
|
22
|
+
export const EXECUTION_STATES = [
|
|
23
|
+
'STARTING',
|
|
24
|
+
'RUNNING',
|
|
25
|
+
'PAUSED',
|
|
26
|
+
'COMPLETED',
|
|
27
|
+
'FAILED',
|
|
28
|
+
'ABORTED',
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* 合法转移。
|
|
32
|
+
*
|
|
33
|
+
* - `STARTING → RUNNING`:宿主确认执行已真正开始。
|
|
34
|
+
* - `RUNNING ↔ PAUSED`:暂停/恢复(见 `./execution.ts` 关于 one-shot 的诚实边界说明)。
|
|
35
|
+
* - `* → COMPLETED`:执行交回了合法结构化结果(**注意:这只说明跑完了,不代表任务完成**)。
|
|
36
|
+
* - `* → FAILED`:宿主观察到执行没跑出合法结果。
|
|
37
|
+
* - `* → ABORTED`:被显式终止(会话停止/用户取消),与 FAILED 区分开。
|
|
38
|
+
*/
|
|
39
|
+
export const EXECUTION_TRANSITIONS = {
|
|
40
|
+
STARTING: ['RUNNING', 'FAILED', 'ABORTED'],
|
|
41
|
+
RUNNING: ['PAUSED', 'COMPLETED', 'FAILED', 'ABORTED'],
|
|
42
|
+
PAUSED: ['RUNNING', 'ABORTED', 'FAILED'],
|
|
43
|
+
COMPLETED: [],
|
|
44
|
+
FAILED: [],
|
|
45
|
+
ABORTED: [],
|
|
46
|
+
};
|
|
47
|
+
/** 终态:不再有后续转移,人物 Sprite 应退场。 */
|
|
48
|
+
export const TERMINAL_EXECUTION_STATES = ['COMPLETED', 'FAILED', 'ABORTED'];
|
|
49
|
+
/** 活跃态:人物应当在场(工作或休息)。 */
|
|
50
|
+
export const LIVE_EXECUTION_STATES = ['STARTING', 'RUNNING', 'PAUSED'];
|
|
51
|
+
export class ExecutionTransitionError extends Error {
|
|
52
|
+
constructor(from, to) {
|
|
53
|
+
super(`非法 Execution 状态转移:${from} → ${to}。`
|
|
54
|
+
+ `${from} 的合法后继为 ${EXECUTION_TRANSITIONS[from].length > 0 ? EXECUTION_TRANSITIONS[from].join(' / ') : '(终态,无后继)'}。`);
|
|
55
|
+
this.name = 'ExecutionTransitionError';
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export class UnknownExecutionStateError extends Error {
|
|
59
|
+
constructor(value) {
|
|
60
|
+
super(`未知 Execution 状态 "${value}",合法值:${EXECUTION_STATES.join(' / ')}。`);
|
|
61
|
+
this.name = 'UnknownExecutionStateError';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function isExecutionState(value) {
|
|
65
|
+
return EXECUTION_STATES.includes(value);
|
|
66
|
+
}
|
|
67
|
+
/** 库里读到的 TEXT 收敛为 ExecutionState;不认识就抛(fail-loud,不猜)。 */
|
|
68
|
+
export function asExecutionState(value) {
|
|
69
|
+
if (!isExecutionState(value))
|
|
70
|
+
throw new UnknownExecutionStateError(value);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
export function isTerminalExecutionState(state) {
|
|
74
|
+
return TERMINAL_EXECUTION_STATES.includes(state);
|
|
75
|
+
}
|
|
76
|
+
export function isLiveExecutionState(state) {
|
|
77
|
+
return LIVE_EXECUTION_STATES.includes(state);
|
|
78
|
+
}
|
|
79
|
+
export function canTransitionExecution(from, to) {
|
|
80
|
+
return EXECUTION_TRANSITIONS[from].includes(to);
|
|
81
|
+
}
|
|
82
|
+
/** 状态机唯一入口:校验并返回目标状态,非法即抛。 */
|
|
83
|
+
export function transitionExecution(from, to) {
|
|
84
|
+
if (!canTransitionExecution(from, to))
|
|
85
|
+
throw new ExecutionTransitionError(from, to);
|
|
86
|
+
return to;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../../src/core/execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,uBAAuB;AACvB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,UAAU;IACV,SAAS;IACT,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,SAAS;CACD,CAAA;AAIV;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAsD;IACtF,QAAQ,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC;IAC1C,OAAO,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;IACxC,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,EAAE;CACZ,CAAA;AAED,gCAAgC;AAChC,MAAM,CAAC,MAAM,yBAAyB,GAA8B,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;AAEtG,yBAAyB;AACzB,MAAM,CAAC,MAAM,qBAAqB,GAA8B,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;AAEjG,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IACjD,YAAY,IAAoB,EAAE,EAAU;QAC1C,KAAK,CACH,qBAAqB,IAAI,MAAM,EAAE,GAAG;cAClC,GAAG,IAAI,WAAW,qBAAqB,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CACrH,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAA;IACxC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,KAAa;QACvB,KAAK,CAAC,oBAAoB,KAAK,SAAS,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACxE,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAA;IAC1C,CAAC;CACF;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAChE,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,0BAA0B,CAAC,KAAK,CAAC,CAAA;IACzE,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,KAAqB;IAC5D,OAAO,yBAAyB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAClD,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAqB;IACxD,OAAO,qBAAqB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAoB,EAAE,EAAkB;IAC7E,OAAO,qBAAqB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;AACjD,CAAC;AAED,8BAA8B;AAC9B,MAAM,UAAU,mBAAmB,CAAC,IAAoB,EAAE,EAAkB;IAC1E,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,EAAE,CAAC;QAAE,MAAM,IAAI,wBAAwB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IACnF,OAAO,EAAE,CAAA;AACX,CAAC"}
|