docs: record P1 local acceptance and external gates
This commit is contained in:
@@ -6,7 +6,11 @@
|
||||
|
||||
本文件是 [Go 重写方案](../architecture/Go重写方案_v0.3.md) 的执行清单,**不是验收通过报告**。项目内已具备 Go 可执行程序、W01/W02 契约与本地测试入口;下文仍将本地通过、协议 Mock、真实集成和生产签收严格分开。
|
||||
|
||||
**本轮MQ-only修订重新打开受影响验收**:SaaS↔D所有请求/响应/事件只能走RabbitMQ,每个D全局唯一ID、独立接收Topic/队列。旧HTTP/仅租户路由/本地OSS验证证据不能覆盖新基线,现行 MQ-only 旧版验证事实见[归档计划§8.2](../archive/plan-0918.md)和[现行 MQ 机器契约](../../contracts/upstream/v1/mq.schema.json);第三方时序说明见[事件顺序](../thirds/第三方对接事件与请求消费顺序_v0.1.md),用户新批准的两只读 HTTP 配置接口仍须按[新计划](../plan-config-read-v0.1.md)另验。新增子场景纳入既有88项,不新增虚假通过数;本轮仅改文档,未执行这些运行测试。
|
||||
**现行外部 MQ-only 合同仍有效;本文件不是验收通过报告。** 现行外部事实见[归档计划§8.2](../archive/plan-0918.md)和[现行 MQ 机器契约](../../contracts/upstream/v1/mq.schema.json)。本轮 P1 本地目标按[配置读取计划](../plan-config-read-v0.1.md)实施四条只读 GET、v3 MQ 与最终 `call.result`;除任务发现已按 [v0.2 §2.5](../thirds/v0.2.md) 修订外,其余项目内合同沿用[第三方对接 v0.1](../thirds/第三方对接事件与请求消费顺序_v0.1.md)。F01/F07 严格 Schema、正反例、来源/hash 和 Mock C 是本地门禁,不等待外部签收/连通;C 后按 F02→F03→F04→F08→F09 重验适用的 88 项子场景,不新增虚假通过数。旧 HTTP/租户路由/OSS 证据不能覆盖新基线;真实 SaaS、management、云、供应商和生产切换仍分别未验证。
|
||||
|
||||
任务发现的单次完整响应修订见 [v0.2 项目内合同](../thirds/v0.2.md)及[严格 Schema](../contracts/task-discovery-v0.2-proposal.schema.json):每 D ≤256、响应不带 queue 地址、空变更保留游标、`removed` 退役和 410 后全量恢复已通过 [F03 本地 Mock 验证](../evidence/f03-local-task-discovery-v0.2.md),F09 完整矩阵仍待重验。原 v0.1 分页 F03 证据保留为历史,不能计入新版通过;真实 SaaS 兼容性仍未验证。
|
||||
|
||||
[F04 本地 Mock 证据](../evidence/f04-local-dial-policy-v0.1.md)仅证明 Dispatcher 的任务×已选线路时段与最后拨号屏障、持久一次性决定及 Mock Agent 指令期限检查;Agent 不重算业务策略,也没有真实 SIP 发起。F08 最终结果/额度释放和 F09 全矩阵未完成;现行真实路径的固定 `09:00`–`20:00` 门禁未放宽,V3 mixed/real 启动拒绝。
|
||||
|
||||
每个阶段分别报告:通过、失败、未执行、被外部条件阻塞,以及“本阶段不适用/延后”。延后不得计入通过率或当成实现。旧Python证据不计Go通过数;管理平台、SIP Mock、供应商和Go Agent分别签收。
|
||||
|
||||
@@ -18,16 +22,16 @@
|
||||
| --- | --- | --- |
|
||||
| P1-01 独立制品/契约 | 单module/Cobra双命令独立构建;格式化/vet/race/构建及实际依赖门禁通过,使用入口与引用Schema可追踪;GAP的P1部分关闭 | C01–C11、L01–L08、A01/A02 |
|
||||
| P1-02 单节点就绪 | 恰有1 Agent/1 Asterisk、1单活D;单 Cell 完成绑定/版本/健康/准入与隔离链路验证;失联或未授权时停止新接单,单 Cell 仅接满足授权与全局额度的新执行 | A03–A11/A18/A20、S07/S10;单 Cell/固定出口 fixture |
|
||||
| P1-03 至少3家SIP | 至少3个不同供应商独立trunk;登记单 Cell/出口授权、主叫/前缀/codec/额度,使用配置/路由/协议 fixture 覆盖;未知/未授权组合拒绝;SIP 外呼时间门禁为 Asia/Shanghai `09:00`(含)至 `20:00`(不含),边界外 fail-closed;真实供应商外呼延期第二阶段 | E01–E08/E20;供应商配置矩阵、SIP/ARI/媒体 fixture、`internal/callwindow` |
|
||||
| P1-03 至少3家SIP | 至少3个不同供应商独立trunk;登记单 Cell/出口授权、主叫/前缀/codec/额度,使用配置/路由/协议 fixture 覆盖;未知/未授权组合拒绝;本地 F04 Mock 由 Dispatcher 按 Asia/Shanghai 任务×已选线路时段及任务排除日期判定;现行真实路径仍须固定 `09:00`(含)至 `20:00`(不含)且边界外 fail-closed;真实供应商外呼延期第二阶段 | E01–E08/E20;供应商配置矩阵、SIP/ARI/媒体 fixture、`internal/callwindow` |
|
||||
| P1-04 ASR-only | 百炼/火山两ASR适配分别验证;D从契约 fixture 取批准版本,命令→ASR文字/录音→结果 outbox 闭环;LLM/TTS不可用不影响且调用/额度为0;ASR参数实际生效、无虚假播放 | GAP-08/09、E09/E14/E17/E22、L06/§5.1;单 Cell 隔离组合 |
|
||||
| P1-05 完整AI | OpenAI兼容LLM+火山TTS在本地/协议隔离环境完成双向对话/取消/打断/超时/背压验证;契约参数直达SDK/控制器,调参不改代码/重启,不硬编码model/voice/speed;无旧实现/静默降级/旧音频重播;真实供应商费用/联调延期 | E09–E11/E14/E17/E22、L06/§5.1;协议/参数/音频 fixture |
|
||||
| P1-06 结果与资产 | 所有SaaS↔D业务改经MQ,8类业务事件及新版请求响应正反例通过,无HTTP兼容/回退;实时文字/opt-out及时,补传保留原事件ID而不重发执行;Agent直传字节一致,D将recording.uploaded可靠交付指定持久队列;不等待SaaS会话/verified/OSS ID,通知恢复不重传文件或重拨 | S01–S04/S16/S23、E08/E12/E17–E19、A07/A15/A16 |
|
||||
| P1-06 结果与资产 | 区分现行外部 v2 与本地目标 v3;本地仅验证四 GET、必要命令/控制回执及单份最终 `call.result`,不恢复 query/replay/实时文字/opt-out/拆分录音事件;Agent直传及持久通知恢复不得重传文件或重拨;超限按 8 MiB 规则阻塞,不截断 | F01/F07 Schema/Mock C、F08/F09 本地适用场景;现有 S/E/A 证据仅作旧基线 |
|
||||
| P1-07 租户骨架/全局额度 | 只启用1个租户,未启用租户拒绝;独立队列/原值key/复合幂等/窗口受控;单 Cell 竞争租户/供应商/按模式AI额度不超配;双租户和跨 Cell 汇总不在本轮 | C05–C07、S08/S09/S18/S20–S22;SQLite/实际许可计数 |
|
||||
| P1-08 故障与控制 | 重投10次同一执行只产生一次实际发起;覆盖§4.1崩溃窗口、MQ/Unary/ARI断连及D/A重启,未知不重拨/不释放;pause/stop/CAS/最后许可及 `09:00`–`20:00` 时间门禁正确,旧库恢复正确 | S01–S27的P1部分、E02/E03/E13/E21、A07/A08/A18/A20 |
|
||||
| P1-08 故障与控制 | 重投同一 call.execute 只产生一次实际发起;覆盖§4.1崩溃窗口、MQ/Unary/ARI断连及D/A重启,未知不重拨/不释放;本地 pause/resume/stop 按 F07 顺序/状态/ACK/退役规则通过,不引入旧 v2 控制 CAS;任务发现单次完整快照/增量、≤256条、拒绝分页/queue 字段、空变更、removed、410 全量恢复与无建队权限均须重新测试;F04 本地 Mock 最后许可及持久签发/拒绝决定按任务×已选线路时段拒绝窗口外发起、不等待或自动重试;真实路径固定 `09:00`–`20:00` 仍须独立验证 | F03/F04/F09 本地适用场景;旧 S/E/A 证据不替代新控制合同 |
|
||||
| P1-09 静态配置/稳定性 | 管理批准制品经维护窗口加载;错误版本/哈希、未排空/未确认、部分失败均不恢复相关准入;两种模式按§9.1受限隔离负载持续稳定测试,告警/录音/资源无未解释泄漏 | E04/E05/E13、A09–A14的P1部分、S27;单 Cell profile与原始计数器 |
|
||||
| P1-10 本地恢复/授权 | 单节点唯一写入与唯一调度所有权、备份/维护更新/恢复演练通过;契约/fixture 签收白名单、时段、限额/预算与风险;明确D单点和未上传资产丢盘边界。生产切换与真实授权延期第二阶段 | §7/§8、A06/A17–A20;运维步骤与隔离签收记录 |
|
||||
| P1-10 本地恢复/授权 | 单节点唯一写入与唯一调度所有权、备份/维护更新/恢复演练通过;项目内契约/fixture/Mock C 留证,白名单、时段、限额/预算与风险边界明确;D单点和未上传资产丢盘边界明确。生产切换与真实授权另行申请 | §7/§8、A06/A17–A20;本地运维步骤与隔离证据 |
|
||||
|
||||
两模式均需在本地/协议隔离环境验证,所有纳入本轮的供应商配置 fixture 和单 Cell 组合分别留存闭环证据;稳定性长跑按批准的隔离负载矩阵覆盖全部 fixture。SIP 外呼时间窗口使用注入时钟覆盖 08:59:59、09:00:00、19:59:59、20:00:00 四个边界,窗口外必须在最后许可前失败且不产生 originate。真实供应商、ECS、生产 SaaS/MQ receipt 和生产切换如实标记为第二阶段,不能把 fixture 写成真实联调完成。
|
||||
两种 AI 模式均需在本地/协议隔离环境验证,所有纳入本轮的供应商配置 fixture 和单 Cell 组合分别留存闭环证据;稳定性长跑按批准的隔离负载矩阵覆盖全部 fixture。F04 本地 Mock 按 Asia/Shanghai 的任务×线路时段、跨日、任务排除日期及左闭右开边界注入时钟;拒绝后持久记录且不产生 Mock Agent originate。现行真实路径另须覆盖固定窗口 08:59:59、09:00:00、19:59:59、20:00:00 四个边界,窗口外必须在最后许可前失败且不产生真实 originate;Mock 不代替真实门禁。真实供应商、ECS、生产 SaaS/MQ receipt 和生产切换如实标记为第二阶段,不能把 fixture 写成真实联调完成。
|
||||
|
||||
### 1.2 88项基线的阶段适用规则
|
||||
|
||||
@@ -246,7 +250,7 @@ P1运行不依赖旧Python Cell;迁移验证如需临时桥接而旧端不满
|
||||
6. P1受限稳定性与已授权费用;P2公平调度;后续完整1000路/N+1分别签收。
|
||||
7. P1维护切换、人工恢复、备份演练;在线发布/HA切换待相应功能启用另验。
|
||||
|
||||
本轮仅能检查第 1 类中的文档结构与一致性,不能把尚未生成的 Go 测试/服务列为“通过”。
|
||||
本轮需按配置读取计划完成项目内 F01/F07、Mock C、F02–F09;每项只在产生可复核的本地测试/服务证据后记“通过”。任何本地结果都不替代真实 SaaS/management 或生产验收。
|
||||
|
||||
开发前的交付/解锁证据见 [G0开发准备与契约冻结方案](../architecture/G0开发准备与契约冻结提案_v0.1.md) §2/§5/§8。D01–D10方案已获用户确认;项目内 W01 版本和 W02 Proto 已交付,但外部权威签收、D10正式PoC和真实供应商仍未完成;十项交付门禁不增加本方案88项运行验收数量。§5.5内部profile已确认为隔离PoC初始值,未实测、不是生产SLA,也不覆盖下节上游/供应商基线。P1必须实施当前租户及单 Cell 原子配额,P2/第二阶段再扩展多租户公平、跨 Cell 和并行竞争验收。
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Dispatcher 有界接纳与控制通道改造计划 v0.1
|
||||
|
||||
**下一版设计草案,未实施、未获 SaaS 签收。** 唯一计划/台账是[plan-config-read-v0.1](../plan-config-read-v0.1.md);对外结构见[第三方对接](../thirds/第三方对接事件与请求消费顺序_v0.1.md)。本文同步替代此前的 ETag/304、控制 CAS、暂停丢弃旧积压和逐条停止回执方案,不修改现行 `contracts/upstream/v1/`。
|
||||
**项目内 P1 设计计划,尚未实施;本地 F01/F07 Schema、正反例、来源/hash 与 Mock C 是实施门禁,不要求 SaaS 外部签收。** 唯一计划/台账是[plan-config-read-v0.1](../plan-config-read-v0.1.md);项目内对接结构见[第三方对接契约](../thirds/第三方对接事件与请求消费顺序_v0.1.md)。本文同步替代此前的 ETag/304、控制 CAS、暂停丢弃旧积压和逐条停止回执方案,不修改现行 `contracts/upstream/v1/`;外部兼容性未验证。
|
||||
|
||||
路径来源:`/internal/v1/dispatcher/sip`、`/internal/v1/dispatcher/task/:task_id`、`/internal/v1/dispatcher/tasks`(含 `?after=<cursor>`)为用户给定路径;`/internal/v1/dispatcher/tenant/:tenant_id/quota` 与任务路由字段 `route_policy_id`、`caller_profile_id`、`allowed_trunk_ids` 为项目内目标,按第三方对接契约和 F01/F07 Schema 实施;不代表 SaaS 现网字段,真实兼容性另记。
|
||||
|
||||
## 1. 目标与范围
|
||||
|
||||
@@ -15,7 +17,7 @@ SaaS 先建持久任务/控制队列和精确绑定,再发布 persistent 消
|
||||
- `/internal/v1/dispatcher/sip`:本 D 获批 SIP 全量,变更关准入、排空/核验实际加载。
|
||||
- `/internal/v1/dispatcher/task/:task_id`:任务及AI、tenant_id、tenant_key、明确主叫、候选线路优先级、两项任务超时。
|
||||
- `/internal/v1/dispatcher/tasks`:启动一致全量/水位,运行每30秒 `?after=<cursor>` 获取变更;cursor非最大任务ID,旧ID变化也返回。
|
||||
- `/internal/v1/dispatcher/tenant/:tenant_id/quota`:**新增路径/字段待签收**;拿到任务后取该租户分给本 D 的额度、版本、截止时间。额度0不接纳,缺失/过期失败不猜默认值。
|
||||
- `/internal/v1/dispatcher/tenant/:tenant_id/quota`:本地项目定义路径;拿到任务后取该租户分给本 D 的额度、版本、截止时间。额度0不接纳,缺失/过期失败不猜默认值;真实 SaaS 路径未验证。
|
||||
|
||||
SIP/任务完整200响应最多缓存约60秒;租户额度也最多约60秒且不超过有效截止时间。不使用 ETag/304。同租户任务复用一份额度与占用,降额不强挂、不清未知;占用低于新限额后才接新。任务时限和AI授权对话时限取较小值;路由按任务获批候选顺序选首个可用且支持明确主叫的线路,拨号后不得自动换线重试。
|
||||
|
||||
@@ -28,23 +30,23 @@ SIP/任务完整200响应最多缓存约60秒;租户额度也最多约60秒且
|
||||
| running、有名额 | 有界接收并原子预留;满额不继续搬队列 | 依持久快照执行 | 接纳/拒绝回执,发生执行后最终结果 |
|
||||
| pause | 关闭准入并暂停消费,已交付未接纳消息退回原队列,不ACK丢弃 | 按drain/hangup | 暂停控制回执;不把暂停积压当作逐条拒绝 |
|
||||
| resume | 强制读取最新任务,running且授权/额度/时段有效才恢复原队列;过期消息拒绝,未过期正常接纳 | 不改旧快照 | 恢复控制回执;无需SaaS重发原积压 |
|
||||
| stop | 先持久停止屏障,再小批量消费并ACK,**无拨号、无逐条回执、无最终结果** | 按drain/hangup处理,保留真实执行结果 | stop控制本身有回执;静默只针对尚未接纳消息 |
|
||||
| stop | 按第三方契约 §0 持久 stopped 屏障,退回已预取未接纳消息并以 `basic.get` 静默 ACK 积压至空;**无拨号、无逐条回执、无最终结果** | 按drain/hangup处理,保留真实执行结果 | 队列无未 ACK 且为空后回 stopped/applied;SaaS 收到后才退役队列 |
|
||||
|
||||
本地 stopped 不可逆,同任务ID不得再resume;paused只有有效resume可解锁。tasks增量/全量和配置缓存不能用旧running解除屏障,低版本不能覆盖高版本;冲突/HTTP错误关新准入。SaaS先持久修改权威任务状态再发控制;无编号控制不设计去重/请求CAS,重投可能重复回执,不能声称exactly-once。乱序/权威状态不符时明确失败并保持关准入,不能根据旧resume自动重开;控制恢复需要新的有效resume核验。
|
||||
本地 stopped 不可逆,同任务ID不得再resume;paused只有有效resume可解锁。tasks增量/全量和配置缓存不能用旧running解除屏障,低版本不能覆盖高版本;冲突/HTTP错误关新准入。SaaS先持久修改权威任务状态再按每任务顺序发控制;无编号控制不设计去重/请求CAS,重投可能重复回执,不能声称 exactly-once。乱序/权威状态不符时明确失败并保持关准入,不能根据旧 resume 自动重开;恢复需要新鲜任务 GET 确认 running。具体状态和错误按第三方契约 §0/§3。
|
||||
|
||||
D重启恢复屏障再应用SaaS全量,取更严格状态。stop排空不依赖通话配额/AI配置可用性:额度0、配置过期仍可ACK;ACK丢失重投再次静默处理。静默仍须保留脱敏计数/错误/恢复事实,不能删除其他任务或忽略已在途执行。SaaS在停止新发布、队列积压和未ACK清零、未知执行核清并完成签收的退役核验后才删队列;队列空不是通话结束证明。
|
||||
D重启恢复屏障再应用SaaS全量,取更严格状态。stop排空不依赖通话配额/AI配置可用性:额度0、配置过期仍可ACK;ACK丢失重投再次静默处理。静默仍须保留脱敏计数/错误/恢复事实,不能删除其他任务或忽略已在途执行。SaaS停止发布后,D 结清已预取投递并 `basic.get` 至空;仅在无未 ACK 且收到 stopped/applied 回执后,SaaS 才能删除队列/绑定并随后发 `removed`。队列空不是通话结束证明。
|
||||
|
||||
## 4. 期限、占用与结果
|
||||
|
||||
30秒轮询不是端到端发现保证,首条命令还需分页/配置/额度准备;有效期由SaaS覆盖其可接受排队时间,不使用30秒默认值。离线/暂停不延长not_after;过期/窗口外非stopped消息明确拒绝,不等待次日。stopped积压即使过期仍静默ACK。
|
||||
|
||||
只有核实通话终结并释放执行资源才释放通话额度,未知不释放;**不等待录音上传和最终消息确认**。录音上传成功后单份call.result带OSS路径;正常未产生录音(忙线/无应答)以not_created即时终结,不申请上传;应有录音但失败用unavailable,上传失败/超时须签收有界终结期限。未接纳且stopped静默处理没有call.result,其他未接纳拒绝只有回执,不造通话。最终文字大小及无截断策略需F07签收,MQ重投同一事实身份不重拨/重PUT。
|
||||
只有核实通话终结并释放执行资源才释放通话额度,未知不释放;**不等待录音上传和最终消息确认**。录音上传成功后单份 call.result 带 OSS 路径;正常未产生录音(忙线/无应答)以 `not_created` 即时终结,不申请上传;授权/PUT 明确失败立即以 `unavailable` 收口,仍无确定结果最迟于 `call.ended_at + 15m` 收口。未接纳且 stopped 静默处理没有 call.result,其他未接纳拒绝只有回执,不造通话。每条 JSON 消息体上限 8,388,608 bytes;超限持久阻塞 outbox,不截断/拆分/丢弃;MQ 重投同一事实身份不重拨/重 PUT。
|
||||
|
||||
取消对外查询/补传与拆分实时文字/拒联/录音事件,不取消内部恢复、日志和外呼幂等。最终通知延迟对拒联业务的影响必须获业务签收。
|
||||
取消对外查询/补传与拆分实时文字/拒联/录音事件,不取消内部恢复、日志和外呼幂等;本轮用户已批准仅最终反馈,真实 SaaS 消费兼容性另记。
|
||||
|
||||
## 5. 开发先后与验收
|
||||
|
||||
不再维护另一套 B 工作包。使用总计划:F01(HTTP/额度)与F07(MQ/发现/状态/结果)并行冻结并联合C → F02配置读取 → F03仅此处的消费/屏障 → F04最后许可/时段 → F08结果集成与切换 → F09矩阵验证 → F06发布。F05多D另授权,避免F01/F07互等和F03/F08重复实现。
|
||||
不再维护另一套 B 工作包。使用总计划:F01(HTTP/额度)与F07(MQ/发现/状态/结果)并行冻结 → 项目内 Mock C → F02配置读取 → F03仅此处的消费/屏障 → F04最后许可/时段 → F08结果集成与本地发布准备 → F09矩阵验证 → F06发布。C 不等待外部签收;F05多D另授权,避免F01/F07互等和F03/F08重复实现。
|
||||
|
||||
必须覆盖总计划§5:同租户多任务原子上限/降额/未知、pause积压100条并在resume继续、stop积压100条后originate/outbox均0而已有2通结果保留、重启/ACK丢失、旧running/迟到resume不解锁、任务ID小而版本新、分页/游标失效、D无建队权限、离线期限、无录音、确认终结即释放额度而OSS延迟、完整最终转写超限。
|
||||
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
## 1. 状态、权限与使用方式
|
||||
|
||||
**状态:D01–D10原方向已确认,旧W01契约和W02 Proto已有项目内证据;本轮用户确认SaaS↔Dispatcher全MQ,受影响G0的项目内部分已按[归档旧计划§1.2/§8.2](../archive/plan-0918.md)重新验证;本轮两只读 HTTP 配置目标见[新计划](../plan-config-read-v0.1.md),旧验证不覆盖新接口。** SaaS与D之间所有请求、响应和事件禁止HTTP,每个D具备全局唯一ID和独立接收Topic/队列;V1 Schema、拓扑和关联已有本地包及RabbitMQ证据,外部发布/签收另计。OSS补充确认:配置存于D配置文件,A向D领取固定15分钟临时上传TOKEN后直传;SaaS不再提供OSS配置/TOKEN,上传完成以recording.uploaded可靠入队为界,不等待SaaS verified或OSS ID,D不转发文件。原HTTP方向被本修订替代,不把旧证据覆盖到新设计。
|
||||
**状态:D01–D10原方向已确认,旧W01契约和W02 Proto已有项目内证据;现行 SaaS↔Dispatcher MQ-only 合同及受影响G0的项目内检查仍是当前外部运行基线;本轮四条只读 HTTP GET(SIP、单任务、任务发现、租户额度)和单份最终 `call.result` 的项目内契约见[新计划](../plan-config-read-v0.1.md),完成 F01/F07 Schema、正反例、来源/hash 与 Mock C 后可继续本地实现,不等待外部签收或连通。** 现行真实 SaaS 与 D 之间仍遵循已发布 MQ 合同;每个 D 具备全局唯一 ID 和独立接收 Topic/队列。V1 Schema、拓扑和关联已有本地包及 RabbitMQ 证据,外部发布/签收另计。OSS 补充确认:配置存于 D 配置文件,A 向 D 领取固定 15 分钟临时上传 TOKEN 后直传;SaaS 不再提供 OSS 配置/TOKEN,上传完成以 `recording.uploaded` 可靠入队为界,不等待 SaaS verified 或 OSS ID,D 不转发文件。本地 C 不宣称 G0、外部兼容、生产验收或上线授权。原 HTTP 方向被本修订替代,不把旧证据覆盖到新设计。
|
||||
|
||||
本项目已创建并验证自己的 Go module、W01 bundle、W02 Proto/stubs、RPC/mTLS 和本地 Mock 测试;未修改父项目权威来源、字段索引或生成产物,未访问真实供应商或创建云资源。文件名保留“提案”以保持链接稳定,不代表还需重复审批已确认方向。
|
||||
|
||||
当前结论:可以继续开展 P0 契约补充、隔离 PoC 和项目内实现;不得宣称 G0 通过或把项目内基线冒充外部权威,也不得启动未获授权的真实供应商/云/拨号。架构、首发范围和供应商方向沿用已有决定,不重新选型。
|
||||
|
||||
- 外部字段/路径/状态仍以带来源哈希的上游主契约为准。本文件记录已确认的变更方向和验收要求,**不能被代码当 Schema 使用**。后续由上游维护者修改唯一来源并发布,再导入生成;本文件保留为决策历史,不继续手工维护字段副本。
|
||||
- 对现行真实 SaaS v1,字段/路径/状态仍以带来源哈希的上游主契约为准。本轮本地目标的规范来源是第三方对接文档,`docs/contracts` 中版本化 Schema、正反例和拓扑为其机器校验件并记录来源/hash;该本地合同不冒称外部发布。本文件仍是 G0 决策历史,不替代上述两类规范。
|
||||
- 内部机制、字段方向及兼容策略已确认,正式 Proto 的类型/编号/错误映射等仍需定稿与校验。本轮不生成 `.proto`,也不以临时 JSON 绕过契约;未提供的字段细节、实际预算和技术验证不能视为一并通过。
|
||||
- 角色简称:S=SaaS/上游契约维护方,M=管理平台维护方,D/A=Dispatcher/Agent 实现方,O=部署/安全/测试负责人。角色不代表已指定人员或已签收;实际姓名、版本、日期和证据须在批准记录补全。
|
||||
- 保留既有业务语义和8类业务事件,但原7条SaaS HTTP路径与AI GET全部废弃为接入方式;控制/查询/补传/配置授权/上传协调都改为专用MQ请求响应。D↔A仍Unary,A→OSS仍直传,不新增任务mode字段或内部MQ。
|
||||
- 以上为 G0 原阶段决策记录:现行 v1 下控制/查询/补传/配置授权/上传协调走专用 MQ。与本轮四条只读 GET、单份最终 `call.result` 目标相关的本地配置及事件边界,以[新计划](../plan-config-read-v0.1.md)和第三方对接契约为准;新本地代码通过 C 前,旧代码/真实外部运行仍按现行 v1。无需外部签收即可完成本地 C;真实切换另行授权与验证。D↔A仍 Unary,A→OSS仍直传,不新增任务 mode 字段或内部 MQ。
|
||||
- 依据:[重写方案](Go重写方案_v0.3.md)、[通信设计](../contracts/通信与事件数据交互_v0.1.md)、[验收方案](../acceptance/验证与切换验收_v0.3.md)、[只读字段索引](../references/OpenAPI与MQ字段索引_v0.1.md)、[组件清单](../dependencies/开源组件选型与复用清单_v0.2.md)。索引不是独立契约包。
|
||||
|
||||
## 2. 方案确认记录与开发边界
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SIP Go Agent 重写方案 v0.3
|
||||
|
||||
本版按本次讨论收敛为**稳定、快速单节点内测上线**:1个Agent/1套Asterisk/1个单活Dispatcher、单 Cell、单租户、静态发布、ASR-only与ASR+LLM+TTS双模式。至少3家SIP供应商保留为 trunk 配置与协议 fixture 覆盖;双节点、第二 Cell、双租户、真实 SaaS/MQ 联调和生产 ECS 延期第二阶段。保留Cobra双命令、Dispatcher SQLite、Agent文件、Unary gRPC及关键可靠性;动态治理和规模化另立项。文件名保留,当前仍只有文档,不代表实现或验收通过。
|
||||
本版按本次讨论收敛为**稳定、快速单节点内测上线**:1个Agent/1套Asterisk/1个单活Dispatcher、单 Cell、单租户、静态发布、ASR-only与ASR+LLM+TTS双模式。至少3家SIP供应商保留为 trunk 配置与协议 fixture 覆盖;双节点、第二 Cell、双租户、真实 SaaS/MQ 联调和生产 ECS 延期第二阶段。保留Cobra双命令、Dispatcher SQLite、Agent文件、Unary gRPC及关键可靠性;动态治理和规模化另立项。文件名保留,当前仍只有文档,不代表实现或验收通过。配置读取及最终反馈改造以[本轮计划](../plan-config-read-v0.1.md)为准:目标为 SIP、单任务、任务发现、租户额度四条只读 GET,并以一份最终 `call.result` 替代实时转写、即时拒联和拆分录音事件。F01/F07 联合 C 与业务签收前,本文记录的 MQ-only 配置和既有事件仍是运行合同;不能据新提案声称新路径/事件已生效。
|
||||
|
||||
## 1. 状态、范围与决策
|
||||
|
||||
@@ -111,19 +111,20 @@ Dispatcher配置包含MQ/SaaS受控引用、SQLite路径、两个Agent Endpoint
|
||||
|
||||
### 3.2 权威来源与独立拆仓
|
||||
|
||||
**本轮用户已确认SaaS↔Dispatcher全MQ:双方不再有任何HTTP请求/回调;每个D有全局唯一ID和独立接收Topic/队列。** 执行、控制、查询、补传、AI配置/授权及上传完成事实均经MQ;上传不申请SaaS会话、不等待verified/OSS ID,详见[现行 MQ Schema](../../contracts/upstream/v1/mq.schema.json)、[第三方事件顺序](../thirds/第三方对接事件与请求消费顺序_v0.1.md)与[归档旧计划§1.2/§8.2](../archive/plan-0918.md);这是现行已发布 MQ-only 合同的历史依据,后续仅配置改为两只读 HTTP 接口的目标见[新计划](../plan-config-read-v0.1.md),尚未成为运行事实。旧HTTP和旧租户路由已删除;新Schema/拓扑/身份生命周期/关联已在项目内唯一 V1 包和本地证据中冻结,旧源包及哈希不改。
|
||||
**外部当前基线**仍是已发布的 SaaS↔Dispatcher MQ-only v2:真实运行中的执行、控制、查询、补传、AI配置/授权及上传事实沿用[现行 MQ Schema](../../contracts/upstream/v1/mq.schema.json)及[归档旧计划§1.2/§8.2](../archive/plan-0918.md),不擅改上游包。**本轮 P1 本地目标**按[新计划](../plan-config-read-v0.1.md)和[第三方对接项目契约](../thirds/第三方对接事件与请求消费顺序_v0.1.md)使用四条只读 HTTP GET、v3 命令/控制及单份最终 `call.result`;F01/F07 Schema、正反例、来源/hash 和 Mock C 通过后可继续本地实现,不等待外部签收或连通。它尚未成为真实运行事实,不能与 MQ v2 拼成线上协议,也不代表 G0/生产切换。
|
||||
|
||||
现有上游权威是《SaaS交互_OpenAPI与MQ契约规划_v0.1.md》(正文 v1.0)及经核验的发布产物。现有产物包括 `mq.schema.json`、`executor.openapi.yaml`、`cell-agent.openapi.yaml`、AI 配置及 SIP 管理相关契约。文件存在不代表完整覆盖:P0 必须逐条核对正文、Schema、状态语义和实现差异。
|
||||
|
||||
- 将经批准的协议作为**版本化、只读发布包**导入本项目 `contracts/`,记录源仓库、源版本/提交、文件 SHA-256 和生成器版本;工作区未提交修改不能冒充某个提交的发布产物。
|
||||
- 类型和校验代码从该发布包生成;禁止手写另一套字段、枚举或业务 Schema。
|
||||
- 对现行外部协议,仍将已发布版本作为**版本化、只读包**导入本项目 `contracts/`,记录源仓库、源版本/提交和文件 SHA-256;工作区修改不能冒充上游发布产物。
|
||||
- 对本轮用户指定的项目内目标,以第三方对接文档为规范来源,`docs/contracts` 中版本化 JSON Schema、正反例与 MQ 拓扑为机器校验件,并在本地 manifest 中记录来源和 SHA-256;不宣称这些字段是 SaaS 已发布响应。
|
||||
- 类型和校验代码按各自版本化契约生成/验证;现行外部上游包与本地目标包分离,不互相覆盖或维护隐式兼容层。
|
||||
- 同步工具在开发阶段获取发布包;普通构建、测试和发行包运行不得读取父目录。
|
||||
- 新增调度器—Cell 的消息、fencing、回执或对账字段,先形成契约变更提案并获批;本方案不擅自定字段或 MQ 路由。
|
||||
- 本项目自己的设计、运行、验收文档只在此处维护;上游共享契约仍只有一个编辑源。
|
||||
- 本项目已独立初始化 Git,并按 `git.ipao.vip/rogee/go-sip` 维护;不创建 submodule 或改变父仓库跟踪关系。项目许可证和第三方 NOTICE 在对外发布前确认。
|
||||
- [通信与事件数据交互](../contracts/通信与事件数据交互_v0.1.md)覆盖执行命令、8类业务事件、全MQ请求响应目录及13个内部Unary职责草案;[字段索引](../references/OpenAPI与MQ字段索引_v0.1.md)完整提取42个HTTP操作/115个命名组件。
|
||||
- 已逐字段/哈希确认MQ信封command_type/command_id、event_type/aggregate_*及task_revision与正文一致;但事件payload目前仅通用object,专属约束仍需上游补齐(GAP-01)。不能以旧测试或通用object校验冒充完整验收。文字事件准确名称为transcript.updated。
|
||||
- 42操作/115组件是上游目录,不是本项目首发工作量。P1保留既有业务语义/8种业务事件,但7条HTTP交互及AI GET改为获批MQ请求响应;消费实际所需AI配置和静态制品;不实现管理平台30个API或复制其业务后端。生成/校验仅覆盖使用入口及其引用闭包,来源包与只读字段索引保持完整。
|
||||
- 42操作/115组件是上游目录,不是本项目首发工作量。现行外部 v2 仍按其已发布语义运行;本地 P1 目标则使用已冻结的四条只读 GET、呼叫/控制必要 MQ 回执与单份最终结果,删除旧 query/replay 和拆分实时文字/拒联/录音事件,不实现管理平台30个API或复制其业务后端。真实 SaaS 兼容性另记未验证。
|
||||
- 当前AI Schema强制要求llm/prompt/tts/asr/conversation,缺少明确的ASR-only表达。GAP-08须先在上游批准模式/缺省/文字与错误语义;不在MQ添加临时mode字段或绕过required校验。
|
||||
|
||||
## 4. Go 1.27.1 的采用策略
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# RabbitMQ local integration evidence — 2026-09-18
|
||||
|
||||
> Historical record: this verifies the former tenant-queue `--consume --tenant-key` path, which F03 removed. It is not current runtime or protocol evidence; current local V3 evidence is [here](f03-local-task-runtime-v0.1.md). No external broker compatibility is implied.
|
||||
|
||||
## Scope
|
||||
|
||||
This is an isolated local Docker broker test only. It is not a SaaS broker,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# MQ-only 本地最终回归证据
|
||||
|
||||
> 历史记录:本文记录上一阶段的 MQ-only/tenant-queue 实现与测试,不是当前 F03 接入协议或验收结论。旧 `mq-only-acceptance-local.sh`、Dispatcher tenant-queue consumer 与旧 control worker 已移除;当前本地 F03 证据见 [f03-local-task-runtime-v0.1.md](f03-local-task-runtime-v0.1.md)。本文中的旧查询/补传/事件结果不得作为新契约或外部 SaaS 兼容依据。
|
||||
|
||||
本记录只证明当前独立项目的单节点、单 Dispatcher、单 Agent、单 Cell、单租户本地/隔离范围;不代表真实 SaaS、真实供应商、云主机、生产 broker 或生产切换通过。
|
||||
|
||||
## 代码与契约
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# F02 本地配置与租户额度读取证据
|
||||
|
||||
## 范围
|
||||
|
||||
本证据只覆盖单 Dispatcher、单 Agent、单 Asterisk、单 Cell、单租户的项目内 v0.1 实现与本地 Mock。它不代表 SaaS/management 外部签收、真实 Agent/Asterisk 已加载、真实部署或真实线路验收。
|
||||
|
||||
## 实现事实
|
||||
|
||||
- 配置客户端读取并严格校验 SIP、任务发现页、任务配置、租户额度四条只读 GET;核对 Dispatcher、任务、tenant_id、原值 tenant_key 与 SaaS 所有的队列路由身份。游标过期时可请求完整发现快照首响应;多页聚合、持久水位与重启恢复由 F03 完成。
|
||||
- Dispatcher 仅在四个完整响应都验证通过且 SIP applied-status verifier 通过后发布配置快照。每个响应原始 JSON、版本、内容 SHA-256、获取时间和失效时间写入 SQLite;版本回退或同版本内容变化拒绝。内存快照按 tenant_id/task_id 索引;SIP/发现快照在任务间共享,租户额度在同租户任务间共享。失败或过期不使用旧缓存准入。
|
||||
- tenant_id 与 tenant_key 在本 Dispatcher 内一对一绑定。租户/任务额度更新与完整响应持久化同事务;额度降级不清理已有 reserved/unknown 占用。
|
||||
- 接纳 `call.execute` 时,tenant 与 task 两个额度范围、任务行、执行配置原始快照、reservation、inbox、command receipt 和 outbox 在一个 SQLite 事务内提交。额度不足时持久化 `quota_exceeded` 拒绝,不创建任务/占用;额度未配置或事务失败时拒绝 ACK。相同 command_id 重投复用原 receipt,不重复占额。
|
||||
- 新配置读取必须通过 Agent applied-config 核验:部署指定的 Agent/Cell 身份需匹配;`applied_configs` 恰有一条 `kind="sip"`,且 `state="applied"`、十进制 revision、SHA-256 与配置响应中的获批 SIP artifact 精确一致,并有正的 `observed_at_unix_ms`。缺失、重复或不匹配均 fail-closed。此处是项目内 Agent 协议规则;Mock status 不证明真实 Asterisk 已加载。
|
||||
- 配置刷新持写锁,命令接纳持读锁;刷新失败清空可用于新接纳的内存快照,避免旧配置与新版本竞态。
|
||||
|
||||
## 验证结果
|
||||
|
||||
- `python3 scripts/validate-local-contracts.py`:四个本地 Schema、正反例和 19 个 manifest SHA-256 项通过。
|
||||
- `go test ./internal/configread ./internal/contract ./internal/store ./internal/dispatcher -count=1`:通过。
|
||||
- `go test -race ./internal/configread ./internal/contract ./internal/store ./internal/dispatcher -count=1`:通过。
|
||||
- `go test ./... -count=1`:通过。
|
||||
- `go vet ./...`:通过。
|
||||
- `go build ./...`:通过。
|
||||
- `go test -cover ./internal/configread ./internal/contract ./internal/store ./internal/dispatcher -count=1`:覆盖率依次为 75.0%、73.3%、65.1%、71.4%,F02 涉及包均不低于 65%。
|
||||
- 当前 `go test -cover ./...` 总覆盖率为 49.5%;全项目 65% 门禁仍由 F09 验证,不能将 F02 包覆盖率当作全项目通过。
|
||||
|
||||
Mock 覆盖配置断连、过期、身份/路由不匹配、版本冲突、额度降级、同租户多任务共享额度、并发额度竞争、刷新与接纳竞态,以及 Agent applied-config 缺失/重复/不匹配。
|
||||
|
||||
## 未验证与后续边界
|
||||
|
||||
- 未连接真实 SaaS、management、云、供应商或 SIP 线路;没有真实拨号、真实 Agent status 或真实 Asterisk 加载证据。
|
||||
- F02 组件及本地测试已交付,但 v3 队列消费/应用启动集成仍属于 F03;当前旧 MQ v2 主入口尚未切换。
|
||||
- F09 其他工作包、真实部署/切换和生产验收未由本证据覆盖。
|
||||
@@ -0,0 +1,22 @@
|
||||
# F03 v0.2 单次任务发现:本地 Mock 验证
|
||||
|
||||
范围:单 Dispatcher、单租户、预建任务队列;仅本地 Mock HTTP 与隔离 RabbitMQ。`docs/evidence/f03-local-task-runtime-v0.1.md` 中的分页发现结果只作历史,不用于本版签收。`contracts/upstream/v1/` 外部运行基线未改,真实 SaaS/management、云、SIP 线路、拨号和生产均未验证。
|
||||
|
||||
## 合同与实际改动
|
||||
|
||||
- `docs/thirds/v0.2.md` §2.5、`docs/contracts/task-discovery-v0.2-proposal.schema.json`、六份 v0.2 正反例/错误例和 `docs/contracts/local-contract-manifest-v0.2.json`:完整快照或增量每次只返回一个响应,最多 256 项;不含 `queue`、分页 token、`snapshot_id`;空变更 `next_cursor` 等于请求 `after`,`removed` 撤销归属,410 `cursor_expired` 重取全量。v0.1 Schema 和示例留在文档校验中供历史核对,但运行时代码只加载 v0.2 任务发现 Schema。
|
||||
- `internal/configread/client.go`:验证完整响应、Dispatcher/租户绑定、重复 task ID、256 项界限和空变更游标。410 仅在游标过期时拉取一次全量;其他失败不推进游标,不把 HTTP 失败误当无变更。
|
||||
- `internal/store/local_v01_discovery.go`、`internal/store/migrations/015_local_v02_task_discovery.sql`:同一事务写入完整响应及 SHA-256、任务归属和游标;主动任务总量超过 256、版本回退或身份冲突时事务回滚。队列名称/路由按 D+task ID 在本地推导;仅保留任务归属及未决执行,旧分页游标/页存储被移除,启动后须重新获取完整快照。SaaS 仍独占队列创建、绑定和退役。
|
||||
- `internal/dispatcher/task_runtime_v3.go`:发现失败即持久关闭新准入并停止任务消费;成功获取完整响应后才重新开放并核对消费者。控制通道不因任务发现失败而关闭。暂停保留积压、恢复原队列、停止先持久屏障后静默 ACK 的既有行为不变。
|
||||
|
||||
## 本地验证事实
|
||||
|
||||
- `python3 scripts/validate-local-contracts.py`:旧 v0.1 历史合同继续可校验;v0.2 草案 26 个正向验证、4 个负向验证、12 个 SHA-256 文件通过。Schema 拒绝旧 `queue`/分页字段与 257 项响应。
|
||||
- `go test ./... -count=1` 与 `./scripts/acceptance-local.sh` 通过:包含格式检查、`go mod verify`、Schema/hash 校验、`go test -race ./... -count=1`、`go vet ./...`、`go build ./...` 和本地 RabbitMQ 集成。RabbitMQ 使用独立预建队列账户和 Dispatcher 账户;Dispatcher `configure=^$`,未声明、绑定或删除队列。Mock 使用 v0.2 发现响应;此结果不是 SaaS 应用收讫或真实队列授权验收。
|
||||
- `internal/configread/discovery_v02_test.go`:单次全量/增量、空变更游标、410 全量恢复、拒绝旧 queue/page 字段及 256/257 边界。
|
||||
- `internal/store/local_v01_discovery_test.go`、`internal/dispatcher/task_runtime_v3_test.go`:完整响应/归属/游标同事务持久化、超限回滚、失效期间拒新、任务消费停止、恢复后重开、410 全量快照退役旧任务;任务队列名称由约定规则推导。
|
||||
- 本地非集成覆盖率:`internal/configread` 74.9%、`internal/dispatcher` 66.0%、`internal/store` 66.0%;`internal/mq` 单独不带 RabbitMQ 集成时仅 1.7%,不能声称所有模块已满足 65%。F09 的完整矩阵与覆盖率门禁仍需另行执行。
|
||||
|
||||
## 未完成边界
|
||||
|
||||
F04 的任务/线路时段与最后拨号门禁、F08 最终结果/切换、F09 全矩阵及真实 SaaS 兼容性均未由本证据签收。Mock 只能证明项目内定义与本地实现一致,不能授权任何真实呼叫、上传或云操作。
|
||||
@@ -0,0 +1,23 @@
|
||||
# F03 本地任务队列、发现与控制证据
|
||||
|
||||
## 范围与结论
|
||||
|
||||
F03 在单 Dispatcher、单 Agent、单 Cell、单租户的本地隔离环境通过。SaaS/management、真实云主机、供应商、SIP 拨号、生产部署与切换均未连接或验证;项目内 Mock 结果不代表外部兼容或生产验收。`contracts/upstream/v1/` 仍是外部运行基线。
|
||||
|
||||
## 实现事实
|
||||
|
||||
- Dispatcher 使用 MQ v3 运行时。任务队列和控制队列由 SaaS 预建;Dispatcher 只被动验证/消费和停止消费,不声明、绑定或删除这些队列。RabbitMQ 集成测试将 provisioner 与 Dispatcher 分成两个身份;Dispatcher 的 `configure` 权限正则为 `^$`,直接 `QueueDeclare` 被拒绝,而被动连接、消费、排空和结果发布通过。CLI 不再提供 `--tenant-key`/`--consume` 自建租户队列路径,旧 tenant-queue consumer 与旧 per-call control worker 已移除。
|
||||
- 任务发现读取完整分页结果;不透明游标/页 token 校验连续性,完整发现窗口及任务归属在同一事务持久化后才推进水位。无游标时取完整快照,客户端检测到游标/页状态失效时走完整快照恢复。
|
||||
- 启动和轮询仅在任务归属、running 状态、有效配置快照均满足时订阅相同的 SaaS 预建任务队列。pause 先持久关闭接纳并停止消费者,保留积压;resume 重新读取权威 running 状态后恢复消费原队列;stop 先持久终态屏障并停止消费者,再读取权威 stopped 状态。
|
||||
- stop 将权威状态/版本先持久化但不写回执,随后被动排空并 ACK 未接纳积压,最后才事务写入 control receipt/outbox。排空失败时无回执,重复控制可继续排空并在成功后写入原任务结果,不产生未接纳命令回执或拨号。
|
||||
|
||||
## 验证记录
|
||||
|
||||
`./scripts/acceptance-local.sh` 通过。该入口检查格式、契约哈希与 Schema 正反例、`go mod verify`、`go test -race ./... -count=1`、`go vet ./...`、构建,并运行本地 RabbitMQ 集成测试。
|
||||
|
||||
- 本地契约:4 个 Schema 有效;正例数量为 config-read 17、task-discovery 13、command-next 6、call-result 4;四类负例均拒绝;19 个 manifest 文件 SHA-256 校验通过。
|
||||
- 覆盖率:`go test ./internal/configread ./internal/dispatcher ./internal/store -cover -count=1` 分别为 76.8%、66.2%、65.3%。带本地 RabbitMQ 的 `-race -cover -tags=integration` 测试中,`internal/dispatcher` 为 66.4%,`internal/mq` 为 55.5%。项目 F09 的完整覆盖率门禁仍待 F09 统一验收,不在此处冒称已通过。
|
||||
- RabbitMQ 使用本机已缓存的 `rabbitmq:4.1-management-alpine` 镜像和临时 loopback 容器;集成 fixture 由独立 Mock SaaS 身份预建并清理队列。无 `configure` 权限的 Dispatcher 身份不能声明队列,但 V3 MQ 与 Dispatcher 端到端测试均通过。脚本在镜像未缓存时 fail-closed,不隐式拉取镜像。
|
||||
- 控制测试覆盖暂停保留积压、权威状态后恢复、已停止任务不能恢复、停止排空前不写回执、排空失败后重试,以及无归属任务的拒绝回执。发现/运行时测试覆盖完整快照/游标持久化、队列接纳资格和运行时缺配置失败关闭。
|
||||
|
||||
本证据只证明本地项目内契约与隔离 Mock。未访问真实 SaaS/management、外部 MQ、云、供应商或 SIP 线路;未发起真实呼叫、上传或切换。
|
||||
@@ -0,0 +1,27 @@
|
||||
# F04 本地 Mock:外呼时段与最后拨号屏障
|
||||
|
||||
状态:**仅本地 Mock 的 F04 门禁已验证**。单节点、单 Dispatcher、单 Agent、单 Cell、单租户;没有接入真实 SaaS、management、SIP 线路、云资源或生产环境,也没有发起真实呼叫。F08 最终结果、额度释放与上传/MQ 收口及 F09 全矩阵仍待验收。
|
||||
|
||||
## 本地规则与执行边界
|
||||
|
||||
- Dispatcher 在命令持久接纳时,以及向 Agent 发出指令前,分别检查原始被叫白名单、任务授权和状态、Asia/Shanghai 的任务×**已绑定线路**周时段、任务排除日期、任务/AI 较小通话时限、命令与授权及租户额度有效期。时段左闭右开;跨日拆分按当地日期判断;排除日期只属于任务。接纳后固定原配置快照、主叫与所选线路,不因新配置、时钟变化、暂停/停止、线路变化而自动换线、等待或重拨。
|
||||
- `local_v02_origination_decisions` 对每个执行持久写入唯一 `issued` 或 `refused`;拒绝后即使时钟回退或 MQ 重投也不能重新获准。Agent 调用前窗口再次关闭时,不调用 Agent,已签发身份仍不得重拨,留待 F08 结果/占用对账。
|
||||
- SaaS 独占队列;任务消费者先持久接纳,再查原命令的待执行记录并执行 Dispatcher 最后门禁。成功或失败均核对持久决定;已决定的重投直接 ACK,不把 Agent 失败当作 MQ 自动重试信号。控制消费者与任务消费者独立。
|
||||
- 新的 `agent-authorized-origination.v0.1` Unary gRPC 只在隔离 Mock 中启用。Dispatcher 下发身份、线路、主叫、时限及最早截止时刻;Agent 只核验会话、指令完整性及 Dispatcher 签发期限,持久记录未知/终态,不重新判断白名单、业务时段或选择线路。Mock 适配器明确不发 SIP;Dispatcher V3 的 mixed/real 模式在启动时拒绝,不能将此合同当作真实拨号许可。现行真实路径的固定 `09:00`–`20:00` 限制未放宽。
|
||||
|
||||
## 验证事实
|
||||
|
||||
| 项目 | 结果 |
|
||||
| --- | --- |
|
||||
| `internal/callwindow/policy_test.go` | 任务和线路交集、左右边界、跨日、任务排除日期、空起止时间 |
|
||||
| `internal/dispatcher/dial_policy_test.go`、`local_v01_test.go`、`local_origination_quota_test.go` | 白名单、固定线路与主叫、任务/AI 时限、命令/额度到期、绑定快照不受缓存更新影响、控制与持久决定竞态 |
|
||||
| `internal/dispatcher/task_queue_v3_origination_test.go`、`local_origination_rpc_test.go` | 消费后 Mock Agent 执行一次;窗口外不调用;已签发/已拒绝命令重投均不触发二次呼出 |
|
||||
| `internal/store/local_origination_test.go` | 原命令与绑定快照的哈希/身份、暂停屏障、唯一签发或拒绝决定、原始消息重复投递与额度占用均失败关闭 |
|
||||
| `internal/rpc/authorized_execution_test.go` | 非 Mock 拒绝、签发期限、相同身份重投、内容冲突、Agent 重启及未知结果不重复调用 |
|
||||
| `./scripts/check-proto.sh`、`./scripts/acceptance-local.sh` | 2026-09-24 本地通过;后者含格式、合同/例子哈希、`go vet ./...`、`go test -race ./...`、构建和本地 RabbitMQ `no configure` 权限测试。RabbitMQ 使用本地缓存镜像,不访问真实 SaaS。 |
|
||||
|
||||
普通测试覆盖率(`go test -cover`):`internal/callwindow` 84.4%、`internal/dispatcher` 68.3%、`internal/store` 66.7%、`internal/rpc` 69.7%;本地 RabbitMQ 集成测试中 `internal/dispatcher` 68.4%、`internal/mq` 55.5%。**F09 的全部适用模块覆盖率≥65% 尚未达到,不以 F04 测试代替 F09 验收。**
|
||||
|
||||
## 未签收与后续
|
||||
|
||||
F08 尚须把 Mock 通话终态与单份 `call.result`、持久 outbox、额度释放和录音上传事实按既定合同接通,并证明断电/重复通知不重拨或重 PUT;此前 Agent 的 Mock 终态不等于 SaaS 已处理的结果。F09 须重跑发现 v0.2 与单节点适用场景全矩阵并解决覆盖率缺口。F06 真实环境、真实线路、供应商、SaaS/management 联调与生产切换均无本轮授权,**未执行、未验证**。
|
||||
@@ -0,0 +1,24 @@
|
||||
# F08 本地 Mock:唯一最终结果与恢复证据
|
||||
|
||||
范围:单节点、单 Dispatcher、单 Agent、单 Cell、单租户的项目内隔离 Mock。除任务发现按 v0.2 外,其余本地 SaaS 对接协议仍按 v0.1;新增录音失败事实仅在 Agent↔Dispatcher 的 Mock 路径使用。未访问真实 SaaS、management、OSS、SIP、云或生产环境;不修改 `contracts/upstream/v1/`。
|
||||
|
||||
## 已验证的本地行为
|
||||
|
||||
| 场景 | 本地结论与证据 |
|
||||
| --- | --- |
|
||||
| 通话确认终结与额度 | `local_call_terminals` 保留已确认终态并立即释放执行额度,不等待 OSS/MQ;通话未知继续占额。`internal/store/local_call_terminal_test.go`、`internal/dispatcher/local_mock_pending_result_test.go`。 |
|
||||
| 唯一结果与无录音 | 已接纳但未拨号的拒绝/期限用执行关联 ID 收口,不伪称 SIP dialog;无应答/忙线等录音为 `not_created`。已终结录音等待完成、明确失败或 15 分钟期限,结果不可变、只入队一个 `call.result`。`internal/dispatcher/local_mock_refusal_pending_test.go`、`local_mock_dispatcher_deadline_test.go`、`local_mock_pending_result_test.go`。 |
|
||||
| 上传成功与明确失败 | 录音 manifest、授权上传 ID、checksum、完成事实必须与唯一执行绑定;结果持久化后不再签新 PUT 授权。`uploaded` 与 `unavailable`(授权/PUT 明确失败、期限)均在隔离 Mock 测试中用合成录音事实验证;未知 PUT(传输异常、HTTP 408/429/5xx)不伪报失败、不重 PUT。`internal/agent/upload_failure_report_test.go`、`internal/store/local_v3_upload_state_test.go`、`internal/rpc/dispatcher_upload_local_v3_test.go`。 |
|
||||
| Agent 失败事实与重启 | 已知失败先写 Agent 文件日志;经原 AgentControl listener 的 `ReportExecutionEvent`、当前会话元数据上报。模拟 Dispatcher 已持久签收但回执丢失,Agent 重启/boot 更新/超过录音期限后仍重送原 fact ID、原摘要与观察时间;Dispatcher 幂等,事实仅一份,不发第二次 PUT 或呼叫。无当前激活会话则保留事实而不冒用旧会话。`internal/dispatcher/local_mock_pending_result_test.go`、`internal/agent/upload_failure_report_test.go`、`cmd/sip-go-agent/upload_failure_recovery_test.go`。 |
|
||||
| 可靠 MQ 与受控边界 | 最终消息经 outbox 保留原 event ID,publisher confirm、mandatory、durable 路由确认后才将相应上传标记完成;confirm 不等于 SaaS 已处理。MQ 失败/确认丢失重发原消息,不重新 originate/PUT;超过 8,388,608 字节持久阻塞并记录 ID、字节数与 SHA-256,不截断或拆分。RabbitMQ 隔离集成验证了单份 `call.result`、重启补投及无 `configure` 权限的发布路径。V3 Mock 拒绝旧拆分执行事件;V3 mixed/real 启动拒绝,现行真实 `09:00`–`20:00` 门禁未放宽。`internal/dispatcher/outbox_payload_limit_test.go`、`local_v01_integration_test.go`、`internal/rpc/dispatcher_events_local_v3_test.go`、`scripts/mq-integration-local.sh`。 |
|
||||
|
||||
新增内部失败事实的字段、4 份正反例、独立 SHA-256 清单和 Agent 嵌入 Schema 的一致性见 `docs/contracts/local-mock-recording-failure-v0.1.md`、同目录 Schema/manifest 与 `scripts/validate-local-contracts.py`。不将此事实当成 SaaS v0.1 扩展,也不启用 mixed/real。
|
||||
|
||||
## 验证记录
|
||||
|
||||
- `go test ./... -count=1`:通过。
|
||||
- `./scripts/check-proto.sh`、`./scripts/check-contracts.sh`:通过,包含新事实正反例、来源/hash 与嵌入 Schema 一致性。
|
||||
- `./scripts/acceptance-local.sh`:通过,内含 gofmt、`go mod verify`、`go test -race ./... -count=1`、`go vet ./...`、构建,以及本地 RabbitMQ 有界权限集成测试。
|
||||
- 本次普通测试覆盖率:`internal/agent` 71.1%、`internal/dispatcher` 69.7%、`internal/rpc` 69.9%、`internal/store` 67.1%、`internal/contract` 74.0%;`internal/mq` 普通测试仅 1.7%,主要逻辑需带 RabbitMQ 的集成测试覆盖,**F09 的 ≥65% 门禁尚未签收**。
|
||||
|
||||
默认 Mock originator 只模拟无应答,不生成真实录音;本地上传成功/失败场景由测试注入严格绑定的合成 manifest/回执,并非真实录音文件、OSS PUT 或真实供应商闭环。录音事实已就绪时的结果/失败恢复可验证,不据此宣称实际媒体采集或真实 SaaS 应用签收已完成。F09 完整本地矩阵、覆盖率及本地发布准备仍另行验证;F06 真实部署/切换没有授权,未执行。
|
||||
@@ -0,0 +1,24 @@
|
||||
# F09 P1 本地 Mock 验收(任务发现 v0.2)
|
||||
|
||||
仅验收单节点、单 Dispatcher、单 Agent、单 Cell、单租户的本地隔离 Mock。任务发现采用 `docs/thirds/v0.2.md` §2.5;其余 SaaS 项目内协议仍为 v0.1。未修改 `contracts/upstream/v1/`,旧分页发现不运行、不回退。此处的通过不代表 SaaS/management、真实 OSS/SIP、Asterisk 媒体、云部署或生产切换通过。
|
||||
|
||||
## 计划 §5 本轮适用矩阵
|
||||
|
||||
| 适用场景 | 本地验证结果 |
|
||||
| --- | --- |
|
||||
| 发现版本与恢复 | 单次完整响应最多 256 项、无分页及队列地址/key;空变更保持请求水位,`removed` 退役,410 `cursor_expired` 重新取得全量并原子持久化;超限/未知字段拒绝,不截断、不启用旧分页兼容。合同正反例、来源及 SHA-256、Mock SaaS 流程见 [`f03-local-task-discovery-v0.2.md`](f03-local-task-discovery-v0.2.md),`internal/configread/discovery_v02_test.go`、`internal/store/local_v01_discovery_test.go`。 |
|
||||
| 只读配置、归属与额度 | D 身份/租户/任务及版本、SIP 快照已加载校验,HTTP 错误与缓存过期关闭新准入;按归属 D 及 tenant_id 取得共享额度,缺失/0/降额/未知占用不擅自发额或释放。`internal/dispatcher/local_config_read_test.go`、`local_v01_config_test.go`、`local_origination_quota_test.go` 及 F02 证据。 |
|
||||
| 最后拨号判断 | 任务×已选线路的上海时区窗口、任务排除日期、号码白名单、有效期及较小时限在接纳和发起前检查;不等下一窗口、不换线重拨;mock 授权仅 Mock Agent 使用,mixed/real 不启用新授权。见 [`f04-local-dial-policy-v0.1.md`](f04-local-dial-policy-v0.1.md)、`internal/dispatcher/dial_policy_test.go`、`local_v01_test.go`。 |
|
||||
| 队列暂停、恢复及停止 | RabbitMQ 隔离测试中 100 条积压经 pause 保留、resume 从原队列继续;stop 静默 ACK 另 100 条未接纳命令,不产生逐条结果。两条已发起的 Mock 执行在 stop 前已将 Agent 归属与一次性拨号决定**同一 SQLite 事务**持久化,故 stop 对两条都发 hangup;已在途通话仍各自产生最终结果、释放额度,不额外拨号。见 `internal/mq/amqp_v3_integration_test.go`、`internal/dispatcher/task_queue_v3_stop_active_test.go`、`task_control_v3_test.go`。此前测试发现 V3 缺失持久 Agent 归属,导致两条在途执行被 stop 控制漏掉;先有失败测试,再修复并复测。 |
|
||||
| 队列所有权、队列满、SQLite 写入失败 | Dispatcher 的受限 RabbitMQ 账号无 `configure` 权限,仅消费 SaaS 预建任务/控制队列;队列缺失不自行声明。SaaS Mock 建 `x-max-length=1`、`reject-publish` 队列,第二条 persistent 命令获拒绝,原第一条保留并由 D 消费,未入队的消息不虚称 D 自动补收。SQLite 写入故障以隔离测试触发器模拟满盘类写入错误:准入事务无残留任务/额度、错误非永久命令错误,恢复后沿原命令身份接纳;MQ 瞬态 handler 错误 NACK/requeue 原消息,恢复后 ACK。**未物理填满磁盘**。见 `internal/mq/amqp_v3_queue_full_integration_test.go`、`amqp_v3_integration_test.go`、`internal/dispatcher/local_sqlite_full_test.go`。 |
|
||||
| 结果、上传及故障恢复 | 确认终态后独立释放额度;`uploaded`/`unavailable`/`not_created` 只出一份最终 `call.result`。明确录音失败事实、未知 PUT、15 分钟期限、断回执/重启、MQ confirm 丢失和超长正文均保留原身份,不重拨或重新 PUT;confirm 不是 SaaS 应用签收。见 [`f08-local-final-result-v0.1.md`](f08-local-final-result-v0.1.md) 与本轮受限 RabbitMQ 集成。默认 Mock 无真实录音,录音分支由严格绑定的合成事实注入。 |
|
||||
|
||||
## 执行与覆盖率
|
||||
|
||||
- `./scripts/acceptance-local.sh`:通过;内含格式、Proto/合同及 hash 校验、`go mod verify`、`go test -race ./... -count=1`、`go vet ./...`、构建和无 `configure` 权限的本地 RabbitMQ 集成测试。
|
||||
- `go test -cover -count=1`:本轮 P1 业务包 `agent` 71.1%、`callwindow` 84.4%、`configread` 74.9%、`contract` 74.0%、`dispatcher` 70.4%、`rpc` 69.9%、`store` 67.2%、`tenant` 85.4%。`mq` 必须带 RabbitMQ integration tag 执行,`./scripts/mq-integration-local.sh` 中为 66.4%。均达到用户确认的**本轮 P1 业务模块 ≥65%**口径。
|
||||
- 独立列明未达线包:`cmd/sip-go-agent` 29.6%、历史 `internal/callruntime` 61.7%;MQ 普通测试不带 integration tag 时仅 1.7%。这些数字**不计入本轮 P1 业务模块门槛**,不宣称 CLI 或全仓库达到 65%,后续补测仍是技术债。
|
||||
|
||||
## 未验证及门禁
|
||||
|
||||
真实 SaaS/management 合同、ECS/OSS/SIP 供应商、Asterisk 媒体、第二节点/Cell/租户、容量及切换均未验证或未获授权。F06 只核对本地制品、合同/队列版本和 fail-closed 发布准备;不得因上述本地 Mock 结果启动真实部署、拨号或生产切换。
|
||||
@@ -0,0 +1,30 @@
|
||||
# 本地 Mock SaaS C 门禁证据(v0.1)
|
||||
|
||||
## 范围
|
||||
|
||||
本证据只证明项目内 F01/F07 契约与本地 Mock 的端到端交互。未访问真实 SaaS、management、云资源、供应商或 SIP 线路;未发起通话、未上传录音,也未验证外部兼容性。`contracts/upstream/v1/` 仍是当前外部运行基线。本地通过不代表外部签收或生产验收。
|
||||
|
||||
## Mock 交互
|
||||
|
||||
`TestLocalDispatcherMockSaaSEndToEndWithOutboxRecovery` 使用本地 HTTP Mock、临时 SQLite 和本地 RabbitMQ:
|
||||
|
||||
1. Dispatcher 使用 `X-DISPATCHER-id` 与 `X-DISPATCHER-SECRET-KEY` 请求四个只读资源:
|
||||
- `GET /internal/v1/dispatcher/sip`
|
||||
- `GET /internal/v1/dispatcher/tasks`
|
||||
- `GET /internal/v1/dispatcher/task/task-mock`
|
||||
- `GET /internal/v1/dispatcher/tenant/tenant-id-mock/quota`
|
||||
2. SaaS Mock 预先创建并绑定其所有的 task/result 队列。测试发布 persistent `call.execute`;Dispatcher 消费后持久化命令与 `command.result` outbox。
|
||||
3. 测试暂时删除 SaaS-owned result queue,确认发布失败并保留 outbox;恢复队列后,Dispatcher 重试并将相同回执送达 Mock。
|
||||
4. 测试使用本地示例构造 synthetic `call.result`,并核对它引用已接纳的 `command_id`、`execution_id`、task 和租户;Mock 收到完整事件。重复相同事件幂等,执行 ID 不匹配时拒绝。
|
||||
|
||||
当前 C 切片只验证配置读取、命令收件/回执及最终结果的持久化交付;不会启动真实执行,也不调用 Asterisk。`call.result` 中的转写和 OSS 对象均为示例数据,不对应真实录音或上传。`pause/resume/stop` 的项目内 Schema 与正反例由合同验证器检查;其运行时控制和队列排空属于后续 F03,不计入本次运行时 E2E。
|
||||
|
||||
## 契约与验证结果
|
||||
|
||||
- `python3 scripts/validate-local-contracts.py`:4 个项目内 Schema 有效;正例分别为 config-read 17、task-discovery 13、command-next 6、call-result 4;每类 Schema 的负例均按预期拒绝;source 与 18 项产物共 19 个 SHA-256 文件通过。
|
||||
- `bash scripts/check-contracts.sh`:上游 v1 契约基线、项目内 Schema/示例及 Go 合同测试通过。
|
||||
- `go test ./internal/configread ./internal/dispatcher ./internal/store ./internal/mq`:通过,覆盖配置读取失败清除旧快照、命令过期/白名单拒绝/窗口拒绝、重复命令和最终结果关联。
|
||||
- `bash scripts/mq-integration-local.sh`:通过;本地 RabbitMQ 集成测试覆盖 Mock 消息发布、result queue 暂不可用后的 outbox 恢复以及最终事件交付。
|
||||
- `git diff --check`:通过。
|
||||
|
||||
`go vet`、`go test -race`、完整构建、模块覆盖率及 F02–F09 的验收仍待后续工作包验证。本证据不宣称这些检查已通过。
|
||||
@@ -1,6 +1,6 @@
|
||||
# Go SIP Agent:配置读取与有界外呼迭代计划 v0.1
|
||||
|
||||
**当前迭代唯一执行入口。状态:项目提案;新 HTTP/MQ 合同、实现及验收均未完成。** 现行 `contracts/upstream/v1/` 和代码仍是旧基线,不将本文当作上线授权。分项设计:[有界消费与控制通道](architecture/Dispatcher有界接纳与控制通道改造计划_v0.1.md);对外结构:[第三方对接](thirds/第三方对接事件与请求消费顺序_v0.1.md);配置字段:[字段提案](contracts/config-read-fields-v0.1-proposal.md)、[草案 Schema](contracts/config-read-v0.1.schema.json)。分项材料须与本文一起更新,不能继续使用旧 ETag/304、控制 CAS 或即时反馈目标。
|
||||
**当前迭代唯一执行入口。状态:用户已授权 P1 本地迭代;项目内契约冻结与 Mock C、实现及本地验收进行中。** 现行 `contracts/upstream/v1/` 和代码仍是旧外部基线;本文不授权真实 SaaS、生产部署、拨号或切换。分项设计:[有界消费与控制通道](architecture/Dispatcher有界接纳与控制通道改造计划_v0.1.md);原本地 SaaS 结构契约:[第三方对接 v0.1](thirds/第三方对接事件与请求消费顺序_v0.1.md);任务发现单次响应的[修订草案 v0.2](thirds/v0.2.md)及[独立 Schema](contracts/task-discovery-v0.2-proposal.schema.json)不回写 v0.1 历史证据,待新合同及 F03 实现验收后切换。机器校验件:[Schema/正反例](contracts/)。分项材料须与本文一起更新,不能继续使用旧 ETag/304、控制 CAS 或即时反馈目标。
|
||||
|
||||
## 1. 范围和完成标准
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
| `/internal/v1/dispatcher/sip` | 用户指定路径;本 D 获管理面批准的 SIP 全量。 |
|
||||
| `/internal/v1/dispatcher/task/:task_id` | 用户指定路径;任务归属、路由/主叫、智能体、时段及两项任务级超时。 |
|
||||
| `/internal/v1/dispatcher/tasks`(可 `?after=<cursor>`) | 用户指定路径;启动一致全量快照,运行中每 30 秒按变更游标发现任务。 |
|
||||
| `/internal/v1/dispatcher/tenant/:tenant_id/quota` | **新增路径/字段为项目草案**:取得任务后按其 `tenant_id` 读取该租户分配给本 D 的并发额度;实际路径须 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、正反例与验收约定签收;**L**:单 D 本地隔离闭环和故障矩阵通过;**M**:多 D 独占资源/份额为另行授权的后续。项目字段草案、本地 Mock 和旧测试不能代签 C 或真实供应商结果。
|
||||
完成分三层:**C**:F01/F07 项目内来源、版本、严格 Schema、正反例、SHA-256 对齐并通过 Mock SaaS 端到端验证;不等待外部签收;**L**:单 D 本地隔离闭环和故障矩阵通过;**M**:多 D 独占资源/份额为另行授权的后续。Mock C 不代表真实 SaaS 或供应商验收。
|
||||
|
||||
## 2. 权威资料和读法
|
||||
|
||||
@@ -31,9 +31,10 @@
|
||||
|
||||
- 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 签收):**`allowed_trunk_ids` 按列表顺序作为候选优先级,选首条满足时段、已加载状态、供应商/线路额度且支持任务 `caller_profile_id` 的线路;无满足项不接纳。`caller_profile_id` 是新增任务级明确引用,必须命中选中线路的获批主叫,不默认取第一个主叫。`route_policy_id` 只标识这份任务路由,不依赖另一个未定义的查询接口。选定线路/主叫后持久绑定;拨号失败或未知不自动换线重拨。
|
||||
- **最小路由约定(本地项目契约,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` 与 `config_sha256` 分别精确匹配获批 SIP artifact revision/SHA-256、`observed_at_unix_ms>0`,才可读取新配置/准入。缺失、重复、身份不符或匹配失败均 fail-closed。此为本地 Agent 协议规则,不是 SaaS/management 外部确认;Mock 状态不能证明真实 Asterisk 已加载。
|
||||
|
||||
### 3.2 租户额度
|
||||
|
||||
@@ -53,34 +54,35 @@ SaaS 先持久修改权威任务状态,再向独立 D 控制队列发布 `task
|
||||
|
||||
### 3.4 任务发现、发布与期限
|
||||
|
||||
D 启动/重启用 `/internal/v1/dispatcher/tasks` 拉一致全量快照和水位,运行中每 30 秒 `?after=<cursor>` 拉本 D 新增/更新/撤销。cursor 是变更水位,不是最大 task_id;完整分页连贯、持久应用成功才推进。游标失效、缺页、快照不一致时关闭受影响任务新准入并重拉全量。发现清单/任务响应必须提供 tenant_id/tenant_key 以便取额度。无变化不撤销消费关系。
|
||||
D 启动/重启用 `/internal/v1/dispatcher/tasks` 拉一致全量快照和水位,运行中每 30 秒 `?after=<cursor>` 拉本 D 新增/更新/撤销。cursor 是不透明变更水位,不是最大 task_id。新版单次返回完整快照或完整变更集,最多 256 条且不分页;响应不带每个任务的 queue/key,D 按已约定的 D+task ID 命名规则推导并只消费 SaaS 预建队列。全量 `cursor`、增量 `next_cursor` 仅在完整校验和原子持久化后推进;空变更的 `next_cursor` 与请求 `after` 相同。`removed` 表示完成退役握手后的撤销归属,不等同于 stop;HTTP 410 `cursor_expired`(含增量超限)关闭新准入并重拉全量,禁止截断或跳过变更。发现清单/任务响应必须提供 tenant_id/tenant_key 以便取额度。无变化不撤销消费关系。
|
||||
|
||||
**队列 ready 不等于 D 已开始消费。** 首条任务可能等待轮询、分页、配置/额度读取和可用名额;30 秒是轮询间隔,不是端到端发现 SLA。SaaS 设置的 `not_after` 应覆盖允许的排队和准备时间,不能用固定 30 秒示例承诺离线恢复必拨。D 重启仅恢复原消息:未过期且有效的才接纳;过期明确拒绝(已 stopped 则静默 ACK),绝不顺延期限/自动造新 command_id 重拨。若要求更短首呼时限,必须在 F07 另定就绪通知协议,不能假设已存在。
|
||||
**队列 ready 不等于 D 已开始消费。** 首条任务可能等待轮询、配置/额度读取和可用名额;30 秒是轮询间隔,不是端到端发现 SLA。SaaS 设置的 `not_after` 应覆盖允许的排队和准备时间,不能用固定 30 秒示例承诺离线恢复必拨。D 重启仅恢复原消息:未过期且有效的才接纳;过期明确拒绝(已 stopped 则静默 ACK),绝不顺延期限/自动造新 command_id 重拨。若要求更短首呼时限,必须在 F07 另定就绪通知协议,不能假设已存在。
|
||||
|
||||
SaaS 清单须保留已 stopped 但未排空任务;停止新发布、积压/未 ACK 排空、无未知执行并完成双方约定的退役核验后,才撤销任务归属/删除队列。该核验不靠逐条停止回执,队列空不代表无在途通话;撤销握手待 F07 冻结。D 不创建/删除队列;任务 ID 唯一性、key 长度/字符、队列总数上限一并冻结。
|
||||
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、实时文字/拒联/录音拆分事件。用户已选择仅最终反馈;取消即时拒联的产品风险与现有验收冲突须正式业务签收。最终结果的身份在本地持久化,MQ 重投仍是同一份事实,不重新拨号或上传。
|
||||
保留呼叫/控制回执及一种最终 `call.result`,不保留对外 query/replay、实时文字/拒联/录音拆分事件。用户已批准仅最终反馈,本轮实现与验收按此更新;真实 SaaS 消费兼容性另行验证。最终结果的身份在本地持久化,MQ 重投仍是同一份事实,不重新拨号或上传。
|
||||
|
||||
- 已产生录音:上传 OSS 成功后 `recording.status=uploaded`、携带路径;上传永久失败/到有限期限后 `unavailable`、明确错误与 null 路径。具体期限是 F07 阻塞项,不无限等待。
|
||||
- 已产生录音:上传 OSS 成功后 `recording.status=uploaded`、携带路径;上传永久失败/到有限期限后 `unavailable`、明确错误与 null 路径。明确上传/授权失败立即以 unavailable 收口,无确定结果最晚于 `call.ended_at + 15m` 收口。
|
||||
- 通话已尝试但忙线/无应答等**未产生录音**:终结已确认后即可发唯一结果,`recording.status=not_created`、身份/路径等资产值为 null,原因如 `no_answer`;不申请上传、不假称上传失败。录音本应生成却失败用 `unavailable` 和明确阶段原因,不伪装正常无录音。
|
||||
- 未接纳且被停止屏障吞掉:无命令回执、无最终结果;其他未接纳拒绝只有命令回执,不能伪造通话。已接纳取消/失败/挂断仍按其事实形成最终结果。
|
||||
- `outcome` 反映通话本身,录音错误写 recording 不改成呼叫失败。通话额度释放与上传/通知独立;日志只保留脱敏事实,不输出完整音频/文本/密钥。
|
||||
- 最终文字合并后的消息大小与现行 MQ 上限可能冲突,F07 必须冻结可容纳的正文上限和明确失败策略,不截断完整转写、不拆成用户已移除的实时事件来掩盖。
|
||||
- 最终文字合并后的消息大小与现行 MQ 上限可能冲突,项目内 JSON 正文上限为 8,388,608 bytes,超限保留 outbox 并显式阻塞,不截断完整转写、不拆成用户已移除的实时事件来掩盖。
|
||||
|
||||
## 4. 依赖顺序与工作包
|
||||
|
||||
**执行顺序:F00 → F01(HTTP/配置/额度)与 F07(MQ/发现/控制/结果)并行冻结 → 联合一致性签收 C → F02 → F03 → F04 → F08 → F09 → F06。F05 是另获授权的后续。** F01 不再要求先完成 F07 的 MQ 改写;二者共同签收后才能进入新路径实现。F03 单独负责新队列消费/状态屏障,F08 只集成结果交付和受控切换,不重复开发同一消费路径。
|
||||
**执行顺序: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 与配置/额度合同 | SaaS/management 签收四条 GET、两 Header、身份映射、任务主叫/候选优先级、两时限较小值、授权/缓存/配置不可变及租户额度份额/版本/有效期。 | 严格 Schema、来源/版本/哈希、正反例;静态提示词或变量来源明确。外部未签收则 blocked。 |
|
||||
| F07 MQ、发现及控制/结果合同 | 与 F01 并行:SaaS 签收任务发现分页/水位、先建后发、队列生命周期、精简 call.execute、无编号控制、pause保留/resume续消费/stop静默排空、状态优先级、回执/最终结果及无录音;联合核验 HTTP 与 MQ 相同身份/版本。 | 新版本权威包及业务签收 C;撤销旧 query/replay/配置MQ/拆分事件;未决结果期限/消息大小/退役握手全部冻结。 |
|
||||
| F02 配置与额度读取(C 后) | SaaS 提供四接口;D 读取并校验 SIP 实际加载、任务租户映射、按 tenant_id 的额度,完整 200 缓存;有期限拒绝与持久快照。 | 断 SaaS、降额、同租户多任务、过期/错身份、新旧配置竞态不超额/不漂移。 |
|
||||
| F03 消费/发现/控制(F02 后) | D 移除新协议 `--tenant-key` 自建租户队列路径,按 SaaS 已建任务队列消费;发现游标/暂停恢复/停止静默ACK/独立控制与原子额度;未接纳仍留 MQ。 | §5 的队列/控制矩阵通过;D 无建队权限仍可工作,stop静默但可排查。 |
|
||||
| F04 时段及最后拨号屏障(F03 后) | 任务×线路时段、排除日期、白名单、有效期和已绑定时限在 D/执行侧一致,最后许可与控制串行判定。 | 窗口边界/跨日/更新/暂停竞态无错误拨号,旧固定窗只在合同/验收批准后替换。 |
|
||||
| F01 HTTP 与配置/额度合同 | 按第三方文档冻结四条 GET、两 Header、身份映射、任务主叫/候选优先级、两时限较小值、授权/缓存/配置不可变及租户额度份额/版本/有效期。 | 项目内严格 Schema、来源/版本/哈希、正反例;静态提示词或变量来源明确;Mock 验证,不等待外部签收。 |
|
||||
| F07 MQ、发现及控制/结果合同 | 历史 F07 先冻结 v0.1 分页发现;仅任务发现随后由 F03 v0.2 单次响应修订取代。其余 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 任务发现修订(F04 前) | 每 D 单次完整响应≤256,正文无 queue/key;失效游标 410 恢复全量,空变更原游标,退役 `removed`;完整响应、任务归属、游标原子持久化,发现失败关准入/停任务消费但不中断控制。 | v0.2 Schema/示例/hash 与 Mock/本地 RabbitMQ 再验;只运行新协议,不把旧 F03 证据当作新版通过。 |
|
||||
| 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/云/线路另外授权。 | 旧本地证据不代签;回退不能并行旧新写入/额度或引起重拨。 |
|
||||
@@ -98,29 +100,35 @@ SaaS 清单须保留已 stopped 但未排空任务;停止新发布、积压/
|
||||
| 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任务变更、分页缺页/重复、游标失效、SaaS创建前误发、stopped仍有积压 | 不漏旧任务变更;重拉一致全量不越过未应用页;未入队原消息由SaaS保留;stopped保留清单直到静默排空,无未ACK/未知执行再退役。 |
|
||||
| 发现/退役 | 较小ID任务变更、空变更、重复/超过256条、游标失效、removed 退役、SaaS创建前误发、stopped仍有积压 | 不漏旧任务变更;不接收分页或响应内队列字段,不截断超限结果,失效后重拉全量且只在原子持久化后推进游标;未入队原消息由SaaS保留;stopped保留清单直到静默排空,无未ACK/未知执行再退役。 |
|
||||
| 队列权限/配额 | D禁止create/bind/delete、队列满、SQLite满盘、租户满额 | D只消费,不补建;SaaS保留未成功发布消息;事务失败不ACK已接纳;不会搬全部积压进SQLite,不阻塞控制/stop清理。 |
|
||||
| 无录音/失败 | 无应答/忙线且无录音;应有录音却失败;OSS超时;停止未接纳命令 | 正常无录音not_created且不等待上传;故障unavailable有阶段原因并在签收期限内最终收口;停止未接纳无回传;不能伪造call_id/成功路径。 |
|
||||
| 释放与结果 | 已确认结束但上传慢、MQ confirm丢失或重启、完整转写超过预算 | 通话额度已释放、未知仍占额;原结果身份重投不重拨/PUT;按签收的大小/失败合同处理,不静默截断或假成功。 |
|
||||
| 无录音/失败 | 无应答/忙线且无录音;应有录音却失败;OSS超时;停止未接纳命令 | 正常无录音not_created且不等待上传;明确授权/PUT失败立即unavailable,未知最晚15分钟收口;停止未接纳无回传;不能伪造call_id/成功路径。 |
|
||||
| 释放与结果 | 已确认结束但上传慢、MQ confirm丢失或重启、完整转写超过8 MiB | 通话额度已释放、未知仍占额;原结果身份重投不重拨/PUT;超限 outbox 显式阻塞,不截断/拆分/丢弃。 |
|
||||
| 时间及真实边界 | 任务/线路交集、空日、排除日、左闭右开、最后许可前控制到达 | 不跨窗或被暂停/停止后新拨,不等待次日自动执行;Mock时钟不等于real放行。 |
|
||||
|
||||
## 6. 写入与实施边界
|
||||
|
||||
项目设计在自身 docs;现行 Schema 保持不动,新合同先签收再导入唯一版本化来源,不手工维护两套发布 Schema。本文/分项/guide/字段提案必须同步;源码、截图、真实凭据、无关父仓库不改动。TDD 先失败后实施,复用现有库,禁止隐藏错误、HTTP/MQ配置回退、重复外呼。大改另开分支,未获得子 Agent 授权由当前负责人执行。
|
||||
项目设计与本地目标契约在自身 docs 维护。`contracts/upstream/v1` 保持现行外部运行基线,不擅改;原 v0.1 本地合同与 F03 证据保留为历史;`docs/thirds/v0.2.md` §2.5 中任务发现单次响应已作为**本地运行修订合同**完成实现和 Mock 校验,独立 v0.2 Schema、正反例和来源哈希见新版 F03 证据;这不代表真实 SaaS 已发布或签收。其他业务合同沿用已有本地 v0.1 机器校验件,须记录规范文件与机器文件 SHA-256。该本地契约不冒称 SaaS/management 已发布,外部签收和连通不阻塞本地 C。本文/分项/guide/字段提案必须同步;源码、截图、真实凭据、无关父仓库不改动。TDD 先失败后实施,复用现有库,禁止隐藏错误、HTTP/MQ配置回退、重复外呼。大改另开分支,未获得子 Agent 授权由当前负责人执行。
|
||||
|
||||
## 7. I/M/G 前置
|
||||
|
||||
**I**:用户方向确认不等于 SaaS/management 权威签收。四接口、租户份额、路由/控制优先级、新消息 Schema、结果失败期限及退役握手未完成联合 C 前不实现新生产路径。**M**:旧 W 的通过不能代替新 F02–F09;仅本地隔离验证不代表真线路/OSS通过。**G**:部署版本、网络/ECS只读核验、SHA-256、systemd enabled+active、Asterisk/ARI/PJSIP、媒体监听和非生产诊断门禁全部保留;实际云/生产/拨号另获授权。
|
||||
**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](archive/plan-0918.md)保留原文,只作历史。 | 不回写旧W台账。 |
|
||||
| F00 | 用户确认按tenant_id另取租户额度、pause保留/resume续消费、stop静默排空;相关文档/项目 Schema 已修订,非现网合同。 | 正反例与文档一致性检查、外部签收。 |
|
||||
| F01/F07 | 三条原路径/Header用户已指定;新增租户额度路径/字段、主叫/候选规则、控制优先级和无录音结构为本轮项目提案。 | 两合同包并行冻结后联合 C,不互设循环依赖。 |
|
||||
| F02–F04/F08 | 新路径未实现;现行代码仍是旧 MQ-only/静态租户队列等基线。 | C 通过,逐包 TDD/故障注入。 |
|
||||
| F09/F06 | 新验收及切换未执行,旧测试不代签。 | L证据与授权,真实联调另行安排。 |
|
||||
| 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`](evidence/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`](evidence/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`](evidence/f03-local-task-runtime-v0.1.md)。本地 acceptance、Race、vet、build、契约与无 `configure` 权限的 RabbitMQ 集成测试通过;`internal/dispatcher` 覆盖率 66.2%。仅是本地隔离验证,外部 SaaS/management、云、线路和生产均未验证;F09 新版本地矩阵见下行,历史分页证据不代签。 |\n| F03 v0.2 修订 | 本地运行已采用单次完整发现:每 D 最多 256 个归属任务、响应不含队列地址;队列名按 D+task ID 推导且只能被动消费 SaaS 预建队列。空变更保持 `next_cursor`,过期游标 HTTP 410 重拉全量,`removed` 退役,超额拒绝且不推进游标;发现故障关闭新准入/停任务消费但保留 MQ 控制。旧 F03 v0.1 证据只作历史。 | 证据:[`f03-local-task-discovery-v0.2.md`](evidence/f03-local-task-discovery-v0.2.md)。新版 Schema/正反例/hash 与本地 Mock、race、vet、构建和无 `configure` 的 RabbitMQ 测试通过;F09 本地全矩阵/覆盖率见下行,真实 SaaS/management/拨号/生产未验证。 |
|
||||
| F04 | 本地隔离 Mock 已将任务×已选线路时段、任务排除日期、白名单/有效期、绑定快照及任务/AI 较小通话时限接入接纳与发起前门禁;执行身份只有一次持久 `issued`/`refused` 决定,队列消费后由 D 经版本化 Unary 向 Mock Agent 下发,Agent 不重算业务策略、不发送 SIP。V3 mixed/real 启动拒绝,原真实固定门禁未放宽。 | 证据:[`f04-local-dial-policy-v0.1.md`](evidence/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`](evidence/f08-local-final-result-v0.1.md);F09 本地矩阵与覆盖率见 [`f09-local-acceptance-v0.2.md`](evidence/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`](evidence/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`](evidence/f09-local-acceptance-v0.2.md);F06 真实部署/切换仍未获授权。 |
|
||||
| F09 | 任务发现 v0.2 的 ≤256 单次完整返回、空变更/removed/410 恢复及计划 §5 单节点/单租户适用矩阵均已重新进行本地 Mock 验证;stop 前两条已发起执行的 Agent 归属与一次性拨号决定现由同一事务持久化,stop 可对两条发 hangup 且旧执行仍返回结果。证据:[`f09-local-acceptance-v0.2.md`](evidence/f09-local-acceptance-v0.2.md)。 | `scripts/acceptance-local.sh`(格式/合同/Proto/hash、race、vet、构建及受限 RabbitMQ)通过;本轮 P1 业务模块均 ≥65%,MQ 仅带 integration tag 时为 66.4%。CLI 29.6% 和历史 callruntime 61.7% 未达线,按用户确认口径单列技术债,**不声称全仓达标**。队列满真实 RabbitMQ Mock 拒绝;SQLite 满盘仅作写入错误注入,未物理填盘。外部/真实验收未完成。 |
|
||||
| F06 | 本地发布准备与切换阻断已核对:Go 1.27.1 一次性制品/校验和、v0.1 其他协议+v0.2 任务发现+项目 v3 MQ 队列及 Proto manifest 的版本/hash 写入制品清单;已有 release/package 输出及归档拒绝覆盖,mixed/real V3 执行在触碰 DB/MQ 前 fail-closed,旧消费 CLI 和旧分散事件不能并行写入新路径。证据:[`f06-local-release-gates-v0.2.md`](evidence/f06-local-release-gates-v0.2.md)。 | `make release-check-local` 与本地 acceptance 通过;来源 dirty,制品仅 local-development、`production_approval=false`。未获真实部署/拨号/切换授权,旧 Python 资源移交、ECS/systemd/Asterisk 实际加载和生产签收均**未执行**;本地阻断不代替真实切换。 |
|
||||
| F05 | 多D/第二租户不在本轮运行范围。 | 另获阶段与额度/资源授权。 |
|
||||
|
||||
## 9. 协作与版本记录
|
||||
|
||||
Reference in New Issue
Block a user