mirror of
https://git.openapi.site/https://github.com/desirecore/agent-desirecore.git
synced 2026-10-21 07:04:13 +08:00
fix: 首装核验复用原始资料并消除 manage 示例误导 (#13)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: 应用安装管理
|
name: 应用安装管理
|
||||||
description: 安装、升级、卸载或检查应用;读取固定资料,复用执行工具核验后记录结果。处理 ApplicationManagement 请求;旧服务 RegistryCatalogAcquisition 请求按需读取兼容指南。
|
description: 安装、升级、卸载或检查应用;读取固定资料,复用执行工具核验后记录结果。处理 ApplicationManagement 请求;旧服务 RegistryCatalogAcquisition 请求按需读取兼容指南。
|
||||||
version: "1.5.0"
|
version: "1.5.1"
|
||||||
requiredClientVersion: "10.0.170"
|
requiredClientVersion: "10.0.170"
|
||||||
type: procedural
|
type: procedural
|
||||||
risk_level: high
|
risk_level: high
|
||||||
@@ -12,7 +12,7 @@ provides:
|
|||||||
tags: [installation, registry, app-management]
|
tags: [installation, registry, app-management]
|
||||||
metadata:
|
metadata:
|
||||||
author: desirecore
|
author: desirecore
|
||||||
updated_at: "2026-09-18"
|
updated_at: "2026-09-19"
|
||||||
---
|
---
|
||||||
|
|
||||||
# 应用安装管理
|
# 应用安装管理
|
||||||
@@ -34,6 +34,6 @@ Agent 理解环境并执行;已有工具提供能力;Agent Service 只可靠
|
|||||||
3. 复用 Read、HttpRequest、Bash/PowerShell 等当前已授权工具。`provides.tools` 仅提示按需披露,不授予权限;没有可靠授权通道时停止,不能读取管理 token 或改用本机文件绕过。
|
3. 复用 Read、HttpRequest、Bash/PowerShell 等当前已授权工具。`provides.tools` 仅提示按需披露,不授予权限;没有可靠授权通道时停止,不能读取管理 token 或改用本机文件绕过。
|
||||||
4. 可以依据环境适配命令;版本、来源、设备和影响范围变化需要重新确认。固定制品先校验摘要;凭据不进入聊天、指南、日志或核验记录。
|
4. 可以依据环境适配命令;版本、来源、设备和影响范围变化需要重新确认。固定制品先校验摘要;凭据不进入聊天、指南、日志或核验记录。
|
||||||
5. 超时、断线和结果不明时先观察,不重放有副作用的命令;同一安装同时存在其他修改任务时不并发执行。核验只说明实际检查过的能力。
|
5. 超时、断线和结果不明时先观察,不重放有副作用的命令;同一安装同时存在其他修改任务时不并发执行。核验只说明实际检查过的能力。
|
||||||
6. 结果明确后提交一次带时间的观察,不预写 installing/reinstalling/uninstalling,不拼装 pending 状态或完整收据,不直接编辑 installed-entries.json。版本必须与本次固定资料一致;发现不同版本应先确认正确资料,不能伪报核验成功。
|
6. 结果明确后提交一次带时间的观察,material 必须原样复用成功 resolve 的 data.material(包括 action 与 snapshot);首装结束也不能改成 manage。不预写 installing/reinstalling/uninstalling,不拼装 pending 状态或完整收据,不直接编辑 installed-entries.json。版本必须与本次固定资料一致;发现不同版本应先确认正确资料,不能伪报核验成功。
|
||||||
7. 记账失败只重读并处理记录,不重复安装/卸载。记录修订冲突要重新观察,不能只换 expectedRevision。异常时按需读取 [恢复原则](references/recovery.md)。
|
7. 记账失败只重读并处理记录,不重复安装/卸载。记录修订冲突要重新观察,不能只换 expectedRevision。异常时按需读取 [恢复原则](references/recovery.md)。
|
||||||
8. 最后说明软件的实际结果与记录是否提交成功;二者可能不同。进度留在当前会话/既有任务;不得承诺无人执行的后续修复或“所有失败都已回滚”。
|
8. 最后说明软件的实际结果与记录是否提交成功;二者可能不同。进度留在当前会话/既有任务;不得承诺无人执行的后续修复或“所有失败都已回滚”。
|
||||||
|
|||||||
@@ -6,21 +6,18 @@
|
|||||||
|
|
||||||
API base 使用当前会话已确认的活动 Agent Service;不要猜固定端口。`deviceId=local` 指该 Agent Service 主机,不一定是界面所在电脑。远程设备使用已授权的现有设备执行工具;接口接受设备定位不代表它验证了远程证据。身份/位置不清楚就停止。
|
API base 使用当前会话已确认的活动 Agent Service;不要猜固定端口。`deviceId=local` 指该 Agent Service 主机,不一定是界面所在电脑。远程设备使用已授权的现有设备执行工具;接口接受设备定位不代表它验证了远程证据。身份/位置不清楚就停止。
|
||||||
|
|
||||||
通过已有 HttpRequest 调用 `POST /api/registry/acquisitions/resolve`,body 为 `ApplicationManagement` 原对象:
|
通过已有 HttpRequest 调用 `POST /api/registry/acquisitions/resolve`,body 为当前请求的 `ApplicationManagement` 原对象。不要用通用示例覆盖本次 action。
|
||||||
|
|
||||||
```json
|
| 用户操作 | 读取资料的 action | snapshot 来源 |
|
||||||
{
|
| --- | --- | --- |
|
||||||
"protocol": "application-observation-v1",
|
| 首装或升级到指定版本 | install / update | 该次市场请求的完整固定 snapshot |
|
||||||
"sourceId": "registry:official",
|
| 管理或卸载已登记应用 | manage / uninstall | 不传,使用历史安装记录 |
|
||||||
"entryId": "desirecore-control",
|
|
||||||
"deviceId": "local",
|
首次安装尚未登记,不能调用 manage 来代替 install。
|
||||||
"action": "manage"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`action=install|update` 必须加上由精确目录条目取得的 `snapshot`:schemaVersion、catalogSourceId、完整 catalogCommit、catalogPath、releaseVersion,及存在时的 contentRef/contentSha256。只允许明确固定版本,不填写 latest,不自行拼下载地址。`action=uninstall|manage` 不传 snapshot,服务端读取原安装资料。
|
`action=install|update` 必须加上由精确目录条目取得的 `snapshot`:schemaVersion、catalogSourceId、完整 catalogCommit、catalogPath、releaseVersion,及存在时的 contentRef/contentSha256。只允许明确固定版本,不填写 latest,不自行拼下载地址。`action=uninstall|manage` 不传 snapshot,服务端读取原安装资料。
|
||||||
|
|
||||||
成功 `data` 包含 `material`、`expectedRevision`、`manifest`、`installGuide` 和 `record`。读取不写账本、不执行软件、不代替审批。复用返回的 material,不复制整份指南进提交请求。服务端内部复核不需要模型重复读全部目录。
|
成功 `data` 包含 `material`、`expectedRevision`、`manifest`、`installGuide` 和 `record`。保留成功响应供最终提交使用,不在安装后重新构造 material。读取不写账本、不执行软件、不代替审批。复用返回的 material,不复制整份指南进提交请求。服务端内部复核不需要模型重复读全部目录。
|
||||||
|
|
||||||
目录的无关条目更新不替换选定版本;资料必须在受信分支可达,当前目标条目仍允许获取。下架/撤回可以阻止新装,原安装的 manage/uninstall 使用历史指南,不依赖目录在线。历史安装缺乏维护资料时明确报告,不能用同名最新指南猜卸载命令。
|
目录的无关条目更新不替换选定版本;资料必须在受信分支可达,当前目标条目仍允许获取。下架/撤回可以阻止新装,原安装的 manage/uninstall 使用历史指南,不依赖目录在线。历史安装缺乏维护资料时明确报告,不能用同名最新指南猜卸载命令。
|
||||||
|
|
||||||
@@ -32,25 +29,21 @@ API base 使用当前会话已确认的活动 Agent Service;不要猜固定端
|
|||||||
|
|
||||||
## 提交观察
|
## 提交观察
|
||||||
|
|
||||||
`PATCH /api/installed-entries/<entryId>/<deviceId>`,路径段应正常 URL 编码,body:
|
`PATCH /api/installed-entries/<entryId>/<deviceId>`,路径段应正常 URL 编码。以下为请求对象的构造关系,不是要求运行一份新脚本;将实际值交给 HttpRequest 的 body:
|
||||||
|
|
||||||
```json
|
```javascript
|
||||||
{
|
const body = {
|
||||||
"material": { "protocol": "application-observation-v1", "sourceId": "registry:official", "entryId": "desirecore-control", "deviceId": "local", "action": "manage" },
|
material: resolution.data.material,
|
||||||
"expectedRevision": "使用此次读取返回的修订值",
|
expectedRevision: resolution.data.expectedRevision,
|
||||||
"requestId": "为本次提交生成一个 UUID,重试保持不变",
|
requestId, // 本次提交 UUID;响应未知时保留原 ID 和完整正文。
|
||||||
"deviceName": "本机",
|
deviceName,
|
||||||
"observation": {
|
observation: { result, observedAt, location, evidenceRefs, notes }
|
||||||
"result": "present",
|
|
||||||
"observedAt": "实际核验时取得的 ISO 时间",
|
|
||||||
"location": "实际核验的安装目录或部署位置",
|
|
||||||
"evidenceRefs": ["当前工具执行结果或已有会话日志的可追溯引用"],
|
|
||||||
"notes": "可选的简短维护信息,不含秘密或自动执行指令"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
示例中的占位文字不能直接提交。首次安装前没有精确记录时,expectedRevision 为服务端返回的 `none`。observedAt 由实际观察决定;recordedAt 由服务端记录,不要把任务开始时间当核验时间。版本来自固定资料,只有实际匹配时才提交。
|
`resolution` 必须是这次成功的资料读取响应。**material 整体原样复用,包括 action 与完整 snapshot;首装完成后仍是 install,不能改为 manage 或删掉 snapshot。** action 表示资料来源,不是把“安装阶段”改成“管理阶段”的状态字段。
|
||||||
|
|
||||||
|
其余变量使用实际值:result 仅 present/absent,observedAt 为核验时取得的 ISO 时间,location 为实际安装/部署位置,evidenceRefs 为已有工具或会话证据引用数组,notes 是可选简短维护说明。不含秘密,不复制安装指南。首次安装前没有精确记录时,expectedRevision 为服务端返回的 `none`。observedAt 由实际观察决定;recordedAt 由服务端记录,不要把任务开始时间当核验时间。版本来自固定资料,只有实际匹配时才提交。
|
||||||
|
|
||||||
限制:location 最多 2048 字符、不能含换行/NUL;evidenceRefs 1–8 个,每项最多 512 字符;notes 最多 2000 字符。不填 runtimeStatus、operationId、pending 字段或 catalogReceipt。证据引用由 Agent 报告,服务端校验结构和记录一致性,不声称验证引用内容或软件真实安全。
|
限制:location 最多 2048 字符、不能含换行/NUL;evidenceRefs 1–8 个,每项最多 512 字符;notes 最多 2000 字符。不填 runtimeStatus、operationId、pending 字段或 catalogReceipt。证据引用由 Agent 报告,服务端校验结构和记录一致性,不声称验证引用内容或软件真实安全。
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
| 下载摘要不符 | 不安装,不换来源绕过;报告并等待明确选择 |
|
| 下载摘要不符 | 不安装,不换来源绕过;报告并等待明确选择 |
|
||||||
| 应用已安装,PATCH 失败/响应丢失 | 重读精确记录,必要时原 requestId+原 body 重试记账;不重新安装 |
|
| 应用已安装,PATCH 失败/响应丢失 | 重读精确记录,必要时原 requestId+原 body 重试记账;不重新安装 |
|
||||||
| 卸载完成但 PATCH 失败 | 先确认已移除,再补记;不再次清理用户目录 |
|
| 卸载完成但 PATCH 失败 | 先确认已移除,再补记;不再次清理用户目录 |
|
||||||
|
| 首装误用 manage,明确返回 historical-material-unavailable | 重读确认 record=null 且 revision 未变;保留软件,改用原成功 resolve 的完整 data.material,以新提交 ID 补记。只有确认原请求被拒且未落盘才允许修正正文;响应未知不能如此处理 |
|
||||||
| application_revision_conflict | 重新读记录和软件现状;不拿旧证据只替换 expectedRevision |
|
| application_revision_conflict | 重新读记录和软件现状;不拿旧证据只替换 expectedRevision |
|
||||||
| application_request_id_conflict | 同 ID 参数不一致,停止;不能自动换 ID 掩盖错误 |
|
| application_request_id_conflict | 同 ID 参数不一致,停止;不能自动换 ID 掩盖错误 |
|
||||||
| application_legacy_source_unresolved | 旧记录来源不明确,不能静默认领为官方应用 |
|
| application_legacy_source_unresolved | 旧记录来源不明确,不能静默认领为官方应用 |
|
||||||
|
|||||||
@@ -654,6 +654,18 @@ test('Skill-first 正文短而完整、按需提供既有 HTTP 工具、不加
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('首装观察示例复用 resolver material,不将 install 改为 manage', async () => {
|
||||||
|
const api = await readFile(join(here, '..', 'references', 'recording-api.md'), 'utf8')
|
||||||
|
const skill = await readFile(skillPath, 'utf8')
|
||||||
|
assert.match(api, /material: resolution\.data\.material/)
|
||||||
|
assert.match(api, /expectedRevision: resolution\.data\.expectedRevision/)
|
||||||
|
assert.match(api, /首装完成后仍是 install/)
|
||||||
|
assert.doesNotMatch(api, /"action":\s*"manage"/)
|
||||||
|
assert.match(skill, /首装结束也不能改成 manage/)
|
||||||
|
const recovery = await readFile(join(here, '..', 'references', 'recovery.md'), 'utf8')
|
||||||
|
assert.match(recovery, /响应未知不能如此处理/)
|
||||||
|
})
|
||||||
|
|
||||||
test('Skill contract has no fixed official/local Registry fallback and resolves before execution', async () => {
|
test('Skill contract has no fixed official/local Registry fallback and resolves before execution', async () => {
|
||||||
const skill = await readFile(join(here, '..', 'references', 'legacy-services.md'), 'utf8')
|
const skill = await readFile(join(here, '..', 'references', 'legacy-services.md'), 'utf8')
|
||||||
assert.doesNotMatch(skill, /registry\/official\/entries/)
|
assert.doesNotMatch(skill, /registry\/official\/entries/)
|
||||||
|
|||||||
Reference in New Issue
Block a user