35 KiB
蚕病智能防控平台整改实施计划
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 依据《蚕病智能防控平台规格说明书 V2.2》,先消除安全与业务正确性风险,再建立可迁移、可测试、可观测、可恢复的试点闭环。
Architecture: 保持现有 Go/Gin 主业务后端、Python/FastAPI AI 微服务、React Web、Taro 小程序、React Native APP 和 IoTDB/PostgreSQL/S3/WVP 基础。整改采用“小步迁移 + TDD + 功能开关 + 可回滚发布”,不在本计划中替换既有主技术栈。
Tech Stack: Go 1.23、Gin、GORM、PostgreSQL、IoTDB、Valkey/Redis、MQTT、FastAPI、ONNX Runtime、React、Taro 4、React Native 0.74、Vitest、pytest。
Global Constraints
- 不得手改
miniapp/dist/、web/dist/、APK、Linux 二进制等生成产物。 - 不得覆盖无关的用户修改;每个任务只提交本任务文件。
- 新功能先写失败测试,再做最小实现,再运行模块和全量检查。
- 生产密钥只通过环境变量/密钥管理注入,不写入提交文件。
- 所有 schema 修改先备份、再迁移;生产不允许 GORM AutoMigrate 自动改表。
- 每项交付必须追加
开发交接记录.md,记录设计依据、验证证据和回滚点。 - 涉及发布时严格执行
AGENTS.md的开发服务器部署前置、备份和回滚要求。 - 任务 0 的开放技术选型未确认前,不得擅自引入迁移工具、CI 平台或新外部服务。
1. 执行原则与分工
1.1 优先级
| 波次 | 目标 | 任务 | 预计串行工期 |
|---|---|---|---|
| Wave 0 | 决策与基线 | 0~1 | 2~3 人日 |
| Wave 1 | P0 安全与正确性 | 2~7 | 10~15 人日 |
| Wave 2 | 工程可靠性 | 8~9 | 6~10 人日 |
| Wave 3 | 业务闭环 | 10~12 | 20~33 人日 |
| Wave 4 | 验收与发布 | 13~14 | 7~11 人日 |
工期只用于排期,不是验收标准。多人并行时,任务 2 是涉及数据库实体任务的前置;任务 3~7 可在接口边界明确后分支并行,但合并前必须统一回归。
1.2 建议责任域
- 后端负责人:任务 2~10、13。
- AI 负责人:任务 6 中 AI 响应与模型元数据、任务 14 AI 验收。
- Web/小程序负责人:任务 1、11、12 的端侧部分。
- 运维负责人:任务 3、8、9、13 的配置、监控、备份和发布。
- 测试负责人:维护需求 ID—用例—结果矩阵,不以开发自测替代验收。
- 领域专家:确认 qPCR 规则、风险动作、病种清单和知识来源。
1.3 每个任务的完成定义
- 需求 ID 与验收用例明确。
- 失败测试已观察到预期失败原因。
- 实现和迁移完成,模块测试通过。
- 相关模块全量检查通过或准确记录环境阻断。
- 文档、配置示例和交接记录更新。
- 回滚步骤经过静态复核;涉及部署时完成实际冒烟。
Task 0: 固化开放决策与整改基线
Requirements: V2.2 第 13 章
Owner: 项目负责人 + 后端/运维/领域负责人
Estimated effort: 0.5~1 人日
Files:
- Create:
docs/decisions/2026-08-13-remediation-decisions.md - Modify:
后续工作计划.md - Modify:
开发交接记录.md
Interfaces:
-
Consumes:
蚕病智能防控平台规格说明书_V2.2.md的开放决策。 -
Produces: 迁移工具、CI 平台、保留期限、qPCR 规则负责人、APP 范围和模型门槛的书面决定。
-
Step 1: 召开 60 分钟决策会并逐项记录负责人、选项、理由和生效日期
文档必须使用如下固定表头:
| Decision ID | 结论 | 备选方案 | 选择理由 | 影响 | 负责人 | 复审条件 |
|---|---|---|---|---|---|---|
- Step 2: 明确七项决定
必须覆盖:数据库迁移工具、CI 承载平台、制品位置、数据保留期限、qPCR 方案确认流程、APP 产品范围、二分类转多病种指标门槛。不得写“以后再定”;暂不实施时写“保持现状 + 明确复审触发条件”。
-
Step 3: 将 Wave 1~4 写入
后续工作计划.md,使用七态能力状态而不是单一勾选 -
Step 4: 评审并提交
rg -n "Decision ID|迁移|CI|保留|qPCR|APP|二分类" docs/decisions/2026-08-13-remediation-decisions.md
git diff --check
Expected: 七项主题均可检索,git diff --check exit 0。
Rollback: 删除决策文档并恢复计划/交接记录;尚未执行的决定不产生运行时影响。
Task 1: 恢复可复现的多端质量基线
Requirements: V2.2 第 10 章
Owner: 各端负责人
Estimated effort: 1~2 人日
Files:
- Modify:
miniapp/src/pages/dashboard/index.tsx - Modify:
miniapp/package.json - Modify:
app/package.json - Modify:
ai-service/README.md - Create:
scripts/verify.ps1 - Modify: CI 配置文件(路径由 Task 0 确认的平台决定)
- Modify:
开发交接记录.md
Interfaces:
-
Produces: 单命令验证入口
powershell -ExecutionPolicy Bypass -File scripts/verify.ps1。 -
Step 1: 修复小程序 JSX 类型错误
将裸文本箭头改为明确字符节点:
<Text className={styles.sectionAction}>详情 {'>'}</Text>
<Text className={styles.sectionAction} onClick={handleAlarmTap}>全部 {'>'}</Text>
- Step 2: 为小程序增加只读类型检查脚本,为 APP 确认本地 devDependencies 安装可用
{
"scripts": {
"typecheck": "tsc --noEmit"
}
}
- Step 3: 创建验证脚本
scripts/verify.ps1 必须按模块执行并在任一失败时返回非 0:
$ErrorActionPreference = 'Stop'
Push-Location server-go; go test ./...; go vet ./...; go build ./...; Pop-Location
Push-Location web; npm test; npm run lint; npm run build; Pop-Location
Push-Location miniapp; npm run typecheck; npm run build:weapp; Pop-Location
Push-Location app; npm run tsc; npm run lint; Pop-Location
Push-Location ai-service; python -m pytest; Pop-Location
- Step 4: 在干净依赖环境运行并保存结果
Expected: 五个模块全部 exit 0;Web lint warning 单独建单,不允许隐藏 exit code。
- Step 5: 接入 Task 0 确认的 CI,禁止失败检查合并
Rollback: 恢复两处 JSX 与脚本变更;CI 门禁可关闭但不得删除失败证据。
Task 2: 引入版本化数据库迁移与 Schema 启动门禁
Requirements: V2.2 5.5、阶段 B
Owner: 后端负责人 + DBA/运维
Estimated effort: 2~3 人日
Files:
- Create:
server-go/migrations/000001_baseline.up.sql - Create:
server-go/migrations/000001_baseline.down.sql - Create:
server-go/internal/database/migrate.go - Create:
server-go/internal/database/migrate_test.go - Modify:
server-go/internal/database/db.go - Modify:
server-go/cmd/server/main.go - Modify:
README.md - Modify:
部署指南(物理机).md
Interfaces:
-
Produces:
database.CheckSchemaVersion(db *gorm.DB, expected string) error。 -
Constraint: 迁移执行器使用 Task 0 批准的工具;SQL 迁移文件作为唯一 schema 事实来源。
-
Step 1: 写失败测试,证明 schema 版本缺失/落后时返回错误
func TestCheckSchemaVersionRejectsMismatch(t *testing.T) {
err := CheckSchemaVersion(fakeDBWithVersion("1"), "2")
if err == nil { t.Fatal("expected schema mismatch") }
}
- Step 2: 生成当前 schema 基线 SQL,并人工核对所有表、索引和约束
不得使用 AutoMigrate 输出作为未经审核的生产脚本;基线需在空库执行后与当前模型对照。
- Step 3: 实现启动检查并移除生产自动迁移
func CheckSchemaVersion(db *gorm.DB, expected string) error
开发环境自动迁移只能由显式 ALLOW_DEV_AUTOMIGRATE=true 开启;生产配置忽略该开关并拒绝 AutoMigrate。
- Step 4: 验证空库建库、旧库升级和 down 回滚
go test ./internal/database -run TestCheckSchemaVersion -v
go test ./...
go vet ./...
go build ./...
Expected: 版本匹配通过,不匹配时服务启动失败且日志不包含 DSN 密码。
Rollback: 恢复旧二进制和迁移前数据库备份;不得只回滚代码而保留不兼容 schema。
Task 3: 移除默认密钥与默认管理员密码
2026-08-13 用户决策:Task 3 本轮跳过,留到最后处理。期间不删除默认密钥/默认管理员密码,不执行客户端密码预填清理。
Requirements: IAM-004、SEC-001、SEC-002
Owner: 后端 + 运维 + 各客户端负责人
Estimated effort: 1~2 人日
Files:
- Modify:
server-go/internal/config/config.go - Create:
server-go/internal/config/config_test.go - Modify:
server-go/internal/handler/auth.go - Modify:
miniapp/src/pages/login/index.tsx - Modify:
app/src/screens/LoginScreen.tsx - Create:
server-go/.env.example - Modify:
app/.env.example - Modify:
README.md
Interfaces:
-
Produces:
config.ValidateForEnvironment(cfg *Config, environment string) error。 -
Step 1: 写表驱动测试,验证 production 缺 JWT/S3/ZLM/Internal API/管理员初始化配置时失败
func TestValidateForEnvironmentRejectsProductionDefaults(t *testing.T) {
cfg := &Config{JWTSecret: "silk-secret-please-change-me"}
if err := ValidateForEnvironment(cfg, "production"); err == nil {
t.Fatal("expected insecure config rejection")
}
}
- Step 2: 删除敏感字段的可用默认值,保留非敏感本地地址默认值
生产环境必须显式设置 APP_ENV=production;关键字段为空、长度不足或等于历史默认值均拒绝启动。
- Step 3: 删除小程序和 APP 密码预填
const [password, setPassword] = useState('');
- Step 4: 生成轮换清单并由运维在目标环境执行
轮换范围至少包括 PostgreSQL、Redis、MQTT、JWT、S3、WVP、ZLM、Internal API 和默认管理员。
- Step 5: 验证
go test ./internal/config ./internal/handler -v
rg -n "silk@123|Silk-App-Secret|silk-internal-2026|su6Tied" server-go miniapp/src app/src
Expected: 测试通过;源码搜索不再出现可用历史密钥。文档可提及已废弃值,但不得作为配置示例。
Rollback: 代码可恢复,但已轮换密钥不得回退为历史值;使用新生成密钥更新旧版本运行环境。
Task 4: 收口视频访问与摄像头密钥输出
Requirements: IAM-003、VIDEO-001、VIDEO-002、SEC-003、SEC-004
Owner: 视频后端负责人
Estimated effort: 2~3 人日
Files:
- Modify:
server-go/internal/model/models.go - Create:
server-go/internal/handler/video_dto.go - Create:
server-go/internal/handler/video_auth.go - Create:
server-go/internal/handler/video_auth_test.go - Modify:
server-go/internal/handler/video_camera.go - Modify:
server-go/internal/handler/video_clip.go - Modify:
server-go/internal/handler/video_stream.go - Modify:
server-go/internal/middleware/auth.go - Modify:
web/src/dal/video.ts
Interfaces:
-
Produces:
IssueVideoToken(userID, resourceType, resourceID string, ttl time.Duration) (string, error)。 -
Produces:
ValidateVideoToken(token, resourceType, resourceID string) error。 -
Token TTL: 5 分钟;绑定资源类型、ID、用户、用途和过期时间。
-
Step 1: 写安全回归测试
func TestCameraResponseNeverContainsSecrets(t *testing.T)
func TestVideoStreamRejectsMissingOrWrongResourceToken(t *testing.T)
func TestVideoTokenExpires(t *testing.T)
- Step 2: 将模型密钥字段标记为不序列化,并使用公开 DTO
PasswordEnc *string `json:"-"`
GbAuthPassword *string `json:"-"`
CameraPublic 只包含播放和管理界面需要的非敏感字段;WVP 配置响应删除 sipPassword。
- Step 3: 播放地址改为短时令牌
/video/clips/:id/play 和 /video/cameras/:id/play 先执行 JWT、权限和对象范围校验,再返回带短时 token 的 URL。stream/proxy 路由即使位于 auth 白名单,也必须验证该 token。
- Step 4: 验证直接枚举 ID、跨用户 token、过期 token 和资源错配均为 401/403
go test ./internal/handler -run "Video|CameraResponse" -v
go test ./...
Rollback: 可临时回滚到“JWT header 直接保护 stream”模式;禁止回滚为公开流或返回密钥。
Task 5: 修复 WebSocket 越权与 AI 流 SSRF
Requirements: IAM-003、SEC-005、SEC-007、VIDEO-004
Owner: 后端 + AI 负责人
Estimated effort: 2~3 人日
Files:
- Modify:
server-go/internal/ws/gateway.go - Create:
server-go/internal/ws/gateway_test.go - Modify:
server-go/cmd/server/main.go - Modify:
server-go/internal/config/config.go - Modify:
ai-service/app/main.py - Create:
ai-service/app/stream_tasks.py - Modify:
ai-service/tests/test_api.py
Interfaces:
-
WebSocket:
NewHub(jwtSecret string, authorizer DeviceAuthorizer, allowedOrigins []string)。 -
AI 流接口:
POST /internal/stream-tasks接受taskId和已解析的内部流引用,不接受公网客户端任意 URL。 -
Step 1: 写失败测试,覆盖非法 Origin、refresh token、无权 deviceKey 和全局广播泄露
-
Step 2: 增加设备授权接口并在 subscribe 时校验
type DeviceAuthorizer interface {
CanReadDevice(userID, deviceKey string) (bool, error)
}
删除普通连接的无范围 telemetry.all 广播;管理视图使用单独权限和组织范围订阅。
- Step 3: 禁止长期 JWT 出现在 query,改用一次性 WebSocket ticket
ticket 有效期 60 秒、仅使用一次;日志中不记录 ticket 值。
- Step 4: 将 AI 流读取移到受限 worker
只允许 Go 后端以内部认证创建任务;限制并发、帧数、分辨率、超时和允许的内部地址范围。FastAPI 路由不得在事件循环中直接执行长时间 VideoCapture.read()。
- Step 5: 验证
go test ./internal/ws -v
Push-Location ai-service; python -m pytest tests/test_api.py -v; Pop-Location
Rollback: 关闭流 AI 功能开关;WebSocket 保留来源和对象授权,不得回滚为 CheckOrigin=true。
Task 6: 修复 AI 风险语义并隔离 Mock 数据
Requirements: AI-INS-002~004、RISK-001~003
Owner: AI + Go 后端负责人
Estimated effort: 2~3 人日
Files:
- Modify:
ai-service/app/main.py - Modify:
ai-service/app/config.py - Modify:
ai-service/tests/test_api.py - Modify:
server-go/internal/service/ai_client.go - Modify:
server-go/internal/service/risk.go - Modify:
server-go/internal/service/risk_test.go - Modify:
server-go/internal/handler/inspection.go - Modify:
server-go/internal/handler/inspection_test.go - Create:
server-go/migrations/000007_inspection_idempotency.up.sql - Create:
server-go/migrations/000007_inspection_idempotency.down.sql - Modify:
server-go/internal/model/inspection.go - Create:
server-go/migrations/000002_risk_assessment.up.sql - Create:
server-go/migrations/000002_risk_assessment.down.sql
Interfaces:
-
AI response adds
modelVersion,isMock,abnormalProbability。 -
Go produces
RiskAssessmentwith score、level、confidence、components、missing、modelVersion、ruleVersion。 -
Step 1: 写关键失败测试
func TestHealthyHighConfidenceDoesNotIncreaseRisk(t *testing.T) {
got := AbnormalProbability([]AIDetection{{ClassName: "healthy", Confidence: .95}})
if got != 0 { t.Fatalf("got %v", got) }
}
func TestSickHighConfidenceIncreasesRisk(t *testing.T) {
got := AbnormalProbability([]AIDetection{{ClassName: "sick", Confidence: .9}})
if got != .9 { t.Fatalf("got %v", got) }
}
- Step 2: 扩展 AI 响应并明确异常类别集合
二分类 sick 和多病种中除 healthy 外的已配置异常类别贡献风险;空检测返回 unknown,不自动当健康。
- Step 3: 用可空组件计算风险
type RiskInput struct {
AI, Env, Stage, Uniformity *float64
}
type RiskAssessment struct {
Score float64; Level, Confidence, RuleVersion string
Components map[string]*float64; Missing []string
}
缺失组件不填 0;V2 规则将可用权重归一化,并把 confidence 降为 low/medium。具体权重先沿用 0.5/0.2/0.15/0.15,标记为待试点校准规则而非科学事实。
- Step 4: 持久化输入快照、模型/规则版本和 mock 标识
Mock 记录可保存供联调,但查询统计默认排除;生产环境收到 isMock=true 时记录失败并告警。
- Step 5: 评估历史数据
生成只读 SQL 报告统计历史 healthy 高置信度记录及其风险等级;未经人工确认不得批量重算或覆盖。
- Step 6: 验证
go test ./internal/service -run "Risk|Abnormal" -v
go test ./internal/handler -run Inspection -v
Push-Location ai-service; python -m pytest -v; Pop-Location
Rollback: 功能开关回退到只展示 AI 原始结果、不计算综合风险;不得恢复错误的最大置信度算法。
Task 7: 修订 qPCR 判读与检测质控
2026-08-14 用户决策:Task 7 本轮跳过,留到最后处理。期间保持 qPCR 只录入、不自动判读;恢复前需领域专家签字确认 protocolVersion 与阈值。
Requirements: DET-003~005
Owner: 后端负责人 + 领域专家
Estimated effort: 1~2 人日
Files:
- Modify:
server-go/internal/model/molecular.go - Modify:
server-go/internal/model/molecular_test.go - Modify:
server-go/internal/model/lamp.go - Modify:
server-go/internal/handler/lamp.go - Modify:
web/src/dal/lamp.ts - Modify:
web/src/pages/LampTests.tsx - Create:
server-go/migrations/000003_detection_qc.up.sql - Create:
server-go/migrations/000003_detection_qc.down.sql
Interfaces:
- Produces:
JudgeQPCR(input QPCRJudgeInput) QPCRJudgeResult。
type QPCRJudgeInput struct {
TargetCt *float64
InternalControlCt *float64
PositiveControlValid bool
NegativeControlValid bool
ProtocolVersion string
Threshold float64
}
- Step 1: 由领域专家签字确认首个 protocolVersion 与阈值适用范围
未确认前功能只能保存原始数据,不能自动输出阴性/阳性。
- Step 2: 写表驱动测试
覆盖:阳性、阴性、缺 Ct、内参失败、阳性对照失败、阴性对照污染、临界值和未知 protocol。
- Step 3: 实现四态结果
positive / negative / invalid / indeterminate
无 Ct 仅在对照和内参有效且方案明确允许时判 negative;其他情况为 invalid/indeterminate。
-
Step 4: UI 强制填写质控字段并展示判读依据,不允许把 invalid 显示为阴性
-
Step 5: 验证
go test ./internal/model -run QPCR -v
go test ./internal/handler -run QPCR -v
Push-Location web; npm test; npm run lint; npm run build; Pop-Location
Rollback: 回退为“只录入、不自动判读”,保留原始 Ct 和质控数据。
Task 8: 建立可靠通知、吊销与跨实例状态
Requirements: IAM-001、MSG-001、MSG-002
Owner: 后端 + 运维
Estimated effort: 3~5 人日
Files:
- Create:
server-go/internal/model/notification.go - Create:
server-go/internal/service/outbox.go - Create:
server-go/internal/service/outbox_test.go - Modify:
server-go/internal/handler/notification.go - Modify:
server-go/internal/middleware/token_blacklist.go - Modify:
server-go/internal/middleware/ratelimit.go - Create:
server-go/migrations/000004_notifications_outbox.up.sql - Create:
server-go/migrations/000004_notifications_outbox.down.sql - Modify:
server-go/cmd/server/main.go
Interfaces:
-
Produces:
Outbox.PublishTx(tx *gorm.DB, event Event) error。 -
Notification states:
pending/sending/sent/retry/failed/cancelled。 -
Step 1: 写测试证明服务重启后 pending 事件仍可处理,重复 eventId 不重复发送
-
Step 2: 业务事务内写 outbox,worker 领取、发送、退避重试并记录最终失败
-
Step 3: 将 token 吊销和登录限流迁移到 Redis
Redis 不可用时:生产登录/刷新采取保守失败;已认证的只读请求按安全评审决定降级,不得静默切回单机内存。
-
Step 4: 微信发送保存模板、用户授权、响应码和重试结果
-
Step 5: 验证并进行进程重启测试
go test ./internal/service ./internal/middleware ./internal/handler -run "Outbox|Notification|Revok|Rate" -v
go test ./...
Rollback: 暂停 worker 保留 outbox 数据;恢复旧读接口时不得删除未发送事件。
Task 9: 建立统一检测任务、样本链与发病事件
Requirements: DET-001/002/006、TRACE-001
Owner: 后端 + Web + 小程序负责人
Estimated effort: 5~8 人日
Files:
- Create:
server-go/internal/model/detection_task.go - Create:
server-go/internal/model/sample.go - Create:
server-go/internal/model/disease_event.go - Create:
server-go/internal/handler/detection_task.go - Create:
server-go/internal/handler/detection_task_test.go - Modify:
server-go/internal/handler/inspection.go - Modify:
server-go/internal/handler/trace.go - Create:
server-go/migrations/000005_detection_disease_events.up.sql - Create:
server-go/migrations/000005_detection_disease_events.down.sql - Create:
web/src/dal/detectionTask.ts - Create:
web/src/pages/DetectionTasks.tsx - Modify:
web/src/router.tsx
Interfaces:
-
DetectionTask states:
draft/pending/assigned/sampling/testing/review/completed/cancelled。 -
Sample states:
created/collected/handed_over/received/testing/consumed/disposed。 -
DiseaseEvent states:
suspected/confirmed/controlled/closed/reopened。 -
Step 1: 写状态机和幂等失败测试
func TestDetectionTaskRejectsInvalidTransition(t *testing.T)
func TestOrangeInspectionCreatesOnlyOnePendingTask(t *testing.T)
func TestDiseaseEventRequiresEvidenceToConfirm(t *testing.T)
-
Step 2: 实现实体、外键、唯一业务键和状态转换服务
-
Step 3: 橙色巡检通过 outbox 创建“待确认”任务,不能直接指派或视为已检测
-
Step 4: 检测有效阳性或专家确认后创建 DiseaseEvent,TraceRecord 改为关联 DiseaseEvent
-
Step 5: Web 提供任务列表、分派、采样交接、检测和复核视图
-
Step 6: 验证完整 API 流程和重复请求
go test ./internal/model ./internal/service ./internal/handler -run "DetectionTask|Sample|DiseaseEvent" -v
Push-Location web; npm test; npm run lint; npm run build; Pop-Location
Rollback: 关闭自动建单开关,保留新表数据;旧 LAMP 记录继续只读,禁止删除已建立关联。
Task 10: 补齐消毒、种源与二维码身份链
Requirements: FARM-002、FARM-004、FARM-005、TRACE-007
Owner: 后端 + Web + 小程序负责人
Estimated effort: 4~6 人日
Files:
- Create:
server-go/internal/model/biosecurity.go - Create:
server-go/internal/handler/biosecurity.go - Create:
server-go/internal/handler/biosecurity_test.go - Create:
server-go/migrations/000006_biosecurity.up.sql - Create:
server-go/migrations/000006_biosecurity.down.sql - Create:
web/src/dal/biosecurity.ts - Create:
web/src/pages/Biosecurity.tsx - Create:
miniapp/src/api/biosecurity.ts - Create:
miniapp/src/pages/biosecurity/index.tsx - Modify:
miniapp/src/app.config.ts
Interfaces:
-
QR payload only contains opaque
entityType、publicId、校验版本,不包含密码、内部自增 ID 或个人信息。 -
Step 1: 写测试覆盖二维码篡改、跨组织访问、种源链循环和消毒记录必填项
-
Step 2: 实现 SeedSource、DisinfectionRecord、二维码解析与对象授权
-
Step 3: Web 提供来源/凭证/消毒计划与执行;小程序提供扫码和现场执行
-
Step 4: 溯源初报消费种源和消毒数据,缺失时明确显示“证据不足”
-
Step 5: 验证
go test ./internal/handler ./internal/service -run "Biosecurity|SeedSource|Disinfection|QRCode" -v
Push-Location web; npm run build; Pop-Location
Push-Location miniapp; npm run typecheck; npm run build:weapp; Pop-Location
Rollback: 隐藏页面入口并停止新增写入,保留已产生的种源/消毒/二维码映射。
Task 11: 实现小程序离线巡检与可靠同步
Requirements: AI-INS-005、9.4 弱网要求
Owner: 小程序 + Go 后端负责人
Estimated effort: 4~6 人日
Files:
- Create:
miniapp/src/services/offlineQueue.ts - Create:
miniapp/src/services/offlineQueue.test.ts - Modify:
miniapp/src/pages/inspection/index.tsx - Modify:
miniapp/src/api/inspections.ts - Modify:
miniapp/src/store/useStore.ts - Modify:
server-go/internal/handler/inspection.go - Modify:
server-go/internal/handler/inspection_test.go
Interfaces:
-
Queue item states:
pending/uploading/synced/conflict/failed。 -
Idempotency key: 客户端生成 UUID,创建后永不变化,重试复用。
-
Step 1: 写队列单测
覆盖断网入队、重启恢复、重复点击、指数退避、成功删除本地图片引用、永久失败和冲突展示。
-
Step 2: 实现本地持久队列,限制容量并显示剩余空间
-
Step 3: 网络恢复后串行上传,401 先刷新令牌,5xx/超时重试,4xx 进入人工处理
-
Step 4: 服务端幂等键增加用户作用域,避免不同用户键碰撞
唯一约束改为 (user_id, idempotency_key),使用 000007_inspection_idempotency 迁移;先扫描并处理既有冲突,迁移不得静默删除记录。
- Step 5: 在开发者工具模拟离线—重启—联网流程并保存截图/日志证据
Push-Location miniapp; npm run typecheck; npm run build:weapp; Pop-Location
go test ./internal/handler -run Inspection -v
Rollback: 关闭离线入口,只允许在线提交;服务端幂等改动保留,避免重复数据回归。
Task 12: 完善环境规则、会诊治理、知识审核与效果评估
Requirements: ENV-003~005、EXP-002~005、KB-001/002、ANA-001/002
Owner: 后端 + Web + 领域专家 + 测试负责人
Estimated effort: 5~8 人日
Files:
- Create:
server-go/internal/model/governance.go - Create:
server-go/internal/service/rule_engine.go - Create:
server-go/internal/service/rule_engine_test.go - Modify:
server-go/internal/service/weather_risk.go - Modify:
server-go/internal/model/consultation.go - Modify:
server-go/internal/handler/consultation.go - Modify:
server-go/internal/handler/consultation_test.go - Modify:
server-go/internal/model/knowledge.go - Modify:
server-go/internal/handler/knowledge.go - Modify:
server-go/internal/service/health_profile.go - Modify:
server-go/internal/service/health_profile_test.go - Create:
server-go/migrations/000008_governance_effectiveness.up.sql - Create:
server-go/migrations/000008_governance_effectiveness.down.sql - Modify:
web/src/pages/Consultations.tsx - Modify:
web/src/pages/Knowledge.tsx - Modify:
web/src/pages/Traces.tsx
Interfaces:
-
Produces:
EvaluateRules(ctx RuleContext, rules []RuleVersion) []RuleResult。 -
Consultation states:
unassigned/assigned/accepted/needs_info/resolved/archived。 -
Knowledge states:
draft/review/published/withdrawn。 -
Produces:
EvaluateControlEffect(eventID string, window EffectWindow) EffectReport。 -
Step 1: 写规则时窗与缺失数据测试
func TestRuleRequiresThreeContinuousDaysOfHumidity(t *testing.T)
func TestStaleTelemetryIsReportedMissing(t *testing.T)
func TestRuleResultKeepsInputAndVersion(t *testing.T)
规则输出必须保存版本、输入时间窗、命中项、缺失项和计算时间;单个最新值不得冒充连续时窗。
- Step 2: 实现规则版本和数据新鲜度
RuleContext 至少包含批次阶段、时间窗遥测、天气、密度、通风、种源和消毒证据。缺失输入降低结论可信度,不填 0。
- Step 3: 写并实现会诊状态机、SLA 和意见版本测试
func TestConsultationRejectsArchiveBeforeResolution(t *testing.T)
func TestConsultationOpinionCreatesNewVersion(t *testing.T)
func TestConsultationSLAMarksOverdue(t *testing.T)
每次意见修改保留作者、时间、旧版本和原因;超时只产生升级事件,不自动伪造专家结论。
- Step 4: 增加知识审核与来源字段
未发布内容只对有审核权限用户可见;撤回后不在农户端出现,但历史病例引用保留版本快照。
- Step 5: 实现防控效果评估
EffectReport 对比处置前后指定窗口的有效巡检风险、有效检测阳性率、复发、死亡/损失和成本;所有缺失维度单独列出,不把缺失当改善。
-
Step 6: Web 完成会诊 SLA、知识审核和效果报告入口
-
Step 7: 验证
go test ./internal/model ./internal/service ./internal/handler -run "Rule|Consultation|Knowledge|Health|Effect" -v
Push-Location web; npm test; npm run lint; npm run build; Pop-Location
Rollback: 关闭新版规则、SLA 和效果报告入口,保留版本与审核数据;不得覆盖或删除旧专家意见。
Task 13: 建立可观测性、容量与恢复验证
Requirements: V2.2 9.1~9.3、10.2
Owner: 运维 + 后端 + 测试负责人
Estimated effort: 4~6 人日
Files:
- Modify:
server-go/internal/middleware/logger.go - Create:
server-go/internal/middleware/request_id.go - Modify:
server-go/internal/service/ai_client.go - Modify:
ai-service/app/main.py - Create:
docs/operations/slo-and-alerts.md - Create:
docs/operations/load-test-scenarios.md - Create:
docs/operations/backup-restore-drill.md - Modify:
部署指南(物理机).md
Interfaces:
-
每个 HTTP 请求生成/透传
X-Request-ID;事件使用eventId;日志字段命名统一。 -
Step 1: 写中间件测试,验证 requestId 响应头、透传和日志脱敏
-
Step 2: 增加依赖指标
至少覆盖 PostgreSQL、Redis、MQTT、IoTDB、S3、AI、WVP、微信、天气的请求数、失败数、p95 和积压/容量。
- Step 3: 定义并执行三类负载场景
A. 500 在线用户:80% 查询、10% 遥测趋势、5% 上传、5% 管理操作
B. 1000 WebSocket 连接:按授权设备订阅,持续 30 分钟
C. AI 峰值:指定 T4、模型版本、输入尺寸和并发,记录 p50/p95/失败率
- Step 4: 执行备份恢复演练
恢复到隔离数据库/对象存储命名空间;记录备份时间、恢复时间、数据点核对、RPO/RTO 和失败项。
- Step 5: 建立告警阈值和负责人表,进行一次模拟故障验证通知链
Rollback: 指标与 requestId 可保持;高开销采样可降低频率,不得删除备份恢复记录。
Task 14: 建立规格追踪、端到端验收与发布门禁
Requirements: V2.2 第 10~12 章
Owner: 测试负责人 + 项目负责人
Estimated effort: 3~5 人日
Files:
- Create:
docs/acceptance/requirements-traceability.md - Create:
docs/acceptance/core-e2e-cases.md - Create:
docs/acceptance/release-checklist.md - Modify:
蚕病智能防控平台规格说明书_V2.2.md - Modify:
后续工作计划.md - Modify:
开发交接记录.md
Interfaces:
-
Traceability columns: Requirement ID、实现、自动测试、手工用例、环境、证据、状态、限制、负责人。
-
Step 1: 为 Wave 1~3 的每个需求 ID 建立追踪行,不允许只写模块名
-
Step 2: 编写核心端到端用例
至少覆盖:
1. healthy 图片 → 低风险/不触发检测
2. sick 图片 → 橙色 → 仅一个待确认任务
3. AI 失败 → 可重试且无虚假风险
4. qPCR 对照失败 → invalid → 不确诊
5. 有效阳性 → DiseaseEvent → 自动溯源初报
6. 无权用户访问视频/设备/WebSocket → 403
7. 离线巡检 → 重启 → 联网 → 仅同步一次
8. 通知发送失败 → 重试 → 最终状态可查
9. 服务重启 → 任务/通知/吊销状态保持
10. 备份恢复 → 核心记录与对象引用核对通过
- Step 3: 在目标环境执行全量质量门禁和端到端用例
powershell -ExecutionPolicy Bypass -File scripts/verify.ps1
git diff --check
-
Step 4: 按 AGENTS.md 完成开发服务器备份、部署、健康检查、冒烟和回滚点记录
-
Step 5: 更新能力状态
只有附有测试/环境/日期证据的功能才能从“部分可用”改为“可验收/已验证”。
Rollback: 使用发布前 tag/commit、数据库 dump、旧二进制和旧 dist;回滚后重新执行健康检查并记录原因。
2. 不纳入本轮整改的事项
以下能力保留在 V2.2 阶段 D/E,不得为了展示进度插入 Wave 1~3:
- 7 类病种真实模型训练与发布。
- 固定摄像头群体巡检和个体追踪。
- LAMP 图像自动判读。
- SERS/高光谱自动分析和方法学结论。
- 区域传播预测模型和数字孪生自动控制。
- 未经确认的 APP 全量蚕病功能同步。
3. 合并与发布顺序
Task 0 决策
↓
Task 1 质量基线 ── Task 2 迁移基线
↓ ↓
Task 3 配置安全 Task 6/7 数据语义
Task 4 视频安全 Task 8 可靠事件
Task 5 WS/AI 安全 ↓
└──────────────→ Task 9 检测/发病主链
↓
Task 10 生物安全链
Task 11 离线同步
↓
Task 12 规则/治理/效果
↓
Task 13 运维验证
↓
Task 14 总体验收
Task 3~5 可以分别评审,但必须在 Wave 1 集成分支统一执行安全回归。Task 6~12 每个 schema 变更必须基于 Task 2 的迁移机制顺序编号,禁止多人自行创建冲突编号。
4. 计划自检清单
- V2.2 的 P0 问题均映射到 Task 2~7。
- 业务可靠性和治理问题映射到 Task 8~13。
- 每个任务有负责人、文件、接口、测试、验证和回滚。
- 未擅自确定迁移工具、CI 平台、云服务和 qPCR 医学/检疫规则。
- 不包含手改生成产物或在服务器直接修源码的步骤。
- 每项部署均要求备份、健康检查、冒烟和回滚记录。
- 研究能力与近期整改明确分离。
5. 交付节奏建议
- 每个 Task 一个独立分支/PR;分支前缀使用
codex/或团队既有规范。 - Task 3~7 每完成一项立即做针对性安全/业务回归,不等待大版本集中验证。
- 每周更新追踪矩阵和风险清单;只汇报有证据的状态变化。
- Wave 1 完成后再开始 Wave 3 业务扩展;P0 未关闭时不部署新增研究功能。
- 每次评审先看测试失败/通过证据,再看代码;每次发布先看回滚点,再执行覆盖操作。