@zhushanwen/subagent-core 0.5.1 → 0.6.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 (68) hide show
  1. package/dist/execution/engine/engines/zcode/reader.d.cts +1 -1
  2. package/dist/execution/engine/engines/zcode/reader.d.ts +1 -1
  3. package/dist/index.cjs +1122 -452
  4. package/dist/index.d.cts +188 -5
  5. package/dist/index.d.ts +188 -5
  6. package/dist/index.js +1133 -463
  7. package/dist/{types-Dv4QhSJ_.d.cts → types-C3fE3R9x.d.cts} +65 -0
  8. package/dist/{types-Dv4QhSJ_.d.ts → types-C3fE3R9x.d.ts} +65 -0
  9. package/dist.bundle/index.cjs +34933 -0
  10. package/package.json +2 -2
  11. package/src/execution/__tests__/agent-registry.test.ts +1 -1
  12. package/src/execution/__tests__/alive-store.test.ts +1 -1
  13. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  14. package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
  15. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  16. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
  17. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  18. package/src/execution/__tests__/config.test.ts +1 -1
  19. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +1 -1
  20. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  21. package/src/execution/__tests__/gc-timer.test.ts +1 -1
  22. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  23. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  24. package/src/execution/__tests__/notify-ledger.test.ts +27 -0
  25. package/src/execution/__tests__/pi-invocation.test.ts +34 -2
  26. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  27. package/src/execution/__tests__/relay-env.test.ts +12 -1
  28. package/src/execution/__tests__/session-file-gc.test.ts +1 -1
  29. package/src/execution/__tests__/spawn-event-adapter.test.ts +2 -2
  30. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  31. package/src/execution/__tests__/start-sync-model-guard.test.ts +1 -1
  32. package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
  33. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +13 -0
  34. package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
  35. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  36. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  37. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  38. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  39. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  40. package/src/execution/collect-coordinator.ts +200 -0
  41. package/src/execution/config.ts +77 -5
  42. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  43. package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
  44. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
  45. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +1 -1
  46. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +1 -1
  47. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +1 -1
  48. package/src/execution/execution-record.ts +7 -0
  49. package/src/execution/finalize-record.ts +15 -11
  50. package/src/execution/notifier.ts +234 -25
  51. package/src/execution/notify-host.ts +21 -1
  52. package/src/execution/record-entry.ts +16 -0
  53. package/src/execution/record-store.ts +161 -30
  54. package/src/execution/subagent-actions-core.ts +62 -6
  55. package/src/execution/subagent-service.ts +416 -7
  56. package/src/execution/sync-rebuild.ts +87 -0
  57. package/src/execution/types.ts +63 -0
  58. package/src/index.ts +1 -1
  59. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  60. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  61. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  62. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  63. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  64. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  65. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  66. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  67. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  68. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ChildProcess } from 'node:child_process';
2
- import { E as EngineCapabilities, P as ProbeReport, A as AgentCallOpts, a as AgentEvent, M as ModelInfo, b as EngineHandleData, c as EngineHandle, d as AgentOutcome, I as InteractAction, e as InteractResult, S as SessionView, f as ExecutionRecord, R as RecordSnapshot, g as SubagentRecord, h as ExecuteOptions, i as AgentResult, j as AgentConfig, k as ResolvedModel, l as AgentResult$1, C as ClosedReason, m as ExecutionOutcome, T as ToolCall, n as AgentEventLogEntry, o as ExecutionStatus, p as ProjectedOutcome, q as SubagentsGlobalConfig, r as ModelRegistryLike, s as ExecutionHandle, t as ExecutionMode, W as WorktreeHandle, u as PatchResult, v as AgentUsage, w as ExecutionTraceNode, x as TracePatch, y as RunStatus, D as DoneReason, z as WorkerLogEntry, B as DisplayItem, F as CancelResponse, G as CloseResponse, H as ForkFromResponse, L as ListResponse, J as MessageResponse, K as BgResponse, N as ExternalState, O as SubagentListItem } from './types-Dv4QhSJ_.cjs';
3
- export { Q as CLOSED_REASONS, U as DEFAULT_AGENT_NAME, V as DirtyWorktreeError, X as ForkDepthExceededError, Y as ReplayedTurn, Z as ResurrectDeniedError, _ as SLUG_MAX_LENGTH, $ as SubagentToolResult, a0 as ToolCallEntry } from './types-Dv4QhSJ_.cjs';
2
+ import { E as EngineCapabilities, P as ProbeReport, A as AgentCallOpts, a as AgentEvent, M as ModelInfo, b as EngineHandleData, c as EngineHandle, d as AgentOutcome, I as InteractAction, e as InteractResult, S as SessionView, f as ExecutionRecord, R as RecordSnapshot, g as SubagentRecord, h as ExecuteOptions, i as AgentResult, j as AgentConfig, k as ResolvedModel, l as AgentResult$1, C as ClosedReason, m as ExecutionOutcome, T as ToolCall, n as AgentEventLogEntry, o as ExecutionStatus, p as ProjectedOutcome, q as SubagentsGlobalConfig, r as ModelRegistryLike, s as ExecutionHandle, t as ExecutionMode, W as WorktreeHandle, u as PatchResult, v as AgentUsage, w as ExecutionTraceNode, x as TracePatch, y as RunStatus, D as DoneReason, z as WorkerLogEntry, B as DisplayItem, F as CancelResponse, G as CloseResponse, H as ForkFromResponse, L as ListResponse, J as MessageResponse, K as BgResponse, N as ExternalState, O as SubagentListItem } from './types-C3fE3R9x.cjs';
3
+ export { Q as CLOSED_REASONS, U as DEFAULT_AGENT_NAME, V as DirtyWorktreeError, X as ForkDepthExceededError, Y as ReplayedTurn, Z as ResurrectDeniedError, _ as SLUG_MAX_LENGTH, $ as SubagentToolResult, a0 as ToolCallEntry } from './types-C3fE3R9x.cjs';
4
4
  import { Worker } from 'node:worker_threads';
5
5
  export { ZCODE_FALLBACK_DEFAULT_MODEL } from './execution/engine/engines/zcode/constants.cjs';
6
6
  import '@xyz-agent/extension-protocol';
@@ -633,15 +633,31 @@ declare class RecordStore {
633
633
  * - 文件不可读(IO 错误,可能暂时)→ 不判终态,落 resumable entry(防御性路径,
634
634
  * IO 恢复后重开可重判)。
635
635
  *
636
+ * [v2 D3] mainSessionFile = 覆写 merge 数据源(主 session 每 id 末条 entry,与 E1
637
+ * 的 scanLastRecordEntries 同款通路):崩溃前的批域标记(collectMode/batchFinalized)
638
+ * 与轮终 result/model 只活在主文件 entry——重建矩阵(buildRecord)的数据源
639
+ * (sidecar/子文件 identity)不含它们,覆写前不 merge 就会被抹掉(v2 §2.2 断链 2:
640
+ * E1 候选集恒空的真根因)。缺省(undefined)时 merge 无源,行为与旧版一致。
641
+ * 参数为追加式第二参(rootSessionFilter 保持首参):既有调用面只传过滤参。
642
+ *
636
643
  * 防重:orphanJudged 实例级缓存(resumable 形态无 sidecar 锚,同进程重复调用跳过;
637
644
  * 终态形态双重防护 = sidecar + 缓存)。调用方:index.ts session_start 恢复段(一次)。
638
645
  */
639
- recoverOrphanRecords(rootSessionFilter?: string): void;
646
+ recoverOrphanRecords(rootSessionFilter?: string, mainSessionFile?: string): void;
640
647
  /**
641
648
  * 单孤儿 record 的终态判定与落 entry(residual-fixes §5.2 三判据 + chat 分流)。
642
649
  * 防重锚(orphanJudged 标记)已由调用方完成。
650
+ *
651
+ * [v2 D3] 覆写前 merge(lastEntry = 主 session 同 id 末条 entry 重建,调用方构建):
652
+ * 覆写是状态迁移不是信息重建,迁移不应丢末条既有信息。三个落 entry 分支(chatMode
653
+ * 分流 / IO 保守 / 终态覆写)统一基于 merge 后的 rec,同款口径。
643
654
  */
644
655
  private finalizeOrphanRecord;
656
+ /** [v2 D3] 孤儿覆写 merge 字段集:末条 entry 的批域标记 + 轮终正文/模型,仅补 rec 侧
657
+ * undefined/空值(model 的空值形态是 ""——light 重建无 model_change entry 时起步
658
+ * 空串),不覆盖已有值。merge 后写 entry 经 reportSubagentRecord →
659
+ * toSubagentRecordEntry 序列化,undefined 字段自然缺省(不引入显式 null)。 */
660
+ private static mergeOrphanLastEntry;
645
661
  /**
646
662
  * [E2E 实测缺口] entry-born 孤儿恢复:register entry 已落主 session、但子 session 文件
647
663
  * 从未创建(父进程死在 spawn 窗口期——register 写点与子进程首笔写入之间的窗口;外部
@@ -663,6 +679,17 @@ declare class RecordStore {
663
679
  /** entry-born 孤儿按无文件判据收敛落 entry:chatMode → resumable(分流语义一致);
664
680
  * 否则 closed+gc+error(子文件由子进程创建,无文件 = 子进程从未开跑,error 方向安全)。 */
665
681
  private finalizeEntryOnlyOrphan;
682
+ /**
683
+ * [E1/U5] sync 批崩溃恢复扫描:主 session 文件「每 id 末条 subagent-record entry」
684
+ * (collectLastRecordEntries + rebuildEntryRecord 组合通路,设计 §3.1.3「标记读取
685
+ * 通路」——batchFinalized 落标 entry 写主 session 文件,本扫描同文件域才可见;禁走
686
+ * collectRecords light 路径,它只读子文件 identity 头+sidecar,主 session 落标
687
+ * entry 不可见)。返回每 id 末条重建的完整 record(含 collectMode/batchFinalized /
688
+ * 终态五字段,损坏 entry 跳过);调用方(service.recoverSyncCollectBatch 的 E1 过滤、
689
+ * recoverOrphanRecords 的覆写 merge)自行取舍。主文件不可读(含新 session 未 flush
690
+ * 的 ENOENT)→ 空数组静默。
691
+ */
692
+ scanLastRecordEntries(mainSessionFile: string | undefined): SubagentRecord[];
666
693
  /** 订阅变更。返回取消订阅函数。 */
667
694
  onChange(listener: ChangeListener): () => void;
668
695
  /** 触发所有监听器(TUI widget/list requestRender)。dispose 后短路。
@@ -2013,8 +2040,25 @@ declare class SubagentService {
2013
2040
  /** [D4-①] 通知簇 host 面(notifyComplete/notifyClosed/pending 注册注销 + notifier
2014
2041
  * 实例封装,原私有通知簇四方法与模块函数的搬移落点——notify-host.ts)。
2015
2042
  * deps 惰性求值(pi/session 级状态运行时可变),行为与原 constructor 内
2016
- * createNotifier(this.piAdapter()) 逐字节等价。session_start revive,shutdown dispose。 */
2043
+ * createNotifier(this.piAdapter()) 逐字节等价。session_start revive,shutdown dispose。
2044
+ * [sync-collect 合并] toNotifyRecord/notify/notifyBatch 随批路由需要由 host 导出
2045
+ * (collectCoordinator 闭包与 E9/E1 直发路径消费,见 notify-host.ts 接口注释)。 */
2017
2046
  private readonly notifyHost;
2047
+ /** collectCoordinator(subagent-sync-collect U2):sync 批缓冲 + 闭合检测 + flush 分流。 */
2048
+ private readonly collectCoordinator;
2049
+ /** [E9] dispose 时已转 async 写账的成员 id(revive 后 flushBatch 防御过滤用)。
2050
+ * 背景:dispose 后同进程 revive(/resume /fork /new)时协调器内部缓冲仍持有已转换
2051
+ * 成员快照(协调器无 drain API,U5 领地不含 collect-coordinator.ts)——若后续新
2052
+ * sync 成员触发闭合,陈旧快照会随批重投(新成员集新 hash,账本跨键不拦)→ 双重
2053
+ * 通知。flushBatch 闭包按本集过滤,陈旧成员零重投。id 唯一 per spawn,无误伤面。 */
2054
+ private readonly e9ConvertedIds;
2055
+ /** [v2 D4] E1 等待分支的 settled 有界重扫状态(null = 未注册)。disposed 后保持
2056
+ * 非 null——同 session 内不再重复注册(补发完成/达限后 settled 边沿已无事可做,
2057
+ * 单注册即单重扫);initSession(revive)置 null 允许新 session 重新注册。
2058
+ * pi.on 无 off(见 armSettledRescan):旧 handler 闭包捕获旧 state,未 disposed 时
2059
+ * 遇 settled 边沿仍会执行,扫描 this.mainSessionFile 当前值(handler 不绑定注册时
2060
+ * 的文件域);dispose 的惰化处置见 dispose()。 */
2061
+ private settledRescanState;
2018
2062
  /** [MF#4][MF#2] fork 深度按 async 调用链传递(AsyncLocalStorage),替代共享可变计数器。
2019
2063
  * 主 session=0;fork 进入子 session 期间推进为子深度,供嵌套 fork 经 ALS 读到自身深度作为
2020
2064
  * parentForkDepth。并发 background fork 各自独立调用链,不再互相压低深度值。
@@ -2049,6 +2093,11 @@ declare class SubagentService {
2049
2093
  * 纯委托同上。PiEngineService 适配器不经此——引擎边界走 piEngineServiceAdapter)。 */
2050
2094
  readonly chatActions: SubagentChatActions;
2051
2095
  private readonly manifestStore;
2096
+ /**
2097
+ * [D6 #7a] records 目录(与 manifestStore 同源同一推导)——屏障失败 warn 带 manifest
2098
+ * 文件路径用(ManifestStore.dir 私有,此处不破封装另存同源值;漂移由构造点同语句保证不发生)。
2099
+ */
2100
+ private readonly recordsDir;
2052
2101
  /**
2053
2102
  * [T1/PS-9] subagent sessionDir(getSubagentSessionDir 推导,与 store 同源同一 rootCwd)。
2054
2103
  * 传给 doFinalizeRecord 的 FinalizeDeps.sessionDir——record.sessionFile 缺失时 finalize
@@ -2088,6 +2137,8 @@ declare class SubagentService {
2088
2137
  /** 孤儿终态恢复委托(RecordStore.recoverOrphanRecords 的唯一调用入口,维持 store
2089
2138
  * private 封装——与 recoverManifestTmpFiles 同模式;[D4] public 面收窄:唯一调用方
2090
2139
  * 是 initSession,转 private)。判定语义见 store 侧注释。
2140
+ * mainSessionFile 随调用透传(v2 D3 覆写 merge 数据源:主文件末条 entry 的批域
2141
+ * 标记与轮终 result/model;initSession 先赋值后恢复,时序就绪)。
2091
2142
  * 随后跑 entry-born 孤儿恢复(无子文件锚的 register-only record,spawn 窗口期死亡,
2092
2143
  * E2E 实测缺口)——主 session 文件经 getMainSessionFile 注入(构造期可空)。 */
2093
2144
  private recoverOrphanRecords;
@@ -2139,6 +2190,107 @@ declare class SubagentService {
2139
2190
  * listener 仍然存活。若 pending-notifications 先于本扩展执行 session_shutdown(后注册
2140
2191
  * 先执行的语义下会如此),listener 已注销,unregister 事件被静默丢弃。这是可接受的
2141
2192
  * 退化——进程退出后两侧状态本就不保证一致,下次 session_start 的 crash recovery 会修正。 */
2193
+ /** [U4 deviation #8 接线] collectSync 预算热读(flush 时读值,与 getCollectSyncDefault
2194
+ * 同款访问链 modelService.getGlobalConfig().collectSync)。节缺失/读失败 → undefined
2195
+ * → notifyBatch 落 buildBatchLlmContent 设计默认值(4000/24000,E5 不炸启动)。
2196
+ * sanitizeCollectSync 保证节存在时两字段必有合法正整数。 */
2197
+ private getCollectSyncBudget;
2198
+ /** [E9 专用] batchFinalized 落标 + manifest fire-and-forget 写(设计 §3.1.5 E9)。
2199
+ * 批通知路径(flush/E1)已改走「manifest 屏障 → 写账 → 纯落标」序列(「通知可达
2200
+ * ⇒ 索引就位」的构造性保证,见 flushBatch 闭包 / runSyncCollectRecoveryScan),
2201
+ * 不再经本 helper;仅 E9 转换的成员保持原形态——其走 async 单条通知(全文注入、
2202
+ * 无指针行消费),manifest 无时序要求,落标后 fire-and-forget 补写(list 后手动
2203
+ * 反查的顺带索引)。
2204
+ * 路径 = getFullRecord 冷路径重建 → appendBatchFinalizedEntry 纯落标 → fire
2205
+ * manifest。getFullRecord 不可达(子 session 文件缺失/已 GC)→ 跳过该成员
2206
+ * (详见 flushBatch 闭包注释)。 */
2207
+ private markMembersBatchFinalized;
2208
+ /** batchFinalized 落标唯一出口(appendEntry 公共末步,纯落标):显式覆写
2209
+ * collectMode/batchFinalized → reportSubagentRecord。覆写动机:recordToSubagent
2210
+ * 投影已含两字段(U5 修复),但 getFullRecord 冷路径含 sidecar/manifest 重建分支
2211
+ * (非 entry 源),显式赋值防非 entry 源重建时丢标记。
2212
+ *
2213
+ * [v2 D1 断链 1] 落标即「离开批 = 通知已/即将送达 = 指针行即将被消费」——成功
2214
+ * 成员走 SP-5 改道 doFinalizeRoundToIdle(不写 manifest),批路径不补写则
2215
+ * records/<sa-id>.json 永不产生、session-reader 反查 0 命中。manifest 写点已从
2216
+ * 本出口的 fire-and-forget 前移至各调用方:批通知路径(flush/E1)在写账前屏障
2217
+ * await 全部落盘(「通知可达 ⇒ 索引就位」的构造性保证);E9 保持落标后
2218
+ * fire-and-forget(async 单条通知无指针行消费,无时序要求)。
2219
+ * rec 两来源(flush 的 getFullRecord 内存全量 / E1 的 rebuildEntryRecord 重建
2220
+ * 快照)必需字段恒齐备(id/agentName←agent/rootSessionId/createdAt←startedAt),
2221
+ * task/slug/parentRecordId 等可选 undefined 自然缺省。 */
2222
+ private appendBatchFinalizedEntry;
2223
+ /** 批成员 manifest(sa- id → sessionFile 反查索引)写的唯一投影点(D2 字段投影 +
2224
+ * status 如实投影:成功成员此刻 record 实态 running+resumable → "running",后续
2225
+ * message upgrade 走完整 finalize 时 Step 4 原子覆盖为 "closed")。
2226
+ * 返回原始 promise 不吞错——失败语义由调用方定:批通知路径经
2227
+ * writeSyncBatchManifestBarrier 的 allSettled(debug 不阻断写账);E9 经
2228
+ * fire-and-forget catch(debug 不阻断落标)。 */
2229
+ private writeBatchMemberManifest;
2230
+ /** [时序屏障] 批通知路径(flush/E1)专用:成员 manifest 并行写 + await 全部完成
2231
+ * (allSettled)后才允许写账投递——「通知可达 ⇒ 索引就位」的构造性保证。写失败
2232
+ * 不阻断(best-effort 语义与 doFinalizeRecord Step 4 一致:反查索引缺失只影响指针行
2233
+ * 反查,session-reader 错误文案已指引绝对路径兜底,不构成写账失败);warn 留痕
2234
+ * (D6 #7a / SC-1:屏障失败意味着该成员指针行反查索引缺失,debug 级在排障时不可见)。 */
2235
+ private writeSyncBatchManifestBarrier;
2236
+ /** [E9] dispose 时批未闭合:缓冲中已终态未通知成员逐条转 async 语义写账(放弃攒批)
2237
+ * + 落 batchFinalized 标记(E1 重建扫描据此排除,防双重通知),交由既有 shutdown
2238
+ * flush / resume 重放兑底;仍在跑的成员走现有退出路径(disposeAllRecords 关闭,
2239
+ * 与 async 一致)。写账用 notifier.notify 现有通路(ledger.record + attemptDeliver)。
2240
+ * 源序:写账先于落标——写账后崩溃 → E1 重建收该成员,但 async notifyId 与批 hash
2241
+ * 跨键不拦的重发属设计披露的 E9 残余窗(at-least-once 良性,PS-17 同族,v1 接受)。 */
2242
+ private convertPendingSyncBufferToAsync;
2243
+ /**
2244
+ * [E1] sync 批崩溃恢复钩子(设计 §3.1.5 E1,index.ts session_start 恢复编排处调用,
2245
+ * 须晚于 initSession——孤儿终态恢复先行收敛 running 成员,「全员终态」判定才可达):
2246
+ *
2247
+ * - 扫描主 session 文件每 id 末条 subagent-record entry(store.scanLastRecordEntries,
2248
+ * collectLastRecordEntries 同构 + 投影扩展含 collectMode/batchFinalized + 终态五
2249
+ * 字段;禁走 collectRecords light 路径——主 session 落标 entry 对它不可见);
2250
+ * - 只收 collectMode=sync 且无 batchFinalized 的成员(排除已通过批 flush 或 E9
2251
+ * 转换离场的,防双重通知),按 rootSessionId 过滤当前根;
2252
+ * - 全员终态且账本无同成员集批记录 → manifest 屏障(await 落盘,「通知可达 ⇒
2253
+ * 索引就位」构造性保证,与 flushBatch 同款)→ notifyBatch 补发(内容 = 末条
2254
+ * entry 终态快照;账本 record 同 hash 幂等拒绝 = 已投递/已在账,两种结局都算
2255
+ * 「已处理」);
2256
+ * - 仍有 running → 本次不动,注册 settled 有界重扫(D4,见 armSettledRescan)——
2257
+ * 成员延迟终态(主 agent 冷路径 resume → 正常流落 entry)由 settled 边沿驱动
2258
+ * 重扫收敛,不再依赖「下次 session_start」作唯一再驱动(v2 §2.4 断链 4);
2259
+ * running 口径与协调器同构
2260
+ * (resumable 豁免,v2 D3——覆写不可达的防御分支残余不被误判「仍在跑」);
2261
+ * - 补发尝试后统一补 batchFinalized 标记(账本拒绝也算已投递;直接用末条重建快照
2262
+ * 落标不经 getFullRecord——子文件缺失/已 GC 时标记仍可落盘,窗口自愈不依赖二次
2263
+ * 重启;补标自身崩溃重入幂等收敛,末条 entry last-writer-wins)。
2264
+ *
2265
+ * async 化(时序屏障修复):返回 Promise 但**内部自捕获不外抛**——宿主 index.ts
2266
+ * session_start 以同步 try/catch 调用(其 catch 兑现不到 promise 内的异常),
2267
+ * 自捕获维持同款 warn 容错语义,浮动调用零适配、不产生 unhandled rejection。
2268
+ *
2269
+ * [U8 拆批修复] 与协调器合批排程无交集:E1 只在 session_start 编排处运行(此前
2270
+ * dispose 已取消挂起排程),补发直走 notifier.notifyBatch 不经协调器;异常时序
2271
+ * 相撞由账本 sync-batch:<hash> 幂等拒绝兜底。
2272
+ */
2273
+ recoverSyncCollectBatch(): Promise<void>;
2274
+ /** [E1/D4] 单次「扫描→判定→可达则补发+落标」,E1 首扫与 settled 重扫共用同一实现
2275
+ * (防两处复制粘贴分岔)。三态返回:idle(无 sync 候选——已全部落标/E9 转换/异根,
2276
+ * 无事可等)/ waiting(仍有 running 成员,本次不动)/ dispatched(全员终态,已补发
2277
+ * +统一落标)。async:补发前有 manifest 屏障 await(见函数头 E1 注释)。 */
2278
+ /** 返回 outcome + waitingIds(达限 warn 需滞留成员 id,D6 #7b——仅 waiting 态非空)。 */
2279
+ private runSyncCollectRecoveryScan;
2280
+ /** [v2 D4] 注册 agent_settled 有界重扫(幂等:settledRescanState 非 null 不叠加注册
2281
+ * ——E1 现仅 session_start 单调用点,守卫是防第二入口引入时的注册叠加断言面)。
2282
+ * 每次 settled 边沿重跑同一 E1 扫描(runSyncCollectRecoveryScan):dispatched
2283
+ * (补发+落标完成,scan 的 warn 已留痕)或 idle(候选已被其他通路落标)→ disposed;
2284
+ * 累计 SETTLED_RESCAN_LIMIT 次仍在等 → disposed + warn 留痕(D6 #7b / SC-2:达限
2285
+ * 放弃重扫意味着滞留成员的批通知要等下次 session_start 才收敛,含滞留 id 的 warn
2286
+ * 是唯一线索,debug 级排障不可见;后续事件零处理,下次 session_start 再收敛)。
2287
+ * pi.on 无 off(0.84.4 实装)——disposed 标志包装兑现退订(scheduler extension
2288
+ * index.ts subscribeSettled 同款先例)。P-settled 定谳(0.84.4 dist 实装证据):
2289
+ * pi.on 为 per-extension 列表分发——loader.js `on()` 把 handler push 进
2290
+ * extension.handlers.get(event) 数组(非覆盖),runner.js `emit()` 对全部
2291
+ * extension 的全部 handler 逐一 await;故本注册与 ledger host 经
2292
+ * piAdapter.onAgentSettled 注册的 settled 分发互不干扰,无需降级并入 host 链。 */
2293
+ private armSettledRescan;
2142
2294
  dispose(): void;
2143
2295
  /**
2144
2296
  * [T4④ / PS-5] shutdown flush 被门拦时把未投递 pending 复写落盘(供重启 replay)。
@@ -2332,6 +2484,17 @@ declare class SubagentService {
2332
2484
  * [perf] 磁盘源为 light(头部 identity + 状态,无 eventLog/result/turns 等重数据)
2333
2485
  * ——列表/补全/hasRunning 够用;详情场景调 getFullRecord(id) 懒加载补齐。 */
2334
2486
  private collectRecords;
2487
+ /**
2488
+ * collectSync.default 当前生效值(subagent-sync-collect U2,偏差#3 接线:
2489
+ * startHandler 缺省 collect 解析用)。
2490
+ * config 未配/读失败 → DEFAULT_COLLECT_SYNC.default 兜底(E5 不炸启动)。
2491
+ * 新 session 生效语义与 engine 配置一致(globalConfig 由 ModelConfigService
2492
+ * reloadGlobalConfig 刷新)。
2493
+ */
2494
+ /** collectSync 节单读取点(S9,code-simplify):「读节」一处,「投影成 default 或
2495
+ * budget」各自 accessor 负责(getCollectSyncDefault / getCollectSyncBudget)。 */
2496
+ private collectSyncSection;
2497
+ getCollectSyncDefault(): "async" | "sync";
2335
2498
  /** [perf] 单 record 详情懒加载(全量:eventLog/displayItems/result/turns/tokens)。
2336
2499
  * 内存 running record 直接投影;磁盘 record 全量重建(per-file 缓存,stat 戳校验)。
2337
2500
  * 返回 undefined:id 不存在于内存与磁盘。 */
@@ -3826,6 +3989,18 @@ interface SubagentRecordEntryData {
3826
3989
  journalPath?: string;
3827
3990
  poolKey: string;
3828
3991
  };
3992
+ /**
3993
+ * 同步收集模式标记(subagent-sync-collect 设计 §3.1.3,U1 foundation)。
3994
+ * undefined = async(缺省语义,旧 entry 零迁移——undefined 经 JSON.stringify 自然缺省)。
3995
+ * 消费方:U5 rebuildEntryRecord 投影扩展 + E1 重建扫描。
3996
+ */
3997
+ collectMode?: "sync";
3998
+ /**
3999
+ * 离开批终局标记(subagent-sync-collect 设计 §3.1.3,U1 foundation)。两出口统一
4000
+ * 落标(批闭合 flush / E9 dispose 转换,均 appendEntry 持久化)。undefined =
4001
+ * 未离开批 / 旧 entry 零迁移。消费方:U5 E1 重建扫描只收无标记成员(防双重通知)。
4002
+ */
4003
+ batchFinalized?: boolean;
3829
4004
  }
3830
4005
  /** SubagentRecord → 自描述 entry data(快照投影,不 mutate 源)。
3831
4006
  *
@@ -4035,6 +4210,14 @@ interface StartHandlerInput {
4035
4210
  idleTimeoutMs?: number;
4036
4211
  /** 执行引擎(三层路由第一层:本参数 > agent frontmatter engine > config defaultEngine)。 */
4037
4212
  engine?: string;
4213
+ /**
4214
+ * 同步收集模式(subagent-sync-collect U1 foundation)。undefined = config
4215
+ * collectSync.default(缺省 "async")。schema 层枚举限 "async"|"sync";运行时
4216
+ * 宽收 string 与 engine 字段同风格(pi 工具框架把 schema Static 解析为 string;
4217
+ * 非法值 ≠ "sync" 按 async 处理,E4 守卫用精确 "sync" 判定)。透传
4218
+ * service.execute(ExecuteOptions.collect;record.collectMode 落点归 U2 接线)。
4219
+ */
4220
+ collect?: string;
4038
4221
  }
4039
4222
  /** start 领域对象(宿主 adapter 包成 bg 工具结果)。 */
4040
4223
  type StartHandlerResult = {
@@ -6152,6 +6335,6 @@ declare function boundedPrettySerialize(value: unknown, budget: number): string;
6152
6335
  * docs/design/subagent-core-sink-design.md(sink 下沉收口扩面,2026-08-31);
6153
6336
  * 宿主接入示例见包 README(§3.4 core_host_not_configured 恢复指引的落点)。
6154
6337
  */
6155
- declare const CORE_PACKAGE_VERSION = "0.5.1";
6338
+ declare const CORE_PACKAGE_VERSION = "0.6.0";
6156
6339
 
6157
6340
  export { AGENT_REF_EXT, AgentCall, AgentCallOpts, type AgentEntry, AgentEvent, AgentEventLogEntry, AgentOutcome, type AgentProfile, AgentRegistry, AgentResult, type AgentRunner, type ArgKeySet, type ArgMetaOptions, type ArgMetaWarning, type AtomicTmpRef, type AtomicWriteFileOptions, type AtomicWriteOptions, BG_MESSAGE, BgResponse, Budget, CORE_PACKAGE_VERSION, type CachedWorkflowMeta, type CancelHandlerInput, type CancelHandlerResult, CancelResponse, type ChangeListener, type ChannelHandler, type CleanupStaleTmpOptions, type CleanupStaleTmpResult, type CleanupWorktreeOptions, type CloseHandlerInput, type CloseHandlerResult, CloseResponse, ClosedReason, type CollectWorktreePatchOptions, type ConcurrencyPool, type CoreLogger, type CreateConcurrencyPoolOptions, DEFAULT_DATA_ROOT, DEFAULT_ENGINE_ID, DEFAULT_LIST_LIMIT, DEFAULT_PROVIDER_ID, DEFAULT_SAVE_MIN_INTERVAL_MS, DEFAULT_STATE_MAX_RUNS, DEFAULT_WORKFLOW_SAVED_DIR, DEFAULT_WORKFLOW_TMP_DIR, DialogGlobalQueue, type DiscoveredResource, type DiscoveryRoot, DisplayItem, DoneReason, EngineCapabilities, EngineHandle, EngineHandleData, type EnginePort, type EngineRouteOptions, type EngineRouteResult, type EngineRouting, type EngineRoutingInput, type EngineRoutingSource, type EngineRunResult, ExecutionMode, ExecutionOutcome, ExecutionRecord, ExecutionStatus, ExecutionTraceNode, ExternalState, FORK_FROM_DEFAULT_PROMPT, FileRunStore, type FinalizeRunOptions, type ForkFromHandlerInput, type ForkFromHandlerResult, ForkFromResponse, type GenerateWorkflowScriptOptions, type GenerateWorkflowScriptResult, GitRunError, type GlobalConfigReadResult, type HostServices, IDENTITY_CUSTOM_TYPE, INDEX_FILENAME, InteractAction, InteractResult, type InvalidAgentRefMessageOptions, type LauncherDeps, type LifecycleDeps, type LintFinding, type LintResult, type ListFormatOptions, type ListHandlerInput, type ListHandlerResult, ListResponse, type ListWorktreePorcelainOptions, type LogLevel, MAX_LIST_LIMIT, MAX_RETAINED_DONE_RUNS, MAX_TIMER_DELAY_MS, type MessageHandlerInput, type MessageHandlerResult, MessageResponse, ModelConfigService, type ModelConfigServiceInit, type ModelEntry, ModelInfo, type ModelListFormatOptions, type ModelReasoningInfo, NOTIFY_CONTRACT, type NormalizeWorkflowRefOptions, type NormalizedArgs, type NormalizedWorkflowRef, type NotifyDomainPorts, type NotifyLedgerHost, type PatchBaselineAnchor, ProbeReport, type QueuePolicy, RecordStore, type RecordStorePi, type RecoverCrashedRunsHooks, type RecoverCrashedRunsResult, type ResourceKind, type ResourceSource, type RunContext, type RunSnapshot, type RunSpec, type RunState, RunStatus, type RunStore, SAFE_ID_RE, SNAPSHOT_VERSION, SUBAGENT_RECORD_CUSTOM_TYPE, type ScanConfig, SessionView, type StartHandlerInput, type StartHandlerResult, type StatusFilter, type SubagentIdentityData, SubagentListItem, SubagentRecord, type SubagentRecordEntryData, SubagentService, type SubagentServiceInit, SubagentStream, SubprocessAgentRunner, THINKING_ORDER, Trace, type UiChannelRegistry, WORKFLOW_REF_EXT, WORKFLOW_REF_RESERVED_NAMES, type WorkerHandlers, type WorkerHost, WorkerHostImpl, WorkerLogEntry, type WorkflowDirOptions, type WorkflowEntry, type WorkflowMeta, type WorkflowRefInvalidReason, WorkflowRun, type WorkflowRunMeta, type WorkflowRunResult, type WorkflowRunSummary, type WorkflowScanConfig, WorkflowScript, type WorkflowScriptRegistry, WorkflowScriptRegistryImpl, type WorkflowSource, WorktreeManager, type WorktreePatchResult, type ZcodeEngineDeps, ZcodeTaskShapeError, abortRun, argKeysFromMeta, assertSafeId, atomicTmpPathFor, bestEffort, bindNotifyLedgerHost, boundedPrettySerialize, buildEngineModelsPromptAppend, buildSubagentEngineSection, cancelHandler, cleanupStaleTmpFiles, cleanupWorktree, clearSkillPathCache, closeHandler, closeOutInFlightCalls, collectWorktreePatch, computeElapsedSeconds, configureCore, configureNotifyDomain, countAllToolCalls, createConcurrencyPool, createSubagentService, createUiRequestHandlerForMode, createZcodeEngine, deleteWorkflow, deriveOutcome, discoverAgents, discoverResources, discoverWorkflows, displayAgentName, endedMessageGuard, escapeXml, evictDoneRunsBeyondCap, executeNestedWorkflow, finalizeRun, findFlattenedArgKeys, findWorkspaceRoot, forkFromHandler, formatAgentList, formatModelList, formatWorkflowList, fromRunSnapshot, generateWorkflowScript, getAllToolCalls, getBoundNotifyLedger, getCachedFileContent, getCachedParsed, getHostServices, getLogger, getModelConfigService, getOrCreateChannelRegistry, getSubagentService, getWorkflow, getWorkflowByPath, gitRun, hasApiKey, invalidAgentRefMessage, invalidateCache, isProcessAlive, isResumable, isSafeId, isScriptRunning, isTreeDirty, killAllSpawnedChildren, killRecordChildWithEscalation, lintScript, listHandler, listStaleTmpFiles, listWorktreePorcelain, loadWorkflowScriptByPath, loadWorkflows, makeSerializeFailedResult, mapExternalState, maxTurnsToWatchdogMs, maybeCleanupExpiredSessionFiles, messageHandler, normalizeArgsByMeta, normalizeEngineId, normalizeRef, normalizeWorkflowRef, notifyGateAllowsDelivery, parseAgentProfile, parseAtomicTmpPath, parseEngineHandle, parseResourceMeta, parseResourceMetaDetailed, postBudgetUpdate, projectLiveProgress, projectOutcome, readGlobalConfig, readSubagentHistoryMessages, recordToListItem, recoverCrashedRuns, registerPiEngine, registerZcodeEngine, renderXmlSection, resetRebuildFailureInjectionForTest, routeEngine, runAndWait, runSummary, runWorkflow, saveWorkflow, scheduleTimeBudget, setModelConfigService, setSubagentService, sortByCodepoint, splitZcodeModelRef, startHandler, summarizeDescription, syncEnginesFile, terminateRunningRuns, toRunSnapshot, toSubagentRecordEntry, wrapForkFromPrompt, writeAtomicFile, writeAtomicFileSync };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ChildProcess } from 'node:child_process';
2
- import { E as EngineCapabilities, P as ProbeReport, A as AgentCallOpts, a as AgentEvent, M as ModelInfo, b as EngineHandleData, c as EngineHandle, d as AgentOutcome, I as InteractAction, e as InteractResult, S as SessionView, f as ExecutionRecord, R as RecordSnapshot, g as SubagentRecord, h as ExecuteOptions, i as AgentResult, j as AgentConfig, k as ResolvedModel, l as AgentResult$1, C as ClosedReason, m as ExecutionOutcome, T as ToolCall, n as AgentEventLogEntry, o as ExecutionStatus, p as ProjectedOutcome, q as SubagentsGlobalConfig, r as ModelRegistryLike, s as ExecutionHandle, t as ExecutionMode, W as WorktreeHandle, u as PatchResult, v as AgentUsage, w as ExecutionTraceNode, x as TracePatch, y as RunStatus, D as DoneReason, z as WorkerLogEntry, B as DisplayItem, F as CancelResponse, G as CloseResponse, H as ForkFromResponse, L as ListResponse, J as MessageResponse, K as BgResponse, N as ExternalState, O as SubagentListItem } from './types-Dv4QhSJ_.js';
3
- export { Q as CLOSED_REASONS, U as DEFAULT_AGENT_NAME, V as DirtyWorktreeError, X as ForkDepthExceededError, Y as ReplayedTurn, Z as ResurrectDeniedError, _ as SLUG_MAX_LENGTH, $ as SubagentToolResult, a0 as ToolCallEntry } from './types-Dv4QhSJ_.js';
2
+ import { E as EngineCapabilities, P as ProbeReport, A as AgentCallOpts, a as AgentEvent, M as ModelInfo, b as EngineHandleData, c as EngineHandle, d as AgentOutcome, I as InteractAction, e as InteractResult, S as SessionView, f as ExecutionRecord, R as RecordSnapshot, g as SubagentRecord, h as ExecuteOptions, i as AgentResult, j as AgentConfig, k as ResolvedModel, l as AgentResult$1, C as ClosedReason, m as ExecutionOutcome, T as ToolCall, n as AgentEventLogEntry, o as ExecutionStatus, p as ProjectedOutcome, q as SubagentsGlobalConfig, r as ModelRegistryLike, s as ExecutionHandle, t as ExecutionMode, W as WorktreeHandle, u as PatchResult, v as AgentUsage, w as ExecutionTraceNode, x as TracePatch, y as RunStatus, D as DoneReason, z as WorkerLogEntry, B as DisplayItem, F as CancelResponse, G as CloseResponse, H as ForkFromResponse, L as ListResponse, J as MessageResponse, K as BgResponse, N as ExternalState, O as SubagentListItem } from './types-C3fE3R9x.js';
3
+ export { Q as CLOSED_REASONS, U as DEFAULT_AGENT_NAME, V as DirtyWorktreeError, X as ForkDepthExceededError, Y as ReplayedTurn, Z as ResurrectDeniedError, _ as SLUG_MAX_LENGTH, $ as SubagentToolResult, a0 as ToolCallEntry } from './types-C3fE3R9x.js';
4
4
  import { Worker } from 'node:worker_threads';
5
5
  export { ZCODE_FALLBACK_DEFAULT_MODEL } from './execution/engine/engines/zcode/constants.js';
6
6
  import '@xyz-agent/extension-protocol';
@@ -633,15 +633,31 @@ declare class RecordStore {
633
633
  * - 文件不可读(IO 错误,可能暂时)→ 不判终态,落 resumable entry(防御性路径,
634
634
  * IO 恢复后重开可重判)。
635
635
  *
636
+ * [v2 D3] mainSessionFile = 覆写 merge 数据源(主 session 每 id 末条 entry,与 E1
637
+ * 的 scanLastRecordEntries 同款通路):崩溃前的批域标记(collectMode/batchFinalized)
638
+ * 与轮终 result/model 只活在主文件 entry——重建矩阵(buildRecord)的数据源
639
+ * (sidecar/子文件 identity)不含它们,覆写前不 merge 就会被抹掉(v2 §2.2 断链 2:
640
+ * E1 候选集恒空的真根因)。缺省(undefined)时 merge 无源,行为与旧版一致。
641
+ * 参数为追加式第二参(rootSessionFilter 保持首参):既有调用面只传过滤参。
642
+ *
636
643
  * 防重:orphanJudged 实例级缓存(resumable 形态无 sidecar 锚,同进程重复调用跳过;
637
644
  * 终态形态双重防护 = sidecar + 缓存)。调用方:index.ts session_start 恢复段(一次)。
638
645
  */
639
- recoverOrphanRecords(rootSessionFilter?: string): void;
646
+ recoverOrphanRecords(rootSessionFilter?: string, mainSessionFile?: string): void;
640
647
  /**
641
648
  * 单孤儿 record 的终态判定与落 entry(residual-fixes §5.2 三判据 + chat 分流)。
642
649
  * 防重锚(orphanJudged 标记)已由调用方完成。
650
+ *
651
+ * [v2 D3] 覆写前 merge(lastEntry = 主 session 同 id 末条 entry 重建,调用方构建):
652
+ * 覆写是状态迁移不是信息重建,迁移不应丢末条既有信息。三个落 entry 分支(chatMode
653
+ * 分流 / IO 保守 / 终态覆写)统一基于 merge 后的 rec,同款口径。
643
654
  */
644
655
  private finalizeOrphanRecord;
656
+ /** [v2 D3] 孤儿覆写 merge 字段集:末条 entry 的批域标记 + 轮终正文/模型,仅补 rec 侧
657
+ * undefined/空值(model 的空值形态是 ""——light 重建无 model_change entry 时起步
658
+ * 空串),不覆盖已有值。merge 后写 entry 经 reportSubagentRecord →
659
+ * toSubagentRecordEntry 序列化,undefined 字段自然缺省(不引入显式 null)。 */
660
+ private static mergeOrphanLastEntry;
645
661
  /**
646
662
  * [E2E 实测缺口] entry-born 孤儿恢复:register entry 已落主 session、但子 session 文件
647
663
  * 从未创建(父进程死在 spawn 窗口期——register 写点与子进程首笔写入之间的窗口;外部
@@ -663,6 +679,17 @@ declare class RecordStore {
663
679
  /** entry-born 孤儿按无文件判据收敛落 entry:chatMode → resumable(分流语义一致);
664
680
  * 否则 closed+gc+error(子文件由子进程创建,无文件 = 子进程从未开跑,error 方向安全)。 */
665
681
  private finalizeEntryOnlyOrphan;
682
+ /**
683
+ * [E1/U5] sync 批崩溃恢复扫描:主 session 文件「每 id 末条 subagent-record entry」
684
+ * (collectLastRecordEntries + rebuildEntryRecord 组合通路,设计 §3.1.3「标记读取
685
+ * 通路」——batchFinalized 落标 entry 写主 session 文件,本扫描同文件域才可见;禁走
686
+ * collectRecords light 路径,它只读子文件 identity 头+sidecar,主 session 落标
687
+ * entry 不可见)。返回每 id 末条重建的完整 record(含 collectMode/batchFinalized /
688
+ * 终态五字段,损坏 entry 跳过);调用方(service.recoverSyncCollectBatch 的 E1 过滤、
689
+ * recoverOrphanRecords 的覆写 merge)自行取舍。主文件不可读(含新 session 未 flush
690
+ * 的 ENOENT)→ 空数组静默。
691
+ */
692
+ scanLastRecordEntries(mainSessionFile: string | undefined): SubagentRecord[];
666
693
  /** 订阅变更。返回取消订阅函数。 */
667
694
  onChange(listener: ChangeListener): () => void;
668
695
  /** 触发所有监听器(TUI widget/list requestRender)。dispose 后短路。
@@ -2013,8 +2040,25 @@ declare class SubagentService {
2013
2040
  /** [D4-①] 通知簇 host 面(notifyComplete/notifyClosed/pending 注册注销 + notifier
2014
2041
  * 实例封装,原私有通知簇四方法与模块函数的搬移落点——notify-host.ts)。
2015
2042
  * deps 惰性求值(pi/session 级状态运行时可变),行为与原 constructor 内
2016
- * createNotifier(this.piAdapter()) 逐字节等价。session_start revive,shutdown dispose。 */
2043
+ * createNotifier(this.piAdapter()) 逐字节等价。session_start revive,shutdown dispose。
2044
+ * [sync-collect 合并] toNotifyRecord/notify/notifyBatch 随批路由需要由 host 导出
2045
+ * (collectCoordinator 闭包与 E9/E1 直发路径消费,见 notify-host.ts 接口注释)。 */
2017
2046
  private readonly notifyHost;
2047
+ /** collectCoordinator(subagent-sync-collect U2):sync 批缓冲 + 闭合检测 + flush 分流。 */
2048
+ private readonly collectCoordinator;
2049
+ /** [E9] dispose 时已转 async 写账的成员 id(revive 后 flushBatch 防御过滤用)。
2050
+ * 背景:dispose 后同进程 revive(/resume /fork /new)时协调器内部缓冲仍持有已转换
2051
+ * 成员快照(协调器无 drain API,U5 领地不含 collect-coordinator.ts)——若后续新
2052
+ * sync 成员触发闭合,陈旧快照会随批重投(新成员集新 hash,账本跨键不拦)→ 双重
2053
+ * 通知。flushBatch 闭包按本集过滤,陈旧成员零重投。id 唯一 per spawn,无误伤面。 */
2054
+ private readonly e9ConvertedIds;
2055
+ /** [v2 D4] E1 等待分支的 settled 有界重扫状态(null = 未注册)。disposed 后保持
2056
+ * 非 null——同 session 内不再重复注册(补发完成/达限后 settled 边沿已无事可做,
2057
+ * 单注册即单重扫);initSession(revive)置 null 允许新 session 重新注册。
2058
+ * pi.on 无 off(见 armSettledRescan):旧 handler 闭包捕获旧 state,未 disposed 时
2059
+ * 遇 settled 边沿仍会执行,扫描 this.mainSessionFile 当前值(handler 不绑定注册时
2060
+ * 的文件域);dispose 的惰化处置见 dispose()。 */
2061
+ private settledRescanState;
2018
2062
  /** [MF#4][MF#2] fork 深度按 async 调用链传递(AsyncLocalStorage),替代共享可变计数器。
2019
2063
  * 主 session=0;fork 进入子 session 期间推进为子深度,供嵌套 fork 经 ALS 读到自身深度作为
2020
2064
  * parentForkDepth。并发 background fork 各自独立调用链,不再互相压低深度值。
@@ -2049,6 +2093,11 @@ declare class SubagentService {
2049
2093
  * 纯委托同上。PiEngineService 适配器不经此——引擎边界走 piEngineServiceAdapter)。 */
2050
2094
  readonly chatActions: SubagentChatActions;
2051
2095
  private readonly manifestStore;
2096
+ /**
2097
+ * [D6 #7a] records 目录(与 manifestStore 同源同一推导)——屏障失败 warn 带 manifest
2098
+ * 文件路径用(ManifestStore.dir 私有,此处不破封装另存同源值;漂移由构造点同语句保证不发生)。
2099
+ */
2100
+ private readonly recordsDir;
2052
2101
  /**
2053
2102
  * [T1/PS-9] subagent sessionDir(getSubagentSessionDir 推导,与 store 同源同一 rootCwd)。
2054
2103
  * 传给 doFinalizeRecord 的 FinalizeDeps.sessionDir——record.sessionFile 缺失时 finalize
@@ -2088,6 +2137,8 @@ declare class SubagentService {
2088
2137
  /** 孤儿终态恢复委托(RecordStore.recoverOrphanRecords 的唯一调用入口,维持 store
2089
2138
  * private 封装——与 recoverManifestTmpFiles 同模式;[D4] public 面收窄:唯一调用方
2090
2139
  * 是 initSession,转 private)。判定语义见 store 侧注释。
2140
+ * mainSessionFile 随调用透传(v2 D3 覆写 merge 数据源:主文件末条 entry 的批域
2141
+ * 标记与轮终 result/model;initSession 先赋值后恢复,时序就绪)。
2091
2142
  * 随后跑 entry-born 孤儿恢复(无子文件锚的 register-only record,spawn 窗口期死亡,
2092
2143
  * E2E 实测缺口)——主 session 文件经 getMainSessionFile 注入(构造期可空)。 */
2093
2144
  private recoverOrphanRecords;
@@ -2139,6 +2190,107 @@ declare class SubagentService {
2139
2190
  * listener 仍然存活。若 pending-notifications 先于本扩展执行 session_shutdown(后注册
2140
2191
  * 先执行的语义下会如此),listener 已注销,unregister 事件被静默丢弃。这是可接受的
2141
2192
  * 退化——进程退出后两侧状态本就不保证一致,下次 session_start 的 crash recovery 会修正。 */
2193
+ /** [U4 deviation #8 接线] collectSync 预算热读(flush 时读值,与 getCollectSyncDefault
2194
+ * 同款访问链 modelService.getGlobalConfig().collectSync)。节缺失/读失败 → undefined
2195
+ * → notifyBatch 落 buildBatchLlmContent 设计默认值(4000/24000,E5 不炸启动)。
2196
+ * sanitizeCollectSync 保证节存在时两字段必有合法正整数。 */
2197
+ private getCollectSyncBudget;
2198
+ /** [E9 专用] batchFinalized 落标 + manifest fire-and-forget 写(设计 §3.1.5 E9)。
2199
+ * 批通知路径(flush/E1)已改走「manifest 屏障 → 写账 → 纯落标」序列(「通知可达
2200
+ * ⇒ 索引就位」的构造性保证,见 flushBatch 闭包 / runSyncCollectRecoveryScan),
2201
+ * 不再经本 helper;仅 E9 转换的成员保持原形态——其走 async 单条通知(全文注入、
2202
+ * 无指针行消费),manifest 无时序要求,落标后 fire-and-forget 补写(list 后手动
2203
+ * 反查的顺带索引)。
2204
+ * 路径 = getFullRecord 冷路径重建 → appendBatchFinalizedEntry 纯落标 → fire
2205
+ * manifest。getFullRecord 不可达(子 session 文件缺失/已 GC)→ 跳过该成员
2206
+ * (详见 flushBatch 闭包注释)。 */
2207
+ private markMembersBatchFinalized;
2208
+ /** batchFinalized 落标唯一出口(appendEntry 公共末步,纯落标):显式覆写
2209
+ * collectMode/batchFinalized → reportSubagentRecord。覆写动机:recordToSubagent
2210
+ * 投影已含两字段(U5 修复),但 getFullRecord 冷路径含 sidecar/manifest 重建分支
2211
+ * (非 entry 源),显式赋值防非 entry 源重建时丢标记。
2212
+ *
2213
+ * [v2 D1 断链 1] 落标即「离开批 = 通知已/即将送达 = 指针行即将被消费」——成功
2214
+ * 成员走 SP-5 改道 doFinalizeRoundToIdle(不写 manifest),批路径不补写则
2215
+ * records/<sa-id>.json 永不产生、session-reader 反查 0 命中。manifest 写点已从
2216
+ * 本出口的 fire-and-forget 前移至各调用方:批通知路径(flush/E1)在写账前屏障
2217
+ * await 全部落盘(「通知可达 ⇒ 索引就位」的构造性保证);E9 保持落标后
2218
+ * fire-and-forget(async 单条通知无指针行消费,无时序要求)。
2219
+ * rec 两来源(flush 的 getFullRecord 内存全量 / E1 的 rebuildEntryRecord 重建
2220
+ * 快照)必需字段恒齐备(id/agentName←agent/rootSessionId/createdAt←startedAt),
2221
+ * task/slug/parentRecordId 等可选 undefined 自然缺省。 */
2222
+ private appendBatchFinalizedEntry;
2223
+ /** 批成员 manifest(sa- id → sessionFile 反查索引)写的唯一投影点(D2 字段投影 +
2224
+ * status 如实投影:成功成员此刻 record 实态 running+resumable → "running",后续
2225
+ * message upgrade 走完整 finalize 时 Step 4 原子覆盖为 "closed")。
2226
+ * 返回原始 promise 不吞错——失败语义由调用方定:批通知路径经
2227
+ * writeSyncBatchManifestBarrier 的 allSettled(debug 不阻断写账);E9 经
2228
+ * fire-and-forget catch(debug 不阻断落标)。 */
2229
+ private writeBatchMemberManifest;
2230
+ /** [时序屏障] 批通知路径(flush/E1)专用:成员 manifest 并行写 + await 全部完成
2231
+ * (allSettled)后才允许写账投递——「通知可达 ⇒ 索引就位」的构造性保证。写失败
2232
+ * 不阻断(best-effort 语义与 doFinalizeRecord Step 4 一致:反查索引缺失只影响指针行
2233
+ * 反查,session-reader 错误文案已指引绝对路径兜底,不构成写账失败);warn 留痕
2234
+ * (D6 #7a / SC-1:屏障失败意味着该成员指针行反查索引缺失,debug 级在排障时不可见)。 */
2235
+ private writeSyncBatchManifestBarrier;
2236
+ /** [E9] dispose 时批未闭合:缓冲中已终态未通知成员逐条转 async 语义写账(放弃攒批)
2237
+ * + 落 batchFinalized 标记(E1 重建扫描据此排除,防双重通知),交由既有 shutdown
2238
+ * flush / resume 重放兑底;仍在跑的成员走现有退出路径(disposeAllRecords 关闭,
2239
+ * 与 async 一致)。写账用 notifier.notify 现有通路(ledger.record + attemptDeliver)。
2240
+ * 源序:写账先于落标——写账后崩溃 → E1 重建收该成员,但 async notifyId 与批 hash
2241
+ * 跨键不拦的重发属设计披露的 E9 残余窗(at-least-once 良性,PS-17 同族,v1 接受)。 */
2242
+ private convertPendingSyncBufferToAsync;
2243
+ /**
2244
+ * [E1] sync 批崩溃恢复钩子(设计 §3.1.5 E1,index.ts session_start 恢复编排处调用,
2245
+ * 须晚于 initSession——孤儿终态恢复先行收敛 running 成员,「全员终态」判定才可达):
2246
+ *
2247
+ * - 扫描主 session 文件每 id 末条 subagent-record entry(store.scanLastRecordEntries,
2248
+ * collectLastRecordEntries 同构 + 投影扩展含 collectMode/batchFinalized + 终态五
2249
+ * 字段;禁走 collectRecords light 路径——主 session 落标 entry 对它不可见);
2250
+ * - 只收 collectMode=sync 且无 batchFinalized 的成员(排除已通过批 flush 或 E9
2251
+ * 转换离场的,防双重通知),按 rootSessionId 过滤当前根;
2252
+ * - 全员终态且账本无同成员集批记录 → manifest 屏障(await 落盘,「通知可达 ⇒
2253
+ * 索引就位」构造性保证,与 flushBatch 同款)→ notifyBatch 补发(内容 = 末条
2254
+ * entry 终态快照;账本 record 同 hash 幂等拒绝 = 已投递/已在账,两种结局都算
2255
+ * 「已处理」);
2256
+ * - 仍有 running → 本次不动,注册 settled 有界重扫(D4,见 armSettledRescan)——
2257
+ * 成员延迟终态(主 agent 冷路径 resume → 正常流落 entry)由 settled 边沿驱动
2258
+ * 重扫收敛,不再依赖「下次 session_start」作唯一再驱动(v2 §2.4 断链 4);
2259
+ * running 口径与协调器同构
2260
+ * (resumable 豁免,v2 D3——覆写不可达的防御分支残余不被误判「仍在跑」);
2261
+ * - 补发尝试后统一补 batchFinalized 标记(账本拒绝也算已投递;直接用末条重建快照
2262
+ * 落标不经 getFullRecord——子文件缺失/已 GC 时标记仍可落盘,窗口自愈不依赖二次
2263
+ * 重启;补标自身崩溃重入幂等收敛,末条 entry last-writer-wins)。
2264
+ *
2265
+ * async 化(时序屏障修复):返回 Promise 但**内部自捕获不外抛**——宿主 index.ts
2266
+ * session_start 以同步 try/catch 调用(其 catch 兑现不到 promise 内的异常),
2267
+ * 自捕获维持同款 warn 容错语义,浮动调用零适配、不产生 unhandled rejection。
2268
+ *
2269
+ * [U8 拆批修复] 与协调器合批排程无交集:E1 只在 session_start 编排处运行(此前
2270
+ * dispose 已取消挂起排程),补发直走 notifier.notifyBatch 不经协调器;异常时序
2271
+ * 相撞由账本 sync-batch:<hash> 幂等拒绝兜底。
2272
+ */
2273
+ recoverSyncCollectBatch(): Promise<void>;
2274
+ /** [E1/D4] 单次「扫描→判定→可达则补发+落标」,E1 首扫与 settled 重扫共用同一实现
2275
+ * (防两处复制粘贴分岔)。三态返回:idle(无 sync 候选——已全部落标/E9 转换/异根,
2276
+ * 无事可等)/ waiting(仍有 running 成员,本次不动)/ dispatched(全员终态,已补发
2277
+ * +统一落标)。async:补发前有 manifest 屏障 await(见函数头 E1 注释)。 */
2278
+ /** 返回 outcome + waitingIds(达限 warn 需滞留成员 id,D6 #7b——仅 waiting 态非空)。 */
2279
+ private runSyncCollectRecoveryScan;
2280
+ /** [v2 D4] 注册 agent_settled 有界重扫(幂等:settledRescanState 非 null 不叠加注册
2281
+ * ——E1 现仅 session_start 单调用点,守卫是防第二入口引入时的注册叠加断言面)。
2282
+ * 每次 settled 边沿重跑同一 E1 扫描(runSyncCollectRecoveryScan):dispatched
2283
+ * (补发+落标完成,scan 的 warn 已留痕)或 idle(候选已被其他通路落标)→ disposed;
2284
+ * 累计 SETTLED_RESCAN_LIMIT 次仍在等 → disposed + warn 留痕(D6 #7b / SC-2:达限
2285
+ * 放弃重扫意味着滞留成员的批通知要等下次 session_start 才收敛,含滞留 id 的 warn
2286
+ * 是唯一线索,debug 级排障不可见;后续事件零处理,下次 session_start 再收敛)。
2287
+ * pi.on 无 off(0.84.4 实装)——disposed 标志包装兑现退订(scheduler extension
2288
+ * index.ts subscribeSettled 同款先例)。P-settled 定谳(0.84.4 dist 实装证据):
2289
+ * pi.on 为 per-extension 列表分发——loader.js `on()` 把 handler push 进
2290
+ * extension.handlers.get(event) 数组(非覆盖),runner.js `emit()` 对全部
2291
+ * extension 的全部 handler 逐一 await;故本注册与 ledger host 经
2292
+ * piAdapter.onAgentSettled 注册的 settled 分发互不干扰,无需降级并入 host 链。 */
2293
+ private armSettledRescan;
2142
2294
  dispose(): void;
2143
2295
  /**
2144
2296
  * [T4④ / PS-5] shutdown flush 被门拦时把未投递 pending 复写落盘(供重启 replay)。
@@ -2332,6 +2484,17 @@ declare class SubagentService {
2332
2484
  * [perf] 磁盘源为 light(头部 identity + 状态,无 eventLog/result/turns 等重数据)
2333
2485
  * ——列表/补全/hasRunning 够用;详情场景调 getFullRecord(id) 懒加载补齐。 */
2334
2486
  private collectRecords;
2487
+ /**
2488
+ * collectSync.default 当前生效值(subagent-sync-collect U2,偏差#3 接线:
2489
+ * startHandler 缺省 collect 解析用)。
2490
+ * config 未配/读失败 → DEFAULT_COLLECT_SYNC.default 兜底(E5 不炸启动)。
2491
+ * 新 session 生效语义与 engine 配置一致(globalConfig 由 ModelConfigService
2492
+ * reloadGlobalConfig 刷新)。
2493
+ */
2494
+ /** collectSync 节单读取点(S9,code-simplify):「读节」一处,「投影成 default 或
2495
+ * budget」各自 accessor 负责(getCollectSyncDefault / getCollectSyncBudget)。 */
2496
+ private collectSyncSection;
2497
+ getCollectSyncDefault(): "async" | "sync";
2335
2498
  /** [perf] 单 record 详情懒加载(全量:eventLog/displayItems/result/turns/tokens)。
2336
2499
  * 内存 running record 直接投影;磁盘 record 全量重建(per-file 缓存,stat 戳校验)。
2337
2500
  * 返回 undefined:id 不存在于内存与磁盘。 */
@@ -3826,6 +3989,18 @@ interface SubagentRecordEntryData {
3826
3989
  journalPath?: string;
3827
3990
  poolKey: string;
3828
3991
  };
3992
+ /**
3993
+ * 同步收集模式标记(subagent-sync-collect 设计 §3.1.3,U1 foundation)。
3994
+ * undefined = async(缺省语义,旧 entry 零迁移——undefined 经 JSON.stringify 自然缺省)。
3995
+ * 消费方:U5 rebuildEntryRecord 投影扩展 + E1 重建扫描。
3996
+ */
3997
+ collectMode?: "sync";
3998
+ /**
3999
+ * 离开批终局标记(subagent-sync-collect 设计 §3.1.3,U1 foundation)。两出口统一
4000
+ * 落标(批闭合 flush / E9 dispose 转换,均 appendEntry 持久化)。undefined =
4001
+ * 未离开批 / 旧 entry 零迁移。消费方:U5 E1 重建扫描只收无标记成员(防双重通知)。
4002
+ */
4003
+ batchFinalized?: boolean;
3829
4004
  }
3830
4005
  /** SubagentRecord → 自描述 entry data(快照投影,不 mutate 源)。
3831
4006
  *
@@ -4035,6 +4210,14 @@ interface StartHandlerInput {
4035
4210
  idleTimeoutMs?: number;
4036
4211
  /** 执行引擎(三层路由第一层:本参数 > agent frontmatter engine > config defaultEngine)。 */
4037
4212
  engine?: string;
4213
+ /**
4214
+ * 同步收集模式(subagent-sync-collect U1 foundation)。undefined = config
4215
+ * collectSync.default(缺省 "async")。schema 层枚举限 "async"|"sync";运行时
4216
+ * 宽收 string 与 engine 字段同风格(pi 工具框架把 schema Static 解析为 string;
4217
+ * 非法值 ≠ "sync" 按 async 处理,E4 守卫用精确 "sync" 判定)。透传
4218
+ * service.execute(ExecuteOptions.collect;record.collectMode 落点归 U2 接线)。
4219
+ */
4220
+ collect?: string;
4038
4221
  }
4039
4222
  /** start 领域对象(宿主 adapter 包成 bg 工具结果)。 */
4040
4223
  type StartHandlerResult = {
@@ -6152,6 +6335,6 @@ declare function boundedPrettySerialize(value: unknown, budget: number): string;
6152
6335
  * docs/design/subagent-core-sink-design.md(sink 下沉收口扩面,2026-08-31);
6153
6336
  * 宿主接入示例见包 README(§3.4 core_host_not_configured 恢复指引的落点)。
6154
6337
  */
6155
- declare const CORE_PACKAGE_VERSION = "0.5.1";
6338
+ declare const CORE_PACKAGE_VERSION = "0.6.0";
6156
6339
 
6157
6340
  export { AGENT_REF_EXT, AgentCall, AgentCallOpts, type AgentEntry, AgentEvent, AgentEventLogEntry, AgentOutcome, type AgentProfile, AgentRegistry, AgentResult, type AgentRunner, type ArgKeySet, type ArgMetaOptions, type ArgMetaWarning, type AtomicTmpRef, type AtomicWriteFileOptions, type AtomicWriteOptions, BG_MESSAGE, BgResponse, Budget, CORE_PACKAGE_VERSION, type CachedWorkflowMeta, type CancelHandlerInput, type CancelHandlerResult, CancelResponse, type ChangeListener, type ChannelHandler, type CleanupStaleTmpOptions, type CleanupStaleTmpResult, type CleanupWorktreeOptions, type CloseHandlerInput, type CloseHandlerResult, CloseResponse, ClosedReason, type CollectWorktreePatchOptions, type ConcurrencyPool, type CoreLogger, type CreateConcurrencyPoolOptions, DEFAULT_DATA_ROOT, DEFAULT_ENGINE_ID, DEFAULT_LIST_LIMIT, DEFAULT_PROVIDER_ID, DEFAULT_SAVE_MIN_INTERVAL_MS, DEFAULT_STATE_MAX_RUNS, DEFAULT_WORKFLOW_SAVED_DIR, DEFAULT_WORKFLOW_TMP_DIR, DialogGlobalQueue, type DiscoveredResource, type DiscoveryRoot, DisplayItem, DoneReason, EngineCapabilities, EngineHandle, EngineHandleData, type EnginePort, type EngineRouteOptions, type EngineRouteResult, type EngineRouting, type EngineRoutingInput, type EngineRoutingSource, type EngineRunResult, ExecutionMode, ExecutionOutcome, ExecutionRecord, ExecutionStatus, ExecutionTraceNode, ExternalState, FORK_FROM_DEFAULT_PROMPT, FileRunStore, type FinalizeRunOptions, type ForkFromHandlerInput, type ForkFromHandlerResult, ForkFromResponse, type GenerateWorkflowScriptOptions, type GenerateWorkflowScriptResult, GitRunError, type GlobalConfigReadResult, type HostServices, IDENTITY_CUSTOM_TYPE, INDEX_FILENAME, InteractAction, InteractResult, type InvalidAgentRefMessageOptions, type LauncherDeps, type LifecycleDeps, type LintFinding, type LintResult, type ListFormatOptions, type ListHandlerInput, type ListHandlerResult, ListResponse, type ListWorktreePorcelainOptions, type LogLevel, MAX_LIST_LIMIT, MAX_RETAINED_DONE_RUNS, MAX_TIMER_DELAY_MS, type MessageHandlerInput, type MessageHandlerResult, MessageResponse, ModelConfigService, type ModelConfigServiceInit, type ModelEntry, ModelInfo, type ModelListFormatOptions, type ModelReasoningInfo, NOTIFY_CONTRACT, type NormalizeWorkflowRefOptions, type NormalizedArgs, type NormalizedWorkflowRef, type NotifyDomainPorts, type NotifyLedgerHost, type PatchBaselineAnchor, ProbeReport, type QueuePolicy, RecordStore, type RecordStorePi, type RecoverCrashedRunsHooks, type RecoverCrashedRunsResult, type ResourceKind, type ResourceSource, type RunContext, type RunSnapshot, type RunSpec, type RunState, RunStatus, type RunStore, SAFE_ID_RE, SNAPSHOT_VERSION, SUBAGENT_RECORD_CUSTOM_TYPE, type ScanConfig, SessionView, type StartHandlerInput, type StartHandlerResult, type StatusFilter, type SubagentIdentityData, SubagentListItem, SubagentRecord, type SubagentRecordEntryData, SubagentService, type SubagentServiceInit, SubagentStream, SubprocessAgentRunner, THINKING_ORDER, Trace, type UiChannelRegistry, WORKFLOW_REF_EXT, WORKFLOW_REF_RESERVED_NAMES, type WorkerHandlers, type WorkerHost, WorkerHostImpl, WorkerLogEntry, type WorkflowDirOptions, type WorkflowEntry, type WorkflowMeta, type WorkflowRefInvalidReason, WorkflowRun, type WorkflowRunMeta, type WorkflowRunResult, type WorkflowRunSummary, type WorkflowScanConfig, WorkflowScript, type WorkflowScriptRegistry, WorkflowScriptRegistryImpl, type WorkflowSource, WorktreeManager, type WorktreePatchResult, type ZcodeEngineDeps, ZcodeTaskShapeError, abortRun, argKeysFromMeta, assertSafeId, atomicTmpPathFor, bestEffort, bindNotifyLedgerHost, boundedPrettySerialize, buildEngineModelsPromptAppend, buildSubagentEngineSection, cancelHandler, cleanupStaleTmpFiles, cleanupWorktree, clearSkillPathCache, closeHandler, closeOutInFlightCalls, collectWorktreePatch, computeElapsedSeconds, configureCore, configureNotifyDomain, countAllToolCalls, createConcurrencyPool, createSubagentService, createUiRequestHandlerForMode, createZcodeEngine, deleteWorkflow, deriveOutcome, discoverAgents, discoverResources, discoverWorkflows, displayAgentName, endedMessageGuard, escapeXml, evictDoneRunsBeyondCap, executeNestedWorkflow, finalizeRun, findFlattenedArgKeys, findWorkspaceRoot, forkFromHandler, formatAgentList, formatModelList, formatWorkflowList, fromRunSnapshot, generateWorkflowScript, getAllToolCalls, getBoundNotifyLedger, getCachedFileContent, getCachedParsed, getHostServices, getLogger, getModelConfigService, getOrCreateChannelRegistry, getSubagentService, getWorkflow, getWorkflowByPath, gitRun, hasApiKey, invalidAgentRefMessage, invalidateCache, isProcessAlive, isResumable, isSafeId, isScriptRunning, isTreeDirty, killAllSpawnedChildren, killRecordChildWithEscalation, lintScript, listHandler, listStaleTmpFiles, listWorktreePorcelain, loadWorkflowScriptByPath, loadWorkflows, makeSerializeFailedResult, mapExternalState, maxTurnsToWatchdogMs, maybeCleanupExpiredSessionFiles, messageHandler, normalizeArgsByMeta, normalizeEngineId, normalizeRef, normalizeWorkflowRef, notifyGateAllowsDelivery, parseAgentProfile, parseAtomicTmpPath, parseEngineHandle, parseResourceMeta, parseResourceMetaDetailed, postBudgetUpdate, projectLiveProgress, projectOutcome, readGlobalConfig, readSubagentHistoryMessages, recordToListItem, recoverCrashedRuns, registerPiEngine, registerZcodeEngine, renderXmlSection, resetRebuildFailureInjectionForTest, routeEngine, runAndWait, runSummary, runWorkflow, saveWorkflow, scheduleTimeBudget, setModelConfigService, setSubagentService, sortByCodepoint, splitZcodeModelRef, startHandler, summarizeDescription, syncEnginesFile, terminateRunningRuns, toRunSnapshot, toSubagentRecordEntry, wrapForkFromPrompt, writeAtomicFile, writeAtomicFileSync };