@gestaltrun/dsh-agent-eval 0.0.0-stage → 0.1.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.
Files changed (37) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +58 -0
  3. package/README.md +194 -2
  4. package/README.zh.md +195 -0
  5. package/cordis.patch.yml +13 -0
  6. package/lib/cs-hosting-plugin-B9bjLaoE.js +6980 -0
  7. package/lib/cs-hosting.js +2 -0
  8. package/lib/index.js +2 -0
  9. package/lib/types/agent-runs.d.ts +56 -0
  10. package/lib/types/cs-hosting-evaluation.d.ts +235 -0
  11. package/lib/types/cs-hosting-plugin.d.ts +10 -0
  12. package/lib/types/handoff.d.ts +4 -0
  13. package/lib/types/human-actions.d.ts +36 -0
  14. package/lib/types/im-purchase-intent.d.ts +12 -0
  15. package/lib/types/im-target.d.ts +45 -0
  16. package/lib/types/index.d.ts +22 -0
  17. package/lib/types/input-admission.d.ts +10 -0
  18. package/lib/types/practice-failure.d.ts +17 -0
  19. package/lib/types/product-field-policy.d.ts +129 -0
  20. package/lib/types/production-budget.d.ts +21 -0
  21. package/lib/types/production-buyers.d.ts +20 -0
  22. package/lib/types/production-workspace.d.ts +64 -0
  23. package/lib/types/purchase-intent.d.ts +66 -0
  24. package/lib/types/record.d.ts +169 -0
  25. package/lib/types/replay-world.d.ts +25 -0
  26. package/lib/types/reply-latency.d.ts +21 -0
  27. package/lib/types/runner.d.ts +97 -0
  28. package/lib/types/sales.d.ts +33 -0
  29. package/lib/types/script-production.d.ts +955 -0
  30. package/lib/types/server-script-source.d.ts +65 -0
  31. package/lib/types/simulated-buyer-role.d.ts +41 -0
  32. package/lib/types/snapshot-replay.d.ts +15 -0
  33. package/lib/types/step-failure.d.ts +25 -0
  34. package/lib/types/types.d.ts +174 -0
  35. package/locale/en.json +6 -0
  36. package/locale/zh.json +6 -0
  37. package/package.json +106 -3
package/README.zh.md ADDED
@@ -0,0 +1,195 @@
1
+ ---
2
+ description: "通过可替换的目标、世界、角色、剧本来源和指标包运行版本化 Agent 评测。"
3
+ kind: "package-library"
4
+ ---
5
+
6
+ # @gestaltrun/dsh-agent-eval
7
+
8
+ [English](README.md) | 中文
9
+
10
+ ## 概要
11
+
12
+ 使用 `EvaluationRunner` 对 Agent 执行冻结剧本,产出版本化用例记录。目标拥有会话,世界拥有回放数据,角色拥有买家动作,剧本来源选择输入,指标包提供检查项。客服适配器使用真实 IM 模拟与托管 preset。运行器不计算用例得分。
13
+
14
+ Desktop 在客服托管之后选择这个独立 bundle。它的 `cordis.patch.yml` 按随包配置的并发数、用例限制和价格注册 `csHostingEvaluation`。两个 bundle 都需启用:评测插件依赖托管、商家账号、IM、工作区、存储、Agent、Session、preset 与默认模型服务,并在启动前初始化评测运行元数据。停用此 bundle 后,运维范围页显示服务未加载提示和“上一步”操作。
15
+
16
+ ## 目录
17
+
18
+ - [使用此包](#use-this-package)
19
+ - [扩展点](#extension-points)
20
+ - [客服评测](#customer-service-evaluation)
21
+ - [Server script source](#server-script-source)
22
+ - [人工协同](#human-collaboration)
23
+ - [成对销售运行](#sales-pairing)
24
+ - [购买意向采集](#purchase-intent-capture)
25
+ - [用例记录](#case-records)
26
+ - [模型体验](#model-experience)
27
+ - [已知限制与后续工作](#known-limitations-and-deferred-work)
28
+ - [开发说明](#dev-note)
29
+
30
+ <a id="use-this-package"></a>
31
+ ## 使用此包
32
+
33
+ 从包根导入 `EvaluationRunner`、`deterministicRole`、`SimulatedBuyerRole`、`ImEvaluationTarget` 和 `CustomerServiceReplayWorld`。调用 `runner.run({ script, target, world, role, metrics }, signal)` 或 `runFrom(source, caseId, adapters, signal)`。调用方准备店铺托管路由与买家工作区;后者必须已经通过 `saveSimulationTarget` 引用该路由。
34
+
35
+ `Config.maxBuyerMessages` 默认 150,`responseTimeoutMs` 默认 120000,`currency` 默认 `CNY`。超时使用主机实际经过时间,记录时间戳使用每条消息发送或工具调用时采样的剧本时钟。`EvaluationConversation.currentTime()` 提供该运行时钟。消息和工具按时间戳排序,同时间保留发送顺序;消息的 `clockAt` 与 `at` 使用同一时刻。IM 回复等待超时会返回带 `replyTimedOut` 标记的部分观察,继续本次对练,不停止被测 Agent。本步被接收的输入出现在被测 Session,且之后有轮次结束时,完成等待。接待暂停也会结束等待。已进入队列的输入被丢弃或未消费,且 Agent 已空闲时,本步返回,不带回复超时标记,也不记首次回复样本。注入输入期间超时会使步骤失败,并在返回前等待注入结束。首次回复计时用已消费的输入匹配发送工具的结构化回执,停在超时时刻,未回复样本的 `firstReplyMs` 为 `null`。已有记录字段 `endedAt` 包含最后一次回复等待的超时时刻,即使没有收到回复。迟到消息和工具结果在下一步观察中只收集一次,保留记录时的时间戳和发起模型步骤的通道。回复等待超时后,买家可以在被测 Agent 仍运行时推进剧本时钟;迟到消息使用新的剧本时间,以便剧情继续。超时时观察到的暂停仍结束用例;确认转人工保持原有继续规则。应用当前输入范围前,尚未检查的模型错误会使用例失败,即使之后的轮次成功。没有未检查错误时,取当前输入范围内最后一个轮次结果;关闭时检查全部剩余未检查错误。调用方取消优先于未检查的模型错误,关闭对话后返回 `cancelled`,并保留已完成轮次;清理失败仍使调用拒绝。目标步骤失败产出 `error` 记录;准备或清理失败使调用拒绝。目标停止完成后才移除世界注册。
36
+
37
+ 订单归属录制会话用真实店铺模型的输出,回放包内客服 preset、CLI Host 参数解析和 IM 模拟链路。实例内订单夹具包含他人订单及要求透露该订单的指令;买家回复不透露这些事实,归属未确认的订单进入人工提问流程,“我是店主”的注入被拒绝。来源录制元数据与免 key 期望会话随[夹具](tests/fixtures/order-ownership/recording.json)保存。
38
+
39
+ <a id="extension-points"></a>
40
+ ## 扩展点
41
+
42
+ | 接口 | 职责 |
43
+ | --- | --- |
44
+ | `EvaluationTarget<Binding>` | 打开、推进、驱动并关闭真实目标会话 |
45
+ | `EvaluationWorld<Binding>` | 挂载用例事实并分类日志中的工具调用 |
46
+ | `EvaluationRole<Binding>` | 从目标绑定产出有序的时间、消息和结束动作 |
47
+ | `EvaluationVariant` | 为整个分组切换一种成对运行条件 |
48
+ | `EvaluationScriptSource` | 加载所选冻结用例 |
49
+ | `EvaluationMetricPack` | 提供适用检查项与所需事实声明,不评分 |
50
+
51
+ 资源中心评测提供使用相同 `Binding` 类型的目标和世界,复用运行器、记录校验和限制,无需使用 IM 身份。适配器必须在调用方取消时停止并等待在途工作;IM 目标在输入注入完成后,信号原因为已导出的 `EvaluationReplyTimeout` 时保留在途工作。`deterministicRole` 只发送各段列出的文字,随后报告剧本的目标达成或放弃状态。
52
+
53
+ 运行器把已打开会话的绑定传给 `role.actions(script, signal, binding)`。不使用绑定的角色省略该参数即可保持相同函数形状。角色在 Host 确认买家侧已使用例不可用时报告 `{ kind: 'invalid', reason }`;运行器随后以 `endReason: error` 结束并记录 `buyerInvalidReason`。
54
+
55
+ <a id="customer-service-evaluation"></a>
56
+ ## 客服评测
57
+
58
+ 商家 Host 只创建一个 `cs-sales-v1` server run,为每个选中用例发起一次执行。销售运行选项使用选中评测集中的品类和逐次运行的比较种子;缺少品类数据时在创建 run 前拒绝。预计用量按每例执行一次计算。并发开始共用尚未完成的 server 创建请求。`humanActionSampleSize` 默认 3;Host 用同一个种子抽取合格剧本,把种子记入 `sales.comparisonSeed`,并向逐例运行器传入所选动作。`humanActionSeed` 可固定该种子以供回放;协议会去除首尾空白并要求 1–120 个字符,在服务加载时校验。离开页面不停止 Host 执行。Host 按 `reportPollIntervalMs`(默认 1000 ms)持续观察尚在判定的运行,读取失败时可见地重试,直到 server 确认完成或取消。取消会等待活跃用例结束,再释放目标与路由;取消被拒或结果未知时保留最后一次确认的 server 状态。释放先关闭准入,取消并等待评测集读取、尚在创建的运行及执行,再请求取消已创建且未终结的 run。身份替换会立即撤下店铺数据并丢弃晚到结果;身份凭据撤销后无法结算旧 server run,其未知状态写入日志,需回到原店铺检查。创建被中止且未返回 run id 时也保持未知,结算需要 server 请求标识。附注注入保持店铺当前配置(默认开启并包含全部分析字段);此入口不应用成对变体。
59
+
60
+ 单条对练失败不会取消其他 worker。首轮结束后,失败项再尝试一次。仍失败时,将最后一次实际产生的消息、工具记录和用量以 `endReason: error` 或 `timeout` 提交;最后一次没有消息时,提交消息最多的那次尝试及其失败原因。两次尝试的观测费用保留在本机缺失用例汇总。`EvaluationCaseFailure` 在初始化或收尾抛错时保留部分证据,`onFailure` 可观察运行器内部收住的错误。尚未产生任何消息时,协议不接受错误记录:Host 在缺失用例汇总中保留空证据为 `PRACTICE_NO_OBSERVATIONS`,不编造买家消息或买家边界失败。其他用例和重试走完后,本机运行标为失败,不在存在未提交用例时请求服务端完成。用例写入未确认时以 `WRITE_UNCONFIRMED` 停止,不自动重发。终态记录仍被明确拒绝时,其他用例先完成,再以 `CASE_SUBMISSION_REJECTED` 报告保留的未接收证据,不声称服务端已完成。连续三条同码 Host/传输失败停止派发(`practiceSystemicFailureLimit` 默认 3);模型内容失败和回复超时保持单条隔离。 全空用例与终态记录被明确拒绝同时出现时,`PRACTICE_NO_OBSERVATIONS` 优先于 `CASE_SUBMISSION_REJECTED`;本机缺失汇总保留这两类用例。
61
+
62
+ 对练不设置预算保护。旧配置中的 `practiceBudgetUsd` 和 `practiceCostBaselineUsd` 被忽略,对练不读写费用基线。取数和写剧本阶段的店铺额度检查仍然有效。profile 存储域 `evaluation_practice_attempts` 版本 1 按店铺、运行、案例的哈希键记录两次尝试及提交状态。现有生产检查点仍为版本 2,不作改写;旧运行元数据可缺少可选字段 `practiceMissing`。本地报告从计分用例数和通过率中排除缺失的产品错误用例,将服务端判定标为仅供参考;正式服务端记录与汇总不变。
63
+
64
+ 本机与云端待命对练统一使用无凭据的评测账号及其独立关闭路由,即使已选中真实账号并开启托管。Host 先确认已登录的 B 商家与当前 seller,再取得评测资源。停止会话对后只释放本次评测路由;正式账号选择、凭据与路由保持不变。
65
+
66
+ Host 插件在自身生命周期内注册模拟买家 preset,并在插件释放时注销。每个评测目标在购买心理观察器打开前持久化空的模拟会话 scope;初始化不发送买家消息。
67
+
68
+ 评测 Provider 通过 `csHosting.watch()` 观察已核验的店铺身份。当前身份捕获出现新的就绪商家时,先取消并等待旧读取结束,再刷新非运行状态的预览,包括本机完成过评测或已恢复取消运行后的预览;重复托管通知不触发刷新。此操作不创建或重启评测运行。scope 更换使旧预览结果失效,即使租户与用户编号相同。托管准备、保留的未知清理结果及释放都会关闭预览准入。身份观察任务与有限的预览工作分开,释放时取消并等待观察任务结束。观察任务正常结束时记录 `EVALUATION_SHOP_READINESS_ENDED`,包括评测运行中或已有有效预览时;保留该预览,仅在没有有效预览时显示不可用状态。观察任务失败时以安全诊断记录 `EVALUATION_SHOP_READINESS_UNAVAILABLE`,保留已有有效预览。中止尚未结束的可选预览后,后续显式刷新使用新的取消控制器;必需清理结果未知时仍拒绝评测准入。可选预览取消时不发布自身的 AbortError。店铺身份错误按稳定的 `CASE_DATA_SHOP_IDENTITY_UNAVAILABLE` 错误码分类,不要求旧托管包提供新的运行时导出。
69
+
70
+ 开始页通过只读 `previewSupply` 读取供给,不发布快照;开始生产后才调用 `captureSupply` 并提交。`historyWindowDays` 默认 30,`historyWindowOptions` 默认 `[7, 30, 90, 180]`;两者均可在 cordis.yml 修改,选项须为 1–180 的唯一整数且包含默认值。`scriptCap` 默认 `auto`,也可取 50、100 或 200。`auto` 最多纳入剩余额度付得起的 200 个用例;数字则最多纳入该数量。买家发现传入所选 from/to 范围;聚合前需求线数标明估算,用量按这些买家估算。聚合仍读取 180 天;生产按最后一条消息过滤窗口外需求线并记录跳过数量。coverage 创建请求在取数之前携带本次运行固定的 `from`/`to`。取数只派选中的需求线;选中项在一次重试后仍失败时,改用同一覆盖组的下一个备选。备选用完的组保持失败,不阻止其余剧本。coverage 将候选限定在窗口内且预筛合格的案例;Host 在编写剧本前校验返回素材,接受选中项或其备选;版本号变大时,只要案例分段消息键与特征 material 的消息键一致就接受。用备选提交剧本时带上 `featureId`,省略表示用原选中项。Host 剧本生产编排先采集供给、轮询买家聚合任务,再在同一窗口创建并轮询预筛任务,然后发布 coverage,只为选中的需求线创建取数 Session,按 `productionScriptConcurrency` 并发补写缺失剧本槽位,提交前按 key 把该槽记为未确认,拿到版本 id 后先写入检查点再挂载该已确认版本,最后创建评测运行。server 仍有重试次数时,`failed` 不视为终态;coverage 完成还必须有非空 `setId`。取数提交先写描述,再写订单。案例取数 preset 把请求固定到店铺云模型,取数与剧本任务消耗估算所对应的店铺额度。revision 冲突按新 revision 重填。当前 revision 不合格的案例不开 Session,记为已处理;其未取数特征保留在 coverage 分布中,但不能被选中。普通发起选择相同天数时复用检查点及其固定窗口;选择不同天数时按新窗口生产,写入结果未知时保持阻塞。Host 恢复沿用已分配运行的固定窗口。属于所选生产范围的已有评测集与已挂载槽位可以复用。恢复时,已有一次失败记录的剧本先等待新剧本任务完成,再使用剩余的一次重试。单条需求线或单个剧本的明确失败会记下原因码,其他任务继续。作者 Session 启动前的 Host 回放自检失败(`SCRIPT_HOST_REPLAY_INVALID`)尚未写入任何内容,属于这种明确的单个剧本失败。该阶段结束后对失败项统一重试一次。仍失败的剧本对应用例不对练。取消仍会到达每个进行中的任务,且只影响本阶段,Host 保持运行。额度不足、身份失效和写入结果未知仍停止整个阶段。离开页面继续运行;取消和切店会中止并等待所属 Session 退出,再移除任务绑定。
71
+
72
+ 预筛前,预览将需求线数量标为估算,并说明合格数据将在评测中确认。评测集以 `SET_NOT_READY` 拒绝开始时,Host 将保存的整体状态、活跃合格需求线数、包含活跃合格特征的分组数、已选评测用例数和 `rules.startMin` 交给本地化工作台。已选数与合格数、分组数分别展示;旧 Host 没有的统计显示“未提供”,不补成零。失败工作台单独标注停止原因;入选数量不足时,提示建议扩大到 90 或 180 天,缺少准入统计时显示通用可读原因。额外的品类和阶段统计不影响此投影。服务端明确拒绝后,Host 关闭待确认的创建记录;取消只在本地处理,后续开始可以重试。
73
+
74
+ 失败工作台显示评测已停止,提供不取消运行的返回数据范围操作,并保留管理员的失败项重试入口。类型化的评测集准入失败,以及旧版在剧本阶段以 `execution_failed` 返回的完整诊断 `Script production stopped: scripts (SET_NOT_READY)`,都将停止处定位到评测集准入。普通失败运行根据生产进度将停止点之前的阶段标为已完成。重新取数则要求各阶段有明确的完成审计;coverage job 完成不能证明聚合、预筛或全范围重新取数完成。保留的 Agent Session 呈现其他阶段的执行证据。无法推断进度的前置阶段显示状态未记录,未执行的后续阶段显示未开始;任务计数不代表评测成功。已选最长历史范围时,空预览说明该店铺仍缺少可评测对话,不再建议扩大范围。
75
+
76
+ 剧本任务与本地提交校验使用开始编写时读取的当前案例结局。覆盖特征保留取数前的结局用于选样,不作为剧本参考结局的来源。
77
+
78
+ 运维在“发起评测”的确认框中选择“从取数开始重新评测”,会先在固定窗口发现买家、聚合其正式对话并完成窗口内预筛,再新建 coverage job。既有服务端入口保留源未变化的 revision 和有效资格结果;新纳入窗口或源已变化的需求线在选例前完成准备。新取数操作在已保存的抽取版本缺失或过旧、供给 revision 与服务端不匹配,或服务端快照商品非空但目的地全为空时,会在建立 coverage job 前刷新供给。读取返回 404 `NOT_FOUND` 也会抓取供给,其他读取失败停在供给阶段。当前抽取版本且 revision 相同的快照可以复用,包括空商品目录。checkpoint 保存新 revision 与抽取版本,重新取数审计记录已确认的供给 revision。新集合的主选强制重新取数,server 上的旧描述或提交不算本批次完成;两次失败后改用同组备选。每个剧本在新集合的空槽位中生成并挂载,不使用旧集合版本,然后对练、判定、出报告。
79
+
80
+ 确认页使用与历史范围选择相同的分段控件。新重评批次固定本次预览的起止窗口,完成该范围的聚合与预筛;未完成批次沿用已保存窗口,不受历史范围选择变化影响。读取结果未知时,已确认的聚合、预筛与覆盖任务按保存的编号继续观察;已有 coverage job 或已发布评测集保持冻结的准备结果,恢复时不会再次聚合。重评用量按配置的单任务价格为全量取数、剧本生成、对练和判定预留,续跑也按全量估算,额度不足时禁止开始。普通开始只估算剩余工作,因此只有普通开始也需要全部任务时,两种估算才相同。工作台以标签和值展示新评测集版本及选样差异,尚未发布的值显示“生成中”,操作编号可选中复制。准备阶段审计的新增值保留 checkpoint 版本 2,见[持久化确认](persistence-changes/2026-10-24-restart-preparation.md)。
81
+
82
+ 普通生产操作在接纳首个 coverage job 前,若缺少 `supplyDestinationExtractionVersion` 或版本过旧,会刷新一次供给。已保存的 set id、显式复用的评测集和已确认的 coverage job 保留其冻结的供给 revision,即使旧 checkpoint 没有版本标记也不重抓。未结束的重新取数操作保留已保存的 revision 和 operation id。抓取结果及当前版本持久保存后,恢复同一操作不会再次抓取,即使目的地仍全为空。提交失败不推进版本标记,也不接纳 coverage job。抓取前,checkpoint 先持久保存供给写入意图;显式重新取数时也保存新操作编号。确认抓取后,一次写入 revision、抽取版本并清除意图。提交前的确定失败或服务端明确拒绝会清除意图,允许重试;写入结果未知或已确认抓取无法保存时保留意图,停止自动重发。该保护以已保存的意图阻止重发,供给接口仍不提供物理恰好一次保证。版本标记与供给意图的兼容性见 [checkpoint 持久化确认](persistence-changes/2026-10-23-supply-extraction-version.md)。
83
+
84
+ 重评使用独立的 `checkpoints/<SHA256 tenant id>.json.collection-restart.json`,保留普通生产检查点。中途失败或生产阶段取消后,再选该入口会继续未完成批次的固定窗口、coverage job、新集合、已确认取数和剧本;报告完成、已观察到 server 取消,或因 `SET_NOT_READY` 停止后,再次选择开始新批次。重新取数生成的评测集在 `canStart` 为 false,或已选数量低于 `rules.startMin` 时,于生成评测集后以 `SET_NOT_READY` 停止,写入 `endedAt`,不再打开取数会话。已挂载的剧本计划为空,或创建评测运行时 server 以 `SET_NOT_READY` 拒绝,同样结束该批次。窗口内选中项的取数会话全部失败时,批次停在取数阶段,错误码为 `CASE_DATA_SESSIONS_FAILED`,各条原因仍留在 `dataFailures`。续跑该批次不会重新打开已失败两次的槽位,直到管理员使用“重试失败项”。重新取数的失败审计在 `ProductionFailure` 的阶段属于批次事件阶段时使用该阶段;`supply` 等其余阶段仍沿用上一条事件的阶段。批次操作编号作为 server 评测幂等 id;检查点记录已确认提交的对练用例,恢复时跳过,包括仍待判定的用例。每步审计记录时间、状态、管理员与操作编号,并保存旧集合、新集合 id/版本、供给 revision,以及主选案例相同、新增、移除的数量。检查点保留阶段审计;按 run id 的本地运行元数据保留生产阶段审计,工作台显示新集合与选样差异。未结束批次中的未知写入会停止,不自动重发。已结束批次即使残留不确定状态,也可开始新操作;原批次审计保留在 checkpoint 历史中。 Host 内存没有运行时,管理员取消会恢复未结束的重新取数检查点,按操作编号核对服务端运行,并在确认取消后写入结束审计;确认服务端运行不存在时可直接结束本地批次。读取或取消结果无法确认时保留检查点。结束后预览不再显示可续跑,下一次重新评测创建新的 coverage job。
85
+
86
+ 旧检查点专用的 `productionScriptRecovery` 不适用于新集合;新入口忽略该配置。下一轮实例配置应移除 agent-eval 插件 `config.productionScriptRecovery` 整个字段及其旧集合标识,保留其余配置;需恢复旧集合时才保留该字段并使用普通入口。不删除检查点或更改 server 绑定。
87
+
88
+ `productionScriptRecovery` 是 cordis.yml 中可选的、由管理员显式启动的恢复配置,必须提供 `operationId`、`setId`、`unconfirmedScriptKeys`、`invalidScriptVersionIds` 和非空 `reason`;标识为 UUID,两个列表内各项不得重复。带此配置开始时记录已认证管理员与时间,只放行指定的、仍未挂载的未确认 key,并将指定的当前挂载版本排除对练和评分。覆盖集、取数结果和服务端挂载保持不变。重新生成可能使此前已确认但未挂载的版本留在服务端而不被使用;检查点记录这种可能、放行的 key 和无效版本。相同操作 id 只允许相同输入的幂等重放。运行元数据与报告读取保留无效版本及原因,运行元数据关联恢复操作 id;重试该集时保留恢复配置。
89
+
90
+ 运行范围元数据包含窗口外跳过数、预筛排除数,以及重试后仍失败的需求线和剧本的条数与原因码分布,按租户与 run id 保存在本地;同一 Host/profile 的报告和运营可读取,其他 Host 或缺少记录的旧运行保持范围未知,不把 server coverage 的素材时间当作运行范围。编排检查点与已校验回放信封存放在 [case-data Host 数据目录](../cs-hosting/README.zh.md#case-data-workspace)的 `checkpoints/`,按租户 id 的哈希隔离,POSIX 文件权限为 `0600`。再次开始复用已确认的案例 revision、job id、set id 与剧本版本;预筛或 coverage 任务仍在运行时,Host 重启后继续使用该任务已确认的窗口,运行元数据也记录这一窗口;只有窗口内案例仍保留当前预筛结果时,才复用已完成的预筛 job。服务端因题目版本变化使结果失效时,生产会新建预筛任务并重新考虑未提交的 revision,保留已提交的案例数据。加载已有检查点时,版本 1 迁到版本 2 并保留已提交的案例;预筛 job、排除数、按 key 记录的未确认剧本、单条失败、备选替换,以及供给注意事项的失败数和截断数均为可选。非幂等写入结果未知时以 `WRITE_UNCONFIRMED` 停止,须由运营核实后再开始;明确的任务拒绝可以重试。`productionTaskConcurrency` 默认 2,`productionScriptConcurrency` 默认 4,两者均为 1–16 的整数。轮询间隔默认 1000 ms,任务队列等待上限默认 30 分钟,`productionTaskTimeoutMs` 为取数默认 10 分钟,`productionScriptTaskTimeoutMs` 为剧本默认 20 分钟,revision 重填上限默认 3 次。`productionDealWindowDays` 与 `productionOrderLookbackDays` 默认 7 和 30;均为可由 cordis.yml 修改的插件 Config 字段。
91
+
92
+ 预计用量包含取数、剧本编写和对练。`estimatedDataTokensPerCase` / `estimatedDataCostUsdPerCase` 默认 8000 / 0.03 USD;剧本估算默认 6000 / 0.02 USD,对练沿用独立估算。聚合前按 `estimatedCasesPerBuyer`(默认 2)估算案例数量。取数预算和工作台总数只计预筛后仍需派发的 Session,开始页估算不变。Host 在取数与编写前重查真实额度,并向 coverage 选取传入可负担案例数;已完成取数与已挂载剧本不计入剩余生产估算。
93
+
94
+ `responseTimeoutMs` 限制每步被测 Agent 回复(默认 120000 毫秒);`buyerStepTimeoutMs` 限制每步模拟买家执行(默认 120000 毫秒)。`firstReplyTargetMs` 是独立于两个硬上限的报告目标(默认 30000 毫秒)。三者都是加载时校验的整数 Config 字段,范围为 1000–600000 毫秒,可在 cordis.yml 设置。首响超过目标但在硬上限内完成的回复照常进入判定;只有超过硬上限才产生对练超时。自动处理暂停期间接收的买家输入及模拟人工轮次不计入首响样本。
95
+
96
+ 每个已接收的买家轮次使用 Host 单调时钟,从入站持久提交计时到首条 AI 出站持久标记为 `sent`,在取消清理前冻结观察。缺少与回执匹配的入站观察时不生成首响样本,轮次继续执行。本 profile 的运行元数据保存目标、用例、重试序号、实际执行 id、轮次、已送达耗时(或 null)及观察时长,包含重试和中断恢复后的重跑。未送达回复的轮次仅在观察达到目标后计为超标;未回复数包含转人工、暂停、取消或错误时没有送达回复的轮次,其中未达到目标就结束的观察为不完整。报告按用例汇总超标轮次、涉及用例、最长已送达首响及未回复数。其他 Host 和旧运行可能没有观察记录。侧车不改变 server 用例记录、判定或产品错误计数。
97
+
98
+ 运维控制台嵌入商家报告。报告渲染和文案变更需同时运行 `pnpm --dir product/cs-hosting exec vitest run tests/ui/evaluation-report.spec.tsx` 与 `pnpm --dir product/ui-ops-console exec vitest run tests/evaluation-ui.spec.tsx`;后者覆盖嵌入的报告与运行健康页。
99
+
100
+ `ImEvaluationTarget` 通过 IM runtime 创建独立的买家 Session 和被测 Session。路由选择当前生产 preset 及其已应用 Agent 配置;本库不复制提示词或替换工具。买家 Session 在调用方的买家工作区中运行,使用调用方的买家 preset 与店铺云模型,其绑定暴露给角色。`merchantCloudModel` 是评测插件的必需服务,对练目标通过它在分配两侧 Session 前检查店铺云模型准入。店铺云模型不可用时拒绝打开买家。模拟实例停止前暂停自动买家模型轮次,被接管的模拟用户 Session 不再接收 IM runtime 的操作员工具。
101
+
102
+ `SimulatedBuyerRole` 开场一次接收完整原始对话、知情卡、Host 计算的风格和购买心理卡。买家决定剧情何时结束,不设分组游标或每组轮数。获准发出的消息可以指定店铺时区的发送分钟,角色先推进剧本时钟,再发送消息。目标提供 `resume` 时,确认转人工后用例继续:人工消息以 `operator` 记在当前买家轮次,恢复自动处理使用生产同一个开关。其他暂停仍结束用例。店铺 AI 和模拟人工回复通过原生 IM 投递进入买家 Session,并作为心态判定证据。一步无动作时提醒一次,再次无动作按剧本结局结束;首条买家消息前发生此情况时,以 `EvaluationCaseFailure` 保留空观测错误。服务重试一次后将 `PRACTICE_NO_OBSERVATIONS` 保留在缺失用例汇总,继续其他用例和重试,全部结束后将本机运行标为失败,不提交空记录。写接待开关失败时保留此前观测。[客服托管包](../cs-hosting/README.zh.md#simulated-buyer-workspace) 拥有四个工具、提示词和知识检查。
103
+
104
+ `CustomerServiceReplayWorld` 要求账号与用例 id 匹配。条目包含已校验的生产 CLI 结果、规范命令参数和观察时间。店铺商品/订单及平台命令选择同时不晚于请求时间和用例时钟的最新匹配条目;`at` 仅控制时间选取,其余参数仍严格匹配,下述显式商品快照视图除外。带 `include*` 分区的 `seller.snapshot.get` 记录可回答请求其中任意子集的查询。缺失条目返回生产空结果,`seller.orders.at` 保留明确的字段不可用格式。缺失数据记录为 `miss`,不会用当前店铺事实替代。只有与世界的 `requiredReads` 之一相符(命令、商品、订单或 POI id、详情屏均相同)的 miss 才设置 `affectsConclusion`;未提供 `requiredReads` 时,每次店铺读取 miss 都设置。server 把含这种 miss 的用例记为环境不完整。平台 miss 只有列入 `requiredReads` 时才影响结论。被测客服不回退到带凭据的平台读取。取数、预览与剧本生成保留生产凭据读取路径。转人工保留独立模拟适配器。店铺读取结果携带固定的 `data.evaluationReplay.reason`:`matched`、`record_unavailable`、`no_command_record`、`order_not_collected`、`arguments_mismatch` 或 `not_yet_available`,并进入用例记录;运营运行健康面板仅投影这些原因码和命中/未命中数量,不暴露原始参数与结果。订单读取没有对应命令记录时,立即返回 `order_not_collected` miss,明确说明“订单数据未采集”。所有订单 miss(包括参数或时间不匹配)都附带未采集警告;miss 不能证明买家没有订单,也不会查询当前平台数据。
105
+
106
+ 商品回放支持已采集的 first/second 屏;third/sku 返回“当时无记录”。显式[字段分类表](src/product-field-policy.ts) 区分变化少的字段(标题、图片、类目、行程、费用包含与不含、自费、退改及预订须知)与变化快的字段(团期、日历价、余位、促销)。变化少字段取对应屏的采集记录,标注“采集时数据”和实际 `observedAt`;历史时间锚点不能替代采集时间。非空历史快照可覆盖标题、类目、图片和下架时间,并提供动态事实。动态字段缺失时只采用按出发日期记录的 `inventoryEstimate` 余位,标注“按订单推算”及方法、限制;不推算价格,也不替换为其他 SKU。不可得字段保持缺失并报告“当时无记录”。混合的不透明根正文和未分类根字段不返回;明确分类为稳定详情节点内的正文保留。原始 first 屏 SKU 规格和 second 屏行程、费用、须知及退改节点遵循同一字段策略。当前价格、团期及库存子字段不会进入稳定字段;采集时 SKU 余位仅作为另行记录的订单推算所用当前库存输入。只含标识/null/空字段的快照不算事实或字段名发现命中。`seller.items.search` 只在本案例已采集的商品(含对比候选)中匹配标题,并标注受限范围。嵌套在 `item` 等包装对象中的标题同样可匹配。结果元数据记录逐字段来源种类与时间。最近前序查找包含相等时间,且不会在可选的 `validThrough` 处过期。商品详情记录通过 server 剧本 JSON 保留 `{fields, collection: {screen, observedAt, skuId?}}`;旧记录缺少采集时间时不充当采集事实。本次变更不采集数据,也不改写检查点。
107
+
108
+ [IM 批量控制器](../im-runtime/README.zh.md#simulation-batches)为多个会话对提供有界创建、执行和终态清理,`maxConcurrency` 默认 2。每个任务提供独立的活跃买家 Session 和回调;停止会取消排队创建,并等待活跃回调和实例清理。
109
+
110
+ Host 观察 Agent 任务会话和工具调用事件,供管理员工作台使用。`recentAgentTaskLimit` 为非负整数,默认 20、最大 1000,仅限制已结束任务。运行中的任务及保留任务的全部重开会话均可见。任务投影包含不带参数的命令名称、提交重试与包含取消在内的终态。只有当前商家成员的 `isAdmin=true` 时 Host 才返回这些观察;切换商家会同步撤回运行。运行中的评测把这些观察保存在进程内存中;运行完成、取消或失败时,Host 把任务引用(不含对话内容,对话仍在各自 Session 中)写入该运行的本地元数据,因此 Host 重启(包括定向升级)后,管理员仍能看到任务列表;恢复只用于查看,不会恢复任何 Agent。保存失败时 Host 记录警告,评测结果不受影响。在服务端运行创建之前就停止的运行没有元数据记录,不保留任务列表。没有该列表的旧记录退回到托管停止运行时保存的任务引用。这些引用不改变 Session 格式;cs-hosting 包在 `persistence-changes/2026-10-25-evaluation-agent-tasks.md` 中记录此元数据变更。
111
+
112
+ <a id="server-script-source"></a>
113
+ `CsHostingEvaluation.resume(runId, interruptedAt)` 恢复当前店铺指定的运行,返回运行投影、已知的执行端最后上报时间与恢复时间。已有活动运行且此前没有恢复时,恢复时间为空。同一运行的并发调用共享一次恢复;已有活动运行不会再次启动。命令代理在执行前绑定服务端任务 id,并使用 `resumeAssigned` 只恢复该任务的运行。活动 Agent 任务引用在模型工作前持久化;写入失败会停止依赖工作。已确认用例和剧本版本保留在检查点,中断的对线用例重新开始。中断的取数或剧本 Session 在原会话写入跟进消息:“【系统跟进】Host 重启后从中断处继续。请核对未完成的工具调用和已提交结果,继续完成当前任务;外部结果未知时先核实,不要盲目重复写入。”正常停机保留 `aborted` 轮次结束;Agent 恢复接口为崩溃遗留的未闭合轮次补 `interrupted`。缺少恢复记录或外部写入结果未确认时停止恢复。
114
+
115
+ ## Server script source
116
+
117
+ `MerchantServerScriptSource` 使用同步的 server 销售案例契约实现 `EvaluationScriptSource`。用 `merchantScriptReader(account)` 从已登录商家账号构建,再用具体 server 剧本版本 UUID 调用 `load(scriptVersionId, signal)`。来源读取不可变 `SalesScriptVersion` 与其评测集,把案例素材按中国时区日期映射为买家消息,并暴露 server 已存检查项与判定输入。消息正文与案例取数对话使用同一渲染:纯文本合为一行,卡片每段不同文本只保留一份,链接保持原样,每张图片写出 URL,没有 URL 的图片写 `[图片]`,没有可读内容时写 `[非文本消息]`。必需查询命令和历史轮次来自引用的回放记录。仅存在于回放的事实设为 `requiredFacts.available=false`,因为查询前尚未提供给被测 Agent。无需订单事实时,`orderFactsAvailable` 启用 server 的事实正确性维度。剧本依赖订单事实时,每个必需订单引用及字段均须在已核实回放中可得;缺记录、数据不可得或字段缺失时保持 false。无关的订单回放不会屏蔽商品判定。指标包接收已完成的模拟时间线,未执行轮次不会生成记录引用。目的地检查保留已存目的地 id,引用订单回放的检查保留订单依赖。它把 server 回放记录转换为生产 CLI 结果,放入 `script.replay`;`CustomerServiceReplayWorld` 将这些条目与种子条目合并。生产 Host 用自己为该剧本 `caseRevision` 采集的回放(读自生产检查点)作为种子,被测 Agent 因而可读取该案例的全部已采集记录,包括剧本未引用的记录。没有该次采集的 Host 不提供种子,Agent 只看到已提交的事实。`requiredReads` 列出提供被引用记录的读取。读取失败带 server 状态与问题码;剧本对应素材不在评测集时拒绝。
118
+
119
+ <a id="human-collaboration"></a>
120
+ ## 人工协同
121
+
122
+ 剧本可提供 `humanActions`,每个计划包含 `{ kind, turn, phase, text }`。`turn` 是从 1 开始的买家轮次;`phase` 为 `before-buyer`、`after-buyer` 或 `after-reply`。已存人工协同保留作者指定的买家/助手时机。正文由剧本提供,不由买家角色生成。`answer` 与 `correction` 以 `operator from DSH` 身份进入模拟会话;`stop`、`proposal` 与 `violation` 作为不带标签的私聊用户消息进入被测 Session。人工会话步骤可以不再回复买家。
123
+
124
+ `runner.runCases({ cases, seed }, signal)` 最多抽取 `Config.humanActionSampleSize` 个合格用例(默认 3),为每个被选用例选择一个计划,再按顺序运行用例。SHA-256 排序使选择由种子和稳定的用例/剧本标识复现,不受输入顺序影响。零表示不抽样;无计划的用例不参与。用例或剧本版本标识重复、动作轮次越界时,在执行前拒绝。省略种子时生成一次,并将其与 `plannedHumanActions`、`cases` 一起放入返回的 `EvaluationRunRecord`。调用方若要在运行失败后恢复,应在开始前提供并保存明确的种子。
125
+
126
+ 运行器对买家前和回复后的动作调用目标可选方法 `intervene(action, signal, accepted)`。买家后的动作传给 `send(text, signal, human)`,在买家输入接收后、收集回复前接收。目标在输入持久化接收后通过 `accepted` 恰好确认一次;被拒绝的输入不记录为已执行动作。每次实际执行的动作将种类、轮次、剧本时间、渠道和正文写入 server 兼容用例的 `humanActions`,并在时间线上增加操作员消息。用例结束前未到达的计划仅保留在运行计划中。私聊助手回答会保留,私聊输入不会经 IM 转发。`run` 也可接收单个明确的 `humanAction`,用于受控用例。人工计划只经过目标与运行器;买家角色只额外接收驱动买家 Session 所需的 target 绑定。
127
+
128
+ <a id="sales-pairing"></a>
129
+ ## 成对销售运行
130
+
131
+ `runPaired({ cases, sales: { category, calibrationId? }, variants, seed?, pairId? })` 用同一个种子、同一个 pairId 和同一份人工动作计划,把同一批售前剧本按变体各跑一次。每组结果是一个 `EvaluationRunRecord`,其 `sales.annotation` 标明 `{ pairId, enabled }`;`sales.comparisonSeed` 为运行种子。调用方用 server 的 `CreateEvaluationRun.sales` 分别创建两次运行,并提交对应组的用例记录,server#164 据此比较两组。必须恰好一个变体开启附注、一个关闭;`apply` 返回的 disposer 由运行器在该组前后等待。
132
+
133
+ 声明 `sales.phase` 的剧本会让每个用例带上 `sales`:阶段(`presales` 或 `other`)、来自 `SimulatedBuyerRole.outcome()` 的 `simulatedDeal`(模拟买家心态进入下单状态),以及 `humanComparisons`——把逐字相同的模拟买家消息与原始买家消息、以及两条原始买家消息之间的人工回复配对。对比要求同一模拟轮次已有助手回复;没有回复的超时/错误轮次保留记录且不生成对比。重复的买家原话依次匹配历史中后续出现的位置。非售前用例不报告模拟成交与逐轮对比。
134
+
135
+ [客服托管包](../cs-hosting/README.zh.md#buying-psychology)提供 `insightAnnotationVariants(insights)`,通过 `BuyingInsights.setInjectionMode` 切换 Host 附注注入;部署配置的校准字段名单仍然生效。
136
+
137
+ <a id="purchase-intent-capture"></a>
138
+ ## 购买意向采集
139
+
140
+ 在评测请求中传入 `purchaseIntent: new ImPurchaseIntentObserver(insights)`,采集售前用例已有的购买心理分析。观察器要求该用例自己的运行中 IM 配对,只记录在被测 Session 已持久化准入来源中找到的传输入站消息。它按准确消息身份匹配,包括多消息批次;相同文本或时间戳不能确定归属。每个点引用运行器的买家消息 ID 和轮次,`at` 等于买家消息在剧本时钟上的实际发送时间;分值表示该轮客服回复前的意向估计。观察器不请求分析、不重建历史、不改变买家心态,也不改变附注注入。
141
+
142
+ `sales.purchaseIntent` 使用同步的 server 可选 schema。observed 保留原始 [0, 1] 分值;unavailable 只有原因,没有分值。分析关闭、结果缺失、取消和分析失败均不沿用上一个分值。原始分析成功后,即使客服随后失败,该点仍为 observed。身份切换和用例收尾会关闭原始观测读取器。非售前用例省略此字段。生产 case driver 装配观察器,并向商家销售运行提交记录。非售前记录携带 server 要求的空 `sales.phase="other"` 标记,不含购买意向、模拟成交或人工对比;server 跳过其销售题。商家展示使用客服产品共享分档规则,与判定阈值和模拟下单决定分开。
143
+
144
+ <a id="case-records"></a>
145
+ ## 用例记录
146
+
147
+ `EvaluationCaseRecord` 在同步的 server schema 上增加品牌化用例/剧本 id,保留 server 的消息引用校验。`EVALUATION_CONTRACT_REVISION` 记录所消费的 server 契约版本;[快照](../cs-hosting/src/sales-case-contract/SNAPSHOT.json) 记录文件摘要。用例与剧本 id 仍序列化为字符串。
148
+
149
+ 记录包含模拟与原始消息、带命中/未命中/透传分类的工具结果、结束原因、用量和判定输入,不含判定得分或判定概率;可选购买意向字段保留原始买家意向估计;server 负责判定。工具结果中的运行时操作标识可能在两次运行间不同;使用受控时钟的 fixture 可复现剧本消息、时间戳、工具事实、分类和录制用量。所属期望文件覆盖[跨两天用例](tests/expected/two-day-case.json)、[买家无效的空用例](tests/expected/empty-buyer-invalid.json)和[商品事实判定](tests/expected/product-facts-judgments.json)。
150
+
151
+ `buyerInvalidReason` 记录 Agent 买家越界改写用尽或越界检查无法判定的情况。Host 原样提交该 server 可选字段,正常用例省略。server 将这些用例排除在商家得分与报告之外,保留原因供运营查看。首条消息获准前即判无效时,带该原因的记录允许模拟消息为空;正常记录仍要求至少一条消息。Host 原样提交空无效记录,不伪造消息,运行可以正常完成。
152
+
153
+ 源测试使用 `pnpm --dir product/agent-eval run test:source`。其公共产品导入解析到源码;买家/入站 fixture 使用源码 preset 模块,拒绝执行商家 CLI。已安装 CLI 场景使用独立入口 `pnpm --dir product/agent-eval run test:built`,前提是先运行 `pnpm --dir product run build:cs-hosting`。包的完整 `test` script 运行这两组检查。标准包类型检查与这些运行时别名分别执行。source→record 测试执行[固定的 server 判定器与查询门禁](tests/support/server-facts-judge.ts),模型、证据组装与聚合使用确定性替身。
154
+
155
+ <a id="model-experience"></a>
156
+ ## 模型体验
157
+
158
+ #### 模型看到什么
159
+
160
+ 被测 Agent 接收普通 IM 消息、托管指令、产品时钟上下文,以及与生产相同的商家工具 schema。回放改变返回事实,不改变命令名或参数。
161
+
162
+ #### Token 影响
163
+
164
+ 评测增加配置的剧本轮次和普通时钟/工具上下文;运行器自身不增加评分提示词或模型请求。
165
+
166
+ #### KV Cache 影响
167
+
168
+ 每个用例有独立 Session;用例内的提示复用由普通 preset 和会话决定。
169
+
170
+ <a id="known-limitations-and-deferred-work"></a>
171
+ ## 已知限制与后续工作
172
+
173
+ 买家发现分页读取 server 正式消息,并在后续游标请求中沿用首个响应的时间窗口,不使用本地 IM 客户或已聚合案例代替来源。发现不会冻结迟到导入,补写后需要重新发现;已发布的就绪评测集与进行中的编排检查点可复用。
174
+
175
+ - 内置确定性角色不需要模型;`SimulatedBuyerRole` 需要判定客户端和买家工作区,两者由调用方提供。
176
+ - 无 key 测试使用录制判定。真实模型买家运行需要在测试组合中挂载真实 provider 适配器并提供 `DEEPSEEK_API_KEY`;`tests/simulated-buyer.spec.ts` 在 CI 使用脚本适配器。
177
+ - 成对运行只返回两组记录;调用方创建两次 server 运行并提交用例。测试店铺的真实成对验收运行属于组合验证。
178
+ - 运行在当前 Host 内,进程重启后不续跑。调用方保留完成记录,并拥有调度或上传。
179
+ - 回放条目须事先完成校验、隐私过滤和店铺/用例归属绑定。本包不挖掘历史对话或发布 Agent 配置。
180
+ - 实时世界结果可能在两次运行间变化;只有受控夹具保证事实完全相同。
181
+
182
+ 需求线列表分页只对网络错误与传输超时重试。`productionCaseReadRetries` 允许额外重试 0–10 次,默认 3 次;指数退避从 `productionCaseReadRetryInitialMs`(默认 1000 ms)开始,上限为 `productionCaseReadRetryMaxMs`(默认 10000 ms)。两个延迟均为 1–60000 ms 的整数,上限不得小于初始延迟。鉴权、额度与写入结果未知的失败不重试。管理员可在评测停止后使用“重试失败项”,为活动批次中重试耗尽的全部主选、同组备选与缺失剧本槽位各放行一次机会。Host 重启后优先读取未完成的重新取数检查点;内存中已有运行时沿用其批次类型。重试继续该检查点的集合和固定窗口,不通过已有剧本计划绕过取数流程。尚未填补的组选从已放行的主选开始,再尝试已放行备选;当前备选已成功时保留该选样。检查点的可选 `retryReleases` 记录操作 id、已认证用户 id、时间、需求线 id、revision 与原错误码,以及可选的剧本 key 和原错误码。已确认挂载与排除版本不放行;没有剧本放行字段的旧审计记录仍可读取;保留已提交结果、固定窗口、coverage set 和回放数据。这次放行不再附加阶段末的自动重试。
183
+
184
+ `prepareForHosting()` 先关闭评测准入、取消可选预览并等待其 Agent 释放与持久化,再取消并等待生产、练习与报告工作结束。必需的运行引用恢复使用商家身份与 Provider 生命周期,不随预览取消。必需读取、创建、取消或持久化结果未知时,托管准备失败并保留该失败。托管清理不再发起展示预览。精确的 server `404 NOT_FOUND` 与已持久化的结束审计确认生产批次没有 practice 运行时,无需写 practice 侧车;该分类只属于同一已结算运行和所捕获身份,scope 更换或新运行使其失效。预览范围与剧本数量上限变更不使该分类或已完成的准备失效。已有 practice 仍要求侧车,待确认创建仍须结算,CLI 仍须在 NAS 准入前关闭。已完成准备不能跨 scope 更换复用。运行创建请求发送前,将幂等引用与固定计划写入本地 metadata。Provider 重载后恢复当前租户报告;显式调用 `resume(runId, interruptedAt)` 后继续符合条件的持久运行。托管清理步骤以 warn 级别记录 `EVALUATION_HOSTING_CLEANUP`;普通预览与取消步骤以 debug 级别记录 `EVALUATION_LIFECYCLE`。固定标量字段使阶段、状态与毫秒耗时经过默认 Host 脱敏后仍保留;安全 code/cause 元数据不包含身份、请求或客户值。
185
+
186
+ <a id="dev-note"></a>
187
+ ## 开发说明
188
+
189
+ 源码检查(`typecheck` 和 `test:source`)通过 `product/tsconfig.base.json` 解析产品公共导入,不依赖产品 `lib/` 输出。`test:built` 运行已安装商家 CLI 冒烟,需要官方依赖,以及 `pnpm --dir product run build:cs-hosting` 生成的 cs-hosting 产物。`test` 命令运行两个测试入口。模拟时间戳变更需同时运行源码测试 `tests/runner.spec.ts`、`tests/im-purchase-intent.spec.ts` 与构建测试 `tests/im-runner.spec.ts`,覆盖消息/工具时间、持久化准入关联和兼容 server 的购买意向记录。
190
+
191
+ 订单归属回放夹具通过原子替换发布完整 JSON 报告,SDK 父进程轮询时不会读到尚未写完的内容。
192
+
193
+ Node Host 投影测试与客服 Client 工作台测试共享 `tests/support/evaluation-view.ts` 中的 Client 安全期望案例。Host 测试将真实服务输出与完整期望投影比较;本地化 Client 测试只读取这份数据和公开视图类型。初始化评测服务、IM 存储或 Node 内置模块的 Host 夹具只由 Node 测试程序加载。
194
+
195
+ [框架决定](../../.agents/notes/proposed/architecture/2026-10-18-agent-evaluation-runner.zh.md)记录职责与未采用的方案。
@@ -0,0 +1,13 @@
1
+ # Customer-service evaluation consumes the services provided by the hosting bundle.
2
+ - insert:
3
+ - id: gestaltrun-agent-eval-cs-hosting
4
+ name: '@gestaltrun/dsh-agent-eval/cs-hosting'
5
+ config:
6
+ desktopConcurrency: 2
7
+ scriptCap: auto
8
+ maxBuyerMessages: 150
9
+ estimatedTokensPerCase: 12000
10
+ estimatedCostUsdPerCase: 0.05
11
+ inputPerMillion: 0.5
12
+ outputPerMillion: 2
13
+ currency: CNY