Files
go-sip/AGENTS.md
T

181 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# go-sip:独立项目约束
## 宪法
- 任何涉及文件的调研或修改,如果当前是 git 仓库,需要先同步远程提交到本地,避免调研过时问题。
- 基于 TDD 进行功能的开发与业务变更,单元测试覆盖率要保证 65% 以上
- 任何时候我提出任何需求均需要理解并**结构化复述后与我进行确认,避免理解偏差**。
- 不要在代码里藏兜底逻辑来吞掉错误、隐藏问题。出了问题就应该让它爆出来,否则你永远找不到真实问题。
- 当一个问题出现时,不要用各种 small fix、针对性补丁来掩盖它。**必须定位真实根因,彻底修复**。在 bug 上糊纸只会让系统积累你不知道的危险暗病。
- 即使问题很难定位,也**绝不要偷懒做表面修复**。应该给项目增加充分的日志和可观测性,保证下次问题再现时你有足够信息去定位。问题无法修复时,只需要诚实告诉我信息不足、需新增日志,不要假装修好了。
- 始终注意在关键路径上给自己留足排查日志,确保每一个**关键节点都是可追溯**的。
- 当项目关键技术栈或产品方向发生变更时,同步更新 agents.md。文档必须随代码一起演进,不能让它变成过时的谎言。
- 大规模重构或实验性改动前,必须先切新分支。
- 不以维护向后兼容性为目标。**对于已经废弃的代码路径,应直接移除**,不再通过兼容层、回退机制或迁移方案予以保留。
- 在充分满足当前需求的前提下,采用**尽可能简单的实现方案**。避免引入缺乏实际需求依据的抽象、配置项和间接层。
- **采用渐进式、分层的方式构建系统**。首先完成能够端到端运行的最小版本,再基于稳定可用的产品逐步增加功能。不要以尚未成熟的复杂性取代已经可用的产品。
- **保持组件的模块化**,并明确划分不同职责与关注点。
- 当成熟且维护良好的库能够降低整体复杂度或提高可靠性时,应优先采用。除非有明确理由,不要重复实现通用功能。
- 在自行实现功能或新增依赖之前,应优先评估项目现有依赖的能力。应先查阅相关文档和类型定义,不应未经确认就认定某个库不具备所需能力。
- 架构决策**应着眼于长期演进**。不要采用仅能解决当前问题、且预期需要在后续替换的权宜方案。
- 在设计解决方案之前,**先研究成熟产品如何解决同类问题**。优先采用经过验证的模式和约定,避免从零开始另行设计一套方案。
## 禁止清单(不主动考虑、不主动提议、不实现,遇到只记入 TODO 技术债列表)
1. 法律合规:商业库授权、开源协议合规、GDPR/个保、隐私政策(法务负责)。
2. 依赖安全:NPM 及第三方包漏洞、安全补丁、依赖升级策略。
3. 访问安全:服务只需支持局域网访问(host 绑定 0.0.0.0 即可),不考虑公网暴露、HTTPS、认证/权限体系(登录、RBAC)、限流、防爬、数据加密、审计日志。
## 红线清单(快速阶段也不能省,现在便宜、以后极贵)
1. 数据模型/表结构:认真设计,建表慎重——改表成本远高于写代码。
2. 目录结构与模块边界:保持简单清晰,不堆一坨代码。
3. 基础错误日志:出错时至少能看到发生了什么。
4. Git:小步提交,保持历史清晰。
5. 基础输入校验:仅防止程序崩溃,不做安全加固。
6. 环境差异配置(端口、地址等)与代码分离(.env 或配置项)。
## 沟通方式
- 向使用者回报时,使用清楚直白的语言说明做了什么、结果如何。最终回复禁用术语、技术实现细节与工程腔。写法是:对一个聪明但没在看代码的人解释。
- 实际执行过程(思考、规划、写程序、除错、解决问题)保持完整的技术严谨度,这条规范只适用于对使用者的沟通方式。
## 回复风格
- 只写结论、实际改动、原因、验证结果
- 不描述推进动作,禁用「我先……再……」等叙述句式
- 不使用工程汇报腔(「落地」「落到」「推进」等类似用语)
- 直接、专业、去表演化
- 回复文字永远使用与对方相同的语系,专有名词维持英文
- 不使用口语化表达,说重点,简单明了
- 需要时搭配条列式与表格加强输出可读性
## 决策规则
- 当方案有多个选项时,列出每个选项的优缺点,并明确指出推荐选项与原因,先问我。
- 有多种实现方式时,选最简单能跑通的。
- 遇到"禁止清单"中的问题:不展开、不实现,追加到 TODO 技术债列表即可。
## Sub-Agent 使用时机
当任务符合以下任一条件时,直接 spawn sub-agent 分工执行,无需询问使用者:
- 任务可拆分为多个**平行且无依赖**的子任务
- 各子任务职责明确分离,合并执行会造成 context 混杂
- 大量结构相同的重复性任务(可用 `spawn_agents_on_csv` batch 执行)
- 各子任务需要不同的 model 配置或 sandbox 权限,例如:
- 探索型任务使用轻量 model + `read-only` sandbox
- 审查型任务使用高推理 model + `read-only` sandbox
- 修改型任务使用执行导向 model + `workspace-write` sandbox
## 验证标准
开始任务前先定义完成标准。交付前依此验证,发现问题就修好再测,不把未完成的工作交回给使用者。只有确认完成,或遇到真正需要使用者介入的障碍时,才回报。
## 当前范围
- 后续Agent必须先读 `docs/plan-0918.md`:映射W/子任务,按索引读取需求/契约正文,确认I/M/G前置、授权及写入边界后实施;并行时按§9认领,子Agent只写独占模块/证据,§8总台账、公共文件及合并状态由集成负责人单写。计划不替代权威Schema或验收,不重复审批已确认方向,不自动授权真实云/付费/拨号。
- 用户指定:若启动开发及配套审查子Agent,固定 **gpt-5.6-luna、max思考、fast模式**。启动前查询精确provider/model和runner支持并显式配置(当前工具用模型`:max`后缀及`fast: true`,不继承默认);不可用/不支持/无法核验则报告阻塞,不静默换模型、降思考档、关fast或换CLI。此为后续执行约束,本轮仅修复计划,未启动开发子Agent。
- 并行开发须先有获授权的可追溯Git/契约基线、一lane一工作区/测试资源、无交叠写集合及每批合并后回归;当前子项目尚未跟踪的文件不能假定存在于HEAD/worktree。不得自动提交、暂存或清理父项目无关改动;详情见计划§9。
- 当前已获授权进行本项目开发:W01 项目内契约基线和 W02 Proto/stubs 已建立;仍不能把设计、Mock、Proto或88项测试清单写成真实供应商/生产验收已通过。入口和权威依据仍为 `docs/Go重写方案_v0.3.md`、`docs/验证与切换验收_v0.3.md`、`docs/通信与事件数据交互_v0.1.md`、`docs/OpenAPI与MQ字段索引_v0.1.md`、`docs/开源组件选型与复用清单_v0.2.md`。
- 开发准备见 `docs/G0开发准备与契约冻结提案_v0.1.md`:D01–D10的方案方向、双模式/许可/恢复机制及内部PoC初始profile已获用户确认;本项目已自行交付 W01/W02 开发基线,但外部权威发布、真实预算、供应商签收和 G0/PoC 仍需分别验证,不能混写为生产合同。缺失字段细节、实际预算及方案变更另行确认。本轮验收基线收敛为单节点/单 Agent/单 Cell/单租户;双节点、第二 Cell、第二租户及其公平/故障矩阵不在本轮开发或验收范围,跨 Cell/多租户能力保留为后续阶段。
- 用户已确认完整 Go Agent、分阶段替换:调度、Cell 执行、ARI/RTP/录音、AI 流及 Cell 配置接收。最终没有 Python 运行依赖;不重写 Asterisk、不实现第二套管理后台。
- 本项目已独立拆仓运营,源码、文档、依赖、配置、迁移、测试、部署、发布入口全部留在本目录。普通构建/测试/运行不读取父目录,不使用其它项目内部模块、环境文件或夹具,不共享其业务数据库。
- 当前已初始化独立 Git 仓库并绑定公开远程 `git.ipao.vip/rogee/go-sip`;未经授权不要重新 `git init`、改为 submodule、移动历史或更改父仓库跟踪关系。
## SIP 接入信息
以下为用户提供的 SIP 参数,服务商名称待补充;已记录不代表已完成真实线路验证。
| 服务商 | SIP 服务端 | 主叫号码/标识 | 被叫前缀 |
| --- | --- | --- | --- |
| 数企 | `61.132.228.221:5060` | `BD93205882` | `7089` |
| 中鼎 | `60.171.24.90:5060` | `mbkq` | 无 |
| 百应 | `160.202.254.79:5060` | `KQ91526` | `mka755` |
## SIP 全局共用定义:外呼号码白名单
- 外呼号码白名单:`15003164745`、`15830461047`。
- 所有 SIP 线路仅允许在此列表范围内发起外呼;不在列表内的号码必须拒绝。该列表仅用于已授权的 Mock/明确安排的测试;不得因写入此处而自动发起真实呼叫,原始号码保持不变。
- SIP 外呼时间窗口固定为 Asia/Shanghai 每日 `09:00`(含)至 `20:00`(不含);窗口外 Dispatcher/Agent 必须 fail-closed,禁止等待、自动延迟、重试或换线。mock 测试可注入时间验证边界,不能用 mock 结果宣称 real 放行。
- 主叫标识保留原值(包括 `BD`),不能按纯数字手机号清洗,也不能直接当成 Digest 认证用户名;具体 From/PAI 等字段映射仍需确认。
- 业务原始被叫号码保持不变;使用该线路时按其规则构造 `7089<被叫号码>`,避免重复添加或把该前缀带到其他供应商线路。
- 传输协议、IP/Digest 鉴权、是否注册及并发限制仍需供应商确认;当前供应商已反馈需使用 PCMA,Asterisk 配置以 `allow=alaw` 表示,仍需真实线路验证。
- 每条线路目前只提供一个服务端地址,未提供独立备用地址。不能把同一地址重复填写成主备并宣称具备容灾;三条已登记线路应作为独立 trunk 配置,不为凑主备虚构供应商。
## ECS 部署环境与 Asterisk 运行约束
- ECS 部署环境固定优先使用 Debian 13(Trixie)minimal;仅当阿里云北京区域没有可用的 Debian 13 镜像时,才允许使用 Ubuntu 24.04 LTS。不得擅自切换到其他操作系统。
- Asterisk 必须直接部署在实际承载它的 ECS 主机上,由 systemd service 统一管理并启用开机自启动;部署验收必须确认 service 已 enabled 且 active,不得以手工前台进程或容器入口替代生产启动方式。
## 开发与非生产环境强制部署/诊断步骤
- 开发、Mock、mixed、real 的**非生产环境**必须默认开启环境部署与诊断步骤;这些步骤是必需的,不得因“只是开发”“环境已存在”“时间紧”或调用方参数而跳过、关闭、静默降级或默认禁用。任何显式关闭均视为配置错误,应失败并阻止验收。
- 每次新主机、新版本或新 Cell 验证至少执行并留存脱敏事实:ECS/EIP/网络资源只读核验、Debian/架构/磁盘/权限核验、`rogee` SSH 与 SSH 加固核验、发布包及依赖 SHA-256、Asterisk/systemd `enabled+active`、ARI/PJSIP endpoint/contact 状态、媒体 profile/监听端口和运行版本。
- 每次非生产 `mixed`/`real` 外呼验证,必须先通过 Asia/Shanghai `09:00`–`20:00`(左闭右开)时间门禁,再在拨号前启动受限 SIP/RTP 抓包和 Asterisk PJSIP logger,并在结束后采集 SIP 响应码、INVITE/180/183/200/4xx/5xx/BYE 或 CANCEL 时间线、SDP codec/媒体地址端口、RTP 包/字节计数、录音与 ASR/LLM/TTS 事实及 SHA-256;无拨号前抓包、状态快照或时间门禁不得宣称验证通过。失败呼叫同样必须保留状态和抓包证据,不能只报告一个 hangup cause。
- 抓包、日志、录音和识别文本只写入受限的非生产证据目录,聊天、源码、配置样例、提交和长期证据不得保存密钥、完整用户音频或完整用户对话;交付证据默认保存脱敏摘要、计数、状态码和哈希。若 tcpdump/CAP_NET_RAW、PJSIP logger、ARI/PJSIP 状态采集任一不可用,必须 fail-closed 报告阻塞,不得静默改成无抓包流程。
- 上述步骤由统一部署/验收入口自动执行;`mock`、`mixed`、`real` 只替换适配器,不能绕开同一套部署、诊断、状态和证据门禁。生产环境仍须另行授权和通过生产安全屏障,非生产默认强制开启不等于生产放行。
## 本次上线目标与分期(用户已确认)
- P1以稳定快速内测上线为目标:1个节点、1个Agent、1套Asterisk、1个单活Dispatcher/SQLite、1个启用租户;本轮不开发、不验收双节点、第二 Cell/第二 Asterisk或第二租户。
- 至少3家独立SIP trunk 的静态配置、路由/主叫/前缀/codec/额度约束和协议 Mock/mixed 覆盖仍需保持;真实供应商外呼和 ECS 仅作为第二阶段联调,不是本轮前置。
- ASR-only和ASR+LLM+TTS均按批准的不可变AI配置在本地/隔离链路验收;不擅自加MQ模式字段,不复用旧LLM/TTS。真实供应商未联调时必须明确标记为第二阶段,不能把 Mock 写成真实供应商通过。
- P1使用管理平台批准的静态单 Cell 快照和受控维护窗口,不做在线发布/回滚编排;静态配置必须关准入、排空、核验实际加载,旧直写通道不得并行。
- P1保留 tenant_key 原值、租户独立队列、复合幂等键、有界窗口及单租户配额/控制边界;不开发或验收双租户公平、第二 Cell 汇总配额和多实例协调。
- `upload-session/complete/verified`、RabbitMQ ACL/TLS 和 application receipt 本阶段按版本化契约、Schema、正反例 fixture、状态机和本地隔离测试验收;真实 SaaS/MQ 联调延期第二阶段。
- 88项验收为跨阶段基线,当前只签收单节点/单 Cell/单租户适用子场景;双节点、第二 Cell、第二租户、真实 ECS/生产联调、容量/N+1及切换均不作为本轮门禁。
## 语言与工程
- 工具链基线为 Go 1.27.1。实施时锁定 CI/构建镜像和依赖,并校验实际工具链;不得自动修改其它项目的 Go 基线。
- 标准库优先、单Go module/二进制,用Cobra显式提供agent、dispatcher两个业务子命令,无默认双角色启动;同一制品分进程/权限/目录,升级受版本兼容和排空约束,不另造CLI框架。
- JSON v2、UUID 和新测试 API 的采用以契约兼容和实测为前提;既有标识、哈希规范不得随 API 更换。实验性 SIMD 不在当前范围。
- 用户已确认不接PG:独立Dispatcher持有SQLite权威任务/配额/outbox,Agent无业务DB,文本/录音及执行/上传恢复信息落文件。禁止NFS共享SQLite/两份DB双活发额度,自动跨机热备不在已实现承诺内。
- 已确认Unary gRPC,Dispatcher预配置Agent Endpoint;Agent业务只需D Endpoint,证书/监听/ARI/持久目录由部署提供。SDK复用连接,不增内部MQ或双向流,不因RPC超时重拨。
- 所有Agent共用mTLS证书,D身份独立;必须通过受控Endpoint主动激活/节点会话授权,不信自报身份/地址。共享私钥泄露影响整组,轮换/撤销和风险要签收,不关闭SAN/SNI校验。
- D感知健康/负载/软件协议/能力及供应商applied配置版本;样本过期/缺失为unknown,低CPU不突破租户/供应商/Cell/AI配额,新boot不清旧未知占用。
- 实施后至少执行本模块的格式化检查、`go vet ./...`、`go test -race ./...` 和构建;当前代码已有 W01/W02/本地 RPC/AI Mock 入口,真实 DB/MQ、媒体、供应商、容量及切换验收仍分别报告,不能用本地通过记录代签。
## 开源复用硬约束(用户已确认)
- SIP 及其它组件有适用开源库/官方 SDK 必须复用,禁止从零手写替代协议栈或客户端。优先标准库、Asterisk 原生能力、现成 SDK;自有代码限业务状态机、事务、权限、配额和薄适配。
- 不自写 SIP/ARI、RTP/RTCP 编解包、G.711、WS/AMQP/数据库驱动、OSS 签名、已有 SDK 覆盖的 AI 协议或 Schema 解析。库不满足先选替代、修上游或报告阻塞;例外须用户另行批准。
- 采用前核验 module/tag/commit、Go1.27.1、许可证/NOTICE、传递依赖/漏洞及真实协议兼容,留存 PoC;不得将 main README、未归档或可下载等同于生产通过。
- SDK 自动重试不得造成二次 originate、旧音频重播或重复收费;不因 SIP 库存在而用 sipgo/diago 替换已选定 Asterisk 架构。
## AI配置与参数(用户已确认)
- P1采用百炼/火山ASR、OpenAI兼容LLM、火山TTS;SDK首选及未通过门禁见组件清单§1.3/§4.3。基础栈方向确定不等于精确版本、许可证或参数能力已验收;不为补字段改为自写协议。
- Dispatcher按MQ任务agent_version_id调用SaaS已有AI版本GET,校验租户/源Schema/不可变摘要/能力后向Agent交付执行快照。Agent不直连SaaS,不从CLI/env/源码常量或SDK默认覆盖AI业务值,不新增task-config猜测路径、MQ模式字段或调参后台。
- 已有model/prompt/voice/speed/ASR输入与识别/temperature/max_tokens/timeout及对话控制必须实际传入SDK或控制器;热词/VAD/top_p/音量/阶段时限等所需扩展先在上游补GAP-09,再生成校验。严格additionalProperties不放宽,不借metadata/raw_request透传。
- SaaS新版本供新任务引用,无需改代码/重启D/A;在途/原排队任务固定快照,同版本异内容拒绝。缓存按租户+版本隔离,断SaaS无有效授权缓存拒新准入;显式0/false与未提供保真,并发通话不得共享可变SDK参数。
- 凭据/供应商端点来自受控引用且有授权/出口校验,不能因可调参数绕过安全硬限额或启用不安全重试。OpenAI默认自动重试显式关闭;日志只留脱敏版本/摘要/有效参数,不打印prompt/变量/密钥。
- 静态发布只约束SIP/节点制品,不将AI配置硬编码;GAP-08/09及SDK参数PoC为P1门禁,验证入口见验收§5.1(现有E/L项子场景,不新增虚假通过数)。
## 契约与可靠性
- 本项目设计/运行/验收文档只在自身 `docs/` 维护。上游共享接口有唯一权威来源;导入带版本、来源和哈希的不可变契约包,再生成类型/校验,不维护重复手写 Schema。
- 新内部消息/许可/fencing 协议需先获批;不擅自改变 SaaS 路径、字段、状态、路由或控制语义。
- SaaS外呼命令/业务结果只经Dispatcher走RabbitMQ;内部Unary是已批准的执行通道,不新增对外HTTP拨号/业务回调。OSS配置源SaaS,D承接recording-uploads/upload_id/complete;Agent从Dispatcher取得受限目标/凭证/headers等配置后**直连OSS上传文件**,D不接收或转发录音内容、不替Agent上传。Agent经R13提交上传元信息,D协调SaaS verified后通过MQ返回OSS ID;Agent不直连SaaS不禁止其直连OSS。
- 文本实时事件准确名为transcript.updated,不新增call.transcript别名;OSS文本归档不能替代实时文字/opt-out,缺少专用资产授权接口时明确未启用,不能伪装recording.ready。
- 现有MQ信封command_type/command_id、event_type/aggregate_*与正文已对齐;事件payload专属约束尚需补齐,不把通用object校验当完整验收。字段索引只读生成,不手改成第二套Schema。
- `tenant_key` 原值一对一绑定,不清洗、编码或截断;超出 224 个 UTF-8 字节的既有路由预算时停止发布并保留源任务。
- 持久 inbox 后 ACK;状态与 outbox 同事务;confirm 不等于 SaaS 应用收讫。重复投递、未知执行和恢复不能触发重复拨号。
- 配额覆盖所有 Cell/实例及未知占用;租约过期不自动释放不明通话。控制CAS为 expected_task_revision,pause与stop的drain/hangup区分;paused可按新授权恢复,stopped不可恢复。整体补传仅call_id/source_command_id,禁止新增task/execution补传。最后发起许可、权限和屏障须故障注入。
- management是SIP配置唯一编辑/审批面。P1通过批准的版本化静态制品和受控部署入口交付,D核验目标/准入屏障,Agent加载并报告;不要求在线发布控制面。静态交接合同须批准,旧直接写Agent面不能同时启用;成功必须证明精确快照已被Asterisk加载。
## 安全和真实验证
- mock/mixed/real 明确隔离;Mock 默认隔离真实外网,正式模式拒绝 Mock/测试凭据,不静默回退。
- 只允许复用既有 ASR 协议;禁止复用 `voice_test` 的 LLM/TTS。P1必须完成新LLM/TTS规范、SDK适配和本地/协议隔离验收;真实供应商联调延期第二阶段,不能以Mock冒充真实供应商通过,也不能把真实联调延期误写成当前 P1 已实测。
- 真实外呼只允许原始号码 `15003164745`、`15830461047`,但白名单和文档不是拨号授权;每次真实验证仍需明确安排,且仅可在 Asia/Shanghai `09:00`–`20:00`(左闭右开)执行。每条 SIP trunk 对每个原始手机号每天最多 3 次;某条线路失败时可在额度内经当前会话确认后改测另一条线路,但不得在窗口外等待、自动延迟、在同一条线路/号码上超额、自动重试或静默换线。
- 不把 SIP 白名单出口 IP 当作 SIP 服务端,不虚构备用线路,不逐呼重写共享配置,不自动重拨已接通/未知的执行。
- 生产使用多机器、多 EIP 直连;1000 路指完整 ASR/LLM/TTS 已接通通话,N+1 与供应商能力须实测,不采用单 EIP+NAT。
- 独立开发和测试不要求云账号。云创建、EIP 改绑、网络放行、供应商消费和测试资源清理必须另获明确授权;不得触碰无关资源。
- 不在源码、配置样例、文档、日志或证据中保存密钥、密码、私钥、完整用户音频/对话;注入受控凭据,诊断端点仅管理网可达。
- 旧 Python 与新 Go 不得同时写同一资源或各自发放共享额度。没有可验证的所有权/状态回迁方案就暂停切换,不以回滚镜像冒险重拨。