test(rdev): record the three real PI samples on dev

Software-plan N/A stayed closed and the proposal completed, but the planning review finished quality_failed at score 20. The poller now treats that status as terminal so it does not spin until timeout.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-19 14:33:25 +00:00
co-authored by Cursor
parent 56a8719863
commit 6bd338e273
14 changed files with 2054 additions and 4 deletions
+1 -1
View File
@@ -149,7 +149,7 @@
| holder | phase | since | scope | queue |
|--------|-------|-------|-------|-------|
| - | idle | 2026-09-19 | dev schema 53 已验收 health。`TestArchitectureBoundaries` 6 条新 import 另记,不占槽 | - |
| - | idle | 2026-09-19 | P3 真 PI 已抽样。评审 `quality_failed`(score 20),不占槽。不晋升 test/main | - |
**phase**: `idle` | `merging` | `smoke` | `e2e`
@@ -46,10 +46,10 @@ updated: 2026-09-19
| FE 缓存 | done(版本字段)。窗口缓存写入 `{schema,data}`,无 schema 的旧载荷丢弃。`window cache: 无 schema` |
| FE lucide | 关闭理由:`package-lock.json` 锁定 `lucide-react@1.42.0`,来源 `registry.npmjs.org`,带 integrity。`^1.16.0` 是合法的 1.x 范围,不是来源不明的包 |
| M7 | done(出站意图 + 同键重放)。`document_content_projections` 与账本同一事务写入;投影成功才销账。`TestDocRevision_PatchOrder_RetryProjectsWithoutSecondLedgerCommit`。账本库与正文库仍不是一个 SQL 事务,进程退出后靠未投影行重放,不靠客户端记忆 |
| FE App.tsx | 部分。登录壳不再静态引用重模块。本地缓存、登录同步、文档补水、服务端文档同步、生命周期、发送消息、块编辑、对话流/任务流重试、卡片动作、立项和成员写操作已分别抽出。工作台壳仍在 `App.tsx` |
| FE App.tsx | 部分收口。登录壳不再静态引用重模块。本地缓存、登录同步、文档补水、服务端文档同步、生命周期、发送消息、块编辑、对话流/任务流重试、卡片动作、立项和成员写操作已分别抽出。文档栏在 `DocumentPane`,聊天栏在 `ChatColumn`,`AppShell` 与工作台弹窗在 `WorkbenchView`。`App.tsx` 仍持有会话状态,不再挂 `<AppShell` |
| H1-del | 关闭理由:`allowLegacyTestPrincipal` 仍被 `AllowInMemory && ContextDbHost==""` 的 dev/test 内存测试使用。删除会把这批测试变成未登录 401。保留告警,删除另开、先改测试夹具 |
仍开放:rdev P3 三样本真 PI、U7 的 Vite/依赖重启矩阵、`App.tsx` 里的 `AppShell` 接线。文档栏已拆到 `DocumentPane`。dev schema 53。U4 n=5 为成员 1、会话 1。U1 慢网 n=20(CPU 4 倍,并阻断 Google 字体):10 Mbps 表单可见 p75 559 ms,2 Mbps p75 1279 ms,都低于拟定 1.5 s / 3 s;这是本机 CDP 抽样,不是公网 SLO。U7 仅 app 重启 5 次到 health:0.433–0.463 s,未覆盖 Vite 与整组依赖。U6 仍不加索引。H2 `TestDocGovCommentsAndAudit_NonMemberIs403_PG` 已在隔离库 PASS。`go test -short` 的 `TestArchitectureBoundaries` 仍有 6 条新 import(intent/squad/template → workflowdef),不是本轮容器改动,槽位不因此一直占着。test/main 仍是 schema 52。
仍开放:rdev P3 评审质量门禁未过(建议书已生成,`rd_sw_plan` 规划期关闭已证实,见 [P3 报告](../test-reports/2026-09-19-rdev-p3-real-pi-test-report.md));U7 的 Vite/依赖重启矩阵。工作台壳已挪到 `WorkbenchView`。dev schema 53。U4 n=5 为成员 1、会话 1。U1 慢网 n=20(CPU 4 倍,并阻断 Google 字体):10 Mbps 表单可见 p75 559 ms,2 Mbps p75 1279 ms,都低于拟定 1.5 s / 3 s;这是本机 CDP 抽样,不是公网 SLO。U7 仅 app 重启 5 次到 health:0.433–0.463 s,未覆盖 Vite 与整组依赖。U6 仍不加索引。H2 `TestDocGovCommentsAndAudit_NonMemberIs403_PG` 已在隔离库 PASS。`go test -short` 的 `TestArchitectureBoundaries` 仍有 6 条新 import(intent/squad/template → workflowdef),不是本轮容器改动。test/main 仍是 schema 52。
红线关闭(不是实现):
+1 -1
View File
@@ -57,7 +57,7 @@
| 对话数据治理(D7) | 留存/删除口径、库·备份·日志控制、敏感字段加密边界 | deferred | deferred_enhancement(违规则升 blocker) | [计划](../remediation/2026-09-16-feature-matrix-production-readiness-plan.md) Scope Boundaries;[收口 §7.1](../remediation/2026-09-16-partial-deferred-completion-plan.md);[D7 ADR 草案](../adr/2026-09-17-d7-chat-data-retention.md);[W7 盘点](../audit/2026-09-17-d7-data-inventory.md);[报告](../test-reports/2026-09-17-w7-d7-inventory-test-report.md) | **after W7**:只读盘点完成(sessions/messages/KB/日志/备份/event)。**未发现**已确认基线违规,未写 gap-matrix。口径仍 `pending-compliance-signoff`;禁止按 365/180/30 物理删除。本行不升 done | `chat` |
| 智能体小队 | 角色-任务-工作区-黑板 | done | non_blocker | [agent-squad](../system-design/agent-squad/);[test 2026-09-07](../test-reports/2026-09-07-dynamic-squad-planning-test-report.md) | 非关键步骤降级(A5/A6)属 backlog | `squad` |
| 工作流治理 | 三正式工作流、设置页/DutyMode、动作级鉴权、真实 PI 三工作流 E2E、full/none 混合长链 | done | non_blocker | [三工作流整改](../remediation/2026-09-12-three-workflows-strict-governance-remediation.md);[409/职责](../test-reports/2026-09-14-workflow-plan-409-frozen-and-optional-duties-test-report.md);[鉴权](../test-reports/2026-09-14-governance-action-level-authz-test-report.md);[PI E2E](../test-reports/2026-09-16-pi-three-workflow-e2e-test-report.md);[Wave2 full/none](../test-reports/2026-09-16-wave2-real-pi-evidence-test-report.md) | full 跨用户审批 + none 免审批不阻塞已签。纯软件自举仍独立 planned | `workflow` |
| 研发设计控制(rdev) | 医疗第 4 工作流:13×60 manifest/模板、`squad.rdev_doc.v1` kind 编排、main-completed 硬 precheck、StageKey 动态化;不含前端/真 PI/键名空间化 | partial | deferred_enhancement | [设计](../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md);[short-term](../archive/ops/2026-09-17-rdev-workflow-integration.md);[模板深度](../archive/ops/2026-09-17-rdev-template-depth.md);[S0+S1 首批报告](../test-reports/2026-09-17-rdev-template-depth-test-report.md);[S1 续批报告](../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md);[写作规范](../system-design/project-workflow/08-rdev模板写作规范.md);[backlog](../backlog/2026-09-17-rdev-phase2-backlog.md) | **P0+P1 done**。**模板深度 S0+S1 首批 + S1 续批 done**:60/60 模板已补强;真 PI 抽样 PASS(含 `rd_planning_review` + `rd_design_vv`,项目 6446)。剩余:S3 overlay 与 R2/R3 已接。P2 名称匹配、阶段折叠、批量审批已接。选中 rdev 时显示与服务端相同的 CDO 前置说明(`workflowPrerequisite.test.ts`)。P4 键名空间化已接:发布清单用 `bd_`/`pm_`/`tm_`/`sw_`,旧键仍走同一套步骤和模板,旧 doc_id 仍可查(`keyspace_test.go`)。P3 三样本真 PI 仍未做 | `workflow-def` / `rdev-templates` |
| 研发设计控制(rdev) | 医疗第 4 工作流:13×60 manifest/模板、`squad.rdev_doc.v1` kind 编排、main-completed 硬 precheck、StageKey 动态化;不含前端/真 PI/键名空间化 | partial | deferred_enhancement | [设计](../system-design/project-workflow/07-研发工作流rdev接入-设计与实施计划.md);[short-term](../archive/ops/2026-09-17-rdev-workflow-integration.md);[模板深度](../archive/ops/2026-09-17-rdev-template-depth.md);[S0+S1 首批报告](../test-reports/2026-09-17-rdev-template-depth-test-report.md);[S1 续批报告](../test-reports/2026-09-17-rdev-template-depth-s1-continued-test-report.md);[写作规范](../system-design/project-workflow/08-rdev模板写作规范.md);[backlog](../backlog/2026-09-17-rdev-phase2-backlog.md) | **P0+P1 done**。**模板深度 S0+S1 首批 + S1 续批 done**:60/60 模板已补强;真 PI 抽样 PASS(含 `rd_planning_review` + `rd_design_vv`,项目 6446)。剩余:S3 overlay 与 R2/R3 已接。P2 名称匹配、阶段折叠、批量审批已接。选中 rdev 时显示与服务端相同的 CDO 前置说明(`workflowPrerequisite.test.ts`)。P4 键名空间化已接:发布清单用 `bd_`/`pm_`/`tm_`/`sw_`,旧键仍走同一套步骤和模板,旧 doc_id 仍可查(`keyspace_test.go`)。P3 三样本已在 dev 真 PI 上跑过(项目 6533):`rd_sw_plan` 规划期关闭;`rd_proposal` completed 但未对齐模板标题;`rd_planning_review` 有规定章节但质量门禁 score 20,FAIL。见 [P3 报告](../test-reports/2026-09-19-rdev-p3-real-pi-test-report.md)。nightly 未扩成四工作流。 | `workflow-def` / `rdev-templates` |
| 纯软件项目自举 | 软件项目创建、Bootstrap、Delivery、受控工程交接 | partial | deferred_enhancement(明确不挡首发) | [设计](../system-design/2026-09-14-software-project-bootstrap-workflow.md);[ADR](../adr/2026-09-16-software-project-bootstrap-keys.md);[L1 报告](../test-reports/2026-09-16-software-project-bootstrap-test-report.md);[W5a](../test-reports/2026-09-17-w5a-software-bootstrap-ui-pi-test-report.md) | **before**:L1 + UI 仍克隆医疗模板。**after W5a**:catalog 驱动创建、软件不挂医疗 key、docs_only 真 PI 建议 delivery 且不自动激活。**SWBOOT-10 仍 stub**(W5b);本行不升 done | `workflow-design` |
| IAM / 鉴权 | 项目级 API 鉴权 + RBAC;会话/阶段授权 | done | 加固 | [v3 full inventory](../audit/authorization-matrix-v3-full.md);[session 中断](../test-reports/2026-09-16-iam-route-inventory-test-report.md);[fail-closed](../test-reports/2026-09-16-wave1-iam-fail-closed-test-report.md);[410 策略](../audit/2026-09-16-bug11-410-retire-decision.md);[R13](../audit/2026-09-16-r13-data-safety-checklist.md) | 全路由 inventory + session 中断负例 + 410 冻结 + R13 基线已签 | `authz` |
| 文档治理 | 法定文档生命周期 + 租约 + 受控正文读取 | done | non_blocker | [docgov](../test-reports/2026-09-08-docgov-lifecycle-and-claiming-framework-test-report.md);[正文 UI](../test-reports/2026-09-14-controlled-content-ui-acceptance.md);[canonical hash](../remediation/2026-09-14-controlled-content-canonical-hash-remediation.md) | 项目 143 只读;不终止 | `docgov` |
@@ -0,0 +1,75 @@
# 研发工作流 P3 三样本真 PI 测试报告
## 一、 测试背景 (Background)
设计计划 P3 要求在真实产品 PI Agent 与 MiniMax 上抽三份样本:`rd_proposal`(document)、`rd_planning_review`(review_minutes),以及 `rd_sw_plan` 在激活规划期关闭(N/A)。此前只有 `rd_planning_review` 与 `rd_design_vv` 的抽样,没有这组三样本。
## 二、 测试目标 (Test Objectives)
- 主流程用 stub 跑完并批准后,才能激活 rdev。
- `rd_proposal`、`rd_planning_review` 必须走 `backend=pi-agent`,不能用 stub 充当验收。
- `rd_sw_plan` 在规划里保持关闭。
- 记录真实状态、字数、是否仍含模板占位句,以及评审质量门禁结果。
## 三、 测试方案与环境 (Test Plan & Environment)
- OS:linux。分支:`fix/audit-remainder-closeout`。
- 入口:dev `http://127.0.0.1:8080`,容器 `shuimu-agent-app-dev`、`shuimu-pi-agent-dev`(MiniMax-M2.7-highspeed)。
- 项目 `6533`。主流程只启用 `bd_intake`(旧键 `intake` 已不再出现在默认规划里),stub 生成后跨用户审批准,阶段推进到 `completed`,再保存并激活 rdev。
- rdev 只启用 `rd_proposal` 与 `rd_planning_review`。脚本:`.doc/test-reports/assets/2026-09-19-rdev-p3-real-pi/run_p3_real_pi.py`。
- 未改 nightly「PI 三工作流」门禁,也未把 rdev 加进 `.github/workflows/nightly-real-pi.yml`。PR CI 仍不跑真 PI。
## 四、 预期结果 (Expected Results)
- 激活回执里 `rd_sw_plan.enabled=false`,两个抽样任务为 true。
- `rd_proposal` 终态为 `completed` 或 `pending_author_confirmation`,正文不含「按本阶段专业结构写」。
- `rd_planning_review` 同样由真 PI 写出,并含「评审范围与对象 / 问题与决议 / 评审结论」。质量门禁要求「问题与决议」表的每一数据行都有问题、决议、责任人、期限。
- 建议书批准后才能离开 `RD01_planning`。未批准时下一阶段任务应被拒绝。
## 五、 实际测试结果与判定 (Actual Results & Evaluation)
### 5.1 `rd_sw_plan` 规划期关闭
- **测试输入**:rdev 规划只保留 `rd_proposal`、`rd_planning_review`。
- **实际输出**:`[13:57:41] plan flags proposal=True review=True sw_plan=False`,随后 `activate rdev http=200`。
- **评价判定**:PASS。不适用语义是规划期关闭,不是再生成一份不适用页。
- **性能与耗时**:激活本身小于 1 秒。
### 5.2 `rd_proposal`(document)
- **测试输入**:项目 6533,`backend=pi-agent`,材料为无创神经电刺激器立项简报。
- **实际输出**:`[14:04:51] done rd_proposal status=completed elapsed=430s`,`proposal chars=11550 placeholder=False`。终稿 [rd_proposal-final.md](./assets/2026-09-19-rdev-p3-real-pi/rd_proposal-final.md)。章节是模型自拟的「产品定义与范围 / 风险清单」等,不是模板里的「项目背景与立项依据」「产品定义与范围」「主要风险与对策概览」。
- **评价判定**:生成 PASS(真 PI、已完成、无占位句)。模板标题对齐 FAIL,不把这份终稿写成模板符合。
- **性能与耗时**:430 秒。
### 5.3 未批准时不能进入评审阶段
- **测试输入**:建议书仍是 `drafting` 时推进 `RD01_planning`。
- **实际输出**:`advance RD01_planning http=409`,正文为 `STAGE_GATE_NOT_READY`。接着启动 `rd_planning_review` 得到 `403 DOC_TASK_NOT_IN_ACTIVE_STAGE`。
- **评价判定**:PASS(负例符合阶段门禁)。随后对 `doc_proj6533_rd_proposal` 认领、送审、审核、批准均为 http 200,再推进 `RD01_planning` 为 200。
- **性能与耗时**:审批链约 5 秒。
### 5.4 `rd_planning_review`(review_minutes)
- **测试输入**:阶段已到 `RD02_planning_review` 后,`backend=pi-agent`。
- **实际输出**:约 580 秒后运行状态变为 `quality_failed`。终稿 13225 字,含「## 评审范围与对象」「## 问题与决议」「## 评审结论」,不含占位句。工作区 `manifest.json` 的质量报告:`passed=false`,`score=20`,四次「问题行缺少问题、决议、责任人或期限」。主表六列是齐的;同级标题下还有一张「法规/标准」表,那些行没有责任人与期限,被算进问题行。修复轮 `repair_1`、`repair_2` 之后仍是这个结果。终稿 [rd_planning_review-final.md](./assets/2026-09-19-rdev-p3-real-pi/rd_planning_review-final.md)。
- **评价判定**:真 PI 抽样已发生,质量门禁 FAIL。不能写成评审样本通过。
- **性能与耗时**:从 `14:11:29` 启动到轮询见到 `quality_failed` 为 580 秒。
## 六、 自动化测试套件汇总 (Test Suite Execution)
本报告的验收数据来自上述真 PI 控制台,不是 `go test` 的 stub。相关结构测试:
```text
cd web && npx tsx --test src/components/layout/WorkbenchView.test.ts src/components/chat/ChatColumn.test.ts src/components/doc/DocumentPane.test.ts
# 3 pass
```
未把 `go test -short ./...` 的既有 `TestArchitectureBoundaries` 失败算进这次 P3 判定。nightly 真 PI 工作流没有修改。
## 七、 测试结论与后续优化建议 (Conclusion & Next Steps)
- 三样本都在 dev 真 PI 上跑过:软件计划 N/A 关闭 PASS;建议书生成完成但未对齐模板标题;评审记录写出了规定章节,质量门禁 20 分,FAIL。
- 因此 P3 还不能标成干净通过,也不能据此晋升 test/main。
- 轮询原先不把 `quality_failed` 当终态,会空转到超时。脚本已把 `quality_failed` 与 `finalizing_failed` 视为结束。
- 红线未动:不写真实软件仓、不合入 FAV、不物理删除 D7。
@@ -0,0 +1,100 @@
{
"project_id": 6533,
"lifecycle_status": "active",
"active_workflow_key": "main",
"instance": {
"id": 360,
"project_id": 6533,
"workflow_version_id": 101,
"instance_no": 1,
"status": "active",
"config_revision": 1,
"plan_hash": "20b4de1efe40968e5116c66e41636da35345ebb117e764771a2456f57e10cd3e",
"config_snapshot": {
"workflow_definition_key": "main",
"workflow_version": 3,
"workflow_version_id": 101,
"stages": [
{
"stage_key": "V0.1_triage",
"stage_name": "V0.1 需求摸底",
"enabled": true,
"doc_tasks": [
{
"task_key": "bd_intake",
"task_title": "用户初始需求收集表",
"enabled": true,
"approval_configurable": true,
"duties": {
"author_user_id": 9,
"reviewer_user_id": 11,
"approver_user_id": 12
}
}
]
},
{
"stage_key": "V0.5_feasibility",
"stage_name": "V0.5 方案与可行性",
"enabled": true,
"doc_tasks": [
{
"task_key": "bd_feasibility_dev",
"task_title": "设计开发可行性评估报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "bd_feasibility_reg",
"task_title": "注册路径可行性评估报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "bd_prelim_design",
"task_title": "系统初步设计方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "bd_research",
"task_title": "调研报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "bd_user_requirements",
"task_title": "用户需求表",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "V1.0_quoting",
"stage_name": "V1.0 商务报价",
"enabled": true,
"doc_tasks": [
{
"task_key": "bd_cdo_quote",
"task_title": "CDO 报价单",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
}
]
},
"activated_by": 9,
"activated_at": "2026-09-19T13:57:29.750885Z",
"created_by": 9,
"created_at": "2026-09-19T13:57:29.745027Z",
"updated_at": "2026-09-19T13:57:29.750885Z"
}
}
@@ -0,0 +1,545 @@
{
"project_id": 6533,
"lifecycle_status": "active",
"active_workflow_key": "rdev",
"instance": {
"id": 361,
"project_id": 6533,
"workflow_version_id": 100,
"instance_no": 2,
"status": "active",
"config_revision": 2,
"plan_hash": "c478cd7459ff309921c6daa04f33acd84fde364d0a8b5a6c5e19f52d9f009533",
"config_snapshot": {
"workflow_definition_key": "rdev",
"workflow_version": 3,
"workflow_version_id": 100,
"stages": [
{
"stage_key": "RD01_planning",
"stage_name": "01 设计和开发策划",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_design_plan",
"task_title": "设计开发计划任务书",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_proposal",
"task_title": "项目建议书",
"enabled": true,
"approval_configurable": true,
"duties": {
"author_user_id": 9,
"reviewer_user_id": 11,
"approver_user_id": 12
}
}
]
},
{
"stage_key": "RD02_planning_review",
"stage_name": "02 策划评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_planning_review",
"task_title": "设计和开发策划评审记录",
"enabled": true,
"approval_configurable": true,
"duties": {
"author_user_id": 9,
"reviewer_user_id": 11,
"approver_user_id": 12
}
}
]
},
{
"stage_key": "RD03_design_input",
"stage_name": "03 设计输入",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_adverse_events",
"task_title": "同类产品不良事件信息",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_design_input_list",
"task_title": "设计输入清单",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_design_input_spec",
"task_title": "设计输入规格书",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_hazard_analysis",
"task_title": "安全性问题清单及可能危险分析表",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_regs_stds",
"task_title": "法规和标准清单",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_risk_plan",
"task_title": "风险管理计划",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_config",
"task_title": "软件配置及维护计划",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_plan",
"task_title": "软件开发计划",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_reqs",
"task_title": "软件需求规格书",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_system_design",
"task_title": "系统设计方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_system_reqs",
"task_title": "系统需求规格书",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_user_needs",
"task_title": "用户需求规格书",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD04_requirements_review",
"stage_name": "04 需求评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_req_review",
"task_title": "需求评审记录",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD05_input_phase_review",
"stage_name": "05 输入阶段评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_input_phase_review",
"task_title": "设计开发评审记录(阶段3和4)",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD06_design_output",
"stage_name": "06 设计输出",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_design_output_list",
"task_title": "设计输出清单",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_drawings_3d",
"task_title": "2D图纸和3D模型",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_ee_bom",
"task_title": "电子电气BOM",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_electrical_sys",
"task_title": "系统电气设计图",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_fqc",
"task_title": "成品检验规范",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_ifu",
"task_title": "产品使用说明书",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_incoming_iqc",
"task_title": "原材料进货检验规范",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_ipqc",
"task_title": "生产过程检验规范",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_packaging",
"task_title": "包装图纸和设计要求",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_pcba",
"task_title": "PCBA原理图及Layout",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_process_flow",
"task_title": "工艺流程图及作业指导",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_product_bom",
"task_title": "产品BOM",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_purchase_spec",
"task_title": "采购技术规范",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_risk_report",
"task_title": "风险管理报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_arch",
"task_title": "软件概要设计方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_ui",
"task_title": "软件UI设计文档",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_tech_req",
"task_title": "产品技术要求",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD07_output_review",
"stage_name": "07 输出评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_output_review",
"task_title": "设计开发评审记录(阶段6)",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD08_verification",
"stage_name": "08 验证",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_biocompatibility",
"task_title": "生物学检测方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_cleaning",
"task_title": "清洁消毒验证方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_design_vv",
"task_title": "设计验证方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_emc_safety",
"task_title": "EMC及安规摸底报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_lifetime",
"task_title": "产品使用期限研究方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_prototype_photos",
"task_title": "样机照片",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_qualified_suppliers",
"task_title": "合格供方名录",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_risk_report_v",
"task_title": "风险管理报告(验证阶段)",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_shelf_life",
"task_title": "货架寿命方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_release",
"task_title": "软件发布清单",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_sys_test",
"task_title": "软件系统测试报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_unit_test",
"task_title": "软件单元测试报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD09_verification_review",
"stage_name": "09 验证评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_verification_review",
"task_title": "设计开发评审记录(验证阶段)",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD10_transfer",
"stage_name": "10 转换",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_dmr_list",
"task_title": "DMR文件清单",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_pack_ship",
"task_title": "包装运输方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_risk_report_t",
"task_title": "风险管理报告(转换阶段)",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD11_transfer_review",
"stage_name": "11 转换评审",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_transfer_review",
"task_title": "设计开发评审记录(转换阶段)",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD12_validation",
"stage_name": "12 确认",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_animal_study",
"task_title": "动物试验方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_clinical",
"task_title": "临床试验报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_risk_report_val",
"task_title": "风险管理报告(确认阶段)",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_sw_quality",
"task_title": "软件质量测试报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_use_error",
"task_title": "使用错误评估报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_user_test",
"task_title": "用户测试报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
},
{
"task_key": "rd_validation_plan",
"task_title": "设计确认方案",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
},
{
"stage_key": "RD13_validation_report",
"stage_name": "13 设计确认报告",
"enabled": true,
"doc_tasks": [
{
"task_key": "rd_design_validation_report",
"task_title": "设计确认报告",
"enabled": false,
"approval_configurable": true,
"duties": {}
}
]
}
]
},
"activated_by": 9,
"activated_at": "2026-09-19T13:57:41.608497Z",
"created_by": 9,
"created_at": "2026-09-19T13:57:41.598543Z",
"updated_at": "2026-09-19T13:57:41.608497Z"
}
}
@@ -0,0 +1,27 @@
{
"run_id": "run_1789826249755340789",
"final": {
"RunID": "run_1789826249755340789",
"SessionID": "sess-s1c-p6533-bd_intake-1789826249",
"ProjectID": 6533,
"UserID": 9,
"ClientTurnID": "s1c-bd_intake-1789826249",
"IdempotencyKey": "turn:sess-s1c-p6533-bd_intake-1789826249:s1c-bd_intake-1789826249",
"TaskKey": "bd_intake",
"Stage": "",
"WorkflowInstanceID": 360,
"StageInstanceID": 537,
"WorkflowStageKey": "V0.1_triage",
"Status": "completed",
"WorkspaceID": "/app/data/workspaces/bizdev/bd_intake_1789826249768280685",
"AssistantMsgID": 4058,
"WorkerID": "",
"LeaseExpiresAt": null,
"CreatedAt": "2026-09-19T13:57:29.755424097Z",
"UpdatedAt": "2026-09-19T13:57:29.786498804Z",
"ErrorMessage": "",
"Attempt": 1,
"resumable": false
},
"elapsed_s": 10
}
@@ -0,0 +1,27 @@
{
"run_id": "run_1789826261615091279",
"final": {
"RunID": "run_1789826261615091279",
"SessionID": "sess-s1c-p6533-rd_proposal-1789826261",
"ProjectID": 6533,
"UserID": 9,
"ClientTurnID": "s1c-rd_proposal-1789826261",
"IdempotencyKey": "turn:sess-s1c-p6533-rd_proposal-1789826261:s1c-rd_proposal-1789826261",
"TaskKey": "rd_proposal",
"Stage": "",
"WorkflowInstanceID": 361,
"StageInstanceID": 540,
"WorkflowStageKey": "RD01_planning",
"Status": "completed",
"WorkspaceID": "/app/data/workspaces/bizdev/rd_proposal_1789826261632224940",
"AssistantMsgID": 4060,
"WorkerID": "",
"LeaseExpiresAt": null,
"CreatedAt": "2026-09-19T13:57:41.615191526Z",
"UpdatedAt": "2026-09-19T14:04:49.692613691Z",
"ErrorMessage": "",
"Attempt": 1,
"resumable": false
},
"elapsed_s": 430
}
@@ -0,0 +1,20 @@
{
"id": 6533,
"code": "rdev-p3-2026-6ea4c830",
"name": "rdev-p3-20260919-135729",
"customer_name": "",
"device_type": "",
"intended_use": "",
"target_market": "",
"product_domain": "medical_device",
"current_stage": "V0.1_triage",
"environment": "dev",
"status": "active",
"creator_user_id": 9,
"lifecycle_status": "planning",
"active_workflow_key": "",
"workflow_selection_version": 1,
"workflow_plan_revision": 0,
"created_at": "2026-09-19T13:57:29.737376982Z",
"updated_at": "2026-09-19T13:57:29.737376982Z"
}
@@ -0,0 +1,327 @@
# 设计和开发策划评审记录
- **项目**:rdev-p3-20260919-141124
- **生成时间**:2026-09-19 14:11:29
- **快照**:ws_rd_planning_review_1789827089172453306
- **文件编号**:RD-PLAN-REV
- **记录归属**:DHF
- **版本**:A
- **阶段**:02 策划评审
---
## 结论
本阶段策划评审**不具备以现有材料召开完整评审的条件**。现有输入材料仅包含一份关于项目建议书的简报(含 4 行文字描述),而 ISO 13485 §7.3.1 要求的策划输入——项目建议书正文、用户初始需求收集表全文、设计控制计划——均未提供正文内容,无法对策划充分性作出有依据的评审。已识别 6 项问题,其中 4 项为阻塞性缺口(项目建议书正文不可见、用户初始需求收集表正文不可见、设计控制计划未提供、适应症边界待确认),2 项为中低优先级风险(电气安全摸底待排期、软件类文件「规划期关闭」含义不明确)。本次评审结论为**有条件通过**:补齐 6 项行动项后方可进入 03 设计输入阶段。
---
## 适用性
- **适用 / 不适用**:适用
- **不适用理由**:(本文件为 ISO 13485 §7.3「设计和和开发策划」所要求的设计历史文件(DHF)记录,适用于二类有源医疗器械(神经刺激)项目 rdev-p3-20260919-141124,目标市场为中国 NMPA,故本栏不适用)
### 适用性解读
本文件作为设计和开发策划评审记录,是 ISO 13485:2016 §7.3 框架下的受控 DHF 文档。本项目的核心属性已由 project.md 锁定〔context/project.md〕:
| 属性 | 内容 |
|------|------|
| 产品类型 | 二类有源医疗器械(神经刺激) |
| 预期用途 | 无创神经电刺激辅助改善目标症状 |
| 目标市场 | 中国 NMPA |
二类有源医疗器械在中国 NMPA 注册路径下,须满足《医疗器械监督管理条例》及配套规章要求。ISO 13485 §7.3「设计和开发策划」要求组织应对设计和开发策划予以建立并保持,策划输出应包含适用的法规要求、风险管理原则、设计开发阶段划分及评审节点安排。〔ISO 13485:2016 §7.3.1〕
---
## 评审范围与对象
### 评审目的
依据 ISO 13485:2016 §7.3.1,验证设计和开发策划是否已建立并保持设计开发过程的策划输出,确认策划阶段输入的充分性与合规性,并就是否具备进入设计输入(§7.3.2)的条件给出评审结论。
### 评审覆盖范围
本次评审覆盖以下评审对象:
| 评审对象 | 文件编号 | 版本 | 批准状态 | 与本评审关系 | 材料提供情况 |
|----------|----------|------|----------|--------------|--------------|
| 项目建议书 | 待确认 | 待确认 | 操作记录显示「完成」,正文不可见 | 策划评审核心输入 | **正文缺失** |
| 用户初始需求收集表 | 待确认 | 待确认 | 操作记录显示「完成」,正文不可见 | 策划评审核心输入;设计输入直接上游 | **正文缺失** |
| 策划评审输入简报 | — | — | 简报已提供(4 行文字) | 本次评审依据的主要文本 | 已提供 |
| 设计控制计划 | — | — | 未提供 | ISO 13485 §7.3 策划阶段要求输出 | **文件缺失** |
> **评审限制声明**:由于项目建议书与用户初始需求收集表正文不可见,本次评审无法核实策划输入的实际内容完整性。评审结论基于简报所称「已起草」「已完成」的事实性陈述,不对文档正文质量作出判断。〔materials_text/plan_brief.md〕〔materials_text/decision_decision_0.md〕〔materials_text/decision_decision_1.md〕
### 评审输入与输出文件追踪
| 文件 | 类型 | 与本评审关系 |
|------|------|--------------|
| 项目建议书 | 输入(§7.3.1 策划) | 评审对象;正文不可见 |
| 用户初始需求收集表 | 输入(§7.3.1 策划 → §7.3.2 设计输入上游) | 评审对象;正文不可见 |
| 设计控制计划 | 策划阶段应输出文件(§7.3) | 本应产出;未提供 |
| 本记录 RD-PLAN-REV | 策划阶段输出文件(§7.3 评审记录) | 本次产出 |
### 前序已批准文档引用
| 前序文档 | 版本 | 批准状态 | 与本评审关系 |
|----------|------|----------|--------------|
| context/project.md(项目全局基线) | — | 项目章程文件 | 本评审的项目前提,已锁定:二类有源医疗器械(神经刺激),目标市场中国 NMPA,预期用途无创神经电刺激辅助改善目标症状 |
| tasks/01_organizer/output.md(资料整理输出) | A | 已完成 | 本评审的直接上游输入,引用其事实清单、缺口分析与待确认清单 |
### 评审范围解读
本评审的范围限定于**策划阶段输入文件的充分性核查**,而非对项目建议书或用户初始需求收集表正文的实质评审。原因如下:
1. **材料局限性**:本次提供的 4 份材料中,仅 plan_brief.md 含有实质描述(4 行文字),其余 3 份为重复简报或无正文操作记录。〔materials_text/plan_brief.md〕〔materials_text/decision_decision_0.md〕〔materials_text/decision_decision_1.md〕
2. **文件不可见**:01_organizer 整理阶段已识别,项目建议书与用户初始需求收集表正文不可见,仅有「完成」操作记录。〔tasks/01_organizer/output.md〕
3. **ISO 13485 要求**:§7.3.1 要求策划输入包含适用的法规要求、风险管理原则。本评审无法验证这些要求是否已满足,因为相关文件正文缺失。
4. **对后续阶段的影响**:策划输入不完整将直接影响设计输入(§7.3.2)的基线建立。若设计输入无充分策划依据,可能导致设计开发过程中的返工与变更,增加注册风险与时间成本。
---
## 评审人员与职责
### 评审角色与职责矩阵
| 角色 | 姓名 | 职责 |
|------|------|------|
| REV-P-001(项目负责人) | **待确认** | 主持评审、汇总决议、协调行动项 |
| REV-P-002(质量/法规代表) | **待确认** | 验证策划输入合规性、确认设计控制计划完备性 |
| REV-P-003(研发/技术代表) | **待确认** | 确认技术可行性、评审适应症边界与电气安全风险 |
| REV-P-004(客户/用户代表) | **待确认** | 确认用户初始需求收集表是否反映真实需求 |
| REV-P-005(记录人) | **待确认** | 记录问题、决议与行动项,维护本 DHF 记录 |
> **编写纪律声明**:评审人员姓名须在实际评审召开后填写。**禁止编造人员姓名。** 上表中姓名栏已填写「待确认」为当前状态占位,不代表实际人员已确定。
### 评审人员要求解读
ISO 13485:2016 §7.3「设计和开发策划」并未强制规定评审人员的具体数量与资质要求,但结合本项目的特性(二类有源医疗器械、目标市场中国 NMPA),评审团队应涵盖以下核心能力:
| 核心能力 | 覆盖角色 | 为什么重要 |
|----------|----------|------------|
| 项目管理与策划 | REV-P-001 | 确保策划输出的完整性与时间节点可控 |
| 质量体系与合规 | REV-P-002 | 验证策划符合 ISO 13485 §7.3 要求 |
| 有源医疗器械技术 | REV-P-003 | 二类有源医疗器械须满足 GB9706.1-2020,电气安全摸底是 P2 优先级风险 |
| 用户需求定义 | REV-P-004 | 用户初始需求收集表是设计输入的直接上游,若需求定义不准确将导致设计返工 |
| DHF 记录维护 | REV-P-005 | 确保评审记录可追溯、可审计 |
---
## 问题与决议
> **质量门禁修复说明**:本节「问题与决议」表格按模板指定列名(编号 | 问题 | 决议 | 责任人 | 期限 | 关闭准则)重写,每行 6 个字段均有实质内容,占位值以评审日 2026-09-19 为基准按业务逻辑设定。所有占位值须在实际评审召开后由项目负责人确认,不得由撰写岗编造为最终决策值。
| 编号 | 问题 | 决议 | 责任人 | 期限 | 关闭准则 |
|------|------|------|--------|------|----------|
| REV-I-001 | 项目建议书正文不可见。现有材料仅有「项目建议书已起草」的简报记录,无正文内容,无法核实策划输入的充分性。 | 补齐项目建议书全文,提交本评审存档;文件编号、版本、编制人须可追溯。 | 项目负责人(或项目建议书编制人) | 2026-09-26(评审后 5 个工作日) | 项目建议书正文(含版本号、批准签字页)提交至 DHF |
| REV-I-002 | 用户初始需求收集表正文不可见。仅有「已完成」的操作记录,无正文内容,无法确认用户需求的定义基线。 | 补齐用户初始需求收集表全文,提交本评审存档;需包含完整的用户需求条目及来源。 | 需求工程师(或项目负责人) | 2026-09-26(评审后 5 个工作日) | 用户初始需求收集表正文(含版本号)提交至 DHF |
| REV-I-003 | 设计控制计划未提供。ISO 13485 §7.3 要求策划阶段建立并保持设计开发过程策划的输出,包含阶段划分、评审节点、职责权限、风险管理入口。 | 编制或调取设计控制计划(DCP),明确各设计开发阶段的划分、评审节点、职责分配及与风险管理过程的接口。 | 质量代表(QMS 负责人) | 2026-10-03(评审后 10 个工作日) | DCP 经批准版本提交至 DHF,包含设计开发阶段划分表与评审计划 |
| REV-I-004 | 适应症边界待确认。简报仅标注「适应症边界待确认」,无具体疾病定义、适用范围、禁忌症或适用人群描述;直接影响产品分类(决定二类/三类)及临床评价路径。 | 客户提供书面适应症边界说明(含目标适应症、禁忌症、适用人群),由临床/医学专家确认;输出文件纳入 DHF。 | 客户方临床/医学专家 | 2026-10-03(评审后 10 个工作日) | 适应症边界说明文件经客户/医学专家签字确认,版本受控 |
| REV-I-005 | 电气安全摸底待排期。简报仅标注「电气安全摸底待排期」,无摸底测试方案、计划时间表或资源配置;二类有源医疗器械 GB9706.1-2020 合规是注册前提。 | 在设计控制计划中增加电气安全摸底里程碑节点,明确摸底范围(GB9706.1 通用要求及适用的并列/专用标准)、时间节点和责任人。 | 研发/测试工程师 | 2026-10-03(纳入 DCP 同步完成) | 电气安全摸底计划作为 DCP 附件或独立文件,经项目负责人批准 |
| REV-I-006 | 软件类文件「规划期关闭」含义不明确。简报称「软件类文件已在规划期关闭,不进入编制」;但未说明是否确认为无软件产品,还是软件采用外包/外购方式;若产品含嵌入式控制软件,GB9706.1-2020 中软件相关条款仍须覆盖。 | 明确本产品是否含软件;若含软件,补充软件安全评估路径(自研则进入设计控制,外购/外包则需供应商审核记录);结论记入 DHF。 | 研发负责人 | 2026-09-26(评审后 5 个工作日) | 软件处置决策记录(含无软件确认或软件管理计划)经项目负责人批准 |
### 决议解读
**结论句**:6 项问题均需在进入设计输入阶段前关闭;其中 5 项(REV-I-001 至 004、006)为阻塞性缺口,须补齐核心输入文件后方可推进。
**依据**:
| 法规/标准 | 相关条款 | 本次评审要求 |
|------------|----------|--------------|
| ISO 13485:2016 | §7.3.1 策划 | 组织应对设计和开发策划予以建立并保持;策划输入应包括适用的法规要求、风险管理原则及设计开发阶段的时间安排 |
| ISO 13485:2016 | §7.3.2 设计输入 | 设计输入应保持记录;设计输入的评审应验证是否符合策划输入的要求 |
| 中国 NMPA | 《医疗器械注册与备案管理办法》 | 注册申报资料须包含产品风险分析资料、产品技术要求、临床评价资料等;适应症边界不清将影响临床评价路径判定 |
**关键风险说明**:
1. **适应症边界(REV-I-004)**:简报仅标注「适应症边界待确认」〔materials_text/plan_brief.md〕,无具体疾病定义、适用范围、禁忌症或适用人群描述。根据中国 NMPA 医疗器械分类规则,适应症边界直接决定产品分类(二类 vs. 三类)及临床评价路径,是设计和开发的高风险决策点。(分析判断,无直接条文依据)
2. **电气安全摸底(REV-I-005)**:二类有源医疗器械须满足 GB9706.1-2020《医用电气设备 第1部分:基本安全和基本性能的通用要求》。简报仅标注「电气安全摸底待排期」〔materials_text/plan_brief.md〕,无摸底范围、时间节点或资源配置。GB9706.1 型检是注册强制性要求,未排期意味着后续时间线存在重大阻塞。(分析判断,无直接条文依据)
3. **软件处置(REV-I-006)**:简报称「软件类文件已在规划期关闭,不进入编制」〔materials_text/plan_brief.md〕,但未说明是确认无软件、外包、外购或其他处置方式。若产品含嵌入式控制软件,GB9706.1-2020 中软件相关条款(并列标准 YY 9706.274)仍须覆盖。〔tasks/01_organizer/output.md〕
---
## 遗留行动项跟踪
### 行动项总表
| 行动项 ID | 内容 | 责任人 | 期限 | 状态 | 阻塞影响 |
|-----------|------|--------|------|------|----------|
| REV-A-001 | 补齐项目建议书正文,提交 DHF 存档;须含版本号、编制人、批准记录 | 项目负责人(或编制人) | 2026-09-26 | 待启动 | 阻塞设计输入(§7.3.2);无策划输入则设计输入无基线 |
| REV-A-002 | 补齐用户初始需求收集表正文,提交 DHF 存档;须含完整需求条目清单 | 需求工程师(或项目负责人) | 2026-09-26 | 待启动 | 阻塞设计输入;用户需求是设计输入的直接上游依据 |
| REV-A-003 | 编制或调取设计控制计划(DCP),经批准后提交 DHF;DCP 应包含阶段划分、评审节点、职责分配 | 质量代表(QMS 负责人) | 2026-10-03 | 待启动 | 阻塞设计开发全流程;无 DCP 则各设计阶段无章可循 |
| REV-A-004 | 客户/医学专家提供书面适应症边界说明,纳入 DHF;应由具备资质的人员签署 | 客户方临床/医学专家 | 2026-10-03 | 待启动 | 阻塞产品分类判定、临床评价路径规划、注册单元划分 |
| REV-A-005 | 在 DCP 中增加电气安全摸底里程碑计划;摸底范围须含 GB9706.1 及适用专用标准 | 研发/测试工程师 | 2026-10-03 | 待启动 | 间接阻塞;影响 GB9706.1 型检进度与注册时间线 |
| REV-A-006 | 明确软件处置决策(无软件确认或软件管理计划),纳入 DHF;决策须可追溯至项目管理层 | 研发负责人 | 2026-09-26 | 待启动 | 阻塞软件相关设计控制与 GB9706.1 软件条款覆盖判定 |
### 阻塞影响分析
| 阻塞级别 | 行动项 | 影响的下一阶段 | 说明 |
|----------|--------|----------------|------|
| **P0 阻塞** | REV-A-001、REV-A-002 | 03 设计输入 | 无策划输入则设计输入无基线,ISO 13485 §7.3.2 无法执行 |
| **P0 阻塞** | REV-A-003 | 03 及后续全部设计开发阶段 | 无 DCP 则各阶段无章可循,无评审节点设置 |
| **P0 阻塞** | REV-A-004 | 03 设计输入、注册路径规划 | 适应症边界决定产品分类与临床评价路径 |
| **P1 中阻** | REV-A-006 | 03 设计输入(若含软件)、04 设计输出 | 软件处置影响设计控制范围界定 |
| **P2 低阻** | REV-A-005 | 04/05 型检、注册 | 电气安全摸底影响型检周期与资源配置 |
### 行动项跟踪解读
**周期影响研判**(分析判断,无直接条文依据):
| 情景 | 条件 | 对设计输入阶段的影响 |
|------|------|----------------------|
| 乐观情景 | 6 项行动项在 15 工作日内全部关闭 | 设计输入阶段可正常推进 |
| 中性情景 | 4 项 P0/P1 行动项在 30 工作日内关闭 | 设计输入阶段延迟约 15 工作日 |
| 悲观情景 | 4 项 P0/P1 行动项超过 30 工作日未关闭 | 整体项目注册时间线将受到实质影响 |
**建议**:项目负责人应在评审结论传达后 5 个工作日内启动 REV-A-001 至 REV-A-006 的责任人分配与时间节点确认,避免行动项无限期悬置。
---
## 评审结论
### 评审总体结论
| 结论项 | 内容 |
|--------|------|
| **总体结论** | **有条件通过** |
| **判定依据** | 简报显示项目建议书「已起草」且用户初始需求收集表「已完成」〔materials_text/plan_brief.md〕,表明策划工作已有初步成果,具备继续推进的基础;但核心输入文件正文不可见,ISO 13485 §7.3.1 要求的策划输入完整性无法核实 |
| **条件** | REV-A-001 至 REV-A-006 共 6 项行动项须在进入 03 设计输入阶段前全部关闭 |
| **条件验证方式** | 行动项关闭时须提交可追溯的文件证据(版本受控的正文、签字页、决策记录),由质量代表核实后更新本 DHF |
### 进入下一阶段前提
| 前提编号 | 前提描述 | 验证方式 | 当前状态 |
|----------|----------|----------|----------|
| 前提-01 | 项目建议书正文(版本受控)提交至 DHF | 文件存档记录核对 | **未满足** |
| 前提-02 | 用户初始需求收集表正文(版本受控)提交至 DHF | 文件存档记录核对 | **未满足** |
| 前提-03 | 设计控制计划(DCP)经批准后提交至 DHF | 批准签字页核对 | **未满足** |
| 前提-04 | 适应症边界书面说明经客户/医学专家确认,纳入 DHF | 签字确认文件核对 | **未满足** |
| 前提-05 | 软件处置决策记录(无软件确认或软件管理计划)纳入 DHF | 决策记录核对 | **未满足** |
| 前提-06 | 电气安全摸底里程碑纳入 DCP | DCP 附件核对 | **待纳入** |
### 评审结论解读
**为什么是「有条件通过」而非「不通过」?**
| 评审结论选项 | 适用条件 | 本项目是否符合 | 说明 |
|--------------|----------|----------------|------|
| 通过 | 所有策划输入齐全且充分,ISO 13485 §7.3.1 要求完全满足 | 否 | 项目建议书、用户初始需求收集表正文不可见 |
| **有条件通过** | 策划工作已有初步成果,但尚需补充关键材料 | **是** | 简报证实项目建议书已有起草动作,用户初始需求收集表已有交付动作 |
| 不通过 | 策划工作严重缺失,或存在根本性合规问题 | 否 | 简报显示策划工作已在推进中 |
ISO 13485 并不要求策划阶段一次性输出完整文件,而是要求「建立并保持策划输出」。分阶段补齐是可接受的方式。因此,结论为有条件通过——在行动项关闭后即可进入设计输入阶段。
**否决条件**:若 REV-A-001(项目建议书正文)、REV-A-002(用户初始需求收集表正文)、REV-A-003(设计控制计划)在 30 工作日内仍无法关闭,项目管理层须重新评估本阶段的策划充分性,并决定是否需要重新召开策划评审。
**失效条件**:若在任何行动项关闭后发现正文内容与简报描述严重不符(如项目建议书正文实质上未完成),本评审结论的有效性需重新评估。
---
## 追溯
| 本文件 ID | 上游(输入/需求) | 下游(输出/验证/确认) |
|----------|-------------------|------------------------|
| RD-PLAN-REV | context/project.md(项目全局基线)〔版本/日期未锁定〕 | 03 设计输入阶段策划输入 |
| | materials_text/plan_brief.md(策划评审输入简报)〔版本未提供〕 | 设计控制计划(DCP,待编制) |
| | materials_text/decision_decision_0.md(操作记录:项目建议书完成)〔无正文内容〕 | 适应症边界说明文件(待编制) |
| | materials_text/decision_decision_1.md(操作记录:用户初始需求收集表完成)〔无正文内容〕 | 软件处置决策记录(待编制) |
| | tasks/01_organizer/output.md(资料整理输出) | 电气安全摸底计划(待纳入 DCP) |
### 追溯链说明
本文件(RD-PLAN-REV)向上追溯至项目全局基线(project.md)和策划阶段输入材料,向下输出至设计开发各阶段的策划输入文件与决策记录。ISO 13485 §7.3 要求设计和开发策划应「确定对设计和开发输出进行评审和验证的阶段」,本记录通过行动项追踪表(REV-A-001 至 006)建立与下游设计输入阶段(§7.3.2)的追溯关联。
---
## 已有材料摘要
### 原始输入材料(按材料清单顺序)
| 编号 | 材料文件名 | 内容摘要 | 关键信息 | 来源标注 |
|------|------------|----------|----------|----------|
| M-01 | plan_brief.md | 策划评审输入简报(4 行) | 项目建议书已起草;关键风险:适应症边界待确认、电气安全摸底待排期;软件类文件已在规划期关闭 | 〔materials_text/plan_brief.md〕 |
| M-02 | upload_material_plan_brief.md.md | 与 plan_brief.md 内容完全相同的重复文件 | 同上 | 〔materials_text/upload_material_plan_brief.md.md〕 |
| M-03 | decision_decision_0.md | 操作记录(operation log) | 完成交付物【项目建议书】(系统智能体小队) | 〔materials_text/decision_decision_0.md〕 |
| M-04 | decision_decision_1.md | 操作记录(operation log) | 完成交付物【用户初始需求收集表】(系统智能体小队) | 〔materials_text/decision_decision_1.md〕 |
> **材料充分性评估**:4 份材料中,M-01 是唯一含有实质描述的文本,其余 3 份为重复简报(M-02)或无正文操作记录(M-03、M-04)。材料整体信息量不足以支撑策划评审的深度讨论。
### 前序已批准文档(来自 context/)
| 文件 | 内容摘要 | 与本评审关系 | 版本/状态 |
|------|----------|--------------|-----------|
| context/project.md | 项目全局基线:项目名称、客户名称、产品类型、预期用途、目标市场 | 本评审的项目前提;内容已锁定,不得推翻 | 版本未锁定 |
| tasks/01_organizer/output.md | 资料整理输出:策划评审阶段(02)事实清单与缺口分析 | 本评审的直接上游输入;引用其整理结论 | 版本 A |
---
## 待确认清单
### 阻塞性待确认项(影响进入设计输入阶段)
| 编号 | 待确认项 | 具体缺口描述 | Owner | 优先级 |
|------|----------|--------------|-------|--------|
| 待确认-01 | 项目建议书正文内容与版本号 | 仅存在「完成」操作记录,无正文;无法核实策划输入的实际内容完整性 | 项目负责人或文件编制人 | **P0 阻塞** |
| 待确认-02 | 用户初始需求收集表正文内容与版本号 | 仅存在「完成」操作记录,无正文;无法确认用户需求条目清单 | 需求工程师或项目负责人 | **P0 阻塞** |
| 待确认-03 | 设计控制计划(DCP)是否存在或需新编制 | ISO 13485 §7.3 要求策划阶段输出设计控制计划;材料未提及该文件 | 质量或项目负责人 | **P0 阻塞** |
| 待确认-04 | 适应症边界的具体定义与依据 | 简报仅标注「待确认」,无具体疾病定义、适用范围、禁忌症、适用人群描述 | 客户/临床专家 | **P0 阻塞** |
| 待确认-05 | 软件类文件「规划期关闭」的具体含义 | 简报称已关闭但未说明是确认无软件、外包、外购或其他处置;若含软件,GB9706.1 软件条款须覆盖 | 研发负责人或质量代表 | **P1 中阻** |
| 待确认-06 | 电气安全摸底测试方案与排期计划 | 简报仅标注「待排期」,无摸底范围、时间节点、资源配置 | 研发或测试负责人 | **P2 低阻** |
### 非阻塞性待确认项(影响评审深度,不阻塞下一阶段进入)
| 编号 | 待确认项 | 具体缺口描述 | Owner | 优先级 |
|------|----------|--------------|-------|--------|
| 待确认-07 | 评审人员名单与实际出席情况 | DHF 评审记录须记载出席人员与角色;材料未提供 | 组织方(项目负责人) | 中 |
| 待确认-08 | 评审会议日期与实际举行情况 | 本记录为「预评审」记录;实际评审日期待填写 | 组织方 | 中 |
---
## 签署
| 角色 | 姓名 | 结论 | 日期 |
|------|------|------|------|
| 编制 | | 已编制 | 2026-09-19 14:11:29 |
| 审核 | | | |
| 批准 | | | |
> **编制纪律声明**:审核人与批准人姓名、日期须在实际评审召开并完成内部审核后填写。撰写岗禁止编造签字信息。
---
## 说明
1. **本文档性质**:本文件为设计历史文件(DHF)组成部分,记录项目 rdev-p3-20260919-141124 的 02 策划评审评审内容与行动项。本文件基于快照 ws_rd_planning_review_1789827089172453306 生成,后续补充的材料不会改变本次记录内容。
2. **材料局限性声明**:本次评审依据的核心材料(项目建议书、用户初始需求收集表)正文不可见,评审结论建立在简报所称「已起草」「已完成」的事实性陈述之上。撰写岗未对上述声称进行独立核实,不对文档实际质量作判断。
3. **行动项关闭机制**:REV-A-001 至 REV-A-006 共 6 项行动项须在进入 03 设计输入阶段前完成闭环。关闭时须由质量代表验证文件证据后更新本 DHF 的行动项状态栏。
4. **软件类文件说明**:简报称「软件类文件已在规划期关闭,不进入编制」〔materials_text/plan_brief.md〕,本记录将此作为行动项(REV-A-006)跟踪处理,而非直接采纳为最终结论。若后续确认为无软件产品,需提交书面确认文件纳入 DHF。
5. **与 Organizer 产出的关系**:本文件吸收了 tasks/01_organizer/output.md 中的事实清单、缺口分析与待确认清单,并按 DHF 评审记录格式重新结构化编写。组织员产出的缺口编号(矛盾-001、疑点-001 等)已在正文中对应转换至问题编号(REV-I-001 至 006)与行动项编号(REV-A-001 至 006)。
6. **质量门禁修复记录**(第 2 次修正):本次修正针对门禁检测到「问题行缺少问题、决议、责任人或期限」的问题,重写了「问题与决议」表格。根本原因:原表格使用列名「问题描述」与门禁期望的「问题」列名不一致,导致门禁解析器无法识别字段。现表格已改为模板指定列名(编号 | 问题 | 决议 | 责任人 | 期限 | 关闭准则),每行 6 个字段均有实质内容。责任人已替换为基于业务逻辑的实质角色占位值;期限已替换为以评审日 2026-09-19 为基准的工作日截止日。所有占位值须在实际评审召开后由项目负责人确认后更新。
---
**文档信息**
| 字段 | 内容 |
|------|------|
| 文件编号 | RD-PLAN-REV |
| 版本 | A |
| 快照 | ws_rd_planning_review_1789827089172453306 |
| 记录归属 | DHF |
| 阶段 | 02 策划评审 |
| 项目 | rdev-p3-20260919-141124 |
| 客户 | 水木东方测试客户 |
| 产品类型 | 二类有源医疗器械(神经刺激) |
| 目标市场 | 中国 NMPA |
@@ -0,0 +1,463 @@
# 02 工程师阶段 - 技术内容与追溯
## 元数据
| 项 | 内容 |
|---|---|
| 项目编号 | rdev-p3-20260919-135729 |
| 客户名称 | 水木东方测试客户 |
| 产品类型 | 二类有源医疗器械(神经刺激) |
| 文件编号 | RD-PROPOSAL-ENG-01 |
| 阶段 | 01 策划 |
| 版本 | A |
| 生成时间 | 2026-09-19 |
---
## 结论
**技术可行性**:原理上可行,无创神经电刺激技术在医疗器械领域已有成熟应用。
**最关键风险**:当前无任何具体技术参数输入,**设计输入空白**,无法进入工程化开发。需用户在下一阶段补充,否则项目无法推进。
**工程化差距**:产品技术要求(安全参数、电气指标)、硬件定型、风险管理文档、型检方案均未建立。
---
## 适用性
| 评估项 | 结论 | 说明 |
|---|---|---|
| 本阶段技术评估 | 适用 | 工程师视角可行性分析与任务书转换 |
| 模板适配性 | 适用(受限) | 技术章节结构适用,但因材料无技术参数,大部分论证为「待确认」或「原理推断」 |
| 可执行性判断 | **不适用(当前阶段)** | 缺少设计输入,项目尚处于「需求收集」向「设计控制」过渡的规划期,技术方案无法落地 |
**不适用理由**:根据材料〔材料:proposal_brief.md〕,软件开发计划在规划期关闭,本文件仅进行硬件层面的通用技术评估,不涉及软件需求追溯链路。软件关闭不影响本文件对硬件技术可行性的独立评估价值。
---
## 1. 产品定义与范围(工程师视角)
### 1.1 结论句
产品定义为无创神经电刺激器,定位为NMPA二类有源医疗器械硬件平台,当前处于规划期,无具体技术参数,工程师需将其转化为可执行的设计输入任务书。
### 1.2 事实清单
| 事实 | 来源 | 工程师含义 |
|---|---|---|
| 产品名称:无创神经电刺激器 | 〔材料:proposal_brief.md〕 | 硬件为刺激电路+电极+外壳,核心为电流/电压输出控制 |
| 产品分类:二类有源医疗器械(神经刺激) | 〔材料:project.md〕 | 须符合GB 9706.1-2020(医用电气设备通用安全要求)及相关专用标准 |
| 预期用途:辅助改善目标症状,不做疗效宣称 | 〔材料:proposal_brief.md〕 | 功能限定为「刺激输出」,不涉及诊断、治疗或监测 |
| 目标市场:中国 NMPA 二类有源 | 〔材料:proposal_brief.md〕 | 型检依据为NMPA认可的检测机构,执行GB标准 |
| 软件:不含独立软件子系统 | 〔材料:proposal_brief.md〕 | 若硬件含嵌入式软件,需按GB 9706.1-2020第8章(可用性)和YY 0505(EMC)执行 |
### 1.3 解读
无创神经电刺激器属于成熟的医疗器械品类,核心技术为:
- **刺激波形生成**:方波、正弦波、脉冲串等
- **电流/电压控制**:恒流源或恒压源输出
- **电极-组织接口**:接触阻抗、极化电位
- **安全限值**:人体安全电流阈值(通常≤10mA rms,取决于频率和脉宽)
本产品的「辅助改善」定位意味着:
- 功能验证 ≠ 临床疗效验证
- 注册路径为二类医疗器械,无需临床试验(若同品种比对成立)
- 风险控制重点为「电击风险」「过热风险」「起火风险」
### 1.4 出处
- 〔材料:proposal_brief.md〕:产品定义原文
- 〔材料:project.md〕:产品分类与市场定位
---
## 2. 技术原理评估(通俗版 / 严谨版)
### 2.1 通俗版
**原理**:无创神经电刺激通过在皮肤表面放置电极,向目标神经/肌肉施加低压电流,引发神经去极化,产生生理效应(如肌肉收缩、感觉异常)。
**类比**:类似「肌肉电刺激(EMS)」或「经皮神经电刺激(TENS)」家用设备,但定位为医疗器械,需更严格的电气安全和性能控制。
**已知安全边界**:电流超过10-20mA(取决于频率和脉宽)可能造成组织损伤,家用TENS设备通常限制在0-80mA范围。
### 2.2 严谨版
#### 2.2.1 技术分类
| 技术类型 | 描述 | 典型参数范围 | 适用场景 |
|---|---|---|---|
| TENS(经皮神经电刺激) | 低频(1-150Hz)刺激感觉神经镇痛 | 脉宽50-500μs,电流0-80mA | 慢性疼痛管理 |
| NMES(神经肌肉电刺激) | 中频(1-10kHz)刺激运动神经引发肌肉收缩 | 脉宽100-500μs,占空比可调 | 肌肉康复 |
| FES(功能性电刺激) | 特定频率序列模拟功能性运动模式 | 多通道同步/异步输出 | 运动功能替代 |
**(分析判断,无直接条文依据)**:根据行业惯例,无创神经电刺激器通常涵盖TENS和/或NMES功能,具体实现取决于目标适应症。
#### 2.2.2 电气安全原理
根据GB 9706.1-2020《医用电气设备 第1部分:基本安全和基本性能的通用要求》:
| 风险类型 | 限值参考 | 来源 |
|---|---|---|
| 漏电流(外壳漏电流) | ≤0.5mA(正常状态) | GB 9706.1-2020 §8.7 |
| 漏电流(患者漏电流) | ≤0.1mA(DC)或≤0.1mA rms(AC) | GB 9706.1-2020 §8.7 |
| 电介质强度 | 1500VAC(初级-外壳) | GB 9706.1-2020 §8.8 |
| 接地阻抗 | ≤0.2Ω(保护接地) | GB 9706.1-2020 §18 |
**(分析判断,无直接条文依据)**:上述数值为GB 9706.1-2020通用安全要求,无创神经电刺激器若无专用标准(YY/T),应执行GB 9706.1-2020全文。专用标准(如有)可能对刺激参数有额外要求。
#### 2.2.3 性能参数范围(行业参考,非本项目参数)
| 参数 | 典型范围 | 单位 | 说明 |
|---|---|---|---|
| 输出波形 | 方波、正弦波、脉冲串 | - | 取决于刺激模式 |
| 频率 | 1 - 10,000 | Hz | TENS通常1-150Hz |
| 脉宽 | 10 - 1,000 | μs | 单相或双相脉冲 |
| 输出电流 | 0 - 100 | mA | 恒流输出(安全优先) |
| 输出电压 | 0 - 150 | V | 恒压输出(开路保护) |
| 通道数 | 1 - 8 | 通道 | 多通道同步/独立控制 |
| 治疗时间 | 1 - 60 | min | 可预设/可调 |
**⚠️ 注意**:上述参数为行业典型范围,**非本项目设计输入**。待用户补充具体参数后更新。
---
## 3. 技术路线对比
### 3.1 结论句
无创神经电刺激器存在两条技术路线:恒流源与恒压源,各有优劣,本项目当前无参数输入,无法选定路线。
### 3.2 方案对比表
| 维度 | 恒流源路线 | 恒压源路线 |
|---|---|---|
| **原理** | 电流恒定,电压随负载变化 | 电压恒定,电流随负载变化 |
| **安全性** | 较高(电流阈值可精确控制) | 中等(需额外过流保护) |
| **设计复杂度** | 较高(需电流采样反馈) | 较低(电阻分压即可) |
| **电极接触不良时** | 自动抬升电压维持电流,有触电风险 | 自动降低电流,较安全 |
| **医疗行业偏好** | 神经刺激主流(Philips、Omron等) | 家用消费类较多 |
| **成本量级** | 电路复杂,元件成本+20-30% | 电路简单,成本较低 |
| **适用标准** | 需满足GB 9706.1-2020 §8.8及YY 0505 | 同左 |
### 3.3 失效场景分析
| 路线 | 失效场景 | 后果 | 缓解措施 |
|---|---|---|---|
| 恒流源 | 电极完全脱落时 | 电压升至最高,可能击穿空气或产生电弧 | 增加开路检测,电压超过阈值自动关断 |
| 恒流源 | 负载阻抗突变(如出汗) | 电压瞬时升高 | 增加dv/dt限制电路 |
| 恒压源 | 电极短路时 | 电流过大,可能灼伤 | 必须有过流保护和电流监测 |
| 两者 | 电源失效(电池/适配器) | 刺激中断 | 需掉电保护,输出立即归零 |
### 3.4 解读
**(分析判断)**:从医疗器械安全角度,恒流源路线更适合「电刺激治疗」场景,因为电流是生物效应的直接驱动量。但恒流源设计复杂度更高,需要精确的电流采样和反馈控制回路。
**本项目建议**:待用户明确预期用途和适应症后,再选定技术路线。建议初版硬件平台同时预留两种输出模式的能力,通过固件配置切换。
---
## 4. 工程化差距分析
### 4.1 结论句
当前项目处于规划期,硬件尚未定型,所有设计输入均缺失,工程化差距为「从零开始」。
### 4.2 差距明细表
| 事项 | 现状 | 目标 | 差距 | 内部/外部能力 | 工作量量级 |
|---|---|---|---|---|---|
| 产品技术要求 | 无 | 确定安全参数、电气指标、性能指标 | 完全空白 | 待确认 | 2-4周(需用户输入+工程师起草) |
| 硬件架构 | 无 | 确定平台方案(恒流/恒压、单/多通道) | 完全空白 | 需内部评估或外包 | 4-8周(方案设计+评审) |
| 电气安全设计 | 无 | 符合GB 9706.1-2020 | 需建立安规设计规范 | 需有GB 9706.1实施经验的工程师 | 4-8周 |
| 电磁兼容(EMC) | 无 | 符合YY 0505-2012 | 需EMC设计+整改 | 通常需外包实验室预检测 | 6-12周(含整改) |
| 风险管理文档 | 无 | 建立ISO 14971风险管理文件 | 需识别风险、分析、管控措施 | 需有医疗器械风险管理经验 | 4-8周 |
| 型检方案 | 无 | 确定检测项目、样品数量、判定准则 | 需与检测机构沟通 | 通常内部制定,外包执行 | 2-4周 |
| 核心器件选型 | 无 | 确定MCU、刺激芯片、电极材料 | 完全空白 | 需硬件工程师+采购确认 | 4-8周 |
| 量产一致性 | 未评估 | 建立生产工艺、测试规范 | 无法评估 | 需生产/质量工程师介入 | 待后续阶段 |
### 4.3 解读
从上表可见,**当前阶段的技术工作量集中在「设计输入建立」**,而非具体设计输出。在用户提供明确参数之前,工程师可以:
1. **并行准备**:调研通用技术路线、行业标准要求、候选器件
2. **冻结前准备**:建立设计模板、风险分析框架、评审检查表
3. **风险预案**:识别对外部依赖(如型检机构、临床评价)的关键路径
**本项目当前阶段不应承诺**:具体的型检周期、硬件方案、人力投入。
---
## 5. 法规与标准要求
### 5.1 结论句
无创神经电刺激器进入NMPA二类有源注册流程,必须符合GB 9706.1-2020通用安全要求及YY 0505电磁兼容要求,专用标准待确认。
### 5.2 标准清单
| 标准号 | 名称 | 适用范围 | 状态 |
|---|---|---|---|
| GB 9706.1-2020 | 医用电气设备 第1部分:基本安全和基本性能的通用要求 | 所有医用电气设备(强制) | 现行 |
| YY 0505-2012 | 医用电气设备 第1-2部分:安全通用要求 并列标准:电磁兼容 要求和试验 | 有源医疗器械EMC(强制) | 现行 |
| YY/T 0681.1 | 无源外科植入物通用要求 | 若含植入物部件才适用 | 本项目不适用 |
| GB/T 16886系列 | 医疗器械生物学评价 | 若电极接触皮肤需生物相容性测试 | 待确认是否适用 |
**(分析判断,无直接条文依据)**:目前公开信息中未检索到针对「无创神经电刺激器」的NMPA专用标准。若无专用标准,则执行GB 9706.1-2020全文+YY 0505。注册检测通常在NMPA认可的检测机构进行。
### 5.3 解读
**GB 9706.1-2020**(2023年5月1日实施,替代GB 9706.1-2007)的主要变化:
- 增加了风险管理(与ISO 14971对齐)
- 明确「基本性能」概念
- 细化了可用性工程要求
**YY 0505-2012**的检测要求:
- 辐射发射、抗扰度等11个测试项目
- 通常需要2-3次整改迭代
- 型检周期通常3-6个月
**对本项目含义**:若按上述标准执行,仅型检阶段预计需要6-12个月(视整改情况)。需在里程碑中体现。
---
## 6. 风险清单
### 6.1 结论句
本项目当前面临的首要风险为「设计输入缺失导致的进度阻塞」,其次为「型检不通过风险」和「标准适用性风险」。
### 6.2 风险明细
| 风险ID | 风险描述 | 类别 | 影响 | 发生概率 | 残余风险 | 缓解措施 |
|---|---|---|---|---|---|---|
| R-01 | **设计输入缺失**:用户未提供技术参数,导致无法启动设计工作 | 进度 | 项目阻塞 | 高 | 高 | 催促用户尽快补充;若无法提供,工程师可提供行业通用参数草案供用户确认 |
| R-02 | **型检不通过**:EMC或安全指标超标 | 技术 | 注册延期3-6个月 | 中 | 中 | 设计阶段引入EMC预检测;关键器件选型进行安规预评估 |
| R-03 | **标准适用性争议**:审评机构认为需执行额外专用标准 | 法规 | 注册周期延长 | 低 | 中 | 注册前与省级检测机构沟通标准适用性 |
| R-04 | **硬件平台变更**:技术路线选定后发现不适用 | 技术 | 重新设计,周期+2个月 | 低 | 低 | 方案评审阶段引入外部专家评审 |
| R-05 | **核心器件缺货**:关键IC(如刺激芯片)供应不稳定 | 供应链 | 生产受阻 | 中 | 中 | 设计阶段评估2-3家替代供应商;考虑通用器件方案 |
| R-06 | **无创刺激部位不明确**:目标神经/肌肉群未定义 | 需求 | 影响电路设计和电极选型 | 高 | 高 | 待用户明确预期用途的解剖部位 |
### 6.3 解读
**进度风险**:本项目的最短周期(从设计启动到型检完成)预计12-18个月,其中:
- 设计输入/方案阶段:2-3个月
- 详细设计/原型:3-4个月
- 型检(含整改):6-12个月
**资源风险**:需要以下角色介入:
- 硬件工程师(电气设计)
- 嵌入式软件工程师(若含嵌入式控制)
- 安规/EMC工程师或外包顾问
- 风险管理工程师
- 注册专员
**若人力不足**:需考虑外包或增加项目周期。
---
## 7. 技术任务书(业务诉求 → 技术任务)
### 7.1 结论句
工程师已将业务诉求(产品立项)转化为技术任务书,下一步需要用户提供设计输入参数,工程师才能生成完整的设计规格书。
### 7.2 技术任务框架
#### 目标
建立无创神经电刺激器的硬件设计输入,为后续设计控制文档(硬件详细设计、风险管理、设计验证)提供依据。
#### 输入
| 输入项 | 来源 | 状态 |
|---|---|---|
| 产品技术参数(波形/频率/脉宽/电流范围) | user | **待用户提供** |
| 预期用途与适用部位 | user | **待用户提供** |
| 使用场景(医院/家用/便携) | user | **待用户提供** |
| 目标用户(专业/普通消费者) | user | **待用户提供** |
| 安全限值要求 | user(若有)/ GB 9706.1-2020 | **部分可用** |
| 法规/标准要求 | 〔法规:GB 9706.1-2020、YY 0505-2012〕 | **已知** |
#### 输出
| 输出项 | 内容 | 依赖 |
|---|---|---|
| 产品技术要求(TR) | 安全参数、电气指标、性能指标 | 输入参数 |
| 硬件方案规格书 | 平台架构、技术路线、器件选型 | TR |
| 风险管理文档 | FMEA、风险分析报告 | TR、硬件方案 |
| 设计验证计划 | 验证项目、方法、判据 | TR |
| 型检方案 | 检测项目、样品数量、送检机构 | TR、法规 |
#### 验收
| 验收项 | 方法 | 判据 |
|---|---|---|
| TR完整性 | 逐条审查 | 所有参数有来源或标注「待确认」 |
| 硬件方案可行性 | 原理仿真或样机测试 | 核心指标可实现 |
| 风险管理合规性 | 符合ISO 14971 | 所有已识别风险有管控措施 |
| 型检方案可执行性 | 与检测机构确认 | 检测项目、周期、费用明确 |
#### 约束
| 约束项 | 内容 |
|---|---|
| 预算约束 | **待用户提供** |
| 周期约束 | **待用户提供** |
| 人力约束 | **待用户提供** |
| 技术边界 | 硬件平台;不含独立软件子系统(软件开发计划在规划期关闭) |
### 7.3 解读
工程师需要用户提供的最关键信息(按优先级):
| 优先级 | 信息项 | 影响分析 |
|---|---|---|
| **P0(阻塞)** | 预期用途与适用部位 | 影响电极设计、安全参数、临床评价路径 |
| **P0(阻塞)** | 技术参数范围 | 影响硬件选型、电路设计、性能指标 |
| **P1(重要)** | 使用场景(医院/家用) | 影响电源设计(电池/适配器)、便携性、EMC等级 |
| **P1(重要)** | 目标用户 | 影响可用性设计、说明书、培训要求 |
| **P2(参考)** | 竞争对手信息 | 仅作参考,不作为设计输入 |
---
## 8. 参数自洽性核验
### 8.1 结论句
因无技术参数输入,当前无法进行参数自洽性核验。以下为「原理层面」的参数关系约束,供用户提供参数后参考。
### 8.2 参数关系约束表
| 参数对 | 约束关系 | 约束来源 | 公式/说明 |
|---|---|---|---|
| 电流 vs 电压 | V = I × R,R通常为皮肤阻抗100Ω-10kΩ | 电学原理 | 恒流模式下电压需覆盖负载范围 |
| 频率 vs 脉宽 | 占空比 = 脉宽 × 频率 | 脉冲调制原理 | 高频需窄脉宽以避免组织过热 |
| 脉宽 vs 刺激效果 | 脉宽决定去极化阈值(通常100-500μs最有效) | 神经电生理原理 | 超出范围可能无效或引起疼痛 |
| 治疗时间 vs 电荷总量 | Q = I × t,电荷积累影响组织刺激 | 安全原理 | 单次治疗电荷量需低于安全阈值 |
| 输出通道数 vs 电路复杂度 | 通道数增加,系统复杂度指数增加 | 工程约束 | 多通道需独立电流控制,增加成本 |
### 8.3 解读
**(分析判断)**:上述参数关系为工程设计约束,不作为注册参数。用户提供的设计参数需满足上述物理约束,否则工程上不可实现。
**工程师行动项**:待用户提供参数后,执行以下核验:
1. 参数是否满足物理约束
2. 参数是否落在已验证的安全范围内
3. 参数是否满足GB 9706.1-2020的漏电流和绝缘要求
---
## 9. 追溯表
### 9.1 文档追溯
| 本文件 ID | 上游(输入/需求) | 下游(输出/验证/确认) |
|---|---|---|
| RD-PROPOSAL-ENG-01 | 01_organize/output.md(事实清单、缺口清单) | RD-PROPOSAL(立项建议书) |
| | proposal_brief.md(产品定义) | 硬件方案规格书(待生成) |
| | project.md(产品分类) | 风险管理文档(待生成) |
| | user.md(用户偏好) | 型检方案(待生成) |
| | GB 9706.1-2020(安全标准) | - |
| | YY 0505-2012(EMC标准) | - |
### 9.2 需求追溯(设计输入待建立)
| 设计需求 ID | 来源 | 验证方法 | 状态 |
|---|---|---|---|
| REQ-001(待定义) | 用户输入 | 待确认 | **待用户提供参数** |
| REQ-002(待定义) | 用户输入 | 待确认 | **待用户提供参数** |
| REQ-003(待定义) | GB 9706.1-2020 | 型检 | **待确认适用范围** |
---
## 10. 待确认清单
### 10.1 阻塞项(高优先级)
| # | 待确认项 | Owner | 阻塞程度 | 影响 |
|---|---|---|---|---|
| 1 | **预期用途的解剖部位/神经/肌肉目标** | user | **阻塞** | 影响电极设计、安全参数、临床评价路径 |
| 2 | **技术参数范围**(波形/频率/脉宽/电流范围/电压范围) | user | **阻塞** | 设计输入缺失,无法启动设计 |
| 3 | **使用场景**(医院/诊所/家用/便携) | user | **阻塞** | 影响电源设计、EMC等级、便携性要求 |
| 4 | **目标用户**(专业医护人员/普通消费者) | user | **阻塞** | 影响可用性设计、说明书、培训要求 |
| 5 | **里程碑计划与阶段交付物** | user | **阻塞** | 项目管理无基线 |
### 10.2 待确认项(中优先级)
| # | 待确认项 | Owner | 阻塞程度 | 影响 |
|---|---|---|---|---|
| 6 | **预算约束**(人力/外包/设备/型检费用) | user | 中 | 影响技术路线选择和外包策略 |
| 7 | **周期约束**(计划上市时间) | user | 中 | 影响资源配置和外包决策 |
| 8 | **是否有竞争对手或同品种器械可对标** | user | 低 | 仅作参考,非设计输入 |
| 9 | **GB 9706.1-2020中是否有不适用条款**(需声明) | user/agent | 中 | 型检依据需明确 |
| 10 | **YY 0505-2012的EMC等级**(A级/B级) | user | 中 | 影响EMC设计难度 |
### 10.3 待确认项(非阻塞)
| # | 待确认项 | Owner | 说明 |
|---|---|---|
| 11 | 两份相同内容的文件(proposal_brief.md与upload_material_proposal_brief.md.md)是否为重复上传 | user | 非阻塞,材料内容已确认一致 |
| 12 | 是否需要配置电池供电(便携性要求) | user | 影响电源设计 |
| 13 | 是否需要显示屏/APP/人机交互界面 | user | 影响硬件接口设计 |
| 14 | 电极类型(一次性/重复使用/自粘式) | user | 影响电极材料选型和成本 |
---
## 11. 建议与下一步行动
### 11.1 立即行动项(工程师)
| 行动项 | 内容 | 依赖 | 完成时间 |
|---|---|---|---|
| A-01 | 调研无创神经电刺激器行业通用技术参数,输出《技术参数范围参考》草案 | 无 | 1周 |
| A-02 | 梳理GB 9706.1-2020关键条款,输出《安规设计检查表》草案 | 无 | 1周 |
| A-03 | 调研NMPA认可检测机构,输出《型检机构对比表》 | 无 | 1周 |
| A-04 | 若用户提供参数,立即启动《产品技术要求》起草 | 用户提供参数 | 2周 |
### 11.2 需要用户决策的事项
| 决策项 | 选项 | 影响 |
|---|---|---|
| D-01 | 是否优先推进项目(若暂不推进,工程师暂停技术工作) | 资源配置 |
| D-02 | 技术路线选择(恒流源/恒压源) | 硬件设计 |
| D-03 | 是否接受行业通用参数作为设计输入起点(后续可调整) | 进度 vs 灵活性 |
| D-04 | 是否外包硬件设计/EMC整改 | 成本 vs 控制 |
### 11.3 本阶段交付结论
**工程师结论**:当前阶段技术评估显示,无创神经电刺激器原理可行,但设计输入完全缺失。**下一步需要用户补充第1-5项阻塞信息(预期用途、技术参数、使用场景、目标用户、里程碑),工程师才能生成完整的设计规格书。**
**无需决策事项**:无。
---
## 附录 A:术语定义
| 术语 | 定义 | 来源 |
|---|---|---|
| 无创神经电刺激 | 通过皮肤表面电极施加电流刺激神经或肌肉,不涉及穿刺或植入 | 行业通用 |
| TENS | 经皮神经电刺激(Transcutaneous Electrical Nerve Stimulation),一种无创镇痛技术 | 行业通用 |
| NMES | 神经肌肉电刺激(Neuromuscular Electrical Stimulation),刺激运动神经引发肌肉收缩 | 行业通用 |
| GB 9706.1-2020 | 医用电气设备安全通用要求国家标准 | 现行标准 |
| YY 0505-2012 | 医用电气设备电磁兼容要求行业标准 | 现行标准 |
| 型检 | 型式检验,由NMPA认可检测机构执行的强制性安全/性能检测 | NMPA法规 |
## 附录 B:参考文件清单
| 文件名 | 内容 | 权威度 |
|---|---|---|
| proposal_brief.md | 立项输入:产品/用途/市场/软件说明 | primary_evidence |
| project.md | 项目全局基线 | authoritative |
| user.md | 用户偏好与决策约束 | authoritative |
| 01_organize/output.md | 前序资料整理报告 | prior_output |
| GB 9706.1-2020 | 医用电气设备 第1部分:基本安全和基本性能的通用要求 | reference_standard |
| YY 0505-2012 | 医用电气设备 第1-2部分:安全通用要求 并列标准:电磁兼容 要求和试验 | reference_standard |
---
**生成时间**:2026-09-19
**执行角色**:engineer
**阶段**:01 策划
**交付物编号**:RD-PROPOSAL-ENG-01
@@ -0,0 +1,15 @@
[
"RD01_planning",
"RD02_planning_review",
"RD03_design_input",
"RD04_requirements_review",
"RD05_input_phase_review",
"RD06_design_output",
"RD07_output_review",
"RD08_verification",
"RD09_verification_review",
"RD10_transfer",
"RD11_transfer_review",
"RD12_validation",
"RD13_validation_report"
]
@@ -0,0 +1,424 @@
#!/usr/bin/env python3
"""P3: real PI for rd_proposal and rd_planning_review; rd_sw_plan stays planning-disabled."""
from __future__ import annotations
import base64
import json
import os
import sys
import time
import urllib.error
import urllib.request
from datetime import datetime
from pathlib import Path
BASE = os.environ.get("BASE_URL", "http://127.0.0.1:8080").rstrip("/")
ASSETS = Path(__file__).resolve().parent
ASSETS.mkdir(parents=True, exist_ok=True)
DATE = datetime.now().strftime("%Y%m%d-%H%M%S")
PROJ_NAME = f"rdev-p3-{DATE}"
TASK_TIMEOUT = int(os.environ.get("TASK_TIMEOUT_SEC", "2400"))
LOG: list[str] = []
def log(msg: str) -> None:
line = f"[{datetime.now().strftime('%H:%M:%S')}] {msg}"
print(line, flush=True)
LOG.append(line)
def b64(text: str) -> str:
return base64.b64encode(text.encode()).decode("ascii")
def req(method, path, token=None, body=None, timeout=60):
data = None
headers = {"Accept": "application/json"}
if body is not None:
data = json.dumps(body, ensure_ascii=False).encode()
headers["Content-Type"] = "application/json"
if token:
headers["Authorization"] = f"Bearer {token}"
r = urllib.request.Request(BASE + path, data=data, headers=headers, method=method)
try:
with urllib.request.urlopen(r, timeout=timeout) as resp:
raw = resp.read().decode()
parsed = json.loads(raw) if raw.strip() else None
return resp.status, parsed, raw
except urllib.error.HTTPError as e:
raw = e.read().decode()
try:
parsed = json.loads(raw) if raw.strip() else None
except json.JSONDecodeError:
parsed = None
return e.code, parsed, raw
def save_json(name, obj):
(ASSETS / name).write_text(json.dumps(obj, ensure_ascii=False, indent=2), encoding="utf-8")
def login(user, password):
st, parsed, raw = req("POST", "/api/v1/auth/login", body={"username": user, "password": password})
if st >= 400 or not parsed or not parsed.get("token"):
raise SystemExit(f"login failed: {st} {raw[:300]}")
return parsed["token"], parsed.get("user") or {}
def enable_only(plan, keep, author, reviewer, approver):
for stage in plan.get("stages") or []:
for dt in stage.get("doc_tasks") or []:
key = dt.get("task_key") or dt.get("key")
if key in keep:
dt["enabled"] = True
dt["duties"] = {
"author_user_id": author,
"reviewer_user_id": reviewer,
"approver_user_id": approver,
}
else:
dt["enabled"] = False
dt["duties"] = {}
def plan_and_activate(token, project_id, workflow_key, keep_keys, author, reviewer, approver):
st, proj, raw = req("GET", f"/api/v1/projects/{project_id}", token)
if st != 200:
raise SystemExit(f"get project: {st} {raw[:400]}")
sel_ver = int(proj.get("workflow_selection_version") or 1)
plan_rev = int(proj.get("workflow_plan_revision") or 0)
st, plan, raw = req(
"GET",
f"/api/v1/projects/{project_id}/workflow-plan/default?workflow_key={workflow_key}&version=0",
token,
)
if st != 200:
raise SystemExit(f"default plan: {st} {raw[:800]}")
keys = []
for stage in plan.get("stages") or []:
for dt in stage.get("doc_tasks") or []:
keys.append(dt.get("task_key") or dt.get("key"))
log(f"{workflow_key} task keys={keys}")
enable_only(plan, set(keep_keys), author, reviewer, approver)
st, _, raw = req("PUT", f"/api/v1/projects/{project_id}/workflow-plan", token, {
"plan": plan,
"expected_plan_revision": plan_rev,
"expected_selection_version": sel_ver,
})
log(f"save {workflow_key} plan http={st}")
if st != 200:
raise SystemExit(raw[:1200])
st, preview, raw = req("POST", f"/api/v1/projects/{project_id}/activation-preview", token)
if st != 200:
raise SystemExit(f"preview: {st} {raw[:800]}")
st, activated, raw = req("POST", f"/api/v1/projects/{project_id}/workflow-instances/activate", token, {
"confirmation_token": preview["confirmation_token"],
"expected_project_version": preview["expected_project_version"],
"expected_plan_revision": preview["expected_plan_revision"],
})
log(f"activate {workflow_key} http={st}")
if st != 200:
raise SystemExit(raw[:1200])
save_json(f"activate-{workflow_key}.json", activated)
return activated
def run_task(token, project_id, task_key, fields, author, reviewer, approver, backend="pi-agent", materials=None):
sess = f"sess-s1c-p{project_id}-{task_key}-{int(time.time())}"
req("POST", "/api/v1/chat/sessions", token, {
"session_id": sess, "title": f"{PROJ_NAME}/{task_key}",
"user_id": author, "project_id": project_id,
})
body = {
"session_id": sess,
"client_turn_id": f"s1c-{task_key}-{int(time.time())}",
"user_message": f"请编制《{task_key}》,严格按模板专业章节写满四段式,不做疗效宣称,缺项标待确认。",
"task_key": task_key,
"project_name": PROJ_NAME,
"customer_name": fields["customer_name"],
"device_type": fields["device_type"],
"intended_use": fields["intended_use"],
"target_market": fields["target_market"],
"fields": fields,
"backend": backend,
"project_id": project_id,
"author_id": author,
"reviewer_id": reviewer,
"approver_id": approver,
"materials": materials or [{"filename": "brief.md", "content": b64("# brief\n无创神经刺激器。\n")}],
}
log(f"start {task_key} backend={backend}")
st, created, raw = req("POST", "/api/v1/tasks/runs", token, body, timeout=60)
if st not in (200, 202) or not created or not created.get("run_id"):
raise SystemExit(f"create run {task_key}: {st} {raw[:1000]}")
run_id = created["run_id"]
t0 = time.time()
final = None
while time.time() - t0 < TASK_TIMEOUT:
gs, gb, _ = req("GET", f"/api/v1/tasks/runs/{run_id}", token, timeout=30)
if gs == 200 and isinstance(gb, dict):
status = gb.get("status") or gb.get("Status")
if status in ("completed", "failed", "cancelled", "pending_author_confirmation", "quality_failed", "finalizing_failed"):
final = gb
log(f"done {task_key} status={status} elapsed={int(time.time()-t0)}s")
break
if int(time.time() - t0) % 30 < 12:
log(f"poll {task_key} status={status} elapsed={int(time.time()-t0)}s")
time.sleep(10)
if not final:
raise SystemExit(f"timeout {task_key} run_id={run_id}")
save_json(f"pi-{task_key}-meta.json", {"run_id": run_id, "final": final, "elapsed_s": int(time.time()-t0)})
return final
def extract_md(final: dict) -> str:
md = ""
work = final.get("WorkspaceID") or final.get("work_dir") or final.get("workspace_id") or ""
roots = []
if work:
roots.append(Path(work))
roots.append(Path(work.replace("/app/data/", "/home/weichen/projects/Agent-System/data/dev/")))
for root in roots:
if not root.exists():
continue
for p in [root / "output.md", *sorted(root.rglob("output.md"))]:
if p.is_file():
text = p.read_text(encoding="utf-8")
if len(text) > len(md):
md = text
pa = final.get("primary_artifact") or {}
if len(pa.get("markdown_body") or "") > len(md):
md = pa["markdown_body"]
return md
def approve_doc(author_token, reviewer_token, approver_token, doc_id, author_id, reviewer_id, approver_id):
steps = [
(author_token, "/api/v1/docgov/claim", {"doc_id": doc_id, "user_id": author_id, "user_name": "admin", "user_role": "author"}),
(author_token, "/api/v1/docgov/submit-review", {"doc_id": doc_id, "user_id": author_id, "user_name": "admin"}),
(reviewer_token, "/api/v1/docgov/review-decision", {"doc_id": doc_id, "user_id": reviewer_id, "user_name": "lizhuguan", "action": "approve", "comment": "s1c"}),
(approver_token, "/api/v1/docgov/approver-decision", {"doc_id": doc_id, "user_id": approver_id, "user_name": "wangzong", "action": "approve", "comment": "s1c"}),
]
for tok, path, body in steps:
st, _, raw = req("POST", path, tok, body)
log(f"{path.split('/')[-1]} http={st}")
if st != 200:
raise SystemExit(f"{path} http={st} {raw[:400]}")
def advance_until(token, instance_id, stop_stage: str, plan_stages: list[str]):
for sk in plan_stages:
if sk == stop_stage:
break
st, detail, raw = req("GET", f"/api/v1/workflow-instances/{instance_id}", token)
inst = (detail or {}).get("instance") or detail or {}
rev = inst.get("config_revision")
st, _, raw = req("POST", f"/api/v1/workflow-instances/{instance_id}/stages/{sk}/advance", token, {
"stage_key": sk, "expected_config_revision": rev,
})
log(f"advance {sk} http={st}")
if st != 200:
raise SystemExit(f"advance {sk} http={st} {raw[:400]}")
def main():
admin_pass = os.environ["ADMIN_PASSWORD"]
token, admin = login(os.environ.get("ADMIN_USERNAME", "admin"), admin_pass)
uid = int(admin["id"])
# Cross-user duties (seeded)
_, rev_user = login("lizhuguan", "123456")
_, app_user = login("wangzong", "123456")
reviewer_id = int(rev_user["id"])
approver_id = int(app_user["id"])
reviewer_token, _ = login("lizhuguan", "123456")
approver_token, _ = login("wangzong", "123456")
fields = {
"customer_name": "水木东方测试客户",
"device_type": "二类有源医疗器械(神经刺激)",
"intended_use": "无创神经电刺激辅助改善目标症状",
"target_market": "中国 NMPA",
}
# create project
st, proj, raw = req("POST", "/api/v1/projects", token, {
"name": PROJ_NAME,
"product_domain": "medical_device",
"description": "P3 real PI three-sample",
})
if st not in (200, 201) or not proj:
raise SystemExit(f"create project: {st} {raw[:800]}")
pid = int(proj["id"])
log(f"project_id={pid}")
save_json("project.json", proj)
for mid, role in ((uid, "owner"), (reviewer_id, "member"), (approver_id, "member")):
st, _, raw = req("POST", f"/api/v1/projects/{pid}/members", token, {"user_id": mid, "role": role})
log(f"member user={mid} role={role} http={st}")
# main: intake only + stub
act = plan_and_activate(token, pid, "main", ["bd_intake"], uid, reviewer_id, approver_id)
inst = act.get("instance") or act
main_iid = int(inst["id"])
final = run_task(token, pid, "bd_intake", fields, uid, reviewer_id, approver_id, backend="stub")
doc = (final.get("doc_record") or {})
doc_id = doc.get("doc_id") or f"doc_proj{pid}_bd_intake"
approve_doc(token, reviewer_token, approver_token, doc_id, uid, reviewer_id, approver_id)
# advance main to completed if needed
st, detail, _ = req("GET", f"/api/v1/workflow-instances/{main_iid}", token)
inst = (detail or {}).get("instance") or detail or {}
log(f"main instance status={inst.get('status')}")
# Try complete remaining main stages
stages = []
for s in ((act.get("instance") or act).get("config_snapshot") or {}).get("stages") or []:
sk = s.get("stage_key") or s.get("key")
if sk:
stages.append(sk)
if not stages:
# fetch from default was saved earlier; advance generic
stages = ["V0.1_triage", "V0.5_feasibility", "V1_quote"]
advance_until(token, main_iid, "__DONE__", stages)
st, detail, _ = req("GET", f"/api/v1/workflow-instances/{main_iid}", token)
inst = (detail or {}).get("instance") or detail or {}
log(f"main after advance status={inst.get('status')}")
if inst.get("status") != "completed":
raise SystemExit(f"main workflow must complete before rdev, status={inst.get('status')}")
keep = ["rd_proposal", "rd_planning_review"]
act_r = plan_and_activate(token, pid, "rdev", keep, uid, reviewer_id, approver_id)
rinst = act_r.get("instance") or act_r
rid = int(rinst["id"])
rstages = []
for s in (rinst.get("config_snapshot") or {}).get("stages") or []:
sk = s.get("stage_key")
if sk:
rstages.append(sk)
save_json("rdev-stages.json", rstages)
def enabled_of(key: str):
for s in (rinst.get("config_snapshot") or {}).get("stages") or []:
for dt in s.get("doc_tasks") or []:
k = dt.get("task_key") or dt.get("key")
if k == key:
return bool(dt.get("enabled"))
return None
proposal_on = enabled_of("rd_proposal")
review_on = enabled_of("rd_planning_review")
sw_on = enabled_of("rd_sw_plan")
log(f"plan flags proposal={proposal_on} review={review_on} sw_plan={sw_on}")
if sw_on is not False:
raise SystemExit(f"rd_sw_plan must stay disabled for planning N/A, got {sw_on}")
if proposal_on is not True or review_on is not True:
raise SystemExit(f"sample tasks must be enabled: proposal={proposal_on} review={review_on}")
materials_prop = [{"filename": "proposal_brief.md", "content": b64(
"# 立项输入\n\n产品:无创神经电刺激器。\n用途:辅助改善目标症状,不做疗效宣称。\n市场:中国 NMPA 二类有源。\n软件:本项目不含独立软件子系统,软件开发计划在规划期关闭。\n"
)}]
materials_rev = [{"filename": "plan_brief.md", "content": b64(
"# 策划评审输入\n\n项目建议书已起草。\n关键风险:适应症边界待确认;电气安全摸底待排期。\n软件类文件已在规划期关闭,不进入编制。\n"
)}]
fin1 = run_task(token, pid, "rd_proposal", fields, uid, reviewer_id, approver_id, backend="pi-agent", materials=materials_prop)
md1 = extract_md(fin1)
(ASSETS / "rd_proposal-final.md").write_text(md1, encoding="utf-8")
log(f"proposal chars={len(md1)} placeholder={'按本阶段专业结构写' in md1}")
approve_doc(token, reviewer_token, approver_token, f"doc_proj{pid}_rd_proposal", uid, reviewer_id, approver_id)
advance_until(token, rid, "RD02_planning_review", rstages)
fin2 = run_task(token, pid, "rd_planning_review", fields, uid, reviewer_id, approver_id, backend="pi-agent", materials=materials_rev)
md2 = extract_md(fin2)
(ASSETS / "rd_planning_review-final.md").write_text(md2, encoding="utf-8")
log(f"planning_review chars={len(md2)} placeholder={'按本阶段专业结构写' in md2}")
summary = {
"project_id": pid,
"project_name": PROJ_NAME,
"rd_sw_plan_na": {"enabled": sw_on, "close": "planning_disable"},
"rd_proposal": {
"run_status": fin1.get("status") or fin1.get("Status"),
"chars": len(md1),
"no_placeholder": "按本阶段专业结构写" not in md1,
"has_document_sections": all(h in md1 for h in ("## 项目背景与立项依据", "## 产品定义与范围", "## 主要风险与对策概览")),
},
"rd_planning_review": {
"run_status": fin2.get("status") or fin2.get("Status"),
"chars": len(md2),
"no_placeholder": "按本阶段专业结构写" not in md2,
"has_review_sections": all(h in md2 for h in ("## 评审范围与对象", "## 问题与决议", "## 评审结论")),
},
}
save_json("summary-p3.json", summary)
(ASSETS / "console.log").write_text("\n".join(LOG) + "\n", encoding="utf-8")
print(json.dumps(summary, ensure_ascii=False, indent=2))
ok = (
summary["rd_sw_plan_na"]["enabled"] is False
and summary["rd_proposal"]["no_placeholder"]
and summary["rd_planning_review"]["no_placeholder"]
and summary["rd_proposal"]["has_document_sections"]
and summary["rd_planning_review"]["has_review_sections"]
and summary["rd_proposal"]["chars"] > 400
and summary["rd_planning_review"]["chars"] > 400
and summary["rd_proposal"]["run_status"] in ("completed", "pending_author_confirmation")
and summary["rd_planning_review"]["run_status"] in ("completed", "pending_author_confirmation")
)
sys.exit(0 if ok else 2)
def resume_planning_review():
"""Continue project 6533: approve rd_proposal, then real-PI rd_planning_review."""
pid = int(os.environ.get("P3_PROJECT_ID", "6533"))
rid = int(os.environ.get("P3_INSTANCE_ID", "361"))
admin_pass = os.environ["ADMIN_PASSWORD"]
token, admin = login(os.environ.get("ADMIN_USERNAME", "admin"), admin_pass)
uid = int(admin["id"])
_, rev_user = login("lizhuguan", "123456")
_, app_user = login("wangzong", "123456")
reviewer_id = int(rev_user["id"])
approver_id = int(app_user["id"])
reviewer_token, _ = login("lizhuguan", "123456")
approver_token, _ = login("wangzong", "123456")
fields = {
"customer_name": "水木东方测试客户",
"device_type": "二类有源医疗器械(神经刺激)",
"intended_use": "无创神经电刺激辅助改善目标症状",
"target_market": "中国 NMPA",
}
approve_doc(token, reviewer_token, approver_token, f"doc_proj{pid}_rd_proposal", uid, reviewer_id, approver_id)
rstages = json.loads((ASSETS / "rdev-stages.json").read_text(encoding="utf-8"))
advance_until(token, rid, "RD02_planning_review", rstages)
materials_rev = [{"filename": "plan_brief.md", "content": b64(
"# 策划评审输入\n\n项目建议书已起草。\n关键风险:适应症边界待确认;电气安全摸底待排期。\n软件类文件已在规划期关闭,不进入编制。\n"
)}]
fin2 = run_task(token, pid, "rd_planning_review", fields, uid, reviewer_id, approver_id, backend="pi-agent", materials=materials_rev)
md2 = extract_md(fin2)
(ASSETS / "rd_planning_review-final.md").write_text(md2, encoding="utf-8")
log(f"planning_review chars={len(md2)} placeholder={'按本阶段专业结构写' in md2}")
md1 = (ASSETS / "rd_proposal-final.md").read_text(encoding="utf-8")
summary = {
"project_id": pid,
"resumed": True,
"rd_sw_plan_na": {"enabled": False, "close": "planning_disable"},
"rd_proposal": {
"run_status": "completed",
"chars": len(md1),
"no_placeholder": "按本阶段专业结构写" not in md1,
"template_headings": all(h in md1 for h in ("## 项目背景与立项依据", "## 产品定义与范围", "## 主要风险与对策概览")),
},
"rd_planning_review": {
"run_status": fin2.get("status") or fin2.get("Status"),
"chars": len(md2),
"no_placeholder": "按本阶段专业结构写" not in md2,
"has_review_sections": all(h in md2 for h in ("## 评审范围与对象", "## 问题与决议", "## 评审结论")),
},
}
save_json("summary-p3.json", summary)
(ASSETS / "console.log").write_text("\n".join(LOG) + "\n", encoding="utf-8")
print(json.dumps(summary, ensure_ascii=False, indent=2))
if __name__ == "__main__":
if os.environ.get("P3_RESUME") == "review":
resume_planning_review()
else:
main()
@@ -0,0 +1,27 @@
{
"project_id": 6533,
"backend": "pi-agent",
"model": "MiniMax-M2.7-highspeed",
"rd_sw_plan_na": {
"enabled": false,
"close": "planning_disable"
},
"rd_proposal": {
"run_status": "completed",
"elapsed_s": 430,
"chars": 11550,
"no_placeholder": true,
"template_headings": false
},
"rd_planning_review": {
"run_status": "quality_failed",
"elapsed_s": 580,
"chars": 13225,
"no_placeholder": true,
"has_review_sections": true,
"quality_score": 20,
"violations": [
"问题行缺少问题、决议、责任人或期限"
]
}
}