docs(integration): align §5 product model to mandatory-git sub mode
sub mode requires git binding (else local-only), so the code deliverable lives solely in the user's own git repo (clone/pull). Demote the legacy "HM parses text artifact into project_folder (manifest/files/archive)" and the local-edits revision flow to legacy/back-compat: §5 now = code via git + artifacts only for non-code (test_report/summary); §6 redirects to git. Backend endpoints remain for back-compat but new integrations must not use them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,9 @@ Manager 生产地址:`https://code.xinghanlab.com`
|
||||
> - **部署 = 客户端执行 + 用户必须确认**;HM 只把凭据从 Key Vault 安全发给客户端,**HM 不部署、不连 VM**(见 §7,已改)。
|
||||
> - **产物归宿是用户自己的 git 仓库**(github/gitea);先绑仓库(及 vm/db/blob)→ §8 资源绑定。
|
||||
>
|
||||
> **2026-06-02 更新(gap-analysis P0/P1 闭环并实跑验证)**:GET 无 body 设备签名(§1)、审批列表(§3.2)、`project_folder` 归一化(§5)、`/archive` 契约(§5)、`?path=`(§5)、revision accepted/applied(§6)、Swarm 同形(§3)。
|
||||
> **2026-06-02 更新(gap-analysis P0/P1 闭环并实跑验证)**:GET 无 body 设备签名(§1)、审批列表(§3.2)、Swarm 同形(§3)。
|
||||
>
|
||||
> **2026-06-03 更新(产物模型对齐)**:sub 模式**强制绑定 git** 才能用,否则只能本地跑——因此**代码产物的唯一归宿是用户自己的 git 仓库**(clone/pull)。早期"HM 把文本产物解析成项目文件夹(`project_folder`/manifest/files/archive)"是无 git 流程的残留,**不再作为代码交付路径**;artifacts 接口仅保留给**非代码产物**(test_report/摘要)。详见 §5。
|
||||
|
||||
## 0. 命名与总原则
|
||||
|
||||
@@ -32,9 +34,8 @@ Manager 生产地址:`https://code.xinghanlab.com`
|
||||
3. (可选) POST .../tasks/{id}/execute 若需"先建后跑"或重试派发
|
||||
4. 轮询 GET .../tasks/{id}/workflow (运行中 3-5s) 读 display_status + 三层状态 + agents (work 视图)
|
||||
5. 出现 approval 时: GET .../approvals?status=pending -> approve/reject
|
||||
6. display_status=completed 后看产物 (两条路):
|
||||
(a) 直接 git clone/pull 用户自己的仓库 (完整工程+历史+diff)
|
||||
(b) 经 HM: GET .../artifacts -> /manifest -> /files?path= -> /archive
|
||||
6. display_status=completed 后: git clone/pull 用户自己的仓库拿代码产物 (完整工程+历史+diff)
|
||||
(非代码产物如 test_report/摘要 -> GET .../artifacts 查看; HM 不托管/不解析项目代码, 见 §5)
|
||||
7. 不满意 -> 改/重做 (两条路): POST .../messages|/execute 回云端改; 或 git pull 本地用客户端自己的 agent 改
|
||||
8. (可选) 部署: 用户确认 -> 客户端凭 resource_binding_id 向 HM 取凭据(V2) -> 客户端本地 git/ssh/部署 (§7, HM 不代执行)
|
||||
```
|
||||
@@ -106,12 +107,10 @@ signature = base64( ed25519_sign(device_priv, sha256(canonical)) )
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/metrics` | 指标 |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/diagnostics` | 诊断(直查 Runtime 状态 + warnings) |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/sk-snapshots` | SK 快照 |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts` | 产物列表(主产物归一化为 `project_folder`,见 §5) |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/manifest` | 项目文件树 |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/files?path=` | 单文件正文 |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/archive` | 整包 zip |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/revisions` | revision 列表 |
|
||||
| POST | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/local-edits` | 本地修改回传(批量 `.../local-edits/batch`) |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts` | 产物列表(**仅非代码产物**:test_report/摘要等;代码看 git,见 §5) |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/artifacts/{artifact_id}/content` | 单产物正文(如测试报告) |
|
||||
| ~~GET~~ | ~~`.../artifacts/{artifact_id}/{manifest,files,archive,revisions}`~~ | **遗留**:无 git 流程的"HM 解析项目文件夹"接口,sub 强制 git 后不再作为代码交付路径(后端仍在,见 §5) |
|
||||
| ~~POST~~ | ~~`.../artifacts/{artifact_id}/local-edits[/batch]`~~ | **遗留**:本地改产物改用 git 提交 |
|
||||
| GET | `/api/heicode/sub-agile/tasks/{task_id}/approvals?status=pending` | 审批列表(gap P0-2) |
|
||||
| POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/approve` | 同意审批 |
|
||||
| POST | `/api/heicode/sub-agile/tasks/{task_id}/approvals/{approval_id}/reject` | 拒绝审批 |
|
||||
@@ -247,98 +246,32 @@ signature = base64( ed25519_sign(device_priv, sha256(canonical)) )
|
||||
|
||||
不要订阅 `.../events/stream`(未提供,会 404)。
|
||||
|
||||
## 5. 产物:项目文件夹
|
||||
## 5. 产物(代码在 git;artifacts 仅非代码产物)
|
||||
|
||||
Runtime 返回单个文本/markdown 多文件 artifact;Manager 解析成项目文件树后提供。
|
||||
> **前提:sub 模式强制绑定 git 才能用**(未绑 git 只能本地跑,进不了 sub)。所以**代码产物的唯一归宿就是用户自己绑定的 git 仓库**。
|
||||
|
||||
**产物列表** `GET .../tasks/{task_id}/artifacts`:
|
||||
**5.1 代码产物 = git 仓库(唯一路径)**
|
||||
|
||||
```json
|
||||
{ "success": true, "data": {
|
||||
"deployment_id":"dep_xxx","task_id":"dep_xxx","total":1,
|
||||
"items":[
|
||||
{"artifact_id":"art_swm_xxx_backend_1","artifact_type":"code_patch","title":"backend task delivery",
|
||||
"summary":"...","uri":"azblob://...",
|
||||
"is_project":true,"display_artifact_type":"project_folder",
|
||||
"manifest_path":".../artifacts/art_swm_xxx_backend_1/manifest",
|
||||
"files_path":".../artifacts/art_swm_xxx_backend_1/files",
|
||||
"archive_path":".../artifacts/art_swm_xxx_backend_1/archive",
|
||||
"revisions_path":".../artifacts/art_swm_xxx_backend_1/revisions"}
|
||||
]
|
||||
}}
|
||||
```
|
||||
`display_status=completed` 后,客户端直接对**用户自己绑定的仓库**(§8 资源绑定里的 `git` 类型)做 `git clone` / `git pull`,拿到完整工程 + 提交历史 + diff。本地改、重做、合并、部署都在工作副本上走标准 git,**不经 HM**——HM 不托管、不解析、不打包项目代码。
|
||||
|
||||
**主产物类型以 `display_artifact_type` 为准**(gap P0-3):结构性代码任务的主交付物 Manager 一律归一化为 `display_artifact_type:"project_folder"` 且 `is_project:true`,并直接给出 manifest/files/archive/revisions 子路径——客户端不用再靠原始 `artifact_type`(可能是 `code_patch`)猜它是不是完整项目。非交付物(纯摘要)`is_project:false`,`display_artifact_type` 回落为原始类型。
|
||||
判断是否真实交付:`display_status=completed` 且 `is_project:true`(Manager 已裁决,客户端无需自判)。
|
||||
**5.2 非代码产物 = artifacts 接口**
|
||||
|
||||
agent_management 跑出的**非代码**东西(如 `test_report` 测试报告、`summary` 摘要、说明),通过 artifacts 列表给客户端**查看**,不承载工程代码:
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `.../artifacts/{artifact_id}/content` | 原始正文(兼容) |
|
||||
| GET | `.../artifacts/{artifact_id}/manifest` | 项目文件树(entries[path,type,mime,size,hash,content_path] + archive) |
|
||||
| GET | `.../artifacts/{artifact_id}/files?path=<相对路径>` | 单个文件正文(见下「路径编码」) |
|
||||
| GET | `.../artifacts/{artifact_id}/archive` | 整个项目 zip 下载(见下「下载契约」) |
|
||||
| GET | `.../tasks/{task_id}/artifacts` | 非代码产物列表(test_report / summary 等) |
|
||||
| GET | `.../artifacts/{artifact_id}/content` | 单个产物正文(如测试报告全文) |
|
||||
|
||||
manifest 示例:
|
||||
`test_report` 只是给客户端/用户**看**,**不参与 HM 的 `display_status` 裁决**(HM 不读代码、不判对错,见 §4 / spec §6.6)。
|
||||
|
||||
```json
|
||||
{ "success": true, "data": {
|
||||
"artifact_id":"art_xxx","artifact_type":"project_folder","root_dir":"project","revision":1,
|
||||
"content_hash":"sha256:...","file_count":2,
|
||||
"entries":[
|
||||
{"path":"app.py","type":"file","mime_type":"text/x-python","size_bytes":420,"content_hash":"sha256:...","content_path":".../files?path=app.py"},
|
||||
{"path":"frontend/src/App.tsx","type":"file","mime_type":"text/typescript","size_bytes":300,"content_hash":"sha256:...","content_path":".../files?path=frontend%2Fsrc%2FApp.tsx"}
|
||||
],
|
||||
"archive":{"format":"zip","download_path":".../archive"}
|
||||
}}
|
||||
```
|
||||
## 6. 本地修改回传 → 改用 git(旧 revision 接口已退役)
|
||||
|
||||
**单文件「路径编码」(gap P1-1)**:用 `?path=` query 传相对路径,整体做一次 URL encode(含 `/`、空格、中文、`#`、`?` 等保留字符)。例:`GET .../files?path=frontend%2Fsrc%2FApp.tsx`。直接用 manifest 里给的 `content_path` 即可,无需自己拼。找不到文件返回 `{"error":{"code":"FILE_NOT_FOUND"}}`;缺 path 返回 `FILE_PATH_REQUIRED`。
|
||||
旧流程靠 `POST .../artifacts/{id}/local-edits[/batch]` 把本地改动以「revision(accepted/applied/conflict)」回传给 HM,再在 `/messages`、`/execute` 时作为基线消费。**sub 强制 git 后这套退役**:本地改完直接 `git add/commit/push` 到用户自己的仓库,云端要继续改就 `git pull` 同步——冲突、历史、diff 全交给 git,HM 不再做基线托管。`local-edits`/`revisions` 后端仍在(向后兼容),但**新集成不要用**。
|
||||
|
||||
**整包「下载契约」(gap P0-4)**:`GET .../archive` 成功时返回真实 zip 二进制,响应头:
|
||||
```text
|
||||
HTTP 200
|
||||
Content-Type: application/zip
|
||||
Content-Disposition: attachment; filename="art_xxx.zip"
|
||||
Content-Length: <字节数>
|
||||
```
|
||||
客户端必须读 `Content-Disposition` 文件名、按 `Content-Length` 校验落盘,**保存成功后才提示「已下载」**。产物尚未就绪(无文件)时返回 `HTTP 200` body 为:
|
||||
```json
|
||||
{ "success": false, "error": { "code": "ARTIFACT_ARCHIVE_NOT_READY", "message": "项目压缩包尚未生成(产物还未就绪),请稍后重试。", "retryable": true } }
|
||||
```
|
||||
此时客户端**不要**提示已下载,按 `retryable` 稍后重试。
|
||||
**5.3 遗留接口(已不再作为代码交付路径)**
|
||||
|
||||
## 6. 本地修改回传(revision)
|
||||
|
||||
用户在本地改了产物后,必须显式上传;Manager 存为新 revision。
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `.../artifacts/{artifact_id}/revisions` | revision 列表 + `current_project_revision` |
|
||||
| POST | `.../artifacts/{artifact_id}/local-edits` | 上传单文件修改 |
|
||||
| POST | `.../artifacts/{artifact_id}/local-edits/batch` | 上传多文件修改(`changes[]`,op=update/create/delete) |
|
||||
|
||||
单文件上传请求:
|
||||
|
||||
```json
|
||||
{ "base_artifact_id":"art_xxx","base_revision":1,"path":"frontend/src/App.tsx",
|
||||
"content":"<html>...</html>","content_hash":"sha256:new","change_summary":"改了首页标题" }
|
||||
```
|
||||
|
||||
批量请求:`{ "base_revision":1, "changes":[ {"op":"update","path":"a.py","content":"..."},{"op":"create","path":"b.py","content":"..."},{"op":"delete","path":"c.py"} ], "change_summary":"..." }`
|
||||
|
||||
成功响应:`{ "success":true,"data":{ "artifact_id":"art_xxx","revision":2,"project_revision":2,"source":"client_local_edit","status":"accepted","content_hash":"sha256:new" } }`
|
||||
|
||||
**revision 状态语义(gap P1-2)**:
|
||||
|
||||
| status | 含义 |
|
||||
|---|---|
|
||||
| `accepted` | 已被接受为**当前可用基线**(无冲突即直接接受,Manager 持有基线) |
|
||||
| `applied` | 已被 Runtime 在后续 `/messages` 或 `/execute` 消费 |
|
||||
| `conflict` | 与最新 revision 冲突(见下,不落库) |
|
||||
|
||||
**后续执行使用最新 accepted revision(gap P1-3)**:调用 `POST .../tasks/{id}/messages` 或 `.../execute` 时,Manager 自动取该任务最新 `accepted` revision 作为基线并置为 `applied`,响应回带 `active_project_revision`(无本地修改时不返回该字段)。客户端无需手动指定 revision。
|
||||
|
||||
冲突:若 `base_revision` 不等于当前最新,返回 `{ "success":false,"error":{"code":"ARTIFACT_REVISION_CONFLICT","retryable":false},"data":{"current_project_revision":3} }`,客户端提示用户先同步最新再提交。
|
||||
下列接口是早期「无 git 流程」的残留——当时 runtime 只吐一坨 markdown 文本,HM 现解析成项目文件树(`project_folder` / `manifest` / `files?path=` / `archive` / `revisions` / `local-edits`)供客户端浏览、下载、回传修改。**sub 强制 git 后这套不再使用**:浏览看 git 工作副本,回传改动用 `git commit/push`。后端实现仍保留(向后兼容 / 万一有无 git 的历史任务),但**新集成不要依赖**,也不要再靠 `is_project` / `display_artifact_type:"project_folder"` 判断交付——是否真实交付以 `display_status=completed`(§4)+ git 仓库有提交为准。
|
||||
|
||||
## 7. 部署(✅ 客户端执行 + 用户必须确认;HM 只发凭据)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user