diff --git a/docs-developer/prompt-background-tasks.mdx b/docs-developer/prompt-background-tasks.mdx index ad65190..e987f23 100644 --- a/docs-developer/prompt-background-tasks.mdx +++ b/docs-developer/prompt-background-tasks.mdx @@ -21,7 +21,7 @@ description: 使用 Pipecat 原生 Jobs 委派远程 OpenCode 任务。 ## 运行与恢复 - NativeTaskRuntime 只组装 `WorkerRunner`、常驻 CoordinatorWorker 和 RemoteAgentWorker。派发、超时、取消和 FIFO 串行执行由 Pipecat 原生 Job 系统负责。 -- 等待时限覆盖每次本地 Job(含排队),重启或重新观察后重新计时,不代表累计任务寿命上限;超时触发远端停止核查。原生 Job 全局 FIFO 串行;若另有未结束的远端句柄,新的编码任务不会提交,需先核查或停止旧任务。无法约束平台之外的 OpenCode 客户端。 +- 等待时限覆盖每次本地 Job(含排队),重启或重新观察后重新计时,不代表累计任务寿命上限;超时触发远端停止核查。原生 Job 全局 FIFO 串行;若另有未结束的远端句柄,新的编码任务不会提交,需先核查或停止旧任务。被阻挡的新任务会标为失败并说明尚未向远端提交;解决旧任务后需重新提交,不会自动恢复。无法约束平台之外的 OpenCode 客户端。 - 提交回执表示平台接受任务。OpenCode 的 204 只表示远端接收;必须取得关联到本次 messageID 的完成消息才能显示成功。 - OpenCodeAdapter 负责创建远端 session、订阅 SSE、异步提交、结果查询和 abort。每个任务使用独立远端 session,内部步骤仍由 OpenCode 完成。 - 原生 Job 取消不代表远端已停止。适配器调用 abort 并查询远端状态;未确认时保留「停止待确认」。 @@ -48,3 +48,5 @@ description: 使用 Pipecat 原生 Jobs 委派远程 OpenCode 任务。 ## 验证边界 测试覆盖真实 Pipecat Jobs 的派发/进度/断线独立/取消,以及显式模拟的 OpenCode HTTP/SSE 协议。不把模拟执行结果当作真实代码修改结果。本次在与项目一致的临时 pgvector/PostgreSQL 17 容器中完成了全量 Alembic 迁移、真实任务 API + 原生 Job + 数据库存储验收,覆盖重复请求不重复提交、事件序号与服务重启后的查询;远端仍由 MockTransport 显式模拟。现有开发库未修改,部署时仍需执行迁移,真实 OpenCode 联调待配置服务后进行。 + +协议配置可参考 [OpenCode Server 官方文档](https://opencode.ai/docs/server/)。 diff --git a/implement-stage/ASSUMPTIONS.md b/implement-stage/ASSUMPTIONS.md index b8b1d7b..5011818 100644 --- a/implement-stage/ASSUMPTIONS.md +++ b/implement-stage/ASSUMPTIONS.md @@ -24,6 +24,7 @@ | A-019 | 超时定义 | 时限针对每次本地观察Job(包含排队);重启/重新观察重新计时,超时与用户停止都进入远端abort核查,确认停止后才显示cancelled,不作为累计任务寿命上限 | semantic | sweep | | A-020 | 自动测试控制函数 | 测试运行器中提交、查询、取消、回复全部拒绝,不访问真实任务服务;修复首轮审阅发现的仅提交有防护问题 | semantic | sweep | | A-021 | 任务列表范围 | 管理API最多100项,优先未结束任务;网页展示全部返回项,无分页,更早记录可凭task_id查询/控制 | interface | sweep | +| A-022 | 远端未结束时的新任务 | 已接受的本地排队任务若发现其他未结束远端句柄,会以failed终结并明确说明未向远端提交;不会等旧任务解决后自动恢复,需用户重新提交 | semantic | sweep | ## Sweep corrections - A-001:修复服务端曾接受 literal/variable 参数的启动 Action task 绑定;不支持即在保存时拒绝。 diff --git a/implement-stage/BUILD_NOTE.md b/implement-stage/BUILD_NOTE.md index b7f941b..6af0aed 100644 --- a/implement-stage/BUILD_NOTE.md +++ b/implement-stage/BUILD_NOTE.md @@ -2,11 +2,11 @@ | Rung | Feature | Acceptance check | Tier | Status | |------|---------|------------------|------|--------| -| F0 | 原生Job主线、断线独立与取消 | backend/.venv/bin/python -m unittest discover -s backend/tests -p test_background_task_native.py | MUST | passed | +| F0 | 原生Job主线、断线独立与取消 | PYTHONPATH=backend backend/.venv/bin/python -m unittest discover -s backend/tests -p test_background_task_native.py | MUST | passed | | F1 | OpenCode协议适配与状态关联 | cd backend && .venv/bin/python -m unittest tests.test_background_task_native tests.test_opencode_tasks | MUST | passed | | F2 | 持久记录、管理API、应用宿主 | cd backend && .venv/bin/python -m unittest tests.test_background_tasks | MUST | passed | | F3 | 提示词绑定、任务通知、网页 | cd frontend && npx tsc --noEmit | MUST | passed | -| F4 | 回归、文档与假设审阅 | make test | MUST | checks passed; sweep pending | +| F4 | 回归、文档与假设审阅 | make test | MUST | passed; sweep provisional | ## Run record - F0: PYTHONPATH=backend backend/.venv/bin/python -m unittest discover -s backend/tests -p test_background_task_native.py → exit 0; native-jobs-smoke.json。 @@ -15,7 +15,7 @@ - F3: 累计9项后端任务测试通过,TypeScript检查通过,前端lint无错误(BatchTestPage已有1条warning)。 - F4: `make test` → exit 0;367 项后端测试、4 项前端契约测试、5 项公开契约检查与生产构建通过。前端已有 BatchTestPage useEffect warning 1 条,无错误。 - F4: 初次回归发现公开契约快照需更新;随后构建受沙箱 Google Fonts 网络限制,联网重试通过;未修改字体设计。 -- F4: 补充待回答问题的状态核查保留与原生超时清理检查;任务生命周期专项测试通过。最终全量 `make test` 再次 exit 0;假设审阅进行中。 +- F4: 补充待回答问题的状态核查保留与原生超时清理检查;任务生命周期专项测试通过。最终全量 `make test` 再次 exit 0。 - 新增迁移区间 SQL:`cd backend && .venv/bin/python -m alembic upgrade 20260907_0025:head --sql` → exit 0。旧历史迁移含数据库读取,未声称全历史离线生成通过。 - F4 数据库集成:使用本机已有 `pgvector/pgvector:pg17` 镜像创建独立临时库,`alembic upgrade head` → exit 0;真实 PostgreSQL TaskRepository + ASGI 管理 API + 原生 Pipecat Job + MockTransport 远端 → exit 0(一次远端 prompt、持久事件连续、服务重启可查询)。临时容器已删除,现有数据库未改动。 - 普通 PostgreSQL 15 镜像不含既有 vector 扩展,首次全历史迁移在旧迁移 0005 失败;切换到仓库 Compose 相同的已缓存 pgvector 镜像后通过,未修改历史迁移。 @@ -28,7 +28,8 @@ ## 假设审阅 - 第一轮:4 项未声明决策(3 semantic)与4项台账不一致。全部记录至台账,修复自动测试控制入口、启动 Action 校验、待停止任务重启和远端未结束时的新任务提交;结果保存完整文本、通知显式标注省略、列表展示范围同步改进。 -- 第二轮:待复审;审阅类型为 same-family / provisional,不等同于真实远端联调。 +- 第二轮:1项未声明 semantic 决策、0项台账不一致;已补 A-022 说明被阻挡的新任务终结失败且需重新提交。本轮仅更新声明和文档,未改代码;2轮审阅预算已用尽,最后声明由执行者核对,未进行第三轮复审。两轮原始回复归档于 SILENT_ASSUMPTION_SWEEP.json。 +- 审阅结论为 gaps,same-family / provisional,不声称模型审阅无遗漏。F0–F4 的确定性验收均已通过;远端真实编码联调与浏览器交互验收仍延后。 ## 行为约定(全部 semantic 决策) - **A-001 — 范围**:只允许提示词 Pipeline 绑定任务工具;不开放 Workflow、Realtime、启动 Action(Source: user)。 @@ -48,11 +49,13 @@ - **A-019 — 超时定义**:时限针对每次本地观察Job(包含排队);重启/重新观察重新计时,超时与用户停止都进入远端abort核查,确认停止后才显示cancelled,不作为累计任务寿命上限(Source: sweep)。 - **A-020 — 自动测试控制函数**:测试运行器中提交、查询、取消、回复全部拒绝,不访问真实任务服务;修复首轮审阅发现的仅提交有防护问题(Source: sweep)。 +- **A-022 — 远端未结束时的新任务**:已接受的本地排队任务若发现其他未结束远端句柄,会以failed终结并明确说明未向远端提交;不会等旧任务解决后自动恢复,需用户重新提交(Source: sweep)。 + ## 接口约定与验证范围 - **A-003 — 配置入口**:新增 task 工具类型,复用 Tool CRUD/绑定;每个助手最多一个(Source: default)。 - **A-004 — 任务作用域**:平台生成 task_id,记录来源 conversation/assistant;管理接口沿用现有管理员鉴权(Source: default)。 - **A-009 — 远端配置**:地址/工作目录/Basic鉴权由管理员工具配置,任务冻结连接信息;LLM不能改地址和目录(Source: default)。 - **A-014 — 任务API字段**:与现有API一致使用camelCase;执行器内部保持Python snake_case(Source: default)。 - **A-021 — 任务列表范围**:管理API最多100项,优先未结束任务;网页展示全部返回项,无分页,更早记录可凭task_id查询/控制(Source: sweep)。 -- ASK=never;生产链路没有固定结果占位实现,模拟执行器仅在明确标注的测试中注入。 +- ASK=never;共22项决定(2 user、15 default、5 sweep);生产链路没有固定结果占位实现,模拟执行器仅在明确标注的测试中注入。 - 未进行浏览器交互验收或真实模型/远端编码验收;前端通过类型检查、lint、契约检查和生产构建。 diff --git a/implement-stage/SILENT_ASSUMPTION_SWEEP.json b/implement-stage/SILENT_ASSUMPTION_SWEEP.json index 454b31b..9867063 100644 --- a/implement-stage/SILENT_ASSUMPTION_SWEEP.json +++ b/implement-stage/SILENT_ASSUMPTION_SWEEP.json @@ -1,6 +1,7 @@ { "review_independence": "same-family", "acceptance_status": "provisional", +"round_budget": 2, "rounds": [ { "undeclared": [ @@ -61,6 +62,19 @@ ], "semantic_undeclared": 3, "verdict": "gaps" +}, +{ + "undeclared": [ + { + "site": "backend/services/background_tasks/service.py:110-114; backend/services/background_tasks/records.py:75-77", + "decision": "When another unresolved remote handle blocks submission, an already accepted queued task becomes terminally failed. It does not remain queued or resume after the earlier task is resolved.", + "why_it_matters": "A-015 declares that new remote submissions are blocked, but does not declare this permanent rejection policy. Consequently, failed can mean the task was never attempted, and resolving the blocking task does not revive it. The added test_unconfirmed_remote_stop_blocks_the_next_submission explicitly confirms failed with no remote handle.", + "class": "semantic" + } + ], + "stale_rows": [], + "semantic_undeclared": 1, + "verdict": "gaps" } ] }