@william2000/dsh-nova-ui-task-board 0.1.0

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.
Files changed (50) hide show
  1. package/README.md +86 -0
  2. package/cordis.patch.yml +13 -0
  3. package/lib/client.js +5641 -0
  4. package/lib/client.js.map +1 -0
  5. package/lib/index.js +4873 -0
  6. package/lib/types/client/NovaTaskBoardSettingsCard.d.ts +17 -0
  7. package/lib/types/client/PlaceholderBoard.d.ts +9 -0
  8. package/lib/types/client/apply-guard.d.ts +25 -0
  9. package/lib/types/client/board/ConfirmDialog.d.ts +12 -0
  10. package/lib/types/client/board/ConfirmTaskDialog.d.ts +8 -0
  11. package/lib/types/client/board/ConvertTaskModal.d.ts +17 -0
  12. package/lib/types/client/board/NewTaskModal.d.ts +6 -0
  13. package/lib/types/client/board/RequirementSplitModal.d.ts +14 -0
  14. package/lib/types/client/board/SplitConfirmDialog.d.ts +9 -0
  15. package/lib/types/client/board/TagEditor.d.ts +6 -0
  16. package/lib/types/client/board/TaskBoard.d.ts +9 -0
  17. package/lib/types/client/board/TaskCard.d.ts +52 -0
  18. package/lib/types/client/board/TaskDetail.d.ts +7 -0
  19. package/lib/types/client/board/status-key.d.ts +8 -0
  20. package/lib/types/client/board-controller.d.ts +274 -0
  21. package/lib/types/client/board-mount.d.ts +10 -0
  22. package/lib/types/client/chat-integration.d.ts +99 -0
  23. package/lib/types/client/drag-utils.d.ts +78 -0
  24. package/lib/types/client/filter.d.ts +42 -0
  25. package/lib/types/client/grouping.d.ts +54 -0
  26. package/lib/types/client/host-api.d.ts +62 -0
  27. package/lib/types/client/index.d.ts +46 -0
  28. package/lib/types/client/legacy-store.d.ts +28 -0
  29. package/lib/types/client/locales.d.ts +202 -0
  30. package/lib/types/client/schedule-presets.d.ts +20 -0
  31. package/lib/types/client/sidebar-entry-core.d.ts +54 -0
  32. package/lib/types/client/sidebar-entry.d.ts +19 -0
  33. package/lib/types/core/context.d.ts +139 -0
  34. package/lib/types/core/cron.d.ts +54 -0
  35. package/lib/types/core/migrate.d.ts +39 -0
  36. package/lib/types/core/model.d.ts +446 -0
  37. package/lib/types/core/recovery.d.ts +25 -0
  38. package/lib/types/core/split.d.ts +81 -0
  39. package/lib/types/core/transitions.d.ts +436 -0
  40. package/lib/types/dsh-home.d.ts +21 -0
  41. package/lib/types/host-automation.d.ts +59 -0
  42. package/lib/types/host-ledger.d.ts +146 -0
  43. package/lib/types/host-routes.d.ts +65 -0
  44. package/lib/types/host-runner.d.ts +177 -0
  45. package/lib/types/host-service.d.ts +291 -0
  46. package/lib/types/index.d.ts +90 -0
  47. package/lib/types/loopback.d.ts +23 -0
  48. package/lib/types/mount-once.d.ts +9 -0
  49. package/lib/types/protocol.d.ts +210 -0
  50. package/package.json +89 -0
@@ -0,0 +1,446 @@
1
+ /**
2
+ * Task board authoritative data model(DSH-REQ-001 §9)。
3
+ *
4
+ * T002 落地完整的 Host 侧数据模型:
5
+ * - 账本文档(§9.1):`LedgerDocument`,`schemaVersion: 2`、单调递增 `revision`、
6
+ * `tasks`、`scheduler`(timeZone/ledgerId/lastTickAt/error/importedSources)、
7
+ * `recentRequests`(最近 256 条幂等缓存);
8
+ * - 任务(§9.2):`TaskRecord` 全字段。`tags/project/order/parentId` 本期落位
9
+ * (默认值/归一化),对应能力分别由 T008/T009/T012 启用;`source` 字段随
10
+ * 对话流转(P3)提前启用;
11
+ * - 执行记录(§9.3):`ExecutionRecord`;
12
+ * - 执行安排(§9.4):`ScheduleRule` 判别联合(cron | one-shot);cron 的到期
13
+ * 计算与 one-shot 的触发消费属 T006/T007,本层只做结构解析与归一化。
14
+ *
15
+ * T010 补齐「自动化收集 + 上下文闭环」(P3,§9.5/§14):
16
+ * - 评论(comments):`TaskComment`(author/body/type/createdAt)挂在任务行;
17
+ * - 上下文快照(context_snapshot):`ContextSnapshot`
18
+ * (goal/keyDecisions/filePaths/lastAiSummary/latestUserFeedback/relatedLinks/
19
+ * updatedAt),每次执行后由 Host 更新,后续调用只注入摘要 + 必要片段(B5);
20
+ * - 产物(artifacts):`Artifact`(type/title/url/contentRef),会话 transcript
21
+ * 即默认产物(执行结算成功时自动记录);
22
+ * - 自动化规则(automation_rules):`AutomationRule` 集合挂在账本文档
23
+ * (trigger=5 段 cron / source=github_issue|bookmark_collector / config /
24
+ * filter.labels / enabled),GitHub Webhook 与收藏收集 cron 共用;
25
+ * - 来源元数据:`TaskRecord.metadata`(Record<string,string>),GitHub Issue
26
+ * 的来源链接 / 书签 URL 等写入此处(§14.1/14.2,供去重与追溯)。
27
+ *
28
+ * 解析/归一化是纯函数(无 fs、无运行时依赖),保证模型可脱离宿主单测;
29
+ * 行级损坏「修复或丢弃 schedule、绝不丢整行」,账本级损坏抛
30
+ * `LedgerSchemaError` 由 HostLedger 走隔离路径(见 host-ledger.ts)。
31
+ */
32
+ /** 账本 schema 版本(不兼容时走损坏隔离路径,见 §9.1)。 */
33
+ export declare const LEDGER_SCHEMA_VERSION: 2;
34
+ /** 幂等缓存保留条数(§11.3:最近 256 条)。 */
35
+ export declare const MAX_REQUEST_CACHE = 256;
36
+ /** 任务生命周期状态,与看板列一一对应(§10.1);`proposed` 为对话流转候选(D7/P3.1)。 */
37
+ export declare const TASK_STATUSES: readonly ["proposed", "backlog", "todo", "running", "done", "failed"];
38
+ /** 任务生命周期状态。 */
39
+ export type TaskStatus = typeof TASK_STATUSES[number];
40
+ /** 任务来源(§9.2,v1.0 字段,P3 随对话流转启用)。 */
41
+ export declare const TASK_SOURCES: readonly ["manual", "conversation", "github_issue", "bookmark_collector", "feishu", "requirement", "other"];
42
+ /** 任务来源。 */
43
+ export type TaskSource = typeof TASK_SOURCES[number];
44
+ /** 执行会话钉住的权限预设 id(`/permission <id>`,§9.2)。 */
45
+ export declare const TASK_PERMISSIONS: readonly ["read-only", "workspace-write", "danger-full-access"];
46
+ /** 执行会话钉住的权限预设 id。 */
47
+ export type TaskPermission = typeof TASK_PERMISSIONS[number];
48
+ /** 执行结果(§9.3)。 */
49
+ export declare const EXECUTION_RESULTS: readonly ["succeeded", "failed", "cancelled"];
50
+ /** 执行结果。 */
51
+ export type ExecutionResult = typeof EXECUTION_RESULTS[number];
52
+ /** 评论类型(§9.5 comments:user_feedback/ai_log/system_event)。 */
53
+ export declare const COMMENT_TYPES: readonly ["user_feedback", "ai_log", "system_event"];
54
+ /** 评论类型。 */
55
+ export type CommentType = typeof COMMENT_TYPES[number];
56
+ /** 产物类型(§9.5 artifacts;会话 transcript 即默认产物 `session`)。 */
57
+ export declare const ARTIFACT_TYPES: readonly ["session", "link", "file", "other"];
58
+ /** 产物类型。 */
59
+ export type ArtifactType = typeof ARTIFACT_TYPES[number];
60
+ /** 自动化收集来源(§14.1/14.2 automation_rules.source)。 */
61
+ export declare const AUTOMATION_SOURCES: readonly ["github_issue", "bookmark_collector"];
62
+ /** 自动化收集来源。 */
63
+ export type AutomationSource = typeof AUTOMATION_SOURCES[number];
64
+ /** 单次执行尝试(§9.3):自己的 id、承载会话(创建后回填)、起止与结算结果。 */
65
+ export interface ExecutionRecord {
66
+ /** 执行尝试 id(uuid)。 */
67
+ id: string;
68
+ /** 承载本次执行的 DSH 会话 id;会话创建后回填,运行中/启动前缺省。 */
69
+ sessionId?: string;
70
+ /** 开始时间(ms epoch)。 */
71
+ startedAt: number;
72
+ /** 结算时间(ms epoch);运行中缺省。 */
73
+ endedAt?: number;
74
+ /** 结算结果;运行中缺省。 */
75
+ result?: ExecutionResult;
76
+ /** 失败/取消原因。 */
77
+ error?: string;
78
+ }
79
+ /** 任务评论(§9.5 comments:author/body/type/createdAt,P3/T010 落地)。 */
80
+ export interface TaskComment {
81
+ /** 评论 id(uuid)。 */
82
+ id: string;
83
+ /** 作者(缺省 'user';'system' 为 Host 侧系统事件)。 */
84
+ author: string;
85
+ /** 正文(已清洗:控制字符剥离、长度封顶)。 */
86
+ body: string;
87
+ /** 评论类型(§9.5)。 */
88
+ type: CommentType;
89
+ /** 创建时间(ms epoch)。 */
90
+ createdAt: number;
91
+ }
92
+ /** 产物记录(§9.5 artifacts:type/title/url/content_ref;会话 transcript 即默认产物)。 */
93
+ export interface Artifact {
94
+ /** 产物 id(uuid)。 */
95
+ id: string;
96
+ /** 产物类型(session/link/file/other)。 */
97
+ type: ArtifactType;
98
+ /** 展示标题。 */
99
+ title: string;
100
+ /** 外链(link 类)。 */
101
+ url?: string;
102
+ /** 内容引用(如会话 id / 文件相对路径)。 */
103
+ contentRef?: string;
104
+ /** 记录时间(ms epoch)。 */
105
+ createdAt: number;
106
+ }
107
+ /**
108
+ * 上下文快照(§9.5 context_snapshot,P3/T010 落地)。
109
+ * 每次执行后由 Host 更新(lastAiSummary 来自会话最近一条 assistant 消息的
110
+ * 文本摘取、latestUserFeedback 来自最近一条 user_feedback 评论、relatedLinks
111
+ * 来自来源 metadata.url);goal/keyDecisions/filePaths 由用户/后续任务维护。
112
+ * 后续调用只注入摘要 + 必要片段(见 core/context.ts 的 composeInjectionContext,
113
+ * B5 调研决定 Host 侧摘取 + 固定 token 预算)。
114
+ */
115
+ export interface ContextSnapshot {
116
+ /** 任务目标(可空;初始可由任务标题/描述派生)。 */
117
+ goal?: string;
118
+ /** 关键决策记录(P3 起,供跨会话续接)。 */
119
+ keyDecisions: string[];
120
+ /** 涉及文件路径(供续接定位)。 */
121
+ filePaths: string[];
122
+ /** 最近一次 AI 执行摘要(Host 执行结算时摘取,长度受 B5 预算约束)。 */
123
+ lastAiSummary?: string;
124
+ /** 最近一条用户反馈(评论 type=user_feedback 的最新正文)。 */
125
+ latestUserFeedback?: string;
126
+ /** 相关链接(来源 metadata.url 等)。 */
127
+ relatedLinks: string[];
128
+ /** 快照更新时间(ms epoch)。 */
129
+ updatedAt: number;
130
+ }
131
+ /**
132
+ * 自动化收集规则(§9.5 automation_rules / §14.1-14.3,P3/T010 落地)。
133
+ * 挂在账本文档级(非任务行):一条规则定义一个外部来源的定时收集行为。
134
+ * - trigger:5 段 cron(收藏收集默认每周日 00:00;GitHub 也可配置轮询兜底);
135
+ * `nextRunAt`/`lastTriggeredAt` 为 Host 独占字段(tick 扫描与收集后维护,
136
+ * 浏览器不可写),与任务 schedule 的 cron 分支同语义(错过跳过不补跑);
137
+ * - source:`github_issue`(GitHub Webhook 推送 + 可选 API 轮询)或
138
+ * `bookmark_collector`(本地收藏收件箱文件,见 host-automation.ts);
139
+ * - config:来源级配置(github_issue:`repo`;bookmark_collector:`filePath`);
140
+ * - filter.labels:GitHub 标签过滤(非空时 Issue 必须命中至少一个标签才收集,
141
+ * §14.1「如仅 bug/enhancement 标签」)。
142
+ */
143
+ export interface AutomationRule {
144
+ /** 规则 id(uuid,浏览器创建时生成)。 */
145
+ id: string;
146
+ /** 是否武装(false = 不参与 tick 扫描与 Webhook 过滤)。 */
147
+ enabled: boolean;
148
+ /** 收集来源。 */
149
+ source: AutomationSource;
150
+ /** 触发:5 段 cron + Host 独占的到期/最近触发时间戳。 */
151
+ trigger: {
152
+ kind: 'cron';
153
+ cron: string;
154
+ nextRunAt?: number;
155
+ lastTriggeredAt?: number;
156
+ };
157
+ /** 来源级配置(均为字符串值)。 */
158
+ config: Record<string, string>;
159
+ /** 过滤器(GitHub 标签;空数组 = 全部接受)。 */
160
+ filter: {
161
+ labels: string[];
162
+ };
163
+ /** 创建时间(ms epoch)。 */
164
+ createdAt: number;
165
+ /** 最后变更时间(ms epoch)。 */
166
+ updatedAt: number;
167
+ }
168
+ /**
169
+ * 执行安排(§9.4 判别联合):一个任务同时只持有一个执行安排,cron 周期定时
170
+ * 或一次性计划(one-shot)二选一。判别联合延续协议层的严格校验风格。
171
+ */
172
+ export type ScheduleRule = {
173
+ kind: 'cron';
174
+ /** 是否武装。 */
175
+ enabled: boolean;
176
+ /** 5 段 cron(分 时 日 月 周),Host 本地时区。 */
177
+ cron: string;
178
+ /** 下次到期点(ms epoch,Host 调度器维护,浏览器不可写)。 */
179
+ nextRunAt?: number;
180
+ /** 最近触发点(ms epoch)。 */
181
+ lastTriggeredAt?: number;
182
+ } | {
183
+ kind: 'one-shot';
184
+ /** 计划执行时刻(ms epoch,Host 本地时区)。 */
185
+ runAt: number;
186
+ /** 触发/消费标记(ms epoch):到点触发执行时写入,防止重启后重复触发。 */
187
+ firedAt?: number;
188
+ };
189
+ /** 看板上的一个任务(§9.2)。 */
190
+ export interface TaskRecord {
191
+ /** 稳定任务 id(uuid),全局唯一。 */
192
+ id: string;
193
+ /** 显示标题(非空,创建时校验)。 */
194
+ title: string;
195
+ /** 长描述,展示于详情页(可空)。 */
196
+ description: string;
197
+ /** 执行时发送给 agent 的 Prompt;空则回退用标题。 */
198
+ prompt: string;
199
+ /** 当前状态(列)。 */
200
+ status: TaskStatus;
201
+ /** 任务来源(P3 随对话流转启用;`requirement` 为需求拆分产物)。 */
202
+ source?: TaskSource;
203
+ /** 创建时间(ms epoch)。 */
204
+ createdAt: number;
205
+ /** 最后变更时间(ms epoch)。 */
206
+ updatedAt: number;
207
+ /** 全部执行记录,最近的在最后。 */
208
+ executions: ExecutionRecord[];
209
+ /** 可选执行安排(cron 或 one-shot,二选一,见 §9.4)。 */
210
+ schedule?: ScheduleRule;
211
+ /** 钉住的工作区(空 = 执行时用最近工作区)。 */
212
+ workspaceId?: string;
213
+ /** 钉住的 agent 预设 id(空 = 部署默认)。 */
214
+ mode?: string;
215
+ /** 钉住的权限预设(空 = 会话默认)。 */
216
+ permission?: TaskPermission;
217
+ /** 归档标记(ms epoch);归档任务离开主看板、只读,定时被解除。 */
218
+ archivedAt?: number;
219
+ /** 标签数组(模块/优先级/技术栈等),默认 [](D9,P2.6 起启用)。 */
220
+ tags: string[];
221
+ /** 所属项目名(D9,P2.6 起启用)。 */
222
+ project?: string;
223
+ /** 父任务 id(需求拆分子任务指向父需求任务,D8,P3.2 起启用)。 */
224
+ parentId?: string;
225
+ /**
226
+ * 列内排序键:同列内唯一(不要求连续,Host 在 reorder/move 时重算,D10,
227
+ * P2.7 起启用);新任务追加到所在列末尾。
228
+ */
229
+ order: number;
230
+ /** 来源元数据(T010,§14.1/14.2):GitHub Issue 链接 / 书签 URL 等;去重与追溯用。 */
231
+ metadata?: Record<string, string>;
232
+ /** 评论(T010,§9.5 comments;默认 [])。 */
233
+ comments: TaskComment[];
234
+ /** 产物记录(T010,§9.5 artifacts;默认 [])。 */
235
+ artifacts: Artifact[];
236
+ /** 上下文快照(T010,§9.5 context_snapshot;每次执行后更新)。 */
237
+ contextSnapshot?: ContextSnapshot;
238
+ }
239
+ /**
240
+ * 新建任务的输入(§11.2 `create` / §12.4 新建表单)。
241
+ * T003 基线不含执行安排(cron/one-shot 属 T006/T007);T008 扩展 project/tags
242
+ * (§9.2,新建表单可选填项目与标签,缺省不落字段/[])。
243
+ */
244
+ export interface NewTaskInput {
245
+ /** 显示标题(非空,trim 后校验)。 */
246
+ title: string;
247
+ /** 长描述(可空)。 */
248
+ description: string;
249
+ /** 执行时发送给 agent 的 Prompt;空则回退用标题。 */
250
+ prompt: string;
251
+ /** 钉住的工作区(空/缺省 = 执行时用最近工作区)。 */
252
+ workspaceId?: string;
253
+ /** 钉住的 agent 预设 id(空/缺省 = 部署默认)。 */
254
+ mode?: string;
255
+ /** 钉住的权限预设(缺省 = 会话默认)。 */
256
+ permission?: TaskPermission;
257
+ /** 所属项目名(T008,可空;trim 后落字段)。 */
258
+ project?: string;
259
+ /** 任意标签(T008,缺省 [];按 normalizeTags 规范化落账)。 */
260
+ tags?: string[];
261
+ }
262
+ /**
263
+ * 任务可编辑字段补丁(§11.2 `update`)。浏览器不可写 Host/runner 独占字段:
264
+ * `schedule.*`、`executions[].result/endedAt`、`archivedAt`、`status` 等一律
265
+ * 不在补丁面内(协议层 exact keys 拒绝)。T008 扩展 project/tags(§9.2:
266
+ * 项目单选可清除、标签数组整体替换,空数组 = 清空)。
267
+ */
268
+ export type TaskUpdatePatch = Partial<Pick<TaskRecord, 'title' | 'description' | 'prompt' | 'workspaceId' | 'mode' | 'permission' | 'project' | 'tags'>>;
269
+ /**
270
+ * 对话流转候选的输入(§11.2 `propose`,T011/P3.1):沿用 NewTaskInput 全部
271
+ * 字段,另加来源会话/消息引用(写入 metadata,供跳回对话追溯,§9.2/§14.4)。
272
+ * 标题/描述/prompt 的清洗(长度/字符/控制字符)由状态机落账层完成
273
+ * (transitions.applyProposeTask,§16.7)。
274
+ */
275
+ export interface ProposeTaskInput extends NewTaskInput {
276
+ /** 来源会话 id(Agent 标记提取 / 手动「转为任务」时写入)。 */
277
+ sourceConversationId?: string;
278
+ /** 来源消息 id(可跳回对话中具体消息;缺省时以 seq 字符串代替)。 */
279
+ sourceMessageId?: string;
280
+ }
281
+ /**
282
+ * 批量候选条目(§11.2 `propose-batch` / §14.5,T012/P3.2):ProposeTaskInput
283
+ * 扩展 `parentId`(父需求任务 id)。校验与落账见 transitions.applyProposeBatch:
284
+ * parentId 必须指向账本内已存在且非自身的任务(禁止环引用,§16.8),创建后
285
+ * 不可改(update 补丁面不含 parentId)。
286
+ */
287
+ export interface BatchProposeItem extends ProposeTaskInput {
288
+ /** 父需求任务 id(需求拆分子任务指向父任务,D8)。 */
289
+ parentId?: string;
290
+ }
291
+ /**
292
+ * 需求拆分请求(§11.2 `start-split` / §12.9 / §14.5,T012/P3.2):用户提交一份
293
+ * 需求文档(粘贴文本或工作区文件路径),Host 启动独立拆分会话(复用执行通道,
294
+ * B8)驱动 agent 按 §14.5 方法论拆分,结算后经父需求任务 propose +
295
+ * propose-batch 落账(全部 proposed,人工确认闸门复用 T011)。
296
+ *
297
+ * - `text` 与 `filePath` 至少提供其一(需求来源);两者都提供时 text 优先内联、
298
+ * filePath 作为来源说明写入父任务描述;
299
+ * - `parentTaskId`:递归拆分入口(§12.9)——对任一任务(含子任务)再发起拆分
300
+ * 时,新建的父需求任务「需求:<标题>」以该任务为父(parentId),子任务再指向
301
+ * 新父任务,形成树状层级。
302
+ */
303
+ export interface SplitRequestInput {
304
+ /** 需求标题(父任务「需求:<标题>」与拆分会话标题)。 */
305
+ title: string;
306
+ /** 粘贴的需求原文(与 filePath 至少其一)。 */
307
+ text?: string;
308
+ /** 工作区内文件相对路径(与 text 至少其一;agent 自行读取文件)。 */
309
+ filePath?: string;
310
+ /** 需求所属项目(父任务与子任务自动带,§14.5 子任务产出结构)。 */
311
+ project?: string;
312
+ /** 默认标签(父任务与子任务自动带;agent 可再细化,见 core/split.ts)。 */
313
+ tags?: string[];
314
+ /** 递归拆分:新父需求任务挂到该任务下(§12.9/§14.5)。 */
315
+ parentTaskId?: string;
316
+ }
317
+ /** 来源会话引用写入 metadata 的键(§9.2/§14.4:可跳回对话)。 */
318
+ export declare const SOURCE_CONVERSATION_META_KEY = "sourceConversationId";
319
+ /** 来源消息引用写入 metadata 的键(§9.2/§14.4:可跳回消息)。 */
320
+ export declare const SOURCE_MESSAGE_META_KEY = "sourceMessageId";
321
+ /** 账本 scheduler 对外快照(不含内部字段 importedSources,见 §11.1 events)。 */
322
+ export interface SchedulerSnapshot {
323
+ /** Host 本地时区。 */
324
+ timeZone: string;
325
+ /** 账本代数(迁移/导入判定)。 */
326
+ ledgerId?: string;
327
+ /** 最近 cron tick(ms epoch)。 */
328
+ lastTickAt?: number;
329
+ /** 可见的调度/恢复错误。 */
330
+ error?: string;
331
+ }
332
+ /** 账本内持久化的 scheduler(含内部字段,仅在文档层可见)。 */
333
+ export interface LedgerScheduler extends SchedulerSnapshot {
334
+ /** 已导入的 v1 来源(§9.1);导入 marker 只在 Host 确认(原子落账)后写入。 */
335
+ importedSources?: string[];
336
+ }
337
+ /** 幂等缓存条目(§11.3)。 */
338
+ export interface RecentRequest {
339
+ requestId: string;
340
+ fingerprint: string;
341
+ }
342
+ /** 账本文档(§9.1)。 */
343
+ export interface LedgerDocument {
344
+ schemaVersion: typeof LEDGER_SCHEMA_VERSION;
345
+ /** 单调递增的版本号;每次原子落账 +1。 */
346
+ revision: number;
347
+ /** 全部任务(含归档)。 */
348
+ tasks: TaskRecord[];
349
+ scheduler: LedgerScheduler;
350
+ /** 最近 256 条幂等缓存,随账本原子持久化。 */
351
+ recentRequests: RecentRequest[];
352
+ /** 自动化收集规则(T010,§9.5 automation_rules)。 */
353
+ automationRules: AutomationRule[];
354
+ }
355
+ /** Host 内部状态快照(revision + tasks 深拷贝 + scheduler + automationRules,不含 power——power 属协议层)。 */
356
+ export interface LedgerState {
357
+ revision: number;
358
+ tasks: TaskRecord[];
359
+ scheduler: SchedulerSnapshot;
360
+ automationRules: AutomationRule[];
361
+ }
362
+ /** 账本级损坏(schema 不兼容/不可解析),由 HostLedger 走隔离路径。 */
363
+ export declare class LedgerSchemaError extends Error {
364
+ constructor(message: string);
365
+ }
366
+ /** 有限数字守卫。 */
367
+ export declare function isFiniteNumber(value: unknown): value is number;
368
+ /** 非空字符串(trim 后)守卫,空串/空白清除钉住字段(对齐参考实现 normalizeTargetId)。 */
369
+ export declare function normalizeOptionalString(value: unknown): string | undefined;
370
+ /** 是否为已知任务状态。 */
371
+ export declare function isTaskStatus(value: unknown): value is TaskStatus;
372
+ /** 是否为已知任务来源。 */
373
+ export declare function isTaskSource(value: unknown): value is TaskSource;
374
+ /** 是否为已知权限预设。 */
375
+ export declare function isTaskPermission(value: unknown): value is TaskPermission;
376
+ /** 是否为已知执行结果。 */
377
+ export declare function isExecutionResult(value: unknown): value is ExecutionResult;
378
+ /** 是否为已知评论类型。 */
379
+ export declare function isCommentType(value: unknown): value is CommentType;
380
+ /** 是否为已知产物类型。 */
381
+ export declare function isArtifactType(value: unknown): value is ArtifactType;
382
+ /** 是否为已知自动化收集来源。 */
383
+ export declare function isAutomationSource(value: unknown): value is AutomationSource;
384
+ export declare function isPlausibleCron(cron: unknown): cron is string;
385
+ /**
386
+ * 归一化一条持久化的执行安排(§9.4 判别联合):
387
+ * - `kind: 'one-shot'` → one-shot 分支;`runAt` 非有限数则整条丢弃;
388
+ * - `kind: 'cron'` 或缺省 kind(v1/v2 旧形状)→ cron 分支;cron 形状非法则整条
389
+ * 丢弃(「修复或丢弃 schedule、绝不丢整行」——坏 schedule 不拖垮任务行);
390
+ * - 其他 kind → 丢弃。
391
+ */
392
+ export declare function normalizeSchedule(value: unknown): ScheduleRule | undefined;
393
+ /** 归一化一条执行记录(§9.3);结构非法返回 undefined。 */
394
+ export declare function normalizeExecution(value: unknown): ExecutionRecord | undefined;
395
+ /**
396
+ * 归一化标签数组(§9.2 默认 []):仅保留字符串元素,逐项 trim、丢弃空白项、
397
+ * 按首次出现顺序去重;缺省/非法 → []。标签是展示/过滤维度的原始字符串,
398
+ * 大小写敏感(`API` 与 `api` 是两个标签),去重不折叠大小写。
399
+ */
400
+ export declare function normalizeTags(value: unknown): string[];
401
+ /** 归一化来源元数据(§14.1/14.2):仅保留字符串键值对;缺省/非法 → undefined。 */
402
+ export declare function normalizeMetadata(value: unknown): Record<string, string> | undefined;
403
+ /** 归一化一条评论(§9.5);结构非法返回 undefined。 */
404
+ export declare function normalizeComment(value: unknown): TaskComment | undefined;
405
+ /** 归一化评论集合(§9.5 comments,默认 []);非法条目丢弃。 */
406
+ export declare function normalizeComments(value: unknown): TaskComment[];
407
+ /** 归一化一条产物(§9.5 artifacts);结构非法返回 undefined。 */
408
+ export declare function normalizeArtifact(value: unknown): Artifact | undefined;
409
+ /** 归一化产物集合(§9.5 artifacts,默认 []);非法条目丢弃。 */
410
+ export declare function normalizeArtifacts(value: unknown): Artifact[];
411
+ /** 归一化上下文快照(§9.5 context_snapshot);结构非法返回 undefined。 */
412
+ export declare function normalizeContextSnapshot(value: unknown): ContextSnapshot | undefined;
413
+ /** 归一化一条自动化规则(§9.5 automation_rules);结构非法返回 undefined。 */
414
+ export declare function normalizeAutomationRule(value: unknown): AutomationRule | undefined;
415
+ /** 归一化自动化规则集合(§9.5 automation_rules,默认 []);非法条目丢弃。 */
416
+ export declare function normalizeAutomationRules(value: unknown): AutomationRule[];
417
+ /**
418
+ * 归一化一条任务行(§9.2)。
419
+ *
420
+ * 结构非法(id/title/description/prompt/createdAt/updatedAt/executions 任一不
421
+ * 符合)→ 返回 undefined(整行丢弃,HostLedger 记入 scheduler.error);
422
+ * 语义非法 → 就地修复:
423
+ * - 未知状态 → `todo`(未来版本的未知状态落入待办而非丢行,对齐参考实现);
424
+ * - 未知 source/permission → undefined;空白 workspaceId/mode/project/parentId
425
+ * → undefined;archivedAt 非有限数 → undefined;
426
+ * - tags 非字符串数组 → [];order 非有限数 → 0(T009 重算列内唯一);
427
+ * - schedule 交给 normalizeSchedule(修复或丢弃,不丢行)。
428
+ */
429
+ export declare function normalizeTask(value: unknown): TaskRecord | undefined;
430
+ /** Host 本地时区(§9.1 scheduler.timeZone)。 */
431
+ export declare function hostTimeZone(): string;
432
+ /**
433
+ * 空账本文档(新账本/损坏隔离后的重建起点)。
434
+ * @param error - 首次持久化即可见的错误(如损坏隔离说明)。
435
+ */
436
+ export declare function emptyLedgerDocument(error?: string): LedgerDocument;
437
+ /**
438
+ * 解析并归一化账本文档(§9.1)。
439
+ *
440
+ * 账本级损坏(非 JSON、根非对象、schemaVersion ≠ 2、tasks 非数组)抛
441
+ * `LedgerSchemaError`,由 HostLedger 隔离原文件(`corrupt-*` 保留原字节)后
442
+ * 以空账本重建。行级损坏(非法任务行、非法执行记录行)丢弃该行并记入
443
+ * `scheduler.error`;`revision` 非负安全整数 → 0;`recentRequests` 仅保留
444
+ * 合法条目并截断到最近 256 条。
445
+ */
446
+ export declare function parseLedgerDocument(raw: string): LedgerDocument;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 加载时恢复(DSH-REQ-001 §17 可恢复性 / §19-7)。
3
+ *
4
+ * Host 崩溃后重启:账本里可能残留 `running` 状态的任务——若其最后一次执行
5
+ * 从未拿到 sessionId(会话还没创建出来进程就死了),该执行永远无法被 runner
6
+ * 结算,必须在此标记 cancelled,否则看板会卡死在幽灵 running 态;若执行已带
7
+ * sessionId,说明会话已真实创建,由 T005 重启后按 sessionId 继续结算,这里不动。
8
+ *
9
+ * 本模块是 T002 的窄恢复逻辑(账本加载职责);T003 的通用 settle 状态机可
10
+ * 吸收/复用同样的语义。
11
+ */
12
+ import type { TaskRecord } from './model.ts';
13
+ /** 无 sessionId 的中断执行被标记 cancelled 的原因文案。 */
14
+ export declare const INTERRUPTED_START_REASON = "host restarted before the execution session was recorded";
15
+ export interface RecoveryResult {
16
+ tasks: TaskRecord[];
17
+ changed: boolean;
18
+ }
19
+ /**
20
+ * 结算中断执行:running 任务 + 最后一条执行 open 且无 sessionId → 置
21
+ * cancelled(endedAt = now,记原因,bump updatedAt),状态按 §10.2
22
+ * `running → settle(cancelled) → todo` 回落待办,避免卡死幽灵 running 态。
23
+ * 其余任务原样保留。
24
+ */
25
+ export declare function settleInterruptedStarts(tasks: readonly TaskRecord[], now: number): RecoveryResult;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * 需求拆分核心(T012/P3.2,DSH-REQ-001 §12.9/§14.5 + 附录 B8 调研定案)。
3
+ *
4
+ * B8 结论(2026-08-23):
5
+ * - **拆分执行通道**:`start-split` action 提交需求(粘贴文本/工作区文件路径)
6
+ * 后,Host 复用 T005 执行通道(runner.launch)启动**独立拆分会话**
7
+ * (标题「需求拆分:<标题>」),按 §14.5 方法论(粒度启发式 + 拆后自检)驱动
8
+ * agent 拆分;会话结束时 Host 读取 transcript,解析结构化标记,经父需求任务
9
+ * propose + `propose-batch` 原子落账(全部 proposed,人工确认闸门复用 T011)。
10
+ * 会话不复用当前对话(不污染聊天记录);成本 = 每次拆分一个独立会话(额度
11
+ * 成本随会话数量线性,递归拆分同理);会话标题可辨识、候选 metadata 携带
12
+ * 拆分会话引用(可跳回追溯,§15)。
13
+ * - **输出契约**:agent 逐条输出单行标记 `⟦task-board:split⟧ 标题 | 描述 | prompt`
14
+ * (与 T011 的 `⟦task-board:propose⟧` 同格式契约,按 `|` 分段),最后一行
15
+ * `⟦task-board:coverage⟧ 覆盖矩阵`。解析为纯函数(本文件),可脱离宿主单测。
16
+ * - **粒度启发式**(§14.5):单一职责、会话边界、单次 3~15 个(超限递归);
17
+ * 拆后自检:覆盖完备 / 无重叠 / 可验收 / 依赖明确;拆分维度:功能模块 /
18
+ * 架构分层 / 交付顺序 / 验收逐条 / 混合。以上全部内嵌于指令模板
19
+ * (composeSplitInstruction),由拆分会话的系统 Prompt 承载。
20
+ * - **父需求任务**(§14.5):不引入独立「需求实体」——拆分结算时创建父任务
21
+ * 「需求:<标题>」(proposed、source=requirement),描述承载需求原文/来源与
22
+ * 覆盖矩阵(P3 产物表落地前存描述);子任务 parentId 指向该父任务;
23
+ * 递归拆分(§12.9)时新父任务以原任务为父(parentId),形成树状层级。
24
+ */
25
+ import type { SplitRequestInput } from './model.ts';
26
+ /** 子任务单行标记(agent 输出契约,与 T011 的 propose 标记同格式)。 */
27
+ export declare const SPLIT_MARKER = "\u27E6task-board:split\u27E7";
28
+ /** 覆盖矩阵单行标记(agent 输出契约;其后内容 = 覆盖矩阵文本)。 */
29
+ export declare const COVERAGE_MARKER = "\u27E6task-board:coverage\u27E7";
30
+ /** 单次拆分的建议数量界下限(§14.5:少于 3 个提示合并)。 */
31
+ export declare const SPLIT_BATCH_MIN = 3;
32
+ /** 单次拆分的建议数量界上限(§14.5:多于 15 个提示递归拆分)。 */
33
+ export declare const SPLIT_BATCH_MAX = 15;
34
+ /** 父需求任务描述的长度封顶(§16.7 清洗:需求原文 + 覆盖矩阵整体封顶)。 */
35
+ export declare const REQUIREMENT_DESCRIPTION_LIMIT = 40000;
36
+ /** 拆分会话(独立执行会话)标题前缀:`需求拆分:<标题>`。 */
37
+ export declare const SPLIT_SESSION_TITLE_PREFIX = "\u9700\u6C42\u62C6\u5206\uFF1A";
38
+ /** 父需求任务标题前缀:`需求:<标题>`(§14.5 父需求任务)。 */
39
+ export declare const REQUIREMENT_PARENT_TITLE_PREFIX = "\u9700\u6C42\uFF1A";
40
+ /** 解析出的一条子任务标记内容(标题必填;描述/prompt 可空)。 */
41
+ export interface SplitMarkerContent {
42
+ title: string;
43
+ description: string;
44
+ prompt: string;
45
+ }
46
+ /** 解析出的整批拆分结果:子任务条目 + 可选的覆盖矩阵文本。 */
47
+ export interface SplitParseResult {
48
+ items: SplitMarkerContent[];
49
+ coverage?: string;
50
+ }
51
+ /**
52
+ * 解析 transcript 中的拆分标记(纯函数,可脱离宿主单测):
53
+ * - 逐行扫描 `⟦task-board:split⟧`,每行一条子任务;行内按 `|` 分段(首段 =
54
+ * 标题,空则丢弃该条;次段 = 描述;其余拼接为 prompt)——与 T011
55
+ * parseProposeMarkers 同契约;
56
+ * - 扫描 `⟦task-board:coverage⟧`,该行标记之后的内容 = 覆盖矩阵文本(首条
57
+ * 为准);无标记 → 无覆盖矩阵;
58
+ * - 其余文本(说明性内容)忽略。
59
+ */
60
+ export declare function parseSplitMarkers(text: string): SplitParseResult;
61
+ /**
62
+ * 需求拆分指令模板(B8:粒度启发式 + 覆盖自检 + 输出 schema,§14.5)。
63
+ * 作为拆分会话(独立执行会话)的首条 Prompt 发送:内嵌需求标题与需求原文
64
+ * (text 优先;filePath 时指示 agent 先读文件),随后是拆分方法论与输出契约。
65
+ * @param input - 拆分请求(title 必填;text/filePath 至少其一)。
66
+ */
67
+ export declare function composeSplitInstruction(input: SplitRequestInput): string;
68
+ /**
69
+ * 构造父需求任务的描述(§14.5:承载需求原文与覆盖矩阵,P3 产物表落地前存
70
+ * 描述):按「需求原文(text)/ 需求来源(filePath)/ 覆盖矩阵」三段拼接。
71
+ * 纯函数;长度封顶与清洗由调用方落账时经 sanitizeCollectedText 完成。
72
+ */
73
+ export declare function buildRequirementDescription(input: {
74
+ text?: string;
75
+ filePath?: string;
76
+ coverage?: string;
77
+ }): string;
78
+ /** 父需求任务标题(§14.5:`需求:<标题>`),清洗后返回;空输入返回空串。 */
79
+ export declare function requirementParentTitle(title: string): string;
80
+ /** 拆分会话标题(`需求拆分:<标题>`),清洗后返回;空输入返回空串。 */
81
+ export declare function splitSessionTitle(title: string): string;