Define multi-agent download workflow (T-301)
This commit is contained in:
@@ -45,6 +45,14 @@
|
||||
- 密钥、许可证私钥、真实注册码、真实下载 URL 一律不入库;示例只用占位符。
|
||||
- 提交信息使用英文祈使句,任务相关提交带上 `T-<编号>`。
|
||||
|
||||
## 多 Agent 协作
|
||||
|
||||
- 任务依赖仍是硬门槛:T-301 → T-302 → T-303 这类依赖链不得把后置任务提前并发实现。
|
||||
- 同一个任务默认只有**一个写入 Agent**拥有任务文件 `write_paths`;其他 Agent 可并行进行只读测试设计、安全审查或代码审查,但不得修改文件、暂存或提交。
|
||||
- 主 Agent / coordinator 负责领取、分配角色、汇总只读意见、执行最终验证与创建该任务唯一提交;审查 Agent 只通过消息返回发现和建议。
|
||||
- 只有先把大任务拆成独立 `T-<编号><后缀>.md`、冻结共享接口并提交,且各子任务 `write_paths` 无目录前缀重叠时,才允许多个写入 Agent 并行编码。
|
||||
- 多 Agent 角色、写入所有权、只读边界和汇总结果必须记录到当前任务的 `## 协作约束` / `## 执行记录`,不能只存在于对话。
|
||||
|
||||
## 验证
|
||||
|
||||
```bash
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
|
||||
### Phase 3 · 下载与安装
|
||||
|
||||
Phase 3 的 T-301 → T-302 → T-303 是安全关键依赖链,任务之间保持串行。每个任务内部默认采用“一个写入 Agent + 测试设计/安全审查只读 Agents”;只有先落成子任务、提交共享接口且写路径无重叠时才并行编码,完整规则见 [`tasks/README.md`](tasks/README.md) 与仓库 `AGENTS.md`。
|
||||
|
||||
| ID | 任务 | 依赖 | 验收要点 |
|
||||
| --- | --- | --- | --- |
|
||||
| T-301 | 下载队列 | T-202 | 并发默认 2;暂停/取消/重试;Range 续传;任务元数据持久化,重启恢复;事件驱动进度 |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-16
|
||||
- 阶段:Phase 2 已完成(T-201~T-204);下一步 Phase 3 的 T-301 下载队列
|
||||
- 阶段:Phase 2 已完成(T-201~T-204);T-301 下载队列已落成并领取,准备按单写入者 + 多只读审查者模式执行
|
||||
- 技术栈:根 Go workspace 纳入 core/app-modern/app-win7 三模块;`app-win7/go.work` 隔离 Go 1.20.14 构建;modern Gio v0.10.1 与 win7 Gio v0.6.0 已实际接入
|
||||
- 生产代码:core 已有 Catalog/本地状态/存储、无 IO 软件列表模型与按 digest+DPI 的可信图标缓存;modern/win7 AppShell 已实现搜索/分类/视图、惰性列表、详情右栏与内存图标
|
||||
- 测试:core 覆盖 Catalog、SemVer/12 状态、本地安装记录、列表筛选和图标内存/磁盘/离线/损坏恢复;两个 app 覆盖 500 项虚拟列表、ID 控件稳定性、详情/ApplyIcon 与平台 stub;ZIP/安装恢复矩阵保持通过
|
||||
@@ -21,14 +21,14 @@
|
||||
- 标准启动路径:`./init.sh` / `./init.ps1`(同步依赖、执行完整 Phase 0 闸门、打印双目标构建命令)
|
||||
- 标准验证路径:`bash scripts/verify_phase0.sh` / `./scripts/verify_phase0.ps1`
|
||||
- 版本管理:git 已初始化,main 分支,远端 origin 为 Gitea `opc/soft_quay`;harness 文档已提交
|
||||
- 当前 blocker:无;下一步按路线图落成并领取 T-301
|
||||
- 当前 blocker:无;当前任务 T-301,后置 T-302/T-303 仍受依赖门槛约束
|
||||
|
||||
## 当前目录要点
|
||||
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `docs/` | 已有 | harness coding 文档集(本次初始化完成) |
|
||||
| `docs/tasks/` | 已有 | Phase 0、Phase 1 与 Phase 2 任务均已完成;T-301 待按路线图落成 |
|
||||
| `docs/tasks/` | 已有 | Phase 0~2 已完成;T-301 已落成并处于 DOING |
|
||||
| `scripts/` | 已有 | harness 治理、core 边界、Go 版本检查与 Phase 0 双平台验证入口 |
|
||||
| `core/` | 已建 | Go 1.20 兼容;已有正式 Catalog、本地状态/存储、列表模型、图标缓存与 Phase 1 安装安全原型 |
|
||||
| `app-modern/` | 已建 | Go 1.25.0 + Gio v0.10.1;Modern AppShell 已接入虚拟列表、详情和内存图标 |
|
||||
@@ -41,8 +41,8 @@
|
||||
任务状态以 `docs/tasks/` 各任务文件 frontmatter 的 `status` 为准。本节只写项目级摘要:
|
||||
|
||||
- 已完成:Phase 0 的 `T-001`~`T-004`;Phase 1 的 `T-101`、`T-102`、`T-103`;Phase 2 的 `T-201`~`T-204`。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取任务:按路线图落成并领取 `T-301 下载队列`。
|
||||
- 正在进行:`T-301 下载队列`(一个写入 Agent + 测试/安全只读 Agents)。
|
||||
- 下一个可领取任务:无;T-302 必须等待 T-301 DONE。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
@@ -53,6 +53,22 @@ write_paths: # 允许修改的仓库相对路径
|
||||
- **执行记录写进本任务文件的 `## 执行记录` 一节**(改了什么、跑了什么验证、结果、决策)——不逐任务追加共享的 `progress.md`(可选历史归档)、也不逐任务覆盖 `current-state.md`(项目级快照,只在启动/验证路径、目录结构或 blocker 变化时更新)。
|
||||
- **只改自己那个任务文件**;不要编辑别人正在做的任务文件。
|
||||
|
||||
### 同一任务的多 Agent 模式
|
||||
|
||||
当任务本身不能安全拆成互不依赖的写路径时,使用“单写入者 + 多只读审查者”:
|
||||
|
||||
1. coordinator 先落成任务文件并提交,明确唯一写入 Agent、只读测试 Agent、只读安全/架构 Agent。
|
||||
2. 写入 Agent 独占任务 `write_paths`;只读 Agent 不调用文件编辑、`git add`、`git commit` 或会改变仓库状态的命令。
|
||||
3. 只读 Agent 返回可复现的测试矩阵、风险和审查意见;coordinator 决定是否采纳并由唯一写入者或 coordinator 修改。
|
||||
4. 所有意见合并后由 coordinator 跑任务完整闸门、更新执行记录并创建唯一任务提交。
|
||||
|
||||
若要让多个 Agent 并行写代码,必须先:
|
||||
|
||||
- 拆成带后缀的独立任务文件(如 `T-301a.md` / `T-301b.md`)。
|
||||
- 先完成并提交共享接口/协议冻结任务。
|
||||
- 确保依赖均 DONE,且 `write_paths` 互不重叠、没有目录前缀包含关系。
|
||||
- 每个子任务独立状态、验证证据和 Git 提交;最后另设串行集成任务。
|
||||
|
||||
未启用 Gitea 时,在独立分支 / worktree 中把任务文件从 `TODO` 改为 `DOING` 即可。启用 Gitea 时,必须先按 [`../gitea-collaboration.md`](../gitea-collaboration.md) 由 dispatcher 串行分配并创建 `claims/T-<编号>` 防御性标记;assignee、标签、读回和普通 create-branch API 都不能单独提供并发互斥。
|
||||
|
||||
## 与 Gitea Issue / PR 的映射(可选)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: T-301
|
||||
title: 可恢复下载队列
|
||||
phase: 3
|
||||
deps: [T-202]
|
||||
status: DOING
|
||||
created: 2026-07-16
|
||||
issue: null
|
||||
context_ref: a52acbf926041550ebc30049ff87f08faaa5ba0c
|
||||
claim_branch: null
|
||||
work_branch: agent/codex/T-301
|
||||
write_paths:
|
||||
- docs/tasks/T-301.md
|
||||
- core/downloader/
|
||||
- core/application/
|
||||
- core/storage/
|
||||
- schemas/download-task.schema.json
|
||||
- testdata/download/
|
||||
- testdata/README.md
|
||||
- docs/api.md
|
||||
- docs/04-architecture.md
|
||||
- docs/current-state.md
|
||||
---
|
||||
|
||||
## 问题 / 背景
|
||||
|
||||
Phase 2 已能识别软件状态并展示列表/详情,但点击下载后还没有并发调度、暂停/取消/重试、HTTP Range 续传或重启恢复。若下载状态只保存在 goroutine 内存中,盒子退出后任务丢失;若 Range 响应、临时文件和元数据不一致,可能把拼接错误的字节交给 T-302 校验/安装链路。
|
||||
|
||||
T-301 是 T-302/T-303 的前置安全边界。它只负责把远端 ZIP 稳定下载为隔离的 `.part`/完成文件并发布进度事件,不声称包已可信可执行。
|
||||
|
||||
## 方案
|
||||
|
||||
1. 在 `core/downloader` 定义任务模型、队列命令与状态机;默认最多 2 个 active transfer,其余保持 queued。
|
||||
2. 支持 enqueue、pause、resume、cancel、retry;每个命令按稳定 `request_id` / `app_id` 定位,重复命令返回确定结果而非产生第二份任务。
|
||||
3. HTTP transport 使用注入接口和标准库实现:
|
||||
- 已有 `.part` 时发送 `Range: bytes=<offset>-`。
|
||||
- `206` 必须校验 Content-Range 起点;不匹配则拒绝。
|
||||
- 服务端返回 `200` 时安全截断并从 0 重下,不得追加到旧字节。
|
||||
- 网络中断保留已落盘 `.part`;取消按策略删除任务临时文件;完成前 flush/sync/close。
|
||||
4. 在 `core/storage` 持久化下载任务元数据,采用同目录临时文件 + backup 原子替换;Schema 落到 `schemas/download-task.schema.json`。
|
||||
5. 启动恢复时:
|
||||
- queued / paused / failed 保持可恢复语义。
|
||||
- 进程退出时遗留的 downloading 降级为 queued,不假装仍在下载。
|
||||
- 元数据与 `.part` 实际长度不一致时以磁盘为准或返回稳定损坏错误,不得静默跳过字节。
|
||||
6. application 事件沿用 `DownloadStarted` / `DownloadProgress` / `DownloadPaused` / `DownloadCompleted` / `DownloadFailed`;负载使用具体类型,UI 只消费事件,不轮询文件。
|
||||
7. 进度包含 done/total/speed;total 未知时明确表示 unknown,不伪造百分比。事件节流与 clock 注入保证测试确定性。
|
||||
|
||||
## 验收要点
|
||||
|
||||
- 并发默认值为 2;表驱动/阻塞 transport 测试证明任意时刻 active transfer 不超过 2,完成/暂停后下一个 queued 自动开始。
|
||||
- pause 保留 `.part` 和元数据;resume 使用正确 Range;cancel 不再发布进度且按协议清理;failed 可 retry。
|
||||
- httptest 覆盖:正常 200、正确 206、错误 Content-Range、服务器忽略 Range 返回 200、连接中断后续传、非成功状态。
|
||||
- 任务元数据严格读写;未知字段、非法状态/ID/URL/路径/计数被拒绝;主文件缺失时可读取中断遗留 backup。
|
||||
- 新队列实例能从磁盘恢复;遗留 downloading → queued,paused 保持 paused,已完成任务不重复下载。
|
||||
- `.part` 长度、done 与下一次 Range offset 一致;不把未完成文件暴露为完成文件。
|
||||
- application 具体事件负载与 request_id/app_id 匹配;进度 done 单调不回退,暂停/取消后不出现迟到 progress。
|
||||
- `cd core && go vet ./... && go test -count=1 ./...`、完整双目标闸门与治理校验通过。
|
||||
|
||||
## 边界(不改什么)
|
||||
|
||||
- 不做 ZIP SHA-256 / package 签名、app.json 比对、解压、staging 切换或健康检查(T-302)。
|
||||
- 不做磁盘空间预检查、程序占用、hash_mismatch/zip_corrupt 等完整失败矩阵(T-303)。
|
||||
- 不实现 Gio DownloadPanel;本任务只交付 core 队列、持久化与事件,后续 UI 通过事件接入。
|
||||
- 不实现多源下载、P2P、带宽限速、代理设置或动态并发 UI。
|
||||
- 不引入第三方下载器、数据库或 Go 1.21+ API。
|
||||
|
||||
## 协作约束
|
||||
|
||||
- 唯一写入 Agent 独占本任务全部 `write_paths`,负责实现但不创建额外任务提交。
|
||||
- 测试设计 Agent 只读输出并发、Range、崩溃恢复和事件时序测试矩阵。
|
||||
- 安全/架构 Agent 只读审查路径隔离、响应拼接、持久化原子性、迟到事件和 T-302 信任边界。
|
||||
- coordinator 汇总意见、要求必要修正、执行最终验证、更新本执行记录并创建唯一 T-301 Git 提交。
|
||||
- T-302/T-303 在本任务 DONE 前不得领取;若后续决定并行编码,先另行落成并提交带后缀子任务及共享接口冻结任务。
|
||||
|
||||
## 执行记录
|
||||
|
||||
- 2026-07-16:正式落成多 Agent 协作方式;采用一个写入 Agent + 测试设计/安全架构两个只读 Agent,保持 T-301 → T-302 → T-303 依赖串行。
|
||||
Reference in New Issue
Block a user