docs(test): 记录受控投影项目绑定的回归

短测、vet 与架构边界已通过。dev 浏览器链路尚未重载本提交,报告记为未运行。
This commit is contained in:
weichen
2026-09-28 12:35:44 +00:00
parent f8730791b9
commit 88e0311a1f
2 changed files with 182 additions and 0 deletions
@@ -0,0 +1,79 @@
---
title: "修复调研报告受控投影断链"
task_id: controlled-projection-project-binding-2026-09-28
status: in_progress
created: 2026-09-28
updated: 2026-09-28
owner: Cursor
task_type: fix
policy_revision: "AGENTS.md + agent-worktree-workflow @ 2026-09-21"
branch: fix/controlled-projection-project-binding-2026-09-28
worktree: .worktrees/controlled-projection-project-binding-2026-09-28
base_dev_sha: "5d762fb2061113285ee21219471baaf11cb2d770"
write_scope:
- internal/server
- internal/coordinator
- internal/bizdev
- .doc/ops/CURRENT.md
- .doc/ops/short-term/2026-09-28-controlled-projection-project-binding.md
- .doc/test-reports/2026-09-28-controlled-projection-project-binding-test-report.md
mutex: controlled-projection-binding
review_state: pending
integration_state: branch_only
deployment: not_loaded
cleanup: pending
remote_sync: not_requested
---
# 修复调研报告受控投影断链
## 用户目标与授权
用户在项目会话里让助手编制调研报告。助手回复已生成并保存(含耗时与基准假设),刷新文档页仍是模板骨架。授权范围是修复受控投影断链:回填项目绑定、会话可追溯、无绑定时失败关闭、回复与账本状态一致。不改前端骨架回退,不删除工作区,不晋升环境,不 push。
## 检索
- 问题台账未另开新条;本任务记录根因与修复。catalog overlap 探测为 none。登记时未带 mutex/intent,避免与持有全仓范围 `.` 的夜间推进任务发生 same_scope 拒绝。
- 经验闭环:本轮采纳「回复口径必须跟受控账本,而不是跟小队成功」。
## 根因
聊天入口只 `SetProjectID` 做访问校验,`UserCtx.Project.ID` 一直为空。协调器 `handleTriggerTask` 用后者解析 projectID,得到 0。`canonicalDocID` 因此返回空串,bizdev 整段跳过 docgov/docrevision 投影。`output.md` 只落在隔离工作区,回复仍写「正文已保存」。
证据工作区:`research_1790576535990100562`(project_id=0、session_id 空、completed)。`doc_proj6024_bd_research` 在 07:06 带绑定重跑前只有模板快照。随后 `research_1790584772615062606`(失败)和 `research_1790585141260333084`(completed)仍是 project_id=0。
## 修复
提交 `f8730791`:
- `bindSessionProjectContext`:`enrichSessionWorkflowStage` 在项目已授权且上下文项目 ID 为空时回填。已有绑定不覆盖。
- `handleTriggerTask` / `handleTriggerAdhocTask` 把 `ChatSessionID` 写入 `TaskRunRequest.SessionID`。
- 受控目录任务(目录键与 `rd_*`)在 `ProjectID <= 0` 时返回「会话未绑定项目,受控交付物无法入账」,不建孤儿工作区。未知自由任务不在此列。
- 完成回复只在 `DocRecord` 有文档 ID 时称已写入受控文档;否则说明交付物在工作区、尚未入账。`CompletionSummary` 对受控键同样区分。
## 数据
`doc_proj6024_bd_research` 已由 07:06 带绑定重跑入账,不做数据修复。
孤儿工作区只登记、不删除:
| 路径 | cleanup | 原因 |
|---|---|---|
| `data/dev/workspaces/bizdev/research_1790576535990100562` | pending | project_id=0 的已完成调研,正文未入账 |
| `data/dev/workspaces/bizdev/research_1790585141260333084` | pending | 修复前再次以 project_id=0 完成 |
cleanup_owner:本任务。复查触发:合入 local dev 并确认新会话不再产生 project_id=0 的受控工作区之后,由独立维护者决定是否归档。
## 验证
见 [测试报告](../../test-reports/2026-09-28-controlled-projection-project-binding-test-report.md)。
## 五态
| 字段 | 值 |
|---|---|
| review_state | pending |
| integration_state | branch_only |
| deployment | not_loaded(运行中的 dev 二进制早于本提交) |
| cleanup | pending |
| remote_sync | not_requested |
@@ -0,0 +1,103 @@
# 调研报告受控投影项目绑定 测试报告
## 一、 测试背景 (Background)
项目会话里触发调研报告后,助手称正文已保存,刷新文档页仍显示模板骨架。根因是会话授权项目 ID 没有回填到协调器读取的 `UserCtx.Project.ID`,受控投影被跳过。任务记录见 [短文](../ops/short-term/2026-09-28-controlled-projection-project-binding.md)。
## 二、 测试目标 (Test Objectives)
- 已授权会话在派发前把项目 ID 写入协调器上下文,且不覆盖已有绑定。
- 协调器触发任务时 `TaskRunRequest` 带上项目 ID 与 `SessionID`。
- 受控任务键在 `ProjectID <= 0` 时失败关闭,不建工作区。
- 完成回复在没有受控账本记录时不称「正文已保存」。
- 既有阶段编排、异步 run 与流式任务在带上项目 ID 后仍能完成。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:Linux。工作树:`.worktrees/controlled-projection-project-binding-2026-09-28`。
- 基线 `5d762fb2061113285ee21219471baaf11cb2d770`。被测提交 `f8730791b9a0a9d4ac67586f622acb6afaf43f10`。
- 层级:Go 接口短测、`go vet ./...`、架构边界 `arch-check --mode block`。
- 产品 PI 浏览器链路依赖已加载本提交的 dev 进程。本报告记录短测时,运行中的 `bin/agent-server` 仍是合入前的主目录制品。
## 四、 预期结果 (Expected Results)
- `bindSessionProjectContext` 把空项目 ID 填成会话项目;已有值保持不变;未授权项目不回填。
- 同步触发 research 时请求的 `ProjectID` 与 `SessionID` 与上下文一致。
- `intake` / `research` 在项目 ID 为 0 时返回 `ErrUnboundControlledProject`,`DocRecord` 为空。
- 无 `DocRecord` 的完成回复包含「尚未写入受控文档账本」,且不含「正文已保存」。
- `go vet ./...` 无输出;三包 `go test -short` 通过;架构边界通过。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 用例 1:项目绑定回填
- 输入:`go test -count=1 -short -timeout 180s ./internal/server/ -run TestBindSessionProjectContext`(含在用例 4 的整包短测中)。
- 实际输出:`internal/server` 整包 `ok`,20.400s。用例覆盖回填 6024、保留已有 `"9"`、`SetProjectID(0)` 时不写入。
- 判定:PASS
- 耗时:见整包短测
### 用例 2:触发请求携带项目与会话
- 输入:`go test -count=1 -short ./internal/coordinator/ -run 'TestSyncTriggerTask|TestFormatTriggerTaskReply'`
- 实际输出:`internal/coordinator` 整包 `ok`,0.015s。`TestSyncTriggerTask_EnablesAutoRepair` 断言 `ProjectID==9` 且 `SessionID==sess-research`。
- 判定:PASS
### 用例 3:无项目绑定失败关闭,回复不声称入账
- 输入:`go test -count=1 -short ./internal/bizdev/ -run 'TestExecuteTask|TestTaskRunResult_'`
- 实际输出:`internal/bizdev` 整包 `ok`,0.180s。受控键无项目时 `errors.Is` 为 `ErrUnboundControlledProject`。无账本的完成摘要包含「尚未写入受控文档账本」。未绑定项目的同步触发回复为该错误原文,状态 `StatusRejected`。
- 判定:PASS
### 用例 4:三包短测、vet、架构边界
- 输入:
```text
gofmt -w internal/server/task_run_observer_test.go
go test -count=1 -short -timeout 180s ./internal/bizdev/ ./internal/coordinator/ ./internal/server/
go vet ./...
./scripts/arch-check.sh --mode block
```
- 实际输出:
```text
ok chat-agent-system/internal/bizdev 0.180s
ok chat-agent-system/internal/coordinator 0.015s
ok chat-agent-system/internal/server 20.400s
VET:0
arch-check mode=block
ok chat-agent-system/internal/archtest 0.194s
ok chat-agent-system/internal/archtest 0.191s
arch-check block: production gate passed
ARCH:0
```
- 判定:PASS
- 耗时:三包短测约 23s;vet 与架构检查约 2s。工作目录为任务 worktree。
说明:`TestTaskRun_DisconnectDoesNotCancelWorker` 曾因 worker 用 `RunRecord.ProjectID` 覆盖请求而失败。测试记录改为 `ProjectID: 1` 后通过。这与线上异步 run 以记录中的项目 ID 为准一致。
### 用例 5:dev 真实 PI 浏览器链路
- 输入:在已加载 `f8730791` 的项目会话中对话触发调研报告,核对 `workspace.json` 的 `project_id`、`document_versions` 的 agent_squad 提交,以及刷新后的文档正文。
- 实际输出:未运行。当前 dev 的 `bin/agent-server` 早于本提交,主目录 `dev` 尚未合入该提交。
- 判定:未运行
- 风险:短测证明绑定与失败关闭,不能代替刷新后文档页看到正文。
## 六、 自动化测试套件汇总 (Test Suite Execution)
| 检查 | 结果 |
|---|---|
| `go test -short` `internal/bizdev` `internal/coordinator` `internal/server` | PASS |
| `go vet ./...` | PASS |
| `./scripts/arch-check.sh --mode block` | PASS |
| 产品 PI 浏览器 | 未运行 |
未跑全仓 `go test -short ./...`。本改动的包与架构门禁已覆盖计划中的回归范围。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
授权内的代码与短测达到任务分支可审终点。合入 local dev 并重载 `agent-server` 之后,仍须用真实 PI 在项目会话触发调研报告,确认工作区 `project_id` 非 0、账本出现 agent_squad 版本,刷新文档页不再只剩模板骨架。
孤儿工作区 `research_1790576535990100562`、`research_1790585141260333084` 保持 cleanup=pending,不删除。`doc_proj6024_bd_research` 已有带绑定重跑入账,无额外数据修复。