[SEN] 建立 Sense 内部事务 Outbox 与可靠 relay 状态机 #78

Closed
opened 2026-08-14 10:29:14 +08:00 by ila · 5 comments
Owner

状态

已完成(用户已验收)

基本信息

  • 类型:需求 / Sense 单项目独立任务
  • 任务类型:单项目
  • 主项目:Sense
  • 主 agent:Sense agent
  • 所属 Epic:#7
  • 所属 MVP / 版本:#80
  • 前置工单:#73
  • 是否允许与前置工单并行:否;必须先冻结前置领域接口
  • 独立运行:Brain、Bell 均不启动时完成实现和验收
  • 需求编号:SEN-014 的 Sense 内部可靠性前置;正式 connector 另建协调工单

原始需求与追溯

  • 来源:用户于 2026-08-14 要求建立 Sense 全部独立任务;Product-Requirements、Requirements-Migration-Matrix 和 Sense/AGENTS.md。
  • 摘要:Sense 单产品能够独立完成的后续能力全部建单;跨项目正式契约、Brain 控制和 Bell connector 留给协调工单。
  • 旧 explore 只用于需求、行为与测试对照,不复制自研基础框架。

目标

建立 Sense 内部事务 Outbox、幂等投递记录、退避和补投状态机,为未来可选 connector 提供可靠性基础。

范围

在同一数据库事务写入内部 outbox;实现 claim、lease、重试、死信/人工恢复、幂等键、指标和仅限测试的 sink。

非目标

不定义 Brain/Bell 标准事件 schema;不调用 Bell;不建立机器身份;不修改 contracts;不把内部 payload 当正式接口。

GoAdmin 复用要求

复用 #61/#64 建立的 GoAdmin/go-admin-ui 认证、RBAC、审计、Router、Store、Axios、Layout、表格、表单、分页、Dialog、Tag 和权限按钮;实施前读取相关冻结 go-admin-doc 并在评论记录采用方式。业务专用组件必须说明复用缺口并保持整体风格。

写路径

  • Sense/server/app/sense/outbox/**
  • Sense/server/database/migrations/*outbox*
  • Sense/ui/src/views/sense/outbox/**
  • Sense/ui/src/api/sense/outbox*
  • Sense/tests/outbox/**

禁止写入:Brain/**、Bell/**、contracts/**、根级构建/部署、docs/**、wiki-docs.json。需要共享路径时停止并转协调工单。

文档影响

更新对应 Sense Wiki 业务规则、配置、运行、排错和验收页面;本地镜像由单一协调工单同步。

验收标准

  • 业务记录与 outbox 原子提交
  • 多 worker claim/lease 不重复并发处理
  • 失败退避、恢复补投和永久幂等记录成立
  • 测试 sink 不可在 production 启用
  • Bell 不存在时不阻断 Sense 核心功能且队列可观察

验证方式

  • 事务、并发、lease、崩溃恢复、退避和幂等测试
  • PostgreSQL 多 worker 集成测试
  • 生产配置禁用测试 sink 与权限审计

风险与回退

Outbox 并发错误会重复或丢失。使用数据库事务、lease 和永久幂等键;回退 relay 进程但保留未投递记录。

协同需求摘要

本工单只实现 Sense 内部端口和夹具。涉及 Sense→Brain、Brain→Sense、Sense/Brain→Bell 的正式 schema、机器身份、部署或 E2E 时另建协调工单。

## 状态 已完成(用户已验收) ## 基本信息 - 类型:需求 / Sense 单项目独立任务 - 任务类型:单项目 - 主项目:Sense - 主 agent:Sense agent - 所属 Epic:#7 - 所属 MVP / 版本:#80 - 前置工单:#73 - 是否允许与前置工单并行:否;必须先冻结前置领域接口 - 独立运行:Brain、Bell 均不启动时完成实现和验收 - 需求编号:SEN-014 的 Sense 内部可靠性前置;正式 connector 另建协调工单 ## 原始需求与追溯 - 来源:用户于 2026-08-14 要求建立 Sense 全部独立任务;Product-Requirements、Requirements-Migration-Matrix 和 Sense/AGENTS.md。 - 摘要:Sense 单产品能够独立完成的后续能力全部建单;跨项目正式契约、Brain 控制和 Bell connector 留给协调工单。 - 旧 `explore` 只用于需求、行为与测试对照,不复制自研基础框架。 ## 目标 建立 Sense 内部事务 Outbox、幂等投递记录、退避和补投状态机,为未来可选 connector 提供可靠性基础。 ## 范围 在同一数据库事务写入内部 outbox;实现 claim、lease、重试、死信/人工恢复、幂等键、指标和仅限测试的 sink。 ## 非目标 不定义 Brain/Bell 标准事件 schema;不调用 Bell;不建立机器身份;不修改 contracts;不把内部 payload 当正式接口。 ## GoAdmin 复用要求 复用 #61/#64 建立的 GoAdmin/go-admin-ui 认证、RBAC、审计、Router、Store、Axios、Layout、表格、表单、分页、Dialog、Tag 和权限按钮;实施前读取相关冻结 go-admin-doc 并在评论记录采用方式。业务专用组件必须说明复用缺口并保持整体风格。 ## 写路径 - `Sense/server/app/sense/outbox/**` - `Sense/server/database/migrations/*outbox*` - `Sense/ui/src/views/sense/outbox/**` - `Sense/ui/src/api/sense/outbox*` - `Sense/tests/outbox/**` 禁止写入:`Brain/**`、`Bell/**`、`contracts/**`、根级构建/部署、`docs/**`、`wiki-docs.json`。需要共享路径时停止并转协调工单。 ## 文档影响 更新对应 Sense Wiki 业务规则、配置、运行、排错和验收页面;本地镜像由单一协调工单同步。 ## 验收标准 - [x] 业务记录与 outbox 原子提交 - [x] 多 worker claim/lease 不重复并发处理 - [x] 失败退避、恢复补投和永久幂等记录成立 - [x] 测试 sink 不可在 production 启用 - [x] Bell 不存在时不阻断 Sense 核心功能且队列可观察 ## 验证方式 - 事务、并发、lease、崩溃恢复、退避和幂等测试 - PostgreSQL 多 worker 集成测试 - 生产配置禁用测试 sink 与权限审计 ## 风险与回退 Outbox 并发错误会重复或丢失。使用数据库事务、lease 和永久幂等键;回退 relay 进程但保留未投递记录。 ## 协同需求摘要 本工单只实现 Sense 内部端口和夹具。涉及 Sense→Brain、Brain→Sense、Sense/Brain→Bell 的正式 schema、机器身份、部署或 E2E 时另建协调工单。
ila added the kind/taskproject/sensescope/independent labels 2026-08-14 10:29:14 +08:00
Author
Owner

原型 v0.1 待审核

  • 形成时间:2026-08-28 16:39:14 +08:00
  • 审核载体:当前 Codex 会话内的交互式可视化
  • 版本识别:#78 / Sense 可靠投递 / v0.1
  • 原型源文件(仓库外):D:\OPC\yovision-visualizations\issue-78\sense-outbox.html
  • 状态:等待用户确认
  • 确认人/确认时间:待用户审核后补录
  • 未导出到 prototypes/:用户未触发“导出原型 #78”,符合原型导出门禁

覆盖范围

  • 沿用 GoAdmin/go-admin-ui 的侧栏、顶部导航、TagsView、页面容器、搜索栏、表格、分页、Dialog、Tag/状态和权限操作形态。
  • 覆盖“未接外部出口、队列积压、死信待处理”三种运维场景。
  • 覆盖队列概览、关键词/状态/内部类型筛选、投递详情、处理时间线、必填恢复原因、重新排队成功反馈。
  • 明确“未配置 connector 不影响 Sense 核心功能”“production 禁用测试 sink”“不展示内部 payload、外部凭据或机器身份”。
  • 人工恢复保留原业务记录与失败历史,仅创建新的投递尝试,并提示操作审计。

非目标与边界

  • 不定义 Brain/Bell 正式事件 schema,不调用 Bell,不建立机器身份,不修改 contracts/**。
  • 本版本仅为审核原型,尚未创建任务分支、修改生产代码或执行数据库迁移。

设计与验证证据

  • 使用 UI/UX 设计规范检查了状态区分、错误恢复、键盘/语义控件、移动端布局和非纯颜色状态表达。
  • 保留项目现有 GoAdmin/Element Plus 风格,没有采用与现有产品不一致的独立暗色视觉或字体体系。
  • 浏览器验证通过:三场景切换、状态与类型筛选、详情 Dialog、恢复原因校验、重新排队、场景状态隔离、390px 小屏无页面级横向溢出。
  • 浏览器控制台未发现 error/warn。
## 原型 v0.1 待审核 - 形成时间:2026-08-28 16:39:14 +08:00 - 审核载体:当前 Codex 会话内的交互式可视化 - 版本识别:#78 / Sense 可靠投递 / v0.1 - 原型源文件(仓库外):`D:\OPC\yovision-visualizations\issue-78\sense-outbox.html` - 状态:等待用户确认 - 确认人/确认时间:待用户审核后补录 - 未导出到 `prototypes/`:用户未触发“导出原型 #78”,符合原型导出门禁 ### 覆盖范围 - 沿用 GoAdmin/go-admin-ui 的侧栏、顶部导航、TagsView、页面容器、搜索栏、表格、分页、Dialog、Tag/状态和权限操作形态。 - 覆盖“未接外部出口、队列积压、死信待处理”三种运维场景。 - 覆盖队列概览、关键词/状态/内部类型筛选、投递详情、处理时间线、必填恢复原因、重新排队成功反馈。 - 明确“未配置 connector 不影响 Sense 核心功能”“production 禁用测试 sink”“不展示内部 payload、外部凭据或机器身份”。 - 人工恢复保留原业务记录与失败历史,仅创建新的投递尝试,并提示操作审计。 ### 非目标与边界 - 不定义 Brain/Bell 正式事件 schema,不调用 Bell,不建立机器身份,不修改 `contracts/**`。 - 本版本仅为审核原型,尚未创建任务分支、修改生产代码或执行数据库迁移。 ### 设计与验证证据 - 使用 UI/UX 设计规范检查了状态区分、错误恢复、键盘/语义控件、移动端布局和非纯颜色状态表达。 - 保留项目现有 GoAdmin/Element Plus 风格,没有采用与现有产品不一致的独立暗色视觉或字体体系。 - 浏览器验证通过:三场景切换、状态与类型筛选、详情 Dialog、恢复原因校验、重新排队、场景状态隔离、390px 小屏无页面级横向溢出。 - 浏览器控制台未发现 error/warn。
Author
Owner

原型审核结论

  • 审核版本:原型 v0.1
  • 确认人:用户 ila
  • 确认时间:2026-08-28
  • 结论:通过审核
  • 覆盖范围:可靠投递页面外壳、三类审核场景、队列概览与筛选、详情、死信人工重新排队、错误/成功反馈及生产禁用测试 sink 提示。
  • 后续:按已确认文字需求和原型进入生产实现;若页面结构、主要流程、权限、状态或异常处理发生实质变化,将重新进入确认门禁。
## 原型审核结论 - 审核版本:原型 v0.1 - 确认人:用户 ila - 确认时间:2026-08-28 - 结论:通过审核 - 覆盖范围:可靠投递页面外壳、三类审核场景、队列概览与筛选、详情、死信人工重新排队、错误/成功反馈及生产禁用测试 sink 提示。 - 后续:按已确认文字需求和原型进入生产实现;若页面结构、主要流程、权限、状态或异常处理发生实质变化,将重新进入确认门禁。
Author
Owner

实施基线与路径校正

  • 冻结 GoAdmin 文档:已读取参考仓库固定提交 424855a360bde00321ac4888ace37a8e36f494c4 中的 router.md、api.md、models.md、pro-gen-code.md。
  • 继承路径:后端继续使用 GoAdmin 的 Gin Router、JWT/Casbin、GORM、迁移注册与操作审计;前端继续使用 go-admin-ui 的动态菜单、BasicLayout、Axios、Element Plus 表格/表单/分页/Dialog/Tag 和权限指令。
  • 默认模块:未新增或恢复任何框架演示模块;只新增 Sense“可靠投递”菜单及对应最小权限/API。
  • 路径校正:工单正文写的是 Sense/server/database/migrations/*outbox*,但当前冻结 GoAdmin 派生代码的真实迁移入口是 Sense/server/cmd/migrate/migration/version/,因此实现文件为 2026082815000_outbox.go;没有创建第二套迁移目录。
  • 共享边界:没有修改 Brain/**、Bell/**、contracts/**、根级编排或 docs/**。正式 connector、共享 schema 和机器身份仍留给协调工单。
  • Wiki:已更新并在线回读 Architecture-and-Code-Map、Business-Rules-and-Glossary、Local-Development-and-Verification、Deployment-and-Operations;本地 docs/** 镜像按本工单约束留给单一协调工单同步。
## 实施基线与路径校正 - 冻结 GoAdmin 文档:已读取参考仓库固定提交 `424855a360bde00321ac4888ace37a8e36f494c4` 中的 `router.md`、`api.md`、`models.md`、`pro-gen-code.md`。 - 继承路径:后端继续使用 GoAdmin 的 Gin Router、JWT/Casbin、GORM、迁移注册与操作审计;前端继续使用 go-admin-ui 的动态菜单、BasicLayout、Axios、Element Plus 表格/表单/分页/Dialog/Tag 和权限指令。 - 默认模块:未新增或恢复任何框架演示模块;只新增 Sense“可靠投递”菜单及对应最小权限/API。 - 路径校正:工单正文写的是 `Sense/server/database/migrations/*outbox*`,但当前冻结 GoAdmin 派生代码的真实迁移入口是 `Sense/server/cmd/migrate/migration/version/`,因此实现文件为 `2026082815000_outbox.go`;没有创建第二套迁移目录。 - 共享边界:没有修改 `Brain/**`、`Bell/**`、`contracts/**`、根级编排或 `docs/**`。正式 connector、共享 schema 和机器身份仍留给协调工单。 - Wiki:已更新并在线回读 Architecture-and-Code-Map、Business-Rules-and-Glossary、Local-Development-and-Verification、Deployment-and-Operations;本地 `docs/**` 镜像按本工单约束留给单一协调工单同步。
Author
Owner

实施完成,等待用户验收

最终差异

  • 新增 Sense 内部 outbox 消息、尝试历史和永久幂等收据模型。
  • 本地事件候选与 outbox 使用同一 GORM/PostgreSQL 事务写入,失败整体回滚。
  • relay 支持 claim/lease、PostgreSQL FOR UPDATE SKIP LOCKED、乐观版本、租约恢复、失败退避、死信、人工重新排队和成功幂等。
  • production/prod 模式拒绝测试 sink;没有正式 connector 时只保留队列,不阻断 Sense 核心功能。
  • 复用 GoAdmin Router、JWT/Casbin、迁移、菜单权限和审计;implementation_operator/site_admin/viewer 可读,只有 implementation_operator/site_admin 可人工恢复。
  • 复用 go-admin-ui BasicLayout、动态菜单、Axios、Element Plus 表格/表单/分页/Dialog/Tag/权限按钮;管理 API 和页面均不暴露 payload、外部凭据或机器身份。

测试与验收证据

  • go test ./...:通过。
  • 隔离 PostgreSQL 17:TestPostgresConcurrentWorkersDoNotClaimSameMessage 通过,验证多 worker 不重复 claim。
  • pnpm lint:0 error;32 条均为现有上游文件 warning,本工单文件无 lint 问题。
  • pnpm test:unit -- --runInBand:31 suites / 74 tests 全部通过。
  • pnpm build:prod:通过,仅有现有依赖/体积 warning。
  • python dev_scripts/harness.py check --strict:通过。
  • python -m unittest discover -s tests -v:48 tests 全部通过。
  • 真实浏览器临时环境:登录、GoAdmin 菜单/外壳、空状态、死信详情、恢复原因必填、重新排队成功与汇总更新均通过;390px 宽度无页面级横向溢出。
  • 临时 Sense、Vue、PostgreSQL 进程均已停止,专用临时目录已删除。

提交与合并

  • 实现提交:02a5af5e3b872a4e04dabf3c4f3d370e60800afd
  • PR:#122
  • dev 合并提交:7274bd42f52feb011b24eb5e291bff799bdcbbbc
  • 当前本地 dev 与 origin/dev 一致,工作区干净。

文档影响

已更新并在线回读:

  • Architecture-and-Code-Map:5ae46f327884de113b488f4caeb51934f772a93b
  • Business-Rules-and-Glossary:637efa818b28c7d041d8799f4ecfbb78a82f4905
  • Local-Development-and-Verification:5721f90d1a7ff768b7e84b510a0228044643ab8f
  • Deployment-and-Operations:21981c220960d793e279ccabe9fdd7d03971b934

harness.py sync --check 如预期报告本地核心镜像 revision 落后;#78 禁止写 docs/**,且工单已明确由单一协调工单统一同步,因此未越界修改镜像。

未验证/后续边界

正式 Brain/Bell connector、共享事件 schema、机器身份和跨项目 E2E 不属于 #78,仍需后续协调工单。#78 保持打开并处于“待验收”,等待用户确认。

## 实施完成,等待用户验收 ### 最终差异 - 新增 Sense 内部 outbox 消息、尝试历史和永久幂等收据模型。 - 本地事件候选与 outbox 使用同一 GORM/PostgreSQL 事务写入,失败整体回滚。 - relay 支持 claim/lease、PostgreSQL `FOR UPDATE SKIP LOCKED`、乐观版本、租约恢复、失败退避、死信、人工重新排队和成功幂等。 - production/prod 模式拒绝测试 sink;没有正式 connector 时只保留队列,不阻断 Sense 核心功能。 - 复用 GoAdmin Router、JWT/Casbin、迁移、菜单权限和审计;implementation_operator/site_admin/viewer 可读,只有 implementation_operator/site_admin 可人工恢复。 - 复用 go-admin-ui BasicLayout、动态菜单、Axios、Element Plus 表格/表单/分页/Dialog/Tag/权限按钮;管理 API 和页面均不暴露 payload、外部凭据或机器身份。 ### 测试与验收证据 - `go test ./...`:通过。 - 隔离 PostgreSQL 17:`TestPostgresConcurrentWorkersDoNotClaimSameMessage` 通过,验证多 worker 不重复 claim。 - `pnpm lint`:0 error;32 条均为现有上游文件 warning,本工单文件无 lint 问题。 - `pnpm test:unit -- --runInBand`:31 suites / 74 tests 全部通过。 - `pnpm build:prod`:通过,仅有现有依赖/体积 warning。 - `python dev_scripts/harness.py check --strict`:通过。 - `python -m unittest discover -s tests -v`:48 tests 全部通过。 - 真实浏览器临时环境:登录、GoAdmin 菜单/外壳、空状态、死信详情、恢复原因必填、重新排队成功与汇总更新均通过;390px 宽度无页面级横向溢出。 - 临时 Sense、Vue、PostgreSQL 进程均已停止,专用临时目录已删除。 ### 提交与合并 - 实现提交:`02a5af5e3b872a4e04dabf3c4f3d370e60800afd` - PR:#122 - dev 合并提交:`7274bd42f52feb011b24eb5e291bff799bdcbbbc` - 当前本地 `dev` 与 `origin/dev` 一致,工作区干净。 ### 文档影响 已更新并在线回读: - Architecture-and-Code-Map:`5ae46f327884de113b488f4caeb51934f772a93b` - Business-Rules-and-Glossary:`637efa818b28c7d041d8799f4ecfbb78a82f4905` - Local-Development-and-Verification:`5721f90d1a7ff768b7e84b510a0228044643ab8f` - Deployment-and-Operations:`21981c220960d793e279ccabe9fdd7d03971b934` `harness.py sync --check` 如预期报告本地核心镜像 revision 落后;#78 禁止写 `docs/**`,且工单已明确由单一协调工单统一同步,因此未越界修改镜像。 ### 未验证/后续边界 正式 Brain/Bell connector、共享事件 schema、机器身份和跨项目 E2E 不属于 #78,仍需后续协调工单。#78 保持打开并处于“待验收”,等待用户确认。
Author
Owner

用户验收结论

  • 验收人:用户 ila
  • 验收时间:2026-08-28
  • 结论:#78 验收通过
  • 验收对象:已合入 dev 的实现提交 02a5af5e3b872a4e04dabf3c4f3d370e60800afd,PR #122,合并提交 7274bd42f52feb011b24eb5e291bff799bdcbbbc
  • 后续边界:正式 Brain/Bell connector、共享 schema、机器身份和跨项目 E2E 继续由后续协调工单承担
  • 文档:长期 Wiki 已在待验收阶段更新;本次验收没有产生新的长期事实,不重复修改 Wiki,也不创建任务归档
## 用户验收结论 - 验收人:用户 ila - 验收时间:2026-08-28 - 结论:#78 验收通过 - 验收对象:已合入 `dev` 的实现提交 `02a5af5e3b872a4e04dabf3c4f3d370e60800afd`,PR #122,合并提交 `7274bd42f52feb011b24eb5e291bff799bdcbbbc` - 后续边界:正式 Brain/Bell connector、共享 schema、机器身份和跨项目 E2E 继续由后续协调工单承担 - 文档:长期 Wiki 已在待验收阶段更新;本次验收没有产生新的长期事实,不重复修改 Wiki,也不创建任务归档
ila closed this issue 2026-08-28 17:33:07 +08:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ila/yovision#78