Files
go-sip/docs/plan-config-read-v0.1.md

33 KiB
Raw Permalink Blame History

Go SIP Agent:配置读取与有界外呼迭代计划 v0.1

历史 v0.3 的执行入口。任务发现 v0.3 项目内合同、运行与 F09/F06 本地门禁仅保留历史证据。现行项目内 v0.4 已完成代码及隔离验收,见 plan-dispatcher-state-v0.1.md、thirds/v0.4.md和验收证据;外部 SaaS 签收与真实切换仍未完成。本文下述“当前”均指编写时的 v0.3,不能当作 v0.4 合同。 现行 contracts/upstream/v1/ 仍是旧外部基线;本文不授权真实 SaaS、生产部署、拨号或切换。分项设计:有界消费与控制通道;其他本地 SaaS 业务契约仍按第三方对接 v0.1;历史 v0.3 发现依据为计划 0926、v0.3 项目内合同及独立 Schema,v0.2也仅保留历史;现行项目内发现见上述 v0.4 合同。机器校验件:Schema/正反例。分项材料须与本文一起更新,不能继续使用旧 ETag/304、控制 CAS 或即时反馈目标。

1. 范围和完成标准

当前 P1 仍为单 D、单 Agent、单 Asterisk、单 Cell、单租户,允许同租户多任务验收;第二租户/多 D 只可另做明确标注的合同 fixture,不等于业务运行授权。真实 SaaS、OSS、云、供应商消费和外呼均另获授权;真实外呼仍遵守白名单、Asia/Shanghai [09:00,20:00) 及每线路/号码每日次数限制。未经新合同和验收,不替换现行运行规则。

拟定四条只读 GET,共用 X-DISPATCHER-id 和 X-DISPATCHER-SECRET-KEY,无请求体:

路径 用途与状态
/internal/v1/dispatcher/sip 用户指定路径;本 D 获管理面批准的 SIP 全量。
/internal/v1/dispatcher/task/:task_id 用户指定路径;任务归属、路由/主叫、智能体、时段及两项任务级超时。
/internal/v1/dispatcher/tasks?after=<cursor> 历史 v0.3 运行方式:首次 after=0、重启从已提交事件游标续读,首次与后续均按统一 tasks[] 分页。现行项目内 v0.4 改为启动 mode=snapshot 全量、运行时 after=<内存游标> 在线增量,已通过隔离 Mock;真实 SaaS 未联调。
/internal/v1/dispatcher/tenant/:tenant_id/quota 本地项目定义路径:取得任务后按其 tenant_id 读取该租户分配给本 D 的并发额度;真实 SaaS 路径兼容性未验证。

任务队列及精确绑定只由 SaaS 创建、维护和退役;D 只消费,不建队、不绑定、不删除。 SaaS 先确认持久队列 ready 再发布 persistent 消息,mandatory 无 return 且 confirm 成功才记入队。D 离线时消息可积压;无队列时未成功入队的原消息由 SaaS 保留,就绪后按原身份重新发布,不能靠 D 重启倒灌。任务队列按 D+任务 ID 定位;租户身份保留原值用于核验和额度汇总。

用户明确的消费规则:pause 保留积压,resume 消费原队列积压;stop 持久生效后静默消费并 ACK 所有未接纳积压,不拨号,不向 SaaS 发布这些消息的回执或通话结果。 静默只限定已停止任务的未接纳命令:停止控制本身仍有处理回执;已接纳/在途通话按 drain/hangup 处理并保留其最终结果。D 的错误日志、停止状态和计数不静默,ACK 丢失后重投仍不拨号、不补发被抑制结果。

完成分三层:C:F01/F07 项目内来源、版本、严格 Schema、正反例、SHA-256 对齐并通过 Mock SaaS 端到端验证;不等待外部签收;L:单 D 本地隔离闭环和故障矩阵通过;M:多 D 独占资源/份额为另行授权的后续。Mock C 不代表真实 SaaS 或供应商验收。

2. 权威资料和读法

先读本文并按 §4 选择 F 包,再读架构、现行验收、通信合同、开源复用及 contracts/upstream/v1/。新旧冲突须版本化替换,不向现行严格合同偷偷加字段。页面分析只作页面语义来源,不证明现网字段。原 plan-0918不回写;本计划 §8 是唯一新台账。

3. 冻结目标与处理规则

3.1 配置、路由、时限

  • management 是 SIP 唯一编辑/审批面,SaaS 只分发获批完整版本。SIP 变更先关准入、排空/对账,再核验实际加载;发现变化约 60 秒不等于加载完成约 60 秒。供应商 transport/auth/registration 不明不得给 real 猜默认值。
  • 新 call.execute.payload 仅 task_id/callee;外呼信封仍有 command_id 防重复拨号。任务必须返回 tenant_id/tenant_key,D 核对消息与任务归属后再按 tenant_id 取额度,身份错配/缺失即拒新准入。任务配置不返回 agent.content_sha256;版本不可变,同版本异内容拒绝,已有执行持久快照不漂移。
  • 最小路由约定(本地项目契约,F01 Schema/Mock 验证):allowed_trunk_ids 按列表顺序作为候选优先级,选首条满足时段、已加载状态、供应商/线路额度且支持任务 caller_profile_id 的线路;无满足项不接纳。caller_profile_id 是新增任务级明确引用,必须命中选中线路的获批主叫,不默认取第一个主叫。route_policy_id 只标识这份任务路由,不依赖另一个未定义的查询接口。选定线路/主叫后持久绑定;拨号失败或未知不自动换线重拨。
  • ring_timeout_ms 是任务级振铃上限;通话有效上限是任务 max_call_duration_ms 与已授权 AI conversation.max_duration_ms 的较小值,控制器和执行侧均使用同一值。两值不相同必须记录来源/有效值,不改写智能体原快照或悄悄放宽任何上限。没有逐呼 variables 的新合同不提供联系人变量来源;需要未提供变量的提示词不得以空字符串代替继续执行,须在 F01 明确静态提示词范围或补齐获批来源。
  • SIP/任务配置约 60 秒缓存到期重取完整 200,不使用 ETag/304;过期/失败拒绝新准入,不影响既有执行快照。配置内 status=running 不是恢复许可,状态按 §3.3 独立处理。
  • F02 项目内 Agent 状态校验:使用受部署配置约束的 agent_id/cell_id 查询 Agent status;applied_configs 必须恰有一条 kind="sip",且 state="applied"、十进制 revision 精确匹配获批 SIP 线路版本、observed_at_unix_ms>0,才可读取新配置/准入。缺失、重复、身份不符或匹配失败均 fail-closed。此为本地 Agent 协议规则,不是 SaaS/management 外部确认;Mock 状态不能证明真实 Asterisk 已加载。

3.2 租户额度

取得有效任务的 tenant_id 后,D 请求拟定 /internal/v1/dispatcher/tenant/:tenant_id/quota。响应包括 D、tenant_id、原值 tenant_key、额度版本、max_concurrent_calls(允许 0)、有效截止时间;该值是 SaaS 分配给此 D 的租户份额,不是每个任务各得一份。相同租户各任务复用同一额度快照/占用账本,SaaS 必须保证 tenant_id 与 tenant_key 一对一。

额度成功核验后最多缓存约 60 秒且不超过响应有效截止时间;缺失、身份错配、过期或刷新失败,关闭该租户所有任务的新准入,不使用无限额/默认额,不阻塞 stop 静默排空。额度调低时不强挂已接通通话、不抹掉已占用/未知执行,直到占用降至上限以下才再接新呼叫。D 以 SQLite 单事务检查并预留租户+任务+Cell/线路/AI 等额度,不能先分别判断后并发超卖。确认通话终结并释放执行资源后释放通话额度,不等待录音上传或 MQ 最终结果确认;未知通话继续占额。多 D 时各份额之和≤租户总额,未经 F05 授权不开放多 D 运行。

3.3 暂停、恢复、停止与状态来源(当前已实现合同)

下一版目标改为 pause/stop 均挂断在途通话、resume 不挂断,且在线任务状态切换以独立控制队列为准;见 下一版计划。以下 drain/hangup 和发现状态规则在代码/Schema 切换前仍属当前合同,不是新目标已实现。

SaaS 先持久修改权威任务状态,再向独立 D 控制队列发布 task.control。请求不含 command_id/expected_task_revision,本阶段不设计控制去重;D 按任务串行处理控制与接纳,并持久记录生效状态后才 ACK/回执。

  1. **pause:**立即关闭新接纳并保存暂停屏障,停止从该任务队列继续取新执行;已投递但未接纳的有界消息退回原队列,不能 ACK 丢弃或搬进无界 SQLite 待拨队列。已有执行按 drain/hangup 处理。重启仍暂停。
  2. **resume:**重新 GET 单任务配置(不使用约 60 秒旧缓存),只有 SaaS 最新状态为 running、归属/授权/租户额度/时段有效、且本地未 stopped,才解除暂停并恢复消费原积压。无需 SaaS 重新发原消息;已过 not_after 的旧消息仍不可拨,暂停不能冻结或延长有效期。过期/窗口外非 stopped 命令给明确拒绝回执,不等待次日自动拨号。
  3. **stop:**持久化不可逆停止屏障,同任务 ID 不能 resume/重新启用;SaaS 停止新发布。D 不申请通话额度,继续小批量消费未接纳积压,仅计本地处置计数并 ACK,不建外呼结果/outbox,不拨号。已停止任务重投/重启、额度为 0、配置缓存失效时仍可排空;不得借此清掉别的任务、伪造已接纳执行终态或漏掉控制回执/既有通话结果。
  4. **优先级:**本地 stopped 永久高于任何 running;本地 paused 只能由有效 resume 解除。tasks[] 事件页及缓存更新可使状态更严格;即使较新的发现页把 paused 改为 running,也只更新 SaaS 状态和游标,不清除已持久的暂停/停止屏障。暂停只由上述 MQ resume 配合新鲜任务读取解除,且低于已知 task_revision 的状态不得覆盖新状态。冷启动恢复本地屏障并从已提交游标追平 SaaS 事件页后取更严格者;冲突/缺失关闭新准入,不丢已有执行事实。
  5. **无编号乱序:**控制重投可能重复返回回执,不保证按消息身份“只处理一次”。pause/stop 先关闭准入;与 SaaS 最新状态不符、不可核验或接收乱序时保持关闭并返回明确失败,不根据到达先后自动恢复。恢复必须重新发送有效 resume 并核对最新权威状态;不引入替代 command_id 或控制 CAS。SaaS 不可把发布成功视为控制已应用,丢失回执下状态不明不得主动扩量。

3.4 任务发现、发布与期限(当前 v0.3)

重启全量、运行中内存游标增量为 v0.4 未实施草案;本节只描述当前运行,不得拿旧持久游标解释新快照。

D 启动/重启从已提交的 v0.3 事件游标续读(无新游标时请求 /internal/v1/dispatcher/tasks?after=0),运行中约每 30 秒继续读取。首次与后续均返回统一 tasks[] 事件页,每页最多 256 项、每 D 活跃归属最多 256 项;after 是规范十进制事件序号,不是最大 task_id。非空页的 next_cursor 必须前进,空页的 next_cursor 保持请求游标并表示本轮追平;同一任务更新后可再次出现,status=removed 为撤销墓碑,不能根据某页未出现任务推断撤销。响应不携带 queue/key,D 按 D+task ID 推导并仅消费 SaaS 预建队列。每页任务、响应和游标同事务提交,首次未追平或任何错误页都拒绝新准入,控制 MQ 保持可用。不设游标过期/410 自动重建,v0.2 checkpoint 不可解释成 v0.3 事件 ID;错误不可静默重置或回退旧 changes 路径。 SaaS 必须保证页内完整有序、旧游标及撤销墓碑长期可读;容量/灾备连续性仍待外部签收。发现项和任务配置须提供 tenant_id/tenant_key 以便核验额度;无变化不撤销消费关系。

队列 ready 不等于 D 已开始消费。 首条任务可能等待轮询、配置/额度读取和可用名额;30 秒是轮询间隔,不是端到端发现 SLA。SaaS 设置的 not_after 应覆盖允许的排队和准备时间,不能用固定 30 秒示例承诺离线恢复必拨。D 重启仅恢复原消息:未过期且有效的才接纳;过期明确拒绝(已 stopped 则静默 ACK),绝不顺延期限/自动造新 command_id 重拨。若要求更短首呼时限,必须在 F07 另定就绪通知协议,不能假设已存在。

SaaS 清单须保留已 stopped 但未排空任务;撤销握手按第三方契约执行:SaaS 停止发布,D 持久 stop 屏障、退回/排空未接纳积压、确认无未 ACK 且队列为空后回执,SaaS 收到后删除队列并发送 removed。D 不创建/删除队列;task_id 为 [A-Za-z0-9_-]{1,128},每 D 最多 256 个未退役任务队列,routing key/queue name 上限见 MQ topology。

3.5 最终结果与无录音

保留呼叫/控制回执及一种最终 call.result,不保留对外 query/replay、实时文字/拒联/录音拆分事件。用户已批准仅最终反馈,本轮实现与验收按此更新;真实 SaaS 消费兼容性另行验证。最终结果的身份在本地持久化,MQ 重投仍是同一份事实,不重新拨号或上传。

  • 已产生录音:上传 OSS 成功后 recording.status=uploaded、携带路径;上传永久失败/到有限期限后 unavailable、明确错误与 null 路径。明确上传/授权失败立即以 unavailable 收口,无确定结果最晚于 call.ended_at + 15m 收口。
  • 通话已尝试但忙线/无应答等未产生录音:终结已确认后即可发唯一结果,recording.status=not_created、身份/路径等资产值为 null,原因如 no_answer;不申请上传、不假称上传失败。录音本应生成却失败用 unavailable 和明确阶段原因,不伪装正常无录音。
  • 未接纳且被停止屏障吞掉:无命令回执、无最终结果;其他未接纳拒绝只有命令回执,不能伪造通话。已接纳取消/失败/挂断仍按其事实形成最终结果。
  • outcome 反映通话本身,录音错误写 recording 不改成呼叫失败。通话额度释放与上传/通知独立;日志只保留脱敏事实,不输出完整音频/文本/密钥。
  • 最终文字合并后的消息大小与现行 MQ 上限可能冲突,项目内 JSON 正文上限为 8,388,608 bytes,超限保留 outbox 并显式阻塞,不截断完整转写、不拆成用户已移除的实时事件来掩盖。

4. 依赖顺序与工作包

执行顺序:F00 → F01(HTTP/配置/额度)与 F07(MQ/发现/控制/结果)并行冻结 → 项目内 Mock C → F02 → F03 → F04 → F08 → F09 → F06。F05 是另获授权的后续。 F01/F07 可按各自边界并行;严格 Schema、正反例与来源/hash 对齐,并由 Mock SaaS 端到端通过后即为本地 C,不等待外部签收/连通。F03 单独负责新队列消费/状态屏障,F08 只集成结果交付和受控切换,不重复开发同一消费路径。

工作包 输入、责任与交付 门禁
F00 草案整理 集成负责人同步本文、分项设计、对接文档、配置 Schema/示例;标明用户给定路径与项目新增额度/路由字段。 正反例可验证,不冒充 SaaS 现网。
F01 HTTP 与配置/额度合同 按第三方文档冻结四条 GET、两 Header、身份映射、任务主叫/候选优先级、两时限较小值、授权/缓存/配置不可变及租户额度份额/版本/有效期。 项目内严格 Schema、来源/版本/哈希、正反例;静态提示词或变量来源明确;Mock 验证,不等待外部签收。
F07 MQ、发现及控制/结果合同 历史 F07 先冻结 v0.1 分页发现,随后 F03 v0.2 单次响应已退为历史;任务发现现按 v0.3 事件游标合同。其余 SaaS 独占队列生命周期、v3 routing、精简 call.execute、无编号控制、pause/resume/stop、回执/唯一最终结果、录音边界及消息大小/期限维持原合同。 项目内严格 Schema、拓扑、正反例、来源/hash;与 F01 一致并由 Mock 端到端验证后 C 通过。移除旧 query/replay/配置 MQ/拆分事件;外部兼容另记未验证。
F02 配置与额度读取(C 后) 接入四条已冻结 GET(本地先由 Mock 提供);D 读取并校验 SIP 实际加载、任务租户映射、按 tenant_id 的额度,完整 200 缓存;有期限拒绝与持久快照。 断服务、降额、同租户多任务、过期/错身份、新旧配置竞态不超额/不漂移;真实 SaaS 未联调不冒称通过。
F03 消费/发现/控制(F02 后) D 移除旧 --tenant-key 自建租户队列路径,按 SaaS 已建任务队列消费;发现游标/暂停恢复/停止静默ACK/独立控制与原子额度;未接纳仍留 MQ。旧分页发现结果仅属历史。 §5 的队列/控制矩阵通过;D 无建队权限仍可工作,stop静默但可排查。
F03 v0.2 任务发现修订(历史) 单次完整返回、changes/410 的前版本实现;已由 v0.3 项目内运行路径替换。 旧 Schema/证据留作追溯,不作当前运行或新版本验收。
F03 v0.3 事件游标发现 首次/后续统一 tasks[] 分页;按提交游标追平、同任务更新/removed 墓碑、错误页关准入、SQLite 同事务;无 v0.2 兼容或 410 重建。 plan-0926 与 v0.3 Schema/正反例/hash、Mock F09 及本地 F06 制品核对;SaaS 页内顺序/长期墓碑和旧状态受控切换仍待外部门禁。
F04 时段及最后拨号屏障(F03 后) 仅 Dispatcher 在持久接纳与发出呼出指令前复核任务×已绑定线路时段、任务排除日期、白名单、有效期及任务/AI 时限,持久化唯一签发/拒绝决定;Agent 只核验会话及 Dispatcher 签发期限。 本地 Mock 验证窗口边界/跨日/更新/暂停竞态不拨号、不等待或自动重试;真实路径固定时段只在外部合同、F09/F06 验收及授权后替换。
F08 结果与受控切换(F04 后) 组装 uploaded/unavailable/not_created 的最终结果与既有命令/控制回执;通话释放独立于上传;旧新版本互斥,恢复原身份 outbox。 本地全流程无重复拨号/PUT,停止积压不产生回传,已有执行结果不丢失。
F09 本地验收(F08 后) 集成负责人运行 §5 全矩阵;单 D 单租户多任务为 L,扩展 fixture 标为非 P1。 gofmt、go vet ./...、go test -race ./...、go build ./...、本模块覆盖率≥65%,脱敏证据。
F06 发布/切换(F09 后) 单写 §8 状态,核对合同/制品/队列实际版本;真实 SaaS/OSS/云/线路另外授权。 旧本地证据不代签;回退不能并行旧新写入/额度或引起重拨。
F05 多 D(后续另授权) SaaS 固定任务归属、分配各 D 有界租户/供应商份额;D 独占 Agent/Asterisk/持久目录。 各份额总和≤总额,未知执行不跨 D 迁移,不用 fixture 冒称双 D 业务。

5. 必测输入与预期结果

用例 输入/故障 必须观察到的结果
配置结构 缺身份 Header、task/消息/额度 tenant_id 或 tenant_key 不一致;agent.content_sha256/旧逐呼字段回流 拒绝新准入,不能猜默认/覆盖;call.execute.payload 仅 task_id/callee,task含两超时与明确主叫。
配置/路由 第一候选不可用、第二可用;无主叫映射;任务120秒/AI90秒;提示词缺变量 首个满足条件的候选并固定;主叫不可解/变量缺失不拨;有效时限90秒,两个控制点一致,拨后失败不自动换线。
租户共享额度 同 tenant 两任务额度各10、租户上限3,同时请求4次 合计最多3个占用;不同任务不各得3。未知占用计入。
降额/失效 已占3时从3降为1;额度0、有效期到、HTTP故障 现有不强挂、不清未知;新准入关闭,占用低于新上限且授权有效才接新;控制/stop排空不被额度阻塞。
pause/resume 暂停时队列100条、D已有有界未接纳交付;重启后恢复 暂停不丢消息/不新拨;未接纳退回原队列;重启仍暂停;有效resume继续消费原100条且无需SaaS重投,已过期的明确拒绝。
stop 静默 未接纳积压100条、在途2通、stop;ACK丢失/重启/额度0 100条最终ACK,originate=0、新回执/最终结果outbox=0;本地计数可核查。stop控制有回执,2通按策略终结并各有最终结果;其他任务不受影响。
状态优先级 pause/stop后收到旧running快照或低版本tasks;旧resume迟到/控制重复/HTTP断连 不自动恢复;resume未获最新running/未过屏障即明确失败;stopped不可逆。控制不按消息身份去重,不保证只回一次;回执不明不当成功。
新任务/离线期限 刚过轮询点新建队列;离线超过not_after;首条期限不足准备时间 消息先入已建队列;恢复只消费仍有效者,过期不拨不顺延,不自动新建外呼命令;30秒只是发请求周期。
发现/退役 首次多页、同任务较小 ID 在翻页中更新、空页、重复/超 256 项、游标倒退或 HTTP 410、removed 墓碑、SaaS 建队前误发、stopped 积压 不漏更新;每页限 256、活跃任务限 256,拒绝响应内队列字段、不截断结果;无 410 回退或重拉全量,只在同事务提交后推进游标;未入队原消息由 SaaS 保留,stopped 持续静默排空;旧状态或顺序无法证明时阻断切换。
队列权限/配额 D禁止create/bind/delete、队列满、SQLite满盘、租户满额 D只消费,不补建;SaaS保留未成功发布消息;事务失败不ACK已接纳;不会搬全部积压进SQLite,不阻塞控制/stop清理。
无录音/失败 无应答/忙线且无录音;应有录音却失败;OSS超时;停止未接纳命令 正常无录音not_created且不等待上传;明确授权/PUT失败立即unavailable,未知最晚15分钟收口;停止未接纳无回传;不能伪造call_id/成功路径。
释放与结果 已确认结束但上传慢、MQ confirm丢失或重启、完整转写超过8 MiB 通话额度已释放、未知仍占额;原结果身份重投不重拨/PUT;超限 outbox 显式阻塞,不截断/拆分/丢弃。
时间及真实边界 任务/线路交集、空日、排除日、左闭右开、最后许可前控制到达 不跨窗或被暂停/停止后新拨,不等待次日自动执行;Mock时钟不等于real放行。

6. 写入与实施边界

项目设计与本地目标契约在自身 docs 维护。contracts/upstream/v1 保持现行外部运行基线,不擅改;原 v0.1 本地合同与 F03 证据保留为历史;docs/thirds/v0.3.md 的任务发现事件游标分页已作为项目内本地运行合同完成实现与 Mock 校验,独立 v0.3 Schema、正反例和来源哈希见 F09 v0.3 证据;v0.2 Schema/证据仅保留历史。这不代表真实 SaaS 已发布、有序返回或长期墓碑容量已签收。其他业务合同沿用已有本地 v0.1 机器校验件,须记录规范文件与机器文件 SHA-256。该本地契约不冒称 SaaS/management 已发布,外部签收和连通不阻塞本地 C。本文/分项/guide/字段提案必须同步;源码、截图、真实凭据、无关父仓库不改动。TDD 先失败后实施,复用现有库,禁止隐藏错误、HTTP/MQ配置回退、重复外呼。大改另开分支,未获得子 Agent 授权由当前负责人执行。

7. I/M/G 前置

I:本地实施按本文件与第三方对接文档冻结的项目内契约;F01/F07 的严格 Schema、正反例、来源/hash 对齐以及 Mock SaaS 端到端 C 通过后即可进入 F02,不等待 SaaS/management 外部签收或连通。M:旧 W 的通过不能代替新 F02–F09;仅本地隔离验证不代表真线路/OSS通过。G:部署版本、网络/ECS只读核验、SHA-256、systemd enabled+active、Asterisk/ARI/PJSIP、媒体监听和非生产诊断门禁全部保留;实际云/生产/拨号另获授权。

8. 当前事实总台账

项目 当前事实 下一门禁
历史计划 plan-0918保留原文,只作历史。 不回写旧W台账。
F00 已对齐计划、分项设计、第三方对接、字段提案、架构/验收入口;三条用户给定路径与新增租户额度路径、项目路由字段来源均有标识,均属项目内目标,非现网合同。 Draft 2020-12 本地校验:4 个有效响应示例通过,1 个额外字段非法样例按预期拒绝;文档链接检查通过。下一门禁为 F01/F07 项目内 Schema/正反例/来源哈希冻结及 Mock C。
F01 四条只读 GET 的身份/归属、路由/主叫、缓存/版本、额度/有效期已按第三方对接文档冻结为项目内规则;resource_not_found/租户额度等 HTTP 错误映射有正向 fixture。contracts/upstream/v1 仍是现行外部基线,真实兼容性未验证。 python3 scripts/validate-local-contracts.py 通过:4 个本地 Schema、17 个配置读取正向例、HTTP 状态映射及负例;manifest SHA-256 校验通过。C 通过见下行;不代表真实 SaaS 兼容性。
F07 项目内任务发现/队列所有权与生命周期、MQ v3 控制/回执、单份 call.result、大小/期限/退役规则已按第三方文档冻结;本地正反例已校验。contracts/upstream/v1 仍是现行外部基线,真实兼容性未验证。 python3 scripts/validate-local-contracts.py 通过:发现 13 个正例、命令 6 个、结果 4 个,各 Schema 负例均拒绝;source 与 18 项产物共 19 个 SHA-256 文件通过。F03 运行时本地交付见下行;外部兼容性仍未验证。
C 本地 Mock SaaS 通过四条只读 GET、call.execute、command.result 与 synthetic call.result 的 Dispatcher 端到端交互;缺少 result queue 时 outbox 保留并在恢复后交付。 证据:local-mock-saas-c-v0.1.md。契约验证、包测试及 bash scripts/mq-integration-local.sh 通过。仅属项目内 Mock;没有真实执行、拨号、录音上传或外部验收。
F02 本地配置与额度读取模块完成:四条 GET 严格校验,四份完整响应按版本/hash/有效期持久化,任务/租户身份绑定,task+tenant 配额与 call.execute reservation 原子接纳;SIP Agent applied-config 核验、断连/过期/不匹配 fail-closed、同租户多任务和配置竞态均有 Mock 覆盖。F02 涉及四包覆盖率为 65.1%–75.0%。 证据:f02-local-config-read-v0.1.md。包测试、race、go test ./...、vet、build 和契约校验通过。F09 按用户确认的本轮 P1 业务模块 ≥65% 口径另验;CLI/历史包低覆盖率单列;F03 应用启动/消费现有本地证据见下行,真实 SaaS/Asterisk 加载仍未验证。
F03(历史分页证据) 单 D/单租户 v3 运行时曾在本地交付:只被动消费 SaaS 预建队列,持久发现游标/任务归属,暂停保留积压,恢复使用原队列,停止先持久屏障与权威状态、后静默排空并 ACK,排空完成后才写控制回执。RabbitMQ ACL Mock 证明 Dispatcher 无 configure 权限仍可消费、排空和发布;旧 tenant-queue consumer、旧 per-call control worker、CLI 旧消费参数及 MQ-only v1 acceptance runner 已移除。 证据:f03-local-task-runtime-v0.1.md。本地 acceptance、Race、vet、build、契约与无 configure 权限的 RabbitMQ 集成测试通过;internal/dispatcher 覆盖率 66.2%。仅是本地隔离验证,外部 SaaS/management、云、线路和生产均未验证;F09 新版本地矩阵见下行,历史分页证据不代签。
F07/F03 v0.3 项目内 tasks[] 事件游标页及来源/hash 冻结;Dispatcher 与 SQLite 按页原子提交,首次追平前和异常页拒绝新执行;同任务更新、撤销墓碑、断页重启从已提交游标续读、控制竞态与无重拨已完成 Mock。旧 changes/410 运行路径移除,SaaS 队列仍独占建队。 证据:f09-local-acceptance-v0.3.md。外部 SaaS 有序返回、长期墓碑容量、旧状态受控切换和真实兼容仍未签收。
F04 本地隔离 Mock 已将任务×已选线路时段、任务排除日期、白名单/有效期、绑定快照及任务/AI 较小通话时限接入接纳与发起前门禁;执行身份只有一次持久 issued/refused 决定,队列消费后由 D 经版本化 Unary 向 Mock Agent 下发,Agent 不重算业务策略、不发送 SIP。V3 mixed/real 启动拒绝,原真实固定门禁未放宽。 证据:f04-local-dial-policy-v0.1.md。Proto/合同、本地 Mock、race、vet、build、RabbitMQ 无 configure 权限及 scripts/acceptance-local.sh 通过;外部合同/真实拨号未验证。F08 后续本地结果见 f08-local-final-result-v0.1.md;F09 本地矩阵与覆盖率见 f09-local-acceptance-v0.2.md。
F08 单份最终 call.result、确认终态后独立释放额度、uploaded/unavailable/not_created、本地 Agent→D 录音失败事实与原身份 outbox 已完成隔离 Mock 验证;V3 Mock 不并行写旧分散事件,V3 mixed/real 启动拒绝。证据:f08-local-final-result-v0.1.md。 scripts/acceptance-local.sh(含 race、vet、构建及受限 RabbitMQ)通过;Mock 录音成功/失败由合成事实注入,默认 Mock 只模拟无应答,无实际媒体/OSS PUT,publisher confirm 不等于 SaaS 应用签收。F09 本地验证见 f09-local-acceptance-v0.2.md;F06 真实部署/切换仍未获授权。
F09 v0.3 首次多页、空页、同任务重现及墓碑、翻页中更新、断页重启、坏游标/410 失败、SQLite 写失败同事务回滚、MQ 控制竞态(含发现 paused→running 仅更新状态/游标、须 MQ resume+新鲜任务核验才恢复队列)、重复执行不重拨完成单节点/单租户本地 Mock 验证;旧 F09 v0.2 证据仅作历史。证据:f09-local-acceptance-v0.3.md。 scripts/acceptance-local.sh(格式/合同/Proto/hash、race、vet、构建、受限 RabbitMQ)通过;P1 业务包 66.4%–85.4%(MQ 含 integration)。CLI 30.0% 和历史 callruntime 61.7% 单列技术债,不声称全仓达标;SQLite 写失败用触发器注入,未物理填盘。外部有序返回/墓碑容量/真实验收未完成。
F06 Go 1.27.1 一次性本地制品/校验和将 v0.1 其他业务+v0.3 任务发现+v3 MQ 拓扑及 Proto 版本/hash 写入清单;已有 release/package/归档拒绝覆盖,制品 mixed/real 在开 DB 前拒绝;旧 CLI 和分散事件不在新运行路径。证据:f06-local-release-gates-v0.3.md。 make release-check-local 与本地 acceptance 通过;来源 dirty、production_approval=false。外部 SaaS 有序返回/长期墓碑容量、v0.2 旧状态受控切换、真实部署/拨号与生产签收均未完成;本地阻断不代签真实切换。
F05 多D/第二租户不在本轮运行范围。 另获阶段与额度/资源授权。
下一版 Dispatcher 状态/临时数据(仅文档) plan-dispatcher-state-v0.1.md 与 thirds/v0.4.md 记录用户本轮提出的重启全量、状态来源收敛、pause/stop 强制挂断与任务结束条件清理;当前代码、Schema、F09/F06 证据未切换。日志全部原样的要求与现行禁令冲突,不列为已批准实施。 冻结全量分页与控制交接、SaaS 应用收讫/恢复依据、清理期限及新严格 Schema/Mock;TDD 实施后再重跑本地门禁。外部兼容、真实拨号和切换另签收。

9. 协作与版本记录

仅集成负责人更新本文 §8、公共合同和合并状态;有并行授权时一 lane 一工作区/独占写集合、每批回归,不假定未跟踪文件在 HEAD。v0.1 是项目规划及字段草案,不是 W01/SaaS 正式发布版本。真实环境的资源、拨号和生产权限不因文档改动增加。